Mirror source for HashiCorp Packer v1.9.4
b/300296425
Signed-off-by: Casey Flynn <caseyflynn@google.com>
diff --git a/README.md b/README.md
new file mode 100644
index 0000000..5621afc
--- /dev/null
+++ b/README.md
@@ -0,0 +1 @@
+# Packer
diff --git a/v1.9.4/.copywrite.hcl b/v1.9.4/.copywrite.hcl
new file mode 100644
index 0000000..2e86e1c
--- /dev/null
+++ b/v1.9.4/.copywrite.hcl
@@ -0,0 +1,14 @@
+project {
+ license = "MPL-2.0"
+ copyright_year = 2013
+ header_ignore = [
+ "*.hcl2spec.go", # generated code specs, since they'll be wiped out until we support adding the headers at generation-time
+ "hcl2template/testdata/**",
+ "test/**",
+ "**/test-fixtures/**",
+ "examples/**",
+ "hcl2template/fixtures/**",
+ "command/plugin.go",
+ "website/**" # candidates for copyright are coming from external sources, so we should not handle those in Packer
+ ]
+}
diff --git a/v1.9.4/.gitattributes b/v1.9.4/.gitattributes
new file mode 100644
index 0000000..af45aba
--- /dev/null
+++ b/v1.9.4/.gitattributes
@@ -0,0 +1,13 @@
+* text=auto
+*.go text eol=lf
+*.sh text eol=lf
+*.json text eol=lf
+*.md text eol=lf
+*.mdx text eol=lf
+*.ps1 text eol=lf
+*.hcl text eol=lf
+*.tmpl text eol=lf
+*.txt text eol=lf
+go.mod text eol=lf
+go.sum text eol=lf
+common/test-fixtures/root/* eol=lf
diff --git a/v1.9.4/.github/CONTRIBUTING.md b/v1.9.4/.github/CONTRIBUTING.md
new file mode 100644
index 0000000..86e030c
--- /dev/null
+++ b/v1.9.4/.github/CONTRIBUTING.md
@@ -0,0 +1,639 @@
+# Contributing to Packer
+
+**First:** if you're unsure or afraid of _anything_, just ask or submit the
+issue or pull request anyway. You won't be yelled at for giving your best
+effort. The worst that can happen is that you'll be politely asked to change
+something. We appreciate any sort of contributions, and don't want a wall of
+rules to get in the way of that.
+
+However, for those individuals who want a bit more guidance on the best way to
+contribute to the project, read on. This document will cover what we're looking
+for. By addressing all the points we're looking for, it raises the chances we
+can quickly merge or address your contributions.
+
+When contributing in any way to the Packer project (new issue, PR, etc), please
+be aware that our team identifies with many gender pronouns. Please remember to
+use nonbinary pronouns (they/them) and gender neutral language ("Hello folks")
+when addressing our team. For more reading on our code of conduct, please see the
+[HashiCorp community guidelines](https://www.hashicorp.com/community-guidelines).
+
+## Issues
+
+### Reporting an Issue
+
+- 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`.
+ For example: `PACKER_LOG=1 packer build template.pkr.hcl`. 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,
+ 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
+ issues will be closed.
+
+### Issue Lifecycle
+
+1. The issue is reported.
+
+2. The issue is verified and categorized by a Packer collaborator.
+ Categorization is done via tags. For example, bugs are marked as "bugs" and
+ simple fixes are marked as "good first issue".
+
+3. Unless it is critical, the issue is left for a period of time (sometimes many
+ weeks), giving outside contributors a chance to address the issue.
+
+4. The issue is addressed in a pull request or commit. The issue will be
+ 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 to test 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.
+
+## Setting up Go
+
+If you have never worked with Go before, you will have to install its
+runtime in order to build packer.
+
+1. This project always releases from the latest version of golang.
+[Install go](https://golang.org/doc/install#install) To properly build from
+source, you need to have golang >= v1.18
+
+## Setting up Packer for dev
+
+If/when you have go installed you can already clone packer and `make` in
+order to compile and test Packer. These instructions target
+POSIX-like environments (macOS, Linux, Cygwin, etc.) so you may need to
+adjust them for Windows or other shells.
+
+
+1. Create a directory in your GOPATH for the code `mkdir -p $(go env GOPATH)/src/github.com/hashicorp && cd $_`
+and clone the packer repository from GitHub into your GOPATH `git clone https://github.com/hashicorp/packer.git`
+then change into the packer directory `cd packer`
+
+2. When working on Packer, first `cd $GOPATH/src/github.com/hashicorp/packer`
+ so you can run `make` and easily access other files. Run `make help` to get
+ information about make targets.
+
+3. Make your changes to the Packer source. You can run `make` in
+ `$GOPATH/src/github.com/hashicorp/packer` to run tests and build the Packer
+ binary. Any compilation errors will be shown when the binaries are
+ rebuilding. If you don't have `make` you can simply run
+ `go build -o bin/packer .` from the project root.
+
+4. After running building Packer successfully, use
+ `$GOPATH/src/github.com/hashicorp/packer/bin/packer` to build a machine and
+ verify your changes work. For instance:
+ `$GOPATH/src/github.com/hashicorp/packer/bin/packer build template.pkr.hcl`.
+
+5. If everything works well and the tests pass, run `go fmt` on your code before
+ 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`
+
+when building using `go` you also need to mention the windows
+executable extension
+
+```
+go build -o bin/packer.exe
+```
+
+### Opening a Pull Request
+
+Thank you for contributing! When you are ready to open a pull-request, you will
+need to [fork
+Packer](https://github.com/hashicorp/packer#fork-destination-box), push your
+changes to your fork, and then open a pull-request.
+
+For example, my GitHub username is `cbednarski`, so I would do the following:
+
+```
+git checkout -b f-my-feature
+# Develop a patch.
+git push https://github.com/cbednarski/Packer f-my-feature
+```
+
+From there, open your fork in your browser to open a new pull-request.
+
+**Note:** Go infers package names from their file paths. This means `go build`
+will break if you `git clone` your fork instead of using `go get` on the main
+Packer project.
+
+**Note:** See '[Working with
+forks](https://help.github.com/articles/working-with-forks/)' for a better way
+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.
+
+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.
+
+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.
+
+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.
+
+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.
+
+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.
+
+### Tips for Working on Packer
+
+#### Getting Your Pull Requests Merged Faster
+
+It is much easier to review pull requests that are:
+
+1. Well-documented: Try to explain in the pull request comments what your
+ change does, why you have made the change, and provide instructions for how
+ to produce the new behavior introduced in the pull request. If you can,
+ provide screen captures or terminal output to show what the changes look
+ like. This helps the reviewers understand and test the change.
+
+2. Small: Try to only make one change per pull request. If you found two bugs
+ and want to fix them both, that's _awesome_, but it's still best to submit
+ the fixes as separate pull requests. This makes it much easier for reviewers
+ to keep in their heads all of the implications of individual code changes,
+ and that means the PR takes less effort and energy to merge. In general, the
+ smaller the pull request, the sooner reviewers will be able to make time to
+ review it.
+
+3. Passing Tests: Based on how much time we have, we may not review pull
+ requests which aren't passing our tests. (Look below for advice on how to
+ run unit tests). If you need help figuring out why tests are failing, please
+ feel free to ask, but while we're happy to give guidance it is generally
+ your responsibility to make sure that tests are passing. If your pull request
+ changes an interface or invalidates an assumption that causes a bunch of
+ tests to fail, then you need to fix those tests before we can merge your PR.
+
+If we request changes, try to make those changes in a timely manner. Otherwise,
+PRs can go stale and be a lot more work for all of us to merge in the future.
+
+Even with everyone making their best effort to be responsive, it can be
+time-consuming to get a PR merged. It can be frustrating to deal with
+the back-and-forth as we make sure that we understand the changes fully. Please
+bear with us, and please know that we appreciate the time and energy you put
+into the project.
+
+### PR Checks
+
+The following checks run when a PR is opened:
+
+- Contributor License Agreement (CLA): If this is your first contribution to Packer you will be asked to sign the CLA.
+- Tests: tests include unit tests, documentation checks, and code formatting checks, and all checks must pass before a PR can be merged.
+
+#### Working on forks
+
+The easiest way to work on a fork is to set it as a remote of the Packer
+project. After following the steps in "Setting up Go to work on Packer":
+
+1. Navigate to the code:
+
+ `cd $GOPATH/src/github.com/hashicorp/packer`
+
+2. Add the remote by running:
+
+ `git remote add <name of remote> <github url of fork>`
+
+ For example:
+
+ `git remote add mwhooker https://github.com/mwhooker/packer.git`
+
+3. Checkout a feature branch:
+
+ `git checkout -b new-feature`
+
+4. Make changes.
+5. (Optional) Push your changes to the fork:
+
+ `git push -u <name of remote> new-feature`
+
+This way you can push to your fork to create a PR, but the code on disk still
+lives in the spot where the go cli tools are expecting to find it.
+
+#### Go modules & go vendor
+
+If you are submitting a change that requires new or updated dependencies,
+please include them in `go.mod`/`go.sum` and in the `vendor/` folder. This
+helps everything get tested properly in CI.
+
+Note that you will need to use [go
+mod](https://github.com/golang/go/wiki/Modules) to do this. This step is
+recommended but not required.
+
+Use `go get <project>` to add dependencies to the project and `go mod vendor`
+to make vendored copy of dependencies. See [go mod quick
+start](https://github.com/golang/go/wiki/Modules#quick-start) for examples.
+
+Please only apply the minimal vendor changes to get your PR to work. Packer
+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)
+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
+your machine's performances. To make it faster it is recommended to run
+localized code generation. Say you are working on the Amazon builder: running
+`go generate ./builder/amazon/...` will do that for you. Make sure that the
+latest code generation tool is installed by running `make install-gen-deps`.
+
+#### Code linting
+
+Packer relies on [golangci-lint](https://github.com/golangci/golangci-lint) for linting its Go code base, excluding any generated code created by `go generate`. Linting is executed on new files during Travis builds via `make ci`; the linting of existing code base is only executed when running `make lint`. Linting a large project like Packer is an iterative process so existing code base will have issues that are actively being fixed; pull-requests that fix existing linting issues are always welcomed :smile:.
+
+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.
+
+```
+make ci-lint
+```
+
+#### Running Unit Tests
+
+You can run tests for individual packages using commands like this:
+
+```
+make test TEST=./builder/amazon/...
+```
+
+#### Running Builder 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.
+
+**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.
+
+To run the acceptance tests, invoke `make testacc`:
+
+```
+make testacc TEST=./builder/amazon/ebs
+...
+```
+
+The `TEST` variable lets you narrow the scope of the acceptance tests to a
+specific package / folder. The `TESTARGS` variable is recommended to filter down
+to a specific resource to test, since testing all of them at once can sometimes
+take a very long time.
+
+To run only a specific test, use the `-run` argument:
+
+```
+make testacc TEST=./builder/amazon/ebs TESTARGS="-run TestBuilderAcc_forceDeleteSnapshot"
+```
+
+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
+socket therefore using a debugger will not work (be complicated at least).
+
+But most of the Packer code is really simple and easy to follow with PACKER_LOG
+turned on. If that doesn't work adding some extra debug print outs when you have
+homed in on the problem is usually enough.
diff --git a/v1.9.4/.github/ISSUE_TEMPLATE/bug_report.md b/v1.9.4/.github/ISSUE_TEMPLATE/bug_report.md
new file mode 100644
index 0000000..b02fc4b
--- /dev/null
+++ b/v1.9.4/.github/ISSUE_TEMPLATE/bug_report.md
@@ -0,0 +1,50 @@
+---
+name: Bug Report
+about: You're experiencing an issue with Packer that is different from the documented behavior.
+labels: bug
+---
+
+<!--- Please keep this note for the community --->
+
+#### 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 other comments that do not add relevant new information or questions, 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
+
+<!--- Thank you for keeping this note for the community --->
+
+When filing a bug, please include the following headings if possible. Any
+example text in this template can be deleted.
+
+#### Overview of the Issue
+
+A paragraph or two about the issue you're experiencing.
+
+#### Reproduction Steps
+
+Steps to reproduce this issue
+
+### Packer version
+
+From `packer version`
+
+### Simplified Packer Template
+
+If the file is longer than a few dozen lines, please include the URL to the
+[gist](https://gist.github.com/) of the log or use the [Github detailed
+format](https://gist.github.com/ericclemmons/b146fe5da72ca1f706b2ef72a20ac39d)
+instead of posting it directly in the issue.
+
+### Operating system and Environment details
+
+OS, Architecture, and any other information you can provide about the
+environment.
+
+### Log Fragments and crash.log files
+
+Include appropriate log fragments. If the log is longer than a few dozen lines,
+please include the URL to the [gist](https://gist.github.com/) of the log or
+use the [Github detailed format](https://gist.github.com/ericclemmons/b146fe5da72ca1f706b2ef72a20ac39d) instead of posting it directly in the issue.
+
+Set the env var `PACKER_LOG=1` for maximum log detail.
diff --git a/v1.9.4/.github/ISSUE_TEMPLATE/config.yml b/v1.9.4/.github/ISSUE_TEMPLATE/config.yml
new file mode 100644
index 0000000..eae8012
--- /dev/null
+++ b/v1.9.4/.github/ISSUE_TEMPLATE/config.yml
@@ -0,0 +1,8 @@
+# Copyright (c) HashiCorp, Inc.
+# SPDX-License-Identifier: MPL-2.0
+
+blank_issues_enabled: false
+contact_links:
+ - name: Packer Community Support
+ url: https://discuss.hashicorp.com/c/packer/23
+ about: If you have a question, or are looking for advice, please post on our Discuss forum! The community loves to chime in to help. Happy Coding!
diff --git a/v1.9.4/.github/ISSUE_TEMPLATE/feature_requests.md b/v1.9.4/.github/ISSUE_TEMPLATE/feature_requests.md
new file mode 100644
index 0000000..1d73353
--- /dev/null
+++ b/v1.9.4/.github/ISSUE_TEMPLATE/feature_requests.md
@@ -0,0 +1,35 @@
+---
+name: Feature Request
+about: If you have something you think Packer could improve or add support for.
+labels: enhancement
+---
+
+<!--- Please keep this note for the community --->
+
+#### 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 other comments that do not add relevant new information or questions, 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
+
+<!--- Thank you for keeping this note for the community --->
+
+Please search the existing issues for relevant feature requests, and use the
+reaction feature
+(https://blog.github.com/2016-03-10-add-reactions-to-pull-requests-issues-and-comments/)
+to add upvotes to pre-existing requests.
+
+#### Description
+
+A written overview of the feature.
+
+#### Use Case(s)
+
+Any relevant use-cases that you see.
+
+#### Potential configuration
+
+```
+```
+
+#### Potential References
diff --git a/v1.9.4/.github/ISSUE_TEMPLATE/question.md b/v1.9.4/.github/ISSUE_TEMPLATE/question.md
new file mode 100644
index 0000000..83a7fd0
--- /dev/null
+++ b/v1.9.4/.github/ISSUE_TEMPLATE/question.md
@@ -0,0 +1,15 @@
+---
+name: Question
+about: If you have a question, please check out our other community resources instead of opening an issue.
+labels: question
+---
+
+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
+- 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
diff --git a/v1.9.4/.github/ISSUE_TEMPLATE/ssh_or_winrm_times_out.md b/v1.9.4/.github/ISSUE_TEMPLATE/ssh_or_winrm_times_out.md
new file mode 100644
index 0000000..1206ae0
--- /dev/null
+++ b/v1.9.4/.github/ISSUE_TEMPLATE/ssh_or_winrm_times_out.md
@@ -0,0 +1,23 @@
+---
+name: SSH or WinRM times out
+about: I have a waiting SSH or WinRM error.
+labels: communicator-question
+---
+
+Got one of the following errors ? See if the related guides can help.
+
+- `Waiting for WinRM to become available` ?
+
+ - See our basic WinRm Packer guide: https://www.packer.io/guides/automatic-operating-system-installs/autounattend_windows
+
+- `Waiting for SSH to become available` ?
+
+ - 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
+- 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
diff --git a/v1.9.4/.github/PULL_REQUEST_TEMPLATE.md b/v1.9.4/.github/PULL_REQUEST_TEMPLATE.md
new file mode 100644
index 0000000..243d893
--- /dev/null
+++ b/v1.9.4/.github/PULL_REQUEST_TEMPLATE.md
@@ -0,0 +1,19 @@
+**DELETE THIS TEMPLATE BEFORE SUBMITTING**
+
+In order to have a good experience with our community, we recommend that you
+read the contributing guidelines for making a PR, and understand the lifecycle
+of a Packer PR:
+
+https://github.com/hashicorp/packer/blob/master/.github/CONTRIBUTING.md#opening-an-pull-request
+
+Describe the change you are making here!
+
+Please include tests. Check out these examples:
+
+- https://github.com/hashicorp/packer/blob/master/builder/parallels/common/ssh_config_test.go#L34
+- https://github.com/hashicorp/packer/blob/master/post-processor/compress/post-processor_test.go#L153-L182
+
+If your PR resolves any open issue(s), please indicate them like this so they will be closed when your PR is merged:
+
+Closes #xxx
+Closes #xxx
diff --git a/v1.9.4/.github/dependabot.yml b/v1.9.4/.github/dependabot.yml
new file mode 100644
index 0000000..bbf1c27
--- /dev/null
+++ b/v1.9.4/.github/dependabot.yml
@@ -0,0 +1,9 @@
+version: 2
+updates:
+- package-ecosystem: gomod
+ directory: /
+ schedule:
+ interval: daily
+ allow:
+ - dependency-name: "github.com/hashicorp/packer-plugin-sdk"
+ - dependency-name: "github.com/hashicorp/hcp-sdk-go"
diff --git a/v1.9.4/.github/labeler-issue-triage.yml b/v1.9.4/.github/labeler-issue-triage.yml
new file mode 100644
index 0000000..1737a33
--- /dev/null
+++ b/v1.9.4/.github/labeler-issue-triage.yml
@@ -0,0 +1,8 @@
+# Copyright (c) HashiCorp, Inc.
+# SPDX-License-Identifier: MPL-2.0
+
+bug:
+ - 'panic:'
+crash:
+ - 'panic:'
+
diff --git a/v1.9.4/.github/workflows/acceptance-test.yml b/v1.9.4/.github/workflows/acceptance-test.yml
new file mode 100644
index 0000000..98d012c
--- /dev/null
+++ b/v1.9.4/.github/workflows/acceptance-test.yml
@@ -0,0 +1,95 @@
+#
+# This GitHub action runs Packer's acceptance tests every night.
+# Failures are reported to slack.
+#
+
+name: "Acceptance Test"
+
+on:
+ schedule:
+ # Runs against the default branch every day at midnight
+ - cron: "0 0 * * *"
+
+permissions:
+ contents: read
+
+jobs:
+ get-go-version:
+ runs-on: ubuntu-latest
+ outputs:
+ go-version: ${{ steps.get-go-version.outputs.go-version }}
+ steps:
+ - uses: actions/checkout@8e5e7e5ab8b370d6c329ec480221332ada57f0ab # v3.5.2
+ - name: 'Determine Go version'
+ id: get-go-version
+ # We use .go-version as our source of truth for current Go
+ # version, because "goenv" can react to it automatically.
+ run: |
+ echo "Building with Go $(cat .go-version)"
+ echo "go-version=$(cat .go-version)" >> $GITHUB_OUTPUT
+ acceptance-test:
+ runs-on: ubuntu-latest
+ name: Acceptance Test
+ needs: get-go-version
+ env:
+ # AWS Creds for Assume Role
+ AWS_ROLE_ARN: ${{ secrets.AWS_ROLE_ARN }}
+ AWS_ACCESS_KEY_ID: ${{ secrets.TESTACC_AWS_ACCESS_KEY_ID }}
+ AWS_SECRET_ACCESS_KEY: ${{ secrets.TESTACC_AWS_SECRET_ACCESS_KEY }}
+ AWS_REGION: ${{ secrets.TESTACC_AWS_REGION }}
+ # Packer GH Token for API Rate Limiting
+ PACKER_GITHUB_API_TOKEN: ${{ secrets.GITHUB_TOKEN }}
+ steps:
+ - uses: actions/checkout@8e5e7e5ab8b370d6c329ec480221332ada57f0ab # v3.5.2
+ - uses: actions/setup-go@4d34df0c2316fe8122ab82dc22947d607c0c91f9 # v4.0.0
+ with:
+ go-version: ${{ needs.get-go-version.outputs.go-version }}
+ - name: IAM Assume Role
+ uses: aws-actions/configure-aws-credentials@e1e17a757e536f70e52b5a12b2e8d1d1c60e04ef # v2.0.0
+ with:
+ role-to-assume: ${{ env.AWS_ROLE_ARN }}
+ aws-region: ${{ env.AWS_REGION }}
+ aws-access-key-id: ${{ env.AWS_ACCESS_KEY_ID }}
+ aws-secret-access-key: ${{ env.AWS_SECRET_ACCESS_KEY }}
+ role-duration-seconds: 3600
+ - name: Install gotestsum
+ run: go install gotest.tools/gotestsum@latest
+ - name: Run acceptance tests per module
+ run: |
+ mkdir -p /tmp/test-results
+ make dev
+ PACKER_ACC=1 gotestsum --format=short-verbose --junitfile /tmp/test-results/gotestsum-report.xml -- -timeout=120m -p 2 $(go list ./... | grep -v inspec | grep -v profitbricks | grep -v oneandone)
+ # Send a slack notification if either job defined above fails
+ slack-notify:
+ permissions:
+ contents: none
+ needs:
+ - get-go-version
+ - acceptance-test
+ if: always() && (needs.get-go-version.result == 'failure' || needs.acceptance-test.result == 'failure')
+ runs-on: ubuntu-latest
+ steps:
+ - name: Send slack notification on failure
+ uses: slackapi/slack-github-action@007b2c3c751a190b6f0f040e47ed024deaa72844 # v1.23.0
+ with:
+ payload: |
+ {
+ "text": ":alert: Packer Nightly Acceptance Tests *FAILED* :alert:",
+ "attachments": [
+ {
+ "color": "#C41E3A",
+ "blocks": [
+ {
+ "type": "section",
+ "text": {
+ "type": "mrkdwn",
+ "text": "Branch: `${{ github.ref_name }}`\nRef: ${{ github.event.pull_request.html_url || github.event.head_commit.url }}\nWorkflow: ${{ github.server_url }}/${{ github.repository }}/actions/runs/${{ github.run_id }}"
+ }
+ }
+ ]
+ }
+ ]
+ }
+ env:
+ SLACK_WEBHOOK_URL: ${{ secrets.SLACK_WEBHOOK_URL }}
+ SLACK_WEBHOOK_TYPE: INCOMING_WEBHOOK
diff --git a/v1.9.4/.github/workflows/auto-close-stale-issues.yml b/v1.9.4/.github/workflows/auto-close-stale-issues.yml
new file mode 100644
index 0000000..40b04de
--- /dev/null
+++ b/v1.9.4/.github/workflows/auto-close-stale-issues.yml
@@ -0,0 +1,29 @@
+name: Close Stale Issues
+
+on:
+ schedule:
+ - cron: '0 0 * * *'
+
+permissions:
+ contents: read
+
+jobs:
+ stale-bot:
+ permissions:
+ issues: write # for actions/stale to close stale issues
+ pull-requests: write # for actions/stale to close stale PRs
+ runs-on: ubuntu-latest
+ steps:
+ - uses: actions/stale@a20b814fb01b71def3bd6f56e7494d667ddf28da # v8.0.0
+ with:
+ repo-token: ${{ secrets.GITHUB_TOKEN }}
+ days-before-issue-stale: 23
+ days-before-pr-stale: -1 # deactivate the action for PRs
+ days-before-close: 7
+ stale-issue-message: |
+ Hi,
+
+ This issue has not received any update in the last 3 weeks, and will automatically be closed in 7 days if it does not receive any activity by then.
+
+ If you find the [community forum](https://discuss.hashicorp.com/c/packer) to be more helpful or if you've found the answer to your question elsewhere please feel free to post a response and close the issue.
+ only-labels: needs-reply
diff --git a/v1.9.4/.github/workflows/backport.yml b/v1.9.4/.github/workflows/backport.yml
new file mode 100644
index 0000000..bb6e5b8
--- /dev/null
+++ b/v1.9.4/.github/workflows/backport.yml
@@ -0,0 +1,52 @@
+---
+name: Backport Assistant Runner
+
+on:
+ pull_request_target:
+ types:
+ - closed
+ - labeled
+
+permissions:
+ contents: read
+
+jobs:
+ backport:
+ permissions:
+ contents: none
+ if: github.event.pull_request.merged
+ runs-on: ubuntu-latest
+ container: hashicorpdev/backport-assistant:0.2.3
+ steps:
+ - name: Backport changes to stable-website
+ run: |
+ backport-assistant backport -automerge
+ env:
+ BACKPORT_LABEL_REGEXP: "backport/(?P<target>website)"
+ BACKPORT_TARGET_TEMPLATE: "stable-{{.target}}"
+ GITHUB_TOKEN: ${{ secrets.ELEVATED_GITHUB_TOKEN }}
+ - name: Backport changes to latest release branch
+ run: |
+ resp=$(curl -f -s "https://api.github.com/repos/$GITHUB_REPOSITORY/labels?per_page=100")
+ ret="$?"
+ if [[ "$ret" -ne 0 ]]; then
+ echo "The GitHub API returned $ret"
+ exit $ret
+ fi
+ # get the latest backport label excluding any website labels, ex: `backport/0.3.x` and not `backport/website`
+ latest_backport_label=$(echo "$resp" | jq -r '.[] | select(.name | (startswith("backport/") and (contains("website") | not))) | .name' | sort -rV | head -n1)
+ echo "Latest backport label: $latest_backport_label"
+ # set BACKPORT_TARGET_TEMPLATE for backport-assistant
+ # trims backport/ from the beginning with parameter substitution
+ export BACKPORT_TARGET_TEMPLATE="release/${latest_backport_label#backport/}"
+ backport-assistant backport -automerge
+ env:
+ BACKPORT_LABEL_REGEXP: "backport/(?P<target>website)"
+ GITHUB_TOKEN: ${{ secrets.ELEVATED_GITHUB_TOKEN }}
+ - name: Backport changes to targeted release branch
+ run: |
+ backport-assistant backport -automerge
+ env:
+ BACKPORT_LABEL_REGEXP: "backport/(?P<target>\\d+\\.\\d+\\.\\w+)"
+ BACKPORT_TARGET_TEMPLATE: "release/{{.target}}"
+ GITHUB_TOKEN: ${{ secrets.ELEVATED_GITHUB_TOKEN }}
diff --git a/v1.9.4/.github/workflows/build.yml b/v1.9.4/.github/workflows/build.yml
new file mode 100644
index 0000000..0f13bed
--- /dev/null
+++ b/v1.9.4/.github/workflows/build.yml
@@ -0,0 +1,281 @@
+#
+# This GitHub action builds Packer binaries, linux packages,
+# and Docker images from source, and uploads them to GitHub artifacts.
+# Note that artifacts available via GitHub Artifacts are not codesigned or notarized.
+#
+
+name: build
+
+on:
+ workflow_dispatch:
+ workflow_call:
+ push:
+ branches:
+ - main
+ - release/**
+
+env:
+ REPO_NAME: "packer"
+
+permissions:
+ contents: read
+
+jobs:
+ get-go-version:
+ runs-on: ubuntu-latest
+ outputs:
+ go-version: ${{ steps.get-go-version.outputs.go-version }}
+ steps:
+ - uses: actions/checkout@8e5e7e5ab8b370d6c329ec480221332ada57f0ab # v3.5.2
+ - name: 'Determine Go version'
+ id: get-go-version
+ # We use .go-version as our source of truth for current Go
+ # version, because "goenv" can react to it automatically.
+ run: |
+ echo "Building with Go $(cat .go-version)"
+ echo "go-version=$(cat .go-version)" >> $GITHUB_OUTPUT
+
+ set-product-version:
+ runs-on: ubuntu-latest
+ outputs:
+ product-version: ${{ steps.set-product-version.outputs.product-version }}
+ base-product-version: ${{ steps.set-product-version.outputs.base-product-version }}
+ product-date: ${{ steps.get-product-version.outputs.product-date }}
+ product-prerelease-version: ${{ steps.set-product-version.outputs.prerelease-product-version }}
+ set-ld-flags: ${{ steps.set-ld-flags.outputs.set-ld-flags }}
+ steps:
+ - uses: actions/checkout@8e5e7e5ab8b370d6c329ec480221332ada57f0ab # v3.5.2
+ - name: set product version
+ id: set-product-version
+ uses: hashicorp/actions-set-product-version@v1
+ - name: set-ld-flags
+ id: set-ld-flags
+ run: |
+ T="github.com/hashicorp/packer/version"
+ echo "set-ld-flags=-s -w -X ${T}.GitCommit=${GITHUB_SHA::8} -X ${T}.GitDescribe=${{ steps.set-product-version.outputs.product-version }} -X ${T}.Version=${{ steps.set-product-version.outputs.base-product-version }} -X ${T}.VersionPrerelease=${{ steps.set-product-version.outputs.prerelease-product-version }} -X ${T}.VersionMetadata=" >> $GITHUB_OUTPUT
+ - name: validate outputs
+ run: |
+ echo "Product Version: ${{ steps.set-product-version.outputs.product-version }}"
+ echo "Base Product Version: ${{ steps.set-product-version.outputs.base-product-version }}"
+ echo "Prerelease Version: ${{ steps.set-product-version.outputs.prerelease-product-version }}"
+ echo "ldflags: ${{ steps.set-ld-flags.outputs.set-ld-flags }}"
+
+ generate-metadata-file:
+ needs: set-product-version
+ runs-on: ubuntu-latest
+ outputs:
+ filepath: ${{ steps.generate-metadata-file.outputs.filepath }}
+ steps:
+ - name: 'Checkout directory'
+ uses: actions/checkout@8e5e7e5ab8b370d6c329ec480221332ada57f0ab # v3.5.2
+ - name: Generate metadata file
+ id: generate-metadata-file
+ uses: hashicorp/actions-generate-metadata@main
+ with:
+ version: ${{ needs.set-product-version.outputs.product-version }}
+ product: ${{ env.REPO_NAME }}
+
+ - uses: actions/upload-artifact@0b7f8abb1508181956e8e162db84b466c27e18ce # v3.1.2
+ with:
+ name: metadata.json
+ path: ${{ steps.generate-metadata-file.outputs.filepath }}
+
+ build-other:
+ needs:
+ - set-product-version
+ - get-go-version
+ runs-on: ubuntu-latest
+ strategy:
+ matrix:
+ goos: [ freebsd, windows, netbsd, openbsd, solaris ]
+ goarch: [ "386", "amd64", "arm"]
+ go: [ "${{ needs.get-go-version.outputs.go-version }}" ]
+ exclude:
+ - goos: solaris
+ goarch: 386
+ - goos: solaris
+ goarch: arm
+ - goos: windows
+ goarch: arm
+ fail-fast: true
+
+ name: Go ${{ matrix.go }} ${{ matrix.goos }} ${{ matrix.goarch }} build
+
+ env:
+ GOPRIVATE: "github.com/hashicorp"
+ GO111MODULE: on
+ steps:
+ - uses: actions/checkout@8e5e7e5ab8b370d6c329ec480221332ada57f0ab # v3.5.2
+ - name: Go Build
+ env:
+ PRODUCT_VERSION: ${{ needs.set-product-version.outputs.product-version }}
+ PRERELEASE_VERSION: ${{ needs.set-product-version.outputs.product-prerelease-version }}
+ LD_FLAGS: "${{ needs.set-product-version.outputs.set-ld-flags}}"
+ CGO_ENABLED: "0"
+ uses: hashicorp/actions-go-build@v0.1.9
+ with:
+ product_name: ${{ env.REPO_NAME }}
+ product_version: ${{ needs.set-product-version.outputs.product-version }}
+ go_version: ${{ matrix.go }}
+ os: ${{ matrix.goos }}
+ arch: ${{ matrix.goarch }}
+ reproducible: report
+ instructions: |-
+ go build -o "$BIN_PATH" -ldflags="$LD_FLAGS" -trimpath -buildvcs=false
+
+ build-linux:
+ needs:
+ - set-product-version
+ - get-go-version
+ runs-on: ubuntu-latest
+ strategy:
+ matrix:
+ goos: [ linux ]
+ goarch: [ "arm", "arm64", "386", "amd64", "ppc64le"]
+ go: [ "${{ needs.get-go-version.outputs.go-version }}" ]
+ fail-fast: true
+
+ name: Go ${{ matrix.go }} ${{ matrix.goos }} ${{ matrix.goarch }} build
+
+ env:
+ GOPRIVATE: "github.com/hashicorp"
+ GO111MODULE: on
+
+ steps:
+ - uses: actions/checkout@8e5e7e5ab8b370d6c329ec480221332ada57f0ab # v3.5.2
+ - name: Go Build
+ env:
+ PRODUCT_VERSION: ${{ needs.set-product-version.outputs.product-version }}
+ PRERELEASE_VERSION: ${{ needs.set-product-version.outputs.product-prerelease-version }}
+ LD_FLAGS: "${{ needs.set-product-version.outputs.set-ld-flags}}"
+ CGO_ENABLED: "0"
+ uses: hashicorp/actions-go-build@v0.1.9
+ with:
+ product_name: ${{ env.REPO_NAME }}
+ product_version: ${{ needs.set-product-version.outputs.product-version }}
+ go_version: ${{ matrix.go }}
+ os: ${{ matrix.goos }}
+ arch: ${{ matrix.goarch }}
+ reproducible: report
+ instructions: |-
+ go build -o "$BIN_PATH" -ldflags="$LD_FLAGS" -trimpath -buildvcs=false
+
+ - name: Linux Packaging
+ uses: hashicorp/actions-packaging-linux@v1
+ with:
+ name: ${{ env.REPO_NAME }}
+ description: "HashiCorp Packer - A tool for creating identical machine images for multiple platforms from a single source configuration"
+ arch: ${{ matrix.goarch }}
+ version: ${{ needs.set-product-version.outputs.product-version }}
+ maintainer: "HashiCorp"
+ homepage: "https://www.packer.io/docs"
+ license: "MPL-2.0"
+ binary: "dist/${{ env.REPO_NAME }}"
+ deb_depends: "openssl"
+ rpm_depends: "openssl"
+ - name: Add Linux Package names to env
+ run: |
+ echo "RPM_PACKAGE=$(basename out/*.rpm)" >> $GITHUB_ENV
+ echo "DEB_PACKAGE=$(basename out/*.deb)" >> $GITHUB_ENV
+ - uses: actions/upload-artifact@0b7f8abb1508181956e8e162db84b466c27e18ce # v3.1.2
+ with:
+ name: ${{ env.RPM_PACKAGE }}
+ path: out/${{ env.RPM_PACKAGE }}
+ - uses: actions/upload-artifact@0b7f8abb1508181956e8e162db84b466c27e18ce # v3.1.2
+ with:
+ name: ${{ env.DEB_PACKAGE }}
+ path: out/${{ env.DEB_PACKAGE }}
+
+ build-darwin:
+ needs:
+ - set-product-version
+ - get-go-version
+ runs-on: macos-latest
+ strategy:
+ matrix:
+ goos: [ darwin ]
+ goarch: [ "amd64", "arm64" ]
+ go: [ "${{ needs.get-go-version.outputs.go-version }}" ]
+ fail-fast: true
+ name: Go ${{ matrix.go }} ${{ matrix.goos }} ${{ matrix.goarch }} build
+
+ env:
+ GOPRIVATE: "github.com/hashicorp"
+ GO111MODULE: on
+
+ steps:
+ - uses: actions/checkout@8e5e7e5ab8b370d6c329ec480221332ada57f0ab # v3.5.2
+ - name: Go Build
+ env:
+ PRODUCT_VERSION: ${{ needs.set-product-version.outputs.product-version }}
+ PRERELEASE_VERSION: ${{ needs.set-product-version.outputs.product-prerelease-version }}
+ LD_FLAGS: "${{ needs.set-product-version.outputs.set-ld-flags}}"
+ CGO_ENABLED: "0"
+ uses: hashicorp/actions-go-build@v0.1.9
+ with:
+ product_name: ${{ env.REPO_NAME }}
+ product_version: ${{ needs.set-product-version.outputs.product-version }}
+ go_version: ${{ matrix.go }}
+ os: ${{ matrix.goos }}
+ arch: ${{ matrix.goarch }}
+ reproducible: report
+ instructions: |-
+ go build -o "$BIN_PATH" -ldflags="$LD_FLAGS" -tags netcgo -trimpath -buildvcs=false
+
+ build-docker-light:
+ name: Docker light ${{ matrix.arch }} build
+ needs:
+ - set-product-version
+ - build-linux
+ runs-on: ubuntu-latest
+ strategy:
+ matrix:
+ arch: [ "arm", "arm64", "386", "amd64" ]
+ env:
+ version: ${{ needs.set-product-version.outputs.product-version }}
+ steps:
+ - uses: actions/checkout@8e5e7e5ab8b370d6c329ec480221332ada57f0ab # v3.5.2
+ - name: Docker Build (Action)
+ uses: hashicorp/actions-docker-build@v1
+ with:
+ version: ${{ env.version }}
+ target: release-light
+ arch: ${{ matrix.arch }}
+ tags: |
+ docker.io/hashicorp/${{ env.REPO_NAME }}:light
+ docker.io/hashicorp/${{ env.REPO_NAME }}:light-${{ env.version }}
+ docker.io/hashicorp/${{ env.REPO_NAME }}:${{ env.version }}
+ public.ecr.aws/hashicorp/${{ env.REPO_NAME }}:light
+ public.ecr.aws/hashicorp/${{ env.REPO_NAME }}:light-${{ env.version }}
+ public.ecr.aws/hashicorp/${{ env.REPO_NAME }}:${{ env.version }}
+ dev_tags: |
+ docker.io/hashicorppreview/${{ env.REPO_NAME }}:${{ env.version }}
+ docker.io/hashicorppreview/${{ env.REPO_NAME }}:${{ env.version }}-${{ github.sha }}
+
+ build-docker-full:
+ name: Docker full ${{ matrix.arch }} build
+ needs:
+ - set-product-version
+ - build-linux
+ runs-on: ubuntu-latest
+ strategy:
+ matrix:
+ arch: [ "arm", "arm64", "386", "amd64" ]
+ env:
+ version: ${{ needs.set-product-version.outputs.product-version }}
+ steps:
+ - uses: actions/checkout@c85c95e3d7251135ab7dc9ce3241c5835cc595a9 # v3.5.3
+ - name: Docker Build (Action)
+ uses: hashicorp/actions-docker-build@v1
+ with:
+ version: ${{ env.version }}
+ target: release-full
+ arch: ${{ matrix.arch }}
+ tags: |
+ docker.io/hashicorp/${{ env.REPO_NAME }}:full
+ docker.io/hashicorp/${{ env.REPO_NAME }}:full-${{ env.version }}
+ public.ecr.aws/hashicorp/${{ env.REPO_NAME }}:full
+ public.ecr.aws/hashicorp/${{ env.REPO_NAME }}:full-${{ env.version }}
+ dev_tags: |
+ docker.io/hashicorppreview/${{ env.REPO_NAME }}:full-${{ env.version }}
+ docker.io/hashicorppreview/${{ env.REPO_NAME }}:full-${{ env.version }}-${{ github.sha }}
diff --git a/v1.9.4/.github/workflows/check-legacy-links-format.yml b/v1.9.4/.github/workflows/check-legacy-links-format.yml
new file mode 100644
index 0000000..08c128a
--- /dev/null
+++ b/v1.9.4/.github/workflows/check-legacy-links-format.yml
@@ -0,0 +1,17 @@
+name: Legacy Link Format Checker
+
+on:
+ push:
+ paths:
+ - "website/content/**/*.mdx"
+ - "website/data/*-nav-data.json"
+
+jobs:
+ check-links:
+ uses: hashicorp/dev-portal/.github/workflows/docs-content-check-legacy-links-format.yml@475289345d312552b745224b46895f51cc5fc490
+ with:
+ repo-owner: "hashicorp"
+ repo-name: "packer"
+ commit-sha: ${{ github.sha }}
+ mdx-directory: "website/content"
+ nav-data-directory: "website/data"
diff --git a/v1.9.4/.github/workflows/check-plugin-docs.js b/v1.9.4/.github/workflows/check-plugin-docs.js
new file mode 100644
index 0000000..cb61a18
--- /dev/null
+++ b/v1.9.4/.github/workflows/check-plugin-docs.js
@@ -0,0 +1,105 @@
+const fs = require("fs");
+const path = require("path");
+const { resolvePluginDocs } = require("@hashicorp/platform-packer-plugins");
+
+const COLOR_RESET = "\x1b[0m";
+const COLOR_GREEN = "\x1b[32m";
+const COLOR_BLUE = "\x1b[34m";
+const COLOR_RED = "\x1b[31m";
+
+const VALID_PLUGIN_TIERS = ["official", "community", "verified"];
+
+
+async function checkPluginDocs() {
+ const failureMessages = [];
+ const pluginsPath = "website/data/plugins-manifest.json";
+ const pluginsFile = fs.readFileSync(path.join(process.cwd(), pluginsPath));
+ const pluginEntries = JSON.parse(pluginsFile);
+ const pluginEntriesWithDocs = await resolvePluginDocs(pluginEntries);
+ const entriesCount = pluginEntries.length;
+ console.log(`\nResolving plugin docs from ${entriesCount} repositories …`);
+ for (var i = 0; i < entriesCount; i++) {
+ const pluginEntry = pluginEntriesWithDocs[i];
+ const { title, repo, version } = pluginEntry;
+ console.log(`\n${COLOR_BLUE}${repo}${COLOR_RESET} | ${title}`);
+ console.log(`Fetching docs from release "${version}" …`);
+ try {
+ // Validate that all required properties are present
+ const undefinedProps = ["title", "repo", "version", "path"].filter(
+ (key) => typeof pluginEntry[key] == "undefined"
+ );
+ if (undefinedProps.length > 0) {
+ throw new Error(
+ `Failed to validate plugin docs config. Undefined configuration properties ${JSON.stringify(
+ undefinedProps
+ )} found for "${
+ title || pluginEntry.path || repo
+ }". In "website/data/docs-remote-plugins.json", please ensure the missing properties ${JSON.stringify(
+ undefinedProps
+ )} are defined. Additional information on this configuration can be found in "website/README.md".`
+ );
+ }
+ // Validate pluginTier property
+ const { pluginTier } = pluginEntry;
+ if (typeof pluginTier !== "undefined") {
+ const isValid = VALID_PLUGIN_TIERS.indexOf(pluginTier) !== -1;
+ if (!isValid) {
+ throw new Error(
+ `Failed to validate plugin docs config. Invalid pluginTier "${pluginTier}" found for "${
+ title || pluginEntry.path || repo
+ }". In "website/data/docs-remote-plugins.json", the optional pluginTier property must be one of ${JSON.stringify(
+ VALID_PLUGIN_TIERS
+ )}. The pluginTier property can also be omitted, in which case it will be determined from the plugin repository owner.`
+ );
+ }
+ }
+ // Validate that local zip files are not used in production
+ if (typeof pluginEntry.zipFile !== "undefined") {
+ throw new Error(
+ `Local ZIP file being used for "${
+ title || pluginEntry.path || repo
+ }". The zipFile option should only be used for local development. Please omit the zipFile attribute and ensure the plugin entry points to a remote repository.`
+ );
+ }
+ // Attempt to fetch plugin docs files
+ const docsMdxFiles = pluginEntry.files
+ const mdxFilesByComponent = docsMdxFiles.reduce((acc, mdxFile) => {
+ const componentType = mdxFile.filePath.split("/")[1];
+ if (!acc[componentType]) acc[componentType] = [];
+ acc[componentType].push(mdxFile);
+ return acc;
+ }, {});
+ console.log(`${COLOR_GREEN}Found valid docs:${COLOR_RESET}`);
+ Object.keys(mdxFilesByComponent).forEach((component) => {
+ const componentFiles = mdxFilesByComponent[component];
+ console.log(` ${component}`);
+ componentFiles.forEach(({ filePath }) => {
+ const pathFromComponent = filePath.split("/").slice(2).join("/");
+ console.log(` ├── ${pathFromComponent}`);
+ });
+ });
+ } catch (err) {
+ console.log(`${COLOR_RED}${err}${COLOR_RESET}`);
+ failureMessages.push(`\n${COLOR_RED}× ${repo}: ${COLOR_RESET}${err}`);
+ }
+ }
+
+ if (failureMessages.length === 0) {
+ console.log(
+ `\n---\n\n${COLOR_GREEN}Summary: Successfully resolved all plugin docs.`
+ );
+ pluginEntries.forEach((e) =>
+ console.log(`${COLOR_GREEN}✓ ${e.repo}${COLOR_RESET}`)
+ );
+ console.log("");
+ } else {
+ console.log(
+ `\n---\n\n${COLOR_RED}Summary: Failed to fetch docs for ${failureMessages.length} plugin(s):`
+ );
+ failureMessages.forEach((err) => console.log(err));
+ console.log("");
+ process.exit(1);
+ }
+}
+
+checkPluginDocs();
diff --git a/v1.9.4/.github/workflows/check-plugin-docs.yml b/v1.9.4/.github/workflows/check-plugin-docs.yml
new file mode 100644
index 0000000..c43ae9c
--- /dev/null
+++ b/v1.9.4/.github/workflows/check-plugin-docs.yml
@@ -0,0 +1,34 @@
+#
+# This GitHub action checks plugin repositories for valid docs.
+#
+# This provides a quick assessment on PRs of whether
+# there might be issues with docs in plugin repositories.
+#
+# This is intended to help debug Vercel build issues, which
+# may or may not be related to docs in plugin repositories.
+
+name: "website: Check plugin docs"
+on:
+ pull_request:
+ paths:
+ - "website/**"
+ schedule:
+ - cron: "45 0 * * *"
+
+permissions:
+ contents: read
+
+jobs:
+ check-plugin-docs:
+ runs-on: ubuntu-latest
+ steps:
+ - name: Checkout
+ uses: actions/checkout@8e5e7e5ab8b370d6c329ec480221332ada57f0ab # v3.5.2
+ - name: Setup Node
+ uses: actions/setup-node@64ed1c7eab4cce3362f8c340dee64e5eaeef8f7c # v3.6.0
+ with:
+ node-version: '16.x'
+ - name: Install Dependencies
+ run: npm i @hashicorp/platform-packer-plugins
+ - name: Fetch and validate plugin docs
+ run: node .github/workflows/check-plugin-docs.js
diff --git a/v1.9.4/.github/workflows/create-release-branch.yml b/v1.9.4/.github/workflows/create-release-branch.yml
new file mode 100644
index 0000000..0d1f4f3
--- /dev/null
+++ b/v1.9.4/.github/workflows/create-release-branch.yml
@@ -0,0 +1,10 @@
+name: Create a release branch
+on: [workflow_dispatch]
+jobs:
+ create-branch:
+ runs-on: ubuntu-latest
+ steps:
+ - uses: actions/checkout@8e5e7e5ab8b370d6c329ec480221332ada57f0ab # v3.5.2
+ - uses: hashicorp/actions-create-release-branch@v1
+ with:
+ token: ${{ secrets.ELEVATED_GITHUB_TOKEN }}
diff --git a/v1.9.4/.github/workflows/go-test.yml b/v1.9.4/.github/workflows/go-test.yml
new file mode 100644
index 0000000..93f8eeb
--- /dev/null
+++ b/v1.9.4/.github/workflows/go-test.yml
@@ -0,0 +1,65 @@
+#
+# This GitHub action runs Packer go tests across
+# Windows, Linux, and MacOS runners.
+#
+
+name: "Go Test"
+
+on:
+ push:
+ branches:
+ - 'main'
+ - release/**
+ pull_request:
+
+env:
+ PACKER_GITHUB_API_TOKEN: ${{ secrets.GITHUB_TOKEN }}
+
+permissions:
+ contents: read
+
+jobs:
+ get-go-version:
+ runs-on: ubuntu-latest
+ outputs:
+ go-version: ${{ steps.get-go-version.outputs.go-version }}
+ steps:
+ - uses: actions/checkout@8f4b7f84864484a7bf31766abe9204da3cbe65b3 # v3.5.0
+ - name: 'Determine Go version'
+ id: get-go-version
+ run: |
+ echo "Found Go $(cat .go-version)"
+ echo "go-version=$(cat .go-version)" >> $GITHUB_OUTPUT
+ linux-go-tests:
+ needs:
+ - get-go-version
+ runs-on: ubuntu-latest
+ name: Linux go tests
+ steps:
+ - uses: actions/checkout@8e5e7e5ab8b370d6c329ec480221332ada57f0ab # v3.5.2
+ - uses: actions/setup-go@4d34df0c2316fe8122ab82dc22947d607c0c91f9 # v4.0.0
+ with:
+ go-version: ${{ needs.get-go-version.outputs.go-version }}
+ - run: TESTARGS="-coverprofile=coverage.txt -covermode=atomic" make ci
+ darwin-go-tests:
+ needs:
+ - get-go-version
+ runs-on: macos-latest
+ name: Darwin go tests
+ steps:
+ - uses: actions/checkout@8e5e7e5ab8b370d6c329ec480221332ada57f0ab # v3.5.2
+ - uses: actions/setup-go@4d34df0c2316fe8122ab82dc22947d607c0c91f9 # v4.0.0
+ with:
+ go-version: ${{ needs.get-go-version.outputs.go-version }}
+ - run: go test ./... -coverprofile=coverage.txt -covermode=atomic
+ windows-go-tests:
+ needs:
+ - get-go-version
+ runs-on: windows-latest
+ name: Windows go tests
+ steps:
+ - uses: actions/checkout@8e5e7e5ab8b370d6c329ec480221332ada57f0ab # v3.5.2
+ - uses: actions/setup-go@4d34df0c2316fe8122ab82dc22947d607c0c91f9 # v4.0.0
+ with:
+ go-version: ${{ needs.get-go-version.outputs.go-version }}
+ - run: go test ./... -coverprofile=coverage.txt -covermode=atomic
diff --git a/v1.9.4/.github/workflows/go-validate.yml b/v1.9.4/.github/workflows/go-validate.yml
new file mode 100644
index 0000000..d67b3aa
--- /dev/null
+++ b/v1.9.4/.github/workflows/go-validate.yml
@@ -0,0 +1,77 @@
+#
+# This GitHub action runs basic linting checks for Packer.
+#
+
+name: "Go Validate"
+
+on:
+ push:
+ branches:
+ - 'main'
+ - release/**
+ pull_request:
+
+permissions:
+ contents: read
+
+jobs:
+ get-go-version:
+ runs-on: ubuntu-latest
+ outputs:
+ go-version: ${{ steps.get-go-version.outputs.go-version }}
+ steps:
+ - uses: actions/checkout@8f4b7f84864484a7bf31766abe9204da3cbe65b3 # v3.5.0
+ - name: 'Determine Go version'
+ id: get-go-version
+ run: |
+ echo "Found Go $(cat .go-version)"
+ echo "go-version=$(cat .go-version)" >> $GITHUB_OUTPUT
+ check-mod-tidy:
+ needs:
+ - get-go-version
+ runs-on: ubuntu-latest
+ name: Go Mod Tidy
+ steps:
+ - uses: actions/checkout@8f4b7f84864484a7bf31766abe9204da3cbe65b3 # v3.5.0
+ - uses: actions/setup-go@4d34df0c2316fe8122ab82dc22947d607c0c91f9 # v4.0.0
+ with:
+ go-version: ${{ needs.get-go-version.outputs.go-version }}
+ - run: go mod tidy
+ check-lint:
+ needs:
+ - get-go-version
+ runs-on: ubuntu-latest
+ name: Lint
+ steps:
+ - uses: actions/checkout@8e5e7e5ab8b370d6c329ec480221332ada57f0ab # v3.5.2
+ with:
+ fetch-depth: 0
+ - uses: actions/setup-go@4d34df0c2316fe8122ab82dc22947d607c0c91f9 # v4.0.0
+ with:
+ go-version: ${{ needs.get-go-version.outputs.go-version }}
+ - run: echo "$GITHUB_SHA"
+ - run: git fetch --all
+ - run: echo $(git merge-base origin/main $GITHUB_SHA)
+ - run: make ci-lint
+ check-fmt:
+ needs:
+ - get-go-version
+ runs-on: ubuntu-latest
+ name: Fmt check
+ steps:
+ - uses: actions/checkout@8e5e7e5ab8b370d6c329ec480221332ada57f0ab # v3.5.2
+ - uses: actions/setup-go@4d34df0c2316fe8122ab82dc22947d607c0c91f9 # v4.0.0
+ with:
+ go-version: ${{ needs.get-go-version.outputs.go-version }}
+ - run: make fmt-check
+ check-generate:
+ needs:
+ - get-go-version
+ runs-on: ubuntu-latest
+ name: Generate check
+ steps:
+ - uses: actions/checkout@8e5e7e5ab8b370d6c329ec480221332ada57f0ab # v3.5.2
+ - uses: actions/setup-go@4d34df0c2316fe8122ab82dc22947d607c0c91f9 # v4.0.0
+ with:
+ go-version: ${{ needs.get-go-version.outputs.go-version }}
+ - run: make generate-check
diff --git a/v1.9.4/.github/workflows/issue-comment-created.yml b/v1.9.4/.github/workflows/issue-comment-created.yml
new file mode 100644
index 0000000..f250dc1
--- /dev/null
+++ b/v1.9.4/.github/workflows/issue-comment-created.yml
@@ -0,0 +1,23 @@
+name: Issue Comment Created Triage
+
+on:
+ issue_comment:
+ types: [created]
+
+permissions:
+ contents: read
+
+jobs:
+ issue_comment_triage:
+ permissions:
+ contents: read # for actions/checkout to fetch code
+ issues: write # for actions-ecosystem/action-remove-labels to remove issue labels
+ runs-on: ubuntu-latest
+ steps:
+ - uses: actions/checkout@8e5e7e5ab8b370d6c329ec480221332ada57f0ab # v3.5.2
+ - uses: actions-ecosystem/action-remove-labels@2ce5d41b4b6aa8503e285553f75ed56e0a40bae0 # v1.3.0
+ with:
+ github_token: "${{ secrets.GITHUB_TOKEN }}"
+ labels: |
+ stale
+ waiting-reply
diff --git a/v1.9.4/.github/workflows/issue-migrator.yml b/v1.9.4/.github/workflows/issue-migrator.yml
new file mode 100644
index 0000000..9acc66e
--- /dev/null
+++ b/v1.9.4/.github/workflows/issue-migrator.yml
@@ -0,0 +1,27 @@
+name: Migrate Remote Plugin Issues
+
+on:
+ issues:
+ types: [labeled]
+
+permissions:
+ issues: write
+
+jobs:
+ PluginSplit:
+ if: startsWith(github.event.label.name, 'remote-plugin/')
+ runs-on: ubuntu-latest
+ steps:
+ - uses: bflad/action-migrate-issue@main # TSCCR: no entry for repository "bflad/action-migrate-issue"
+ with:
+ source-issue-comment: |
+ This issue has been migrated to {target-issue-url} due to the [Packer Plugin split](https://github.com/hashicorp/packer/issues/8610#issuecomment-770034737).
+
+ Please follow the new issue for updates.
+ source-issue-skip-label-names: |
+ core
+ new-plugin-contribution
+ website
+ target-repository-name-prefix: 'packer-plugin-'
+ target-repository-name-prefix-label-prefix: 'remote-plugin/'
+ target-repository-github-token: ${{ secrets.PLUGIN_REPO_GITHUB_TOKEN }}
diff --git a/v1.9.4/.github/workflows/issues-opened.yml b/v1.9.4/.github/workflows/issues-opened.yml
new file mode 100644
index 0000000..57a8cd0
--- /dev/null
+++ b/v1.9.4/.github/workflows/issues-opened.yml
@@ -0,0 +1,46 @@
+on:
+ issues:
+ types: [opened]
+
+permissions:
+ contents: read
+
+jobs:
+ issue_triage:
+ name: Issue Opened Triage
+ permissions:
+ contents: read
+ issues: write # for github/issue-labeler to create or remove labels
+ runs-on: ubuntu-latest
+ steps:
+ - uses: actions/checkout@8e5e7e5ab8b370d6c329ec480221332ada57f0ab # v3.5.2
+ - uses: github/issue-labeler@e24a3eb6b2e28c8904d086302a2b760647f5f45c # v3.1
+ with:
+ repo-token: "${{ secrets.GITHUB_TOKEN }}"
+ configuration-path: .github/labeler-issue-triage.yml
+ enable-versioned-regex: 0
+ label-question:
+ name: Redirect to discuss
+ permissions:
+ contents: read
+ issues: write # for actions-ecosystem/action-create-comment to create comments
+ if: contains(github.event.issue.labels.*.name, 'question')
+ runs-on: ubuntu-latest
+ steps:
+ - uses: actions-ecosystem/action-create-comment@v1.0.2 # TSCCR: no entry for repository "actions-ecosystem/action-create-comment"
+ with:
+ github_token: ${{ secrets.GITHUB_TOKEN }}
+ body: |
+ Hi 👋 thanks for reaching out.
+
+ For general questions we recommend reaching out to the [community forum](https://discuss.hashicorp.com/c/packer) for greater visibility.
+ As the GitHub issue tracker is only watched by a small subset of maintainers and is really reserved for bugs and enhancements, you'll have a better chance of finding someone who can help you in the forum.
+ We'll mark this issue as needs-reply to help inform maintainers that this question is awaiting a response.
+ If no activity is taken on this question within 30 days it will be automatically closed.
+
+ If you find the forum to be more helpful or if you've found the answer to your question elsewhere please feel free to post a response and close the issue.
+ - uses: actions-ecosystem/action-add-labels@v1.1.3 # TSCCR: no entry for repository "actions-ecosystem/action-add-labels"
+ with:
+ github_token: ${{ secrets.GITHUB_TOKEN }}
+ labels: needs-reply
+
diff --git a/v1.9.4/.github/workflows/jira.yml b/v1.9.4/.github/workflows/jira.yml
new file mode 100644
index 0000000..e0e82a9
--- /dev/null
+++ b/v1.9.4/.github/workflows/jira.yml
@@ -0,0 +1,86 @@
+on:
+ issues:
+ types: [labeled]
+
+permissions:
+ contents: read
+
+name: JIRA Sync
+
+jobs:
+ sync:
+ name: Sync to JIRA
+ permissions:
+ issues: write # for actions-ecosytem/action-create-comment
+ runs-on: ubuntu-latest
+ steps:
+ - name: Login
+ uses: atlassian/gajira-login@45fd029b9f1d6d8926c6f04175aa80c0e42c9026 # v3.0.1
+ env:
+ JIRA_BASE_URL: ${{ secrets.JIRA_BASE_URL }}
+ JIRA_USER_EMAIL: ${{ secrets.JIRA_USER_EMAIL }}
+ JIRA_API_TOKEN: ${{ secrets.JIRA_API_TOKEN }}
+
+ - name: Search
+ if: github.event.action == 'labeled'
+ id: search
+ uses: tomhjp/gh-action-jira-search@04700b457f317c3e341ce90da5a3ff4ce058f2fa # v0.2.2
+ with:
+ # cf[10089] is Issue Link (use JIRA API to retrieve)
+ jql: 'project = "HPR" AND cf[10089] = "${{ github.event.issue.html_url }}"'
+
+
+ - name: Set type
+ id: set-ticket-type
+ run: |
+ # Questions are not tracked in JIRA at this time.
+ if [[ "${{ contains(github.event.issue.labels.*.name, 'question') }}" == "true" ]]; then
+ echo "type=Invalid" >> $GITHUB_OUTPUT
+ else
+ # Properly labeled GH issues are assigned the standard "GH Issue" type upon creation.
+ echo "type=GH Issue" >> $GITHUB_OUTPUT
+ fi
+
+ - name: Set labels
+ id: set-ticket-labels
+ run: |
+ if [[ "${{ contains(github.event.issue.labels.*.name, 'bug') }}" == "true" ]]; then
+ echo "labels=[\"bug\"]" >> $GITHUB_OUTPUT
+ elif [[ "${{ contains(github.event.issue.labels.*.name, 'enhancement') }}" == "true" ]]; then
+ echo "labels=[\"enhancement\"]" >> $GITHUB_OUTPUT
+ else
+ echo "labels=[]" >> $GITHUB_OUTPUT
+ fi
+
+ - name: Validate ticket
+ if: steps.set-ticket-type.outputs.type == 'Invalid'
+ run: |
+ echo "Questions are not being synced to JIRA at this time."
+ echo "If the issue is a bug or an enhancement please remove the question label and reapply the 'sync to jira' label."
+
+ - name: Create ticket
+ id: create-ticket
+ if: steps.search.outputs.issue == '' && github.event.label.name == 'sync to jira' && steps.set-ticket-type.outputs.type != 'Invalid'
+ uses: atlassian/gajira-create@59e177c4f6451399df5b4911c2211104f171e669 # v3.0.1
+ with:
+ project: HPR
+ issuetype: "${{ steps.set-ticket-type.outputs.type }}"
+ summary: "${{ github.event.repository.name }}: ${{ github.event.issue.title }}"
+ description: "${{ github.event.issue.body }}\n\n_Created from GitHub by ${{ github.actor }}._"
+ # The field customfield_10089 refers to the Issue Link field in JIRA.
+ fields: '{ "customfield_10089": "${{ github.event.issue.html_url }}",
+ "components": [{ "name": "OSS" }],
+ "labels": ${{ steps.set-ticket-labels.outputs.labels }} }'
+
+ - name: Add tracking comment
+ if: steps.create-ticket.outputs.issue != '' && steps.set-ticket-type.outputs.type != 'Invalid'
+ uses: actions-ecosystem/action-create-comment@v1.0.0 # TSCCR: no entry for repository "actions-ecosystem/action-create-comment"
+ with:
+ github_token: ${{ secrets.GITHUB_TOKEN }}
+ body: |
+ This issue has been synced to JIRA for planning.
+
+ JIRA ID: [${{ steps.create-ticket.outputs.issue }}](https://hashicorp.atlassian.net/browse/${{steps.create-ticket.outputs.issue}})
+
+
+
diff --git a/v1.9.4/.github/workflows/lock.yml b/v1.9.4/.github/workflows/lock.yml
new file mode 100644
index 0000000..77f57ab
--- /dev/null
+++ b/v1.9.4/.github/workflows/lock.yml
@@ -0,0 +1,35 @@
+name: 'Lock Threads'
+
+on:
+ schedule:
+ - cron: '50 1 * * *'
+
+# Only 50 issues will be handled during a given run.
+permissions:
+ contents: read
+
+jobs:
+ lock:
+ permissions:
+ issues: write # for dessant/lock-threads to lock issues
+ pull-requests: write # for dessant/lock-threads to lock PRs
+ runs-on: ubuntu-latest
+ steps:
+ - uses: dessant/lock-threads@c1b35aecc5cdb1a34539d14196df55838bb2f836 # v4.0.0
+ with:
+ github-token: ${{ github.token }}
+ issue-comment: >
+ 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.
+
+ If you have found a problem that seems similar to this, please open a new issue and complete the issue template so we can capture all the details necessary to investigate further.
+ issue-inactive-days: '30'
+ # Issues older than 180 days ago should be ignored
+ exclude-issue-created-before: '2020-11-01'
+ pr-comment: >
+ I'm going to lock this pull request because it has been closed for _30 days_ ⏳. This helps our maintainers find and focus on the active issues.
+
+ If you have found a problem that seems related to this change, please open a new issue and complete the issue template so we can capture all the details necessary to investigate further.
+ pr-inactive-days: '30'
+ # Issues older than 180 days ago should be ignored
+ exclude-pr-created-before: '2020-11-01'
+
diff --git a/v1.9.4/.github/workflows/nightly-release-readme.md b/v1.9.4/.github/workflows/nightly-release-readme.md
new file mode 100644
index 0000000..4f92515
--- /dev/null
+++ b/v1.9.4/.github/workflows/nightly-release-readme.md
@@ -0,0 +1,5 @@
+Nightly releases are snapshots of the development activity on the Packer project that may include new features and bug fixes scheduled for upcoming [releases](https://github.com/hashicorp/packer/milestones). These releases are made available to make it easier for users to test their existing build configurations against the latest Packer code base for potential issues or to experiment with new features, with a chance to provide feedback on ways to improve the changes before being released.
+
+As these releases are snapshots of the latest code, you may encounter an issue compared to the latest stable release. Users are encouraged to run nightly releases in a non production environment. If you encounter an issue, please check our [issue tracker](https://github.com/hashicorp/packer/issues) to see if the issue has already been reported; if a report hasn't been made, please report it so we can review the issue and make any needed fixes.
+
+**Note**: Nightly releases are only available via GitHub Releases, and artifacts are not codesigned or notarized. Distribution via other [Release Channels](https://www.hashicorp.com/official-release-channels) such as the Releases Site or Homebrew is not yet supported.
diff --git a/v1.9.4/.github/workflows/nightly-release.yml b/v1.9.4/.github/workflows/nightly-release.yml
new file mode 100644
index 0000000..ea388be
--- /dev/null
+++ b/v1.9.4/.github/workflows/nightly-release.yml
@@ -0,0 +1,142 @@
+#
+# This GitHub action triggers a fresh set of Packer builds
+# and publishes them to GitHub Releases under the `nightly` tag.
+# Note that artifacts available via GitHub Releases are not codesigned or notarized.
+# Failures are reported to slack.
+#
+
+name: Nightly Release
+
+on:
+ schedule:
+ # Runs against the default branch every day at midnight
+ - cron: "0 0 * * *"
+ workflow_dispatch:
+
+permissions:
+ contents: write
+
+jobs:
+ # Build a fresh set of artifacts
+ build-artifacts:
+ uses: hashicorp/packer/.github/workflows/build.yml@main
+ github-release:
+ needs: build-artifacts
+ runs-on: ubuntu-latest
+ steps:
+ - uses: actions/checkout@8e5e7e5ab8b370d6c329ec480221332ada57f0ab # v3.5.2
+ - name: Download built artifacts
+ uses: actions/download-artifact@9bc31d5ccc31df68ecc42ccf4149144866c47d8a # v3.0.2
+ with:
+ path: out/
+ # Set BUILD_OUTPUT_LIST to out\<project>-<version>.<fileext>\*,out\...
+ # This is needed to attach the build artifacts to the GitHub Release
+ - name: Set BUILD_OUTPUT_LIST
+ run: |
+ echo "$(ls -xm1 out/)" > tmp.txt
+ cat tmp.txt | sed 's:.*:out/&/*:' > tmp2.txt
+ echo "BUILD_OUTPUT_LIST=$(cat tmp2.txt | tr '\n' ',' | perl -ple 'chop')" >> $GITHUB_ENV
+ rm -rf tmp.txt && rm -rf tmp2.txt
+ - name: Advance nightly tag
+ uses: actions/github-script@ffc2c79a5b2490bd33e0a41c1de74b877714d736 # v3
+ with:
+ github-token: ${{ secrets.GITHUB_TOKEN }}
+ script: |
+ try {
+ await github.git.deleteRef({
+ owner: context.repo.owner,
+ repo: context.repo.repo,
+ ref: "tags/nightly"
+ })
+ } catch (e) {
+ console.log("Warning: The nightly tag doesn't exist yet, so there's nothing to do. Trace: " + e)
+ }
+ await github.git.createRef({
+ owner: context.repo.owner,
+ repo: context.repo.repo,
+ ref: "refs/tags/nightly",
+ sha: context.sha
+ })
+ # This will create a new GitHub Release called `nightly`
+ # If a release with this name already exists, it will overwrite the existing data
+ - name: Create a nightly GitHub prerelease
+ id: create_prerelease
+ continue-on-error: true
+ uses: ncipollo/release-action@v1 # TSCCR: no entry for repository "ncipollo/release-action"
+ with:
+ name: nightly
+ artifacts: "${{ env.BUILD_OUTPUT_LIST }}"
+ tag: nightly
+ bodyFile: ".github/workflows/nightly-release-readme.md"
+ prerelease: true
+ allowUpdates: true
+ removeArtifacts: true
+ draft: false
+ token: ${{ secrets.GITHUB_TOKEN }}
+ - name: Store GitHub Release ID
+ if: steps.create_prerelease.outcome == 'success'
+ run: |
+ echo "prerelease_id=${{ steps.create_prerelease.outputs.id }}" >> $GITHUB_ENV
+ - name: Sleep before retry
+ id: sleep_before_retry
+ if: steps.create_prerelease.outcome == 'failure'
+ run : sleep 30m
+ shell: bash
+ - name: Retry failed nightly GitHub prerelease
+ id: create_prerelease_retry
+ if: steps.create_prerelease.outcome == 'failure'
+ uses: ncipollo/release-action@v1 # TSCCR: no entry for repository "ncipollo/release-action"
+ with:
+ name: nightly
+ artifacts: "${{ env.BUILD_OUTPUT_LIST }}"
+ tag: nightly
+ bodyFile: ".github/workflows/nightly-release-readme.md"
+ prerelease: true
+ allowUpdates: true
+ removeArtifacts: true
+ draft: false
+ token: ${{ secrets.GITHUB_TOKEN }}
+ - name: Store Updated GitHub Release ID
+ if: steps.create_prerelease_retry.outcome == 'success'
+ run: |
+ echo "prerelease_id=${{ steps.create_prerelease_retry.outputs.id }}" >> $GITHUB_ENV
+ - name: Publish nightly GitHub prerelease
+ uses: eregon/publish-release@v1 # TSCCR: no entry for repository "eregon/publish-release"
+ env:
+ GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
+ with:
+ release_id: ${{ env.prerelease_id }}
+ # Send a slack notification if either job defined above fails
+ slack-notify:
+ permissions:
+ contents: none
+ needs:
+ - build-artifacts
+ - github-release
+ if: always() && (needs.build-artifacts.result == 'failure' || needs.github-release.result == 'failure')
+ runs-on: ubuntu-latest
+ steps:
+ - name: Send slack notification on failure
+ uses: slackapi/slack-github-action@007b2c3c751a190b6f0f040e47ed024deaa72844 # v1.23.0
+ with:
+ payload: |
+ {
+ "text": ":alert: Packer Nightly Release *FAILED* :alert:",
+ "attachments": [
+ {
+ "color": "#C41E3A",
+ "blocks": [
+ {
+ "type": "section",
+ "text": {
+ "type": "mrkdwn",
+ "text": "Branch: `${{ github.ref_name }}`\nRef: ${{ github.sha }}\nWorkflow: ${{ github.server_url }}/${{ github.repository }}/actions/runs/${{ github.run_id }}"
+ }
+ }
+ ]
+ }
+ ]
+ }
+ env:
+ SLACK_WEBHOOK_URL: ${{ secrets.SLACK_WEBHOOK_URL }}
+ SLACK_WEBHOOK_TYPE: INCOMING_WEBHOOK
diff --git a/v1.9.4/.gitignore b/v1.9.4/.gitignore
new file mode 100644
index 0000000..9f5add0
--- /dev/null
+++ b/v1.9.4/.gitignore
@@ -0,0 +1,32 @@
+/bin
+/local
+/pkg
+/src
+/website/.sass-cache
+/website/build
+/website/tmp
+.DS_Store
+.vagrant
+.idea
+test/.env
+*~
+*.received.*
+*.swp
+
+vendor/
+
+website/.bundle
+website/vendor
+
+packer-test*.log
+
+*.received.txt
+*.received.json
+
+.idea/
+*.iml
+Thumbs.db
+/packer.exe
+.project
+cache
+/.vscode/
diff --git a/v1.9.4/.go-version b/v1.9.4/.go-version
new file mode 100644
index 0000000..8909929
--- /dev/null
+++ b/v1.9.4/.go-version
@@ -0,0 +1 @@
+1.20.7
diff --git a/v1.9.4/.golangci.yml b/v1.9.4/.golangci.yml
new file mode 100644
index 0000000..ccd990c
--- /dev/null
+++ b/v1.9.4/.golangci.yml
@@ -0,0 +1,126 @@
+# Copyright (c) HashiCorp, Inc.
+# SPDX-License-Identifier: MPL-2.0
+
+issues:
+ # List of regexps of issue texts to exclude, empty list by default.
+ # But independently from this option we use default exclude patterns,
+ # it can be disabled by `exclude-use-default: false`. To list all
+ # excluded by default patterns execute `golangci-lint run --help`
+
+ exclude-rules:
+ # Exclude gosimple bool check
+ - linters:
+ - gosimple
+ text: "S(1002|1008|1021)"
+ # Exclude failing staticchecks for now
+ - linters:
+ - staticcheck
+ text: "SA(1006|1019|4006|4010|4017|5007|6005|9004):"
+ # Exclude lll issues for long lines with go:generate
+ - linters:
+ - lll
+ source: "^//go:generate "
+
+ # Maximum issues count per one linter. Set to 0 to disable. Default is 50.
+ max-issues-per-linter: 0
+
+ # Maximum count of issues with the same text. Set to 0 to disable. Default is 3.
+ max-same-issues: 0
+
+linters:
+ disable-all: true
+ enable:
+ - deadcode
+ - errcheck
+ - goimports
+ - gosimple
+ - govet
+ - ineffassign
+ - staticcheck
+ - unconvert
+ - unused
+ - varcheck
+ fast: true
+
+# options for analysis running
+run:
+ # default concurrency is a available CPU number
+ concurrency: 4
+
+ # timeout for analysis, e.g. 30s, 5m, default is 1m
+ timeout: 10m
+
+ # exit code when at least one issue was found, default is 1
+ issues-exit-code: 1
+
+ # include test files or not, default is true
+ tests: true
+
+ # list of build tags, all linters use it. Default is empty list.
+ #build-tags:
+ # - mytag
+
+ # which dirs to skip: issues from them won't be reported;
+ # can use regexp here: generated.*, regexp is applied on full path;
+ # default value is empty list, but default dirs are skipped independently
+ # from this option's value (see skip-dirs-use-default).
+ #skip-dirs:
+ # - src/external_libs
+ # - autogenerated_by_my_lib
+
+ # default is true. Enables skipping of directories:
+ # vendor$, third_party$, testdata$, examples$, Godeps$, builtin$
+ skip-dirs-use-default: true
+
+ # which files to skip: they will be analyzed, but issues from them
+ # won't be reported. Default value is empty list, but there is
+ # no need to include all autogenerated files, we confidently recognize
+ # autogenerated files. If it's not please let us know.
+ skip-files:
+ - ".*\\.hcl2spec\\.go$"
+ # - lib/bad.go
+
+ # by default isn't set. If set we pass it to "go list -mod={option}". From "go help modules":
+ # If invoked with -mod=readonly, the go command is disallowed from the implicit
+ # automatic updating of go.mod described above. Instead, it fails when any changes
+ # to go.mod are needed. This setting is most useful to check that go.mod does
+ # not need updates, such as in a continuous integration and testing system.
+ # If invoked with -mod=vendor, the go command assumes that the vendor
+ # directory holds the correct copies of dependencies and ignores
+ # the dependency descriptions in go.mod.
+ modules-download-mode: readonly
+
+# output configuration options
+output:
+ # colored-line-number|line-number|json|tab|checkstyle|code-climate, default is "colored-line-number"
+ format: colored-line-number
+
+ # print lines of code with issue, default is true
+ print-issued-lines: true
+
+ # print linter name in the end of issue text, default is true
+ print-linter-name: true
+
+ # make issues output unique by line, default is true
+ uniq-by-line: true
+
+
+# all available settings of specific linters
+linters-settings:
+ errcheck:
+ # report about not checking of errors in type assetions: `a := b.(MyStruct)`;
+ # default is false: such cases aren't reported by default.
+ check-type-assertions: false
+
+ # report about assignment of errors to blank identifier: `num, _ := strconv.Atoi(numStr)`;
+ # default is false: such cases aren't reported by default.
+ check-blank: false
+
+ # [deprecated] comma-separated list of pairs of the form pkg:regex
+ # the regex is used to ignore names within pkg. (default "fmt:.*").
+ # see https://github.com/kisielk/errcheck#the-deprecated-method for details
+ ignore: fmt:.*,io/ioutil:^Read.*,io:Close
+
+ # path to a file containing a list of functions to exclude from checking
+ # see https://github.com/kisielk/errcheck#excluding-functions for details
+ #exclude: /path/to/file.txt
diff --git a/v1.9.4/.release/ci.hcl b/v1.9.4/.release/ci.hcl
new file mode 100644
index 0000000..6ca7eb0
--- /dev/null
+++ b/v1.9.4/.release/ci.hcl
@@ -0,0 +1,166 @@
+# Copyright (c) HashiCorp, Inc.
+# SPDX-License-Identifier: MPL-2.0
+
+schema = "1"
+
+project "packer" {
+ team = "#proj-packer-releases"
+ slack {
+ notification_channel = "C032TD9KCMQ"
+ }
+ github {
+ organization = "hashicorp"
+ repository = "packer"
+ release_branches = [
+ "main",
+ "release/**"
+ ]
+ }
+}
+
+event "merge" {
+ // "entrypoint" to use if build is not run automatically
+ // i.e. send "merge" complete signal to orchestrator to trigger build
+}
+
+event "build" {
+ depends = ["merge"]
+ action "build" {
+ organization = "hashicorp"
+ repository = "packer"
+ workflow = "build"
+ }
+}
+
+event "prepare" {
+ depends = ["build"]
+
+ action "prepare" {
+ organization = "hashicorp"
+ repository = "crt-workflows-common"
+ workflow = "prepare"
+ depends = ["build"]
+ }
+
+ notification {
+ on = "fail"
+ }
+}
+
+## These are promotion and post-publish events
+## they should be added to the end of the file after the verify event stanza.
+
+event "trigger-staging" {
+// This event is dispatched by the bob trigger-promotion command
+// and is required - do not delete.
+}
+
+event "promote-staging" {
+ depends = ["trigger-staging"]
+ action "promote-staging" {
+ organization = "hashicorp"
+ repository = "crt-workflows-common"
+ workflow = "promote-staging"
+ config = "release-metadata.hcl"
+ }
+
+ notification {
+ on = "always"
+ }
+}
+
+event "promote-staging-docker" {
+ depends = ["promote-staging"]
+ action "promote-staging-docker" {
+ organization = "hashicorp"
+ repository = "crt-workflows-common"
+ workflow = "promote-staging-docker"
+ }
+
+ notification {
+ on = "always"
+ }
+}
+
+event "trigger-production" {
+// This event is dispatched by the bob trigger-promotion command
+// and is required - do not delete.
+}
+
+event "promote-production" {
+ depends = ["trigger-production"]
+ action "promote-production" {
+ organization = "hashicorp"
+ repository = "crt-workflows-common"
+ workflow = "promote-production"
+ }
+
+ notification {
+ on = "always"
+ }
+}
+
+event "promote-production-docker" {
+ depends = ["promote-production"]
+ action "promote-production-docker" {
+ organization = "hashicorp"
+ repository = "crt-workflows-common"
+ workflow = "promote-production-docker"
+ }
+
+ notification {
+ on = "always"
+ }
+}
+
+event "promote-production-packaging" {
+ depends = ["promote-production-docker"]
+ action "promote-production-packaging" {
+ organization = "hashicorp"
+ repository = "crt-workflows-common"
+ workflow = "promote-production-packaging"
+ }
+
+ notification {
+ on = "always"
+ }
+}
+
+event "post-publish-website" {
+ depends = ["promote-production-packaging"]
+ action "post-publish-website" {
+ organization = "hashicorp"
+ repository = "crt-workflows-common"
+ workflow = "post-publish-website"
+ }
+
+ notification {
+ on = "always"
+ }
+}
+
+event "bump-version" {
+ depends = ["post-publish-website"]
+ action "bump-version" {
+ organization = "hashicorp"
+ repository = "crt-workflows-common"
+ workflow = "bump-version"
+ }
+
+ notification {
+ on = "fail"
+ }
+}
+
+event "update-ironbank" {
+ depends = ["bump-version"]
+ action "update-ironbank" {
+ organization = "hashicorp"
+ repository = "crt-workflows-common"
+ workflow = "update-ironbank"
+ }
+
+ notification {
+ on = "fail"
+ }
+}
diff --git a/v1.9.4/.release/docker/README.md b/v1.9.4/.release/docker/README.md
new file mode 100644
index 0000000..f733efb
--- /dev/null
+++ b/v1.9.4/.release/docker/README.md
@@ -0,0 +1,108 @@
+# Packer Docker Container
+
+The root of this repository contains the officially supported HashiCorp Dockerfile to build the hashicorp/packer docker image. The `dev` docker image should be built for local dev and testing, while the production docker image, `release`, is built in CI and makes use of CI-built binaries. The `light` and `full` docker images are built using the official binaries from releases.hashicorp.com.
+
+## Build
+
+Refer to the Makefile of this repository, especially the `docker` and `docker-dev` targets to build a local version of the dev image based on the sources available.
+
+### Usage
+
+This repository automatically builds containers for using the
+[`packer`](https://developer.hashicorp.com/packer) command line program. It contains three distinct
+varieties of build: a `light` version, which just contains the binary,
+a `full` build, which contains the Packer binary with pre-installed plugins,
+and a `dev` version, which compiles the binary from source
+inside the container before exposing it for use.
+
+##### `light`
+
+The `light` version of this container will copy the current stable version of
+the binary, taken from releases.hashicorp.com, into the container. It will also
+set it for use as the default entrypoint. This will be the best option for most uses,
+especially if you are just looking to run the binary from a container.
+The `latest` tag on DockerHub also points to this version.
+
+You can use this version with the following:
+```shell
+docker run <args> hashicorp/packer:light <command>
+```
+
+##### `full`
+
+The `full` version of the container builds upon `light` and pre-installs
+the plugins officially maintained by HashiCorp.
+
+You can use this version with the following:
+```shell
+docker run <args> hashicorp/packer:full <command>
+```
+
+You can view the list of pre-installed plugins with the following:
+```shell
+docker run <args> hashicorp/packer:full plugins installed
+```
+
+##### `dev`
+
+The `dev` version of this container contains all of the source code found in
+the current ref of this [repository](https://github.com/hashicorp/packer). Using [Google's
+official `golang` image](https://hub.docker.com/_/golang/) as a base, this
+container will copy the source from the current branch, build the binary, and
+expose it for running. Because all build artifacts are included, it should be quite a bit larger than
+the `light` image. This version of the container is most useful for development or
+debugging.
+
+You can use this version with the following:
+```shell
+docker run <args> hashicorp/packer:dev <command>
+```
+
+#### Running a build:
+
+The easiest way to run a command that references a configuration with one or more template files, is to mount a volume for the local workspace.
+
+Running `packer init`
+```shell
+docker run \
+ -v `pwd`:/workspace -w /workspace \
+ -e PACKER_PLUGIN_PATH=/workspace/.packer.d/plugins \
+ hashicorp/packer:latest \
+ init .
+```
+
+~> **Note**: packer init is available from Packer v1.7.0 and later
+
+The command will mount the working directory (`pwd`) to `workspace`, which is the working directory (`-w`) inside the container.
+Any plugin installed with `packer init` will be installed under the directory specified under the `PACKER_PLUGIN_PATH` environment variable. `PACKER_PLUGIN_PATH` must be set to a path inside the volume mount so that plugins can become available at `packer build`.
+
+Running `packer build`
+```shell
+docker run \
+ -v `pwd`:/workspace -w /workspace \
+ -e PACKER_PLUGIN_PATH=/workspace/.packer.d/plugins \
+ hashicorp/packer:latest \
+ build .
+```
+##### Building old-legacy JSON templates
+
+For old-legacy JSON, the build command must specify the template file(s).
+
+```shell
+docker run \
+ -v `pwd`:/workspace -w /workspace \
+ hashicorp/packer:latest \
+ build template.json
+```
+
+For the [manual installation](https://www.packer.io/docs/plugins#installing-plugins) of third-party plugins, we recommended that plugin binaries are placed under a sub-directory under the working directory. Add `-e PACKER_PLUGIN_PATH=/workspace/<subdirectory_plugin_path>` to the command above to tell Packer where the plugins are.
+
+To pass a var file (`var.json`) to the build command:
+
+```shell
+docker run \
+ -v `pwd`:/workspace -w /workspace \
+ hashicorp/packer:latest \
+ build --var-file var.json template.json
+```
+`var.json` is expected to be inside the local working directory (`pwd`) and in the container's workspace mount.
diff --git a/v1.9.4/.release/release-metadata.hcl b/v1.9.4/.release/release-metadata.hcl
new file mode 100644
index 0000000..0fb2456
--- /dev/null
+++ b/v1.9.4/.release/release-metadata.hcl
@@ -0,0 +1,8 @@
+# Copyright (c) HashiCorp, Inc.
+# SPDX-License-Identifier: MPL-2.0
+
+url_docker_registry_dockerhub = "https://hub.docker.com/r/hashicorp/packer"
+url_docker_registry_ecr = "https://gallery.ecr.aws/hashicorp/packer"
+url_license = "https://github.com/hashicorp/packer/blob/main/LICENSE"
+url_project_website = "https://www.packer.io/"
+url_source_repository = "https://github.com/hashicorp/packer"
diff --git a/v1.9.4/.release/security-scan.hcl b/v1.9.4/.release/security-scan.hcl
new file mode 100644
index 0000000..7d32581
--- /dev/null
+++ b/v1.9.4/.release/security-scan.hcl
@@ -0,0 +1,16 @@
+# Copyright (c) HashiCorp, Inc.
+# SPDX-License-Identifier: MPL-2.0
+
+container {
+ dependencies = false
+ alpine_secdb = true
+ secrets = false
+}
+
+binary {
+ secrets = true
+ go_modules = true
+ osv = true
+ oss_index = true
+ nvd = false
+}
diff --git a/v1.9.4/CHANGELOG.md b/v1.9.4/CHANGELOG.md
new file mode 100644
index 0000000..b9b36ab
--- /dev/null
+++ b/v1.9.4/CHANGELOG.md
@@ -0,0 +1,5908 @@
+## 1.9.4 (August 18, 2023)
+
+### BUG FIXES:
+
+* core: When invoking Packer with the CHECKPOINT_DISABLE environment variable the telemetry
+ reporter is left uninitialized in order to disable telemetry reporting.
+ Any method calls on the nil reporter is expected to check if the reporter is active or in
+ NOOP mode. The SetBundledUsage function, introduced in Packer 1.9.2, failed to perform a nil
+ check before attempting to modify an attribute, causing Packer to fail when telemetry is
+ disabled. This release fixes this issue by introducing such a check.
+
+## 1.9.3 (August 17, 2023)
+
+### NOTES:
+* **New Docker Image**: As part of the bundled plugin removal effort, a new
+ Docker target called `release-full` has been added to the Packer release
+ artifacts. The release-full image includes Packer and all the official
+ plugins pre-installed in its environment. This image is being offered as an
+ alternative option for those users who may still be relying on the plugin
+ versions bundled into the Packer binary.
+ [GH-12532](https://github.com/hashicorp/packer/pull/12532)
+
+### IMPROVEMENTS:
+* core/docs: Clarify the expected usage of the `packer init` command for HCL2
+ template builds.[GH-12535](https://github.com/hashicorp/packer/pull/12535)
+* core/hcp: Add support for project-level service principals. A user connecting
+ with a project level service principals must provide a valid HCP_PROJECT_ID
+ in order to connect.
+ [GH-12520](https://github.com/hashicorp/packer/pull/12520)
+ [GH-12576](https://github.com/hashicorp/packer/pull/12576)
+* core: A new Docker image `packer:release-full` has been added for all
+ supported architectures. The release-full image includes Packer and all the
+ official plugins pre-installed in its environment.
+ [GH-12532](https://github.com/hashicorp/packer/pull/12532)
+* core: Add enhanced support to Packer telemetry for bundle plugins usage.
+ [GH-12536](https://github.com/hashicorp/packer/pull/12536)
+
+### BUG FIXES:
+
+* core: Bump golang.org/x/net to v0.13.0 to address CVE GO-2023-1988. Packer
+ itself is not vulnerable to the CVE as we don't render web pages, but
+ security checks do point it as an issue that needs to be addressed.
+ [GH-12561](https://github.com/hashicorp/packer/pull/12561)
+* core: Fix custom plugin loading in current working directory regression.
+ [GH-12544](https://github.com/hashicorp/packer/pull/12544)
+
+
+## 1.9.2 (July 19, 2023)
+
+### NOTES:
+
+* Vendored plugins within Packer have not been updated. Plugin releases occur on
+ a regular basis to address issues and feature requests.
+ Please note that in an upcoming version of Packer, we will remove the last
+ bundled plugins from Packer. Users are encouraged to use `packer init` for HCL2 templates or
+ `packer plugins install` with legacy JSON templates for installing external
+ plugins.
+
+* Packer will now warn when using bundled plugins. This feature will be removed in
+ a future version of the tool, so this warning is meant to bring awareness of the
+ upcoming change, and help users update their templates.
+ [GH-12495](https://github.com/hashicorp/packer/pull/12495)
+
+### BUG FIXES:
+
+* Fixed a bug with how Packer was discovering plugins: in order to load
+ plugins, Packer would recursively scan all the known directories in which
+ we could have installed plugins. This caused unnecessary directory
+ walks and slowdowns upon invocation. Packer will now only check
+ for nested plugins within the directories used by commands such as `packer
+ init`, or `packer plugins install`, or as defined in PACKER_PLUGIN_PATH.
+ Refer to
+ [Packer's plugin directory documentation](https://developer.hashicorp.com/packer/docs/configure#packer-s-plugin-directory)
+ for details on how loading works.
+ [GH-12414](https://github.com/hashicorp/packer/pull/12414)
+
+* The `packer init` subcommand now bundles all the missing installed plugins into one
+ condensed warning, as opposed to one warning per missing plugin.
+ [GH-12506](https://github.com/hashicorp/packer/pull/12506)
+
+### PLUGINS:
+
+* packer-plugin-parallels: The Parallels plugin has been handed over to the Parallels
+ team. New releases for this plugin are available at
+ https://github.com/parallels/packer-plugin-parallels. This plugin is no longer
+ being bundled in the Packer binary release. Existing references to the
+ plugin will continue to work but users are advised to update the
+ `required_plugins` block to use the new plugin source address.
+ [GH-12476](https://github.com/hashicorp/packer/pull/12476)
+ ```
+ required_plugins {
+ parallels = {
+ source = "github.com/parallels/parallels"
+ version = "~> 1"
+ }
+ }
+ ```
+
+### IMPROVEMENTS:
+
+* The `hcl2_upgrade` sub-command will now add `required_plugins` to the template
+ generated from JSON for [official plugins](https://developer.hashicorp.com/packer/plugins#tiers-and-namespaces).
+ [GH-12504](https://github.com/hashicorp/packer/pull/12504)
+
+## 1.9.1 (June 1, 2023)
+
+### BUG FIXES:
+
+* On May 16th 2023, HCP introduced multi-project support to the platform.
+ In order to use multiple projects in your organization, you will need to update Packer
+ to version 1.9.1 or above. Starting with 1.9.1, you may specify a project ID to push
+ builds to with the `HCP_PROJECT_ID` environment variable. If no project ID is specified,
+ Packer will pick the project with the oldest creation date. Older versions of Packer are
+ incompatible with multi-project support on HCP, and builds will fail for HCP
+ organizations with multiple projects on versions before 1.9.1.
+ [GH-12453](https://github.com/hashicorp/packer/pull/12453)
+
+## 1.9.0 (May 31, 2023)
+
+### NOTES:
+
+* **Breaking Change**: Iteration fingerprints used to be computed from the Git SHA of the
+ repository where the template is located when running packer build. This
+ changes with this release, and now fingerprints are automatically generated
+ as a ULID. This implies that continuing an existing iteration will require
+ users to define the fingerprint in the environment manually in order to
+ adopt this behaviour, otherwise, by default, a new iteration will be
+ created. This does not impact workflows where the fingerprint was defined
+ through the `HCP_PACKER_ITERATION_FINGERPRINT` environment variable, and
+ these builds will work exactly as they did before.
+ [GH-12172](https://github.com/hashicorp/packer/pull/12172)
+
+* **Breaking Change**: Community-maintained plugins bundled with the Packer binary have been removed.
+ These external plugin components are released independently of Packer core and can be installed
+ directly by the user. Users relying on the external plugin components listed below should refer
+ to the `packer plugins` sub-command and, if using HCL2, a `required_plugins` block to define a
+ list of plugins for building a template.
+
+### PLUGINS
+
+* Remove provisioner plugins for Chef, Converge, Puppet, Salt, and Inspec as
+ vendored plugins. These plugins have been previously archived and not
+ updated in release since being archived. These plugins can be installed
+ using `packer init` or with the Packer plugins sub-command `packer plugins install github.com/hashicorp/chef`.
+ [GH-12374](https://github.com/hashicorp/packer/pull/12374)
+
+* The following community plugins won't be bundled with Packer anymore:
+
+ * [Alicloud](https://github.com/hashicorp/packer-plugin-alicloud)
+ * [CloudStack](https://github.com/hashicorp/packer-plugin-cloudstack)
+ * [HCloud](https://github.com/hashicorp/packer-plugin-hcloud)
+ * [HyperOne](https://github.com/hashicorp/packer-plugin-hyperone)
+ * [Hyper-V](https://github.com/hashicorp/packer-plugin-hyperv)
+ * [JDCloud](https://github.com/hashicorp/packer-plugin-jdcloud)
+ * [LXC](https://github.com/hashicorp/packer-plugin-lxc)
+ * [LXD](https://github.com/hashicorp/packer-plugin-lxd)
+ * [NCloud](https://github.com/hashicorp/packer-plugin-ncloud)
+ * [OpenStack](https://github.com/hashicorp/packer-plugin-openstack)
+ * [Proxmox](https://github.com/hashicorp/packer-plugin-proxmox)
+ * [TencentCloud](https://github.com/hashicorp/packer-plugin-tencentcloud)
+ * [Triton](https://github.com/hashicorp/packer-plugin-triton)
+ * [Yandex](https://github.com/hashicorp/packer-plugin-yandex)
+
+ [GH-12436](https://github.com/hashicorp/packer/pull/12436)
+
+Users relying on these external plugin components should refer to the `packer plugins` sub-command and,
+if using HCL2, a `required_plugins` block to define a list of plugins to use for building a template.
+
+### IMPROVEMENTS:
+
+* core/hcp: Now, fingerprints used by HCP Packer are randomly generated ULIDs
+ instead of a Git SHA, and a new one is always generated, unless one is
+ specified in the environment.
+ [GH-12172](https://github.com/hashicorp/packer/pull/12172)
+
+### BUG FIXES:
+
+* Fix LDFLAGS for release pipelines: Between Packer 1.8.5 and Packer 1.8.7, changes
+ to the LDFLAGS in use for building the binaries for Packer had mistakenly
+ removed some compilation flags, leading to the final binaries not being stripped.
+ This change raised the size of the built binaries by as much as 45%.
+ In this release, we fixed the LDFLAGS during compilation, yielding leaner binaries.
+
+* Bumped gopsutil to v3. This fixes a macOS intermittent crash reported by the community
+ [GH-12430](https://github.com/hashicorp/packer/issues/12430)
+
+## 1.8.7 (May 4, 2023)
+
+### NOTES:
+* Vendored plugins within Packer have not been updated. Plugin releases occur on
+ a regular basis to address issues and feature requests. Users are encouraged
+ to use `packer init` for HCL2 templates or `packer plugins install` with
+ legacy JSON templates for installing external plugins.
+
+* packer-plugin-digitalocean: The Digital Ocean Packer plugin has been handed
+ over to the Digital Ocean team. New releases for this plugin are available
+ at https://github.com/digitalocean/packer-plugin-digitalocean.
+ ```
+ required_plugins {
+ digitalocean = {
+ source = "github.com/digitalocean/digitalocean"
+ version = ">=1.1.1"
+ }
+ }
+ ```
+* packer-plugin-linode: The Linode plugin has been handed over to the Linode
+ team. New releases for this plugin are available at
+ https://github.com/linode/packer-plugin-linode. This plugin is is no longer
+ being bundled in the Packer binary release. Existing references to the
+ plugin will continue to work but users are advised to update the
+ `required_plugins` block to use the new plugin source address.
+ [GH-12329](https://github.com/hashicorp/packer/pull/12329)
+ ```
+ required_plugins {
+ linode = {
+ source = "github.com/linode/linode"
+ version = ">=1.0.5"
+ }
+ }
+ ```
+* packer-plugin-ucloud: The UCloud plugin has been handed over to the UCloud
+ team. New releases for this plugin are available at
+ https://github.com/ucloud/packer-plugin-ucloud. This plugin is is no longer
+ being bundled in the Packer binary release. Existing references to the
+ plugin will continue to work but users are advised to update the
+ `required_plugins` block to use the new plugin source address.
+ [GH-12335](https://github.com/hashicorp/packer/pull/12335)
+ ```
+ required_plugins {
+ ucloud = {
+ source = "github.com/ucloud/ucloud"
+ version = ">=1.0.8"
+ }
+ }
+ ```
+* packer-plugin-profitbricks: The Profitbricks plugin has been removed as a
+ bundled plugin in Packer. New releases for this plugin are available at
+ https://github.com/hashicorp/packer-plugin-profitbricks. This plugin is is
+ no longer being bundled in the Packer binary release. Existing references
+ to the plugin will continue to work but users are advised to update the
+ `required_plugins` block to use the new plugin source address.
+ [GH-12385](https://github.com/hashicorp/packer/pull/12385)
+ ```
+ required_plugins {
+ ucloud = {
+ source = "github.com/hashicorp/profitbricks"
+ version = ">=1.0.2"
+ }
+ }
+ ```
+
+### PLUGINS
+* core: Migrate external Linode plugin to linode/packer-plugin-linode.
+ [GH-12329](https://github.com/hashicorp/packer/pull/12329)
+* core: Migrate external UCloud plugin to ucloud/packer-plugin-ucloud.
+ [GH-12335](https://github.com/hashicorp/packer/pull/12335)
+* core: Remove external plugin for Digital Ocean as a vendored plugin.
+ [GH-12376](https://github.com/hashicorp/packer/pull/12376)
+* core: Remove external plugins for Profitbricks and 1&1 as vendored plugins.
+ [GH-12385](https://github.com/hashicorp/packer/pull/12385)
+* docs: Add HCP Ready label to Oracle builder components.
+ [GH-12217](https://github.com/hashicorp/packer/pull/12217)
+
+
+### IMPROVEMENTS
+* cmd/console: Add config-type flag to command help.
+ [GH-12360](https://github.com/hashicorp/packer/pull/12360)
+* core: Add enhanced support to Packer telemetry for HCL2.
+ [GH-12319](https://github.com/hashicorp/packer/pull/12319)
+* Enhance zsh completion for the Packer command.
+ [GH-12356](https://github.com/hashicorp/packer/pull/12356),
+ [GH-12366](https://github.com/hashicorp/packer/pull/12366)
+
+### BUG FIXES
+* cmd/hcl2_upgrade: Fix a crash when running the hcl2_upgrade command against a
+ legacy JSON template containing user variables with an undefined variables
+ block. [GH-12257](https://github.com/hashicorp/packer/pull/12257)
+* core: Bump github.com/hashicorp/hcp-sdk-go to 0.36.0.
+ [GH-12292](https://github.com/hashicorp/packer/pull/12292)
+* core: Bump github.com/hashicorp/packer-plugin-sdk to 0.4.0 to address
+ CVE-2023-0475, CVE-2022-41723.
+ [GH-12306](https://github.com/hashicorp/packer/pull/12306)
+* core: Bump Go module version to 1.20
+ [GH-12380](https://github.com/hashicorp/packer/pull/12380)
+* core: Fix regression introduced in 1.8.6, where legacy JSON templates with
+ custom builder names are outputted to STDOUT as uninterpolated user
+ variables. [GH-12290](https://github.com/hashicorp/packer/pull/12290)
+
+
+## 1.8.6 (February 15, 2023)
+
+### NOTES:
+* core: Users will see some changes in how names are displayed during a Packer
+ build for JSON templates. Previously only the builder type or the builder
+ name, if it was set, would be displayed. Now for named builders
+ (`"name":"mybuilder"`) the builder's type and name will be displayed (i.e
+ "<type>.mybuilder". This does not impact the behavior of options such as
+ only or except, they will continue to work as they did before.)
+
+### PLUGINS:
+The following external plugins have been updated and pinned to address open
+ issues. Please see their respective changelogs for details on plugin
+ specific bug fixes and improvements.
+
+* alicloud@v1.0.7 - [CHANGELOG](https://github.com/hashicorp/packer-plugin-alicloud/releases/tag/v1.0.7)
+* amazon@v1.2.1 - [CHANGELOG](https://github.com/hashicorp/packer-plugin-amazon/releases/tag/v1.2.1)
+* azure@v1.4.0 - [CHANGELOG](https://github.com/hashicorp/packer-plugin-azure/releases/tag/v1.4.0)
+* googlecompute@v1.1.0 - [CHANGELOG](https://github.com/hashicorp/packer-plugin-googlecompute/releases/tag/v1.1.0)
+* proxmox@v1.1.1 - [CHANGELOG](https://github.com/hashicorp/packer-plugin-proxmox/releases/tag/v1.1.1)
+* tencentcloud@v1.0.6 - [CHANGELOG](https://github.com/hashicorp/packer-plugin-tencentcloud/releases/tag/v1.0.6)
+* qemu@v1.0.9 - [CHANGELOG](https://github.com/hashicorp/packer-plugin-qemu/releases/tag/v1.0.9)
+
+
+### IMPROVEMENTS:
+* Bump bundled plugins to latest available version.
+ [GH-12274](https://github.com/hashicorp/packer/pull/12274)
+* bump github.com/hashicorp/hcp-sdk-go from 0.28.0 to 0.29.0
+ [GH-12163](https://github.com/hashicorp/packer/pull/12163)
+* Bump github.com/hashicorp/hcp-sdk-go from 0.33.0 to 0.34.0
+ [GH-12275](https://github.com/hashicorp/packer/pull/12275)
+* core/hcl2: Packer will no longer warn on excluded post-processors when using
+ `-only/exlude` filters for running select builds.
+ [GH-12187](https://github.com/hashicorp/packer/pull/12187)
+
+### BUG FIXES:
+* cmd/hcl2_upgrade: Fix crash when variables block is undefined.
+ [GH-12250](https://github.com/hashicorp/packer/pull/12250)
+* core/hcl2: Templates with build blocks referencing an unknown source block
+ would display an empty string for the template filename at line 0, which
+ made it difficult to identify the broken build block. Packer has been
+ updated to display the proper filename and line number where the unknown
+ reference resides.
+ [GH-12167](https://github.com/hashicorp/packer/pull/12167)
+* core: Linux packages now have vendor label and set the default label to
+ HashiCorp. This fix is implemented for any future releases, but will not be
+ updated for historical releases.
+ [GH-12252](https://github.com/hashicorp/packer/pull/12252)
+* core/hcp: The bucket's description was not properly set in the bucket
+ object sent to HCP Packer leaving all newly created buckets with an empty
+ description. [GH-12235]
+ [GH-12235](https://github.com/hashicorp/packer/pull/12235)
+
+## 1.8.5 (December 12, 2022)
+
+### NOTES:
+* data/packer-image-iteration has been removed. This was an undocumented and
+ unusable data source that was built for experimentation but not released. It
+ should not affect users in any way but is being mentioned for visibility
+ purposes.
+ [GH-12111](https://github.com/hashicorp/packer/pull/12111)
+
+### FEATURES:
+* core: Metadata for capturing template types such as JSON or HCL2 has been added to the
+ HCP Packer registry metadata. Upon running a `packer build` the type of
+ template used during execution will be sent along to the registry as
+ additional build metadata.[GH-12132](https://github.com/hashicorp/packer/pull/12132)
+
+### PLUGINS:
+The following external plugins have been updated and pinned to address open
+ issues. Please see their respective changelogs for details on plugin
+ specific bug fixes and improvements.
+
+* alicloud@v1.0.5 - [CHANGELOG](https://github.com/hashicorp/packer-plugin-alicloud/releases/tag/v1.0.5)
+* amazon@v1.1.6 - [CHANGELOG](https://github.com/hashicorp/packer-plugin-amazon/releases/tag/v1.1.6)
+* proxmox@v1.1.0 - [CHANGELOG](https://github.com/hashicorp/packer-plugin-proxmox/releases/tag/v1.1.0)
+* vsphere@v1.1.1 - [CHANGELOG](https://github.com/hashicorp/packer-plugin-vsphere/releases/tag/v1.1.1)
+* qemu@v1.0.8 - [CHANGELOG](https://github.com/hashicorp/packer-plugin-qemu/releases/tag/v1.0.8)
+
+### IMPROVEMENTS:
+* cmd/hcl2_upgrade: Generate variable block for all referenced user input
+ variables. [GH-12136](https://github.com/hashicorp/packer/pull/12136)
+* cmd/validate: Add support for the `-evaluate-datasources` flag to evaluate
+ the data sources from a template during validation time.
+ [GH-12106](https://github.com/hashicorp/packer/pull/12106)
+ [GH-12152](https://github.com/hashicorp/packer/pull/12152)
+* core/hcl2: Variable definition files containing undeclared variables within
+ an HCL2 template will no longer warn during build execution. Warnings will
+ be displayed to a user during template validation, which can be disabled by
+ passing the `-no-warn-undeclared-var` flag to the validate command.
+ [GH-12104](https://github.com/hashicorp/packer/pull/12104)
+ [GH-12109](https://github.com/hashicorp/packer/pull/12109)
+* core: Docker images have been updated to include the `xorriso` package for
+ supporting the creation of ISO files.[GH-12081](https://github.com/hashicorp/packer/pull/12081)
+* core: Split HCP Packer publishing components into a separate internal-only
+ module. [GH-11](https://github.com/hashicorp/packer/pull/11967)
+ [GH-12116](https://github.com/hashicorp/packer/pull/12116)
+
+### BUG FIXES:
+* cmd/init: The init command will try to fallback to the next available version
+ for a plugin, if the most recent version is not available or has a missing
+ checksum file. This should prevent Packer from trying to install versions
+ that have a GitHub tag but no actual assets.
+ [GH-12103](https://github.com/hashicorp/packer/pull/12103)
+* cmd/plugins: The `plugins install` sub-command will try to fallback to the
+ next available version for a plugin, if the most recent version is not
+ available or has a missing checksum file. This should prevent Packer from
+ trying to install versions that have a GitHub tag but no actual assets.
+ [GH-12103](https://github.com/hashicorp/packer/pull/12103)
+* core: Bump Go version to 1.18.9 to address vulnerability GO-2022-1144, which
+ concerns the net/http and golang.org/x/net
+ packages.[GH-12153](https://github.com/hashicorp/packer/pull/12153)
+ [GH-12158](https://github.com/hashicorp/packer/pull/12158)
+* core: Fix the registration of deleted input artifacts in HCP Packer when
+ setting `keep_input_artifacts` to
+ false.[GH-11462](https://github.com/hashicorp/packer/pull/11967)
+* core: Using different template types when building a HCP Packer
+ image iteration will now trigger a runtime build error due to the
+ mixing of template types.
+ [GH-12132](https://github.com/hashicorp/packer/pull/12132)
+
+## 1.8.4 (October 28 2022)
+
+### NOTES:
+
+* Packer user documentation has been moved to the new HashiCorp developer
+ documentation portal. The main Packer site (https://www.packer.io) will
+ continue to be the home for Packer but all requests for general
+ documentation and binary downloads will be redirected to
+ https://developer.hashicorp.com/packer. Users are encouraged to visit the
+ developer documentation portal for access to all Packer related
+ documentation; including integrations with HCP Packer.
+
+* The Oracle builder and post-processor are no longer vendored with Packer
+ core. Users of the Oracle plugin should use `packer init` to install the
+ latest version of the plugin. See the [Oracle Plugin
+ Documentation](https://github.com/hashicorp/packer-plugin-oracle) for more
+ information. [GH-11983](https://github.com/hashicorp/packer/pull/11983)
+
+* HCP Packer environment variables: The behavior of some HCP Packer-specific
+ environment variables have changed slightly. Refer to [HCP Packer](https://developer.hashicorp.com/packer/docs/hcp)
+ in the Packer documentation for a full list of HCP Packer environment variables. [GH-12059](https://github.com/hashicorp/packer/pull/12059)
+ - For JSON templates, the `HCP_PACKER_REGISTRY` environment variable was
+ previously required to enable the HCP Packer integration. In this release,
+ the environment variable is now optional, and can be used for disabling the
+ publishing of metadata for any HCP Packer enabled configuration template.
+ - For HCL2 templates, the `HCP_PACKER_REGISTRY` environment variable can be used
+ to disable publishing to a HCP Packer registry even if the template defines a
+ `hcp_packer_registry` block. This can be useful for testing that a template
+ works as intended prior to pushing metadata to HCP Packer.
+ - The `HCP_PACKER_BUCKET_NAME` environment variable is now the only
+ requirement to push metadata to a HCP Packer registry, in both JSON
+ and HCL2 templates without a `hcp_packer_registry` block.
+
+### FEATURES:
+
+* provisioner/powershell: Add `use_pwsh` configuration argument to support pwsh
+ in powershell provisioner. [GH-11950](https://github.com/hashicorp/packer/pull/11950)
+
+### PLUGINS:
+
+* builder/oracle: Remove Oracle plugin from the list of vendored
+ plugins. [GH-11983](https://github.com/hashicorp/packer/pull/11983)
+
+### IMPROVEMENTS:
+
+* command/hcl2_upgrade: Has been updated to persist all possible template
+ engine options that were supported by the legacy JSON templates. While the
+ upgrade command copies the template engine options as is support for the
+ template options may not actually work with HCL2 templates; indicated by an
+ error similar to `fieldname type <no value> is invalid`. Before executing a
+ build with the upgraded template you are encouraged to run `packer validate`
+ against the template and fix any invalid `<no value>` references.
+ [GH-12068](https://github.com/hashicorp/packer/pull/12068)
+* core/hcl2: Packer will now report an error when executing a build with no
+ sources selected for execution.
+ [GH-12016](https://github.com/hashicorp/packer/pull/12016)
+* core/hcp: Configuration errors for HCP Packer enabled builds have been
+ consolidated into a single report to help users address all potential
+ issues before retrying their build.
+ [GH-12031](https://github.com/hashicorp/packer/pull/12031)
+* core/hcp: Named builds within a legacy JSON template are now published to a
+ HCP Packer registry using its full build name (e.g `happycloud.windows-srv-2019)`,
+ as opposed to just the build name field (e.g `"name"="windows-srv-2019"`).
+ Builders with no defined name will continue to publish build
+ metadate using the builder type as the build name (e.g `happycloud`).
+ [GH-12059](https://github.com/hashicorp/packer/pull/12059)
+* core:hcl2: When a variable is set in a variables definitions file (i.e
+ \*.pkrvars.hcl), but isn't defined with the template files (i.e
+ \*.pkr.hcl), the outputted error message will now include an example of
+ variable block that can be added to the build template to remedy the issue.
+ [GH-12020](https://github.com/hashicorp/packer/pull/12020)
+* core: Add ppc64le to binary releases for Linux.
+ [GH-11966](https://github.com/hashicorp/packer/pull/11966)
+* core: Bump github.com/hashicorp/packer-plugin-sdk from 0.3.1 to 0.3.2.
+ [GH-11981](https://github.com/hashicorp/packer/pull/11981)
+* core: Bump supported Go version to 1.18.
+ [GH-11927](https://github.com/hashicorp/packer/pull/11927)
+
+### BUG FIXES:
+* command/hcl2_upgrade: special case: Azure `shared_image_gallery` fix.
+ [GH-12087](https://github.com/hashicorp/packer/pull/12087)
+* core: Bump golang.org/x/sys to address CVE-2022-29526.
+ [GH-11953](https://github.com/hashicorp/packer/pull/11953)
+* core: Bump golang.org/x/text to v0.3.8.
+ [GH-12047](https://github.com/hashicorp/packer/pull/12047)
+* core: Update dependency to resolve GO-2022-0969.
+ [GH-12009](https://github.com/hashicorp/packer/pull/12009)
+
+## 1.8.3 (August 2, 2022)
+
+### NOTES:
+* There's been a change in the way the `ssh_timeout` and the
+ `ssh_handshake_attempts` configuration arguments work together. The
+ behaviour is unchanged if both or none are specified. However, if only one
+ of the two is set the other won't have a default value anymore and will be
+ ignored. See [Packer Plugin SDK change](https://github.com/hashicorp/packer-plugin-sdk/pull/116) for details
+
+* packer-plugin-digitalocean: The Digital Ocean Packer plugin has been handed over
+ to the Digital Ocean team. New releases for this plugin are available at
+ https://github.com/digitalocean/packer-plugin-digitalocean. This plugin is
+ still being bundled in the Packer binary but will be removed in a future
+ release. Existing references to the plugin will continue to work but
+ users are advised to update the required_plugins block to use the new
+ plugin source address.
+ [GH-11912](https://github.com/hashicorp/packer/pull/11912)
+```
+required_plugins {
+ digitalocean = {
+ source = "github.com/digitalocean/digitalocean"
+ version = ">=1.0.8"
+ }
+}
+```
+* packer-plugin-outscale: The Outscale Packer plugin managed by the Outscale
+ team, since Packer 1.7.9, has been removed from the Packer binary. Users are
+ advised to install the latest version of the plugin by running
+ `packer plugins install github.com/outscale/outscale`. [GH-11912](https://github.com/hashicorp/packer/pull/11912)
+
+* packer-plugin-scaleway: The Scaleway Packer plugin managed by the Scaleway
+ team, since Packer 1.7.7, has been removed from the Packer binary. Users are
+ advised to install the latest version of the plugin by running
+ `packer plugins install github.com/scaleway/scaleway`. [GH-11912](https://github.com/hashicorp/packer/pull/11912)
+
+### FEATURES:
+* Future Scaffolding: This release contains additional changes that allow
+ Packer core to validate that a newly built image is a direct child of a HCP
+ Packer registry source image. This feature is only available for HCP Packer
+ enabled builds using the `hcp_packer_image` and `hcp_packer_iteration` data
+ source for setting a builder's source image.
+ [GH-11861](https://github.com/hashicorp/packer/pull/11861)
+
+### PLUGINS:
+
+The following external plugins have been updated and pinned to address open
+ issues. Please see their respective changelogs for details on plugin
+ specific bug fixes and improvements.
+
+* amazon@v1.1.2 - [CHANGELOG](https://github.com/hashicorp/packer-plugin-amazon/releases/tag/v1.1.2)
+* ansible@v1.0.3 - [CHANGELOG](https://github.com/hashicorp/packer-plugin-ansible/releases/tag/v1.0.3)
+* azure@v1.3.0 - [CHANGELOG](https://github.com/hashicorp/packer-plugin-azure/releases/tag/v1.3.0)
+* docker@v1.0.7 - [CHANGELOG](https://github.com/hashicorp/packer-plugin-docker/releases/tag/v1.0.7)
+* googlecompute@v1.0.14 - [CHANGELOG](https://github.com/hashicorp/packer-plugin-googlecompute/releases/tag/v1.0.14)
+* lxc@v1.0.2 - [CHANGELOG](https://github.com/hashicorp/packer-plugin-lxc/releases/tag/v1.0.2)
+* triton@v1.0.2 - [CHANGELOG](https://github.com/hashicorp/packer-plugin-triton/releases/tag/v1.0.2)
+* vsphere@v1.0.7 - [CHANGELOG](https://github.com/hashicorp/packer-plugin-vsphere/releases/tag/v1.0.7)
+* yandex@v1.1.2 - [CHANGELOG](https://github.com/hashicorp/packer-plugin-yandex/releases/tag/v1.1.2)
+
+
+### IMPROVEMENTS:
+* Bump packer-plugin-sdk to v0.3.1 to fix inconsistencies between `ssh_timeout`
+ and `ssh_handshake_attempts` configuration arguments in the SSH
+ communicator. [GH-11909](https://github.com/hashicorp/packer/pull/11909)
+* core: During long running builds the HCP Packer registry will mark a build as
+ timed out if it has not posted an update after a certain number of minutes.
+ For HCP Packer enabled builds a status update will now be sent every 2
+ minutes to the registry to prevent long builds from being marked as timed
+ out. [GH-11846](https://github.com/hashicorp/packer/pull/11846)
+* data/hcp_packer_image: Add `component_type` configuration argument to
+ support specifying an exact build image when multiple images exist in the
+ same provider and region for a given HCP Packer bucket iteration.
+ [GH-11872](https://github.com/hashicorp/packer/pull/11872)
+* data/hcp_packer_image: Add support for `channel` as input argument to
+ retrieve an image from the associated iteration. If
+ using several images from a single iteration, you may prefer sourcing an
+ iteration first, and referencing it for subsequent uses, as every
+ `hcp_packer_image` with the channel set will generate a potentially
+ billable HCP Packer request but if several `hcp_packer_image`s use a
+ shared `hcp_packer_iteration` that will only generate one potentially
+ billable request.
+ [GH-11865](https://github.com/hashicorp/packer/pull/11865)
+
+
+
+### BUG FIXES
+
+* core/hcl2: Fix crash when parsing malformed provisioner override blocks.
+ [GH-11881](https://github.com/hashicorp/packer/pull/11881)
+* core/hcl2: Fix crash when running `packer validate` on templates containing
+ one or more HCP Packer data sources.
+ [GH-11883](https://github.com/hashicorp/packer/pull/11883)
+
+
+## 1.8.2 (June 21, 2022)
+
+### NOTES:
+* The Packer plugin SDK includes the latest version of the go-getter library,
+ which has been updated to address the vulnerabilities listed in
+ [HCSEC-2022-13](https://discuss.hashicorp.com/t/hcsec-2022-13-multiple-vulnerabilities-in-go-getter-library/39930).
+ The updated SDK contains changes that can
+ be breaking for some plugins as the updated go-getter settings in the SDK
+ prevent reading/writing through symlinks and to sub-directories that
+ require upward path traversal (e.g /tmp/.../etc/hosts). The updates also
+ includes a 30 minute maximum timeout for file downloading, which can be an
+ issue for very large or slow downloads if they exceed more than 30 minutes
+ to complete.
+
+### SECURITY:
+* Bump packer-plugin-sdk to v0.3.0 to address reported vulnerabilities within
+ the go-getter library.
+ [GH-11843](https://github.com/hashicorp/packer/pull/11843)
+* Bump plugins relying on go-getter for downloading remote files to address
+ reported vulnerabilities within the go-getter library. See [HCSEC-2022-13](https://discuss.hashicorp.com/t/hcsec-2022-13-multiple-vulnerabilities-in-go-getter-library/39930) for details.
+ [GH-11844](https://github.com/hashicorp/packer/pull/11844)
+
+### FEATURES:
+* Future Scaffolding: This release contains changes that allow Packer core to
+ validate that a newly built image is a direct child of a HCP Packer
+ registry source image. This feature is only available for HCP Packer
+ enabled builds using the `hcp_packer_image` data source for setting a
+ builder's source image.
+ [GH-11832](https://github.com/hashicorp/packer/pull/11832)
+
+### PLUGINS:
+
+External plugins have been pinned to the following versions. Please see their
+ respective changelogs for details on plugin specific bug fixes and
+ improvements.
+
+* azure@v1.1.0 - [CHANGELOG](https://github.com/hashicorp/packer-plugin-azure/releases/tag/v1.1.0)
+* hyperv@v1.0.4 - [CHANGELOG](https://github.com/hashicorp/packer-plugin-hyperv/releases/tag/v1.0.4)
+* parallels@v1.0.3 - [CHANGELOG](https://github.com/hashicorp/packer-plugin-parallels/releases/tag/v1.0.3)
+* proxmox@v1.0.8 - [CHANGELOG](https://github.com/hashicorp/packer-plugin-proxmox/releases/tag/v1.0.8)
+* qemu@v1.0.5 - [CHANGELOG](https://github.com/hashicorp/packer-plugin-qemu/releases/tag/v1.0.5)
+* vagrant@v1.0.3 - [CHANGELOG](https://github.com/hashicorp/packer-plugin-vagrant/releases/tag/v1.0.3)
+* virtualbox@v1.0.4 - [CHANGELOG](https://github.com/hashicorp/packer-plugin-virtualbox/releases/tag/v1.0.4)
+* vmware@v1.0.7 - [CHANGELOG](https://github.com/hashicorp/packer-plugin-vmware/releases/tag/v1.0.7)
+* vsphere@v1.0.5 - [CHANGELOG](https://github.com/hashicorp/packer-plugin-vsphere/releases/tag/v1.0.5)
+
+### IMPROVEMENTS:
+* Add `pause_after` configuration argument to Powershell provisioner.
+ [GH-11792](https://github.com/hashicorp/packer/pull/11792)
+* HCP Packer data sources will now fail for revoked iterations to prevent building non-compliant images.
+ [GH-11854](https://github.com/hashicorp/packer/pull/11854)
+
+### BUG FIXES:
+
+* Add missing support for the `env` configuration argument in remote shell
+ provisioners. [GH-11819](https://github.com/hashicorp/packer/pull/11819)
+* The preinst and postrm user scripts, including the service configuration
+ directives, have been removed from the Packer rpm installations packages,
+ as Packer does not require a service user in order to run.
+ [GH-11831](https://github.com/hashicorp/packer/pull/11831)
+
+## 1.8.1 (May 27, 2022)
+
+### NOTES:
+* All bundled plugins have been updated to their latest release to address any
+ open issues pertaining to the legacy SSH key algorithm fix made to the
+ Packer plugin SDK.
+ [GH-11761](https://github.com/hashicorp/packer/pull/11761)
+ [GH-11802](https://github.com/hashicorp/packer/pull/11802)
+* This release contains the latest golang.org/x/crypto/ssh module which
+ implements client authentication support for signature algorithms based on
+ SHA-2 for use with existing RSA keys. Previously, a client would fail to
+ authenticate with RSA keys to servers that reject signature algorithms
+ based on SHA-1.
+
+### FEATURES:
+* **New Datasource** HTTP data source retrieves information from a HTTP
+ endpoint to be used during Packer builds.
+ [GH-11658](https://github.com/hashicorp/packer/pull/11658)
+
+### PLUGINS:
+
+External plugins have been pinned to the following versions. Please see their
+ respective changelogs for details on plugin specific bug fixes and
+ improvements.
+
+* alicloud@v1.0.2 - [CHANGELOG](https://github.com/hashicorp/packer-plugin-alicloud/releases/tag/v1.0.2)
+* amazon@v1.1.0 - [CHANGELOG](https://github.com/hashicorp/packer-plugin-amazon/releases/tag/v1.1.0)
+* ansible@v1.0.2 - [CHANGELOG](https://github.com/hashicorp/packer-plugin-ansible/releases/tag/v1.0.2)
+* azure@v1.0.8 - [CHANGELOG](https://github.com/hashicorp/packer-plugin-azure/releases/tag/v1.0.8)
+* chef@v1.0.2 - [CHANGELOG](https://github.com/hashicorp/packer-plugin-chef/releases/tag/v1.0.2)
+* cloudstack@v1.0.1 - [CHANGELOG](https://github.com/hashicorp/packer-plugin-cloudstack/releases/tag/v1.0.1)
+* converge@v1.0.1 - [CHANGELOG](https://github.com/hashicorp/packer-plugin-converge/releases/tag/v1.0.1)
+* digitalocean@v1.0.3 - [CHANGELOG](https://github.com/hashicorp/packer-plugin-digitalocean/releases/tag/v1.0.3)
+* docker@v1.0.5 - [CHANGELOG](https://github.com/hashicorp/packer-plugin-docker/releases/tag/v1.0.5)
+* googlecompute@v1.0.13 - [CHANGELOG](https://github.com/hashicorp/packer-plugin-googlecompute/releases/tag/v1.0.13)
+* hcloud@v1.0.4 - [CHANGELOG](https://github.com/hashicorp/packer-plugin-hcloud/releases/tag/v1.0.4)
+* hyperone@v1.0.1 - [CHANGELOG](https://github.com/hashicorp/packer-plugin-hyperone/releases/tag/v1.0.1)
+* hyperv@v1.0.3 - [CHANGELOG](https://github.com/hashicorp/packer-plugin-hyperv/releases/tag/v1.0.3)
+* inspec@v1.0.0 - [CHANGELOG](https://github.com/hashicorp/packer-plugin-inspec/releases/tag/v1.0.0)
+* jdcloud@v1.0.1 - [CHANGELOG](https://github.com/hashicorp/packer-plugin-jdcloud/releases/tag/v1.0.1)
+* linode@v1.0.3 - [CHANGELOG](https://github.com/hashicorp/packer-plugin-linode/releases/tag/v1.0.3)
+* lxc@v1.0.1 - [CHANGELOG](https://github.com/hashicorp/packer-plugin-lxc/releases/tag/v1.0.1)
+* lxd@v1.0.1 - [CHANGELOG](https://github.com/hashicorp/packer-plugin-lxd/releases/tag/v1.0.1)
+* ncloud@v1.0.3 - [CHANGELOG](https://github.com/hashicorp/packer-plugin-ncloud/releases/tag/v1.0.3)
+* oneandone@v1.0.1 - [CHANGELOG](https://github.com/hashicorp/packer-plugin-oneandone/releases/tag/v1.0.1)
+* openstack@v1.0.1 - [CHANGELOG](https://github.com/hashicorp/packer-plugin-openstack/releases/tag/v1.0.1)
+* oracle@v1.0.2 - [CHANGELOG](https://github.com/hashicorp/packer-plugin-oracle/releases/tag/v1.0.2)
+* parallels@v1.0.2 - [CHANGELOG](https://github.com/hashicorp/packer-plugin-parallels/releases/tag/v1.0.2)
+* profitbricks@v1.0.2 - [CHANGELOG](https://github.com/hashicorp/packer-plugin-profitbricks/releases/tag/v1.0.2)
+* proxmox@v1.0.7 - [CHANGELOG](https://github.com/hashicorp/packer-plugin-proxmox/releases/tag/v1.0.7)
+* puppet@v1.0.1 - [CHANGELOG](https://github.com/hashicorp/packer-plugin-puppet/releases/tag/v1.0.1)
+* qemu@v1.0.4 - [CHANGELOG](https://github.com/hashicorp/packer-plugin-qemu/releases/tag/v1.0.4)
+* salt@v1.0.0 - [CHANGELOG](https://github.com/hashicorp/packer-plugin-salt/releases/tag/v1.0.0)
+* tencentcloud@v1.0.5 - [CHANGELOG](https://github.com/hashicorp/packer-plugin-tencentcloud/releases/tag/v1.0.5)
+* triton@v1.0.1 - [CHANGELOG](https://github.com/hashicorp/packer-plugin-triton/releases/tag/v1.0.1)
+* ucloud@v1.0.1 - [CHANGELOG](https://github.com/hashicorp/packer-plugin-ucloud/releases/tag/v1.0.1)
+* vagrant@v1.0.2 - [CHANGELOG](https://github.com/hashicorp/packer-plugin-vagrant/releases/tag/v1.0.2)
+* virtualbox@v1.0.3 - [CHANGELOG](https://github.com/hashicorp/packer-plugin-virtualbox/releases/tag/v1.0.3)
+* vmware@v1.0.5 - [CHANGELOG](https://github.com/hashicorp/packer-plugin-vmware/releases/tag/v1.0.5)
+* vsphere@v1.0.4 - [CHANGELOG](https://github.com/hashicorp/packer-plugin-vsphere/releases/tag/v1.0.4)
+* yandex@v1.1.1 - [CHANGELOG](https://github.com/hashicorp/packer-plugin-yandex/releases/tag/v1.1.1)
+
+### IMPROVEMENTS:
+* Bump hcp-sdk-go to latest version.
+ [GH-11763](https://github.com/hashicorp/packer/pull/11763)
+* Plugins installed via the `packer plugins install` command will now
+ automatically load for builds using HCL2 templates without a
+ required_plugins block.
+ [GH-11712](https://github.com/hashicorp/packer/pull/11712)
+* Plugins installed via the `packer plugins install` command will now
+ automatically load for builds using JSON templates.
+ [GH-11712](https://github.com/hashicorp/packer/pull/11712)
+
+### BUG FIXES:
+* Bump github.com/hashicorp/go-getter to fix the untarring of OVA files
+ regression. [GH-11675](https://github.com/hashicorp/packer/pull/11675)
+* Bump github.com/hashicorp/packer-plugin-sdk to address legacy SSH key
+ algorithms in SSH communicator.
+ [GH-11774](https://github.com/hashicorp/packer/pull/11774)
+ [GH-11754](https://github.com/hashicorp/packer/pull/11754)
+
+## 1.8.0 (March 4, 2022)
+
+### NOTES:
+* **Breaking Change**: Support for the following architectures `ppc64le, mips,
+ mips64, mipsle, mipsle64, s390x` have been removed from the Packer releases
+ page. Packer, along with the HashiCorp maintained Packer plugins, have been
+ updated to release binaries for the HashiCorp supported architectures arm,
+ arm64, 386, and amd64. A full list of supported platforms can be found
+ on the [Packer Downloads](https://www.packer.io/downloads) page.
+ [GH-11564](https://github.com/hashicorp/packer/pull/11564)
+ [GH-11601](https://github.com/hashicorp/packer/pull/11601)
+ [GH-11603](https://github.com/hashicorp/packer/pull/11603)
+
+* **Breaking Change**: The `packer-plugin-check`(github.com/hashicorp/packer/cmd/packer-plugins-check) has been
+ replaced by the [`packer-sdc plugin-check` command](https://github.com/hashicorp/packer- plugin sdk/tree/main/cmd/packer-sdc#packer-sdc).
+ Plugin maintainers who may be using the packer-plugin-check as part of their
+ release pipeline are encouraged to move to the packer-sdc command. As an
+ alternative, maintainers can continue to use the packer-plugin-check by
+ pinning the command to Packer 1.7.10.
+ [GH-11317](https://github.com/hashicorp/packer/pull/11317)
+
+### FEATURES
+* **New Command** `packer plugins` command and subcommands to manage external
+ plugins. [GH-11553](https://github.com/hashicorp/packer/pull/11553)
+ [GH-11625](https://github.com/hashicorp/packer/pull/11625)
+
+### IMPROVEMENTS
+* core: Add a `env` argument to provisioner blocks that allow for setting a
+ map of key/value pairs to inject prior to the execute_command. The env argument
+ is an alternative to using environment_vars for setting environment variables,
+ which has the added ability to read from Packer datasources. [GH-11569](https://github.com/hashicorp/packer/pull/11569)
+* core: Bump version of go-getter to allow for downloading ISOs with PGP signed
+ checksums. [GH-11495](https://github.com/hashicorp/packer/pull/11495)
+* core: Docker images are now available for all supported architectures that
+ the linux binaries are built for including arm, arm64, 386, and amd64
+ [GH-11564](https://github.com/hashicorp/packer/pull/11564)
+ [GH-11601](https://github.com/hashicorp/packer/pull/11601)
+ [GH-11603](https://github.com/hashicorp/packer/pull/11603)
+* core: Packer's Linux package service configs and pre/post install scripts are
+ now available under .release/linux.
+ [GH-11601](https://github.com/hashicorp/packer/pull/11601)
+ [GH-11603](https://github.com/hashicorp/packer/pull/11603)
+* core: Packer's Linux packages are now available for all supported Linux
+ architectures including arm, arm64, 386, and amd64
+ [GH-11564](https://github.com/hashicorp/packer/pull/11564)
+ [GH-11601](https://github.com/hashicorp/packer/pull/11601)
+ [GH-11603](https://github.com/hashicorp/packer/pull/11603)
+* core: The dockerfile that is used to build the packer docker image available
+ at hashicorp/packer now lives in the root of this repo. The README that
+ describes how to build the docker targets defined in the Dockerfile are
+ available under ./release/docker/README.md.
+ [GH-11564](https://github.com/hashicorp/packer/pull/11564)
+ [GH-11601](https://github.com/hashicorp/packer/pull/11601)
+ [GH-11603](https://github.com/hashicorp/packer/pull/11603)
+* core: The packer-plugin-check command has been removed. Plugin maintainers
+ should update their release configuration to use the `packer-sdc plugin-
+ check` command. [GH-11317](https://github.com/hashicorp/packer/pull/11317)
+
+
+### BUG FIXES
+* core/hcl2: Fixes an issue preventing builds from pausing between provisioners when
+ the `--debug` argument has been passed.
+ [GH-11537](https://github.com/hashicorp/packer/pull/11537)
+* core/hcl2: Fixes a data loss issue when merging an empty-object map to a non-
+ empty map variable.
+ [GH-11566](https://github.com/hashicorp/packer/pull/11566)
+* core/hcl2: Fixes a regression where references to locals via the lookup
+ function were failing to find defined keys.
+ [GH-11566](https://github.com/hashicorp/packer/pull/11566)
+* core/hcl2: Fixes an issue where HCP Packer build labels from the first
+ completed build image were being copied to all images within the same
+ build. [GH-11574](https://github.com/hashicorp/packer/pull/11574)
+ [GH-11584](https://github.com/hashicorp/packer/pull/11584)
+* core: HCP Packer datasources will no longer fail for iterations with
+ scheduled revocations.
+ [GH-11619](https://github.com/hashicorp/packer/pull/11619)
+* core: Packer darwin builds now use macOS system DNS resolver for resolving
+ hostnames. [GH-9710](https://github.com/hashicorp/packer/issues/9710)
+ [GH-11564](https://github.com/hashicorp/packer/pull/11564)
+
+## 1.7.10 (February 02, 2022)
+
+### NOTES:
+
+This patch release fixes a crash in m1 caused by the psutils dep,
+ https://github.com/hashicorp/packer/pull/11546, originally reported by the
+ HomeBrew team here https://github.com/hashicorp/packer/issues/11512
+
+### IMPROVEMENTS
+* Print all locals errors when there is a circular error.
+ [GH-11527](https://github.com/hashicorp/packer/pull/11527
+
+### BUG FIXES
+* Prevent duplicate local block creation.
+ [GH-11534](https://github.com/hashicorp/packer/pull/11534)
+* Update psutils dep to avoid crash on Arm64 Macs.
+ [GH-11546](https://github.com/hashicorp/packer/pull/11546)
+
+## 1.7.9 (January 19, 2022)
+### NOTES:
+
+* HCP Packer compatible plugins will contain a "HCP Packer Ready" badge at the
+ top of on their documentation page.
+ [GH-11456](https://github.com/hashicorp/packer/pull/11456)
+* Packer core [documentation](https://packer.io/docs) now supports versioning
+ on Packer.io. Users can select documentation for the version of Packer they
+ are using. [GH-11434](https://github.com/hashicorp/packer/pull/11434)
+* The `hcp_packer_registry.labels` argument has been deprecated in favor of the
+ new `bucket_labels` argument to support custom user generated bucket
+ labels. [GH-11401](https://github.com/hashicorp/packer/pull/11401)
+* The code of the Outscale builder was handed over to the outscale org
+ [GH-11428](https://github.com/hashicorp/packer/pull/11428)
+* Version information for external plugins has been added as a badge to the
+ plugin documentation.
+ [GH-11457](https://github.com/hashicorp/packer/pull/11457)
+* The following unmaintained external provisioner plugins have been archived: chef,
+ converge, inspec, salt-masterless, puppet. More
+ information on what this deprecation means for users can be found on the
+ blog post - [Plans to Archive Unmaintained Provisioner
+ Plugins](https://www.hashicorp.com/blog/plans-to-archive-unmaintained-packer-provisioner-plugins)
+
+
+### PLUGINS:
+
+External plugins have been pinned to the following versions. Please see
+ their respective changelogs for details on plugin specific bug fixes and
+ improvements.
+
+* alicloud@v1.0.1 - [CHANGELOG](https://github.com/hashicorp/packer-plugin-alicloud/releases/tag/v1.0.1)
+* amazon@v1.0.6 - [CHANGELOG](https://github.com/hashicorp/packer-plugin-amazon/releases/tag/v1.0.6)
+* ansible@v1.0.1 - [CHANGELOG](https://github.com/hashicorp/packer-plugin-ansible/releases/tag/v1.0.1)
+* azure@v1.0.4 - [CHANGELOG](https://github.com/hashicorp/packer-plugin-azure/releases/tag/v1.0.4)
+* chef@v1.0.2 - [CHANGELOG](https://github.com/hashicorp/packer-plugin-chef/releases/tag/v1.0.2)
+* cloudstack@v1.0.0 - [CHANGELOG](https://github.com/hashicorp/packer-plugin-cloudstack/releases/tag/v1.0.0)
+* converge@v1.0.1 - [CHANGELOG](https://github.com/hashicorp/packer-plugin-converge/releases/tag/v1.0.1)
+* digitalocean@v1.0.1 - [CHANGELOG](https://github.com/hashicorp/packer-plugin-digitalocean/releases/tag/v1.0.1)
+* docker@v1.0.3 - [CHANGELOG](https://github.com/hashicorp/packer-plugin-docker/releases/tag/v1.0.3)
+* googlecompute@v1.0.9 - [CHANGELOG](https://github.com/hashicorp/packer-plugin-googlecompute/releases/tag/v1.0.9)
+* hcloud@v1.0.2 - [CHANGELOG](https://github.com/hashicorp/packer-plugin-hcloud/releases/tag/v1.0.2)
+* hyperone@v1.0.0 - [CHANGELOG](https://github.com/hashicorp/packer-plugin-hyperone/releases/tag/v1.0.0)
+* hyperv@v1.0.1 - [CHANGELOG](https://github.com/hashicorp/packer-plugin-hyperv/releases/tag/v1.0.1)
+* inspec@v1.0.0 - [CHANGELOG](https://github.com/hashicorp/packer-plugin-inspec/releases/tag/v1.0.0)
+* jdcloud@v1.0.0 - [CHANGELOG](https://github.com/hashicorp/packer-plugin-jdcloud/releases/tag/v1.0.0)
+* linode@v1.0.1 - [CHANGELOG](https://github.com/hashicorp/packer-plugin-linode/releases/tag/v1.0.1)
+* lxc@v1.0.0 - [CHANGELOG](https://github.com/hashicorp/packer-plugin-lxc/releases/tag/v1.0.0)
+* lxd@v1.0.0 - [CHANGELOG](https://github.com/hashicorp/packer-plugin-lxd/releases/tag/v1.0.0)
+* ncloud@v1.0.1 - [CHANGELOG](https://github.com/hashicorp/packer-plugin-ncloud/releases/tag/v1.0.1)
+* oneandone@v1.0.0 - [CHANGELOG](https://github.com/hashicorp/packer-plugin-oneandone/releases/tag/v1.0.0)
+* openstack@v1.0.0 - [CHANGELOG](https://github.com/hashicorp/packer-plugin-openstack/releases/tag/v1.0.0)
+* oracle@v1.0.1 - [CHANGELOG](https://github.com/hashicorp/packer-plugin-oracle/releases/tag/v1.0.1)
+* outscale@v1.0.2 - [CHANGELOG](https://github.com/hashicorp/packer-plugin-outscale/releases/tag/v1.0.2)
+* parallels@v1.0.0 - [CHANGELOG](https://github.com/hashicorp/packer-plugin-parallels/releases/tag/v1.0.0)
+* profitbricks@v1.0.1 - [CHANGELOG](https://github.com/hashicorp/packer-plugin-profitbricks/releases/tag/v1.0.1)
+* proxmox@v1.0.4 - [CHANGELOG](https://github.com/hashicorp/packer-plugin-proxmox/releases/tag/v1.0.4)
+* puppet@v1.0.1 - [CHANGELOG](https://github.com/hashicorp/packer-plugin-puppet/releases/tag/v1.0.1)
+* qemu@v1.0.1 - [CHANGELOG](https://github.com/hashicorp/packer-plugin-qemu/releases/tag/v1.0.1)
+* salt@v1.0.0 - [CHANGELOG](https://github.com/hashicorp/packer-plugin-salt/releases/tag/v1.0.0)
+* tencentcloud@v1.0.3 - [CHANGELOG](https://github.com/hashicorp/packer-plugin-tencentcloud/releases/tag/v1.0.3)
+* triton@v1.0.0 - [CHANGELOG](https://github.com/hashicorp/packer-plugin-triton/releases/tag/v1.0.0)
+* ucloud@v1.0.0 - [CHANGELOG](https://github.com/hashicorp/packer-plugin-ucloud/releases/tag/v1.0.0)
+* vagrant@v1.0.1 - [CHANGELOG](https://github.com/hashicorp/packer-plugin-vagrant/releases/tag/v1.0.1)
+* virtualbox@v1.0.1 - [CHANGELOG](https://github.com/hashicorp/packer-plugin-virtualbox/releases/tag/v1.0.1)
+* vmware@v1.0.5 - [CHANGELOG](https://github.com/hashicorp/packer-plugin-vmware/releases/tag/v1.0.5)
+* vsphere@v1.0.2 - [CHANGELOG](https://github.com/hashicorp/packer-plugin-vsphere/releases/tag/v1.0.2)
+* yandex@v1.0.3 - [CHANGELOG](https://github.com/hashicorp/packer-plugin-yandex/releases/tag/v1.0.3)
+* scaleway@v1.0.4 - [CHANGELOG](https://github.com/scaleway/packer-plugin-scaleway/releases/tag/v1.0.4)
+
+### IMPROVEMENTS:
+
+* core/hcl2: Add `bucket_labels` argument to the `hcp_packer_registry` block to
+ support custom user generated bucket labels.
+ [GH-11401](https://github.com/hashicorp/packer/pull/11401)
+* core/hcl2: Add `build_labels` argument to the `hcp_packer_registry` block to
+ support custom user generated build labels.
+ [GH-11401](https://github.com/hashicorp/packer/pull/11401)
+* core/hcl2: Allow for the use of variables and locals within a `build` block.
+ [GH-11421](https://github.com/hashicorp/packer/pull/11421)
+* core/hcl2: Allow for the use of variables and locals within a
+ `hcp_packer_registry` block.
+ [GH-11421](https://github.com/hashicorp/packer/pull/11421)
+* core/website: Add HCP Packer Ready badge to supported plugins.
+ [GH-11456](https://github.com/hashicorp/packer/pull/11456)
+* core/website: Add Packer version selection toggle to Packer core
+ documentation. [GH-11434](https://github.com/hashicorp/packer/pull/11434)
+* core/website: Add version information to external plugin documentation.
+ [GH-11456](https://github.com/hashicorp/packer/pull/11456)
+* core/website: Extract external plugins documentation from `packer.io/docs/`
+ into `packer.io/plugins`.
+ [GH-11464](https://github.com/hashicorp/packer/pull/11464)
+* core: Add Packer user agent information to HCP Packer client requests.
+ [GH-11455](https://github.com/hashicorp/packer/pull/11455)
+* core: Bump github.com/hashicorp/packer-plugin-sdk from 0.2.9 to 0.2.11 to
+ prevent HCP Packer builds from failing when no SourceImageID is
+ provided. [GH-11459](https://github.com/hashicorp/packer/pull/11459)
+* core: Bump to latest preview version of hashicorp/hcp-sdk-go to prevent HCP
+ Packer builds from trying to update a revoked iteration.
+ [GH-11492](https://github.com/hashicorp/packer/pull/11492)
+* provisioner/powwershell: Tiny tweaks and fixes for the PowerShell
+ provisioner. [GH-11410](https://github.com/hashicorp/packer/pull/11410)
+
+### BUG FIXES:
+
+* core/hcl2: Allow the use of `build.name` for naming provisioners and
+ post-processors. [GH-11432](https://github.com/hashicorp/packer/pull/11432)
+* core/hcl2: Fix crash when a provisioner `timeout` argument is improperly
+ formatted. [GH-11382](https://github.com/hashicorp/packer/pull/11382)
+* core/hcl2: HCP Packer builds containing metadata not expected by Packer core
+ will no longer fail the build.
+ [GH-11458](https://github.com/hashicorp/packer/pull/11458)
+* provisioner/file: File provisioner will now perform a noop when no source
+ file content is specified; previously missing content resulted in a hard
+ fail. [GH-11349](https://github.com/hashicorp/packer/pull/11349)
+
+
+## 1.7.8 (October 27, 2021)
+
+### BUG FIXES
+* builder/amazon: Bump plugin to latest version to address a variable
+ interpolation issue for builder `run_tags`. [GH-11360](https://github.com/hashicorp/packer/pull/11360)
+
+## 1.7.7 (October 19, 2021)
+
+### NOTES:
+
+* The code of the Scaleway builder was handed over to the scaleway org
+ [GH-11298](https://github.com/hashicorp/packer/pull/11298)
+ [GH-11296](https://github.com/hashicorp/packer/pull/11296)
+
+### IMPROVEMENTS:
+* Improved support and user experience for HCP Packer registry.
+ [GH-11304](https://github.com/hashicorp/packer/pull/11304)
+ [GH-11315](https://github.com/hashicorp/packer/pull/11315)
+ [GH-11320](https://github.com/hashicorp/packer/pull/11320)
+ [GH-11319](https://github.com/hashicorp/packer/pull/11319)
+
+* core: Allow to use build variables in a post processor.
+ [GH-11323](https://github.com/hashicorp/packer/pull/11323)
+* core: Allow use in top level source variables in a build.source block.
+ [GH-11318](https://github.com/hashicorp/packer/pull/11318)
+* core: Show successful message upon successful packer validate.
+ [GH-11337](https://github.com/hashicorp/packer/pull/11337)
+* packer init: better error handling.
+ [GH-11330](https://github.com/hashicorp/packer/pull/11330)
+
+## 1.7.6 (September 28, 2021)
+
+### BUG FIXES:
+* core: Update Go module dependencies to fix an issue preventing Go 1.16 users
+ from installing the packer-plugins-check command via go install. [GH-11282]
+
+## 1.7.5 (September 14, 2021)
+
+### NOTES:
+The Exoscale builder and post-processor are no longer vendored with Packer
+ core, users of the Exoscale plugin should use `packer init` to install the
+ latest version of the plugin. See the [Exoscale Plugin
+ Documentation](https://github.com/exoscale/packer-plugin-exoscale#exoscale-packer-plugin) for more information. [GH-11237]
+
+### FEATURES:
+* **Future Scaffolding** This release contains no-op refactors in preparation
+ for connecting Packer to the HCP Packer Registry.
+
+### IMPROVEMENTS:
+* core: Upgrade to Go 1.17. [GH-11237]
+* hcl2_upgrade: support strftime function. [GH-11220]
+* provisioner/file: add option to set content + tests. [GH-11209]
+* provisioner/inspec: Remove inspec provisioner from Packer core. [GH-11230]
+* provisioner/salt-masterless: Remove salt-masterless provisioner from Packer
+ core to github.com/hashicorp/packer-plugin-salt/provisioner/salt-
+ masterless. [GH-11229]
+
+### BUG FIXES:
+* builder/azure: Bump plugin to latest version to address a vulnerable
+ dependency in azure-sdk-for-go. [GH-11162]
+* builder/googlecompute: Bump plugin to latest version to fix an issue when
+ building an instance via an IAP tunnel. [GH-11235]
+* builder/ncloud: Bump ncloud dependency to fix dependency that got deleted
+ from github [GH-11224]
+* core: Fix `{{packer_version}}` interpolation regression for HCL and JSON
+ templates. [GH-11200]
+* hcl2_upgrade: Fix panic when file does not exist. [GH-11206]
+* hcl2_upgrade: special case: vsphere fix. [GH-11216]
+
+## 1.7.4 (July 20, 2021)
+
+### BUG FIXES:
+
+* builder/outscale: Update Outscale multi-component plugin to fix `go build`
+ failures due to missing Go module dependencies. [GH-11147]
+
+## 1.7.3 (June 15, 2021)
+
+### IMPROVEMENTS:
+
+We've extracted a majority of HashiCorp-maintained and community plugins from the Packer Core repository. They now live in their own multi-component plugin repositories. This is not a breaking change as we are enabling backwards compatibility in this release by vendoring components back into Packer.
+However, we encourage users to begin using `packer init` to download and install plugins to get the latest updates to each plugin, and to prepare for Packer v2.0 when we will stop vendoring the above plugins into the main Packer binary.
+
+The following repositories have been created, and their components have been deleted from the "github.com/hashicorp/packer" repository.
+
+* "github.com/hashicorp/packer-plugin-alicloud" [GH-10932]
+* "github.com/hashicorp/packer-plugin-amazon" [GH-10800]
+* "github.com/hashicorp/packer-plugin-ansible" [GH-10912]
+* "github.com/hashicorp/packer-plugin-azure" [GH-10979]
+* "github.com/hashicorp/packer-plugin-chef" [GH-10921]
+* "github.com/hashicorp/packer-plugin-cloudstack" [GH-10934]
+* "github.com/hashicorp/packer-plugin-converge" [GH-10956]
+* "github.com/hashicorp/packer-plugin-digitalocean" [GH-10961]
+* "github.com/hashicorp/packer-plugin-docker" [GH-10695]
+* "github.com/hashicorp/packer-plugin-googlecompute" [GH-10890]
+* "github.com/hashicorp/packer-plugin-hcloud" [GH-10966]
+* "github.com/hashicorp/packer-plugin-hyperone" [GH-10949]
+* "github.com/hashicorp/packer-plugin-hyperv" [GH-10949]
+* "github.com/hashicorp/packer-plugin-inspec"
+* "github.com/hashicorp/packer-plugin-ionos-cloud"
+* "github.com/hashicorp/packer-plugin-jdcloud" [GH-10946]
+* "github.com/hashicorp/packer-plugin-linode" [GH-10947]
+* "github.com/hashicorp/packer-plugin-lxc" [GH-10965]
+* "github.com/hashicorp/packer-plugin-lxd" [GH-10965]
+* "github.com/hashicorp/packer-plugin-ncloud" [GH-10937]
+* "github.com/hashicorp/packer-plugin-openstack" [GH-10933]
+* "github.com/hashicorp/packer-plugin-oracle" [GH-10962]
+* "github.com/hashicorp/packer-plugin-outscale" [GH-10941]
+* "github.com/hashicorp/packer-plugin-parallels" [GH-10936]
+* "github.com/hashicorp/packer-plugin-profitbricks" [GH-11084]
+* "github.com/hashicorp/packer-plugin-proxmox" [GH-10930]
+* "github.com/hashicorp/packer-plugin-puppet" [GH-10943]
+* "github.com/hashicorp/packer-plugin-qemu" [GH-10929]
+* "github.com/hashicorp/packer-plugin-salt"
+* "github.com/hashicorp/packer-plugin-scaleway" [GH-10939]
+* "github.com/hashicorp/packer-plugin-tencentcloud" [GH-10967]
+* "github.com/hashicorp/packer-plugin-triton" [GH-10963]
+* "github.com/hashicorp/packer-plugin-ucloud" [GH-10953]
+* "github.com/hashicorp/packer-plugin-vagrant" [GH-10960]
+* "github.com/hashicorp/packer-plugin-virtualbox" [GH-10910]
+* "github.com/hashicorp/packer-plugin-vmware" [GH-10920]
+* "github.com/hashicorp/packer-plugin-vsphere" [GH-10896]
+* "github.com/hashicorp/packer-plugin-yandex" [GH-10970]
+
+The following components will not be removed from the main packer binary:
+
+* `null` builder
+* `file` builder
+* `breakpoint` provisioner
+
+* `file` provisioner
+* `powershell` provisioner
+* `shell` provisioner
+* `shell-local` provisioner
+* `sleep` provisioner
+* `windows-restart` provisioner
+* `windows-shell` provisioner
+
+* `artifice` post-processor
+* `checksum` post-processor
+* `compress` post-processor
+* `manifest` post-processor
+* `shell-local` post-processor
+
+### Bug Fixes:
+* builder/azure: Add `keep_os_disk` parameter to control OS disk deletion
+ [GH-10045]
+* builder/azure: Stop SIG timout from being overridden by PollingDuration
+ [GH-10816]
+* builder/azure: Support shared image gallery storage account type [GH-10863]
+* builder/proxmox: Proxmox builder use ipv4 address instead of always ipv6.
+ [GH-10858]
+* core/hcl2_upgrade: Allow hcl2_upgrade continue with unknown builders.
+ [GH-11049]
+* core/hcl2_upgrade: Improve regex to fix escaping on split function.
+ [GH-11083]
+* core/hcl: Fix Invalid provisioner pause_before panic [GH-10978]
+* core: HCL "index" function now actually returns the index of the element
+ [GH-11008]
+* core: Implemented DEFAULT_NAME handling for datasource plugins [GH-11026]
+
+### Enhancements:
+
+* builder/azure: Added custom nicname and osdiskname [GH-10938]
+* builder/azure: Add support for shared image gallery storage account type
+ [GH-10863]
+* builder/digitalocean: support ecdsa, ed25519, dsa temporary key types.
+ [GH-10856]
+* builder/ncloud: Support ncloud vpc version [GH-10870]
+* core/fmt: When reading from stdin `packer fmt` will output the contents of
+ the formatted file even if the input was already formatted. [GH-11047]
+* core/hcl: HCL variables are now supported within the `name`, `only`,
+ `except`, and `keep_input_artifact` fields for post-processor blocks.
+ [GH-11094]
+* core/hcl: Running `packer build` with an `-only` or `-exclude` flag will now
+ inform the user if no match was found. [GH-11050]
+* post-processor/compress: Add bzip2 support to post-processor [GH-10867]
+* post-processor/googlecompute-import: Add Image Storage Locations field
+ [GH-10864]
+* Removed the golang "vendor" directory in favor of go modules. This should not
+ affect end users. [GH-10916]
+
+## 1.7.2 (April 05, 2021)
+
+### IMPROVEMENTS:
+
+* builder/alicloud: Add `ramrole` configuration to ECS instance. [GH-10845]
+
+### BUG FIXES:
+
+* builder/proxmox: Update Proxmox Go API to ensure only the first non-loopback
+ IPv4 address gets returned. [GH-10858]
+* builder/vsphere: Fix primary disk resize on clone. [GH-10848]
+* core: Fix bug where call to "packer version" sent output to stderr instead of
+ stdout. [GH-10850]
+
+## 1.7.1 (March 31, 2021)
+
+### NOTES:
+
+* builder/amazon: Has been vendored in this release and will no longer be
+ updated with Packer core. In Packer v1.8.0 the plugin will be removed
+ entirely. The `amazon` components will continue to work as expected until
+ then, but for the latest offerings of the Amazon plugin, users are
+ encourage to use the `packer init` command to install the latest release
+ version. For more details see [Installing Packer
+ Plugins](https://www.packer.io/docs/plugins#installing-plugins)
+* builder/docker: Has been vendored in this release and will no longer be
+ updated with Packer core. In Packer v1.8.0 the plugin will be removed
+ entirely. The `docker` builder will continue to work as expected until
+ then, but for the latest offerings of the Docker plugin, users are
+ encourage to use the `packer init` command to install the latest release
+ version. For more details see [Installing Packer
+ Plugins](https://www.packer.io/docs/plugins#installing-plugins)
+* darwin/arm64: Packer now includes the darwin/arm64 binary to its releases to
+ supports the new OSX M1. [GH-10804]
+* post-processor/docker-\*: Have been vendored in this release and will no
+ longer be updated with Packer core. In Packer v1.8.0 the plugin will be
+ removed entirely. The `docker` builder will continue to work as expected
+ until then, but for the latest offerings of the Docker plugin, users are
+ encourage to use the `packer init` command to install the latest release
+ version. For more details see [Installing Packer
+ Plugins](https://www.packer.io/docs/plugins#installing-plugins)
+* post-processor/exoscale-import: Has been vendored in this release and will no
+ longer be updated with Packer core. In Packer v1.8.0 the plugin will be
+ removed entirely. The `exoscale-import` post-processor will continue to
+ work as expected until then, but for the latest offerings of the Exoscale
+ plugin, users are encourage to use the `packer init` command to install the
+ latest release version. For more details see [Exoscale Plugin
+ Repostiroy](https://github.com/exoscale/packer-plugin-exoscale). [GH-10709]
+
+### IMPROVEMENTS
+* builder/amazon: allow creation of ebs snapshots without volumes. [GH-9591]
+* builder/amazon: Fix issue for multi-region AMI build that fail when
+ encrypting with KMS and sharing across accounts. [GH-10754]
+* builder/azure: Add client_cert_token_timeout option. [GH-10528]
+* builder/google: Make Windows password timeout configurable. [GH-10727]
+* builder/google: Update public GCP image project as gce-uefi-images are
+ deprecated. [GH-10724]
+* builder/oracle-oci: Update Oracle Go SDK to add support for OCI flexible
+ shapes. [GH-10833]
+* builder/proxmox: Allow using API tokens for Proxmox authentication.
+ [GH-10797]
+* builder/qemu: Added firmware option. [GH-10683]
+* builder/scaleway: add support for timeout in shutdown step. [GH-10503]
+* builder/vagrant: Fix logging to be clearer when Vagrant builder overrides
+ values retrieved from vagrant's ssh_config call. [GH-10743]
+* builder/virtualbox: Added ISO builder option to create additional disks.
+ [GH-10674]
+* builder/virtualbox: Add options for nested virtualisation and RTC time base.
+ [GH-10736]
+* builder/virtualbox: Add template options for chipset, firmware, nic, graphics
+ controller, and audio controller. [GH-10671]
+* builder/virtualbox: Support for "virtio" storage and ISO drive. [GH-10632]
+* builder/vmware: Added "attach_snapshot" parameter to vmware vmx builder.
+ [GH-10651]
+* command/fmt: Adding recursive flag to formatter to format subdirectories.
+ [GH-10457]
+* core/hcl2: Add legacy_isotime function. [GH-10780]
+* core/hcl2: Add support for generating `dynamic` blocks within a `build`
+ block. [GH-10825]
+* core/hcl2: Add templatefile function. [GH-10776]
+* core/hcl2_upgrade: hcl2_upgrade command can now upgrade json var-files.
+ [GH-10676]
+* core/init: Add implicit required_plugin blocks feature. [GH-10732]
+* core: Add http_content option to serve variables from HTTP at preseed.
+ [GH-10801]
+* core: Change template parsing error to include warning about file extensions.
+ [GH-10652]
+* core: Update to gopsutil v3.21.1 to allow builds to work for darwin arm64.
+ [GH-10697]
+* provisioner/inspec: Allow non-zero exit codes for inspec provisioner.
+ [GH-10723]
+
+### BUG FIXES
+* buider/azure: Update builder to ensure a proper clean up Azure temporary
+ managed Os disks. [GH-10713]
+* builder/amazon: Update amazon SDK to fix an SSO login issue. [GH-10668]
+* builder/azure: Don't overwrite subscription id if unset. [GH-10659]
+* builder/azure: Set default for the parameter client_cert_token_timeout
+ [GH-10783]
+* builder/google: Add new configuration field `windows_password_timeout` to
+ allow user to set configurable timeouts. [GH-10727]
+* builder/hyperv: Make Packer respect winrm_host flag in winrm connect func.
+ [GH-10748]
+* builder/openstack: Make Packer respect winrm_host flag in winrm connect func.
+ [GH-10748]
+* builder/oracle-oci: Update Oracle Go SDK to fix issue with reading key file.
+ [GH-10560] [GH-10774]
+* builder/outscale: Fix omi_description that was ignored in Osc builder
+ [GH-10792]
+* builder/parallels: Make Packer respect winrm_host flag in winrm connect func.
+ [GH-10748]
+* builder/proxmox: Fixes issue when using `additional_iso_files` in HCL enabled
+ templates. [GH-10772]
+* builder/qemu: Make Packer respect winrm_host flag in winrm connect func.
+ [GH-10748]
+* builder/virtualbox: Make Packer respect winrm_host flag in winrm connect
+ func. [GH-10748]
+* builder/vmware: Added a fallback file check when trying to determine the
+ network-mapping configuration. [GH-10543]
+* builder/vsphere: Fix invalid device configuration issue when creating a
+ vm with multiple disk on the same controller. [GH-10844]
+* builder/vsphere: Fix issue where boot command would fail the build do to a
+ key typing error. This change will now retry to type the key on error
+ before giving up. [GH-10541]
+* core/hcl2_upgrade: Check for nil config map when provisioner/post-processor
+ doesn't have config. [GH-10730]
+* core/hcl2_upgrade: Fix escaped quotes in template functions [GH-10794]
+* core/hcl2_upgrade: Make hcl2_upgrade command correctly translate
+ pause_before. [GH-10654]
+* core/hcl2_upgrade: Make json variables using template engines get stored as
+ locals so they can be properly interpolated. [GH-10685]
+* core/init: Fixes issue where `packer init` was failing to install valid
+ plugins containing a 'v' within its name. [GH-10760]
+* core: Packer will now show a proper error message when failing to load the
+ contents of PACKER_CONFIG. [GH-10766]
+* core: Pin Packer to Golang 1.16 to fix code generation issues. [GH-10702]
+* core: Templates previously could not interpolate the environment variable
+ PACKER_LOG_PATH. [GH-10660]
+* post-processor/vagrant-cloud: Override direct upload based on box size
+ [GH-10820]
+* provisioner/chef-solo: HCL2 templates can support the json_string option.
+ [GH-10655]
+* provisioner/inspec: Add new configuration field `valid_exit_codes` to allow
+ for non-zero exit codes. [GH-10723]
+* provisioner/salt-masterless: Update urls for the bootstrap scripts used by
+ salt-masterless provide. [GH-10755]
+
+## 1.7.0 (February 17, 2021)
+
+### FEATURES
+* **New Command** (HCL only) `packer init` command will download plugins defined
+ in a new `required_plugins` block [GH-10304] [GH-10633].
+* **New Plugin Type** Data sources can be implemented (blog post forthcoming).
+ [GH-10440]
+* **New Plugin** Aws Secrets Manager data source [GH-10505] [GH-10467]
+
+### BACKWARDS INCOMPATIBILITIES
+* core: The API that the Packer core uses to communicate with community plugins
+ has changed; maintainers of community plugins will need to upgrade their
+ plugins in order to make them compatible with v1.7.0. An upgrade guide will
+ be available on our guides page https://www.packer.io/guides.
+
+### IMPROVEMENTS
+* builder/amazon: Add `skip_create_ami` option for testing and situations where
+ artifact is not the ami. [GH-10531]
+* builder/amazon: Add IMDSv2 support for AWS EBS builder. [GH-10546]
+* builder/amazon: Add resource tags in the launch template used to request spot
+ instances. [GH-10456]
+* builder/openstack: Add `skip_create_image` option for testing and situations
+ where artifact is not the image. [GH-10496]
+* builder/oracle-oci: Add retry strategies to oci calls [GH-10591]
+* core/fmt: The `packer fmt` can now read from stdin. [GH-10500]
+* core/hcl: Add regex and regexall hcl2 template functions. [GH-10601]
+* core/hcl: Templates now support "sensitive" locals. [GH-10509]
+* core/hcl: Templates now support error-cleanup-provisioner. [GH-10604]
+* hcl2_upgrade: Command now comes with a flag so you can control whether output
+ templates are annotated with helpful comments. [GH-10619]
+* hcl2_upgrade: Command now gracefully handles options with template engine
+ interpolations. [GH-10625]
+* hcl2_upgrade: Command will convert amazon filters to use the ami data source.
+ [GH-10491]
+
+### BUG FIXES
+* amazon/ebssurrogate: Apply snapshot tags at same time as when taking
+ snapshot. [GH-10150]
+* builder/amazon: Fix bug where validation fails if optional iops value is
+ unset. [GH-10518]
+* builder/amazon: Wrap API call to get filtered image in a retry. [GH-10610]
+* builder/bsusurrogate: override bsu when omi root device is set. [GH-10490]
+* builder/google: Fix bug where Packer would fail when run by users who do not
+ have permission to access the metadata, even though the metadata is not
+ necessary to the run. [GH-10458]
+* builder/profitbricks: Profitbricks builder could not connect using SSH
+ communicator. [GH-10549]
+* builder/proxmox: Ensure ISOs in additional_iso_files are mounted during VM
+ creation. [GH-10586]
+* builder/proxmox: Improve cloud init error logging for proxmox builder.
+ [GH-10499]
+* builder/qemu: Fix bug where vnc_min_port set to value greater then 5900 could
+ prevent Packer from connecting to QEMU. [GH-10450] [GH-10451]
+* builder/qemu: Fix regression with cd indexing when disk_interface is `ide`.
+ [GH-10519]
+* builder/vmware-esx: Skip credential validation, which requires ovftool to be
+ installed, if we are not exporting an image. [GH-10520]
+* builder/yandex: Fix cloud-init config for ubuntu 20.04. [GH-10522]
+* builder/yandex: Fix incorrect access to `instance_id`. [GH-10522]
+* core/hcl: Fix bug where []uint8 types could not be passed to plugins.
+* core/hcl: fix bug where HCL core could not handle passing []uint8 to plugins.
+ [GH-10516]
+* core/hcl: Fix force flag for hcl2 provisioners and post-processors.
+ [GH-10571]
+* post-processor/vsphere: Fix regression where Packer would not check the exit
+ status after streaming UI from the ovftool command. [GH-10468]
+* post-processor/yandex-export: Changed dhclient command and supported
+ configuring disk for exportupdate-dump-method. Also added support for
+ `file` builder. [GH-10488]
+
+## 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]
+
+### 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
+ 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]
+
+## 1.5.4 (February 14, 2020)
+no-change release to fix code-signing on OSX binaries. Since checksums for these
+binaries has changed, we are releasing a second time to prevent confusion.
+
+## 1.5.3 (February 14, 2020)
+
+### IMPROVEMENTS:
+* builder/vsphere: Add ability to define multiple NICs for vsphere-iso
+ [GH-8739]
+* builder/vsphere: Add option to remove CD-ROM drives. [GH-8690]
+* core: Add validation to catch when users accidentally add duplicate fields to
+ template [GH-8725]
+
+### Bug Fixes:
+* core/hcl2: Fix template prepare/validation for HCL2 templates [GH-8742]
+* core: Fix `build` template function interpolation [GH-8727]
+
+## 1.5.2 (February 12, 2020)
+**New Builder** The vsphere-iso builder, previously maintained by JetBrains,
+has been merged with the Packer core. It will be officially supported by the
+Packer team at HashiCorp moving forward. [GH-8480]
+
+**HCL2 variables & functions** HCL2 configurations can now use `variable`,
+`variables`, `locals`, and functions [GH-8588].
+
+### IMPROVEMENTS:
+* builder/alicloud: Add AlicloudProfile option. [GH-8560]
+* builder/amazon: Add max_retries option to aws builders [GH-8709]
+* builder/amazon: Add source AMI owner ID/name to template engines [GH-8550]
+* builder/amazon: Update instance waiters to use global waiter settings set by
+ `AWS_POLL_DELAY_SECONDS` and `AWS_TIMEOUT_SECONDS` [GH-8699]
+* builder/azure: Allow users to use custom key vault for storing Windows
+ certificates [GH-8704]
+* builder/azure: Set expiry for image versions in SIG [GH-8561]
+* builder/proxmox: Add option to upload the boot ISO rather than pointing out a
+ previously manually uploaded one. [GH-8624]
+* builder/vagrant: Fix a crash in the Vagrant driver [GH-8607]
+* builder/yandex: Add service account ID to config [GH-8717]
+* communicator/winrm: Users can now override winrm_host with a static IP even
+ when using cloud builders. [GH-8675]
+* core/hcl2: Fix bug preventing reading slices within other slices [GH-8669]
+* core: Interpolation within post-processors can now access build-specific
+ values like Host IP, communicator password, and more [GH-8632]
+* core: Add `PACKER_PLUGIN_PATH` to list of supported paths for plugin
+ discovery [GH-8616]
+* core: clean up messy log line in plugin execution. [GH-8542]
+* core: Ensure `PACKER_HTTP_ADDR` is always set for any builder that provides a
+ HTTP server for file transfer [GH-8654]
+* core: Fix loading external plugins defined in PACKER_CONFIG [GH-8582]
+* core: Log name of postprocessor running to disambiguate long chains of post-
+ processors. [GH-8613]
+* core: Packer can use isos in-place on Windows again, instead of copying them
+ into its cache. [GH-7627]
+* core: step_download: return without error if Urls is empty [GH-8579]
+* post-processor/vsphere-template] Simplify method to use vm.MarkAsTemplate
+ (optionally) [GH-8511]
+* scripts: Fix some issues with mapstructure-to-hcl2 code generator. [GH-8574]
+* scripts: Update Vagrant bootstrapping scripts [GH-8604]
+
+### Bug Fixes:
+* builder/alicloud: Fix "security group doesn't exist" error when there are >10
+ security groups. [GH-8535]
+* builder/amazon: Allow AWS builder pre-validation to pass when subnet filters
+ are present [GH-8622]
+* builder/azure: Fix bug where deployments were not being cleaned up: [GH-8496]
+* builder/azure: Fix issue where WinRMPassword was being left unset [GH-8670]
+* builder/lxd: Fix file uploading issue when using the file provisioner
+ [GH-8636]
+* builder/null: Fix crash when configuring builder using HCL2. [GH-8612]
+* builder/osc: Fix ssh host detection in Public Cloud and Nets [GH-8414]
+* builder/vagrant: Fix bug with reading key from a path with spaces [GH-8605]
+* builder/virtualbox-ovf: Remove config dependency from StepImport [GH-8509]
+* builder/virtualbox-vm: use config as a non pointer to avoid a panic [GH-8576]
+* core: Fix crash when build.sources is set to an invalid name [GH-8569]
+* core: Fix error loading .packerconfig [GH-8623]
+* core: Fix loading local ISO files when using `iso_target_path` [GH-8689]
+* core: Fix loading of external plugins. GH-8543]
+* post-processor/docker-tag: Fix regression if no tags were specified.
+ [GH-8593]
+* post-processor/vagrant-cloud: Update error handling for Vagrant Cloud API
+ [GH-8594]
+* post-processor/vagrant: correctly handle the diskSize property as a qemu size
+ string [GH-8567]
+* provisioner/ansible: Fix password sanitization to account for empty string
+ values. [GH-8570]
+* provisioner/shell: Fix bug with shell provisioner failing to clean up the
+ environment var file when env_var_file is true. [GH-8639]
+
+## 1.5.1 (December 20, 2019)
+This was a fast-follow release to fix a number of panics that we introduced when
+making changes for HCL2.
+
+### IMPROVEMENTS:
+* builder/alicloud: Add show_expired option for describing images [GH-8425]
+
+### Bug Fixes:
+* builder/cloudstack: Fix panics associated with loading config [GH-8513]
+* builder/hyperv/iso: Fix panics associated with loading config [GH-8513]
+* builder/hyperv/vmcx: Fix panics associated with loading config [GH-8513]
+* builder/jdcloud: Update jdcloud statebag to use pointers for config [GH-8518]
+* builder/linode: Fix panics associated with loading config [GH-8513]
+* builder/lxc: Fix panics associated with loading config [GH-8513]
+* builder/lxd: Fix panics associated with loading config [GH-8513]
+* builder/oneandone: Fix panics associated with loading config [GH-8513]
+* builder/oracle/classic: Fix panics associated with loading config [GH-8513]
+* builder/oracle/oci: Fix panics associated with loading config [GH-8513]
+* builder/osc/bsuvolume: Fix panics associated with loading config [GH-8513]
+* builder/parallels/pvm: Fix panics associated with loading config [GH-8513]
+* builder/profitbricks: Fix panics associated with loading config [GH-8513]
+* builder/scaleway: Fix panics associated with loading config [GH-8513]
+* builder/vagrant: Fix panics associated with loading config [GH-8513]
+* builder/virtualbox/ovf: Fix panics associated with loading config [GH-8513]
+* builder/virtualbox: Configure NAT interface before forwarded port mapping
+ #8514
+* post-processor/vagrant-cloud: Configure NAT interface before forwarded port
+ mapping [GH-8514]
+
+## 1.5.0 (December 18, 2019)
+
+### IMPROVEMENTS:
+* builder/amazon: Add no_ephemeral template option to remove ephemeral drives
+ from launch mappings. [GH-8393]
+* builder/amazon: Add validation for "subnet_id" when specifying "vpc_id"
+ [GH-8360] [GH-8387] [GH-8391]
+* builder/amazon: allow enabling ena/sr-iov on ebssurrogate spot instances
+ [GH-8397]
+* builder/amazon: Retry runinstances aws api call to mitigate throttling
+ [GH-8342]
+* builder/hyperone: Update builder schema and tags [GH-8444]
+* builder/qemu: Add display template option for qemu. [GH-7676]
+* builder/qemu: Disk Size is now read as a string to support units. [GH-8320]
+ [GH-7546]
+* builder/qemu: Add fixer to convert disk size from int to string [GH-8390]
+* builder/qemu: Disk Size is now read as a string to support units. [GH-8320]
+ [GH-7546]
+* builder/qemu: When a user adds a new drive in qemuargs, process it to make
+ sure that necessary settings are applied to that drive. [GH-8380]
+* builder/vmware: Fix error message when ovftool is missing [GH-8371]
+* core: Cleanup logging for external plugins [GH-8471]
+* core: HCL2 template support is now in beta. [GH-8423]
+* core: Interpolation within provisioners can now access build-specific values
+ like Host IP, communicator password, and more. [GH-7866]
+* core: Various fixes to error handling. [GH-8343] [GH-8333] [GH-8316]
+ [GH-8354] [GH-8361] [GH-8363] [GH-8370]
+* post-processor/docker-tag: Add support for multiple tags. [GH-8392]
+* post-processor/shell-local: Add "valid_exit_codes" option to shell-local.
+ [GH-8401]
+* provisioner/chef-client: Add version selection option. [GH-8468]
+* provisioner/shell-local: Add "valid_exit_codes" option to shell-local.
+ [GH-8401]
+* provisioner/shell: Add support for the "env_var_format" parameter [GH-8319]
+
+### 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.
+ [GH-8490]
+* builder/hyperv: Fix bug in checking VM name that could cause flakiness if
+ many VMs are defined. [GH-8357]
+* builder/vagrant: Use absolute path for Vagrantfile [GH-8321]
+* builder/virtualbox: Fix panic in snapshot builder. [GH-8336] [GH-8329]
+* communicator/winrm: Resolve ntlm nil pointer bug by bumping go-ntlmssp
+ dependency [GH-8369]
+* communicator: Fix proxy connection settings to use "SSHProxyUsername" and
+ "SSHProxyPassword" where relevant instead of bastion username and password.
+ [GH-8375]
+* core: Fix bug where Packer froze if asked to log an extremely long line
+ [GH-8356]
+* core: Fix iso_target_path option; don't cache when target path is non-nil
+ [GH-8394]
+* core: Return exit code 1 when builder type is not found [GH-8474]
+* core: Return exit code 1 when builder type is not found [GH-8475]
+* core: Update to newest version of go-tty to re-enable CTRL-S and CTRL-Q usage
+ [GH-8364]
+
+### BACKWARDS INCOMPATIBILITIES:
+* builder/amazon: Complete deprecation of clean_ami_name template func
+ [GH-8320] [GH-8193]
+* core: Changes have been made to both the Prepare() method signature on the
+ builder interface and on the Provision() method signature on the
+ provisioner interface. [GH-7866]
+* provisioner/ansible-local: The "galaxycommand" option has been renamed to
+ "galaxy_command". A fixer has been written for this, which can be invoked
+ with `packer fix`. [GH-8411]
+
+## 1.4.5 (November 4, 2019)
+
+### IMPROVEMENTS:
+* added ucloud-import post-processsor to import custom image for UCloud UHost
+ instance [GH-8261]
+* builder/amazon: New option to specify IAM policy for a temporary instance
+ profile [GH-8247]
+* builder/amazon: improved validation around encrypt_boot and kms_key_id for a
+ better experience [GH-8288]
+* builder/azure-arm: Allow specification of polling duration [GH-8226]
+* builder/azure-chroot: Add Azure chroot builder [GH-8185] & refactored some
+ common code together after it [GH-8269]
+* builder/azure: Deploy NSG if list of IP addresses is provided in config
+ [GH-8203]
+* builder/azure: Set correct user agent for Azure client set [GH-8259]
+* builder/cloudstack: Add instance_display_name for cloudstack builder
+ [GH-8280]
+* builder/hyperv: Add the additional_disk_size option tho the hyperv vmcx
+ builder. [GH-8246]
+* builder/openstack: Add option to discover provisioning network [GH-8279]
+* builder/oracle-oci: Support defined tags for oci builder [GH-8172]
+* builder/proxmox: Add ability to select CPU type [GH-8201]
+* builder/proxmox: Add support for SCSI controller selection [GH-8199]
+* builder/proxmoz: Bump Proxmox dependency: [GH-8241]
+* builder/tencent: Add retry on remote api call [GH-8250]
+* builder/vagrant: Pass through logs from vagrant in real time rather than
+ buffering until command is complete [GH-8274]
+* builder/vagrant: add insert_key option for toggling whether to add Vagrant's
+ insecure key [GH-8274]
+* builder/virtualbox: enabled pcie disks usage, but this feature is in beta and
+ won't work out of the box yet [GH-8305]
+* communicator/winrm: Prevent busy loop while waiting for WinRM connection
+ [GH-8213]
+* core: Add strftime function in templates [GH-8208]
+* core: Improve error message when comment is bad [GH-8267]
+* post-processor/amazon-import: delete intermediary snapshots [GH-8307]
+* Fix various dropped errors an removed unused code: [GH-8230] [GH-8265]
+ [GH-8276] [GH-8281] [GH-8309] [GH-8311] [GH-8304] [GH-8303] [GH-8293]
+
+### BUG FIXES:
+* builder/amazon: Fix region copy for non-ebs amazon builders [GH-8212]
+* builder/amazon: Fix spot instance bug where builder would fail if one
+ availability zone could not support the requested spot instance type, even
+ if another AZ could do so. [GH-8184]
+* builder/azure: Fix build failure after a retry config generation error.
+ [GH-8209]
+* builder/docker: Use a unique temp dir for each build to prevent concurrent
+ builds from stomping on each other [GH-8192]
+* builder/hyperv: Improve filter for determining which files to compact
+ [GH-8248]
+* builder/hyperv: Use first adapter, rather than failing, when multiple
+ adapters are attached to host OS's VM switch [GH-8234]
+* builder/openstack: Fix setting openstack metadata for use_blockstorage_volume
+ [GH-8186]
+* builder/openstack: Warn instead of failing on terminate if instance is
+ already shut down [GH-8176]
+* post-processor/digitalocean-import: Fix panic when 'image_regions' not set
+ [GH-8179]
+* provisioner/powershell: Fix powershell syntax error causing failed builds
+ [GH-8195]
+
+## 1.4.4 (October 1, 2019)
+
+### IMPROVEMENTS:
+**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]
+* builder/cloudstack: New step to detach iso. [GH-8106]
+* builder/googlecompute: Fail fast when image name is invalid. [GH-8112]
+* builder/googlecompute: Users can now query Vault for an Oauth token rather
+ than setting an account file [GH-8143]
+* builder/hcloud: Allow selecting image based on filters [GH-7945]
+* builder/hyper-v: Decrease the delay between Hyper-V VM startup and hyper-v
+ builder's ability to send keystrokes to the target VM. [GH-7970]
+* builder/openstack: Store WinRM password for provisioners to use [GH-7940]
+* builder/proxmox: Shorten default boot_key_interval to 5ms from 100ms
+ [GH-8088]
+* builder/proxmox: Allow running the template VM in a Proxmox resource pool
+ [GH-7862]
+* builder/ucloud: Make ucloud builder's base url configurable [GH-8095]
+* builder/virtualbox-vm: Make target snapshot optional [GH-8011] [GH-8004]
+* builder/vmware: Allow user to attach floppy files to remote vmx builds
+ [GH-8132]
+* builder/yandex: Add ability to retry API requests [GH-8142]
+* builder/yandex: Support GPU instances and set source image by name [GH-8091]
+* communicator/ssh: Support for SSH port tunneling [GH-7918]
+* core: Add a new `floppy_label` option [GH-8099]
+* core: Added version compatibility to console command [GH-8080]
+* post-processor/vagrant-cloud: Allow blank access_token for private vagrant
+ box hosting [GH-8097]
+* 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]
+
+### BUG FIXES:
+* builder/amazon: Fix FleetID crash. [GH-8013]
+* builder/amazon: Gracefully handle rate limiting when retrieving winrm
+ password. [GH-8087]
+* builder/amazon: Fix race condition in spot instance launching [GH-8165]
+* builder/amazon: Amazon builders now respect ssh_host option [GH-8162]
+* builder/amazon: Update the AWS sdk to resolve some credential handling issues
+ [GH-8131]
+* builder/azure: Avoid a panic in getObjectIdFromToken [GH-8047]
+* builder/googlecompute: Fix crash caused by nil account file. [GH-8102]
+* builder/hyper-v: Fix when management interface is not part of virtual switch
+ [GH-8017]
+* builder/openstack: Fix dropped error when creating image client. [GH-8110]
+* builder/openstack: Fix race condition created when adding metadata [GH-8016]
+* builder/outscale: Get SSH Host from VM.Nics instead of VM Root [GH-8077]
+* builder/proxmox: Bump proxmox api dep, fixing bug with checking http status
+ during boot command [GH-8083]
+* builder/proxmox: Check that disk format is set when pool type requires it
+ [GH-8084]
+* builder/proxmox: Fix panic caused by cancelling build [GH-8067] [GH-8072]
+* builder/qemu: Fix dropped error when retrieving version [GH-8050]
+* builder/vagrant: Fix dropped errors in code and tests. [GH-8118]
+* builder/vagrant: Fix provisioning boxes, define source and output boxes
+ [GH-7957]
+* builder/vagrant: Fix ssh and package steps to use source syntax. [GH-8125]
+* builder/vagrant: Use GlobalID when provided [GH-8092]
+* builder/virtualbox: Fix windows pathing problem for guest additions checksum
+ download. [GH-7996]
+* 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
+ properly sanitized in UI calls. [GH-7997]
+* core: Fix handling of booleans where "unset" is a value distinct from
+ "false". [GH-8021]
+* core: Fix tests that swallowed errors in goroutines [GH-8094]
+* core: Fix bug where Packer could no longer run as background process [GH-8101]
+* core: Fix zsh auto-completion [GH-8160]
+* communicator/ssh: Friendlier message warning user that their creds may be
+ wrong [GH-8167]
+* post-processor/amazon-import: Fix non-default encryption. [GH-8113]
+* post-processor/vagrant-cloud: Fix dropped errors [GH-8156]
+* provisioner/ansible: Fix provisioner dropped errors [GH-8045]
+
+### BACKWARDS INCOMPATIBILITIES:
+* core: "sed" template function has been deprecated in favor of "replace" and
+ "replace_all" functions [GH-8119]
+
+## 1.4.3 (August 14, 2019)
+
+### IMPROVEMENTS:
+* **new builder** UCloud builder [GH-7775]
+* **new builder** Outscale [GH-7459]
+* **new builder** VirtualBox Snapshot [GH-7780]
+* **new builder** JDCloud [GH-7962]
+* **new post-processor** Exoscale Import post-processor [GH-7822] [GH-7946]
+* build: Change Makefile to behave differently inside and outside the gopath
+ when generating code. [GH-7827]
+* builder/amazon: Don't calculate spot bids; Amazon has changed spot pricing to
+ no longer require this. [GH-7813]
+* builder/google: Add suse-byos-cloud to list of public GCP cloud image
+ projects [GH-7935]
+* builder/openstack: New `image_min_disk` option [GH-7290]
+* builder/openstack: New option `use_blockstorage_volume` to set openstack
+ image metadata [GH-7792]
+* builder/openstack: Select instance network on which to assign floating ip
+ [GH-7884]
+* builder/qemu: Implement VNC password functionality [GH-7836]
+* builder/scaleway: Allow removing volume after image creation for Scaleway
+ builder [GH-7887]
+* builder/tencent: Add `run_tags` to option to tag instance. [GH-7810]
+* builder/tencent: Remove unnecessary image name validation check. [GH-7786]
+* builder/tencent: Support data disks for tencentcloud builder [GH-7815]
+* builder/vmware: Fix intense CPU usage because of poorly handled errors.
+ [GH-7877]
+* communicator: Use context for timeouts, interruption in ssh and winrm
+ communicators [GH-7868]
+* core: Change how on-error=abort is handled to prevent EOF errors that mask
+ real issues [GH-7913]
+* core: Clean up logging vs ui call in step download [GH-7936]
+* core: New environment var option to allow user to set location of config
+ directory [GH-7912]
+* core: Remove obsolete Cancel functions from builtin provisioners [GH-7917]
+* post-processor/vagrant: Add option to allow box Vagrantfiles to be generated
+ during the build [GH-7951]
+* provisioner/ansible: Add support for installing roles with ansible-galaxy
+ [GH-7916
+* provisioner/salt-masterless: Modify file upload to handle non-root case.
+ [GH-7833]
+
+### BUG FIXES:
+* builder/amazon: Add error to warn users of spot_tags regression. [GH-7989]
+* builder/amazon: Allow EC2 Spot Fleet packer instances to run in parallel
+ [GH-7818]
+* builder/amazon: Fix failures and duplication in Amazon region copy and
+ encryption step. [GH-7870] [GH-7923]
+* builder/amazon: No longer store names of volumes which get deleted on
+ termination inside ebssurrogate artifact. [GH-7829]
+* builder/amazon: Update aws-sdk-go to v1.22.2, resolving some AssumeRole
+ issues [GH-7967]
+* builder/azure: Create configurable polling duration and set higher default
+ for image copies to prevent timeouts on successful copies [GH-7920]
+* builder/digitalocean: increase timeout for Digital Ocean snapshot creation.
+ [GH-7841]
+* builder/docker: Check container os, not host os, when creating container dir
+ default [GH-7939]
+* builder/docker: Fix bug where PACKER_TMP_DIR was created with root perms on
+ linux [GH-7905]
+* builder/docker: Fix file download hang caused by blocking ReadAll call
+ [GH-7814]
+* builder/google: Fix outdated oauth URL. [GH-7835] [GH-7927]
+* builder/hyperv: Improve code for detecting IP address [GH-7880]
+* builder/ucloud: Update the api about stop instance to fix the read-only image
+ build by ucloud-uhost [GH-7914]
+* builder/vagrant: Fix bug where source_path was being used instead of box_name
+ when generating the Vagrantfile. [GH-7859]
+* builder/virtualbox: Honor value of 'Comment' field in ssh keypair generation.
+ [GH-7922]
+* builder/vmware: Fix validation regression that occurred when user provided a
+ checksum file [GH-7804]
+* buildere/azure: Fix crash with managed images not published to shared image
+ gallery. [GH-7837]
+* communicator/ssh: Move ssh_interface back into individual builders from ssh
+ communicator to prevent validation issues where it isn't implemented.
+ [GH-7831]
+* console: Fix console help text [GH-7960]
+* core: Fix bug in template parsing where function errors were getting
+ swallowed. [GH-7854]
+* core: Fix regression where a local filepath containing `//` was no longer
+ properly resolving to `/`. [GH-7888]
+* core: Fix regression where we could no longer access isos on SMB shares.
+ [GH-7800]
+* core: Make ssh_host template option always override all builders' IP
+ discovery. [GH-7832]
+* core: Regenerate boot_command PEG code [GH-7977]
+* fix: clean up help text and fixer order to make sure all fixers are called
+ [GH-7903]
+* provisioner/inspec: Use --input-file instead of --attrs to avoid deprecation
+ warning [GH-7893]
+* provisioner/salt-masterless: Make salt-masterless provisioner respect
+ disable_sudo directive for all commands [GH-7774]
+
+## 1.4.2 (June 26, 2019)
+
+### IMPROVEMENTS:
+* **new feature:** Packer console [GH-7726]
+* builder/alicloud: cleanup image and snapshot if target image is still not
+ available after timeout [GH-7744]
+* builder/alicloud: let product API determine the default value of io_optimized
+ [GH-7747]
+* builder/amazon: Add new `skip_save_build_region` option to fix naming
+ conflicts when building in a region you don't want the final image saved
+ in. [GH-7759]
+* builder/amazon: Add retry for temp key-pair generation in amazon-ebs
+ [GH-7731]
+* builder/amazon: Enable encrypted AMI sharing across accounts [GH-7707]
+* builder/amazon: New SpotInstanceTypes feature for spot instance users.
+ [GH-7682]
+* builder/azure: Allow users to publish Managed Images to Azure Shared Image
+ Gallery (same Subscription) [GH-7778]
+* builder/azure: Update Azure SDK for Go to v30.0.0 [GH-7706]
+* builder/cloudstack: Add tags to instance upon creation [GH-7526]
+* builder/docker: Better windows defaults [GH-7678]
+* builder/google: Add feature to import user-data from a file [GH-7720]
+* builder/hyperv: Abort build if there's a name collision [GH-7746]
+* builder/hyperv: Clarify pathing requirements for hyperv-vmcx [GH-7790]
+* builder/hyperv: Increase MaxRamSize to match modern Windows [GH-7785]
+* builder/openstack: Add image filtering on properties. [GH-7597]
+* builder/qemu: Add additional disk support [GH-7791]
+* builder/vagrant: Allow user to override vagrant ssh-config details [GH-7782]
+* builder/yandex: Gracefully shutdown instance, allow metadata from file, and
+ create preemptible instance type [GH-7734]
+* core: scrub out sensitive variables in scrub out sensitive variables logs
+ [GH-7743]
+
+### BUG FIXES:
+* builder/alicloud: Fix describing snapshots issue when image_ignore_data_disks
+ is provided [GH-7736]
+* builder/amazon: Fix bug in region copy which produced badly-named AMIs in the
+ 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
+ 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 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]
+* core: Switch makefile to use "GO111MODULE=auto" to allow for modern gomodule
+ usage. [GH-7753]
+* provisioner/ansible: prevent nil pointer dereference after a language change
+ [GH-7738]
+* provisioner/chef: Accept chef license by default to prevent hangs in latest
+ Chef [GH-7653]
+* provisioner/powershell: Fix crash caused by error in retry logic check in
+ powershell provisioner [GH-7657]
+* provisioner/powershell: Fix null file descriptor error that occurred when
+ remote_path provided is a directory and not a file. [GH-7705]
+
+## 1.4.1 (May 15, 2019)
+
+### IMPROVEMENTS:
+* **new builder:** new proxmox builder implemented [GH-7490]
+* **new builder:** new yandex cloud builder implemented [GH-7484]
+* **new builder:** new linode builder implemented [GH-7508]
+* build: Circle CI now generates test binaries for all pull requests [GH-7624]
+ [GH-7625] [GH-7630]
+* builder/alicloud: Support encryption with default service key [GH-7574]
+* builder/amazon: Users of chroot and ebssurrogate builders may now choose
+ between "x86_64" and "arm64" architectures when registering their AMIs.
+ [GH-7620]
+* builder/amazon: Users of the ebssurrogage builder may now choose to omit
+ certain launch_block_devices from the final AMI mapping by using the
+ omit_from_artifact feature. [GH-7612]
+* builder/azure: Update Azure SDK [GH-7563]
+* builder/docker: Better error messaging with container downloads. [GH-7513]
+* builder/google: add image encryption support [GH-7551]
+* builder/hyperv: Add keep_registered option to hyperv [GH-7498]
+* builder/qemu: Replace dot-based parsing with hashicorp/go-version [GH-7614]
+* builder/vmware: Add 30 minute timeout for destroying a VM [GH-7553]
+* core: Cleanup cache of used port after closing [GH-7613]
+* core: New option to set number of builds running in parallel & test
+ BuildCommand more [GH-7501]
+* packer compiles on s390x [GH-7567]
+* provisioner/file: Added warnings about writeable locations [GH-7494]
+
+
+### BUG FIXES:
+* builder/amazon: Fix bug that always encrypted build region with default key.
+ [GH-7507]
+* builder/amazon: Fix bug that wasn't deleting unencrypted temporary snapshots
+ [GH-7521]
+* builder/amazon: Fix EBSsurrogate copy, encryption, and deletion of temporary
+ unencrypted amis. [GH-7598]
+* builder/hyperv: Fixes IP detection error if more than one VMNetworkAdapter is
+ found [GH-7480]
+* builder/qemu: Fix mistake switching ssh port mix/max for vnc port min/max
+ [GH-7615]
+* builder/vagrant: Fix bug with builder and vagrant-libvirt plugin [GH-7633]
+* builder/virtualbox: Don't fail download when checksum is not set. [GH-7512]
+* builder/virtualbox: Fix ovf download failures by using local ovf files in
+ place instead of symlinking [GH-7497]
+* builder/vmware: Fix panic configuring VNC for remote builds [GH-7509]
+* core/build: Allow building Packer on solaris by removing progress bar and tty
+ imports on solaris [GH-7618]
+* core: Fix race condition causing hang [GH-7579]
+* core: Fix tty related panics [GH-7517]
+* core: Step download: Always copy local files on windows rather than
+ symlinking them [GH-7575]
+* packer compiles on Solaris again [GH-7589] [GH-7618]
+* post-processor/vagrant: Fix bug in retry logic that caused failed upload to
+ report success. [GH-7554]
+
+## 1.4.0 (April 11, 2019)
+
+### IMPROVEMENTS:
+* builder/alicloud: Improve error message for conflicting images name [GH-7415]
+* builder/amazon-chroot: Allow users to specify custom block device mapping
+ [GH-7370]
+* builder/ansible: Documentation fix explaining how to use ansible 2.7 + winrm
+ [GH-7461]
+* builder/azure-arm: specify zone resilient image from config [GH-7211]
+* builder/docker: Add support for windows containers [GH-7444]
+* builder/openstack: Allow both ports and networks in openstack builder
+ [GH-7451]
+* builder/openstack: Expose force_delete for openstack builder [GH-7395]
+* builder/OpenStack: Support Application Credential Authentication [GH-7300]
+* builder/virtualbox: Add validation for 'none' communicator. [GH-7419]
+* builder/virtualbox: create ephemeral SSH key pair for build process [GH-7287]
+* core: Add functionality to marshal a Template to valid Packer JSON [GH-7339]
+* core: Allow user variables to be interpreted within the variables section
+ [GH-7390]
+* core: Incorporate the go-getter to handle downloads [GH-6999]
+* core: Lock Packer VNC ports using a lock file to prevent collisions [GH-7422]
+* core: Print VerifyChecksum log for the download as ui.Message output
+ [GH-7387]
+* core: Users can now set provisioner timeouts [GH-7466]
+* core: Switch to using go mod for managing dependencies [GH-7270]
+* core: Select a new VNC port if initial port is busy [GH-7423]
+* post-processor/googlecompute-export: Set network project id to builder
+ [GH-7359]
+* post-processor/vagrant-cloud: support for the vagrant builder [GH-7397]
+* post-processor/Vagrant: Option to ignore SSL verification when using on-
+ premise vagrant cloud [GH-7377]
+* postprocessor/amazon-import: Support S3 and AMI encryption. [GH-7396]
+* provisioner/shell provisioner/windows-shell: allow to specify valid exit
+ codes [GH-7385]
+* core: Filter sensitive variables out of the ui as well as the logs
+ [GH-7462]
+
+### BUG FIXES:
+* builder/alibaba: Update to latest Alibaba Cloud official image to fix
+ acceptance tests [GH-7375]
+* builder/amazon-chroot: Fix building PV images and where mount_partition is
+ set [GH-7337]
+* builder/amazon: Fix http_proxy env var regression [GH-7361]
+* builder/azure: Fix: Power off before taking snapshot (windows) [GH-7464]
+* builder/hcloud: Fix usage of freebsd64 rescue image [GH-7381]
+* builder/vagrant: windows : fix docs and usage [GH-7416] [GH-7417]
+* builder/vmware-esxi: properly copy .vmxf files in remote vmx builds [GH-7357]
+* core: fix bug where Packer didn't pause in debug on certain linux platforms.
+ [GH-7352]
+* builder/amazon: Fix bug copying encrypted images between regions [GH-7342]
+
+### BACKWARDS INCOMPATIBILITIES:
+* builder/amazon: Change `temporary_security_group_source_cidr` to
+ `temporary_security_group_source_cidrs` and allow it to accept a list of
+ strings. [GH-7450]
+* builder/amazon: If users do not pass any encrypt setting, retain any initial
+ encryption setting of the AMI. [GH-6787]
+* builder/docker: Update docker's default config to use /bin/sh instead of
+ /bin/bash [GH-7106]
+* builder/hyperv: Change option names cpu->cpus and ram_size->memory to bring
+ naming in line with vmware and virtualbox builders [GH-7447]
+* builder/oracle-classic: Remove default ssh_username from oracle classic
+ builder, but add note to docs with oracle's default user. [GH-7446]
+* builder/scaleway: Renamed attribute api_access_key to organization_id.
+ [GH-6983]
+* Change clean_image name and clean_ami_name to a more general clean_resource
+ name for Googlecompute, Azure, and AWS builders. [GH-7456]
+* core/post-processors: Change interface for post-processors to allow an
+ overridable default for keeping input artifacts. [GH-7463]
+
+## 1.3.5 (February 28, 2019)
+
+### IMPROVEMENTS:
+* builder/alicloud: Update aliyun sdk to support eu-west-1 region [GH-7338]
+* builder/amazon: AWS users can now use the Vault AWS engine to generate
+ temporary credentials. [GH-7282]
+* builder/azure: IMDS to get subscription for Azure MSI [GH-7332]
+* builder/openstack: Replaced deprecated compute/ api with imageservice/
+ [GH-7038]
+* builder/virtualbox: New "guest_additions_interface" option to enable
+ attaching via a SATA interface. [GH-7298]
+* builder/vmware: Add `cores` option for specifying the number of cores per
+ socket. [GH-7191]
+* bulder/openstac: Deprecated compute/v2/images API [GH-7268]
+* core: Add validation check to help folks who swap their iso_path and
+ checksum_path [GH-7311]
+* fixer/amazon: Make the amazon-private-ip fixer errors more visible [GH-7336]
+* post-processor/googlecompute-export: Extend auth for the GCE-post-processors
+ to act like the GCE builder. [GH-7222]
+* post-processor/googlecompute-import: Extend auth for the GCE-post-processors
+ to act like the GCE builder. [GH-7222]
+* post-processor/manifest: Add "custom_data" key to packer manifest post-
+ processor [GH-7248]
+
+### BUG FIXES:
+* builder/amazon: Fix support for aws-us-gov [GH-7347]
+* builder/amazon: Move snapshot deletion to cleanup phase. [GH-7343]
+* builder/azure: Fixed Azure interactive authentication [GH-7276]
+* builder/cloudstack: Updated sdk version; can now use ostype name in
+ template_os option. [GH-7264]
+* builder/google: Change metadata url to use a FQDN fixing bug stemming from
+ differing DNS/search domains. [GH-7260]
+* builder/hyper-v: Fix integer overflows in 32-bit builds [GH-7251]
+* builder/hyper-v: Fix regression where we improperly handled spaces in switch
+ names [GH-7266]
+* builder/openstack: Pass context So we know to cancel during WaitForImage
+ [GH-7341]
+* builder/vmware-esxi: Strip \r\n whitespace from end of names of
+ files stored on esxi. [GH-7310]
+* builder/vmware: Add "--noSSLVerify" to args in ovftool Validation [GH-7314]
+* core: clean up Makefile [GH-7254][GH-7265]
+* core: Fixes mismatches in checksums for dependencies for Go 1.11.4+ [GH-7261]
+* core: make sure 'only' option is completely ignored by post-processors
+ [GH-7262]
+* core: name a post-processor to its type when it is not named [GH-7330]
+* provisioner/salt: Force powershell to overwrite duplicate files [GH-7281]
+
+### Features:
+* **new builder** `vagrant` allows users to call vagrant to provision starting
+ from vagrant boxes and save them as new vagrant boxes. [GH-7221]
+* **new builder:** `hyperone` for building new images on HyperOne Platform on
+ top of existing image or from the scratch with the use of chroot. [GH-7294]
+* **new post-processor** `digitalocean-import`Add digitalocean-import post-
+ processor. [GH-7060]
+* **new provisioner**`inspec` Added inspec.io provisioner [GH-7180]
+* communicator: Add configurable pause after communicator can connect but
+ before it performs provisioning tasks [GH-7317] [GH-7351]
+
+## 1.3.4 (January 30, 2019)
+### IMPROVEMENTS:
+* builder/alicloud: delete copied image and snapshots if corresponding options
+ are specified [GH-7050]
+* builder/amazon: allow to interpolate more variables [GH-7059]
+* builder/amazon: Check that the KMS key ID is valid [GH-7090]
+* builder/amazon: Clean up logging for aws waiters so that it only runs once
+ per builder [GH-7080]
+* builder/amazon: don't Cleanup Temp Keys when there is no communicator to
+ avoid a panic [GH-7100] [GH-7095]
+* builder/amazon: Don't try to guess region from metadata if not set & update
+ aws-sdk-go [GH-7230]
+* builder/amazon: Import error messages should now contain reason for failure
+ [GH-7207]
+* builder/azure: add certificate authentication [GH-7189]
+* builder/azure: allow to configure disk caching [GH-7061]
+* builder/azure: use deallocate instead of just power-off [GH-7203]
+* builder/hyperv: Add support for legacy network adapters on Hyper-V. [GH-7128]
+* builder/hyperv: Allow user to set `version` option in the New-VM command.
+ [GH-7136]
+* builder/openstack: Add `volume_size` option [GH-7130]
+* builder/openstack: Don't require network v2 [GH-6933]
+* builder/openstack: Support for tagging new images [GH-7037]
+* builder/qemu: Add configuration options to specify cpu count and memory size
+ [GH-7156]
+* builder/qemu: Add support for whpx accelerator to qemu builder [GH-7151]
+* builder/vmware: Escape query as suggested in issue #7200 [GH-7223]
+* core/shell: Add env vars "PACKER_HTTP_IP" and "PACKER_HTTP_PORT" to shell
+ provisioners [GH-7075]
+* core: allow to use `-except` on post-processors [GH-7183]
+* core: Clean up internal handling and creation of temporary directories
+ [GH-7102]
+* core: Deprecate mitchellh/go-homedir package in favor of os/user [GH-7062]
+* core: Download checksum match failures will now log the received checksum.
+ [GH-7210]
+* core: Explicitly set ProxyFromEnvironment in httpclients when creating an aws
+ session [GH-7226]
+* 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
+ [GH-7115]
+* provisioner/chef-client: Elevated support for chef-client provisioner
+ [GH-7078]
+* provisioner/puppet: Elevated support for puppet-* provisioner [GH-7078]
+* provisioner/windows-restart: wait for already-scheduled reboot [GH-7056] and
+ ignore reboot specific errors [GH-7071]
+
+
+### BUG FIXES:
+* builder/azure: Ensure the Windows Guest Agent is fully functional before
+ Sysprep is executed. [GH-7176]
+* builder/azure: Fix snapshot regression [GH-7111]
+* builder/docker: Ensure that entrypoint and arguments get passed to docker,
+ not the image. [GH-7091]
+* builder/hcloud: fix go mod dependency [GH-7099]
+* builder/hcloud: prevent panic when ssh key was not passed [GH-7118]
+* builder/hyperv: Fix the Hyper-V gen 1 guest boot order. [GH-7147]
+* builder/hyperv: hyper-v builder no longer ignores `ssh_host` option.
+ [GH-7154]
+* builder/oracle-oci: Fix crash that occurs when image is nil [GH-7126]
+* builder/parallels: Fix attaching prl tools [GH-7158]
+* builder/virtualbox: Fix handling of portcount argument for version 6 beta
+ [GH-7174] [GH-7094]
+* builder/vmware: Fix bug caused by 'nil' dir field in artifact struct when
+ building locally [GH-7116]
+* communicator/docker: Fix docker file provisioner on Windows [GH-7163]
+* core: prioritize AppData over default user directory ( UserProfile )
+ [GH-7166]
+* core: removed a flaky race condition in tests [GH-7119]
+* postprocessor/vsphere: Stop setting HDDOrder, since it was breaking uploads
+ [GH-7108]
+
+
+## 1.3.3 (December 5, 2018)
+### IMPROVEMENTS:
+* builder/alicloud: Add options for system disk properties [GH-6939]
+* builder/alicloud: Apply tags to relevant snapshots [GH-7040]
+* builder/alicloud: Support creating image without data disks [GH-7022]
+* builder/amazon: Add option for skipping TLS verification [GH-6842]
+* builder/azure: Add options for Managed Image OS Disk and Data Disk snapshots
+ [GH-6980]
+* builder/hcloud: Add `snapshot_labels` option to hcloud builder [GH-7046]
+* builder/hcloud: Add ssh_keys config to hcloud builder [GH-7028]
+* builder/hcloud: Update hcloud-go version and support builds using rescue mode
+ [GH-7034]
+* builder/oracle: Parameterized volume size support for Oracle classic builder
+ [GH-6918]
+* builder/parallels: Add configuration options to parallels builder to specify
+ cpu count and memory size [GH-7018]
+* builder/virtualbox: Add configuration options to virtualbox builder to
+ specify cpu count and memory size [GH-7017]
+* builder/virtualbox: expose the VBoxManage export --iso option [GH-5950]
+* builder/vmware: Add configuration options to vmware builder to specify cpu
+ count and memory size [GH-7019]
+* builder/vmware: Add new display_name template option [GH-6984]
+* builder/vmware: Extend vmware-vmx builder to allow esxi builds. [GH-4591]
+ [GH-6927]
+* builder/vmware: Validate username/password for ovftool during prepare.
+ [GH-6977]
+* builder/vmware: Warn users if their vmx_data overrides data that Packer uses
+ the template engine to set in its default vmx template. [GH-6987]
+* communicator/ssh: Expand user path for SSH private key [GH-6946]
+* core: Add a sed template engine [GH-6580]
+* core: More explicit error message in rpc/ui.go [GH-6981]
+* core: Replaced unsafe method of determining homedir with os/user
+ implementation [GH-7036]
+* core: Update vagrantfile's go version. [GH-6841]
+* post-processor/amazon-import: Support ova, raw, vmdk, and vhdx formats in the
+ amazon-import post-processor. [GH-6938]
+* post-processor/vsphere-template: Add option to snapshot vm before marking as
+ template [GH-6969]
+* provisioner/breakpoint: Add a new breakpoint provisioner. [GH-7058]
+* provisioner/powershell: Allow Powershell provisioner to use service accounts
+ [GH-6972]
+* provisioner/shell: Add PauseAfter option to shell provisioner [GH-6913]
+
+### BUG FIXES:
+* builder/amazon: Better error handling of region/credential guessing from
+ metadata [GH-6931]
+* builder/amazon: move region validation to run so that we don't break
+ validation when no credentials are set [GH-7032]
+* builder/hyperv: Remove -Copy:$false when calling Hyper-V\Compare-VM
+ compatability report [GH-7030]
+* builder/qemu: Do not set detect-zeroes option when we want it "off" [GH-7064]
+* builder/vmware-esxi: Create export directories for vmx and ovf file types
+ [GH-6985]
+* builder/vmware: Correctly parse version for VMware Fusion Tech Preview
+ [GH-7016]
+* builder/vmware: Escape vSphere username when putting it into the export call
+ [GH-6962]
+* post-processor/vagrant: Add "hvf" as a libvirt driver [GH-6955]
+* provisioner/ansible: inventory is no longer set to inventory_directory
+ [GH-7065]
+
+## 1.3.2 (October 29, 2018)
+### IMPROVEMENTS:
+* builder/alicloud: Add new `disable_stop_instance` option. [GH-6764]
+* builder/alicloud: Support adding tags to image. [GH-6719]
+* builder/alicloud: Support ssh with private ip address. [GH-6688]
+* builder/amazon: Add support to explicitly control ENA support [GH-6872]
+* builder/amazon: Add suppport for `vpc_filter`, `subnet_filter`, and
+ `security_group_filter`. [GH-6374]
+* builder/amazon: Add validation for required `device_name` parameter in
+ `block_device_mappings`. [GH-6845]
+* builder/amazon: Clean up security group wait code. [GH-6843]
+* builder/amazon: Update aws-sdk-go to v1.15.54, adding support for
+ `credential_source`. [GH-6849]
+* builder/amazon: Use DescribeRegions for aws region validation. [GH-6512],
+ [GH-6904]
+* builder/azure: Add new `shared_image_gallery` option. [GH-6798]
+* builder/googlecompute: Return an error if `startup_script_file` is specified,
+ but file does not exist. [GH-6848]
+* builder/hcloud: Add Hetzner Cloud builder. [GH-6871]
+* builder/openstack: Add new `disk_format` option. [GH-6702]
+* builder/openstack: Fix bug where `source_image_name` wasn't being used to
+ properly find a UUID. [GH-6751]
+* builder/openstack: Wait for volume availability when cleaning up [GH-6703]
+* builder/qemu: Add `disk_detect_zeroes` option. [GH-6827]
+* builder/scaleway: Add `boottype` parameter to config. [GH-6772]
+* builder/scaleway: Update scaleway-cli vendor. [GH-6771]
+* core: New option to add timestamps to UI output. [GH-6784]
+* post-processor/vagrant-cloud: Validate vagrant cloud auth token doing an auth
+ request [GH-6914]
+* provisioner/file: Improve error messaging when file destination is a
+ directory with no trailing slash. [GH-6756]
+* provisioner/powershell: Provide better error when Packer can't find
+ Powershell executable. [GH-6817]
+* provisioner/shell-local: Add ability to specify OSs where shell-local can run
+ [GH-6878]
+
+### BUG FIXES:
+* builder/alicloud: Fix ssh configuration pointer issues that could cause a bug
+ [GH-6720]
+* builder/alicloud: Fix type error in step_create_tags [GH-6763]
+* builder/amazon: Error validating credentials is no longer obscured by a
+ region validation error. and some region validation refactors and
+ improvements [GH-6865]
+* builder/amazon: Fix error calculating defaults in AWS waiters. [GH-6727]
+* builder/amazon: Increase default wait for image import to one hour. [GH-6818]
+* builder/amazon: Waiter now fails rather than hanging for extra time when an
+ image import fails. [GH-6747]
+* builder/azure: Updated Azure/go-ntlmssp dependency to resolve an issue with
+ the winrm communicator not connecting to Windows machines requiring NTLMv2
+ session security
+* builder/digitalocean: Fix ssh configuration pointer issues that could cause a
+ panic [GH-6729]
+* builder/hyperv/vmcx: Allow to set generation from buildfile [GH-6909]
+* builder/scaleway: Fix issues with ssh keys. [GH-6768]
+* core: Fix error where logging was always enabled when Packer was run from
+ inside Terraform. [GH-6758]
+* core: Fix issue with with names containing spaces in ESX5Driver and in ssh
+ communicator [GH-6891], [GH-6823]
+* core: Fix logger so it doesn't accidentally try to format unescaped strings.
+ [GH-6824]
+* core: Fix race conditions in progress bar code [GH-6858], [GH-6788],
+ [GH-6851]
+* core: Fix various places in multiple builders where config was not being
+ passed as a pointer. [GH-6739]
+* post-processor/manifest: No longer provides an empty ID string for Azure's
+ managed image artifact [GH-6822]
+* provisioner/powershell: Fix a bug in the way we set the ProgressPreference
+ variable in the default `execute_command` [GH-6838]
+* provisioner/windows-restart: Fix extraneous break which forced early exit
+ from our wait loop. [GH-6792]
+
+## 1.3.1 (September 13, 2018)
+
+### IMPROVEMENTS:
+* builder/amazon: automatically decode encoded authorization messages if
+ possible [GH-5415]
+* builder:amazon: Optional cleanup of the authorized keys file [GH-6713]
+* builder/qemu: Fixed bug where a -device in the qemuargs would override the default network settings, resulting in no network [GH-6807]
+
+### BUG FIXES:
+* 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]
+
+## 1.3.0 (September 11, 2018)
+
+### IMPROVEMENTS:
+* azure/arm: Retry cleanup of individual resources on error [GH-6644]
+* builder/alicloud: Support source image coming from marketplace [GH-6588]
+* builder/amazon-chroot: Add new `root_volume_type` option. [GH-6669]
+* builder/amazon-chroot: If you have a PV source AMI, with the Amazon Chroot
+ builder, and the destination AMI is type HVM, you can now enable
+ ena_support, example: [GH-6670]
+* builder/amazon-chroot: New feature `root_volume_tags` to tag the created
+ volumes. [GH-6504]
+* builder/amazon: Create a random interim AMI name when encrypt_boot is true so
+ that ami name is not searchable. [GH-6657]
+* builder/azure: Implement clean_image_name template engine. [GH-6558]
+* builder/cloudstack: Add option to use a fixed port via public_port. [GH-6532]
+* builder/digitalocean: Add support for tagging to instances [GH-6546]
+* builder/googlecompute: Add new `min_cpu_platform` feature [GH-6607]
+* builder/googlecompute: Update the list of public image projects that we
+ search, based on GCE documentation. [GH-6648]
+* builder/lxc: Allow unplivileged LXC containers. [GH-6279]
+* builder/oci: Add `metadata` feature to Packer config. [GH-6498]
+* builder/openstack: Add support for getting config from clouds-public.yaml.
+ [GH-6595]
+* builder/openstack: Add support for ports. [GH-6570]
+* builder/openstack: Add support for source_image_filter. [GH-6490]
+* builder/openstack: Migrate floating IP usage to Network v2 API from Compute
+ API. [GH-6373]
+* builder/openstack: Support Block Storage volumes as boot volume. [GH-6596]
+* builder/oracle-oci: Add support for freeform tagging of OCI images [GH-6338]
+* builder/qemu: add ssh agent support. [GH-6541]
+* builder/qemu: New `use_backing_file` feature [GH-6249]
+* builder/vmware-iso: Add support for disk compaction [GH-6411]
+* builder/vmware-iso: Try to use ISO files uploaded to the datastore when
+ building remotely instead of uploading them freshly every time [GH-5165]
+* command/validate: Warn users if config needs fixing. [GH-6423]
+* core: Add a 'split' function to parse template variables. [GH-6357]
+* core: Add a template function allowing users to read keys from consul
+ [GH-6577]
+* core: Add a template function allowing users to read keys from vault
+ [GH-6533]
+* core: Add progress-bar to download step. [GH-5851]
+* core: Create a new root-level Packer template option, "sensitive-variables"
+ which allows users to list which variables they would like to have scrubbed
+ from the Packer logs. [GH-6610]
+* core: Create new config options, "boot_keygroup_interval" and
+ "boot_key_interval" that can be set at the builder-level to supercede
+ PACKER_KEY_INTERVAL for the bootcommand. [GH-6616]
+* core: Deduplicate ui and log lines that stream to terminal [GH-6611]
+* core: Refactor and deduplicate ssh code across builders. This should be a no-
+ op but is a big win for maintainability. [GH-6621] [GH-6613]
+* post-processor/compress: Add support for xz compression [GH-6534]
+* post-processor/vagrant: Support for Docker images. [GH-6494]
+* post-processor/vsphere: Add new `esxi_host` option. [GH-5366]
+* postprocessor/vagrant: Add support for Azure. [GH-6576]
+* provisioner/ansible: Add new "extra var", packer_http_addr. [GH-6501]
+* provisioner/ansible: Enable {{.WinRMPassword}} template engine. [GH-6450]
+* provisioner/shell-local: Create PACKER_HTTP_ADDR environment variable
+ [GH-6503]
+
+
+### BUG FIXES:
+* builder/amazon-ebssurrogate: Clean up volumes at end of build. [GH-6514]
+* builder/amazon: Increase default waiter timeout for AWS
+ WaitUntilImageAvailable command [GH-6601]
+* builder/amazon: Increase the MaxRetries in the Amazon client from the default
+ to 20, to work around users who regularly reach their requestlimit and are
+ being throttled. [GH-6641]
+* builder/amazon: Properly apply environment overrides to our custom-written
+ 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
+ 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]
+* builder/lxc: Fix file copying for unprivileged LXC containers [GH-6544]
+* builder/oracle-oci: Update OCI sdk, fixing validation bug that occurred when
+ RSA key was encrypted. [GH-6492]
+* builder/vmware-iso: Fix crash caused by invalid datacenter url. [GH-6529]
+* builder/vmware: Maintain original boot order during CreateVMX step for
+ vmware-iso builder [GH-6204]
+* communicator/chroot: Fix quote escaping so that ansible provisioner works
+ properly. [GH-6635]
+* core: Better error handling in downloader when connection error occurs.
+ [GH-6557]
+* core: Fix broken pathing checks in checksum files. [GH-6525]
+* provisioner/shell Create new template option allowing users to choose to
+ source env vars from a file rather than declaring them inline. This
+ resolves a bug that occurred when users had complex quoting in their
+ `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
+ with SSH communicator [GH-6606]
+
+### BACKWARDS INCOMPATIBILITIES:
+* builder/amazon: "owners" field on source_ami_filter is now required for
+ secuirty reasons. [GH-6585]
+* builder/vmware-iso: validation will fail for templates using esxi that have the "disk_type_id" set to something other than "thin" or "" and that do not have "skip_compaction": true also set. Use `packer fix` to fix this. [GH-6411]
+
+## 1.2.5 (July 16, 2018)
+
+### BUG FIXES:
+* builder/alickoud: Fix issue where internet_max_bandwidth_out template option
+ was not being passed to builder. [GH-6416]
+* builder/alicloud: Fix an issue with VPC cleanup. [GH-6418]
+* builder/amazon-chroot: Fix communicator bug that broke chroot builds.
+ [GH-6363]
+* builder/amazon: Replace packer's waiters with those from the AWS sdk, solving
+ several timeout bugs. [GH-6332]
+* builder/azure: update azure-sdk-for-go, fixing 32-bit build errors. [GH-6479]
+* builder/azure: update the max length of managed_image_resource_group to match
+ new increased length of 90 characters. [GH-6477]
+* builder/hyper-v: Fix secure boot template feature so that it properly passes
+ the temolate for MicrosoftUEFICertificateAuthority. [GH-6415]
+* builder/hyperv: Fix bug in HyperV IP lookups that was causing breakages in
+ FreeBSD/OpenBSD builds. [GH-6416]
+* builder/qemu: Fix error race condition in qemu builder that caused convert to
+ fail on ubuntu 18.x [GH-6437]
+* builder/qemu: vnc_bind_address was not being passed to qemu. [GH-6467]
+* builder/virtualbox: Allow iso_url to be a symlink. [GH-6370]
+* builder/vmware: Don't fail on DHCP lease files that cannot be read, fixing
+ bug where builder failed on NAT networks that don't serve DHCP. [GH-6415]
+* builder/vmware: Fix bug where we couldn't discover IP if vm_name differed
+ from the vmx displayName. [GH-6448]
+* builder/vmware: Fix validation to prevent hang when remopte_password is not
+ sent but vmware is building on esxi. [GH-6424]
+* builder/vmware:Correctly default the vm export format to ovf; this is what
+ the docs claimed we already did, but we didn't. [GH-4538]
+* communicator/winrm: Revert an attempt to determine whether remote upload
+ destinations were files or directories, as this broke uploads on systems
+ without Powershell installed. [GH-6481]
+* core: Fix bug in parsing of iso checksum files that arose when setting
+ iso_url to a relative filepath. [GH-6488]
+* core: Fix Packer crash caused by improper error handling in the downloader.
+ [GH-6381]
+* fix: Fix bug where fixer for ssh_private_ip that failed when boolean values
+ are passed as strings. [GH-6458]
+* provisioner/powershell: Make upload of powershell variables retryable, in
+ case of system restarts. [GH-6388]
+
+### IMPROVEMENTS:
+* builder/amazon: Add the ap-northeast-3 region. [GH-6385]
+* builder/amazon: Spot requests may now have tags applied using the `spot_tags`
+ option [GH-5452]
+* builder/cloudstack: Add support for Projectid and new config option
+ prevent_firewall_changes. [GH-6487]
+* builder/openstack: Add support for token authorization and cloud.yaml.
+ [GH-6362]
+* builder/oracle-oci: Add new "instance_name" template option. [GH-6408]
+* builder/scaleway: Add new "bootscript" parameter, allowing the user to not
+ use the default local bootscript [GH-6439]
+* builder/vmware: Add support for linked clones to vmware-vmx. [GH-6394]
+* debug: The -debug flag will now cause Packer to pause between provisioner
+ scripts in addition to Packer steps. [GH-4663]
+* post-processor/googlecompute-import: Added new googlecompute-import post-
+ processor [GH-6451]
+* provisioner/ansible: Add new "playbook_files" option to execute multiple
+ playbooks within one provisioner call. [GH-5086]
+
+## 1.2.4 (May 29, 2018)
+
+### BUG FIXES:
+
+* builder/amazon: Can now force the chroot builder to mount an entire block
+ device instead of a partition [GH-6194]
+* builder/azure: windows-sql-cloud is now in the default list of projects to
+ check for provided images. [GH-6210]
+* builder/chroot: A new template option, `nvme_device_path` has been added to
+ provide a workaround for users who need the amazon-chroot builder to mount
+ a NVMe volume on their instances. [GH-6295]
+* builder/hyper-v: Fix command for mounting multiple disks [GH-6267]
+* builder/hyperv: Enable IP retrieval for Server 2008 R2 hosts. [GH-6219]
+* builder/hyperv: Fix bug in MAC address specification on Hyper-V. [GH-6187]
+* builder/parallels-pvm: Add missing disk compaction step. [GH-6202]
+* builder/vmware-esxi: Remove floppy files from the remote server on cleanup.
+ [GH-6206]
+* communicator/winrm: Updated dependencies to fix a race condition [GH-6261]
+* core: When using `-on-error=[abort|ask]`, output the error to the user.
+ [GH-6252]
+* provisioner/puppet: Extra-Arguments are no longer prematurely
+ interpolated. [GH-6215]
+* provisioner/shell: Remove file stat that was causing problems uploading files
+ [GH-6239]
+
+### IMPROVEMENTS:
+
+* builder/amazon: Amazon builders other than `chroot` now support T2 unlimited
+ instances [GH-6265]
+* builder/azure: Allow device login for US government cloud. [GH-6105]
+* builder/azure: Devicelogin Support for Windows [GH-6285]
+* builder/azure: Enable simultaneous builds within one resource group.
+ [GH-6231]
+* builder/azure: Faster deletion of Azure Resource Groups. [GH-6269]
+* builder/azure: Updated Azure SDK to v15.0.0 [GH-6224]
+* builder/hyper-v: Hyper-V builds now connect to vnc display by default when
+ building [GH-6243]
+* builder/hyper-v: New `use_fixed_vhd_format` allows vm export in an Azure-
+ compatible format [GH-6101]
+* builder/hyperv: New config option for specifying what secure boot template to
+ use, allowing secure boot of linux vms. [GH-5883]
+* builder/qemu: Add support for hvf accelerator. [GH-6193]
+* builder/scaleway: Fix SSH communicator connection issue. [GH-6238]
+* core: Add opt-in Packer top-level command autocomplete [GH-5454]
+* post-processor/shell-local: New options have been added to create feature
+ parity with the shell-local provisioner. This feature now works on Windows
+ hosts. [GH-5956]
+* provisioner/chef: New config option allows user to skip cleanup of chef
+ client staging directory. [GH-4300]
+* provisioner/shell-local: Can now access automatically-generated WinRM
+ password as variable [GH-6251]
+* provisoner/shell-local: New options have been added to create feature parity
+ with the shell-local post-processor. This feature now works on Windows
+ hosts. [GH-5956]
+* builder/virtualbox: Use HTTPS to download guest editions, now that it's
+ available. [GH-6406]
+
+## 1.2.3 (April 25, 2018)
+
+### BUG FIXES:
+
+* builder/azure: Azure CLI may now be logged into several accounts. [GH-6087]
+* builder/ebssurrogate: Snapshot all launch devices. [GH-6056]
+* builder/hyper-v: Fix CopyExportedVirtualMachine script so it works with
+ links. [GH-6082]
+* builder/oracle-classic: Fix panics when cleaning up resources that haven't
+ been created. [GH-6095]
+* builder/parallels: Allow user to cancel build while the OS is starting up.
+ [GH-6166]
+* builder/qemu: Avoid warning when using raw format. [GH-6080]
+* builder/scaleway: Fix compilation issues on solaris/amd64. [GH-6069]
+* 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
+ 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]
+* builder/vmware: Multi-disk VM's can be properly handled by the compacting
+ stage. [GH-6074]
+* common/bootcommand: Fix numerous bugs in the boot command code, and make
+ supported features consistent across builders. [GH-6129]
+* communicator/ssh: Stop trying to discover whether destination is a directory
+ from uploader. [GH-6124]
+* post-processor/vagrant: Large VMDKs should no longer show a 0-byte size on OS
+ X. [GH-6084]
+* post-processor/vsphere: Fix encoding of spaces in passwords for upload.
+ [GH-6110]
+* provisioner/ansible: Pass the inventory_directory configuration option to
+ ansible -i when it is set. [GH-6065]
+* provisioner/powershell: fix bug with SSH communicator + cygwin. [GH-6160]
+* provisioner/powershell: The {{.WinRMPassword}} template variable now works
+ with parallel builders. [GH-6144]
+
+### IMPROVEMENTS:
+
+* builder/alicloud: Update aliyungo common package. [GH-6157]
+* builder/amazon: Expose more source ami data as template variables. [GH-6088]
+* builder/amazon: Setting `force_delete` will only delete AMIs owned by the
+ user. This should prevent failures where we try to delete an AMI with a
+ matching name, but owned by someone else. [GH-6111]
+* builder/azure: Users of Powershell provisioner may access the randomly-
+ generated winrm password using the template variable {{.WinRMPassword}}.
+ [GH-6113]
+* builder/google: Users of Powershell provisioner may access the randomly-
+ generated winrm password using the template variable {{.WinRMPassword}}.
+ [GH-6141]
+* builder/hyper-v: User can now configure hyper-v disk block size. [GH-5941]
+* builder/openstack: Add configuration option for `instance_name`. [GH-6041]
+* builder/oracle-classic: Better validation of destination image name.
+ [GH-6089]
+* builder/oracle-oci: New config options for user data and user data file.
+ [GH-6079]
+* builder/oracle-oci: use the official OCI sdk instead of handcrafted client.
+ [GH-6142]
+* builder/triton: Add support to Skip TLS Verification of Triton Certificate.
+ [GH-6039]
+* provisioner/ansible: Ansible users may provide a custom inventory file.
+ [GH-6107]
+* provisioner/file: New `generated` tag allows users to upload files created
+ during Packer run. [GH-3891]
+
+## 1.2.2 (March 26, 2018)
+
+### BUG FIXES:
+
+* builder/amazon: Fix AWS credential defaulting [GH-6019]
+* builder/LXC: make sleep timeout easily configurable [GH-6038]
+* builder/virtualbox: Correctly send multi-byte scancodes when typing boot
+ command. [GH-5987]
+* builder/virtualbox: Special boot-commands no longer overwrite previous
+ commands [GH-6002]
+* builder/vmware: Default to disabling XHCI bus for USB on the vmware-iso
+ builder. [GH-5975]
+* builder/vmware: Handle multiple devices per VMware network type [GH-5985]
+* communicator/ssh: Handle errors uploading files more gracefully [GH-6033]
+* provisioner/powershell: Fix environment variable file escaping. [GH-5973]
+
+
+### IMPROVEMENTS:
+
+* builder/amazon: Added new region `cn-northwest-1`. [GH-5960]
+* builder/amazon: Users may now access the amazon-generated administrator
+ password [GH-5998]
+* builder/azure: Add support concurrent deployments in the same resource group.
+ [GH-6005]
+* builder/azure: Add support for building with additional disks. [GH-5944]
+* builder/azure: Add support for marketplace plan information. [GH-5970]
+* builder/azure: Make all command output human readable. [GH-5967]
+* builder/azure: Respect `-force` for managed image deletion. [GH-6003]
+* builder/google: Add option to specify a service account, or to run without
+ one. [GH-5991] [GH-5928]
+* builder/oracle-oci: Add new "use_private_ip" option. [GH-5893]
+* post-processor/vagrant: Add LXC support. [GH-5980]
+* provisioner/salt-masterless: Added Windows support. [GH-5702]
+* provisioner/salt: Add windows support to salt provisioner [GH-6012] [GH-6012]
+
+
+## 1.2.1 (February 23, 2018)
+
+### BUG FIXES:
+
+* builder/amazon: Fix authorization using assume role. [GH-5914]
+* builder/hyper-v: Fix command collisions with VMWare PowerCLI. [GH-5861]
+* builder/vmware-iso: Fix panic when building on esx5 remotes. [GH-5931]
+* builder/vmware: Fix issue detecting host IP. [GH-5898] [GH-5900]
+* provisioner/ansible-local: Fix conflicting escaping schemes for vars provided
+ via `--extra-vars`. [GH-5888]
+
+### IMPROVEMENTS:
+
+* builder/oracle-classic: Add `snapshot_timeout` option to control how long we
+ wait for the snapshot to be created. [GH-5932]
+* builder/oracle-classic: Add support for WinRM connections. [GH-5929]
+
+
+## 1.2.0 (February 9, 2018)
+
+### BACKWARDS INCOMPATIBILITIES:
+
+* 3rd party plugins: We have moved internal dependencies, meaning your 3rd
+ party plugins will no longer compile (however existing builds will still
+ work fine); the work to fix them is minimal and documented in GH-5810.
+ [GH-5810]
+* builder/amazon: The `ssh_private_ip` option has been removed. Instead, please
+ use `"ssh_interface": "private"`. A fixer has been written for this, which
+ can be invoked with `packer fix`. [GH-5876]
+* builder/openstack: Extension support has been removed. To use OpenStack
+ builder with the OpenStack Newton (Oct 2016) or earlier, we recommend you
+ use Packer v1.1.2 or earlier version.
+* core: Affects Windows guests: User variables containing Powershell special
+ characters no longer need to be escaped. [GH-5376]
+* provisioner/file: We've made destination semantics more consistent across the
+ various communicators. In general, if the destination is a directory, files
+ will be uploaded into the directory instead of failing. This mirrors the
+ behavior of `rsync`. There's a chance some users might be depending on the
+ previous buggy behavior, so it's worth ensuring your configuration is
+ correct. [GH-5426]
+* provisioner/powershell: Regression from v1.1.1 forcing extra escaping of
+ environment variables in the non-elevated provisioner has been fixed.
+ [GH-5515] [GH-5872]
+
+### IMPROVEMENTS:
+
+* **New builder:** `ncloud` for building server images using the NAVER Cloud
+ Platform. [GH-5791]
+* **New builder:** `oci-classic` for building new custom images for use with
+ Oracle Cloud Infrastructure Classic Compute. [GH-5819]
+* **New builder:** `scaleway` - The Scaleway Packer builder is able to create
+ new images for use with Scaleway BareMetal and Virtual cloud server.
+ [GH-4770]
+* builder/amazon: Add `kms_key_id` option to block device mappings. [GH-5774]
+* builder/amazon: Add `skip_metadata_api_check` option to skip consulting the
+ amazon metadata service. [GH-5764]
+* builder/amazon: Add Paris region (eu-west-3) [GH-5718]
+* builder/amazon: Give better error messages if we have trouble during
+ authentication. [GH-5764]
+* builder/amazon: Remove Session Token (STS) from being shown in the log.
+ [GH-5665]
+* builder/amazon: Replace `InstanceStatusOK` check with `InstanceReady`. This
+ reduces build times universally while still working for all instance types.
+ [GH-5678]
+* builder/amazon: Report which authentication provider we're using. [GH-5764]
+* builder/amazon: Timeout early if metadata service can't be reached. [GH-5764]
+* builder/amazon: Warn during prepare if we didn't get both an access key and a
+ secret key when we were expecting one. [GH-5762]
+* builder/azure: Add validation for incorrect VHD URLs [GH-5695]
+* builder/docker: Remove credentials from being shown in the log. [GH-5666]
+* builder/google: Support specifying licenses for images. [GH-5842]
+* builder/hyper-v: Allow MAC address specification. [GH-5709]
+* builder/hyper-v: New option to use differential disks and Inline disk
+ creation to improve build time and reduce disk usage [GH-5631]
+* builder/qemu: Add Intel HAXM support to QEMU builder [GH-5738]
+* builder/triton: Triton RBAC is now supported. [GH-5741]
+* builder/triton: Updated triton-go dependencies, allowing better error
+ handling. [GH-5795]
+* builder/vmware-iso: Add support for cdrom and disk adapter types. [GH-3417]
+* builder/vmware-iso: Add support for setting network type and network adapter
+ type. [GH-3417]
+* builder/vmware-iso: Add support for usb/serial/parallel ports. [GH-3417]
+* builder/vmware-iso: Add support for virtual soundcards. [GH-3417]
+* builder/vmware-iso: More reliably retrieve the guest networking
+ configuration. [GH-3417]
+* builder/vmware: Add support for "super" key in `boot_command`. [GH-5681]
+* communicator/ssh: Add session-level keep-alives [GH-5830]
+* communicator/ssh: Detect dead connections. [GH-4709]
+* core: Gracefully clean up resources on SIGTERM. [GH-5318]
+* core: Improved error logging in floppy file handling. [GH-5802]
+* core: Improved support for downloading and validating a uri containing a
+ Windows UNC path or a relative file:// scheme. [GH-2906]
+* post-processor/amazon-import: Allow user to specify role name in amazon-
+ import [GH-5817]
+* post-processor/docker: Remove credentials from being shown in the log.
+ [GH-5666]
+* post-processor/google-export: Synchronize credential semantics with the
+ Google builder. [GH-4148]
+* post-processor/vagrant: Add vagrant post-processor support for Google
+ [GH-5732]
+* post-processor/vsphere-template: Now accepts artifacts from the vSphere post-
+ processor. [GH-5380]
+* provisioner/amazon: Use Amazon SDK's InstanceRunning waiter instead of
+ InstanceStatusOK waiter [GH-5773]
+* provisioner/ansible: Improve user retrieval. [GH-5758]
+* provisioner/chef: Add support for 'trusted_certs_dir' chef-client
+ configuration option [GH-5790]
+* provisioner/chef: Added Policyfile support to chef-client provisioner.
+ [GH-5831]
+
+### BUG FIXES:
+
+* builder/alicloud-ecs: Attach keypair before starting instance in alicloud
+ builder [GH-5739]
+* builder/amazon: Fix tagging support when building in us-gov/china. [GH-5841]
+* builder/amazon: NewSession now inherits MaxRetries and other settings.
+ [GH-5719]
+* builder/virtualbox: Fix interpolation ordering so that edge cases around
+ guest_additions_url are handled correctly [GH-5757]
+* builder/virtualbox: Fix regression affecting users running Packer on a
+ Windows host that kept Packer from finding Virtualbox guest additions if
+ Packer ran on a different drive from the one where the guest additions were
+ stored. [GH-5761]
+* builder/vmware: Fix case where artifacts might not be cleaned up correctly.
+ [GH-5835]
+* builder/vmware: Fixed file handle leak that may have caused race conditions
+ in vmware builder [GH-5767]
+* communicator/ssh: Add deadline to SSH connection to prevent Packer hangs
+ after script provisioner reboots vm [GH-4684]
+* communicator/winrm: Fix issue copying empty directories. [GH-5763]
+* provisioner/ansible-local: Fix support for `--extra-vars` in
+ `extra_arguments`. [GH-5703]
+* provisioner/ansible-remote: Fixes an error where Packer's private key can be
+ overridden by inherited `ansible_ssh_private_key` options. [GH-5869]
+* provisioner/ansible: The "default extra variables" feature added in Packer
+ v1.0.1 caused the ansible-local provisioner to fail when an --extra-vars
+ argument was specified in the extra_arguments configuration option; this
+ has been fixed. [GH-5335]
+* provisioner/powershell: Regression from v1.1.1 forcing extra escaping of
+ environment variables in the non-elevated provisioner has been fixed.
+ [GH-5515] [GH-5872]
+
+
+## 1.1.3 (December 8, 2017)
+
+### IMPROVEMENTS:
+
+* builder/alicloud-ecs: Add security token support and set TLS handshake
+ timeout through environment variable. [GH-5641]
+* builder/amazon: Add a new parameter `ssh_interface`. Valid values include
+ `public_ip`, `private_ip`, `public_dns` or `private_dns`. [GH-5630]
+* builder/azure: Add sanity checks for resource group names [GH-5599]
+* builder/azure: Allow users to specify an existing resource group to use,
+ instead of creating a new one for every run. [GH-5548]
+* builder/hyper-v: Add support for differencing disk. [GH-5458]
+* builder/vmware-iso: Improve logging of network errors. [GH-5456]
+* core: Add new `packer_version` template engine. [GH-5619]
+* core: Improve logic checking for downloaded ISOs in case where user has
+ provided more than one URL in `iso_urls` [GH-5632]
+* provisioner/ansible-local: Add ability to clean staging directory. [GH-5618]
+
+### BUG FIXES:
+
+* builder/amazon: Allow `region` to appear in `ami_regions`. [GH-5660]
+* builder/amazon: `C5` instance types now build more reliably. [GH-5678]
+* builder/amazon: Correctly set AWS region if given in template along with a
+ profile. [GH-5676]
+* builder/amazon: Prevent `sriov_support` and `ena_support` from being used
+ with spot instances, which would cause a build failure. [GH-5679]
+* builder/hyper-v: Fix interpolation context for user variables in
+ `boot_command` [GH-5547]
+* builder/qemu: Set default disk size to 40960 MB to prevent boot failures.
+ [GH-5588]
+* builder/vmware: Correctly detect Windows boot on vmware workstation.
+ [GH-5672]
+* core: Fix windows path regression when downloading ISOs. [GH-5591]
+* provisioner/chef: Fix chef installs on Windows. [GH-5649]
+
+## 1.1.2 (November 15, 2017)
+
+### IMPROVEMENTS:
+
+* builder/amazon: Correctly deregister AMIs when `force_deregister` is set.
+ [GH-5525]
+* builder/digitalocean: Add `ipv6` option to enable on droplet. [GH-5534]
+* builder/docker: Add `aws_profile` option to control the aws profile for ECR.
+ [GH-5470]
+* builder/google: Add `clean_image_name` template engine. [GH-5463]
+* builder/google: Allow selecting container optimized images. [GH-5576]
+* builder/google: Interpolate network and subnetwork values, rather than
+ relying on an API call that packer may not have permission for. [GH-5343]
+* builder/hyper-v: Add `disk_additional_size` option to allow for up to 64
+ additional disks. [GH-5491]
+* builder/hyper-v: Also disable automatic checkpoints for gen 2 VMs. [GH-5517]
+* builder/lxc: Add new `publish_properties` field to set image properties.
+ [GH-5475]
+* builder/lxc: Add three new configuration option categories to LXC builder:
+ `create_options`, `start_options`, and `attach_options`. [GH-5530]
+* builder/triton: Add `source_machine_image_filter` option to select an image
+ ID based on a variety of parameters. [GH-5538]
+* builder/virtualbox-ovf: Error during prepare if source path doesn't exist.
+ [GH-5573]
+* builder/virtualbox-ovf: Retry while removing VM to solve for transient
+ errors. [GH-5512]
+* communicator/ssh: Add socks 5 proxy support. [GH-5439]
+* core/iso_config: Support relative paths in checksum file. [GH-5578]
+* core: Rewrite vagrantfile code to make cross-platform development easier.
+ [GH-5539]
+* post-processor/docker-push: Add `aws_profile` option to control the aws
+ profile for ECR. [GH-5470]
+* post-processor/vsphere: Properly capture `ovftool` output. [GH-5499]
+
+### BUG FIXES:
+
+* builder/amazon: Add a delay option to security group waiter. [GH-5536]
+* builder/amazon: Fix regressions relating to spot instances and EBS volumes.
+ [GH-5495]
+* builder/amazon: Set region from profile, if profile is set, rather than being
+ overridden by metadata. [GH-5562]
+* builder/docker: Remove `login_email`, which no longer exists in the docker
+ client. [GH-5511]
+* builder/hyperv: Fix admin check that was causing powershell failures.
+ [GH-5510]
+* builder/oracle: Defaulting of OCI builder region will first check the packer
+ template and the OCI config file. [GH-5407]
+* builder/triton: Fix a bug where partially created images can be reported as
+ complete. [GH-5566]
+* post-processor/vsphere: Use the vm disk path information to re-create the vmx
+ datastore path. [GH-5567]
+* provisioner/windows-restart: Wait for restart no longer endlessly loops if
+ user specifies a custom restart check command. [GH-5563]
+
+## 1.1.1 (October 13, 2017)
+
+### IMPROVEMENTS:
+
+* **New builder:** `hyperv-vmcx` for building images from existing VMs.
+ [GH-4944] [GH-5444]
+* builder/amazon-instance: Add `.Token` as a variable in the
+ `BundleUploadCommand` template. [GH-5288]
+* builder/amazon: Add `temporary_security_group_source_cidr` option to control
+ ingress to source instances. [GH-5384]
+* builder/amazon: Output AMI Name during prevalidation. [GH-5389]
+* builder/amazon: Support template functions in tag keys. [GH-5381]
+* builder/amazon: Tag volumes on creation instead of as a separate step.
+ [GH-5417]
+* builder/docker: Add option to set `--user` flag when running `exec`.
+ [GH-5406]
+* builder/docker: Set file owner to container user when uploading. Can be
+ disabled by setting `fix_upload_owner` to `false`. [GH-5422]
+* builder/googlecompute: Support setting labels on the resulting image.
+ [GH-5356]
+* builder/hyper-v: Add `vhd_temp_path` option to control where the VHD resides
+ while it's being provisioned. [GH-5206]
+* builder/hyper-v: Allow vhd or vhdx source images instead of just ISO.
+ [GH-4944] [GH-5444]
+* builder/hyper-v: Disable automatic checkpoints. [GH-5374]
+* builder/virtualbox-ovf: Add `keep_registered` option. [GH-5336]
+* builder/vmware: Add `disable_vnc` option to prevent VNC connections from
+ being made. [GH-5436]
+* core: Releases will now be built for ppc64le.
+* post-processor/vagrant: When building from a builder/hyper-v artifact, link
+ instead of copy when available. [GH-5207]
+
+
+### BUG FIXES:
+
+* builder/cloudstack: Fix panic if build is aborted. [GH-5388]
+* builder/hyper-v: Respect `enable_dynamic_memory` flag. [GH-5363]
+* builder/puppet-masterless: Make sure directories created with sudo are
+ writable by the packer user. [GH-5351]
+* provisioner/chef-solo: Fix issue installing chef-solo on Windows. [GH-5357]
+* provisioner/powershell: Fix issue setting environment variables by writing
+ them to a file, instead of the command line. [GH-5345]
+* provisioner/powershell: Fix issue where powershell scripts could hang.
+ [GH-5082]
+* provisioner/powershell: Fix Powershell progress stream leak to stderr for
+ normal and elevated commands. [GH-5365]
+* provisioner/puppet-masterless: Fix bug where `puppet_bin_dir` wasn't being
+ respected. [GH-5340]
+* provisioner/puppet: Fix setting facter vars on Windows. [GH-5341]
+
+
+## 1.1.0 (September 12, 2017)
+
+### IMPROVEMENTS:
+
+* builder/alicloud: Update alicloud go sdk and enable multi sites support for
+ alicloud [GH-5219]
+* builder/amazon: Upgrade aws-sdk-go to 1.10.14, add tags at instance run time.
+ [GH-5196]
+* builder/azure: Add object_id to windows_custom_image.json. [GH-5285]
+* builder/azure: Add support for storage account for managed images. [GH-5244]
+* builder/azure: Update pkcs12 package. [GH-5301]
+* builder/cloudstack: Add support for Security Groups. [GH-5175]
+* builder/docker: Uploading files and directories now use docker cp. [GH-5273]
+ [GH-5333]
+* builder/googlecompute: Add `labels` option for labeling launched instances.
+ [GH-5308]
+* builder/googlecompute: Add support for accelerator api. [GH-5137]
+* builder/profitbricks: added support for Cloud API v4. [GH-5233]
+* builder/vmware-esxi: Remote builds now respect `output_directory` [GH-4592]
+* builder/vmware: Set artifact ID to `VMName`. [GH-5187]
+* core: Build solaris binary by default. [GH-5268] [GH-5248]
+* core: Remove LGPL dependencies. [GH-5262]
+* provisioner/puppet: Add `guest_os_type` option to add support for Windows.
+ [GH-5252]
+* provisioner/salt-masterless: Also use sudo to clean up if we used sudo to
+ install. [GH-5240]
+
+### BACKWARDS INCOMPATIBILITIES:
+
+* builder/amazon: Changes way that AMI artifacts are printed out after build,
+ aligning them to builder. Could affect output parsing. [GH-5281]
+* builder/amazon: Split `enhanced_networking` into `sriov_support` and
+ `ena_support` to support finer grained control. Use `packer fix
+ <template.json>` to automatically update your template to use `ena_support`
+ where previously there was only `enhanced_networking`. Make sure to also
+ add `sriov_support` if you need that feature, and to ensure `ena_support`
+ is what you intended to be in your template. [GH-5284]
+* builder/cloudstack: Setup temporary SSH keypair; backwards incompatible in
+ the uncommon case that the source image allowed SSH auth with password but
+ not with keypair. [GH-5174]
+* communicator/ssh: Renamed `ssh_disable_agent` to
+ `ssh_disable_agent_forwarding`. Need to run fixer on packer configs that
+ use `ssh_disable_agent`. [GH-5024]
+* communicator: Preserve left-sided white-space in remote command output. Make
+ sure any scripts that parse this output can handle the new whitespace
+ before upgrading. [GH-5167]
+* provisioner/shell: Set default for `ExpectDisconnect` to `false`. If your
+ script causes the connection to be reset, you should set this to `true` to
+ prevent errors. [GH-5283]
+
+### BUG FIXES:
+
+* builder/amazon: `force_deregister` works in all regions, not just original
+ region. [GH-5250]
+* builder/docker: Directory uploads now use the same semantics as the rest of
+ the communicators. [GH-5333]
+* builder/vmware: Fix timestamp in default VMName. [GH-5274]
+* builder/winrm: WinRM now waits to make sure commands can run successfully
+ before considering itself connected. [GH-5300]
+* core: Fix issue where some builders wouldn't respect `-on-error` behavior.
+ [GH-5297]
+* provisioner/windows-restart: The first powershell provisioner after a restart
+ now works. [GH-5272]
+
+### FEATURES:
+
+* **New builder**: Oracle Cloud Infrastructure (OCI) builder for creating
+ custom images. [GH-4554]
+* **New builder:** `lxc` for building lxc images. [GH-3523]
+* **New builder:** `lxd` for building lxd images. [GH-3625]
+* **New post-processor**: vSphere Template post-processor to be used with
+ vmware-iso builder enabling user to mark a VM as a template. [GH-5114]
+
+## 1.0.4 (August 11, 2017)
+
+### IMPROVEMENTS:
+
+* builder/alicloud: Increase polling timeout. [GH-5148]
+* builder/azure: Add `private_virtual_network_with_public_ip` option to
+ optionally obtain a public IP. [GH-5222]
+* builder/googlecompute: use a more portable method of obtaining zone.
+ [GH-5192]
+* builder/hyperv: Properly interpolate user variables in template. [GH-5184]
+* builder/parallels: Remove soon to be removed --vmtype flag in createvm.
+ [GH-5172]
+* contrib: add json files to zsh completion. [GH-5195]
+
+### BUG FIXES:
+
+* builder/amazon: Don't delete snapshots we didn't create. [GH-5211]
+* builder/amazon: fix builds when using the null communicator. [GH-5217]
+* builder/docker: Correctly handle case when uploading an empty directory.
+ [GH-5234]
+* command/push: Don't push variables if they are unspecified. Reverts to
+ behavior in 1.0.1. [GH-5235]
+* command/push: fix handling of symlinks. [GH-5226]
+* core: Strip query parameters from ISO URLs when checking against a checksum
+ file. [GH-5181]
+* provisioner/ansible-remote: Fix issue where packer could hang communicating
+ with ansible-remote. [GH-5146]
+
+## 1.0.3 (July 17, 2017)
+
+### IMPROVEMENTS:
+* builder/azure: Update to latest Azure SDK, enabling support for managed
+ disks. [GH-4511]
+* builder/cloudstack: Add default cidr_list [ 0.0.0.0/0 ]. [GH-5125]
+* builder/cloudstack: Add support for ssh_agent_auth. [GH-5130]
+* builder/cloudstack: Add support for using a HTTP server. [GH-5017]
+* builder/cloudstack: Allow reading api_url, api_key, and secret_key from env
+ vars. [GH-5124]
+* builder/cloudstack: Make expunge optional and improve logging output.
+ [GH-5099]
+* builder/googlecompute: Allow using URL's for network and subnetwork.
+ [GH-5035]
+* builder/hyperv: Add support for floppy_dirs with hyperv-iso builder.
+* builder/hyperv: Add support for override of system %temp% path.
+* core: Experimental Android ARM support. [GH-5111]
+* post-processor/atlas: Disallow packer push of vagrant.box artifacts to atlas.
+ [GH-4780]
+* postprocessor/atlas: Disallow pushing vagrant.box artifacts now that Vagrant
+ cloud is live. [GH-4780]
+
+### BUG FIXES:
+* builder/amazon: Fix panic that happens if ami_block_device_mappings is empty.
+ [GH-5059]
+* builder/azure: Write private SSH to file in debug mode. [GH-5070] [GH-5074]
+* builder/cloudstack: Properly report back errors. [GH-5103] [GH-5123]
+* builder/docker: Fix windows filepath in docker-toolbox call [GH-4887]
+* builder/docker: Fix windows filepath in docker-toolbox call. [GH-4887]
+* builder/hyperv: Use SID to verify membership in Admin group, fixing for non-
+ english users. [GH-5022]
+* builder/hyperv: Verify membership in the group Hyper-V Administrators by SID
+ not name. [GH-5022]
+* builder/openstack: Update gophercloud version, fixing builds > 1 hr long.
+ [GH-5046]
+* builder/parallels: Skip missing paths when looking for unnecessary files.
+ [GH-5058]
+* builder/vmware-esxi: Fix VNC port discovery default timeout. [GH-5051]
+* communicator/ssh: Add ProvisionerTypes to communicator tests, resolving panic
+ [GH-5116]
+* communicator/ssh: Resolve race condition that sometimes truncates ssh
+ provisioner stdout [GH-4719]
+* post-processor/checksum: Fix interpolation of "output". [GH-5112]
+* push: Push vars in packer config, not just those set from command line and in
+ var-file. [GH-5101]
+
+## 1.0.2 (June 21, 2017)
+
+### BUG FIXES:
+* communicator/ssh: Fix truncated stdout from remote ssh provisioner. [GH-5050]
+* builder/amazon: Fix bugs related to stop instance command. [GH-4719]
+* communicator/ssh: Fix ssh connection errors. [GH-5038]
+* core: Remove logging that shouldn't be there when running commands. [GH-5042]
+* provisioner/shell: Fix bug where scripts were being run under `sh`. [GH-5043]
+
+### IMPROVEMENTS:
+
+* provisioner/windows-restart: make it clear that timeouts come from the
+ provisioner, not winrm. [GH-5040]
+
+## 1.0.1 (June 19, 2017)
+
+### IMPROVEMENTS:
+
+* builder/amazon: Allow amis to be copied to other regions, encrypted with
+ custom KMS keys. [GH-4948]
+* builder/amazon: Allow configuration of api endpoint to support api-compatible
+ cloud providers. [GH-4896]
+* builder/amazon: Fix regex used for ami name validation [GH-4902]
+* builder/amazon: Look up vpc from subnet id if no vpc was specified. [GH-4879]
+* builder/amazon: Print temporary security group name to the UI. [GH-4997]
+* builder/amazon: Support Assume Role with MFA and ECS Task Roles. Also updates
+ to a newer version of aws-sdk-go. [GH-4996]
+* builder/amazon: Use retry logic when creating instance tags. [GH-4876]
+* builder/amazon: Validate ami name. [GH-4762]
+* builder/azure: Add build output to artifact. [GH-4953]
+* builder/azure: Use disk URI as artifact ID. [GH-4981]
+* builder/digitalocean: Added support for monitoring. [GH-4782]
+* builder/digitalocean: Support for copying snapshot to other regions.
+ [GH-4893]
+* builder/hyper-v: Remove the check for administrator rights when sending key
+ strokes to Hyper-V. [GH-4687] # builder/openstack: Fix private key error
+ message to match documentation [GH-4898]
+* builder/null: Support SSH agent auth [GH-4956]
+* builder/openstack: Add ssh agent support. [GH-4655]
+* builder/openstack: Support client x509 certificates. [GH-4921]
+* builder/parallels-iso: Configuration of disk type, plain or expanding.
+ [GH-4621]
+* builder/triton: An SSH agent can be used to authenticate requests, making
+ `triton_key_material` optional. [GH-4838]
+* builder/triton: If no source machine networks are specified, instances are
+ started on the default public and internal networks. [GH-4838]
+* builder/virtualbox: Add sata port count configuration option. [GH-4699]
+* builder/virtualbox: Don't add port forwarding when using "none" communicator.
+ [GH-4960]
+* builder/vmware: Add option to remove interfaces from the vmx. [GH-4927]
+* builder/vmware: Properly remove mounted CDs on OS X. [GH-4810]
+* builder/vmware: VNC probe timeout is configurable. [GH-4919]
+* command/push: add `-sensitive` flag to mark pushed vars are sensitive.
+ [GH-4970]
+* command/push: Vagrant support in Terraform Enterprise is deprecated.
+ [GH-4950]
+* communicator/ssh: Add ssh agent support for bastion connections. [GH-4940]
+* communicator/winrm: Add NTLM authentication support. [GH-4979]
+* communicator/winrm: Add support for file downloads. [GH-4748]
+* core: add telemetry for better product support. [GH-5015]
+* core: Build binaries for arm64 [GH-4892]
+* post-processor/amazon-import: Add support for `license_type`. [GH-4634]
+* post-processor/vagrant-cloud: Get vagrant cloud token from environment.
+ [GH-4982]
+* provisioner/ansible-local: Add extra-vars `packer_build_name`,
+ `packer_builder_type`, and `packer_http_addr`. [GH-4821]
+* provisioner/ansible: Add `inventory_directory` option to control where to
+ place the generated inventory file. [GH-4760]
+* provisioner/ansible: Add `skip_version_check` flag for when ansible will be
+ installed from a prior provisioner. [GH-4983]
+* provisioner/ansible: Add extra-vars `packer_build_name` and
+ `packer_builder_type`. [GH-4821]
+* provisioner/chef-solo: Add option to select Chef version. [GH-4791]
+* provisioner/salt: Add salt bin directory configuration. [GH-5009]
+* provisioner/salt: Add support for grains. [GH-4961]
+* provisioner/shell: Use `env` to set environment variables to support freebsd
+ out of the box. [GH-4909]
+* website/docs: Clarify language, improve formatting. [GH-4866]
+* website/docs: Update docker metadata fields that can be changed. [GH-4867]
+
+
+### BUG FIXES:
+
+* builder/amazon-ebssurrogate: Use ami device settings when creating the AMI.
+ [GH-4972]
+* builder/amazon: don't try to delete extra volumes during clean up. [GH-4930]
+* builder/amazon: fix `force_delete_snapshot` when the launch instance has
+ extra volumes. [GH-4931]
+* builder/amazon: Only delete temporary key if we created one. [GH-4850]
+* builder/azure: Replace calls to panic with error returns. [GH-4846]
+* communicator/winrm: Use KeepAlive to keep long-running connections open.
+ [GH-4952]
+* core: Correctly reject config files which have junk after valid json.
+ [GH-4906]
+* post-processor/checksum: fix crash when invalid checksum is used. [GH-4812]
+* post-processor/vagrant-cloud: don't read files to upload in to memory first.
+ [GH-5005]
+* post-processor/vagrant-cloud: only upload once under normal conditions.
+ [GH-5008]
+* provisioner/ansible-local: Correctly set the default staging directory under
+ Windows. [GH-4792]
+
+### FEATURES:
+
+* **New builder:** `alicloud-ecs` for building Alicloud ECS images. [GH-4619]
+
+
+## 1.0.0 (April 4, 2017)
+
+### BUG FIXES:
+
+* builder/amazon: Fix b/c issue by reporting again the tags we create.
+ [GH-4704]
+* builder/amazon: Fix crash in `step_region_copy`. [GH-4642]
+* builder/googlecompute: Correct values for `on_host_maintenance`. [GH-4643]
+* builder/googlecompute: Use "default" service account. [GH-4749]
+* builder/hyper-v: Don't wait for shutdown_command to return. [GH-4691]
+* builder/virtualbox: fix `none` communicator by allowing skipping upload of
+ version file. [GH-4678]
+* builder/virtualbox: retry removing floppy controller. [GH-4705]
+* communicator/ssh: don't return error if we can't close connection. [GH-4741]
+* communicator/ssh: fix nil pointer error. [GH-4690]
+* core: fix version number
+* core: Invoking packer `--help` or `--version` now exits with status 0.
+ [GH-4723]
+* core: show correct step name when debugging. [GH-4672]
+* communicator/winrm: Directory uploads behave more like scp. [GH-4438]
+
+### IMPROVEMENTS:
+
+* builder/amazon-chroot: Ability to give an empty list in `copy_files` to
+ prevent the default `/etc/resolv.conf` file from being copied. If
+ `copy_files` isn't given at all, the default behavior remains. [GH-4708]
+* builder/amazon: set force_deregister to true on -force. [GH-4649]
+* builder/amazon: validate ssh key name/file. [GH-4665]
+* builder/ansible: Clearer error message when we have problems getting the
+ ansible version. [GH-4694]
+* builder/hyper-v: validate output dir in step, not in config. [GH-4645]
+* More diligently try to complete azure-setup.sh. [GH-4752]
+* website: fix display on ios devices. [GH-4618]
+
+## 0.12.3 (March 1, 2017)
+
+### BACKWARDS INCOMPATIBILITIES:
+
+* provisioner/ansible: by default, the staging dir will be randomized. [GH-4472]
+
+### FEATURES:
+
+* **New builder:** `ebs-surrogate` for building AMIs from EBS volumes. [GH-4351]
+
+### IMPROVEMENTS:
+
+* builder/amazon-chroot: support encrypted boot volume. [GH-4584]
+* builder/amazon: Add BuildRegion and SourceAMI template variables. [GH-4399]
+* builder/amazon: Change EC2 Windows password timeout to 20 minutes. [GH-4590]
+* builder/amazon: enable ena when `enhanced_networking` is set. [GH-4578]
+* builder/azure:: add two new config variables for temp_compute_name and
+ temp_resource_group_name. [GH-4468]
+* builder/docker: create export dir if needed. [GH-4439]
+* builder/googlecompute: Add `on_host_maintenance` option. [GH-4544]
+* builder/openstack: add reuse_ips option to try to re-use existing IPs.
+ [GH-4564]
+* builder/vmware-esxi: try for longer to connect to vnc port. [GH-4480]
+ [GH-4610]
+* builder/vmware: allow extra options for ovftool. [GH-4536]
+* builder/vmware: don't cache ip address so we know if it changes. [GH-4532]
+* communicator/docker: preserve file mode. [GH-4443]
+* communicator/ssh: Use SSH agent when enabled for bastion step. [GH-4598]
+* communicator/winrm: support ProxyFromEnvironment. [GH-4463]
+* core: don't show ui color if we're not colorized. [GH-4525]
+* core: make VNC links clickable in terminal. [GH-4497] [GH-4498]
+* docs: add community page. [GH-4550]
+* post-processor/amazon-import: support AMI attributes on import [GH-4216]
+* post-processor/docker-import: print stderr on docker import failure.
+ [GH-4529]
+
+### BUG FIXES:
+
+* builder/amazon-ebsvolume: Fix interpolation of block_device. [GH-4464]
+* builder/amazon: Fix ssh agent authentication. [GH-4597]
+* builder/docker: Don't force tag if using a docker version that doesn't
+ support it. [GH-4560]
+* builder/googlecompute: fix bug when creating image from custom image_family.
+ [GH-4518]
+* builder/virtualbox: remove guest additions before saving image. [GH-4496]
+* core: always check for an error first when walking a path. [GH-4467]
+* core: update crypto/ssh lib to fix large file uploads. [GH-4546]
+* provisioner/chef-client: only upload knife config if we're cleaning.
+ [GH-4534]
+
+## 0.12.2 (January 20, 2017)
+
+### FEATURES:
+
+* **New builder:** `triton` for building images for Joyent Triton. [GH-4325]
+* **New provisioner:** `converge` for provisioning with converge.sh. [GH-4326]
+
+### IMPROVEMENTS:
+
+* builder/hyperv-iso: add `iso_target_extension` option. [GH-4294]
+* builder/openstack: Add support for instance metadata. [GH-4361]
+* builder/openstack: Attempt to use existing floating IPs before allocating a
+ new one. [GH-4357]
+* builder/parallels-iso: add `iso_target_extension` option. [GH-4294]
+* builder/qemu: add `iso_target_extension` option. [GH-4294]
+* builder/qemu: add `use_default_display` option for osx compatibility.
+ [GH-4293]
+* builder/qemu: Detect input disk image format during copy/convert. [GH-4343]
+* builder/virtualbox-iso: add `iso_target_extension` option. [GH-4294]
+* builder/virtualbox: add `skip_export` option to skip exporting the VM after
+ build completes. [GH-4339]
+* builder/vmware & builder/qemu: Allow configurable delay between keystrokes
+ when typing boot command. [GH-4403]
+* builder/vmware-iso: add `iso_target_extension` option. [GH-4294]
+* builder/vmware-iso: add `skip_export` option to skip exporting the VM after
+ build completes. [GH-4378]
+* builder/vmware: Try to use `ip address` to find host IP. [GH-4411]
+* common/step_http\_server: set `PACKER_HTTP_ADDR` env var for accessing http
+ server from inside builder. [GH-4409]
+* provisioner/powershell: Allow equals sign in value of environment variables.
+ [GH-4328]
+* provisioner/puppet-server: Add default facts. [GH-4286]
+
+### BUG FIXES:
+
+* builder/amazon-chroot: Panic in AMI region copy step. [GH-4341]
+* builder/amazon: Crashes when new EBS vols are used. [GH-4308]
+* builder/amazon: Fix crash in amazon-instance. [GH-4372]
+* builder/amazon: fix run volume tagging [GH-4420]
+* builder/amazon: fix when using non-existent security\_group\_id. [GH-4425]
+* builder/amazon: Properly error if we don't have the
+ ec2:DescribeSecurityGroups permission. [GH-4304]
+* builder/amazon: Properly wait for security group to exist. [GH-4369]
+* builder/docker: Fix crash when performing log in to ECR with an invalid URL.
+ [GH-4385]
+* builder/openstack: fix for finding resource by ID. [GH-4301]
+* builder/qemu: Explicitly set WinRMPort for StepConnect. [GH-4321]
+* builder/virtualbox: Explicitly set WinRMPort for StepConnect. [GH-4321]
+* builder/virtualbox: Pause between each boot command element in -debug.
+ [GH-4346]
+* builder/vmware builder/parallels: Fix hang when shutting down windows in
+ certain cases. [GH-4436]
+* command/push: Don't interpolate variables when pushing. [GH-4389]
+* common/step_http_server: make port range inclusive. [GH-4398]
+* communicator/winrm: update winrm client, resolving `MaxMemoryPerShellMB`
+ errors and properly error logging instead of panicking. [GH-4412] [GH-4424]
+* provider/windows-shell: Allows equals sign in env var value. [GH-4423]
+
+## 0.12.1 (December 15, 2016)
+
+### BACKWARDS INCOMPATIBILITIES:
+
+* `ssh_username` is now required if using communicator ssh. [GH-4172]
+* builder/amazon: Change `shutdown_behaviour` to `shutdown_behavior`. Run
+ "packer fix template.json" to migrate a template. [GH-4285]
+* builder/openstack: No long supports the `api_key` option for rackspace.
+ [GH-4283]
+* post-processor/manifest: Changed `filename` field to be `output`, to be more
+ consistent with other post-processors. `packer fix` will fix this for you.
+ [GH-4192]
+* post-processor/shell-local: Now runs per-builder instead of per-file. The
+ filename is no longer passed in as an argument to the script, but instead
+ needs to be gleaned from the manifest post-processor. [GH-4189]
+
+### FEATURES:
+
+* **New builder:** "Hyper-V" Added new builder for Hyper-V on Windows.
+ [GH-2576]
+* **New builder:** "1&1" Added new builder for [1&1](https://www.1and1.com/).
+ [GH-4163]
+
+### IMPROVEMENTS:
+
+* builder/amazon-ebs: Support specifying KMS key for encryption. [GH-4023]
+* builder/amazon-ebsvolume: Add artifact output. [GH-4141]
+* builder/amazon: Add `snapshot_tag` overrides. [GH-4015]
+* builder/amazon: Added new region London - eu-west-2. [GH-4284]
+* builder/amazon: Added ca-central-1 to list of known aws regions. [GH-4274]
+* builder/amazon: Adds `force_delete_snapshot` flag to also cleanup snapshots
+ if we're removing a preexisting image, as with `force_deregister_image`.
+ [GH-4223]
+* builder/amazon: Support `snapshot_users` and `snapshot_groups` for sharing
+ ebs snapshots. [GH-4243]
+* builder/cloudstack: Support reusing an already associated public IP.
+ [GH-4149]
+* builder/docker: Introduce docker commit changes, author, and message.
+ [GH-4202]
+* builder/googlecompute: Support `source_image_family`. [GH-4162]
+* builder/googlecompute: enable support for Google Compute XPN. [GH-4288]
+* builder/openstack: Added `image_members` to add new members to image after
+ it's created. [GH-4283]
+* builder/openstack: Added `image_visibility` field to specify visibility of
+ created image. [GH-4283]
+* builder/openstack: Automatically reauth as needed. [GH-4262]
+* builder/virtualbox-ovf: Can now give a URL to an ova file. [GH-3982]
+* communicator/ssh: adds ability to download download directories and
+ wildcards, fix destination file mode (not hardcoded anymore). [GH-4210]
+* post-processor/shell-local: support spaces in script path. [GH-4144]
+* provisioner/ansible: Allow `winrm` communicator. [GH-4209]
+* provisioner/salt: Bootstrap fallback on wget if curl failed. [GH-4244]
+
+### BUG FIXES:
+
+* builder/amazon: Correctly assign key from `ssh_keypair_name` to source
+ instance. [GH-4222]
+* builder/amazon: Fix `source_ami_filter` ignores `owners`. [GH-4235]
+* builder/amazon: Fix launching spot instances in EC2 Classic [GH-4204]
+* builder/qemu: Fix issue where multiple <waitXX> commands on a single line
+ in boot_command wouldn't be parsed correctly. [GH-4269]
+* core: Unbreak glob patterns in `floppy_files`. [GH-3890]
+* post-processor/checksum: cleanup, and fix output to specified file with
+ more than one artifacts. [GH-4210]
+* post-processor/checksum: reset hash after each artifact file. [GH-4210]
+* provisioner/file: fix for directory download. [GH-4210]
+* provisioner/file: fix issue uploading multiple files to a directory,
+ mentioned in [GH-4049]. [GH-4210]
+* provisioner/shell: Treat disconnects as retryable when running cleanup. If
+ you have a reboot in your script, we'll now wait until the host is
+ available before attempting to cleanup the script. [GH-4197]
+
+## 0.12.0 (November 15, 2016)
+
+### FEATURES:
+
+* **New builder:** "cloudstack" Can create new templates for use with
+ CloudStack taking either an ISO or existing template as input. [GH-3909]
+* **New builder:** "profitbricks" Builder for creating images in the
+ ProfitBricks cloud. [GH-3660]
+* **New builder:** "amazon-ebsvolume" Can create Amazon EBS volumes which are
+ preinitialized with a filesystem and data. [GH-4088]
+
+
+### IMPROVEMENTS:
+
+* builder/amazon: Allow polling delay override with `AWS_POLL_DELAY_SECONDS`.
+ [GH-4083]
+* builder/amazon: Allow use of local SSH Agent. [GH-4050]
+* builder/amazon: Dynamic source AMI [GH-3817]
+* builder/amazon: Show AMI ID found when using `source_ami_filter`. [GH-4096]
+* builder/googlecompute: Support `ssh_private_key_file` in communicator.
+ [GH-4101]
+* builder/googlecompute: Support custom scopes. [GH-4043]
+* command/push: Fix variable pushes to Atlas. Still needs Atlas server to be
+ updated before the issue will be fixed completely. [GH-4089]
+* communicator/ssh: Improved SSH upload performance. [GH-3940]
+* contrib/azure-setup.sh: Support for azure-cli 0.10.7. [GH-4133]
+* docs: Fix command line variable docs. [GH-4143]
+* post-processor/vagrant: Fixed inconsistency between vagrant-libvirt driver
+ and packer QEMU accelerator. [GH-4104]
+* provisioner/ansible: Move info messages to log [GH-4123]
+* provisioner/puppet: Add `puppet_bin_dir` option. [GH-4014]
+* provisioner/salt: Add `salt_call_args` option. [GH-4158]
+
+### BUG FIXES:
+
+* builder/amazon: Fixed an error where we wouldn't fail the build even if we
+ timed out waiting for the temporary security group to become available.
+ [GH-4099]
+* builder/amazon: Properly cleanup temporary key pairs. [GH-4080]
+* builder/google: Fix issue where we'd hang waiting for a startup script
+ which doesn't exist. [GH-4102]
+* builder/qemu: Fix keycodes for ctrl, shift and alt keys. [GH-4115]
+* builder/vmware: Fix keycodes for ctrl, shift and alt keys. [GH-4115]
+* builder/vmware: Fixed build error when shutting down. [GH-4041]
+* common/step_create_floppy: Fixed support for 1.44MB floppies on Windows.
+ [GH-4135]
+* post-processor/googlecompute-export: Fixes scopes. [GH-4147]
+* provisioner/powershell: Reverted [GH-3371] fixes quoting issue. [GH-4069]
+* scripts: Fix build under Windows for go 1.5. [GH-4142]
+
+## 0.11.0 (October 21, 2016)
+
+### BACKWARDS INCOMPATIBILITIES:
+
+* VNC and VRDP-like features in VirtualBox, VMware, and QEMU now configurable
+ but bind to 127.0.0.1 by default to improve security. See the relevant
+ builder docs for more info.
+* Docker builder requires Docker > 1.3
+* provisioner/chef-solo: default staging directory renamed to
+ `packer-chef-solo`. [GH-3971]
+
+### FEATURES:
+
+* **New Checksum post-processor**: Create a checksum file from your build
+ artifacts as part of your build. [GH-3492] [GH-3790]
+* **New build flag** `-on-error` to allow inspection and keeping artifacts on
+ builder errors. [GH-3885]
+* **New Google Compute Export post-processor**: exports an image from a Packer
+ googlecompute builder run and uploads it to Google Cloud Storage.
+ [GH-3760]
+* **New Manifest post-processor**: writes metadata about packer's output
+ artifacts data to a JSON file. [GH-3651]
+
+
+### IMPROVEMENTS:
+
+* builder/amazon: Added `disable_stop_instance` option to prevent automatic
+ shutdown when the build is complete. [GH-3352]
+* builder/amazon: Added `shutdown_behavior` option to support `stop` or
+ `terminate` at the end of the build. [GH-3556]
+* builder/amazon: Added `skip_region_validation` option to allow newer or
+ custom AWS regions. [GH-3598]
+* builder/amazon: Added `us-east-2` and `ap-south-1` regions. [GH-4021]
+ [GH-3663]
+* builder/amazon: Support building from scratch with amazon-chroot builder.
+ [GH-3855] [GH-3895]
+* builder/amazon: Support create an AMI with an `encrypt_boot` volume.
+ [GH-3382]
+* builder/azure: Add `os_disk_size_gb`. [GH-3995]
+* builder/azure: Add location to setup script. [GH-3803]
+* builder/azure: Allow user to set custom data. [GH-3996]
+* builder/azure: Made `tenant_id` optional. [GH-3643]
+* builder/azure: Now pre-validates `capture_container_name` and
+ `capture_name_prefix` [GH-3537]
+* builder/azure: Removed superfluous polling code for deployments. [GH-3638]
+* builder/azure: Support for a user defined VNET. [GH-3683]
+* builder/azure: Support for custom images. [GH-3575]
+* builder/azure: tag all resources. [GH-3764]
+* builder/digitalocean: Added `user_data_file` support. [GH-3933]
+* builder/digitalocean: Fixes timeout waiting for snapshot. [GH-3868]
+* builder/digitalocean: Use `state_timeout` for unlock and off transitions.
+ [GH-3444]
+* builder/docker: Improved support for Docker pull from Amazon ECR. [GH-3856]
+* builder/google: Add `-force` option to delete old image before creating new
+ one. [GH-3918]
+* builder/google: Add image license metadata. [GH-3873]
+* builder/google: Added support for `image_family` [GH-3531]
+* builder/google: Added support for startup scripts. [GH-3639]
+* builder/google: Create passwords for Windows instances. [GH-3932]
+* builder/google: Enable to select NVMe images. [GH-3338]
+* builder/google: Signal that startup script fished via metadata. [GH-3873]
+* builder/google: Use gcloud application default credentials. [GH-3655]
+* builder/google: provision VM without external IP address. [GH-3774]
+* builder/null: Can now be used with WinRM. [GH-2525]
+* builder/openstack: Added support for `ssh_password` instead of generating
+ ssh keys. [GH-3976]
+* builder/parallels: Add support for ctrl, shift and alt keys in
+ `boot_command`. [GH-3767]
+* builder/parallels: Copy directories recursively with `floppy_dirs`.
+ [GH-2919]
+* builder/parallels: Now pauses between `boot_command` entries when running
+ with `-debug` [GH-3547]
+* builder/parallels: Support future versions of Parallels by using the latest
+ driver. [GH-3673]
+* builder/qemu: Add support for ctrl, shift and alt keys in `boot_command`.
+ [GH-3767]
+* builder/qemu: Added `vnc_bind_address` option. [GH-3574]
+* builder/qemu: Copy directories recursively with `floppy_dirs`. [GH-2919]
+* builder/qemu: Now pauses between `boot_command` entries when running with
+ `-debug` [GH-3547]
+* builder/qemu: Specify disk format when starting qemu. [GH-3888]
+* builder/virtualbox-iso: Added `hard_drive_nonrotational` and
+ `hard_drive_discard` options to enable trim/discard. [GH-4013]
+* builder/virtualbox-iso: Added `keep_registered` option to skip cleaning up
+ the image. [GH-3954]
+* builder/virtualbox: Add support for ctrl, shift and alt keys in
+ `boot_command`. [GH-3767]
+* builder/virtualbox: Added `post_shutdown_delay` option to wait after
+ shutting down to prevent issues removing floppy drive. [GH-3952]
+* builder/virtualbox: Added `vrdp_bind_address` option. [GH-3566]
+* builder/virtualbox: Copy directories recursively with `floppy_dirs`.
+ [GH-2919]
+* builder/virtualbox: Now pauses between `boot_command` entries when running
+ with `-debug` [GH-3542]
+* builder/vmware-vmx: Added `tools_upload_flavor` and `tools_upload_path` to
+ docs.
+* builder/vmware: Add support for ctrl, shift and alt keys in `boot_command`.
+ [GH-3767]
+* builder/vmware: Added `vnc_bind_address` option. [GH-3565]
+* builder/vmware: Adds passwords for VNC. [GH-2325]
+* builder/vmware: Copy directories recursively with `floppy_dirs`. [GH-2919]
+* builder/vmware: Handle connection to VM with more than one NIC on ESXi
+ [GH-3347]
+* builder/vmware: Now paused between `boot_command` entries when running with
+ `-debug` [GH-3542]
+* core: Supress plugin discovery from plugins. [GH-4002]
+* core: Test floppy disk files actually exist. [GH-3756]
+* core: setting `PACKER_LOG=0` now disables logging. [GH-3964]
+* post-processor/amazon-import: Support `ami_name` for naming imported AMI.
+ [GH-3941]
+* post-processor/compress: Added support for bgzf compression. [GH-3501]
+* post-processor/docker: Improved support for Docker push to Amazon ECR.
+ [GH-3856]
+* post-processor/docker: Preserve tags when running docker push. [GH-3631]
+* post-processor/vagrant: Added vsphere-esx hosts to supported machine types.
+ [GH-3967]
+* provisioner/ansible-local: Support for ansible-galaxy. [GH-3350] [GH-3836]
+* provisioner/ansible: Improved logging and error handling. [GH-3477]
+* provisioner/ansible: Support scp. [GH-3861]
+* provisioner/chef: Added `knife_command` option and added a correct default
+ value for Windows. [GH-3622]
+* provisioner/chef: Installs 64bit chef on Windows if available. [GH-3848]
+* provisioner/file: Now makes destination directory. [GH-3692]
+* provisioner/puppet: Added `execute_command` option. [GH-3614]
+* provisioner/salt: Added `custom_state` to specify state to run instead of
+ `highstate`. [GH-3776]
+* provisioner/shell: Added `expect_disconnect` flag to fail if remote
+ unexpectedly disconnects. [GH-4034]
+* scripts: Added `help` target to Makefile. [GH-3290]
+* vendor: Moving from Godep to govendor. See `CONTRIBUTING.md` for details.
+ [GH-3956]
+* website: code examples now use inconsolata. Improve code font rendering on
+ linux.
+
+### BUG FIXES:
+
+* builder/amazon: Add 0.5 cents to discovered spot price. [GH-3662]
+* builder/amazon: Allow using `ssh_private_key_file` and `ssh_password`.
+ [GH-3953]
+* builder/amazon: Fix packer crash when waiting for SSH. [GH-3865]
+* builder/amazon: Honor ssh_private_ip flag in EC2-Classic. [GH-3752]
+* builder/amazon: Properly clean up EBS volumes on failure. [GH-3789]
+* builder/amazon: Use `temporary_key_pair_name` when specified. [GH-3739]
+* builder/amazon: retry creating tags on images since the images might take
+ some time to become available. [GH-3938]
+* builder/azure: Fix authorization setup script failing to creating service
+ principal. [GH-3812]
+* builder/azure: check for empty resource group. [GH-3606]
+* builder/azure: fix token validity test. [GH-3609]
+* builder/docker: Fix file provisioner dotfile matching. [GH-3800]
+* builder/docker: fix docker builder with ansible provisioner. [GH-3476]
+* builder/qemu: Don't fail on communicator set to `none`. [GH-3681]
+* builder/qemu: Make `ssh_host_port_max` an inclusive bound. [GH-2784]
+* builder/virtualbox: Make `ssh_host_port_max` an inclusive bound. [GH-2784]
+* builder/virtualbox: Respect `ssh_host` [GH-3617]
+* builder/vmware: Do not add remotedisplay.vnc.ip to VMX data on ESXi
+ [GH-3740]
+* builder/vmware: Don't check for poweron errors on ESXi. [GH-3195]
+* builder/vmware: Re-introduce case sensitive VMX keys. [GH-2707]
+* builder/vmware: Respect `ssh_host`/`winrm_host` on ESXi. [GH-3738]
+* command/push: Allows dot (`.`) in image names. [GH-3937]
+* common/iso_config: fix potential panic when iso checksum url was given but
+ not the iso url. [GH-4004]
+* communicator/ssh: fixed possible panic when reconnecting fails. [GH-4008]
+* communicator/ssh: handle error case where server closes the connection but
+ doesn't give us an error code. [GH-3966]
+* post-processor/shell-local: Do not set execute bit on artifact file.
+ [GH-3505]
+* post-processor/vsphere: Fix upload failures with vsphere. [GH-3321]
+* provisioner/ansible: Properly set host key checking even when a custom ENV
+ is specified. [GH-3568]
+* provisioner/file: Fix directory download. [GH-3899]
+* provisioner/powershell: fixed issue with setting environment variables.
+ [GH-2785]
+* website: improved rendering on iPad. [GH-3780]
+
+## 0.10.2 (September 20, 2016)
+
+### BUG FIXES:
+
+* Rebuilding with OS X Sierra and go 1.7.1 to fix bug in Sierra
+
+## 0.10.1 (May 7, 2016)
+
+### FEATURES:
+
+* `azure-arm` builder: Can now build Windows images, and supports additional
+ configuration. Please refer to the documentation for details.
+
+### IMPROVEMENTS:
+
+* core: Added support for `ATLAS_CAFILE` and `ATLAS_CAPATH` [GH-3494]
+* builder/azure: Improved build cancellation and cleanup of partially-
+ provisioned resources. [GH-3461]
+* builder/azure: Improved logging. [GH-3461]
+* builder/azure: Added support for US Government and China clouds. [GH-3461]
+* builder/azure: Users may now specify an image version. [GH-3461]
+* builder/azure: Added device login. [GH-3461]
+* builder/docker: Added `privileged` build option. [GH-3475]
+* builder/google: Packer now identifies its version to the service. [GH-3465]
+* provisioner/shell: Added `remote_folder` and `remote_file` options
+ [GH-3462]
+* post-processor/compress: Added support for `bgzf` format and added
+ `format` option. [GH-3501]
+
+### BUG FIXES:
+
+* core: Fix hang after pressing enter key in `-debug` mode. [GH-3346]
+* provisioner/chef: Use custom values for remote validation key path
+ [GH-3468]
+
+## 0.10.0 (March 14, 2016)
+
+### BACKWARDS INCOMPATIBILITIES:
+
+* Building Packer now requires go >= 1.5 (>= 1.6 is recommended). If you want
+ to continue building with go 1.4 you can remove the `azurearmbuilder` line
+ from `command/plugin.go`.
+
+### FEATURES:
+
+* **New `azure-arm` builder**: Build virtual machines in Azure Resource
+ Manager
+
+### IMPROVEMENTS:
+
+* builder/google: Added support for `disk_type` [GH-2830]
+* builder/openstack: Added support for retrieving the Administrator password
+ when using WinRM if no `winrm_password` is set. [GH-3209]
+* provisioner/ansible: Added the `empty_groups` parameter. [GH-3232]
+* provisioner/ansible: Added the `user` parameter. [GH-3276]
+* provisioner/ansible: Don't use deprecated ssh option with Ansible 2.0
+ [GH-3291]
+* provisioner/puppet-masterless: Add `ignore_exit_codes` parameter. [GH-3349]
+
+### BUG FIXES:
+
+* builders/parallels: Handle `output_directory` containing `.` and `..`
+ [GH-3239]
+* provisioner/ansible: os.Environ() should always be passed to the ansible
+ command. [GH-3274]
+
+## 0.9.0 (February 19, 2016)
+
+### BACKWARDS INCOMPATIBILITIES:
+
+* Packer now ships as a single binary, including plugins. If you install packer
+ 0.9.0 over a previous packer installation, **you must delete all of the
+ packer-* plugin files** or packer will load out-of-date plugins from disk.
+* Release binaries are now provided via <https://releases.hashicorp.com>.
+* Packer 0.9.0 is now built with Go 1.6.
+* core: Plugins that implement the Communicator interface must now implement
+ a DownloadDir method. [GH-2618]
+* builder/amazon: Inline `user_data` for EC2 is now base64 encoded
+ automatically. [GH-2539]
+* builder/parallels: `parallels_tools_host_path` and `guest_os_distribution`
+ have been replaced by `guest_os_type`; use `packer fix` to update your
+ templates. [GH-2751]
+
+### FEATURES:
+
+* **Chef on Windows**: The chef provisioner now has native support for
+ Windows using Powershell and WinRM. [GH-1215]
+* **New `vmware-esxi` feature**: Packer can now export images from vCloud or
+ vSphere during the build. [GH-1921]
+* **New Ansible Provisioner**: `ansible` provisioner supports remote
+ provisioning to keep your build image cleaner. [GH-1969]
+* **New Amazon Import post-processor**: `amazon-import` allows you to upload an
+ OVA-based VM to Amazon EC2. [GH-2962]
+* **Shell Local post-processor**: `shell-local` allows you to run shell
+ commands on the host after a build has completed for custom packaging or
+ publishing of your artifacts. [GH-2706]
+* **Artifice post-processor**: Override packer artifacts during post-
+ processing. This allows you to extract artifacts from a packer builder and
+ use them with other post-processors like compress, docker, and Atlas.
+
+### IMPROVEMENTS:
+
+* core: Packer plugins are now compiled into the main binary, reducing file
+ size and build times, and making packer easier to install. The overall
+ plugin architecture has not changed and third-party plugins can still be
+ loaded from disk. Please make sure your plugins are up-to-date! [GH-2854]
+* core: Packer now indicates line numbers for template parse errors. [GH-2742]
+* core: Scripts are executed via `/usr/bin/env bash` instead of `/bin/bash`
+ for broader compatibility. [GH-2913]
+* core: `target_path` for builder downloads can now be specified. [GH-2600]
+* core: WinRM communicator now supports HTTPS protocol. [GH-3061]
+* core: Template syntax errors now show line, column, offset. [GH-3180]
+* core: SSH communicator now supports downloading directories. [GH-2618]
+* builder/amazon: Add support for `ebs_optimized` [GH-2806]
+* builder/amazon: You can now specify `0` for `spot_price` to switch to on
+ demand instances. [GH-2845]
+* builder/amazon: Added `ap-northeast-2` (Seoul) [GH-3056]
+* builder/amazon: packer will try to derive the AZ if only a subnet is
+ specified. [GH-3037]
+* builder/digitalocean: doubled instance wait timeouts to power off or
+ shutdown (now 4 minutes) and to complete a snapshot (now 20 minutes)
+ [GH-2939]
+* builder/google: `account_file` can now be provided as a JSON string
+ [GH-2811]
+* builder/google: added support for `preemptible` instances. [GH-2982]
+* builder/google: added support for static external IPs via `address` option
+ [GH-3030]
+* builder/openstack: added retry on WaitForImage 404. [GH-3009]
+* builder/openstack: Can specify `source_image_name` instead of the ID
+ [GH-2577]
+* builder/openstack: added support for SSH over IPv6. [GH-3197]
+* builder/parallels: Improve support for Parallels 11. [GH-2662]
+* builder/parallels: Parallels disks are now compacted by default. [GH-2731]
+* builder/parallels: Packer will look for Parallels in
+ `/Applications/Parallels Desktop.app` if it is not detected automatically
+ [GH-2839]
+* builder/qemu: qcow2 images are now compacted by default. [GH-2748]
+* builder/qemu: qcow2 images can now be compressed. [GH-2748]
+* builder/qemu: Now specifies `virtio-scsi` by default. [GH-2422]
+* builder/qemu: Now checks for version-specific options. [GH-2376]
+* builder/qemu: Can now bypass disk cache using `iso_skip_cache` [GH-3105]
+* builder/qemu: `<wait>` in `boot_command` now accepts an arbitrary duration
+ like <wait1m30s> [GH-3129]
+* builder/qemu: Expose `{{ .SSHHostPort }}` in templates. [GH-2884]
+* builder/virtualbox: Added VRDP for debugging. [GH-3188]
+* builder/vmware-esxi: Added private key auth for remote builds via
+ `remote_private_key_file` [GH-2912]
+* post-processor/atlas: Added support for compile ID. [GH-2775]
+* post-processor/docker-import: Can now import Artifice artifacts. [GH-2718]
+* provisioner/chef: Added `encrypted_data_bag_secret_path` option. [GH-2653]
+* provisioner/puppet: Added the `extra_arguments` parameter. [GH-2635]
+* provisioner/salt: Added `no_exit_on_failure`, `log_level`, and improvements
+ to salt command invocation. [GH-2660]
+
+### BUG FIXES:
+
+* core: Random number generator is now seeded. [GH-2640]
+* core: Packer should now have a lot less race conditions. [GH-2824]
+* builder/amazon: The `no_device` option for block device mappings is now handled correctly. [GH-2398]
+* builder/amazon: AMI name validation now matches Amazon's spec. [GH-2774]
+* builder/amazon: Use snapshot size when volume size is unspecified. [GH-2480]
+* builder/amazon: Pass AccessKey and SecretKey when uploading bundles for
+ instance-backed AMIs. [GH-2596]
+* builder/parallels: Added interpolation in `prlctl_post` [GH-2828]
+* builder/vmware: `format` option is now read correctly. [GH-2892]
+* builder/vmware-esxi: Correct endless loop in destroy validation logic
+ [GH-2911]
+* provisioner/shell: No longer leaves temp scripts behind. [GH-1536]
+* provisioner/winrm: Now waits for reboot to complete before continuing with provisioning. [GH-2568]
+* post-processor/artifice: Fix truncation of files downloaded from Docker. [GH-2793]
+
+
+## 0.8.6 (Aug 22, 2015)
+
+### IMPROVEMENTS:
+
+* builder/docker: Now supports Download so it can be used with the file
+ provisioner to download a file from a container. [GH-2585]
+* builder/docker: Now verifies that the artifact will be used before the build
+ starts, unless the `discard` option is specified. This prevent failures
+ after the build completes. [GH-2626]
+* post-processor/artifice: Now supports glob-like syntax for filenames. [GH-2619]
+* post-processor/vagrant: Like the compress post-processor, vagrant now uses a
+ parallel gzip algorithm to compress vagrant boxes. [GH-2590]
+
+### BUG FIXES:
+
+* core: When `iso_url` is a local file and the checksum is invalid, the local
+ file will no longer be deleted. [GH-2603]
+* builder/parallels: Fix interpolation in `parallels_tools_guest_path` [GH-2543]
+
+## 0.8.5 (Aug 10, 2015)
+
+### FEATURES:
+
+* **[Beta]** Artifice post-processor: Override packer artifacts during post-
+ processing. This allows you to extract artifacts from a packer builder
+ and use them with other post-processors like compress, docker, and Atlas.
+
+### IMPROVEMENTS:
+
+* Many docs have been updated and corrected; big thanks to our contributors!
+* builder/openstack: Add debug logging for IP addresses used for SSH. [GH-2513]
+* builder/openstack: Add option to use existing SSH keypair. [GH-2512]
+* builder/openstack: Add support for Glance metadata. [GH-2434]
+* builder/qemu and builder/vmware: Packer's VNC connection no longer asks for
+ an exclusive connection. [GH-2522]
+* provisioner/salt-masterless: Can now customize salt remote directories. [GH-2519]
+
+### BUG FIXES:
+
+* builder/amazon: Improve instance cleanup by storing id sooner. [GH-2404]
+* builder/amazon: Only fetch windows password when using WinRM communicator. [GH-2538]
+* builder/openstack: Support IPv6 SSH address. [GH-2450]
+* builder/openstack: Track new IP address discovered during RackConnect. [GH-2514]
+* builder/qemu: Add 100ms delay between VNC key events. [GH-2415]
+* post-processor/atlas: atlas_url configuration option works now. [GH-2478]
+* post-processor/compress: Now supports interpolation in output config. [GH-2414]
+* provisioner/powershell: Elevated runs now receive environment variables. [GH-2378]
+* provisioner/salt-masterless: Clarify error messages when we can't create or
+ write to the temp directory. [GH-2518]
+* provisioner/salt-masterless: Copy state even if /srv/salt exists already. [GH-1699]
+* provisioner/salt-masterless: Make sure /etc/salt exists before writing to it. [GH-2520]
+* provisioner/winrm: Connect to the correct port when using NAT with
+ VirtualBox / VMware. [GH-2399]
+
+## Note: 0.8.3 was pulled and 0.8.4 was skipped.
+
+## 0.8.2 (July 17, 2015)
+
+### IMPROVEMENTS:
+
+* builder/docker: Add option to use a Pty. [GH-2425]
+
+### BUG FIXES:
+
+* core: Fix crash when `min_packer_version` is specified in a template. [GH-2385]
+* builder/amazon: Fix EC2 devices being included in EBS mappings. [GH-2459]
+* builder/googlecompute: Fix default name for GCE images. [GH-2400]
+* builder/null: Fix error message with missing ssh_host. [GH-2407]
+* builder/virtualbox: Use --portcount on VirtualBox 5.x. [GH-2438]
+* provisioner/puppet: Packer now correctly handles a directory for manifest_file. [GH-2463]
+* provisioner/winrm: Fix potential crash with WinRM. [GH-2416]
+
+## 0.8.1 (July 2, 2015)
+
+### IMPROVEMENTS:
+
+* builder/amazon: When debug mode is enabled, the Windows administrator
+ password for Windows instances will be shown. [GH-2351]
+
+### BUG FIXES:
+
+* core: `min_packer_version` field in configs work. [GH-2356]
+* core: The `build_name` and `build_type` functions work in provisioners. [GH-2367]
+* core: Handle timeout in SSH handshake. [GH-2333]
+* command/build: Fix reading configuration from stdin. [GH-2366]
+* builder/amazon: Fix issue with sharing AMIs when using `ami_users` [GH-2308]
+* builder/amazon: Fix issue when using multiple Security Groups. [GH-2381]
+* builder/amazon: Fix for tag creation when creating new ec2 instance. [GH-2317]
+* builder/amazon: Fix issue with creating AMIs with multiple device mappings. [GH-2320]
+* builder/amazon: Fix failing AMI snapshot tagging when copying to other
+ regions. [GH-2316]
+* builder/amazon: Fix setting AMI launch permissions. [GH-2348]
+* builder/amazon: Fix spot instance cleanup to remove the correct request. [GH-2327]
+* builder/amazon: Fix `bundle_prefix` not interpolating `timestamp` [GH-2352]
+* builder/amazon-instance: Fix issue with creating AMIs without specifying a
+ virtualization type. [GH-2330]
+* builder/digitalocean: Fix builder using private IP instead of public IP. [GH-2339]
+* builder/google: Set default communicator settings properly. [GH-2353]
+* builder/vmware-iso: Setting `checksum_type` to `none` for ESX builds
+ now works. [GH-2323]
+* provisioner/chef: Use knife config file vs command-line params to
+ clean up nodes so full set of features can be used. [GH-2306]
+* post-processor/compress: Fixed crash in compress post-processor plugin. [GH-2311]
+
+## 0.8.0 (June 23, 2015)
+
+### BACKWARDS INCOMPATIBILITIES:
+
+* core: SSH connection will no longer request a PTY by default. This
+ can be enabled per builder.
+* builder/digitalocean: no longer supports the v1 API which has been
+ deprecated for some time. Most configurations should continue to
+ work as long as you use the `api_token` field for auth.
+* builder/digitalocean: `image`, `region`, and `size` are now required.
+* builder/openstack: auth parameters have been changed to better
+ reflect OS terminology. Existing environment variables still work.
+
+### FEATURES:
+
+* **WinRM:** You can now connect via WinRM with almost every builder.
+ See the docs for more info. [GH-2239]
+* **Windows AWS Support:** Windows AMIs can now be built without any
+ external plugins: Packer will start a Windows instance, get the
+ admin password, and can use WinRM (above) to connect through. [GH-2240]
+* **Disable SSH:** Set `communicator` to "none" in any builder to disable SSH
+ connections. Note that provisioners won't work if this is done. [GH-1591]
+* **SSH Agent Forwarding:** SSH Agent Forwarding will now be enabled
+ to allow access to remote servers such as private git repos. [GH-1066]
+* **SSH Bastion Hosts:** You can now specify a bastion host for
+ SSH access (works with all builders). [GH-387]
+* **OpenStack v3 Identity:** The OpenStack builder now supports the
+ v3 identity API.
+* **Docker builder supports SSH**: The Docker builder now supports containers
+ with SSH, just set `communicator` to "ssh" [GH-2244]
+* **File provisioner can download**: The file provisioner can now download
+ files out of the build process. [GH-1909]
+* **New config function: `build_name`**: The name of the currently running
+ build. [GH-2232]
+* **New config function: `build_type`**: The type of the currently running
+ builder. This is useful for provisioners. [GH-2232]
+* **New config function: `template_dir`**: The directory to the template
+ being built. This should be used for template-relative paths. [GH-54]
+* **New provisioner: shell-local**: Runs a local shell script. [GH-770]
+* **New provisioner: powershell**: Provision Windows machines
+ with PowerShell scripts. [GH-2243]
+* **New provisioner: windows-shell**: Provision Windows machines with
+ batch files. [GH-2243]
+* **New provisioner: windows-restart**: Restart a Windows machines and
+ wait for it to come back online. [GH-2243]
+* **Compress post-processor supports multiple algorithms:** The compress
+ post-processor now supports lz4 compression and compresses gzip in
+ parallel for much faster throughput.
+
+### IMPROVEMENTS:
+
+* core: Interrupt handling for SIGTERM signal as well. [GH-1858]
+* core: HTTP downloads support resuming. [GH-2106]
+ * builder/*: Add `ssh_handshake_attempts` to configure the number of
+ handshake attempts done before failure. [GH-2237]
+* builder/amazon: Add `force_deregister` option for automatic AMI
+ deregistration. [GH-2221]
+* builder/amazon: Now applies tags to EBS snapshots. [GH-2212]
+* builder/amazon: Clean up orphaned volumes from Source AMIs. [GH-1783]
+* builder/amazon: Support custom keypairs. [GH-1837]
+* builder/amazon-chroot: Can now resize the root volume of the resulting
+ AMI with the `root_volume_size` option. [GH-2289]
+* builder/amazon-chroot: Add `mount_options` configuration option for providing
+ options to the `mount` command. [GH-2296]
+* builder/digitalocean: Save SSH key to pwd if debug mode is on. [GH-1829]
+* builder/digitalocean: User data support. [GH-2113]
+* builder/googlecompute: Option to use internal IP for connections. [GH-2152]
+* builder/parallels: Support Parallels Desktop 11. [GH-2199]
+* builder/openstack: Add `rackconnect_wait` for Rackspace customers to wait for
+ RackConnect data to appear
+* builder/openstack: Add `ssh_interface` option for rackconnect for users that
+ have prohibitive firewalls
+* builder/openstack: Flavor names can be used as well as refs
+* builder/openstack: Add `availability_zone` [GH-2016]
+* builder/openstack: Machine will be stopped prior to imaging if the
+ cluster supports the `startstop` extension. [GH-2223]
+* builder/openstack: Support for user data. [GH-2224]
+* builder/qemu: Default accelerator to "tcg" on Windows. [GH-2291]
+* builder/virtualbox: Added option: `ssh_skip_nat_mapping` to skip the
+ automatic port forward for SSH and to use the guest port directly. [GH-1078]
+* builder/virtualbox: Added SCSI support
+* builder/vmware: Support for additional disks. [GH-1382]
+* builder/vmware: Can now customize the template used for adding disks. [GH-2254]
+* command/fix: After fixing, the template is validated. [GH-2228]
+* command/push: Add `-name` flag for specifying name from CLI. [GH-2042]
+* command/push: Push configuration in templates supports variables. [GH-1861]
+* post-processor/docker-save: Can be chained. [GH-2179]
+* post-processor/docker-tag: Support `force` option. [GH-2055]
+* post-processor/docker-tag: Can be chained. [GH-2179]
+* post-processor/vsphere: Make more fields optional, support empty
+ resource pools. [GH-1868]
+* provisioner/puppet-masterless: `working_directory` option. [GH-1831]
+* provisioner/puppet-masterless: `packer_build_name` and
+ `packer_build_type` are default facts. [GH-1878]
+* provisioner/puppet-server: `ignore_exit_codes` option added. [GH-2280]
+
+### BUG FIXES:
+
+* core: Fix potential panic for post-processor plugin exits. [GH-2098]
+* core: `PACKER_CONFIG` may point to a non-existent file. [GH-2226]
+* builder/amazon: Allow spaces in AMI names when using `clean_ami_name` [GH-2182]
+* builder/amazon: Remove deprecated ec2-upload-bundle parameter. [GH-1931]
+* builder/amazon: Use IAM Profile to upload bundle if provided. [GH-1985]
+* builder/amazon: Use correct exit code after SSH authentication failed. [GH-2004]
+* builder/amazon: Retry finding created instance for eventual
+ consistency. [GH-2129]
+* builder/amazon: If no AZ is specified, use AZ chosen automatically by
+ AWS for spot instance. [GH-2017]
+* builder/amazon: Private key file (only available in debug mode)
+ is deleted on cleanup. [GH-1801]
+* builder/amazon: AMI copy won't copy to the source region. [GH-2123]
+* builder/amazon: Validate AMI doesn't exist with name prior to build. [GH-1774]
+* builder/amazon: Improved retry logic around waiting for instances. [GH-1764]
+* builder/amazon: Fix issues with creating Block Devices. [GH-2195]
+* builder/amazon/chroot: Retry waiting for disk attachments. [GH-2046]
+* builder/amazon/chroot: Only unmount path if it is mounted. [GH-2054]
+* builder/amazon/instance: Use `-i` in sudo commands so PATH is inherited. [GH-1930]
+* builder/amazon/instance: Use `--region` flag for bundle upload command. [GH-1931]
+* builder/digitalocean: Wait for droplet to unlock before changing state,
+ should lower the "pending event" errors.
+* builder/digitalocean: Ignore invalid fields from the ever-changing v2 API
+* builder/digitalocean: Private images can be used as a source. [GH-1792]
+* builder/docker: Fixed hang on prompt while copying script
+* builder/docker: Use `docker exec` for newer versions of Docker for
+ running scripts. [GH-1993]
+* builder/docker: Fix crash that could occur at certain timed ctrl-c. [GH-1838]
+* builder/docker: validate that `export_path` is not a directory. [GH-2105]
+* builder/google: `ssh_timeout` is respected. [GH-1781]
+* builder/openstack: `ssh_interface` can be used to specify the interface
+ to retrieve the SSH IP from. [GH-2220]
+* builder/qemu: Add `disk_discard` option. [GH-2120]
+* builder/qemu: Use proper SSH port, not hardcoded to 22. [GH-2236]
+* builder/qemu: Find unused SSH port if SSH port is taken. [GH-2032]
+* builder/virtualbox: Bind HTTP server to IPv4, which is more compatible with
+ OS installers. [GH-1709]
+* builder/virtualbox: Remove the floppy controller in addition to the
+ floppy disk. [GH-1879]
+* builder/virtualbox: Fixed regression where downloading ISO without a
+ ".iso" extension didn't work. [GH-1839]
+* builder/virtualbox: Output dir is verified at runtime, not template
+ validation time. [GH-2233]
+* builder/virtualbox: Find unused SSH port if SSH port is taken. [GH-2032]
+* builder/vmware: Add 100ms delay between keystrokes to avoid subtle
+ timing issues in most cases. [GH-1663]
+* builder/vmware: Bind HTTP server to IPv4, which is more compatible with
+ OS installers. [GH-1709]
+* builder/vmware: Case-insensitive match of MAC address to find IP. [GH-1989]
+* builder/vmware: More robust IP parsing from ifconfig output. [GH-1999]
+* builder/vmware: Nested output directories for ESXi work. [GH-2174]
+* builder/vmware: Output dir is verified at runtime, not template
+ validation time. [GH-2233]
+* command/fix: For the `virtualbox` to `virtualbox-iso` builder rename,
+ provisioner overrides are now also fixed. [GH-2231]
+* command/validate: don't crash for invalid builds. [GH-2139]
+* post-processor/atlas: Find common archive prefix for Windows. [GH-1874]
+* post-processor/atlas: Fix index out of range panic. [GH-1959]
+* post-processor/vagrant-cloud: Fixed failing on response
+* post-processor/vagrant-cloud: Don't delete version on error. [GH-2014]
+* post-processor/vagrant-cloud: Retry failed uploads a few times
+* provisioner/chef-client: Fix permissions issues on default dir. [GH-2255]
+* provisioner/chef-client: Node cleanup works now. [GH-2257]
+* provisioner/puppet-masterless: Allow manifest_file to be a directory
+* provisioner/salt-masterless: Add `--retcode-passthrough` to salt-call
+* provisioner/shell: chmod executable script to 0755, not 0777. [GH-1708]
+* provisioner/shell: inline commands failing will fail the provisioner. [GH-2069]
+* provisioner/shell: single quotes in env vars are escaped. [GH-2229]
+* provisioner/shell: Temporary file is deleted after run. [GH-2259]
+* provisioner/shell: Randomize default script name to avoid strange
+ race issues from Windows. [GH-2270]
+
+## 0.7.5 (December 9, 2014)
+
+### FEATURES:
+
+* **New command: `packer push`**: Push template and files to HashiCorp's
+ Atlas for building your templates automatically.
+* **New post-processor: `atlas`**: Send artifact to HashiCorp's Atlas for
+ versioning and storing artifacts. These artifacts can then be queried
+ using the API, Terraform, etc.
+
+### IMPROVEMENTS:
+
+* builder/googlecompute: Support for ubuntu-os-cloud project
+* builder/googlecompute: Support for OAuth2 to avoid client secrets file
+* builder/googlecompute: GCE image from persistent disk instead of tarball
+* builder/qemu: Checksum type "none" can be used
+* provisioner/chef: Generate a node name if none available
+* provisioner/chef: Added ssl_verify_mode configuration
+
+### BUG FIXES:
+
+* builder/parallels: Fixed attachment of ISO to cdrom device
+* builder/parallels: Fixed boot load ordering
+* builder/digitalocean: Fixed decoding of size
+* builder/digitalocean: Fixed missing content-type header in request
+* builder/digitalocean: Fixed use of private IP
+* builder/digitalocean: Fixed the artifact ID generation
+* builder/vsphere: Fixed credential escaping
+* builder/qemu: Fixed use of CDROM with disk_image
+* builder/aws: Fixed IP address for SSH in VPC
+* builder/aws: Fixed issue with multiple block devices
+* builder/vmware: Upload VMX to ESX5 after editing
+* communicator/docker: Fix handling of symlinks during upload
+* provisioner/chef: Fixed use of sudo in some cases
+* core: Fixed build name interpolation
+* postprocessor/vagrant: Fixed check for Vagrantfile template
+
+## 0.7.2 (October 28, 2014)
+
+### FEATURES:
+
+* builder/digitalocean: API V2 support. [GH-1463]
+* builder/parallels: Don't depend on _prl-utils_. [GH-1499]
+
+### IMPROVEMENTS:
+
+* builder/amazon/all: Support new AWS Frankfurt region.
+* builder/docker: Allow remote `DOCKER_HOST`, which works as long as
+ volumes work. [GH-1594]
+* builder/qemu: Can set cache mode for main disk. [GH-1558]
+* builder/qemu: Can build from pre-existing disk. [GH-1342]
+* builder/vmware: Can specify path to Fusion installation with environmental
+ variable `FUSION_APP_PATH`. [GH-1552]
+* builder/vmware: Can specify the HW version for the VMX. [GH-1530]
+* builder/vmware/esxi: Will now cache ISOs/floppies remotely. [GH-1479]
+* builder/vmware/vmx: Source VMX can have a disk connected via SATA. [GH-1604]
+* post-processors/vagrant: Support Qemu (libvirt) boxes. [GH-1330]
+* post-processors/vagrantcloud: Support self-hosted box URLs.
+
+### BUG FIXES:
+
+* core: Fix loading plugins from pwd. [GH-1521]
+* builder/amazon: Prefer token in config if given. [GH-1544]
+* builder/amazon/all: Extended timeout for waiting for AMI. [GH-1533]
+* builder/virtualbox: Can read VirtualBox version on FreeBSD. [GH-1570]
+* builder/virtualbox: More robust reading of guest additions URL. [GH-1509]
+* builder/vmware: Always remove floppies/drives. [GH-1504]
+* builder/vmware: Wait some time so that post-VMX update aren't
+ overwritten. [GH-1504]
+* builder/vmware/esxi: Retry power on if it fails. [GH-1334]
+* builder/vmware-vmx: Fix issue with order of boot command support. [GH-1492]
+* builder/amazon: Extend timeout and allow user override. [GH-1533]
+* builder/parallels: Ignore 'The fdd0 device does not exist' [GH-1501]
+* builder/parallels: Rely on Cleanup functions to detach devices. [GH-1502]
+* builder/parallels: Create VM without hdd and then add it later. [GH-1548]
+* builder/parallels: Disconnect cdrom0. [GH-1605]
+* builder/qemu: Don't use `-redir` flag anymore, replace with
+ `hostfwd` options. [GH-1561]
+* builder/qemu: Use `pc` as default machine type instead of `pc-1.0`.
+* providers/aws: Ignore transient network errors. [GH-1579]
+* provisioner/ansible: Don't buffer output so output streams in. [GH-1585]
+* provisioner/ansible: Use inventory file always to avoid potentially
+ deprecated feature. [GH-1562]
+* provisioner/shell: Quote environmental variables. [GH-1568]
+* provisioner/salt: Bootstrap over SSL. [GH-1608]
+* post-processors/docker-push: Work with docker-tag artifacts. [GH-1526]
+* post-processors/vsphere: Append "/" to object address. [GH-1615]
+
+## 0.7.1 (September 10, 2014)
+
+### FEATURES:
+
+* builder/vmware: VMware Fusion Pro 7 is now supported. [GH-1478]
+
+### BUG FIXES:
+
+* core: SSH will connect slightly faster if it is ready immediately.
+* provisioner/file: directory uploads no longer hang. [GH-1484]
+* provisioner/file: fixed crash on large files. [GH-1473]
+* scripts: Windows executable renamed to packer.exe. [GH-1483]
+
+## 0.7.0 (September 8, 2014)
+
+### BACKWARDS INCOMPATIBILITIES:
+
+* The authentication configuration for Google Compute Engine has changed.
+ The new method is much simpler, but is not backwards compatible.
+ `packer fix` will _not_ fix this. Please read the updated GCE docs.
+
+### FEATURES:
+
+* **New Post-Processor: `compress`** - Gzip compresses artifacts with files.
+* **New Post-Processor: `docker-save`** - Save an image. This is similar to
+ export, but preserves the image hierarchy.
+* **New Post-Processor: `docker-tag`** - Tag a created image.
+* **New Template Functions: `upper`, `lower`** - See documentation for
+ more details.
+* core: Plugins are automatically discovered if they're named properly.
+ Packer will look in the PWD and the directory with `packer` for
+ binaries named `packer-TYPE-NAME`.
+* core: Plugins placed in `~/.packer.d/plugins` are now automatically
+ discovered.
+* builder/amazon: Spot instances can now be used to build EBS backed and
+ instance store images. [GH-1139]
+* builder/docker: Images can now be committed instead of exported. [GH-1198]
+* builder/virtualbox-ovf: New `import_flags` setting can be used to add
+ new command line flags to `VBoxManage import` to allow things such
+ as EULAs to be accepted. [GH-1383]
+* builder/virtualbox-ovf: Boot commands and the HTTP server are supported.
+ [GH-1169]
+* builder/vmware: VMware Player 6 is now supported. [GH-1168]
+* builder/vmware-vmx: Boot commands and the HTTP server are supported.
+ [GH-1169]
+
+### IMPROVEMENTS:
+
+* core: `isotime` function can take a format. [GH-1126]
+* builder/amazon/all: `AWS_SECURITY_TOKEN` is read and can also be
+ set with the `token` configuration. [GH-1236]
+* builder/amazon/all: Can force SSH on the private IP address with
+ `ssh_private_ip`. [GH-1229]
+* builder/amazon/all: String fields in device mappings can use variables. [GH-1090]
+* builder/amazon-instance: EBS AMIs can be used as a source. [GH-1453]
+* builder/digitalocean: Can set API URL endpoint. [GH-1448]
+* builder/digitalocean: Region supports variables. [GH-1452]
+* builder/docker: Can now specify login credentials to pull images.
+* builder/docker: Support mounting additional volumes. [GH-1430]
+* builder/parallels/all: Path to tools ISO is calculated automatically. [GH-1455]
+* builder/parallels-pvm: `reassign_mac` option to choose whether or not
+ to generate a new MAC address. [GH-1461]
+* builder/qemu: Can specify "none" acceleration type. [GH-1395]
+* builder/qemu: Can specify "tcg" acceleration type. [GH-1395]
+* builder/virtualbox/all: `iso_interface` option to mount ISO with SATA. [GH-1200]
+* builder/vmware-vmx: Proper `floppy_files` support. [GH-1057]
+* command/build: Add `-color=false` flag to disable color. [GH-1433]
+* post-processor/docker-push: Can now specify login credentials. [GH-1243]
+* provisioner/chef-client: Support `chef_environment`. [GH-1190]
+
+### BUG FIXES:
+
+* core: nicer error message if an encrypted private key is used for
+ SSH. [GH-1445]
+* core: Fix crash that could happen with a well timed double Ctrl-C.
+ [GH-1328] [GH-1314]
+* core: SSH TCP keepalive period is now 5 seconds (shorter). [GH-1232]
+* builder/amazon-chroot: Can properly build HVM images now. [GH-1360]
+* builder/amazon-chroot: Fix crash in root device check. [GH-1360]
+* builder/amazon-chroot: Add description that Packer made the snapshot
+ with a time. [GH-1388]
+* builder/amazon-ebs: AMI is deregistered if an error. [GH-1186]
+* builder/amazon-instance: Fix deprecation warning for `ec2-bundle-vol`
+ [GH-1424]
+* builder/amazon-instance: Add `--no-filter` to the `ec2-bundle-vol`
+ command by default to avoid corrupting data by removing package
+ manager certs. [GH-1137]
+* builder/amazon/all: `delete_on_termination` set to false will work.
+* builder/amazon/all: Fix race condition on setting tags. [GH-1367]
+* builder/amazon/all: More descriptive error messages if Amazon only
+ sends an error code. [GH-1189]
+* builder/docker: Error if `DOCKER_HOST` is set.
+* builder/docker: Remove the container during cleanup. [GH-1206]
+* builder/docker: Fix case where not all output would show up from
+ provisioners.
+* builder/googlecompute: add `disk_size` option. [GH-1397]
+* builder/googlecompute: Auth works with latest formats on Google Cloud
+ Console. [GH-1344]
+* builder/openstack: Region is not required. [GH-1418]
+* builder/parallels-iso: ISO not removed from VM after install. [GH-1338]
+* builder/parallels/all: Add support for Parallels Desktop 10. [GH-1438]
+* builder/parallels/all: Added some navigation keys. [GH-1442]
+* builder/qemu: If headless, sdl display won't be used. [GH-1395]
+* builder/qemu: Use `512M` as `-m` default. [GH-1444]
+* builder/virtualbox/all: Search `VBOX_MSI_INSTALL_PATH` for path to
+ `VBoxManage` on Windows. [GH-1337]
+* builder/virtualbox/all: Seed RNG to avoid same ports. [GH-1386]
+* builder/virtualbox/all: Better error if guest additions URL couldn't be
+ detected. [GH-1439]
+* builder/virtualbox/all: Detect errors even when `VBoxManage` exits
+ with a zero exit code. [GH-1119]
+* builder/virtualbox/iso: Append timestamp to default name for parallel
+ builds. [GH-1365]
+* builder/vmware/all: No more error when Packer stops an already-stopped
+ VM. [GH-1300]
+* builder/vmware/all: `ssh_host` accepts templates. [GH-1396]
+* builder/vmware/all: Don't remount floppy in VMX post step. [GH-1239]
+* builder/vmware/vmx: Do not re-add floppy disk files to VMX. [GH-1361]
+* builder/vmware-iso: Fix crash when `vnc_port_min` and max were the
+ same value. [GH-1288]
+* builder/vmware-iso: Finding an available VNC port on Windows works. [GH-1372]
+* builder/vmware-vmx: Nice error if Clone is not supported (not VMware
+ Fusion Pro). [GH-787]
+* post-processor/vagrant: Can supply your own metadata.json. [GH-1143]
+* provisioner/ansible-local: Use proper path on Windows. [GH-1375]
+* provisioner/file: Mode will now be preserved. [GH-1064]
+
+## 0.6.1 (July 20, 2014)
+
+### FEATURES:
+
+* **New post processor:** `vagrant-cloud` - Push box files generated by
+ vagrant post processor to Vagrant Cloud. [GH-1289]
+* Vagrant post-processor can now packer Hyper-V boxes.
+
+### IMPROVEMENTS:
+
+* builder/amazon: Support for enhanced networking on HVM images. [GH-1228]
+* builder/amazon-ebs: Support encrypted EBS volumes. [GH-1194]
+* builder/ansible: Add `playbook_dir` option. [GH-1000]
+* builder/openstack: Add ability to configure networks. [GH-1261]
+* builder/openstack: Skip certificate verification. [GH-1121]
+* builder/parallels/all: Add ability to select interface to connect to.
+* builder/parallels/pvm: Support `boot_command`. [GH-1082]
+* builder/virtualbox/all: Attempt to use local guest additions ISO
+ before downloading from internet. [GH-1123]
+* builder/virtualbox/ovf: Supports `guest_additions_mode` [GH-1035]
+* builder/vmware/all: Increase cleanup timeout to 120 seconds. [GH-1167]
+* builder/vmware/all: Add `vmx_data_post` for modifying VMX data
+ after shutdown. [GH-1149]
+* builder/vmware/vmx: Supports tools uploading. [GH-1154]
+
+### BUG FIXES:
+
+* core: `isotime` is the same time during the entire build. [GH-1153]
+* builder/amazon-common: Sort AMI strings before outputting. [GH-1305]
+* builder/amazon: User data can use templates/variables. [GH-1343]
+* builder/amazon: Can now build AMIs in GovCloud.
+* builder/null: SSH info can use templates/variables. [GH-1343]
+* builder/openstack: Workaround for gophercloud.ServerById crashing. [GH-1257]
+* builder/openstack: Force IPv4 addresses from address pools. [GH-1258]
+* builder/parallels: Do not delete entire CDROM device. [GH-1115]
+* builder/parallels: Errors while creating floppy disk. [GH-1225]
+* builder/parallels: Errors while removing floppy drive. [GH-1226]
+* builder/virtualbox-ovf: Supports guest additions options. [GH-1120]
+* builder/vmware-iso: Fix esx5 path separator in windows. [GH-1316]
+* builder/vmware: Remote ESXi builder now uploads floppy. [GH-1106]
+* builder/vmware: Remote ESXi builder no longer re-uploads ISO every
+ time. [GH-1244]
+* post-processor/vsphere: Accept DOMAIN\account usernames. [GH-1178]
+ * provisioner/chef-*: Fix remotePaths for Windows. [GH-394]
+
+## 0.6.0 (May 2, 2014)
+
+### FEATURES:
+
+* **New builder:** `null` - The null builder does not produce any
+ artifacts, but is useful for debugging provisioning scripts. [GH-970]
+* **New builder:** `parallels-iso` and `parallels-pvm` - These can be
+ used to build Parallels virtual machines. [GH-1101]
+* **New provisioner:** `chef-client` - Provision using a the `chef-client`
+ command, which talks to a Chef Server. [GH-855]
+* **New provisioner:** `puppet-server` - Provision using Puppet by
+ communicating to a Puppet master. [GH-796]
+* `min_packer_version` can be specified in a Packer template to force
+ a minimum version. [GH-487]
+
+### IMPROVEMENTS:
+
+* core: RPC transport between plugins switched to MessagePack
+* core: Templates array values can now be comma separated strings.
+ Most importantly, this allows for user variables to fill
+ array configurations. [GH-950]
+* builder/amazon: Added `ssh_private_key_file` option. [GH-971]
+* builder/amazon: Added `ami_virtualization_type` option. [GH-1021]
+* builder/digitalocean: Regions, image names, and sizes can be
+ names that are looked up for their valid ID. [GH-960]
+* builder/googlecompute: Configurable instance name. [GH-1065]
+* builder/openstack: Support for conventional OpenStack environmental
+ variables such as `OS_USERNAME`, `OS_PASSWORD`, etc. [GH-768]
+* builder/openstack: Support `openstack_provider` option to automatically
+ fill defaults for different OpenStack variants. [GH-912]
+* builder/openstack: Support security groups. [GH-848]
+* builder/qemu: User variable expansion in `ssh_key_path` [GH-918]
+* builder/qemu: Floppy disk files list can also include globs
+ and directories. [GH-1086]
+* builder/virtualbox: Support an `export_opts` option which allows
+ specifying arbitrary arguments when exporting the VM. [GH-945]
+* builder/virtualbox: Added `vboxmanage_post` option to run vboxmanage
+ commands just before exporting. [GH-664]
+* builder/virtualbox: Floppy disk files list can also include globs
+ and directories. [GH-1086]
+* builder/vmware: Workstation 10 support for Linux. [GH-900]
+* builder/vmware: add cloning support on Windows. [GH-824]
+* builder/vmware: Floppy disk files list can also include globs
+ and directories. [GH-1086]
+* command/build: Added `-parallel` flag so you can disable parallelization
+ with `-no-parallel`. [GH-924]
+* post-processors/vsphere: `disk_mode` option. [GH-778]
+* provisioner/ansible: Add `inventory_file` option. [GH-1006]
+* provisioner/chef-client: Add `validation_client_name` option. [GH-1056]
+
+### BUG FIXES:
+
+* core: Errors are properly shown when adding bad floppy files. [GH-1043]
+* core: Fix some URL parsing issues on Windows.
+* core: Create Cache directory only when it is needed. [GH-367]
+* builder/amazon-instance: Use S3Endpoint for ec2-upload-bundle arg,
+ which works for every region. [GH-904]
+* builder/digitalocean: updated default image_id. [GH-1032]
+* builder/googlecompute: Create persistent disk as boot disk via
+ API v1. [GH-1001]
+* builder/openstack: Return proper error on invalid instance states. [GH-1018]
+* builder/virtualbox-iso: Retry unregister a few times to deal with
+ VBoxManage randomness. [GH-915]
+* provisioner/ansible: Fix paths when provisioning Linux from
+ Windows. [GH-963]
+* provisioner/ansible: set cwd to staging directory. [GH-1016]
+* provisioners/chef-client: Don't chown directory with Ubuntu. [GH-939]
+* provisioners/chef-solo: Deeply nested JSON works properly. [GH-1076]
+* provisioners/shell: Env var values can have equal signs. [GH-1045]
+* provisioners/shell: chmod the uploaded script file to 0777. [GH-994]
+* post-processor/docker-push: Allow repositories with ports. [GH-923]
+* post-processor/vagrant: Create parent directories for `output` path. [GH-1059]
+* post-processor/vsphere: datastore, network, and folder are no longer
+ required. [GH-1091]
+
+## 0.5.2 (02/21/2014)
+
+### FEATURES:
+
+* **New post-processor:** `docker-import` - Import a Docker image and give it
+ a specific repository/tag.
+* **New post-processor:** `docker-push` - Push an imported image to
+ a registry.
+
+### IMPROVEMENTS:
+
+* core: Most downloads made by Packer now use a custom user agent. [GH-803]
+* builder/googlecompute: SSH private key will be saved to disk if `-debug` is
+ specified. [GH-867]
+* builder/qemu: Can specify the name of the qemu binary. [GH-854]
+* builder/virtualbox-ovf: Can specify import options such as "keepallmacs".
+ [GH-883]
+
+### BUG FIXES:
+
+* core: Fix crash case if blank parameters are given to Packer. [GH-832]
+* core: Fix crash if big file uploads are done. [GH-897]
+* core: Fix crash if machine-readable output is going to a closed
+ pipe. [GH-875]
+* builder/docker: user variables work properly. [GH-777]
+* builder/qemu: reboots are now possible in provisioners. [GH-864]
+* builder/virtualbox,vmware: iso\_checksum is not required if the
+ checksum type is "none"
+* builder/virtualbox,vmware/qemu: Support for additional scancodes for
+ `boot_command` such as `<up>`, `<left>`, `<insert>`, etc. [GH-808]
+* communicator/ssh: Send TCP keep-alives on connections. [GH-872]
+* post-processor/vagrant: AWS/DigitalOcean keep input artifacts by
+ default. [GH-55]
+* provisioners/ansible-local: Properly upload custom playbooks. [GH-829]
+* provisioners/ansible-local: Better error if ansible isn't installed.
+ [GH-836]
+
+## 0.5.1 (01/02/2014)
+
+### BUG FIXES:
+
+* core: If a stream ID loops around, don't let it use stream ID 0. [GH-767]
+* core: Fix issue where large writes to plugins would result in stream
+ corruption. [GH-727]
+* builders/virtualbox-ovf: `shutdown_timeout` config works. [GH-772]
+* builders/vmware-iso: Remote driver works properly again. [GH-773]
+
+## 0.5.0 (12/30/2013)
+
+### BACKWARDS INCOMPATIBILITIES:
+
+* "virtualbox" builder has been renamed to "virtualbox-iso". Running your
+ template through `packer fix` will resolve this.
+* "vmware" builder has been renamed to "vmware-iso". Running your template
+ through `packer fix` will resolve this.
+* post-processor/vagrant: Syntax for overriding by provider has changed.
+ See the documentation for more information. Running your template
+ through `packer fix` should resolve this.
+* post-processor/vsphere: Some available configuration options were
+ changed. Running your template through `packer fix` should resolve
+ this.
+* provisioner/puppet-masterless: The `execute_command` no longer has
+ the `Has*` variables, since the templating language now supports
+ comparison operations. See the Go documentation for more info:
+ http://golang.org/pkg/text/template/
+
+### FEATURES:
+
+* **New builder:** Google Compute Engine. You can now build images for
+ use in Google Compute Engine. See the documentation for more information.
+ [GH-715]
+* **New builder:** "virtualbox-ovf" can build VirtualBox images from
+ an existing OVF or OVA. [GH-201]
+* **New builder:** "vmware-vmx" can build VMware images from an existing
+ VMX. [GH-201]
+* Environmental variables can now be accessed as default values for
+ user variables using the "env" function. See the documentation for more
+ information.
+* "description" field in templates: write a human-readable description
+ of what a template does. This will be shown in `packer inspect`.
+* Vagrant post-processor now accepts a list of files to include in the
+ box.
+* All provisioners can now have a "pause\_before" parameter to wait
+ some period of time before running that provisioner. This is useful
+ for reboots. [GH-737]
+
+### IMPROVEMENTS:
+
+* core: Plugins communicate over a single TCP connection per plugin now,
+ instead of sometimes dozens. Performance around plugin communication
+ dramatically increased.
+* core: Build names are now template processed so you can use things
+ like user variables in them. [GH-744]
+* core: New "pwd" function available globally that returns the working
+ directory. [GH-762]
+* builder/amazon/all: Launched EC2 instances now have a name of
+ "Packer Builder" so that they are easily recognizable. [GH-642]
+* builder/amazon/all: Copying AMIs to multiple regions now happens
+ in parallel. [GH-495]
+* builder/amazon/all: Ability to specify "run\_tags" to tag the instance
+ while running. [GH-722]
+* builder/digitalocean: Private networking support. [GH-698]
+* builder/docker: A "run\_command" can be specified, configuring how
+ the container is started. [GH-648]
+* builder/openstack: In debug mode, the generated SSH keypair is saved
+ so you can SSH into the machine. [GH-746]
+* builder/qemu: Floppy files are supported. [GH-686]
+* builder/qemu: Next `run_once` option tells Qemu to run only once,
+ which is useful for Windows installs that handle reboots for you.
+ [GH-687]
+* builder/virtualbox: Nice errors if Packer can't write to
+ the output directory.
+* builder/virtualbox: ISO is ejected prior to export.
+* builder/virtualbox: Checksum type can be "none" [GH-471]
+* builder/vmware: Can now specify path to the Fusion application. [GH-677]
+* builder/vmware: Checksum type can be "none" [GH-471]
+* provisioner/puppet-masterless: Can now specify a `manifest_dir` to
+ upload manifests to the remote machine for imports. [GH-655]
+
+### BUG FIXES:
+
+* core: No colored output in machine-readable output. [GH-684]
+* core: User variables can now be used for non-string fields. [GH-598]
+* core: Fix bad download paths if the download URL contained a "."
+ before a "/" [GH-716]
+* core: "{{timestamp}}" values will always be the same for the entire
+ duration of a build. [GH-744]
+* builder/amazon: Handle cases where security group isn't instantly
+ available. [GH-494]
+* builder/virtualbox: don't download guest additions if disabled. [GH-731]
+* post-processor/vsphere: Uploads VM properly. [GH-694]
+* post-processor/vsphere: Process user variables.
+* provisioner/ansible-local: all configurations are processed as templates
+ [GH-749]
+* provisioner/ansible-local: playbook paths are properly validated
+ as directories, not files. [GH-710]
+* provisioner/chef-solo: Environments are recognized. [GH-726]
+
+## 0.4.1 (December 7, 2013)
+
+### IMPROVEMENTS:
+
+* builder/amazon/ebs: New option allows associating a public IP with
+ non-default VPC instances. [GH-660]
+* builder/openstack: A "proxy\_url" setting was added to define an HTTP
+ proxy to use when building with this builder. [GH-637]
+
+### BUG FIXES:
+
+* core: Don't change background color on CLI anymore, making things look
+ a tad nicer in some terminals.
+* core: multiple ISO URLs works properly in all builders. [GH-683]
+* builder/amazon/chroot: Block when obtaining file lock to allow
+ parallel builds. [GH-689]
+* builder/amazon/instance: Add location flag to upload bundle command
+ so that building AMIs works out of us-east-1. [GH-679]
+* builder/qemu: Qemu arguments are templated. [GH-688]
+* builder/vmware: Cleanup of VMX keys works properly so cd-rom won't
+ get stuck with ISO. [GH-685]
+* builder/vmware: File cleanup is more resilient to file delete races
+ with the operating system. [GH-675]
+* provisioner/puppet-masterless: Check for hiera config path existence
+ properly. [GH-656]
+
+## 0.4.0 (November 19, 2013)
+
+### FEATURES:
+
+* Docker builder: build and export Docker containers, easily provisioned
+ with any of the Packer built-in provisioners.
+* QEMU builder: builds a new VM compatible with KVM or Xen using QEMU.
+* Remote ESXi builder: builds a VMware VM using ESXi remotely using only
+ SSH to an ESXi machine directly.
+* vSphere post-processor: Can upload VMware artifacts to vSphere
+* Vagrant post-processor can now make DigitalOcean provider boxes. [GH-504]
+
+### IMPROVEMENTS:
+
+* builder/amazon/all: Can now specify a list of multiple security group
+ IDs to apply. [GH-499]
+* builder/amazon/all: AWS API requests are now retried when a temporary
+ network error occurs as well as 500 errors. [GH-559]
+* builder/virtualbox: Use VBOX\_INSTALL\_PATH env var on Windows to find
+ VBoxManage. [GH-628]
+* post-processor/vagrant: skips gzip compression when compression_level=0
+* provisioner/chef-solo: Encrypted data bag support. [GH-625]
+
+### BUG FIXES:
+
+* builder/amazon/chroot: Copying empty directories works. [GH-588]
+* builder/amazon/chroot: Chroot commands work with shell provisioners. [GH-581]
+* builder/amazon/chroot: Don't choose a mount point that is a partition of
+ an already mounted device. [GH-635]
+* builder/virtualbox: Ctrl-C interrupts during waiting for boot. [GH-618]
+* builder/vmware: VMX modifications are now case-insensitive. [GH-608]
+* builder/vmware: VMware Fusion won't ask for VM upgrade.
+* builder/vmware: Ctrl-C interrupts during waiting for boot. [GH-618]
+* provisioner/chef-solo: Output is slightly prettier and more informative.
+
+## 0.3.11 (November 4, 2013)
+
+### FEATURES:
+
+* builder/amazon/ebs: Ability to specify which availability zone to create
+ instance in. [GH-536]
+
+### IMPROVEMENTS:
+
+* core: builders can now give warnings during validation. warnings won't
+ fail the build but may hint at potential future problems.
+* builder/digitalocean: Can now specify a droplet name
+* builder/virtualbox: Can now disable guest addition download entirely
+ by setting "guest_additions_mode" to "disable" [GH-580]
+* builder/virtualbox,vmware: ISO urls can now be https. [GH-587]
+* builder/virtualbox,vmware: Warning if shutdown command is not specified,
+ since it is a common case of data loss.
+
+### BUG FIXES:
+
+* core: Won't panic when writing to a bad pipe. [GH-560]
+* builder/amazon/all: Properly scrub access key and secret key from logs.
+ [GH-554]
+* builder/openstack: Properly scrub password from logs. [GH-554]
+* builder/virtualbox: No panic if SSH host port min/max is the same. [GH-594]
+* builder/vmware: checks if `ifconfig` is in `/sbin` [GH-591]
+* builder/vmware: Host IP lookup works for non-C locales. [GH-592]
+* common/uuid: Use cryptographically secure PRNG when generating
+ UUIDs. [GH-552]
+* communicator/ssh: File uploads that exceed the size of memory no longer
+ cause crashes. [GH-561]
+
+## 0.3.10 (October 20, 2013)
+
+### FEATURES:
+
+* Ansible provisioner
+
+### IMPROVEMENTS:
+
+* post-processor/vagrant: support instance-store AMIs built by Packer. [GH-502]
+* post-processor/vagrant: can now specify compression level to use
+ when creating the box. [GH-506]
+
+### BUG FIXES:
+
+* builder/all: timeout waiting for SSH connection is a failure. [GH-491]
+* builder/amazon: Scrub sensitive data from the logs. [GH-521]
+* builder/amazon: Handle the situation where an EC2 instance might not
+ be immediately available. [GH-522]
+* builder/amazon/chroot: Files copied into the chroot remove destination
+ before copy, fixing issues with dangling symlinks. [GH-500]
+* builder/digitalocean: don't panic if erroneous API response doesn't
+ contain error message. [GH-492]
+* builder/digitalocean: scrub API keys from config debug output. [GH-516]
+* builder/virtualbox: error if VirtualBox version cant be detected. [GH-488]
+* builder/virtualbox: detect if vboxdrv isn't properly setup. [GH-488]
+* builder/virtualbox: sleep a bit before export to ensure the session
+ is unlocked. [GH-512]
+* builder/virtualbox: create SATA drives properly on VirtualBox 4.3. [GH-547]
+* builder/virtualbox: support user templates in SSH key path. [GH-539]
+* builder/vmware: support user templates in SSH key path. [GH-539]
+* communicator/ssh: Fix issue where a panic could arise from a nil
+ dereference. [GH-525]
+* post-processor/vagrant: Fix issue with VirtualBox OVA. [GH-548]
+* provisioner/salt: Move salt states to correct remote directory. [GH-513]
+* provisioner/shell: Won't block on certain scripts on Windows anymore.
+ [GH-507]
+
+## 0.3.9 (October 2, 2013)
+
+### FEATURES:
+
+* The Amazon chroot builder is now able to run without any `sudo` privileges
+ by using the "command_wrapper" configuration. [GH-430]
+* Chef provisioner supports environments. [GH-483]
+
+### 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/digitalocean: Use proper error message JSON key (DO API change).
+* communicator/ssh: SCP uploads now work properly when directories
+ contain symlinks. [GH-449]
+* provisioner/chef-solo: Data bags and roles path are now properly
+ populated when set. [GH-470]
+* provisioner/shell: Windows line endings are actually properly changed
+ to Unix line endings. [GH-477]
+
+## 0.3.8 (September 22, 2013)
+
+### FEATURES:
+
+* core: You can now specify `only` and `except` configurations on any
+ provisioner or post-processor to specify a list of builds that they
+ are valid for. [GH-438]
+* builders/virtualbox: Guest additions can be attached rather than uploaded,
+ easier to handle for Windows guests. [GH-405]
+* provisioner/chef-solo: Ability to specify a custom Chef configuration
+ template.
+* provisioner/chef-solo: Roles and data bags support. [GH-348]
+
+### IMPROVEMENTS:
+
+* core: User variables can now be used for integer, boolean, etc.
+ values. [GH-418]
+* core: Plugins made with incompatible versions will no longer load.
+* builder/amazon/all: Interrupts work while waiting for AMI to be ready.
+* provisioner/shell: Script line-endings are automatically converted to
+ Unix-style line-endings. Can be disabled by setting "binary" to "true".
+ [GH-277]
+
+### BUG FIXES:
+
+* core: Set TCP KeepAlives on internally created RPC connections so that
+ they don't die. [GH-416]
+* builder/amazon/all: While waiting for AMI, will detect "failed" state.
+* builder/amazon/all: Waiting for state will detect if the resource (AMI,
+ instance, etc.) disappears from under it.
+* builder/amazon/instance: Exclude only contents of /tmp, not /tmp
+ itself. [GH-437]
+* builder/amazon/instance: Make AccessKey/SecretKey available to bundle
+ command even when they come from the environment. [GH-434]
+* builder/virtualbox: F1-F12 and delete scancodes now work. [GH-425]
+* post-processor/vagrant: Override configurations properly work. [GH-426]
+* provisioner/puppet-masterless: Fix failure case when both facter vars
+ are used and prevent_sudo. [GH-415]
+* provisioner/puppet-masterless: User variables now work properly in
+ manifest file and hiera path. [GH-448]
+
+## 0.3.7 (September 9, 2013)
+
+### BACKWARDS INCOMPATIBILITIES:
+
+* The "event_delay" option for the DigitalOcean builder is now gone.
+ The builder automatically waits for events to go away. Run your templates
+ through `packer fix` to get rid of these.
+
+### FEATURES:
+
+* **NEW PROVISIONER:** `puppet-masterless`. You can now provision with
+ a masterless Puppet setup. [GH-234]
+* New globally available template function: `uuid`. Generates a new random
+ UUID.
+* New globally available template function: `isotime`. Generates the
+ current time in ISO standard format.
+* New Amazon template function: `clean_ami_name`. Substitutes '-' for
+ characters that are illegal to use in an AMI name.
+
+### IMPROVEMENTS:
+
+* builder/amazon/all: Ability to specify the format of the temporary
+ keypair created. [GH-389]
+* builder/amazon/all: Support the NoDevice flag for block mappings. [GH-396]
+* builder/digitalocean: Retry on any pending event errors.
+* builder/openstack: Can now specify a project. [GH-382]
+* builder/virtualbox: Can now attach hard drive over SATA. [GH-391]
+* provisioner/file: Can now upload directories. [GH-251]
+
+### BUG FIXES:
+
+* core: Detect if SCP is not enabled on the other side. [GH-386]
+* builder/amazon/all: When copying AMI to multiple regions, copy
+ the metadata (tags and attributes) as well. [GH-388]
+* builder/amazon/all: Fix panic case where eventually consistent
+ instance state caused an index out of bounds.
+* builder/virtualbox: The `vm_name` setting now properly sets the OVF
+ name of the output. [GH-401]
+* builder/vmware: Autoanswer VMware dialogs. [GH-393]
+* command/inspect: Fix weird output for default values for optional vars.
+
+## 0.3.6 (September 2, 2013)
+
+### FEATURES:
+
+* User variables can now be specified as "required", meaning the user
+ MUST specify a value. Just set the default value to "null". [GH-374]
+
+### IMPROVEMENTS:
+
+* core: Much improved interrupt handling. For example, interrupts now
+ cancel much more quickly within provisioners.
+* builder/amazon: In `-debug` mode, the keypair used will be saved to
+ the current directory so you can access the machine. [GH-373]
+* builder/amazon: In `-debug` mode, the DNS is outputted.
+* builder/openstack: IPv6 addresses supported for SSH. [GH-379]
+* communicator/ssh: Support for private keys encrypted using PKCS8. [GH-376]
+* provisioner/chef-solo: You can now use user variables in the `json`
+ configuration for Chef. [GH-362]
+
+### BUG FIXES:
+
+* core: Concurrent map access is completely gone, fixing rare issues
+ with runtime memory corruption. [GH-307]
+* core: Fix possible panic when ctrl-C during provisioner run.
+* builder/digitalocean: Retry destroy a few times because DO sometimes
+ gives false errors.
+* builder/openstack: Properly handle the case no image is made. [GH-375]
+* builder/openstack: Specifying a region is now required in a template.
+* provisioners/salt-masterless: Use filepath join to properly join paths.
+
+## 0.3.5 (August 28, 2013)
+
+### FEATURES:
+
+* **NEW BUILDER:** `openstack`. You can now build on OpenStack. [GH-155]
+* **NEW PROVISIONER:** `chef-solo`. You can now provision with Chef
+ using `chef-solo` from local cookbooks.
+* builder/amazon: Copy AMI to multiple regions with `ami_regions`. [GH-322]
+* builder/virtualbox,vmware: Can now use SSH keys as an auth mechanism for
+ SSH using `ssh_key_path`. [GH-70]
+* builder/virtualbox,vmware: Support SHA512 as a checksum type. [GH-356]
+* builder/vmware: The root hard drive type can now be specified with
+ "disk_type_id" for advanced users. [GH-328]
+* provisioner/salt-masterless: Ability to specify a minion config. [GH-264]
+* provisioner/salt-masterless: Ability to upload pillars. [GH-353]
+
+### IMPROVEMENTS:
+
+* core: Output message when Ctrl-C received that we're cleaning up. [GH-338]
+* builder/amazon: Tagging now works with all amazon builder types.
+* builder/vmware: Option `ssh_skip_request_pty` for not requesting a PTY
+ for the SSH connection. [GH-270]
+* builder/vmware: Specify a `vmx_template_path` in order to customize
+ the generated VMX. [GH-270]
+* command/build: Machine-readable output now contains build errors, if any.
+* command/build: An "end" sentinel is outputted in machine-readable output
+ for artifact listing so it is easier to know when it is over.
+
+### BUG FIXES:
+
+* core: Fixed a couple cases where a double ctrl-C could panic.
+* core: Template validation fails if an override is specified for a
+ non-existent builder. [GH-336]
+* core: The SSH connection is heartbeated so that drops can be
+ detected. [GH-200]
+* builder/amazon/instance: Remove check for ec2-ami-tools because it
+ didn't allow absolute paths to work properly. [GH-330]
+* builder/digitalocean: Send a soft shutdown request so that files
+ are properly synced before shutdown. [GH-332]
+* command/build,command/validate: If a non-existent build is specified to
+ '-only' or '-except', it is now an error. [GH-326]
+* post-processor/vagrant: Setting OutputPath with a timestamp now
+ always works properly. [GH-324]
+* post-processor/vagrant: VirtualBox OVA formats now turn into
+ Vagrant boxes properly. [GH-331]
+* provisioner/shell: Retry upload if start command fails, making reboot
+ handling much more robust.
+
+## 0.3.4 (August 21, 2013)
+
+### IMPROVEMENTS:
+
+* post-processor/vagrant: the file being compressed will be shown
+ in the UI. [GH-314]
+
+### BUG FIXES:
+
+* core: Avoid panics when double-interrupting Packer.
+* provisioner/shell: Retry shell script uploads, making reboots more
+ robust if they happen to fail in this stage. [GH-282]
+
+## 0.3.3 (August 19, 2013)
+
+### FEATURES:
+
+* builder/virtualbox: support exporting in OVA format. [GH-309]
+
+### IMPROVEMENTS:
+
+* core: All HTTP downloads across Packer now support the standard
+ proxy environmental variables (`HTTP_PROXY`, `NO_PROXY`, etc.) [GH-252]
+* builder/amazon: API requests will use HTTP proxy if specified by
+ environmental variables.
+* builder/digitalocean: API requests will use HTTP proxy if specified
+ by environmental variables.
+
+### BUG FIXES:
+
+* core: TCP connection between plugin processes will keep-alive. [GH-312]
+* core: No more "unused key keep_input_artifact" for post processors. [GH-310]
+* post-processor/vagrant: `output_path` templates now work again.
+
+## 0.3.2 (August 18, 2013)
+
+### FEATURES:
+
+* New command: `packer inspect`. This command tells you the components of
+ a template. It respects the `-machine-readable` flag as well so you can
+ parse out components of a template.
+* Packer will detect its own crashes (always a bug) and save a "crash.log"
+ file.
+* builder/virtualbox: You may now specify multiple URLs for an ISO
+ using "iso_url" in a template. The URLs will be tried in order.
+* builder/vmware: You may now specify multiple URLs for an ISO
+ using "iso_url" in a template. The URLs will be tried in order.
+
+### IMPROVEMENTS:
+
+* core: built with Go 1.1.2
+* core: packer help output now loads much faster.
+* builder/virtualbox: guest_additions_url can now use the `Version`
+ variable to get the VirtualBox version. [GH-272]
+* builder/virtualbox: Do not check for VirtualBox as part of template
+ validation; only check at execution.
+* builder/vmware: Do not check for VMware as part of template validation;
+ only check at execution.
+* command/build: A path of "-" will read the template from stdin.
+* builder/amazon: add block device mappings. [GH-90]
+
+### BUG FIXES:
+
+* windows: file URLs are easier to get right as Packer
+ has better parsing and error handling for Windows file paths. [GH-284]
+* builder/amazon/all: Modifying more than one AMI attribute type no longer
+ crashes.
+* builder/amazon-instance: send IAM instance profile data. [GH-294]
+* builder/digitalocean: API request parameters are properly URL
+ encoded. [GH-281]
+* builder/virtualbox: download progress won't be shown until download
+ actually starts. [GH-288]
+* builder/virtualbox: floppy files names of 13 characters are now properly
+ written to the FAT12 filesystem. [GH-285]
+* builder/vmware: download progress won't be shown until download
+ actually starts. [GH-288]
+* builder/vmware: interrupt works while typing commands over VNC.
+* builder/virtualbox: floppy files names of 13 characters are now properly
+ written to the FAT12 filesystem. [GH-285]
+* post-processor/vagrant: Process user variables. [GH-295]
+
+## 0.3.1 (August 12, 2013)
+
+### IMPROVEMENTS:
+
+* provisioner/shell: New setting `start_retry_timeout` which is the timeout
+ for the provisioner to attempt to _start_ the remote process. This allows
+ the shell provisioner to work properly with reboots. [GH-260]
+
+### BUG FIXES:
+
+* core: Remote command output containing '\r' now looks much better
+ within the Packer output.
+* builder/vmware: Fix issue with finding driver files. [GH-279]
+* provisioner/salt-masterless: Uploads work properly from Windows. [GH-276]
+
+## 0.3.0 (August 12, 2013)
+
+### BACKWARDS INCOMPATIBILITIES:
+
+* All `{{.CreateTime}}` variables within templates (such as for AMI names)
+ are now replaced with `{{timestamp}}`. Run `packer fix` to fix your
+ templates.
+
+### FEATURES:
+
+* **User Variables** allow you to specify variables within your templates
+ that can be replaced using the command-line, files, or environmental
+ variables. This dramatically improves the portability of packer templates.
+ See the documentation for more information.
+* **Machine-readable output** can be enabled by passing the
+ `-machine-readable` flag to _any_ Packer command.
+* All strings in a template are now processed for variables/functions,
+ so things like `{{timestamp}}` can be used everywhere. More features will
+ be added in the future.
+* The `amazon` builders (all of them) can now have attributes of their
+ resulting AMIs modified, such as access permissions and product codes.
+
+### IMPROVEMENTS:
+
+* builder/amazon/all: User data can be passed to start the instances. [GH-253]
+* provisioner/salt-masterless: `local_state_tree` is no longer required,
+ allowing you to use shell provisioner (or others) to bring this down.
+ [GH-269]
+
+### BUG FIXES:
+
+* builder/amazon/ebs,instance: Retry deleing security group a few times.
+ [GH-278]
+* builder/vmware: Workstation works on Windows XP now. [GH-238]
+* builder/vmware: Look for files on Windows in multiple locations
+ using multiple environmental variables. [GH-263]
+* provisioner/salt-masterless: states aren't deleted after the run
+ anymore. [GH-265]
+* provisioner/salt-masterless: error if any commands exit with a non-zero
+ exit status. [GH-266]
+
+## 0.2.3 (August 7, 2013)
+
+### IMPROVEMENTS:
+
+* builder/amazon/all: Added Amazon AMI tag support. [GH-233]
+
+### BUG FIXES:
+
+* core: Absolute/relative filepaths on Windows now work for iso_url
+ and other settings. [GH-240]
+* builder/amazon/all: instance info is refreshed while waiting for SSH,
+ allowing Packer to see updated IP/DNS info. [GH-243]
+
+## 0.2.2 (August 1, 2013)
+
+### FEATURES:
+
+* New builder: `amazon-chroot` can create EBS-backed AMIs without launching
+ a new EC2 instance. This can shave minutes off of the AMI creation process.
+ See the docs for more info.
+* New provisioner: `salt-masterless` will provision the node using Salt
+ without a master.
+* The `vmware` builder now works with Workstation 9 on Windows. [GH-222]
+* The `vmware` builder now works with Player 5 on Linux. [GH-190]
+
+### IMPROVEMENTS:
+
+* core: Colors won't be outputted on Windows unless in Cygwin.
+* builder/amazon/all: Added `iam_instance_profile` to launch the source
+ image with a given IAM profile. [GH-226]
+
+### BUG FIXES:
+
+* builder/virtualbox,vmware: relative paths work properly as URL
+ configurations. [GH-215]
+* builder/virtualbox,vmware: fix race condition in deleting the output
+ directory on Windows by retrying.
+
+## 0.2.1 (July 26, 2013)
+
+### FEATURES:
+
+* New builder: `amazon-instance` can create instance-storage backed
+ AMIs.
+* VMware builder now works with Workstation 9 on Linux.
+
+### IMPROVEMENTS:
+
+* builder/amazon/all: Ctrl-C while waiting for state change works
+* builder/amazon/ebs: Can now launch instances into a VPC for added protection. [GH-210]
+* builder/virtualbox,vmware: Add backspace, delete, and F1-F12 keys to the boot
+ command.
+* builder/virtualbox: massive performance improvements with big ISO files because
+ an expensive copy is avoided. [GH-202]
+* builder/vmware: CD is removed prior to exporting final machine. [GH-198]
+
+### BUG FIXES:
+
+* builder/amazon/all: Gracefully handle when AMI appears to not exist
+ while AWS state is propagating. [GH-207]
+* builder/virtualbox: Trim carriage returns for Windows to properly
+ detect VM state on Windows. [GH-218]
+* core: build names no longer cause invalid config errors. [GH-197]
+* command/build: If any builds fail, exit with non-zero exit status.
+* communicator/ssh: SCP exit codes are tested and errors are reported. [GH-195]
+* communicator/ssh: Properly change slash direction for Windows hosts. [GH-218]
+
+## 0.2.0 (July 16, 2013)
+
+### BACKWARDS INCOMPATIBILITIES:
+
+* "iso_md5" in the virtualbox and vmware builders is replaced with
+ "iso_checksum" and "iso_checksum_type" (with the latter set to "md5").
+ See the announce below on `packer fix` to automatically fix your templates.
+
+### FEATURES:
+
+* **NEW COMMAND:** `packer fix` will attempt to fix templates from older
+ versions of Packer that are now broken due to backwards incompatibilities.
+ This command will fix the backwards incompatibilities introduced in this
+ version.
+* Amazon EBS builder can now optionally use a pre-made security group
+ instead of randomly generating one.
+* DigitalOcean API key and client IDs can now be passed in as
+ environmental variables. See the documentation for more details.
+* VirtualBox and VMware can now have `floppy_files` specified to attach
+ floppy disks when booting. This allows for unattended Windows installs.
+* `packer build` has a new `-force` flag that forces the removal of
+ existing artifacts if they exist. [GH-173]
+* You can now log to a file (instead of just stderr) by setting the
+ `PACKER_LOG_FILE` environmental variable. [GH-168]
+* Checksums other than MD5 can now be used. SHA1 and SHA256 can also
+ be used. See the documentation on `iso_checksum_type` for more info. [GH-175]
+
+### IMPROVEMENTS:
+
+* core: invalid keys in configuration are now considered validation
+ errors. [GH-104]
+* core: all builders now share a common SSH connection core, improving
+ SSH reliability over all the builders.
+* amazon-ebs: Credentials will come from IAM role if available. [GH-160]
+* amazon-ebs: Verify the source AMI is EBS-backed before launching. [GH-169]
+* shell provisioner: the build name and builder type are available in
+ the `PACKER_BUILD_NAME` and `PACKER_BUILDER_TYPE` env vars by default,
+ respectively. [GH-154]
+* vmware: error if shutdown command has non-zero exit status.
+
+### BUG FIXES:
+
+* core: UI messages are now properly prefixed with spaces again.
+* core: If SSH connection ends, re-connection attempts will take
+ place. [GH-152]
+* virtualbox: "paused" doesn't mean the VM is stopped, improving
+ shutdown detection.
+* vmware: error if guest IP could not be detected. [GH-189]
+
+## 0.1.5 (July 7, 2013)
+
+### FEATURES:
+
+* "file" uploader will upload files from the machine running Packer to the
+ remote machine.
+* VirtualBox guest additions URL and checksum can now be specified, allowing
+ the VirtualBox builder to have the ability to be used completely offline.
+
+### IMPROVEMENTS:
+
+* core: If SCP is not available, a more descriptive error message
+ is shown telling the user. [GH-127]
+* shell: Scripts are now executed by default according to their shebang,
+ not with `/bin/sh`. [GH-105]
+* shell: You can specify what interpreter you want inline scripts to
+ run with `inline_shebang`.
+* virtualbox: Delete the packer-made SSH port forwarding prior to
+ exporting the VM.
+
+### BUG FIXES:
+
+* core: Non-200 response codes on downloads now show proper errors.
+ [GH-141]
+* amazon-ebs: SSH handshake is retried. [GH-130]
+* vagrant: The `BuildName` template property works properly in
+ the output path.
+* vagrant: Properly configure the provider-specific post-processors so
+ things like `vagrantfile_template` work. [GH-129]
+* vagrant: Close filehandles when copying files so Windows can
+ rename files. [GH-100]
+
+## 0.1.4 (July 2, 2013)
+
+### FEATURES:
+
+* virtualbox: Can now be built headless with the "Headless" option. [GH-99]
+* virtualbox: <wait5> and <wait10> codes for waiting 5 and 10 seconds
+ during the boot sequence, respectively. [GH-97]
+* vmware: Can now be built headless with the "Headless" option. [GH-99]
+* vmware: <wait5> and <wait10> codes for waiting 5 and 10 seconds
+ during the boot sequence, respectively. [GH-97]
+* vmware: Disks are defragmented and compacted at the end of the build.
+ This can be disabled using "skip_compaction"
+
+### IMPROVEMENTS:
+
+* core: Template syntax errors now show line and character number. [GH-56]
+* amazon-ebs: Access key and secret access key default to
+ environmental variables. [GH-40]
+* virtualbox: Send password for keyboard-interactive auth. [GH-121]
+* vmware: Send password for keyboard-interactive auth. [GH-121]
+
+### BUG FIXES:
+
+* vmware: Wait until shut down cleans up properly to avoid corrupt
+ disk files. [GH-111]
+
+## 0.1.3 (July 1, 2013)
+
+### FEATURES:
+
+* The VMware builder can now upload the VMware tools for you into
+ the VM. This is opt-in, you must specify the `tools_upload_flavor`
+ option. See the website for more documentation.
+
+### IMPROVEMENTS:
+
+* digitalocean: Errors contain human-friendly error messages. [GH-85]
+
+### BUG FIXES:
+
+* core: More plugin server fixes that avoid hangs on OS X 10.7. [GH-87]
+* vagrant: AWS boxes will keep the AMI artifact around. [GH-55]
+* virtualbox: More robust version parsing for uploading guest additions. [GH-69]
+* virtualbox: Output dir and VM name defaults depend on build name,
+ avoiding collisions. [GH-91]
+* vmware: Output dir and VM name defaults depend on build name,
+ avoiding collisions. [GH-91]
+
+## 0.1.2 (June 29, 2013)
+
+### IMPROVEMENTS:
+
+* core: Template doesn't validate if there are no builders.
+* vmware: Delete any VMware files in the VM that aren't necessary for
+ it to function.
+
+### BUG FIXES:
+
+* core: Plugin servers consider a port in use if there is any
+ error listening to it. This fixes I18n issues and Windows. [GH-58]
+* amazon-ebs: Sleep between checking instance state to avoid
+ RequestLimitExceeded. [GH-50]
+* vagrant: Rename VirtualBox ovf to "box.ovf" [GH-64]
+* vagrant: VMware boxes have the correct provider type.
+* vmware: Properly populate files in artifact so that the Vagrant
+ post-processor works. [GH-63]
+
+## 0.1.1 (June 28, 2013)
+
+### BUG FIXES:
+
+* core: plugins listen explicitly on 127.0.0.1, fixing odd hangs. [GH-37]
+* core: fix race condition on verifying checksum of large ISOs which
+ could cause panics. [GH-52]
+* virtualbox: `boot_wait` defaults to "10s" rather than 0. [GH-44]
+* virtualbox: if `http_port_min` and max are the same, it will no longer
+ panic. [GH-53]
+* vmware: `boot_wait` defaults to "10s" rather than 0. [GH-44]
+* vmware: if `http_port_min` and max are the same, it will no longer
+ panic. [GH-53]
+
+## 0.1.0 (June 28, 2013)
+
+* Initial release
+
diff --git a/v1.9.4/CODEOWNERS b/v1.9.4/CODEOWNERS
new file mode 100644
index 0000000..0efb6b1
--- /dev/null
+++ b/v1.9.4/CODEOWNERS
@@ -0,0 +1,6 @@
+* @hashicorp/packer
+
+# release configuration
+
+/.release/ @hashicorp/release-engineering
+/.github/workflows/build.yml @hashicorp/release-engineering
diff --git a/v1.9.4/Dockerfile b/v1.9.4/Dockerfile
new file mode 100644
index 0000000..1b5ae54
--- /dev/null
+++ b/v1.9.4/Dockerfile
@@ -0,0 +1,76 @@
+# Copyright (c) HashiCorp, Inc.
+# SPDX-License-Identifier: MPL-2.0
+
+# ========================================================================
+#
+# This Dockerfile contains multiple targets.
+# Use 'docker build --target=<name> .' to build one.
+# e.g. `docker build --target=release-light .`
+#
+# All non-dev targets have a PRODUCT_VERSION argument that must be provided
+# via --build-arg=PRODUCT_VERSION=<version> when building.
+# e.g. --build-arg PRODUCT_VERSION=1.11.2
+#
+# For local dev and testing purposes, please build and use the `dev` docker image.
+#
+# ========================================================================
+
+
+# Development docker image primarily used for development and debugging.
+# This image builds from the locally generated binary in ./bin/.
+# To generate the local binary, run `make dev`.
+FROM docker.mirror.hashicorp.services/alpine:latest as dev
+
+RUN apk add --no-cache git bash openssl ca-certificates
+
+COPY bin/packer /bin/packer
+
+ENTRYPOINT ["/bin/packer"]
+
+# Light docker image which can be used to run the binary from a container.
+# This image builds from the locally generated binary in ./bin/, and from CI-built binaries within CI.
+# To generate the local binary, run `make dev`.
+# This image is published to DockerHub under the `light`, `light-$VERSION`, and `latest` tags.
+FROM docker.mirror.hashicorp.services/alpine:latest as release-light
+
+ARG PRODUCT_VERSION
+ARG BIN_NAME
+
+# TARGETARCH and TARGETOS are set automatically when --platform is provided.
+ARG TARGETOS TARGETARCH
+
+LABEL name="Packer" \
+ maintainer="HashiCorp Packer Team <packer@hashicorp.com>" \
+ vendor="HashiCorp" \
+ version=$PRODUCT_VERSION \
+ release=$PRODUCT_VERSION \
+ summary="Packer is a tool for creating identical machine images for multiple platforms from a single source configuration." \
+ description="Packer is a tool for creating identical machine images for multiple platforms from a single source configuration. Please submit issues to https://github.com/hashicorp/packer/issues"
+
+RUN apk add --no-cache git bash wget openssl gnupg xorriso
+
+COPY dist/$TARGETOS/$TARGETARCH/$BIN_NAME /bin/
+
+ENTRYPOINT ["/bin/packer"]
+
+# Full docker image which can be used to run the binary from a container.
+# This image is essentially the same as the `release-light` one, but embeds
+# the official plugins in it.
+FROM release-light as release-full
+
+# Install the latest version of the official plugins
+RUN /bin/packer plugins install "github.com/hashicorp/amazon" && \
+ /bin/packer plugins install "github.com/hashicorp/ansible" && \
+ /bin/packer plugins install "github.com/hashicorp/azure" && \
+ /bin/packer plugins install "github.com/hashicorp/docker" && \
+ /bin/packer plugins install "github.com/hashicorp/googlecompute" && \
+ /bin/packer plugins install "github.com/hashicorp/qemu" && \
+ /bin/packer plugins install "github.com/hashicorp/vagrant" && \
+ /bin/packer plugins install "github.com/hashicorp/virtualbox" && \
+ /bin/packer plugins install "github.com/hashicorp/vmware" && \
+ /bin/packer plugins install "github.com/hashicorp/vsphere"
+
+ENTRYPOINT ["/bin/packer"]
+
+# Set default target to 'dev'.
+FROM dev
diff --git a/v1.9.4/LICENSE b/v1.9.4/LICENSE
new file mode 100644
index 0000000..c96665e
--- /dev/null
+++ b/v1.9.4/LICENSE
@@ -0,0 +1,375 @@
+Copyright (c) 2013 HashiCorp, Inc.
+
+Mozilla Public License Version 2.0
+==================================
+
+1. Definitions
+--------------
+
+1.1. "Contributor"
+ means each individual or legal entity that creates, contributes to
+ the creation of, or owns Covered Software.
+
+1.2. "Contributor Version"
+ means the combination of the Contributions of others (if any) used
+ by a Contributor and that particular Contributor's Contribution.
+
+1.3. "Contribution"
+ means Covered Software of a particular Contributor.
+
+1.4. "Covered Software"
+ means Source Code Form to which the initial Contributor has attached
+ the notice in Exhibit A, the Executable Form of such Source Code
+ Form, and Modifications of such Source Code Form, in each case
+ including portions thereof.
+
+1.5. "Incompatible With Secondary Licenses"
+ means
+
+ (a) that the initial Contributor has attached the notice described
+ in Exhibit B to the Covered Software; or
+
+ (b) that the Covered Software was made available under the terms of
+ version 1.1 or earlier of the License, but not also under the
+ terms of a Secondary License.
+
+1.6. "Executable Form"
+ means any form of the work other than Source Code Form.
+
+1.7. "Larger Work"
+ means a work that combines Covered Software with other material, in
+ a separate file or files, that is not Covered Software.
+
+1.8. "License"
+ means this document.
+
+1.9. "Licensable"
+ means having the right to grant, to the maximum extent possible,
+ whether at the time of the initial grant or subsequently, any and
+ all of the rights conveyed by this License.
+
+1.10. "Modifications"
+ means any of the following:
+
+ (a) any file in Source Code Form that results from an addition to,
+ deletion from, or modification of the contents of Covered
+ Software; or
+
+ (b) any new file in Source Code Form that contains any Covered
+ Software.
+
+1.11. "Patent Claims" of a Contributor
+ means any patent claim(s), including without limitation, method,
+ process, and apparatus claims, in any patent Licensable by such
+ Contributor that would be infringed, but for the grant of the
+ License, by the making, using, selling, offering for sale, having
+ made, import, or transfer of either its Contributions or its
+ Contributor Version.
+
+1.12. "Secondary License"
+ means either the GNU General Public License, Version 2.0, the GNU
+ Lesser General Public License, Version 2.1, the GNU Affero General
+ Public License, Version 3.0, or any later versions of those
+ licenses.
+
+1.13. "Source Code Form"
+ means the form of the work preferred for making modifications.
+
+1.14. "You" (or "Your")
+ means an individual or a legal entity exercising rights under this
+ License. For legal entities, "You" includes any entity that
+ controls, is controlled by, or is under common control with You. For
+ purposes of this definition, "control" means (a) the power, direct
+ or indirect, to cause the direction or management of such entity,
+ whether by contract or otherwise, or (b) ownership of more than
+ fifty percent (50%) of the outstanding shares or beneficial
+ ownership of such entity.
+
+2. License Grants and Conditions
+--------------------------------
+
+2.1. Grants
+
+Each Contributor hereby grants You a world-wide, royalty-free,
+non-exclusive license:
+
+(a) under intellectual property rights (other than patent or trademark)
+ Licensable by such Contributor to use, reproduce, make available,
+ modify, display, perform, distribute, and otherwise exploit its
+ Contributions, either on an unmodified basis, with Modifications, or
+ as part of a Larger Work; and
+
+(b) under Patent Claims of such Contributor to make, use, sell, offer
+ for sale, have made, import, and otherwise transfer either its
+ Contributions or its Contributor Version.
+
+2.2. Effective Date
+
+The licenses granted in Section 2.1 with respect to any Contribution
+become effective for each Contribution on the date the Contributor first
+distributes such Contribution.
+
+2.3. Limitations on Grant Scope
+
+The licenses granted in this Section 2 are the only rights granted under
+this License. No additional rights or licenses will be implied from the
+distribution or licensing of Covered Software under this License.
+Notwithstanding Section 2.1(b) above, no patent license is granted by a
+Contributor:
+
+(a) for any code that a Contributor has removed from Covered Software;
+ or
+
+(b) for infringements caused by: (i) Your and any other third party's
+ modifications of Covered Software, or (ii) the combination of its
+ Contributions with other software (except as part of its Contributor
+ Version); or
+
+(c) under Patent Claims infringed by Covered Software in the absence of
+ its Contributions.
+
+This License does not grant any rights in the trademarks, service marks,
+or logos of any Contributor (except as may be necessary to comply with
+the notice requirements in Section 3.4).
+
+2.4. Subsequent Licenses
+
+No Contributor makes additional grants as a result of Your choice to
+distribute the Covered Software under a subsequent version of this
+License (see Section 10.2) or under the terms of a Secondary License (if
+permitted under the terms of Section 3.3).
+
+2.5. Representation
+
+Each Contributor represents that the Contributor believes its
+Contributions are its original creation(s) or it has sufficient rights
+to grant the rights to its Contributions conveyed by this License.
+
+2.6. Fair Use
+
+This License is not intended to limit any rights You have under
+applicable copyright doctrines of fair use, fair dealing, or other
+equivalents.
+
+2.7. Conditions
+
+Sections 3.1, 3.2, 3.3, and 3.4 are conditions of the licenses granted
+in Section 2.1.
+
+3. Responsibilities
+-------------------
+
+3.1. Distribution of Source Form
+
+All distribution of Covered Software in Source Code Form, including any
+Modifications that You create or to which You contribute, must be under
+the terms of this License. You must inform recipients that the Source
+Code Form of the Covered Software is governed by the terms of this
+License, and how they can obtain a copy of this License. You may not
+attempt to alter or restrict the recipients' rights in the Source Code
+Form.
+
+3.2. Distribution of Executable Form
+
+If You distribute Covered Software in Executable Form then:
+
+(a) such Covered Software must also be made available in Source Code
+ Form, as described in Section 3.1, and You must inform recipients of
+ the Executable Form how they can obtain a copy of such Source Code
+ Form by reasonable means in a timely manner, at a charge no more
+ than the cost of distribution to the recipient; and
+
+(b) You may distribute such Executable Form under the terms of this
+ License, or sublicense it under different terms, provided that the
+ license for the Executable Form does not attempt to limit or alter
+ the recipients' rights in the Source Code Form under this License.
+
+3.3. Distribution of a Larger Work
+
+You may create and distribute a Larger Work under terms of Your choice,
+provided that You also comply with the requirements of this License for
+the Covered Software. If the Larger Work is a combination of Covered
+Software with a work governed by one or more Secondary Licenses, and the
+Covered Software is not Incompatible With Secondary Licenses, this
+License permits You to additionally distribute such Covered Software
+under the terms of such Secondary License(s), so that the recipient of
+the Larger Work may, at their option, further distribute the Covered
+Software under the terms of either this License or such Secondary
+License(s).
+
+3.4. Notices
+
+You may not remove or alter the substance of any license notices
+(including copyright notices, patent notices, disclaimers of warranty,
+or limitations of liability) contained within the Source Code Form of
+the Covered Software, except that You may alter any license notices to
+the extent required to remedy known factual inaccuracies.
+
+3.5. Application of Additional Terms
+
+You may choose to offer, and to charge a fee for, warranty, support,
+indemnity or liability obligations to one or more recipients of Covered
+Software. However, You may do so only on Your own behalf, and not on
+behalf of any Contributor. You must make it absolutely clear that any
+such warranty, support, indemnity, or liability obligation is offered by
+You alone, and You hereby agree to indemnify every Contributor for any
+liability incurred by such Contributor as a result of warranty, support,
+indemnity or liability terms You offer. You may include additional
+disclaimers of warranty and limitations of liability specific to any
+jurisdiction.
+
+4. Inability to Comply Due to Statute or Regulation
+---------------------------------------------------
+
+If it is impossible for You to comply with any of the terms of this
+License with respect to some or all of the Covered Software due to
+statute, judicial order, or regulation then You must: (a) comply with
+the terms of this License to the maximum extent possible; and (b)
+describe the limitations and the code they affect. Such description must
+be placed in a text file included with all distributions of the Covered
+Software under this License. Except to the extent prohibited by statute
+or regulation, such description must be sufficiently detailed for a
+recipient of ordinary skill to be able to understand it.
+
+5. Termination
+--------------
+
+5.1. The rights granted under this License will terminate automatically
+if You fail to comply with any of its terms. However, if You become
+compliant, then the rights granted under this License from a particular
+Contributor are reinstated (a) provisionally, unless and until such
+Contributor explicitly and finally terminates Your grants, and (b) on an
+ongoing basis, if such Contributor fails to notify You of the
+non-compliance by some reasonable means prior to 60 days after You have
+come back into compliance. Moreover, Your grants from a particular
+Contributor are reinstated on an ongoing basis if such Contributor
+notifies You of the non-compliance by some reasonable means, this is the
+first time You have received notice of non-compliance with this License
+from such Contributor, and You become compliant prior to 30 days after
+Your receipt of the notice.
+
+5.2. If You initiate litigation against any entity by asserting a patent
+infringement claim (excluding declaratory judgment actions,
+counter-claims, and cross-claims) alleging that a Contributor Version
+directly or indirectly infringes any patent, then the rights granted to
+You by any and all Contributors for the Covered Software under Section
+2.1 of this License shall terminate.
+
+5.3. In the event of termination under Sections 5.1 or 5.2 above, all
+end user license agreements (excluding distributors and resellers) which
+have been validly granted by You or Your distributors under this License
+prior to termination shall survive termination.
+
+************************************************************************
+* *
+* 6. Disclaimer of Warranty *
+* ------------------------- *
+* *
+* Covered Software is provided under this License on an "as is" *
+* basis, without warranty of any kind, either expressed, implied, or *
+* statutory, including, without limitation, warranties that the *
+* Covered Software is free of defects, merchantable, fit for a *
+* particular purpose or non-infringing. The entire risk as to the *
+* quality and performance of the Covered Software is with You. *
+* Should any Covered Software prove defective in any respect, You *
+* (not any Contributor) assume the cost of any necessary servicing, *
+* repair, or correction. This disclaimer of warranty constitutes an *
+* essential part of this License. No use of any Covered Software is *
+* authorized under this License except under this disclaimer. *
+* *
+************************************************************************
+
+************************************************************************
+* *
+* 7. Limitation of Liability *
+* -------------------------- *
+* *
+* Under no circumstances and under no legal theory, whether tort *
+* (including negligence), contract, or otherwise, shall any *
+* Contributor, or anyone who distributes Covered Software as *
+* permitted above, be liable to You for any direct, indirect, *
+* special, incidental, or consequential damages of any character *
+* including, without limitation, damages for lost profits, loss of *
+* goodwill, work stoppage, computer failure or malfunction, or any *
+* and all other commercial damages or losses, even if such party *
+* shall have been informed of the possibility of such damages. This *
+* limitation of liability shall not apply to liability for death or *
+* personal injury resulting from such party's negligence to the *
+* extent applicable law prohibits such limitation. Some *
+* jurisdictions do not allow the exclusion or limitation of *
+* incidental or consequential damages, so this exclusion and *
+* limitation may not apply to You. *
+* *
+************************************************************************
+
+8. Litigation
+-------------
+
+Any litigation relating to this License may be brought only in the
+courts of a jurisdiction where the defendant maintains its principal
+place of business and such litigation shall be governed by laws of that
+jurisdiction, without reference to its conflict-of-law provisions.
+Nothing in this Section shall prevent a party's ability to bring
+cross-claims or counter-claims.
+
+9. Miscellaneous
+----------------
+
+This License represents the complete agreement concerning the subject
+matter hereof. If any provision of this License is held to be
+unenforceable, such provision shall be reformed only to the extent
+necessary to make it enforceable. Any law or regulation which provides
+that the language of a contract shall be construed against the drafter
+shall not be used to construe this License against a Contributor.
+
+10. Versions of the License
+---------------------------
+
+10.1. New Versions
+
+Mozilla Foundation is the license steward. Except as provided in Section
+10.3, no one other than the license steward has the right to modify or
+publish new versions of this License. Each version will be given a
+distinguishing version number.
+
+10.2. Effect of New Versions
+
+You may distribute the Covered Software under the terms of the version
+of the License under which You originally received the Covered Software,
+or under the terms of any subsequent version published by the license
+steward.
+
+10.3. Modified Versions
+
+If you create software not governed by this License, and you want to
+create a new license for such software, you may create and use a
+modified version of this License if you rename the license and remove
+any references to the name of the license steward (except to note that
+such modified license differs from this License).
+
+10.4. Distributing Source Code Form that is Incompatible With Secondary
+Licenses
+
+If You choose to distribute Source Code Form that is Incompatible With
+Secondary Licenses under the terms of this version of the License, the
+notice described in Exhibit B of this License must be attached.
+
+Exhibit A - Source Code Form License Notice
+-------------------------------------------
+
+ This Source Code Form is subject to the terms of the Mozilla Public
+ License, v. 2.0. If a copy of the MPL was not distributed with this
+ file, You can obtain one at http://mozilla.org/MPL/2.0/.
+
+If it is not possible or desirable to put the notice in a particular
+file, then You may include the notice in a location (such as a LICENSE
+file in a relevant directory) where a recipient would be likely to look
+for such a notice.
+
+You may add additional accurate notices of copyright ownership.
+
+Exhibit B - "Incompatible With Secondary Licenses" Notice
+---------------------------------------------------------
+
+ This Source Code Form is "Incompatible With Secondary Licenses", as
+ defined by the Mozilla Public License, v. 2.0.
diff --git a/v1.9.4/Makefile b/v1.9.4/Makefile
new file mode 100644
index 0000000..ed46303
--- /dev/null
+++ b/v1.9.4/Makefile
@@ -0,0 +1,168 @@
+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)
+GITBRANCH:=$(shell git symbolic-ref --short HEAD 2>/dev/null)
+GOOS=$(shell go env GOOS)
+GOARCH=$(shell go env GOARCH)
+GOPATH=$(shell go env GOPATH)
+
+# Get the git commit
+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)
+
+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 version
+
+default: install-build-deps install-gen-deps generate dev
+
+ci: testrace ## Test in continuous integration
+
+release: install-build-deps test releasebin package ## Build a release build
+
+bin: install-build-deps ## Build debug/test build
+ @echo "WARN: 'make bin' is for debug / test builds only. Use 'make release' for release builds."
+ @GO111MODULE=auto sh -c "$(CURDIR)/scripts/build.sh"
+
+releasebin: install-build-deps
+ @grep 'const VersionPrerelease = "dev"' version/version.go > /dev/null ; if [ $$? -eq 0 ]; then \
+ echo "ERROR: You must remove prerelease tags from version/version.go prior to release."; \
+ exit 1; \
+ fi
+ @GO111MODULE=auto sh -c "$(CURDIR)/scripts/build.sh"
+
+package:
+ $(if $(VERSION),,@echo 'VERSION= needed to release; Use make package skip compilation'; exit 1)
+ @sh -c "$(CURDIR)/scripts/dist.sh $(VERSION)"
+
+install-build-deps: ## Install dependencies for bin build
+ @go install github.com/mitchellh/gox@v1.0.1
+
+install-gen-deps: ## Install dependencies for code generation
+ @GO111MODULE=on go install github.com/alvaroloes/enumer@master
+ @go install github.com/hashicorp/packer-plugin-sdk/cmd/packer-sdc@latest
+
+install-lint-deps: ## Install linter dependencies
+ @echo "==> Updating linter dependencies..."
+ @curl -sSfL -q https://raw.githubusercontent.com/golangci/golangci-lint/master/install.sh | sh -s -- -b $(GOPATH)/bin v1.52.0
+
+dev: ## Build and install a development build
+ @grep 'const VersionPrerelease = ""' version/version.go > /dev/null ; if [ $$? -eq 0 ]; then \
+ echo "ERROR: You must add prerelease tags to version/version.go prior to making a dev build."; \
+ exit 1; \
+ fi
+ @mkdir -p pkg/$(GOOS)_$(GOARCH)
+ @mkdir -p bin
+ @go install -ldflags '$(GOLDFLAGS)'
+ @cp $(GOPATH)/bin/packer bin/packer
+ @cp $(GOPATH)/bin/packer pkg/$(GOOS)_$(GOARCH)
+
+# Docker build variables and targets
+REGISTRY_NAME?=docker.io/hashicorp
+IMAGE_NAME=packer
+IMAGE_TAG_DEV=$(REGISTRY_NAME)/$(IMAGE_NAME):latest-$(GIT_COMMIT)
+
+docker: docker-dev
+
+# Builds from the locally generated binary in ./bin/
+# To generate the local binary, run `make dev`
+docker-dev:
+ @GOOS=linux \
+ GOARCH=amd64 \
+ CGO_ENABLED=0 \
+ go build -ldflags '$(GOLDFLAGS)' -o bin/packer .
+ @docker build \
+ --tag $(IMAGE_TAG_DEV) \
+ --target=dev \
+ .
+ @rm -f bin/packer # Clean up the Linux/amd64 binary to avoid conficts on other OS/archs
+
+lint: install-lint-deps ## Lint Go code
+ @if [ ! -z $(PKG_NAME) ]; then \
+ echo "golangci-lint run ./$(PKG_NAME)/..."; \
+ golangci-lint run ./$(PKG_NAME)/...; \
+ else \
+ echo "golangci-lint run ./..."; \
+ golangci-lint run ./...; \
+ fi
+
+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/main HEAD) ./...
+
+fmt: ## Format Go code
+ @go fmt ./...
+
+fmt-check: fmt ## Check go code formatting
+ @echo "==> Checking that code complies with go fmt requirements..."
+ @git diff --exit-code; if [ $$? -eq 1 ]; then \
+ echo "Found files that are not fmt'ed."; \
+ echo "You can use the command: \`make fmt\` to reformat code."; \
+ exit 1; \
+ 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 {} \;
+
+# Install js-beautify with npm install -g js-beautify
+fmt-examples:
+ find examples -name *.json | xargs js-beautify -r -s 2 -n -eol "\n"
+
+# 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 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)
+
+generate-check: generate ## Check go code generation is on par
+ @echo "==> Checking that auto-generated code is not changed..."
+ @git diff --exit-code; if [ $$? -eq 1 ]; then \
+ echo "Found diffs in go generated code."; \
+ echo "You can use the command: \`make generate\` to reformat code."; \
+ exit 1; \
+ fi
+
+test: 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
+
+# testacc runs acceptance tests
+testacc: # install-build-deps generate ## Run acceptance tests
+ @echo "WARN: Acceptance tests will take a long time to run and may cost money. Ctrl-C if you want to cancel."
+ PACKER_ACC=1 go test -count $(COUNT) -v $(TEST) $(TESTARGS) -timeout=120m
+
+testrace: vet ## Test with race detection enabled
+ @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
+
+vet: ## Vet Go code
+ @go vet $(VET) ; if [ $$? -eq 1 ]; then \
+ echo "ERROR: Vet found problems in the code."; \
+ exit 1; \
+ fi
+
+help:
+ @grep -E '^[a-zA-Z_-]+:.*?## .*$$' $(MAKEFILE_LIST) | sort | awk 'BEGIN {FS = ":.*?## "}; {printf "\033[36m%-30s\033[0m %s\n", $$1, $$2}'
+
diff --git a/v1.9.4/README.md b/v1.9.4/README.md
new file mode 100644
index 0000000..c6a6703
--- /dev/null
+++ b/v1.9.4/README.md
@@ -0,0 +1,120 @@
+# Packer
+
+[![Build Status](https://github.com/hashicorp/packer/actions/workflows/build.yml/badge.svg)](https://github.com/hashicorp/packer/actions/workflows/build.yml)
+[![Discuss](https://img.shields.io/badge/discuss-packer-3d89ff?style=flat)](https://discuss.hashicorp.com/c/packer)
+[![PkgGoDev](https://pkg.go.dev/badge/github.com/hashicorp/packer)](https://pkg.go.dev/github.com/hashicorp/packer)
+[![GoReportCard][report-badge]][report]
+
+[github-badge]: https://github.com/hashicorp/packer/actions/workflows/build.yml/badge.svg
+[appveyor-badge]: https://ci.appveyor.com/api/projects/status/miavlgnp989e5obc/branch/master?svg=true
+[godoc-badge]: https://godoc.org/github.com/hashicorp/packer?status.svg
+[godoc]: https://godoc.org/github.com/hashicorp/packer
+[report-badge]: https://goreportcard.com/badge/github.com/hashicorp/packer
+[report]: https://goreportcard.com/report/github.com/hashicorp/packer
+
+<p align="center" style="text-align:center;">
+ <a href="https://www.packer.io">
+ <img alt="HashiCorp Packer logo" src="website/public/img/logo-packer-padded.svg" width="500" />
+ </a>
+</p>
+
+Packer is a tool for building identical machine images for multiple platforms
+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.
+
+Support for other platforms can be added via plugins.
+
+The images that Packer creates can easily be turned into
+[Vagrant](http://www.vagrantup.com) boxes.
+
+## Quick Start
+
+**Note:** There is a great
+[introduction and getting started guide](https://learn.hashicorp.com/tutorials/packer/get-started-install-cli)
+for those with a bit more patience. Otherwise, the quick start below
+will get you up and running quickly, at the sacrifice of not explaining some
+key points.
+
+First, [download a pre-built Packer
+binary](https://www.packer.io/downloads.html) for your operating system or
+[compile Packer
+yourself](https://github.com/hashicorp/packer/blob/main/.github/CONTRIBUTING.md#setting-up-go).
+
+After Packer is installed, create your first template, which tells Packer
+what platforms to build images for and how you want to build them. In our
+case, we'll create a simple AMI that has Redis pre-installed.
+
+Save this file as `quick-start.pkr.hcl`. Export your AWS credentials as the
+`AWS_ACCESS_KEY_ID` and `AWS_SECRET_ACCESS_KEY` environment variables.
+
+```hcl
+variable "access_key" {
+ type = string
+ default = "${env("AWS_ACCESS_KEY_ID")}"
+}
+
+variable "secret_key" {
+ type = string
+ default = "${env("AWS_SECRET_ACCESS_KEY")}"
+ sensitive = true
+}
+
+locals { timestamp = regex_replace(timestamp(), "[- TZ:]", "") }
+
+source "amazon-ebs" "quick-start" {
+ access_key = "${var.access_key}"
+ ami_name = "packer-example ${local.timestamp}"
+ instance_type = "t2.micro"
+ region = "us-east-1"
+ secret_key = "${var.secret_key}"
+ source_ami = "ami-af22d9b9"
+ ssh_username = "ubuntu"
+}
+
+build {
+ sources = ["source.amazon-ebs.quick-start"]
+}
+```
+
+Next, tell Packer to build the image:
+
+```
+$ packer build quick-start.pkr.hcl
+...
+```
+
+Packer will build an AMI according to the "quick-start" template. The AMI
+will be available in your AWS account. To delete the AMI, you must manually
+delete it using the [AWS console](https://console.aws.amazon.com/). Packer
+builds your images, it does not manage their lifecycle. Where they go, how
+they're run, etc., is up to you.
+
+## Documentation
+
+Comprehensive documentation is viewable on the Packer website at https://www.packer.io/docs.
+
+## Contributing to Packer
+
+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, HashiCorp may use GitHub's option to archive the
+plugin’s repository, 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 HashiCorp.
+
+If you are interested in maintaining an unmaintained or archived plugin, please reach out to us at packer@hashicorp.com.
+
diff --git a/v1.9.4/Vagrantfile b/v1.9.4/Vagrantfile
new file mode 100644
index 0000000..5f4234b
--- /dev/null
+++ b/v1.9.4/Vagrantfile
@@ -0,0 +1,94 @@
+# -*- mode: ruby -*-
+# vi: set ft=ruby :
+
+LINUX_BASE_BOX = "bento/ubuntu-16.04"
+FREEBSD_BASE_BOX = "jen20/FreeBSD-12.0-CURRENT"
+
+Vagrant.configure(2) do |config|
+ if Vagrant.has_plugin?("vagrant-cachier")
+ config.cache.scope = :box
+ end
+
+ # Compilation and development boxes
+ config.vm.define "linux", autostart: true, primary: true do |vmCfg|
+ vmCfg.vm.box = LINUX_BASE_BOX
+ vmCfg.vm.hostname = "linux"
+ vmCfg = configureProviders vmCfg,
+ cpus: suggestedCPUCores()
+
+ vmCfg.vm.synced_folder ".", "/vagrant", disabled: true
+ vmCfg.vm.synced_folder '.',
+ '/opt/gopath/src/github.com/hashicorp/packer'
+
+ vmCfg.vm.provision "shell",
+ privileged: true,
+ inline: 'rm -f /home/vagrant/linux.iso'
+
+ vmCfg.vm.provision "shell",
+ privileged: true,
+ path: './scripts/vagrant-linux-priv-go.sh'
+
+ vmCfg.vm.provision "shell",
+ privileged: true,
+ path: './scripts/vagrant-linux-priv-config.sh'
+
+ vmCfg.vm.provision "shell",
+ privileged: false,
+ path: './scripts/vagrant-linux-unpriv-bootstrap.sh'
+ end
+
+ config.vm.define "freebsd", autostart: false, primary: false do |vmCfg|
+ vmCfg.vm.box = FREEBSD_BASE_BOX
+ vmCfg.vm.hostname = "freebsd"
+ vmCfg = configureProviders vmCfg,
+ cpus: suggestedCPUCores()
+
+ vmCfg.vm.synced_folder ".", "/vagrant", disabled: true
+ vmCfg.vm.synced_folder '.',
+ '/opt/gopath/src/github.com/hashicorp/packer',
+ type: "nfs",
+ bsd__nfs_options: ['noatime']
+
+ vmCfg.vm.provision "shell",
+ privileged: true,
+ path: './scripts/vagrant-freebsd-priv-config.sh'
+
+ vmCfg.vm.provision "shell",
+ privileged: false,
+ path: './scripts/vagrant-freebsd-unpriv-bootstrap.sh'
+ end
+end
+
+def configureProviders(vmCfg, cpus: "2", memory: "2048")
+ vmCfg.vm.provider "virtualbox" do |v|
+ v.memory = memory
+ v.cpus = cpus
+ end
+
+ ["vmware_fusion", "vmware_workstation"].each do |p|
+ vmCfg.vm.provider p do |v|
+ v.enable_vmrun_ip_lookup = false
+ v.vmx["memsize"] = memory
+ v.vmx["numvcpus"] = cpus
+ end
+ end
+
+ vmCfg.vm.provider "docker" do |d, override|
+ d.build_dir = "."
+ d.has_ssh = true
+ override.vm.box = nil
+ end
+
+ return vmCfg
+end
+
+def suggestedCPUCores()
+ case RbConfig::CONFIG['host_os']
+ when /darwin/
+ Integer(`sysctl -n hw.ncpu`) / 2
+ when /linux/
+ Integer(`cat /proc/cpuinfo | grep processor | wc -l`) / 2
+ else
+ 2
+ end
+end
diff --git a/v1.9.4/acctest/plugin/bundled_plugin_test.go b/v1.9.4/acctest/plugin/bundled_plugin_test.go
new file mode 100644
index 0000000..9f21dfa
--- /dev/null
+++ b/v1.9.4/acctest/plugin/bundled_plugin_test.go
@@ -0,0 +1,184 @@
+// Copyright (c) HashiCorp, Inc.
+// SPDX-License-Identifier: MPL-2.0
+
+package plugin
+
+import (
+ _ "embed"
+ "errors"
+ "fmt"
+ "os"
+ "os/exec"
+ "strings"
+ "testing"
+
+ "github.com/hashicorp/go-multierror"
+ amazonacc "github.com/hashicorp/packer-plugin-amazon/builder/ebs/acceptance"
+ "github.com/hashicorp/packer-plugin-sdk/acctest"
+ "github.com/hashicorp/packer/hcl2template/addrs"
+)
+
+//go:embed test-fixtures/basic_amazon_bundled.pkr.hcl
+var basicAmazonBundledEbsTemplate string
+
+func TestAccBuildBundledPlugins(t *testing.T) {
+ plugin := addrs.Plugin{
+ Hostname: "github.com",
+ Namespace: "hashicorp",
+ Type: "amazon",
+ }
+ testCase := &acctest.PluginTestCase{
+ Name: "amazon-ebs_bundled_test",
+ Setup: func() error {
+ return cleanupPluginInstallation(plugin)
+ },
+ Teardown: func() error {
+ helper := amazonacc.AMIHelper{
+ Region: "us-east-1",
+ Name: "packer-plugin-bundled-amazon-ebs-test",
+ }
+ return helper.CleanUpAmi()
+ },
+ Template: basicAmazonBundledEbsTemplate,
+ Type: "amazon-ebs",
+ Init: false,
+ 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)
+ }
+ }
+
+ rawLogs, err := os.ReadFile(logfile)
+ if err != nil {
+ return fmt.Errorf("failed to read logs: %s", err)
+ }
+
+ var errs error
+
+ logs := string(rawLogs)
+
+ if !strings.Contains(logs, "Warning: Bundled plugins used") {
+ errs = multierror.Append(errs, errors.New("expected warning about bundled plugins used, did not find it"))
+ }
+
+ if !strings.Contains(logs, "Then run 'packer init' to manage installation of the plugins") {
+ errs = multierror.Append(errs, errors.New("expected suggestion about packer init in logs, did not find it."))
+ }
+
+ return errs
+ },
+ }
+
+ acctest.TestPlugin(t, testCase)
+}
+
+//go:embed test-fixtures/basic_amazon_with_required_plugins.pkr.hcl
+var basicAmazonRequiredPluginEbsTemplate string
+
+func TestAccBuildBundledPluginsWithRequiredPlugins(t *testing.T) {
+ plugin := addrs.Plugin{
+ Hostname: "github.com",
+ Namespace: "hashicorp",
+ Type: "amazon",
+ }
+ testCase := &acctest.PluginTestCase{
+ Name: "amazon-ebs_with_required_plugins_test",
+ Setup: func() error {
+ return cleanupPluginInstallation(plugin)
+ },
+ Teardown: func() error {
+ helper := amazonacc.AMIHelper{
+ Region: "us-east-1",
+ Name: "packer-plugin-required-plugin-amazon-ebs-test",
+ }
+ return helper.CleanUpAmi()
+ },
+ Template: basicAmazonRequiredPluginEbsTemplate,
+ Type: "amazon-ebs",
+ Init: false,
+ Check: func(buildCommand *exec.Cmd, logfile string) error {
+ if buildCommand.ProcessState != nil {
+ if buildCommand.ProcessState.ExitCode() != 1 {
+ return fmt.Errorf("Bad exit code. Logfile: %s", logfile)
+ }
+ }
+
+ rawLogs, err := os.ReadFile(logfile)
+ if err != nil {
+ return fmt.Errorf("failed to read logs: %s", err)
+ }
+
+ var errs error
+
+ logs := string(rawLogs)
+
+ if strings.Contains(logs, "Warning: Bundled plugins used") {
+ errs = multierror.Append(errs, errors.New("did not expect warning about bundled plugins used"))
+ }
+
+ if !strings.Contains(logs, "Missing plugins") {
+ errs = multierror.Append(errs, errors.New("expected error about plugins required and not installed, did not find it"))
+ }
+
+ return errs
+ },
+ }
+
+ acctest.TestPlugin(t, testCase)
+}
+
+//go:embed test-fixtures/basic_amazon_bundled.json
+var basicAmazonBundledEbsTemplateJSON string
+
+func TestAccBuildBundledPluginsJSON(t *testing.T) {
+ plugin := addrs.Plugin{
+ Hostname: "github.com",
+ Namespace: "hashicorp",
+ Type: "amazon",
+ }
+ testCase := &acctest.PluginTestCase{
+ Name: "amazon-ebs_bundled_test_json",
+ Setup: func() error {
+ return cleanupPluginInstallation(plugin)
+ },
+ Teardown: func() error {
+ helper := amazonacc.AMIHelper{
+ Region: "us-east-1",
+ Name: "packer-plugin-bundled-amazon-ebs-test-json",
+ }
+ return helper.CleanUpAmi()
+ },
+ Template: basicAmazonBundledEbsTemplateJSON,
+ Type: "amazon-ebs",
+ Init: false,
+ 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)
+ }
+ }
+
+ rawLogs, err := os.ReadFile(logfile)
+ if err != nil {
+ return fmt.Errorf("failed to read logs: %s", err)
+ }
+
+ var errs error
+
+ logs := string(rawLogs)
+
+ if !strings.Contains(logs, "Warning: Bundled plugins used") {
+ errs = multierror.Append(errs, errors.New("expected warning about bundled plugins, did not find it."))
+ }
+
+ if !strings.Contains(logs, "plugins with the 'packer plugins install' command") {
+ errs = multierror.Append(errs, errors.New("expected suggestion about packer plugins install in logs, did not find it."))
+ }
+
+ return errs
+ },
+ }
+
+ acctest.TestPlugin(t, testCase)
+}
diff --git a/v1.9.4/acctest/plugin/component_acc_test.go b/v1.9.4/acctest/plugin/component_acc_test.go
new file mode 100644
index 0000000..ff77adf
--- /dev/null
+++ b/v1.9.4/acctest/plugin/component_acc_test.go
@@ -0,0 +1,74 @@
+// Copyright (c) HashiCorp, Inc.
+// SPDX-License-Identifier: MPL-2.0
+
+// component_acc_test.go should contain acceptance tests for plugin components
+// to make sure all component types can be discovered and started.
+package plugin
+
+import (
+ _ "embed"
+ "fmt"
+ "io/ioutil"
+ "os"
+ "os/exec"
+ "testing"
+
+ amazonacc "github.com/hashicorp/packer-plugin-amazon/builder/ebs/acceptance"
+ "github.com/hashicorp/packer-plugin-sdk/acctest"
+ "github.com/hashicorp/packer/hcl2template/addrs"
+)
+
+//go:embed test-fixtures/basic-amazon-ami-datasource.pkr.hcl
+var basicAmazonAmiDatasourceHCL2Template string
+
+func TestAccInitAndBuildBasicAmazonAmiDatasource(t *testing.T) {
+ plugin := addrs.Plugin{
+ Hostname: "github.com",
+ Namespace: "hashicorp",
+ Type: "amazon",
+ }
+ testCase := &acctest.PluginTestCase{
+ Name: "amazon-ami_basic_datasource_test",
+ Setup: func() error {
+ return cleanupPluginInstallation(plugin)
+ },
+ Teardown: func() error {
+ helper := amazonacc.AMIHelper{
+ Region: "us-west-2",
+ Name: "packer-amazon-ami-test",
+ }
+ return helper.CleanUpAmi()
+ },
+ Template: basicAmazonAmiDatasourceHCL2Template,
+ Type: "amazon-ami",
+ Init: true,
+ CheckInit: func(initCommand *exec.Cmd, logfile string) error {
+ if initCommand.ProcessState != nil {
+ if initCommand.ProcessState.ExitCode() != 0 {
+ return fmt.Errorf("Bad exit code. Logfile: %s", logfile)
+ }
+ }
+ logs, err := os.Open(logfile)
+ if err != nil {
+ return fmt.Errorf("Unable find %s", logfile)
+ }
+ defer logs.Close()
+
+ logsBytes, err := ioutil.ReadAll(logs)
+ if err != nil {
+ return fmt.Errorf("Unable to read %s", logfile)
+ }
+ initOutput := string(logsBytes)
+ return checkPluginInstallation(initOutput, plugin)
+ },
+ 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)
+ }
+ }
+ return nil
+ },
+ }
+ acctest.TestPlugin(t, testCase)
+}
diff --git a/v1.9.4/acctest/plugin/plugin_acc_test.go b/v1.9.4/acctest/plugin/plugin_acc_test.go
new file mode 100644
index 0000000..9e69afe
--- /dev/null
+++ b/v1.9.4/acctest/plugin/plugin_acc_test.go
@@ -0,0 +1,136 @@
+// Copyright (c) HashiCorp, Inc.
+// SPDX-License-Identifier: MPL-2.0
+
+// plugin_acc_test.go should contain acceptance tests for features related to
+// installing, discovering and running plugins.
+package plugin
+
+import (
+ _ "embed"
+ "fmt"
+ "io/ioutil"
+ "os"
+ "os/exec"
+ "path/filepath"
+ "regexp"
+ "testing"
+
+ amazonacc "github.com/hashicorp/packer-plugin-amazon/builder/ebs/acceptance"
+ "github.com/hashicorp/packer-plugin-sdk/acctest"
+ "github.com/hashicorp/packer-plugin-sdk/acctest/testutils"
+ "github.com/hashicorp/packer/hcl2template/addrs"
+ "github.com/mitchellh/go-homedir"
+)
+
+//go:embed test-fixtures/basic-amazon-ebs.pkr.hcl
+var basicAmazonEbsHCL2Template string
+
+func TestAccInitAndBuildBasicAmazonEbs(t *testing.T) {
+ plugin := addrs.Plugin{
+ Hostname: "github.com",
+ Namespace: "hashicorp",
+ Type: "amazon",
+ }
+ testCase := &acctest.PluginTestCase{
+ Name: "amazon-ebs_basic_plugin_init_and_build_test",
+ Setup: func() error {
+ return cleanupPluginInstallation(plugin)
+ },
+ Teardown: func() error {
+ helper := amazonacc.AMIHelper{
+ Region: "us-east-1",
+ Name: "packer-plugin-amazon-ebs-test",
+ }
+ return helper.CleanUpAmi()
+ },
+ Template: basicAmazonEbsHCL2Template,
+ Type: "amazon-ebs",
+ Init: true,
+ CheckInit: func(initCommand *exec.Cmd, logfile string) error {
+ if initCommand.ProcessState != nil {
+ if initCommand.ProcessState.ExitCode() != 0 {
+ return fmt.Errorf("Bad exit code. Logfile: %s", logfile)
+ }
+ }
+ logs, err := os.Open(logfile)
+ if err != nil {
+ return fmt.Errorf("Unable find %s", logfile)
+ }
+ defer logs.Close()
+
+ logsBytes, err := ioutil.ReadAll(logs)
+ if err != nil {
+ return fmt.Errorf("Unable to read %s", logfile)
+ }
+ initOutput := string(logsBytes)
+ return checkPluginInstallation(initOutput, plugin)
+ },
+ 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)
+ }
+ }
+ return nil
+ },
+ }
+ acctest.TestPlugin(t, testCase)
+}
+
+func cleanupPluginInstallation(plugin addrs.Plugin) error {
+ home, err := homedir.Dir()
+ if err != nil {
+ return err
+ }
+ pluginPath := filepath.Join(home,
+ ".packer.d",
+ "plugins",
+ plugin.Hostname,
+ plugin.Namespace,
+ plugin.Type)
+
+ if xdgConfigHome := os.Getenv("XDG_CONFIG_HOME"); xdgConfigHome != "" {
+ pluginPath = filepath.Join(xdgConfigHome,
+ "packer",
+ "plugins",
+ plugin.Hostname,
+ plugin.Namespace,
+ plugin.Type)
+ }
+
+ testutils.CleanupFiles(pluginPath)
+ return nil
+}
+
+func checkPluginInstallation(initOutput string, plugin addrs.Plugin) error {
+ expectedInitLog := "Installed plugin " + plugin.String()
+ if matched, _ := regexp.MatchString(expectedInitLog+".*", initOutput); !matched {
+ return fmt.Errorf("logs doesn't contain expected foo value %q", initOutput)
+ }
+
+ home, err := homedir.Dir()
+ if err != nil {
+ return err
+ }
+
+ pluginPath := filepath.Join(home,
+ ".packer.d",
+ "plugins",
+ plugin.Hostname,
+ plugin.Namespace,
+ plugin.Type)
+
+ if xdgConfigHome := os.Getenv("XDG_CONFIG_HOME"); xdgConfigHome != "" {
+ pluginPath = filepath.Join(xdgConfigHome,
+ "packer",
+ "plugins",
+ plugin.Hostname,
+ plugin.Namespace,
+ plugin.Type)
+ }
+
+ if !testutils.FileExists(pluginPath) {
+ return fmt.Errorf("%s plugin installation not found", plugin.String())
+ }
+ return nil
+}
diff --git a/v1.9.4/acctest/plugin/test-fixtures/basic-amazon-ami-datasource.pkr.hcl b/v1.9.4/acctest/plugin/test-fixtures/basic-amazon-ami-datasource.pkr.hcl
new file mode 100644
index 0000000..b3c4696
--- /dev/null
+++ b/v1.9.4/acctest/plugin/test-fixtures/basic-amazon-ami-datasource.pkr.hcl
@@ -0,0 +1,34 @@
+packer {
+ required_plugins {
+ amazon = {
+ version = ">= 0.0.1"
+ source = "github.com/hashicorp/amazon"
+ }
+ }
+}
+
+data "amazon-ami" "test" {
+ filters = {
+ name = "ubuntu/images/*ubuntu-xenial-16.04-amd64-server-*"
+ root-device-type = "ebs"
+ virtualization-type = "hvm"
+ }
+ region = "us-west-2"
+ most_recent = true
+ owners = ["099720109477"]
+}
+
+source "amazon-ebs" "basic-example" {
+ region = "us-west-2"
+ source_ami = data.amazon-ami.test.id
+ ami_name = "packer-amazon-ami-test"
+ communicator = "ssh"
+ instance_type = "t2.micro"
+ ssh_username = "ubuntu"
+}
+
+build {
+ sources = [
+ "source.amazon-ebs.basic-example"
+ ]
+}
diff --git a/v1.9.4/acctest/plugin/test-fixtures/basic-amazon-ebs.pkr.hcl b/v1.9.4/acctest/plugin/test-fixtures/basic-amazon-ebs.pkr.hcl
new file mode 100644
index 0000000..aa9399a
--- /dev/null
+++ b/v1.9.4/acctest/plugin/test-fixtures/basic-amazon-ebs.pkr.hcl
@@ -0,0 +1,20 @@
+packer {
+ required_plugins {
+ amazon = {
+ version = ">= 0.0.1"
+ source = "github.com/hashicorp/amazon"
+ }
+ }
+}
+
+source "amazon-ebs" "basic-test" {
+ region = "us-east-1"
+ instance_type = "m3.medium"
+ source_ami = "ami-76b2a71e"
+ ssh_username = "ubuntu"
+ ami_name = "packer-plugin-amazon-ebs-test"
+}
+
+build {
+ sources = ["source.amazon-ebs.basic-test"]
+}
diff --git a/v1.9.4/acctest/plugin/test-fixtures/basic_amazon_bundled.json b/v1.9.4/acctest/plugin/test-fixtures/basic_amazon_bundled.json
new file mode 100644
index 0000000..f674cd1
--- /dev/null
+++ b/v1.9.4/acctest/plugin/test-fixtures/basic_amazon_bundled.json
@@ -0,0 +1,10 @@
+{
+ "builders": [{
+ "type": "amazon-ebs",
+ "region": "us-east-1",
+ "instance_type": "m3.medium",
+ "source_ami": "ami-76b2a71e",
+ "ssh_username": "ubuntu",
+ "ami_name": "packer-plugin-bundled-amazon-ebs-test-json"
+ }]
+}
diff --git a/v1.9.4/acctest/plugin/test-fixtures/basic_amazon_bundled.pkr.hcl b/v1.9.4/acctest/plugin/test-fixtures/basic_amazon_bundled.pkr.hcl
new file mode 100644
index 0000000..c17a09d
--- /dev/null
+++ b/v1.9.4/acctest/plugin/test-fixtures/basic_amazon_bundled.pkr.hcl
@@ -0,0 +1,11 @@
+source "amazon-ebs" "basic-test" {
+ region = "us-east-1"
+ instance_type = "m3.medium"
+ source_ami = "ami-76b2a71e"
+ ssh_username = "ubuntu"
+ ami_name = "packer-plugin-bundled-amazon-ebs-test"
+}
+
+build {
+ sources = ["source.amazon-ebs.basic-test"]
+}
diff --git a/v1.9.4/acctest/plugin/test-fixtures/basic_amazon_with_required_plugins.pkr.hcl b/v1.9.4/acctest/plugin/test-fixtures/basic_amazon_with_required_plugins.pkr.hcl
new file mode 100644
index 0000000..a30f85f
--- /dev/null
+++ b/v1.9.4/acctest/plugin/test-fixtures/basic_amazon_with_required_plugins.pkr.hcl
@@ -0,0 +1,20 @@
+packer {
+ required_plugins {
+ amazon = {
+ source = "github.com/hashicorp/amazon",
+ version = "~> 1"
+ }
+ }
+}
+
+source "amazon-ebs" "basic-test" {
+ region = "us-east-1"
+ instance_type = "m3.medium"
+ source_ami = "ami-76b2a71e"
+ ssh_username = "ubuntu"
+ ami_name = "packer-plugin-external-amazon-ebs-test"
+}
+
+build {
+ sources = ["source.amazon-ebs.basic-test"]
+}
diff --git a/v1.9.4/acctest/testing.go b/v1.9.4/acctest/testing.go
new file mode 100644
index 0000000..e716ec9
--- /dev/null
+++ b/v1.9.4/acctest/testing.go
@@ -0,0 +1,227 @@
+// Copyright (c) HashiCorp, Inc.
+// SPDX-License-Identifier: MPL-2.0
+
+package acctest
+
+import (
+ "context"
+ "fmt"
+ "io/ioutil"
+ "log"
+ "os"
+ "strings"
+ "testing"
+
+ packersdk "github.com/hashicorp/packer-plugin-sdk/packer"
+ "github.com/hashicorp/packer-plugin-sdk/template"
+ "github.com/hashicorp/packer/packer"
+ "github.com/hashicorp/packer/provisioner/file"
+ shellprovisioner "github.com/hashicorp/packer/provisioner/shell"
+)
+
+// TestEnvVar must be set to a non-empty value for acceptance tests to run.
+const TestEnvVar = "PACKER_ACC"
+
+// TestCase is a single set of tests to run for a backend. A TestCase
+// should generally map 1:1 to each test method for your acceptance
+// tests.
+type TestCase struct {
+ // Precheck, if non-nil, will be called once before the test case
+ // runs at all. This can be used for some validation prior to the
+ // test running.
+ PreCheck func()
+
+ // Builder is the Builder that will be tested. It will be available
+ // as the "test" builder in the template.
+ Builder packersdk.Builder
+
+ // Template is the template contents to use.
+ Template string
+
+ // 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 TestCheckFunc
+
+ // 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 TestTeardownFunc
+
+ // If SkipArtifactTeardown is true, we will not attempt to destroy the
+ // artifact created in this test run.
+ SkipArtifactTeardown bool
+ // If set, overrides the default provisioner store with custom provisioners.
+ // This can be useful for running acceptance tests for a particular
+ // provisioner using a specific builder.
+ // Default provisioner store:
+ // ProvisionerStore: packersdk.MapOfProvisioner{
+ // "shell": func() (packersdk.Provisioner, error) { return &shellprovisioner.Provisioner{}, nil },
+ // "file": func() (packersdk.Provisioner, error) { return &file.Provisioner{}, nil },
+ // },
+ ProvisionerStore packersdk.MapOfProvisioner
+}
+
+// TestCheckFunc is the callback used for Check in TestStep.
+type TestCheckFunc func([]packersdk.Artifact) error
+
+// TestTeardownFunc is the callback used for Teardown in TestCase.
+type TestTeardownFunc func() error
+
+// TestT is the interface used to handle the test lifecycle of a test.
+//
+// Users should just use a *testing.T object, which implements this.
+type TestT interface {
+ Error(args ...interface{})
+ Fatal(args ...interface{})
+ Skip(args ...interface{})
+}
+
+type TestBuilderSet struct {
+ packer.BuilderSet
+ StartFn func(name string) (packersdk.Builder, error)
+}
+
+func (tbs TestBuilderSet) Start(name string) (packersdk.Builder, error) { return tbs.StartFn(name) }
+
+// Test performs an acceptance test on a backend with the given test case.
+//
+// Tests are not run unless an environmental variable "PACKER_ACC" is
+// set to some non-empty value. This is to avoid test cases surprising
+// a user by creating real resources.
+//
+// Tests will fail unless the verbose flag (`go test -v`, or explicitly
+// the "-test.v" flag) is set. Because some acceptance tests take quite
+// long, we require the verbose flag so users are able to see progress
+// output.
+func Test(t TestT, c TestCase) {
+ // We only run acceptance tests if an env var is set because they're
+ // slow and generally require some outside configuration.
+ if os.Getenv(TestEnvVar) == "" {
+ t.Skip(fmt.Sprintf(
+ "Acceptance tests skipped unless env '%s' set",
+ TestEnvVar))
+ return
+ }
+
+ // We require verbose mode so that the user knows what is going on.
+ if !testTesting && !testing.Verbose() {
+ t.Fatal("Acceptance tests must be run with the -v flag on tests")
+ return
+ }
+
+ // Run the PreCheck if we have it
+ if c.PreCheck != nil {
+ c.PreCheck()
+ }
+
+ // Parse the template
+ log.Printf("[DEBUG] Parsing template...")
+ tpl, err := template.Parse(strings.NewReader(c.Template))
+ if err != nil {
+ t.Fatal(fmt.Sprintf("Failed to parse template: %s", err))
+ return
+ }
+
+ if c.ProvisionerStore == nil {
+ c.ProvisionerStore = packersdk.MapOfProvisioner{
+ "shell": func() (packersdk.Provisioner, error) { return &shellprovisioner.Provisioner{}, nil },
+ "file": func() (packersdk.Provisioner, error) { return &file.Provisioner{}, nil },
+ }
+ }
+ // Build the core
+ log.Printf("[DEBUG] Initializing core...")
+ core := packer.NewCore(&packer.CoreConfig{
+ Components: packer.ComponentFinder{
+ PluginConfig: &packer.PluginConfig{
+ Builders: TestBuilderSet{
+ StartFn: func(n string) (packersdk.Builder, error) {
+ if n == "test" {
+ return c.Builder, nil
+ }
+
+ return nil, nil
+ },
+ },
+ Provisioners: c.ProvisionerStore,
+ },
+ },
+ Template: tpl,
+ })
+ diags := core.Initialize(packer.InitializeOptions{})
+ if diags.HasErrors() {
+ t.Fatal(fmt.Sprintf("Failed to init core: %s", err))
+ return
+ }
+
+ // Get the build
+ log.Printf("[DEBUG] Retrieving 'test' build")
+ build, err := core.Build("test")
+ if err != nil {
+ t.Fatal(fmt.Sprintf("Failed to get 'test' build: %s", err))
+ return
+ }
+
+ // Prepare it
+ log.Printf("[DEBUG] Preparing 'test' build")
+ warnings, err := build.Prepare()
+ if err != nil {
+ t.Fatal(fmt.Sprintf("Prepare error: %s", err))
+ return
+ }
+ if len(warnings) > 0 {
+ t.Fatal(fmt.Sprintf(
+ "Prepare warnings:\n\n%s",
+ strings.Join(warnings, "\n")))
+ return
+ }
+
+ // Run it! We use a temporary directory for caching and discard
+ // any UI output. We discard since it shows up in logs anyways.
+ log.Printf("[DEBUG] Running 'test' build")
+ ui := &packersdk.BasicUi{
+ Reader: os.Stdin,
+ Writer: ioutil.Discard,
+ ErrorWriter: ioutil.Discard,
+ PB: &packersdk.NoopProgressTracker{},
+ }
+ artifacts, err := build.Run(context.Background(), ui)
+ if err != nil {
+ t.Fatal(fmt.Sprintf("Run error:\n\n%s", err))
+ goto TEARDOWN
+ }
+
+ // Check function
+ if c.Check != nil {
+ log.Printf("[DEBUG] Running check function")
+ if err := c.Check(artifacts); err != nil {
+ t.Fatal(fmt.Sprintf("Check error:\n\n%s", err))
+ goto TEARDOWN
+ }
+ }
+
+TEARDOWN:
+ if !c.SkipArtifactTeardown {
+ // Delete all artifacts
+ for _, a := range artifacts {
+ if err := a.Destroy(); err != nil {
+ t.Error(fmt.Sprintf(
+ "!!! ERROR REMOVING ARTIFACT '%s': %s !!!",
+ a.String(), err))
+ }
+ }
+ }
+
+ // Teardown
+ if c.Teardown != nil {
+ log.Printf("[DEBUG] Running teardown function")
+ if err := c.Teardown(); err != nil {
+ t.Fatal(fmt.Sprintf("Teardown failure:\n\n%s", err))
+ return
+ }
+ }
+}
+
+// This is for unit tests of this package.
+var testTesting = false
diff --git a/v1.9.4/acctest/testing_test.go b/v1.9.4/acctest/testing_test.go
new file mode 100644
index 0000000..71247d4
--- /dev/null
+++ b/v1.9.4/acctest/testing_test.go
@@ -0,0 +1,72 @@
+// Copyright (c) HashiCorp, Inc.
+// SPDX-License-Identifier: MPL-2.0
+
+package acctest
+
+import (
+ "os"
+ "testing"
+)
+
+func init() {
+ testTesting = true
+
+ if err := os.Setenv(TestEnvVar, "1"); err != nil {
+ panic(err)
+ }
+}
+
+func TestTest_noEnv(t *testing.T) {
+ // Unset the variable
+ t.Setenv(TestEnvVar, "")
+
+ mt := new(mockT)
+ Test(mt, TestCase{})
+
+ if !mt.SkipCalled {
+ t.Fatal("skip not called")
+ }
+}
+
+func TestTest_preCheck(t *testing.T) {
+ called := false
+
+ mt := new(mockT)
+ Test(mt, TestCase{
+ PreCheck: func() { called = true },
+ })
+
+ if !called {
+ t.Fatal("precheck should be called")
+ }
+}
+
+// mockT implements TestT for testing
+type mockT struct {
+ ErrorCalled bool
+ ErrorArgs []interface{}
+ FatalCalled bool
+ FatalArgs []interface{}
+ SkipCalled bool
+ SkipArgs []interface{}
+
+ f bool
+}
+
+func (t *mockT) Error(args ...interface{}) {
+ t.ErrorCalled = true
+ t.ErrorArgs = args
+ t.f = true
+}
+
+func (t *mockT) Fatal(args ...interface{}) {
+ t.FatalCalled = true
+ t.FatalArgs = args
+ t.f = true
+}
+
+func (t *mockT) Skip(args ...interface{}) {
+ t.SkipCalled = true
+ t.SkipArgs = args
+ t.f = true
+}
diff --git a/v1.9.4/background_check.go b/v1.9.4/background_check.go
new file mode 100644
index 0000000..3eaf7ee
--- /dev/null
+++ b/v1.9.4/background_check.go
@@ -0,0 +1,26 @@
+// Copyright (c) HashiCorp, Inc.
+// SPDX-License-Identifier: MPL-2.0
+
+//go:build !openbsd
+// +build !openbsd
+
+package main
+
+import (
+ "fmt"
+
+ "github.com/shirou/gopsutil/v3/process"
+)
+
+func checkProcess(currentPID int) (bool, error) {
+ myProc, err := process.NewProcess(int32(currentPID))
+ if err != nil {
+ return false, fmt.Errorf("Process check error: %s", err)
+ }
+ bg, err := myProc.Background()
+ if err != nil {
+ return bg, fmt.Errorf("Process background check error: %s", err)
+ }
+
+ return bg, nil
+}
diff --git a/v1.9.4/background_check_openbsd.go b/v1.9.4/background_check_openbsd.go
new file mode 100644
index 0000000..ff2ef4b
--- /dev/null
+++ b/v1.9.4/background_check_openbsd.go
@@ -0,0 +1,13 @@
+// Copyright (c) HashiCorp, Inc.
+// SPDX-License-Identifier: MPL-2.0
+
+package main
+
+import (
+ "fmt"
+)
+
+func checkProcess(currentPID int) (bool, error) {
+ return false, fmt.Errorf("cannot determine if process is backgrounded in " +
+ "openbsd")
+}
diff --git a/v1.9.4/builder/file/artifact.go b/v1.9.4/builder/file/artifact.go
new file mode 100644
index 0000000..9b9ed8e
--- /dev/null
+++ b/v1.9.4/builder/file/artifact.go
@@ -0,0 +1,58 @@
+// Copyright (c) HashiCorp, Inc.
+// SPDX-License-Identifier: MPL-2.0
+
+package file
+
+import (
+ "fmt"
+ "log"
+ "os"
+ "path"
+
+ registryimage "github.com/hashicorp/packer-plugin-sdk/packer/registry/image"
+)
+
+type FileArtifact struct {
+ source string
+ filename string
+}
+
+func (*FileArtifact) BuilderId() string {
+ return BuilderId
+}
+
+func (a *FileArtifact) Files() []string {
+ return []string{a.filename}
+}
+
+func (a *FileArtifact) Id() string {
+ return "File"
+}
+
+func (a *FileArtifact) String() string {
+ return fmt.Sprintf("Stored file: %s", a.filename)
+}
+
+func (a *FileArtifact) State(name string) interface{} {
+ if name == registryimage.ArtifactStateURI {
+ img, err := registryimage.FromArtifact(a,
+ registryimage.WithID(path.Base(a.filename)),
+ registryimage.WithRegion(path.Dir(a.filename)),
+ registryimage.WithSourceID(a.source),
+ )
+
+ if err != nil {
+ log.Printf("[DEBUG] error encountered when creating a registry image %v", err)
+ return nil
+ }
+
+ return img
+ }
+
+ return nil
+}
+
+func (a *FileArtifact) Destroy() error {
+ log.Printf("Deleting %s", a.filename)
+ return os.Remove(a.filename)
+}
diff --git a/v1.9.4/builder/file/artifact_test.go b/v1.9.4/builder/file/artifact_test.go
new file mode 100644
index 0000000..ea799e1
--- /dev/null
+++ b/v1.9.4/builder/file/artifact_test.go
@@ -0,0 +1,14 @@
+// Copyright (c) HashiCorp, Inc.
+// SPDX-License-Identifier: MPL-2.0
+
+package file
+
+import (
+ "testing"
+
+ packersdk "github.com/hashicorp/packer-plugin-sdk/packer"
+)
+
+func TestNullArtifact(t *testing.T) {
+ var _ packersdk.Artifact = new(FileArtifact)
+}
diff --git a/v1.9.4/builder/file/builder.go b/v1.9.4/builder/file/builder.go
new file mode 100644
index 0000000..e6df9b5
--- /dev/null
+++ b/v1.9.4/builder/file/builder.go
@@ -0,0 +1,95 @@
+// Copyright (c) HashiCorp, Inc.
+// SPDX-License-Identifier: MPL-2.0
+
+package file
+
+/*
+The File builder creates an artifact from a file. Because it does not require
+any virtualization or network resources, it's very fast and useful for testing.
+*/
+
+import (
+ "context"
+ "fmt"
+ "io"
+ "io/ioutil"
+ "os"
+ "path/filepath"
+
+ "github.com/hashicorp/hcl/v2/hcldec"
+ "github.com/hashicorp/packer-plugin-sdk/multistep"
+ packersdk "github.com/hashicorp/packer-plugin-sdk/packer"
+)
+
+const BuilderId = "packer.file"
+
+type Builder struct {
+ config Config
+ runner multistep.Runner
+}
+
+func (b *Builder) ConfigSpec() hcldec.ObjectSpec { return b.config.FlatMapstructure().HCL2Spec() }
+
+func (b *Builder) Prepare(raws ...interface{}) ([]string, []string, error) {
+ warnings, errs := b.config.Prepare(raws...)
+ if errs != nil {
+ return nil, warnings, errs
+ }
+
+ return nil, warnings, nil
+}
+
+// Run is where the actual build should take place. It takes a Build and a Ui.
+func (b *Builder) Run(ctx context.Context, ui packersdk.Ui, hook packersdk.Hook) (packersdk.Artifact, error) {
+ artifact := new(FileArtifact)
+
+ // Create all directories leading to target
+ dir := filepath.Dir(b.config.Target)
+ if dir != "." {
+ if err := os.MkdirAll(dir, 0755); err != nil {
+ return nil, err
+ }
+ }
+
+ if b.config.Source != "" {
+ source, err := os.Open(b.config.Source)
+ if err != nil {
+ return nil, err
+ }
+ defer source.Close()
+
+ // Create will truncate an existing file
+ target, err := os.Create(b.config.Target)
+ if err != nil {
+ return nil, err
+ }
+ defer target.Close()
+
+ ui.Say(fmt.Sprintf("Copying %s to %s", source.Name(), target.Name()))
+ bytes, err := io.Copy(target, source)
+ if err != nil {
+ return nil, err
+ }
+ ui.Say(fmt.Sprintf("Copied %d bytes", bytes))
+
+ artifact.source = b.config.Source
+ artifact.filename = target.Name()
+ } else {
+ // We're going to write Contents; if it's empty we'll just create an
+ // empty file.
+ err := ioutil.WriteFile(b.config.Target, []byte(b.config.Content), 0600)
+ if err != nil {
+ return nil, err
+ }
+ artifact.source = "<no-defined-source-file>"
+ artifact.filename = b.config.Target
+ }
+
+ if hook != nil {
+ if err := hook.Run(ctx, packersdk.HookProvision, ui, new(packersdk.MockCommunicator), nil); err != nil {
+ return nil, err
+ }
+ }
+
+ return artifact, nil
+}
diff --git a/v1.9.4/builder/file/builder_test.go b/v1.9.4/builder/file/builder_test.go
new file mode 100644
index 0000000..dfa8727
--- /dev/null
+++ b/v1.9.4/builder/file/builder_test.go
@@ -0,0 +1,81 @@
+// Copyright (c) HashiCorp, Inc.
+// SPDX-License-Identifier: MPL-2.0
+
+package file
+
+import (
+ "fmt"
+ "io/ioutil"
+ "testing"
+
+ packersdk "github.com/hashicorp/packer-plugin-sdk/packer"
+ builderT "github.com/hashicorp/packer/acctest"
+)
+
+func TestBuilder_implBuilder(t *testing.T) {
+ var _ packersdk.Builder = new(Builder)
+}
+
+func TestBuilderFileAcc_content(t *testing.T) {
+ builderT.Test(t, builderT.TestCase{
+ Builder: &Builder{},
+ Template: fileContentTest,
+ Check: checkContent,
+ })
+}
+
+func TestBuilderFileAcc_copy(t *testing.T) {
+ builderT.Test(t, builderT.TestCase{
+ Builder: &Builder{},
+ Template: fileCopyTest,
+ Check: checkCopy,
+ })
+}
+
+func checkContent(artifacts []packersdk.Artifact) error {
+ content, err := ioutil.ReadFile("contentTest.txt")
+ if err != nil {
+ return err
+ }
+ contentString := string(content)
+ if contentString != "hello world!" {
+ return fmt.Errorf("Unexpected file contents: %s", contentString)
+ }
+ return nil
+}
+
+func checkCopy(artifacts []packersdk.Artifact) error {
+ content, err := ioutil.ReadFile("copyTest.txt")
+ if err != nil {
+ return err
+ }
+ contentString := string(content)
+ if contentString != "Hello world.\n" {
+ return fmt.Errorf("Unexpected file contents: %s", contentString)
+ }
+ return nil
+}
+
+const fileContentTest = `
+{
+ "builders": [
+ {
+ "type":"test",
+ "target":"contentTest.txt",
+ "content":"hello world!"
+ }
+ ]
+}
+`
+
+const fileCopyTest = `
+{
+ "builders": [
+ {
+ "type":"test",
+ "target":"copyTest.txt",
+ "source":"test-fixtures/artifact.txt"
+ }
+ ]
+}
+`
diff --git a/v1.9.4/builder/file/config.go b/v1.9.4/builder/file/config.go
new file mode 100644
index 0000000..017355e
--- /dev/null
+++ b/v1.9.4/builder/file/config.go
@@ -0,0 +1,60 @@
+// Copyright (c) HashiCorp, Inc.
+// SPDX-License-Identifier: MPL-2.0
+
+//go:generate packer-sdc mapstructure-to-hcl2 -type Config
+
+package file
+
+import (
+ "fmt"
+
+ "github.com/hashicorp/packer-plugin-sdk/common"
+ packersdk "github.com/hashicorp/packer-plugin-sdk/packer"
+ "github.com/hashicorp/packer-plugin-sdk/template/config"
+ "github.com/hashicorp/packer-plugin-sdk/template/interpolate"
+)
+
+var ErrTargetRequired = fmt.Errorf("target required")
+var ErrContentSourceConflict = fmt.Errorf("Cannot specify source file AND content")
+
+type Config struct {
+ common.PackerConfig `mapstructure:",squash"`
+
+ Source string `mapstructure:"source"`
+ Target string `mapstructure:"target"`
+ Content string `mapstructure:"content"`
+}
+
+func (c *Config) Prepare(raws ...interface{}) ([]string, error) {
+ warnings := []string{}
+
+ err := config.Decode(c, &config.DecodeOpts{
+ Interpolate: true,
+ InterpolateFilter: &interpolate.RenderFilter{
+ Exclude: []string{},
+ },
+ }, raws...)
+ if err != nil {
+ return warnings, err
+ }
+
+ var errs *packersdk.MultiError
+
+ if c.Target == "" {
+ errs = packersdk.MultiErrorAppend(errs, ErrTargetRequired)
+ }
+
+ if c.Content == "" && c.Source == "" {
+ warnings = append(warnings, "Both source file and contents are blank; target will have no content")
+ }
+
+ if c.Content != "" && c.Source != "" {
+ errs = packersdk.MultiErrorAppend(errs, ErrContentSourceConflict)
+ }
+
+ if errs != nil && len(errs.Errors) > 0 {
+ return warnings, errs
+ }
+
+ return warnings, nil
+}
diff --git a/v1.9.4/builder/file/config.hcl2spec.go b/v1.9.4/builder/file/config.hcl2spec.go
new file mode 100644
index 0000000..0ddc9ac
--- /dev/null
+++ b/v1.9.4/builder/file/config.hcl2spec.go
@@ -0,0 +1,51 @@
+// Code generated by "packer-sdc mapstructure-to-hcl2"; DO NOT EDIT.
+
+package file
+
+import (
+ "github.com/hashicorp/hcl/v2/hcldec"
+ "github.com/zclconf/go-cty/cty"
+)
+
+// FlatConfig is an auto-generated flat version of Config.
+// Where the contents of a field with a `mapstructure:,squash` tag are bubbled up.
+type FlatConfig struct {
+ PackerBuildName *string `mapstructure:"packer_build_name" cty:"packer_build_name" 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"`
+ Source *string `mapstructure:"source" cty:"source" hcl:"source"`
+ Target *string `mapstructure:"target" cty:"target" hcl:"target"`
+ Content *string `mapstructure:"content" cty:"content" hcl:"content"`
+}
+
+// FlatMapstructure returns a new FlatConfig.
+// FlatConfig is an auto-generated flat version of Config.
+// Where the contents a fields with a `mapstructure:,squash` tag are bubbled up.
+func (*Config) FlatMapstructure() interface{ HCL2Spec() map[string]hcldec.Spec } {
+ return new(FlatConfig)
+}
+
+// HCL2Spec returns the hcl spec of a Config.
+// This spec is used by HCL to read the fields of Config.
+// The decoded values from this spec will then be applied to a FlatConfig.
+func (*FlatConfig) HCL2Spec() map[string]hcldec.Spec {
+ s := map[string]hcldec.Spec{
+ "packer_build_name": &hcldec.AttrSpec{Name: "packer_build_name", Type: cty.String, Required: false},
+ "packer_builder_type": &hcldec.AttrSpec{Name: "packer_builder_type", Type: cty.String, Required: false},
+ "packer_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_sensitive_variables": &hcldec.AttrSpec{Name: "packer_sensitive_variables", Type: cty.List(cty.String), Required: false},
+ "source": &hcldec.AttrSpec{Name: "source", Type: cty.String, Required: false},
+ "target": &hcldec.AttrSpec{Name: "target", Type: cty.String, Required: false},
+ "content": &hcldec.AttrSpec{Name: "content", Type: cty.String, Required: false},
+ }
+ return s
+}
diff --git a/v1.9.4/builder/file/config_test.go b/v1.9.4/builder/file/config_test.go
new file mode 100644
index 0000000..60d3553
--- /dev/null
+++ b/v1.9.4/builder/file/config_test.go
@@ -0,0 +1,51 @@
+// Copyright (c) HashiCorp, Inc.
+// SPDX-License-Identifier: MPL-2.0
+
+package file
+
+import (
+ "strings"
+ "testing"
+)
+
+func testConfig() map[string]interface{} {
+ return map[string]interface{}{
+ "source": "src.txt",
+ "target": "dst.txt",
+ "content": "Hello, world!",
+ }
+}
+
+func TestContentSourceConflict(t *testing.T) {
+ raw := testConfig()
+
+ var c Config
+ _, errs := c.Prepare(raw)
+ if !strings.Contains(errs.Error(), ErrContentSourceConflict.Error()) {
+ t.Errorf("Expected config error: %s", ErrContentSourceConflict.Error())
+ }
+}
+
+func TestNoFilename(t *testing.T) {
+ raw := testConfig()
+
+ delete(raw, "filename")
+ var c Config
+ _, errs := c.Prepare(raw)
+ if errs == nil {
+ t.Errorf("Expected config error: %s", ErrTargetRequired.Error())
+ }
+}
+
+func TestNoContent(t *testing.T) {
+ raw := testConfig()
+
+ delete(raw, "content")
+ delete(raw, "source")
+ var c Config
+ warns, _ := c.Prepare(raw)
+
+ if len(warns) == 0 {
+ t.Error("Expected config warning without any content")
+ }
+}
diff --git a/v1.9.4/builder/file/test-fixtures/artifact.txt b/v1.9.4/builder/file/test-fixtures/artifact.txt
new file mode 100644
index 0000000..18249f3
--- /dev/null
+++ b/v1.9.4/builder/file/test-fixtures/artifact.txt
@@ -0,0 +1 @@
+Hello world.
diff --git a/v1.9.4/builder/file/version/version.go b/v1.9.4/builder/file/version/version.go
new file mode 100644
index 0000000..3cb6b9e
--- /dev/null
+++ b/v1.9.4/builder/file/version/version.go
@@ -0,0 +1,16 @@
+// Copyright (c) HashiCorp, Inc.
+// SPDX-License-Identifier: MPL-2.0
+
+package version
+
+import (
+ "github.com/hashicorp/packer-plugin-sdk/version"
+ packerVersion "github.com/hashicorp/packer/version"
+)
+
+var FilePluginVersion *version.PluginVersion
+
+func init() {
+ FilePluginVersion = version.InitializePluginVersion(
+ packerVersion.Version, packerVersion.VersionPrerelease)
+}
diff --git a/v1.9.4/builder/null/artifact_export.go b/v1.9.4/builder/null/artifact_export.go
new file mode 100644
index 0000000..ae6e46f
--- /dev/null
+++ b/v1.9.4/builder/null/artifact_export.go
@@ -0,0 +1,53 @@
+// Copyright (c) HashiCorp, Inc.
+// SPDX-License-Identifier: MPL-2.0
+
+package null
+
+import (
+ "fmt"
+
+ registryimage "github.com/hashicorp/packer-plugin-sdk/packer/registry/image"
+)
+
+// dummy Artifact implementation - does nothing
+type NullArtifact struct {
+}
+
+func (*NullArtifact) BuilderId() string {
+ return BuilderId
+}
+
+func (a *NullArtifact) Files() []string {
+ return []string{}
+}
+
+func (*NullArtifact) Id() string {
+ return "Null"
+}
+
+func (a *NullArtifact) String() string {
+ return fmt.Sprintf("Did not export anything. This is the null builder")
+}
+
+func (a *NullArtifact) State(name string) interface{} {
+ switch name {
+ case registryimage.ArtifactStateURI:
+ img, _ := registryimage.FromArtifact(a,
+ registryimage.WithID(a.Id()),
+ registryimage.WithProvider("null"),
+ registryimage.WithRegion("null"),
+ registryimage.WithSourceID("null"),
+ )
+ return img
+ case "generated_data":
+ return map[interface{}]interface{}{
+ "ID": "Null",
+ }
+ default:
+ return nil
+ }
+}
+
+func (a *NullArtifact) Destroy() error {
+ return nil
+}
diff --git a/v1.9.4/builder/null/artifact_export_test.go b/v1.9.4/builder/null/artifact_export_test.go
new file mode 100644
index 0000000..ffa6688
--- /dev/null
+++ b/v1.9.4/builder/null/artifact_export_test.go
@@ -0,0 +1,14 @@
+// Copyright (c) HashiCorp, Inc.
+// SPDX-License-Identifier: MPL-2.0
+
+package null
+
+import (
+ "testing"
+
+ packersdk "github.com/hashicorp/packer-plugin-sdk/packer"
+)
+
+func TestNullArtifact(t *testing.T) {
+ var _ packersdk.Artifact = new(NullArtifact)
+}
diff --git a/v1.9.4/builder/null/builder.go b/v1.9.4/builder/null/builder.go
new file mode 100644
index 0000000..9b660bd
--- /dev/null
+++ b/v1.9.4/builder/null/builder.go
@@ -0,0 +1,67 @@
+// Copyright (c) HashiCorp, Inc.
+// SPDX-License-Identifier: MPL-2.0
+
+package null
+
+import (
+ "context"
+
+ "github.com/hashicorp/hcl/v2/hcldec"
+ "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"
+)
+
+const BuilderId = "fnoeding.null"
+
+type Builder struct {
+ config Config
+ runner multistep.Runner
+}
+
+func (b *Builder) ConfigSpec() hcldec.ObjectSpec { return b.config.FlatMapstructure().HCL2Spec() }
+
+func (b *Builder) Prepare(raws ...interface{}) ([]string, []string, error) {
+ warnings, errs := b.config.Prepare(raws...)
+ if errs != nil {
+ return nil, warnings, errs
+ }
+
+ return nil, warnings, nil
+}
+
+func (b *Builder) Run(ctx context.Context, ui packersdk.Ui, hook packersdk.Hook) (packersdk.Artifact, error) {
+ steps := []multistep.Step{}
+
+ steps = append(steps,
+ &communicator.StepConnect{
+ Config: &b.config.CommConfig,
+ Host: CommHost(b.config.CommConfig.Host()),
+ SSHConfig: b.config.CommConfig.SSHConfigFunc(),
+ },
+ )
+
+ steps = append(steps,
+ new(commonsteps.StepProvision),
+ )
+
+ // Setup the state bag and initial state for the steps
+ state := new(multistep.BasicStateBag)
+ state.Put("hook", hook)
+ state.Put("ui", ui)
+ state.Put("instance_id", "Null")
+
+ // Run!
+ b.runner = commonsteps.NewRunner(steps, b.config.PackerConfig, ui)
+ b.runner.Run(ctx, state)
+
+ // If there was an error, return that
+ if rawErr, ok := state.GetOk("error"); ok {
+ return nil, rawErr.(error)
+ }
+
+ // No errors, must've worked
+ artifact := &NullArtifact{}
+ return artifact, nil
+}
diff --git a/v1.9.4/builder/null/builder_test.go b/v1.9.4/builder/null/builder_test.go
new file mode 100644
index 0000000..b50d148
--- /dev/null
+++ b/v1.9.4/builder/null/builder_test.go
@@ -0,0 +1,14 @@
+// Copyright (c) HashiCorp, Inc.
+// SPDX-License-Identifier: MPL-2.0
+
+package null
+
+import (
+ "testing"
+
+ packersdk "github.com/hashicorp/packer-plugin-sdk/packer"
+)
+
+func TestBuilder_implBuilder(t *testing.T) {
+ var _ packersdk.Builder = new(Builder)
+}
diff --git a/v1.9.4/builder/null/config.go b/v1.9.4/builder/null/config.go
new file mode 100644
index 0000000..b240d57
--- /dev/null
+++ b/v1.9.4/builder/null/config.go
@@ -0,0 +1,70 @@
+// Copyright (c) HashiCorp, Inc.
+// SPDX-License-Identifier: MPL-2.0
+
+//go:generate packer-sdc mapstructure-to-hcl2 -type Config
+
+package null
+
+import (
+ "fmt"
+
+ "github.com/hashicorp/packer-plugin-sdk/common"
+ "github.com/hashicorp/packer-plugin-sdk/communicator"
+ packersdk "github.com/hashicorp/packer-plugin-sdk/packer"
+ "github.com/hashicorp/packer-plugin-sdk/template/config"
+ "github.com/hashicorp/packer-plugin-sdk/template/interpolate"
+)
+
+type Config struct {
+ common.PackerConfig `mapstructure:",squash"`
+
+ CommConfig communicator.Config `mapstructure:",squash"`
+}
+
+func (c *Config) Prepare(raws ...interface{}) ([]string, error) {
+
+ err := config.Decode(c, &config.DecodeOpts{
+ PluginType: BuilderId,
+ Interpolate: true,
+ InterpolateFilter: &interpolate.RenderFilter{},
+ }, raws...)
+ if err != nil {
+ return nil, err
+ }
+
+ var errs *packersdk.MultiError
+ if es := c.CommConfig.Prepare(nil); len(es) > 0 {
+ errs = packersdk.MultiErrorAppend(errs, es...)
+ }
+
+ if c.CommConfig.Type != "none" {
+ if c.CommConfig.Host() == "" {
+ errs = packersdk.MultiErrorAppend(errs,
+ fmt.Errorf("a Host must be specified, please reference your communicator documentation"))
+ }
+
+ if c.CommConfig.User() == "" {
+ errs = packersdk.MultiErrorAppend(errs,
+ fmt.Errorf("a Username must be specified, please reference your communicator documentation"))
+ }
+
+ if !c.CommConfig.SSHAgentAuth && c.CommConfig.Password() == "" && c.CommConfig.SSHPrivateKeyFile == "" {
+ errs = packersdk.MultiErrorAppend(errs,
+ fmt.Errorf("one authentication method must be specified, please reference your communicator documentation"))
+ }
+
+ if (c.CommConfig.SSHAgentAuth &&
+ (c.CommConfig.SSHPassword != "" || c.CommConfig.SSHPrivateKeyFile != "")) ||
+ (c.CommConfig.SSHPassword != "" && c.CommConfig.SSHPrivateKeyFile != "") {
+ errs = packersdk.MultiErrorAppend(errs,
+ fmt.Errorf("only one of ssh_agent_auth, ssh_password, and ssh_private_key_file must be specified"))
+
+ }
+ }
+
+ if errs != nil && len(errs.Errors) > 0 {
+ return nil, errs
+ }
+
+ return nil, nil
+}
diff --git a/v1.9.4/builder/null/config.hcl2spec.go b/v1.9.4/builder/null/config.hcl2spec.go
new file mode 100644
index 0000000..8d710f1
--- /dev/null
+++ b/v1.9.4/builder/null/config.hcl2spec.go
@@ -0,0 +1,143 @@
+// Code generated by "packer-sdc mapstructure-to-hcl2"; DO NOT EDIT.
+
+package null
+
+import (
+ "github.com/hashicorp/hcl/v2/hcldec"
+ "github.com/zclconf/go-cty/cty"
+)
+
+// FlatConfig is an auto-generated flat version of Config.
+// Where the contents of a field with a `mapstructure:,squash` tag are bubbled up.
+type FlatConfig struct {
+ PackerBuildName *string `mapstructure:"packer_build_name" cty:"packer_build_name" 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"`
+ 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"`
+}
+
+// FlatMapstructure returns a new FlatConfig.
+// FlatConfig is an auto-generated flat version of Config.
+// Where the contents a fields with a `mapstructure:,squash` tag are bubbled up.
+func (*Config) FlatMapstructure() interface{ HCL2Spec() map[string]hcldec.Spec } {
+ return new(FlatConfig)
+}
+
+// HCL2Spec returns the hcl spec of a Config.
+// This spec is used by HCL to read the fields of Config.
+// The decoded values from this spec will then be applied to a FlatConfig.
+func (*FlatConfig) HCL2Spec() map[string]hcldec.Spec {
+ s := map[string]hcldec.Spec{
+ "packer_build_name": &hcldec.AttrSpec{Name: "packer_build_name", Type: cty.String, Required: false},
+ "packer_builder_type": &hcldec.AttrSpec{Name: "packer_builder_type", Type: cty.String, Required: false},
+ "packer_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_sensitive_variables": &hcldec.AttrSpec{Name: "packer_sensitive_variables", Type: cty.List(cty.String), Required: false},
+ "communicator": &hcldec.AttrSpec{Name: "communicator", Type: cty.String, Required: false},
+ "pause_before_connecting": &hcldec.AttrSpec{Name: "pause_before_connecting", Type: cty.String, Required: false},
+ "ssh_host": &hcldec.AttrSpec{Name: "ssh_host", Type: cty.String, Required: false},
+ "ssh_port": &hcldec.AttrSpec{Name: "ssh_port", Type: cty.Number, Required: false},
+ "ssh_username": &hcldec.AttrSpec{Name: "ssh_username", Type: cty.String, Required: false},
+ "ssh_password": &hcldec.AttrSpec{Name: "ssh_password", Type: cty.String, Required: false},
+ "ssh_keypair_name": &hcldec.AttrSpec{Name: "ssh_keypair_name", Type: cty.String, Required: false},
+ "temporary_key_pair_name": &hcldec.AttrSpec{Name: "temporary_key_pair_name", Type: cty.String, Required: false},
+ "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},
+ "ssh_bastion_host": &hcldec.AttrSpec{Name: "ssh_bastion_host", Type: cty.String, Required: false},
+ "ssh_bastion_port": &hcldec.AttrSpec{Name: "ssh_bastion_port", Type: cty.Number, Required: false},
+ "ssh_bastion_agent_auth": &hcldec.AttrSpec{Name: "ssh_bastion_agent_auth", Type: cty.Bool, Required: false},
+ "ssh_bastion_username": &hcldec.AttrSpec{Name: "ssh_bastion_username", Type: cty.String, Required: false},
+ "ssh_bastion_password": &hcldec.AttrSpec{Name: "ssh_bastion_password", Type: cty.String, Required: false},
+ "ssh_bastion_interactive": &hcldec.AttrSpec{Name: "ssh_bastion_interactive", Type: cty.Bool, Required: false},
+ "ssh_bastion_private_key_file": &hcldec.AttrSpec{Name: "ssh_bastion_private_key_file", Type: cty.String, Required: false},
+ "ssh_bastion_certificate_file": &hcldec.AttrSpec{Name: "ssh_bastion_certificate_file", Type: cty.String, Required: false},
+ "ssh_file_transfer_method": &hcldec.AttrSpec{Name: "ssh_file_transfer_method", Type: cty.String, Required: false},
+ "ssh_proxy_host": &hcldec.AttrSpec{Name: "ssh_proxy_host", Type: cty.String, Required: false},
+ "ssh_proxy_port": &hcldec.AttrSpec{Name: "ssh_proxy_port", Type: cty.Number, Required: false},
+ "ssh_proxy_username": &hcldec.AttrSpec{Name: "ssh_proxy_username", Type: cty.String, Required: false},
+ "ssh_proxy_password": &hcldec.AttrSpec{Name: "ssh_proxy_password", Type: cty.String, Required: false},
+ "ssh_keep_alive_interval": &hcldec.AttrSpec{Name: "ssh_keep_alive_interval", Type: cty.String, Required: false},
+ "ssh_read_write_timeout": &hcldec.AttrSpec{Name: "ssh_read_write_timeout", Type: cty.String, Required: false},
+ "ssh_remote_tunnels": &hcldec.AttrSpec{Name: "ssh_remote_tunnels", Type: cty.List(cty.String), Required: false},
+ "ssh_local_tunnels": &hcldec.AttrSpec{Name: "ssh_local_tunnels", Type: cty.List(cty.String), Required: false},
+ "ssh_public_key": &hcldec.AttrSpec{Name: "ssh_public_key", Type: cty.List(cty.Number), Required: false},
+ "ssh_private_key": &hcldec.AttrSpec{Name: "ssh_private_key", Type: cty.List(cty.Number), Required: false},
+ "winrm_username": &hcldec.AttrSpec{Name: "winrm_username", Type: cty.String, Required: false},
+ "winrm_password": &hcldec.AttrSpec{Name: "winrm_password", Type: cty.String, Required: false},
+ "winrm_host": &hcldec.AttrSpec{Name: "winrm_host", Type: cty.String, Required: false},
+ "winrm_no_proxy": &hcldec.AttrSpec{Name: "winrm_no_proxy", Type: cty.Bool, Required: false},
+ "winrm_port": &hcldec.AttrSpec{Name: "winrm_port", Type: cty.Number, Required: false},
+ "winrm_timeout": &hcldec.AttrSpec{Name: "winrm_timeout", Type: cty.String, Required: false},
+ "winrm_use_ssl": &hcldec.AttrSpec{Name: "winrm_use_ssl", Type: cty.Bool, Required: false},
+ "winrm_insecure": &hcldec.AttrSpec{Name: "winrm_insecure", Type: cty.Bool, Required: false},
+ "winrm_use_ntlm": &hcldec.AttrSpec{Name: "winrm_use_ntlm", Type: cty.Bool, Required: false},
+ }
+ return s
+}
diff --git a/v1.9.4/builder/null/config_test.go b/v1.9.4/builder/null/config_test.go
new file mode 100644
index 0000000..1123d47
--- /dev/null
+++ b/v1.9.4/builder/null/config_test.go
@@ -0,0 +1,106 @@
+// Copyright (c) HashiCorp, Inc.
+// SPDX-License-Identifier: MPL-2.0
+
+package null
+
+import (
+ "os"
+ "testing"
+
+ "github.com/hashicorp/packer-plugin-sdk/communicator"
+)
+
+func testConfig() map[string]interface{} {
+ return map[string]interface{}{
+ "ssh_host": "foo",
+ "ssh_username": "bar",
+ "ssh_password": "baz",
+ }
+}
+
+func testConfigStruct(t *testing.T) *Config {
+ var c Config
+ warns, errs := c.Prepare(testConfig())
+ if len(warns) > 0 {
+ t.Fatalf("bad: %#v", len(warns))
+ }
+ if errs != nil {
+ t.Fatalf("bad: %#v", errs)
+ }
+
+ return &c
+}
+
+func testConfigErr(t *testing.T, warns []string, err error) {
+ if len(warns) > 0 {
+ t.Fatalf("bad: %#v", warns)
+ }
+ if err == nil {
+ t.Fatal("should error")
+ }
+}
+
+func testConfigOk(t *testing.T, warns []string, err error) {
+ if len(warns) > 0 {
+ t.Fatalf("bad: %#v", warns)
+ }
+ if err != nil {
+ t.Fatalf("bad: %s", err)
+ }
+}
+
+func TestConfigPrepare_port(t *testing.T) {
+ raw := testConfig()
+
+ // default port should be 22
+ delete(raw, "port")
+ var c Config
+ warns, errs := c.Prepare(raw)
+ if c.CommConfig.SSHPort != 22 {
+ t.Fatalf("bad: port should default to 22, not %d", c.CommConfig.SSHPort)
+ }
+ testConfigOk(t, warns, errs)
+}
+
+func TestConfigPrepare_host(t *testing.T) {
+ raw := testConfig()
+
+ // No host
+ delete(raw, "ssh_host")
+ var c Config
+ warns, errs := c.Prepare(raw)
+ testConfigErr(t, warns, errs)
+
+ // Good host
+ raw["ssh_host"] = "good"
+ warns, errs = c.Prepare(raw)
+ testConfigOk(t, warns, errs)
+}
+
+func TestConfigPrepare_sshCredential(t *testing.T) {
+ raw := testConfig()
+
+ // no ssh_password and no ssh_private_key_file
+ delete(raw, "ssh_password")
+ delete(raw, "ssh_private_key_file")
+ warns, errs := (&Config{}).Prepare(raw)
+ testConfigErr(t, warns, errs)
+
+ // only ssh_password
+ raw["ssh_password"] = "good"
+ warns, errs = (&Config{}).Prepare(raw)
+ testConfigOk(t, warns, errs)
+
+ // only ssh_private_key_file
+ testFile := communicator.TestPEM(t)
+ defer os.Remove(testFile)
+ raw["ssh_private_key_file"] = testFile
+ delete(raw, "ssh_password")
+ warns, errs = (&Config{}).Prepare(raw)
+ testConfigOk(t, warns, errs)
+
+ // both ssh_password and ssh_private_key_file set
+ raw["ssh_password"] = "bad"
+ warns, errs = (&Config{}).Prepare(raw)
+ testConfigErr(t, warns, errs)
+}
diff --git a/v1.9.4/builder/null/ssh.go b/v1.9.4/builder/null/ssh.go
new file mode 100644
index 0000000..f79bdd1
--- /dev/null
+++ b/v1.9.4/builder/null/ssh.go
@@ -0,0 +1,14 @@
+// Copyright (c) HashiCorp, Inc.
+// SPDX-License-Identifier: MPL-2.0
+
+package null
+
+import (
+ "github.com/hashicorp/packer-plugin-sdk/multistep"
+)
+
+func CommHost(host string) func(multistep.StateBag) (string, error) {
+ return func(state multistep.StateBag) (string, error) {
+ return host, nil
+ }
+}
diff --git a/v1.9.4/builder/null/version/version.go b/v1.9.4/builder/null/version/version.go
new file mode 100644
index 0000000..f3b8cb4
--- /dev/null
+++ b/v1.9.4/builder/null/version/version.go
@@ -0,0 +1,16 @@
+// Copyright (c) HashiCorp, Inc.
+// SPDX-License-Identifier: MPL-2.0
+
+package version
+
+import (
+ "github.com/hashicorp/packer-plugin-sdk/version"
+ packerVersion "github.com/hashicorp/packer/version"
+)
+
+var NullPluginVersion *version.PluginVersion
+
+func init() {
+ NullPluginVersion = version.InitializePluginVersion(
+ packerVersion.Version, packerVersion.VersionPrerelease)
+}
diff --git a/v1.9.4/builder/test-fixtures/floppies/bar.bat b/v1.9.4/builder/test-fixtures/floppies/bar.bat
new file mode 100644
index 0000000..0d6a4f3
--- /dev/null
+++ b/v1.9.4/builder/test-fixtures/floppies/bar.bat
@@ -0,0 +1 @@
+Echo I am a floppy with a batch file
\ No newline at end of file
diff --git a/v1.9.4/builder/test-fixtures/floppies/foo.ps1 b/v1.9.4/builder/test-fixtures/floppies/foo.ps1
new file mode 100644
index 0000000..672daeb
--- /dev/null
+++ b/v1.9.4/builder/test-fixtures/floppies/foo.ps1
@@ -0,0 +1 @@
+Write-Host "I am a floppy with some Powershell"
\ No newline at end of file
diff --git a/v1.9.4/checkpoint.go b/v1.9.4/checkpoint.go
new file mode 100644
index 0000000..5ca534e
--- /dev/null
+++ b/v1.9.4/checkpoint.go
@@ -0,0 +1,86 @@
+// Copyright (c) HashiCorp, Inc.
+// SPDX-License-Identifier: MPL-2.0
+
+package main
+
+import (
+ "fmt"
+ "log"
+ "path/filepath"
+
+ "github.com/hashicorp/go-checkpoint"
+ "github.com/hashicorp/packer-plugin-sdk/pathing"
+ "github.com/hashicorp/packer/command"
+ packerVersion "github.com/hashicorp/packer/version"
+)
+
+func init() {
+ checkpointResult = make(chan *checkpoint.CheckResponse, 1)
+}
+
+var checkpointResult chan *checkpoint.CheckResponse
+
+// runCheckpoint runs a HashiCorp Checkpoint request. You can read about
+// Checkpoint here: https://github.com/hashicorp/go-checkpoint.
+func runCheckpoint(c *config) {
+ // If the user doesn't want checkpoint at all, then return.
+ if c.DisableCheckpoint {
+ log.Printf("[INFO] Checkpoint disabled. Not running.")
+ checkpointResult <- nil
+ return
+ }
+
+ configDir, err := pathing.ConfigDir()
+ if err != nil {
+ log.Printf("[ERR] Checkpoint setup error: %s", err)
+ checkpointResult <- nil
+ return
+ }
+
+ version := packerVersion.Version
+ if packerVersion.VersionPrerelease != "" {
+ version += fmt.Sprintf("-%s", packerVersion.VersionPrerelease)
+ }
+
+ signaturePath := filepath.Join(configDir, "checkpoint_signature")
+ if c.DisableCheckpointSignature {
+ log.Printf("[INFO] Checkpoint signature disabled")
+ signaturePath = ""
+ }
+
+ resp, err := checkpoint.Check(&checkpoint.CheckParams{
+ Product: "packer",
+ Version: version,
+ SignatureFile: signaturePath,
+ CacheFile: filepath.Join(configDir, "checkpoint_cache"),
+ })
+ if err != nil {
+ log.Printf("[ERR] Checkpoint error: %s", err)
+ resp = nil
+ }
+
+ checkpointResult <- resp
+}
+
+// commandVersionCheck implements command.VersionCheckFunc and is used
+// as the version checker.
+func commandVersionCheck() (command.VersionCheckInfo, error) {
+ // Wait for the result to come through
+ info := <-checkpointResult
+ if info == nil {
+ var zero command.VersionCheckInfo
+ return zero, nil
+ }
+
+ // Build the alerts that we may have received about our version
+ alerts := make([]string, len(info.Alerts))
+ for i, a := range info.Alerts {
+ alerts[i] = a.Message
+ }
+
+ return command.VersionCheckInfo{
+ Outdated: info.Outdated,
+ Latest: info.CurrentVersion,
+ Alerts: alerts,
+ }, nil
+}
diff --git a/v1.9.4/cmd/generate-fixer-deprecations/main.go b/v1.9.4/cmd/generate-fixer-deprecations/main.go
new file mode 100644
index 0000000..a3e7654
--- /dev/null
+++ b/v1.9.4/cmd/generate-fixer-deprecations/main.go
@@ -0,0 +1,96 @@
+// Copyright (c) HashiCorp, Inc.
+// SPDX-License-Identifier: MPL-2.0
+
+package main
+
+import (
+ "bytes"
+ "flag"
+ "fmt"
+ "go/format"
+ "os"
+ "path/filepath"
+ "strings"
+ "text/template"
+
+ "github.com/hashicorp/packer/fix"
+)
+
+var deprecatedOptsTemplate = template.Must(template.New("deprecatedOptsTemplate").Funcs(template.FuncMap{"StringsJoin": strings.Join}).Parse(`//<!-- Code generated by generate-fixer-deprecations; DO NOT EDIT MANUALLY -->
+
+package config
+
+var DeprecatedOptions = map[string][]string{
+{{- range $key, $value := .DeprecatedOpts}}
+ "{{$key}}": []string{"{{ StringsJoin . "\", \"" }}"},
+{{- end}}
+}
+`))
+
+type executeOpts struct {
+ DeprecatedOpts map[string][]string
+}
+
+func main() {
+ // Figure out location in directory structure
+ args := flag.Args()
+ if len(args) == 0 {
+ // Default: process the file
+ args = []string{os.Getenv("GOFILE")}
+ }
+ fname := args[0]
+
+ absFilePath, err := filepath.Abs(fname)
+ if err != nil {
+ panic(err)
+ }
+ paths := strings.Split(absFilePath, "cmd"+string(os.PathSeparator)+
+ "generate-fixer-deprecations"+string(os.PathSeparator)+"main.go")
+ packerDir := paths[0]
+
+ // Load all deprecated options from all active fixers
+ allDeprecatedOpts := map[string][]string{}
+ for _, name := range fix.FixerOrder {
+ fixer, ok := fix.Fixers[name]
+ if !ok {
+ panic("fixer not found: " + name)
+ }
+
+ deprecated := fixer.DeprecatedOptions()
+ for k, v := range deprecated {
+ if allDeprecatedOpts[k] == nil {
+ allDeprecatedOpts[k] = v
+ } else {
+ allDeprecatedOpts[k] = append(allDeprecatedOpts[k], v...)
+ }
+ }
+ }
+
+ deprecated_path := filepath.Join(packerDir, "packer-plugin-sdk", "template",
+ "config", "deprecated_options.go")
+
+ buf := bytes.Buffer{}
+
+ // execute template into buffer
+ deprecated := &executeOpts{DeprecatedOpts: allDeprecatedOpts}
+ err = deprecatedOptsTemplate.Execute(&buf, deprecated)
+ if err != nil {
+ panic(err)
+ }
+ // we've written unformatted go code to the file. now we have to format it.
+ out, err := format.Source(buf.Bytes())
+ if err != nil {
+ panic(err)
+ }
+
+ outputFile, err := os.Create(deprecated_path)
+ if err != nil {
+ panic(err)
+ }
+ _, err = outputFile.Write(out)
+ defer outputFile.Close()
+ if err != nil {
+ fmt.Printf("%v", err)
+ os.Exit(1)
+ }
+}
diff --git a/v1.9.4/cmd/ssh-keygen/main.go b/v1.9.4/cmd/ssh-keygen/main.go
new file mode 100644
index 0000000..a15797e
--- /dev/null
+++ b/v1.9.4/cmd/ssh-keygen/main.go
@@ -0,0 +1,98 @@
+// Copyright (c) HashiCorp, Inc.
+// SPDX-License-Identifier: MPL-2.0
+
+package main
+
+import (
+ "flag"
+ "io/ioutil"
+ "log"
+ "os"
+ "os/user"
+ "path/filepath"
+
+ "github.com/hashicorp/packer-plugin-sdk/communicator/sshkey"
+)
+
+type options struct {
+ Type string
+ Bits int
+ Filename string
+}
+
+func (o *options) AddFlagSets(fs *flag.FlagSet) {
+ fs.StringVar(&o.Type, "type", "rsa", `dsa | ecdsa | ed25519 | rsa
+Specifies the type of key to create. The possible values are 'dsa', 'ecdsa',
+'ed25519', or 'rsa'.
+`)
+ fs.IntVar(&o.Bits, "bits", 0, `Specifies the number of bits in the key to create. By default maximum
+number will be picked. For RSA keys, the minimum size is 1024 bits and the
+default is 3072 bits. Generally, 3072 bits is considered sufficient. DSA
+keys must be exactly 1024 bits as specified by FIPS 186-2. For ECDSA keys,
+the bits flag determines the key length by selecting from one of three
+elliptic curve sizes: 256, 384 or 521 bits. Attempting to use bit lengths
+other than these three values for ECDSA keys will fail. Ed25519 keys have a
+fixed length and the bits flag will be ignored.
+`)
+
+ defaultPath := ""
+ user, err := user.Current()
+ if err == nil {
+ defaultPath = filepath.Join(user.HomeDir, ".ssh", "tests")
+ }
+
+ fs.StringVar(&o.Filename, "filename", defaultPath, `Specifies the filename of the key file.
+`)
+}
+
+func main() {
+ log.SetFlags(0)
+ log.SetPrefix("ssh-keygen: ")
+ fs := flag.NewFlagSet("ssh-keygen", flag.ContinueOnError)
+ cla := options{}
+ cla.AddFlagSets(fs)
+ if err := fs.Parse(os.Args[1:]); err != nil {
+ log.Fatal(err)
+ }
+
+ algo, err := sshkey.AlgorithmString(cla.Type)
+ if err != nil {
+ log.Fatal(err)
+ }
+
+ log.Printf("Generating public/private %s key pair.", algo)
+
+ keypair, err := sshkey.GeneratePair(algo, nil, cla.Bits)
+ if err != nil {
+ log.Fatal(err)
+ }
+
+ if isDir(cla.Filename) {
+ cla.Filename = filepath.Join(cla.Filename, "id_"+algo.String())
+ }
+ if fileExists(cla.Filename) {
+ log.Fatalf("%s already exists.", cla.Filename)
+ }
+ log.Printf("Saving private key to %s", cla.Filename)
+ if err := ioutil.WriteFile(cla.Filename, keypair.Private, 0600); err != nil {
+ log.Fatal(err)
+ }
+ publicFilename := cla.Filename + ".pub"
+ log.Printf("Saving public key to %s", publicFilename)
+ if err := ioutil.WriteFile(publicFilename, keypair.Public, 0644); err != nil {
+ log.Fatal(err)
+ }
+}
+
+func isDir(filename string) bool {
+ info, err := os.Stat(filename)
+ if err != nil {
+ log.Fatal(err)
+ }
+ return info.IsDir()
+}
+
+func fileExists(filename string) bool {
+ _, err := os.Stat(filename)
+ return err == nil
+}
diff --git a/v1.9.4/command/build.go b/v1.9.4/command/build.go
new file mode 100644
index 0000000..842938a
--- /dev/null
+++ b/v1.9.4/command/build.go
@@ -0,0 +1,445 @@
+// Copyright (c) HashiCorp, Inc.
+// SPDX-License-Identifier: MPL-2.0
+
+package command
+
+import (
+ "bytes"
+ "context"
+ "errors"
+ "fmt"
+ "log"
+ "math"
+ "strconv"
+ "strings"
+ "sync"
+ "time"
+
+ "github.com/hashicorp/hcl/v2"
+ packersdk "github.com/hashicorp/packer-plugin-sdk/packer"
+ "github.com/hashicorp/packer/internal/hcp/registry"
+ "github.com/hashicorp/packer/packer"
+ "golang.org/x/sync/semaphore"
+
+ "github.com/hako/durafmt"
+ "github.com/posener/complete"
+)
+
+type BuildCommand struct {
+ Meta
+}
+
+func (c *BuildCommand) Run(args []string) int {
+ ctx, cleanup := handleTermInterrupt(c.Ui)
+ defer cleanup()
+
+ cfg, ret := c.ParseArgs(args)
+ if ret != 0 {
+ return ret
+ }
+
+ return c.RunContext(ctx, cfg)
+}
+
+func (c *BuildCommand) ParseArgs(args []string) (*BuildArgs, int) {
+ var cfg BuildArgs
+ flags := c.Meta.FlagSet("build", FlagSetBuildFilter|FlagSetVars)
+ flags.Usage = func() { c.Ui.Say(c.Help()) }
+ cfg.AddFlagSets(flags)
+ if err := flags.Parse(args); err != nil {
+ return &cfg, 1
+ }
+
+ if cfg.ParallelBuilds < 1 {
+ cfg.ParallelBuilds = math.MaxInt64
+ }
+
+ args = flags.Args()
+ if len(args) != 1 {
+ flags.Usage()
+ return &cfg, 1
+ }
+ cfg.Path = args[0]
+ return &cfg, 0
+}
+
+func writeDiags(ui packersdk.Ui, files map[string]*hcl.File, diags hcl.Diagnostics) int {
+ // write HCL errors/diagnostics if any.
+ b := bytes.NewBuffer(nil)
+ err := hcl.NewDiagnosticTextWriter(b, files, 80, false).WriteDiagnostics(diags)
+ if err != nil {
+ ui.Error("could not write diagnostic: " + err.Error())
+ return 1
+ }
+ if b.Len() != 0 {
+ if diags.HasErrors() {
+ ui.Error(b.String())
+ return 1
+ }
+ ui.Say(b.String())
+ }
+ return 0
+}
+
+func (c *BuildCommand) RunContext(buildCtx context.Context, cla *BuildArgs) int {
+ packerStarter, ret := c.GetConfig(&cla.MetaArgs)
+ if ret != 0 {
+ return ret
+ }
+
+ diags := packerStarter.DetectPluginBinaries()
+ ret = writeDiags(c.Ui, nil, diags)
+ if ret != 0 {
+ return ret
+ }
+
+ diags = packerStarter.Initialize(packer.InitializeOptions{})
+ bundledDiags := c.DetectBundledPlugins(packerStarter)
+ diags = append(bundledDiags, diags...)
+ ret = writeDiags(c.Ui, nil, diags)
+ if ret != 0 {
+ return ret
+ }
+
+ hcpRegistry, diags := registry.New(packerStarter, c.Ui)
+ ret = writeDiags(c.Ui, nil, diags)
+ if ret != 0 {
+ return ret
+ }
+
+ defer hcpRegistry.IterationStatusSummary()
+
+ err := hcpRegistry.PopulateIteration(buildCtx)
+ if err != nil {
+ return writeDiags(c.Ui, nil, hcl.Diagnostics{
+ &hcl.Diagnostic{
+ Summary: "HCP: populating iteration failed",
+ Severity: hcl.DiagError,
+ Detail: err.Error(),
+ },
+ })
+ }
+
+ builds, diags := packerStarter.GetBuilds(packer.GetBuildsOptions{
+ Only: cla.Only,
+ Except: cla.Except,
+ Debug: cla.Debug,
+ Force: cla.Force,
+ OnError: cla.OnError,
+ })
+
+ // here, something could have gone wrong but we still want to run valid
+ // builds.
+ ret = writeDiags(c.Ui, nil, diags)
+ if len(builds) == 0 && ret != 0 {
+ return ret
+ }
+
+ if cla.Debug {
+ c.Ui.Say("Debug mode enabled. Builds will not be parallelized.")
+ }
+
+ // Compile all the UIs for the builds
+ colors := [5]packer.UiColor{
+ packer.UiColorGreen,
+ packer.UiColorCyan,
+ packer.UiColorMagenta,
+ packer.UiColorYellow,
+ packer.UiColorBlue,
+ }
+ buildUis := make(map[packersdk.Build]packersdk.Ui)
+ for i := range builds {
+ ui := c.Ui
+ if cla.Color {
+ // Only set up UI colors if -machine-readable isn't set.
+ if _, ok := c.Ui.(*packer.MachineReadableUi); !ok {
+ ui = &packer.ColoredUi{
+ Color: colors[i%len(colors)],
+ Ui: ui,
+ }
+ ui.Say(fmt.Sprintf("%s: output will be in this color.", builds[i].Name()))
+ if i+1 == len(builds) {
+ // Add a newline between the color output and the actual output
+ c.Ui.Say("")
+ }
+ }
+ }
+ // Now add timestamps if requested
+ if cla.TimestampUi {
+ ui = &packer.TimestampedUi{
+ Ui: ui,
+ }
+ }
+
+ buildUis[builds[i]] = ui
+ }
+ log.Printf("Build debug mode: %v", cla.Debug)
+ log.Printf("Force build: %v", cla.Force)
+ log.Printf("On error: %v", cla.OnError)
+
+ if len(builds) == 0 {
+ return writeDiags(c.Ui, nil, hcl.Diagnostics{
+ &hcl.Diagnostic{
+ Summary: "No builds to run",
+ Detail: "A build command cannot run without at least one build to process. " +
+ "If the only or except flags have been specified at run time check that" +
+ " at least one build is selected for execution.",
+ Severity: hcl.DiagError,
+ },
+ })
+ }
+
+ // Get the start of the build command
+ buildCommandStart := time.Now()
+
+ // Run all the builds in parallel and wait for them to complete
+ var wg sync.WaitGroup
+ var artifacts = struct {
+ sync.RWMutex
+ m map[string][]packersdk.Artifact
+ }{m: make(map[string][]packersdk.Artifact)}
+ // Get the builds we care about
+ var errs = struct {
+ sync.RWMutex
+ m map[string]error
+ }{m: make(map[string]error)}
+ limitParallel := semaphore.NewWeighted(cla.ParallelBuilds)
+ for i := range builds {
+ if err := buildCtx.Err(); err != nil {
+ log.Println("Interrupted, not going to start any more builds.")
+ break
+ }
+
+ b := builds[i]
+ name := b.Name()
+ ui := buildUis[b]
+ if err := limitParallel.Acquire(buildCtx, 1); err != nil {
+ ui.Error(fmt.Sprintf("Build '%s' failed to acquire semaphore: %s", name, err))
+ errs.Lock()
+ errs.m[name] = err
+ errs.Unlock()
+ break
+ }
+ // Increment the waitgroup so we wait for this item to finish properly
+ wg.Add(1)
+
+ // Run the build in a goroutine
+ go func() {
+ // Get the start of the build
+ buildStart := time.Now()
+
+ defer wg.Done()
+
+ defer limitParallel.Release(1)
+
+ err := hcpRegistry.StartBuild(buildCtx, b)
+ // Seems odd to require this error check here. Now that it is an error we can just exit with diag
+ if err != nil {
+ // If the build is already done, we skip without a warning
+ if errors.As(err, ®istry.ErrBuildAlreadyDone{}) {
+ ui.Say(fmt.Sprintf("skipping already done build %q", name))
+ return
+ }
+ writeDiags(c.Ui, nil, hcl.Diagnostics{
+ &hcl.Diagnostic{
+ Summary: fmt.Sprintf(
+ "hcp: failed to start build %q",
+ name),
+ Severity: hcl.DiagError,
+ Detail: err.Error(),
+ },
+ })
+ return
+ }
+
+ log.Printf("Starting build run: %s", name)
+ runArtifacts, err := b.Run(buildCtx, ui)
+
+ // Get the duration of the build and parse it
+ buildEnd := time.Now()
+ buildDuration := buildEnd.Sub(buildStart)
+ fmtBuildDuration := durafmt.Parse(buildDuration).LimitFirstN(2)
+
+ runArtifacts, hcperr := hcpRegistry.CompleteBuild(
+ buildCtx,
+ b,
+ runArtifacts,
+ err)
+ if hcperr != nil {
+ writeDiags(c.Ui, nil, hcl.Diagnostics{
+ &hcl.Diagnostic{
+ Summary: fmt.Sprintf(
+ "failed to complete HCP-enabled build %q",
+ name),
+ Severity: hcl.DiagError,
+ Detail: hcperr.Error(),
+ },
+ })
+ }
+
+ if err != nil {
+ ui.Error(fmt.Sprintf("Build '%s' errored after %s: %s", name, fmtBuildDuration, err))
+ errs.Lock()
+ errs.m[name] = err
+ errs.Unlock()
+ } else {
+ ui.Say(fmt.Sprintf("Build '%s' finished after %s.", name, fmtBuildDuration))
+ if runArtifacts != nil {
+ artifacts.Lock()
+ artifacts.m[name] = runArtifacts
+ artifacts.Unlock()
+ }
+ }
+ }()
+
+ if cla.Debug {
+ log.Printf("Debug enabled, so waiting for build to finish: %s", b.Name())
+ wg.Wait()
+ }
+
+ if cla.ParallelBuilds == 1 {
+ log.Printf("Parallelization disabled, waiting for build to finish: %s", b.Name())
+ wg.Wait()
+ }
+ }
+
+ // Wait for both the builds to complete and the interrupt handler,
+ // if it is interrupted.
+ log.Printf("Waiting on builds to complete...")
+ wg.Wait()
+
+ // Get the duration of the buildCommand command and parse it
+ buildCommandEnd := time.Now()
+ buildCommandDuration := buildCommandEnd.Sub(buildCommandStart)
+ fmtBuildCommandDuration := durafmt.Parse(buildCommandDuration).LimitFirstN(2)
+ c.Ui.Say(fmt.Sprintf("\n==> Wait completed after %s", fmtBuildCommandDuration))
+
+ if err := buildCtx.Err(); err != nil {
+ c.Ui.Say("Cleanly cancelled builds after being interrupted.")
+ return 1
+ }
+
+ if len(errs.m) > 0 {
+ c.Ui.Machine("error-count", strconv.FormatInt(int64(len(errs.m)), 10))
+
+ c.Ui.Error("\n==> Some builds didn't complete successfully and had errors:")
+ for name, err := range errs.m {
+ // Create a UI for the machine readable stuff to be targeted
+ ui := &packer.TargetedUI{
+ Target: name,
+ Ui: c.Ui,
+ }
+
+ ui.Machine("error", err.Error())
+
+ c.Ui.Error(fmt.Sprintf("--> %s: %s", name, err))
+ }
+ }
+
+ if len(artifacts.m) > 0 {
+ c.Ui.Say("\n==> Builds finished. The artifacts of successful builds are:")
+ for name, buildArtifacts := range artifacts.m {
+ // Create a UI for the machine readable stuff to be targeted
+ ui := &packer.TargetedUI{
+ Target: name,
+ Ui: c.Ui,
+ }
+
+ // Machine-readable helpful
+ ui.Machine("artifact-count", strconv.FormatInt(int64(len(buildArtifacts)), 10))
+
+ for i, artifact := range buildArtifacts {
+ var message bytes.Buffer
+ fmt.Fprintf(&message, "--> %s: ", name)
+
+ if artifact != nil {
+ fmt.Fprint(&message, artifact.String())
+ } else {
+ fmt.Fprint(&message, "<nothing>")
+ }
+
+ iStr := strconv.FormatInt(int64(i), 10)
+ if artifact != nil {
+ ui.Machine("artifact", iStr, "builder-id", artifact.BuilderId())
+ ui.Machine("artifact", iStr, "id", artifact.Id())
+ ui.Machine("artifact", iStr, "string", artifact.String())
+
+ files := artifact.Files()
+ ui.Machine("artifact",
+ iStr,
+ "files-count", strconv.FormatInt(int64(len(files)), 10))
+ for fi, file := range files {
+ fiStr := strconv.FormatInt(int64(fi), 10)
+ ui.Machine("artifact", iStr, "file", fiStr, file)
+ }
+ } else {
+ ui.Machine("artifact", iStr, "nil")
+ }
+
+ ui.Machine("artifact", iStr, "end")
+ c.Ui.Say(message.String())
+
+ }
+
+ }
+ } else {
+ c.Ui.Say("\n==> Builds finished but no artifacts were created.")
+ }
+
+ if len(errs.m) > 0 {
+ // If any errors occurred, exit with a non-zero exit status
+ ret = 1
+ }
+
+ return ret
+}
+
+func (*BuildCommand) Help() string {
+ helpText := `
+Usage: packer build [options] TEMPLATE
+
+ Will execute multiple builds in parallel as defined in the template.
+ The various artifacts created by the template will be outputted.
+
+Options:
+
+ -color=false Disable color output. (Default: color)
+ -debug Debug mode enabled for builds.
+ -except=foo,bar,baz Run all builds and post-processors other than these.
+ -only=foo,bar,baz Build only the specified builds.
+ -force Force a build to continue if artifacts exist, deletes existing artifacts.
+ -machine-readable Produce machine-readable output.
+ -on-error=[cleanup|abort|ask|run-cleanup-provisioner] If the build fails do: clean up (default), abort, ask, or run-cleanup-provisioner.
+ -parallel-builds=1 Number of builds to run in parallel. 1 disables parallelization. 0 means no limit (Default: 0)
+ -timestamp-ui Enable prefixing of each ui output with an RFC3339 timestamp.
+ -var 'key=value' Variable for templates, can be used multiple times.
+ -var-file=path JSON or HCL2 file containing user variables, can be used multiple times.
+ -warn-on-undeclared-var Display warnings for user variable files containing undeclared variables.
+`
+
+ return strings.TrimSpace(helpText)
+}
+
+func (*BuildCommand) Synopsis() string {
+ return "build image(s) from template"
+}
+
+func (*BuildCommand) AutocompleteArgs() complete.Predictor {
+ return complete.PredictNothing
+}
+
+func (*BuildCommand) AutocompleteFlags() complete.Flags {
+ return complete.Flags{
+ "-color": complete.PredictNothing,
+ "-debug": complete.PredictNothing,
+ "-except": complete.PredictNothing,
+ "-only": complete.PredictNothing,
+ "-force": complete.PredictNothing,
+ "-machine-readable": complete.PredictNothing,
+ "-on-error": complete.PredictNothing,
+ "-parallel": complete.PredictNothing,
+ "-timestamp-ui": complete.PredictNothing,
+ "-var": complete.PredictNothing,
+ "-var-file": complete.PredictNothing,
+ }
+}
diff --git a/v1.9.4/command/build_cancellation_test.go b/v1.9.4/command/build_cancellation_test.go
new file mode 100644
index 0000000..348b1d9
--- /dev/null
+++ b/v1.9.4/command/build_cancellation_test.go
@@ -0,0 +1,92 @@
+// Copyright (c) HashiCorp, Inc.
+// SPDX-License-Identifier: MPL-2.0
+
+package command
+
+import (
+ "context"
+ "path/filepath"
+ "testing"
+ "time"
+
+ "github.com/google/go-cmp/cmp"
+)
+
+func TestBuildCommand_RunContext_CtxCancel(t *testing.T) {
+
+ tests := []struct {
+ name string
+ args []string
+ parallelPassingTests int
+ expected int
+ }{
+ {"cancel 1 pending build - parallel=true",
+ []string{"-parallel-builds=10", filepath.Join(testFixture("parallel"), "1lock-5wg.json")},
+ 5,
+ 1,
+ },
+ {"cancel in the middle with 2 pending builds - parallel=true",
+ []string{"-parallel-builds=10", filepath.Join(testFixture("parallel"), "2lock-4wg.json")},
+ 4,
+ 1,
+ },
+ {"cancel 1 locked build - debug - parallel=true",
+ []string{"-parallel-builds=10", "-debug=true", filepath.Join(testFixture("parallel"), "1lock.json")},
+ 0,
+ 1,
+ },
+ {"cancel 2 locked builds - debug - parallel=true",
+ []string{"-parallel-builds=10", "-debug=true", filepath.Join(testFixture("parallel"), "2lock.json")},
+ 0,
+ 1,
+ },
+ {"cancel 1 locked build - debug - parallel=false",
+ []string{"-parallel-builds=1", "-debug=true", filepath.Join(testFixture("parallel"), "1lock.json")},
+ 0,
+ 1,
+ },
+ {"cancel 2 locked builds - debug - parallel=false",
+ []string{"-parallel-builds=1", "-debug=true", filepath.Join(testFixture("parallel"), "2lock.json")},
+ 0,
+ 1,
+ },
+ }
+
+ for _, tt := range tests {
+ tt := tt
+ t.Run(tt.name, func(t *testing.T) {
+ t.Parallel()
+ b := NewParallelTestBuilder(tt.parallelPassingTests)
+ locked := &LockedBuilder{unlock: make(chan interface{})}
+ c := &BuildCommand{
+ Meta: testMetaParallel(t, b, locked),
+ }
+
+ ctx, cancelCtx := context.WithCancel(context.Background())
+ codeC := make(chan int)
+ go func() {
+ defer close(codeC)
+ cfg, ret := c.ParseArgs(tt.args)
+ if ret != 0 {
+ t.Error("ParseArgs failed.")
+ return
+ }
+ codeC <- c.RunContext(ctx, cfg)
+ }()
+ t.Logf("waiting for passing tests if any")
+ b.wg.Wait() // ran `tt.parallelPassingTests` times
+ t.Logf("cancelling context")
+ cancelCtx()
+
+ select {
+ case code := <-codeC:
+ if code != tt.expected {
+ t.Logf("wrong code: %s", cmp.Diff(code, tt.expected))
+ fatalCommand(t, c.Meta)
+ }
+ case <-time.After(15 * time.Second):
+ t.Fatal("deadlock")
+ }
+ })
+ }
+}
diff --git a/v1.9.4/command/build_cleanup_script_test.go b/v1.9.4/command/build_cleanup_script_test.go
new file mode 100644
index 0000000..82f7fdd
--- /dev/null
+++ b/v1.9.4/command/build_cleanup_script_test.go
@@ -0,0 +1,32 @@
+// Copyright (c) HashiCorp, Inc.
+// SPDX-License-Identifier: MPL-2.0
+
+package command
+
+import (
+ "path/filepath"
+ "testing"
+)
+
+func TestBuildWithCleanupScript(t *testing.T) {
+ c := &BuildCommand{
+ Meta: TestMetaFile(t),
+ }
+
+ args := []string{
+ "-parallel-builds=1",
+ filepath.Join(testFixture("cleanup-script"), "template.json"),
+ }
+
+ defer cleanup()
+
+ // build should exit with error code!
+ if code := c.Run(args); code == 0 {
+ fatalCommand(t, c.Meta)
+ }
+
+ if !fileExists("ducky.txt") {
+ t.Errorf("Expected to find ducky.txt")
+ }
+
+}
diff --git a/v1.9.4/command/build_parallel_test.go b/v1.9.4/command/build_parallel_test.go
new file mode 100644
index 0000000..959134f
--- /dev/null
+++ b/v1.9.4/command/build_parallel_test.go
@@ -0,0 +1,178 @@
+// Copyright (c) HashiCorp, Inc.
+// SPDX-License-Identifier: MPL-2.0
+
+package command
+
+import (
+ "bytes"
+ "context"
+ "fmt"
+ "path/filepath"
+ "sync"
+ "testing"
+
+ "github.com/hashicorp/hcl/v2/hcldec"
+
+ "golang.org/x/sync/errgroup"
+
+ packersdk "github.com/hashicorp/packer-plugin-sdk/packer"
+ "github.com/hashicorp/packer/builder/file"
+ "github.com/hashicorp/packer/packer"
+ "github.com/hashicorp/packer/provisioner/sleep"
+)
+
+// NewParallelTestBuilder will return a New ParallelTestBuilder that will
+// unlock after `runs` builds
+func NewParallelTestBuilder(runs int) *ParallelTestBuilder {
+ pb := &ParallelTestBuilder{}
+ pb.wg.Add(runs)
+ return pb
+}
+
+// The ParallelTestBuilder's first run will lock
+type ParallelTestBuilder struct {
+ wg sync.WaitGroup
+}
+
+func (b *ParallelTestBuilder) ConfigSpec() hcldec.ObjectSpec { return nil }
+
+func (b *ParallelTestBuilder) Prepare(raws ...interface{}) ([]string, []string, error) {
+ return nil, nil, nil
+}
+
+func (b *ParallelTestBuilder) Run(ctx context.Context, ui packersdk.Ui, hook packersdk.Hook) (packersdk.Artifact, error) {
+ ui.Say("building")
+ b.wg.Done()
+ return nil, nil
+}
+
+// LockedBuilder wont run until unlock is called
+type LockedBuilder struct{ unlock chan interface{} }
+
+func (b *LockedBuilder) ConfigSpec() hcldec.ObjectSpec { return nil }
+
+func (b *LockedBuilder) Prepare(raws ...interface{}) ([]string, []string, error) {
+ return nil, nil, nil
+}
+
+func (b *LockedBuilder) Run(ctx context.Context, ui packersdk.Ui, hook packersdk.Hook) (packersdk.Artifact, error) {
+ ui.Say("locking build")
+ select {
+ case <-b.unlock:
+ case <-ctx.Done():
+ return nil, ctx.Err()
+ }
+ return nil, nil
+}
+
+// testMetaFile creates a Meta object that includes a file builder
+func testMetaParallel(t *testing.T, builder *ParallelTestBuilder, locked *LockedBuilder) Meta {
+ var out, err bytes.Buffer
+ return Meta{
+ CoreConfig: &packer.CoreConfig{
+ Components: packer.ComponentFinder{
+ PluginConfig: &packer.PluginConfig{
+ Builders: packer.MapOfBuilder{
+ "parallel-test": func() (packersdk.Builder, error) { return builder, nil },
+ "file": func() (packersdk.Builder, error) { return &file.Builder{}, nil },
+ "lock": func() (packersdk.Builder, error) { return locked, nil },
+ },
+ Provisioners: packer.MapOfProvisioner{
+ "sleep": func() (packersdk.Provisioner, error) { return &sleep.Provisioner{}, nil },
+ },
+ },
+ },
+ },
+ Ui: &packersdk.BasicUi{
+ Writer: &out,
+ ErrorWriter: &err,
+ },
+ }
+}
+
+func TestBuildParallel_1(t *testing.T) {
+ // testfile has 6 builds, with first one locks 'forever', other builds
+ // should go through.
+ b := NewParallelTestBuilder(5)
+ locked := &LockedBuilder{unlock: make(chan interface{})}
+
+ c := &BuildCommand{
+ Meta: testMetaParallel(t, b, locked),
+ }
+
+ args := []string{
+ fmt.Sprintf("-parallel-builds=10"),
+ filepath.Join(testFixture("parallel"), "1lock-5wg.json"),
+ }
+
+ wg := errgroup.Group{}
+
+ wg.Go(func() error {
+ if code := c.Run(args); code != 0 {
+ fatalCommand(t, c.Meta)
+ }
+ return nil
+ })
+
+ b.wg.Wait() // ran 5 times
+ close(locked.unlock) // unlock locking one
+ wg.Wait() // wait for termination
+}
+
+func TestBuildParallel_2(t *testing.T) {
+ // testfile has 6 builds, 2 of them lock 'forever', other builds
+ // should go through.
+ b := NewParallelTestBuilder(4)
+ locked := &LockedBuilder{unlock: make(chan interface{})}
+
+ c := &BuildCommand{
+ Meta: testMetaParallel(t, b, locked),
+ }
+
+ args := []string{
+ fmt.Sprintf("-parallel-builds=3"),
+ filepath.Join(testFixture("parallel"), "2lock-4wg.json"),
+ }
+
+ wg := errgroup.Group{}
+
+ wg.Go(func() error {
+ if code := c.Run(args); code != 0 {
+ fatalCommand(t, c.Meta)
+ }
+ return nil
+ })
+
+ b.wg.Wait() // ran 4 times
+ close(locked.unlock) // unlock locking one
+ wg.Wait() // wait for termination
+}
+
+func TestBuildParallel_Timeout(t *testing.T) {
+ // testfile has 6 builds, 1 of them locks 'forever', one locks and times
+ // out other builds should go through.
+ b := NewParallelTestBuilder(4)
+ locked := &LockedBuilder{unlock: make(chan interface{})}
+
+ c := &BuildCommand{
+ Meta: testMetaParallel(t, b, locked),
+ }
+
+ args := []string{
+ fmt.Sprintf("-parallel-builds=3"),
+ filepath.Join(testFixture("parallel"), "2lock-timeout.json"),
+ }
+
+ wg := errgroup.Group{}
+
+ wg.Go(func() error {
+ if code := c.Run(args); code == 0 {
+ fatalCommand(t, c.Meta)
+ }
+ return nil
+ })
+
+ b.wg.Wait() // ran 4 times
+ close(locked.unlock) // unlock locking one
+ wg.Wait() // wait for termination
+}
diff --git a/v1.9.4/command/build_test.go b/v1.9.4/command/build_test.go
new file mode 100644
index 0000000..8dac9b8
--- /dev/null
+++ b/v1.9.4/command/build_test.go
@@ -0,0 +1,1377 @@
+// Copyright (c) HashiCorp, Inc.
+// SPDX-License-Identifier: MPL-2.0
+
+package command
+
+import (
+ "fmt"
+ "io/ioutil"
+ "math"
+ "os"
+ "path/filepath"
+ "regexp"
+ "runtime"
+ "strings"
+ "testing"
+
+ "github.com/google/go-cmp/cmp"
+ "github.com/hashicorp/go-uuid"
+)
+
+var (
+ spaghettiCarbonara = `spaghetti
+carbonara
+`
+ lasagna = `lasagna
+tomato
+mozza
+cooking...
+`
+ tiramisu = `whip_york
+mascarpone
+whipped_egg_white
+dress
+`
+ one = "1\n"
+ two = "2\n"
+)
+
+func TestBuild(t *testing.T) {
+ tc := []struct {
+ name string
+ args []string
+ expectedCode int
+ fileCheck
+ }{
+ {
+ name: "var-args: json - json varfile sets an apple env var",
+ args: []string{
+ "-var-file=" + filepath.Join(testFixture("var-arg"), "apple.json"),
+ filepath.Join(testFixture("var-arg"), "fruit_builder.json"),
+ },
+ fileCheck: fileCheck{expected: []string{"apple.txt"}},
+ },
+ {
+ name: "json - json varfile sets an apple env var, " +
+ "override with banana cli var",
+ args: []string{
+ "-var", "fruit=banana",
+ "-var-file=" + filepath.Join(testFixture("var-arg"), "apple.json"),
+ filepath.Join(testFixture("var-arg"), "fruit_builder.json"),
+ },
+ fileCheck: fileCheck{expected: []string{"banana.txt"}},
+ },
+ {
+ name: "var-args: json - arg sets a pear env var",
+ args: []string{
+ "-var=fruit=pear",
+ filepath.Join(testFixture("var-arg"), "fruit_builder.json"),
+ },
+ fileCheck: fileCheck{expected: []string{"pear.txt"}},
+ },
+
+ {
+ name: "var-args: json - nonexistent var file errs",
+ args: []string{
+ "-var-file=" + filepath.Join(testFixture("var-arg"), "potato.json"),
+ filepath.Join(testFixture("var-arg"), "fruit_builder.json"),
+ },
+ expectedCode: 1,
+ fileCheck: fileCheck{notExpected: []string{"potato.txt"}},
+ },
+
+ {
+ name: "var-args: hcl - nonexistent json var file errs",
+ args: []string{
+ "-var-file=" + filepath.Join(testFixture("var-arg"), "potato.json"),
+ testFixture("var-arg"),
+ },
+ expectedCode: 1,
+ fileCheck: fileCheck{notExpected: []string{"potato.txt"}},
+ },
+
+ {
+ name: "var-args: hcl - nonexistent hcl var file errs",
+ args: []string{
+ "-var-file=" + filepath.Join(testFixture("var-arg"), "potato.hcl"),
+ testFixture("var-arg"),
+ },
+ expectedCode: 1,
+ fileCheck: fileCheck{notExpected: []string{"potato.hcl"}},
+ },
+
+ {
+ name: "var-args: hcl - auto varfile sets a chocolate env var",
+ args: []string{
+ testFixture("var-arg"),
+ },
+ fileCheck: fileCheck{expected: []string{"chocolate.txt"}},
+ },
+
+ {
+ name: "var-args: hcl - hcl varfile sets a apple env var",
+ args: []string{
+ "-var-file=" + filepath.Join(testFixture("var-arg"), "apple.hcl"),
+ testFixture("var-arg"),
+ },
+ fileCheck: fileCheck{expected: []string{"apple.txt"}},
+ },
+
+ {
+ name: "var-args: hcl - json varfile sets a apple env var",
+ args: []string{
+ "-var-file=" + filepath.Join(testFixture("var-arg"), "apple.json"),
+ testFixture("var-arg"),
+ },
+ fileCheck: fileCheck{expected: []string{"apple.txt"}},
+ },
+
+ {
+ name: "var-args: hcl - arg sets a tomato env var",
+ args: []string{
+ "-var=fruit=tomato",
+ testFixture("var-arg"),
+ },
+ fileCheck: fileCheck{expected: []string{"tomato.txt"}},
+ },
+
+ {
+ name: "source name: HCL",
+ args: []string{
+ "-parallel-builds=1", // to ensure order is kept
+ testFixture("build-name-and-type"),
+ },
+ fileCheck: fileCheck{
+ expectedContent: map[string]string{
+ "manifest.json": `{
+ "builds": [
+ {
+ "name": "test",
+ "builder_type": "null",
+ "files": null,
+ "artifact_id": "Null",
+ "packer_run_uuid": "",
+ "custom_data": null
+ },
+ {
+ "name": "potato",
+ "builder_type": "null",
+ "files": null,
+ "artifact_id": "Null",
+ "packer_run_uuid": "",
+ "custom_data": null
+ }
+ ],
+ "last_run_uuid": ""
+}`,
+ },
+ },
+ },
+
+ {
+ name: "build name: JSON except potato",
+ args: []string{
+ "-except=potato",
+ "-parallel-builds=1", // to ensure order is kept
+ filepath.Join(testFixture("build-name-and-type"), "all.json"),
+ },
+ fileCheck: fileCheck{
+ expected: []string{
+ "null.test.txt",
+ "null.potato.txt",
+ },
+ expectedContent: map[string]string{
+ "manifest.json": `{
+ "builds": [
+ {
+ "name": "test",
+ "builder_type": "null",
+ "files": null,
+ "artifact_id": "Null",
+ "packer_run_uuid": "",
+ "custom_data": null
+ }
+ ],
+ "last_run_uuid": ""
+}`,
+ },
+ },
+ },
+
+ {
+ name: "build name: JSON only potato",
+ args: []string{
+ "-only=potato",
+ "-parallel-builds=1", // to ensure order is kept
+ filepath.Join(testFixture("build-name-and-type"), "all.json"),
+ },
+ fileCheck: fileCheck{
+ expectedContent: map[string]string{
+ "manifest.json": `{
+ "builds": [
+ {
+ "name": "potato",
+ "builder_type": "null",
+ "files": null,
+ "artifact_id": "Null",
+ "packer_run_uuid": "",
+ "custom_data": null
+ }
+ ],
+ "last_run_uuid": ""
+}`,
+ },
+ },
+ },
+
+ // only / except HCL2
+ {
+ name: "hcl - 'except' a build block",
+ args: []string{
+ "-except=my_build.*",
+ testFixture("hcl-only-except"),
+ },
+ fileCheck: fileCheck{
+ expected: []string{"cherry.txt"},
+ notExpected: []string{"chocolate.txt", "vanilla.txt"},
+ },
+ },
+
+ {
+ name: "hcl - 'only' a build block",
+ args: []string{
+ "-only=my_build.*",
+ testFixture("hcl-only-except"),
+ },
+ fileCheck: fileCheck{
+ notExpected: []string{"cherry.txt"},
+ expected: []string{"chocolate.txt", "vanilla.txt"},
+ },
+ },
+
+ // recipes
+ {
+ name: "hcl - recipes",
+ args: []string{
+ testFixture("hcl", "recipes"),
+ },
+ fileCheck: fileCheck{
+ expectedContent: map[string]string{
+ "NULL.spaghetti_carbonara.txt": spaghettiCarbonara,
+ "NULL.lasagna.txt": lasagna,
+ "NULL.tiramisu.txt": tiramisu,
+ },
+ },
+ },
+
+ {
+ name: "hcl - recipes - except carbonara",
+ args: []string{
+ "-except", "recipes.null.spaghetti_carbonara",
+ testFixture("hcl", "recipes"),
+ },
+ fileCheck: fileCheck{
+ notExpected: []string{"NULL.spaghetti_carbonara.txt"},
+ expectedContent: map[string]string{
+ "NULL.lasagna.txt": lasagna,
+ "NULL.tiramisu.txt": tiramisu,
+ },
+ },
+ },
+
+ {
+ name: "hcl - recipes - only lasagna",
+ args: []string{
+ "-only", "*lasagna",
+ testFixture("hcl", "recipes"),
+ },
+ fileCheck: fileCheck{
+ notExpected: []string{
+ "NULL.spaghetti_carbonara.txt",
+ "NULL.tiramisu.txt",
+ },
+ expectedContent: map[string]string{
+ "NULL.lasagna.txt": lasagna,
+ },
+ },
+ },
+ {
+ name: "hcl - recipes - only recipes",
+ args: []string{
+ "-only", "recipes.*",
+ testFixture("hcl", "recipes"),
+ },
+ fileCheck: fileCheck{
+ notExpected: []string{
+ "NULL.tiramisu.txt",
+ },
+ expectedContent: map[string]string{
+ "NULL.spaghetti_carbonara.txt": spaghettiCarbonara,
+ "NULL.lasagna.txt": lasagna,
+ },
+ },
+ },
+ {
+ name: "hcl - build.name accessible",
+ args: []string{
+ filepath.Join(testFixture("build-name-and-type"), "buildname.pkr.hcl"),
+ },
+ fileCheck: fileCheck{
+ expected: []string{
+ "pineapple.pizza.txt",
+ },
+ },
+ },
+
+ {
+ name: "hcl - valid validation rule for default value",
+ args: []string{
+ filepath.Join(testFixture("hcl", "validation", "map")),
+ },
+ expectedCode: 0,
+ },
+
+ {
+ name: "hcl - valid setting from varfile",
+ args: []string{
+ "-var-file", filepath.Join(testFixture("hcl", "validation", "map", "valid_value.pkrvars.hcl")),
+ filepath.Join(testFixture("hcl", "validation", "map")),
+ },
+ expectedCode: 0,
+ },
+
+ {
+ name: "hcl - invalid setting from varfile",
+ args: []string{
+ "-var-file", filepath.Join(testFixture("hcl", "validation", "map", "invalid_value.pkrvars.hcl")),
+ filepath.Join(testFixture("hcl", "validation", "map")),
+ },
+ expectedCode: 1,
+ },
+
+ {
+ name: "hcl - valid cmd ( invalid varfile bypased )",
+ args: []string{
+ "-var-file", filepath.Join(testFixture("hcl", "validation", "map", "invalid_value.pkrvars.hcl")),
+ "-var", `image_metadata={key = "new_value", something = { foo = "bar" }}`,
+ filepath.Join(testFixture("hcl", "validation", "map")),
+ },
+ expectedCode: 0,
+ },
+
+ {
+ name: "hcl - invalid cmd ( valid varfile bypased )",
+ args: []string{
+ "-var-file", filepath.Join(testFixture("hcl", "validation", "map", "valid_value.pkrvars.hcl")),
+ "-var", `image_metadata={key = "?", something = { foo = "wrong" }}`,
+ filepath.Join(testFixture("hcl", "validation", "map")),
+ },
+ expectedCode: 1,
+ },
+ {
+ name: "hcl - execute and use datasource",
+ args: []string{
+ testFixture("hcl", "datasource.pkr.hcl"),
+ },
+ fileCheck: fileCheck{
+ expectedContent: map[string]string{
+ "chocolate.txt": "chocolate",
+ },
+ },
+ },
+ {
+ name: "hcl - dynamic source blocks in a build block",
+ args: []string{
+ testFixture("hcl", "dynamic", "build.pkr.hcl"),
+ },
+ fileCheck: fileCheck{
+ expectedContent: map[string]string{
+ "dummy.txt": "layers/base/main/files",
+ "postgres/13.txt": "layers/base/main/files\nlayers/base/init/files\nlayers/postgres/files",
+ },
+ expected: []string{"dummy-fooo.txt", "dummy-baar.txt", "postgres/13-fooo.txt", "postgres/13-baar.txt"},
+ },
+ },
+
+ {
+ name: "hcl - variables can be used in shared post-processor fields",
+ args: []string{
+ testFixture("hcl", "var-in-pp-name.pkr.hcl"),
+ },
+ fileCheck: fileCheck{
+ expectedContent: map[string]string{
+ "example1.1.txt": one,
+ "example2.2.txt": two,
+ },
+ notExpected: []string{
+ "example1.2.txt",
+ "example2.1.txt",
+ },
+ },
+ },
+ {
+ name: "hcl - using build variables in post-processor",
+ args: []string{
+ testFixture("hcl", "build-var-in-pp.pkr.hcl"),
+ },
+ fileCheck: fileCheck{
+ expectedContent: map[string]string{
+ "example.2.txt": two,
+ },
+ },
+ },
+
+ {
+ name: "hcl - test crash #11381",
+ args: []string{
+ testFixture("hcl", "nil-component-crash.pkr.hcl"),
+ },
+ expectedCode: 1,
+ },
+ {
+ name: "hcl - using variables in build block",
+ args: []string{
+ testFixture("hcl", "vars-in-build-block.pkr.hcl"),
+ },
+ fileCheck: fileCheck{
+ expectedContent: map[string]string{
+ "example.2.txt": two,
+ },
+ },
+ },
+ {
+ name: "hcl - recursive local using input var",
+ args: []string{
+ testFixture("hcl", "recursive_local_with_input"),
+ },
+ fileCheck: fileCheck{
+ expectedContent: map[string]string{
+ "hey.txt": "hello",
+ },
+ },
+ },
+ {
+ name: "hcl - recursive local using an unset input var",
+ args: []string{
+ testFixture("hcl", "recursive_local_with_unset_input"),
+ },
+ fileCheck: fileCheck{},
+ expectedCode: 1,
+ },
+ {
+ name: "hcl - var with default value empty object/list can be set",
+ args: []string{
+ testFixture("hcl", "empty_object"),
+ },
+ fileCheck: fileCheck{
+ expectedContent: map[string]string{
+ "foo.txt": "yo",
+ },
+ },
+ },
+ {
+ name: "hcl - unknown ",
+ args: []string{
+ testFixture("hcl", "data-source-validation.pkr.hcl"),
+ },
+ fileCheck: fileCheck{
+ expectedContent: map[string]string{
+ "foo.txt": "foo",
+ },
+ expected: []string{
+ "s3cr3t",
+ },
+ },
+ },
+ }
+
+ for _, tt := range tc {
+ t.Run(tt.name, func(t *testing.T) {
+ defer tt.cleanup(t)
+ t.Logf("Running build on %s", tt.args)
+ run(t, tt.args, tt.expectedCode)
+ tt.fileCheck.verify(t, "")
+ })
+ }
+}
+
+func Test_build_output(t *testing.T) {
+
+ tc := []struct {
+ command []string
+ env []string
+ expected []string
+ notExpected []string
+ runtime string
+ }{
+ {[]string{"build", "--color=false", testFixture("hcl", "reprepare", "shell-local.pkr.hcl")},
+ nil,
+ []string{"null.example: hello from the NULL builder packeruser", "Build 'null.example' finished after"},
+ []string{},
+ "posix"},
+ {[]string{"build", "--color=false", testFixture("hcl", "reprepare", "shell-local-windows.pkr.hcl")},
+ nil,
+ []string{"null.example: hello from the NULL builder packeruser", "Build 'null.example' finished after"},
+ []string{},
+ "windows"},
+ {[]string{"build", "--color=false", testFixture("hcl", "provisioner-override.pkr.hcl")},
+ nil,
+ []string{"null.example1: yes overridden", "null.example2: not overridden"},
+ []string{"null.example2: yes overridden", "null.example1: not overridden"},
+ "posix"},
+ {[]string{"build", "--color=false", testFixture("provisioners", "provisioner-override.json")},
+ nil,
+ []string{"example1: yes overridden", "example2: not overridden"},
+ []string{"example2: yes overridden", "example1: not overridden"},
+ "posix"},
+ }
+
+ for _, tc := range tc {
+ if (runtime.GOOS == "windows") != (tc.runtime == "windows") {
+ continue
+ }
+ t.Run(fmt.Sprintf("packer %s", tc.command), func(t *testing.T) {
+ p := helperCommand(t, tc.command...)
+ p.Env = append(p.Env, tc.env...)
+ bs, err := p.Output()
+ if err != nil {
+ t.Fatalf("%v: %s", err, bs)
+ }
+ for _, expected := range tc.expected {
+ if !strings.Contains(string(bs), expected) {
+ t.Fatalf("Should contain output %s.\nReceived: %s", tc.expected, string(bs))
+ }
+ }
+ for _, notExpected := range tc.notExpected {
+ if strings.Contains(string(bs), notExpected) {
+ t.Fatalf("Should NOT contain output %s.\nReceived: %s", tc.expected, string(bs))
+ }
+ }
+ })
+ }
+}
+
+func TestBuildOnlyFileCommaFlags(t *testing.T) {
+ c := &BuildCommand{
+ Meta: TestMetaFile(t),
+ }
+
+ args := []string{
+ "-parallel-builds=1",
+ "-only=chocolate,vanilla",
+ filepath.Join(testFixture("build-only"), "template.json"),
+ }
+
+ defer cleanup()
+
+ if code := c.Run(args); code != 0 {
+ fatalCommand(t, c.Meta)
+ }
+
+ for _, f := range []string{"chocolate.txt", "vanilla.txt",
+ "apple.txt", "peach.txt", "pear.txt", "unnamed.txt"} {
+ if !fileExists(f) {
+ t.Errorf("Expected to find %s", f)
+ }
+ }
+
+ if fileExists("cherry.txt") {
+ t.Error("Expected NOT to find cherry.txt")
+ }
+
+ if !fileExists("tomato.txt") {
+ t.Error("Expected to find tomato.txt")
+ }
+}
+
+func TestBuildStdin(t *testing.T) {
+ c := &BuildCommand{
+ Meta: TestMetaFile(t),
+ }
+ f, err := os.Open(filepath.Join(testFixture("build-only"), "template.json"))
+ if err != nil {
+ t.Fatal(err)
+ }
+ defer f.Close()
+
+ stdin := os.Stdin
+ os.Stdin = f
+ defer func() { os.Stdin = stdin }()
+
+ defer cleanup()
+ if code := c.Run([]string{"-parallel-builds=1", "-"}); code != 0 {
+ fatalCommand(t, c.Meta)
+ }
+
+ for _, f := range []string{"vanilla.txt", "cherry.txt", "chocolate.txt",
+ "unnamed.txt"} {
+ if !fileExists(f) {
+ t.Errorf("Expected to find %s", f)
+ }
+ }
+}
+
+func TestBuildOnlyFileMultipleFlags(t *testing.T) {
+ c := &BuildCommand{
+ Meta: TestMetaFile(t),
+ }
+
+ args := []string{
+ "-parallel-builds=1",
+ "-only=chocolate",
+ "-only=cherry",
+ "-only=apple", // ignored
+ "-only=peach", // ignored
+ "-only=pear", // ignored
+ filepath.Join(testFixture("build-only"), "template.json"),
+ }
+
+ defer cleanup()
+
+ if code := c.Run(args); code != 0 {
+ fatalCommand(t, c.Meta)
+ }
+
+ for _, f := range []string{"vanilla.txt", "tomato.txt"} {
+ if fileExists(f) {
+ t.Errorf("Expected NOT to find %s", f)
+ }
+ }
+ for _, f := range []string{"chocolate.txt", "cherry.txt",
+ "apple.txt", "peach.txt", "pear.txt", "unnamed.txt"} {
+ if !fileExists(f) {
+ t.Errorf("Expected to find %s", f)
+ }
+ }
+}
+
+func TestBuildProvisionAndPosProcessWithBuildVariablesSharing(t *testing.T) {
+ c := &BuildCommand{
+ Meta: TestMetaFile(t),
+ }
+
+ args := []string{
+ filepath.Join(testFixture("build-variable-sharing"), "template.json"),
+ }
+
+ files := []string{
+ "provisioner.Null.txt",
+ "post-processor.Null.txt",
+ }
+
+ defer cleanup(files...)
+
+ if code := c.Run(args); code != 0 {
+ fatalCommand(t, c.Meta)
+ }
+
+ for _, f := range files {
+ if !fileExists(f) {
+ t.Errorf("Expected to find %s", f)
+ }
+ }
+}
+
+func TestBuildEverything(t *testing.T) {
+ c := &BuildCommand{
+ Meta: TestMetaFile(t),
+ }
+
+ args := []string{
+ "-parallel-builds=1",
+ `-except=`,
+ filepath.Join(testFixture("build-only"), "template.json"),
+ }
+
+ defer cleanup()
+
+ if code := c.Run(args); code != 0 {
+ fatalCommand(t, c.Meta)
+ }
+
+ for _, f := range []string{"chocolate.txt", "vanilla.txt", "tomato.txt",
+ "apple.txt", "cherry.txt", "pear.txt", "peach.txt", "unnamed.txt"} {
+ if !fileExists(f) {
+ t.Errorf("Expected to find %s", f)
+ }
+ }
+}
+
+func TestBuildExceptFileCommaFlags(t *testing.T) {
+ c := &BuildCommand{
+ Meta: TestMetaFile(t),
+ }
+ tc := []struct {
+ name string
+ args []string
+ expectedFiles []string
+ buildNotExpectedFiles []string
+ postProcNotExpectedFiles []string
+ }{
+ {
+ name: "JSON: except build and post-processor",
+ args: []string{
+ "-parallel-builds=1",
+ "-except=chocolate,vanilla,tomato",
+ filepath.Join(testFixture("build-only"), "template.json"),
+ },
+ expectedFiles: []string{"apple.txt", "cherry.txt", "peach.txt"},
+ buildNotExpectedFiles: []string{"chocolate.txt", "vanilla.txt", "tomato.txt", "unnamed.txt"},
+ postProcNotExpectedFiles: []string{"pear.txt, banana.txt"},
+ },
+ {
+ name: "HCL2: except build and post-processor",
+ args: []string{
+ "-parallel-builds=1",
+ "-except=file.chocolate,file.vanilla,tomato",
+ filepath.Join(testFixture("build-only"), "template.pkr.hcl"),
+ },
+ expectedFiles: []string{"apple.txt", "cherry.txt", "peach.txt"},
+ buildNotExpectedFiles: []string{"chocolate.txt", "vanilla.txt", "tomato.txt", "unnamed.txt"},
+ postProcNotExpectedFiles: []string{"pear.txt, banana.txt"},
+ },
+ {
+ name: "HCL2-JSON: except build and post-processor",
+ args: []string{
+ "-parallel-builds=1",
+ "-except=file.chocolate,file.vanilla,tomato",
+ filepath.Join(testFixture("build-only"), "template.pkr.json"),
+ },
+ expectedFiles: []string{"apple.txt", "cherry.txt", "peach.txt"},
+ buildNotExpectedFiles: []string{"chocolate.txt", "vanilla.txt", "tomato.txt", "unnamed.txt"},
+ postProcNotExpectedFiles: []string{"pear.txt, banana.txt"},
+ },
+ }
+
+ for _, tt := range tc {
+ t.Run(tt.name, func(t *testing.T) {
+ defer cleanup()
+
+ if code := c.Run(tt.args); code != 0 {
+ fatalCommand(t, c.Meta)
+ }
+
+ for _, f := range tt.buildNotExpectedFiles {
+ if fileExists(f) {
+ t.Errorf("build not skipped: Expected NOT to find %s", f)
+ }
+ }
+ for _, f := range tt.postProcNotExpectedFiles {
+ if fileExists(f) {
+ t.Errorf("post-processor not skipped: Expected NOT to find %s", f)
+ }
+ }
+ for _, f := range tt.expectedFiles {
+ if !fileExists(f) {
+ t.Errorf("Expected to find %s", f)
+ }
+ }
+ })
+ }
+}
+
+func testHCLOnlyExceptFlags(t *testing.T, args, present, notPresent []string, expectReturn int) {
+ c := &BuildCommand{
+ Meta: TestMetaFile(t),
+ }
+
+ defer cleanup()
+
+ finalArgs := []string{"-parallel-builds=1"}
+ finalArgs = append(finalArgs, args...)
+ finalArgs = append(finalArgs, testFixture("hcl-only-except"))
+
+ if code := c.Run(finalArgs); code != expectReturn {
+ fatalCommand(t, c.Meta)
+ }
+
+ for _, f := range notPresent {
+ if fileExists(f) {
+ t.Errorf("Expected NOT to find %s", f)
+ }
+ }
+ for _, f := range present {
+ if !fileExists(f) {
+ t.Errorf("Expected to find %s", f)
+ }
+ }
+}
+
+func TestHCL2PostProcessorForceFlag(t *testing.T) {
+ t.Helper()
+
+ UUID, _ := uuid.GenerateUUID()
+ // Manifest will only clean with force if the build's PACKER_RUN_UUID are different
+ t.Setenv("PACKER_RUN_UUID", UUID)
+
+ args := []string{
+ filepath.Join(testFixture("hcl"), "force.pkr.hcl"),
+ }
+ fCheck := fileCheck{
+ expectedContent: map[string]string{
+ "manifest.json": fmt.Sprintf(`{
+ "builds": [
+ {
+ "name": "potato",
+ "builder_type": "null",
+ "files": null,
+ "artifact_id": "Null",
+ "packer_run_uuid": %q,
+ "custom_data": null
+ }
+ ],
+ "last_run_uuid": %q
+}`, UUID, UUID),
+ },
+ }
+ defer fCheck.cleanup(t)
+
+ c := &BuildCommand{
+ Meta: TestMetaFile(t),
+ }
+ if code := c.Run(args); code != 0 {
+ fatalCommand(t, c.Meta)
+ }
+ fCheck.verify(t, "")
+
+ // Second build should override previous manifest
+ UUID, _ = uuid.GenerateUUID()
+ t.Setenv("PACKER_RUN_UUID", UUID)
+
+ args = []string{
+ "-force",
+ filepath.Join(testFixture("hcl"), "force.pkr.hcl"),
+ }
+ fCheck = fileCheck{
+ expectedContent: map[string]string{
+ "manifest.json": fmt.Sprintf(`{
+ "builds": [
+ {
+ "name": "potato",
+ "builder_type": "null",
+ "files": null,
+ "artifact_id": "Null",
+ "packer_run_uuid": %q,
+ "custom_data": null
+ }
+ ],
+ "last_run_uuid": %q
+}`, UUID, UUID),
+ },
+ }
+
+ c = &BuildCommand{
+ Meta: TestMetaFile(t),
+ }
+ if code := c.Run(args); code != 0 {
+ fatalCommand(t, c.Meta)
+ }
+ fCheck.verify(t, "")
+}
+
+func TestBuildCommand_HCLOnlyExceptOptions(t *testing.T) {
+ tests := []struct {
+ args []string
+ present []string
+ notPresent []string
+ expectReturn int
+ }{
+ {
+ []string{"-only=chocolate"},
+ []string{},
+ []string{"chocolate.txt", "vanilla.txt", "cherry.txt"},
+ 1,
+ },
+ {
+ []string{"-only=*chocolate*"},
+ []string{"chocolate.txt"},
+ []string{"vanilla.txt", "cherry.txt"},
+ 0,
+ },
+ {
+ []string{"-except=*chocolate*"},
+ []string{"vanilla.txt", "cherry.txt"},
+ []string{"chocolate.txt"},
+ 0,
+ },
+ {
+ []string{"-except=*ch*"},
+ []string{"vanilla.txt"},
+ []string{"chocolate.txt", "cherry.txt"},
+ 0,
+ },
+ {
+ []string{"-only=*chocolate*", "-only=*vanilla*"},
+ []string{"chocolate.txt", "vanilla.txt"},
+ []string{"cherry.txt"},
+ 0,
+ },
+ {
+ []string{"-except=*chocolate*", "-except=*vanilla*"},
+ []string{"cherry.txt"},
+ []string{"chocolate.txt", "vanilla.txt"},
+ 0,
+ },
+ {
+ []string{"-only=my_build.file.chocolate"},
+ []string{"chocolate.txt"},
+ []string{"vanilla.txt", "cherry.txt"},
+ 0,
+ },
+ {
+ []string{"-except=my_build.file.chocolate"},
+ []string{"vanilla.txt", "cherry.txt"},
+ []string{"chocolate.txt"},
+ 0,
+ },
+ {
+ []string{"-only=file.cherry"},
+ []string{"cherry.txt"},
+ []string{"vanilla.txt", "chocolate.txt"},
+ 0,
+ },
+ }
+
+ for _, tt := range tests {
+ t.Run(fmt.Sprintf("%s", tt.args), func(t *testing.T) {
+ testHCLOnlyExceptFlags(t, tt.args, tt.present, tt.notPresent, tt.expectReturn)
+ })
+ }
+}
+
+func TestBuildWithNonExistingBuilder(t *testing.T) {
+ c := &BuildCommand{
+ Meta: TestMetaFile(t),
+ }
+
+ args := []string{
+ "-parallel-builds=1",
+ `-except=`,
+ filepath.Join(testFixture("build-only"), "not-found.json"),
+ }
+
+ defer cleanup()
+
+ if code := c.Run(args); code != 1 {
+ t.Errorf("Expected to find exit code 1, found %d", code)
+ }
+ if !fileExists("chocolate.txt") {
+ t.Errorf("Expected to find chocolate.txt")
+ }
+ if fileExists("vanilla.txt") {
+ t.Errorf("NOT expected to find vanilla.tx")
+ }
+}
+
+func run(t *testing.T, args []string, expectedCode int) {
+ t.Helper()
+
+ c := &BuildCommand{
+ Meta: TestMetaFile(t),
+ }
+
+ if code := c.Run(args); code != expectedCode {
+ fatalCommand(t, c.Meta)
+ }
+}
+
+type fileCheck struct {
+ expected, notExpected []string
+ expectedContent map[string]string
+}
+
+func (fc fileCheck) cleanup(t *testing.T) {
+ for _, file := range fc.expectedFiles() {
+ t.Logf("removing %v", file)
+ if err := os.Remove(file); err != nil {
+ t.Errorf("failed to remove file %s: %v", file, err)
+ }
+ }
+}
+
+func (fc fileCheck) expectedFiles() []string {
+ expected := fc.expected
+ for file := range fc.expectedContent {
+ expected = append(expected, file)
+ }
+ return expected
+}
+
+func (fc fileCheck) verify(t *testing.T, dir string) {
+ for _, f := range fc.expectedFiles() {
+ if _, err := os.Stat(filepath.Join(dir, f)); err != nil {
+ t.Errorf("Expected to find %s: %v", f, err)
+ }
+ }
+ for _, f := range fc.notExpected {
+ if _, err := os.Stat(filepath.Join(dir, f)); err == nil {
+ t.Errorf("Expected to not find %s", f)
+ }
+ }
+ for file, expectedContent := range fc.expectedContent {
+ content, err := ioutil.ReadFile(filepath.Join(dir, file))
+ if err != nil {
+ t.Fatalf("ioutil.ReadFile: %v", err)
+ }
+ if diff := cmp.Diff(expectedContent, string(content)); diff != "" {
+ t.Errorf("content of %s differs: %s", file, diff)
+ }
+ }
+}
+
+func cleanup(moreFiles ...string) {
+ os.RemoveAll("chocolate.txt")
+ os.RemoveAll("vanilla.txt")
+ os.RemoveAll("cherry.txt")
+ os.RemoveAll("apple.txt")
+ os.RemoveAll("peach.txt")
+ os.RemoveAll("banana.txt")
+ os.RemoveAll("pear.txt")
+ os.RemoveAll("tomato.txt")
+ os.RemoveAll("unnamed.txt")
+ os.RemoveAll("roses.txt")
+ os.RemoveAll("fuchsias.txt")
+ os.RemoveAll("lilas.txt")
+ os.RemoveAll("campanules.txt")
+ os.RemoveAll("ducky.txt")
+ os.RemoveAll("banana.txt")
+ for _, file := range moreFiles {
+ os.RemoveAll(file)
+ }
+}
+
+func TestBuildCommand_ParseArgs(t *testing.T) {
+ defaultMeta := TestMetaFile(t)
+ type fields struct {
+ Meta Meta
+ }
+ type args struct {
+ args []string
+ }
+ tests := []struct {
+ fields fields
+ args args
+ wantCfg *BuildArgs
+ wantExitCode int
+ }{
+ {fields{defaultMeta},
+ args{[]string{"file.json"}},
+ &BuildArgs{
+ MetaArgs: MetaArgs{Path: "file.json"},
+ ParallelBuilds: math.MaxInt64,
+ Color: true,
+ },
+ 0,
+ },
+ {fields{defaultMeta},
+ args{[]string{"-parallel-builds=10", "file.json"}},
+ &BuildArgs{
+ MetaArgs: MetaArgs{Path: "file.json"},
+ ParallelBuilds: 10,
+ Color: true,
+ },
+ 0,
+ },
+ {fields{defaultMeta},
+ args{[]string{"-parallel-builds=1", "file.json"}},
+ &BuildArgs{
+ MetaArgs: MetaArgs{Path: "file.json"},
+ ParallelBuilds: 1,
+ Color: true,
+ },
+ 0,
+ },
+ {fields{defaultMeta},
+ args{[]string{"-parallel-builds=5", "file.json"}},
+ &BuildArgs{
+ MetaArgs: MetaArgs{Path: "file.json"},
+ ParallelBuilds: 5,
+ Color: true,
+ },
+ 0,
+ },
+ {fields{defaultMeta},
+ args{[]string{"-parallel-builds=1", "-parallel-builds=5", "otherfile.json"}},
+ &BuildArgs{
+ MetaArgs: MetaArgs{Path: "otherfile.json"},
+ ParallelBuilds: 5,
+ Color: true,
+ },
+ 0,
+ },
+ }
+ for _, tt := range tests {
+ t.Run(fmt.Sprintf("%s", tt.args.args), func(t *testing.T) {
+ c := &BuildCommand{
+ Meta: tt.fields.Meta,
+ }
+ gotCfg, gotExitCode := c.ParseArgs(tt.args.args)
+ if diff := cmp.Diff(gotCfg, tt.wantCfg); diff != "" {
+ t.Fatalf("BuildCommand.ParseArgs() unexpected cfg %s", diff)
+ }
+ if gotExitCode != tt.wantExitCode {
+ t.Fatalf("BuildCommand.ParseArgs() gotExitCode = %v, want %v", gotExitCode, tt.wantExitCode)
+ }
+ })
+ }
+}
+
+// TestProvisionerOnlyExcept checks that only/except blocks in provisioners/post-processors behave as expected
+func TestProvisionerAndPostProcessorOnlyExcept(t *testing.T) {
+ tests := []struct {
+ name string
+ args []string
+ expectedCode int
+ outputCheck func(string, string) error
+ }{
+ {
+ "json - only named build",
+ []string{
+ "-only", "packer",
+ testFixture("provisioners", "provisioner-only-except.json"),
+ },
+ 0,
+ func(out, _ string) error {
+ if !strings.Contains(out, "packer provisioner packer and null") {
+ return fmt.Errorf("missing expected provisioner output")
+ }
+
+ if !strings.Contains(out, "packer post-processor packer and null") {
+ return fmt.Errorf("missing expected post-processor output")
+ }
+
+ if strings.Contains(out, "null post-processor") || strings.Contains(out, "null provisioner") {
+ return fmt.Errorf("found traces of unnamed provisioner/post-processor, should not")
+ }
+
+ return nil
+ },
+ },
+ {
+ "json - only unnamed build",
+ []string{
+ "-only", "null",
+ testFixture("provisioners", "provisioner-only-except.json"),
+ },
+ 0,
+ func(out, _ string) error {
+ if !strings.Contains(out, "null provisioner null and null") {
+ return fmt.Errorf("missing expected provisioner output")
+ }
+
+ if !strings.Contains(out, "null post-processor null and null") {
+ return fmt.Errorf("missing expected post-processor output")
+ }
+
+ if strings.Contains(out, "packer post-processor") || strings.Contains(out, "packer provisioner") {
+ return fmt.Errorf("found traces of named provisioner/post-processor, should not")
+ }
+
+ return nil
+ },
+ },
+ {
+ "hcl - only one source build",
+ []string{
+ "-only", "null.packer",
+ testFixture("provisioners", "provisioner-only-except.pkr.hcl"),
+ },
+ 0,
+ func(out, _ string) error {
+ if !strings.Contains(out, "packer provisioner packer and null") {
+ return fmt.Errorf("missing expected provisioner output")
+ }
+
+ if !strings.Contains(out, "packer post-processor packer and null") {
+ return fmt.Errorf("missing expected post-processor output")
+ }
+
+ if strings.Contains(out, "other post-processor") || strings.Contains(out, "other provisioner") {
+ return fmt.Errorf("found traces of other provisioner/post-processor, should not")
+ }
+
+ return nil
+ },
+ },
+ {
+ "hcl - only other build",
+ []string{
+ "-only", "null.other",
+ testFixture("provisioners", "provisioner-only-except.pkr.hcl"),
+ },
+ 0,
+ func(out, _ string) error {
+ if !strings.Contains(out, "other provisioner other and null") {
+ return fmt.Errorf("missing expected provisioner output")
+ }
+
+ if !strings.Contains(out, "other post-processor other and null") {
+ return fmt.Errorf("missing expected post-processor output")
+ }
+
+ if strings.Contains(out, "packer post-processor") || strings.Contains(out, "packer provisioner") {
+ return fmt.Errorf("found traces of \"packer\" source provisioner/post-processor, should not")
+ }
+
+ return nil
+ },
+ },
+ }
+
+ for _, tt := range tests {
+ t.Run(tt.name, func(t *testing.T) {
+ c := &BuildCommand{
+ Meta: TestMetaFile(t),
+ }
+
+ exitCode := c.Run(tt.args)
+ if exitCode != tt.expectedCode {
+ t.Errorf("process exit code mismatch: expected %d, got %d",
+ tt.expectedCode,
+ exitCode)
+ }
+
+ out, stderr := GetStdoutAndErrFromTestMeta(t, c.Meta)
+ err := tt.outputCheck(out, stderr)
+ if err != nil {
+ if len(out) != 0 {
+ t.Logf("command stdout: %q", out)
+ }
+
+ if len(stderr) != 0 {
+ t.Logf("command stderr: %q", stderr)
+ }
+ t.Error(err.Error())
+ }
+ })
+ }
+}
+
+// TestBuildCmd aims to test the build command, with output validation
+func TestBuildCmd(t *testing.T) {
+ tests := []struct {
+ name string
+ args []string
+ expectedCode int
+ outputCheck func(string, string) error
+ }{
+ {
+ name: "hcl - no build block error",
+ args: []string{
+ testFixture("hcl", "no_build.pkr.hcl"),
+ },
+ expectedCode: 1,
+ outputCheck: func(_, err string) error {
+ if !strings.Contains(err, "Error: Missing build block") {
+ return fmt.Errorf("expected 'Error: Missing build block' in output, did not find it")
+ }
+
+ nbErrs := strings.Count(err, "Error: ")
+ if nbErrs != 1 {
+ return fmt.Errorf(
+ "error: too many errors in stdout for build block, expected 1, got %d",
+ nbErrs)
+ }
+
+ return nil
+ },
+ },
+ {
+ name: "hcl - undefined var set in pkrvars",
+ args: []string{
+ testFixture("hcl", "variables", "ref_non_existing"),
+ },
+ expectedCode: 0,
+ outputCheck: func(out, err string) error {
+ nbWarns := strings.Count(out, "Warning: ")
+ if nbWarns != 0 {
+ return fmt.Errorf(
+ "error: too many warnings in build output, expected 0, got %d",
+ nbWarns)
+ }
+
+ nbErrs := strings.Count(err, "Error: ")
+ if nbErrs != 0 {
+ return fmt.Errorf("error: expected build to succeed without errors, got %d",
+ nbErrs)
+ }
+ return nil
+ },
+ },
+ {
+ name: "hcl - build block without source",
+ args: []string{
+ testFixture("hcl", "build_no_source.pkr.hcl"),
+ },
+ expectedCode: 1,
+ outputCheck: func(_, err string) error {
+ if !strings.Contains(err, "Error: missing source reference") {
+ return fmt.Errorf("expected 'Error: missing source reference' in output, did not find it")
+ }
+
+ nbErrs := strings.Count(err, "Error: ")
+ if nbErrs != 1 {
+ return fmt.Errorf(
+ "error: too many errors in stderr for build, expected 1, got %d",
+ nbErrs)
+ }
+
+ logRegex := regexp.MustCompile("on.*build_no_source.pkr.hcl line 1")
+ if !logRegex.MatchString(err) {
+ return fmt.Errorf("error: missing context for error message")
+ }
+
+ return nil
+ },
+ },
+ {
+ name: "hcl - exclude post-processor, expect no warning",
+ args: []string{
+ "-except", "manifest",
+ testFixture("hcl", "test_except_manifest.pkr.hcl"),
+ },
+ expectedCode: 0,
+ outputCheck: func(out, err string) error {
+ for _, stream := range []string{out, err} {
+ if strings.Contains(stream, "Warning: an 'except' option was passed, but did not match any build") {
+ return fmt.Errorf("Unexpected warning for build no match with except")
+ }
+
+ if strings.Contains(stream, "Running post-processor:") {
+ return fmt.Errorf("Should not run post-processors, but found one")
+ }
+ }
+
+ return nil
+ },
+ },
+ }
+
+ for _, tt := range tests {
+ t.Run(tt.name, func(t *testing.T) {
+ c := &BuildCommand{
+ Meta: TestMetaFile(t),
+ }
+
+ exitCode := c.Run(tt.args)
+ if exitCode != tt.expectedCode {
+ t.Errorf("process exit code mismatch: expected %d, got %d",
+ tt.expectedCode,
+ exitCode)
+ }
+
+ out, stderr := GetStdoutAndErrFromTestMeta(t, c.Meta)
+ err := tt.outputCheck(out, stderr)
+ if err != nil {
+ if len(out) != 0 {
+ t.Logf("command stdout: %q", out)
+ }
+
+ if len(stderr) != 0 {
+ t.Logf("command stderr: %q", stderr)
+ }
+ t.Error(err.Error())
+ }
+ })
+ }
+}
diff --git a/v1.9.4/command/build_timeout_test.go b/v1.9.4/command/build_timeout_test.go
new file mode 100644
index 0000000..9896894
--- /dev/null
+++ b/v1.9.4/command/build_timeout_test.go
@@ -0,0 +1,77 @@
+// Copyright (c) HashiCorp, Inc.
+// SPDX-License-Identifier: MPL-2.0
+
+package command
+
+import (
+ "bytes"
+ "path/filepath"
+ "testing"
+
+ packersdk "github.com/hashicorp/packer-plugin-sdk/packer"
+ "github.com/hashicorp/packer/builder/file"
+ "github.com/hashicorp/packer/packer"
+ shell_local "github.com/hashicorp/packer/provisioner/shell-local"
+ "github.com/hashicorp/packer/provisioner/sleep"
+)
+
+// testCoreConfigBuilder creates a packer CoreConfig that has a file builder
+// available. This allows us to test a builder that writes files to disk.
+func testCoreConfigSleepBuilder(t *testing.T) *packer.CoreConfig {
+ components := packer.ComponentFinder{
+ PluginConfig: &packer.PluginConfig{
+ Builders: packer.MapOfBuilder{
+ "file": func() (packersdk.Builder, error) { return &file.Builder{}, nil },
+ },
+ Provisioners: packer.MapOfProvisioner{
+ "sleep": func() (packersdk.Provisioner, error) { return &sleep.Provisioner{}, nil },
+ "shell-local": func() (packersdk.Provisioner, error) { return &shell_local.Provisioner{}, nil },
+ },
+ },
+ }
+ return &packer.CoreConfig{
+ Components: components,
+ }
+}
+
+// testMetaFile creates a Meta object that includes a file builder
+func testMetaSleepFile(t *testing.T) Meta {
+ var out, err bytes.Buffer
+ return Meta{
+ CoreConfig: testCoreConfigSleepBuilder(t),
+ Ui: &packersdk.BasicUi{
+ Writer: &out,
+ ErrorWriter: &err,
+ },
+ }
+}
+
+func TestBuildSleepTimeout(t *testing.T) {
+ defer cleanup()
+
+ c := &BuildCommand{
+ Meta: testMetaSleepFile(t),
+ }
+
+ args := []string{
+ filepath.Join(testFixture("timeout"), "template.json"),
+ }
+
+ defer cleanup()
+
+ if code := c.Run(args); code == 0 {
+ fatalCommand(t, c.Meta)
+ }
+
+ for _, f := range []string{"roses.txt", "fuchsias.txt", "lilas.txt"} {
+ if !fileExists(f) {
+ t.Errorf("Expected to find %s", f)
+ }
+ }
+
+ for _, f := range []string{"campanules.txt"} {
+ if fileExists(f) {
+ t.Errorf("Expected to not find %s", f)
+ }
+ }
+}
diff --git a/v1.9.4/command/build_windows_test.go b/v1.9.4/command/build_windows_test.go
new file mode 100644
index 0000000..5c99cd9
--- /dev/null
+++ b/v1.9.4/command/build_windows_test.go
@@ -0,0 +1,18 @@
+// Copyright (c) HashiCorp, Inc.
+// SPDX-License-Identifier: MPL-2.0
+
+package command
+
+import "strings"
+
+func init() {
+ spaghettiCarbonara = fixWindowsLineEndings(spaghettiCarbonara)
+ lasagna = fixWindowsLineEndings(lasagna)
+ tiramisu = fixWindowsLineEndings(tiramisu)
+ one = fixWindowsLineEndings(one)
+ two = fixWindowsLineEndings(two)
+}
+
+func fixWindowsLineEndings(s string) string {
+ return strings.ReplaceAll(s, "\n", " \r\n")
+}
diff --git a/v1.9.4/command/cli.go b/v1.9.4/command/cli.go
new file mode 100644
index 0000000..de47a73
--- /dev/null
+++ b/v1.9.4/command/cli.go
@@ -0,0 +1,189 @@
+// Copyright (c) HashiCorp, Inc.
+// SPDX-License-Identifier: MPL-2.0
+
+package command
+
+import (
+ "flag"
+ "strings"
+
+ "github.com/hashicorp/packer/command/enumflag"
+ kvflag "github.com/hashicorp/packer/command/flag-kv"
+ sliceflag "github.com/hashicorp/packer/command/flag-slice"
+)
+
+//go:generate enumer -type configType -trimprefix ConfigType -transform snake
+type configType int
+
+const (
+ ConfigTypeJSON configType = iota // default config type
+ ConfigTypeHCL2
+)
+
+func (c *configType) Set(value string) error {
+ v, err := configTypeString(value)
+ if err == nil {
+ *c = v
+ }
+ return err
+}
+
+// ConfigType tells what type of config we should use, it can return values
+// like "hcl" or "json".
+// Make sure Args was correctly set before.
+func (ma *MetaArgs) GetConfigType() (configType, error) {
+ if ma.Path == "" {
+ return ma.ConfigType, nil
+ }
+ name := ma.Path
+ if name == "-" {
+ // TODO(azr): To allow piping HCL2 confs (when args is "-"), we probably
+ // will need to add a setting that says "this is an HCL config".
+ return ma.ConfigType, nil
+ }
+ if strings.HasSuffix(name, ".pkr.hcl") ||
+ strings.HasSuffix(name, ".pkr.json") {
+ return ConfigTypeHCL2, nil
+ }
+ isDir, err := isDir(name)
+ if isDir {
+ return ConfigTypeHCL2, err
+ }
+ return ma.ConfigType, err
+}
+
+// NewMetaArgs parses cli args and put possible values
+func (ma *MetaArgs) AddFlagSets(fs *flag.FlagSet) {
+ fs.Var((*sliceflag.StringFlag)(&ma.Only), "only", "")
+ fs.Var((*sliceflag.StringFlag)(&ma.Except), "except", "")
+ fs.Var((*kvflag.Flag)(&ma.Vars), "var", "")
+ fs.Var((*kvflag.StringSlice)(&ma.VarFiles), "var-file", "")
+ fs.Var(&ma.ConfigType, "config-type", "set to 'hcl2' to run in hcl2 mode when no file is passed.")
+}
+
+// MetaArgs defines commonalities between all commands
+type MetaArgs struct {
+ // TODO(azr): in the future, I want to allow passing multiple path to
+ // merge HCL confs together; but this will probably need an RFC first.
+ Path string
+ Only, Except []string
+ Vars map[string]string
+ VarFiles []string
+ // set to "hcl2" to force hcl2 mode
+ ConfigType configType
+
+ // WarnOnUndeclared does not have a common default, as the default varies per sub-command usage.
+ // Refer to individual command FlagSets for usage.
+ WarnOnUndeclaredVar bool
+}
+
+func (ba *BuildArgs) AddFlagSets(flags *flag.FlagSet) {
+ flags.BoolVar(&ba.Color, "color", true, "")
+ flags.BoolVar(&ba.Debug, "debug", false, "")
+ flags.BoolVar(&ba.Force, "force", false, "")
+ flags.BoolVar(&ba.TimestampUi, "timestamp-ui", false, "")
+ flags.BoolVar(&ba.MachineReadable, "machine-readable", false, "")
+
+ flags.Int64Var(&ba.ParallelBuilds, "parallel-builds", 0, "")
+
+ flagOnError := enumflag.New(&ba.OnError, "cleanup", "abort", "ask", "run-cleanup-provisioner")
+ flags.Var(flagOnError, "on-error", "")
+
+ flags.BoolVar(&ba.MetaArgs.WarnOnUndeclaredVar, "warn-on-undeclared-var", false, "Show warnings for variable files containing undeclared variables.")
+ ba.MetaArgs.AddFlagSets(flags)
+}
+
+// BuildArgs represents a parsed cli line for a `packer build`
+type BuildArgs struct {
+ MetaArgs
+ Debug, Force bool
+ Color, TimestampUi, MachineReadable bool
+ ParallelBuilds int64
+ OnError string
+}
+
+func (ia *InitArgs) AddFlagSets(flags *flag.FlagSet) {
+ flags.BoolVar(&ia.Upgrade, "upgrade", false, "upgrade any present plugin to the highest allowed version.")
+
+ ia.MetaArgs.AddFlagSets(flags)
+}
+
+// InitArgs represents a parsed cli line for a `packer init <path>`
+type InitArgs struct {
+ MetaArgs
+ Upgrade bool
+}
+
+// PluginsRequiredArgs represents a parsed cli line for a `packer plugins required <path>`
+type PluginsRequiredArgs struct {
+ MetaArgs
+}
+
+// ConsoleArgs represents a parsed cli line for a `packer console`
+type ConsoleArgs struct {
+ MetaArgs
+}
+
+func (fa *FixArgs) AddFlagSets(flags *flag.FlagSet) {
+ flags.BoolVar(&fa.Validate, "validate", true, "")
+
+ fa.MetaArgs.AddFlagSets(flags)
+}
+
+// FixArgs represents a parsed cli line for a `packer fix`
+type FixArgs struct {
+ MetaArgs
+ Validate bool
+}
+
+func (va *ValidateArgs) AddFlagSets(flags *flag.FlagSet) {
+ flags.BoolVar(&va.SyntaxOnly, "syntax-only", false, "check syntax only")
+ flags.BoolVar(&va.NoWarnUndeclaredVar, "no-warn-undeclared-var", false, "Ignore warnings for variable files containing undeclared variables.")
+ flags.BoolVar(&va.EvaluateDatasources, "evaluate-datasources", false, "evaluate datasources for validation (HCL2 only, may incur costs)")
+
+ va.MetaArgs.AddFlagSets(flags)
+}
+
+// ValidateArgs represents a parsed cli line for a `packer validate`
+type ValidateArgs struct {
+ MetaArgs
+ SyntaxOnly, NoWarnUndeclaredVar bool
+ EvaluateDatasources bool
+}
+
+func (va *InspectArgs) AddFlagSets(flags *flag.FlagSet) {
+ va.MetaArgs.AddFlagSets(flags)
+}
+
+// InspectArgs represents a parsed cli line for a `packer inspect`
+type InspectArgs struct {
+ MetaArgs
+}
+
+func (va *HCL2UpgradeArgs) AddFlagSets(flags *flag.FlagSet) {
+ flags.StringVar(&va.OutputFile, "output-file", "", "File where to put the hcl2 generated config. Defaults to JSON_TEMPLATE.pkr.hcl")
+ flags.BoolVar(&va.WithAnnotations, "with-annotations", false, "Adds helper annotations with information about the generated HCL2 blocks.")
+
+ va.MetaArgs.AddFlagSets(flags)
+}
+
+// HCL2UpgradeArgs represents a parsed cli line for a `packer hcl2_upgrade`
+type HCL2UpgradeArgs struct {
+ MetaArgs
+ OutputFile string
+ WithAnnotations bool
+}
+
+func (va *FormatArgs) AddFlagSets(flags *flag.FlagSet) {
+ flags.BoolVar(&va.Check, "check", false, "check if the input is formatted")
+ flags.BoolVar(&va.Diff, "diff", false, "display the diff of formatting changes")
+ flags.BoolVar(&va.Write, "write", true, "overwrite source files instead of writing to stdout")
+ flags.BoolVar(&va.Recursive, "recursive", false, "Also process files in subdirectories")
+ va.MetaArgs.AddFlagSets(flags)
+}
+
+// FormatArgs represents a parsed cli line for `packer fmt`
+type FormatArgs struct {
+ MetaArgs
+ Check, Diff, Write, Recursive bool
+}
diff --git a/v1.9.4/command/command_test.go b/v1.9.4/command/command_test.go
new file mode 100644
index 0000000..4666a41
--- /dev/null
+++ b/v1.9.4/command/command_test.go
@@ -0,0 +1,53 @@
+// Copyright (c) HashiCorp, Inc.
+// SPDX-License-Identifier: MPL-2.0
+
+package command
+
+import (
+ "bytes"
+ "io/ioutil"
+ "path/filepath"
+ "testing"
+
+ packersdk "github.com/hashicorp/packer-plugin-sdk/packer"
+ "github.com/hashicorp/packer/packer"
+)
+
+const fixturesDir = "./test-fixtures"
+
+func fatalCommand(t *testing.T, m Meta) {
+ ui := m.Ui.(*packersdk.BasicUi)
+ out := ui.Writer.(*bytes.Buffer)
+ err := ui.ErrorWriter.(*bytes.Buffer)
+ t.Fatalf(
+ "Bad exit code.\n\nStdout:\n\n%s\n\nStderr:\n\n%s",
+ out.String(),
+ err.String())
+}
+
+func testFixtureContent(n ...string) string {
+ path := filepath.Join(append([]string{fixturesDir}, n...)...)
+ b, err := ioutil.ReadFile(path)
+ if err != nil {
+ panic(err)
+ }
+ return string(b)
+}
+
+func testFixture(n ...string) string {
+ paths := []string{fixturesDir}
+ paths = append(paths, n...)
+ return filepath.Join(paths...)
+}
+
+func testMeta(t *testing.T) Meta {
+ var out, err bytes.Buffer
+
+ return Meta{
+ CoreConfig: packer.TestCoreConfig(t),
+ Ui: &packersdk.BasicUi{
+ Writer: &out,
+ ErrorWriter: &err,
+ },
+ }
+}
diff --git a/v1.9.4/command/config_file_unix.go b/v1.9.4/command/config_file_unix.go
new file mode 100644
index 0000000..31a8db0
--- /dev/null
+++ b/v1.9.4/command/config_file_unix.go
@@ -0,0 +1,11 @@
+// Copyright (c) HashiCorp, Inc.
+// SPDX-License-Identifier: MPL-2.0
+
+//go:build darwin || freebsd || linux || netbsd || openbsd || solaris
+// +build darwin freebsd linux netbsd openbsd solaris
+
+package command
+
+const (
+ defaultConfigDir = ".packer.d"
+)
diff --git a/v1.9.4/command/config_file_windows.go b/v1.9.4/command/config_file_windows.go
new file mode 100644
index 0000000..52cdf42
--- /dev/null
+++ b/v1.9.4/command/config_file_windows.go
@@ -0,0 +1,11 @@
+// Copyright (c) HashiCorp, Inc.
+// SPDX-License-Identifier: MPL-2.0
+
+//go:build windows
+// +build windows
+
+package command
+
+const (
+ defaultConfigDir = "packer.d"
+)
diff --git a/v1.9.4/command/configtype_enumer.go b/v1.9.4/command/configtype_enumer.go
new file mode 100644
index 0000000..c7a5cf5
--- /dev/null
+++ b/v1.9.4/command/configtype_enumer.go
@@ -0,0 +1,49 @@
+// Code generated by "enumer -type configType -trimprefix ConfigType -transform snake"; DO NOT EDIT.
+
+package command
+
+import (
+ "fmt"
+)
+
+const _configTypeName = "jsonhcl2"
+
+var _configTypeIndex = [...]uint8{0, 4, 8}
+
+func (i configType) String() string {
+ if i < 0 || i >= configType(len(_configTypeIndex)-1) {
+ return fmt.Sprintf("configType(%d)", i)
+ }
+ return _configTypeName[_configTypeIndex[i]:_configTypeIndex[i+1]]
+}
+
+var _configTypeValues = []configType{0, 1}
+
+var _configTypeNameToValueMap = map[string]configType{
+ _configTypeName[0:4]: 0,
+ _configTypeName[4:8]: 1,
+}
+
+// configTypeString retrieves an enum value from the enum constants string name.
+// Throws an error if the param is not part of the enum.
+func configTypeString(s string) (configType, error) {
+ if val, ok := _configTypeNameToValueMap[s]; ok {
+ return val, nil
+ }
+ return 0, fmt.Errorf("%s does not belong to configType values", s)
+}
+
+// configTypeValues returns all values of the enum
+func configTypeValues() []configType {
+ return _configTypeValues
+}
+
+// IsAconfigType returns "true" if the value is listed in the enum definition. "false" otherwise
+func (i configType) IsAconfigType() bool {
+ for _, v := range _configTypeValues {
+ if i == v {
+ return true
+ }
+ }
+ return false
+}
diff --git a/v1.9.4/command/console.go b/v1.9.4/command/console.go
new file mode 100644
index 0000000..54281fd
--- /dev/null
+++ b/v1.9.4/command/console.go
@@ -0,0 +1,165 @@
+// Copyright (c) HashiCorp, Inc.
+// SPDX-License-Identifier: MPL-2.0
+
+package command
+
+import (
+ "bufio"
+ "context"
+ "fmt"
+ "io"
+ "strings"
+
+ "github.com/chzyer/readline"
+ "github.com/hashicorp/packer/helper/wrappedreadline"
+ "github.com/hashicorp/packer/helper/wrappedstreams"
+ "github.com/hashicorp/packer/packer"
+ "github.com/posener/complete"
+)
+
+var TiniestBuilder = strings.NewReader(`{
+ "builders": [
+ {
+ "type":"null",
+ "communicator": "none"
+ }
+ ]
+}`)
+
+type ConsoleCommand struct {
+ Meta
+}
+
+func (c *ConsoleCommand) Run(args []string) int {
+ ctx := context.Background()
+
+ cfg, ret := c.ParseArgs(args)
+ if ret != 0 {
+ return ret
+ }
+
+ return c.RunContext(ctx, cfg)
+}
+
+func (c *ConsoleCommand) ParseArgs(args []string) (*ConsoleArgs, int) {
+ var cfg ConsoleArgs
+ flags := c.Meta.FlagSet("console", FlagSetVars)
+ flags.Usage = func() { c.Ui.Say(c.Help()) }
+ cfg.AddFlagSets(flags)
+ if err := flags.Parse(args); err != nil {
+ return &cfg, 1
+ }
+
+ args = flags.Args()
+ if len(args) == 1 {
+ cfg.Path = args[0]
+ }
+ return &cfg, 0
+}
+
+func (c *ConsoleCommand) RunContext(ctx context.Context, cla *ConsoleArgs) int {
+ packerStarter, ret := c.GetConfig(&cla.MetaArgs)
+ if ret != 0 {
+ return ret
+ }
+
+ _ = packerStarter.Initialize(packer.InitializeOptions{})
+
+ // Determine if stdin is a pipe. If so, we evaluate directly.
+ if c.StdinPiped() {
+ return c.modePiped(packerStarter)
+ }
+
+ return c.modeInteractive(packerStarter)
+}
+
+func (*ConsoleCommand) Help() string {
+ helpText := `
+Usage: packer console [options] [TEMPLATE]
+
+ Creates a console for testing variable interpolation.
+ If a template is provided, this command will load the template and any
+ variables defined therein into its context to be referenced during
+ interpolation.
+
+Options:
+ -var 'key=value' Variable for templates, can be used multiple times.
+ -var-file=path JSON or HCL2 file containing user variables.
+ -config-type Set to 'hcl2' to run in HCL2 mode when no file is passed. Defaults to json.
+`
+
+ return strings.TrimSpace(helpText)
+}
+
+func (*ConsoleCommand) Synopsis() string {
+ return "creates a console for testing variable interpolation"
+}
+
+func (*ConsoleCommand) AutocompleteArgs() complete.Predictor {
+ return complete.PredictNothing
+}
+
+func (*ConsoleCommand) AutocompleteFlags() complete.Flags {
+ return complete.Flags{
+ "-var": complete.PredictNothing,
+ "-var-file": complete.PredictNothing,
+ }
+}
+
+func (c *ConsoleCommand) modePiped(cfg packer.Evaluator) int {
+ var lastResult string
+ scanner := bufio.NewScanner(wrappedstreams.Stdin())
+ ret := 0
+ for scanner.Scan() {
+ result, _, diags := cfg.EvaluateExpression(strings.TrimSpace(scanner.Text()))
+ if len(diags) > 0 {
+ ret = writeDiags(c.Ui, nil, diags)
+ }
+ // Store the last result
+ lastResult = result
+ }
+
+ // Output the final result
+ c.Ui.Message(lastResult)
+ return ret
+}
+
+func (c *ConsoleCommand) modeInteractive(cfg packer.Evaluator) int {
+ // Setup the UI so we can output directly to stdout
+ l, err := readline.NewEx(wrappedreadline.Override(&readline.Config{
+ Prompt: "> ",
+ InterruptPrompt: "^C",
+ EOFPrompt: "exit",
+ HistorySearchFold: true,
+ }))
+ if err != nil {
+ c.Ui.Error(fmt.Sprintf(
+ "Error initializing console: %s",
+ err))
+ return 1
+ }
+ for {
+ // Read a line
+ line, err := l.Readline()
+ if err == readline.ErrInterrupt {
+ if len(line) == 0 {
+ break
+ } else {
+ continue
+ }
+ } else if err == io.EOF {
+ break
+ }
+ out, exit, diags := cfg.EvaluateExpression(line)
+ ret := writeDiags(c.Ui, nil, diags)
+ if exit {
+ return ret
+ }
+ c.Ui.Say(out)
+ if exit {
+ return ret
+ }
+ }
+
+ return 0
+}
diff --git a/v1.9.4/command/console_test.go b/v1.9.4/command/console_test.go
new file mode 100644
index 0000000..b8c4989
--- /dev/null
+++ b/v1.9.4/command/console_test.go
@@ -0,0 +1,57 @@
+// Copyright (c) HashiCorp, Inc.
+// SPDX-License-Identifier: MPL-2.0
+
+package command
+
+import (
+ "fmt"
+ "os"
+ "path/filepath"
+ "strings"
+ "testing"
+
+ "github.com/hashicorp/packer/hcl2template"
+ "github.com/hashicorp/packer/packer"
+ "github.com/stretchr/testify/assert"
+)
+
+func Test_console(t *testing.T) {
+ cwd, err := os.Getwd()
+ if err != nil {
+ t.Fatalf("Getwd: %v", err)
+ }
+
+ tc := []struct {
+ piped string
+ command []string
+ env []string
+ expected string
+ }{
+ {"help", []string{"console"}, nil, packer.ConsoleHelp + "\n"},
+ {"help", []string{"console", "--config-type=hcl2"}, nil, hcl2template.PackerConsoleHelp + "\n"},
+ {"var.fruit", []string{"console", filepath.Join(testFixture("var-arg"), "fruit_builder.pkr.hcl")}, []string{"PKR_VAR_fruit=potato"}, "potato\n"},
+ {"upper(var.fruit)", []string{"console", filepath.Join(testFixture("var-arg"), "fruit_builder.pkr.hcl")}, []string{"PKR_VAR_fruit=potato"}, "POTATO\n"},
+ {"1 + 5", []string{"console", "--config-type=hcl2"}, nil, "6\n"},
+ {"var.images", []string{"console", filepath.Join(testFixture("var-arg"), "map.pkr.hcl")}, nil, "{\n" + ` "key" = "value"` + "\n}\n"},
+ {"path.cwd", []string{"console", filepath.Join(testFixture("var-arg"), "map.pkr.hcl")}, nil, strings.ReplaceAll(cwd, `\`, `/`) + "\n"},
+ {"path.root", []string{"console", filepath.Join(testFixture("var-arg"), "map.pkr.hcl")}, nil, strings.ReplaceAll(testFixture("var-arg"), `\`, `/`) + "\n"},
+ {"var.list_of_string[0]", []string{"console", `-var=list_of_string=["first"]`, filepath.Join(testFixture("hcl", "variables", "list_of_string"))}, nil, "first\n"},
+ {"var.untyped[2]", []string{"console", filepath.Join(testFixture("hcl", "variables", "untyped_var"))}, nil, "strings\n"},
+ {"var.untyped", []string{"console", `-var=untyped=just_a_string`, filepath.Join(testFixture("hcl", "variables", "untyped_var"))}, nil, "just_a_string\n"},
+ {"var.untyped", []string{"console", filepath.Join(testFixture("hcl", "variables", "untyped_var", "var.pkr.hcl"))}, nil, "<unknown>\n"},
+ {"var.untyped", []string{"console", filepath.Join(testFixture("hcl", "variables", "untyped_var", "var.pkr.hcl"))}, []string{"PKR_VAR_untyped=just_a_string"}, "just_a_string\n"},
+ }
+
+ for _, tc := range tc {
+ t.Run(fmt.Sprintf("echo %q | packer %s", tc.piped, tc.command), func(t *testing.T) {
+ p := helperCommand(t, tc.command...)
+ p.Stdin = strings.NewReader(tc.piped)
+ p.Env = append(p.Env, tc.env...)
+ bs, err := p.Output()
+ if err != nil {
+ t.Fatalf("%v: %s", err, bs)
+ }
+ assert.Equal(t, tc.expected, string(bs))
+ })
+ }
+}
diff --git a/v1.9.4/command/enumflag/flag.go b/v1.9.4/command/enumflag/flag.go
new file mode 100644
index 0000000..cbb5876
--- /dev/null
+++ b/v1.9.4/command/enumflag/flag.go
@@ -0,0 +1,31 @@
+// Copyright (c) HashiCorp, Inc.
+// SPDX-License-Identifier: MPL-2.0
+
+package enumflag
+
+import "fmt"
+
+type enumFlag struct {
+ target *string
+ options []string
+}
+
+// New returns a flag.Value implementation for parsing flags with a one-of-a-set value
+func New(target *string, options ...string) *enumFlag {
+ return &enumFlag{target: target, options: options}
+}
+
+func (f *enumFlag) String() string {
+ return *f.target
+}
+
+func (f *enumFlag) Set(value string) error {
+ for _, v := range f.options {
+ if v == value {
+ *f.target = value
+ return nil
+ }
+ }
+
+ return fmt.Errorf("expected one of %q", f.options)
+}
diff --git a/v1.9.4/command/exec_test.go b/v1.9.4/command/exec_test.go
new file mode 100644
index 0000000..cfdbda6
--- /dev/null
+++ b/v1.9.4/command/exec_test.go
@@ -0,0 +1,140 @@
+// Copyright (c) HashiCorp, Inc.
+// SPDX-License-Identifier: MPL-2.0
+
+package command
+
+import (
+ "context"
+ "fmt"
+ "os"
+ "os/exec"
+ "runtime"
+ "testing"
+
+ "github.com/hashicorp/packer-plugin-amazon/builder/ebs"
+ packersdk "github.com/hashicorp/packer-plugin-sdk/packer"
+ "github.com/hashicorp/packer/builder/file"
+ "github.com/hashicorp/packer/builder/null"
+ "github.com/hashicorp/packer/packer"
+ "github.com/hashicorp/packer/post-processor/manifest"
+ shell_local_pp "github.com/hashicorp/packer/post-processor/shell-local"
+ filep "github.com/hashicorp/packer/provisioner/file"
+ "github.com/hashicorp/packer/provisioner/shell"
+ shell_local "github.com/hashicorp/packer/provisioner/shell-local"
+ "github.com/hashicorp/packer/version"
+)
+
+// HasExec reports whether the current system can start new processes
+// using os.StartProcess or (more commonly) exec.Command.
+func HasExec() bool {
+ switch runtime.GOOS {
+ case "js":
+ return false
+ }
+ return true
+}
+
+// MustHaveExec checks that the current system can start new processes
+// using os.StartProcess or (more commonly) exec.Command.
+// If not, MustHaveExec calls t.Skip with an explanation.
+func MustHaveExec(t testing.TB) {
+ if !HasExec() {
+ t.Skipf("skipping test: cannot exec subprocess on %s/%s", runtime.GOOS, runtime.GOARCH)
+ }
+}
+
+func helperCommandContext(t *testing.T, ctx context.Context, s ...string) (cmd *exec.Cmd) {
+ MustHaveExec(t)
+
+ cs := []string{"-test.run=TestHelperProcess", "--"}
+ cs = append(cs, s...)
+ if ctx != nil {
+ cmd = exec.CommandContext(ctx, os.Args[0], cs...)
+ } else {
+ cmd = exec.Command(os.Args[0], cs...)
+ }
+ cmd.Env = append(os.Environ(), "GO_WANT_HELPER_PROCESS=1")
+ return cmd
+}
+
+func helperCommand(t *testing.T, s ...string) *exec.Cmd {
+ return helperCommandContext(t, nil, s...)
+}
+
+// TestHelperProcess isn't a real test. It's used as a helper process
+// for TestParameterRun.
+func TestHelperProcess(*testing.T) {
+ if os.Getenv("GO_WANT_HELPER_PROCESS") != "1" {
+ return
+ }
+ defer os.Exit(0)
+
+ args := os.Args
+ for len(args) > 0 {
+ if args[0] == "--" {
+ args = args[1:]
+ break
+ }
+ args = args[1:]
+ }
+ if len(args) == 0 {
+ fmt.Fprintf(os.Stderr, "No command\n")
+ os.Exit(2)
+ }
+
+ cmd, args := args[0], args[1:]
+ switch cmd {
+ case "console":
+ os.Exit((&ConsoleCommand{Meta: commandMeta()}).Run(args))
+ case "fmt":
+ os.Exit((&FormatCommand{Meta: commandMeta()}).Run(args))
+ case "inspect":
+ os.Exit((&InspectCommand{Meta: commandMeta()}).Run(args))
+ case "build":
+ os.Exit((&BuildCommand{Meta: commandMeta()}).Run(args))
+ case "hcl2_upgrade":
+ os.Exit((&HCL2UpgradeCommand{Meta: commandMeta()}).Run(args))
+ default:
+ fmt.Fprintf(os.Stderr, "Unknown command %q\n", cmd)
+ os.Exit(2)
+ }
+}
+
+func commandMeta() Meta {
+ basicUi := &packersdk.BasicUi{
+ Reader: os.Stdin,
+ Writer: os.Stdout,
+ ErrorWriter: os.Stdout,
+ }
+
+ CommandMeta := Meta{
+ CoreConfig: &packer.CoreConfig{
+ Components: getBareComponentFinder(),
+ Version: version.Version,
+ },
+ Ui: basicUi,
+ }
+ return CommandMeta
+}
+
+func getBareComponentFinder() packer.ComponentFinder {
+ return packer.ComponentFinder{
+ PluginConfig: &packer.PluginConfig{
+ Builders: packer.MapOfBuilder{
+ "file": func() (packersdk.Builder, error) { return &file.Builder{}, nil },
+ "null": func() (packersdk.Builder, error) { return &null.Builder{}, nil },
+ "amazon-ebs": func() (packersdk.Builder, error) { return &ebs.Builder{}, nil },
+ "azure-arm": func() (packersdk.Builder, error) { return &ebs.Builder{}, nil },
+ },
+ Provisioners: packer.MapOfProvisioner{
+ "shell-local": func() (packersdk.Provisioner, error) { return &shell_local.Provisioner{}, nil },
+ "shell": func() (packersdk.Provisioner, error) { return &shell.Provisioner{}, nil },
+ "file": func() (packersdk.Provisioner, error) { return &filep.Provisioner{}, nil },
+ },
+ PostProcessors: packer.MapOfPostProcessor{
+ "shell-local": func() (packersdk.PostProcessor, error) { return &shell_local_pp.PostProcessor{}, nil },
+ "manifest": func() (packersdk.PostProcessor, error) { return &manifest.PostProcessor{}, nil },
+ },
+ },
+ }
+}
diff --git a/v1.9.4/command/fix.go b/v1.9.4/command/fix.go
new file mode 100644
index 0000000..893c788
--- /dev/null
+++ b/v1.9.4/command/fix.go
@@ -0,0 +1,179 @@
+// Copyright (c) HashiCorp, Inc.
+// SPDX-License-Identifier: MPL-2.0
+
+package command
+
+import (
+ "bytes"
+ "context"
+ "encoding/json"
+ "fmt"
+ "log"
+ "os"
+ "strings"
+
+ "github.com/hashicorp/packer-plugin-sdk/template"
+ "github.com/hashicorp/packer/fix"
+
+ "github.com/posener/complete"
+)
+
+type FixCommand struct {
+ Meta
+}
+
+func (c *FixCommand) Run(args []string) int {
+ ctx, cleanup := handleTermInterrupt(c.Ui)
+ defer cleanup()
+
+ cfg, ret := c.ParseArgs(args)
+ if ret != 0 {
+ return ret
+ }
+
+ return c.RunContext(ctx, cfg)
+}
+
+func (c *FixCommand) ParseArgs(args []string) (*FixArgs, int) {
+ var cfg FixArgs
+ flags := c.Meta.FlagSet("fix", FlagSetNone)
+ flags.Usage = func() { c.Ui.Say(c.Help()) }
+ cfg.AddFlagSets(flags)
+ if err := flags.Parse(args); err != nil {
+ return &cfg, 1
+ }
+
+ args = flags.Args()
+ if len(args) != 1 {
+ flags.Usage()
+ return &cfg, 1
+ }
+ cfg.Path = args[0]
+ return &cfg, 0
+}
+
+func (c *FixCommand) RunContext(ctx context.Context, cla *FixArgs) int {
+ if hcl2, _ := isHCLLoaded(cla.Path); hcl2 {
+ c.Ui.Error("packer fix only works with JSON files for now.")
+ return 1
+ }
+ // Read the file for decoding
+ tplF, err := os.Open(cla.Path)
+ if err != nil {
+ c.Ui.Error(fmt.Sprintf("Error opening template: %s", err))
+ return 1
+ }
+ defer tplF.Close()
+
+ // Decode the JSON into a generic map structure
+ var templateData map[string]interface{}
+ decoder := json.NewDecoder(tplF)
+ if err := decoder.Decode(&templateData); err != nil {
+ c.Ui.Error(fmt.Sprintf("Error parsing template: %s", err))
+ return 1
+ }
+
+ // Close the file since we're done with that
+ tplF.Close()
+
+ input := templateData
+ for _, name := range fix.FixerOrder {
+ var err error
+ fixer, ok := fix.Fixers[name]
+ if !ok {
+ panic("fixer not found: " + name)
+ }
+
+ log.Printf("Running fixer: %s", name)
+ input, err = fixer.Fix(input)
+ if err != nil {
+ c.Ui.Error(fmt.Sprintf("Error fixing: %s", err))
+ return 1
+ }
+ }
+
+ var output bytes.Buffer
+ encoder := json.NewEncoder(&output)
+ if err := encoder.Encode(input); err != nil {
+ c.Ui.Error(fmt.Sprintf("Error encoding: %s", err))
+ return 1
+ }
+
+ var indented bytes.Buffer
+ if err := json.Indent(&indented, output.Bytes(), "", " "); err != nil {
+ c.Ui.Error(fmt.Sprintf("Error encoding: %s", err))
+ return 1
+ }
+
+ result := indented.String()
+ result = strings.Replace(result, `\u003c`, "<", -1)
+ result = strings.Replace(result, `\u003e`, ">", -1)
+ c.Ui.Say(result)
+
+ if cla.Validate == false {
+ return 0
+ }
+
+ // Attempt to parse and validate the template
+ tpl, err := template.Parse(strings.NewReader(result))
+ if err != nil {
+ c.Ui.Error(fmt.Sprintf(
+ "Error! Fixed template fails to parse: %s\n\n"+
+ "This is usually caused by an error in the input template.\n"+
+ "Please fix the error and try again.",
+ err))
+ return 1
+ }
+ if err := tpl.Validate(); err != nil {
+ c.Ui.Error(fmt.Sprintf(
+ "Error! Fixed template failed to validate: %s\n\n"+
+ "This is usually caused by an error in the input template.\n"+
+ "Please fix the error and try again.",
+ err))
+ return 1
+ }
+
+ return 0
+}
+
+func (*FixCommand) Help() string {
+ helpText := `
+Usage: packer fix [options] TEMPLATE
+
+ Reads the JSON template and attempts to fix known backwards
+ incompatibilities. The fixed template will be outputted to standard out.
+
+ If the template cannot be fixed due to an error, the command will exit
+ with a non-zero exit status. Error messages will appear on standard error.
+
+Fixes that are run (in order):
+
+`
+
+ for _, name := range fix.FixerOrder {
+ helpText += fmt.Sprintf(
+ " %-27s%s\n", name, fix.Fixers[name].Synopsis())
+ }
+
+ helpText += `
+Options:
+
+ -validate=true If true (default), validates the fixed template.
+`
+
+ return strings.TrimSpace(helpText)
+}
+
+func (c *FixCommand) Synopsis() string {
+ return "fixes templates from old versions of packer"
+}
+
+func (c *FixCommand) AutocompleteArgs() complete.Predictor {
+ return complete.PredictNothing
+}
+
+func (c *FixCommand) AutocompleteFlags() complete.Flags {
+ return complete.Flags{
+ "-validate": complete.PredictNothing,
+ }
+}
diff --git a/v1.9.4/command/fix_test.go b/v1.9.4/command/fix_test.go
new file mode 100644
index 0000000..d092a80
--- /dev/null
+++ b/v1.9.4/command/fix_test.go
@@ -0,0 +1,66 @@
+// Copyright (c) HashiCorp, Inc.
+// SPDX-License-Identifier: MPL-2.0
+
+package command
+
+import (
+ "path/filepath"
+ "strings"
+ "testing"
+
+ packersdk "github.com/hashicorp/packer-plugin-sdk/packer"
+ "github.com/stretchr/testify/assert"
+)
+
+func TestFix(t *testing.T) {
+ s := &strings.Builder{}
+ ui := &packersdk.BasicUi{
+ Writer: s,
+ }
+ c := &FixCommand{
+ Meta: testMeta(t),
+ }
+
+ c.Ui = ui
+
+ args := []string{filepath.Join(testFixture("fix"), "template.json")}
+ if code := c.Run(args); code != 0 {
+ fatalCommand(t, c.Meta)
+ }
+ expected := `{
+ "builders": [
+ {
+ "type": "dummy"
+ }
+ ],
+ "push": {
+ "name": "foo/bar"
+ }
+}`
+ assert.Equal(t, expected, strings.TrimSpace(s.String()))
+}
+
+func TestFix_invalidTemplate(t *testing.T) {
+ c := &FixCommand{
+ Meta: testMeta(t),
+ }
+
+ args := []string{filepath.Join(testFixture("fix-invalid"), "template.json")}
+ if code := c.Run(args); code != 1 {
+ fatalCommand(t, c.Meta)
+ }
+}
+
+func TestFix_invalidTemplateDisableValidation(t *testing.T) {
+ c := &FixCommand{
+ Meta: testMeta(t),
+ }
+
+ args := []string{
+ "-validate=false",
+ filepath.Join(testFixture("fix-invalid"), "template.json"),
+ }
+ if code := c.Run(args); code != 0 {
+ fatalCommand(t, c.Meta)
+ }
+}
diff --git a/v1.9.4/command/flag-kv/flag.go b/v1.9.4/command/flag-kv/flag.go
new file mode 100644
index 0000000..96cda31
--- /dev/null
+++ b/v1.9.4/command/flag-kv/flag.go
@@ -0,0 +1,32 @@
+// Copyright (c) HashiCorp, Inc.
+// SPDX-License-Identifier: MPL-2.0
+
+package kvflag
+
+import (
+ "fmt"
+ "strings"
+)
+
+// Flag is a flag.Value implementation for parsing user variables
+// from the command-line in the format of '-var key=value'.
+type Flag map[string]string
+
+func (v *Flag) String() string {
+ return ""
+}
+
+func (v *Flag) Set(raw string) error {
+ idx := strings.Index(raw, "=")
+ if idx == -1 {
+ return fmt.Errorf("No '=' value in arg: %s", raw)
+ }
+
+ if *v == nil {
+ *v = make(map[string]string)
+ }
+
+ key, value := raw[0:idx], raw[idx+1:]
+ (*v)[key] = value
+ return nil
+}
diff --git a/v1.9.4/command/flag-kv/flag_json.go b/v1.9.4/command/flag-kv/flag_json.go
new file mode 100644
index 0000000..25d34ef
--- /dev/null
+++ b/v1.9.4/command/flag-kv/flag_json.go
@@ -0,0 +1,37 @@
+// Copyright (c) HashiCorp, Inc.
+// SPDX-License-Identifier: MPL-2.0
+
+package kvflag
+
+import (
+ "encoding/json"
+ "fmt"
+ "os"
+)
+
+// FlagJSON is a flag.Value implementation for parsing user variables
+// from the command-line using JSON files.
+type FlagJSON map[string]string
+
+func (v *FlagJSON) String() string {
+ return ""
+}
+
+func (v *FlagJSON) Set(raw string) error {
+ f, err := os.Open(raw)
+ if err != nil {
+ return err
+ }
+ defer f.Close()
+
+ if *v == nil {
+ *v = make(map[string]string)
+ }
+
+ if err := json.NewDecoder(f).Decode(v); err != nil {
+ return fmt.Errorf(
+ "Error reading variables in '%s': %s", raw, err)
+ }
+
+ return nil
+}
diff --git a/v1.9.4/command/flag-kv/flag_json_test.go b/v1.9.4/command/flag-kv/flag_json_test.go
new file mode 100644
index 0000000..ab8a67e
--- /dev/null
+++ b/v1.9.4/command/flag-kv/flag_json_test.go
@@ -0,0 +1,62 @@
+// Copyright (c) HashiCorp, Inc.
+// SPDX-License-Identifier: MPL-2.0
+
+package kvflag
+
+import (
+ "flag"
+ "path/filepath"
+ "reflect"
+ "testing"
+)
+
+func TestFlagJSON_impl(t *testing.T) {
+ var _ flag.Value = new(FlagJSON)
+}
+
+func TestFlagJSON(t *testing.T) {
+ cases := []struct {
+ Input string
+ Initial map[string]string
+ Output map[string]string
+ Error bool
+ }{
+ {
+ "basic.json",
+ nil,
+ map[string]string{"key": "value"},
+ false,
+ },
+
+ {
+ "basic.json",
+ map[string]string{"foo": "bar"},
+ map[string]string{"foo": "bar", "key": "value"},
+ false,
+ },
+
+ {
+ "basic.json",
+ map[string]string{"key": "bar"},
+ map[string]string{"key": "value"},
+ false,
+ },
+ }
+
+ for _, tc := range cases {
+ f := new(FlagJSON)
+ if tc.Initial != nil {
+ f = (*FlagJSON)(&tc.Initial)
+ }
+
+ err := f.Set(filepath.Join("./test-fixtures", tc.Input))
+ if (err != nil) != tc.Error {
+ t.Fatalf("bad error. Input: %#v\n\n%s", tc.Input, err)
+ }
+
+ actual := map[string]string(*f)
+ if !reflect.DeepEqual(actual, tc.Output) {
+ t.Fatalf("bad: %#v", actual)
+ }
+ }
+}
diff --git a/v1.9.4/command/flag-kv/flag_strings.go b/v1.9.4/command/flag-kv/flag_strings.go
new file mode 100644
index 0000000..d639bde
--- /dev/null
+++ b/v1.9.4/command/flag-kv/flag_strings.go
@@ -0,0 +1,19 @@
+// Copyright (c) HashiCorp, Inc.
+// SPDX-License-Identifier: MPL-2.0
+
+package kvflag
+
+import (
+ "strings"
+)
+
+type StringSlice []string
+
+func (s *StringSlice) String() string {
+ return strings.Join(*s, ", ")
+}
+
+func (s *StringSlice) Set(value string) error {
+ *s = append(*s, value)
+ return nil
+}
diff --git a/v1.9.4/command/flag-kv/flag_strings_test.go b/v1.9.4/command/flag-kv/flag_strings_test.go
new file mode 100644
index 0000000..070e95c
--- /dev/null
+++ b/v1.9.4/command/flag-kv/flag_strings_test.go
@@ -0,0 +1,38 @@
+// Copyright (c) HashiCorp, Inc.
+// SPDX-License-Identifier: MPL-2.0
+
+package kvflag
+
+import (
+ "testing"
+
+ "github.com/google/go-cmp/cmp"
+)
+
+func TestStringSlice_Set(t *testing.T) {
+ type args struct {
+ values []string
+ }
+ tests := []struct {
+ name string
+ s StringSlice
+ args args
+ wantStringSlice StringSlice
+ }{
+ {"basic", StringSlice{"hey", "yo"}, args{[]string{"how", "are", "you"}},
+ StringSlice{"hey", "yo", "how", "are", "you"}},
+ }
+ for _, tt := range tests {
+ t.Run(tt.name, func(t *testing.T) {
+ for _, value := range tt.args.values {
+ err := tt.s.Set(value)
+ if err != nil {
+ t.Fatal(err)
+ }
+ }
+ if diff := cmp.Diff(tt.s, tt.wantStringSlice); diff != "" {
+ t.Fatal(diff)
+ }
+ })
+ }
+}
diff --git a/v1.9.4/command/flag-kv/flag_test.go b/v1.9.4/command/flag-kv/flag_test.go
new file mode 100644
index 0000000..2864411
--- /dev/null
+++ b/v1.9.4/command/flag-kv/flag_test.go
@@ -0,0 +1,59 @@
+// Copyright (c) HashiCorp, Inc.
+// SPDX-License-Identifier: MPL-2.0
+
+package kvflag
+
+import (
+ "flag"
+ "reflect"
+ "testing"
+)
+
+func TestFlag_impl(t *testing.T) {
+ var _ flag.Value = new(Flag)
+}
+
+func TestFlag(t *testing.T) {
+ cases := []struct {
+ Input string
+ Output map[string]string
+ Error bool
+ }{
+ {
+ "key=value",
+ map[string]string{"key": "value"},
+ false,
+ },
+
+ {
+ "key=",
+ map[string]string{"key": ""},
+ false,
+ },
+
+ {
+ "key=foo=bar",
+ map[string]string{"key": "foo=bar"},
+ false,
+ },
+
+ {
+ "key",
+ nil,
+ true,
+ },
+ }
+
+ for _, tc := range cases {
+ f := new(Flag)
+ err := f.Set(tc.Input)
+ if (err != nil) != tc.Error {
+ t.Fatalf("bad error. Input: %#v", tc.Input)
+ }
+
+ actual := map[string]string(*f)
+ if !reflect.DeepEqual(actual, tc.Output) {
+ t.Fatalf("bad: %#v", actual)
+ }
+ }
+}
diff --git a/v1.9.4/command/flag-kv/test-fixtures/basic.json b/v1.9.4/command/flag-kv/test-fixtures/basic.json
new file mode 100644
index 0000000..21da3b2
--- /dev/null
+++ b/v1.9.4/command/flag-kv/test-fixtures/basic.json
@@ -0,0 +1,3 @@
+{
+ "key": "value"
+}
diff --git a/v1.9.4/command/flag-slice/flag.go b/v1.9.4/command/flag-slice/flag.go
new file mode 100644
index 0000000..b75580e
--- /dev/null
+++ b/v1.9.4/command/flag-slice/flag.go
@@ -0,0 +1,19 @@
+// Copyright (c) HashiCorp, Inc.
+// SPDX-License-Identifier: MPL-2.0
+
+package sliceflag
+
+import "strings"
+
+// StringFlag implements the flag.Value interface and allows multiple
+// calls to the same variable to append a list.
+type StringFlag []string
+
+func (s *StringFlag) String() string {
+ return strings.Join(*s, ",")
+}
+
+func (s *StringFlag) Set(value string) error {
+ *s = append(*s, strings.Split(value, ",")...)
+ return nil
+}
diff --git a/v1.9.4/command/flag-slice/flag_test.go b/v1.9.4/command/flag-slice/flag_test.go
new file mode 100644
index 0000000..d70b270
--- /dev/null
+++ b/v1.9.4/command/flag-slice/flag_test.go
@@ -0,0 +1,53 @@
+// Copyright (c) HashiCorp, Inc.
+// SPDX-License-Identifier: MPL-2.0
+
+package sliceflag
+
+import (
+ "flag"
+ "reflect"
+ "testing"
+)
+
+func TestStringFlag_implements(t *testing.T) {
+ var raw interface{}
+ raw = new(StringFlag)
+ if _, ok := raw.(flag.Value); !ok {
+ t.Fatalf("StringFlag should be a Value")
+ }
+}
+
+// TestStringFlagSet tests for setting the same flag more than once on the CLI
+// like: blah -flag foo -flag bar
+func TestStringFlagSet(t *testing.T) {
+ sv := new(StringFlag)
+ err := sv.Set("foo")
+ if err != nil {
+ t.Fatalf("err: %s", err)
+ }
+
+ err = sv.Set("bar")
+ if err != nil {
+ t.Fatalf("err: %s", err)
+ }
+
+ expected := []string{"foo", "bar"}
+ if !reflect.DeepEqual([]string(*sv), expected) {
+ t.Fatalf("Bad: %#v", sv)
+ }
+}
+
+// TestMultiStringFlag tests for setting the same flag using a comma-separated
+// list of items like: blah -flag=foo,bar
+func TestMultiStringFlag(t *testing.T) {
+ sv := new(StringFlag)
+ err := sv.Set("chocolate,vanilla")
+ if err != nil {
+ t.Fatalf("err :%s", err)
+ }
+
+ expected := []string{"chocolate", "vanilla"}
+ if !reflect.DeepEqual([]string(*sv), expected) {
+ t.Fatalf("Expected: %#v, found: %#v", expected, sv)
+ }
+}
diff --git a/v1.9.4/command/fmt.go b/v1.9.4/command/fmt.go
new file mode 100644
index 0000000..9cfaa46
--- /dev/null
+++ b/v1.9.4/command/fmt.go
@@ -0,0 +1,119 @@
+// Copyright (c) HashiCorp, Inc.
+// SPDX-License-Identifier: MPL-2.0
+
+package command
+
+import (
+ "context"
+ "os"
+ "strings"
+
+ hclutils "github.com/hashicorp/packer/hcl2template"
+ "github.com/posener/complete"
+)
+
+type FormatCommand struct {
+ Meta
+}
+
+func (c *FormatCommand) Run(args []string) int {
+ ctx := context.Background()
+ cfg, ret := c.ParseArgs(args)
+ if ret != 0 {
+ return ret
+ }
+
+ return c.RunContext(ctx, cfg)
+}
+
+func (c *FormatCommand) ParseArgs(args []string) (*FormatArgs, int) {
+ var cfg FormatArgs
+ flags := c.Meta.FlagSet("format", FlagSetNone)
+ flags.Usage = func() { c.Ui.Say(c.Help()) }
+ cfg.AddFlagSets(flags)
+ if err := flags.Parse(args); err != nil {
+ return &cfg, 1
+ }
+
+ args = flags.Args()
+ if len(args) != 1 {
+ flags.Usage()
+ return &cfg, 1
+ }
+
+ cfg.Path = args[0]
+ return &cfg, 0
+}
+
+func (c *FormatCommand) RunContext(ctx context.Context, cla *FormatArgs) int {
+ if cla.Check {
+ cla.Write = false
+ }
+
+ formatter := hclutils.HCL2Formatter{
+ ShowDiff: cla.Diff,
+ Write: cla.Write,
+ Output: os.Stdout,
+ Recursive: cla.Recursive,
+ }
+
+ bytesModified, diags := formatter.Format(cla.Path)
+ ret := writeDiags(c.Ui, nil, diags)
+ if ret != 0 {
+ return ret
+ }
+
+ if cla.Check && bytesModified > 0 {
+ // exit code taken from `terraform fmt` command
+ return 3
+ }
+
+ return 0
+}
+
+func (*FormatCommand) Help() string {
+ helpText := `
+Usage: packer fmt [options] [TEMPLATE]
+
+ Rewrites all Packer configuration files to a canonical format. Both
+ configuration files (.pkr.hcl) and variable files (.pkrvars.hcl) are updated.
+ JSON files (.json) are not modified.
+
+ If TEMPLATE is "." the current directory will be used.
+ If TEMPLATE is "-" then content will be read from STDIN.
+
+ The given content must be in Packer's HCL2 configuration language; JSON is
+ not supported.
+
+Options:
+ -check Check if the input is formatted. Exit status will be 0 if all
+ input is properly formatted and non-zero otherwise.
+
+ -diff Display diffs of formatting change
+
+ -write=false Don't write to source files
+ (always disabled if using -check)
+
+ -recursive Also process files in subdirectories. By default, only the
+ given directory (or current directory) is processed.
+`
+
+ return strings.TrimSpace(helpText)
+}
+
+func (*FormatCommand) Synopsis() string {
+ return "Rewrites HCL2 config files to canonical format"
+}
+
+func (*FormatCommand) AutocompleteArgs() complete.Predictor {
+ return complete.PredictNothing
+}
+
+func (*FormatCommand) AutocompleteFlags() complete.Flags {
+ return complete.Flags{
+ "-check": complete.PredictNothing,
+ "-diff": complete.PredictNothing,
+ "-write": complete.PredictNothing,
+ "-recursive": complete.PredictNothing,
+ }
+}
diff --git a/v1.9.4/command/fmt_test.go b/v1.9.4/command/fmt_test.go
new file mode 100644
index 0000000..b642cde
--- /dev/null
+++ b/v1.9.4/command/fmt_test.go
@@ -0,0 +1,180 @@
+// Copyright (c) HashiCorp, Inc.
+// SPDX-License-Identifier: MPL-2.0
+
+package command
+
+import (
+ "bytes"
+ "fmt"
+ "io/ioutil"
+ "os"
+ "path/filepath"
+ "strings"
+ "testing"
+
+ "github.com/google/go-cmp/cmp"
+ packersdk "github.com/hashicorp/packer-plugin-sdk/packer"
+ "github.com/stretchr/testify/assert"
+)
+
+func TestFmt(t *testing.T) {
+ s := &strings.Builder{}
+ ui := &packersdk.BasicUi{
+ Writer: s,
+ }
+ c := &FormatCommand{
+ Meta: testMeta(t),
+ }
+
+ c.Ui = ui
+
+ args := []string{"-check=true", filepath.Join(testFixture("fmt"), "formatted.pkr.hcl")}
+ if code := c.Run(args); code != 0 {
+ fatalCommand(t, c.Meta)
+ }
+ expected := ""
+ assert.Equal(t, expected, strings.TrimSpace(s.String()))
+}
+
+func TestFmt_unformattedPKRVarsTemplate(t *testing.T) {
+ c := &FormatCommand{
+ Meta: testMeta(t),
+ }
+
+ args := []string{"-check=true", filepath.Join(testFixture("fmt"), "unformatted.pkrvars.hcl")}
+ if code := c.Run(args); code != 3 {
+ fatalCommand(t, c.Meta)
+ }
+}
+
+func TestFmt_unfomattedTemlateDirectory(t *testing.T) {
+ c := &FormatCommand{
+ Meta: testMeta(t),
+ }
+
+ args := []string{"-check=true", filepath.Join(testFixture("fmt"), "")}
+
+ if code := c.Run(args); code != 3 {
+ fatalCommand(t, c.Meta)
+ }
+}
+
+const (
+ unformattedHCL = `
+ami_filter_name ="amzn2-ami-hvm-*-x86_64-gp2"
+ami_filter_owners =[ "137112412989" ]
+
+`
+ formattedHCL = `
+ami_filter_name = "amzn2-ami-hvm-*-x86_64-gp2"
+ami_filter_owners = ["137112412989"]
+
+`
+)
+
+func TestFmt_Recursive(t *testing.T) {
+
+ tests := []struct {
+ name string
+ formatArgs []string // arguments passed to format
+ alreadyPresentContent map[string]string
+ fileCheck
+ }{
+ {
+ name: "nested formats recursively",
+ formatArgs: []string{"-recursive=true"},
+ alreadyPresentContent: map[string]string{
+ "foo/bar/baz.pkr.hcl": unformattedHCL,
+ "foo/bar/baz/woo.pkrvars.hcl": unformattedHCL,
+ "potato": unformattedHCL,
+ "foo/bar/potato": unformattedHCL,
+ "bar.pkr.hcl": unformattedHCL,
+ "-": unformattedHCL,
+ },
+ fileCheck: fileCheck{
+ expectedContent: map[string]string{
+ "foo/bar/baz.pkr.hcl": formattedHCL,
+ "foo/bar/baz/woo.pkrvars.hcl": formattedHCL,
+ "potato": unformattedHCL,
+ "foo/bar/potato": unformattedHCL,
+ "bar.pkr.hcl": formattedHCL,
+ "-": unformattedHCL,
+ }},
+ },
+ {
+ name: "nested no recursive format",
+ formatArgs: []string{},
+ alreadyPresentContent: map[string]string{
+ "foo/bar/baz.pkr.hcl": unformattedHCL,
+ "foo/bar/baz/woo.pkrvars.hcl": unformattedHCL,
+ "bar.pkr.hcl": unformattedHCL,
+ "-": unformattedHCL,
+ },
+ fileCheck: fileCheck{
+ expectedContent: map[string]string{
+ "foo/bar/baz.pkr.hcl": unformattedHCL,
+ "foo/bar/baz/woo.pkrvars.hcl": unformattedHCL,
+ "bar.pkr.hcl": formattedHCL,
+ "-": unformattedHCL,
+ }},
+ },
+ }
+
+ c := &FormatCommand{
+ Meta: testMeta(t),
+ }
+
+ testDir := "test-fixtures/fmt"
+
+ for _, tt := range tests {
+ t.Run(tt.name, func(t *testing.T) {
+ tempDirectory := mustString(ioutil.TempDir(testDir, "test-dir-*"))
+ defer os.RemoveAll(tempDirectory)
+
+ createFiles(tempDirectory, tt.alreadyPresentContent)
+
+ testArgs := append(tt.formatArgs, tempDirectory)
+ if code := c.Run(testArgs); code != 0 {
+ ui := c.Meta.Ui.(*packersdk.BasicUi)
+ out := ui.Writer.(*bytes.Buffer)
+ err := ui.ErrorWriter.(*bytes.Buffer)
+ t.Fatalf(
+ "Bad exit code for test case: %s.\n\nStdout:\n\n%s\n\nStderr:\n\n%s",
+ tt.name,
+ out.String(),
+ err.String())
+ }
+
+ tt.fileCheck.verify(t, tempDirectory)
+ })
+ }
+}
+
+func Test_fmt_pipe(t *testing.T) {
+
+ tc := []struct {
+ piped string
+ command []string
+ env []string
+ expected string
+ }{
+ {unformattedHCL, []string{"fmt", "-"}, nil, formattedHCL},
+ {formattedHCL, []string{"fmt", "-"}, nil, formattedHCL},
+ }
+
+ for _, tc := range tc {
+ t.Run(fmt.Sprintf("echo %q | packer %s", tc.piped, tc.command), func(t *testing.T) {
+ p := helperCommand(t, tc.command...)
+ p.Stdin = strings.NewReader(tc.piped)
+ p.Env = append(p.Env, tc.env...)
+ fmt.Println(fmt.Sprintf("Path: %s", p.Path))
+ bs, err := p.Output()
+ if err != nil {
+ t.Fatalf("Error occurred running command %v: %s", err, bs)
+ }
+ if diff := cmp.Diff(tc.expected, string(bs)); diff != "" {
+ t.Fatalf("Error in diff: %s", diff)
+ }
+ })
+ }
+}
diff --git a/v1.9.4/command/hcl2_upgrade.go b/v1.9.4/command/hcl2_upgrade.go
new file mode 100644
index 0000000..08b7d2a
--- /dev/null
+++ b/v1.9.4/command/hcl2_upgrade.go
@@ -0,0 +1,1414 @@
+// Copyright (c) HashiCorp, Inc.
+// SPDX-License-Identifier: MPL-2.0
+
+package command
+
+import (
+ "bytes"
+ "context"
+ "fmt"
+ "io"
+ "os"
+ "path/filepath"
+ "reflect"
+ "regexp"
+ "sort"
+ "strconv"
+ "strings"
+ texttemplate "text/template"
+ "text/template/parse"
+
+ "github.com/hashicorp/go-multierror"
+ "github.com/hashicorp/hcl/v2/hclwrite"
+ awscommon "github.com/hashicorp/packer-plugin-amazon/builder/common"
+ hcl2shim "github.com/hashicorp/packer-plugin-sdk/hcl2helper"
+ "github.com/hashicorp/packer-plugin-sdk/template"
+ "github.com/hashicorp/packer/packer"
+ "github.com/mitchellh/mapstructure"
+ "github.com/posener/complete"
+ "github.com/zclconf/go-cty/cty"
+)
+
+type HCL2UpgradeCommand struct {
+ Meta
+}
+
+func (c *HCL2UpgradeCommand) Run(args []string) int {
+ ctx, cleanup := handleTermInterrupt(c.Ui)
+ defer cleanup()
+
+ cfg, ret := c.ParseArgs(args)
+ if ret != 0 {
+ return ret
+ }
+
+ return c.RunContext(ctx, cfg)
+}
+
+func (c *HCL2UpgradeCommand) ParseArgs(args []string) (*HCL2UpgradeArgs, int) {
+ var cfg HCL2UpgradeArgs
+ flags := c.Meta.FlagSet("hcl2_upgrade", FlagSetNone)
+ flags.Usage = func() { c.Ui.Say(c.Help()) }
+ cfg.AddFlagSets(flags)
+ if err := flags.Parse(args); err != nil {
+ return &cfg, 1
+ }
+ args = flags.Args()
+ if len(args) != 1 {
+ flags.Usage()
+ return &cfg, 1
+ }
+ cfg.Path = args[0]
+ if cfg.OutputFile == "" {
+ cfg.OutputFile = cfg.Path + ".pkr.hcl"
+ }
+ return &cfg, 0
+}
+
+const (
+ hcl2UpgradeFileHeader = `# This file was autogenerated by the 'packer hcl2_upgrade' command. We
+# recommend double checking that everything is correct before going forward. We
+# also recommend treating this file as disposable. The HCL2 blocks in this
+# file can be moved to other files. For example, the variable blocks could be
+# moved to their own 'variables.pkr.hcl' file, etc. Those files need to be
+# suffixed with '.pkr.hcl' to be visible to Packer. To use multiple files at
+# once they also need to be in the same folder. 'packer inspect folder/'
+# will describe to you what is in that folder.
+
+# Avoid mixing go templating calls ( for example ` + "```{{ upper(`string`) }}```" + ` )
+# and HCL2 calls (for example '${ var.string_value_example }' ). They won't be
+# executed together and the outcome will be unknown.
+`
+ inputVarHeader = `
+# All generated input variables will be of 'string' type as this is how Packer JSON
+# views them; you can change their type later on. Read the variables type
+# constraints documentation
+# https://www.packer.io/docs/templates/hcl_templates/variables#type-constraints for more info.`
+ localsVarHeader = `
+# All locals variables are generated from variables that uses expressions
+# that are not allowed in HCL2 variables.
+# Read the documentation for locals blocks here:
+# https://www.packer.io/docs/templates/hcl_templates/blocks/locals`
+ packerBlockHeader = `
+# See https://www.packer.io/docs/templates/hcl_templates/blocks/packer for more info
+`
+
+ sourcesHeader = `
+# source blocks are generated from your builders; a source can be referenced in
+# build blocks. A build block runs provisioner and post-processors on a
+# source. Read the documentation for source blocks here:
+# https://www.packer.io/docs/templates/hcl_templates/blocks/source`
+
+ buildHeader = `
+# a build block invokes sources and runs provisioning steps on them. The
+# documentation for build blocks can be found here:
+# https://www.packer.io/docs/templates/hcl_templates/blocks/build
+`
+
+ amazonAmiDataHeader = `
+# The amazon-ami data block is generated from your amazon builder source_ami_filter; a data
+# from this block can be referenced in source and locals blocks.
+# Read the documentation for data blocks here:
+# https://www.packer.io/docs/templates/hcl_templates/blocks/data
+# Read the documentation for the Amazon AMI Data Source here:
+# https://www.packer.io/plugins/datasources/amazon/ami`
+
+ amazonSecretsManagerDataHeader = `
+# The amazon-secretsmanager data block is generated from your aws_secretsmanager template function; a data
+# from this block can be referenced in source and locals blocks.
+# Read the documentation for data blocks here:
+# https://www.packer.io/docs/templates/hcl_templates/blocks/data
+# Read the documentation for the Amazon Secrets Manager Data Source here:
+# https://www.packer.io/plugins/datasources/amazon/secretsmanager`
+)
+
+var (
+ amazonSecretsManagerMap = map[string]map[string]interface{}{}
+ localsVariableMap = map[string]string{}
+ timestamp = false
+ isotime = false
+ strftime = false
+)
+
+type BlockParser interface {
+ Parse(*template.Template) error
+ Write(*bytes.Buffer)
+}
+
+func (c *HCL2UpgradeCommand) RunContext(_ context.Context, cla *HCL2UpgradeArgs) int {
+ var output io.Writer
+ if err := os.MkdirAll(filepath.Dir(cla.OutputFile), 0755); err != nil {
+ c.Ui.Error(fmt.Sprintf("Failed to create output directory: %v", err))
+ return 1
+ }
+ if f, err := os.Create(cla.OutputFile); err == nil {
+ output = f
+ defer f.Close()
+ } else {
+ c.Ui.Error(fmt.Sprintf("Failed to create output file: %v", err))
+ return 1
+ }
+
+ if cla.WithAnnotations {
+ if _, err := output.Write([]byte(hcl2UpgradeFileHeader)); err != nil {
+ c.Ui.Error(fmt.Sprintf("Failed to write to file: %v", err))
+ return 1
+ }
+ }
+
+ hdl, ret := c.GetConfigFromJSON(&cla.MetaArgs)
+ if ret != 0 {
+ c.Ui.Error("Failed to get config from JSON")
+ return 1
+ }
+
+ core := hdl.(*packer.Core)
+ if err := core.Initialize(packer.InitializeOptions{}); err != nil {
+ c.Ui.Error(fmt.Sprintf("Ignoring following initialization error: %v", err))
+ }
+ tpl := core.Template
+
+ // Parse blocks
+
+ packerBlock := &PackerParser{
+ WithAnnotations: cla.WithAnnotations,
+ }
+ if err := packerBlock.Parse(tpl); err != nil {
+ c.Ui.Error(fmt.Sprintf("Ignoring following Parse error: %v", err))
+ ret = 1
+ }
+
+ variables := &VariableParser{
+ WithAnnotations: cla.WithAnnotations,
+ }
+ if err := variables.Parse(tpl); err != nil {
+ c.Ui.Error(fmt.Sprintf("Ignoring following variables.Parse error: %v", err))
+ ret = 1
+ }
+
+ locals := &LocalsParser{
+ LocalsOut: variables.localsOut,
+ WithAnnotations: cla.WithAnnotations,
+ }
+ if err := locals.Parse(tpl); err != nil {
+ c.Ui.Error(fmt.Sprintf("Ignoring following locals.Parse error: %v", err))
+ ret = 1
+ }
+
+ builders := []*template.Builder{}
+ {
+ // sort builders to avoid map's randomness
+ for _, builder := range tpl.Builders {
+ builders = append(builders, builder)
+ }
+ }
+ sort.Slice(builders, func(i, j int) bool {
+ return builders[i].Type+builders[i].Name < builders[j].Type+builders[j].Name
+ })
+
+ amazonAmiDatasource := &AmazonAmiDatasourceParser{
+ Builders: builders,
+ WithAnnotations: cla.WithAnnotations,
+ }
+ if err := amazonAmiDatasource.Parse(tpl); err != nil {
+ c.Ui.Error(fmt.Sprintf("Ignoring following amazonAmiDatasource.Parse error: %v", err))
+ ret = 1
+ }
+
+ sources := &SourceParser{
+ Builders: builders,
+ BuilderPlugins: c.Meta.CoreConfig.Components.PluginConfig.Builders,
+ WithAnnotations: cla.WithAnnotations,
+ }
+ if err := sources.Parse(tpl); err != nil {
+ c.Ui.Error(fmt.Sprintf("Ignoring following sources.Parse error: %v", err))
+ ret = 1
+ }
+
+ build := &BuildParser{
+ Builders: builders,
+ WithAnnotations: cla.WithAnnotations,
+ }
+ if err := build.Parse(tpl); err != nil {
+ c.Ui.Error(fmt.Sprintf("Ignoring following build.Parse error: %v", err))
+ ret = 1
+ }
+
+ amazonSecretsDatasource := &AmazonSecretsDatasourceParser{
+ WithAnnotations: cla.WithAnnotations,
+ }
+ if err := amazonSecretsDatasource.Parse(tpl); err != nil {
+ c.Ui.Error(fmt.Sprintf("Ignoring following amazonSecretsDatasource.Parse error: %v", err))
+ ret = 1
+ }
+
+ // Write file
+ out := &bytes.Buffer{}
+ for _, block := range []BlockParser{
+ packerBlock,
+ variables,
+ amazonSecretsDatasource,
+ amazonAmiDatasource,
+ locals,
+ sources,
+ build,
+ } {
+ block.Write(out)
+ }
+
+ if _, err := output.Write(hclwrite.Format(out.Bytes())); err != nil {
+ c.Ui.Error(fmt.Sprintf("Failed to write to file: %v", err))
+ return 1
+ }
+
+ c.Ui.Say(fmt.Sprintf("Successfully created %s. Exit %d", cla.OutputFile, ret))
+ return ret
+}
+
+type UnhandleableArgumentError struct {
+ Call string
+ Correspondance string
+ Docs string
+}
+
+func (uc UnhandleableArgumentError) Error() string {
+ return fmt.Sprintf(`unhandled %q call:
+# there is no way to automatically upgrade the %[1]q call.
+# Please manually upgrade to %s
+# Visit %s for more infos.`, uc.Call, uc.Correspondance, uc.Docs)
+}
+
+func fallbackReturn(err error, s []byte) []byte {
+ if strings.Contains(err.Error(), "unhandled") {
+ return append([]byte(fmt.Sprintf("\n# %s\n", err)), s...)
+ }
+
+ return append([]byte(fmt.Sprintf("\n# could not parse template for following block: %q\n", err)), s...)
+}
+
+// reTemplate writes a new template to `out` and escapes all unknown variables
+// so that we don't interpret them later on when interpreting the template
+func reTemplate(nd parse.Node, out io.Writer, funcs texttemplate.FuncMap) error {
+ switch node := nd.(type) {
+ case *parse.ActionNode:
+ // Leave pipes as-is
+ if len(node.Pipe.Cmds) > 1 {
+ fmt.Fprintf(out, "%s", node.String())
+ return nil
+ }
+
+ cmd := node.Pipe.Cmds[0]
+ args := cmd.Args
+ if len(args) > 1 {
+ // Function calls with parameters are left aside
+ fmt.Fprintf(out, "%s", node.String())
+ return nil
+ }
+
+ _, ok := funcs[args[0].String()]
+ if ok {
+ // Known functions left as-is
+ fmt.Fprintf(out, "%s", node.String())
+ return nil
+ }
+
+ // Escape anything that isn't in the func map
+ fmt.Fprintf(out, "{{ \"{{\" }} %s {{ \"}}\" }}", cmd.String())
+
+ // TODO maybe node.Pipe.Decls? Though in Packer templates they're not
+ // supported officially so they can be left aside for now
+ case *parse.ListNode:
+ for _, child := range node.Nodes {
+ err := reTemplate(child, out, funcs)
+ if err != nil {
+ return err
+ }
+ }
+ case *parse.TextNode:
+ _, err := fmt.Fprintf(out, "%s", node.Text)
+ if err != nil {
+ return err
+ }
+ default:
+ return fmt.Errorf("unhandled node type %s", reflect.TypeOf(nd))
+ }
+ return nil
+}
+
+// transposeTemplatingCalls executes parts of blocks as go template files and replaces
+// their result with their hcl2 variant. If something goes wrong the template
+// containing the go template string is returned.
+func transposeTemplatingCalls(s []byte) []byte {
+ funcErrors := &multierror.Error{
+ ErrorFormat: func(es []error) string {
+ if len(es) == 1 {
+ return fmt.Sprintf("# 1 error occurred upgrading the following block:\n\t# %s\n", es[0])
+ }
+
+ points := make([]string, len(es))
+ for i, err := range es {
+ if i == len(es)-1 {
+ points[i] = fmt.Sprintf("# %s", err)
+ continue
+ }
+ points[i] = fmt.Sprintf("# %s\n", err)
+ }
+
+ return fmt.Sprintf(
+ "# %d errors occurred upgrading the following block:\n\t%s",
+ len(es), strings.Join(points, "\n\t"))
+ },
+ }
+
+ funcMap := texttemplate.FuncMap{
+ "aws_secretsmanager": func(a ...string) string {
+ if len(a) == 2 {
+ for key, config := range amazonSecretsManagerMap {
+ nameOk := config["name"] == a[0]
+ keyOk := config["key"] == a[1]
+ if nameOk && keyOk {
+ return fmt.Sprintf("${data.amazon-secretsmanager.%s.value}", key)
+ }
+ }
+ id := fmt.Sprintf("autogenerated_%d", len(amazonSecretsManagerMap)+1)
+ amazonSecretsManagerMap[id] = map[string]interface{}{
+ "name": a[0],
+ "key": a[1],
+ }
+ return fmt.Sprintf("${data.amazon-secretsmanager.%s.value}", id)
+ }
+ for key, config := range amazonSecretsManagerMap {
+ nameOk := config["name"] == a[0]
+ if nameOk {
+ return fmt.Sprintf("${data.amazon-secretsmanager.%s.value}", key)
+ }
+ }
+ id := fmt.Sprintf("autogenerated_%d", len(amazonSecretsManagerMap)+1)
+ amazonSecretsManagerMap[id] = map[string]interface{}{
+ "name": a[0],
+ }
+ return fmt.Sprintf("${data.amazon-secretsmanager.%s.value}", id)
+ },
+ "timestamp": func() string {
+ timestamp = true
+ return "${local.timestamp}"
+ },
+ "isotime": func(a ...string) string {
+ if len(a) == 0 {
+ // returns rfc3339 formatted string.
+ return "${timestamp()}"
+ }
+ // otherwise a valid isotime func has one input.
+ isotime = true
+ return fmt.Sprintf("${legacy_isotime(\"%s\")}", a[0])
+
+ },
+ "strftime": func(a ...string) string {
+ if len(a) == 0 {
+ // returns rfc3339 formatted string.
+ return "${timestamp()}"
+ }
+ strftime = true
+ return fmt.Sprintf("${legacy_strftime(\"%s\")}", a[0])
+ },
+ "user": func(in string) string {
+ if _, ok := localsVariableMap[in]; ok {
+ // variable is now a local
+ return fmt.Sprintf("${local.%s}", in)
+ }
+ return fmt.Sprintf("${var.%s}", in)
+ },
+ "env": func(in string) string {
+ return fmt.Sprintf("${env(%q)}", in)
+ },
+ "build": func(a string) string {
+ return fmt.Sprintf("${build.%s}", a)
+ },
+ "data": func(a string) string {
+ return fmt.Sprintf("${data.%s}", a)
+ },
+ "template_dir": func() string {
+ return "${path.root}"
+ },
+ "pwd": func() string {
+ return "${path.cwd}"
+ },
+ "packer_version": func() string {
+ return "${packer.version}"
+ },
+ "uuid": func() string {
+ return "${uuidv4()}"
+ },
+ "lower": func(a string) (string, error) {
+ funcErrors = multierror.Append(funcErrors, UnhandleableArgumentError{
+ "lower",
+ "`lower(var.example)`",
+ "https://www.packer.io/docs/templates/hcl_templates/functions/string/lower",
+ })
+ return fmt.Sprintf("{{ lower `%s` }}", a), nil
+ },
+ "upper": func(a string) (string, error) {
+ funcErrors = multierror.Append(funcErrors, UnhandleableArgumentError{
+ "upper",
+ "`upper(var.example)`",
+ "https://www.packer.io/docs/templates/hcl_templates/functions/string/upper",
+ })
+ return fmt.Sprintf("{{ upper `%s` }}", a), nil
+ },
+ "split": func(a, b string, n int) (string, error) {
+ funcErrors = multierror.Append(funcErrors, UnhandleableArgumentError{
+ "split",
+ "`split(separator, string)`",
+ "https://www.packer.io/docs/templates/hcl_templates/functions/string/split",
+ })
+ return fmt.Sprintf("{{ split `%s` `%s` %d }}", a, b, n), nil
+ },
+ "replace": func(a, b string, n int, c string) (string, error) {
+ funcErrors = multierror.Append(funcErrors, UnhandleableArgumentError{
+ "replace",
+ "`replace(string, substring, replacement)` or `regex_replace(string, substring, replacement)`",
+ "https://www.packer.io/docs/templates/hcl_templates/functions/string/replace or https://www.packer.io/docs/templates/hcl_templates/functions/string/regex_replace",
+ })
+ return fmt.Sprintf("{{ replace `%s` `%s` `%s` %d }}", a, b, c, n), nil
+ },
+ "replace_all": func(a, b, c string) (string, error) {
+ funcErrors = multierror.Append(funcErrors, UnhandleableArgumentError{
+ "replace_all",
+ "`replace(string, substring, replacement)` or `regex_replace(string, substring, replacement)`",
+ "https://www.packer.io/docs/templates/hcl_templates/functions/string/replace or https://www.packer.io/docs/templates/hcl_templates/functions/string/regex_replace",
+ })
+ return fmt.Sprintf("{{ replace_all `%s` `%s` `%s` }}", a, b, c), nil
+ },
+ "clean_resource_name": func(a string) (string, error) {
+ funcErrors = multierror.Append(funcErrors, UnhandleableArgumentError{
+ "clean_resource_name",
+ "use custom validation rules, `replace(string, substring, replacement)` or `regex_replace(string, substring, replacement)`",
+ "https://packer.io/docs/templates/hcl_templates/variables#custom-validation-rules" +
+ " , https://www.packer.io/docs/templates/hcl_templates/functions/string/replace" +
+ " or https://www.packer.io/docs/templates/hcl_templates/functions/string/regex_replace",
+ })
+ return fmt.Sprintf("{{ clean_resource_name `%s` }}", a), nil
+ },
+ "build_name": func() string {
+ return "${build.name}"
+ },
+ "build_type": func() string {
+ return "${build.type}"
+ },
+ }
+
+ tpl, err := texttemplate.New("hcl2_upgrade").
+ Funcs(funcMap).
+ Parse(string(s))
+
+ if err != nil {
+ if strings.Contains(err.Error(), "unexpected \"\\\\\" in operand") {
+ // This error occurs if the operand in the text template used
+ // escaped quoting \" instead of bactick quoting `
+ // Create a regex to do a string replace on this block, to fix
+ // quoting.
+ q := fixQuoting(string(s))
+ unquoted := []byte(q)
+ tpl, err = texttemplate.New("hcl2_upgrade").
+ Funcs(funcMap).
+ Parse(string(unquoted))
+ if err != nil {
+ return fallbackReturn(err, unquoted)
+ }
+ } else {
+ return fallbackReturn(err, s)
+ }
+ }
+
+ retempl := &bytes.Buffer{}
+ if err := reTemplate(tpl.Root, retempl, funcMap); err != nil {
+ return fallbackReturn(err, s)
+ }
+
+ tpl, err = texttemplate.New("hcl2_upgrade").
+ Funcs(funcMap).
+ Parse(retempl.String())
+
+ str := &bytes.Buffer{}
+
+ if err := tpl.Execute(str, nil); err != nil {
+ return fallbackReturn(err, s)
+ }
+
+ out := str.Bytes()
+
+ if funcErrors.Len() > 0 {
+ return append([]byte(fmt.Sprintf("\n%s", funcErrors)), out...)
+ }
+ return out
+}
+
+// variableTransposeTemplatingCalls executes parts of blocks as go template files and replaces
+// their result with their hcl2 variant for variables block only. If something goes wrong the template
+// containing the go template string is returned.
+// In variableTransposeTemplatingCalls the definition of aws_secretsmanager function will create a data source
+// with the same name as the variable.
+func variableTransposeTemplatingCalls(s []byte) (isLocal bool, body []byte) {
+ setIsLocal := func(a ...string) string {
+ isLocal = true
+ return ""
+ }
+
+ // Make locals from variables using valid template engine,
+ // expect the ones using only 'env'
+ // ref: https://www.packer.io/docs/templates/legacy_json_templates/engine#template-engine
+ funcMap := texttemplate.FuncMap{
+ "aws_secretsmanager": setIsLocal,
+ "timestamp": setIsLocal,
+ "isotime": setIsLocal,
+ "strftime": setIsLocal,
+ "user": setIsLocal,
+ "env": func(in string) string {
+ return fmt.Sprintf("${env(%q)}", in)
+ },
+ "template_dir": setIsLocal,
+ "pwd": setIsLocal,
+ "packer_version": setIsLocal,
+ "uuid": setIsLocal,
+ "lower": setIsLocal,
+ "upper": setIsLocal,
+ "split": func(_, _ string, _ int) (string, error) {
+ isLocal = true
+ return "", nil
+ },
+ "replace": func(_, _ string, _ int, _ string) (string, error) {
+ isLocal = true
+ return "", nil
+ },
+ "replace_all": func(_, _, _ string) (string, error) {
+ isLocal = true
+ return "", nil
+ },
+ }
+
+ tpl, err := texttemplate.New("hcl2_upgrade").
+ Funcs(funcMap).
+ Parse(string(s))
+
+ if err != nil {
+ if strings.Contains(err.Error(), "unexpected \"\\\\\" in operand") {
+ // This error occurs if the operand in the text template used
+ // escaped quoting \" instead of bactick quoting `
+ // Create a regex to do a string replace on this block, to fix
+ // quoting.
+ q := fixQuoting(string(s))
+ unquoted := []byte(q)
+ tpl, err = texttemplate.New("hcl2_upgrade").
+ Funcs(funcMap).
+ Parse(string(unquoted))
+ if err != nil {
+ return isLocal, fallbackReturn(err, unquoted)
+ }
+ } else {
+ return isLocal, fallbackReturn(err, s)
+ }
+ }
+
+ retempl := &bytes.Buffer{}
+ if err := reTemplate(tpl.Root, retempl, funcMap); err != nil {
+ return isLocal, fallbackReturn(err, s)
+ }
+
+ tpl, err = texttemplate.New("hcl2_upgrade").
+ Funcs(funcMap).
+ Parse(retempl.String())
+
+ str := &bytes.Buffer{}
+ if err := tpl.Execute(str, nil); err != nil {
+ return isLocal, fallbackReturn(err, s)
+ }
+
+ return isLocal, str.Bytes()
+}
+
+// referencedUserVariables executes parts of blocks as go template files finding user variables referenced
+// within the template. This function should be called once to extract those variables referenced via the {{user `...`}}
+// template function. The resulting map will contain variables defined in the JSON variables property, and some that
+// are declared via var-files; to avoid duplicates the results of this function should be reconciled against tpl.Variables.
+func referencedUserVariables(s []byte) map[string]*template.Variable {
+ userVars := make([]string, 0)
+ funcMap := texttemplate.FuncMap{
+ "user": func(in string) string {
+ userVars = append(userVars, in)
+ return ""
+ },
+ }
+
+ tpl, err := texttemplate.New("hcl2_upgrade").
+ Funcs(funcMap).
+ Parse(string(s))
+ if err != nil {
+ return nil
+ }
+
+ if err := tpl.Execute(&bytes.Buffer{}, nil); err != nil {
+ return nil
+ }
+
+ vars := make(map[string]*template.Variable)
+ for _, v := range userVars {
+ vars[v] = &template.Variable{
+ Key: v,
+ Required: true,
+ }
+ }
+ return vars
+}
+
+func jsonBodyToHCL2Body(out *hclwrite.Body, kvs map[string]interface{}) {
+ ks := []string{}
+ for k := range kvs {
+ ks = append(ks, k)
+ }
+ sort.Strings(ks)
+
+ for _, k := range ks {
+ value := kvs[k]
+
+ switch value := value.(type) {
+ case map[string]interface{}:
+ var mostComplexElem interface{}
+ for _, randomElem := range value {
+ if k == "linux_options" || k == "network_interface" || k == "shared_image_gallery" {
+ break
+ }
+ // HACK: we take the most complex element of that map because
+ // in HCL2, map of objects can be bodies, for example:
+ // map containing object: source_ami_filter {} ( body )
+ // simple string/string map: tags = {} ) ( attribute )
+ //
+ // if we could not find an object in this map then it's most
+ // likely a plain map and so we guess it should be and
+ // attribute. Though now if value refers to something that is
+ // an object but only contains a string or a bool; we could
+ // generate a faulty object. For example a (somewhat invalid)
+ // source_ami_filter where only `most_recent` is set.
+ switch randomElem.(type) {
+ case string, int, float64, bool:
+ if mostComplexElem != nil {
+ continue
+ }
+ mostComplexElem = randomElem
+ default:
+ mostComplexElem = randomElem
+ }
+ }
+
+ switch mostComplexElem.(type) {
+ case string, int, float64, bool:
+ out.SetAttributeValue(k, hcl2shim.HCL2ValueFromConfigValue(value))
+ default:
+ nestedBlockBody := out.AppendNewBlock(k, nil).Body()
+ jsonBodyToHCL2Body(nestedBlockBody, value)
+ }
+ case map[string]string, map[string]int, map[string]float64:
+ out.SetAttributeValue(k, hcl2shim.HCL2ValueFromConfigValue(value))
+ case []interface{}:
+ if len(value) == 0 {
+ continue
+ }
+
+ var mostComplexElem interface{}
+ for _, randomElem := range value {
+ // HACK: we take the most complex element of that slice because
+ // in hcl2 slices of plain types can be arrays, for example:
+ // simple string type: owners = ["0000000000"]
+ // object: launch_block_device_mappings {}
+ switch randomElem.(type) {
+ case string, int, float64, bool:
+ if mostComplexElem != nil {
+ continue
+ }
+ mostComplexElem = randomElem
+ default:
+ mostComplexElem = randomElem
+ }
+ }
+ switch mostComplexElem.(type) {
+ case map[string]interface{}:
+ // this is an object in a slice; so we unwrap it. We
+ // could try to remove any 's' suffix in the key, but
+ // this might not work everywhere.
+ for i := range value {
+ value := value[i].(map[string]interface{})
+ nestedBlockBody := out.AppendNewBlock(k, nil).Body()
+ jsonBodyToHCL2Body(nestedBlockBody, value)
+ }
+ continue
+ default:
+ out.SetAttributeValue(k, hcl2shim.HCL2ValueFromConfigValue(value))
+ }
+ default:
+ out.SetAttributeValue(k, hcl2shim.HCL2ValueFromConfigValue(value))
+ }
+ }
+}
+
+func isSensitiveVariable(key string, vars []*template.Variable) bool {
+ for _, v := range vars {
+ if v.Key == key {
+ return true
+ }
+ }
+ return false
+}
+
+func (*HCL2UpgradeCommand) Help() string {
+ helpText := `
+Usage: packer hcl2_upgrade [options] TEMPLATE
+
+ Will transform your JSON template into an HCL2 configuration.
+
+Options:
+
+ -output-file=path Set output file name. By default this will be the
+ TEMPLATE name with ".pkr.hcl" appended to it. To be a
+ valid Packer HCL template, it must have the suffix
+ ".pkr.hcl"
+ -with-annotations Add helper annotation comments to the file to help new
+ HCL2 users understand the template format.
+`
+
+ return strings.TrimSpace(helpText)
+}
+
+func (*HCL2UpgradeCommand) Synopsis() string {
+ return "transform a JSON template into an HCL2 configuration"
+}
+
+func (*HCL2UpgradeCommand) AutocompleteArgs() complete.Predictor {
+ return complete.PredictNothing
+}
+
+func (*HCL2UpgradeCommand) AutocompleteFlags() complete.Flags {
+ return complete.Flags{}
+}
+
+// Specific blocks parser responsible to parse and write the block
+
+type PackerParser struct {
+ WithAnnotations bool
+ out []byte
+}
+
+func (p *PackerParser) Parse(tpl *template.Template) error {
+ reqPlugins, err := p.generateRequiredPluginsBlock(tpl)
+ if err != nil {
+ return err
+ }
+
+ if tpl.MinVersion == "" && reqPlugins == nil {
+ return nil
+ }
+
+ fileContent := hclwrite.NewEmptyFile()
+ body := fileContent.Body()
+ packerBody := body.AppendNewBlock("packer", nil).Body()
+
+ if tpl.MinVersion != "" {
+ packerBody.SetAttributeValue("required_version", cty.StringVal(fmt.Sprintf(">= %s", tpl.MinVersion)))
+ }
+
+ if reqPlugins != nil {
+ packerBody.AppendBlock(reqPlugins)
+ }
+
+ p.out = fileContent.Bytes()
+
+ return nil
+}
+
+func gatherPluginsFromTemplate(tpl *template.Template) []string {
+ plugins := map[string]struct{}{}
+
+ for _, b := range tpl.Builders {
+ for prefix, plugin := range knownPluginPrefixes {
+ if strings.HasPrefix(b.Type, prefix) {
+ plugins[plugin] = struct{}{}
+ }
+ }
+ }
+
+ for _, p := range tpl.Provisioners {
+ for prefix, plugin := range knownPluginPrefixes {
+ if strings.HasPrefix(p.Type, prefix) {
+ plugins[plugin] = struct{}{}
+ }
+ }
+ }
+
+ for _, pps := range tpl.PostProcessors {
+ for _, pp := range pps {
+ for prefix, plugin := range knownPluginPrefixes {
+ if strings.HasPrefix(pp.Type, prefix) {
+ plugins[plugin] = struct{}{}
+ }
+ }
+ }
+ }
+
+ if len(plugins) == 0 {
+ return nil
+ }
+
+ retPlugins := make([]string, 0, len(plugins))
+ for plugin := range plugins {
+ retPlugins = append(retPlugins, plugin)
+ }
+
+ sort.Strings(retPlugins)
+
+ return retPlugins
+}
+
+func (p *PackerParser) generateRequiredPluginsBlock(tpl *template.Template) (*hclwrite.Block, error) {
+ plugins := gatherPluginsFromTemplate(tpl)
+ if len(plugins) == 0 {
+ return nil, nil
+ }
+
+ reqPlugins := hclwrite.NewBlock("required_plugins", nil)
+ for _, plugin := range plugins {
+ pluginBlock := cty.ObjectVal(map[string]cty.Value{
+ "source": cty.StringVal(plugin),
+ "version": cty.StringVal("~> 1"),
+ })
+ reqPlugins.Body().SetAttributeValue(strings.Replace(plugin, "github.com/hashicorp/", "", 1), pluginBlock)
+ }
+
+ return reqPlugins, nil
+}
+
+func (p *PackerParser) Write(out *bytes.Buffer) {
+ if len(p.out) > 0 {
+ if p.WithAnnotations {
+ out.Write([]byte(packerBlockHeader))
+ }
+ out.Write(p.out)
+ }
+}
+
+type VariableParser struct {
+ WithAnnotations bool
+ variablesOut []byte
+ localsOut []byte
+}
+
+func makeLocal(variable *template.Variable, sensitive bool, localBody *hclwrite.Body, localsContent *hclwrite.File, hasLocals *bool) []byte {
+ if sensitive {
+ // Create Local block because this is sensitive
+ sensitiveLocalContent := hclwrite.NewEmptyFile()
+ body := sensitiveLocalContent.Body()
+ body.AppendNewline()
+ sensitiveLocalBody := body.AppendNewBlock("local", []string{variable.Key}).Body()
+ sensitiveLocalBody.SetAttributeValue("sensitive", cty.BoolVal(true))
+ sensitiveLocalBody.SetAttributeValue("expression", hcl2shim.HCL2ValueFromConfigValue(variable.Default))
+ localsVariableMap[variable.Key] = "local"
+ return sensitiveLocalContent.Bytes()
+ }
+ localBody.SetAttributeValue(variable.Key, hcl2shim.HCL2ValueFromConfigValue(variable.Default))
+ localsVariableMap[variable.Key] = "locals"
+ *hasLocals = true
+ return []byte{}
+}
+
+func makeVariable(variable *template.Variable, sensitive bool) []byte {
+ variablesContent := hclwrite.NewEmptyFile()
+ variablesBody := variablesContent.Body()
+ variablesBody.AppendNewline()
+ variableBody := variablesBody.AppendNewBlock("variable", []string{variable.Key}).Body()
+ variableBody.SetAttributeRaw("type", hclwrite.Tokens{&hclwrite.Token{Bytes: []byte("string")}})
+
+ if variable.Default != "" || !variable.Required {
+ shimmed := hcl2shim.HCL2ValueFromConfigValue(variable.Default)
+ variableBody.SetAttributeValue("default", shimmed)
+ }
+ if sensitive {
+ variableBody.SetAttributeValue("sensitive", cty.BoolVal(true))
+ }
+
+ return variablesContent.Bytes()
+}
+
+func (p *VariableParser) Parse(tpl *template.Template) error {
+ // Output Locals and Local blocks
+ localsContent := hclwrite.NewEmptyFile()
+ localsBody := localsContent.Body()
+ localsBody.AppendNewline()
+ localBody := localsBody.AppendNewBlock("locals", nil).Body()
+ hasLocals := false
+
+ if len(p.variablesOut) == 0 {
+ p.variablesOut = []byte{}
+ }
+ if len(p.localsOut) == 0 {
+ p.localsOut = []byte{}
+ }
+
+ if len(tpl.Variables) == 0 {
+ tpl.Variables = make(map[string]*template.Variable)
+ }
+ // JSON supports variable declaration via var-files.
+ // User variables that might be defined in a var-file
+ // but not in the actual JSON template should be accounted for.
+ userVars := referencedUserVariables(tpl.RawContents)
+ for name, variable := range userVars {
+ if _, ok := tpl.Variables[name]; ok {
+ continue
+ }
+ tpl.Variables[name] = variable
+ }
+
+ variables := []*template.Variable{}
+ {
+ // sort variables to avoid map's randomness
+ for _, variable := range tpl.Variables {
+ variables = append(variables, variable)
+ }
+ sort.Slice(variables, func(i, j int) bool {
+ return variables[i].Key < variables[j].Key
+ })
+ }
+
+ for _, variable := range variables {
+ // Create new HCL2 "variables" block, and populate the "value"
+ // field with the "Default" value from the JSON variable.
+
+ // Interpolate Jsonval first as an hcl variable to determine if it is
+ // a local. Variables referencing some form of variable expression must be defined as a local in HCL2,
+ // as variables in HCL2 must have a known value at parsing time.
+ isLocal, _ := variableTransposeTemplatingCalls([]byte(variable.Default))
+ sensitive := false
+ if isSensitiveVariable(variable.Key, tpl.SensitiveVariables) {
+ sensitive = true
+ }
+ // Create final HCL block and append.
+ if isLocal {
+ sensitiveBlocks := makeLocal(variable, sensitive, localBody, localsContent, &hasLocals)
+ if len(sensitiveBlocks) > 0 {
+ p.localsOut = append(p.localsOut, transposeTemplatingCalls(sensitiveBlocks)...)
+ }
+ continue
+ }
+ varbytes := makeVariable(variable, sensitive)
+ _, out := variableTransposeTemplatingCalls(varbytes)
+ p.variablesOut = append(p.variablesOut, out...)
+ }
+
+ if hasLocals == true {
+ p.localsOut = append(p.localsOut, transposeTemplatingCalls(localsContent.Bytes())...)
+ }
+
+ return nil
+}
+
+func (p *VariableParser) Write(out *bytes.Buffer) {
+ if len(p.variablesOut) > 0 {
+ if p.WithAnnotations {
+ out.Write([]byte(inputVarHeader))
+ }
+ out.Write(p.variablesOut)
+ }
+}
+
+type LocalsParser struct {
+ WithAnnotations bool
+ LocalsOut []byte
+}
+
+func (p *LocalsParser) Parse(tpl *template.Template) error {
+ // Locals where parsed with Variables
+ return nil
+}
+
+func (p *LocalsParser) Write(out *bytes.Buffer) {
+ if timestamp {
+ _, _ = out.Write([]byte("\n"))
+ if p.WithAnnotations {
+ fmt.Fprintln(out, `# "timestamp" template function replacement`)
+ }
+ fmt.Fprintln(out, `locals { timestamp = regex_replace(timestamp(), "[- TZ:]", "") }`)
+ }
+ if isotime {
+ fmt.Fprintln(out, `# The "legacy_isotime" function has been provided for backwards compatability, but we recommend switching to the timestamp and formatdate functions.`)
+ }
+ if strftime {
+ fmt.Fprintln(out, `# The "legacy_strftime" function has been provided for backwards compatability, but we recommend switching to the timestamp and formatdate functions.`)
+ }
+ if len(p.LocalsOut) > 0 {
+ if p.WithAnnotations {
+ out.Write([]byte(localsVarHeader))
+ }
+ out.Write(p.LocalsOut)
+ }
+}
+
+type AmazonSecretsDatasourceParser struct {
+ WithAnnotations bool
+ out []byte
+}
+
+func (p *AmazonSecretsDatasourceParser) Parse(_ *template.Template) error {
+ if p.out == nil {
+ p.out = []byte{}
+ }
+
+ keys := make([]string, 0, len(amazonSecretsManagerMap))
+ for k := range amazonSecretsManagerMap {
+ keys = append(keys, k)
+ }
+ sort.Strings(keys)
+
+ for _, dataSourceName := range keys {
+ datasourceContent := hclwrite.NewEmptyFile()
+ body := datasourceContent.Body()
+ body.AppendNewline()
+ datasourceBody := body.AppendNewBlock("data", []string{"amazon-secretsmanager", dataSourceName}).Body()
+ jsonBodyToHCL2Body(datasourceBody, amazonSecretsManagerMap[dataSourceName])
+ p.out = append(p.out, datasourceContent.Bytes()...)
+ }
+
+ return nil
+}
+
+func (p *AmazonSecretsDatasourceParser) Write(out *bytes.Buffer) {
+ if len(p.out) > 0 {
+ if p.WithAnnotations {
+ out.Write([]byte(amazonSecretsManagerDataHeader))
+ }
+ out.Write(p.out)
+ }
+}
+
+type AmazonAmiDatasourceParser struct {
+ Builders []*template.Builder
+ WithAnnotations bool
+ out []byte
+}
+
+func (p *AmazonAmiDatasourceParser) Parse(_ *template.Template) error {
+ if p.out == nil {
+ p.out = []byte{}
+ }
+
+ amazonAmiFilters := []map[string]interface{}{}
+ i := 1
+ for _, builder := range p.Builders {
+ if strings.HasPrefix(builder.Type, "amazon-") {
+ if sourceAmiFilter, ok := builder.Config["source_ami_filter"]; ok {
+ sourceAmiFilterCfg := map[string]interface{}{}
+ if err := mapstructure.Decode(sourceAmiFilter, &sourceAmiFilterCfg); err != nil {
+ return fmt.Errorf("Failed to write amazon-ami data source: %v", err)
+ }
+
+ sourceAmiFilterCfg, err := copyAWSAccessConfig(sourceAmiFilterCfg, builder.Config)
+ if err != nil {
+ return err
+ }
+
+ duplicate := false
+ dataSourceName := fmt.Sprintf("autogenerated_%d", i)
+ for j, filter := range amazonAmiFilters {
+ if reflect.DeepEqual(filter, sourceAmiFilterCfg) {
+ duplicate = true
+ dataSourceName = fmt.Sprintf("autogenerated_%d", j+1)
+ continue
+ }
+ }
+
+ // This is a hack...
+ // Use templating so that it could be correctly transformed later into a data resource
+ sourceAmiDataRef := fmt.Sprintf("{{ data `amazon-ami.%s.id` }}", dataSourceName)
+
+ if duplicate {
+ delete(builder.Config, "source_ami_filter")
+ builder.Config["source_ami"] = sourceAmiDataRef
+ continue
+ }
+
+ amazonAmiFilters = append(amazonAmiFilters, sourceAmiFilterCfg)
+ delete(builder.Config, "source_ami_filter")
+ builder.Config["source_ami"] = sourceAmiDataRef
+ i++
+
+ datasourceContent := hclwrite.NewEmptyFile()
+ body := datasourceContent.Body()
+ body.AppendNewline()
+ sourceBody := body.AppendNewBlock("data", []string{"amazon-ami", dataSourceName}).Body()
+ jsonBodyToHCL2Body(sourceBody, sourceAmiFilterCfg)
+ p.out = append(p.out, transposeTemplatingCalls(datasourceContent.Bytes())...)
+ }
+ }
+ }
+ return nil
+}
+
+func copyAWSAccessConfig(sourceAmi map[string]interface{}, builder map[string]interface{}) (map[string]interface{}, error) {
+ // Transform access config to a map
+ accessConfigMap := map[string]interface{}{}
+ if err := mapstructure.Decode(awscommon.AccessConfig{}, &accessConfigMap); err != nil {
+ return sourceAmi, err
+ }
+
+ for k := range accessConfigMap {
+ // Copy only access config present in the builder
+ if v, ok := builder[k]; ok {
+ sourceAmi[k] = v
+ }
+ }
+
+ return sourceAmi, nil
+}
+
+func (p *AmazonAmiDatasourceParser) Write(out *bytes.Buffer) {
+ if len(p.out) > 0 {
+ if p.WithAnnotations {
+ out.Write([]byte(amazonAmiDataHeader))
+ }
+ out.Write(p.out)
+ }
+}
+
+type SourceParser struct {
+ Builders []*template.Builder
+ BuilderPlugins packer.BuilderSet
+ WithAnnotations bool
+ out []byte
+}
+
+func (p *SourceParser) Parse(tpl *template.Template) error {
+ var unknownBuilders []string
+ if p.out == nil {
+ p.out = []byte{}
+ }
+ for i, builderCfg := range p.Builders {
+ sourcesContent := hclwrite.NewEmptyFile()
+ body := sourcesContent.Body()
+
+ body.AppendNewline()
+ if !p.BuilderPlugins.Has(builderCfg.Type) {
+ unknownBuilders = append(unknownBuilders, builderCfg.Type)
+
+ }
+ if builderCfg.Name == "" || builderCfg.Name == builderCfg.Type {
+ builderCfg.Name = fmt.Sprintf("autogenerated_%d", i+1)
+ }
+ builderCfg.Name = strings.ReplaceAll(strings.TrimSpace(builderCfg.Name), " ", "_")
+
+ sourceBody := body.AppendNewBlock("source", []string{builderCfg.Type, builderCfg.Name}).Body()
+
+ jsonBodyToHCL2Body(sourceBody, builderCfg.Config)
+
+ p.out = append(p.out, transposeTemplatingCalls(sourcesContent.Bytes())...)
+ }
+ if len(unknownBuilders) > 0 {
+ return fmt.Errorf("unknown builder type(s): %v\n", unknownBuilders)
+ }
+ return nil
+}
+
+func (p *SourceParser) Write(out *bytes.Buffer) {
+ if len(p.out) > 0 {
+ if p.WithAnnotations {
+ out.Write([]byte(sourcesHeader))
+ }
+ out.Write(p.out)
+ }
+}
+
+type BuildParser struct {
+ Builders []*template.Builder
+ WithAnnotations bool
+
+ provisioners BlockParser
+ postProcessors BlockParser
+ out []byte
+}
+
+func (p *BuildParser) Parse(tpl *template.Template) error {
+ if len(p.Builders) == 0 {
+ return nil
+ }
+
+ buildContent := hclwrite.NewEmptyFile()
+ buildBody := buildContent.Body()
+ if tpl.Description != "" {
+ buildBody.SetAttributeValue("description", cty.StringVal(tpl.Description))
+ buildBody.AppendNewline()
+ }
+
+ sourceNames := []string{}
+ for _, builder := range p.Builders {
+ sourceNames = append(sourceNames, fmt.Sprintf("source.%s.%s", builder.Type, builder.Name))
+ }
+ buildBody.SetAttributeValue("sources", hcl2shim.HCL2ValueFromConfigValue(sourceNames))
+ buildBody.AppendNewline()
+ p.out = buildContent.Bytes()
+
+ p.provisioners = &ProvisionerParser{
+ WithAnnotations: p.WithAnnotations,
+ }
+ if err := p.provisioners.Parse(tpl); err != nil {
+ return err
+ }
+
+ p.postProcessors = &PostProcessorParser{
+ WithAnnotations: p.WithAnnotations,
+ }
+ if err := p.postProcessors.Parse(tpl); err != nil {
+ return err
+ }
+
+ return nil
+}
+
+func (p *BuildParser) Write(out *bytes.Buffer) {
+ if len(p.out) > 0 {
+ if p.WithAnnotations {
+ out.Write([]byte(buildHeader))
+ } else {
+ _, _ = out.Write([]byte("\n"))
+ }
+ _, _ = out.Write([]byte("build {\n"))
+ out.Write(p.out)
+ p.provisioners.Write(out)
+ p.postProcessors.Write(out)
+ _, _ = out.Write([]byte("}\n"))
+ }
+}
+
+type ProvisionerParser struct {
+ WithAnnotations bool
+ out []byte
+}
+
+func (p *ProvisionerParser) Parse(tpl *template.Template) error {
+ if p.out == nil {
+ p.out = []byte{}
+ }
+ for _, provisioner := range tpl.Provisioners {
+ contentBytes := writeProvisioner("provisioner", provisioner)
+ p.out = append(p.out, transposeTemplatingCalls(contentBytes)...)
+ }
+
+ if tpl.CleanupProvisioner != nil {
+ contentBytes := writeProvisioner("error-cleanup-provisioner", tpl.CleanupProvisioner)
+ p.out = append(p.out, transposeTemplatingCalls(contentBytes)...)
+ }
+ return nil
+}
+
+func writeProvisioner(typeName string, provisioner *template.Provisioner) []byte {
+ provisionerContent := hclwrite.NewEmptyFile()
+ body := provisionerContent.Body()
+ block := body.AppendNewBlock(typeName, []string{provisioner.Type})
+
+ cfg := provisioner.Config
+ if cfg == nil {
+ cfg = map[string]interface{}{}
+ }
+
+ if len(provisioner.Except) > 0 {
+ cfg["except"] = provisioner.Except
+ }
+ if len(provisioner.Only) > 0 {
+ cfg["only"] = provisioner.Only
+ }
+ if provisioner.MaxRetries != "" {
+ cfg["max_retries"] = provisioner.MaxRetries
+ }
+ if provisioner.Timeout > 0 {
+ cfg["timeout"] = provisioner.Timeout.String()
+ }
+ if provisioner.PauseBefore > 0 {
+ cfg["pause_before"] = provisioner.PauseBefore.String()
+ }
+ body.AppendNewline()
+ jsonBodyToHCL2Body(block.Body(), cfg)
+ return provisionerContent.Bytes()
+}
+
+func (p *ProvisionerParser) Write(out *bytes.Buffer) {
+ if len(p.out) > 0 {
+ out.Write(p.out)
+ }
+}
+
+type PostProcessorParser struct {
+ WithAnnotations bool
+ out []byte
+}
+
+func (p *PostProcessorParser) Parse(tpl *template.Template) error {
+ if p.out == nil {
+ p.out = []byte{}
+ }
+ for _, pps := range tpl.PostProcessors {
+ postProcessorContent := hclwrite.NewEmptyFile()
+ body := postProcessorContent.Body()
+
+ switch len(pps) {
+ case 0:
+ continue
+ case 1:
+ default:
+ body = body.AppendNewBlock("post-processors", nil).Body()
+ }
+ for _, pp := range pps {
+ ppBody := body.AppendNewBlock("post-processor", []string{pp.Type}).Body()
+ if pp.KeepInputArtifact != nil {
+ ppBody.SetAttributeValue("keep_input_artifact", cty.BoolVal(*pp.KeepInputArtifact))
+ }
+ cfg := pp.Config
+ if cfg == nil {
+ cfg = map[string]interface{}{}
+ }
+
+ if len(pp.Except) > 0 {
+ cfg["except"] = pp.Except
+ }
+ if len(pp.Only) > 0 {
+ cfg["only"] = pp.Only
+ }
+ if pp.Name != "" && pp.Name != pp.Type {
+ cfg["name"] = pp.Name
+ }
+ jsonBodyToHCL2Body(ppBody, cfg)
+ }
+
+ p.out = append(p.out, transposeTemplatingCalls(postProcessorContent.Bytes())...)
+ }
+ return nil
+}
+
+func (p *PostProcessorParser) Write(out *bytes.Buffer) {
+ if len(p.out) > 0 {
+ out.Write(p.out)
+ }
+}
+
+func fixQuoting(old string) string {
+ // This regex captures golang template functions that use escaped quotes:
+ // {{ env \"myvar\" }}
+ // {{ split `some-string` \"-\" 0 }}
+ re := regexp.MustCompile(`{{\s*\w*(\s*(\\".*\\")\s*)+\w*\s*}}`)
+
+ body := re.ReplaceAllFunc([]byte(old), func(s []byte) []byte {
+ // Get the capture group
+ group := re.ReplaceAllString(string(s), `$1`)
+
+ unquoted, err := strconv.Unquote(fmt.Sprintf("\"%s\"", group))
+ if err != nil {
+ return s
+ }
+ return []byte(strings.Replace(string(s), group, unquoted, 1))
+
+ })
+
+ return string(body)
+}
diff --git a/v1.9.4/command/hcl2_upgrade_test.go b/v1.9.4/command/hcl2_upgrade_test.go
new file mode 100644
index 0000000..afa8575
--- /dev/null
+++ b/v1.9.4/command/hcl2_upgrade_test.go
@@ -0,0 +1,82 @@
+// Copyright (c) HashiCorp, Inc.
+// SPDX-License-Identifier: MPL-2.0
+
+package command
+
+import (
+ "io/ioutil"
+ "os"
+ "path/filepath"
+ "testing"
+
+ "github.com/google/go-cmp/cmp"
+)
+
+func Test_hcl2_upgrade(t *testing.T) {
+
+ tc := []struct {
+ folder string
+ flags []string
+ exitCode int
+ exitEarly bool
+ }{
+ {folder: "unknown_builder", flags: []string{}, exitCode: 1},
+ {folder: "complete", flags: []string{"-with-annotations"}},
+ {folder: "without-annotations", flags: []string{}},
+ {folder: "minimal", flags: []string{"-with-annotations"}},
+ {folder: "source-name", flags: []string{"-with-annotations"}},
+ {folder: "error-cleanup-provisioner", flags: []string{"-with-annotations"}},
+ {folder: "aws-access-config", flags: []string{}},
+ {folder: "escaping", flags: []string{}},
+ {folder: "vsphere_linux_options_and_network_interface", exitCode: 1, flags: []string{}},
+ {folder: "nonexistent", flags: []string{}, exitCode: 1, exitEarly: true},
+ {folder: "placeholders", flags: []string{}, exitCode: 0},
+ {folder: "ami_test", flags: []string{}, exitCode: 0},
+ {folder: "azure_shg", flags: []string{}, exitCode: 0},
+ {folder: "variables-only", flags: []string{}},
+ {folder: "variables-with-variables", flags: []string{}},
+ {folder: "complete-variables-with-template-engine", flags: []string{}},
+ {folder: "undeclared-variables", flags: []string{}, exitCode: 0},
+ {folder: "varfile-with-no-variables-block", flags: []string{}, exitCode: 0},
+ {folder: "bundled-plugin-used", flags: []string{}, exitCode: 0},
+ }
+
+ for _, tc := range tc {
+ t.Run(tc.folder, func(t *testing.T) {
+ inputPath := filepath.Join(testFixture("hcl2_upgrade", tc.folder, "input.json"))
+ outputPath := inputPath + ".pkr.hcl"
+ expectedPath := filepath.Join(testFixture("hcl2_upgrade", tc.folder, "expected.pkr.hcl"))
+ args := []string{"hcl2_upgrade"}
+ if len(tc.flags) > 0 {
+ args = append(args, tc.flags...)
+ }
+ args = append(args, inputPath)
+ p := helperCommand(t, args...)
+ err := p.Run()
+ defer os.Remove(outputPath)
+ if err != nil {
+ t.Logf("run returned an error: %s", err)
+ }
+ actualExitCode := p.ProcessState.ExitCode()
+ if tc.exitCode != actualExitCode {
+ t.Fatalf("unexpected exit code: %d found; expected %d ", actualExitCode, tc.exitCode)
+ }
+ if tc.exitEarly {
+ return
+ }
+ expected := string(mustBytes(ioutil.ReadFile(expectedPath)))
+ actual := string(mustBytes(ioutil.ReadFile(outputPath)))
+
+ if diff := cmp.Diff(expected, actual); diff != "" {
+ t.Fatalf("unexpected output: %s", diff)
+ }
+ })
+ }
+}
+
+func mustBytes(b []byte, e error) []byte {
+ if e != nil {
+ panic(e)
+ }
+ return b
+}
diff --git a/v1.9.4/command/init.go b/v1.9.4/command/init.go
new file mode 100644
index 0000000..fb21aab
--- /dev/null
+++ b/v1.9.4/command/init.go
@@ -0,0 +1,175 @@
+// Copyright (c) HashiCorp, Inc.
+// SPDX-License-Identifier: MPL-2.0
+
+package command
+
+import (
+ "context"
+ "crypto/sha256"
+ "fmt"
+ "log"
+ "runtime"
+ "strings"
+
+ pluginsdk "github.com/hashicorp/packer-plugin-sdk/plugin"
+ "github.com/hashicorp/packer/packer"
+ plugingetter "github.com/hashicorp/packer/packer/plugin-getter"
+ "github.com/hashicorp/packer/packer/plugin-getter/github"
+ "github.com/hashicorp/packer/version"
+ "github.com/posener/complete"
+)
+
+type InitCommand struct {
+ Meta
+}
+
+func (c *InitCommand) Run(args []string) int {
+ ctx, cleanup := handleTermInterrupt(c.Ui)
+ defer cleanup()
+
+ cfg, ret := c.ParseArgs(args)
+ if ret != 0 {
+ return ret
+ }
+
+ return c.RunContext(ctx, cfg)
+}
+
+func (c *InitCommand) ParseArgs(args []string) (*InitArgs, int) {
+ var cfg InitArgs
+ flags := c.Meta.FlagSet("init", 0)
+ flags.Usage = func() { c.Ui.Say(c.Help()) }
+ cfg.AddFlagSets(flags)
+ if err := flags.Parse(args); err != nil {
+ return &cfg, 1
+ }
+
+ args = flags.Args()
+ if len(args) != 1 {
+ flags.Usage()
+ return &cfg, 1
+ }
+ cfg.Path = args[0]
+ return &cfg, 0
+}
+
+func (c *InitCommand) RunContext(buildCtx context.Context, cla *InitArgs) int {
+ packerStarter, ret := c.GetConfig(&cla.MetaArgs)
+ if ret != 0 {
+ return ret
+ }
+
+ // Get plugins requirements
+ reqs, diags := packerStarter.PluginRequirements()
+ ret = writeDiags(c.Ui, nil, diags)
+ if ret != 0 {
+ return ret
+ }
+
+ opts := plugingetter.ListInstallationsOptions{
+ FromFolders: c.Meta.CoreConfig.Components.PluginConfig.KnownPluginFolders,
+ BinaryInstallationOptions: plugingetter.BinaryInstallationOptions{
+ OS: runtime.GOOS,
+ ARCH: runtime.GOARCH,
+ APIVersionMajor: pluginsdk.APIVersionMajor,
+ APIVersionMinor: pluginsdk.APIVersionMinor,
+ Checksummers: []plugingetter.Checksummer{
+ {Type: "sha256", Hash: sha256.New()},
+ },
+ },
+ }
+
+ if runtime.GOOS == "windows" && opts.Ext == "" {
+ opts.BinaryInstallationOptions.Ext = ".exe"
+ }
+
+ log.Printf("[TRACE] init: %#v", opts)
+
+ getters := []plugingetter.Getter{
+ &github.Getter{
+ // In the past some terraform plugins downloads were blocked from a
+ // specific aws region by s3. Changing the user agent unblocked the
+ // downloads so having one user agent per version will help mitigate
+ // that a little more. Especially in the case someone forks this
+ // code to make it more aggressive or something.
+ // TODO: allow to set this from the config file or an environment
+ // variable.
+ UserAgent: "packer-getter-github-" + version.String(),
+ },
+ }
+
+ ui := &packer.ColoredUi{
+ Color: packer.UiColorCyan,
+ Ui: c.Ui,
+ }
+
+ for _, pluginRequirement := range reqs {
+ // Get installed plugins that match requirement
+
+ installs, err := pluginRequirement.ListInstallations(opts)
+ if err != nil {
+ c.Ui.Error(err.Error())
+ return 1
+ }
+
+ log.Printf("[TRACE] for plugin %s found %d matching installation(s)", pluginRequirement.Identifier, len(installs))
+
+ if len(installs) > 0 && cla.Upgrade == false {
+ continue
+ }
+
+ newInstall, err := pluginRequirement.InstallLatest(plugingetter.InstallOptions{
+ InFolders: opts.FromFolders,
+ BinaryInstallationOptions: opts.BinaryInstallationOptions,
+ Getters: getters,
+ })
+ if err != nil {
+ c.Ui.Error(fmt.Sprintf("Failed getting the %q plugin:", pluginRequirement.Identifier))
+ c.Ui.Error(err.Error())
+ ret = 1
+ }
+ if newInstall != nil {
+ msg := fmt.Sprintf("Installed plugin %s %s in %q", pluginRequirement.Identifier, newInstall.Version, newInstall.BinaryPath)
+ ui.Say(msg)
+ }
+ }
+ return ret
+}
+
+func (*InitCommand) Help() string {
+ helpText := `
+Usage: packer init [options] TEMPLATE
+
+ Install all the missing plugins required in a Packer config. Note that Packer
+ does not have a state.
+
+ This is the first command that should be executed when working with a new
+ or existing template.
+
+ This command is always safe to run multiple times. Though subsequent runs may
+ give errors, this command will never delete anything.
+
+Options:
+ -upgrade On top of installing missing plugins, update
+ installed plugins to the latest available
+ version, if there is a new higher one. Note that
+ this still takes into consideration the version
+ constraint of the config.
+`
+
+ return strings.TrimSpace(helpText)
+}
+
+func (*InitCommand) Synopsis() string {
+ return "Install missing plugins or upgrade plugins"
+}
+
+func (*InitCommand) AutocompleteArgs() complete.Predictor {
+ return complete.PredictNothing
+}
+
+func (*InitCommand) AutocompleteFlags() complete.Flags {
+ return complete.Flags{
+ "-upgrade": complete.PredictNothing,
+ }
+}
diff --git a/v1.9.4/command/init_test.go b/v1.9.4/command/init_test.go
new file mode 100644
index 0000000..8a10cbb
--- /dev/null
+++ b/v1.9.4/command/init_test.go
@@ -0,0 +1,416 @@
+// Copyright (c) HashiCorp, Inc.
+// SPDX-License-Identifier: MPL-2.0
+
+//go:build amd64 && (darwin || windows || linux)
+
+package command
+
+import (
+ "context"
+ "fmt"
+ "log"
+ "os"
+ "path/filepath"
+ "runtime"
+ "sort"
+ "testing"
+
+ "github.com/google/go-cmp/cmp"
+ "github.com/hashicorp/go-getter/v2"
+ "github.com/hashicorp/packer-plugin-sdk/acctest"
+ "golang.org/x/mod/sumdb/dirhash"
+)
+
+type testCaseInit struct {
+ name string
+ setup []func(*testing.T, testCaseInit)
+ Meta Meta
+ inPluginFolder map[string]string
+ expectedPackerConfigDirHashBeforeInit string
+ inConfigFolder map[string]string
+ packerConfigDir string
+ packerUserFolder string
+ want int
+ dirFiles []string
+ expectedPackerConfigDirHashAfterInit string
+ moreTests []func(*testing.T, testCaseInit)
+}
+
+type testBuild struct {
+ want int
+}
+
+func (tb testBuild) fn(t *testing.T, tc testCaseInit) {
+ bc := BuildCommand{
+ Meta: tc.Meta,
+ }
+
+ args := []string{tc.packerUserFolder}
+ want := tb.want
+ if got := bc.Run(args); got != want {
+ t.Errorf("BuildCommand.Run() = %v, want %v", got, want)
+ }
+}
+
+func TestInitCommand_Run(t *testing.T) {
+ // These tests will try to optimise for doing the least amount of github api
+ // requests whilst testing the max amount of things at once. Hopefully they
+ // don't require a GH token just yet. Acc tests are run on linux, darwin and
+ // windows, so requests are done 3 times.
+
+ cfg := &configDirSingleton{map[string]string{}}
+
+ tests := []testCaseInit{
+ {
+ // here we pre-write plugins with valid checksums, Packer will
+ // see those as valid installations it did.
+ // the directory hash before and after init should be the same,
+ // that's a no-op. This also should do no GH query, so it is best
+ // to always run it.
+ "already-installed-no-op",
+ nil,
+ TestMetaFile(t),
+ map[string]string{
+ "github.com/sylviamoss/comment/packer-plugin-comment_v0.2.18_x5.0_darwin_amd64": "1",
+ "github.com/sylviamoss/comment/packer-plugin-comment_v0.2.18_x5.0_darwin_amd64_SHA256SUM": "6b86b273ff34fce19d6b804eff5a3f5747ada4eaa22f1d49c01e52ddb7875b4b",
+ "github.com/sylviamoss/comment/packer-plugin-comment_v0.2.18_x5.0_windows_amd64.exe": "1.exe",
+ "github.com/sylviamoss/comment/packer-plugin-comment_v0.2.18_x5.0_windows_amd64.exe_SHA256SUM": "07d8453027192ee0c4120242e6e84e2ca2328b8e0f506e2f818a1a5b82790a0b",
+ "github.com/sylviamoss/comment/packer-plugin-comment_v0.2.18_x5.0_linux_amd64": "1.out",
+ "github.com/sylviamoss/comment/packer-plugin-comment_v0.2.18_x5.0_linux_amd64_SHA256SUM": "59031c50e0dfeedfde2b4e9445754804dce3f29e4efa737eead0ca9b4f5b85a5",
+ },
+ "h1:Q5qyAOdD43hL3CquQdVfaHpOYGf0UsZ/+wVA9Ry6cbA=",
+ map[string]string{
+ `cfg.pkr.hcl`: `
+ packer {
+ required_plugins {
+ comment = {
+ source = "github.com/sylviamoss/comment"
+ version = "v0.2.018"
+ }
+ }
+ }`,
+ },
+ cfg.dir("1_pkr_config"),
+ cfg.dir("1_pkr_user_folder"),
+ 0,
+ nil,
+ "h1:Q5qyAOdD43hL3CquQdVfaHpOYGf0UsZ/+wVA9Ry6cbA=",
+ []func(t *testing.T, tc testCaseInit){
+ // test that a build will not work since plugins are broken for
+ // this tests (they are not binaries).
+ testBuild{want: 1}.fn,
+ },
+ },
+ {
+ // here we pre-write plugins with valid checksums, Packer will
+ // see those as valid installations it did.
+ // But because we require version 0.2.19, we will upgrade.
+ "already-installed-upgrade",
+ []func(t *testing.T, tc testCaseInit){
+ skipInitTestUnlessEnVar(acctest.TestEnvVar).fn,
+ },
+ TestMetaFile(t),
+ map[string]string{
+ "github.com/sylviamoss/comment/packer-plugin-comment_v0.2.18_x5.0_darwin_amd64": "1",
+ "github.com/sylviamoss/comment/packer-plugin-comment_v0.2.18_x5.0_darwin_amd64_SHA256SUM": "6b86b273ff34fce19d6b804eff5a3f5747ada4eaa22f1d49c01e52ddb7875b4b",
+ "github.com/sylviamoss/comment/packer-plugin-comment_v0.2.18_x5.0_windows_amd64.exe": "1.exe",
+ "github.com/sylviamoss/comment/packer-plugin-comment_v0.2.18_x5.0_windows_amd64.exe_SHA256SUM": "07d8453027192ee0c4120242e6e84e2ca2328b8e0f506e2f818a1a5b82790a0b",
+ "github.com/sylviamoss/comment/packer-plugin-comment_v0.2.18_x5.0_linux_amd64": "1.out",
+ "github.com/sylviamoss/comment/packer-plugin-comment_v0.2.18_x5.0_linux_amd64_SHA256SUM": "59031c50e0dfeedfde2b4e9445754804dce3f29e4efa737eead0ca9b4f5b85a5",
+ },
+ "h1:Q5qyAOdD43hL3CquQdVfaHpOYGf0UsZ/+wVA9Ry6cbA=",
+ map[string]string{
+ `cfg.pkr.hcl`: `
+ packer {
+ required_plugins {
+ comment = {
+ source = "github.com/sylviamoss/comment"
+ version = "v0.2.019"
+ }
+ }
+ }`,
+ `source.pkr.hcl`: `
+ source "null" "test" {
+ communicator = "none"
+ }
+ `,
+ `build.pkr.hcl`: `
+ build {
+ sources = ["source.null.test"]
+ provisioner "comment" {
+ comment = "Begin ¡"
+ ui = true
+ bubble_text = true
+ }
+ }
+ `,
+ },
+ cfg.dir("2_pkr_config"),
+ cfg.dir("2_pkr_user_folder"),
+ 0,
+ []string{
+ "github.com/sylviamoss/comment/packer-plugin-comment_v0.2.18_x5.0_darwin_amd64",
+ "github.com/sylviamoss/comment/packer-plugin-comment_v0.2.18_x5.0_darwin_amd64_SHA256SUM",
+ "github.com/sylviamoss/comment/packer-plugin-comment_v0.2.18_x5.0_linux_amd64",
+ "github.com/sylviamoss/comment/packer-plugin-comment_v0.2.18_x5.0_linux_amd64_SHA256SUM",
+ "github.com/sylviamoss/comment/packer-plugin-comment_v0.2.18_x5.0_windows_amd64.exe",
+ "github.com/sylviamoss/comment/packer-plugin-comment_v0.2.18_x5.0_windows_amd64.exe_SHA256SUM",
+ map[string]string{
+ "darwin": "github.com/sylviamoss/comment/packer-plugin-comment_v0.2.19_x5.0_darwin_amd64_SHA256SUM",
+ "linux": "github.com/sylviamoss/comment/packer-plugin-comment_v0.2.19_x5.0_linux_amd64_SHA256SUM",
+ "windows": "github.com/sylviamoss/comment/packer-plugin-comment_v0.2.19_x5.0_windows_amd64.exe_SHA256SUM",
+ }[runtime.GOOS],
+ map[string]string{
+ "darwin": "github.com/sylviamoss/comment/packer-plugin-comment_v0.2.19_x5.0_darwin_amd64",
+ "linux": "github.com/sylviamoss/comment/packer-plugin-comment_v0.2.19_x5.0_linux_amd64",
+ "windows": "github.com/sylviamoss/comment/packer-plugin-comment_v0.2.19_x5.0_windows_amd64.exe",
+ }[runtime.GOOS],
+ },
+ map[string]string{
+ "darwin": "h1:ORwcCYUx8z/5n/QvuTJo2vrgKpfJA4AxlNg1G9/BCDI=",
+ "linux": "h1:CGym0+Nd0LEANgzqL0wx/LDjRL8bYwlpZ0HajPJo/hs=",
+ "windows": "h1:ag0/C1YjP7KoEDYOiJHE0K+lhFgs0tVgjriWCXVT1fg=",
+ }[runtime.GOOS],
+ []func(t *testing.T, tc testCaseInit){
+ // test that a build will work as the plugin was just installed
+ testBuild{want: 0}.fn,
+ },
+ },
+ {
+ "release-with-no-binary",
+ []func(t *testing.T, tc testCaseInit){
+ skipInitTestUnlessEnVar(acctest.TestEnvVar).fn,
+ },
+ TestMetaFile(t),
+ nil,
+ "h1:47DEQpj8HBSa+/TImW+5JCeuQeRkm5NMpJWZG3hSuFU=",
+ map[string]string{
+ `cfg.pkr.hcl`: `
+ packer {
+ required_plugins {
+ comment = {
+ source = "github.com/sylviamoss/comment"
+ version = "v0.2.20"
+ }
+ }
+ }`,
+ },
+ cfg.dir("3_pkr_config"),
+ cfg.dir("3_pkr_user_folder"),
+ 1,
+ nil,
+ "h1:47DEQpj8HBSa+/TImW+5JCeuQeRkm5NMpJWZG3hSuFU=",
+ nil,
+ },
+ {
+ "manually-installed-single-component-plugin-works",
+ []func(t *testing.T, tc testCaseInit){
+ skipInitTestUnlessEnVar(acctest.TestEnvVar).fn,
+ initTestGoGetPlugin{
+ Src: "https://github.com/azr/packer-provisioner-comment/releases/download/v1.0.0/" +
+ "packer-provisioner-comment_v1.0.0_" + runtime.GOOS + "_" + runtime.GOARCH + ".zip",
+ Dst: filepath.Join(cfg.dir("4_pkr_config"), defaultConfigDir, "plugins"),
+ }.fn,
+ },
+ TestMetaFile(t),
+ nil,
+ map[string]string{
+ "darwin": "h1:nVebbXToeehPUASRbvV9M4qaA9+UgoR5AMp7LjTrSBk=",
+ "linux": "h1:/U5vdeMtOpRKNu0ld8+qf4t6WC+BsfCQ6JRo9Dh/khI=",
+ "windows": "h1:0nkdNCjtTHTgBNkzVKG++/VYmWAvq/o236GGTxrIf/Q=",
+ }[runtime.GOOS],
+ map[string]string{
+ `source.pkr.hcl`: `
+ source "null" "test" {
+ communicator = "none"
+ }
+ `,
+ `build.pkr.hcl`: `
+ build {
+ sources = ["source.null.test"]
+ provisioner "comment" {
+ comment = "Begin ¡"
+ ui = true
+ bubble_text = true
+ }
+ }
+ `,
+ },
+ cfg.dir("4_pkr_config"),
+ cfg.dir("4_pkr_user_folder"),
+ 0,
+ nil,
+ map[string]string{
+ "darwin": "h1:nVebbXToeehPUASRbvV9M4qaA9+UgoR5AMp7LjTrSBk=",
+ "linux": "h1:/U5vdeMtOpRKNu0ld8+qf4t6WC+BsfCQ6JRo9Dh/khI=",
+ "windows": "h1:0nkdNCjtTHTgBNkzVKG++/VYmWAvq/o236GGTxrIf/Q=",
+ }[runtime.GOOS],
+ []func(*testing.T, testCaseInit){
+ testBuild{want: 0}.fn,
+ },
+ },
+ {
+ "manually-installed-single-component-plugin-old-api-fails",
+ []func(t *testing.T, tc testCaseInit){
+ skipInitTestUnlessEnVar(acctest.TestEnvVar).fn,
+ initTestGoGetPlugin{
+ Src: "https://github.com/azr/packer-provisioner-comment/releases/download/v0.0.0/" +
+ "packer-provisioner-comment_v0.0.0_" + runtime.GOOS + "_" + runtime.GOARCH + ".zip",
+ Dst: filepath.Join(cfg.dir("5_pkr_config"), defaultConfigDir, "plugins"),
+ }.fn,
+ },
+ TestMetaFile(t),
+ nil,
+ map[string]string{
+ "darwin": "h1:gW4gzpDXeu3cDrXgHJj9iWAN7Pyak626Gq8Bu2LG1kY=",
+ "linux": "h1:wQ2H5+J7VXwQzqR9DgpWtjhw9OVEFbcKQL6dgm/+zwo=",
+ "windows": "h1:BqRdW3c5H1PZ2Q4DOaKWja21v3nDlY5Nn8kqahhHGSw=",
+ }[runtime.GOOS],
+ map[string]string{
+ `source.pkr.hcl`: `
+ source "null" "test" {
+ communicator = "none"
+ }
+ `,
+ `build.pkr.hcl`: `
+ build {
+ sources = ["source.null.test"]
+ provisioner "comment" {
+ comment = "Begin ¡"
+ ui = true
+ bubble_text = true
+ }
+ }
+ `,
+ },
+ cfg.dir("5_pkr_config"),
+ cfg.dir("5_pkr_user_folder"),
+ 0,
+ nil,
+ map[string]string{
+ "darwin": "h1:gW4gzpDXeu3cDrXgHJj9iWAN7Pyak626Gq8Bu2LG1kY=",
+ "linux": "h1:wQ2H5+J7VXwQzqR9DgpWtjhw9OVEFbcKQL6dgm/+zwo=",
+ "windows": "h1:BqRdW3c5H1PZ2Q4DOaKWja21v3nDlY5Nn8kqahhHGSw=",
+ }[runtime.GOOS],
+ []func(*testing.T, testCaseInit){
+ testBuild{want: 1}.fn,
+ },
+ },
+ {
+ "unsupported-non-github-source-address",
+ []func(t *testing.T, tc testCaseInit){
+ skipInitTestUnlessEnVar(acctest.TestEnvVar).fn,
+ },
+ TestMetaFile(t),
+ nil,
+ "h1:47DEQpj8HBSa+/TImW+5JCeuQeRkm5NMpJWZG3hSuFU=",
+ map[string]string{
+ `cfg.pkr.hcl`: `
+ packer {
+ required_plugins {
+ comment = {
+ source = "example.com/sylviamoss/comment"
+ version = "v0.2.19"
+ }
+ }
+ }`,
+ },
+ cfg.dir("6_pkr_config"),
+ cfg.dir("6_pkr_user_folder"),
+ 1,
+ nil,
+ "h1:47DEQpj8HBSa+/TImW+5JCeuQeRkm5NMpJWZG3hSuFU=",
+ nil,
+ },
+ }
+ for _, tt := range tests {
+ t.Run(tt.name, func(t *testing.T) {
+ log.Printf("starting %s", tt.name)
+ log.Printf("%#v", tt)
+ t.Cleanup(func() {
+ _ = os.RemoveAll(tt.packerConfigDir)
+ })
+ t.Cleanup(func() {
+ _ = os.RemoveAll(tt.packerUserFolder)
+ })
+ t.Setenv("PACKER_CONFIG_DIR", tt.packerConfigDir)
+ for _, init := range tt.setup {
+ init(t, tt)
+ if t.Skipped() {
+ return
+ }
+ }
+ createFiles(tt.packerConfigDir, tt.inPluginFolder)
+ createFiles(tt.packerUserFolder, tt.inConfigFolder)
+
+ hash, err := dirhash.HashDir(tt.packerConfigDir, "", dirhash.DefaultHash)
+ if err != nil {
+ t.Fatalf("HashDir: %v", err)
+ }
+ if diff := cmp.Diff(tt.expectedPackerConfigDirHashBeforeInit, hash); diff != "" {
+ t.Errorf("unexpected dir hash before init: +found -expected %s", diff)
+ }
+
+ args := []string{tt.packerUserFolder}
+
+ c := &InitCommand{
+ Meta: tt.Meta,
+ }
+
+ if err := c.CoreConfig.Components.PluginConfig.Discover(); err != nil {
+ t.Fatalf("Failed to discover plugins: %s", err)
+ }
+
+ c.CoreConfig.Components.PluginConfig.KnownPluginFolders = []string{tt.packerConfigDir}
+ if got := c.Run(args); got != tt.want {
+ t.Errorf("InitCommand.Run() = %v, want %v", got, tt.want)
+ }
+
+ if tt.dirFiles != nil {
+ dirFiles, err := dirhash.DirFiles(tt.packerConfigDir, "")
+ if err != nil {
+ t.Fatalf("DirFiles: %v", err)
+ }
+ sort.Strings(tt.dirFiles)
+ sort.Strings(dirFiles)
+ if diff := cmp.Diff(tt.dirFiles, dirFiles); diff != "" {
+ t.Errorf("found files differ: %v", diff)
+ }
+ }
+
+ hash, err = dirhash.HashDir(tt.packerConfigDir, "", dirhash.DefaultHash)
+ if err != nil {
+ t.Fatalf("HashDir: %v", err)
+ }
+ if diff := cmp.Diff(tt.expectedPackerConfigDirHashAfterInit, hash); diff != "" {
+ t.Errorf("unexpected dir hash after init: %s", diff)
+ }
+
+ for i, subTest := range tt.moreTests {
+ t.Run(fmt.Sprintf("-subtest-%d", i), func(t *testing.T) {
+ subTest(t, tt)
+ })
+ }
+ })
+ }
+}
+
+type skipInitTestUnlessEnVar string
+
+func (key skipInitTestUnlessEnVar) fn(t *testing.T, tc testCaseInit) {
+ // always run acc tests for now
+ // if os.Getenv(string(key)) == "" {
+ // t.Skipf("Acceptance test skipped unless env '%s' set", key)
+ // }
+}
+
+type initTestGoGetPlugin struct {
+ Src string
+ Dst string
+}
+
+func (opts initTestGoGetPlugin) fn(t *testing.T, _ testCaseInit) {
+ if _, err := getter.Get(context.Background(), opts.Dst, opts.Src); err != nil {
+ t.Fatalf("get: %v", err)
+ }
+}
diff --git a/v1.9.4/command/inspect.go b/v1.9.4/command/inspect.go
new file mode 100644
index 0000000..827d61f
--- /dev/null
+++ b/v1.9.4/command/inspect.go
@@ -0,0 +1,87 @@
+// Copyright (c) HashiCorp, Inc.
+// SPDX-License-Identifier: MPL-2.0
+
+package command
+
+import (
+ "context"
+ "strings"
+
+ "github.com/hashicorp/packer/packer"
+ "github.com/posener/complete"
+)
+
+type InspectCommand struct {
+ Meta
+}
+
+func (c *InspectCommand) Run(args []string) int {
+ ctx := context.Background()
+
+ cfg, ret := c.ParseArgs(args)
+ if ret != 0 {
+ return ret
+ }
+
+ return c.RunContext(ctx, cfg)
+}
+
+func (c *InspectCommand) ParseArgs(args []string) (*InspectArgs, int) {
+ var cfg InspectArgs
+ flags := c.Meta.FlagSet("inspect", FlagSetVars)
+ flags.Usage = func() { c.Ui.Say(c.Help()) }
+ cfg.AddFlagSets(flags)
+ if err := flags.Parse(args); err != nil {
+ return &cfg, 1
+ }
+
+ args = flags.Args()
+ if len(args) == 1 {
+ cfg.Path = args[0]
+ }
+ return &cfg, 0
+}
+
+func (c *InspectCommand) RunContext(ctx context.Context, cla *InspectArgs) int {
+ packerStarter, ret := c.GetConfig(&cla.MetaArgs)
+ if ret != 0 {
+ return ret
+ }
+
+ // here we ignore init diags to allow unknown variables to be used
+ _ = packerStarter.Initialize(packer.InitializeOptions{})
+
+ return packerStarter.InspectConfig(packer.InspectConfigOptions{
+ Ui: c.Ui,
+ })
+}
+
+func (*InspectCommand) Help() string {
+ helpText := `
+Usage: packer inspect TEMPLATE
+
+ Inspects a template, parsing and outputting the components a template
+ defines. This does not validate the contents of a template (other than
+ basic syntax by necessity).
+
+Options:
+
+ -machine-readable Machine-readable output
+`
+
+ return strings.TrimSpace(helpText)
+}
+
+func (c *InspectCommand) Synopsis() string {
+ return "see components of a template"
+}
+
+func (c *InspectCommand) AutocompleteArgs() complete.Predictor {
+ return complete.PredictNothing
+}
+
+func (c *InspectCommand) AutocompleteFlags() complete.Flags {
+ return complete.Flags{
+ "-machine-readable": complete.PredictNothing,
+ }
+}
diff --git a/v1.9.4/command/inspect_test.go b/v1.9.4/command/inspect_test.go
new file mode 100644
index 0000000..0d87ee7
--- /dev/null
+++ b/v1.9.4/command/inspect_test.go
@@ -0,0 +1,186 @@
+// Copyright (c) HashiCorp, Inc.
+// SPDX-License-Identifier: MPL-2.0
+
+package command
+
+import (
+ "fmt"
+ "path/filepath"
+ "testing"
+
+ "github.com/google/go-cmp/cmp"
+)
+
+func Test_commands(t *testing.T) {
+
+ tc := []struct {
+ command []string
+ env []string
+ expected string
+ }{
+ {[]string{"inspect", filepath.Join(testFixture("var-arg"), "fruit_builder.pkr.hcl")}, nil, `Packer Inspect: HCL2 mode
+
+> input-variables:
+
+var.fruit: "<unknown>"
+
+> local-variables:
+
+local.fruit: "<unknown>"
+
+> builds:
+
+ > <unnamed build 0>:
+
+ sources:
+
+ null.builder
+
+ provisioners:
+
+ shell-local
+
+ post-processors:
+
+ <no post-processor>
+
+`},
+ {[]string{"inspect", "-var=fruit=banana", filepath.Join(testFixture("var-arg"), "fruit_builder.pkr.hcl")}, nil, `Packer Inspect: HCL2 mode
+
+> input-variables:
+
+var.fruit: "banana"
+
+> local-variables:
+
+local.fruit: "banana"
+
+> builds:
+
+ > <unnamed build 0>:
+
+ sources:
+
+ null.builder
+
+ provisioners:
+
+ shell-local
+
+ post-processors:
+
+ <no post-processor>
+
+`},
+ {[]string{"inspect", "-var=fruit=peach",
+ "-var=unknown_string=also_peach",
+ `-var=unknown_unknown=["peach_too"]`,
+ `-var=unknown_list_of_string=["first_peach", "second_peach"]`,
+ filepath.Join(testFixture("hcl"), "inspect", "fruit_string.pkr.hcl")}, nil,
+ `Packer Inspect: HCL2 mode
+
+> input-variables:
+
+var.default_from_env: ""
+var.fruit: "peach"
+var.other_default_from_env: ""
+var.unknown_list_of_string: "[\n \"first_peach\",\n \"second_peach\",\n]"
+var.unknown_string: "also_peach"
+var.unknown_unknown: "[\"peach_too\"]"
+
+> local-variables:
+
+
+> builds:
+
+`},
+ {[]string{"inspect", "-var=fruit=peach", "-var=other_default_from_env=apple", filepath.Join(testFixture("hcl"), "inspect")}, []string{"DEFAULT_FROM_ENV=cherry"}, `Packer Inspect: HCL2 mode
+
+> input-variables:
+
+var.default_from_env: "cherry"
+var.fruit: "peach"
+var.other_default_from_env: "apple"
+var.unknown_list_of_string: "<unknown>"
+var.unknown_string: "<unknown>"
+var.unknown_unknown: "<unknown>"
+
+> local-variables:
+
+
+> builds:
+
+ > aws_example_builder:
+
+ > Description: The builder of clouds !!
+
+Use it at will.
+
+
+ sources:
+
+ amazon-ebs.example-1
+
+ amazon-ebs.example-2
+
+ provisioners:
+
+ shell
+
+ post-processors:
+
+ 0:
+ manifest
+
+ 1:
+ shell-local
+
+ 2:
+ manifest
+ shell-local
+
+`},
+ {[]string{"inspect", filepath.Join(testFixture("inspect"), "unset_var.json")}, nil, `Packer Inspect: JSON mode
+Required variables:
+
+ something
+
+Optional variables and their defaults:
+
+
+Builders:
+
+ <No builders>
+
+Provisioners:
+
+ <No provisioners>
+
+Note: If your build names contain user variables or template
+functions such as 'timestamp', these are processed at build time,
+and therefore only show in their raw form here.
+`},
+ {
+ []string{
+ "inspect", filepath.Join(testFixture("hcl-inspect-with-sensitive-vars")),
+ },
+ nil,
+ testFixtureContent("hcl-inspect-with-sensitive-vars", "expected-output.txt"),
+ },
+ }
+
+ for _, tc := range tc {
+ t.Run(fmt.Sprintf("packer %s", tc.command), func(t *testing.T) {
+ p := helperCommand(t, tc.command...)
+ p.Env = append(p.Env, tc.env...)
+ bs, err := p.Output()
+ if err != nil {
+ t.Fatalf("%v: %s", err, bs)
+ }
+ actual := string(bs)
+ if diff := cmp.Diff(tc.expected, actual); diff != "" {
+ t.Fatalf("unexpected ouput %s", diff)
+ }
+ })
+ }
+}
diff --git a/v1.9.4/command/meta.go b/v1.9.4/command/meta.go
new file mode 100644
index 0000000..fb3d9ef
--- /dev/null
+++ b/v1.9.4/command/meta.go
@@ -0,0 +1,358 @@
+// Copyright (c) HashiCorp, Inc.
+// SPDX-License-Identifier: MPL-2.0
+
+package command
+
+import (
+ "bufio"
+ "flag"
+ "fmt"
+ "io"
+ "os"
+ "strings"
+
+ "github.com/hashicorp/hcl/v2"
+ "github.com/hashicorp/hcl/v2/hclparse"
+ packersdk "github.com/hashicorp/packer-plugin-sdk/packer"
+ "github.com/hashicorp/packer-plugin-sdk/template"
+ kvflag "github.com/hashicorp/packer/command/flag-kv"
+ "github.com/hashicorp/packer/hcl2template"
+ "github.com/hashicorp/packer/helper/wrappedstreams"
+ "github.com/hashicorp/packer/packer"
+ "github.com/hashicorp/packer/version"
+)
+
+// FlagSetFlags is an enum to define what flags are present in the
+// default FlagSet returned by Meta.FlagSet
+type FlagSetFlags uint
+
+const (
+ FlagSetNone FlagSetFlags = 0
+ FlagSetBuildFilter FlagSetFlags = 1 << iota
+ FlagSetVars
+)
+
+// Meta contains the meta-options and functionality that nearly every
+// Packer command inherits.
+type Meta struct {
+ CoreConfig *packer.CoreConfig
+ Ui packersdk.Ui
+ Version string
+}
+
+// Core returns the core for the given template given the configured
+// CoreConfig and user variables on this Meta.
+func (m *Meta) Core(tpl *template.Template, cla *MetaArgs) (*packer.Core, error) {
+ // Copy the config so we don't modify it
+ config := *m.CoreConfig
+ config.Template = tpl
+
+ fj := &kvflag.FlagJSON{}
+ // First populate fj with contents from var files
+ for _, file := range cla.VarFiles {
+ err := fj.Set(file)
+ if err != nil {
+ return nil, err
+ }
+ }
+ // Now read fj values back into flagvars and set as config.Variables. Only
+ // add to flagVars if the key doesn't already exist, because flagVars comes
+ // from the command line and should not be overridden by variable files.
+ if cla.Vars == nil {
+ cla.Vars = map[string]string{}
+ }
+ for k, v := range *fj {
+ if _, exists := cla.Vars[k]; !exists {
+ cla.Vars[k] = v
+ }
+ }
+ config.Variables = cla.Vars
+
+ core := packer.NewCore(&config)
+ return core, nil
+}
+
+// FlagSet returns a FlagSet with the common flags that every
+// command implements. The exact behavior of FlagSet can be configured
+// using the flags as the second parameter, for example to disable
+// build settings on the commands that don't handle builds.
+func (m *Meta) FlagSet(n string, _ FlagSetFlags) *flag.FlagSet {
+ f := flag.NewFlagSet(n, flag.ContinueOnError)
+
+ // Create an io.Writer that writes to our Ui properly for errors.
+ // This is kind of a hack, but it does the job. Basically: create
+ // a pipe, use a scanner to break it into lines, and output each line
+ // to the UI. Do this forever.
+ errR, errW := io.Pipe()
+ errScanner := bufio.NewScanner(errR)
+ go func() {
+ for errScanner.Scan() {
+ m.Ui.Error(errScanner.Text())
+ }
+ }()
+ f.SetOutput(errW)
+
+ return f
+}
+
+// ValidateFlags should be called after parsing flags to validate the
+// given flags
+func (m *Meta) ValidateFlags() error {
+ // TODO
+ return nil
+}
+
+// StdinPiped returns true if the input is piped.
+func (m *Meta) StdinPiped() bool {
+ fi, err := wrappedstreams.Stdin().Stat()
+ if err != nil {
+ // If there is an error, let's just say its not piped
+ return false
+ }
+
+ return fi.Mode()&os.ModeNamedPipe != 0
+}
+
+func (m *Meta) GetConfig(cla *MetaArgs) (packer.Handler, int) {
+ cfgType, err := cla.GetConfigType()
+ if err != nil {
+ m.Ui.Error(fmt.Sprintf("%q: %s", cla.Path, err))
+ return nil, 1
+ }
+
+ switch cfgType {
+ case ConfigTypeHCL2:
+ packer.CheckpointReporter.SetTemplateType(packer.HCL2Template)
+ // TODO(azr): allow to pass a slice of files here.
+ return m.GetConfigFromHCL(cla)
+ default:
+ packer.CheckpointReporter.SetTemplateType(packer.JSONTemplate)
+ // TODO: uncomment once we've polished HCL a bit more.
+ // c.Ui.Say(`Legacy JSON Configuration Will Be Used.
+ // The template will be parsed in the legacy configuration style. This style
+ // will continue to work but users are encouraged to move to the new style.
+ // See: https://packer.io/guides/hcl
+ // `)
+ return m.GetConfigFromJSON(cla)
+ }
+}
+
+func (m *Meta) GetConfigFromHCL(cla *MetaArgs) (*hcl2template.PackerConfig, int) {
+ parser := &hcl2template.Parser{
+ CorePackerVersion: version.SemVer,
+ CorePackerVersionString: version.FormattedVersion(),
+ Parser: hclparse.NewParser(),
+ PluginConfig: m.CoreConfig.Components.PluginConfig,
+ ValidationOptions: hcl2template.ValidationOptions{
+ WarnOnUndeclaredVar: cla.WarnOnUndeclaredVar,
+ },
+ }
+ cfg, diags := parser.Parse(cla.Path, cla.VarFiles, cla.Vars)
+ return cfg, writeDiags(m.Ui, parser.Files(), diags)
+}
+
+func (m *Meta) GetConfigFromJSON(cla *MetaArgs) (packer.Handler, int) {
+ // Parse the template
+ var tpl *template.Template
+ var err error
+ if cla.Path == "" {
+ // here cla validation passed so this means we want a default builder
+ // and we probably are in the console command
+ tpl, err = template.Parse(TiniestBuilder)
+ } else {
+ tpl, err = template.ParseFile(cla.Path)
+ }
+
+ if err != nil {
+ m.Ui.Error(fmt.Sprintf("Failed to parse file as legacy JSON template: "+
+ "if you are using an HCL template, check your file extensions; they "+
+ "should be either *.pkr.hcl or *.pkr.json; see the docs for more "+
+ "details: https://www.packer.io/docs/templates/hcl_templates. \n"+
+ "Original error: %s", err))
+ return nil, 1
+ }
+
+ // Get the core
+ core, err := m.Core(tpl, cla)
+ ret := 0
+ if err != nil {
+ m.Ui.Error(err.Error())
+ ret = 1
+ }
+ return core, ret
+}
+
+func (m *Meta) DetectBundledPlugins(handler packer.Handler) hcl.Diagnostics {
+ var plugins []string
+
+ switch h := handler.(type) {
+ case *packer.Core:
+ plugins = m.detectBundledPluginsJSON(h)
+ case *hcl2template.PackerConfig:
+ plugins = m.detectBundledPluginsHCL2(handler.(*hcl2template.PackerConfig))
+ }
+
+ if len(plugins) == 0 {
+ return nil
+ }
+
+ packer.CheckpointReporter.SetBundledUsage()
+
+ buf := &strings.Builder{}
+ buf.WriteString("This template relies on the use of plugins bundled into the Packer binary.\n")
+ buf.WriteString("The practice of bundling external plugins into Packer will be removed in an upcoming version.\n\n")
+ switch h := handler.(type) {
+ case *packer.Core:
+ buf.WriteString("To remove this warning and ensure builds keep working you can install these external plugins with the 'packer plugins install' command\n\n")
+
+ for _, plugin := range plugins {
+ fmt.Fprintf(buf, "* packer plugins install %s\n", plugin)
+ }
+
+ buf.WriteString("\nAlternatively, if you upgrade your templates to HCL2, you can use 'packer init' with a 'required_plugins' block to automatically install external plugins.\n\n")
+ fmt.Fprintf(buf, "You can try HCL2 by running 'packer hcl2_upgrade %s'", h.Template.Path)
+ case *hcl2template.PackerConfig:
+ buf.WriteString("To remove this warning, add the following section to your template:\n")
+ buf.WriteString(m.fixRequiredPlugins(h))
+ buf.WriteString("\nThen run 'packer init' to manage installation of the plugins")
+ }
+
+ return hcl.Diagnostics{
+ &hcl.Diagnostic{
+ Severity: hcl.DiagWarning,
+ Summary: "Bundled plugins used",
+ Detail: buf.String(),
+ },
+ }
+}
+
+func (m *Meta) detectBundledPluginsJSON(core *packer.Core) []string {
+ bundledPlugins := map[string]struct{}{}
+
+ tmpl := core.Template
+ if tmpl == nil {
+ panic("No template parsed. This is a Packer bug which should be reported, please open an issue on the project's issue tracker.")
+ }
+
+ for _, b := range tmpl.Builders {
+ builderType := fmt.Sprintf("packer-builder-%s", b.Type)
+ if bundledStatus[builderType] {
+ bundledPlugins[builderType] = struct{}{}
+ }
+ }
+
+ for _, p := range tmpl.Provisioners {
+ provisionerType := fmt.Sprintf("packer-provisioner-%s", p.Type)
+ if bundledStatus[provisionerType] {
+ bundledPlugins[provisionerType] = struct{}{}
+ }
+ }
+
+ for _, pps := range tmpl.PostProcessors {
+ for _, pp := range pps {
+ postProcessorType := fmt.Sprintf("packer-post-processor-%s", pp.Type)
+ if bundledStatus[postProcessorType] {
+ bundledPlugins[postProcessorType] = struct{}{}
+ }
+ }
+ }
+
+ return compileBundledPluginList(bundledPlugins)
+}
+
+var knownPluginPrefixes = map[string]string{
+ "amazon": "github.com/hashicorp/amazon",
+ "ansible": "github.com/hashicorp/ansible",
+ "azure": "github.com/hashicorp/azure",
+ "docker": "github.com/hashicorp/docker",
+ "googlecompute": "github.com/hashicorp/googlecompute",
+ "qemu": "github.com/hashicorp/qemu",
+ "vagrant": "github.com/hashicorp/vagrant",
+ "vmware": "github.com/hashicorp/vmware",
+ "vsphere": "github.com/hashicorp/vsphere",
+}
+
+func (m *Meta) fixRequiredPlugins(config *hcl2template.PackerConfig) string {
+ plugins := map[string]struct{}{}
+
+ for _, b := range config.Builds {
+ for _, b := range b.Sources {
+ for prefix, plugin := range knownPluginPrefixes {
+ if strings.HasPrefix(b.Type, prefix) {
+ plugins[plugin] = struct{}{}
+ }
+ }
+ }
+
+ for _, p := range b.ProvisionerBlocks {
+ for prefix, plugin := range knownPluginPrefixes {
+ if strings.HasPrefix(p.PType, prefix) {
+ plugins[plugin] = struct{}{}
+ }
+ }
+ }
+
+ for _, pps := range b.PostProcessorsLists {
+ for _, pp := range pps {
+ for prefix, plugin := range knownPluginPrefixes {
+ if strings.HasPrefix(pp.PType, prefix) {
+ plugins[plugin] = struct{}{}
+ }
+ }
+ }
+ }
+ }
+
+ for _, ds := range config.Datasources {
+ for prefix, plugin := range knownPluginPrefixes {
+ if strings.HasPrefix(ds.Type, prefix) {
+ plugins[plugin] = struct{}{}
+ }
+ }
+ }
+
+ retPlugins := make([]string, 0, len(plugins))
+ for plugin := range plugins {
+ retPlugins = append(retPlugins, plugin)
+ }
+
+ return generateRequiredPluginsBlock(retPlugins)
+}
+
+func (m *Meta) detectBundledPluginsHCL2(config *hcl2template.PackerConfig) []string {
+ bundledPlugins := map[string]struct{}{}
+
+ for _, b := range config.Builds {
+ for _, src := range b.Sources {
+ builderType := fmt.Sprintf("packer-builder-%s", src.Type)
+ if bundledStatus[builderType] {
+ bundledPlugins[builderType] = struct{}{}
+ }
+ }
+
+ for _, p := range b.ProvisionerBlocks {
+ provisionerType := fmt.Sprintf("packer-provisioner-%s", p.PType)
+ if bundledStatus[provisionerType] {
+ bundledPlugins[provisionerType] = struct{}{}
+ }
+ }
+
+ for _, pps := range b.PostProcessorsLists {
+ for _, pp := range pps {
+ postProcessorType := fmt.Sprintf("packer-post-processor-%s", pp.PType)
+ if bundledStatus[postProcessorType] {
+ bundledPlugins[postProcessorType] = struct{}{}
+ }
+ }
+ }
+ }
+
+ for _, ds := range config.Datasources {
+ dsType := fmt.Sprintf("packer-datasource-%s", ds.Type)
+ if bundledStatus[dsType] {
+ bundledPlugins[dsType] = struct{}{}
+ }
+ }
+
+ return compileBundledPluginList(bundledPlugins)
+}
diff --git a/v1.9.4/command/plugin.go b/v1.9.4/command/plugin.go
new file mode 100644
index 0000000..5069965
--- /dev/null
+++ b/v1.9.4/command/plugin.go
@@ -0,0 +1,149 @@
+//
+// This file is automatically generated by scripts/generate-plugins.go -- Do not edit!
+//
+
+package command
+
+import (
+ "fmt"
+ "log"
+ "regexp"
+ "strings"
+
+ packersdk "github.com/hashicorp/packer-plugin-sdk/packer"
+ "github.com/hashicorp/packer-plugin-sdk/plugin"
+
+ filebuilder "github.com/hashicorp/packer/builder/file"
+ nullbuilder "github.com/hashicorp/packer/builder/null"
+ hcppackerimagedatasource "github.com/hashicorp/packer/datasource/hcp-packer-image"
+ hcppackeriterationdatasource "github.com/hashicorp/packer/datasource/hcp-packer-iteration"
+ httpdatasource "github.com/hashicorp/packer/datasource/http"
+ nulldatasource "github.com/hashicorp/packer/datasource/null"
+ artificepostprocessor "github.com/hashicorp/packer/post-processor/artifice"
+ checksumpostprocessor "github.com/hashicorp/packer/post-processor/checksum"
+ compresspostprocessor "github.com/hashicorp/packer/post-processor/compress"
+ manifestpostprocessor "github.com/hashicorp/packer/post-processor/manifest"
+ shelllocalpostprocessor "github.com/hashicorp/packer/post-processor/shell-local"
+ breakpointprovisioner "github.com/hashicorp/packer/provisioner/breakpoint"
+ fileprovisioner "github.com/hashicorp/packer/provisioner/file"
+ powershellprovisioner "github.com/hashicorp/packer/provisioner/powershell"
+ shellprovisioner "github.com/hashicorp/packer/provisioner/shell"
+ shelllocalprovisioner "github.com/hashicorp/packer/provisioner/shell-local"
+ sleepprovisioner "github.com/hashicorp/packer/provisioner/sleep"
+ windowsrestartprovisioner "github.com/hashicorp/packer/provisioner/windows-restart"
+ windowsshellprovisioner "github.com/hashicorp/packer/provisioner/windows-shell"
+)
+
+type PluginCommand struct {
+ Meta
+}
+
+var Builders = map[string]packersdk.Builder{
+ "file": new(filebuilder.Builder),
+ "null": new(nullbuilder.Builder),
+}
+
+var Provisioners = map[string]packersdk.Provisioner{
+ "breakpoint": new(breakpointprovisioner.Provisioner),
+ "file": new(fileprovisioner.Provisioner),
+ "powershell": new(powershellprovisioner.Provisioner),
+ "shell": new(shellprovisioner.Provisioner),
+ "shell-local": new(shelllocalprovisioner.Provisioner),
+ "sleep": new(sleepprovisioner.Provisioner),
+ "windows-restart": new(windowsrestartprovisioner.Provisioner),
+ "windows-shell": new(windowsshellprovisioner.Provisioner),
+}
+
+var PostProcessors = map[string]packersdk.PostProcessor{
+ "artifice": new(artificepostprocessor.PostProcessor),
+ "checksum": new(checksumpostprocessor.PostProcessor),
+ "compress": new(compresspostprocessor.PostProcessor),
+ "manifest": new(manifestpostprocessor.PostProcessor),
+ "shell-local": new(shelllocalpostprocessor.PostProcessor),
+}
+
+var Datasources = map[string]packersdk.Datasource{
+ "hcp-packer-image": new(hcppackerimagedatasource.Datasource),
+ "hcp-packer-iteration": new(hcppackeriterationdatasource.Datasource),
+ "http": new(httpdatasource.Datasource),
+ "null": new(nulldatasource.Datasource),
+}
+
+var pluginRegexp = regexp.MustCompile("packer-(builder|post-processor|provisioner|datasource)-(.+)")
+
+func (c *PluginCommand) Run(args []string) int {
+ // This is an internal call (users should not call this directly) so we're
+ // not going to do much input validation. If there's a problem we'll often
+ // just crash. Error handling should be added to facilitate debugging.
+ log.Printf("args: %#v", args)
+ if len(args) != 1 {
+ c.Ui.Error("Wrong number of args")
+ return 1
+ }
+
+ // Plugin will match something like "packer-builder-amazon-ebs"
+ parts := pluginRegexp.FindStringSubmatch(args[0])
+ if len(parts) != 3 {
+ c.Ui.Error(fmt.Sprintf("Error parsing plugin argument [DEBUG]: %#v", parts))
+ return 1
+ }
+ pluginType := parts[1] // capture group 1 (builder|post-processor|provisioner)
+ pluginName := parts[2] // capture group 2 (.+)
+
+ server, err := plugin.Server()
+ if err != nil {
+ c.Ui.Error(fmt.Sprintf("Error starting plugin server: %s", err))
+ return 1
+ }
+
+ switch pluginType {
+ case "builder":
+ builder, found := Builders[pluginName]
+ if !found {
+ c.Ui.Error(fmt.Sprintf("Could not load builder: %s", pluginName))
+ return 1
+ }
+ server.RegisterBuilder(builder)
+ case "provisioner":
+ provisioner, found := Provisioners[pluginName]
+ if !found {
+ c.Ui.Error(fmt.Sprintf("Could not load provisioner: %s", pluginName))
+ return 1
+ }
+ server.RegisterProvisioner(provisioner)
+ case "post-processor":
+ postProcessor, found := PostProcessors[pluginName]
+ if !found {
+ c.Ui.Error(fmt.Sprintf("Could not load post-processor: %s", pluginName))
+ return 1
+ }
+ server.RegisterPostProcessor(postProcessor)
+ case "datasource":
+ datasource, found := Datasources[pluginName]
+ if !found {
+ c.Ui.Error(fmt.Sprintf("Could not load datasource: %s", pluginName))
+ return 1
+ }
+ server.RegisterDatasource(datasource)
+ }
+
+ server.Serve()
+
+ return 0
+}
+
+func (*PluginCommand) Help() string {
+ helpText := `
+Usage: packer plugin PLUGIN
+
+ Runs an internally-compiled version of a plugin from the packer binary.
+
+ NOTE: this is an internal command and you should not call it yourself.
+`
+
+ return strings.TrimSpace(helpText)
+}
+
+func (c *PluginCommand) Synopsis() string {
+ return "internal plugin command"
+}
diff --git a/v1.9.4/command/plugins.go b/v1.9.4/command/plugins.go
new file mode 100644
index 0000000..0b415d8
--- /dev/null
+++ b/v1.9.4/command/plugins.go
@@ -0,0 +1,35 @@
+// Copyright (c) HashiCorp, Inc.
+// SPDX-License-Identifier: MPL-2.0
+
+package command
+
+import (
+ "strings"
+
+ "github.com/mitchellh/cli"
+)
+
+type PluginsCommand struct {
+ Meta
+}
+
+func (c *PluginsCommand) Synopsis() string {
+ return "Interact with Packer plugins and catalog"
+}
+
+func (c *PluginsCommand) Help() string {
+ helpText := `
+Usage: packer plugins <subcommand> [options] [args]
+ This command groups subcommands for interacting with Packer plugins.
+
+Related but not under the "plugins" command :
+
+- "packer init <path>" will install all plugins required by a config.
+`
+
+ return strings.TrimSpace(helpText)
+}
+
+func (c *PluginsCommand) Run(args []string) int {
+ return cli.RunResultHelp
+}
diff --git a/v1.9.4/command/plugins_install.go b/v1.9.4/command/plugins_install.go
new file mode 100644
index 0000000..31fe7ec
--- /dev/null
+++ b/v1.9.4/command/plugins_install.go
@@ -0,0 +1,130 @@
+// Copyright (c) HashiCorp, Inc.
+// SPDX-License-Identifier: MPL-2.0
+
+package command
+
+import (
+ "context"
+ "crypto/sha256"
+ "fmt"
+ "runtime"
+ "strings"
+
+ "github.com/hashicorp/go-version"
+ pluginsdk "github.com/hashicorp/packer-plugin-sdk/plugin"
+ "github.com/hashicorp/packer/hcl2template/addrs"
+ "github.com/hashicorp/packer/packer"
+ plugingetter "github.com/hashicorp/packer/packer/plugin-getter"
+ "github.com/hashicorp/packer/packer/plugin-getter/github"
+ pkrversion "github.com/hashicorp/packer/version"
+ "github.com/mitchellh/cli"
+)
+
+type PluginsInstallCommand struct {
+ Meta
+}
+
+func (c *PluginsInstallCommand) Synopsis() string {
+ return "Install latest Packer plugin [matching version constraint]"
+}
+
+func (c *PluginsInstallCommand) Help() string {
+ helpText := `
+Usage: packer plugins install <plugin> [<version constraint>]
+
+ This command will install the most recent compatible Packer plugin matching
+ version constraint.
+ When the version constraint is omitted, the most recent version will be
+ installed.
+
+ Ex: packer plugins install github.com/hashicorp/happycloud v1.2.3
+`
+
+ return strings.TrimSpace(helpText)
+}
+
+func (c *PluginsInstallCommand) Run(args []string) int {
+ ctx, cleanup := handleTermInterrupt(c.Ui)
+ defer cleanup()
+
+ return c.RunContext(ctx, args)
+}
+
+func (c *PluginsInstallCommand) RunContext(buildCtx context.Context, args []string) int {
+ if len(args) < 1 || len(args) > 2 {
+ return cli.RunResultHelp
+ }
+
+ opts := plugingetter.ListInstallationsOptions{
+ FromFolders: c.Meta.CoreConfig.Components.PluginConfig.KnownPluginFolders,
+ BinaryInstallationOptions: plugingetter.BinaryInstallationOptions{
+ OS: runtime.GOOS,
+ ARCH: runtime.GOARCH,
+ APIVersionMajor: pluginsdk.APIVersionMajor,
+ APIVersionMinor: pluginsdk.APIVersionMinor,
+ Checksummers: []plugingetter.Checksummer{
+ {Type: "sha256", Hash: sha256.New()},
+ },
+ },
+ }
+
+ plugin, diags := addrs.ParsePluginSourceString(args[0])
+ if diags.HasErrors() {
+ c.Ui.Error(diags.Error())
+ return 1
+ }
+
+ // a plugin requirement that matches them all
+ pluginRequirement := plugingetter.Requirement{
+ Identifier: plugin,
+ }
+
+ if len(args) > 1 {
+ constraints, err := version.NewConstraint(args[1])
+ if err != nil {
+ c.Ui.Error(err.Error())
+ return 1
+ }
+ pluginRequirement.VersionConstraints = constraints
+ }
+
+ if runtime.GOOS == "windows" && opts.Ext == "" {
+ opts.BinaryInstallationOptions.Ext = ".exe"
+ }
+
+ getters := []plugingetter.Getter{
+ &github.Getter{
+ // In the past some terraform plugins downloads were blocked from a
+ // specific aws region by s3. Changing the user agent unblocked the
+ // downloads so having one user agent per version will help mitigate
+ // that a little more. Especially in the case someone forks this
+ // code to make it more aggressive or something.
+ // TODO: allow to set this from the config file or an environment
+ // variable.
+ UserAgent: "packer-getter-github-" + pkrversion.String(),
+ },
+ }
+
+ newInstall, err := pluginRequirement.InstallLatest(plugingetter.InstallOptions{
+ InFolders: opts.FromFolders,
+ BinaryInstallationOptions: opts.BinaryInstallationOptions,
+ Getters: getters,
+ })
+
+ if err != nil {
+ c.Ui.Error(err.Error())
+ return 1
+ }
+
+ if newInstall != nil {
+ msg := fmt.Sprintf("Installed plugin %s %s in %q", pluginRequirement.Identifier, newInstall.Version, newInstall.BinaryPath)
+ ui := &packer.ColoredUi{
+ Color: packer.UiColorCyan,
+ Ui: c.Ui,
+ }
+ ui.Say(msg)
+ return 0
+ }
+
+ return 0
+}
diff --git a/v1.9.4/command/plugins_install_test.go b/v1.9.4/command/plugins_install_test.go
new file mode 100644
index 0000000..7f34cb5
--- /dev/null
+++ b/v1.9.4/command/plugins_install_test.go
@@ -0,0 +1,181 @@
+// Copyright (c) HashiCorp, Inc.
+// SPDX-License-Identifier: MPL-2.0
+
+//go:build amd64 && (darwin || windows || linux)
+
+package command
+
+import (
+ "log"
+ "os"
+ "runtime"
+ "sort"
+ "testing"
+
+ "github.com/google/go-cmp/cmp"
+ "github.com/mitchellh/cli"
+ "golang.org/x/mod/sumdb/dirhash"
+)
+
+type testCasePluginsInstall struct {
+ name string
+ Meta Meta
+ inPluginFolder map[string]string
+ expectedPackerConfigDirHashBeforeInstall string
+ packerConfigDir string
+ pluginSourceArgs []string
+ want int
+ dirFiles []string
+ expectedPackerConfigDirHashAfterInstall string
+}
+
+func TestPluginsInstallCommand_Run(t *testing.T) {
+
+ cfg := &configDirSingleton{map[string]string{}}
+
+ tests := []testCasePluginsInstall{
+ {
+ name: "already-installed-no-op",
+ Meta: TestMetaFile(t),
+ inPluginFolder: map[string]string{
+ "github.com/sylviamoss/comment/packer-plugin-comment_v0.2.18_x5.0_darwin_amd64": "1",
+ "github.com/sylviamoss/comment/packer-plugin-comment_v0.2.18_x5.0_darwin_amd64_SHA256SUM": "6b86b273ff34fce19d6b804eff5a3f5747ada4eaa22f1d49c01e52ddb7875b4b",
+ "github.com/sylviamoss/comment/packer-plugin-comment_v0.2.18_x5.0_windows_amd64.exe": "1.exe",
+ "github.com/sylviamoss/comment/packer-plugin-comment_v0.2.18_x5.0_windows_amd64.exe_SHA256SUM": "07d8453027192ee0c4120242e6e84e2ca2328b8e0f506e2f818a1a5b82790a0b",
+ "github.com/sylviamoss/comment/packer-plugin-comment_v0.2.18_x5.0_linux_amd64": "1.out",
+ "github.com/sylviamoss/comment/packer-plugin-comment_v0.2.18_x5.0_linux_amd64_SHA256SUM": "59031c50e0dfeedfde2b4e9445754804dce3f29e4efa737eead0ca9b4f5b85a5",
+ },
+ expectedPackerConfigDirHashBeforeInstall: "h1:Q5qyAOdD43hL3CquQdVfaHpOYGf0UsZ/+wVA9Ry6cbA=",
+ packerConfigDir: cfg.dir("1_pkr_plugins_config"),
+ pluginSourceArgs: []string{"github.com/sylviamoss/comment", "v0.2.18"},
+ want: 0,
+ dirFiles: nil,
+ expectedPackerConfigDirHashAfterInstall: "h1:Q5qyAOdD43hL3CquQdVfaHpOYGf0UsZ/+wVA9Ry6cbA=",
+ },
+ {
+ name: "install-newer-version",
+ Meta: TestMetaFile(t),
+ inPluginFolder: map[string]string{
+ "github.com/sylviamoss/comment/packer-plugin-comment_v0.2.18_x5.0_darwin_amd64": "1",
+ "github.com/sylviamoss/comment/packer-plugin-comment_v0.2.18_x5.0_darwin_amd64_SHA256SUM": "6b86b273ff34fce19d6b804eff5a3f5747ada4eaa22f1d49c01e52ddb7875b4b",
+ "github.com/sylviamoss/comment/packer-plugin-comment_v0.2.18_x5.0_windows_amd64.exe": "1.exe",
+ "github.com/sylviamoss/comment/packer-plugin-comment_v0.2.18_x5.0_windows_amd64.exe_SHA256SUM": "07d8453027192ee0c4120242e6e84e2ca2328b8e0f506e2f818a1a5b82790a0b",
+ "github.com/sylviamoss/comment/packer-plugin-comment_v0.2.18_x5.0_linux_amd64": "1.out",
+ "github.com/sylviamoss/comment/packer-plugin-comment_v0.2.18_x5.0_linux_amd64_SHA256SUM": "59031c50e0dfeedfde2b4e9445754804dce3f29e4efa737eead0ca9b4f5b85a5",
+ },
+ expectedPackerConfigDirHashBeforeInstall: "h1:Q5qyAOdD43hL3CquQdVfaHpOYGf0UsZ/+wVA9Ry6cbA=",
+ packerConfigDir: cfg.dir("2_pkr_plugins_config"),
+ pluginSourceArgs: []string{"github.com/sylviamoss/comment", "v0.2.19"},
+ want: 0,
+ dirFiles: []string{
+ "github.com/sylviamoss/comment/packer-plugin-comment_v0.2.18_x5.0_darwin_amd64",
+ "github.com/sylviamoss/comment/packer-plugin-comment_v0.2.18_x5.0_darwin_amd64_SHA256SUM",
+ "github.com/sylviamoss/comment/packer-plugin-comment_v0.2.18_x5.0_linux_amd64",
+ "github.com/sylviamoss/comment/packer-plugin-comment_v0.2.18_x5.0_linux_amd64_SHA256SUM",
+ "github.com/sylviamoss/comment/packer-plugin-comment_v0.2.18_x5.0_windows_amd64.exe",
+ "github.com/sylviamoss/comment/packer-plugin-comment_v0.2.18_x5.0_windows_amd64.exe_SHA256SUM",
+ map[string]string{
+ "darwin": "github.com/sylviamoss/comment/packer-plugin-comment_v0.2.19_x5.0_darwin_amd64_SHA256SUM",
+ "linux": "github.com/sylviamoss/comment/packer-plugin-comment_v0.2.19_x5.0_linux_amd64_SHA256SUM",
+ "windows": "github.com/sylviamoss/comment/packer-plugin-comment_v0.2.19_x5.0_windows_amd64.exe_SHA256SUM",
+ }[runtime.GOOS],
+ map[string]string{
+ "darwin": "github.com/sylviamoss/comment/packer-plugin-comment_v0.2.19_x5.0_darwin_amd64",
+ "linux": "github.com/sylviamoss/comment/packer-plugin-comment_v0.2.19_x5.0_linux_amd64",
+ "windows": "github.com/sylviamoss/comment/packer-plugin-comment_v0.2.19_x5.0_windows_amd64.exe",
+ }[runtime.GOOS],
+ },
+ expectedPackerConfigDirHashAfterInstall: map[string]string{
+ "darwin": "h1:ORwcCYUx8z/5n/QvuTJo2vrgKpfJA4AxlNg1G9/BCDI=",
+ "linux": "h1:CGym0+Nd0LEANgzqL0wx/LDjRL8bYwlpZ0HajPJo/hs=",
+ "windows": "h1:ag0/C1YjP7KoEDYOiJHE0K+lhFgs0tVgjriWCXVT1fg=",
+ }[runtime.GOOS],
+ },
+ {
+ name: "unsupported-non-github-source-address",
+ Meta: TestMetaFile(t),
+ inPluginFolder: nil,
+ expectedPackerConfigDirHashBeforeInstall: "h1:47DEQpj8HBSa+/TImW+5JCeuQeRkm5NMpJWZG3hSuFU=",
+ packerConfigDir: cfg.dir("3_pkr_plugins_config"),
+ pluginSourceArgs: []string{"example.com/sylviamoss/comment", "v0.2.19"},
+ want: 1,
+ dirFiles: nil,
+ expectedPackerConfigDirHashAfterInstall: "h1:47DEQpj8HBSa+/TImW+5JCeuQeRkm5NMpJWZG3hSuFU=",
+ },
+ {
+ name: "multiple-source-addresses-provided",
+ Meta: TestMetaFile(t),
+ inPluginFolder: nil,
+ expectedPackerConfigDirHashBeforeInstall: "h1:47DEQpj8HBSa+/TImW+5JCeuQeRkm5NMpJWZG3hSuFU=",
+ packerConfigDir: cfg.dir("4_pkr_plugins_config"),
+ pluginSourceArgs: []string{"github.com/sylviamoss/comment", "v0.2.18", "github.com/sylviamoss/comment", "v0.2.19"},
+ want: cli.RunResultHelp,
+ dirFiles: nil,
+ expectedPackerConfigDirHashAfterInstall: "h1:47DEQpj8HBSa+/TImW+5JCeuQeRkm5NMpJWZG3hSuFU=",
+ },
+ {
+ name: "no-source-address-provided",
+ Meta: TestMetaFile(t),
+ inPluginFolder: nil,
+ expectedPackerConfigDirHashBeforeInstall: "h1:47DEQpj8HBSa+/TImW+5JCeuQeRkm5NMpJWZG3hSuFU=",
+ packerConfigDir: cfg.dir("5_pkr_plugins_config"),
+ pluginSourceArgs: []string{},
+ want: cli.RunResultHelp,
+ dirFiles: nil,
+ expectedPackerConfigDirHashAfterInstall: "h1:47DEQpj8HBSa+/TImW+5JCeuQeRkm5NMpJWZG3hSuFU=",
+ },
+ }
+
+ for _, tt := range tests {
+ t.Run(tt.name, func(t *testing.T) {
+ log.Printf("starting %s", tt.name)
+ log.Printf("%#v", tt)
+ t.Cleanup(func() {
+ _ = os.RemoveAll(tt.packerConfigDir)
+ })
+ t.Setenv("PACKER_CONFIG_DIR", tt.packerConfigDir)
+ createFiles(tt.packerConfigDir, tt.inPluginFolder)
+
+ hash, err := dirhash.HashDir(tt.packerConfigDir, "", dirhash.DefaultHash)
+ if err != nil {
+ t.Fatalf("HashDir: %v", err)
+ }
+ if diff := cmp.Diff(tt.expectedPackerConfigDirHashBeforeInstall, hash); diff != "" {
+ t.Errorf("unexpected dir hash before plugins install: +found -expected %s", diff)
+ }
+
+ c := &PluginsInstallCommand{
+ Meta: tt.Meta,
+ }
+
+ if err := c.CoreConfig.Components.PluginConfig.Discover(); err != nil {
+ t.Fatalf("Failed to discover plugins: %s", err)
+ }
+
+ c.CoreConfig.Components.PluginConfig.KnownPluginFolders = []string{tt.packerConfigDir}
+ if got := c.Run(tt.pluginSourceArgs); got != tt.want {
+ t.Errorf("PluginsInstallCommand.Run() = %v, want %v", got, tt.want)
+ }
+
+ if tt.dirFiles != nil {
+ dirFiles, err := dirhash.DirFiles(tt.packerConfigDir, "")
+ if err != nil {
+ t.Fatalf("DirFiles: %v", err)
+ }
+ sort.Strings(tt.dirFiles)
+ sort.Strings(dirFiles)
+ if diff := cmp.Diff(tt.dirFiles, dirFiles); diff != "" {
+ t.Errorf("found files differ: %v", diff)
+ }
+ }
+
+ hash, err = dirhash.HashDir(tt.packerConfigDir, "", dirhash.DefaultHash)
+ if err != nil {
+ t.Fatalf("HashDir: %v", err)
+ }
+ if diff := cmp.Diff(tt.expectedPackerConfigDirHashAfterInstall, hash); diff != "" {
+ t.Errorf("unexpected dir hash after plugins install: %s", diff)
+ }
+ })
+ }
+}
diff --git a/v1.9.4/command/plugins_installed.go b/v1.9.4/command/plugins_installed.go
new file mode 100644
index 0000000..bc6175a
--- /dev/null
+++ b/v1.9.4/command/plugins_installed.go
@@ -0,0 +1,80 @@
+// Copyright (c) HashiCorp, Inc.
+// SPDX-License-Identifier: MPL-2.0
+
+package command
+
+import (
+ "context"
+ "crypto/sha256"
+ "log"
+ "runtime"
+ "strings"
+
+ plugingetter "github.com/hashicorp/packer/packer/plugin-getter"
+)
+
+type PluginsInstalledCommand struct {
+ Meta
+}
+
+func (c *PluginsInstalledCommand) Synopsis() string {
+ return "List all installed Packer plugin binaries"
+}
+
+func (c *PluginsInstalledCommand) Help() string {
+ helpText := `
+Usage: packer plugins installed
+
+ This command lists all installed plugin binaries that match with the current
+ OS and architecture. Packer's API version will be ignored.
+
+`
+
+ return strings.TrimSpace(helpText)
+}
+
+func (c *PluginsInstalledCommand) Run(args []string) int {
+ ctx, cleanup := handleTermInterrupt(c.Ui)
+ defer cleanup()
+
+ return c.RunContext(ctx)
+}
+
+func (c *PluginsInstalledCommand) RunContext(buildCtx context.Context) int {
+
+ opts := plugingetter.ListInstallationsOptions{
+ FromFolders: c.Meta.CoreConfig.Components.PluginConfig.KnownPluginFolders,
+ BinaryInstallationOptions: plugingetter.BinaryInstallationOptions{
+ OS: runtime.GOOS,
+ ARCH: runtime.GOARCH,
+ Checksummers: []plugingetter.Checksummer{
+ {Type: "sha256", Hash: sha256.New()},
+ },
+ },
+ }
+
+ if runtime.GOOS == "windows" && opts.Ext == "" {
+ opts.BinaryInstallationOptions.Ext = ".exe"
+ }
+
+ log.Printf("[TRACE] init: %#v", opts)
+
+ // a plugin requirement that matches them all
+ allPlugins := plugingetter.Requirement{
+ Accessor: "",
+ VersionConstraints: nil,
+ Identifier: nil,
+ }
+
+ installations, err := allPlugins.ListInstallations(opts)
+ if err != nil {
+ c.Ui.Error(err.Error())
+ return 1
+ }
+
+ for _, installation := range installations {
+ c.Ui.Message(installation.BinaryPath)
+ }
+
+ return 0
+}
diff --git a/v1.9.4/command/plugins_remove.go b/v1.9.4/command/plugins_remove.go
new file mode 100644
index 0000000..592f7cf
--- /dev/null
+++ b/v1.9.4/command/plugins_remove.go
@@ -0,0 +1,102 @@
+// Copyright (c) HashiCorp, Inc.
+// SPDX-License-Identifier: MPL-2.0
+
+package command
+
+import (
+ "context"
+ "crypto/sha256"
+ "os"
+ "runtime"
+ "strings"
+
+ "github.com/hashicorp/go-version"
+ "github.com/hashicorp/packer/hcl2template/addrs"
+ plugingetter "github.com/hashicorp/packer/packer/plugin-getter"
+ "github.com/mitchellh/cli"
+)
+
+type PluginsRemoveCommand struct {
+ Meta
+}
+
+func (c *PluginsRemoveCommand) Synopsis() string {
+ return "Remove Packer plugins [matching a version]"
+}
+
+func (c *PluginsRemoveCommand) Help() string {
+ helpText := `
+Usage: packer plugins remove <plugin> [<version constraint>]
+
+ This command will remove all Packer plugins matching the version constraint
+ for the current OS and architecture.
+ When the version is omitted all installed versions will be removed.
+
+ Ex: packer plugins remove github.com/hashicorp/happycloud v1.2.3
+`
+
+ return strings.TrimSpace(helpText)
+}
+
+func (c *PluginsRemoveCommand) Run(args []string) int {
+ ctx, cleanup := handleTermInterrupt(c.Ui)
+ defer cleanup()
+
+ return c.RunContext(ctx, args)
+}
+
+func (c *PluginsRemoveCommand) RunContext(buildCtx context.Context, args []string) int {
+ if len(args) < 1 || len(args) > 2 {
+ return cli.RunResultHelp
+ }
+
+ opts := plugingetter.ListInstallationsOptions{
+ FromFolders: c.Meta.CoreConfig.Components.PluginConfig.KnownPluginFolders,
+ BinaryInstallationOptions: plugingetter.BinaryInstallationOptions{
+ OS: runtime.GOOS,
+ ARCH: runtime.GOARCH,
+ Checksummers: []plugingetter.Checksummer{
+ {Type: "sha256", Hash: sha256.New()},
+ },
+ },
+ }
+
+ if runtime.GOOS == "windows" && opts.Ext == "" {
+ opts.BinaryInstallationOptions.Ext = ".exe"
+ }
+
+ plugin, diags := addrs.ParsePluginSourceString(args[0])
+ if diags.HasErrors() {
+ c.Ui.Error(diags.Error())
+ return 1
+ }
+
+ // a plugin requirement that matches them all
+ pluginRequirement := plugingetter.Requirement{
+ Identifier: plugin,
+ }
+
+ if len(args) > 1 {
+ constraints, err := version.NewConstraint(args[1])
+ if err != nil {
+ c.Ui.Error(err.Error())
+ return 1
+ }
+ pluginRequirement.VersionConstraints = constraints
+ }
+
+ installations, err := pluginRequirement.ListInstallations(opts)
+ if err != nil {
+ c.Ui.Error(err.Error())
+ return 1
+ }
+ for _, installation := range installations {
+ if err := os.Remove(installation.BinaryPath); err != nil {
+ c.Ui.Error(err.Error())
+ return 1
+ }
+ c.Ui.Message(installation.BinaryPath)
+ }
+
+ return 0
+}
diff --git a/v1.9.4/command/plugins_remove_test.go b/v1.9.4/command/plugins_remove_test.go
new file mode 100644
index 0000000..83b2463
--- /dev/null
+++ b/v1.9.4/command/plugins_remove_test.go
@@ -0,0 +1,224 @@
+// Copyright (c) HashiCorp, Inc.
+// SPDX-License-Identifier: MPL-2.0
+
+//go:build amd64 && (darwin || windows || linux)
+
+package command
+
+import (
+ "log"
+ "os"
+ "runtime"
+ "sort"
+ "testing"
+
+ "github.com/google/go-cmp/cmp"
+ "golang.org/x/mod/sumdb/dirhash"
+)
+
+type testCasePluginsRemove struct {
+ name string
+ Meta Meta
+ inPluginFolder map[string]string
+ expectedPackerConfigDirHashBeforeRemove string
+ packerConfigDir string
+ pluginSourceArgs []string
+ want int
+ dirFiles []string
+ expectedPackerConfigDirHashAfterRemove string
+}
+
+func TestPluginsRemoveCommand_Run(t *testing.T) {
+
+ cfg := &configDirSingleton{map[string]string{}}
+
+ tests := []testCasePluginsRemove{
+ {
+ name: "version-not-installed-no-op",
+ Meta: TestMetaFile(t),
+ inPluginFolder: map[string]string{
+ "github.com/sylviamoss/comment/packer-plugin-comment_v0.2.18_x5.0_darwin_amd64": "1",
+ "github.com/sylviamoss/comment/packer-plugin-comment_v0.2.18_x5.0_darwin_amd64_SHA256SUM": "6b86b273ff34fce19d6b804eff5a3f5747ada4eaa22f1d49c01e52ddb7875b4b",
+ "github.com/sylviamoss/comment/packer-plugin-comment_v0.2.18_x5.0_windows_amd64.exe": "1.exe",
+ "github.com/sylviamoss/comment/packer-plugin-comment_v0.2.18_x5.0_windows_amd64.exe_SHA256SUM": "07d8453027192ee0c4120242e6e84e2ca2328b8e0f506e2f818a1a5b82790a0b",
+ "github.com/sylviamoss/comment/packer-plugin-comment_v0.2.18_x5.0_linux_amd64": "1.out",
+ "github.com/sylviamoss/comment/packer-plugin-comment_v0.2.18_x5.0_linux_amd64_SHA256SUM": "59031c50e0dfeedfde2b4e9445754804dce3f29e4efa737eead0ca9b4f5b85a5",
+ },
+ expectedPackerConfigDirHashBeforeRemove: "h1:Q5qyAOdD43hL3CquQdVfaHpOYGf0UsZ/+wVA9Ry6cbA=",
+ packerConfigDir: cfg.dir("1_pkr_plugins_config"),
+ pluginSourceArgs: []string{"github.com/sylviamoss/comment", "v0.2.19"},
+ want: 0,
+ dirFiles: nil,
+ expectedPackerConfigDirHashAfterRemove: "h1:Q5qyAOdD43hL3CquQdVfaHpOYGf0UsZ/+wVA9Ry6cbA=",
+ },
+ {
+ name: "remove-specific-version",
+ Meta: TestMetaFile(t),
+ inPluginFolder: map[string]string{
+ "github.com/sylviamoss/comment/packer-plugin-comment_v0.2.18_x5.0_darwin_amd64": "1",
+ "github.com/sylviamoss/comment/packer-plugin-comment_v0.2.18_x5.0_darwin_amd64_SHA256SUM": "6b86b273ff34fce19d6b804eff5a3f5747ada4eaa22f1d49c01e52ddb7875b4b",
+ "github.com/sylviamoss/comment/packer-plugin-comment_v0.2.18_x5.0_windows_amd64.exe": "1.exe",
+ "github.com/sylviamoss/comment/packer-plugin-comment_v0.2.18_x5.0_windows_amd64.exe_SHA256SUM": "07d8453027192ee0c4120242e6e84e2ca2328b8e0f506e2f818a1a5b82790a0b",
+ "github.com/sylviamoss/comment/packer-plugin-comment_v0.2.18_x5.0_linux_amd64": "1.out",
+ "github.com/sylviamoss/comment/packer-plugin-comment_v0.2.18_x5.0_linux_amd64_SHA256SUM": "59031c50e0dfeedfde2b4e9445754804dce3f29e4efa737eead0ca9b4f5b85a5",
+ },
+ expectedPackerConfigDirHashBeforeRemove: "h1:Q5qyAOdD43hL3CquQdVfaHpOYGf0UsZ/+wVA9Ry6cbA=",
+ packerConfigDir: cfg.dir("2_pkr_plugins_config"),
+ pluginSourceArgs: []string{"github.com/sylviamoss/comment", "v0.2.18"},
+ want: 0,
+ dirFiles: map[string][]string{
+ "darwin": {
+ "github.com/sylviamoss/comment/packer-plugin-comment_v0.2.18_x5.0_darwin_amd64_SHA256SUM",
+ "github.com/sylviamoss/comment/packer-plugin-comment_v0.2.18_x5.0_linux_amd64",
+ "github.com/sylviamoss/comment/packer-plugin-comment_v0.2.18_x5.0_linux_amd64_SHA256SUM",
+ "github.com/sylviamoss/comment/packer-plugin-comment_v0.2.18_x5.0_windows_amd64.exe",
+ "github.com/sylviamoss/comment/packer-plugin-comment_v0.2.18_x5.0_windows_amd64.exe_SHA256SUM",
+ },
+ "linux": {
+ "github.com/sylviamoss/comment/packer-plugin-comment_v0.2.18_x5.0_darwin_amd64",
+ "github.com/sylviamoss/comment/packer-plugin-comment_v0.2.18_x5.0_darwin_amd64_SHA256SUM",
+ "github.com/sylviamoss/comment/packer-plugin-comment_v0.2.18_x5.0_linux_amd64_SHA256SUM",
+ "github.com/sylviamoss/comment/packer-plugin-comment_v0.2.18_x5.0_windows_amd64.exe",
+ "github.com/sylviamoss/comment/packer-plugin-comment_v0.2.18_x5.0_windows_amd64.exe_SHA256SUM",
+ },
+ "windows": {
+ "github.com/sylviamoss/comment/packer-plugin-comment_v0.2.18_x5.0_darwin_amd64",
+ "github.com/sylviamoss/comment/packer-plugin-comment_v0.2.18_x5.0_darwin_amd64_SHA256SUM",
+ "github.com/sylviamoss/comment/packer-plugin-comment_v0.2.18_x5.0_linux_amd64",
+ "github.com/sylviamoss/comment/packer-plugin-comment_v0.2.18_x5.0_linux_amd64_SHA256SUM",
+ "github.com/sylviamoss/comment/packer-plugin-comment_v0.2.18_x5.0_windows_amd64.exe_SHA256SUM",
+ },
+ }[runtime.GOOS],
+ expectedPackerConfigDirHashAfterRemove: map[string]string{
+ "darwin": "h1:IMsWPgJZzRhn80t78zE45003gFKN6EXq562/wjaCrKE=",
+ "linux": "h1:Ez7SU1GZLvNGJmoTm9PeFIwHv9fvEgzZAZTMl6874iM=",
+ "windows": "h1:RrXlhy9tG9Bi3c2aOzjx/FLLyVNQolcY+MAr4V1etRI=",
+ }[runtime.GOOS],
+ },
+ {
+ name: "remove-all-installed-versions",
+ Meta: TestMetaFile(t),
+ inPluginFolder: map[string]string{
+ "github.com/sylviamoss/comment/packer-plugin-comment_v0.2.18_x5.0_darwin_amd64": "1",
+ "github.com/sylviamoss/comment/packer-plugin-comment_v0.2.18_x5.0_darwin_amd64_SHA256SUM": "6b86b273ff34fce19d6b804eff5a3f5747ada4eaa22f1d49c01e52ddb7875b4b",
+ "github.com/sylviamoss/comment/packer-plugin-comment_v0.2.19_x5.0_darwin_amd64": "1",
+ "github.com/sylviamoss/comment/packer-plugin-comment_v0.2.19_x5.0_darwin_amd64_SHA256SUM": "6b86b273ff34fce19d6b804eff5a3f5747ada4eaa22f1d49c01e52ddb7875b4b",
+ "github.com/sylviamoss/comment/packer-plugin-comment_v0.2.18_x5.0_windows_amd64.exe": "1.exe",
+ "github.com/sylviamoss/comment/packer-plugin-comment_v0.2.18_x5.0_windows_amd64.exe_SHA256SUM": "07d8453027192ee0c4120242e6e84e2ca2328b8e0f506e2f818a1a5b82790a0b",
+ "github.com/sylviamoss/comment/packer-plugin-comment_v0.2.19_x5.0_windows_amd64.exe": "1.exe",
+ "github.com/sylviamoss/comment/packer-plugin-comment_v0.2.19_x5.0_windows_amd64.exe_SHA256SUM": "07d8453027192ee0c4120242e6e84e2ca2328b8e0f506e2f818a1a5b82790a0b",
+ "github.com/sylviamoss/comment/packer-plugin-comment_v0.2.18_x5.0_linux_amd64": "1.out",
+ "github.com/sylviamoss/comment/packer-plugin-comment_v0.2.18_x5.0_linux_amd64_SHA256SUM": "59031c50e0dfeedfde2b4e9445754804dce3f29e4efa737eead0ca9b4f5b85a5",
+ "github.com/sylviamoss/comment/packer-plugin-comment_v0.2.19_x5.0_linux_amd64": "1.out",
+ "github.com/sylviamoss/comment/packer-plugin-comment_v0.2.19_x5.0_linux_amd64_SHA256SUM": "59031c50e0dfeedfde2b4e9445754804dce3f29e4efa737eead0ca9b4f5b85a5",
+ },
+ expectedPackerConfigDirHashBeforeRemove: "h1:IEvr6c46+Uk776Hnzy04PuXqnyHGKnnEvIJ713cv0iU=",
+ packerConfigDir: cfg.dir("2_pkr_plugins_config"),
+ pluginSourceArgs: []string{"github.com/sylviamoss/comment"},
+ want: 0,
+ dirFiles: map[string][]string{
+ "darwin": {
+ "github.com/sylviamoss/comment/packer-plugin-comment_v0.2.18_x5.0_darwin_amd64_SHA256SUM",
+ "github.com/sylviamoss/comment/packer-plugin-comment_v0.2.19_x5.0_darwin_amd64_SHA256SUM",
+ "github.com/sylviamoss/comment/packer-plugin-comment_v0.2.18_x5.0_linux_amd64",
+ "github.com/sylviamoss/comment/packer-plugin-comment_v0.2.18_x5.0_linux_amd64_SHA256SUM",
+ "github.com/sylviamoss/comment/packer-plugin-comment_v0.2.19_x5.0_linux_amd64",
+ "github.com/sylviamoss/comment/packer-plugin-comment_v0.2.19_x5.0_linux_amd64_SHA256SUM",
+ "github.com/sylviamoss/comment/packer-plugin-comment_v0.2.18_x5.0_windows_amd64.exe",
+ "github.com/sylviamoss/comment/packer-plugin-comment_v0.2.18_x5.0_windows_amd64.exe_SHA256SUM",
+ "github.com/sylviamoss/comment/packer-plugin-comment_v0.2.19_x5.0_windows_amd64.exe",
+ "github.com/sylviamoss/comment/packer-plugin-comment_v0.2.19_x5.0_windows_amd64.exe_SHA256SUM",
+ },
+ "linux": {
+ "github.com/sylviamoss/comment/packer-plugin-comment_v0.2.18_x5.0_darwin_amd64",
+ "github.com/sylviamoss/comment/packer-plugin-comment_v0.2.18_x5.0_darwin_amd64_SHA256SUM",
+ "github.com/sylviamoss/comment/packer-plugin-comment_v0.2.19_x5.0_darwin_amd64",
+ "github.com/sylviamoss/comment/packer-plugin-comment_v0.2.19_x5.0_darwin_amd64_SHA256SUM",
+ "github.com/sylviamoss/comment/packer-plugin-comment_v0.2.18_x5.0_linux_amd64_SHA256SUM",
+ "github.com/sylviamoss/comment/packer-plugin-comment_v0.2.19_x5.0_linux_amd64_SHA256SUM",
+ "github.com/sylviamoss/comment/packer-plugin-comment_v0.2.18_x5.0_windows_amd64.exe",
+ "github.com/sylviamoss/comment/packer-plugin-comment_v0.2.18_x5.0_windows_amd64.exe_SHA256SUM",
+ "github.com/sylviamoss/comment/packer-plugin-comment_v0.2.19_x5.0_windows_amd64.exe",
+ "github.com/sylviamoss/comment/packer-plugin-comment_v0.2.19_x5.0_windows_amd64.exe_SHA256SUM",
+ },
+ "windows": {
+ "github.com/sylviamoss/comment/packer-plugin-comment_v0.2.18_x5.0_darwin_amd64",
+ "github.com/sylviamoss/comment/packer-plugin-comment_v0.2.18_x5.0_darwin_amd64_SHA256SUM",
+ "github.com/sylviamoss/comment/packer-plugin-comment_v0.2.19_x5.0_darwin_amd64",
+ "github.com/sylviamoss/comment/packer-plugin-comment_v0.2.19_x5.0_darwin_amd64_SHA256SUM",
+ "github.com/sylviamoss/comment/packer-plugin-comment_v0.2.18_x5.0_linux_amd64",
+ "github.com/sylviamoss/comment/packer-plugin-comment_v0.2.18_x5.0_linux_amd64_SHA256SUM",
+ "github.com/sylviamoss/comment/packer-plugin-comment_v0.2.19_x5.0_linux_amd64",
+ "github.com/sylviamoss/comment/packer-plugin-comment_v0.2.19_x5.0_linux_amd64_SHA256SUM",
+ "github.com/sylviamoss/comment/packer-plugin-comment_v0.2.18_x5.0_windows_amd64.exe_SHA256SUM",
+ "github.com/sylviamoss/comment/packer-plugin-comment_v0.2.19_x5.0_windows_amd64.exe_SHA256SUM",
+ },
+ }[runtime.GOOS],
+ expectedPackerConfigDirHashAfterRemove: map[string]string{
+ "darwin": "h1:FBBGQ1SKngN9PvF98awv8TZcKaS+CKzJmQoS7vuSXqY=",
+ "linux": "h1:F8lN4Q3sv45ig8r1BLOS/wFuQQy6tSfmuIJf3fnbD5k=",
+ "windows": "h1:DOfH6WR1eJNLJcaL8ar8j1xu2WB7Jcn6oG7LGEvNBZI=",
+ }[runtime.GOOS],
+ },
+ {
+ name: "no-installed-binaries",
+ Meta: TestMetaFile(t),
+ inPluginFolder: nil,
+ expectedPackerConfigDirHashBeforeRemove: "h1:47DEQpj8HBSa+/TImW+5JCeuQeRkm5NMpJWZG3hSuFU=",
+ packerConfigDir: cfg.dir("3_pkr_plugins_config"),
+ pluginSourceArgs: []string{"example.com/sylviamoss/comment", "v0.2.19"},
+ want: 0,
+ dirFiles: nil,
+ expectedPackerConfigDirHashAfterRemove: "h1:47DEQpj8HBSa+/TImW+5JCeuQeRkm5NMpJWZG3hSuFU=",
+ },
+ }
+
+ for _, tt := range tests {
+ t.Run(tt.name, func(t *testing.T) {
+ log.Printf("starting %s", tt.name)
+ log.Printf("%#v", tt)
+ t.Cleanup(func() {
+ _ = os.RemoveAll(tt.packerConfigDir)
+ })
+ t.Setenv("PACKER_CONFIG_DIR", tt.packerConfigDir)
+ createFiles(tt.packerConfigDir, tt.inPluginFolder)
+
+ hash, err := dirhash.HashDir(tt.packerConfigDir, "", dirhash.DefaultHash)
+ if err != nil {
+ t.Fatalf("HashDir: %v", err)
+ }
+ if diff := cmp.Diff(tt.expectedPackerConfigDirHashBeforeRemove, hash); diff != "" {
+ t.Errorf("unexpected dir hash before plugins remove: +found -expected %s", diff)
+ }
+
+ c := &PluginsRemoveCommand{
+ Meta: tt.Meta,
+ }
+
+ c.CoreConfig.Components.PluginConfig.KnownPluginFolders = []string{tt.packerConfigDir}
+ if got := c.Run(tt.pluginSourceArgs); got != tt.want {
+ t.Errorf("PluginsRemoveCommand.Run() = %v, want %v", got, tt.want)
+ }
+
+ if tt.dirFiles != nil {
+ dirFiles, err := dirhash.DirFiles(tt.packerConfigDir, "")
+ if err != nil {
+ t.Fatalf("DirFiles: %v", err)
+ }
+ sort.Strings(tt.dirFiles)
+ sort.Strings(dirFiles)
+ if diff := cmp.Diff(tt.dirFiles, dirFiles); diff != "" {
+ t.Errorf("found files differ: %v", diff)
+ }
+ }
+
+ hash, err = dirhash.HashDir(tt.packerConfigDir, "", dirhash.DefaultHash)
+ if err != nil {
+ t.Fatalf("HashDir: %v", err)
+ }
+ if diff := cmp.Diff(tt.expectedPackerConfigDirHashAfterRemove, hash); diff != "" {
+ t.Errorf("unexpected dir hash after plugins remove: %s", diff)
+ }
+ })
+ }
+}
diff --git a/v1.9.4/command/plugins_required.go b/v1.9.4/command/plugins_required.go
new file mode 100644
index 0000000..d484322
--- /dev/null
+++ b/v1.9.4/command/plugins_required.go
@@ -0,0 +1,121 @@
+// Copyright (c) HashiCorp, Inc.
+// SPDX-License-Identifier: MPL-2.0
+
+package command
+
+import (
+ "context"
+ "crypto/sha256"
+ "fmt"
+ "runtime"
+ "strings"
+
+ pluginsdk "github.com/hashicorp/packer-plugin-sdk/plugin"
+ plugingetter "github.com/hashicorp/packer/packer/plugin-getter"
+ "github.com/mitchellh/cli"
+)
+
+type PluginsRequiredCommand struct {
+ Meta
+}
+
+func (c *PluginsRequiredCommand) Synopsis() string {
+ return "List plugins required by a config"
+}
+
+func (c *PluginsRequiredCommand) Help() string {
+ helpText := `
+Usage: packer plugins required <path>
+
+ This command will list every Packer plugin required by a Packer config, in
+ packer.required_plugins blocks. All binaries matching the required version
+ constrain and the current OS and Architecture will be listed. The most recent
+ version (and the first of the list) will be the one picked by Packer during a
+ build.
+
+ Ex: packer plugins required require.pkr.hcl
+ Ex: packer plugins required path/to/folder/
+`
+
+ return strings.TrimSpace(helpText)
+}
+
+func (c *PluginsRequiredCommand) Run(args []string) int {
+ ctx, cleanup := handleTermInterrupt(c.Ui)
+ defer cleanup()
+
+ cfg, ret := c.ParseArgs(args)
+ if ret != 0 {
+ return ret
+ }
+
+ return c.RunContext(ctx, cfg)
+}
+
+func (c *PluginsRequiredCommand) ParseArgs(args []string) (*PluginsRequiredArgs, int) {
+ var cfg PluginsRequiredArgs
+ flags := c.Meta.FlagSet("plugins required", 0)
+ flags.Usage = func() { c.Ui.Say(c.Help()) }
+ cfg.AddFlagSets(flags)
+ if err := flags.Parse(args); err != nil {
+ return &cfg, 1
+ }
+
+ args = flags.Args()
+ if len(args) != 1 {
+ return &cfg, cli.RunResultHelp
+ }
+ cfg.Path = args[0]
+ return &cfg, 0
+}
+
+func (c *PluginsRequiredCommand) RunContext(buildCtx context.Context, cla *PluginsRequiredArgs) int {
+
+ packerStarter, ret := c.GetConfig(&cla.MetaArgs)
+ if ret != 0 {
+ return ret
+ }
+
+ // Get plugins requirements
+ reqs, diags := packerStarter.PluginRequirements()
+ ret = writeDiags(c.Ui, nil, diags)
+ if ret != 0 {
+ return ret
+ }
+
+ opts := plugingetter.ListInstallationsOptions{
+ FromFolders: c.Meta.CoreConfig.Components.PluginConfig.KnownPluginFolders,
+ BinaryInstallationOptions: plugingetter.BinaryInstallationOptions{
+ OS: runtime.GOOS,
+ ARCH: runtime.GOARCH,
+ APIVersionMajor: pluginsdk.APIVersionMajor,
+ APIVersionMinor: pluginsdk.APIVersionMinor,
+ Checksummers: []plugingetter.Checksummer{
+ {Type: "sha256", Hash: sha256.New()},
+ },
+ },
+ }
+
+ for _, pluginRequirement := range reqs {
+ s := fmt.Sprintf("%s %s %q", pluginRequirement.Accessor, pluginRequirement.Identifier.String(), pluginRequirement.VersionConstraints.String())
+ installs, err := pluginRequirement.ListInstallations(opts)
+ if err != nil {
+ c.Ui.Error(err.Error())
+ return 1
+ }
+ for _, install := range installs {
+ s += fmt.Sprintf(" %s", install.BinaryPath)
+ }
+ c.Ui.Message(s)
+ }
+
+ if len(reqs) == 0 {
+ c.Ui.Message(`
+No plugins requirement found, make sure you reference a Packer config
+containing a packer.required_plugins block. See
+https://www.packer.io/docs/templates/hcl_templates/blocks/packer
+for more info.`)
+ }
+
+ return 0
+}
diff --git a/v1.9.4/command/signal.go b/v1.9.4/command/signal.go
new file mode 100644
index 0000000..5980192
--- /dev/null
+++ b/v1.9.4/command/signal.go
@@ -0,0 +1,40 @@
+// Copyright (c) HashiCorp, Inc.
+// SPDX-License-Identifier: MPL-2.0
+
+package command
+
+import (
+ "context"
+ "fmt"
+ "os"
+ "os/signal"
+ "syscall"
+
+ packersdk "github.com/hashicorp/packer-plugin-sdk/packer"
+)
+
+func handleTermInterrupt(ui packersdk.Ui) (context.Context, func()) {
+ ctx, cancelCtx := context.WithCancel(context.Background())
+ // Handle interrupts for this build
+ sigCh := make(chan os.Signal, 1)
+ signal.Notify(sigCh, os.Interrupt, syscall.SIGTERM)
+ cleanup := func() {
+ cancelCtx()
+ signal.Stop(sigCh)
+ close(sigCh)
+ }
+ go func() {
+ select {
+ case sig := <-sigCh:
+ if sig == nil {
+ // context got cancelled and this closed chan probably
+ // triggered first
+ return
+ }
+ ui.Error(fmt.Sprintf("Cancelling build after receiving %s", sig))
+ cancelCtx()
+ case <-ctx.Done():
+ }
+ }()
+ return ctx, cleanup
+}
diff --git a/v1.9.4/command/test-fixtures/build-name-and-type/all.json b/v1.9.4/command/test-fixtures/build-name-and-type/all.json
new file mode 100644
index 0000000..e0150f9
--- /dev/null
+++ b/v1.9.4/command/test-fixtures/build-name-and-type/all.json
@@ -0,0 +1,21 @@
+{
+ "builders": [
+ {
+ "name": "test",
+ "communicator": "none",
+ "type": "null"
+ },
+ {
+ "name": "potato",
+ "communicator": "none",
+ "type": "null"
+ }
+ ],
+ "post-processors": [
+ {
+ "type": "manifest",
+ "output": "manifest.json",
+ "strip_time": true
+ }
+ ]
+}
diff --git a/v1.9.4/command/test-fixtures/build-name-and-type/all.pkr.hcl b/v1.9.4/command/test-fixtures/build-name-and-type/all.pkr.hcl
new file mode 100644
index 0000000..b0dbf2b
--- /dev/null
+++ b/v1.9.4/command/test-fixtures/build-name-and-type/all.pkr.hcl
@@ -0,0 +1,25 @@
+source "null" "test" {
+ communicator = "none"
+}
+
+source "null" "potato" {
+ communicator = "none"
+}
+
+build {
+ sources = [
+ "sources.null.test",
+ "sources.null.potato",
+ ]
+
+ provisioner "shell-local" {
+ inline = [
+ "echo '' > ${source.type}.${source.name}.txt"
+ ]
+ }
+
+ post-processor "manifest" {
+ output = "manifest.json"
+ strip_time = true
+ }
+}
diff --git a/v1.9.4/command/test-fixtures/build-name-and-type/buildname.pkr.hcl b/v1.9.4/command/test-fixtures/build-name-and-type/buildname.pkr.hcl
new file mode 100644
index 0000000..a77b26f
--- /dev/null
+++ b/v1.9.4/command/test-fixtures/build-name-and-type/buildname.pkr.hcl
@@ -0,0 +1,16 @@
+source "null" "pizza" {
+ communicator = "none"
+}
+
+build {
+ name = "pineapple"
+ sources = [
+ "sources.null.pizza",
+ ]
+
+ provisioner "shell-local" {
+ inline = [
+ "echo '' > ${build.name}.${source.name}.txt"
+ ]
+ }
+}
diff --git a/v1.9.4/command/test-fixtures/build-only/not-found.json b/v1.9.4/command/test-fixtures/build-only/not-found.json
new file mode 100644
index 0000000..4f327d8
--- /dev/null
+++ b/v1.9.4/command/test-fixtures/build-only/not-found.json
@@ -0,0 +1,41 @@
+{
+ "builders": [
+ {
+ "name": "chocolate",
+ "type": "file",
+ "content": "chocolate",
+ "target": "chocolate.txt"
+ },
+ {
+ "name": "vanilla",
+ "type": "non-existing",
+ "content": "vanilla",
+ "target": "vanilla.txt"
+ }
+ ],
+ "post-processors": [
+ [
+ {
+ "only": [
+ "vanilla"
+ ],
+ "name": "tomato",
+ "type": "shell-local",
+ "inline": [
+ "echo tomato > tomato.txt"
+ ]
+ }
+ ],
+ [
+ {
+ "only": [
+ "chocolate"
+ ],
+ "type": "shell-local",
+ "inline": [
+ "echo unnamed > unnamed.txt"
+ ]
+ }
+ ]
+ ]
+}
\ No newline at end of file
diff --git a/v1.9.4/command/test-fixtures/build-only/template.json b/v1.9.4/command/test-fixtures/build-only/template.json
new file mode 100644
index 0000000..03982a1
--- /dev/null
+++ b/v1.9.4/command/test-fixtures/build-only/template.json
@@ -0,0 +1,67 @@
+{
+ "builders": [
+ {
+ "name": "chocolate",
+ "type": "file",
+ "content": "chocolate",
+ "target": "chocolate.txt"
+ },
+ {
+ "name": "vanilla",
+ "type": "file",
+ "content": "vanilla",
+ "target": "vanilla.txt"
+ },
+ {
+ "name": "cherry",
+ "type": "file",
+ "content": "cherry",
+ "target": "cherry.txt"
+ }
+ ],
+ "post-processors": [
+ [
+ {
+ "name": "apple",
+ "type": "shell-local",
+ "inline": [ "echo apple > apple.txt" ]
+ },
+ {
+ "name": "peach",
+ "type": "shell-local",
+ "inline": [ "echo peach > peach.txt" ]
+ }
+ ],
+ [
+ {
+ "name": "pear",
+ "type": "shell-local",
+ "inline": [ "echo pear > pear.txt" ]
+ },
+ {
+ "name": "banana",
+ "type": "shell-local",
+ "inline": [ "echo pear > banana.txt" ]
+ }
+ ],
+ [
+ {
+ "only": [
+ "vanilla"
+ ],
+ "name": "tomato",
+ "type": "shell-local",
+ "inline": [ "echo tomato > tomato.txt" ]
+ }
+ ],
+ [
+ {
+ "only": [
+ "chocolate"
+ ],
+ "type": "shell-local",
+ "inline": [ "echo unnamed > unnamed.txt" ]
+ }
+ ]
+ ]
+}
\ No newline at end of file
diff --git a/v1.9.4/command/test-fixtures/build-only/template.pkr.hcl b/v1.9.4/command/test-fixtures/build-only/template.pkr.hcl
new file mode 100644
index 0000000..934d028
--- /dev/null
+++ b/v1.9.4/command/test-fixtures/build-only/template.pkr.hcl
@@ -0,0 +1,54 @@
+source "file" "chocolate" {
+ content = "chocolate"
+ target = "chocolate.txt"
+}
+
+source "file" "vanilla" {
+ content = "vanilla"
+ target = "vanilla.txt"
+}
+
+source "file" "cherry" {
+ content = "cherry"
+ target = "cherry.txt"
+}
+
+
+build {
+ sources = [
+ "sources.file.chocolate",
+ "sources.file.vanilla",
+ "sources.file.cherry",
+ ]
+
+ post-processor "shell-local" {
+ name = "apple"
+ inline = [ "echo apple > apple.txt" ]
+ }
+
+ post-processor "shell-local" {
+ name = "peach"
+ inline = [ "echo apple > peach.txt" ]
+ }
+
+ post-processor "shell-local" {
+ name = "pear"
+ inline = [ "echo apple > pear.txt" ]
+ }
+
+ post-processor "shell-local" {
+ name = "banana"
+ inline = [ "echo apple > banana.txt" ]
+ }
+
+ post-processor "shell-local" {
+ only = ["file.vanilla"]
+ name = "tomato"
+ inline = [ "echo apple > tomato.txt" ]
+ }
+
+ post-processor "shell-local" {
+ only = ["file.chocolate"]
+ inline = [ "echo apple > unnamed.txt" ]
+ }
+}
diff --git a/v1.9.4/command/test-fixtures/build-only/template.pkr.json b/v1.9.4/command/test-fixtures/build-only/template.pkr.json
new file mode 100644
index 0000000..c289bd6
--- /dev/null
+++ b/v1.9.4/command/test-fixtures/build-only/template.pkr.json
@@ -0,0 +1,83 @@
+{
+ "source": {
+ "file": {
+ "chocolate": {
+ "content": "chocolate",
+ "target": "chocolate.txt"
+ }
+ },
+ "file": {
+ "vanilla": {
+ "content": "vanilla",
+ "target": "vanilla.txt"
+ }
+ },
+ "file": {
+ "cherry": {
+ "content": "cherry",
+ "target": "cherry.txt"
+ }
+ }
+ },
+ "build": {
+ "sources": [
+ "sources.file.chocolate",
+ "sources.file.vanilla",
+ "sources.file.cherry"
+ ],
+ "provisioner": [
+ {
+ "shell-local": {
+ "name": "apple",
+ "inline": [
+ "echo apple > apple.txt"
+ ]
+ }
+ }
+ ],
+ "post-processor": [
+ {
+ "shell-local": {
+ "name": "peach",
+ "inline": [
+ "echo peach > peach.txt"
+ ]
+ }
+ },
+ {
+ "shell-local": {
+ "name": "pear",
+ "inline": [
+ "echo pear > pear.txt"
+ ]
+ }
+ },
+ {
+ "shell-local": {
+ "name": "banana",
+ "inline": [
+ "echo banana > banana.txt"
+ ]
+ }
+ },
+ {
+ "shell-local": {
+ "name": "tomato",
+ "inline": [
+ "echo tomato > tomato.txt"
+ ]
+ }
+ },
+ {
+ "shell-local": {
+ "only": [
+ "sources.file.chocolate"
+ ],
+ "inline": [
+ "echo unnamed > unnamed.txt"
+ ]
+ }
+ }
+ ]
+ }
+}
diff --git a/v1.9.4/command/test-fixtures/build-variable-sharing/template.json b/v1.9.4/command/test-fixtures/build-variable-sharing/template.json
new file mode 100644
index 0000000..ac1c410
--- /dev/null
+++ b/v1.9.4/command/test-fixtures/build-variable-sharing/template.json
@@ -0,0 +1,25 @@
+{
+ "builders": [
+ {
+ "name": "chocolate",
+ "type": "null",
+ "communicator": "none"
+ }
+ ],
+ "provisioners": [
+ {
+ "type": "shell-local",
+ "inline": [
+ "echo hi > provisioner.{{ build `ID`}}.txt"
+ ]
+ }
+ ],
+ "post-processors": [
+ {
+ "type": "shell-local",
+ "inline": [
+ "echo hi > post-processor.{{ build `ID`}}.txt"
+ ]
+ }
+ ]
+}
\ No newline at end of file
diff --git a/v1.9.4/command/test-fixtures/cleanup-script/template.json b/v1.9.4/command/test-fixtures/cleanup-script/template.json
new file mode 100644
index 0000000..eea3e7e
--- /dev/null
+++ b/v1.9.4/command/test-fixtures/cleanup-script/template.json
@@ -0,0 +1,18 @@
+{
+ "builders": [
+ {
+ "type": "null",
+ "communicator": "none"
+ }
+ ],
+ "provisioners": [
+ {
+ "type": "shell-local",
+ "inline": ["exit 2"]
+ }
+ ],
+ "error-cleanup-provisioner": {
+ "type": "shell-local",
+ "inline": ["echo 'rubber ducky'> ducky.txt"]
+ }
+}
\ No newline at end of file
diff --git a/v1.9.4/command/test-fixtures/fix-invalid/template.json b/v1.9.4/command/test-fixtures/fix-invalid/template.json
new file mode 100644
index 0000000..ea50c5d
--- /dev/null
+++ b/v1.9.4/command/test-fixtures/fix-invalid/template.json
@@ -0,0 +1,3 @@
+{
+ "hello": "world"
+}
diff --git a/v1.9.4/command/test-fixtures/fix/template.json b/v1.9.4/command/test-fixtures/fix/template.json
new file mode 100644
index 0000000..63b0f90
--- /dev/null
+++ b/v1.9.4/command/test-fixtures/fix/template.json
@@ -0,0 +1,7 @@
+{
+ "builders": [{"type": "dummy"}],
+
+ "push": {
+ "name": "foo/bar"
+ }
+}
diff --git a/v1.9.4/command/test-fixtures/fmt/formatted.pkr.hcl b/v1.9.4/command/test-fixtures/fmt/formatted.pkr.hcl
new file mode 100644
index 0000000..17c57f1
--- /dev/null
+++ b/v1.9.4/command/test-fixtures/fmt/formatted.pkr.hcl
@@ -0,0 +1,7 @@
+source "null" "example" {
+ communicator = "none"
+}
+
+build {
+ sources = ["source.null.example"]
+}
diff --git a/v1.9.4/command/test-fixtures/fmt/unformatted.auto.pkrvars.hcl b/v1.9.4/command/test-fixtures/fmt/unformatted.auto.pkrvars.hcl
new file mode 100644
index 0000000..803e3d7
--- /dev/null
+++ b/v1.9.4/command/test-fixtures/fmt/unformatted.auto.pkrvars.hcl
@@ -0,0 +1 @@
+region ="us-west-2"
diff --git a/v1.9.4/command/test-fixtures/fmt/unformatted.pkr.hcl b/v1.9.4/command/test-fixtures/fmt/unformatted.pkr.hcl
new file mode 100644
index 0000000..761d2f8
--- /dev/null
+++ b/v1.9.4/command/test-fixtures/fmt/unformatted.pkr.hcl
@@ -0,0 +1,11 @@
+variable "region" {
+ type =string
+}
+
+source "amazon-ebs" "example" {
+ region = var.region
+}
+
+build {
+ sources = ["source.amazon-ebs.example"]
+}
diff --git a/v1.9.4/command/test-fixtures/fmt/unformatted.pkrvars.hcl b/v1.9.4/command/test-fixtures/fmt/unformatted.pkrvars.hcl
new file mode 100644
index 0000000..7ddc9df
--- /dev/null
+++ b/v1.9.4/command/test-fixtures/fmt/unformatted.pkrvars.hcl
@@ -0,0 +1,3 @@
+ami_filter_name ="amzn2-ami-hvm-*-x86_64-gp2"
+ami_filter_owners =[ "137112412989" ]
+
diff --git a/v1.9.4/command/test-fixtures/hcl-inspect-with-sensitive-vars/expected-output.txt b/v1.9.4/command/test-fixtures/hcl-inspect-with-sensitive-vars/expected-output.txt
new file mode 100644
index 0000000..3d13bb4
--- /dev/null
+++ b/v1.9.4/command/test-fixtures/hcl-inspect-with-sensitive-vars/expected-output.txt
@@ -0,0 +1,16 @@
+Packer Inspect: HCL2 mode
+
+> input-variables:
+
+var.not_sensitive: "I am soooo not sensitive"
+var.not_sensitive_unknown: "<unknown>"
+var.sensitive: "<sensitive>"
+var.sensitive_array: "[\n \"<sensitive>\",\n \"<sensitive>\",\n]"
+var.sensitive_tags: "{\n \"first_key\" = \"<sensitive>\"\n \"second_key\" = \"<sensitive>\"\n}"
+var.sensitive_unknown: "<unknown>"
+
+> local-variables:
+
+
+> builds:
+
diff --git a/v1.9.4/command/test-fixtures/hcl-inspect-with-sensitive-vars/vars.pkr.hcl b/v1.9.4/command/test-fixtures/hcl-inspect-with-sensitive-vars/vars.pkr.hcl
new file mode 100644
index 0000000..e3bd983
--- /dev/null
+++ b/v1.9.4/command/test-fixtures/hcl-inspect-with-sensitive-vars/vars.pkr.hcl
@@ -0,0 +1,29 @@
+
+variable "not_sensitive" {
+ default = "I am soooo not sensitive"
+}
+
+variable "not_sensitive_unknown" {
+}
+
+variable "sensitive" {
+ default = "I am soooo sensitive"
+ sensitive = true
+}
+
+variable "sensitive_array" {
+ default = ["Im supersensitive", "me too !!!!"]
+ sensitive = true
+}
+
+variable "sensitive_tags" {
+ default = {
+ first_key = "this-is-mega-sensitive"
+ second_key = "this-is-also-sensitive"
+ }
+ sensitive = true
+}
+
+variable "sensitive_unknown" {
+ sensitive = true
+}
diff --git a/v1.9.4/command/test-fixtures/hcl-only-except/build.pkr.hcl b/v1.9.4/command/test-fixtures/hcl-only-except/build.pkr.hcl
new file mode 100644
index 0000000..be8c72e
--- /dev/null
+++ b/v1.9.4/command/test-fixtures/hcl-only-except/build.pkr.hcl
@@ -0,0 +1,28 @@
+source "file" "chocolate" {
+ content = "chocolate"
+ target = "chocolate.txt"
+}
+
+source "file" "vanilla" {
+ content = "vanilla"
+ target = "vanilla.txt"
+}
+
+source "file" "cherry" {
+ content = "cherry"
+ target = "cherry.txt"
+}
+
+build {
+ source "file.cherry" {
+
+ }
+}
+
+build {
+ name = "my_build"
+ sources = [
+ "file.chocolate",
+ "file.vanilla",
+ ]
+}
diff --git a/v1.9.4/command/test-fixtures/hcl/build-var-in-pp.pkr.hcl b/v1.9.4/command/test-fixtures/hcl/build-var-in-pp.pkr.hcl
new file mode 100644
index 0000000..96c36e7
--- /dev/null
+++ b/v1.9.4/command/test-fixtures/hcl/build-var-in-pp.pkr.hcl
@@ -0,0 +1,12 @@
+source "null" "example" {
+ communicator = "none"
+}
+
+build {
+ name = "example"
+ sources = ["source.null.example"]
+
+ post-processor "shell-local" {
+ inline = ["echo 2 > ${build.name}.2.txt"]
+ }
+}
diff --git a/v1.9.4/command/test-fixtures/hcl/build_no_source.pkr.hcl b/v1.9.4/command/test-fixtures/hcl/build_no_source.pkr.hcl
new file mode 100644
index 0000000..af4fbda
--- /dev/null
+++ b/v1.9.4/command/test-fixtures/hcl/build_no_source.pkr.hcl
@@ -0,0 +1 @@
+build{}
diff --git a/v1.9.4/command/test-fixtures/hcl/data-source-validation.pkr.hcl b/v1.9.4/command/test-fixtures/hcl/data-source-validation.pkr.hcl
new file mode 100644
index 0000000..3a0d5a7
--- /dev/null
+++ b/v1.9.4/command/test-fixtures/hcl/data-source-validation.pkr.hcl
@@ -0,0 +1,39 @@
+
+data "null" "secret" {
+ input = "s3cr3t"
+}
+
+locals {
+ secret = data.null.secret.output
+}
+
+source "file" "foo" {
+ content = "foo"
+ target = "foo.txt"
+}
+
+build {
+ sources = ["file.foo"]
+ provisioner "shell-local" {
+ only_on = ["darwin", "freebsd", "linux", "openbsd", "solaris"]
+ # original bug in :
+ # environment_vars = ["MY_SECRET=${local.secret}"]
+ env = {
+ "MY_SECRET":"${local.secret}",
+ }
+ inline = [
+ "echo yo, my secret is $MY_SECRET",
+ "echo '' > $MY_SECRET",
+ ]
+ }
+ provisioner "shell-local" {
+ only_on = ["windows"]
+ env = {
+ "MY_SECRET":"${local.secret}",
+ }
+ inline = [
+ "echo yo, my secret is %MY_SECRET%",
+ "echo '' > %MY_SECRET%",
+ ]
+ }
+}
diff --git a/v1.9.4/command/test-fixtures/hcl/datasource.pkr.hcl b/v1.9.4/command/test-fixtures/hcl/datasource.pkr.hcl
new file mode 100644
index 0000000..88521d3
--- /dev/null
+++ b/v1.9.4/command/test-fixtures/hcl/datasource.pkr.hcl
@@ -0,0 +1,14 @@
+data "mock" "content" {
+ foo = "chocolate"
+}
+
+source "file" "chocolate" {
+ content = data.mock.content.foo
+ target = "chocolate.txt"
+}
+
+build {
+ sources = [
+ "sources.file.chocolate",
+ ]
+}
diff --git a/v1.9.4/command/test-fixtures/hcl/dynamic/build.pkr.hcl b/v1.9.4/command/test-fixtures/hcl/dynamic/build.pkr.hcl
new file mode 100644
index 0000000..3fc70dc
--- /dev/null
+++ b/v1.9.4/command/test-fixtures/hcl/dynamic/build.pkr.hcl
@@ -0,0 +1,47 @@
+
+source "file" "base" {
+}
+
+variables {
+ images = {
+ dummy = {
+ image = "dummy"
+ layers = ["base/main"]
+ }
+ postgres = {
+ image = "postgres/13"
+ layers = ["base/main", "base/init", "postgres"]
+ }
+ }
+}
+
+locals {
+ files = {
+ foo = {
+ destination = "fooo"
+ }
+ bar = {
+ destination = "baar"
+ }
+ }
+}
+
+build {
+ dynamic "source" {
+ for_each = var.images
+ labels = ["file.base"]
+ content {
+ name = source.key
+ target = "${source.value.image}.txt"
+ content = join("\n", formatlist("layers/%s/files", var.images[source.key].layers))
+ }
+ }
+
+ dynamic "provisioner" {
+ for_each = local.files
+ labels = ["shell-local"]
+ content {
+ inline = ["echo '' > ${var.images[source.name].image}-${provisioner.value.destination}.txt"]
+ }
+ }
+}
diff --git a/v1.9.4/command/test-fixtures/hcl/empty_object/setting.auto.pkrvars.hcl b/v1.9.4/command/test-fixtures/hcl/empty_object/setting.auto.pkrvars.hcl
new file mode 100644
index 0000000..da5194a
--- /dev/null
+++ b/v1.9.4/command/test-fixtures/hcl/empty_object/setting.auto.pkrvars.hcl
@@ -0,0 +1,4 @@
+foo = ["yo"]
+bar = {
+ "baz": "foo",
+}
diff --git a/v1.9.4/command/test-fixtures/hcl/empty_object/var.pkr.hcl b/v1.9.4/command/test-fixtures/hcl/empty_object/var.pkr.hcl
new file mode 100644
index 0000000..4cd3531
--- /dev/null
+++ b/v1.9.4/command/test-fixtures/hcl/empty_object/var.pkr.hcl
@@ -0,0 +1,18 @@
+
+variable "foo" {
+ default = []
+}
+
+variable "bar" {
+ default = {}
+}
+
+source "file" "base" {
+}
+
+build {
+ source "sources.file.base" {
+ target = "${var.bar.baz}.txt"
+ content = var.foo[0]
+ }
+}
diff --git a/v1.9.4/command/test-fixtures/hcl/force.pkr.hcl b/v1.9.4/command/test-fixtures/hcl/force.pkr.hcl
new file mode 100644
index 0000000..98b31b0
--- /dev/null
+++ b/v1.9.4/command/test-fixtures/hcl/force.pkr.hcl
@@ -0,0 +1,12 @@
+source "null" "potato" {
+ communicator = "none"
+}
+
+build {
+ sources = ["sources.null.potato"]
+
+ post-processor "manifest" {
+ output = "manifest.json"
+ strip_time = true
+ }
+}
\ No newline at end of file
diff --git a/v1.9.4/command/test-fixtures/hcl/inspect/aws-builds.pkr.hcl b/v1.9.4/command/test-fixtures/hcl/inspect/aws-builds.pkr.hcl
new file mode 100644
index 0000000..64c25e3
--- /dev/null
+++ b/v1.9.4/command/test-fixtures/hcl/inspect/aws-builds.pkr.hcl
@@ -0,0 +1,40 @@
+
+
+build {
+ name = "aws_example_builder"
+ description = <<EOF
+The builder of clouds !!
+
+Use it at will.
+EOF
+
+ sources = [
+ "source.amazon-ebs.example-1",
+
+ // this one is not defined but we don't want to error there, we just
+ // would like to show what sources are being referenced.
+ "source.amazon-ebs.example-2",
+ ]
+
+ provisioner "shell" {
+ files = [
+ "bins/install-this.sh",
+ "bins/install-that.sh",
+ "bins/conf-this.sh",
+ ]
+ }
+
+ post-processor "manifest" {
+ }
+
+ post-processor "shell-local" {
+ }
+
+ post-processors {
+ post-processor "manifest" {
+ }
+
+ post-processor "shell-local" {
+ }
+ }
+}
\ No newline at end of file
diff --git a/v1.9.4/command/test-fixtures/hcl/inspect/fruit_string.pkr.hcl b/v1.9.4/command/test-fixtures/hcl/inspect/fruit_string.pkr.hcl
new file mode 100644
index 0000000..51bc427
--- /dev/null
+++ b/v1.9.4/command/test-fixtures/hcl/inspect/fruit_string.pkr.hcl
@@ -0,0 +1,25 @@
+
+variable "fruit" {
+ type = string
+ default = "banana"
+}
+
+variable "unknown_string" {
+ type = string
+}
+
+
+variable "unknown_list_of_string" {
+ type = list(string)
+}
+
+variable "unknown_unknown" {
+}
+
+variable "default_from_env" {
+ default = env("DEFAULT_FROM_ENV")
+}
+
+variable "other_default_from_env" {
+ default = env("OTHER_DEFAULT_FROM_ENV")
+}
diff --git a/v1.9.4/command/test-fixtures/hcl/inspect/virtualbox-builds.pkr.hcl b/v1.9.4/command/test-fixtures/hcl/inspect/virtualbox-builds.pkr.hcl
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/v1.9.4/command/test-fixtures/hcl/inspect/virtualbox-builds.pkr.hcl
diff --git a/v1.9.4/command/test-fixtures/hcl/local-ds-validate.pkr.hcl b/v1.9.4/command/test-fixtures/hcl/local-ds-validate.pkr.hcl
new file mode 100644
index 0000000..47a2f9f
--- /dev/null
+++ b/v1.9.4/command/test-fixtures/hcl/local-ds-validate.pkr.hcl
@@ -0,0 +1,17 @@
+data "null" "dep" {
+ input = "upload"
+}
+
+source "null" "test" {
+ communicator = "none"
+}
+
+build {
+ sources = ["sources.null.test"]
+
+ provisioner "file" {
+ source = "test-fixtures/hcl/force.pkr.hcl"
+ destination = "dest"
+ direction = "${data.null.dep.output}"
+ }
+}
diff --git a/v1.9.4/command/test-fixtures/hcl/nil-component-crash.pkr.hcl b/v1.9.4/command/test-fixtures/hcl/nil-component-crash.pkr.hcl
new file mode 100644
index 0000000..a194396
--- /dev/null
+++ b/v1.9.4/command/test-fixtures/hcl/nil-component-crash.pkr.hcl
@@ -0,0 +1,10 @@
+source "null" "basic-example" {
+}
+
+build {
+ sources = ["sources.null.basic-example"]
+
+ provisioner "foo" {
+ timeout = "10"
+ }
+}
diff --git a/v1.9.4/command/test-fixtures/hcl/no_build.pkr.hcl b/v1.9.4/command/test-fixtures/hcl/no_build.pkr.hcl
new file mode 100644
index 0000000..ae75d38
--- /dev/null
+++ b/v1.9.4/command/test-fixtures/hcl/no_build.pkr.hcl
@@ -0,0 +1,3 @@
+source "null" "papaya" {
+ communicator = "none"
+}
diff --git a/v1.9.4/command/test-fixtures/hcl/provisioner-override.pkr.hcl b/v1.9.4/command/test-fixtures/hcl/provisioner-override.pkr.hcl
new file mode 100644
index 0000000..a52c84d
--- /dev/null
+++ b/v1.9.4/command/test-fixtures/hcl/provisioner-override.pkr.hcl
@@ -0,0 +1,19 @@
+source "null" "example1" {
+ communicator = "none"
+}
+
+source "null" "example2" {
+ communicator = "none"
+}
+
+build {
+ sources = ["source.null.example1", "source.null.example2"]
+ provisioner "shell-local" {
+ inline = ["echo not overridden"]
+ override = {
+ example1 = {
+ inline = ["echo yes overridden"]
+ }
+ }
+ }
+}
\ No newline at end of file
diff --git a/v1.9.4/command/test-fixtures/hcl/recipes/build.pkr.hcl b/v1.9.4/command/test-fixtures/hcl/recipes/build.pkr.hcl
new file mode 100644
index 0000000..782bf10
--- /dev/null
+++ b/v1.9.4/command/test-fixtures/hcl/recipes/build.pkr.hcl
@@ -0,0 +1,72 @@
+
+build {
+ source "source.null.base" {
+ name = "tiramisu"
+ // pull me up !
+ }
+
+ provisioner "shell-local" {
+ name = "whipped_york"
+ inline = [ "echo whip_york > ${upper(build.ID)}.${source.name}.txt" ]
+ }
+ provisioner "shell-local" {
+ name = "mascarpone"
+ inline = [ "echo mascarpone >> ${upper(build.ID)}.${source.name}.txt" ]
+ }
+ post-processor "shell-local" {
+ name = "whipped_egg_white"
+ inline = [ "echo whipped_egg_white >> ${upper(build.ID)}.${source.name}.txt" ]
+ }
+ post-processor "shell-local" {
+ name = "dress_with_coffeed_boudoirs"
+ inline = [ "echo dress >> ${upper(build.ID)}.${source.name}.txt" ]
+ }
+}
+
+build {
+ name = "recipes"
+ source "source.null.base" {
+ name = "spaghetti_carbonara"
+ }
+ source "source.null.base" {
+ name = "lasagna"
+ }
+
+ provisioner "shell-local" {
+ name = "add_spaghetti"
+ inline = [ "echo spaghetti > ${upper(build.ID)}.${source.name}.txt" ]
+ only = ["null.spaghetti_carbonara"]
+ }
+
+ post-processor "shell-local" {
+ name = "carbonara_it"
+ inline = [ "echo carbonara >> ${upper(build.ID)}.${source.name}.txt" ]
+ except = ["null.lasagna"]
+ }
+
+
+ provisioner "shell-local" {
+ name = "add_lasagna"
+ inline = [ "echo lasagna > ${upper(build.ID)}.${source.name}.txt" ]
+ only = ["null.lasagna"]
+ }
+
+ provisioner "shell-local" {
+ name = "add_tomato"
+ inline = [ "echo tomato >> ${upper(build.ID)}.${source.name}.txt" ]
+ except = ["null.spaghetti_carbonara"]
+ }
+
+ provisioner "shell-local" {
+ name = "add_mozza"
+ inline = [ "echo mozza >> ${upper(build.ID)}.${source.name}.txt" ]
+ except = ["null.spaghetti_carbonara"]
+ }
+
+ post-processor "shell-local" {
+ name = "cook"
+ inline = [ "echo cooking... >> ${upper(build.ID)}.${source.name}.txt" ]
+ except = ["null.spaghetti_carbonara"]
+ }
+
+}
diff --git a/v1.9.4/command/test-fixtures/hcl/recipes/sources.pkr.hcl b/v1.9.4/command/test-fixtures/hcl/recipes/sources.pkr.hcl
new file mode 100644
index 0000000..baeae65
--- /dev/null
+++ b/v1.9.4/command/test-fixtures/hcl/recipes/sources.pkr.hcl
@@ -0,0 +1,3 @@
+source "null" "base" {
+ communicator = "none"
+}
diff --git a/v1.9.4/command/test-fixtures/hcl/recursive_local_with_input/locals.pkr.hcl b/v1.9.4/command/test-fixtures/hcl/recursive_local_with_input/locals.pkr.hcl
new file mode 100644
index 0000000..2f99b0d
--- /dev/null
+++ b/v1.9.4/command/test-fixtures/hcl/recursive_local_with_input/locals.pkr.hcl
@@ -0,0 +1,25 @@
+variable "vms_to_build" {
+ default = {
+ "amgroup": "hey"
+ }
+}
+
+locals {
+ vms_to_build = var.vms_to_build
+ dynamic_slice = {
+ for vm, val in var.vms_to_build :
+ vm => lookup(local.vms_to_build, vm, "VM NAME NOT FOUND")
+ }
+}
+
+
+source "file" "chocolate" {
+ content = "hello"
+ target = "${local.dynamic_slice.amgroup}.txt"
+}
+
+build {
+ sources = [
+ "sources.file.chocolate",
+ ]
+}
diff --git a/v1.9.4/command/test-fixtures/hcl/recursive_local_with_unset_input/file.pkr.hcl b/v1.9.4/command/test-fixtures/hcl/recursive_local_with_unset_input/file.pkr.hcl
new file mode 100644
index 0000000..05fd53c
--- /dev/null
+++ b/v1.9.4/command/test-fixtures/hcl/recursive_local_with_unset_input/file.pkr.hcl
@@ -0,0 +1,12 @@
+
+variable "vms_to_build" {
+}
+
+locals {
+ vms_to_build = var.vms_to_build
+ dynamic_map = {
+ for vm in local.vms_to_build :
+ vm => lookup(local, vm, "VM NAME NOT FOUND")
+ }
+}
+
diff --git a/v1.9.4/command/test-fixtures/hcl/reprepare/hello.sh b/v1.9.4/command/test-fixtures/hcl/reprepare/hello.sh
new file mode 100755
index 0000000..e3cd0fc
--- /dev/null
+++ b/v1.9.4/command/test-fixtures/hcl/reprepare/hello.sh
@@ -0,0 +1 @@
+echo hello from the ${BUILDER} builder ${USER}
\ No newline at end of file
diff --git a/v1.9.4/command/test-fixtures/hcl/reprepare/shell-local-windows.pkr.hcl b/v1.9.4/command/test-fixtures/hcl/reprepare/shell-local-windows.pkr.hcl
new file mode 100644
index 0000000..a09cba1
--- /dev/null
+++ b/v1.9.4/command/test-fixtures/hcl/reprepare/shell-local-windows.pkr.hcl
@@ -0,0 +1,13 @@
+source "null" "example" {
+ communicator = "none"
+}
+
+build {
+ sources = [
+ "source.null.example"
+ ]
+ provisioner "shell-local" {
+ script = "./${path.root}/test_cmd.cmd"
+ environment_vars = ["USER=packeruser", "BUILDER=${upper(build.ID)}"]
+ }
+}
diff --git a/v1.9.4/command/test-fixtures/hcl/reprepare/shell-local.pkr.hcl b/v1.9.4/command/test-fixtures/hcl/reprepare/shell-local.pkr.hcl
new file mode 100644
index 0000000..5e2fcc1
--- /dev/null
+++ b/v1.9.4/command/test-fixtures/hcl/reprepare/shell-local.pkr.hcl
@@ -0,0 +1,13 @@
+source "null" "example" {
+ communicator = "none"
+}
+
+build {
+ sources = [
+ "source.null.example"
+ ]
+ provisioner "shell-local" {
+ script = "./${path.root}/hello.sh"
+ environment_vars = ["USER=packeruser", "BUILDER=${upper(build.ID)}"]
+ }
+}
diff --git a/v1.9.4/command/test-fixtures/hcl/reprepare/test_cmd.cmd b/v1.9.4/command/test-fixtures/hcl/reprepare/test_cmd.cmd
new file mode 100644
index 0000000..f0c984a
--- /dev/null
+++ b/v1.9.4/command/test-fixtures/hcl/reprepare/test_cmd.cmd
@@ -0,0 +1 @@
+echo hello from the %BUILDER% builder %USER%
\ No newline at end of file
diff --git a/v1.9.4/command/test-fixtures/hcl/test_except_manifest.pkr.hcl b/v1.9.4/command/test-fixtures/hcl/test_except_manifest.pkr.hcl
new file mode 100644
index 0000000..bf9f7ad
--- /dev/null
+++ b/v1.9.4/command/test-fixtures/hcl/test_except_manifest.pkr.hcl
@@ -0,0 +1,9 @@
+source "null" "test" {
+ communicator = "none"
+}
+
+build {
+ sources = ["null.test"]
+
+ post-processor "manifest" {}
+}
diff --git a/v1.9.4/command/test-fixtures/hcl/validation/map/definition.pkr.hcl b/v1.9.4/command/test-fixtures/hcl/validation/map/definition.pkr.hcl
new file mode 100644
index 0000000..a480d96
--- /dev/null
+++ b/v1.9.4/command/test-fixtures/hcl/validation/map/definition.pkr.hcl
@@ -0,0 +1,25 @@
+
+variable "image_metadata" {
+ default = {
+ key: "value",
+ something: {
+ foo: "bar",
+ }
+ }
+ validation {
+ condition = length(var.image_metadata.key) > 4
+ error_message = "The image_metadata.key field must be more than 4 runes."
+ }
+ validation {
+ condition = substr(var.image_metadata.something.foo, 0, 3) == "bar"
+ error_message = "The image_metadata.something.foo field must start with \"bar\"."
+ }
+}
+
+source "null" "test" {
+ communicator = "none"
+}
+
+build {
+ sources = ["source.null.test"]
+}
diff --git a/v1.9.4/command/test-fixtures/hcl/validation/map/invalid_value.pkrvars.hcl b/v1.9.4/command/test-fixtures/hcl/validation/map/invalid_value.pkrvars.hcl
new file mode 100644
index 0000000..9734f36
--- /dev/null
+++ b/v1.9.4/command/test-fixtures/hcl/validation/map/invalid_value.pkrvars.hcl
@@ -0,0 +1,7 @@
+
+image_metadata = {
+ key: "value",
+ something: {
+ foo: "woo",
+ }
+}
diff --git a/v1.9.4/command/test-fixtures/hcl/validation/map/valid_value.pkrvars.hcl b/v1.9.4/command/test-fixtures/hcl/validation/map/valid_value.pkrvars.hcl
new file mode 100644
index 0000000..250fcfc
--- /dev/null
+++ b/v1.9.4/command/test-fixtures/hcl/validation/map/valid_value.pkrvars.hcl
@@ -0,0 +1,7 @@
+
+image_metadata = {
+ key: "value",
+ something: {
+ foo: "barwoo",
+ }
+}
diff --git a/v1.9.4/command/test-fixtures/hcl/validation/wrong_pause_before.pkr.hcl b/v1.9.4/command/test-fixtures/hcl/validation/wrong_pause_before.pkr.hcl
new file mode 100644
index 0000000..a30aa55
--- /dev/null
+++ b/v1.9.4/command/test-fixtures/hcl/validation/wrong_pause_before.pkr.hcl
@@ -0,0 +1,12 @@
+source "null" "example1" {
+ communicator = "none"
+}
+
+build {
+ sources = ["source.null.example1"]
+
+ provisioner "shell-local" {
+ pause_before = "5"
+ inline = ["echo Did I wait a bit?"]
+ }
+}
diff --git a/v1.9.4/command/test-fixtures/hcl/var-in-pp-name.pkr.hcl b/v1.9.4/command/test-fixtures/hcl/var-in-pp-name.pkr.hcl
new file mode 100644
index 0000000..bc59d0f
--- /dev/null
+++ b/v1.9.4/command/test-fixtures/hcl/var-in-pp-name.pkr.hcl
@@ -0,0 +1,35 @@
+source "null" "example1" {
+ communicator = "none"
+}
+
+source "null" "example2" {
+ communicator = "none"
+}
+
+locals {
+ except_example2 = "null.example2"
+ true = true
+}
+
+variable "only_example2" {
+ default = "null.example2"
+}
+
+variable "foo" {
+ default = "bar"
+}
+
+build {
+ sources = ["source.null.example1", "source.null.example2"]
+ post-processor "shell-local" {
+ keep_input_artifact = local.true
+ except = [local.except_example2]
+ inline = ["echo 1 > ${source.name}.1.txt"]
+ }
+
+ post-processor "shell-local" {
+ name = var.foo
+ only = [var.only_example2]
+ inline = ["echo 2 > ${source.name}.2.txt"]
+ }
+}
diff --git a/v1.9.4/command/test-fixtures/hcl/variables/list_of_string/var.pkr.hcl b/v1.9.4/command/test-fixtures/hcl/variables/list_of_string/var.pkr.hcl
new file mode 100644
index 0000000..eb1d199
--- /dev/null
+++ b/v1.9.4/command/test-fixtures/hcl/variables/list_of_string/var.pkr.hcl
@@ -0,0 +1,4 @@
+
+variable "list_of_string" {
+ type = list(string)
+}
diff --git a/v1.9.4/command/test-fixtures/hcl/variables/ref_non_existing/ref_non_existing_var.pkr.hcl b/v1.9.4/command/test-fixtures/hcl/variables/ref_non_existing/ref_non_existing_var.pkr.hcl
new file mode 100644
index 0000000..e005230
--- /dev/null
+++ b/v1.9.4/command/test-fixtures/hcl/variables/ref_non_existing/ref_non_existing_var.pkr.hcl
@@ -0,0 +1,7 @@
+source "null" "test" {
+ communicator = "none"
+}
+
+build {
+ sources = ["null.test"]
+}
diff --git a/v1.9.4/command/test-fixtures/hcl/variables/ref_non_existing/variables.auto.pkrvars.hcl b/v1.9.4/command/test-fixtures/hcl/variables/ref_non_existing/variables.auto.pkrvars.hcl
new file mode 100644
index 0000000..ae45fb4
--- /dev/null
+++ b/v1.9.4/command/test-fixtures/hcl/variables/ref_non_existing/variables.auto.pkrvars.hcl
@@ -0,0 +1 @@
+testvar = "auto"
diff --git a/v1.9.4/command/test-fixtures/hcl/variables/untyped_var/settings.auto.pkrvars.hcl b/v1.9.4/command/test-fixtures/hcl/variables/untyped_var/settings.auto.pkrvars.hcl
new file mode 100644
index 0000000..48cf27f
--- /dev/null
+++ b/v1.9.4/command/test-fixtures/hcl/variables/untyped_var/settings.auto.pkrvars.hcl
@@ -0,0 +1,2 @@
+
+untyped = ["slice", "of", "strings"]
diff --git a/v1.9.4/command/test-fixtures/hcl/variables/untyped_var/var.pkr.hcl b/v1.9.4/command/test-fixtures/hcl/variables/untyped_var/var.pkr.hcl
new file mode 100644
index 0000000..9d69f7f
--- /dev/null
+++ b/v1.9.4/command/test-fixtures/hcl/variables/untyped_var/var.pkr.hcl
@@ -0,0 +1,3 @@
+
+variable "untyped" {
+}
diff --git a/v1.9.4/command/test-fixtures/hcl/vars-in-build-block.pkr.hcl b/v1.9.4/command/test-fixtures/hcl/vars-in-build-block.pkr.hcl
new file mode 100644
index 0000000..357735d
--- /dev/null
+++ b/v1.9.4/command/test-fixtures/hcl/vars-in-build-block.pkr.hcl
@@ -0,0 +1,24 @@
+variable "name" {
+ type = string
+ default = "example"
+}
+
+variable "description" {
+ type = string
+ default = "blah blah blah"
+}
+
+source "null" "example" {
+ communicator = "none"
+}
+
+build {
+ name = var.name
+ description = var.description
+
+ sources = ["source.null.example"]
+
+ post-processor "shell-local" {
+ inline = ["echo 2 > ${build.name}.2.txt"]
+ }
+}
diff --git a/v1.9.4/command/test-fixtures/hcl2_upgrade/ami_test/expected.pkr.hcl b/v1.9.4/command/test-fixtures/hcl2_upgrade/ami_test/expected.pkr.hcl
new file mode 100644
index 0000000..8a72f35
--- /dev/null
+++ b/v1.9.4/command/test-fixtures/hcl2_upgrade/ami_test/expected.pkr.hcl
@@ -0,0 +1,32 @@
+packer {
+ required_plugins {
+ amazon = {
+ source = "github.com/hashicorp/amazon"
+ version = "~> 1"
+ }
+ }
+}
+
+source "amazon-ebs" "autogenerated_1" {
+ run_tags = {
+ SourceAMI = "{{ .SourceAMI }}"
+ SourceAMICreationDate = "{{ .SourceAMICreationDate }}"
+ SourceAMIName = "{{ .SourceAMIName }}"
+ SourceAMIOwner = "{{ .SourceAMIOwner }}"
+ SourceAMIOwnerName = "{{ .SourceAMIOwnerName }}"
+ SourceAMITags = "{{ .SourceAMITags.TagName }}"
+ }
+ tags = {
+ SourceAMI = "{{ .SourceAMI }}"
+ SourceAMICreationDate = "{{ .SourceAMICreationDate }}"
+ SourceAMIName = "{{ .SourceAMIName }}"
+ SourceAMIOwner = "{{ .SourceAMIOwner }}"
+ SourceAMIOwnerName = "{{ .SourceAMIOwnerName }}"
+ SourceAMITags = "{{ .SourceAMITags.TagName }}"
+ }
+}
+
+build {
+ sources = ["source.amazon-ebs.autogenerated_1"]
+
+}
diff --git a/v1.9.4/command/test-fixtures/hcl2_upgrade/ami_test/input.json b/v1.9.4/command/test-fixtures/hcl2_upgrade/ami_test/input.json
new file mode 100644
index 0000000..b66524c
--- /dev/null
+++ b/v1.9.4/command/test-fixtures/hcl2_upgrade/ami_test/input.json
@@ -0,0 +1,21 @@
+{
+ "builders": [{
+ "type": "amazon-ebs",
+ "tags": {
+ "SourceAMIName" : "{{ .SourceAMIName }}",
+ "SourceAMI" : "{{ .SourceAMI }}",
+ "SourceAMICreationDate" : "{{ .SourceAMICreationDate }}",
+ "SourceAMIOwner" : "{{ .SourceAMIOwner }}",
+ "SourceAMIOwnerName" : "{{ .SourceAMIOwnerName }}",
+ "SourceAMITags": "{{ .SourceAMITags.TagName }}"
+ },
+ "run_tags": {
+ "SourceAMIName" : "{{.SourceAMIName}}",
+ "SourceAMI" : "{{.SourceAMI}}",
+ "SourceAMICreationDate" : "{{.SourceAMICreationDate}}",
+ "SourceAMIOwner" : "{{.SourceAMIOwner}}",
+ "SourceAMIOwnerName" : "{{.SourceAMIOwnerName}}",
+ "SourceAMITags": "{{ .SourceAMITags.TagName }}"
+ }
+ }]
+}
diff --git a/v1.9.4/command/test-fixtures/hcl2_upgrade/aws-access-config/expected.pkr.hcl b/v1.9.4/command/test-fixtures/hcl2_upgrade/aws-access-config/expected.pkr.hcl
new file mode 100644
index 0000000..8c34e47
--- /dev/null
+++ b/v1.9.4/command/test-fixtures/hcl2_upgrade/aws-access-config/expected.pkr.hcl
@@ -0,0 +1,78 @@
+packer {
+ required_version = ">= 1.6.0"
+ required_plugins {
+ amazon = {
+ source = "github.com/hashicorp/amazon"
+ version = "~> 1"
+ }
+ }
+}
+
+variable "aws_access_key" {
+ type = string
+ default = ""
+ sensitive = true
+}
+
+variable "aws_region" {
+ type = string
+}
+
+variable "aws_secret_key" {
+ type = string
+ default = ""
+ sensitive = true
+}
+
+data "amazon-ami" "autogenerated_1" {
+ access_key = "NJDBFASJDbsajhbda5487"
+ filters = {
+ name = "ubuntu/images/*/ubuntu-xenial-16.04-amd64-server-*"
+ root-device-type = "ebs"
+ virtualization-type = "hvm"
+ }
+ most_recent = true
+ owners = ["099720109477"]
+ region = "us-west-2"
+ secret_key = "ASEfewdsfAWASTT51874"
+}
+
+data "amazon-ami" "autogenerated_2" {
+ access_key = "${var.aws_access_key}"
+ filters = {
+ name = "ubuntu/images/*/ubuntu-xenial-16.04-amd64-server-*"
+ root-device-type = "ebs"
+ virtualization-type = "hvm"
+ }
+ most_recent = true
+ owners = ["099720109477"]
+ region = "${var.aws_region}"
+ secret_key = "${var.aws_secret_key}"
+}
+
+locals { timestamp = regex_replace(timestamp(), "[- TZ:]", "") }
+
+source "amazon-ebs" "autogenerated_1" {
+ access_key = "NJDBFASJDbsajhbda5487"
+ ami_name = "ubuntu-16-04-test-${local.timestamp}"
+ region = "us-west-2"
+ secret_key = "ASEfewdsfAWASTT51874"
+ source_ami = "${data.amazon-ami.autogenerated_1.id}"
+ ssh_interface = "session_manager"
+ ssh_username = "ubuntu"
+}
+
+source "amazon-ebs" "named_builder" {
+ access_key = "${var.aws_access_key}"
+ ami_name = "ubuntu-16-04-test-${local.timestamp}"
+ region = "${var.aws_region}"
+ secret_key = "${var.aws_secret_key}"
+ source_ami = "${data.amazon-ami.autogenerated_2.id}"
+ ssh_interface = "session_manager"
+ ssh_username = "ubuntu"
+}
+
+build {
+ sources = ["source.amazon-ebs.autogenerated_1", "source.amazon-ebs.named_builder"]
+
+}
diff --git a/v1.9.4/command/test-fixtures/hcl2_upgrade/aws-access-config/input.json b/v1.9.4/command/test-fixtures/hcl2_upgrade/aws-access-config/input.json
new file mode 100644
index 0000000..e82a93e
--- /dev/null
+++ b/v1.9.4/command/test-fixtures/hcl2_upgrade/aws-access-config/input.json
@@ -0,0 +1,55 @@
+{
+ "min_packer_version": "1.6.0",
+ "variables": {
+ "aws_region": null,
+ "aws_secret_key": "",
+ "aws_access_key": ""
+ },
+ "sensitive-variables": [
+ "aws_secret_key",
+ "aws_access_key"
+ ],
+ "builders": [
+ {
+ "type": "amazon-ebs",
+ "region": "us-west-2",
+ "secret_key": "ASEfewdsfAWASTT51874",
+ "access_key": "NJDBFASJDbsajhbda5487",
+ "ami_name": "ubuntu-16-04-test-{{ timestamp }}",
+ "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
+ },
+ "ssh_username": "ubuntu",
+ "ssh_interface": "session_manager"
+ },
+ {
+ "type": "amazon-ebs",
+ "name": "named_builder",
+ "region": "{{ user `aws_region` }}",
+ "secret_key": "{{ user `aws_secret_key` }}",
+ "access_key": "{{ user `aws_access_key` }}",
+ "ami_name": "ubuntu-16-04-test-{{ timestamp }}",
+ "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
+ },
+ "ssh_username": "ubuntu",
+ "ssh_interface": "session_manager"
+ }
+ ]
+}
\ No newline at end of file
diff --git a/v1.9.4/command/test-fixtures/hcl2_upgrade/azure_shg/expected.pkr.hcl b/v1.9.4/command/test-fixtures/hcl2_upgrade/azure_shg/expected.pkr.hcl
new file mode 100644
index 0000000..15d5a4a
--- /dev/null
+++ b/v1.9.4/command/test-fixtures/hcl2_upgrade/azure_shg/expected.pkr.hcl
@@ -0,0 +1,19 @@
+packer {
+ required_plugins {
+ azure = {
+ source = "github.com/hashicorp/azure"
+ version = "~> 1"
+ }
+ }
+}
+
+source "azure-arm" "autogenerated_1" {
+ shared_image_gallery {
+ gallery_name = "web_app"
+ }
+}
+
+build {
+ sources = ["source.azure-arm.autogenerated_1"]
+
+}
diff --git a/v1.9.4/command/test-fixtures/hcl2_upgrade/azure_shg/input.json b/v1.9.4/command/test-fixtures/hcl2_upgrade/azure_shg/input.json
new file mode 100644
index 0000000..02f89bf
--- /dev/null
+++ b/v1.9.4/command/test-fixtures/hcl2_upgrade/azure_shg/input.json
@@ -0,0 +1,8 @@
+{
+ "builders": [{
+ "type": "azure-arm",
+ "shared_image_gallery": {
+ "gallery_name": "web_app"
+ }
+ }]
+}
diff --git a/v1.9.4/command/test-fixtures/hcl2_upgrade/bundled-plugin-used/expected.pkr.hcl b/v1.9.4/command/test-fixtures/hcl2_upgrade/bundled-plugin-used/expected.pkr.hcl
new file mode 100644
index 0000000..cce175b
--- /dev/null
+++ b/v1.9.4/command/test-fixtures/hcl2_upgrade/bundled-plugin-used/expected.pkr.hcl
@@ -0,0 +1,29 @@
+packer {
+ required_plugins {
+ amazon = {
+ source = "github.com/hashicorp/amazon"
+ version = "~> 1"
+ }
+ ansible = {
+ source = "github.com/hashicorp/ansible"
+ version = "~> 1"
+ }
+ googlecompute = {
+ source = "github.com/hashicorp/googlecompute"
+ version = "~> 1"
+ }
+ }
+}
+
+source "amazon-ebs" "autogenerated_1" {
+}
+
+build {
+ sources = ["source.amazon-ebs.autogenerated_1"]
+
+ provisioner "ansible-local" {
+ }
+
+ post-processor "googlecompute-import" {
+ }
+}
diff --git a/v1.9.4/command/test-fixtures/hcl2_upgrade/bundled-plugin-used/input.json b/v1.9.4/command/test-fixtures/hcl2_upgrade/bundled-plugin-used/input.json
new file mode 100644
index 0000000..917c710
--- /dev/null
+++ b/v1.9.4/command/test-fixtures/hcl2_upgrade/bundled-plugin-used/input.json
@@ -0,0 +1,11 @@
+{
+ "builders": [{
+ "type": "amazon-ebs"
+ }],
+ "provisioners": [{
+ "type": "ansible-local"
+ }],
+ "post-processors": [{
+ "type": "googlecompute-import"
+ }]
+}
diff --git a/v1.9.4/command/test-fixtures/hcl2_upgrade/complete-variables-with-template-engine/expected.pkr.hcl b/v1.9.4/command/test-fixtures/hcl2_upgrade/complete-variables-with-template-engine/expected.pkr.hcl
new file mode 100644
index 0000000..1bf776b
--- /dev/null
+++ b/v1.9.4/command/test-fixtures/hcl2_upgrade/complete-variables-with-template-engine/expected.pkr.hcl
@@ -0,0 +1,59 @@
+
+variable "env_test" {
+ type = string
+ default = "${env("TEST_ENV")}"
+}
+
+locals { timestamp = regex_replace(timestamp(), "[- TZ:]", "") }
+# The "legacy_isotime" function has been provided for backwards compatability, but we recommend switching to the timestamp and formatdate functions.
+
+# 5 errors occurred upgrading the following block:
+# unhandled "lower" call:
+# there is no way to automatically upgrade the "lower" call.
+# Please manually upgrade to `lower(var.example)`
+# Visit https://www.packer.io/docs/templates/hcl_templates/functions/string/lower for more infos.
+
+# unhandled "replace" call:
+# there is no way to automatically upgrade the "replace" call.
+# Please manually upgrade to `replace(string, substring, replacement)` or `regex_replace(string, substring, replacement)`
+# Visit https://www.packer.io/docs/templates/hcl_templates/functions/string/replace or https://www.packer.io/docs/templates/hcl_templates/functions/string/regex_replace for more infos.
+
+# unhandled "replace_all" call:
+# there is no way to automatically upgrade the "replace_all" call.
+# Please manually upgrade to `replace(string, substring, replacement)` or `regex_replace(string, substring, replacement)`
+# Visit https://www.packer.io/docs/templates/hcl_templates/functions/string/replace or https://www.packer.io/docs/templates/hcl_templates/functions/string/regex_replace for more infos.
+
+# unhandled "split" call:
+# there is no way to automatically upgrade the "split" call.
+# Please manually upgrade to `split(separator, string)`
+# Visit https://www.packer.io/docs/templates/hcl_templates/functions/string/split for more infos.
+
+# unhandled "upper" call:
+# there is no way to automatically upgrade the "upper" call.
+# Please manually upgrade to `upper(var.example)`
+# Visit https://www.packer.io/docs/templates/hcl_templates/functions/string/upper for more infos.
+locals {
+ build_timestamp = "${local.timestamp}"
+ iso_datetime = "${legacy_isotime("2006-01-02T15:04:05Z07:00")}"
+ lower = "{{ lower `HELLO` }}"
+ pwd = "${path.cwd}"
+ replace = "{{ replace `b` `c` `ababa` 2 }}"
+ replace_all = "{{ replace_all `b` `c` `ababa` }}"
+ split = "{{ split `aba` `b` 1 }}"
+ temp_directory = "${path.root}"
+ upper = "{{ upper `hello` }}"
+ uuid = "${uuidv4()}"
+}
+
+source "null" "autogenerated_1" {
+ communicator = "none"
+}
+
+build {
+ sources = ["source.null.autogenerated_1"]
+
+ provisioner "shell-local" {
+ inline = ["echo ${local.build_timestamp}", "echo ${local.temp_directory}", "echo ${local.iso_datetime}", "echo ${local.uuid}", "echo ${var.env_test}", "echo ${local.lower}", "echo ${local.upper}", "echo ${local.pwd}", "echo ${local.replace}", "echo ${local.replace_all}", "echo ${local.split}"]
+ }
+
+}
diff --git a/v1.9.4/command/test-fixtures/hcl2_upgrade/complete-variables-with-template-engine/input.json b/v1.9.4/command/test-fixtures/hcl2_upgrade/complete-variables-with-template-engine/input.json
new file mode 100644
index 0000000..1711722
--- /dev/null
+++ b/v1.9.4/command/test-fixtures/hcl2_upgrade/complete-variables-with-template-engine/input.json
@@ -0,0 +1,35 @@
+{
+ "variables": {
+ "build_timestamp": "{{timestamp}}",
+ "temp_directory": "{{template_dir}}",
+ "uuid": "{{uuid}}",
+ "env_test": "{{env `TEST_ENV`}}",
+ "lower": "{{lower `HELLO`}}",
+ "upper": "{{upper `hello`}}",
+ "pwd": "{{pwd}}",
+ "replace": "{{replace `b` `c` 2 `ababa`}}",
+ "replace_all": "{{replace_all `b` `c` `ababa`}}",
+ "split": "{{split `aba` `b` 1}}",
+ "iso_datetime": "{{isotime `2006-01-02T15:04:05Z07:00`}}"
+ },
+ "builders": [{
+ "type": "null",
+ "communicator": "none"
+ }],
+ "provisioners": [{
+ "type": "shell-local",
+ "inline": [
+ "echo {{ user `build_timestamp`}}",
+ "echo {{ user `temp_directory`}}",
+ "echo {{ user `iso_datetime`}}",
+ "echo {{ user `uuid`}}",
+ "echo {{ user `env_test`}}",
+ "echo {{ user `lower`}}",
+ "echo {{ user `upper`}}",
+ "echo {{ user `pwd`}}",
+ "echo {{ user `replace`}}",
+ "echo {{ user `replace_all`}}",
+ "echo {{ user `split`}}"
+ ]
+ }]
+}
\ No newline at end of file
diff --git a/v1.9.4/command/test-fixtures/hcl2_upgrade/complete/expected.pkr.hcl b/v1.9.4/command/test-fixtures/hcl2_upgrade/complete/expected.pkr.hcl
new file mode 100644
index 0000000..a6800c6
--- /dev/null
+++ b/v1.9.4/command/test-fixtures/hcl2_upgrade/complete/expected.pkr.hcl
@@ -0,0 +1,294 @@
+# This file was autogenerated by the 'packer hcl2_upgrade' command. We
+# recommend double checking that everything is correct before going forward. We
+# also recommend treating this file as disposable. The HCL2 blocks in this
+# file can be moved to other files. For example, the variable blocks could be
+# moved to their own 'variables.pkr.hcl' file, etc. Those files need to be
+# suffixed with '.pkr.hcl' to be visible to Packer. To use multiple files at
+# once they also need to be in the same folder. 'packer inspect folder/'
+# will describe to you what is in that folder.
+
+# Avoid mixing go templating calls ( for example ```{{ upper(`string`) }}``` )
+# and HCL2 calls (for example '${ var.string_value_example }' ). They won't be
+# executed together and the outcome will be unknown.
+
+# See https://www.packer.io/docs/templates/hcl_templates/blocks/packer for more info
+packer {
+ required_version = ">= 1.6.0"
+ required_plugins {
+ amazon = {
+ source = "github.com/hashicorp/amazon"
+ version = "~> 1"
+ }
+ }
+}
+
+# All generated input variables will be of 'string' type as this is how Packer JSON
+# views them; you can change their type later on. Read the variables type
+# constraints documentation
+# https://www.packer.io/docs/templates/hcl_templates/variables#type-constraints for more info.
+variable "aws_access_key" {
+ type = string
+ default = ""
+ sensitive = true
+}
+
+variable "aws_region" {
+ type = string
+}
+
+variable "aws_secondary_region" {
+ type = string
+ default = "${env("AWS_DEFAULT_REGION")}"
+}
+
+variable "aws_secret_key" {
+ type = string
+ default = ""
+ sensitive = true
+}
+
+variable "secret_account" {
+ type = string
+ default = "🤷"
+ sensitive = true
+}
+
+# The amazon-secretsmanager data block is generated from your aws_secretsmanager template function; a data
+# from this block can be referenced in source and locals blocks.
+# Read the documentation for data blocks here:
+# https://www.packer.io/docs/templates/hcl_templates/blocks/data
+# Read the documentation for the Amazon Secrets Manager Data Source here:
+# https://www.packer.io/plugins/datasources/amazon/secretsmanager
+data "amazon-secretsmanager" "autogenerated_1" {
+ name = "sample/app/password"
+}
+
+data "amazon-secretsmanager" "autogenerated_2" {
+ key = "api_key"
+ name = "sample/app/passwords"
+}
+
+data "amazon-secretsmanager" "autogenerated_3" {
+ name = "some_secret"
+}
+
+data "amazon-secretsmanager" "autogenerated_4" {
+ key = "with_key"
+ name = "some_secret"
+}
+
+# The amazon-ami data block is generated from your amazon builder source_ami_filter; a data
+# from this block can be referenced in source and locals blocks.
+# Read the documentation for data blocks here:
+# https://www.packer.io/docs/templates/hcl_templates/blocks/data
+# Read the documentation for the Amazon AMI Data Source here:
+# https://www.packer.io/plugins/datasources/amazon/ami
+data "amazon-ami" "autogenerated_1" {
+ access_key = "${var.aws_access_key}"
+ filters = {
+ name = "ubuntu/images/*/ubuntu-xenial-16.04-amd64-server-*"
+ root-device-type = "ebs"
+ virtualization-type = "hvm"
+ }
+ most_recent = true
+ owners = ["099720109477"]
+ region = "${var.aws_region}"
+ secret_key = "${var.aws_secret_key}"
+}
+
+# "timestamp" template function replacement
+locals { timestamp = regex_replace(timestamp(), "[- TZ:]", "") }
+
+# All locals variables are generated from variables that uses expressions
+# that are not allowed in HCL2 variables.
+# Read the documentation for locals blocks here:
+# https://www.packer.io/docs/templates/hcl_templates/blocks/locals
+local "password" {
+ sensitive = true
+ expression = "${data.amazon-secretsmanager.autogenerated_1.value}"
+}
+
+locals {
+ password_key = "MY_KEY_${data.amazon-secretsmanager.autogenerated_2.value}"
+}
+
+# source blocks are generated from your builders; a source can be referenced in
+# build blocks. A build block runs provisioner and post-processors on a
+# source. Read the documentation for source blocks here:
+# https://www.packer.io/docs/templates/hcl_templates/blocks/source
+source "amazon-ebs" "autogenerated_1" {
+ access_key = "${var.aws_access_key}"
+ ami_description = "Ubuntu 16.04 LTS - expand root partition"
+ ami_name = "ubuntu-16-04-test-${local.timestamp}"
+ encrypt_boot = true
+ launch_block_device_mappings {
+ delete_on_termination = true
+ device_name = "/dev/sda1"
+ volume_size = 48
+ volume_type = "gp2"
+ }
+ region = "${var.aws_region}"
+ secret_key = "${var.aws_secret_key}"
+ source_ami = "${data.amazon-ami.autogenerated_1.id}"
+ spot_instance_types = ["t2.small", "t2.medium", "t2.large"]
+ spot_price = "0.0075"
+ ssh_interface = "session_manager"
+ ssh_username = "ubuntu"
+ temporary_iam_instance_profile_policy_document {
+ Statement {
+ Action = ["*"]
+ Effect = "Allow"
+ Resource = ["*"]
+ }
+ Version = "2012-10-17"
+ }
+}
+
+source "amazon-ebs" "named_builder" {
+ access_key = "${var.aws_access_key}"
+ ami_description = "Ubuntu 16.04 LTS - expand root partition"
+ ami_name = "ubuntu-16-04-test-${local.timestamp}"
+ encrypt_boot = true
+ launch_block_device_mappings {
+ delete_on_termination = true
+ device_name = "/dev/sda1"
+ volume_size = 48
+ volume_type = "gp2"
+ }
+ region = "${var.aws_region}"
+ secret_key = "${var.aws_secret_key}"
+ source_ami = "${data.amazon-ami.autogenerated_1.id}"
+ spot_instance_types = ["t2.small", "t2.medium", "t2.large"]
+ spot_price = "0.0075"
+ ssh_interface = "session_manager"
+ ssh_username = "ubuntu"
+ temporary_iam_instance_profile_policy_document {
+ Statement {
+ Action = ["*"]
+ Effect = "Allow"
+ Resource = ["*"]
+ }
+ Version = "2012-10-17"
+ }
+}
+
+# a build block invokes sources and runs provisioning steps on them. The
+# documentation for build blocks can be found here:
+# https://www.packer.io/docs/templates/hcl_templates/blocks/build
+build {
+ sources = ["source.amazon-ebs.autogenerated_1", "source.amazon-ebs.named_builder"]
+
+ provisioner "breakpoint" {
+ only = ["amazon-ebs"]
+ pause_before = "5s"
+ }
+
+ provisioner "shell" {
+ except = ["amazon-ebs"]
+ inline = ["echo ${var.secret_account}", "echo ${build.ID}", "echo ${build.SSHPublicKey} | head -c 14", "echo ${path.root} is not ${path.cwd}", "echo ${packer.version}", "echo ${uuidv4()}"]
+ max_retries = "5"
+ }
+
+ provisioner "shell" {
+ inline = ["echo ${local.password}", "echo ${data.amazon-secretsmanager.autogenerated_1.value}", "echo ${local.password_key}", "echo ${data.amazon-secretsmanager.autogenerated_2.value}"]
+ }
+
+ provisioner "shell" {
+ inline = ["echo ${data.amazon-secretsmanager.autogenerated_3.value}", "echo ${data.amazon-secretsmanager.autogenerated_4.value}"]
+ }
+
+
+ # 1 error occurred upgrading the following block:
+ # unhandled "clean_resource_name" call:
+ # there is no way to automatically upgrade the "clean_resource_name" call.
+ # Please manually upgrade to use custom validation rules, `replace(string, substring, replacement)` or `regex_replace(string, substring, replacement)`
+ # Visit https://packer.io/docs/templates/hcl_templates/variables#custom-validation-rules , https://www.packer.io/docs/templates/hcl_templates/functions/string/replace or https://www.packer.io/docs/templates/hcl_templates/functions/string/regex_replace for more infos.
+ provisioner "shell" {
+ inline = ["echo mybuild-{{ clean_resource_name `${timestamp()}` }}"]
+ }
+
+
+ # 1 error occurred upgrading the following block:
+ # unhandled "lower" call:
+ # there is no way to automatically upgrade the "lower" call.
+ # Please manually upgrade to `lower(var.example)`
+ # Visit https://www.packer.io/docs/templates/hcl_templates/functions/string/lower for more infos.
+ provisioner "shell" {
+ inline = ["echo {{ lower `SOMETHING` }}"]
+ }
+
+
+ # 1 error occurred upgrading the following block:
+ # unhandled "upper" call:
+ # there is no way to automatically upgrade the "upper" call.
+ # Please manually upgrade to `upper(var.example)`
+ # Visit https://www.packer.io/docs/templates/hcl_templates/functions/string/upper for more infos.
+ provisioner "shell" {
+ inline = ["echo {{ upper `something` }}"]
+ }
+
+
+ # 1 error occurred upgrading the following block:
+ # unhandled "split" call:
+ # there is no way to automatically upgrade the "split" call.
+ # Please manually upgrade to `split(separator, string)`
+ # Visit https://www.packer.io/docs/templates/hcl_templates/functions/string/split for more infos.
+ provisioner "shell" {
+ inline = ["echo {{ split `some-string` `-` 0 }}"]
+ }
+
+
+ # 1 error occurred upgrading the following block:
+ # unhandled "replace_all" call:
+ # there is no way to automatically upgrade the "replace_all" call.
+ # Please manually upgrade to `replace(string, substring, replacement)` or `regex_replace(string, substring, replacement)`
+ # Visit https://www.packer.io/docs/templates/hcl_templates/functions/string/replace or https://www.packer.io/docs/templates/hcl_templates/functions/string/regex_replace for more infos.
+ provisioner "shell" {
+ inline = ["echo {{ replace_all `-` `/` `${build.name}` }}"]
+ }
+
+
+ # 1 error occurred upgrading the following block:
+ # unhandled "replace" call:
+ # there is no way to automatically upgrade the "replace" call.
+ # Please manually upgrade to `replace(string, substring, replacement)` or `regex_replace(string, substring, replacement)`
+ # Visit https://www.packer.io/docs/templates/hcl_templates/functions/string/replace or https://www.packer.io/docs/templates/hcl_templates/functions/string/regex_replace for more infos.
+ provisioner "shell" {
+ inline = ["echo {{ replace `some-string` `-` `/` 1 }}"]
+ }
+
+ provisioner "shell-local" {
+ inline = ["sleep 100000"]
+ only = ["amazon-ebs"]
+ pause_before = "5s"
+ timeout = "5s"
+ }
+
+ post-processor "amazon-import" {
+ format = "vmdk"
+ license_type = "BYOL"
+ region = "eu-west-3"
+ s3_bucket_name = "hashicorp.adrien"
+ tags = {
+ Description = "packer amazon-import ${local.timestamp}"
+ }
+ }
+ post-processors {
+ post-processor "artifice" {
+ keep_input_artifact = true
+ files = ["path/something.ova"]
+ name = "very_special_artifice_post-processor"
+ only = ["amazon-ebs"]
+ }
+ post-processor "amazon-import" {
+ except = ["amazon-ebs"]
+ license_type = "BYOL"
+ s3_bucket_name = "hashicorp.adrien"
+ tags = {
+ Description = "packer amazon-import ${local.timestamp}"
+ }
+ }
+ post-processor "compress" {
+ }
+ }
+}
diff --git a/v1.9.4/command/test-fixtures/hcl2_upgrade/complete/input.json b/v1.9.4/command/test-fixtures/hcl2_upgrade/complete/input.json
new file mode 100644
index 0000000..9d7af97
--- /dev/null
+++ b/v1.9.4/command/test-fixtures/hcl2_upgrade/complete/input.json
@@ -0,0 +1,246 @@
+{
+ "min_packer_version": "1.6.0",
+ "variables": {
+ "secret_account": "🤷",
+ "aws_region": null,
+ "aws_secondary_region": "{{ env `AWS_DEFAULT_REGION` }}",
+ "aws_secret_key": "",
+ "aws_access_key": "",
+ "password": "{{ aws_secretsmanager `sample/app/password` }}",
+ "password_key": "MY_KEY_{{ aws_secretsmanager `sample/app/passwords` `api_key` }}"
+ },
+ "sensitive-variables": [
+ "aws_secret_key",
+ "aws_access_key",
+ "secret_account",
+ "potato",
+ "password"
+ ],
+ "builders": [
+ {
+ "type": "amazon-ebs",
+ "region": "{{ user `aws_region` }}",
+ "secret_key": "{{ user `aws_secret_key` }}",
+ "access_key": "{{ user `aws_access_key` }}",
+ "ami_name": "ubuntu-16-04-test-{{ timestamp }}",
+ "ami_description": "Ubuntu 16.04 LTS - expand root partition",
+ "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
+ },
+ "launch_block_device_mappings": [
+ {
+ "delete_on_termination": true,
+ "device_name": "/dev/sda1",
+ "volume_type": "gp2",
+ "volume_size": 48
+ }
+ ],
+ "spot_price": "0.0075",
+ "spot_instance_types": [
+ "t2.small",
+ "t2.medium",
+ "t2.large"
+ ],
+ "encrypt_boot": true,
+ "ssh_username": "ubuntu",
+ "temporary_iam_instance_profile_policy_document": {
+ "Version": "2012-10-17",
+ "Statement": [
+ {
+ "Effect": "Allow",
+ "Action": [
+ "*"
+ ],
+ "Resource": ["*"]
+ }
+ ]
+ },
+ "ssh_interface": "session_manager"
+ },
+ {
+ "type": "amazon-ebs",
+ "name": "named_builder",
+ "region": "{{ user `aws_region` }}",
+ "secret_key": "{{ user `aws_secret_key` }}",
+ "access_key": "{{ user `aws_access_key` }}",
+ "ami_name": "ubuntu-16-04-test-{{ timestamp }}",
+ "ami_description": "Ubuntu 16.04 LTS - expand root partition",
+ "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
+ },
+ "launch_block_device_mappings": [
+ {
+ "delete_on_termination": true,
+ "device_name": "/dev/sda1",
+ "volume_type": "gp2",
+ "volume_size": 48
+ }
+ ],
+ "spot_price": "0.0075",
+ "spot_instance_types": [
+ "t2.small",
+ "t2.medium",
+ "t2.large"
+ ],
+ "encrypt_boot": true,
+ "ssh_username": "ubuntu",
+ "temporary_iam_instance_profile_policy_document": {
+ "Version": "2012-10-17",
+ "Statement": [
+ {
+ "Effect": "Allow",
+ "Action": [
+ "*"
+ ],
+ "Resource": ["*"]
+ }
+ ]
+ },
+ "ssh_interface": "session_manager"
+ }
+ ],
+ "provisioners": [
+ {
+ "type": "breakpoint",
+ "only": [
+ "amazon-ebs"
+ ],
+ "pause_before": "5s"
+ },
+ {
+ "type": "shell",
+ "except": [
+ "amazon-ebs"
+ ],
+ "max_retries": 5,
+ "inline": [
+ "echo {{ user `secret_account` }}",
+ "echo {{ build `ID` }}",
+ "echo {{ build `SSHPublicKey` }} | head -c 14",
+ "echo {{ template_dir }} is not {{ pwd }}",
+ "echo {{ packer_version }}",
+ "echo {{ uuid }}"
+ ]
+ },
+ {
+ "type": "shell",
+ "inline": [
+ "echo {{ user `password` }}",
+ "echo {{ aws_secretsmanager `sample/app/password` }}",
+ "echo {{ user `password_key` }}",
+ "echo {{ aws_secretsmanager `sample/app/passwords` `api_key` }}"
+ ]
+ },
+ {
+ "type": "shell",
+ "inline": [
+ "echo {{ aws_secretsmanager `some_secret` }}",
+ "echo {{ aws_secretsmanager `some_secret` `with_key` }}"
+ ]
+ },
+ {
+ "type": "shell",
+ "inline": [
+ "echo mybuild-{{isotime | clean_resource_name}}"
+ ]
+ },
+ {
+ "type": "shell",
+ "inline": [
+ "echo {{ `SOMETHING` | lower }}"
+ ]
+ },
+ {
+ "type": "shell",
+ "inline": [
+ "echo {{ `something` | upper }}"
+ ]
+ },
+ {
+ "type": "shell",
+ "inline": [
+ "echo {{ split `some-string` `-` 0 }}"
+ ]
+ },
+ {
+ "type": "shell",
+ "inline": [
+ "echo {{ replace_all `-` `/` build_name }}"
+ ]
+ },
+ {
+ "type": "shell",
+ "inline": [
+ "echo {{ replace `some-string` `-` 1 `/` }}"
+ ]
+ },
+ {
+ "type": "shell-local",
+ "only": [
+ "amazon-ebs"
+ ],
+ "timeout": "5s",
+ "pause_before": "5s",
+ "inline": [
+ "sleep 100000"
+ ]
+ }
+ ],
+ "post-processors": [
+ [
+ {
+ "type": "amazon-import",
+ "region": "eu-west-3",
+ "s3_bucket_name": "hashicorp.adrien",
+ "license_type": "BYOL",
+ "format": "vmdk",
+ "tags": {
+ "Description": "packer amazon-import {{timestamp}}"
+ }
+ }
+ ],
+ [
+ {
+ "only": [
+ "amazon-ebs"
+ ],
+ "files": [
+ "path/something.ova"
+ ],
+ "keep_input_artifact": true,
+ "name": "very_special_artifice_post-processor",
+ "type": "artifice"
+ },
+ {
+ "except": [
+ "amazon-ebs"
+ ],
+ "type": "amazon-import",
+ "s3_bucket_name": "hashicorp.adrien",
+ "license_type": "BYOL",
+ "tags": {
+ "Description": "packer amazon-import {{timestamp}}"
+ }
+ },
+ {
+ "type": "compress"
+ }
+ ]
+ ]
+}
\ No newline at end of file
diff --git a/v1.9.4/command/test-fixtures/hcl2_upgrade/error-cleanup-provisioner/expected.pkr.hcl b/v1.9.4/command/test-fixtures/hcl2_upgrade/error-cleanup-provisioner/expected.pkr.hcl
new file mode 100644
index 0000000..200fcc9
--- /dev/null
+++ b/v1.9.4/command/test-fixtures/hcl2_upgrade/error-cleanup-provisioner/expected.pkr.hcl
@@ -0,0 +1,36 @@
+# This file was autogenerated by the 'packer hcl2_upgrade' command. We
+# recommend double checking that everything is correct before going forward. We
+# also recommend treating this file as disposable. The HCL2 blocks in this
+# file can be moved to other files. For example, the variable blocks could be
+# moved to their own 'variables.pkr.hcl' file, etc. Those files need to be
+# suffixed with '.pkr.hcl' to be visible to Packer. To use multiple files at
+# once they also need to be in the same folder. 'packer inspect folder/'
+# will describe to you what is in that folder.
+
+# Avoid mixing go templating calls ( for example ```{{ upper(`string`) }}``` )
+# and HCL2 calls (for example '${ var.string_value_example }' ). They won't be
+# executed together and the outcome will be unknown.
+
+# source blocks are generated from your builders; a source can be referenced in
+# build blocks. A build block runs provisioner and post-processors on a
+# source. Read the documentation for source blocks here:
+# https://www.packer.io/docs/templates/hcl_templates/blocks/source
+source "null" "autogenerated_1" {
+ communicator = "none"
+}
+
+# a build block invokes sources and runs provisioning steps on them. The
+# documentation for build blocks can be found here:
+# https://www.packer.io/docs/templates/hcl_templates/blocks/build
+build {
+ sources = ["source.null.autogenerated_1"]
+
+ provisioner "shell-local" {
+ inline = ["exit 2"]
+ }
+
+ error-cleanup-provisioner "shell-local" {
+ inline = ["echo 'rubber ducky'> ducky.txt"]
+ }
+
+}
diff --git a/v1.9.4/command/test-fixtures/hcl2_upgrade/error-cleanup-provisioner/input.json b/v1.9.4/command/test-fixtures/hcl2_upgrade/error-cleanup-provisioner/input.json
new file mode 100644
index 0000000..971d9f5
--- /dev/null
+++ b/v1.9.4/command/test-fixtures/hcl2_upgrade/error-cleanup-provisioner/input.json
@@ -0,0 +1,18 @@
+{
+ "builders": [
+ {
+ "type": "null",
+ "communicator": "none"
+ }
+ ],
+ "provisioners": [
+ {
+ "type": "shell-local",
+ "inline": ["exit 2"]
+ }
+ ],
+ "error-cleanup-provisioner": {
+ "type": "shell-local",
+ "inline": ["echo 'rubber ducky'> ducky.txt"]
+ }
+}
\ No newline at end of file
diff --git a/v1.9.4/command/test-fixtures/hcl2_upgrade/escaping/expected.pkr.hcl b/v1.9.4/command/test-fixtures/hcl2_upgrade/escaping/expected.pkr.hcl
new file mode 100644
index 0000000..1cc690e
--- /dev/null
+++ b/v1.9.4/command/test-fixtures/hcl2_upgrade/escaping/expected.pkr.hcl
@@ -0,0 +1,41 @@
+
+variable "conf" {
+ type = string
+ default = "${env("ONE")}-${env("ANOTHER")}-${env("BACKTICKED")}"
+}
+
+variable "manyspaces" {
+ type = string
+ default = "${env("ASDFASDF")}"
+}
+
+variable "nospaces" {
+ type = string
+ default = "${env("SOMETHING")}"
+}
+
+locals { timestamp = regex_replace(timestamp(), "[- TZ:]", "") }
+# The "legacy_isotime" function has been provided for backwards compatability, but we recommend switching to the timestamp and formatdate functions.
+
+source "null" "autogenerated_1" {
+ communicator = "none"
+}
+
+build {
+ sources = ["source.null.autogenerated_1"]
+
+ provisioner "shell-local" {
+ inline = ["echo ${var.conf}-${local.timestamp}-${legacy_isotime("01-02-2006")}"]
+ }
+
+
+ # 1 error occurred upgrading the following block:
+ # unhandled "split" call:
+ # there is no way to automatically upgrade the "split" call.
+ # Please manually upgrade to `split(separator, string)`
+ # Visit https://www.packer.io/docs/templates/hcl_templates/functions/string/split for more infos.
+ provisioner "shell-local" {
+ inline = ["echo {{ split `some-string` `-` 0 }}"]
+ }
+
+}
diff --git a/v1.9.4/command/test-fixtures/hcl2_upgrade/escaping/input.json b/v1.9.4/command/test-fixtures/hcl2_upgrade/escaping/input.json
new file mode 100644
index 0000000..3304e69
--- /dev/null
+++ b/v1.9.4/command/test-fixtures/hcl2_upgrade/escaping/input.json
@@ -0,0 +1,27 @@
+{
+ "variables": {
+ "conf": "{{ env \"ONE\" }}-{{env \"ANOTHER\"}}-{{ env `BACKTICKED` }}",
+ "nospaces": "{{env \"SOMETHING\"}}",
+ "manyspaces": "{{ env \"ASDFASDF\"}}"
+ },
+ "builders": [
+ {
+ "type": "null",
+ "communicator": "none"
+ }
+ ],
+ "provisioners": [
+ {
+ "type": "shell-local",
+ "inline": [
+ "echo {{user \"conf\"}}-{{timestamp}}-{{isotime \"01-02-2006\"}}"
+ ]
+ },
+ {
+ "type": "shell-local",
+ "inline": [
+ "echo {{ split \"some-string\" \"-\" 0 }}"
+ ]
+ }
+ ]
+}
\ No newline at end of file
diff --git a/v1.9.4/command/test-fixtures/hcl2_upgrade/minimal/expected.pkr.hcl b/v1.9.4/command/test-fixtures/hcl2_upgrade/minimal/expected.pkr.hcl
new file mode 100644
index 0000000..316293c
--- /dev/null
+++ b/v1.9.4/command/test-fixtures/hcl2_upgrade/minimal/expected.pkr.hcl
@@ -0,0 +1,81 @@
+# This file was autogenerated by the 'packer hcl2_upgrade' command. We
+# recommend double checking that everything is correct before going forward. We
+# also recommend treating this file as disposable. The HCL2 blocks in this
+# file can be moved to other files. For example, the variable blocks could be
+# moved to their own 'variables.pkr.hcl' file, etc. Those files need to be
+# suffixed with '.pkr.hcl' to be visible to Packer. To use multiple files at
+# once they also need to be in the same folder. 'packer inspect folder/'
+# will describe to you what is in that folder.
+
+# Avoid mixing go templating calls ( for example ```{{ upper(`string`) }}``` )
+# and HCL2 calls (for example '${ var.string_value_example }' ). They won't be
+# executed together and the outcome will be unknown.
+
+# See https://www.packer.io/docs/templates/hcl_templates/blocks/packer for more info
+packer {
+ required_version = ">= 1.6.0"
+ required_plugins {
+ amazon = {
+ source = "github.com/hashicorp/amazon"
+ version = "~> 1"
+ }
+ }
+}
+
+# All generated input variables will be of 'string' type as this is how Packer JSON
+# views them; you can change their type later on. Read the variables type
+# constraints documentation
+# https://www.packer.io/docs/templates/hcl_templates/variables#type-constraints for more info.
+variable "aws_access_key" {
+ type = string
+ default = ""
+}
+
+variable "aws_region" {
+ type = string
+}
+
+variable "aws_secret_key" {
+ type = string
+ default = ""
+}
+
+# source blocks are generated from your builders; a source can be referenced in
+# build blocks. A build block runs provisioner and post-processors on a
+# source. Read the documentation for source blocks here:
+# https://www.packer.io/docs/templates/hcl_templates/blocks/source
+source "amazon-ebs" "autogenerated_1" {
+ access_key = "${var.aws_access_key}"
+ ami_description = "Ubuntu 16.04 LTS - expand root partition"
+ ami_name = "ubuntu-16-04-test"
+ encrypt_boot = true
+ launch_block_device_mappings {
+ delete_on_termination = true
+ device_name = "/dev/sda1"
+ volume_size = 48
+ volume_type = "gp2"
+ }
+ region = "${var.aws_region}"
+ secret_key = "${var.aws_secret_key}"
+ source_ami = "ami1234567"
+ spot_instance_types = ["t2.small", "t2.medium", "t2.large"]
+ spot_price = "0.0075"
+ ssh_interface = "session_manager"
+ ssh_username = "ubuntu"
+ temporary_iam_instance_profile_policy_document {
+ Statement {
+ Action = ["*"]
+ Effect = "Allow"
+ Resource = ["*"]
+ }
+ Version = "2012-10-17"
+ }
+}
+
+# a build block invokes sources and runs provisioning steps on them. The
+# documentation for build blocks can be found here:
+# https://www.packer.io/docs/templates/hcl_templates/blocks/build
+build {
+ sources = ["source.amazon-ebs.autogenerated_1"]
+
+}
diff --git a/v1.9.4/command/test-fixtures/hcl2_upgrade/minimal/input.json b/v1.9.4/command/test-fixtures/hcl2_upgrade/minimal/input.json
new file mode 100644
index 0000000..71109b9
--- /dev/null
+++ b/v1.9.4/command/test-fixtures/hcl2_upgrade/minimal/input.json
@@ -0,0 +1,48 @@
+{
+ "min_packer_version": "1.6.0",
+ "variables": {
+ "aws_region": null,
+ "aws_secret_key": "",
+ "aws_access_key": ""
+ },
+ "builders": [
+ {
+ "type": "amazon-ebs",
+ "region": "{{ user `aws_region` }}",
+ "secret_key": "{{ user `aws_secret_key` }}",
+ "access_key": "{{ user `aws_access_key` }}",
+ "ami_name": "ubuntu-16-04-test",
+ "ami_description": "Ubuntu 16.04 LTS - expand root partition",
+ "source_ami": "ami1234567",
+ "launch_block_device_mappings": [
+ {
+ "delete_on_termination": true,
+ "device_name": "/dev/sda1",
+ "volume_type": "gp2",
+ "volume_size": 48
+ }
+ ],
+ "spot_price": "0.0075",
+ "spot_instance_types": [
+ "t2.small",
+ "t2.medium",
+ "t2.large"
+ ],
+ "encrypt_boot": true,
+ "ssh_username": "ubuntu",
+ "temporary_iam_instance_profile_policy_document": {
+ "Version": "2012-10-17",
+ "Statement": [
+ {
+ "Effect": "Allow",
+ "Action": [
+ "*"
+ ],
+ "Resource": ["*"]
+ }
+ ]
+ },
+ "ssh_interface": "session_manager"
+ }
+ ]
+}
\ No newline at end of file
diff --git a/v1.9.4/command/test-fixtures/hcl2_upgrade/placeholders/expected.pkr.hcl b/v1.9.4/command/test-fixtures/hcl2_upgrade/placeholders/expected.pkr.hcl
new file mode 100644
index 0000000..04cd477
--- /dev/null
+++ b/v1.9.4/command/test-fixtures/hcl2_upgrade/placeholders/expected.pkr.hcl
@@ -0,0 +1,20 @@
+
+variable "envtest" {
+ type = string
+ default = "${env("Something")}"
+}
+
+variable "test" {
+ type = string
+ default = "{{ .Something }}"
+}
+
+source "null" "autogenerated_1" {
+ communicator = "none"
+ other_prop = "{{ .Else }}"
+}
+
+build {
+ sources = ["source.null.autogenerated_1"]
+
+}
diff --git a/v1.9.4/command/test-fixtures/hcl2_upgrade/placeholders/input.json b/v1.9.4/command/test-fixtures/hcl2_upgrade/placeholders/input.json
new file mode 100644
index 0000000..cf7d442
--- /dev/null
+++ b/v1.9.4/command/test-fixtures/hcl2_upgrade/placeholders/input.json
@@ -0,0 +1,13 @@
+{
+ "variables": {
+ "test": "{{ .Something }}",
+ "envtest": "{{ env \"Something\"}}"
+ },
+ "builders": [
+ {
+ "type": "null",
+ "communicator": "none",
+ "other_prop": "{{ .Else }}"
+ }
+ ]
+}
diff --git a/v1.9.4/command/test-fixtures/hcl2_upgrade/source-name/expected.pkr.hcl b/v1.9.4/command/test-fixtures/hcl2_upgrade/source-name/expected.pkr.hcl
new file mode 100644
index 0000000..c4145f7
--- /dev/null
+++ b/v1.9.4/command/test-fixtures/hcl2_upgrade/source-name/expected.pkr.hcl
@@ -0,0 +1,84 @@
+# This file was autogenerated by the 'packer hcl2_upgrade' command. We
+# recommend double checking that everything is correct before going forward. We
+# also recommend treating this file as disposable. The HCL2 blocks in this
+# file can be moved to other files. For example, the variable blocks could be
+# moved to their own 'variables.pkr.hcl' file, etc. Those files need to be
+# suffixed with '.pkr.hcl' to be visible to Packer. To use multiple files at
+# once they also need to be in the same folder. 'packer inspect folder/'
+# will describe to you what is in that folder.
+
+# Avoid mixing go templating calls ( for example ```{{ upper(`string`) }}``` )
+# and HCL2 calls (for example '${ var.string_value_example }' ). They won't be
+# executed together and the outcome will be unknown.
+
+# See https://www.packer.io/docs/templates/hcl_templates/blocks/packer for more info
+packer {
+ required_version = ">= 1.6.0"
+ required_plugins {
+ amazon = {
+ source = "github.com/hashicorp/amazon"
+ version = "~> 1"
+ }
+ }
+}
+
+# All generated input variables will be of 'string' type as this is how Packer JSON
+# views them; you can change their type later on. Read the variables type
+# constraints documentation
+# https://www.packer.io/docs/templates/hcl_templates/variables#type-constraints for more info.
+variable "aws_access_key" {
+ type = string
+ default = ""
+}
+
+variable "aws_region" {
+ type = string
+}
+
+variable "aws_secret_key" {
+ type = string
+ default = ""
+}
+
+# "timestamp" template function replacement
+locals { timestamp = regex_replace(timestamp(), "[- TZ:]", "") }
+
+# source blocks are generated from your builders; a source can be referenced in
+# build blocks. A build block runs provisioner and post-processors on a
+# source. Read the documentation for source blocks here:
+# https://www.packer.io/docs/templates/hcl_templates/blocks/source
+source "amazon-ebs" "party_parrot" {
+ access_key = "${var.aws_access_key}"
+ ami_description = "Ubuntu 16.04 LTS - expand root partition"
+ ami_name = "ubuntu-16-04-test-${local.timestamp}"
+ encrypt_boot = true
+ launch_block_device_mappings {
+ delete_on_termination = true
+ device_name = "/dev/sda1"
+ volume_size = 48
+ volume_type = "gp2"
+ }
+ region = "${var.aws_region}"
+ secret_key = "${var.aws_secret_key}"
+ source_ami = "ami1234567"
+ spot_instance_types = ["t2.small", "t2.medium", "t2.large"]
+ spot_price = "0.0075"
+ ssh_interface = "session_manager"
+ ssh_username = "ubuntu"
+ temporary_iam_instance_profile_policy_document {
+ Statement {
+ Action = ["*"]
+ Effect = "Allow"
+ Resource = ["*"]
+ }
+ Version = "2012-10-17"
+ }
+}
+
+# a build block invokes sources and runs provisioning steps on them. The
+# documentation for build blocks can be found here:
+# https://www.packer.io/docs/templates/hcl_templates/blocks/build
+build {
+ sources = ["source.amazon-ebs.party_parrot"]
+
+}
diff --git a/v1.9.4/command/test-fixtures/hcl2_upgrade/source-name/input.json b/v1.9.4/command/test-fixtures/hcl2_upgrade/source-name/input.json
new file mode 100644
index 0000000..1c271a7
--- /dev/null
+++ b/v1.9.4/command/test-fixtures/hcl2_upgrade/source-name/input.json
@@ -0,0 +1,49 @@
+{
+ "min_packer_version": "1.6.0",
+ "variables": {
+ "aws_region": null,
+ "aws_secret_key": "",
+ "aws_access_key": ""
+ },
+ "builders": [
+ {
+ "type": "amazon-ebs",
+ "name": " party parrot ",
+ "region": "{{ user `aws_region` }}",
+ "secret_key": "{{ user `aws_secret_key` }}",
+ "access_key": "{{ user `aws_access_key` }}",
+ "ami_name": "ubuntu-16-04-test-{{ timestamp }}",
+ "ami_description": "Ubuntu 16.04 LTS - expand root partition",
+ "source_ami": "ami1234567",
+ "launch_block_device_mappings": [
+ {
+ "delete_on_termination": true,
+ "device_name": "/dev/sda1",
+ "volume_type": "gp2",
+ "volume_size": 48
+ }
+ ],
+ "spot_price": "0.0075",
+ "spot_instance_types": [
+ "t2.small",
+ "t2.medium",
+ "t2.large"
+ ],
+ "encrypt_boot": true,
+ "ssh_username": "ubuntu",
+ "temporary_iam_instance_profile_policy_document": {
+ "Version": "2012-10-17",
+ "Statement": [
+ {
+ "Effect": "Allow",
+ "Action": [
+ "*"
+ ],
+ "Resource": ["*"]
+ }
+ ]
+ },
+ "ssh_interface": "session_manager"
+ }
+ ]
+}
\ No newline at end of file
diff --git a/v1.9.4/command/test-fixtures/hcl2_upgrade/undeclared-variables/expected.pkr.hcl b/v1.9.4/command/test-fixtures/hcl2_upgrade/undeclared-variables/expected.pkr.hcl
new file mode 100644
index 0000000..cee87f9
--- /dev/null
+++ b/v1.9.4/command/test-fixtures/hcl2_upgrade/undeclared-variables/expected.pkr.hcl
@@ -0,0 +1,26 @@
+
+variable "communicator_type" {
+ type = string
+}
+
+variable "foo" {
+ type = string
+ default = "bar"
+}
+
+variable "scriptpath" {
+ type = string
+}
+
+source "null" "autogenerated_1" {
+ communicator = "${var.communicator_type}"
+}
+
+build {
+ sources = ["source.null.autogenerated_1"]
+
+ provisioner "shell" {
+ script = "${var.scriptpath}"
+ }
+
+}
diff --git a/v1.9.4/command/test-fixtures/hcl2_upgrade/undeclared-variables/input.json b/v1.9.4/command/test-fixtures/hcl2_upgrade/undeclared-variables/input.json
new file mode 100644
index 0000000..ba6e198
--- /dev/null
+++ b/v1.9.4/command/test-fixtures/hcl2_upgrade/undeclared-variables/input.json
@@ -0,0 +1,18 @@
+{
+ "variables": {
+ "foo": "bar"
+ },
+ "builders": [
+ {
+ "type": "null",
+ "communicator": "{{ user `communicator_type` }}"
+ }
+ ],
+ "provisioners": [
+ {
+ "type": "shell",
+ "script": "{{user `scriptpath`}}"
+ }
+ ]
+}
+
diff --git a/v1.9.4/command/test-fixtures/hcl2_upgrade/unknown_builder/expected.pkr.hcl b/v1.9.4/command/test-fixtures/hcl2_upgrade/unknown_builder/expected.pkr.hcl
new file mode 100644
index 0000000..62e07e6
--- /dev/null
+++ b/v1.9.4/command/test-fixtures/hcl2_upgrade/unknown_builder/expected.pkr.hcl
@@ -0,0 +1,50 @@
+packer {
+ required_version = ">= 1.6.0"
+}
+
+variable "aws_access_key" {
+ type = string
+ default = ""
+}
+
+variable "aws_region" {
+ type = string
+}
+
+variable "aws_secret_key" {
+ type = string
+ default = ""
+}
+
+source "potatoes" "autogenerated_1" {
+ access_key = "${var.aws_access_key}"
+ ami_description = "Ubuntu 16.04 LTS - expand root partition"
+ ami_name = "ubuntu-16-04-test"
+ encrypt_boot = true
+ launch_block_device_mappings {
+ delete_on_termination = true
+ device_name = "/dev/sda1"
+ volume_size = 48
+ volume_type = "gp2"
+ }
+ region = "${var.aws_region}"
+ secret_key = "${var.aws_secret_key}"
+ source_ami = "ami1234567"
+ spot_instance_types = ["t2.small", "t2.medium", "t2.large"]
+ spot_price = "0.0075"
+ ssh_interface = "session_manager"
+ ssh_username = "ubuntu"
+ temporary_iam_instance_profile_policy_document {
+ Statement {
+ Action = ["*"]
+ Effect = "Allow"
+ Resource = ["*"]
+ }
+ Version = "2012-10-17"
+ }
+}
+
+build {
+ sources = ["source.potatoes.autogenerated_1"]
+
+}
diff --git a/v1.9.4/command/test-fixtures/hcl2_upgrade/unknown_builder/input.json b/v1.9.4/command/test-fixtures/hcl2_upgrade/unknown_builder/input.json
new file mode 100644
index 0000000..774dac4
--- /dev/null
+++ b/v1.9.4/command/test-fixtures/hcl2_upgrade/unknown_builder/input.json
@@ -0,0 +1,48 @@
+{
+ "min_packer_version": "1.6.0",
+ "variables": {
+ "aws_region": null,
+ "aws_secret_key": "",
+ "aws_access_key": ""
+ },
+ "builders": [
+ {
+ "type": "potatoes",
+ "region": "{{ user `aws_region` }}",
+ "secret_key": "{{ user `aws_secret_key` }}",
+ "access_key": "{{ user `aws_access_key` }}",
+ "ami_name": "ubuntu-16-04-test",
+ "ami_description": "Ubuntu 16.04 LTS - expand root partition",
+ "source_ami": "ami1234567",
+ "launch_block_device_mappings": [
+ {
+ "delete_on_termination": true,
+ "device_name": "/dev/sda1",
+ "volume_type": "gp2",
+ "volume_size": 48
+ }
+ ],
+ "spot_price": "0.0075",
+ "spot_instance_types": [
+ "t2.small",
+ "t2.medium",
+ "t2.large"
+ ],
+ "encrypt_boot": true,
+ "ssh_username": "ubuntu",
+ "temporary_iam_instance_profile_policy_document": {
+ "Version": "2012-10-17",
+ "Statement": [
+ {
+ "Effect": "Allow",
+ "Action": [
+ "*"
+ ],
+ "Resource": ["*"]
+ }
+ ]
+ },
+ "ssh_interface": "session_manager"
+ }
+ ]
+}
\ No newline at end of file
diff --git a/v1.9.4/command/test-fixtures/hcl2_upgrade/varfile-with-no-variables-block/expected.pkr.hcl b/v1.9.4/command/test-fixtures/hcl2_upgrade/varfile-with-no-variables-block/expected.pkr.hcl
new file mode 100644
index 0000000..c2e5767
--- /dev/null
+++ b/v1.9.4/command/test-fixtures/hcl2_upgrade/varfile-with-no-variables-block/expected.pkr.hcl
@@ -0,0 +1,33 @@
+
+variable "ssh_host" {
+ type = string
+}
+
+variable "ssh_password" {
+ type = string
+}
+
+variable "ssh_username" {
+ type = string
+}
+
+variable "version_tag" {
+ type = string
+}
+
+source "null" "autogenerated_1" {
+ communicator = "ssh"
+ ssh_host = "${var.ssh_host}"
+ ssh_password = "${var.ssh_password}"
+ ssh_username = "${var.ssh_username}"
+}
+
+build {
+ sources = ["source.null.autogenerated_1"]
+
+ provisioner "shell-local" {
+ inline = ["echo ${var.version_tag} > provision.txt"]
+ pause_before = "20s"
+ }
+
+}
diff --git a/v1.9.4/command/test-fixtures/hcl2_upgrade/varfile-with-no-variables-block/input.json b/v1.9.4/command/test-fixtures/hcl2_upgrade/varfile-with-no-variables-block/input.json
new file mode 100644
index 0000000..bb901d0
--- /dev/null
+++ b/v1.9.4/command/test-fixtures/hcl2_upgrade/varfile-with-no-variables-block/input.json
@@ -0,0 +1,18 @@
+{
+ "builders": [
+ {
+ "type": "null",
+ "communicator": "ssh",
+ "ssh_host": "{{ user `ssh_host` }}",
+ "ssh_password": "{{ user `ssh_password` }}",
+ "ssh_username": "{{ user `ssh_username` }}"
+ }
+ ],
+ "provisioners": [
+ {
+ "pause_before": "20s",
+ "type": "shell-local",
+ "inline": [ "echo {{ user `version_tag` }} > provision.txt" ]
+ }
+ ]
+}
diff --git a/v1.9.4/command/test-fixtures/hcl2_upgrade/varfile-with-no-variables-block/variables.json b/v1.9.4/command/test-fixtures/hcl2_upgrade/varfile-with-no-variables-block/variables.json
new file mode 100644
index 0000000..4e4b93c
--- /dev/null
+++ b/v1.9.4/command/test-fixtures/hcl2_upgrade/varfile-with-no-variables-block/variables.json
@@ -0,0 +1,6 @@
+{
+ "version_tag": "1.0.0",
+ "ssh_host": "localhost",
+ "ssh_username": "packer",
+ "ssh_password": "packer"
+}
diff --git a/v1.9.4/command/test-fixtures/hcl2_upgrade/variables-only/expected.pkr.hcl b/v1.9.4/command/test-fixtures/hcl2_upgrade/variables-only/expected.pkr.hcl
new file mode 100644
index 0000000..a78a2ba
--- /dev/null
+++ b/v1.9.4/command/test-fixtures/hcl2_upgrade/variables-only/expected.pkr.hcl
@@ -0,0 +1,47 @@
+
+variable "aws_access_key" {
+ type = string
+ default = ""
+ sensitive = true
+}
+
+variable "aws_region" {
+ type = string
+}
+
+variable "aws_secondary_region" {
+ type = string
+ default = "${env("AWS_DEFAULT_REGION")}"
+}
+
+variable "aws_secret_key" {
+ type = string
+ default = ""
+ sensitive = true
+}
+
+variable "secret_account" {
+ type = string
+ default = "🤷"
+ sensitive = true
+}
+
+data "amazon-secretsmanager" "autogenerated_1" {
+ name = "sample/app/password"
+}
+
+data "amazon-secretsmanager" "autogenerated_2" {
+ key = "api_key"
+ name = "sample/app/passwords"
+}
+# The "legacy_strftime" function has been provided for backwards compatability, but we recommend switching to the timestamp and formatdate functions.
+
+local "password" {
+ sensitive = true
+ expression = "${data.amazon-secretsmanager.autogenerated_1.value}"
+}
+
+locals {
+ ami_description = "AMI ${legacy_strftime("%Y-%m")}"
+ password_key = "MY_KEY_${data.amazon-secretsmanager.autogenerated_2.value}"
+}
diff --git a/v1.9.4/command/test-fixtures/hcl2_upgrade/variables-only/input.json b/v1.9.4/command/test-fixtures/hcl2_upgrade/variables-only/input.json
new file mode 100644
index 0000000..949d177
--- /dev/null
+++ b/v1.9.4/command/test-fixtures/hcl2_upgrade/variables-only/input.json
@@ -0,0 +1,19 @@
+{
+ "variables": {
+ "secret_account": "🤷",
+ "aws_region": null,
+ "aws_secondary_region": "{{ env `AWS_DEFAULT_REGION` }}",
+ "aws_secret_key": "",
+ "aws_access_key": "",
+ "password": "{{ aws_secretsmanager `sample/app/password` }}",
+ "ami_description": "AMI {{strftime \"%Y-%m\"}}",
+ "password_key": "MY_KEY_{{ aws_secretsmanager `sample/app/passwords` `api_key` }}"
+ },
+ "sensitive-variables": [
+ "aws_secret_key",
+ "aws_access_key",
+ "secret_account",
+ "potato",
+ "password"
+ ]
+}
\ No newline at end of file
diff --git a/v1.9.4/command/test-fixtures/hcl2_upgrade/variables-with-variables/expected.pkr.hcl b/v1.9.4/command/test-fixtures/hcl2_upgrade/variables-with-variables/expected.pkr.hcl
new file mode 100644
index 0000000..d3838ed
--- /dev/null
+++ b/v1.9.4/command/test-fixtures/hcl2_upgrade/variables-with-variables/expected.pkr.hcl
@@ -0,0 +1,25 @@
+
+variable "aws_access_key" {
+ type = string
+ default = ""
+ sensitive = true
+}
+
+variable "aws_region" {
+ type = string
+}
+
+variable "aws_secret_key" {
+ type = string
+ default = ""
+ sensitive = true
+}
+
+local "password" {
+ sensitive = true
+ expression = "${var.aws_secret_key}-${var.aws_access_key}"
+}
+
+locals {
+ aws_secondary_region = "${var.aws_region}"
+}
diff --git a/v1.9.4/command/test-fixtures/hcl2_upgrade/variables-with-variables/input.json b/v1.9.4/command/test-fixtures/hcl2_upgrade/variables-with-variables/input.json
new file mode 100644
index 0000000..4696945
--- /dev/null
+++ b/v1.9.4/command/test-fixtures/hcl2_upgrade/variables-with-variables/input.json
@@ -0,0 +1,14 @@
+{
+ "variables": {
+ "aws_region": null,
+ "aws_secondary_region": "{{ user `aws_region` }}",
+ "aws_secret_key": "",
+ "aws_access_key": "",
+ "password": "{{ user `aws_secret_key` }}-{{ user `aws_access_key` }}"
+ },
+ "sensitive-variables": [
+ "aws_secret_key",
+ "aws_access_key",
+ "password"
+ ]
+}
\ No newline at end of file
diff --git a/v1.9.4/command/test-fixtures/hcl2_upgrade/vsphere_linux_options_and_network_interface/expected.pkr.hcl b/v1.9.4/command/test-fixtures/hcl2_upgrade/vsphere_linux_options_and_network_interface/expected.pkr.hcl
new file mode 100644
index 0000000..16c3c21
--- /dev/null
+++ b/v1.9.4/command/test-fixtures/hcl2_upgrade/vsphere_linux_options_and_network_interface/expected.pkr.hcl
@@ -0,0 +1,49 @@
+packer {
+ required_plugins {
+ vsphere = {
+ source = "github.com/hashicorp/vsphere"
+ version = "~> 1"
+ }
+ }
+}
+
+source "vsphere-clone" "autogenerated_1" {
+ RAM_reserve_all = false
+ cluster = "USER_VALUE"
+ convert_to_template = false
+ customize {
+ dns_server_list = ["192.168.254.1", "192.168.254.2"]
+ ipv4_gateway = "172.15.102.254"
+ linux_options {
+ domain = "test.internal"
+ host_name = "packer-test"
+ }
+ network_interface {
+ ipv4_address = "172.15.102.202"
+ ipv4_netmask = "24"
+ }
+ }
+ datacenter = "USER_VALUE"
+ datastore = "USER_VALUE"
+ disable_shutdown = true
+ disk_controller_type = ["pvscsi", "pvscsi"]
+ insecure_connection = "true"
+ network = "USER_VALUE"
+ notes = "Build via Packer"
+ password = "USER_VALUE"
+ ssh_password = "Aa123456"
+ ssh_username = "root"
+ storage {
+ disk_controller_index = 0
+ disk_size = 100000
+ }
+ template = "erez's template"
+ username = "USER_VALUE"
+ vcenter_server = "USER_VALUE"
+ vm_name = "USER_VALUE"
+}
+
+build {
+ sources = ["source.vsphere-clone.autogenerated_1"]
+
+}
diff --git a/v1.9.4/command/test-fixtures/hcl2_upgrade/vsphere_linux_options_and_network_interface/input.json b/v1.9.4/command/test-fixtures/hcl2_upgrade/vsphere_linux_options_and_network_interface/input.json
new file mode 100644
index 0000000..2fc3f3a
--- /dev/null
+++ b/v1.9.4/command/test-fixtures/hcl2_upgrade/vsphere_linux_options_and_network_interface/input.json
@@ -0,0 +1,48 @@
+{
+ "builders": [
+ {
+ "disable_shutdown": true,
+ "type": "vsphere-clone",
+ "vcenter_server": "USER_VALUE",
+ "username": "USER_VALUE",
+ "password": "USER_VALUE",
+ "insecure_connection": "true",
+ "datacenter": "USER_VALUE",
+ "cluster": "USER_VALUE",
+ "network": "USER_VALUE",
+ "datastore": "USER_VALUE",
+ "vm_name": "USER_VALUE",
+ "notes": "Build via Packer",
+ "ssh_username": "root",
+ "ssh_password": "Aa123456",
+ "template": "erez's template",
+ "RAM_reserve_all": false,
+ "convert_to_template": false,
+ "disk_controller_type": [
+ "pvscsi",
+ "pvscsi"
+ ],
+ "storage": [
+ {
+ "disk_controller_index": 0,
+ "disk_size": 100000
+ }
+ ],
+ "customize": {
+ "linux_options": {
+ "host_name": "packer-test",
+ "domain": "test.internal"
+ },
+ "network_interface": {
+ "ipv4_address": "172.15.102.202",
+ "ipv4_netmask": "24"
+ },
+ "ipv4_gateway": "172.15.102.254",
+ "dns_server_list": [
+ "192.168.254.1",
+ "192.168.254.2"
+ ]
+ }
+ }
+ ]
+}
\ No newline at end of file
diff --git a/v1.9.4/command/test-fixtures/hcl2_upgrade/without-annotations/expected.pkr.hcl b/v1.9.4/command/test-fixtures/hcl2_upgrade/without-annotations/expected.pkr.hcl
new file mode 100644
index 0000000..414ebc5
--- /dev/null
+++ b/v1.9.4/command/test-fixtures/hcl2_upgrade/without-annotations/expected.pkr.hcl
@@ -0,0 +1,244 @@
+packer {
+ required_version = ">= 1.6.0"
+ required_plugins {
+ amazon = {
+ source = "github.com/hashicorp/amazon"
+ version = "~> 1"
+ }
+ }
+}
+
+variable "aws_access_key" {
+ type = string
+ default = ""
+ sensitive = true
+}
+
+variable "aws_region" {
+ type = string
+}
+
+variable "aws_secondary_region" {
+ type = string
+ default = "${env("AWS_DEFAULT_REGION")}"
+}
+
+variable "aws_secret_key" {
+ type = string
+ default = ""
+ sensitive = true
+}
+
+variable "secret_account" {
+ type = string
+ default = "🤷"
+ sensitive = true
+}
+
+data "amazon-secretsmanager" "autogenerated_1" {
+ name = "sample/app/password"
+}
+
+data "amazon-secretsmanager" "autogenerated_2" {
+ key = "api_key"
+ name = "sample/app/passwords"
+}
+
+data "amazon-secretsmanager" "autogenerated_3" {
+ name = "some_secret"
+}
+
+data "amazon-secretsmanager" "autogenerated_4" {
+ key = "with_key"
+ name = "some_secret"
+}
+
+data "amazon-ami" "autogenerated_1" {
+ access_key = "${var.aws_access_key}"
+ filters = {
+ name = "ubuntu/images/*/ubuntu-xenial-16.04-amd64-server-*"
+ root-device-type = "ebs"
+ virtualization-type = "hvm"
+ }
+ most_recent = true
+ owners = ["099720109477"]
+ region = "${var.aws_region}"
+ secret_key = "${var.aws_secret_key}"
+}
+
+locals { timestamp = regex_replace(timestamp(), "[- TZ:]", "") }
+
+local "password" {
+ sensitive = true
+ expression = "${data.amazon-secretsmanager.autogenerated_1.value}"
+}
+
+locals {
+ password_key = "MY_KEY_${data.amazon-secretsmanager.autogenerated_2.value}"
+}
+
+source "amazon-ebs" "autogenerated_1" {
+ access_key = "${var.aws_access_key}"
+ ami_description = "Ubuntu 16.04 LTS - expand root partition"
+ ami_name = "ubuntu-16-04-test-${local.timestamp}"
+ encrypt_boot = true
+ launch_block_device_mappings {
+ delete_on_termination = true
+ device_name = "/dev/sda1"
+ volume_size = 48
+ volume_type = "gp2"
+ }
+ region = "${var.aws_region}"
+ secret_key = "${var.aws_secret_key}"
+ source_ami = "${data.amazon-ami.autogenerated_1.id}"
+ spot_instance_types = ["t2.small", "t2.medium", "t2.large"]
+ spot_price = "0.0075"
+ ssh_interface = "session_manager"
+ ssh_username = "ubuntu"
+ temporary_iam_instance_profile_policy_document {
+ Statement {
+ Action = ["*"]
+ Effect = "Allow"
+ Resource = ["*"]
+ }
+ Version = "2012-10-17"
+ }
+}
+
+source "amazon-ebs" "named_builder" {
+ access_key = "${var.aws_access_key}"
+ ami_description = "Ubuntu 16.04 LTS - expand root partition"
+ ami_name = "ubuntu-16-04-test-${local.timestamp}"
+ encrypt_boot = true
+ launch_block_device_mappings {
+ delete_on_termination = true
+ device_name = "/dev/sda1"
+ volume_size = 48
+ volume_type = "gp2"
+ }
+ region = "${var.aws_region}"
+ secret_key = "${var.aws_secret_key}"
+ source_ami = "${data.amazon-ami.autogenerated_1.id}"
+ spot_instance_types = ["t2.small", "t2.medium", "t2.large"]
+ spot_price = "0.0075"
+ ssh_interface = "session_manager"
+ ssh_username = "ubuntu"
+ temporary_iam_instance_profile_policy_document {
+ Statement {
+ Action = ["*"]
+ Effect = "Allow"
+ Resource = ["*"]
+ }
+ Version = "2012-10-17"
+ }
+}
+
+build {
+ sources = ["source.amazon-ebs.autogenerated_1", "source.amazon-ebs.named_builder"]
+
+ provisioner "shell" {
+ except = ["amazon-ebs"]
+ inline = ["echo ${var.secret_account}", "echo ${build.ID}", "echo ${build.SSHPublicKey} | head -c 14", "echo ${path.root} is not ${path.cwd}", "echo ${packer.version}", "echo ${uuidv4()}"]
+ max_retries = "5"
+ }
+
+ provisioner "shell" {
+ inline = ["echo ${local.password}", "echo ${data.amazon-secretsmanager.autogenerated_1.value}", "echo ${local.password_key}", "echo ${data.amazon-secretsmanager.autogenerated_2.value}"]
+ }
+
+ provisioner "shell" {
+ inline = ["echo ${data.amazon-secretsmanager.autogenerated_3.value}", "echo ${data.amazon-secretsmanager.autogenerated_4.value}"]
+ }
+
+
+ # 1 error occurred upgrading the following block:
+ # unhandled "clean_resource_name" call:
+ # there is no way to automatically upgrade the "clean_resource_name" call.
+ # Please manually upgrade to use custom validation rules, `replace(string, substring, replacement)` or `regex_replace(string, substring, replacement)`
+ # Visit https://packer.io/docs/templates/hcl_templates/variables#custom-validation-rules , https://www.packer.io/docs/templates/hcl_templates/functions/string/replace or https://www.packer.io/docs/templates/hcl_templates/functions/string/regex_replace for more infos.
+ provisioner "shell" {
+ inline = ["echo mybuild-{{ clean_resource_name `${timestamp()}` }}"]
+ }
+
+
+ # 1 error occurred upgrading the following block:
+ # unhandled "lower" call:
+ # there is no way to automatically upgrade the "lower" call.
+ # Please manually upgrade to `lower(var.example)`
+ # Visit https://www.packer.io/docs/templates/hcl_templates/functions/string/lower for more infos.
+ provisioner "shell" {
+ inline = ["echo {{ lower `SOMETHING` }}"]
+ }
+
+
+ # 1 error occurred upgrading the following block:
+ # unhandled "upper" call:
+ # there is no way to automatically upgrade the "upper" call.
+ # Please manually upgrade to `upper(var.example)`
+ # Visit https://www.packer.io/docs/templates/hcl_templates/functions/string/upper for more infos.
+ provisioner "shell" {
+ inline = ["echo {{ upper `something` }}"]
+ }
+
+
+ # 1 error occurred upgrading the following block:
+ # unhandled "split" call:
+ # there is no way to automatically upgrade the "split" call.
+ # Please manually upgrade to `split(separator, string)`
+ # Visit https://www.packer.io/docs/templates/hcl_templates/functions/string/split for more infos.
+ provisioner "shell" {
+ inline = ["echo {{ split `some-string` `-` 0 }}"]
+ }
+
+
+ # 1 error occurred upgrading the following block:
+ # unhandled "replace_all" call:
+ # there is no way to automatically upgrade the "replace_all" call.
+ # Please manually upgrade to `replace(string, substring, replacement)` or `regex_replace(string, substring, replacement)`
+ # Visit https://www.packer.io/docs/templates/hcl_templates/functions/string/replace or https://www.packer.io/docs/templates/hcl_templates/functions/string/regex_replace for more infos.
+ provisioner "shell" {
+ inline = ["echo {{ replace_all `-` `/` `${build.name}` }}"]
+ }
+
+
+ # 1 error occurred upgrading the following block:
+ # unhandled "replace" call:
+ # there is no way to automatically upgrade the "replace" call.
+ # Please manually upgrade to `replace(string, substring, replacement)` or `regex_replace(string, substring, replacement)`
+ # Visit https://www.packer.io/docs/templates/hcl_templates/functions/string/replace or https://www.packer.io/docs/templates/hcl_templates/functions/string/regex_replace for more infos.
+ provisioner "shell" {
+ inline = ["echo {{ replace `some-string` `-` `/` 1 }}"]
+ }
+
+ provisioner "shell-local" {
+ inline = ["sleep 100000"]
+ only = ["amazon-ebs"]
+ timeout = "5s"
+ }
+
+ post-processor "amazon-import" {
+ format = "vmdk"
+ license_type = "BYOL"
+ region = "eu-west-3"
+ s3_bucket_name = "hashicorp.adrien"
+ tags = {
+ Description = "packer amazon-import ${local.timestamp}"
+ }
+ }
+ post-processors {
+ post-processor "artifice" {
+ keep_input_artifact = true
+ files = ["path/something.ova"]
+ name = "very_special_artifice_post-processor"
+ only = ["amazon-ebs"]
+ }
+ post-processor "amazon-import" {
+ except = ["amazon-ebs"]
+ license_type = "BYOL"
+ s3_bucket_name = "hashicorp.adrien"
+ tags = {
+ Description = "packer amazon-import ${local.timestamp}"
+ }
+ }
+ }
+}
diff --git a/v1.9.4/command/test-fixtures/hcl2_upgrade/without-annotations/input.json b/v1.9.4/command/test-fixtures/hcl2_upgrade/without-annotations/input.json
new file mode 100644
index 0000000..fdd5cf2
--- /dev/null
+++ b/v1.9.4/command/test-fixtures/hcl2_upgrade/without-annotations/input.json
@@ -0,0 +1,235 @@
+{
+ "min_packer_version": "1.6.0",
+ "variables": {
+ "secret_account": "🤷",
+ "aws_region": null,
+ "aws_secondary_region": "{{ env `AWS_DEFAULT_REGION` }}",
+ "aws_secret_key": "",
+ "aws_access_key": "",
+ "password": "{{ aws_secretsmanager `sample/app/password` }}",
+ "password_key": "MY_KEY_{{ aws_secretsmanager `sample/app/passwords` `api_key` }}"
+ },
+ "sensitive-variables": [
+ "aws_secret_key",
+ "aws_access_key",
+ "secret_account",
+ "potato",
+ "password"
+ ],
+ "builders": [
+ {
+ "type": "amazon-ebs",
+ "region": "{{ user `aws_region` }}",
+ "secret_key": "{{ user `aws_secret_key` }}",
+ "access_key": "{{ user `aws_access_key` }}",
+ "ami_name": "ubuntu-16-04-test-{{ timestamp }}",
+ "ami_description": "Ubuntu 16.04 LTS - expand root partition",
+ "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
+ },
+ "launch_block_device_mappings": [
+ {
+ "delete_on_termination": true,
+ "device_name": "/dev/sda1",
+ "volume_type": "gp2",
+ "volume_size": 48
+ }
+ ],
+ "spot_price": "0.0075",
+ "spot_instance_types": [
+ "t2.small",
+ "t2.medium",
+ "t2.large"
+ ],
+ "encrypt_boot": true,
+ "ssh_username": "ubuntu",
+ "temporary_iam_instance_profile_policy_document": {
+ "Version": "2012-10-17",
+ "Statement": [
+ {
+ "Effect": "Allow",
+ "Action": [
+ "*"
+ ],
+ "Resource": ["*"]
+ }
+ ]
+ },
+ "ssh_interface": "session_manager"
+ },
+ {
+ "type": "amazon-ebs",
+ "name": "named_builder",
+ "region": "{{ user `aws_region` }}",
+ "secret_key": "{{ user `aws_secret_key` }}",
+ "access_key": "{{ user `aws_access_key` }}",
+ "ami_name": "ubuntu-16-04-test-{{ timestamp }}",
+ "ami_description": "Ubuntu 16.04 LTS - expand root partition",
+ "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
+ },
+ "launch_block_device_mappings": [
+ {
+ "delete_on_termination": true,
+ "device_name": "/dev/sda1",
+ "volume_type": "gp2",
+ "volume_size": 48
+ }
+ ],
+ "spot_price": "0.0075",
+ "spot_instance_types": [
+ "t2.small",
+ "t2.medium",
+ "t2.large"
+ ],
+ "encrypt_boot": true,
+ "ssh_username": "ubuntu",
+ "temporary_iam_instance_profile_policy_document": {
+ "Version": "2012-10-17",
+ "Statement": [
+ {
+ "Effect": "Allow",
+ "Action": [
+ "*"
+ ],
+ "Resource": ["*"]
+ }
+ ]
+ },
+ "ssh_interface": "session_manager"
+ }
+ ],
+ "provisioners": [
+ {
+ "type": "shell",
+ "except": [
+ "amazon-ebs"
+ ],
+ "max_retries": 5,
+ "inline": [
+ "echo {{ user `secret_account` }}",
+ "echo {{ build `ID` }}",
+ "echo {{ build `SSHPublicKey` }} | head -c 14",
+ "echo {{ template_dir }} is not {{ pwd }}",
+ "echo {{ packer_version }}",
+ "echo {{ uuid }}"
+ ]
+ },
+ {
+ "type": "shell",
+ "inline": [
+ "echo {{ user `password` }}",
+ "echo {{ aws_secretsmanager `sample/app/password` }}",
+ "echo {{ user `password_key` }}",
+ "echo {{ aws_secretsmanager `sample/app/passwords` `api_key` }}"
+ ]
+ },
+ {
+ "type": "shell",
+ "inline": [
+ "echo {{ aws_secretsmanager `some_secret` }}",
+ "echo {{ aws_secretsmanager `some_secret` `with_key` }}"
+ ]
+ },
+ {
+ "type": "shell",
+ "inline": [
+ "echo mybuild-{{isotime | clean_resource_name}}"
+ ]
+ },
+ {
+ "type": "shell",
+ "inline": [
+ "echo {{ `SOMETHING` | lower }}"
+ ]
+ },
+ {
+ "type": "shell",
+ "inline": [
+ "echo {{ `something` | upper }}"
+ ]
+ },
+ {
+ "type": "shell",
+ "inline": [
+ "echo {{ split `some-string` `-` 0 }}"
+ ]
+ },
+ {
+ "type": "shell",
+ "inline": [
+ "echo {{ replace_all `-` `/` build_name }}"
+ ]
+ },
+ {
+ "type": "shell",
+ "inline": [
+ "echo {{ replace `some-string` `-` 1 `/` }}"
+ ]
+ },
+ {
+ "type": "shell-local",
+ "only": [
+ "amazon-ebs"
+ ],
+ "timeout": "5s",
+ "inline": [
+ "sleep 100000"
+ ]
+ }
+ ],
+ "post-processors": [
+ [
+ {
+ "type": "amazon-import",
+ "region": "eu-west-3",
+ "s3_bucket_name": "hashicorp.adrien",
+ "license_type": "BYOL",
+ "format": "vmdk",
+ "tags": {
+ "Description": "packer amazon-import {{timestamp}}"
+ }
+ }
+ ],
+ [
+ {
+ "only": [
+ "amazon-ebs"
+ ],
+ "files": [
+ "path/something.ova"
+ ],
+ "keep_input_artifact": true,
+ "name": "very_special_artifice_post-processor",
+ "type": "artifice"
+ },
+ {
+ "except": [
+ "amazon-ebs"
+ ],
+ "type": "amazon-import",
+ "s3_bucket_name": "hashicorp.adrien",
+ "license_type": "BYOL",
+ "tags": {
+ "Description": "packer amazon-import {{timestamp}}"
+ }
+ }
+ ]
+ ]
+}
\ No newline at end of file
diff --git a/v1.9.4/command/test-fixtures/hcp/build-description.pkr.hcl b/v1.9.4/command/test-fixtures/hcp/build-description.pkr.hcl
new file mode 100644
index 0000000..87c3c97
--- /dev/null
+++ b/v1.9.4/command/test-fixtures/hcp/build-description.pkr.hcl
@@ -0,0 +1,17 @@
+source file "test" {
+ content = " "
+ target = "output"
+}
+
+build {
+ name = "bucket-slug"
+
+ description = "Some build description"
+
+ hcp_packer_registry {}
+
+ sources = [
+ "sources.file.test",
+ ]
+}
+
diff --git a/v1.9.4/command/test-fixtures/hcp/deprecated_labels.pkr.hcl b/v1.9.4/command/test-fixtures/hcp/deprecated_labels.pkr.hcl
new file mode 100644
index 0000000..1d84e60
--- /dev/null
+++ b/v1.9.4/command/test-fixtures/hcp/deprecated_labels.pkr.hcl
@@ -0,0 +1,19 @@
+source file "test" {
+ content = " "
+ target = "output"
+}
+
+build {
+ description = "Some build description"
+
+ hcp_packer_registry {
+ bucket_name = "bucket-slug"
+ labels = {
+ "foo" = "bar"
+ }
+ }
+
+ sources = [
+ "sources.file.test",
+ ]
+}
diff --git a/v1.9.4/command/test-fixtures/hcp/dup_build_blocks.pkr.hcl b/v1.9.4/command/test-fixtures/hcp/dup_build_blocks.pkr.hcl
new file mode 100644
index 0000000..73b3a8e
--- /dev/null
+++ b/v1.9.4/command/test-fixtures/hcp/dup_build_blocks.pkr.hcl
@@ -0,0 +1,29 @@
+source file "test" {
+ content = " "
+ target = "output"
+}
+
+build {
+ description = "Some build description"
+
+ hcp_packer_registry {
+ bucket_name = "bucket-slug"
+ description = "Some override description"
+ }
+
+ sources = [
+ "sources.file.test",
+ ]
+}
+
+build {
+ description = "Some other build"
+
+ hcp_packer_registry {
+ bucket_name = "bucket-bis"
+ }
+
+ sources = [
+ "sources.file.test",
+ ]
+}
diff --git a/v1.9.4/command/test-fixtures/hcp/duplicate.pkr.hcl b/v1.9.4/command/test-fixtures/hcp/duplicate.pkr.hcl
new file mode 100644
index 0000000..f228956
--- /dev/null
+++ b/v1.9.4/command/test-fixtures/hcp/duplicate.pkr.hcl
@@ -0,0 +1,22 @@
+source file "test" {
+ content = " "
+ target = "output"
+}
+
+build {
+ description = "Some build description"
+
+ hcp_packer_registry {
+ bucket_name = "bucket-slug"
+ description = "Some override description"
+ }
+
+ hcp_packer_registry {
+ bucket_name = "bucket-slug"
+ description = "Some override description"
+ }
+
+ sources = [
+ "sources.file.test",
+ ]
+}
diff --git a/v1.9.4/command/test-fixtures/hcp/hcp_build.json b/v1.9.4/command/test-fixtures/hcp/hcp_build.json
new file mode 100644
index 0000000..ffa3ea0
--- /dev/null
+++ b/v1.9.4/command/test-fixtures/hcp/hcp_build.json
@@ -0,0 +1,10 @@
+{
+ "description": "Some legacy JSON build",
+ "builders": [
+ {
+ "type": "file",
+ "content": " ",
+ "target": "output"
+ }
+ ]
+}
diff --git a/v1.9.4/command/test-fixtures/hcp/hcp_normal.pkr.json b/v1.9.4/command/test-fixtures/hcp/hcp_normal.pkr.json
new file mode 100644
index 0000000..c615872
--- /dev/null
+++ b/v1.9.4/command/test-fixtures/hcp/hcp_normal.pkr.json
@@ -0,0 +1,16 @@
+{
+ "source": {
+ "file": {
+ "test": {
+ "content": " ",
+ "target": "output"
+ }
+ }
+ },
+ "build": {
+ "name": "test-file",
+ "description": "Some build description",
+ "sources": ["sources.file.test"]
+ }
+}
+
diff --git a/v1.9.4/command/test-fixtures/hcp/multiple_sources.pkr.hcl b/v1.9.4/command/test-fixtures/hcp/multiple_sources.pkr.hcl
new file mode 100644
index 0000000..3e3c02e
--- /dev/null
+++ b/v1.9.4/command/test-fixtures/hcp/multiple_sources.pkr.hcl
@@ -0,0 +1,30 @@
+source file "test" {
+ content = " "
+ target = "output"
+}
+
+source file "other" {
+ content = "b"
+ target = "output 2"
+}
+
+build {
+ name = "bucket-slug"
+
+ hcp_packer_registry {
+ description = <<EOT
+Some description
+ EOT
+ bucket_labels = {
+ "foo" = "bar"
+ }
+ build_labels = {
+ "python_version" = "3.0"
+ }
+ }
+
+ sources = [
+ "sources.file.test",
+ "sources.file.other"
+ ]
+}
diff --git a/v1.9.4/command/test-fixtures/hcp/override-build-description.pkr.hcl b/v1.9.4/command/test-fixtures/hcp/override-build-description.pkr.hcl
new file mode 100644
index 0000000..0159996
--- /dev/null
+++ b/v1.9.4/command/test-fixtures/hcp/override-build-description.pkr.hcl
@@ -0,0 +1,20 @@
+source file "test" {
+ content = " "
+ target = "output"
+}
+
+build {
+ description = "Some build description"
+
+ hcp_packer_registry {
+ bucket_name = "bucket-slug"
+ description = "Some override description"
+ }
+
+ sources = [
+ "sources.file.test",
+ ]
+}
+
+
+
diff --git a/v1.9.4/command/test-fixtures/hcp/slug.pkr.hcl b/v1.9.4/command/test-fixtures/hcp/slug.pkr.hcl
new file mode 100644
index 0000000..17e1f9c
--- /dev/null
+++ b/v1.9.4/command/test-fixtures/hcp/slug.pkr.hcl
@@ -0,0 +1,23 @@
+source file "test" {
+ content = " "
+ target = "output"
+}
+
+build {
+ name = "bucket-slug"
+
+ hcp_packer_registry {
+ bucket_name = "real-bucket-slug"
+
+ description = <<EOT
+Some description
+ EOT
+ bucket_labels = {
+ "foo" = "bar"
+ }
+ }
+
+ sources = [
+ "sources.file.test",
+ ]
+}
diff --git a/v1.9.4/command/test-fixtures/hcp/variable-for-bucket_name.pkr.hcl b/v1.9.4/command/test-fixtures/hcp/variable-for-bucket_name.pkr.hcl
new file mode 100644
index 0000000..261fb4c
--- /dev/null
+++ b/v1.9.4/command/test-fixtures/hcp/variable-for-bucket_name.pkr.hcl
@@ -0,0 +1,21 @@
+source file "test" {
+ content = " "
+ target = "output"
+}
+
+build {
+ description = "Some build description"
+
+ hcp_packer_registry {
+ bucket_name = "bucket-slug"
+ description = "Some override description"
+ }
+
+ sources = [
+ "sources.file.test",
+ ]
+}
+
+
+
+
diff --git a/v1.9.4/command/test-fixtures/inspect/unset_var.json b/v1.9.4/command/test-fixtures/inspect/unset_var.json
new file mode 100644
index 0000000..f2d2471
--- /dev/null
+++ b/v1.9.4/command/test-fixtures/inspect/unset_var.json
@@ -0,0 +1,5 @@
+{
+ "variables": {
+ "something": null
+ }
+}
diff --git a/v1.9.4/command/test-fixtures/parallel/1lock-5wg.json b/v1.9.4/command/test-fixtures/parallel/1lock-5wg.json
new file mode 100644
index 0000000..966528d
--- /dev/null
+++ b/v1.9.4/command/test-fixtures/parallel/1lock-5wg.json
@@ -0,0 +1,10 @@
+{
+ "builders": [
+ {"type": "lock", "name": "build0"},
+ {"type": "parallel-test", "name": "build1"},
+ {"type": "parallel-test", "name": "build2"},
+ {"type": "parallel-test", "name": "build3"},
+ {"type": "parallel-test", "name": "build4"},
+ {"type": "parallel-test", "name": "build5"}
+ ]
+}
\ No newline at end of file
diff --git a/v1.9.4/command/test-fixtures/parallel/1lock.json b/v1.9.4/command/test-fixtures/parallel/1lock.json
new file mode 100644
index 0000000..952f45d
--- /dev/null
+++ b/v1.9.4/command/test-fixtures/parallel/1lock.json
@@ -0,0 +1,5 @@
+{
+ "builders": [
+ {"type": "lock", "name": "build0"}
+ ]
+}
\ No newline at end of file
diff --git a/v1.9.4/command/test-fixtures/parallel/2lock-4wg.json b/v1.9.4/command/test-fixtures/parallel/2lock-4wg.json
new file mode 100644
index 0000000..59da8a3
--- /dev/null
+++ b/v1.9.4/command/test-fixtures/parallel/2lock-4wg.json
@@ -0,0 +1,10 @@
+{
+ "builders": [
+ {"type": "lock", "name": "build0"},
+ {"type": "parallel-test", "name": "build1"},
+ {"type": "parallel-test", "name": "build2"},
+ {"type": "lock", "name": "build3"},
+ {"type": "parallel-test", "name": "build4"},
+ {"type": "parallel-test", "name": "build5"}
+ ]
+}
\ No newline at end of file
diff --git a/v1.9.4/command/test-fixtures/parallel/2lock-timeout.json b/v1.9.4/command/test-fixtures/parallel/2lock-timeout.json
new file mode 100644
index 0000000..a3425fc
--- /dev/null
+++ b/v1.9.4/command/test-fixtures/parallel/2lock-timeout.json
@@ -0,0 +1,19 @@
+{
+ "builders": [
+ {"type": "lock", "name": "build0"},
+ {"type": "parallel-test", "name": "build1"},
+ {"type": "parallel-test", "name": "build2"},
+ {"type": "file", "name": "timeout-build", "target": "roses.txt"},
+ {"type": "parallel-test", "name": "build4"},
+ {"type": "parallel-test", "name": "build5"}
+ ],
+ "provisioners": [
+ {
+ "only": ["timeout-build"],
+ "type": "sleep",
+ "duration": "2m",
+
+ "timeout": "1ns"
+ }
+ ]
+}
\ No newline at end of file
diff --git a/v1.9.4/command/test-fixtures/parallel/2lock.json b/v1.9.4/command/test-fixtures/parallel/2lock.json
new file mode 100644
index 0000000..af81f26
--- /dev/null
+++ b/v1.9.4/command/test-fixtures/parallel/2lock.json
@@ -0,0 +1,6 @@
+{
+ "builders": [
+ {"type": "lock", "name": "build0"},
+ {"type": "lock", "name": "build1"}
+ ]
+}
\ No newline at end of file
diff --git a/v1.9.4/command/test-fixtures/provisioners/provisioner-only-except.json b/v1.9.4/command/test-fixtures/provisioners/provisioner-only-except.json
new file mode 100644
index 0000000..6eee423
--- /dev/null
+++ b/v1.9.4/command/test-fixtures/provisioners/provisioner-only-except.json
@@ -0,0 +1,37 @@
+{
+ "builders": [
+ {
+ "type": "null",
+ "communicator": "none"
+ },
+ {
+ "type": "null",
+ "name": "packer",
+ "communicator": "none"
+ }
+ ],
+ "provisioners": [
+ {
+ "type": "shell-local",
+ "inline": ["echo packer provisioner {{build_name}} and {{build_type}}"],
+ "only": ["packer"]
+ },
+ {
+ "type": "shell-local",
+ "inline": ["echo null provisioner {{build_name}} and {{build_type}}"],
+ "except": ["packer"]
+ }
+ ],
+ "post-processors": [
+ {
+ "type": "shell-local",
+ "inline": ["echo packer post-processor {{build_name}} and {{build_type}}"],
+ "only": ["packer"]
+ },
+ {
+ "type": "shell-local",
+ "inline": ["echo null post-processor {{build_name}} and {{build_type}}"],
+ "except": ["packer"]
+ }
+ ]
+}
diff --git a/v1.9.4/command/test-fixtures/provisioners/provisioner-only-except.pkr.hcl b/v1.9.4/command/test-fixtures/provisioners/provisioner-only-except.pkr.hcl
new file mode 100644
index 0000000..8118965
--- /dev/null
+++ b/v1.9.4/command/test-fixtures/provisioners/provisioner-only-except.pkr.hcl
@@ -0,0 +1,31 @@
+source "null" "packer" {
+ communicator = "none"
+}
+
+source "null" "other" {
+ communicator = "none"
+}
+
+build {
+ sources = ["sources.null.packer", "null.other"]
+
+ provisioner "shell-local" {
+ inline = ["echo packer provisioner {{build_name}} and {{build_type}}"]
+ only = ["null.packer"]
+ }
+
+ provisioner "shell-local" {
+ inline = ["echo other provisioner {{build_name}} and {{build_type}}"]
+ except = ["null.packer"]
+ }
+
+ post-processor "shell-local" {
+ inline = ["echo packer post-processor {{build_name}} and {{build_type}}"]
+ only = ["null.packer"]
+ }
+
+ post-processor "shell-local" {
+ inline = ["echo other post-processor {{build_name}} and {{build_type}}"]
+ except = ["null.packer"]
+ }
+}
diff --git a/v1.9.4/command/test-fixtures/provisioners/provisioner-override.json b/v1.9.4/command/test-fixtures/provisioners/provisioner-override.json
new file mode 100644
index 0000000..53d2c82
--- /dev/null
+++ b/v1.9.4/command/test-fixtures/provisioners/provisioner-override.json
@@ -0,0 +1,25 @@
+{
+ "builders": [
+ {
+ "type": "null",
+ "name": "example1",
+ "communicator": "none"
+ },
+ {
+ "type": "null",
+ "name": "example2",
+ "communicator": "none"
+ }
+ ],
+ "provisioners": [
+ {
+ "type": "shell-local",
+ "inline": ["echo not overridden"],
+ "override": {
+ "example1": {
+ "inline": ["echo yes overridden"]
+ }
+ }
+ }
+ ]
+}
\ No newline at end of file
diff --git a/v1.9.4/command/test-fixtures/timeout/template.json b/v1.9.4/command/test-fixtures/timeout/template.json
new file mode 100644
index 0000000..b577d21
--- /dev/null
+++ b/v1.9.4/command/test-fixtures/timeout/template.json
@@ -0,0 +1,37 @@
+{
+ "builders": [
+ {
+ "name": "roses",
+ "type": "file",
+ "content": "roses",
+ "target": "roses.txt"
+ }
+ ],
+ "provisioners": [
+ {
+ "type": "shell-local",
+ "inline": [
+ "touch fuchsias.txt"
+ ],
+ "timeout": "5s"
+ },
+ {
+ "type": "shell-local",
+ "inline": [
+ "touch lilas.txt"
+ ]
+ },
+ {
+ "type": "sleep",
+ "duration": "2m",
+
+ "timeout": "1ms"
+ },
+ {
+ "type": "shell-local",
+ "inline": [
+ "touch campanules.txt"
+ ]
+ }
+ ]
+}
\ No newline at end of file
diff --git a/v1.9.4/command/test-fixtures/validate-invalid/bad_provisioner.json b/v1.9.4/command/test-fixtures/validate-invalid/bad_provisioner.json
new file mode 100644
index 0000000..1f4b6cf
--- /dev/null
+++ b/v1.9.4/command/test-fixtures/validate-invalid/bad_provisioner.json
@@ -0,0 +1,15 @@
+{
+ "builders":[
+ {
+ "type":"file",
+ "target":"chocolate.txt",
+ "content":"chocolate"
+ }
+ ],
+ "provisioners": [
+ {
+ "type": "file",
+ "comment": "unknown field"
+ }
+ ]
+}
diff --git a/v1.9.4/command/test-fixtures/validate-invalid/broken.json b/v1.9.4/command/test-fixtures/validate-invalid/broken.json
new file mode 100644
index 0000000..af297ef
--- /dev/null
+++ b/v1.9.4/command/test-fixtures/validate-invalid/broken.json
@@ -0,0 +1,10 @@
+{
+ "builders":[
+ {
+ "type":"file",
+ "target":"chocolate.txt",
+ "content":"chocolate"
+ }
+ ],
+ "provisioners": "not an array"
+}
diff --git a/v1.9.4/command/test-fixtures/validate-invalid/missing_build_block.pkr.hcl b/v1.9.4/command/test-fixtures/validate-invalid/missing_build_block.pkr.hcl
new file mode 100644
index 0000000..10488a0
--- /dev/null
+++ b/v1.9.4/command/test-fixtures/validate-invalid/missing_build_block.pkr.hcl
@@ -0,0 +1,9 @@
+source "file" "chocolate" {
+ target = "chocolate.txt"
+ content = "chocolate"
+}
+
+build {
+ sources = ["source.file.cho"]
+}
+
diff --git a/v1.9.4/command/test-fixtures/validate/build.json b/v1.9.4/command/test-fixtures/validate/build.json
new file mode 100644
index 0000000..674eb1c
--- /dev/null
+++ b/v1.9.4/command/test-fixtures/validate/build.json
@@ -0,0 +1,9 @@
+{
+ "builders":[
+ {
+ "type":"file",
+ "target":"chocolate.txt",
+ "content":"chocolate"
+ }
+ ]
+}
diff --git a/v1.9.4/command/test-fixtures/validate/build.pkr.hcl b/v1.9.4/command/test-fixtures/validate/build.pkr.hcl
new file mode 100644
index 0000000..b70cd53
--- /dev/null
+++ b/v1.9.4/command/test-fixtures/validate/build.pkr.hcl
@@ -0,0 +1,12 @@
+packer {
+ required_version = ">= v1.0.0"
+}
+
+source "file" "chocolate" {
+ target = "chocolate.txt"
+ content = "chocolate"
+}
+
+build {
+ sources = ["source.file.chocolate"]
+}
diff --git a/v1.9.4/command/test-fixtures/validate/build_with_vars.pkr.hcl b/v1.9.4/command/test-fixtures/validate/build_with_vars.pkr.hcl
new file mode 100644
index 0000000..0b8b073
--- /dev/null
+++ b/v1.9.4/command/test-fixtures/validate/build_with_vars.pkr.hcl
@@ -0,0 +1,13 @@
+variable "target" {
+ type = string
+ default = "chocolate.txt"
+}
+
+source "file" "chocolate" {
+ target = var.target
+ content = "chocolate"
+}
+
+build {
+ sources = ["source.file.chocolate"]
+}
diff --git a/v1.9.4/command/test-fixtures/validate/circular_error.pkr.hcl b/v1.9.4/command/test-fixtures/validate/circular_error.pkr.hcl
new file mode 100644
index 0000000..4ee895c
--- /dev/null
+++ b/v1.9.4/command/test-fixtures/validate/circular_error.pkr.hcl
@@ -0,0 +1,5 @@
+
+locals {
+ timestamp = formatdate("YYYY-MM-DDX", timestamp())
+ other_local = "test-${local.timestamp}"
+}
diff --git a/v1.9.4/command/test-fixtures/validate/datasource.pkr.hcl b/v1.9.4/command/test-fixtures/validate/datasource.pkr.hcl
new file mode 100644
index 0000000..d41cccb
--- /dev/null
+++ b/v1.9.4/command/test-fixtures/validate/datasource.pkr.hcl
@@ -0,0 +1,16 @@
+packer {
+ required_version = ">= v1.0.0"
+}
+
+data "mock" "content" {
+ foo = "content"
+}
+
+source "file" "chocolate" {
+ target = "chocolate.txt"
+ content = data.mock.content.foo
+}
+
+build {
+ sources = ["source.file.chocolate"]
+}
diff --git a/v1.9.4/command/test-fixtures/validate/invalid_packer_block.pkr.hcl b/v1.9.4/command/test-fixtures/validate/invalid_packer_block.pkr.hcl
new file mode 100644
index 0000000..6388be9
--- /dev/null
+++ b/v1.9.4/command/test-fixtures/validate/invalid_packer_block.pkr.hcl
@@ -0,0 +1,3 @@
+packer {
+ version = ">= v1.0.0"
+}
diff --git a/v1.9.4/command/test-fixtures/validate/null_var.json b/v1.9.4/command/test-fixtures/validate/null_var.json
new file mode 100644
index 0000000..016e20b
--- /dev/null
+++ b/v1.9.4/command/test-fixtures/validate/null_var.json
@@ -0,0 +1,15 @@
+{
+ "variables": {
+ "null_var": null
+ },
+ "builders": [{
+ "type": "null",
+ "communicator": "none"
+ }],
+ "provisioners": [
+ {
+ "type": "shell-local",
+ "inline": "echo yop"
+ }
+ ]
+}
diff --git a/v1.9.4/command/test-fixtures/validate/template.json b/v1.9.4/command/test-fixtures/validate/template.json
new file mode 100644
index 0000000..75b3f62
--- /dev/null
+++ b/v1.9.4/command/test-fixtures/validate/template.json
@@ -0,0 +1,10 @@
+{
+ "builders":[
+ {
+ "type":"file",
+ "target":"chocolate.txt",
+ "content":"chocolate"
+ }
+ ],
+ "min_packer_version":"101.0.0"
+}
diff --git a/v1.9.4/command/test-fixtures/validate/validate_except.json b/v1.9.4/command/test-fixtures/validate/validate_except.json
new file mode 100644
index 0000000..74e1f3f
--- /dev/null
+++ b/v1.9.4/command/test-fixtures/validate/validate_except.json
@@ -0,0 +1,39 @@
+{
+ "builders": [
+ {
+ "name": "chocolate",
+ "type": "file",
+ "target": "chocolate.txt",
+ "content": "chocolate"
+ },
+ {
+ "type": "file",
+ "name": "vanilla"
+ }
+ ],
+ "post-processors": [
+ [
+ {
+ "name": "apple",
+ "type": "shell-local",
+ "inline": [
+ "echo apple 'apple'"
+ ]
+ }
+ ],
+ [
+ {
+ "name": "pear",
+ "type": "shell-local",
+ "inline": [
+ "echo apple 'pear'"
+ ]
+ },
+ {
+ "name": "banana",
+ "type": "shell-local"
+ }
+ ]
+ ],
+ "min_packer_version": "101.0.0"
+}
diff --git a/v1.9.4/command/test-fixtures/validate/validate_except.pkr.hcl b/v1.9.4/command/test-fixtures/validate/validate_except.pkr.hcl
new file mode 100644
index 0000000..5c38c9b
--- /dev/null
+++ b/v1.9.4/command/test-fixtures/validate/validate_except.pkr.hcl
@@ -0,0 +1,30 @@
+source "file" "chocolate" {
+ content = "chocolate"
+ target = "chocolate.txt"
+}
+source "file" "vanilla" {
+ content = "vanilla"
+}
+
+build {
+ sources = [
+ "source.file.chocolate",
+ "source.file.vanilla"
+ ]
+
+ post-processors {
+ post-processor "shell-local" {
+ name = "apple"
+ inline = [ "echo apple 'apple'" ]
+ }
+
+ post-processor "shell-local" {
+ name = "pear"
+ inline = [ "echo apple 'pear'" ]
+ }
+
+ post-processor "shell-local" {
+ name = "banana"
+ }
+ }
+}
diff --git a/v1.9.4/command/test-fixtures/validate/var-file-tests/basic.pkr.hcl b/v1.9.4/command/test-fixtures/validate/var-file-tests/basic.pkr.hcl
new file mode 100644
index 0000000..1fd3325
--- /dev/null
+++ b/v1.9.4/command/test-fixtures/validate/var-file-tests/basic.pkr.hcl
@@ -0,0 +1,17 @@
+packer {
+ required_version = ">= v1.0.0"
+}
+
+variable "test" {
+ type = string
+ default = null
+}
+
+source "file" "chocolate" {
+ target = "chocolate.txt"
+ content = "chocolate"
+}
+
+build {
+ sources = ["source.file.chocolate"]
+}
diff --git a/v1.9.4/command/test-fixtures/validate/var-file-tests/basic.pkrvars.hcl b/v1.9.4/command/test-fixtures/validate/var-file-tests/basic.pkrvars.hcl
new file mode 100644
index 0000000..efa60c7
--- /dev/null
+++ b/v1.9.4/command/test-fixtures/validate/var-file-tests/basic.pkrvars.hcl
@@ -0,0 +1 @@
+test = "myvalue"
diff --git a/v1.9.4/command/test-fixtures/validate/var-file-tests/undeclared.json b/v1.9.4/command/test-fixtures/validate/var-file-tests/undeclared.json
new file mode 100644
index 0000000..5004198
--- /dev/null
+++ b/v1.9.4/command/test-fixtures/validate/var-file-tests/undeclared.json
@@ -0,0 +1,3 @@
+{
+ "unused": ["one", "cookie", "two", "cookie"]
+}
diff --git a/v1.9.4/command/test-fixtures/validate/var-file-tests/undeclared.pkrvars.hcl b/v1.9.4/command/test-fixtures/validate/var-file-tests/undeclared.pkrvars.hcl
new file mode 100644
index 0000000..dace598
--- /dev/null
+++ b/v1.9.4/command/test-fixtures/validate/var-file-tests/undeclared.pkrvars.hcl
@@ -0,0 +1 @@
+unused = "unused variables should warn"
diff --git a/v1.9.4/command/test-fixtures/validate/var_foo_with_no_default.pkr.hcl b/v1.9.4/command/test-fixtures/validate/var_foo_with_no_default.pkr.hcl
new file mode 100644
index 0000000..57d1e68
--- /dev/null
+++ b/v1.9.4/command/test-fixtures/validate/var_foo_with_no_default.pkr.hcl
@@ -0,0 +1,3 @@
+
+variable "foo" {
+}
\ No newline at end of file
diff --git a/v1.9.4/command/test-fixtures/var-arg/apple.hcl b/v1.9.4/command/test-fixtures/var-arg/apple.hcl
new file mode 100644
index 0000000..0a54a34
--- /dev/null
+++ b/v1.9.4/command/test-fixtures/var-arg/apple.hcl
@@ -0,0 +1,2 @@
+
+fruit = "apple"
diff --git a/v1.9.4/command/test-fixtures/var-arg/apple.json b/v1.9.4/command/test-fixtures/var-arg/apple.json
new file mode 100644
index 0000000..125836e
--- /dev/null
+++ b/v1.9.4/command/test-fixtures/var-arg/apple.json
@@ -0,0 +1,3 @@
+{
+ "fruit": "apple"
+}
diff --git a/v1.9.4/command/test-fixtures/var-arg/chocolate.auto.pkrvars.hcl b/v1.9.4/command/test-fixtures/var-arg/chocolate.auto.pkrvars.hcl
new file mode 100644
index 0000000..51149d6
--- /dev/null
+++ b/v1.9.4/command/test-fixtures/var-arg/chocolate.auto.pkrvars.hcl
@@ -0,0 +1,2 @@
+
+fruit = "chocolate" // is that even a fruit !?
diff --git a/v1.9.4/command/test-fixtures/var-arg/fruit_builder.json b/v1.9.4/command/test-fixtures/var-arg/fruit_builder.json
new file mode 100644
index 0000000..9d6831c
--- /dev/null
+++ b/v1.9.4/command/test-fixtures/var-arg/fruit_builder.json
@@ -0,0 +1,20 @@
+{
+ "variables": {
+ "fruit": null
+ },
+ "builders": [
+ {
+ "communicator": "none",
+ "type": "null"
+ }
+ ],
+ "post-processors": [
+ [
+ {
+ "name": "apple",
+ "type": "shell-local",
+ "inline": [ "echo {{ user `fruit` }} > {{ user `fruit` }}.txt" ]
+ }
+ ]
+ ]
+}
diff --git a/v1.9.4/command/test-fixtures/var-arg/fruit_builder.pkr.hcl b/v1.9.4/command/test-fixtures/var-arg/fruit_builder.pkr.hcl
new file mode 100644
index 0000000..63ece8a
--- /dev/null
+++ b/v1.9.4/command/test-fixtures/var-arg/fruit_builder.pkr.hcl
@@ -0,0 +1,22 @@
+
+variable "fruit" {
+ type = string
+}
+
+locals {
+ fruit = var.fruit
+}
+
+source "null" "builder" {
+ communicator = "none"
+}
+
+build {
+ sources = [
+ "source.null.builder",
+ ]
+
+ provisioner "shell-local" {
+ inline = ["echo ${local.fruit} > ${local.fruit}.txt"]
+ }
+}
diff --git a/v1.9.4/command/test-fixtures/var-arg/map.pkr.hcl b/v1.9.4/command/test-fixtures/var-arg/map.pkr.hcl
new file mode 100644
index 0000000..5e72ec1
--- /dev/null
+++ b/v1.9.4/command/test-fixtures/var-arg/map.pkr.hcl
@@ -0,0 +1,7 @@
+
+variable "images" {
+ type = map(string)
+ default = {
+ key = "value"
+ }
+}
\ No newline at end of file
diff --git a/v1.9.4/command/test-fixtures/version_req/base_failure/version.pkr.hcl b/v1.9.4/command/test-fixtures/version_req/base_failure/version.pkr.hcl
new file mode 100644
index 0000000..6a85120
--- /dev/null
+++ b/v1.9.4/command/test-fixtures/version_req/base_failure/version.pkr.hcl
@@ -0,0 +1,9 @@
+packer {
+ required_version = ">= 700000.0.0"
+}
+
+block_from_the_future {
+ the_answer_to_life_the_universe_and_everything = 42
+}
+
+build {}
diff --git a/v1.9.4/command/test-fixtures/version_req/base_success/version.pkr.hcl b/v1.9.4/command/test-fixtures/version_req/base_success/version.pkr.hcl
new file mode 100644
index 0000000..2886986
--- /dev/null
+++ b/v1.9.4/command/test-fixtures/version_req/base_success/version.pkr.hcl
@@ -0,0 +1,11 @@
+packer {
+ required_version = ">= 1.0.0"
+}
+
+source "null" "test" {
+ communicator = "none"
+}
+
+build {
+ sources = ["null.test"]
+}
diff --git a/v1.9.4/command/test-fixtures/version_req/wrong_field_name/version.pkr.hcl b/v1.9.4/command/test-fixtures/version_req/wrong_field_name/version.pkr.hcl
new file mode 100644
index 0000000..411b7f7
--- /dev/null
+++ b/v1.9.4/command/test-fixtures/version_req/wrong_field_name/version.pkr.hcl
@@ -0,0 +1,3 @@
+packer {
+ version = ">= 700000.0.0"
+}
diff --git a/v1.9.4/command/test_utils.go b/v1.9.4/command/test_utils.go
new file mode 100644
index 0000000..41e02db
--- /dev/null
+++ b/v1.9.4/command/test_utils.go
@@ -0,0 +1,75 @@
+// Copyright (c) HashiCorp, Inc.
+// SPDX-License-Identifier: MPL-2.0
+
+package command
+
+import (
+ "bytes"
+ "testing"
+
+ packersdk "github.com/hashicorp/packer-plugin-sdk/packer"
+ "github.com/hashicorp/packer/builder/file"
+ "github.com/hashicorp/packer/builder/null"
+ hcppackerimagedatasource "github.com/hashicorp/packer/datasource/hcp-packer-image"
+ hcppackeriterationdatasource "github.com/hashicorp/packer/datasource/hcp-packer-iteration"
+ nulldatasource "github.com/hashicorp/packer/datasource/null"
+ "github.com/hashicorp/packer/packer"
+ "github.com/hashicorp/packer/post-processor/manifest"
+ shell_local_pp "github.com/hashicorp/packer/post-processor/shell-local"
+ filep "github.com/hashicorp/packer/provisioner/file"
+ "github.com/hashicorp/packer/provisioner/shell"
+ shell_local "github.com/hashicorp/packer/provisioner/shell-local"
+)
+
+// Utils to use in other tests
+
+// TestMetaFile creates a Meta object that includes a file builder
+func TestMetaFile(t *testing.T) Meta {
+ var out, err bytes.Buffer
+ return Meta{
+ CoreConfig: testCoreConfigBuilder(t),
+ Ui: &packersdk.BasicUi{
+ Writer: &out,
+ ErrorWriter: &err,
+ },
+ }
+}
+
+// GetStdoutAndErrFromTestMeta extracts stdout/stderr from a Meta created by TestMetaFile
+func GetStdoutAndErrFromTestMeta(t *testing.T, m Meta) (string, string) {
+ ui := m.Ui.(*packersdk.BasicUi)
+ out := ui.Writer.(*bytes.Buffer)
+ err := ui.ErrorWriter.(*bytes.Buffer)
+ return out.String(), err.String()
+}
+
+// testCoreConfigBuilder creates a packer CoreConfig that has a file builder
+// available. This allows us to test a builder that writes files to disk.
+func testCoreConfigBuilder(t *testing.T) *packer.CoreConfig {
+ components := packer.ComponentFinder{
+ PluginConfig: &packer.PluginConfig{
+ Builders: packer.MapOfBuilder{
+ "file": func() (packersdk.Builder, error) { return &file.Builder{}, nil },
+ "null": func() (packersdk.Builder, error) { return &null.Builder{}, nil },
+ },
+ Provisioners: packer.MapOfProvisioner{
+ "shell-local": func() (packersdk.Provisioner, error) { return &shell_local.Provisioner{}, nil },
+ "shell": func() (packersdk.Provisioner, error) { return &shell.Provisioner{}, nil },
+ "file": func() (packersdk.Provisioner, error) { return &filep.Provisioner{}, nil },
+ },
+ PostProcessors: packer.MapOfPostProcessor{
+ "shell-local": func() (packersdk.PostProcessor, error) { return &shell_local_pp.PostProcessor{}, nil },
+ "manifest": func() (packersdk.PostProcessor, error) { return &manifest.PostProcessor{}, nil },
+ },
+ DataSources: packer.MapOfDatasource{
+ "mock": func() (packersdk.Datasource, error) { return &packersdk.MockDatasource{}, nil },
+ "null": func() (packersdk.Datasource, error) { return &nulldatasource.Datasource{}, nil },
+ "hcp-packer-image": func() (packersdk.Datasource, error) { return &hcppackerimagedatasource.Datasource{}, nil },
+ "hcp-packer-iteration": func() (packersdk.Datasource, error) { return &hcppackeriterationdatasource.Datasource{}, nil },
+ },
+ },
+ }
+ return &packer.CoreConfig{
+ Components: components,
+ }
+}
diff --git a/v1.9.4/command/utils.go b/v1.9.4/command/utils.go
new file mode 100644
index 0000000..9fee02d
--- /dev/null
+++ b/v1.9.4/command/utils.go
@@ -0,0 +1,25 @@
+// Copyright (c) HashiCorp, Inc.
+// SPDX-License-Identifier: MPL-2.0
+
+package command
+
+import (
+ "os"
+ "strings"
+)
+
+func isDir(name string) (bool, error) {
+ s, err := os.Stat(name)
+ if err != nil {
+ return false, err
+ }
+ return s.IsDir(), nil
+}
+
+func isHCLLoaded(name string) (bool, error) {
+ if strings.HasSuffix(name, ".pkr.hcl") ||
+ strings.HasSuffix(name, ".pkr.json") {
+ return true, nil
+ }
+ return isDir(name)
+}
diff --git a/v1.9.4/command/utils_test.go b/v1.9.4/command/utils_test.go
new file mode 100644
index 0000000..426ea65
--- /dev/null
+++ b/v1.9.4/command/utils_test.go
@@ -0,0 +1,52 @@
+// Copyright (c) HashiCorp, Inc.
+// SPDX-License-Identifier: MPL-2.0
+
+package command
+
+import (
+ "io/ioutil"
+ "log"
+ "os"
+ "path/filepath"
+)
+
+func mustString(s string, e error) string {
+ if e != nil {
+ panic(e)
+ }
+ return s
+}
+
+func createFiles(dir string, content map[string]string) {
+ for relPath, content := range content {
+ contentPath := filepath.Join(dir, relPath)
+ if err := os.MkdirAll(filepath.Dir(contentPath), 0777); err != nil {
+ panic(err)
+ }
+ if err := ioutil.WriteFile(contentPath, []byte(content), 0666); err != nil {
+ panic(err)
+ }
+ log.Printf("created tmp file: %s", contentPath)
+ }
+}
+
+type configDirSingleton struct {
+ dirs map[string]string
+}
+
+// when you call dir twice with the same key, the result should be the same
+func (c *configDirSingleton) dir(key string) string {
+ if v, exists := c.dirs[key]; exists {
+ return v
+ }
+ c.dirs[key] = mustString(ioutil.TempDir("", "pkr-test-cfg-dir-"+key))
+ return c.dirs[key]
+}
+
+// fileExists returns true if the filename is found
+func fileExists(filename string) bool {
+ if _, err := os.Stat(filename); err == nil {
+ return true
+ }
+ return false
+}
diff --git a/v1.9.4/command/validate.go b/v1.9.4/command/validate.go
new file mode 100644
index 0000000..2b7e210
--- /dev/null
+++ b/v1.9.4/command/validate.go
@@ -0,0 +1,145 @@
+// Copyright (c) HashiCorp, Inc.
+// SPDX-License-Identifier: MPL-2.0
+
+package command
+
+import (
+ "context"
+ "strings"
+
+ "github.com/hashicorp/packer/packer"
+
+ "github.com/posener/complete"
+)
+
+type ValidateCommand struct {
+ Meta
+}
+
+func (c *ValidateCommand) Run(args []string) int {
+ ctx, cleanup := handleTermInterrupt(c.Ui)
+ defer cleanup()
+
+ cfg, ret := c.ParseArgs(args)
+ if ret != 0 {
+ return ret
+ }
+
+ return c.RunContext(ctx, cfg)
+}
+
+func (c *ValidateCommand) ParseArgs(args []string) (*ValidateArgs, int) {
+ var cfg ValidateArgs
+
+ flags := c.Meta.FlagSet("validate", FlagSetBuildFilter|FlagSetVars)
+ flags.Usage = func() { c.Ui.Say(c.Help()) }
+ cfg.AddFlagSets(flags)
+ if err := flags.Parse(args); err != nil {
+ return &cfg, 1
+ }
+
+ args = flags.Args()
+ if len(args) != 1 {
+ flags.Usage()
+ return &cfg, 1
+ }
+ cfg.Path = args[0]
+ return &cfg, 0
+}
+
+func (c *ValidateCommand) RunContext(ctx context.Context, cla *ValidateArgs) int {
+ // By default we want to inform users of undeclared variables when validating but not during build time.
+ cla.MetaArgs.WarnOnUndeclaredVar = true
+ if cla.NoWarnUndeclaredVar {
+ cla.MetaArgs.WarnOnUndeclaredVar = false
+ }
+
+ packerStarter, ret := c.GetConfig(&cla.MetaArgs)
+ if ret != 0 {
+ return 1
+ }
+
+ // If we're only checking syntax, then we're done already
+ if cla.SyntaxOnly {
+ c.Ui.Say("Syntax-only check passed. Everything looks okay.")
+ return 0
+ }
+
+ diags := packerStarter.DetectPluginBinaries()
+ ret = writeDiags(c.Ui, nil, diags)
+ if ret != 0 {
+ return ret
+ }
+
+ diags = packerStarter.Initialize(packer.InitializeOptions{
+ SkipDatasourcesExecution: !cla.EvaluateDatasources,
+ })
+ bundledDiags := c.DetectBundledPlugins(packerStarter)
+ diags = append(bundledDiags, diags...)
+ ret = writeDiags(c.Ui, nil, diags)
+ if ret != 0 {
+ return ret
+ }
+
+ _, diags = packerStarter.GetBuilds(packer.GetBuildsOptions{
+ Only: cla.Only,
+ Except: cla.Except,
+ })
+
+ fixerDiags := packerStarter.FixConfig(packer.FixConfigOptions{
+ Mode: packer.Diff,
+ })
+ diags = append(diags, fixerDiags...)
+
+ ret = writeDiags(c.Ui, nil, diags)
+ if ret == 0 {
+ c.Ui.Say("The configuration is valid.")
+ }
+
+ return ret
+}
+
+func (*ValidateCommand) Help() string {
+ helpText := `
+Usage: packer validate [options] TEMPLATE
+
+ Checks the template is valid by parsing the template and also
+ checking the configuration with the various builders, provisioners, etc.
+
+ If it is not valid, the errors will be shown and the command will exit
+ with a non-zero exit status. If it is valid, it will exit with a zero
+ exit status.
+
+Options:
+
+ -syntax-only Only check syntax. Do not verify config of the template.
+ -except=foo,bar,baz Validate all builds other than these.
+ -only=foo,bar,baz Validate only these builds.
+ -machine-readable Produce machine-readable output.
+ -var 'key=value' Variable for templates, can be used multiple times.
+ -var-file=path JSON or HCL2 file containing user variables, can be used multiple times.
+ -no-warn-undeclared-var Disable warnings for user variable files containing undeclared variables.
+ -evaluate-datasources Evaluate data sources during validation (HCL2 only, may incur costs); Defaults to false.
+`
+
+ return strings.TrimSpace(helpText)
+}
+
+func (*ValidateCommand) Synopsis() string {
+ return "check that a template is valid"
+}
+
+func (*ValidateCommand) AutocompleteArgs() complete.Predictor {
+ return complete.PredictNothing
+}
+
+func (*ValidateCommand) AutocompleteFlags() complete.Flags {
+ return complete.Flags{
+ "-syntax-only": complete.PredictNothing,
+ "-except": complete.PredictNothing,
+ "-only": complete.PredictNothing,
+ "-var": complete.PredictNothing,
+ "-machine-readable": complete.PredictNothing,
+ "-var-file": complete.PredictNothing,
+ }
+}
diff --git a/v1.9.4/command/validate_test.go b/v1.9.4/command/validate_test.go
new file mode 100644
index 0000000..5b51f37
--- /dev/null
+++ b/v1.9.4/command/validate_test.go
@@ -0,0 +1,386 @@
+// Copyright (c) HashiCorp, Inc.
+// SPDX-License-Identifier: MPL-2.0
+
+package command
+
+import (
+ "fmt"
+ "path/filepath"
+ "testing"
+
+ "github.com/google/go-cmp/cmp"
+ packersdk "github.com/hashicorp/packer-plugin-sdk/packer"
+ "github.com/hashicorp/packer/packer"
+)
+
+func TestValidateCommand(t *testing.T) {
+ tt := []struct {
+ path string
+ exitCode int
+ extraArgs []string
+ }{
+ {path: filepath.Join(testFixture("validate"), "build.json")},
+ {path: filepath.Join(testFixture("validate"), "build.pkr.hcl")},
+ {path: filepath.Join(testFixture("validate"), "build_with_vars.pkr.hcl")},
+ {path: filepath.Join(testFixture("validate-invalid"), "bad_provisioner.json"), exitCode: 1},
+ {path: filepath.Join(testFixture("validate-invalid"), "missing_build_block.pkr.hcl"), exitCode: 1},
+ {path: filepath.Join(testFixture("validate"), "null_var.json"), exitCode: 1},
+ {path: filepath.Join(testFixture("validate"), "var_foo_with_no_default.pkr.hcl"), exitCode: 1},
+
+ {path: testFixture("hcl", "validation", "wrong_pause_before.pkr.hcl"), exitCode: 1},
+
+ // wrong version fails
+ {path: filepath.Join(testFixture("version_req", "base_failure")), exitCode: 1},
+ {path: filepath.Join(testFixture("version_req", "base_success")), exitCode: 0},
+
+ // wrong version field
+ {path: filepath.Join(testFixture("version_req", "wrong_field_name")), exitCode: 1},
+
+ // wrong packer block
+ {path: filepath.Join(testFixture("validate", "invalid_packer_block.pkr.hcl")), exitCode: 1},
+
+ // Should return multiple errors,
+ {path: filepath.Join(testFixture("validate", "circular_error.pkr.hcl")), exitCode: 1},
+
+ // datasource could be unknown at that moment
+ {path: filepath.Join(testFixture("hcl", "data-source-validation.pkr.hcl")), exitCode: 0},
+
+ // datasource unknown at validation-time without datasource evaluation -> fail on provisioner
+ {path: filepath.Join(testFixture("hcl", "local-ds-validate.pkr.hcl")), exitCode: 1},
+ // datasource unknown at validation-time with datasource evaluation -> success
+ {path: filepath.Join(testFixture("hcl", "local-ds-validate.pkr.hcl")), exitCode: 0, extraArgs: []string{"--evaluate-datasources"}},
+ }
+
+ for _, tc := range tt {
+ t.Run(tc.path, func(t *testing.T) {
+ c := &ValidateCommand{
+ Meta: TestMetaFile(t),
+ }
+ tc := tc
+ args := tc.extraArgs
+ args = append(args, tc.path)
+ if code := c.Run(args); code != tc.exitCode {
+ fatalCommand(t, c.Meta)
+ }
+ })
+ }
+}
+
+func TestValidateCommand_SkipDatasourceExecution(t *testing.T) {
+ datasourceMock := &packersdk.MockDatasource{}
+ meta := TestMetaFile(t)
+ meta.CoreConfig.Components.PluginConfig.DataSources = packer.MapOfDatasource{
+ "mock": func() (packersdk.Datasource, error) {
+ return datasourceMock, nil
+ },
+ }
+ c := &ValidateCommand{
+ Meta: meta,
+ }
+ args := []string{filepath.Join(testFixture("validate"), "datasource.pkr.hcl")}
+ if code := c.Run(args); code != 0 {
+ fatalCommand(t, c.Meta)
+ }
+ if datasourceMock.ExecuteCalled {
+ t.Fatalf("Datasource should not be executed on validation")
+ }
+ if !datasourceMock.OutputSpecCalled {
+ t.Fatalf("Datasource OutPutSpec should be called on validation")
+ }
+}
+
+func TestValidateCommand_SyntaxOnly(t *testing.T) {
+ tt := []struct {
+ path string
+ exitCode int
+ }{
+ {path: filepath.Join(testFixture("validate"), "build.json")},
+ {path: filepath.Join(testFixture("validate"), "build.pkr.hcl")},
+ {path: filepath.Join(testFixture("validate"), "build_with_vars.pkr.hcl")},
+ {path: filepath.Join(testFixture("validate-invalid"), "bad_provisioner.json")},
+ {path: filepath.Join(testFixture("validate-invalid"), "missing_build_block.pkr.hcl")},
+ {path: filepath.Join(testFixture("validate-invalid"), "broken.json"), exitCode: 1},
+ {path: filepath.Join(testFixture("validate"), "null_var.json")},
+ {path: filepath.Join(testFixture("validate"), "var_foo_with_no_default.pkr.hcl")},
+ }
+
+ for _, tc := range tt {
+ t.Run(tc.path, func(t *testing.T) {
+ c := &ValidateCommand{
+ Meta: TestMetaFile(t),
+ }
+ c.CoreConfig.Version = "102.0.0"
+ tc := tc
+ args := []string{"-syntax-only", tc.path}
+ if code := c.Run(args); code != tc.exitCode {
+ fatalCommand(t, c.Meta)
+ }
+ })
+ }
+}
+
+func TestValidateCommandOKVersion(t *testing.T) {
+ c := &ValidateCommand{
+ Meta: TestMetaFile(t),
+ }
+ args := []string{
+ filepath.Join(testFixture("validate"), "template.json"),
+ }
+
+ // This should pass with a valid configuration version
+ c.CoreConfig.Version = "102.0.0"
+ if code := c.Run(args); code != 0 {
+ fatalCommand(t, c.Meta)
+ }
+}
+
+func TestValidateCommandBadVersion(t *testing.T) {
+ c := &ValidateCommand{
+ Meta: TestMetaFile(t),
+ }
+ args := []string{
+ filepath.Join(testFixture("validate"), "template.json"),
+ }
+
+ // This should fail with an invalid configuration version
+ c.CoreConfig.Version = "100.0.0"
+ if code := c.Run(args); code != 1 {
+ t.Errorf("Expected exit code 1")
+ }
+
+ stdout, stderr := GetStdoutAndErrFromTestMeta(t, c.Meta)
+ expected := `Error:
+
+This template requires Packer version 101.0.0 or higher; using 100.0.0
+
+
+`
+
+ if diff := cmp.Diff(expected, stderr); diff != "" {
+ t.Errorf("Unexpected output: %s", diff)
+ }
+ t.Log(stdout)
+}
+
+func TestValidateCommandExcept(t *testing.T) {
+ tt := []struct {
+ name string
+ args []string
+ exitCode int
+ }{
+ {
+ name: "JSON: validate except build and post-processor",
+ args: []string{
+ "-except=vanilla,pear",
+ filepath.Join(testFixture("validate"), "validate_except.json"),
+ },
+ },
+ {
+ name: "JSON: fail validate except build and post-processor",
+ args: []string{
+ "-except=chocolate,apple",
+ filepath.Join(testFixture("validate"), "validate_except.json"),
+ },
+ exitCode: 1,
+ },
+ {
+ name: "HCL2: validate except build and post-processor",
+ args: []string{
+ "-except=file.vanilla,pear",
+ filepath.Join(testFixture("validate"), "validate_except.pkr.hcl"),
+ },
+ },
+ {
+ name: "HCL2: fail validation except build and post-processor",
+ args: []string{
+ "-except=file.chocolate,apple",
+ filepath.Join(testFixture("validate"), "validate_except.pkr.hcl"),
+ },
+ exitCode: 1,
+ },
+ }
+
+ c := &ValidateCommand{
+ Meta: TestMetaFile(t),
+ }
+ c.CoreConfig.Version = "102.0.0"
+
+ for _, tc := range tt {
+ t.Run(tc.name, func(t *testing.T) {
+ defer cleanup()
+
+ tc := tc
+ if code := c.Run(tc.args); code != tc.exitCode {
+ fatalCommand(t, c.Meta)
+ }
+ })
+ }
+}
+
+func TestValidateCommand_VarFiles(t *testing.T) {
+ tt := []struct {
+ name string
+ path string
+ varfile string
+ exitCode int
+ }{
+ {name: "with basic HCL var-file definition",
+ path: filepath.Join(testFixture(filepath.Join("validate", "var-file-tests")), "basic.pkr.hcl"),
+ varfile: filepath.Join(testFixture(filepath.Join("validate", "var-file-tests")), "basic.pkrvars.hcl"),
+ exitCode: 0,
+ },
+ {name: "with unused variable in var-file definition",
+ path: filepath.Join(testFixture(filepath.Join("validate", "var-file-tests")), "basic.pkr.hcl"),
+ varfile: filepath.Join(testFixture(filepath.Join("validate", "var-file-tests")), "undeclared.pkrvars.hcl"),
+ exitCode: 0,
+ },
+ {name: "with unused variable in JSON var-file definition",
+ path: filepath.Join(testFixture(filepath.Join("validate", "var-file-tests")), "basic.pkr.hcl"),
+ varfile: filepath.Join(testFixture(filepath.Join("validate", "var-file-tests")), "undeclared.json"),
+ exitCode: 0,
+ },
+ }
+ for _, tc := range tt {
+ t.Run(tc.path, func(t *testing.T) {
+ c := &ValidateCommand{
+ Meta: TestMetaFile(t),
+ }
+ tc := tc
+ args := []string{"-var-file", tc.varfile, tc.path}
+ if code := c.Run(args); code != tc.exitCode {
+ fatalCommand(t, c.Meta)
+ }
+ })
+ }
+}
+
+func TestValidateCommand_VarFilesWarnOnUndeclared(t *testing.T) {
+ tt := []struct {
+ name string
+ path string
+ varfile string
+ exitCode int
+ }{
+ {name: "default warning with unused variable in HCL var-file definition",
+ path: filepath.Join(testFixture(filepath.Join("validate", "var-file-tests")), "basic.pkr.hcl"),
+ varfile: filepath.Join(testFixture(filepath.Join("validate", "var-file-tests")), "undeclared.pkrvars.hcl"),
+ exitCode: 0,
+ },
+ {name: "default warning with unused variable in JSON var-file definition",
+ path: filepath.Join(testFixture(filepath.Join("validate", "var-file-tests")), "basic.pkr.hcl"),
+ varfile: filepath.Join(testFixture(filepath.Join("validate", "var-file-tests")), "undeclared.json"),
+ exitCode: 0,
+ },
+ }
+ for _, tc := range tt {
+ t.Run(tc.path, func(t *testing.T) {
+ c := &ValidateCommand{
+ Meta: TestMetaFile(t),
+ }
+ tc := tc
+ args := []string{"-var-file", tc.varfile, tc.path}
+ if code := c.Run(args); code != tc.exitCode {
+ fatalCommand(t, c.Meta)
+ }
+
+ stdout, stderr := GetStdoutAndErrFromTestMeta(t, c.Meta)
+ expected := `Warning: Undefined variable
+
+The variable "unused" was set but was not declared as an input variable.
+To declare variable "unused" place this block in one of your .pkr.hcl files,
+such as variables.pkr.hcl
+
+variable "unused" {
+ type = string
+ default = null
+}
+
+
+The configuration is valid.
+`
+ if diff := cmp.Diff(expected, stdout); diff != "" {
+ t.Errorf("Unexpected output: %s", diff)
+ }
+ t.Log(stderr)
+ })
+ }
+}
+
+func TestValidateCommand_VarFilesDisableWarnOnUndeclared(t *testing.T) {
+ tt := []struct {
+ name string
+ path string
+ varfile string
+ exitCode int
+ }{
+ {name: "no-warn-undeclared-var with unused variable in HCL var-file definition",
+ path: filepath.Join(testFixture(filepath.Join("validate", "var-file-tests")), "basic.pkr.hcl"),
+ varfile: filepath.Join(testFixture(filepath.Join("validate", "var-file-tests")), "undeclared.pkrvars.hcl"),
+ exitCode: 0,
+ },
+ {name: "no-warn-undeclared-var with unused variable in JSON var-file definition",
+ path: filepath.Join(testFixture(filepath.Join("validate", "var-file-tests")), "basic.pkr.hcl"),
+ varfile: filepath.Join(testFixture(filepath.Join("validate", "var-file-tests")), "undeclared.json"),
+ exitCode: 0,
+ },
+ }
+ for _, tc := range tt {
+ t.Run(tc.path, func(t *testing.T) {
+ c := &ValidateCommand{
+ Meta: TestMetaFile(t),
+ }
+ tc := tc
+ args := []string{"-no-warn-undeclared-var", "-var-file", tc.varfile, tc.path}
+ if code := c.Run(args); code != tc.exitCode {
+ fatalCommand(t, c.Meta)
+ }
+
+ stdout, stderr := GetStdoutAndErrFromTestMeta(t, c.Meta)
+ expected := `The configuration is valid.
+`
+ if diff := cmp.Diff(expected, stdout); diff != "" {
+ t.Errorf("Unexpected output: %s", diff)
+ }
+ t.Log(stderr)
+ })
+ }
+}
+
+func TestValidateCommand_ShowLineNumForMissing(t *testing.T) {
+ tt := []struct {
+ path string
+ exitCode int
+ extraArgs []string
+ }{
+ {path: filepath.Join(testFixture("validate-invalid"), "missing_build_block.pkr.hcl"), exitCode: 1},
+ }
+
+ for _, tc := range tt {
+ t.Run(tc.path, func(t *testing.T) {
+ c := &ValidateCommand{
+ Meta: TestMetaFile(t),
+ }
+ tc := tc
+ args := tc.extraArgs
+ args = append(args, tc.path)
+ if code := c.Run(args); code != tc.exitCode {
+ fatalCommand(t, c.Meta)
+ }
+
+ stdout, stderr := GetStdoutAndErrFromTestMeta(t, c.Meta)
+ expected := fmt.Sprintf(`Error: Unknown source file.cho
+
+ on %s line 6:
+ (source code not available)
+
+Known: [file.chocolate]
+
+
+`, tc.path)
+ if diff := cmp.Diff(expected, stderr); diff != "" {
+ t.Errorf("Unexpected output: %s", diff)
+ }
+ t.Log(stdout)
+ })
+ }
+}
diff --git a/v1.9.4/command/vendored_plugins.go b/v1.9.4/command/vendored_plugins.go
new file mode 100644
index 0000000..d6e5f83
--- /dev/null
+++ b/v1.9.4/command/vendored_plugins.go
@@ -0,0 +1,303 @@
+// Copyright (c) HashiCorp, Inc.
+// SPDX-License-Identifier: MPL-2.0
+
+package command
+
+import (
+ "fmt"
+ "log"
+ "strings"
+
+ packersdk "github.com/hashicorp/packer-plugin-sdk/packer"
+
+ // Previously core-bundled components, split into their own plugins but
+ // still vendored with Packer for now. Importing as library instead of
+ // forcing use of packer init.
+
+ amazonchrootbuilder "github.com/hashicorp/packer-plugin-amazon/builder/chroot"
+ amazonebsbuilder "github.com/hashicorp/packer-plugin-amazon/builder/ebs"
+ amazonebssurrogatebuilder "github.com/hashicorp/packer-plugin-amazon/builder/ebssurrogate"
+ amazonebsvolumebuilder "github.com/hashicorp/packer-plugin-amazon/builder/ebsvolume"
+ amazoninstancebuilder "github.com/hashicorp/packer-plugin-amazon/builder/instance"
+ amazonamidatasource "github.com/hashicorp/packer-plugin-amazon/datasource/ami"
+ amazonsecretsmanagerdatasource "github.com/hashicorp/packer-plugin-amazon/datasource/secretsmanager"
+ anazibimportpostprocessor "github.com/hashicorp/packer-plugin-amazon/post-processor/import"
+ ansibleprovisioner "github.com/hashicorp/packer-plugin-ansible/provisioner/ansible"
+ ansiblelocalprovisioner "github.com/hashicorp/packer-plugin-ansible/provisioner/ansible-local"
+ azurearmbuilder "github.com/hashicorp/packer-plugin-azure/builder/azure/arm"
+ azurechrootbuilder "github.com/hashicorp/packer-plugin-azure/builder/azure/chroot"
+ azuredtlbuilder "github.com/hashicorp/packer-plugin-azure/builder/azure/dtl"
+ azuredtlartifactprovisioner "github.com/hashicorp/packer-plugin-azure/provisioner/azure-dtlartifact"
+ dockerbuilder "github.com/hashicorp/packer-plugin-docker/builder/docker"
+ dockerimportpostprocessor "github.com/hashicorp/packer-plugin-docker/post-processor/docker-import"
+ dockerpushpostprocessor "github.com/hashicorp/packer-plugin-docker/post-processor/docker-push"
+ dockersavepostprocessor "github.com/hashicorp/packer-plugin-docker/post-processor/docker-save"
+ dockertagpostprocessor "github.com/hashicorp/packer-plugin-docker/post-processor/docker-tag"
+ googlecomputebuilder "github.com/hashicorp/packer-plugin-googlecompute/builder/googlecompute"
+ googlecomputeexportpostprocessor "github.com/hashicorp/packer-plugin-googlecompute/post-processor/googlecompute-export"
+ googlecomputeimportpostprocessor "github.com/hashicorp/packer-plugin-googlecompute/post-processor/googlecompute-import"
+ qemubuilder "github.com/hashicorp/packer-plugin-qemu/builder/qemu"
+ vagrantbuilder "github.com/hashicorp/packer-plugin-vagrant/builder/vagrant"
+ vagrantpostprocessor "github.com/hashicorp/packer-plugin-vagrant/post-processor/vagrant"
+ vagrantcloudpostprocessor "github.com/hashicorp/packer-plugin-vagrant/post-processor/vagrant-cloud"
+ virtualboxisobuilder "github.com/hashicorp/packer-plugin-virtualbox/builder/virtualbox/iso"
+ virtualboxovfbuilder "github.com/hashicorp/packer-plugin-virtualbox/builder/virtualbox/ovf"
+ virtualboxvmbuilder "github.com/hashicorp/packer-plugin-virtualbox/builder/virtualbox/vm"
+ vmwareisobuilder "github.com/hashicorp/packer-plugin-vmware/builder/vmware/iso"
+ vmwarevmxbuilder "github.com/hashicorp/packer-plugin-vmware/builder/vmware/vmx"
+ vsphereclonebuilder "github.com/hashicorp/packer-plugin-vsphere/builder/vsphere/clone"
+ vsphereisobuilder "github.com/hashicorp/packer-plugin-vsphere/builder/vsphere/iso"
+ vspherepostprocessor "github.com/hashicorp/packer-plugin-vsphere/post-processor/vsphere"
+ vspheretemplatepostprocessor "github.com/hashicorp/packer-plugin-vsphere/post-processor/vsphere-template"
+)
+
+// VendoredDatasources are datasource components that were once bundled with the
+// Packer core, but are now being imported from their counterpart plugin repos
+var VendoredDatasources = map[string]packersdk.Datasource{
+ "amazon-ami": new(amazonamidatasource.Datasource),
+ "amazon-secretsmanager": new(amazonsecretsmanagerdatasource.Datasource),
+}
+
+// VendoredBuilders are builder components that were once bundled with the
+// Packer core, but are now being imported from their counterpart plugin repos
+var VendoredBuilders = map[string]packersdk.Builder{
+ "amazon-ebs": new(amazonebsbuilder.Builder),
+ "amazon-chroot": new(amazonchrootbuilder.Builder),
+ "amazon-ebssurrogate": new(amazonebssurrogatebuilder.Builder),
+ "amazon-ebsvolume": new(amazonebsvolumebuilder.Builder),
+ "amazon-instance": new(amazoninstancebuilder.Builder),
+ "azure-arm": new(azurearmbuilder.Builder),
+ "azure-chroot": new(azurechrootbuilder.Builder),
+ "azure-dtl": new(azuredtlbuilder.Builder),
+ "docker": new(dockerbuilder.Builder),
+ "googlecompute": new(googlecomputebuilder.Builder),
+ "qemu": new(qemubuilder.Builder),
+ "vagrant": new(vagrantbuilder.Builder),
+ "vsphere-clone": new(vsphereclonebuilder.Builder),
+ "vsphere-iso": new(vsphereisobuilder.Builder),
+ "virtualbox-iso": new(virtualboxisobuilder.Builder),
+ "virtualbox-ovf": new(virtualboxovfbuilder.Builder),
+ "virtualbox-vm": new(virtualboxvmbuilder.Builder),
+ "vmware-iso": new(vmwareisobuilder.Builder),
+ "vmware-vmx": new(vmwarevmxbuilder.Builder),
+}
+
+// VendoredProvisioners are provisioner components that were once bundled with the
+// Packer core, but are now being imported from their counterpart plugin repos
+var VendoredProvisioners = map[string]packersdk.Provisioner{
+ "azure-dtlartifact": new(azuredtlartifactprovisioner.Provisioner),
+ "ansible": new(ansibleprovisioner.Provisioner),
+ "ansible-local": new(ansiblelocalprovisioner.Provisioner),
+}
+
+// VendoredPostProcessors are post-processor components that were once bundled with the
+// Packer core, but are now being imported from their counterpart plugin repos
+var VendoredPostProcessors = map[string]packersdk.PostProcessor{
+ "amazon-import": new(anazibimportpostprocessor.PostProcessor),
+ "docker-import": new(dockerimportpostprocessor.PostProcessor),
+ "docker-push": new(dockerpushpostprocessor.PostProcessor),
+ "docker-save": new(dockersavepostprocessor.PostProcessor),
+ "docker-tag": new(dockertagpostprocessor.PostProcessor),
+ "googlecompute-export": new(googlecomputeexportpostprocessor.PostProcessor),
+ "googlecompute-import": new(googlecomputeimportpostprocessor.PostProcessor),
+ "vagrant": new(vagrantpostprocessor.PostProcessor),
+ "vagrant-cloud": new(vagrantcloudpostprocessor.PostProcessor),
+ "vsphere-template": new(vspheretemplatepostprocessor.PostProcessor),
+ "vsphere": new(vspherepostprocessor.PostProcessor),
+}
+
+// bundledStatus is used to know if one of the bundled components is loaded from
+// an external plugin, or from the bundled plugins.
+//
+// We keep track of this to produce a warning if a user relies on one
+// such plugin, as they will be removed in a later version of Packer.
+var bundledStatus = map[string]bool{
+ "packer-builder-amazon-ebs": false,
+ "packer-builder-amazon-chroot": false,
+ "packer-builder-amazon-ebssurrogate": false,
+ "packer-builder-amazon-ebsvolume": false,
+ "packer-builder-amazon-instance": false,
+ "packer-post-processor-amazon-import": false,
+ "packer-datasource-amazon-ami": false,
+ "packer-datasource-amazon-secretsmanager": false,
+
+ "packer-provisioner-ansible": false,
+ "packer-provisioner-ansible-local": false,
+
+ "packer-provisioner-azure-dtlartifact": false,
+ "packer-builder-azure-arm": false,
+ "packer-builder-azure-chroot": false,
+ "packer-builder-azure-dtl": false,
+
+ "packer-builder-docker": false,
+ "packer-post-processor-docker-import": false,
+ "packer-post-processor-docker-push": false,
+ "packer-post-processor-docker-save": false,
+ "packer-post-processor-docker-tag": false,
+
+ "packer-builder-googlecompute": false,
+ "packer-post-processor-googlecompute-export": false,
+ "packer-post-processor-googlecompute-import": false,
+
+ "packer-builder-qemu": false,
+
+ "packer-builder-vagrant": false,
+ "packer-post-processor-vagrant": false,
+ "packer-post-processor-vagrant-cloud": false,
+
+ "packer-builder-virtualbox-iso": false,
+ "packer-builder-virtualbox-ovf": false,
+ "packer-builder-virtualbox-vm": false,
+
+ "packer-builder-vmware-iso": false,
+ "packer-builder-vmware-vmx": false,
+
+ "packer-builder-vsphere-clone": false,
+ "packer-builder-vsphere-iso": false,
+ "packer-post-processor-vsphere-template": false,
+ "packer-post-processor-vsphere": false,
+}
+
+// TrackBundledPlugin marks a component as loaded from Packer's bundled plugins
+// instead of from an externally loaded plugin.
+//
+// NOTE: `pluginName' must be in the format `packer-<type>-<component_name>'
+func TrackBundledPlugin(pluginName string) {
+ _, exists := bundledStatus[pluginName]
+ if !exists {
+ return
+ }
+
+ bundledStatus[pluginName] = true
+}
+
+var componentPluginMap = map[string]string{
+ "packer-builder-amazon-ebs": "github.com/hashicorp/amazon",
+ "packer-builder-amazon-chroot": "github.com/hashicorp/amazon",
+ "packer-builder-amazon-ebssurrogate": "github.com/hashicorp/amazon",
+ "packer-builder-amazon-ebsvolume": "github.com/hashicorp/amazon",
+ "packer-builder-amazon-instance": "github.com/hashicorp/amazon",
+ "packer-post-processor-amazon-import": "github.com/hashicorp/amazon",
+ "packer-datasource-amazon-ami": "github.com/hashicorp/amazon",
+ "packer-datasource-amazon-secretsmanager": "github.com/hashicorp/amazon",
+
+ "packer-provisioner-ansible": "github.com/hashicorp/ansible",
+ "packer-provisioner-ansible-local": "github.com/hashicorp/ansible",
+
+ "packer-provisioner-azure-dtlartifact": "github.com/hashicorp/azure",
+ "packer-builder-azure-arm": "github.com/hashicorp/azure",
+ "packer-builder-azure-chroot": "github.com/hashicorp/azure",
+ "packer-builder-azure-dtl": "github.com/hashicorp/azure",
+
+ "packer-builder-docker": "github.com/hashicorp/docker",
+ "packer-post-processor-docker-import": "github.com/hashicorp/docker",
+ "packer-post-processor-docker-push": "github.com/hashicorp/docker",
+ "packer-post-processor-docker-save": "github.com/hashicorp/docker",
+ "packer-post-processor-docker-tag": "github.com/hashicorp/docker",
+
+ "packer-builder-googlecompute": "github.com/hashicorp/googlecompute",
+ "packer-post-processor-googlecompute-export": "github.com/hashicorp/googlecompute",
+ "packer-post-processor-googlecompute-import": "github.com/hashicorp/googlecompute",
+
+ "packer-builder-qemu": "github.com/hashicorp/qemu",
+
+ "packer-builder-vagrant": "github.com/hashicorp/vagrant",
+ "packer-post-processor-vagrant": "github.com/hashicorp/vagrant",
+ "packer-post-processor-vagrant-cloud": "github.com/hashicorp/vagrant",
+
+ "packer-builder-virtualbox-iso": "github.com/hashicorp/virtualbox",
+ "packer-builder-virtualbox-ovf": "github.com/hashicorp/virtualbox",
+ "packer-builder-virtualbox-vm": "github.com/hashicorp/virtualbox",
+
+ "packer-builder-vmware-iso": "github.com/hashicorp/vmware",
+ "packer-builder-vmware-vmx": "github.com/hashicorp/vmware",
+
+ "packer-builder-vsphere-clone": "github.com/hashicorp/vsphere",
+ "packer-builder-vsphere-iso": "github.com/hashicorp/vsphere",
+ "packer-post-processor-vsphere-template": "github.com/hashicorp/vsphere",
+ "packer-post-processor-vsphere": "github.com/hashicorp/vsphere",
+}
+
+// compileBundledPluginList returns a list of plugins to import in a config
+//
+// This only works on bundled plugins and serves as a way to inform users that
+// they should not rely on a bundled plugin anymore, but give them recommendations
+// on how to manage those plugins instead.
+func compileBundledPluginList(componentMap map[string]struct{}) []string {
+ plugins := map[string]struct{}{}
+ for component := range componentMap {
+ plugin, ok := componentPluginMap[component]
+ if !ok {
+ log.Printf("Unknown bundled plugin component: %q", component)
+ continue
+ }
+
+ plugins[plugin] = struct{}{}
+ }
+
+ pluginList := make([]string, 0, len(plugins))
+ for plugin := range plugins {
+ pluginList = append(pluginList, plugin)
+ }
+
+ return pluginList
+}
+
+func generateRequiredPluginsBlock(plugins []string) string {
+ if len(plugins) == 0 {
+ return ""
+ }
+
+ buf := &strings.Builder{}
+ buf.WriteString(`
+packer {
+ required_plugins {`)
+
+ for _, plugin := range plugins {
+ pluginName := strings.Replace(plugin, "github.com/hashicorp/", "", 1)
+ fmt.Fprintf(buf, `
+ %s = {
+ source = %q
+ version = "~> 1"
+ }`, pluginName, plugin)
+ }
+
+ buf.WriteString(`
+ }
+}
+`)
+
+ return buf.String()
+}
+
+// Upon init lets load up any plugins that were vendored manually into the default
+// set of plugins.
+func init() {
+ for k, v := range VendoredDatasources {
+ if _, ok := Datasources[k]; ok {
+ continue
+ }
+ Datasources[k] = v
+ }
+
+ for k, v := range VendoredBuilders {
+ if _, ok := Builders[k]; ok {
+ continue
+ }
+ Builders[k] = v
+ }
+
+ for k, v := range VendoredProvisioners {
+ if _, ok := Provisioners[k]; ok {
+ continue
+ }
+ Provisioners[k] = v
+ }
+
+ for k, v := range VendoredPostProcessors {
+ if _, ok := PostProcessors[k]; ok {
+ continue
+ }
+ PostProcessors[k] = v
+ }
+}
diff --git a/v1.9.4/command/version.go b/v1.9.4/command/version.go
new file mode 100644
index 0000000..3a6db86
--- /dev/null
+++ b/v1.9.4/command/version.go
@@ -0,0 +1,66 @@
+// Copyright (c) HashiCorp, Inc.
+// SPDX-License-Identifier: MPL-2.0
+
+package command
+
+import (
+ "fmt"
+
+ "github.com/hashicorp/packer/version"
+)
+
+// VersionCommand is a Command implementation prints the version.
+type VersionCommand struct {
+ Meta
+
+ CheckFunc VersionCheckFunc
+}
+
+// VersionCheckFunc is the callback called by the Version command to
+// check if there is a new version of Packer.
+type VersionCheckFunc func() (VersionCheckInfo, error)
+
+// VersionCheckInfo is the return value for the VersionCheckFunc callback
+// and tells the Version command information about the latest version
+// of Packer.
+type VersionCheckInfo struct {
+ Outdated bool
+ Latest string
+ Alerts []string
+}
+
+func (c *VersionCommand) Help() string {
+ return "Prints the Packer version, and checks for new release."
+}
+
+func (c *VersionCommand) Run(args []string) int {
+ c.Ui.Machine("version", version.Version)
+ c.Ui.Machine("version-prelease", version.VersionPrerelease)
+ c.Ui.Machine("version-commit", version.GitCommit)
+
+ c.Ui.Say(fmt.Sprintf("Packer v%s", version.FormattedVersion()))
+
+ // If we have a version check function, then let's check for
+ // the latest version as well.
+ if c.CheckFunc != nil {
+
+ // Check the latest version
+ info, err := c.CheckFunc()
+ if err != nil {
+ c.Ui.Error(fmt.Sprintf(
+ "\nError checking latest version: %s", err))
+ }
+ if info.Outdated {
+ c.Ui.Say(fmt.Sprintf(
+ "\nYour version of Packer is out of date! The latest version\n"+
+ "is %s. You can update by downloading from www.packer.io/downloads",
+ info.Latest))
+ }
+ }
+
+ return 0
+}
+
+func (c *VersionCommand) Synopsis() string {
+ return "Prints the Packer version"
+}
diff --git a/v1.9.4/command/version_test.go b/v1.9.4/command/version_test.go
new file mode 100644
index 0000000..cd2b67e
--- /dev/null
+++ b/v1.9.4/command/version_test.go
@@ -0,0 +1,14 @@
+// Copyright (c) HashiCorp, Inc.
+// SPDX-License-Identifier: MPL-2.0
+
+package command
+
+import (
+ "testing"
+
+ "github.com/mitchellh/cli"
+)
+
+func TestVersionCommand_implements(t *testing.T) {
+ var _ cli.Command = &VersionCommand{}
+}
diff --git a/v1.9.4/commands.go b/v1.9.4/commands.go
new file mode 100644
index 0000000..01e3bf5
--- /dev/null
+++ b/v1.9.4/commands.go
@@ -0,0 +1,111 @@
+// Copyright (c) HashiCorp, Inc.
+// SPDX-License-Identifier: MPL-2.0
+
+package main
+
+import (
+ "github.com/hashicorp/packer/command"
+ "github.com/mitchellh/cli"
+)
+
+// Commands is the mapping of all the available Packer commands.
+var Commands map[string]cli.CommandFactory
+
+// CommandMeta is the Meta to use for the commands. This must be written
+// before the CLI is started.
+var CommandMeta *command.Meta
+
+const ErrorPrefix = "e:"
+const OutputPrefix = "o:"
+
+func init() {
+ Commands = map[string]cli.CommandFactory{
+ "build": func() (cli.Command, error) {
+ return &command.BuildCommand{Meta: *CommandMeta}, nil
+ },
+ "console": func() (cli.Command, error) {
+ return &command.ConsoleCommand{
+ Meta: *CommandMeta,
+ }, nil
+ },
+
+ "fix": func() (cli.Command, error) {
+ return &command.FixCommand{
+ Meta: *CommandMeta,
+ }, nil
+ },
+
+ "fmt": func() (cli.Command, error) {
+ return &command.FormatCommand{
+ Meta: *CommandMeta,
+ }, nil
+ },
+
+ "hcl2_upgrade": func() (cli.Command, error) {
+ return &command.HCL2UpgradeCommand{
+ Meta: *CommandMeta,
+ }, nil
+ },
+
+ "init": func() (cli.Command, error) {
+ return &command.InitCommand{
+ Meta: *CommandMeta,
+ }, nil
+ },
+
+ "inspect": func() (cli.Command, error) {
+ return &command.InspectCommand{
+ Meta: *CommandMeta,
+ }, nil
+ },
+
+ "plugin": func() (cli.Command, error) {
+ return &command.PluginCommand{
+ Meta: *CommandMeta,
+ }, nil
+ },
+
+ "plugins": func() (cli.Command, error) {
+ return &command.PluginsCommand{
+ Meta: *CommandMeta,
+ }, nil
+ },
+
+ "plugins installed": func() (cli.Command, error) {
+ return &command.PluginsInstalledCommand{
+ Meta: *CommandMeta,
+ }, nil
+ },
+
+ "plugins install": func() (cli.Command, error) {
+ return &command.PluginsInstallCommand{
+ Meta: *CommandMeta,
+ }, nil
+ },
+
+ "plugins remove": func() (cli.Command, error) {
+ return &command.PluginsRemoveCommand{
+ Meta: *CommandMeta,
+ }, nil
+ },
+
+ "plugins required": func() (cli.Command, error) {
+ return &command.PluginsRequiredCommand{
+ Meta: *CommandMeta,
+ }, nil
+ },
+
+ "validate": func() (cli.Command, error) {
+ return &command.ValidateCommand{
+ Meta: *CommandMeta,
+ }, nil
+ },
+
+ "version": func() (cli.Command, error) {
+ return &command.VersionCommand{
+ Meta: *CommandMeta,
+ CheckFunc: commandVersionCheck,
+ }, nil
+ },
+ }
+}
diff --git a/v1.9.4/config.go b/v1.9.4/config.go
new file mode 100644
index 0000000..af679dd
--- /dev/null
+++ b/v1.9.4/config.go
@@ -0,0 +1,202 @@
+// Copyright (c) HashiCorp, Inc.
+// SPDX-License-Identifier: MPL-2.0
+
+package main
+
+import (
+ "encoding/json"
+ "fmt"
+ "io"
+ "log"
+ "os"
+ "path/filepath"
+ "runtime"
+ "sort"
+ "strings"
+
+ packersdk "github.com/hashicorp/packer-plugin-sdk/packer"
+ "github.com/hashicorp/packer/command"
+ "github.com/hashicorp/packer/packer"
+)
+
+// PACKERSPACE is used to represent the spaces that separate args for a command
+// without being confused with spaces in the path to the command itself.
+const PACKERSPACE = "-PACKERSPACE-"
+
+type config struct {
+ DisableCheckpoint bool `json:"disable_checkpoint"`
+ DisableCheckpointSignature bool `json:"disable_checkpoint_signature"`
+ RawBuilders map[string]string `json:"builders"`
+ RawProvisioners map[string]string `json:"provisioners"`
+ RawPostProcessors map[string]string `json:"post-processors"`
+
+ Plugins *packer.PluginConfig
+}
+
+// decodeConfig decodes configuration in JSON format from the given io.Reader into
+// the config object pointed to.
+func decodeConfig(r io.Reader, c *config) error {
+ decoder := json.NewDecoder(r)
+ return decoder.Decode(c)
+}
+
+// LoadExternalComponentsFromConfig loads plugins defined in RawBuilders, RawProvisioners, and RawPostProcessors.
+func (c *config) LoadExternalComponentsFromConfig() {
+ // helper to build up list of plugin paths
+ extractPaths := func(m map[string]string) []string {
+ paths := make([]string, 0, len(m))
+ for _, v := range m {
+ paths = append(paths, v)
+ }
+
+ return paths
+ }
+
+ var pluginPaths []string
+ pluginPaths = append(pluginPaths, extractPaths(c.RawProvisioners)...)
+ pluginPaths = append(pluginPaths, extractPaths(c.RawBuilders)...)
+ pluginPaths = append(pluginPaths, extractPaths(c.RawPostProcessors)...)
+
+ var externallyUsed = make([]string, 0, len(pluginPaths))
+ for _, pluginPath := range pluginPaths {
+ name, err := c.loadSingleComponent(pluginPath)
+ if err != nil {
+ log.Print(err)
+ continue
+ }
+
+ log.Printf("loaded plugin: %s = %s", name, pluginPath)
+ externallyUsed = append(externallyUsed, name)
+ }
+
+ if len(externallyUsed) > 0 {
+ sort.Strings(externallyUsed)
+ log.Printf("using external plugins %v", externallyUsed)
+ }
+}
+
+func (c *config) loadSingleComponent(path string) (string, error) {
+ pluginName := filepath.Base(path)
+
+ // On Windows, ignore any plugins that don't end in .exe.
+ // We could do a full PATHEXT parse, but this is probably good enough.
+ if runtime.GOOS == "windows" && strings.ToLower(filepath.Ext(pluginName)) != ".exe" {
+ return "", fmt.Errorf("error loading plugin %q, no exe extension", path)
+ }
+
+ if _, err := os.Stat(path); err != nil {
+ return "", fmt.Errorf("error loading plugin %q: %s", path, err)
+ }
+
+ // If the filename has a ".", trim up to there
+ if idx := strings.Index(pluginName, "."); idx >= 0 {
+ pluginName = pluginName[:idx]
+ }
+
+ switch {
+ case strings.HasPrefix(pluginName, "packer-builder-"):
+ pluginName = pluginName[len("packer-builder-"):]
+ c.Plugins.Builders.Set(pluginName, func() (packersdk.Builder, error) {
+ return c.Plugins.Client(path).Builder()
+ })
+ case strings.HasPrefix(pluginName, "packer-post-processor-"):
+ pluginName = pluginName[len("packer-post-processor-"):]
+ c.Plugins.PostProcessors.Set(pluginName, func() (packersdk.PostProcessor, error) {
+ return c.Plugins.Client(path).PostProcessor()
+ })
+ case strings.HasPrefix(pluginName, "packer-provisioner-"):
+ pluginName = pluginName[len("packer-provisioner-"):]
+ c.Plugins.Provisioners.Set(pluginName, func() (packersdk.Provisioner, error) {
+ return c.Plugins.Client(path).Provisioner()
+ })
+ }
+
+ return pluginName, nil
+}
+
+// This is a proper packer.BuilderFunc that can be used to load packersdk.Builder
+// implementations from the defined plugins.
+func (c *config) StartBuilder(name string) (packersdk.Builder, error) {
+ log.Printf("Loading builder: %s\n", name)
+ return c.Plugins.Builders.Start(name)
+}
+
+// This is a proper implementation of packer.HookFunc that can be used
+// to load packersdk.Hook implementations from the defined plugins.
+func (c *config) StarHook(name string) (packersdk.Hook, error) {
+ log.Printf("Loading hook: %s\n", name)
+ return c.Plugins.Client(name).Hook()
+}
+
+// This is a proper packersdk.PostProcessorFunc that can be used to load
+// packersdk.PostProcessor implementations from defined plugins.
+func (c *config) StartPostProcessor(name string) (packersdk.PostProcessor, error) {
+ log.Printf("Loading post-processor: %s", name)
+ return c.Plugins.PostProcessors.Start(name)
+}
+
+// This is a proper packer.ProvisionerFunc that can be used to load
+// packer.Provisioner implementations from defined plugins.
+func (c *config) StartProvisioner(name string) (packersdk.Provisioner, error) {
+ log.Printf("Loading provisioner: %s\n", name)
+ return c.Plugins.Provisioners.Start(name)
+}
+
+func (c *config) discoverInternalComponents() error {
+ // Get the packer binary path
+ packerPath, err := os.Executable()
+ if err != nil {
+ log.Printf("[ERR] Error loading exe directory: %s", err)
+ return err
+ }
+
+ for builder := range command.Builders {
+ builder := builder
+ if !c.Plugins.Builders.Has(builder) {
+ command.TrackBundledPlugin(fmt.Sprintf("packer-builder-%s", builder))
+ bin := fmt.Sprintf("%s%splugin%spacker-builder-%s",
+ packerPath, PACKERSPACE, PACKERSPACE, builder)
+ c.Plugins.Builders.Set(builder, func() (packersdk.Builder, error) {
+ return c.Plugins.Client(bin).Builder()
+ })
+ }
+ }
+
+ for provisioner := range command.Provisioners {
+ provisioner := provisioner
+ if !c.Plugins.Provisioners.Has(provisioner) {
+ command.TrackBundledPlugin(fmt.Sprintf("packer-provisioner-%s", provisioner))
+ bin := fmt.Sprintf("%s%splugin%spacker-provisioner-%s",
+ packerPath, PACKERSPACE, PACKERSPACE, provisioner)
+ c.Plugins.Provisioners.Set(provisioner, func() (packersdk.Provisioner, error) {
+ return c.Plugins.Client(bin).Provisioner()
+ })
+ }
+ }
+
+ for postProcessor := range command.PostProcessors {
+ postProcessor := postProcessor
+ if !c.Plugins.PostProcessors.Has(postProcessor) {
+ command.TrackBundledPlugin(fmt.Sprintf("packer-post-processor-%s", postProcessor))
+ bin := fmt.Sprintf("%s%splugin%spacker-post-processor-%s",
+ packerPath, PACKERSPACE, PACKERSPACE, postProcessor)
+ c.Plugins.PostProcessors.Set(postProcessor, func() (packersdk.PostProcessor, error) {
+ return c.Plugins.Client(bin).PostProcessor()
+ })
+ }
+ }
+
+ for dataSource := range command.Datasources {
+ dataSource := dataSource
+ if !c.Plugins.DataSources.Has(dataSource) {
+ command.TrackBundledPlugin(fmt.Sprintf("packer-datasource-%s", dataSource))
+ bin := fmt.Sprintf("%s%splugin%spacker-datasource-%s",
+ packerPath, PACKERSPACE, PACKERSPACE, dataSource)
+ c.Plugins.DataSources.Set(dataSource, func() (packersdk.Datasource, error) {
+ return c.Plugins.Client(bin).Datasource()
+ })
+ }
+ }
+
+ return nil
+}
diff --git a/v1.9.4/config_test.go b/v1.9.4/config_test.go
new file mode 100644
index 0000000..772fea4
--- /dev/null
+++ b/v1.9.4/config_test.go
@@ -0,0 +1,227 @@
+// Copyright (c) HashiCorp, Inc.
+// SPDX-License-Identifier: MPL-2.0
+
+package main
+
+import (
+ "encoding/json"
+ "fmt"
+ "io/ioutil"
+ "os"
+ "path/filepath"
+ "reflect"
+ "runtime"
+ "strings"
+ "testing"
+
+ "github.com/hashicorp/packer/packer"
+)
+
+func TestDecodeConfig(t *testing.T) {
+
+ packerConfig := `
+ {
+ "PluginMinPort": 10,
+ "PluginMaxPort": 25,
+ "disable_checkpoint": true,
+ "disable_checkpoint_signature": true,
+ "provisioners": {
+ "super-shell": "packer-provisioner-super-shell"
+ }
+ }`
+
+ var cfg config
+ err := decodeConfig(strings.NewReader(packerConfig), &cfg)
+ if err != nil {
+ t.Fatalf("error encountered decoding configuration: %v", err)
+ }
+
+ var expectedCfg config
+ json.NewDecoder(strings.NewReader(packerConfig)).Decode(&expectedCfg)
+ if !reflect.DeepEqual(cfg, expectedCfg) {
+ t.Errorf("failed to load custom configuration data; expected %v got %v", expectedCfg, cfg)
+ }
+
+}
+
+func TestLoadExternalComponentsFromConfig(t *testing.T) {
+ packerConfigData, cleanUpFunc, err := generateFakePackerConfigData()
+ if err != nil {
+ t.Fatalf("error encountered while creating fake Packer configuration data %v", err)
+ }
+ defer cleanUpFunc()
+
+ cfg := config{
+ Plugins: &packer.PluginConfig{
+ Builders: packer.MapOfBuilder{},
+ PostProcessors: packer.MapOfPostProcessor{},
+ Provisioners: packer.MapOfProvisioner{},
+ },
+ }
+
+ if err := decodeConfig(strings.NewReader(packerConfigData), &cfg); err != nil {
+ t.Fatalf("error encountered decoding configuration: %v", err)
+ }
+
+ cfg.LoadExternalComponentsFromConfig()
+
+ if len(cfg.Plugins.Builders.List()) != 1 || !cfg.Plugins.Builders.Has("cloud-xyz") {
+ t.Errorf("failed to load external builders; got %v as the resulting config", cfg.Plugins.Builders)
+ }
+
+ if len(cfg.Plugins.PostProcessors.List()) != 1 || !cfg.Plugins.PostProcessors.Has("noop") {
+ t.Errorf("failed to load external post-processors; got %v as the resulting config", cfg.Plugins.PostProcessors)
+ }
+
+ if len(cfg.Plugins.Provisioners.List()) != 1 || !cfg.Plugins.Provisioners.Has("super-shell") {
+ t.Errorf("failed to load external provisioners; got %v as the resulting config", cfg.Plugins.Provisioners)
+ }
+
+}
+
+func TestLoadExternalComponentsFromConfig_onlyProvisioner(t *testing.T) {
+ packerConfigData, cleanUpFunc, err := generateFakePackerConfigData()
+ if err != nil {
+ t.Fatalf("error encountered while creating fake Packer configuration data %v", err)
+ }
+ defer cleanUpFunc()
+
+ cfg := config{
+ Plugins: &packer.PluginConfig{
+ Builders: packer.MapOfBuilder{},
+ PostProcessors: packer.MapOfPostProcessor{},
+ Provisioners: packer.MapOfProvisioner{},
+ },
+ }
+
+ if err := decodeConfig(strings.NewReader(packerConfigData), &cfg); err != nil {
+ t.Fatalf("error encountered decoding configuration: %v", err)
+ }
+
+ /* Let's clear out any custom Builders or PostProcessors that were part of the config.
+ This step does not remove them from disk, it just removes them from of plugins Packer knows about.
+ */
+ cfg.RawBuilders = nil
+ cfg.RawPostProcessors = nil
+
+ cfg.LoadExternalComponentsFromConfig()
+
+ if len(cfg.Plugins.Builders.List()) != 0 {
+ t.Errorf("loaded external builders when it wasn't supposed to; got %v as the resulting config", cfg.Plugins.Builders)
+ }
+
+ if len(cfg.Plugins.PostProcessors.List()) != 0 {
+ t.Errorf("loaded external post-processors when it wasn't supposed to; got %v as the resulting config", cfg.Plugins.PostProcessors)
+ }
+
+ if len(cfg.Plugins.Provisioners.List()) != 1 || !cfg.Plugins.Provisioners.Has("super-shell") {
+ t.Errorf("failed to load external provisioners; got %v as the resulting config", cfg.Plugins.Provisioners)
+ }
+}
+
+func TestLoadSingleComponent(t *testing.T) {
+
+ // .exe will work everyone for testing purpose, but mostly here to help Window's test runs.
+ tmpFile, err := ioutil.TempFile(".", "packer-builder-*.exe")
+ if err != nil {
+ t.Fatalf("failed to create test file with error: %s", err)
+ }
+ defer os.Remove(tmpFile.Name())
+
+ tt := []struct {
+ pluginPath string
+ errorExpected bool
+ }{
+ {pluginPath: tmpFile.Name(), errorExpected: false},
+ {pluginPath: "./non-existing-file", errorExpected: true},
+ }
+
+ cfg := config{
+ Plugins: &packer.PluginConfig{
+ Builders: packer.MapOfBuilder{},
+ PostProcessors: packer.MapOfPostProcessor{},
+ Provisioners: packer.MapOfProvisioner{},
+ },
+ }
+
+ for _, tc := range tt {
+ tc := tc
+ _, err := cfg.loadSingleComponent(tc.pluginPath)
+ if tc.errorExpected && err == nil {
+ t.Errorf("expected loadSingleComponent(%s) to error but it didn't", tc.pluginPath)
+ continue
+ }
+
+ if err != nil && !tc.errorExpected {
+ t.Errorf("expected loadSingleComponent(%s) to load properly but got an error: %v", tc.pluginPath, err)
+ }
+ }
+
+}
+
+func generateFakePlugins(dirname string, pluginNames []string) (string, []string, func(), error) {
+ dir, err := ioutil.TempDir("", dirname)
+ if err != nil {
+ return "", nil, nil, fmt.Errorf("failed to create temporary test directory: %v", err)
+ }
+
+ cleanUpFunc := func() {
+ os.RemoveAll(dir)
+ }
+
+ var suffix string
+ if runtime.GOOS == "windows" {
+ suffix = ".exe"
+ }
+
+ plugins := make([]string, len(pluginNames))
+ for i, plugin := range pluginNames {
+ plug := filepath.Join(dir, plugin+suffix)
+ plugins[i] = plug
+ _, err := os.Create(plug)
+ if err != nil {
+ cleanUpFunc()
+ return "", nil, nil, fmt.Errorf("failed to create temporary plugin file (%s): %v", plug, err)
+ }
+ }
+
+ return dir, plugins, cleanUpFunc, nil
+}
+
+/*
+ generateFakePackerConfigData creates a collection of mock plugins along with a basic packerconfig.
+
+The return packerConfigData is a valid packerconfig file that can be used for configuring external plugins, cleanUpFunc is a function that should be called for cleaning up any generated mock data.
+This function will only clean up if there is an error, on successful runs the caller
+is responsible for cleaning up the data via cleanUpFunc().
+*/
+func generateFakePackerConfigData() (packerConfigData string, cleanUpFunc func(), err error) {
+ _, plugins, cleanUpFunc, err := generateFakePlugins("random-testdata",
+ []string{"packer-builder-cloud-xyz",
+ "packer-provisioner-super-shell",
+ "packer-post-processor-noop"})
+
+ if err != nil {
+ cleanUpFunc()
+ return "", nil, err
+ }
+
+ packerConfigData = fmt.Sprintf(`
+ {
+ "PluginMinPort": 10,
+ "PluginMaxPort": 25,
+ "disable_checkpoint": true,
+ "disable_checkpoint_signature": true,
+ "builders": {
+ "cloud-xyz": %q
+ },
+ "provisioners": {
+ "super-shell": %q
+ },
+ "post-processors": {
+ "noop": %q
+ }
+ }`, plugins[0], plugins[1], plugins[2])
+
+ return
+}
diff --git a/v1.9.4/contrib/zsh-completion/_packer b/v1.9.4/contrib/zsh-completion/_packer
new file mode 100644
index 0000000..4b361b4
--- /dev/null
+++ b/v1.9.4/contrib/zsh-completion/_packer
@@ -0,0 +1,100 @@
+#compdef packer
+
+_packer () {
+ local -a sub_commands && sub_commands=(
+ 'build:Build image(s) from template'
+ 'console:Creates a console for testing variable interpolation'
+ 'fix:Fixes templates from old versions of packer'
+ 'fmt:Rewrites HCL2 config files to canonical format'
+ 'hcl2_upgrade:Transform a JSON template into an HCL2 configuration'
+ 'init:Install missing plugins or upgrade plugins'
+ 'inspect:See components of a template'
+ 'plugins:Interact with Packer plugins and catalog'
+ 'validate:Check that a template is valid'
+ 'version:Prints the Packer version'
+ )
+
+ local -a build_arguments && build_arguments=(
+ '-debug[Debug mode enabled for builds.]'
+ '-force[Force a build to continue if artifacts exist, deletes existing artifacts.]'
+ '-machine-readable[Produce machine-readable output.]'
+ '-color=[(false) Disable color output. (Default: color)]'
+ '-except=[(foo,bar,baz) Run all builds and post-processors other than these.]'
+ '-on-error=[(cleanup,abort,ask) If the build fails do: clean up (default), abort, or ask.]'
+ '-only=[(foo,bar,baz) Only build the given builds by name.]'
+ '-parallel=[(false) Disable parallelization. (Default: false)]'
+ '-parallel-builds=[(0) Number of builds to run in parallel. (Defaults to infinite: 0)]'
+ '-timestamp-ui[Enable prefixing of each ui output with an RFC3339 timestamp]'
+ '-var[("key=value") Variable for templates, can be used multiple times.]'
+ '-var-file=[(path) JSON or HCL2 file containing user variables.]'
+ '-warn-on-undeclared-var[Display warnings for user variable files containing undeclared variables.]'
+ '(-)*:files:_files -g "*pkr.{hcl,json}"'
+ )
+
+ local -a console_arguments && console_arguments=(
+ '-var[("key=value") Variable for templates, can be used multiple times.]'
+ '-var-file=[(path) JSON or HCL2 file containing user variables.]'
+ '(-)*:files:_files -g "*pkr.{hcl,json}"'
+ )
+
+ local -a fix_arguments && fix_arguments=(
+ '(-)*:files:_files -g "*.json"'
+ )
+
+ local -a fmt_arguments && fmt_arguments=(
+ '-check[Check if the input is formatted. Exit status 0 = properly formatted, non-zero otherwise.]'
+ '-diff[Display diffs of formatting change]'
+ '-write=[(false) Don not write to source files (always disabled if using -check)]'
+ '-recursive[Also process files in subdirectories. By default cwd only]'
+ '(-)*:files:_files -g "*pkr.{hcl,json}"'
+ )
+
+ local -a init_arguments && init_arguments=(
+ '-upgrade[on top also update plugins to latest]'
+ '(-)*:files:_files -g "*pkr.{hcl,json}"'
+ )
+
+ local -a inspect_arguments && inspect_arguments=(
+ '-machine-readable[Machine-readable output]'
+ '(-)*:files:_files -g "*pkr.{hcl,json}"'
+ )
+
+ local -a validate_arguments && validate_arguments=(
+ '-syntax-only[Only check syntax. Do not verify config of the template.]'
+ '-except=[(foo,bar,baz) Validate all builds other than these.]'
+ '-only=[(foo,bar,baz) Validate only these builds.]'
+ '-var[("key=value") Variable for templates, can be used multiple times.]'
+ '-var-file=[(path) JSON or HCL2 file containing user variables.]'
+ '-no-warn-undeclared-var[Disable warnings for user variable files containing undeclared variables.]'
+ '-evaluate-datasources[(false) Evaluate data sources during validation (HCL2 only, may incur costs).]'
+ '(-)*:files:_files -g "*pkr.{hcl,json}"'
+ )
+
+ _arguments -C \
+ ':command:->command' \
+ '*::options:->options'
+
+ case $state in
+ command)
+ _describe -t commands 'command' sub_commands ;;
+ options)
+ case $line[1] in
+ build)
+ _arguments -s -S : $build_arguments ;;
+ console)
+ _arguments -s -S : $console_arguments ;;
+ fix)
+ _arguments -s -S : $fix_arguments ;;
+ fmt)
+ _arguments -s -S : $fmt_arguments ;;
+ init)
+ _arguments -s -S : $init_arguments ;;
+ inspect)
+ _arguments -s -S : $inspect_arguments ;;
+ validate)
+ _arguments -s -S : $validate_arguments ;;
+ esac
+ ;;
+ esac
+}
+_packer "$@"
diff --git a/v1.9.4/datasource/.gitkeep b/v1.9.4/datasource/.gitkeep
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/v1.9.4/datasource/.gitkeep
diff --git a/v1.9.4/datasource/hcp-packer-image/data.go b/v1.9.4/datasource/hcp-packer-image/data.go
new file mode 100644
index 0000000..3e473e1
--- /dev/null
+++ b/v1.9.4/datasource/hcp-packer-image/data.go
@@ -0,0 +1,229 @@
+// Copyright (c) HashiCorp, Inc.
+// SPDX-License-Identifier: MPL-2.0
+
+//go:generate packer-sdc struct-markdown
+//go:generate packer-sdc mapstructure-to-hcl2 -type DatasourceOutput,Config
+package hcp_packer_image
+
+import (
+ "context"
+ "errors"
+ "fmt"
+ "log"
+ "time"
+
+ "github.com/zclconf/go-cty/cty"
+
+ "github.com/hashicorp/hcl/v2/hcldec"
+ "github.com/hashicorp/hcp-sdk-go/clients/cloud-packer-service/stable/2021-04-30/models"
+ "github.com/hashicorp/packer-plugin-sdk/common"
+ "github.com/hashicorp/packer-plugin-sdk/hcl2helper"
+ packersdk "github.com/hashicorp/packer-plugin-sdk/packer"
+ "github.com/hashicorp/packer-plugin-sdk/template/config"
+ hcpapi "github.com/hashicorp/packer/internal/hcp/api"
+)
+
+type Datasource struct {
+ config Config
+}
+
+type Config struct {
+ common.PackerConfig `mapstructure:",squash"`
+ // The name of the bucket your image is in.
+ Bucket string `mapstructure:"bucket_name" required:"true"`
+ // The name of the channel to use when retrieving your image.
+ // Either this or `iteration_id` MUST be set.
+ // Mutually exclusive with `iteration_id`.
+ // If using several images from a single iteration, you may prefer
+ // sourcing an iteration first, and referencing it for subsequent uses,
+ // as every `hcp_packer_image` with the channel set will generate a
+ // potentially billable HCP Packer request, but if several
+ // `hcp_packer_image`s use a shared `hcp_packer_iteration` that will
+ // only generate one potentially billable request.
+ Channel string `mapstructure:"channel" required:"true"`
+ // The ID of the iteration to use when retrieving your image
+ // Either this or `channel` MUST be set.
+ // Mutually exclusive with `channel`
+ IterationID string `mapstructure:"iteration_id" required:"true"`
+ // The name of the cloud provider that your image is for. For example,
+ // "aws" or "gce".
+ CloudProvider string `mapstructure:"cloud_provider" required:"true"`
+ // The name of the cloud region your image is in. For example "us-east-1".
+ Region string `mapstructure:"region" required:"true"`
+ // The specific Packer builder used to create the image.
+ // For example, "amazon-ebs.example"
+ ComponentType string `mapstructure:"component_type" required:"false"`
+ // TODO: Version string `mapstructure:"version"`
+ // TODO: Fingerprint string `mapstructure:"fingerprint"`
+ // TODO: Label string `mapstructure:"label"`
+}
+
+func (d *Datasource) ConfigSpec() hcldec.ObjectSpec {
+ return d.config.FlatMapstructure().HCL2Spec()
+}
+
+func (d *Datasource) Configure(raws ...interface{}) error {
+ err := config.Decode(&d.config, nil, raws...)
+ if err != nil {
+ return err
+ }
+
+ var errs *packersdk.MultiError
+
+ if d.config.Bucket == "" {
+ errs = packersdk.MultiErrorAppend(errs, fmt.Errorf("The `bucket_name` must be specified"))
+ }
+
+ // Ensure either channel or iteration_id are set, and not both at the same time
+ if d.config.Channel == "" &&
+ d.config.IterationID == "" {
+ errs = packersdk.MultiErrorAppend(errs, errors.New(
+ "The `iteration_id` or `channel` must be specified."))
+ }
+ if d.config.Channel != "" &&
+ d.config.IterationID != "" {
+ errs = packersdk.MultiErrorAppend(errs, errors.New(
+ "`iteration_id` and `channel` cannot both be specified."))
+ }
+
+ if d.config.Region == "" {
+ errs = packersdk.MultiErrorAppend(errs, fmt.Errorf("`region` is "+
+ "currently a required field."))
+ }
+ if d.config.CloudProvider == "" {
+ errs = packersdk.MultiErrorAppend(errs, fmt.Errorf("`cloud_provider` is "+
+ "currently a required field."))
+ }
+
+ if errs != nil && len(errs.Errors) > 0 {
+ return errs
+ }
+ return nil
+}
+
+// DatasourceOutput Information from []*models.HashicorpCloudPackerImage with some information
+// from the parent []*models.HashicorpCloudPackerBuild included where it seemed
+// like it might be relevant. Need to copy so we can generate
+type DatasourceOutput struct {
+ // The name of the cloud provider that the image exists in. For example,
+ // "aws", "azure", or "gce".
+ CloudProvider string `mapstructure:"cloud_provider"`
+ // The specific Packer builder or post-processor used to create the image.
+ ComponentType string `mapstructure:"component_type"`
+ // The date and time at which the image was created.
+ CreatedAt string `mapstructure:"created_at"`
+ // The ID of the build that created the image. This is a ULID, which is a
+ // unique identifier similar to a UUID. It is created by the HCP Packer
+ // Registry when an build is first created, and is unique to this build.
+ BuildID string `mapstructure:"build_id"`
+ // The iteration ID. This is a ULID, which is a unique identifier similar
+ // to a UUID. It is created by the HCP Packer Registry when an iteration is
+ // first created, and is unique to this iteration.
+ IterationID string `mapstructure:"iteration_id"`
+ // The ID of the channel used to query the image iteration. This value will be empty if the `iteration_id` was used
+ // directly instead of a channel.
+ ChannelID string `mapstructure:"channel_id"`
+ // The UUID associated with the Packer run that created this image.
+ PackerRunUUID string `mapstructure:"packer_run_uuid"`
+ // ID or URL of the remote cloud image as given by a build.
+ ID string `mapstructure:"id"`
+ // The cloud region as given by `packer build`. eg. "ap-east-1".
+ // For locally managed clouds, this may map instead to a cluster, server
+ // or datastore.
+ Region string `mapstructure:"region"`
+ // The key:value metadata labels associated with this build.
+ Labels map[string]string `mapstructure:"labels"`
+}
+
+func (d *Datasource) OutputSpec() hcldec.ObjectSpec {
+ return (&DatasourceOutput{}).FlatMapstructure().HCL2Spec()
+}
+
+func (d *Datasource) Execute() (cty.Value, error) {
+ ctx := context.TODO()
+
+ cli, err := hcpapi.NewClient()
+ if err != nil {
+ return cty.NullVal(cty.EmptyObject), err
+ }
+
+ var iteration *models.HashicorpCloudPackerIteration
+ var channelID string
+ if d.config.IterationID != "" {
+ log.Printf("[INFO] Reading info from HCP Packer registry (%s) [project_id=%s, organization_id=%s, iteration_id=%s]",
+ d.config.Bucket, cli.ProjectID, cli.OrganizationID, d.config.IterationID)
+
+ iter, err := cli.GetIteration(ctx, d.config.Bucket, hcpapi.GetIteration_byID(d.config.IterationID))
+ if err != nil {
+ return cty.NullVal(cty.EmptyObject), fmt.Errorf(
+ "error retrieving image iteration from HCP Packer registry: %s",
+ err)
+ }
+ iteration = iter
+ } else {
+ log.Printf("[INFO] Reading info from HCP Packer registry (%s) [project_id=%s, organization_id=%s, channel=%s]",
+ d.config.Bucket, cli.ProjectID, cli.OrganizationID, d.config.Channel)
+
+ channel, err := cli.GetChannel(ctx, d.config.Bucket, d.config.Channel)
+ if err != nil {
+ return cty.NullVal(cty.EmptyObject), fmt.Errorf("error retrieving "+
+ "channel from HCP Packer registry: %s", err.Error())
+ }
+
+ if channel.Iteration == nil {
+ return cty.NullVal(cty.EmptyObject), fmt.Errorf("there is no iteration associated with the channel %s",
+ d.config.Channel)
+ }
+ channelID = channel.ID
+ iteration = channel.Iteration
+ }
+
+ revokeAt := time.Time(iteration.RevokeAt)
+ if !revokeAt.IsZero() && revokeAt.Before(time.Now().UTC()) {
+ // If RevokeAt is not a zero date and is before NOW, it means this iteration is revoked and should not be used
+ // to build new images.
+ return cty.NullVal(cty.EmptyObject), fmt.Errorf("the iteration %s is revoked and can not be used on Packer builds",
+ iteration.ID)
+ }
+
+ output := DatasourceOutput{}
+
+ cloudAndRegions := map[string][]string{}
+ for _, build := range iteration.Builds {
+ if build.CloudProvider != d.config.CloudProvider {
+ continue
+ }
+ for _, image := range build.Images {
+ cloudAndRegions[build.CloudProvider] = append(cloudAndRegions[build.CloudProvider], image.Region)
+ if image.Region == d.config.Region && filterBuildByComponentType(build, d.config.ComponentType) {
+ // This is the desired image.
+ output = DatasourceOutput{
+ CloudProvider: build.CloudProvider,
+ ComponentType: build.ComponentType,
+ CreatedAt: image.CreatedAt.String(),
+ BuildID: build.ID,
+ IterationID: build.IterationID,
+ ChannelID: channelID,
+ PackerRunUUID: build.PackerRunUUID,
+ ID: image.ImageID,
+ Region: image.Region,
+ Labels: build.Labels,
+ }
+ return hcl2helper.HCL2ValueFromConfig(output, d.OutputSpec()), nil
+ }
+ }
+ }
+
+ return cty.NullVal(cty.EmptyObject), fmt.Errorf("could not find a build result matching "+
+ "[region=%q, cloud_provider=%q, component_type=%q]. Available: %v ",
+ d.config.Region, d.config.CloudProvider, d.config.ComponentType, cloudAndRegions)
+}
+
+func filterBuildByComponentType(build *models.HashicorpCloudPackerBuild, componentType string) bool {
+ // optional field is not specified, passthrough
+ if componentType == "" {
+ return true
+ }
+ // if specified, only the matched image metadata is returned by this effect
+ return build.ComponentType == componentType
+}
diff --git a/v1.9.4/datasource/hcp-packer-image/data.hcl2spec.go b/v1.9.4/datasource/hcp-packer-image/data.hcl2spec.go
new file mode 100644
index 0000000..2bae3fe
--- /dev/null
+++ b/v1.9.4/datasource/hcp-packer-image/data.hcl2spec.go
@@ -0,0 +1,98 @@
+// Code generated by "packer-sdc mapstructure-to-hcl2"; DO NOT EDIT.
+
+package hcp_packer_image
+
+import (
+ "github.com/hashicorp/hcl/v2/hcldec"
+ "github.com/zclconf/go-cty/cty"
+)
+
+// FlatConfig is an auto-generated flat version of Config.
+// Where the contents of a field with a `mapstructure:,squash` tag are bubbled up.
+type FlatConfig struct {
+ PackerBuildName *string `mapstructure:"packer_build_name" cty:"packer_build_name" 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"`
+ Bucket *string `mapstructure:"bucket_name" required:"true" cty:"bucket_name" hcl:"bucket_name"`
+ Channel *string `mapstructure:"channel" required:"true" cty:"channel" hcl:"channel"`
+ IterationID *string `mapstructure:"iteration_id" required:"true" cty:"iteration_id" hcl:"iteration_id"`
+ CloudProvider *string `mapstructure:"cloud_provider" required:"true" cty:"cloud_provider" hcl:"cloud_provider"`
+ Region *string `mapstructure:"region" required:"true" cty:"region" hcl:"region"`
+ ComponentType *string `mapstructure:"component_type" required:"false" cty:"component_type" hcl:"component_type"`
+}
+
+// FlatMapstructure returns a new FlatConfig.
+// FlatConfig is an auto-generated flat version of Config.
+// Where the contents a fields with a `mapstructure:,squash` tag are bubbled up.
+func (*Config) FlatMapstructure() interface{ HCL2Spec() map[string]hcldec.Spec } {
+ return new(FlatConfig)
+}
+
+// HCL2Spec returns the hcl spec of a Config.
+// This spec is used by HCL to read the fields of Config.
+// The decoded values from this spec will then be applied to a FlatConfig.
+func (*FlatConfig) HCL2Spec() map[string]hcldec.Spec {
+ s := map[string]hcldec.Spec{
+ "packer_build_name": &hcldec.AttrSpec{Name: "packer_build_name", Type: cty.String, Required: false},
+ "packer_builder_type": &hcldec.AttrSpec{Name: "packer_builder_type", Type: cty.String, Required: false},
+ "packer_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_sensitive_variables": &hcldec.AttrSpec{Name: "packer_sensitive_variables", Type: cty.List(cty.String), Required: false},
+ "bucket_name": &hcldec.AttrSpec{Name: "bucket_name", Type: cty.String, Required: false},
+ "channel": &hcldec.AttrSpec{Name: "channel", Type: cty.String, Required: false},
+ "iteration_id": &hcldec.AttrSpec{Name: "iteration_id", Type: cty.String, Required: false},
+ "cloud_provider": &hcldec.AttrSpec{Name: "cloud_provider", Type: cty.String, Required: false},
+ "region": &hcldec.AttrSpec{Name: "region", Type: cty.String, Required: false},
+ "component_type": &hcldec.AttrSpec{Name: "component_type", Type: cty.String, Required: false},
+ }
+ return s
+}
+
+// FlatDatasourceOutput is an auto-generated flat version of DatasourceOutput.
+// Where the contents of a field with a `mapstructure:,squash` tag are bubbled up.
+type FlatDatasourceOutput struct {
+ CloudProvider *string `mapstructure:"cloud_provider" cty:"cloud_provider" hcl:"cloud_provider"`
+ ComponentType *string `mapstructure:"component_type" cty:"component_type" hcl:"component_type"`
+ CreatedAt *string `mapstructure:"created_at" cty:"created_at" hcl:"created_at"`
+ BuildID *string `mapstructure:"build_id" cty:"build_id" hcl:"build_id"`
+ IterationID *string `mapstructure:"iteration_id" cty:"iteration_id" hcl:"iteration_id"`
+ ChannelID *string `mapstructure:"channel_id" cty:"channel_id" hcl:"channel_id"`
+ PackerRunUUID *string `mapstructure:"packer_run_uuid" cty:"packer_run_uuid" hcl:"packer_run_uuid"`
+ ID *string `mapstructure:"id" cty:"id" hcl:"id"`
+ Region *string `mapstructure:"region" cty:"region" hcl:"region"`
+ Labels map[string]string `mapstructure:"labels" cty:"labels" hcl:"labels"`
+}
+
+// FlatMapstructure returns a new FlatDatasourceOutput.
+// FlatDatasourceOutput is an auto-generated flat version of DatasourceOutput.
+// Where the contents a fields with a `mapstructure:,squash` tag are bubbled up.
+func (*DatasourceOutput) FlatMapstructure() interface{ HCL2Spec() map[string]hcldec.Spec } {
+ return new(FlatDatasourceOutput)
+}
+
+// HCL2Spec returns the hcl spec of a DatasourceOutput.
+// This spec is used by HCL to read the fields of DatasourceOutput.
+// The decoded values from this spec will then be applied to a FlatDatasourceOutput.
+func (*FlatDatasourceOutput) HCL2Spec() map[string]hcldec.Spec {
+ s := map[string]hcldec.Spec{
+ "cloud_provider": &hcldec.AttrSpec{Name: "cloud_provider", Type: cty.String, Required: false},
+ "component_type": &hcldec.AttrSpec{Name: "component_type", Type: cty.String, Required: false},
+ "created_at": &hcldec.AttrSpec{Name: "created_at", Type: cty.String, Required: false},
+ "build_id": &hcldec.AttrSpec{Name: "build_id", Type: cty.String, Required: false},
+ "iteration_id": &hcldec.AttrSpec{Name: "iteration_id", Type: cty.String, Required: false},
+ "channel_id": &hcldec.AttrSpec{Name: "channel_id", Type: cty.String, Required: false},
+ "packer_run_uuid": &hcldec.AttrSpec{Name: "packer_run_uuid", Type: cty.String, Required: false},
+ "id": &hcldec.AttrSpec{Name: "id", Type: cty.String, Required: false},
+ "region": &hcldec.AttrSpec{Name: "region", Type: cty.String, Required: false},
+ "labels": &hcldec.AttrSpec{Name: "labels", Type: cty.Map(cty.String), Required: false},
+ }
+ return s
+}
diff --git a/v1.9.4/datasource/hcp-packer-iteration/data.go b/v1.9.4/datasource/hcp-packer-iteration/data.go
new file mode 100644
index 0000000..7a7be3e
--- /dev/null
+++ b/v1.9.4/datasource/hcp-packer-iteration/data.go
@@ -0,0 +1,146 @@
+// Copyright (c) HashiCorp, Inc.
+// SPDX-License-Identifier: MPL-2.0
+
+//go:generate packer-sdc struct-markdown
+//go:generate packer-sdc mapstructure-to-hcl2 -type DatasourceOutput,Config
+package hcp_packer_iteration
+
+import (
+ "context"
+ "fmt"
+ "log"
+ "time"
+
+ "github.com/zclconf/go-cty/cty"
+
+ "github.com/hashicorp/hcl/v2/hcldec"
+ "github.com/hashicorp/packer-plugin-sdk/common"
+ "github.com/hashicorp/packer-plugin-sdk/hcl2helper"
+ packersdk "github.com/hashicorp/packer-plugin-sdk/packer"
+ "github.com/hashicorp/packer-plugin-sdk/template/config"
+ hcpapi "github.com/hashicorp/packer/internal/hcp/api"
+)
+
+type Datasource struct {
+ config Config
+}
+
+type Config struct {
+ common.PackerConfig `mapstructure:",squash"`
+ // The name of the bucket your image is in.
+ Bucket string `mapstructure:"bucket_name" required:"true"`
+ // The name of the channel to use when retrieving your image
+ Channel string `mapstructure:"channel" required:"true"`
+ // TODO: Version string `mapstructure:"version"`
+ // TODO: Fingerprint string `mapstructure:"fingerprint"`
+ // TODO: Label string `mapstructure:"label"`
+}
+
+func (d *Datasource) ConfigSpec() hcldec.ObjectSpec {
+ return d.config.FlatMapstructure().HCL2Spec()
+}
+
+func (d *Datasource) Configure(raws ...interface{}) error {
+ err := config.Decode(&d.config, nil, raws...)
+ if err != nil {
+ return err
+ }
+
+ var errs *packersdk.MultiError
+
+ if d.config.Bucket == "" {
+ errs = packersdk.MultiErrorAppend(errs, fmt.Errorf("The `bucket_name` must be specified"))
+ }
+ if d.config.Channel == "" {
+ errs = packersdk.MultiErrorAppend(errs, fmt.Errorf("`channel` is currently a required field."))
+ }
+
+ if errs != nil && len(errs.Errors) > 0 {
+ return errs
+ }
+ return nil
+}
+
+// DatasourceOutput is essentially a copy of []*models.HashicorpCloudPackerIteration, but without the
+// []Builds or ancestor id.
+type DatasourceOutput struct {
+ // who created the iteration
+ AuthorID string `mapstructure:"author_id"`
+ // Name of the bucket that the iteration was retrieved from
+ BucketName string `mapstructure:"bucket_name"`
+ // If true, this iteration is considered "ready to use" and will be
+ // returned even if the include_incomplete flag is "false" in the
+ // list iterations request. Note that if you are retrieving an iteration
+ // using a channel, this will always be "true"; channels cannot be assigned
+ // to incomplete iterations.
+ Complete bool `mapstructure:"complete"`
+ // The date the iteration was created.
+ CreatedAt string `mapstructure:"created_at"`
+ // The fingerprint of the build; this could be a git sha or other unique
+ // identifier as set by the Packer build that created this iteration.
+ Fingerprint string `mapstructure:"fingerprint"`
+ // The iteration ID. This is a ULID, which is a unique identifier similar
+ // to a UUID. It is created by the HCP Packer Registry when an iteration is
+ // first created, and is unique to this iteration.
+ ID string `mapstructure:"id"`
+ // The version number assigned to an iteration. This number is an integer,
+ // and is created by the HCP Packer Registry once an iteration is
+ // marked "complete". If a new iteration is marked "complete", the version
+ // that HCP Packer assigns to it will always be the highest previous
+ // iteration version plus one.
+ IncrementalVersion int32 `mapstructure:"incremental_version"`
+ // The date when this iteration was last updated.
+ UpdatedAt string `mapstructure:"updated_at"`
+ // The ID of the channel used to query the image iteration.
+ ChannelID string `mapstructure:"channel_id"`
+}
+
+func (d *Datasource) OutputSpec() hcldec.ObjectSpec {
+ return (&DatasourceOutput{}).FlatMapstructure().HCL2Spec()
+}
+
+func (d *Datasource) Execute() (cty.Value, error) {
+ ctx := context.TODO()
+
+ cli, err := hcpapi.NewClient()
+ if err != nil {
+ return cty.NullVal(cty.EmptyObject), err
+ }
+ // Load channel.
+ log.Printf("[INFO] Reading iteration info from HCP Packer registry (%s) [project_id=%s, organization_id=%s, channel=%s]",
+ d.config.Bucket, cli.ProjectID, cli.OrganizationID, d.config.Channel)
+
+ channel, err := cli.GetChannel(ctx, d.config.Bucket, d.config.Channel)
+ if err != nil {
+ return cty.NullVal(cty.EmptyObject), fmt.Errorf("error retrieving "+
+ "iteration from HCP Packer registry: %s", err.Error())
+ }
+ if channel.Iteration == nil {
+ return cty.NullVal(cty.EmptyObject), fmt.Errorf("there is no iteration associated with the channel %s",
+ d.config.Channel)
+ }
+
+ iteration := channel.Iteration
+
+ revokeAt := time.Time(iteration.RevokeAt)
+ if !revokeAt.IsZero() && revokeAt.Before(time.Now().UTC()) {
+ // If RevokeAt is not a zero date and is before NOW, it means this iteration is revoked and should not be used
+ // to build new images.
+ return cty.NullVal(cty.EmptyObject), fmt.Errorf("the iteration associated with the channel %s is revoked and can not be used on Packer builds",
+ d.config.Channel)
+ }
+
+ output := DatasourceOutput{
+ AuthorID: iteration.AuthorID,
+ BucketName: iteration.BucketSlug,
+ Complete: iteration.Complete,
+ CreatedAt: iteration.CreatedAt.String(),
+ Fingerprint: iteration.Fingerprint,
+ ID: iteration.ID,
+ IncrementalVersion: iteration.IncrementalVersion,
+ UpdatedAt: iteration.UpdatedAt.String(),
+ ChannelID: channel.ID,
+ }
+
+ return hcl2helper.HCL2ValueFromConfig(output, d.OutputSpec()), nil
+}
diff --git a/v1.9.4/datasource/hcp-packer-iteration/data.hcl2spec.go b/v1.9.4/datasource/hcp-packer-iteration/data.hcl2spec.go
new file mode 100644
index 0000000..512331f
--- /dev/null
+++ b/v1.9.4/datasource/hcp-packer-iteration/data.hcl2spec.go
@@ -0,0 +1,88 @@
+// Code generated by "packer-sdc mapstructure-to-hcl2"; DO NOT EDIT.
+
+package hcp_packer_iteration
+
+import (
+ "github.com/hashicorp/hcl/v2/hcldec"
+ "github.com/zclconf/go-cty/cty"
+)
+
+// FlatConfig is an auto-generated flat version of Config.
+// Where the contents of a field with a `mapstructure:,squash` tag are bubbled up.
+type FlatConfig struct {
+ PackerBuildName *string `mapstructure:"packer_build_name" cty:"packer_build_name" 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"`
+ Bucket *string `mapstructure:"bucket_name" required:"true" cty:"bucket_name" hcl:"bucket_name"`
+ Channel *string `mapstructure:"channel" required:"true" cty:"channel" hcl:"channel"`
+}
+
+// FlatMapstructure returns a new FlatConfig.
+// FlatConfig is an auto-generated flat version of Config.
+// Where the contents a fields with a `mapstructure:,squash` tag are bubbled up.
+func (*Config) FlatMapstructure() interface{ HCL2Spec() map[string]hcldec.Spec } {
+ return new(FlatConfig)
+}
+
+// HCL2Spec returns the hcl spec of a Config.
+// This spec is used by HCL to read the fields of Config.
+// The decoded values from this spec will then be applied to a FlatConfig.
+func (*FlatConfig) HCL2Spec() map[string]hcldec.Spec {
+ s := map[string]hcldec.Spec{
+ "packer_build_name": &hcldec.AttrSpec{Name: "packer_build_name", Type: cty.String, Required: false},
+ "packer_builder_type": &hcldec.AttrSpec{Name: "packer_builder_type", Type: cty.String, Required: false},
+ "packer_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_sensitive_variables": &hcldec.AttrSpec{Name: "packer_sensitive_variables", Type: cty.List(cty.String), Required: false},
+ "bucket_name": &hcldec.AttrSpec{Name: "bucket_name", Type: cty.String, Required: false},
+ "channel": &hcldec.AttrSpec{Name: "channel", Type: cty.String, Required: false},
+ }
+ return s
+}
+
+// FlatDatasourceOutput is an auto-generated flat version of DatasourceOutput.
+// Where the contents of a field with a `mapstructure:,squash` tag are bubbled up.
+type FlatDatasourceOutput struct {
+ AuthorID *string `mapstructure:"author_id" cty:"author_id" hcl:"author_id"`
+ BucketName *string `mapstructure:"bucket_name" cty:"bucket_name" hcl:"bucket_name"`
+ Complete *bool `mapstructure:"complete" cty:"complete" hcl:"complete"`
+ CreatedAt *string `mapstructure:"created_at" cty:"created_at" hcl:"created_at"`
+ Fingerprint *string `mapstructure:"fingerprint" cty:"fingerprint" hcl:"fingerprint"`
+ ID *string `mapstructure:"id" cty:"id" hcl:"id"`
+ IncrementalVersion *int32 `mapstructure:"incremental_version" cty:"incremental_version" hcl:"incremental_version"`
+ UpdatedAt *string `mapstructure:"updated_at" cty:"updated_at" hcl:"updated_at"`
+ ChannelID *string `mapstructure:"channel_id" cty:"channel_id" hcl:"channel_id"`
+}
+
+// FlatMapstructure returns a new FlatDatasourceOutput.
+// FlatDatasourceOutput is an auto-generated flat version of DatasourceOutput.
+// Where the contents a fields with a `mapstructure:,squash` tag are bubbled up.
+func (*DatasourceOutput) FlatMapstructure() interface{ HCL2Spec() map[string]hcldec.Spec } {
+ return new(FlatDatasourceOutput)
+}
+
+// HCL2Spec returns the hcl spec of a DatasourceOutput.
+// This spec is used by HCL to read the fields of DatasourceOutput.
+// The decoded values from this spec will then be applied to a FlatDatasourceOutput.
+func (*FlatDatasourceOutput) HCL2Spec() map[string]hcldec.Spec {
+ s := map[string]hcldec.Spec{
+ "author_id": &hcldec.AttrSpec{Name: "author_id", Type: cty.String, Required: false},
+ "bucket_name": &hcldec.AttrSpec{Name: "bucket_name", Type: cty.String, Required: false},
+ "complete": &hcldec.AttrSpec{Name: "complete", Type: cty.Bool, Required: false},
+ "created_at": &hcldec.AttrSpec{Name: "created_at", Type: cty.String, Required: false},
+ "fingerprint": &hcldec.AttrSpec{Name: "fingerprint", Type: cty.String, Required: false},
+ "id": &hcldec.AttrSpec{Name: "id", Type: cty.String, Required: false},
+ "incremental_version": &hcldec.AttrSpec{Name: "incremental_version", Type: cty.Number, Required: false},
+ "updated_at": &hcldec.AttrSpec{Name: "updated_at", Type: cty.String, Required: false},
+ "channel_id": &hcldec.AttrSpec{Name: "channel_id", Type: cty.String, Required: false},
+ }
+ return s
+}
diff --git a/v1.9.4/datasource/hcp-packer-iteration/data_acc_test.go b/v1.9.4/datasource/hcp-packer-iteration/data_acc_test.go
new file mode 100644
index 0000000..bf91e87
--- /dev/null
+++ b/v1.9.4/datasource/hcp-packer-iteration/data_acc_test.go
@@ -0,0 +1,53 @@
+// Copyright (c) HashiCorp, Inc.
+// SPDX-License-Identifier: MPL-2.0
+
+package hcp_packer_iteration
+
+import (
+ _ "embed"
+ "fmt"
+ "os"
+ "os/exec"
+ "testing"
+
+ "github.com/hashicorp/packer-plugin-sdk/acctest"
+ "github.com/hashicorp/packer/internal/hcp/env"
+)
+
+//go:embed test-fixtures/template.pkr.hcl
+var testDatasourceBasic string
+
+// Acceptance tests for data sources.
+//
+// To be successful, the HCP project you're providing credentials for must
+// contain a bucket named "hardened-ubuntu-16-04", with a channel named
+// "packer-acc-test". It must contain a build that references an image in AWS
+// region "us-east-1". Your HCP credentials must be provided through your
+// runtime environment because the template this test uses does not set them.
+//
+// TODO: update this acceptance to create and clean up the HCP resources this
+// data source queries, to prevent plugin developers from having to have images
+// as defined above.
+
+func TestAccDatasource_HCPPackerIteration(t *testing.T) {
+ if os.Getenv(env.HCPClientID) == "" && os.Getenv(env.HCPClientSecret) == "" {
+ t.Skipf(fmt.Sprintf("Acceptance tests skipped unless envs %q and %q are set", env.HCPClientID, env.HCPClientSecret))
+ return
+ }
+
+ testCase := &acctest.PluginTestCase{
+ Name: "hcp_packer_iteration_datasource_basic_test",
+ Template: testDatasourceBasic,
+ // TODO have acc test write iteration id to a file and check it to make
+ // sure it isn't empty.
+ 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)
+ }
+ }
+ return nil
+ },
+ }
+ acctest.TestPlugin(t, testCase)
+}
diff --git a/v1.9.4/datasource/hcp-packer-iteration/test-fixtures/template.pkr.hcl b/v1.9.4/datasource/hcp-packer-iteration/test-fixtures/template.pkr.hcl
new file mode 100644
index 0000000..52bac83
--- /dev/null
+++ b/v1.9.4/datasource/hcp-packer-iteration/test-fixtures/template.pkr.hcl
@@ -0,0 +1,33 @@
+source "null" "example" {
+ communicator = "none"
+}
+
+data "hcp-packer-iteration" "hardened-source" {
+ bucket_name = "hardened-ubuntu-16-04"
+ channel = "packer-acc-test"
+}
+
+data "hcp-packer-image" "aws" {
+ bucket_name = "hardened-ubuntu-16-04"
+ iteration_id = "${data.hcp-packer-iteration.hardened-source.id}"
+ cloud_provider = "aws"
+ region = "us-east-1"
+}
+
+locals {
+ foo = "${data.hcp-packer-iteration.hardened-source.id}"
+ bar = "${data.hcp-packer-image.aws.id}"
+}
+
+build {
+ name = "mybuild"
+ sources = [
+ "source.null.example"
+ ]
+ provisioner "shell-local" {
+ inline = [
+ "echo data is ${local.foo}",
+ "echo data is ${local.bar}"
+ ]
+ }
+}
diff --git a/v1.9.4/datasource/http/data.go b/v1.9.4/datasource/http/data.go
new file mode 100644
index 0000000..ec7a1b3
--- /dev/null
+++ b/v1.9.4/datasource/http/data.go
@@ -0,0 +1,160 @@
+// Copyright (c) HashiCorp, Inc.
+// SPDX-License-Identifier: MPL-2.0
+
+//go:generate packer-sdc struct-markdown
+//go:generate packer-sdc mapstructure-to-hcl2 -type DatasourceOutput,Config
+package http
+
+import (
+ "context"
+ "fmt"
+ "io/ioutil"
+ "mime"
+ "net/http"
+ "regexp"
+ "strings"
+
+ "github.com/hashicorp/hcl/v2/hcldec"
+ "github.com/hashicorp/packer-plugin-sdk/common"
+ "github.com/hashicorp/packer-plugin-sdk/hcl2helper"
+ packersdk "github.com/hashicorp/packer-plugin-sdk/packer"
+ "github.com/hashicorp/packer-plugin-sdk/template/config"
+ "github.com/zclconf/go-cty/cty"
+)
+
+type Config struct {
+ common.PackerConfig `mapstructure:",squash"`
+ // The URL to request data from. This URL must respond with a `200 OK` response and a `text/*` or `application/json` Content-Type.
+ Url string `mapstructure:"url" required:"true"`
+ // A map of strings representing additional HTTP headers to include in the request.
+ RequestHeaders map[string]string `mapstructure:"request_headers" required:"false"`
+}
+
+type Datasource struct {
+ config Config
+}
+
+type DatasourceOutput struct {
+ // The URL the data was requested from.
+ Url string `mapstructure:"url"`
+ // The raw body of the HTTP response.
+ ResponseBody string `mapstructure:"body"`
+ // A map of strings representing the response HTTP headers.
+ // Duplicate headers are concatenated with, according to [RFC2616](https://www.w3.org/Protocols/rfc2616/rfc2616-sec4.html#sec4.2).
+ ResponseHeaders map[string]string `mapstructure:"request_headers"`
+}
+
+func (d *Datasource) ConfigSpec() hcldec.ObjectSpec {
+ return d.config.FlatMapstructure().HCL2Spec()
+}
+
+func (d *Datasource) Configure(raws ...interface{}) error {
+ err := config.Decode(&d.config, nil, raws...)
+ if err != nil {
+ return err
+ }
+
+ var errs *packersdk.MultiError
+
+ if d.config.Url == "" {
+ errs = packersdk.MultiErrorAppend(
+ errs,
+ fmt.Errorf("the `url` must be specified"))
+ }
+
+ if errs != nil && len(errs.Errors) > 0 {
+ return errs
+ }
+ return nil
+}
+
+func (d *Datasource) OutputSpec() hcldec.ObjectSpec {
+ return (&DatasourceOutput{}).FlatMapstructure().HCL2Spec()
+}
+
+// This is to prevent potential issues w/ binary files
+// and generally unprintable characters
+// See https://github.com/hashicorp/terraform/pull/3858#issuecomment-156856738
+func isContentTypeText(contentType string) bool {
+
+ parsedType, params, err := mime.ParseMediaType(contentType)
+ if err != nil {
+ return false
+ }
+
+ allowedContentTypes := []*regexp.Regexp{
+ regexp.MustCompile("^text/.+"),
+ regexp.MustCompile("^application/json$"),
+ regexp.MustCompile("^application/samlmetadata\\+xml"),
+ }
+
+ for _, r := range allowedContentTypes {
+ if r.MatchString(parsedType) {
+ charset := strings.ToLower(params["charset"])
+ return charset == "" || charset == "utf-8" || charset == "us-ascii"
+ }
+ }
+
+ return false
+}
+
+// Most of this code comes from http terraform provider data source
+// https://github.com/hashicorp/terraform-provider-http/blob/main/internal/provider/data_source.go
+func (d *Datasource) Execute() (cty.Value, error) {
+ ctx := context.TODO()
+ url, headers := d.config.Url, d.config.RequestHeaders
+ client := &http.Client{}
+
+ req, err := http.NewRequestWithContext(ctx, "GET", url, nil)
+ // TODO: How to make a test case for this?
+ if err != nil {
+ fmt.Println("Error creating http request")
+ return cty.NullVal(cty.EmptyObject), err
+ }
+
+ for name, value := range headers {
+ req.Header.Set(name, value)
+ }
+
+ resp, err := client.Do(req)
+ // TODO: How to make test case for this
+ if err != nil {
+ fmt.Println("Error making performing http request")
+ return cty.NullVal(cty.EmptyObject), err
+ }
+
+ defer resp.Body.Close()
+
+ if resp.StatusCode != 200 {
+ return cty.NullVal(cty.EmptyObject), fmt.Errorf("HTTP request error. Response code: %d", resp.StatusCode)
+ }
+
+ contentType := resp.Header.Get("Content-Type")
+ if contentType == "" || isContentTypeText(contentType) == false {
+ fmt.Println(fmt.Sprintf(
+ "Content-Type is not recognized as a text type, got %q",
+ contentType))
+ fmt.Println("If the content is binary data, Packer may not properly handle the contents of the response.")
+ }
+
+ bytes, err := ioutil.ReadAll(resp.Body)
+ // TODO: How to make test case for this?
+ if err != nil {
+ fmt.Println("Error processing response body of call")
+ return cty.NullVal(cty.EmptyObject), err
+ }
+
+ responseHeaders := make(map[string]string)
+ for k, v := range resp.Header {
+ // Concatenate according to RFC2616
+ // cf. https://www.w3.org/Protocols/rfc2616/rfc2616-sec4.html#sec4.2
+ responseHeaders[k] = strings.Join(v, ", ")
+ }
+
+ output := DatasourceOutput{
+ Url: d.config.Url,
+ ResponseHeaders: responseHeaders,
+ ResponseBody: string(bytes),
+ }
+ return hcl2helper.HCL2ValueFromConfig(output, d.OutputSpec()), nil
+}
diff --git a/v1.9.4/datasource/http/data.hcl2spec.go b/v1.9.4/datasource/http/data.hcl2spec.go
new file mode 100644
index 0000000..fb9bfc6
--- /dev/null
+++ b/v1.9.4/datasource/http/data.hcl2spec.go
@@ -0,0 +1,76 @@
+// Code generated by "packer-sdc mapstructure-to-hcl2"; DO NOT EDIT.
+
+package http
+
+import (
+ "github.com/hashicorp/hcl/v2/hcldec"
+ "github.com/zclconf/go-cty/cty"
+)
+
+// FlatConfig is an auto-generated flat version of Config.
+// Where the contents of a field with a `mapstructure:,squash` tag are bubbled up.
+type FlatConfig struct {
+ PackerBuildName *string `mapstructure:"packer_build_name" cty:"packer_build_name" 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"`
+ Url *string `mapstructure:"url" required:"true" cty:"url" hcl:"url"`
+ RequestHeaders map[string]string `mapstructure:"request_headers" required:"false" cty:"request_headers" hcl:"request_headers"`
+}
+
+// FlatMapstructure returns a new FlatConfig.
+// FlatConfig is an auto-generated flat version of Config.
+// Where the contents a fields with a `mapstructure:,squash` tag are bubbled up.
+func (*Config) FlatMapstructure() interface{ HCL2Spec() map[string]hcldec.Spec } {
+ return new(FlatConfig)
+}
+
+// HCL2Spec returns the hcl spec of a Config.
+// This spec is used by HCL to read the fields of Config.
+// The decoded values from this spec will then be applied to a FlatConfig.
+func (*FlatConfig) HCL2Spec() map[string]hcldec.Spec {
+ s := map[string]hcldec.Spec{
+ "packer_build_name": &hcldec.AttrSpec{Name: "packer_build_name", Type: cty.String, Required: false},
+ "packer_builder_type": &hcldec.AttrSpec{Name: "packer_builder_type", Type: cty.String, Required: false},
+ "packer_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_sensitive_variables": &hcldec.AttrSpec{Name: "packer_sensitive_variables", Type: cty.List(cty.String), Required: false},
+ "url": &hcldec.AttrSpec{Name: "url", Type: cty.String, Required: false},
+ "request_headers": &hcldec.AttrSpec{Name: "request_headers", Type: cty.Map(cty.String), Required: false},
+ }
+ return s
+}
+
+// FlatDatasourceOutput is an auto-generated flat version of DatasourceOutput.
+// Where the contents of a field with a `mapstructure:,squash` tag are bubbled up.
+type FlatDatasourceOutput struct {
+ Url *string `mapstructure:"url" cty:"url" hcl:"url"`
+ ResponseBody *string `mapstructure:"body" cty:"body" hcl:"body"`
+ ResponseHeaders map[string]string `mapstructure:"request_headers" cty:"request_headers" hcl:"request_headers"`
+}
+
+// FlatMapstructure returns a new FlatDatasourceOutput.
+// FlatDatasourceOutput is an auto-generated flat version of DatasourceOutput.
+// Where the contents a fields with a `mapstructure:,squash` tag are bubbled up.
+func (*DatasourceOutput) FlatMapstructure() interface{ HCL2Spec() map[string]hcldec.Spec } {
+ return new(FlatDatasourceOutput)
+}
+
+// HCL2Spec returns the hcl spec of a DatasourceOutput.
+// This spec is used by HCL to read the fields of DatasourceOutput.
+// The decoded values from this spec will then be applied to a FlatDatasourceOutput.
+func (*FlatDatasourceOutput) HCL2Spec() map[string]hcldec.Spec {
+ s := map[string]hcldec.Spec{
+ "url": &hcldec.AttrSpec{Name: "url", Type: cty.String, Required: false},
+ "body": &hcldec.AttrSpec{Name: "body", Type: cty.String, Required: false},
+ "request_headers": &hcldec.AttrSpec{Name: "request_headers", Type: cty.Map(cty.String), Required: false},
+ }
+ return s
+}
diff --git a/v1.9.4/datasource/http/data_acc_test.go b/v1.9.4/datasource/http/data_acc_test.go
new file mode 100644
index 0000000..ffad021
--- /dev/null
+++ b/v1.9.4/datasource/http/data_acc_test.go
@@ -0,0 +1,112 @@
+// Copyright (c) HashiCorp, Inc.
+// SPDX-License-Identifier: MPL-2.0
+
+package http
+
+import (
+ _ "embed"
+ "fmt"
+ "io/ioutil"
+ "os"
+ "os/exec"
+ "regexp"
+ "testing"
+
+ "github.com/hashicorp/packer-plugin-sdk/acctest"
+)
+
+//go:embed test-fixtures/basic.pkr.hcl
+var testDatasourceBasic string
+
+//go:embed test-fixtures/empty_url.pkr.hcl
+var testDatasourceEmptyUrl string
+
+//go:embed test-fixtures/404_url.pkr.hcl
+var testDatasource404Url string
+
+func TestHttpDataSource(t *testing.T) {
+ tests := []struct {
+ Name string
+ Path string
+ Error bool
+ Outputs map[string]string
+ }{
+ {
+ Name: "basic_test",
+ Path: testDatasourceBasic,
+ Error: false,
+ Outputs: map[string]string{
+ "url": "url is https://www.packer.io/",
+ // Check that body is not empty
+ "body": "body is true",
+ },
+ },
+ {
+ Name: "url_is_empty",
+ Path: testDatasourceEmptyUrl,
+ Error: true,
+ Outputs: map[string]string{
+ "error": "the `url` must be specified",
+ },
+ },
+ {
+ Name: "404_url",
+ Path: testDatasource404Url,
+ Error: true,
+ },
+ }
+ for _, tt := range tests {
+ t.Run(tt.Name, func(t *testing.T) {
+ testCase := &acctest.PluginTestCase{
+ Name: tt.Name,
+ Setup: func() error {
+ return nil
+ },
+ Teardown: func() error {
+ return nil
+ },
+ Template: tt.Path,
+ Type: "http",
+ Check: func(buildCommand *exec.Cmd, logfile string) error {
+ if buildCommand.ProcessState != nil {
+ if buildCommand.ProcessState.ExitCode() != 0 && !tt.Error {
+ return fmt.Errorf("Bad exit code. Logfile: %s", logfile)
+ }
+ if tt.Error && buildCommand.ProcessState.ExitCode() == 0 {
+ return fmt.Errorf("Expected Bad exit code.")
+ }
+ }
+
+ if tt.Outputs != nil {
+ logs, err := os.Open(logfile)
+ if err != nil {
+ return fmt.Errorf("Unable find %s", logfile)
+ }
+ defer logs.Close()
+
+ logsBytes, err := ioutil.ReadAll(logs)
+ if err != nil {
+ return fmt.Errorf("Unable to read %s", logfile)
+ }
+ logsString := string(logsBytes)
+
+ for key, val := range tt.Outputs {
+ if matched, _ := regexp.MatchString(val+".*", logsString); !matched {
+ t.Fatalf(
+ "logs doesn't contain expected log %v with value %v in %q",
+ key,
+ val,
+ logsString)
+ }
+ }
+
+ }
+
+ return nil
+ },
+ }
+ acctest.TestPlugin(t, testCase)
+ })
+ }
+
+}
diff --git a/v1.9.4/datasource/http/test-fixtures/404_url.pkr.hcl b/v1.9.4/datasource/http/test-fixtures/404_url.pkr.hcl
new file mode 100644
index 0000000..398af37
--- /dev/null
+++ b/v1.9.4/datasource/http/test-fixtures/404_url.pkr.hcl
@@ -0,0 +1,24 @@
+
+source "null" "example" {
+ communicator = "none"
+}
+
+data "http" "basic" {
+ url = "https://www.packer.io/thisWillFail"
+}
+
+locals {
+ url = "${data.http.basic.url}"
+}
+
+build {
+ name = "mybuild"
+ sources = [
+ "source.null.example"
+ ]
+ provisioner "shell-local" {
+ inline = [
+ "echo data is ${local.url}",
+ ]
+ }
+}
diff --git a/v1.9.4/datasource/http/test-fixtures/basic.pkr.hcl b/v1.9.4/datasource/http/test-fixtures/basic.pkr.hcl
new file mode 100644
index 0000000..1e7e4a4
--- /dev/null
+++ b/v1.9.4/datasource/http/test-fixtures/basic.pkr.hcl
@@ -0,0 +1,25 @@
+source "null" "example" {
+ communicator = "none"
+}
+
+data "http" "basic" {
+ url = "https://www.packer.io/"
+}
+
+locals {
+ url = "${data.http.basic.url}"
+ body = "${data.http.basic.body}" != ""
+}
+
+build {
+ name = "mybuild"
+ sources = [
+ "source.null.example"
+ ]
+ provisioner "shell-local" {
+ inline = [
+ "echo url is ${local.url}",
+ "echo body is ${local.body}"
+ ]
+ }
+}
diff --git a/v1.9.4/datasource/http/test-fixtures/empty_url.pkr.hcl b/v1.9.4/datasource/http/test-fixtures/empty_url.pkr.hcl
new file mode 100644
index 0000000..7810218
--- /dev/null
+++ b/v1.9.4/datasource/http/test-fixtures/empty_url.pkr.hcl
@@ -0,0 +1,23 @@
+source "null" "example" {
+ communicator = "none"
+}
+
+data "http" "basic" {
+ url = ""
+}
+
+locals {
+ url = "${data.http.basic.url}"
+}
+
+build {
+ name = "mybuild"
+ sources = [
+ "source.null.example"
+ ]
+ provisioner "shell-local" {
+ inline = [
+ "echo data is ${local.url}",
+ ]
+ }
+}
diff --git a/v1.9.4/datasource/null/data.go b/v1.9.4/datasource/null/data.go
new file mode 100644
index 0000000..308e062
--- /dev/null
+++ b/v1.9.4/datasource/null/data.go
@@ -0,0 +1,71 @@
+// Copyright (c) HashiCorp, Inc.
+// SPDX-License-Identifier: MPL-2.0
+
+//go:generate packer-sdc struct-markdown
+//go:generate packer-sdc mapstructure-to-hcl2 -type DatasourceOutput,Config
+package null
+
+import (
+ "fmt"
+
+ "github.com/zclconf/go-cty/cty"
+
+ "github.com/hashicorp/hcl/v2/hcldec"
+ "github.com/hashicorp/packer-plugin-sdk/common"
+ "github.com/hashicorp/packer-plugin-sdk/hcl2helper"
+ packersdk "github.com/hashicorp/packer-plugin-sdk/packer"
+ "github.com/hashicorp/packer-plugin-sdk/template/config"
+)
+
+type Datasource struct {
+ config Config
+}
+
+// The Null data source is designed to demonstrate how data sources work, and
+// to provide a test plugin. It does not do anything useful; you assign an
+// input string and it gets returned as an output string.
+type Config struct {
+ common.PackerConfig `mapstructure:",squash"`
+ // This variable will get stored as "output" in the output spec.
+ Input string `mapstructure:"input" required:"true"`
+}
+
+func (d *Datasource) ConfigSpec() hcldec.ObjectSpec {
+ return d.config.FlatMapstructure().HCL2Spec()
+}
+
+func (d *Datasource) Configure(raws ...interface{}) error {
+ err := config.Decode(&d.config, nil, raws...)
+ if err != nil {
+ return err
+ }
+
+ var errs *packersdk.MultiError
+
+ if d.config.Input == "" {
+ errs = packersdk.MultiErrorAppend(errs, fmt.Errorf("The `input` must be specified"))
+ }
+
+ if errs != nil && len(errs.Errors) > 0 {
+ return errs
+ }
+ return nil
+}
+
+type DatasourceOutput struct {
+ // Output will return the input variable, as output.
+ Output string `mapstructure:"output"`
+}
+
+func (d *Datasource) OutputSpec() hcldec.ObjectSpec {
+ return (&DatasourceOutput{}).FlatMapstructure().HCL2Spec()
+}
+
+func (d *Datasource) Execute() (cty.Value, error) {
+ // Pass input variable through to output.
+ output := DatasourceOutput{
+ Output: d.config.Input,
+ }
+
+ return hcl2helper.HCL2ValueFromConfig(output, d.OutputSpec()), nil
+}
diff --git a/v1.9.4/datasource/null/data.hcl2spec.go b/v1.9.4/datasource/null/data.hcl2spec.go
new file mode 100644
index 0000000..00c113c
--- /dev/null
+++ b/v1.9.4/datasource/null/data.hcl2spec.go
@@ -0,0 +1,70 @@
+// Code generated by "packer-sdc mapstructure-to-hcl2"; DO NOT EDIT.
+
+package null
+
+import (
+ "github.com/hashicorp/hcl/v2/hcldec"
+ "github.com/zclconf/go-cty/cty"
+)
+
+// FlatConfig is an auto-generated flat version of Config.
+// Where the contents of a field with a `mapstructure:,squash` tag are bubbled up.
+type FlatConfig struct {
+ PackerBuildName *string `mapstructure:"packer_build_name" cty:"packer_build_name" 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"`
+ Input *string `mapstructure:"input" required:"true" cty:"input" hcl:"input"`
+}
+
+// FlatMapstructure returns a new FlatConfig.
+// FlatConfig is an auto-generated flat version of Config.
+// Where the contents a fields with a `mapstructure:,squash` tag are bubbled up.
+func (*Config) FlatMapstructure() interface{ HCL2Spec() map[string]hcldec.Spec } {
+ return new(FlatConfig)
+}
+
+// HCL2Spec returns the hcl spec of a Config.
+// This spec is used by HCL to read the fields of Config.
+// The decoded values from this spec will then be applied to a FlatConfig.
+func (*FlatConfig) HCL2Spec() map[string]hcldec.Spec {
+ s := map[string]hcldec.Spec{
+ "packer_build_name": &hcldec.AttrSpec{Name: "packer_build_name", Type: cty.String, Required: false},
+ "packer_builder_type": &hcldec.AttrSpec{Name: "packer_builder_type", Type: cty.String, Required: false},
+ "packer_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_sensitive_variables": &hcldec.AttrSpec{Name: "packer_sensitive_variables", Type: cty.List(cty.String), Required: false},
+ "input": &hcldec.AttrSpec{Name: "input", Type: cty.String, Required: false},
+ }
+ return s
+}
+
+// FlatDatasourceOutput is an auto-generated flat version of DatasourceOutput.
+// Where the contents of a field with a `mapstructure:,squash` tag are bubbled up.
+type FlatDatasourceOutput struct {
+ Output *string `mapstructure:"output" cty:"output" hcl:"output"`
+}
+
+// FlatMapstructure returns a new FlatDatasourceOutput.
+// FlatDatasourceOutput is an auto-generated flat version of DatasourceOutput.
+// Where the contents a fields with a `mapstructure:,squash` tag are bubbled up.
+func (*DatasourceOutput) FlatMapstructure() interface{ HCL2Spec() map[string]hcldec.Spec } {
+ return new(FlatDatasourceOutput)
+}
+
+// HCL2Spec returns the hcl spec of a DatasourceOutput.
+// This spec is used by HCL to read the fields of DatasourceOutput.
+// The decoded values from this spec will then be applied to a FlatDatasourceOutput.
+func (*FlatDatasourceOutput) HCL2Spec() map[string]hcldec.Spec {
+ s := map[string]hcldec.Spec{
+ "output": &hcldec.AttrSpec{Name: "output", Type: cty.String, Required: false},
+ }
+ return s
+}
diff --git a/v1.9.4/examples/_common/minimize.sh b/v1.9.4/examples/_common/minimize.sh
new file mode 100644
index 0000000..0173b42
--- /dev/null
+++ b/v1.9.4/examples/_common/minimize.sh
@@ -0,0 +1,36 @@
+#!/bin/sh -eux
+
+case "$PACKER_BUILDER_TYPE" in
+ qemu) exit 0 ;;
+esac
+
+# Whiteout root
+count=$(df --sync -kP / | tail -n1 | awk -F ' ' '{print $4}')
+count=$(($count-1))
+dd if=/dev/zero of=/tmp/whitespace bs=1M count=$count || echo "dd exit code $? is suppressed";
+rm /tmp/whitespace
+
+# Whiteout /boot
+count=$(df --sync -kP /boot | tail -n1 | awk -F ' ' '{print $4}')
+count=$(($count-1))
+dd if=/dev/zero of=/boot/whitespace bs=1M count=$count || echo "dd exit code $? is suppressed";
+rm /boot/whitespace
+
+set +e
+swapuuid="`/sbin/blkid -o value -l -s UUID -t TYPE=swap`";
+case "$?" in
+ 2|0) ;;
+ *) exit 1 ;;
+esac
+set -e
+
+if [ "x${swapuuid}" != "x" ]; then
+ # Whiteout the swap partition to reduce box size
+ # Swap is disabled till reboot
+ swappart="`readlink -f /dev/disk/by-uuid/$swapuuid`";
+ /sbin/swapoff "$swappart";
+ dd if=/dev/zero of="$swappart" bs=1M || echo "dd exit code $? is suppressed";
+ /sbin/mkswap -U "$swapuuid" "$swappart";
+fi
+
+sync;
diff --git a/v1.9.4/examples/_common/parallels.sh b/v1.9.4/examples/_common/parallels.sh
new file mode 100644
index 0000000..1b2a689
--- /dev/null
+++ b/v1.9.4/examples/_common/parallels.sh
@@ -0,0 +1,35 @@
+#!/bin/sh -eux
+
+# set a default HOME_DIR environment variable if not set
+HOME_DIR="${HOME_DIR:-/home/vagrant}";
+
+case "$PACKER_BUILDER_TYPE" in
+parallels-iso|parallels-pvm)
+ mkdir -p /tmp/parallels;
+ mount -o loop $HOME_DIR/prl-tools-lin.iso /tmp/parallels;
+ VER="`cat /tmp/parallels/version`";
+
+ echo "Parallels Tools Version: $VER";
+
+ /tmp/parallels/install --install-unattended-with-deps \
+ || (code="$?"; \
+ echo "Parallels tools installation exited $code, attempting" \
+ "to output /var/log/parallels-tools-install.log"; \
+ cat /var/log/parallels-tools-install.log; \
+ exit $code);
+ umount /tmp/parallels;
+ rm -rf /tmp/parallels;
+ rm -f $HOME_DIR/*.iso;
+
+ # Parallels Tools for Linux includes native auto-mount script,
+ # which causes losing some of Vagrant-relative shared folders.
+ # So, we should disable this behavior.
+ # https://github.com/Parallels/vagrant-parallels/issues/325#issuecomment-418727113
+ auto_mount_script='/usr/bin/prlfsmountd'
+ if [ -f "${auto_mount_script}" ]; then
+ echo -e '#!/bin/sh\n'\
+ '# Shared folders auto-mount is disabled by Vagrant ' \
+ > "${auto_mount_script}"
+ fi
+ ;;
+esac
diff --git a/v1.9.4/examples/_common/sshd.sh b/v1.9.4/examples/_common/sshd.sh
new file mode 100644
index 0000000..1bb16f5
--- /dev/null
+++ b/v1.9.4/examples/_common/sshd.sh
@@ -0,0 +1,20 @@
+#!/bin/sh -eux
+
+SSHD_CONFIG="/etc/ssh/sshd_config"
+
+# ensure that there is a trailing newline before attempting to concatenate
+sed -i -e '$a\' "$SSHD_CONFIG"
+
+USEDNS="UseDNS no"
+if grep -q -E "^[[:space:]]*UseDNS" "$SSHD_CONFIG"; then
+ sed -i "s/^\s*UseDNS.*/${USEDNS}/" "$SSHD_CONFIG"
+else
+ echo "$USEDNS" >>"$SSHD_CONFIG"
+fi
+
+GSSAPI="GSSAPIAuthentication no"
+if grep -q -E "^[[:space:]]*GSSAPIAuthentication" "$SSHD_CONFIG"; then
+ sed -i "s/^\s*GSSAPIAuthentication.*/${GSSAPI}/" "$SSHD_CONFIG"
+else
+ echo "$GSSAPI" >>"$SSHD_CONFIG"
+fi
diff --git a/v1.9.4/examples/_common/vagrant.sh b/v1.9.4/examples/_common/vagrant.sh
new file mode 100644
index 0000000..c2a14bb
--- /dev/null
+++ b/v1.9.4/examples/_common/vagrant.sh
@@ -0,0 +1,19 @@
+#!/bin/sh -eux
+
+# set a default HOME_DIR environment variable if not set
+HOME_DIR="${HOME_DIR:-/home/vagrant}";
+
+pubkey_url="https://raw.githubusercontent.com/hashicorp/vagrant/master/keys/vagrant.pub";
+mkdir -p $HOME_DIR/.ssh;
+if command -v wget >/dev/null 2>&1; then
+ wget --no-check-certificate "$pubkey_url" -O $HOME_DIR/.ssh/authorized_keys;
+elif command -v curl >/dev/null 2>&1; then
+ curl --insecure --location "$pubkey_url" > $HOME_DIR/.ssh/authorized_keys;
+elif command -v fetch >/dev/null 2>&1; then
+ fetch -am -o $HOME_DIR/.ssh/authorized_keys "$pubkey_url";
+else
+ echo "Cannot download vagrant public key";
+ exit 1;
+fi
+chown -R vagrant $HOME_DIR/.ssh;
+chmod -R go-rwsx $HOME_DIR/.ssh;
diff --git a/v1.9.4/examples/_common/virtualbox.sh b/v1.9.4/examples/_common/virtualbox.sh
new file mode 100644
index 0000000..c1e3409
--- /dev/null
+++ b/v1.9.4/examples/_common/virtualbox.sh
@@ -0,0 +1,19 @@
+#!/bin/sh -eux
+
+# set a default HOME_DIR environment variable if not set
+HOME_DIR="${HOME_DIR:-/home/vagrant}";
+
+case "$PACKER_BUILDER_TYPE" in
+virtualbox-iso|virtualbox-ovf)
+ VER="`cat $HOME_DIR/.vbox_version`";
+ ISO="VBoxGuestAdditions_$VER.iso";
+ mkdir -p /tmp/vbox;
+ mount -o loop $HOME_DIR/$ISO /tmp/vbox;
+ sh /tmp/vbox/VBoxLinuxAdditions.run \
+ || echo "VBoxLinuxAdditions.run exited $? and is suppressed." \
+ "For more read https://www.virtualbox.org/ticket/12479";
+ umount /tmp/vbox;
+ rm -rf /tmp/vbox;
+ rm -f $HOME_DIR/*.iso;
+ ;;
+esac
diff --git a/v1.9.4/examples/_common/vmware.sh b/v1.9.4/examples/_common/vmware.sh
new file mode 100644
index 0000000..ae1d874
--- /dev/null
+++ b/v1.9.4/examples/_common/vmware.sh
@@ -0,0 +1,34 @@
+#!/bin/sh -eux
+
+# set a default HOME_DIR environment variable if not set
+HOME_DIR="${HOME_DIR:-/home/vagrant}";
+
+case "$PACKER_BUILDER_TYPE" in
+vmware-iso|vmware-vmx)
+
+ # make sure we have /sbin in our path. RHEL systems lack this
+ PATH=/sbin:$PATH
+ export PATH
+
+ mkdir -p /tmp/vmware;
+ mkdir -p /tmp/vmware-archive;
+ mount -o loop $HOME_DIR/linux.iso /tmp/vmware;
+
+ TOOLS_PATH="`ls /tmp/vmware/VMwareTools-*.tar.gz`";
+ VER="`echo "${TOOLS_PATH}" | cut -f2 -d'-'`";
+ MAJ_VER="`echo ${VER} | cut -d '.' -f 1`";
+
+ echo "VMware Tools Version: $VER";
+
+ tar xzf ${TOOLS_PATH} -C /tmp/vmware-archive;
+ if [ "${MAJ_VER}" -lt "10" ]; then
+ /tmp/vmware-archive/vmware-tools-distrib/vmware-install.pl --default;
+ else
+ /tmp/vmware-archive/vmware-tools-distrib/vmware-install.pl --force-install;
+ fi
+ umount /tmp/vmware;
+ rm -rf /tmp/vmware;
+ rm -rf /tmp/vmware-archive;
+ rm -f $HOME_DIR/*.iso;
+ ;;
+esac
diff --git a/v1.9.4/examples/hcl/linux/README.md b/v1.9.4/examples/hcl/linux/README.md
new file mode 100644
index 0000000..ca0b06f
--- /dev/null
+++ b/v1.9.4/examples/hcl/linux/README.md
@@ -0,0 +1,6 @@
+# Basic HCL2 Ubuntu builders
+
+Taking the [chef/bento](https://github.com/chef/bento) repo as an example.
+
+I recommend you start by reading the build.pkr.hcl file and the
+comments/description there.
diff --git a/v1.9.4/examples/hcl/linux/build.alpine.pkr.hcl b/v1.9.4/examples/hcl/linux/build.alpine.pkr.hcl
new file mode 100644
index 0000000..06f4a86
--- /dev/null
+++ b/v1.9.4/examples/hcl/linux/build.alpine.pkr.hcl
@@ -0,0 +1,42 @@
+
+build {
+ name = "alpine"
+ description = <<EOF
+This build creates alpine images for versions :
+* v3.12
+For the following builders :
+* virtualbox-iso
+EOF
+
+ // the common fields of the source blocks are defined in the
+ // source.builder-type.pkr.hcl files, here we only set the fields specific to
+ // the different versions of ubuntu.
+ source "source.virtualbox-iso.base-alpine-amd64" {
+ name = "3.12"
+ iso_url = local.iso_url_alpine_312
+ iso_checksum = "file:${local.iso_checksum_url_alpine_312}"
+ output_directory = "virtualbox_iso_alpine_312_amd64"
+ boot_command = local.alpine_312_floppy_boot_command
+ boot_wait = "10s"
+ }
+
+ source "source.vsphere-iso.base-alpine-amd64" {
+ name = "3.12"
+ vm_name = "alpine-3.12"
+ iso_url = local.iso_url_alpine_312
+ iso_checksum = "file:${local.iso_checksum_url_alpine_312}"
+ boot_command = local.alpine_312_floppy_boot_command_vsphere
+ boot_wait = "10s"
+ }
+
+ source "source.vmware-iso.esxi-base-alpine-amd64" {
+ name = "3.12-from-esxi"
+ iso_url = local.iso_url_alpine_312
+ iso_checksum = "file:${local.iso_checksum_url_alpine_312}"
+ boot_command = local.alpine_312_floppy_boot_command_vsphere
+ }
+
+ provisioner "shell" {
+ inline = ["echo hi"]
+ }
+}
diff --git a/v1.9.4/examples/hcl/linux/build.ubuntu.pkr.hcl b/v1.9.4/examples/hcl/linux/build.ubuntu.pkr.hcl
new file mode 100644
index 0000000..d1f7f83
--- /dev/null
+++ b/v1.9.4/examples/hcl/linux/build.ubuntu.pkr.hcl
@@ -0,0 +1,112 @@
+
+build {
+ name = "ubuntu"
+ description = <<EOF
+This build creates ubuntu images for ubuntu versions :
+* 16.04
+* 18.04
+For the following builders :
+* virtualbox-iso
+* parallels-iso
+* vmware-iso
+* qemu
+* vsphere-iso
+EOF
+
+ // the common fields of the source blocks are defined in the
+ // source.builder-type.pkr.hcl files, here we only set the fields specific to
+ // the different versions of ubuntu.
+ source "source.virtualbox-iso.base-ubuntu-amd64" {
+ name = "16.04"
+ iso_url = local.iso_url_ubuntu_1604
+ iso_checksum = "file:${local.iso_checksum_url_ubuntu_1604}"
+ output_directory = "virtualbox_iso_ubuntu_1604_amd64"
+ boot_command = local.ubuntu_1604_boot_command
+ boot_wait = "10s"
+ }
+
+ source "source.virtualbox-iso.base-ubuntu-amd64" {
+ name = "18.04"
+ iso_url = local.iso_url_ubuntu_1804
+ iso_checksum = "file:${local.iso_checksum_url_ubuntu_1804}"
+ output_directory = "virtualbox_iso_ubuntu_1804_amd64"
+ boot_command = local.ubuntu_1804_boot_command
+ boot_wait = "5s"
+ }
+
+ source "source.parallels-iso.base-ubuntu-amd64" {
+ name = "16.04"
+ iso_url = local.iso_url_ubuntu_1604
+ iso_checksum = "file:${local.iso_checksum_url_ubuntu_1604}"
+ output_directory = "parallels_iso_ubuntu_1604_amd64"
+ boot_command = local.ubuntu_1604_boot_command
+ }
+
+ source "source.parallels-iso.base-ubuntu-amd64" {
+ name = "18.04"
+ iso_url = local.iso_url_ubuntu_1804
+ iso_checksum = "file:${local.iso_checksum_url_ubuntu_1804}"
+ output_directory = "parallels_iso_ubuntu_1804_amd64"
+ boot_command = local.ubuntu_1804_boot_command
+ }
+
+ source "source.vmware-iso.base-ubuntu-amd64" {
+ name = "16.04"
+ iso_url = local.iso_url_ubuntu_1604
+ iso_checksum = "file:${local.iso_checksum_url_ubuntu_1604}"
+ output_directory = "vmware_iso_ubuntu_1604_amd64"
+ boot_command = local.ubuntu_1604_boot_command
+ }
+
+ source "source.vmware-vmx.base-ubuntu-amd64" {
+ name = "16.04"
+ source_path = "vmware_iso_ubuntu_1604_amd64/packer-base-ubuntu-amd64.vmx"
+ }
+
+ source "source.vmware-iso.base-ubuntu-amd64" {
+ name = "18.04"
+ iso_url = local.iso_url_ubuntu_1804
+ iso_checksum = "file:${local.iso_checksum_url_ubuntu_1804}"
+ output_directory = "vmware_iso_ubuntu_1804_amd64"
+ boot_command = local.ubuntu_1804_boot_command
+ }
+
+ source "source.vmware-iso.esxi-base-ubuntu-amd64" {
+ name = "16.04-from-esxi"
+ iso_url = local.iso_url_ubuntu_1604
+ iso_checksum = "file:${local.iso_checksum_url_ubuntu_1604}"
+ output_directory = "vmware_iso_ubuntu_1604_amd64_from_esxi"
+ boot_command = local.ubuntu_1604_boot_command
+ }
+
+ source "source.qemu.base-ubuntu-amd64" {
+ name = "16.04"
+ iso_url = local.iso_url_ubuntu_1604
+ iso_checksum = "file:${local.iso_checksum_url_ubuntu_1604}"
+ output_directory = "qemu_iso_ubuntu_1604_amd64"
+ boot_command = local.ubuntu_1604_boot_command
+ }
+
+ source "source.qemu.base-ubuntu-amd64" {
+ name = "18.04"
+ iso_url = local.iso_url_ubuntu_1804
+ iso_checksum = "file:${local.iso_checksum_url_ubuntu_1804}"
+ output_directory = "qemu_iso_ubuntu_1804_amd64"
+ boot_command = local.ubuntu_1804_boot_command
+ }
+
+ source "source.vsphere-iso.base-ubuntu-amd64" {
+ name = "16.04"
+ vm_name = "ubuntu-16.04"
+ iso_url = local.iso_url_ubuntu_1604
+ iso_checksum = "file:${local.iso_checksum_url_ubuntu_1604}"
+ }
+
+ provisioner "shell" {
+ environment_vars = [ "HOME_DIR=/home/vagrant" ]
+ execute_command = "echo 'vagrant' | {{.Vars}} sudo -S -E sh -eux '{{.Path}}'"
+ expect_disconnect = true
+ // fileset will list files in etc/scripts sorted in an alphanumerical way.
+ scripts = fileset(".", "etc/scripts/*.sh")
+ }
+}
diff --git a/v1.9.4/examples/hcl/linux/etc/http/alpine-answers b/v1.9.4/examples/hcl/linux/etc/http/alpine-answers
new file mode 100644
index 0000000..529fa54
--- /dev/null
+++ b/v1.9.4/examples/hcl/linux/etc/http/alpine-answers
@@ -0,0 +1,15 @@
+KEYMAPOPTS="us us"
+HOSTNAMEOPTS="-n alpine"
+INTERFACESOPTS="auto lo
+iface lo inet loopback
+
+auto eth0
+iface eth0 inet dhcp
+ hostname alpine
+"
+TIMEZONEOPTS="-z UTC"
+PROXYOPTS="none"
+APKREPOSOPTS="http://mirrors.dotsrc.org/alpine/v3.8/main"
+SSHDOPTS="-c openssh"
+NTPOPTS="-c none"
+DISKOPTS="-m sys /dev/sda"
diff --git a/v1.9.4/examples/hcl/linux/etc/http/alpine-setup.sh b/v1.9.4/examples/hcl/linux/etc/http/alpine-setup.sh
new file mode 100644
index 0000000..6c26e30
--- /dev/null
+++ b/v1.9.4/examples/hcl/linux/etc/http/alpine-setup.sh
@@ -0,0 +1,21 @@
+#!/bin/sh
+
+set -ex
+
+apk add libressl
+apk add open-vm-tools
+rc-update add open-vm-tools
+/etc/init.d/open-vm-tools start
+
+cat >/usr/local/bin/shutdown <<EOF
+#!/bin/sh
+poweroff
+EOF
+chmod +x /usr/local/bin/shutdown
+
+sed -i "/#PermitRootLogin/c\PermitRootLogin yes" /etc/ssh/sshd_config
+sed -i "/#PasswordAuthentication/c\PasswordAuthentication yes" /etc/ssh/sshd_config
+mkdir ~/.ssh
+# copy ssy key ?
+
+/etc/init.d/sshd restart
diff --git a/v1.9.4/examples/hcl/linux/etc/http/alpine-vsphere-answers b/v1.9.4/examples/hcl/linux/etc/http/alpine-vsphere-answers
new file mode 100644
index 0000000..7afe5e4
--- /dev/null
+++ b/v1.9.4/examples/hcl/linux/etc/http/alpine-vsphere-answers
@@ -0,0 +1,22 @@
+KEYMAPOPTS="us us"
+HOSTNAMEOPTS="-n alpine"
+INTERFACESOPTS="auto lo
+iface lo inet loopback
+
+auto eth0
+iface eth0 inet static
+ address 147.75.201.6
+ netmask 255.255.255.248
+ network 147.75.201.0
+ broadcast 147.75.201.7
+ gateway 147.75.201.1
+"
+DNSOPTS="-d example.com 8.8.8.8"
+TIMEZONEOPTS="-z UTC"
+PROXYOPTS="none"
+APKREPOSOPTS="http://dl-cdn.alpinelinux.org/alpine/v3.12/main
+http://dl-cdn.alpinelinux.org/alpine/v3.8/main
+"
+SSHDOPTS="-c openssh"
+NTPOPTS="-c none"
+DISKOPTS="-m sys /dev/sda"
diff --git a/v1.9.4/examples/hcl/linux/etc/http/preseed.cfg b/v1.9.4/examples/hcl/linux/etc/http/preseed.cfg
new file mode 100644
index 0000000..5287ae0
--- /dev/null
+++ b/v1.9.4/examples/hcl/linux/etc/http/preseed.cfg
@@ -0,0 +1,35 @@
+choose-mirror-bin mirror/http/proxy string
+d-i base-installer/kernel/override-image string linux-server
+d-i clock-setup/utc boolean true
+d-i clock-setup/utc-auto boolean true
+d-i finish-install/reboot_in_progress note
+d-i grub-installer/only_debian boolean true
+d-i grub-installer/with_other_os boolean true
+d-i mirror/country string manual
+d-i mirror/http/directory string /ubuntu/
+d-i mirror/http/hostname string archive.ubuntu.com
+d-i mirror/http/proxy string
+d-i partman-auto-lvm/guided_size string max
+d-i partman-auto/choose_recipe select atomic
+d-i partman-auto/method string lvm
+d-i partman-lvm/confirm boolean true
+d-i partman-lvm/confirm boolean true
+d-i partman-lvm/confirm_nooverwrite boolean true
+d-i partman-lvm/device_remove_lvm boolean true
+d-i partman/choose_partition select finish
+d-i partman/confirm boolean true
+d-i partman/confirm_nooverwrite boolean true
+d-i partman/confirm_write_new_label boolean true
+d-i passwd/user-fullname string vagrant
+d-i passwd/user-uid string 1000
+d-i passwd/user-password password vagrant
+d-i passwd/user-password-again password vagrant
+d-i passwd/username string vagrant
+d-i pkgsel/include string openssh-server cryptsetup build-essential libssl-dev libreadline-dev zlib1g-dev linux-source dkms nfs-common linux-headers-$(uname -r) perl cifs-utils software-properties-common rsync ifupdown
+d-i pkgsel/install-language-support boolean false
+d-i pkgsel/update-policy select none
+d-i pkgsel/upgrade select full-upgrade
+d-i time/zone string UTC
+d-i user-setup/allow-password-weak boolean true
+d-i user-setup/encrypt-home boolean false
+tasksel tasksel/first multiselect standard, server
diff --git a/v1.9.4/examples/hcl/linux/etc/http/preseed_hardcoded_ip.cfg b/v1.9.4/examples/hcl/linux/etc/http/preseed_hardcoded_ip.cfg
new file mode 100644
index 0000000..8e31885
--- /dev/null
+++ b/v1.9.4/examples/hcl/linux/etc/http/preseed_hardcoded_ip.cfg
@@ -0,0 +1,68 @@
+#
+# Based upon: https://help.ubuntu.com/12.04/installation-guide/example-preseed.txt
+#
+
+# localisation
+
+d-i debian-installer/locale string en_US.utf8
+d-i console-setup/ask_detect boolean false
+d-i keyboard-configuration/layoutcode string us
+
+# networking
+# Static network configuration.
+d-i netcfg/disable_autoconfig boolean true
+d-i netcfg/get_nameservers string 8.8.8.8
+d-i netcfg/get_netmask string 255.255.255.248
+d-i netcfg/confirm_static boolean true
+
+
+# d-i netcfg/choose_interface select auto
+# d-i netcfg/get_hostname string unassigned-hostname
+# d-i netcfg/get_domain string unassigned-domain
+# d-i netcfg/wireless_wep string
+
+# apt mirrors
+d-i mirror/country string manual
+d-i mirror/http/directory string /ubuntu/
+d-i mirror/http/hostname string archive.ubuntu.com
+d-i mirror/http/proxy string
+
+# clock and time zone
+d-i clock-setup/utc boolean true
+d-i time/zone string GMT
+d-i clock-setup/ntp boolean true
+
+# partitioning
+d-i partman-auto/method string lvm
+d-i partman-lvm/device_remove_lvm boolean true
+d-i partman-md/device_remove_md boolean true
+d-i partman-lvm/confirm boolean true
+d-i partman-lvm/confirm_nooverwrite boolean true
+d-i partman-auto-lvm/guided_size string max
+d-i partman-auto/choose_recipe select atomic
+d-i partman-partitioning/confirm_write_new_label boolean true
+d-i partman/choose_partition select finish
+d-i partman/confirm boolean true
+d-i partman/confirm_nooverwrite boolean true
+
+# users
+d-i passwd/user-fullname string Vagrant
+d-i passwd/username string vagrant
+d-i passwd/user-password password vagrant
+d-i passwd/user-password-again password vagrant
+d-i user-setup/allow-password-weak boolean true
+d-i user-setup/encrypt-home boolean false
+
+# packages
+tasksel tasksel/first multiselect standard, ubuntu-server
+d-i pkgsel/install-language-support boolean false
+d-i pkgsel/include string openssh-server nfs-common open-vm-tools
+d-i pkgsel/upgrade select full-upgrade
+d-i pkgsel/update-policy select none
+# postfix postfix/main_mailer_type select No configuration
+
+# boot loader
+d-i grub-installer/only_debian boolean true
+
+# hide the shutdown notice
+d-i finish-install/reboot_in_progress note
\ No newline at end of file
diff --git a/v1.9.4/examples/hcl/linux/etc/scripts/010-update.sh b/v1.9.4/examples/hcl/linux/etc/scripts/010-update.sh
new file mode 100644
index 0000000..40b1ebf
--- /dev/null
+++ b/v1.9.4/examples/hcl/linux/etc/scripts/010-update.sh
@@ -0,0 +1,40 @@
+#!/bin/sh -eux
+export DEBIAN_FRONTEND=noninteractive
+
+ubuntu_version="`lsb_release -r | awk '{print $2}'`";
+major_version="`echo $ubuntu_version | awk -F. '{print $1}'`";
+
+# Disable release-upgrades
+sed -i.bak 's/^Prompt=.*$/Prompt=never/' /etc/update-manager/release-upgrades;
+
+# Disable systemd apt timers/services
+if [ "$major_version" -ge "16" ]; then
+ systemctl stop apt-daily.timer;
+ systemctl stop apt-daily-upgrade.timer;
+ systemctl disable apt-daily.timer;
+ systemctl disable apt-daily-upgrade.timer;
+ systemctl mask apt-daily.service;
+ systemctl mask apt-daily-upgrade.service;
+ systemctl daemon-reload;
+fi
+
+# Disable periodic activities of apt to be safe
+cat <<EOF >/etc/apt/apt.conf.d/10periodic;
+APT::Periodic::Enable "0";
+APT::Periodic::Update-Package-Lists "0";
+APT::Periodic::Download-Upgradeable-Packages "0";
+APT::Periodic::AutocleanInterval "0";
+APT::Periodic::Unattended-Upgrade "0";
+EOF
+
+# Clean and nuke the package from orbit
+rm -rf /var/log/unattended-upgrades;
+apt-get -y purge unattended-upgrades;
+
+# Update the package list
+apt-get -y update;
+
+# Upgrade all installed packages incl. kernel and kernel headers
+apt-get -y dist-upgrade -o Dpkg::Options::="--force-confnew";
+
+reboot
diff --git a/v1.9.4/examples/hcl/linux/etc/scripts/020-sshd.sh b/v1.9.4/examples/hcl/linux/etc/scripts/020-sshd.sh
new file mode 120000
index 0000000..d70a00b
--- /dev/null
+++ b/v1.9.4/examples/hcl/linux/etc/scripts/020-sshd.sh
@@ -0,0 +1 @@
+../../../../_common/sshd.sh
\ No newline at end of file
diff --git a/v1.9.4/examples/hcl/linux/etc/scripts/030-networking.sh b/v1.9.4/examples/hcl/linux/etc/scripts/030-networking.sh
new file mode 100644
index 0000000..2d4b337
--- /dev/null
+++ b/v1.9.4/examples/hcl/linux/etc/scripts/030-networking.sh
@@ -0,0 +1,25 @@
+#!/bin/sh -eux
+
+ubuntu_version="`lsb_release -r | awk '{print $2}'`";
+major_version="`echo $ubuntu_version | awk -F. '{print $1}'`";
+
+if [ "$major_version" -ge "18" ]; then
+echo "Create netplan config for eth0"
+cat <<EOF >/etc/netplan/01-netcfg.yaml;
+network:
+ version: 2
+ ethernets:
+ eth0:
+ dhcp4: true
+EOF
+else
+ # Adding a 2 sec delay to the interface up, to make the dhclient happy
+ echo "pre-up sleep 2" >> /etc/network/interfaces;
+fi
+
+if [ "$major_version" -ge "16" ]; then
+ # Disable Predictable Network Interface names and use eth0
+ sed -i 's/en[[:alnum:]]*/eth0/g' /etc/network/interfaces;
+ sed -i 's/GRUB_CMDLINE_LINUX="\(.*\)"/GRUB_CMDLINE_LINUX="net.ifnames=0 biosdevname=0 \1"/g' /etc/default/grub;
+ update-grub;
+fi
diff --git a/v1.9.4/examples/hcl/linux/etc/scripts/040-sudoers.sh b/v1.9.4/examples/hcl/linux/etc/scripts/040-sudoers.sh
new file mode 100644
index 0000000..e56537f
--- /dev/null
+++ b/v1.9.4/examples/hcl/linux/etc/scripts/040-sudoers.sh
@@ -0,0 +1,7 @@
+#!/bin/sh -eux
+
+sed -i -e '/Defaults\s\+env_reset/a Defaults\texempt_group=sudo' /etc/sudoers;
+
+# Set up password-less sudo for the vagrant user
+echo 'vagrant ALL=(ALL) NOPASSWD:ALL' >/etc/sudoers.d/99_vagrant;
+chmod 440 /etc/sudoers.d/99_vagrant;
diff --git a/v1.9.4/examples/hcl/linux/etc/scripts/050-vagrant.sh b/v1.9.4/examples/hcl/linux/etc/scripts/050-vagrant.sh
new file mode 120000
index 0000000..48ec2f9
--- /dev/null
+++ b/v1.9.4/examples/hcl/linux/etc/scripts/050-vagrant.sh
@@ -0,0 +1 @@
+../../../../_common/vagrant.sh
\ No newline at end of file
diff --git a/v1.9.4/examples/hcl/linux/etc/scripts/060-virtualbox.sh b/v1.9.4/examples/hcl/linux/etc/scripts/060-virtualbox.sh
new file mode 120000
index 0000000..db9a1ad
--- /dev/null
+++ b/v1.9.4/examples/hcl/linux/etc/scripts/060-virtualbox.sh
@@ -0,0 +1 @@
+../../../../_common/virtualbox.sh
\ No newline at end of file
diff --git a/v1.9.4/examples/hcl/linux/etc/scripts/070-vmware.sh b/v1.9.4/examples/hcl/linux/etc/scripts/070-vmware.sh
new file mode 100644
index 0000000..0f23f55
--- /dev/null
+++ b/v1.9.4/examples/hcl/linux/etc/scripts/070-vmware.sh
@@ -0,0 +1,10 @@
+#!/bin/sh -eux
+
+case "$PACKER_BUILDER_TYPE" in
+vmware-iso|vmware-vmx)
+ apt-get install -y open-vm-tools;
+ mkdir /mnt/hgfs;
+ systemctl enable open-vm-tools
+ systemctl start open-vm-tools
+ echo "platform specific vmware.sh executed";
+esac
diff --git a/v1.9.4/examples/hcl/linux/etc/scripts/080-parallels.sh b/v1.9.4/examples/hcl/linux/etc/scripts/080-parallels.sh
new file mode 120000
index 0000000..0d63dac
--- /dev/null
+++ b/v1.9.4/examples/hcl/linux/etc/scripts/080-parallels.sh
@@ -0,0 +1 @@
+../../../../_common/parallels.sh
\ No newline at end of file
diff --git a/v1.9.4/examples/hcl/linux/etc/scripts/090-hyperv.sh b/v1.9.4/examples/hcl/linux/etc/scripts/090-hyperv.sh
new file mode 100644
index 0000000..af379bc
--- /dev/null
+++ b/v1.9.4/examples/hcl/linux/etc/scripts/090-hyperv.sh
@@ -0,0 +1,12 @@
+#!/bin/sh -eux
+ubuntu_version="`lsb_release -r | awk '{print $2}'`";
+major_version="`echo $ubuntu_version | awk -F. '{print $1}'`";
+
+case "$PACKER_BUILDER_TYPE" in
+hyperv-iso)
+ if [ "$major_version" -eq "16" ]; then
+ apt-get install -y linux-tools-virtual-lts-xenial linux-cloud-tools-virtual-lts-xenial;
+ else
+ apt-get -y install linux-image-virtual linux-tools-virtual linux-cloud-tools-virtual;
+ fi
+esac
diff --git a/v1.9.4/examples/hcl/linux/etc/scripts/100-cleanup.sh b/v1.9.4/examples/hcl/linux/etc/scripts/100-cleanup.sh
new file mode 100644
index 0000000..aef7822
--- /dev/null
+++ b/v1.9.4/examples/hcl/linux/etc/scripts/100-cleanup.sh
@@ -0,0 +1,81 @@
+#!/bin/sh -eux
+
+# Delete all Linux headers
+dpkg --list \
+ | awk '{ print $2 }' \
+ | grep 'linux-headers' \
+ | xargs apt-get -y purge;
+
+# Remove specific Linux kernels, such as linux-image-3.11.0-15-generic but
+# keeps the current kernel and does not touch the virtual packages,
+# e.g. 'linux-image-generic', etc.
+dpkg --list \
+ | awk '{ print $2 }' \
+ | grep 'linux-image-.*-generic' \
+ | grep -v `uname -r` \
+ | xargs apt-get -y purge;
+
+# Delete Linux source
+dpkg --list \
+ | awk '{ print $2 }' \
+ | grep linux-source \
+ | xargs apt-get -y purge;
+
+# Delete development packages
+dpkg --list \
+ | awk '{ print $2 }' \
+ | grep -- '-dev$' \
+ | xargs apt-get -y purge;
+
+# delete docs packages
+dpkg --list \
+ | awk '{ print $2 }' \
+ | grep -- '-doc$' \
+ | xargs apt-get -y purge;
+
+# Delete X11 libraries
+apt-get -y purge libx11-data xauth libxmuu1 libxcb1 libx11-6 libxext6;
+
+# Delete obsolete networking
+apt-get -y purge ppp pppconfig pppoeconf;
+
+# Delete oddities
+apt-get -y purge popularity-contest installation-report command-not-found friendly-recovery bash-completion fonts-ubuntu-font-family-console laptop-detect;
+
+# 19.10+ don't have this package so fail gracefully
+apt-get -y purge command-not-found-data || true;
+
+# Exlude the files we don't need w/o uninstalling linux-firmware
+echo "==> Setup dpkg excludes for linux-firmware"
+cat <<_EOF_ | cat >> /etc/dpkg/dpkg.cfg.d/excludes
+#BENTO-BEGIN
+path-exclude=/lib/firmware/*
+path-exclude=/usr/share/doc/linux-firmware/*
+#BENTO-END
+_EOF_
+
+# Delete the massive firmware packages
+rm -rf /lib/firmware/*
+rm -rf /usr/share/doc/linux-firmware/*
+
+apt-get -y autoremove;
+apt-get -y clean;
+
+# Remove docs
+rm -rf /usr/share/doc/*
+
+# Remove caches
+find /var/cache -type f -exec rm -rf {} \;
+
+# truncate any logs that have built up during the install
+find /var/log -type f -exec truncate --size=0 {} \;
+
+# Blank netplan machine-id (DUID) so machines get unique ID generated on boot.
+truncate -s 0 /etc/machine-id
+
+# remove the contents of /tmp and /var/tmp
+rm -rf /tmp/* /var/tmp/*
+
+# clear the history so our install isn't there
+export HISTSIZE=0
+rm -f /root/.wget-hsts
diff --git a/v1.9.4/examples/hcl/linux/etc/scripts/110-minimize.sh b/v1.9.4/examples/hcl/linux/etc/scripts/110-minimize.sh
new file mode 120000
index 0000000..fa918ae
--- /dev/null
+++ b/v1.9.4/examples/hcl/linux/etc/scripts/110-minimize.sh
@@ -0,0 +1 @@
+../../../../_common/minimize.sh
\ No newline at end of file
diff --git a/v1.9.4/examples/hcl/linux/source.esxi-vmware-iso.pkr.hcl b/v1.9.4/examples/hcl/linux/source.esxi-vmware-iso.pkr.hcl
new file mode 100644
index 0000000..eb6393a
--- /dev/null
+++ b/v1.9.4/examples/hcl/linux/source.esxi-vmware-iso.pkr.hcl
@@ -0,0 +1,49 @@
+source "vmware-iso" "esxi-base-ubuntu-amd64" {
+ headless = var.headless
+ boot_wait = "10s"
+ guest_os_type = "ubuntu-64"
+ http_directory = local.http_directory
+ shutdown_command = "echo 'vagrant' | sudo -S shutdown -P now"
+ ssh_password = "vagrant"
+ ssh_port = 22
+ ssh_timeout = "10000s"
+ ssh_username = "vagrant"
+ tools_upload_flavor = "linux"
+ vmx_data = {
+ "cpuid.coresPerSocket" = "1"
+ "ethernet0.pciSlotNumber" = "32"
+ }
+ vmx_remove_ethernet_interfaces = true
+
+ remote_type = "esx5"
+ remote_host = var.esxi_host
+ remote_username = var.esxi_user
+ remote_password = var.esxi_password
+ remote_datastore = var.datastore
+ remote_private_key_file = var.remote_private_key_file_path
+}
+
+source "vmware-iso" "esxi-base-alpine-amd64" {
+ headless = var.headless
+ boot_wait = "10s"
+ guest_os_type = "otherLinux64Guest"
+ floppy_files = local.floppy_files_alpine_vsphere
+ ssh_port = 22
+ ssh_timeout = "10000s"
+ ssh_username = "root"
+ ssh_password = var.alpine_password
+ tools_upload_flavor = "linux"
+ shutdown_command = "poweroff"
+ vmx_data = {
+ "cpuid.coresPerSocket" = "1"
+ "ethernet0.pciSlotNumber" = "32"
+ }
+ vmx_remove_ethernet_interfaces = true
+
+ remote_type = "esx5"
+ remote_host = var.esxi_host
+ remote_username = var.esxi_user
+ remote_password = var.esxi_password
+ remote_datastore = var.datastore
+ remote_private_key_file = var.remote_private_key_file_path
+}
diff --git a/v1.9.4/examples/hcl/linux/source.parallels-iso.pkr.hcl b/v1.9.4/examples/hcl/linux/source.parallels-iso.pkr.hcl
new file mode 100644
index 0000000..7f2c1a7
--- /dev/null
+++ b/v1.9.4/examples/hcl/linux/source.parallels-iso.pkr.hcl
@@ -0,0 +1,13 @@
+
+source "parallels-iso" "base-ubuntu-amd64" {
+ boot_wait = "10s"
+ guest_os_type = "ubuntu"
+ http_content = local.http_directory_content
+ parallels_tools_flavor = "lin"
+ prlctl_version_file = ".prlctl_version"
+ shutdown_command = "echo 'vagrant' | sudo -S shutdown -P now"
+ ssh_password = "vagrant"
+ ssh_port = 22
+ ssh_timeout = "10000s"
+ ssh_username = "vagrant"
+}
diff --git a/v1.9.4/examples/hcl/linux/source.qemu.pkr.hcl b/v1.9.4/examples/hcl/linux/source.qemu.pkr.hcl
new file mode 100644
index 0000000..69d8bea
--- /dev/null
+++ b/v1.9.4/examples/hcl/linux/source.qemu.pkr.hcl
@@ -0,0 +1,16 @@
+source "qemu" "base-ubuntu-amd64" {
+ headless = var.headless
+ floppy_files = [
+ "${local.http_directory}/preseed.cfg",
+ ]
+ http_directory = local.http_directory
+ shutdown_command = "echo 'vagrant'|sudo -S shutdown -P now"
+ ssh_password = "vagrant"
+ ssh_username = "vagrant"
+ ssh_wait_timeout = "50m"
+ disk_size = 5000
+ disk_interface = "virtio-scsi"
+ memory = 512 * 4
+ cpus = 4
+ boot_wait = "5s"
+}
diff --git a/v1.9.4/examples/hcl/linux/source.virtualbox-iso.pkr.hcl b/v1.9.4/examples/hcl/linux/source.virtualbox-iso.pkr.hcl
new file mode 100644
index 0000000..5cd5f1a
--- /dev/null
+++ b/v1.9.4/examples/hcl/linux/source.virtualbox-iso.pkr.hcl
@@ -0,0 +1,26 @@
+source "virtualbox-iso" "base-ubuntu-amd64" {
+ headless = var.headless
+ guest_os_type = "Ubuntu_64"
+ http_content = local.http_directory_content
+ shutdown_command = "echo 'vagrant' | sudo -S shutdown -P now"
+ ssh_username = "vagrant"
+ ssh_password = "vagrant"
+ ssh_port = 22
+ ssh_wait_timeout = "15m"
+ hard_drive_interface = "sata"
+ virtualbox_version_file = ".vbox_version"
+ guest_additions_path = "VBoxGuestAdditions_{{.Version}}.iso"
+ guest_additions_url = var.guest_additions_url
+}
+
+source "virtualbox-iso" "base-alpine-amd64" {
+ headless = var.headless
+ guest_os_type = "Linux26_64"
+ http_directory = local.http_directory
+ hard_drive_interface = "sata"
+ ssh_username = "root"
+ ssh_password = var.alpine_password
+ ssh_wait_timeout = "60m"
+ shutdown_command = "poweroff"
+ floppy_files = local.floppy_files_alpine
+}
diff --git a/v1.9.4/examples/hcl/linux/source.vmware-iso.pkr.hcl b/v1.9.4/examples/hcl/linux/source.vmware-iso.pkr.hcl
new file mode 100644
index 0000000..d7d32ee
--- /dev/null
+++ b/v1.9.4/examples/hcl/linux/source.vmware-iso.pkr.hcl
@@ -0,0 +1,17 @@
+source "vmware-iso" "base-ubuntu-amd64" {
+ headless = var.headless
+ boot_wait = "10s"
+ guest_os_type = "ubuntu-64"
+ http_directory = local.http_directory
+ shutdown_command = "echo 'vagrant' | sudo -S shutdown -P now"
+ ssh_password = "vagrant"
+ ssh_port = 22
+ ssh_timeout = "10000s"
+ ssh_username = "vagrant"
+ tools_upload_flavor = "linux"
+ vmx_data = {
+ "cpuid.coresPerSocket" = "1"
+ "ethernet0.pciSlotNumber" = "32"
+ }
+ vmx_remove_ethernet_interfaces = true
+}
diff --git a/v1.9.4/examples/hcl/linux/source.vmware-vmx.pkr.hcl b/v1.9.4/examples/hcl/linux/source.vmware-vmx.pkr.hcl
new file mode 100644
index 0000000..a4a6713
--- /dev/null
+++ b/v1.9.4/examples/hcl/linux/source.vmware-vmx.pkr.hcl
@@ -0,0 +1,16 @@
+source "vmware-vmx" "base-ubuntu-amd64" {
+ headless = var.headless
+ boot_wait = "10s"
+ http_directory = local.http_directory
+ shutdown_command = "echo 'vagrant' | sudo -S shutdown -P now"
+ ssh_password = "vagrant"
+ ssh_port = 22
+ ssh_timeout = "10000s"
+ ssh_username = "vagrant"
+ tools_upload_flavor = "linux"
+ vmx_data = {
+ "cpuid.coresPerSocket" = "1"
+ "ethernet0.pciSlotNumber" = "32"
+ }
+ vmx_remove_ethernet_interfaces = true
+}
diff --git a/v1.9.4/examples/hcl/linux/source.vsphere-iso.pkr.hcl b/v1.9.4/examples/hcl/linux/source.vsphere-iso.pkr.hcl
new file mode 100644
index 0000000..b3c33ce
--- /dev/null
+++ b/v1.9.4/examples/hcl/linux/source.vsphere-iso.pkr.hcl
@@ -0,0 +1,115 @@
+// I use the following config with direnv and set the following values:
+// export PKR_VAR_bastion_host=""
+// export PKR_VAR_bastion_user=""
+// export PKR_VAR_datacenter_name=""
+// export PKR_VAR_esxi_host=""
+// export PKR_VAR_esxi_password=""
+// export PKR_VAR_esxi_user=""
+// export PKR_VAR_vcenter_endpoint=""
+// export PKR_VAR_vcenter_password=""
+// export PKR_VAR_vcenter_user=""
+// export PKR_VAR_vm_ip=""
+// export PKR_VAR_gateway_ip=""
+// ...
+
+variable "vcenter_endpoint" { type = string }
+variable "vcenter_user" { type = string }
+variable "vcenter_password" { type = string }
+variable "esxi_host" { type = string }
+variable "esxi_password" { type = string }
+variable "esxi_user" { type = string }
+variable "datacenter_name" { type = string }
+variable "vm_ip" { type = string }
+variable "gateway_ip" { type = string }
+variable "datastore" {
+ default = "datastore1"
+}
+variable "remote_private_key_file_path" {
+ type = string
+}
+
+source "vsphere-iso" "base-ubuntu-amd64" {
+ vcenter_server = var.vcenter_endpoint
+ username = var.vcenter_user
+ password = var.vcenter_password
+ host = var.esxi_host
+ insecure_connection = true
+
+ datacenter = var.datacenter_name
+ datastore = "datastore1"
+
+ ssh_password = "vagrant"
+ ssh_username = "vagrant"
+
+ CPUs = 1
+ RAM = 512 * 2
+ RAM_reserve_all = true
+
+ disk_controller_type = "pvscsi"
+ floppy_files = [
+ "etc/http/preseed_hardcoded_ip.cfg"
+ ]
+ guest_os_type = "ubuntu64Guest"
+ network_adapters {
+ network = "VM Network"
+ network_card = "vmxnet3"
+ }
+ storage {
+ disk_size = 32768
+ disk_thin_provisioned = true
+ }
+
+ boot_command = [
+ "<enter><wait><f6><wait><esc><wait>",
+ "<bs><bs><bs><bs><bs><bs><bs><bs><bs><bs>",
+ "<bs><bs><bs><bs><bs><bs><bs><bs><bs><bs>",
+ "<bs><bs><bs><bs><bs><bs><bs><bs><bs><bs>",
+ "<bs><bs><bs><bs><bs><bs><bs><bs><bs><bs>",
+ "<bs><bs><bs><bs><bs><bs><bs><bs><bs><bs>",
+ "<bs><bs><bs><bs><bs><bs><bs><bs><bs><bs>",
+ "<bs><bs><bs><bs><bs><bs><bs><bs><bs><bs>",
+ "<bs><bs><bs><bs><bs><bs><bs><bs><bs><bs>",
+ "<bs><bs><bs>",
+ "/install/vmlinuz",
+ " initrd=/install/initrd.gz",
+ " priority=critical",
+ " locale=en_US",
+ " file=/media/preseed_hardcoded_ip.cfg",
+ " netcfg/get_ipaddress=${var.vm_ip}",
+ " netcfg/get_gateway=${var.gateway_ip}",
+ "<enter>"
+ ]
+}
+
+
+source "vsphere-iso" "base-alpine-amd64" {
+ vcenter_server = var.vcenter_endpoint
+ username = var.vcenter_user
+ password = var.vcenter_password
+ host = var.esxi_host
+ insecure_connection = true
+
+ datacenter = var.datacenter_name
+ datastore = "datastore1"
+
+ ssh_username = "root"
+ ssh_password = var.alpine_password
+
+ CPUs = 1
+ RAM = 512 * 2
+ RAM_reserve_all = true
+
+ guest_os_type = "otherLinux64Guest"
+
+ floppy_files = local.floppy_files_alpine_vsphere
+
+ network_adapters {
+ network = "VM Network"
+ network_card = "vmxnet3"
+ }
+
+ storage {
+ disk_size = 32768
+ disk_thin_provisioned = true
+ }
+}
diff --git a/v1.9.4/examples/hcl/linux/variables.16.04.pkr.hcl b/v1.9.4/examples/hcl/linux/variables.16.04.pkr.hcl
new file mode 100644
index 0000000..953f52a
--- /dev/null
+++ b/v1.9.4/examples/hcl/linux/variables.16.04.pkr.hcl
@@ -0,0 +1,34 @@
+variable "ubuntu_1604_version" {
+ default = "16.04.7"
+}
+
+locals {
+ iso_url_ubuntu_1604 = "http://releases.ubuntu.com/releases/16.04/ubuntu-${var.ubuntu_1604_version}-server-amd64.iso"
+ iso_checksum_url_ubuntu_1604 = "http://releases.ubuntu.com/releases/16.04/SHA256SUMS"
+ ubuntu_1604_boot_command = [
+ "<enter><wait><f6><esc><bs><bs><bs><bs><bs><bs><bs><bs><bs><bs><bs><bs><bs><bs><bs><bs><bs>",
+ "<bs><bs><bs><bs><bs><bs><bs><bs><bs><bs><bs><bs><bs><bs><bs><bs><bs><bs><bs><bs><bs><bs>",
+ "<bs><bs><bs><bs><bs><bs><bs><bs><bs><bs><bs><bs><bs><bs><bs><bs><bs><bs><bs><bs><bs><bs>",
+ "<bs><bs><bs><bs><bs><bs><bs><bs><bs><bs><bs><bs><bs><bs><bs><bs><bs><bs><bs><bs><bs><bs>",
+ "/install/vmlinuz<wait>",
+ " auto<wait>",
+ " console-setup/ask_detect=false<wait>",
+ " console-setup/layoutcode=us<wait>",
+ " console-setup/modelcode=pc105<wait>",
+ " debconf/frontend=noninteractive<wait>",
+ " debian-installer=en_US.UTF-8<wait>",
+ " fb=false<wait>",
+ " initrd=/install/initrd.gz<wait>",
+ " kbd-chooser/method=us<wait>",
+ " keyboard-configuration/layout=USA<wait>",
+ " keyboard-configuration/variant=USA<wait>",
+ " locale=en_US.UTF-8<wait>",
+ " netcfg/get_domain=vm<wait>",
+ " netcfg/get_hostname=vagrant<wait>",
+ " grub-installer/bootdev=/dev/sda<wait>",
+ " noapic<wait>",
+ " preseed/url=http://{{ .HTTPIP }}:{{ .HTTPPort }}/${var.preseed_path}<wait>",
+ " -- <wait>",
+ "<enter><wait>"
+ ]
+}
diff --git a/v1.9.4/examples/hcl/linux/variables.18.04.pkr.hcl b/v1.9.4/examples/hcl/linux/variables.18.04.pkr.hcl
new file mode 100644
index 0000000..abdbc8e
--- /dev/null
+++ b/v1.9.4/examples/hcl/linux/variables.18.04.pkr.hcl
@@ -0,0 +1,33 @@
+variable "ubuntu_1804_version" {
+ default = "18.04.5"
+}
+
+locals {
+ iso_url_ubuntu_1804 = "http://cdimage.ubuntu.com/ubuntu/releases/18.04/release/ubuntu-${var.ubuntu_1804_version}-server-amd64.iso"
+ iso_checksum_url_ubuntu_1804 = "http://cdimage.ubuntu.com/ubuntu/releases/18.04/release/SHA256SUMS"
+ ubuntu_1804_boot_command = [
+ "<esc><wait>",
+ "<esc><wait>",
+ "<enter><wait>",
+ "/install/vmlinuz<wait>",
+ " auto<wait>",
+ " console-setup/ask_detect=false<wait>",
+ " console-setup/layoutcode=us<wait>",
+ " console-setup/modelcode=pc105<wait>",
+ " debconf/frontend=noninteractive<wait>",
+ " debian-installer=en_US.UTF-8<wait>",
+ " fb=false<wait>",
+ " initrd=/install/initrd.gz<wait>",
+ " kbd-chooser/method=us<wait>",
+ " keyboard-configuration/layout=USA<wait>",
+ " keyboard-configuration/variant=USA<wait>",
+ " locale=en_US.UTF-8<wait>",
+ " netcfg/get_domain=vm<wait>",
+ " netcfg/get_hostname=vagrant<wait>",
+ " grub-installer/bootdev=/dev/sda<wait>",
+ " noapic<wait>",
+ " preseed/url=http://{{ .HTTPIP }}:{{ .HTTPPort }}/${var.preseed_path}<wait>",
+ " -- <wait>",
+ "<enter><wait>"
+ ]
+}
diff --git a/v1.9.4/examples/hcl/linux/variables.alpine.pkr.hcl b/v1.9.4/examples/hcl/linux/variables.alpine.pkr.hcl
new file mode 100644
index 0000000..62c0e47
--- /dev/null
+++ b/v1.9.4/examples/hcl/linux/variables.alpine.pkr.hcl
@@ -0,0 +1,56 @@
+
+variable "alpine_password" {
+ type = string
+ default = "alpine"
+}
+
+locals {
+ iso_url_alpine_312 = "http://dl-cdn.alpinelinux.org/alpine/v3.12/releases/x86_64/alpine-virt-3.12.0-x86_64.iso"
+ iso_checksum_url_alpine_312 = "http://dl-cdn.alpinelinux.org/alpine/v3.12/releases/x86_64/alpine-virt-3.12.0-x86_64.iso.sha256"
+ floppy_files_alpine = [
+ "${local.http_directory}/alpine-answers",
+ "${local.http_directory}/alpine-setup.sh"
+ ]
+
+ alpine_312_floppy_boot_command = [
+ "root<enter><wait>",
+ "mount -t vfat /dev/fd0 /media/floppy<enter><wait>",
+ "setup-alpine -f /media/floppy/alpine-answers<enter>",
+ "<wait5>",
+ "${var.alpine_password}<enter>",
+ "${var.alpine_password}<enter>",
+ "<wait5>",
+ "y<enter>",
+ "<wait40s>",
+ "reboot<enter>",
+ "<wait20s>",
+ "root<enter>",
+ "${var.alpine_password}<enter><wait>",
+ "mount -t vfat /dev/fd0 /media/floppy<enter><wait>",
+ "/media/floppy/alpine-setup.sh<enter>",
+ ]
+
+ floppy_files_alpine_vsphere = [
+ "${local.http_directory}/alpine-vsphere-answers",
+ "${local.http_directory}/alpine-setup.sh"
+ ]
+
+ alpine_312_floppy_boot_command_vsphere = [
+ "root<enter><wait1s>",
+ "mount -t vfat /dev/fd0 /media/floppy<enter><wait1s>",
+ "setup-alpine -f /media/floppy/alpine-vsphere-answers<enter><wait3s>",
+ "${var.alpine_password}<enter>",
+ "${var.alpine_password}<enter>",
+ "<wait6s>",
+ "y<enter>",
+ "<wait12s>",
+ "reboot<enter>",
+ "<wait12s>",
+ "root<enter>",
+ "${var.alpine_password}<enter><wait>",
+ "mount -t vfat /dev/fd0 /media/floppy<enter><wait>",
+ "/media/floppy/alpine-setup.sh<enter>",
+ "<wait55s>",
+ ]
+
+}
diff --git a/v1.9.4/examples/hcl/linux/variables.common.pkr.hcl b/v1.9.4/examples/hcl/linux/variables.common.pkr.hcl
new file mode 100644
index 0000000..01a1789
--- /dev/null
+++ b/v1.9.4/examples/hcl/linux/variables.common.pkr.hcl
@@ -0,0 +1,29 @@
+
+variable "preseed_path" {
+ type = string
+ default = "preseed.cfg"
+}
+
+variable "guest_additions_url" {
+ type = string
+ default = ""
+}
+
+variable "headless" {
+ type = bool
+ default = true
+}
+
+locals {
+ // fileset lists all files in the http directory as a set, we convert that
+ // set to a list of strings and we then take the directory of the first
+ // value. This validates that the http directory exists even before starting
+ // any builder/provisioner.
+ http_directory = dirname(convert(fileset(".", "etc/http/*"), list(string))[0])
+ http_directory_content = {
+ "/alpine-answers" = file("${local.http_directory}/alpine-answers"),
+ "/alpine-setup.sh" = file("${local.http_directory}/alpine-setup.sh"),
+ "/preseed_hardcoded_ip.cfg" = file("${local.http_directory}/preseed_hardcoded_ip.cfg"),
+ "/preseed.cfg" = file("${local.http_directory}/preseed.cfg"),
+ }
+}
diff --git a/v1.9.4/examples/preseeds/ubuntu_preseed.cfg b/v1.9.4/examples/preseeds/ubuntu_preseed.cfg
new file mode 100644
index 0000000..1786445
--- /dev/null
+++ b/v1.9.4/examples/preseeds/ubuntu_preseed.cfg
@@ -0,0 +1,61 @@
+# Preseeding only locale sets language, country and locale.
+d-i debian-installer/locale string en_US
+
+# Keyboard selection.
+d-i console-setup/ask_detect boolean false
+d-i keyboard-configuration/xkb-keymap select us
+
+choose-mirror-bin mirror/http/proxy string
+
+### Clock and time zone setup
+d-i clock-setup/utc boolean true
+d-i time/zone string UTC
+
+# Avoid that last message about the install being complete.
+d-i finish-install/reboot_in_progress note
+
+# This is fairly safe to set, it makes grub install automatically to the MBR
+# if no other operating system is detected on the machine.
+d-i grub-installer/only_debian boolean true
+
+# This one makes grub-installer install to the MBR if it also finds some other
+# OS, which is less safe as it might not be able to boot that other OS.
+d-i grub-installer/with_other_os boolean true
+
+### Mirror settings
+# If you select ftp, the mirror/country string does not need to be set.
+d-i mirror/country string manual
+d-i mirror/http/directory string /ubuntu/
+d-i mirror/http/hostname string archive.ubuntu.com
+d-i mirror/http/proxy string
+
+### Partitioning
+d-i partman-auto/method string lvm
+
+# This makes partman automatically partition without confirmation.
+d-i partman-md/confirm boolean true
+d-i partman-partitioning/confirm_write_new_label boolean true
+d-i partman/choose_partition select finish
+d-i partman/confirm boolean true
+d-i partman/confirm_nooverwrite boolean true
+
+### Account setup
+d-i passwd/user-fullname string vagrant
+d-i passwd/user-uid string 1000
+d-i passwd/user-password password vagrant
+d-i passwd/user-password-again password vagrant
+d-i passwd/username string vagrant
+
+# The installer will warn about weak passwords. If you are sure you know
+# what you're doing and want to override it, uncomment this.
+d-i user-setup/allow-password-weak boolean true
+d-i user-setup/encrypt-home boolean false
+
+### Package selection
+tasksel tasksel/first standard
+d-i pkgsel/include string openssh-server build-essential
+d-i pkgsel/install-language-support boolean false
+
+# disable automatic package updates
+d-i pkgsel/update-policy select none
+d-i pkgsel/upgrade select full-upgrade
\ No newline at end of file
diff --git a/v1.9.4/fix/fixer.go b/v1.9.4/fix/fixer.go
new file mode 100644
index 0000000..3de4bc1
--- /dev/null
+++ b/v1.9.4/fix/fixer.go
@@ -0,0 +1,104 @@
+// Copyright (c) HashiCorp, Inc.
+// SPDX-License-Identifier: MPL-2.0
+
+package fix
+
+// A Fixer is something that can perform a fix operation on a template.
+type Fixer interface {
+ // DeprecatedOptions returns the name(s) of the option(s) being replaced in
+ // this fixer. It is used to generate a list of deprecated options that the
+ // template parser checks against to warn users that they need to call
+ // `packer fix` against their templates after upgrading.
+ DeprecatedOptions() map[string][]string
+
+ // Fix takes a raw map structure input, potentially transforms it
+ // in some way, and returns the new, transformed structure. The
+ // Fix method is allowed to mutate the input.
+ Fix(input map[string]interface{}) (map[string]interface{}, error)
+
+ // Synopsis returns a string description of what the fixer actually
+ // does.
+ Synopsis() string
+}
+
+// Fixers is the map of all available fixers, by name.
+var Fixers map[string]Fixer
+
+// FixerOrder is the default order the fixers should be run.
+var FixerOrder []string
+
+func init() {
+ Fixers = map[string]Fixer{
+ "iso-md5": new(FixerISOMD5),
+ "createtime": new(FixerCreateTime),
+ "pp-vagrant-override": new(FixerVagrantPPOverride),
+ "virtualbox-gaattach": new(FixerVirtualBoxGAAttach),
+ "virtualbox-rename": new(FixerVirtualBoxRename),
+ "vmware-rename": new(FixerVMwareRename),
+ "parallels-headless": new(FixerParallelsHeadless),
+ "parallels-deprecations": new(FixerParallelsDeprecations),
+ "sshkeypath": new(FixerSSHKeyPath),
+ "sshdisableagent": new(FixerSSHDisableAgent),
+ "scaleway-access-key": new(FixerScalewayAccessKey),
+ "manifest-filename": new(FixerManifestFilename),
+ "amazon-shutdown_behavior": new(FixerAmazonShutdownBehavior),
+ "amazon-enhanced-networking": new(FixerAmazonEnhancedNetworking),
+ "amazon-private-ip": new(FixerAmazonPrivateIP),
+ "amazon-temp-sec-cidrs": new(FixerAmazonTemporarySecurityCIDRs),
+ "docker-email": new(FixerDockerEmail),
+ "powershell-escapes": new(FixerPowerShellEscapes),
+ "hyperv-deprecations": new(FixerHypervDeprecations),
+ "hyperv-vmxc-typo": new(FixerHypervVmxcTypo),
+ "hyperv-cpu-and-ram": new(FizerHypervCPUandRAM),
+ "vmware-compaction": new(FixerVMwareCompaction),
+ "clean-image-name": new(FixerCleanImageName),
+ "spot-price-auto-product": new(FixerAmazonSpotPriceProductDeprecation),
+ "qemu-disk-size": new(FixerQEMUDiskSize),
+ "galaxy-command": new(FixerGalaxyCommand),
+ "comm-config": new(FixerCommConfig),
+ "ssh-wait-timeout": new(FixerSSHTimout),
+ "docker-tag-tags": new(FixerDockerTagtoTags),
+ "vsphere-iso-net-disk": new(FixerVSphereNetworkDisk),
+ "iso-checksum-type-and-url": new(FixerISOChecksumTypeAndURL),
+ "qemu-host-port": new(FixerQEMUHostPort),
+ "azure-exclude_from_latest": new(FixerAzureExcludeFromLatest),
+ "proxmox-type": new(FixerProxmoxType),
+ }
+
+ FixerOrder = []string{
+ "iso-md5",
+ "createtime",
+ "virtualbox-gaattach",
+ "pp-vagrant-override",
+ "virtualbox-rename",
+ "vmware-rename",
+ "parallels-headless",
+ "parallels-deprecations",
+ "sshkeypath",
+ "sshdisableagent",
+ "scaleway-access-key",
+ "manifest-filename",
+ "amazon-shutdown_behavior",
+ "amazon-enhanced-networking",
+ "amazon-private-ip",
+ "amazon-temp-sec-cidrs",
+ "docker-email",
+ "docker-tag-tags",
+ "powershell-escapes",
+ "vmware-compaction",
+ "hyperv-deprecations",
+ "hyperv-vmxc-typo",
+ "hyperv-cpu-and-ram",
+ "clean-image-name",
+ "spot-price-auto-product",
+ "qemu-disk-size",
+ "galaxy-command",
+ "comm-config",
+ "ssh-wait-timeout",
+ "vsphere-iso-net-disk",
+ "iso-checksum-type-and-url",
+ "qemu-host-port",
+ "azure-exclude_from_latest",
+ "proxmox-type",
+ }
+}
diff --git a/v1.9.4/fix/fixer_amazon_enhanced_networking.go b/v1.9.4/fix/fixer_amazon_enhanced_networking.go
new file mode 100644
index 0000000..708d2f5
--- /dev/null
+++ b/v1.9.4/fix/fixer_amazon_enhanced_networking.go
@@ -0,0 +1,69 @@
+// Copyright (c) HashiCorp, Inc.
+// SPDX-License-Identifier: MPL-2.0
+
+package fix
+
+import (
+ "strings"
+
+ "github.com/mitchellh/mapstructure"
+)
+
+// FixerAmazonEnhancedNetworking is a Fixer that replaces the "enhanced_networking" configuration key
+// with the clearer "ena_support". This disambiguates ena_support from sriov_support.
+type FixerAmazonEnhancedNetworking struct{}
+
+func (FixerAmazonEnhancedNetworking) DeprecatedOptions() map[string][]string {
+ return map[string][]string{
+ "*amazon*": []string{"enhanced_networking"},
+ }
+}
+
+func (FixerAmazonEnhancedNetworking) Fix(input map[string]interface{}) (map[string]interface{}, error) {
+ // Our template type we'll use for this fixer only
+ type template struct {
+ Builders []map[string]interface{}
+ }
+
+ // Decode the input into our structure, if we can
+ var tpl template
+ if err := mapstructure.Decode(input, &tpl); err != nil {
+ return nil, err
+ }
+
+ // Go through each builder and replace the enhanced_networking if we can
+ for _, builder := range tpl.Builders {
+ builderTypeRaw, ok := builder["type"]
+ if !ok {
+ continue
+ }
+
+ builderType, ok := builderTypeRaw.(string)
+ if !ok {
+ continue
+ }
+
+ if !strings.HasPrefix(builderType, "amazon-") {
+ continue
+ }
+ enhancedNetworkingRaw, ok := builder["enhanced_networking"]
+ if !ok {
+ continue
+ }
+ enhancedNetworkingString, ok := enhancedNetworkingRaw.(bool)
+ if !ok {
+ // TODO: error?
+ continue
+ }
+
+ delete(builder, "enhanced_networking")
+ builder["ena_support"] = enhancedNetworkingString
+ }
+
+ input["builders"] = tpl.Builders
+ return input, nil
+}
+
+func (FixerAmazonEnhancedNetworking) Synopsis() string {
+ return `Replaces "enhanced_networking" in builders with "ena_support"`
+}
diff --git a/v1.9.4/fix/fixer_amazon_enhanced_networking_test.go b/v1.9.4/fix/fixer_amazon_enhanced_networking_test.go
new file mode 100644
index 0000000..4abdcc5
--- /dev/null
+++ b/v1.9.4/fix/fixer_amazon_enhanced_networking_test.go
@@ -0,0 +1,67 @@
+// Copyright (c) HashiCorp, Inc.
+// SPDX-License-Identifier: MPL-2.0
+
+package fix
+
+import (
+ "reflect"
+ "testing"
+)
+
+func TestFixerAmazonEnhancedNetworking_Impl(t *testing.T) {
+ var _ Fixer = new(FixerAmazonEnhancedNetworking)
+}
+
+func TestFixerAmazonEnhancedNetworking(t *testing.T) {
+ cases := []struct {
+ Input map[string]interface{}
+ Expected map[string]interface{}
+ }{
+ // Attach field == false
+ {
+ Input: map[string]interface{}{
+ "type": "amazon-ebs",
+ "enhanced_networking": false,
+ },
+
+ Expected: map[string]interface{}{
+ "type": "amazon-ebs",
+ "ena_support": false,
+ },
+ },
+
+ // Attach field == true
+ {
+ Input: map[string]interface{}{
+ "type": "amazon-ebs",
+ "enhanced_networking": true,
+ },
+
+ Expected: map[string]interface{}{
+ "type": "amazon-ebs",
+ "ena_support": true,
+ },
+ },
+ }
+
+ for _, tc := range cases {
+ var f FixerAmazonEnhancedNetworking
+
+ input := map[string]interface{}{
+ "builders": []map[string]interface{}{tc.Input},
+ }
+
+ expected := map[string]interface{}{
+ "builders": []map[string]interface{}{tc.Expected},
+ }
+
+ output, err := f.Fix(input)
+ if err != nil {
+ t.Fatalf("err: %s", err)
+ }
+
+ if !reflect.DeepEqual(output, expected) {
+ t.Fatalf("unexpected: %#v\nexpected: %#v\n", output, expected)
+ }
+ }
+}
diff --git a/v1.9.4/fix/fixer_amazon_private_ip.go b/v1.9.4/fix/fixer_amazon_private_ip.go
new file mode 100644
index 0000000..ee18770
--- /dev/null
+++ b/v1.9.4/fix/fixer_amazon_private_ip.go
@@ -0,0 +1,83 @@
+// Copyright (c) HashiCorp, Inc.
+// SPDX-License-Identifier: MPL-2.0
+
+package fix
+
+import (
+ "fmt"
+ "strconv"
+ "strings"
+
+ "github.com/mitchellh/mapstructure"
+)
+
+// FixerAmazonPrivateIP is a Fixer that replaces instances of `"private_ip":
+// true` with `"ssh_interface": "private_ip"`
+type FixerAmazonPrivateIP struct{}
+
+func (FixerAmazonPrivateIP) DeprecatedOptions() map[string][]string {
+ return map[string][]string{
+ "*amazon*": []string{"ssh_private_ip"},
+ }
+}
+
+func (FixerAmazonPrivateIP) Fix(input map[string]interface{}) (map[string]interface{}, error) {
+ type template struct {
+ Builders []map[string]interface{}
+ }
+
+ // Decode the input into our structure, if we can
+ var tpl template
+ if err := mapstructure.Decode(input, &tpl); err != nil {
+ return nil, err
+ }
+
+ // Go through each builder and replace the enhanced_networking if we can
+ for _, builder := range tpl.Builders {
+ builderTypeRaw, ok := builder["type"]
+ if !ok {
+ continue
+ }
+
+ builderType, ok := builderTypeRaw.(string)
+ if !ok {
+ continue
+ }
+
+ if !strings.HasPrefix(builderType, "amazon-") {
+ continue
+ }
+
+ // if ssh_interface already set, do nothing
+ if _, ok := builder["ssh_interface"]; ok {
+ continue
+ }
+
+ privateIPi, ok := builder["ssh_private_ip"]
+ if !ok {
+ continue
+ }
+ privateIP, ok := privateIPi.(bool)
+ if !ok {
+ var err error
+ privateIP, err = strconv.ParseBool(privateIPi.(string))
+ if err != nil {
+ return nil, fmt.Errorf("ssh_private_ip is not a boolean, %s", err)
+ }
+ }
+
+ delete(builder, "ssh_private_ip")
+ if privateIP {
+ builder["ssh_interface"] = "private_ip"
+ } else {
+ builder["ssh_interface"] = "public_ip"
+ }
+ }
+
+ input["builders"] = tpl.Builders
+ return input, nil
+}
+
+func (FixerAmazonPrivateIP) Synopsis() string {
+ return "Replaces `\"ssh_private_ip\": true` in amazon builders with `\"ssh_interface\": \"private_ip\"`"
+}
diff --git a/v1.9.4/fix/fixer_amazon_private_ip_test.go b/v1.9.4/fix/fixer_amazon_private_ip_test.go
new file mode 100644
index 0000000..554e2e7
--- /dev/null
+++ b/v1.9.4/fix/fixer_amazon_private_ip_test.go
@@ -0,0 +1,96 @@
+// Copyright (c) HashiCorp, Inc.
+// SPDX-License-Identifier: MPL-2.0
+
+package fix
+
+import (
+ "reflect"
+ "testing"
+)
+
+func TestFixerAmazonPrivateIP_Impl(t *testing.T) {
+ var _ Fixer = new(FixerAmazonPrivateIP)
+}
+
+func TestFixerAmazonPrivateIP(t *testing.T) {
+ cases := []struct {
+ Input map[string]interface{}
+ Expected map[string]interface{}
+ }{
+ // Attach field == false
+ {
+ Input: map[string]interface{}{
+ "type": "amazon-ebs",
+ "ssh_private_ip": false,
+ },
+
+ Expected: map[string]interface{}{
+ "type": "amazon-ebs",
+ "ssh_interface": "public_ip",
+ },
+ },
+
+ // Attach field == true
+ {
+ Input: map[string]interface{}{
+ "type": "amazon-ebs",
+ "ssh_private_ip": true,
+ },
+
+ Expected: map[string]interface{}{
+ "type": "amazon-ebs",
+ "ssh_interface": "private_ip",
+ },
+ },
+
+ // ssh_private_ip specified as string
+ {
+ Input: map[string]interface{}{
+ "type": "amazon-ebs",
+ "ssh_private_ip": "true",
+ },
+
+ Expected: map[string]interface{}{
+ "type": "amazon-ebs",
+ "ssh_interface": "private_ip",
+ },
+ },
+ }
+
+ for _, tc := range cases {
+ var f FixerAmazonPrivateIP
+
+ input := map[string]interface{}{
+ "builders": []map[string]interface{}{tc.Input},
+ }
+
+ expected := map[string]interface{}{
+ "builders": []map[string]interface{}{tc.Expected},
+ }
+
+ output, err := f.Fix(input)
+ if err != nil {
+ t.Fatalf("err: %s", err)
+ }
+
+ if !reflect.DeepEqual(output, expected) {
+ t.Fatalf("unexpected: %#v\nexpected: %#v\n", output, expected)
+ }
+ }
+}
+
+func TestFixerAmazonPrivateIPNonBoolean(t *testing.T) {
+ var f FixerAmazonPrivateIP
+
+ input := map[string]interface{}{
+ "builders": []map[string]interface{}{{
+ "type": "amazon-ebs",
+ "ssh_private_ip": "not-a-boolean-value",
+ }},
+ }
+
+ _, err := f.Fix(input)
+ if err == nil {
+ t.Fatal("should have errored")
+ }
+}
diff --git a/v1.9.4/fix/fixer_amazon_shutdown_behavior.go b/v1.9.4/fix/fixer_amazon_shutdown_behavior.go
new file mode 100644
index 0000000..c7e2db0
--- /dev/null
+++ b/v1.9.4/fix/fixer_amazon_shutdown_behavior.go
@@ -0,0 +1,63 @@
+// Copyright (c) HashiCorp, Inc.
+// SPDX-License-Identifier: MPL-2.0
+
+package fix
+
+import (
+ "strings"
+
+ "github.com/mitchellh/mapstructure"
+)
+
+// FixerAmazonShutdownBehavior fix the spelling of "shutdown_behavior"
+// template in a Amazon builder
+type FixerAmazonShutdownBehavior struct{}
+
+func (FixerAmazonShutdownBehavior) DeprecatedOptions() map[string][]string {
+ return map[string][]string{
+ "*amazon*": []string{"shutdown_behaviour"},
+ }
+}
+
+func (FixerAmazonShutdownBehavior) Fix(input map[string]interface{}) (map[string]interface{}, error) {
+ // The type we'll decode into; we only care about builders
+ type template struct {
+ Builders []map[string]interface{}
+ }
+
+ // Decode the input into our structure, if we can
+ var tpl template
+ if err := mapstructure.Decode(input, &tpl); err != nil {
+ return nil, err
+ }
+
+ for _, builder := range tpl.Builders {
+ builderTypeRaw, ok := builder["type"]
+ if !ok {
+ continue
+ }
+
+ builderType, ok := builderTypeRaw.(string)
+ if !ok {
+ continue
+ }
+
+ if !strings.HasPrefix(builderType, "amazon-") {
+ continue
+ }
+
+ shutdownBehavior, ok := builder["shutdown_behaviour"]
+
+ if ok {
+ builder["shutdown_behavior"] = shutdownBehavior
+ delete(builder, "shutdown_behaviour")
+ }
+ }
+
+ input["builders"] = tpl.Builders
+ return input, nil
+}
+
+func (FixerAmazonShutdownBehavior) Synopsis() string {
+ return `Changes "shutdown_behaviour" to "shutdown_behavior" in Amazon builders.`
+}
diff --git a/v1.9.4/fix/fixer_amazon_shutdown_behavior_test.go b/v1.9.4/fix/fixer_amazon_shutdown_behavior_test.go
new file mode 100644
index 0000000..87058ea
--- /dev/null
+++ b/v1.9.4/fix/fixer_amazon_shutdown_behavior_test.go
@@ -0,0 +1,65 @@
+// Copyright (c) HashiCorp, Inc.
+// SPDX-License-Identifier: MPL-2.0
+
+package fix
+
+import (
+ "reflect"
+ "testing"
+)
+
+func TestFixerAmazonShutdownBehavior(t *testing.T) {
+ var _ Fixer = new(FixerAmazonShutdownBehavior)
+}
+
+func TestFixerAmazonShutdownBehavior_Fix_shutdown_behaviour(t *testing.T) {
+ cases := []struct {
+ Input map[string]interface{}
+ Expected map[string]interface{}
+ }{
+ // No shutdown_behaviour field
+ {
+ Input: map[string]interface{}{
+ "type": "amazon-ebs",
+ },
+
+ Expected: map[string]interface{}{
+ "type": "amazon-ebs",
+ },
+ },
+
+ // shutdown_behaviour field
+ {
+ Input: map[string]interface{}{
+ "type": "amazon-ebs",
+ "shutdown_behaviour": "stop",
+ },
+
+ Expected: map[string]interface{}{
+ "type": "amazon-ebs",
+ "shutdown_behavior": "stop",
+ },
+ },
+ }
+
+ for _, tc := range cases {
+ var f FixerAmazonShutdownBehavior
+
+ input := map[string]interface{}{
+ "builders": []map[string]interface{}{tc.Input},
+ }
+
+ expected := map[string]interface{}{
+ "builders": []map[string]interface{}{tc.Expected},
+ }
+
+ output, err := f.Fix(input)
+ if err != nil {
+ t.Fatalf("err: %s", err)
+ }
+
+ if !reflect.DeepEqual(output, expected) {
+ t.Fatalf("unexpected: %#v\nexpected: %#v\n", output, expected)
+ }
+ }
+}
diff --git a/v1.9.4/fix/fixer_amazon_spot_price_product.go b/v1.9.4/fix/fixer_amazon_spot_price_product.go
new file mode 100644
index 0000000..b701e1d
--- /dev/null
+++ b/v1.9.4/fix/fixer_amazon_spot_price_product.go
@@ -0,0 +1,69 @@
+// Copyright (c) HashiCorp, Inc.
+// SPDX-License-Identifier: MPL-2.0
+
+package fix
+
+import (
+ "github.com/mitchellh/mapstructure"
+)
+
+// FixerAmazonSpotPriceProductDeprecation removes the deprecated "spot_price_auto_product" setting
+// from Amazon builder templates
+type FixerAmazonSpotPriceProductDeprecation struct{}
+
+func (FixerAmazonSpotPriceProductDeprecation) DeprecatedOptions() map[string][]string {
+ return map[string][]string{
+ "*amazon*": []string{"spot_price_auto_product"},
+ }
+}
+
+func (FixerAmazonSpotPriceProductDeprecation) Fix(input map[string]interface{}) (map[string]interface{}, error) {
+ // The type we'll decode into; we only care about builders
+ type template struct {
+ Builders []map[string]interface{}
+ }
+
+ // Decode the input into our structure, if we can
+ var tpl template
+ if err := mapstructure.Decode(input, &tpl); err != nil {
+ return nil, err
+ }
+
+ for _, builder := range tpl.Builders {
+ builderTypeRaw, ok := builder["type"]
+ if !ok {
+ continue
+ }
+
+ builderType, ok := builderTypeRaw.(string)
+ if !ok {
+ continue
+ }
+
+ buildersToFix := []string{"amazon-ebs", "amazon-ebssurrogate",
+ "amazon-ebsvolume", "amazon-instance"}
+
+ matched := false
+ for _, b := range buildersToFix {
+ if builderType == b {
+ matched = true
+ break
+ }
+ }
+ if !matched {
+ continue
+ }
+
+ _, ok = builder["spot_price_auto_product"]
+ if ok {
+ delete(builder, "spot_price_auto_product")
+ }
+ }
+
+ input["builders"] = tpl.Builders
+ return input, nil
+}
+
+func (FixerAmazonSpotPriceProductDeprecation) Synopsis() string {
+ return `Removes the deprecated "spot_price_auto_product" setting from Amazon builder templates`
+}
diff --git a/v1.9.4/fix/fixer_amazon_temporary_security_group_cidrs.go b/v1.9.4/fix/fixer_amazon_temporary_security_group_cidrs.go
new file mode 100644
index 0000000..ffd75eb
--- /dev/null
+++ b/v1.9.4/fix/fixer_amazon_temporary_security_group_cidrs.go
@@ -0,0 +1,63 @@
+// Copyright (c) HashiCorp, Inc.
+// SPDX-License-Identifier: MPL-2.0
+
+package fix
+
+import (
+ "strings"
+
+ "github.com/mitchellh/mapstructure"
+)
+
+type FixerAmazonTemporarySecurityCIDRs struct{}
+
+func (FixerAmazonTemporarySecurityCIDRs) DeprecatedOptions() map[string][]string {
+ return map[string][]string{
+ "*amazon*": []string{"temporary_security_group_source_cidr"},
+ }
+}
+
+func (FixerAmazonTemporarySecurityCIDRs) Fix(input map[string]interface{}) (map[string]interface{}, error) {
+ // Our template type we'll use for this fixer only
+ type template struct {
+ Builders []map[string]interface{}
+ }
+
+ // Decode the input into our structure, if we can
+ var tpl template
+ if err := mapstructure.Decode(input, &tpl); err != nil {
+ return nil, err
+ }
+
+ // Go through each builder and replace the temporary_security_group_source_cidr if we can
+ for _, builder := range tpl.Builders {
+ builderTypeRaw, ok := builder["type"]
+ if !ok {
+ continue
+ }
+
+ builderType, ok := builderTypeRaw.(string)
+ if !ok {
+ continue
+ }
+
+ if !strings.HasPrefix(builderType, "amazon-") {
+ continue
+ }
+
+ temporarySecurityGroupCIDR, ok := builder["temporary_security_group_source_cidr"].(string)
+ if !ok {
+ continue
+ }
+
+ delete(builder, "temporary_security_group_source_cidr")
+ builder["temporary_security_group_source_cidrs"] = []string{temporarySecurityGroupCIDR}
+ }
+
+ input["builders"] = tpl.Builders
+ return input, nil
+}
+
+func (FixerAmazonTemporarySecurityCIDRs) Synopsis() string {
+ return `Replaces "temporary_security_group_source_cidr" (string) with "temporary_security_group_source_cidrs" (list of strings)`
+}
diff --git a/v1.9.4/fix/fixer_amazon_temporary_security_group_cidrs_test.go b/v1.9.4/fix/fixer_amazon_temporary_security_group_cidrs_test.go
new file mode 100644
index 0000000..2ed9f4b
--- /dev/null
+++ b/v1.9.4/fix/fixer_amazon_temporary_security_group_cidrs_test.go
@@ -0,0 +1,53 @@
+// Copyright (c) HashiCorp, Inc.
+// SPDX-License-Identifier: MPL-2.0
+
+package fix
+
+import (
+ "reflect"
+ "testing"
+)
+
+func TestFixerAmazonTemporarySecurityCIDRs_Impl(t *testing.T) {
+ var _ Fixer = new(FixerAmazonTemporarySecurityCIDRs)
+}
+
+func TestFixerAmazonTemporarySecurityCIDRs(t *testing.T) {
+ cases := []struct {
+ Input map[string]interface{}
+ Expected map[string]interface{}
+ }{
+ {
+ Input: map[string]interface{}{
+ "type": "amazon-ebs",
+ "temporary_security_group_source_cidr": "0.0.0.0/0",
+ },
+
+ Expected: map[string]interface{}{
+ "type": "amazon-ebs",
+ "temporary_security_group_source_cidrs": []string{"0.0.0.0/0"},
+ },
+ },
+ }
+
+ for _, tc := range cases {
+ var f FixerAmazonTemporarySecurityCIDRs
+
+ input := map[string]interface{}{
+ "builders": []map[string]interface{}{tc.Input},
+ }
+
+ expected := map[string]interface{}{
+ "builders": []map[string]interface{}{tc.Expected},
+ }
+
+ output, err := f.Fix(input)
+ if err != nil {
+ t.Fatalf("err: %s", err)
+ }
+
+ if !reflect.DeepEqual(output, expected) {
+ t.Fatalf("unexpected: %#v\nexpected: %#v\n", output, expected)
+ }
+ }
+}
diff --git a/v1.9.4/fix/fixer_azure_exclude_from_latest.go b/v1.9.4/fix/fixer_azure_exclude_from_latest.go
new file mode 100644
index 0000000..210b59f
--- /dev/null
+++ b/v1.9.4/fix/fixer_azure_exclude_from_latest.go
@@ -0,0 +1,75 @@
+// Copyright (c) HashiCorp, Inc.
+// SPDX-License-Identifier: MPL-2.0
+
+package fix
+
+import (
+ "strings"
+
+ "github.com/mitchellh/mapstructure"
+)
+
+// FixerAzureExcludeFromLatest fix the spelling of "exclude_from_latest"
+// template in an Azure builder
+type FixerAzureExcludeFromLatest struct{}
+
+func (FixerAzureExcludeFromLatest) DeprecatedOptions() map[string][]string {
+ return map[string][]string{
+ "Azure*": []string{"exlude_from_latest"},
+ }
+}
+
+func (FixerAzureExcludeFromLatest) Fix(input map[string]interface{}) (map[string]interface{}, error) {
+ // The type we'll decode into; we only care about builders
+ type template struct {
+ Builders []map[string]interface{}
+ }
+
+ // Decode the input into our structure, if we can
+ var tpl template
+ if err := mapstructure.Decode(input, &tpl); err != nil {
+ return nil, err
+ }
+
+ for _, builder := range tpl.Builders {
+ builderTypeRaw, ok := builder["type"]
+ if !ok {
+ continue
+ }
+
+ builderType, ok := builderTypeRaw.(string)
+ if !ok {
+ continue
+ }
+
+ if !strings.HasPrefix(builderType, "azure-chroot") {
+ continue
+ }
+
+ if !strings.HasPrefix(builderType, "azure-chroot") {
+ continue
+ }
+
+ sharedImageDestination, ok := builder["shared_image_destination"].(map[string]interface{})
+ if !ok {
+ continue
+ }
+
+ excludeFromLatest, ok := sharedImageDestination["exlude_from_latest"]
+ if !ok {
+ continue
+ }
+
+ sharedImageDestination["exclude_from_latest"] = excludeFromLatest
+ delete(sharedImageDestination, "exlude_from_latest")
+
+ builder["shared_image_destination"] = sharedImageDestination
+ }
+
+ input["builders"] = tpl.Builders
+ return input, nil
+}
+
+func (FixerAzureExcludeFromLatest) Synopsis() string {
+ return `Changes "exlude_from_latest" to "exclude_from_latest" in Azure builders.`
+}
diff --git a/v1.9.4/fix/fixer_azure_exclude_from_latest_test.go b/v1.9.4/fix/fixer_azure_exclude_from_latest_test.go
new file mode 100644
index 0000000..a3cd70d
--- /dev/null
+++ b/v1.9.4/fix/fixer_azure_exclude_from_latest_test.go
@@ -0,0 +1,69 @@
+// Copyright (c) HashiCorp, Inc.
+// SPDX-License-Identifier: MPL-2.0
+
+package fix
+
+import (
+ "reflect"
+ "testing"
+)
+
+func TestFixerAzureExcludeFromLatest(t *testing.T) {
+ var _ Fixer = new(FixerAzureExcludeFromLatest)
+}
+
+func TestFixerAzureExcludeFromLatest_Fix_exlude_from_latest(t *testing.T) {
+ cases := []struct {
+ Input map[string]interface{}
+ Expected map[string]interface{}
+ }{
+ // No shared_image_destination field
+ {
+ Input: map[string]interface{}{
+ "type": "azure-chroot",
+ },
+
+ Expected: map[string]interface{}{
+ "type": "azure-chroot",
+ },
+ },
+
+ // exlude_from_latest field
+ {
+ Input: map[string]interface{}{
+ "type": "azure-chroot",
+ "shared_image_destination": map[string]interface{}{
+ "exlude_from_latest": "false",
+ },
+ },
+
+ Expected: map[string]interface{}{
+ "type": "azure-chroot",
+ "shared_image_destination": map[string]interface{}{
+ "exclude_from_latest": "false",
+ },
+ },
+ },
+ }
+
+ for _, tc := range cases {
+ var f FixerAzureExcludeFromLatest
+
+ input := map[string]interface{}{
+ "builders": []map[string]interface{}{tc.Input},
+ }
+
+ expected := map[string]interface{}{
+ "builders": []map[string]interface{}{tc.Expected},
+ }
+
+ output, err := f.Fix(input)
+ if err != nil {
+ t.Fatalf("err: %s", err)
+ }
+
+ if !reflect.DeepEqual(output, expected) {
+ t.Fatalf("unexpected: %#v\nexpected: %#v\n", output, expected)
+ }
+ }
+}
diff --git a/v1.9.4/fix/fixer_clean_image_name.go b/v1.9.4/fix/fixer_clean_image_name.go
new file mode 100644
index 0000000..423d2e3
--- /dev/null
+++ b/v1.9.4/fix/fixer_clean_image_name.go
@@ -0,0 +1,73 @@
+// Copyright (c) HashiCorp, Inc.
+// SPDX-License-Identifier: MPL-2.0
+
+package fix
+
+import (
+ "fmt"
+ "regexp"
+
+ "github.com/mitchellh/mapstructure"
+)
+
+// FixerCleanImageName is a Fixer that replaces the "clean_(image|ami)_name" template
+// calls with "clean_resource_name"
+type FixerCleanImageName struct{}
+
+func (FixerCleanImageName) DeprecatedOptions() map[string][]string {
+ return map[string][]string{
+ "*amazon*": []string{"clean_ami_name"},
+ "packer.googlecompute": []string{"clean_image_name"},
+ "Azure*": []string{"clean_image_name"},
+ }
+}
+
+func (FixerCleanImageName) Fix(input map[string]interface{}) (map[string]interface{}, error) {
+ // Our template type we'll use for this fixer only
+ type template struct {
+ Builders []map[string]interface{}
+ }
+
+ // Decode the input into our structure, if we can
+ var tpl template
+ if err := mapstructure.Decode(input, &tpl); err != nil {
+ return nil, err
+ }
+
+ re := regexp.MustCompile(`clean_(image|ami)_name`)
+
+ // Go through each builder and replace CreateTime if we can
+ for _, builder := range tpl.Builders {
+ for key, value := range builder {
+ switch v := value.(type) {
+ case string:
+ changed := re.ReplaceAllString(v, "clean_resource_name")
+ builder[key] = changed
+ case map[string]string:
+ for k := range v {
+ v[k] = re.ReplaceAllString(v[k], "clean_resource_name")
+ }
+ builder[key] = v
+ case map[string]interface{}:
+ for k := range v {
+ if s, ok := v[k].(string); ok {
+ v[k] = re.ReplaceAllString(s, "clean_resource_name")
+ }
+ }
+ builder[key] = v
+ default:
+ if key == "image_labels" {
+
+ panic(fmt.Sprintf("value: %#v", value))
+ }
+ }
+ }
+ }
+
+ input["builders"] = tpl.Builders
+ return input, nil
+}
+
+func (FixerCleanImageName) Synopsis() string {
+ return `Replaces /clean_(image|ami)_name/ in builder configs with "clean_resource_name"`
+}
diff --git a/v1.9.4/fix/fixer_clean_image_name_test.go b/v1.9.4/fix/fixer_clean_image_name_test.go
new file mode 100644
index 0000000..385e6f1
--- /dev/null
+++ b/v1.9.4/fix/fixer_clean_image_name_test.go
@@ -0,0 +1,55 @@
+// Copyright (c) HashiCorp, Inc.
+// SPDX-License-Identifier: MPL-2.0
+
+package fix
+
+import (
+ "testing"
+
+ "github.com/google/go-cmp/cmp"
+)
+
+func TestFixerCleanImageName_Impl(t *testing.T) {
+ var raw interface{}
+ raw = new(FixerCleanImageName)
+ if _, ok := raw.(Fixer); !ok {
+ t.Fatalf("must be a Fixer")
+ }
+}
+
+func TestFixerCleanImageName_Fix(t *testing.T) {
+ var f FixerCleanImageName
+
+ input := map[string]interface{}{
+ "builders": []interface{}{
+ map[string]interface{}{
+ "type": "foo",
+ "ami_name": "heyo clean_image_name",
+ "image_labels": map[string]interface{}{
+ "name": "test-packer-{{packer_version | clean_image_name}}",
+ },
+ },
+ },
+ }
+
+ expected := map[string]interface{}{
+ "builders": []map[string]interface{}{
+ {
+ "type": "foo",
+ "ami_name": "heyo clean_resource_name",
+ "image_labels": map[string]interface{}{
+ "name": "test-packer-{{packer_version | clean_resource_name}}",
+ },
+ },
+ },
+ }
+
+ output, err := f.Fix(input)
+ if err != nil {
+ t.Fatalf("err: %s", err)
+ }
+
+ if diff := cmp.Diff(expected, output); diff != "" {
+ t.Fatalf("unexpected output: %s", diff)
+ }
+}
diff --git a/v1.9.4/fix/fixer_comm_config.go b/v1.9.4/fix/fixer_comm_config.go
new file mode 100644
index 0000000..6f2c49a
--- /dev/null
+++ b/v1.9.4/fix/fixer_comm_config.go
@@ -0,0 +1,112 @@
+// Copyright (c) HashiCorp, Inc.
+// SPDX-License-Identifier: MPL-2.0
+
+package fix
+
+import (
+ "strings"
+
+ "github.com/mitchellh/mapstructure"
+)
+
+// FixerCommConfig removes ssh prefix from communicator port forwarding config
+// for variables host_port_min, host_port_max, skip_nat_mapping
+type FixerCommConfig struct{}
+
+func (FixerCommConfig) DeprecatedOptions() map[string][]string {
+ return map[string][]string{
+ "*": []string{"ssh_host_port_min", "ssh_host_port_max",
+ "ssh_skip_nat_mapping"},
+ }
+}
+
+func (FixerCommConfig) Fix(input map[string]interface{}) (map[string]interface{}, error) {
+ type template struct {
+ Builders []interface{}
+ }
+
+ // Decode the input into our structure, if we can
+ var tpl template
+ if err := mapstructure.WeakDecode(input, &tpl); err != nil {
+ return nil, err
+ }
+
+ for i, raw := range tpl.Builders {
+ var builders map[string]interface{}
+ if err := mapstructure.Decode(raw, &builders); err != nil {
+ // Ignore errors, could be a non-map
+ continue
+ }
+
+ // only virtualbox builders
+ builderType := builders["type"].(string)
+ if ok := strings.HasPrefix(builderType, "virtualbox"); !ok {
+ continue
+ }
+
+ // ssh_host_port_min to host_port_min
+ if _, ok := builders["host_port_min"]; ok {
+
+ // drop ssh_host_port_min if it is also included
+ if _, sshHostPortMinIncluded := builders["ssh_host_port_min"]; sshHostPortMinIncluded {
+ delete(builders, "ssh_host_port_min")
+ }
+
+ } else if _, ok := builders["ssh_host_port_min"]; ok {
+
+ // replace ssh_host_port_min with host_port_min
+ sshHostPortMinRaw := builders["ssh_host_port_min"]
+ delete(builders, "ssh_host_port_min")
+ builders["host_port_min"] = sshHostPortMinRaw
+ }
+
+ // ssh_host_port_max to host_port_max
+ if _, ok := builders["host_port_max"]; ok {
+
+ // drop ssh_host_port_max if it is also included
+ if _, sshHostPortMaxIncluded := builders["ssh_host_port_max"]; sshHostPortMaxIncluded {
+ delete(builders, "ssh_host_port_max")
+ }
+
+ } else if _, ok := builders["ssh_host_port_max"]; ok {
+
+ // replace ssh_host_port_max with host_port_max
+ sshHostPortMaxRaw := builders["ssh_host_port_max"]
+ delete(builders, "ssh_host_port_max")
+ builders["host_port_max"] = sshHostPortMaxRaw
+
+ }
+
+ // ssh_skip_nat_mapping to skip_nat_mapping
+ if _, ok := builders["skip_nat_mapping"]; ok {
+
+ // drop ssh_skip_nat_mapping if it is also included
+ if _, sshSkipNatMappingIncluded := builders["ssh_skip_nat_mapping"]; sshSkipNatMappingIncluded {
+ delete(builders, "ssh_skip_nat_mapping")
+ }
+
+ } else if _, ok := builders["ssh_skip_nat_mapping"]; ok {
+
+ // replace ssh_skip_nat_mapping with skip_nat_mapping
+ sshSkipNatMappingRaw := builders["ssh_skip_nat_mapping"]
+ sshSkipNatMappingBool, ok := sshSkipNatMappingRaw.(bool)
+ if ok {
+ delete(builders, "ssh_skip_nat_mapping")
+ builders["skip_nat_mapping"] = sshSkipNatMappingBool
+ }
+ }
+
+ // Write all changes back to template
+ tpl.Builders[i] = builders
+ }
+
+ if len(tpl.Builders) > 0 {
+ input["builders"] = tpl.Builders
+ }
+
+ return input, nil
+}
+
+func (FixerCommConfig) Synopsis() string {
+ return `Remove ssh prefixes from communicator port forwarding configuration (host_port_min, host_port_max, skip_nat_mapping)`
+}
diff --git a/v1.9.4/fix/fixer_comm_config_test.go b/v1.9.4/fix/fixer_comm_config_test.go
new file mode 100644
index 0000000..52beb05
--- /dev/null
+++ b/v1.9.4/fix/fixer_comm_config_test.go
@@ -0,0 +1,164 @@
+// Copyright (c) HashiCorp, Inc.
+// SPDX-License-Identifier: MPL-2.0
+
+package fix
+
+import (
+ "reflect"
+ "testing"
+)
+
+func TestFixerCommConfig_Impl(t *testing.T) {
+ var _ Fixer = new(FixerCommConfig)
+}
+
+func TestFixerCommConfig_Fix(t *testing.T) {
+ cases := []struct {
+ Input map[string]interface{}
+ Expected map[string]interface{}
+ }{
+ // set host_port_min
+ {
+ Input: map[string]interface{}{
+ "type": "virtualbox-iso",
+ "host_port_min": 2222,
+ },
+
+ Expected: map[string]interface{}{
+ "type": "virtualbox-iso",
+ "host_port_min": 2222,
+ },
+ },
+
+ // set ssh_host_port_min (old key)
+ {
+ Input: map[string]interface{}{
+ "type": "virtualbox-ovf",
+ "ssh_host_port_min": 2222,
+ },
+
+ Expected: map[string]interface{}{
+ "type": "virtualbox-ovf",
+ "host_port_min": 2222,
+ },
+ },
+
+ // set ssh_host_port_min and host_port_min
+ // host_port_min takes precedence
+ {
+ Input: map[string]interface{}{
+ "type": "virtualbox-vm",
+ "ssh_host_port_min": 1234,
+ "host_port_min": 4321,
+ },
+
+ Expected: map[string]interface{}{
+ "type": "virtualbox-vm",
+ "host_port_min": 4321,
+ },
+ },
+
+ // set host_port_max
+ {
+ Input: map[string]interface{}{
+ "type": "virtualbox-iso",
+ "host_port_max": 4444,
+ },
+
+ Expected: map[string]interface{}{
+ "type": "virtualbox-iso",
+ "host_port_max": 4444,
+ },
+ },
+
+ // set ssh_host_port_max (old key)
+ {
+ Input: map[string]interface{}{
+ "type": "virtualbox-iso",
+ "ssh_host_port_max": 4444,
+ },
+
+ Expected: map[string]interface{}{
+ "type": "virtualbox-iso",
+ "host_port_max": 4444,
+ },
+ },
+
+ // set ssh_host_port_max and host_port_max
+ // host_port_max takes precedence
+ {
+ Input: map[string]interface{}{
+ "type": "virtualbox-vm",
+ "ssh_host_port_max": 1234,
+ "host_port_max": 4321,
+ },
+
+ Expected: map[string]interface{}{
+ "type": "virtualbox-vm",
+ "host_port_max": 4321,
+ },
+ },
+
+ // set skip_nat_mapping
+ {
+ Input: map[string]interface{}{
+ "type": "virtualbox-vm",
+ "skip_nat_mapping": true,
+ },
+
+ Expected: map[string]interface{}{
+ "type": "virtualbox-vm",
+ "skip_nat_mapping": true,
+ },
+ },
+
+ // set ssh_skip_nat_mapping (old key)
+ {
+ Input: map[string]interface{}{
+ "type": "virtualbox-vm",
+ "ssh_skip_nat_mapping": true,
+ },
+
+ Expected: map[string]interface{}{
+ "type": "virtualbox-vm",
+ "skip_nat_mapping": true,
+ },
+ },
+
+ // set ssh_skip_nat_mapping and skip_nat_mapping
+ // skip_nat_mapping takes precedence
+ {
+ Input: map[string]interface{}{
+ "type": "virtualbox-iso",
+ "ssh_skip_nat_mapping": false,
+ "skip_nat_mapping": true,
+ },
+
+ Expected: map[string]interface{}{
+ "type": "virtualbox-iso",
+ "skip_nat_mapping": true,
+ },
+ },
+ }
+
+ for _, tc := range cases {
+ var f FixerCommConfig
+
+ input := map[string]interface{}{
+ "builders": []interface{}{tc.Input},
+ }
+
+ expected := map[string]interface{}{
+ "builders": []interface{}{tc.Expected},
+ }
+
+ output, err := f.Fix(input)
+ if err != nil {
+ t.Fatalf("err: %s", err)
+ }
+
+ if !reflect.DeepEqual(output, expected) {
+ t.Fatalf("unexpected: %#v\nexpected: %#v\n", output, expected)
+ }
+ }
+}
diff --git a/v1.9.4/fix/fixer_createtime.go b/v1.9.4/fix/fixer_createtime.go
new file mode 100644
index 0000000..0412c4d
--- /dev/null
+++ b/v1.9.4/fix/fixer_createtime.go
@@ -0,0 +1,63 @@
+// Copyright (c) HashiCorp, Inc.
+// SPDX-License-Identifier: MPL-2.0
+
+package fix
+
+import (
+ "regexp"
+
+ "github.com/mitchellh/mapstructure"
+)
+
+// FixerCreateTime is a Fixer that replaces the ".CreateTime" template
+// calls with "{{timestamp}"
+type FixerCreateTime struct{}
+
+func (FixerCreateTime) DeprecatedOptions() map[string][]string {
+ return map[string][]string{}
+}
+
+func (FixerCreateTime) Fix(input map[string]interface{}) (map[string]interface{}, error) {
+ // Our template type we'll use for this fixer only
+ type template struct {
+ Builders []map[string]interface{}
+ }
+
+ // Decode the input into our structure, if we can
+ var tpl template
+ if err := mapstructure.Decode(input, &tpl); err != nil {
+ return nil, err
+ }
+
+ badKeys := []string{
+ "ami_name",
+ "bundle_prefix",
+ "snapshot_name",
+ }
+
+ re := regexp.MustCompile(`{{\s*\.CreateTime\s*}}`)
+
+ // Go through each builder and replace CreateTime if we can
+ for _, builder := range tpl.Builders {
+ for _, key := range badKeys {
+ raw, ok := builder[key]
+ if !ok {
+ continue
+ }
+
+ v, ok := raw.(string)
+ if !ok {
+ continue
+ }
+
+ builder[key] = re.ReplaceAllString(v, "{{timestamp}}")
+ }
+ }
+
+ input["builders"] = tpl.Builders
+ return input, nil
+}
+
+func (FixerCreateTime) Synopsis() string {
+ return `Replaces ".CreateTime" in builder configs with "{{timestamp}}"`
+}
diff --git a/v1.9.4/fix/fixer_createtime_test.go b/v1.9.4/fix/fixer_createtime_test.go
new file mode 100644
index 0000000..a735096
--- /dev/null
+++ b/v1.9.4/fix/fixer_createtime_test.go
@@ -0,0 +1,48 @@
+// Copyright (c) HashiCorp, Inc.
+// SPDX-License-Identifier: MPL-2.0
+
+package fix
+
+import (
+ "reflect"
+ "testing"
+)
+
+func TestFixerCreateTime_Impl(t *testing.T) {
+ var raw interface{}
+ raw = new(FixerCreateTime)
+ if _, ok := raw.(Fixer); !ok {
+ t.Fatalf("must be a Fixer")
+ }
+}
+
+func TestFixerCreateTime_Fix(t *testing.T) {
+ var f FixerCreateTime
+
+ input := map[string]interface{}{
+ "builders": []interface{}{
+ map[string]string{
+ "type": "foo",
+ "ami_name": "{{.CreateTime}} foo",
+ },
+ },
+ }
+
+ expected := map[string]interface{}{
+ "builders": []map[string]interface{}{
+ {
+ "type": "foo",
+ "ami_name": "{{timestamp}} foo",
+ },
+ },
+ }
+
+ output, err := f.Fix(input)
+ if err != nil {
+ t.Fatalf("err: %s", err)
+ }
+
+ if !reflect.DeepEqual(output, expected) {
+ t.Fatalf("unexpected: %#v\nexpected: %#v\n", output, expected)
+ }
+}
diff --git a/v1.9.4/fix/fixer_docker_email.go b/v1.9.4/fix/fixer_docker_email.go
new file mode 100644
index 0000000..3a5883f
--- /dev/null
+++ b/v1.9.4/fix/fixer_docker_email.go
@@ -0,0 +1,62 @@
+// Copyright (c) HashiCorp, Inc.
+// SPDX-License-Identifier: MPL-2.0
+
+package fix
+
+import "github.com/mitchellh/mapstructure"
+
+type FixerDockerEmail struct{}
+
+func (FixerDockerEmail) DeprecatedOptions() map[string][]string {
+ return map[string][]string{
+ "packer.docker": []string{"login_email"},
+ "packer.post-processor.docker-import": []string{"login_email"},
+ }
+
+}
+
+func (FixerDockerEmail) Fix(input map[string]interface{}) (map[string]interface{}, error) {
+ if input["post-processors"] == nil {
+ return input, nil
+ }
+
+ // Our template type we'll use for this fixer only
+ type template struct {
+ Builders []map[string]interface{}
+ PP `mapstructure:",squash"`
+ }
+
+ // Decode the input into our structure, if we can
+ var tpl template
+ if err := mapstructure.Decode(input, &tpl); err != nil {
+ return nil, err
+ }
+
+ // Go through each builder and delete `docker_login` if present
+ for _, builder := range tpl.Builders {
+ _, ok := builder["login_email"]
+ if !ok {
+ continue
+ }
+ delete(builder, "login_email")
+ }
+
+ // Go through each post-processor and delete `docker_login` if present
+ pps := tpl.ppList()
+
+ for _, pp := range pps {
+ _, ok := pp["login_email"]
+ if !ok {
+ continue
+ }
+ delete(pp, "login_email")
+ }
+
+ input["builders"] = tpl.Builders
+ input["post-processors"] = tpl.PostProcessors
+ return input, nil
+}
+
+func (FixerDockerEmail) Synopsis() string {
+ return `Removes "login_email" from the Docker builder.`
+}
diff --git a/v1.9.4/fix/fixer_galaxy_command.go b/v1.9.4/fix/fixer_galaxy_command.go
new file mode 100644
index 0000000..f5988d9
--- /dev/null
+++ b/v1.9.4/fix/fixer_galaxy_command.go
@@ -0,0 +1,79 @@
+// Copyright (c) HashiCorp, Inc.
+// SPDX-License-Identifier: MPL-2.0
+
+package fix
+
+import (
+ "github.com/mitchellh/mapstructure"
+)
+
+// FixerGalaxyCommand removes the escape character from user
+// environment variables and replace galaxycommand with galaxy_command
+type FixerGalaxyCommand struct{}
+
+func (FixerGalaxyCommand) DeprecatedOptions() map[string][]string {
+ return map[string][]string{
+ "ansible": []string{"galaxycommand"},
+ }
+}
+
+func (FixerGalaxyCommand) Fix(input map[string]interface{}) (map[string]interface{}, error) {
+ type template struct {
+ Provisioners []interface{}
+ }
+
+ // Decode the input into our structure, if we can
+ var tpl template
+ if err := mapstructure.WeakDecode(input, &tpl); err != nil {
+ return nil, err
+ }
+
+ for i, raw := range tpl.Provisioners {
+ var provisioners map[string]interface{}
+ if err := mapstructure.Decode(raw, &provisioners); err != nil {
+ // Ignore errors, could be a non-map
+ continue
+ }
+
+ if ok := provisioners["type"] == "ansible-local"; !ok {
+ continue
+ }
+
+ if _, ok := provisioners["galaxy_command"]; ok {
+
+ // drop galaxycommand if it is also included
+ if _, galaxyCommandIncluded := provisioners["galaxycommand"]; galaxyCommandIncluded {
+ delete(provisioners, "galaxycommand")
+ }
+
+ } else {
+
+ // replace galaxycommand with galaxy_command if it exists
+ galaxyCommandRaw, ok := provisioners["galaxycommand"]
+ if !ok {
+ continue
+ }
+
+ galaxyCommandString, ok := galaxyCommandRaw.(string)
+ if !ok {
+ continue
+ }
+
+ delete(provisioners, "galaxycommand")
+ provisioners["galaxy_command"] = galaxyCommandString
+ }
+
+ // Write all changes back to template
+ tpl.Provisioners[i] = provisioners
+ }
+
+ if len(tpl.Provisioners) > 0 {
+ input["provisioners"] = tpl.Provisioners
+ }
+
+ return input, nil
+}
+
+func (FixerGalaxyCommand) Synopsis() string {
+ return `Replaces "galaxycommand" in ansible-local provisioner configs with "galaxy_command"`
+}
diff --git a/v1.9.4/fix/fixer_galaxy_command_test.go b/v1.9.4/fix/fixer_galaxy_command_test.go
new file mode 100644
index 0000000..ee067b1
--- /dev/null
+++ b/v1.9.4/fix/fixer_galaxy_command_test.go
@@ -0,0 +1,82 @@
+// Copyright (c) HashiCorp, Inc.
+// SPDX-License-Identifier: MPL-2.0
+
+package fix
+
+import (
+ "reflect"
+ "testing"
+)
+
+func TestFixerGalaxyCommand_Impl(t *testing.T) {
+ var _ Fixer = new(FixerGalaxyCommand)
+}
+
+func TestFixerGalaxyCommand_Fix(t *testing.T) {
+ cases := []struct {
+ Input map[string]interface{}
+ Expected map[string]interface{}
+ }{
+ // set galaxy_command
+ {
+ Input: map[string]interface{}{
+ "type": "ansible-local",
+ "galaxy_command": "/usr/local/bin/ansible-galaxy",
+ },
+
+ Expected: map[string]interface{}{
+ "type": "ansible-local",
+ "galaxy_command": "/usr/local/bin/ansible-galaxy",
+ },
+ },
+
+ // set galaxycommand (old key)
+ {
+ Input: map[string]interface{}{
+ "type": "ansible-local",
+ "galaxycommand": "/usr/bin/ansible-galaxy",
+ },
+
+ Expected: map[string]interface{}{
+ "type": "ansible-local",
+ "galaxy_command": "/usr/bin/ansible-galaxy",
+ },
+ },
+
+ // set galaxy_command and galaxycommand
+ // galaxy_command takes precedence
+ {
+ Input: map[string]interface{}{
+ "type": "ansible-local",
+ "galaxy_command": "ansible_galaxy_command",
+ "galaxycommand": "ansible_galaxycommand",
+ },
+
+ Expected: map[string]interface{}{
+ "type": "ansible-local",
+ "galaxy_command": "ansible_galaxy_command",
+ },
+ },
+ }
+
+ for _, tc := range cases {
+ var f FixerGalaxyCommand
+
+ input := map[string]interface{}{
+ "provisioners": []interface{}{tc.Input},
+ }
+
+ expected := map[string]interface{}{
+ "provisioners": []interface{}{tc.Expected},
+ }
+
+ output, err := f.Fix(input)
+ if err != nil {
+ t.Fatalf("err: %s", err)
+ }
+
+ if !reflect.DeepEqual(output, expected) {
+ t.Fatalf("unexpected: %#v\nexpected: %#v\n", output, expected)
+ }
+ }
+}
diff --git a/v1.9.4/fix/fixer_hyperv_cpu_and_ram_naming.go b/v1.9.4/fix/fixer_hyperv_cpu_and_ram_naming.go
new file mode 100644
index 0000000..4983b5c
--- /dev/null
+++ b/v1.9.4/fix/fixer_hyperv_cpu_and_ram_naming.go
@@ -0,0 +1,66 @@
+// Copyright (c) HashiCorp, Inc.
+// SPDX-License-Identifier: MPL-2.0
+
+package fix
+
+import (
+ "github.com/mitchellh/mapstructure"
+)
+
+// FizerHypervCPUandRAM changes `cpu` to `cpus` and `ram_size` to `memory`
+type FizerHypervCPUandRAM struct{}
+
+func (FizerHypervCPUandRAM) DeprecatedOptions() map[string][]string {
+ return map[string][]string{
+ "MSOpenTech.hyperv": []string{"cpu", "ram_size"},
+ }
+}
+
+func (FizerHypervCPUandRAM) Fix(input map[string]interface{}) (map[string]interface{}, error) {
+ // The type we'll decode into; we only care about builders
+ type template struct {
+ Builders []map[string]interface{}
+ }
+
+ // Decode the input into our structure, if we can
+ var tpl template
+ if err := mapstructure.Decode(input, &tpl); err != nil {
+ return nil, err
+ }
+
+ for _, builder := range tpl.Builders {
+ builderTypeRaw, ok := builder["type"]
+ if !ok {
+ continue
+ }
+
+ builderType, ok := builderTypeRaw.(string)
+ if !ok {
+ continue
+ }
+
+ if builderType != "hyperv-vmcx" && builderType != "hyperv-iso" {
+ continue
+ }
+
+ ncpus, ok := builder["cpu"]
+ if ok {
+ delete(builder, "cpu")
+ builder["cpus"] = ncpus
+ }
+
+ memory, ok := builder["ram_size"]
+ if ok {
+ delete(builder, "ram_size")
+ builder["memory"] = memory
+ }
+ }
+
+ input["builders"] = tpl.Builders
+ return input, nil
+}
+
+func (FizerHypervCPUandRAM) Synopsis() string {
+ return `Replaces "cpu" with "cpus" and "ram_size" with "memory"` +
+ `in Hyper-V VMCX builder templates`
+}
diff --git a/v1.9.4/fix/fixer_hyperv_deprecations.go b/v1.9.4/fix/fixer_hyperv_deprecations.go
new file mode 100644
index 0000000..12714d9
--- /dev/null
+++ b/v1.9.4/fix/fixer_hyperv_deprecations.go
@@ -0,0 +1,59 @@
+// Copyright (c) HashiCorp, Inc.
+// SPDX-License-Identifier: MPL-2.0
+
+package fix
+
+import (
+ "github.com/mitchellh/mapstructure"
+)
+
+// FixerHypervDeprecations removes the deprecated "vhd_temp_path" setting
+// from Hyper-V ISO builder templates
+type FixerHypervDeprecations struct{}
+
+func (FixerHypervDeprecations) DeprecatedOptions() map[string][]string {
+ return map[string][]string{
+ "MSOpenTech.hyperv": []string{"vhd_temp_path"},
+ }
+}
+
+func (FixerHypervDeprecations) Fix(input map[string]interface{}) (map[string]interface{}, error) {
+ // The type we'll decode into; we only care about builders
+ type template struct {
+ Builders []map[string]interface{}
+ }
+
+ // Decode the input into our structure, if we can
+ var tpl template
+ if err := mapstructure.Decode(input, &tpl); err != nil {
+ return nil, err
+ }
+
+ for _, builder := range tpl.Builders {
+ builderTypeRaw, ok := builder["type"]
+ if !ok {
+ continue
+ }
+
+ builderType, ok := builderTypeRaw.(string)
+ if !ok {
+ continue
+ }
+
+ if builderType != "hyperv-iso" {
+ continue
+ }
+
+ _, ok = builder["vhd_temp_path"]
+ if ok {
+ delete(builder, "vhd_temp_path")
+ }
+ }
+
+ input["builders"] = tpl.Builders
+ return input, nil
+}
+
+func (FixerHypervDeprecations) Synopsis() string {
+ return `Removes the deprecated "vhd_temp_path" setting from Hyper-V ISO builder templates`
+}
diff --git a/v1.9.4/fix/fixer_hyperv_deprecations_test.go b/v1.9.4/fix/fixer_hyperv_deprecations_test.go
new file mode 100644
index 0000000..00154e2
--- /dev/null
+++ b/v1.9.4/fix/fixer_hyperv_deprecations_test.go
@@ -0,0 +1,63 @@
+// Copyright (c) HashiCorp, Inc.
+// SPDX-License-Identifier: MPL-2.0
+
+package fix
+
+import (
+ "testing"
+
+ "github.com/stretchr/testify/assert"
+)
+
+func TestFixerHypervDeprecations_impl(t *testing.T) {
+ var _ Fixer = new(FixerHypervDeprecations)
+}
+
+func TestFixerHypervDeprecations_Fix(t *testing.T) {
+ cases := []struct {
+ Input map[string]interface{}
+ Expected map[string]interface{}
+ }{
+ // No vhd_temp_path field in template - noop
+ {
+ Input: map[string]interface{}{
+ "type": "hyperv-iso",
+ },
+
+ Expected: map[string]interface{}{
+ "type": "hyperv-iso",
+ },
+ },
+
+ // Deprecated vhd_temp_path field in template should be deleted
+ {
+ Input: map[string]interface{}{
+ "type": "hyperv-iso",
+ "vhd_temp_path": "foopath",
+ },
+
+ Expected: map[string]interface{}{
+ "type": "hyperv-iso",
+ },
+ },
+ }
+
+ for _, tc := range cases {
+ var f FixerHypervDeprecations
+
+ input := map[string]interface{}{
+ "builders": []map[string]interface{}{tc.Input},
+ }
+
+ expected := map[string]interface{}{
+ "builders": []map[string]interface{}{tc.Expected},
+ }
+
+ output, err := f.Fix(input)
+ if err != nil {
+ t.Fatalf("err: %s", err)
+ }
+
+ assert.Equal(t, expected, output, "Should be equal")
+ }
+}
diff --git a/v1.9.4/fix/fixer_hyperv_vmxc_typo.go b/v1.9.4/fix/fixer_hyperv_vmxc_typo.go
new file mode 100644
index 0000000..f9c5d63
--- /dev/null
+++ b/v1.9.4/fix/fixer_hyperv_vmxc_typo.go
@@ -0,0 +1,61 @@
+// Copyright (c) HashiCorp, Inc.
+// SPDX-License-Identifier: MPL-2.0
+
+package fix
+
+import (
+ "github.com/mitchellh/mapstructure"
+)
+
+// FixerHypervVmxcTypo fixes the typo in "clone_from_vmxc_path" replacing
+// it with "clone_from_vmcx_path" in Hyper-V VMCX builder templates
+type FixerHypervVmxcTypo struct{}
+
+func (FixerHypervVmxcTypo) DeprecatedOptions() map[string][]string {
+ return map[string][]string{
+ "MSOpenTech.hyperv": []string{"clone_from_vmxc_path"},
+ }
+}
+
+func (FixerHypervVmxcTypo) Fix(input map[string]interface{}) (map[string]interface{}, error) {
+ // The type we'll decode into; we only care about builders
+ type template struct {
+ Builders []map[string]interface{}
+ }
+
+ // Decode the input into our structure, if we can
+ var tpl template
+ if err := mapstructure.Decode(input, &tpl); err != nil {
+ return nil, err
+ }
+
+ for _, builder := range tpl.Builders {
+ builderTypeRaw, ok := builder["type"]
+ if !ok {
+ continue
+ }
+
+ builderType, ok := builderTypeRaw.(string)
+ if !ok {
+ continue
+ }
+
+ if builderType != "hyperv-vmcx" {
+ continue
+ }
+
+ path, ok := builder["clone_from_vmxc_path"]
+ if ok {
+ delete(builder, "clone_from_vmxc_path")
+ builder["clone_from_vmcx_path"] = path
+ }
+ }
+
+ input["builders"] = tpl.Builders
+ return input, nil
+}
+
+func (FixerHypervVmxcTypo) Synopsis() string {
+ return `Fixes a typo replacing "clone_from_vmxc_path" with "clone_from_vmcx_path" ` +
+ `in Hyper-V VMCX builder templates`
+}
diff --git a/v1.9.4/fix/fixer_hyperv_vmxc_typo_test.go b/v1.9.4/fix/fixer_hyperv_vmxc_typo_test.go
new file mode 100644
index 0000000..1f7ac62
--- /dev/null
+++ b/v1.9.4/fix/fixer_hyperv_vmxc_typo_test.go
@@ -0,0 +1,67 @@
+// Copyright (c) HashiCorp, Inc.
+// SPDX-License-Identifier: MPL-2.0
+
+package fix
+
+import (
+ "testing"
+
+ "github.com/stretchr/testify/assert"
+)
+
+func TestFixerHypervVmxcTypo_impl(t *testing.T) {
+ var _ Fixer = new(FixerHypervVmxcTypo)
+}
+
+func TestFixerHypervVmxcTypo_Fix(t *testing.T) {
+ cases := []struct {
+ Input map[string]interface{}
+ Expected map[string]interface{}
+ }{
+ // No "clone_from_vmxc_path" in template - noop
+ {
+ Input: map[string]interface{}{
+ "type": "hyperv-vmcx",
+ "temp_path": "C:/some/temp/path",
+ },
+
+ Expected: map[string]interface{}{
+ "type": "hyperv-vmcx",
+ "temp_path": "C:/some/temp/path",
+ },
+ },
+
+ // "clone_from_vmxc_path" should be replaced with
+ // "clone_from_vmcx_path" in template
+ {
+ Input: map[string]interface{}{
+ "type": "hyperv-vmcx",
+ "clone_from_vmxc_path": "C:/some/vmcx/path",
+ },
+
+ Expected: map[string]interface{}{
+ "type": "hyperv-vmcx",
+ "clone_from_vmcx_path": "C:/some/vmcx/path",
+ },
+ },
+ }
+
+ for _, tc := range cases {
+ var f FixerHypervVmxcTypo
+
+ input := map[string]interface{}{
+ "builders": []map[string]interface{}{tc.Input},
+ }
+
+ expected := map[string]interface{}{
+ "builders": []map[string]interface{}{tc.Expected},
+ }
+
+ output, err := f.Fix(input)
+ if err != nil {
+ t.Fatalf("err: %s", err)
+ }
+
+ assert.Equal(t, expected, output, "Should be equal")
+ }
+}
diff --git a/v1.9.4/fix/fixer_iso_checksum_type_and_url.go b/v1.9.4/fix/fixer_iso_checksum_type_and_url.go
new file mode 100644
index 0000000..fc50055
--- /dev/null
+++ b/v1.9.4/fix/fixer_iso_checksum_type_and_url.go
@@ -0,0 +1,66 @@
+// Copyright (c) HashiCorp, Inc.
+// SPDX-License-Identifier: MPL-2.0
+
+package fix
+
+import (
+ "github.com/mitchellh/mapstructure"
+)
+
+// FixerISOChecksumTypeAndURL is a Fixer that remove the "iso_checksum_url" and
+// "iso_checksum_type" to put everything in the checksum field.
+type FixerISOChecksumTypeAndURL struct{}
+
+func (FixerISOChecksumTypeAndURL) DeprecatedOptions() map[string][]string {
+ return map[string][]string{
+ "*": []string{"iso_checksum_url", "iso_checksum_type"},
+ }
+}
+
+func (FixerISOChecksumTypeAndURL) Fix(input map[string]interface{}) (map[string]interface{}, error) {
+ // Our template type we'll use for this fixer only
+ type template struct {
+ Builders []map[string]interface{}
+ }
+
+ // Decode the input into our structure, if we can
+ var tpl template
+ if err := mapstructure.Decode(input, &tpl); err != nil {
+ return nil, err
+ }
+
+ // Go through each builder and replace the iso_md5 if we can
+ for _, builder := range tpl.Builders {
+ checksumUrl := stringValue(builder["iso_checksum_url"])
+ checksumType := stringValue(builder["iso_checksum_type"])
+ checksum := stringValue(builder["iso_checksum"])
+ delete(builder, "iso_checksum_url")
+ delete(builder, "iso_checksum_type")
+ if checksum == "" && checksumUrl == "" {
+ continue
+ }
+ if checksumUrl != "" {
+ checksum = "file:" + checksumUrl
+ } else if checksumType != "" {
+ checksum = checksumType + ":" + checksum
+ }
+
+ builder["iso_checksum"] = checksum
+ }
+
+ input["builders"] = tpl.Builders
+ return input, nil
+}
+
+func stringValue(v interface{}) string {
+ switch rfl := v.(type) {
+ case string:
+ return rfl
+ default:
+ return ""
+ }
+}
+
+func (FixerISOChecksumTypeAndURL) Synopsis() string {
+ return `Puts content of potential "iso_checksum_url" and "iso_checksum_url" in "iso_checksum"`
+}
diff --git a/v1.9.4/fix/fixer_iso_checksum_type_and_url_test.go b/v1.9.4/fix/fixer_iso_checksum_type_and_url_test.go
new file mode 100644
index 0000000..f3492dc
--- /dev/null
+++ b/v1.9.4/fix/fixer_iso_checksum_type_and_url_test.go
@@ -0,0 +1,85 @@
+// Copyright (c) HashiCorp, Inc.
+// SPDX-License-Identifier: MPL-2.0
+
+package fix
+
+import (
+ "testing"
+
+ "github.com/stretchr/testify/assert"
+)
+
+func TestFixerISOChecksumTypeAndURL_Impl(t *testing.T) {
+ var raw interface{}
+ raw = new(FixerISOChecksumTypeAndURL)
+ if _, ok := raw.(Fixer); !ok {
+ t.Fatalf("must be a Fixer")
+ }
+}
+
+func TestFixerISOChecksumTypeAndURL_Fix(t *testing.T) {
+
+ cases := []struct {
+ Input map[string]interface{}
+ Expected map[string]interface{}
+ }{
+
+ {
+ Input: map[string]interface{}{
+ "type": "foo",
+ "iso_checksum_url": "bar",
+ "iso_checksum_type": "ignored",
+ },
+
+ Expected: map[string]interface{}{
+ "type": "foo",
+ "iso_checksum": "file:bar",
+ },
+ },
+
+ {
+ Input: map[string]interface{}{
+ "type": "foo",
+ "iso_checksum": "checksum",
+ "iso_checksum_type": "md5",
+ },
+
+ Expected: map[string]interface{}{
+ "type": "foo",
+ "iso_checksum": "md5:checksum",
+ },
+ },
+
+ {
+ Input: map[string]interface{}{
+ "type": "foo",
+ "iso_checksum": "checksum",
+ "iso_checksum_url": "path/to/checksumfile",
+ },
+
+ Expected: map[string]interface{}{
+ "type": "foo",
+ "iso_checksum": "file:path/to/checksumfile",
+ },
+ },
+ }
+
+ for _, tc := range cases {
+ var f FixerISOChecksumTypeAndURL
+
+ input := map[string]interface{}{
+ "builders": []map[string]interface{}{tc.Input},
+ }
+
+ expected := map[string]interface{}{
+ "builders": []map[string]interface{}{tc.Expected},
+ }
+
+ output, err := f.Fix(input)
+ if err != nil {
+ t.Fatalf("err: %s", err)
+ }
+
+ assert.Equal(t, expected, output, "Should be equal")
+ }
+}
diff --git a/v1.9.4/fix/fixer_iso_md5.go b/v1.9.4/fix/fixer_iso_md5.go
new file mode 100644
index 0000000..074a0b2
--- /dev/null
+++ b/v1.9.4/fix/fixer_iso_md5.go
@@ -0,0 +1,56 @@
+// Copyright (c) HashiCorp, Inc.
+// SPDX-License-Identifier: MPL-2.0
+
+package fix
+
+import (
+ "github.com/mitchellh/mapstructure"
+)
+
+// FixerISOMD5 is a Fixer that replaces the "iso_md5" configuration key
+// with the newer "iso_checksum" and "iso_checksum_type" within builders.
+type FixerISOMD5 struct{}
+
+func (FixerISOMD5) DeprecatedOptions() map[string][]string {
+ return map[string][]string{
+ "*": []string{"iso_md5"},
+ }
+}
+
+func (FixerISOMD5) Fix(input map[string]interface{}) (map[string]interface{}, error) {
+ // Our template type we'll use for this fixer only
+ type template struct {
+ Builders []map[string]interface{}
+ }
+
+ // Decode the input into our structure, if we can
+ var tpl template
+ if err := mapstructure.Decode(input, &tpl); err != nil {
+ return nil, err
+ }
+
+ // Go through each builder and replace the iso_md5 if we can
+ for _, builder := range tpl.Builders {
+ md5raw, ok := builder["iso_md5"]
+ if !ok {
+ continue
+ }
+
+ md5, ok := md5raw.(string)
+ if !ok {
+ // TODO: error?
+ continue
+ }
+
+ delete(builder, "iso_md5")
+ builder["iso_checksum"] = md5
+ builder["iso_checksum_type"] = "md5"
+ }
+
+ input["builders"] = tpl.Builders
+ return input, nil
+}
+
+func (FixerISOMD5) Synopsis() string {
+ return `Replaces "iso_md5" in builders with "iso_checksum"`
+}
diff --git a/v1.9.4/fix/fixer_iso_md5_test.go b/v1.9.4/fix/fixer_iso_md5_test.go
new file mode 100644
index 0000000..fc39650
--- /dev/null
+++ b/v1.9.4/fix/fixer_iso_md5_test.go
@@ -0,0 +1,49 @@
+// Copyright (c) HashiCorp, Inc.
+// SPDX-License-Identifier: MPL-2.0
+
+package fix
+
+import (
+ "reflect"
+ "testing"
+)
+
+func TestFixerISOMD5_Impl(t *testing.T) {
+ var raw interface{}
+ raw = new(FixerISOMD5)
+ if _, ok := raw.(Fixer); !ok {
+ t.Fatalf("must be a Fixer")
+ }
+}
+
+func TestFixerISOMD5_Fix(t *testing.T) {
+ var f FixerISOMD5
+
+ input := map[string]interface{}{
+ "builders": []interface{}{
+ map[string]string{
+ "type": "foo",
+ "iso_md5": "bar",
+ },
+ },
+ }
+
+ expected := map[string]interface{}{
+ "builders": []map[string]interface{}{
+ {
+ "type": "foo",
+ "iso_checksum": "bar",
+ "iso_checksum_type": "md5",
+ },
+ },
+ }
+
+ output, err := f.Fix(input)
+ if err != nil {
+ t.Fatalf("err: %s", err)
+ }
+
+ if !reflect.DeepEqual(output, expected) {
+ t.Fatalf("unexpected: %#v\nexpected: %#v\n", output, expected)
+ }
+}
diff --git a/v1.9.4/fix/fixer_parallels_deprecations.go b/v1.9.4/fix/fixer_parallels_deprecations.go
new file mode 100644
index 0000000..36ad9a7
--- /dev/null
+++ b/v1.9.4/fix/fixer_parallels_deprecations.go
@@ -0,0 +1,67 @@
+// Copyright (c) HashiCorp, Inc.
+// SPDX-License-Identifier: MPL-2.0
+
+package fix
+
+import (
+ "github.com/mitchellh/mapstructure"
+)
+
+// FixerParallelsDeprecations removes "parallels_tools_host_path" from a
+// template in a Parallels builder and changes "guest_os_distribution" to
+// "guest_os_type", possibly overwriting any existing "guest_os_type"
+type FixerParallelsDeprecations struct{}
+
+func (FixerParallelsDeprecations) DeprecatedOptions() map[string][]string {
+ return map[string][]string{
+ "packer.parallels": []string{"parallels_tools_host_path", "guest_os_distribution"},
+ }
+}
+
+func (FixerParallelsDeprecations) Fix(input map[string]interface{}) (map[string]interface{}, error) {
+ // The type we'll decode into; we only care about builders
+ type template struct {
+ Builders []map[string]interface{}
+ }
+
+ // Decode the input into our structure, if we can
+ var tpl template
+ if err := mapstructure.Decode(input, &tpl); err != nil {
+ return nil, err
+ }
+
+ for _, builder := range tpl.Builders {
+ builderTypeRaw, ok := builder["type"]
+ if !ok {
+ continue
+ }
+
+ builderType, ok := builderTypeRaw.(string)
+ if !ok {
+ continue
+ }
+
+ if builderType != "parallels-iso" && builderType != "parallels-pvm" {
+ continue
+ }
+
+ _, ok = builder["parallels_tools_host_path"]
+ if ok {
+ delete(builder, "parallels_tools_host_path")
+ }
+
+ guestOsDistribution, ok := builder["guest_os_distribution"]
+
+ if ok {
+ builder["guest_os_type"] = guestOsDistribution
+ delete(builder, "guest_os_distribution")
+ }
+ }
+
+ input["builders"] = tpl.Builders
+ return input, nil
+}
+
+func (FixerParallelsDeprecations) Synopsis() string {
+ return `Removes deprecated "parallels_tools_host_path" from Parallels builders and changes "guest_os_distribution" to "guest_os_type".`
+}
diff --git a/v1.9.4/fix/fixer_parallels_deprecations_test.go b/v1.9.4/fix/fixer_parallels_deprecations_test.go
new file mode 100644
index 0000000..a5fd425
--- /dev/null
+++ b/v1.9.4/fix/fixer_parallels_deprecations_test.go
@@ -0,0 +1,132 @@
+// Copyright (c) HashiCorp, Inc.
+// SPDX-License-Identifier: MPL-2.0
+
+package fix
+
+import (
+ "reflect"
+ "testing"
+)
+
+func TestFixerParallelsDeprecations(t *testing.T) {
+ var _ Fixer = new(FixerParallelsDeprecations)
+}
+
+func TestFixerParallelsDeprecations_Fix_parallels_tools_guest_path(t *testing.T) {
+ cases := []struct {
+ Input map[string]interface{}
+ Expected map[string]interface{}
+ }{
+ // No parallels_tools_host_path field
+ {
+ Input: map[string]interface{}{
+ "type": "parallels-iso",
+ },
+
+ Expected: map[string]interface{}{
+ "type": "parallels-iso",
+ },
+ },
+
+ // parallels_tools_host_path field
+ {
+ Input: map[string]interface{}{
+ "type": "parallels-iso",
+ "parallels_tools_host_path": "/Path...",
+ },
+
+ Expected: map[string]interface{}{
+ "type": "parallels-iso",
+ },
+ },
+ }
+
+ for _, tc := range cases {
+ var f FixerParallelsDeprecations
+
+ input := map[string]interface{}{
+ "builders": []map[string]interface{}{tc.Input},
+ }
+
+ expected := map[string]interface{}{
+ "builders": []map[string]interface{}{tc.Expected},
+ }
+
+ output, err := f.Fix(input)
+ if err != nil {
+ t.Fatalf("err: %s", err)
+ }
+
+ if !reflect.DeepEqual(output, expected) {
+ t.Fatalf("unexpected: %#v\nexpected: %#v\n", output, expected)
+ }
+ }
+}
+
+func TestFixerParallelsDeprecations_Fix_guest_os_distribution(t *testing.T) {
+ cases := []struct {
+ Input map[string]interface{}
+ Expected map[string]interface{}
+ }{
+ // No guest_os_distribution field
+ {
+ Input: map[string]interface{}{
+ "type": "parallels-iso",
+ "guest_os_type": "ubuntu",
+ },
+
+ Expected: map[string]interface{}{
+ "type": "parallels-iso",
+ "guest_os_type": "ubuntu",
+ },
+ },
+
+ // guest_os_distribution and guest_os_type field
+ {
+ Input: map[string]interface{}{
+ "type": "parallels-iso",
+ "guest_os_type": "linux",
+ "guest_os_distribution": "ubuntu",
+ },
+
+ Expected: map[string]interface{}{
+ "type": "parallels-iso",
+ "guest_os_type": "ubuntu",
+ },
+ },
+
+ // guest_os_distribution but no guest_os_type field
+ {
+ Input: map[string]interface{}{
+ "type": "parallels-iso",
+ "guest_os_distribution": "ubuntu",
+ },
+
+ Expected: map[string]interface{}{
+ "type": "parallels-iso",
+ "guest_os_type": "ubuntu",
+ },
+ },
+ }
+
+ for _, tc := range cases {
+ var f FixerParallelsDeprecations
+
+ input := map[string]interface{}{
+ "builders": []map[string]interface{}{tc.Input},
+ }
+
+ expected := map[string]interface{}{
+ "builders": []map[string]interface{}{tc.Expected},
+ }
+
+ output, err := f.Fix(input)
+ if err != nil {
+ t.Fatalf("err: %s", err)
+ }
+
+ if !reflect.DeepEqual(output, expected) {
+ t.Fatalf("unexpected: %#v\nexpected: %#v\n", output, expected)
+ }
+ }
+}
diff --git a/v1.9.4/fix/fixer_parallels_headless.go b/v1.9.4/fix/fixer_parallels_headless.go
new file mode 100644
index 0000000..164deff
--- /dev/null
+++ b/v1.9.4/fix/fixer_parallels_headless.go
@@ -0,0 +1,60 @@
+// Copyright (c) HashiCorp, Inc.
+// SPDX-License-Identifier: MPL-2.0
+
+package fix
+
+import (
+ "github.com/mitchellh/mapstructure"
+)
+
+// FixerParallelsHeadless removes "headless" from a template in a Parallels builder
+type FixerParallelsHeadless struct{}
+
+func (FixerParallelsHeadless) DeprecatedOptions() map[string][]string {
+ return map[string][]string{
+ "packer.parallels": []string{"headless"},
+ }
+}
+
+func (FixerParallelsHeadless) Fix(input map[string]interface{}) (map[string]interface{}, error) {
+ // The type we'll decode into; we only care about builders
+ type template struct {
+ Builders []map[string]interface{}
+ }
+
+ // Decode the input into our structure, if we can
+ var tpl template
+ if err := mapstructure.Decode(input, &tpl); err != nil {
+ return nil, err
+ }
+
+ for _, builder := range tpl.Builders {
+ builderTypeRaw, ok := builder["type"]
+ if !ok {
+ continue
+ }
+
+ builderType, ok := builderTypeRaw.(string)
+ if !ok {
+ continue
+ }
+
+ if builderType != "parallels-iso" && builderType != "parallels-pvm" {
+ continue
+ }
+
+ _, ok = builder["headless"]
+ if !ok {
+ continue
+ }
+
+ delete(builder, "headless")
+ }
+
+ input["builders"] = tpl.Builders
+ return input, nil
+}
+
+func (FixerParallelsHeadless) Synopsis() string {
+ return `Removes unused "headless" from Parallels builders`
+}
diff --git a/v1.9.4/fix/fixer_parallels_headless_test.go b/v1.9.4/fix/fixer_parallels_headless_test.go
new file mode 100644
index 0000000..bc3efbc
--- /dev/null
+++ b/v1.9.4/fix/fixer_parallels_headless_test.go
@@ -0,0 +1,64 @@
+// Copyright (c) HashiCorp, Inc.
+// SPDX-License-Identifier: MPL-2.0
+
+package fix
+
+import (
+ "reflect"
+ "testing"
+)
+
+func TestFixerParallelsHeadless_Impl(t *testing.T) {
+ var _ Fixer = new(FixerParallelsHeadless)
+}
+
+func TestFixerParallelsHeadless_Fix(t *testing.T) {
+ cases := []struct {
+ Input map[string]interface{}
+ Expected map[string]interface{}
+ }{
+ // No headless field
+ {
+ Input: map[string]interface{}{
+ "type": "parallels-iso",
+ },
+
+ Expected: map[string]interface{}{
+ "type": "parallels-iso",
+ },
+ },
+
+ // Headless field
+ {
+ Input: map[string]interface{}{
+ "type": "parallels-iso",
+ "headless": false,
+ },
+
+ Expected: map[string]interface{}{
+ "type": "parallels-iso",
+ },
+ },
+ }
+
+ for _, tc := range cases {
+ var f FixerParallelsHeadless
+
+ input := map[string]interface{}{
+ "builders": []map[string]interface{}{tc.Input},
+ }
+
+ expected := map[string]interface{}{
+ "builders": []map[string]interface{}{tc.Expected},
+ }
+
+ output, err := f.Fix(input)
+ if err != nil {
+ t.Fatalf("err: %s", err)
+ }
+
+ if !reflect.DeepEqual(output, expected) {
+ t.Fatalf("unexpected: %#v\nexpected: %#v\n", output, expected)
+ }
+ }
+}
diff --git a/v1.9.4/fix/fixer_powershell_escapes.go b/v1.9.4/fix/fixer_powershell_escapes.go
new file mode 100644
index 0000000..d33d046
--- /dev/null
+++ b/v1.9.4/fix/fixer_powershell_escapes.go
@@ -0,0 +1,81 @@
+// Copyright (c) HashiCorp, Inc.
+// SPDX-License-Identifier: MPL-2.0
+
+package fix
+
+import (
+ "strings"
+
+ "github.com/mitchellh/mapstructure"
+)
+
+// FixerPowerShellEscapes removes the PowerShell escape character from user
+// environment variables and elevated username and password strings
+type FixerPowerShellEscapes struct{}
+
+func (FixerPowerShellEscapes) DeprecatedOptions() map[string][]string {
+ return map[string][]string{}
+}
+
+func (FixerPowerShellEscapes) Fix(input map[string]interface{}) (map[string]interface{}, error) {
+ type template struct {
+ Provisioners []interface{}
+ }
+
+ var psUnescape = strings.NewReplacer(
+ "`$", "$",
+ "`\"", "\"",
+ "``", "`",
+ "`'", "'",
+ )
+
+ // Decode the input into our structure, if we can
+ var tpl template
+ if err := mapstructure.WeakDecode(input, &tpl); err != nil {
+ return nil, err
+ }
+
+ for i, raw := range tpl.Provisioners {
+ var provisioners map[string]interface{}
+ if err := mapstructure.Decode(raw, &provisioners); err != nil {
+ // Ignore errors, could be a non-map
+ continue
+ }
+
+ if ok := provisioners["type"] == "powershell"; !ok {
+ continue
+ }
+
+ if _, ok := provisioners["elevated_user"]; ok {
+ provisioners["elevated_user"] = psUnescape.Replace(provisioners["elevated_user"].(string))
+ }
+ if _, ok := provisioners["elevated_password"]; ok {
+ provisioners["elevated_password"] = psUnescape.Replace(provisioners["elevated_password"].(string))
+ }
+ if raw, ok := provisioners["environment_vars"]; ok {
+ var env_vars []string
+ if err := mapstructure.Decode(raw, &env_vars); err != nil {
+ continue
+ }
+ env_vars_unescaped := make([]interface{}, len(env_vars))
+ for j, env_var := range env_vars {
+ env_vars_unescaped[j] = psUnescape.Replace(env_var)
+ }
+ // Replace with unescaped environment variables
+ provisioners["environment_vars"] = env_vars_unescaped
+ }
+
+ // Write all changes back to template
+ tpl.Provisioners[i] = provisioners
+ }
+
+ if len(tpl.Provisioners) > 0 {
+ input["provisioners"] = tpl.Provisioners
+ }
+
+ return input, nil
+}
+
+func (FixerPowerShellEscapes) Synopsis() string {
+ return `Removes PowerShell escapes from user env vars and elevated username and password strings`
+}
diff --git a/v1.9.4/fix/fixer_pp_docker_tag_tags.go b/v1.9.4/fix/fixer_pp_docker_tag_tags.go
new file mode 100644
index 0000000..49e33eb
--- /dev/null
+++ b/v1.9.4/fix/fixer_pp_docker_tag_tags.go
@@ -0,0 +1,115 @@
+// Copyright (c) HashiCorp, Inc.
+// SPDX-License-Identifier: MPL-2.0
+
+package fix
+
+import (
+ "strings"
+
+ "github.com/mitchellh/mapstructure"
+)
+
+// FixerDockerTagtoTags renames tag to tags
+type FixerDockerTagtoTags struct{}
+
+func (FixerDockerTagtoTags) DeprecatedOptions() map[string][]string {
+ return map[string][]string{
+ "packer.post-processor.docker-tag": []string{"tag"},
+ }
+}
+
+func (FixerDockerTagtoTags) Fix(input map[string]interface{}) (map[string]interface{}, error) {
+ if input["post-processors"] == nil {
+ return input, nil
+ }
+
+ // Our template type we'll use for this fixer only
+ type template struct {
+ PP `mapstructure:",squash"`
+ }
+
+ // Decode the input into our structure, if we can
+ var tpl template
+ if err := mapstructure.Decode(input, &tpl); err != nil {
+ return nil, err
+ }
+
+ // Go through each post-processor and get out all the complex configs
+ pps := tpl.ppList()
+
+ for _, pp := range pps {
+ ppTypeRaw, ok := pp["type"]
+ if !ok {
+ continue
+ }
+
+ if ppType, ok := ppTypeRaw.(string); !ok {
+ continue
+ } else if ppType != "docker-tag" {
+ continue
+ }
+
+ // Create a []string to hold tag and tags values
+ allTags := []string{}
+
+ tagRaw, ok := pp["tag"]
+ if ok {
+ // Gather all "tag" into the []string
+ switch t := tagRaw.(type) {
+ case []interface{}:
+ for _, tag := range t {
+ allTags = append(allTags, tag.(string))
+ }
+ case []string:
+ allTags = append(allTags, t...)
+ case string:
+ tList := strings.Split(t, ",")
+ for _, tag := range tList {
+ allTags = append(allTags, strings.TrimSpace(tag))
+ }
+ }
+ }
+
+ // Now check to see if they already have the "tags" field
+ tagsRaw, ok := pp["tags"]
+ if ok {
+ // Gather all "tag" into the []string
+ switch t := tagsRaw.(type) {
+ case []interface{}:
+ for _, tag := range t {
+ allTags = append(allTags, tag.(string))
+ }
+ case []string:
+ allTags = append(allTags, t...)
+ case string:
+ tList := strings.Split(t, ",")
+ for _, tag := range tList {
+ allTags = append(allTags, strings.TrimSpace(tag))
+ }
+ }
+ }
+
+ // Now deduplicate the tags in the list so we don't tag the same thing
+ // multiple times.
+ deduplicater := map[string]bool{}
+ finalTags := []string{}
+ for _, tag := range allTags {
+ if found := deduplicater[tag]; found {
+ continue
+ }
+ deduplicater[tag] = true
+ finalTags = append(finalTags, tag)
+ }
+
+ // Delete tag key, and set tags key to the final deduplicated list.
+ delete(pp, "tag")
+ pp["tags"] = finalTags
+ }
+
+ input["post-processors"] = tpl.PostProcessors
+ return input, nil
+}
+
+func (FixerDockerTagtoTags) Synopsis() string {
+ return `Updates "docker" post-processor so any "tag" field is renamed to "tags".`
+}
diff --git a/v1.9.4/fix/fixer_pp_docker_tag_tags_test.go b/v1.9.4/fix/fixer_pp_docker_tag_tags_test.go
new file mode 100644
index 0000000..908c076
--- /dev/null
+++ b/v1.9.4/fix/fixer_pp_docker_tag_tags_test.go
@@ -0,0 +1,56 @@
+// Copyright (c) HashiCorp, Inc.
+// SPDX-License-Identifier: MPL-2.0
+
+package fix
+
+import (
+ "testing"
+
+ "github.com/stretchr/testify/assert"
+)
+
+func TestFixerDockerTags(t *testing.T) {
+ var _ Fixer = new(FixerVagrantPPOverride)
+}
+
+func TestFixerDockerTags_Fix(t *testing.T) {
+ var f FixerDockerTagtoTags
+
+ input := map[string]interface{}{
+ "post-processors": []interface{}{
+ map[string]interface{}{
+ "type": "docker-tag",
+ "tag": "foo",
+ "tags": []string{"foo", "bar"},
+ },
+ []interface{}{
+ map[string]interface{}{
+ "type": "docker-tag",
+ "tag": []string{"baz"},
+ "tags": []string{"foo", "bar"},
+ },
+ },
+ },
+ }
+
+ expected := map[string]interface{}{
+ "post-processors": []interface{}{
+ map[string]interface{}{
+ "type": "docker-tag",
+ "tags": []string{"foo", "bar"},
+ },
+ []interface{}{
+ map[string]interface{}{
+ "type": "docker-tag",
+ "tags": []string{"baz", "foo", "bar"},
+ },
+ },
+ },
+ }
+
+ output, err := f.Fix(input)
+ assert.NoError(t, err)
+ for k, v := range expected {
+ assert.EqualValues(t, v, output[k])
+ }
+}
diff --git a/v1.9.4/fix/fixer_pp_manifest_filename.go b/v1.9.4/fix/fixer_pp_manifest_filename.go
new file mode 100644
index 0000000..9f66bc7
--- /dev/null
+++ b/v1.9.4/fix/fixer_pp_manifest_filename.go
@@ -0,0 +1,68 @@
+// Copyright (c) HashiCorp, Inc.
+// SPDX-License-Identifier: MPL-2.0
+
+package fix
+
+import (
+ "github.com/mitchellh/mapstructure"
+)
+
+// FixerManifestFilename renames any Filename to Output
+type FixerManifestFilename struct{}
+
+func (FixerManifestFilename) DeprecatedOptions() map[string][]string {
+ return map[string][]string{
+ "packer.post-processor.manifest": []string{"filename"},
+ }
+}
+
+func (FixerManifestFilename) Fix(input map[string]interface{}) (map[string]interface{}, error) {
+ if input["post-processors"] == nil {
+ return input, nil
+ }
+
+ // Our template type we'll use for this fixer only
+ type template struct {
+ PP `mapstructure:",squash"`
+ }
+
+ // Decode the input into our structure, if we can
+ var tpl template
+ if err := mapstructure.Decode(input, &tpl); err != nil {
+ return nil, err
+ }
+
+ // Go through each post-processor and get out all the complex configs
+ pps := tpl.ppList()
+
+ for _, pp := range pps {
+ ppTypeRaw, ok := pp["type"]
+ if !ok {
+ continue
+ }
+
+ if ppType, ok := ppTypeRaw.(string); !ok {
+ continue
+ } else if ppType != "manifest" {
+ continue
+ }
+
+ filenameRaw, ok := pp["filename"]
+ if !ok {
+ continue
+ }
+
+ if filename, ok := filenameRaw.(string); ok {
+ delete(pp, "filename")
+ pp["output"] = filename
+ }
+
+ }
+
+ input["post-processors"] = tpl.PostProcessors
+ return input, nil
+}
+
+func (FixerManifestFilename) Synopsis() string {
+ return `Updates "manifest" post-processor so any "filename" field is renamed to "output".`
+}
diff --git a/v1.9.4/fix/fixer_pp_manifest_filename_test.go b/v1.9.4/fix/fixer_pp_manifest_filename_test.go
new file mode 100644
index 0000000..ab86324
--- /dev/null
+++ b/v1.9.4/fix/fixer_pp_manifest_filename_test.go
@@ -0,0 +1,53 @@
+// Copyright (c) HashiCorp, Inc.
+// SPDX-License-Identifier: MPL-2.0
+
+package fix
+
+import (
+ "testing"
+
+ "github.com/stretchr/testify/assert"
+)
+
+func TestFixerManifestPPFilename_Impl(t *testing.T) {
+ var _ Fixer = new(FixerVagrantPPOverride)
+}
+
+func TestFixerManifestPPFilename_Fix(t *testing.T) {
+ var f FixerManifestFilename
+
+ input := map[string]interface{}{
+ "post-processors": []interface{}{
+ map[string]interface{}{
+ "type": "manifest",
+ "filename": "foo",
+ },
+ []interface{}{
+ map[string]interface{}{
+ "type": "manifest",
+ "filename": "foo",
+ },
+ },
+ },
+ }
+
+ expected := map[string]interface{}{
+ "post-processors": []interface{}{
+ map[string]interface{}{
+ "type": "manifest",
+ "output": "foo",
+ },
+ []interface{}{
+ map[string]interface{}{
+ "type": "manifest",
+ "output": "foo",
+ },
+ },
+ },
+ }
+
+ output, err := f.Fix(input)
+ assert.NoError(t, err)
+
+ assert.Equal(t, expected, output)
+}
diff --git a/v1.9.4/fix/fixer_pp_vagrant_override.go b/v1.9.4/fix/fixer_pp_vagrant_override.go
new file mode 100644
index 0000000..eee2622
--- /dev/null
+++ b/v1.9.4/fix/fixer_pp_vagrant_override.go
@@ -0,0 +1,70 @@
+// Copyright (c) HashiCorp, Inc.
+// SPDX-License-Identifier: MPL-2.0
+
+package fix
+
+import "github.com/mitchellh/mapstructure"
+
+// FixerVagrantPPOverride is a Fixer that replaces the provider-specific
+// overrides for the Vagrant post-processor with the new style introduced
+// as part of Packer 0.5.0.
+type FixerVagrantPPOverride struct{}
+
+func (FixerVagrantPPOverride) DeprecatedOptions() map[string][]string {
+ return map[string][]string{}
+}
+
+func (FixerVagrantPPOverride) Fix(input map[string]interface{}) (map[string]interface{}, error) {
+ if input["post-processors"] == nil {
+ return input, nil
+ }
+
+ // Our template type we'll use for this fixer only
+ type template struct {
+ PP `mapstructure:",squash"`
+ }
+
+ // Decode the input into our structure, if we can
+ var tpl template
+ if err := mapstructure.Decode(input, &tpl); err != nil {
+ return nil, err
+ }
+
+ pps := tpl.ppList()
+
+ // Go through each post-processor and make the fix if necessary
+ possible := []string{"aws", "digitalocean", "virtualbox", "vmware"}
+ for _, pp := range pps {
+ typeRaw, ok := pp["type"]
+ if !ok {
+ continue
+ }
+
+ if typeName, ok := typeRaw.(string); !ok {
+ continue
+ } else if typeName != "vagrant" {
+ continue
+ }
+
+ overrides := make(map[string]interface{})
+ for _, name := range possible {
+ if _, ok := pp[name]; !ok {
+ continue
+ }
+
+ overrides[name] = pp[name]
+ delete(pp, name)
+ }
+
+ if len(overrides) > 0 {
+ pp["override"] = overrides
+ }
+ }
+
+ input["post-processors"] = tpl.PostProcessors
+ return input, nil
+}
+
+func (FixerVagrantPPOverride) Synopsis() string {
+ return `Fixes provider-specific overrides for Vagrant post-processor`
+}
diff --git a/v1.9.4/fix/fixer_pp_vagrant_override_test.go b/v1.9.4/fix/fixer_pp_vagrant_override_test.go
new file mode 100644
index 0000000..1ba56eb
--- /dev/null
+++ b/v1.9.4/fix/fixer_pp_vagrant_override_test.go
@@ -0,0 +1,79 @@
+// Copyright (c) HashiCorp, Inc.
+// SPDX-License-Identifier: MPL-2.0
+
+package fix
+
+import (
+ "testing"
+
+ "github.com/stretchr/testify/assert"
+)
+
+func TestFixerVagrantPPOverride_Impl(t *testing.T) {
+ var _ Fixer = new(FixerVagrantPPOverride)
+}
+
+func TestFixerVagrantPPOverride_Fix(t *testing.T) {
+ var f FixerVagrantPPOverride
+
+ input := map[string]interface{}{
+ "post-processors": []interface{}{
+ "foo",
+
+ map[string]interface{}{
+ "type": "vagrant",
+ "aws": map[string]interface{}{
+ "foo": "bar",
+ },
+ },
+
+ map[string]interface{}{
+ "type": "vsphere",
+ },
+
+ []interface{}{
+ map[string]interface{}{
+ "type": "vagrant",
+ "vmware": map[string]interface{}{
+ "foo": "bar",
+ },
+ },
+ },
+ },
+ }
+
+ expected := map[string]interface{}{
+ "post-processors": []interface{}{
+ "foo",
+
+ map[string]interface{}{
+ "type": "vagrant",
+ "override": map[string]interface{}{
+ "aws": map[string]interface{}{
+ "foo": "bar",
+ },
+ },
+ },
+
+ map[string]interface{}{
+ "type": "vsphere",
+ },
+
+ []interface{}{
+ map[string]interface{}{
+ "type": "vagrant",
+ "override": map[string]interface{}{
+ "vmware": map[string]interface{}{
+ "foo": "bar",
+ },
+ },
+ },
+ },
+ },
+ }
+
+ output, err := f.Fix(input)
+ assert.NoError(t, err)
+
+ assert.Equal(t, expected, output)
+}
diff --git a/v1.9.4/fix/fixer_proxmox_type.go b/v1.9.4/fix/fixer_proxmox_type.go
new file mode 100644
index 0000000..602e82a
--- /dev/null
+++ b/v1.9.4/fix/fixer_proxmox_type.go
@@ -0,0 +1,52 @@
+// Copyright (c) HashiCorp, Inc.
+// SPDX-License-Identifier: MPL-2.0
+
+package fix
+
+import (
+ "github.com/mitchellh/mapstructure"
+)
+
+// FixerProxmoxType updates proxmox builder types to proxmox-iso
+type FixerProxmoxType struct{}
+
+func (FixerProxmoxType) DeprecatedOptions() map[string][]string {
+ return map[string][]string{}
+}
+
+func (FixerProxmoxType) Fix(input map[string]interface{}) (map[string]interface{}, error) {
+ type template struct {
+ Builders []map[string]interface{}
+ }
+
+ // Decode the input into our structure, if we can
+ var tpl template
+ if err := mapstructure.Decode(input, &tpl); err != nil {
+ return nil, err
+ }
+
+ for _, builder := range tpl.Builders {
+ builderTypeRaw, ok := builder["type"]
+ if !ok {
+ continue
+ }
+
+ builderType, ok := builderTypeRaw.(string)
+ if !ok {
+ continue
+ }
+
+ if builderType != "proxmox" {
+ continue
+ }
+
+ builder["type"] = "proxmox-iso"
+ }
+
+ input["builders"] = tpl.Builders
+ return input, nil
+}
+
+func (FixerProxmoxType) Synopsis() string {
+ return `Updates the builder type proxmox to proxmox-iso`
+}
diff --git a/v1.9.4/fix/fixer_proxmox_type_test.go b/v1.9.4/fix/fixer_proxmox_type_test.go
new file mode 100644
index 0000000..e0ea378
--- /dev/null
+++ b/v1.9.4/fix/fixer_proxmox_type_test.go
@@ -0,0 +1,76 @@
+// Copyright (c) HashiCorp, Inc.
+// SPDX-License-Identifier: MPL-2.0
+
+package fix
+
+import (
+ "testing"
+
+ "github.com/stretchr/testify/assert"
+)
+
+func TestFixerProxmoxType_Impl(t *testing.T) {
+ var raw interface{}
+ raw = new(FixerProxmoxType)
+ if _, ok := raw.(Fixer); !ok {
+ t.Fatalf("must be a Fixer")
+ }
+}
+
+func TestFixerProxmoxType_Fix(t *testing.T) {
+
+ cases := []struct {
+ Input map[string]interface{}
+ Expected map[string]interface{}
+ }{
+
+ {
+ Input: map[string]interface{}{
+ "type": "proxmox",
+ },
+
+ Expected: map[string]interface{}{
+ "type": "proxmox-iso",
+ },
+ },
+
+ {
+ Input: map[string]interface{}{
+ "type": "proxmox-iso",
+ },
+
+ Expected: map[string]interface{}{
+ "type": "proxmox-iso",
+ },
+ },
+
+ {
+ Input: map[string]interface{}{
+ "type": "proxmox-clone",
+ },
+
+ Expected: map[string]interface{}{
+ "type": "proxmox-clone",
+ },
+ },
+ }
+
+ for _, tc := range cases {
+ var f FixerProxmoxType
+
+ input := map[string]interface{}{
+ "builders": []map[string]interface{}{tc.Input},
+ }
+
+ expected := map[string]interface{}{
+ "builders": []map[string]interface{}{tc.Expected},
+ }
+
+ output, err := f.Fix(input)
+ if err != nil {
+ t.Fatalf("err: %s", err)
+ }
+
+ assert.Equal(t, expected, output, "Should be equal")
+ }
+}
diff --git a/v1.9.4/fix/fixer_qemu_disk_size.go b/v1.9.4/fix/fixer_qemu_disk_size.go
new file mode 100644
index 0000000..7cd5380
--- /dev/null
+++ b/v1.9.4/fix/fixer_qemu_disk_size.go
@@ -0,0 +1,60 @@
+// Copyright (c) HashiCorp, Inc.
+// SPDX-License-Identifier: MPL-2.0
+
+package fix
+
+import (
+ "strconv"
+
+ "github.com/mitchellh/mapstructure"
+)
+
+// FixerQEMUDiskSize updates disk_size from a string to int for QEMU builders
+type FixerQEMUDiskSize struct{}
+
+func (FixerQEMUDiskSize) DeprecatedOptions() map[string][]string {
+ return map[string][]string{}
+}
+
+func (FixerQEMUDiskSize) Fix(input map[string]interface{}) (map[string]interface{}, error) {
+ type template struct {
+ Builders []map[string]interface{}
+ }
+
+ // Decode the input into our structure, if we can
+ var tpl template
+ if err := mapstructure.Decode(input, &tpl); err != nil {
+ return nil, err
+ }
+
+ for _, builder := range tpl.Builders {
+ builderTypeRaw, ok := builder["type"]
+ if !ok {
+ continue
+ }
+
+ builderType, ok := builderTypeRaw.(string)
+ if !ok {
+ continue
+ }
+
+ if builderType != "qemu" {
+ continue
+ }
+
+ switch diskSize := builder["disk_size"].(type) {
+ case float64:
+ builder["disk_size"] = strconv.Itoa(int(diskSize)) + "M"
+ case int:
+ builder["disk_size"] = strconv.Itoa(diskSize) + "M"
+ }
+
+ }
+
+ input["builders"] = tpl.Builders
+ return input, nil
+}
+
+func (FixerQEMUDiskSize) Synopsis() string {
+ return `Updates "disk_size" from int to string in QEMU builders.`
+}
diff --git a/v1.9.4/fix/fixer_qemu_disk_size_test.go b/v1.9.4/fix/fixer_qemu_disk_size_test.go
new file mode 100644
index 0000000..3d141a5
--- /dev/null
+++ b/v1.9.4/fix/fixer_qemu_disk_size_test.go
@@ -0,0 +1,64 @@
+// Copyright (c) HashiCorp, Inc.
+// SPDX-License-Identifier: MPL-2.0
+
+package fix
+
+import (
+ "reflect"
+ "testing"
+)
+
+func TestFixerQEMUDiskSize_impl(t *testing.T) {
+ var _ Fixer = new(FixerQEMUDiskSize)
+}
+
+func TestFixerQEMUDiskSize(t *testing.T) {
+ cases := []struct {
+ Input map[string]interface{}
+ Expected map[string]interface{}
+ }{
+ {
+ Input: map[string]interface{}{
+ "type": "qemu",
+ "disk_size": int(40960),
+ },
+
+ Expected: map[string]interface{}{
+ "type": "qemu",
+ "disk_size": "40960M",
+ },
+ },
+ {
+ Input: map[string]interface{}{
+ "type": "qemu",
+ "disk_size": float64(50000),
+ },
+
+ Expected: map[string]interface{}{
+ "type": "qemu",
+ "disk_size": "50000M",
+ },
+ },
+ }
+
+ for _, tc := range cases {
+ var f FixerQEMUDiskSize
+
+ input := map[string]interface{}{
+ "builders": []map[string]interface{}{tc.Input},
+ }
+
+ expected := map[string]interface{}{
+ "builders": []map[string]interface{}{tc.Expected},
+ }
+
+ output, err := f.Fix(input)
+ if err != nil {
+ t.Fatalf("err: %s", err)
+ }
+
+ if !reflect.DeepEqual(output, expected) {
+ t.Fatalf("unexpected: %#v\nexpected: %#v\n", output, expected)
+ }
+ }
+}
diff --git a/v1.9.4/fix/fixer_qemu_host_port.go b/v1.9.4/fix/fixer_qemu_host_port.go
new file mode 100644
index 0000000..4cd96b5
--- /dev/null
+++ b/v1.9.4/fix/fixer_qemu_host_port.go
@@ -0,0 +1,66 @@
+// Copyright (c) HashiCorp, Inc.
+// SPDX-License-Identifier: MPL-2.0
+
+package fix
+
+import (
+ "github.com/mitchellh/mapstructure"
+)
+
+// FixerQEMUHostPort updates ssh_host_port_min and ssh_host_port_max to host_port_min and host_port_max for QEMU builders
+type FixerQEMUHostPort struct{}
+
+func (FixerQEMUHostPort) Fix(input map[string]interface{}) (map[string]interface{}, error) {
+ type template struct {
+ Builders []map[string]interface{}
+ }
+
+ // Decode the input into our structure, if we can
+ var tpl template
+ if err := mapstructure.Decode(input, &tpl); err != nil {
+ return nil, err
+ }
+
+ for _, builder := range tpl.Builders {
+ builderTypeRaw, ok := builder["type"]
+ if !ok {
+ continue
+ }
+
+ builderType, ok := builderTypeRaw.(string)
+ if !ok {
+ continue
+ }
+
+ if builderType != "qemu" {
+ continue
+ }
+
+ // replace ssh_host_port_min with host_port_min if it exists
+ sshHostPortMin, ok := builder["ssh_host_port_min"]
+ if ok {
+ delete(builder, "ssh_host_port_min")
+ builder["host_port_min"] = sshHostPortMin
+ }
+
+ // replace ssh_host_port_min with host_port_min if it exists
+ sshHostPortMax, ok := builder["ssh_host_port_max"]
+ if ok {
+ delete(builder, "ssh_host_port_max")
+ builder["host_port_max"] = sshHostPortMax
+ }
+ }
+
+ input["builders"] = tpl.Builders
+ return input, nil
+}
+
+func (FixerQEMUHostPort) Synopsis() string {
+ return `Updates ssh_host_port_min and ssh_host_port_max to host_port_min and host_port_max`
+}
+
+func (FixerQEMUHostPort) DeprecatedOptions() map[string][]string {
+ return map[string][]string{
+ "transcend.qemu": []string{"ssh_host_port_max", "ssh_host_port_min"},
+ }
+}
diff --git a/v1.9.4/fix/fixer_qemu_host_port_test.go b/v1.9.4/fix/fixer_qemu_host_port_test.go
new file mode 100644
index 0000000..64aaedd
--- /dev/null
+++ b/v1.9.4/fix/fixer_qemu_host_port_test.go
@@ -0,0 +1,64 @@
+// Copyright (c) HashiCorp, Inc.
+// SPDX-License-Identifier: MPL-2.0
+
+package fix
+
+import (
+ "reflect"
+ "testing"
+)
+
+func TestFixerQEMUHostPort_impl(t *testing.T) {
+ var _ Fixer = new(FixerQEMUHostPort)
+}
+
+func TestFixerQEMUHostPort(t *testing.T) {
+ cases := []struct {
+ Input map[string]interface{}
+ Expected map[string]interface{}
+ }{
+ {
+ Input: map[string]interface{}{
+ "type": "qemu",
+ "ssh_host_port_min": 2222,
+ },
+
+ Expected: map[string]interface{}{
+ "type": "qemu",
+ "host_port_min": 2222,
+ },
+ },
+ {
+ Input: map[string]interface{}{
+ "type": "qemu",
+ "ssh_host_port_max": 4444,
+ },
+
+ Expected: map[string]interface{}{
+ "type": "qemu",
+ "host_port_max": 4444,
+ },
+ },
+ }
+
+ for _, tc := range cases {
+ var f FixerQEMUHostPort
+
+ input := map[string]interface{}{
+ "builders": []map[string]interface{}{tc.Input},
+ }
+
+ expected := map[string]interface{}{
+ "builders": []map[string]interface{}{tc.Expected},
+ }
+
+ output, err := f.Fix(input)
+ if err != nil {
+ t.Fatalf("err: %s", err)
+ }
+
+ if !reflect.DeepEqual(output, expected) {
+ t.Fatalf("unexpected: %#v\nexpected: %#v\n", output, expected)
+ }
+ }
+}
diff --git a/v1.9.4/fix/fixer_scaleway_access_key.go b/v1.9.4/fix/fixer_scaleway_access_key.go
new file mode 100644
index 0000000..c7e4548
--- /dev/null
+++ b/v1.9.4/fix/fixer_scaleway_access_key.go
@@ -0,0 +1,63 @@
+// Copyright (c) HashiCorp, Inc.
+// SPDX-License-Identifier: MPL-2.0
+
+package fix
+
+import (
+ "github.com/mitchellh/mapstructure"
+)
+
+// FixerScalewayAccessKey changes the "access_key" of a template
+// to "organization_id".
+type FixerScalewayAccessKey struct{}
+
+func (FixerScalewayAccessKey) DeprecatedOptions() map[string][]string {
+ return map[string][]string{
+ "hashicorp.scaleway": []string{"access_key"},
+ }
+}
+
+func (FixerScalewayAccessKey) Fix(input map[string]interface{}) (map[string]interface{}, error) {
+ // The type we'll decode into; we only care about builders
+ type template struct {
+ Builders []map[string]interface{}
+ }
+
+ // Decode the input into our structure, if we can
+ var tpl template
+ if err := mapstructure.Decode(input, &tpl); err != nil {
+ return nil, err
+ }
+
+ for _, builder := range tpl.Builders {
+ if builder["type"] != "scaleway" {
+ continue
+ }
+
+ keyRaw, ok := builder["access_key"]
+ if !ok {
+ continue
+ }
+
+ accessKey, ok := keyRaw.(string)
+ if !ok {
+ continue
+ }
+
+ // only assign to organization_id if it doesn't
+ // already exist; otherwise we'll just ignore access_key
+ _, organizationIdIncluded := builder["organization_id"]
+ if !organizationIdIncluded {
+ builder["organization_id"] = accessKey
+ }
+
+ delete(builder, "access_key")
+ }
+
+ input["builders"] = tpl.Builders
+ return input, nil
+}
+
+func (FixerScalewayAccessKey) Synopsis() string {
+ return `Updates builders using "access_key" to use "organization_id"`
+}
diff --git a/v1.9.4/fix/fixer_scaleway_access_key_test.go b/v1.9.4/fix/fixer_scaleway_access_key_test.go
new file mode 100644
index 0000000..365bb46
--- /dev/null
+++ b/v1.9.4/fix/fixer_scaleway_access_key_test.go
@@ -0,0 +1,92 @@
+// Copyright (c) HashiCorp, Inc.
+// SPDX-License-Identifier: MPL-2.0
+
+package fix
+
+import (
+ "reflect"
+ "testing"
+)
+
+func TestFixerScalewayAccessKey_Fix_Impl(t *testing.T) {
+ var _ Fixer = new(FixerScalewayAccessKey)
+}
+
+func TestFixerScalewayAccessKey_Fix(t *testing.T) {
+ cases := []struct {
+ Input map[string]interface{}
+ Expected map[string]interface{}
+ }{
+ // No key_path field
+ {
+ Input: map[string]interface{}{
+ "type": "scaleway",
+ },
+
+ Expected: map[string]interface{}{
+ "type": "scaleway",
+ },
+ },
+
+ // organization_id without access_key
+ {
+ Input: map[string]interface{}{
+ "type": "scaleway",
+ "organization_id": "0000",
+ },
+
+ Expected: map[string]interface{}{
+ "type": "scaleway",
+ "organization_id": "0000",
+ },
+ },
+
+ // access_key without organization_id
+ {
+ Input: map[string]interface{}{
+ "type": "scaleway",
+ "access_key": "1111",
+ },
+
+ Expected: map[string]interface{}{
+ "type": "scaleway",
+ "organization_id": "1111",
+ },
+ },
+
+ // access_key and organization_id
+ {
+ Input: map[string]interface{}{
+ "type": "scaleway",
+ "access_key": "2222",
+ "organization_id": "3333",
+ },
+
+ Expected: map[string]interface{}{
+ "type": "scaleway",
+ "organization_id": "3333",
+ },
+ },
+ }
+
+ for _, tc := range cases {
+ var f FixerScalewayAccessKey
+
+ input := map[string]interface{}{
+ "builders": []map[string]interface{}{tc.Input},
+ }
+
+ expected := map[string]interface{}{
+ "builders": []map[string]interface{}{tc.Expected},
+ }
+
+ output, err := f.Fix(input)
+ if err != nil {
+ t.Fatalf("err: %s", err)
+ }
+
+ if !reflect.DeepEqual(output, expected) {
+ t.Fatalf("unexpected: %#v\nexpected: %#v\n", output, expected)
+ }
+ }
+}
diff --git a/v1.9.4/fix/fixer_ssh_timeout.go b/v1.9.4/fix/fixer_ssh_timeout.go
new file mode 100644
index 0000000..fc67519
--- /dev/null
+++ b/v1.9.4/fix/fixer_ssh_timeout.go
@@ -0,0 +1,74 @@
+// Copyright (c) HashiCorp, Inc.
+// SPDX-License-Identifier: MPL-2.0
+
+package fix
+
+import (
+ "github.com/mitchellh/mapstructure"
+)
+
+// FixerSSHTimout replaces ssh_wait_timeout with ssh_timeout
+type FixerSSHTimout struct{}
+
+func (FixerSSHTimout) DeprecatedOptions() map[string][]string {
+ return map[string][]string{
+ "*": []string{"ssh_wait_timeout"},
+ }
+}
+
+func (FixerSSHTimout) Fix(input map[string]interface{}) (map[string]interface{}, error) {
+ type template struct {
+ Builders []interface{}
+ }
+
+ // Decode the input into our structure, if we can
+ var tpl template
+ if err := mapstructure.WeakDecode(input, &tpl); err != nil {
+ return nil, err
+ }
+
+ for i, raw := range tpl.Builders {
+ var builders map[string]interface{}
+ if err := mapstructure.Decode(raw, &builders); err != nil {
+ // Ignore errors, could be a non-map
+ continue
+ }
+
+ if _, ok := builders["ssh_timeout"]; ok {
+
+ // drop ssh_wait_timeout if it is also included
+ if _, sshWaitTimeoutIncluded := builders["ssh_wait_timeout"]; sshWaitTimeoutIncluded {
+ delete(builders, "ssh_wait_timeout")
+ }
+
+ } else {
+
+ // replace ssh_wait_timeout with ssh_timeout if it exists
+ sshWaitTimeoutRaw, ok := builders["ssh_wait_timeout"]
+ if !ok {
+ continue
+ }
+
+ sshWaitTimeoutString, ok := sshWaitTimeoutRaw.(string)
+ if !ok {
+ continue
+ }
+
+ delete(builders, "ssh_wait_timeout")
+ builders["ssh_timeout"] = sshWaitTimeoutString
+ }
+
+ // Write all changes back to template
+ tpl.Builders[i] = builders
+ }
+
+ if len(tpl.Builders) > 0 {
+ input["builders"] = tpl.Builders
+ }
+
+ return input, nil
+}
+
+func (FixerSSHTimout) Synopsis() string {
+ return `Replaces "ssh_wait_timeout" with "ssh_timeout"`
+}
diff --git a/v1.9.4/fix/fixer_ssh_timeout_test.go b/v1.9.4/fix/fixer_ssh_timeout_test.go
new file mode 100644
index 0000000..558a94d
--- /dev/null
+++ b/v1.9.4/fix/fixer_ssh_timeout_test.go
@@ -0,0 +1,76 @@
+// Copyright (c) HashiCorp, Inc.
+// SPDX-License-Identifier: MPL-2.0
+
+package fix
+
+import (
+ "reflect"
+ "testing"
+)
+
+func TestFixerSSHTimout_Impl(t *testing.T) {
+ var _ Fixer = new(FixerSSHTimout)
+}
+
+func TestFixerSSHTimout_Fix(t *testing.T) {
+ cases := []struct {
+ Input map[string]interface{}
+ Expected map[string]interface{}
+ }{
+ // set galaxy_command
+ {
+ Input: map[string]interface{}{
+ "ssh_timeout": "1h5m2s",
+ },
+
+ Expected: map[string]interface{}{
+ "ssh_timeout": "1h5m2s",
+ },
+ },
+
+ // set galaxycommand (old key)
+ {
+ Input: map[string]interface{}{
+ "ssh_wait_timeout": "1h5m2s",
+ },
+
+ Expected: map[string]interface{}{
+ "ssh_timeout": "1h5m2s",
+ },
+ },
+
+ // set galaxy_command and galaxycommand
+ // galaxy_command takes precedence
+ {
+ Input: map[string]interface{}{
+ "ssh_timeout": "1h5m2s",
+ "ssh_wait_timeout": "30m",
+ },
+
+ Expected: map[string]interface{}{
+ "ssh_timeout": "1h5m2s",
+ },
+ },
+ }
+
+ for _, tc := range cases {
+ var f FixerSSHTimout
+
+ input := map[string]interface{}{
+ "builders": []interface{}{tc.Input},
+ }
+
+ expected := map[string]interface{}{
+ "builders": []interface{}{tc.Expected},
+ }
+
+ output, err := f.Fix(input)
+ if err != nil {
+ t.Fatalf("err: %s", err)
+ }
+
+ if !reflect.DeepEqual(output, expected) {
+ t.Fatalf("unexpected: %#v\nexpected: %#v\n", output, expected)
+ }
+ }
+}
diff --git a/v1.9.4/fix/fixer_sshdisableagent.go b/v1.9.4/fix/fixer_sshdisableagent.go
new file mode 100644
index 0000000..1ed262f
--- /dev/null
+++ b/v1.9.4/fix/fixer_sshdisableagent.go
@@ -0,0 +1,59 @@
+// Copyright (c) HashiCorp, Inc.
+// SPDX-License-Identifier: MPL-2.0
+
+package fix
+
+import (
+ "github.com/mitchellh/mapstructure"
+)
+
+// FixerSSHDisableAgent changes the "ssh_disable_agent" of a template
+// to "ssh_disable_agent_forwarding".
+type FixerSSHDisableAgent struct{}
+
+func (FixerSSHDisableAgent) DeprecatedOptions() map[string][]string {
+ return map[string][]string{
+ "*": []string{"ssh_disable_agent"},
+ }
+}
+
+func (FixerSSHDisableAgent) Fix(input map[string]interface{}) (map[string]interface{}, error) {
+ // The type we'll decode into; we only care about builders
+ type template struct {
+ Builders []map[string]interface{}
+ }
+
+ // Decode the input into our structure, if we can
+ var tpl template
+ if err := mapstructure.Decode(input, &tpl); err != nil {
+ return nil, err
+ }
+
+ for _, builder := range tpl.Builders {
+ sshDisableAgentRaw, ok := builder["ssh_disable_agent"]
+ if !ok {
+ continue
+ }
+
+ sshDisableAgent, ok := sshDisableAgentRaw.(bool)
+ if !ok {
+ continue
+ }
+
+ // only assign to ssh_disable_agent_forwarding if it doesn't
+ // already exist; otherwise we'll just ignore ssh_disable_agent
+ _, sshDisableAgentIncluded := builder["ssh_disable_agent_forwarding"]
+ if !sshDisableAgentIncluded {
+ builder["ssh_disable_agent_forwarding"] = sshDisableAgent
+ }
+
+ delete(builder, "ssh_disable_agent")
+ }
+
+ input["builders"] = tpl.Builders
+ return input, nil
+}
+
+func (FixerSSHDisableAgent) Synopsis() string {
+ return `Updates builders using "ssh_disable_agent" to use "ssh_disable_agent_forwarding"`
+}
diff --git a/v1.9.4/fix/fixer_sshdisableagent_test.go b/v1.9.4/fix/fixer_sshdisableagent_test.go
new file mode 100644
index 0000000..9fc67bd
--- /dev/null
+++ b/v1.9.4/fix/fixer_sshdisableagent_test.go
@@ -0,0 +1,86 @@
+// Copyright (c) HashiCorp, Inc.
+// SPDX-License-Identifier: MPL-2.0
+
+package fix
+
+import (
+ "reflect"
+ "testing"
+)
+
+func TestFixerSSHDisableAgent_Impl(t *testing.T) {
+ var _ Fixer = new(FixerSSHDisableAgent)
+}
+
+func TestFixerSSHDisableAgent_Fix(t *testing.T) {
+ cases := []struct {
+ Input map[string]interface{}
+ Expected map[string]interface{}
+ }{
+ // No disable_agent field
+ {
+ Input: map[string]interface{}{
+ "type": "virtualbox",
+ },
+
+ Expected: map[string]interface{}{
+ "type": "virtualbox",
+ },
+ },
+
+ // disable_agent_forwarding without disable_agent
+ {
+ Input: map[string]interface{}{
+ "ssh_disable_agent_forwarding": true,
+ },
+
+ Expected: map[string]interface{}{
+ "ssh_disable_agent_forwarding": true,
+ },
+ },
+
+ // disable_agent without disable_agent_forwarding
+ {
+ Input: map[string]interface{}{
+ "ssh_disable_agent": true,
+ },
+
+ Expected: map[string]interface{}{
+ "ssh_disable_agent_forwarding": true,
+ },
+ },
+
+ // disable_agent and disable_agent_forwarding
+ {
+ Input: map[string]interface{}{
+ "ssh_disable_agent": true,
+ "ssh_disable_agent_forwarding": false,
+ },
+
+ Expected: map[string]interface{}{
+ "ssh_disable_agent_forwarding": false,
+ },
+ },
+ }
+
+ for _, tc := range cases {
+ var f FixerSSHDisableAgent
+
+ input := map[string]interface{}{
+ "builders": []map[string]interface{}{tc.Input},
+ }
+
+ expected := map[string]interface{}{
+ "builders": []map[string]interface{}{tc.Expected},
+ }
+
+ output, err := f.Fix(input)
+ if err != nil {
+ t.Fatalf("err: %s", err)
+ }
+
+ if !reflect.DeepEqual(output, expected) {
+ t.Fatalf("unexpected: %#v\nexpected: %#v\n", output, expected)
+ }
+ }
+}
diff --git a/v1.9.4/fix/fixer_sshkeypath.go b/v1.9.4/fix/fixer_sshkeypath.go
new file mode 100644
index 0000000..48bc8ee
--- /dev/null
+++ b/v1.9.4/fix/fixer_sshkeypath.go
@@ -0,0 +1,59 @@
+// Copyright (c) HashiCorp, Inc.
+// SPDX-License-Identifier: MPL-2.0
+
+package fix
+
+import (
+ "github.com/mitchellh/mapstructure"
+)
+
+// FixerSSHKeyPath changes the "ssh_key_path" of a template
+// to "ssh_private_key_file".
+type FixerSSHKeyPath struct{}
+
+func (FixerSSHKeyPath) DeprecatedOptions() map[string][]string {
+ return map[string][]string{
+ "*": []string{"ssh_key_path"},
+ }
+}
+
+func (FixerSSHKeyPath) Fix(input map[string]interface{}) (map[string]interface{}, error) {
+ // The type we'll decode into; we only care about builders
+ type template struct {
+ Builders []map[string]interface{}
+ }
+
+ // Decode the input into our structure, if we can
+ var tpl template
+ if err := mapstructure.Decode(input, &tpl); err != nil {
+ return nil, err
+ }
+
+ for _, builder := range tpl.Builders {
+ sshKeyPathRaw, ok := builder["ssh_key_path"]
+ if !ok {
+ continue
+ }
+
+ sshKeyPath, ok := sshKeyPathRaw.(string)
+ if !ok {
+ continue
+ }
+
+ // only assign to ssh_private_key_file if it doesn't
+ // already exist; otherwise we'll just ignore ssh_key_path
+ _, sshPrivateIncluded := builder["ssh_private_key_file"]
+ if !sshPrivateIncluded {
+ builder["ssh_private_key_file"] = sshKeyPath
+ }
+
+ delete(builder, "ssh_key_path")
+ }
+
+ input["builders"] = tpl.Builders
+ return input, nil
+}
+
+func (FixerSSHKeyPath) Synopsis() string {
+ return `Updates builders using "ssh_key_path" to use "ssh_private_key_file"`
+}
diff --git a/v1.9.4/fix/fixer_sshkeypath_test.go b/v1.9.4/fix/fixer_sshkeypath_test.go
new file mode 100644
index 0000000..c959179
--- /dev/null
+++ b/v1.9.4/fix/fixer_sshkeypath_test.go
@@ -0,0 +1,86 @@
+// Copyright (c) HashiCorp, Inc.
+// SPDX-License-Identifier: MPL-2.0
+
+package fix
+
+import (
+ "reflect"
+ "testing"
+)
+
+func TestFixerSSHKeyPath_Impl(t *testing.T) {
+ var _ Fixer = new(FixerSSHKeyPath)
+}
+
+func TestFixerSSHKeyPath_Fix(t *testing.T) {
+ cases := []struct {
+ Input map[string]interface{}
+ Expected map[string]interface{}
+ }{
+ // No key_path field
+ {
+ Input: map[string]interface{}{
+ "type": "virtualbox",
+ },
+
+ Expected: map[string]interface{}{
+ "type": "virtualbox",
+ },
+ },
+
+ // private_key_file without key_path
+ {
+ Input: map[string]interface{}{
+ "ssh_private_key_file": "id_rsa",
+ },
+
+ Expected: map[string]interface{}{
+ "ssh_private_key_file": "id_rsa",
+ },
+ },
+
+ // key_path without private_key_file
+ {
+ Input: map[string]interface{}{
+ "ssh_key_path": "id_rsa",
+ },
+
+ Expected: map[string]interface{}{
+ "ssh_private_key_file": "id_rsa",
+ },
+ },
+
+ // key_path and private_key_file
+ {
+ Input: map[string]interface{}{
+ "ssh_key_path": "key_id_rsa",
+ "ssh_private_key_file": "private_id_rsa",
+ },
+
+ Expected: map[string]interface{}{
+ "ssh_private_key_file": "private_id_rsa",
+ },
+ },
+ }
+
+ for _, tc := range cases {
+ var f FixerSSHKeyPath
+
+ input := map[string]interface{}{
+ "builders": []map[string]interface{}{tc.Input},
+ }
+
+ expected := map[string]interface{}{
+ "builders": []map[string]interface{}{tc.Expected},
+ }
+
+ output, err := f.Fix(input)
+ if err != nil {
+ t.Fatalf("err: %s", err)
+ }
+
+ if !reflect.DeepEqual(output, expected) {
+ t.Fatalf("unexpected: %#v\nexpected: %#v\n", output, expected)
+ }
+ }
+}
diff --git a/v1.9.4/fix/fixer_test.go b/v1.9.4/fix/fixer_test.go
new file mode 100644
index 0000000..091084a
--- /dev/null
+++ b/v1.9.4/fix/fixer_test.go
@@ -0,0 +1,32 @@
+// Copyright (c) HashiCorp, Inc.
+// SPDX-License-Identifier: MPL-2.0
+
+package fix
+
+import (
+ "testing"
+)
+
+func TestFix_allFixersEnabled(t *testing.T) {
+ f := Fixers
+ o := FixerOrder
+
+ if len(f) != len(o) {
+ t.Fatalf("Fixers length (%d) does not match FixerOrder length (%d)", len(f), len(o))
+ }
+
+ for fixer := range f {
+ found := false
+
+ for _, orderedFixer := range o {
+ if orderedFixer == fixer {
+ found = true
+ break
+ }
+ }
+
+ if !found {
+ t.Fatalf("Did not find Fixer %s in FixerOrder", fixer)
+ }
+ }
+}
diff --git a/v1.9.4/fix/fixer_virtualbox_gaattach.go b/v1.9.4/fix/fixer_virtualbox_gaattach.go
new file mode 100644
index 0000000..23e8c7f
--- /dev/null
+++ b/v1.9.4/fix/fixer_virtualbox_gaattach.go
@@ -0,0 +1,72 @@
+// Copyright (c) HashiCorp, Inc.
+// SPDX-License-Identifier: MPL-2.0
+
+package fix
+
+import (
+ "github.com/mitchellh/mapstructure"
+)
+
+// FixerVirtualBoxGAAttach changes the "guest_additions_attach" of a template
+// to "guest_additions_mode".
+type FixerVirtualBoxGAAttach struct{}
+
+func (FixerVirtualBoxGAAttach) DeprecatedOptions() map[string][]string {
+ return map[string][]string{
+ "mitchellh.virtualbox": []string{"guest_additions_attach"},
+ }
+}
+
+func (FixerVirtualBoxGAAttach) Fix(input map[string]interface{}) (map[string]interface{}, error) {
+ // The type we'll decode into; we only care about builders
+ type template struct {
+ Builders []map[string]interface{}
+ }
+
+ // Decode the input into our structure, if we can
+ var tpl template
+ if err := mapstructure.Decode(input, &tpl); err != nil {
+ return nil, err
+ }
+
+ for _, builder := range tpl.Builders {
+ builderTypeRaw, ok := builder["type"]
+ if !ok {
+ continue
+ }
+
+ builderType, ok := builderTypeRaw.(string)
+ if !ok {
+ continue
+ }
+
+ if builderType != "virtualbox" {
+ continue
+ }
+
+ gaAttachRaw, ok := builder["guest_additions_attach"]
+ if !ok {
+ continue
+ }
+
+ gaAttach, ok := gaAttachRaw.(bool)
+ if !ok {
+ continue
+ }
+
+ gaMode := "upload"
+ if gaAttach {
+ gaMode = "attach"
+ }
+
+ delete(builder, "guest_additions_attach")
+ builder["guest_additions_mode"] = gaMode
+ }
+
+ input["builders"] = tpl.Builders
+ return input, nil
+}
+
+func (FixerVirtualBoxGAAttach) Synopsis() string {
+ return `Updates VirtualBox builders using "guest_additions_attach" to use "guest_additions_mode"`
+}
diff --git a/v1.9.4/fix/fixer_virtualbox_gaattach_test.go b/v1.9.4/fix/fixer_virtualbox_gaattach_test.go
new file mode 100644
index 0000000..83fa00b
--- /dev/null
+++ b/v1.9.4/fix/fixer_virtualbox_gaattach_test.go
@@ -0,0 +1,91 @@
+// Copyright (c) HashiCorp, Inc.
+// SPDX-License-Identifier: MPL-2.0
+
+package fix
+
+import (
+ "reflect"
+ "testing"
+)
+
+func TestFixerVirtualBoxGAAttach_Impl(t *testing.T) {
+ var _ Fixer = new(FixerVirtualBoxGAAttach)
+}
+
+func TestFixerVirtualBoxGAAttach_Fix(t *testing.T) {
+ cases := []struct {
+ Input map[string]interface{}
+ Expected map[string]interface{}
+ }{
+ // No attach field
+ {
+ Input: map[string]interface{}{
+ "type": "virtualbox",
+ },
+
+ Expected: map[string]interface{}{
+ "type": "virtualbox",
+ },
+ },
+
+ // Attach field == false
+ {
+ Input: map[string]interface{}{
+ "type": "virtualbox",
+ "guest_additions_attach": false,
+ },
+
+ Expected: map[string]interface{}{
+ "type": "virtualbox",
+ "guest_additions_mode": "upload",
+ },
+ },
+
+ // Attach field == true
+ {
+ Input: map[string]interface{}{
+ "type": "virtualbox",
+ "guest_additions_attach": true,
+ },
+
+ Expected: map[string]interface{}{
+ "type": "virtualbox",
+ "guest_additions_mode": "attach",
+ },
+ },
+
+ // Attach field is not a bool
+ {
+ Input: map[string]interface{}{
+ "type": "virtualbox",
+ "guest_additions_attach": "what",
+ },
+
+ Expected: map[string]interface{}{
+ "type": "virtualbox",
+ "guest_additions_attach": "what",
+ },
+ },
+ }
+
+ for _, tc := range cases {
+ var f FixerVirtualBoxGAAttach
+
+ input := map[string]interface{}{
+ "builders": []map[string]interface{}{tc.Input},
+ }
+
+ expected := map[string]interface{}{
+ "builders": []map[string]interface{}{tc.Expected},
+ }
+
+ output, err := f.Fix(input)
+ if err != nil {
+ t.Fatalf("err: %s", err)
+ }
+
+ if !reflect.DeepEqual(output, expected) {
+ t.Fatalf("unexpected: %#v\nexpected: %#v\n", output, expected)
+ }
+ }
+}
diff --git a/v1.9.4/fix/fixer_virtualbox_rename.go b/v1.9.4/fix/fixer_virtualbox_rename.go
new file mode 100644
index 0000000..a3723f2
--- /dev/null
+++ b/v1.9.4/fix/fixer_virtualbox_rename.go
@@ -0,0 +1,85 @@
+// Copyright (c) HashiCorp, Inc.
+// SPDX-License-Identifier: MPL-2.0
+
+package fix
+
+import (
+ "github.com/mitchellh/mapstructure"
+)
+
+// FixerVirtualBoxRename changes "virtualbox" builders to "virtualbox-iso"
+type FixerVirtualBoxRename struct{}
+
+func (FixerVirtualBoxRename) DeprecatedOptions() map[string][]string {
+ return map[string][]string{}
+}
+
+func (FixerVirtualBoxRename) Fix(input map[string]interface{}) (map[string]interface{}, error) {
+ type template struct {
+ Builders []map[string]interface{}
+ Provisioners []interface{}
+ }
+
+ // Decode the input into our structure, if we can
+ var tpl template
+ if err := mapstructure.WeakDecode(input, &tpl); err != nil {
+ return nil, err
+ }
+
+ for _, builder := range tpl.Builders {
+ builderTypeRaw, ok := builder["type"]
+ if !ok {
+ continue
+ }
+
+ builderType, ok := builderTypeRaw.(string)
+ if !ok {
+ continue
+ }
+
+ if builderType != "virtualbox" {
+ continue
+ }
+
+ builder["type"] = "virtualbox-iso"
+ }
+
+ for i, raw := range tpl.Provisioners {
+ var m map[string]interface{}
+ if err := mapstructure.WeakDecode(raw, &m); err != nil {
+ // Ignore errors, could be a non-map
+ continue
+ }
+
+ raw, ok := m["override"]
+ if !ok {
+ continue
+ }
+
+ var override map[string]interface{}
+ if err := mapstructure.WeakDecode(raw, &override); err != nil {
+ return nil, err
+ }
+
+ if raw, ok := override["virtualbox"]; ok {
+ override["virtualbox-iso"] = raw
+ delete(override, "virtualbox")
+
+ // Set the change
+ m["override"] = override
+ tpl.Provisioners[i] = m
+ }
+ }
+
+ if len(tpl.Builders) > 0 {
+ input["builders"] = tpl.Builders
+ }
+ if len(tpl.Provisioners) > 0 {
+ input["provisioners"] = tpl.Provisioners
+ }
+ return input, nil
+}
+
+func (FixerVirtualBoxRename) Synopsis() string {
+ return `Updates "virtualbox" builders to "virtualbox-iso"`
+}
diff --git a/v1.9.4/fix/fixer_virtualbox_rename_test.go b/v1.9.4/fix/fixer_virtualbox_rename_test.go
new file mode 100644
index 0000000..fc570f3
--- /dev/null
+++ b/v1.9.4/fix/fixer_virtualbox_rename_test.go
@@ -0,0 +1,93 @@
+// Copyright (c) HashiCorp, Inc.
+// SPDX-License-Identifier: MPL-2.0
+
+package fix
+
+import (
+ "reflect"
+ "testing"
+)
+
+func TestFixerVirtualBoxRename_impl(t *testing.T) {
+ var _ Fixer = new(FixerVirtualBoxRename)
+}
+
+func TestFixerVirtualBoxRename_Fix(t *testing.T) {
+ cases := []struct {
+ Input map[string]interface{}
+ Expected map[string]interface{}
+ }{
+ {
+ Input: map[string]interface{}{
+ "type": "virtualbox",
+ },
+
+ Expected: map[string]interface{}{
+ "type": "virtualbox-iso",
+ },
+ },
+ }
+
+ for _, tc := range cases {
+ var f FixerVirtualBoxRename
+
+ input := map[string]interface{}{
+ "builders": []map[string]interface{}{tc.Input},
+ }
+
+ expected := map[string]interface{}{
+ "builders": []map[string]interface{}{tc.Expected},
+ }
+
+ output, err := f.Fix(input)
+ if err != nil {
+ t.Fatalf("err: %s", err)
+ }
+
+ if !reflect.DeepEqual(output, expected) {
+ t.Fatalf("unexpected: %#v\nexpected: %#v\n", output, expected)
+ }
+ }
+}
+
+func TestFixerVirtualBoxRenameFix_provisionerOverride(t *testing.T) {
+ cases := []struct {
+ Input map[string]interface{}
+ Expected map[string]interface{}
+ }{
+ {
+ Input: map[string]interface{}{
+ "provisioners": []interface{}{
+ map[string]interface{}{
+ "override": map[string]interface{}{
+ "virtualbox": map[string]interface{}{},
+ },
+ },
+ },
+ },
+
+ Expected: map[string]interface{}{
+ "provisioners": []interface{}{
+ map[string]interface{}{
+ "override": map[string]interface{}{
+ "virtualbox-iso": map[string]interface{}{},
+ },
+ },
+ },
+ },
+ },
+ }
+
+ for _, tc := range cases {
+ var f FixerVirtualBoxRename
+
+ output, err := f.Fix(tc.Input)
+ if err != nil {
+ t.Fatalf("err: %s", err)
+ }
+
+ if !reflect.DeepEqual(output, tc.Expected) {
+ t.Fatalf("unexpected:\n\n%#v\nexpected:\n\n%#v\n", output, tc.Expected)
+ }
+ }
+}
diff --git a/v1.9.4/fix/fixer_vmware_compaction.go b/v1.9.4/fix/fixer_vmware_compaction.go
new file mode 100644
index 0000000..906ff4d
--- /dev/null
+++ b/v1.9.4/fix/fixer_vmware_compaction.go
@@ -0,0 +1,98 @@
+// Copyright (c) HashiCorp, Inc.
+// SPDX-License-Identifier: MPL-2.0
+
+package fix
+
+import (
+ "github.com/mitchellh/mapstructure"
+)
+
+// FixerVMwareCompaction adds "skip_compaction = true" to "vmware-iso" builders with incompatible disk_type_id
+type FixerVMwareCompaction struct{}
+
+func (FixerVMwareCompaction) DeprecatedOptions() map[string][]string {
+ return map[string][]string{}
+}
+
+func (FixerVMwareCompaction) Fix(input map[string]interface{}) (map[string]interface{}, error) {
+ // The type we'll decode into; we only care about builders
+ type template struct {
+ Builders []map[string]interface{}
+ }
+
+ // Decode the input into our structure, if we can
+ var tpl template
+ if err := mapstructure.Decode(input, &tpl); err != nil {
+ return nil, err
+ }
+
+ for _, builder := range tpl.Builders {
+ builderTypeRaw, ok := builder["type"]
+ if !ok {
+ continue
+ }
+
+ builderType, ok := builderTypeRaw.(string)
+ if !ok {
+ continue
+ }
+
+ if builderType != "vmware-iso" {
+ continue
+ }
+
+ builderRemoteTypeRaw, ok := builder["remote_type"]
+ if !ok {
+ continue
+ }
+
+ builderRemoteType, ok := builderRemoteTypeRaw.(string)
+ if !ok {
+ continue
+ }
+
+ if builderRemoteType != "esx5" {
+ continue
+ }
+
+ builderDiskTypeIdRaw, ok := builder["disk_type_id"]
+ // set to default when this fixer was added due to incompatibility of defaults
+ if !ok {
+ builderDiskTypeId := "zeroedthick"
+ builder["disk_type_id"] = builderDiskTypeId
+ }
+
+ if ok {
+ builderDiskTypeId, ok := builderDiskTypeIdRaw.(string)
+ if !ok {
+ continue
+ }
+ if builderDiskTypeId == "thin" {
+ continue
+ }
+ }
+
+ builderSkipCompactionRaw, ok := builder["skip_compaction"]
+ // already verified this is not creating a "thin" disk, will need to skip_compaction
+ if ok {
+ builderSkipCompaction, ok := builderSkipCompactionRaw.(bool)
+ if !ok {
+ continue
+ }
+ if !builderSkipCompaction {
+ builder["skip_compaction"] = !builderSkipCompaction
+ }
+ continue
+ }
+
+ builderSkipCompaction := true
+ builder["skip_compaction"] = builderSkipCompaction
+ }
+
+ input["builders"] = tpl.Builders
+ return input, nil
+}
+
+func (FixerVMwareCompaction) Synopsis() string {
+ return `Adds "skip_compaction = true" to "vmware-iso" builders with incompatible disk_type_id`
+}
diff --git a/v1.9.4/fix/fixer_vmware_compaction_test.go b/v1.9.4/fix/fixer_vmware_compaction_test.go
new file mode 100644
index 0000000..bd10770
--- /dev/null
+++ b/v1.9.4/fix/fixer_vmware_compaction_test.go
@@ -0,0 +1,115 @@
+// Copyright (c) HashiCorp, Inc.
+// SPDX-License-Identifier: MPL-2.0
+
+package fix
+
+import (
+ "reflect"
+ "testing"
+)
+
+func TestFixerVMwareCompaction_impl(t *testing.T) {
+ var _ Fixer = new(FixerVMwareCompaction)
+}
+
+func TestFixerVMwareCompaction_Fix(t *testing.T) {
+ cases := []struct {
+ Input map[string]interface{}
+ Expected map[string]interface{}
+ }{
+ {
+ Input: map[string]interface{}{
+ "type": "virtualbox-iso",
+ },
+
+ Expected: map[string]interface{}{
+ "type": "virtualbox-iso",
+ },
+ },
+ {
+ Input: map[string]interface{}{
+ "type": "vmware-iso",
+ },
+
+ Expected: map[string]interface{}{
+ "type": "vmware-iso",
+ },
+ },
+ {
+ Input: map[string]interface{}{
+ "type": "vmware-iso",
+ "remote_type": "esx5",
+ },
+
+ Expected: map[string]interface{}{
+ "type": "vmware-iso",
+ "remote_type": "esx5",
+ "disk_type_id": "zeroedthick",
+ "skip_compaction": true,
+ },
+ },
+ {
+ Input: map[string]interface{}{
+ "type": "vmware-iso",
+ "remote_type": "esx5",
+ "disk_type_id": "zeroedthick",
+ },
+
+ Expected: map[string]interface{}{
+ "type": "vmware-iso",
+ "remote_type": "esx5",
+ "disk_type_id": "zeroedthick",
+ "skip_compaction": true,
+ },
+ },
+ {
+ Input: map[string]interface{}{
+ "type": "vmware-iso",
+ "remote_type": "esx5",
+ "disk_type_id": "zeroedthick",
+ "skip_compaction": false,
+ },
+
+ Expected: map[string]interface{}{
+ "type": "vmware-iso",
+ "remote_type": "esx5",
+ "disk_type_id": "zeroedthick",
+ "skip_compaction": true,
+ },
+ },
+ {
+ Input: map[string]interface{}{
+ "type": "vmware-iso",
+ "remote_type": "esx5",
+ "disk_type_id": "thin",
+ },
+
+ Expected: map[string]interface{}{
+ "type": "vmware-iso",
+ "remote_type": "esx5",
+ "disk_type_id": "thin",
+ },
+ },
+ }
+
+ for _, tc := range cases {
+ var f FixerVMwareCompaction
+
+ input := map[string]interface{}{
+ "builders": []map[string]interface{}{tc.Input},
+ }
+
+ expected := map[string]interface{}{
+ "builders": []map[string]interface{}{tc.Expected},
+ }
+
+ output, err := f.Fix(input)
+ if err != nil {
+ t.Fatalf("err: %s", err)
+ }
+
+ if !reflect.DeepEqual(output, expected) {
+ t.Fatalf("unexpected: %#v\nexpected: %#v\n", output, expected)
+ }
+ }
+}
diff --git a/v1.9.4/fix/fixer_vmware_rename.go b/v1.9.4/fix/fixer_vmware_rename.go
new file mode 100644
index 0000000..5e7db8a
--- /dev/null
+++ b/v1.9.4/fix/fixer_vmware_rename.go
@@ -0,0 +1,53 @@
+// Copyright (c) HashiCorp, Inc.
+// SPDX-License-Identifier: MPL-2.0
+
+package fix
+
+import (
+ "github.com/mitchellh/mapstructure"
+)
+
+// FixerVMwareRename changes "vmware" builders to "vmware-iso"
+type FixerVMwareRename struct{}
+
+func (FixerVMwareRename) DeprecatedOptions() map[string][]string {
+ return map[string][]string{}
+}
+
+func (FixerVMwareRename) Fix(input map[string]interface{}) (map[string]interface{}, error) {
+ // The type we'll decode into; we only care about builders
+ type template struct {
+ Builders []map[string]interface{}
+ }
+
+ // Decode the input into our structure, if we can
+ var tpl template
+ if err := mapstructure.Decode(input, &tpl); err != nil {
+ return nil, err
+ }
+
+ for _, builder := range tpl.Builders {
+ builderTypeRaw, ok := builder["type"]
+ if !ok {
+ continue
+ }
+
+ builderType, ok := builderTypeRaw.(string)
+ if !ok {
+ continue
+ }
+
+ if builderType != "vmware" {
+ continue
+ }
+
+ builder["type"] = "vmware-iso"
+ }
+
+ input["builders"] = tpl.Builders
+ return input, nil
+}
+
+func (FixerVMwareRename) Synopsis() string {
+ return `Updates "vmware" builders to "vmware-iso"`
+}
diff --git a/v1.9.4/fix/fixer_vmware_rename_test.go b/v1.9.4/fix/fixer_vmware_rename_test.go
new file mode 100644
index 0000000..6d8710c
--- /dev/null
+++ b/v1.9.4/fix/fixer_vmware_rename_test.go
@@ -0,0 +1,51 @@
+// Copyright (c) HashiCorp, Inc.
+// SPDX-License-Identifier: MPL-2.0
+
+package fix
+
+import (
+ "reflect"
+ "testing"
+)
+
+func TestFixerVMwareRename_impl(t *testing.T) {
+ var _ Fixer = new(FixerVMwareRename)
+}
+
+func TestFixerVMwareRename_Fix(t *testing.T) {
+ cases := []struct {
+ Input map[string]interface{}
+ Expected map[string]interface{}
+ }{
+ {
+ Input: map[string]interface{}{
+ "type": "vmware",
+ },
+
+ Expected: map[string]interface{}{
+ "type": "vmware-iso",
+ },
+ },
+ }
+
+ for _, tc := range cases {
+ var f FixerVMwareRename
+
+ input := map[string]interface{}{
+ "builders": []map[string]interface{}{tc.Input},
+ }
+
+ expected := map[string]interface{}{
+ "builders": []map[string]interface{}{tc.Expected},
+ }
+
+ output, err := f.Fix(input)
+ if err != nil {
+ t.Fatalf("err: %s", err)
+ }
+
+ if !reflect.DeepEqual(output, expected) {
+ t.Fatalf("unexpected: %#v\nexpected: %#v\n", output, expected)
+ }
+ }
+}
diff --git a/v1.9.4/fix/fixer_vsphere_network_storage.go b/v1.9.4/fix/fixer_vsphere_network_storage.go
new file mode 100644
index 0000000..87723a9
--- /dev/null
+++ b/v1.9.4/fix/fixer_vsphere_network_storage.go
@@ -0,0 +1,130 @@
+// Copyright (c) HashiCorp, Inc.
+// SPDX-License-Identifier: MPL-2.0
+
+package fix
+
+import (
+ "github.com/mitchellh/mapstructure"
+)
+
+// FixerVSphereNetworkDisk changes vsphere-iso network and networkCard fields
+// into a network adapter and changes the disk_size, disk_thin_provisioned, and
+// disk_eagerly_scrub into a storage adapter
+type FixerVSphereNetworkDisk struct{}
+
+func (FixerVSphereNetworkDisk) DeprecatedOptions() map[string][]string {
+ return map[string][]string{
+ "jetbrains.vsphere": []string{"network_card", "network", "networkCard", "disk_size",
+ "disk_thin_provisioned", "disk_eagerly_scrub"},
+ }
+}
+
+func (FixerVSphereNetworkDisk) Fix(input map[string]interface{}) (map[string]interface{}, error) {
+ // The type we'll decode into; we only care about builders
+ type template struct {
+ Builders []map[string]interface{}
+ }
+
+ // Decode the input into our structure, if we can
+ var tpl template
+ if err := mapstructure.Decode(input, &tpl); err != nil {
+ return nil, err
+ }
+
+ for _, builder := range tpl.Builders {
+ builderTypeRaw, ok := builder["type"]
+ if !ok {
+ continue
+ }
+
+ builderType, ok := builderTypeRaw.(string)
+ if !ok {
+ continue
+ }
+
+ if builderType != "vsphere-iso" {
+ continue
+ }
+
+ var networkAdapters []interface{}
+ nic := make(map[string]interface{})
+ hasNetwork := false
+
+ networkRaw, ok := builder["network"]
+ if ok {
+ nic["network"] = networkRaw
+ delete(builder, "network")
+ hasNetwork = true
+ }
+
+ // legacy syntax from when VSphere was 3rd party
+ networkCardRaw, ok := builder["networkCard"]
+ if ok {
+ nic["network_card"] = networkCardRaw
+ delete(builder, "networkCard")
+ hasNetwork = true
+ }
+
+ // underscored syntax used when Packer merged vSphere
+ networkCardRaw, ok = builder["network_card"]
+ if ok {
+ nic["network_card"] = networkCardRaw
+ delete(builder, "network_card")
+ hasNetwork = true
+ }
+
+ if hasNetwork {
+ networkAdapters = append(networkAdapters, nic)
+ adaptersRaw, ok := builder["network_adapters"]
+ if ok {
+ existingAdapters := adaptersRaw.([]interface{})
+ networkAdapters = append(networkAdapters, existingAdapters...)
+ }
+
+ builder["network_adapters"] = networkAdapters
+ }
+
+ var storage []interface{}
+ disk := make(map[string]interface{})
+ hasStorage := false
+
+ diskSizeRaw, ok := builder["disk_size"]
+ if ok {
+ disk["disk_size"] = diskSizeRaw
+ delete(builder, "disk_size")
+ hasStorage = true
+ }
+
+ discThinProvisionedRaw, ok := builder["disk_thin_provisioned"]
+ if ok {
+ disk["disk_thin_provisioned"] = discThinProvisionedRaw
+ hasStorage = true
+ delete(builder, "disk_thin_provisioned")
+ }
+
+ diskEagerlyScrubRaw, ok := builder["disk_eagerly_scrub"]
+ if ok {
+ disk["disk_eagerly_scrub"] = diskEagerlyScrubRaw
+ hasStorage = true
+ delete(builder, "disk_eagerly_scrub")
+ }
+
+ if hasStorage {
+ storage = append(storage, disk)
+ storageRaw, ok := builder["storage"]
+ if ok {
+ existingStorage := storageRaw.([]interface{})
+ storage = append(storage, existingStorage...)
+ }
+
+ builder["storage"] = storage
+ }
+ }
+
+ input["builders"] = tpl.Builders
+ return input, nil
+}
+
+func (FixerVSphereNetworkDisk) Synopsis() string {
+ return `Removes deprecated network and disk fields from "vsphere-iso" builder`
+}
diff --git a/v1.9.4/fix/fixer_vsphere_network_storage_test.go b/v1.9.4/fix/fixer_vsphere_network_storage_test.go
new file mode 100644
index 0000000..54ebb80
--- /dev/null
+++ b/v1.9.4/fix/fixer_vsphere_network_storage_test.go
@@ -0,0 +1,164 @@
+// Copyright (c) HashiCorp, Inc.
+// SPDX-License-Identifier: MPL-2.0
+
+package fix
+
+import (
+ "reflect"
+ "testing"
+)
+
+func TestFixerVSphereNetwork_impl(t *testing.T) {
+ var _ Fixer = new(FixerVSphereNetworkDisk)
+}
+
+func TestFixerVSphereNetwork_Fix(t *testing.T) {
+ cases := []struct {
+ Input map[string]interface{}
+ Expected map[string]interface{}
+ }{
+ {
+ Input: map[string]interface{}{
+ "type": "vsphere-iso",
+ "network": "",
+ "networkCard": "vmxnet3",
+ "disk_size": 5000,
+ },
+
+ Expected: map[string]interface{}{
+ "type": "vsphere-iso",
+ "network_adapters": []interface{}{
+ map[string]interface{}{
+ "network": "",
+ "network_card": "vmxnet3",
+ },
+ },
+ "storage": []interface{}{
+ map[string]interface{}{
+ "disk_size": 5000,
+ },
+ },
+ },
+ },
+ {
+ Input: map[string]interface{}{
+ "type": "vsphere-iso",
+ "network": "",
+ "network_card": "vmxnet3",
+ "disk_size": 5000,
+ },
+
+ Expected: map[string]interface{}{
+ "type": "vsphere-iso",
+ "network_adapters": []interface{}{
+ map[string]interface{}{
+ "network": "",
+ "network_card": "vmxnet3",
+ },
+ },
+ "storage": []interface{}{
+ map[string]interface{}{
+ "disk_size": 5000,
+ },
+ },
+ },
+ },
+ {
+ Input: map[string]interface{}{
+ "type": "vsphere-iso",
+ "network": "myNetwork",
+ "networkCard": "vmxnet3",
+ "disk_size": 5000,
+ "disk_thin_provisioned": true,
+ "disk_eagerly_scrub": true,
+ },
+
+ Expected: map[string]interface{}{
+ "type": "vsphere-iso",
+ "network_adapters": []interface{}{
+ map[string]interface{}{
+ "network": "myNetwork",
+ "network_card": "vmxnet3",
+ },
+ },
+ "storage": []interface{}{
+ map[string]interface{}{
+ "disk_size": 5000,
+ "disk_thin_provisioned": true,
+ "disk_eagerly_scrub": true,
+ },
+ },
+ },
+ },
+ {
+ Input: map[string]interface{}{
+ "type": "vsphere-iso",
+ "network": "myNetwork",
+ "networkCard": "vmxnet3",
+ "disk_size": 5000,
+ "disk_thin_provisioned": true,
+ "disk_eagerly_scrub": true,
+ "network_adapters": []interface{}{
+ map[string]interface{}{
+ "network": "net1",
+ "network_card": "vmxnet3",
+ },
+ },
+ "storage": []interface{}{
+ map[string]interface{}{
+ "disk_size": 5001,
+ "disk_thin_provisioned": true,
+ "disk_eagerly_scrub": true,
+ },
+ },
+ },
+
+ Expected: map[string]interface{}{
+ "type": "vsphere-iso",
+ "network_adapters": []interface{}{
+ map[string]interface{}{
+ "network": "myNetwork",
+ "network_card": "vmxnet3",
+ },
+ map[string]interface{}{
+ "network": "net1",
+ "network_card": "vmxnet3",
+ },
+ },
+ "storage": []interface{}{
+ map[string]interface{}{
+ "disk_size": 5000,
+ "disk_thin_provisioned": true,
+ "disk_eagerly_scrub": true,
+ },
+ map[string]interface{}{
+ "disk_size": 5001,
+ "disk_thin_provisioned": true,
+ "disk_eagerly_scrub": true,
+ },
+ },
+ },
+ },
+ }
+
+ for _, tc := range cases {
+ var f FixerVSphereNetworkDisk
+
+ input := map[string]interface{}{
+ "builders": []map[string]interface{}{tc.Input},
+ }
+
+ expected := map[string]interface{}{
+ "builders": []map[string]interface{}{tc.Expected},
+ }
+
+ output, err := f.Fix(input)
+ if err != nil {
+ t.Fatalf("err: %s", err)
+ }
+
+ if !reflect.DeepEqual(output, expected) {
+ t.Fatalf("unexpected: %#v\nexpected: %#v\n", output, expected)
+ }
+ }
+}
diff --git a/v1.9.4/fix/helpers.go b/v1.9.4/fix/helpers.go
new file mode 100644
index 0000000..f381267
--- /dev/null
+++ b/v1.9.4/fix/helpers.go
@@ -0,0 +1,28 @@
+// Copyright (c) HashiCorp, Inc.
+// SPDX-License-Identifier: MPL-2.0
+
+package fix
+
+// PP is a convenient way to interact with the post-processors within a fixer
+type PP struct {
+ PostProcessors []interface{} `mapstructure:"post-processors"`
+}
+
+// postProcessors converts the variable structure of the template to a list
+func (pp *PP) ppList() []map[string]interface{} {
+ pps := make([]map[string]interface{}, 0, len(pp.PostProcessors))
+ for _, rawPP := range pp.PostProcessors {
+ switch pp := rawPP.(type) {
+ case string:
+ case map[string]interface{}:
+ pps = append(pps, pp)
+ case []interface{}:
+ for _, innerRawPP := range pp {
+ if innerPP, ok := innerRawPP.(map[string]interface{}); ok {
+ pps = append(pps, innerPP)
+ }
+ }
+ }
+ }
+ return pps
+}
diff --git a/v1.9.4/go.mod b/v1.9.4/go.mod
new file mode 100644
index 0000000..ab2d8ed
--- /dev/null
+++ b/v1.9.4/go.mod
@@ -0,0 +1,215 @@
+module github.com/hashicorp/packer
+
+require (
+ cloud.google.com/go v0.105.0 // indirect
+ github.com/biogo/hts v1.4.3
+ github.com/cheggaaa/pb v1.0.27
+ github.com/chzyer/readline v0.0.0-20180603132655-2972be24d48e
+ github.com/dsnet/compress v0.0.1
+ github.com/go-git/go-git/v5 v5.4.2
+ github.com/go-openapi/runtime v0.25.0
+ github.com/gobwas/glob v0.2.3
+ github.com/gofrs/flock v0.8.1 // indirect
+ github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da // indirect
+ github.com/google/go-cmp v0.5.9
+ github.com/google/go-github/v33 v33.0.1-0.20210113204525-9318e629ec69
+ github.com/google/go-querystring v1.1.0 // indirect
+ github.com/hako/durafmt v0.0.0-20200710122514-c0fb7b4da026
+ github.com/hashicorp/go-checkpoint v0.0.0-20171009173528-1545e56e46de
+ github.com/hashicorp/go-cty-funcs v0.0.0-20200930094925-2721b1e36840
+ github.com/hashicorp/go-getter/v2 v2.2.0
+ github.com/hashicorp/go-multierror v1.1.1
+ github.com/hashicorp/go-uuid v1.0.2
+ github.com/hashicorp/go-version v1.6.0
+ github.com/hashicorp/hcl/v2 v2.14.1
+ github.com/hashicorp/hcp-sdk-go v0.36.0
+ github.com/hashicorp/packer-plugin-amazon v1.2.1
+ github.com/hashicorp/packer-plugin-sdk v0.4.0
+ github.com/jehiah/go-strftime v0.0.0-20171201141054-1d33003b3869
+ github.com/klauspost/compress v1.13.6 // indirect
+ github.com/klauspost/pgzip v1.2.5
+ github.com/masterzen/winrm v0.0.0-20210623064412-3b76017826b0
+ github.com/mattn/go-runewidth v0.0.13 // indirect
+ github.com/mattn/go-tty v0.0.0-20191112051231-74040eebce08
+ github.com/mitchellh/cli v1.1.2
+ github.com/mitchellh/go-fs v0.0.0-20180402235330-b7b9ca407fff // indirect
+ github.com/mitchellh/go-homedir v1.1.0
+ github.com/mitchellh/mapstructure v1.5.0
+ github.com/mitchellh/panicwrap v1.0.0
+ github.com/mitchellh/prefixedio v0.0.0-20151214002211-6e6954073784
+ github.com/packer-community/winrmcp v0.0.0-20180921211025-c76d91c1e7db // indirect
+ github.com/pierrec/lz4 v2.6.1+incompatible
+ github.com/pkg/sftp v1.13.2 // indirect
+ github.com/posener/complete v1.2.3
+ github.com/stretchr/testify v1.8.2
+ github.com/ulikunitz/xz v0.5.10
+ github.com/zclconf/go-cty v1.10.0
+ github.com/zclconf/go-cty-yaml v1.0.1
+ golang.org/x/crypto v0.11.0 // indirect
+ golang.org/x/mod v0.8.0
+ golang.org/x/net v0.13.0
+ golang.org/x/oauth2 v0.1.0
+ golang.org/x/sync v0.1.0
+ golang.org/x/sys v0.10.0 // indirect
+ golang.org/x/term v0.10.0 // indirect
+ golang.org/x/text v0.11.0 // indirect
+ golang.org/x/tools v0.6.0
+ google.golang.org/api v0.101.0 // indirect
+ google.golang.org/grpc v1.50.1
+)
+
+require (
+ github.com/go-openapi/strfmt v0.21.3
+ github.com/hashicorp/packer-plugin-ansible v1.0.3
+ github.com/hashicorp/packer-plugin-azure v1.4.0
+ github.com/hashicorp/packer-plugin-docker v1.0.8
+ github.com/hashicorp/packer-plugin-googlecompute v1.1.0
+ github.com/hashicorp/packer-plugin-qemu v1.0.9
+ github.com/hashicorp/packer-plugin-vagrant v1.0.3
+ github.com/hashicorp/packer-plugin-virtualbox v1.0.4
+ github.com/hashicorp/packer-plugin-vmware v1.0.7
+ github.com/hashicorp/packer-plugin-vsphere v1.1.1
+ github.com/oklog/ulid v1.3.1
+ github.com/shirou/gopsutil/v3 v3.23.4
+)
+
+require (
+ cloud.google.com/go/compute v1.12.1 // indirect
+ cloud.google.com/go/compute/metadata v0.1.1 // indirect
+ cloud.google.com/go/iam v0.6.0 // indirect
+ cloud.google.com/go/storage v1.27.0 // indirect
+ github.com/Azure/azure-sdk-for-go v64.0.0+incompatible // indirect
+ github.com/Azure/go-autorest v14.2.0+incompatible // indirect
+ github.com/Azure/go-autorest/autorest v0.11.19 // indirect
+ github.com/Azure/go-autorest/autorest/adal v0.9.18 // indirect
+ github.com/Azure/go-autorest/autorest/azure/auth v0.4.2 // indirect
+ github.com/Azure/go-autorest/autorest/azure/cli v0.4.2 // indirect
+ github.com/Azure/go-autorest/autorest/date v0.3.0 // indirect
+ github.com/Azure/go-autorest/autorest/to v0.4.0 // indirect
+ github.com/Azure/go-autorest/autorest/validation v0.3.1 // indirect
+ github.com/Azure/go-autorest/logger v0.2.1 // indirect
+ github.com/Azure/go-autorest/tracing v0.6.0 // indirect
+ github.com/Azure/go-ntlmssp v0.0.0-20200615164410-66371956d46c // indirect
+ github.com/ChrisTrenkamp/goxpath v0.0.0-20210404020558-97928f7e12b6 // indirect
+ github.com/Masterminds/goutils v1.1.1 // indirect
+ github.com/Masterminds/semver v1.5.0 // indirect
+ github.com/Masterminds/sprig v2.22.0+incompatible // indirect
+ github.com/Microsoft/go-winio v0.4.16 // indirect
+ github.com/ProtonMail/go-crypto v0.0.0-20210428141323-04723f9f07d7 // indirect
+ github.com/acomagu/bufpipe v1.0.3 // indirect
+ github.com/agext/levenshtein v1.2.3 // indirect
+ github.com/apparentlymart/go-cidr v1.0.1 // indirect
+ github.com/apparentlymart/go-textseg/v13 v13.0.0 // indirect
+ github.com/armon/go-metrics v0.3.9 // indirect
+ github.com/armon/go-radix v1.0.0 // indirect
+ github.com/asaskevich/govalidator v0.0.0-20210307081110-f21760c49a8d // indirect
+ github.com/aws/aws-sdk-go v1.44.114 // indirect
+ github.com/bgentry/go-netrc v0.0.0-20140422174119-9fd32a8b3d3d // indirect
+ github.com/bgentry/speakeasy v0.1.0 // indirect
+ github.com/bmatcuk/doublestar v1.1.5 // indirect
+ github.com/cenkalti/backoff/v3 v3.2.2 // indirect
+ github.com/chzyer/test v1.0.0 // indirect
+ github.com/davecgh/go-spew v1.1.1 // indirect
+ github.com/digitalocean/go-libvirt v0.0.0-20201209184759-e2a69bcd5bd1 // indirect
+ github.com/digitalocean/go-qemu v0.0.0-20210326154740-ac9e0b687001 // indirect
+ github.com/dimchansky/utfbom v1.1.1 // indirect
+ github.com/dylanmei/iso8601 v0.1.0 // indirect
+ github.com/emirpasic/gods v1.12.0 // indirect
+ github.com/fatih/color v1.12.0 // indirect
+ github.com/go-git/gcfg v1.5.0 // indirect
+ github.com/go-git/go-billy/v5 v5.3.1 // indirect
+ github.com/go-logr/logr v1.2.3 // indirect
+ github.com/go-logr/stdr v1.2.2 // indirect
+ github.com/go-ole/go-ole v1.2.6 // indirect
+ github.com/go-openapi/analysis v0.21.4 // indirect
+ github.com/go-openapi/errors v0.20.3 // indirect
+ github.com/go-openapi/jsonpointer v0.19.5 // indirect
+ github.com/go-openapi/jsonreference v0.20.0 // indirect
+ github.com/go-openapi/loads v0.21.2 // indirect
+ github.com/go-openapi/spec v0.20.8 // indirect
+ github.com/go-openapi/swag v0.22.3 // indirect
+ github.com/go-openapi/validate v0.22.1 // indirect
+ github.com/gofrs/uuid v4.0.0+incompatible // indirect
+ github.com/golang-collections/collections v0.0.0-20130729185459-604e922904d3 // indirect
+ github.com/golang-jwt/jwt v3.2.2+incompatible // indirect
+ github.com/golang-jwt/jwt/v4 v4.2.0 // indirect
+ github.com/golang/protobuf v1.5.2 // indirect
+ github.com/golang/snappy v0.0.4 // indirect
+ github.com/google/btree v1.0.1 // indirect
+ github.com/google/shlex v0.0.0-20191202100458-e7afc7fbc510 // indirect
+ github.com/google/uuid v1.3.0 // indirect
+ github.com/googleapis/enterprise-certificate-proxy v0.2.0 // indirect
+ github.com/googleapis/gax-go/v2 v2.6.0 // indirect
+ github.com/hashicorp/aws-sdk-go-base v0.7.1 // indirect
+ github.com/hashicorp/consul/api v1.10.1 // indirect
+ github.com/hashicorp/errwrap v1.1.0 // indirect
+ github.com/hashicorp/go-azure-helpers v0.16.5 // indirect
+ github.com/hashicorp/go-cleanhttp v0.5.2 // indirect
+ github.com/hashicorp/go-getter/gcs/v2 v2.2.0 // indirect
+ github.com/hashicorp/go-getter/s3/v2 v2.2.0 // indirect
+ github.com/hashicorp/go-hclog v0.16.2 // indirect
+ github.com/hashicorp/go-immutable-radix v1.3.1 // indirect
+ github.com/hashicorp/go-retryablehttp v0.7.0 // indirect
+ github.com/hashicorp/go-rootcerts v1.0.2 // indirect
+ github.com/hashicorp/go-safetemp v1.0.0 // indirect
+ github.com/hashicorp/go-sockaddr v1.0.2 // indirect
+ github.com/hashicorp/golang-lru v0.5.4 // indirect
+ github.com/hashicorp/hcl v1.0.0 // indirect
+ github.com/hashicorp/serf v0.9.5 // indirect
+ github.com/hashicorp/vault/api v1.1.1 // indirect
+ github.com/hashicorp/vault/sdk v0.2.1 // indirect
+ github.com/hashicorp/yamux v0.0.0-20210826001029-26ff87cf9493 // indirect
+ github.com/huandu/xstrings v1.3.2 // indirect
+ github.com/imdario/mergo v0.3.12 // indirect
+ github.com/jbenet/go-context v0.0.0-20150711004518-d14ea06fba99 // indirect
+ github.com/jmespath/go-jmespath v0.4.0 // indirect
+ github.com/josharian/intern v1.0.0 // indirect
+ github.com/kevinburke/ssh_config v0.0.0-20201106050909-4977a11b4351 // indirect
+ github.com/kr/fs v0.1.0 // indirect
+ github.com/lufia/plan9stats v0.0.0-20211012122336-39d0f177ccd0 // indirect
+ github.com/mailru/easyjson v0.7.7 // indirect
+ github.com/masterzen/simplexml v0.0.0-20190410153822-31eea3082786 // indirect
+ github.com/matryer/is v1.4.0 // indirect
+ github.com/mattn/go-colorable v0.1.8 // indirect
+ github.com/mattn/go-isatty v0.0.13 // indirect
+ github.com/mitchellh/colorstring v0.0.0-20190213212951-d06e56a500db // indirect
+ github.com/mitchellh/copystructure v1.2.0 // indirect
+ github.com/mitchellh/go-testing-interface v1.14.1 // indirect
+ github.com/mitchellh/go-vnc v0.0.0-20150629162542-723ed9867aed // indirect
+ github.com/mitchellh/go-wordwrap v1.0.1 // indirect
+ github.com/mitchellh/iochan v1.0.0 // indirect
+ github.com/mitchellh/reflectwalk v1.0.2 // indirect
+ github.com/nu7hatch/gouuid v0.0.0-20131221200532-179d4d0c4d8d // indirect
+ github.com/opentracing/opentracing-go v1.2.0 // indirect
+ github.com/pkg/errors v0.9.1 // indirect
+ github.com/pmezard/go-difflib v1.0.0 // indirect
+ github.com/power-devops/perfstat v0.0.0-20210106213030-5aafc221ea8c // indirect
+ github.com/rivo/uniseg v0.2.0 // indirect
+ github.com/ryanuber/go-glob v1.0.0 // indirect
+ github.com/sergi/go-diff v1.1.0 // indirect
+ github.com/shoenig/go-m1cpu v0.1.5 // indirect
+ github.com/skratchdot/open-golang v0.0.0-20200116055534-eef842397966 // indirect
+ github.com/tklauser/go-sysconf v0.3.11 // indirect
+ github.com/tklauser/numcpus v0.6.0 // indirect
+ github.com/ugorji/go/codec v1.2.6 // indirect
+ github.com/vmware/govmomi v0.29.0 // indirect
+ github.com/xanzy/ssh-agent v0.3.0 // indirect
+ github.com/yusufpapurcu/wmi v1.2.2 // indirect
+ go.mongodb.org/mongo-driver v1.11.0 // indirect
+ go.opencensus.io v0.23.0 // indirect
+ go.opentelemetry.io/otel v1.11.1 // indirect
+ go.opentelemetry.io/otel/trace v1.11.1 // indirect
+ golang.org/x/mobile v0.0.0-20210901025245-1fde1d6c3ca1 // indirect
+ golang.org/x/time v0.0.0-20220210224613-90d013bbcef8 // indirect
+ golang.org/x/xerrors v0.0.0-20220907171357-04be3eba64a2 // indirect
+ google.golang.org/appengine v1.6.7 // indirect
+ google.golang.org/genproto v0.0.0-20221027153422-115e99e71e1c // indirect
+ google.golang.org/protobuf v1.28.1 // indirect
+ gopkg.in/cheggaaa/pb.v1 v1.0.28 // indirect
+ gopkg.in/square/go-jose.v2 v2.6.0 // indirect
+ gopkg.in/warnings.v0 v0.1.2 // indirect
+ gopkg.in/yaml.v2 v2.4.0 // indirect
+ gopkg.in/yaml.v3 v3.0.1 // indirect
+)
+
+go 1.20
diff --git a/v1.9.4/go.sum b/v1.9.4/go.sum
new file mode 100644
index 0000000..81a0347
--- /dev/null
+++ b/v1.9.4/go.sum
@@ -0,0 +1,1030 @@
+bazil.org/fuse v0.0.0-20160811212531-371fbbdaa898/go.mod h1:Xbm+BRKSBEpa4q4hTSxohYNQpsxXPbPry4JJWOB3LB8=
+cloud.google.com/go v0.26.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw=
+cloud.google.com/go v0.105.0 h1:DNtEKRBAAzeS4KyIory52wWHuClNaXJ5x1F7xa4q+5Y=
+cloud.google.com/go v0.105.0/go.mod h1:PrLgOJNe5nfE9UMxKxgXj4mD3voiP+YQ6gdt6KMFOKM=
+cloud.google.com/go/compute v1.12.1 h1:gKVJMEyqV5c/UnpzjjQbo3Rjvvqpr9B1DFSbJC4OXr0=
+cloud.google.com/go/compute v1.12.1/go.mod h1:e8yNOBcBONZU1vJKCvCoDw/4JQsA0dpM4x/6PIIOocU=
+cloud.google.com/go/compute/metadata v0.1.1 h1:/sxEbyrm6cw+XOUw1YxBHlatV71z4vpnmO7z2IZ0h3I=
+cloud.google.com/go/compute/metadata v0.1.1/go.mod h1:Z1VN+bulIf6bt4P/C37K4DyZYZEXYonfTBHHFPO/4UU=
+cloud.google.com/go/iam v0.6.0 h1:nsqQC88kT5Iwlm4MeNGTpfMWddp6NB/UOLFTH6m1QfQ=
+cloud.google.com/go/iam v0.6.0/go.mod h1:+1AH33ueBne5MzYccyMHtEKqLE4/kJOibtffMHDMFMc=
+cloud.google.com/go/longrunning v0.1.1 h1:y50CXG4j0+qvEukslYFBCrzaXX0qpFbBzc3PchSu/LE=
+cloud.google.com/go/storage v1.27.0 h1:YOO045NZI9RKfCj1c5A/ZtuuENUc8OAW+gHdGnDgyMQ=
+cloud.google.com/go/storage v1.27.0/go.mod h1:x9DOL8TK/ygDUMieqwfhdpQryTeEkhGKMi80i/iqR2s=
+dmitri.shuralyov.com/gpu/mtl v0.0.0-20190408044501-666a987793e9/go.mod h1:H6x//7gZCb22OMCxBHrMx7a5I7Hp++hsVxbQ4BYO7hU=
+github.com/Azure/azure-sdk-for-go v51.2.0+incompatible/go.mod h1:9XXNKU+eRnpl9moKnB4QOLf1HestfXbmab5FXxiDBjc=
+github.com/Azure/azure-sdk-for-go v64.0.0+incompatible h1:WAA77WBDWYtNfCC95V70VvkdzHe+wM/r2MQ9mG7fnQs=
+github.com/Azure/azure-sdk-for-go v64.0.0+incompatible/go.mod h1:9XXNKU+eRnpl9moKnB4QOLf1HestfXbmab5FXxiDBjc=
+github.com/Azure/go-ansiterm v0.0.0-20170929234023-d6e3b3328b78/go.mod h1:LmzpDX56iTiv29bbRTIsUNlaFfuhWRQBWjQdVyAevI8=
+github.com/Azure/go-autorest v14.2.0+incompatible h1:V5VMDjClD3GiElqLWO7mz2MxNAK/vTfRHdAubSIPRgs=
+github.com/Azure/go-autorest v14.2.0+incompatible/go.mod h1:r+4oMnoxhatjLLJ6zxSWATqVooLgysK6ZNox3g/xq24=
+github.com/Azure/go-autorest/autorest v0.9.0/go.mod h1:xyHB1BMZT0cuDHU7I0+g046+BFDTQ8rEZB0s4Yfa6bI=
+github.com/Azure/go-autorest/autorest v0.9.3/go.mod h1:GsRuLYvwzLjjjRoWEIyMUaYq8GNUx2nRB378IPt/1p0=
+github.com/Azure/go-autorest/autorest v0.11.18/go.mod h1:dSiJPy22c3u0OtOKDNttNgqpNFY/GeWa7GH/Pz56QRA=
+github.com/Azure/go-autorest/autorest v0.11.19 h1:7/IqD2fEYVha1EPeaiytVKhzmPV223pfkRIQUGOK2IE=
+github.com/Azure/go-autorest/autorest v0.11.19/go.mod h1:dSiJPy22c3u0OtOKDNttNgqpNFY/GeWa7GH/Pz56QRA=
+github.com/Azure/go-autorest/autorest/adal v0.5.0/go.mod h1:8Z9fGy2MpX0PvDjB1pEgQTmVqjGhiHBW7RJJEciWzS0=
+github.com/Azure/go-autorest/autorest/adal v0.8.0/go.mod h1:Z6vX6WXXuyieHAXwMj0S6HY6e6wcHn37qQMBQlvY3lc=
+github.com/Azure/go-autorest/autorest/adal v0.8.1/go.mod h1:ZjhuQClTqx435SRJ2iMlOxPYt3d2C/T/7TiQCVZSn3Q=
+github.com/Azure/go-autorest/autorest/adal v0.9.5/go.mod h1:B7KF7jKIeC9Mct5spmyCB/A8CG/sEz1vwIRGv/bbw7A=
+github.com/Azure/go-autorest/autorest/adal v0.9.13/go.mod h1:W/MM4U6nLxnIskrw4UwWzlHfGjwUS50aOsc/I3yuU8M=
+github.com/Azure/go-autorest/autorest/adal v0.9.18 h1:kLnPsRjzZZUF3K5REu/Kc+qMQrvuza2bwSnNdhmzLfQ=
+github.com/Azure/go-autorest/autorest/adal v0.9.18/go.mod h1:XVVeme+LZwABT8K5Lc3hA4nAe8LDBVle26gTrguhhPQ=
+github.com/Azure/go-autorest/autorest/azure/auth v0.4.2 h1:iM6UAvjR97ZIeR93qTcwpKNMpV+/FTWjwEbuPD495Tk=
+github.com/Azure/go-autorest/autorest/azure/auth v0.4.2/go.mod h1:90gmfKdlmKgfjUpnCEpOJzsUEjrWDSLwHIG73tSXddM=
+github.com/Azure/go-autorest/autorest/azure/cli v0.3.1/go.mod h1:ZG5p860J94/0kI9mNJVoIoLgXcirM2gF5i2kWloofxw=
+github.com/Azure/go-autorest/autorest/azure/cli v0.4.2 h1:dMOmEJfkLKW/7JsokJqkyoYSgmR08hi9KrhjZb+JALY=
+github.com/Azure/go-autorest/autorest/azure/cli v0.4.2/go.mod h1:7qkJkT+j6b+hIpzMOwPChJhTqS8VbsqqgULzMNRugoM=
+github.com/Azure/go-autorest/autorest/date v0.1.0/go.mod h1:plvfp3oPSKwf2DNjlBjWF/7vwR+cUD/ELuzDCXwHUVA=
+github.com/Azure/go-autorest/autorest/date v0.2.0/go.mod h1:vcORJHLJEh643/Ioh9+vPmf1Ij9AEBM5FuBIXLmIy0g=
+github.com/Azure/go-autorest/autorest/date v0.3.0 h1:7gUk1U5M/CQbp9WoqinNzJar+8KY+LPI6wiWrP/myHw=
+github.com/Azure/go-autorest/autorest/date v0.3.0/go.mod h1:BI0uouVdmngYNUzGWeSYnokU+TrmwEsOqdt8Y6sso74=
+github.com/Azure/go-autorest/autorest/mocks v0.1.0/go.mod h1:OTyCOPRA2IgIlWxVYxBee2F5Gr4kF2zd2J5cFRaIDN0=
+github.com/Azure/go-autorest/autorest/mocks v0.2.0/go.mod h1:OTyCOPRA2IgIlWxVYxBee2F5Gr4kF2zd2J5cFRaIDN0=
+github.com/Azure/go-autorest/autorest/mocks v0.3.0/go.mod h1:a8FDP3DYzQ4RYfVAxAN3SVSiiO77gL2j2ronKKP0syM=
+github.com/Azure/go-autorest/autorest/mocks v0.4.1 h1:K0laFcLE6VLTOwNgSxaGbUcLPuGXlNkbVvq4cW4nIHk=
+github.com/Azure/go-autorest/autorest/mocks v0.4.1/go.mod h1:LTp+uSrOhSkaKrUy935gNZuuIPPVsHlr9DSOxSayd+k=
+github.com/Azure/go-autorest/autorest/to v0.4.0 h1:oXVqrxakqqV1UZdSazDOPOLvOIz+XA683u8EctwboHk=
+github.com/Azure/go-autorest/autorest/to v0.4.0/go.mod h1:fE8iZBn7LQR7zH/9XU2NcPR4o9jEImooCeWJcYV/zLE=
+github.com/Azure/go-autorest/autorest/validation v0.3.1 h1:AgyqjAd94fwNAoTjl/WQXg4VvFeRFpO+UhNyRXqF1ac=
+github.com/Azure/go-autorest/autorest/validation v0.3.1/go.mod h1:yhLgjC0Wda5DYXl6JAsWyUe4KVNffhoDhG0zVzUMo3E=
+github.com/Azure/go-autorest/logger v0.1.0/go.mod h1:oExouG+K6PryycPJfVSxi/koC6LSNgds39diKLz7Vrc=
+github.com/Azure/go-autorest/logger v0.2.1 h1:IG7i4p/mDa2Ce4TRyAO8IHnVhAVF3RFU+ZtXWSmf4Tg=
+github.com/Azure/go-autorest/logger v0.2.1/go.mod h1:T9E3cAhj2VqvPOtCYAvby9aBXkZmbF5NWuPV8+WeEW8=
+github.com/Azure/go-autorest/tracing v0.5.0/go.mod h1:r/s2XiOKccPW3HrqB+W0TQzfbtp2fGCgRFtBroKn4Dk=
+github.com/Azure/go-autorest/tracing v0.6.0 h1:TYi4+3m5t6K48TGI9AUdb+IzbnSxvnvUMfuitfgcfuo=
+github.com/Azure/go-autorest/tracing v0.6.0/go.mod h1:+vhtPC754Xsa23ID7GlGsrdKBpUA79WCAKPPZVC2DeU=
+github.com/Azure/go-ntlmssp v0.0.0-20180810175552-4a21cbd618b4/go.mod h1:chxPXzSsl7ZWRAuOIE23GDNzjWuZquvFlgA8xmpunjU=
+github.com/Azure/go-ntlmssp v0.0.0-20200615164410-66371956d46c h1:/IBSNwUN8+eKzUzbJPqhK839ygXJ82sde8x3ogr6R28=
+github.com/Azure/go-ntlmssp v0.0.0-20200615164410-66371956d46c/go.mod h1:chxPXzSsl7ZWRAuOIE23GDNzjWuZquvFlgA8xmpunjU=
+github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU=
+github.com/BurntSushi/xgb v0.0.0-20160522181843-27f122750802/go.mod h1:IVnqGOEym/WlBOVXweHU+Q+/VP0lqqI8lqeDx9IjBqo=
+github.com/ChrisTrenkamp/goxpath v0.0.0-20170922090931-c385f95c6022/go.mod h1:nuWgzSkT5PnyOd+272uUmV0dnAnAn42Mk7PiQC5VzN4=
+github.com/ChrisTrenkamp/goxpath v0.0.0-20210404020558-97928f7e12b6 h1:w0E0fgc1YafGEh5cROhlROMWXiNoZqApk2PDN0M1+Ns=
+github.com/ChrisTrenkamp/goxpath v0.0.0-20210404020558-97928f7e12b6/go.mod h1:nuWgzSkT5PnyOd+272uUmV0dnAnAn42Mk7PiQC5VzN4=
+github.com/DataDog/datadog-go v3.2.0+incompatible/go.mod h1:LButxg5PwREeZtORoXG3tL4fMGNddJ+vMq1mwgfaqoQ=
+github.com/Masterminds/goutils v1.1.0/go.mod h1:8cTjp+g8YejhMuvIA5y2vz3BpJxksy863GQaJW2MFNU=
+github.com/Masterminds/goutils v1.1.1 h1:5nUrii3FMTL5diU80unEVvNevw1nH4+ZV4DSLVJLSYI=
+github.com/Masterminds/goutils v1.1.1/go.mod h1:8cTjp+g8YejhMuvIA5y2vz3BpJxksy863GQaJW2MFNU=
+github.com/Masterminds/semver v1.5.0 h1:H65muMkzWKEuNDnfl9d70GUjFniHKHRbFPGBuZ3QEww=
+github.com/Masterminds/semver v1.5.0/go.mod h1:MB6lktGJrhw8PrUyiEoblNEGEQ+RzHPF078ddwwvV3Y=
+github.com/Masterminds/sprig v2.22.0+incompatible h1:z4yfnGrZ7netVz+0EDJ0Wi+5VZCSYp4Z0m2dk6cEM60=
+github.com/Masterminds/sprig v2.22.0+incompatible/go.mod h1:y6hNFY5UBTIWBxnzTeuNhlNS5hqE0NB0E6fgfo2Br3o=
+github.com/Microsoft/go-winio v0.4.14/go.mod h1:qXqCSQ3Xa7+6tgxaGTIe4Kpcdsi+P8jBhyzoq1bpyYA=
+github.com/Microsoft/go-winio v0.4.15-0.20190919025122-fc70bd9a86b5/go.mod h1:tTuCMEN+UleMWgg9dVx4Hu52b1bJo+59jBh3ajtinzw=
+github.com/Microsoft/go-winio v0.4.16 h1:FtSW/jqD+l4ba5iPBj9CODVtgfYAD8w2wS923g/cFDk=
+github.com/Microsoft/go-winio v0.4.16/go.mod h1:XB6nPKklQyQ7GC9LdcBEcBl8PF76WugXOPRXwdLnMv0=
+github.com/Microsoft/hcsshim v0.8.9/go.mod h1:5692vkUqntj1idxauYlpoINNKeqCiG6Sg38RRsjT5y8=
+github.com/ProtonMail/go-crypto v0.0.0-20210428141323-04723f9f07d7 h1:YoJbenK9C67SkzkDfmQuVln04ygHj3vjZfd9FL+GmQQ=
+github.com/ProtonMail/go-crypto v0.0.0-20210428141323-04723f9f07d7/go.mod h1:z4/9nQmJSSwwds7ejkxaJwO37dru3geImFUdJlaLzQo=
+github.com/PuerkitoBio/purell v1.1.1/go.mod h1:c11w/QuzBsJSee3cPx9rAFu61PvFxuPbtSwDGJws/X0=
+github.com/PuerkitoBio/urlesc v0.0.0-20170810143723-de5bf2ad4578/go.mod h1:uGdkoq3SwY9Y+13GIhn11/XLaGBb4BfwItxLd5jeuXE=
+github.com/acomagu/bufpipe v1.0.3 h1:fxAGrHZTgQ9w5QqVItgzwj235/uYZYgbXitB+dLupOk=
+github.com/acomagu/bufpipe v1.0.3/go.mod h1:mxdxdup/WdsKVreO5GpW4+M/1CE2sMG4jeGJ2sYmHc4=
+github.com/agext/levenshtein v1.2.3 h1:YB2fHEn0UJagG8T1rrWknE3ZQzWM06O8AMAatNn7lmo=
+github.com/agext/levenshtein v1.2.3/go.mod h1:JEDfjyjHDjOF/1e4FlBE/PkbqA9OfWu2ki2W0IB5558=
+github.com/alecthomas/template v0.0.0-20160405071501-a0175ee3bccc/go.mod h1:LOuyumcjzFXgccqObfd/Ljyb9UuFJ6TxHnclSeseNhc=
+github.com/alecthomas/template v0.0.0-20190718012654-fb15b899a751/go.mod h1:LOuyumcjzFXgccqObfd/Ljyb9UuFJ6TxHnclSeseNhc=
+github.com/alecthomas/units v0.0.0-20151022065526-2efee857e7cf/go.mod h1:ybxpYRFXyAe+OPACYpWeL0wqObRcbAqCMya13uyzqw0=
+github.com/alecthomas/units v0.0.0-20190717042225-c3de453c63f4/go.mod h1:ybxpYRFXyAe+OPACYpWeL0wqObRcbAqCMya13uyzqw0=
+github.com/anmitsu/go-shlex v0.0.0-20161002113705-648efa622239 h1:kFOfPq6dUM1hTo4JG6LR5AXSUEsOjtdm0kw0FtQtMJA=
+github.com/anmitsu/go-shlex v0.0.0-20161002113705-648efa622239/go.mod h1:2FmKhYUyUczH0OGQWaF5ceTx0UBShxjsH6f8oGKYe2c=
+github.com/antchfx/xpath v1.1.11 h1:WOFtK8TVAjLm3lbgqeP0arlHpvCEeTANeWZ/csPpJkQ=
+github.com/antchfx/xquery v0.0.0-20180515051857-ad5b8c7a47b0 h1:JaCC8jz0zdMLk2m+qCCVLLLM/PL93p84w4pK3aJWj60=
+github.com/apparentlymart/go-cidr v1.0.1 h1:NmIwLZ/KdsjIUlhf+/Np40atNXm/+lZ5txfTJ/SpF+U=
+github.com/apparentlymart/go-cidr v1.0.1/go.mod h1:EBcsNrHc3zQeuaeCeCtQruQm+n9/YjEn/vI25Lg7Gwc=
+github.com/apparentlymart/go-dump v0.0.0-20180507223929-23540a00eaa3 h1:ZSTrOEhiM5J5RFxEaFvMZVEAM1KvT1YzbEOwB2EAGjA=
+github.com/apparentlymart/go-textseg v1.0.0/go.mod h1:z96Txxhf3xSFMPmb5X/1W05FF/Nj9VFpLOpjS5yuumk=
+github.com/apparentlymart/go-textseg/v12 v12.0.0/go.mod h1:S/4uRK2UtaQttw1GenVJEynmyUenKwP++x/+DdGV/Ec=
+github.com/apparentlymart/go-textseg/v13 v13.0.0 h1:Y+KvPE1NYz0xl601PVImeQfFyEy6iT90AvPUL1NNfNw=
+github.com/apparentlymart/go-textseg/v13 v13.0.0/go.mod h1:ZK2fH7c4NqDTLtiYLvIkEghdlcqw7yxLeM89kiTRPUo=
+github.com/approvals/go-approval-tests v0.0.0-20210131072903-38d0b0ec12b1 h1:uroQ0JaeVom9Ffv9xFtc7DcqrpGmyQeZCRzHD9FqPBg=
+github.com/armon/circbuf v0.0.0-20150827004946-bbbad097214e/go.mod h1:3U/XgcO3hCbHZ8TKRvWD2dDTCfh9M9ya+I9JpbB7O8o=
+github.com/armon/go-metrics v0.0.0-20180917152333-f0300d1749da/go.mod h1:Q73ZrmVTwzkszR9V5SSuryQ31EELlFMUz1kKyl939pY=
+github.com/armon/go-metrics v0.3.0/go.mod h1:zXjbSimjXTd7vOpY8B0/2LpvNvDoXBuplAD+gJD3GYs=
+github.com/armon/go-metrics v0.3.3/go.mod h1:4O98XIr/9W0sxpJ8UaYkvjk10Iff7SnFrb4QAOwNTFc=
+github.com/armon/go-metrics v0.3.9 h1:O2sNqxBdvq8Eq5xmzljcYzAORli6RWCvEym4cJf9m18=
+github.com/armon/go-metrics v0.3.9/go.mod h1:4O98XIr/9W0sxpJ8UaYkvjk10Iff7SnFrb4QAOwNTFc=
+github.com/armon/go-radix v0.0.0-20180808171621-7fddfc383310/go.mod h1:ufUuZ+zHj4x4TnLV4JWEpy2hxWSpsRywHrMgIH9cCH8=
+github.com/armon/go-radix v1.0.0 h1:F4z6KzEeeQIMeLFa97iZU6vupzoecKdU5TX24SNppXI=
+github.com/armon/go-radix v1.0.0/go.mod h1:ufUuZ+zHj4x4TnLV4JWEpy2hxWSpsRywHrMgIH9cCH8=
+github.com/armon/go-socks5 v0.0.0-20160902184237-e75332964ef5 h1:0CwZNZbxp69SHPdPJAN/hZIm0C4OItdklCFmMRWYpio=
+github.com/armon/go-socks5 v0.0.0-20160902184237-e75332964ef5/go.mod h1:wHh0iHkYZB8zMSxRWpUBQtwG5a7fFgvEO+odwuTv2gs=
+github.com/asaskevich/govalidator v0.0.0-20200907205600-7a23bdc65eef/go.mod h1:WaHUgvxTVq04UNunO+XhnAqY/wQc+bxr74GqbsZ/Jqw=
+github.com/asaskevich/govalidator v0.0.0-20210307081110-f21760c49a8d h1:Byv0BzEl3/e6D5CLfI0j/7hiIEtvGVFPCZ7Ei2oq8iQ=
+github.com/asaskevich/govalidator v0.0.0-20210307081110-f21760c49a8d/go.mod h1:WaHUgvxTVq04UNunO+XhnAqY/wQc+bxr74GqbsZ/Jqw=
+github.com/aws/aws-sdk-go v1.25.37/go.mod h1:KmX6BPdI08NWTb3/sm4ZGu5ShLoqVDhKgpiN924inxo=
+github.com/aws/aws-sdk-go v1.30.27/go.mod h1:5zCpMtNQVjRREroY7sYe8lOMRSxkhG6MZveU8YkpAk0=
+github.com/aws/aws-sdk-go v1.31.9/go.mod h1:5zCpMtNQVjRREroY7sYe8lOMRSxkhG6MZveU8YkpAk0=
+github.com/aws/aws-sdk-go v1.44.114 h1:plIkWc/RsHr3DXBj4MEw9sEW4CcL/e2ryokc+CKyq1I=
+github.com/aws/aws-sdk-go v1.44.114/go.mod h1:y4AeaBuwd2Lk+GepC1E9v0qOiTws0MIWAX4oIKwKHZo=
+github.com/beorn7/perks v0.0.0-20180321164747-3a771d992973/go.mod h1:Dwedo/Wpr24TaqPxmxbtue+5NUziq4I4S80YR8gNf3Q=
+github.com/beorn7/perks v1.0.0/go.mod h1:KWe93zE9D1o94FZ5RNwFwVgaQK1VOXiVxmqh+CedLV8=
+github.com/beorn7/perks v1.0.1/go.mod h1:G2ZrVWU2WbWT9wwq4/hrbKbnv/1ERSJQ0ibhJ6rlkpw=
+github.com/bgentry/go-netrc v0.0.0-20140422174119-9fd32a8b3d3d h1:xDfNPAt8lFiC1UJrqV3uuy861HCTo708pDMbjHHdCas=
+github.com/bgentry/go-netrc v0.0.0-20140422174119-9fd32a8b3d3d/go.mod h1:6QX/PXZ00z/TKoufEY6K/a0k6AhaJrQKdFe6OfVXsa4=
+github.com/bgentry/speakeasy v0.1.0 h1:ByYyxL9InA1OWqxJqqp2A5pYHUrCiAL6K3J+LKSsQkY=
+github.com/bgentry/speakeasy v0.1.0/go.mod h1:+zsyZBPWlz7T6j88CTgSN5bM796AkVf0kBD4zp0CCIs=
+github.com/biogo/boom v0.0.0-20150317015657-28119bc1ffc1/go.mod h1:fwtxkutinkQcME9Zlywh66T0jZLLjgrwSLY2WxH2N3U=
+github.com/biogo/hts v1.4.3 h1:vir2yUTiRkPvtp6ZTpzh9lWTKQJZXJKZ563rpAQAsRM=
+github.com/biogo/hts v1.4.3/go.mod h1:eW40HJ1l2ExK9C+yvvoRSftInqWsf3ue+zAEjzCGWjA=
+github.com/bmatcuk/doublestar v1.1.5 h1:2bNwBOmhyFEFcoB3tGvTD5xanq+4kyOZlB8wFYbMjkk=
+github.com/bmatcuk/doublestar v1.1.5/go.mod h1:wiQtGV+rzVYxB7WIlirSN++5HPtPlXEo9MEoZQC/PmE=
+github.com/cenkalti/backoff/v3 v3.0.0/go.mod h1:cIeZDE3IrqwwJl6VUwCN6trj1oXrTS4rc0ij+ULvLYs=
+github.com/cenkalti/backoff/v3 v3.2.2 h1:cfUAAO3yvKMYKPrvhDuHSwQnhZNk/RMHKdZqKTxfm6M=
+github.com/cenkalti/backoff/v3 v3.2.2/go.mod h1:cIeZDE3IrqwwJl6VUwCN6trj1oXrTS4rc0ij+ULvLYs=
+github.com/census-instrumentation/opencensus-proto v0.2.1/go.mod h1:f6KPmirojxKA12rnyqOA5BBL4O983OfeGPqjHWSTneU=
+github.com/cespare/xxhash/v2 v2.1.1/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs=
+github.com/cheggaaa/pb v1.0.27 h1:wIkZHkNfC7R6GI5w7l/PdAdzXzlrbcI3p8OAlnkTsnc=
+github.com/cheggaaa/pb v1.0.27/go.mod h1:pQciLPpbU0oxA0h+VJYYLxO+XeDQb5pZijXscXHm81s=
+github.com/chzyer/logex v1.2.1 h1:XHDu3E6q+gdHgsdTPH6ImJMIp436vR6MPtH8gP05QzM=
+github.com/chzyer/logex v1.2.1/go.mod h1:JLbx6lG2kDbNRFnfkgvh4eRJRPX1QCoOIWomwysCBrQ=
+github.com/chzyer/readline v0.0.0-20180603132655-2972be24d48e h1:fY5BOSpyZCqRo5OhCuC+XN+r/bBCmeuuJtjz+bCNIf8=
+github.com/chzyer/readline v0.0.0-20180603132655-2972be24d48e/go.mod h1:nSuG5e5PlCu98SY8svDHJxuZscDgtXS6KTTbou5AhLI=
+github.com/chzyer/test v1.0.0 h1:p3BQDXSxOhOG0P9z6/hGnII4LGiEPOYBhs8asl/fC04=
+github.com/chzyer/test v1.0.0/go.mod h1:2JlltgoNkt4TW/z9V/IzDdFaMTM2JPIi26O1pF38GC8=
+github.com/circonus-labs/circonus-gometrics v2.3.1+incompatible/go.mod h1:nmEj6Dob7S7YxXgwXpfOuvO54S+tGdZdw9fuRZt25Ag=
+github.com/circonus-labs/circonusllhist v0.1.3/go.mod h1:kMXHVDlOchFAehlya5ePtbp5jckzBHf4XRpQvBOLI+I=
+github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDkc90ppPyw=
+github.com/cncf/udpa/go v0.0.0-20191209042840-269d4d468f6f/go.mod h1:M8M6+tZqaGXZJjfX53e64911xZQV5JYwmTeXPW+k8Sc=
+github.com/containerd/cgroups v0.0.0-20190919134610-bf292b21730f/go.mod h1:OApqhQ4XNSNC13gXIwDjhOQxjWa/NxkwZXJ1EvqT0ko=
+github.com/containerd/console v0.0.0-20180822173158-c12b1e7919c1/go.mod h1:Tj/on1eG8kiEhd0+fhSDzsPAFESxzBBvdyEgyryXffw=
+github.com/containerd/containerd v1.3.2/go.mod h1:bC6axHOhabU15QhwfG7w5PipXdVtMXFTttgp+kVtyUA=
+github.com/containerd/containerd v1.3.4/go.mod h1:bC6axHOhabU15QhwfG7w5PipXdVtMXFTttgp+kVtyUA=
+github.com/containerd/continuity v0.0.0-20190426062206-aaeac12a7ffc/go.mod h1:GL3xCUCBDV3CZiTSEKksMWbLE66hEyuu9qyDOOqM47Y=
+github.com/containerd/continuity v0.0.0-20200709052629-daa8e1ccc0bc/go.mod h1:cECdGN1O8G9bgKTlLhuPJimka6Xb/Gg7vYzCTNVxhvo=
+github.com/containerd/fifo v0.0.0-20190226154929-a9fb20d87448/go.mod h1:ODA38xgv3Kuk8dQz2ZQXpnv/UZZUHUCL7pnLehbXgQI=
+github.com/containerd/go-runc v0.0.0-20180907222934-5a6d9f37cfa3/go.mod h1:IV7qH3hrUgRmyYrtgEeGWJfWbgcHL9CSRruz2Vqcph0=
+github.com/containerd/ttrpc v0.0.0-20190828154514-0e0f228740de/go.mod h1:PvCDdDGpgqzQIzDW1TphrGLssLDZp2GuS+X5DkEJB8o=
+github.com/containerd/typeurl v0.0.0-20180627222232-a93fcdb778cd/go.mod h1:Cm3kwCdlkCfMSHURc+r6fwoGH6/F1hH3S4sg0rLFWPc=
+github.com/coreos/go-systemd v0.0.0-20190321100706-95778dfbb74e/go.mod h1:F5haX7vjVVG0kc13fIWeqUViNPyEJxv/OmvnBo0Yme4=
+github.com/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E=
+github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
+github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
+github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
+github.com/dgrijalva/jwt-go v3.2.0+incompatible/go.mod h1:E3ru+11k8xSBh+hMPgOLZmtrrCbhqsmaPHjLKYnJCaQ=
+github.com/digitalocean/go-libvirt v0.0.0-20201209184759-e2a69bcd5bd1 h1:j6vGflaQ2T7yOWqVgPdiRF73j/U2Zmpbbzab8nyDCRQ=
+github.com/digitalocean/go-libvirt v0.0.0-20201209184759-e2a69bcd5bd1/go.mod h1:QS1XzqZLcDniNYrN7EZefq3wIyb/M2WmJbql4ZKoc1Q=
+github.com/digitalocean/go-qemu v0.0.0-20210326154740-ac9e0b687001 h1:WAg57gnaAWWjMAELcwHjc2xy0PoXQ5G+vn3+XS6s1jI=
+github.com/digitalocean/go-qemu v0.0.0-20210326154740-ac9e0b687001/go.mod h1:IetBE52JfFxK46p2n2Rqm+p5Gx1gpu2hRHsrbnPOWZQ=
+github.com/dimchansky/utfbom v1.1.0/go.mod h1:rO41eb7gLfo8SF1jd9F8HplJm1Fewwi4mQvIirEdv+8=
+github.com/dimchansky/utfbom v1.1.1 h1:vV6w1AhK4VMnhBno/TPVCoK9U/LP0PkLCS9tbxHdi/U=
+github.com/dimchansky/utfbom v1.1.1/go.mod h1:SxdoEBH5qIqFocHMyGOXVAybYJdr71b1Q/j0mACtrfE=
+github.com/dnaeon/go-vcr v1.1.0 h1:ReYa/UBrRyQdant9B4fNHGoCNKw6qh6P0fsdGmZpR7c=
+github.com/docker/distribution v2.7.1+incompatible/go.mod h1:J2gT2udsDAN96Uj4KfcMRqY0/ypR+oyYUYmja8H+y+w=
+github.com/docker/docker v1.4.2-0.20200319182547-c7ad2b866182/go.mod h1:eEKB0N0r5NX/I1kEveEz05bcu8tLC/8azJZsviup8Sk=
+github.com/docker/go-connections v0.4.0/go.mod h1:Gbd7IOopHjR8Iph03tsViu4nIes5XhDvyHbTtUxmeec=
+github.com/docker/go-units v0.4.0/go.mod h1:fgPhTUdO+D/Jk86RDLlptpiXQzgHJF7gydDDbaIK4Dk=
+github.com/dsnet/compress v0.0.1 h1:PlZu0n3Tuv04TzpfPbrnI0HW/YwodEXDS+oPKahKF0Q=
+github.com/dsnet/compress v0.0.1/go.mod h1:Aw8dCMJ7RioblQeTqt88akK31OvO8Dhf5JflhBbQEHo=
+github.com/dsnet/golib v0.0.0-20171103203638-1ea166775780/go.mod h1:Lj+Z9rebOhdfkVLjJ8T6VcRQv3SXugXy999NBtR9aFY=
+github.com/dustin/go-humanize v0.0.0-20171111073723-bb3d318650d4/go.mod h1:HtrtbFcZ19U5GC7JDqmcUSB87Iq5E25KnS6fMYU6eOk=
+github.com/dylanmei/iso8601 v0.1.0 h1:812NGQDBcqquTfH5Yeo7lwR0nzx/cKdsmf3qMjPURUI=
+github.com/dylanmei/iso8601 v0.1.0/go.mod h1:w9KhXSgIyROl1DefbMYIE7UVSIvELTbMrCfx+QkYnoQ=
+github.com/dylanmei/winrmtest v0.0.0-20170819153634-c2fbb09e6c08 h1:0bp6/GrNOrTDtSXe9YYGCwf8jp5Fb/b+4a6MTRm4qzY=
+github.com/emirpasic/gods v1.12.0 h1:QAUIPSaCu4G+POclxeqb3F+WPpdKqFGlw36+yOzGlrg=
+github.com/emirpasic/gods v1.12.0/go.mod h1:YfzfFFoVP/catgzJb4IKIqXjX78Ha8FMSDh3ymbK86o=
+github.com/envoyproxy/go-control-plane v0.9.0/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4=
+github.com/envoyproxy/go-control-plane v0.9.1-0.20191026205805-5f8ba28d4473/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4=
+github.com/envoyproxy/go-control-plane v0.9.4/go.mod h1:6rpuAdCZL397s3pYoYcLgu1mIlRU8Am5FuJP05cCM98=
+github.com/envoyproxy/protoc-gen-validate v0.1.0/go.mod h1:iSmxcyjqTsJpI2R4NaDN7+kN2VEUnK/pcBlmesArF7c=
+github.com/fatih/camelcase v1.0.0/go.mod h1:yN2Sb0lFhZJUdVvtELVWefmrXpuZESvPmqwoZc+/fpc=
+github.com/fatih/color v1.7.0/go.mod h1:Zm6kSWBoL9eyXnKyktHP6abPY2pDugNf5KwzbycvMj4=
+github.com/fatih/color v1.9.0/go.mod h1:eQcE1qtQxscV5RaZvpXrrb8Drkc3/DdQ+uUYCNjL+zU=
+github.com/fatih/color v1.12.0 h1:mRhaKNwANqRgUBGKmnI5ZxEk7QXmjQeCcuYFMX2bfcc=
+github.com/fatih/color v1.12.0/go.mod h1:ELkj/draVOlAH/xkhN6mQ50Qd0MPOk5AAr3maGEBuJM=
+github.com/fatih/structs v1.1.0/go.mod h1:9NiDSp5zOcgEDl+j00MP/WkGVPOlPRLejGD8Ga6PJ7M=
+github.com/flynn/go-shlex v0.0.0-20150515145356-3f9db97f8568/go.mod h1:xEzjJPgXI435gkrCt3MPfRiAkVrwSbHsst4LCFVfpJc=
+github.com/form3tech-oss/jwt-go v3.2.2+incompatible/go.mod h1:pbq4aXjuKjdthFRnoDwaVPLA+WlJuPGy+QneDUgJi2k=
+github.com/frankban/quicktest v1.10.0 h1:Gfh+GAJZOAoKZsIZeZbdn2JF10kN1XHNvjsvQK8gVkE=
+github.com/frankban/quicktest v1.10.0/go.mod h1:ui7WezCLWMWxVWr1GETZY3smRy0G4KWq9vcPtJmFl7Y=
+github.com/fsnotify/fsnotify v1.4.7/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMoQvtojpjFo=
+github.com/gliderlabs/ssh v0.2.2 h1:6zsha5zo/TWhRhwqCD3+EarCAgZ2yN28ipRnGPnwkI0=
+github.com/gliderlabs/ssh v0.2.2/go.mod h1:U7qILu1NlMHj9FlMhZLlkCdDnU1DBEAqr0aevW3Awn0=
+github.com/go-asn1-ber/asn1-ber v1.3.1/go.mod h1:hEBeB/ic+5LoWskz+yKT7vGhhPYkProFKoKdwZRWMe0=
+github.com/go-git/gcfg v1.5.0 h1:Q5ViNfGF8zFgyJWPqYwA7qGFoMTEiBmdlkcfRmpIMa4=
+github.com/go-git/gcfg v1.5.0/go.mod h1:5m20vg6GwYabIxaOonVkTdrILxQMpEShl1xiMF4ua+E=
+github.com/go-git/go-billy/v5 v5.2.0/go.mod h1:pmpqyWchKfYfrkb/UVH4otLvyi/5gJlGI4Hb3ZqZ3W0=
+github.com/go-git/go-billy/v5 v5.3.1 h1:CPiOUAzKtMRvolEKw+bG1PLRpT7D3LIs3/3ey4Aiu34=
+github.com/go-git/go-billy/v5 v5.3.1/go.mod h1:pmpqyWchKfYfrkb/UVH4otLvyi/5gJlGI4Hb3ZqZ3W0=
+github.com/go-git/go-git-fixtures/v4 v4.2.1 h1:n9gGL1Ct/yIw+nfsfr8s4+sbhT+Ncu2SubfXjIWgci8=
+github.com/go-git/go-git-fixtures/v4 v4.2.1/go.mod h1:K8zd3kDUAykwTdDCr+I0per6Y6vMiRR/nnVTBtavnB0=
+github.com/go-git/go-git/v5 v5.4.2 h1:BXyZu9t0VkbiHtqrsvdq39UDhGJTl1h55VW6CSC4aY4=
+github.com/go-git/go-git/v5 v5.4.2/go.mod h1:gQ1kArt6d+n+BGd+/B/I74HwRTLhth2+zti4ihgckDc=
+github.com/go-gl/glfw/v3.3/glfw v0.0.0-20191125211704-12ad95a8df72/go.mod h1:tQ2UAYgL5IevRw8kRxooKSPJfGvJ9fJQFa0TUsXzTg8=
+github.com/go-kit/kit v0.8.0/go.mod h1:xBxKIO96dXMWWy0MnWVtmwkA9/13aqxPnvrjFYMA2as=
+github.com/go-kit/kit v0.9.0/go.mod h1:xBxKIO96dXMWWy0MnWVtmwkA9/13aqxPnvrjFYMA2as=
+github.com/go-ldap/ldap/v3 v3.1.3/go.mod h1:3rbOH3jRS2u6jg2rJnKAMLE/xQyCKIveG2Sa/Cohzb8=
+github.com/go-ldap/ldap/v3 v3.1.10/go.mod h1:5Zun81jBTabRaI8lzN7E1JjyEl1g6zI6u9pd8luAK4Q=
+github.com/go-logfmt/logfmt v0.3.0/go.mod h1:Qt1PoO58o5twSAckw1HlFXLmHsOX5/0LbT9GBnD5lWE=
+github.com/go-logfmt/logfmt v0.4.0/go.mod h1:3RMwSq7FuexP4Kalkev3ejPJsZTpXXBr9+V4qmtdjCk=
+github.com/go-logr/logr v1.2.2/go.mod h1:jdQByPbusPIv2/zmleS9BjJVeZ6kBagPoEUsqbVz/1A=
+github.com/go-logr/logr v1.2.3 h1:2DntVwHkVopvECVRSlL5PSo9eG+cAkDCuckLubN+rq0=
+github.com/go-logr/logr v1.2.3/go.mod h1:jdQByPbusPIv2/zmleS9BjJVeZ6kBagPoEUsqbVz/1A=
+github.com/go-logr/stdr v1.2.2 h1:hSWxHoqTgW2S2qGc0LTAI563KZ5YKYRhT3MFKZMbjag=
+github.com/go-logr/stdr v1.2.2/go.mod h1:mMo/vtBO5dYbehREoey6XUKy/eSumjCCveDpRre4VKE=
+github.com/go-ole/go-ole v1.2.6 h1:/Fpf6oFPoeFik9ty7siob0G6Ke8QvQEuVcuChpwXzpY=
+github.com/go-ole/go-ole v1.2.6/go.mod h1:pprOEPIfldk/42T2oK7lQ4v4JSDwmV0As9GaiUsvbm0=
+github.com/go-openapi/analysis v0.21.2/go.mod h1:HZwRk4RRisyG8vx2Oe6aqeSQcoxRp47Xkp3+K6q+LdY=
+github.com/go-openapi/analysis v0.21.4 h1:ZDFLvSNxpDaomuCueM0BlSXxpANBlFYiBvr+GXrvIHc=
+github.com/go-openapi/analysis v0.21.4/go.mod h1:4zQ35W4neeZTqh3ol0rv/O8JBbka9QyAgQRPp9y3pfo=
+github.com/go-openapi/errors v0.19.8/go.mod h1:cM//ZKUKyO06HSwqAelJ5NsEMMcpa6VpXe8DOa1Mi1M=
+github.com/go-openapi/errors v0.19.9/go.mod h1:cM//ZKUKyO06HSwqAelJ5NsEMMcpa6VpXe8DOa1Mi1M=
+github.com/go-openapi/errors v0.20.2/go.mod h1:cM//ZKUKyO06HSwqAelJ5NsEMMcpa6VpXe8DOa1Mi1M=
+github.com/go-openapi/errors v0.20.3 h1:rz6kiC84sqNQoqrtulzaL/VERgkoCyB6WdEkc2ujzUc=
+github.com/go-openapi/errors v0.20.3/go.mod h1:Z3FlZ4I8jEGxjUK+bugx3on2mIAk4txuAOhlsB1FSgk=
+github.com/go-openapi/jsonpointer v0.19.3/go.mod h1:Pl9vOtqEWErmShwVjC8pYs9cog34VGT37dQOVbmoatg=
+github.com/go-openapi/jsonpointer v0.19.5 h1:gZr+CIYByUqjcgeLXnQu2gHYQC9o73G2XUeOFYEICuY=
+github.com/go-openapi/jsonpointer v0.19.5/go.mod h1:Pl9vOtqEWErmShwVjC8pYs9cog34VGT37dQOVbmoatg=
+github.com/go-openapi/jsonreference v0.19.6/go.mod h1:diGHMEHg2IqXZGKxqyvWdfWU/aim5Dprw5bqpKkTvns=
+github.com/go-openapi/jsonreference v0.20.0 h1:MYlu0sBgChmCfJxxUKZ8g1cPWFOB37YSZqewK7OKeyA=
+github.com/go-openapi/jsonreference v0.20.0/go.mod h1:Ag74Ico3lPc+zR+qjn4XBUmXymS4zJbYVCZmcgkasdo=
+github.com/go-openapi/loads v0.21.1/go.mod h1:/DtAMXXneXFjbQMGEtbamCZb+4x7eGwkvZCvBmwUG+g=
+github.com/go-openapi/loads v0.21.2 h1:r2a/xFIYeZ4Qd2TnGpWDIQNcP80dIaZgf704za8enro=
+github.com/go-openapi/loads v0.21.2/go.mod h1:Jq58Os6SSGz0rzh62ptiu8Z31I+OTHqmULx5e/gJbNw=
+github.com/go-openapi/runtime v0.25.0 h1:7yQTCdRbWhX8vnIjdzU8S00tBYf7Sg71EBeorlPHvhc=
+github.com/go-openapi/runtime v0.25.0/go.mod h1:Ux6fikcHXyyob6LNWxtE96hWwjBPYF0DXgVFuMTneOs=
+github.com/go-openapi/spec v0.20.4/go.mod h1:faYFR1CvsJZ0mNsmsphTMSoRrNV3TEDoAM7FOEWeq8I=
+github.com/go-openapi/spec v0.20.6/go.mod h1:2OpW+JddWPrpXSCIX8eOx7lZ5iyuWj3RYR6VaaBKcWA=
+github.com/go-openapi/spec v0.20.8 h1:ubHmXNY3FCIOinT8RNrrPfGc9t7I1qhPtdOGoG2AxRU=
+github.com/go-openapi/spec v0.20.8/go.mod h1:2OpW+JddWPrpXSCIX8eOx7lZ5iyuWj3RYR6VaaBKcWA=
+github.com/go-openapi/strfmt v0.21.0/go.mod h1:ZRQ409bWMj+SOgXofQAGTIo2Ebu72Gs+WaRADcS5iNg=
+github.com/go-openapi/strfmt v0.21.1/go.mod h1:I/XVKeLc5+MM5oPNN7P6urMOpuLXEcNrCX/rPGuWb0k=
+github.com/go-openapi/strfmt v0.21.3 h1:xwhj5X6CjXEZZHMWy1zKJxvW9AfHC9pkyUjLvHtKG7o=
+github.com/go-openapi/strfmt v0.21.3/go.mod h1:k+RzNO0Da+k3FrrynSNN8F7n/peCmQQqbbXjtDfvmGg=
+github.com/go-openapi/swag v0.19.5/go.mod h1:POnQmlKehdgb5mhVOsnJFsivZCEZ/vjK9gh66Z9tfKk=
+github.com/go-openapi/swag v0.19.15/go.mod h1:QYRuS/SOXUCsnplDa677K7+DxSOj6IPNl/eQntq43wQ=
+github.com/go-openapi/swag v0.21.1/go.mod h1:QYRuS/SOXUCsnplDa677K7+DxSOj6IPNl/eQntq43wQ=
+github.com/go-openapi/swag v0.22.3 h1:yMBqmnQ0gyZvEb/+KzuWZOXgllrXT4SADYbvDaXHv/g=
+github.com/go-openapi/swag v0.22.3/go.mod h1:UzaqsxGiab7freDnrUUra0MwWfN/q7tE4j+VcZ0yl14=
+github.com/go-openapi/validate v0.22.1 h1:G+c2ub6q47kfX1sOBLwIQwzBVt8qmOAARyo/9Fqs9NU=
+github.com/go-openapi/validate v0.22.1/go.mod h1:rjnrwK57VJ7A8xqfpAOEKRH8yQSGUriMu5/zuPSQ1hg=
+github.com/go-sql-driver/mysql v1.5.0/go.mod h1:DCzpHaOWr8IXmIStZouvnhqoel9Qv2LBy8hT2VhHyBg=
+github.com/go-stack/stack v1.8.0/go.mod h1:v0f6uXyyMGvRgIKkXu+yp6POWl0qKG85gN/melR3HDY=
+github.com/go-test/deep v1.0.2-0.20181118220953-042da051cf31/go.mod h1:wGDj63lr65AM2AQyKZd/NYHGb0R+1RLqB8NKt3aSFNA=
+github.com/go-test/deep v1.0.2/go.mod h1:wGDj63lr65AM2AQyKZd/NYHGb0R+1RLqB8NKt3aSFNA=
+github.com/go-test/deep v1.0.3 h1:ZrJSEWsXzPOxaZnFteGEfooLba+ju3FYIbOrS+rQd68=
+github.com/gobuffalo/attrs v0.0.0-20190224210810-a9411de4debd/go.mod h1:4duuawTqi2wkkpB4ePgWMaai6/Kc6WEz83bhFwpHzj0=
+github.com/gobuffalo/depgen v0.0.0-20190329151759-d478694a28d3/go.mod h1:3STtPUQYuzV0gBVOY3vy6CfMm/ljR4pABfrTeHNLHUY=
+github.com/gobuffalo/depgen v0.1.0/go.mod h1:+ifsuy7fhi15RWncXQQKjWS9JPkdah5sZvtHc2RXGlg=
+github.com/gobuffalo/envy v1.6.15/go.mod h1:n7DRkBerg/aorDM8kbduw5dN3oXGswK5liaSCx4T5NI=
+github.com/gobuffalo/envy v1.7.0/go.mod h1:n7DRkBerg/aorDM8kbduw5dN3oXGswK5liaSCx4T5NI=
+github.com/gobuffalo/flect v0.1.0/go.mod h1:d2ehjJqGOH/Kjqcoz+F7jHTBbmDb38yXA598Hb50EGs=
+github.com/gobuffalo/flect v0.1.1/go.mod h1:8JCgGVbRjJhVgD6399mQr4fx5rRfGKVzFjbj6RE/9UI=
+github.com/gobuffalo/flect v0.1.3/go.mod h1:8JCgGVbRjJhVgD6399mQr4fx5rRfGKVzFjbj6RE/9UI=
+github.com/gobuffalo/genny v0.0.0-20190329151137-27723ad26ef9/go.mod h1:rWs4Z12d1Zbf19rlsn0nurr75KqhYp52EAGGxTbBhNk=
+github.com/gobuffalo/genny v0.0.0-20190403191548-3ca520ef0d9e/go.mod h1:80lIj3kVJWwOrXWWMRzzdhW3DsrdjILVil/SFKBzF28=
+github.com/gobuffalo/genny v0.1.0/go.mod h1:XidbUqzak3lHdS//TPu2OgiFB+51Ur5f7CSnXZ/JDvo=
+github.com/gobuffalo/genny v0.1.1/go.mod h1:5TExbEyY48pfunL4QSXxlDOmdsD44RRq4mVZ0Ex28Xk=
+github.com/gobuffalo/gitgen v0.0.0-20190315122116-cc086187d211/go.mod h1:vEHJk/E9DmhejeLeNt7UVvlSGv3ziL+djtTr3yyzcOw=
+github.com/gobuffalo/gogen v0.0.0-20190315121717-8f38393713f5/go.mod h1:V9QVDIxsgKNZs6L2IYiGR8datgMhB577vzTDqypH360=
+github.com/gobuffalo/gogen v0.1.0/go.mod h1:8NTelM5qd8RZ15VjQTFkAW6qOMx5wBbW4dSCS3BY8gg=
+github.com/gobuffalo/gogen v0.1.1/go.mod h1:y8iBtmHmGc4qa3urIyo1shvOD8JftTtfcKi+71xfDNE=
+github.com/gobuffalo/logger v0.0.0-20190315122211-86e12af44bc2/go.mod h1:QdxcLw541hSGtBnhUc4gaNIXRjiDppFGaDqzbrBd3v8=
+github.com/gobuffalo/mapi v1.0.1/go.mod h1:4VAGh89y6rVOvm5A8fKFxYG+wIW6LO1FMTG9hnKStFc=
+github.com/gobuffalo/mapi v1.0.2/go.mod h1:4VAGh89y6rVOvm5A8fKFxYG+wIW6LO1FMTG9hnKStFc=
+github.com/gobuffalo/packd v0.0.0-20190315124812-a385830c7fc0/go.mod h1:M2Juc+hhDXf/PnmBANFCqx4DM3wRbgDvnVWeG2RIxq4=
+github.com/gobuffalo/packd v0.1.0/go.mod h1:M2Juc+hhDXf/PnmBANFCqx4DM3wRbgDvnVWeG2RIxq4=
+github.com/gobuffalo/packr/v2 v2.0.9/go.mod h1:emmyGweYTm6Kdper+iywB6YK5YzuKchGtJQZ0Odn4pQ=
+github.com/gobuffalo/packr/v2 v2.2.0/go.mod h1:CaAwI0GPIAv+5wKLtv8Afwl+Cm78K/I/VCm/3ptBN+0=
+github.com/gobuffalo/syncx v0.0.0-20190224160051-33c29581e754/go.mod h1:HhnNqWY95UYwwW3uSASeV7vtgYkT2t16hJgV3AEPUpw=
+github.com/gobwas/glob v0.2.3 h1:A4xDbljILXROh+kObIiy5kIaPYD8e96x1tgBhUI5J+Y=
+github.com/gobwas/glob v0.2.3/go.mod h1:d3Ez4x06l9bZtSvzIay5+Yzi0fmZzPgnTbPcKjJAkT8=
+github.com/godbus/dbus v0.0.0-20190422162347-ade71ed3457e/go.mod h1:bBOAhwG1umN6/6ZUMtDFBMQR8jRg9O75tm9K00oMsK4=
+github.com/gofrs/flock v0.8.1 h1:+gYjHKf32LDeiEEFhQaotPbLuUXjY5ZqxKgXy7n59aw=
+github.com/gofrs/flock v0.8.1/go.mod h1:F1TvTiK9OcQqauNUHlbJvyl9Qa1QvF/gOUDKA14jxHU=
+github.com/gofrs/uuid v3.2.0+incompatible/go.mod h1:b2aQJv3Z4Fp6yNu3cdSllBxTCLRxnplIgP/c0N/04lM=
+github.com/gofrs/uuid v4.0.0+incompatible h1:1SD/1F5pU8p29ybwgQSwpQk+mwdRrXCYuPhW6m+TnJw=
+github.com/gofrs/uuid v4.0.0+incompatible/go.mod h1:b2aQJv3Z4Fp6yNu3cdSllBxTCLRxnplIgP/c0N/04lM=
+github.com/gogo/protobuf v1.1.1/go.mod h1:r8qH/GZQm5c6nD/R0oafs1akxWv10x8SbQlK7atdtwQ=
+github.com/gogo/protobuf v1.2.1/go.mod h1:hp+jE20tsWTFYpLwKvXlhS1hjn+gTNwPg2I6zVXpSg4=
+github.com/gogo/protobuf v1.3.1/go.mod h1:SlYgWuQ5SjCEi6WLHjHCa1yvBfUnHcTbrrZtXPKa29o=
+github.com/golang-collections/collections v0.0.0-20130729185459-604e922904d3 h1:zN2lZNZRflqFyxVaTIU61KNKQ9C0055u9CAfpmqUvo4=
+github.com/golang-collections/collections v0.0.0-20130729185459-604e922904d3/go.mod h1:nPpo7qLxd6XL3hWJG/O60sR8ZKfMCiIoNap5GvD12KU=
+github.com/golang-jwt/jwt v3.2.2+incompatible h1:IfV12K8xAKAnZqdXVzCZ+TOjboZ2keLg81eXfW3O+oY=
+github.com/golang-jwt/jwt v3.2.2+incompatible/go.mod h1:8pz2t5EyA70fFQQSrl6XZXzqecmYZeUEB8OUGHkxJ+I=
+github.com/golang-jwt/jwt/v4 v4.0.0/go.mod h1:/xlHOz8bRuivTWchD4jCa+NbatV+wEUSzwAxVc6locg=
+github.com/golang-jwt/jwt/v4 v4.2.0 h1:besgBTC8w8HjP6NzQdxwKH9Z5oQMZ24ThTrHp3cZ8eU=
+github.com/golang-jwt/jwt/v4 v4.2.0/go.mod h1:/xlHOz8bRuivTWchD4jCa+NbatV+wEUSzwAxVc6locg=
+github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b/go.mod h1:SBH7ygxi8pfUlaOkMMuAQtPIUF8ecWP5IEl/CR7VP2Q=
+github.com/golang/groupcache v0.0.0-20200121045136-8c9f03a8e57e/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc=
+github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da h1:oI5xCqsCo564l8iNU+DwB5epxmsaqB+rhGL0m5jtYqE=
+github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc=
+github.com/golang/mock v1.1.1/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A=
+github.com/golang/protobuf v1.1.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
+github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
+github.com/golang/protobuf v1.3.1/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
+github.com/golang/protobuf v1.3.2/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
+github.com/golang/protobuf v1.3.3/go.mod h1:vzj43D7+SQXF/4pzW/hwtAqwc6iTitCiVSaWz5lYuqw=
+github.com/golang/protobuf v1.3.4/go.mod h1:vzj43D7+SQXF/4pzW/hwtAqwc6iTitCiVSaWz5lYuqw=
+github.com/golang/protobuf v1.4.0-rc.1/go.mod h1:ceaxUfeHdC40wWswd/P6IGgMaK3YpKi5j83Wpe3EHw8=
+github.com/golang/protobuf v1.4.0-rc.1.0.20200221234624-67d41d38c208/go.mod h1:xKAWHe0F5eneWXFV3EuXVDTCmh+JuBKY0li0aMyXATA=
+github.com/golang/protobuf v1.4.0-rc.2/go.mod h1:LlEzMj4AhA7rCAGe4KMBDvJI+AwstrUpVNzEA03Pprs=
+github.com/golang/protobuf v1.4.0-rc.4.0.20200313231945-b860323f09d0/go.mod h1:WU3c8KckQ9AFe+yFwt9sWVRKCVIyN9cPHBJSNnbL67w=
+github.com/golang/protobuf v1.4.0/go.mod h1:jodUvKwWbYaEsadDk5Fwe5c77LiNKVO9IDvqG2KuDX0=
+github.com/golang/protobuf v1.4.1/go.mod h1:U8fpvMrcmy5pZrNK1lt4xCsGvpyWQ/VVv6QDs8UjoX8=
+github.com/golang/protobuf v1.4.2/go.mod h1:oDoupMAO8OvCJWAcko0GGGIgR6R6ocIYbsSw735rRwI=
+github.com/golang/protobuf v1.4.3/go.mod h1:oDoupMAO8OvCJWAcko0GGGIgR6R6ocIYbsSw735rRwI=
+github.com/golang/protobuf v1.5.0/go.mod h1:FsONVRAS9T7sI+LIUmWTfcYkHO4aIWwzhcaSAoJOfIk=
+github.com/golang/protobuf v1.5.2 h1:ROPKBNFfQgOUMifHyP+KYbvpjbdoFNs+aK7DXlji0Tw=
+github.com/golang/protobuf v1.5.2/go.mod h1:XVQd3VNwM+JqD3oG2Ue2ip4fOMUkwXdXDdiuN0vRsmY=
+github.com/golang/snappy v0.0.1/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q=
+github.com/golang/snappy v0.0.4 h1:yAGX7huGHXlcLOEtBnF4w7FQwA26wojNCwOYAEhLjQM=
+github.com/golang/snappy v0.0.4/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q=
+github.com/google/btree v0.0.0-20180813153112-4030bb1f1f0c/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ5JPQ=
+github.com/google/btree v1.0.1 h1:gK4Kx5IaGY9CD5sPJ36FHiBJ6ZXl0kilRiiCj+jdYp4=
+github.com/google/btree v1.0.1/go.mod h1:xXMiIv4Fb/0kKde4SpL7qlzvu5cMJDRkFDxJfI9uaxA=
+github.com/google/go-cmp v0.2.0/go.mod h1:oXzfMopK8JAjlY9xF4vHSVASa0yLyX7SntLO5aqRK0M=
+github.com/google/go-cmp v0.3.0/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU=
+github.com/google/go-cmp v0.3.1/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU=
+github.com/google/go-cmp v0.4.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
+github.com/google/go-cmp v0.5.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
+github.com/google/go-cmp v0.5.2/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
+github.com/google/go-cmp v0.5.3/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
+github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
+github.com/google/go-cmp v0.5.6/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
+github.com/google/go-cmp v0.5.9 h1:O2Tfq5qg4qc4AmwVlvv0oLiVAGB7enBSJ2x2DqQFi38=
+github.com/google/go-cmp v0.5.9/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY=
+github.com/google/go-github/v33 v33.0.1-0.20210113204525-9318e629ec69 h1:zL0/Ug5CMhV0XRb3A6vnK1SQ9kJM3VIyRxPQ5t9w8Bg=
+github.com/google/go-github/v33 v33.0.1-0.20210113204525-9318e629ec69/go.mod h1:GMdDnVZY/2TsWgp/lkYnpSAh6TrzhANBBwm6k6TTEXg=
+github.com/google/go-querystring v1.0.0/go.mod h1:odCYkC5MyYFN7vkCjXpyrEuKhc/BUO6wN/zVPAxq5ck=
+github.com/google/go-querystring v1.1.0 h1:AnCroh3fv4ZBgVIf1Iwtovgjaw/GiKJo8M8yD/fhyJ8=
+github.com/google/go-querystring v1.1.0/go.mod h1:Kcdr2DB4koayq7X8pmAG4sNG59So17icRSOU623lUBU=
+github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg=
+github.com/google/martian/v3 v3.2.1 h1:d8MncMlErDFTwQGBK1xhv026j9kqhvw1Qv9IbWT1VLQ=
+github.com/google/shlex v0.0.0-20191202100458-e7afc7fbc510 h1:El6M4kTTCOh6aBiKaUGG7oYTSPP8MxqL4YI3kZKwcP4=
+github.com/google/shlex v0.0.0-20191202100458-e7afc7fbc510/go.mod h1:pupxD2MaaD3pAXIBCelhxNneeOaAeabZDe5s4K6zSpQ=
+github.com/google/uuid v1.1.1/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
+github.com/google/uuid v1.1.2/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
+github.com/google/uuid v1.3.0 h1:t6JiXgmwXMjEs8VusXIJk2BXHsn+wx8BZdTaoZ5fu7I=
+github.com/google/uuid v1.3.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
+github.com/googleapis/enterprise-certificate-proxy v0.2.0 h1:y8Yozv7SZtlU//QXbezB6QkpuE6jMD2/gfzk4AftXjs=
+github.com/googleapis/enterprise-certificate-proxy v0.2.0/go.mod h1:8C0jb7/mgJe/9KK8Lm7X9ctZC2t60YyIpYEI16jx0Qg=
+github.com/googleapis/gax-go/v2 v2.6.0 h1:SXk3ABtQYDT/OH8jAyvEOQ58mgawq5C4o/4/89qN2ZU=
+github.com/googleapis/gax-go/v2 v2.6.0/go.mod h1:1mjbznJAPHFpesgE5ucqfYEscaz5kMdcIDwU/6+DDoY=
+github.com/gorilla/mux v1.7.4/go.mod h1:DVbg23sWSpFRCP0SfiEN6jmj59UnW/n46BH5rLB71So=
+github.com/hako/durafmt v0.0.0-20200710122514-c0fb7b4da026 h1:BpJ2o0OR5FV7vrkDYfXYVJQeMNWa8RhklZOpW2ITAIQ=
+github.com/hako/durafmt v0.0.0-20200710122514-c0fb7b4da026/go.mod h1:5Scbynm8dF1XAPwIwkGPqzkM/shndPm79Jd1003hTjE=
+github.com/hashicorp/aws-sdk-go-base v0.7.1 h1:7s/aR3hFn74tYPVihzDyZe7y/+BorN70rr9ZvpV3j3o=
+github.com/hashicorp/aws-sdk-go-base v0.7.1/go.mod h1:2fRjWDv3jJBeN6mVWFHV6hFTNeFBx2gpDLQaZNxUVAY=
+github.com/hashicorp/consul/api v1.10.1 h1:MwZJp86nlnL+6+W1Zly4JUuVn9YHhMggBirMpHGD7kw=
+github.com/hashicorp/consul/api v1.10.1/go.mod h1:XjsvQN+RJGWI2TWy1/kqaE16HrR2J/FWgkYjdZQsX9M=
+github.com/hashicorp/consul/sdk v0.8.0 h1:OJtKBtEjboEZvG6AOUdh4Z1Zbyu0WcxQ0qatRrZHTVU=
+github.com/hashicorp/consul/sdk v0.8.0/go.mod h1:GBvyrGALthsZObzUGsfgHZQDXjg4lOjagTIwIR1vPms=
+github.com/hashicorp/errwrap v1.0.0/go.mod h1:YH+1FKiLXxHSkmPseP+kNlulaMuP3n2brvKWEqk/Jc4=
+github.com/hashicorp/errwrap v1.1.0 h1:OxrOeh75EUXMY8TBjag2fzXGZ40LB6IKw45YeGUDY2I=
+github.com/hashicorp/errwrap v1.1.0/go.mod h1:YH+1FKiLXxHSkmPseP+kNlulaMuP3n2brvKWEqk/Jc4=
+github.com/hashicorp/go-azure-helpers v0.16.5 h1:rhcpg2Nk1Li6173KTHNnj/i+MGXYNjvYKIdNlg6q3RU=
+github.com/hashicorp/go-azure-helpers v0.16.5/go.mod h1:kR7+sTDEb9TOp/O80ss1UEJg1t4/BHLD/U8wHLS4BGQ=
+github.com/hashicorp/go-checkpoint v0.0.0-20171009173528-1545e56e46de h1:XDCSythtg8aWSRSO29uwhgh7b127fWr+m5SemqjSUL8=
+github.com/hashicorp/go-checkpoint v0.0.0-20171009173528-1545e56e46de/go.mod h1:xIwEieBHERyEvaeKF/TcHh1Hu+lxPM+n2vT1+g9I4m4=
+github.com/hashicorp/go-cleanhttp v0.5.0/go.mod h1:JpRdi6/HCYpAwUzNwuwqhbovhLtngrth3wmdIIUrZ80=
+github.com/hashicorp/go-cleanhttp v0.5.1/go.mod h1:JpRdi6/HCYpAwUzNwuwqhbovhLtngrth3wmdIIUrZ80=
+github.com/hashicorp/go-cleanhttp v0.5.2 h1:035FKYIWjmULyFRBKPs8TBQoi0x6d9G4xc9neXJWAZQ=
+github.com/hashicorp/go-cleanhttp v0.5.2/go.mod h1:kO/YDlP8L1346E6Sodw+PrpBSV4/SoxCXGY6BqNFT48=
+github.com/hashicorp/go-cty-funcs v0.0.0-20200930094925-2721b1e36840 h1:kgvybwEeu0SXktbB2y3uLHX9lklLo+nzUwh59A3jzQc=
+github.com/hashicorp/go-cty-funcs v0.0.0-20200930094925-2721b1e36840/go.mod h1:Abjk0jbRkDaNCzsRhOv2iDCofYpX1eVsjozoiK63qLA=
+github.com/hashicorp/go-getter/gcs/v2 v2.2.0 h1:oo6LVXva9I4CZzv531mn/FY5gtRx540I6eWwJVPWA4o=
+github.com/hashicorp/go-getter/gcs/v2 v2.2.0/go.mod h1:oDHNhZN2Gf6UqfIol4S9PkbzMFlf8rBctrJvAHDTtOM=
+github.com/hashicorp/go-getter/s3/v2 v2.2.0 h1:JGZihrdkZnuw+bDf8BnxuRLPwi0cfL2mwRlWA2lREAg=
+github.com/hashicorp/go-getter/s3/v2 v2.2.0/go.mod h1:hj0uM2nGIi0rln/VcvxjaQYQg3WGssfUh/ya5jA555g=
+github.com/hashicorp/go-getter/v2 v2.2.0 h1:vLenCsJqB5oNE141xKtT6cajhwAE8dneiNgzZA3oOqs=
+github.com/hashicorp/go-getter/v2 v2.2.0/go.mod h1:EcJx6oZE8hmGuRR1l38QrfnyiujQbwsEAn11eHv6l2M=
+github.com/hashicorp/go-hclog v0.0.0-20180709165350-ff2cf002a8dd/go.mod h1:9bjs9uLqI8l75knNv3lV1kA55veR+WUPSiKIWcQHudI=
+github.com/hashicorp/go-hclog v0.9.2/go.mod h1:5CU+agLiy3J7N7QjHK5d05KxGsuXiQLrjA0H7acj2lQ=
+github.com/hashicorp/go-hclog v0.12.0/go.mod h1:whpDNt7SSdeAju8AWKIWsul05p54N/39EeqMAyrmvFQ=
+github.com/hashicorp/go-hclog v0.14.1/go.mod h1:whpDNt7SSdeAju8AWKIWsul05p54N/39EeqMAyrmvFQ=
+github.com/hashicorp/go-hclog v0.16.1/go.mod h1:whpDNt7SSdeAju8AWKIWsul05p54N/39EeqMAyrmvFQ=
+github.com/hashicorp/go-hclog v0.16.2 h1:K4ev2ib4LdQETX5cSZBG0DVLk1jwGqSPXBjdah3veNs=
+github.com/hashicorp/go-hclog v0.16.2/go.mod h1:whpDNt7SSdeAju8AWKIWsul05p54N/39EeqMAyrmvFQ=
+github.com/hashicorp/go-immutable-radix v1.0.0/go.mod h1:0y9vanUI8NX6FsYoO3zeMjhV/C5i9g4Q3DwcSNZ4P60=
+github.com/hashicorp/go-immutable-radix v1.1.0/go.mod h1:0y9vanUI8NX6FsYoO3zeMjhV/C5i9g4Q3DwcSNZ4P60=
+github.com/hashicorp/go-immutable-radix v1.3.1 h1:DKHmCUm2hRBK510BaiZlwvpD40f8bJFeZnpfm2KLowc=
+github.com/hashicorp/go-immutable-radix v1.3.1/go.mod h1:0y9vanUI8NX6FsYoO3zeMjhV/C5i9g4Q3DwcSNZ4P60=
+github.com/hashicorp/go-kms-wrapping/entropy v0.1.0/go.mod h1:d1g9WGtAunDNpek8jUIEJnBlbgKS1N2Q61QkHiZyR1g=
+github.com/hashicorp/go-msgpack v0.5.3/go.mod h1:ahLV/dePpqEmjfWmKiqvPkv/twdG7iPBM1vqhUKIvfM=
+github.com/hashicorp/go-msgpack v0.5.5 h1:i9R9JSrqIz0QVLz3sz+i3YJdT7TTSLcfLLzJi9aZTuI=
+github.com/hashicorp/go-multierror v1.0.0/go.mod h1:dHtQlpGsu+cZNNAkkCN/P3hoUDHhCYQXV3UM06sGGrk=
+github.com/hashicorp/go-multierror v1.1.0/go.mod h1:spPvp8C1qA32ftKqdAHm4hHTbPw+vmowP0z+KUhOZdA=
+github.com/hashicorp/go-multierror v1.1.1 h1:H5DkEtf6CXdFp0N0Em5UCwQpXMWke8IA0+lD48awMYo=
+github.com/hashicorp/go-multierror v1.1.1/go.mod h1:iw975J/qwKPdAO1clOe2L8331t/9/fmwbPZ6JB6eMoM=
+github.com/hashicorp/go-plugin v1.0.1/go.mod h1:++UyYGoz3o5w9ZzAdZxtQKrWWP+iqPBn3cQptSMzBuY=
+github.com/hashicorp/go-retryablehttp v0.5.3/go.mod h1:9B5zBasrRhHXnJnui7y6sL7es7NDiJgTc6Er0maI1Xs=
+github.com/hashicorp/go-retryablehttp v0.6.2/go.mod h1:gEx6HMUGxYYhJScX7W1Il64m6cc2C1mDaW3NQ9sY1FY=
+github.com/hashicorp/go-retryablehttp v0.6.6/go.mod h1:vAew36LZh98gCBJNLH42IQ1ER/9wtLZZ8meHqQvEYWY=
+github.com/hashicorp/go-retryablehttp v0.7.0 h1:eu1EI/mbirUgP5C8hVsTNaGZreBDlYiwC1FZWkvQPQ4=
+github.com/hashicorp/go-retryablehttp v0.7.0/go.mod h1:vAew36LZh98gCBJNLH42IQ1ER/9wtLZZ8meHqQvEYWY=
+github.com/hashicorp/go-rootcerts v1.0.1/go.mod h1:pqUvnprVnM5bf7AOirdbb01K4ccR319Vf4pU3K5EGc8=
+github.com/hashicorp/go-rootcerts v1.0.2 h1:jzhAVGtqPKbwpyCPELlgNWhE1znq+qwJtW5Oi2viEzc=
+github.com/hashicorp/go-rootcerts v1.0.2/go.mod h1:pqUvnprVnM5bf7AOirdbb01K4ccR319Vf4pU3K5EGc8=
+github.com/hashicorp/go-safetemp v1.0.0 h1:2HR189eFNrjHQyENnQMMpCiBAsRxzbTMIgBhEyExpmo=
+github.com/hashicorp/go-safetemp v1.0.0/go.mod h1:oaerMy3BhqiTbVye6QuFhFtIceqFoDHxNAB65b+Rj1I=
+github.com/hashicorp/go-sockaddr v1.0.0/go.mod h1:7Xibr9yA9JjQq1JpNB2Vw7kxv8xerXegt+ozgdvDeDU=
+github.com/hashicorp/go-sockaddr v1.0.2 h1:ztczhD1jLxIRjVejw8gFomI1BQZOe2WoVOu0SyteCQc=
+github.com/hashicorp/go-sockaddr v1.0.2/go.mod h1:rB4wwRAUzs07qva3c5SdrY/NEtAUjGlgmH/UkBUC97A=
+github.com/hashicorp/go-syslog v1.0.0/go.mod h1:qPfqrKkXGihmCqbJM2mZgkZGvKG1dFdvsLplgctolz4=
+github.com/hashicorp/go-uuid v1.0.0/go.mod h1:6SBZvOh/SIDV7/2o3Jml5SYk/TvGqwFJ/bN7x4byOro=
+github.com/hashicorp/go-uuid v1.0.1/go.mod h1:6SBZvOh/SIDV7/2o3Jml5SYk/TvGqwFJ/bN7x4byOro=
+github.com/hashicorp/go-uuid v1.0.2 h1:cfejS+Tpcp13yd5nYHWDI6qVCny6wyX2Mt5SGur2IGE=
+github.com/hashicorp/go-uuid v1.0.2/go.mod h1:6SBZvOh/SIDV7/2o3Jml5SYk/TvGqwFJ/bN7x4byOro=
+github.com/hashicorp/go-version v1.1.0/go.mod h1:fltr4n8CU8Ke44wwGCBoEymUuxUHl09ZGVZPK5anwXA=
+github.com/hashicorp/go-version v1.2.0/go.mod h1:fltr4n8CU8Ke44wwGCBoEymUuxUHl09ZGVZPK5anwXA=
+github.com/hashicorp/go-version v1.2.1/go.mod h1:fltr4n8CU8Ke44wwGCBoEymUuxUHl09ZGVZPK5anwXA=
+github.com/hashicorp/go-version v1.6.0 h1:feTTfFNnjP967rlCxM/I9g701jU+RN74YKx2mOkIeek=
+github.com/hashicorp/go-version v1.6.0/go.mod h1:fltr4n8CU8Ke44wwGCBoEymUuxUHl09ZGVZPK5anwXA=
+github.com/hashicorp/golang-lru v0.5.0/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8=
+github.com/hashicorp/golang-lru v0.5.1/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8=
+github.com/hashicorp/golang-lru v0.5.3/go.mod h1:iADmTwqILo4mZ8BN3D2Q6+9jd8WM5uGBxy+E8yxSoD4=
+github.com/hashicorp/golang-lru v0.5.4 h1:YDjusn29QI/Das2iO9M0BHnIbxPeyuCHsjMW+lJfyTc=
+github.com/hashicorp/golang-lru v0.5.4/go.mod h1:iADmTwqILo4mZ8BN3D2Q6+9jd8WM5uGBxy+E8yxSoD4=
+github.com/hashicorp/hcl v1.0.0 h1:0Anlzjpi4vEasTeNFn2mLJgTSwt0+6sfsiTG8qcWGx4=
+github.com/hashicorp/hcl v1.0.0/go.mod h1:E5yfLk+7swimpb2L/Alb/PJmXilQ/rhwaUYs4T20WEQ=
+github.com/hashicorp/hcl/v2 v2.14.1 h1:x0BpjfZ+CYdbiz+8yZTQ+gdLO7IXvOut7Da+XJayx34=
+github.com/hashicorp/hcl/v2 v2.14.1/go.mod h1:e4z5nxYlWNPdDSNYX+ph14EvWYMFm3eP0zIUqPc2jr0=
+github.com/hashicorp/hcp-sdk-go v0.36.0 h1:B1qvnsStyYQyuEudgPrpMdheEC/zTeHRhyF1UwpYTJQ=
+github.com/hashicorp/hcp-sdk-go v0.36.0/go.mod h1:mJHPFD1Rs62bieKNVXUiFQlF76NCGACKqHu9a8ihcFk=
+github.com/hashicorp/logutils v1.0.0/go.mod h1:QIAnNjmIWmVIIkWDTG1z5v++HQmx9WQRO+LraFDTW64=
+github.com/hashicorp/mdns v1.0.1/go.mod h1:4gW7WsVCke5TE7EPeYliwHlRUyBtfCwuFwuMg2DmyNY=
+github.com/hashicorp/memberlist v0.2.2 h1:5+RffWKwqJ71YPu9mWsF7ZOscZmwfasdA8kbdC7AO2g=
+github.com/hashicorp/memberlist v0.2.2/go.mod h1:MS2lj3INKhZjWNqd3N0m3J+Jxf3DAOnAH9VT3Sh9MUE=
+github.com/hashicorp/packer-plugin-amazon v1.2.1 h1:0Xqr8KsTJJhIo0vvjqPYrVMgyVxNRuYH4DeB5m/WAtw=
+github.com/hashicorp/packer-plugin-amazon v1.2.1/go.mod h1:qlp0h5TWVGgcPzN9mSxPiEAwOUOW3XU/zep0pGd0ZsM=
+github.com/hashicorp/packer-plugin-ansible v1.0.3 h1:XjltQVPYnnZdNyBjwHr1QthR413SjZxTtRrmM0sM3VI=
+github.com/hashicorp/packer-plugin-ansible v1.0.3/go.mod h1:N4OZtNDq2FSRBknuNU/GSoKtllfxQnHCYYaJUD1p1MA=
+github.com/hashicorp/packer-plugin-azure v1.4.0 h1:rxkcGe5pjjnzddfR5/sBJmg8kb+ko+r2M+Ce7OC8sQ4=
+github.com/hashicorp/packer-plugin-azure v1.4.0/go.mod h1:7j1q0SNPeZr7xRID0c/Hu9QojE41pSlSJwsNB9/rOTI=
+github.com/hashicorp/packer-plugin-docker v1.0.8 h1:UWPG/pl+1RFsaNQVhEuowCeOZuES6/mqy5R6FTyMeQo=
+github.com/hashicorp/packer-plugin-docker v1.0.8/go.mod h1:4U3gHULbUw3okSqqZgQZD5ptyJKs0S7LfOOt2U3V4Jk=
+github.com/hashicorp/packer-plugin-googlecompute v1.1.0 h1:/cSZCJuRV6osaSa1uOy8cpN+c/uiCbrSsZ8vyNC0slk=
+github.com/hashicorp/packer-plugin-googlecompute v1.1.0/go.mod h1:k7MhKwEDw9ASP3a1y1syKJFZiZ8pO4oH40HvVgGHzUE=
+github.com/hashicorp/packer-plugin-qemu v1.0.9 h1:1YKBBzBULYUBWtpAZJTbaLjjZPAdQ63okkpTqMBTnzM=
+github.com/hashicorp/packer-plugin-qemu v1.0.9/go.mod h1:BpWIpVpOoPFV9Ppmzq4DP/S0QNoh1R+7DUCqxHdXc+Y=
+github.com/hashicorp/packer-plugin-sdk v0.4.0 h1:UyLYe0y02D9wkOQ3FeeZWyFg2+mx2vLuWRGUL5xt50I=
+github.com/hashicorp/packer-plugin-sdk v0.4.0/go.mod h1:uNhU3pmjM2ejgHYce/g4J+sa5rh81iYQztpGvGa5FOs=
+github.com/hashicorp/packer-plugin-vagrant v1.0.3 h1:IUfEdYuAjSjGsgJI2rnZ1qEo5rI0UWoueJ+yq9ysx4M=
+github.com/hashicorp/packer-plugin-vagrant v1.0.3/go.mod h1:Ymg8LJrT8N2Dclu91G3ZhXpE67jL7hfbtyDVKeNsKTc=
+github.com/hashicorp/packer-plugin-virtualbox v1.0.4 h1:mceFO34yhBU4BUMmCcQAB6KQ98GPjBIXTG3eS22RmZM=
+github.com/hashicorp/packer-plugin-virtualbox v1.0.4/go.mod h1:rnDkWJpkbcFPBmsMZcoImWDd9kLjTiXiN0sfHypuHac=
+github.com/hashicorp/packer-plugin-vmware v1.0.7 h1:cnc6XRNAkE+P5EoiI4VLXmIUeb2VAqW6zdNFmIW11YY=
+github.com/hashicorp/packer-plugin-vmware v1.0.7/go.mod h1:AGeNk9f/qKUP8yGoiofMqvBw8TJLtdhsZgvqannZQS4=
+github.com/hashicorp/packer-plugin-vsphere v1.1.1 h1:X4PtYV7TGPqoudjfvHpI2qRl9pAGf1SfkiJ7sMCKAEU=
+github.com/hashicorp/packer-plugin-vsphere v1.1.1/go.mod h1:kLbvU4EwRISjhvY3c5pVisCKE0Usn+pOMRkIPnwcPfU=
+github.com/hashicorp/serf v0.9.5 h1:EBWvyu9tcRszt3Bxp3KNssBMP1KuHWyO51lz9+786iM=
+github.com/hashicorp/serf v0.9.5/go.mod h1:UWDWwZeL5cuWDJdl0C6wrvrUwEqtQ4ZKBKKENpqIUyk=
+github.com/hashicorp/vault/api v1.0.5-0.20200519221902-385fac77e20f/go.mod h1:euTFbi2YJgwcju3imEt919lhJKF68nN1cQPq3aA+kBE=
+github.com/hashicorp/vault/api v1.1.1 h1:907ld+Z9cALyvbZK2qUX9cLwvSaEQsMVQB3x2KE8+AI=
+github.com/hashicorp/vault/api v1.1.1/go.mod h1:29UXcn/1cLOPHQNMWA7bCz2By4PSd0VKPAydKXS5yN0=
+github.com/hashicorp/vault/sdk v0.1.14-0.20200519221530-14615acda45f/go.mod h1:WX57W2PwkrOPQ6rVQk+dy5/htHIaB4aBM70EwKThu10=
+github.com/hashicorp/vault/sdk v0.2.1 h1:S4O6Iv/dyKlE9AUTXGa7VOvZmsCvg36toPKgV4f2P4M=
+github.com/hashicorp/vault/sdk v0.2.1/go.mod h1:WfUiO1vYzfBkz1TmoE4ZGU7HD0T0Cl/rZwaxjBkgN4U=
+github.com/hashicorp/yamux v0.0.0-20180604194846-3520598351bb/go.mod h1:+NfK9FKeTrX5uv1uIXGdwYDTeHna2qgaIlx54MXqjAM=
+github.com/hashicorp/yamux v0.0.0-20210826001029-26ff87cf9493 h1:brI5vBRUlAlM34VFmnLPwjnCL/FxAJp9XvOdX6Zt+XE=
+github.com/hashicorp/yamux v0.0.0-20210826001029-26ff87cf9493/go.mod h1:CtWFDAQgb7dxtzFs4tWbplKIe2jSi3+5vKbgIO0SLnQ=
+github.com/hpcloud/tail v1.0.0/go.mod h1:ab1qPbhIpdTxEkNHXyeSf5vhxWSCs/tWer42PpOxQnU=
+github.com/huandu/xstrings v1.3.2 h1:L18LIDzqlW6xN2rEkpdV8+oL/IXWJ1APd+vsdYy4Wdw=
+github.com/huandu/xstrings v1.3.2/go.mod h1:y5/lhBue+AyNmUVz9RLU9xbLR0o4KIIExikq4ovT0aE=
+github.com/imdario/mergo v0.3.11/go.mod h1:jmQim1M+e3UYxmgPu/WyfjB3N3VflVyUjjjwH0dnCYA=
+github.com/imdario/mergo v0.3.12 h1:b6R2BslTbIEToALKP7LxUvijTsNI9TAe80pLWN2g/HU=
+github.com/imdario/mergo v0.3.12/go.mod h1:jmQim1M+e3UYxmgPu/WyfjB3N3VflVyUjjjwH0dnCYA=
+github.com/inconshreveable/mousetrap v1.0.0/go.mod h1:PxqpIevigyE2G7u3NXJIT2ANytuPF1OarO4DADm73n8=
+github.com/jbenet/go-context v0.0.0-20150711004518-d14ea06fba99 h1:BQSFePA1RWJOlocH6Fxy8MmwDt+yVQYULKfN0RoTN8A=
+github.com/jbenet/go-context v0.0.0-20150711004518-d14ea06fba99/go.mod h1:1lJo3i6rXxKeerYnT8Nvf0QmHCRC1n8sfWVwXF2Frvo=
+github.com/jehiah/go-strftime v0.0.0-20171201141054-1d33003b3869 h1:IPJ3dvxmJ4uczJe5YQdrYB16oTJlGSC/OyZDqUk9xX4=
+github.com/jehiah/go-strftime v0.0.0-20171201141054-1d33003b3869/go.mod h1:cJ6Cj7dQo+O6GJNiMx+Pa94qKj+TG8ONdKHgMNIyyag=
+github.com/jessevdk/go-flags v1.5.0/go.mod h1:Fw0T6WPc1dYxT4mKEZRfG5kJhaTDP9pj1c2EWnYs/m4=
+github.com/jmespath/go-jmespath v0.0.0-20180206201540-c2b33e8439af/go.mod h1:Nht3zPeWKUH0NzdCt2Blrr5ys8VGpn0CEB0cQHVjt7k=
+github.com/jmespath/go-jmespath v0.3.0/go.mod h1:9QtRXoHjLGCJ5IBSaohpXITPlowMeeYCZ7fLUTSywik=
+github.com/jmespath/go-jmespath v0.4.0 h1:BEgLn5cpjn8UN1mAw4NjwDrS35OdebyEtFe+9YPoQUg=
+github.com/jmespath/go-jmespath v0.4.0/go.mod h1:T8mJZnbsbmF+m6zOOFylbeCJqk5+pHWvzYPziyZiYoo=
+github.com/jmespath/go-jmespath/internal/testify v1.5.1 h1:shLQSRRSCCPj3f2gpwzGwWFoC7ycTf1rcQZHOlsJ6N8=
+github.com/jmespath/go-jmespath/internal/testify v1.5.1/go.mod h1:L3OGu8Wl2/fWfCI6z80xFu9LTZmf1ZRjMHUOPmWr69U=
+github.com/joho/godotenv v1.3.0/go.mod h1:7hK45KPybAkOC6peb+G5yklZfMxEjkZhHbwpqxOKXbg=
+github.com/josharian/intern v1.0.0 h1:vlS4z54oSdjm0bgjRigI+G1HpF+tI+9rE5LLzOg8HmY=
+github.com/josharian/intern v1.0.0/go.mod h1:5DoeVV0s6jJacbCEi61lwdGj/aVlrQvzHFFd8Hwg//Y=
+github.com/json-iterator/go v1.1.6/go.mod h1:+SdeFBvtyEkXs7REEP0seUULqWtbJapLOCVDaaPEHmU=
+github.com/json-iterator/go v1.1.9/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4=
+github.com/julienschmidt/httprouter v1.2.0/go.mod h1:SYymIcj16QtmaHHD7aYtjjsJG7VTCxuUUipMqKk8s4w=
+github.com/karrick/godirwalk v1.8.0/go.mod h1:H5KPZjojv4lE+QYImBI8xVtrBRgYrIVsaRPx4tDPEn4=
+github.com/karrick/godirwalk v1.10.3/go.mod h1:RoGL9dQei4vP9ilrpETWE8CLOZ1kiN0LhBygSwrAsHA=
+github.com/kevinburke/ssh_config v0.0.0-20201106050909-4977a11b4351 h1:DowS9hvgyYSX4TO5NpyC606/Z4SxnNYbT+WX27or6Ck=
+github.com/kevinburke/ssh_config v0.0.0-20201106050909-4977a11b4351/go.mod h1:CT57kijsi8u/K/BOFA39wgDQJ9CxiF4nAY/ojJ6r6mM=
+github.com/kisielk/errcheck v1.1.0/go.mod h1:EZBBE59ingxPouuu3KfxchcWSUPOHkagtvWXihfKN4Q=
+github.com/kisielk/errcheck v1.2.0/go.mod h1:/BMXB+zMLi60iA8Vv6Ksmxu/1UDYcXs4uQLJ+jE2L00=
+github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck=
+github.com/klauspost/compress v1.4.1/go.mod h1:RyIbtBH6LamlWaDj8nUwkbUhJ87Yi3uG0guNDohfE1A=
+github.com/klauspost/compress v1.13.6 h1:P76CopJELS0TiO2mebmnzgWaajssP/EszplttgQxcgc=
+github.com/klauspost/compress v1.13.6/go.mod h1:/3/Vjq9QcHkK5uEr5lBEmyoZ1iFhe47etQ6QUkpK6sk=
+github.com/klauspost/cpuid v1.2.0/go.mod h1:Pj4uuM528wm8OyEC2QMXAi2YiTZ96dNQPGgoMS4s3ek=
+github.com/klauspost/pgzip v1.2.5 h1:qnWYvvKqedOF2ulHpMG72XQol4ILEJ8k2wwRl/Km8oE=
+github.com/klauspost/pgzip v1.2.5/go.mod h1:Ch1tH69qFZu15pkjo5kYi6mth2Zzwzt50oCQKQE9RUs=
+github.com/konsorten/go-windows-terminal-sequences v1.0.1/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ=
+github.com/konsorten/go-windows-terminal-sequences v1.0.2/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ=
+github.com/kortschak/utter v0.0.0-20190412033250-50fe362e6560/go.mod h1:oDr41C7kH9wvAikWyFhr6UFr8R7nelpmCF5XR5rL7I8=
+github.com/kr/fs v0.1.0 h1:Jskdu9ieNAYnjxsi0LbQp1ulIKZV1LAFgK1tWhpZgl8=
+github.com/kr/fs v0.1.0/go.mod h1:FFnZGqtBN9Gxj7eW1uZ42v5BccTP0vu6NEaFoC2HwRg=
+github.com/kr/logfmt v0.0.0-20140226030751-b84e30acd515/go.mod h1:+0opPa2QZZtGFBFZlji/RkVcI2GknAs/DXo4wKdlNEc=
+github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo=
+github.com/kr/pretty v0.2.0/go.mod h1:ipq/a2n7PKx3OHsz4KJII5eveXtPO4qwEXGdVfWzfnI=
+github.com/kr/pretty v0.2.1/go.mod h1:ipq/a2n7PKx3OHsz4KJII5eveXtPO4qwEXGdVfWzfnI=
+github.com/kr/pretty v0.3.0 h1:WgNl7dwNpEZ6jJ9k1snq4pZsg7DOEN8hP9Xw0Tsjwk0=
+github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ=
+github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI=
+github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY=
+github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE=
+github.com/kylelemons/godebug v0.0.0-20170820004349-d65d576e9348 h1:MtvEpTB6LX3vkb4ax0b5D2DHbNAUsen0Gx5wZoq3lV4=
+github.com/kylelemons/godebug v0.0.0-20170820004349-d65d576e9348/go.mod h1:B69LEHPfb2qLo0BaaOLcbitczOKLWTsrBG9LczfCD4k=
+github.com/lufia/plan9stats v0.0.0-20211012122336-39d0f177ccd0 h1:6E+4a0GO5zZEnZ81pIr0yLvtUWk2if982qA3F3QD6H4=
+github.com/lufia/plan9stats v0.0.0-20211012122336-39d0f177ccd0/go.mod h1:zJYVVT2jmtg6P3p1VtQj7WsuWi/y4VnjVBn7F8KPB3I=
+github.com/mailru/easyjson v0.0.0-20190614124828-94de47d64c63/go.mod h1:C1wdFJiN94OJF2b5HbByQZoLdCWB1Yqtg26g4irojpc=
+github.com/mailru/easyjson v0.0.0-20190626092158-b2ccc519800e/go.mod h1:C1wdFJiN94OJF2b5HbByQZoLdCWB1Yqtg26g4irojpc=
+github.com/mailru/easyjson v0.7.6/go.mod h1:xzfreul335JAWq5oZzymOObrkdz5UnU4kGfJJLY9Nlc=
+github.com/mailru/easyjson v0.7.7 h1:UGYAvKxe3sBsEDzO8ZeWOSlIQfWFlxbzLZe7hwFURr0=
+github.com/mailru/easyjson v0.7.7/go.mod h1:xzfreul335JAWq5oZzymOObrkdz5UnU4kGfJJLY9Nlc=
+github.com/markbates/oncer v0.0.0-20181203154359-bf2de49a0be2/go.mod h1:Ld9puTsIW75CHf65OeIOkyKbteujpZVXDpWK6YGZbxE=
+github.com/markbates/safe v1.0.1/go.mod h1:nAqgmRi7cY2nqMc92/bSEeQA+R4OheNU2T1kNSCBdG0=
+github.com/masterzen/simplexml v0.0.0-20160608183007-4572e39b1ab9/go.mod h1:kCEbxUJlNDEBNbdQMkPSp6yaKcRXVI6f4ddk8Riv4bc=
+github.com/masterzen/simplexml v0.0.0-20190410153822-31eea3082786 h1:2ZKn+w/BJeL43sCxI2jhPLRv73oVVOjEKZjKkflyqxg=
+github.com/masterzen/simplexml v0.0.0-20190410153822-31eea3082786/go.mod h1:kCEbxUJlNDEBNbdQMkPSp6yaKcRXVI6f4ddk8Riv4bc=
+github.com/masterzen/winrm v0.0.0-20210623064412-3b76017826b0 h1:KqYuDbSr8I2X8H65InN8SafDEa0UaLRy6WEmxDqd0F0=
+github.com/masterzen/winrm v0.0.0-20210623064412-3b76017826b0/go.mod h1:l31LCh9VvG43RJ83A5JLkFPjuz48cZAxBSLQLaIn1p8=
+github.com/matryer/is v1.2.0/go.mod h1:2fLPjFQM9rhQ15aVEtbuwhJinnOqrmgXPNdZsdwlWXA=
+github.com/matryer/is v1.4.0 h1:sosSmIWwkYITGrxZ25ULNDeKiMNzFSr4V/eqBQP0PeE=
+github.com/matryer/is v1.4.0/go.mod h1:8I/i5uYgLzgsgEloJE1U6xx5HkBQpAZvepWuujKwMRU=
+github.com/mattn/go-colorable v0.0.9/go.mod h1:9vuHe8Xs5qXnSaW/c/ABM9alt+Vo+STaOChaDxuIBZU=
+github.com/mattn/go-colorable v0.1.4/go.mod h1:U0ppj6V5qS13XJ6of8GYAs25YV2eR4EVcfRqFIhoBtE=
+github.com/mattn/go-colorable v0.1.6/go.mod h1:u6P/XSegPjTcexA+o6vUJrdnUu04hMope9wVRipJSqc=
+github.com/mattn/go-colorable v0.1.8 h1:c1ghPdyEDarC70ftn0y+A/Ee++9zz8ljHG1b13eJ0s8=
+github.com/mattn/go-colorable v0.1.8/go.mod h1:u6P/XSegPjTcexA+o6vUJrdnUu04hMope9wVRipJSqc=
+github.com/mattn/go-isatty v0.0.3/go.mod h1:M+lRXTBqGeGNdLjl/ufCoiOlB5xdOkqRJdNxMWT7Zi4=
+github.com/mattn/go-isatty v0.0.8/go.mod h1:Iq45c/XA43vh69/j3iqttzPXn0bhXyGjM0Hdxcsrc5s=
+github.com/mattn/go-isatty v0.0.10/go.mod h1:qgIWMr58cqv1PHHyhnkY9lrL7etaEgOFcMEpPG5Rm84=
+github.com/mattn/go-isatty v0.0.11/go.mod h1:PhnuNfih5lzO57/f3n+odYbM4JtupLOxQOAqxQCu2WE=
+github.com/mattn/go-isatty v0.0.12/go.mod h1:cbi8OIDigv2wuxKPP5vlRcQ1OAZbq2CE4Kysco4FUpU=
+github.com/mattn/go-isatty v0.0.13 h1:qdl+GuBjcsKKDco5BsxPJlId98mSWNKqYA+Co0SC1yA=
+github.com/mattn/go-isatty v0.0.13/go.mod h1:cbi8OIDigv2wuxKPP5vlRcQ1OAZbq2CE4Kysco4FUpU=
+github.com/mattn/go-runewidth v0.0.13 h1:lTGmDsbAYt5DmK6OnoV7EuIF1wEIFAcxld6ypU4OSgU=
+github.com/mattn/go-runewidth v0.0.13/go.mod h1:Jdepj2loyihRzMpdS35Xk/zdY8IAYHsh153qUoGf23w=
+github.com/mattn/go-tty v0.0.0-20191112051231-74040eebce08 h1:8YAWbq7rJqfbc6IaAvA2eCQuOQvf6Bs4vHKcOyWw//E=
+github.com/mattn/go-tty v0.0.0-20191112051231-74040eebce08/go.mod h1:XPvLUNfbS4fJH25nqRHfWLMa1ONC8Amw+mIA639KxkE=
+github.com/matttproud/golang_protobuf_extensions v1.0.1/go.mod h1:D8He9yQNgCq6Z5Ld7szi9bcBfOoFv/3dc6xSMkL2PC0=
+github.com/miekg/dns v1.0.14/go.mod h1:W1PPwlIAgtquWBMBEV9nkV9Cazfe8ScdGz/Lj7v3Nrg=
+github.com/miekg/dns v1.1.26 h1:gPxPSwALAeHJSjarOs00QjVdV9QoBvc1D2ujQUr5BzU=
+github.com/miekg/dns v1.1.26/go.mod h1:bPDLeHnStXmXAq1m/Ch/hvfNHr14JKNPMBo3VZKjuso=
+github.com/mitchellh/cli v1.0.0/go.mod h1:hNIlj7HEI86fIcpObd7a0FcrxTWetlwJDGcceTlRvqc=
+github.com/mitchellh/cli v1.1.0/go.mod h1:xcISNoH86gajksDmfB23e/pu+B+GeFRMYmoHXxx3xhI=
+github.com/mitchellh/cli v1.1.2 h1:PvH+lL2B7IQ101xQL63Of8yFS2y+aDlsFcsqNc+u/Kw=
+github.com/mitchellh/cli v1.1.2/go.mod h1:6iaV0fGdElS6dPBx0EApTxHrcWvmJphyh2n8YBLPPZ4=
+github.com/mitchellh/colorstring v0.0.0-20190213212951-d06e56a500db h1:62I3jR2EmQ4l5rM/4FEfDWcRD+abF5XlKShorW5LRoQ=
+github.com/mitchellh/colorstring v0.0.0-20190213212951-d06e56a500db/go.mod h1:l0dey0ia/Uv7NcFFVbCLtqEBQbrT4OCwCSKTEv6enCw=
+github.com/mitchellh/copystructure v1.0.0/go.mod h1:SNtv71yrdKgLRyLFxmLdkAbkKEFWgYaq1OVrnRcwhnw=
+github.com/mitchellh/copystructure v1.2.0 h1:vpKXTN4ewci03Vljg/q9QvCGUDttBOGBIa15WveJJGw=
+github.com/mitchellh/copystructure v1.2.0/go.mod h1:qLl+cE2AmVv+CoeAwDPye/v+N2HKCj9FbZEVFJRxO9s=
+github.com/mitchellh/go-fs v0.0.0-20180402235330-b7b9ca407fff h1:bFJ74ac7ZK/jyislqiWdzrnENesFt43sNEBRh1xk/+g=
+github.com/mitchellh/go-fs v0.0.0-20180402235330-b7b9ca407fff/go.mod h1:g7SZj7ABpStq3tM4zqHiVEG5un/DZ1+qJJKO7qx1EvU=
+github.com/mitchellh/go-homedir v1.1.0 h1:lukF9ziXFxDFPkA1vsr5zpc1XuPDn/wFntq5mG+4E0Y=
+github.com/mitchellh/go-homedir v1.1.0/go.mod h1:SfyaCUpYCn1Vlf4IUYiD9fPX4A5wJrkLzIz1N1q0pr0=
+github.com/mitchellh/go-testing-interface v0.0.0-20171004221916-a61a99592b77/go.mod h1:kRemZodwjscx+RGhAo8eIhFbs2+BFgRtFPeD/KE+zxI=
+github.com/mitchellh/go-testing-interface v1.0.0/go.mod h1:kRemZodwjscx+RGhAo8eIhFbs2+BFgRtFPeD/KE+zxI=
+github.com/mitchellh/go-testing-interface v1.14.1 h1:jrgshOhYAUVNMAJiKbEu7EqAwgJJ2JqpQmpLJOu07cU=
+github.com/mitchellh/go-testing-interface v1.14.1/go.mod h1:gfgS7OtZj6MA4U1UrDRp04twqAjfvlZyCfX3sDjEym8=
+github.com/mitchellh/go-vnc v0.0.0-20150629162542-723ed9867aed h1:FI2NIv6fpef6BQl2u3IZX/Cj20tfypRF4yd+uaHOMtI=
+github.com/mitchellh/go-vnc v0.0.0-20150629162542-723ed9867aed/go.mod h1:3rdaFaCv4AyBgu5ALFM0+tSuHrBh6v692nyQe3ikrq0=
+github.com/mitchellh/go-wordwrap v1.0.0/go.mod h1:ZXFpozHsX6DPmq2I0TCekCxypsnAUbP2oI0UX1GXzOo=
+github.com/mitchellh/go-wordwrap v1.0.1 h1:TLuKupo69TCn6TQSyGxwI1EblZZEsQ0vMlAFQflz0v0=
+github.com/mitchellh/go-wordwrap v1.0.1/go.mod h1:R62XHJLzvMFRBbcrT7m7WgmE1eOyTSsCt+hzestvNj0=
+github.com/mitchellh/iochan v1.0.0 h1:C+X3KsSTLFVBr/tK1eYN/vs4rJcvsiLU338UhYPJWeY=
+github.com/mitchellh/iochan v1.0.0/go.mod h1:JwYml1nuB7xOzsp52dPpHFffvOCDupsG0QubkSMEySY=
+github.com/mitchellh/mapstructure v0.0.0-20160808181253-ca63d7c062ee/go.mod h1:FVVH3fgwuzCH5S8UJGiWEs2h04kUh9fWfEaFds41c1Y=
+github.com/mitchellh/mapstructure v1.1.2/go.mod h1:FVVH3fgwuzCH5S8UJGiWEs2h04kUh9fWfEaFds41c1Y=
+github.com/mitchellh/mapstructure v1.3.2/go.mod h1:bFUtVrKA4DC2yAKiSyO/QUcy7e+RRV2QTWOzhPopBRo=
+github.com/mitchellh/mapstructure v1.3.3/go.mod h1:bFUtVrKA4DC2yAKiSyO/QUcy7e+RRV2QTWOzhPopBRo=
+github.com/mitchellh/mapstructure v1.4.1/go.mod h1:bFUtVrKA4DC2yAKiSyO/QUcy7e+RRV2QTWOzhPopBRo=
+github.com/mitchellh/mapstructure v1.5.0 h1:jeMsZIYE/09sWLaz43PL7Gy6RuMjD2eJVyuac5Z2hdY=
+github.com/mitchellh/mapstructure v1.5.0/go.mod h1:bFUtVrKA4DC2yAKiSyO/QUcy7e+RRV2QTWOzhPopBRo=
+github.com/mitchellh/panicwrap v1.0.0 h1:67zIyVakCIvcs69A0FGfZjBdPleaonSgGlXRSRlb6fE=
+github.com/mitchellh/panicwrap v1.0.0/go.mod h1:pKvZHwWrZowLUzftuFq7coarnxbBXU4aQh3N0BJOeeA=
+github.com/mitchellh/prefixedio v0.0.0-20151214002211-6e6954073784 h1:+DAetXqxv/mSyCkE9KBIYOZs9b68y7SUaDCxQMRjA68=
+github.com/mitchellh/prefixedio v0.0.0-20151214002211-6e6954073784/go.mod h1:kB1naBgV9ORnkiTVeyJOI1DavaJkG4oNIq0Af6ZVKUo=
+github.com/mitchellh/reflectwalk v1.0.0/go.mod h1:mSTlrgnPZtwu0c4WaC2kGObEpuNDbx0jmZXqmk4esnw=
+github.com/mitchellh/reflectwalk v1.0.2 h1:G2LzWKi524PWgd3mLHV8Y5k7s6XUvT0Gef6zxSIeXaQ=
+github.com/mitchellh/reflectwalk v1.0.2/go.mod h1:mSTlrgnPZtwu0c4WaC2kGObEpuNDbx0jmZXqmk4esnw=
+github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q=
+github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q=
+github.com/modern-go/reflect2 v0.0.0-20180701023420-4b7aa43c6742/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0=
+github.com/modern-go/reflect2 v1.0.1/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0=
+github.com/montanaflynn/stats v0.0.0-20171201202039-1bf9dbcd8cbe/go.mod h1:wL8QJuTMNUDYhXwkmfOly8iTdp5TEcJFWZD2D7SIkUc=
+github.com/morikuni/aec v1.0.0/go.mod h1:BbKIizmSmc5MMPqRYbxO4ZU0S0+P200+tUnFx7PXmsc=
+github.com/mwitkow/go-conntrack v0.0.0-20161129095857-cc309e4a2223/go.mod h1:qRWi+5nqEBWmkhHvq77mSJWrCKwh8bxhgT7d/eI7P4U=
+github.com/niemeyer/pretty v0.0.0-20200227124842-a10e7caefd8e/go.mod h1:zD1mROLANZcx1PVRCS0qkT7pwLkGfwJo4zjcN/Tysno=
+github.com/nu7hatch/gouuid v0.0.0-20131221200532-179d4d0c4d8d h1:VhgPp6v9qf9Agr/56bj7Y/xa04UccTW04VP0Qed4vnQ=
+github.com/nu7hatch/gouuid v0.0.0-20131221200532-179d4d0c4d8d/go.mod h1:YUTz3bUH2ZwIWBy3CJBeOBEugqcmXREj14T+iG/4k4U=
+github.com/oklog/run v1.0.0/go.mod h1:dlhp/R75TPv97u0XWUtDeV/lRKWPKSdTuV0TZvrmrQA=
+github.com/oklog/ulid v1.3.1 h1:EGfNDEx6MqHz8B3uNV6QAib1UR2Lm97sHi3ocA6ESJ4=
+github.com/oklog/ulid v1.3.1/go.mod h1:CirwcVhetQ6Lv90oh/F+FBtV6XMibvdAFo93nm5qn4U=
+github.com/onsi/ginkgo v1.6.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE=
+github.com/onsi/ginkgo v1.10.1/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE=
+github.com/onsi/gomega v1.7.0/go.mod h1:ex+gbHU/CVuBBDIJjb2X0qEXbFg53c61hWP/1CpauHY=
+github.com/opencontainers/go-digest v0.0.0-20180430190053-c9281466c8b2/go.mod h1:cMLVZDEM3+U2I4VmLI6N8jQYUd2OVphdqWwCJHrFt2s=
+github.com/opencontainers/go-digest v1.0.0-rc1/go.mod h1:cMLVZDEM3+U2I4VmLI6N8jQYUd2OVphdqWwCJHrFt2s=
+github.com/opencontainers/go-digest v1.0.0/go.mod h1:0JzlMkj0TRzQZfJkVvzbP0HBR3IKzErnv2BNG4W4MAM=
+github.com/opencontainers/image-spec v1.0.1/go.mod h1:BtxoFyWECRxE4U/7sNtV5W15zMzWCbyJoFRP3s7yZA0=
+github.com/opencontainers/runc v0.0.0-20190115041553-12f6a991201f/go.mod h1:qT5XzbpPznkRYVz/mWwUaVBUv2rmF59PVA73FjuZG0U=
+github.com/opencontainers/runc v0.1.1/go.mod h1:qT5XzbpPznkRYVz/mWwUaVBUv2rmF59PVA73FjuZG0U=
+github.com/opencontainers/runtime-spec v0.1.2-0.20190507144316-5b71a03e2700/go.mod h1:jwyrGlmzljRJv/Fgzds9SsS/C5hL+LL3ko9hs6T5lQ0=
+github.com/opentracing/opentracing-go v1.2.0 h1:uEJPy/1a5RIPAJ0Ov+OIO8OxWu77jEv+1B0VhjKrZUs=
+github.com/opentracing/opentracing-go v1.2.0/go.mod h1:GxEUsuufX4nBwe+T+Wl9TAgYrxe9dPLANfrWvHYVTgc=
+github.com/packer-community/winrmcp v0.0.0-20180921211025-c76d91c1e7db h1:9uViuKtx1jrlXLBW/pMnhOfzn3iSEdLase/But/IZRU=
+github.com/packer-community/winrmcp v0.0.0-20180921211025-c76d91c1e7db/go.mod h1:f6Izs6JvFTdnRbziASagjZ2vmf55NSIkC/weStxCHqk=
+github.com/pascaldekloe/goe v0.0.0-20180627143212-57f6aae5913c/go.mod h1:lzWF7FIEvWOWxwDKqyGYQf6ZUaNfKdP144TG7ZOy1lc=
+github.com/pascaldekloe/goe v0.1.0 h1:cBOtyMzM9HTpWjXfbbunk26uA6nG3a8n06Wieeh0MwY=
+github.com/pascaldekloe/goe v0.1.0/go.mod h1:lzWF7FIEvWOWxwDKqyGYQf6ZUaNfKdP144TG7ZOy1lc=
+github.com/pelletier/go-toml v1.7.0/go.mod h1:vwGMzjaWMwyfHwgIBhI2YUM4fB6nL6lVAvS1LBMMhTE=
+github.com/pierrec/lz4 v2.0.5+incompatible/go.mod h1:pdkljMzZIN41W+lC3N2tnIh5sFi+IEE17M5jbnwPHcY=
+github.com/pierrec/lz4 v2.5.2+incompatible/go.mod h1:pdkljMzZIN41W+lC3N2tnIh5sFi+IEE17M5jbnwPHcY=
+github.com/pierrec/lz4 v2.6.1+incompatible h1:9UY3+iC23yxF0UfGaYrGplQ+79Rg+h/q9FV9ix19jjM=
+github.com/pierrec/lz4 v2.6.1+incompatible/go.mod h1:pdkljMzZIN41W+lC3N2tnIh5sFi+IEE17M5jbnwPHcY=
+github.com/pkg/errors v0.8.0/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
+github.com/pkg/errors v0.8.1-0.20171018195549-f15c970de5b7/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
+github.com/pkg/errors v0.8.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
+github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4=
+github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
+github.com/pkg/sftp v1.13.2 h1:taJnKntsWgU+qae21Rx52lIwndAdKrj0mfUNQsz1z4Q=
+github.com/pkg/sftp v1.13.2/go.mod h1:LzqnAvaD5TWeNBsZpfKxSYn1MbjWwOsCIAFFJbpIsK8=
+github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
+github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
+github.com/posener/complete v1.1.1/go.mod h1:em0nMJCgc9GFtwrmVmEMR/ZL6WyhyjMBndrE9hABlRI=
+github.com/posener/complete v1.2.3 h1:NP0eAhjcjImqslEwo/1hq7gpajME0fTLTezBKDqfXqo=
+github.com/posener/complete v1.2.3/go.mod h1:WZIdtGGp+qx0sLrYKtIRAruyNpv6hFCicSgv7Sy7s/s=
+github.com/power-devops/perfstat v0.0.0-20210106213030-5aafc221ea8c h1:ncq/mPwQF4JjgDlrVEn3C11VoGHZN7m8qihwgMEtzYw=
+github.com/power-devops/perfstat v0.0.0-20210106213030-5aafc221ea8c/go.mod h1:OmDBASR4679mdNQnz2pUhc2G8CO2JrUAVFDRBDP/hJE=
+github.com/prometheus/client_golang v0.9.1/go.mod h1:7SWBe2y4D6OKWSNQJUaRYU/AaXPKyh/dDVn+NZz0KFw=
+github.com/prometheus/client_golang v0.9.2/go.mod h1:OsXs2jCmiKlQ1lTBmv21f2mNfw4xf/QclQDMrYNZzcM=
+github.com/prometheus/client_golang v1.0.0/go.mod h1:db9x61etRT2tGnBNRi70OPL5FsnadC4Ky3P0J6CfImo=
+github.com/prometheus/client_golang v1.4.0/go.mod h1:e9GMxYsXl05ICDXkRhurwBS4Q3OK1iX/F2sw+iXX5zU=
+github.com/prometheus/client_model v0.0.0-20180712105110-5c3871d89910/go.mod h1:MbSGuTsp3dbXC40dX6PRTWyKYBIrTGTE9sqQNg2J8bo=
+github.com/prometheus/client_model v0.0.0-20190129233127-fd36f4220a90/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA=
+github.com/prometheus/client_model v0.0.0-20190812154241-14fe0d1b01d4/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA=
+github.com/prometheus/client_model v0.2.0/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA=
+github.com/prometheus/common v0.0.0-20181126121408-4724e9255275/go.mod h1:daVV7qP5qjZbuso7PdcryaAu0sAZbrN9i7WWcTMWvro=
+github.com/prometheus/common v0.4.1/go.mod h1:TNfzLD0ON7rHzMJeJkieUDPYmFC7Snx/y86RQel1bk4=
+github.com/prometheus/common v0.9.1/go.mod h1:yhUN8i9wzaXS3w1O07YhxHEBxD+W35wd8bs7vj7HSQ4=
+github.com/prometheus/procfs v0.0.0-20180125133057-cb4147076ac7/go.mod h1:c3At6R/oaqEKCNdg8wHV1ftS6bRYblBhIjjI8uT2IGk=
+github.com/prometheus/procfs v0.0.0-20181005140218-185b4288413d/go.mod h1:c3At6R/oaqEKCNdg8wHV1ftS6bRYblBhIjjI8uT2IGk=
+github.com/prometheus/procfs v0.0.0-20181204211112-1dc9a6cbc91a/go.mod h1:c3At6R/oaqEKCNdg8wHV1ftS6bRYblBhIjjI8uT2IGk=
+github.com/prometheus/procfs v0.0.2/go.mod h1:TjEm7ze935MbeOT/UhFTIMYKhuLP4wbCsTZCD3I8kEA=
+github.com/prometheus/procfs v0.0.8/go.mod h1:7Qr8sr6344vo1JqZ6HhLceV9o3AJ1Ff+GxbHq6oeK9A=
+github.com/rivo/uniseg v0.2.0 h1:S1pD9weZBuJdFmowNwbpi7BJ8TNftyUImj/0WQi72jY=
+github.com/rivo/uniseg v0.2.0/go.mod h1:J6wj4VEh+S6ZtnVlnTBMWIodfgj8LQOQFoIToxlJtxc=
+github.com/rogpeppe/go-internal v1.1.0/go.mod h1:M8bDsm7K2OlrFYOpmOWEs/qY81heoFRclV5y23lUDJ4=
+github.com/rogpeppe/go-internal v1.2.2/go.mod h1:M8bDsm7K2OlrFYOpmOWEs/qY81heoFRclV5y23lUDJ4=
+github.com/rogpeppe/go-internal v1.3.0/go.mod h1:M8bDsm7K2OlrFYOpmOWEs/qY81heoFRclV5y23lUDJ4=
+github.com/rogpeppe/go-internal v1.9.0 h1:73kH8U+JUqXU8lRuOHeVHaa/SZPifC7BkcraZVejAe8=
+github.com/ryanuber/columnize v0.0.0-20160712163229-9b3edd62028f/go.mod h1:sm1tb6uqfes/u+d4ooFouqFdy9/2g9QGwK3SQygK0Ts=
+github.com/ryanuber/columnize v2.1.0+incompatible/go.mod h1:sm1tb6uqfes/u+d4ooFouqFdy9/2g9QGwK3SQygK0Ts=
+github.com/ryanuber/go-glob v1.0.0 h1:iQh3xXAumdQ+4Ufa5b25cRpC5TYKlno6hsv6Cb3pkBk=
+github.com/ryanuber/go-glob v1.0.0/go.mod h1:807d1WSdnB0XRJzKNil9Om6lcp/3a0v4qIHxIXzX/Yc=
+github.com/satori/go.uuid v1.2.0 h1:0uYX9dsZ2yD7q2RtLRtPSdGDWzjeM3TbMJP9utgA0ww=
+github.com/sean-/seed v0.0.0-20170313163322-e2103e2c3529 h1:nn5Wsu0esKSJiIVhscUtVbo7ada43DJhG55ua/hjS5I=
+github.com/sean-/seed v0.0.0-20170313163322-e2103e2c3529/go.mod h1:DxrIzT+xaE7yg65j358z/aeFdxmN0P9QXhEzd20vsDc=
+github.com/sergi/go-diff v1.1.0 h1:we8PVUC3FE2uYfodKH/nBHMSetSfHDR6scGdBi+erh0=
+github.com/sergi/go-diff v1.1.0/go.mod h1:STckp+ISIX8hZLjrqAeVduY0gWCT9IjLuqbuNXdaHfM=
+github.com/shirou/gopsutil/v3 v3.23.4 h1:hZwmDxZs7Ewt75DV81r4pFMqbq+di2cbt9FsQBqLD2o=
+github.com/shirou/gopsutil/v3 v3.23.4/go.mod h1:ZcGxyfzAMRevhUR2+cfhXDH6gQdFYE/t8j1nsU4mPI8=
+github.com/shoenig/go-m1cpu v0.1.5 h1:LF57Z/Fpb/WdGLjt2HZilNnmZOxg/q2bSKTQhgbrLrQ=
+github.com/shoenig/go-m1cpu v0.1.5/go.mod h1:Wwvst4LR89UxjeFtLRMrpgRiyY4xPsejnVZym39dbAQ=
+github.com/shoenig/test v0.6.3 h1:GVXWJFk9PiOjN0KoJ7VrJGH6uLPnqxR7/fe3HUPfE0c=
+github.com/shoenig/test v0.6.3/go.mod h1:byHiCGXqrVaflBLAMq/srcZIHynQPQgeyvkvXnjqq0k=
+github.com/sirupsen/logrus v1.0.4-0.20170822132746-89742aefa4b2/go.mod h1:pMByvHTf9Beacp5x1UXfOR9xyW/9antXMhjMPG0dEzc=
+github.com/sirupsen/logrus v1.2.0/go.mod h1:LxeOpSwHxABJmUn/MG1IvRgCAasNZTLOkJPxbbu5VWo=
+github.com/sirupsen/logrus v1.4.0/go.mod h1:LxeOpSwHxABJmUn/MG1IvRgCAasNZTLOkJPxbbu5VWo=
+github.com/sirupsen/logrus v1.4.1/go.mod h1:ni0Sbl8bgC9z8RoU9G6nDWqqs/fq4eDPysMBDgk/93Q=
+github.com/sirupsen/logrus v1.4.2/go.mod h1:tLMulIdttU9McNUspp0xgXVQah82FyeX6MwdIuYE2rE=
+github.com/skratchdot/open-golang v0.0.0-20200116055534-eef842397966 h1:JIAuq3EEf9cgbU6AtGPK4CTG3Zf6CKMNqf0MHTggAUA=
+github.com/skratchdot/open-golang v0.0.0-20200116055534-eef842397966/go.mod h1:sUM3LWHvSMaG192sy56D9F7CNvL7jUJVXoqM1QKLnog=
+github.com/spf13/cobra v0.0.2-0.20171109065643-2da4a54c5cee/go.mod h1:1l0Ry5zgKvJasoi3XT1TypsSe7PqH0Sj9dhYf7v3XqQ=
+github.com/spf13/cobra v0.0.3/go.mod h1:1l0Ry5zgKvJasoi3XT1TypsSe7PqH0Sj9dhYf7v3XqQ=
+github.com/spf13/pflag v1.0.1-0.20171106142849-4c012f6dcd95/go.mod h1:DYY7MBk1bdzusC3SYhjObp+wFpr4gzcvqqNjLnInEg4=
+github.com/spf13/pflag v1.0.3/go.mod h1:DYY7MBk1bdzusC3SYhjObp+wFpr4gzcvqqNjLnInEg4=
+github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
+github.com/stretchr/objx v0.1.1/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
+github.com/stretchr/objx v0.4.0/go.mod h1:YvHI0jy2hoMjB+UWwv71VJQ9isScKT/TqJzVSSt89Yw=
+github.com/stretchr/objx v0.5.0 h1:1zr/of2m5FGMsad5YfcqgdqdWrIhu+EBEJRhR1U7z/c=
+github.com/stretchr/objx v0.5.0/go.mod h1:Yh+to48EsGEfYuaHDzXPcE3xhTkx73EhmCGUpEOglKo=
+github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs=
+github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI=
+github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4=
+github.com/stretchr/testify v1.5.1/go.mod h1:5W2xD1RspED5o8YsWQXVCued0rvSQ+mT+I5cxcmMvtA=
+github.com/stretchr/testify v1.6.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
+github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
+github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
+github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU=
+github.com/stretchr/testify v1.8.2 h1:+h33VjcLVPDHtOdpUCuF+7gSuG3yGIftsP1YvFihtJ8=
+github.com/stretchr/testify v1.8.2/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4=
+github.com/tidwall/pretty v1.0.0 h1:HsD+QiTn7sK6flMKIvNmpqz1qrpP3Ps6jOKIKMooyg4=
+github.com/tidwall/pretty v1.0.0/go.mod h1:XNkn88O1ChpSDQmQeStsy+sBenx6DDtFZJxhVysOjyk=
+github.com/tklauser/go-sysconf v0.3.11 h1:89WgdJhk5SNwJfu+GKyYveZ4IaJ7xAkecBo+KdJV0CM=
+github.com/tklauser/go-sysconf v0.3.11/go.mod h1:GqXfhXY3kiPa0nAXPDIQIWzJbMCB7AmcWpGR8lSZfqI=
+github.com/tklauser/numcpus v0.6.0 h1:kebhY2Qt+3U6RNK7UqpYNA+tJ23IBEGKkB7JQBfDYms=
+github.com/tklauser/numcpus v0.6.0/go.mod h1:FEZLMke0lhOUG6w2JadTzp0a+Nl8PF/GFkQ5UVIcaL4=
+github.com/tv42/httpunix v0.0.0-20150427012821-b75d8614f926/go.mod h1:9ESjWnEqriFuLhtthL60Sar/7RFoluCcXsuvEwTV5KM=
+github.com/ugorji/go v1.2.6/go.mod h1:anCg0y61KIhDlPZmnH+so+RQbysYVyDko0IMgJv0Nn0=
+github.com/ugorji/go/codec v1.2.6 h1:7kbGefxLoDBuYXOms4yD7223OpNMMPNPZxXk5TvFcyQ=
+github.com/ugorji/go/codec v1.2.6/go.mod h1:V6TCNZ4PHqoHGFZuSG1W8nrCzzdgA2DozYxWFFpvxTw=
+github.com/ulikunitz/xz v0.5.6/go.mod h1:2bypXElzHzzJZwzH67Y6wb67pO62Rzfn7BSiF4ABRW8=
+github.com/ulikunitz/xz v0.5.10 h1:t92gobL9l3HE202wg3rlk19F6X+JOxl9BBrCCMYEYd8=
+github.com/ulikunitz/xz v0.5.10/go.mod h1:nbz6k7qbPmH4IRqmfOplQw/tblSgqTqBwxkY0oWt/14=
+github.com/urfave/cli v0.0.0-20171014202726-7bc6a0acffa5/go.mod h1:70zkFmudgCuE/ngEzBv17Jvp/497gISqfk5gWijbERA=
+github.com/vmihailenco/msgpack v3.3.3+incompatible/go.mod h1:fy3FlTQTDXWkZ7Bh6AcGMlsjHatGryHQYUTf1ShIgkk=
+github.com/vmihailenco/msgpack/v4 v4.3.12/go.mod h1:gborTTJjAo/GWTqqRjrLCn9pgNN+NXzzngzBKDPIqw4=
+github.com/vmihailenco/tagparser v0.1.1/go.mod h1:OeAg3pn3UbLjkWt+rN9oFYB6u/cQgqMEUPoW2WPyhdI=
+github.com/vmware/govmomi v0.29.0 h1:SHJQ7DUc4fltFZv16znJNGHR1/XhiDK5iKxm2OqwkuU=
+github.com/vmware/govmomi v0.29.0/go.mod h1:F7adsVewLNHsW/IIm7ziFURaXDaHEwcc+ym4r3INMdY=
+github.com/xanzy/ssh-agent v0.3.0 h1:wUMzuKtKilRgBAD1sUb8gOwwRr2FGoBVumcjoOACClI=
+github.com/xanzy/ssh-agent v0.3.0/go.mod h1:3s9xbODqPuuhK9JV1R321M/FlMZSBvE5aY6eAcqrDh0=
+github.com/xdg-go/pbkdf2 v1.0.0/go.mod h1:jrpuAogTd400dnrH08LKmI/xc1MbPOebTwRqcT5RDeI=
+github.com/xdg-go/scram v1.0.2/go.mod h1:1WAq6h33pAW+iRreB34OORO2Nf7qel3VV3fjBj+hCSs=
+github.com/xdg-go/scram v1.1.1/go.mod h1:RaEWvsqvNKKvBPvcKeFjrG2cJqOkHTiyTpzz23ni57g=
+github.com/xdg-go/stringprep v1.0.2/go.mod h1:8F9zXuvzgwmyT5DUm4GUfZGDdT3W+LCvS6+da4O5kxM=
+github.com/xdg-go/stringprep v1.0.3/go.mod h1:W3f5j4i+9rC0kuIEJL0ky1VpHXQU3ocBgklLGvcBnW8=
+github.com/youmark/pkcs8 v0.0.0-20181117223130-1be2e3e5546d/go.mod h1:rHwXgn7JulP+udvsHwJoVG1YGAP6VLg4y9I5dyZdqmA=
+github.com/yuin/goldmark v1.1.32/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
+github.com/yuin/goldmark v1.3.5/go.mod h1:mwnBkeHKe2W/ZEtQ+71ViKU8L12m81fl3OWwC1Zlc8k=
+github.com/yusufpapurcu/wmi v1.2.2 h1:KBNDSne4vP5mbSWnJbO+51IMOXJB67QiYCSBrubbPRg=
+github.com/yusufpapurcu/wmi v1.2.2/go.mod h1:SBZ9tNy3G9/m5Oi98Zks0QjeHVDvuK0qfxQmPyzfmi0=
+github.com/zclconf/go-cty v1.0.0/go.mod h1:xnAOWiHeOqg2nWS62VtQ7pbOu17FtxJNW8RLEih+O3s=
+github.com/zclconf/go-cty v1.4.0/go.mod h1:nHzOclRkoj++EU9ZjSrZvRG0BXIWt8c7loYc0qXAFGQ=
+github.com/zclconf/go-cty v1.10.0 h1:mp9ZXQeIcN8kAwuqorjH+Q+njbJKjLrvB2yIh4q7U+0=
+github.com/zclconf/go-cty v1.10.0/go.mod h1:vVKLxnk3puL4qRAv72AO+W99LUD4da90g3uUAzyuvAk=
+github.com/zclconf/go-cty-yaml v1.0.1 h1:up11wlgAaDvlAGENcFDnZgkn0qUJurso7k6EpURKNF8=
+github.com/zclconf/go-cty-yaml v1.0.1/go.mod h1:IP3Ylp0wQpYm50IHK8OZWKMu6sPJIUgKa8XhiVHura0=
+go.mongodb.org/mongo-driver v1.7.3/go.mod h1:NqaYOwnXWr5Pm7AOpO5QFxKJ503nbMse/R79oO62zWg=
+go.mongodb.org/mongo-driver v1.7.5/go.mod h1:VXEWRZ6URJIkUq2SCAyapmhH0ZLRBP+FT4xhp5Zvxng=
+go.mongodb.org/mongo-driver v1.10.0/go.mod h1:wsihk0Kdgv8Kqu1Anit4sfK+22vSFbUrAVEYRhCXrA8=
+go.mongodb.org/mongo-driver v1.11.0 h1:FZKhBSTydeuffHj9CBjXlR8vQLee1cQyTWYPA6/tqiE=
+go.mongodb.org/mongo-driver v1.11.0/go.mod h1:s7p5vEtfbeR1gYi6pnj3c3/urpbLv2T5Sfd6Rp2HBB8=
+go.opencensus.io v0.22.0/go.mod h1:+kGneAE2xo2IficOXnaByMWTGM9T73dGwxeWcUqIpI8=
+go.opencensus.io v0.23.0 h1:gqCw0LfLxScz8irSi8exQc7fyQ0fKQU/qnC/X8+V/1M=
+go.opencensus.io v0.23.0/go.mod h1:XItmlyltB5F7CS4xOC1DcqMoFqwtC6OG2xF7mCv7P7E=
+go.opentelemetry.io/otel v1.11.1 h1:4WLLAmcfkmDk2ukNXJyq3/kiz/3UzCaYq6PskJsaou4=
+go.opentelemetry.io/otel v1.11.1/go.mod h1:1nNhXBbWSD0nsL38H6btgnFN2k4i0sNLHNNMZMSbUGE=
+go.opentelemetry.io/otel/sdk v1.11.1 h1:F7KmQgoHljhUuJyA+9BiU+EkJfyX5nVVF4wyzWZpKxs=
+go.opentelemetry.io/otel/trace v1.11.1 h1:ofxdnzsNrGBYXbP7t7zpUK281+go5rF7dvdIZXF8gdQ=
+go.opentelemetry.io/otel/trace v1.11.1/go.mod h1:f/Q9G7vzk5u91PhbmKbg1Qn0rzH1LJ4vbPHFGkTPtOk=
+go.uber.org/atomic v1.6.0/go.mod h1:sABNBOSYdrvTF6hTgEIbc7YasKWGhgEQZyfxyTvoXHQ=
+golang.org/x/crypto v0.0.0-20171113213409-9f005a07e0d3/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4=
+golang.org/x/crypto v0.0.0-20180904163835-0709b304e793/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4=
+golang.org/x/crypto v0.0.0-20181029021203-45a5f77698d3/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4=
+golang.org/x/crypto v0.0.0-20190219172222-a4c6cb3142f2/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4=
+golang.org/x/crypto v0.0.0-20190222235706-ffb98f73852f/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4=
+golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
+golang.org/x/crypto v0.0.0-20190418165655-df01cb2cc480/go.mod h1:WFFai1msRO1wXaEeE5yQxYXgSfI8pQAWXbQop6sCtWE=
+golang.org/x/crypto v0.0.0-20190422162423-af44ce270edf/go.mod h1:WFFai1msRO1wXaEeE5yQxYXgSfI8pQAWXbQop6sCtWE=
+golang.org/x/crypto v0.0.0-20190510104115-cbcb75029529/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
+golang.org/x/crypto v0.0.0-20190923035154-9ee001bba392/go.mod h1:/lpIB1dKB+9EgE3H3cr1v9wB50oz8l4C4h62xy7jSTY=
+golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
+golang.org/x/crypto v0.0.0-20191206172530-e9b2fee46413/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
+golang.org/x/crypto v0.0.0-20200302210943-78000ba7a073/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
+golang.org/x/crypto v0.0.0-20200422194213-44a606286825/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
+golang.org/x/crypto v0.0.0-20200604202706-70a84ac30bf9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
+golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
+golang.org/x/crypto v0.0.0-20200820211705-5c72a883971a/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
+golang.org/x/crypto v0.0.0-20201002170205-7f63de1d35b0/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
+golang.org/x/crypto v0.0.0-20210220033148-5ea612d1eb83/go.mod h1:jdWPYTVW3xRLrWPugEBEK3UY2ZEsg3UU495nc5E+M+I=
+golang.org/x/crypto v0.0.0-20210322153248-0c34fe9e7dc2/go.mod h1:T9bdIzuCu7OtxOm1hfPfRQxPLYneinmdGuTeoZ9dtd4=
+golang.org/x/crypto v0.0.0-20210421170649-83a5a9bb288b/go.mod h1:T9bdIzuCu7OtxOm1hfPfRQxPLYneinmdGuTeoZ9dtd4=
+golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc=
+golang.org/x/crypto v0.0.0-20220622213112-05595931fe9d/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4=
+golang.org/x/crypto v0.11.0 h1:6Ewdq3tDic1mg5xRO4milcWCfMVQhI4NkqWWvqejpuA=
+golang.org/x/crypto v0.11.0/go.mod h1:xgJhtzW8F9jGdVFWZESrid1U1bjeNy4zgy5cRr/CIio=
+golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA=
+golang.org/x/exp v0.0.0-20190306152737-a1d7652674e8/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA=
+golang.org/x/exp v0.0.0-20190731235908-ec7cb31e5a56/go.mod h1:JhuoJpWY28nO4Vef9tZUw9qufEGTyX1+7lmHxV5q5G4=
+golang.org/x/exp v0.0.0-20200119233911-0405dc783f0a/go.mod h1:2RIsYlXP63K8oxa1u096TMicItID8zy7Y6sNkU49FU4=
+golang.org/x/image v0.0.0-20190227222117-0694c2d4d067/go.mod h1:kZ7UVZpmo3dzQBMxlp+ypCbDeSB+sBbTgSJuh5dn5js=
+golang.org/x/image v0.0.0-20190802002840-cff245a6509b/go.mod h1:FeLwcggjj3mMvU+oOTbSwawSJRM1uh48EjtB4UJZlP0=
+golang.org/x/lint v0.0.0-20181026193005-c67002cb31c3/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE=
+golang.org/x/lint v0.0.0-20190227174305-5b3e6a55c961/go.mod h1:wehouNa3lNwaWXcvxsM5YxQ5yQlVC4a0KAMCusXpPoU=
+golang.org/x/lint v0.0.0-20190313153728-d0100b6bd8b3/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc=
+golang.org/x/lint v0.0.0-20190930215403-16217165b5de/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc=
+golang.org/x/mobile v0.0.0-20190312151609-d3739f865fa6/go.mod h1:z+o9i4GpDbdi3rU15maQ/Ox0txvL9dWGYEHz965HBQE=
+golang.org/x/mobile v0.0.0-20190719004257-d2bd2a29d028/go.mod h1:E/iHnbuqvinMTCcRqshq8CkpyQDoeVncDDYHnLhea+o=
+golang.org/x/mobile v0.0.0-20210901025245-1fde1d6c3ca1 h1:t3ZHqovedSY8DEAUmZA99fPJhUhOb176PLACYA1sJ8Y=
+golang.org/x/mobile v0.0.0-20210901025245-1fde1d6c3ca1/go.mod h1:jFTmtFYCV0MFtXBU+J5V/+5AUeVS0ON/0WkE/KSrl6E=
+golang.org/x/mod v0.1.0/go.mod h1:0QHyrYULN0/3qlju5TqG8bIK38QM8yzMo5ekMj3DlcY=
+golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
+golang.org/x/mod v0.4.2/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
+golang.org/x/mod v0.8.0 h1:LUYupSeNrTNCGzR/hVBk2NHZO4hXcVaW1k4Qx7rjPx8=
+golang.org/x/mod v0.8.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs=
+golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
+golang.org/x/net v0.0.0-20180811021610-c39426892332/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
+golang.org/x/net v0.0.0-20180826012351-8a410e7b638d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
+golang.org/x/net v0.0.0-20180906233101-161cd47e91fd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
+golang.org/x/net v0.0.0-20181023162649-9b4f9f5ad519/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
+golang.org/x/net v0.0.0-20181114220301-adae6a3d119a/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
+golang.org/x/net v0.0.0-20181201002055-351d144fa1fc/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
+golang.org/x/net v0.0.0-20190213061140-3a22650c66bd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
+golang.org/x/net v0.0.0-20190311183353-d8887717615a/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
+golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
+golang.org/x/net v0.0.0-20190501004415-9ce7a6920f09/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
+golang.org/x/net v0.0.0-20190603091049-60506f45cf65/go.mod h1:HSz+uSET+XFnRR8LxR5pz3Of3rY3CfYBVs4xY44aLks=
+golang.org/x/net v0.0.0-20190613194153-d28f0bde5980/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
+golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
+golang.org/x/net v0.0.0-20190813141303-74dc4d7220e7/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
+golang.org/x/net v0.0.0-20190923162816-aa69164e4478/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
+golang.org/x/net v0.0.0-20191004110552-13f9640d40b9/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
+golang.org/x/net v0.0.0-20200202094626-16171245cfb2/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
+golang.org/x/net v0.0.0-20200301022130-244492dfa37a/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
+golang.org/x/net v0.0.0-20200602114024-627f9648deb9/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A=
+golang.org/x/net v0.0.0-20200625001655-4c5254603344/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA=
+golang.org/x/net v0.0.0-20201110031124-69a78807bb2b/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU=
+golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg=
+golang.org/x/net v0.0.0-20210326060303-6b1517762897/go.mod h1:uSPa2vr4CLtc/ILN5odXGNXS6mhrKVzTaCXzk9m6W3k=
+golang.org/x/net v0.0.0-20210405180319-a5a99cb37ef4/go.mod h1:p54w0d4576C0XHj96bSt6lcn1PtDYWL6XObtHCRCNQM=
+golang.org/x/net v0.0.0-20210421230115-4e50805a0758/go.mod h1:72T/g9IO56b78aLF+1Kcs5dz7/ng1VjMUvfKvpfy+jM=
+golang.org/x/net v0.0.0-20211112202133-69e39bad7dc2/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=
+golang.org/x/net v0.0.0-20220127200216-cd36cc0744dd/go.mod h1:CfG3xpIq0wQ8r1q4Su4UZFWDARRcnwPjda9FqA0JpMk=
+golang.org/x/net v0.13.0 h1:Nvo8UFsZ8X3BhAC9699Z1j7XQ3rsZnUUm7jfBEk1ueY=
+golang.org/x/net v0.13.0/go.mod h1:zEVYFnQC7m/vmpQFELhcD1EWkZlX69l4oqgmer6hfKA=
+golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U=
+golang.org/x/oauth2 v0.1.0 h1:isLCZuhj4v+tYv7eskaN4v/TM+A1begWWgyVJDdl1+Y=
+golang.org/x/oauth2 v0.1.0/go.mod h1:G9FE4dLTsbXUu90h/Pf85g4w1D+SSAgR+q46nJZ8M4A=
+golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
+golang.org/x/sync v0.0.0-20181108010431-42b317875d0f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
+golang.org/x/sync v0.0.0-20181221193216-37e7f081c4d4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
+golang.org/x/sync v0.0.0-20190227155943-e225da77a7e6/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
+golang.org/x/sync v0.0.0-20190412183630-56d357773e84/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
+golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
+golang.org/x/sync v0.0.0-20190911185100-cd5d95a43a6e/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
+golang.org/x/sync v0.0.0-20200625203802-6e8e738ad208/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
+golang.org/x/sync v0.0.0-20210220032951-036812b2e83c/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
+golang.org/x/sync v0.1.0 h1:wsuoTGHzEhffawBOhz5CYhcrV4IdKZbEyZjBMuTp12o=
+golang.org/x/sync v0.1.0/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
+golang.org/x/sys v0.0.0-20180823144017-11551d06cbcc/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
+golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
+golang.org/x/sys v0.0.0-20180905080454-ebe1bf3edb33/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
+golang.org/x/sys v0.0.0-20180909124046-d0be0721c37e/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
+golang.org/x/sys v0.0.0-20181026203630-95b1ffbd15a5/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
+golang.org/x/sys v0.0.0-20181116152217-5ac8a444bdc5/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
+golang.org/x/sys v0.0.0-20190129075346-302c3dd5f1cc/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
+golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
+golang.org/x/sys v0.0.0-20190222072716-a9d3bda3a223/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
+golang.org/x/sys v0.0.0-20190312061237-fead79001313/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
+golang.org/x/sys v0.0.0-20190403152447-81d4e9dc473e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
+golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
+golang.org/x/sys v0.0.0-20190419153524-e8e3143a4f4a/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
+golang.org/x/sys v0.0.0-20190422165155-953cdadca894/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
+golang.org/x/sys v0.0.0-20190502145724-3ef323f4f1fd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
+golang.org/x/sys v0.0.0-20190507160741-ecd444e8653b/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
+golang.org/x/sys v0.0.0-20190514135907-3a4b5fb9f71f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
+golang.org/x/sys v0.0.0-20190531175056-4c3a928424d2/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
+golang.org/x/sys v0.0.0-20190916202348-b4ddaad3f8a3/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
+golang.org/x/sys v0.0.0-20190922100055-0a153f010e69/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
+golang.org/x/sys v0.0.0-20190924154521-2837fb4f24fe/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
+golang.org/x/sys v0.0.0-20191008105621-543471e840be/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
+golang.org/x/sys v0.0.0-20191026070338-33540a1f6037/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
+golang.org/x/sys v0.0.0-20200116001909-b77594299b42/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
+golang.org/x/sys v0.0.0-20200122134326-e047566fdf82/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
+golang.org/x/sys v0.0.0-20200124204421-9fbb57f87de9/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
+golang.org/x/sys v0.0.0-20200223170610-d5e6a3e2c0ae/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
+golang.org/x/sys v0.0.0-20200302150141-5c8b2ff67527/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
+golang.org/x/sys v0.0.0-20200323222414-85ca7c5b95cd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
+golang.org/x/sys v0.0.0-20200602225109-6fdc65e7d980/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
+golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
+golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
+golang.org/x/sys v0.0.0-20201204225414-ed752295db88/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
+golang.org/x/sys v0.0.0-20210119212857-b64e53b001e4/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
+golang.org/x/sys v0.0.0-20210320140829-1e4c9ba3b0c4/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
+golang.org/x/sys v0.0.0-20210324051608-47abb6519492/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
+golang.org/x/sys v0.0.0-20210330210617-4fbd30eecc44/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
+golang.org/x/sys v0.0.0-20210420072515-93ed5bcd2bfe/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
+golang.org/x/sys v0.0.0-20210423082822-04245dca01da/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
+golang.org/x/sys v0.0.0-20210423185535-09eb48e85fd7/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
+golang.org/x/sys v0.0.0-20210502180810-71e4cd670f79/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
+golang.org/x/sys v0.0.0-20210510120138-977fb7262007/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
+golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
+golang.org/x/sys v0.0.0-20211216021012-1d35b9e2eb4e/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
+golang.org/x/sys v0.2.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
+golang.org/x/sys v0.7.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
+golang.org/x/sys v0.10.0 h1:SqMFp9UcQJZa+pmYuAKjd9xq1f0j5rLcDIk0mj4qAsA=
+golang.org/x/sys v0.10.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
+golang.org/x/term v0.0.0-20201117132131-f5c789dd3221/go.mod h1:Nr5EML6q2oocZ2LXRh80K7BxOlk5/8JxuGnuhpl+muw=
+golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
+golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8=
+golang.org/x/term v0.10.0 h1:3R7pNqamzBraeqj/Tj8qt1aQ2HpmlC+Cx/qL/7hn4/c=
+golang.org/x/term v0.10.0/go.mod h1:lpqdcUyK/oCiQxvxVrppt5ggO2KCZ5QblwqPnfZ6d5o=
+golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
+golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk=
+golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
+golang.org/x/text v0.3.5/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
+golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
+golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ=
+golang.org/x/text v0.11.0 h1:LAntKIrcmeSKERyiOh0XMV39LXS8IE9UL2yP7+f5ij4=
+golang.org/x/text v0.11.0/go.mod h1:TvPlkZtksWOMsz7fbANvkp4WM8x/WCo/om8BMLbz+aE=
+golang.org/x/time v0.0.0-20190308202827-9d24e82272b4/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
+golang.org/x/time v0.0.0-20200416051211-89c76fbcd5d1/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
+golang.org/x/time v0.0.0-20220210224613-90d013bbcef8 h1:vVKdlvoWBphwdxWKrFZEuM0kGgGLxUOYcY4U/2Vjg44=
+golang.org/x/time v0.0.0-20220210224613-90d013bbcef8/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
+golang.org/x/tools v0.0.0-20180221164845-07fd8470d635/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
+golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
+golang.org/x/tools v0.0.0-20181030221726-6c7e314b6563/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
+golang.org/x/tools v0.0.0-20190114222345-bf090417da8b/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
+golang.org/x/tools v0.0.0-20190226205152-f727befe758c/go.mod h1:9Yl7xja0Znq3iFh3HoIrodX9oNMXvdceNzlUR8zjMvY=
+golang.org/x/tools v0.0.0-20190311212946-11955173bddd/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs=
+golang.org/x/tools v0.0.0-20190312151545-0bb0c0a6e846/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs=
+golang.org/x/tools v0.0.0-20190329151228-23e29df326fe/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs=
+golang.org/x/tools v0.0.0-20190416151739-9c9e1878f421/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs=
+golang.org/x/tools v0.0.0-20190420181800-aa740d480789/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs=
+golang.org/x/tools v0.0.0-20190524140312-2c0ae7006135/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q=
+golang.org/x/tools v0.0.0-20190531172133-b3315ee88b7d/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc=
+golang.org/x/tools v0.0.0-20190624222133-a101b041ded4/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc=
+golang.org/x/tools v0.0.0-20190907020128-2ca718005c18/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
+golang.org/x/tools v0.0.0-20191012152004-8de300cfc20a/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
+golang.org/x/tools v0.0.0-20191029041327-9cc4af7d6b2c/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
+golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
+golang.org/x/tools v0.0.0-20200711155855-7342f9734a7d/go.mod h1:njjCfa9FT2d7l9Bc6FUM5FLjQPp3cFF28FI3qnDFljA=
+golang.org/x/tools v0.1.2/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk=
+golang.org/x/tools v0.6.0 h1:BOw41kyTf3PuCW1pVQf8+Cyg8pMlkYB1oo9iJ6D/lKM=
+golang.org/x/tools v0.6.0/go.mod h1:Xwgl3UAJ/d3gWutnCtw505GrjyAbvKui8lOU390QaIU=
+golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
+golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
+golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
+golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
+golang.org/x/xerrors v0.0.0-20220907171357-04be3eba64a2 h1:H2TDz8ibqkAF6YGhCdN3jS9O0/s90v0rJh3X/OLHEUk=
+golang.org/x/xerrors v0.0.0-20220907171357-04be3eba64a2/go.mod h1:K8+ghG5WaK9qNqU5K3HdILfMLy1f3aNYFI/wnl100a8=
+google.golang.org/api v0.101.0 h1:lJPPeEBIRxGpGLwnBTam1NPEM8Z2BmmXEd3z812pjwM=
+google.golang.org/api v0.101.0/go.mod h1:CjxAAWWt3A3VrUE2IGDY2bgK5qhoG/OkyWVlYcP05MY=
+google.golang.org/appengine v1.1.0/go.mod h1:EbEs0AVv82hx2wNQdGPgUI5lhzA/G0D9YwlJXL52JkM=
+google.golang.org/appengine v1.4.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4=
+google.golang.org/appengine v1.6.5/go.mod h1:8WjMMxjGQR8xUklV/ARdw2HLXBOI7O7uCIDZVag1xfc=
+google.golang.org/appengine v1.6.7 h1:FZR1q0exgwxzPzp/aF+VccGrSfxfPpkBqjIIEq3ru6c=
+google.golang.org/appengine v1.6.7/go.mod h1:8WjMMxjGQR8xUklV/ARdw2HLXBOI7O7uCIDZVag1xfc=
+google.golang.org/genproto v0.0.0-20180817151627-c66870c02cf8/go.mod h1:JiN7NxoALGmiZfu7CAH4rXhgtRTLTxftemlI0sWmxmc=
+google.golang.org/genproto v0.0.0-20190425155659-357c62f0e4bb/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE=
+google.golang.org/genproto v0.0.0-20190502173448-54afdca5d873/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE=
+google.golang.org/genproto v0.0.0-20190819201941-24fa4b261c55/go.mod h1:DMBHOl98Agz4BDEuKkezgsaosCRResVns1a3J2ZsMNc=
+google.golang.org/genproto v0.0.0-20200526211855-cb27e3aa2013/go.mod h1:NbSheEEYHJ7i3ixzK3sjbqSGDJWnxyFXZblF3eUsNvo=
+google.golang.org/genproto v0.0.0-20221027153422-115e99e71e1c h1:QgY/XxIAIeccR+Ca/rDdKubLIU9rcJ3xfy1DC/Wd2Oo=
+google.golang.org/genproto v0.0.0-20221027153422-115e99e71e1c/go.mod h1:CGI5F/G+E5bKwmfYo09AXuVN4dD894kIKUFmVbP2/Fo=
+google.golang.org/grpc v1.14.0/go.mod h1:yo6s7OP7yaDglbqo1J04qKzAhqBH6lvTonzMVmEdcZw=
+google.golang.org/grpc v1.19.0/go.mod h1:mqu4LbDTu4XGKhr4mRzUsmM4RtVoemTSY81AxZiDr8c=
+google.golang.org/grpc v1.20.1/go.mod h1:10oTOabMzJvdu6/UiuZezV6QK5dSlG84ov/aaiqXj38=
+google.golang.org/grpc v1.22.0/go.mod h1:Y5yQAOtifL1yxbo5wqy6BxZv8vAUGQwXBOALyacEbxg=
+google.golang.org/grpc v1.23.0/go.mod h1:Y5yQAOtifL1yxbo5wqy6BxZv8vAUGQwXBOALyacEbxg=
+google.golang.org/grpc v1.23.1/go.mod h1:Y5yQAOtifL1yxbo5wqy6BxZv8vAUGQwXBOALyacEbxg=
+google.golang.org/grpc v1.25.1/go.mod h1:c3i+UQWmh7LiEpx4sFZnkU36qjEYZ0imhYfXVyQciAY=
+google.golang.org/grpc v1.27.0/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8abTk=
+google.golang.org/grpc v1.29.1/go.mod h1:itym6AZVZYACWQqET3MqgPpjcuV5QH3BxFS3IjizoKk=
+google.golang.org/grpc v1.33.2/go.mod h1:JMHMWHQWaTccqQQlmk3MJZS+GWXOdAesneDmEnv2fbc=
+google.golang.org/grpc v1.50.1 h1:DS/BukOZWp8s6p4Dt/tOaJaTQyPyOoCcrjroHuCeLzY=
+google.golang.org/grpc v1.50.1/go.mod h1:ZgQEeidpAuNRZ8iRrlBKXZQP1ghovWIVhdJRyCDK+GI=
+google.golang.org/protobuf v0.0.0-20200109180630-ec00e32a8dfd/go.mod h1:DFci5gLYBciE7Vtevhsrf46CRTquxDuWsQurQQe4oz8=
+google.golang.org/protobuf v0.0.0-20200221191635-4d8936d0db64/go.mod h1:kwYJMbMJ01Woi6D6+Kah6886xMZcty6N08ah7+eCXa0=
+google.golang.org/protobuf v0.0.0-20200228230310-ab0ca4ff8a60/go.mod h1:cfTl7dwQJ+fmap5saPgwCLgHXTUD7jkjRqWcaiX5VyM=
+google.golang.org/protobuf v1.20.1-0.20200309200217-e05f789c0967/go.mod h1:A+miEFZTKqfCUM6K7xSMQL9OKL/b6hQv+e19PK+JZNE=
+google.golang.org/protobuf v1.21.0/go.mod h1:47Nbq4nVaFHyn7ilMalzfO3qCViNmqZ2kzikPIcrTAo=
+google.golang.org/protobuf v1.22.0/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU=
+google.golang.org/protobuf v1.23.0/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU=
+google.golang.org/protobuf v1.23.1-0.20200526195155-81db48ad09cc/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU=
+google.golang.org/protobuf v1.25.0/go.mod h1:9JNX74DMeImyA3h4bdi1ymwjUzf21/xIlbajtzgsN7c=
+google.golang.org/protobuf v1.26.0-rc.1/go.mod h1:jlhhOSvTdKEhbULTjvd4ARK9grFBp09yW+WbY/TyQbw=
+google.golang.org/protobuf v1.26.0/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc=
+google.golang.org/protobuf v1.28.1 h1:d0NfwRgPtno5B1Wa6L2DAG+KivqkdutMf1UhdNx175w=
+google.golang.org/protobuf v1.28.1/go.mod h1:HV8QOd/L58Z+nl8r43ehVNZIU/HEI6OcFqwMG9pJV4I=
+gopkg.in/airbrake/gobrake.v2 v2.0.9/go.mod h1:/h5ZAUhDkGaJfjzjKLSjv6zCL6O0LLBxU4K+aSYdM/U=
+gopkg.in/alecthomas/kingpin.v2 v2.2.6/go.mod h1:FMv+mEhP44yOT+4EoQTLFTRgOQ1FBLkstjWtayDeSgw=
+gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
+gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
+gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
+gopkg.in/check.v1 v1.0.0-20200227125254-8fa46927fb4f/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
+gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c h1:Hei/4ADfdWqJk1ZMxUNpqntNwaWcugrBjAiHlqqRiVk=
+gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c/go.mod h1:JHkPIbrfpd72SG/EVd6muEfDQjcINNoR0C8j2r3qZ4Q=
+gopkg.in/cheggaaa/pb.v1 v1.0.28 h1:n1tBJnnK2r7g9OW2btFH91V92STTUevLXYFb8gy9EMk=
+gopkg.in/cheggaaa/pb.v1 v1.0.28/go.mod h1:V/YB90LKu/1FcN3WVnfiiE5oMCibMjukxqG/qStrOgw=
+gopkg.in/errgo.v2 v2.1.0/go.mod h1:hNsd1EY+bozCKY1Ytp96fpM3vjJbqLJn88ws8XvfDNI=
+gopkg.in/fsnotify.v1 v1.4.7/go.mod h1:Tz8NjZHkW78fSQdbUxIjBTcgA1z1m8ZHf0WmKUhAMys=
+gopkg.in/gemnasium/logrus-airbrake-hook.v2 v2.1.2/go.mod h1:Xk6kEKp8OKb+X14hQBKWaSkCsqBpgog8nAV2xsGOxlo=
+gopkg.in/square/go-jose.v2 v2.3.1/go.mod h1:M9dMgbHiYLoDGQrXy7OpJDJWiKiU//h+vD76mk0e1AI=
+gopkg.in/square/go-jose.v2 v2.5.1/go.mod h1:M9dMgbHiYLoDGQrXy7OpJDJWiKiU//h+vD76mk0e1AI=
+gopkg.in/square/go-jose.v2 v2.6.0 h1:NGk74WTnPKBNUhNzQX7PYcTLUjoq7mzKk2OKbvwk2iI=
+gopkg.in/square/go-jose.v2 v2.6.0/go.mod h1:M9dMgbHiYLoDGQrXy7OpJDJWiKiU//h+vD76mk0e1AI=
+gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7/go.mod h1:dt/ZhP58zS4L8KSrWDmTeBkI65Dw0HsyUHuEVlX15mw=
+gopkg.in/warnings.v0 v0.1.2 h1:wFXVbFY8DY5/xOe1ECiWdKCzZlxgshcYVNkBHstARME=
+gopkg.in/warnings.v0 v0.1.2/go.mod h1:jksf8JmL6Qr/oQM2OXTHunEvvTAsrWBLb6OOjuVWRNI=
+gopkg.in/yaml.v2 v2.2.1/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
+gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
+gopkg.in/yaml.v2 v2.2.4/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
+gopkg.in/yaml.v2 v2.2.5/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
+gopkg.in/yaml.v2 v2.2.8/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
+gopkg.in/yaml.v2 v2.3.0/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
+gopkg.in/yaml.v2 v2.4.0 h1:D8xgwECY7CYvx+Y2n4sBz93Jn9JRvxdiyyo8CTfuKaY=
+gopkg.in/yaml.v2 v2.4.0/go.mod h1:RDklbk79AGWmwhnvt/jBztapEOGDOx6ZbXqjP6csGnQ=
+gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
+gopkg.in/yaml.v3 v3.0.0-20200605160147-a5ece683394c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
+gopkg.in/yaml.v3 v3.0.0-20200615113413-eeeca48fe776/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
+gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
+gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
+gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
+gotest.tools v2.2.0+incompatible/go.mod h1:DsYFclhRJ6vuDpmuTbkuFWG+y2sxOXAzmJt81HFBacw=
+gotest.tools/v3 v3.0.2/go.mod h1:3SzNCllyD9/Y+b5r9JIKQ474KzkZyqLqEfYqMsX94Bk=
+honnef.co/go/tools v0.0.0-20190102054323-c2f93a96b099/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
+honnef.co/go/tools v0.0.0-20190523083050-ea95bdfd59fc/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
diff --git a/v1.9.4/hcl2template/addrs/doc.go b/v1.9.4/hcl2template/addrs/doc.go
new file mode 100644
index 0000000..9768f45
--- /dev/null
+++ b/v1.9.4/hcl2template/addrs/doc.go
@@ -0,0 +1,14 @@
+// Copyright (c) HashiCorp, Inc.
+// SPDX-License-Identifier: MPL-2.0
+
+// Package addrs contains types that represent "addresses", which are
+// references to specific objects within a Packer configuration.
+//
+// All addresses have string representations based on HCL traversal syntax
+// which should be used in the user-interface, and also in-memory
+// representations that can be used internally.
+//
+// All types within this package should be treated as immutable, even if this
+// is not enforced by the Go compiler. It is always an implementation error
+// to modify an address object in-place after it is initially constructed.
+package addrs
diff --git a/v1.9.4/hcl2template/addrs/input_variable.go b/v1.9.4/hcl2template/addrs/input_variable.go
new file mode 100644
index 0000000..e2821e7
--- /dev/null
+++ b/v1.9.4/hcl2template/addrs/input_variable.go
@@ -0,0 +1,14 @@
+// Copyright (c) HashiCorp, Inc.
+// SPDX-License-Identifier: MPL-2.0
+
+package addrs
+
+// InputVariable is the address of an input variable.
+type InputVariable struct {
+ referenceable
+ Name string
+}
+
+func (v InputVariable) String() string {
+ return "var." + v.Name
+}
diff --git a/v1.9.4/hcl2template/addrs/parse_ref.go b/v1.9.4/hcl2template/addrs/parse_ref.go
new file mode 100644
index 0000000..866ced8
--- /dev/null
+++ b/v1.9.4/hcl2template/addrs/parse_ref.go
@@ -0,0 +1,96 @@
+// Copyright (c) HashiCorp, Inc.
+// SPDX-License-Identifier: MPL-2.0
+
+package addrs
+
+import (
+ "fmt"
+
+ "github.com/hashicorp/hcl/v2"
+)
+
+// Reference describes a reference to an address with source location
+// information.
+type Reference struct {
+ Subject Referenceable
+ SourceRange hcl.Range
+ Remaining hcl.Traversal
+}
+
+// ParseRef attempts to extract a referencable address from the prefix of the
+// given traversal, which must be an absolute traversal or this function
+// will panic.
+//
+// If no error diagnostics are returned, the returned reference includes the
+// address that was extracted, the source range it was extracted from, and any
+// remaining relative traversal that was not consumed as part of the
+// reference.
+//
+// If error diagnostics are returned then the Reference value is invalid and
+// must not be used.
+func ParseRef(traversal hcl.Traversal) (*Reference, hcl.Diagnostics) {
+ ref, diags := parseRef(traversal)
+
+ // Normalize a little to make life easier for callers.
+ if ref != nil {
+ if len(ref.Remaining) == 0 {
+ ref.Remaining = nil
+ }
+ }
+
+ return ref, diags
+}
+
+func parseRef(traversal hcl.Traversal) (*Reference, hcl.Diagnostics) {
+ var diags hcl.Diagnostics
+
+ root := traversal.RootName()
+ rootRange := traversal[0].SourceRange()
+
+ switch root {
+
+ case "var":
+ name, rng, remain, diags := parseSingleAttrRef(traversal)
+ return &Reference{
+ Subject: InputVariable{Name: name},
+ SourceRange: rng,
+ Remaining: remain,
+ }, diags
+
+ default:
+ diags = append(diags, &hcl.Diagnostic{
+ Severity: hcl.DiagError,
+ Summary: "Unhandled reference type",
+ Detail: `Currently parseRef can only parse "var" references.`,
+ Subject: &rootRange,
+ })
+ }
+ return nil, diags
+}
+
+func parseSingleAttrRef(traversal hcl.Traversal) (string, hcl.Range, hcl.Traversal, hcl.Diagnostics) {
+ var diags hcl.Diagnostics
+
+ root := traversal.RootName()
+ rootRange := traversal[0].SourceRange()
+
+ if len(traversal) < 2 {
+ diags = append(diags, &hcl.Diagnostic{
+ Severity: hcl.DiagError,
+ Summary: "Invalid reference",
+ Detail: fmt.Sprintf("The %q object cannot be accessed directly. Instead, access one of its attributes.", root),
+ Subject: &rootRange,
+ })
+ return "", hcl.Range{}, nil, diags
+ }
+ if attrTrav, ok := traversal[1].(hcl.TraverseAttr); ok {
+ return attrTrav.Name, hcl.RangeBetween(rootRange, attrTrav.SrcRange), traversal[2:], diags
+ }
+ diags = diags.Append(&hcl.Diagnostic{
+ Severity: hcl.DiagError,
+ Summary: "Invalid reference",
+ Detail: fmt.Sprintf("The %q object does not support this operation.", root),
+ Subject: traversal[1].SourceRange().Ptr(),
+ })
+ return "", hcl.Range{}, nil, diags
+}
diff --git a/v1.9.4/hcl2template/addrs/plugin.go b/v1.9.4/hcl2template/addrs/plugin.go
new file mode 100644
index 0000000..8b48910
--- /dev/null
+++ b/v1.9.4/hcl2template/addrs/plugin.go
@@ -0,0 +1,212 @@
+// Copyright (c) HashiCorp, Inc.
+// SPDX-License-Identifier: MPL-2.0
+
+package addrs
+
+import (
+ "fmt"
+ "strings"
+
+ "github.com/hashicorp/hcl/v2"
+ "golang.org/x/net/idna"
+)
+
+// Plugin encapsulates a single plugin type.
+type Plugin struct {
+ Hostname string
+ Namespace string
+ Type string
+}
+
+func (p Plugin) RealRelativePath() string {
+ return p.Namespace + "/packer-plugin-" + p.Type
+}
+
+func (p Plugin) Parts() []string {
+ return []string{p.Hostname, p.Namespace, p.Type}
+}
+
+func (p Plugin) String() string {
+ return strings.Join(p.Parts(), "/")
+}
+
+// ParsePluginPart processes an addrs.Plugin namespace or type string
+// provided by an end-user, producing a normalized version if possible or
+// an error if the string contains invalid characters.
+//
+// A plugin part is processed in the same way as an individual label in a DNS
+// domain name: it is transformed to lowercase per the usual DNS case mapping
+// and normalization rules and may contain only letters, digits, and dashes.
+// Additionally, dashes may not appear at the start or end of the string.
+//
+// These restrictions are intended to allow these names to appear in fussy
+// contexts such as directory/file names on case-insensitive filesystems,
+// repository names on GitHub, etc. We're using the DNS rules in particular,
+// rather than some similar rules defined locally, because the hostname part
+// of an addrs.Plugin is already a hostname and it's ideal to use exactly
+// the same case folding and normalization rules for all of the parts.
+//
+// It's valid to pass the result of this function as the argument to a
+// subsequent call, in which case the result will be identical.
+func ParsePluginPart(given string) (string, error) {
+ if len(given) == 0 {
+ return "", fmt.Errorf("must have at least one character")
+ }
+
+ // We're going to process the given name using the same "IDNA" library we
+ // use for the hostname portion, since it already implements the case
+ // folding rules we want.
+ //
+ // The idna library doesn't expose individual label parsing directly, but
+ // once we've verified it doesn't contain any dots we can just treat it
+ // like a top-level domain for this library's purposes.
+ if strings.ContainsRune(given, '.') {
+ return "", fmt.Errorf("dots are not allowed")
+ }
+
+ // We don't allow names containing multiple consecutive dashes, just as
+ // a matter of preference: they look confusing, or incorrect.
+ // This also, as a side-effect, prevents the use of the "punycode"
+ // indicator prefix "xn--" that would cause the IDNA library to interpret
+ // the given name as punycode, because that would be weird and unexpected.
+ if strings.Contains(given, "--") {
+ return "", fmt.Errorf("cannot use multiple consecutive dashes")
+ }
+
+ result, err := idna.Lookup.ToUnicode(given)
+ if err != nil {
+ return "", fmt.Errorf("must contain only letters, digits, and dashes, and may not use leading or trailing dashes: %w", err)
+ }
+
+ return result, nil
+}
+
+// IsPluginPartNormalized compares a given string to the result of ParsePluginPart(string)
+func IsPluginPartNormalized(str string) (bool, error) {
+ normalized, err := ParsePluginPart(str)
+ if err != nil {
+ return false, err
+ }
+ if str == normalized {
+ return true, nil
+ }
+ return false, nil
+}
+
+// ParsePluginSourceString parses the source attribute and returns a plugin.
+// This is intended primarily to parse the FQN-like strings
+//
+// The following are valid source string formats:
+//
+// name
+// namespace/name
+// hostname/namespace/name
+func ParsePluginSourceString(str string) (*Plugin, hcl.Diagnostics) {
+ ret := &Plugin{
+ Hostname: "",
+ Namespace: "",
+ }
+ var diags hcl.Diagnostics
+
+ // split the source string into individual components
+ parts := strings.Split(str, "/")
+ if len(parts) != 3 {
+ diags = diags.Append(&hcl.Diagnostic{
+ Severity: hcl.DiagError,
+ Summary: "Invalid plugin source string",
+ Detail: `The "source" attribute must be in the format "hostname/namespace/name"`,
+ })
+ return nil, diags
+ }
+
+ // check for an invalid empty string in any part
+ for i := range parts {
+ if parts[i] == "" {
+ diags = diags.Append(&hcl.Diagnostic{
+ Severity: hcl.DiagError,
+ Summary: "Invalid plugin source string",
+ Detail: `The "source" attribute must be in the format "hostname/namespace/name"`,
+ })
+ return nil, diags
+ }
+ }
+
+ // check the 'name' portion, which is always the last part
+ givenName := parts[len(parts)-1]
+ name, err := ParsePluginPart(givenName)
+ if err != nil {
+ diags = diags.Append(&hcl.Diagnostic{
+ Severity: hcl.DiagError,
+ Summary: "Invalid plugin type",
+ Detail: fmt.Sprintf(`Invalid plugin type %q in source %q: %s"`, givenName, str, err),
+ })
+ return nil, diags
+ }
+ ret.Type = name
+
+ // the namespace is always the second-to-last part
+ givenNamespace := parts[len(parts)-2]
+ namespace, err := ParsePluginPart(givenNamespace)
+ if err != nil {
+ diags = diags.Append(&hcl.Diagnostic{
+ Severity: hcl.DiagError,
+ Summary: "Invalid plugin namespace",
+ Detail: fmt.Sprintf(`Invalid plugin namespace %q in source %q: %s"`, namespace, str, err),
+ })
+ return nil, diags
+ }
+ ret.Namespace = namespace
+
+ // the hostname is always the first part in a three-part source string
+ ret.Hostname = parts[0]
+
+ // Due to how plugin executables are named and plugin git repositories
+ // are conventionally named, it's a reasonable and
+ // apparently-somewhat-common user error to incorrectly use the
+ // "packer-plugin-" prefix in a plugin source address. There is
+ // no good reason for a plugin to have the prefix "packer-" anyway,
+ // so we've made that invalid from the start both so we can give feedback
+ // to plugin developers about the packer- prefix being redundant
+ // and give specialized feedback to folks who incorrectly use the full
+ // packer-plugin- prefix to help them self-correct.
+ const redundantPrefix = "packer-"
+ const userErrorPrefix = "packer-plugin-"
+ if strings.HasPrefix(ret.Type, redundantPrefix) {
+ if strings.HasPrefix(ret.Type, userErrorPrefix) {
+ // Likely user error. We only return this specialized error if
+ // whatever is after the prefix would otherwise be a
+ // syntactically-valid plugin type, so we don't end up advising
+ // the user to try something that would be invalid for another
+ // reason anyway.
+ // (This is mainly just for robustness, because the validation
+ // we already did above should've rejected most/all ways for
+ // the suggestedType to end up invalid here.)
+ suggestedType := ret.Type[len(userErrorPrefix):]
+ if _, err := ParsePluginPart(suggestedType); err == nil {
+ suggestedAddr := ret
+ suggestedAddr.Type = suggestedType
+ diags = diags.Append(&hcl.Diagnostic{
+ Severity: hcl.DiagError,
+ Summary: "Invalid plugin type",
+ Detail: fmt.Sprintf("Plugin source %q has a type with the prefix %q, which isn't valid. "+
+ "Although that prefix is often used in the names of version control repositories for Packer plugins, "+
+ "plugin source strings should not include it.\n"+
+ "\nDid you mean %q?", ret, userErrorPrefix, suggestedAddr),
+ })
+ return nil, diags
+ }
+ }
+ // Otherwise, probably instead an incorrectly-named plugin, perhaps
+ // arising from a similar instinct to what causes there to be
+ // thousands of Python packages on PyPI with "python-"-prefixed
+ // names.
+ diags = diags.Append(&hcl.Diagnostic{
+ Severity: hcl.DiagError,
+ Summary: "Invalid plugin type",
+ Detail: fmt.Sprintf("Plugin source %q has a type with the prefix %q, which isn't allowed because it would be redundant to name a Packer plugin with that prefix. If you are the author of this plugin, rename it to not include the prefix.", ret, redundantPrefix),
+ })
+ return nil, diags
+ }
+
+ return ret, diags
+}
diff --git a/v1.9.4/hcl2template/addrs/plugin_test.go b/v1.9.4/hcl2template/addrs/plugin_test.go
new file mode 100644
index 0000000..491d222
--- /dev/null
+++ b/v1.9.4/hcl2template/addrs/plugin_test.go
@@ -0,0 +1,35 @@
+// Copyright (c) HashiCorp, Inc.
+// SPDX-License-Identifier: MPL-2.0
+
+package addrs
+
+import (
+ "reflect"
+ "testing"
+)
+
+func TestParsePluginSourceString(t *testing.T) {
+ type args struct {
+ str string
+ }
+ tests := []struct {
+ args args
+ want *Plugin
+ wantDiags bool
+ }{
+ {args{"potato"}, nil, true},
+ {args{"hashicorp/azr"}, nil, true},
+ {args{"github.com/hashicorp/azr"}, &Plugin{"github.com", "hashicorp", "azr"}, false},
+ }
+ for _, tt := range tests {
+ t.Run(tt.args.str, func(t *testing.T) {
+ got, gotDiags := ParsePluginSourceString(tt.args.str)
+ if !reflect.DeepEqual(got, tt.want) {
+ t.Errorf("ParsePluginSourceString() got = %v, want %v", got, tt.want)
+ }
+ if tt.wantDiags == (len(gotDiags) == 0) {
+ t.Errorf("Unexpected diags %s", gotDiags)
+ }
+ })
+ }
+}
diff --git a/v1.9.4/hcl2template/addrs/referenceable.go b/v1.9.4/hcl2template/addrs/referenceable.go
new file mode 100644
index 0000000..9b54c5b
--- /dev/null
+++ b/v1.9.4/hcl2template/addrs/referenceable.go
@@ -0,0 +1,25 @@
+// Copyright (c) HashiCorp, Inc.
+// SPDX-License-Identifier: MPL-2.0
+
+package addrs
+
+// Referenceable is an interface implemented by all address types that can
+// appear as references in configuration language expressions.
+type Referenceable interface {
+ // referenceableSigil is private to ensure that all Referenceables are
+ // implentented in this current package. For now this does nothing.
+ referenceableSigil()
+
+ // String produces a string representation of the address that could be
+ // parsed as a HCL traversal and passed to ParseRef to produce an identical
+ // result.
+ String() string
+}
+
+// referenceable is an empty struct that implements Referenceable, add it to
+// your Referenceable struct so that it can be recognized as such.
+type referenceable struct {
+}
+
+func (r referenceable) referenceableSigil() {
+}
diff --git a/v1.9.4/hcl2template/common_test.go b/v1.9.4/hcl2template/common_test.go
new file mode 100644
index 0000000..cb37a7b
--- /dev/null
+++ b/v1.9.4/hcl2template/common_test.go
@@ -0,0 +1,386 @@
+// Copyright (c) HashiCorp, Inc.
+// SPDX-License-Identifier: MPL-2.0
+
+package hcl2template
+
+import (
+ "testing"
+ "time"
+
+ "github.com/google/go-cmp/cmp"
+ "github.com/google/go-cmp/cmp/cmpopts"
+ "github.com/hashicorp/go-version"
+ "github.com/hashicorp/hcl/v2"
+ "github.com/hashicorp/hcl/v2/hclparse"
+ packersdk "github.com/hashicorp/packer-plugin-sdk/packer"
+ "github.com/hashicorp/packer-plugin-sdk/template/config"
+ "github.com/hashicorp/packer/builder/null"
+ dnull "github.com/hashicorp/packer/datasource/null"
+ . "github.com/hashicorp/packer/hcl2template/internal"
+ hcl2template "github.com/hashicorp/packer/hcl2template/internal"
+ "github.com/hashicorp/packer/packer"
+ "github.com/zclconf/go-cty/cty"
+)
+
+const lockedVersion = "v1.5.0"
+
+func getBasicParser(opts ...getParserOption) *Parser {
+ parser := &Parser{
+ CorePackerVersion: version.Must(version.NewSemver(lockedVersion)),
+ CorePackerVersionString: lockedVersion,
+ Parser: hclparse.NewParser(),
+ PluginConfig: &packer.PluginConfig{
+ Builders: packer.MapOfBuilder{
+ "amazon-ebs": func() (packersdk.Builder, error) { return &MockBuilder{}, nil },
+ "virtualbox-iso": func() (packersdk.Builder, error) { return &MockBuilder{}, nil },
+ "null": func() (packersdk.Builder, error) { return &null.Builder{}, nil },
+ },
+ Provisioners: packer.MapOfProvisioner{
+ "shell": func() (packersdk.Provisioner, error) { return &MockProvisioner{}, nil },
+ "file": func() (packersdk.Provisioner, error) { return &MockProvisioner{}, nil },
+ },
+ PostProcessors: packer.MapOfPostProcessor{
+ "amazon-import": func() (packersdk.PostProcessor, error) { return &MockPostProcessor{}, nil },
+ "manifest": func() (packersdk.PostProcessor, error) { return &MockPostProcessor{}, nil },
+ },
+ DataSources: packer.MapOfDatasource{
+ "amazon-ami": func() (packersdk.Datasource, error) { return &MockDatasource{}, nil },
+ "null": func() (packersdk.Datasource, error) { return &dnull.Datasource{}, nil },
+ },
+ },
+ }
+ for _, configure := range opts {
+ configure(parser)
+ }
+ return parser
+}
+
+type getParserOption func(*Parser)
+
+type parseTestArgs struct {
+ filename string
+ vars map[string]string
+ varFiles []string
+}
+
+type parseTest struct {
+ name string
+ parser *Parser
+ args parseTestArgs
+
+ parseWantCfg *PackerConfig
+ parseWantDiags bool
+ parseWantDiagHasErrors bool
+
+ getBuildsWantBuilds []packersdk.Build
+ getBuildsWantDiags bool
+ // getBuildsWantDiagHasErrors bool
+}
+
+func testParse(t *testing.T, tests []parseTest) {
+ t.Helper()
+
+ for _, tt := range tests {
+ t.Run(tt.name, func(t *testing.T) {
+ gotCfg, gotDiags := tt.parser.Parse(tt.args.filename, tt.args.varFiles, tt.args.vars)
+ moreDiags := gotCfg.Initialize(packer.InitializeOptions{})
+ gotDiags = append(gotDiags, moreDiags...)
+ if tt.parseWantDiags == (gotDiags == nil) {
+ t.Fatalf("Parser.parse() unexpected %q diagnostics.", gotDiags)
+ }
+ if tt.parseWantDiagHasErrors != gotDiags.HasErrors() {
+ t.Fatalf("Parser.parse() unexpected diagnostics HasErrors. %s", gotDiags)
+ }
+ if diff := cmp.Diff(tt.parseWantCfg, gotCfg, cmpOpts...); diff != "" {
+ t.Fatalf("Parser.parse() wrong packer config. %s", diff)
+ }
+
+ if gotCfg != nil && !tt.parseWantDiagHasErrors {
+ if diff := cmp.Diff(tt.parseWantCfg.InputVariables, gotCfg.InputVariables, cmpOpts...); diff != "" {
+ t.Fatalf("Parser.parse() unexpected input vars. %s", diff)
+ }
+
+ if diff := cmp.Diff(tt.parseWantCfg.LocalVariables, gotCfg.LocalVariables, cmpOpts...); diff != "" {
+ t.Fatalf("Parser.parse() unexpected local vars. %s", diff)
+ }
+ }
+
+ if gotDiags.HasErrors() {
+ return
+ }
+
+ gotBuilds, gotDiags := gotCfg.GetBuilds(packer.GetBuildsOptions{})
+ if tt.getBuildsWantDiags == (gotDiags == nil) {
+ t.Fatalf("Parser.getBuilds() unexpected diagnostics. %s", gotDiags)
+ }
+ if diff := cmp.Diff(tt.getBuildsWantBuilds, gotBuilds, cmpOpts...); diff != "" {
+ t.Fatalf("Parser.getBuilds() wrong packer builds. %s", diff)
+ }
+ })
+ }
+}
+
+func testParse_only_Parse(t *testing.T, tests []parseTest) {
+ t.Helper()
+
+ for _, tt := range tests {
+ t.Run(tt.name, func(t *testing.T) {
+ gotCfg, gotDiags := tt.parser.Parse(tt.args.filename, tt.args.varFiles, tt.args.vars)
+ if tt.parseWantDiags == (gotDiags == nil) {
+ t.Fatalf("Parser.parse() unexpected %q diagnostics.", gotDiags)
+ }
+ if tt.parseWantDiagHasErrors != gotDiags.HasErrors() {
+ t.Fatalf("Parser.parse() unexpected diagnostics HasErrors. %s", gotDiags)
+ }
+ if diff := cmp.Diff(tt.parseWantCfg, gotCfg, cmpOpts...); diff != "" {
+ t.Fatalf("Parser.parse() wrong packer config. %s", diff)
+ }
+
+ if gotCfg != nil && !tt.parseWantDiagHasErrors {
+ if diff := cmp.Diff(tt.parseWantCfg.InputVariables, gotCfg.InputVariables, cmpOpts...); diff != "" {
+ t.Fatalf("Parser.parse() unexpected input vars. %s", diff)
+ }
+
+ if diff := cmp.Diff(tt.parseWantCfg.LocalVariables, gotCfg.LocalVariables, cmpOpts...); diff != "" {
+ t.Fatalf("Parser.parse() unexpected local vars. %s", diff)
+ }
+ }
+
+ if gotDiags.HasErrors() {
+ return
+ }
+ })
+ }
+}
+
+var (
+ // everything in the tests is a basicNestedMockConfig this allow to test
+ // each known type to packer ( and embedding ) in one go.
+ basicNestedMockConfig = NestedMockConfig{
+ String: "string",
+ Int: 42,
+ Int64: 43,
+ Bool: true,
+ Trilean: config.TriTrue,
+ Duration: 10 * time.Second,
+ MapStringString: map[string]string{
+ "a": "b",
+ "c": "d",
+ },
+ SliceString: []string{
+ "a",
+ "b",
+ "c",
+ },
+ SliceSliceString: [][]string{
+ {"a", "b"},
+ {"c", "d"},
+ },
+ Tags: []MockTag{},
+ }
+
+ // everything in the tests is a basicNestedMockConfig this allow to test
+ // each known type to packer ( and embedding ) in one go.
+ builderBasicNestedMockConfig = NestedMockConfig{
+ String: "string",
+ Int: 42,
+ Int64: 43,
+ Bool: true,
+ Trilean: config.TriTrue,
+ Duration: 10 * time.Second,
+ MapStringString: map[string]string{
+ "a": "b",
+ "c": "d",
+ },
+ SliceString: []string{
+ "a",
+ "b",
+ "c",
+ },
+ SliceSliceString: [][]string{
+ {"a", "b"},
+ {"c", "d"},
+ },
+ Tags: []MockTag{},
+ Datasource: "string",
+ }
+
+ basicMockBuilder = &MockBuilder{
+ Config: MockConfig{
+ NestedMockConfig: builderBasicNestedMockConfig,
+ Nested: builderBasicNestedMockConfig,
+ NestedSlice: []NestedMockConfig{
+ builderBasicNestedMockConfig,
+ builderBasicNestedMockConfig,
+ },
+ },
+ }
+
+ basicMockProvisioner = &MockProvisioner{
+ Config: MockConfig{
+ NotSquashed: "value <UNKNOWN>",
+ NestedMockConfig: basicNestedMockConfig,
+ Nested: basicNestedMockConfig,
+ NestedSlice: []NestedMockConfig{
+ {
+ Tags: dynamicTagList,
+ },
+ },
+ },
+ }
+ basicMockPostProcessor = &MockPostProcessor{
+ Config: MockConfig{
+ NotSquashed: "value <UNKNOWN>",
+ NestedMockConfig: basicNestedMockConfig,
+ Nested: basicNestedMockConfig,
+ NestedSlice: []NestedMockConfig{
+ {
+ Tags: []MockTag{},
+ },
+ },
+ },
+ }
+ basicMockPostProcessorDynamicTags = &MockPostProcessor{
+ Config: MockConfig{
+ NotSquashed: "value <UNKNOWN>",
+ NestedMockConfig: NestedMockConfig{
+ String: "string",
+ Int: 42,
+ Int64: 43,
+ Bool: true,
+ Trilean: config.TriTrue,
+ Duration: 10 * time.Second,
+ MapStringString: map[string]string{
+ "a": "b",
+ "c": "d",
+ },
+ SliceString: []string{
+ "a",
+ "b",
+ "c",
+ },
+ SliceSliceString: [][]string{
+ {"a", "b"},
+ {"c", "d"},
+ },
+ Tags: []MockTag{
+ {Key: "first_tag_key", Value: "first_tag_value"},
+ {Key: "Component", Value: "user-service"},
+ {Key: "Environment", Value: "production"},
+ },
+ },
+ Nested: basicNestedMockConfig,
+ NestedSlice: []NestedMockConfig{},
+ },
+ }
+ basicMockCommunicator = &MockCommunicator{
+ Config: MockConfig{
+ NestedMockConfig: basicNestedMockConfig,
+ Nested: basicNestedMockConfig,
+ NestedSlice: []NestedMockConfig{
+ {
+ Tags: []MockTag{},
+ },
+ },
+ },
+ }
+
+ emptyMockBuilder = &MockBuilder{
+ Config: MockConfig{
+ NestedMockConfig: NestedMockConfig{
+ Tags: []MockTag{},
+ },
+ Nested: NestedMockConfig{},
+ NestedSlice: []NestedMockConfig{},
+ },
+ }
+
+ emptyMockProvisioner = &MockProvisioner{
+ Config: MockConfig{
+ NestedMockConfig: NestedMockConfig{Tags: []MockTag{}},
+ NestedSlice: []NestedMockConfig{},
+ },
+ }
+
+ dynamicTagList = []MockTag{
+ {
+ Key: "first_tag_key",
+ Value: "first_tag_value",
+ },
+ {
+ Key: "Component",
+ Value: "user-service",
+ },
+ {
+ Key: "Environment",
+ Value: "production",
+ },
+ }
+)
+
+var ctyValueComparer = cmp.Comparer(func(x, y cty.Value) bool {
+ return x.RawEquals(y)
+})
+
+var ctyTypeComparer = cmp.Comparer(func(x, y cty.Type) bool {
+ if x == cty.NilType && y == cty.NilType {
+ return true
+ }
+ if x == cty.NilType || y == cty.NilType {
+ return false
+ }
+ return x.Equals(y)
+})
+
+var versionComparer = cmp.Comparer(func(x, y *version.Version) bool {
+ return x.Equal(y)
+})
+
+var versionConstraintComparer = cmp.Comparer(func(x, y *version.Constraint) bool {
+ return x.String() == y.String()
+})
+
+var cmpOpts = []cmp.Option{
+ ctyValueComparer,
+ ctyTypeComparer,
+ versionComparer,
+ versionConstraintComparer,
+ cmpopts.IgnoreUnexported(
+ PackerConfig{},
+ Variable{},
+ SourceBlock{},
+ DatasourceBlock{},
+ ProvisionerBlock{},
+ PostProcessorBlock{},
+ packer.CoreBuild{},
+ HCL2Provisioner{},
+ HCL2PostProcessor{},
+ packer.CoreBuildPostProcessor{},
+ packer.CoreBuildProvisioner{},
+ packer.CoreBuildPostProcessor{},
+ null.Builder{},
+ ),
+ cmpopts.IgnoreFields(PackerConfig{},
+ "Cwd", // Cwd will change for every os type
+ "HCPVars", // HCPVars will not be filled-in during parsing
+ ),
+ cmpopts.IgnoreFields(VariableAssignment{},
+ "Expr", // its an interface
+ ),
+ cmpopts.IgnoreFields(packer.CoreBuild{},
+ "HCLConfig",
+ ),
+ cmpopts.IgnoreFields(packer.CoreBuildProvisioner{},
+ "HCLConfig",
+ ),
+ cmpopts.IgnoreFields(packer.CoreBuildPostProcessor{},
+ "HCLConfig",
+ ),
+ cmpopts.IgnoreTypes(hcl2template.MockBuilder{}),
+ cmpopts.IgnoreTypes(HCL2Ref{}),
+ cmpopts.IgnoreTypes([]*LocalBlock{}),
+ cmpopts.IgnoreTypes([]hcl.Range{}),
+ cmpopts.IgnoreTypes(hcl.Range{}),
+ cmpopts.IgnoreInterfaces(struct{ hcl.Expression }{}),
+ cmpopts.IgnoreInterfaces(struct{ hcl.Body }{}),
+}
diff --git a/v1.9.4/hcl2template/components.go b/v1.9.4/hcl2template/components.go
new file mode 100644
index 0000000..956a753
--- /dev/null
+++ b/v1.9.4/hcl2template/components.go
@@ -0,0 +1,14 @@
+// Copyright (c) HashiCorp, Inc.
+// SPDX-License-Identifier: MPL-2.0
+
+package hcl2template
+
+// ComponentKind helps enumerate what kind of components exist in this Package.
+type ComponentKind int
+
+const (
+ Builder ComponentKind = iota
+ Provisioner
+ PostProcessor
+ Datasource
+)
diff --git a/v1.9.4/hcl2template/decode.go b/v1.9.4/hcl2template/decode.go
new file mode 100644
index 0000000..137e54e
--- /dev/null
+++ b/v1.9.4/hcl2template/decode.go
@@ -0,0 +1,21 @@
+// Copyright (c) HashiCorp, Inc.
+// SPDX-License-Identifier: MPL-2.0
+
+package hcl2template
+
+import (
+ "github.com/hashicorp/hcl/v2"
+ "github.com/hashicorp/hcl/v2/hcldec"
+ "github.com/zclconf/go-cty/cty"
+)
+
+// Decodable structs are structs that can tell their hcl2 ObjectSpec; this
+// config spec will be passed to hcldec.Decode and the result will be a
+// cty.Value. This Value can then be applied on the said struct.
+type Decodable interface {
+ ConfigSpec() hcldec.ObjectSpec
+}
+
+func decodeHCL2Spec(body hcl.Body, ectx *hcl.EvalContext, dec Decodable) (cty.Value, hcl.Diagnostics) {
+ return hcldec.Decode(body, dec.ConfigSpec(), ectx)
+}
diff --git a/v1.9.4/hcl2template/docs.go b/v1.9.4/hcl2template/docs.go
new file mode 100644
index 0000000..2b19f42
--- /dev/null
+++ b/v1.9.4/hcl2template/docs.go
@@ -0,0 +1,10 @@
+// Copyright (c) HashiCorp, Inc.
+// SPDX-License-Identifier: MPL-2.0
+
+// Package hcl2template defines code to parse hcl2 template files.
+//
+// In order to configure a packer builder,provisioner, and post processor.
+//
+// Checkout the files in testdata/complete/ to see what a packer config could
+// look like.
+package hcl2template
diff --git a/v1.9.4/hcl2template/fixtures/malformed_override.pkr.hcl b/v1.9.4/hcl2template/fixtures/malformed_override.pkr.hcl
new file mode 100644
index 0000000..753eefe
--- /dev/null
+++ b/v1.9.4/hcl2template/fixtures/malformed_override.pkr.hcl
@@ -0,0 +1,4 @@
+provisioner "shell-local" {
+ inline = ["echo 'hi'"]
+ override = "hello"
+}
diff --git a/v1.9.4/hcl2template/fixtures/malformed_override_innards.pkr.hcl b/v1.9.4/hcl2template/fixtures/malformed_override_innards.pkr.hcl
new file mode 100644
index 0000000..cd44f13
--- /dev/null
+++ b/v1.9.4/hcl2template/fixtures/malformed_override_innards.pkr.hcl
@@ -0,0 +1,6 @@
+provisioner "shell-local" {
+ inline = ["echo 'hi'"]
+ override = {
+ test = "hello"
+ }
+}
diff --git a/v1.9.4/hcl2template/fixtures/well_formed_provisioner.pkr.hcl b/v1.9.4/hcl2template/fixtures/well_formed_provisioner.pkr.hcl
new file mode 100644
index 0000000..b70bd15
--- /dev/null
+++ b/v1.9.4/hcl2template/fixtures/well_formed_provisioner.pkr.hcl
@@ -0,0 +1,9 @@
+provisioner "shell-local" {
+ inline = ["echo 'hi'"]
+ override = {
+ test = {
+ "hello" = "new value"
+ }
+ }
+}
+
diff --git a/v1.9.4/hcl2template/formatter.go b/v1.9.4/hcl2template/formatter.go
new file mode 100644
index 0000000..7e1cab5
--- /dev/null
+++ b/v1.9.4/hcl2template/formatter.go
@@ -0,0 +1,205 @@
+// Copyright (c) HashiCorp, Inc.
+// SPDX-License-Identifier: MPL-2.0
+
+package hcl2template
+
+import (
+ "bytes"
+ "fmt"
+ "io"
+ "io/ioutil"
+ "os"
+ "os/exec"
+ "path/filepath"
+ "strings"
+
+ "github.com/hashicorp/hcl/v2"
+ "github.com/hashicorp/hcl/v2/hclparse"
+ "github.com/hashicorp/hcl/v2/hclwrite"
+)
+
+type HCL2Formatter struct {
+ ShowDiff, Write, Recursive bool
+ Output io.Writer
+ parser *hclparse.Parser
+}
+
+// NewHCL2Formatter creates a new formatter, ready to format configuration files.
+func NewHCL2Formatter() *HCL2Formatter {
+ return &HCL2Formatter{
+ parser: hclparse.NewParser(),
+ }
+}
+
+func isHcl2FileOrVarFile(path string) bool {
+ if strings.HasSuffix(path, hcl2FileExt) || strings.HasSuffix(path, hcl2VarFileExt) {
+ return true
+ }
+ return false
+}
+
+func (f *HCL2Formatter) formatFile(path string, diags hcl.Diagnostics, bytesModified int) (int, hcl.Diagnostics) {
+ data, err := f.processFile(path)
+ if err != nil {
+ diags = append(diags, &hcl.Diagnostic{
+ Severity: hcl.DiagError,
+ Summary: fmt.Sprintf("encountered an error while formatting %s", path),
+ Detail: err.Error(),
+ })
+ }
+ bytesModified += len(data)
+ return bytesModified, diags
+}
+
+// Format all HCL2 files in path and return the total bytes formatted.
+// If any error is encountered, zero bytes will be returned.
+//
+// Path can be a directory or a file.
+func (f *HCL2Formatter) Format(path string) (int, hcl.Diagnostics) {
+ var diags hcl.Diagnostics
+ var bytesModified int
+
+ if path == "" {
+ diags = append(diags, &hcl.Diagnostic{
+ Severity: hcl.DiagError,
+ Summary: "path is empty, cannot format",
+ Detail: "path is empty, cannot format",
+ })
+ return bytesModified, diags
+ }
+
+ if f.parser == nil {
+ f.parser = hclparse.NewParser()
+ }
+
+ if s, err := os.Stat(path); err != nil || !s.IsDir() {
+ return f.formatFile(path, diags, bytesModified)
+ }
+
+ fileInfos, err := ioutil.ReadDir(path)
+ if err != nil {
+ diag := &hcl.Diagnostic{
+ Severity: hcl.DiagError,
+ Summary: "Cannot read hcl directory",
+ Detail: err.Error(),
+ }
+ diags = append(diags, diag)
+ return bytesModified, diags
+ }
+
+ for _, fileInfo := range fileInfos {
+ filename := filepath.Join(path, fileInfo.Name())
+ if fileInfo.IsDir() {
+ if f.Recursive {
+ var tempDiags hcl.Diagnostics
+ var tempBytesModified int
+ tempBytesModified, tempDiags = f.Format(filename)
+ bytesModified += tempBytesModified
+ diags = diags.Extend(tempDiags)
+ }
+ continue
+ }
+ if isHcl2FileOrVarFile(filename) {
+ bytesModified, diags = f.formatFile(filename, diags, bytesModified)
+ }
+ }
+
+ return bytesModified, diags
+}
+
+// processFile formats the source contents of filename and return the formatted data.
+// overwriting the contents of the original when the f.Write is true; a diff of the changes
+// will be outputted if f.ShowDiff is true.
+func (f *HCL2Formatter) processFile(filename string) ([]byte, error) {
+
+ if f.Output == nil {
+ f.Output = os.Stdout
+ }
+
+ var in io.Reader
+ var err error
+
+ if filename == "-" {
+ in = os.Stdin
+ f.ShowDiff = false
+ } else {
+ in, err = os.Open(filename)
+ if err != nil {
+ return nil, fmt.Errorf("failed to open %s: %s", filename, err)
+ }
+ }
+
+ inSrc, err := ioutil.ReadAll(in)
+ if err != nil {
+ return nil, fmt.Errorf("failed to read %s: %s", filename, err)
+ }
+
+ _, diags := f.parser.ParseHCL(inSrc, filename)
+ if diags.HasErrors() {
+ return nil, fmt.Errorf("failed to parse HCL %s", filename)
+ }
+
+ outSrc := hclwrite.Format(inSrc)
+
+ if bytes.Equal(inSrc, outSrc) {
+ if filename == "-" {
+ _, _ = f.Output.Write(outSrc)
+ }
+
+ return nil, nil
+ }
+
+ if filename != "-" {
+ s := []byte(fmt.Sprintf("%s\n", filename))
+ _, _ = f.Output.Write(s)
+ }
+
+ if f.Write {
+ if filename == "-" {
+ _, _ = f.Output.Write(outSrc)
+ } else {
+ if err := ioutil.WriteFile(filename, outSrc, 0644); err != nil {
+ return nil, err
+ }
+ }
+ }
+
+ if f.ShowDiff {
+ diff, err := bytesDiff(inSrc, outSrc, filename)
+ if err != nil {
+ return outSrc, fmt.Errorf("failed to generate diff for %s: %s", filename, err)
+ }
+ _, _ = f.Output.Write(diff)
+ }
+
+ return outSrc, nil
+}
+
+// bytesDiff returns the unified diff of b1 and b2
+// Shamelessly copied from Terraform's fmt command.
+func bytesDiff(b1, b2 []byte, path string) (data []byte, err error) {
+ f1, err := ioutil.TempFile("", "")
+ if err != nil {
+ return
+ }
+ defer os.Remove(f1.Name())
+ defer f1.Close()
+
+ f2, err := ioutil.TempFile("", "")
+ if err != nil {
+ return
+ }
+ defer os.Remove(f2.Name())
+ defer f2.Close()
+
+ _, _ = f1.Write(b1)
+ _, _ = f2.Write(b2)
+
+ data, err = exec.Command("diff", "--label=old/"+path, "--label=new/"+path, "-u", f1.Name(), f2.Name()).CombinedOutput()
+ if len(data) > 0 {
+ // diff exits with a non-zero status when the files don't match.
+ // Ignore that failure as long as we get output.
+ err = nil
+ }
+ return
+}
diff --git a/v1.9.4/hcl2template/formatter_test.go b/v1.9.4/hcl2template/formatter_test.go
new file mode 100644
index 0000000..42051c0
--- /dev/null
+++ b/v1.9.4/hcl2template/formatter_test.go
@@ -0,0 +1,112 @@
+// Copyright (c) HashiCorp, Inc.
+// SPDX-License-Identifier: MPL-2.0
+
+package hcl2template
+
+import (
+ "bytes"
+ "io/ioutil"
+ "os"
+ "os/exec"
+ "strings"
+ "testing"
+
+ "github.com/google/go-cmp/cmp"
+)
+
+func TestHCL2Formatter_Format(t *testing.T) {
+ tt := []struct {
+ Name string
+ Path string
+ FormatExpected bool
+ }{
+ {Name: "Unformatted file", Path: "testdata/format/unformatted.pkr.hcl", FormatExpected: true},
+ {Name: "Unformatted vars file", Path: "testdata/format/unformatted.pkrvars.hcl", FormatExpected: true},
+ {Name: "Formatted file", Path: "testdata/format/formatted.pkr.hcl"},
+ {Name: "Directory", Path: "testdata/format", FormatExpected: true},
+ }
+
+ for _, tc := range tt {
+ tc := tc
+ var buf bytes.Buffer
+ f := NewHCL2Formatter()
+ f.Output = &buf
+ _, diags := f.Format(tc.Path)
+ if diags.HasErrors() {
+ t.Fatalf("the call to Format failed unexpectedly %s", diags.Error())
+ }
+ if buf.String() != "" && tc.FormatExpected == false {
+ t.Errorf("Format(%q) should contain the name of the formatted file(s), but got %q", tc.Path, buf.String())
+ }
+ }
+}
+
+func TestHCL2Formatter_Format_Write(t *testing.T) {
+
+ var buf bytes.Buffer
+ f := NewHCL2Formatter()
+ f.Output = &buf
+ f.Write = true
+
+ unformattedData, err := ioutil.ReadFile("testdata/format/unformatted.pkr.hcl")
+ if err != nil {
+ t.Fatalf("failed to open the unformatted fixture %s", err)
+ }
+
+ tf, err := ioutil.TempFile("", "*.pkr.hcl")
+ if err != nil {
+ t.Fatalf("failed to create tempfile for test %s", err)
+ }
+ defer os.Remove(tf.Name())
+
+ _, _ = tf.Write(unformattedData)
+ tf.Close()
+
+ _, diags := f.Format(tf.Name())
+ if diags.HasErrors() {
+ t.Fatalf("the call to Format failed unexpectedly %s", diags.Error())
+ }
+
+ //lets re-read the tempfile which should now be formatted
+ data, err := ioutil.ReadFile(tf.Name())
+ if err != nil {
+ t.Fatalf("failed to open the newly formatted fixture %s", err)
+ }
+
+ formattedData, err := ioutil.ReadFile("testdata/format/formatted.pkr.hcl")
+ if err != nil {
+ t.Fatalf("failed to open the formatted fixture %s", err)
+ }
+
+ if diff := cmp.Diff(string(data), string(formattedData)); diff != "" {
+ t.Errorf("Unexpected format output %s", diff)
+ }
+}
+
+func TestHCL2Formatter_Format_ShowDiff(t *testing.T) {
+
+ if _, err := exec.LookPath("diff"); err != nil {
+ t.Skip("Skipping test because diff is not in the executable PATH")
+ }
+
+ var buf bytes.Buffer
+ f := HCL2Formatter{
+ Output: &buf,
+ ShowDiff: true,
+ }
+
+ _, diags := f.Format("testdata/format/unformatted.pkr.hcl")
+ if diags.HasErrors() {
+ t.Fatalf("the call to Format failed unexpectedly %s", diags.Error())
+ }
+
+ diffHeader := `
+--- old/testdata/format/unformatted.pkr.hcl
++++ new/testdata/format/unformatted.pkr.hcl
+@@ -1,149 +1,149 @@
+`
+ if !strings.Contains(buf.String(), diffHeader) {
+ t.Errorf("expected buf to contain a file diff, but instead we got %s", buf.String())
+ }
+
+}
diff --git a/v1.9.4/hcl2template/function/Consul.go b/v1.9.4/hcl2template/function/Consul.go
new file mode 100644
index 0000000..4f51ca4
--- /dev/null
+++ b/v1.9.4/hcl2template/function/Consul.go
@@ -0,0 +1,28 @@
+// Copyright (c) HashiCorp, Inc.
+// SPDX-License-Identifier: MPL-2.0
+
+package function
+
+import (
+ "github.com/zclconf/go-cty/cty"
+ "github.com/zclconf/go-cty/cty/function"
+
+ commontpl "github.com/hashicorp/packer-plugin-sdk/template"
+)
+
+// ConsulFunc constructs a function that retrieves KV secrets from HC vault
+var ConsulFunc = function.New(&function.Spec{
+ Params: []function.Parameter{
+ {
+ Name: "key",
+ Type: cty.String,
+ },
+ },
+ Type: function.StaticReturnType(cty.String),
+ Impl: func(args []cty.Value, retType cty.Type) (cty.Value, error) {
+ key := args[0].AsString()
+ val, err := commontpl.Consul(key)
+
+ return cty.StringVal(val), err
+ },
+})
diff --git a/v1.9.4/hcl2template/function/aws_secretetkey.go b/v1.9.4/hcl2template/function/aws_secretetkey.go
new file mode 100644
index 0000000..50b4fe9
--- /dev/null
+++ b/v1.9.4/hcl2template/function/aws_secretetkey.go
@@ -0,0 +1,42 @@
+// Copyright (c) HashiCorp, Inc.
+// SPDX-License-Identifier: MPL-2.0
+
+package function
+
+import (
+ "github.com/zclconf/go-cty/cty"
+ "github.com/zclconf/go-cty/cty/function"
+
+ commontpl "github.com/hashicorp/packer-plugin-sdk/template"
+)
+
+// AWSSecret constructs a function that retrieves secrets from aws secrets
+// manager. If Key field is not set then we will return first secret key stored
+// in secret name.
+var AWSSecret = function.New(&function.Spec{
+ Params: []function.Parameter{
+ {
+ Name: "name",
+ Type: cty.String,
+ AllowNull: false,
+ AllowUnknown: false,
+ },
+ {
+ Name: "key",
+ Type: cty.String,
+ AllowNull: true,
+ AllowUnknown: false,
+ },
+ },
+ Type: function.StaticReturnType(cty.String),
+ Impl: func(args []cty.Value, retType cty.Type) (cty.Value, error) {
+ name := args[0].AsString()
+ var key string
+ if !args[1].IsNull() && args[1].IsWhollyKnown() {
+ key = args[1].AsString()
+ }
+ val, err := commontpl.GetAWSSecret(name, key)
+
+ return cty.StringVal(val), err
+ },
+})
diff --git a/v1.9.4/hcl2template/function/datetime.go b/v1.9.4/hcl2template/function/datetime.go
new file mode 100644
index 0000000..1d807e4
--- /dev/null
+++ b/v1.9.4/hcl2template/function/datetime.go
@@ -0,0 +1,101 @@
+// Copyright (c) HashiCorp, Inc.
+// SPDX-License-Identifier: MPL-2.0
+
+package function
+
+import (
+ "fmt"
+ "time"
+
+ "github.com/jehiah/go-strftime"
+ "github.com/zclconf/go-cty/cty"
+ "github.com/zclconf/go-cty/cty/function"
+)
+
+// InitTime is the UTC time when this package was initialized. It is
+// used as the timestamp for all configuration templates so that they
+// match for a single build.
+var InitTime time.Time
+
+func init() {
+ InitTime = time.Now().UTC()
+}
+
+// TimestampFunc constructs a function that returns a string representation of the current date and time.
+var TimestampFunc = function.New(&function.Spec{
+ Params: []function.Parameter{},
+ Type: function.StaticReturnType(cty.String),
+ Impl: func(args []cty.Value, retType cty.Type) (cty.Value, error) {
+ return cty.StringVal(time.Now().UTC().Format(time.RFC3339)), nil
+ },
+})
+
+// Timestamp returns a string representation of the current date and time.
+//
+// In the HCL language, timestamps are conventionally represented as strings
+// using RFC 3339 "Date and Time format" syntax, and so timestamp returns a
+// string in this format.
+func Timestamp() (cty.Value, error) {
+ return TimestampFunc.Call([]cty.Value{})
+}
+
+// LegacyIsotimeFunc constructs a function that returns a string representation
+// of the current date and time using golang's datetime formatting.
+var LegacyIsotimeFunc = function.New(&function.Spec{
+ Params: []function.Parameter{},
+ VarParam: &function.Parameter{
+ Name: "format",
+ Type: cty.String,
+ },
+ Type: function.StaticReturnType(cty.String),
+ Impl: func(args []cty.Value, retType cty.Type) (cty.Value, error) {
+ if len(args) > 1 {
+ return cty.StringVal(""), fmt.Errorf("too many values, 1 needed: %v", args)
+ } else if len(args) == 0 {
+ return cty.StringVal(InitTime.Format(time.RFC3339)), nil
+ }
+ format := args[0].AsString()
+ return cty.StringVal(InitTime.Format(format)), nil
+ },
+})
+
+// LegacyStrftimeFunc constructs a function that returns a string representation
+// of the current date and time using golang's strftime datetime formatting.
+var LegacyStrftimeFunc = function.New(&function.Spec{
+ Params: []function.Parameter{},
+ VarParam: &function.Parameter{
+ Name: "format",
+ Type: cty.String,
+ },
+ Type: function.StaticReturnType(cty.String),
+ Impl: func(args []cty.Value, retType cty.Type) (cty.Value, error) {
+ if len(args) > 1 {
+ return cty.StringVal(""), fmt.Errorf("too many values, 1 needed: %v", args)
+ } else if len(args) == 0 {
+ return cty.StringVal(InitTime.Format(time.RFC3339)), nil
+ }
+ format := args[0].AsString()
+ return cty.StringVal(strftime.Format(format, InitTime)), nil
+ },
+})
+
+// LegacyIsotimeFunc returns a string representation of the current date and
+// time using the given format string. The format string follows golang's
+// datetime formatting. See
+// https://www.packer.io/docs/templates/legacy_json_templates/engine#isotime-function-format-reference
+// for more details.
+//
+// This function has been provided to create backwards compatability with
+// Packer's legacy JSON templates. However, we recommend that you upgrade your
+// HCL Packer template to use Timestamp and FormatDate together as soon as is
+// convenient.
+//
+// Please note that if you are using a large number of builders, provisioners
+// or post-processors, the isotime may be slightly different for each one
+// because it is from when the plugin is launched not the initial Packer
+// process. In order to avoid this and make the timestamp consistent across all
+// plugins, set it as a user variable and then access the user variable within
+// your plugins.
+func LegacyIsotime(format cty.Value) (cty.Value, error) {
+ return LegacyIsotimeFunc.Call([]cty.Value{format})
+}
diff --git a/v1.9.4/hcl2template/function/datetime_test.go b/v1.9.4/hcl2template/function/datetime_test.go
new file mode 100644
index 0000000..6865648
--- /dev/null
+++ b/v1.9.4/hcl2template/function/datetime_test.go
@@ -0,0 +1,67 @@
+// Copyright (c) HashiCorp, Inc.
+// SPDX-License-Identifier: MPL-2.0
+
+package function
+
+import (
+ "fmt"
+ "regexp"
+ "testing"
+ "time"
+
+ "github.com/zclconf/go-cty/cty"
+)
+
+// HCL template usage example:
+//
+// locals {
+// emptyformat = legacy_isotime()
+// golangformat = legacy_isotime("01-02-2006")
+// }
+
+func TestLegacyIsotime_empty(t *testing.T) {
+ got, err := LegacyIsotimeFunc.Call([]cty.Value{})
+ if err != nil {
+ t.Fatalf("unexpected error: %s", err)
+ }
+
+ _, err = time.Parse(time.RFC3339, got.AsString())
+ if err != nil {
+ t.Fatalf("Didn't get an RFC3339 string from empty case: %s", err)
+ }
+
+}
+
+func TestLegacyIsotime_inputs(t *testing.T) {
+ tests := []struct {
+ Value cty.Value
+ Want string
+ }{
+ {
+ cty.StringVal("01-02-2006"),
+ `^\d{2}-\d{2}-\d{4}$`,
+ },
+ {
+ cty.StringVal("Mon Jan 02, 2006"),
+ `^(Mon|Tue|Wed|Thu|Fri|Sat|Sun){1} (Jan|Feb|Mar|Apr|May|Jun|Jul|Aug|Sep|Oct|Nov|Dec){1} \d{2}, \d{4}$`,
+ },
+ }
+
+ for _, test := range tests {
+ t.Run(fmt.Sprintf("legacy_isotime(%#v)", test.Value), func(t *testing.T) {
+ got, err := LegacyIsotime(test.Value)
+
+ if err != nil {
+ t.Fatalf("unexpected error: %s", err)
+ }
+ re, err := regexp.Compile(test.Want)
+ if err != nil {
+ t.Fatalf("Bad regular expression test string: %#v", err)
+ }
+
+ if !re.MatchString(got.AsString()) {
+ t.Errorf("wrong result\ngot: %#v\nwant: %#v", got, test.Want)
+ }
+ })
+ }
+}
diff --git a/v1.9.4/hcl2template/function/env.go b/v1.9.4/hcl2template/function/env.go
new file mode 100644
index 0000000..aeb632a
--- /dev/null
+++ b/v1.9.4/hcl2template/function/env.go
@@ -0,0 +1,35 @@
+// Copyright (c) HashiCorp, Inc.
+// SPDX-License-Identifier: MPL-2.0
+
+package function
+
+import (
+ "os"
+
+ "github.com/zclconf/go-cty/cty"
+ "github.com/zclconf/go-cty/cty/function"
+)
+
+// EnvFunc constructs a function that returns a string representation of the
+// env var behind a value
+var EnvFunc = function.New(&function.Spec{
+ Params: []function.Parameter{
+ {
+ Name: "key",
+ Type: cty.String,
+ AllowNull: false,
+ AllowUnknown: false,
+ },
+ },
+ Type: function.StaticReturnType(cty.String),
+ Impl: func(args []cty.Value, retType cty.Type) (cty.Value, error) {
+ key := args[0].AsString()
+ value := os.Getenv(key)
+ return cty.StringVal(value), nil
+ },
+})
+
+// Env returns a string representation of the env var behind key.
+func Env(key cty.Value) (cty.Value, error) {
+ return EnvFunc.Call([]cty.Value{key})
+}
diff --git a/v1.9.4/hcl2template/function/index.go b/v1.9.4/hcl2template/function/index.go
new file mode 100644
index 0000000..3c5f73c
--- /dev/null
+++ b/v1.9.4/hcl2template/function/index.go
@@ -0,0 +1,61 @@
+// Copyright (c) HashiCorp, Inc.
+// SPDX-License-Identifier: MPL-2.0
+
+package function
+
+import (
+ "errors"
+
+ "github.com/zclconf/go-cty/cty"
+ "github.com/zclconf/go-cty/cty/function"
+ "github.com/zclconf/go-cty/cty/function/stdlib"
+)
+
+// IndexFunc constructs a function that finds the element index for a given value in a list.
+var IndexFunc = function.New(&function.Spec{
+ Params: []function.Parameter{
+ {
+ Name: "list",
+ Type: cty.DynamicPseudoType,
+ },
+ {
+ Name: "value",
+ Type: cty.DynamicPseudoType,
+ },
+ },
+ Type: function.StaticReturnType(cty.Number),
+ Impl: func(args []cty.Value, retType cty.Type) (ret cty.Value, err error) {
+ if !(args[0].Type().IsListType() || args[0].Type().IsTupleType()) {
+ return cty.NilVal, errors.New("argument must be a list or tuple")
+ }
+
+ if !args[0].IsKnown() {
+ return cty.UnknownVal(cty.Number), nil
+ }
+
+ if args[0].LengthInt() == 0 { // Easy path
+ return cty.NilVal, errors.New("cannot search an empty list")
+ }
+
+ for it := args[0].ElementIterator(); it.Next(); {
+ i, v := it.Element()
+ eq, err := stdlib.Equal(v, args[1])
+ if err != nil {
+ return cty.NilVal, err
+ }
+ if !eq.IsKnown() {
+ return cty.UnknownVal(cty.Number), nil
+ }
+ if eq.True() {
+ return i, nil
+ }
+ }
+ return cty.NilVal, errors.New("item not found")
+
+ },
+})
+
+// Index finds the element index for a given value in a list.
+func Index(list, value cty.Value) (cty.Value, error) {
+ return IndexFunc.Call([]cty.Value{list, value})
+}
diff --git a/v1.9.4/hcl2template/function/index_test.go b/v1.9.4/hcl2template/function/index_test.go
new file mode 100644
index 0000000..d70511a
--- /dev/null
+++ b/v1.9.4/hcl2template/function/index_test.go
@@ -0,0 +1,130 @@
+// Copyright (c) HashiCorp, Inc.
+// SPDX-License-Identifier: MPL-2.0
+
+package function
+
+import (
+ "fmt"
+ "testing"
+
+ "github.com/zclconf/go-cty/cty"
+)
+
+func TestIndex(t *testing.T) {
+ tests := []struct {
+ List cty.Value
+ Value cty.Value
+ Want cty.Value
+ Err bool
+ }{
+ {
+ cty.ListVal([]cty.Value{
+ cty.StringVal("a"),
+ cty.StringVal("b"),
+ cty.StringVal("c"),
+ }),
+ cty.StringVal("a"),
+ cty.NumberIntVal(0),
+ false,
+ },
+ {
+ cty.ListVal([]cty.Value{
+ cty.StringVal("a"),
+ cty.StringVal("b"),
+ cty.UnknownVal(cty.String),
+ }),
+ cty.StringVal("a"),
+ cty.NumberIntVal(0),
+ false,
+ },
+ {
+ cty.ListVal([]cty.Value{
+ cty.StringVal("a"),
+ cty.StringVal("b"),
+ cty.StringVal("c"),
+ }),
+ cty.StringVal("b"),
+ cty.NumberIntVal(1),
+ false,
+ },
+ {
+ cty.ListVal([]cty.Value{
+ cty.StringVal("a"),
+ cty.StringVal("b"),
+ cty.StringVal("c"),
+ }),
+ cty.StringVal("z"),
+ cty.NilVal,
+ true,
+ },
+ {
+ cty.ListVal([]cty.Value{
+ cty.StringVal("1"),
+ cty.StringVal("2"),
+ cty.StringVal("3"),
+ }),
+ cty.NumberIntVal(1),
+ cty.NumberIntVal(0),
+ true,
+ },
+ {
+ cty.ListVal([]cty.Value{
+ cty.NumberIntVal(1),
+ cty.NumberIntVal(2),
+ cty.NumberIntVal(3),
+ }),
+ cty.NumberIntVal(2),
+ cty.NumberIntVal(1),
+ false,
+ },
+ {
+ cty.ListVal([]cty.Value{
+ cty.NumberIntVal(1),
+ cty.NumberIntVal(2),
+ cty.NumberIntVal(3),
+ }),
+ cty.NumberIntVal(4),
+ cty.NilVal,
+ true,
+ },
+ {
+ cty.ListVal([]cty.Value{
+ cty.NumberIntVal(1),
+ cty.NumberIntVal(2),
+ cty.NumberIntVal(3),
+ }),
+ cty.StringVal("1"),
+ cty.NumberIntVal(0),
+ true,
+ },
+ {
+ cty.TupleVal([]cty.Value{
+ cty.NumberIntVal(1),
+ cty.NumberIntVal(2),
+ cty.NumberIntVal(3),
+ }),
+ cty.NumberIntVal(1),
+ cty.NumberIntVal(0),
+ false,
+ },
+ }
+
+ for _, test := range tests {
+ t.Run(fmt.Sprintf("index(%#v, %#v)", test.List, test.Value), func(t *testing.T) {
+ got, err := Index(test.List, test.Value)
+
+ if test.Err {
+ if err == nil {
+ t.Fatal("succeeded; want error")
+ }
+ return
+ } else if err != nil {
+ t.Fatalf("unexpected error: %s", err)
+ }
+
+ if !got.RawEquals(test.Want) {
+ t.Errorf("wrong result\ngot: %#v\nwant: %#v", got, test.Want)
+ }
+ })
+ }
+}
diff --git a/v1.9.4/hcl2template/function/length.go b/v1.9.4/hcl2template/function/length.go
new file mode 100644
index 0000000..90ab799
--- /dev/null
+++ b/v1.9.4/hcl2template/function/length.go
@@ -0,0 +1,62 @@
+// Copyright (c) HashiCorp, Inc.
+// SPDX-License-Identifier: MPL-2.0
+
+package function
+
+import (
+ "errors"
+
+ "github.com/zclconf/go-cty/cty"
+ "github.com/zclconf/go-cty/cty/function"
+ "github.com/zclconf/go-cty/cty/function/stdlib"
+)
+
+var LengthFunc = function.New(&function.Spec{
+ Params: []function.Parameter{
+ {
+ Name: "value",
+ Type: cty.DynamicPseudoType,
+ AllowDynamicType: true,
+ AllowUnknown: true,
+ },
+ },
+ Type: func(args []cty.Value) (cty.Type, error) {
+ collTy := args[0].Type()
+ switch {
+ case collTy == cty.String || collTy.IsTupleType() || collTy.IsObjectType() || collTy.IsListType() || collTy.IsMapType() || collTy.IsSetType() || collTy == cty.DynamicPseudoType:
+ return cty.Number, nil
+ default:
+ return cty.Number, errors.New("argument must be a string, a collection type, or a structural type")
+ }
+ },
+ Impl: func(args []cty.Value, retType cty.Type) (cty.Value, error) {
+ coll := args[0]
+ collTy := args[0].Type()
+ switch {
+ case collTy == cty.DynamicPseudoType:
+ return cty.UnknownVal(cty.Number), nil
+ case collTy.IsTupleType():
+ l := len(collTy.TupleElementTypes())
+ return cty.NumberIntVal(int64(l)), nil
+ case collTy.IsObjectType():
+ l := len(collTy.AttributeTypes())
+ return cty.NumberIntVal(int64(l)), nil
+ case collTy == cty.String:
+ // We'll delegate to the cty stdlib strlen function here, because
+ // it deals with all of the complexities of tokenizing unicode
+ // grapheme clusters.
+ return stdlib.Strlen(coll)
+ case collTy.IsListType() || collTy.IsSetType() || collTy.IsMapType():
+ return coll.Length(), nil
+ default:
+ // Should never happen, because of the checks in our Type func above
+ return cty.UnknownVal(cty.Number), errors.New("impossible value type for length(...)")
+ }
+ },
+})
+
+// Length returns the number of elements in the given collection or number of
+// Unicode characters in the given string.
+func Length(collection cty.Value) (cty.Value, error) {
+ return LengthFunc.Call([]cty.Value{collection})
+}
diff --git a/v1.9.4/hcl2template/function/length_test.go b/v1.9.4/hcl2template/function/length_test.go
new file mode 100644
index 0000000..2c6f10c
--- /dev/null
+++ b/v1.9.4/hcl2template/function/length_test.go
@@ -0,0 +1,142 @@
+// Copyright (c) HashiCorp, Inc.
+// SPDX-License-Identifier: MPL-2.0
+
+package function
+
+import (
+ "fmt"
+ "testing"
+
+ "github.com/zclconf/go-cty/cty"
+)
+
+func TestLength(t *testing.T) {
+ tests := []struct {
+ Value cty.Value
+ Want cty.Value
+ }{
+ {
+ cty.ListValEmpty(cty.Number),
+ cty.NumberIntVal(0),
+ },
+ {
+ cty.ListVal([]cty.Value{cty.True}),
+ cty.NumberIntVal(1),
+ },
+ {
+ cty.ListVal([]cty.Value{cty.UnknownVal(cty.Bool)}),
+ cty.NumberIntVal(1),
+ },
+ {
+ cty.SetValEmpty(cty.Number),
+ cty.NumberIntVal(0),
+ },
+ {
+ cty.SetVal([]cty.Value{cty.True}),
+ cty.NumberIntVal(1),
+ },
+ {
+ cty.MapValEmpty(cty.Bool),
+ cty.NumberIntVal(0),
+ },
+ {
+ cty.MapVal(map[string]cty.Value{"hello": cty.True}),
+ cty.NumberIntVal(1),
+ },
+ {
+ cty.EmptyTupleVal,
+ cty.NumberIntVal(0),
+ },
+ {
+ cty.UnknownVal(cty.EmptyTuple),
+ cty.NumberIntVal(0),
+ },
+ {
+ cty.TupleVal([]cty.Value{cty.True}),
+ cty.NumberIntVal(1),
+ },
+ {
+ cty.EmptyObjectVal,
+ cty.NumberIntVal(0),
+ },
+ {
+ cty.UnknownVal(cty.EmptyObject),
+ cty.NumberIntVal(0),
+ },
+ {
+ cty.ObjectVal(map[string]cty.Value{"true": cty.True}),
+ cty.NumberIntVal(1),
+ },
+ {
+ cty.UnknownVal(cty.List(cty.Bool)),
+ cty.UnknownVal(cty.Number),
+ },
+ {
+ cty.DynamicVal,
+ cty.UnknownVal(cty.Number),
+ },
+ {
+ cty.StringVal("hello"),
+ cty.NumberIntVal(5),
+ },
+ {
+ cty.StringVal(""),
+ cty.NumberIntVal(0),
+ },
+ {
+ cty.StringVal("1"),
+ cty.NumberIntVal(1),
+ },
+ {
+ cty.StringVal("Живой Журнал"),
+ cty.NumberIntVal(12),
+ },
+ {
+ // note that the dieresis here is intentionally a combining
+ // ligature.
+ cty.StringVal("noël"),
+ cty.NumberIntVal(4),
+ },
+ {
+ // The Es in this string has three combining acute accents.
+ // This tests something that NFC-normalization cannot collapse
+ // into a single precombined codepoint, since otherwise we might
+ // be cheating and relying on the single-codepoint forms.
+ cty.StringVal("wé́́é́́é́́!"),
+ cty.NumberIntVal(5),
+ },
+ {
+ // Go's normalization forms don't handle this ligature, so we
+ // will produce the wrong result but this is now a compatibility
+ // constraint and so we'll test it.
+ cty.StringVal("baffle"),
+ cty.NumberIntVal(4),
+ },
+ {
+ cty.StringVal("😸😾"),
+ cty.NumberIntVal(2),
+ },
+ {
+ cty.UnknownVal(cty.String),
+ cty.UnknownVal(cty.Number),
+ },
+ {
+ cty.DynamicVal,
+ cty.UnknownVal(cty.Number),
+ },
+ }
+
+ for _, test := range tests {
+ t.Run(fmt.Sprintf("Length(%#v)", test.Value), func(t *testing.T) {
+ got, err := Length(test.Value)
+
+ if err != nil {
+ t.Fatalf("unexpected error: %s", err)
+ }
+
+ if !got.RawEquals(test.Want) {
+ t.Errorf("wrong result\ngot: %#v\nwant: %#v", got, test.Want)
+ }
+ })
+ }
+}
diff --git a/v1.9.4/hcl2template/function/templatefile.go b/v1.9.4/hcl2template/function/templatefile.go
new file mode 100644
index 0000000..eee0092
--- /dev/null
+++ b/v1.9.4/hcl2template/function/templatefile.go
@@ -0,0 +1,143 @@
+// Copyright (c) HashiCorp, Inc.
+// SPDX-License-Identifier: MPL-2.0
+
+package function
+
+import (
+ "fmt"
+
+ "github.com/hashicorp/go-cty-funcs/filesystem"
+ "github.com/hashicorp/hcl/v2"
+ "github.com/hashicorp/hcl/v2/hclsyntax"
+ "github.com/zclconf/go-cty/cty"
+ "github.com/zclconf/go-cty/cty/function"
+)
+
+// MakeTemplateFileFunc constructs a function that takes a file path and
+// an arbitrary object of named values and attempts to render the referenced
+// file as a template using HCL template syntax.
+//
+// The template itself may recursively call other functions so a callback
+// must be provided to get access to those functions. The template cannot,
+// however, access any variables defined in the scope: it is restricted only to
+// those variables provided in the second function argument.
+//
+// As a special exception, a referenced template file may not recursively call
+// the templatefile function, since that would risk the same file being
+// included into itself indefinitely.
+func MakeTemplateFileFunc(baseDir string, funcsCb func() map[string]function.Function) function.Function {
+
+ params := []function.Parameter{
+ {
+ Name: "path",
+ Type: cty.String,
+ },
+ {
+ Name: "vars",
+ Type: cty.DynamicPseudoType,
+ },
+ }
+
+ loadTmpl := func(fn string) (hcl.Expression, error) {
+ // We re-use File here to ensure the same filename interpretation
+ // as it does, along with its other safety checks.
+ tmplVal, err := filesystem.File(baseDir, cty.StringVal(fn))
+ if err != nil {
+ return nil, err
+ }
+
+ expr, diags := hclsyntax.ParseTemplate([]byte(tmplVal.AsString()), fn, hcl.Pos{Line: 1, Column: 1})
+ if diags.HasErrors() {
+ return nil, diags
+ }
+
+ return expr, nil
+ }
+
+ renderTmpl := func(expr hcl.Expression, varsVal cty.Value) (cty.Value, error) {
+ if varsTy := varsVal.Type(); !(varsTy.IsMapType() || varsTy.IsObjectType()) {
+ return cty.DynamicVal, function.NewArgErrorf(1, "invalid vars value: must be a map") // or an object, but we don't strongly distinguish these most of the time
+ }
+
+ ctx := &hcl.EvalContext{
+ Variables: varsVal.AsValueMap(),
+ }
+
+ // We require all of the variables to be valid HCL identifiers, because
+ // otherwise there would be no way to refer to them in the template
+ // anyway. Rejecting this here gives better feedback to the user
+ // than a syntax error somewhere in the template itself.
+ for n := range ctx.Variables {
+ if !hclsyntax.ValidIdentifier(n) {
+ // This error message intentionally doesn't describe _all_ of
+ // the different permutations that are technically valid as an
+ // HCL identifier, but rather focuses on what we might
+ // consider to be an "idiomatic" variable name.
+ return cty.DynamicVal, function.NewArgErrorf(1, "invalid template variable name %q: must start with a letter, followed by zero or more letters, digits, and underscores", n)
+ }
+ }
+
+ // We'll pre-check references in the template here so we can give a
+ // more specialized error message than HCL would by default, so it's
+ // clearer that this problem is coming from a templatefile call.
+ for _, traversal := range expr.Variables() {
+ root := traversal.RootName()
+ if _, ok := ctx.Variables[root]; !ok {
+ return cty.DynamicVal, function.NewArgErrorf(1, "vars map does not contain key %q, referenced at %s", root, traversal[0].SourceRange())
+ }
+ }
+
+ givenFuncs := funcsCb() // this callback indirection is to avoid chicken/egg problems
+ funcs := make(map[string]function.Function, len(givenFuncs))
+ for name, fn := range givenFuncs {
+ if name == "templatefile" {
+ // We stub this one out to prevent recursive calls.
+ funcs[name] = function.New(&function.Spec{
+ Params: params,
+ Type: func(args []cty.Value) (cty.Type, error) {
+ return cty.NilType, fmt.Errorf("cannot recursively call templatefile from inside templatefile call")
+ },
+ })
+ continue
+ }
+ funcs[name] = fn
+ }
+ ctx.Functions = funcs
+
+ val, diags := expr.Value(ctx)
+ if diags.HasErrors() {
+ return cty.DynamicVal, diags
+ }
+ return val, nil
+ }
+
+ return function.New(&function.Spec{
+ Params: params,
+ Type: func(args []cty.Value) (cty.Type, error) {
+ if !(args[0].IsKnown() && args[1].IsKnown()) {
+ return cty.DynamicPseudoType, nil
+ }
+
+ // We'll render our template now to see what result type it
+ // produces. A template consisting only of a single interpolation
+ // can potentially return any type.
+ expr, err := loadTmpl(args[0].AsString())
+ if err != nil {
+ return cty.DynamicPseudoType, err
+ }
+
+ // This is safe even if args[1] contains unknowns because the HCL
+ // template renderer itself knows how to short-circuit those.
+ val, err := renderTmpl(expr, args[1])
+ return val.Type(), err
+ },
+ Impl: func(args []cty.Value, retType cty.Type) (cty.Value, error) {
+ expr, err := loadTmpl(args[0].AsString())
+ if err != nil {
+ return cty.DynamicVal, err
+ }
+ return renderTmpl(expr, args[1])
+ },
+ })
+
+}
diff --git a/v1.9.4/hcl2template/function/templatefile_test.go b/v1.9.4/hcl2template/function/templatefile_test.go
new file mode 100644
index 0000000..a4536b5
--- /dev/null
+++ b/v1.9.4/hcl2template/function/templatefile_test.go
@@ -0,0 +1,154 @@
+// Copyright (c) HashiCorp, Inc.
+// SPDX-License-Identifier: MPL-2.0
+
+package function
+
+import (
+ "fmt"
+ "path/filepath"
+ "testing"
+
+ "github.com/hashicorp/go-cty-funcs/filesystem"
+ "github.com/zclconf/go-cty/cty"
+ "github.com/zclconf/go-cty/cty/function"
+ "github.com/zclconf/go-cty/cty/function/stdlib"
+)
+
+func TestTemplateFile(t *testing.T) {
+ tests := []struct {
+ Path cty.Value
+ Vars cty.Value
+ Want cty.Value
+ Err string
+ }{
+ {
+ cty.StringVal("testdata/hello.txt"),
+ cty.EmptyObjectVal,
+ cty.StringVal("Hello World"),
+ ``,
+ },
+ {
+ cty.StringVal("testdata/icon.png"),
+ cty.EmptyObjectVal,
+ cty.NilVal,
+ `contents of testdata/icon.png are not valid UTF-8; use the filebase64 function to obtain the Base64 encoded contents or the other file functions (e.g. filemd5, filesha256) to obtain file hashing results instead`,
+ },
+ {
+ cty.StringVal("testdata/missing"),
+ cty.EmptyObjectVal,
+ cty.NilVal,
+ `no file exists at ` + filepath.Clean("testdata/missing"),
+ },
+ {
+ cty.StringVal("testdata/hello.tmpl"),
+ cty.MapVal(map[string]cty.Value{
+ "name": cty.StringVal("Jodie"),
+ }),
+ cty.StringVal("Hello, Jodie!"),
+ ``,
+ },
+ {
+ cty.StringVal("testdata/hello.tmpl"),
+ cty.MapVal(map[string]cty.Value{
+ "name!": cty.StringVal("Jodie"),
+ }),
+ cty.NilVal,
+ `invalid template variable name "name!": must start with a letter, followed by zero or more letters, digits, and underscores`,
+ },
+ {
+ cty.StringVal("testdata/hello.tmpl"),
+ cty.ObjectVal(map[string]cty.Value{
+ "name": cty.StringVal("Jimbo"),
+ }),
+ cty.StringVal("Hello, Jimbo!"),
+ ``,
+ },
+ {
+ cty.StringVal("testdata/hello.tmpl"),
+ cty.EmptyObjectVal,
+ cty.NilVal,
+ `vars map does not contain key "name", referenced at testdata/hello.tmpl:1,10-14`,
+ },
+ {
+ cty.StringVal("testdata/func.tmpl"),
+ cty.ObjectVal(map[string]cty.Value{
+ "list": cty.ListVal([]cty.Value{
+ cty.StringVal("a"),
+ cty.StringVal("b"),
+ cty.StringVal("c"),
+ }),
+ }),
+ cty.StringVal("The items are a, b, c"),
+ ``,
+ },
+ {
+ cty.StringVal("testdata/recursive.tmpl"),
+ cty.MapValEmpty(cty.String),
+ cty.NilVal,
+ `testdata/recursive.tmpl:1,3-16: Error in function call; Call to function "templatefile" failed: cannot recursively call templatefile from inside templatefile call.`,
+ },
+ {
+ cty.StringVal("testdata/list.tmpl"),
+ cty.ObjectVal(map[string]cty.Value{
+ "list": cty.ListVal([]cty.Value{
+ cty.StringVal("a"),
+ cty.StringVal("b"),
+ cty.StringVal("c"),
+ }),
+ }),
+ cty.StringVal("- a\n- b\n- c\n"),
+ ``,
+ },
+ {
+ cty.StringVal("testdata/list.tmpl"),
+ cty.ObjectVal(map[string]cty.Value{
+ "list": cty.True,
+ }),
+ cty.NilVal,
+ `testdata/list.tmpl:1,13-17: Iteration over non-iterable value; A value of type bool cannot be used as the collection in a 'for' expression.`,
+ },
+ {
+ cty.StringVal("testdata/bare.tmpl"),
+ cty.ObjectVal(map[string]cty.Value{
+ "val": cty.True,
+ }),
+ cty.True, // since this template contains only an interpolation, its true value shines through
+ ``,
+ },
+ }
+
+ templateFileFn := MakeTemplateFileFunc(".", func() map[string]function.Function {
+ return map[string]function.Function{
+ "join": stdlib.JoinFunc,
+ "templatefile": filesystem.MakeFileFunc(".", false), // just a placeholder, since templatefile itself overrides this
+ }
+ })
+
+ for _, test := range tests {
+ t.Run(fmt.Sprintf("TemplateFile(%#v, %#v)", test.Path, test.Vars), func(t *testing.T) {
+ got, err := templateFileFn.Call([]cty.Value{test.Path, test.Vars})
+
+ if argErr, ok := err.(function.ArgError); ok {
+ if argErr.Index < 0 || argErr.Index > 1 {
+ t.Errorf("ArgError index %d is out of range for templatefile (must be 0 or 1)", argErr.Index)
+ }
+ }
+
+ if test.Err != "" {
+ if err == nil {
+ t.Fatal("succeeded; want error")
+ }
+ if got, want := err.Error(), test.Err; got != want {
+ t.Errorf("wrong error\ngot: %s\nwant: %s", got, want)
+ }
+ return
+ } else if err != nil {
+ t.Fatalf("unexpected error: %s", err)
+ }
+
+ if !got.RawEquals(test.Want) {
+ t.Errorf("wrong result\ngot: %#v\nwant: %#v", got, test.Want)
+ }
+ })
+ }
+}
diff --git a/v1.9.4/hcl2template/function/testdata/bare.tmpl b/v1.9.4/hcl2template/function/testdata/bare.tmpl
new file mode 100644
index 0000000..da7cbab
--- /dev/null
+++ b/v1.9.4/hcl2template/function/testdata/bare.tmpl
@@ -0,0 +1 @@
+${val}
\ No newline at end of file
diff --git a/v1.9.4/hcl2template/function/testdata/func.tmpl b/v1.9.4/hcl2template/function/testdata/func.tmpl
new file mode 100644
index 0000000..33a2400
--- /dev/null
+++ b/v1.9.4/hcl2template/function/testdata/func.tmpl
@@ -0,0 +1 @@
+The items are ${join(", ", list)}
\ No newline at end of file
diff --git a/v1.9.4/hcl2template/function/testdata/hello.tmpl b/v1.9.4/hcl2template/function/testdata/hello.tmpl
new file mode 100644
index 0000000..f112ef8
--- /dev/null
+++ b/v1.9.4/hcl2template/function/testdata/hello.tmpl
@@ -0,0 +1 @@
+Hello, ${name}!
\ No newline at end of file
diff --git a/v1.9.4/hcl2template/function/testdata/hello.txt b/v1.9.4/hcl2template/function/testdata/hello.txt
new file mode 100644
index 0000000..5e1c309
--- /dev/null
+++ b/v1.9.4/hcl2template/function/testdata/hello.txt
@@ -0,0 +1 @@
+Hello World
\ No newline at end of file
diff --git a/v1.9.4/hcl2template/function/testdata/icon.png b/v1.9.4/hcl2template/function/testdata/icon.png
new file mode 100644
index 0000000..a474f14
--- /dev/null
+++ b/v1.9.4/hcl2template/function/testdata/icon.png
Binary files differ
diff --git a/v1.9.4/hcl2template/function/testdata/list.tmpl b/v1.9.4/hcl2template/function/testdata/list.tmpl
new file mode 100644
index 0000000..da8f474
--- /dev/null
+++ b/v1.9.4/hcl2template/function/testdata/list.tmpl
@@ -0,0 +1,3 @@
+%{ for x in list ~}
+- ${x}
+%{ endfor ~}
diff --git a/v1.9.4/hcl2template/function/testdata/recursive.tmpl b/v1.9.4/hcl2template/function/testdata/recursive.tmpl
new file mode 100644
index 0000000..f121b60
--- /dev/null
+++ b/v1.9.4/hcl2template/function/testdata/recursive.tmpl
@@ -0,0 +1 @@
+${templatefile("recursive.tmpl", {})}
\ No newline at end of file
diff --git a/v1.9.4/hcl2template/function/vault.go b/v1.9.4/hcl2template/function/vault.go
new file mode 100644
index 0000000..4aa49da
--- /dev/null
+++ b/v1.9.4/hcl2template/function/vault.go
@@ -0,0 +1,34 @@
+// Copyright (c) HashiCorp, Inc.
+// SPDX-License-Identifier: MPL-2.0
+
+package function
+
+import (
+ "github.com/zclconf/go-cty/cty"
+ "github.com/zclconf/go-cty/cty/function"
+
+ commontpl "github.com/hashicorp/packer-plugin-sdk/template"
+)
+
+// VaultFunc constructs a function that retrieves KV secrets from HC vault
+var VaultFunc = function.New(&function.Spec{
+ Params: []function.Parameter{
+ {
+ Name: "path",
+ Type: cty.String,
+ },
+ {
+ Name: "key",
+ Type: cty.String,
+ },
+ },
+ Type: function.StaticReturnType(cty.String),
+ Impl: func(args []cty.Value, retType cty.Type) (cty.Value, error) {
+ path := args[0].AsString()
+ key := args[1].AsString()
+
+ val, err := commontpl.Vault(path, key)
+
+ return cty.StringVal(val), err
+ },
+})
diff --git a/v1.9.4/hcl2template/functions.go b/v1.9.4/hcl2template/functions.go
new file mode 100644
index 0000000..cc14494
--- /dev/null
+++ b/v1.9.4/hcl2template/functions.go
@@ -0,0 +1,140 @@
+// Copyright (c) HashiCorp, Inc.
+// SPDX-License-Identifier: MPL-2.0
+
+package hcl2template
+
+import (
+ "fmt"
+
+ "github.com/hashicorp/go-cty-funcs/cidr"
+ "github.com/hashicorp/go-cty-funcs/collection"
+ "github.com/hashicorp/go-cty-funcs/crypto"
+ "github.com/hashicorp/go-cty-funcs/encoding"
+ "github.com/hashicorp/go-cty-funcs/filesystem"
+ "github.com/hashicorp/go-cty-funcs/uuid"
+ "github.com/hashicorp/hcl/v2/ext/tryfunc"
+ "github.com/hashicorp/hcl/v2/ext/typeexpr"
+ pkrfunction "github.com/hashicorp/packer/hcl2template/function"
+ ctyyaml "github.com/zclconf/go-cty-yaml"
+ "github.com/zclconf/go-cty/cty"
+ "github.com/zclconf/go-cty/cty/function"
+ "github.com/zclconf/go-cty/cty/function/stdlib"
+)
+
+// Functions returns the set of functions that should be used to when
+// evaluating expressions in the receiving scope.
+//
+// basedir is used with file functions and allows a user to reference a file
+// using local path. Usually basedir is the directory in which the config file
+// is located
+func Functions(basedir string) map[string]function.Function {
+
+ funcs := map[string]function.Function{
+ "abs": stdlib.AbsoluteFunc,
+ "abspath": filesystem.AbsPathFunc,
+ "aws_secretsmanager": pkrfunction.AWSSecret,
+ "basename": filesystem.BasenameFunc,
+ "base64decode": encoding.Base64DecodeFunc,
+ "base64encode": encoding.Base64EncodeFunc,
+ "bcrypt": crypto.BcryptFunc,
+ "can": tryfunc.CanFunc,
+ "ceil": stdlib.CeilFunc,
+ "chomp": stdlib.ChompFunc,
+ "chunklist": stdlib.ChunklistFunc,
+ "cidrhost": cidr.HostFunc,
+ "cidrnetmask": cidr.NetmaskFunc,
+ "cidrsubnet": cidr.SubnetFunc,
+ "cidrsubnets": cidr.SubnetsFunc,
+ "coalesce": collection.CoalesceFunc,
+ "coalescelist": stdlib.CoalesceListFunc,
+ "compact": stdlib.CompactFunc,
+ "concat": stdlib.ConcatFunc,
+ "consul_key": pkrfunction.ConsulFunc,
+ "contains": stdlib.ContainsFunc,
+ "convert": typeexpr.ConvertFunc,
+ "csvdecode": stdlib.CSVDecodeFunc,
+ "dirname": filesystem.DirnameFunc,
+ "distinct": stdlib.DistinctFunc,
+ "element": stdlib.ElementFunc,
+ "file": filesystem.MakeFileFunc(basedir, false),
+ "fileexists": filesystem.MakeFileExistsFunc(basedir),
+ "fileset": filesystem.MakeFileSetFunc(basedir),
+ "flatten": stdlib.FlattenFunc,
+ "floor": stdlib.FloorFunc,
+ "format": stdlib.FormatFunc,
+ "formatdate": stdlib.FormatDateFunc,
+ "formatlist": stdlib.FormatListFunc,
+ "indent": stdlib.IndentFunc,
+ "index": pkrfunction.IndexFunc, // stdlib.IndexFunc is not compatible
+ "join": stdlib.JoinFunc,
+ "jsondecode": stdlib.JSONDecodeFunc,
+ "jsonencode": stdlib.JSONEncodeFunc,
+ "keys": stdlib.KeysFunc,
+ "legacy_isotime": pkrfunction.LegacyIsotimeFunc,
+ "legacy_strftime": pkrfunction.LegacyStrftimeFunc,
+ "length": pkrfunction.LengthFunc,
+ "log": stdlib.LogFunc,
+ "lookup": stdlib.LookupFunc,
+ "lower": stdlib.LowerFunc,
+ "max": stdlib.MaxFunc,
+ "md5": crypto.Md5Func,
+ "merge": stdlib.MergeFunc,
+ "min": stdlib.MinFunc,
+ "parseint": stdlib.ParseIntFunc,
+ "pathexpand": filesystem.PathExpandFunc,
+ "pow": stdlib.PowFunc,
+ "range": stdlib.RangeFunc,
+ "reverse": stdlib.ReverseListFunc,
+ "replace": stdlib.ReplaceFunc,
+ "regex": stdlib.RegexFunc,
+ "regexall": stdlib.RegexAllFunc,
+ "regex_replace": stdlib.RegexReplaceFunc,
+ "rsadecrypt": crypto.RsaDecryptFunc,
+ "setintersection": stdlib.SetIntersectionFunc,
+ "setproduct": stdlib.SetProductFunc,
+ "setunion": stdlib.SetUnionFunc,
+ "sha1": crypto.Sha1Func,
+ "sha256": crypto.Sha256Func,
+ "sha512": crypto.Sha512Func,
+ "signum": stdlib.SignumFunc,
+ "slice": stdlib.SliceFunc,
+ "sort": stdlib.SortFunc,
+ "split": stdlib.SplitFunc,
+ "strrev": stdlib.ReverseFunc,
+ "substr": stdlib.SubstrFunc,
+ "timestamp": pkrfunction.TimestampFunc,
+ "timeadd": stdlib.TimeAddFunc,
+ "title": stdlib.TitleFunc,
+ "trim": stdlib.TrimFunc,
+ "trimprefix": stdlib.TrimPrefixFunc,
+ "trimspace": stdlib.TrimSpaceFunc,
+ "trimsuffix": stdlib.TrimSuffixFunc,
+ "try": tryfunc.TryFunc,
+ "upper": stdlib.UpperFunc,
+ "urlencode": encoding.URLEncodeFunc,
+ "uuidv4": uuid.V4Func,
+ "uuidv5": uuid.V5Func,
+ "values": stdlib.ValuesFunc,
+ "vault": pkrfunction.VaultFunc,
+ "yamldecode": ctyyaml.YAMLDecodeFunc,
+ "yamlencode": ctyyaml.YAMLEncodeFunc,
+ "zipmap": stdlib.ZipmapFunc,
+ }
+
+ funcs["templatefile"] = pkrfunction.MakeTemplateFileFunc(basedir, func() map[string]function.Function {
+ // The templatefile function prevents recursive calls to itself
+ // by copying this map and overwriting the "templatefile" entry.
+ return funcs
+ })
+
+ return funcs
+}
+
+var unimplFunc = function.New(&function.Spec{
+ Type: func([]cty.Value) (cty.Type, error) {
+ return cty.DynamicPseudoType, fmt.Errorf("function not yet implemented")
+ },
+ Impl: func([]cty.Value, cty.Type) (cty.Value, error) {
+ return cty.DynamicVal, fmt.Errorf("function not yet implemented")
+ },
+})
diff --git a/v1.9.4/hcl2template/internal/mock.go b/v1.9.4/hcl2template/internal/mock.go
new file mode 100644
index 0000000..86d5b0e
--- /dev/null
+++ b/v1.9.4/hcl2template/internal/mock.go
@@ -0,0 +1,183 @@
+// Copyright (c) HashiCorp, Inc.
+// SPDX-License-Identifier: MPL-2.0
+
+//go:generate packer-sdc mapstructure-to-hcl2 -type MockConfig,NestedMockConfig,MockTag
+
+package hcl2template
+
+import (
+ "context"
+ "time"
+
+ "github.com/hashicorp/hcl/v2/hcldec"
+ "github.com/hashicorp/packer-plugin-sdk/hcl2helper"
+ packersdk "github.com/hashicorp/packer-plugin-sdk/packer"
+ "github.com/hashicorp/packer-plugin-sdk/template/config"
+ "github.com/zclconf/go-cty/cty"
+ "github.com/zclconf/go-cty/cty/json"
+)
+
+type NestedMockConfig struct {
+ String string `mapstructure:"string"`
+ Int int `mapstructure:"int"`
+ Int64 int64 `mapstructure:"int64"`
+ Bool bool `mapstructure:"bool"`
+ Trilean config.Trilean `mapstructure:"trilean"`
+ Duration time.Duration `mapstructure:"duration"`
+ MapStringString map[string]string `mapstructure:"map_string_string"`
+ SliceString []string `mapstructure:"slice_string"`
+ SliceSliceString [][]string `mapstructure:"slice_slice_string"`
+ NamedMapStringString NamedMapStringString `mapstructure:"named_map_string_string"`
+ NamedString NamedString `mapstructure:"named_string"`
+ Tags []MockTag `mapstructure:"tag"`
+ Datasource string `mapstructure:"data_source"`
+}
+
+type MockTag struct {
+ Key string `mapstructure:"key"`
+ Value string `mapstructure:"value"`
+}
+
+type MockConfig struct {
+ NotSquashed string `mapstructure:"not_squashed"`
+ NestedMockConfig `mapstructure:",squash"`
+ Nested NestedMockConfig `mapstructure:"nested"`
+ NestedSlice []NestedMockConfig `mapstructure:"nested_slice"`
+}
+
+func (b *MockConfig) Prepare(raws ...interface{}) error {
+ for i, raw := range raws {
+ cval, ok := raw.(cty.Value)
+ if !ok {
+ continue
+ }
+ b, err := json.Marshal(cval, cty.DynamicPseudoType)
+ if err != nil {
+ return err
+ }
+ ccval, err := json.Unmarshal(b, cty.DynamicPseudoType)
+ if err != nil {
+ return err
+ }
+ raws[i] = ccval
+ }
+ return config.Decode(b, &config.DecodeOpts{
+ Interpolate: true,
+ }, raws...)
+}
+
+//////
+// MockBuilder
+//////
+
+type MockBuilder struct {
+ Config MockConfig
+}
+
+var _ packersdk.Builder = new(MockBuilder)
+
+func (b *MockBuilder) ConfigSpec() hcldec.ObjectSpec { return b.Config.FlatMapstructure().HCL2Spec() }
+
+func (b *MockBuilder) Prepare(raws ...interface{}) ([]string, []string, error) {
+ return []string{"ID"}, nil, b.Config.Prepare(raws...)
+}
+
+func (b *MockBuilder) Run(ctx context.Context, ui packersdk.Ui, hook packersdk.Hook) (packersdk.Artifact, error) {
+ return nil, nil
+}
+
+//////
+// MockProvisioner
+//////
+
+type MockProvisioner struct {
+ Config MockConfig
+}
+
+var _ packersdk.Provisioner = new(MockProvisioner)
+
+func (b *MockProvisioner) ConfigSpec() hcldec.ObjectSpec {
+ return b.Config.FlatMapstructure().HCL2Spec()
+}
+
+func (b *MockProvisioner) Prepare(raws ...interface{}) error {
+ return b.Config.Prepare(raws...)
+}
+
+func (b *MockProvisioner) Provision(ctx context.Context, ui packersdk.Ui, comm packersdk.Communicator, _ map[string]interface{}) error {
+ return nil
+}
+
+//////
+// MockDatasource
+//////
+
+type MockDatasource struct {
+ Config MockConfig
+}
+
+var _ packersdk.Datasource = new(MockDatasource)
+
+func (d *MockDatasource) ConfigSpec() hcldec.ObjectSpec {
+ return d.Config.FlatMapstructure().HCL2Spec()
+}
+
+func (d *MockDatasource) OutputSpec() hcldec.ObjectSpec {
+ return d.Config.FlatMapstructure().HCL2Spec()
+}
+
+func (d *MockDatasource) Configure(raws ...interface{}) error {
+ return d.Config.Prepare(raws...)
+}
+
+func (d *MockDatasource) Execute() (cty.Value, error) {
+ return hcl2helper.HCL2ValueFromConfig(d.Config, d.OutputSpec()), nil
+}
+
+//////
+// MockPostProcessor
+//////
+
+type MockPostProcessor struct {
+ Config MockConfig
+}
+
+var _ packersdk.PostProcessor = new(MockPostProcessor)
+
+func (b *MockPostProcessor) ConfigSpec() hcldec.ObjectSpec {
+ return b.Config.FlatMapstructure().HCL2Spec()
+}
+
+func (b *MockPostProcessor) Configure(raws ...interface{}) error {
+ return b.Config.Prepare(raws...)
+}
+
+func (b *MockPostProcessor) PostProcess(ctx context.Context, ui packersdk.Ui, a packersdk.Artifact) (packersdk.Artifact, bool, bool, error) {
+ return nil, false, false, nil
+}
+
+//////
+// MockCommunicator
+//////
+
+type MockCommunicator struct {
+ Config MockConfig
+ packersdk.Communicator
+}
+
+var _ packersdk.ConfigurableCommunicator = new(MockCommunicator)
+
+func (b *MockCommunicator) ConfigSpec() hcldec.ObjectSpec {
+ return b.Config.FlatMapstructure().HCL2Spec()
+}
+
+func (b *MockCommunicator) Configure(raws ...interface{}) ([]string, error) {
+ return nil, b.Config.Prepare(raws...)
+}
+
+//////
+// Utils
+//////
+
+type NamedMapStringString map[string]string
+type NamedString string
diff --git a/v1.9.4/hcl2template/internal/mock.hcl2spec.go b/v1.9.4/hcl2template/internal/mock.hcl2spec.go
new file mode 100644
index 0000000..8449859
--- /dev/null
+++ b/v1.9.4/hcl2template/internal/mock.hcl2spec.go
@@ -0,0 +1,133 @@
+// Code generated by "packer-sdc mapstructure-to-hcl2"; DO NOT EDIT.
+
+package hcl2template
+
+import (
+ "github.com/hashicorp/hcl/v2/hcldec"
+ "github.com/zclconf/go-cty/cty"
+)
+
+// FlatMockConfig is an auto-generated flat version of MockConfig.
+// Where the contents of a field with a `mapstructure:,squash` tag are bubbled up.
+type FlatMockConfig struct {
+ NotSquashed *string `mapstructure:"not_squashed" cty:"not_squashed" hcl:"not_squashed"`
+ String *string `mapstructure:"string" cty:"string" hcl:"string"`
+ Int *int `mapstructure:"int" cty:"int" hcl:"int"`
+ Int64 *int64 `mapstructure:"int64" cty:"int64" hcl:"int64"`
+ Bool *bool `mapstructure:"bool" cty:"bool" hcl:"bool"`
+ Trilean *bool `mapstructure:"trilean" cty:"trilean" hcl:"trilean"`
+ Duration *string `mapstructure:"duration" cty:"duration" hcl:"duration"`
+ MapStringString map[string]string `mapstructure:"map_string_string" cty:"map_string_string" hcl:"map_string_string"`
+ SliceString []string `mapstructure:"slice_string" cty:"slice_string" hcl:"slice_string"`
+ SliceSliceString [][]string `mapstructure:"slice_slice_string" cty:"slice_slice_string" hcl:"slice_slice_string"`
+ NamedMapStringString NamedMapStringString `mapstructure:"named_map_string_string" cty:"named_map_string_string" hcl:"named_map_string_string"`
+ NamedString *NamedString `mapstructure:"named_string" cty:"named_string" hcl:"named_string"`
+ Tags []FlatMockTag `mapstructure:"tag" cty:"tag" hcl:"tag"`
+ Datasource *string `mapstructure:"data_source" cty:"data_source" hcl:"data_source"`
+ Nested *FlatNestedMockConfig `mapstructure:"nested" cty:"nested" hcl:"nested"`
+ NestedSlice []FlatNestedMockConfig `mapstructure:"nested_slice" cty:"nested_slice" hcl:"nested_slice"`
+}
+
+// FlatMapstructure returns a new FlatMockConfig.
+// FlatMockConfig is an auto-generated flat version of MockConfig.
+// Where the contents a fields with a `mapstructure:,squash` tag are bubbled up.
+func (*MockConfig) FlatMapstructure() interface{ HCL2Spec() map[string]hcldec.Spec } {
+ return new(FlatMockConfig)
+}
+
+// HCL2Spec returns the hcl spec of a MockConfig.
+// This spec is used by HCL to read the fields of MockConfig.
+// The decoded values from this spec will then be applied to a FlatMockConfig.
+func (*FlatMockConfig) HCL2Spec() map[string]hcldec.Spec {
+ s := map[string]hcldec.Spec{
+ "not_squashed": &hcldec.AttrSpec{Name: "not_squashed", Type: cty.String, Required: false},
+ "string": &hcldec.AttrSpec{Name: "string", Type: cty.String, Required: false},
+ "int": &hcldec.AttrSpec{Name: "int", Type: cty.Number, Required: false},
+ "int64": &hcldec.AttrSpec{Name: "int64", Type: cty.Number, Required: false},
+ "bool": &hcldec.AttrSpec{Name: "bool", Type: cty.Bool, Required: false},
+ "trilean": &hcldec.AttrSpec{Name: "trilean", Type: cty.Bool, Required: false},
+ "duration": &hcldec.AttrSpec{Name: "duration", Type: cty.String, Required: false},
+ "map_string_string": &hcldec.AttrSpec{Name: "map_string_string", Type: cty.Map(cty.String), Required: false},
+ "slice_string": &hcldec.AttrSpec{Name: "slice_string", Type: cty.List(cty.String), Required: false},
+ "slice_slice_string": &hcldec.AttrSpec{Name: "slice_slice_string", Type: cty.List(cty.List(cty.String)), Required: false},
+ "named_map_string_string": &hcldec.AttrSpec{Name: "named_map_string_string", Type: cty.Map(cty.String), Required: false},
+ "named_string": &hcldec.AttrSpec{Name: "named_string", Type: cty.String, Required: false},
+ "tag": &hcldec.BlockListSpec{TypeName: "tag", Nested: hcldec.ObjectSpec((*FlatMockTag)(nil).HCL2Spec())},
+ "data_source": &hcldec.AttrSpec{Name: "data_source", Type: cty.String, Required: false},
+ "nested": &hcldec.BlockSpec{TypeName: "nested", Nested: hcldec.ObjectSpec((*FlatNestedMockConfig)(nil).HCL2Spec())},
+ "nested_slice": &hcldec.BlockListSpec{TypeName: "nested_slice", Nested: hcldec.ObjectSpec((*FlatNestedMockConfig)(nil).HCL2Spec())},
+ }
+ return s
+}
+
+// FlatMockTag is an auto-generated flat version of MockTag.
+// Where the contents of a field with a `mapstructure:,squash` tag are bubbled up.
+type FlatMockTag struct {
+ Key *string `mapstructure:"key" cty:"key" hcl:"key"`
+ Value *string `mapstructure:"value" cty:"value" hcl:"value"`
+}
+
+// FlatMapstructure returns a new FlatMockTag.
+// FlatMockTag is an auto-generated flat version of MockTag.
+// Where the contents a fields with a `mapstructure:,squash` tag are bubbled up.
+func (*MockTag) FlatMapstructure() interface{ HCL2Spec() map[string]hcldec.Spec } {
+ return new(FlatMockTag)
+}
+
+// HCL2Spec returns the hcl spec of a MockTag.
+// This spec is used by HCL to read the fields of MockTag.
+// The decoded values from this spec will then be applied to a FlatMockTag.
+func (*FlatMockTag) HCL2Spec() map[string]hcldec.Spec {
+ s := map[string]hcldec.Spec{
+ "key": &hcldec.AttrSpec{Name: "key", Type: cty.String, Required: false},
+ "value": &hcldec.AttrSpec{Name: "value", Type: cty.String, Required: false},
+ }
+ return s
+}
+
+// FlatNestedMockConfig is an auto-generated flat version of NestedMockConfig.
+// Where the contents of a field with a `mapstructure:,squash` tag are bubbled up.
+type FlatNestedMockConfig struct {
+ String *string `mapstructure:"string" cty:"string" hcl:"string"`
+ Int *int `mapstructure:"int" cty:"int" hcl:"int"`
+ Int64 *int64 `mapstructure:"int64" cty:"int64" hcl:"int64"`
+ Bool *bool `mapstructure:"bool" cty:"bool" hcl:"bool"`
+ Trilean *bool `mapstructure:"trilean" cty:"trilean" hcl:"trilean"`
+ Duration *string `mapstructure:"duration" cty:"duration" hcl:"duration"`
+ MapStringString map[string]string `mapstructure:"map_string_string" cty:"map_string_string" hcl:"map_string_string"`
+ SliceString []string `mapstructure:"slice_string" cty:"slice_string" hcl:"slice_string"`
+ SliceSliceString [][]string `mapstructure:"slice_slice_string" cty:"slice_slice_string" hcl:"slice_slice_string"`
+ NamedMapStringString NamedMapStringString `mapstructure:"named_map_string_string" cty:"named_map_string_string" hcl:"named_map_string_string"`
+ NamedString *NamedString `mapstructure:"named_string" cty:"named_string" hcl:"named_string"`
+ Tags []FlatMockTag `mapstructure:"tag" cty:"tag" hcl:"tag"`
+ Datasource *string `mapstructure:"data_source" cty:"data_source" hcl:"data_source"`
+}
+
+// FlatMapstructure returns a new FlatNestedMockConfig.
+// FlatNestedMockConfig is an auto-generated flat version of NestedMockConfig.
+// Where the contents a fields with a `mapstructure:,squash` tag are bubbled up.
+func (*NestedMockConfig) FlatMapstructure() interface{ HCL2Spec() map[string]hcldec.Spec } {
+ return new(FlatNestedMockConfig)
+}
+
+// HCL2Spec returns the hcl spec of a NestedMockConfig.
+// This spec is used by HCL to read the fields of NestedMockConfig.
+// The decoded values from this spec will then be applied to a FlatNestedMockConfig.
+func (*FlatNestedMockConfig) HCL2Spec() map[string]hcldec.Spec {
+ s := map[string]hcldec.Spec{
+ "string": &hcldec.AttrSpec{Name: "string", Type: cty.String, Required: false},
+ "int": &hcldec.AttrSpec{Name: "int", Type: cty.Number, Required: false},
+ "int64": &hcldec.AttrSpec{Name: "int64", Type: cty.Number, Required: false},
+ "bool": &hcldec.AttrSpec{Name: "bool", Type: cty.Bool, Required: false},
+ "trilean": &hcldec.AttrSpec{Name: "trilean", Type: cty.Bool, Required: false},
+ "duration": &hcldec.AttrSpec{Name: "duration", Type: cty.String, Required: false},
+ "map_string_string": &hcldec.AttrSpec{Name: "map_string_string", Type: cty.Map(cty.String), Required: false},
+ "slice_string": &hcldec.AttrSpec{Name: "slice_string", Type: cty.List(cty.String), Required: false},
+ "slice_slice_string": &hcldec.AttrSpec{Name: "slice_slice_string", Type: cty.List(cty.List(cty.String)), Required: false},
+ "named_map_string_string": &hcldec.AttrSpec{Name: "named_map_string_string", Type: cty.Map(cty.String), Required: false},
+ "named_string": &hcldec.AttrSpec{Name: "named_string", Type: cty.String, Required: false},
+ "tag": &hcldec.BlockListSpec{TypeName: "tag", Nested: hcldec.ObjectSpec((*FlatMockTag)(nil).HCL2Spec())},
+ "data_source": &hcldec.AttrSpec{Name: "data_source", Type: cty.String, Required: false},
+ }
+ return s
+}
diff --git a/v1.9.4/hcl2template/parser.go b/v1.9.4/hcl2template/parser.go
new file mode 100644
index 0000000..1a0d402
--- /dev/null
+++ b/v1.9.4/hcl2template/parser.go
@@ -0,0 +1,404 @@
+// Copyright (c) HashiCorp, Inc.
+// SPDX-License-Identifier: MPL-2.0
+
+package hcl2template
+
+import (
+ "fmt"
+ "os"
+ "path/filepath"
+
+ "github.com/hashicorp/go-version"
+ "github.com/hashicorp/hcl/v2"
+ "github.com/hashicorp/hcl/v2/ext/dynblock"
+ "github.com/hashicorp/hcl/v2/hclparse"
+ packersdk "github.com/hashicorp/packer-plugin-sdk/packer"
+ "github.com/hashicorp/packer/packer"
+ "github.com/zclconf/go-cty/cty"
+)
+
+const (
+ packerLabel = "packer"
+ sourceLabel = "source"
+ variablesLabel = "variables"
+ variableLabel = "variable"
+ localsLabel = "locals"
+ localLabel = "local"
+ dataSourceLabel = "data"
+ buildLabel = "build"
+ communicatorLabel = "communicator"
+)
+
+var configSchema = &hcl.BodySchema{
+ Blocks: []hcl.BlockHeaderSchema{
+ {Type: packerLabel},
+ {Type: sourceLabel, LabelNames: []string{"type", "name"}},
+ {Type: variablesLabel},
+ {Type: variableLabel, LabelNames: []string{"name"}},
+ {Type: localsLabel},
+ {Type: localLabel, LabelNames: []string{"name"}},
+ {Type: dataSourceLabel, LabelNames: []string{"type", "name"}},
+ {Type: buildLabel},
+ {Type: communicatorLabel, LabelNames: []string{"type", "name"}},
+ },
+}
+
+// packerBlockSchema is the schema for a top-level "packer" block in
+// a configuration file.
+var packerBlockSchema = &hcl.BodySchema{
+ Attributes: []hcl.AttributeSchema{
+ {Name: "required_version"},
+ },
+ Blocks: []hcl.BlockHeaderSchema{
+ {Type: "required_plugins"},
+ },
+}
+
+// Parser helps you parse HCL folders. It will parse an hcl file or directory
+// and start builders, provisioners and post-processors to configure them with
+// the parsed HCL and then return a []packersdk.Build. Packer will use that list
+// of Builds to run everything in order.
+type Parser struct {
+ CorePackerVersion *version.Version
+
+ CorePackerVersionString string
+
+ PluginConfig *packer.PluginConfig
+
+ ValidationOptions
+
+ *hclparse.Parser
+}
+
+const (
+ hcl2FileExt = ".pkr.hcl"
+ hcl2JsonFileExt = ".pkr.json"
+ hcl2VarFileExt = ".pkrvars.hcl"
+ hcl2VarJsonFileExt = ".pkrvars.json"
+ hcl2AutoVarFileExt = ".auto.pkrvars.hcl"
+ hcl2AutoVarJsonFileExt = ".auto.pkrvars.json"
+)
+
+// Parse will Parse all HCL files in filename. Path can be a folder or a file.
+//
+// Parse will first Parse packer and variables blocks, omitting the rest, which
+// can be expanded with dynamic blocks. We need to evaluate all variables for
+// that, so that data sources can expand dynamic blocks too.
+//
+// Parse returns a PackerConfig that contains configuration layout of a packer
+// build; sources(builders)/provisioners/posts-processors will not be started
+// and their contents wont be verified; Most syntax errors will cause an error,
+// init should be called next to expand dynamic blocks and verify that used
+// things do exist.
+func (p *Parser) Parse(filename string, varFiles []string, argVars map[string]string) (*PackerConfig, hcl.Diagnostics) {
+ var files []*hcl.File
+ var diags hcl.Diagnostics
+
+ // parse config files
+ if filename != "" {
+ hclFiles, jsonFiles, moreDiags := GetHCL2Files(filename, hcl2FileExt, hcl2JsonFileExt)
+ diags = append(diags, moreDiags...)
+ if moreDiags.HasErrors() {
+ // here this probably means that the file was not found, let's
+ // simply leave early.
+ return nil, diags
+ }
+ if len(hclFiles)+len(jsonFiles) == 0 {
+ diags = append(diags, &hcl.Diagnostic{
+ Severity: hcl.DiagError,
+ Summary: "Could not find any config file in " + filename,
+ Detail: "A config file must be suffixed with `.pkr.hcl` or " +
+ "`.pkr.json`. A folder can be referenced.",
+ })
+ }
+ for _, filename := range hclFiles {
+ f, moreDiags := p.ParseHCLFile(filename)
+ diags = append(diags, moreDiags...)
+ files = append(files, f)
+ }
+ for _, filename := range jsonFiles {
+ f, moreDiags := p.ParseJSONFile(filename)
+ diags = append(diags, moreDiags...)
+ files = append(files, f)
+ }
+ if diags.HasErrors() {
+ return nil, diags
+ }
+ }
+
+ basedir := filename
+ if isDir, err := isDir(basedir); err == nil && !isDir {
+ basedir = filepath.Dir(basedir)
+ }
+ wd, err := os.Getwd()
+ if err != nil {
+ diags = append(diags, &hcl.Diagnostic{
+ Severity: hcl.DiagError,
+ Summary: "Could not find current working directory",
+ Detail: err.Error(),
+ })
+ }
+ cfg := &PackerConfig{
+ Basedir: basedir,
+ Cwd: wd,
+ CorePackerVersionString: p.CorePackerVersionString,
+ HCPVars: map[string]cty.Value{},
+ ValidationOptions: p.ValidationOptions,
+ parser: p,
+ files: files,
+ }
+
+ for _, file := range files {
+ coreVersionConstraints, moreDiags := sniffCoreVersionRequirements(file.Body)
+ cfg.Packer.VersionConstraints = append(cfg.Packer.VersionConstraints, coreVersionConstraints...)
+ diags = append(diags, moreDiags...)
+ }
+
+ // Before we go further, we'll check to make sure this version can read
+ // all files, so we can produce a version-related error message rather than
+ // potentially-confusing downstream errors.
+ versionDiags := cfg.CheckCoreVersionRequirements(p.CorePackerVersion)
+ diags = append(diags, versionDiags...)
+ if versionDiags.HasErrors() {
+ return cfg, diags
+ }
+
+ // Decode required_plugins blocks.
+ //
+ // Note: using `latest` ( or actually an empty string ) in a config file
+ // does not work and packer will ask you to pick a version
+ {
+ for _, file := range files {
+ diags = append(diags, cfg.decodeRequiredPluginsBlock(file)...)
+ }
+ }
+
+ // Decode variable blocks so that they are available later on. Here locals
+ // can use input variables so we decode input variables first.
+ {
+ for _, file := range files {
+ diags = append(diags, cfg.decodeInputVariables(file)...)
+ }
+
+ for _, file := range files {
+ morediags := p.decodeDatasources(file, cfg)
+ diags = append(diags, morediags...)
+ }
+
+ for _, file := range files {
+ moreLocals, morediags := parseLocalVariableBlocks(file)
+ diags = append(diags, morediags...)
+ cfg.LocalBlocks = append(cfg.LocalBlocks, moreLocals...)
+ }
+ }
+
+ // parse var files
+ {
+ hclVarFiles, jsonVarFiles, moreDiags := GetHCL2Files(filename, hcl2AutoVarFileExt, hcl2AutoVarJsonFileExt)
+ diags = append(diags, moreDiags...)
+ for _, file := range varFiles {
+ switch filepath.Ext(file) {
+ case ".hcl":
+ hclVarFiles = append(hclVarFiles, file)
+ case ".json":
+ jsonVarFiles = append(jsonVarFiles, file)
+ default:
+ diags = append(moreDiags, &hcl.Diagnostic{
+ Severity: hcl.DiagError,
+ Summary: "Could not guess format of " + file,
+ Detail: "A var file must be suffixed with `.hcl` or `.json`.",
+ })
+ }
+ }
+ var varFiles []*hcl.File
+ for _, filename := range hclVarFiles {
+ f, moreDiags := p.ParseHCLFile(filename)
+ diags = append(diags, moreDiags...)
+ if moreDiags.HasErrors() {
+ continue
+ }
+ varFiles = append(varFiles, f)
+ }
+ for _, filename := range jsonVarFiles {
+ f, moreDiags := p.ParseJSONFile(filename)
+ diags = append(diags, moreDiags...)
+ if moreDiags.HasErrors() {
+ continue
+ }
+ varFiles = append(varFiles, f)
+ }
+
+ diags = append(diags, cfg.collectInputVariableValues(os.Environ(), varFiles, argVars)...)
+ }
+
+ return cfg, diags
+}
+
+// sniffCoreVersionRequirements does minimal parsing of the given body for
+// "packer" blocks with "required_version" attributes, returning the
+// requirements found.
+//
+// This is intended to maximize the chance that we'll be able to read the
+// requirements (syntax errors notwithstanding) even if the config file contains
+// constructs that might've been added in future versions
+//
+// This is a "best effort" sort of method which will return constraints it is
+// able to find, but may return no constraints at all if the given body is
+// so invalid that it cannot be decoded at all.
+func sniffCoreVersionRequirements(body hcl.Body) ([]VersionConstraint, hcl.Diagnostics) {
+
+ var sniffRootSchema = &hcl.BodySchema{
+ Blocks: []hcl.BlockHeaderSchema{
+ {
+ Type: packerLabel,
+ },
+ },
+ }
+
+ rootContent, _, diags := body.PartialContent(sniffRootSchema)
+
+ var constraints []VersionConstraint
+
+ for _, block := range rootContent.Blocks {
+ content, blockDiags := block.Body.Content(packerBlockSchema)
+ diags = append(diags, blockDiags...)
+
+ attr, exists := content.Attributes["required_version"]
+ if !exists {
+ continue
+ }
+
+ constraint, constraintDiags := decodeVersionConstraint(attr)
+ diags = append(diags, constraintDiags...)
+ if !constraintDiags.HasErrors() {
+ constraints = append(constraints, constraint)
+ }
+ }
+
+ return constraints, diags
+}
+
+func filterVarsFromLogs(inputOrLocal Variables) {
+ for _, variable := range inputOrLocal {
+ if !variable.Sensitive {
+ continue
+ }
+ value := variable.Value()
+ _ = cty.Walk(value, func(_ cty.Path, nested cty.Value) (bool, error) {
+ if nested.IsWhollyKnown() && !nested.IsNull() && nested.Type().Equals(cty.String) {
+ packersdk.LogSecretFilter.Set(nested.AsString())
+ }
+ return true, nil
+ })
+ }
+}
+
+func (cfg *PackerConfig) Initialize(opts packer.InitializeOptions) hcl.Diagnostics {
+ diags := cfg.InputVariables.ValidateValues()
+ diags = append(diags, cfg.LocalVariables.ValidateValues()...)
+ diags = append(diags, cfg.evaluateDatasources(opts.SkipDatasourcesExecution)...)
+ diags = append(diags, checkForDuplicateLocalDefinition(cfg.LocalBlocks)...)
+ diags = append(diags, cfg.evaluateLocalVariables(cfg.LocalBlocks)...)
+
+ filterVarsFromLogs(cfg.InputVariables)
+ filterVarsFromLogs(cfg.LocalVariables)
+
+ // parse the actual content // rest
+ for _, file := range cfg.files {
+ diags = append(diags, cfg.parser.parseConfig(file, cfg)...)
+ }
+
+ diags = append(diags, cfg.initializeBlocks()...)
+
+ return diags
+}
+
+// parseConfig looks in the found blocks for everything that is not a variable
+// block.
+func (p *Parser) parseConfig(f *hcl.File, cfg *PackerConfig) hcl.Diagnostics {
+ var diags hcl.Diagnostics
+
+ body := f.Body
+ body = dynblock.Expand(body, cfg.EvalContext(DatasourceContext, nil))
+ content, moreDiags := body.Content(configSchema)
+ diags = append(diags, moreDiags...)
+
+ for _, block := range content.Blocks {
+ switch block.Type {
+ case sourceLabel:
+ source, moreDiags := p.decodeSource(block)
+ diags = append(diags, moreDiags...)
+ if moreDiags.HasErrors() {
+ continue
+ }
+
+ ref := source.Ref()
+ if existing, found := cfg.Sources[ref]; found {
+ diags = append(diags, &hcl.Diagnostic{
+ Severity: hcl.DiagError,
+ Summary: "Duplicate " + sourceLabel + " block",
+ Detail: fmt.Sprintf("This "+sourceLabel+" block has the "+
+ "same builder type and name as a previous block declared "+
+ "at %s. Each "+sourceLabel+" must have a unique name per builder type.",
+ existing.block.DefRange.Ptr()),
+ Subject: source.block.DefRange.Ptr(),
+ })
+ continue
+ }
+
+ if cfg.Sources == nil {
+ cfg.Sources = map[SourceRef]SourceBlock{}
+ }
+ cfg.Sources[ref] = source
+
+ case buildLabel:
+ build, moreDiags := p.decodeBuildConfig(block, cfg)
+ diags = append(diags, moreDiags...)
+ if moreDiags.HasErrors() {
+ continue
+ }
+
+ cfg.Builds = append(cfg.Builds, build)
+ }
+ }
+
+ return diags
+}
+
+func (p *Parser) decodeDatasources(file *hcl.File, cfg *PackerConfig) hcl.Diagnostics {
+ var diags hcl.Diagnostics
+
+ body := file.Body
+ content, moreDiags := body.Content(configSchema)
+ diags = append(diags, moreDiags...)
+
+ for _, block := range content.Blocks {
+ switch block.Type {
+ case dataSourceLabel:
+ datasource, moreDiags := p.decodeDataBlock(block)
+ diags = append(diags, moreDiags...)
+ if moreDiags.HasErrors() {
+ continue
+ }
+ ref := datasource.Ref()
+ if existing, found := cfg.Datasources[ref]; found {
+ diags = append(diags, &hcl.Diagnostic{
+ Severity: hcl.DiagError,
+ Summary: "Duplicate " + dataSourceLabel + " block",
+ Detail: fmt.Sprintf("This "+dataSourceLabel+" block has the "+
+ "same data type and name as a previous block declared "+
+ "at %s. Each "+dataSourceLabel+" must have a unique name per builder type.",
+ existing.block.DefRange.Ptr()),
+ Subject: datasource.block.DefRange.Ptr(),
+ })
+ continue
+ }
+ if cfg.Datasources == nil {
+ cfg.Datasources = Datasources{}
+ }
+ cfg.Datasources[ref] = *datasource
+ }
+ }
+
+ return diags
+}
diff --git a/v1.9.4/hcl2template/plugin.go b/v1.9.4/hcl2template/plugin.go
new file mode 100644
index 0000000..ac109ee
--- /dev/null
+++ b/v1.9.4/hcl2template/plugin.go
@@ -0,0 +1,208 @@
+// Copyright (c) HashiCorp, Inc.
+// SPDX-License-Identifier: MPL-2.0
+
+package hcl2template
+
+import (
+ "crypto/sha256"
+ "fmt"
+ "log"
+ "runtime"
+ "strings"
+
+ "github.com/hashicorp/hcl/v2"
+ "github.com/hashicorp/packer-plugin-sdk/didyoumean"
+ pluginsdk "github.com/hashicorp/packer-plugin-sdk/plugin"
+ plugingetter "github.com/hashicorp/packer/packer/plugin-getter"
+)
+
+// PluginRequirements returns a sorted list of plugin requirements.
+func (cfg *PackerConfig) PluginRequirements() (plugingetter.Requirements, hcl.Diagnostics) {
+
+ var diags hcl.Diagnostics
+ var reqs plugingetter.Requirements
+ reqPluginsBlocks := cfg.Packer.RequiredPlugins
+
+ // Take all required plugins, make sure there are no conflicting blocks
+ // and append them to the list.
+ uniq := map[string]*RequiredPlugin{}
+ for _, requiredPluginsBlock := range reqPluginsBlocks {
+ for name, block := range requiredPluginsBlock.RequiredPlugins {
+
+ if previouslySeenBlock, found := uniq[name]; found {
+ diags = append(diags, &hcl.Diagnostic{
+ Severity: hcl.DiagError,
+ Summary: fmt.Sprintf("Duplicate required_plugin.%q block", name),
+ Detail: fmt.Sprintf("Block previously seen at %s is already named %q.\n", previouslySeenBlock.DeclRange, name) +
+ "Names at the left hand side of required_plugins are made available to use in your HCL2 configurations.\n" +
+ "To allow to calling to their features correctly two plugins have to have different accessors.",
+ Context: &block.DeclRange,
+ })
+ continue
+ }
+
+ reqs = append(reqs, &plugingetter.Requirement{
+ Accessor: name,
+ Identifier: block.Type,
+ VersionConstraints: block.Requirement.Required,
+ })
+ uniq[name] = block
+ }
+
+ }
+
+ return reqs, diags
+}
+
+func (cfg *PackerConfig) DetectPluginBinaries() hcl.Diagnostics {
+ opts := plugingetter.ListInstallationsOptions{
+ FromFolders: cfg.parser.PluginConfig.KnownPluginFolders,
+ BinaryInstallationOptions: plugingetter.BinaryInstallationOptions{
+ OS: runtime.GOOS,
+ ARCH: runtime.GOARCH,
+ APIVersionMajor: pluginsdk.APIVersionMajor,
+ APIVersionMinor: pluginsdk.APIVersionMinor,
+ Checksummers: []plugingetter.Checksummer{
+ {Type: "sha256", Hash: sha256.New()},
+ },
+ },
+ }
+
+ if runtime.GOOS == "windows" && opts.Ext == "" {
+ opts.BinaryInstallationOptions.Ext = ".exe"
+ }
+
+ pluginReqs, diags := cfg.PluginRequirements()
+ if diags.HasErrors() {
+ return diags
+ }
+
+ uninstalledPlugins := map[string]string{}
+
+ for _, pluginRequirement := range pluginReqs {
+ sortedInstalls, err := pluginRequirement.ListInstallations(opts)
+ if err != nil {
+ diags = append(diags, &hcl.Diagnostic{
+ Severity: hcl.DiagError,
+ Summary: fmt.Sprintf("Failed to list installation for %s", pluginRequirement.Identifier),
+ Detail: err.Error(),
+ })
+ continue
+ }
+ if len(sortedInstalls) == 0 {
+ uninstalledPlugins[pluginRequirement.Identifier.String()] = pluginRequirement.VersionConstraints.String()
+ continue
+ }
+ log.Printf("[TRACE] Found the following %q installations: %v", pluginRequirement.Identifier, sortedInstalls)
+ install := sortedInstalls[len(sortedInstalls)-1]
+ err = cfg.parser.PluginConfig.DiscoverMultiPlugin(pluginRequirement.Accessor, install.BinaryPath)
+ if err != nil {
+ diags = append(diags, &hcl.Diagnostic{
+ Severity: hcl.DiagError,
+ Summary: fmt.Sprintf("Error discovering plugin %s", pluginRequirement.Identifier),
+ Detail: err.Error(),
+ })
+ continue
+ }
+ }
+
+ if len(uninstalledPlugins) > 0 {
+ detailMessage := &strings.Builder{}
+ detailMessage.WriteString("The following plugins are required, but not installed:\n\n")
+ for pluginName, pluginVersion := range uninstalledPlugins {
+ fmt.Fprintf(detailMessage, "* %s %s\n", pluginName, pluginVersion)
+ }
+ detailMessage.WriteString("\nDid you run packer init for this project ?")
+ diags = append(diags, &hcl.Diagnostic{
+ Severity: hcl.DiagError,
+ Summary: "Missing plugins",
+ Detail: detailMessage.String(),
+ })
+ }
+
+ return diags
+}
+
+func (cfg *PackerConfig) initializeBlocks() hcl.Diagnostics {
+ // verify that all used plugins do exist
+ var diags hcl.Diagnostics
+
+ for _, build := range cfg.Builds {
+ for i := range build.Sources {
+ // here we grab a pointer to the source usage because we will set
+ // its body.
+ srcUsage := &(build.Sources[i])
+ if !cfg.parser.PluginConfig.Builders.Has(srcUsage.Type) {
+ diags = append(diags, &hcl.Diagnostic{
+ Summary: "Unknown " + buildSourceLabel + " type " + srcUsage.Type,
+ Subject: &build.HCL2Ref.DefRange,
+ Detail: fmt.Sprintf("known builders: %v", cfg.parser.PluginConfig.Builders.List()),
+ Severity: hcl.DiagError,
+ })
+ continue
+ }
+
+ sourceDefinition, found := cfg.Sources[srcUsage.SourceRef]
+ if !found {
+ availableSrcs := listAvailableSourceNames(cfg.Sources)
+ detail := fmt.Sprintf("Known: %v", availableSrcs)
+ if sugg := didyoumean.NameSuggestion(srcUsage.SourceRef.String(), availableSrcs); sugg != "" {
+ detail = fmt.Sprintf("Did you mean to use %q?", sugg)
+ }
+ diags = append(diags, &hcl.Diagnostic{
+ Summary: "Unknown " + sourceLabel + " " + srcUsage.SourceRef.String(),
+ Subject: build.HCL2Ref.DefRange.Ptr(),
+ Severity: hcl.DiagError,
+ Detail: detail,
+ })
+ continue
+ }
+
+ body := sourceDefinition.block.Body
+ if srcUsage.Body != nil {
+ // merge additions into source definition to get a new body.
+ body = hcl.MergeBodies([]hcl.Body{body, srcUsage.Body})
+ }
+
+ srcUsage.Body = body
+ }
+
+ for _, provBlock := range build.ProvisionerBlocks {
+ if !cfg.parser.PluginConfig.Provisioners.Has(provBlock.PType) {
+ diags = append(diags, &hcl.Diagnostic{
+ Summary: fmt.Sprintf("Unknown "+buildProvisionerLabel+" type %q", provBlock.PType),
+ Subject: provBlock.HCL2Ref.TypeRange.Ptr(),
+ Detail: fmt.Sprintf("known "+buildProvisionerLabel+"s: %v", cfg.parser.PluginConfig.Provisioners.List()),
+ Severity: hcl.DiagError,
+ })
+ }
+ }
+
+ if build.ErrorCleanupProvisionerBlock != nil {
+ if !cfg.parser.PluginConfig.Provisioners.Has(build.ErrorCleanupProvisionerBlock.PType) {
+ diags = append(diags, &hcl.Diagnostic{
+ Summary: fmt.Sprintf("Unknown "+buildErrorCleanupProvisionerLabel+" type %q", build.ErrorCleanupProvisionerBlock.PType),
+ Subject: build.ErrorCleanupProvisionerBlock.HCL2Ref.TypeRange.Ptr(),
+ Detail: fmt.Sprintf("known "+buildErrorCleanupProvisionerLabel+"s: %v", cfg.parser.PluginConfig.Provisioners.List()),
+ Severity: hcl.DiagError,
+ })
+ }
+ }
+
+ for _, ppList := range build.PostProcessorsLists {
+ for _, ppBlock := range ppList {
+ if !cfg.parser.PluginConfig.PostProcessors.Has(ppBlock.PType) {
+ diags = append(diags, &hcl.Diagnostic{
+ Summary: fmt.Sprintf("Unknown "+buildPostProcessorLabel+" type %q", ppBlock.PType),
+ Subject: ppBlock.HCL2Ref.TypeRange.Ptr(),
+ Detail: fmt.Sprintf("known "+buildPostProcessorLabel+"s: %v", cfg.parser.PluginConfig.PostProcessors.List()),
+ Severity: hcl.DiagError,
+ })
+ }
+ }
+ }
+
+ }
+
+ return diags
+}
diff --git a/v1.9.4/hcl2template/repl/format.go b/v1.9.4/hcl2template/repl/format.go
new file mode 100644
index 0000000..8e596e4
--- /dev/null
+++ b/v1.9.4/hcl2template/repl/format.go
@@ -0,0 +1,109 @@
+// Copyright (c) HashiCorp, Inc.
+// SPDX-License-Identifier: MPL-2.0
+
+package repl
+
+import (
+ "bufio"
+ "bytes"
+ "fmt"
+ "sort"
+ "strconv"
+ "strings"
+)
+
+// FormatResult formats the given result value for human-readable output.
+//
+// The value must currently be a string, list, map, and any nested values
+// with those same types.
+func FormatResult(value interface{}) string {
+ return formatResult(value, false)
+}
+
+func formatResult(value interface{}, nested bool) string {
+ if value == nil {
+ return "null"
+ }
+ switch output := value.(type) {
+ case string:
+ if nested {
+ return fmt.Sprintf("%q", output)
+ }
+ return output
+ case int:
+ return strconv.Itoa(output)
+ case float64:
+ return fmt.Sprintf("%g", output)
+ case bool:
+ switch {
+ case output == true:
+ return "true"
+ default:
+ return "false"
+ }
+ case []interface{}:
+ return formatListResult(output)
+ case map[string]interface{}:
+ return formatMapResult(output)
+ default:
+ return "<unknown-type>"
+ }
+}
+
+func formatListResult(value []interface{}) string {
+ var outputBuf bytes.Buffer
+ outputBuf.WriteString("[")
+ if len(value) > 0 {
+ outputBuf.WriteString("\n")
+ }
+
+ for _, v := range value {
+ raw := formatResult(v, true)
+ outputBuf.WriteString(indent(raw))
+ outputBuf.WriteString(",\n")
+ }
+
+ outputBuf.WriteString("]")
+ return outputBuf.String()
+}
+
+func formatMapResult(value map[string]interface{}) string {
+ ks := make([]string, 0, len(value))
+ for k := range value {
+ ks = append(ks, k)
+ }
+ sort.Strings(ks)
+
+ var outputBuf bytes.Buffer
+ outputBuf.WriteString("{")
+ if len(value) > 0 {
+ outputBuf.WriteString("\n")
+ }
+
+ for _, k := range ks {
+ v := value[k]
+ rawK := formatResult(k, true)
+ rawV := formatResult(v, true)
+
+ outputBuf.WriteString(indent(fmt.Sprintf("%s = %s", rawK, rawV)))
+ outputBuf.WriteString("\n")
+ }
+
+ outputBuf.WriteString("}")
+ return outputBuf.String()
+}
+
+func indent(value string) string {
+ var outputBuf bytes.Buffer
+ s := bufio.NewScanner(strings.NewReader(value))
+ newline := false
+ for s.Scan() {
+ if newline {
+ outputBuf.WriteByte('\n')
+ }
+ outputBuf.WriteString(" " + s.Text())
+ newline = true
+ }
+
+ return outputBuf.String()
+}
diff --git a/v1.9.4/hcl2template/repl/repl.go b/v1.9.4/hcl2template/repl/repl.go
new file mode 100644
index 0000000..7a698f8
--- /dev/null
+++ b/v1.9.4/hcl2template/repl/repl.go
@@ -0,0 +1,7 @@
+// Copyright (c) HashiCorp, Inc.
+// SPDX-License-Identifier: MPL-2.0
+
+// Package repl provides the structs and functions necessary to run REPL for
+// HCL2. The REPL allows experimentation of HCL2 interpolations without having
+// to run a HCL2 configuration.
+package repl
diff --git a/v1.9.4/hcl2template/shim/mock.go b/v1.9.4/hcl2template/shim/mock.go
new file mode 100644
index 0000000..adeda84
--- /dev/null
+++ b/v1.9.4/hcl2template/shim/mock.go
@@ -0,0 +1,43 @@
+// Copyright (c) HashiCorp, Inc.
+// SPDX-License-Identifier: MPL-2.0
+
+//go:generate packer-sdc mapstructure-to-hcl2 -type MockConfig,NestedMockConfig,MockTag
+
+package hcl2shim
+
+import (
+ "time"
+
+ "github.com/hashicorp/packer-plugin-sdk/template/config"
+)
+
+type NestedMockConfig struct {
+ String string `mapstructure:"string"`
+ Int int `mapstructure:"int"`
+ Int64 int64 `mapstructure:"int64"`
+ Bool bool `mapstructure:"bool"`
+ Trilean config.Trilean `mapstructure:"trilean"`
+ Duration time.Duration `mapstructure:"duration"`
+ MapStringString map[string]string `mapstructure:"map_string_string"`
+ SliceString []string `mapstructure:"slice_string"`
+ SliceSliceString [][]string `mapstructure:"slice_slice_string"`
+ NamedMapStringString NamedMapStringString `mapstructure:"named_map_string_string"`
+ NamedString NamedString `mapstructure:"named_string"`
+ Tags []MockTag `mapstructure:"tag"`
+ Datasource string `mapstructure:"data_source"`
+}
+
+type MockTag struct {
+ Key string `mapstructure:"key"`
+ Value string `mapstructure:"value"`
+}
+
+type MockConfig struct {
+ NotSquashed string `mapstructure:"not_squashed"`
+ NestedMockConfig `mapstructure:",squash"`
+ Nested NestedMockConfig `mapstructure:"nested"`
+ NestedSlice []NestedMockConfig `mapstructure:"nested_slice"`
+}
+
+type NamedMapStringString map[string]string
+type NamedString string
diff --git a/v1.9.4/hcl2template/shim/mock.hcl2spec.go b/v1.9.4/hcl2template/shim/mock.hcl2spec.go
new file mode 100644
index 0000000..3dadeca
--- /dev/null
+++ b/v1.9.4/hcl2template/shim/mock.hcl2spec.go
@@ -0,0 +1,133 @@
+// Code generated by "packer-sdc mapstructure-to-hcl2"; DO NOT EDIT.
+
+package hcl2shim
+
+import (
+ "github.com/hashicorp/hcl/v2/hcldec"
+ "github.com/zclconf/go-cty/cty"
+)
+
+// FlatMockConfig is an auto-generated flat version of MockConfig.
+// Where the contents of a field with a `mapstructure:,squash` tag are bubbled up.
+type FlatMockConfig struct {
+ NotSquashed *string `mapstructure:"not_squashed" cty:"not_squashed" hcl:"not_squashed"`
+ String *string `mapstructure:"string" cty:"string" hcl:"string"`
+ Int *int `mapstructure:"int" cty:"int" hcl:"int"`
+ Int64 *int64 `mapstructure:"int64" cty:"int64" hcl:"int64"`
+ Bool *bool `mapstructure:"bool" cty:"bool" hcl:"bool"`
+ Trilean *bool `mapstructure:"trilean" cty:"trilean" hcl:"trilean"`
+ Duration *string `mapstructure:"duration" cty:"duration" hcl:"duration"`
+ MapStringString map[string]string `mapstructure:"map_string_string" cty:"map_string_string" hcl:"map_string_string"`
+ SliceString []string `mapstructure:"slice_string" cty:"slice_string" hcl:"slice_string"`
+ SliceSliceString [][]string `mapstructure:"slice_slice_string" cty:"slice_slice_string" hcl:"slice_slice_string"`
+ NamedMapStringString NamedMapStringString `mapstructure:"named_map_string_string" cty:"named_map_string_string" hcl:"named_map_string_string"`
+ NamedString *NamedString `mapstructure:"named_string" cty:"named_string" hcl:"named_string"`
+ Tags []FlatMockTag `mapstructure:"tag" cty:"tag" hcl:"tag"`
+ Datasource *string `mapstructure:"data_source" cty:"data_source" hcl:"data_source"`
+ Nested *FlatNestedMockConfig `mapstructure:"nested" cty:"nested" hcl:"nested"`
+ NestedSlice []FlatNestedMockConfig `mapstructure:"nested_slice" cty:"nested_slice" hcl:"nested_slice"`
+}
+
+// FlatMapstructure returns a new FlatMockConfig.
+// FlatMockConfig is an auto-generated flat version of MockConfig.
+// Where the contents a fields with a `mapstructure:,squash` tag are bubbled up.
+func (*MockConfig) FlatMapstructure() interface{ HCL2Spec() map[string]hcldec.Spec } {
+ return new(FlatMockConfig)
+}
+
+// HCL2Spec returns the hcl spec of a MockConfig.
+// This spec is used by HCL to read the fields of MockConfig.
+// The decoded values from this spec will then be applied to a FlatMockConfig.
+func (*FlatMockConfig) HCL2Spec() map[string]hcldec.Spec {
+ s := map[string]hcldec.Spec{
+ "not_squashed": &hcldec.AttrSpec{Name: "not_squashed", Type: cty.String, Required: false},
+ "string": &hcldec.AttrSpec{Name: "string", Type: cty.String, Required: false},
+ "int": &hcldec.AttrSpec{Name: "int", Type: cty.Number, Required: false},
+ "int64": &hcldec.AttrSpec{Name: "int64", Type: cty.Number, Required: false},
+ "bool": &hcldec.AttrSpec{Name: "bool", Type: cty.Bool, Required: false},
+ "trilean": &hcldec.AttrSpec{Name: "trilean", Type: cty.Bool, Required: false},
+ "duration": &hcldec.AttrSpec{Name: "duration", Type: cty.String, Required: false},
+ "map_string_string": &hcldec.AttrSpec{Name: "map_string_string", Type: cty.Map(cty.String), Required: false},
+ "slice_string": &hcldec.AttrSpec{Name: "slice_string", Type: cty.List(cty.String), Required: false},
+ "slice_slice_string": &hcldec.AttrSpec{Name: "slice_slice_string", Type: cty.List(cty.List(cty.String)), Required: false},
+ "named_map_string_string": &hcldec.AttrSpec{Name: "named_map_string_string", Type: cty.Map(cty.String), Required: false},
+ "named_string": &hcldec.AttrSpec{Name: "named_string", Type: cty.String, Required: false},
+ "tag": &hcldec.BlockListSpec{TypeName: "tag", Nested: hcldec.ObjectSpec((*FlatMockTag)(nil).HCL2Spec())},
+ "data_source": &hcldec.AttrSpec{Name: "data_source", Type: cty.String, Required: false},
+ "nested": &hcldec.BlockSpec{TypeName: "nested", Nested: hcldec.ObjectSpec((*FlatNestedMockConfig)(nil).HCL2Spec())},
+ "nested_slice": &hcldec.BlockListSpec{TypeName: "nested_slice", Nested: hcldec.ObjectSpec((*FlatNestedMockConfig)(nil).HCL2Spec())},
+ }
+ return s
+}
+
+// FlatMockTag is an auto-generated flat version of MockTag.
+// Where the contents of a field with a `mapstructure:,squash` tag are bubbled up.
+type FlatMockTag struct {
+ Key *string `mapstructure:"key" cty:"key" hcl:"key"`
+ Value *string `mapstructure:"value" cty:"value" hcl:"value"`
+}
+
+// FlatMapstructure returns a new FlatMockTag.
+// FlatMockTag is an auto-generated flat version of MockTag.
+// Where the contents a fields with a `mapstructure:,squash` tag are bubbled up.
+func (*MockTag) FlatMapstructure() interface{ HCL2Spec() map[string]hcldec.Spec } {
+ return new(FlatMockTag)
+}
+
+// HCL2Spec returns the hcl spec of a MockTag.
+// This spec is used by HCL to read the fields of MockTag.
+// The decoded values from this spec will then be applied to a FlatMockTag.
+func (*FlatMockTag) HCL2Spec() map[string]hcldec.Spec {
+ s := map[string]hcldec.Spec{
+ "key": &hcldec.AttrSpec{Name: "key", Type: cty.String, Required: false},
+ "value": &hcldec.AttrSpec{Name: "value", Type: cty.String, Required: false},
+ }
+ return s
+}
+
+// FlatNestedMockConfig is an auto-generated flat version of NestedMockConfig.
+// Where the contents of a field with a `mapstructure:,squash` tag are bubbled up.
+type FlatNestedMockConfig struct {
+ String *string `mapstructure:"string" cty:"string" hcl:"string"`
+ Int *int `mapstructure:"int" cty:"int" hcl:"int"`
+ Int64 *int64 `mapstructure:"int64" cty:"int64" hcl:"int64"`
+ Bool *bool `mapstructure:"bool" cty:"bool" hcl:"bool"`
+ Trilean *bool `mapstructure:"trilean" cty:"trilean" hcl:"trilean"`
+ Duration *string `mapstructure:"duration" cty:"duration" hcl:"duration"`
+ MapStringString map[string]string `mapstructure:"map_string_string" cty:"map_string_string" hcl:"map_string_string"`
+ SliceString []string `mapstructure:"slice_string" cty:"slice_string" hcl:"slice_string"`
+ SliceSliceString [][]string `mapstructure:"slice_slice_string" cty:"slice_slice_string" hcl:"slice_slice_string"`
+ NamedMapStringString NamedMapStringString `mapstructure:"named_map_string_string" cty:"named_map_string_string" hcl:"named_map_string_string"`
+ NamedString *NamedString `mapstructure:"named_string" cty:"named_string" hcl:"named_string"`
+ Tags []FlatMockTag `mapstructure:"tag" cty:"tag" hcl:"tag"`
+ Datasource *string `mapstructure:"data_source" cty:"data_source" hcl:"data_source"`
+}
+
+// FlatMapstructure returns a new FlatNestedMockConfig.
+// FlatNestedMockConfig is an auto-generated flat version of NestedMockConfig.
+// Where the contents a fields with a `mapstructure:,squash` tag are bubbled up.
+func (*NestedMockConfig) FlatMapstructure() interface{ HCL2Spec() map[string]hcldec.Spec } {
+ return new(FlatNestedMockConfig)
+}
+
+// HCL2Spec returns the hcl spec of a NestedMockConfig.
+// This spec is used by HCL to read the fields of NestedMockConfig.
+// The decoded values from this spec will then be applied to a FlatNestedMockConfig.
+func (*FlatNestedMockConfig) HCL2Spec() map[string]hcldec.Spec {
+ s := map[string]hcldec.Spec{
+ "string": &hcldec.AttrSpec{Name: "string", Type: cty.String, Required: false},
+ "int": &hcldec.AttrSpec{Name: "int", Type: cty.Number, Required: false},
+ "int64": &hcldec.AttrSpec{Name: "int64", Type: cty.Number, Required: false},
+ "bool": &hcldec.AttrSpec{Name: "bool", Type: cty.Bool, Required: false},
+ "trilean": &hcldec.AttrSpec{Name: "trilean", Type: cty.Bool, Required: false},
+ "duration": &hcldec.AttrSpec{Name: "duration", Type: cty.String, Required: false},
+ "map_string_string": &hcldec.AttrSpec{Name: "map_string_string", Type: cty.Map(cty.String), Required: false},
+ "slice_string": &hcldec.AttrSpec{Name: "slice_string", Type: cty.List(cty.String), Required: false},
+ "slice_slice_string": &hcldec.AttrSpec{Name: "slice_slice_string", Type: cty.List(cty.List(cty.String)), Required: false},
+ "named_map_string_string": &hcldec.AttrSpec{Name: "named_map_string_string", Type: cty.Map(cty.String), Required: false},
+ "named_string": &hcldec.AttrSpec{Name: "named_string", Type: cty.String, Required: false},
+ "tag": &hcldec.BlockListSpec{TypeName: "tag", Nested: hcldec.ObjectSpec((*FlatMockTag)(nil).HCL2Spec())},
+ "data_source": &hcldec.AttrSpec{Name: "data_source", Type: cty.String, Required: false},
+ }
+ return s
+}
diff --git a/v1.9.4/hcl2template/shim/values.go b/v1.9.4/hcl2template/shim/values.go
new file mode 100644
index 0000000..88580f1
--- /dev/null
+++ b/v1.9.4/hcl2template/shim/values.go
@@ -0,0 +1,187 @@
+// Copyright (c) HashiCorp, Inc.
+// SPDX-License-Identifier: MPL-2.0
+
+package hcl2shim
+
+import (
+ "fmt"
+ "math/big"
+
+ "github.com/hashicorp/packer-plugin-sdk/hcl2helper"
+ "github.com/zclconf/go-cty/cty"
+)
+
+// ConfigValueFromHCL2 converts a value from HCL2 (really, from the cty dynamic
+// types library that HCL2 uses) to a value type that matches what would've
+// been produced from the HCL-based interpolator for an equivalent structure.
+//
+// This function will transform a cty null value into a Go nil value, which
+// isn't a possible outcome of the HCL/HIL-based decoder and so callers may
+// need to detect and reject any null values.
+func ConfigValueFromHCL2(v cty.Value) interface{} {
+ if !v.IsKnown() {
+ return hcl2helper.UnknownVariableValue
+ }
+ if v.IsNull() {
+ return nil
+ }
+
+ switch v.Type() {
+ case cty.Bool:
+ return v.True() // like HCL.BOOL
+ case cty.String:
+ return v.AsString() // like HCL token.STRING or token.HEREDOC
+ case cty.Number:
+ // We can't match HCL _exactly_ here because it distinguishes between
+ // int and float values, but we'll get as close as we can by using
+ // an int if the number is exactly representable, and a float if not.
+ // The conversion to float will force precision to that of a float64,
+ // which is potentially losing information from the specific number
+ // given, but no worse than what HCL would've done in its own conversion
+ // to float.
+
+ f := v.AsBigFloat()
+ if i, acc := f.Int64(); acc == big.Exact {
+ // if we're on a 32-bit system and the number is too big for 32-bit
+ // int then we'll fall through here and use a float64.
+ const MaxInt = int(^uint(0) >> 1)
+ const MinInt = -MaxInt - 1
+ if i <= int64(MaxInt) && i >= int64(MinInt) {
+ return int(i) // Like HCL token.NUMBER
+ }
+ }
+
+ f64, _ := f.Float64()
+ return f64 // like HCL token.FLOAT
+ }
+
+ if v.Type().IsListType() || v.Type().IsSetType() || v.Type().IsTupleType() {
+ l := make([]interface{}, 0, v.LengthInt())
+ it := v.ElementIterator()
+ for it.Next() {
+ _, ev := it.Element()
+ l = append(l, ConfigValueFromHCL2(ev))
+ }
+ return l
+ }
+
+ if v.Type().IsMapType() || v.Type().IsObjectType() {
+ l := make(map[string]interface{})
+ it := v.ElementIterator()
+ for it.Next() {
+ ek, ev := it.Element()
+ cv := ConfigValueFromHCL2(ev)
+ if cv != nil {
+ l[ek.AsString()] = cv
+ }
+ }
+ return l
+ }
+
+ // If we fall out here then we have some weird type that we haven't
+ // accounted for. This should never happen unless the caller is using
+ // capsule types, and we don't currently have any such types defined.
+ panic(fmt.Errorf("can't convert %#v to config value", v))
+}
+
+// WriteUnknownPlaceholderValues will replace every Unknown value with a equivalent placeholder.
+// This is useful to use before marshaling the value to JSON. The default values are:
+// - string: "<unknown>"
+// - number: 0
+// - bool: false
+// - objects/lists/tuples/sets/maps: empty
+func WriteUnknownPlaceholderValues(v cty.Value) cty.Value {
+ if v.IsNull() {
+ return v
+ }
+ t := v.Type()
+ switch {
+ case t.IsPrimitiveType():
+ if v.IsKnown() {
+ return v
+ }
+ switch t {
+ case cty.String:
+ return cty.StringVal("<unknown>")
+ case cty.Number:
+ return cty.MustParseNumberVal("0")
+ case cty.Bool:
+ return cty.BoolVal(false)
+ default:
+ panic("unsupported primitive type")
+ }
+ case t.IsListType():
+ if !v.IsKnown() {
+ return cty.ListValEmpty(t.ElementType())
+ }
+ arr := []cty.Value{}
+ it := v.ElementIterator()
+ for it.Next() {
+ _, ev := it.Element()
+ arr = append(arr, WriteUnknownPlaceholderValues(ev))
+ }
+ if len(arr) == 0 {
+ return cty.ListValEmpty(t.ElementType())
+ }
+ return cty.ListVal(arr)
+ case t.IsSetType():
+ if !v.IsKnown() {
+ return cty.SetValEmpty(t.ElementType())
+ }
+ arr := []cty.Value{}
+ it := v.ElementIterator()
+ for it.Next() {
+ _, ev := it.Element()
+ arr = append(arr, WriteUnknownPlaceholderValues(ev))
+ }
+ if len(arr) == 0 {
+ return cty.SetValEmpty(t.ElementType())
+ }
+ return cty.SetVal(arr)
+ case t.IsMapType():
+ if !v.IsKnown() {
+ return cty.MapValEmpty(t.ElementType())
+ }
+ obj := map[string]cty.Value{}
+ it := v.ElementIterator()
+ for it.Next() {
+ ek, ev := it.Element()
+ obj[ek.AsString()] = WriteUnknownPlaceholderValues(ev)
+ }
+ if len(obj) == 0 {
+ return cty.MapValEmpty(t.ElementType())
+ }
+ return cty.MapVal(obj)
+ case t.IsTupleType():
+ if !v.IsKnown() {
+ return cty.EmptyTupleVal
+ }
+ arr := []cty.Value{}
+ it := v.ElementIterator()
+ for it.Next() {
+ _, ev := it.Element()
+ arr = append(arr, WriteUnknownPlaceholderValues(ev))
+ }
+ if len(arr) == 0 {
+ return cty.EmptyTupleVal
+ }
+ return cty.TupleVal(arr)
+ case t.IsObjectType():
+ if !v.IsKnown() {
+ return cty.EmptyObjectVal
+ }
+ obj := map[string]cty.Value{}
+ it := v.ElementIterator()
+ for it.Next() {
+ ek, ev := it.Element()
+ obj[ek.AsString()] = WriteUnknownPlaceholderValues(ev)
+ }
+ if len(obj) == 0 {
+ return cty.EmptyObjectVal
+ }
+ return cty.ObjectVal(obj)
+ default:
+ // should never happen
+ panic("unknown type")
+ }
+}
diff --git a/v1.9.4/hcl2template/shim/values_test.go b/v1.9.4/hcl2template/shim/values_test.go
new file mode 100644
index 0000000..46e1540
--- /dev/null
+++ b/v1.9.4/hcl2template/shim/values_test.go
@@ -0,0 +1,237 @@
+// Copyright (c) HashiCorp, Inc.
+// SPDX-License-Identifier: MPL-2.0
+
+package hcl2shim
+
+import (
+ "fmt"
+ "reflect"
+ "testing"
+
+ "github.com/hashicorp/packer-plugin-sdk/hcl2helper"
+ "github.com/zclconf/go-cty/cty"
+)
+
+func TestConfigValueFromHCL2(t *testing.T) {
+ tests := []struct {
+ Input cty.Value
+ Want interface{}
+ }{
+ {
+ cty.True,
+ true,
+ },
+ {
+ cty.False,
+ false,
+ },
+ {
+ cty.NumberIntVal(12),
+ int(12),
+ },
+ {
+ cty.NumberFloatVal(12.5),
+ float64(12.5),
+ },
+ {
+ cty.StringVal("hello world"),
+ "hello world",
+ },
+ {
+ cty.ObjectVal(map[string]cty.Value{
+ "name": cty.StringVal("Ermintrude"),
+ "age": cty.NumberIntVal(19),
+ "address": cty.ObjectVal(map[string]cty.Value{
+ "street": cty.ListVal([]cty.Value{cty.StringVal("421 Shoreham Loop")}),
+ "city": cty.StringVal("Fridgewater"),
+ "state": cty.StringVal("MA"),
+ "zip": cty.StringVal("91037"),
+ }),
+ }),
+ map[string]interface{}{
+ "name": "Ermintrude",
+ "age": int(19),
+ "address": map[string]interface{}{
+ "street": []interface{}{"421 Shoreham Loop"},
+ "city": "Fridgewater",
+ "state": "MA",
+ "zip": "91037",
+ },
+ },
+ },
+ {
+ cty.MapVal(map[string]cty.Value{
+ "foo": cty.StringVal("bar"),
+ "bar": cty.StringVal("baz"),
+ }),
+ map[string]interface{}{
+ "foo": "bar",
+ "bar": "baz",
+ },
+ },
+ {
+ cty.TupleVal([]cty.Value{
+ cty.StringVal("foo"),
+ cty.True,
+ }),
+ []interface{}{
+ "foo",
+ true,
+ },
+ },
+ {
+ cty.NullVal(cty.String),
+ nil,
+ },
+ {
+ cty.UnknownVal(cty.String),
+ hcl2helper.UnknownVariableValue,
+ },
+ }
+
+ for _, test := range tests {
+ t.Run(fmt.Sprintf("%#v", test.Input), func(t *testing.T) {
+ got := ConfigValueFromHCL2(test.Input)
+ if !reflect.DeepEqual(got, test.Want) {
+ t.Errorf("wrong result\ninput: %#v\ngot: %#v\nwant: %#v", test.Input, got, test.Want)
+ }
+ })
+ }
+}
+
+func TestWriteUnknownPlaceholderValues(t *testing.T) {
+ tests := []struct {
+ Name string
+ Input cty.Value
+ Want cty.Value
+ }{
+ {
+ Name: "Unknown bool",
+ Input: cty.UnknownVal(cty.Bool),
+ Want: cty.False,
+ },
+ {
+ Name: "Unknown number",
+ Input: cty.UnknownVal(cty.Number),
+ Want: cty.NumberIntVal(0),
+ },
+ {
+ Name: "Unknown string",
+ Input: cty.UnknownVal(cty.String),
+ Want: cty.StringVal("<unknown>"),
+ },
+ {
+ Name: "Unknown object",
+ Input: cty.UnknownVal(cty.EmptyObject),
+ Want: cty.EmptyObjectVal,
+ },
+ {
+ Name: "Object with unknown values",
+ Input: cty.ObjectVal(map[string]cty.Value{
+ "name": cty.UnknownVal(cty.String),
+ "address": cty.UnknownVal(cty.EmptyObject),
+ }),
+ Want: cty.ObjectVal(map[string]cty.Value{
+ "name": cty.StringVal("<unknown>"),
+ "address": cty.EmptyObjectVal,
+ }),
+ },
+ {
+ Name: "Empty object",
+ Input: cty.ObjectVal(map[string]cty.Value{}),
+ Want: cty.EmptyObjectVal,
+ },
+ {
+ Name: "Unknown tuple",
+ Input: cty.UnknownVal(cty.EmptyTuple),
+ Want: cty.EmptyTupleVal,
+ },
+ {
+ Name: "Tuple with unknown values",
+ Input: cty.TupleVal([]cty.Value{
+ cty.UnknownVal(cty.String),
+ cty.UnknownVal(cty.Bool),
+ }),
+ Want: cty.TupleVal([]cty.Value{
+ cty.StringVal("<unknown>"),
+ cty.False,
+ }),
+ },
+ {
+ Name: "Empty tuple",
+ Input: cty.TupleVal([]cty.Value{}),
+ Want: cty.EmptyTupleVal,
+ },
+ {
+ Name: "Unknown list",
+ Input: cty.UnknownVal(cty.List(cty.String)),
+ Want: cty.ListValEmpty(cty.String),
+ },
+ {
+ Name: "List with unknown values",
+ Input: cty.ListVal([]cty.Value{
+ cty.UnknownVal(cty.String),
+ }),
+ Want: cty.ListVal([]cty.Value{
+ cty.StringVal("<unknown>"),
+ }),
+ },
+ {
+ Name: "Empty list",
+ Input: cty.ListValEmpty(cty.String),
+ Want: cty.ListValEmpty(cty.String),
+ },
+ {
+ Name: "Unknown set",
+ Input: cty.UnknownVal(cty.Set(cty.String)),
+ Want: cty.SetValEmpty(cty.String),
+ },
+ {
+ Name: "Set with unknown values",
+ Input: cty.SetVal([]cty.Value{
+ cty.UnknownVal(cty.String),
+ }),
+ Want: cty.SetVal([]cty.Value{
+ cty.StringVal("<unknown>"),
+ }),
+ },
+ {
+ Name: "Empty Set",
+ Input: cty.SetValEmpty(cty.String),
+ Want: cty.SetValEmpty(cty.String),
+ },
+ {
+ Name: "Unknown map",
+ Input: cty.UnknownVal(cty.Map(cty.String)),
+ Want: cty.MapValEmpty(cty.String),
+ },
+ {
+ Name: "Map with unknown values",
+ Input: cty.MapVal(map[string]cty.Value{
+ "name": cty.UnknownVal(cty.String),
+ }),
+ Want: cty.MapVal(map[string]cty.Value{
+ "name": cty.StringVal("<unknown>"),
+ }),
+ },
+ {
+ Name: "Empty Map",
+ Input: cty.MapValEmpty(cty.String),
+ Want: cty.MapValEmpty(cty.String),
+ },
+ {
+ Name: "Null val",
+ Input: cty.NullVal(cty.String),
+ Want: cty.NullVal(cty.String),
+ },
+ }
+
+ for _, test := range tests {
+ t.Run(t.Name(), func(t *testing.T) {
+ got := WriteUnknownPlaceholderValues(test.Input)
+ if got.Equals(test.Want).False() {
+ t.Errorf("wrong result\ninput: %#v\ngot: %#v\nwant: %#v", test.Input, got, test.Want)
+ }
+ })
+ }
+}
diff --git a/v1.9.4/hcl2template/testdata/build.pkr.hcl/basic.pkr.hcl b/v1.9.4/hcl2template/testdata/build.pkr.hcl/basic.pkr.hcl
new file mode 100644
index 0000000..782b6fb
--- /dev/null
+++ b/v1.9.4/hcl2template/testdata/build.pkr.hcl/basic.pkr.hcl
@@ -0,0 +1,125 @@
+
+// starts resources to provision them.
+build {
+ sources = [
+ "source.amazon-ebs.ubuntu-1604",
+ "source.virtualbox-iso.ubuntu-1204",
+ ]
+
+ provisioner "shell" {
+ string = lower("STRING")
+ int = 42
+ int64 = 43
+ bool = true
+ trilean = true
+ duration = "10s"
+ map_string_string = {
+ a = "b"
+ c = "d"
+ }
+ slice_string = [
+ "a",
+ "b",
+ "c",
+ ]
+
+ nested {
+ string = "string"
+ int = 42
+ int64 = 43
+ bool = true
+ trilean = true
+ duration = "10s"
+ map_string_string = {
+ a = "b"
+ c = "d"
+ }
+ slice_string = [
+ "a",
+ "b",
+ "c",
+ ]
+ }
+
+ nested_slice {
+ }
+ }
+
+ provisioner "file" {
+ string = "string"
+ int = 42
+ int64 = 43
+ bool = true
+ trilean = true
+ duration = "10s"
+ map_string_string = {
+ a = "b"
+ c = "d"
+ }
+ slice_string = [
+ "a",
+ "b",
+ "c",
+ ]
+
+ nested {
+ string = "string"
+ int = 42
+ int64 = 43
+ bool = true
+ trilean = true
+ duration = "10s"
+ map_string_string = {
+ a = "b"
+ c = "d"
+ }
+ slice_string = [
+ "a",
+ "b",
+ "c",
+ ]
+ }
+
+ nested_slice {
+ }
+ }
+
+ post-processor "amazon-import" {
+ string = "string"
+ int = 42
+ int64 = 43
+ bool = true
+ trilean = true
+ duration = "10s"
+ map_string_string = {
+ a = "b"
+ c = "d"
+ }
+ slice_string = [
+ "a",
+ "b",
+ "c",
+ ]
+
+ nested {
+ string = "string"
+ int = 42
+ int64 = 43
+ bool = true
+ trilean = true
+ duration = "10s"
+ map_string_string = {
+ a = "b"
+ c = "d"
+ }
+ slice_string = [
+ "a",
+ "b",
+ "c",
+ ]
+ }
+
+ nested_slice {
+ }
+ }
+}
diff --git a/v1.9.4/hcl2template/testdata/build/basic.pkr.hcl b/v1.9.4/hcl2template/testdata/build/basic.pkr.hcl
new file mode 100644
index 0000000..6b6510b
--- /dev/null
+++ b/v1.9.4/hcl2template/testdata/build/basic.pkr.hcl
@@ -0,0 +1,149 @@
+
+// starts resources to provision them.
+build {
+ sources = [
+ "source.amazon-ebs.ubuntu-1604",
+ "source.virtualbox-iso.ubuntu-1204",
+ ]
+
+ provisioner "shell" {
+ string = coalesce(null, "", "string")
+ int = "${41 + 1}"
+ int64 = "${42 + 1}"
+ bool = "true"
+ trilean = true
+ duration = "${9 + 1}s"
+ map_string_string = {
+ a = "b"
+ c = "d"
+ }
+ slice_string = [
+ "a",
+ "b",
+ "c",
+ ]
+ slice_slice_string = [
+ ["a","b"],
+ ["c","d"]
+ ]
+
+ nested {
+ string = "string"
+ int = 42
+ int64 = 43
+ bool = true
+ trilean = true
+ duration = "10s"
+ map_string_string = {
+ a = "b"
+ c = "d"
+ }
+ slice_string = [
+ "a",
+ "b",
+ "c",
+ ]
+ slice_slice_string = [
+ ["a","b"],
+ ["c","d"]
+ ]
+ }
+
+ nested_slice {
+ }
+ }
+
+ provisioner "file" {
+ string = "string"
+ int = 42
+ int64 = 43
+ bool = true
+ trilean = true
+ duration = "10s"
+ map_string_string = {
+ a = "b"
+ c = "d"
+ }
+ slice_string = [
+ "a",
+ "b",
+ "c",
+ ]
+ slice_slice_string = [
+ ["a","b"],
+ ["c","d"]
+ ]
+
+ nested {
+ string = "string"
+ int = 42
+ int64 = 43
+ bool = true
+ trilean = true
+ duration = "10s"
+ map_string_string = {
+ a = "b"
+ c = "d"
+ }
+ slice_string = [
+ "a",
+ "b",
+ "c",
+ ]
+ slice_slice_string = [
+ ["a","b"],
+ ["c","d"]
+ ]
+ }
+
+ nested_slice {
+ }
+ }
+
+ post-processor "amazon-import" {
+ string = "string"
+ int = 42
+ int64 = 43
+ bool = true
+ trilean = true
+ duration = "10s"
+ map_string_string = {
+ a = "b"
+ c = "d"
+ }
+ slice_string = [
+ "a",
+ "b",
+ "c",
+ ]
+ slice_slice_string = [
+ ["a","b"],
+ ["c","d"]
+ ]
+
+ nested {
+ string = "string"
+ int = 42
+ int64 = 43
+ bool = true
+ trilean = true
+ duration = "10s"
+ map_string_string = {
+ a = "b"
+ c = "d"
+ }
+ slice_string = [
+ "a",
+ "b",
+ "c",
+ ]
+ slice_slice_string = [
+ ["a","b"],
+ ["c","d"]
+ ]
+ }
+
+ nested_slice {
+ }
+ }
+}
diff --git a/v1.9.4/hcl2template/testdata/build/invalid_build_name_variable.pkr.hcl b/v1.9.4/hcl2template/testdata/build/invalid_build_name_variable.pkr.hcl
new file mode 100644
index 0000000..23459c2
--- /dev/null
+++ b/v1.9.4/hcl2template/testdata/build/invalid_build_name_variable.pkr.hcl
@@ -0,0 +1,9 @@
+variable "name" {
+ type = int
+ default = 123
+}
+
+build {
+ name = var.name
+}
+
diff --git a/v1.9.4/hcl2template/testdata/build/invalid_source_reference.pkr.hcl b/v1.9.4/hcl2template/testdata/build/invalid_source_reference.pkr.hcl
new file mode 100644
index 0000000..a1c28da
--- /dev/null
+++ b/v1.9.4/hcl2template/testdata/build/invalid_source_reference.pkr.hcl
@@ -0,0 +1,4 @@
+
+build {
+ sources = ["ami"]
+}
diff --git a/v1.9.4/hcl2template/testdata/build/named.pkr.hcl b/v1.9.4/hcl2template/testdata/build/named.pkr.hcl
new file mode 100644
index 0000000..ae6dca9
--- /dev/null
+++ b/v1.9.4/hcl2template/testdata/build/named.pkr.hcl
@@ -0,0 +1,8 @@
+build {
+ name = "somebuild"
+
+ sources = [
+ "source.amazon-ebs.ubuntu-1604",
+ "source.virtualbox-iso.ubuntu-1204",
+ ]
+}
diff --git a/v1.9.4/hcl2template/testdata/build/post-processor_build_name_interpolation.pkr.hcl b/v1.9.4/hcl2template/testdata/build/post-processor_build_name_interpolation.pkr.hcl
new file mode 100644
index 0000000..81799a2
--- /dev/null
+++ b/v1.9.4/hcl2template/testdata/build/post-processor_build_name_interpolation.pkr.hcl
@@ -0,0 +1,13 @@
+build {
+ name = "test-build"
+ sources = [ "source.virtualbox-iso.ubuntu-1204" ]
+
+ post-processor "manifest" {
+ name = build.name
+ slice_string = ["${packer.version}", "${build.name}"]
+ }
+
+}
+
+source "virtualbox-iso" "ubuntu-1204" {
+}
diff --git a/v1.9.4/hcl2template/testdata/build/post-processor_nonexistent.pkr.hcl b/v1.9.4/hcl2template/testdata/build/post-processor_nonexistent.pkr.hcl
new file mode 100644
index 0000000..4ea811f
--- /dev/null
+++ b/v1.9.4/hcl2template/testdata/build/post-processor_nonexistent.pkr.hcl
@@ -0,0 +1,9 @@
+source "null" "test" {}
+
+build {
+ sources = [ "null.test" ]
+
+ post-processor "nonexistent" {
+ foo = "bar"
+ }
+}
diff --git a/v1.9.4/hcl2template/testdata/build/post-processor_onlyexcept.pkr.hcl b/v1.9.4/hcl2template/testdata/build/post-processor_onlyexcept.pkr.hcl
new file mode 100644
index 0000000..b9ba018
--- /dev/null
+++ b/v1.9.4/hcl2template/testdata/build/post-processor_onlyexcept.pkr.hcl
@@ -0,0 +1,29 @@
+
+// starts resources to provision them.
+build {
+ sources = [
+ "source.virtualbox-iso.ubuntu-1204",
+ ]
+ source "source.amazon-ebs.ubuntu-1604" {
+ name = "aws-ubuntu-16.04"
+ }
+
+ post-processor "amazon-import" {
+ only = ["virtualbox-iso.ubuntu-1204"]
+ }
+ post-processor "manifest" {
+ except = ["virtualbox-iso.ubuntu-1204"]
+ }
+ post-processor "amazon-import" {
+ only = ["amazon-ebs.aws-ubuntu-16.04"]
+ }
+ post-processor "manifest" {
+ except = ["amazon-ebs.aws-ubuntu-16.04"]
+ }
+}
+
+source "virtualbox-iso" "ubuntu-1204" {
+}
+
+source "amazon-ebs" "ubuntu-1604" {
+}
diff --git a/v1.9.4/hcl2template/testdata/build/post-processor_untyped.pkr.hcl b/v1.9.4/hcl2template/testdata/build/post-processor_untyped.pkr.hcl
new file mode 100644
index 0000000..4b72336
--- /dev/null
+++ b/v1.9.4/hcl2template/testdata/build/post-processor_untyped.pkr.hcl
@@ -0,0 +1,6 @@
+
+build {
+ post-process {
+ foo = "bar"
+ }
+}
diff --git a/v1.9.4/hcl2template/testdata/build/provisioner_build_name_interpolation.pkr.hcl b/v1.9.4/hcl2template/testdata/build/provisioner_build_name_interpolation.pkr.hcl
new file mode 100644
index 0000000..79e2ca2
--- /dev/null
+++ b/v1.9.4/hcl2template/testdata/build/provisioner_build_name_interpolation.pkr.hcl
@@ -0,0 +1,17 @@
+
+// starts resources to provision them.
+build {
+ name = "build-name-test"
+ sources = [
+ "source.virtualbox-iso.ubuntu-1204",
+ ]
+
+ provisioner "shell" {
+ name = build.name
+ slice_string = ["${build.name}"]
+ }
+}
+
+source "virtualbox-iso" "ubuntu-1204" {
+}
+
diff --git a/v1.9.4/hcl2template/testdata/build/provisioner_nonexistent.pkr.hcl b/v1.9.4/hcl2template/testdata/build/provisioner_nonexistent.pkr.hcl
new file mode 100644
index 0000000..a8d4290
--- /dev/null
+++ b/v1.9.4/hcl2template/testdata/build/provisioner_nonexistent.pkr.hcl
@@ -0,0 +1,9 @@
+source "null" "test" {}
+
+build {
+ sources = [ "null.test" ]
+
+ provisioner "nonexistent" {
+ foo = "bar"
+ }
+}
diff --git a/v1.9.4/hcl2template/testdata/build/provisioner_onlyexcept.pkr.hcl b/v1.9.4/hcl2template/testdata/build/provisioner_onlyexcept.pkr.hcl
new file mode 100644
index 0000000..368375e
--- /dev/null
+++ b/v1.9.4/hcl2template/testdata/build/provisioner_onlyexcept.pkr.hcl
@@ -0,0 +1,29 @@
+
+// starts resources to provision them.
+build {
+ sources = [
+ "source.virtualbox-iso.ubuntu-1204",
+ ]
+ source "source.amazon-ebs.ubuntu-1604" {
+ name = "aws-ubuntu-16.04"
+ }
+
+ provisioner "shell" {
+ only = ["virtualbox-iso.ubuntu-1204"]
+ }
+ provisioner "file" {
+ except = ["virtualbox-iso.ubuntu-1204"]
+ }
+ provisioner "shell" {
+ only = ["amazon-ebs.aws-ubuntu-16.04"]
+ }
+ provisioner "file" {
+ except = ["amazon-ebs.aws-ubuntu-16.04"]
+ }
+}
+
+source "virtualbox-iso" "ubuntu-1204" {
+}
+
+source "amazon-ebs" "ubuntu-1604" {
+}
diff --git a/v1.9.4/hcl2template/testdata/build/provisioner_packer_version_interpolation.pkr.hcl b/v1.9.4/hcl2template/testdata/build/provisioner_packer_version_interpolation.pkr.hcl
new file mode 100644
index 0000000..01d93fa
--- /dev/null
+++ b/v1.9.4/hcl2template/testdata/build/provisioner_packer_version_interpolation.pkr.hcl
@@ -0,0 +1,15 @@
+
+// starts resources to provision them.
+build {
+ sources = [
+ "source.virtualbox-iso.ubuntu-1204",
+ ]
+
+ provisioner "shell" {
+ slice_string = ["{{packer_version}}"]
+ }
+}
+
+source "virtualbox-iso" "ubuntu-1204" {
+}
+
diff --git a/v1.9.4/hcl2template/testdata/build/provisioner_paused_before_retry.pkr.hcl b/v1.9.4/hcl2template/testdata/build/provisioner_paused_before_retry.pkr.hcl
new file mode 100644
index 0000000..04a8bbb
--- /dev/null
+++ b/v1.9.4/hcl2template/testdata/build/provisioner_paused_before_retry.pkr.hcl
@@ -0,0 +1,15 @@
+
+// starts resources to provision them.
+build {
+ sources = [
+ "source.virtualbox-iso.ubuntu-1204"
+ ]
+
+ provisioner "shell" {
+ pause_before = "10s"
+ max_retries = 5
+ }
+}
+
+source "virtualbox-iso" "ubuntu-1204" {
+}
\ No newline at end of file
diff --git a/v1.9.4/hcl2template/testdata/build/provisioner_timeout.pkr.hcl b/v1.9.4/hcl2template/testdata/build/provisioner_timeout.pkr.hcl
new file mode 100644
index 0000000..4779510
--- /dev/null
+++ b/v1.9.4/hcl2template/testdata/build/provisioner_timeout.pkr.hcl
@@ -0,0 +1,14 @@
+
+// starts resources to provision them.
+build {
+ sources = [
+ "source.virtualbox-iso.ubuntu-1204"
+ ]
+
+ provisioner "shell" {
+ timeout = "10s"
+ }
+}
+
+source "virtualbox-iso" "ubuntu-1204" {
+}
\ No newline at end of file
diff --git a/v1.9.4/hcl2template/testdata/build/provisioner_untyped.pkr.hcl b/v1.9.4/hcl2template/testdata/build/provisioner_untyped.pkr.hcl
new file mode 100644
index 0000000..33a9fdb
--- /dev/null
+++ b/v1.9.4/hcl2template/testdata/build/provisioner_untyped.pkr.hcl
@@ -0,0 +1,6 @@
+
+build {
+ provision {
+ foo = "bar"
+ }
+}
diff --git a/v1.9.4/hcl2template/testdata/build/two-error-cleanup-provisioner.pkr.hcl b/v1.9.4/hcl2template/testdata/build/two-error-cleanup-provisioner.pkr.hcl
new file mode 100644
index 0000000..588bcf0
--- /dev/null
+++ b/v1.9.4/hcl2template/testdata/build/two-error-cleanup-provisioner.pkr.hcl
@@ -0,0 +1,15 @@
+source "virtualbox-iso" "ubuntu-1204" {
+}
+
+// starts resources to provision them.
+build {
+ sources = [
+ "source.virtualbox-iso.ubuntu-1204"
+ ]
+
+ error-cleanup-provisioner "shell-local" {
+ }
+
+ error-cleanup-provisioner "file" {
+ }
+}
diff --git a/v1.9.4/hcl2template/testdata/build/variables.pkr.hcl b/v1.9.4/hcl2template/testdata/build/variables.pkr.hcl
new file mode 100644
index 0000000..eb4d72a
--- /dev/null
+++ b/v1.9.4/hcl2template/testdata/build/variables.pkr.hcl
@@ -0,0 +1,21 @@
+variable "name" {
+ type = string
+ default = "build-name"
+}
+
+local "description" {
+ expression = "This is the description for ${var.name}."
+}
+
+build {
+ name = var.name
+ description = local.description
+
+ sources = [
+ "source.virtualbox-iso.ubuntu-1204"
+ ]
+}
+
+source "virtualbox-iso" "ubuntu-1204" {
+}
+
diff --git a/v1.9.4/hcl2template/testdata/communicator/basic.pkr.hcl b/v1.9.4/hcl2template/testdata/communicator/basic.pkr.hcl
new file mode 100644
index 0000000..0505218
--- /dev/null
+++ b/v1.9.4/hcl2template/testdata/communicator/basic.pkr.hcl
@@ -0,0 +1,39 @@
+
+communicator "ssh" "vagrant" {
+ string = "string"
+ int = 42
+ int64 = 43
+ bool = true
+ trilean = true
+ duration = "10s"
+ map_string_string = {
+ a = "b"
+ c = "d"
+ }
+ slice_string = [
+ "a",
+ "b",
+ "c",
+ ]
+
+ nested {
+ string = "string"
+ int = 42
+ int64 = 43
+ bool = true
+ trilean = true
+ duration = "10s"
+ map_string_string = {
+ a = "b"
+ c = "d"
+ }
+ slice_string = [
+ "a",
+ "b",
+ "c",
+ ]
+ }
+
+ nested_slice {
+ }
+}
diff --git a/v1.9.4/hcl2template/testdata/complete/build.pkr.hcl b/v1.9.4/hcl2template/testdata/complete/build.pkr.hcl
new file mode 100644
index 0000000..9f0f77f
--- /dev/null
+++ b/v1.9.4/hcl2template/testdata/complete/build.pkr.hcl
@@ -0,0 +1,494 @@
+
+packer {
+ required_version = ">= v1"
+}
+
+// starts resources to provision them.
+build {
+ sources = [
+ "source.virtualbox-iso.ubuntu-1204",
+ ]
+
+ source "source.amazon-ebs.ubuntu-1604" {
+ string = "setting from build section"
+ nested {
+ dynamic "tag" {
+ for_each = local.standard_tags
+ content {
+ key = tag.key
+ value = tag.value
+ }
+ }
+ }
+ }
+
+ provisioner "shell" {
+ name = "provisioner that does something"
+ not_squashed = "${var.foo} ${upper(build.ID)}"
+ string = "string"
+ int = "${41 + 1}"
+ int64 = "${42 + 1}"
+ bool = "true"
+ trilean = true
+ duration = "${9 + 1}s"
+ map_string_string = {
+ a = "b"
+ c = "d"
+ }
+ slice_string = [for s in var.availability_zone_names : lower(s)]
+ slice_slice_string = [
+ ["a","b"],
+ ["c","d"]
+ ]
+
+ nested {
+ string = "string"
+ int = 42
+ int64 = 43
+ bool = true
+ trilean = true
+ duration = "10s"
+ map_string_string = {
+ a = "b"
+ c = "d"
+ }
+ slice_string = [for s in var.availability_zone_names : lower(s)]
+ slice_slice_string = [
+ ["a","b"],
+ ["c","d"]
+ ]
+ }
+
+ nested_slice {
+ tag {
+ key = "first_tag_key"
+ value = "first_tag_value"
+ }
+ dynamic "tag" {
+ for_each = local.standard_tags
+ content {
+ key = tag.key
+ value = tag.value
+ }
+ }
+ }
+ }
+
+ provisioner "file" {
+ not_squashed = "${var.foo} ${upper(build.ID)}"
+ string = "string"
+ int = 42
+ int64 = 43
+ bool = true
+ trilean = true
+ duration = "10s"
+ map_string_string = {
+ a = "b"
+ c = "d"
+ }
+ slice_string = local.abc_map[*].id
+ slice_slice_string = [
+ ["a","b"],
+ ["c","d"]
+ ]
+
+ nested {
+ string = "string"
+ int = 42
+ int64 = 43
+ bool = true
+ trilean = true
+ duration = "10s"
+ map_string_string = {
+ a = "b"
+ c = "d"
+ }
+ slice_string = [
+ "a",
+ "b",
+ "c",
+ ]
+ slice_slice_string = [
+ ["a","b"],
+ ["c","d"]
+ ]
+ }
+
+ nested_slice {
+ tag {
+ key = "first_tag_key"
+ value = "first_tag_value"
+ }
+ dynamic "tag" {
+ for_each = local.standard_tags
+ content {
+ key = tag.key
+ value = tag.value
+ }
+ }
+ }
+ }
+
+ error-cleanup-provisioner "shell" {
+ name = "error-cleanup-provisioner that does something"
+ not_squashed = "${var.foo} ${upper(build.ID)}"
+ string = "string"
+ int = "${41 + 1}"
+ int64 = "${42 + 1}"
+ bool = "true"
+ trilean = true
+ duration = "${9 + 1}s"
+ map_string_string = {
+ a = "b"
+ c = "d"
+ }
+ slice_string = [for s in var.availability_zone_names : lower(s)]
+ slice_slice_string = [
+ ["a","b"],
+ ["c","d"]
+ ]
+
+ nested {
+ string = "string"
+ int = 42
+ int64 = 43
+ bool = true
+ trilean = true
+ duration = "10s"
+ map_string_string = {
+ a = "b"
+ c = "d"
+ }
+ slice_string = [for s in var.availability_zone_names : lower(s)]
+ slice_slice_string = [
+ ["a","b"],
+ ["c","d"]
+ ]
+ }
+
+ nested_slice {
+ tag {
+ key = "first_tag_key"
+ value = "first_tag_value"
+ }
+ dynamic "tag" {
+ for_each = local.standard_tags
+ content {
+ key = tag.key
+ value = tag.value
+ }
+ }
+ }
+ }
+
+ post-processor "amazon-import" {
+ name = "something"
+ string = "string"
+ int = 42
+ int64 = 43
+ bool = true
+ trilean = true
+ duration = "10s"
+ keep_input_artifact = true
+ map_string_string = {
+ a = "b"
+ c = "d"
+ }
+ slice_string = [
+ "a",
+ "b",
+ "c",
+ ]
+ slice_slice_string = [
+ ["a","b"],
+ ["c","d"]
+ ]
+ not_squashed = "${var.foo} ${upper(build.ID)}"
+
+ nested {
+ string = "string"
+ int = 42
+ int64 = 43
+ bool = true
+ trilean = true
+ duration = "10s"
+ map_string_string = {
+ a = "b"
+ c = "d"
+ }
+ slice_string = [
+ "a",
+ "b",
+ "c",
+ ]
+ slice_slice_string = [
+ ["a","b"],
+ ["c","d"]
+ ]
+ }
+
+ tag {
+ key = "first_tag_key"
+ value = "first_tag_value"
+ }
+ dynamic "tag" {
+ for_each = local.standard_tags
+ content {
+ key = tag.key
+ value = tag.value
+ }
+ }
+ }
+
+ post-processor "amazon-import" {
+ string = "string"
+ int = 42
+ int64 = 43
+ bool = true
+ trilean = true
+ duration = "10s"
+ map_string_string = {
+ a = "b"
+ c = "d"
+ }
+ slice_string = [
+ "a",
+ "b",
+ "c",
+ ]
+ slice_slice_string = [
+ ["a","b"],
+ ["c","d"]
+ ]
+ not_squashed = "${var.foo} ${upper(build.ID)}"
+
+ nested {
+ string = "string"
+ int = 42
+ int64 = 43
+ bool = true
+ trilean = true
+ duration = "10s"
+ map_string_string = {
+ a = "b"
+ c = "d"
+ }
+ slice_string = [
+ "a",
+ "b",
+ "c",
+ ]
+ slice_slice_string = [
+ ["a","b"],
+ ["c","d"]
+ ]
+ }
+
+ nested_slice {
+ }
+ }
+
+ post-processors {
+
+ post-processor "amazon-import" {
+ name = "first-nested-post-processor"
+ string = "string"
+ int = 42
+ int64 = 43
+ bool = true
+ trilean = true
+ duration = "10s"
+ map_string_string = {
+ a = "b"
+ c = "d"
+ }
+ slice_string = [
+ "a",
+ "b",
+ "c",
+ ]
+ slice_slice_string = [
+ ["a","b"],
+ ["c","d"]
+ ]
+ not_squashed = "${var.foo} ${upper(build.ID)}"
+
+ nested {
+ string = "string"
+ int = 42
+ int64 = 43
+ bool = true
+ trilean = true
+ duration = "10s"
+ map_string_string = {
+ a = "b"
+ c = "d"
+ }
+ slice_string = [
+ "a",
+ "b",
+ "c",
+ ]
+ slice_slice_string = [
+ ["a","b"],
+ ["c","d"]
+ ]
+ }
+
+ nested_slice {
+ }
+ }
+
+ post-processor "amazon-import" {
+ name = "second-nested-post-processor"
+ string = "string"
+ int = 42
+ int64 = 43
+ bool = true
+ trilean = true
+ duration = "10s"
+ map_string_string = {
+ a = "b"
+ c = "d"
+ }
+ slice_string = [
+ "a",
+ "b",
+ "c",
+ ]
+ slice_slice_string = [
+ ["a","b"],
+ ["c","d"]
+ ]
+ not_squashed = "${var.foo} ${upper(build.ID)}"
+
+ nested {
+ string = "string"
+ int = 42
+ int64 = 43
+ bool = true
+ trilean = true
+ duration = "10s"
+ map_string_string = {
+ a = "b"
+ c = "d"
+ }
+ slice_string = [
+ "a",
+ "b",
+ "c",
+ ]
+ slice_slice_string = [
+ ["a","b"],
+ ["c","d"]
+ ]
+ }
+
+ nested_slice {
+ }
+ }
+
+ }
+
+ post-processors {
+
+ post-processor "amazon-import" {
+ name = "third-nested-post-processor"
+ string = "string"
+ int = 42
+ int64 = 43
+ bool = true
+ trilean = true
+ duration = "10s"
+ map_string_string = {
+ a = "b"
+ c = "d"
+ }
+ slice_string = [
+ "a",
+ "b",
+ "c",
+ ]
+ slice_slice_string = [
+ ["a","b"],
+ ["c","d"]
+ ]
+ not_squashed = "${var.foo} ${upper(build.ID)}"
+
+ nested {
+ string = "string"
+ int = 42
+ int64 = 43
+ bool = true
+ trilean = true
+ duration = "10s"
+ map_string_string = {
+ a = "b"
+ c = "d"
+ }
+ slice_string = [
+ "a",
+ "b",
+ "c",
+ ]
+ slice_slice_string = [
+ ["a","b"],
+ ["c","d"]
+ ]
+ }
+
+ nested_slice {
+ }
+ }
+
+ post-processor "amazon-import" {
+ name = "fourth-nested-post-processor"
+ string = "string"
+ int = 42
+ int64 = 43
+ bool = true
+ trilean = true
+ duration = "10s"
+ map_string_string = {
+ a = "b"
+ c = "d"
+ }
+ slice_string = [
+ "a",
+ "b",
+ "c",
+ ]
+ slice_slice_string = [
+ ["a","b"],
+ ["c","d"]
+ ]
+ not_squashed = "${var.foo} ${upper(build.ID)}"
+
+ nested {
+ string = "string"
+ int = 42
+ int64 = 43
+ bool = true
+ trilean = true
+ duration = "10s"
+ map_string_string = {
+ a = "b"
+ c = "d"
+ }
+ slice_string = [
+ "a",
+ "b",
+ "c",
+ ]
+ slice_slice_string = [
+ ["a","b"],
+ ["c","d"]
+ ]
+ }
+
+ nested_slice {
+ }
+ }
+
+ }
+}
diff --git a/v1.9.4/hcl2template/testdata/complete/datasource.pkr.hcl b/v1.9.4/hcl2template/testdata/complete/datasource.pkr.hcl
new file mode 100644
index 0000000..24ed30f
--- /dev/null
+++ b/v1.9.4/hcl2template/testdata/complete/datasource.pkr.hcl
@@ -0,0 +1,3 @@
+data "amazon-ami" "test" {
+ string = "string"
+}
\ No newline at end of file
diff --git a/v1.9.4/hcl2template/testdata/complete/sources.pkr.hcl b/v1.9.4/hcl2template/testdata/complete/sources.pkr.hcl
new file mode 100644
index 0000000..7b71356
--- /dev/null
+++ b/v1.9.4/hcl2template/testdata/complete/sources.pkr.hcl
@@ -0,0 +1,107 @@
+
+source "amazon-ebs" "ubuntu-1604" {
+ int = 42
+ nested_slice {
+ dynamic "tag" {
+ for_each = local.standard_tags
+ content {
+ key = tag.key
+ value = tag.value
+ }
+ }
+ }
+}
+
+source "virtualbox-iso" "ubuntu-1204" {
+ string = "${source.name}-${source.type}"
+ int = 42
+ int64 = 43
+ bool = true
+ trilean = true
+ duration = "10s"
+
+ map_string_string = {
+ a = "b"
+ c = "d"
+ }
+ slice_string = [
+ "a",
+ "b",
+ "c",
+ ]
+ slice_slice_string = [
+ ["a","b"],
+ ["c","d"]
+ ]
+
+ data_source = data.amazon-ami.test.string
+
+ nested {
+ string = "string"
+ int = 42
+ int64 = 43
+ bool = true
+ trilean = true
+ duration = "10s"
+ map_string_string = {
+ a = "b"
+ c = "d"
+ }
+ slice_string = [
+ "a",
+ "b",
+ "c",
+ ]
+ slice_slice_string = [
+ ["a","b"],
+ ["c","d"]
+ ]
+ data_source = data.amazon-ami.test.string
+ }
+
+ nested_slice {
+ string = "string"
+ int = 42
+ int64 = 43
+ bool = true
+ trilean = true
+ duration = "10s"
+ map_string_string = {
+ a = "b"
+ c = "d"
+ }
+ slice_string = [
+ "a",
+ "b",
+ "c",
+ ]
+ slice_slice_string = [
+ ["a","b"],
+ ["c","d"]
+ ]
+ data_source = data.amazon-ami.test.string
+ }
+
+ nested_slice {
+ string = "string"
+ int = 42
+ int64 = 43
+ bool = true
+ trilean = true
+ duration = "10s"
+ map_string_string = {
+ a = "b"
+ c = "d"
+ }
+ slice_string = [
+ "a",
+ "b",
+ "c",
+ ]
+ slice_slice_string = [
+ ["a","b"],
+ ["c","d"]
+ ]
+ data_source = data.amazon-ami.test.string
+ }
+}
diff --git a/v1.9.4/hcl2template/testdata/complete/variables.pkr.hcl b/v1.9.4/hcl2template/testdata/complete/variables.pkr.hcl
new file mode 100644
index 0000000..59120d1
--- /dev/null
+++ b/v1.9.4/hcl2template/testdata/complete/variables.pkr.hcl
@@ -0,0 +1,45 @@
+
+variables {
+ foo = "value"
+ // my_secret = "foo"
+ // image_name = "foo-image-{{user `my_secret`}}"
+}
+
+variable "image_id" {
+ type = string
+ default = "image-id-default"
+}
+
+variable "port" {
+ type = number
+ default = 42
+}
+
+variable "availability_zone_names" {
+ type = list(string)
+ default = ["A", "B", "C"]
+}
+
+locals {
+ feefoo = "${var.foo}_${var.image_id}"
+ data_source = data.amazon-ami.test.string
+}
+
+
+locals {
+ standard_tags = {
+ Component = "user-service"
+ Environment = "production"
+ }
+
+ abc_map = [
+ {id = "a"},
+ {id = "b"},
+ {id = "c"},
+ ]
+}
+
+local "supersecret" {
+ expression = "${var.image_id}-password"
+ sensitive = true
+}
diff --git a/v1.9.4/hcl2template/testdata/datasources/basic.pkr.hcl b/v1.9.4/hcl2template/testdata/datasources/basic.pkr.hcl
new file mode 100644
index 0000000..70a5133
--- /dev/null
+++ b/v1.9.4/hcl2template/testdata/datasources/basic.pkr.hcl
@@ -0,0 +1,95 @@
+data "amazon-ami" "test" {
+ string = "string"
+ int = 42
+ int64 = 43
+ bool = true
+ trilean = true
+ duration = "10s"
+ map_string_string = {
+ a = "b"
+ c = "d"
+ }
+ slice_string = [
+ "a",
+ "b",
+ "c",
+ ]
+ slice_slice_string = [
+ ["a","b"],
+ ["c","d"]
+ ]
+
+ nested {
+ string = "string"
+ int = 42
+ int64 = 43
+ bool = true
+ trilean = true
+ duration = "10s"
+ map_string_string = {
+ a = "b"
+ c = "d"
+ }
+ slice_string = [
+ "a",
+ "b",
+ "c",
+ ]
+ slice_slice_string = [
+ ["a","b"],
+ ["c","d"]
+ ]
+ }
+
+ nested_slice {
+ string = "string"
+ int = 42
+ int64 = 43
+ bool = true
+ trilean = true
+ duration = "10s"
+ map_string_string = {
+ a = "b"
+ c = "d"
+ }
+ slice_string = [
+ "a",
+ "b",
+ "c",
+ ]
+ slice_slice_string = [
+ ["a","b"],
+ ["c","d"]
+ ]
+ }
+
+ nested_slice {
+ string = "string"
+ int = 42
+ int64 = 43
+ bool = true
+ trilean = true
+ duration = "10s"
+ map_string_string = {
+ a = "b"
+ c = "d"
+ }
+ slice_string = [
+ "a",
+ "b",
+ "c",
+ ]
+ slice_slice_string = [
+ ["a","b"],
+ ["c","d"]
+ ]
+ }
+}
+
+source "null" "test" {
+ communicator = "none"
+}
+
+build {
+ sources = ["null.test"]
+}
diff --git a/v1.9.4/hcl2template/testdata/datasources/dependency_cycle.pkr.hcl b/v1.9.4/hcl2template/testdata/datasources/dependency_cycle.pkr.hcl
new file mode 100644
index 0000000..1cd397b
--- /dev/null
+++ b/v1.9.4/hcl2template/testdata/datasources/dependency_cycle.pkr.hcl
@@ -0,0 +1,6 @@
+data "null" "gummy" {
+ input = "${data.null.bear.output}"
+}
+data "null" "bear" {
+ input = "${data.null.gummy.output}"
+}
\ No newline at end of file
diff --git a/v1.9.4/hcl2template/testdata/datasources/duplicate.pkr.hcl b/v1.9.4/hcl2template/testdata/datasources/duplicate.pkr.hcl
new file mode 100644
index 0000000..97bfa21
--- /dev/null
+++ b/v1.9.4/hcl2template/testdata/datasources/duplicate.pkr.hcl
@@ -0,0 +1,2 @@
+data "amazon-ami" "test" {}
+data "amazon-ami" "test" {}
diff --git a/v1.9.4/hcl2template/testdata/datasources/nonexistent.pkr.hcl b/v1.9.4/hcl2template/testdata/datasources/nonexistent.pkr.hcl
new file mode 100644
index 0000000..128f391
--- /dev/null
+++ b/v1.9.4/hcl2template/testdata/datasources/nonexistent.pkr.hcl
@@ -0,0 +1,3 @@
+data "nonexistent" "test" {
+ foo = "bar"
+}
\ No newline at end of file
diff --git a/v1.9.4/hcl2template/testdata/datasources/not-allowed.pkr.hcl b/v1.9.4/hcl2template/testdata/datasources/not-allowed.pkr.hcl
new file mode 100644
index 0000000..5e7d0a1
--- /dev/null
+++ b/v1.9.4/hcl2template/testdata/datasources/not-allowed.pkr.hcl
@@ -0,0 +1,7 @@
+data "amazon-ami" "test_0" {
+ string = "string"
+}
+
+data "amazon-ami" "test_1" {
+ string = data.amazon-ami.test_0.string
+}
\ No newline at end of file
diff --git a/v1.9.4/hcl2template/testdata/datasources/recursive.pkr.hcl b/v1.9.4/hcl2template/testdata/datasources/recursive.pkr.hcl
new file mode 100644
index 0000000..84acac9
--- /dev/null
+++ b/v1.9.4/hcl2template/testdata/datasources/recursive.pkr.hcl
@@ -0,0 +1,27 @@
+data "null" "foo" {
+ input = "chocolate"
+}
+
+data "null" "yummy" {
+ input = "${data.null.bang.output}-and-sprinkles"
+}
+
+data "null" "bar" {
+ input = "vanilla"
+}
+
+data "null" "baz" {
+ input = "${data.null.foo.output}-${data.null.bar.output}-swirl"
+}
+
+data "null" "bang" {
+ input = "${data.null.baz.output}-with-marshmallows"
+}
+
+source "null" "test" {
+ communicator = "none"
+}
+
+build {
+ sources = ["null.test"]
+}
diff --git a/v1.9.4/hcl2template/testdata/datasources/unnamed.pkr.hcl b/v1.9.4/hcl2template/testdata/datasources/unnamed.pkr.hcl
new file mode 100644
index 0000000..58ae034
--- /dev/null
+++ b/v1.9.4/hcl2template/testdata/datasources/unnamed.pkr.hcl
@@ -0,0 +1,3 @@
+data "amazon-ami" {
+ foo = "bar"
+}
\ No newline at end of file
diff --git a/v1.9.4/hcl2template/testdata/datasources/untyped.pkr.hcl b/v1.9.4/hcl2template/testdata/datasources/untyped.pkr.hcl
new file mode 100644
index 0000000..f03e374
--- /dev/null
+++ b/v1.9.4/hcl2template/testdata/datasources/untyped.pkr.hcl
@@ -0,0 +1,3 @@
+data {
+ foo = "bar"
+}
\ No newline at end of file
diff --git a/v1.9.4/hcl2template/testdata/empty/.gitkeep b/v1.9.4/hcl2template/testdata/empty/.gitkeep
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/v1.9.4/hcl2template/testdata/empty/.gitkeep
diff --git a/v1.9.4/hcl2template/testdata/format/formatted.pkr.hcl b/v1.9.4/hcl2template/testdata/format/formatted.pkr.hcl
new file mode 100644
index 0000000..17a84d8
--- /dev/null
+++ b/v1.9.4/hcl2template/testdata/format/formatted.pkr.hcl
@@ -0,0 +1,149 @@
+
+// starts resources to provision them.
+build {
+ sources = [
+ "source.amazon-ebs.ubuntu-1604",
+ "source.virtualbox-iso.ubuntu-1204",
+ ]
+
+ provisioner "shell" {
+ string = coalesce(null, "", "string")
+ int = "${41 + 1}"
+ int64 = "${42 + 1}"
+ bool = "true"
+ trilean = true
+ duration = "${9 + 1}s"
+ map_string_string = {
+ a = "b"
+ c = "d"
+ }
+ slice_string = [
+ "a",
+ "b",
+ "c",
+ ]
+ slice_slice_string = [
+ ["a", "b"],
+ ["c", "d"]
+ ]
+
+ nested {
+ string = "string"
+ int = 42
+ int64 = 43
+ bool = true
+ trilean = true
+ duration = "10s"
+ map_string_string = {
+ a = "b"
+ c = "d"
+ }
+ slice_string = [
+ "a",
+ "b",
+ "c",
+ ]
+ slice_slice_string = [
+ ["a", "b"],
+ ["c", "d"]
+ ]
+ }
+
+ nested_slice {
+ }
+ }
+
+ provisioner "file" {
+ string = "string"
+ int = 42
+ int64 = 43
+ bool = true
+ trilean = true
+ duration = "10s"
+ map_string_string = {
+ a = "b"
+ c = "d"
+ }
+ slice_string = [
+ "a",
+ "b",
+ "c",
+ ]
+ slice_slice_string = [
+ ["a", "b"],
+ ["c", "d"]
+ ]
+
+ nested {
+ string = "string"
+ int = 42
+ int64 = 43
+ bool = true
+ trilean = true
+ duration = "10s"
+ map_string_string = {
+ a = "b"
+ c = "d"
+ }
+ slice_string = [
+ "a",
+ "b",
+ "c",
+ ]
+ slice_slice_string = [
+ ["a", "b"],
+ ["c", "d"]
+ ]
+ }
+
+ nested_slice {
+ }
+ }
+
+ post-processor "amazon-import" {
+ string = "string"
+ int = 42
+ int64 = 43
+ bool = true
+ trilean = true
+ duration = "10s"
+ map_string_string = {
+ a = "b"
+ c = "d"
+ }
+ slice_string = [
+ "a",
+ "b",
+ "c",
+ ]
+ slice_slice_string = [
+ ["a", "b"],
+ ["c", "d"]
+ ]
+
+ nested {
+ string = "string"
+ int = 42
+ int64 = 43
+ bool = true
+ trilean = true
+ duration = "10s"
+ map_string_string = {
+ a = "b"
+ c = "d"
+ }
+ slice_string = [
+ "a",
+ "b",
+ "c",
+ ]
+ slice_slice_string = [
+ ["a", "b"],
+ ["c", "d"]
+ ]
+ }
+
+ nested_slice {
+ }
+ }
+}
diff --git a/v1.9.4/hcl2template/testdata/format/unformatted.pkr.hcl b/v1.9.4/hcl2template/testdata/format/unformatted.pkr.hcl
new file mode 100644
index 0000000..86aa3a1
--- /dev/null
+++ b/v1.9.4/hcl2template/testdata/format/unformatted.pkr.hcl
@@ -0,0 +1,149 @@
+
+// starts resources to provision them.
+build {
+ sources = [
+ "source.amazon-ebs.ubuntu-1604",
+ "source.virtualbox-iso.ubuntu-1204",
+ ]
+
+ provisioner "shell" {
+ string = coalesce(null, "", "string")
+ int = "${41 + 1}"
+ int64 = "${42 + 1}"
+ bool = "true"
+ trilean = true
+ duration = "${9 + 1}s"
+ map_string_string = {
+ a = "b"
+ c = "d"
+ }
+ slice_string = [
+ "a",
+ "b",
+ "c",
+ ]
+ slice_slice_string = [
+ ["a","b"],
+ ["c","d"]
+ ]
+
+ nested {
+ string = "string"
+ int = 42
+ int64 = 43
+ bool = true
+ trilean = true
+ duration = "10s"
+ map_string_string = {
+ a = "b"
+ c = "d"
+ }
+ slice_string = [
+ "a",
+ "b",
+ "c",
+ ]
+ slice_slice_string = [
+ ["a","b"],
+ ["c","d"]
+ ]
+ }
+
+ nested_slice {
+ }
+ }
+
+ provisioner "file" {
+ string = "string"
+ int = 42
+ int64 = 43
+ bool = true
+ trilean = true
+ duration = "10s"
+ map_string_string = {
+ a = "b"
+ c = "d"
+ }
+ slice_string = [
+ "a",
+ "b",
+ "c",
+ ]
+ slice_slice_string = [
+ ["a","b"],
+ ["c","d"]
+ ]
+
+ nested {
+ string = "string"
+ int = 42
+ int64 = 43
+ bool = true
+ trilean = true
+ duration = "10s"
+ map_string_string = {
+ a = "b"
+ c = "d"
+ }
+ slice_string = [
+ "a",
+ "b",
+ "c",
+ ]
+ slice_slice_string = [
+ ["a","b"],
+ ["c","d"]
+ ]
+ }
+
+ nested_slice {
+ }
+ }
+
+ post-processor "amazon-import" {
+ string = "string"
+ int = 42
+ int64 = 43
+ bool = true
+ trilean = true
+ duration = "10s"
+ map_string_string = {
+ a = "b"
+ c = "d"
+ }
+ slice_string = [
+ "a",
+ "b",
+ "c",
+ ]
+ slice_slice_string = [
+ ["a","b"],
+ ["c","d"]
+ ]
+
+ nested {
+ string = "string"
+ int = 42
+ int64 = 43
+ bool = true
+ trilean = true
+ duration = "10s"
+ map_string_string = {
+ a = "b"
+ c = "d"
+ }
+ slice_string = [
+ "a",
+ "b",
+ "c",
+ ]
+ slice_slice_string = [
+ ["a","b"],
+ ["c","d"]
+ ]
+ }
+
+ nested_slice {
+ }
+ }
+}
diff --git a/v1.9.4/hcl2template/testdata/format/unformatted.pkrvars.hcl b/v1.9.4/hcl2template/testdata/format/unformatted.pkrvars.hcl
new file mode 100644
index 0000000..7ddc9df
--- /dev/null
+++ b/v1.9.4/hcl2template/testdata/format/unformatted.pkrvars.hcl
@@ -0,0 +1,3 @@
+ami_filter_name ="amzn2-ami-hvm-*-x86_64-gp2"
+ami_filter_owners =[ "137112412989" ]
+
diff --git a/v1.9.4/hcl2template/testdata/hcp_par/invalid.pkr.hcl b/v1.9.4/hcl2template/testdata/hcp_par/invalid.pkr.hcl
new file mode 100644
index 0000000..8634de1
--- /dev/null
+++ b/v1.9.4/hcl2template/testdata/hcp_par/invalid.pkr.hcl
@@ -0,0 +1,6 @@
+build {
+ name = "bucket-slug"
+ hcp_packer_registry {
+ labels = ""
+ }
+}
diff --git a/v1.9.4/hcl2template/testdata/hcp_par/long-description.pkr.hcl b/v1.9.4/hcl2template/testdata/hcp_par/long-description.pkr.hcl
new file mode 100644
index 0000000..c20502e
--- /dev/null
+++ b/v1.9.4/hcl2template/testdata/hcp_par/long-description.pkr.hcl
@@ -0,0 +1,10 @@
+build {
+ name = "bucket-slug"
+ hcp_packer_registry {
+ description = <<EOT
+This is a super super super super super super super super super super super super super super super super super super
+super super super super super super super super super super super super super super super super super super super super
+super super super long description
+ EOT
+ }
+}
diff --git a/v1.9.4/hcl2template/testdata/hcp_par/variable-for-bucket_name.pkr.hcl b/v1.9.4/hcl2template/testdata/hcp_par/variable-for-bucket_name.pkr.hcl
new file mode 100644
index 0000000..2cfcab5
--- /dev/null
+++ b/v1.9.4/hcl2template/testdata/hcp_par/variable-for-bucket_name.pkr.hcl
@@ -0,0 +1,15 @@
+variable "bucket" {
+ type = string
+ default = "variable-bucket-slug"
+}
+build {
+ hcp_packer_registry {
+ bucket_name = var.bucket
+ }
+ sources = [
+ "source.virtualbox-iso.ubuntu-1204",
+ ]
+}
+
+source "virtualbox-iso" "ubuntu-1204" {
+}
diff --git a/v1.9.4/hcl2template/testdata/hcp_par/variables-for-labels.pkr.hcl b/v1.9.4/hcl2template/testdata/hcp_par/variables-for-labels.pkr.hcl
new file mode 100644
index 0000000..c5128a3
--- /dev/null
+++ b/v1.9.4/hcl2template/testdata/hcp_par/variables-for-labels.pkr.hcl
@@ -0,0 +1,30 @@
+
+variable "bucket_labels" {
+ type = map(string)
+ default = {
+ "team": "development",
+ }
+}
+
+variable "build_labels" {
+ type = map(string)
+ default = {
+ "packageA": "v3.17.5",
+ "packageZ": "v0.6",
+ }
+}
+
+build {
+ hcp_packer_registry {
+ bucket_name = "bucket-slug"
+ bucket_labels = var.bucket_labels
+ build_labels = var.build_labels
+ }
+ sources = [
+ "source.virtualbox-iso.ubuntu-1204",
+ ]
+}
+
+source "virtualbox-iso" "ubuntu-1204" {
+}
+
diff --git a/v1.9.4/hcl2template/testdata/init/duplicate_required_plugins/packer.pkr.hcl b/v1.9.4/hcl2template/testdata/init/duplicate_required_plugins/packer.pkr.hcl
new file mode 100644
index 0000000..1cf3f29
--- /dev/null
+++ b/v1.9.4/hcl2template/testdata/init/duplicate_required_plugins/packer.pkr.hcl
@@ -0,0 +1,13 @@
+
+packer {
+ required_plugins {
+ amazon = {
+ source = "github.com/hashicorp/amazon"
+ version = ">= v0"
+ }
+ amazon = {
+ source = "github.com/hashicorp/amazon"
+ version = ">= v4"
+ }
+ }
+}
\ No newline at end of file
diff --git a/v1.9.4/hcl2template/testdata/init/imports/build.pkr.hcl b/v1.9.4/hcl2template/testdata/init/imports/build.pkr.hcl
new file mode 100644
index 0000000..7220f3b
--- /dev/null
+++ b/v1.9.4/hcl2template/testdata/init/imports/build.pkr.hcl
@@ -0,0 +1,462 @@
+
+packer {
+ required_version = ">= v1"
+
+ required_plugins {
+ amazon = {
+ source = "github.com/hashicorp/amazon"
+ version = ">= v0"
+ }
+ amazon-v1 = {
+ source = "github.com/hashicorp/amazon"
+ version = ">= v1"
+ }
+ amazon-v2 = {
+ source = "github.com/hashicorp/amazon"
+ version = ">= v2"
+ }
+ amazon-v3 = {
+ source = "github.com/hashicorp/amazon"
+ version = ">= v3"
+ }
+ amazon-v3-azr = {
+ source = "github.com/azr/amazon"
+ version = ">= v3"
+ }
+ amazon-v4 = {
+ source = "github.com/hashicorp/amazon"
+ version = ">= v4"
+ }
+ }
+}
+
+// starts resources to provision them.
+build {
+ sources = [
+ "source.virtualbox-iso.ubuntu-1204",
+ ]
+
+ source "source.amazon-v3-ebs.my-image" {
+ string = "setting from build section"
+ }
+
+ provisioner "shell" {
+ name = "provisioner that does something"
+ not_squashed = "${var.foo} ${upper(build.ID)}"
+ string = "string"
+ int = "${41 + 1}"
+ int64 = "${42 + 1}"
+ bool = "true"
+ trilean = true
+ duration = "${9 + 1}s"
+ map_string_string = {
+ a = "b"
+ c = "d"
+ }
+ slice_string = [for s in var.availability_zone_names : lower(s)]
+ slice_slice_string = [
+ ["a","b"],
+ ["c","d"]
+ ]
+
+ nested {
+ string = "string"
+ int = 42
+ int64 = 43
+ bool = true
+ trilean = true
+ duration = "10s"
+ map_string_string = {
+ a = "b"
+ c = "d"
+ }
+ slice_string = [for s in var.availability_zone_names : lower(s)]
+ slice_slice_string = [
+ ["a","b"],
+ ["c","d"]
+ ]
+ }
+
+ nested_slice {
+ tag {
+ key = "first_tag_key"
+ value = "first_tag_value"
+ }
+ dynamic "tag" {
+ for_each = local.standard_tags
+ content {
+ key = tag.key
+ value = tag.value
+ }
+ }
+ }
+ }
+
+ provisioner "file" {
+ not_squashed = "${var.foo} ${upper(build.ID)}"
+ string = "string"
+ int = 42
+ int64 = 43
+ bool = true
+ trilean = true
+ duration = "10s"
+ map_string_string = {
+ a = "b"
+ c = "d"
+ }
+ slice_string = local.abc_map[*].id
+ slice_slice_string = [
+ ["a","b"],
+ ["c","d"]
+ ]
+
+ nested {
+ string = "string"
+ int = 42
+ int64 = 43
+ bool = true
+ trilean = true
+ duration = "10s"
+ map_string_string = {
+ a = "b"
+ c = "d"
+ }
+ slice_string = [
+ "a",
+ "b",
+ "c",
+ ]
+ slice_slice_string = [
+ ["a","b"],
+ ["c","d"]
+ ]
+ }
+
+ nested_slice {
+ tag {
+ key = "first_tag_key"
+ value = "first_tag_value"
+ }
+ dynamic "tag" {
+ for_each = local.standard_tags
+ content {
+ key = tag.key
+ value = tag.value
+ }
+ }
+ }
+ }
+
+ post-processor "amazon-import" {
+ name = "something"
+ string = "string"
+ int = 42
+ int64 = 43
+ bool = true
+ trilean = true
+ duration = "10s"
+ keep_input_artifact = true
+ map_string_string = {
+ a = "b"
+ c = "d"
+ }
+ slice_string = [
+ "a",
+ "b",
+ "c",
+ ]
+ slice_slice_string = [
+ ["a","b"],
+ ["c","d"]
+ ]
+ not_squashed = "${var.foo} ${upper(build.ID)}"
+
+ nested {
+ string = "string"
+ int = 42
+ int64 = 43
+ bool = true
+ trilean = true
+ duration = "10s"
+ map_string_string = {
+ a = "b"
+ c = "d"
+ }
+ slice_string = [
+ "a",
+ "b",
+ "c",
+ ]
+ slice_slice_string = [
+ ["a","b"],
+ ["c","d"]
+ ]
+ }
+
+ nested_slice {
+ tag {
+ key = "first_tag_key"
+ value = "first_tag_value"
+ }
+ dynamic "tag" {
+ for_each = local.standard_tags
+ content {
+ key = tag.key
+ value = tag.value
+ }
+ }
+ }
+ }
+
+ post-processor "amazon-import" {
+ string = "string"
+ int = 42
+ int64 = 43
+ bool = true
+ trilean = true
+ duration = "10s"
+ map_string_string = {
+ a = "b"
+ c = "d"
+ }
+ slice_string = [
+ "a",
+ "b",
+ "c",
+ ]
+ slice_slice_string = [
+ ["a","b"],
+ ["c","d"]
+ ]
+ not_squashed = "${var.foo} ${upper(build.ID)}"
+
+ nested {
+ string = "string"
+ int = 42
+ int64 = 43
+ bool = true
+ trilean = true
+ duration = "10s"
+ map_string_string = {
+ a = "b"
+ c = "d"
+ }
+ slice_string = [
+ "a",
+ "b",
+ "c",
+ ]
+ slice_slice_string = [
+ ["a","b"],
+ ["c","d"]
+ ]
+ }
+
+ nested_slice {
+ }
+ }
+
+ post-processors {
+
+ post-processor "amazon-import" {
+ name = "first-nested-post-processor"
+ string = "string"
+ int = 42
+ int64 = 43
+ bool = true
+ trilean = true
+ duration = "10s"
+ map_string_string = {
+ a = "b"
+ c = "d"
+ }
+ slice_string = [
+ "a",
+ "b",
+ "c",
+ ]
+ slice_slice_string = [
+ ["a","b"],
+ ["c","d"]
+ ]
+ not_squashed = "${var.foo} ${upper(build.ID)}"
+
+ nested {
+ string = "string"
+ int = 42
+ int64 = 43
+ bool = true
+ trilean = true
+ duration = "10s"
+ map_string_string = {
+ a = "b"
+ c = "d"
+ }
+ slice_string = [
+ "a",
+ "b",
+ "c",
+ ]
+ slice_slice_string = [
+ ["a","b"],
+ ["c","d"]
+ ]
+ }
+
+ nested_slice {
+ }
+ }
+
+ post-processor "amazon-import" {
+ name = "second-nested-post-processor"
+ string = "string"
+ int = 42
+ int64 = 43
+ bool = true
+ trilean = true
+ duration = "10s"
+ map_string_string = {
+ a = "b"
+ c = "d"
+ }
+ slice_string = [
+ "a",
+ "b",
+ "c",
+ ]
+ slice_slice_string = [
+ ["a","b"],
+ ["c","d"]
+ ]
+ not_squashed = "${var.foo} ${upper(build.ID)}"
+
+ nested {
+ string = "string"
+ int = 42
+ int64 = 43
+ bool = true
+ trilean = true
+ duration = "10s"
+ map_string_string = {
+ a = "b"
+ c = "d"
+ }
+ slice_string = [
+ "a",
+ "b",
+ "c",
+ ]
+ slice_slice_string = [
+ ["a","b"],
+ ["c","d"]
+ ]
+ }
+
+ nested_slice {
+ }
+ }
+
+ }
+
+ post-processors {
+
+ post-processor "amazon-import" {
+ name = "third-nested-post-processor"
+ string = "string"
+ int = 42
+ int64 = 43
+ bool = true
+ trilean = true
+ duration = "10s"
+ map_string_string = {
+ a = "b"
+ c = "d"
+ }
+ slice_string = [
+ "a",
+ "b",
+ "c",
+ ]
+ slice_slice_string = [
+ ["a","b"],
+ ["c","d"]
+ ]
+ not_squashed = "${var.foo} ${upper(build.ID)}"
+
+ nested {
+ string = "string"
+ int = 42
+ int64 = 43
+ bool = true
+ trilean = true
+ duration = "10s"
+ map_string_string = {
+ a = "b"
+ c = "d"
+ }
+ slice_string = [
+ "a",
+ "b",
+ "c",
+ ]
+ slice_slice_string = [
+ ["a","b"],
+ ["c","d"]
+ ]
+ }
+
+ nested_slice {
+ }
+ }
+
+ post-processor "amazon-import" {
+ name = "fourth-nested-post-processor"
+ string = "string"
+ int = 42
+ int64 = 43
+ bool = true
+ trilean = true
+ duration = "10s"
+ map_string_string = {
+ a = "b"
+ c = "d"
+ }
+ slice_string = [
+ "a",
+ "b",
+ "c",
+ ]
+ slice_slice_string = [
+ ["a","b"],
+ ["c","d"]
+ ]
+ not_squashed = "${var.foo} ${upper(build.ID)}"
+
+ nested {
+ string = "string"
+ int = 42
+ int64 = 43
+ bool = true
+ trilean = true
+ duration = "10s"
+ map_string_string = {
+ a = "b"
+ c = "d"
+ }
+ slice_string = [
+ "a",
+ "b",
+ "c",
+ ]
+ slice_slice_string = [
+ ["a","b"],
+ ["c","d"]
+ ]
+ }
+
+ nested_slice {
+ }
+ }
+
+ }
+}
diff --git a/v1.9.4/hcl2template/testdata/init/imports/sources.pkr.hcl b/v1.9.4/hcl2template/testdata/init/imports/sources.pkr.hcl
new file mode 100644
index 0000000..7b7dc71
--- /dev/null
+++ b/v1.9.4/hcl2template/testdata/init/imports/sources.pkr.hcl
@@ -0,0 +1,94 @@
+
+source "amazon-v3-ebs" "my-image" {
+ int = 42
+}
+
+
+source "virtualbox-iso" "ubuntu-1204" {
+ string = "string"
+ int = 42
+ int64 = 43
+ bool = true
+ trilean = true
+ duration = "10s"
+
+ map_string_string = {
+ a = "b"
+ c = "d"
+ }
+ slice_string = [
+ "a",
+ "b",
+ "c",
+ ]
+ slice_slice_string = [
+ ["a","b"],
+ ["c","d"]
+ ]
+
+ nested {
+ string = "string"
+ int = 42
+ int64 = 43
+ bool = true
+ trilean = true
+ duration = "10s"
+ map_string_string = {
+ a = "b"
+ c = "d"
+ }
+ slice_string = [
+ "a",
+ "b",
+ "c",
+ ]
+ slice_slice_string = [
+ ["a","b"],
+ ["c","d"]
+ ]
+ }
+
+ nested_slice {
+ string = "string"
+ int = 42
+ int64 = 43
+ bool = true
+ trilean = true
+ duration = "10s"
+ map_string_string = {
+ a = "b"
+ c = "d"
+ }
+ slice_string = [
+ "a",
+ "b",
+ "c",
+ ]
+ slice_slice_string = [
+ ["a","b"],
+ ["c","d"]
+ ]
+ }
+
+ nested_slice {
+ string = "string"
+ int = 42
+ int64 = 43
+ bool = true
+ trilean = true
+ duration = "10s"
+ map_string_string = {
+ a = "b"
+ c = "d"
+ }
+ slice_string = [
+ "a",
+ "b",
+ "c",
+ ]
+ slice_slice_string = [
+ ["a","b"],
+ ["c","d"]
+ ]
+ }
+}
diff --git a/v1.9.4/hcl2template/testdata/init/imports/variables.pkr.hcl b/v1.9.4/hcl2template/testdata/init/imports/variables.pkr.hcl
new file mode 100644
index 0000000..beebda9
--- /dev/null
+++ b/v1.9.4/hcl2template/testdata/init/imports/variables.pkr.hcl
@@ -0,0 +1,39 @@
+
+variables {
+ foo = "value"
+ // my_secret = "foo"
+ // image_name = "foo-image-{{user `my_secret`}}"
+}
+
+variable "image_id" {
+ type = string
+ default = "image-id-default"
+}
+
+variable "port" {
+ type = number
+ default = 42
+}
+
+variable "availability_zone_names" {
+ type = list(string)
+ default = ["A", "B", "C"]
+}
+
+locals {
+ feefoo = "${var.foo}_${var.image_id}"
+}
+
+
+locals {
+ standard_tags = {
+ Component = "user-service"
+ Environment = "production"
+ }
+
+ abc_map = [
+ {id = "a"},
+ {id = "b"},
+ {id = "c"},
+ ]
+}
diff --git a/v1.9.4/hcl2template/testdata/init/invalid_inexplicit_source.pkr.hcl b/v1.9.4/hcl2template/testdata/init/invalid_inexplicit_source.pkr.hcl
new file mode 100644
index 0000000..3c84ffc
--- /dev/null
+++ b/v1.9.4/hcl2template/testdata/init/invalid_inexplicit_source.pkr.hcl
@@ -0,0 +1,8 @@
+packer {
+ required_plugins {
+ amazon = {
+ source = "amazon"
+ version = ">= v0"
+ }
+ }
+}
\ No newline at end of file
diff --git a/v1.9.4/hcl2template/testdata/init/invalid_inexplicit_source_2.pkr.hcl b/v1.9.4/hcl2template/testdata/init/invalid_inexplicit_source_2.pkr.hcl
new file mode 100644
index 0000000..3e71b82
--- /dev/null
+++ b/v1.9.4/hcl2template/testdata/init/invalid_inexplicit_source_2.pkr.hcl
@@ -0,0 +1,8 @@
+packer {
+ required_plugins {
+ amazon = {
+ source = "hashicorp/amazon"
+ version = ">= v0"
+ }
+ }
+}
\ No newline at end of file
diff --git a/v1.9.4/hcl2template/testdata/init/invalid_short_source.pkr.hcl b/v1.9.4/hcl2template/testdata/init/invalid_short_source.pkr.hcl
new file mode 100644
index 0000000..13ea61a
--- /dev/null
+++ b/v1.9.4/hcl2template/testdata/init/invalid_short_source.pkr.hcl
@@ -0,0 +1,5 @@
+packer {
+ required_plugins {
+ amazon = ">= v0"
+ }
+}
\ No newline at end of file
diff --git a/v1.9.4/hcl2template/testdata/sources/basic.pkr.hcl b/v1.9.4/hcl2template/testdata/sources/basic.pkr.hcl
new file mode 100644
index 0000000..d7efb81
--- /dev/null
+++ b/v1.9.4/hcl2template/testdata/sources/basic.pkr.hcl
@@ -0,0 +1,96 @@
+// a source represents a reusable setting for a system boot/start.
+source "virtualbox-iso" "ubuntu-1204" {
+ string = "string"
+ int = 42
+ int64 = 43
+ bool = true
+ trilean = true
+ duration = "10s"
+ map_string_string = {
+ a = "b"
+ c = "d"
+ }
+ slice_string = [
+ "a",
+ "b",
+ "c",
+ ]
+ slice_slice_string = [
+ ["a","b"],
+ ["c","d"]
+ ]
+
+ nested {
+ string = "string"
+ int = 42
+ int64 = 43
+ bool = true
+ trilean = true
+ duration = "10s"
+ map_string_string = {
+ a = "b"
+ c = "d"
+ }
+ slice_string = [
+ "a",
+ "b",
+ "c",
+ ]
+ slice_slice_string = [
+ ["a","b"],
+ ["c","d"]
+ ]
+ }
+
+ nested_slice {
+ string = "string"
+ int = 42
+ int64 = 43
+ bool = true
+ trilean = true
+ duration = "10s"
+ map_string_string = {
+ a = "b"
+ c = "d"
+ }
+ slice_string = [
+ "a",
+ "b",
+ "c",
+ ]
+ slice_slice_string = [
+ ["a","b"],
+ ["c","d"]
+ ]
+ }
+
+ nested_slice {
+ string = "string"
+ int = 42
+ int64 = 43
+ bool = true
+ trilean = true
+ duration = "10s"
+ map_string_string = {
+ a = "b"
+ c = "d"
+ }
+ slice_string = [
+ "a",
+ "b",
+ "c",
+ ]
+ slice_slice_string = [
+ ["a","b"],
+ ["c","d"]
+ ]
+ }
+}
+
+source "null" "test" {
+ communicator = "none"
+}
+
+build {
+ sources = ["null.test"]
+}
diff --git a/v1.9.4/hcl2template/testdata/sources/duplicate.pkr.hcl b/v1.9.4/hcl2template/testdata/sources/duplicate.pkr.hcl
new file mode 100644
index 0000000..823d17e
--- /dev/null
+++ b/v1.9.4/hcl2template/testdata/sources/duplicate.pkr.hcl
@@ -0,0 +1,3 @@
+
+source "virtualbox-iso" "ubuntu-1204" {}
+source "virtualbox-iso" "ubuntu-1204" {}
diff --git a/v1.9.4/hcl2template/testdata/sources/nonexistent.pkr.hcl b/v1.9.4/hcl2template/testdata/sources/nonexistent.pkr.hcl
new file mode 100644
index 0000000..b0b219b
--- /dev/null
+++ b/v1.9.4/hcl2template/testdata/sources/nonexistent.pkr.hcl
@@ -0,0 +1,6 @@
+// a source represents a reusable setting for a system boot/start.
+source "nonexistent" "ubuntu-1204" {
+ foo = "bar"
+}
+
+build {}
diff --git a/v1.9.4/hcl2template/testdata/sources/nonexistent_used.pkr.hcl b/v1.9.4/hcl2template/testdata/sources/nonexistent_used.pkr.hcl
new file mode 100644
index 0000000..ac2c96f
--- /dev/null
+++ b/v1.9.4/hcl2template/testdata/sources/nonexistent_used.pkr.hcl
@@ -0,0 +1,8 @@
+// a source represents a reusable setting for a system boot/start.
+source "nonexistent" "ubuntu-1204" {
+ foo = "bar"
+}
+
+build {
+ sources = ["nonexistent.ubuntu-1204"]
+}
diff --git a/v1.9.4/hcl2template/testdata/sources/unnamed.pkr.hcl b/v1.9.4/hcl2template/testdata/sources/unnamed.pkr.hcl
new file mode 100644
index 0000000..30adb03
--- /dev/null
+++ b/v1.9.4/hcl2template/testdata/sources/unnamed.pkr.hcl
@@ -0,0 +1,4 @@
+// a source represents a reusable setting for a system boot/start.
+source "virtualbox-iso" {
+ foo = "bar"
+}
\ No newline at end of file
diff --git a/v1.9.4/hcl2template/testdata/sources/untyped.pkr.hcl b/v1.9.4/hcl2template/testdata/sources/untyped.pkr.hcl
new file mode 100644
index 0000000..28d4fad
--- /dev/null
+++ b/v1.9.4/hcl2template/testdata/sources/untyped.pkr.hcl
@@ -0,0 +1,4 @@
+// a source represents a reusable setting for a system boot/start.
+source {
+ foo = "bar"
+}
\ No newline at end of file
diff --git a/v1.9.4/hcl2template/testdata/unknown/block_type.pkr.hcl b/v1.9.4/hcl2template/testdata/unknown/block_type.pkr.hcl
new file mode 100644
index 0000000..8ae2c40
--- /dev/null
+++ b/v1.9.4/hcl2template/testdata/unknown/block_type.pkr.hcl
@@ -0,0 +1,3 @@
+
+potato {
+}
diff --git a/v1.9.4/hcl2template/testdata/variables/basic.pkr.hcl b/v1.9.4/hcl2template/testdata/variables/basic.pkr.hcl
new file mode 100644
index 0000000..3c3c813
--- /dev/null
+++ b/v1.9.4/hcl2template/testdata/variables/basic.pkr.hcl
@@ -0,0 +1,51 @@
+
+variables {
+ key = "value"
+ my_secret = "foo"
+ image_name = "foo-image-{{user `my_secret`}}"
+}
+
+variable "image_id" {
+ type = string
+ default = "image-id-default"
+}
+
+variable "port" {
+ type = number
+ default = 42
+}
+
+variable "availability_zone_names" {
+ type = list(string)
+ default = ["us-west-1a"]
+ description = <<POTATO
+Describing is awesome ;D
+POTATO
+}
+
+variable "super_secret_password" {
+ type = string
+ sensitive = true
+description = <<IMSENSIBLE
+Handle with care plz
+IMSENSIBLE
+ default = null
+}
+
+locals {
+ service_name = "forum"
+ owner = "Community Team"
+}
+
+local "supersecret" {
+ sensitive = true
+ expression = "secretvar"
+}
+
+source "null" "test" {
+ communicator = "none"
+}
+
+build {
+ sources = ["null.test"]
+}
diff --git a/v1.9.4/hcl2template/testdata/variables/complicated/a.pkr.hcl b/v1.9.4/hcl2template/testdata/variables/complicated/a.pkr.hcl
new file mode 100644
index 0000000..dfe3a50
--- /dev/null
+++ b/v1.9.4/hcl2template/testdata/variables/complicated/a.pkr.hcl
@@ -0,0 +1,8 @@
+locals {
+ for_var = "${local.name_prefix}"
+ bar_var = [
+ local.for_var,
+ local.foo,
+ var.name_prefix,
+ ]
+}
\ No newline at end of file
diff --git a/v1.9.4/hcl2template/testdata/variables/complicated/b.pkr.hcl b/v1.9.4/hcl2template/testdata/variables/complicated/b.pkr.hcl
new file mode 100644
index 0000000..8559d58
--- /dev/null
+++ b/v1.9.4/hcl2template/testdata/variables/complicated/b.pkr.hcl
@@ -0,0 +1,5 @@
+locals {
+ name_prefix = "${var.name_prefix}"
+ foo = "${local.name_prefix}"
+ bar = local.name_prefix
+}
\ No newline at end of file
diff --git a/v1.9.4/hcl2template/testdata/variables/complicated/c.pkr.hcl b/v1.9.4/hcl2template/testdata/variables/complicated/c.pkr.hcl
new file mode 100644
index 0000000..ff7b6ac
--- /dev/null
+++ b/v1.9.4/hcl2template/testdata/variables/complicated/c.pkr.hcl
@@ -0,0 +1,3 @@
+variable "name_prefix" {
+ default = "foo"
+}
\ No newline at end of file
diff --git a/v1.9.4/hcl2template/testdata/variables/complicated/d.pkr.hcl b/v1.9.4/hcl2template/testdata/variables/complicated/d.pkr.hcl
new file mode 100644
index 0000000..e005230
--- /dev/null
+++ b/v1.9.4/hcl2template/testdata/variables/complicated/d.pkr.hcl
@@ -0,0 +1,7 @@
+source "null" "test" {
+ communicator = "none"
+}
+
+build {
+ sources = ["null.test"]
+}
diff --git a/v1.9.4/hcl2template/testdata/variables/duplicate_locals/one.pkr.hcl b/v1.9.4/hcl2template/testdata/variables/duplicate_locals/one.pkr.hcl
new file mode 100644
index 0000000..d267a3f
--- /dev/null
+++ b/v1.9.4/hcl2template/testdata/variables/duplicate_locals/one.pkr.hcl
@@ -0,0 +1,4 @@
+
+local "sensible" {
+ expression = "something"
+}
diff --git a/v1.9.4/hcl2template/testdata/variables/duplicate_locals/one_copy.pkr.hcl b/v1.9.4/hcl2template/testdata/variables/duplicate_locals/one_copy.pkr.hcl
new file mode 100644
index 0000000..d267a3f
--- /dev/null
+++ b/v1.9.4/hcl2template/testdata/variables/duplicate_locals/one_copy.pkr.hcl
@@ -0,0 +1,4 @@
+
+local "sensible" {
+ expression = "something"
+}
diff --git a/v1.9.4/hcl2template/testdata/variables/duplicate_variable.pkr.hcl b/v1.9.4/hcl2template/testdata/variables/duplicate_variable.pkr.hcl
new file mode 100644
index 0000000..a2ef386
--- /dev/null
+++ b/v1.9.4/hcl2template/testdata/variables/duplicate_variable.pkr.hcl
@@ -0,0 +1,8 @@
+
+variable "boolean_value" {
+ default = false
+}
+
+variable "boolean_value" {
+ default = true
+}
diff --git a/v1.9.4/hcl2template/testdata/variables/duplicate_variables.pkr.hcl b/v1.9.4/hcl2template/testdata/variables/duplicate_variables.pkr.hcl
new file mode 100644
index 0000000..e9eac04
--- /dev/null
+++ b/v1.9.4/hcl2template/testdata/variables/duplicate_variables.pkr.hcl
@@ -0,0 +1,8 @@
+
+variables {
+ boolean_value = false
+}
+
+variables {
+ boolean_value = true
+}
diff --git a/v1.9.4/hcl2template/testdata/variables/empty.pkr.hcl b/v1.9.4/hcl2template/testdata/variables/empty.pkr.hcl
new file mode 100644
index 0000000..e005230
--- /dev/null
+++ b/v1.9.4/hcl2template/testdata/variables/empty.pkr.hcl
@@ -0,0 +1,7 @@
+source "null" "test" {
+ communicator = "none"
+}
+
+build {
+ sources = ["null.test"]
+}
diff --git a/v1.9.4/hcl2template/testdata/variables/foo-string.variable.pkr.hcl b/v1.9.4/hcl2template/testdata/variables/foo-string.variable.pkr.hcl
new file mode 100644
index 0000000..f15ad13
--- /dev/null
+++ b/v1.9.4/hcl2template/testdata/variables/foo-string.variable.pkr.hcl
@@ -0,0 +1,12 @@
+variable "foo" {
+ type = string
+ default = "bar"
+}
+
+source "null" "test" {
+ communicator = "none"
+}
+
+build {
+ sources = ["null.test"]
+}
diff --git a/v1.9.4/hcl2template/testdata/variables/invalid_default.pkr.hcl b/v1.9.4/hcl2template/testdata/variables/invalid_default.pkr.hcl
new file mode 100644
index 0000000..01bfc98
--- /dev/null
+++ b/v1.9.4/hcl2template/testdata/variables/invalid_default.pkr.hcl
@@ -0,0 +1,6 @@
+
+
+variable "broken_type" {
+ type = list(string)
+ default = true
+}
diff --git a/v1.9.4/hcl2template/testdata/variables/provisioner_variable_decoding.pkr.hcl b/v1.9.4/hcl2template/testdata/variables/provisioner_variable_decoding.pkr.hcl
new file mode 100644
index 0000000..f6a3b07
--- /dev/null
+++ b/v1.9.4/hcl2template/testdata/variables/provisioner_variable_decoding.pkr.hcl
@@ -0,0 +1,21 @@
+variables {
+ max_retries = "1"
+ max_retries_int = 1
+}
+
+source "null" "null-builder" {
+ communicator = "none"
+}
+
+build {
+ sources = [
+ "source.null.null-builder",
+ ]
+
+ provisioner "shell" {
+ max_retries = var.max_retries_int
+ }
+ provisioner "shell" {
+ max_retries = var.max_retries
+ }
+}
\ No newline at end of file
diff --git a/v1.9.4/hcl2template/testdata/variables/recursive_locals.pkr.hcl b/v1.9.4/hcl2template/testdata/variables/recursive_locals.pkr.hcl
new file mode 100644
index 0000000..67fae7d
--- /dev/null
+++ b/v1.9.4/hcl2template/testdata/variables/recursive_locals.pkr.hcl
@@ -0,0 +1,4 @@
+locals {
+ first = local.second
+ second = local.first
+}
\ No newline at end of file
diff --git a/v1.9.4/hcl2template/testdata/variables/set-foo-too-wee.hcl b/v1.9.4/hcl2template/testdata/variables/set-foo-too-wee.hcl
new file mode 100644
index 0000000..5e643a4
--- /dev/null
+++ b/v1.9.4/hcl2template/testdata/variables/set-foo-too-wee.hcl
@@ -0,0 +1 @@
+foo = "wee"
diff --git a/v1.9.4/hcl2template/testdata/variables/unknown_key.pkr.hcl b/v1.9.4/hcl2template/testdata/variables/unknown_key.pkr.hcl
new file mode 100644
index 0000000..e5db1ea
--- /dev/null
+++ b/v1.9.4/hcl2template/testdata/variables/unknown_key.pkr.hcl
@@ -0,0 +1,5 @@
+
+variable "broken_variable" {
+ invalid = true
+ default = true
+}
diff --git a/v1.9.4/hcl2template/testdata/variables/unset_unused_string_variable.pkr.hcl b/v1.9.4/hcl2template/testdata/variables/unset_unused_string_variable.pkr.hcl
new file mode 100644
index 0000000..1853a09
--- /dev/null
+++ b/v1.9.4/hcl2template/testdata/variables/unset_unused_string_variable.pkr.hcl
@@ -0,0 +1,15 @@
+
+variable "foo" {
+ type = string
+}
+
+
+build {
+ sources = [
+ "source.null.null-builder",
+ ]
+}
+
+source "null" "null-builder" {
+ communicator = "none"
+}
diff --git a/v1.9.4/hcl2template/testdata/variables/unset_used_string_variable.pkr.hcl b/v1.9.4/hcl2template/testdata/variables/unset_used_string_variable.pkr.hcl
new file mode 100644
index 0000000..f8060cc
--- /dev/null
+++ b/v1.9.4/hcl2template/testdata/variables/unset_used_string_variable.pkr.hcl
@@ -0,0 +1,10 @@
+
+variable "foo" {
+ type = string
+}
+
+build {
+ sources = [
+ "source.null.null-builder${var.foo}",
+ ]
+}
diff --git a/v1.9.4/hcl2template/testdata/variables/validation/invalid_default.pkr.hcl b/v1.9.4/hcl2template/testdata/variables/validation/invalid_default.pkr.hcl
new file mode 100644
index 0000000..4fafe36
--- /dev/null
+++ b/v1.9.4/hcl2template/testdata/variables/validation/invalid_default.pkr.hcl
@@ -0,0 +1,9 @@
+
+variable "image_id" {
+ type = string
+ default = "potato"
+ validation {
+ condition = length(var.image_id) > 4 && substr(var.image_id, 0, 4) == "ami-"
+ error_message = "The image_id value must be a valid AMI id, starting with \"ami-\"."
+ }
+}
diff --git a/v1.9.4/hcl2template/testdata/variables/validation/valid.pkr.hcl b/v1.9.4/hcl2template/testdata/variables/validation/valid.pkr.hcl
new file mode 100644
index 0000000..dbab09d
--- /dev/null
+++ b/v1.9.4/hcl2template/testdata/variables/validation/valid.pkr.hcl
@@ -0,0 +1,17 @@
+
+variable "image_id" {
+ type = string
+ default = "ami-something-something"
+ validation {
+ condition = length(var.image_id) > 4 && substr(var.image_id, 0, 4) == "ami-"
+ error_message = "The image_id value must be a valid AMI id, starting with \"ami-\"."
+ }
+}
+
+source "null" "test" {
+ communicator = "none"
+}
+
+build {
+ sources = ["null.test"]
+}
diff --git a/v1.9.4/hcl2template/testdata/variables/validation/valid_map/definition.pkr.hcl b/v1.9.4/hcl2template/testdata/variables/validation/valid_map/definition.pkr.hcl
new file mode 100644
index 0000000..f095e90
--- /dev/null
+++ b/v1.9.4/hcl2template/testdata/variables/validation/valid_map/definition.pkr.hcl
@@ -0,0 +1,17 @@
+
+variable "image_metadata" {
+ default = {
+ key: "value",
+ something: {
+ foo: "bar",
+ }
+ }
+ validation {
+ condition = length(var.image_metadata.key) > 4
+ error_message = "The image_metadata.key field must be more than 4 runes."
+ }
+ validation {
+ condition = substr(var.image_metadata.something.foo, 0, 3) == "bar"
+ error_message = "The image_metadata.something.foo field must start with \"bar\"."
+ }
+}
diff --git a/v1.9.4/hcl2template/testdata/variables/validation/valid_map/invalid_value.auto.pkrvars.hcl b/v1.9.4/hcl2template/testdata/variables/validation/valid_map/invalid_value.auto.pkrvars.hcl
new file mode 100644
index 0000000..9734f36
--- /dev/null
+++ b/v1.9.4/hcl2template/testdata/variables/validation/valid_map/invalid_value.auto.pkrvars.hcl
@@ -0,0 +1,7 @@
+
+image_metadata = {
+ key: "value",
+ something: {
+ foo: "woo",
+ }
+}
diff --git a/v1.9.4/hcl2template/types.build.from.go b/v1.9.4/hcl2template/types.build.from.go
new file mode 100644
index 0000000..9661fa1
--- /dev/null
+++ b/v1.9.4/hcl2template/types.build.from.go
@@ -0,0 +1,23 @@
+// Copyright (c) HashiCorp, Inc.
+// SPDX-License-Identifier: MPL-2.0
+
+package hcl2template
+
+import (
+ "strings"
+)
+
+func sourceRefFromString(in string) SourceRef {
+ args := strings.Split(in, ".")
+ if len(args) < 2 {
+ return NoSource
+ }
+ if len(args) > 2 {
+ // source.type.name
+ args = args[1:]
+ }
+ return SourceRef{
+ Type: args[0],
+ Name: args[1],
+ }
+}
diff --git a/v1.9.4/hcl2template/types.build.go b/v1.9.4/hcl2template/types.build.go
new file mode 100644
index 0000000..2ab6aa7
--- /dev/null
+++ b/v1.9.4/hcl2template/types.build.go
@@ -0,0 +1,246 @@
+// Copyright (c) HashiCorp, Inc.
+// SPDX-License-Identifier: MPL-2.0
+
+package hcl2template
+
+import (
+ "fmt"
+
+ "github.com/hashicorp/hcl/v2"
+ "github.com/hashicorp/hcl/v2/gohcl"
+ "github.com/hashicorp/hcl/v2/hclsyntax"
+ "github.com/zclconf/go-cty/cty"
+)
+
+const (
+ buildFromLabel = "from"
+
+ buildSourceLabel = "source"
+
+ buildProvisionerLabel = "provisioner"
+
+ buildErrorCleanupProvisionerLabel = "error-cleanup-provisioner"
+
+ buildPostProcessorLabel = "post-processor"
+
+ buildPostProcessorsLabel = "post-processors"
+
+ buildHCPPackerRegistryLabel = "hcp_packer_registry"
+)
+
+var buildSchema = &hcl.BodySchema{
+ Blocks: []hcl.BlockHeaderSchema{
+ {Type: buildFromLabel, LabelNames: []string{"type"}},
+ {Type: sourceLabel, LabelNames: []string{"reference"}},
+ {Type: buildProvisionerLabel, LabelNames: []string{"type"}},
+ {Type: buildErrorCleanupProvisionerLabel, LabelNames: []string{"type"}},
+ {Type: buildPostProcessorLabel, LabelNames: []string{"type"}},
+ {Type: buildPostProcessorsLabel, LabelNames: []string{}},
+ {Type: buildHCPPackerRegistryLabel},
+ },
+}
+
+var postProcessorsSchema = &hcl.BodySchema{
+ Blocks: []hcl.BlockHeaderSchema{
+ {Type: buildPostProcessorLabel, LabelNames: []string{"type"}},
+ },
+}
+
+// BuildBlock references an HCL 'build' block and it content, for example :
+//
+// build {
+// sources = [
+// ...
+// ]
+// provisioner "" { ... }
+// post-processor "" { ... }
+// }
+type BuildBlock struct {
+ // Name is a string representing the named build to show in the logs
+ Name string
+
+ // A description of what this build does, it could be used in a inspect
+ // call for example.
+ Description string
+
+ // HCPPackerRegistry contains the configuration for publishing the image to the HCP Packer Registry.
+ HCPPackerRegistry *HCPPackerRegistryBlock
+
+ // Sources is the list of sources that we want to start in this build block.
+ Sources []SourceUseBlock
+
+ // ProvisionerBlocks references a list of HCL provisioner block that will
+ // will be ran against the sources.
+ ProvisionerBlocks []*ProvisionerBlock
+
+ // ErrorCleanupProvisionerBlock references a special provisioner block that
+ // will be ran only if the provision step fails.
+ ErrorCleanupProvisionerBlock *ProvisionerBlock
+
+ // PostProcessorLists references the lists of lists of HCL post-processors
+ // block that will be run against the artifacts from the provisioning
+ // steps.
+ PostProcessorsLists [][]*PostProcessorBlock
+
+ HCL2Ref HCL2Ref
+}
+
+type Builds []*BuildBlock
+
+// decodeBuildConfig is called when a 'build' block has been detected. It will
+// load the references to the contents of the build block.
+func (p *Parser) decodeBuildConfig(block *hcl.Block, cfg *PackerConfig) (*BuildBlock, hcl.Diagnostics) {
+ var b struct {
+ Name string `hcl:"name,optional"`
+ Description string `hcl:"description,optional"`
+ FromSources []string `hcl:"sources,optional"`
+ Config hcl.Body `hcl:",remain"`
+ }
+
+ body := block.Body
+ diags := gohcl.DecodeBody(body, cfg.EvalContext(LocalContext, nil), &b)
+ if diags.HasErrors() {
+ return nil, diags
+ }
+
+ build := &BuildBlock{
+ HCL2Ref: newHCL2Ref(block, b.Config),
+ }
+
+ build.Name = b.Name
+ build.Description = b.Description
+ build.HCL2Ref.DefRange = block.DefRange
+
+ // Expose build.name during parsing of pps and provisioners
+ ectx := cfg.EvalContext(BuildContext, nil)
+ ectx.Variables[buildAccessor] = cty.ObjectVal(map[string]cty.Value{
+ "name": cty.StringVal(b.Name),
+ })
+
+ // We rely on `hadSource` to determine which error to proc.
+ //
+ // If a source block is referenced in the build block, but isn't valid, we
+ // cannot rely on the `build.Sources' since it's only populated when a valid
+ // source is processed.
+ hadSource := false
+
+ for _, buildFrom := range b.FromSources {
+ hadSource = true
+
+ ref := sourceRefFromString(buildFrom)
+
+ if ref == NoSource ||
+ !hclsyntax.ValidIdentifier(ref.Type) ||
+ !hclsyntax.ValidIdentifier(ref.Name) {
+ diags = append(diags, &hcl.Diagnostic{
+ Severity: hcl.DiagError,
+ Summary: "Invalid " + sourceLabel + " reference",
+ Detail: "A " + sourceLabel + " type is made of three parts that are" +
+ "split by a dot `.`; each part must start with a letter and " +
+ "may contain only letters, digits, underscores, and dashes." +
+ "A valid source reference looks like: `source.type.name`",
+ Subject: block.DefRange.Ptr(),
+ })
+ continue
+ }
+
+ // source with no body
+ build.Sources = append(build.Sources, SourceUseBlock{SourceRef: ref})
+ }
+
+ body = b.Config
+ content, moreDiags := body.Content(buildSchema)
+ diags = append(diags, moreDiags...)
+ if diags.HasErrors() {
+ return nil, diags
+ }
+ for _, block := range content.Blocks {
+ switch block.Type {
+ case buildHCPPackerRegistryLabel:
+ if build.HCPPackerRegistry != nil {
+ diags = append(diags, &hcl.Diagnostic{
+ Severity: hcl.DiagError,
+ Summary: fmt.Sprintf("Only one " + buildHCPPackerRegistryLabel + " is allowed"),
+ Subject: block.DefRange.Ptr(),
+ })
+ continue
+ }
+ hcpPackerRegistry, moreDiags := p.decodeHCPRegistry(block, cfg)
+ diags = append(diags, moreDiags...)
+ if moreDiags.HasErrors() {
+ continue
+ }
+ build.HCPPackerRegistry = hcpPackerRegistry
+ case sourceLabel:
+ hadSource = true
+ ref, moreDiags := p.decodeBuildSource(block)
+ diags = append(diags, moreDiags...)
+ if moreDiags.HasErrors() {
+ continue
+ }
+ build.Sources = append(build.Sources, ref)
+ case buildProvisionerLabel:
+ p, moreDiags := p.decodeProvisioner(block, ectx)
+ diags = append(diags, moreDiags...)
+ if moreDiags.HasErrors() {
+ continue
+ }
+ build.ProvisionerBlocks = append(build.ProvisionerBlocks, p)
+ case buildErrorCleanupProvisionerLabel:
+ if build.ErrorCleanupProvisionerBlock != nil {
+ diags = append(diags, &hcl.Diagnostic{
+ Severity: hcl.DiagError,
+ Summary: fmt.Sprintf("Only one " + buildErrorCleanupProvisionerLabel + " is allowed"),
+ Subject: block.DefRange.Ptr(),
+ })
+ continue
+ }
+ p, moreDiags := p.decodeProvisioner(block, ectx)
+ diags = append(diags, moreDiags...)
+ if moreDiags.HasErrors() {
+ continue
+ }
+ build.ErrorCleanupProvisionerBlock = p
+ case buildPostProcessorLabel:
+ pp, moreDiags := p.decodePostProcessor(block, ectx)
+ diags = append(diags, moreDiags...)
+ if moreDiags.HasErrors() {
+ continue
+ }
+ build.PostProcessorsLists = append(build.PostProcessorsLists, []*PostProcessorBlock{pp})
+ case buildPostProcessorsLabel:
+
+ content, moreDiags := block.Body.Content(postProcessorsSchema)
+ diags = append(diags, moreDiags...)
+ if moreDiags.HasErrors() {
+ continue
+ }
+
+ errored := false
+ postProcessors := []*PostProcessorBlock{}
+ for _, block := range content.Blocks {
+ pp, moreDiags := p.decodePostProcessor(block, ectx)
+ diags = append(diags, moreDiags...)
+ if moreDiags.HasErrors() {
+ errored = true
+ break
+ }
+ postProcessors = append(postProcessors, pp)
+ }
+ if errored == false {
+ build.PostProcessorsLists = append(build.PostProcessorsLists, postProcessors)
+ }
+ }
+ }
+
+ if !hadSource {
+ diags = append(diags, &hcl.Diagnostic{
+ Summary: "missing source reference",
+ Detail: "a build block must reference at least one source to be built",
+ Severity: hcl.DiagError,
+ Subject: block.DefRange.Ptr(),
+ })
+ }
+
+ return build, diags
+}
diff --git a/v1.9.4/hcl2template/types.build.hcp_packer_registry.go b/v1.9.4/hcl2template/types.build.hcp_packer_registry.go
new file mode 100644
index 0000000..6d1b99f
--- /dev/null
+++ b/v1.9.4/hcl2template/types.build.hcp_packer_registry.go
@@ -0,0 +1,79 @@
+// Copyright (c) HashiCorp, Inc.
+// SPDX-License-Identifier: MPL-2.0
+
+package hcl2template
+
+import (
+ "fmt"
+
+ "github.com/hashicorp/hcl/v2"
+ "github.com/hashicorp/hcl/v2/gohcl"
+)
+
+type HCPPackerRegistryBlock struct {
+ // Bucket slug
+ Slug string
+ // Bucket description
+ Description string
+ // Bucket labels
+ BucketLabels map[string]string
+ // Build labels
+ BuildLabels map[string]string
+
+ HCL2Ref
+}
+
+func (p *Parser) decodeHCPRegistry(block *hcl.Block, cfg *PackerConfig) (*HCPPackerRegistryBlock, hcl.Diagnostics) {
+ par := &HCPPackerRegistryBlock{}
+ body := block.Body
+
+ var b struct {
+ Slug string `hcl:"bucket_name,optional"`
+ Description string `hcl:"description,optional"`
+ //Deprecated labels for bucket_labels
+ Labels map[string]string `hcl:"labels,optional"`
+ BucketLabels map[string]string `hcl:"bucket_labels,optional"`
+ BuildLabels map[string]string `hcl:"build_labels,optional"`
+ Config hcl.Body `hcl:",remain"`
+ }
+ ectx := cfg.EvalContext(BuildContext, nil)
+ diags := gohcl.DecodeBody(body, ectx, &b)
+ if diags.HasErrors() {
+ return nil, diags
+ }
+
+ if len(b.Description) > 255 {
+ diags = append(diags, &hcl.Diagnostic{
+ Severity: hcl.DiagError,
+ Summary: fmt.Sprintf(buildHCPPackerRegistryLabel + ".description should have a maximum length of 255 characters"),
+ Subject: block.DefRange.Ptr(),
+ })
+ return nil, diags
+ }
+
+ par.Slug = b.Slug
+ par.Description = b.Description
+
+ if len(b.Labels) > 0 && len(b.BucketLabels) > 0 {
+ diags = append(diags, &hcl.Diagnostic{
+ Severity: hcl.DiagError,
+ Summary: fmt.Sprintf("%s.labels and %[1]s.bucket_labels are mutually exclusive; please use the recommended argument %[1]s.bucket_labels", buildHCPPackerRegistryLabel),
+ Subject: block.DefRange.Ptr(),
+ })
+ return nil, diags
+ }
+
+ if len(b.Labels) > 0 {
+ diags = append(diags, &hcl.Diagnostic{
+ Severity: hcl.DiagWarning,
+ Summary: fmt.Sprintf("the argument %s.labels has been deprecated and will be removed in the next minor release; please use %[1]s.bucket_labels", buildHCPPackerRegistryLabel),
+ })
+
+ b.BucketLabels = b.Labels
+ }
+
+ par.BucketLabels = b.BucketLabels
+ par.BuildLabels = b.BuildLabels
+
+ return par, diags
+}
diff --git a/v1.9.4/hcl2template/types.build.hcp_packer_registry_test.go b/v1.9.4/hcl2template/types.build.hcp_packer_registry_test.go
new file mode 100644
index 0000000..18c8ca3
--- /dev/null
+++ b/v1.9.4/hcl2template/types.build.hcp_packer_registry_test.go
@@ -0,0 +1,139 @@
+// Copyright (c) HashiCorp, Inc.
+// SPDX-License-Identifier: MPL-2.0
+
+package hcl2template
+
+import (
+ "path/filepath"
+ "testing"
+
+ packersdk "github.com/hashicorp/packer-plugin-sdk/packer"
+ "github.com/hashicorp/packer/packer"
+ "github.com/zclconf/go-cty/cty"
+)
+
+func Test_ParseHCPPackerRegistryBlock(t *testing.T) {
+ t.Setenv("HCP_PACKER_BUILD_FINGERPRINT", "hcp-par-test")
+
+ defaultParser := getBasicParser()
+
+ tests := []parseTest{
+ {"bucket_name as variable",
+ defaultParser,
+ parseTestArgs{"testdata/hcp_par/variable-for-bucket_name.pkr.hcl", nil, nil},
+ &PackerConfig{
+ CorePackerVersionString: lockedVersion,
+ Basedir: filepath.Join("testdata", "hcp_par"),
+ InputVariables: Variables{
+ "bucket": &Variable{
+ Name: "bucket",
+ Type: cty.String,
+ Values: []VariableAssignment{{From: "default", Value: cty.StringVal("variable-bucket-slug")}},
+ },
+ },
+ Sources: map[SourceRef]SourceBlock{
+ refVBIsoUbuntu1204: {Type: "virtualbox-iso", Name: "ubuntu-1204"},
+ },
+ Builds: Builds{
+ &BuildBlock{
+ HCPPackerRegistry: &HCPPackerRegistryBlock{
+ Slug: "variable-bucket-slug",
+ },
+ Sources: []SourceUseBlock{
+ {
+ SourceRef: refVBIsoUbuntu1204,
+ },
+ },
+ },
+ },
+ },
+ false, false,
+ []packersdk.Build{
+ &packer.CoreBuild{
+ Type: "virtualbox-iso.ubuntu-1204",
+ Prepared: true,
+ Builder: emptyMockBuilder,
+ Provisioners: []packer.CoreBuildProvisioner{},
+ PostProcessors: [][]packer.CoreBuildPostProcessor{},
+ },
+ },
+ false,
+ },
+ {"bucket_labels and build_labels as variables",
+ defaultParser,
+ parseTestArgs{"testdata/hcp_par/variables-for-labels.pkr.hcl", nil, nil},
+ &PackerConfig{
+ CorePackerVersionString: lockedVersion,
+ Basedir: filepath.Join("testdata", "hcp_par"),
+ InputVariables: Variables{
+ "bucket_labels": &Variable{
+ Name: "bucket_labels",
+ Type: cty.Map(cty.String),
+ Values: []VariableAssignment{{From: "default", Value: cty.MapVal(map[string]cty.Value{"team": cty.StringVal("development")})}},
+ },
+ "build_labels": &Variable{
+ Name: "build_labels",
+ Type: cty.Map(cty.String),
+ Values: []VariableAssignment{{
+ From: "default",
+ Value: cty.MapVal(map[string]cty.Value{
+ "packageA": cty.StringVal("v3.17.5"),
+ "packageZ": cty.StringVal("v0.6"),
+ })}},
+ },
+ },
+ Sources: map[SourceRef]SourceBlock{
+ refVBIsoUbuntu1204: {Type: "virtualbox-iso", Name: "ubuntu-1204"},
+ },
+ Builds: Builds{
+ &BuildBlock{
+ HCPPackerRegistry: &HCPPackerRegistryBlock{
+ Slug: "bucket-slug",
+ BucketLabels: map[string]string{"team": "development"},
+ BuildLabels: map[string]string{"packageA": "v3.17.5", "packageZ": "v0.6"},
+ },
+ Sources: []SourceUseBlock{
+ {
+ SourceRef: refVBIsoUbuntu1204,
+ },
+ },
+ },
+ },
+ },
+ false, false,
+ []packersdk.Build{
+ &packer.CoreBuild{
+ Type: "virtualbox-iso.ubuntu-1204",
+ Prepared: true,
+ Builder: emptyMockBuilder,
+ Provisioners: []packer.CoreBuildProvisioner{},
+ PostProcessors: [][]packer.CoreBuildPostProcessor{},
+ },
+ },
+ false,
+ },
+ {"invalid hcp_packer_registry config",
+ defaultParser,
+ parseTestArgs{"testdata/hcp_par/invalid.pkr.hcl", nil, nil},
+ &PackerConfig{
+ CorePackerVersionString: lockedVersion,
+ Basedir: filepath.Join("testdata", "hcp_par"),
+ },
+ true, true,
+ nil,
+ false,
+ },
+ {"long hcp_packer_registry.description",
+ defaultParser,
+ parseTestArgs{"testdata/hcp_par/long-description.pkr.hcl", nil, nil},
+ &PackerConfig{
+ CorePackerVersionString: lockedVersion,
+ Basedir: filepath.Join("testdata", "hcp_par"),
+ },
+ true, true,
+ nil,
+ false,
+ },
+ }
+ testParse(t, tests)
+}
diff --git a/v1.9.4/hcl2template/types.build.post-processor.go b/v1.9.4/hcl2template/types.build.post-processor.go
new file mode 100644
index 0000000..1216f32
--- /dev/null
+++ b/v1.9.4/hcl2template/types.build.post-processor.go
@@ -0,0 +1,97 @@
+// Copyright (c) HashiCorp, Inc.
+// SPDX-License-Identifier: MPL-2.0
+
+package hcl2template
+
+import (
+ "fmt"
+ "strconv"
+
+ "github.com/hashicorp/hcl/v2"
+ "github.com/hashicorp/hcl/v2/gohcl"
+ packersdk "github.com/hashicorp/packer-plugin-sdk/packer"
+)
+
+// ProvisionerBlock references a detected but unparsed post processor
+type PostProcessorBlock struct {
+ PType string
+ PName string
+ OnlyExcept OnlyExcept
+ KeepInputArtifact *bool
+
+ HCL2Ref
+}
+
+func (p *PostProcessorBlock) String() string {
+ return fmt.Sprintf(buildPostProcessorLabel+"-block %q %q", p.PType, p.PName)
+}
+
+func (p *Parser) decodePostProcessor(block *hcl.Block, ectx *hcl.EvalContext) (*PostProcessorBlock, hcl.Diagnostics) {
+ var b struct {
+ Name string `hcl:"name,optional"`
+ Only []string `hcl:"only,optional"`
+ Except []string `hcl:"except,optional"`
+ KeepInputArtifact *bool `hcl:"keep_input_artifact,optional"`
+ Rest hcl.Body `hcl:",remain"`
+ }
+
+ diags := gohcl.DecodeBody(block.Body, ectx, &b)
+ if diags.HasErrors() {
+ return nil, diags
+ }
+
+ postProcessor := &PostProcessorBlock{
+ PType: block.Labels[0],
+ PName: b.Name,
+ OnlyExcept: OnlyExcept{Only: b.Only, Except: b.Except},
+ HCL2Ref: newHCL2Ref(block, b.Rest),
+ KeepInputArtifact: b.KeepInputArtifact,
+ }
+
+ diags = diags.Extend(postProcessor.OnlyExcept.Validate())
+ if diags.HasErrors() {
+ return nil, diags
+ }
+
+ return postProcessor, diags
+}
+
+func (cfg *PackerConfig) startPostProcessor(source SourceUseBlock, pp *PostProcessorBlock, ectx *hcl.EvalContext) (packersdk.PostProcessor, hcl.Diagnostics) {
+ // ProvisionerBlock represents a detected but unparsed provisioner
+ var diags hcl.Diagnostics
+
+ postProcessor, err := cfg.parser.PluginConfig.PostProcessors.Start(pp.PType)
+ if err != nil {
+ diags = append(diags, &hcl.Diagnostic{
+ Severity: hcl.DiagError,
+ Summary: fmt.Sprintf("Failed loading %s", pp.PType),
+ Subject: pp.DefRange.Ptr(),
+ Detail: err.Error(),
+ })
+ return nil, diags
+ }
+
+ builderVars := source.builderVariables()
+ builderVars["packer_core_version"] = cfg.CorePackerVersionString
+ builderVars["packer_debug"] = strconv.FormatBool(cfg.debug)
+ builderVars["packer_force"] = strconv.FormatBool(cfg.force)
+ builderVars["packer_on_error"] = cfg.onError
+
+ hclPostProcessor := &HCL2PostProcessor{
+ PostProcessor: postProcessor,
+ postProcessorBlock: pp,
+ evalContext: ectx,
+ builderVariables: builderVars,
+ }
+ err = hclPostProcessor.HCL2Prepare(nil)
+ if err != nil {
+ diags = append(diags, &hcl.Diagnostic{
+ Severity: hcl.DiagError,
+ Summary: fmt.Sprintf("Failed preparing %s", pp),
+ Detail: err.Error(),
+ Subject: pp.DefRange.Ptr(),
+ })
+ return nil, diags
+ }
+ return hclPostProcessor, diags
+}
diff --git a/v1.9.4/hcl2template/types.build.provisioners.go b/v1.9.4/hcl2template/types.build.provisioners.go
new file mode 100644
index 0000000..8459f1b
--- /dev/null
+++ b/v1.9.4/hcl2template/types.build.provisioners.go
@@ -0,0 +1,213 @@
+// Copyright (c) HashiCorp, Inc.
+// SPDX-License-Identifier: MPL-2.0
+
+package hcl2template
+
+import (
+ "fmt"
+ "strconv"
+ "time"
+
+ "github.com/hashicorp/hcl/v2"
+ "github.com/hashicorp/hcl/v2/gohcl"
+ packersdk "github.com/hashicorp/packer-plugin-sdk/packer"
+ hcl2shim "github.com/hashicorp/packer/hcl2template/shim"
+ "github.com/zclconf/go-cty/cty"
+)
+
+// OnlyExcept is a struct that is meant to be embedded that contains the
+// logic required for "only" and "except" meta-parameters.
+type OnlyExcept struct {
+ Only []string `json:"only,omitempty"`
+ Except []string `json:"except,omitempty"`
+}
+
+// Skip says whether or not to skip the build with the given name.
+func (o *OnlyExcept) Skip(n string) bool {
+ if len(o.Only) > 0 {
+ for _, v := range o.Only {
+ if v == n {
+ return false
+ }
+ }
+
+ return true
+ }
+
+ if len(o.Except) > 0 {
+ for _, v := range o.Except {
+ if v == n {
+ return true
+ }
+ }
+
+ return false
+ }
+
+ return false
+}
+
+// Validate validates that the OnlyExcept settings are correct for a thing.
+func (o *OnlyExcept) Validate() hcl.Diagnostics {
+ var diags hcl.Diagnostics
+
+ if len(o.Only) > 0 && len(o.Except) > 0 {
+ diags = diags.Append(&hcl.Diagnostic{
+ Summary: "only one of 'only' or 'except' may be specified",
+ Severity: hcl.DiagError,
+ })
+ }
+
+ return diags
+}
+
+// ProvisionerBlock references a detected but unparsed provisioner
+type ProvisionerBlock struct {
+ PType string
+ PName string
+ PauseBefore time.Duration
+ MaxRetries int
+ Timeout time.Duration
+ Override map[string]interface{}
+ OnlyExcept OnlyExcept
+ HCL2Ref
+}
+
+func (p *ProvisionerBlock) String() string {
+ return fmt.Sprintf(buildProvisionerLabel+"-block %q %q", p.PType, p.PName)
+}
+
+func (p *Parser) decodeProvisioner(block *hcl.Block, ectx *hcl.EvalContext) (*ProvisionerBlock, hcl.Diagnostics) {
+ var b struct {
+ Name string `hcl:"name,optional"`
+ PauseBefore string `hcl:"pause_before,optional"`
+ MaxRetries int `hcl:"max_retries,optional"`
+ Timeout string `hcl:"timeout,optional"`
+ Only []string `hcl:"only,optional"`
+ Except []string `hcl:"except,optional"`
+ Override cty.Value `hcl:"override,optional"`
+ Rest hcl.Body `hcl:",remain"`
+ }
+ diags := gohcl.DecodeBody(block.Body, ectx, &b)
+ if diags.HasErrors() {
+ return nil, diags
+ }
+
+ provisioner := &ProvisionerBlock{
+ PType: block.Labels[0],
+ PName: b.Name,
+ MaxRetries: b.MaxRetries,
+ OnlyExcept: OnlyExcept{Only: b.Only, Except: b.Except},
+ HCL2Ref: newHCL2Ref(block, b.Rest),
+ }
+
+ diags = diags.Extend(provisioner.OnlyExcept.Validate())
+ if diags.HasErrors() {
+ return nil, diags
+ }
+
+ if !b.Override.IsNull() {
+ if !b.Override.Type().IsObjectType() {
+ return nil, append(diags, &hcl.Diagnostic{
+ Severity: hcl.DiagError,
+ Summary: "provisioner's override block must be an HCL object",
+ Subject: block.DefRange.Ptr(),
+ })
+ }
+
+ override := make(map[string]interface{})
+ for buildName, overrides := range b.Override.AsValueMap() {
+ buildOverrides := make(map[string]interface{})
+
+ if !overrides.Type().IsObjectType() {
+ return nil, append(diags, &hcl.Diagnostic{
+ Severity: hcl.DiagError,
+ Summary: fmt.Sprintf(
+ "provisioner's override.'%s' block must be an HCL object",
+ buildName),
+ Subject: block.DefRange.Ptr(),
+ })
+ }
+
+ for option, value := range overrides.AsValueMap() {
+ buildOverrides[option] = hcl2shim.ConfigValueFromHCL2(value)
+ }
+ override[buildName] = buildOverrides
+ }
+ provisioner.Override = override
+ }
+
+ if b.PauseBefore != "" {
+ pauseBefore, err := time.ParseDuration(b.PauseBefore)
+ if err != nil {
+ return nil, append(diags, &hcl.Diagnostic{
+ Summary: "Failed to parse pause_before duration",
+ Severity: hcl.DiagError,
+ Detail: err.Error(),
+ Subject: &block.DefRange,
+ })
+ }
+ provisioner.PauseBefore = pauseBefore
+ }
+
+ if b.Timeout != "" {
+ timeout, err := time.ParseDuration(b.Timeout)
+ if err != nil {
+ return nil, append(diags, &hcl.Diagnostic{
+ Summary: "Failed to parse timeout duration",
+ Severity: hcl.DiagError,
+ Detail: err.Error(),
+ Subject: &block.DefRange,
+ })
+ }
+ provisioner.Timeout = timeout
+ }
+
+ return provisioner, diags
+}
+
+func (cfg *PackerConfig) startProvisioner(source SourceUseBlock, pb *ProvisionerBlock, ectx *hcl.EvalContext) (packersdk.Provisioner, hcl.Diagnostics) {
+ var diags hcl.Diagnostics
+
+ provisioner, err := cfg.parser.PluginConfig.Provisioners.Start(pb.PType)
+ if err != nil {
+ diags = append(diags, &hcl.Diagnostic{
+ Severity: hcl.DiagError,
+ Summary: fmt.Sprintf("failed loading %s", pb.PType),
+ Subject: pb.HCL2Ref.LabelsRanges[0].Ptr(),
+ Detail: err.Error(),
+ })
+ return nil, diags
+ }
+
+ builderVars := source.builderVariables()
+ builderVars["packer_core_version"] = cfg.CorePackerVersionString
+ builderVars["packer_debug"] = strconv.FormatBool(cfg.debug)
+ builderVars["packer_force"] = strconv.FormatBool(cfg.force)
+ builderVars["packer_on_error"] = cfg.onError
+
+ hclProvisioner := &HCL2Provisioner{
+ Provisioner: provisioner,
+ provisionerBlock: pb,
+ evalContext: ectx,
+ builderVariables: builderVars,
+ }
+
+ if pb.Override != nil {
+ if override, ok := pb.Override[source.name()]; ok {
+ hclProvisioner.override = override.(map[string]interface{})
+ }
+ }
+
+ err = hclProvisioner.HCL2Prepare(nil)
+ if err != nil {
+ diags = append(diags, &hcl.Diagnostic{
+ Severity: hcl.DiagError,
+ Summary: fmt.Sprintf("Failed preparing %s", pb),
+ Detail: err.Error(),
+ Subject: pb.HCL2Ref.DefRange.Ptr(),
+ })
+ return nil, diags
+ }
+ return hclProvisioner, diags
+}
diff --git a/v1.9.4/hcl2template/types.build.provisioners_test.go b/v1.9.4/hcl2template/types.build.provisioners_test.go
new file mode 100644
index 0000000..e19570d
--- /dev/null
+++ b/v1.9.4/hcl2template/types.build.provisioners_test.go
@@ -0,0 +1,85 @@
+// Copyright (c) HashiCorp, Inc.
+// SPDX-License-Identifier: MPL-2.0
+
+package hcl2template
+
+import (
+ "testing"
+
+ "github.com/hashicorp/hcl/v2"
+)
+
+func TestPackerConfig_ParseProvisionerBlock(t *testing.T) {
+ tests := []struct {
+ name string
+ inputFile string
+ expectError bool
+ expectedErrorMessage string
+ }{
+ {
+ "success - provisioner is valid",
+ "fixtures/well_formed_provisioner.pkr.hcl",
+ false,
+ "",
+ },
+ {
+ "failure - provisioner override is malformed",
+ "fixtures/malformed_override.pkr.hcl",
+ true,
+ "provisioner's override block must be an HCL object",
+ },
+ {
+ "failure - provisioner override.test is malformed",
+ "fixtures/malformed_override_innards.pkr.hcl",
+ true,
+ "provisioner's override.'test' block must be an HCL object",
+ },
+ }
+
+ for _, test := range tests {
+ t.Run(test.name, func(t *testing.T) {
+ cfg := PackerConfig{parser: getBasicParser()}
+ f, diags := cfg.parser.ParseHCLFile(test.inputFile)
+ if diags.HasErrors() {
+ t.Errorf("failed to parse input file %s", test.inputFile)
+ for _, d := range diags {
+ t.Errorf("%s", d)
+ }
+ return
+ }
+ provBlock := f.OutermostBlockAtPos(hcl.Pos{
+ Line: 1,
+ Column: 1,
+ Byte: 0,
+ })
+ _, diags = cfg.parser.decodeProvisioner(provBlock, nil)
+
+ if !diags.HasErrors() {
+ if !test.expectError {
+ return
+ }
+
+ t.Fatalf("unexpected success")
+ }
+
+ if !test.expectError {
+ for _, d := range diags {
+ t.Errorf("%s", d)
+ }
+ }
+
+ gotExpectedErr := false
+ for _, d := range diags {
+ if d.Summary == test.expectedErrorMessage {
+ gotExpectedErr = true
+ }
+
+ t.Logf("got error (expected): '%s'", d.Summary)
+ }
+
+ if !gotExpectedErr {
+ t.Errorf("never got expected error: '%s'", test.expectedErrorMessage)
+ }
+ })
+ }
+}
diff --git a/v1.9.4/hcl2template/types.build_test.go b/v1.9.4/hcl2template/types.build_test.go
new file mode 100644
index 0000000..376646c
--- /dev/null
+++ b/v1.9.4/hcl2template/types.build_test.go
@@ -0,0 +1,690 @@
+// Copyright (c) HashiCorp, Inc.
+// SPDX-License-Identifier: MPL-2.0
+
+package hcl2template
+
+import (
+ "path/filepath"
+ "testing"
+
+ packersdk "github.com/hashicorp/packer-plugin-sdk/packer"
+ . "github.com/hashicorp/packer/hcl2template/internal"
+ "github.com/hashicorp/packer/packer"
+ "github.com/zclconf/go-cty/cty"
+)
+
+func TestParse_build(t *testing.T) {
+ defaultParser := getBasicParser()
+
+ tests := []parseTest{
+ {"basic build no src",
+ defaultParser,
+ parseTestArgs{"testdata/build/basic.pkr.hcl", nil, nil},
+ &PackerConfig{
+ CorePackerVersionString: lockedVersion,
+ Basedir: filepath.Join("testdata", "build"),
+ Builds: Builds{
+ &BuildBlock{
+ Sources: []SourceUseBlock{
+ {
+ SourceRef: SourceRef{
+ Type: "amazon-ebs",
+ Name: "ubuntu-1604",
+ },
+ },
+ {
+ SourceRef: refVBIsoUbuntu1204,
+ },
+ },
+ ProvisionerBlocks: []*ProvisionerBlock{
+ {
+ PType: "shell",
+ },
+ {
+ PType: "file",
+ },
+ },
+ PostProcessorsLists: [][]*PostProcessorBlock{
+ {
+ {
+ PType: "amazon-import",
+ },
+ },
+ },
+ },
+ },
+ },
+ true, true,
+ []packersdk.Build{},
+ true,
+ },
+ {"untyped provisioner",
+ defaultParser,
+ parseTestArgs{"testdata/build/provisioner_untyped.pkr.hcl", nil, nil},
+ &PackerConfig{
+ CorePackerVersionString: lockedVersion,
+ Basedir: filepath.Join("testdata", "build"),
+ Builds: nil,
+ },
+ true, true,
+ nil,
+ false,
+ },
+ {"nonexistent provisioner",
+ defaultParser,
+ parseTestArgs{"testdata/build/provisioner_nonexistent.pkr.hcl", nil, nil},
+ &PackerConfig{
+ CorePackerVersionString: lockedVersion,
+ Basedir: filepath.Join("testdata", "build"),
+ Sources: map[SourceRef]SourceBlock{
+ {
+ Type: "null",
+ Name: "test",
+ }: {
+ Type: "null",
+ Name: "test",
+ },
+ },
+ Builds: Builds{
+ &BuildBlock{
+ ProvisionerBlocks: []*ProvisionerBlock{
+ {
+ PType: "nonexistent",
+ },
+ },
+ Sources: []SourceUseBlock{
+ {
+ SourceRef: SourceRef{
+ Type: "null",
+ Name: "test",
+ },
+ },
+ },
+ },
+ },
+ },
+ true, true,
+ []packersdk.Build{&packer.CoreBuild{
+ Provisioners: []packer.CoreBuildProvisioner{},
+ }},
+ false,
+ },
+ {"two error-cleanup-provisioner",
+ defaultParser,
+ parseTestArgs{"testdata/build/two-error-cleanup-provisioner.pkr.hcl", nil, nil},
+ &PackerConfig{
+ CorePackerVersionString: lockedVersion,
+ Basedir: filepath.Join("testdata", "build"),
+ Sources: map[SourceRef]SourceBlock{
+ refVBIsoUbuntu1204: {Type: "virtualbox-iso", Name: "ubuntu-1204"},
+ },
+ },
+ true, true,
+ []packersdk.Build{&packer.CoreBuild{
+ Builder: emptyMockBuilder,
+ CleanupProvisioner: packer.CoreBuildProvisioner{
+ PType: "shell-local",
+ Provisioner: &HCL2Provisioner{
+ Provisioner: &MockProvisioner{
+ Config: MockConfig{
+ NestedMockConfig: NestedMockConfig{Tags: []MockTag{}},
+ NestedSlice: []NestedMockConfig{},
+ },
+ },
+ },
+ },
+ }},
+ false,
+ },
+ {"untyped post-processor",
+ defaultParser,
+ parseTestArgs{"testdata/build/post-processor_untyped.pkr.hcl", nil, nil},
+ &PackerConfig{
+ CorePackerVersionString: lockedVersion,
+ Basedir: filepath.Join("testdata", "build"),
+ Builds: nil,
+ },
+ true, true,
+ []packersdk.Build{&packer.CoreBuild{}},
+ false,
+ },
+ {"nonexistent post-processor",
+ defaultParser,
+ parseTestArgs{"testdata/build/post-processor_nonexistent.pkr.hcl", nil, nil},
+ &PackerConfig{
+ CorePackerVersionString: lockedVersion,
+ Basedir: filepath.Join("testdata", "build"),
+ Sources: map[SourceRef]SourceBlock{
+ {
+ Type: "null",
+ Name: "test",
+ }: {
+ Type: "null",
+ Name: "test",
+ },
+ },
+ Builds: Builds{
+ &BuildBlock{
+ PostProcessorsLists: [][]*PostProcessorBlock{
+ {
+ {
+ PType: "nonexistent",
+ },
+ },
+ },
+ Sources: []SourceUseBlock{
+ {
+ SourceRef: SourceRef{
+ Type: "null",
+ Name: "test",
+ },
+ },
+ },
+ },
+ },
+ },
+ true, true,
+ []packersdk.Build{&packer.CoreBuild{
+ PostProcessors: [][]packer.CoreBuildPostProcessor{},
+ }},
+ true,
+ },
+ {"invalid source",
+ defaultParser,
+ parseTestArgs{"testdata/build/invalid_source_reference.pkr.hcl", nil, nil},
+ &PackerConfig{
+ CorePackerVersionString: lockedVersion,
+ Basedir: filepath.Join("testdata", "build"),
+ Builds: nil,
+ },
+ true, true,
+ []packersdk.Build{},
+ false,
+ },
+ {"named build",
+ defaultParser,
+ parseTestArgs{"testdata/build/named.pkr.hcl", nil, nil},
+ &PackerConfig{
+ CorePackerVersionString: lockedVersion,
+ Basedir: filepath.Join("testdata", "build"),
+ Builds: Builds{
+ &BuildBlock{
+ Name: "somebuild",
+ Sources: []SourceUseBlock{
+ {
+ SourceRef: SourceRef{
+ Type: "amazon-ebs",
+ Name: "ubuntu-1604",
+ },
+ },
+ {
+ SourceRef: refVBIsoUbuntu1204,
+ },
+ },
+ },
+ },
+ },
+ true, true,
+ []packersdk.Build{},
+ true,
+ },
+ {"post-processor with only and except",
+ defaultParser,
+ parseTestArgs{"testdata/build/post-processor_onlyexcept.pkr.hcl", nil, nil},
+ &PackerConfig{
+ CorePackerVersionString: lockedVersion,
+ Basedir: filepath.Join("testdata", "build"),
+ Sources: map[SourceRef]SourceBlock{
+ refVBIsoUbuntu1204: {Type: "virtualbox-iso", Name: "ubuntu-1204"},
+ refAWSEBSUbuntu1604: {Type: "amazon-ebs", Name: "ubuntu-1604"},
+ },
+ Builds: Builds{
+ &BuildBlock{
+ Sources: []SourceUseBlock{
+ {
+ SourceRef: refVBIsoUbuntu1204,
+ },
+ {
+ SourceRef: SourceRef{Type: "amazon-ebs", Name: "ubuntu-1604"},
+ LocalName: "aws-ubuntu-16.04",
+ },
+ },
+ ProvisionerBlocks: nil,
+ PostProcessorsLists: [][]*PostProcessorBlock{
+ {
+ {
+ PType: "amazon-import",
+ OnlyExcept: OnlyExcept{Only: []string{"virtualbox-iso.ubuntu-1204"}, Except: nil},
+ },
+ },
+ {
+ {
+ PType: "manifest",
+ OnlyExcept: OnlyExcept{Only: nil, Except: []string{"virtualbox-iso.ubuntu-1204"}},
+ },
+ },
+ {
+ {
+ PType: "amazon-import",
+ OnlyExcept: OnlyExcept{Only: []string{"amazon-ebs.aws-ubuntu-16.04"}, Except: nil},
+ },
+ },
+ {
+ {
+ PType: "manifest",
+ OnlyExcept: OnlyExcept{Only: nil, Except: []string{"amazon-ebs.aws-ubuntu-16.04"}},
+ },
+ },
+ },
+ },
+ },
+ },
+ false, false,
+ []packersdk.Build{
+ &packer.CoreBuild{
+ Type: "virtualbox-iso.ubuntu-1204",
+ Prepared: true,
+ Builder: emptyMockBuilder,
+ Provisioners: []packer.CoreBuildProvisioner{},
+ PostProcessors: [][]packer.CoreBuildPostProcessor{
+ {
+ {
+ PType: "amazon-import",
+ PostProcessor: &HCL2PostProcessor{
+ PostProcessor: &MockPostProcessor{
+ Config: MockConfig{
+ NestedMockConfig: NestedMockConfig{Tags: []MockTag{}},
+ NestedSlice: []NestedMockConfig{},
+ },
+ },
+ },
+ },
+ },
+ {
+ {
+ PType: "manifest",
+ PostProcessor: &HCL2PostProcessor{
+ PostProcessor: &MockPostProcessor{
+ Config: MockConfig{
+ NestedMockConfig: NestedMockConfig{Tags: []MockTag{}},
+ NestedSlice: []NestedMockConfig{},
+ },
+ },
+ },
+ },
+ },
+ },
+ },
+ &packer.CoreBuild{
+ Type: "amazon-ebs.aws-ubuntu-16.04",
+ Prepared: true,
+ Builder: emptyMockBuilder,
+ Provisioners: []packer.CoreBuildProvisioner{},
+ PostProcessors: [][]packer.CoreBuildPostProcessor{
+ {
+ {
+ PType: "manifest",
+ PostProcessor: &HCL2PostProcessor{
+ PostProcessor: &MockPostProcessor{
+ Config: MockConfig{
+ NestedMockConfig: NestedMockConfig{Tags: []MockTag{}},
+ NestedSlice: []NestedMockConfig{},
+ },
+ },
+ },
+ },
+ },
+ {
+ {
+ PType: "amazon-import",
+ PostProcessor: &HCL2PostProcessor{
+ PostProcessor: &MockPostProcessor{
+ Config: MockConfig{
+ NestedMockConfig: NestedMockConfig{Tags: []MockTag{}},
+ NestedSlice: []NestedMockConfig{},
+ },
+ },
+ },
+ },
+ },
+ },
+ },
+ },
+ false,
+ },
+ {"provisioner with only and except",
+ defaultParser,
+ parseTestArgs{"testdata/build/provisioner_onlyexcept.pkr.hcl", nil, nil},
+ &PackerConfig{
+ CorePackerVersionString: lockedVersion,
+ Basedir: filepath.Join("testdata", "build"),
+ Sources: map[SourceRef]SourceBlock{
+ refVBIsoUbuntu1204: {Type: "virtualbox-iso", Name: "ubuntu-1204"},
+ refAWSEBSUbuntu1604: {Type: "amazon-ebs", Name: "ubuntu-1604"},
+ },
+ Builds: Builds{
+ &BuildBlock{
+ Sources: []SourceUseBlock{
+ {
+ SourceRef: refVBIsoUbuntu1204,
+ },
+ {
+ SourceRef: SourceRef{Type: "amazon-ebs", Name: "ubuntu-1604"},
+ LocalName: "aws-ubuntu-16.04",
+ },
+ },
+ ProvisionerBlocks: []*ProvisionerBlock{
+ {
+ PType: "shell",
+ OnlyExcept: OnlyExcept{Only: []string{"virtualbox-iso.ubuntu-1204"}},
+ },
+ {
+ PType: "file",
+ OnlyExcept: OnlyExcept{Except: []string{"virtualbox-iso.ubuntu-1204"}},
+ },
+ {
+ PType: "shell",
+ OnlyExcept: OnlyExcept{Only: []string{"amazon-ebs.aws-ubuntu-16.04"}},
+ },
+ {
+ PType: "file",
+ OnlyExcept: OnlyExcept{Except: []string{"amazon-ebs.aws-ubuntu-16.04"}},
+ },
+ },
+ },
+ },
+ },
+ false, false,
+ []packersdk.Build{
+ &packer.CoreBuild{
+ Type: "virtualbox-iso.ubuntu-1204",
+ Prepared: true,
+ Builder: emptyMockBuilder,
+ Provisioners: []packer.CoreBuildProvisioner{
+ {
+ PType: "shell",
+ Provisioner: &HCL2Provisioner{
+ Provisioner: &MockProvisioner{
+ Config: MockConfig{
+ NestedMockConfig: NestedMockConfig{Tags: []MockTag{}},
+ NestedSlice: []NestedMockConfig{},
+ },
+ },
+ },
+ },
+ {
+ PType: "file",
+ Provisioner: &HCL2Provisioner{
+ Provisioner: &MockProvisioner{
+ Config: MockConfig{
+ NestedMockConfig: NestedMockConfig{Tags: []MockTag{}},
+ NestedSlice: []NestedMockConfig{},
+ },
+ },
+ },
+ },
+ },
+ PostProcessors: [][]packer.CoreBuildPostProcessor{},
+ },
+ &packer.CoreBuild{
+ Type: "amazon-ebs.aws-ubuntu-16.04",
+ Prepared: true,
+ Builder: emptyMockBuilder,
+ Provisioners: []packer.CoreBuildProvisioner{
+ {
+ PType: "file",
+ Provisioner: &HCL2Provisioner{
+ Provisioner: &MockProvisioner{
+ Config: MockConfig{
+ NestedMockConfig: NestedMockConfig{Tags: []MockTag{}},
+ NestedSlice: []NestedMockConfig{},
+ },
+ },
+ },
+ },
+ {
+ PType: "shell",
+ Provisioner: &HCL2Provisioner{
+ Provisioner: &MockProvisioner{
+ Config: MockConfig{
+ NestedMockConfig: NestedMockConfig{Tags: []MockTag{}},
+ NestedSlice: []NestedMockConfig{},
+ },
+ },
+ },
+ },
+ },
+ PostProcessors: [][]packer.CoreBuildPostProcessor{},
+ },
+ },
+ false,
+ },
+ {"provisioner with packer_version interpolation",
+ defaultParser,
+ parseTestArgs{"testdata/build/provisioner_packer_version_interpolation.pkr.hcl", nil, nil},
+ &PackerConfig{
+ CorePackerVersionString: lockedVersion,
+ Basedir: filepath.Join("testdata", "build"),
+ Sources: map[SourceRef]SourceBlock{
+ refVBIsoUbuntu1204: {Type: "virtualbox-iso", Name: "ubuntu-1204"},
+ },
+ Builds: Builds{
+ &BuildBlock{
+ Sources: []SourceUseBlock{
+ {
+ SourceRef: refVBIsoUbuntu1204,
+ },
+ },
+ ProvisionerBlocks: []*ProvisionerBlock{
+ {
+ PType: "shell",
+ },
+ },
+ },
+ },
+ },
+ false, false,
+ []packersdk.Build{
+ &packer.CoreBuild{
+ Type: "virtualbox-iso.ubuntu-1204",
+ Prepared: true,
+ Builder: emptyMockBuilder,
+ Provisioners: []packer.CoreBuildProvisioner{
+ {
+ PType: "shell",
+ Provisioner: &HCL2Provisioner{
+ Provisioner: &MockProvisioner{
+ Config: MockConfig{
+ NestedMockConfig: NestedMockConfig{
+ Tags: []MockTag{},
+ SliceString: []string{lockedVersion},
+ },
+ NestedSlice: []NestedMockConfig{},
+ },
+ },
+ },
+ },
+ },
+ PostProcessors: [][]packer.CoreBuildPostProcessor{},
+ },
+ },
+ false,
+ },
+ {"variable interpolation for build name and description",
+ defaultParser,
+ parseTestArgs{"testdata/build/variables.pkr.hcl", nil, nil},
+ &PackerConfig{
+ CorePackerVersionString: lockedVersion,
+ Basedir: filepath.Join("testdata", "build"),
+ InputVariables: Variables{
+ "name": &Variable{
+ Name: "name",
+ Type: cty.String,
+ Values: []VariableAssignment{{From: "default", Value: cty.StringVal("build-name")}},
+ },
+ },
+ LocalVariables: Variables{
+ "description": &Variable{
+ Name: "description",
+ Type: cty.String,
+ Values: []VariableAssignment{{From: "default", Value: cty.StringVal("This is the description for build-name.")}},
+ },
+ },
+ Sources: map[SourceRef]SourceBlock{
+ refVBIsoUbuntu1204: {Type: "virtualbox-iso", Name: "ubuntu-1204"},
+ },
+ Builds: Builds{
+ &BuildBlock{
+ Name: "build-name",
+ Description: "This is the description for build-name.",
+ Sources: []SourceUseBlock{
+ {
+ SourceRef: refVBIsoUbuntu1204,
+ },
+ },
+ },
+ },
+ },
+ false, false,
+ []packersdk.Build{
+ &packer.CoreBuild{
+ BuildName: "build-name",
+ Type: "virtualbox-iso.ubuntu-1204",
+ Prepared: true,
+ Builder: emptyMockBuilder,
+ Provisioners: []packer.CoreBuildProvisioner{},
+ PostProcessors: [][]packer.CoreBuildPostProcessor{},
+ },
+ },
+ false,
+ },
+ {"invalid variable for build name",
+ defaultParser,
+ parseTestArgs{"testdata/build/invalid_build_name_variable.pkr.hcl", nil, nil},
+ &PackerConfig{
+ CorePackerVersionString: lockedVersion,
+ Basedir: filepath.Join("testdata", "build"),
+ InputVariables: Variables{},
+ Builds: nil,
+ },
+ true, true,
+ []packersdk.Build{},
+ false,
+ },
+ {"use build.name in post-processor block",
+ defaultParser,
+ parseTestArgs{"testdata/build/post-processor_build_name_interpolation.pkr.hcl", nil, nil},
+ &PackerConfig{
+ CorePackerVersionString: lockedVersion,
+ Basedir: filepath.Join("testdata", "build"),
+ Sources: map[SourceRef]SourceBlock{
+ refVBIsoUbuntu1204: {Type: "virtualbox-iso", Name: "ubuntu-1204"},
+ },
+ Builds: Builds{
+ &BuildBlock{
+ Name: "test-build",
+ Sources: []SourceUseBlock{
+ {
+ SourceRef: refVBIsoUbuntu1204,
+ },
+ },
+ PostProcessorsLists: [][]*PostProcessorBlock{
+ {
+ {
+ PName: "test-build",
+ PType: "manifest",
+ },
+ },
+ },
+ },
+ },
+ },
+ false, false,
+ []packersdk.Build{
+ &packer.CoreBuild{
+ BuildName: "test-build",
+ Type: "virtualbox-iso.ubuntu-1204",
+ Prepared: true,
+ Builder: emptyMockBuilder,
+ Provisioners: []packer.CoreBuildProvisioner{},
+ PostProcessors: [][]packer.CoreBuildPostProcessor{
+ {
+ {
+ PName: "test-build",
+ PType: "manifest",
+ PostProcessor: &HCL2PostProcessor{
+ PostProcessor: &MockPostProcessor{
+ Config: MockConfig{
+ NestedMockConfig: NestedMockConfig{
+ Tags: []MockTag{},
+ SliceString: []string{lockedVersion, "test-build"},
+ },
+ NestedSlice: []NestedMockConfig{},
+ },
+ },
+ },
+ },
+ },
+ },
+ },
+ },
+ false,
+ },
+ {"use build.name in provisioner block",
+ defaultParser,
+ parseTestArgs{"testdata/build/provisioner_build_name_interpolation.pkr.hcl", nil, nil},
+ &PackerConfig{
+ CorePackerVersionString: lockedVersion,
+ Basedir: filepath.Join("testdata", "build"),
+ Sources: map[SourceRef]SourceBlock{
+ refVBIsoUbuntu1204: {Type: "virtualbox-iso", Name: "ubuntu-1204"},
+ },
+ Builds: Builds{
+ &BuildBlock{
+ Name: "build-name-test",
+ Sources: []SourceUseBlock{
+ {
+ SourceRef: refVBIsoUbuntu1204,
+ },
+ },
+ ProvisionerBlocks: []*ProvisionerBlock{
+ {
+ PName: "build-name-test",
+ PType: "shell",
+ },
+ },
+ },
+ },
+ },
+ false, false,
+ []packersdk.Build{
+ &packer.CoreBuild{
+ BuildName: "build-name-test",
+ Type: "virtualbox-iso.ubuntu-1204",
+ Prepared: true,
+ Builder: emptyMockBuilder,
+ Provisioners: []packer.CoreBuildProvisioner{
+ {
+ PName: "build-name-test",
+ PType: "shell",
+ Provisioner: &HCL2Provisioner{
+ Provisioner: &MockProvisioner{
+ Config: MockConfig{
+ NestedMockConfig: NestedMockConfig{
+ Tags: []MockTag{},
+ SliceString: []string{"build-name-test"},
+ },
+ NestedSlice: []NestedMockConfig{},
+ },
+ },
+ },
+ },
+ },
+ PostProcessors: [][]packer.CoreBuildPostProcessor{},
+ },
+ },
+ false,
+ },
+ }
+ testParse(t, tests)
+}
diff --git a/v1.9.4/hcl2template/types.datasource.go b/v1.9.4/hcl2template/types.datasource.go
new file mode 100644
index 0000000..9ae5e99
--- /dev/null
+++ b/v1.9.4/hcl2template/types.datasource.go
@@ -0,0 +1,160 @@
+// Copyright (c) HashiCorp, Inc.
+// SPDX-License-Identifier: MPL-2.0
+
+package hcl2template
+
+import (
+ "fmt"
+
+ "github.com/hashicorp/hcl/v2"
+ "github.com/hashicorp/hcl/v2/hclsyntax"
+ packersdk "github.com/hashicorp/packer-plugin-sdk/packer"
+ hcl2shim "github.com/hashicorp/packer/hcl2template/shim"
+ "github.com/hashicorp/packer/packer"
+ "github.com/zclconf/go-cty/cty"
+)
+
+// DatasourceBlock references an HCL 'data' block.
+type DatasourceBlock struct {
+ Type string
+ Name string
+
+ value cty.Value
+ block *hcl.Block
+}
+
+type DatasourceRef struct {
+ Type string
+ Name string
+}
+
+type Datasources map[DatasourceRef]DatasourceBlock
+
+func (data *DatasourceBlock) Ref() DatasourceRef {
+ return DatasourceRef{
+ Type: data.Type,
+ Name: data.Name,
+ }
+}
+
+func (ds *Datasources) Values() (map[string]cty.Value, hcl.Diagnostics) {
+ var diags hcl.Diagnostics
+ res := map[string]cty.Value{}
+ valuesMap := map[string]map[string]cty.Value{}
+
+ for ref, datasource := range *ds {
+ if datasource.value == (cty.Value{}) {
+ diags = append(diags, &hcl.Diagnostic{
+ Summary: fmt.Sprintf("empty value"),
+ Subject: &datasource.block.DefRange,
+ Severity: hcl.DiagError,
+ })
+ continue
+ }
+ inner := valuesMap[ref.Type]
+ if inner == nil {
+ inner = map[string]cty.Value{}
+ }
+ inner[ref.Name] = datasource.value
+ res[ref.Type] = cty.MapVal(inner)
+
+ // Keeps values of different datasources from same type
+ valuesMap[ref.Type] = inner
+ }
+
+ return res, diags
+}
+
+func (cfg *PackerConfig) startDatasource(dataSourceStore packer.DatasourceStore, ref DatasourceRef, secondaryEvaluation bool) (packersdk.Datasource, hcl.Diagnostics) {
+ var diags hcl.Diagnostics
+ block := cfg.Datasources[ref].block
+
+ if dataSourceStore == nil {
+ diags = append(diags, &hcl.Diagnostic{
+ Summary: "Unknown " + dataSourceLabel + " type " + ref.Type,
+ Subject: block.LabelRanges[0].Ptr(),
+ Detail: fmt.Sprintf("packer does not currently know any data source."),
+ Severity: hcl.DiagError,
+ })
+ return nil, diags
+ }
+
+ if !dataSourceStore.Has(ref.Type) {
+ diags = append(diags, &hcl.Diagnostic{
+ Summary: "Unknown " + dataSourceLabel + " type " + ref.Type,
+ Subject: block.LabelRanges[0].Ptr(),
+ Detail: fmt.Sprintf("known data sources: %v", dataSourceStore.List()),
+ Severity: hcl.DiagError,
+ })
+ return nil, diags
+ }
+
+ datasource, err := dataSourceStore.Start(ref.Type)
+ if err != nil {
+ diags = append(diags, &hcl.Diagnostic{
+ Summary: err.Error(),
+ Subject: &block.DefRange,
+ Severity: hcl.DiagError,
+ })
+ }
+ if datasource == nil {
+ diags = append(diags, &hcl.Diagnostic{
+ Summary: fmt.Sprintf("failed to start datasource plugin %q.%q", ref.Type, ref.Name),
+ Subject: &block.DefRange,
+ Severity: hcl.DiagError,
+ })
+ }
+
+ var decoded cty.Value
+ var moreDiags hcl.Diagnostics
+ body := block.Body
+ decoded, moreDiags = decodeHCL2Spec(body, cfg.EvalContext(DatasourceContext, nil), datasource)
+
+ diags = append(diags, moreDiags...)
+ if moreDiags.HasErrors() {
+ return nil, diags
+ }
+
+ // In case of cty.Unknown values, this will write a equivalent placeholder
+ // of the same type. Unknown types are not recognized by the json marshal
+ // during the RPC call and we have to do this here to avoid json parsing
+ // failures when running the validate command. We don't do this before so
+ // we can validate if variable type matches correctly on decodeHCL2Spec.
+ decoded = hcl2shim.WriteUnknownPlaceholderValues(decoded)
+ if err := datasource.Configure(decoded); err != nil {
+ diags = append(diags, &hcl.Diagnostic{
+ Summary: err.Error(),
+ Subject: &block.DefRange,
+ Severity: hcl.DiagError,
+ })
+ }
+ return datasource, diags
+}
+
+func (p *Parser) decodeDataBlock(block *hcl.Block) (*DatasourceBlock, hcl.Diagnostics) {
+ var diags hcl.Diagnostics
+ r := &DatasourceBlock{
+ Type: block.Labels[0],
+ Name: block.Labels[1],
+ block: block,
+ }
+
+ if !hclsyntax.ValidIdentifier(r.Type) {
+ diags = append(diags, &hcl.Diagnostic{
+ Severity: hcl.DiagError,
+ Summary: "Invalid data source name",
+ Detail: badIdentifierDetail,
+ Subject: &block.LabelRanges[0],
+ })
+ }
+ if !hclsyntax.ValidIdentifier(r.Name) {
+ diags = append(diags, &hcl.Diagnostic{
+ Severity: hcl.DiagError,
+ Summary: "Invalid data resource name",
+ Detail: badIdentifierDetail,
+ Subject: &block.LabelRanges[1],
+ })
+ }
+
+ return r, diags
+}
diff --git a/v1.9.4/hcl2template/types.datasource_test.go b/v1.9.4/hcl2template/types.datasource_test.go
new file mode 100644
index 0000000..b22f438
--- /dev/null
+++ b/v1.9.4/hcl2template/types.datasource_test.go
@@ -0,0 +1,237 @@
+// Copyright (c) HashiCorp, Inc.
+// SPDX-License-Identifier: MPL-2.0
+
+package hcl2template
+
+import (
+ "path/filepath"
+ "testing"
+
+ packersdk "github.com/hashicorp/packer-plugin-sdk/packer"
+ "github.com/hashicorp/packer/builder/null"
+ "github.com/hashicorp/packer/packer"
+)
+
+func TestParse_datasource(t *testing.T) {
+ defaultParser := getBasicParser()
+
+ tests := []parseTest{
+ {"two basic datasources",
+ defaultParser,
+ parseTestArgs{"testdata/datasources/basic.pkr.hcl", nil, nil},
+ &PackerConfig{
+ CorePackerVersionString: lockedVersion,
+ Builds: Builds{
+ &BuildBlock{
+ Sources: []SourceUseBlock{
+ {
+ SourceRef: SourceRef{
+ Type: "null",
+ Name: "test",
+ },
+ },
+ },
+ },
+ },
+ Sources: map[SourceRef]SourceBlock{
+ {
+ Type: "null",
+ Name: "test",
+ }: {
+ Type: "null",
+ Name: "test",
+ },
+ },
+ Basedir: filepath.Join("testdata", "datasources"),
+ Datasources: Datasources{
+ {
+ Type: "amazon-ami",
+ Name: "test",
+ }: {
+ Type: "amazon-ami",
+ Name: "test",
+ },
+ },
+ },
+ false, false,
+ []packersdk.Build{
+ &packer.CoreBuild{
+ Type: "null.test",
+ Builder: &null.Builder{},
+ Provisioners: []packer.CoreBuildProvisioner{},
+ PostProcessors: [][]packer.CoreBuildPostProcessor{},
+ Prepared: true,
+ },
+ },
+ false,
+ },
+ {"recursive datasources",
+ defaultParser,
+ parseTestArgs{"testdata/datasources/recursive.pkr.hcl", nil, nil},
+ &PackerConfig{
+ CorePackerVersionString: lockedVersion,
+ Builds: Builds{
+ &BuildBlock{
+ Sources: []SourceUseBlock{
+ {
+ SourceRef: SourceRef{
+ Type: "null",
+ Name: "test",
+ },
+ },
+ },
+ },
+ },
+ Sources: map[SourceRef]SourceBlock{
+ {
+ Type: "null",
+ Name: "test",
+ }: {
+ Type: "null",
+ Name: "test",
+ },
+ },
+ Basedir: filepath.Join("testdata", "datasources"),
+ Datasources: Datasources{
+ {
+ Type: "null",
+ Name: "foo",
+ }: {
+ Type: "null",
+ Name: "foo",
+ },
+ {
+ Type: "null",
+ Name: "bar",
+ }: {
+ Type: "null",
+ Name: "bar",
+ },
+ {
+ Type: "null",
+ Name: "baz",
+ }: {
+ Type: "null",
+ Name: "baz",
+ },
+ {
+ Type: "null",
+ Name: "bang",
+ }: {
+ Type: "null",
+ Name: "bang",
+ },
+ {
+ Type: "null",
+ Name: "yummy",
+ }: {
+ Type: "null",
+ Name: "yummy",
+ },
+ },
+ },
+ false, false,
+ []packersdk.Build{
+ &packer.CoreBuild{
+ Type: "null.test",
+ Builder: &null.Builder{},
+ Provisioners: []packer.CoreBuildProvisioner{},
+ PostProcessors: [][]packer.CoreBuildPostProcessor{},
+ Prepared: true,
+ },
+ },
+ false,
+ },
+ {"untyped datasource",
+ defaultParser,
+ parseTestArgs{"testdata/datasources/untyped.pkr.hcl", nil, nil},
+ &PackerConfig{
+ CorePackerVersionString: lockedVersion,
+ Basedir: filepath.Join("testdata", "datasources"),
+ },
+ true, true,
+ nil,
+ false,
+ },
+ {"unnamed source",
+ defaultParser,
+ parseTestArgs{"testdata/datasources/unnamed.pkr.hcl", nil, nil},
+ &PackerConfig{
+ CorePackerVersionString: lockedVersion,
+ Basedir: filepath.Join("testdata", "datasources"),
+ },
+ true, true,
+ nil,
+ false,
+ },
+ {"nonexistent source",
+ defaultParser,
+ parseTestArgs{"testdata/datasources/nonexistent.pkr.hcl", nil, nil},
+ &PackerConfig{
+ CorePackerVersionString: lockedVersion,
+ Basedir: filepath.Join("testdata", "datasources"),
+ Datasources: Datasources{
+ {
+ Type: "nonexistent",
+ Name: "test",
+ }: {
+ Type: "nonexistent",
+ Name: "test",
+ },
+ },
+ },
+ true, true,
+ nil,
+ false,
+ },
+ {"duplicate source",
+ defaultParser,
+ parseTestArgs{"testdata/datasources/duplicate.pkr.hcl", nil, nil},
+ &PackerConfig{
+ CorePackerVersionString: lockedVersion,
+ Basedir: filepath.Join("testdata", "datasources"),
+ Datasources: Datasources{
+ {
+ Type: "amazon-ami",
+ Name: "test",
+ }: {
+ Type: "amazon-ami",
+ Name: "test",
+ },
+ },
+ },
+ true, true,
+ nil,
+ false,
+ },
+ {"cyclic dependency between data sources",
+ defaultParser,
+ parseTestArgs{"testdata/datasources/dependency_cycle.pkr.hcl", nil, nil},
+ &PackerConfig{
+ CorePackerVersionString: lockedVersion,
+ Basedir: filepath.Join("testdata", "datasources"),
+ Datasources: Datasources{
+ {
+ Type: "null",
+ Name: "gummy",
+ }: {
+ Type: "null",
+ Name: "gummy",
+ },
+ {
+ Type: "null",
+ Name: "bear",
+ }: {
+ Type: "null",
+ Name: "bear",
+ },
+ },
+ },
+ true, true,
+ nil,
+ false,
+ },
+ }
+
+ testParse(t, tests)
+}
diff --git a/v1.9.4/hcl2template/types.hcl_post-processor.go b/v1.9.4/hcl2template/types.hcl_post-processor.go
new file mode 100644
index 0000000..26974aa
--- /dev/null
+++ b/v1.9.4/hcl2template/types.hcl_post-processor.go
@@ -0,0 +1,85 @@
+// Copyright (c) HashiCorp, Inc.
+// SPDX-License-Identifier: MPL-2.0
+
+package hcl2template
+
+import (
+ "context"
+
+ "github.com/hashicorp/hcl/v2"
+ "github.com/hashicorp/hcl/v2/hcldec"
+ packersdk "github.com/hashicorp/packer-plugin-sdk/packer"
+ hcl2shim "github.com/hashicorp/packer/hcl2template/shim"
+ "github.com/zclconf/go-cty/cty"
+)
+
+// HCL2PostProcessor has a reference to the part of the HCL2 body where it is
+// defined, allowing to completely reconfigure the PostProcessor right before
+// calling PostProcess: with contextual variables.
+// This permits using "${build.ID}" values for example.
+type HCL2PostProcessor struct {
+ PostProcessor packersdk.PostProcessor
+ postProcessorBlock *PostProcessorBlock
+ evalContext *hcl.EvalContext
+ builderVariables map[string]string
+}
+
+func (p *HCL2PostProcessor) ConfigSpec() hcldec.ObjectSpec {
+ return p.PostProcessor.ConfigSpec()
+}
+
+func (p *HCL2PostProcessor) HCL2Prepare(buildVars map[string]interface{}) error {
+ var diags hcl.Diagnostics
+ ectx := p.evalContext
+ if len(buildVars) > 0 {
+ ectx = p.evalContext.NewChild()
+ buildValues := map[string]cty.Value{}
+ if !p.evalContext.Variables[buildAccessor].IsNull() {
+ buildValues = p.evalContext.Variables[buildAccessor].AsValueMap()
+ }
+ for k, v := range buildVars {
+ val, err := ConvertPluginConfigValueToHCLValue(v)
+ if err != nil {
+ return err
+ }
+
+ buildValues[k] = val
+ }
+ ectx.Variables = map[string]cty.Value{
+ buildAccessor: cty.ObjectVal(buildValues),
+ }
+ }
+
+ flatPostProcessorCfg, moreDiags := decodeHCL2Spec(p.postProcessorBlock.HCL2Ref.Rest, ectx, p.PostProcessor)
+ diags = append(diags, moreDiags...)
+ if diags.HasErrors() {
+ return diags
+ }
+
+ // In case of cty.Unknown values, this will write a equivalent placeholder of the same type
+ // Unknown types are not recognized by the json marshal during the RPC call and we have to do this here
+ // to avoid json parsing failures when running the validate command.
+ // We don't do this before so we can validate if variable types matches correctly on decodeHCL2Spec.
+ flatPostProcessorCfg = hcl2shim.WriteUnknownPlaceholderValues(flatPostProcessorCfg)
+
+ return p.PostProcessor.Configure(p.builderVariables, flatPostProcessorCfg)
+}
+
+func (p *HCL2PostProcessor) Configure(args ...interface{}) error {
+ return p.PostProcessor.Configure(args...)
+}
+
+func (p *HCL2PostProcessor) PostProcess(ctx context.Context, ui packersdk.Ui, artifact packersdk.Artifact) (packersdk.Artifact, bool, bool, error) {
+ generatedData := make(map[string]interface{})
+ if artifactStateData, ok := artifact.State("generated_data").(map[interface{}]interface{}); ok {
+ for k, v := range artifactStateData {
+ generatedData[k.(string)] = v
+ }
+ }
+
+ err := p.HCL2Prepare(generatedData)
+ if err != nil {
+ return nil, false, false, err
+ }
+ return p.PostProcessor.PostProcess(ctx, ui, artifact)
+}
diff --git a/v1.9.4/hcl2template/types.hcl_provisioner.go b/v1.9.4/hcl2template/types.hcl_provisioner.go
new file mode 100644
index 0000000..022a2fd
--- /dev/null
+++ b/v1.9.4/hcl2template/types.hcl_provisioner.go
@@ -0,0 +1,79 @@
+// Copyright (c) HashiCorp, Inc.
+// SPDX-License-Identifier: MPL-2.0
+
+package hcl2template
+
+import (
+ "context"
+
+ "github.com/hashicorp/hcl/v2"
+ "github.com/hashicorp/hcl/v2/hcldec"
+ packersdk "github.com/hashicorp/packer-plugin-sdk/packer"
+ hcl2shim "github.com/hashicorp/packer/hcl2template/shim"
+ "github.com/zclconf/go-cty/cty"
+)
+
+// HCL2Provisioner has a reference to the part of the HCL2 body where it is
+// defined, allowing to completely reconfigure the Provisioner right before
+// calling Provision: with contextual variables.
+// This permits using "${build.ID}" values for example.
+type HCL2Provisioner struct {
+ Provisioner packersdk.Provisioner
+ provisionerBlock *ProvisionerBlock
+ evalContext *hcl.EvalContext
+ builderVariables map[string]string
+ override map[string]interface{}
+}
+
+func (p *HCL2Provisioner) ConfigSpec() hcldec.ObjectSpec {
+ return p.Provisioner.ConfigSpec()
+}
+
+func (p *HCL2Provisioner) HCL2Prepare(buildVars map[string]interface{}) error {
+ var diags hcl.Diagnostics
+ ectx := p.evalContext
+ if len(buildVars) > 0 {
+ ectx = p.evalContext.NewChild()
+ buildValues := map[string]cty.Value{}
+ if !p.evalContext.Variables[buildAccessor].IsNull() {
+ buildValues = p.evalContext.Variables[buildAccessor].AsValueMap()
+ }
+ for k, v := range buildVars {
+ val, err := ConvertPluginConfigValueToHCLValue(v)
+ if err != nil {
+ return err
+ }
+
+ buildValues[k] = val
+ }
+ ectx.Variables = map[string]cty.Value{
+ buildAccessor: cty.ObjectVal(buildValues),
+ }
+ }
+
+ flatProvisionerCfg, moreDiags := decodeHCL2Spec(p.provisionerBlock.HCL2Ref.Rest, ectx, p.Provisioner)
+ diags = append(diags, moreDiags...)
+ if diags.HasErrors() {
+ return diags
+ }
+
+ // In case of cty.Unknown values, this will write a equivalent placeholder of the same type
+ // Unknown types are not recognized by the json marshal during the RPC call and we have to do this here
+ // to avoid json parsing failures when running the validate command.
+ // We don't do this before so we can validate if variable types matches correctly on decodeHCL2Spec.
+ flatProvisionerCfg = hcl2shim.WriteUnknownPlaceholderValues(flatProvisionerCfg)
+
+ return p.Provisioner.Prepare(p.builderVariables, flatProvisionerCfg, p.override)
+}
+
+func (p *HCL2Provisioner) Prepare(args ...interface{}) error {
+ return p.Provisioner.Prepare(args...)
+}
+
+func (p *HCL2Provisioner) Provision(ctx context.Context, ui packersdk.Ui, c packersdk.Communicator, vars map[string]interface{}) error {
+ err := p.HCL2Prepare(vars)
+ if err != nil {
+ return err
+ }
+ return p.Provisioner.Provision(ctx, ui, c, vars)
+}
diff --git a/v1.9.4/hcl2template/types.hcl_ref.go b/v1.9.4/hcl2template/types.hcl_ref.go
new file mode 100644
index 0000000..091a204
--- /dev/null
+++ b/v1.9.4/hcl2template/types.hcl_ref.go
@@ -0,0 +1,31 @@
+// Copyright (c) HashiCorp, Inc.
+// SPDX-License-Identifier: MPL-2.0
+
+package hcl2template
+
+import (
+ "github.com/hashicorp/hcl/v2"
+)
+
+// HCL2Ref references to the source definition in configuration text file. It
+// is used to tell were something was wrong, - like a warning or an error -
+// long after it was parsed; allowing to give pointers as to where change/fix
+// things in a file.
+type HCL2Ref struct {
+ // references
+ DefRange hcl.Range
+ TypeRange hcl.Range
+ LabelsRanges []hcl.Range
+
+ // remainder of unparsed body
+ Rest hcl.Body
+}
+
+func newHCL2Ref(block *hcl.Block, rest hcl.Body) HCL2Ref {
+ return HCL2Ref{
+ Rest: rest,
+ DefRange: block.DefRange,
+ TypeRange: block.TypeRange,
+ LabelsRanges: block.LabelRanges,
+ }
+}
diff --git a/v1.9.4/hcl2template/types.packer_config.go b/v1.9.4/hcl2template/types.packer_config.go
new file mode 100644
index 0000000..003db57
--- /dev/null
+++ b/v1.9.4/hcl2template/types.packer_config.go
@@ -0,0 +1,882 @@
+// Copyright (c) HashiCorp, Inc.
+// SPDX-License-Identifier: MPL-2.0
+
+package hcl2template
+
+import (
+ "fmt"
+ "log"
+ "sort"
+ "strings"
+
+ "github.com/gobwas/glob"
+ hcl "github.com/hashicorp/hcl/v2"
+ "github.com/hashicorp/hcl/v2/hcldec"
+ "github.com/hashicorp/hcl/v2/hclsyntax"
+ packersdk "github.com/hashicorp/packer-plugin-sdk/packer"
+ pkrfunction "github.com/hashicorp/packer/hcl2template/function"
+ "github.com/hashicorp/packer/packer"
+ "github.com/zclconf/go-cty/cty"
+ "github.com/zclconf/go-cty/cty/function"
+)
+
+// PackerConfig represents a loaded Packer HCL config. It will contain
+// references to all possible blocks of the allowed configuration.
+type PackerConfig struct {
+ Packer struct {
+ VersionConstraints []VersionConstraint
+ RequiredPlugins []*RequiredPlugins
+ }
+
+ // Directory where the config files are defined
+ Basedir string
+
+ // Core Packer version, for reference by plugins and template functions.
+ CorePackerVersionString string
+
+ // directory Packer was called from
+ Cwd string
+
+ // Available Source blocks
+ Sources map[SourceRef]SourceBlock
+
+ // InputVariables and LocalVariables are the list of defined input and
+ // local variables. They are of the same type but are not used in the same
+ // way. Local variables will not be decoded from any config file, env var,
+ // or ect. Like the Input variables will.
+ InputVariables Variables
+ LocalVariables Variables
+
+ Datasources Datasources
+
+ LocalBlocks []*LocalBlock
+
+ ValidationOptions
+
+ // Builds is the list of Build blocks defined in the config files.
+ Builds Builds
+
+ // HCPVars is the list of HCP-set variables for use later in a template
+ HCPVars map[string]cty.Value
+
+ parser *Parser
+ files []*hcl.File
+
+ // Fields passed as command line flags
+ except []glob.Glob
+ only []glob.Glob
+ force bool
+ debug bool
+ onError string
+}
+
+type ValidationOptions struct {
+ WarnOnUndeclaredVar bool
+}
+
+const (
+ inputVariablesAccessor = "var"
+ localsAccessor = "local"
+ pathVariablesAccessor = "path"
+ sourcesAccessor = "source"
+ buildAccessor = "build"
+ packerAccessor = "packer"
+ dataAccessor = "data"
+)
+
+type BlockContext int
+
+const (
+ InputVariableContext BlockContext = iota
+ LocalContext
+ BuildContext
+ DatasourceContext
+ NilContext
+)
+
+// EvalContext returns the *hcl.EvalContext that will be passed to an hcl
+// decoder in order to tell what is the actual value of a var or a local and
+// the list of defined functions.
+func (cfg *PackerConfig) EvalContext(ctx BlockContext, variables map[string]cty.Value) *hcl.EvalContext {
+ inputVariables := cfg.InputVariables.Values()
+ localVariables := cfg.LocalVariables.Values()
+ ectx := &hcl.EvalContext{
+ Functions: Functions(cfg.Basedir),
+ Variables: map[string]cty.Value{
+ inputVariablesAccessor: cty.ObjectVal(inputVariables),
+ localsAccessor: cty.ObjectVal(localVariables),
+ sourcesAccessor: cty.ObjectVal(map[string]cty.Value{
+ "type": cty.UnknownVal(cty.String),
+ "name": cty.UnknownVal(cty.String),
+ }),
+ buildAccessor: cty.UnknownVal(cty.EmptyObject),
+ packerAccessor: cty.ObjectVal(map[string]cty.Value{
+ "version": cty.StringVal(cfg.CorePackerVersionString),
+ "iterationID": cty.UnknownVal(cty.String),
+ }),
+ pathVariablesAccessor: cty.ObjectVal(map[string]cty.Value{
+ "cwd": cty.StringVal(strings.ReplaceAll(cfg.Cwd, `\`, `/`)),
+ "root": cty.StringVal(strings.ReplaceAll(cfg.Basedir, `\`, `/`)),
+ }),
+ },
+ }
+
+ iterID, ok := cfg.HCPVars["iterationID"]
+ if ok {
+ ectx.Variables[packerAccessor] = cty.ObjectVal(map[string]cty.Value{
+ "version": cty.StringVal(cfg.CorePackerVersionString),
+ "iterationID": iterID,
+ })
+ }
+
+ // In the future we'd like to load and execute HCL blocks using a graph
+ // dependency tree, so that any block can use any block whatever the
+ // order.
+ // For now, don't add DataSources if there's a NilContext, which gets
+ // used with packer console.
+ switch ctx {
+ case LocalContext, BuildContext, DatasourceContext:
+ datasourceVariables, _ := cfg.Datasources.Values()
+ ectx.Variables[dataAccessor] = cty.ObjectVal(datasourceVariables)
+ }
+
+ for k, v := range variables {
+ ectx.Variables[k] = v
+ }
+ return ectx
+}
+
+// decodeInputVariables looks in the found blocks for 'variables' and
+// 'variable' blocks. It should be called firsthand so that other blocks can
+// use the variables.
+func (c *PackerConfig) decodeInputVariables(f *hcl.File) hcl.Diagnostics {
+ var diags hcl.Diagnostics
+
+ content, moreDiags := f.Body.Content(configSchema)
+ diags = append(diags, moreDiags...)
+
+ // for input variables we allow to use env in the default value section.
+ ectx := &hcl.EvalContext{
+ Functions: map[string]function.Function{
+ "env": pkrfunction.EnvFunc,
+ },
+ }
+
+ for _, block := range content.Blocks {
+ switch block.Type {
+ case variableLabel:
+ moreDiags := c.InputVariables.decodeVariableBlock(block, ectx)
+ diags = append(diags, moreDiags...)
+ case variablesLabel:
+ attrs, moreDiags := block.Body.JustAttributes()
+ diags = append(diags, moreDiags...)
+ for key, attr := range attrs {
+ moreDiags = c.InputVariables.decodeVariable(key, attr, ectx)
+ diags = append(diags, moreDiags...)
+ }
+ }
+ }
+ return diags
+}
+
+// parseLocalVariableBlocks looks in the AST for 'local' and 'locals' blocks and
+// returns them all.
+func parseLocalVariableBlocks(f *hcl.File) ([]*LocalBlock, hcl.Diagnostics) {
+ var diags hcl.Diagnostics
+
+ content, moreDiags := f.Body.Content(configSchema)
+ diags = append(diags, moreDiags...)
+
+ var locals []*LocalBlock
+
+ for _, block := range content.Blocks {
+ switch block.Type {
+ case localLabel:
+ block, moreDiags := decodeLocalBlock(block)
+ diags = append(diags, moreDiags...)
+ if moreDiags.HasErrors() {
+ return locals, diags
+ }
+ locals = append(locals, block)
+ case localsLabel:
+ attrs, moreDiags := block.Body.JustAttributes()
+ diags = append(diags, moreDiags...)
+ for name, attr := range attrs {
+ locals = append(locals, &LocalBlock{
+ Name: name,
+ Expr: attr.Expr,
+ })
+ }
+ }
+ }
+
+ return locals, diags
+}
+
+func (c *PackerConfig) evaluateAllLocalVariables(locals []*LocalBlock) hcl.Diagnostics {
+ var diags hcl.Diagnostics
+
+ for _, local := range locals {
+ diags = append(diags, c.evaluateLocalVariable(local)...)
+ }
+
+ return diags
+}
+
+func (c *PackerConfig) evaluateLocalVariables(locals []*LocalBlock) hcl.Diagnostics {
+ var diags hcl.Diagnostics
+
+ if len(locals) == 0 {
+ return diags
+ }
+
+ if c.LocalVariables == nil {
+ c.LocalVariables = Variables{}
+ }
+
+ for foundSomething := true; foundSomething; {
+ foundSomething = false
+ for i := 0; i < len(locals); {
+ local := locals[i]
+ moreDiags := c.evaluateLocalVariable(local)
+ if moreDiags.HasErrors() {
+ i++
+ continue
+ }
+ foundSomething = true
+ locals = append(locals[:i], locals[i+1:]...)
+ }
+ }
+
+ if len(locals) != 0 {
+ // get errors from remaining variables
+ return c.evaluateAllLocalVariables(locals)
+ }
+
+ return diags
+}
+
+func checkForDuplicateLocalDefinition(locals []*LocalBlock) hcl.Diagnostics {
+ var diags hcl.Diagnostics
+
+ // we could sort by name and then check contiguous names to use less memory,
+ // but using a map sounds good enough.
+ names := map[string]struct{}{}
+ for _, local := range locals {
+ if _, found := names[local.Name]; found {
+ diags = append(diags, &hcl.Diagnostic{
+ Severity: hcl.DiagError,
+ Summary: "Duplicate local definition",
+ Detail: "Duplicate " + local.Name + " definition found.",
+ Subject: local.Expr.Range().Ptr(),
+ })
+ continue
+ }
+ names[local.Name] = struct{}{}
+ }
+ return diags
+}
+
+func (c *PackerConfig) evaluateLocalVariable(local *LocalBlock) hcl.Diagnostics {
+ var diags hcl.Diagnostics
+
+ value, moreDiags := local.Expr.Value(c.EvalContext(LocalContext, nil))
+ diags = append(diags, moreDiags...)
+ if moreDiags.HasErrors() {
+ return diags
+ }
+ c.LocalVariables[local.Name] = &Variable{
+ Name: local.Name,
+ Sensitive: local.Sensitive,
+ Values: []VariableAssignment{{
+ Value: value,
+ Expr: local.Expr,
+ From: "default",
+ }},
+ Type: value.Type(),
+ }
+
+ return diags
+}
+
+func (cfg *PackerConfig) evaluateDatasources(skipExecution bool) hcl.Diagnostics {
+ var diags hcl.Diagnostics
+
+ dependencies := map[DatasourceRef][]DatasourceRef{}
+ for ref, ds := range cfg.Datasources {
+ if ds.value != (cty.Value{}) {
+ continue
+ }
+ // Pre-examine body of this data source to see if it uses another data
+ // source in any of its input expressions. If so, skip evaluating it for
+ // now, and add it to a list of datasources to evaluate again, later,
+ // with the datasources in its context.
+ // This is essentially creating a very primitive DAG just for data
+ // source interdependencies.
+ block := ds.block
+ body := block.Body
+ attrs, _ := body.JustAttributes()
+
+ skipFirstEval := false
+ for _, attr := range attrs {
+ vars := attr.Expr.Variables()
+ for _, v := range vars {
+ // check whether the variable is a data source
+ if v.RootName() == "data" {
+ // construct, backwards, the data source type and name we
+ // need to evaluate before this one can be evaluated.
+ dependsOn := DatasourceRef{
+ Type: v[1].(hcl.TraverseAttr).Name,
+ Name: v[2].(hcl.TraverseAttr).Name,
+ }
+ log.Printf("The data source %#v depends on datasource %#v", ref, dependsOn)
+ if dependencies[ref] != nil {
+ dependencies[ref] = append(dependencies[ref], dependsOn)
+ } else {
+ dependencies[ref] = []DatasourceRef{dependsOn}
+ }
+ skipFirstEval = true
+ }
+ }
+ }
+
+ // Now we have a list of data sources that depend on other data sources.
+ // Don't evaluate these; only evaluate data sources that we didn't
+ // mark as having dependencies.
+ if skipFirstEval {
+ continue
+ }
+
+ datasource, startDiags := cfg.startDatasource(cfg.parser.PluginConfig.DataSources, ref, false)
+ diags = append(diags, startDiags...)
+ if diags.HasErrors() {
+ continue
+ }
+
+ if skipExecution {
+ placeholderValue := cty.UnknownVal(hcldec.ImpliedType(datasource.OutputSpec()))
+ ds.value = placeholderValue
+ cfg.Datasources[ref] = ds
+ continue
+ }
+
+ dsOpts, _ := decodeHCL2Spec(body, cfg.EvalContext(DatasourceContext, nil), datasource)
+ sp := packer.CheckpointReporter.AddSpan(ref.Type, "datasource", dsOpts)
+ realValue, err := datasource.Execute()
+ sp.End(err)
+ if err != nil {
+ diags = append(diags, &hcl.Diagnostic{
+ Summary: err.Error(),
+ Subject: &cfg.Datasources[ref].block.DefRange,
+ Severity: hcl.DiagError,
+ })
+ continue
+ }
+
+ ds.value = realValue
+ cfg.Datasources[ref] = ds
+ }
+
+ // Now that most of our data sources have been started and executed, we can
+ // try to execute the ones that depend on other data sources.
+ for ref := range dependencies {
+ _, moreDiags, _ := cfg.recursivelyEvaluateDatasources(ref, dependencies, skipExecution, 0)
+ // Deduplicate diagnostics to prevent recursion messes.
+ cleanedDiags := map[string]*hcl.Diagnostic{}
+ for _, diag := range moreDiags {
+ cleanedDiags[diag.Summary] = diag
+ }
+
+ for _, diag := range cleanedDiags {
+ diags = append(diags, diag)
+ }
+ }
+
+ return diags
+}
+
+func (cfg *PackerConfig) recursivelyEvaluateDatasources(ref DatasourceRef, dependencies map[DatasourceRef][]DatasourceRef, skipExecution bool, depth int) (map[DatasourceRef][]DatasourceRef, hcl.Diagnostics, bool) {
+ var diags hcl.Diagnostics
+ var moreDiags hcl.Diagnostics
+ shouldContinue := true
+
+ if depth > 10 {
+ // Add a comment about recursion.
+ diags = append(diags, &hcl.Diagnostic{
+ Severity: hcl.DiagError,
+ Summary: "Max datasource recursion depth exceeded.",
+ Detail: "An error occured while recursively evaluating data " +
+ "sources. Either your data source depends on more than ten " +
+ "other data sources, or your data sources have a cyclic " +
+ "dependency. Please simplify your config to continue. ",
+ })
+ return dependencies, diags, false
+ }
+
+ ds := cfg.Datasources[ref]
+ // Make sure everything ref depends on has already been evaluated.
+ for _, dep := range dependencies[ref] {
+ if _, ok := dependencies[dep]; ok {
+ depth += 1
+ // If this dependency is not in the map, it means we've already
+ // launched and executed this datasource. Otherwise, it means
+ // we still need to run it. RECURSION TIME!!
+ dependencies, moreDiags, shouldContinue = cfg.recursivelyEvaluateDatasources(dep, dependencies, skipExecution, depth)
+ diags = append(diags, moreDiags...)
+ if moreDiags.HasErrors() {
+ diags = append(diags, moreDiags...)
+ return dependencies, diags, shouldContinue
+ }
+ }
+ }
+ // If we've gotten here, then it means ref doesn't seem to have any further
+ // dependencies we need to evaluate first. Evaluate it, with the cfg's full
+ // data source context.
+ datasource, startDiags := cfg.startDatasource(cfg.parser.PluginConfig.DataSources, ref, true)
+ if startDiags.HasErrors() {
+ diags = append(diags, startDiags...)
+ return dependencies, diags, shouldContinue
+ }
+
+ if skipExecution {
+ placeholderValue := cty.UnknownVal(hcldec.ImpliedType(datasource.OutputSpec()))
+ ds.value = placeholderValue
+ cfg.Datasources[ref] = ds
+ return dependencies, diags, shouldContinue
+ }
+
+ opts, _ := decodeHCL2Spec(ds.block.Body, cfg.EvalContext(DatasourceContext, nil), datasource)
+ sp := packer.CheckpointReporter.AddSpan(ref.Type, "datasource", opts)
+ realValue, err := datasource.Execute()
+ sp.End(err)
+ if err != nil {
+ diags = append(diags, &hcl.Diagnostic{
+ Summary: err.Error(),
+ Subject: &cfg.Datasources[ref].block.DefRange,
+ Severity: hcl.DiagError,
+ })
+ return dependencies, diags, shouldContinue
+ }
+
+ ds.value = realValue
+ cfg.Datasources[ref] = ds
+ // remove ref from the dependencies map.
+ delete(dependencies, ref)
+ return dependencies, diags, shouldContinue
+}
+
+// getCoreBuildProvisioners takes a list of provisioner block, starts according
+// provisioners and sends parsed HCL2 over to it.
+func (cfg *PackerConfig) getCoreBuildProvisioners(source SourceUseBlock, blocks []*ProvisionerBlock, ectx *hcl.EvalContext) ([]packer.CoreBuildProvisioner, hcl.Diagnostics) {
+ var diags hcl.Diagnostics
+ res := []packer.CoreBuildProvisioner{}
+ for _, pb := range blocks {
+ if pb.OnlyExcept.Skip(source.String()) {
+ continue
+ }
+
+ coreBuildProv, moreDiags := cfg.getCoreBuildProvisioner(source, pb, ectx)
+ diags = append(diags, moreDiags...)
+ if moreDiags.HasErrors() {
+ continue
+ }
+ res = append(res, coreBuildProv)
+ }
+ return res, diags
+}
+
+func (cfg *PackerConfig) getCoreBuildProvisioner(source SourceUseBlock, pb *ProvisionerBlock, ectx *hcl.EvalContext) (packer.CoreBuildProvisioner, hcl.Diagnostics) {
+ var diags hcl.Diagnostics
+ provisioner, moreDiags := cfg.startProvisioner(source, pb, ectx)
+ diags = append(diags, moreDiags...)
+ if moreDiags.HasErrors() {
+ return packer.CoreBuildProvisioner{}, diags
+ }
+
+ flatProvisionerCfg, _ := decodeHCL2Spec(pb.HCL2Ref.Rest, ectx, provisioner)
+
+ // If we're pausing, we wrap the provisioner in a special pauser.
+ if pb.PauseBefore != 0 {
+ provisioner = &packer.PausedProvisioner{
+ PauseBefore: pb.PauseBefore,
+ Provisioner: provisioner,
+ }
+ } else if pb.Timeout != 0 {
+ provisioner = &packer.TimeoutProvisioner{
+ Timeout: pb.Timeout,
+ Provisioner: provisioner,
+ }
+ }
+ if pb.MaxRetries != 0 {
+ provisioner = &packer.RetriedProvisioner{
+ MaxRetries: pb.MaxRetries,
+ Provisioner: provisioner,
+ }
+ }
+
+ return packer.CoreBuildProvisioner{
+ PType: pb.PType,
+ PName: pb.PName,
+ Provisioner: provisioner,
+ HCLConfig: flatProvisionerCfg,
+ }, diags
+}
+
+// getCoreBuildProvisioners takes a list of post processor block, starts
+// according provisioners and sends parsed HCL2 over to it.
+func (cfg *PackerConfig) getCoreBuildPostProcessors(source SourceUseBlock, blocksList [][]*PostProcessorBlock, ectx *hcl.EvalContext, exceptMatches *int) ([][]packer.CoreBuildPostProcessor, hcl.Diagnostics) {
+ var diags hcl.Diagnostics
+ res := [][]packer.CoreBuildPostProcessor{}
+ for _, blocks := range blocksList {
+ pps := []packer.CoreBuildPostProcessor{}
+ for _, ppb := range blocks {
+ if ppb.OnlyExcept.Skip(source.String()) {
+ continue
+ }
+
+ name := ppb.PName
+ if name == "" {
+ name = ppb.PType
+ }
+ // -except
+ exclude := false
+ for _, exceptGlob := range cfg.except {
+ if exceptGlob.Match(name) {
+ exclude = true
+ *exceptMatches = *exceptMatches + 1
+ break
+ }
+ }
+ if exclude {
+ break
+ }
+
+ postProcessor, moreDiags := cfg.startPostProcessor(source, ppb, ectx)
+ diags = append(diags, moreDiags...)
+ if moreDiags.HasErrors() {
+ continue
+ }
+
+ flatPostProcessorCfg, moreDiags := decodeHCL2Spec(ppb.HCL2Ref.Rest, ectx, postProcessor)
+
+ pps = append(pps, packer.CoreBuildPostProcessor{
+ PostProcessor: postProcessor,
+ PName: ppb.PName,
+ PType: ppb.PType,
+ HCLConfig: flatPostProcessorCfg,
+ KeepInputArtifact: ppb.KeepInputArtifact,
+ })
+ }
+ if len(pps) > 0 {
+ res = append(res, pps)
+ }
+ }
+
+ return res, diags
+}
+
+// GetBuilds returns a list of packer Build based on the HCL2 parsed build
+// blocks. All Builders, Provisioners and Post Processors will be started and
+// configured.
+func (cfg *PackerConfig) GetBuilds(opts packer.GetBuildsOptions) ([]packersdk.Build, hcl.Diagnostics) {
+ res := []packersdk.Build{}
+ var diags hcl.Diagnostics
+ possibleBuildNames := []string{}
+
+ cfg.debug = opts.Debug
+ cfg.force = opts.Force
+ cfg.onError = opts.OnError
+
+ if len(cfg.Builds) == 0 {
+ return res, append(diags, &hcl.Diagnostic{
+ Summary: "Missing build block",
+ Detail: "A build block with one or more sources is required for executing a build.",
+ Severity: hcl.DiagError,
+ })
+ }
+
+ for _, build := range cfg.Builds {
+ for _, srcUsage := range build.Sources {
+ src, found := cfg.Sources[srcUsage.SourceRef]
+ if !found {
+ diags = append(diags, &hcl.Diagnostic{
+ Summary: "Unknown " + sourceLabel + " " + srcUsage.String(),
+ Subject: build.HCL2Ref.DefRange.Ptr(),
+ Severity: hcl.DiagError,
+ Detail: fmt.Sprintf("Known: %v", cfg.Sources),
+ })
+ continue
+ }
+
+ pcb := &packer.CoreBuild{
+ BuildName: build.Name,
+ Type: srcUsage.String(),
+ }
+
+ pcb.SetDebug(cfg.debug)
+ pcb.SetForce(cfg.force)
+ pcb.SetOnError(cfg.onError)
+
+ // Apply the -only and -except command-line options to exclude matching builds.
+ buildName := pcb.Name()
+ possibleBuildNames = append(possibleBuildNames, buildName)
+ // -only
+ if len(opts.Only) > 0 {
+ onlyGlobs, diags := convertFilterOption(opts.Only, "only")
+ if diags.HasErrors() {
+ return nil, diags
+ }
+ cfg.only = onlyGlobs
+ include := false
+ for _, onlyGlob := range onlyGlobs {
+ if onlyGlob.Match(buildName) {
+ include = true
+ break
+ }
+ }
+ if !include {
+ continue
+ }
+ opts.OnlyMatches++
+ }
+
+ // -except
+ if len(opts.Except) > 0 {
+ exceptGlobs, diags := convertFilterOption(opts.Except, "except")
+ if diags.HasErrors() {
+ return nil, diags
+ }
+ cfg.except = exceptGlobs
+ exclude := false
+ for _, exceptGlob := range exceptGlobs {
+ if exceptGlob.Match(buildName) {
+ exclude = true
+ break
+ }
+ }
+ if exclude {
+ opts.ExceptMatches++
+ continue
+ }
+ }
+
+ builder, moreDiags, generatedVars := cfg.startBuilder(srcUsage, cfg.EvalContext(BuildContext, nil))
+ diags = append(diags, moreDiags...)
+ if moreDiags.HasErrors() {
+ continue
+ }
+
+ decoded, _ := decodeHCL2Spec(srcUsage.Body, cfg.EvalContext(BuildContext, nil), builder)
+ pcb.HCLConfig = decoded
+
+ // If the builder has provided a list of to-be-generated variables that
+ // should be made accessible to provisioners, pass that list into
+ // the provisioner prepare() so that the provisioner can appropriately
+ // validate user input against what will become available. Otherwise,
+ // only pass the default variables, using the basic placeholder data.
+ unknownBuildValues := map[string]cty.Value{}
+ for _, k := range append(packer.BuilderDataCommonKeys, generatedVars...) {
+ unknownBuildValues[k] = cty.StringVal("<unknown>")
+ }
+ unknownBuildValues["name"] = cty.StringVal(build.Name)
+
+ variables := map[string]cty.Value{
+ sourcesAccessor: cty.ObjectVal(srcUsage.ctyValues()),
+ buildAccessor: cty.ObjectVal(unknownBuildValues),
+ }
+
+ provisioners, moreDiags := cfg.getCoreBuildProvisioners(srcUsage, build.ProvisionerBlocks, cfg.EvalContext(BuildContext, variables))
+ diags = append(diags, moreDiags...)
+ if moreDiags.HasErrors() {
+ continue
+ }
+ pps, moreDiags := cfg.getCoreBuildPostProcessors(srcUsage, build.PostProcessorsLists, cfg.EvalContext(BuildContext, variables), &opts.ExceptMatches)
+ diags = append(diags, moreDiags...)
+ if moreDiags.HasErrors() {
+ continue
+ }
+
+ if build.ErrorCleanupProvisionerBlock != nil &&
+ !build.ErrorCleanupProvisionerBlock.OnlyExcept.Skip(srcUsage.String()) {
+ errorCleanupProv, moreDiags := cfg.getCoreBuildProvisioner(srcUsage, build.ErrorCleanupProvisionerBlock, cfg.EvalContext(BuildContext, variables))
+ diags = append(diags, moreDiags...)
+ if moreDiags.HasErrors() {
+ continue
+ }
+ pcb.CleanupProvisioner = errorCleanupProv
+ }
+
+ pcb.Builder = builder
+ pcb.Provisioners = provisioners
+ pcb.PostProcessors = pps
+ pcb.Prepared = true
+
+ // Prepare just sets the "prepareCalled" flag on CoreBuild, since
+ // we did all the prep here.
+ _, err := pcb.Prepare()
+ if err != nil {
+ diags = append(diags, &hcl.Diagnostic{
+ Severity: hcl.DiagError,
+ Summary: fmt.Sprintf("Preparing packer core build %s failed", src.Ref().String()),
+ Detail: err.Error(),
+ Subject: build.HCL2Ref.DefRange.Ptr(),
+ })
+ continue
+ }
+
+ res = append(res, pcb)
+ }
+ }
+ if len(opts.Only) > opts.OnlyMatches {
+ diags = append(diags, &hcl.Diagnostic{
+ Severity: hcl.DiagWarning,
+ Summary: "an 'only' option was passed, but not all matches were found for the given build.",
+ Detail: fmt.Sprintf("Possible build names: %v.\n"+
+ "These could also be matched with a glob pattern like: 'happycloud.*'", possibleBuildNames),
+ })
+ }
+ if len(opts.Except) > opts.ExceptMatches {
+ diags = append(diags, &hcl.Diagnostic{
+ Severity: hcl.DiagWarning,
+ Summary: "an 'except' option was passed, but did not match any build.",
+ Detail: fmt.Sprintf("Possible build names: %v.\n"+
+ "These could also be matched with a glob pattern like: 'happycloud.*'", possibleBuildNames),
+ })
+ }
+ return res, diags
+}
+
+var PackerConsoleHelp = strings.TrimSpace(`
+Packer console HCL2 Mode.
+The Packer console allows you to experiment with Packer interpolations.
+You may access variables and functions in the Packer config you called the
+console with.
+
+Type in the interpolation to test and hit <enter> to see the result.
+
+"upper(var.foo.id)" would evaluate to the ID of "foo" and uppercase is, if it
+exists in your config file.
+
+"variables" will dump all available variables and their values.
+
+To exit the console, type "exit" and hit <enter>, or use Control-C.
+
+/!\ It is not possible to use go templating interpolation like "{{timestamp}}"
+with in HCL2 mode.
+`)
+
+func (p *PackerConfig) EvaluateExpression(line string) (out string, exit bool, diags hcl.Diagnostics) {
+ switch {
+ case line == "":
+ return "", false, nil
+ case line == "exit":
+ return "", true, nil
+ case line == "help":
+ return PackerConsoleHelp, false, nil
+ case line == "variables":
+ return p.printVariables(), false, nil
+ default:
+ return p.handleEval(line)
+ }
+}
+
+func (p *PackerConfig) printVariables() string {
+ out := &strings.Builder{}
+ out.WriteString("> input-variables:\n\n")
+ keys := p.InputVariables.Keys()
+ sort.Strings(keys)
+ for _, key := range keys {
+ v := p.InputVariables[key]
+ val := v.Value()
+ fmt.Fprintf(out, "var.%s: %q\n", v.Name, PrintableCtyValue(val))
+ }
+ out.WriteString("\n> local-variables:\n\n")
+ keys = p.LocalVariables.Keys()
+ sort.Strings(keys)
+ for _, key := range keys {
+ v := p.LocalVariables[key]
+ val := v.Value()
+ fmt.Fprintf(out, "local.%s: %q\n", v.Name, PrintableCtyValue(val))
+ }
+ return out.String()
+}
+
+func (p *PackerConfig) printBuilds() string {
+ out := &strings.Builder{}
+ out.WriteString("> builds:\n")
+ for i, build := range p.Builds {
+ name := build.Name
+ if name == "" {
+ name = fmt.Sprintf("<unnamed build %d>", i)
+ }
+ fmt.Fprintf(out, "\n > %s:\n", name)
+ if build.Description != "" {
+ fmt.Fprintf(out, "\n > Description: %s\n", build.Description)
+ }
+ fmt.Fprintf(out, "\n sources:\n")
+ if len(build.Sources) == 0 {
+ fmt.Fprintf(out, "\n <no source>\n")
+ }
+ for _, source := range build.Sources {
+ fmt.Fprintf(out, "\n %s\n", source.String())
+ }
+ fmt.Fprintf(out, "\n provisioners:\n\n")
+ if len(build.ProvisionerBlocks) == 0 {
+ fmt.Fprintf(out, " <no provisioner>\n")
+ }
+ for _, prov := range build.ProvisionerBlocks {
+ str := prov.PType
+ if prov.PName != "" {
+ str = strings.Join([]string{prov.PType, prov.PName}, ".")
+ }
+ fmt.Fprintf(out, " %s\n", str)
+ }
+ fmt.Fprintf(out, "\n post-processors:\n")
+ if len(build.PostProcessorsLists) == 0 {
+ fmt.Fprintf(out, "\n <no post-processor>\n")
+ }
+ for i, ppList := range build.PostProcessorsLists {
+ fmt.Fprintf(out, "\n %d:\n", i)
+ for _, pp := range ppList {
+ str := pp.PType
+ if pp.PName != "" {
+ str = strings.Join([]string{pp.PType, pp.PName}, ".")
+ }
+ fmt.Fprintf(out, " %s\n", str)
+ }
+ }
+ }
+ return out.String()
+}
+
+func (p *PackerConfig) handleEval(line string) (out string, exit bool, diags hcl.Diagnostics) {
+
+ // Parse the given line as an expression
+ expr, parseDiags := hclsyntax.ParseExpression([]byte(line), "<console-input>", hcl.Pos{Line: 1, Column: 1})
+ diags = append(diags, parseDiags...)
+ if parseDiags.HasErrors() {
+ return "", false, diags
+ }
+
+ val, valueDiags := expr.Value(p.EvalContext(NilContext, nil))
+ diags = append(diags, valueDiags...)
+ if valueDiags.HasErrors() {
+ return "", false, diags
+ }
+
+ return PrintableCtyValue(val), false, diags
+}
+
+func (p *PackerConfig) FixConfig(_ packer.FixConfigOptions) (diags hcl.Diagnostics) {
+ // No Fixers exist for HCL2 configs so there is nothing to do here for now.
+ return
+}
+
+func (p *PackerConfig) InspectConfig(opts packer.InspectConfigOptions) int {
+
+ ui := opts.Ui
+ ui.Say("Packer Inspect: HCL2 mode\n")
+ ui.Say(p.printVariables())
+ ui.Say(p.printBuilds())
+ return 0
+}
diff --git a/v1.9.4/hcl2template/types.packer_config_test.go b/v1.9.4/hcl2template/types.packer_config_test.go
new file mode 100644
index 0000000..d8881c1
--- /dev/null
+++ b/v1.9.4/hcl2template/types.packer_config_test.go
@@ -0,0 +1,667 @@
+// Copyright (c) HashiCorp, Inc.
+// SPDX-License-Identifier: MPL-2.0
+
+package hcl2template
+
+import (
+ "path/filepath"
+ "testing"
+ "time"
+
+ "github.com/hashicorp/go-version"
+ packersdk "github.com/hashicorp/packer-plugin-sdk/packer"
+ "github.com/hashicorp/packer-plugin-sdk/template/config"
+ "github.com/hashicorp/packer/hcl2template/addrs"
+ . "github.com/hashicorp/packer/hcl2template/internal"
+ hcl2template "github.com/hashicorp/packer/hcl2template/internal"
+ "github.com/hashicorp/packer/packer"
+ "github.com/zclconf/go-cty/cty"
+)
+
+var (
+ refVBIsoUbuntu1204 = SourceRef{Type: "virtualbox-iso", Name: "ubuntu-1204"}
+ refAWSEBSUbuntu1604 = SourceRef{Type: "amazon-ebs", Name: "ubuntu-1604"}
+ refAWSV3MyImage = SourceRef{Type: "amazon-v3-ebs", Name: "my-image"}
+ pTrue = pointerToBool(true)
+)
+
+func TestParser_complete(t *testing.T) {
+ defaultParser := getBasicParser()
+
+ tests := []parseTest{
+ {"working build",
+ defaultParser,
+ parseTestArgs{"testdata/complete", nil, nil},
+ &PackerConfig{
+ Packer: struct {
+ VersionConstraints []VersionConstraint
+ RequiredPlugins []*RequiredPlugins
+ }{
+ VersionConstraints: []VersionConstraint{
+ {
+ Required: mustVersionConstraints(version.NewConstraint(">= v1")),
+ },
+ },
+ RequiredPlugins: nil,
+ },
+ CorePackerVersionString: lockedVersion,
+ Basedir: "testdata/complete",
+
+ InputVariables: Variables{
+ "foo": &Variable{
+ Name: "foo",
+ Values: []VariableAssignment{{From: "default", Value: cty.StringVal("value")}},
+ Type: cty.String,
+ },
+ "image_id": &Variable{
+ Name: "image_id",
+ Values: []VariableAssignment{{From: "default", Value: cty.StringVal("image-id-default")}},
+ Type: cty.String,
+ },
+ "port": &Variable{
+ Name: "port",
+ Values: []VariableAssignment{{From: "default", Value: cty.NumberIntVal(42)}},
+ Type: cty.Number,
+ },
+ "availability_zone_names": &Variable{
+ Name: "availability_zone_names",
+ Values: []VariableAssignment{{
+ From: "default",
+ Value: cty.ListVal([]cty.Value{
+ cty.StringVal("A"),
+ cty.StringVal("B"),
+ cty.StringVal("C"),
+ }),
+ }},
+ Type: cty.List(cty.String),
+ },
+ },
+ LocalVariables: Variables{
+ "feefoo": &Variable{
+ Name: "feefoo",
+ Values: []VariableAssignment{{From: "default", Value: cty.StringVal("value_image-id-default")}},
+ Type: cty.String,
+ },
+ "data_source": &Variable{
+ Name: "data_source",
+ Values: []VariableAssignment{{From: "default", Value: cty.StringVal("string")}},
+ Type: cty.String,
+ },
+ "standard_tags": &Variable{
+ Name: "standard_tags",
+ Values: []VariableAssignment{{From: "default",
+ Value: cty.ObjectVal(map[string]cty.Value{
+ "Component": cty.StringVal("user-service"),
+ "Environment": cty.StringVal("production"),
+ }),
+ }},
+ Type: cty.Object(map[string]cty.Type{
+ "Component": cty.String,
+ "Environment": cty.String,
+ }),
+ },
+ "abc_map": &Variable{
+ Name: "abc_map",
+ Values: []VariableAssignment{{From: "default",
+ Value: cty.TupleVal([]cty.Value{
+ cty.ObjectVal(map[string]cty.Value{
+ "id": cty.StringVal("a"),
+ }),
+ cty.ObjectVal(map[string]cty.Value{
+ "id": cty.StringVal("b"),
+ }),
+ cty.ObjectVal(map[string]cty.Value{
+ "id": cty.StringVal("c"),
+ }),
+ }),
+ }},
+ Type: cty.Tuple([]cty.Type{
+ cty.Object(map[string]cty.Type{
+ "id": cty.String,
+ }),
+ cty.Object(map[string]cty.Type{
+ "id": cty.String,
+ }),
+ cty.Object(map[string]cty.Type{
+ "id": cty.String,
+ }),
+ }),
+ },
+ "supersecret": &Variable{
+ Name: "supersecret",
+ Values: []VariableAssignment{{From: "default",
+ Value: cty.StringVal("image-id-default-password")}},
+ Type: cty.String,
+ Sensitive: true,
+ },
+ },
+ Datasources: Datasources{
+ DatasourceRef{Type: "amazon-ami", Name: "test"}: DatasourceBlock{
+ Type: "amazon-ami",
+ Name: "test",
+ value: cty.StringVal("foo"),
+ },
+ },
+ Sources: map[SourceRef]SourceBlock{
+ refVBIsoUbuntu1204: {Type: "virtualbox-iso", Name: "ubuntu-1204"},
+ refAWSEBSUbuntu1604: {Type: "amazon-ebs", Name: "ubuntu-1604"},
+ },
+ Builds: Builds{
+ &BuildBlock{
+ Sources: []SourceUseBlock{
+ {
+ SourceRef: refVBIsoUbuntu1204,
+ },
+ {
+ SourceRef: refAWSEBSUbuntu1604,
+ },
+ },
+ ProvisionerBlocks: []*ProvisionerBlock{
+ {
+ PType: "shell",
+ PName: "provisioner that does something",
+ },
+ {PType: "file"},
+ },
+ ErrorCleanupProvisionerBlock: &ProvisionerBlock{
+ PType: "shell",
+ PName: "error-cleanup-provisioner that does something",
+ },
+ PostProcessorsLists: [][]*PostProcessorBlock{
+ {
+ {
+ PType: "amazon-import",
+ PName: "something",
+ KeepInputArtifact: pTrue,
+ },
+ },
+ {
+ {
+ PType: "amazon-import",
+ },
+ },
+ {
+ {
+ PType: "amazon-import",
+ PName: "first-nested-post-processor",
+ },
+ {
+ PType: "amazon-import",
+ PName: "second-nested-post-processor",
+ },
+ },
+ {
+ {
+ PType: "amazon-import",
+ PName: "third-nested-post-processor",
+ },
+ {
+ PType: "amazon-import",
+ PName: "fourth-nested-post-processor",
+ },
+ },
+ },
+ },
+ },
+ },
+ false, false,
+ []packersdk.Build{
+ &packer.CoreBuild{
+ Type: "virtualbox-iso.ubuntu-1204",
+ Prepared: true,
+ Builder: &MockBuilder{
+ Config: MockConfig{
+ NestedMockConfig: NestedMockConfig{
+ // interpolates source and type in builder
+ String: "ubuntu-1204-virtualbox-iso",
+ Int: 42,
+ Int64: 43,
+ Bool: true,
+ Trilean: config.TriTrue,
+ Duration: 10 * time.Second,
+ MapStringString: map[string]string{
+ "a": "b",
+ "c": "d",
+ },
+ SliceString: []string{
+ "a",
+ "b",
+ "c",
+ },
+ SliceSliceString: [][]string{
+ {"a", "b"},
+ {"c", "d"},
+ },
+ Tags: []MockTag{},
+ Datasource: "string",
+ },
+ Nested: builderBasicNestedMockConfig,
+ NestedSlice: []NestedMockConfig{
+ builderBasicNestedMockConfig,
+ builderBasicNestedMockConfig,
+ },
+ },
+ },
+ Provisioners: []packer.CoreBuildProvisioner{
+ {
+ PType: "shell",
+ PName: "provisioner that does something",
+ Provisioner: &HCL2Provisioner{
+ Provisioner: basicMockProvisioner,
+ },
+ },
+ {
+ PType: "file",
+ Provisioner: &HCL2Provisioner{
+ Provisioner: basicMockProvisioner,
+ },
+ },
+ },
+ CleanupProvisioner: packer.CoreBuildProvisioner{
+ PType: "shell",
+ PName: "error-cleanup-provisioner that does something",
+ Provisioner: &HCL2Provisioner{
+ Provisioner: basicMockProvisioner,
+ },
+ },
+ PostProcessors: [][]packer.CoreBuildPostProcessor{
+ {
+ {
+ PType: "amazon-import",
+ PName: "something",
+ PostProcessor: &HCL2PostProcessor{
+ PostProcessor: basicMockPostProcessorDynamicTags,
+ },
+ KeepInputArtifact: pTrue,
+ },
+ },
+ {
+ {
+ PType: "amazon-import",
+ PostProcessor: &HCL2PostProcessor{
+ PostProcessor: basicMockPostProcessor,
+ },
+ },
+ },
+ {
+ {
+ PType: "amazon-import",
+ PName: "first-nested-post-processor",
+ PostProcessor: &HCL2PostProcessor{
+ PostProcessor: basicMockPostProcessor,
+ },
+ },
+ {
+ PType: "amazon-import",
+ PName: "second-nested-post-processor",
+ PostProcessor: &HCL2PostProcessor{
+ PostProcessor: basicMockPostProcessor,
+ },
+ },
+ },
+ {
+ {
+ PType: "amazon-import",
+ PName: "third-nested-post-processor",
+ PostProcessor: &HCL2PostProcessor{
+ PostProcessor: basicMockPostProcessor,
+ },
+ },
+ {
+ PType: "amazon-import",
+ PName: "fourth-nested-post-processor",
+ PostProcessor: &HCL2PostProcessor{
+ PostProcessor: basicMockPostProcessor,
+ },
+ },
+ },
+ },
+ },
+ &packer.CoreBuild{
+ Type: "amazon-ebs.ubuntu-1604",
+ Prepared: true,
+ Builder: &MockBuilder{
+ Config: MockConfig{
+ NestedMockConfig: NestedMockConfig{
+ String: "setting from build section",
+ Int: 42,
+ Tags: []MockTag{},
+ },
+ Nested: hcl2template.NestedMockConfig{
+ Tags: []hcl2template.MockTag{
+ {Key: "Component", Value: "user-service"},
+ {Key: "Environment", Value: "production"},
+ },
+ },
+ NestedSlice: []NestedMockConfig{
+ hcl2template.NestedMockConfig{
+ Tags: []hcl2template.MockTag{
+ {Key: "Component", Value: "user-service"},
+ {Key: "Environment", Value: "production"},
+ },
+ },
+ },
+ },
+ },
+ Provisioners: []packer.CoreBuildProvisioner{
+ {
+ PType: "shell",
+ PName: "provisioner that does something",
+ Provisioner: &HCL2Provisioner{
+ Provisioner: basicMockProvisioner,
+ },
+ },
+ {
+ PType: "file",
+ Provisioner: &HCL2Provisioner{
+ Provisioner: basicMockProvisioner,
+ },
+ },
+ },
+ CleanupProvisioner: packer.CoreBuildProvisioner{
+ PType: "shell",
+ PName: "error-cleanup-provisioner that does something",
+ Provisioner: &HCL2Provisioner{
+ Provisioner: basicMockProvisioner,
+ },
+ },
+ PostProcessors: [][]packer.CoreBuildPostProcessor{
+ {
+ {
+ PType: "amazon-import",
+ PName: "something",
+ PostProcessor: &HCL2PostProcessor{
+ PostProcessor: basicMockPostProcessorDynamicTags,
+ },
+ KeepInputArtifact: pTrue,
+ },
+ },
+ {
+ {
+ PType: "amazon-import",
+ PostProcessor: &HCL2PostProcessor{
+ PostProcessor: basicMockPostProcessor,
+ },
+ },
+ },
+ {
+ {
+ PType: "amazon-import",
+ PName: "first-nested-post-processor",
+ PostProcessor: &HCL2PostProcessor{
+ PostProcessor: basicMockPostProcessor,
+ },
+ },
+ {
+ PType: "amazon-import",
+ PName: "second-nested-post-processor",
+ PostProcessor: &HCL2PostProcessor{
+ PostProcessor: basicMockPostProcessor,
+ },
+ },
+ },
+ {
+ {
+ PType: "amazon-import",
+ PName: "third-nested-post-processor",
+ PostProcessor: &HCL2PostProcessor{
+ PostProcessor: basicMockPostProcessor,
+ },
+ },
+ {
+ PType: "amazon-import",
+ PName: "fourth-nested-post-processor",
+ PostProcessor: &HCL2PostProcessor{
+ PostProcessor: basicMockPostProcessor,
+ },
+ },
+ },
+ },
+ },
+ },
+ false,
+ },
+ }
+ testParse(t, tests)
+}
+
+func TestParser_ValidateFilterOption(t *testing.T) {
+ tests := []struct {
+ pattern string
+ expectError bool
+ }{
+ {"*foo*", false},
+ {"foo[]bar", true},
+ }
+
+ for _, test := range tests {
+ t.Run(test.pattern, func(t *testing.T) {
+ _, diags := convertFilterOption([]string{test.pattern}, "")
+ if diags.HasErrors() && !test.expectError {
+ t.Fatalf("Expected %s to parse as glob", test.pattern)
+ }
+ if !diags.HasErrors() && test.expectError {
+ t.Fatalf("Expected %s to fail to parse as glob", test.pattern)
+ }
+ })
+ }
+}
+
+func TestParser_no_init(t *testing.T) {
+ defaultParser := getBasicParser()
+
+ tests := []parseTest{
+ {"working build with imports",
+ defaultParser,
+ parseTestArgs{"testdata/init/imports", nil, nil},
+ &PackerConfig{
+ Packer: struct {
+ VersionConstraints []VersionConstraint
+ RequiredPlugins []*RequiredPlugins
+ }{
+ VersionConstraints: []VersionConstraint{
+ {
+ Required: mustVersionConstraints(version.NewConstraint(">= v1")),
+ },
+ },
+ RequiredPlugins: []*RequiredPlugins{
+ {
+ RequiredPlugins: map[string]*RequiredPlugin{
+ "amazon": {
+ Name: "amazon",
+ Source: "github.com/hashicorp/amazon",
+ Type: &addrs.Plugin{
+ Type: "amazon",
+ Namespace: "hashicorp",
+ Hostname: "github.com",
+ },
+ Requirement: VersionConstraint{
+ Required: mustVersionConstraints(version.NewConstraint(">= v0")),
+ },
+ },
+ "amazon-v1": {
+ Name: "amazon-v1",
+ Source: "github.com/hashicorp/amazon",
+ Type: &addrs.Plugin{
+ Type: "amazon",
+ Namespace: "hashicorp",
+ Hostname: "github.com",
+ },
+ Requirement: VersionConstraint{
+ Required: mustVersionConstraints(version.NewConstraint(">= v1")),
+ },
+ },
+ "amazon-v2": {
+ Name: "amazon-v2",
+ Source: "github.com/hashicorp/amazon",
+ Type: &addrs.Plugin{
+ Type: "amazon",
+ Namespace: "hashicorp",
+ Hostname: "github.com",
+ },
+ Requirement: VersionConstraint{
+ Required: mustVersionConstraints(version.NewConstraint(">= v2")),
+ },
+ },
+ "amazon-v3": {
+ Name: "amazon-v3",
+ Source: "github.com/hashicorp/amazon",
+ Type: &addrs.Plugin{
+ Type: "amazon",
+ Namespace: "hashicorp",
+ Hostname: "github.com",
+ },
+ Requirement: VersionConstraint{
+ Required: mustVersionConstraints(version.NewConstraint(">= v3")),
+ },
+ },
+ "amazon-v3-azr": {
+ Name: "amazon-v3-azr",
+ Source: "github.com/azr/amazon",
+ Type: &addrs.Plugin{
+ Type: "amazon",
+ Namespace: "azr",
+ Hostname: "github.com",
+ },
+ Requirement: VersionConstraint{
+ Required: mustVersionConstraints(version.NewConstraint(">= v3")),
+ },
+ },
+ "amazon-v4": {
+ Name: "amazon-v4",
+ Source: "github.com/hashicorp/amazon",
+ Type: &addrs.Plugin{
+ Type: "amazon",
+ Namespace: "hashicorp",
+ Hostname: "github.com",
+ },
+ Requirement: VersionConstraint{
+ Required: mustVersionConstraints(version.NewConstraint(">= v4")),
+ },
+ },
+ },
+ },
+ },
+ },
+ CorePackerVersionString: lockedVersion,
+ Basedir: "testdata/init/imports",
+
+ InputVariables: Variables{
+ "foo": &Variable{
+ Name: "foo",
+ Values: []VariableAssignment{{From: "default", Value: cty.StringVal("value")}},
+ Type: cty.String,
+ },
+ "image_id": &Variable{
+ Name: "image_id",
+ Values: []VariableAssignment{{From: "default", Value: cty.StringVal("image-id-default")}},
+ Type: cty.String,
+ },
+ "port": &Variable{
+ Name: "port",
+ Values: []VariableAssignment{{From: "default", Value: cty.NumberIntVal(42)}},
+ Type: cty.Number,
+ },
+ "availability_zone_names": &Variable{
+ Name: "availability_zone_names",
+ Values: []VariableAssignment{{
+ From: "default",
+ Value: cty.ListVal([]cty.Value{
+ cty.StringVal("A"),
+ cty.StringVal("B"),
+ cty.StringVal("C"),
+ }),
+ }},
+ Type: cty.List(cty.String),
+ },
+ },
+ Sources: nil,
+ Builds: nil,
+ },
+ false, false,
+ []packersdk.Build{},
+ false,
+ },
+
+ {"duplicate required plugin accessor fails",
+ defaultParser,
+ parseTestArgs{"testdata/init/duplicate_required_plugins", nil, nil},
+ nil,
+ true, true,
+ []packersdk.Build{},
+ false,
+ },
+ {"invalid_inexplicit_source.pkr.hcl",
+ defaultParser,
+ parseTestArgs{"testdata/init/invalid_inexplicit_source.pkr.hcl", nil, nil},
+ &PackerConfig{
+ Packer: struct {
+ VersionConstraints []VersionConstraint
+ RequiredPlugins []*RequiredPlugins
+ }{
+ VersionConstraints: nil,
+ RequiredPlugins: []*RequiredPlugins{
+ {},
+ },
+ },
+ CorePackerVersionString: lockedVersion,
+ Basedir: filepath.Clean("testdata/init"),
+ },
+ true, true,
+ []packersdk.Build{},
+ false,
+ },
+ {"invalid_short_source.pkr.hcl",
+ defaultParser,
+ parseTestArgs{"testdata/init/invalid_short_source.pkr.hcl", nil, nil},
+ &PackerConfig{
+ Packer: struct {
+ VersionConstraints []VersionConstraint
+ RequiredPlugins []*RequiredPlugins
+ }{
+ VersionConstraints: nil,
+ RequiredPlugins: []*RequiredPlugins{
+ {},
+ },
+ },
+ CorePackerVersionString: lockedVersion,
+ Basedir: filepath.Clean("testdata/init"),
+ },
+ true, true,
+ []packersdk.Build{},
+ false,
+ },
+ {"invalid_inexplicit_source_2.pkr.hcl",
+ defaultParser,
+ parseTestArgs{"testdata/init/invalid_inexplicit_source_2.pkr.hcl", nil, nil},
+ &PackerConfig{
+ Packer: struct {
+ VersionConstraints []VersionConstraint
+ RequiredPlugins []*RequiredPlugins
+ }{
+ VersionConstraints: nil,
+ RequiredPlugins: []*RequiredPlugins{
+ {},
+ },
+ },
+ CorePackerVersionString: lockedVersion,
+ Basedir: filepath.Clean("testdata/init"),
+ },
+ true, true,
+ []packersdk.Build{},
+ false,
+ },
+ }
+ testParse_only_Parse(t, tests)
+}
+
+func pointerToBool(b bool) *bool {
+ return &b
+}
+
+func mustVersionConstraints(vs version.Constraints, err error) version.Constraints {
+ if err != nil {
+ panic(err)
+ }
+ return vs
+}
diff --git a/v1.9.4/hcl2template/types.required_plugins.go b/v1.9.4/hcl2template/types.required_plugins.go
new file mode 100644
index 0000000..179434c
--- /dev/null
+++ b/v1.9.4/hcl2template/types.required_plugins.go
@@ -0,0 +1,242 @@
+// Copyright (c) HashiCorp, Inc.
+// SPDX-License-Identifier: MPL-2.0
+
+package hcl2template
+
+import (
+ "fmt"
+
+ "github.com/hashicorp/go-version"
+ "github.com/hashicorp/hcl/v2"
+ "github.com/hashicorp/packer/hcl2template/addrs"
+ "github.com/zclconf/go-cty/cty"
+)
+
+func (cfg *PackerConfig) decodeRequiredPluginsBlock(f *hcl.File) hcl.Diagnostics {
+ var diags hcl.Diagnostics
+
+ content, moreDiags := f.Body.Content(configSchema)
+ diags = append(diags, moreDiags...)
+
+ for _, block := range content.Blocks {
+ switch block.Type {
+ case packerLabel:
+ content, contentDiags := block.Body.Content(packerBlockSchema)
+ diags = append(diags, contentDiags...)
+
+ // We ignore "packer_version"" here because
+ // sniffCoreVersionRequirements already dealt with that
+
+ for _, innerBlock := range content.Blocks {
+ switch innerBlock.Type {
+ case "required_plugins":
+ reqs, reqsDiags := decodeRequiredPluginsBlock(innerBlock)
+ diags = append(diags, reqsDiags...)
+ cfg.Packer.RequiredPlugins = append(cfg.Packer.RequiredPlugins, reqs)
+ default:
+ continue
+ }
+
+ }
+ }
+ }
+ return diags
+}
+
+// RequiredPlugin represents a declaration of a dependency on a particular
+// Plugin version or source.
+type RequiredPlugin struct {
+ Name string
+ // Source used to be able to tell how the template referenced this source,
+ // for example, "awesomecloud" instead of github.com/awesome/awesomecloud.
+ // This one is left here in case we want to go back to allowing inexplicit
+ // source url definitions.
+ Source string
+ Type *addrs.Plugin
+ Requirement VersionConstraint
+ DeclRange hcl.Range
+}
+
+type RequiredPlugins struct {
+ RequiredPlugins map[string]*RequiredPlugin
+ DeclRange hcl.Range
+}
+
+func decodeRequiredPluginsBlock(block *hcl.Block) (*RequiredPlugins, hcl.Diagnostics) {
+ attrs, diags := block.Body.JustAttributes()
+ ret := &RequiredPlugins{
+ RequiredPlugins: nil,
+ DeclRange: block.DefRange,
+ }
+ for name, attr := range attrs {
+ expr, err := attr.Expr.Value(nil)
+ if err != nil {
+ diags = append(diags, err...)
+ }
+
+ nameDiags := checkPluginNameNormalized(name, attr.Expr.Range())
+ diags = append(diags, nameDiags...)
+
+ rp := &RequiredPlugin{
+ Name: name,
+ DeclRange: attr.Expr.Range(),
+ }
+
+ switch {
+ case expr.Type().IsPrimitiveType():
+ c := "version"
+ if cs, _ := decodeVersionConstraint(attr); len(cs.Required) > 0 {
+ c = cs.Required.String()
+ }
+
+ diags = diags.Append(&hcl.Diagnostic{
+ Severity: hcl.DiagError,
+ Summary: "Invalid plugin requirement",
+ Detail: fmt.Sprintf(`'%s = "%s"' plugin requirement calls are not possible.`+
+ ` You must define a whole block. For example:`+"\n"+
+ `%[1]s = {`+"\n"+
+ ` source = "github.com/hashicorp/%[1]s"`+"\n"+
+ ` version = "%[2]s"`+"\n"+`}`,
+ name, c),
+ Subject: attr.Range.Ptr(),
+ })
+ continue
+
+ case expr.Type().IsObjectType():
+ if !expr.Type().HasAttribute("version") {
+ diags = append(diags, &hcl.Diagnostic{
+ Severity: hcl.DiagError,
+ Summary: "No version constraint was set",
+ Detail: "The version field must be specified as a string. Ex: `version = \">= 1.2.0, < 2.0.0\". See https://www.packer.io/docs/templates/hcl_templates/blocks/packer#version-constraints for docs",
+ Subject: attr.Expr.Range().Ptr(),
+ })
+ continue
+ }
+
+ vc := VersionConstraint{
+ DeclRange: attr.Range,
+ }
+ constraint := expr.GetAttr("version")
+ if !constraint.Type().Equals(cty.String) || constraint.IsNull() {
+ diags = append(diags, &hcl.Diagnostic{
+ Severity: hcl.DiagError,
+ Summary: "Invalid version constraint",
+ Detail: "Version must be specified as a string. See https://www.packer.io/docs/templates/hcl_templates/blocks/packer#version-constraint-syntax for docs.",
+ Subject: attr.Expr.Range().Ptr(),
+ })
+ continue
+ }
+ constraintStr := constraint.AsString()
+ constraints, err := version.NewConstraint(constraintStr)
+ if err != nil {
+ // NewConstraint doesn't return user-friendly errors, so we'll just
+ // ignore the provided error and produce our own generic one.
+ diags = append(diags, &hcl.Diagnostic{
+ Severity: hcl.DiagError,
+ Summary: "Invalid version constraint",
+ Detail: "This string does not use correct version constraint syntax. " +
+ "See https://www.packer.io/docs/templates/hcl_templates/blocks/packer#version-constraint-syntax for docs.\n" +
+ err.Error(),
+ Subject: attr.Expr.Range().Ptr(),
+ })
+ continue
+ }
+ vc.Required = constraints
+ rp.Requirement = vc
+
+ if !expr.Type().HasAttribute("source") {
+ diags = append(diags, &hcl.Diagnostic{
+ Severity: hcl.DiagError,
+ Summary: "No source was set",
+ Detail: "The source field must be specified as a string. Ex: `source = \"coolcloud\". See https://www.packer.io/docs/templates/hcl_templates/blocks/packer#specifying-plugin-requirements for docs",
+ Subject: attr.Expr.Range().Ptr(),
+ })
+ continue
+ }
+ source := expr.GetAttr("source")
+
+ if !source.Type().Equals(cty.String) || source.IsNull() {
+ diags = append(diags, &hcl.Diagnostic{
+ Severity: hcl.DiagError,
+ Summary: "Invalid source",
+ Detail: "Source must be specified as a string. For example: " + `source = "coolcloud"`,
+ Subject: attr.Expr.Range().Ptr(),
+ })
+ continue
+ }
+
+ rp.Source = source.AsString()
+ p, sourceDiags := addrs.ParsePluginSourceString(rp.Source)
+
+ if sourceDiags.HasErrors() {
+ for _, diag := range sourceDiags {
+ if diag.Subject == nil {
+ diag.Subject = attr.Expr.Range().Ptr()
+ }
+ }
+ diags = append(diags, sourceDiags...)
+ continue
+ } else {
+ rp.Type = p
+ }
+
+ attrTypes := expr.Type().AttributeTypes()
+ for name := range attrTypes {
+ if name == "version" || name == "source" {
+ continue
+ }
+ diags = append(diags, &hcl.Diagnostic{
+ Severity: hcl.DiagError,
+ Summary: "Invalid required_plugins object",
+ Detail: `required_plugins objects can only contain "version" and "source" attributes.`,
+ Subject: attr.Expr.Range().Ptr(),
+ })
+ break
+ }
+
+ default:
+ // should not happen
+ diags = append(diags, &hcl.Diagnostic{
+ Severity: hcl.DiagError,
+ Summary: "Invalid required_plugins syntax",
+ Detail: "required_plugins entries must be objects.",
+ Subject: attr.Expr.Range().Ptr(),
+ })
+ }
+
+ if ret.RequiredPlugins == nil {
+ ret.RequiredPlugins = make(map[string]*RequiredPlugin)
+ }
+ ret.RequiredPlugins[rp.Name] = rp
+ }
+
+ return ret, diags
+}
+
+// checkPluginNameNormalized verifies that the given string is already
+// normalized and returns an error if not.
+func checkPluginNameNormalized(name string, declrange hcl.Range) hcl.Diagnostics {
+ var diags hcl.Diagnostics
+ // verify that the plugin local name is normalized
+ normalized, err := addrs.IsPluginPartNormalized(name)
+ if err != nil {
+ diags = append(diags, &hcl.Diagnostic{
+ Severity: hcl.DiagError,
+ Summary: "Invalid plugin local name",
+ Detail: fmt.Sprintf("%s is an invalid plugin local name: %s", name, err),
+ Subject: &declrange,
+ })
+ return diags
+ }
+ if !normalized {
+ // we would have returned this error already
+ normalizedPlugin, _ := addrs.ParsePluginPart(name)
+ diags = append(diags, &hcl.Diagnostic{
+ Severity: hcl.DiagError,
+ Summary: "Invalid plugin local name",
+ Detail: fmt.Sprintf("Plugin names must be normalized. Replace %q with %q to fix this error.", name, normalizedPlugin),
+ Subject: &declrange,
+ })
+ }
+ return diags
+}
diff --git a/v1.9.4/hcl2template/types.required_plugins_test.go b/v1.9.4/hcl2template/types.required_plugins_test.go
new file mode 100644
index 0000000..7d832c4
--- /dev/null
+++ b/v1.9.4/hcl2template/types.required_plugins_test.go
@@ -0,0 +1,154 @@
+// Copyright (c) HashiCorp, Inc.
+// SPDX-License-Identifier: MPL-2.0
+
+package hcl2template
+
+import (
+ "testing"
+
+ "github.com/google/go-cmp/cmp"
+ "github.com/hashicorp/go-version"
+ "github.com/hashicorp/packer/hcl2template/addrs"
+)
+
+func TestPackerConfig_required_plugin_parse(t *testing.T) {
+
+ tests := []struct {
+ name string
+ cfg PackerConfig
+ requirePlugins string
+ restOfTemplate string
+ wantDiags bool
+ wantConfig PackerConfig
+ }{
+ {"required_plugin", PackerConfig{parser: getBasicParser()}, `
+ packer {
+ required_plugins {
+ amazon = {
+ source = "github.com/hashicorp/amazon"
+ version = "~> v1.2.3"
+ }
+ }
+ } `, `
+ source "amazon-ebs" "example" {
+ }
+ `, false, PackerConfig{
+ Packer: struct {
+ VersionConstraints []VersionConstraint
+ RequiredPlugins []*RequiredPlugins
+ }{
+ RequiredPlugins: []*RequiredPlugins{
+ {RequiredPlugins: map[string]*RequiredPlugin{
+ "amazon": {
+ Name: "amazon",
+ Source: "github.com/hashicorp/amazon",
+ Type: &addrs.Plugin{Hostname: "github.com", Namespace: "hashicorp", Type: "amazon"},
+ Requirement: VersionConstraint{
+ Required: mustVersionConstraints(version.NewConstraint("~> v1.2.3")),
+ },
+ },
+ }},
+ },
+ },
+ }},
+ {"required_plugin_forked_no_redirect", PackerConfig{parser: getBasicParser()}, `
+ packer {
+ required_plugins {
+ amazon = {
+ source = "github.com/azr/amazon"
+ version = "~> v1.2.3"
+ }
+ }
+ } `, `
+ source "amazon-chroot" "example" {
+ }
+ `, false, PackerConfig{
+ Packer: struct {
+ VersionConstraints []VersionConstraint
+ RequiredPlugins []*RequiredPlugins
+ }{
+ RequiredPlugins: []*RequiredPlugins{
+ {RequiredPlugins: map[string]*RequiredPlugin{
+ "amazon": {
+ Name: "amazon",
+ Source: "github.com/azr/amazon",
+ Type: &addrs.Plugin{Hostname: "github.com", Namespace: "azr", Type: "amazon"},
+ Requirement: VersionConstraint{
+ Required: mustVersionConstraints(version.NewConstraint("~> v1.2.3")),
+ },
+ },
+ }},
+ },
+ },
+ }},
+ {"required_plugin_forked", PackerConfig{
+ parser: getBasicParser(func(p *Parser) {})}, `
+ packer {
+ required_plugins {
+ amazon = {
+ source = "github.com/azr/amazon"
+ version = "~> v1.2.3"
+ }
+ }
+ } `, `
+ source "amazon-chroot" "example" {
+ }
+ `, false, PackerConfig{
+ Packer: struct {
+ VersionConstraints []VersionConstraint
+ RequiredPlugins []*RequiredPlugins
+ }{
+ RequiredPlugins: []*RequiredPlugins{
+ {RequiredPlugins: map[string]*RequiredPlugin{
+ "amazon": {
+ Name: "amazon",
+ Source: "github.com/azr/amazon",
+ Type: &addrs.Plugin{Hostname: "github.com", Namespace: "azr", Type: "amazon"},
+ Requirement: VersionConstraint{
+ Required: mustVersionConstraints(version.NewConstraint("~> v1.2.3")),
+ },
+ },
+ }},
+ },
+ },
+ }},
+ {"missing-required-plugin-for-pre-defined-builder", PackerConfig{
+ parser: getBasicParser(func(p *Parser) {})},
+ `
+ packer {
+ }`, `
+ # amazon-ebs is mocked in getBasicParser()
+ source "amazon-ebs" "example" {
+ }
+ `,
+ false,
+ PackerConfig{
+ Packer: struct {
+ VersionConstraints []VersionConstraint
+ RequiredPlugins []*RequiredPlugins
+ }{
+ RequiredPlugins: nil,
+ },
+ }},
+ }
+ for _, tt := range tests {
+ t.Run(tt.name, func(t *testing.T) {
+ cfg := tt.cfg
+ file, diags := cfg.parser.ParseHCL([]byte(tt.requirePlugins), "required_plugins.pkr.hcl")
+ if len(diags) > 0 {
+ t.Fatal(diags)
+ }
+ if diags := cfg.decodeRequiredPluginsBlock(file); len(diags) > 0 {
+ t.Fatal(diags)
+ }
+
+ _, diags = cfg.parser.ParseHCL([]byte(tt.restOfTemplate), "rest.pkr.hcl")
+ if len(diags) > 0 {
+ t.Fatal(diags)
+ }
+ if diff := cmp.Diff(tt.wantConfig, cfg, cmpOpts...); diff != "" {
+ t.Errorf("PackerConfig.inferImplicitRequiredPluginFromBlocks() unexpected PackerConfig: %v", diff)
+ }
+ })
+ }
+}
diff --git a/v1.9.4/hcl2template/types.source.go b/v1.9.4/hcl2template/types.source.go
new file mode 100644
index 0000000..1ea939d
--- /dev/null
+++ b/v1.9.4/hcl2template/types.source.go
@@ -0,0 +1,190 @@
+// Copyright (c) HashiCorp, Inc.
+// SPDX-License-Identifier: MPL-2.0
+
+package hcl2template
+
+import (
+ "fmt"
+ "sort"
+ "strconv"
+
+ "github.com/hashicorp/hcl/v2"
+ "github.com/hashicorp/hcl/v2/gohcl"
+ packersdk "github.com/hashicorp/packer-plugin-sdk/packer"
+ hcl2shim "github.com/hashicorp/packer/hcl2template/shim"
+ "github.com/zclconf/go-cty/cty"
+)
+
+// SourceBlock references an HCL 'source' block to be used in a build for
+// example.
+type SourceBlock struct {
+ // Type of source; ex: virtualbox-iso
+ Type string
+ // Given name; if any
+ Name string
+
+ block *hcl.Block
+
+ // LocalName can be set in a singular source block from a build block, it
+ // allows to give a special name to a build in the logs.
+ LocalName string
+}
+
+// SourceUseBlock is a SourceBlock 'usage' from a config stand point.
+// For example when one uses `build.sources = ["..."]` or
+// `build.source "..." {...}`.
+type SourceUseBlock struct {
+ // reference to an actual source block definition, or SourceBlock.
+ SourceRef
+
+ // LocalName can be set in a singular source block from a build block, it
+ // allows to give a special name to a build in the logs.
+ LocalName string
+
+ // Rest of the body, in case the build.source block has more specific
+ // content
+ // Body can be expanded by a dynamic tag.
+ Body hcl.Body
+}
+
+func (b *SourceUseBlock) name() string {
+ if b.LocalName != "" {
+ return b.LocalName
+ }
+ return b.Name
+}
+
+func (b *SourceUseBlock) String() string {
+ return fmt.Sprintf("%s.%s", b.Type, b.name())
+}
+
+// EvalContext adds the values of the source to the passed eval context.
+func (b *SourceUseBlock) ctyValues() map[string]cty.Value {
+ return map[string]cty.Value{
+ "type": cty.StringVal(b.Type),
+ "name": cty.StringVal(b.name()),
+ }
+}
+
+// decodeBuildSource reads a used source block from a build:
+//
+// build {
+// source "type.example" {
+// name = "local_name"
+// }
+// }
+func (p *Parser) decodeBuildSource(block *hcl.Block) (SourceUseBlock, hcl.Diagnostics) {
+ ref := sourceRefFromString(block.Labels[0])
+ out := SourceUseBlock{SourceRef: ref}
+ var b struct {
+ Name string `hcl:"name,optional"`
+ Rest hcl.Body `hcl:",remain"`
+ }
+ diags := gohcl.DecodeBody(block.Body, nil, &b)
+ if diags.HasErrors() {
+ return out, diags
+ }
+ out.LocalName = b.Name
+ out.Body = b.Rest
+ return out, nil
+}
+
+func (p *Parser) decodeSource(block *hcl.Block) (SourceBlock, hcl.Diagnostics) {
+ source := SourceBlock{
+ Type: block.Labels[0],
+ Name: block.Labels[1],
+ block: block,
+ }
+ var diags hcl.Diagnostics
+
+ return source, diags
+}
+
+func (cfg *PackerConfig) startBuilder(source SourceUseBlock, ectx *hcl.EvalContext) (packersdk.Builder, hcl.Diagnostics, []string) {
+ var diags hcl.Diagnostics
+
+ builder, err := cfg.parser.PluginConfig.Builders.Start(source.Type)
+ if err != nil {
+ diags = append(diags, &hcl.Diagnostic{
+ Severity: hcl.DiagError,
+ Summary: "Failed to load " + sourceLabel + " type",
+ Detail: err.Error(),
+ })
+ return builder, diags, nil
+ }
+
+ body := source.Body
+ // Add known values to source accessor in eval context.
+ ectx.Variables[sourcesAccessor] = cty.ObjectVal(source.ctyValues())
+
+ decoded, moreDiags := decodeHCL2Spec(body, ectx, builder)
+ diags = append(diags, moreDiags...)
+ if moreDiags.HasErrors() {
+ return builder, diags, nil
+ }
+
+ // In case of cty.Unknown values, this will write a equivalent placeholder of the same type
+ // Unknown types are not recognized by the json marshal during the RPC call and we have to do this here
+ // to avoid json parsing failures when running the validate command.
+ // We don't do this before so we can validate if variable types matches correctly on decodeHCL2Spec.
+ decoded = hcl2shim.WriteUnknownPlaceholderValues(decoded)
+
+ // Note: HCL prepares inside of the Start func, but Json does not. Json
+ // builds are instead prepared only in command/build.go
+ // TODO: either make json prepare when plugins are loaded, or make HCL
+ // prepare at a later step, to make builds from different template types
+ // easier to reason about.
+ builderVars := source.builderVariables()
+ builderVars["packer_core_version"] = cfg.CorePackerVersionString
+ builderVars["packer_debug"] = strconv.FormatBool(cfg.debug)
+ builderVars["packer_force"] = strconv.FormatBool(cfg.force)
+ builderVars["packer_on_error"] = cfg.onError
+
+ generatedVars, warning, err := builder.Prepare(builderVars, decoded)
+ moreDiags = warningErrorsToDiags(cfg.Sources[source.SourceRef].block, warning, err)
+ diags = append(diags, moreDiags...)
+ return builder, diags, generatedVars
+}
+
+// These variables will populate the PackerConfig inside of the builders.
+func (source *SourceUseBlock) builderVariables() map[string]string {
+ return map[string]string{
+ "packer_build_name": source.Name,
+ "packer_builder_type": source.Type,
+ }
+}
+
+func (source *SourceBlock) Ref() SourceRef {
+ return SourceRef{
+ Type: source.Type,
+ Name: source.Name,
+ }
+}
+
+// SourceRef is a nice way to put `virtualbox-iso.source_name`
+type SourceRef struct {
+ // Type of the source, for example `virtualbox-iso`
+ Type string
+ // Name of the source, for example `source_name`
+ Name string
+
+ // No other field should be added to the SourceRef because we used that
+ // struct as a map accessor in many places.
+}
+
+// NoSource is the zero value of sourceRef, representing the absense of an
+// source.
+var NoSource SourceRef
+
+func (r SourceRef) String() string {
+ return fmt.Sprintf("%s.%s", r.Type, r.Name)
+}
+
+func listAvailableSourceNames(srcs map[SourceRef]SourceBlock) []string {
+ res := make([]string, 0, len(srcs))
+ for k := range srcs {
+ res = append(res, k.String())
+ }
+ sort.Strings(res)
+ return res
+}
diff --git a/v1.9.4/hcl2template/types.source_test.go b/v1.9.4/hcl2template/types.source_test.go
new file mode 100644
index 0000000..efdddea
--- /dev/null
+++ b/v1.9.4/hcl2template/types.source_test.go
@@ -0,0 +1,148 @@
+// Copyright (c) HashiCorp, Inc.
+// SPDX-License-Identifier: MPL-2.0
+
+package hcl2template
+
+import (
+ "path/filepath"
+ "testing"
+
+ packersdk "github.com/hashicorp/packer-plugin-sdk/packer"
+ "github.com/hashicorp/packer/builder/null"
+ "github.com/hashicorp/packer/packer"
+)
+
+func TestParse_source(t *testing.T) {
+ defaultParser := getBasicParser()
+
+ tests := []parseTest{
+ {"two basic sources",
+ defaultParser,
+ parseTestArgs{"testdata/sources/basic.pkr.hcl", nil, nil},
+ &PackerConfig{
+ CorePackerVersionString: lockedVersion,
+ Builds: Builds{
+ &BuildBlock{
+ Sources: []SourceUseBlock{
+ {
+ SourceRef: SourceRef{
+ Type: "null",
+ Name: "test",
+ },
+ },
+ },
+ },
+ },
+ Basedir: filepath.Join("testdata", "sources"),
+ Sources: map[SourceRef]SourceBlock{
+ {
+ Type: "virtualbox-iso",
+ Name: "ubuntu-1204",
+ }: {
+ Type: "virtualbox-iso",
+ Name: "ubuntu-1204",
+ },
+ {
+ Type: "null",
+ Name: "test",
+ }: {
+ Type: "null",
+ Name: "test",
+ },
+ },
+ },
+ false, false,
+ []packersdk.Build{
+ &packer.CoreBuild{
+ Type: "null.test",
+ Builder: &null.Builder{},
+ Provisioners: []packer.CoreBuildProvisioner{},
+ PostProcessors: [][]packer.CoreBuildPostProcessor{},
+ Prepared: true,
+ },
+ },
+ false,
+ },
+ {"untyped source",
+ defaultParser,
+ parseTestArgs{"testdata/sources/untyped.pkr.hcl", nil, nil},
+ &PackerConfig{
+ CorePackerVersionString: lockedVersion,
+ Basedir: filepath.Join("testdata", "sources"),
+ },
+ true, true,
+ nil,
+ false,
+ },
+ {"unnamed source",
+ defaultParser,
+ parseTestArgs{"testdata/sources/unnamed.pkr.hcl", nil, nil},
+ &PackerConfig{
+ CorePackerVersionString: lockedVersion,
+ Basedir: filepath.Join("testdata", "sources"),
+ },
+ true, true,
+ nil,
+ false,
+ },
+ {"unused source with unknown type fails",
+ defaultParser,
+ parseTestArgs{"testdata/sources/nonexistent.pkr.hcl", nil, nil},
+ &PackerConfig{
+ CorePackerVersionString: lockedVersion,
+ Builds: nil,
+ Basedir: filepath.Join("testdata", "sources"),
+ Sources: map[SourceRef]SourceBlock{
+ {Type: "nonexistent", Name: "ubuntu-1204"}: {Type: "nonexistent", Name: "ubuntu-1204"},
+ },
+ },
+ true, true,
+ []packersdk.Build{},
+ false,
+ },
+ {"used source with unknown type fails",
+ defaultParser,
+ parseTestArgs{"testdata/sources/nonexistent_used.pkr.hcl", nil, nil},
+ &PackerConfig{
+ CorePackerVersionString: lockedVersion,
+ Basedir: filepath.Join("testdata", "sources"),
+ Sources: map[SourceRef]SourceBlock{
+ {Type: "nonexistent", Name: "ubuntu-1204"}: {Type: "nonexistent", Name: "ubuntu-1204"},
+ },
+ Builds: Builds{
+ &BuildBlock{
+ Sources: []SourceUseBlock{
+ {
+ SourceRef: SourceRef{Type: "nonexistent", Name: "ubuntu-1204"},
+ },
+ },
+ },
+ },
+ },
+ true, true,
+ nil,
+ false,
+ },
+ {"duplicate source",
+ defaultParser,
+ parseTestArgs{"testdata/sources/duplicate.pkr.hcl", nil, nil},
+ &PackerConfig{
+ CorePackerVersionString: lockedVersion,
+ Basedir: filepath.Join("testdata", "sources"),
+ Sources: map[SourceRef]SourceBlock{
+ {
+ Type: "virtualbox-iso",
+ Name: "ubuntu-1204",
+ }: {
+ Type: "virtualbox-iso",
+ Name: "ubuntu-1204",
+ },
+ },
+ },
+ true, true,
+ nil,
+ false,
+ },
+ }
+ testParse(t, tests)
+}
diff --git a/v1.9.4/hcl2template/types.variables.go b/v1.9.4/hcl2template/types.variables.go
new file mode 100644
index 0000000..9111ced
--- /dev/null
+++ b/v1.9.4/hcl2template/types.variables.go
@@ -0,0 +1,771 @@
+// Copyright (c) HashiCorp, Inc.
+// SPDX-License-Identifier: MPL-2.0
+
+package hcl2template
+
+import (
+ "fmt"
+ "log"
+ "strings"
+ "unicode"
+
+ "github.com/hashicorp/hcl/v2"
+ "github.com/hashicorp/hcl/v2/ext/typeexpr"
+ "github.com/hashicorp/hcl/v2/gohcl"
+ "github.com/hashicorp/hcl/v2/hclsyntax"
+ "github.com/hashicorp/packer/hcl2template/addrs"
+ "github.com/zclconf/go-cty/cty"
+ "github.com/zclconf/go-cty/cty/convert"
+)
+
+// A consistent detail message for all "not a valid identifier" diagnostics.
+const badIdentifierDetail = "A name must start with a letter or underscore and may contain only letters, digits, underscores, and dashes."
+
+// Local represents a single entry from a "locals" block in a file.
+// The "locals" block itself is not represented, because it serves only to
+// provide context for us to interpret its contents.
+type LocalBlock struct {
+ Name string
+ Expr hcl.Expression
+ // When Sensitive is set to true Packer will try its best to hide/obfuscate
+ // the variable from the output stream. By replacing the text.
+ Sensitive bool
+}
+
+// VariableAssignment represents a way a variable was set: the expression
+// setting it and the value of that expression. It helps pinpoint were
+// something was set in diagnostics.
+type VariableAssignment struct {
+ // From tells were it was taken from, command/varfile/env/default
+ From string
+ Value cty.Value
+ Expr hcl.Expression
+}
+
+type Variable struct {
+ // Values contains possible values for the variable; The last value set
+ // from these will be the one used. If none is set; an error will be
+ // returned by Value().
+ Values []VariableAssignment
+
+ // Validations contains all variables validation rules to be applied to the
+ // used value. Only the used value - the last value from Values - is
+ // validated.
+ Validations []*VariableValidation
+
+ // Cty Type of the variable. If the default value or a collected value is
+ // not of this type nor can be converted to this type an error diagnostic
+ // will show up. This allows us to assume that values are valid later in
+ // code.
+ //
+ // When a default value - and no type - is passed in the variable
+ // declaration, the type of the default variable will be used. This will
+ // allow to ensure that users set this variable correctly.
+ Type cty.Type
+ // Common name of the variable
+ Name string
+ // Description of the variable
+ Description string
+ // When Sensitive is set to true Packer will try it best to hide/obfuscate
+ // the variable from the output stream. By replacing the text.
+ Sensitive bool
+
+ Range hcl.Range
+}
+
+func (v *Variable) GoString() string {
+ b := &strings.Builder{}
+ fmt.Fprintf(b, "{type:%s", v.Type.GoString())
+ for _, vv := range v.Values {
+ fmt.Fprintf(b, ",%s:%s", vv.From, vv.Value)
+ }
+ fmt.Fprintf(b, "}")
+ return b.String()
+}
+
+// validateValue ensures that all of the configured custom validations for a
+// variable value are passing.
+func (v *Variable) validateValue(val VariableAssignment) (diags hcl.Diagnostics) {
+ if len(v.Validations) == 0 {
+ log.Printf("[TRACE] validateValue: not active for %s, so skipping", v.Name)
+ return nil
+ }
+
+ hclCtx := &hcl.EvalContext{
+ Variables: map[string]cty.Value{
+ "var": cty.ObjectVal(map[string]cty.Value{
+ v.Name: val.Value,
+ }),
+ },
+ Functions: Functions(""),
+ }
+
+ for _, validation := range v.Validations {
+ const errInvalidCondition = "Invalid variable validation result"
+
+ result, moreDiags := validation.Condition.Value(hclCtx)
+ diags = append(diags, moreDiags...)
+ if moreDiags.HasErrors() {
+ log.Printf("[TRACE] evalVariableValidations: %s rule %s condition expression failed: %s", v.Name, validation.DeclRange, moreDiags.Error())
+ }
+ if !result.IsKnown() {
+ log.Printf("[TRACE] evalVariableValidations: %s rule %s condition value is unknown, so skipping validation for now", v.Name, validation.DeclRange)
+ continue // We'll wait until we've learned more, then.
+ }
+ if result.IsNull() {
+ diags = append(diags, &hcl.Diagnostic{
+ Severity: hcl.DiagError,
+ Summary: errInvalidCondition,
+ Detail: "Validation condition expression must return either true or false, not null.",
+ Subject: validation.Condition.Range().Ptr(),
+ Expression: validation.Condition,
+ EvalContext: hclCtx,
+ })
+ continue
+ }
+ var err error
+ result, err = convert.Convert(result, cty.Bool)
+ if err != nil {
+ diags = append(diags, &hcl.Diagnostic{
+ Severity: hcl.DiagError,
+ Summary: errInvalidCondition,
+ Detail: fmt.Sprintf("Invalid validation condition result value: %s.", err),
+ Subject: validation.Condition.Range().Ptr(),
+ Expression: validation.Condition,
+ EvalContext: hclCtx,
+ })
+ continue
+ }
+
+ if result.False() {
+ subj := validation.DeclRange.Ptr()
+ if val.Expr != nil {
+ subj = val.Expr.Range().Ptr()
+ }
+ diags = append(diags, &hcl.Diagnostic{
+ Severity: hcl.DiagError,
+ Summary: fmt.Sprintf("Invalid value for %s variable", val.From),
+ Detail: fmt.Sprintf("%s\n\nThis was checked by the validation rule at %s.", validation.ErrorMessage, validation.DeclRange.String()),
+ Subject: subj,
+ })
+ }
+ }
+
+ return diags
+}
+
+// Value returns the last found value from the list of variable settings.
+func (v *Variable) Value() cty.Value {
+ if len(v.Values) == 0 {
+ return cty.UnknownVal(v.Type)
+ }
+ val := v.Values[len(v.Values)-1]
+ return val.Value
+}
+
+// ValidateValue tells if the selected value for the Variable is valid according
+// to its validation settings.
+func (v *Variable) ValidateValue() hcl.Diagnostics {
+ if len(v.Values) == 0 {
+ return hcl.Diagnostics{&hcl.Diagnostic{
+ Severity: hcl.DiagError,
+ Summary: fmt.Sprintf("Unset variable %q", v.Name),
+ Detail: "A used variable must be set or have a default value; see " +
+ "https://packer.io/docs/templates/hcl_templates/syntax for " +
+ "details.",
+ Context: v.Range.Ptr(),
+ }}
+ }
+
+ return v.validateValue(v.Values[len(v.Values)-1])
+}
+
+type Variables map[string]*Variable
+
+func (variables Variables) Keys() []string {
+ keys := make([]string, 0, len(variables))
+ for key := range variables {
+ keys = append(keys, key)
+ }
+ return keys
+}
+
+func (variables Variables) Values() map[string]cty.Value {
+ res := map[string]cty.Value{}
+ for k, v := range variables {
+ value := v.Value()
+ res[k] = value
+ }
+ return res
+}
+
+func (variables Variables) ValidateValues() hcl.Diagnostics {
+ var diags hcl.Diagnostics
+ for _, v := range variables {
+ diags = append(diags, v.ValidateValue()...)
+ }
+ return diags
+}
+
+// decodeVariable decodes a variable key and value into Variables
+func (variables *Variables) decodeVariable(key string, attr *hcl.Attribute, ectx *hcl.EvalContext) hcl.Diagnostics {
+ var diags hcl.Diagnostics
+
+ if (*variables) == nil {
+ (*variables) = Variables{}
+ }
+
+ if _, found := (*variables)[key]; found {
+ diags = append(diags, &hcl.Diagnostic{
+ Severity: hcl.DiagError,
+ Summary: "Duplicate variable",
+ Detail: "Duplicate " + key + " variable definition found.",
+ Subject: attr.NameRange.Ptr(),
+ })
+ return diags
+ }
+
+ value, moreDiags := attr.Expr.Value(ectx)
+ diags = append(diags, moreDiags...)
+ if moreDiags.HasErrors() {
+ return diags
+ }
+
+ (*variables)[key] = &Variable{
+ Name: key,
+ Values: []VariableAssignment{{
+ From: "default",
+ Value: value,
+ Expr: attr.Expr,
+ }},
+ Type: value.Type(),
+ Range: attr.Range,
+ }
+
+ return diags
+}
+
+var variableBlockSchema = &hcl.BodySchema{
+ Attributes: []hcl.AttributeSchema{
+ {
+ Name: "description",
+ },
+ {
+ Name: "default",
+ },
+ {
+ Name: "type",
+ },
+ {
+ Name: "sensitive",
+ },
+ },
+ Blocks: []hcl.BlockHeaderSchema{
+ {
+ Type: "validation",
+ },
+ },
+}
+
+var localBlockSchema = &hcl.BodySchema{
+ Attributes: []hcl.AttributeSchema{
+ {
+ Name: "expression",
+ },
+ {
+ Name: "sensitive",
+ },
+ },
+}
+
+func decodeLocalBlock(block *hcl.Block) (*LocalBlock, hcl.Diagnostics) {
+ name := block.Labels[0]
+
+ content, diags := block.Body.Content(localBlockSchema)
+ if !hclsyntax.ValidIdentifier(name) {
+ diags = append(diags, &hcl.Diagnostic{
+ Severity: hcl.DiagError,
+ Summary: "Invalid local name",
+ Detail: badIdentifierDetail,
+ Subject: &block.LabelRanges[0],
+ })
+ }
+
+ l := &LocalBlock{
+ Name: name,
+ }
+
+ if attr, exists := content.Attributes["sensitive"]; exists {
+ valDiags := gohcl.DecodeExpression(attr.Expr, nil, &l.Sensitive)
+ diags = append(diags, valDiags...)
+ }
+
+ if def, ok := content.Attributes["expression"]; ok {
+ l.Expr = def.Expr
+ }
+
+ return l, diags
+}
+
+// decodeVariableBlock decodes a "variable" block
+// ectx is passed only in the evaluation of the default value.
+func (variables *Variables) decodeVariableBlock(block *hcl.Block, ectx *hcl.EvalContext) hcl.Diagnostics {
+ if (*variables) == nil {
+ (*variables) = Variables{}
+ }
+
+ if _, found := (*variables)[block.Labels[0]]; found {
+ return []*hcl.Diagnostic{{
+ Severity: hcl.DiagError,
+ Summary: "Duplicate variable",
+ Detail: "Duplicate " + block.Labels[0] + " variable definition found.",
+ Context: block.DefRange.Ptr(),
+ }}
+ }
+
+ name := block.Labels[0]
+
+ content, diags := block.Body.Content(variableBlockSchema)
+ if !hclsyntax.ValidIdentifier(name) {
+ diags = append(diags, &hcl.Diagnostic{
+ Severity: hcl.DiagError,
+ Summary: "Invalid variable name",
+ Detail: badIdentifierDetail,
+ Subject: &block.LabelRanges[0],
+ })
+ }
+
+ v := &Variable{
+ Name: name,
+ Range: block.DefRange,
+ Type: cty.DynamicPseudoType,
+ }
+
+ if attr, exists := content.Attributes["description"]; exists {
+ valDiags := gohcl.DecodeExpression(attr.Expr, nil, &v.Description)
+ diags = append(diags, valDiags...)
+ }
+
+ if t, ok := content.Attributes["type"]; ok {
+ tp, moreDiags := typeexpr.Type(t.Expr)
+ diags = append(diags, moreDiags...)
+ if moreDiags.HasErrors() {
+ return diags
+ }
+
+ v.Type = tp
+ }
+
+ if attr, exists := content.Attributes["sensitive"]; exists {
+ valDiags := gohcl.DecodeExpression(attr.Expr, nil, &v.Sensitive)
+ diags = append(diags, valDiags...)
+ }
+
+ if def, ok := content.Attributes["default"]; ok {
+ defaultValue, moreDiags := def.Expr.Value(ectx)
+ diags = append(diags, moreDiags...)
+ if moreDiags.HasErrors() {
+ return diags
+ }
+
+ if v.Type != cty.NilType {
+ var err error
+ defaultValue, err = convert.Convert(defaultValue, v.Type)
+ if err != nil {
+ diags = append(diags, &hcl.Diagnostic{
+ Severity: hcl.DiagError,
+ Summary: "Invalid default value for variable",
+ Detail: fmt.Sprintf("This default value is not compatible with the variable's type constraint: %s.", err),
+ Subject: def.Expr.Range().Ptr(),
+ })
+ defaultValue = cty.DynamicVal
+ }
+ }
+
+ v.Values = append(v.Values, VariableAssignment{
+ From: "default",
+ Value: defaultValue,
+ Expr: def.Expr,
+ })
+
+ // It's possible no type attribute was assigned so lets make sure we
+ // have a valid type otherwise there could be issues parsing the value.
+ if v.Type == cty.DynamicPseudoType &&
+ !defaultValue.Type().Equals(cty.EmptyObject) &&
+ !defaultValue.Type().Equals(cty.EmptyTuple) {
+ v.Type = defaultValue.Type()
+ }
+ }
+
+ for _, block := range content.Blocks {
+ switch block.Type {
+ case "validation":
+ vv, moreDiags := decodeVariableValidationBlock(v.Name, block)
+ diags = append(diags, moreDiags...)
+ v.Validations = append(v.Validations, vv)
+ }
+ }
+
+ (*variables)[name] = v
+
+ return diags
+}
+
+var variableValidationBlockSchema = &hcl.BodySchema{
+ Attributes: []hcl.AttributeSchema{
+ {
+ Name: "condition",
+ Required: true,
+ },
+ {
+ Name: "error_message",
+ Required: true,
+ },
+ },
+}
+
+// VariableValidation represents a configuration-defined validation rule
+// for a particular input variable, given as a "validation" block inside
+// a "variable" block.
+type VariableValidation struct {
+ // Condition is an expression that refers to the variable being tested and
+ // contains no other references. The expression must return true to
+ // indicate that the value is valid or false to indicate that it is
+ // invalid. If the expression produces an error, that's considered a bug in
+ // the block defining the validation rule, not an error in the caller.
+ Condition hcl.Expression
+
+ // ErrorMessage is one or more full sentences, which _should_ be in English
+ // for consistency with the rest of the error message output but can in
+ // practice be in any language as long as it ends with a period. The
+ // message should describe what is required for the condition to return
+ // true in a way that would make sense to a caller of the module.
+ ErrorMessage string
+
+ DeclRange hcl.Range
+}
+
+func decodeVariableValidationBlock(varName string, block *hcl.Block) (*VariableValidation, hcl.Diagnostics) {
+ var diags hcl.Diagnostics
+ vv := &VariableValidation{
+ DeclRange: block.DefRange,
+ }
+
+ content, moreDiags := block.Body.Content(variableValidationBlockSchema)
+ diags = append(diags, moreDiags...)
+
+ if attr, exists := content.Attributes["condition"]; exists {
+ vv.Condition = attr.Expr
+
+ // The validation condition must refer to the variable itself and
+ // nothing else; to ensure that the variable declaration can't create
+ // additional edges in the dependency graph.
+ goodRefs := 0
+ for _, traversal := range vv.Condition.Variables() {
+
+ ref, moreDiags := addrs.ParseRef(traversal)
+ if !moreDiags.HasErrors() {
+ if addr, ok := ref.Subject.(addrs.InputVariable); ok {
+ if addr.Name == varName {
+ goodRefs++
+ continue // Reference is valid
+ }
+ }
+ }
+
+ // If we fall out here then the reference is invalid.
+ diags = diags.Append(&hcl.Diagnostic{
+ Severity: hcl.DiagError,
+ Summary: "Invalid reference in variable validation",
+ Detail: fmt.Sprintf("The condition for variable %q can only refer to the variable itself, using var.%s.", varName, varName),
+ Subject: traversal.SourceRange().Ptr(),
+ })
+ }
+ if goodRefs < 1 {
+ diags = diags.Append(&hcl.Diagnostic{
+ Severity: hcl.DiagError,
+ Summary: "Invalid variable validation condition",
+ Detail: fmt.Sprintf("The condition for variable %q must refer to var.%s in order to test incoming values.", varName, varName),
+ Subject: attr.Expr.Range().Ptr(),
+ })
+ }
+ }
+
+ if attr, exists := content.Attributes["error_message"]; exists {
+ moreDiags := gohcl.DecodeExpression(attr.Expr, nil, &vv.ErrorMessage)
+ diags = append(diags, moreDiags...)
+ if !moreDiags.HasErrors() {
+ const errSummary = "Invalid validation error message"
+ switch {
+ case vv.ErrorMessage == "":
+ diags = diags.Append(&hcl.Diagnostic{
+ Severity: hcl.DiagError,
+ Summary: errSummary,
+ Detail: "An empty string is not a valid nor useful error message.",
+ Subject: attr.Expr.Range().Ptr(),
+ })
+ case !looksLikeSentences(vv.ErrorMessage):
+ // Because we're going to include this string verbatim as part
+ // of a bigger error message written in our usual style, we'll
+ // require the given error message to conform to that. We might
+ // relax this in future if e.g. we start presenting these error
+ // messages in a different way, or if Packer starts supporting
+ // producing error messages in other human languages, etc. For
+ // pragmatism we also allow sentences ending with exclamation
+ // points, but we don't mention it explicitly here because
+ // that's not really consistent with the Packer UI writing
+ // style.
+ diags = diags.Append(&hcl.Diagnostic{
+ Severity: hcl.DiagError,
+ Summary: errSummary,
+ Detail: "Validation error message must be at least one full sentence starting with an uppercase letter ( if the alphabet permits it ) and ending with a period or question mark.",
+ Subject: attr.Expr.Range().Ptr(),
+ })
+ }
+ }
+ }
+
+ return vv, diags
+}
+
+// looksLikeSentence is a simple heuristic that encourages writing error
+// messages that will be presentable when included as part of a larger error
+// diagnostic whose other text is written in the UI writing style.
+//
+// This is intentionally not a very strong validation since we're assuming that
+// authors want to write good messages and might just need a nudge about
+// Packer's specific style, rather than that they are going to try to work
+// around these rules to write a lower-quality message.
+func looksLikeSentences(s string) bool {
+ s = strings.TrimSpace(s)
+ if len(s) < 1 {
+ return false
+ }
+ runes := []rune(s) // HCL guarantees that all strings are valid UTF-8
+ first := runes[0]
+ last := runes[len(runes)-1]
+
+ // If the first rune is a letter then it must be an uppercase letter. To
+ // sorts of nudge people into writting sentences. For alphabets that don't
+ // have the notion of 'upper', this does nothing.
+ if unicode.IsLetter(first) && !unicode.IsUpper(first) {
+ return false
+ }
+
+ // The string must be at least one full sentence, which implies having
+ // sentence-ending punctuation.
+ return last == '.' || last == '?' || last == '!'
+}
+
+// Prefix your environment variables with VarEnvPrefix so that Packer can see
+// them.
+const VarEnvPrefix = "PKR_VAR_"
+
+func (cfg *PackerConfig) collectInputVariableValues(env []string, files []*hcl.File, argv map[string]string) hcl.Diagnostics {
+ var diags hcl.Diagnostics
+ variables := cfg.InputVariables
+
+ for _, raw := range env {
+ if !strings.HasPrefix(raw, VarEnvPrefix) {
+ continue
+ }
+ raw = raw[len(VarEnvPrefix):] // trim the prefix
+
+ eq := strings.Index(raw, "=")
+ if eq == -1 {
+ // Seems invalid, so we'll ignore it.
+ continue
+ }
+
+ name := raw[:eq]
+ value := raw[eq+1:]
+
+ variable, found := variables[name]
+ if !found {
+ // this variable was not defined in the hcl files, let's skip it !
+ continue
+ }
+
+ fakeFilename := fmt.Sprintf("<value for var.%s from env>", name)
+ expr, moreDiags := expressionFromVariableDefinition(fakeFilename, value, variable.Type)
+ diags = append(diags, moreDiags...)
+ if moreDiags.HasErrors() {
+ continue
+ }
+
+ val, valDiags := expr.Value(nil)
+ diags = append(diags, valDiags...)
+ if variable.Type != cty.NilType {
+ var err error
+ val, err = convert.Convert(val, variable.Type)
+ if err != nil {
+ diags = append(diags, &hcl.Diagnostic{
+ Severity: hcl.DiagError,
+ Summary: "Invalid value for variable",
+ Detail: fmt.Sprintf("The value for %s is not compatible with the variable's type constraint: %s.", name, err),
+ Subject: expr.Range().Ptr(),
+ })
+ val = cty.DynamicVal
+ }
+ }
+ variable.Values = append(variable.Values, VariableAssignment{
+ From: "env",
+ Value: val,
+ Expr: expr,
+ })
+ }
+
+ // files will contain files found in the folder then files passed as
+ // arguments.
+ for _, file := range files {
+ // Before we do our real decode, we'll probe to see if there are any
+ // blocks of type "variable" in this body, since it's a common mistake
+ // for new users to put variable declarations in pkrvars rather than
+ // variable value definitions, and otherwise our error message for that
+ // case is not so helpful.
+ {
+ content, _, _ := file.Body.PartialContent(&hcl.BodySchema{
+ Blocks: []hcl.BlockHeaderSchema{
+ {
+ Type: "variable",
+ LabelNames: []string{"name"},
+ },
+ },
+ })
+ for _, block := range content.Blocks {
+ name := block.Labels[0]
+ diags = append(diags, &hcl.Diagnostic{
+ Severity: hcl.DiagError,
+ Summary: "Variable declaration in a .pkrvar file",
+ Detail: fmt.Sprintf("A .pkrvar file is used to assign "+
+ "values to variables that have already been declared "+
+ "in .pkr files, not to declare new variables. To "+
+ "declare variable %q, place this block in one of your"+
+ " .pkr files, such as variables.pkr.hcl\n\nTo set a "+
+ "value for this variable in %s, use the definition "+
+ "syntax instead:\n %s = <value>",
+ name, block.TypeRange.Filename, name),
+ Subject: &block.TypeRange,
+ })
+ }
+ if diags.HasErrors() {
+ // If we already found problems then JustAttributes below will find
+ // the same problems with less-helpful messages, so we'll bail for
+ // now to let the user focus on the immediate problem.
+ return diags
+ }
+ }
+
+ attrs, moreDiags := file.Body.JustAttributes()
+ diags = append(diags, moreDiags...)
+
+ for name, attr := range attrs {
+ variable, found := variables[name]
+ if !found {
+ if !cfg.ValidationOptions.WarnOnUndeclaredVar {
+ continue
+ }
+
+ diags = append(diags, &hcl.Diagnostic{
+ Severity: hcl.DiagWarning,
+ Summary: "Undefined variable",
+ Detail: fmt.Sprintf("The variable %[1]q was set but was not declared as an input variable."+
+ "\nTo declare variable %[1]q place this block in one of your .pkr.hcl files, "+
+ "such as variables.pkr.hcl\n\n"+
+ "variable %[1]q {\n"+
+ " type = string\n"+
+ " default = null\n"+
+ "}",
+ name),
+ Context: attr.Range.Ptr(),
+ })
+ continue
+ }
+
+ val, moreDiags := attr.Expr.Value(nil)
+ diags = append(diags, moreDiags...)
+
+ if variable.Type != cty.NilType {
+ var err error
+ val, err = convert.Convert(val, variable.Type)
+ if err != nil {
+ diags = append(diags, &hcl.Diagnostic{
+ Severity: hcl.DiagError,
+ Summary: "Invalid value for variable",
+ Detail: fmt.Sprintf("The value for %s is not compatible with the variable's type constraint: %s.", name, err),
+ Subject: attr.Expr.Range().Ptr(),
+ })
+ val = cty.DynamicVal
+ }
+ }
+
+ variable.Values = append(variable.Values, VariableAssignment{
+ From: "varfile",
+ Value: val,
+ Expr: attr.Expr,
+ })
+ }
+ }
+
+ // Finally we process values given explicitly on the command line.
+ for name, value := range argv {
+ variable, found := variables[name]
+ if !found {
+ diags = append(diags, &hcl.Diagnostic{
+ Severity: hcl.DiagError,
+ Summary: "Undefined -var variable",
+ Detail: fmt.Sprintf("A %q variable was passed in the command "+
+ "line but was not found in known variables. "+
+ "To declare variable %q, place this block in one of your"+
+ " .pkr files, such as variables.pkr.hcl",
+ name, name),
+ })
+ continue
+ }
+
+ fakeFilename := fmt.Sprintf("<value for var.%s from arguments>", name)
+ expr, moreDiags := expressionFromVariableDefinition(fakeFilename, value, variable.Type)
+ diags = append(diags, moreDiags...)
+ if moreDiags.HasErrors() {
+ continue
+ }
+
+ val, valDiags := expr.Value(nil)
+ diags = append(diags, valDiags...)
+
+ if variable.Type != cty.NilType {
+ var err error
+ val, err = convert.Convert(val, variable.Type)
+ if err != nil {
+ diags = append(diags, &hcl.Diagnostic{
+ Severity: hcl.DiagError,
+ Summary: "Invalid argument value for -var variable",
+ Detail: fmt.Sprintf("The received arg value for %s is not compatible with the variable's type constraint: %s.", name, err),
+ Subject: expr.Range().Ptr(),
+ })
+ val = cty.DynamicVal
+ }
+ }
+
+ variable.Values = append(variable.Values, VariableAssignment{
+ From: "cmd",
+ Value: val,
+ Expr: expr,
+ })
+ }
+
+ return diags
+}
+
+// expressionFromVariableDefinition creates an hclsyntax.Expression that is capable of evaluating the specified value for a given cty.Type.
+// The specified filename is to identify the source of where value originated from in the diagnostics report, if there is an error.
+func expressionFromVariableDefinition(filename string, value string, variableType cty.Type) (hclsyntax.Expression, hcl.Diagnostics) {
+ switch variableType {
+ case cty.String, cty.Number, cty.NilType, cty.DynamicPseudoType:
+ // when the type is nil (not set in a variable block) we default to
+ // interpreting everything as a string literal.
+ return &hclsyntax.LiteralValueExpr{Val: cty.StringVal(value)}, nil
+ default:
+ return hclsyntax.ParseExpression([]byte(value), filename, hcl.Pos{Line: 1, Column: 1})
+ }
+}
diff --git a/v1.9.4/hcl2template/types.variables_test.go b/v1.9.4/hcl2template/types.variables_test.go
new file mode 100644
index 0000000..d0691a0
--- /dev/null
+++ b/v1.9.4/hcl2template/types.variables_test.go
@@ -0,0 +1,1042 @@
+// Copyright (c) HashiCorp, Inc.
+// SPDX-License-Identifier: MPL-2.0
+
+package hcl2template
+
+import (
+ "fmt"
+ "path/filepath"
+ "testing"
+
+ "github.com/google/go-cmp/cmp"
+ "github.com/hashicorp/hcl/v2"
+ packersdk "github.com/hashicorp/packer-plugin-sdk/packer"
+ "github.com/hashicorp/packer/builder/null"
+ . "github.com/hashicorp/packer/hcl2template/internal"
+ "github.com/hashicorp/packer/packer"
+ "github.com/zclconf/go-cty/cty"
+ "github.com/zclconf/go-cty/cty/convert"
+)
+
+func TestParse_variables(t *testing.T) {
+ defaultParser := getBasicParser()
+
+ tests := []parseTest{
+ {"basic variables",
+ defaultParser,
+ parseTestArgs{"testdata/variables/basic.pkr.hcl", nil, nil},
+ &PackerConfig{
+ CorePackerVersionString: lockedVersion,
+ Builds: Builds{
+ &BuildBlock{
+ Sources: []SourceUseBlock{
+ {
+ SourceRef: SourceRef{
+ Type: "null",
+ Name: "test",
+ },
+ },
+ },
+ },
+ },
+ Sources: map[SourceRef]SourceBlock{
+ {
+ Type: "null",
+ Name: "test",
+ }: {
+ Type: "null",
+ Name: "test",
+ },
+ },
+ Basedir: filepath.Join("testdata", "variables"),
+ InputVariables: Variables{
+ "image_name": &Variable{
+ Name: "image_name",
+ Type: cty.String,
+ Values: []VariableAssignment{{From: "default", Value: cty.StringVal("foo-image-{{user `my_secret`}}")}},
+ },
+ "key": &Variable{
+ Name: "key",
+ Type: cty.String,
+ Values: []VariableAssignment{{From: "default", Value: cty.StringVal("value")}},
+ },
+ "my_secret": &Variable{
+ Name: "my_secret",
+ Type: cty.String,
+ Values: []VariableAssignment{{From: "default", Value: cty.StringVal("foo")}},
+ },
+ "image_id": &Variable{
+ Name: "image_id",
+ Type: cty.String,
+ Values: []VariableAssignment{{From: "default", Value: cty.StringVal("image-id-default")}},
+ },
+ "port": &Variable{
+ Name: "port",
+ Type: cty.Number,
+ Values: []VariableAssignment{{From: "default", Value: cty.NumberIntVal(42)}},
+ },
+ "availability_zone_names": &Variable{
+ Name: "availability_zone_names",
+ Values: []VariableAssignment{{
+ From: "default",
+ Value: cty.ListVal([]cty.Value{
+ cty.StringVal("us-west-1a"),
+ }),
+ }},
+ Type: cty.List(cty.String),
+ Description: fmt.Sprintln("Describing is awesome ;D"),
+ },
+ "super_secret_password": &Variable{
+ Name: "super_secret_password",
+ Sensitive: true,
+ Values: []VariableAssignment{{
+ From: "default",
+ Value: cty.NullVal(cty.String),
+ }},
+ Type: cty.String,
+ Description: fmt.Sprintln("Handle with care plz"),
+ },
+ },
+ LocalVariables: Variables{
+ "owner": &Variable{
+ Name: "owner",
+ Values: []VariableAssignment{{
+ From: "default",
+ Value: cty.StringVal("Community Team"),
+ }},
+ Type: cty.String,
+ },
+ "service_name": &Variable{
+ Name: "service_name",
+ Values: []VariableAssignment{{
+ From: "default",
+ Value: cty.StringVal("forum"),
+ }},
+ Type: cty.String,
+ },
+ "supersecret": &Variable{
+ Name: "supersecret",
+ Values: []VariableAssignment{{
+ From: "default",
+ Value: cty.StringVal("secretvar"),
+ }},
+ Type: cty.String,
+ Sensitive: true,
+ },
+ },
+ },
+ false, false,
+ []packersdk.Build{
+ &packer.CoreBuild{
+ Type: "null.test",
+ Builder: &null.Builder{},
+ Provisioners: []packer.CoreBuildProvisioner{},
+ PostProcessors: [][]packer.CoreBuildPostProcessor{},
+ Prepared: true,
+ },
+ },
+ false,
+ },
+ {"duplicate variable",
+ defaultParser,
+ parseTestArgs{"testdata/variables/duplicate_variable.pkr.hcl", nil, nil},
+ &PackerConfig{
+ CorePackerVersionString: lockedVersion,
+ Basedir: filepath.Join("testdata", "variables"),
+ InputVariables: Variables{
+ "boolean_value": &Variable{
+ Name: "boolean_value",
+ Values: []VariableAssignment{{
+ From: "default",
+ Value: cty.BoolVal(false),
+ }},
+ Type: cty.Bool,
+ },
+ },
+ },
+ true, true,
+ []packersdk.Build{},
+ false,
+ },
+ {"duplicate variable in variables",
+ defaultParser,
+ parseTestArgs{"testdata/variables/duplicate_variables.pkr.hcl", nil, nil},
+ &PackerConfig{
+ CorePackerVersionString: lockedVersion,
+ Basedir: filepath.Join("testdata", "variables"),
+ InputVariables: Variables{
+ "boolean_value": &Variable{
+ Name: "boolean_value",
+ Values: []VariableAssignment{{
+ From: "default",
+ Value: cty.BoolVal(false),
+ }},
+ Type: cty.Bool,
+ },
+ },
+ },
+ true, true,
+ []packersdk.Build{},
+ false,
+ },
+ {"duplicate local block",
+ defaultParser,
+ parseTestArgs{"testdata/variables/duplicate_locals", nil, nil},
+ &PackerConfig{
+ CorePackerVersionString: lockedVersion,
+ Basedir: "testdata/variables/duplicate_locals",
+ LocalVariables: Variables{
+ "sensible": &Variable{
+ Values: []VariableAssignment{
+ {
+ From: "default",
+ Value: cty.StringVal("something"),
+ },
+ },
+ Type: cty.String,
+ Name: "sensible",
+ },
+ },
+ },
+ true, true,
+ []packersdk.Build{},
+ false,
+ },
+ {"invalid default type",
+ defaultParser,
+ parseTestArgs{"testdata/variables/invalid_default.pkr.hcl", nil, nil},
+ &PackerConfig{
+ CorePackerVersionString: lockedVersion,
+ Basedir: filepath.Join("testdata", "variables"),
+ InputVariables: Variables{
+ "broken_type": &Variable{
+ Name: "broken_type",
+ Values: []VariableAssignment{{
+ From: "default",
+ Value: cty.UnknownVal(cty.DynamicPseudoType),
+ }},
+ Type: cty.List(cty.String),
+ },
+ },
+ },
+ true, true,
+ []packersdk.Build{},
+ false,
+ },
+
+ {"unknown key",
+ defaultParser,
+ parseTestArgs{"testdata/variables/unknown_key.pkr.hcl", nil, nil},
+ &PackerConfig{
+ CorePackerVersionString: lockedVersion,
+ Basedir: filepath.Join("testdata", "variables"),
+ InputVariables: Variables{
+ "broken_variable": &Variable{
+ Name: "broken_variable",
+ Values: []VariableAssignment{{From: "default", Value: cty.BoolVal(true)}},
+ Type: cty.Bool,
+ },
+ },
+ },
+ true, true,
+ []packersdk.Build{},
+ false,
+ },
+
+ {"unset used variable",
+ defaultParser,
+ parseTestArgs{"testdata/variables/unset_used_string_variable.pkr.hcl", nil, nil},
+ &PackerConfig{
+ CorePackerVersionString: lockedVersion,
+ Basedir: filepath.Join("testdata", "variables"),
+ InputVariables: Variables{
+ "foo": &Variable{
+ Name: "foo",
+ Type: cty.String,
+ },
+ },
+ },
+ true, true,
+ []packersdk.Build{},
+ true,
+ },
+
+ {"unset unused variable",
+ defaultParser,
+ parseTestArgs{"testdata/variables/unset_unused_string_variable.pkr.hcl", nil, nil},
+ &PackerConfig{
+ CorePackerVersionString: lockedVersion,
+ Basedir: filepath.Join("testdata", "variables"),
+ InputVariables: Variables{
+ "foo": &Variable{
+ Name: "foo",
+ Type: cty.String,
+ },
+ },
+ Sources: map[SourceRef]SourceBlock{
+ SourceRef{Type: "null", Name: "null-builder"}: SourceBlock{
+ Name: "null-builder",
+ Type: "null",
+ },
+ },
+ Builds: Builds{
+ &BuildBlock{
+ Sources: []SourceUseBlock{
+ {
+ SourceRef: SourceRef{Type: "null", Name: "null-builder"},
+ },
+ },
+ },
+ },
+ },
+ true, true,
+ []packersdk.Build{
+ &packer.CoreBuild{
+ Type: "null",
+ Builder: &null.Builder{},
+ Provisioners: []packer.CoreBuildProvisioner{},
+ PostProcessors: [][]packer.CoreBuildPostProcessor{},
+ Prepared: true,
+ },
+ },
+ false,
+ },
+
+ {"locals within another locals usage in different files",
+ defaultParser,
+ parseTestArgs{"testdata/variables/complicated", nil, nil},
+ &PackerConfig{
+ CorePackerVersionString: lockedVersion,
+ Builds: Builds{
+ &BuildBlock{
+ Sources: []SourceUseBlock{
+ {
+ SourceRef: SourceRef{
+ Type: "null",
+ Name: "test",
+ },
+ },
+ },
+ },
+ },
+ Sources: map[SourceRef]SourceBlock{
+ {
+ Type: "null",
+ Name: "test",
+ }: {
+ Type: "null",
+ Name: "test",
+ },
+ },
+ Basedir: "testdata/variables/complicated",
+ InputVariables: Variables{
+ "name_prefix": &Variable{
+ Name: "name_prefix",
+ Values: []VariableAssignment{{From: "default", Value: cty.StringVal("foo")}},
+ Type: cty.String,
+ },
+ },
+ LocalVariables: Variables{
+ "name_prefix": &Variable{
+ Name: "name_prefix",
+ Values: []VariableAssignment{{From: "default", Value: cty.StringVal("foo")}},
+ Type: cty.String,
+ },
+ "foo": &Variable{
+ Name: "foo",
+ Values: []VariableAssignment{{From: "default", Value: cty.StringVal("foo")}},
+ Type: cty.String,
+ },
+ "bar": &Variable{
+ Name: "bar",
+ Values: []VariableAssignment{{From: "default", Value: cty.StringVal("foo")}},
+ Type: cty.String,
+ },
+ "for_var": &Variable{
+ Name: "for_var",
+ Values: []VariableAssignment{{From: "default", Value: cty.StringVal("foo")}},
+ Type: cty.String,
+ },
+ "bar_var": &Variable{
+ Name: "bar_var",
+ Values: []VariableAssignment{{
+ From: "default",
+ Value: cty.TupleVal([]cty.Value{
+ cty.StringVal("foo"),
+ cty.StringVal("foo"),
+ cty.StringVal("foo"),
+ }),
+ }},
+ Type: cty.Tuple([]cty.Type{
+ cty.String,
+ cty.String,
+ cty.String,
+ }),
+ },
+ },
+ },
+ false, false,
+ []packersdk.Build{
+ &packer.CoreBuild{
+ Type: "null.test",
+ Builder: &null.Builder{},
+ Provisioners: []packer.CoreBuildProvisioner{},
+ PostProcessors: [][]packer.CoreBuildPostProcessor{},
+ Prepared: true,
+ },
+ },
+ false,
+ },
+ {"recursive locals",
+ defaultParser,
+ parseTestArgs{"testdata/variables/recursive_locals.pkr.hcl", nil, nil},
+ &PackerConfig{
+ CorePackerVersionString: lockedVersion,
+ Basedir: filepath.Join("testdata", "variables"),
+ LocalVariables: Variables{},
+ },
+ true, true,
+ []packersdk.Build{},
+ false,
+ },
+
+ {"set variable from var-file",
+ defaultParser,
+ parseTestArgs{"testdata/variables/foo-string.variable.pkr.hcl", nil, []string{"testdata/variables/set-foo-too-wee.hcl"}},
+ &PackerConfig{
+ CorePackerVersionString: lockedVersion,
+ Basedir: filepath.Join("testdata", "variables"),
+ Builds: Builds{
+ &BuildBlock{
+ Sources: []SourceUseBlock{
+ {
+ SourceRef: SourceRef{
+ Type: "null",
+ Name: "test",
+ },
+ },
+ },
+ },
+ },
+ Sources: map[SourceRef]SourceBlock{
+ {
+ Type: "null",
+ Name: "test",
+ }: {
+ Type: "null",
+ Name: "test",
+ },
+ },
+ InputVariables: Variables{
+ "foo": &Variable{
+ Name: "foo",
+ Values: []VariableAssignment{
+ VariableAssignment{"default", cty.StringVal("bar"), nil},
+ VariableAssignment{"varfile", cty.StringVal("wee"), nil},
+ },
+ Type: cty.String,
+ },
+ },
+ },
+ false, false,
+ []packersdk.Build{
+ &packer.CoreBuild{
+ Type: "null.test",
+ Builder: &null.Builder{},
+ Provisioners: []packer.CoreBuildProvisioner{},
+ PostProcessors: [][]packer.CoreBuildPostProcessor{},
+ Prepared: true,
+ },
+ },
+ false,
+ },
+
+ {"unknown variable from var-file",
+ defaultParser,
+ parseTestArgs{"testdata/variables/empty.pkr.hcl", nil, []string{"testdata/variables/set-foo-too-wee.hcl"}},
+ &PackerConfig{
+ CorePackerVersionString: lockedVersion,
+ Builds: Builds{
+ &BuildBlock{
+ Sources: []SourceUseBlock{
+ {
+ SourceRef: SourceRef{
+ Type: "null",
+ Name: "test",
+ },
+ },
+ },
+ },
+ },
+ Sources: map[SourceRef]SourceBlock{
+ {
+ Type: "null",
+ Name: "test",
+ }: {
+ Type: "null",
+ Name: "test",
+ },
+ },
+ Basedir: filepath.Join("testdata", "variables"),
+ },
+ false, false,
+ []packersdk.Build{
+ &packer.CoreBuild{
+ Type: "null.test",
+ Builder: &null.Builder{},
+ Provisioners: []packer.CoreBuildProvisioner{},
+ PostProcessors: [][]packer.CoreBuildPostProcessor{},
+ Prepared: true,
+ },
+ },
+ false,
+ },
+
+ {"provisioner variable decoding",
+ defaultParser,
+ parseTestArgs{"testdata/variables/provisioner_variable_decoding.pkr.hcl", nil, nil},
+ &PackerConfig{
+ CorePackerVersionString: lockedVersion,
+ Basedir: filepath.Join("testdata", "variables"),
+ InputVariables: Variables{
+ "max_retries": &Variable{
+ Name: "max_retries",
+ Values: []VariableAssignment{{"default", cty.StringVal("1"), nil}},
+ Type: cty.String,
+ },
+ "max_retries_int": &Variable{
+ Name: "max_retries_int",
+ Values: []VariableAssignment{{"default", cty.NumberIntVal(1), nil}},
+ Type: cty.Number,
+ },
+ },
+ Sources: map[SourceRef]SourceBlock{
+ SourceRef{Type: "null", Name: "null-builder"}: SourceBlock{
+ Name: "null-builder",
+ Type: "null",
+ },
+ },
+ Builds: Builds{
+ &BuildBlock{
+ Sources: []SourceUseBlock{
+ {
+ SourceRef: SourceRef{Type: "null", Name: "null-builder"},
+ },
+ },
+ ProvisionerBlocks: []*ProvisionerBlock{
+ {
+ PType: "shell",
+ MaxRetries: 1,
+ },
+ {
+ PType: "shell",
+ MaxRetries: 1,
+ },
+ },
+ },
+ },
+ },
+ false, false,
+ []packersdk.Build{&packer.CoreBuild{
+ Type: "null.null-builder",
+ Prepared: true,
+ Builder: &null.Builder{},
+ Provisioners: []packer.CoreBuildProvisioner{
+ {
+ PType: "shell",
+ Provisioner: &packer.RetriedProvisioner{
+ MaxRetries: 1,
+ Provisioner: &HCL2Provisioner{
+ Provisioner: &MockProvisioner{
+ Config: MockConfig{
+ NestedMockConfig: NestedMockConfig{
+ Tags: []MockTag{},
+ },
+ NestedSlice: []NestedMockConfig{},
+ },
+ },
+ },
+ },
+ },
+ {
+ PType: "shell",
+ Provisioner: &packer.RetriedProvisioner{
+ MaxRetries: 1,
+ Provisioner: &HCL2Provisioner{
+ Provisioner: &MockProvisioner{
+ Config: MockConfig{
+ NestedMockConfig: NestedMockConfig{
+ Tags: []MockTag{},
+ },
+ NestedSlice: []NestedMockConfig{},
+ },
+ },
+ },
+ },
+ },
+ },
+ PostProcessors: [][]packer.CoreBuildPostProcessor{},
+ },
+ },
+ false,
+ },
+
+ {"valid validation block",
+ defaultParser,
+ parseTestArgs{"testdata/variables/validation/valid.pkr.hcl", nil, nil},
+ &PackerConfig{
+ CorePackerVersionString: lockedVersion,
+ Basedir: filepath.Join("testdata", "variables", "validation"),
+ Builds: Builds{
+ &BuildBlock{
+ Sources: []SourceUseBlock{
+ {
+ SourceRef: SourceRef{
+ Type: "null",
+ Name: "test",
+ },
+ },
+ },
+ },
+ },
+ Sources: map[SourceRef]SourceBlock{
+ {
+ Type: "null",
+ Name: "test",
+ }: {
+ Type: "null",
+ Name: "test",
+ },
+ },
+ InputVariables: Variables{
+ "image_id": &Variable{
+ Values: []VariableAssignment{
+ {"default", cty.StringVal("ami-something-something"), nil},
+ },
+ Name: "image_id",
+ Type: cty.String,
+ Validations: []*VariableValidation{
+ &VariableValidation{
+ ErrorMessage: `The image_id value must be a valid AMI id, starting with "ami-".`,
+ },
+ },
+ },
+ },
+ },
+ false, false,
+ []packersdk.Build{
+ &packer.CoreBuild{
+ Type: "null.test",
+ Builder: &null.Builder{},
+ Provisioners: []packer.CoreBuildProvisioner{},
+ PostProcessors: [][]packer.CoreBuildPostProcessor{},
+ Prepared: true,
+ },
+ },
+ false,
+ },
+
+ {"valid validation block - invalid default",
+ defaultParser,
+ parseTestArgs{"testdata/variables/validation/invalid_default.pkr.hcl", nil, nil},
+ &PackerConfig{
+ CorePackerVersionString: lockedVersion,
+ Basedir: filepath.Join("testdata", "variables", "validation"),
+ InputVariables: Variables{
+ "image_id": &Variable{
+ Values: []VariableAssignment{{"default", cty.StringVal("potato"), nil}},
+ Name: "image_id",
+ Type: cty.String,
+ Validations: []*VariableValidation{
+ &VariableValidation{
+ ErrorMessage: `The image_id value must be a valid AMI id, starting with "ami-".`,
+ },
+ },
+ },
+ },
+ },
+ true, true,
+ nil,
+ false,
+ },
+ }
+ testParse(t, tests)
+}
+
+func TestVariables_collectVariableValues(t *testing.T) {
+ type args struct {
+ env []string
+ hclFiles []string
+ argv map[string]string
+ }
+ tests := []struct {
+ name string
+ variables Variables
+ validationOptions ValidationOptions
+ args args
+ wantDiags bool
+ wantDiagsHasError bool
+ wantVariables Variables
+ wantValues map[string]cty.Value
+ }{
+
+ {name: "string",
+ variables: Variables{"used_string": &Variable{
+ Values: []VariableAssignment{
+ {"default", cty.StringVal("default_value"), nil},
+ },
+ Type: cty.String,
+ }},
+ args: args{
+ env: []string{`PKR_VAR_used_string=env_value`},
+ hclFiles: []string{
+ `used_string="xy"`,
+ `used_string="varfile_value"`,
+ },
+ argv: map[string]string{
+ "used_string": `cmd_value`,
+ },
+ },
+
+ // output
+ wantDiags: false,
+ wantVariables: Variables{
+ "used_string": &Variable{
+ Type: cty.String,
+ Values: []VariableAssignment{
+ {"default", cty.StringVal(`default_value`), nil},
+ {"env", cty.StringVal(`env_value`), nil},
+ {"varfile", cty.StringVal(`xy`), nil},
+ {"varfile", cty.StringVal(`varfile_value`), nil},
+ {"cmd", cty.StringVal(`cmd_value`), nil},
+ },
+ },
+ },
+ wantValues: map[string]cty.Value{
+ "used_string": cty.StringVal("cmd_value"),
+ },
+ },
+
+ {name: "quoted string",
+ variables: Variables{"quoted_string": &Variable{
+ Values: []VariableAssignment{
+ {"default", cty.StringVal(`"default_value"`), nil},
+ },
+ Type: cty.String,
+ }},
+ args: args{
+ env: []string{`PKR_VAR_quoted_string="env_value"`},
+ hclFiles: []string{
+ `quoted_string="\"xy\""`,
+ `quoted_string="\"varfile_value\""`,
+ },
+ argv: map[string]string{
+ "quoted_string": `"cmd_value"`,
+ },
+ },
+
+ // output
+ wantDiags: false,
+ wantVariables: Variables{
+ "quoted_string": &Variable{
+ Type: cty.String,
+ Values: []VariableAssignment{
+ {"default", cty.StringVal(`"default_value"`), nil},
+ {"env", cty.StringVal(`"env_value"`), nil},
+ {"varfile", cty.StringVal(`"xy"`), nil},
+ {"varfile", cty.StringVal(`"varfile_value"`), nil},
+ {"cmd", cty.StringVal(`"cmd_value"`), nil},
+ },
+ },
+ },
+ wantValues: map[string]cty.Value{
+ "quoted_string": cty.StringVal(`"cmd_value"`),
+ },
+ },
+
+ {name: "array of strings",
+ variables: Variables{"used_strings": &Variable{
+ Values: []VariableAssignment{
+ {"default", stringListVal("default_value_1"), nil},
+ },
+ Type: cty.List(cty.String),
+ }},
+ args: args{
+ env: []string{`PKR_VAR_used_strings=["env_value_1", "env_value_2"]`},
+ hclFiles: []string{
+ `used_strings=["xy"]`,
+ `used_strings=["varfile_value_1"]`,
+ },
+ argv: map[string]string{
+ "used_strings": `["cmd_value_1"]`,
+ },
+ },
+
+ // output
+ wantDiags: false,
+ wantVariables: Variables{
+ "used_strings": &Variable{
+ Type: cty.List(cty.String),
+ Values: []VariableAssignment{
+ {"default", stringListVal("default_value_1"), nil},
+ {"env", stringListVal("env_value_1", "env_value_2"), nil},
+ {"varfile", stringListVal("xy"), nil},
+ {"varfile", stringListVal("varfile_value_1"), nil},
+ {"cmd", stringListVal("cmd_value_1"), nil},
+ },
+ },
+ },
+ wantValues: map[string]cty.Value{
+ "used_strings": stringListVal("cmd_value_1"),
+ },
+ },
+
+ {name: "bool",
+ variables: Variables{"enabled": &Variable{
+ Values: []VariableAssignment{{"default", cty.False, nil}},
+ Type: cty.Bool,
+ }},
+ args: args{
+ env: []string{`PKR_VAR_enabled=true`},
+ hclFiles: []string{
+ `enabled="false"`,
+ },
+ argv: map[string]string{
+ "enabled": `true`,
+ },
+ },
+
+ // output
+ wantDiags: false,
+ wantVariables: Variables{
+ "enabled": &Variable{
+ Type: cty.Bool,
+ Values: []VariableAssignment{
+ {"default", cty.False, nil},
+ {"env", cty.True, nil},
+ {"varfile", cty.False, nil},
+ {"cmd", cty.True, nil},
+ },
+ },
+ },
+ wantValues: map[string]cty.Value{
+ "enabled": cty.True,
+ },
+ },
+
+ {name: "invalid env var",
+ variables: Variables{"used_string": &Variable{
+ Values: []VariableAssignment{{"default", cty.StringVal("default_value"), nil}},
+ Type: cty.String,
+ }},
+ args: args{
+ env: []string{`PKR_VAR_used_string`},
+ },
+
+ // output
+ wantDiags: false,
+ wantVariables: Variables{
+ "used_string": &Variable{
+ Type: cty.String,
+ Values: []VariableAssignment{{"default", cty.StringVal("default_value"), nil}},
+ },
+ },
+ wantValues: map[string]cty.Value{
+ "used_string": cty.StringVal("default_value"),
+ },
+ },
+
+ {name: "undefined but set value - pkrvar file - normal mode",
+ variables: Variables{},
+ args: args{
+ hclFiles: []string{`undefined_string="value"`},
+ },
+
+ // output
+ wantDiags: false,
+ wantDiagsHasError: false,
+ wantVariables: Variables{},
+ wantValues: map[string]cty.Value{},
+ },
+
+ {name: "undefined but set value - pkrvar file - strict mode",
+ variables: Variables{},
+ validationOptions: ValidationOptions{
+ WarnOnUndeclaredVar: true,
+ },
+ args: args{
+ hclFiles: []string{`undefined_string="value"`},
+ },
+
+ // output
+ wantDiags: true,
+ wantDiagsHasError: false,
+ wantVariables: Variables{},
+ wantValues: map[string]cty.Value{},
+ },
+
+ {name: "undefined but set value - env",
+ variables: Variables{},
+ args: args{
+ env: []string{`PKR_VAR_undefined_string=value`},
+ },
+
+ // output
+ wantDiags: false,
+ wantVariables: Variables{},
+ wantValues: map[string]cty.Value{},
+ },
+
+ {name: "undefined but set value - argv",
+ variables: Variables{},
+ args: args{
+ argv: map[string]string{
+ "undefined_string": "value",
+ },
+ },
+
+ // output
+ wantDiags: true,
+ wantDiagsHasError: true,
+ wantVariables: Variables{},
+ wantValues: map[string]cty.Value{},
+ },
+
+ {name: "value not corresponding to type - env",
+ variables: Variables{
+ "used_string": &Variable{
+ Type: cty.List(cty.String),
+ },
+ },
+ args: args{
+ env: []string{`PKR_VAR_used_string="string"`},
+ },
+
+ // output
+ wantDiags: true,
+ wantDiagsHasError: true,
+ wantVariables: Variables{
+ "used_string": &Variable{
+ Type: cty.List(cty.String),
+ Values: []VariableAssignment{{"env", cty.DynamicVal, nil}},
+ },
+ },
+ wantValues: map[string]cty.Value{
+ "used_string": cty.DynamicVal,
+ },
+ },
+
+ {name: "value not corresponding to type - cfg file",
+ variables: Variables{
+ "used_string": &Variable{
+ Type: cty.Bool,
+ },
+ },
+ args: args{
+ hclFiles: []string{`used_string=["string"]`},
+ },
+
+ // output
+ wantDiags: true,
+ wantDiagsHasError: true,
+ wantVariables: Variables{
+ "used_string": &Variable{
+ Type: cty.Bool,
+ Values: []VariableAssignment{{"varfile", cty.DynamicVal, nil}},
+ },
+ },
+ wantValues: map[string]cty.Value{
+ "used_string": cty.DynamicVal,
+ },
+ },
+
+ {name: "value not corresponding to type - argv",
+ variables: Variables{
+ "used_string": &Variable{
+ Type: cty.Bool,
+ },
+ },
+ args: args{
+ argv: map[string]string{
+ "used_string": `["true"]`,
+ },
+ },
+
+ // output
+ wantDiags: true,
+ wantDiagsHasError: true,
+ wantVariables: Variables{
+ "used_string": &Variable{
+ Type: cty.Bool,
+ Values: []VariableAssignment{{"cmd", cty.DynamicVal, nil}},
+ },
+ },
+ wantValues: map[string]cty.Value{
+ "used_string": cty.DynamicVal,
+ },
+ },
+
+ {name: "defining a variable block in a variables file is invalid ",
+ variables: Variables{},
+ args: args{
+ hclFiles: []string{`variable "something" {}`},
+ },
+
+ // output
+ wantDiags: true,
+ wantDiagsHasError: true,
+ wantVariables: Variables{},
+ wantValues: map[string]cty.Value{},
+ },
+ }
+ for _, tt := range tests {
+ t.Run(tt.name, func(t *testing.T) {
+ var files []*hcl.File
+ parser := getBasicParser()
+ for i, hclContent := range tt.args.hclFiles {
+ file, diags := parser.ParseHCL([]byte(hclContent), fmt.Sprintf("test_file_%d_*"+hcl2AutoVarFileExt, i))
+ if diags != nil {
+ t.Fatalf("ParseHCLFile %d: %v", i, diags)
+ }
+ files = append(files, file)
+ }
+ cfg := &PackerConfig{
+ InputVariables: tt.variables,
+ ValidationOptions: tt.validationOptions,
+ }
+ gotDiags := cfg.collectInputVariableValues(tt.args.env, files, tt.args.argv)
+ if (gotDiags == nil) == tt.wantDiags {
+ t.Fatalf("Variables.collectVariableValues() = %v, want %v", gotDiags, tt.wantDiags)
+ }
+ if tt.wantDiagsHasError != gotDiags.HasErrors() {
+ t.Fatalf("Variables.collectVariableValues() unexpected diagnostics HasErrors. %s", gotDiags)
+ }
+ if diff := cmp.Diff(tt.wantVariables, tt.variables, cmpOpts...); diff != "" {
+ t.Fatalf("didn't get expected variables: %s", diff)
+ }
+ values := map[string]cty.Value{}
+ for k, v := range tt.variables {
+ value, diag := v.Value(), v.ValidateValue()
+ if diag != nil {
+ t.Fatalf("Value %s: %v", k, diag)
+ }
+ values[k] = value
+ }
+ if diff := cmp.Diff(fmt.Sprintf("%#v", values), fmt.Sprintf("%#v", tt.wantValues)); diff != "" {
+ t.Fatalf("didn't get expected values: %s", diff)
+ }
+ })
+ }
+}
+
+func stringListVal(strings ...string) cty.Value {
+ values := []cty.Value{}
+ for _, str := range strings {
+ values = append(values, cty.StringVal(str))
+ }
+ list, err := convert.Convert(cty.ListVal(values), cty.List(cty.String))
+ if err != nil {
+ panic(err)
+ }
+ return list
+}
diff --git a/v1.9.4/hcl2template/utils.go b/v1.9.4/hcl2template/utils.go
new file mode 100644
index 0000000..b74093b
--- /dev/null
+++ b/v1.9.4/hcl2template/utils.go
@@ -0,0 +1,189 @@
+// Copyright (c) HashiCorp, Inc.
+// SPDX-License-Identifier: MPL-2.0
+
+package hcl2template
+
+import (
+ "fmt"
+ "io/ioutil"
+ "os"
+ "path/filepath"
+ "strings"
+
+ "github.com/gobwas/glob"
+ "github.com/hashicorp/hcl/v2"
+ "github.com/hashicorp/packer/hcl2template/repl"
+ hcl2shim "github.com/hashicorp/packer/hcl2template/shim"
+ "github.com/zclconf/go-cty/cty"
+)
+
+func warningErrorsToDiags(block *hcl.Block, warnings []string, err error) hcl.Diagnostics {
+ var diags hcl.Diagnostics
+
+ for _, warning := range warnings {
+ diags = append(diags, &hcl.Diagnostic{
+ Summary: warning,
+ Subject: &block.DefRange,
+ Severity: hcl.DiagWarning,
+ })
+ }
+ if err != nil {
+ diags = append(diags, &hcl.Diagnostic{
+ Summary: err.Error(),
+ Subject: &block.DefRange,
+ Severity: hcl.DiagError,
+ })
+ }
+ return diags
+}
+
+func isDir(name string) (bool, error) {
+ s, err := os.Stat(name)
+ if err != nil {
+ return false, err
+ }
+ return s.IsDir(), nil
+}
+
+// GetHCL2Files returns two slices of json formatted and hcl formatted files,
+// hclSuffix and jsonSuffix tell which file is what. Filename can be a folder
+// or a file.
+//
+// When filename is a folder all files of folder matching the suffixes will be
+// returned. Otherwise if filename references a file and filename matches one
+// of the suffixes it is returned in the according slice.
+func GetHCL2Files(filename, hclSuffix, jsonSuffix string) (hclFiles, jsonFiles []string, diags hcl.Diagnostics) {
+ if filename == "" {
+ return
+ }
+ isDir, err := isDir(filename)
+ if err != nil {
+ diags = append(diags, &hcl.Diagnostic{
+ Severity: hcl.DiagError,
+ Detail: err.Error(),
+ })
+ return nil, nil, diags
+ }
+ if !isDir {
+ if strings.HasSuffix(filename, jsonSuffix) {
+ return nil, []string{filename}, diags
+ }
+ if strings.HasSuffix(filename, hclSuffix) {
+ return []string{filename}, nil, diags
+ }
+ return nil, nil, diags
+ }
+
+ fileInfos, err := ioutil.ReadDir(filename)
+ if err != nil {
+ diag := &hcl.Diagnostic{
+ Severity: hcl.DiagError,
+ Summary: "Cannot read hcl directory",
+ Detail: err.Error(),
+ }
+ diags = append(diags, diag)
+ return nil, nil, diags
+ }
+ for _, fileInfo := range fileInfos {
+ if fileInfo.IsDir() {
+ continue
+ }
+ filename := filepath.Join(filename, fileInfo.Name())
+ if strings.HasSuffix(filename, hclSuffix) {
+ hclFiles = append(hclFiles, filename)
+ } else if strings.HasSuffix(filename, jsonSuffix) {
+ jsonFiles = append(jsonFiles, filename)
+ }
+ }
+
+ return hclFiles, jsonFiles, diags
+}
+
+// Convert -only and -except globs to glob.Glob instances.
+func convertFilterOption(patterns []string, optionName string) ([]glob.Glob, hcl.Diagnostics) {
+ var globs []glob.Glob
+ var diags hcl.Diagnostics
+
+ for _, pattern := range patterns {
+ g, err := glob.Compile(pattern)
+ if err != nil {
+ diags = append(diags, &hcl.Diagnostic{
+ Summary: fmt.Sprintf("Invalid -%s pattern %s: %s", optionName, pattern, err),
+ Severity: hcl.DiagError,
+ })
+ }
+ globs = append(globs, g)
+ }
+
+ return globs, diags
+}
+
+func PrintableCtyValue(v cty.Value) string {
+ if !v.IsWhollyKnown() {
+ return "<unknown>"
+ }
+ gval := hcl2shim.ConfigValueFromHCL2(v)
+ str := repl.FormatResult(gval)
+ return str
+}
+
+func ConvertPluginConfigValueToHCLValue(v interface{}) (cty.Value, error) {
+ var buildValue cty.Value
+ switch v := v.(type) {
+ case bool:
+ buildValue = cty.BoolVal(v)
+ case string:
+ buildValue = cty.StringVal(v)
+ case uint8:
+ buildValue = cty.NumberUIntVal(uint64(v))
+ case float64:
+ buildValue = cty.NumberFloatVal(v)
+ case int64:
+ buildValue = cty.NumberIntVal(v)
+ case uint64:
+ buildValue = cty.NumberUIntVal(v)
+ case []string:
+ vals := make([]cty.Value, len(v))
+ for i, ev := range v {
+ vals[i] = cty.StringVal(ev)
+ }
+ if len(vals) == 0 {
+ buildValue = cty.ListValEmpty(cty.String)
+ } else {
+ buildValue = cty.ListVal(vals)
+ }
+ case []uint8:
+ vals := make([]cty.Value, len(v))
+ for i, ev := range v {
+ vals[i] = cty.NumberUIntVal(uint64(ev))
+ }
+ if len(vals) == 0 {
+ buildValue = cty.ListValEmpty(cty.Number)
+ } else {
+ buildValue = cty.ListVal(vals)
+ }
+ case []int64:
+ vals := make([]cty.Value, len(v))
+ for i, ev := range v {
+ vals[i] = cty.NumberIntVal(ev)
+ }
+ if len(vals) == 0 {
+ buildValue = cty.ListValEmpty(cty.Number)
+ } else {
+ buildValue = cty.ListVal(vals)
+ }
+ case []uint64:
+ vals := make([]cty.Value, len(v))
+ for i, ev := range v {
+ vals[i] = cty.NumberUIntVal(ev)
+ }
+ if len(vals) == 0 {
+ buildValue = cty.ListValEmpty(cty.Number)
+ } else {
+ buildValue = cty.ListVal(vals)
+ }
+ default:
+ return cty.Value{}, fmt.Errorf("unhandled buildvar type: %T", v)
+ }
+ return buildValue, nil
+}
diff --git a/v1.9.4/hcl2template/version.go b/v1.9.4/hcl2template/version.go
new file mode 100644
index 0000000..920cff5
--- /dev/null
+++ b/v1.9.4/hcl2template/version.go
@@ -0,0 +1,73 @@
+// Copyright (c) HashiCorp, Inc.
+// SPDX-License-Identifier: MPL-2.0
+
+package hcl2template
+
+import (
+ "fmt"
+
+ "github.com/hashicorp/go-version"
+ "github.com/hashicorp/hcl/v2"
+ "github.com/zclconf/go-cty/cty"
+ "github.com/zclconf/go-cty/cty/convert"
+)
+
+// VersionConstraint represents a version constraint on some resource that
+// carries with it a source range so that a helpful diagnostic can be printed
+// in the event that a particular constraint does not match.
+type VersionConstraint struct {
+ Required version.Constraints
+ DeclRange hcl.Range
+}
+
+func decodeVersionConstraint(attr *hcl.Attribute) (VersionConstraint, hcl.Diagnostics) {
+ ret := VersionConstraint{
+ DeclRange: attr.Range,
+ }
+
+ val, diags := attr.Expr.Value(nil)
+ if diags.HasErrors() {
+ return ret, diags
+ }
+ var err error
+ val, err = convert.Convert(val, cty.String)
+ if err != nil {
+ diags = append(diags, &hcl.Diagnostic{
+ Severity: hcl.DiagError,
+ Summary: "Invalid version constraint",
+ Detail: fmt.Sprintf("A string value is required for %s.", attr.Name),
+ Subject: attr.Expr.Range().Ptr(),
+ })
+ return ret, diags
+ }
+
+ if val.IsNull() {
+ // A null version constraint is strange, but we'll just treat it
+ // like an empty constraint set.
+ return ret, diags
+ }
+
+ if !val.IsWhollyKnown() {
+ // If there is a syntax error, HCL sets the value of the given attribute
+ // to cty.DynamicVal. A diagnostic for the syntax error will already
+ // bubble up, so we will move forward gracefully here.
+ return ret, diags
+ }
+
+ constraintStr := val.AsString()
+ constraints, err := version.NewConstraint(constraintStr)
+ if err != nil {
+ // NewConstraint doesn't return user-friendly errors, so we'll just
+ // ignore the provided error and produce our own generic one.
+ diags = append(diags, &hcl.Diagnostic{
+ Severity: hcl.DiagError,
+ Summary: "Invalid version constraint",
+ Detail: "This string does not use correct version constraint syntax. Check out the docs: https://packer.io/docs/templates/hcl_templates/blocks/packer#version-constraints",
+ Subject: attr.Expr.Range().Ptr(),
+ })
+ return ret, diags
+ }
+
+ ret.Required = constraints
+ return ret, diags
+}
diff --git a/v1.9.4/hcl2template/version_required.go b/v1.9.4/hcl2template/version_required.go
new file mode 100644
index 0000000..c418eda
--- /dev/null
+++ b/v1.9.4/hcl2template/version_required.go
@@ -0,0 +1,42 @@
+// Copyright (c) HashiCorp, Inc.
+// SPDX-License-Identifier: MPL-2.0
+
+package hcl2template
+
+import (
+ "fmt"
+
+ "github.com/hashicorp/go-version"
+ "github.com/hashicorp/hcl/v2"
+)
+
+// CheckCoreVersionRequirements visits each of the block in the given
+// configuration and verifies that any given Core version constraints match
+// with the version of Packer Core that is being used.
+//
+// The returned diagnostics will contain errors if any constraints do not match.
+// The returned diagnostics might also return warnings, which should be
+// displayed to the user.
+func (cfg *PackerConfig) CheckCoreVersionRequirements(coreVersion *version.Version) hcl.Diagnostics {
+ if cfg == nil {
+ return nil
+ }
+
+ var diags hcl.Diagnostics
+
+ for _, constraint := range cfg.Packer.VersionConstraints {
+ if !constraint.Required.Check(coreVersion) {
+ diags = diags.Append(&hcl.Diagnostic{
+ Severity: hcl.DiagError,
+ Summary: "Unsupported Packer Core version",
+ Detail: fmt.Sprintf(
+ "This configuration does not support Packer version %s. To proceed, either choose another supported Packer version or update this version constraint. Version constraints are normally set for good reason, so updating the constraint may lead to other errors or unexpected behavior.",
+ coreVersion.String(),
+ ),
+ Subject: constraint.DeclRange.Ptr(),
+ })
+ }
+ }
+
+ return diags
+}
diff --git a/v1.9.4/helper/wrappedreadline/wrappedreadline.go b/v1.9.4/helper/wrappedreadline/wrappedreadline.go
new file mode 100644
index 0000000..6641cb8
--- /dev/null
+++ b/v1.9.4/helper/wrappedreadline/wrappedreadline.go
@@ -0,0 +1,85 @@
+// Copyright (c) HashiCorp, Inc.
+// SPDX-License-Identifier: MPL-2.0
+
+// STOLEN SHAMELESSLY FROM THE TERRAFORM REPO BECAUSE VENDORING OUT
+// WRAPPEDREADLINE AND WRAPPEDSTREAMS FELT LIKE TOO MUCH WORK.
+//
+// "a little copying is better than a lot of dependency"
+//
+// wrappedreadline is a package that has helpers for interacting with
+// readline from a panicwrap executable.
+//
+// panicwrap overrides the standard file descriptors so that the child process
+// no longer looks like a TTY. The helpers here access the extra file descriptors
+// passed by panicwrap to fix that.
+//
+// panicwrap should be checked for with panicwrap.Wrapped before using this
+// librar, since this library won't adapt if the binary is not wrapped.
+package wrappedreadline
+
+import (
+ "runtime"
+
+ "github.com/chzyer/readline"
+
+ "github.com/hashicorp/packer/helper/wrappedstreams"
+)
+
+// Override overrides the values in readline.Config that need to be
+// set with wrapped values.
+func Override(cfg *readline.Config) *readline.Config {
+ cfg.Stdin = wrappedstreams.Stdin()
+ cfg.Stdout = wrappedstreams.Stdout()
+ cfg.Stderr = wrappedstreams.Stderr()
+
+ cfg.FuncGetWidth = TerminalWidth
+ cfg.FuncIsTerminal = IsTerminal
+
+ rm := RawMode{StdinFd: int(wrappedstreams.Stdin().Fd())}
+ cfg.FuncMakeRaw = rm.Enter
+ cfg.FuncExitRaw = rm.Exit
+
+ return cfg
+}
+
+// IsTerminal determines if this process is attached to a TTY.
+func IsTerminal() bool {
+ // Windows is always a terminal
+ if runtime.GOOS == "windows" {
+ return true
+ }
+
+ // Same implementation as readline but with our custom fds
+ return readline.IsTerminal(int(wrappedstreams.Stdin().Fd())) &&
+ (readline.IsTerminal(int(wrappedstreams.Stdout().Fd())) ||
+ readline.IsTerminal(int(wrappedstreams.Stderr().Fd())))
+}
+
+// TerminalWidth gets the terminal width in characters.
+func TerminalWidth() int {
+ if runtime.GOOS == "windows" {
+ return readline.GetScreenWidth()
+ }
+
+ return getWidth()
+}
+
+// RawMode is a helper for entering and exiting raw mode.
+type RawMode struct {
+ StdinFd int
+
+ state *readline.State
+}
+
+func (r *RawMode) Enter() (err error) {
+ r.state, err = readline.MakeRaw(r.StdinFd)
+ return err
+}
+
+func (r *RawMode) Exit() error {
+ if r.state == nil {
+ return nil
+ }
+
+ return readline.Restore(r.StdinFd, r.state)
+}
diff --git a/v1.9.4/helper/wrappedreadline/wrappedreadline_solaris.go b/v1.9.4/helper/wrappedreadline/wrappedreadline_solaris.go
new file mode 100644
index 0000000..fb2a938
--- /dev/null
+++ b/v1.9.4/helper/wrappedreadline/wrappedreadline_solaris.go
@@ -0,0 +1,14 @@
+// Copyright (c) HashiCorp, Inc.
+// SPDX-License-Identifier: MPL-2.0
+
+package wrappedreadline
+
+// getWidth impl for Solaris
+func getWidth() int {
+ return 80
+}
+
+// get width of the terminal
+func getWidthFd(stdoutFd int) int {
+ return getWidth()
+}
diff --git a/v1.9.4/helper/wrappedreadline/wrappedreadline_unix.go b/v1.9.4/helper/wrappedreadline/wrappedreadline_unix.go
new file mode 100644
index 0000000..ff621e7
--- /dev/null
+++ b/v1.9.4/helper/wrappedreadline/wrappedreadline_unix.go
@@ -0,0 +1,50 @@
+// Copyright (c) HashiCorp, Inc.
+// SPDX-License-Identifier: MPL-2.0
+
+//go:build darwin || dragonfly || freebsd || (linux && !appengine) || netbsd || openbsd
+// +build darwin dragonfly freebsd linux,!appengine netbsd openbsd
+
+package wrappedreadline
+
+import (
+ "syscall"
+ "unsafe"
+
+ "github.com/hashicorp/packer/helper/wrappedstreams"
+)
+
+// getWidth impl for Unix
+func getWidth() int {
+ stdoutFd := int(wrappedstreams.Stdout().Fd())
+ stderrFd := int(wrappedstreams.Stderr().Fd())
+
+ w := getWidthFd(stdoutFd)
+ if w < 0 {
+ w = getWidthFd(stderrFd)
+ }
+
+ return w
+}
+
+type winsize struct {
+ Row uint16
+ Col uint16
+ Xpixel uint16
+ Ypixel uint16
+}
+
+// get width of the terminal
+func getWidthFd(stdoutFd int) int {
+ ws := &winsize{}
+ retCode, _, errno := syscall.Syscall(syscall.SYS_IOCTL,
+ uintptr(stdoutFd),
+ uintptr(syscall.TIOCGWINSZ),
+ uintptr(unsafe.Pointer(ws)))
+
+ if int(retCode) == -1 {
+ _ = errno
+ return -1
+ }
+
+ return int(ws.Col)
+}
diff --git a/v1.9.4/helper/wrappedreadline/wrappedreadline_windows.go b/v1.9.4/helper/wrappedreadline/wrappedreadline_windows.go
new file mode 100644
index 0000000..d3d3615
--- /dev/null
+++ b/v1.9.4/helper/wrappedreadline/wrappedreadline_windows.go
@@ -0,0 +1,12 @@
+// Copyright (c) HashiCorp, Inc.
+// SPDX-License-Identifier: MPL-2.0
+
+//go:build windows
+// +build windows
+
+package wrappedreadline
+
+// getWidth impl for other
+func getWidth() int {
+ return 0
+}
diff --git a/v1.9.4/helper/wrappedstreams/streams.go b/v1.9.4/helper/wrappedstreams/streams.go
new file mode 100644
index 0000000..80d1e66
--- /dev/null
+++ b/v1.9.4/helper/wrappedstreams/streams.go
@@ -0,0 +1,52 @@
+// Copyright (c) HashiCorp, Inc.
+// SPDX-License-Identifier: MPL-2.0
+
+// STOLEN SHAMELESSLY FROM THE TERRAFORM REPO BECAUSE VENDORING OUT
+// WRAPPEDREADLINE AND WRAPPEDSTREAMS FELT LIKE TOO MUCH WORK.
+//
+// "a little copying is better than a lot of dependency"
+//
+// Package wrappedstreams provides access to the standard OS streams
+// (stdin, stdout, stderr) even if wrapped under panicwrap.
+package wrappedstreams
+
+import (
+ "os"
+
+ "github.com/mitchellh/panicwrap"
+)
+
+// Stdin returns the true stdin of the process.
+func Stdin() *os.File {
+ stdin, _, _ := fds()
+ return stdin
+}
+
+// Stdout returns the true stdout of the process.
+func Stdout() *os.File {
+ _, stdout, _ := fds()
+ return stdout
+}
+
+// Stderr returns the true stderr of the process.
+func Stderr() *os.File {
+ _, _, stderr := fds()
+ return stderr
+}
+
+func fds() (stdin, stdout, stderr *os.File) {
+ stdin, stdout, stderr = os.Stdin, os.Stdout, os.Stderr
+ if panicwrap.Wrapped(nil) {
+ initPlatform()
+ stdin, stdout, stderr = wrappedStdin, wrappedStdout, wrappedStderr
+ }
+ return
+}
+
+// These are the wrapped standard streams. These are setup by the
+// platform specific code in initPlatform.
+var (
+ wrappedStdin *os.File
+ wrappedStdout *os.File
+ wrappedStderr *os.File
+)
diff --git a/v1.9.4/helper/wrappedstreams/streams_other.go b/v1.9.4/helper/wrappedstreams/streams_other.go
new file mode 100644
index 0000000..34ecf76
--- /dev/null
+++ b/v1.9.4/helper/wrappedstreams/streams_other.go
@@ -0,0 +1,25 @@
+// Copyright (c) HashiCorp, Inc.
+// SPDX-License-Identifier: MPL-2.0
+
+//go:build !windows
+// +build !windows
+
+package wrappedstreams
+
+import (
+ "os"
+ "sync"
+)
+
+var initOnce sync.Once
+
+func initPlatform() {
+ // These must be initialized lazily, once it's been determined that this is
+ // a wrapped process.
+ initOnce.Do(func() {
+ // The standard streams are passed in via extra file descriptors.
+ wrappedStdin = os.NewFile(uintptr(3), "stdin")
+ wrappedStdout = os.NewFile(uintptr(4), "stdout")
+ wrappedStderr = os.NewFile(uintptr(5), "stderr")
+ })
+}
diff --git a/v1.9.4/helper/wrappedstreams/streams_windows.go b/v1.9.4/helper/wrappedstreams/streams_windows.go
new file mode 100644
index 0000000..18489fd
--- /dev/null
+++ b/v1.9.4/helper/wrappedstreams/streams_windows.go
@@ -0,0 +1,56 @@
+// Copyright (c) HashiCorp, Inc.
+// SPDX-License-Identifier: MPL-2.0
+
+//go:build windows
+// +build windows
+
+package wrappedstreams
+
+import (
+ "log"
+ "os"
+ "syscall"
+)
+
+func initPlatform() {
+ wrappedStdin = openConsole("CONIN$", os.Stdin)
+ wrappedStdout = openConsole("CONOUT$", os.Stdout)
+ wrappedStderr = wrappedStdout
+}
+
+// openConsole opens a console handle, using a backup if it fails.
+// This is used to get the exact console handle instead of the redirected
+// handles from panicwrap.
+func openConsole(name string, backup *os.File) *os.File {
+ // Convert to UTF16
+ path, err := syscall.UTF16PtrFromString(name)
+ if err != nil {
+ log.Printf("[ERROR] wrappedstreams: %s", err)
+ return backup
+ }
+
+ // Determine the share mode
+ var shareMode uint32
+ switch name {
+ case "CONIN$":
+ shareMode = syscall.FILE_SHARE_READ
+ case "CONOUT$":
+ shareMode = syscall.FILE_SHARE_WRITE
+ }
+
+ // Get the file
+ h, err := syscall.CreateFile(
+ path,
+ syscall.GENERIC_READ|syscall.GENERIC_WRITE,
+ shareMode,
+ nil,
+ syscall.OPEN_EXISTING,
+ 0, 0)
+ if err != nil {
+ log.Printf("[ERROR] wrappedstreams: %s", err)
+ return backup
+ }
+
+ // Create the Go file
+ return os.NewFile(uintptr(h), name)
+}
diff --git a/v1.9.4/internal/hcp/api/client.go b/v1.9.4/internal/hcp/api/client.go
new file mode 100644
index 0000000..f28999d
--- /dev/null
+++ b/v1.9.4/internal/hcp/api/client.go
@@ -0,0 +1,204 @@
+// Copyright (c) HashiCorp, Inc.
+// SPDX-License-Identifier: MPL-2.0
+
+// Package api provides access to the HCP Packer Registry API.
+package api
+
+import (
+ "fmt"
+ "log"
+ "net/http"
+ "os"
+ "time"
+
+ "github.com/hashicorp/hcp-sdk-go/clients/cloud-packer-service/stable/2021-04-30/client/packer_service"
+ packerSvc "github.com/hashicorp/hcp-sdk-go/clients/cloud-packer-service/stable/2021-04-30/client/packer_service"
+ organizationSvc "github.com/hashicorp/hcp-sdk-go/clients/cloud-resource-manager/preview/2019-12-10/client/organization_service"
+ projectSvc "github.com/hashicorp/hcp-sdk-go/clients/cloud-resource-manager/preview/2019-12-10/client/project_service"
+ "github.com/hashicorp/hcp-sdk-go/clients/cloud-resource-manager/preview/2019-12-10/models"
+ rmmodels "github.com/hashicorp/hcp-sdk-go/clients/cloud-resource-manager/preview/2019-12-10/models"
+ "github.com/hashicorp/hcp-sdk-go/httpclient"
+ "github.com/hashicorp/packer/internal/hcp/env"
+ "github.com/hashicorp/packer/version"
+)
+
+// Client is an HCP client capable of making requests on behalf of a service principal
+type Client struct {
+ Packer packerSvc.ClientService
+ Organization organizationSvc.ClientService
+ Project projectSvc.ClientService
+
+ // OrganizationID is the organization unique identifier on HCP.
+ OrganizationID string
+
+ // ProjectID is the project unique identifier on HCP.
+ ProjectID string
+}
+
+// NewClient returns an authenticated client to a HCP Packer Registry.
+// Client authentication requires the following environment variables be set HCP_CLIENT_ID and HCP_CLIENT_SECRET.
+// Upon error a HCPClientError will be returned.
+func NewClient() (*Client, error) {
+ if !env.HasHCPCredentials() {
+ return nil, &ClientError{
+ StatusCode: InvalidClientConfig,
+ Err: fmt.Errorf("the client authentication requires both %s and %s environment variables to be set", env.HCPClientID, env.HCPClientSecret),
+ }
+ }
+
+ hcpClientCfg := httpclient.Config{
+ SourceChannel: fmt.Sprintf("packer/%s", version.PackerVersion.FormattedVersion()),
+ }
+ if err := hcpClientCfg.Canonicalize(); err != nil {
+ return nil, &ClientError{
+ StatusCode: InvalidClientConfig,
+ Err: err,
+ }
+ }
+
+ cl, err := httpclient.New(hcpClientCfg)
+ if err != nil {
+ return nil, &ClientError{
+ StatusCode: InvalidClientConfig,
+ Err: err,
+ }
+ }
+ client := &Client{
+ Packer: packerSvc.New(cl, nil),
+ Organization: organizationSvc.New(cl, nil),
+ Project: projectSvc.New(cl, nil),
+ }
+ // A client.Config.hcpConfig is set when calling Canonicalize on basic HCP httpclient, as on line 52.
+ // If a user sets HCP_* env. variables they will be loaded into the client via the SDK and used for any client calls.
+ // For HCP_ORGANIZATION_ID and HCP_PROJECT_ID if they are both set via env. variables the call to hcpClientCfg.Connicalize()
+ // will automatically loaded them using the FromEnv configOption.
+ //
+ // If both values are set we should have all that we need to continue so we can returned the configured client.
+ if hcpClientCfg.Profile().OrganizationID != "" && hcpClientCfg.Profile().ProjectID != "" {
+ client.OrganizationID = hcpClientCfg.Profile().OrganizationID
+ client.ProjectID = hcpClientCfg.Profile().ProjectID
+
+ return client, nil
+ }
+
+ if client.OrganizationID == "" {
+ err := client.loadOrganizationID()
+ if err != nil {
+ return nil, &ClientError{
+ StatusCode: InvalidClientConfig,
+ Err: err,
+ }
+ }
+ }
+
+ if client.ProjectID == "" {
+ err := client.loadProjectID()
+ if err != nil {
+ return nil, &ClientError{
+ StatusCode: InvalidClientConfig,
+ Err: err,
+ }
+ }
+ }
+
+ return client, nil
+}
+
+func (c *Client) loadOrganizationID() error {
+ if env.HasOrganizationID() {
+ c.OrganizationID = os.Getenv(env.HCPOrganizationID)
+ return nil
+ }
+ // Get the organization ID.
+ listOrgParams := organizationSvc.NewOrganizationServiceListParams()
+ listOrgResp, err := c.Organization.OrganizationServiceList(listOrgParams, nil)
+ if err != nil {
+ return fmt.Errorf("unable to fetch organization list: %v", err)
+ }
+ orgLen := len(listOrgResp.Payload.Organizations)
+ if orgLen != 1 {
+ return fmt.Errorf("unexpected number of organizations: expected 1, actual: %v", orgLen)
+ }
+ c.OrganizationID = listOrgResp.Payload.Organizations[0].ID
+ return nil
+}
+
+func (c *Client) loadProjectID() error {
+ if env.HasProjectID() {
+ c.ProjectID = os.Getenv(env.HCPProjectID)
+ err := c.ValidateRegistryForProject()
+ if err != nil {
+ return fmt.Errorf("project validation for id %q responded in error: %v", c.ProjectID, err)
+ }
+ return nil
+ }
+ // Get the project using the organization ID.
+ listProjParams := projectSvc.NewProjectServiceListParams()
+ listProjParams.ScopeID = &c.OrganizationID
+ scopeType := string(rmmodels.HashicorpCloudResourcemanagerResourceIDResourceTypeORGANIZATION)
+ listProjParams.ScopeType = &scopeType
+ listProjResp, err := c.Project.ProjectServiceList(listProjParams, nil)
+
+ if err != nil {
+ //For permission errors, our service principal may not have the ability
+ // to see all projects for an Org; this is the case for project-level service principals.
+ serviceErr, ok := err.(*projectSvc.ProjectServiceListDefault)
+ if !ok {
+ return fmt.Errorf("unable to fetch project list: %v", err)
+ }
+ if serviceErr.Code() == http.StatusForbidden {
+ return fmt.Errorf("unable to fetch project\n\n"+
+ "If the provided credentials are tied to a specific project try setting the %s environment variable to one you want to use.", env.HCPProjectID)
+ }
+ }
+
+ if len(listProjResp.Payload.Projects) > 1 {
+ log.Printf("[WARNING] Multiple HCP projects found, will pick the oldest one by default\n"+
+ "To specify which project to use, set the %s environment variable to the one you want to use.", env.HCPProjectID)
+ }
+
+ proj, err := getOldestProject(listProjResp.Payload.Projects)
+ if err != nil {
+ return err
+ }
+ c.ProjectID = proj.ID
+ return nil
+}
+
+// getOldestProject retrieves the oldest project from a list based on its created_at time.
+func getOldestProject(projects []*models.HashicorpCloudResourcemanagerProject) (*models.HashicorpCloudResourcemanagerProject, error) {
+ if len(projects) == 0 {
+ return nil, fmt.Errorf("no project found")
+ }
+
+ oldestTime := time.Now()
+ var oldestProj *models.HashicorpCloudResourcemanagerProject
+ for _, proj := range projects {
+ projTime := time.Time(proj.CreatedAt)
+ if projTime.Before(oldestTime) {
+ oldestProj = proj
+ oldestTime = projTime
+ }
+ }
+ return oldestProj, nil
+}
+
+// ValidateRegistryForProject validates that there is an active registry associated to the configured organization and project ids.
+// A successful validation will result in a nil response. All other response represent an invalid registry error request or a registry not found error.
+func (client *Client) ValidateRegistryForProject() error {
+ params := packer_service.NewPackerServiceGetRegistryParams()
+ params.LocationOrganizationID = client.OrganizationID
+ params.LocationProjectID = client.ProjectID
+
+ resp, err := client.Packer.PackerServiceGetRegistry(params, nil)
+ if err != nil {
+ return err
+ }
+
+ if resp.GetPayload().Registry == nil {
+ return fmt.Errorf("No active HCP Packer registry was found for the organization %q and project %q", client.OrganizationID, client.ProjectID)
+ }
+
+ return nil
+
+}
diff --git a/v1.9.4/internal/hcp/api/client_test.go b/v1.9.4/internal/hcp/api/client_test.go
new file mode 100644
index 0000000..16d321b
--- /dev/null
+++ b/v1.9.4/internal/hcp/api/client_test.go
@@ -0,0 +1,83 @@
+// Copyright (c) HashiCorp, Inc.
+// SPDX-License-Identifier: MPL-2.0
+
+package api
+
+import (
+ "testing"
+ "time"
+
+ "github.com/go-openapi/strfmt"
+ "github.com/hashicorp/hcp-sdk-go/clients/cloud-resource-manager/preview/2019-12-10/models"
+)
+
+func TestGetOldestProject(t *testing.T) {
+ testcases := []struct {
+ Name string
+ ProjectList []*models.HashicorpCloudResourcemanagerProject
+ ExpectProjectID string
+ ExpectErr bool
+ }{
+ {
+ "Only one project, project exists, success",
+ []*models.HashicorpCloudResourcemanagerProject{
+ {
+ ID: "test-project-exists",
+ },
+ },
+ "test-project-exists",
+ false,
+ },
+ {
+ "Multiple projects, pick the oldest",
+ []*models.HashicorpCloudResourcemanagerProject{
+ {
+ ID: "test-project-exists",
+ CreatedAt: strfmt.DateTime(time.Date(2023, 1, 1, 1, 0, 0, 0, time.UTC)),
+ },
+ {
+ ID: "test-oldest-project",
+ CreatedAt: strfmt.DateTime(time.Date(2022, 1, 1, 1, 0, 0, 0, time.UTC)),
+ },
+ },
+ "test-oldest-project",
+ false,
+ },
+ {
+ "Multiple projects, different order, pick the oldest",
+ []*models.HashicorpCloudResourcemanagerProject{
+ {
+ ID: "test-oldest-project",
+ CreatedAt: strfmt.DateTime(time.Date(2022, 1, 1, 1, 0, 0, 0, time.UTC)),
+ },
+ {
+ ID: "test-project-exists",
+ CreatedAt: strfmt.DateTime(time.Date(2023, 1, 1, 1, 0, 0, 0, time.UTC)),
+ },
+ },
+ "test-oldest-project",
+ false,
+ },
+ {
+ "No projects, should error",
+ []*models.HashicorpCloudResourcemanagerProject{},
+ "",
+ true,
+ },
+ }
+
+ for _, tt := range testcases {
+ t.Run(tt.Name, func(t *testing.T) {
+ proj, err := getOldestProject(tt.ProjectList)
+ if (err != nil) != tt.ExpectErr {
+ t.Errorf("test findProjectByID, expected %t, got %t",
+ tt.ExpectErr,
+ err != nil)
+ }
+
+ if proj != nil && proj.ID != tt.ExpectProjectID {
+ t.Errorf("expected to select project %q, got %q", tt.ExpectProjectID, proj.ID)
+ }
+ })
+ }
+}
diff --git a/v1.9.4/internal/hcp/api/errors.go b/v1.9.4/internal/hcp/api/errors.go
new file mode 100644
index 0000000..32a5708
--- /dev/null
+++ b/v1.9.4/internal/hcp/api/errors.go
@@ -0,0 +1,39 @@
+// Copyright (c) HashiCorp, Inc.
+// SPDX-License-Identifier: MPL-2.0
+
+package api
+
+import (
+ "fmt"
+ "strings"
+
+ "google.golang.org/grpc/codes"
+)
+
+const (
+ _ = iota
+ InvalidClientConfig
+)
+
+// ClientError represents a generic error for the Cloud Packer Service client.
+type ClientError struct {
+ StatusCode uint
+ Err error
+}
+
+// Error returns the string message for some ClientError.
+func (c *ClientError) Error() string {
+ return fmt.Sprintf("status %d: err %v", c.StatusCode, c.Err)
+}
+
+// CheckErrorCode checks the error string for err for some code and returns true
+// if the code is found. Ideally this function should use status.FromError
+// https://pkg.go.dev/google.golang.org/grpc/status#pkg-functions but that
+// doesn't appear to work for all of the Cloud Packer Service response errors.
+func CheckErrorCode(err error, code codes.Code) bool {
+ if err == nil {
+ return false
+ }
+
+ return strings.Contains(err.Error(), fmt.Sprintf("Code:%d", code))
+}
diff --git a/v1.9.4/internal/hcp/api/mock_service.go b/v1.9.4/internal/hcp/api/mock_service.go
new file mode 100644
index 0000000..9a12634
--- /dev/null
+++ b/v1.9.4/internal/hcp/api/mock_service.go
@@ -0,0 +1,258 @@
+// Copyright (c) HashiCorp, Inc.
+// SPDX-License-Identifier: MPL-2.0
+
+package api
+
+import (
+ "errors"
+ "fmt"
+ "strconv"
+
+ "github.com/go-openapi/runtime"
+ "github.com/hashicorp/hcp-sdk-go/clients/cloud-packer-service/stable/2021-04-30/client/packer_service"
+ packerSvc "github.com/hashicorp/hcp-sdk-go/clients/cloud-packer-service/stable/2021-04-30/client/packer_service"
+ "github.com/hashicorp/hcp-sdk-go/clients/cloud-packer-service/stable/2021-04-30/models"
+ "google.golang.org/grpc/codes"
+ "google.golang.org/grpc/status"
+)
+
+// MockPackerClientService represents a basic mock of the Cloud Packer Service.
+// Upon calling a service method a boolean is set to true to indicate that a method has been called.
+// To skip the setting of these booleans set TrackCalledServiceMethods to false; defaults to true in NewMockPackerClientService().
+type MockPackerClientService struct {
+ CreateBucketCalled, UpdateBucketCalled, BucketAlreadyExist bool
+ CreateIterationCalled, GetIterationCalled, IterationAlreadyExist, IterationCompleted bool
+ CreateBuildCalled, UpdateBuildCalled, ListBuildsCalled, BuildAlreadyDone bool
+ TrackCalledServiceMethods bool
+
+ // Mock Creates
+ CreateBucketResp *models.HashicorpCloudPackerCreateBucketResponse
+ CreateIterationResp *models.HashicorpCloudPackerCreateIterationResponse
+ CreateBuildResp *models.HashicorpCloudPackerCreateBuildResponse
+
+ // Mock Gets
+ GetIterationResp *models.HashicorpCloudPackerGetIterationResponse
+
+ ExistingBuilds []string
+ ExistingBuildLabels map[string]string
+
+ packerSvc.ClientService
+}
+
+// NewMockPackerClientService returns a basic mock of the Cloud Packer Service.
+// Upon calling a service method a boolean is set to true to indicate that a method has been called.
+// To skip the setting of these booleans set TrackCalledServiceMethods to false. By default it is true.
+func NewMockPackerClientService() *MockPackerClientService {
+ m := MockPackerClientService{
+ ExistingBuilds: make([]string, 0),
+ ExistingBuildLabels: make(map[string]string),
+ TrackCalledServiceMethods: true,
+ }
+
+ return &m
+}
+
+func (svc *MockPackerClientService) PackerServiceCreateBucket(params *packerSvc.PackerServiceCreateBucketParams, _ runtime.ClientAuthInfoWriter, opts ...packer_service.ClientOption) (*packerSvc.PackerServiceCreateBucketOK, error) {
+
+ if svc.BucketAlreadyExist {
+ return nil, status.Error(codes.AlreadyExists, fmt.Sprintf("Code:%d %s", codes.AlreadyExists, codes.AlreadyExists.String()))
+ }
+
+ if params.Body.BucketSlug == "" {
+ return nil, errors.New("No bucket slug was passed in")
+ }
+
+ if svc.TrackCalledServiceMethods {
+ svc.CreateBucketCalled = true
+ }
+ payload := &models.HashicorpCloudPackerCreateBucketResponse{
+ Bucket: &models.HashicorpCloudPackerBucket{
+ ID: "bucket-id",
+ },
+ }
+ payload.Bucket.Slug = params.Body.BucketSlug
+
+ ok := &packerSvc.PackerServiceCreateBucketOK{
+ Payload: payload,
+ }
+
+ return ok, nil
+}
+
+func (svc *MockPackerClientService) PackerServiceUpdateBucket(params *packerSvc.PackerServiceUpdateBucketParams, _ runtime.ClientAuthInfoWriter, opts ...packer_service.ClientOption) (*packerSvc.PackerServiceUpdateBucketOK, error) {
+ if svc.TrackCalledServiceMethods {
+ svc.UpdateBucketCalled = true
+ }
+
+ return packerSvc.NewPackerServiceUpdateBucketOK(), nil
+}
+
+func (svc *MockPackerClientService) PackerServiceCreateIteration(params *packerSvc.PackerServiceCreateIterationParams, _ runtime.ClientAuthInfoWriter, opts ...packer_service.ClientOption) (*packerSvc.PackerServiceCreateIterationOK, error) {
+ if svc.IterationAlreadyExist {
+ return nil, status.Error(codes.AlreadyExists, fmt.Sprintf("Code:%d %s", codes.AlreadyExists, codes.AlreadyExists.String()))
+ }
+
+ if params.Body.Fingerprint == "" {
+ return nil, errors.New("No valid Fingerprint was passed in")
+ }
+
+ if svc.TrackCalledServiceMethods {
+ svc.CreateIterationCalled = true
+ }
+ payload := &models.HashicorpCloudPackerCreateIterationResponse{
+ Iteration: &models.HashicorpCloudPackerIteration{
+ ID: "iteration-id",
+ TemplateType: params.Body.TemplateType,
+ },
+ }
+
+ payload.Iteration.BucketSlug = params.BucketSlug
+ payload.Iteration.Fingerprint = params.Body.Fingerprint
+
+ ok := &packerSvc.PackerServiceCreateIterationOK{
+ Payload: payload,
+ }
+
+ return ok, nil
+}
+
+func (svc *MockPackerClientService) PackerServiceGetIteration(params *packerSvc.PackerServiceGetIterationParams, _ runtime.ClientAuthInfoWriter, opts ...packer_service.ClientOption) (*packerSvc.PackerServiceGetIterationOK, error) {
+ if !svc.IterationAlreadyExist {
+ return nil, status.Error(codes.AlreadyExists, fmt.Sprintf("Code:%d %s", codes.Aborted, codes.Aborted.String()))
+ }
+
+ if params.BucketSlug == "" {
+ return nil, errors.New("No valid BucketSlug was passed in")
+ }
+
+ if params.Fingerprint == nil {
+ return nil, errors.New("No valid Fingerprint was passed in")
+ }
+
+ if svc.TrackCalledServiceMethods {
+ svc.GetIterationCalled = true
+ }
+
+ payload := &models.HashicorpCloudPackerGetIterationResponse{
+ Iteration: &models.HashicorpCloudPackerIteration{
+ ID: "iteration-id",
+ Builds: make([]*models.HashicorpCloudPackerBuild, 0),
+ TemplateType: models.HashicorpCloudPackerIterationTemplateTypeTEMPLATETYPEUNSET.Pointer(),
+ },
+ }
+
+ payload.Iteration.BucketSlug = params.BucketSlug
+ payload.Iteration.Fingerprint = *params.Fingerprint
+ ok := &packerSvc.PackerServiceGetIterationOK{
+ Payload: payload,
+ }
+
+ if svc.IterationCompleted {
+ ok.Payload.Iteration.Complete = true
+ ok.Payload.Iteration.IncrementalVersion = 1
+ ok.Payload.Iteration.Builds = append(ok.Payload.Iteration.Builds, &models.HashicorpCloudPackerBuild{
+ ID: "build-id",
+ ComponentType: svc.ExistingBuilds[0],
+ Status: models.HashicorpCloudPackerBuildStatusDONE.Pointer(),
+ Images: []*models.HashicorpCloudPackerImage{
+ {ImageID: "image-id", Region: "somewhere"},
+ },
+ Labels: make(map[string]string),
+ })
+ }
+
+ return ok, nil
+}
+
+func (svc *MockPackerClientService) PackerServiceCreateBuild(params *packerSvc.PackerServiceCreateBuildParams, _ runtime.ClientAuthInfoWriter, opts ...packer_service.ClientOption) (*packerSvc.PackerServiceCreateBuildOK, error) {
+ if params.BucketSlug == "" {
+ return nil, errors.New("No valid BucketSlug was passed in")
+ }
+
+ if params.Body.Fingerprint == "" {
+ return nil, errors.New("No valid Fingerprint was passed in")
+ }
+
+ if params.Body.Build.ComponentType == "" {
+ return nil, errors.New("No build componentType was passed in")
+ }
+
+ if svc.TrackCalledServiceMethods {
+ svc.CreateBuildCalled = true
+ }
+
+ payload := &models.HashicorpCloudPackerCreateBuildResponse{
+ Build: &models.HashicorpCloudPackerBuild{
+ PackerRunUUID: "test-uuid",
+ Status: models.HashicorpCloudPackerBuildStatusUNSET.Pointer(),
+ },
+ }
+
+ payload.Build.ComponentType = params.Body.Build.ComponentType
+ payload.Build.IterationID = params.IterationID
+
+ ok := packerSvc.NewPackerServiceCreateBuildOK()
+ ok.Payload = payload
+
+ return ok, nil
+}
+
+func (svc *MockPackerClientService) PackerServiceUpdateBuild(params *packerSvc.PackerServiceUpdateBuildParams, _ runtime.ClientAuthInfoWriter, opts ...packer_service.ClientOption) (*packerSvc.PackerServiceUpdateBuildOK, error) {
+ if params.BuildID == "" {
+ return nil, errors.New("No valid BuildID was passed in")
+ }
+
+ if params.Body.Updates == nil {
+ return nil, errors.New("No valid Updates were passed in")
+ }
+
+ if params.Body.Updates.Status == nil || *params.Body.Updates.Status == "" {
+ return nil, errors.New("No build status was passed in")
+ }
+
+ if svc.TrackCalledServiceMethods {
+ svc.UpdateBuildCalled = true
+ }
+
+ ok := packerSvc.NewPackerServiceUpdateBuildOK()
+ ok.Payload = &models.HashicorpCloudPackerUpdateBuildResponse{
+ Build: &models.HashicorpCloudPackerBuild{
+ ID: params.BuildID,
+ },
+ }
+ return ok, nil
+}
+
+func (svc *MockPackerClientService) PackerServiceListBuilds(params *packerSvc.PackerServiceListBuildsParams, _ runtime.ClientAuthInfoWriter, opts ...packer_service.ClientOption) (*packerSvc.PackerServiceListBuildsOK, error) {
+
+ status := models.HashicorpCloudPackerBuildStatusUNSET
+ images := make([]*models.HashicorpCloudPackerImage, 0)
+ labels := make(map[string]string)
+ if svc.BuildAlreadyDone {
+ status = models.HashicorpCloudPackerBuildStatusDONE
+ images = append(images, &models.HashicorpCloudPackerImage{ImageID: "image-id", Region: "somewhere"})
+ }
+
+ for k, v := range svc.ExistingBuildLabels {
+ labels[k] = v
+ }
+
+ builds := make([]*models.HashicorpCloudPackerBuild, 0, len(svc.ExistingBuilds))
+ for i, name := range svc.ExistingBuilds {
+ builds = append(builds, &models.HashicorpCloudPackerBuild{
+ ID: name + "--" + strconv.Itoa(i),
+ ComponentType: name,
+ CloudProvider: "mockProvider",
+ Status: status.Pointer(),
+ Images: images,
+ Labels: labels,
+ })
+ }
+
+ ok := packerSvc.NewPackerServiceListBuildsOK()
+ ok.Payload = &models.HashicorpCloudPackerListBuildsResponse{
+ Builds: builds,
+ }
+
+ return ok, nil
+}
diff --git a/v1.9.4/internal/hcp/api/service.go b/v1.9.4/internal/hcp/api/service.go
new file mode 100644
index 0000000..a0ee9f8
--- /dev/null
+++ b/v1.9.4/internal/hcp/api/service.go
@@ -0,0 +1,253 @@
+// Copyright (c) HashiCorp, Inc.
+// SPDX-License-Identifier: MPL-2.0
+
+package api
+
+import (
+ "context"
+ "errors"
+ "fmt"
+
+ "github.com/hashicorp/hcp-sdk-go/clients/cloud-packer-service/stable/2021-04-30/client/packer_service"
+ "github.com/hashicorp/hcp-sdk-go/clients/cloud-packer-service/stable/2021-04-30/models"
+ "google.golang.org/grpc/codes"
+)
+
+func (client *Client) CreateBucket(
+ ctx context.Context,
+ bucketSlug,
+ bucketDescription string,
+ bucketLabels map[string]string,
+) (*packer_service.PackerServiceCreateBucketOK, error) {
+
+ createBktParams := packer_service.NewPackerServiceCreateBucketParams()
+ createBktParams.LocationOrganizationID = client.OrganizationID
+ createBktParams.LocationProjectID = client.ProjectID
+ createBktParams.Body = packer_service.PackerServiceCreateBucketBody{
+ BucketSlug: bucketSlug,
+ Description: bucketDescription,
+ Labels: bucketLabels,
+ }
+
+ return client.Packer.PackerServiceCreateBucket(createBktParams, nil)
+}
+
+func (client *Client) DeleteBucket(
+ ctx context.Context,
+ bucketSlug string,
+) (*packer_service.PackerServiceDeleteBucketOK, error) {
+
+ deleteBktParams := packer_service.NewPackerServiceDeleteBucketParamsWithContext(ctx)
+ deleteBktParams.LocationOrganizationID = client.OrganizationID
+ deleteBktParams.LocationProjectID = client.ProjectID
+ deleteBktParams.BucketSlug = bucketSlug
+
+ return client.Packer.PackerServiceDeleteBucket(deleteBktParams, nil)
+}
+
+// UpsertBucket tries to create a bucket on a HCP Packer Registry. If the bucket
+// exists it will handle the error and update the bucket with the provided
+// details.
+func (client *Client) UpsertBucket(
+ ctx context.Context,
+ bucketSlug,
+ bucketDescription string,
+ bucketLabels map[string]string,
+) error {
+
+ // Create bucket if exist we continue as is, eventually we want to treat
+ // this like an upsert
+ _, err := client.CreateBucket(ctx, bucketSlug, bucketDescription, bucketLabels)
+ if err != nil && !CheckErrorCode(err, codes.AlreadyExists) {
+ return err
+ }
+
+ if err == nil {
+ return nil
+ }
+
+ params := packer_service.NewPackerServiceUpdateBucketParamsWithContext(ctx)
+ params.LocationOrganizationID = client.OrganizationID
+ params.LocationProjectID = client.ProjectID
+ params.BucketSlug = bucketSlug
+ params.Body = packer_service.PackerServiceUpdateBucketBody{
+ Description: bucketDescription,
+ Labels: bucketLabels,
+ }
+ _, err = client.Packer.PackerServiceUpdateBucket(params, nil)
+
+ return err
+}
+
+func (client *Client) CreateIteration(
+ ctx context.Context,
+ bucketSlug,
+ fingerprint string,
+ templateType models.HashicorpCloudPackerIterationTemplateType,
+) (*packer_service.PackerServiceCreateIterationOK, error) {
+
+ params := packer_service.NewPackerServiceCreateIterationParamsWithContext(ctx)
+ params.LocationOrganizationID = client.OrganizationID
+ params.LocationProjectID = client.ProjectID
+ params.BucketSlug = bucketSlug
+ params.Body = packer_service.PackerServiceCreateIterationBody{
+ Fingerprint: fingerprint,
+ TemplateType: templateType.Pointer(),
+ }
+
+ return client.Packer.PackerServiceCreateIteration(params, nil)
+}
+
+type GetIterationOption func(*packer_service.PackerServiceGetIterationParams)
+
+var (
+ GetIteration_byID = func(id string) GetIterationOption {
+ return func(params *packer_service.PackerServiceGetIterationParams) {
+ params.IterationID = &id
+ }
+ }
+ GetIteration_byFingerprint = func(fingerprint string) GetIterationOption {
+ return func(params *packer_service.PackerServiceGetIterationParams) {
+ params.Fingerprint = &fingerprint
+ }
+ }
+)
+
+func (client *Client) GetIteration(ctx context.Context, bucketSlug string, opts ...GetIterationOption) (*models.HashicorpCloudPackerIteration, error) {
+ getItParams := packer_service.NewPackerServiceGetIterationParams()
+ getItParams.LocationOrganizationID = client.OrganizationID
+ getItParams.LocationProjectID = client.ProjectID
+ getItParams.BucketSlug = bucketSlug
+
+ for _, opt := range opts {
+ opt(getItParams)
+ }
+
+ resp, err := client.Packer.PackerServiceGetIteration(getItParams, nil)
+ if err != nil {
+ return nil, err
+ }
+
+ if resp.Payload.Iteration != nil {
+ return resp.Payload.Iteration, nil
+ }
+
+ return nil, fmt.Errorf("something went wrong retrieving the iteration for bucket %s", bucketSlug)
+}
+
+func (client *Client) CreateBuild(
+ ctx context.Context,
+ bucketSlug,
+ runUUID,
+ iterationID,
+ fingerprint,
+ componentType string,
+ status models.HashicorpCloudPackerBuildStatus,
+) (*packer_service.PackerServiceCreateBuildOK, error) {
+
+ params := packer_service.NewPackerServiceCreateBuildParamsWithContext(ctx)
+
+ params.LocationOrganizationID = client.OrganizationID
+ params.LocationProjectID = client.ProjectID
+ params.BucketSlug = bucketSlug
+ params.IterationID = iterationID
+ params.Body = packer_service.PackerServiceCreateBuildBody{
+ Fingerprint: fingerprint,
+ Build: &models.HashicorpCloudPackerBuildCreateBody{
+ ComponentType: componentType,
+ PackerRunUUID: runUUID,
+ Status: status.Pointer(),
+ },
+ }
+
+ return client.Packer.PackerServiceCreateBuild(params, nil)
+}
+
+// ListBuilds queries an Iteration on HCP Packer registry for all of it's
+// associated builds. Currently all builds are returned regardless of status.
+func (client *Client) ListBuilds(
+ ctx context.Context,
+ bucketSlug string,
+ iterationID string,
+) ([]*models.HashicorpCloudPackerBuild, error) {
+
+ params := packer_service.NewPackerServiceListBuildsParamsWithContext(ctx)
+ params.LocationOrganizationID = client.OrganizationID
+ params.LocationProjectID = client.ProjectID
+ params.BucketSlug = bucketSlug
+ params.IterationID = iterationID
+
+ resp, err := client.Packer.PackerServiceListBuilds(params, nil)
+ if err != nil {
+ return []*models.HashicorpCloudPackerBuild{}, err
+ }
+
+ return resp.Payload.Builds, nil
+}
+
+// UpdateBuild updates a single iteration build entry with the incoming input
+// data.
+func (client *Client) UpdateBuild(
+ ctx context.Context,
+ buildID,
+ runUUID,
+ cloudProvider,
+ sourceImageID string,
+ sourceIterationID string,
+ sourceChannelID string,
+ labels map[string]string,
+ status models.HashicorpCloudPackerBuildStatus,
+ images []*models.HashicorpCloudPackerImageCreateBody,
+) (string, error) {
+
+ params := packer_service.NewPackerServiceUpdateBuildParamsWithContext(ctx)
+ params.BuildID = buildID
+ params.LocationOrganizationID = client.OrganizationID
+ params.LocationProjectID = client.ProjectID
+
+ params.Body = packer_service.PackerServiceUpdateBuildBody{
+ Updates: &models.HashicorpCloudPackerBuildUpdates{
+ Images: images,
+ PackerRunUUID: runUUID,
+ Labels: labels,
+ Status: status.Pointer(),
+ CloudProvider: cloudProvider,
+ SourceImageID: sourceImageID,
+ SourceIterationID: sourceIterationID,
+ SourceChannelID: sourceChannelID,
+ },
+ }
+
+ resp, err := client.Packer.PackerServiceUpdateBuild(params, nil)
+ if err != nil {
+ return "", err
+ }
+
+ if resp == nil {
+ return "", errors.New("Not sure why response is nil")
+ }
+
+ return resp.Payload.Build.ID, nil
+}
+
+// GetChannel loads the named channel that is associated to the bucket slug . If the
+// channel does not exist in HCP Packer, GetChannel returns an error.
+func (client *Client) GetChannel(ctx context.Context, bucketSlug string, channelName string) (*models.HashicorpCloudPackerChannel, error) {
+ params := packer_service.NewPackerServiceGetChannelParamsWithContext(ctx)
+ params.LocationOrganizationID = client.OrganizationID
+ params.LocationProjectID = client.ProjectID
+ params.BucketSlug = bucketSlug
+ params.Slug = channelName
+
+ resp, err := client.Packer.PackerServiceGetChannel(params, nil)
+ if err != nil {
+ return nil, err
+ }
+
+ if resp.Payload.Channel == nil {
+ return nil, fmt.Errorf("there is no channel with the name %s associated with the bucket %s",
+ channelName, bucketSlug)
+ }
+
+ return resp.Payload.Channel, nil
+}
diff --git a/v1.9.4/internal/hcp/env/env.go b/v1.9.4/internal/hcp/env/env.go
new file mode 100644
index 0000000..0186be1
--- /dev/null
+++ b/v1.9.4/internal/hcp/env/env.go
@@ -0,0 +1,64 @@
+// Copyright (c) HashiCorp, Inc.
+// SPDX-License-Identifier: MPL-2.0
+
+// Package env provides HCP Packer environment variables.
+package env
+
+import (
+ "os"
+ "strings"
+)
+
+func HasProjectID() bool {
+ return hasEnvVar(HCPProjectID)
+}
+
+func HasOrganizationID() bool {
+ return hasEnvVar(HCPOrganizationID)
+}
+
+func HasClientID() bool {
+ return hasEnvVar(HCPClientID)
+}
+
+func HasClientSecret() bool {
+ return hasEnvVar(HCPClientSecret)
+}
+
+func HasPackerRegistryBucket() bool {
+ return hasEnvVar(HCPPackerBucket)
+}
+
+func hasEnvVar(varName string) bool {
+ val, ok := os.LookupEnv(varName)
+ if !ok {
+ return false
+ }
+ return val != ""
+}
+
+func HasHCPCredentials() bool {
+ checks := []func() bool{
+ HasClientID,
+ HasClientSecret,
+ }
+
+ for _, check := range checks {
+ if !check() {
+ return false
+ }
+ }
+
+ return true
+}
+
+func IsHCPDisabled() bool {
+ hcp, ok := os.LookupEnv(HCPPackerRegistry)
+ return ok && strings.ToLower(hcp) == "off" || hcp == "0"
+}
+
+// IsHCPExplicitelyEnabled returns true if the client enabled HCP_PACKER_REGISTRY explicitely, i.e. it is defined and not 0 or off
+func IsHCPExplicitelyEnabled() bool {
+ _, ok := os.LookupEnv(HCPPackerRegistry)
+ return ok && !IsHCPDisabled()
+}
diff --git a/v1.9.4/internal/hcp/env/env_test.go b/v1.9.4/internal/hcp/env/env_test.go
new file mode 100644
index 0000000..1de73f5
--- /dev/null
+++ b/v1.9.4/internal/hcp/env/env_test.go
@@ -0,0 +1,52 @@
+// Copyright (c) HashiCorp, Inc.
+// SPDX-License-Identifier: MPL-2.0
+
+package env
+
+import (
+ "testing"
+)
+
+func Test_IsHCPDisabled(t *testing.T) {
+ tcs := []struct {
+ name string
+ registry_value string
+ output bool
+ }{
+ {
+ name: "nothing set",
+ registry_value: "",
+ output: false,
+ },
+ {
+ name: "registry set with 1",
+ registry_value: "1",
+ output: false,
+ },
+ {
+ name: "registry set with 0",
+ registry_value: "0",
+ output: true,
+ },
+ {
+ name: "registry set with OFF",
+ registry_value: "OFF",
+ output: true,
+ },
+ {
+ name: "registry set with off",
+ registry_value: "off",
+ output: true,
+ },
+ }
+
+ for _, tc := range tcs {
+ t.Run(tc.name, func(t *testing.T) {
+ t.Setenv(HCPPackerRegistry, tc.registry_value)
+ out := IsHCPDisabled()
+ if out != tc.output {
+ t.Fatalf("unexpected output: %t", out)
+ }
+ })
+ }
+}
diff --git a/v1.9.4/internal/hcp/env/variables.go b/v1.9.4/internal/hcp/env/variables.go
new file mode 100644
index 0000000..8c74b60
--- /dev/null
+++ b/v1.9.4/internal/hcp/env/variables.go
@@ -0,0 +1,14 @@
+// Copyright (c) HashiCorp, Inc.
+// SPDX-License-Identifier: MPL-2.0
+
+package env
+
+const (
+ HCPClientID = "HCP_CLIENT_ID"
+ HCPClientSecret = "HCP_CLIENT_SECRET"
+ HCPProjectID = "HCP_PROJECT_ID"
+ HCPOrganizationID = "HCP_ORGANIZATION_ID"
+ HCPPackerRegistry = "HCP_PACKER_REGISTRY"
+ HCPPackerBucket = "HCP_PACKER_BUCKET_NAME"
+ HCPPackerBuildFingerprint = "HCP_PACKER_BUILD_FINGERPRINT"
+)
diff --git a/v1.9.4/internal/hcp/registry/artifact.go b/v1.9.4/internal/hcp/registry/artifact.go
new file mode 100644
index 0000000..a0b0049
--- /dev/null
+++ b/v1.9.4/internal/hcp/registry/artifact.go
@@ -0,0 +1,40 @@
+// Copyright (c) HashiCorp, Inc.
+// SPDX-License-Identifier: MPL-2.0
+
+package registry
+
+import (
+ "fmt"
+)
+
+const BuilderId = "packer.post-processor.hpc-packer-registry"
+
+type registryArtifact struct {
+ BucketSlug string
+ IterationID string
+ BuildName string
+}
+
+func (a *registryArtifact) BuilderId() string {
+ return BuilderId
+}
+
+func (*registryArtifact) Id() string {
+ return ""
+}
+
+func (a *registryArtifact) Files() []string {
+ return []string{}
+}
+
+func (a *registryArtifact) String() string {
+ return fmt.Sprintf("Published metadata to HCP Packer registry packer/%s/iterations/%s", a.BucketSlug, a.IterationID)
+}
+
+func (*registryArtifact) State(name string) interface{} {
+ return nil
+}
+
+func (a *registryArtifact) Destroy() error {
+ return nil
+}
diff --git a/v1.9.4/internal/hcp/registry/errors.go b/v1.9.4/internal/hcp/registry/errors.go
new file mode 100644
index 0000000..a93f960
--- /dev/null
+++ b/v1.9.4/internal/hcp/registry/errors.go
@@ -0,0 +1,14 @@
+// Copyright (c) HashiCorp, Inc.
+// SPDX-License-Identifier: MPL-2.0
+
+package registry
+
+// ErrBuildAlreadyDone is the error returned by an HCP handler when a build cannot be started since it's already marked as DONE.
+type ErrBuildAlreadyDone struct {
+ Message string
+}
+
+// Error returns the message for the ErrBuildAlreadyDone type
+func (b ErrBuildAlreadyDone) Error() string {
+ return b.Message
+}
diff --git a/v1.9.4/internal/hcp/registry/hcl.go b/v1.9.4/internal/hcp/registry/hcl.go
new file mode 100644
index 0000000..64c57a5
--- /dev/null
+++ b/v1.9.4/internal/hcp/registry/hcl.go
@@ -0,0 +1,271 @@
+// Copyright (c) HashiCorp, Inc.
+// SPDX-License-Identifier: MPL-2.0
+
+package registry
+
+import (
+ "context"
+ "fmt"
+ "log"
+
+ "github.com/hashicorp/hcl/v2"
+ "github.com/hashicorp/hcp-sdk-go/clients/cloud-packer-service/stable/2021-04-30/models"
+ sdkpacker "github.com/hashicorp/packer-plugin-sdk/packer"
+ "github.com/hashicorp/packer/hcl2template"
+ "github.com/hashicorp/packer/packer"
+ "github.com/zclconf/go-cty/cty"
+ "github.com/zclconf/go-cty/cty/gocty"
+)
+
+// HCLMetadataRegistry is a HCP handler made for handling HCL configurations
+type HCLMetadataRegistry struct {
+ configuration *hcl2template.PackerConfig
+ bucket *Bucket
+ ui sdkpacker.Ui
+}
+
+const (
+ // Known HCP Packer Image Datasource, whose id is the SourceImageId for some build.
+ hcpImageDatasourceType string = "hcp-packer-image"
+ hcpIterationDatasourceType string = "hcp-packer-iteration"
+ buildLabel string = "build"
+)
+
+// PopulateIteration creates the metadata on HCP for a build
+func (h *HCLMetadataRegistry) PopulateIteration(ctx context.Context) error {
+ err := h.bucket.Initialize(ctx, models.HashicorpCloudPackerIterationTemplateTypeHCL2)
+ if err != nil {
+ return err
+ }
+
+ err = h.bucket.populateIteration(ctx)
+ if err != nil {
+ return err
+ }
+
+ iterationID := h.bucket.Iteration.ID
+
+ h.configuration.HCPVars["iterationID"] = cty.StringVal(iterationID)
+
+ sha, err := getGitSHA(h.configuration.Basedir)
+ if err != nil {
+ log.Printf("failed to get GIT SHA from environment, won't set as build labels")
+ } else {
+ h.bucket.Iteration.AddSHAToBuildLabels(sha)
+ }
+
+ return nil
+}
+
+// StartBuild is invoked when one build for the configuration is starting to be processed
+func (h *HCLMetadataRegistry) StartBuild(ctx context.Context, build sdkpacker.Build) error {
+ name := build.Name()
+ cb, ok := build.(*packer.CoreBuild)
+ if ok {
+ name = cb.Type
+ }
+ return h.bucket.startBuild(ctx, name)
+}
+
+// CompleteBuild is invoked when one build for the configuration has finished
+func (h *HCLMetadataRegistry) CompleteBuild(
+ ctx context.Context,
+ build sdkpacker.Build,
+ artifacts []sdkpacker.Artifact,
+ buildErr error,
+) ([]sdkpacker.Artifact, error) {
+ name := build.Name()
+ cb, ok := build.(*packer.CoreBuild)
+ if ok {
+ name = cb.Type
+ }
+ return h.bucket.completeBuild(ctx, name, artifacts, buildErr)
+}
+
+// IterationStatusSummary prints a status report in the UI if the iteration is not yet done
+func (h *HCLMetadataRegistry) IterationStatusSummary() {
+ h.bucket.Iteration.iterationStatusSummary(h.ui)
+}
+
+func NewHCLMetadataRegistry(config *hcl2template.PackerConfig, ui sdkpacker.Ui) (*HCLMetadataRegistry, hcl.Diagnostics) {
+ var diags hcl.Diagnostics
+ if len(config.Builds) > 1 {
+ diags = append(diags, &hcl.Diagnostic{
+ Severity: hcl.DiagError,
+ Summary: "Multiple " + buildLabel + " blocks",
+ Detail: fmt.Sprintf("For Packer Registry enabled builds, only one " + buildLabel +
+ " block can be defined. Please remove any additional " + buildLabel +
+ " block(s). If this " + buildLabel + " is not meant for the Packer registry please " +
+ "clear any HCP_PACKER_* environment variables."),
+ })
+
+ return nil, diags
+ }
+
+ withHCLBucketConfiguration := func(bb *hcl2template.BuildBlock) bucketConfigurationOpts {
+ return func(bucket *Bucket) hcl.Diagnostics {
+ bucket.ReadFromHCLBuildBlock(bb)
+ // If at this point the bucket.Slug is still empty,
+ // last try is to use the build.Name if present
+ if bucket.Slug == "" && bb.Name != "" {
+ bucket.Slug = bb.Name
+ }
+
+ // If the description is empty, use the one from the build block
+ if bucket.Description == "" && bb.Description != "" {
+ bucket.Description = bb.Description
+ }
+ return nil
+ }
+ }
+
+ // Capture Datasource configuration data
+ vals, dsDiags := config.Datasources.Values()
+ if dsDiags != nil {
+ diags = append(diags, dsDiags...)
+ }
+
+ build := config.Builds[0]
+ bucket, bucketDiags := createConfiguredBucket(
+ config.Basedir,
+ withPackerEnvConfiguration,
+ withHCLBucketConfiguration(build),
+ withDatasourceConfiguration(vals),
+ )
+ if bucketDiags != nil {
+ diags = append(diags, bucketDiags...)
+ }
+
+ if diags.HasErrors() {
+ return nil, diags
+ }
+
+ for _, source := range build.Sources {
+ bucket.RegisterBuildForComponent(source.String())
+ }
+
+ ui.Say(fmt.Sprintf("Tracking build on HCP Packer with fingerprint %q", bucket.Iteration.Fingerprint))
+
+ return &HCLMetadataRegistry{
+ configuration: config,
+ bucket: bucket,
+ ui: ui,
+ }, nil
+}
+
+type hcpImage struct {
+ ID string
+ ChannelID string
+ IterationID string
+}
+
+func imageValueToDSOutput(imageVal map[string]cty.Value) hcpImage {
+ image := hcpImage{}
+ for k, v := range imageVal {
+ switch k {
+ case "id":
+ image.ID = v.AsString()
+ case "channel_id":
+ image.ChannelID = v.AsString()
+ case "iteration_id":
+ image.IterationID = v.AsString()
+ }
+ }
+
+ return image
+}
+
+type hcpIteration struct {
+ ID string
+ ChannelID string
+}
+
+func iterValueToDSOutput(iterVal map[string]cty.Value) hcpIteration {
+ iter := hcpIteration{}
+ for k, v := range iterVal {
+ switch k {
+ case "id":
+ iter.ID = v.AsString()
+ case "channel_id":
+ iter.ChannelID = v.AsString()
+ }
+ }
+ return iter
+}
+
+func withDatasourceConfiguration(vals map[string]cty.Value) bucketConfigurationOpts {
+ return func(bucket *Bucket) hcl.Diagnostics {
+ var diags hcl.Diagnostics
+
+ imageDS, imageOK := vals[hcpImageDatasourceType]
+ iterDS, iterOK := vals[hcpIterationDatasourceType]
+
+ if !imageOK && !iterOK {
+ return nil
+ }
+
+ iterations := map[string]hcpIteration{}
+
+ var err error
+ if iterOK {
+ hcpData := map[string]cty.Value{}
+ err = gocty.FromCtyValue(iterDS, &hcpData)
+ if err != nil {
+ diags = append(diags, &hcl.Diagnostic{
+ Severity: hcl.DiagError,
+ Summary: "Invalid HCP datasources",
+ Detail: fmt.Sprintf("Failed to decode hcp_packer_iteration datasources: %s", err),
+ })
+ return diags
+ }
+
+ for k, v := range hcpData {
+ iterVals := v.AsValueMap()
+ iter := iterValueToDSOutput(iterVals)
+ iterations[k] = iter
+ }
+ }
+
+ images := map[string]hcpImage{}
+
+ if imageOK {
+ hcpData := map[string]cty.Value{}
+ err = gocty.FromCtyValue(imageDS, &hcpData)
+ if err != nil {
+ diags = append(diags, &hcl.Diagnostic{
+ Severity: hcl.DiagError,
+ Summary: "Invalid HCP datasources",
+ Detail: fmt.Sprintf("Failed to decode hcp_packer_image datasources: %s", err),
+ })
+ return diags
+ }
+
+ for k, v := range hcpData {
+ imageVals := v.AsValueMap()
+ img := imageValueToDSOutput(imageVals)
+ images[k] = img
+ }
+ }
+
+ for _, img := range images {
+ sourceIteration := ParentIteration{}
+
+ sourceIteration.IterationID = img.IterationID
+
+ if img.ChannelID != "" {
+ sourceIteration.ChannelID = img.ChannelID
+ } else {
+ for _, it := range iterations {
+ if it.ID == img.IterationID {
+ sourceIteration.ChannelID = it.ChannelID
+ break
+ }
+ }
+ }
+
+ bucket.SourceImagesToParentIterations[img.ID] = sourceIteration
+ }
+
+ return diags
+ }
+}
diff --git a/v1.9.4/internal/hcp/registry/hcp.go b/v1.9.4/internal/hcp/registry/hcp.go
new file mode 100644
index 0000000..838350b
--- /dev/null
+++ b/v1.9.4/internal/hcp/registry/hcp.go
@@ -0,0 +1,153 @@
+// Copyright (c) HashiCorp, Inc.
+// SPDX-License-Identifier: MPL-2.0
+
+package registry
+
+import (
+ "fmt"
+
+ git "github.com/go-git/go-git/v5"
+ "github.com/hashicorp/hcl/v2"
+ "github.com/hashicorp/packer/hcl2template"
+ "github.com/hashicorp/packer/internal/hcp/env"
+ "github.com/hashicorp/packer/packer"
+)
+
+// HCPConfigMode types specify the mode in which HCP configuration
+// is defined for a given Packer build execution.
+type HCPConfigMode int
+
+const (
+ // HCPConfigUnset mode is set when no HCP configuration has been found for the Packer execution.
+ HCPConfigUnset HCPConfigMode = iota
+ // HCPConfigEnabled mode is set when the HCP configuration is codified in the template.
+ HCPConfigEnabled
+ // HCPEnvEnabled mode is set when the HCP configuration is read from environment variables.
+ HCPEnvEnabled
+)
+
+type bucketConfigurationOpts func(*Bucket) hcl.Diagnostics
+
+// IsHCPEnabled returns true if HCP integration is enabled for a build
+func IsHCPEnabled(cfg packer.Handler) bool {
+ // HCP_PACKER_REGISTRY is explicitly turned off
+ if env.IsHCPDisabled() {
+ return false
+ }
+
+ mode := HCPConfigUnset
+
+ switch config := cfg.(type) {
+ case *hcl2template.PackerConfig:
+ for _, build := range config.Builds {
+ if build.HCPPackerRegistry != nil {
+ mode = HCPConfigEnabled
+ }
+ }
+ }
+
+ // HCP_PACKER_BUCKET_NAME is set or HCP_PACKER_REGISTRY not toggled off
+ if mode == HCPConfigUnset && (env.HasPackerRegistryBucket() || env.IsHCPExplicitelyEnabled()) {
+ mode = HCPEnvEnabled
+ }
+
+ return mode != HCPConfigUnset
+}
+
+// createConfiguredBucket returns a bucket that can be used for connecting to the HCP Packer registry.
+// Configuration for the bucket is obtained from the base iteration setting and any addition configuration
+// options passed in as opts. All errors during configuration are collected and returned as Diagnostics.
+func createConfiguredBucket(templateDir string, opts ...bucketConfigurationOpts) (*Bucket, hcl.Diagnostics) {
+ var diags hcl.Diagnostics
+
+ if !env.HasHCPCredentials() {
+ diags = append(diags, &hcl.Diagnostic{
+ Summary: "HCP authentication information required",
+ Detail: fmt.Sprintf("The client authentication requires both %s and %s environment "+
+ "variables to be set for authenticating with HCP.",
+ env.HCPClientID,
+ env.HCPClientSecret),
+ Severity: hcl.DiagError,
+ })
+ }
+
+ bucket := NewBucketWithIteration()
+
+ for _, opt := range opts {
+ if optDiags := opt(bucket); optDiags.HasErrors() {
+ diags = append(diags, optDiags...)
+ }
+ }
+
+ if bucket.Slug == "" {
+ diags = append(diags, &hcl.Diagnostic{
+ Summary: "Image bucket name required",
+ Detail: "You must provide an image bucket name for HCP Packer builds. " +
+ "You can set the HCP_PACKER_BUCKET_NAME environment variable. " +
+ "For HCL2 templates, the registry either uses the name of your " +
+ "template's build block, or you can set the bucket_name argument " +
+ "in an hcp_packer_registry block.",
+ Severity: hcl.DiagError,
+ })
+ }
+
+ err := bucket.Iteration.Initialize()
+ if err != nil {
+ diags = append(diags, &hcl.Diagnostic{
+ Severity: hcl.DiagError,
+ Summary: "Failed to initialize iteration",
+ Detail: fmt.Sprintf("The iteration failed to be initialized for bucket %q: %s",
+ bucket.Slug, err),
+ })
+ }
+
+ if err != nil {
+ diags = append(diags, &hcl.Diagnostic{
+ Summary: "Iteration initialization failed",
+ Detail: fmt.Sprintf("Initialization of the iteration failed with "+
+ "the following error message: %s", err),
+ Severity: hcl.DiagError,
+ })
+ }
+ return bucket, diags
+}
+
+func withPackerEnvConfiguration(bucket *Bucket) hcl.Diagnostics {
+ // Add default values for Packer settings configured via EnvVars.
+ // TODO look to break this up to be more explicit on what is loaded here.
+ bucket.LoadDefaultSettingsFromEnv()
+
+ return nil
+}
+
+// getGitSHA returns the HEAD commit for some template dir defined in baseDir.
+// If the base directory is not under version control an error is returned.
+func getGitSHA(baseDir string) (string, error) {
+ r, err := git.PlainOpenWithOptions(baseDir, &git.PlainOpenOptions{
+ DetectDotGit: true,
+ })
+
+ if err != nil {
+ return "", fmt.Errorf("Packer could not read the fingerprint from git.")
+ }
+
+ // The config can be used to retrieve user identity. for example,
+ // c.User.Email. Leaving in but commented because I'm not sure we care
+ // about this identity right now. - Megan
+ //
+ // c, err := r.ConfigScoped(config.GlobalScope)
+ // if err != nil {
+ // return "", fmt.Errorf("Error setting git scope", err)
+ // }
+ ref, err := r.Head()
+ if err != nil {
+ // If we get there, we're in a Git dir, but HEAD cannot be read.
+ //
+ // This may happen when there's no commit in the git dir.
+ return "", fmt.Errorf("Packer could not read a git SHA in directory %q: %s", baseDir, err)
+ }
+
+ // log.Printf("Author: %v, Commit: %v\n", c.User.Email, ref.Hash())
+
+ return ref.Hash().String(), nil
+}
diff --git a/v1.9.4/internal/hcp/registry/json.go b/v1.9.4/internal/hcp/registry/json.go
new file mode 100644
index 0000000..bb0bba1
--- /dev/null
+++ b/v1.9.4/internal/hcp/registry/json.go
@@ -0,0 +1,102 @@
+// Copyright (c) HashiCorp, Inc.
+// SPDX-License-Identifier: MPL-2.0
+
+package registry
+
+import (
+ "context"
+ "fmt"
+ "log"
+ "path/filepath"
+
+ "github.com/hashicorp/hcl/v2"
+ "github.com/hashicorp/hcp-sdk-go/clients/cloud-packer-service/stable/2021-04-30/models"
+ sdkpacker "github.com/hashicorp/packer-plugin-sdk/packer"
+ "github.com/hashicorp/packer/packer"
+)
+
+// JSONMetadataRegistry is a HCP handler made to process legacy JSON templates
+type JSONMetadataRegistry struct {
+ configuration *packer.Core
+ bucket *Bucket
+ ui sdkpacker.Ui
+}
+
+func NewJSONMetadataRegistry(config *packer.Core, ui sdkpacker.Ui) (*JSONMetadataRegistry, hcl.Diagnostics) {
+ bucket, diags := createConfiguredBucket(
+ filepath.Dir(config.Template.Path),
+ withPackerEnvConfiguration,
+ )
+
+ if diags.HasErrors() {
+ return nil, diags
+ }
+
+ for _, b := range config.Template.Builders {
+ buildName := b.Name
+
+ // By default, if the name is unspecified, it will be assigned the type
+ //
+ // If the two are different, we can compose the HCP build name from both
+ if b.Name != b.Type {
+ buildName = fmt.Sprintf("%s.%s", b.Type, b.Name)
+ }
+
+ // Get all builds slated within config ignoring any only or exclude flags.
+ bucket.RegisterBuildForComponent(buildName)
+ }
+
+ ui.Say(fmt.Sprintf("Tracking build on HCP Packer with fingerprint %q", bucket.Iteration.Fingerprint))
+
+ return &JSONMetadataRegistry{
+ configuration: config,
+ bucket: bucket,
+ ui: ui,
+ }, nil
+}
+
+// PopulateIteration creates the metadata on HCP for a build
+func (h *JSONMetadataRegistry) PopulateIteration(ctx context.Context) error {
+ err := h.bucket.Validate()
+ if err != nil {
+ return err
+ }
+ err = h.bucket.Initialize(ctx, models.HashicorpCloudPackerIterationTemplateTypeJSON)
+ if err != nil {
+ return err
+ }
+
+ err = h.bucket.populateIteration(ctx)
+ if err != nil {
+ return err
+ }
+
+ sha, err := getGitSHA(h.configuration.Template.Path)
+ if err != nil {
+ log.Printf("failed to get GIT SHA from environment, won't set as build labels")
+ } else {
+ h.bucket.Iteration.AddSHAToBuildLabels(sha)
+ }
+
+ return nil
+}
+
+// StartBuild is invoked when one build for the configuration is starting to be processed
+func (h *JSONMetadataRegistry) StartBuild(ctx context.Context, build sdkpacker.Build) error {
+ return h.bucket.startBuild(ctx, build.Name())
+}
+
+// CompleteBuild is invoked when one build for the configuration has finished
+func (h *JSONMetadataRegistry) CompleteBuild(
+ ctx context.Context,
+ build sdkpacker.Build,
+ artifacts []sdkpacker.Artifact,
+ buildErr error,
+) ([]sdkpacker.Artifact, error) {
+ return h.bucket.completeBuild(ctx, build.Name(), artifacts, buildErr)
+}
+
+// IterationStatusSummary prints a status report in the UI if the iteration is not yet done
+func (h *JSONMetadataRegistry) IterationStatusSummary() {
+ h.bucket.Iteration.iterationStatusSummary(h.ui)
+}
diff --git a/v1.9.4/internal/hcp/registry/null_registry.go b/v1.9.4/internal/hcp/registry/null_registry.go
new file mode 100644
index 0000000..5aee3e6
--- /dev/null
+++ b/v1.9.4/internal/hcp/registry/null_registry.go
@@ -0,0 +1,32 @@
+// Copyright (c) HashiCorp, Inc.
+// SPDX-License-Identifier: MPL-2.0
+
+package registry
+
+import (
+ "context"
+
+ sdkpacker "github.com/hashicorp/packer-plugin-sdk/packer"
+)
+
+// nullRegistry is a special handler that does nothing
+type nullRegistry struct{}
+
+func (r nullRegistry) PopulateIteration(context.Context) error {
+ return nil
+}
+
+func (r nullRegistry) StartBuild(context.Context, sdkpacker.Build) error {
+ return nil
+}
+
+func (r nullRegistry) CompleteBuild(
+ ctx context.Context,
+ build sdkpacker.Build,
+ artifacts []sdkpacker.Artifact,
+ buildErr error,
+) ([]sdkpacker.Artifact, error) {
+ return artifacts, nil
+}
+
+func (r nullRegistry) IterationStatusSummary() {}
diff --git a/v1.9.4/internal/hcp/registry/registry.go b/v1.9.4/internal/hcp/registry/registry.go
new file mode 100644
index 0000000..b095e14
--- /dev/null
+++ b/v1.9.4/internal/hcp/registry/registry.go
@@ -0,0 +1,48 @@
+// Copyright (c) HashiCorp, Inc.
+// SPDX-License-Identifier: MPL-2.0
+
+// Package registry provides access to the HCP registry.
+package registry
+
+import (
+ "context"
+
+ "github.com/hashicorp/hcl/v2"
+ sdkpacker "github.com/hashicorp/packer-plugin-sdk/packer"
+ "github.com/hashicorp/packer/hcl2template"
+ "github.com/hashicorp/packer/packer"
+)
+
+// Registry is an entity capable to orchestrate a Packer build and upload metadata to HCP
+type Registry interface {
+ PopulateIteration(context.Context) error
+ StartBuild(context.Context, sdkpacker.Build) error
+ CompleteBuild(ctx context.Context, build sdkpacker.Build, artifacts []sdkpacker.Artifact, buildErr error) ([]sdkpacker.Artifact, error)
+ IterationStatusSummary()
+}
+
+// New instanciates the appropriate registry for the Packer configuration template type.
+// A nullRegistry is returned for non-HCP Packer registry enabled templates.
+func New(cfg packer.Handler, ui sdkpacker.Ui) (Registry, hcl.Diagnostics) {
+ if !IsHCPEnabled(cfg) {
+ return &nullRegistry{}, nil
+ }
+
+ switch config := cfg.(type) {
+ case *hcl2template.PackerConfig:
+ // Maybe rename to what it represents....
+ return NewHCLMetadataRegistry(config, ui)
+ case *packer.Core:
+ return NewJSONMetadataRegistry(config, ui)
+ }
+
+ return nil, hcl.Diagnostics{
+ &hcl.Diagnostic{
+ Severity: hcl.DiagError,
+ Summary: "Unknown Config type",
+ Detail: "The config type %s does not match a Packer-known template type. " +
+ "This is a Packer error and should be brought up to the Packer " +
+ "team via a GitHub Issue.",
+ },
+ }
+}
diff --git a/v1.9.4/internal/hcp/registry/types.bucket.go b/v1.9.4/internal/hcp/registry/types.bucket.go
new file mode 100644
index 0000000..7e54864
--- /dev/null
+++ b/v1.9.4/internal/hcp/registry/types.bucket.go
@@ -0,0 +1,627 @@
+// Copyright (c) HashiCorp, Inc.
+// SPDX-License-Identifier: MPL-2.0
+
+package registry
+
+import (
+ "context"
+ "errors"
+ "fmt"
+ "log"
+ "os"
+ "sync"
+ "time"
+
+ "github.com/hashicorp/go-multierror"
+ "github.com/hashicorp/hcp-sdk-go/clients/cloud-packer-service/stable/2021-04-30/models"
+ "github.com/hashicorp/packer-plugin-sdk/packer"
+ registryimage "github.com/hashicorp/packer-plugin-sdk/packer/registry/image"
+ "github.com/hashicorp/packer/hcl2template"
+ "github.com/hashicorp/packer/internal/hcp/api"
+ "github.com/hashicorp/packer/internal/hcp/env"
+ "github.com/mitchellh/mapstructure"
+ "google.golang.org/grpc/codes"
+)
+
+// HeartbeatPeriod dictates how often a heartbeat is sent to HCP to signal a
+// build is still alive.
+const HeartbeatPeriod = 2 * time.Minute
+
+// Bucket represents a single Image bucket on the HCP Packer registry.
+type Bucket struct {
+ Slug string
+ Description string
+ Destination string
+ BucketLabels map[string]string
+ BuildLabels map[string]string
+ SourceImagesToParentIterations map[string]ParentIteration
+ RunningBuilds map[string]chan struct{}
+ Iteration *Iteration
+ client *api.Client
+}
+
+type ParentIteration struct {
+ IterationID string
+ ChannelID string
+}
+
+// NewBucketWithIteration initializes a simple Bucket that can be used publishing Packer build
+// images to the HCP Packer registry.
+func NewBucketWithIteration() *Bucket {
+ b := Bucket{
+ BucketLabels: make(map[string]string),
+ BuildLabels: make(map[string]string),
+ SourceImagesToParentIterations: make(map[string]ParentIteration),
+ RunningBuilds: make(map[string]chan struct{}),
+ }
+ b.Iteration = NewIteration()
+
+ return &b
+}
+
+func (b *Bucket) Validate() error {
+ if b.Slug == "" {
+ return fmt.Errorf("no Packer bucket name defined; either the environment variable %q is undefined or the HCL configuration has no build name", env.HCPPackerBucket)
+ }
+ return nil
+}
+
+// ReadFromHCLBuildBlock reads the information for initialising a Bucket from a HCL2 build block
+func (b *Bucket) ReadFromHCLBuildBlock(build *hcl2template.BuildBlock) {
+ if b == nil {
+ return
+ }
+
+ registryBlock := build.HCPPackerRegistry
+ if registryBlock == nil {
+ return
+ }
+
+ b.Description = registryBlock.Description
+ b.BucketLabels = registryBlock.BucketLabels
+ b.BuildLabels = registryBlock.BuildLabels
+ // If there's already a Slug this was set from env variable.
+ // In Packer, env variable overrides config values so we keep it that way for consistency.
+ if b.Slug == "" && registryBlock.Slug != "" {
+ b.Slug = registryBlock.Slug
+ }
+}
+
+// connect initializes a client connection to a remote HCP Packer Registry service on HCP.
+// Upon a successful connection the initialized client is persisted on the Bucket b for later usage.
+func (b *Bucket) connect() error {
+ if b.client != nil {
+ return nil
+ }
+
+ registryClient, err := api.NewClient()
+ if err != nil {
+ return errors.New("Failed to create client connection to artifact registry: " + err.Error())
+ }
+ b.client = registryClient
+ return nil
+}
+
+// Initialize registers the Bucket b with the configured HCP Packer Registry.
+// Upon initialization a Bucket will be upserted to, and new iteration will be created for the build if the configured
+// fingerprint has no associated iterations. Lastly, the initialization process with register the builds that need to be
+// completed before an iteration can be marked as DONE.
+//
+// b.Initialize() must be called before any data can be published to the configured HCP Packer Registry.
+// TODO ensure initialize can only be called once
+func (b *Bucket) Initialize(ctx context.Context, templateType models.HashicorpCloudPackerIterationTemplateType) error {
+
+ if err := b.connect(); err != nil {
+ return err
+ }
+
+ b.Destination = fmt.Sprintf("%s/%s", b.client.OrganizationID, b.client.ProjectID)
+
+ err := b.client.UpsertBucket(ctx, b.Slug, b.Description, b.BucketLabels)
+ if err != nil {
+ return fmt.Errorf("failed to initialize bucket %q: %w", b.Slug, err)
+ }
+
+ return b.initializeIteration(ctx, templateType)
+}
+
+func (b *Bucket) RegisterBuildForComponent(sourceName string) {
+ if b == nil {
+ return
+ }
+
+ if ok := b.Iteration.HasBuild(sourceName); ok {
+ return
+ }
+
+ b.Iteration.expectedBuilds = append(b.Iteration.expectedBuilds, sourceName)
+}
+
+// CreateInitialBuildForIteration will create a build entry on the HCP Packer Registry for the named componentType.
+// This initial creation is needed so that Packer can properly track when an iteration is complete.
+func (b *Bucket) CreateInitialBuildForIteration(ctx context.Context, componentType string) error {
+ status := models.HashicorpCloudPackerBuildStatusUNSET
+
+ resp, err := b.client.CreateBuild(ctx,
+ b.Slug,
+ b.Iteration.RunUUID,
+ b.Iteration.ID,
+ b.Iteration.Fingerprint,
+ componentType,
+ status,
+ )
+ if err != nil {
+ return err
+ }
+
+ build, err := NewBuildFromCloudPackerBuild(resp.Payload.Build)
+ if err != nil {
+ log.Printf("[TRACE] unable to load created build for %q: %v", componentType, err)
+ }
+
+ build.Labels = make(map[string]string)
+ build.Images = make(map[string]registryimage.Image)
+
+ // Initial build labels are only pushed to the registry when an actual Packer run is executed on the said build.
+ // For example filtered builds (e.g --only or except) will not get the initial build labels until a build is executed on them.
+ // Global build label updates to existing builds are handled in PopulateIteration.
+ if len(b.BuildLabels) > 0 {
+ build.MergeLabels(b.BuildLabels)
+ }
+ b.Iteration.StoreBuild(componentType, build)
+
+ return nil
+}
+
+// UpdateBuildStatus updates the status of a build entry on the HCP Packer registry with its current local status.
+// For updating a build status to DONE use CompleteBuild.
+func (b *Bucket) UpdateBuildStatus(ctx context.Context, name string, status models.HashicorpCloudPackerBuildStatus) error {
+ if status == models.HashicorpCloudPackerBuildStatusDONE {
+ return fmt.Errorf("do not use UpdateBuildStatus for updating to DONE")
+ }
+
+ buildToUpdate, err := b.Iteration.Build(name)
+ if err != nil {
+ return err
+ }
+
+ if buildToUpdate.ID == "" {
+ return fmt.Errorf("the build for the component %q does not have a valid id", name)
+ }
+
+ if buildToUpdate.Status == models.HashicorpCloudPackerBuildStatusDONE {
+ return fmt.Errorf("cannot modify status of DONE build %s", name)
+ }
+
+ _, err = b.client.UpdateBuild(ctx,
+ buildToUpdate.ID,
+ buildToUpdate.RunUUID,
+ "",
+ "",
+ "",
+ "",
+ nil,
+ status,
+ nil,
+ )
+ if err != nil {
+ return err
+ }
+ buildToUpdate.Status = status
+ b.Iteration.StoreBuild(name, buildToUpdate)
+ return nil
+}
+
+// markBuildComplete should be called to set a build on the HCP Packer registry to DONE.
+// Upon a successful call markBuildComplete will publish all images created by the named build,
+// and set the registry build to done. A build with no images can not be set to DONE.
+func (b *Bucket) markBuildComplete(ctx context.Context, name string) error {
+ buildToUpdate, err := b.Iteration.Build(name)
+ if err != nil {
+ return err
+ }
+
+ if buildToUpdate.ID == "" {
+ return fmt.Errorf("the build for the component %q does not have a valid id", name)
+ }
+
+ status := models.HashicorpCloudPackerBuildStatusDONE
+
+ if buildToUpdate.Status == status {
+ // let's no mess with anything that is already done
+ return nil
+ }
+
+ if len(buildToUpdate.Images) == 0 {
+ return fmt.Errorf("setting a build to DONE with no published images is not currently supported.")
+ }
+
+ var providerName, sourceID, sourceIterationID, sourceChannelID string
+ images := make([]*models.HashicorpCloudPackerImageCreateBody, 0, len(buildToUpdate.Images))
+ for _, image := range buildToUpdate.Images {
+ // These values will always be the same for all images in a single build,
+ // so we can just set it inside the loop without consequence
+ if providerName == "" {
+ providerName = image.ProviderName
+ }
+ if image.SourceImageID != "" {
+ sourceID = image.SourceImageID
+ }
+
+ // Check if image is using some other HCP Packer image
+ if v, ok := b.SourceImagesToParentIterations[image.SourceImageID]; ok {
+ sourceIterationID = v.IterationID
+ sourceChannelID = v.ChannelID
+ }
+
+ images = append(images, &models.HashicorpCloudPackerImageCreateBody{ImageID: image.ImageID, Region: image.ProviderRegion})
+ }
+
+ _, err = b.client.UpdateBuild(ctx,
+ buildToUpdate.ID,
+ buildToUpdate.RunUUID,
+ buildToUpdate.CloudProvider,
+ sourceID,
+ sourceIterationID,
+ sourceChannelID,
+ buildToUpdate.Labels,
+ status,
+ images,
+ )
+ if err != nil {
+ return err
+ }
+
+ buildToUpdate.Status = status
+ b.Iteration.StoreBuild(name, buildToUpdate)
+ return nil
+}
+
+// UpdateImageForBuild appends one or more images artifacts to the build referred to by componentType.
+func (b *Bucket) UpdateImageForBuild(componentType string, images ...registryimage.Image) error {
+ return b.Iteration.AddImageToBuild(componentType, images...)
+}
+
+// UpdateLabelsForBuild merges the contents of data to the labels associated with the build referred to by componentType.
+func (b *Bucket) UpdateLabelsForBuild(componentType string, data map[string]string) error {
+ return b.Iteration.AddLabelsToBuild(componentType, data)
+}
+
+// Load defaults from environment variables
+func (b *Bucket) LoadDefaultSettingsFromEnv() {
+ // Configure HCP Packer Registry destination
+ if b.Slug == "" {
+ b.Slug = os.Getenv(env.HCPPackerBucket)
+ }
+
+ // Set some iteration values. For Packer RunUUID should always be set.
+ // Creating an iteration differently? Let's not overwrite a UUID that might be set.
+ if b.Iteration.RunUUID == "" {
+ b.Iteration.RunUUID = os.Getenv("PACKER_RUN_UUID")
+ }
+
+}
+
+// createIteration creates an empty iteration for a give bucket on the HCP Packer registry.
+// The iteration can then be stored locally and used for tracking build status and images for a running
+// Packer build.
+func (b *Bucket) createIteration(templateType models.HashicorpCloudPackerIterationTemplateType) (*models.HashicorpCloudPackerIteration, error) {
+ ctx := context.Background()
+
+ if templateType == models.HashicorpCloudPackerIterationTemplateTypeTEMPLATETYPEUNSET {
+ return nil, fmt.Errorf("packer error: template type should not be unset when creating an iteration. This is a Packer internal bug which should be reported to the development team for a fix.")
+ }
+
+ createIterationResp, err := b.client.CreateIteration(ctx, b.Slug, b.Iteration.Fingerprint, templateType)
+ if err != nil {
+ return nil, fmt.Errorf("failed to create Iteration for Bucket %s with error: %w", b.Slug, err)
+ }
+
+ if createIterationResp == nil {
+ return nil, fmt.Errorf("failed to create Iteration for Bucket %s with error: %w", b.Slug, err)
+ }
+
+ log.Println("[TRACE] a valid iteration for build was created with the Id", createIterationResp.Payload.Iteration.ID)
+ return createIterationResp.Payload.Iteration, nil
+}
+
+func (b *Bucket) initializeIteration(ctx context.Context, templateType models.HashicorpCloudPackerIterationTemplateType) error {
+ // load existing iteration using fingerprint.
+ iteration, err := b.client.GetIteration(ctx, b.Slug, api.GetIteration_byFingerprint(b.Iteration.Fingerprint))
+ if api.CheckErrorCode(err, codes.Aborted) {
+ // probably means Iteration doesn't exist need a way to check the error
+ iteration, err = b.createIteration(templateType)
+ }
+
+ if err != nil {
+ return fmt.Errorf("failed to initialize iteration for fingerprint %s: %s", b.Iteration.Fingerprint, err)
+ }
+
+ if iteration == nil {
+ return fmt.Errorf("failed to initialize iteration details for Bucket %s with error: %w", b.Slug, err)
+ }
+
+ if iteration.TemplateType != nil &&
+ *iteration.TemplateType != models.HashicorpCloudPackerIterationTemplateTypeTEMPLATETYPEUNSET &&
+ *iteration.TemplateType != templateType {
+ return fmt.Errorf("This iteration was initially created with a %[2]s template. Changing from %[2]s to %[1]s is not supported.",
+ templateType, *iteration.TemplateType)
+ }
+
+ log.Println("[TRACE] a valid iteration was retrieved with the id", iteration.ID)
+ b.Iteration.ID = iteration.ID
+
+ // If the iteration is completed and there are no new builds to add, Packer
+ // should exit and inform the user that artifacts already exists for the
+ // fingerprint associated with the iteration.
+ if iteration.Complete {
+ return fmt.Errorf("This iteration associated to the fingerprint %s is complete. "+
+ "If you wish to add a new build to this image a new iteration must be created by changing the build fingerprint.", b.Iteration.Fingerprint)
+ }
+
+ return nil
+}
+
+// populateIteration populates the bucket iteration with the details needed for tracking builds for a Packer run.
+// If an existing Packer registry iteration exists for the said iteration fingerprint, calling initialize on iteration
+// that doesn't yet exist will call createIteration to create the entry on the HCP packer registry for the given bucket.
+// All build details will be created (if they don't exists) and added to b.Iteration.builds for tracking during runtime.
+func (b *Bucket) populateIteration(ctx context.Context) error {
+ // list all this iteration's builds so we can figure out which ones
+ // we want to run against. TODO: pagination?
+ existingBuilds, err := b.client.ListBuilds(ctx, b.Slug, b.Iteration.ID)
+ if err != nil {
+ return fmt.Errorf("error listing builds for this existing iteration: %s", err)
+ }
+
+ var toCreate []string
+ for _, expected := range b.Iteration.expectedBuilds {
+ var found bool
+ for _, existing := range existingBuilds {
+
+ if existing.ComponentType == expected {
+ found = true
+ build, err := NewBuildFromCloudPackerBuild(existing)
+ if err != nil {
+ return fmt.Errorf("Unable to load existing build for %q: %v", existing.ComponentType, err)
+ }
+
+ // When running against an existing build the Packer RunUUID is most likely different.
+ // We capture that difference here to know that the image was created in a different Packer run.
+ build.RunUUID = b.Iteration.RunUUID
+
+ // When bucket build labels represent some dynamic data set, possibly set via some user variable,
+ // we need to make sure that any newly executed builds get the labels at runtime.
+ if build.IsNotDone() && len(b.BuildLabels) > 0 {
+ build.MergeLabels(b.BuildLabels)
+ }
+
+ log.Printf("[TRACE] a build of component type %s already exists; skipping the create call", expected)
+ b.Iteration.StoreBuild(existing.ComponentType, build)
+
+ break
+ }
+ }
+
+ if !found {
+ missingbuild := expected
+ toCreate = append(toCreate, missingbuild)
+ }
+ }
+
+ if len(toCreate) == 0 {
+ return nil
+ }
+
+ var errs *multierror.Error
+ var wg sync.WaitGroup
+ var mu sync.Mutex
+ for _, buildName := range toCreate {
+ wg.Add(1)
+ go func(name string) {
+ defer wg.Done()
+
+ log.Printf("[TRACE] registering build with iteration for %q.", name)
+ err := b.CreateInitialBuildForIteration(ctx, name)
+
+ if api.CheckErrorCode(err, codes.AlreadyExists) {
+ log.Printf("[TRACE] build %s already exists in Packer registry, continuing...", name)
+ return
+ }
+
+ if err != nil {
+ mu.Lock()
+ errs = multierror.Append(errs, err)
+ mu.Unlock()
+ }
+ }(buildName)
+ }
+ wg.Wait()
+
+ return errs.ErrorOrNil()
+}
+
+// IsExpectingBuildForComponent returns true if the component referenced by buildName is part of the iteration
+// and is not marked as DONE on the HCP Packer registry.
+func (b *Bucket) IsExpectingBuildForComponent(buildName string) bool {
+ if !b.Iteration.HasBuild(buildName) {
+ return false
+ }
+
+ build, err := b.Iteration.Build(buildName)
+ if err != nil {
+ return false
+ }
+
+ return build.IsNotDone()
+}
+
+// HeartbeatBuild periodically sends status updates for the build
+//
+// This lets HCP infer that a build is still running and should not be marked
+// as cancelled by the HCP Packer registry service.
+//
+// Usage: defer (b.HeartbeatBuild(ctx, build, period))()
+func (b *Bucket) HeartbeatBuild(ctx context.Context, build string) (func(), error) {
+ buildToUpdate, err := b.Iteration.Build(build)
+ if err != nil {
+ return nil, err
+ }
+
+ heartbeatChan := make(chan struct{})
+ go func() {
+ log.Printf("[TRACE] starting heartbeats")
+
+ tick := time.NewTicker(HeartbeatPeriod)
+
+ outHeartbeats:
+ for {
+ select {
+ case <-heartbeatChan:
+ tick.Stop()
+ break outHeartbeats
+ case <-ctx.Done():
+ tick.Stop()
+ break outHeartbeats
+ case <-tick.C:
+ _, err = b.client.UpdateBuild(ctx,
+ buildToUpdate.ID,
+ buildToUpdate.RunUUID,
+ "",
+ "",
+ "",
+ "",
+ nil,
+ models.HashicorpCloudPackerBuildStatusRUNNING,
+ nil,
+ )
+ if err != nil {
+ log.Printf("[ERROR] failed to send heartbeat for build %q: %s", build, err)
+ } else {
+ log.Printf("[TRACE] updating build status for %q to running", build)
+ }
+ }
+ }
+
+ log.Printf("[TRACE] stopped heartbeating build %s", build)
+ }()
+ return func() {
+ close(heartbeatChan)
+ }, nil
+}
+
+func (b *Bucket) startBuild(ctx context.Context, buildName string) error {
+ if !b.IsExpectingBuildForComponent(buildName) {
+ return &ErrBuildAlreadyDone{
+ Message: "build is already done",
+ }
+ }
+
+ err := b.UpdateBuildStatus(ctx, buildName, models.HashicorpCloudPackerBuildStatusRUNNING)
+ if err != nil {
+ return fmt.Errorf("failed to update HCP Packer registry status for %q: %s", buildName, err)
+ }
+
+ cleanupHeartbeat, err := b.HeartbeatBuild(ctx, buildName)
+ if err != nil {
+ log.Printf("[ERROR] failed to start heartbeat function")
+ }
+
+ buildDone := make(chan struct{}, 1)
+ go func() {
+ log.Printf("[TRACE] waiting for heartbeat completion")
+ select {
+ case <-ctx.Done():
+ cleanupHeartbeat()
+ err := b.UpdateBuildStatus(
+ context.Background(),
+ buildName,
+ models.HashicorpCloudPackerBuildStatusCANCELLED)
+ if err != nil {
+ log.Printf(
+ "[ERROR] failed to update HCP Packer registry status for %q: %s",
+ buildName,
+ err)
+ }
+ case <-buildDone:
+ cleanupHeartbeat()
+ }
+ log.Printf("[TRACE] done waiting for heartbeat completion")
+ }()
+
+ b.RunningBuilds[buildName] = buildDone
+
+ return nil
+}
+
+func (b *Bucket) completeBuild(
+ ctx context.Context,
+ buildName string,
+ artifacts []packer.Artifact,
+ buildErr error,
+) ([]packer.Artifact, error) {
+ doneCh, ok := b.RunningBuilds[buildName]
+ if !ok {
+ log.Print("[ERROR] done build does not have an entry in the heartbeat table, state will be inconsistent.")
+
+ } else {
+ log.Printf("[TRACE] signal stopping heartbeats")
+ // Stop heartbeating
+ doneCh <- struct{}{}
+ log.Printf("[TRACE] stopped heartbeats")
+ }
+
+ if buildErr != nil {
+ status := models.HashicorpCloudPackerBuildStatusFAILED
+ if ctx.Err() != nil {
+ status = models.HashicorpCloudPackerBuildStatusCANCELLED
+ }
+ err := b.UpdateBuildStatus(context.Background(), buildName, status)
+ if err != nil {
+ log.Printf("[ERROR] failed to update build %q status to FAILED: %s", buildName, err)
+ }
+ return artifacts, fmt.Errorf("build failed, not uploading artifacts")
+ }
+
+ for _, art := range artifacts {
+ var images []registryimage.Image
+ decoder, err := mapstructure.NewDecoder(&mapstructure.DecoderConfig{
+ Result: &images,
+ WeaklyTypedInput: true,
+ ErrorUnused: false,
+ })
+ if err != nil {
+ return artifacts, fmt.Errorf(
+ "failed to create decoder for HCP Packer registry image: %w",
+ err)
+ }
+
+ state := art.State(registryimage.ArtifactStateURI)
+ err = decoder.Decode(state)
+ if err != nil {
+ return artifacts, fmt.Errorf(
+ "failed to obtain HCP Packer registry image from post-processor artifact: %w",
+ err)
+ }
+ log.Printf("[TRACE] updating artifacts for build %q", buildName)
+ err = b.UpdateImageForBuild(buildName, images...)
+
+ if err != nil {
+ return artifacts, fmt.Errorf("failed to add image artifact for %q: %s", buildName, err)
+ }
+ }
+
+ parErr := b.markBuildComplete(ctx, buildName)
+ if parErr != nil {
+ return artifacts, fmt.Errorf(
+ "failed to update Packer registry with image artifacts for %q: %s",
+ buildName,
+ parErr)
+ }
+
+ return append(artifacts, ®istryArtifact{
+ BuildName: buildName,
+ BucketSlug: b.Slug,
+ IterationID: b.Iteration.ID,
+ }), nil
+}
diff --git a/v1.9.4/internal/hcp/registry/types.bucket_service_test.go b/v1.9.4/internal/hcp/registry/types.bucket_service_test.go
new file mode 100644
index 0000000..5fa28ac
--- /dev/null
+++ b/v1.9.4/internal/hcp/registry/types.bucket_service_test.go
@@ -0,0 +1,368 @@
+// Copyright (c) HashiCorp, Inc.
+// SPDX-License-Identifier: MPL-2.0
+
+package registry
+
+import (
+ "context"
+ "testing"
+
+ "github.com/hashicorp/hcp-sdk-go/clients/cloud-packer-service/stable/2021-04-30/models"
+ "github.com/hashicorp/packer/internal/hcp/api"
+)
+
+func TestInitialize_NewBucketNewIteration(t *testing.T) {
+ mockService := api.NewMockPackerClientService()
+
+ b := &Bucket{
+ Slug: "TestBucket",
+ client: &api.Client{
+ Packer: mockService,
+ },
+ }
+
+ b.Iteration = NewIteration()
+ err := b.Iteration.Initialize()
+ if err != nil {
+ t.Errorf("unexpected failure: %v", err)
+ }
+
+ b.Iteration.expectedBuilds = append(b.Iteration.expectedBuilds, "happycloud.image")
+
+ err = b.Initialize(context.TODO(), models.HashicorpCloudPackerIterationTemplateTypeHCL2)
+ if err != nil {
+ t.Errorf("unexpected failure: %v", err)
+ }
+
+ if !mockService.CreateBucketCalled {
+ t.Errorf("expected a call to CreateBucket but it didn't happen")
+ }
+
+ if !mockService.CreateIterationCalled {
+ t.Errorf("expected a call to CreateIteration but it didn't happen")
+ }
+
+ if mockService.CreateBuildCalled {
+ t.Errorf("Didn't expect a call to CreateBuild")
+ }
+
+ if b.Iteration.ID != "iteration-id" {
+ t.Errorf("expected an iteration to created but it didn't")
+ }
+
+ err = b.populateIteration(context.TODO())
+ if err != nil {
+ t.Errorf("unexpected failure: %v", err)
+ }
+ if !mockService.CreateBuildCalled {
+ t.Errorf("Expected a call to CreateBuild but it didn't happen")
+ }
+
+ if ok := b.Iteration.HasBuild("happycloud.image"); !ok {
+ t.Errorf("expected a basic build entry to be created but it didn't")
+ }
+}
+
+func TestInitialize_UnsetTemplateTypeError(t *testing.T) {
+ mockService := api.NewMockPackerClientService()
+ mockService.BucketAlreadyExist = true
+
+ b := &Bucket{
+ Slug: "TestBucket",
+ client: &api.Client{
+ Packer: mockService,
+ },
+ }
+
+ b.Iteration = NewIteration()
+ err := b.Iteration.Initialize()
+ if err != nil {
+ t.Errorf("unexpected failure: %v", err)
+ }
+
+ err = b.Initialize(context.TODO(), models.HashicorpCloudPackerIterationTemplateTypeTEMPLATETYPEUNSET)
+ if err == nil {
+ t.Fatalf("unexpected success")
+ }
+
+ t.Logf("iteration creating failed as expected: %s", err)
+}
+
+func TestInitialize_ExistingBucketNewIteration(t *testing.T) {
+ mockService := api.NewMockPackerClientService()
+ mockService.BucketAlreadyExist = true
+
+ b := &Bucket{
+ Slug: "TestBucket",
+ client: &api.Client{
+ Packer: mockService,
+ },
+ }
+
+ b.Iteration = NewIteration()
+ err := b.Iteration.Initialize()
+ if err != nil {
+ t.Errorf("unexpected failure: %v", err)
+ }
+ b.Iteration.expectedBuilds = append(b.Iteration.expectedBuilds, "happycloud.image")
+
+ err = b.Initialize(context.TODO(), models.HashicorpCloudPackerIterationTemplateTypeHCL2)
+ if err != nil {
+ t.Errorf("unexpected failure: %v", err)
+ }
+
+ if !mockService.UpdateBucketCalled {
+ t.Errorf("expected call to UpdateBucket but it didn't happen")
+ }
+
+ if !mockService.CreateIterationCalled {
+ t.Errorf("expected a call to CreateIteration but it didn't happen")
+ }
+
+ if mockService.CreateBuildCalled {
+ t.Errorf("Didn't expect a call to CreateBuild")
+ }
+
+ if b.Iteration.ID != "iteration-id" {
+ t.Errorf("expected an iteration to created but it didn't")
+ }
+
+ err = b.populateIteration(context.TODO())
+ if err != nil {
+ t.Errorf("unexpected failure: %v", err)
+ }
+ if !mockService.CreateBuildCalled {
+ t.Errorf("Expected a call to CreateBuild but it didn't happen")
+ }
+
+ if ok := b.Iteration.HasBuild("happycloud.image"); !ok {
+ t.Errorf("expected a basic build entry to be created but it didn't")
+ }
+
+}
+
+func TestInitialize_ExistingBucketExistingIteration(t *testing.T) {
+ mockService := api.NewMockPackerClientService()
+ mockService.BucketAlreadyExist = true
+ mockService.IterationAlreadyExist = true
+
+ b := &Bucket{
+ Slug: "TestBucket",
+ client: &api.Client{
+ Packer: mockService,
+ },
+ }
+
+ b.Iteration = NewIteration()
+ err := b.Iteration.Initialize()
+ if err != nil {
+ t.Errorf("unexpected failure: %v", err)
+ }
+
+ b.Iteration.expectedBuilds = append(b.Iteration.expectedBuilds, "happycloud.image")
+ mockService.ExistingBuilds = append(mockService.ExistingBuilds, "happycloud.image")
+
+ err = b.Initialize(context.TODO(), models.HashicorpCloudPackerIterationTemplateTypeHCL2)
+ if err != nil {
+ t.Errorf("unexpected failure: %v", err)
+ }
+ err = b.populateIteration(context.TODO())
+ if err != nil {
+ t.Errorf("unexpected failure: %v", err)
+ }
+
+ if mockService.CreateBucketCalled {
+ t.Errorf("unexpected call to CreateBucket")
+ }
+
+ if !mockService.UpdateBucketCalled {
+ t.Errorf("expected call to UpdateBucket but it didn't happen")
+ }
+
+ if mockService.CreateIterationCalled {
+ t.Errorf("unexpected a call to CreateIteration")
+ }
+
+ if !mockService.GetIterationCalled {
+ t.Errorf("expected a call to GetIteration but it didn't happen")
+ }
+
+ if mockService.CreateBuildCalled {
+ t.Errorf("unexpected a call to CreateBuild")
+ }
+
+ if b.Iteration.ID != "iteration-id" {
+ t.Errorf("expected an iteration to created but it didn't")
+ }
+
+ err = b.populateIteration(context.TODO())
+ if err != nil {
+ t.Errorf("unexpected failure: %v", err)
+ }
+
+ existingBuild, err := b.Iteration.Build("happycloud.image")
+ if err != nil {
+ t.Errorf("expected the existing build loaded from an existing bucket to be valid: %v", err)
+ }
+
+ if existingBuild.Status != models.HashicorpCloudPackerBuildStatusUNSET {
+ t.Errorf("expected the existing build to be in the default state")
+ }
+}
+
+func TestInitialize_ExistingBucketCompleteIteration(t *testing.T) {
+ mockService := api.NewMockPackerClientService()
+ mockService.BucketAlreadyExist = true
+ mockService.IterationAlreadyExist = true
+ mockService.IterationCompleted = true
+ mockService.BuildAlreadyDone = true
+
+ b := &Bucket{
+ Slug: "TestBucket",
+ client: &api.Client{
+ Packer: mockService,
+ },
+ }
+
+ b.Iteration = NewIteration()
+ err := b.Iteration.Initialize()
+ if err != nil {
+ t.Errorf("unexpected failure: %v", err)
+ }
+
+ b.Iteration.expectedBuilds = append(b.Iteration.expectedBuilds, "happycloud.image")
+ mockService.ExistingBuilds = append(mockService.ExistingBuilds, "happycloud.image")
+
+ err = b.Initialize(context.TODO(), models.HashicorpCloudPackerIterationTemplateTypeHCL2)
+ if err == nil {
+ t.Errorf("unexpected failure: %v", err)
+ }
+
+ if mockService.CreateIterationCalled {
+ t.Errorf("unexpected call to CreateIteration")
+ }
+
+ if !mockService.GetIterationCalled {
+ t.Errorf("expected a call to GetIteration but it didn't happen")
+ }
+
+ if mockService.CreateBuildCalled {
+ t.Errorf("unexpected call to CreateBuild")
+ }
+
+ if b.Iteration.ID != "iteration-id" {
+ t.Errorf("expected an iteration to be returned but it wasn't")
+ }
+}
+
+func TestUpdateBuildStatus(t *testing.T) {
+ mockService := api.NewMockPackerClientService()
+ mockService.BucketAlreadyExist = true
+ mockService.IterationAlreadyExist = true
+
+ b := &Bucket{
+ Slug: "TestBucket",
+ client: &api.Client{
+ Packer: mockService,
+ },
+ }
+
+ b.Iteration = NewIteration()
+ err := b.Iteration.Initialize()
+ if err != nil {
+ t.Errorf("unexpected failure: %v", err)
+ }
+ b.Iteration.expectedBuilds = append(b.Iteration.expectedBuilds, "happycloud.image")
+ mockService.ExistingBuilds = append(mockService.ExistingBuilds, "happycloud.image")
+
+ err = b.Initialize(context.TODO(), models.HashicorpCloudPackerIterationTemplateTypeHCL2)
+ if err != nil {
+ t.Errorf("unexpected failure: %v", err)
+ }
+ err = b.populateIteration(context.TODO())
+ if err != nil {
+ t.Errorf("unexpected failure: %v", err)
+ }
+
+ existingBuild, err := b.Iteration.Build("happycloud.image")
+ if err != nil {
+ t.Errorf("expected the existing build loaded from an existing bucket to be valid: %v", err)
+ }
+
+ if existingBuild.Status != models.HashicorpCloudPackerBuildStatusUNSET {
+ t.Errorf("expected the existing build to be in the default state")
+ }
+
+ err = b.UpdateBuildStatus(context.TODO(), "happycloud.image", models.HashicorpCloudPackerBuildStatusRUNNING)
+ if err != nil {
+ t.Errorf("unexpected failure for PublishBuildStatus: %v", err)
+ }
+
+ existingBuild, err = b.Iteration.Build("happycloud.image")
+ if err != nil {
+ t.Errorf("expected the existing build loaded from an existing bucket to be valid: %v", err)
+ }
+
+ if existingBuild.Status != models.HashicorpCloudPackerBuildStatusRUNNING {
+ t.Errorf("expected the existing build to be in the running state")
+ }
+}
+
+func TestUpdateBuildStatus_DONENoImages(t *testing.T) {
+ mockService := api.NewMockPackerClientService()
+ mockService.BucketAlreadyExist = true
+ mockService.IterationAlreadyExist = true
+
+ b := &Bucket{
+ Slug: "TestBucket",
+ client: &api.Client{
+ Packer: mockService,
+ },
+ }
+
+ b.Iteration = NewIteration()
+ err := b.Iteration.Initialize()
+ if err != nil {
+ t.Errorf("unexpected failure: %v", err)
+ }
+
+ b.Iteration.expectedBuilds = append(b.Iteration.expectedBuilds, "happycloud.image")
+ mockService.ExistingBuilds = append(mockService.ExistingBuilds, "happycloud.image")
+
+ err = b.Initialize(context.TODO(), models.HashicorpCloudPackerIterationTemplateTypeHCL2)
+ if err != nil {
+ t.Errorf("unexpected failure: %v", err)
+ }
+ err = b.populateIteration(context.TODO())
+ if err != nil {
+ t.Errorf("unexpected failure: %v", err)
+ }
+
+ existingBuild, err := b.Iteration.Build("happycloud.image")
+ if err != nil {
+ t.Errorf("expected the existing build loaded from an existing bucket to be valid: %v", err)
+ }
+
+ if existingBuild.Status != models.HashicorpCloudPackerBuildStatusUNSET {
+ t.Errorf("expected the existing build to be in the default state")
+ }
+
+ //nolint:errcheck
+ b.UpdateBuildStatus(context.TODO(), "happycloud.image", models.HashicorpCloudPackerBuildStatusRUNNING)
+
+ err = b.UpdateBuildStatus(context.TODO(), "happycloud.image", models.HashicorpCloudPackerBuildStatusDONE)
+ if err == nil {
+ t.Errorf("expected failure for PublishBuildStatus when setting status to DONE with no images")
+ }
+
+ existingBuild, err = b.Iteration.Build("happycloud.image")
+ if err != nil {
+ t.Errorf("expected the existing build loaded from an existing bucket to be valid: %v", err)
+ }
+
+ if existingBuild.Status != models.HashicorpCloudPackerBuildStatusRUNNING {
+ t.Errorf("expected the existing build to be in the running state")
+ }
+}
+
+//func (b *Bucket) PublishBuildStatus(ctx context.Context, name string, status models.HashicorpCloudPackerBuildStatus) error {}
diff --git a/v1.9.4/internal/hcp/registry/types.bucket_test.go b/v1.9.4/internal/hcp/registry/types.bucket_test.go
new file mode 100644
index 0000000..30f73de
--- /dev/null
+++ b/v1.9.4/internal/hcp/registry/types.bucket_test.go
@@ -0,0 +1,387 @@
+// Copyright (c) HashiCorp, Inc.
+// SPDX-License-Identifier: MPL-2.0
+
+package registry
+
+import (
+ "context"
+ "strconv"
+ "testing"
+
+ "github.com/google/go-cmp/cmp"
+ "github.com/hashicorp/packer/hcl2template"
+ "github.com/hashicorp/packer/internal/hcp/api"
+)
+
+func createInitialTestBucket(t testing.TB) *Bucket {
+ t.Helper()
+ bucket := NewBucketWithIteration()
+ err := bucket.Iteration.Initialize()
+ if err != nil {
+ t.Errorf("failed to initialize Bucket: %s", err)
+ return nil
+ }
+
+ mockService := api.NewMockPackerClientService()
+ mockService.TrackCalledServiceMethods = false
+ bucket.Slug = "TestBucket"
+ bucket.client = &api.Client{
+ Packer: mockService,
+ }
+
+ return bucket
+}
+
+func checkError(t testing.TB, err error) {
+ t.Helper()
+
+ if err == nil {
+ return
+ }
+
+ t.Errorf("received an error during testing %s", err)
+}
+
+func TestBucket_CreateInitialBuildForIteration(t *testing.T) {
+ bucket := createInitialTestBucket(t)
+
+ componentName := "happycloud.image"
+ bucket.RegisterBuildForComponent(componentName)
+ bucket.BuildLabels = map[string]string{
+ "version": "1.7.0",
+ "based_off": "alpine",
+ }
+ err := bucket.CreateInitialBuildForIteration(context.TODO(), componentName)
+ checkError(t, err)
+
+ // Assert that a build stored on the iteration
+ build, err := bucket.Iteration.Build(componentName)
+ if err != nil {
+ t.Errorf("expected an initial build for %s to be created, but it failed", componentName)
+ }
+
+ if build.ComponentType != componentName {
+ t.Errorf("expected the initial build to have the defined component type")
+ }
+
+ if diff := cmp.Diff(build.Labels, bucket.BuildLabels); diff != "" {
+ t.Errorf("expected the initial build to have the defined build labels %v", diff)
+ }
+}
+
+func TestBucket_UpdateLabelsForBuild(t *testing.T) {
+ tc := []struct {
+ desc string
+ buildName string
+ bucketBuildLabels map[string]string
+ buildLabels map[string]string
+ labelsCount int
+ noDiffExpected bool
+ }{
+ {
+ desc: "no bucket or build specific labels",
+ buildName: "happcloud.image",
+ noDiffExpected: true,
+ },
+ {
+ desc: "bucket build labels",
+ buildName: "happcloud.image",
+ bucketBuildLabels: map[string]string{
+ "version": "1.7.0",
+ "based_off": "alpine",
+ },
+ labelsCount: 2,
+ noDiffExpected: true,
+ },
+ {
+ desc: "bucket build labels and build specific label",
+ buildName: "happcloud.image",
+ bucketBuildLabels: map[string]string{
+ "version": "1.7.0",
+ "based_off": "alpine",
+ },
+ buildLabels: map[string]string{
+ "source_image": "another-happycloud-image",
+ },
+ labelsCount: 3,
+ noDiffExpected: false,
+ },
+ {
+ desc: "build specific label",
+ buildName: "happcloud.image",
+ buildLabels: map[string]string{
+ "source_image": "another-happycloud-image",
+ },
+ labelsCount: 1,
+ noDiffExpected: false,
+ },
+ }
+
+ for _, tt := range tc {
+ tt := tt
+ t.Run(tt.desc, func(t *testing.T) {
+ bucket := createInitialTestBucket(t)
+
+ componentName := tt.buildName
+ bucket.RegisterBuildForComponent(componentName)
+
+ for k, v := range tt.bucketBuildLabels {
+ bucket.BuildLabels[k] = v
+ }
+
+ err := bucket.CreateInitialBuildForIteration(context.TODO(), componentName)
+ checkError(t, err)
+
+ // Assert that the build is stored on the iteration
+ build, err := bucket.Iteration.Build(componentName)
+ if err != nil {
+ t.Errorf("expected an initial build for %s to be created, but it failed", componentName)
+ }
+
+ if build.ComponentType != componentName {
+ t.Errorf("expected the build to have the defined component type")
+ }
+
+ err = bucket.UpdateLabelsForBuild(componentName, tt.buildLabels)
+ checkError(t, err)
+
+ if len(build.Labels) != tt.labelsCount {
+ t.Errorf("expected the build to have %d build labels but there is only: %d", tt.labelsCount, len(build.Labels))
+ }
+
+ diff := cmp.Diff(build.Labels, bucket.BuildLabels)
+ if (diff == "") != tt.noDiffExpected {
+ t.Errorf("expected the build to have an additional build label but there is no diff: %q", diff)
+ }
+
+ })
+ }
+}
+
+func TestBucket_UpdateLabelsForBuild_withMultipleBuilds(t *testing.T) {
+ bucket := createInitialTestBucket(t)
+
+ firstComponent := "happycloud.image"
+ bucket.RegisterBuildForComponent(firstComponent)
+
+ secondComponent := "happycloud.image2"
+ bucket.RegisterBuildForComponent(secondComponent)
+
+ err := bucket.populateIteration(context.TODO())
+ checkError(t, err)
+
+ err = bucket.UpdateLabelsForBuild(firstComponent, map[string]string{
+ "source_image": "another-happycloud-image",
+ })
+ checkError(t, err)
+
+ err = bucket.UpdateLabelsForBuild(secondComponent, map[string]string{
+ "source_image": "the-original-happycloud-image",
+ "role_name": "no-role-is-a-good-role",
+ })
+ checkError(t, err)
+
+ var registeredBuilds []*Build
+ expectedComponents := []string{firstComponent, secondComponent}
+ for _, componentName := range expectedComponents {
+ // Assert that a build stored on the iteration
+ build, err := bucket.Iteration.Build(componentName)
+ if err != nil {
+ t.Errorf("expected an initial build for %s to be created, but it failed", componentName)
+ }
+ registeredBuilds = append(registeredBuilds, build)
+
+ if build.ComponentType != componentName {
+ t.Errorf("expected the initial build to have the defined component type")
+ }
+
+ if ok := cmp.Equal(build.Labels, bucket.BuildLabels); ok {
+ t.Errorf("expected the build to have an additional build label but they are equal")
+ }
+ }
+
+ if len(registeredBuilds) != 2 {
+ t.Errorf("expected the bucket to have 2 registered builds but got %d", len(registeredBuilds))
+ }
+
+ if ok := cmp.Equal(registeredBuilds[0].Labels, registeredBuilds[1].Labels); ok {
+ t.Errorf("expected registered builds to have different labels but they are equal")
+ }
+}
+
+func TestBucket_PopulateIteration(t *testing.T) {
+ tc := []struct {
+ desc string
+ buildName string
+ bucketBuildLabels map[string]string
+ buildLabels map[string]string
+ labelsCount int
+ buildCompleted bool
+ noDiffExpected bool
+ }{
+ {
+ desc: "populating iteration with existing incomplete build and no bucket build labels does nothing",
+ buildName: "happcloud.image",
+ labelsCount: 0,
+ buildCompleted: false,
+ noDiffExpected: true,
+ },
+ {
+ desc: "populating iteration with existing incomplete build should add bucket build labels",
+ buildName: "happcloud.image",
+ bucketBuildLabels: map[string]string{
+ "version": "1.7.0",
+ "based_off": "alpine",
+ },
+ labelsCount: 2,
+ buildCompleted: false,
+ noDiffExpected: true,
+ },
+ {
+ desc: "populating iteration with existing incomplete build should update bucket build labels",
+ buildName: "happcloud.image",
+ bucketBuildLabels: map[string]string{
+ "version": "1.7.3",
+ "based_off": "alpine-3.14",
+ },
+ buildLabels: map[string]string{
+ "version": "packer.version",
+ "based_off": "var.distro",
+ },
+ labelsCount: 2,
+ buildCompleted: false,
+ noDiffExpected: true,
+ },
+ {
+ desc: "populating iteration with completed build should not modify any labels",
+ buildName: "happcloud.image",
+ bucketBuildLabels: map[string]string{
+ "version": "1.7.0",
+ "based_off": "alpine",
+ },
+ labelsCount: 0,
+ buildCompleted: true,
+ noDiffExpected: false,
+ },
+ {
+ desc: "populating iteration with existing build should only modify bucket build labels",
+ buildName: "happcloud.image",
+ bucketBuildLabels: map[string]string{
+ "version": "1.7.3",
+ "based_off": "alpine-3.14",
+ },
+ buildLabels: map[string]string{
+ "arch": "linux/386",
+ },
+ labelsCount: 3,
+ buildCompleted: false,
+ noDiffExpected: false,
+ },
+ }
+
+ for i, tt := range tc {
+ tt := tt
+ t.Run(tt.desc, func(t *testing.T) {
+
+ t.Setenv("HCP_PACKER_BUILD_FINGERPRINT", "test-run-"+strconv.Itoa(i))
+
+ mockService := api.NewMockPackerClientService()
+ mockService.BucketAlreadyExist = true
+ mockService.IterationAlreadyExist = true
+ mockService.BuildAlreadyDone = tt.buildCompleted
+
+ bucket := NewBucketWithIteration()
+ err := bucket.Iteration.Initialize()
+ if err != nil {
+ t.Fatalf("failed when calling NewBucketWithIteration: %s", err)
+ }
+
+ bucket.Slug = "TestBucket"
+ bucket.client = &api.Client{
+ Packer: mockService,
+ }
+ for k, v := range tt.bucketBuildLabels {
+ bucket.BuildLabels[k] = v
+ }
+
+ componentName := "happycloud.image"
+ bucket.RegisterBuildForComponent(componentName)
+
+ mockService.ExistingBuilds = append(mockService.ExistingBuilds, componentName)
+ mockService.ExistingBuildLabels = tt.buildLabels
+
+ err = bucket.populateIteration(context.TODO())
+ checkError(t, err)
+
+ if mockService.CreateBuildCalled {
+ t.Errorf("expected an initial build for %s to already exist, but it called CreateBuild", componentName)
+ }
+ // Assert that a build stored on the iteration
+ build, err := bucket.Iteration.Build(componentName)
+ if err != nil {
+ t.Errorf("expected an existing build for %s to be stored, but it failed", componentName)
+ }
+
+ if build.ComponentType != componentName {
+ t.Errorf("expected the build to have the defined component type")
+ }
+
+ if len(build.Labels) != tt.labelsCount {
+ t.Errorf("expected the build to have %d build labels but there is only: %d", tt.labelsCount, len(build.Labels))
+ }
+
+ diff := cmp.Diff(build.Labels, bucket.BuildLabels)
+ if (diff == "") != tt.noDiffExpected {
+ t.Errorf("expected the build to have bucket build labels but there is no diff: %q", diff)
+ }
+ })
+ }
+}
+
+func TestReadFromHCLBuildBlock(t *testing.T) {
+ tc := []struct {
+ desc string
+ buildBlock *hcl2template.BuildBlock
+ expectedBucket *Bucket
+ }{
+ {
+ desc: "configure bucket using only hcp_packer_registry block",
+ buildBlock: &hcl2template.BuildBlock{
+ HCPPackerRegistry: &hcl2template.HCPPackerRegistryBlock{
+ Slug: "hcp_packer_registry-block-test",
+ Description: "description from hcp_packer_registry block",
+ BucketLabels: map[string]string{
+ "org": "test",
+ },
+ BuildLabels: map[string]string{
+ "version": "1.7.0",
+ "based_off": "alpine",
+ },
+ },
+ },
+ expectedBucket: &Bucket{
+ Slug: "hcp_packer_registry-block-test",
+ Description: "description from hcp_packer_registry block",
+ BucketLabels: map[string]string{
+ "org": "test",
+ },
+ BuildLabels: map[string]string{
+ "version": "1.7.0",
+ "based_off": "alpine",
+ },
+ },
+ },
+ }
+ for _, tt := range tc {
+ tt := tt
+ t.Run(tt.desc, func(t *testing.T) {
+ bucket := &Bucket{}
+ bucket.ReadFromHCLBuildBlock(tt.buildBlock)
+
+ diff := cmp.Diff(bucket, tt.expectedBucket, cmp.AllowUnexported(Bucket{}))
+ if diff != "" {
+ t.Errorf("expected the build to to have contents of hcp_packer_registry block but it does not: %v", diff)
+ }
+ })
+ }
+}
diff --git a/v1.9.4/internal/hcp/registry/types.builds.go b/v1.9.4/internal/hcp/registry/types.builds.go
new file mode 100644
index 0000000..9245a9d
--- /dev/null
+++ b/v1.9.4/internal/hcp/registry/types.builds.go
@@ -0,0 +1,108 @@
+// Copyright (c) HashiCorp, Inc.
+// SPDX-License-Identifier: MPL-2.0
+
+package registry
+
+import (
+ "fmt"
+
+ "github.com/hashicorp/hcp-sdk-go/clients/cloud-packer-service/stable/2021-04-30/models"
+ registryimage "github.com/hashicorp/packer-plugin-sdk/packer/registry/image"
+)
+
+// Build represents a build of a given component type for some bucket on the HCP Packer Registry.
+type Build struct {
+ ID string
+ CloudProvider string
+ ComponentType string
+ RunUUID string
+ Labels map[string]string
+ Images map[string]registryimage.Image
+ Status models.HashicorpCloudPackerBuildStatus
+}
+
+// NewBuildFromCloudPackerBuild converts a HashicorpCloudePackerBuild to a local build that can be tracked and published to the HCP Packer Registry.
+// Any existing labels or images associated to src will be copied to the returned Build.
+func NewBuildFromCloudPackerBuild(src *models.HashicorpCloudPackerBuild) (*Build, error) {
+
+ build := Build{
+ ID: src.ID,
+ ComponentType: src.ComponentType,
+ CloudProvider: src.CloudProvider,
+ RunUUID: src.PackerRunUUID,
+ Status: *src.Status,
+ Labels: src.Labels,
+ }
+
+ var err error
+ for _, image := range src.Images {
+ image := image
+ err = build.AddImages(registryimage.Image{
+ ImageID: image.ImageID,
+ ProviderName: build.CloudProvider,
+ ProviderRegion: image.Region,
+ })
+
+ if err != nil {
+ return nil, fmt.Errorf("NewBuildFromCloudPackerBuild: %w", err)
+ }
+ }
+
+ return &build, nil
+}
+
+// AddLabelsToBuild merges the contents of data to the labels associated with the build.
+// Duplicate keys will be updated to reflect the new value.
+func (b *Build) MergeLabels(data map[string]string) {
+ if data == nil {
+ return
+ }
+
+ if b.Labels == nil {
+ b.Labels = make(map[string]string)
+ }
+
+ for k, v := range data {
+ // TODO: (nywilken) Determine why we skip labels already set
+ //if _, ok := build.Labels[k]; ok {
+ //continue
+ //}
+ b.Labels[k] = v
+ }
+
+}
+
+// AddImages appends one or more images artifacts to the build.
+func (b *Build) AddImages(images ...registryimage.Image) error {
+
+ if b.Images == nil {
+ b.Images = make(map[string]registryimage.Image)
+ }
+
+ for _, image := range images {
+ image := image
+
+ if err := image.Validate(); err != nil {
+ return fmt.Errorf("AddImages: failed to add image to build %q: %w", b.ComponentType, err)
+ }
+
+ if b.CloudProvider == "" {
+ b.CloudProvider = image.ProviderName
+ }
+
+ b.MergeLabels(image.Labels)
+ b.Images[image.String()] = image
+ }
+
+ return nil
+}
+
+// IsNotDone returns true if build does not satisfy all requirements of a completed build.
+// A completed build must have a valid ID, one or more Images, and its Status is HashicorpCloudPackerBuildStatusDONE.
+func (b *Build) IsNotDone() bool {
+ hasBuildID := b.ID != ""
+ hasNoImages := len(b.Images) == 0
+ isNotDone := b.Status != models.HashicorpCloudPackerBuildStatusDONE
+
+ return hasBuildID && hasNoImages && isNotDone
+}
diff --git a/v1.9.4/internal/hcp/registry/types.iterations.go b/v1.9.4/internal/hcp/registry/types.iterations.go
new file mode 100644
index 0000000..b9ffc23
--- /dev/null
+++ b/v1.9.4/internal/hcp/registry/types.iterations.go
@@ -0,0 +1,177 @@
+// Copyright (c) HashiCorp, Inc.
+// SPDX-License-Identifier: MPL-2.0
+
+package registry
+
+import (
+ "errors"
+ "fmt"
+ "math/rand"
+ "os"
+ "strings"
+ "sync"
+ "time"
+
+ "github.com/hashicorp/hcp-sdk-go/clients/cloud-packer-service/stable/2021-04-30/models"
+ sdkpacker "github.com/hashicorp/packer-plugin-sdk/packer"
+ registryimage "github.com/hashicorp/packer-plugin-sdk/packer/registry/image"
+ "github.com/hashicorp/packer/internal/hcp/env"
+ "github.com/oklog/ulid"
+)
+
+type Iteration struct {
+ ID string
+ AncestorSlug string
+ Fingerprint string
+ RunUUID string
+ builds sync.Map
+ expectedBuilds []string
+}
+
+type IterationOptions struct {
+ TemplateBaseDir string
+}
+
+// NewIteration returns a pointer to an Iteration that can be used for storing Packer build details needed by PAR.
+func NewIteration() *Iteration {
+ i := Iteration{
+ expectedBuilds: make([]string, 0),
+ }
+
+ return &i
+}
+
+// Initialize prepares the iteration to be used with an active HCP Packer registry bucket.
+func (i *Iteration) Initialize() error {
+ if i == nil {
+ return errors.New("Unexpected call to initialize for a nil Iteration")
+ }
+
+ // By default we try to load a Fingerprint from the environment variable.
+ // If no variable is defined we generate a new fingerprint.
+ i.Fingerprint = os.Getenv(env.HCPPackerBuildFingerprint)
+
+ if i.Fingerprint != "" {
+ return nil
+ }
+
+ fp, err := ulid.New(ulid.Now(), ulid.Monotonic(rand.New(rand.NewSource(time.Now().UnixNano())), 0))
+ if err != nil {
+ return fmt.Errorf("Failed to generate a fingerprint: %s", err)
+ }
+ i.Fingerprint = fp.String()
+
+ return nil
+}
+
+// StoreBuild stores a build for buildName to an active iteration.
+func (i *Iteration) StoreBuild(buildName string, build *Build) {
+ i.builds.Store(buildName, build)
+}
+
+// Build gets the store build associated with buildName in the active iteration.
+func (i *Iteration) Build(buildName string) (*Build, error) {
+ build, ok := i.builds.Load(buildName)
+ if !ok {
+ return nil, errors.New("no associated build found for the name " + buildName)
+ }
+
+ b, ok := build.(*Build)
+ if !ok {
+ return nil, fmt.Errorf("the build for the component %q does not appear to be a valid registry Build", buildName)
+ }
+
+ return b, nil
+}
+
+// HasBuild checks if iteration has a stored build associated with buildName.
+func (i *Iteration) HasBuild(buildName string) bool {
+ _, ok := i.builds.Load(buildName)
+
+ return ok
+}
+
+// AddImageToBuild appends one or more images artifacts to the build referred to by buildName.
+func (i *Iteration) AddImageToBuild(buildName string, images ...registryimage.Image) error {
+ build, err := i.Build(buildName)
+ if err != nil {
+ return fmt.Errorf("AddImageToBuild: %w", err)
+ }
+
+ err = build.AddImages(images...)
+ if err != nil {
+ return fmt.Errorf("AddImageToBuild: %w", err)
+ }
+
+ i.StoreBuild(buildName, build)
+ return nil
+}
+
+// AddLabelsToBuild merges the contents of data to the labels associated with the build referred to by buildName.
+func (i *Iteration) AddLabelsToBuild(buildName string, data map[string]string) error {
+ build, err := i.Build(buildName)
+ if err != nil {
+ return fmt.Errorf("AddLabelsToBuild: %w", err)
+ }
+
+ build.MergeLabels(data)
+
+ i.StoreBuild(buildName, build)
+ return nil
+}
+
+// AddSHAToBuildLabels adds the Git SHA for the current iteration (if set) as a label for all the builds of the iteration
+func (i *Iteration) AddSHAToBuildLabels(sha string) {
+ i.builds.Range(func(_, v any) bool {
+ b, ok := v.(*Build)
+ if !ok {
+ return true
+ }
+
+ b.MergeLabels(map[string]string{
+ "git_sha": sha,
+ })
+
+ return true
+ })
+}
+
+// RemainingBuilds returns the list of builds that are not in a DONE status
+func (i *Iteration) RemainingBuilds() []*Build {
+ var todo []*Build
+
+ i.builds.Range(func(k, v any) bool {
+ build, ok := v.(*Build)
+ if !ok {
+ // Unlikely since the builds map contains only Build instances
+ return true
+ }
+
+ if build.Status != models.HashicorpCloudPackerBuildStatusDONE {
+ todo = append(todo, build)
+ }
+ return true
+ })
+
+ return todo
+}
+
+func (i *Iteration) iterationStatusSummary(ui sdkpacker.Ui) {
+ rem := i.RemainingBuilds()
+ if rem == nil {
+ return
+ }
+
+ buf := &strings.Builder{}
+
+ buf.WriteString(fmt.Sprintf(
+ "\nIteration %q is not complete, the following builds are not done:\n\n",
+ i.Fingerprint))
+ for _, b := range rem {
+ buf.WriteString(fmt.Sprintf("* %q: %s\n", b.ComponentType, b.Status))
+ }
+ buf.WriteString("\nYou may resume work on this iteration in further Packer builds by defining the following variable in your environment:\n")
+ buf.WriteString(fmt.Sprintf("HCP_PACKER_BUILD_FINGERPRINT=%q", i.Fingerprint))
+
+ ui.Say(buf.String())
+}
diff --git a/v1.9.4/internal/hcp/registry/types.iterations_test.go b/v1.9.4/internal/hcp/registry/types.iterations_test.go
new file mode 100644
index 0000000..fe7132d
--- /dev/null
+++ b/v1.9.4/internal/hcp/registry/types.iterations_test.go
@@ -0,0 +1,87 @@
+// Copyright (c) HashiCorp, Inc.
+// SPDX-License-Identifier: MPL-2.0
+
+package registry
+
+import (
+ "os"
+ "path"
+ "testing"
+
+ git "github.com/go-git/go-git/v5"
+)
+
+func TestIteration_Initialize(t *testing.T) {
+ var tc = []struct {
+ name string
+ fingerprint string
+ setupFn func(t *testing.T)
+ errorExpected bool
+ }{
+ {
+ name: "using fingerprint env variable",
+ fingerprint: "6825d1ad0d5e",
+ setupFn: func(t *testing.T) {
+ t.Setenv("HCP_PACKER_BUILD_FINGERPRINT", "6825d1ad0d5e")
+ },
+ },
+ {
+ name: "using git fingerprint",
+ fingerprint: "4ec004e18e977a5b8a3a28f4b24279b6993d7e7c",
+ setupFn: func(t *testing.T) {
+ //nolint:errcheck
+ git.PlainClone(tempdir("4ec004e18e"), false, &git.CloneOptions{
+ // Archived repo
+ URL: "https://github.com/hashicorp/packer-builder-vsphere",
+ Depth: 1,
+ })
+
+ t.Setenv("HCP_PACKER_BUILD_FINGERPRINT", "4ec004e18e977a5b8a3a28f4b24279b6993d7e7c")
+
+ t.Cleanup(func() {
+ //nolint:errcheck
+ os.RemoveAll(tempdir("4ec004e18e"))
+ })
+ },
+ },
+ {
+ name: "using no fingerprint in clean directory",
+ },
+ }
+
+ for _, tt := range tc {
+ tt := tt
+ t.Run(tt.name, func(t *testing.T) {
+ if tt.setupFn != nil {
+ tt.setupFn(t)
+ }
+
+ i := NewIteration()
+ err := i.Initialize()
+ if tt.errorExpected {
+ t.Logf("%v", err)
+ if err == nil {
+ t.Errorf("expected %q to result in an error, but it return no error", tt.name)
+ }
+
+ if i.Fingerprint != "" {
+ t.Errorf("expected %q to result in an error with an empty iteration fingerprint, but got %q", tt.name, i.Fingerprint)
+ }
+ return
+ }
+
+ if err != nil {
+ t.Errorf("expected %q to return with no error, but it %v", tt.name, err)
+ }
+
+ if tt.fingerprint != "" && i.Fingerprint != tt.fingerprint {
+ t.Errorf("%q failed to load the expected fingerprint %q, but got %q", tt.name, tt.fingerprint, i.Fingerprint)
+ }
+
+ })
+ }
+}
+
+func tempdir(dirname string) string {
+ return path.Join(os.TempDir(), dirname)
+}
diff --git a/v1.9.4/log.go b/v1.9.4/log.go
new file mode 100644
index 0000000..2c15a70
--- /dev/null
+++ b/v1.9.4/log.go
@@ -0,0 +1,95 @@
+// Copyright (c) HashiCorp, Inc.
+// SPDX-License-Identifier: MPL-2.0
+
+package main
+
+import (
+ "bufio"
+ "bytes"
+ "fmt"
+ "io"
+ "os"
+ "strings"
+)
+
+// These are the environmental variables that determine if we log, and if
+// we log whether or not the log should go to a file.
+const EnvLog = "PACKER_LOG" //Set to True
+const EnvLogFile = "PACKER_LOG_PATH" //Set to a file
+
+// logOutput determines where we should send logs (if anywhere).
+func logOutput() (logOutput io.Writer, err error) {
+ logOutput = nil
+ if os.Getenv(EnvLog) != "" && os.Getenv(EnvLog) != "0" {
+ logOutput = os.Stderr
+
+ if logPath := os.Getenv(EnvLogFile); logPath != "" {
+ var err error
+ logOutput, err = os.Create(logPath)
+ if err != nil {
+ return nil, err
+ }
+ } else {
+ // no path; do a little light filtering to avoid double-dipping UI
+ // calls.
+ r, w := io.Pipe()
+ scanner := bufio.NewScanner(r)
+ scanner.Split(ScanLinesSmallerThanBuffer)
+
+ go func(scanner *bufio.Scanner) {
+ for scanner.Scan() {
+ if strings.Contains(scanner.Text(), "ui:") {
+ continue
+ }
+ if strings.Contains(scanner.Text(), "ui error:") {
+ continue
+ }
+ os.Stderr.WriteString(fmt.Sprint(scanner.Text() + "\n"))
+ }
+ if err := scanner.Err(); err != nil {
+ os.Stderr.WriteString(err.Error())
+ w.Close()
+ }
+ }(scanner)
+ logOutput = w
+ }
+ }
+
+ return
+}
+
+// The below functions come from bufio.Scanner with a small tweak, to fix an
+// edgecase where the default ScanFunc fails: sometimes, if someone tries to
+// log a line that is longer than 64*1024 bytes long before it contains a
+// newline, the ScanLine will continue to return, requesting more data from the
+// buffer, which can't increase in size anymore, causing a hang.
+func dropCR(data []byte) []byte {
+ if len(data) > 0 && data[len(data)-1] == '\r' {
+ return data[0 : len(data)-1]
+ }
+ return data
+}
+
+func ScanLinesSmallerThanBuffer(data []byte, atEOF bool) (advance int, token []byte, err error) {
+ if atEOF && len(data) == 0 {
+ return 0, nil, nil
+ }
+ if i := bytes.IndexByte(data, '\n'); i >= 0 {
+ // We have a full newline-terminated line.
+ return i + 1, dropCR(data[0:i]), nil
+ }
+ // If we're at EOF, we have a final, non-terminated line. Return it.
+ if atEOF {
+ return len(data), dropCR(data), nil
+ }
+
+ // Our tweak:
+ // Buffer is full, so we can't get more data. Just return what we have as
+ // its own token so we can keep going, even though there's no newline.
+ if len(data)+1 >= bufio.MaxScanTokenSize {
+ return len(data), data[0 : len(data)-1], nil
+ }
+
+ // Request more data.
+ return 0, nil, nil
+}
diff --git a/v1.9.4/main.go b/v1.9.4/main.go
new file mode 100644
index 0000000..e8da068
--- /dev/null
+++ b/v1.9.4/main.go
@@ -0,0 +1,423 @@
+// Copyright (c) HashiCorp, Inc.
+// SPDX-License-Identifier: MPL-2.0
+
+// This is the main package for the `packer` application.
+
+//go:generate go run ./scripts/generate-plugins.go
+package main
+
+import (
+ "fmt"
+ "io"
+ "io/ioutil"
+ "log"
+ "math/rand"
+ "os"
+ "runtime"
+ "sync"
+ "syscall"
+ "time"
+
+ "github.com/hashicorp/go-uuid"
+ packersdk "github.com/hashicorp/packer-plugin-sdk/packer"
+ "github.com/hashicorp/packer-plugin-sdk/pathing"
+ pluginsdk "github.com/hashicorp/packer-plugin-sdk/plugin"
+ "github.com/hashicorp/packer-plugin-sdk/tmp"
+ "github.com/hashicorp/packer/command"
+ "github.com/hashicorp/packer/packer"
+ "github.com/hashicorp/packer/version"
+ "github.com/mitchellh/cli"
+ "github.com/mitchellh/panicwrap"
+ "github.com/mitchellh/prefixedio"
+)
+
+func main() {
+ // Call realMain instead of doing the work here so we can use
+ // `defer` statements within the function and have them work properly.
+ // (defers aren't called with os.Exit)
+ os.Exit(realMain())
+}
+
+// realMain is executed from main and returns the exit status to exit with.
+func realMain() int {
+ var wrapConfig panicwrap.WrapConfig
+ // When following env variable is set, packer
+ // wont panic wrap itself as it's already wrapped.
+ // i.e.: when terraform runs it.
+ wrapConfig.CookieKey = "PACKER_WRAP_COOKIE"
+ wrapConfig.CookieValue = "49C22B1A-3A93-4C98-97FA-E07D18C787B5"
+
+ if inPlugin() || panicwrap.Wrapped(&wrapConfig) {
+ // Call the real main
+ return wrappedMain()
+ }
+
+ // Generate a UUID for this packer run and pass it to the environment.
+ // GenerateUUID always returns a nil error (based on rand.Read) so we'll
+ // just ignore it.
+ UUID, _ := uuid.GenerateUUID()
+ os.Setenv("PACKER_RUN_UUID", UUID)
+
+ // Determine where logs should go in general (requested by the user)
+ logWriter, err := logOutput()
+ if err != nil {
+ fmt.Fprintf(os.Stderr, "Couldn't setup log output: %s", err)
+ return 1
+ }
+ if logWriter == nil {
+ logWriter = ioutil.Discard
+ }
+
+ packersdk.LogSecretFilter.SetOutput(logWriter)
+
+ // Disable logging here
+ log.SetOutput(ioutil.Discard)
+
+ // We always send logs to a temporary file that we use in case
+ // there is a panic. Otherwise, we delete it.
+ logTempFile, err := tmp.File("packer-log")
+ if err != nil {
+ fmt.Fprintf(os.Stderr, "Couldn't setup logging tempfile: %s", err)
+ return 1
+ }
+ defer os.Remove(logTempFile.Name())
+ defer logTempFile.Close()
+
+ // Setup the prefixed readers that send data properly to
+ // stdout/stderr.
+ doneCh := make(chan struct{})
+ outR, outW := io.Pipe()
+ go copyOutput(outR, doneCh)
+
+ // Enable checkpoint for panic reporting
+ if config, _ := loadConfig(); config != nil && !config.DisableCheckpoint {
+ packer.CheckpointReporter = packer.NewCheckpointReporter(
+ config.DisableCheckpointSignature,
+ )
+ }
+
+ // Create the configuration for panicwrap and wrap our executable
+ wrapConfig.Handler = panicHandler(logTempFile)
+ wrapConfig.Writer = io.MultiWriter(logTempFile, &packersdk.LogSecretFilter)
+ wrapConfig.Stdout = outW
+ wrapConfig.DetectDuration = 500 * time.Millisecond
+ wrapConfig.ForwardSignals = []os.Signal{syscall.SIGTERM}
+ exitStatus, err := panicwrap.Wrap(&wrapConfig)
+ if err != nil {
+ fmt.Fprintf(os.Stderr, "Couldn't start Packer: %s", err)
+ return 1
+ }
+
+ // If >= 0, we're the parent, so just exit
+ if exitStatus >= 0 {
+ // Close the stdout writer so that our copy process can finish
+ outW.Close()
+
+ // Wait for the output copying to finish
+ <-doneCh
+
+ return exitStatus
+ }
+
+ // We're the child, so just close the tempfile we made in order to
+ // save file handles since the tempfile is only used by the parent.
+ logTempFile.Close()
+
+ return 0
+}
+
+// wrappedMain is called only when we're wrapped by panicwrap and
+// returns the exit status to exit with.
+func wrappedMain() int {
+ // WARNING: WrappedMain causes unexpected behaviors when writing to stderr
+ // and stdout. Anything in this function written to stderr will be captured
+ // by the logger, but will not be written to the terminal. Anything in
+ // this function written to standard out must be prefixed with ErrorPrefix
+ // or OutputPrefix to be sent to the right terminal stream, but adding
+ // these prefixes can cause nondeterministic results for output from
+ // other, asynchronous methods. Try to avoid modifying output in this
+ // function if at all possible.
+
+ // If there is no explicit number of Go threads to use, then set it
+ if os.Getenv("GOMAXPROCS") == "" {
+ runtime.GOMAXPROCS(runtime.NumCPU())
+ }
+
+ packersdk.LogSecretFilter.SetOutput(os.Stderr)
+ log.SetOutput(&packersdk.LogSecretFilter)
+
+ inPlugin := inPlugin()
+ if inPlugin {
+ // This prevents double-logging timestamps
+ log.SetFlags(0)
+ }
+
+ log.Printf("[INFO] Packer version: %s [%s %s %s]",
+ version.FormattedVersion(),
+ runtime.Version(),
+ runtime.GOOS, runtime.GOARCH)
+
+ // The config being loaded here is the Packer config -- it defines
+ // the location of third party builder plugins, plugin ports to use, and
+ // whether to disable telemetry. It is a global config.
+ // Do not confuse this config with the .json Packer template which gets
+ // passed into commands like `packer build`
+ config, err := loadConfig()
+ if err != nil {
+ // Writing to Stdout here so that the error message bypasses panicwrap. By using the
+ // ErrorPrefix this output will be redirected to Stderr by the copyOutput func.
+ // TODO: nywilken need to revisit this setup to better output errors to Stderr, and output to Stdout
+ // without panicwrap
+ fmt.Fprintf(os.Stdout, "%s Error loading configuration: \n\n%s\n", ErrorPrefix, err)
+ return 1
+ }
+
+ // Fire off the checkpoint.
+ go runCheckpoint(config)
+ if !config.DisableCheckpoint {
+ packer.CheckpointReporter = packer.NewCheckpointReporter(
+ config.DisableCheckpointSignature,
+ )
+ }
+
+ cacheDir, err := packersdk.CachePath()
+ if err != nil {
+ // Writing to Stdout here so that the error message bypasses panicwrap. By using the
+ // ErrorPrefix this output will be redirected to Stderr by the copyOutput func.
+ // TODO: nywilken need to revisit this setup to better output errors to Stderr, and output to Stdout
+ // without panicwrap
+ fmt.Fprintf(os.Stdout, "%s Error preparing cache directory: \n\n%s\n", ErrorPrefix, err)
+ return 1
+ }
+ log.Printf("[INFO] Setting cache directory: %s", cacheDir)
+
+ // Determine if we're in machine-readable mode by mucking around with
+ // the arguments...
+ args, machineReadable := extractMachineReadable(os.Args[1:])
+
+ defer packer.CleanupClients()
+
+ var ui packersdk.Ui
+ if machineReadable {
+ // Setup the UI as we're being machine-readable
+ ui = &packer.MachineReadableUi{
+ Writer: os.Stdout,
+ }
+
+ // Set this so that we don't get colored output in our machine-
+ // readable UI.
+ if err := os.Setenv("PACKER_NO_COLOR", "1"); err != nil {
+ // Outputting error using Ui here to conform to the machine readable format.
+ ui.Error(fmt.Sprintf("Packer failed to initialize UI: %s\n", err))
+ return 1
+ }
+ } else {
+ basicUi := &packersdk.BasicUi{
+ Reader: os.Stdin,
+ Writer: os.Stdout,
+ ErrorWriter: os.Stdout,
+ PB: &packersdk.NoopProgressTracker{},
+ }
+ ui = basicUi
+ if !inPlugin {
+ currentPID := os.Getpid()
+ backgrounded, err := checkProcess(currentPID)
+ if err != nil {
+ // Writing to Stderr will ensure that the output gets captured by panicwrap.
+ // This error message and any other message writing to Stderr after this point will only show up with PACKER_LOG=1
+ // TODO: nywilken need to revisit this setup to better output errors to Stderr, and output to Stdout without panicwrap.
+ fmt.Fprintf(os.Stderr, "%s cannot determine if process is in background: %s\n", ErrorPrefix, err)
+ }
+
+ if backgrounded {
+ fmt.Fprintf(os.Stderr, "%s Running in background, not using a TTY\n", ErrorPrefix)
+ } else if TTY, err := openTTY(); err != nil {
+ fmt.Fprintf(os.Stderr, "%s No tty available: %s\n", ErrorPrefix, err)
+ } else {
+ basicUi.TTY = TTY
+ basicUi.PB = &packer.UiProgressBar{}
+ defer TTY.Close()
+ }
+ }
+ }
+ // Create the CLI meta
+ CommandMeta = &command.Meta{
+ CoreConfig: &packer.CoreConfig{
+ Components: packer.ComponentFinder{
+ Hook: config.StarHook,
+ PluginConfig: config.Plugins,
+ },
+ Version: version.Version,
+ },
+ Ui: ui,
+ }
+
+ cli := &cli.CLI{
+ Args: args,
+ Autocomplete: true,
+ Commands: Commands,
+ HelpFunc: excludeHelpFunc(Commands, []string{"plugin"}),
+ HelpWriter: os.Stdout,
+ Name: "packer",
+ Version: version.Version,
+ }
+
+ exitCode, err := cli.Run()
+ if !inPlugin {
+ if err := packer.CheckpointReporter.Finalize(cli.Subcommand(), exitCode, err); err != nil {
+ log.Printf("[WARN] (telemetry) Error finalizing report. This is safe to ignore. %s", err.Error())
+ }
+ }
+
+ if err != nil {
+ // Writing to Stdout here so that the error message bypasses panicwrap. By using the
+ // ErrorPrefix this output will be redirected to Stderr by the copyOutput func.
+ // TODO: nywilken need to revisit this setup to better output errors to Stderr, and output to Stdout
+ // without panicwrap
+ fmt.Fprintf(os.Stdout, "%s Error executing CLI: %s\n", ErrorPrefix, err)
+ return 1
+ }
+
+ return exitCode
+}
+
+// excludeHelpFunc filters commands we don't want to show from the list of
+// commands displayed in packer's help text.
+func excludeHelpFunc(commands map[string]cli.CommandFactory, exclude []string) cli.HelpFunc {
+ // Make search slice into a map so we can use use the `if found` idiom
+ // instead of a nested loop.
+ var excludes = make(map[string]interface{}, len(exclude))
+ for _, item := range exclude {
+ excludes[item] = nil
+ }
+
+ // Create filtered list of commands
+ helpCommands := []string{}
+ for command := range commands {
+ if _, found := excludes[command]; !found {
+ helpCommands = append(helpCommands, command)
+ }
+ }
+
+ return cli.FilteredHelpFunc(helpCommands, cli.BasicHelpFunc("packer"))
+}
+
+// extractMachineReadable checks the args for the machine readable
+// flag and returns whether or not it is on. It modifies the args
+// to remove this flag.
+func extractMachineReadable(args []string) ([]string, bool) {
+ for i, arg := range args {
+ if arg == "-machine-readable" {
+ // We found it. Slice it out.
+ result := make([]string, len(args)-1)
+ copy(result, args[:i])
+ copy(result[i:], args[i+1:])
+ return result, true
+ }
+ }
+
+ return args, false
+}
+
+func loadConfig() (*config, error) {
+ var config config
+ config.Plugins = &packer.PluginConfig{
+ PluginMinPort: 10000,
+ PluginMaxPort: 25000,
+ KnownPluginFolders: packer.PluginFolders("."),
+ }
+ if err := config.Plugins.Discover(); err != nil {
+ return nil, err
+ }
+
+ // Finally, try to use an internal plugin. Note that this will not override
+ // any previously-loaded plugins.
+ if err := config.discoverInternalComponents(); err != nil {
+ return nil, err
+ }
+
+ // start by loading from PACKER_CONFIG if available
+ configFilePath := os.Getenv("PACKER_CONFIG")
+ if configFilePath == "" {
+ var err error
+ log.Print("[INFO] PACKER_CONFIG env var not set; checking the default config file path")
+ configFilePath, err = pathing.ConfigFile()
+ if err != nil {
+ log.Printf("Error detecting default config file path: %s", err)
+ }
+ }
+ if configFilePath == "" {
+ return &config, nil
+ }
+ log.Printf("[INFO] PACKER_CONFIG env var set; attempting to open config file: %s", configFilePath)
+ f, err := os.Open(configFilePath)
+ if err != nil {
+ if !os.IsNotExist(err) {
+ return nil, err
+ }
+
+ log.Printf("[WARN] Config file doesn't exist: %s", configFilePath)
+ return &config, nil
+ }
+ defer f.Close()
+
+ // This loads a json config, defined in packer/config.go
+ if err := decodeConfig(f, &config); err != nil {
+ return nil, err
+ }
+
+ config.LoadExternalComponentsFromConfig()
+
+ return &config, nil
+}
+
+// copyOutput uses output prefixes to determine whether data on stdout
+// should go to stdout or stderr. This is due to panicwrap using stderr
+// as the log and error channel.
+func copyOutput(r io.Reader, doneCh chan<- struct{}) {
+ defer close(doneCh)
+
+ pr, err := prefixedio.NewReader(r)
+ if err != nil {
+ panic(err)
+ }
+
+ stderrR, err := pr.Prefix(ErrorPrefix)
+ if err != nil {
+ panic(err)
+ }
+ stdoutR, err := pr.Prefix(OutputPrefix)
+ if err != nil {
+ panic(err)
+ }
+ defaultR, err := pr.Prefix("")
+ if err != nil {
+ panic(err)
+ }
+
+ var wg sync.WaitGroup
+ wg.Add(3)
+ go func() {
+ defer wg.Done()
+ io.Copy(os.Stderr, stderrR)
+ }()
+ go func() {
+ defer wg.Done()
+ io.Copy(os.Stdout, stdoutR)
+ }()
+ go func() {
+ defer wg.Done()
+ io.Copy(os.Stdout, defaultR)
+ }()
+
+ wg.Wait()
+}
+
+func inPlugin() bool {
+ return os.Getenv(pluginsdk.MagicCookieKey) == pluginsdk.MagicCookieValue
+}
+
+func init() {
+ // Seed the random number generator
+ rand.Seed(time.Now().UTC().UnixNano())
+}
diff --git a/v1.9.4/main_test.go b/v1.9.4/main_test.go
new file mode 100644
index 0000000..69be0ac
--- /dev/null
+++ b/v1.9.4/main_test.go
@@ -0,0 +1,72 @@
+// Copyright (c) HashiCorp, Inc.
+// SPDX-License-Identifier: MPL-2.0
+
+package main
+
+import (
+ "math/rand"
+ "reflect"
+ "strings"
+ "testing"
+
+ "github.com/hashicorp/packer/command"
+ "github.com/mitchellh/cli"
+)
+
+func TestExcludeHelpFunc(t *testing.T) {
+ commands := map[string]cli.CommandFactory{
+ "build": func() (cli.Command, error) {
+ return &command.BuildCommand{
+ Meta: command.Meta{},
+ }, nil
+ },
+
+ "fix": func() (cli.Command, error) {
+ return &command.FixCommand{
+ Meta: command.Meta{},
+ }, nil
+ },
+ }
+
+ helpFunc := excludeHelpFunc(commands, []string{"fix"})
+ helpText := helpFunc(commands)
+
+ if strings.Contains(helpText, "fix") {
+ t.Fatalf("Found fix in help text even though we excluded it: \n\n%s\n\n", helpText)
+ }
+}
+
+func TestExtractMachineReadable(t *testing.T) {
+ var args, expected, result []string
+ var mr bool
+
+ // Not
+ args = []string{"foo", "bar", "baz"}
+ result, mr = extractMachineReadable(args)
+ expected = []string{"foo", "bar", "baz"}
+ if !reflect.DeepEqual(result, expected) {
+ t.Fatalf("bad: %#v", result)
+ }
+
+ if mr {
+ t.Fatal("should not be mr")
+ }
+
+ // Yes
+ args = []string{"foo", "-machine-readable", "baz"}
+ result, mr = extractMachineReadable(args)
+ expected = []string{"foo", "baz"}
+ if !reflect.DeepEqual(result, expected) {
+ t.Fatalf("bad: %#v", result)
+ }
+
+ if !mr {
+ t.Fatal("should be mr")
+ }
+}
+
+func TestRandom(t *testing.T) {
+ if rand.Intn(9999999) == 8498210 {
+ t.Fatal("math.rand is not seeded properly")
+ }
+}
diff --git a/v1.9.4/packer/build.go b/v1.9.4/packer/build.go
new file mode 100644
index 0000000..3309bb1
--- /dev/null
+++ b/v1.9.4/packer/build.go
@@ -0,0 +1,405 @@
+// Copyright (c) HashiCorp, Inc.
+// SPDX-License-Identifier: MPL-2.0
+
+package packer
+
+import (
+ "context"
+ "fmt"
+ "log"
+ "sync"
+
+ "github.com/hashicorp/packer-plugin-sdk/common"
+ packersdk "github.com/hashicorp/packer-plugin-sdk/packer"
+ "github.com/hashicorp/packer-plugin-sdk/packerbuilderdata"
+ "github.com/hashicorp/packer/version"
+ "github.com/zclconf/go-cty/cty"
+)
+
+// A CoreBuild struct represents a single build job, the result of which should
+// be a single machine image artifact. This artifact may be comprised of
+// multiple files, of course, but it should be for only a single provider (such
+// as VirtualBox, EC2, etc.).
+type CoreBuild struct {
+ BuildName string
+ Type string
+ Builder packersdk.Builder
+ // BuilderConfig is the config for the builder.
+ //
+ // Is is deserialised directly from the JSON template,
+ // and is only populated for legacy JSON templates.
+ BuilderConfig interface{}
+ // HCLConfig is the HCL config for the builder
+ //
+ // Its only use is for telemetry, since we use it to extract the
+ // field names from it.
+ HCLConfig cty.Value
+ BuilderType string
+ hooks map[string][]packersdk.Hook
+ Provisioners []CoreBuildProvisioner
+ PostProcessors [][]CoreBuildPostProcessor
+ CleanupProvisioner CoreBuildProvisioner
+ TemplatePath string
+ Variables map[string]string
+
+ // Indicates whether the build is already initialized before calling Prepare(..)
+ Prepared bool
+
+ debug bool
+ force bool
+ onError string
+ l sync.Mutex
+ prepareCalled bool
+}
+
+// CoreBuildPostProcessor Keeps track of the post-processor and the
+// configuration of the post-processor used within a build.
+type CoreBuildPostProcessor struct {
+ PostProcessor packersdk.PostProcessor
+ PType string
+ PName string
+ // HCLConfig is the HCL config for the post-processor
+ //
+ // Its only use is for telemetry, since we use it to extract the
+ // field names from it.
+ HCLConfig cty.Value
+ // config is JSON-specific, the configuration for the post-processor
+ // deserialised directly from the JSON template
+ config map[string]interface{}
+ KeepInputArtifact *bool
+}
+
+// CoreBuildProvisioner keeps track of the provisioner and the configuration of
+// the provisioner within the build.
+type CoreBuildProvisioner struct {
+ PType string
+ PName string
+ Provisioner packersdk.Provisioner
+ // HCLConfig is the HCL config for the provisioner
+ //
+ // Its only use is for telemetry, since we use it to extract the
+ // field names from it.
+ HCLConfig cty.Value
+ // config is JSON-specific, and is the configuration of the
+ // provisioner, with overrides
+ config []interface{}
+}
+
+// Returns the name of the build.
+func (b *CoreBuild) Name() string {
+ if b.BuildName != "" {
+ return b.BuildName + "." + b.Type
+ }
+ return b.Type
+}
+
+// Prepare prepares the build by doing some initialization for the builder
+// and any hooks. This _must_ be called prior to Run. The parameter is the
+// overrides for the variables within the template (if any).
+func (b *CoreBuild) Prepare() (warn []string, err error) {
+ // For HCL2 templates, the builder and hooks are initialized when the
+ // template is parsed. Calling Prepare(...) is not necessary
+ if b.Prepared {
+ b.prepareCalled = true
+ return
+ }
+
+ b.l.Lock()
+ defer b.l.Unlock()
+
+ if b.prepareCalled {
+ panic("prepare already called")
+ }
+
+ // Templates loaded from HCL2 will never get here. TODO: move this code into
+ // a custom json area instead of just aborting early for HCL.
+ b.prepareCalled = true
+
+ packerConfig := map[string]interface{}{
+ common.BuildNameConfigKey: b.Type,
+ common.BuilderTypeConfigKey: b.BuilderType,
+ common.CoreVersionConfigKey: version.FormattedVersion(),
+ common.DebugConfigKey: b.debug,
+ common.ForceConfigKey: b.force,
+ common.OnErrorConfigKey: b.onError,
+ common.TemplatePathKey: b.TemplatePath,
+ common.UserVariablesConfigKey: b.Variables,
+ }
+
+ // Prepare the builder
+ generatedVars, warn, err := b.Builder.Prepare(b.BuilderConfig, packerConfig)
+ if err != nil {
+ log.Printf("Build '%s' prepare failure: %s\n", b.Type, err)
+ return
+ }
+
+ // If the builder has provided a list of to-be-generated variables that
+ // should be made accessible to provisioners, pass that list into
+ // the provisioner prepare() so that the provisioner can appropriately
+ // validate user input against what will become available.
+ generatedPlaceholderMap := BasicPlaceholderData()
+ for _, k := range generatedVars {
+ generatedPlaceholderMap[k] = fmt.Sprintf("Build_%s. "+
+ packerbuilderdata.PlaceholderMsg, k)
+ }
+
+ // Prepare the provisioners
+ for _, coreProv := range b.Provisioners {
+ configs := make([]interface{}, len(coreProv.config), len(coreProv.config)+1)
+ copy(configs, coreProv.config)
+ configs = append(configs, packerConfig)
+ configs = append(configs, generatedPlaceholderMap)
+
+ if err = coreProv.Provisioner.Prepare(configs...); err != nil {
+ return
+ }
+ }
+
+ // Prepare the on-error-cleanup provisioner
+ if b.CleanupProvisioner.PType != "" {
+ configs := make([]interface{}, len(b.CleanupProvisioner.config), len(b.CleanupProvisioner.config)+1)
+ copy(configs, b.CleanupProvisioner.config)
+ configs = append(configs, packerConfig)
+ configs = append(configs, generatedPlaceholderMap)
+ err = b.CleanupProvisioner.Provisioner.Prepare(configs...)
+ if err != nil {
+ return
+ }
+ }
+
+ // Prepare the post-processors
+ for _, ppSeq := range b.PostProcessors {
+ for _, corePP := range ppSeq {
+ err = corePP.PostProcessor.Configure(corePP.config, packerConfig, generatedPlaceholderMap)
+ if err != nil {
+ return
+ }
+ }
+ }
+
+ return
+}
+
+// Runs the actual build. Prepare must be called prior to running this.
+func (b *CoreBuild) Run(ctx context.Context, originalUi packersdk.Ui) ([]packersdk.Artifact, error) {
+ if !b.prepareCalled {
+ panic("Prepare must be called first")
+ }
+
+ // Copy the hooks
+ hooks := make(map[string][]packersdk.Hook)
+ for hookName, hookList := range b.hooks {
+ hooks[hookName] = make([]packersdk.Hook, len(hookList))
+ copy(hooks[hookName], hookList)
+ }
+
+ // Add a hook for the provisioners if we have provisioners
+ if len(b.Provisioners) > 0 {
+ hookedProvisioners := make([]*HookedProvisioner, len(b.Provisioners))
+ for i, p := range b.Provisioners {
+ var pConfig interface{}
+ if len(p.config) > 0 {
+ pConfig = p.config[0]
+ } else {
+ pConfig = p.HCLConfig
+ }
+ if b.debug {
+ hookedProvisioners[i] = &HookedProvisioner{
+ &DebuggedProvisioner{Provisioner: p.Provisioner},
+ pConfig,
+ p.PType,
+ }
+ } else {
+ hookedProvisioners[i] = &HookedProvisioner{
+ p.Provisioner,
+ pConfig,
+ p.PType,
+ }
+ }
+ }
+
+ if _, ok := hooks[packersdk.HookProvision]; !ok {
+ hooks[packersdk.HookProvision] = make([]packersdk.Hook, 0, 1)
+ }
+
+ hooks[packersdk.HookProvision] = append(hooks[packersdk.HookProvision], &ProvisionHook{
+ Provisioners: hookedProvisioners,
+ })
+ }
+
+ if b.CleanupProvisioner.PType != "" {
+ hookedCleanupProvisioner := &HookedProvisioner{
+ b.CleanupProvisioner.Provisioner,
+ b.CleanupProvisioner.config,
+ b.CleanupProvisioner.PType,
+ }
+ hooks[packersdk.HookCleanupProvision] = []packersdk.Hook{&ProvisionHook{
+ Provisioners: []*HookedProvisioner{hookedCleanupProvisioner},
+ }}
+ }
+
+ hook := &packersdk.DispatchHook{Mapping: hooks}
+ artifacts := make([]packersdk.Artifact, 0, 1)
+
+ // The builder just has a normal Ui, but targeted
+ builderUi := &TargetedUI{
+ Target: b.Name(),
+ Ui: originalUi,
+ }
+
+ var ts *TelemetrySpan
+ log.Printf("Running builder: %s", b.BuilderType)
+ if b.BuilderConfig != nil {
+ ts = CheckpointReporter.AddSpan(b.Type, "builder", b.BuilderConfig)
+ } else {
+ ts = CheckpointReporter.AddSpan(b.Type, "builder", b.HCLConfig)
+ }
+ builderArtifact, err := b.Builder.Run(ctx, builderUi, hook)
+ ts.End(err)
+ if err != nil {
+ return nil, err
+ }
+
+ // If there was no result, don't worry about running post-processors
+ // because there is nothing they can do, just return.
+ if builderArtifact == nil {
+ return nil, nil
+ }
+
+ errors := make([]error, 0)
+ keepOriginalArtifact := len(b.PostProcessors) == 0
+
+ select {
+ case <-ctx.Done():
+ log.Println("Build was cancelled. Skipping post-processors.")
+ return nil, ctx.Err()
+ default:
+ }
+
+ // Run the post-processors
+PostProcessorRunSeqLoop:
+ for _, ppSeq := range b.PostProcessors {
+ priorArtifact := builderArtifact
+ for i, corePP := range ppSeq {
+ ppUi := &TargetedUI{
+ Target: fmt.Sprintf("%s (%s)", b.Name(), corePP.PType),
+ Ui: originalUi,
+ }
+
+ if corePP.PName == corePP.PType {
+ builderUi.Say(fmt.Sprintf("Running post-processor: %s", corePP.PType))
+ } else {
+ builderUi.Say(fmt.Sprintf("Running post-processor: %s (type %s)", corePP.PName, corePP.PType))
+ }
+ var ts *TelemetrySpan
+ if corePP.config != nil {
+ ts = CheckpointReporter.AddSpan(corePP.PType, "post-processor", corePP.config)
+ } else {
+ ts = CheckpointReporter.AddSpan(corePP.PType, "post-processor", corePP.HCLConfig)
+ }
+ artifact, defaultKeep, forceOverride, err := corePP.PostProcessor.PostProcess(ctx, ppUi, priorArtifact)
+ ts.End(err)
+ if err != nil {
+ errors = append(errors, fmt.Errorf("Post-processor failed: %s", err))
+ continue PostProcessorRunSeqLoop
+ }
+
+ if artifact == nil {
+ log.Println("Nil artifact, halting post-processor chain.")
+ continue PostProcessorRunSeqLoop
+ }
+
+ keep := defaultKeep
+ // When user has not set keep_input_artifact
+ // corePP.keepInputArtifact is nil.
+ // In this case, use the keepDefault provided by the postprocessor.
+ // When user _has_ set keep_input_artifact, go with that instead.
+ // Exception: for postprocessors that will fail/become
+ // useless if keep isn't true, heed forceOverride and keep the
+ // input artifact regardless of user preference.
+ if corePP.KeepInputArtifact != nil {
+ if defaultKeep && *corePP.KeepInputArtifact == false && forceOverride {
+ log.Printf("The %s post-processor forces "+
+ "keep_input_artifact=true to preserve integrity of the"+
+ "build chain. User-set keep_input_artifact=false will be"+
+ "ignored.", corePP.PType)
+ } else {
+ // User overrides default.
+ keep = *corePP.KeepInputArtifact
+ }
+ }
+ if i == 0 {
+ // This is the first post-processor. We handle deleting
+ // previous artifacts a bit different because multiple
+ // post-processors may be using the original and need it.
+ if !keepOriginalArtifact && keep {
+ log.Printf(
+ "Flagging to keep original artifact from post-processor '%s'",
+ corePP.PType)
+ keepOriginalArtifact = true
+ }
+ } else {
+ // We have a prior artifact. If we want to keep it, we append
+ // it to the results list. Otherwise, we destroy it.
+ if keep {
+ artifacts = append(artifacts, priorArtifact)
+ } else {
+ log.Printf("Deleting prior artifact from post-processor '%s'", corePP.PType)
+ if err := priorArtifact.Destroy(); err != nil {
+ log.Printf("Error is %#v", err)
+ errors = append(errors, fmt.Errorf("Failed cleaning up prior artifact: %s; pp is %s", err, corePP.PType))
+ }
+ }
+ }
+
+ priorArtifact = artifact
+ }
+
+ // Add on the last artifact to the results
+ if priorArtifact != nil {
+ artifacts = append(artifacts, priorArtifact)
+ }
+ }
+
+ if keepOriginalArtifact {
+ artifacts = append(artifacts, nil)
+ copy(artifacts[1:], artifacts)
+ artifacts[0] = builderArtifact
+ } else {
+ log.Printf("Deleting original artifact for build '%s'", b.Type)
+ if err := builderArtifact.Destroy(); err != nil {
+ errors = append(errors, fmt.Errorf("Error destroying builder artifact: %s; bad artifact: %#v", err, builderArtifact.Files()))
+ }
+ }
+
+ if len(errors) > 0 {
+ err = &packersdk.MultiError{Errors: errors}
+ return artifacts, err
+ }
+
+ return artifacts, nil
+}
+
+func (b *CoreBuild) SetDebug(val bool) {
+ if b.prepareCalled {
+ panic("prepare has already been called")
+ }
+
+ b.debug = val
+}
+
+func (b *CoreBuild) SetForce(val bool) {
+ if b.prepareCalled {
+ panic("prepare has already been called")
+ }
+
+ b.force = val
+}
+
+func (b *CoreBuild) SetOnError(val string) {
+ if b.prepareCalled {
+ panic("prepare has already been called")
+ }
+
+ b.onError = val
+}
diff --git a/v1.9.4/packer/build_test.go b/v1.9.4/packer/build_test.go
new file mode 100644
index 0000000..86531d8
--- /dev/null
+++ b/v1.9.4/packer/build_test.go
@@ -0,0 +1,502 @@
+// Copyright (c) HashiCorp, Inc.
+// SPDX-License-Identifier: MPL-2.0
+
+package packer
+
+import (
+ "context"
+ "reflect"
+ "testing"
+
+ "github.com/hashicorp/packer-plugin-sdk/common"
+ packersdk "github.com/hashicorp/packer-plugin-sdk/packer"
+ "github.com/hashicorp/packer-plugin-sdk/packerbuilderdata"
+ "github.com/hashicorp/packer/version"
+ "github.com/zclconf/go-cty/cty"
+)
+
+func boolPointer(tf bool) *bool {
+ return &tf
+}
+
+func testBuild() *CoreBuild {
+ return &CoreBuild{
+ Type: "test",
+ Builder: &packersdk.MockBuilder{ArtifactId: "b"},
+ BuilderConfig: 42,
+ BuilderType: "foo",
+ hooks: map[string][]packersdk.Hook{
+ "foo": {&packersdk.MockHook{}},
+ },
+ Provisioners: []CoreBuildProvisioner{
+ {
+ PType: "mock-provisioner",
+ Provisioner: &packersdk.MockProvisioner{},
+ config: []interface{}{42}},
+ },
+ PostProcessors: [][]CoreBuildPostProcessor{
+ {
+ {&MockPostProcessor{ArtifactId: "pp"}, "testPP", "testPPName", cty.Value{}, make(map[string]interface{}), boolPointer(true)},
+ },
+ },
+ Variables: make(map[string]string),
+ onError: "cleanup",
+ }
+}
+
+func testDefaultPackerConfig() map[string]interface{} {
+ return map[string]interface{}{
+ common.BuildNameConfigKey: "test",
+ common.BuilderTypeConfigKey: "foo",
+ common.CoreVersionConfigKey: version.FormattedVersion(),
+ common.DebugConfigKey: false,
+ common.ForceConfigKey: false,
+ common.OnErrorConfigKey: "cleanup",
+ common.TemplatePathKey: "",
+ common.UserVariablesConfigKey: make(map[string]string),
+ }
+}
+func TestBuild_Name(t *testing.T) {
+ build := testBuild()
+ if build.Name() != "test" {
+ t.Fatalf("bad: %s", build.Name())
+ }
+}
+
+func TestBuild_Prepare(t *testing.T) {
+ packerConfig := testDefaultPackerConfig()
+
+ build := testBuild()
+ builder := build.Builder.(*packersdk.MockBuilder)
+
+ build.Prepare()
+ if !builder.PrepareCalled {
+ t.Fatal("should be called")
+ }
+ if !reflect.DeepEqual(builder.PrepareConfig, []interface{}{42, packerConfig}) {
+ t.Fatalf("bad: %#v", builder.PrepareConfig)
+ }
+
+ coreProv := build.Provisioners[0]
+ prov := coreProv.Provisioner.(*packersdk.MockProvisioner)
+ if !prov.PrepCalled {
+ t.Fatal("prep should be called")
+ }
+ if !reflect.DeepEqual(prov.PrepConfigs, []interface{}{42, packerConfig, BasicPlaceholderData()}) {
+ t.Fatalf("bad: %#v", prov.PrepConfigs)
+ }
+
+ corePP := build.PostProcessors[0][0]
+ pp := corePP.PostProcessor.(*MockPostProcessor)
+ if !pp.ConfigureCalled {
+ t.Fatal("should be called")
+ }
+ if !reflect.DeepEqual(pp.ConfigureConfigs, []interface{}{make(map[string]interface{}), packerConfig, BasicPlaceholderData()}) {
+ t.Fatalf("bad: %#v", pp.ConfigureConfigs)
+ }
+}
+
+func TestBuild_Prepare_SkipWhenBuilderAlreadyInitialized(t *testing.T) {
+ build := testBuild()
+ builder := build.Builder.(*packersdk.MockBuilder)
+
+ build.Prepared = true
+ build.Prepare()
+ if builder.PrepareCalled {
+ t.Fatal("should not be called")
+ }
+}
+
+func TestBuild_Prepare_Twice(t *testing.T) {
+ build := testBuild()
+ warn, err := build.Prepare()
+ if len(warn) > 0 {
+ t.Fatalf("bad: %#v", warn)
+ }
+ if err != nil {
+ t.Fatalf("bad error: %s", err)
+ }
+
+ defer func() {
+ p := recover()
+ if p == nil {
+ t.Fatalf("should've paniced")
+ }
+
+ if p.(string) != "prepare already called" {
+ t.Fatalf("Invalid panic: %s", p)
+ }
+ }()
+
+ build.Prepare()
+}
+
+func TestBuildPrepare_BuilderWarnings(t *testing.T) {
+ expected := []string{"foo"}
+
+ build := testBuild()
+ builder := build.Builder.(*packersdk.MockBuilder)
+ builder.PrepareWarnings = expected
+
+ warn, err := build.Prepare()
+ if err != nil {
+ t.Fatalf("err: %s", err)
+ }
+ if !reflect.DeepEqual(warn, expected) {
+ t.Fatalf("bad: %#v", warn)
+ }
+}
+
+func TestBuild_Prepare_Debug(t *testing.T) {
+ packerConfig := testDefaultPackerConfig()
+ packerConfig[common.DebugConfigKey] = true
+
+ build := testBuild()
+ builder := build.Builder.(*packersdk.MockBuilder)
+
+ build.SetDebug(true)
+ build.Prepare()
+ if !builder.PrepareCalled {
+ t.Fatalf("should be called")
+ }
+ if !reflect.DeepEqual(builder.PrepareConfig, []interface{}{42, packerConfig}) {
+ t.Fatalf("bad: %#v", builder.PrepareConfig)
+ }
+
+ coreProv := build.Provisioners[0]
+ prov := coreProv.Provisioner.(*packersdk.MockProvisioner)
+ if !prov.PrepCalled {
+ t.Fatal("prepare should be called")
+ }
+ if !reflect.DeepEqual(prov.PrepConfigs, []interface{}{42, packerConfig, BasicPlaceholderData()}) {
+ t.Fatalf("bad: %#v", prov.PrepConfigs)
+ }
+}
+
+func TestBuildPrepare_variables_default(t *testing.T) {
+ packerConfig := testDefaultPackerConfig()
+ packerConfig[common.UserVariablesConfigKey] = map[string]string{
+ "foo": "bar",
+ }
+
+ build := testBuild()
+ build.Variables["foo"] = "bar"
+ builder := build.Builder.(*packersdk.MockBuilder)
+
+ warn, err := build.Prepare()
+ if len(warn) > 0 {
+ t.Fatalf("bad: %#v", warn)
+ }
+ if err != nil {
+ t.Fatalf("err: %s", err)
+ }
+
+ if !builder.PrepareCalled {
+ t.Fatal("prepare should be called")
+ }
+
+ if !reflect.DeepEqual(builder.PrepareConfig[1], packerConfig) {
+ t.Fatalf("prepare bad: %#v", builder.PrepareConfig[1])
+ }
+}
+
+func TestBuildPrepare_ProvisionerGetsGeneratedMap(t *testing.T) {
+ packerConfig := testDefaultPackerConfig()
+
+ build := testBuild()
+ builder := build.Builder.(*packersdk.MockBuilder)
+ builder.GeneratedVars = []string{"PartyVar"}
+
+ build.Prepare()
+ if !builder.PrepareCalled {
+ t.Fatalf("should be called")
+ }
+ if !reflect.DeepEqual(builder.PrepareConfig, []interface{}{42, packerConfig}) {
+ t.Fatalf("bad: %#v", builder.PrepareConfig)
+ }
+
+ coreProv := build.Provisioners[0]
+ prov := coreProv.Provisioner.(*packersdk.MockProvisioner)
+ if !prov.PrepCalled {
+ t.Fatal("prepare should be called")
+ }
+
+ generated := BasicPlaceholderData()
+ generated["PartyVar"] = "Build_PartyVar. " + packerbuilderdata.PlaceholderMsg
+ if !reflect.DeepEqual(prov.PrepConfigs, []interface{}{42, packerConfig, generated}) {
+ t.Fatalf("bad: %#v", prov.PrepConfigs)
+ }
+}
+
+func TestBuild_Run(t *testing.T) {
+ ui := testUi()
+
+ build := testBuild()
+ build.Prepare()
+ ctx := context.Background()
+ artifacts, err := build.Run(ctx, ui)
+ if err != nil {
+ t.Fatalf("err: %s", err)
+ }
+ if len(artifacts) != 2 {
+ t.Fatalf("bad: %#v", artifacts)
+ }
+
+ // Verify builder was run
+ builder := build.Builder.(*packersdk.MockBuilder)
+ if !builder.RunCalled {
+ t.Fatal("should be called")
+ }
+
+ // Verify hooks are dispatchable
+ dispatchHook := builder.RunHook
+ dispatchHook.Run(ctx, "foo", nil, nil, 42)
+
+ hook := build.hooks["foo"][0].(*packersdk.MockHook)
+ if !hook.RunCalled {
+ t.Fatal("should be called")
+ }
+ if hook.RunData != 42 {
+ t.Fatalf("bad: %#v", hook.RunData)
+ }
+
+ // Verify provisioners run
+ err = dispatchHook.Run(ctx, packersdk.HookProvision, nil, new(packersdk.MockCommunicator), 42)
+ if err != nil {
+ t.Fatalf("should not have errored")
+ }
+ prov := build.Provisioners[0].Provisioner.(*packersdk.MockProvisioner)
+ if !prov.ProvCalled {
+ t.Fatal("should be called")
+ }
+
+ // Verify post-processor was run
+ pp := build.PostProcessors[0][0].PostProcessor.(*MockPostProcessor)
+ if !pp.PostProcessCalled {
+ t.Fatal("should be called")
+ }
+}
+
+func TestBuild_Run_Artifacts(t *testing.T) {
+ ui := testUi()
+
+ // Test case: Test that with no post-processors, we only get the
+ // main build.
+ build := testBuild()
+ build.PostProcessors = [][]CoreBuildPostProcessor{}
+
+ build.Prepare()
+ artifacts, err := build.Run(context.Background(), ui)
+ if err != nil {
+ t.Fatalf("err: %s", err)
+ }
+
+ expectedIds := []string{"b"}
+ artifactIds := make([]string, len(artifacts))
+ for i, artifact := range artifacts {
+ artifactIds[i] = artifact.Id()
+ }
+
+ if !reflect.DeepEqual(artifactIds, expectedIds) {
+ t.Fatalf("unexpected ids: %#v", artifactIds)
+ }
+
+ // Test case: Test that with a single post-processor that doesn't keep
+ // inputs, only that post-processors results are returned.
+ build = testBuild()
+ build.PostProcessors = [][]CoreBuildPostProcessor{
+ {
+ {&MockPostProcessor{ArtifactId: "pp"}, "pp", "testPPName", cty.Value{}, make(map[string]interface{}), boolPointer(false)},
+ },
+ }
+
+ build.Prepare()
+ artifacts, err = build.Run(context.Background(), ui)
+ if err != nil {
+ t.Fatalf("err: %s", err)
+ }
+
+ expectedIds = []string{"pp"}
+ artifactIds = make([]string, len(artifacts))
+ for i, artifact := range artifacts {
+ artifactIds[i] = artifact.Id()
+ }
+
+ if !reflect.DeepEqual(artifactIds, expectedIds) {
+ t.Fatalf("unexpected ids: %#v", artifactIds)
+ }
+
+ // Test case: Test that with multiple post-processors, as long as one
+ // keeps the original, the original is kept.
+ build = testBuild()
+ build.PostProcessors = [][]CoreBuildPostProcessor{
+ {
+ {&MockPostProcessor{ArtifactId: "pp1"}, "pp", "testPPName", cty.Value{}, make(map[string]interface{}), boolPointer(false)},
+ },
+ {
+ {&MockPostProcessor{ArtifactId: "pp2"}, "pp", "testPPName", cty.Value{}, make(map[string]interface{}), boolPointer(true)},
+ },
+ }
+
+ build.Prepare()
+ artifacts, err = build.Run(context.Background(), ui)
+ if err != nil {
+ t.Fatalf("err: %s", err)
+ }
+
+ expectedIds = []string{"b", "pp1", "pp2"}
+ artifactIds = make([]string, len(artifacts))
+ for i, artifact := range artifacts {
+ artifactIds[i] = artifact.Id()
+ }
+
+ if !reflect.DeepEqual(artifactIds, expectedIds) {
+ t.Fatalf("unexpected ids: %#v", artifactIds)
+ }
+
+ // Test case: Test that with sequences, intermediaries are kept if they
+ // want to be.
+ build = testBuild()
+ build.PostProcessors = [][]CoreBuildPostProcessor{
+ {
+ {&MockPostProcessor{ArtifactId: "pp1a"}, "pp", "testPPName", cty.Value{}, make(map[string]interface{}), boolPointer(false)},
+ {&MockPostProcessor{ArtifactId: "pp1b"}, "pp", "testPPName", cty.Value{}, make(map[string]interface{}), boolPointer(true)},
+ },
+ {
+ {&MockPostProcessor{ArtifactId: "pp2a"}, "pp", "testPPName", cty.Value{}, make(map[string]interface{}), boolPointer(false)},
+ {&MockPostProcessor{ArtifactId: "pp2b"}, "pp", "testPPName", cty.Value{}, make(map[string]interface{}), boolPointer(false)},
+ },
+ }
+
+ build.Prepare()
+ artifacts, err = build.Run(context.Background(), ui)
+ if err != nil {
+ t.Fatalf("err: %s", err)
+ }
+
+ expectedIds = []string{"pp1a", "pp1b", "pp2b"}
+ artifactIds = make([]string, len(artifacts))
+ for i, artifact := range artifacts {
+ artifactIds[i] = artifact.Id()
+ }
+
+ if !reflect.DeepEqual(artifactIds, expectedIds) {
+ t.Fatalf("unexpected ids: %#v", artifactIds)
+ }
+
+ // Test case: Test that with a single post-processor that forcibly
+ // keeps inputs, that the artifacts are kept.
+ build = testBuild()
+ build.PostProcessors = [][]CoreBuildPostProcessor{
+ {
+ {
+ &MockPostProcessor{ArtifactId: "pp", Keep: true, ForceOverride: true}, "pp", "testPPName", cty.Value{}, make(map[string]interface{}), boolPointer(false),
+ },
+ },
+ }
+
+ build.Prepare()
+
+ artifacts, err = build.Run(context.Background(), ui)
+ if err != nil {
+ t.Fatalf("err: %s", err)
+ }
+
+ expectedIds = []string{"b", "pp"}
+ artifactIds = make([]string, len(artifacts))
+ for i, artifact := range artifacts {
+ artifactIds[i] = artifact.Id()
+ }
+
+ if !reflect.DeepEqual(artifactIds, expectedIds) {
+ t.Fatalf("unexpected ids: %#v", artifactIds)
+ }
+
+ // Test case: Test that with a single post-processor that non-forcibly
+ // keeps inputs, that the artifacts are discarded if user overrides.
+ build = testBuild()
+ build.PostProcessors = [][]CoreBuildPostProcessor{
+ {
+ {
+ &MockPostProcessor{ArtifactId: "pp", Keep: true, ForceOverride: false}, "pp", "testPPName", cty.Value{}, make(map[string]interface{}), boolPointer(false),
+ },
+ },
+ }
+
+ build.Prepare()
+ artifacts, err = build.Run(context.Background(), ui)
+ if err != nil {
+ t.Fatalf("err: %s", err)
+ }
+
+ expectedIds = []string{"pp"}
+ artifactIds = make([]string, len(artifacts))
+ for i, artifact := range artifacts {
+ artifactIds[i] = artifact.Id()
+ }
+
+ if !reflect.DeepEqual(artifactIds, expectedIds) {
+ t.Fatalf("unexpected ids: %#v", artifactIds)
+ }
+
+ // Test case: Test that with a single post-processor that non-forcibly
+ // keeps inputs, that the artifacts are kept if user does not have preference.
+ build = testBuild()
+ build.PostProcessors = [][]CoreBuildPostProcessor{
+ {
+ {
+ &MockPostProcessor{ArtifactId: "pp", Keep: true, ForceOverride: false}, "pp", "testPPName", cty.Value{}, make(map[string]interface{}), nil,
+ },
+ },
+ }
+
+ build.Prepare()
+ artifacts, err = build.Run(context.Background(), ui)
+ if err != nil {
+ t.Fatalf("err: %s", err)
+ }
+
+ expectedIds = []string{"b", "pp"}
+ artifactIds = make([]string, len(artifacts))
+ for i, artifact := range artifacts {
+ artifactIds[i] = artifact.Id()
+ }
+
+ if !reflect.DeepEqual(artifactIds, expectedIds) {
+ t.Fatalf("unexpected ids: %#v", artifactIds)
+ }
+}
+
+func TestBuild_RunBeforePrepare(t *testing.T) {
+ defer func() {
+ p := recover()
+ if p == nil {
+ t.Fatal("should panic")
+ }
+
+ if p.(string) != "Prepare must be called first" {
+ t.Fatalf("bad: %s", p.(string))
+ }
+ }()
+
+ testBuild().Run(context.Background(), testUi())
+}
+
+func TestBuild_Cancel(t *testing.T) {
+ build := testBuild()
+
+ build.Prepare()
+
+ topCtx, topCtxCancel := context.WithCancel(context.Background())
+
+ builder := build.Builder.(*packersdk.MockBuilder)
+
+ builder.RunFn = func(ctx context.Context) {
+ topCtxCancel()
+ }
+
+ _, err := build.Run(topCtx, testUi())
+ if err == nil {
+ t.Fatal("build should err")
+ }
+}
diff --git a/v1.9.4/packer/builder_test.go b/v1.9.4/packer/builder_test.go
new file mode 100644
index 0000000..1276552
--- /dev/null
+++ b/v1.9.4/packer/builder_test.go
@@ -0,0 +1,4 @@
+// Copyright (c) HashiCorp, Inc.
+// SPDX-License-Identifier: MPL-2.0
+
+package packer
diff --git a/v1.9.4/packer/client_test.go b/v1.9.4/packer/client_test.go
new file mode 100644
index 0000000..f9a1483
--- /dev/null
+++ b/v1.9.4/packer/client_test.go
@@ -0,0 +1,148 @@
+// Copyright (c) HashiCorp, Inc.
+// SPDX-License-Identifier: MPL-2.0
+
+package packer
+
+import (
+ "bytes"
+ "io/ioutil"
+ "os"
+ "strings"
+ "testing"
+ "time"
+)
+
+func TestClient(t *testing.T) {
+ process := helperProcess("mock")
+ c := NewClient(&PluginClientConfig{Cmd: process})
+ defer c.Kill()
+
+ // Test that it parses the proper address
+ addr, err := c.Start()
+ if err != nil {
+ t.Fatalf("err should be nil, got %s", err)
+ }
+
+ if addr.Network() != "tcp" {
+ t.Fatalf("bad: %#v", addr)
+ }
+
+ if addr.String() != ":1234" {
+ t.Fatalf("bad: %#v", addr)
+ }
+
+ // Test that it exits properly if killed
+ c.Kill()
+
+ if process.ProcessState == nil {
+ t.Fatal("should have process state")
+ }
+
+ // Test that it knows it is exited
+ if !c.Exited() {
+ t.Fatal("should say client has exited")
+ }
+}
+
+func TestClientStart_badVersion(t *testing.T) {
+ config := &PluginClientConfig{
+ Cmd: helperProcess("bad-version"),
+ StartTimeout: 50 * time.Millisecond,
+ }
+
+ c := NewClient(config)
+ defer c.Kill()
+
+ _, err := c.Start()
+ if err == nil {
+ t.Fatal("err should not be nil")
+ }
+}
+
+func TestClient_Start_Timeout(t *testing.T) {
+ config := &PluginClientConfig{
+ Cmd: helperProcess("start-timeout"),
+ StartTimeout: 50 * time.Millisecond,
+ }
+
+ c := NewClient(config)
+ defer c.Kill()
+
+ _, err := c.Start()
+ if err == nil {
+ t.Fatal("err should not be nil")
+ }
+}
+
+func TestClient_Stderr(t *testing.T) {
+ stderr := new(bytes.Buffer)
+ process := helperProcess("stderr")
+ c := NewClient(&PluginClientConfig{
+ Cmd: process,
+ Stderr: stderr,
+ })
+ defer c.Kill()
+
+ if _, err := c.Start(); err != nil {
+ t.Fatalf("err: %s", err)
+ }
+
+ for !c.Exited() {
+ time.Sleep(10 * time.Millisecond)
+ }
+
+ if !strings.Contains(stderr.String(), "HELLO\n") {
+ t.Fatalf("bad log data: '%s'", stderr.String())
+ }
+
+ if !strings.Contains(stderr.String(), "WORLD\n") {
+ t.Fatalf("bad log data: '%s'", stderr.String())
+ }
+}
+
+func TestClient_Stdin(t *testing.T) {
+ // Overwrite stdin for this test with a temporary file
+ tf, err := ioutil.TempFile("", "packer")
+ if err != nil {
+ t.Fatalf("err: %s", err)
+ }
+ defer os.Remove(tf.Name())
+ defer tf.Close()
+
+ if _, err = tf.WriteString("hello"); err != nil {
+ t.Fatalf("error: %s", err)
+ }
+
+ if err = tf.Sync(); err != nil {
+ t.Fatalf("error: %s", err)
+ }
+
+ if _, err = tf.Seek(0, 0); err != nil {
+ t.Fatalf("error: %s", err)
+ }
+
+ oldStdin := os.Stdin
+ defer func() { os.Stdin = oldStdin }()
+ os.Stdin = tf
+
+ process := helperProcess("stdin")
+ c := NewClient(&PluginClientConfig{Cmd: process})
+ defer c.Kill()
+
+ _, err = c.Start()
+ if err != nil {
+ t.Fatalf("error: %s", err)
+ }
+
+ for {
+ if c.Exited() {
+ break
+ }
+
+ time.Sleep(50 * time.Millisecond)
+ }
+
+ if !process.ProcessState.Success() {
+ t.Fatal("process didn't exit cleanly")
+ }
+}
diff --git a/v1.9.4/packer/cmd_builder.go b/v1.9.4/packer/cmd_builder.go
new file mode 100644
index 0000000..99a0bc6
--- /dev/null
+++ b/v1.9.4/packer/cmd_builder.go
@@ -0,0 +1,52 @@
+// Copyright (c) HashiCorp, Inc.
+// SPDX-License-Identifier: MPL-2.0
+
+package packer
+
+import (
+ "context"
+ "log"
+
+ "github.com/hashicorp/hcl/v2/hcldec"
+ packersdk "github.com/hashicorp/packer-plugin-sdk/packer"
+)
+
+type cmdBuilder struct {
+ builder packersdk.Builder
+ client *PluginClient
+}
+
+func (b *cmdBuilder) ConfigSpec() hcldec.ObjectSpec {
+ defer func() {
+ r := recover()
+ b.checkExit(r, nil)
+ }()
+
+ return b.builder.ConfigSpec()
+}
+
+func (b *cmdBuilder) Prepare(config ...interface{}) ([]string, []string, error) {
+ defer func() {
+ r := recover()
+ b.checkExit(r, nil)
+ }()
+
+ return b.builder.Prepare(config...)
+}
+
+func (b *cmdBuilder) Run(ctx context.Context, ui packersdk.Ui, hook packersdk.Hook) (packersdk.Artifact, error) {
+ defer func() {
+ r := recover()
+ b.checkExit(r, nil)
+ }()
+
+ return b.builder.Run(ctx, ui, hook)
+}
+
+func (c *cmdBuilder) checkExit(p interface{}, cb func()) {
+ if c.client.Exited() && cb != nil {
+ cb()
+ } else if p != nil && !Killed {
+ log.Panic(p)
+ }
+}
diff --git a/v1.9.4/packer/cmd_builder_test.go b/v1.9.4/packer/cmd_builder_test.go
new file mode 100644
index 0000000..dfc5d15
--- /dev/null
+++ b/v1.9.4/packer/cmd_builder_test.go
@@ -0,0 +1,29 @@
+// Copyright (c) HashiCorp, Inc.
+// SPDX-License-Identifier: MPL-2.0
+
+package packer
+
+import (
+ "os/exec"
+ "testing"
+)
+
+func TestBuilder_NoExist(t *testing.T) {
+ c := NewClient(&PluginClientConfig{Cmd: exec.Command("i-should-not-exist")})
+ defer c.Kill()
+
+ _, err := c.Builder()
+ if err == nil {
+ t.Fatal("should have error")
+ }
+}
+
+func TestBuilder_Good(t *testing.T) {
+ c := NewClient(&PluginClientConfig{Cmd: helperProcess("builder")})
+ defer c.Kill()
+
+ _, err := c.Builder()
+ if err != nil {
+ t.Fatalf("should not have error: %s", err)
+ }
+}
diff --git a/v1.9.4/packer/cmd_datasource.go b/v1.9.4/packer/cmd_datasource.go
new file mode 100644
index 0000000..4e8b325
--- /dev/null
+++ b/v1.9.4/packer/cmd_datasource.go
@@ -0,0 +1,61 @@
+// Copyright (c) HashiCorp, Inc.
+// SPDX-License-Identifier: MPL-2.0
+
+package packer
+
+import (
+ "log"
+
+ "github.com/hashicorp/hcl/v2/hcldec"
+ packersdk "github.com/hashicorp/packer-plugin-sdk/packer"
+ "github.com/zclconf/go-cty/cty"
+)
+
+type cmdDatasource struct {
+ d packersdk.Datasource
+ client *PluginClient
+}
+
+func (d *cmdDatasource) ConfigSpec() hcldec.ObjectSpec {
+ defer func() {
+ r := recover()
+ d.checkExit(r, nil)
+ }()
+
+ return d.d.ConfigSpec()
+}
+
+func (d *cmdDatasource) Configure(configs ...interface{}) error {
+ defer func() {
+ r := recover()
+ d.checkExit(r, nil)
+ }()
+
+ return d.d.Configure(configs...)
+}
+
+func (d *cmdDatasource) OutputSpec() hcldec.ObjectSpec {
+ defer func() {
+ r := recover()
+ d.checkExit(r, nil)
+ }()
+
+ return d.d.OutputSpec()
+}
+
+func (d *cmdDatasource) Execute() (cty.Value, error) {
+ defer func() {
+ r := recover()
+ d.checkExit(r, nil)
+ }()
+
+ return d.d.Execute()
+}
+
+func (d *cmdDatasource) checkExit(p interface{}, cb func()) {
+ if d.client.Exited() && cb != nil {
+ cb()
+ } else if p != nil && !Killed {
+ log.Panic(p)
+ }
+}
diff --git a/v1.9.4/packer/cmd_datasource_test.go b/v1.9.4/packer/cmd_datasource_test.go
new file mode 100644
index 0000000..c174c8e
--- /dev/null
+++ b/v1.9.4/packer/cmd_datasource_test.go
@@ -0,0 +1,29 @@
+// Copyright (c) HashiCorp, Inc.
+// SPDX-License-Identifier: MPL-2.0
+
+package packer
+
+import (
+ "os/exec"
+ "testing"
+)
+
+func TestDatasource_NoExist(t *testing.T) {
+ c := NewClient(&PluginClientConfig{Cmd: exec.Command("i-should-not-exist")})
+ defer c.Kill()
+
+ _, err := c.Datasource()
+ if err == nil {
+ t.Fatal("should have error")
+ }
+}
+
+func TestDatasource_Good(t *testing.T) {
+ c := NewClient(&PluginClientConfig{Cmd: helperProcess("datasource")})
+ defer c.Kill()
+
+ _, err := c.Datasource()
+ if err != nil {
+ t.Fatalf("should not have error: %s", err)
+ }
+}
diff --git a/v1.9.4/packer/cmd_hook.go b/v1.9.4/packer/cmd_hook.go
new file mode 100644
index 0000000..ace3d2c
--- /dev/null
+++ b/v1.9.4/packer/cmd_hook.go
@@ -0,0 +1,33 @@
+// Copyright (c) HashiCorp, Inc.
+// SPDX-License-Identifier: MPL-2.0
+
+package packer
+
+import (
+ "context"
+ "log"
+
+ packersdk "github.com/hashicorp/packer-plugin-sdk/packer"
+)
+
+type cmdHook struct {
+ hook packersdk.Hook
+ client *PluginClient
+}
+
+func (c *cmdHook) Run(ctx context.Context, name string, ui packersdk.Ui, comm packersdk.Communicator, data interface{}) error {
+ defer func() {
+ r := recover()
+ c.checkExit(r, nil)
+ }()
+
+ return c.hook.Run(ctx, name, ui, comm, data)
+}
+
+func (c *cmdHook) checkExit(p interface{}, cb func()) {
+ if c.client.Exited() && cb != nil {
+ cb()
+ } else if p != nil && !Killed {
+ log.Panic(p)
+ }
+}
diff --git a/v1.9.4/packer/cmd_hook_test.go b/v1.9.4/packer/cmd_hook_test.go
new file mode 100644
index 0000000..f2a1f4d
--- /dev/null
+++ b/v1.9.4/packer/cmd_hook_test.go
@@ -0,0 +1,29 @@
+// Copyright (c) HashiCorp, Inc.
+// SPDX-License-Identifier: MPL-2.0
+
+package packer
+
+import (
+ "os/exec"
+ "testing"
+)
+
+func TestHook_NoExist(t *testing.T) {
+ c := NewClient(&PluginClientConfig{Cmd: exec.Command("i-should-not-exist")})
+ defer c.Kill()
+
+ _, err := c.Hook()
+ if err == nil {
+ t.Fatal("should have error")
+ }
+}
+
+func TestHook_Good(t *testing.T) {
+ c := NewClient(&PluginClientConfig{Cmd: helperProcess("hook")})
+ defer c.Kill()
+
+ _, err := c.Hook()
+ if err != nil {
+ t.Fatalf("should not have error: %s", err)
+ }
+}
diff --git a/v1.9.4/packer/cmd_post_processor.go b/v1.9.4/packer/cmd_post_processor.go
new file mode 100644
index 0000000..c686a39
--- /dev/null
+++ b/v1.9.4/packer/cmd_post_processor.go
@@ -0,0 +1,52 @@
+// Copyright (c) HashiCorp, Inc.
+// SPDX-License-Identifier: MPL-2.0
+
+package packer
+
+import (
+ "context"
+ "log"
+
+ "github.com/hashicorp/hcl/v2/hcldec"
+ packersdk "github.com/hashicorp/packer-plugin-sdk/packer"
+)
+
+type cmdPostProcessor struct {
+ p packersdk.PostProcessor
+ client *PluginClient
+}
+
+func (b *cmdPostProcessor) ConfigSpec() hcldec.ObjectSpec {
+ defer func() {
+ r := recover()
+ b.checkExit(r, nil)
+ }()
+
+ return b.p.ConfigSpec()
+}
+
+func (c *cmdPostProcessor) Configure(config ...interface{}) error {
+ defer func() {
+ r := recover()
+ c.checkExit(r, nil)
+ }()
+
+ return c.p.Configure(config...)
+}
+
+func (c *cmdPostProcessor) PostProcess(ctx context.Context, ui packersdk.Ui, a packersdk.Artifact) (packersdk.Artifact, bool, bool, error) {
+ defer func() {
+ r := recover()
+ c.checkExit(r, nil)
+ }()
+
+ return c.p.PostProcess(ctx, ui, a)
+}
+
+func (c *cmdPostProcessor) checkExit(p interface{}, cb func()) {
+ if c.client.Exited() && cb != nil {
+ cb()
+ } else if p != nil && !Killed {
+ log.Panic(p)
+ }
+}
diff --git a/v1.9.4/packer/cmd_post_processor_test.go b/v1.9.4/packer/cmd_post_processor_test.go
new file mode 100644
index 0000000..ce70a8b
--- /dev/null
+++ b/v1.9.4/packer/cmd_post_processor_test.go
@@ -0,0 +1,45 @@
+// Copyright (c) HashiCorp, Inc.
+// SPDX-License-Identifier: MPL-2.0
+
+package packer
+
+import (
+ "context"
+ "os/exec"
+ "testing"
+
+ "github.com/hashicorp/hcl/v2/hcldec"
+ packersdk "github.com/hashicorp/packer-plugin-sdk/packer"
+)
+
+type helperPostProcessor byte
+
+func (helperPostProcessor) ConfigSpec() hcldec.ObjectSpec { return nil }
+
+func (helperPostProcessor) Configure(...interface{}) error {
+ return nil
+}
+
+func (helperPostProcessor) PostProcess(context.Context, packersdk.Ui, packersdk.Artifact) (packersdk.Artifact, bool, bool, error) {
+ return nil, false, false, nil
+}
+
+func TestPostProcessor_NoExist(t *testing.T) {
+ c := NewClient(&PluginClientConfig{Cmd: exec.Command("i-should-not-exist")})
+ defer c.Kill()
+
+ _, err := c.PostProcessor()
+ if err == nil {
+ t.Fatal("should have error")
+ }
+}
+
+func TestPostProcessor_Good(t *testing.T) {
+ c := NewClient(&PluginClientConfig{Cmd: helperProcess("post-processor")})
+ defer c.Kill()
+
+ _, err := c.PostProcessor()
+ if err != nil {
+ t.Fatalf("should not have error: %s", err)
+ }
+}
diff --git a/v1.9.4/packer/cmd_provisioner.go b/v1.9.4/packer/cmd_provisioner.go
new file mode 100644
index 0000000..965ad89
--- /dev/null
+++ b/v1.9.4/packer/cmd_provisioner.go
@@ -0,0 +1,52 @@
+// Copyright (c) HashiCorp, Inc.
+// SPDX-License-Identifier: MPL-2.0
+
+package packer
+
+import (
+ "context"
+ "log"
+
+ "github.com/hashicorp/hcl/v2/hcldec"
+ packersdk "github.com/hashicorp/packer-plugin-sdk/packer"
+)
+
+type cmdProvisioner struct {
+ p packersdk.Provisioner
+ client *PluginClient
+}
+
+func (p *cmdProvisioner) ConfigSpec() hcldec.ObjectSpec {
+ defer func() {
+ r := recover()
+ p.checkExit(r, nil)
+ }()
+
+ return p.p.ConfigSpec()
+}
+
+func (c *cmdProvisioner) Prepare(configs ...interface{}) error {
+ defer func() {
+ r := recover()
+ c.checkExit(r, nil)
+ }()
+
+ return c.p.Prepare(configs...)
+}
+
+func (c *cmdProvisioner) Provision(ctx context.Context, ui packersdk.Ui, comm packersdk.Communicator, generatedData map[string]interface{}) error {
+ defer func() {
+ r := recover()
+ c.checkExit(r, nil)
+ }()
+
+ return c.p.Provision(ctx, ui, comm, generatedData)
+}
+
+func (c *cmdProvisioner) checkExit(p interface{}, cb func()) {
+ if c.client.Exited() && cb != nil {
+ cb()
+ } else if p != nil && !Killed {
+ log.Panic(p)
+ }
+}
diff --git a/v1.9.4/packer/cmd_provisioner_test.go b/v1.9.4/packer/cmd_provisioner_test.go
new file mode 100644
index 0000000..5bb8694
--- /dev/null
+++ b/v1.9.4/packer/cmd_provisioner_test.go
@@ -0,0 +1,29 @@
+// Copyright (c) HashiCorp, Inc.
+// SPDX-License-Identifier: MPL-2.0
+
+package packer
+
+import (
+ "os/exec"
+ "testing"
+)
+
+func TestProvisioner_NoExist(t *testing.T) {
+ c := NewClient(&PluginClientConfig{Cmd: exec.Command("i-should-not-exist")})
+ defer c.Kill()
+
+ _, err := c.Provisioner()
+ if err == nil {
+ t.Fatal("should have error")
+ }
+}
+
+func TestProvisioner_Good(t *testing.T) {
+ c := NewClient(&PluginClientConfig{Cmd: helperProcess("provisioner")})
+ defer c.Kill()
+
+ _, err := c.Provisioner()
+ if err != nil {
+ t.Fatalf("should not have error: %s", err)
+ }
+}
diff --git a/v1.9.4/packer/core.go b/v1.9.4/packer/core.go
new file mode 100644
index 0000000..b711af0
--- /dev/null
+++ b/v1.9.4/packer/core.go
@@ -0,0 +1,909 @@
+// Copyright (c) HashiCorp, Inc.
+// SPDX-License-Identifier: MPL-2.0
+
+package packer
+
+import (
+ "encoding/json"
+ "fmt"
+ "log"
+ "regexp"
+ "sort"
+ "strconv"
+ "strings"
+
+ ttmp "text/template"
+
+ "github.com/google/go-cmp/cmp"
+ multierror "github.com/hashicorp/go-multierror"
+ version "github.com/hashicorp/go-version"
+ hcl "github.com/hashicorp/hcl/v2"
+ packersdk "github.com/hashicorp/packer-plugin-sdk/packer"
+ "github.com/hashicorp/packer-plugin-sdk/template"
+ "github.com/hashicorp/packer-plugin-sdk/template/interpolate"
+ plugingetter "github.com/hashicorp/packer/packer/plugin-getter"
+ packerversion "github.com/hashicorp/packer/version"
+)
+
+// Core is the main executor of Packer. If Packer is being used as a
+// library, this is the struct you'll want to instantiate to get anything done.
+type Core struct {
+ Template *template.Template
+
+ components ComponentFinder
+ variables map[string]string
+ builds map[string]*template.Builder
+ version string
+ secrets []string
+
+ except []string
+ only []string
+}
+
+// CoreConfig is the structure for initializing a new Core. Once a CoreConfig
+// is used to initialize a Core, it shouldn't be re-used or modified again.
+type CoreConfig struct {
+ Components ComponentFinder
+ Template *template.Template
+ Variables map[string]string
+ SensitiveVariables []string
+ Version string
+
+ // These are set by command-line flags
+ Except []string
+ Only []string
+}
+
+// The function type used to lookup Builder implementations.
+type BuilderFunc func(name string) (packersdk.Builder, error)
+
+// The function type used to lookup Hook implementations.
+type HookFunc func(name string) (packersdk.Hook, error)
+
+// The function type used to lookup PostProcessor implementations.
+type PostProcessorFunc func(name string) (packersdk.PostProcessor, error)
+
+// The function type used to lookup Provisioner implementations.
+type ProvisionerFunc func(name string) (packersdk.Provisioner, error)
+
+type BasicStore interface {
+ Has(name string) bool
+ List() (names []string)
+}
+
+type BuilderStore interface {
+ BasicStore
+ Start(name string) (packersdk.Builder, error)
+}
+
+type BuilderSet interface {
+ BuilderStore
+ Set(name string, starter func() (packersdk.Builder, error))
+}
+
+type ProvisionerStore interface {
+ BasicStore
+ Start(name string) (packersdk.Provisioner, error)
+}
+
+type ProvisionerSet interface {
+ ProvisionerStore
+ Set(name string, starter func() (packersdk.Provisioner, error))
+}
+
+type PostProcessorStore interface {
+ BasicStore
+ Start(name string) (packersdk.PostProcessor, error)
+}
+
+type PostProcessorSet interface {
+ PostProcessorStore
+ Set(name string, starter func() (packersdk.PostProcessor, error))
+}
+
+type DatasourceStore interface {
+ BasicStore
+ Start(name string) (packersdk.Datasource, error)
+}
+
+type DatasourceSet interface {
+ DatasourceStore
+ Set(name string, starter func() (packersdk.Datasource, error))
+}
+
+// ComponentFinder is a struct that contains the various function
+// pointers necessary to look up components of Packer such as builders,
+// commands, etc.
+type ComponentFinder struct {
+ Hook HookFunc
+ PluginConfig *PluginConfig
+}
+
+// NewCore creates a new Core.
+func NewCore(c *CoreConfig) *Core {
+ core := &Core{
+ Template: c.Template,
+ components: c.Components,
+ variables: c.Variables,
+ version: c.Version,
+ only: c.Only,
+ except: c.Except,
+ }
+ return core
+}
+
+// DetectPluginBinaries is used to load required plugins from the template,
+// since it is unsupported in JSON, this is essentially a no-op.
+func (c *Core) DetectPluginBinaries() hcl.Diagnostics {
+ return nil
+}
+
+func (c *Core) Initialize(_ InitializeOptions) hcl.Diagnostics {
+ err := c.initialize()
+ if err != nil {
+ return hcl.Diagnostics{
+ &hcl.Diagnostic{
+ Detail: err.Error(),
+ Severity: hcl.DiagError,
+ },
+ }
+ }
+ return nil
+}
+
+func (core *Core) initialize() error {
+ if err := core.validate(); err != nil {
+ return err
+ }
+ if err := core.init(); err != nil {
+ return err
+ }
+ for _, secret := range core.secrets {
+ packersdk.LogSecretFilter.Set(secret)
+ }
+
+ // Go through and interpolate all the build names. We should be able
+ // to do this at this point with the variables.
+ core.builds = make(map[string]*template.Builder)
+ for _, b := range core.Template.Builders {
+ v, err := interpolate.Render(b.Name, core.Context())
+ if err != nil {
+ return fmt.Errorf(
+ "Error interpolating builder '%s': %s",
+ b.Name, err)
+ }
+
+ core.builds[v] = b
+ }
+
+ return nil
+}
+
+func (c *Core) PluginRequirements() (plugingetter.Requirements, hcl.Diagnostics) {
+ return nil, hcl.Diagnostics{
+ &hcl.Diagnostic{
+ Summary: "Packer plugins currently only works with HCL2 configuration templates",
+ Detail: "Please manually install plugins with the plugins command or use a HCL2 configuration that will do that for you.",
+ Severity: hcl.DiagError,
+ },
+ }
+}
+
+// BuildNames returns the builds that are available in this configured core.
+func (c *Core) BuildNames(only, except []string) []string {
+
+ sort.Strings(only)
+ sort.Strings(except)
+ c.except = except
+ c.only = only
+
+ r := make([]string, 0, len(c.builds))
+ for n := range c.builds {
+ onlyPos := sort.SearchStrings(only, n)
+ foundInOnly := onlyPos < len(only) && only[onlyPos] == n
+ if len(only) > 0 && !foundInOnly {
+ continue
+ }
+
+ if pos := sort.SearchStrings(except, n); pos < len(except) && except[pos] == n {
+ continue
+ }
+ r = append(r, n)
+ }
+ sort.Strings(r)
+
+ return r
+}
+
+func (c *Core) generateCoreBuildProvisioner(rawP *template.Provisioner, rawName string) (CoreBuildProvisioner, error) {
+ // Get the provisioner
+ cbp := CoreBuildProvisioner{}
+ provisioner, err := c.components.PluginConfig.Provisioners.Start(rawP.Type)
+ if err != nil {
+ return cbp, fmt.Errorf(
+ "error initializing provisioner '%s': %s",
+ rawP.Type, err)
+ }
+ if provisioner == nil {
+ return cbp, fmt.Errorf(
+ "provisioner type not found: %s", rawP.Type)
+ }
+
+ // Get the configuration
+ config := make([]interface{}, 1, 2)
+ config[0] = rawP.Config
+ if rawP.Override != nil {
+ if override, ok := rawP.Override[rawName]; ok {
+ config = append(config, override)
+ }
+ }
+ // If we're pausing, we wrap the provisioner in a special pauser.
+ if rawP.PauseBefore != 0 {
+ provisioner = &PausedProvisioner{
+ PauseBefore: rawP.PauseBefore,
+ Provisioner: provisioner,
+ }
+ } else if rawP.Timeout != 0 {
+ provisioner = &TimeoutProvisioner{
+ Timeout: rawP.Timeout,
+ Provisioner: provisioner,
+ }
+ }
+ maxRetries := 0
+ if rawP.MaxRetries != "" {
+ renderedMaxRetries, err := interpolate.Render(rawP.MaxRetries, c.Context())
+ if err != nil {
+ return cbp, fmt.Errorf("failed to interpolate `max_retries`: %s", err.Error())
+ }
+ maxRetries, err = strconv.Atoi(renderedMaxRetries)
+ if err != nil {
+ return cbp, fmt.Errorf("`max_retries` must be a valid integer: %s", err.Error())
+ }
+ }
+ if maxRetries != 0 {
+ provisioner = &RetriedProvisioner{
+ MaxRetries: maxRetries,
+ Provisioner: provisioner,
+ }
+ }
+ cbp = CoreBuildProvisioner{
+ PType: rawP.Type,
+ Provisioner: provisioner,
+ config: config,
+ }
+
+ return cbp, nil
+}
+
+// This is used for json templates to launch the build plugins.
+// They will be prepared via b.Prepare() later.
+func (c *Core) GetBuilds(opts GetBuildsOptions) ([]packersdk.Build, hcl.Diagnostics) {
+ buildNames := c.BuildNames(opts.Only, opts.Except)
+ builds := []packersdk.Build{}
+ diags := hcl.Diagnostics{}
+ for _, n := range buildNames {
+ b, err := c.Build(n)
+ if err != nil {
+ diags = append(diags, &hcl.Diagnostic{
+ Severity: hcl.DiagError,
+ Summary: fmt.Sprintf("Failed to initialize build %q", n),
+ Detail: err.Error(),
+ })
+ continue
+ }
+
+ // Now that build plugin has been launched, call Prepare()
+ log.Printf("Preparing build: %s", b.Name())
+ b.SetDebug(opts.Debug)
+ b.SetForce(opts.Force)
+ b.SetOnError(opts.OnError)
+
+ warnings, err := b.Prepare()
+ if err != nil {
+ diags = append(diags, &hcl.Diagnostic{
+ Severity: hcl.DiagError,
+ Summary: fmt.Sprintf("Failed to prepare build: %q", n),
+ Detail: err.Error(),
+ })
+ continue
+ }
+
+ // Only append builds to list if the Prepare() is successful.
+ builds = append(builds, b)
+
+ if len(warnings) > 0 {
+ for _, warning := range warnings {
+ diags = append(diags, &hcl.Diagnostic{
+ Severity: hcl.DiagWarning,
+ Summary: fmt.Sprintf("Warning when preparing build: %q", n),
+ Detail: warning,
+ })
+ }
+ }
+ }
+ return builds, diags
+}
+
+// Build returns the Build object for the given name.
+func (c *Core) Build(n string) (packersdk.Build, error) {
+ // Setup the builder
+ configBuilder, ok := c.builds[n]
+ if !ok {
+ return nil, fmt.Errorf("no such build found: %s", n)
+ }
+ // BuilderStore = config.Builders, gathered in loadConfig() in main.go
+ // For reference, the builtin BuilderStore is generated in
+ // packer/config.go in the Discover() func.
+
+ // the Start command launches the builder plugin of the given type without
+ // calling Prepare() or passing any build-specific details.
+ builder, err := c.components.PluginConfig.Builders.Start(configBuilder.Type)
+ if err != nil {
+ return nil, fmt.Errorf(
+ "error initializing builder '%s': %s",
+ configBuilder.Type, err)
+ }
+ if builder == nil {
+ return nil, fmt.Errorf(
+ "builder type not found: %s", configBuilder.Type)
+ }
+
+ // rawName is the uninterpolated name that we use for various lookups
+ rawName := configBuilder.Name
+
+ // Setup the provisioners for this build
+ provisioners := make([]CoreBuildProvisioner, 0, len(c.Template.Provisioners))
+ for _, rawP := range c.Template.Provisioners {
+ // If we're skipping this, then ignore it
+ if rawP.OnlyExcept.Skip(rawName) {
+ continue
+ }
+ cbp, err := c.generateCoreBuildProvisioner(rawP, rawName)
+ if err != nil {
+ return nil, err
+ }
+
+ provisioners = append(provisioners, cbp)
+ }
+
+ var cleanupProvisioner CoreBuildProvisioner
+ if c.Template.CleanupProvisioner != nil {
+ // This is a special instantiation of the shell-local provisioner that
+ // is only run on error at end of provisioning step before other step
+ // cleanup occurs.
+ cleanupProvisioner, err = c.generateCoreBuildProvisioner(c.Template.CleanupProvisioner, rawName)
+ if err != nil {
+ return nil, err
+ }
+ }
+
+ // Setup the post-processors
+ postProcessors := make([][]CoreBuildPostProcessor, 0, len(c.Template.PostProcessors))
+ for _, rawPs := range c.Template.PostProcessors {
+ current := make([]CoreBuildPostProcessor, 0, len(rawPs))
+ for _, rawP := range rawPs {
+ if rawP.Skip(rawName) {
+ continue
+ }
+ // -except skips post-processor & build
+ foundExcept := false
+ for _, except := range c.except {
+ if except != "" && except == rawP.Name {
+ foundExcept = true
+ }
+ }
+ if foundExcept {
+ break
+ }
+
+ // Get the post-processor
+ postProcessor, err := c.components.PluginConfig.PostProcessors.Start(rawP.Type)
+ if err != nil {
+ return nil, fmt.Errorf(
+ "error initializing post-processor '%s': %s",
+ rawP.Type, err)
+ }
+ if postProcessor == nil {
+ return nil, fmt.Errorf(
+ "post-processor type not found: %s", rawP.Type)
+ }
+
+ current = append(current, CoreBuildPostProcessor{
+ PostProcessor: postProcessor,
+ PType: rawP.Type,
+ PName: rawP.Name,
+ config: rawP.Config,
+ KeepInputArtifact: rawP.KeepInputArtifact,
+ })
+ }
+
+ // If we have no post-processors in this chain, just continue.
+ if len(current) == 0 {
+ continue
+ }
+
+ postProcessors = append(postProcessors, current)
+ }
+
+ // TODO hooks one day
+
+ // Return a structure that contains the plugins, their types, variables, and
+ // the raw builder config loaded from the json template
+ cb := &CoreBuild{
+ Type: n,
+ Builder: builder,
+ BuilderConfig: configBuilder.Config,
+ BuilderType: configBuilder.Type,
+ PostProcessors: postProcessors,
+ Provisioners: provisioners,
+ CleanupProvisioner: cleanupProvisioner,
+ TemplatePath: c.Template.Path,
+ Variables: c.variables,
+ }
+
+ //configBuilder.Name is left uninterpolated so we must check against
+ // the interpolated name.
+ if configBuilder.Type != configBuilder.Name {
+ cb.BuildName = configBuilder.Type
+ }
+
+ return cb, nil
+}
+
+// Context returns an interpolation context.
+func (c *Core) Context() *interpolate.Context {
+ return &interpolate.Context{
+ TemplatePath: c.Template.Path,
+ UserVariables: c.variables,
+ CorePackerVersionString: packerversion.FormattedVersion(),
+ }
+}
+
+var ConsoleHelp = strings.TrimSpace(`
+Packer console JSON Mode.
+The Packer console allows you to experiment with Packer interpolations.
+You may access variables in the Packer config you called the console with.
+
+Type in the interpolation to test and hit <enter> to see the result.
+
+"variables" will dump all available variables and their values.
+
+"{{timestamp}}" will output the timestamp, for example "1559855090".
+
+To exit the console, type "exit" and hit <enter>, or use Control-C.
+
+/!\ If you would like to start console in hcl2 mode without a config you can
+use the --config-type=hcl2 option.
+`)
+
+func (c *Core) EvaluateExpression(line string) (string, bool, hcl.Diagnostics) {
+ switch {
+ case line == "":
+ return "", false, nil
+ case line == "exit":
+ return "", true, nil
+ case line == "help":
+ return ConsoleHelp, false, nil
+ case line == "variables":
+ varsstring := "\n"
+ for k, v := range c.Context().UserVariables {
+ varsstring += fmt.Sprintf("%s: %+v,\n", k, v)
+ }
+
+ return varsstring, false, nil
+ default:
+ ctx := c.Context()
+ rendered, err := interpolate.Render(line, ctx)
+ var diags hcl.Diagnostics
+ if err != nil {
+ diags = append(diags, &hcl.Diagnostic{
+ Summary: "Interpolation error",
+ Detail: err.Error(),
+ })
+ }
+ return rendered, false, diags
+ }
+}
+
+func (c *Core) InspectConfig(opts InspectConfigOptions) int {
+
+ // Convenience...
+ ui := opts.Ui
+ tpl := c.Template
+ ui.Say("Packer Inspect: JSON mode")
+
+ // Description
+ if tpl.Description != "" {
+ ui.Say("Description:\n")
+ ui.Say(tpl.Description + "\n")
+ }
+
+ // Variables
+ if len(tpl.Variables) == 0 {
+ ui.Say("Variables:\n")
+ ui.Say(" <No variables>")
+ } else {
+ requiredHeader := false
+ for k, v := range tpl.Variables {
+ for _, sensitive := range tpl.SensitiveVariables {
+ if ok := strings.Compare(sensitive.Default, v.Default); ok == 0 {
+ v.Default = "<sensitive>"
+ }
+ }
+ if v.Required {
+ if !requiredHeader {
+ requiredHeader = true
+ ui.Say("Required variables:\n")
+ }
+
+ ui.Machine("template-variable", k, v.Default, "1")
+ ui.Say(" " + k)
+ }
+ }
+
+ if requiredHeader {
+ ui.Say("")
+ }
+
+ ui.Say("Optional variables and their defaults:\n")
+ keys := make([]string, 0, len(tpl.Variables))
+ max := 0
+ for k := range tpl.Variables {
+ keys = append(keys, k)
+ if len(k) > max {
+ max = len(k)
+ }
+ }
+
+ sort.Strings(keys)
+
+ for _, k := range keys {
+ v := tpl.Variables[k]
+ if v.Required {
+ continue
+ }
+ for _, sensitive := range tpl.SensitiveVariables {
+ if ok := strings.Compare(sensitive.Default, v.Default); ok == 0 {
+ v.Default = "<sensitive>"
+ }
+ }
+
+ padding := strings.Repeat(" ", max-len(k))
+ output := fmt.Sprintf(" %s%s = %s", k, padding, v.Default)
+
+ ui.Machine("template-variable", k, v.Default, "0")
+ ui.Say(output)
+ }
+ }
+
+ ui.Say("")
+
+ // Builders
+ ui.Say("Builders:\n")
+ if len(tpl.Builders) == 0 {
+ ui.Say(" <No builders>")
+ } else {
+ keys := make([]string, 0, len(tpl.Builders))
+ max := 0
+ for k := range tpl.Builders {
+ keys = append(keys, k)
+ if len(k) > max {
+ max = len(k)
+ }
+ }
+
+ sort.Strings(keys)
+
+ for _, k := range keys {
+ v := tpl.Builders[k]
+ padding := strings.Repeat(" ", max-len(k))
+ output := fmt.Sprintf(" %s%s", k, padding)
+ if v.Name != v.Type {
+ output = fmt.Sprintf("%s (%s)", output, v.Type)
+ }
+
+ ui.Machine("template-builder", k, v.Type)
+ ui.Say(output)
+
+ }
+ }
+
+ ui.Say("")
+
+ // Provisioners
+ ui.Say("Provisioners:\n")
+ if len(tpl.Provisioners) == 0 {
+ ui.Say(" <No provisioners>")
+ } else {
+ for _, v := range tpl.Provisioners {
+ ui.Machine("template-provisioner", v.Type)
+ ui.Say(fmt.Sprintf(" %s", v.Type))
+ }
+ }
+
+ ui.Say("\nNote: If your build names contain user variables or template\n" +
+ "functions such as 'timestamp', these are processed at build time,\n" +
+ "and therefore only show in their raw form here.")
+
+ return 0
+}
+
+func (c *Core) FixConfig(opts FixConfigOptions) hcl.Diagnostics {
+ var diags hcl.Diagnostics
+
+ // Remove once we have support for the Inplace FixConfigMode
+ if opts.Mode != Diff {
+ diags = append(diags, &hcl.Diagnostic{
+ Severity: hcl.DiagError,
+ Summary: fmt.Sprintf("FixConfig only supports template diff; FixConfigMode %d not supported", opts.Mode),
+ })
+
+ return diags
+ }
+
+ var rawTemplateData map[string]interface{}
+ input := make(map[string]interface{})
+ templateData := make(map[string]interface{})
+ if err := json.Unmarshal(c.Template.RawContents, &rawTemplateData); err != nil {
+ diags = append(diags, &hcl.Diagnostic{
+ Severity: hcl.DiagError,
+ Summary: fmt.Sprintf("unable to read the contents of the JSON configuration file: %s", err),
+ Detail: err.Error(),
+ })
+ return diags
+ }
+ // Hold off on Diff for now - need to think about displaying to user.
+ // delete empty top-level keys since the fixers seem to add them
+ // willy-nilly
+ for k := range input {
+ ml, ok := input[k].([]map[string]interface{})
+ if !ok {
+ continue
+ }
+ if len(ml) == 0 {
+ delete(input, k)
+ }
+ }
+ // marshal/unmarshal to make comparable to templateData
+ var fixedData map[string]interface{}
+ // Guaranteed to be valid json, so we can ignore errors
+ j, _ := json.Marshal(input)
+ if err := json.Unmarshal(j, &fixedData); err != nil {
+ diags = append(diags, &hcl.Diagnostic{
+ Severity: hcl.DiagError,
+ Summary: fmt.Sprintf("unable to read the contents of the JSON configuration file: %s", err),
+ Detail: err.Error(),
+ })
+
+ return diags
+ }
+
+ if diff := cmp.Diff(templateData, fixedData); diff != "" {
+ diags = append(diags, &hcl.Diagnostic{
+ Severity: hcl.DiagError,
+ Summary: "Fixable configuration found.\nPlease run `packer fix` to get your build to run correctly.\nSee debug log for more information.",
+ Detail: diff,
+ })
+ }
+ return diags
+}
+
+// validate does a full validation of the template.
+//
+// This will automatically call template.validate() in addition to doing
+// richer semantic checks around variables and so on.
+func (c *Core) validate() error {
+ // First validate the template in general, we can't do anything else
+ // unless the template itself is valid.
+ if err := c.Template.Validate(); err != nil {
+ return err
+ }
+
+ // Validate the minimum version is satisfied
+ if c.Template.MinVersion != "" {
+ versionActual, err := version.NewVersion(c.version)
+ if err != nil {
+ // This shouldn't happen since we set it via the compiler
+ panic(err)
+ }
+
+ versionMin, err := version.NewVersion(c.Template.MinVersion)
+ if err != nil {
+ return fmt.Errorf(
+ "min_version is invalid: %s", err)
+ }
+
+ if versionActual.LessThan(versionMin) {
+ return fmt.Errorf(
+ "This template requires Packer version %s or higher; using %s",
+ versionMin,
+ versionActual)
+ }
+ }
+
+ // Validate variables are set
+ var err error
+ for n, v := range c.Template.Variables {
+ if v.Required {
+ if _, ok := c.variables[n]; !ok {
+ err = multierror.Append(err, fmt.Errorf(
+ "required variable not set: %s", n))
+ }
+ }
+ }
+
+ // TODO: validate all builders exist
+ // TODO: ^^ provisioner
+ // TODO: ^^ post-processor
+
+ return err
+}
+
+func isDoneInterpolating(v string) (bool, error) {
+ // Check for whether the var contains any more references to `user`, wrapped
+ // in interpolation syntax.
+ filter := `{{\s*user\s*\x60.*\x60\s*}}`
+ matched, err := regexp.MatchString(filter, v)
+ if err != nil {
+ return false, fmt.Errorf("Can't tell if interpolation is done: %s", err)
+ }
+ if matched {
+ // not done interpolating; there's still a call to "user" in a template
+ // engine
+ return false, nil
+ }
+ // No more calls to "user" as a template engine, so we're done.
+ return true, nil
+}
+
+func (c *Core) renderVarsRecursively() (*interpolate.Context, error) {
+ ctx := c.Context()
+ ctx.EnableEnv = true
+ ctx.UserVariables = make(map[string]string)
+ shouldRetry := true
+ changed := false
+ failedInterpolation := ""
+
+ // Why this giant loop? User variables can be recursively defined. For
+ // example:
+ // "variables": {
+ // "foo": "bar",
+ // "baz": "{{user `foo`}}baz",
+ // "bang": "bang{{user `baz`}}"
+ // },
+ // In this situation, we cannot guarantee that we've added "foo" to
+ // UserVariables before we try to interpolate "baz" the first time. We need
+ // to have the option to loop back over in order to add the properly
+ // interpolated "baz" to the UserVariables map.
+ // Likewise, we'd need to loop up to two times to properly add "bang",
+ // since that depends on "baz" being set, which depends on "foo" being set.
+
+ // We break out of the while loop either if all our variables have been
+ // interpolated or if after 100 loops we still haven't succeeded in
+ // interpolating them. Please don't actually nest your variables in 100
+ // layers of other variables. Please.
+
+ // c.Template.Variables is populated by variables defined within the Template
+ // itself
+ // c.variables is populated by variables read in from the command line and
+ // var-files.
+ // We need to read the keys from both, then loop over all of them to figure
+ // out the appropriate interpolations.
+
+ repeatMap := make(map[string]string)
+ allKeys := make([]string, 0)
+
+ // load in template variables
+ for k, v := range c.Template.Variables {
+ repeatMap[k] = v.Default
+ allKeys = append(allKeys, k)
+ }
+
+ // overwrite template variables with command-line-read variables
+ for k, v := range c.variables {
+ repeatMap[k] = v
+ allKeys = append(allKeys, k)
+ }
+
+ // sort map to force the following loop to be deterministic.
+ sort.Strings(allKeys)
+ type keyValue struct {
+ Key string
+ Value string
+ }
+ sortedMap := make([]keyValue, len(repeatMap))
+ for _, k := range allKeys {
+ sortedMap = append(sortedMap, keyValue{k, repeatMap[k]})
+ }
+
+ // Regex to exclude any build function variable or template variable
+ // from interpolating earlier
+ // E.g.: {{ .HTTPIP }} won't interpolate now
+ renderFilter := "{{(\\s|)\\.(.*?)(\\s|)}}"
+
+ for i := 0; i < 100; i++ {
+ shouldRetry = false
+ changed = false
+ deleteKeys := []string{}
+ // First, loop over the variables in the template
+ for _, kv := range sortedMap {
+ // Interpolate the default
+ renderedV, err := interpolate.RenderRegex(kv.Value, ctx, renderFilter)
+ switch err.(type) {
+ case nil:
+ // We only get here if interpolation has succeeded, so something is
+ // different in this loop than in the last one.
+ changed = true
+ c.variables[kv.Key] = renderedV
+ ctx.UserVariables = c.variables
+ // Remove fully-interpolated variables from the map, and flag
+ // variables that still need interpolating for a repeat.
+ done, err := isDoneInterpolating(kv.Value)
+ if err != nil {
+ return ctx, err
+ }
+ if done {
+ deleteKeys = append(deleteKeys, kv.Key)
+ } else {
+ shouldRetry = true
+ }
+ case ttmp.ExecError:
+ castError := err.(ttmp.ExecError)
+ if strings.Contains(castError.Error(), interpolate.ErrVariableNotSetString) {
+ shouldRetry = true
+ failedInterpolation = fmt.Sprintf(`"%s": "%s"; error: %s`, kv.Key, kv.Value, err)
+ } else {
+ return ctx, err
+ }
+ default:
+ return ctx, fmt.Errorf(
+ // unexpected interpolation error: abort the run
+ "error interpolating default value for '%s': %s",
+ kv.Key, err)
+ }
+ }
+ if !shouldRetry {
+ break
+ }
+
+ // Clear completed vars from sortedMap before next loop. Do this one
+ // key at a time because the indices are gonna change ever time you
+ // delete from the map.
+ for _, k := range deleteKeys {
+ for ind, kv := range sortedMap {
+ if kv.Key == k {
+ sortedMap = append(sortedMap[:ind], sortedMap[ind+1:]...)
+ break
+ }
+ }
+ }
+ deleteKeys = []string{}
+ }
+
+ if !changed && shouldRetry {
+ return ctx, fmt.Errorf("Failed to interpolate %s: Please make sure that "+
+ "the variable you're referencing has been defined; Packer treats "+
+ "all variables used to interpolate other user variables as "+
+ "required.", failedInterpolation)
+ }
+
+ return ctx, nil
+}
+
+func (c *Core) init() error {
+ if c.variables == nil {
+ c.variables = make(map[string]string)
+ }
+ // Go through the variables and interpolate the environment and
+ // user variables
+ ctx, err := c.renderVarsRecursively()
+ if err != nil {
+ return err
+ }
+ for _, v := range c.Template.SensitiveVariables {
+ secret := ctx.UserVariables[v.Key]
+ c.secrets = append(c.secrets, secret)
+ }
+
+ return nil
+}
diff --git a/v1.9.4/packer/core_test.go b/v1.9.4/packer/core_test.go
new file mode 100644
index 0000000..e46f62e
--- /dev/null
+++ b/v1.9.4/packer/core_test.go
@@ -0,0 +1,939 @@
+// Copyright (c) HashiCorp, Inc.
+// SPDX-License-Identifier: MPL-2.0
+
+package packer
+
+import (
+ "context"
+ "errors"
+ "os"
+ "path/filepath"
+ "reflect"
+ "testing"
+
+ packersdk "github.com/hashicorp/packer-plugin-sdk/packer"
+ "github.com/hashicorp/packer-plugin-sdk/template"
+ configHelper "github.com/hashicorp/packer-plugin-sdk/template/config"
+ "github.com/hashicorp/packer/version"
+)
+
+func TestCoreBuildNames(t *testing.T) {
+ cases := []struct {
+ File string
+ Vars map[string]string
+ Result []string
+ }{
+ {
+ "build-names-basic.json",
+ nil,
+ []string{"something"},
+ },
+
+ {
+ "build-names-func.json",
+ nil,
+ []string{"TUBES"},
+ },
+ }
+
+ for _, tc := range cases {
+ tpl, err := template.ParseFile(fixtureDir(tc.File))
+ if err != nil {
+ t.Fatalf("err: %s\n\n%s", tc.File, err)
+ }
+
+ core := NewCore(&CoreConfig{
+ Template: tpl,
+ Variables: tc.Vars,
+ })
+ diags := core.Initialize(InitializeOptions{})
+ if diags.HasErrors() {
+ t.Fatalf("err: %s\n\n%s", tc.File, diags)
+ }
+
+ names := core.BuildNames(nil, nil)
+ if !reflect.DeepEqual(names, tc.Result) {
+ t.Fatalf("err: %s\n\n%#v", tc.File, names)
+ }
+ }
+}
+
+func TestCoreBuild_basic(t *testing.T) {
+ config := TestCoreConfig(t)
+ testCoreTemplate(t, config, fixtureDir("build-basic.json"))
+ b := TestBuilder(t, config, "test")
+ core := TestCore(t, config)
+
+ b.ArtifactId = "hello"
+
+ build, err := core.Build("test")
+ if err != nil {
+ t.Fatalf("err: %s", err)
+ }
+
+ if build.Name() != "test" {
+ t.Fatalf("bad: build name does not match expected: %q, got: %q", "test", build.Name())
+ }
+
+ if _, err := build.Prepare(); err != nil {
+ t.Fatalf("err: %s", err)
+ }
+
+ artifact, err := build.Run(context.Background(), nil)
+ if err != nil {
+ t.Fatalf("err: %s", err)
+ }
+ if len(artifact) != 1 {
+ t.Fatalf("bad: %#v", artifact)
+ }
+
+ if artifact[0].Id() != b.ArtifactId {
+ t.Fatalf("bad: %s", artifact[0].Id())
+ }
+}
+
+func TestCoreBuild_basicInterpolated(t *testing.T) {
+ config := TestCoreConfig(t)
+ testCoreTemplate(t, config, fixtureDir("build-basic-interpolated.json"))
+ b := TestBuilder(t, config, "test")
+ core := TestCore(t, config)
+
+ b.ArtifactId = "hello"
+
+ build, err := core.Build("NAME")
+ if err != nil {
+ t.Fatalf("err: %s", err)
+ }
+
+ if build.Name() != "test.NAME" {
+ t.Fatalf("bad: build name does not match expected: %q, got: %q", "NAME", build.Name())
+ }
+
+ if _, err := build.Prepare(); err != nil {
+ t.Fatalf("err: %s", err)
+ }
+
+ artifact, err := build.Run(context.Background(), nil)
+ if err != nil {
+ t.Fatalf("err: %s", err)
+ }
+ if len(artifact) != 1 {
+ t.Fatalf("bad: %#v", artifact)
+ }
+
+ if artifact[0].Id() != b.ArtifactId {
+ t.Fatalf("bad: %s", artifact[0].Id())
+ }
+}
+
+func TestCoreBuild_env(t *testing.T) {
+ t.Setenv("PACKER_TEST_ENV", "test")
+
+ config := TestCoreConfig(t)
+ testCoreTemplate(t, config, fixtureDir("build-env.json"))
+ b := TestBuilder(t, config, "test")
+ core := TestCore(t, config)
+
+ b.ArtifactId = "hello"
+
+ build, err := core.Build("test")
+ if err != nil {
+ t.Fatalf("err: %s", err)
+ }
+
+ if _, err := build.Prepare(); err != nil {
+ t.Fatalf("err: %s", err)
+ }
+
+ // Interpolate the config
+ var result map[string]interface{}
+ err = configHelper.Decode(&result, nil, b.PrepareConfig...)
+ if err != nil {
+ t.Fatalf("err: %s", err)
+ }
+
+ if result["value"] != "test" {
+ t.Fatalf("bad: %#v", result)
+ }
+}
+
+func TestCoreBuild_IgnoreTemplateVariables(t *testing.T) {
+ t.Setenv("PACKER_TEST_ENV", "test")
+
+ config := TestCoreConfig(t)
+ testCoreTemplate(t, config, fixtureDir("build-ignore-template-variable.json"))
+ core := TestCore(t, config)
+
+ if core.variables["http_ip"] != "{{ .HTTPIP }}" {
+ t.Fatalf("bad: User variable http_ip={{ .HTTPIP }} should not be interpolated")
+ }
+
+ if core.variables["var"] != "test_{{ .PACKER_TEST_TEMP }}" {
+ t.Fatalf("bad: User variable var should be half interpolated to var=test_{{ .PACKER_TEST_TEMP }} but was var=%s", core.variables["var"])
+ }
+
+ if core.variables["array_var"] != "us-west-1,us-west-2" {
+ t.Fatalf("bad: User variable array_var should be \"us-west-1,us-west-2\" but was %s", core.variables["var"])
+ }
+
+ build, err := core.Build("test")
+ if err != nil {
+ t.Fatalf("err: %s", err)
+ }
+
+ if _, err := build.Prepare(); err != nil {
+ t.Fatalf("err: %s", err)
+ }
+}
+
+func TestCoreBuild_buildNameVar(t *testing.T) {
+ config := TestCoreConfig(t)
+ testCoreTemplate(t, config, fixtureDir("build-var-build-name.json"))
+ b := TestBuilder(t, config, "test")
+ core := TestCore(t, config)
+
+ b.ArtifactId = "hello"
+
+ build, err := core.Build("test")
+ if err != nil {
+ t.Fatalf("err: %s", err)
+ }
+
+ if _, err := build.Prepare(); err != nil {
+ t.Fatalf("err: %s", err)
+ }
+
+ // Interpolate the config
+ var result map[string]interface{}
+ err = configHelper.Decode(&result, nil, b.PrepareConfig...)
+ if err != nil {
+ t.Fatalf("err: %s", err)
+ }
+
+ if result["value"] != "test" {
+ t.Fatalf("bad: %#v", result)
+ }
+}
+
+func TestCoreBuild_buildTypeVar(t *testing.T) {
+ config := TestCoreConfig(t)
+ testCoreTemplate(t, config, fixtureDir("build-var-build-type.json"))
+ b := TestBuilder(t, config, "test")
+ core := TestCore(t, config)
+
+ b.ArtifactId = "hello"
+
+ build, err := core.Build("test")
+ if err != nil {
+ t.Fatalf("err: %s", err)
+ }
+
+ if _, err := build.Prepare(); err != nil {
+ t.Fatalf("err: %s", err)
+ }
+
+ // Interpolate the config
+ var result map[string]interface{}
+ err = configHelper.Decode(&result, nil, b.PrepareConfig...)
+ if err != nil {
+ t.Fatalf("err: %s", err)
+ }
+
+ if result["value"] != "test" {
+ t.Fatalf("bad: %#v", result)
+ }
+}
+
+func TestCoreBuild_nonExist(t *testing.T) {
+ config := TestCoreConfig(t)
+ testCoreTemplate(t, config, fixtureDir("build-basic.json"))
+ TestBuilder(t, config, "test")
+ core := TestCore(t, config)
+
+ _, err := core.Build("nope")
+ if err == nil {
+ t.Fatal("should error")
+ }
+}
+
+func TestCoreBuild_prov(t *testing.T) {
+ config := TestCoreConfig(t)
+ testCoreTemplate(t, config, fixtureDir("build-prov.json"))
+ b := TestBuilder(t, config, "test")
+ p := TestProvisioner(t, config, "test")
+ core := TestCore(t, config)
+
+ b.ArtifactId = "hello"
+
+ build, err := core.Build("test")
+ if err != nil {
+ t.Fatalf("err: %s", err)
+ }
+
+ if _, err := build.Prepare(); err != nil {
+ t.Fatalf("err: %s", err)
+ }
+
+ artifact, err := build.Run(context.Background(), nil)
+ if err != nil {
+ t.Fatalf("err: %s", err)
+ }
+ if len(artifact) != 1 {
+ t.Fatalf("bad: %#v", artifact)
+ }
+
+ if artifact[0].Id() != b.ArtifactId {
+ t.Fatalf("bad: %s", artifact[0].Id())
+ }
+ if !p.ProvCalled {
+ t.Fatal("provisioner not called")
+ }
+}
+
+func TestCoreBuild_provSkip(t *testing.T) {
+ config := TestCoreConfig(t)
+ testCoreTemplate(t, config, fixtureDir("build-prov-skip.json"))
+ b := TestBuilder(t, config, "test")
+ p := TestProvisioner(t, config, "test")
+ core := TestCore(t, config)
+
+ b.ArtifactId = "hello"
+
+ build, err := core.Build("test")
+ if err != nil {
+ t.Fatalf("err: %s", err)
+ }
+
+ if _, err := build.Prepare(); err != nil {
+ t.Fatalf("err: %s", err)
+ }
+
+ artifact, err := build.Run(context.Background(), nil)
+ if err != nil {
+ t.Fatalf("err: %s", err)
+ }
+ if len(artifact) != 1 {
+ t.Fatalf("bad: %#v", artifact)
+ }
+
+ if artifact[0].Id() != b.ArtifactId {
+ t.Fatalf("bad: %s", artifact[0].Id())
+ }
+ if p.ProvCalled {
+ t.Fatal("provisioner should not be called")
+ }
+}
+
+func TestCoreBuild_provSkipInclude(t *testing.T) {
+ config := TestCoreConfig(t)
+ testCoreTemplate(t, config, fixtureDir("build-prov-skip-include.json"))
+ b := TestBuilder(t, config, "test")
+ p := TestProvisioner(t, config, "test")
+ core := TestCore(t, config)
+
+ b.ArtifactId = "hello"
+
+ build, err := core.Build("test")
+ if err != nil {
+ t.Fatalf("err: %s", err)
+ }
+
+ if _, err := build.Prepare(); err != nil {
+ t.Fatalf("err: %s", err)
+ }
+
+ artifact, err := build.Run(context.Background(), nil)
+ if err != nil {
+ t.Fatalf("err: %s", err)
+ }
+ if len(artifact) != 1 {
+ t.Fatalf("bad: %#v", artifact)
+ }
+
+ if artifact[0].Id() != b.ArtifactId {
+ t.Fatalf("bad: %s", artifact[0].Id())
+ }
+ if !p.ProvCalled {
+ t.Fatal("provisioner should be called")
+ }
+}
+
+func TestCoreBuild_provOverride(t *testing.T) {
+ config := TestCoreConfig(t)
+ testCoreTemplate(t, config, fixtureDir("build-prov-override.json"))
+ b := TestBuilder(t, config, "test")
+ p := TestProvisioner(t, config, "test")
+ core := TestCore(t, config)
+
+ b.ArtifactId = "hello"
+
+ build, err := core.Build("test")
+ if err != nil {
+ t.Fatalf("err: %s", err)
+ }
+
+ if _, err := build.Prepare(); err != nil {
+ t.Fatalf("err: %s", err)
+ }
+
+ artifact, err := build.Run(context.Background(), nil)
+ if err != nil {
+ t.Fatalf("err: %s", err)
+ }
+ if len(artifact) != 1 {
+ t.Fatalf("bad: %#v", artifact)
+ }
+
+ if artifact[0].Id() != b.ArtifactId {
+ t.Fatalf("bad: %s", artifact[0].Id())
+ }
+ if !p.ProvCalled {
+ t.Fatal("provisioner not called")
+ }
+
+ found := false
+ for _, raw := range p.PrepConfigs {
+ if m, ok := raw.(map[string]interface{}); ok {
+ if _, ok := m["foo"]; ok {
+ found = true
+ break
+ }
+ }
+ }
+ if !found {
+ t.Fatal("override not called")
+ }
+}
+
+func TestCoreBuild_postProcess(t *testing.T) {
+ config := TestCoreConfig(t)
+ testCoreTemplate(t, config, fixtureDir("build-pp.json"))
+ b := TestBuilder(t, config, "test")
+ p := TestPostProcessor(t, config, "test")
+ core := TestCore(t, config)
+ ui := TestUi(t)
+
+ b.ArtifactId = "hello"
+ p.ArtifactId = "goodbye"
+
+ build, err := core.Build("test")
+ if err != nil {
+ t.Fatalf("err: %s", err)
+ }
+
+ if _, err := build.Prepare(); err != nil {
+ t.Fatalf("err: %s", err)
+ }
+
+ artifact, err := build.Run(context.Background(), ui)
+ if err != nil {
+ t.Fatalf("err: %s", err)
+ }
+ if len(artifact) != 1 {
+ t.Fatalf("bad: %#v", artifact)
+ }
+
+ if artifact[0].Id() != p.ArtifactId {
+ t.Fatalf("bad: %s", artifact[0].Id())
+ }
+ if p.PostProcessArtifact.Id() != b.ArtifactId {
+ t.Fatalf("bad: %s", p.PostProcessArtifact.Id())
+ }
+}
+
+func TestCoreBuild_templatePath(t *testing.T) {
+ config := TestCoreConfig(t)
+ testCoreTemplate(t, config, fixtureDir("build-template-path.json"))
+ b := TestBuilder(t, config, "test")
+ core := TestCore(t, config)
+
+ expected, _ := filepath.Abs("./test-fixtures")
+
+ build, err := core.Build("test")
+ if err != nil {
+ t.Fatalf("err: %s", err)
+ }
+
+ if _, err := build.Prepare(); err != nil {
+ t.Fatalf("err: %s", err)
+ }
+
+ // Interpolate the config
+ var result map[string]interface{}
+ err = configHelper.Decode(&result, nil, b.PrepareConfig...)
+ if err != nil {
+ t.Fatalf("err: %s", err)
+ }
+
+ if result["value"] != expected {
+ t.Fatalf("bad: %#v", result)
+ }
+}
+
+func TestCoreValidate(t *testing.T) {
+ cases := []struct {
+ File string
+ Vars map[string]string
+ Err bool
+ }{
+ {"validate-dup-builder.json", nil, true},
+
+ // Required variable not set
+ {"validate-req-variable.json", nil, true},
+ {"validate-req-variable.json", map[string]string{"foo": "bar"}, false},
+
+ // Min version good
+ {"validate-min-version.json", map[string]string{"foo": "bar"}, false},
+ {"validate-min-version-high.json", map[string]string{"foo": "bar"}, true},
+ }
+
+ for _, tc := range cases {
+ f, err := os.Open(fixtureDir(tc.File))
+ if err != nil {
+ t.Fatalf("err: %s", err)
+ }
+
+ tpl, err := template.Parse(f)
+ f.Close()
+ if err != nil {
+ t.Fatalf("err: %s\n\n%s", tc.File, err)
+ }
+
+ core := NewCore(&CoreConfig{
+ Template: tpl,
+ Variables: tc.Vars,
+ Version: "1.0.0",
+ })
+ diags := core.Initialize(InitializeOptions{})
+
+ if diags.HasErrors() != tc.Err {
+ t.Fatalf("err: %s\n\n%s", tc.File, err)
+ }
+ }
+}
+
+// Tests that we can properly interpolate user variables defined within the
+// packer template
+func TestCore_InterpolateUserVars(t *testing.T) {
+ cases := []struct {
+ File string
+ Expected map[string]string
+ Err bool
+ }{
+ {
+ "build-variables-interpolate.json",
+ map[string]string{
+ "foo": "bar",
+ "bar": "bar",
+ "baz": "barbaz",
+ "bang": "bangbarbaz",
+ },
+ false,
+ },
+ {
+ "build-variables-interpolate2.json",
+ map[string]string{},
+ true,
+ },
+ }
+ for _, tc := range cases {
+ f, err := os.Open(fixtureDir(tc.File))
+ if err != nil {
+ t.Fatalf("err: %s", err)
+ }
+
+ tpl, err := template.Parse(f)
+ f.Close()
+ if err != nil {
+ t.Fatalf("err: %s\n\n%s", tc.File, err)
+ }
+
+ ccf := NewCore(&CoreConfig{
+ Template: tpl,
+ Version: "1.0.0",
+ })
+ diags := ccf.Initialize(InitializeOptions{})
+
+ if diags.HasErrors() != tc.Err {
+ if tc.Err == false {
+ t.Fatalf("Error interpolating %s: Expected no error, but got: %s", tc.File, diags)
+ } else {
+ t.Fatalf("Error interpolating %s: Expected an error, but got: %s", tc.File, diags)
+ }
+
+ }
+ if !tc.Err {
+ for k, v := range ccf.variables {
+ if tc.Expected[k] != v {
+ t.Fatalf("Expected %s but got %s", tc.Expected[k], v)
+ }
+ }
+ }
+ }
+}
+
+// Tests that we can properly interpolate user variables defined within a
+// var-file provided alongside the Packer template
+func TestCore_InterpolateUserVars_VarFile(t *testing.T) {
+ cases := []struct {
+ File string
+ Variables map[string]string
+ Expected map[string]string
+ Err bool
+ }{
+ {
+ // tests that we can interpolate from var files when var isn't set in
+ // originating template
+ "build-basic-interpolated.json",
+ map[string]string{
+ "name": "gotta-{{user `my_var`}}",
+ "my_var": "interpolate-em-all",
+ },
+ map[string]string{
+ "name": "gotta-interpolate-em-all",
+ "my_var": "interpolate-em-all"},
+ false,
+ },
+ {
+ // tests that we can interpolate from var files when var is set in
+ // originating template as required
+ "build-basic-interpolated-required.json",
+ map[string]string{
+ "name": "gotta-{{user `my_var`}}",
+ "my_var": "interpolate-em-all",
+ },
+ map[string]string{
+ "name": "gotta-interpolate-em-all",
+ "my_var": "interpolate-em-all"},
+ false,
+ },
+ }
+ for _, tc := range cases {
+ f, err := os.Open(fixtureDir(tc.File))
+ if err != nil {
+ t.Fatalf("err: %s", err)
+ }
+
+ tpl, err := template.Parse(f)
+ f.Close()
+ if err != nil {
+ t.Fatalf("err: %s\n\n%s", tc.File, err)
+ }
+
+ ccf := NewCore(&CoreConfig{
+ Template: tpl,
+ Version: "1.0.0",
+ Variables: tc.Variables,
+ })
+ diags := ccf.Initialize(InitializeOptions{})
+
+ if diags.HasErrors() != tc.Err {
+ t.Fatalf("err: %s\n\n%s", tc.File, diags)
+ }
+ if !tc.Err {
+ for k, v := range ccf.variables {
+ if tc.Expected[k] != v {
+ t.Fatalf("Expected value %s for key %s but got %s",
+ tc.Expected[k], k, v)
+ }
+ }
+ }
+ }
+}
+
+func TestSensitiveVars(t *testing.T) {
+ cases := []struct {
+ File string
+ Vars map[string]string
+ SensitiveVars []string
+ Expected string
+ Err bool
+ }{
+ // hardcoded
+ {
+ "sensitive-variables.json",
+ map[string]string{"foo": "bar_extra_sensitive_probably_a_password"},
+ []string{"foo"},
+ "the foo jumped over the <sensitive>",
+ false,
+ },
+ // interpolated
+ {
+ "sensitive-variables.json",
+ map[string]string{"foo": "bar_extra_sensitive_probably_a_password",
+ "bang": "{{ user `foo`}}"},
+ []string{"bang"},
+ "the foo jumped over the <sensitive>",
+ false,
+ },
+ }
+
+ for _, tc := range cases {
+ f, err := os.Open(fixtureDir(tc.File))
+ if err != nil {
+ t.Fatalf("err: %s", err)
+ }
+
+ tpl, err := template.Parse(f)
+ f.Close()
+ if err != nil {
+ t.Fatalf("err: %s\n\n%s", tc.File, err)
+ }
+
+ ccf := NewCore(&CoreConfig{
+ Template: tpl,
+ Variables: tc.Vars,
+ Version: "1.0.0",
+ })
+ diags := ccf.Initialize(InitializeOptions{})
+
+ if diags.HasErrors() != tc.Err {
+ t.Fatalf("err: %s\n\n%s", tc.File, diags)
+ }
+ // Check that filter correctly manipulates strings:
+ filtered := packersdk.LogSecretFilter.FilterString("the foo jumped over the bar_extra_sensitive_probably_a_password")
+ if filtered != tc.Expected {
+ t.Fatalf("not filtering sensitive vars; filtered is %#v", filtered)
+ }
+ }
+}
+
+// Normally I wouldn't test a little helper function, but it's regex.
+func TestIsDoneInterpolating(t *testing.T) {
+ cases := []struct {
+ inputString string
+ expectedBool bool
+ expectedErr bool
+ }{
+ // Many of these tests are just exercising the regex to make sure it
+ // doesnt get confused by different kinds of whitespace
+ {"charmander-{{ user `spacesaroundticks` }}", false, false},
+ {"pidgey-{{ user `partyparrot`}}", false, false},
+ {"jigglypuff-{{ user`notickspaaces`}}", false, false},
+ {"eevee-{{user`nospaces`}}", false, false},
+ {"staryu-{{ user `somanyspaces` }}", false, false},
+ {"{{ user `somanyspaces` }}-{{isotime}}", false, false},
+ // Make sure that we only flag on "user" when it's in the right set of
+ // brackets, in a properly declared template engine format
+ {"missingno-{{ user `missingbracket` }", true, false},
+ {"missing2-{user ``missingopenbrackets }}", true, false},
+ {"wat-userjustinname", true, false},
+ // Any functions that aren't "user" should have already been properly
+ // interpolated by the time this is called, so these cases aren't
+ // realistic. That said, this makes it clear that this function doesn't
+ // care about anything but the user function
+ {"pokemon-{{ isotime }}", true, false},
+ {"squirtle-{{ env `water`}}", true, false},
+ {"bulbasaur-notinterpolated", true, false},
+ {"extra-{{thisfunc `user`}}", true, false},
+ }
+ for _, tc := range cases {
+ done, err := isDoneInterpolating(tc.inputString)
+ if (err != nil) != tc.expectedErr {
+ t.Fatalf("Test case failed. Error: %s expected error: "+
+ "%t test string: %s", err, tc.expectedErr, tc.inputString)
+ }
+ if done != tc.expectedBool {
+ t.Fatalf("Test case failed. inputString: %s. "+
+ "Expected done = %t but got done = %t", tc.inputString,
+ tc.expectedBool, done)
+ }
+ }
+}
+
+func TestEnvAndFileVars(t *testing.T) {
+ t.Setenv("INTERPOLATE_TEST_ENV_1", "bulbasaur")
+ t.Setenv("INTERPOLATE_TEST_ENV_3", "/path/to/nowhere")
+ t.Setenv("INTERPOLATE_TEST_ENV_2", "5")
+ t.Setenv("INTERPOLATE_TEST_ENV_4", "bananas")
+
+ f, err := os.Open(fixtureDir("complex-recursed-env-user-var-file.json"))
+ if err != nil {
+ t.Fatalf("err: %s", err)
+ }
+
+ tpl, err := template.Parse(f)
+ f.Close()
+ if err != nil {
+ t.Fatalf("err: %s\n\n%s", "complex-recursed-env-user-var-file.json", err)
+ }
+
+ ccf := NewCore(&CoreConfig{
+ Template: tpl,
+ Version: "1.0.0",
+ Variables: map[string]string{
+ "var_1": "partyparrot",
+ "var_2": "{{user `env_1`}}-{{user `env_2`}}{{user `env_3`}}-{{user `var_1`}}",
+ "final_var": "{{user `env_1`}}/{{user `env_2`}}/{{user `env_4`}}{{user `env_3`}}-{{user `var_1`}}/vmware/{{user `var_2`}}.vmx",
+ },
+ })
+ diags := ccf.Initialize(InitializeOptions{})
+
+ expected := map[string]string{
+ "var_1": "partyparrot",
+ "var_2": "bulbasaur-5/path/to/nowhere-partyparrot",
+ "final_var": "bulbasaur/5/bananas/path/to/nowhere-partyparrot/vmware/bulbasaur-5/path/to/nowhere-partyparrot.vmx",
+ "env_1": "bulbasaur",
+ "env_2": "5",
+ "env_3": "/path/to/nowhere",
+ "env_4": "bananas",
+ }
+ if diags.HasErrors() {
+ t.Fatalf("err: %s\n\n%s", "complex-recursed-env-user-var-file.json", diags)
+ }
+ for k, v := range ccf.variables {
+ if expected[k] != v {
+ t.Fatalf("Expected value %s for key %s but got %s",
+ expected[k], k, v)
+ }
+ }
+}
+
+func testCoreTemplate(t *testing.T, c *CoreConfig, p string) {
+ tpl, err := template.ParseFile(p)
+ if err != nil {
+ t.Fatalf("err: %s\n\n%s", p, err)
+ }
+
+ c.Template = tpl
+}
+
+func TestCoreBuild_provRetry(t *testing.T) {
+ config := TestCoreConfig(t)
+ testCoreTemplate(t, config, fixtureDir("build-prov-retry.json"))
+ b := TestBuilder(t, config, "test")
+ pString := new(packersdk.MockProvisioner)
+ pInt := new(packersdk.MockProvisioner)
+ config.Components.PluginConfig.Provisioners = MapOfProvisioner{
+ "test-string": func() (packersdk.Provisioner, error) { return pString, nil },
+ // backwards compatibility
+ "test-integer": func() (packersdk.Provisioner, error) { return pInt, nil },
+ }
+ core := TestCore(t, config)
+
+ b.ArtifactId = "hello"
+
+ build, err := core.Build("test")
+ if err != nil {
+ t.Fatalf("err: %s", err)
+ }
+
+ if _, err := build.Prepare(); err != nil {
+ t.Fatalf("err: %s", err)
+ }
+
+ ui := testUi()
+ pInt.ProvFunc = func(ctx context.Context) error {
+ return errors.New("failed")
+ }
+ pString.ProvFunc = func(ctx context.Context) error {
+ return errors.New("failed")
+ }
+
+ artifact, err := build.Run(context.Background(), ui)
+ if err != nil {
+ t.Fatalf("err: %s", err)
+ }
+ if len(artifact) != 1 {
+ t.Fatalf("bad: %#v", artifact)
+ }
+
+ if artifact[0].Id() != b.ArtifactId {
+ t.Fatalf("bad: %s", artifact[0].Id())
+ }
+ if !pString.ProvRetried {
+ t.Fatal("provisioner should retry for max_retries string value")
+ }
+ // backwards compatibility
+ if !pInt.ProvRetried {
+ t.Fatal("provisioner should retry for max_retries integer value")
+ }
+}
+
+func TestCoreBuild_packerVersion(t *testing.T) {
+ config := TestCoreConfig(t)
+ testCoreTemplate(t, config, fixtureDir("build-var-packer-version.json"))
+ b := TestBuilder(t, config, "test")
+ core := TestCore(t, config)
+
+ expected := version.FormattedVersion()
+ build, err := core.Build("test")
+ if err != nil {
+ t.Fatalf("err: %s", err)
+ }
+
+ if _, err := build.Prepare(); err != nil {
+ t.Fatalf("err: %s", err)
+ }
+ // Interpolate the config
+ var result map[string]interface{}
+ err = configHelper.Decode(&result, nil, b.PrepareConfig...)
+ if err != nil {
+ t.Fatalf("err: %s", err)
+ }
+
+ if result["value"] != expected {
+ t.Fatalf("bad: %#v", result)
+ }
+}
+
+func TestCoreBuild_buildNameIntepolation(t *testing.T) {
+ config := TestCoreConfig(t)
+ cases := []struct {
+ File string
+ InterpolatedName, Expected string
+ Vars map[string]string
+ }{
+ {
+ File: "build-interpolated-name.json",
+ InterpolatedName: "mybuild-RandomToken",
+ Expected: "test.mybuild-RandomToken",
+ Vars: map[string]string{
+ "build_name": "mybuild-RandomToken",
+ },
+ },
+ {
+ File: "build-interpolated-name.json",
+ InterpolatedName: "build-vardata",
+ Expected: "test.build-vardata",
+ Vars: map[string]string{
+ "build_name": "build-vardata",
+ },
+ },
+ {
+ File: "build-interpolated-name.json",
+ InterpolatedName: "build-12345",
+ Expected: "test.build-12345",
+ Vars: map[string]string{
+ "something": "build-12345",
+ "build_name": "{{user `something`}}",
+ },
+ },
+ {
+ // When no name attribute is provided in the config the builder type is the default name.
+ File: "build-basic.json",
+ InterpolatedName: "test",
+ Expected: "test",
+ },
+ }
+
+ for _, tc := range cases {
+ config.Variables = tc.Vars
+ testCoreTemplate(t, config, fixtureDir(tc.File))
+ core := TestCore(t, config)
+ diags := core.Initialize(InitializeOptions{})
+ if diags.HasErrors() {
+ t.Fatalf("err: %s\n\n%s", tc.File, diags)
+ }
+
+ build, err := core.Build(tc.InterpolatedName)
+ if err != nil {
+ t.Fatalf("err for InterpolatedName(%q): %s", tc.InterpolatedName, err)
+ }
+
+ if build.Name() != tc.Expected {
+ t.Errorf("build type interpolation failed; expected %q, got %q", tc.Expected, build.Name())
+ }
+
+ }
+}
diff --git a/v1.9.4/packer/fixconfigmode_enumer.go b/v1.9.4/packer/fixconfigmode_enumer.go
new file mode 100644
index 0000000..715fa73
--- /dev/null
+++ b/v1.9.4/packer/fixconfigmode_enumer.go
@@ -0,0 +1,50 @@
+// Code generated by "enumer -type FixConfigMode"; DO NOT EDIT.
+
+package packer
+
+import (
+ "fmt"
+)
+
+const _FixConfigModeName = "StdoutInplaceDiff"
+
+var _FixConfigModeIndex = [...]uint8{0, 6, 13, 17}
+
+func (i FixConfigMode) String() string {
+ if i < 0 || i >= FixConfigMode(len(_FixConfigModeIndex)-1) {
+ return fmt.Sprintf("FixConfigMode(%d)", i)
+ }
+ return _FixConfigModeName[_FixConfigModeIndex[i]:_FixConfigModeIndex[i+1]]
+}
+
+var _FixConfigModeValues = []FixConfigMode{0, 1, 2}
+
+var _FixConfigModeNameToValueMap = map[string]FixConfigMode{
+ _FixConfigModeName[0:6]: 0,
+ _FixConfigModeName[6:13]: 1,
+ _FixConfigModeName[13:17]: 2,
+}
+
+// FixConfigModeString retrieves an enum value from the enum constants string name.
+// Throws an error if the param is not part of the enum.
+func FixConfigModeString(s string) (FixConfigMode, error) {
+ if val, ok := _FixConfigModeNameToValueMap[s]; ok {
+ return val, nil
+ }
+ return 0, fmt.Errorf("%s does not belong to FixConfigMode values", s)
+}
+
+// FixConfigModeValues returns all values of the enum
+func FixConfigModeValues() []FixConfigMode {
+ return _FixConfigModeValues
+}
+
+// IsAFixConfigMode returns "true" if the value is listed in the enum definition. "false" otherwise
+func (i FixConfigMode) IsAFixConfigMode() bool {
+ for _, v := range _FixConfigModeValues {
+ if i == v {
+ return true
+ }
+ }
+ return false
+}
diff --git a/v1.9.4/packer/maps.go b/v1.9.4/packer/maps.go
new file mode 100644
index 0000000..6fec5c6
--- /dev/null
+++ b/v1.9.4/packer/maps.go
@@ -0,0 +1,118 @@
+// Copyright (c) HashiCorp, Inc.
+// SPDX-License-Identifier: MPL-2.0
+
+package packer
+
+import (
+ "fmt"
+
+ packersdk "github.com/hashicorp/packer-plugin-sdk/packer"
+)
+
+type MapOfProvisioner map[string]func() (packersdk.Provisioner, error)
+
+func (mop MapOfProvisioner) Has(provisioner string) bool {
+ _, res := mop[provisioner]
+ return res
+}
+
+func (mop MapOfProvisioner) Set(provisioner string, starter func() (packersdk.Provisioner, error)) {
+ mop[provisioner] = starter
+}
+
+func (mop MapOfProvisioner) Start(provisioner string) (packersdk.Provisioner, error) {
+ p, found := mop[provisioner]
+ if !found {
+ return nil, fmt.Errorf("Unknown provisioner %s", provisioner)
+ }
+ return p()
+}
+
+func (mop MapOfProvisioner) List() []string {
+ res := []string{}
+ for k := range mop {
+ res = append(res, k)
+ }
+ return res
+}
+
+type MapOfPostProcessor map[string]func() (packersdk.PostProcessor, error)
+
+func (mopp MapOfPostProcessor) Has(postProcessor string) bool {
+ _, res := mopp[postProcessor]
+ return res
+}
+
+func (mopp MapOfPostProcessor) Set(postProcessor string, starter func() (packersdk.PostProcessor, error)) {
+ mopp[postProcessor] = starter
+}
+
+func (mopp MapOfPostProcessor) Start(postProcessor string) (packersdk.PostProcessor, error) {
+ p, found := mopp[postProcessor]
+ if !found {
+ return nil, fmt.Errorf("Unknown post-processor %s", postProcessor)
+ }
+ return p()
+}
+
+func (mopp MapOfPostProcessor) List() []string {
+ res := []string{}
+ for k := range mopp {
+ res = append(res, k)
+ }
+ return res
+}
+
+type MapOfBuilder map[string]func() (packersdk.Builder, error)
+
+func (mob MapOfBuilder) Has(builder string) bool {
+ _, res := mob[builder]
+ return res
+}
+
+func (mob MapOfBuilder) Set(builder string, starter func() (packersdk.Builder, error)) {
+ mob[builder] = starter
+}
+
+func (mob MapOfBuilder) Start(builder string) (packersdk.Builder, error) {
+ d, found := mob[builder]
+ if !found {
+ return nil, fmt.Errorf("Unknown builder %s", builder)
+ }
+ return d()
+}
+
+func (mob MapOfBuilder) List() []string {
+ res := []string{}
+ for k := range mob {
+ res = append(res, k)
+ }
+ return res
+}
+
+type MapOfDatasource map[string]func() (packersdk.Datasource, error)
+
+func (mod MapOfDatasource) Has(dataSource string) bool {
+ _, res := mod[dataSource]
+ return res
+}
+
+func (mod MapOfDatasource) Set(dataSource string, starter func() (packersdk.Datasource, error)) {
+ mod[dataSource] = starter
+}
+
+func (mod MapOfDatasource) Start(dataSource string) (packersdk.Datasource, error) {
+ d, found := mod[dataSource]
+ if !found {
+ return nil, fmt.Errorf("Unknown data source %s", dataSource)
+ }
+ return d()
+}
+
+func (mod MapOfDatasource) List() []string {
+ res := []string{}
+ for k := range mod {
+ res = append(res, k)
+ }
+ return res
+}
diff --git a/v1.9.4/packer/packer_test.go b/v1.9.4/packer/packer_test.go
new file mode 100644
index 0000000..bc75903
--- /dev/null
+++ b/v1.9.4/packer/packer_test.go
@@ -0,0 +1,14 @@
+// Copyright (c) HashiCorp, Inc.
+// SPDX-License-Identifier: MPL-2.0
+
+package packer
+
+import (
+ "path/filepath"
+)
+
+const FixtureDir = "./test-fixtures"
+
+func fixtureDir(n string) string {
+ return filepath.Join(FixtureDir, n)
+}
diff --git a/v1.9.4/packer/plugin-getter/checksum.go b/v1.9.4/packer/plugin-getter/checksum.go
new file mode 100644
index 0000000..507a17e
--- /dev/null
+++ b/v1.9.4/packer/plugin-getter/checksum.go
@@ -0,0 +1,119 @@
+// Copyright (c) HashiCorp, Inc.
+// SPDX-License-Identifier: MPL-2.0
+
+package plugingetter
+
+import (
+ "bytes"
+ "encoding/hex"
+ "fmt"
+ "hash"
+ "io"
+ "os"
+ "strings"
+)
+
+// A ChecksumError is returned when a checksum differs
+type ChecksumError struct {
+ Hash hash.Hash
+ Actual []byte
+ Expected []byte
+ File string
+}
+
+func (cerr *ChecksumError) Error() string {
+ if cerr == nil {
+ return "<nil>"
+ }
+ return fmt.Sprintf(
+ "Checksums (%T) did not match.\nExpected: %s\nGot : %s\n",
+ cerr.Hash, // ex: *sha256.digest
+ hex.EncodeToString(cerr.Expected),
+ hex.EncodeToString(cerr.Actual),
+ )
+}
+
+type Checksum []byte
+
+func (c Checksum) String() string { return hex.EncodeToString(c) }
+
+type FileChecksum struct {
+ Filename string
+ Expected Checksum
+ Checksummer
+}
+
+type Checksummer struct {
+ // Something like md5 or sha256
+ Type string
+ // Hash function
+ hash.Hash
+}
+
+func (c *Checksummer) FileExt() string {
+ return "_" + strings.ToUpper(c.Type) + "SUM"
+}
+
+// GetCacheChecksumOfFile will extract the checksum from file `filePath + c.FileExt()`.
+// It expects the checksum file to only contains the checksum and nothing else.
+func (c *Checksummer) GetCacheChecksumOfFile(filePath string) ([]byte, error) {
+ checksumFile := filePath + c.FileExt()
+
+ f, err := os.Open(checksumFile)
+ if err != nil {
+ return nil, err
+ }
+ defer f.Close()
+ return c.ParseChecksum(f)
+}
+
+// ParseChecksum expects the checksum reader to only contain the checksum and
+// nothing else.
+func (c *Checksummer) ParseChecksum(f io.Reader) (Checksum, error) {
+ res := make([]byte, c.Hash.Size())
+ _, err := hex.NewDecoder(f).Read(res)
+ if err == io.EOF {
+ err = nil
+ }
+ return res, err
+}
+
+// ChecksumFile compares the expected checksum to the checksum of the file in
+// filePath using the hash function.
+func (c *Checksummer) ChecksumFile(expected []byte, filePath string) error {
+ f, err := os.Open(filePath)
+ if err != nil {
+ return fmt.Errorf("Checksum: failed to open file for checksum: %s", err)
+ }
+ defer f.Close()
+ err = c.Checksum(expected, f)
+ if cerr, ok := err.(*ChecksumError); ok {
+ cerr.File = filePath
+ }
+ return err
+}
+
+func (c *Checksummer) Sum(f io.Reader) ([]byte, error) {
+ c.Hash.Reset()
+ if _, err := io.Copy(c.Hash, f); err != nil {
+ return nil, fmt.Errorf("Failed to hash: %s", err)
+ }
+ return c.Hash.Sum(nil), nil
+}
+
+func (c *Checksummer) Checksum(expected []byte, f io.Reader) error {
+ actual, err := c.Sum(f)
+ if err != nil {
+ return err
+ }
+
+ if !bytes.Equal(actual, expected) {
+ return &ChecksumError{
+ Hash: c.Hash,
+ Actual: actual,
+ Expected: expected,
+ }
+ }
+
+ return nil
+}
diff --git a/v1.9.4/packer/plugin-getter/docs.go b/v1.9.4/packer/plugin-getter/docs.go
new file mode 100644
index 0000000..6c8cfba
--- /dev/null
+++ b/v1.9.4/packer/plugin-getter/docs.go
@@ -0,0 +1,5 @@
+// Copyright (c) HashiCorp, Inc.
+// SPDX-License-Identifier: MPL-2.0
+
+// Package plugingetter defines means to download and install plugins.
+package plugingetter
diff --git a/v1.9.4/packer/plugin-getter/github/docs.go b/v1.9.4/packer/plugin-getter/github/docs.go
new file mode 100644
index 0000000..9c189df
--- /dev/null
+++ b/v1.9.4/packer/plugin-getter/github/docs.go
@@ -0,0 +1,6 @@
+// Copyright (c) HashiCorp, Inc.
+// SPDX-License-Identifier: MPL-2.0
+
+// Package github defines a Github getter.
+
+package github
diff --git a/v1.9.4/packer/plugin-getter/github/getter.go b/v1.9.4/packer/plugin-getter/github/getter.go
new file mode 100644
index 0000000..c094a33
--- /dev/null
+++ b/v1.9.4/packer/plugin-getter/github/getter.go
@@ -0,0 +1,249 @@
+// Copyright (c) HashiCorp, Inc.
+// SPDX-License-Identifier: MPL-2.0
+
+package github
+
+import (
+ "bufio"
+ "bytes"
+ "context"
+ "encoding/json"
+ "errors"
+ "fmt"
+ "io"
+ "io/ioutil"
+ "log"
+ "net/http"
+ "os"
+ "path/filepath"
+ "strings"
+
+ "github.com/google/go-github/v33/github"
+ plugingetter "github.com/hashicorp/packer/packer/plugin-getter"
+ "golang.org/x/oauth2"
+)
+
+const (
+ ghTokenAccessor = "PACKER_GITHUB_API_TOKEN"
+ defaultUserAgent = "packer-github-plugin-getter"
+ defaultHostname = "github.com"
+)
+
+type Getter struct {
+ Client *github.Client
+ UserAgent string
+}
+
+var _ plugingetter.Getter = &Getter{}
+
+func transformChecksumStream() func(in io.ReadCloser) (io.ReadCloser, error) {
+ return func(in io.ReadCloser) (io.ReadCloser, error) {
+ defer in.Close()
+ rd := bufio.NewReader(in)
+ buffer := bytes.NewBufferString("[")
+ json := json.NewEncoder(buffer)
+ for i := 0; ; i++ {
+ line, err := rd.ReadString('\n')
+ if err != nil {
+ if err != io.EOF {
+ return nil, fmt.Errorf(
+ "Error reading checksum file: %s", err)
+ }
+ break
+ }
+ parts := strings.Fields(line)
+ switch len(parts) {
+ case 2: // nominal case
+ checksumString, checksumFilename := parts[0], parts[1]
+
+ if i > 0 {
+ _, _ = buffer.WriteString(",")
+ }
+ if err := json.Encode(struct {
+ Checksum string `json:"checksum"`
+ Filename string `json:"filename"`
+ }{
+ Checksum: checksumString,
+ Filename: checksumFilename,
+ }); err != nil {
+ return nil, err
+ }
+ }
+ }
+ _, _ = buffer.WriteString("]")
+ return ioutil.NopCloser(buffer), nil
+ }
+}
+
+// transformVersionStream get a stream from github tags and transforms it into
+// something Packer wants, namely a json list of Release.
+func transformVersionStream(in io.ReadCloser) (io.ReadCloser, error) {
+ if in == nil {
+ return nil, fmt.Errorf("transformVersionStream got nil body")
+ }
+ defer in.Close()
+ dec := json.NewDecoder(in)
+
+ m := []struct {
+ Ref string `json:"ref"`
+ }{}
+ if err := dec.Decode(&m); err != nil {
+ return nil, err
+ }
+
+ out := []plugingetter.Release{}
+ for _, m := range m {
+ out = append(out, plugingetter.Release{
+ Version: strings.TrimPrefix(m.Ref, "refs/tags/"),
+ })
+ }
+
+ buf := &bytes.Buffer{}
+ if err := json.NewEncoder(buf).Encode(out); err != nil {
+ return nil, err
+ }
+
+ return ioutil.NopCloser(buf), nil
+}
+
+// HostSpecificTokenAuthTransport makes sure the http roundtripper only sets an
+// auth token for requests aimed at a specific host.
+//
+// This helps for example to get release files from Github as Github will
+// redirect to s3 which will error if we give it a Github auth token.
+type HostSpecificTokenAuthTransport struct {
+ // Host to TokenSource map
+ TokenSources map[string]oauth2.TokenSource
+
+ // actual RoundTripper, nil means we use the default one from http.
+ Base http.RoundTripper
+}
+
+// RoundTrip authorizes and authenticates the request with an
+// access token from Transport's Source.
+func (t *HostSpecificTokenAuthTransport) RoundTrip(req *http.Request) (*http.Response, error) {
+ source, found := t.TokenSources[req.Host]
+ if found {
+ reqBodyClosed := false
+ if req.Body != nil {
+ defer func() {
+ if !reqBodyClosed {
+ req.Body.Close()
+ }
+ }()
+ }
+
+ if source == nil {
+ return nil, errors.New("transport's Source is nil")
+ }
+ token, err := source.Token()
+ if err != nil {
+ return nil, err
+ }
+
+ token.SetAuthHeader(req)
+
+ // req.Body is assumed to be closed by the base RoundTripper.
+ reqBodyClosed = true
+ }
+
+ return t.base().RoundTrip(req)
+}
+
+func (t *HostSpecificTokenAuthTransport) base() http.RoundTripper {
+ if t.Base != nil {
+ return t.Base
+ }
+ return http.DefaultTransport
+}
+
+func (g *Getter) Get(what string, opts plugingetter.GetOptions) (io.ReadCloser, error) {
+ if opts.PluginRequirement.Identifier.Hostname != defaultHostname {
+ s := opts.PluginRequirement.Identifier.String() + " doesn't appear to be a valid " + defaultHostname + " source address; check source and try again."
+ return nil, errors.New(s)
+ }
+
+ ctx := context.TODO()
+ if g.Client == nil {
+ var tc *http.Client
+ if tk := os.Getenv(ghTokenAccessor); tk != "" {
+ log.Printf("[DEBUG] github-getter: using %s", ghTokenAccessor)
+ ts := oauth2.StaticTokenSource(
+ &oauth2.Token{AccessToken: tk},
+ )
+ tc = &http.Client{
+ Transport: &HostSpecificTokenAuthTransport{
+ TokenSources: map[string]oauth2.TokenSource{
+ "api.github.com": ts,
+ },
+ },
+ }
+ } else {
+ log.Printf("[WARNING] github-getter: no GitHub token set, if you intend to install plugins often, please set the %s env var", ghTokenAccessor)
+ }
+ g.Client = github.NewClient(tc)
+ g.Client.UserAgent = defaultUserAgent
+ if g.UserAgent != "" {
+ g.Client.UserAgent = g.UserAgent
+ }
+ }
+
+ var req *http.Request
+ var err error
+ transform := func(in io.ReadCloser) (io.ReadCloser, error) {
+ return in, nil
+ }
+
+ switch what {
+ case "releases":
+ u := filepath.ToSlash("/repos/" + opts.PluginRequirement.Identifier.RealRelativePath() + "/git/matching-refs/tags")
+ req, err = g.Client.NewRequest("GET", u, nil)
+ transform = transformVersionStream
+ case "sha256":
+ // something like https://github.com/sylviamoss/packer-plugin-comment/releases/download/v0.2.11/packer-plugin-comment_v0.2.11_x5_SHA256SUMS
+ u := filepath.ToSlash("https://github.com/" + opts.PluginRequirement.Identifier.RealRelativePath() + "/releases/download/" + opts.Version() + "/" + opts.PluginRequirement.FilenamePrefix() + opts.Version() + "_SHA256SUMS")
+ req, err = g.Client.NewRequest(
+ "GET",
+ u,
+ nil,
+ )
+ transform = transformChecksumStream()
+ case "zip":
+ u := filepath.ToSlash("https://github.com/" + opts.PluginRequirement.Identifier.RealRelativePath() + "/releases/download/" + opts.Version() + "/" + opts.ExpectedZipFilename())
+ req, err = g.Client.NewRequest(
+ "GET",
+ u,
+ nil,
+ )
+
+ default:
+ return nil, fmt.Errorf("%q not implemented", what)
+ }
+ if err != nil {
+ return nil, err
+ }
+ log.Printf("[DEBUG] github-getter: getting %q", req.URL)
+ resp, err := g.Client.BareDo(ctx, req)
+ if err != nil {
+ // here BareDo will return an err if the request failed or if the status
+ // is not considered a valid http status. So we have to close the body
+ // if it's not nil.
+ if resp != nil {
+ resp.Body.Close()
+ }
+ switch err := err.(type) {
+ case *github.RateLimitError:
+ return nil, &plugingetter.RateLimitError{
+ SetableEnvVar: ghTokenAccessor,
+ Err: err,
+ ResetTime: err.Rate.Reset.Time,
+ }
+ default:
+ log.Printf("[TRACE] failed requesting: %T. %v", err, err)
+ return nil, err
+ }
+
+ }
+
+ return transform(resp.Body)
+}
diff --git a/v1.9.4/packer/plugin-getter/plugins.go b/v1.9.4/packer/plugin-getter/plugins.go
new file mode 100644
index 0000000..b32ec38
--- /dev/null
+++ b/v1.9.4/packer/plugin-getter/plugins.go
@@ -0,0 +1,744 @@
+// Copyright (c) HashiCorp, Inc.
+// SPDX-License-Identifier: MPL-2.0
+
+package plugingetter
+
+import (
+ "archive/zip"
+ "encoding/hex"
+ "encoding/json"
+ "fmt"
+ "io"
+ "io/ioutil"
+ "log"
+ "os"
+ "path/filepath"
+ "sort"
+ "strconv"
+ "strings"
+ "time"
+
+ "github.com/hashicorp/go-multierror"
+ "github.com/hashicorp/go-version"
+ "github.com/hashicorp/packer-plugin-sdk/tmp"
+ "github.com/hashicorp/packer/hcl2template/addrs"
+)
+
+type Requirements []*Requirement
+
+// Requirement describes a required plugin and how it is installed. Usually a list
+// of required plugins is generated from a config file. From it we check what
+// is actually installed and what needs to happen to get in the desired state.
+type Requirement struct {
+ // Plugin accessor as defined in the config file.
+ // For Packer, using :
+ // required_plugins { amazon = {...} }
+ // Will set Accessor to `amazon`.
+ Accessor string
+
+ // Something like github.com/hashicorp/packer-plugin-amazon, from the
+ // previous example.
+ Identifier *addrs.Plugin
+
+ // VersionConstraints as defined by user. Empty ( to be avoided ) means
+ // highest found version.
+ VersionConstraints version.Constraints
+}
+
+type BinaryInstallationOptions struct {
+ //
+ APIVersionMajor, APIVersionMinor string
+ // OS and ARCH usually should be runtime.GOOS and runtime.ARCH, they allow
+ // to pick the correct binary.
+ OS, ARCH string
+
+ // Ext is ".exe" on windows
+ Ext string
+
+ Checksummers []Checksummer
+}
+
+type ListInstallationsOptions struct {
+ // FromFolders where plugins could be installed. Paths should be absolute for
+ // safety but can also be relative.
+ FromFolders []string
+
+ BinaryInstallationOptions
+}
+
+// RateLimitError is returned when a getter is being rate limited.
+type RateLimitError struct {
+ SetableEnvVar string
+ ResetTime time.Time
+ Err error
+}
+
+func (rlerr *RateLimitError) Error() string {
+ s := fmt.Sprintf("Plugin host rate limited the plugin getter. Try again in %s.\n", time.Until(rlerr.ResetTime))
+ if rlerr.SetableEnvVar != "" {
+ s += fmt.Sprintf("HINT: Set the %s env var with a token to get more requests.\n", rlerr.SetableEnvVar)
+ }
+ s += rlerr.Err.Error()
+ return s
+}
+
+func (pr Requirement) FilenamePrefix() string {
+ if pr.Identifier == nil {
+ return "packer-plugin-"
+ }
+ return "packer-plugin-" + pr.Identifier.Type + "_"
+}
+
+func (opts BinaryInstallationOptions) FilenameSuffix() string {
+ return "_" + opts.OS + "_" + opts.ARCH + opts.Ext
+}
+
+// ListInstallations lists unique installed versions of plugin Requirement pr
+// with opts as a filter.
+//
+// Installations are sorted by version and one binary per version is returned.
+// Last binary detected takes precedence: in the order 'FromFolders' option.
+//
+// At least one opts.Checksumers must be given for a binary to be even
+// considered.
+func (pr Requirement) ListInstallations(opts ListInstallationsOptions) (InstallList, error) {
+ res := InstallList{}
+ FilenamePrefix := pr.FilenamePrefix()
+ filenameSuffix := opts.FilenameSuffix()
+ log.Printf("[TRACE] listing potential installations for %q that match %q. %#v", pr.Identifier, pr.VersionConstraints, opts)
+ for _, knownFolder := range opts.FromFolders {
+ glob := ""
+ if pr.Identifier == nil {
+ glob = filepath.Join(knownFolder, "*", "*", "*", FilenamePrefix+"*"+filenameSuffix)
+ } else {
+ glob = filepath.Join(knownFolder, pr.Identifier.Hostname, pr.Identifier.Namespace, pr.Identifier.Type, FilenamePrefix+"*"+filenameSuffix)
+ }
+
+ matches, err := filepath.Glob(glob)
+ if err != nil {
+ return nil, fmt.Errorf("ListInstallations: %q failed to list binaries in folder: %v", pr.Identifier.String(), err)
+ }
+ for _, path := range matches {
+ fname := filepath.Base(path)
+ if fname == "." {
+ continue
+ }
+
+ // base name could look like packer-plugin-amazon_v1.2.3_x5.1_darwin_amd64.exe
+ versionsStr := strings.TrimPrefix(fname, FilenamePrefix)
+ versionsStr = strings.TrimSuffix(versionsStr, filenameSuffix)
+
+ if pr.Identifier == nil {
+ if idx := strings.Index(versionsStr, "_"); idx > 0 {
+ versionsStr = versionsStr[idx+1:]
+ }
+ }
+
+ // versionsStr now looks like v1.2.3_x5.1 or amazon_v1.2.3_x5.1
+ parts := strings.SplitN(versionsStr, "_", 2)
+ pluginVersionStr, protocolVerionStr := parts[0], parts[1]
+ pv, err := version.NewVersion(pluginVersionStr)
+ if err != nil {
+ // could not be parsed, ignoring the file
+ log.Printf("found %q with an incorrect %q version, ignoring it. %v", path, pluginVersionStr, err)
+ continue
+ }
+
+ // no constraint means always pass, this will happen for implicit
+ // plugin requirements and when we list all plugins.
+ if !pr.VersionConstraints.Check(pv) {
+ log.Printf("[TRACE] version %q of file %q does not match constraint %q", pluginVersionStr, path, pr.VersionConstraints.String())
+ continue
+ }
+
+ if err := opts.CheckProtocolVersion(protocolVerionStr); err != nil {
+ log.Printf("[NOTICE] binary %s requires protocol version %s that is incompatible "+
+ "with this version of Packer. %s", path, protocolVerionStr, err)
+ continue
+ }
+
+ checksumOk := false
+ for _, checksummer := range opts.Checksummers {
+
+ cs, err := checksummer.GetCacheChecksumOfFile(path)
+ if err != nil {
+ log.Printf("[TRACE] GetChecksumOfFile(%q) failed: %v", path, err)
+ continue
+ }
+
+ if err := checksummer.ChecksumFile(cs, path); err != nil {
+ log.Printf("[TRACE] ChecksumFile(%q) failed: %v", path, err)
+ continue
+ }
+ checksumOk = true
+ break
+ }
+ if !checksumOk {
+ log.Printf("[TRACE] No checksum found for %q ignoring possibly unsafe binary", path)
+ continue
+ }
+
+ res.InsertSortedUniq(&Installation{
+ BinaryPath: path,
+ Version: pluginVersionStr,
+ })
+ }
+ }
+ return res, nil
+}
+
+// InstallList is a list of installed plugins (binaries) with their versions,
+// ListInstallations should be used to get an InstallList.
+//
+// ListInstallations sorts binaries by version and one binary per version is
+// returned.
+type InstallList []*Installation
+
+func (l InstallList) String() string {
+ v := &strings.Builder{}
+ v.Write([]byte("["))
+ for i, inst := range l {
+ if i > 0 {
+ v.Write([]byte(","))
+ }
+ fmt.Fprintf(v, "%v", *inst)
+ }
+ v.Write([]byte("]"))
+ return v.String()
+}
+
+// InsertSortedUniq inserts the installation in the right spot in the list by
+// comparing the version lexicographically.
+// A Duplicate version will replace any already present version.
+func (l *InstallList) InsertSortedUniq(install *Installation) {
+ pos := sort.Search(len(*l), func(i int) bool { return (*l)[i].Version >= install.Version })
+ if len(*l) > pos && (*l)[pos].Version == install.Version {
+ // already detected, let's ignore any new foundings, this way any plugin
+ // close to cwd or the packer exec takes precedence; this will be better
+ // for plugin development/tests.
+ return
+ }
+ (*l) = append((*l), nil)
+ copy((*l)[pos+1:], (*l)[pos:])
+ (*l)[pos] = install
+}
+
+// Installation describes a plugin installation
+type Installation struct {
+ // path to where binary is installed, if installed.
+ // Ex: /usr/azr/.packer.d/plugins/github.com/hashicorp/packer-plugin-amazon/packer-plugin-amazon_v1.2.3_darwin_amd64
+ BinaryPath string
+
+ // Version of this plugin, if installed and versionned. Ex:
+ // * v1.2.3 for packer-plugin-amazon_v1.2.3_darwin_x5
+ // * empty for packer-plugin-amazon
+ Version string
+}
+
+// InstallOptions describes the possible options for installing the plugin that
+// fits the plugin Requirement.
+type InstallOptions struct {
+ // Different means to get releases, sha256 and binary files.
+ Getters []Getter
+
+ // Any downloaded binary and checksum file will be put in the last possible
+ // folder of this list.
+ InFolders []string
+
+ BinaryInstallationOptions
+}
+
+type GetOptions struct {
+ PluginRequirement *Requirement
+
+ BinaryInstallationOptions
+
+ version *version.Version
+
+ expectedZipFilename string
+}
+
+// ExpectedZipFilename is the filename of the zip we expect to find, the
+// value is known only after parsing the checksum file file.
+func (gp *GetOptions) ExpectedZipFilename() string {
+ return gp.expectedZipFilename
+}
+
+func (binOpts *BinaryInstallationOptions) CheckProtocolVersion(remoteProt string) error {
+ remoteProt = strings.TrimPrefix(remoteProt, "x")
+ parts := strings.Split(remoteProt, ".")
+ if len(parts) < 2 {
+ return fmt.Errorf("Invalid remote protocol: %q, expected something like '%s.%s'", remoteProt, binOpts.APIVersionMajor, binOpts.APIVersionMinor)
+ }
+ vMajor, vMinor := parts[0], parts[1]
+
+ // no protocol version check
+ if binOpts.APIVersionMajor == "" && binOpts.APIVersionMinor == "" {
+ return nil
+ }
+
+ if vMajor != binOpts.APIVersionMajor {
+ return fmt.Errorf("Unsupported remote protocol MAJOR version %q. The current MAJOR protocol version is %q."+
+ " This version of Packer can only communicate with plugins using that version.", vMajor, binOpts.APIVersionMajor)
+ }
+
+ if vMinor == binOpts.APIVersionMinor {
+ return nil
+ }
+
+ vMinori, err := strconv.Atoi(vMinor)
+ if err != nil {
+ return err
+ }
+
+ APIVersoinMinori, err := strconv.Atoi(binOpts.APIVersionMinor)
+ if err != nil {
+ return err
+ }
+
+ if vMinori > APIVersoinMinori {
+ return fmt.Errorf("Unsupported remote protocol MINOR version %q. The supported MINOR protocol versions are version %q and bellow."+
+ "Please upgrade Packer or use an older version of the plugin if possible.", vMinor, binOpts.APIVersionMinor)
+ }
+
+ return nil
+}
+
+func (gp *GetOptions) Version() string {
+ return "v" + gp.version.String()
+}
+
+// A Getter helps get the appropriate files to download a binary.
+type Getter interface {
+ // Get allows Packer to know more information about releases of a plugin in
+ // order to decide which version to install. Get behaves similarly to an
+ // HTTP server. Packer will stream responses from get in order to do what's
+ // needed. In order to minimize the amount of requests done, Packer is
+ // strict on filenames and we highly recommend on automating releases.
+ // In the future, Packer will make it possible to ship plugin getters as
+ // binaries this is why Packer streams from the output of get, which will
+ // then be a command.
+ //
+ // * 'releases', get 'releases' should return the complete list of Releases
+ // in JSON format following the format of the Release struct. It is also
+ // possible to read GetOptions to filter for a smaller response. Some
+ // getters don't. Packer will then decide the highest compatible
+ // version of the plugin to install by using the sha256 function.
+ //
+ // * 'sha256', get 'sha256' should return a SHA256SUMS txt file. It will be
+ // called with the highest possible & user allowed version from get
+ // 'releases'. Packer will check if the release has a binary matching what
+ // Packer can install and use. If so, get 'binary' will be called;
+ // otherwise, lower versions will be checked.
+ // For version 1.0.0 of the 'hashicorp/amazon' builder, the GitHub getter
+ // will fetch the following URL:
+ // https://github.com/hashicorp/packer-plugin-amazon/releases/download/v1.0.0/packer-plugin-amazon_v1.0.0_SHA256SUMS
+ // This URL can be parameterized to the following one:
+ // https://github.com/{plugin.path}/releases/download/{plugin.version}/packer-plugin-{plugin.name}_{plugin.version}_SHA256SUMS
+ // If Packer is running on Linux AMD 64, then Packer will check for the
+ // existence of a packer-plugin-amazon_v1.0.0_x5.0_linux_amd64 checksum in
+ // that file. This filename can be parameterized to the following one:
+ // packer-plugin-{plugin.name}_{plugin.version}_x{proto_ver.major}.{proto_ver._minor}_{os}_{arch}
+ //
+ // See
+ // https://github.com/hashicorp/packer-plugin-scaffolding/blob/main/.goreleaser.yml
+ // and
+ // https://www.packer.io/docs/plugins/creation#plugin-development-basics
+ // to learn how to create and automate your releases and for docs on
+ // plugin development basics.
+ //
+ // * get 'zip' is called once we know what version we want and that it is
+ // compatible with the OS and Packer. Zip expects an io stream of a zip
+ // file containing a binary. For version 1.0.0 of the 'hashicorp/amazon'
+ // builder and on darwin_amd64, the GitHub getter will fetch the
+ // following ZIP:
+ // https://github.com/hashicorp/packer-plugin-amazon/releases/download/v1.0.0/packer-plugin-amazon_v1.0.0_x5.0_darwin_amd64.zip
+ // this zip is expected to contain a
+ // packer-plugin-amazon_v1.0.0_x5.0_linux_amd64 file that will be checksum
+ // verified then copied to the correct plugin location.
+ Get(what string, opts GetOptions) (io.ReadCloser, error)
+}
+
+type Release struct {
+ Version string `json:"version"`
+}
+
+func ParseReleases(f io.ReadCloser) ([]Release, error) {
+ var releases []Release
+ defer f.Close()
+ return releases, json.NewDecoder(f).Decode(&releases)
+}
+
+type ChecksumFileEntry struct {
+ Filename string `json:"filename"`
+ Checksum string `json:"checksum"`
+ ext, binVersion, os, arch string
+ protVersion string
+}
+
+func (e ChecksumFileEntry) Ext() string { return e.ext }
+func (e ChecksumFileEntry) BinVersion() string { return e.binVersion }
+func (e ChecksumFileEntry) ProtVersion() string { return e.protVersion }
+func (e ChecksumFileEntry) Os() string { return e.os }
+func (e ChecksumFileEntry) Arch() string { return e.arch }
+
+// a file inside will look like so:
+//
+// packer-plugin-comment_v0.2.12_x5.0_freebsd_amd64.zip
+func (e *ChecksumFileEntry) init(req *Requirement) (err error) {
+ filename := e.Filename
+ res := strings.TrimPrefix(filename, req.FilenamePrefix())
+ // res now looks like v0.2.12_x5.0_freebsd_amd64.zip
+
+ e.ext = filepath.Ext(res)
+
+ res = strings.TrimSuffix(res, e.ext)
+ // res now looks like v0.2.12_x5.0_freebsd_amd64
+
+ parts := strings.Split(res, "_")
+ // ["v0.2.12", "x5.0", "freebsd", "amd64"]
+ if len(parts) < 4 {
+ return fmt.Errorf("malformed filename expected %s{version}_x{protocol-version}_{os}_{arch}", req.FilenamePrefix())
+ }
+
+ e.binVersion, e.protVersion, e.os, e.arch = parts[0], parts[1], parts[2], parts[3]
+
+ return err
+}
+
+func (e *ChecksumFileEntry) validate(expectedVersion string, installOpts BinaryInstallationOptions) error {
+ if e.binVersion != expectedVersion {
+ return fmt.Errorf("wrong version: '%s' does not match expected %s ", e.binVersion, expectedVersion)
+ }
+ if e.os != installOpts.OS || e.arch != installOpts.ARCH {
+ return fmt.Errorf("wrong system, expected %s_%s ", installOpts.OS, installOpts.ARCH)
+ }
+
+ return installOpts.CheckProtocolVersion(e.protVersion)
+}
+
+func ParseChecksumFileEntries(f io.Reader) ([]ChecksumFileEntry, error) {
+ var entries []ChecksumFileEntry
+ return entries, json.NewDecoder(f).Decode(&entries)
+}
+
+func (pr *Requirement) InstallLatest(opts InstallOptions) (*Installation, error) {
+
+ getters := opts.Getters
+
+ log.Printf("[TRACE] getting available versions for the %s plugin", pr.Identifier)
+ versions := version.Collection{}
+ var errs *multierror.Error
+ for _, getter := range getters {
+
+ releasesFile, err := getter.Get("releases", GetOptions{
+ PluginRequirement: pr,
+ BinaryInstallationOptions: opts.BinaryInstallationOptions,
+ })
+ if err != nil {
+ errs = multierror.Append(errs, err)
+ log.Printf("[TRACE] %s", err.Error())
+ continue
+ }
+
+ releases, err := ParseReleases(releasesFile)
+ if err != nil {
+ err := fmt.Errorf("could not parse release: %w", err)
+ errs = multierror.Append(errs, err)
+ log.Printf("[TRACE] %s", err.Error())
+ continue
+ }
+ if len(releases) == 0 {
+ err := fmt.Errorf("no release found")
+ errs = multierror.Append(errs, err)
+ log.Printf("[TRACE] %s", err.Error())
+ continue
+ }
+ for _, release := range releases {
+ v, err := version.NewVersion(release.Version)
+ if err != nil {
+ err := fmt.Errorf("could not parse release version %s. %w", release.Version, err)
+ errs = multierror.Append(errs, err)
+ log.Printf("[TRACE] %s, ignoring it", err.Error())
+ continue
+ }
+ if pr.VersionConstraints.Check(v) {
+ versions = append(versions, v)
+ }
+ }
+ if len(versions) == 0 {
+ err := fmt.Errorf("no matching version found in releases. In %v", releases)
+ errs = multierror.Append(errs, err)
+ log.Printf("[TRACE] %s", err.Error())
+ continue
+ }
+
+ break
+ }
+
+ if len(versions) == 0 {
+ if errs.Len() == 0 {
+ err := fmt.Errorf("no release version found for constraints: %q", pr.VersionConstraints.String())
+ errs = multierror.Append(errs, err)
+ }
+ return nil, errs
+ }
+
+ // Here we want to try every release in order, starting from the highest one
+ // that matches the requirements. The system and protocol version need to
+ // match too.
+ sort.Sort(sort.Reverse(versions))
+ log.Printf("[DEBUG] will try to install: %s", versions)
+
+ for _, version := range versions {
+ //TODO(azr): split in its own InstallVersion(version, opts) function
+
+ outputFolder := filepath.Join(
+ // Pick last folder as it's the one with the highest priority
+ opts.InFolders[len(opts.InFolders)-1],
+ // add expected full path
+ filepath.Join(pr.Identifier.Parts()...),
+ )
+
+ log.Printf("[TRACE] fetching checksums file for the %q version of the %s plugin in %q...", version, pr.Identifier, outputFolder)
+
+ var checksum *FileChecksum
+ for _, getter := range getters {
+ if checksum != nil {
+ break
+ }
+ for _, checksummer := range opts.Checksummers {
+ if checksum != nil {
+ break
+ }
+ checksumFile, err := getter.Get(checksummer.Type, GetOptions{
+ PluginRequirement: pr,
+ BinaryInstallationOptions: opts.BinaryInstallationOptions,
+ version: version,
+ })
+ if err != nil {
+ err := fmt.Errorf("could not get %s checksum file for %s version %s. Is the file present on the release and correctly named ? %w", checksummer.Type, pr.Identifier, version, err)
+ errs = multierror.Append(errs, err)
+ log.Printf("[TRACE] %s", err)
+ continue
+ }
+ entries, err := ParseChecksumFileEntries(checksumFile)
+ _ = checksumFile.Close()
+ if err != nil {
+ err := fmt.Errorf("could not parse %s checksumfile: %v. Make sure the checksum file contains a checksum and a binary filename per line", checksummer.Type, err)
+ errs = multierror.Append(errs, err)
+ log.Printf("[TRACE] %s", err)
+ continue
+ }
+
+ for _, entry := range entries {
+ if err := entry.init(pr); err != nil {
+ err := fmt.Errorf("could not parse checksum filename %s. Is it correctly formatted ? %s", entry.Filename, err)
+ errs = multierror.Append(errs, err)
+ log.Printf("[TRACE] %s", err)
+ continue
+ }
+ if err := entry.validate("v"+version.String(), opts.BinaryInstallationOptions); err != nil {
+ err := fmt.Errorf("ignoring invalid remote binary %s: %s", entry.Filename, err)
+ errs = multierror.Append(errs, err)
+ log.Printf("[TRACE] %s", err)
+ continue
+ }
+
+ log.Printf("[TRACE] About to get: %s", entry.Filename)
+
+ cs, err := checksummer.ParseChecksum(strings.NewReader(entry.Checksum))
+ if err != nil {
+ err := fmt.Errorf("could not parse %s checksum: %s. Make sure the checksum file contains the checksum and only the checksum", checksummer.Type, err)
+ errs = multierror.Append(errs, err)
+ log.Printf("[TRACE] %s", err)
+ continue
+ }
+
+ checksum = &FileChecksum{
+ Filename: entry.Filename,
+ Expected: cs,
+ Checksummer: checksummer,
+ }
+ expectedZipFilename := checksum.Filename
+ expectedBinaryFilename := strings.TrimSuffix(expectedZipFilename, filepath.Ext(expectedZipFilename)) + opts.BinaryInstallationOptions.Ext
+
+ for _, outputFolder := range opts.InFolders {
+ potentialOutputFilename := filepath.Join(
+ outputFolder,
+ filepath.Join(pr.Identifier.Parts()...),
+ expectedBinaryFilename,
+ )
+ for _, potentialChecksumer := range opts.Checksummers {
+ // First check if a local checksum file is already here in the expected
+ // download folder. Here we want to download a binary so we only check
+ // for an existing checksum file from the folder we want to download
+ // into.
+ cs, err := potentialChecksumer.GetCacheChecksumOfFile(potentialOutputFilename)
+ if err == nil && len(cs) > 0 {
+ localChecksum := &FileChecksum{
+ Expected: cs,
+ Checksummer: potentialChecksumer,
+ }
+
+ log.Printf("[TRACE] found a pre-exising %q checksum file", potentialChecksumer.Type)
+ // if outputFile is there and matches the checksum: do nothing more.
+ if err := localChecksum.ChecksumFile(localChecksum.Expected, potentialOutputFilename); err == nil {
+ log.Printf("[INFO] %s v%s plugin is already correctly installed in %q", pr.Identifier, version, potentialOutputFilename)
+ return nil, nil // success
+ }
+ }
+ }
+ }
+
+ // The last folder from the installation list is where we will install.
+ outputFileName := filepath.Join(outputFolder, expectedBinaryFilename)
+
+ // create directories if need be
+ if err := os.MkdirAll(outputFolder, 0755); err != nil {
+ err := fmt.Errorf("could not create plugin folder %q: %w", outputFolder, err)
+ errs = multierror.Append(errs, err)
+ log.Printf("[TRACE] %s", err.Error())
+ return nil, errs
+ }
+
+ for _, getter := range getters {
+ // create temporary file that will receive a temporary binary.zip
+ tmpFile, err := tmp.File("packer-plugin-*.zip")
+ if err != nil {
+ err = fmt.Errorf("could not create temporary file to dowload plugin: %w", err)
+ errs = multierror.Append(errs, err)
+ return nil, errs
+ }
+ defer tmpFile.Close()
+
+ // start fetching binary
+ remoteZipFile, err := getter.Get("zip", GetOptions{
+ PluginRequirement: pr,
+ BinaryInstallationOptions: opts.BinaryInstallationOptions,
+ version: version,
+ expectedZipFilename: expectedZipFilename,
+ })
+ if err != nil {
+ err := fmt.Errorf("could not get binary for %s version %s. Is the file present on the release and correctly named ? %s", pr.Identifier, version, err)
+ errs = multierror.Append(errs, err)
+ log.Printf("[TRACE] %v", err)
+ continue
+ }
+
+ // write binary to tmp file
+ _, err = io.Copy(tmpFile, remoteZipFile)
+ _ = remoteZipFile.Close()
+ if err != nil {
+ err := fmt.Errorf("Error getting plugin, trying another getter: %w", err)
+ errs = multierror.Append(errs, err)
+ log.Printf("[TRACE] %s", err)
+ continue
+ }
+
+ if _, err := tmpFile.Seek(0, 0); err != nil {
+ err := fmt.Errorf("Error seeking begining of temporary file for checksumming, continuing: %w", err)
+ errs = multierror.Append(errs, err)
+ log.Printf("[TRACE] %s", err)
+ continue
+ }
+
+ // verify that the checksum for the zip is what we expect.
+ if err := checksum.Checksummer.Checksum(checksum.Expected, tmpFile); err != nil {
+ err := fmt.Errorf("%w. Is the checksum file correct ? Is the binary file correct ?", err)
+ errs = multierror.Append(errs, err)
+ log.Printf("%s, truncating the zipfile", err)
+ if err := tmpFile.Truncate(0); err != nil {
+ log.Printf("[TRACE] %v", err)
+ }
+ continue
+ }
+
+ tmpFileStat, err := tmpFile.Stat()
+ if err != nil {
+ err := fmt.Errorf("failed to stat: %w", err)
+ errs = multierror.Append(errs, err)
+ return nil, errs
+ }
+
+ zr, err := zip.NewReader(tmpFile, tmpFileStat.Size())
+ if err != nil {
+ err := fmt.Errorf("zip : %v", err)
+ errs = multierror.Append(errs, err)
+ return nil, errs
+ }
+
+ var copyFrom io.ReadCloser
+ for _, f := range zr.File {
+ if f.Name != expectedBinaryFilename {
+ continue
+ }
+ copyFrom, err = f.Open()
+ if err != nil {
+ err := fmt.Errorf("failed to open temp file: %w", err)
+ errs = multierror.Append(errs, err)
+ return nil, errs
+ }
+ break
+ }
+ if copyFrom == nil {
+ err := fmt.Errorf("could not find a %s file in zipfile", checksum.Filename)
+ errs = multierror.Append(errs, err)
+ return nil, errs
+ }
+
+ outputFile, err := os.OpenFile(outputFileName, os.O_RDWR|os.O_CREATE|os.O_TRUNC, 0755)
+ if err != nil {
+ err := fmt.Errorf("failed to create %s: %w", outputFileName, err)
+ errs = multierror.Append(errs, err)
+ return nil, errs
+ }
+ defer outputFile.Close()
+
+ if _, err := io.Copy(outputFile, copyFrom); err != nil {
+ err := fmt.Errorf("extract file: %w", err)
+ errs = multierror.Append(errs, err)
+ return nil, errs
+ }
+
+ if _, err := outputFile.Seek(0, 0); err != nil {
+ err := fmt.Errorf("Error seeking begining of binary file for checksumming: %w", err)
+ errs = multierror.Append(errs, err)
+ log.Printf("[WARNING] %v, ignoring", err)
+ }
+
+ cs, err := checksum.Checksummer.Sum(outputFile)
+ if err != nil {
+ err := fmt.Errorf("failed to checksum binary file: %s", err)
+ errs = multierror.Append(errs, err)
+ log.Printf("[WARNING] %v, ignoring", err)
+ }
+
+ if err := ioutil.WriteFile(outputFileName+checksum.Checksummer.FileExt(), []byte(hex.EncodeToString(cs)), 0555); err != nil {
+ err := fmt.Errorf("failed to write local binary checksum file: %s", err)
+ errs = multierror.Append(errs, err)
+ log.Printf("[WARNING] %v, ignoring", err)
+ }
+
+ // Success !!
+ return &Installation{
+ BinaryPath: strings.ReplaceAll(outputFileName, "\\", "/"),
+ Version: "v" + version.String(),
+ }, nil
+ }
+
+ }
+ }
+
+ }
+ }
+
+ if errs.Len() == 0 {
+ err := fmt.Errorf("could not find a local nor a remote checksum for plugin %q %q", pr.Identifier, pr.VersionConstraints)
+ errs = multierror.Append(errs, err)
+ }
+
+ errs = multierror.Append(errs, fmt.Errorf("could not install any compatible version of plugin %q", pr.Identifier))
+
+ return nil, errs
+}
diff --git a/v1.9.4/packer/plugin-getter/plugins_test.go b/v1.9.4/packer/plugin-getter/plugins_test.go
new file mode 100644
index 0000000..3105fb1
--- /dev/null
+++ b/v1.9.4/packer/plugin-getter/plugins_test.go
@@ -0,0 +1,784 @@
+// Copyright (c) HashiCorp, Inc.
+// SPDX-License-Identifier: MPL-2.0
+
+package plugingetter
+
+import (
+ "archive/zip"
+ "bytes"
+ "crypto/sha256"
+ "encoding/json"
+ "fmt"
+ "io"
+ "io/ioutil"
+ "log"
+ "os"
+ "path/filepath"
+ "strings"
+ "testing"
+
+ "github.com/google/go-cmp/cmp"
+ "github.com/hashicorp/go-version"
+ "github.com/hashicorp/hcl/v2"
+ "github.com/hashicorp/packer/hcl2template/addrs"
+)
+
+var (
+ pluginFolderOne = filepath.Join("testdata", "plugins")
+
+ pluginFolderTwo = filepath.Join("testdata", "plugins_2")
+
+ pluginFolderWrongChecksums = filepath.Join("testdata", "wrong_checksums")
+)
+
+func TestChecksumFileEntry_init(t *testing.T) {
+ expectedVersion := "v0.3.0"
+ req := &Requirement{
+ Identifier: &addrs.Plugin{
+ Hostname: "github.com",
+ Namespace: "ddelnano",
+ Type: "xenserver",
+ },
+ }
+
+ checkSum := &ChecksumFileEntry{
+ Filename: fmt.Sprintf("packer-plugin-xenserver_%s_x5.0_darwin_amd64.zip", expectedVersion),
+ Checksum: "0f5969b069b9c0a58f2d5786c422341c70dfe17bd68f896fcbd46677e8c913f1",
+ }
+
+ err := checkSum.init(req)
+
+ if err != nil {
+ t.Fatalf("ChecksumFileEntry.init failure: %v", err)
+ }
+
+ if checkSum.binVersion != expectedVersion {
+ t.Errorf("failed to parse ChecksumFileEntry properly expected version '%s' but found '%s'", expectedVersion, checkSum.binVersion)
+ }
+}
+
+func TestPlugin_ListInstallations(t *testing.T) {
+
+ type fields struct {
+ Identifier string
+ VersionConstraints version.Constraints
+ }
+ tests := []struct {
+ name string
+ fields fields
+ opts ListInstallationsOptions
+ wantErr bool
+ want InstallList
+ }{
+
+ {
+ "windows_all_plugins",
+ fields{
+ // empty
+ },
+ ListInstallationsOptions{
+ []string{
+ pluginFolderOne,
+ pluginFolderTwo,
+ },
+ BinaryInstallationOptions{
+ OS: "windows", ARCH: "amd64",
+ Ext: ".exe",
+ Checksummers: []Checksummer{
+ {
+ Type: "sha256",
+ Hash: sha256.New(),
+ },
+ },
+ },
+ },
+ false,
+ []*Installation{
+ {
+ Version: "v1.2.3",
+ BinaryPath: filepath.Join(pluginFolderOne, "github.com", "hashicorp", "amazon", "packer-plugin-amazon_v1.2.3_x5.0_windows_amd64.exe"),
+ },
+ {
+ Version: "v1.2.4",
+ BinaryPath: filepath.Join(pluginFolderOne, "github.com", "hashicorp", "amazon", "packer-plugin-amazon_v1.2.4_x5.0_windows_amd64.exe"),
+ },
+ {
+ Version: "v1.2.5",
+ BinaryPath: filepath.Join(pluginFolderOne, "github.com", "hashicorp", "amazon", "packer-plugin-amazon_v1.2.5_x5.0_windows_amd64.exe"),
+ },
+ {
+ BinaryPath: filepath.Join(pluginFolderOne, "github.com", "hashicorp", "google", "packer-plugin-google_v4.5.6_x5.0_windows_amd64.exe"),
+ Version: "v4.5.6",
+ },
+ {
+ Version: "v4.5.7",
+ BinaryPath: filepath.Join(pluginFolderOne, "github.com", "hashicorp", "google", "packer-plugin-google_v4.5.7_x5.0_windows_amd64.exe"),
+ },
+ {
+ Version: "v4.5.8",
+ BinaryPath: filepath.Join(pluginFolderOne, "github.com", "hashicorp", "google", "packer-plugin-google_v4.5.8_x5.0_windows_amd64.exe"),
+ },
+ {
+ Version: "v4.5.9",
+ BinaryPath: filepath.Join(pluginFolderTwo, "github.com", "hashicorp", "google", "packer-plugin-google_v4.5.9_x5.0_windows_amd64.exe"),
+ },
+ },
+ },
+
+ {
+ "darwin_amazon_prot_5.0",
+ fields{
+ Identifier: "github.com/hashicorp/amazon",
+ },
+ ListInstallationsOptions{
+ []string{
+ pluginFolderOne,
+ pluginFolderTwo,
+ },
+ BinaryInstallationOptions{
+ APIVersionMajor: "5", APIVersionMinor: "0",
+ OS: "darwin", ARCH: "amd64",
+ Checksummers: []Checksummer{
+ {
+ Type: "sha256",
+ Hash: sha256.New(),
+ },
+ },
+ },
+ },
+ false,
+ []*Installation{
+ {
+ Version: "v1.2.3",
+ BinaryPath: filepath.Join(pluginFolderOne, "github.com", "hashicorp", "amazon", "packer-plugin-amazon_v1.2.3_x5.0_darwin_amd64"),
+ },
+ {
+ Version: "v1.2.4",
+ BinaryPath: filepath.Join(pluginFolderOne, "github.com", "hashicorp", "amazon", "packer-plugin-amazon_v1.2.4_x5.0_darwin_amd64"),
+ },
+ {
+ Version: "v1.2.5",
+ BinaryPath: filepath.Join(pluginFolderOne, "github.com", "hashicorp", "amazon", "packer-plugin-amazon_v1.2.5_x5.0_darwin_amd64"),
+ },
+ },
+ },
+ {
+ "darwin_amazon_prot_5.1",
+ fields{
+ Identifier: "github.com/hashicorp/amazon",
+ },
+ ListInstallationsOptions{
+ []string{
+ pluginFolderOne,
+ pluginFolderTwo,
+ },
+ BinaryInstallationOptions{
+ APIVersionMajor: "5", APIVersionMinor: "1",
+ OS: "darwin", ARCH: "amd64",
+ Checksummers: []Checksummer{
+ {
+ Type: "sha256",
+ Hash: sha256.New(),
+ },
+ },
+ },
+ },
+ false,
+ []*Installation{
+ {
+ Version: "v1.2.3",
+ BinaryPath: filepath.Join(pluginFolderOne, "github.com", "hashicorp", "amazon", "packer-plugin-amazon_v1.2.3_x5.0_darwin_amd64"),
+ },
+ {
+ Version: "v1.2.4",
+ BinaryPath: filepath.Join(pluginFolderOne, "github.com", "hashicorp", "amazon", "packer-plugin-amazon_v1.2.4_x5.0_darwin_amd64"),
+ },
+ {
+ Version: "v1.2.5",
+ BinaryPath: filepath.Join(pluginFolderOne, "github.com", "hashicorp", "amazon", "packer-plugin-amazon_v1.2.5_x5.0_darwin_amd64"),
+ },
+ {
+ Version: "v1.2.6",
+ BinaryPath: filepath.Join(pluginFolderTwo, "github.com", "hashicorp", "amazon", "packer-plugin-amazon_v1.2.6_x5.1_darwin_amd64"),
+ },
+ },
+ },
+ {
+ "windows_amazon",
+ fields{
+ Identifier: "github.com/hashicorp/amazon",
+ },
+ ListInstallationsOptions{
+ []string{
+ pluginFolderOne,
+ pluginFolderTwo,
+ },
+ BinaryInstallationOptions{
+ APIVersionMajor: "5", APIVersionMinor: "0",
+ OS: "windows", ARCH: "amd64",
+ Ext: ".exe",
+ Checksummers: []Checksummer{
+ {
+ Type: "sha256",
+ Hash: sha256.New(),
+ },
+ },
+ },
+ },
+ false,
+ []*Installation{
+ {
+ Version: "v1.2.3",
+ BinaryPath: filepath.Join(pluginFolderOne, "github.com", "hashicorp", "amazon", "packer-plugin-amazon_v1.2.3_x5.0_windows_amd64.exe"),
+ },
+ {
+ Version: "v1.2.4",
+ BinaryPath: filepath.Join(pluginFolderOne, "github.com", "hashicorp", "amazon", "packer-plugin-amazon_v1.2.4_x5.0_windows_amd64.exe"),
+ },
+ {
+ Version: "v1.2.5",
+ BinaryPath: filepath.Join(pluginFolderOne, "github.com", "hashicorp", "amazon", "packer-plugin-amazon_v1.2.5_x5.0_windows_amd64.exe"),
+ },
+ },
+ },
+ {
+ "windows_google_multifolder",
+ fields{
+ Identifier: "github.com/hashicorp/google",
+ },
+ ListInstallationsOptions{
+ []string{
+ pluginFolderOne,
+ pluginFolderTwo,
+ },
+ BinaryInstallationOptions{
+ APIVersionMajor: "5", APIVersionMinor: "0",
+ OS: "windows", ARCH: "amd64",
+ Ext: ".exe",
+ Checksummers: []Checksummer{
+ {
+ Type: "sha256",
+ Hash: sha256.New(),
+ },
+ },
+ },
+ },
+ false,
+ []*Installation{
+ {
+ Version: "v4.5.6",
+ BinaryPath: filepath.Join(pluginFolderOne, "github.com", "hashicorp", "google", "packer-plugin-google_v4.5.6_x5.0_windows_amd64.exe"),
+ },
+ {
+ Version: "v4.5.7",
+ BinaryPath: filepath.Join(pluginFolderOne, "github.com", "hashicorp", "google", "packer-plugin-google_v4.5.7_x5.0_windows_amd64.exe"),
+ },
+ {
+ Version: "v4.5.8",
+ BinaryPath: filepath.Join(pluginFolderOne, "github.com", "hashicorp", "google", "packer-plugin-google_v4.5.8_x5.0_windows_amd64.exe"),
+ },
+ {
+ Version: "v4.5.9",
+ BinaryPath: filepath.Join(pluginFolderTwo, "github.com", "hashicorp", "google", "packer-plugin-google_v4.5.9_x5.0_windows_amd64.exe"),
+ },
+ },
+ },
+ }
+ for _, tt := range tests {
+ t.Run(tt.name, func(t *testing.T) {
+ var identifier *addrs.Plugin
+ if tt.fields.Identifier != "" {
+ var diags hcl.Diagnostics
+ identifier, diags = addrs.ParsePluginSourceString(tt.fields.Identifier)
+ if diags.HasErrors() {
+ t.Fatalf("%v", diags)
+ }
+ }
+ p := Requirement{
+ Identifier: identifier,
+ VersionConstraints: tt.fields.VersionConstraints,
+ }
+ got, err := p.ListInstallations(tt.opts)
+ if (err != nil) != tt.wantErr {
+ t.Errorf("Plugin.ListInstallations() error = %v, wantErr %v", err, tt.wantErr)
+ return
+ }
+ if diff := cmp.Diff(tt.want, got); diff != "" {
+ t.Errorf("Plugin.ListInstallations() unexpected output: %s", diff)
+ }
+ })
+ }
+}
+
+func TestRequirement_InstallLatest(t *testing.T) {
+ type fields struct {
+ Identifier string
+ VersionConstraints string
+ }
+ type args struct {
+ opts InstallOptions
+ }
+ tests := []struct {
+ name string
+ fields fields
+ args args
+ want *Installation
+ wantErr bool
+ }{
+ {"already-installed-same-api-version",
+ fields{"amazon", "v1.2.3"},
+ args{InstallOptions{
+ []Getter{
+ &mockPluginGetter{
+ Releases: []Release{
+ {Version: "v1.2.3"},
+ },
+ ChecksumFileEntries: map[string][]ChecksumFileEntry{
+ "1.2.3": {{
+ // here the checksum file tells us what zipfiles
+ // to expect. maybe we could cache the zip file
+ // ? but then the plugin is present on the drive
+ // twice.
+ Filename: "packer-plugin-amazon_v1.2.3_x5.0_darwin_amd64.zip",
+ Checksum: "1337c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855",
+ }},
+ },
+ },
+ },
+ []string{
+ pluginFolderWrongChecksums,
+ pluginFolderOne,
+ pluginFolderTwo,
+ },
+ BinaryInstallationOptions{
+ APIVersionMajor: "5", APIVersionMinor: "0",
+ OS: "darwin", ARCH: "amd64",
+ Checksummers: []Checksummer{
+ {
+ Type: "sha256",
+ Hash: sha256.New(),
+ },
+ },
+ },
+ }},
+ nil, false},
+
+ {"already-installed-compatible-api-minor-version",
+ // here 'packer' uses the procol version 5.1 which is compatible
+ // with the 5.0 one of an already installed plugin.
+ fields{"amazon", "v1.2.3"},
+ args{InstallOptions{
+ []Getter{
+ &mockPluginGetter{
+ Releases: []Release{
+ {Version: "v1.2.3"},
+ },
+ ChecksumFileEntries: map[string][]ChecksumFileEntry{
+ "1.2.3": {{
+ Filename: "packer-plugin-amazon_v1.2.3_x5.0_darwin_amd64.zip",
+ Checksum: "1337c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855",
+ }},
+ },
+ },
+ },
+ []string{
+ pluginFolderWrongChecksums,
+ pluginFolderOne,
+ pluginFolderTwo,
+ },
+ BinaryInstallationOptions{
+ APIVersionMajor: "5", APIVersionMinor: "1",
+ OS: "darwin", ARCH: "amd64",
+ Checksummers: []Checksummer{
+ {
+ Type: "sha256",
+ Hash: sha256.New(),
+ },
+ },
+ },
+ }},
+ nil, false},
+
+ {"ignore-incompatible-higher-protocol-version",
+ // here 'packer' needs a binary with protocol version 5.0, and a
+ // working plugin is already installed; but a plugin with version
+ // 6.0 is available locally and remotely. It simply needs to be
+ // ignored.
+ fields{"amazon", ">= v1"},
+ args{InstallOptions{
+ []Getter{
+ &mockPluginGetter{
+ Releases: []Release{
+ {Version: "v1.2.3"},
+ {Version: "v1.2.4"},
+ {Version: "v1.2.5"},
+ {Version: "v2.0.0"},
+ },
+ ChecksumFileEntries: map[string][]ChecksumFileEntry{
+ "2.0.0": {{
+ Filename: "packer-plugin-amazon_v2.0.0_x6.0_darwin_amd64.zip",
+ Checksum: "1337c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855",
+ }},
+ "1.2.5": {{
+ Filename: "packer-plugin-amazon_v1.2.5_x5.0_darwin_amd64.zip",
+ Checksum: "1337c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855",
+ }},
+ },
+ },
+ },
+ []string{
+ pluginFolderWrongChecksums,
+ pluginFolderOne,
+ pluginFolderTwo,
+ },
+ BinaryInstallationOptions{
+ APIVersionMajor: "5", APIVersionMinor: "0",
+ OS: "darwin", ARCH: "amd64",
+ Checksummers: []Checksummer{
+ {
+ Type: "sha256",
+ Hash: sha256.New(),
+ },
+ },
+ },
+ }},
+ nil, false},
+
+ {"upgrade-with-diff-protocol-version",
+ // here we have something locally and test that a newer version will
+ // be installed, the newer version has a lower minor protocol
+ // version than the one we support.
+ fields{"amazon", ">= v2"},
+ args{InstallOptions{
+ []Getter{
+ &mockPluginGetter{
+ Releases: []Release{
+ {Version: "v1.2.3"},
+ {Version: "v1.2.4"},
+ {Version: "v1.2.5"},
+ {Version: "v2.0.0"},
+ {Version: "v2.1.0"},
+ {Version: "v2.10.0"},
+ },
+ ChecksumFileEntries: map[string][]ChecksumFileEntry{
+ "2.10.0": {{
+ Filename: "packer-plugin-amazon_v2.10.0_x6.0_darwin_amd64.zip",
+ Checksum: "43156b1900dc09b026b54610c4a152edd277366a7f71ff3812583e4a35dd0d4a",
+ }},
+ },
+ Zips: map[string]io.ReadCloser{
+ "github.com/hashicorp/packer-plugin-amazon/packer-plugin-amazon_v2.10.0_x6.0_darwin_amd64.zip": zipFile(map[string]string{
+ "packer-plugin-amazon_v2.10.0_x6.0_darwin_amd64": "v2.10.0_x6.0_darwin_amd64",
+ }),
+ },
+ },
+ },
+ []string{
+ pluginFolderWrongChecksums,
+ pluginFolderOne,
+ pluginFolderTwo,
+ },
+ BinaryInstallationOptions{
+ APIVersionMajor: "6", APIVersionMinor: "1",
+ OS: "darwin", ARCH: "amd64",
+ Checksummers: []Checksummer{
+ {
+ Type: "sha256",
+ Hash: sha256.New(),
+ },
+ },
+ },
+ }},
+ &Installation{
+ BinaryPath: "testdata/plugins_2/github.com/hashicorp/amazon/packer-plugin-amazon_v2.10.0_x6.0_darwin_amd64",
+ Version: "v2.10.0",
+ }, false},
+
+ {"upgrade-with-same-protocol-version",
+ // here we have something locally and test that a newer version will
+ // be installed.
+ fields{"amazon", ">= v2"},
+ args{InstallOptions{
+ []Getter{
+ &mockPluginGetter{
+ Releases: []Release{
+ {Version: "v1.2.3"},
+ {Version: "v1.2.4"},
+ {Version: "v1.2.5"},
+ {Version: "v2.0.0"},
+ {Version: "v2.1.0"},
+ {Version: "v2.10.0"},
+ {Version: "v2.10.1"},
+ },
+ ChecksumFileEntries: map[string][]ChecksumFileEntry{
+ "2.10.1": {{
+ Filename: "packer-plugin-amazon_v2.10.1_x6.1_darwin_amd64.zip",
+ Checksum: "90ca5b0f13a90238b62581bbf30bacd7e2c9af6592c7f4849627bddbcb039dec",
+ }},
+ },
+ Zips: map[string]io.ReadCloser{
+ "github.com/hashicorp/packer-plugin-amazon/packer-plugin-amazon_v2.10.1_x6.1_darwin_amd64.zip": zipFile(map[string]string{
+ "packer-plugin-amazon_v2.10.1_x6.1_darwin_amd64": "v2.10.1_x6.1_darwin_amd64",
+ }),
+ },
+ },
+ },
+ []string{
+ pluginFolderWrongChecksums,
+ pluginFolderOne,
+ pluginFolderTwo,
+ },
+ BinaryInstallationOptions{
+ APIVersionMajor: "6", APIVersionMinor: "1",
+ OS: "darwin", ARCH: "amd64",
+ Checksummers: []Checksummer{
+ {
+ Type: "sha256",
+ Hash: sha256.New(),
+ },
+ },
+ },
+ }},
+ &Installation{
+ BinaryPath: "testdata/plugins_2/github.com/hashicorp/amazon/packer-plugin-amazon_v2.10.1_x6.1_darwin_amd64",
+ Version: "v2.10.1",
+ }, false},
+
+ {"upgrade-with-one-missing-checksum-file",
+ // here we have something locally and test that a newer version will
+ // be installed.
+ fields{"amazon", ">= v2"},
+ args{InstallOptions{
+ []Getter{
+ &mockPluginGetter{
+ Releases: []Release{
+ {Version: "v1.2.3"},
+ {Version: "v1.2.4"},
+ {Version: "v1.2.5"},
+ {Version: "v2.0.0"},
+ {Version: "v2.1.0"},
+ {Version: "v2.10.0"},
+ {Version: "v2.10.1"},
+ },
+ ChecksumFileEntries: map[string][]ChecksumFileEntry{
+ "2.10.0": {{
+ Filename: "packer-plugin-amazon_v2.10.0_x6.1_linux_amd64.zip",
+ Checksum: "825fc931ae0cb151df0c56be41a17a9136c4d1f1ee73ddb8ed6baa17cef31afa",
+ }},
+ },
+ Zips: map[string]io.ReadCloser{
+ "github.com/hashicorp/packer-plugin-amazon/packer-plugin-amazon_v2.10.0_x6.1_linux_amd64.zip": zipFile(map[string]string{
+ "packer-plugin-amazon_v2.10.0_x6.1_linux_amd64": "v2.10.0_x6.1_linux_amd64",
+ }),
+ },
+ },
+ },
+ []string{
+ pluginFolderWrongChecksums,
+ pluginFolderOne,
+ pluginFolderTwo,
+ },
+ BinaryInstallationOptions{
+ APIVersionMajor: "6", APIVersionMinor: "1",
+ OS: "linux", ARCH: "amd64",
+ Checksummers: []Checksummer{
+ {
+ Type: "sha256",
+ Hash: sha256.New(),
+ },
+ },
+ },
+ }},
+ &Installation{
+ BinaryPath: "testdata/plugins_2/github.com/hashicorp/amazon/packer-plugin-amazon_v2.10.0_x6.1_linux_amd64",
+ Version: "v2.10.0",
+ }, false},
+
+ {"wrong-zip-checksum",
+ // here we have something locally and test that a newer version with
+ // a wrong checksum will not be installed and error.
+ fields{"amazon", ">= v2"},
+ args{InstallOptions{
+ []Getter{
+ &mockPluginGetter{
+ Releases: []Release{
+ {Version: "v2.10.0"},
+ },
+ ChecksumFileEntries: map[string][]ChecksumFileEntry{
+ "2.10.0": {{
+ Filename: "packer-plugin-amazon_v2.10.0_x6.0_darwin_amd64.zip",
+ Checksum: "133713371337133713371337c4a152edd277366a7f71ff3812583e4a35dd0d4a",
+ }},
+ },
+ Zips: map[string]io.ReadCloser{
+ "github.com/hashicorp/packer-plugin-amazon/packer-plugin-amazon_v2.10.0_x6.0_darwin_amd64.zip": zipFile(map[string]string{
+ "packer-plugin-amazon_v2.10.0_x6.0_darwin_amd64": "h4xx",
+ }),
+ },
+ },
+ },
+ []string{
+ pluginFolderWrongChecksums,
+ pluginFolderOne,
+ pluginFolderTwo,
+ },
+ BinaryInstallationOptions{
+ APIVersionMajor: "6", APIVersionMinor: "1",
+ OS: "darwin", ARCH: "amd64",
+ Checksummers: []Checksummer{
+ {
+ Type: "sha256",
+ Hash: sha256.New(),
+ },
+ },
+ },
+ }},
+
+ nil, true},
+
+ {"wrong-local-checksum",
+ // here we have something wrong locally and test that a newer
+ // version with a wrong checksum will not be installed
+ // this should totally error.
+ fields{"amazon", ">= v1"},
+ args{InstallOptions{
+ []Getter{
+ &mockPluginGetter{
+ Releases: []Release{
+ {Version: "v2.10.0"},
+ },
+ ChecksumFileEntries: map[string][]ChecksumFileEntry{
+ "2.10.0": {{
+ Filename: "packer-plugin-amazon_v2.10.0_x6.0_darwin_amd64.zip",
+ Checksum: "133713371337133713371337c4a152edd277366a7f71ff3812583e4a35dd0d4a",
+ }},
+ },
+ Zips: map[string]io.ReadCloser{
+ "github.com/hashicorp/packer-plugin-amazon/packer-plugin-amazon_v2.10.0_x6.0_darwin_amd64.zip": zipFile(map[string]string{
+ "packer-plugin-amazon_v2.10.0_x6.0_darwin_amd64": "h4xx",
+ }),
+ },
+ },
+ },
+ []string{
+ pluginFolderWrongChecksums,
+ },
+ BinaryInstallationOptions{
+ APIVersionMajor: "6", APIVersionMinor: "1",
+ OS: "darwin", ARCH: "amd64",
+ Checksummers: []Checksummer{
+ {
+ Type: "sha256",
+ Hash: sha256.New(),
+ },
+ },
+ },
+ }},
+
+ nil, true},
+ }
+ for _, tt := range tests {
+ t.Run(tt.name, func(t *testing.T) {
+ log.Printf("starting %s test", tt.name)
+
+ identifier, diags := addrs.ParsePluginSourceString("github.com/hashicorp/" + tt.fields.Identifier)
+ if len(diags) != 0 {
+ t.Fatalf("ParsePluginSourceString(%q): %v", tt.fields.Identifier, diags)
+ }
+ cts, err := version.NewConstraint(tt.fields.VersionConstraints)
+ if err != nil {
+ t.Fatalf("version.NewConstraint(%q): %v", tt.fields.Identifier, err)
+ }
+ pr := &Requirement{
+ Identifier: identifier,
+ VersionConstraints: cts,
+ }
+ got, err := pr.InstallLatest(tt.args.opts)
+ if (err != nil) != tt.wantErr {
+ t.Errorf("Requirement.InstallLatest() error = %v, wantErr %v", err, tt.wantErr)
+ return
+ }
+ if diff := cmp.Diff(got, tt.want); diff != "" {
+ t.Errorf("Requirement.InstallLatest() %s", diff)
+ }
+ if tt.want != nil && tt.want.BinaryPath != "" {
+ // Cleanup.
+ // These two files should be here by now and os.Remove will fail if
+ // they aren't.
+ if err := os.Remove(filepath.Clean(tt.want.BinaryPath)); err != nil {
+ t.Fatal(err)
+ }
+ if err := os.Remove(filepath.Clean(tt.want.BinaryPath + "_SHA256SUM")); err != nil {
+ t.Fatal(err)
+ }
+ }
+ })
+ }
+}
+
+type mockPluginGetter struct {
+ Releases []Release
+ ChecksumFileEntries map[string][]ChecksumFileEntry
+ Zips map[string]io.ReadCloser
+}
+
+func (g *mockPluginGetter) Get(what string, options GetOptions) (io.ReadCloser, error) {
+
+ var toEncode interface{}
+ switch what {
+ case "releases":
+ toEncode = g.Releases
+ case "sha256":
+ enc, ok := g.ChecksumFileEntries[options.version.String()]
+ if !ok {
+ return nil, fmt.Errorf("No checksum available for version %q", options.version.String())
+ }
+ toEncode = enc
+ case "zip":
+ acc := options.PluginRequirement.Identifier.Hostname + "/" +
+ options.PluginRequirement.Identifier.RealRelativePath() + "/" +
+ options.ExpectedZipFilename()
+
+ zip, found := g.Zips[acc]
+ if found == false {
+ panic(fmt.Sprintf("could not find zipfile %s. %v", acc, g.Zips))
+ }
+ return zip, nil
+ default:
+ panic("Don't know how to get " + what)
+ }
+
+ read, write := io.Pipe()
+ go func() {
+ if err := json.NewEncoder(write).Encode(toEncode); err != nil {
+ panic(err)
+ }
+ }()
+ return ioutil.NopCloser(read), nil
+}
+
+func zipFile(content map[string]string) io.ReadCloser {
+ buff := bytes.NewBuffer(nil)
+ zipWriter := zip.NewWriter(buff)
+ for fileName, content := range content {
+ header := &zip.FileHeader{
+ Name: fileName,
+ UncompressedSize: uint32(len([]byte(content))),
+ }
+ fWriter, err := zipWriter.CreateHeader(header)
+ if err != nil {
+ panic(err)
+ }
+ _, err = io.Copy(fWriter, strings.NewReader(content))
+ if err != nil {
+ panic(err)
+ }
+ }
+ err := zipWriter.Close()
+ if err != nil {
+ panic(err)
+ }
+ return ioutil.NopCloser(buff)
+}
+
+var _ Getter = &mockPluginGetter{}
diff --git a/v1.9.4/packer/plugin-getter/testdata/plugins/github.com/hashicorp/amazon/packer-plugin-amazon_v1.2.3_x5.0_darwin_amd64 b/v1.9.4/packer/plugin-getter/testdata/plugins/github.com/hashicorp/amazon/packer-plugin-amazon_v1.2.3_x5.0_darwin_amd64
new file mode 100644
index 0000000..e440e5c
--- /dev/null
+++ b/v1.9.4/packer/plugin-getter/testdata/plugins/github.com/hashicorp/amazon/packer-plugin-amazon_v1.2.3_x5.0_darwin_amd64
@@ -0,0 +1 @@
+3
\ No newline at end of file
diff --git a/v1.9.4/packer/plugin-getter/testdata/plugins/github.com/hashicorp/amazon/packer-plugin-amazon_v1.2.3_x5.0_darwin_amd64_SHA256SUM b/v1.9.4/packer/plugin-getter/testdata/plugins/github.com/hashicorp/amazon/packer-plugin-amazon_v1.2.3_x5.0_darwin_amd64_SHA256SUM
new file mode 100644
index 0000000..a135f52
--- /dev/null
+++ b/v1.9.4/packer/plugin-getter/testdata/plugins/github.com/hashicorp/amazon/packer-plugin-amazon_v1.2.3_x5.0_darwin_amd64_SHA256SUM
@@ -0,0 +1 @@
+4e07408562bedb8b60ce05c1decfe3ad16b72230967de01f640b7e4729b49fce
\ No newline at end of file
diff --git a/v1.9.4/packer/plugin-getter/testdata/plugins/github.com/hashicorp/amazon/packer-plugin-amazon_v1.2.3_x5.0_windows_amd64.exe b/v1.9.4/packer/plugin-getter/testdata/plugins/github.com/hashicorp/amazon/packer-plugin-amazon_v1.2.3_x5.0_windows_amd64.exe
new file mode 100644
index 0000000..e440e5c
--- /dev/null
+++ b/v1.9.4/packer/plugin-getter/testdata/plugins/github.com/hashicorp/amazon/packer-plugin-amazon_v1.2.3_x5.0_windows_amd64.exe
@@ -0,0 +1 @@
+3
\ No newline at end of file
diff --git a/v1.9.4/packer/plugin-getter/testdata/plugins/github.com/hashicorp/amazon/packer-plugin-amazon_v1.2.3_x5.0_windows_amd64.exe_SHA256SUM b/v1.9.4/packer/plugin-getter/testdata/plugins/github.com/hashicorp/amazon/packer-plugin-amazon_v1.2.3_x5.0_windows_amd64.exe_SHA256SUM
new file mode 100644
index 0000000..a135f52
--- /dev/null
+++ b/v1.9.4/packer/plugin-getter/testdata/plugins/github.com/hashicorp/amazon/packer-plugin-amazon_v1.2.3_x5.0_windows_amd64.exe_SHA256SUM
@@ -0,0 +1 @@
+4e07408562bedb8b60ce05c1decfe3ad16b72230967de01f640b7e4729b49fce
\ No newline at end of file
diff --git a/v1.9.4/packer/plugin-getter/testdata/plugins/github.com/hashicorp/amazon/packer-plugin-amazon_v1.2.3_x5.1_darwin_amd64 b/v1.9.4/packer/plugin-getter/testdata/plugins/github.com/hashicorp/amazon/packer-plugin-amazon_v1.2.3_x5.1_darwin_amd64
new file mode 100644
index 0000000..e440e5c
--- /dev/null
+++ b/v1.9.4/packer/plugin-getter/testdata/plugins/github.com/hashicorp/amazon/packer-plugin-amazon_v1.2.3_x5.1_darwin_amd64
@@ -0,0 +1 @@
+3
\ No newline at end of file
diff --git a/v1.9.4/packer/plugin-getter/testdata/plugins/github.com/hashicorp/amazon/packer-plugin-amazon_v1.2.3_x5.1_darwin_amd64_SHA256SUM b/v1.9.4/packer/plugin-getter/testdata/plugins/github.com/hashicorp/amazon/packer-plugin-amazon_v1.2.3_x5.1_darwin_amd64_SHA256SUM
new file mode 100644
index 0000000..a135f52
--- /dev/null
+++ b/v1.9.4/packer/plugin-getter/testdata/plugins/github.com/hashicorp/amazon/packer-plugin-amazon_v1.2.3_x5.1_darwin_amd64_SHA256SUM
@@ -0,0 +1 @@
+4e07408562bedb8b60ce05c1decfe3ad16b72230967de01f640b7e4729b49fce
\ No newline at end of file
diff --git a/v1.9.4/packer/plugin-getter/testdata/plugins/github.com/hashicorp/amazon/packer-plugin-amazon_v1.2.4_x5.0_darwin_amd64 b/v1.9.4/packer/plugin-getter/testdata/plugins/github.com/hashicorp/amazon/packer-plugin-amazon_v1.2.4_x5.0_darwin_amd64
new file mode 100644
index 0000000..bf0d87a
--- /dev/null
+++ b/v1.9.4/packer/plugin-getter/testdata/plugins/github.com/hashicorp/amazon/packer-plugin-amazon_v1.2.4_x5.0_darwin_amd64
@@ -0,0 +1 @@
+4
\ No newline at end of file
diff --git a/v1.9.4/packer/plugin-getter/testdata/plugins/github.com/hashicorp/amazon/packer-plugin-amazon_v1.2.4_x5.0_darwin_amd64_SHA256SUM b/v1.9.4/packer/plugin-getter/testdata/plugins/github.com/hashicorp/amazon/packer-plugin-amazon_v1.2.4_x5.0_darwin_amd64_SHA256SUM
new file mode 100644
index 0000000..e85cbd5
--- /dev/null
+++ b/v1.9.4/packer/plugin-getter/testdata/plugins/github.com/hashicorp/amazon/packer-plugin-amazon_v1.2.4_x5.0_darwin_amd64_SHA256SUM
@@ -0,0 +1 @@
+4b227777d4dd1fc61c6f884f48641d02b4d121d3fd328cb08b5531fcacdabf8a
\ No newline at end of file
diff --git a/v1.9.4/packer/plugin-getter/testdata/plugins/github.com/hashicorp/amazon/packer-plugin-amazon_v1.2.4_x5.0_windows_amd64.exe b/v1.9.4/packer/plugin-getter/testdata/plugins/github.com/hashicorp/amazon/packer-plugin-amazon_v1.2.4_x5.0_windows_amd64.exe
new file mode 100644
index 0000000..bf0d87a
--- /dev/null
+++ b/v1.9.4/packer/plugin-getter/testdata/plugins/github.com/hashicorp/amazon/packer-plugin-amazon_v1.2.4_x5.0_windows_amd64.exe
@@ -0,0 +1 @@
+4
\ No newline at end of file
diff --git a/v1.9.4/packer/plugin-getter/testdata/plugins/github.com/hashicorp/amazon/packer-plugin-amazon_v1.2.4_x5.0_windows_amd64.exe_SHA256SUM b/v1.9.4/packer/plugin-getter/testdata/plugins/github.com/hashicorp/amazon/packer-plugin-amazon_v1.2.4_x5.0_windows_amd64.exe_SHA256SUM
new file mode 100644
index 0000000..e85cbd5
--- /dev/null
+++ b/v1.9.4/packer/plugin-getter/testdata/plugins/github.com/hashicorp/amazon/packer-plugin-amazon_v1.2.4_x5.0_windows_amd64.exe_SHA256SUM
@@ -0,0 +1 @@
+4b227777d4dd1fc61c6f884f48641d02b4d121d3fd328cb08b5531fcacdabf8a
\ No newline at end of file
diff --git a/v1.9.4/packer/plugin-getter/testdata/plugins/github.com/hashicorp/amazon/packer-plugin-amazon_v1.2.5_x5.0_darwin_amd64 b/v1.9.4/packer/plugin-getter/testdata/plugins/github.com/hashicorp/amazon/packer-plugin-amazon_v1.2.5_x5.0_darwin_amd64
new file mode 100644
index 0000000..7813681
--- /dev/null
+++ b/v1.9.4/packer/plugin-getter/testdata/plugins/github.com/hashicorp/amazon/packer-plugin-amazon_v1.2.5_x5.0_darwin_amd64
@@ -0,0 +1 @@
+5
\ No newline at end of file
diff --git a/v1.9.4/packer/plugin-getter/testdata/plugins/github.com/hashicorp/amazon/packer-plugin-amazon_v1.2.5_x5.0_darwin_amd64_SHA256SUM b/v1.9.4/packer/plugin-getter/testdata/plugins/github.com/hashicorp/amazon/packer-plugin-amazon_v1.2.5_x5.0_darwin_amd64_SHA256SUM
new file mode 100644
index 0000000..2ef9d7d
--- /dev/null
+++ b/v1.9.4/packer/plugin-getter/testdata/plugins/github.com/hashicorp/amazon/packer-plugin-amazon_v1.2.5_x5.0_darwin_amd64_SHA256SUM
@@ -0,0 +1 @@
+ef2d127de37b942baad06145e54b0c619a1f22327b2ebbcfbec78f5564afe39d
\ No newline at end of file
diff --git a/v1.9.4/packer/plugin-getter/testdata/plugins/github.com/hashicorp/amazon/packer-plugin-amazon_v1.2.5_x5.0_windows_amd64.exe b/v1.9.4/packer/plugin-getter/testdata/plugins/github.com/hashicorp/amazon/packer-plugin-amazon_v1.2.5_x5.0_windows_amd64.exe
new file mode 100644
index 0000000..7813681
--- /dev/null
+++ b/v1.9.4/packer/plugin-getter/testdata/plugins/github.com/hashicorp/amazon/packer-plugin-amazon_v1.2.5_x5.0_windows_amd64.exe
@@ -0,0 +1 @@
+5
\ No newline at end of file
diff --git a/v1.9.4/packer/plugin-getter/testdata/plugins/github.com/hashicorp/amazon/packer-plugin-amazon_v1.2.5_x5.0_windows_amd64.exe_SHA256SUM b/v1.9.4/packer/plugin-getter/testdata/plugins/github.com/hashicorp/amazon/packer-plugin-amazon_v1.2.5_x5.0_windows_amd64.exe_SHA256SUM
new file mode 100644
index 0000000..2ef9d7d
--- /dev/null
+++ b/v1.9.4/packer/plugin-getter/testdata/plugins/github.com/hashicorp/amazon/packer-plugin-amazon_v1.2.5_x5.0_windows_amd64.exe_SHA256SUM
@@ -0,0 +1 @@
+ef2d127de37b942baad06145e54b0c619a1f22327b2ebbcfbec78f5564afe39d
\ No newline at end of file
diff --git a/v1.9.4/packer/plugin-getter/testdata/plugins/github.com/hashicorp/amazon/packer-plugin-amazon_v2.0.0_x6.0_darwin_amd64 b/v1.9.4/packer/plugin-getter/testdata/plugins/github.com/hashicorp/amazon/packer-plugin-amazon_v2.0.0_x6.0_darwin_amd64
new file mode 100644
index 0000000..62f9457
--- /dev/null
+++ b/v1.9.4/packer/plugin-getter/testdata/plugins/github.com/hashicorp/amazon/packer-plugin-amazon_v2.0.0_x6.0_darwin_amd64
@@ -0,0 +1 @@
+6
\ No newline at end of file
diff --git a/v1.9.4/packer/plugin-getter/testdata/plugins/github.com/hashicorp/amazon/packer-plugin-amazon_v2.0.0_x6.0_darwin_amd64_SHA256SUM b/v1.9.4/packer/plugin-getter/testdata/plugins/github.com/hashicorp/amazon/packer-plugin-amazon_v2.0.0_x6.0_darwin_amd64_SHA256SUM
new file mode 100644
index 0000000..2ef9d7d
--- /dev/null
+++ b/v1.9.4/packer/plugin-getter/testdata/plugins/github.com/hashicorp/amazon/packer-plugin-amazon_v2.0.0_x6.0_darwin_amd64_SHA256SUM
@@ -0,0 +1 @@
+ef2d127de37b942baad06145e54b0c619a1f22327b2ebbcfbec78f5564afe39d
\ No newline at end of file
diff --git a/v1.9.4/packer/plugin-getter/testdata/plugins/github.com/hashicorp/google/packer-plugin-google_v4.5.6_x5.0_darwin_amd64 b/v1.9.4/packer/plugin-getter/testdata/plugins/github.com/hashicorp/google/packer-plugin-google_v4.5.6_x5.0_darwin_amd64
new file mode 100644
index 0000000..62f9457
--- /dev/null
+++ b/v1.9.4/packer/plugin-getter/testdata/plugins/github.com/hashicorp/google/packer-plugin-google_v4.5.6_x5.0_darwin_amd64
@@ -0,0 +1 @@
+6
\ No newline at end of file
diff --git a/v1.9.4/packer/plugin-getter/testdata/plugins/github.com/hashicorp/google/packer-plugin-google_v4.5.6_x5.0_darwin_amd64_SHA256SUM b/v1.9.4/packer/plugin-getter/testdata/plugins/github.com/hashicorp/google/packer-plugin-google_v4.5.6_x5.0_darwin_amd64_SHA256SUM
new file mode 100644
index 0000000..e85cbd5
--- /dev/null
+++ b/v1.9.4/packer/plugin-getter/testdata/plugins/github.com/hashicorp/google/packer-plugin-google_v4.5.6_x5.0_darwin_amd64_SHA256SUM
@@ -0,0 +1 @@
+4b227777d4dd1fc61c6f884f48641d02b4d121d3fd328cb08b5531fcacdabf8a
\ No newline at end of file
diff --git a/v1.9.4/packer/plugin-getter/testdata/plugins/github.com/hashicorp/google/packer-plugin-google_v4.5.6_x5.0_windows_amd64.exe b/v1.9.4/packer/plugin-getter/testdata/plugins/github.com/hashicorp/google/packer-plugin-google_v4.5.6_x5.0_windows_amd64.exe
new file mode 100644
index 0000000..62f9457
--- /dev/null
+++ b/v1.9.4/packer/plugin-getter/testdata/plugins/github.com/hashicorp/google/packer-plugin-google_v4.5.6_x5.0_windows_amd64.exe
@@ -0,0 +1 @@
+6
\ No newline at end of file
diff --git a/v1.9.4/packer/plugin-getter/testdata/plugins/github.com/hashicorp/google/packer-plugin-google_v4.5.6_x5.0_windows_amd64.exe_SHA256SUM b/v1.9.4/packer/plugin-getter/testdata/plugins/github.com/hashicorp/google/packer-plugin-google_v4.5.6_x5.0_windows_amd64.exe_SHA256SUM
new file mode 100644
index 0000000..c93f96e
--- /dev/null
+++ b/v1.9.4/packer/plugin-getter/testdata/plugins/github.com/hashicorp/google/packer-plugin-google_v4.5.6_x5.0_windows_amd64.exe_SHA256SUM
@@ -0,0 +1 @@
+e7f6c011776e8db7cd330b54174fd76f7d0216b612387a5ffcfb81e6f0919683
\ No newline at end of file
diff --git a/v1.9.4/packer/plugin-getter/testdata/plugins/github.com/hashicorp/google/packer-plugin-google_v4.5.7_x5.0_darwin_amd64 b/v1.9.4/packer/plugin-getter/testdata/plugins/github.com/hashicorp/google/packer-plugin-google_v4.5.7_x5.0_darwin_amd64
new file mode 100644
index 0000000..c793025
--- /dev/null
+++ b/v1.9.4/packer/plugin-getter/testdata/plugins/github.com/hashicorp/google/packer-plugin-google_v4.5.7_x5.0_darwin_amd64
@@ -0,0 +1 @@
+7
\ No newline at end of file
diff --git a/v1.9.4/packer/plugin-getter/testdata/plugins/github.com/hashicorp/google/packer-plugin-google_v4.5.7_x5.0_darwin_amd64_SHA256SUM b/v1.9.4/packer/plugin-getter/testdata/plugins/github.com/hashicorp/google/packer-plugin-google_v4.5.7_x5.0_darwin_amd64_SHA256SUM
new file mode 100644
index 0000000..e85cbd5
--- /dev/null
+++ b/v1.9.4/packer/plugin-getter/testdata/plugins/github.com/hashicorp/google/packer-plugin-google_v4.5.7_x5.0_darwin_amd64_SHA256SUM
@@ -0,0 +1 @@
+4b227777d4dd1fc61c6f884f48641d02b4d121d3fd328cb08b5531fcacdabf8a
\ No newline at end of file
diff --git a/v1.9.4/packer/plugin-getter/testdata/plugins/github.com/hashicorp/google/packer-plugin-google_v4.5.7_x5.0_windows_amd64.exe b/v1.9.4/packer/plugin-getter/testdata/plugins/github.com/hashicorp/google/packer-plugin-google_v4.5.7_x5.0_windows_amd64.exe
new file mode 100644
index 0000000..c793025
--- /dev/null
+++ b/v1.9.4/packer/plugin-getter/testdata/plugins/github.com/hashicorp/google/packer-plugin-google_v4.5.7_x5.0_windows_amd64.exe
@@ -0,0 +1 @@
+7
\ No newline at end of file
diff --git a/v1.9.4/packer/plugin-getter/testdata/plugins/github.com/hashicorp/google/packer-plugin-google_v4.5.7_x5.0_windows_amd64.exe_SHA256SUM b/v1.9.4/packer/plugin-getter/testdata/plugins/github.com/hashicorp/google/packer-plugin-google_v4.5.7_x5.0_windows_amd64.exe_SHA256SUM
new file mode 100644
index 0000000..e250428
--- /dev/null
+++ b/v1.9.4/packer/plugin-getter/testdata/plugins/github.com/hashicorp/google/packer-plugin-google_v4.5.7_x5.0_windows_amd64.exe_SHA256SUM
@@ -0,0 +1 @@
+7902699be42c8a8e46fbbb4501726517e86b22c56a189f7625a6da49081b2451
\ No newline at end of file
diff --git a/v1.9.4/packer/plugin-getter/testdata/plugins/github.com/hashicorp/google/packer-plugin-google_v4.5.8_x5.0_darwin_amd64 b/v1.9.4/packer/plugin-getter/testdata/plugins/github.com/hashicorp/google/packer-plugin-google_v4.5.8_x5.0_darwin_amd64
new file mode 100644
index 0000000..301160a
--- /dev/null
+++ b/v1.9.4/packer/plugin-getter/testdata/plugins/github.com/hashicorp/google/packer-plugin-google_v4.5.8_x5.0_darwin_amd64
@@ -0,0 +1 @@
+8
\ No newline at end of file
diff --git a/v1.9.4/packer/plugin-getter/testdata/plugins/github.com/hashicorp/google/packer-plugin-google_v4.5.8_x5.0_darwin_amd64_SHA256SUM b/v1.9.4/packer/plugin-getter/testdata/plugins/github.com/hashicorp/google/packer-plugin-google_v4.5.8_x5.0_darwin_amd64_SHA256SUM
new file mode 100644
index 0000000..e85cbd5
--- /dev/null
+++ b/v1.9.4/packer/plugin-getter/testdata/plugins/github.com/hashicorp/google/packer-plugin-google_v4.5.8_x5.0_darwin_amd64_SHA256SUM
@@ -0,0 +1 @@
+4b227777d4dd1fc61c6f884f48641d02b4d121d3fd328cb08b5531fcacdabf8a
\ No newline at end of file
diff --git a/v1.9.4/packer/plugin-getter/testdata/plugins/github.com/hashicorp/google/packer-plugin-google_v4.5.8_x5.0_windows_amd64.exe b/v1.9.4/packer/plugin-getter/testdata/plugins/github.com/hashicorp/google/packer-plugin-google_v4.5.8_x5.0_windows_amd64.exe
new file mode 100644
index 0000000..301160a
--- /dev/null
+++ b/v1.9.4/packer/plugin-getter/testdata/plugins/github.com/hashicorp/google/packer-plugin-google_v4.5.8_x5.0_windows_amd64.exe
@@ -0,0 +1 @@
+8
\ No newline at end of file
diff --git a/v1.9.4/packer/plugin-getter/testdata/plugins/github.com/hashicorp/google/packer-plugin-google_v4.5.8_x5.0_windows_amd64.exe_SHA256SUM b/v1.9.4/packer/plugin-getter/testdata/plugins/github.com/hashicorp/google/packer-plugin-google_v4.5.8_x5.0_windows_amd64.exe_SHA256SUM
new file mode 100644
index 0000000..a1b6ebc
--- /dev/null
+++ b/v1.9.4/packer/plugin-getter/testdata/plugins/github.com/hashicorp/google/packer-plugin-google_v4.5.8_x5.0_windows_amd64.exe_SHA256SUM
@@ -0,0 +1 @@
+2c624232cdd221771294dfbb310aca000a0df6ac8b66b696d90ef06fdefb64a3
\ No newline at end of file
diff --git a/v1.9.4/packer/plugin-getter/testdata/plugins_2/github.com/hashicorp copy/amazon/packer-plugin-amazon_v1.2.6_x5.1_darwin_amd64 b/v1.9.4/packer/plugin-getter/testdata/plugins_2/github.com/hashicorp copy/amazon/packer-plugin-amazon_v1.2.6_x5.1_darwin_amd64
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/v1.9.4/packer/plugin-getter/testdata/plugins_2/github.com/hashicorp copy/amazon/packer-plugin-amazon_v1.2.6_x5.1_darwin_amd64
diff --git a/v1.9.4/packer/plugin-getter/testdata/plugins_2/github.com/hashicorp copy/amazon/packer-plugin-amazon_v1.2.6_x5.1_darwin_amd64_SHA256SUM b/v1.9.4/packer/plugin-getter/testdata/plugins_2/github.com/hashicorp copy/amazon/packer-plugin-amazon_v1.2.6_x5.1_darwin_amd64_SHA256SUM
new file mode 100644
index 0000000..293ce40
--- /dev/null
+++ b/v1.9.4/packer/plugin-getter/testdata/plugins_2/github.com/hashicorp copy/amazon/packer-plugin-amazon_v1.2.6_x5.1_darwin_amd64_SHA256SUM
@@ -0,0 +1 @@
+e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855
\ No newline at end of file
diff --git a/v1.9.4/packer/plugin-getter/testdata/plugins_2/github.com/hashicorp copy/google/packer-plugin-google_v4.5.6_x5.0_darwin_amd64 b/v1.9.4/packer/plugin-getter/testdata/plugins_2/github.com/hashicorp copy/google/packer-plugin-google_v4.5.6_x5.0_darwin_amd64
new file mode 100644
index 0000000..62f9457
--- /dev/null
+++ b/v1.9.4/packer/plugin-getter/testdata/plugins_2/github.com/hashicorp copy/google/packer-plugin-google_v4.5.6_x5.0_darwin_amd64
@@ -0,0 +1 @@
+6
\ No newline at end of file
diff --git a/v1.9.4/packer/plugin-getter/testdata/plugins_2/github.com/hashicorp copy/google/packer-plugin-google_v4.5.6_x5.0_darwin_amd64_SHA256SUM b/v1.9.4/packer/plugin-getter/testdata/plugins_2/github.com/hashicorp copy/google/packer-plugin-google_v4.5.6_x5.0_darwin_amd64_SHA256SUM
new file mode 100644
index 0000000..2ef9d7d
--- /dev/null
+++ b/v1.9.4/packer/plugin-getter/testdata/plugins_2/github.com/hashicorp copy/google/packer-plugin-google_v4.5.6_x5.0_darwin_amd64_SHA256SUM
@@ -0,0 +1 @@
+ef2d127de37b942baad06145e54b0c619a1f22327b2ebbcfbec78f5564afe39d
\ No newline at end of file
diff --git a/v1.9.4/packer/plugin-getter/testdata/plugins_2/github.com/hashicorp copy/google/packer-plugin-google_v4.5.6_x5.0_windows_amd64.exe b/v1.9.4/packer/plugin-getter/testdata/plugins_2/github.com/hashicorp copy/google/packer-plugin-google_v4.5.6_x5.0_windows_amd64.exe
new file mode 100644
index 0000000..62f9457
--- /dev/null
+++ b/v1.9.4/packer/plugin-getter/testdata/plugins_2/github.com/hashicorp copy/google/packer-plugin-google_v4.5.6_x5.0_windows_amd64.exe
@@ -0,0 +1 @@
+6
\ No newline at end of file
diff --git a/v1.9.4/packer/plugin-getter/testdata/plugins_2/github.com/hashicorp copy/google/packer-plugin-google_v4.5.6_x5.0_windows_amd64.exe_SHA256SUM b/v1.9.4/packer/plugin-getter/testdata/plugins_2/github.com/hashicorp copy/google/packer-plugin-google_v4.5.6_x5.0_windows_amd64.exe_SHA256SUM
new file mode 100644
index 0000000..c93f96e
--- /dev/null
+++ b/v1.9.4/packer/plugin-getter/testdata/plugins_2/github.com/hashicorp copy/google/packer-plugin-google_v4.5.6_x5.0_windows_amd64.exe_SHA256SUM
@@ -0,0 +1 @@
+e7f6c011776e8db7cd330b54174fd76f7d0216b612387a5ffcfb81e6f0919683
\ No newline at end of file
diff --git a/v1.9.4/packer/plugin-getter/testdata/plugins_2/github.com/hashicorp copy/google/packer-plugin-google_v4.5.9_x5.0_darwin_amd64 b/v1.9.4/packer/plugin-getter/testdata/plugins_2/github.com/hashicorp copy/google/packer-plugin-google_v4.5.9_x5.0_darwin_amd64
new file mode 100644
index 0000000..f11c82a
--- /dev/null
+++ b/v1.9.4/packer/plugin-getter/testdata/plugins_2/github.com/hashicorp copy/google/packer-plugin-google_v4.5.9_x5.0_darwin_amd64
@@ -0,0 +1 @@
+9
\ No newline at end of file
diff --git a/v1.9.4/packer/plugin-getter/testdata/plugins_2/github.com/hashicorp copy/google/packer-plugin-google_v4.5.9_x5.0_darwin_amd64_SHA256SUM b/v1.9.4/packer/plugin-getter/testdata/plugins_2/github.com/hashicorp copy/google/packer-plugin-google_v4.5.9_x5.0_darwin_amd64_SHA256SUM
new file mode 100644
index 0000000..2ef9d7d
--- /dev/null
+++ b/v1.9.4/packer/plugin-getter/testdata/plugins_2/github.com/hashicorp copy/google/packer-plugin-google_v4.5.9_x5.0_darwin_amd64_SHA256SUM
@@ -0,0 +1 @@
+ef2d127de37b942baad06145e54b0c619a1f22327b2ebbcfbec78f5564afe39d
\ No newline at end of file
diff --git a/v1.9.4/packer/plugin-getter/testdata/plugins_2/github.com/hashicorp copy/google/packer-plugin-google_v4.5.9_x5.0_windows_amd64.exe b/v1.9.4/packer/plugin-getter/testdata/plugins_2/github.com/hashicorp copy/google/packer-plugin-google_v4.5.9_x5.0_windows_amd64.exe
new file mode 100644
index 0000000..f11c82a
--- /dev/null
+++ b/v1.9.4/packer/plugin-getter/testdata/plugins_2/github.com/hashicorp copy/google/packer-plugin-google_v4.5.9_x5.0_windows_amd64.exe
@@ -0,0 +1 @@
+9
\ No newline at end of file
diff --git a/v1.9.4/packer/plugin-getter/testdata/plugins_2/github.com/hashicorp copy/google/packer-plugin-google_v4.5.9_x5.0_windows_amd64.exe_SHA256SUM b/v1.9.4/packer/plugin-getter/testdata/plugins_2/github.com/hashicorp copy/google/packer-plugin-google_v4.5.9_x5.0_windows_amd64.exe_SHA256SUM
new file mode 100644
index 0000000..f74df5f
--- /dev/null
+++ b/v1.9.4/packer/plugin-getter/testdata/plugins_2/github.com/hashicorp copy/google/packer-plugin-google_v4.5.9_x5.0_windows_amd64.exe_SHA256SUM
@@ -0,0 +1 @@
+19581e27de7ced00ff1ce50b2047e7a567c76b1cbaebabe5ef03f7c3017bb5b7
\ No newline at end of file
diff --git a/v1.9.4/packer/plugin-getter/testdata/plugins_2/github.com/hashicorp/amazon/packer-plugin-amazon_v1.2.6_x5.1_darwin_amd64 b/v1.9.4/packer/plugin-getter/testdata/plugins_2/github.com/hashicorp/amazon/packer-plugin-amazon_v1.2.6_x5.1_darwin_amd64
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/v1.9.4/packer/plugin-getter/testdata/plugins_2/github.com/hashicorp/amazon/packer-plugin-amazon_v1.2.6_x5.1_darwin_amd64
diff --git a/v1.9.4/packer/plugin-getter/testdata/plugins_2/github.com/hashicorp/amazon/packer-plugin-amazon_v1.2.6_x5.1_darwin_amd64_SHA256SUM b/v1.9.4/packer/plugin-getter/testdata/plugins_2/github.com/hashicorp/amazon/packer-plugin-amazon_v1.2.6_x5.1_darwin_amd64_SHA256SUM
new file mode 100644
index 0000000..293ce40
--- /dev/null
+++ b/v1.9.4/packer/plugin-getter/testdata/plugins_2/github.com/hashicorp/amazon/packer-plugin-amazon_v1.2.6_x5.1_darwin_amd64_SHA256SUM
@@ -0,0 +1 @@
+e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855
\ No newline at end of file
diff --git a/v1.9.4/packer/plugin-getter/testdata/plugins_2/github.com/hashicorp/google/packer-plugin-google_v4.5.6_x5.0_darwin_amd64 b/v1.9.4/packer/plugin-getter/testdata/plugins_2/github.com/hashicorp/google/packer-plugin-google_v4.5.6_x5.0_darwin_amd64
new file mode 100644
index 0000000..62f9457
--- /dev/null
+++ b/v1.9.4/packer/plugin-getter/testdata/plugins_2/github.com/hashicorp/google/packer-plugin-google_v4.5.6_x5.0_darwin_amd64
@@ -0,0 +1 @@
+6
\ No newline at end of file
diff --git a/v1.9.4/packer/plugin-getter/testdata/plugins_2/github.com/hashicorp/google/packer-plugin-google_v4.5.6_x5.0_darwin_amd64_SHA256SUM b/v1.9.4/packer/plugin-getter/testdata/plugins_2/github.com/hashicorp/google/packer-plugin-google_v4.5.6_x5.0_darwin_amd64_SHA256SUM
new file mode 100644
index 0000000..2ef9d7d
--- /dev/null
+++ b/v1.9.4/packer/plugin-getter/testdata/plugins_2/github.com/hashicorp/google/packer-plugin-google_v4.5.6_x5.0_darwin_amd64_SHA256SUM
@@ -0,0 +1 @@
+ef2d127de37b942baad06145e54b0c619a1f22327b2ebbcfbec78f5564afe39d
\ No newline at end of file
diff --git a/v1.9.4/packer/plugin-getter/testdata/plugins_2/github.com/hashicorp/google/packer-plugin-google_v4.5.6_x5.0_windows_amd64.exe b/v1.9.4/packer/plugin-getter/testdata/plugins_2/github.com/hashicorp/google/packer-plugin-google_v4.5.6_x5.0_windows_amd64.exe
new file mode 100644
index 0000000..62f9457
--- /dev/null
+++ b/v1.9.4/packer/plugin-getter/testdata/plugins_2/github.com/hashicorp/google/packer-plugin-google_v4.5.6_x5.0_windows_amd64.exe
@@ -0,0 +1 @@
+6
\ No newline at end of file
diff --git a/v1.9.4/packer/plugin-getter/testdata/plugins_2/github.com/hashicorp/google/packer-plugin-google_v4.5.6_x5.0_windows_amd64.exe_SHA256SUM b/v1.9.4/packer/plugin-getter/testdata/plugins_2/github.com/hashicorp/google/packer-plugin-google_v4.5.6_x5.0_windows_amd64.exe_SHA256SUM
new file mode 100644
index 0000000..c93f96e
--- /dev/null
+++ b/v1.9.4/packer/plugin-getter/testdata/plugins_2/github.com/hashicorp/google/packer-plugin-google_v4.5.6_x5.0_windows_amd64.exe_SHA256SUM
@@ -0,0 +1 @@
+e7f6c011776e8db7cd330b54174fd76f7d0216b612387a5ffcfb81e6f0919683
\ No newline at end of file
diff --git a/v1.9.4/packer/plugin-getter/testdata/plugins_2/github.com/hashicorp/google/packer-plugin-google_v4.5.9_x5.0_darwin_amd64 b/v1.9.4/packer/plugin-getter/testdata/plugins_2/github.com/hashicorp/google/packer-plugin-google_v4.5.9_x5.0_darwin_amd64
new file mode 100644
index 0000000..f11c82a
--- /dev/null
+++ b/v1.9.4/packer/plugin-getter/testdata/plugins_2/github.com/hashicorp/google/packer-plugin-google_v4.5.9_x5.0_darwin_amd64
@@ -0,0 +1 @@
+9
\ No newline at end of file
diff --git a/v1.9.4/packer/plugin-getter/testdata/plugins_2/github.com/hashicorp/google/packer-plugin-google_v4.5.9_x5.0_darwin_amd64_SHA256SUM b/v1.9.4/packer/plugin-getter/testdata/plugins_2/github.com/hashicorp/google/packer-plugin-google_v4.5.9_x5.0_darwin_amd64_SHA256SUM
new file mode 100644
index 0000000..2ef9d7d
--- /dev/null
+++ b/v1.9.4/packer/plugin-getter/testdata/plugins_2/github.com/hashicorp/google/packer-plugin-google_v4.5.9_x5.0_darwin_amd64_SHA256SUM
@@ -0,0 +1 @@
+ef2d127de37b942baad06145e54b0c619a1f22327b2ebbcfbec78f5564afe39d
\ No newline at end of file
diff --git a/v1.9.4/packer/plugin-getter/testdata/plugins_2/github.com/hashicorp/google/packer-plugin-google_v4.5.9_x5.0_windows_amd64.exe b/v1.9.4/packer/plugin-getter/testdata/plugins_2/github.com/hashicorp/google/packer-plugin-google_v4.5.9_x5.0_windows_amd64.exe
new file mode 100644
index 0000000..f11c82a
--- /dev/null
+++ b/v1.9.4/packer/plugin-getter/testdata/plugins_2/github.com/hashicorp/google/packer-plugin-google_v4.5.9_x5.0_windows_amd64.exe
@@ -0,0 +1 @@
+9
\ No newline at end of file
diff --git a/v1.9.4/packer/plugin-getter/testdata/plugins_2/github.com/hashicorp/google/packer-plugin-google_v4.5.9_x5.0_windows_amd64.exe_SHA256SUM b/v1.9.4/packer/plugin-getter/testdata/plugins_2/github.com/hashicorp/google/packer-plugin-google_v4.5.9_x5.0_windows_amd64.exe_SHA256SUM
new file mode 100644
index 0000000..f74df5f
--- /dev/null
+++ b/v1.9.4/packer/plugin-getter/testdata/plugins_2/github.com/hashicorp/google/packer-plugin-google_v4.5.9_x5.0_windows_amd64.exe_SHA256SUM
@@ -0,0 +1 @@
+19581e27de7ced00ff1ce50b2047e7a567c76b1cbaebabe5ef03f7c3017bb5b7
\ No newline at end of file
diff --git a/v1.9.4/packer/plugin-getter/testdata/wrong_checksums/github.com/hashicorp/amazon/packer-plugin-amazon_v1.2.3_x5.0_darwin_amd64 b/v1.9.4/packer/plugin-getter/testdata/wrong_checksums/github.com/hashicorp/amazon/packer-plugin-amazon_v1.2.3_x5.0_darwin_amd64
new file mode 100644
index 0000000..e440e5c
--- /dev/null
+++ b/v1.9.4/packer/plugin-getter/testdata/wrong_checksums/github.com/hashicorp/amazon/packer-plugin-amazon_v1.2.3_x5.0_darwin_amd64
@@ -0,0 +1 @@
+3
\ No newline at end of file
diff --git a/v1.9.4/packer/plugin-getter/testdata/wrong_checksums/github.com/hashicorp/amazon/packer-plugin-amazon_v1.2.3_x5.0_darwin_amd64_SHA256SUM b/v1.9.4/packer/plugin-getter/testdata/wrong_checksums/github.com/hashicorp/amazon/packer-plugin-amazon_v1.2.3_x5.0_darwin_amd64_SHA256SUM
new file mode 100644
index 0000000..2d660ef
--- /dev/null
+++ b/v1.9.4/packer/plugin-getter/testdata/wrong_checksums/github.com/hashicorp/amazon/packer-plugin-amazon_v1.2.3_x5.0_darwin_amd64_SHA256SUM
@@ -0,0 +1 @@
+1337408562bedb8b60ce05c1decfe3ad16b72230967de01f640b7e4729b49fce
\ No newline at end of file
diff --git a/v1.9.4/packer/plugin-getter/testdata/wrong_checksums/github.com/hashicorp/amazon/packer-plugin-amazon_v1.2.6_x5.1_darwin_amd64 b/v1.9.4/packer/plugin-getter/testdata/wrong_checksums/github.com/hashicorp/amazon/packer-plugin-amazon_v1.2.6_x5.1_darwin_amd64
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/v1.9.4/packer/plugin-getter/testdata/wrong_checksums/github.com/hashicorp/amazon/packer-plugin-amazon_v1.2.6_x5.1_darwin_amd64
diff --git a/v1.9.4/packer/plugin.go b/v1.9.4/packer/plugin.go
new file mode 100644
index 0000000..caf05df
--- /dev/null
+++ b/v1.9.4/packer/plugin.go
@@ -0,0 +1,425 @@
+// Copyright (c) HashiCorp, Inc.
+// SPDX-License-Identifier: MPL-2.0
+
+package packer
+
+import (
+ "crypto/sha256"
+ "encoding/json"
+ "fmt"
+ "log"
+ "os"
+ "os/exec"
+ "path/filepath"
+ "runtime"
+ "sort"
+ "strings"
+
+ packersdk "github.com/hashicorp/packer-plugin-sdk/packer"
+ pluginsdk "github.com/hashicorp/packer-plugin-sdk/plugin"
+ plugingetter "github.com/hashicorp/packer/packer/plugin-getter"
+)
+
+var defaultChecksummer = plugingetter.Checksummer{
+ Type: "sha256",
+ Hash: sha256.New(),
+}
+
+// PluginConfig helps load and use packer plugins
+type PluginConfig struct {
+ KnownPluginFolders []string
+ PluginMinPort int
+ PluginMaxPort int
+ Builders BuilderSet
+ Provisioners ProvisionerSet
+ PostProcessors PostProcessorSet
+ DataSources DatasourceSet
+}
+
+// PACKERSPACE is used to represent the spaces that separate args for a command
+// without being confused with spaces in the path to the command itself.
+const PACKERSPACE = "-PACKERSPACE-"
+
+// Discover discovers plugins.
+//
+// Search the directory of the executable, then the plugins directory, and
+// finally the CWD, in that order. Any conflicts will overwrite previously
+// found plugins, in that order.
+// Hence, the priority order is the reverse of the search order - i.e., the
+// CWD has the highest priority.
+func (c *PluginConfig) Discover() error {
+ if c.Builders == nil {
+ c.Builders = MapOfBuilder{}
+ }
+ if c.Provisioners == nil {
+ c.Provisioners = MapOfProvisioner{}
+ }
+ if c.PostProcessors == nil {
+ c.PostProcessors = MapOfPostProcessor{}
+ }
+ if c.DataSources == nil {
+ c.DataSources = MapOfDatasource{}
+ }
+
+ // If we are already inside a plugin process we should not need to
+ // discover anything.
+ if os.Getenv(pluginsdk.MagicCookieKey) == pluginsdk.MagicCookieValue {
+ return nil
+ }
+
+ if len(c.KnownPluginFolders) == 0 {
+ //PluginFolders should match the call in github.com/hahicorp/packer/main.go#loadConfig
+ c.KnownPluginFolders = PluginFolders(".")
+ }
+
+ // TODO after JSON is deprecated remove support for legacy component plugins.
+ for _, knownFolder := range c.KnownPluginFolders {
+ if err := c.discoverLegacyMonoComponents(knownFolder); err != nil {
+ return err
+ }
+ }
+
+ // Pick last folder as it's the one with the highest priority
+ // This is the same logic used when installing plugins via Packer's plugin installation commands.
+ pluginInstallationPath := c.KnownPluginFolders[len(c.KnownPluginFolders)-1]
+ if err := c.discoverInstalledComponents(pluginInstallationPath); err != nil {
+ return err
+ }
+
+ // Manually installed plugins take precedence over all. Duplicate plugins installed
+ // prior to the packer plugins install command should be removed by user to avoid overrides.
+ for _, knownFolder := range c.KnownPluginFolders {
+ pluginPaths, err := c.discoverSingle(filepath.Join(knownFolder, "packer-plugin-*"))
+ if err != nil {
+ return err
+ }
+ for pluginName, pluginPath := range pluginPaths {
+ // Test pluginPath points to an executable
+ if _, err := exec.LookPath(pluginPath); err != nil {
+ log.Printf("[WARN] %q is not executable; skipping", pluginPath)
+ continue
+ }
+ if err := c.DiscoverMultiPlugin(pluginName, pluginPath); err != nil {
+ return err
+ }
+ }
+ }
+ return nil
+}
+
+func (c *PluginConfig) discoverLegacyMonoComponents(path string) error {
+ var err error
+ log.Printf("[TRACE] discovering plugins in %s", path)
+
+ if !filepath.IsAbs(path) {
+ path, err = filepath.Abs(path)
+ if err != nil {
+ return err
+ }
+ }
+ var externallyUsed []string
+
+ pluginPaths, err := c.discoverSingle(filepath.Join(path, "packer-builder-*"))
+ if err != nil {
+ return err
+ }
+ for pluginName, pluginPath := range pluginPaths {
+ newPath := pluginPath // this needs to be stored in a new variable for the func below
+ c.Builders.Set(pluginName, func() (packersdk.Builder, error) {
+ return c.Client(newPath).Builder()
+ })
+ externallyUsed = append(externallyUsed, pluginName)
+ }
+ if len(externallyUsed) > 0 {
+ sort.Strings(externallyUsed)
+ log.Printf("[INFO] using external builders: %v", externallyUsed)
+ externallyUsed = nil
+ }
+
+ pluginPaths, err = c.discoverSingle(filepath.Join(path, "packer-post-processor-*"))
+ if err != nil {
+ return err
+ }
+ for pluginName, pluginPath := range pluginPaths {
+ newPath := pluginPath // this needs to be stored in a new variable for the func below
+ c.PostProcessors.Set(pluginName, func() (packersdk.PostProcessor, error) {
+ return c.Client(newPath).PostProcessor()
+ })
+ externallyUsed = append(externallyUsed, pluginName)
+ }
+ if len(externallyUsed) > 0 {
+ sort.Strings(externallyUsed)
+ log.Printf("using external post-processors %v", externallyUsed)
+ externallyUsed = nil
+ }
+
+ pluginPaths, err = c.discoverSingle(filepath.Join(path, "packer-provisioner-*"))
+ if err != nil {
+ return err
+ }
+ for pluginName, pluginPath := range pluginPaths {
+ newPath := pluginPath // this needs to be stored in a new variable for the func below
+ c.Provisioners.Set(pluginName, func() (packersdk.Provisioner, error) {
+ return c.Client(newPath).Provisioner()
+ })
+ externallyUsed = append(externallyUsed, pluginName)
+ }
+ if len(externallyUsed) > 0 {
+ sort.Strings(externallyUsed)
+ log.Printf("using external provisioners %v", externallyUsed)
+ externallyUsed = nil
+ }
+
+ pluginPaths, err = c.discoverSingle(filepath.Join(path, "packer-datasource-*"))
+ if err != nil {
+ return err
+ }
+ for pluginName, pluginPath := range pluginPaths {
+ newPath := pluginPath // this needs to be stored in a new variable for the func below
+ c.DataSources.Set(pluginName, func() (packersdk.Datasource, error) {
+ return c.Client(newPath).Datasource()
+ })
+ externallyUsed = append(externallyUsed, pluginName)
+ }
+ if len(externallyUsed) > 0 {
+ sort.Strings(externallyUsed)
+ log.Printf("using external datasource %v", externallyUsed)
+ }
+
+ return nil
+}
+
+func (c *PluginConfig) discoverSingle(glob string) (map[string]string, error) {
+ matches, err := filepath.Glob(glob)
+ if err != nil {
+ return nil, err
+ }
+ var prefix string
+ res := make(map[string]string)
+ // Sort the matches so we add the newer version of a plugin last
+ sort.Strings(matches)
+ prefix = filepath.Base(glob)
+ prefix = prefix[:strings.Index(prefix, "*")]
+ for _, match := range matches {
+ file := filepath.Base(match)
+ // skip folders like packer-plugin-sdk
+ if stat, err := os.Stat(file); err == nil && stat.IsDir() {
+ continue
+ }
+
+ // On Windows, ignore any plugins that don't end in .exe.
+ // We could do a full PATHEXT parse, but this is probably good enough.
+ if runtime.GOOS == "windows" && strings.ToLower(filepath.Ext(file)) != ".exe" {
+ log.Printf(
+ "[TRACE] Ignoring plugin match %s, no exe extension",
+ match)
+ continue
+ }
+
+ if strings.Contains(strings.ToUpper(file), defaultChecksummer.FileExt()) {
+ log.Printf(
+ "[TRACE] Ignoring plugin match %s, which looks to be a checksum file",
+ match)
+ continue
+
+ }
+
+ // If the filename has a ".", trim up to there
+ if idx := strings.Index(file, ".exe"); idx >= 0 {
+ file = file[:idx]
+ }
+
+ // Look for foo-bar-baz. The plugin name is "baz"
+ pluginName := file[len(prefix):]
+ // multi-component plugins installed via the plugins subcommand will have a name that looks like baz_vx.y.z_x5.0_darwin_arm64.
+ // After the split the plugin name is "baz".
+ pluginName = strings.SplitN(pluginName, "_", 2)[0]
+
+ log.Printf("[INFO] Discovered potential plugin: %s = %s", pluginName, match)
+ pluginPath, err := filepath.Abs(match)
+ if err != nil {
+ pluginPath = match
+ }
+ res[pluginName] = pluginPath
+ }
+
+ return res, nil
+}
+
+// DiscoverMultiPlugin takes the description from a multi-component plugin
+// binary and makes the plugins available to use in Packer. Each plugin found in the
+// binary will be addressable using `${pluginName}-${builderName}` for example.
+// pluginName could be manually set. It usually is a cloud name like amazon.
+// pluginName can be extrapolated from the filename of the binary; so
+// if the "packer-plugin-amazon" binary had an "ebs" builder one could use
+// the "amazon-ebs" builder.
+func (c *PluginConfig) DiscoverMultiPlugin(pluginName, pluginPath string) error {
+ out, err := exec.Command(pluginPath, "describe").Output()
+ if err != nil {
+ return err
+ }
+ var desc pluginsdk.SetDescription
+ if err := json.Unmarshal(out, &desc); err != nil {
+ return err
+ }
+
+ pluginPrefix := pluginName + "-"
+
+ for _, builderName := range desc.Builders {
+ builderName := builderName // copy to avoid pointer overwrite issue
+ key := pluginPrefix + builderName
+ if builderName == pluginsdk.DEFAULT_NAME {
+ key = pluginName
+ }
+ c.Builders.Set(key, func() (packersdk.Builder, error) {
+ return c.Client(pluginPath, "start", "builder", builderName).Builder()
+ })
+ }
+
+ if len(desc.Builders) > 0 {
+ log.Printf("[INFO] found external %v builders from %s plugin", desc.Builders, pluginName)
+ }
+
+ for _, postProcessorName := range desc.PostProcessors {
+ postProcessorName := postProcessorName // copy to avoid pointer overwrite issue
+ key := pluginPrefix + postProcessorName
+ if postProcessorName == pluginsdk.DEFAULT_NAME {
+ key = pluginName
+ }
+ c.PostProcessors.Set(key, func() (packersdk.PostProcessor, error) {
+ return c.Client(pluginPath, "start", "post-processor", postProcessorName).PostProcessor()
+ })
+ }
+
+ if len(desc.PostProcessors) > 0 {
+ log.Printf("[INFO] found external %v post-processors from %s plugin", desc.PostProcessors, pluginName)
+ }
+
+ for _, provisionerName := range desc.Provisioners {
+ provisionerName := provisionerName // copy to avoid pointer overwrite issue
+ key := pluginPrefix + provisionerName
+ if provisionerName == pluginsdk.DEFAULT_NAME {
+ key = pluginName
+ }
+ c.Provisioners.Set(key, func() (packersdk.Provisioner, error) {
+ return c.Client(pluginPath, "start", "provisioner", provisionerName).Provisioner()
+ })
+ }
+ if len(desc.Provisioners) > 0 {
+ log.Printf("found external %v provisioner from %s plugin", desc.Provisioners, pluginName)
+ }
+
+ for _, datasourceName := range desc.Datasources {
+ datasourceName := datasourceName // copy to avoid pointer overwrite issue
+ key := pluginPrefix + datasourceName
+ if datasourceName == pluginsdk.DEFAULT_NAME {
+ key = pluginName
+ }
+ c.DataSources.Set(key, func() (packersdk.Datasource, error) {
+ return c.Client(pluginPath, "start", "datasource", datasourceName).Datasource()
+ })
+ }
+ if len(desc.Datasources) > 0 {
+ log.Printf("found external %v datasource from %s plugin", desc.Datasources, pluginName)
+ }
+
+ return nil
+}
+
+func (c *PluginConfig) Client(path string, args ...string) *PluginClient {
+ originalPath := path
+
+ // Check for special case using `packer plugin PLUGIN`
+ if strings.Contains(path, PACKERSPACE) {
+ parts := strings.Split(path, PACKERSPACE)
+ path = parts[0]
+ args = parts[1:]
+ }
+
+ // First attempt to find the executable by consulting the PATH.
+ path, err := exec.LookPath(path)
+ if err != nil {
+ // If that doesn't work, look for it in the same directory
+ // as the `packer` executable (us).
+ log.Printf("[INFO] exec.LookPath: %s : %v. Checking same directory as executable.", path, err)
+ exePath, err := os.Executable()
+ if err != nil {
+ log.Printf("Couldn't get current exe path: %s", err)
+ } else {
+ log.Printf("Current exe path: %s", exePath)
+ path = filepath.Join(filepath.Dir(exePath), filepath.Base(originalPath))
+ }
+ }
+
+ // If everything failed, just use the original path and let the error
+ // bubble through.
+ if path == "" {
+ path = originalPath
+ }
+
+ if strings.Contains(originalPath, PACKERSPACE) {
+ log.Printf("[INFO] Starting internal plugin %s", args[len(args)-1])
+ } else {
+ log.Printf("[INFO] Starting external plugin %s %s", path, strings.Join(args, " "))
+ }
+ var config PluginClientConfig
+ config.Cmd = exec.Command(path, args...)
+ config.Managed = true
+ config.MinPort = c.PluginMinPort
+ config.MaxPort = c.PluginMaxPort
+ return NewClient(&config)
+}
+
+// discoverInstalledComponents scans the provided path for plugins installed by running packer plugins install or packer init.
+// Valid plugins contain a matching system binary and valid checksum file.
+func (c *PluginConfig) discoverInstalledComponents(path string) error {
+ //Check for installed plugins using the `packer plugins install` command
+ binInstallOpts := plugingetter.BinaryInstallationOptions{
+ OS: runtime.GOOS,
+ ARCH: runtime.GOARCH,
+ APIVersionMajor: pluginsdk.APIVersionMajor,
+ APIVersionMinor: pluginsdk.APIVersionMinor,
+ Checksummers: []plugingetter.Checksummer{
+ defaultChecksummer,
+ },
+ }
+
+ if runtime.GOOS == "windows" {
+ binInstallOpts.Ext = ".exe"
+ }
+
+ pluginPath := filepath.Join(path, "*", "*", "*", fmt.Sprintf("packer-plugin-*%s", binInstallOpts.FilenameSuffix()))
+ pluginPaths, err := c.discoverSingle(pluginPath)
+ if err != nil {
+ return err
+ }
+
+ for pluginName, pluginPath := range pluginPaths {
+ var checksumOk bool
+ for _, checksummer := range binInstallOpts.Checksummers {
+ cs, err := checksummer.GetCacheChecksumOfFile(pluginPath)
+ if err != nil {
+ log.Printf("[TRACE] GetChecksumOfFile(%q) failed: %v", pluginPath, err)
+ continue
+ }
+
+ if err := checksummer.ChecksumFile(cs, pluginPath); err != nil {
+ log.Printf("[TRACE] ChecksumFile(%q) failed: %v", pluginPath, err)
+ continue
+ }
+ checksumOk = true
+ break
+ }
+
+ if !checksumOk {
+ log.Printf("[WARN] No checksum found for %q ignoring possibly unsafe binary", path)
+ continue
+ }
+
+ if err := c.DiscoverMultiPlugin(pluginName, pluginPath); err != nil {
+ return err
+ }
+ }
+
+ return nil
+}
diff --git a/v1.9.4/packer/plugin_client.go b/v1.9.4/packer/plugin_client.go
new file mode 100644
index 0000000..f1d1274
--- /dev/null
+++ b/v1.9.4/packer/plugin_client.go
@@ -0,0 +1,420 @@
+// Copyright (c) HashiCorp, Inc.
+// SPDX-License-Identifier: MPL-2.0
+
+package packer
+
+import (
+ "bufio"
+ "errors"
+ "fmt"
+ "io"
+ "io/ioutil"
+ "log"
+ "net"
+ "os"
+ "os/exec"
+ "path/filepath"
+ "strings"
+ "sync"
+ "time"
+ "unicode"
+
+ packersdk "github.com/hashicorp/packer-plugin-sdk/packer"
+ pluginsdk "github.com/hashicorp/packer-plugin-sdk/plugin"
+ packerrpc "github.com/hashicorp/packer-plugin-sdk/rpc"
+)
+
+// If this is true, then the "unexpected EOF" panic will not be
+// raised throughout the clients.
+var Killed = false
+
+// This is a slice of the "managed" clients which are cleaned up when
+// calling Cleanup
+var managedClients = make([]*PluginClient, 0, 5)
+
+// Client handles the lifecycle of a plugin application, determining its
+// RPC address, and returning various types of packer interface implementations
+// across the multi-process communication layer.
+type PluginClient struct {
+ config *PluginClientConfig
+ exited bool
+ doneLogging chan struct{}
+ l sync.Mutex
+ address net.Addr
+}
+
+// PluginClientConfig is the configuration used to initialize a new
+// plugin client. After being used to initialize a plugin client,
+// that configuration must not be modified again.
+type PluginClientConfig struct {
+ // The unstarted subprocess for starting the plugin.
+ Cmd *exec.Cmd
+
+ // Managed represents if the client should be managed by the
+ // plugin package or not. If true, then by calling CleanupClients,
+ // it will automatically be cleaned up. Otherwise, the client
+ // user is fully responsible for making sure to Kill all plugin
+ // clients. By default the client is _not_ managed.
+ Managed bool
+
+ // The minimum and maximum port to use for communicating with
+ // the subprocess. If not set, this defaults to 10,000 and 25,000
+ // respectively.
+ MinPort, MaxPort int
+
+ // StartTimeout is the timeout to wait for the plugin to say it
+ // has started successfully.
+ StartTimeout time.Duration
+
+ // If non-nil, then the stderr of the client will be written to here
+ // (as well as the log).
+ Stderr io.Writer
+}
+
+// This makes sure all the managed subprocesses are killed and properly
+// logged. This should be called before the parent process running the
+// plugins exits.
+//
+// This must only be called _once_.
+func CleanupClients() {
+ // Set the killed to true so that we don't get unexpected panics
+ Killed = true
+
+ // Kill all the managed clients in parallel and use a WaitGroup
+ // to wait for them all to finish up.
+ var wg sync.WaitGroup
+ for _, client := range managedClients {
+ wg.Add(1)
+
+ go func(client *PluginClient) {
+ client.Kill()
+ wg.Done()
+ }(client)
+ }
+
+ log.Println("waiting for all plugin processes to complete...")
+ wg.Wait()
+}
+
+// Creates a new plugin client which manages the lifecycle of an external
+// plugin and gets the address for the RPC connection.
+//
+// The client must be cleaned up at some point by calling Kill(). If
+// the client is a managed client (created with NewManagedClient) you
+// can just call CleanupClients at the end of your program and they will
+// be properly cleaned.
+func NewClient(config *PluginClientConfig) (c *PluginClient) {
+ if config.MinPort == 0 && config.MaxPort == 0 {
+ config.MinPort = 10000
+ config.MaxPort = 25000
+ }
+
+ if config.StartTimeout == 0 {
+ config.StartTimeout = 1 * time.Minute
+ }
+
+ if config.Stderr == nil {
+ config.Stderr = ioutil.Discard
+ }
+
+ c = &PluginClient{config: config}
+ if config.Managed {
+ managedClients = append(managedClients, c)
+ }
+
+ return
+}
+
+// Tells whether or not the underlying process has exited.
+func (c *PluginClient) Exited() bool {
+ c.l.Lock()
+ defer c.l.Unlock()
+ return c.exited
+}
+
+// Returns a builder implementation that is communicating over this
+// client. If the client hasn't been started, this will start it.
+func (c *PluginClient) Builder() (packersdk.Builder, error) {
+ client, err := c.Client()
+ if err != nil {
+ return nil, err
+ }
+
+ return &cmdBuilder{client.Builder(), c}, nil
+}
+
+// Returns a hook implementation that is communicating over this
+// client. If the client hasn't been started, this will start it.
+func (c *PluginClient) Hook() (packersdk.Hook, error) {
+ client, err := c.Client()
+ if err != nil {
+ return nil, err
+ }
+
+ return &cmdHook{client.Hook(), c}, nil
+}
+
+// Returns a post-processor implementation that is communicating over
+// this client. If the client hasn't been started, this will start it.
+func (c *PluginClient) PostProcessor() (packersdk.PostProcessor, error) {
+ client, err := c.Client()
+ if err != nil {
+ return nil, err
+ }
+
+ return &cmdPostProcessor{client.PostProcessor(), c}, nil
+}
+
+// Returns a provisioner implementation that is communicating over this
+// client. If the client hasn't been started, this will start it.
+func (c *PluginClient) Provisioner() (packersdk.Provisioner, error) {
+ client, err := c.Client()
+ if err != nil {
+ return nil, err
+ }
+
+ return &cmdProvisioner{client.Provisioner(), c}, nil
+}
+
+// Returns a data source implementation that is communicating over this
+// client. If the client hasn't been started, this will start it.
+func (c *PluginClient) Datasource() (packersdk.Datasource, error) {
+ client, err := c.Client()
+ if err != nil {
+ return nil, err
+ }
+ return &cmdDatasource{client.Datasource(), c}, nil
+}
+
+// End the executing subprocess (if it is running) and perform any cleanup
+// tasks necessary such as capturing any remaining logs and so on.
+//
+// This method blocks until the process successfully exits.
+//
+// This method can safely be called multiple times.
+func (c *PluginClient) Kill() {
+ cmd := c.config.Cmd
+
+ if cmd.Process == nil {
+ return
+ }
+
+ cmd.Process.Kill()
+
+ // Wait for the client to finish logging so we have a complete log
+ <-c.doneLogging
+}
+
+// Starts the underlying subprocess, communicating with it to negotiate
+// a port for RPC connections, and returning the address to connect via RPC.
+//
+// This method is safe to call multiple times. Subsequent calls have no effect.
+// Once a client has been started once, it cannot be started again, even if
+// it was killed.
+func (c *PluginClient) Start() (net.Addr, error) {
+ c.l.Lock()
+ defer c.l.Unlock()
+
+ if c.address != nil {
+ return c.address, nil
+ }
+
+ c.doneLogging = make(chan struct{})
+
+ env := []string{
+ fmt.Sprintf("%s=%s", pluginsdk.MagicCookieKey, pluginsdk.MagicCookieValue),
+ fmt.Sprintf("PACKER_PLUGIN_MIN_PORT=%d", c.config.MinPort),
+ fmt.Sprintf("PACKER_PLUGIN_MAX_PORT=%d", c.config.MaxPort),
+ }
+
+ stdout_r, stdout_w := io.Pipe()
+ stderr_r, stderr_w := io.Pipe()
+
+ cmd := c.config.Cmd
+ cmd.Env = append(cmd.Env, os.Environ()...)
+ cmd.Env = append(cmd.Env, env...)
+ cmd.Stdin = os.Stdin
+ cmd.Stderr = stderr_w
+ cmd.Stdout = stdout_w
+
+ log.Printf("Starting plugin: %s %#v", cmd.Path, cmd.Args)
+ err := cmd.Start()
+ if err != nil {
+ return nil, err
+ }
+
+ // Make sure the command is properly cleaned up if there is an error
+ defer func() {
+ r := recover()
+
+ if err != nil || r != nil {
+ cmd.Process.Kill()
+ }
+
+ if r != nil {
+ panic(r)
+ }
+ }()
+
+ // Start goroutine to wait for process to exit
+ exitCh := make(chan struct{})
+ go func() {
+ // Make sure we close the write end of our stderr/stdout so
+ // that the readers send EOF properly.
+ defer stderr_w.Close()
+ defer stdout_w.Close()
+
+ // Wait for the command to end.
+ cmd.Wait()
+
+ // Log and make sure to flush the logs write away
+ log.Printf("%s: plugin process exited\n", cmd.Path)
+ os.Stderr.Sync()
+
+ // Mark that we exited
+ close(exitCh)
+
+ // Set that we exited, which takes a lock
+ c.l.Lock()
+ defer c.l.Unlock()
+ c.exited = true
+ }()
+
+ // Start goroutine that logs the stderr
+ go c.logStderr(stderr_r)
+
+ // Start a goroutine that is going to be reading the lines
+ // out of stdout
+ linesCh := make(chan []byte)
+ go func() {
+ defer close(linesCh)
+
+ buf := bufio.NewReader(stdout_r)
+ for {
+ line, err := buf.ReadBytes('\n')
+ if line != nil {
+ linesCh <- line
+ }
+
+ if err == io.EOF {
+ return
+ }
+ }
+ }()
+
+ // Make sure after we exit we read the lines from stdout forever
+ // so they dont' block since it is an io.Pipe
+ defer func() {
+ go func() {
+ for range linesCh {
+ }
+ }()
+ }()
+
+ // Some channels for the next step
+ timeout := time.After(c.config.StartTimeout)
+
+ // Start looking for the address
+ log.Printf("Waiting for RPC address for: %s", cmd.Path)
+ select {
+ case <-timeout:
+ err = errors.New("timeout while waiting for plugin to start")
+ case <-exitCh:
+ err = errors.New("plugin exited before we could connect")
+ case lineBytes := <-linesCh:
+ // Trim the line and split by "|" in order to get the parts of
+ // the output.
+ line := strings.TrimSpace(string(lineBytes))
+ parts := strings.SplitN(line, "|", 4)
+ if len(parts) == 3 {
+ // In protocol version 4 and before, the protocol only had a Major
+ // version
+ err = fmt.Errorf("The protocol of this plugin (protocol version 4 " +
+ "and lower) was deprecated, please use a newer version of this plugin." +
+ "Or use an older version of Packer (pre 1.7) with this plugin.")
+ return nil, err
+ }
+ if len(parts) < 4 {
+ err = fmt.Errorf("Unrecognized remote plugin message: %s", line)
+ return nil, err
+ }
+ pluginMajorAPIVersion, pluginMinorAPIVersion, network, netAddr := parts[0], parts[1], parts[2], parts[3]
+
+ // Test the API versions
+ if pluginMajorAPIVersion != pluginsdk.APIVersionMajor {
+ err = fmt.Errorf("Incompatible API MAJOR version with plugin. "+
+ "plugin MINOR API version: %s, Ours: %s", pluginMajorAPIVersion, pluginsdk.APIVersionMajor)
+ return nil, err
+ }
+ if pluginMinorAPIVersion > pluginsdk.APIVersionMinor {
+ err = fmt.Errorf("Incompatible API MINOR version with plugin. "+
+ "plugin MINOR API version: %s, Ours: %s. Please upgrade Packer.", pluginMinorAPIVersion, pluginsdk.APIVersionMinor)
+ return nil, err
+ }
+
+ switch network {
+ case "tcp":
+ c.address, err = net.ResolveTCPAddr("tcp", netAddr)
+ case "unix":
+ c.address, err = net.ResolveUnixAddr("unix", netAddr)
+ default:
+ return nil, fmt.Errorf("Unknown address type: %s", network)
+ }
+ log.Printf("Received %s RPC address for %s: addr is %s", network, cmd.Path, c.address)
+ }
+
+ return c.address, err
+}
+
+func (c *PluginClient) logStderr(r io.Reader) {
+ logPrefix := filepath.Base(c.config.Cmd.Path)
+ if logPrefix == "packer" {
+ // we just called the normal packer binary with the plugin arg.
+ // grab the last arg from the list which will match the plugin name.
+ logPrefix = c.config.Cmd.Args[len(c.config.Cmd.Args)-1]
+ }
+
+ bufR := bufio.NewReader(r)
+ for {
+ line, err := bufR.ReadString('\n')
+ if line != "" {
+ c.config.Stderr.Write([]byte(line))
+
+ line = strings.TrimRightFunc(line, unicode.IsSpace)
+
+ log.Printf("%s plugin: %s", logPrefix, line)
+ }
+
+ if err == io.EOF {
+ break
+ }
+ }
+
+ // Flag that we've completed logging for others
+ close(c.doneLogging)
+}
+
+func (c *PluginClient) Client() (*packerrpc.Client, error) {
+ addr, err := c.Start()
+ if err != nil {
+ return nil, err
+ }
+
+ conn, err := net.Dial(addr.Network(), addr.String())
+ if err != nil {
+ return nil, err
+ }
+
+ if tcpConn, ok := conn.(*net.TCPConn); ok {
+ // Make sure to set keep alive so that the connection doesn't die
+ tcpConn.SetKeepAlive(true)
+ }
+
+ client, err := packerrpc.NewClient(conn)
+ if err != nil {
+ conn.Close()
+ return nil, err
+ }
+
+ return client, nil
+}
diff --git a/v1.9.4/packer/plugin_discover_test.go b/v1.9.4/packer/plugin_discover_test.go
new file mode 100644
index 0000000..fec5260
--- /dev/null
+++ b/v1.9.4/packer/plugin_discover_test.go
@@ -0,0 +1,700 @@
+// Copyright (c) HashiCorp, Inc.
+// SPDX-License-Identifier: MPL-2.0
+
+package packer
+
+import (
+ "crypto/sha256"
+ "fmt"
+ "os"
+ "os/exec"
+ "path"
+ "path/filepath"
+ "runtime"
+ "strings"
+ "testing"
+
+ packersdk "github.com/hashicorp/packer-plugin-sdk/packer"
+ pluginsdk "github.com/hashicorp/packer-plugin-sdk/plugin"
+ "github.com/hashicorp/packer-plugin-sdk/tmp"
+ plugingetter "github.com/hashicorp/packer/packer/plugin-getter"
+)
+
+func newPluginConfig() PluginConfig {
+ var conf PluginConfig
+ conf.PluginMinPort = 10000
+ conf.PluginMaxPort = 25000
+ return conf
+}
+
+func TestDiscoverReturnsIfMagicCookieSet(t *testing.T) {
+ config := newPluginConfig()
+
+ t.Setenv(pluginsdk.MagicCookieKey, pluginsdk.MagicCookieValue)
+
+ err := config.Discover()
+ if err != nil {
+ t.Fatalf("Should not have errored: %s", err)
+ }
+
+ if len(config.Builders.List()) != 0 {
+ t.Fatalf("Should not have tried to find builders")
+ }
+}
+
+func TestEnvVarPackerPluginPath(t *testing.T) {
+ // Create a temporary directory to store plugins in
+ dir, _, cleanUpFunc, err := generateFakePlugins("custom_plugin_dir",
+ []string{"packer-provisioner-partyparrot"})
+ if err != nil {
+ t.Fatalf("Error creating fake custom plugins: %s", err)
+ }
+
+ defer cleanUpFunc()
+
+ // Add temp dir to path.
+ t.Setenv("PACKER_PLUGIN_PATH", dir)
+
+ config := newPluginConfig()
+
+ err = config.Discover()
+ if err != nil {
+ t.Fatalf("Should not have errored: %s", err)
+ }
+
+ if len(config.Provisioners.List()) == 0 {
+ t.Fatalf("Should have found partyparrot provisioner")
+ }
+ if !config.Provisioners.Has("partyparrot") {
+ t.Fatalf("Should have found partyparrot provisioner.")
+ }
+}
+
+func TestEnvVarPackerPluginPath_MultiplePaths(t *testing.T) {
+ // Create a temporary directory to store plugins in
+ dir, _, cleanUpFunc, err := generateFakePlugins("custom_plugin_dir",
+ []string{"packer-provisioner-partyparrot"})
+ if err != nil {
+ t.Fatalf("Error creating fake custom plugins: %s", err)
+ }
+
+ defer cleanUpFunc()
+
+ pathsep := ":"
+ if runtime.GOOS == "windows" {
+ pathsep = ";"
+ }
+
+ // Create a second dir to look in that will be empty
+ decoyDir, err := os.MkdirTemp("", "decoy")
+ if err != nil {
+ t.Fatalf("Failed to create a temporary test dir.")
+ }
+ defer os.Remove(decoyDir)
+
+ pluginPath := dir + pathsep + decoyDir
+
+ // Add temp dir to path.
+ t.Setenv("PACKER_PLUGIN_PATH", pluginPath)
+
+ config := newPluginConfig()
+
+ err = config.Discover()
+ if err != nil {
+ t.Fatalf("Should not have errored: %s", err)
+ }
+
+ if len(config.Provisioners.List()) == 0 {
+ t.Fatalf("Should have found partyparrot provisioner")
+ }
+ if !config.Provisioners.Has("partyparrot") {
+ t.Fatalf("Should have found partyparrot provisioner.")
+ }
+}
+
+func TestDiscoverDatasource(t *testing.T) {
+ // Create a temporary directory to store plugins in
+ dir, _, cleanUpFunc, err := generateFakePlugins("custom_plugin_dir",
+ []string{"packer-datasource-partyparrot"})
+ if err != nil {
+ t.Fatalf("Error creating fake custom plugins: %s", err)
+ }
+
+ defer cleanUpFunc()
+
+ pathsep := ":"
+ if runtime.GOOS == "windows" {
+ pathsep = ";"
+ }
+
+ // Create a second dir to look in that will be empty
+ decoyDir, err := os.MkdirTemp("", "decoy")
+ if err != nil {
+ t.Fatalf("Failed to create a temporary test dir.")
+ }
+ defer os.Remove(decoyDir)
+
+ pluginPath := dir + pathsep + decoyDir
+
+ // Add temp dir to path.
+ t.Setenv("PACKER_PLUGIN_PATH", pluginPath)
+
+ config := newPluginConfig()
+
+ err = config.Discover()
+ if err != nil {
+ t.Fatalf("Should not have errored: %s", err)
+ }
+
+ if len(config.DataSources.List()) == 0 {
+ t.Fatalf("Should have found partyparrot datasource")
+ }
+ if !config.DataSources.Has("partyparrot") {
+ t.Fatalf("Should have found partyparrot datasource.")
+ }
+}
+
+func TestMultiPlugin_describe(t *testing.T) {
+ createMockPlugins(t, mockPlugins)
+ pluginDir := os.Getenv("PACKER_PLUGIN_PATH")
+ defer os.RemoveAll(pluginDir)
+ c := PluginConfig{}
+ err := c.Discover()
+ if err != nil {
+ t.Fatalf("error discovering plugins; %s", err.Error())
+ }
+
+ for mockPluginName, plugin := range mockPlugins {
+ for mockBuilderName := range plugin.Builders {
+ expectedBuilderName := mockPluginName + "-" + mockBuilderName
+
+ if !c.Builders.Has(expectedBuilderName) {
+ t.Fatalf("expected to find builder %q", expectedBuilderName)
+ }
+ }
+ for mockProvisionerName := range plugin.Provisioners {
+ expectedProvisionerName := mockPluginName + "-" + mockProvisionerName
+ if !c.Provisioners.Has(expectedProvisionerName) {
+ t.Fatalf("expected to find builder %q", expectedProvisionerName)
+ }
+ }
+ for mockPostProcessorName := range plugin.PostProcessors {
+ expectedPostProcessorName := mockPluginName + "-" + mockPostProcessorName
+ if !c.PostProcessors.Has(expectedPostProcessorName) {
+ t.Fatalf("expected to find post-processor %q", expectedPostProcessorName)
+ }
+ }
+ for mockDatasourceName := range plugin.Datasources {
+ expectedDatasourceName := mockPluginName + "-" + mockDatasourceName
+ if !c.DataSources.Has(expectedDatasourceName) {
+ t.Fatalf("expected to find datasource %q", expectedDatasourceName)
+ }
+ }
+ }
+}
+
+func TestMultiPlugin_describe_installed(t *testing.T) {
+ createMockInstalledPlugins(t, mockInstalledPlugins, createMockChecksumFile)
+ pluginDir := os.Getenv("PACKER_PLUGIN_PATH")
+ defer os.RemoveAll(pluginDir)
+
+ c := PluginConfig{}
+ err := c.Discover()
+ if err != nil {
+ t.Fatalf("error discovering plugins; %s", err.Error())
+ }
+
+ for mockPluginName, plugin := range mockInstalledPlugins {
+ mockPluginName = strings.Split(mockPluginName, "_")[0]
+ for mockBuilderName := range plugin.Builders {
+ expectedBuilderName := mockPluginName + "-" + mockBuilderName
+ if !c.Builders.Has(expectedBuilderName) {
+ t.Fatalf("expected to find builder %q", expectedBuilderName)
+ }
+ }
+ for mockProvisionerName := range plugin.Provisioners {
+ expectedProvisionerName := mockPluginName + "-" + mockProvisionerName
+ if !c.Provisioners.Has(expectedProvisionerName) {
+ t.Fatalf("expected to find builder %q", expectedProvisionerName)
+ }
+ }
+ for mockPostProcessorName := range plugin.PostProcessors {
+ expectedPostProcessorName := mockPluginName + "-" + mockPostProcessorName
+ if !c.PostProcessors.Has(expectedPostProcessorName) {
+ t.Fatalf("expected to find post-processor %q", expectedPostProcessorName)
+ }
+ }
+ for mockDatasourceName := range plugin.Datasources {
+ expectedDatasourceName := mockPluginName + "-" + mockDatasourceName
+ if !c.DataSources.Has(expectedDatasourceName) {
+ t.Fatalf("expected to find datasource %q", expectedDatasourceName)
+ }
+ }
+ }
+}
+
+func TestMultiPlugin_describe_installed_for_invalid(t *testing.T) {
+ tc := []struct {
+ desc string
+ installedPluginsMock map[string]pluginsdk.Set
+ createMockFn func(*testing.T, map[string]pluginsdk.Set)
+ }{
+ {
+ desc: "Incorrectly named plugins",
+ installedPluginsMock: invalidInstalledPluginsMock,
+ createMockFn: func(t *testing.T, mocks map[string]pluginsdk.Set) {
+ createMockInstalledPlugins(t, mocks, createMockChecksumFile)
+ },
+ },
+ {
+ desc: "Plugins missing checksums",
+ installedPluginsMock: mockInstalledPlugins,
+ createMockFn: func(t *testing.T, mocks map[string]pluginsdk.Set) {
+ createMockInstalledPlugins(t, mocks)
+ },
+ },
+ }
+
+ for _, tt := range tc {
+ t.Run(tt.desc, func(t *testing.T) {
+ tt.createMockFn(t, tt.installedPluginsMock)
+ pluginDir := os.Getenv("PACKER_PLUGIN_PATH")
+ defer os.RemoveAll(pluginDir)
+
+ c := PluginConfig{}
+ err := c.Discover()
+ if err != nil {
+ t.Fatalf("error discovering plugins; %s", err.Error())
+ }
+ if c.Builders.Has("feather") {
+ t.Fatalf("expected to not find builder %q", "feather")
+ }
+ for mockPluginName, plugin := range tt.installedPluginsMock {
+ mockPluginName = strings.Split(mockPluginName, "_")[0]
+ for mockBuilderName := range plugin.Builders {
+ expectedBuilderName := mockPluginName + "-" + mockBuilderName
+ if c.Builders.Has(expectedBuilderName) {
+ t.Fatalf("expected to not find builder %q", expectedBuilderName)
+ }
+ }
+ for mockProvisionerName := range plugin.Provisioners {
+ expectedProvisionerName := mockPluginName + "-" + mockProvisionerName
+ if c.Provisioners.Has(expectedProvisionerName) {
+ t.Fatalf("expected to not find builder %q", expectedProvisionerName)
+ }
+ }
+ for mockPostProcessorName := range plugin.PostProcessors {
+ expectedPostProcessorName := mockPluginName + "-" + mockPostProcessorName
+ if c.PostProcessors.Has(expectedPostProcessorName) {
+ t.Fatalf("expected to not find post-processor %q", expectedPostProcessorName)
+ }
+ }
+ for mockDatasourceName := range plugin.Datasources {
+ expectedDatasourceName := mockPluginName + "-" + mockDatasourceName
+ if c.DataSources.Has(expectedDatasourceName) {
+ t.Fatalf("expected to not find datasource %q", expectedDatasourceName)
+ }
+ }
+ }
+ })
+ }
+}
+
+func TestMultiPlugin_defaultName(t *testing.T) {
+ createMockPlugins(t, defaultNameMock)
+ pluginDir := os.Getenv("PACKER_PLUGIN_PATH")
+ defer os.RemoveAll(pluginDir)
+
+ c := PluginConfig{}
+ err := c.Discover()
+ if err != nil {
+ t.Fatalf("error discovering plugins; %s ; mocks are %#v", err.Error(), defaultNameMock)
+ }
+
+ expectedBuilderNames := []string{"foo-bar", "foo-baz", "foo"}
+ for _, mockBuilderName := range expectedBuilderNames {
+ if !c.Builders.Has(mockBuilderName) {
+ t.Fatalf("expected to find builder %q; builders is %#v", mockBuilderName, c.Builders)
+ }
+ }
+}
+
+// no T.Parallel using os.Chdir
+func TestMultiPlugin_CWD(t *testing.T) {
+ createMockPlugins(t, defaultNameMock)
+ pluginDir := os.Getenv("PACKER_PLUGIN_PATH")
+ defer os.RemoveAll(pluginDir)
+ // Unset PACKER_PLUGIN_PATH to test CWD loading
+ os.Unsetenv("PACKER_PLUGIN_PATH")
+ if err := os.Chdir(pluginDir); err != nil {
+ t.Fatalf("failed to change directory to test loading from CWD: %s", err)
+ }
+ c := PluginConfig{}
+ err := c.Discover()
+ if err != nil {
+ t.Fatalf("error discovering plugins; %s ; mocks are %#v", err.Error(), defaultNameMock)
+ }
+ expectedBuilderNames := []string{"foo-bar", "foo-baz", "foo"}
+ for _, mockBuilderName := range expectedBuilderNames {
+ if !c.Builders.Has(mockBuilderName) {
+ t.Fatalf("expected to find builder %q; builders is %#v", mockBuilderName, c.Builders)
+ }
+ }
+}
+
+func TestMultiPlugin_IgnoreChecksumFile(t *testing.T) {
+ createMockPlugins(t, defaultNameMock)
+ pluginDir := os.Getenv("PACKER_PLUGIN_PATH")
+ defer os.RemoveAll(pluginDir)
+
+ csFile, err := generateMockChecksumFile(filepath.Join(pluginDir, "packer-plugin-foo"))
+ if err != nil {
+ t.Fatal(err.Error())
+ }
+ // Copy plugin contents into checksum file to validate that it is not only skipped but that it never gets loaded
+ if err := os.Rename(filepath.Join(pluginDir, "packer-plugin-foo"), csFile); err != nil {
+ t.Fatalf("failed to rename plugin bin file to checkfum file needed for test: %s", err)
+ }
+
+ c := PluginConfig{}
+ err = c.Discover()
+ if err != nil {
+ t.Fatalf("error discovering plugins; %s ; mocks are %#v", err.Error(), defaultNameMock)
+ }
+ expectedBuilderNames := []string{"foo-bar", "foo-baz", "foo"}
+ for _, mockBuilderName := range expectedBuilderNames {
+ if c.Builders.Has(mockBuilderName) {
+ t.Fatalf("expected to not find builder %q; builders is %#v", mockBuilderName, c.Builders)
+ }
+ }
+}
+
+func TestMultiPlugin_defaultName_each_plugin_type(t *testing.T) {
+ createMockPlugins(t, doubleDefaultMock)
+ pluginDir := os.Getenv("PACKER_PLUGIN_PATH")
+ defer os.RemoveAll(pluginDir)
+
+ c := PluginConfig{}
+ err := c.Discover()
+ if err != nil {
+ t.Fatal("Should not have error because pluginsdk.DEFAULT_NAME is used twice but only once per plugin type.")
+ }
+}
+
+func generateFakePlugins(dirname string, pluginNames []string) (string, []string, func(), error) {
+ dir, err := os.MkdirTemp("", dirname)
+ if err != nil {
+ return "", nil, nil, fmt.Errorf("failed to create temporary test directory: %v", err)
+ }
+
+ cleanUpFunc := func() {
+ os.RemoveAll(dir)
+ }
+
+ var suffix string
+ if runtime.GOOS == "windows" {
+ suffix = ".exe"
+ }
+
+ plugins := make([]string, len(pluginNames))
+ for i, plugin := range pluginNames {
+ plug := filepath.Join(dir, plugin+suffix)
+ plugins[i] = plug
+ _, err := os.Create(plug)
+ if err != nil {
+ cleanUpFunc()
+ return "", nil, nil, fmt.Errorf("failed to create temporary plugin file (%s): %v", plug, err)
+ }
+ }
+
+ return dir, plugins, cleanUpFunc, nil
+}
+
+// TestHelperProcess isn't a real test. It's used as a helper process
+// for multi-component plugin tests.
+func TestHelperPlugins(t *testing.T) {
+ if os.Getenv("PKR_WANT_TEST_PLUGINS") != "1" {
+ return
+ }
+ defer os.Exit(0)
+
+ args := os.Args
+ for len(args) > 0 {
+ if args[0] == "--" {
+ args = args[1:]
+ break
+ }
+ args = args[1:]
+ }
+ if len(args) == 0 {
+ fmt.Fprintf(os.Stderr, "No command\n")
+ os.Exit(2)
+ }
+
+ pluginName, args := args[0], args[1:]
+
+ allMocks := []map[string]pluginsdk.Set{mockPlugins, defaultNameMock, doubleDefaultMock, badDefaultNameMock}
+ for _, mock := range allMocks {
+ plugin, found := mock[pluginName]
+ if found {
+ err := plugin.RunCommand(args...)
+ if err != nil {
+ fmt.Fprintf(os.Stderr, "%v\n", err)
+ os.Exit(1)
+ }
+ os.Exit(0)
+ }
+ }
+
+ fmt.Fprintf(os.Stderr, "No %q plugin found\n", pluginName)
+ os.Exit(2)
+}
+
+// HasExec reports whether the current system can start new processes
+// using os.StartProcess or (more commonly) exec.Command.
+func HasExec() bool {
+ switch runtime.GOOS {
+ case "js":
+ return false
+ case "windows":
+ // TODO(azr): Fix this once versioning is added and we know more
+ return false
+ }
+ return true
+}
+
+// MustHaveExec checks that the current system can start new processes
+// using os.StartProcess or (more commonly) exec.Command.
+// If not, MustHaveExec calls t.Skip with an explanation.
+func MustHaveExec(t testing.TB) {
+ if !HasExec() {
+ t.Skipf("skipping test: cannot exec subprocess on %s/%s", runtime.GOOS, runtime.GOARCH)
+ }
+}
+
+func MustHaveCommand(t testing.TB, cmd string) string {
+ path, err := exec.LookPath(cmd)
+ if err != nil {
+ t.Skipf("skipping test: cannot find the %q command: %v", cmd, err)
+ }
+ return path
+}
+
+func helperCommand(t *testing.T, s ...string) []string {
+ MustHaveExec(t)
+
+ cmd := []string{os.Args[0], "-test.run=TestHelperPlugins", "--"}
+ return append(cmd, s...)
+}
+
+func createMockPlugins(t *testing.T, plugins map[string]pluginsdk.Set) {
+ pluginDir, err := tmp.Dir("pkr-multi-component-plugin-test-*")
+ {
+ // create an exectutable file with a `sh` sheebang
+ // this file will look like:
+ // #!/bin/sh
+ // PKR_WANT_TEST_PLUGINS=1 ...plugin/debug.test -test.run=TestHelperPlugins -- bird $@
+ // 'bird' is the mock plugin we want to start
+ // $@ just passes all passed arguments
+ // This will allow to run the fake plugin from go tests which in turn
+ // will run go tests callback to `TestHelperPlugins`, this one will be
+ // transparently calling our mock multi-component plugins `mockPlugins`.
+ if err != nil {
+ t.Fatal(err)
+ }
+
+ t.Logf("putting temporary mock plugins in %s", pluginDir)
+
+ shPath := MustHaveCommand(t, "bash")
+ for name := range plugins {
+ plugin := path.Join(pluginDir, "packer-plugin-"+name)
+ t.Logf("creating fake plugin %s", plugin)
+ fileContent := ""
+ fileContent = fmt.Sprintf("#!%s\n", shPath)
+ fileContent += strings.Join(
+ append([]string{"PKR_WANT_TEST_PLUGINS=1"}, helperCommand(t, name, "$@")...),
+ " ")
+ if err := os.WriteFile(plugin, []byte(fileContent), os.ModePerm); err != nil {
+ t.Fatalf("failed to create fake plugin binary: %v", err)
+ }
+ }
+ }
+ t.Setenv("PACKER_PLUGIN_PATH", pluginDir)
+}
+
+func createMockChecksumFile(t testing.TB, filePath string) {
+ t.Helper()
+ cs, err := generateMockChecksumFile(filePath)
+ if err != nil {
+ t.Fatalf(err.Error())
+ }
+ t.Logf("created fake plugin checksum file %s", cs)
+}
+
+func generateMockChecksumFile(filePath string) (string, error) {
+ cs := plugingetter.Checksummer{
+ Type: "sha256",
+ Hash: sha256.New(),
+ }
+
+ f, err := os.Open(filePath)
+ if err != nil {
+ return "", fmt.Errorf("failed to open fake plugin binary: %v", err)
+ }
+ defer f.Close()
+
+ sum, err := cs.Sum(f)
+ if err != nil {
+ return "", fmt.Errorf("failed to checksum fake plugin binary: %v", err)
+ }
+
+ sumfile := filePath + cs.FileExt()
+ if err := os.WriteFile(sumfile, []byte(fmt.Sprintf("%x", sum)), os.ModePerm); err != nil {
+ return "", fmt.Errorf("failed to write checksum fake plugin binary: %v", err)
+ }
+ return sumfile, nil
+}
+
+func createMockInstalledPlugins(t *testing.T, plugins map[string]pluginsdk.Set, opts ...func(tb testing.TB, filePath string)) {
+ pluginDir, err := tmp.Dir("pkr-multi-component-plugin-test-*")
+ {
+ // create an exectutable file with a `sh` sheebang
+ // this file will look like:
+ // #!/bin/sh
+ // PKR_WANT_TEST_PLUGINS=1 ...plugin/debug.test -test.run=TestHelperPlugins -- bird $@
+ // 'bird' is the mock plugin we want to start
+ // $@ just passes all passed arguments
+ // This will allow to run the fake plugin from go tests which in turn
+ // will run go tests callback to `TestHelperPlugins`, this one will be
+ // transparently calling our mock multi-component plugins `mockPlugins`.
+ if err != nil {
+ t.Fatal(err)
+ }
+ dir, err := os.MkdirTemp(pluginDir, "github.com")
+ if err != nil {
+ t.Fatalf("failed to create temporary test directory: %v", err)
+ }
+ dir, err = os.MkdirTemp(dir, "hashicorp")
+ if err != nil {
+ t.Fatalf("failed to create temporary test directory: %v", err)
+ }
+ dir, err = os.MkdirTemp(dir, "plugin")
+ if err != nil {
+ t.Fatalf("failed to create temporary test directory: %v", err)
+ }
+ t.Logf("putting temporary mock installed plugins in %s", dir)
+
+ shPath := MustHaveCommand(t, "bash")
+ for name := range plugins {
+ plugin := path.Join(dir, "packer-plugin-"+name)
+ t.Logf("creating fake plugin %s", plugin)
+ fileContent := ""
+ fileContent = fmt.Sprintf("#!%s\n", shPath)
+ fileContent += strings.Join(
+ append([]string{"PKR_WANT_TEST_PLUGINS=1"}, helperCommand(t, strings.Split(name, "_")[0], "$@")...),
+ " ")
+ if err := os.WriteFile(plugin, []byte(fileContent), os.ModePerm); err != nil {
+ t.Fatalf("failed to create fake plugin binary: %v", err)
+ }
+
+ for _, opt := range opts {
+ opt(t, plugin)
+ }
+ }
+ }
+ t.Setenv("PACKER_PLUGIN_PATH", pluginDir)
+}
+
+func getFormattedInstalledPluginSuffix() string {
+ return fmt.Sprintf("v1.0.0_x5.0_%s_%s", runtime.GOOS, runtime.GOARCH)
+}
+
+var (
+ mockPlugins = map[string]pluginsdk.Set{
+ "bird": {
+ Builders: map[string]packersdk.Builder{
+ "feather": nil,
+ "guacamole": nil,
+ },
+ },
+ "chimney": {
+ PostProcessors: map[string]packersdk.PostProcessor{
+ "smoke": nil,
+ },
+ },
+ "data": {
+ Datasources: map[string]packersdk.Datasource{
+ "source": nil,
+ },
+ },
+ }
+ mockInstalledPlugins = map[string]pluginsdk.Set{
+ fmt.Sprintf("bird_%s", getFormattedInstalledPluginSuffix()): {
+ Builders: map[string]packersdk.Builder{
+ "feather": nil,
+ "guacamole": nil,
+ },
+ },
+ fmt.Sprintf("chimney_%s", getFormattedInstalledPluginSuffix()): {
+ PostProcessors: map[string]packersdk.PostProcessor{
+ "smoke": nil,
+ },
+ },
+ fmt.Sprintf("data_%s", getFormattedInstalledPluginSuffix()): {
+ Datasources: map[string]packersdk.Datasource{
+ "source": nil,
+ },
+ },
+ }
+
+ invalidInstalledPluginsMock = map[string]pluginsdk.Set{
+ "bird_v0.1.1_x5.0_wrong_architecture": {
+ Builders: map[string]packersdk.Builder{
+ "feather": nil,
+ "guacamole": nil,
+ },
+ },
+ "chimney_cool_ranch": {
+ PostProcessors: map[string]packersdk.PostProcessor{
+ "smoke": nil,
+ },
+ },
+ "data": {
+ Datasources: map[string]packersdk.Datasource{
+ "source": nil,
+ },
+ },
+ }
+ defaultNameMock = map[string]pluginsdk.Set{
+ "foo": {
+ Builders: map[string]packersdk.Builder{
+ "bar": nil,
+ "baz": nil,
+ pluginsdk.DEFAULT_NAME: nil,
+ },
+ },
+ }
+
+ doubleDefaultMock = map[string]pluginsdk.Set{
+ "yolo": {
+ Builders: map[string]packersdk.Builder{
+ "bar": nil,
+ "baz": nil,
+ pluginsdk.DEFAULT_NAME: nil,
+ },
+ PostProcessors: map[string]packersdk.PostProcessor{
+ pluginsdk.DEFAULT_NAME: nil,
+ },
+ },
+ }
+
+ badDefaultNameMock = map[string]pluginsdk.Set{
+ "foo": {
+ Builders: map[string]packersdk.Builder{
+ "bar": nil,
+ "baz": nil,
+ pluginsdk.DEFAULT_NAME: nil,
+ },
+ },
+ }
+)
diff --git a/v1.9.4/packer/plugin_folders.go b/v1.9.4/packer/plugin_folders.go
new file mode 100644
index 0000000..52d63aa
--- /dev/null
+++ b/v1.9.4/packer/plugin_folders.go
@@ -0,0 +1,39 @@
+// Copyright (c) HashiCorp, Inc.
+// SPDX-License-Identifier: MPL-2.0
+
+package packer
+
+import (
+ "log"
+ "os"
+ "path/filepath"
+ "strings"
+
+ "github.com/hashicorp/packer-plugin-sdk/pathing"
+)
+
+// PluginFolders returns the list of known plugin folders based on system.
+func PluginFolders(dirs ...string) []string {
+ res := []string{}
+
+ if packerPluginPath := os.Getenv("PACKER_PLUGIN_PATH"); packerPluginPath != "" {
+ res = append(res, strings.Split(packerPluginPath, string(os.PathListSeparator))...)
+ return res
+ }
+
+ if path, err := os.Executable(); err != nil {
+ log.Printf("[ERR] Error finding executable: %v", err)
+ } else {
+ res = append(res, filepath.Dir(path))
+ }
+
+ res = append(res, dirs...)
+
+ if cd, err := pathing.ConfigDir(); err != nil {
+ log.Printf("[ERR] Error loading config directory: %v", err)
+ } else {
+ res = append(res, filepath.Join(cd, "plugins"))
+ }
+
+ return res
+}
diff --git a/v1.9.4/packer/plugin_test.go b/v1.9.4/packer/plugin_test.go
new file mode 100644
index 0000000..099d9cf
--- /dev/null
+++ b/v1.9.4/packer/plugin_test.go
@@ -0,0 +1,150 @@
+// Copyright (c) HashiCorp, Inc.
+// SPDX-License-Identifier: MPL-2.0
+
+package packer
+
+import (
+ "fmt"
+ "log"
+ "os"
+ "os/exec"
+ "testing"
+ "time"
+
+ packersdk "github.com/hashicorp/packer-plugin-sdk/packer"
+ pluginsdk "github.com/hashicorp/packer-plugin-sdk/plugin"
+)
+
+func helperProcess(s ...string) *exec.Cmd {
+ cs := []string{"-test.run=TestHelperProcess", "--"}
+ cs = append(cs, s...)
+ env := []string{
+ "GO_WANT_HELPER_PROCESS=1",
+ "PACKER_PLUGIN_MIN_PORT=10000",
+ "PACKER_PLUGIN_MAX_PORT=25000",
+ }
+
+ cmd := exec.Command(os.Args[0], cs...)
+ cmd.Env = append(env, os.Environ()...)
+ return cmd
+}
+
+// This is not a real test. This is just a helper process kicked off by
+// tests.
+func TestHelperProcess(*testing.T) {
+ if os.Getenv("GO_WANT_HELPER_PROCESS") != "1" {
+ return
+ }
+
+ defer os.Exit(0)
+
+ args := os.Args
+ for len(args) > 0 {
+ if args[0] == "--" {
+ args = args[1:]
+ break
+ }
+
+ args = args[1:]
+ }
+
+ if len(args) == 0 {
+ fmt.Fprintf(os.Stderr, "No command\n")
+ os.Exit(2)
+ }
+
+ cmd, _ := args[0], args[1:]
+ switch cmd {
+ case "bad-version":
+ fmt.Printf("%s1|%s|tcp|:1234\n", pluginsdk.APIVersionMajor, pluginsdk.APIVersionMinor)
+ <-make(chan int)
+ case "builder":
+ server, err := pluginsdk.Server()
+ if err != nil {
+ log.Printf("[ERR] %s", err)
+ os.Exit(1)
+ }
+ err = server.RegisterBuilder(new(packersdk.MockBuilder))
+ if err != nil {
+ log.Printf("[ERR] %s", err)
+ os.Exit(1)
+ }
+ server.Serve()
+ case "hook":
+ server, err := pluginsdk.Server()
+ if err != nil {
+ log.Printf("[ERR] %s", err)
+ os.Exit(1)
+ }
+ err = server.RegisterHook(new(packersdk.MockHook))
+ if err != nil {
+ log.Printf("[ERR] %s", err)
+ os.Exit(1)
+ }
+ server.Serve()
+ case "invalid-rpc-address":
+ fmt.Println("lolinvalid")
+ case "mock":
+ fmt.Printf("%s|%s|tcp|:1234\n", pluginsdk.APIVersionMajor, pluginsdk.APIVersionMinor)
+ <-make(chan int)
+ case "post-processor":
+ server, err := pluginsdk.Server()
+ if err != nil {
+ log.Printf("[ERR] %s", err)
+ os.Exit(1)
+ }
+ err = server.RegisterPostProcessor(new(helperPostProcessor))
+ if err != nil {
+ log.Printf("[ERR] %s", err)
+ os.Exit(1)
+ }
+ server.Serve()
+ case "provisioner":
+ server, err := pluginsdk.Server()
+ if err != nil {
+ log.Printf("[ERR] %s", err)
+ os.Exit(1)
+ }
+ err = server.RegisterProvisioner(new(packersdk.MockProvisioner))
+ if err != nil {
+ log.Printf("[ERR] %s", err)
+ os.Exit(1)
+ }
+ server.Serve()
+ case "datasource":
+ server, err := pluginsdk.Server()
+ if err != nil {
+ log.Printf("[ERR] %s", err)
+ os.Exit(1)
+ }
+ err = server.RegisterDatasource(new(packersdk.MockDatasource))
+ if err != nil {
+ log.Printf("[ERR] %s", err)
+ os.Exit(1)
+ }
+ server.Serve()
+ case "start-timeout":
+ time.Sleep(1 * time.Minute)
+ os.Exit(1)
+ case "stderr":
+ fmt.Printf("%s|%s|tcp|:1234\n", pluginsdk.APIVersionMajor, pluginsdk.APIVersionMinor)
+ log.Println("HELLO")
+ log.Println("WORLD")
+ case "stdin":
+ fmt.Printf("%s|%s|tcp|:1234\n", pluginsdk.APIVersionMajor, pluginsdk.APIVersionMinor)
+ data := make([]byte, 5)
+ if _, err := os.Stdin.Read(data); err != nil {
+ log.Printf("stdin read error: %s", err)
+ os.Exit(100)
+ }
+
+ if string(data) == "hello" {
+ os.Exit(0)
+ }
+
+ os.Exit(1)
+ default:
+ fmt.Fprintf(os.Stderr, "Unknown command: %q\n", cmd)
+ os.Exit(2)
+ }
+}
diff --git a/v1.9.4/packer/post_processor_mock.go b/v1.9.4/packer/post_processor_mock.go
new file mode 100644
index 0000000..b6156e2
--- /dev/null
+++ b/v1.9.4/packer/post_processor_mock.go
@@ -0,0 +1,47 @@
+// Copyright (c) HashiCorp, Inc.
+// SPDX-License-Identifier: MPL-2.0
+
+//go:generate packer-sdc mapstructure-to-hcl2 -type MockPostProcessor
+package packer
+
+import (
+ "context"
+
+ "github.com/hashicorp/hcl/v2/hcldec"
+ packersdk "github.com/hashicorp/packer-plugin-sdk/packer"
+)
+
+// MockPostProcessor is an implementation of PostProcessor that can be
+// used for tests.
+type MockPostProcessor struct {
+ ArtifactId string
+ Keep bool
+ ForceOverride bool
+ Error error
+
+ ConfigureCalled bool
+ ConfigureConfigs []interface{}
+ ConfigureError error
+
+ PostProcessCalled bool
+ PostProcessArtifact packersdk.Artifact
+ PostProcessUi packersdk.Ui
+}
+
+func (t *MockPostProcessor) ConfigSpec() hcldec.ObjectSpec { return t.FlatMapstructure().HCL2Spec() }
+
+func (t *MockPostProcessor) Configure(configs ...interface{}) error {
+ t.ConfigureCalled = true
+ t.ConfigureConfigs = configs
+ return t.ConfigureError
+}
+
+func (t *MockPostProcessor) PostProcess(ctx context.Context, ui packersdk.Ui, a packersdk.Artifact) (packersdk.Artifact, bool, bool, error) {
+ t.PostProcessCalled = true
+ t.PostProcessArtifact = a
+ t.PostProcessUi = ui
+
+ return &packersdk.MockArtifact{
+ IdValue: t.ArtifactId,
+ }, t.Keep, t.ForceOverride, t.Error
+}
diff --git a/v1.9.4/packer/post_processor_mock.hcl2spec.go b/v1.9.4/packer/post_processor_mock.hcl2spec.go
new file mode 100644
index 0000000..51829b0
--- /dev/null
+++ b/v1.9.4/packer/post_processor_mock.hcl2spec.go
@@ -0,0 +1,50 @@
+// Code generated by "packer-sdc mapstructure-to-hcl2"; DO NOT EDIT.
+
+package packer
+
+import (
+ "github.com/hashicorp/hcl/v2/hcldec"
+ "github.com/hashicorp/packer-plugin-sdk/packer"
+ "github.com/zclconf/go-cty/cty"
+)
+
+// FlatMockPostProcessor is an auto-generated flat version of MockPostProcessor.
+// Where the contents of a field with a `mapstructure:,squash` tag are bubbled up.
+type FlatMockPostProcessor struct {
+ ArtifactId *string `cty:"artifact_id" hcl:"artifact_id"`
+ Keep *bool `cty:"keep" hcl:"keep"`
+ ForceOverride *bool `cty:"force_override" hcl:"force_override"`
+ Error error `cty:"error" hcl:"error"`
+ ConfigureCalled *bool `cty:"configure_called" hcl:"configure_called"`
+ ConfigureConfigs []interface{} `cty:"configure_configs" hcl:"configure_configs"`
+ ConfigureError error `cty:"configure_error" hcl:"configure_error"`
+ PostProcessCalled *bool `cty:"post_process_called" hcl:"post_process_called"`
+ PostProcessArtifact packer.Artifact `cty:"post_process_artifact" hcl:"post_process_artifact"`
+ PostProcessUi packer.Ui `cty:"post_process_ui" hcl:"post_process_ui"`
+}
+
+// FlatMapstructure returns a new FlatMockPostProcessor.
+// FlatMockPostProcessor is an auto-generated flat version of MockPostProcessor.
+// Where the contents a fields with a `mapstructure:,squash` tag are bubbled up.
+func (*MockPostProcessor) FlatMapstructure() interface{ HCL2Spec() map[string]hcldec.Spec } {
+ return new(FlatMockPostProcessor)
+}
+
+// HCL2Spec returns the hcl spec of a MockPostProcessor.
+// This spec is used by HCL to read the fields of MockPostProcessor.
+// The decoded values from this spec will then be applied to a FlatMockPostProcessor.
+func (*FlatMockPostProcessor) HCL2Spec() map[string]hcldec.Spec {
+ s := map[string]hcldec.Spec{
+ "artifact_id": &hcldec.AttrSpec{Name: "artifact_id", Type: cty.String, Required: false},
+ "keep": &hcldec.AttrSpec{Name: "keep", Type: cty.Bool, Required: false},
+ "force_override": &hcldec.AttrSpec{Name: "force_override", Type: cty.Bool, Required: false},
+ "error": &hcldec.AttrSpec{Name: "error", Type: cty.Bool, Required: false}, /* TODO(azr): could not find type */
+ "configure_called": &hcldec.AttrSpec{Name: "configure_called", Type: cty.Bool, Required: false},
+ "configure_configs": &hcldec.AttrSpec{Name: "configure_configs", Type: cty.Bool, Required: false}, /* TODO(azr): could not find type */
+ "configure_error": &hcldec.AttrSpec{Name: "configure_error", Type: cty.Bool, Required: false}, /* TODO(azr): could not find type */
+ "post_process_called": &hcldec.AttrSpec{Name: "post_process_called", Type: cty.Bool, Required: false},
+ "post_process_artifact": &hcldec.AttrSpec{Name: "post_process_artifact", Type: cty.Bool, Required: false}, /* TODO(azr): could not find type */
+ "post_process_ui": &hcldec.AttrSpec{Name: "post_process_ui", Type: cty.Bool, Required: false}, /* TODO(azr): could not find type */
+ }
+ return s
+}
diff --git a/v1.9.4/packer/progressbar.go b/v1.9.4/packer/progressbar.go
new file mode 100644
index 0000000..c7e68f7
--- /dev/null
+++ b/v1.9.4/packer/progressbar.go
@@ -0,0 +1,78 @@
+// Copyright (c) HashiCorp, Inc.
+// SPDX-License-Identifier: MPL-2.0
+
+//go:build !solaris
+// +build !solaris
+
+package packer
+
+import (
+ "io"
+ "path/filepath"
+ "sync"
+
+ pb "github.com/cheggaaa/pb"
+)
+
+func ProgressBarConfig(bar *pb.ProgressBar, prefix string) {
+ bar.SetUnits(pb.U_BYTES)
+ bar.Prefix(prefix)
+}
+
+// UiProgressBar is a progress bar compatible with go-getter used in our
+// UI structs.
+type UiProgressBar struct {
+ lock sync.Mutex
+ pool *pb.Pool
+ pbs int
+}
+
+func (p *UiProgressBar) TrackProgress(src string, currentSize, totalSize int64, stream io.ReadCloser) io.ReadCloser {
+ if p == nil {
+ return stream
+ }
+ p.lock.Lock()
+ defer p.lock.Unlock()
+
+ newPb := pb.New64(totalSize)
+ newPb.Set64(currentSize)
+ ProgressBarConfig(newPb, filepath.Base(src))
+
+ if p.pool == nil {
+ pool := pb.NewPool()
+ err := pool.Start()
+ if err != nil {
+ // here, we probably cannot lock
+ // stdout, so let's just return
+ // stream to avoid any error.
+ return stream
+ }
+ p.pool = pool
+ }
+ p.pool.Add(newPb)
+ reader := newPb.NewProxyReader(stream)
+
+ p.pbs++
+ return &readCloser{
+ Reader: reader,
+ close: func() error {
+ p.lock.Lock()
+ defer p.lock.Unlock()
+
+ newPb.Finish()
+ p.pbs--
+ if p.pbs <= 0 {
+ p.pool.Stop()
+ p.pool = nil
+ }
+ return nil
+ },
+ }
+}
+
+type readCloser struct {
+ io.Reader
+ close func() error
+}
+
+func (c *readCloser) Close() error { return c.close() }
diff --git a/v1.9.4/packer/progressbar_solaris.go b/v1.9.4/packer/progressbar_solaris.go
new file mode 100644
index 0000000..cfc0266
--- /dev/null
+++ b/v1.9.4/packer/progressbar_solaris.go
@@ -0,0 +1,10 @@
+// Copyright (c) HashiCorp, Inc.
+// SPDX-License-Identifier: MPL-2.0
+
+package packer
+
+import (
+ packersdk "github.com/hashicorp/packer-plugin-sdk/packer"
+)
+
+type UiProgressBar = packersdk.NoopProgressTracker
diff --git a/v1.9.4/packer/progressbar_test.go b/v1.9.4/packer/progressbar_test.go
new file mode 100644
index 0000000..a50049c
--- /dev/null
+++ b/v1.9.4/packer/progressbar_test.go
@@ -0,0 +1,61 @@
+// Copyright (c) HashiCorp, Inc.
+// SPDX-License-Identifier: MPL-2.0
+
+package packer
+
+import (
+ "bytes"
+ "io/ioutil"
+ "testing"
+
+ "golang.org/x/sync/errgroup"
+)
+
+// The following tests rarelly just happen. So we run them 100 times.
+
+func TestProgressTracking_open_close(t *testing.T) {
+ var bar *UiProgressBar
+
+ tracker := bar.TrackProgress("1,", 1, 42, ioutil.NopCloser(nil))
+ tracker.Close()
+
+ tracker = bar.TrackProgress("2,", 1, 42, ioutil.NopCloser(nil))
+ tracker.Close()
+}
+
+func TestProgressTracking_multi_open_close(t *testing.T) {
+ var bar *UiProgressBar
+ g := errgroup.Group{}
+
+ for i := 0; i < 100; i++ {
+ g.Go(func() error {
+ tracker := bar.TrackProgress("file,", 1, 42, ioutil.NopCloser(nil))
+ return tracker.Close()
+ })
+ }
+ if err := g.Wait(); err != nil {
+ t.Fatal(err)
+ }
+}
+
+func TestProgressTracking_races(t *testing.T) {
+ var bar *UiProgressBar
+ g := errgroup.Group{}
+
+ for i := 0; i < 100; i++ {
+ g.Go(func() error {
+ txt := []byte("foobarbaz dolores")
+ b := bytes.NewReader(txt)
+ tracker := bar.TrackProgress("file,", 1, 42, ioutil.NopCloser(b))
+
+ for i := 0; i < 42; i++ {
+ tracker.Read([]byte("i"))
+ }
+ return tracker.Close()
+ })
+ }
+
+ if err := g.Wait(); err != nil {
+ t.Fatal(err)
+ }
+}
diff --git a/v1.9.4/packer/provisioner.go b/v1.9.4/packer/provisioner.go
new file mode 100644
index 0000000..66d61d9
--- /dev/null
+++ b/v1.9.4/packer/provisioner.go
@@ -0,0 +1,241 @@
+// Copyright (c) HashiCorp, Inc.
+// SPDX-License-Identifier: MPL-2.0
+
+package packer
+
+import (
+ "context"
+ "fmt"
+ "log"
+ "sync"
+ "time"
+
+ "github.com/hashicorp/hcl/v2/hcldec"
+ packersdk "github.com/hashicorp/packer-plugin-sdk/packer"
+ "github.com/hashicorp/packer-plugin-sdk/packerbuilderdata"
+)
+
+// A HookedProvisioner represents a provisioner and information describing it
+type HookedProvisioner struct {
+ Provisioner packersdk.Provisioner
+ Config interface{}
+ TypeName string
+}
+
+// A Hook implementation that runs the given provisioners.
+type ProvisionHook struct {
+ // The provisioners to run as part of the hook. These should already
+ // be prepared (by calling Prepare) at some earlier stage.
+ Provisioners []*HookedProvisioner
+}
+
+// BuilderDataCommonKeys is the list of common keys that all builder will
+// return
+var BuilderDataCommonKeys = []string{
+ "ID",
+ // The following correspond to communicator-agnostic functions that are }
+ // part of the SSH and WinRM communicator implementations. These functions
+ // are not part of the communicator interface, but are stored on the
+ // Communicator Config and return the appropriate values rather than
+ // depending on the actual communicator config values. E.g "Password"
+ // reprosents either WinRMPassword or SSHPassword, which makes this more
+ // useful if a template contains multiple builds.
+ "Host",
+ "Port",
+ "User",
+ "Password",
+ "ConnType",
+ "PackerRunUUID",
+ "PackerHTTPPort",
+ "PackerHTTPIP",
+ "PackerHTTPAddr",
+ "SSHPublicKey",
+ "SSHPrivateKey",
+ "WinRMPassword",
+}
+
+// Provisioners interpolate most of their fields in the prepare stage; this
+// placeholder map helps keep fields that are only generated at build time from
+// accidentally being interpolated into empty strings at prepare time.
+// This helper function generates the most basic placeholder data which should
+// be accessible to the provisioners. It is used to initialize provisioners, to
+// force validation using the `generated` template function. In the future,
+// custom generated data could be passed into provisioners from builders to
+// enable specialized builder-specific (but still validated!!) access to builder
+// data.
+func BasicPlaceholderData() map[string]string {
+ placeholderData := map[string]string{}
+ for _, key := range BuilderDataCommonKeys {
+ placeholderData[key] = fmt.Sprintf("Build_%s. "+packerbuilderdata.PlaceholderMsg, key)
+ }
+
+ // Backwards-compatability: WinRM Password can get through without forcing
+ // the generated func validation.
+ placeholderData["WinRMPassword"] = "{{.WinRMPassword}}"
+
+ return placeholderData
+}
+
+func CastDataToMap(data interface{}) map[string]interface{} {
+
+ if interMap, ok := data.(map[string]interface{}); ok {
+ // null and file builder sometimes don't use a communicator and
+ // therefore don't go through RPC
+ return interMap
+ }
+
+ // Provisioners expect a map[string]interface{} in their data field, but
+ // it gets converted into a map[interface]interface on the way over the
+ // RPC. Check that data can be cast into such a form, and cast it.
+ cast := make(map[string]interface{})
+ interMap, ok := data.(map[interface{}]interface{})
+ if !ok {
+ log.Printf("Unable to read map[string]interface out of data."+
+ "Using empty interface: %#v", data)
+ } else {
+ for key, val := range interMap {
+ keyString, ok := key.(string)
+ if ok {
+ cast[keyString] = val
+ } else {
+ log.Printf("Error casting generated data key to a string.")
+ }
+ }
+ }
+ return cast
+}
+
+// Runs the provisioners in order.
+func (h *ProvisionHook) Run(ctx context.Context, name string, ui packersdk.Ui, comm packersdk.Communicator, data interface{}) error {
+ // Shortcut
+ if len(h.Provisioners) == 0 {
+ return nil
+ }
+
+ if comm == nil {
+ return fmt.Errorf(
+ "No communicator found for provisioners! This is usually because the\n" +
+ "`communicator` config was set to \"none\". If you have any provisioners\n" +
+ "then a communicator is required. Please fix this to continue.")
+ }
+ for _, p := range h.Provisioners {
+ ts := CheckpointReporter.AddSpan(p.TypeName, "provisioner", p.Config)
+
+ cast := CastDataToMap(data)
+ err := p.Provisioner.Provision(ctx, ui, comm, cast)
+
+ ts.End(err)
+ if err != nil {
+ return err
+ }
+ }
+
+ return nil
+}
+
+// PausedProvisioner is a Provisioner implementation that pauses before
+// the provisioner is actually run.
+type PausedProvisioner struct {
+ PauseBefore time.Duration
+ Provisioner packersdk.Provisioner
+}
+
+func (p *PausedProvisioner) ConfigSpec() hcldec.ObjectSpec { return p.ConfigSpec() }
+func (p *PausedProvisioner) FlatConfig() interface{} { return p.FlatConfig() }
+func (p *PausedProvisioner) Prepare(raws ...interface{}) error {
+ return p.Provisioner.Prepare(raws...)
+}
+
+func (p *PausedProvisioner) Provision(ctx context.Context, ui packersdk.Ui, comm packersdk.Communicator, generatedData map[string]interface{}) error {
+
+ // Use a select to determine if we get cancelled during the wait
+ ui.Say(fmt.Sprintf("Pausing %s before the next provisioner...", p.PauseBefore))
+ select {
+ case <-time.After(p.PauseBefore):
+ case <-ctx.Done():
+ return ctx.Err()
+ }
+
+ return p.Provisioner.Provision(ctx, ui, comm, generatedData)
+}
+
+// RetriedProvisioner is a Provisioner implementation that retries
+// the provisioner whenever there's an error.
+type RetriedProvisioner struct {
+ MaxRetries int
+ Provisioner packersdk.Provisioner
+}
+
+func (r *RetriedProvisioner) ConfigSpec() hcldec.ObjectSpec { return r.ConfigSpec() }
+func (r *RetriedProvisioner) FlatConfig() interface{} { return r.FlatConfig() }
+func (r *RetriedProvisioner) Prepare(raws ...interface{}) error {
+ return r.Provisioner.Prepare(raws...)
+}
+
+func (r *RetriedProvisioner) Provision(ctx context.Context, ui packersdk.Ui, comm packersdk.Communicator, generatedData map[string]interface{}) error {
+ if ctx.Err() != nil { // context was cancelled
+ return ctx.Err()
+ }
+
+ err := r.Provisioner.Provision(ctx, ui, comm, generatedData)
+ if err == nil {
+ return nil
+ }
+
+ leftTries := r.MaxRetries
+ for ; leftTries > 0; leftTries-- {
+ if ctx.Err() != nil { // context was cancelled
+ return ctx.Err()
+ }
+
+ ui.Say(fmt.Sprintf("Provisioner failed with %q, retrying with %d trie(s) left", err, leftTries))
+
+ err := r.Provisioner.Provision(ctx, ui, comm, generatedData)
+ if err == nil {
+ return nil
+ }
+
+ }
+ ui.Say("retry limit reached.")
+
+ return err
+}
+
+// DebuggedProvisioner is a Provisioner implementation that waits until a key
+// press before the provisioner is actually run.
+type DebuggedProvisioner struct {
+ Provisioner packersdk.Provisioner
+
+ cancelCh chan struct{}
+ doneCh chan struct{}
+ lock sync.Mutex
+}
+
+func (p *DebuggedProvisioner) ConfigSpec() hcldec.ObjectSpec { return p.ConfigSpec() }
+func (p *DebuggedProvisioner) FlatConfig() interface{} { return p.FlatConfig() }
+func (p *DebuggedProvisioner) Prepare(raws ...interface{}) error {
+ return p.Provisioner.Prepare(raws...)
+}
+
+func (p *DebuggedProvisioner) Provision(ctx context.Context, ui packersdk.Ui, comm packersdk.Communicator, generatedData map[string]interface{}) error {
+ // Use a select to determine if we get cancelled during the wait
+ message := "Pausing before the next provisioner . Press enter to continue."
+
+ result := make(chan string, 1)
+ go func() {
+ line, err := ui.Ask(message)
+ if err != nil {
+ log.Printf("Error asking for input: %s", err)
+ }
+
+ result <- line
+ }()
+
+ select {
+ case <-result:
+ case <-ctx.Done():
+ return ctx.Err()
+ }
+
+ return p.Provisioner.Provision(ctx, ui, comm, generatedData)
+}
diff --git a/v1.9.4/packer/provisioner_test.go b/v1.9.4/packer/provisioner_test.go
new file mode 100644
index 0000000..d5e1910
--- /dev/null
+++ b/v1.9.4/packer/provisioner_test.go
@@ -0,0 +1,348 @@
+// Copyright (c) HashiCorp, Inc.
+// SPDX-License-Identifier: MPL-2.0
+
+package packer
+
+import (
+ "context"
+ "errors"
+ "fmt"
+ "testing"
+ "time"
+
+ packersdk "github.com/hashicorp/packer-plugin-sdk/packer"
+)
+
+func TestProvisionHook_Impl(t *testing.T) {
+ var raw interface{}
+ raw = &ProvisionHook{}
+ if _, ok := raw.(packersdk.Hook); !ok {
+ t.Fatalf("must be a Hook")
+ }
+}
+
+func TestProvisionHook(t *testing.T) {
+ pA := &packersdk.MockProvisioner{}
+ pB := &packersdk.MockProvisioner{}
+
+ ui := testUi()
+ var comm packersdk.Communicator = new(packersdk.MockCommunicator)
+ var data interface{} = nil
+
+ hook := &ProvisionHook{
+ Provisioners: []*HookedProvisioner{
+ {pA, nil, ""},
+ {pB, nil, ""},
+ },
+ }
+
+ hook.Run(context.Background(), "foo", ui, comm, data)
+
+ if !pA.ProvCalled {
+ t.Error("provision should be called on pA")
+ }
+
+ if !pB.ProvCalled {
+ t.Error("provision should be called on pB")
+ }
+}
+
+func TestProvisionHook_nilComm(t *testing.T) {
+ pA := &packersdk.MockProvisioner{}
+ pB := &packersdk.MockProvisioner{}
+
+ ui := testUi()
+ var comm packersdk.Communicator = nil
+ var data interface{} = nil
+
+ hook := &ProvisionHook{
+ Provisioners: []*HookedProvisioner{
+ {pA, nil, ""},
+ {pB, nil, ""},
+ },
+ }
+
+ err := hook.Run(context.Background(), "foo", ui, comm, data)
+ if err == nil {
+ t.Fatal("should error")
+ }
+}
+
+func TestProvisionHook_cancel(t *testing.T) {
+ topCtx, topCtxCancel := context.WithCancel(context.Background())
+
+ p := &packersdk.MockProvisioner{
+ ProvFunc: func(ctx context.Context) error {
+ topCtxCancel()
+ <-ctx.Done()
+ return ctx.Err()
+ },
+ }
+
+ hook := &ProvisionHook{
+ Provisioners: []*HookedProvisioner{
+ {p, nil, ""},
+ },
+ }
+
+ err := hook.Run(topCtx, "foo", nil, new(packersdk.MockCommunicator), nil)
+ if err == nil {
+ t.Fatal("should have err")
+ }
+}
+
+// TODO(mitchellh): Test that they're run in the proper order
+
+func TestPausedProvisioner_impl(t *testing.T) {
+ var _ packersdk.Provisioner = new(PausedProvisioner)
+}
+
+func TestPausedProvisionerPrepare(t *testing.T) {
+ mock := new(packersdk.MockProvisioner)
+ prov := &PausedProvisioner{
+ Provisioner: mock,
+ }
+
+ prov.Prepare(42)
+ if !mock.PrepCalled {
+ t.Fatal("prepare should be called")
+ }
+ if mock.PrepConfigs[0] != 42 {
+ t.Fatal("should have proper configs")
+ }
+}
+
+func TestPausedProvisionerProvision(t *testing.T) {
+ mock := new(packersdk.MockProvisioner)
+ prov := &PausedProvisioner{
+ Provisioner: mock,
+ }
+
+ ui := testUi()
+ comm := new(packersdk.MockCommunicator)
+ prov.Provision(context.Background(), ui, comm, make(map[string]interface{}))
+ if !mock.ProvCalled {
+ t.Fatal("prov should be called")
+ }
+ if mock.ProvUi != ui {
+ t.Fatal("should have proper ui")
+ }
+ if mock.ProvCommunicator != comm {
+ t.Fatal("should have proper comm")
+ }
+}
+
+func TestPausedProvisionerProvision_waits(t *testing.T) {
+ startTime := time.Now()
+ waitTime := 50 * time.Millisecond
+
+ prov := &PausedProvisioner{
+ PauseBefore: waitTime,
+ Provisioner: &packersdk.MockProvisioner{
+ ProvFunc: func(context.Context) error {
+ timeSinceStartTime := time.Since(startTime)
+ if timeSinceStartTime < waitTime {
+ return fmt.Errorf("Spent not enough time waiting: %s", timeSinceStartTime)
+ }
+ return nil
+ },
+ },
+ }
+
+ err := prov.Provision(context.Background(), testUi(), new(packersdk.MockCommunicator), make(map[string]interface{}))
+
+ if err != nil {
+ t.Fatalf("prov failed: %v", err)
+ }
+}
+
+func TestPausedProvisionerCancel(t *testing.T) {
+ topCtx, cancelTopCtx := context.WithCancel(context.Background())
+
+ mock := new(packersdk.MockProvisioner)
+ prov := &PausedProvisioner{
+ Provisioner: mock,
+ }
+
+ mock.ProvFunc = func(ctx context.Context) error {
+ cancelTopCtx()
+ <-ctx.Done()
+ return ctx.Err()
+ }
+
+ err := prov.Provision(topCtx, testUi(), new(packersdk.MockCommunicator), make(map[string]interface{}))
+ if err == nil {
+ t.Fatal("should have err")
+ }
+}
+
+func TestDebuggedProvisioner_impl(t *testing.T) {
+ var _ packersdk.Provisioner = new(DebuggedProvisioner)
+}
+
+func TestDebuggedProvisionerPrepare(t *testing.T) {
+ mock := new(packersdk.MockProvisioner)
+ prov := &DebuggedProvisioner{
+ Provisioner: mock,
+ }
+
+ prov.Prepare(42)
+ if !mock.PrepCalled {
+ t.Fatal("prepare should be called")
+ }
+ if mock.PrepConfigs[0] != 42 {
+ t.Fatal("should have proper configs")
+ }
+}
+
+func TestDebuggedProvisionerProvision(t *testing.T) {
+ mock := new(packersdk.MockProvisioner)
+ prov := &DebuggedProvisioner{
+ Provisioner: mock,
+ }
+
+ ui := testUi()
+ comm := new(packersdk.MockCommunicator)
+ writeReader(ui, "\n")
+ prov.Provision(context.Background(), ui, comm, make(map[string]interface{}))
+ if !mock.ProvCalled {
+ t.Fatal("prov should be called")
+ }
+ if mock.ProvUi != ui {
+ t.Fatal("should have proper ui")
+ }
+ if mock.ProvCommunicator != comm {
+ t.Fatal("should have proper comm")
+ }
+}
+
+func TestDebuggedProvisionerCancel(t *testing.T) {
+ topCtx, topCtxCancel := context.WithCancel(context.Background())
+
+ mock := new(packersdk.MockProvisioner)
+ prov := &DebuggedProvisioner{
+ Provisioner: mock,
+ }
+
+ mock.ProvFunc = func(ctx context.Context) error {
+ topCtxCancel()
+ <-ctx.Done()
+ return ctx.Err()
+ }
+
+ err := prov.Provision(topCtx, testUi(), new(packersdk.MockCommunicator), make(map[string]interface{}))
+ if err == nil {
+ t.Fatal("should have error")
+ }
+}
+
+func TestRetriedProvisioner_impl(t *testing.T) {
+ var _ packersdk.Provisioner = new(RetriedProvisioner)
+}
+
+func TestRetriedProvisionerPrepare(t *testing.T) {
+ mock := new(packersdk.MockProvisioner)
+ prov := &RetriedProvisioner{
+ Provisioner: mock,
+ }
+
+ err := prov.Prepare(42)
+ if err != nil {
+ t.Fatal("should not have errored")
+ }
+ if !mock.PrepCalled {
+ t.Fatal("prepare should be called")
+ }
+ if mock.PrepConfigs[0] != 42 {
+ t.Fatal("should have proper configs")
+ }
+}
+
+func TestRetriedProvisionerProvision(t *testing.T) {
+ mock := &packersdk.MockProvisioner{
+ ProvFunc: func(ctx context.Context) error {
+ return errors.New("failed")
+ },
+ }
+
+ prov := &RetriedProvisioner{
+ MaxRetries: 2,
+ Provisioner: mock,
+ }
+
+ ui := testUi()
+ comm := new(packersdk.MockCommunicator)
+ err := prov.Provision(context.Background(), ui, comm, make(map[string]interface{}))
+ if err != nil {
+ t.Fatal("should not have errored")
+ }
+ if !mock.ProvCalled {
+ t.Fatal("prov should be called")
+ }
+ if !mock.ProvRetried {
+ t.Fatal("prov should be retried")
+ }
+ if mock.ProvUi != ui {
+ t.Fatal("should have proper ui")
+ }
+ if mock.ProvCommunicator != comm {
+ t.Fatal("should have proper comm")
+ }
+}
+
+func TestRetriedProvisionerCancelledProvision(t *testing.T) {
+ // Don't retry if context is cancelled
+ ctx, topCtxCancel := context.WithCancel(context.Background())
+
+ mock := &packersdk.MockProvisioner{
+ ProvFunc: func(ctx context.Context) error {
+ topCtxCancel()
+ <-ctx.Done()
+ return ctx.Err()
+ },
+ }
+
+ prov := &RetriedProvisioner{
+ MaxRetries: 2,
+ Provisioner: mock,
+ }
+
+ ui := testUi()
+ comm := new(packersdk.MockCommunicator)
+ err := prov.Provision(ctx, ui, comm, make(map[string]interface{}))
+ if err == nil {
+ t.Fatal("should have errored")
+ }
+ if !mock.ProvCalled {
+ t.Fatal("prov should be called")
+ }
+ if mock.ProvRetried {
+ t.Fatal("prov should NOT be retried")
+ }
+ if mock.ProvUi != ui {
+ t.Fatal("should have proper ui")
+ }
+ if mock.ProvCommunicator != comm {
+ t.Fatal("should have proper comm")
+ }
+}
+
+func TestRetriedProvisionerCancel(t *testing.T) {
+ topCtx, cancelTopCtx := context.WithCancel(context.Background())
+
+ mock := new(packersdk.MockProvisioner)
+ prov := &RetriedProvisioner{
+ Provisioner: mock,
+ }
+
+ mock.ProvFunc = func(ctx context.Context) error {
+ cancelTopCtx()
+ <-ctx.Done()
+ return ctx.Err()
+ }
+
+ err := prov.Provision(topCtx, testUi(), new(packersdk.MockCommunicator), make(map[string]interface{}))
+ if err == nil {
+ t.Fatal("should have err")
+ }
+}
diff --git a/v1.9.4/packer/provisioner_timeout.go b/v1.9.4/packer/provisioner_timeout.go
new file mode 100644
index 0000000..c740713
--- /dev/null
+++ b/v1.9.4/packer/provisioner_timeout.go
@@ -0,0 +1,48 @@
+// Copyright (c) HashiCorp, Inc.
+// SPDX-License-Identifier: MPL-2.0
+
+package packer
+
+import (
+ "context"
+ "fmt"
+ "time"
+
+ packersdk "github.com/hashicorp/packer-plugin-sdk/packer"
+)
+
+// TimeoutProvisioner is a Provisioner implementation that can timeout after a
+// duration
+type TimeoutProvisioner struct {
+ packersdk.Provisioner
+ Timeout time.Duration
+}
+
+func (p *TimeoutProvisioner) Provision(ctx context.Context, ui packersdk.Ui, comm packersdk.Communicator, generatedData map[string]interface{}) error {
+ ctx, cancel := context.WithTimeout(ctx, p.Timeout)
+ defer cancel()
+
+ // Use a select to determine if we get cancelled during the wait
+ ui.Say(fmt.Sprintf("Setting a %s timeout for the next provisioner...", p.Timeout))
+
+ errC := make(chan interface{})
+
+ go func() {
+ select {
+ case <-errC:
+ // all good
+ case <-ctx.Done():
+ switch ctx.Err() {
+ case context.DeadlineExceeded:
+ ui.Error("Cancelling provisioner after a timeout...")
+ default:
+ // the context also gets cancelled when the provisioner is
+ // successful
+ }
+ }
+ }()
+
+ err := p.Provisioner.Provision(ctx, ui, comm, generatedData)
+ close(errC)
+ return err
+}
diff --git a/v1.9.4/packer/run_interfaces.go b/v1.9.4/packer/run_interfaces.go
new file mode 100644
index 0000000..253998c
--- /dev/null
+++ b/v1.9.4/packer/run_interfaces.go
@@ -0,0 +1,94 @@
+// Copyright (c) HashiCorp, Inc.
+// SPDX-License-Identifier: MPL-2.0
+
+package packer
+
+import (
+ hcl "github.com/hashicorp/hcl/v2"
+ packersdk "github.com/hashicorp/packer-plugin-sdk/packer"
+ plugingetter "github.com/hashicorp/packer/packer/plugin-getter"
+)
+
+type GetBuildsOptions struct {
+ // Get builds except the ones that match with except and with only the ones
+ // that match with Only. When those are empty everything matches.
+ Except, Only []string
+ Debug, Force bool
+ OnError string
+
+ // count only/except match count; so say something when nothing matched.
+ ExceptMatches, OnlyMatches int
+}
+
+type BuildGetter interface {
+ // GetBuilds return all possible builds for a config. It also starts all
+ // builders.
+ // TODO(azr): rename to builder starter ?
+ GetBuilds(GetBuildsOptions) ([]packersdk.Build, hcl.Diagnostics)
+}
+
+type Evaluator interface {
+ // EvaluateExpression is meant to be used in the `packer console` command.
+ // It parses the input string and returns what needs to be displayed. In
+ // case of an error the error should be displayed.
+ EvaluateExpression(expr string) (output string, exit bool, diags hcl.Diagnostics)
+}
+
+type InitializeOptions struct {
+ // When set, the execution of datasources will be skipped and the datasource will provide
+ // an output spec that will be used for validation only.
+ SkipDatasourcesExecution bool
+}
+
+type PluginBinaryDetector interface {
+ // DetectPluginBinaries is used only for HCL2 templates, and loads required
+ // plugins if specified.
+ DetectPluginBinaries() hcl.Diagnostics
+}
+
+// The Handler handles all Packer things. This interface reflects the Packer
+// commands, ex: init, console ( evaluate ), fix config, inspect config, etc. To
+// run a build we will start the builds and then the core of Packer handles
+// execution.
+type Handler interface {
+ Initialize(InitializeOptions) hcl.Diagnostics
+ // PluginRequirements returns the list of plugin Requirements from the
+ // config file.
+ PluginRequirements() (plugingetter.Requirements, hcl.Diagnostics)
+ Evaluator
+ BuildGetter
+ ConfigFixer
+ ConfigInspector
+ PluginBinaryDetector
+}
+
+//go:generate enumer -type FixConfigMode
+type FixConfigMode int
+
+const (
+ // Stdout will make FixConfig simply print what the config should be; it
+ // will only work when a single file is passed.
+ Stdout FixConfigMode = iota
+ // Inplace fixes your files on the spot.
+ Inplace
+ // Diff shows a full diff.
+ Diff
+)
+
+type FixConfigOptions struct {
+ Mode FixConfigMode
+}
+
+type ConfigFixer interface {
+ // FixConfig will output the config in a fixed manner.
+ FixConfig(FixConfigOptions) hcl.Diagnostics
+}
+
+type InspectConfigOptions struct {
+ packersdk.Ui
+}
+
+type ConfigInspector interface {
+ // Inspect will output self inspection for a configuration
+ InspectConfig(InspectConfigOptions) (ret int)
+}
diff --git a/v1.9.4/packer/telemetry.go b/v1.9.4/packer/telemetry.go
new file mode 100644
index 0000000..1245ce5
--- /dev/null
+++ b/v1.9.4/packer/telemetry.go
@@ -0,0 +1,257 @@
+// Copyright (c) HashiCorp, Inc.
+// SPDX-License-Identifier: MPL-2.0
+
+package packer
+
+import (
+ "context"
+ "fmt"
+ "log"
+ "os"
+ "path/filepath"
+ "sort"
+ "time"
+
+ checkpoint "github.com/hashicorp/go-checkpoint"
+ "github.com/hashicorp/packer-plugin-sdk/pathing"
+ packerVersion "github.com/hashicorp/packer/version"
+ "github.com/zclconf/go-cty/cty"
+)
+
+type PackerTemplateType string
+
+const (
+ UnknownTemplate PackerTemplateType = "Unknown"
+ HCL2Template PackerTemplateType = "HCL2"
+ JSONTemplate PackerTemplateType = "JSON"
+)
+
+const TelemetryVersion string = "beta/packer/7"
+const TelemetryPanicVersion string = "beta/packer_panic/4"
+
+var CheckpointReporter *CheckpointTelemetry
+
+type PackerReport struct {
+ Spans []*TelemetrySpan `json:"spans"`
+ ExitCode int `json:"exit_code"`
+ Error string `json:"error"`
+ Command string `json:"command"`
+ TemplateType PackerTemplateType `json:"template_type"`
+ UseBundled bool `json:"use_bundled"`
+}
+
+type CheckpointTelemetry struct {
+ spans []*TelemetrySpan
+ signatureFile string
+ startTime time.Time
+ templateType PackerTemplateType
+ useBundled bool
+}
+
+func NewCheckpointReporter(disableSignature bool) *CheckpointTelemetry {
+ if disabled := os.Getenv("CHECKPOINT_DISABLE"); disabled != "" {
+ return nil
+ }
+
+ configDir, err := pathing.ConfigDir()
+ if err != nil {
+ log.Printf("[WARN] (telemetry) setup error: %s", err)
+ return nil
+ }
+
+ signatureFile := ""
+ if disableSignature {
+ log.Printf("[INFO] (telemetry) Checkpoint signature disabled")
+ } else {
+ signatureFile = filepath.Join(configDir, "checkpoint_signature")
+ }
+
+ return &CheckpointTelemetry{
+ signatureFile: signatureFile,
+ startTime: time.Now().UTC(),
+ templateType: UnknownTemplate,
+ }
+}
+
+func (c *CheckpointTelemetry) baseParams(prefix string) *checkpoint.ReportParams {
+ version := packerVersion.Version
+ if packerVersion.VersionPrerelease != "" {
+ version += "-" + packerVersion.VersionPrerelease
+ }
+
+ return &checkpoint.ReportParams{
+ Product: "packer",
+ SchemaVersion: prefix,
+ StartTime: c.startTime,
+ Version: version,
+ RunID: os.Getenv("PACKER_RUN_UUID"),
+ SignatureFile: c.signatureFile,
+ }
+}
+
+func (c *CheckpointTelemetry) ReportPanic(m string) error {
+ if c == nil {
+ return nil
+ }
+ panicParams := c.baseParams(TelemetryPanicVersion)
+ panicParams.Payload = m
+ panicParams.EndTime = time.Now().UTC()
+
+ // This timeout can be longer because it runs in the real main.
+ // We're also okay waiting a bit longer to collect panic information
+ ctx, cancel := context.WithTimeout(context.Background(), 2*time.Second)
+ defer cancel()
+
+ return checkpoint.Report(ctx, panicParams)
+}
+
+func (c *CheckpointTelemetry) AddSpan(name, pluginType string, options interface{}) *TelemetrySpan {
+ if c == nil {
+ return nil
+ }
+ log.Printf("[INFO] (telemetry) Starting %s %s", pluginType, name)
+
+ ts := &TelemetrySpan{
+ Name: name,
+ Options: flattenConfigKeys(options),
+ StartTime: time.Now().UTC(),
+ Type: pluginType,
+ }
+ c.spans = append(c.spans, ts)
+ return ts
+}
+
+// SetTemplateType registers the template type being processed for a Packer command
+func (c *CheckpointTelemetry) SetTemplateType(t PackerTemplateType) {
+ if c == nil {
+ return
+ }
+
+ c.templateType = t
+}
+
+// SetBundledUsage marks the template as using bundled plugins
+func (c *CheckpointTelemetry) SetBundledUsage() {
+ if c == nil {
+ return
+ }
+ c.useBundled = true
+}
+
+func (c *CheckpointTelemetry) Finalize(command string, errCode int, err error) error {
+ if c == nil {
+ return nil
+ }
+
+ params := c.baseParams(TelemetryVersion)
+ params.EndTime = time.Now().UTC()
+
+ extra := &PackerReport{
+ Spans: c.spans,
+ ExitCode: errCode,
+ Command: command,
+ }
+ if err != nil {
+ extra.Error = err.Error()
+ }
+
+ extra.UseBundled = c.useBundled
+ extra.TemplateType = c.templateType
+ params.Payload = extra
+ // b, _ := json.MarshalIndent(params, "", " ")
+ // log.Println(string(b))
+
+ ctx, cancel := context.WithTimeout(context.Background(), 2*time.Second)
+ defer cancel()
+
+ log.Printf("[INFO] (telemetry) Finalizing.")
+ return checkpoint.Report(ctx, params)
+}
+
+type TelemetrySpan struct {
+ EndTime time.Time `json:"end_time"`
+ Error string `json:"error"`
+ Name string `json:"name"`
+ Options []string `json:"options"`
+ StartTime time.Time `json:"start_time"`
+ Type string `json:"type"`
+}
+
+func (s *TelemetrySpan) End(err error) {
+ if s == nil {
+ return
+ }
+ s.EndTime = time.Now().UTC()
+ log.Printf("[INFO] (telemetry) ending %s", s.Name)
+ if err != nil {
+ s.Error = err.Error()
+ }
+}
+
+func flattenConfigKeys(options interface{}) []string {
+ var flatten func(string, interface{}) []string
+
+ flatten = func(prefix string, options interface{}) (strOpts []string) {
+ switch opt := options.(type) {
+ case map[string]interface{}:
+ return flattenJSON(prefix, options)
+ case cty.Value:
+ return flattenHCL(prefix, opt)
+ default:
+ return nil
+ }
+ }
+
+ flattened := flatten("", options)
+ sort.Strings(flattened)
+ return flattened
+}
+
+func flattenJSON(prefix string, options interface{}) (strOpts []string) {
+ if m, ok := options.(map[string]interface{}); ok {
+ for k, v := range m {
+ if prefix != "" {
+ k = prefix + "/" + k
+ }
+ if n, ok := v.(map[string]interface{}); ok {
+ strOpts = append(strOpts, flattenJSON(k, n)...)
+ } else {
+ strOpts = append(strOpts, k)
+ }
+ }
+ }
+ return
+}
+
+func flattenHCL(prefix string, v cty.Value) (args []string) {
+ if v.IsNull() {
+ return []string{}
+ }
+ t := v.Type()
+ switch {
+ case t.IsObjectType(), t.IsMapType():
+ if !v.IsKnown() {
+ return []string{}
+ }
+ it := v.ElementIterator()
+ for it.Next() {
+ key, val := it.Element()
+ keyStr := key.AsString()
+
+ if val.IsNull() {
+ continue
+ }
+
+ if prefix != "" {
+ keyStr = fmt.Sprintf("%s/%s", prefix, keyStr)
+ }
+
+ if val.Type().IsObjectType() || val.Type().IsMapType() {
+ args = append(args, flattenHCL(keyStr, val)...)
+ } else {
+ args = append(args, keyStr)
+ }
+ }
+ }
+ return args
+}
diff --git a/v1.9.4/packer/telemetry_test.go b/v1.9.4/packer/telemetry_test.go
new file mode 100644
index 0000000..a45db2b
--- /dev/null
+++ b/v1.9.4/packer/telemetry_test.go
@@ -0,0 +1,57 @@
+// Copyright (c) HashiCorp, Inc.
+// SPDX-License-Identifier: MPL-2.0
+
+package packer
+
+import (
+ "errors"
+ "testing"
+
+ "github.com/stretchr/testify/assert"
+)
+
+func TestFlattenConfigKeys_nil(t *testing.T) {
+ f := flattenConfigKeys(nil)
+ assert.Zero(t, f, "Expected empty list.")
+}
+
+func TestFlattenConfigKeys_nested(t *testing.T) {
+ inp := make(map[string]interface{})
+ inp["A"] = ""
+ inp["B"] = []string{}
+
+ c := make(map[string]interface{})
+ c["X"] = ""
+ d := make(map[string]interface{})
+ d["a"] = ""
+
+ c["Y"] = d
+ inp["C"] = c
+
+ assert.Equal(t,
+ []string{"A", "B", "C/X", "C/Y/a"},
+ flattenConfigKeys(inp),
+ "Input didn't flatten correctly.",
+ )
+}
+
+func TestCheckpointTelemetry(t *testing.T) {
+ defer func() {
+ if r := recover(); r != nil {
+ t.Error("a noop CheckpointTelemetry should not to panic but it did\n", r)
+ }
+ }()
+
+ // A null CheckpointTelemetry obtained in Packer when the CHECKPOINT_DISABLE env var is set results in a NOOP reporter
+ // The null reporter can be executable as a configured reporter but does not report any telemetry data.
+ var c *CheckpointTelemetry
+ c.SetTemplateType(HCL2Template)
+ c.SetBundledUsage()
+ c.AddSpan("mockprovisioner", "provisioner", nil)
+ if err := c.ReportPanic("Bogus Panic"); err != nil {
+ t.Errorf("calling ReportPanic on a nil checkpoint reporter should not error")
+ }
+ if err := c.Finalize("test", 1, errors.New("Bogus Error")); err != nil {
+ t.Errorf("calling Finalize on a nil checkpoint reporter should not error")
+ }
+}
diff --git a/v1.9.4/packer/test-fixtures/build-basic-interpolated-required.json b/v1.9.4/packer/test-fixtures/build-basic-interpolated-required.json
new file mode 100644
index 0000000..2cdd3df
--- /dev/null
+++ b/v1.9.4/packer/test-fixtures/build-basic-interpolated-required.json
@@ -0,0 +1,9 @@
+{
+ "variables": {
+ "name": null
+ },
+ "builders": [{
+ "name": "{{upper `name`}}",
+ "type": "test"
+ }]
+}
diff --git a/v1.9.4/packer/test-fixtures/build-basic-interpolated.json b/v1.9.4/packer/test-fixtures/build-basic-interpolated.json
new file mode 100644
index 0000000..c70677c
--- /dev/null
+++ b/v1.9.4/packer/test-fixtures/build-basic-interpolated.json
@@ -0,0 +1,6 @@
+{
+ "builders": [{
+ "name": "{{upper `name`}}",
+ "type": "test"
+ }]
+}
diff --git a/v1.9.4/packer/test-fixtures/build-basic.json b/v1.9.4/packer/test-fixtures/build-basic.json
new file mode 100644
index 0000000..d14f6ca
--- /dev/null
+++ b/v1.9.4/packer/test-fixtures/build-basic.json
@@ -0,0 +1,5 @@
+{
+ "builders": [{
+ "type": "test"
+ }]
+}
diff --git a/v1.9.4/packer/test-fixtures/build-env.json b/v1.9.4/packer/test-fixtures/build-env.json
new file mode 100644
index 0000000..4f2c9b1
--- /dev/null
+++ b/v1.9.4/packer/test-fixtures/build-env.json
@@ -0,0 +1,10 @@
+{
+ "variables": {
+ "var": "{{env `PACKER_TEST_ENV`}}"
+ },
+
+ "builders": [{
+ "type": "test",
+ "value": "{{user `var`}}"
+ }]
+}
diff --git a/v1.9.4/packer/test-fixtures/build-ignore-template-variable.json b/v1.9.4/packer/test-fixtures/build-ignore-template-variable.json
new file mode 100644
index 0000000..b835937
--- /dev/null
+++ b/v1.9.4/packer/test-fixtures/build-ignore-template-variable.json
@@ -0,0 +1,11 @@
+{
+ "variables": {
+ "var": "{{env `PACKER_TEST_ENV`}}_{{ .PACKER_TEST_TEMP }}",
+ "http_ip": "{{ .HTTPIP }}",
+ "array_var": "us-west-1,us-west-2"
+ },
+
+ "builders": [{
+ "type": "test"
+ }]
+}
diff --git a/v1.9.4/packer/test-fixtures/build-interpolated-name.json b/v1.9.4/packer/test-fixtures/build-interpolated-name.json
new file mode 100644
index 0000000..9ac1dd7
--- /dev/null
+++ b/v1.9.4/packer/test-fixtures/build-interpolated-name.json
@@ -0,0 +1,7 @@
+
+{
+ "builders": [{
+ "type": "test",
+ "name": "{{user `build_name`}}"
+ }]
+}
diff --git a/v1.9.4/packer/test-fixtures/build-names-basic.json b/v1.9.4/packer/test-fixtures/build-names-basic.json
new file mode 100644
index 0000000..1b01625
--- /dev/null
+++ b/v1.9.4/packer/test-fixtures/build-names-basic.json
@@ -0,0 +1,5 @@
+{
+ "builders": [
+ {"type": "something"}
+ ]
+}
diff --git a/v1.9.4/packer/test-fixtures/build-names-func.json b/v1.9.4/packer/test-fixtures/build-names-func.json
new file mode 100644
index 0000000..feb28cf
--- /dev/null
+++ b/v1.9.4/packer/test-fixtures/build-names-func.json
@@ -0,0 +1,5 @@
+{
+ "builders": [
+ {"type": "{{upper `tubes`}}"}
+ ]
+}
diff --git a/v1.9.4/packer/test-fixtures/build-pp.json b/v1.9.4/packer/test-fixtures/build-pp.json
new file mode 100644
index 0000000..e2b32cf
--- /dev/null
+++ b/v1.9.4/packer/test-fixtures/build-pp.json
@@ -0,0 +1,7 @@
+{
+ "builders": [{
+ "type": "test"
+ }],
+
+ "post-processors": ["test"]
+}
diff --git a/v1.9.4/packer/test-fixtures/build-prov-override.json b/v1.9.4/packer/test-fixtures/build-prov-override.json
new file mode 100644
index 0000000..eb35547
--- /dev/null
+++ b/v1.9.4/packer/test-fixtures/build-prov-override.json
@@ -0,0 +1,14 @@
+{
+ "builders": [{
+ "type": "test"
+ }],
+
+ "provisioners": [{
+ "type": "test",
+ "override": {
+ "test": {
+ "foo": "bar"
+ }
+ }
+ }]
+}
diff --git a/v1.9.4/packer/test-fixtures/build-prov-retry.json b/v1.9.4/packer/test-fixtures/build-prov-retry.json
new file mode 100644
index 0000000..ebfd54f
--- /dev/null
+++ b/v1.9.4/packer/test-fixtures/build-prov-retry.json
@@ -0,0 +1,16 @@
+{
+ "builders": [{
+ "type": "test"
+ }],
+
+ "provisioners": [
+ {
+ "type": "test-integer",
+ "max_retries": 1
+ },
+ {
+ "type": "test-string",
+ "max_retries": "1"
+ }
+ ]
+}
diff --git a/v1.9.4/packer/test-fixtures/build-prov-skip-include.json b/v1.9.4/packer/test-fixtures/build-prov-skip-include.json
new file mode 100644
index 0000000..2ba5e77
--- /dev/null
+++ b/v1.9.4/packer/test-fixtures/build-prov-skip-include.json
@@ -0,0 +1,10 @@
+{
+ "builders": [{
+ "type": "test"
+ }],
+
+ "provisioners": [{
+ "type": "test",
+ "only": ["test"]
+ }]
+}
diff --git a/v1.9.4/packer/test-fixtures/build-prov-skip.json b/v1.9.4/packer/test-fixtures/build-prov-skip.json
new file mode 100644
index 0000000..24d5971
--- /dev/null
+++ b/v1.9.4/packer/test-fixtures/build-prov-skip.json
@@ -0,0 +1,13 @@
+{
+ "builders": [{
+ "type": "test"
+ }, {
+ "name": "foo",
+ "type": "test"
+ }],
+
+ "provisioners": [{
+ "type": "test",
+ "only": ["foo"]
+ }]
+}
diff --git a/v1.9.4/packer/test-fixtures/build-prov.json b/v1.9.4/packer/test-fixtures/build-prov.json
new file mode 100644
index 0000000..332c28b
--- /dev/null
+++ b/v1.9.4/packer/test-fixtures/build-prov.json
@@ -0,0 +1,9 @@
+{
+ "builders": [{
+ "type": "test"
+ }],
+
+ "provisioners": [{
+ "type": "test"
+ }]
+}
diff --git a/v1.9.4/packer/test-fixtures/build-split-func.json b/v1.9.4/packer/test-fixtures/build-split-func.json
new file mode 100644
index 0000000..1b18f9f
--- /dev/null
+++ b/v1.9.4/packer/test-fixtures/build-split-func.json
@@ -0,0 +1,6 @@
+{
+ "builders": [{
+ "type": "test",
+ "value": "{{split \"foo-bar\" \"-\" 0}}"
+ }]
+}
diff --git a/v1.9.4/packer/test-fixtures/build-template-path.json b/v1.9.4/packer/test-fixtures/build-template-path.json
new file mode 100644
index 0000000..dcda081
--- /dev/null
+++ b/v1.9.4/packer/test-fixtures/build-template-path.json
@@ -0,0 +1,6 @@
+{
+ "builders": [{
+ "type": "test",
+ "value": "{{template_dir}}"
+ }]
+}
diff --git a/v1.9.4/packer/test-fixtures/build-var-build-name.json b/v1.9.4/packer/test-fixtures/build-var-build-name.json
new file mode 100644
index 0000000..da43d9a
--- /dev/null
+++ b/v1.9.4/packer/test-fixtures/build-var-build-name.json
@@ -0,0 +1,6 @@
+{
+ "builders": [{
+ "type": "test",
+ "value": "{{build_name}}"
+ }]
+}
diff --git a/v1.9.4/packer/test-fixtures/build-var-build-type.json b/v1.9.4/packer/test-fixtures/build-var-build-type.json
new file mode 100644
index 0000000..3d925e4
--- /dev/null
+++ b/v1.9.4/packer/test-fixtures/build-var-build-type.json
@@ -0,0 +1,6 @@
+{
+ "builders": [{
+ "type": "test",
+ "value": "{{build_type}}"
+ }]
+}
diff --git a/v1.9.4/packer/test-fixtures/build-var-file-interpolate.json b/v1.9.4/packer/test-fixtures/build-var-file-interpolate.json
new file mode 100644
index 0000000..d2f8f52
--- /dev/null
+++ b/v1.9.4/packer/test-fixtures/build-var-file-interpolate.json
@@ -0,0 +1,3 @@
+{
+ "name": "{{ user `my_var` }}"
+}
\ No newline at end of file
diff --git a/v1.9.4/packer/test-fixtures/build-var-file-interpolate2.json b/v1.9.4/packer/test-fixtures/build-var-file-interpolate2.json
new file mode 100644
index 0000000..c7a4c96
--- /dev/null
+++ b/v1.9.4/packer/test-fixtures/build-var-file-interpolate2.json
@@ -0,0 +1,3 @@
+{
+ "my_var": "interpolate this, yall"
+}
\ No newline at end of file
diff --git a/v1.9.4/packer/test-fixtures/build-var-packer-version.json b/v1.9.4/packer/test-fixtures/build-var-packer-version.json
new file mode 100644
index 0000000..89ffe39
--- /dev/null
+++ b/v1.9.4/packer/test-fixtures/build-var-packer-version.json
@@ -0,0 +1,9 @@
+{
+ "variables": {
+ "CreatedBy": "{{packer_version}}"
+ },
+ "builders": [{
+ "type": "test",
+ "value": "{{user `CreatedBy`}}"
+ }]
+}
diff --git a/v1.9.4/packer/test-fixtures/build-variables-interpolate.json b/v1.9.4/packer/test-fixtures/build-variables-interpolate.json
new file mode 100644
index 0000000..b3b32a7
--- /dev/null
+++ b/v1.9.4/packer/test-fixtures/build-variables-interpolate.json
@@ -0,0 +1,11 @@
+{
+ "variables": {
+ "foo": "bar",
+ "bar": "{{user `foo`}}",
+ "baz": "{{user `bar`}}baz",
+ "bang": "bang{{user `baz`}}"
+ },
+ "builders": [
+ {"type": "foo"}
+ ]
+}
diff --git a/v1.9.4/packer/test-fixtures/build-variables-interpolate2.json b/v1.9.4/packer/test-fixtures/build-variables-interpolate2.json
new file mode 100644
index 0000000..3d40197
--- /dev/null
+++ b/v1.9.4/packer/test-fixtures/build-variables-interpolate2.json
@@ -0,0 +1,10 @@
+{
+ "variables": {
+ "bar": "{{user `foo`}}",
+ "baz": "{{user `bar`}}baz",
+ "bang": "bang{{user `baz`}}"
+ },
+ "builders": [
+ {"type": "foo"}
+ ]
+}
diff --git a/v1.9.4/packer/test-fixtures/complex-recursed-env-user-var-file.json b/v1.9.4/packer/test-fixtures/complex-recursed-env-user-var-file.json
new file mode 100644
index 0000000..bffb4b1
--- /dev/null
+++ b/v1.9.4/packer/test-fixtures/complex-recursed-env-user-var-file.json
@@ -0,0 +1,11 @@
+{
+ "variables": {
+ "env_1": "{{ env `INTERPOLATE_TEST_ENV_1` }}",
+ "env_2": "{{ env `INTERPOLATE_TEST_ENV_2` }}",
+ "env_3": "{{ env `INTERPOLATE_TEST_ENV_3` }}",
+ "env_4": "{{ env `INTERPOLATE_TEST_ENV_4` }}"
+ },
+ "builders": [{
+ "type": "test"
+ }]
+}
\ No newline at end of file
diff --git a/v1.9.4/packer/test-fixtures/push-vars.json b/v1.9.4/packer/test-fixtures/push-vars.json
new file mode 100644
index 0000000..b5f5181
--- /dev/null
+++ b/v1.9.4/packer/test-fixtures/push-vars.json
@@ -0,0 +1,11 @@
+{
+ "variables": {
+ "foo": null
+ },
+
+ "builders": [{"type": "test"}],
+
+ "push": {
+ "name": "{{user `foo`}}"
+ }
+}
diff --git a/v1.9.4/packer/test-fixtures/sensitive-variables.json b/v1.9.4/packer/test-fixtures/sensitive-variables.json
new file mode 100644
index 0000000..7052ec4
--- /dev/null
+++ b/v1.9.4/packer/test-fixtures/sensitive-variables.json
@@ -0,0 +1,12 @@
+{
+ "variables": {
+ "foo": "bar_extra_sensitive_probably_a_password"
+ },
+ "sensitive-variables": [
+ "foo"
+ ],
+ "builders": [{
+ "type": "test",
+ "value": "{{build_name}}"
+ }]
+}
diff --git a/v1.9.4/packer/test-fixtures/validate-dup-builder.json b/v1.9.4/packer/test-fixtures/validate-dup-builder.json
new file mode 100644
index 0000000..21d206d
--- /dev/null
+++ b/v1.9.4/packer/test-fixtures/validate-dup-builder.json
@@ -0,0 +1,10 @@
+{
+ "builders": [
+ {"type": "foo"}
+ ],
+
+ "provisioners": [{
+ "type": "foo",
+ "only": ["bar"]
+ }]
+}
diff --git a/v1.9.4/packer/test-fixtures/validate-min-version-high.json b/v1.9.4/packer/test-fixtures/validate-min-version-high.json
new file mode 100644
index 0000000..2dd93a8
--- /dev/null
+++ b/v1.9.4/packer/test-fixtures/validate-min-version-high.json
@@ -0,0 +1,7 @@
+{
+ "min_packer_version": "2.1.0",
+
+ "builders": [
+ {"type": "foo"}
+ ]
+}
diff --git a/v1.9.4/packer/test-fixtures/validate-min-version.json b/v1.9.4/packer/test-fixtures/validate-min-version.json
new file mode 100644
index 0000000..a8bd742
--- /dev/null
+++ b/v1.9.4/packer/test-fixtures/validate-min-version.json
@@ -0,0 +1,7 @@
+{
+ "min_packer_version": "0.1.0",
+
+ "builders": [
+ {"type": "foo"}
+ ]
+}
diff --git a/v1.9.4/packer/test-fixtures/validate-req-variable.json b/v1.9.4/packer/test-fixtures/validate-req-variable.json
new file mode 100644
index 0000000..796d0b6
--- /dev/null
+++ b/v1.9.4/packer/test-fixtures/validate-req-variable.json
@@ -0,0 +1,9 @@
+{
+ "variables": {
+ "foo": null
+ },
+
+ "builders": [{
+ "type": "foo"
+ }]
+}
diff --git a/v1.9.4/packer/testing.go b/v1.9.4/packer/testing.go
new file mode 100644
index 0000000..0b24495
--- /dev/null
+++ b/v1.9.4/packer/testing.go
@@ -0,0 +1,82 @@
+// Copyright (c) HashiCorp, Inc.
+// SPDX-License-Identifier: MPL-2.0
+
+package packer
+
+import (
+ "bytes"
+ "io/ioutil"
+ "testing"
+
+ packersdk "github.com/hashicorp/packer-plugin-sdk/packer"
+)
+
+func TestCoreConfig(t *testing.T) *CoreConfig {
+ // Create some test components
+ components := ComponentFinder{
+ PluginConfig: &PluginConfig{
+ Builders: MapOfBuilder{
+ "test": func() (packersdk.Builder, error) { return &packersdk.MockBuilder{}, nil },
+ },
+ },
+ }
+
+ return &CoreConfig{
+ Components: components,
+ }
+}
+
+func TestCore(t *testing.T, c *CoreConfig) *Core {
+ core := NewCore(c)
+ err := core.Initialize(InitializeOptions{})
+ if err != nil {
+ t.Fatalf("err: %s", err)
+ }
+
+ return core
+}
+
+func TestUi(t *testing.T) packersdk.Ui {
+ var buf bytes.Buffer
+ return &packersdk.BasicUi{
+ Reader: &buf,
+ Writer: ioutil.Discard,
+ ErrorWriter: ioutil.Discard,
+ }
+}
+
+// TestBuilder sets the builder with the name n to the component finder
+// and returns the mock.
+func TestBuilder(t *testing.T, c *CoreConfig, n string) *packersdk.MockBuilder {
+ var b packersdk.MockBuilder
+
+ c.Components.PluginConfig.Builders = MapOfBuilder{
+ n: func() (packersdk.Builder, error) { return &b, nil },
+ }
+
+ return &b
+}
+
+// TestProvisioner sets the prov. with the name n to the component finder
+// and returns the mock.
+func TestProvisioner(t *testing.T, c *CoreConfig, n string) *packersdk.MockProvisioner {
+ var b packersdk.MockProvisioner
+
+ c.Components.PluginConfig.Provisioners = MapOfProvisioner{
+ n: func() (packersdk.Provisioner, error) { return &b, nil },
+ }
+
+ return &b
+}
+
+// TestPostProcessor sets the prov. with the name n to the component finder
+// and returns the mock.
+func TestPostProcessor(t *testing.T, c *CoreConfig, n string) *MockPostProcessor {
+ var b MockPostProcessor
+
+ c.Components.PluginConfig.PostProcessors = MapOfPostProcessor{
+ n: func() (packersdk.PostProcessor, error) { return &b, nil },
+ }
+
+ return &b
+}
diff --git a/v1.9.4/packer/ui.go b/v1.9.4/packer/ui.go
new file mode 100644
index 0000000..dac5689
--- /dev/null
+++ b/v1.9.4/packer/ui.go
@@ -0,0 +1,257 @@
+// Copyright (c) HashiCorp, Inc.
+// SPDX-License-Identifier: MPL-2.0
+
+package packer
+
+import (
+ "bytes"
+ "errors"
+ "fmt"
+ "io"
+ "log"
+ "os"
+ "runtime"
+ "strings"
+ "syscall"
+ "time"
+ "unicode"
+
+ getter "github.com/hashicorp/go-getter/v2"
+ packersdk "github.com/hashicorp/packer-plugin-sdk/packer"
+)
+
+var ErrInterrupted = errors.New("interrupted")
+
+type UiColor uint
+
+const (
+ UiColorRed UiColor = 31
+ UiColorGreen = 32
+ UiColorYellow = 33
+ UiColorBlue = 34
+ UiColorMagenta = 35
+ UiColorCyan = 36
+)
+
+// ColoredUi is a UI that is colored using terminal colors.
+type ColoredUi struct {
+ Color UiColor
+ ErrorColor UiColor
+ Ui packersdk.Ui
+ PB getter.ProgressTracker
+}
+
+var _ packersdk.Ui = new(ColoredUi)
+
+func (u *ColoredUi) Ask(query string) (string, error) {
+ return u.Ui.Ask(u.colorize(query, u.Color, true))
+}
+
+func (u *ColoredUi) Say(message string) {
+ u.Ui.Say(u.colorize(message, u.Color, true))
+}
+
+func (u *ColoredUi) Message(message string) {
+ u.Ui.Message(u.colorize(message, u.Color, false))
+}
+
+func (u *ColoredUi) Error(message string) {
+ color := u.ErrorColor
+ if color == 0 {
+ color = UiColorRed
+ }
+
+ u.Ui.Error(u.colorize(message, color, true))
+}
+
+func (u *ColoredUi) Machine(t string, args ...string) {
+ // Don't colorize machine-readable output
+ u.Ui.Machine(t, args...)
+}
+
+func (u *ColoredUi) TrackProgress(src string, currentSize, totalSize int64, stream io.ReadCloser) io.ReadCloser {
+ return u.Ui.TrackProgress(u.colorize(src, u.Color, false), currentSize, totalSize, stream)
+}
+
+func (u *ColoredUi) colorize(message string, color UiColor, bold bool) string {
+ if !u.supportsColors() {
+ return message
+ }
+
+ attr := 0
+ if bold {
+ attr = 1
+ }
+
+ return fmt.Sprintf("\033[%d;%dm%s\033[0m", attr, color, message)
+}
+
+func (u *ColoredUi) supportsColors() bool {
+ // Never use colors if we have this environmental variable
+ if os.Getenv("PACKER_NO_COLOR") != "" {
+ return false
+ }
+
+ // For now, on non-Windows machine, just assume it does
+ if runtime.GOOS != "windows" {
+ return true
+ }
+
+ // On Windows, if we appear to be in Cygwin, then it does
+ cygwin := os.Getenv("CYGWIN") != "" ||
+ os.Getenv("OSTYPE") == "cygwin" ||
+ os.Getenv("TERM") == "cygwin"
+
+ return cygwin
+}
+
+// TargetedUI is a UI that wraps another UI implementation and modifies
+// the output to indicate a specific target. Specifically, all Say output
+// is prefixed with the target name. Message output is not prefixed but
+// is offset by the length of the target so that output is lined up properly
+// with Say output. Machine-readable output has the proper target set.
+type TargetedUI struct {
+ Target string
+ Ui packersdk.Ui
+}
+
+var _ packersdk.Ui = new(TargetedUI)
+
+func (u *TargetedUI) Ask(query string) (string, error) {
+ return u.Ui.Ask(u.prefixLines(true, query))
+}
+
+func (u *TargetedUI) Say(message string) {
+ u.Ui.Say(u.prefixLines(true, message))
+}
+
+func (u *TargetedUI) Message(message string) {
+ u.Ui.Message(u.prefixLines(false, message))
+}
+
+func (u *TargetedUI) Error(message string) {
+ u.Ui.Error(u.prefixLines(true, message))
+}
+
+func (u *TargetedUI) Machine(t string, args ...string) {
+ // Prefix in the target, then pass through
+ u.Ui.Machine(fmt.Sprintf("%s,%s", u.Target, t), args...)
+}
+
+func (u *TargetedUI) prefixLines(arrow bool, message string) string {
+ arrowText := "==>"
+ if !arrow {
+ arrowText = strings.Repeat(" ", len(arrowText))
+ }
+
+ var result bytes.Buffer
+
+ for _, line := range strings.Split(message, "\n") {
+ result.WriteString(fmt.Sprintf("%s %s: %s\n", arrowText, u.Target, line))
+ }
+
+ return strings.TrimRightFunc(result.String(), unicode.IsSpace)
+}
+
+func (u *TargetedUI) TrackProgress(src string, currentSize, totalSize int64, stream io.ReadCloser) io.ReadCloser {
+ return u.Ui.TrackProgress(u.prefixLines(false, src), currentSize, totalSize, stream)
+}
+
+// MachineReadableUi is a UI that only outputs machine-readable output
+// to the given Writer.
+type MachineReadableUi struct {
+ Writer io.Writer
+ PB packersdk.NoopProgressTracker
+}
+
+var _ packersdk.Ui = new(MachineReadableUi)
+
+func (u *MachineReadableUi) Ask(query string) (string, error) {
+ return "", errors.New("machine-readable UI can't ask")
+}
+
+func (u *MachineReadableUi) Say(message string) {
+ u.Machine("ui", "say", message)
+}
+
+func (u *MachineReadableUi) Message(message string) {
+ u.Machine("ui", "message", message)
+}
+
+func (u *MachineReadableUi) Error(message string) {
+ u.Machine("ui", "error", message)
+}
+
+func (u *MachineReadableUi) Machine(category string, args ...string) {
+ now := time.Now().UTC()
+
+ // Determine if we have a target, and set it
+ target := ""
+ commaIdx := strings.Index(category, ",")
+ if commaIdx > -1 {
+ target = category[0:commaIdx]
+ category = category[commaIdx+1:]
+ }
+
+ // Prepare the args
+ for i, v := range args {
+ // Use packersdk.LogSecretFilter to scrub out sensitive variables
+ args[i] = packersdk.LogSecretFilter.FilterString(args[i])
+ args[i] = strings.Replace(v, ",", "%!(PACKER_COMMA)", -1)
+ args[i] = strings.Replace(args[i], "\r", "\\r", -1)
+ args[i] = strings.Replace(args[i], "\n", "\\n", -1)
+ }
+ argsString := strings.Join(args, ",")
+
+ _, err := fmt.Fprintf(u.Writer, "%d,%s,%s,%s\n", now.Unix(), target, category, argsString)
+ if err != nil {
+ if err == syscall.EPIPE || strings.Contains(err.Error(), "broken pipe") {
+ // Ignore epipe errors because that just means that the file
+ // is probably closed or going to /dev/null or something.
+ } else {
+ panic(err)
+ }
+ }
+ log.Printf("%d,%s,%s,%s\n", now.Unix(), target, category, argsString)
+}
+
+func (u *MachineReadableUi) TrackProgress(src string, currentSize, totalSize int64, stream io.ReadCloser) (body io.ReadCloser) {
+ return u.PB.TrackProgress(src, currentSize, totalSize, stream)
+}
+
+// TimestampedUi is a UI that wraps another UI implementation and
+// prefixes each message with an RFC3339 timestamp
+type TimestampedUi struct {
+ Ui packersdk.Ui
+ PB getter.ProgressTracker
+}
+
+var _ packersdk.Ui = new(TimestampedUi)
+
+func (u *TimestampedUi) Ask(query string) (string, error) {
+ return u.Ui.Ask(query)
+}
+
+func (u *TimestampedUi) Say(message string) {
+ u.Ui.Say(u.timestampLine(message))
+}
+
+func (u *TimestampedUi) Message(message string) {
+ u.Ui.Message(u.timestampLine(message))
+}
+
+func (u *TimestampedUi) Error(message string) {
+ u.Ui.Error(u.timestampLine(message))
+}
+
+func (u *TimestampedUi) Machine(message string, args ...string) {
+ u.Ui.Machine(message, args...)
+}
+
+func (u *TimestampedUi) TrackProgress(src string, currentSize, totalSize int64, stream io.ReadCloser) (body io.ReadCloser) {
+ return u.Ui.TrackProgress(src, currentSize, totalSize, stream)
+}
+
+func (u *TimestampedUi) timestampLine(string string) string {
+ return fmt.Sprintf("%v: %v", time.Now().Format(time.RFC3339), string)
+}
diff --git a/v1.9.4/packer/ui_test.go b/v1.9.4/packer/ui_test.go
new file mode 100644
index 0000000..1d15cb4
--- /dev/null
+++ b/v1.9.4/packer/ui_test.go
@@ -0,0 +1,300 @@
+// Copyright (c) HashiCorp, Inc.
+// SPDX-License-Identifier: MPL-2.0
+
+package packer
+
+import (
+ "bytes"
+ "strings"
+ "testing"
+
+ packersdk "github.com/hashicorp/packer-plugin-sdk/packer"
+)
+
+// This reads the output from the bytes.Buffer in our test object
+// and then resets the buffer.
+func readWriter(ui *packersdk.BasicUi) (result string) {
+ buffer := ui.Writer.(*bytes.Buffer)
+ result = buffer.String()
+ buffer.Reset()
+ return
+}
+
+// Reset the input Reader than add some input to it.
+func writeReader(ui *packersdk.BasicUi, input string) {
+ buffer := ui.Reader.(*bytes.Buffer)
+ buffer.WriteString(input)
+}
+
+func readErrorWriter(ui *packersdk.BasicUi) (result string) {
+ buffer := ui.ErrorWriter.(*bytes.Buffer)
+ result = buffer.String()
+ buffer.Reset()
+ return
+}
+
+func testUi() *packersdk.BasicUi {
+ return &packersdk.BasicUi{
+ Reader: new(bytes.Buffer),
+ Writer: new(bytes.Buffer),
+ ErrorWriter: new(bytes.Buffer),
+ TTY: new(testTTY),
+ }
+}
+
+type testTTY struct {
+ say string
+}
+
+func (tty *testTTY) Close() error { return nil }
+func (tty *testTTY) ReadString() (string, error) {
+ return tty.say, nil
+}
+
+func TestColoredUi(t *testing.T) {
+ bufferUi := testUi()
+ ui := &ColoredUi{UiColorYellow, UiColorRed, bufferUi, &UiProgressBar{}}
+
+ if !ui.supportsColors() {
+ t.Skip("skipping for ui without color support")
+ }
+
+ ui.Say("foo")
+ result := readWriter(bufferUi)
+ if result != "\033[1;33mfoo\033[0m\n" {
+ t.Fatalf("invalid output: %s", result)
+ }
+
+ ui.Message("foo")
+ result = readWriter(bufferUi)
+ if result != "\033[0;33mfoo\033[0m\n" {
+ t.Fatalf("invalid output: %s", result)
+ }
+
+ ui.Error("foo")
+ result = readWriter(bufferUi)
+ if result != "" {
+ t.Fatalf("invalid output: %s", result)
+ }
+
+ result = readErrorWriter(bufferUi)
+ if result != "\033[1;31mfoo\033[0m\n" {
+ t.Fatalf("invalid output: %s", result)
+ }
+}
+
+func TestColoredUi_noColorEnv(t *testing.T) {
+ bufferUi := testUi()
+ ui := &ColoredUi{UiColorYellow, UiColorRed, bufferUi, &UiProgressBar{}}
+
+ // Set the env var to get rid of the color
+ t.Setenv("PACKER_NO_COLOR", "1")
+
+ ui.Say("foo")
+ result := readWriter(bufferUi)
+ if result != "foo\n" {
+ t.Fatalf("invalid output: %s", result)
+ }
+
+ ui.Message("foo")
+ result = readWriter(bufferUi)
+ if result != "foo\n" {
+ t.Fatalf("invalid output: %s", result)
+ }
+
+ ui.Error("foo")
+ result = readErrorWriter(bufferUi)
+ if result != "foo\n" {
+ t.Fatalf("invalid output: %s", result)
+ }
+}
+
+func TestTargetedUI(t *testing.T) {
+ bufferUi := testUi()
+ targetedUi := &TargetedUI{
+ Target: "foo",
+ Ui: bufferUi,
+ }
+
+ var actual, expected string
+ targetedUi.Say("foo")
+ actual = readWriter(bufferUi)
+ expected = "==> foo: foo\n"
+ if actual != expected {
+ t.Fatalf("bad: %#v", actual)
+ }
+
+ targetedUi.Message("foo")
+ actual = readWriter(bufferUi)
+ expected = " foo: foo\n"
+ if actual != expected {
+ t.Fatalf("bad: %#v", actual)
+ }
+
+ targetedUi.Error("bar")
+ actual = readErrorWriter(bufferUi)
+ expected = "==> foo: bar\n"
+ if actual != expected {
+ t.Fatalf("bad: %#v", actual)
+ }
+
+ targetedUi.Say("foo\nbar")
+ actual = readWriter(bufferUi)
+ expected = "==> foo: foo\n==> foo: bar\n"
+ if actual != expected {
+ t.Fatalf("bad: %#v", actual)
+ }
+}
+
+func TestColoredUi_ImplUi(t *testing.T) {
+ var raw interface{}
+ raw = &ColoredUi{}
+ if _, ok := raw.(packersdk.Ui); !ok {
+ t.Fatalf("ColoredUi must implement Ui")
+ }
+}
+
+func TestTargetedUI_ImplUi(t *testing.T) {
+ var raw interface{}
+ raw = &TargetedUI{}
+ if _, ok := raw.(packersdk.Ui); !ok {
+ t.Fatalf("TargetedUI must implement Ui")
+ }
+}
+
+func TestBasicUi_ImplUi(t *testing.T) {
+ var raw interface{}
+ raw = &packersdk.BasicUi{}
+ if _, ok := raw.(packersdk.Ui); !ok {
+ t.Fatalf("BasicUi must implement Ui")
+ }
+}
+
+func TestBasicUi_Error(t *testing.T) {
+ bufferUi := testUi()
+
+ var actual, expected string
+ bufferUi.Error("foo")
+ actual = readErrorWriter(bufferUi)
+ expected = "foo\n"
+ if actual != expected {
+ t.Fatalf("bad: %#v", actual)
+ }
+
+ bufferUi.ErrorWriter = nil
+ bufferUi.Error("5")
+ actual = readWriter(bufferUi)
+ expected = "5\n"
+ if actual != expected {
+ t.Fatalf("bad: %#v", actual)
+ }
+}
+
+func TestBasicUi_Say(t *testing.T) {
+ bufferUi := testUi()
+
+ var actual, expected string
+
+ bufferUi.Say("foo")
+ actual = readWriter(bufferUi)
+ expected = "foo\n"
+ if actual != expected {
+ t.Fatalf("bad: %#v", actual)
+ }
+
+ bufferUi.Say("5")
+ actual = readWriter(bufferUi)
+ expected = "5\n"
+ if actual != expected {
+ t.Fatalf("bad: %#v", actual)
+ }
+}
+
+func TestBasicUi_Ask(t *testing.T) {
+
+ var actual, expected string
+ var err error
+
+ var testCases = []struct {
+ Prompt, Input, Answer string
+ }{
+ {"[c]ontinue or [a]bort", "c\n", "c"},
+ {"[c]ontinue or [a]bort", "c", "c"},
+ // Empty input shouldn't give an error
+ {"Name", "Joe Bloggs\n", "Joe Bloggs"},
+ {"Name", "Joe Bloggs", "Joe Bloggs"},
+ {"Name", "\n", ""},
+ }
+
+ for _, testCase := range testCases {
+ // Because of the internal bufio we can't easily reset the input, so create a new one each time
+ bufferUi := testUi()
+ bufferUi.TTY = &testTTY{testCase.Input}
+
+ actual, err = bufferUi.Ask(testCase.Prompt)
+ if err != nil {
+ t.Fatal(err)
+ }
+
+ if actual != testCase.Answer {
+ t.Fatalf("bad answer: %#v", actual)
+ }
+
+ actual = readWriter(bufferUi)
+ expected = testCase.Prompt + " "
+ if actual != expected {
+ t.Fatalf("bad prompt: %#v", actual)
+ }
+ }
+
+}
+
+func TestMachineReadableUi_ImplUi(t *testing.T) {
+ var raw interface{}
+ raw = &MachineReadableUi{}
+ if _, ok := raw.(packersdk.Ui); !ok {
+ t.Fatalf("MachineReadableUi must implement Ui")
+ }
+}
+
+func TestMachineReadableUi(t *testing.T) {
+ var data, expected string
+
+ buf := new(bytes.Buffer)
+ ui := &MachineReadableUi{Writer: buf}
+
+ // No target
+ ui.Machine("foo", "bar", "baz")
+ data = strings.SplitN(buf.String(), ",", 2)[1]
+ expected = ",foo,bar,baz\n"
+ if data != expected {
+ t.Fatalf("bad: %s", data)
+ }
+
+ // Target
+ buf.Reset()
+ ui.Machine("mitchellh,foo", "bar", "baz")
+ data = strings.SplitN(buf.String(), ",", 2)[1]
+ expected = "mitchellh,foo,bar,baz\n"
+ if data != expected {
+ t.Fatalf("bad: %s", data)
+ }
+
+ // Commas
+ buf.Reset()
+ ui.Machine("foo", "foo,bar")
+ data = strings.SplitN(buf.String(), ",", 2)[1]
+ expected = ",foo,foo%!(PACKER_COMMA)bar\n"
+ if data != expected {
+ t.Fatalf("bad: %s", data)
+ }
+
+ // New lines
+ buf.Reset()
+ ui.Machine("foo", "foo\n")
+ data = strings.SplitN(buf.String(), ",", 2)[1]
+ expected = ",foo,foo\\n\n"
+ if data != expected {
+ t.Fatalf("bad: %#v", data)
+ }
+}
diff --git a/v1.9.4/panic.go b/v1.9.4/panic.go
new file mode 100644
index 0000000..6f60964
--- /dev/null
+++ b/v1.9.4/panic.go
@@ -0,0 +1,71 @@
+// Copyright (c) HashiCorp, Inc.
+// SPDX-License-Identifier: MPL-2.0
+
+package main
+
+import (
+ "fmt"
+ "io"
+ "os"
+ "strings"
+
+ "github.com/hashicorp/packer/packer"
+ "github.com/mitchellh/panicwrap"
+)
+
+// This is output if a panic happens.
+const panicOutput = `
+
+!!!!!!!!!!!!!!!!!!!!!!!!!!! PACKER CRASH !!!!!!!!!!!!!!!!!!!!!!!!!!!!
+
+Packer crashed! This is always indicative of a bug within Packer.
+A crash log has been placed at "crash.log" relative to your current
+working directory. It would be immensely helpful if you could please
+report the crash with Packer[1] so that we can fix this.
+
+[1]: https://github.com/hashicorp/packer/issues
+
+!!!!!!!!!!!!!!!!!!!!!!!!!!! PACKER CRASH !!!!!!!!!!!!!!!!!!!!!!!!!!!!
+`
+
+// panicHandler is what is called by panicwrap when a panic is encountered
+// within Packer. It is guaranteed to run after the resulting process has
+// exited so we can take the log file, add in the panic, and store it
+// somewhere locally.
+func panicHandler(logF *os.File) panicwrap.HandlerFunc {
+ return func(m string) {
+ // Write away just output this thing on stderr so that it gets
+ // shown in case anything below fails.
+ fmt.Fprintf(os.Stderr, fmt.Sprintf("%s\n", m))
+
+ if err := packer.CheckpointReporter.ReportPanic(m); err != nil {
+ fmt.Fprintf(os.Stderr, "Failed to report panic. This is safe to ignore: %s", err)
+ }
+
+ // Create the crash log file where we'll write the logs
+ f, err := os.Create("crash.log")
+ if err != nil {
+ fmt.Fprintf(os.Stderr, "Failed to create crash log file: %s", err)
+ return
+ }
+ defer f.Close()
+
+ // Seek the log file back to the beginning
+ if _, err = logF.Seek(0, 0); err != nil {
+ fmt.Fprintf(os.Stderr, "Failed to seek log file for crash: %s", err)
+ return
+ }
+
+ // Copy the contents to the crash file. This will include
+ // the panic that just happened.
+ if _, err = io.Copy(f, logF); err != nil {
+ fmt.Fprintf(os.Stderr, "Failed to write crash log: %s", err)
+ return
+ }
+
+ // Tell the user a crash occurred in some helpful way that
+ // they'll hopefully notice.
+ fmt.Printf("\n\n")
+ fmt.Println(strings.TrimSpace(panicOutput))
+ }
+}
diff --git a/v1.9.4/post-processor/artifice/artifact.go b/v1.9.4/post-processor/artifice/artifact.go
new file mode 100644
index 0000000..4f481b2
--- /dev/null
+++ b/v1.9.4/post-processor/artifice/artifact.go
@@ -0,0 +1,65 @@
+// Copyright (c) HashiCorp, Inc.
+// SPDX-License-Identifier: MPL-2.0
+
+package artifice
+
+import (
+ "fmt"
+ "os"
+ "path/filepath"
+ "strings"
+)
+
+const BuilderId = "packer.post-processor.artifice"
+
+type Artifact struct {
+ files []string
+}
+
+func NewArtifact(files []string) (*Artifact, error) {
+ artifact := &Artifact{}
+ for _, f := range files {
+ globfiles, err := filepath.Glob(f)
+ if err != nil {
+ return nil, err
+ }
+ for _, gf := range globfiles {
+ if _, err := os.Stat(gf); err != nil {
+ return nil, err
+ }
+ artifact.files = append(artifact.files, gf)
+ }
+ }
+ return artifact, nil
+}
+
+func (a *Artifact) BuilderId() string {
+ return BuilderId
+}
+
+func (a *Artifact) Files() []string {
+ return a.files
+}
+
+func (a *Artifact) Id() string {
+ return ""
+}
+
+func (a *Artifact) String() string {
+ files := strings.Join(a.files, ", ")
+ return fmt.Sprintf("Created artifact from files: %s", files)
+}
+
+func (a *Artifact) State(name string) interface{} {
+ return nil
+}
+
+func (a *Artifact) Destroy() error {
+ for _, f := range a.files {
+ err := os.RemoveAll(f)
+ if err != nil {
+ return err
+ }
+ }
+ return nil
+}
diff --git a/v1.9.4/post-processor/artifice/post-processor.go b/v1.9.4/post-processor/artifice/post-processor.go
new file mode 100644
index 0000000..334d853
--- /dev/null
+++ b/v1.9.4/post-processor/artifice/post-processor.go
@@ -0,0 +1,70 @@
+// Copyright (c) HashiCorp, Inc.
+// SPDX-License-Identifier: MPL-2.0
+
+//go:generate packer-sdc mapstructure-to-hcl2 -type Config
+
+package artifice
+
+import (
+ "context"
+ "fmt"
+ "strings"
+
+ "github.com/hashicorp/hcl/v2/hcldec"
+ "github.com/hashicorp/packer-plugin-sdk/common"
+ packersdk "github.com/hashicorp/packer-plugin-sdk/packer"
+ "github.com/hashicorp/packer-plugin-sdk/template/config"
+ "github.com/hashicorp/packer-plugin-sdk/template/interpolate"
+)
+
+// The artifact-override post-processor allows you to specify arbitrary files as
+// artifacts. These will override any other artifacts created by the builder.
+// This allows you to use a builder and provisioner to create some file, such as
+// a compiled binary or tarball, extract it from the builder (VM or container)
+// and then save that binary or tarball and throw away the builder.
+
+type Config struct {
+ common.PackerConfig `mapstructure:",squash"`
+
+ Files []string `mapstructure:"files"`
+ Keep bool `mapstructure:"keep_input_artifact"`
+
+ ctx interpolate.Context
+}
+
+type PostProcessor struct {
+ config Config
+}
+
+func (p *PostProcessor) ConfigSpec() hcldec.ObjectSpec { return p.config.FlatMapstructure().HCL2Spec() }
+
+func (p *PostProcessor) Configure(raws ...interface{}) error {
+ err := config.Decode(&p.config, &config.DecodeOpts{
+ PluginType: "artifice",
+ Interpolate: true,
+ InterpolateContext: &p.config.ctx,
+ InterpolateFilter: &interpolate.RenderFilter{
+ Exclude: []string{},
+ },
+ }, raws...)
+ if err != nil {
+ return err
+ }
+
+ if len(p.config.Files) == 0 {
+ return fmt.Errorf("No files specified in artifice configuration")
+ }
+
+ return nil
+}
+
+func (p *PostProcessor) PostProcess(ctx context.Context, ui packersdk.Ui, artifact packersdk.Artifact) (packersdk.Artifact, bool, bool, error) {
+ if len(artifact.Files()) > 0 {
+ ui.Say(fmt.Sprintf("Discarding files from artifact: %s", strings.Join(artifact.Files(), ", ")))
+ }
+
+ artifact, err := NewArtifact(p.config.Files)
+ ui.Say(fmt.Sprintf("Using these artifact files: %s", strings.Join(artifact.Files(), ", ")))
+
+ return artifact, true, false, err
+}
diff --git a/v1.9.4/post-processor/artifice/post-processor.hcl2spec.go b/v1.9.4/post-processor/artifice/post-processor.hcl2spec.go
new file mode 100644
index 0000000..d2f4f98
--- /dev/null
+++ b/v1.9.4/post-processor/artifice/post-processor.hcl2spec.go
@@ -0,0 +1,49 @@
+// Code generated by "packer-sdc mapstructure-to-hcl2"; DO NOT EDIT.
+
+package artifice
+
+import (
+ "github.com/hashicorp/hcl/v2/hcldec"
+ "github.com/zclconf/go-cty/cty"
+)
+
+// FlatConfig is an auto-generated flat version of Config.
+// Where the contents of a field with a `mapstructure:,squash` tag are bubbled up.
+type FlatConfig struct {
+ PackerBuildName *string `mapstructure:"packer_build_name" cty:"packer_build_name" 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"`
+ Files []string `mapstructure:"files" cty:"files" hcl:"files"`
+ Keep *bool `mapstructure:"keep_input_artifact" cty:"keep_input_artifact" hcl:"keep_input_artifact"`
+}
+
+// FlatMapstructure returns a new FlatConfig.
+// FlatConfig is an auto-generated flat version of Config.
+// Where the contents a fields with a `mapstructure:,squash` tag are bubbled up.
+func (*Config) FlatMapstructure() interface{ HCL2Spec() map[string]hcldec.Spec } {
+ return new(FlatConfig)
+}
+
+// HCL2Spec returns the hcl spec of a Config.
+// This spec is used by HCL to read the fields of Config.
+// The decoded values from this spec will then be applied to a FlatConfig.
+func (*FlatConfig) HCL2Spec() map[string]hcldec.Spec {
+ s := map[string]hcldec.Spec{
+ "packer_build_name": &hcldec.AttrSpec{Name: "packer_build_name", Type: cty.String, Required: false},
+ "packer_builder_type": &hcldec.AttrSpec{Name: "packer_builder_type", Type: cty.String, Required: false},
+ "packer_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_sensitive_variables": &hcldec.AttrSpec{Name: "packer_sensitive_variables", Type: cty.List(cty.String), Required: false},
+ "files": &hcldec.AttrSpec{Name: "files", Type: cty.List(cty.String), Required: false},
+ "keep_input_artifact": &hcldec.AttrSpec{Name: "keep_input_artifact", Type: cty.Bool, Required: false},
+ }
+ return s
+}
diff --git a/v1.9.4/post-processor/artifice/version/version.go b/v1.9.4/post-processor/artifice/version/version.go
new file mode 100644
index 0000000..b426efb
--- /dev/null
+++ b/v1.9.4/post-processor/artifice/version/version.go
@@ -0,0 +1,16 @@
+// Copyright (c) HashiCorp, Inc.
+// SPDX-License-Identifier: MPL-2.0
+
+package version
+
+import (
+ "github.com/hashicorp/packer-plugin-sdk/version"
+ packerVersion "github.com/hashicorp/packer/version"
+)
+
+var ArtificePluginVersion *version.PluginVersion
+
+func init() {
+ ArtificePluginVersion = version.InitializePluginVersion(
+ packerVersion.Version, packerVersion.VersionPrerelease)
+}
diff --git a/v1.9.4/post-processor/checksum/LICENSE b/v1.9.4/post-processor/checksum/LICENSE
new file mode 100644
index 0000000..bd410b0
--- /dev/null
+++ b/v1.9.4/post-processor/checksum/LICENSE
@@ -0,0 +1,21 @@
+The MIT License (MIT)
+
+Copyright (c) 2016 Vasiliy Tolstov
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in all
+copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+SOFTWARE.
diff --git a/v1.9.4/post-processor/checksum/artifact.go b/v1.9.4/post-processor/checksum/artifact.go
new file mode 100644
index 0000000..eb1eeee
--- /dev/null
+++ b/v1.9.4/post-processor/checksum/artifact.go
@@ -0,0 +1,51 @@
+// Copyright (c) HashiCorp, Inc.
+// SPDX-License-Identifier: MPL-2.0
+
+package checksum
+
+import (
+ "fmt"
+ "os"
+ "strings"
+)
+
+const BuilderId = "packer.post-processor.checksum"
+
+type Artifact struct {
+ files []string
+}
+
+func NewArtifact(files []string) *Artifact {
+ return &Artifact{files: files}
+}
+
+func (a *Artifact) BuilderId() string {
+ return BuilderId
+}
+
+func (a *Artifact) Files() []string {
+ return a.files
+}
+
+func (a *Artifact) Id() string {
+ return ""
+}
+
+func (a *Artifact) String() string {
+ files := strings.Join(a.files, ", ")
+ return fmt.Sprintf("Created artifact from files: %s", files)
+}
+
+func (a *Artifact) State(name string) interface{} {
+ return nil
+}
+
+func (a *Artifact) Destroy() error {
+ for _, f := range a.files {
+ err := os.RemoveAll(f)
+ if err != nil {
+ return err
+ }
+ }
+ return nil
+}
diff --git a/v1.9.4/post-processor/checksum/post-processor.go b/v1.9.4/post-processor/checksum/post-processor.go
new file mode 100644
index 0000000..28b107c
--- /dev/null
+++ b/v1.9.4/post-processor/checksum/post-processor.go
@@ -0,0 +1,163 @@
+// Copyright (c) HashiCorp, Inc.
+// SPDX-License-Identifier: MPL-2.0
+
+//go:generate packer-sdc mapstructure-to-hcl2 -type Config
+
+package checksum
+
+import (
+ "context"
+ "crypto/md5"
+ "crypto/sha1"
+ "crypto/sha256"
+ "crypto/sha512"
+ "fmt"
+ "hash"
+ "io"
+ "os"
+ "path/filepath"
+
+ "github.com/hashicorp/hcl/v2/hcldec"
+ "github.com/hashicorp/packer-plugin-sdk/common"
+ packersdk "github.com/hashicorp/packer-plugin-sdk/packer"
+ "github.com/hashicorp/packer-plugin-sdk/template/config"
+ "github.com/hashicorp/packer-plugin-sdk/template/interpolate"
+)
+
+type Config struct {
+ common.PackerConfig `mapstructure:",squash"`
+
+ ChecksumTypes []string `mapstructure:"checksum_types"`
+ OutputPath string `mapstructure:"output"`
+ ctx interpolate.Context
+}
+
+type PostProcessor struct {
+ config Config
+}
+
+func getHash(t string) hash.Hash {
+ var h hash.Hash
+ switch t {
+ case "md5":
+ h = md5.New()
+ case "sha1":
+ h = sha1.New()
+ case "sha224":
+ h = sha256.New224()
+ case "sha256":
+ h = sha256.New()
+ case "sha384":
+ h = sha512.New384()
+ case "sha512":
+ h = sha512.New()
+ }
+ return h
+}
+
+func (p *PostProcessor) ConfigSpec() hcldec.ObjectSpec { return p.config.FlatMapstructure().HCL2Spec() }
+
+func (p *PostProcessor) Configure(raws ...interface{}) error {
+ err := config.Decode(&p.config, &config.DecodeOpts{
+ PluginType: "checksum",
+ Interpolate: true,
+ InterpolateContext: &p.config.ctx,
+ InterpolateFilter: &interpolate.RenderFilter{
+ Exclude: []string{"output"},
+ },
+ }, raws...)
+ if err != nil {
+ return err
+ }
+ errs := new(packersdk.MultiError)
+
+ if p.config.ChecksumTypes == nil {
+ p.config.ChecksumTypes = []string{"md5"}
+ }
+
+ for _, k := range p.config.ChecksumTypes {
+ if h := getHash(k); h == nil {
+ errs = packersdk.MultiErrorAppend(errs,
+ fmt.Errorf("Unrecognized checksum type: %s", k))
+ }
+ }
+
+ if p.config.OutputPath == "" {
+ p.config.OutputPath = "packer_{{.BuildName}}_{{.BuilderType}}_{{.ChecksumType}}.checksum"
+ }
+
+ if err = interpolate.Validate(p.config.OutputPath, &p.config.ctx); err != nil {
+ errs = packersdk.MultiErrorAppend(
+ errs, fmt.Errorf("Error parsing target template: %s", err))
+ }
+
+ if len(errs.Errors) > 0 {
+ return errs
+ }
+
+ return nil
+}
+
+func (p *PostProcessor) PostProcess(ctx context.Context, ui packersdk.Ui, artifact packersdk.Artifact) (packersdk.Artifact, bool, bool, error) {
+ files := artifact.Files()
+ var h hash.Hash
+
+ var generatedData map[interface{}]interface{}
+ stateData := artifact.State("generated_data")
+ if stateData != nil {
+ // Make sure it's not a nil map so we can assign to it later.
+ generatedData = stateData.(map[interface{}]interface{})
+ }
+ // If stateData has a nil map generatedData will be nil
+ // and we need to make sure it's not
+ if generatedData == nil {
+ generatedData = make(map[interface{}]interface{})
+ }
+ generatedData["BuildName"] = p.config.PackerBuildName
+ generatedData["BuilderType"] = p.config.PackerBuilderType
+
+ newartifact := NewArtifact(artifact.Files())
+
+ for _, ct := range p.config.ChecksumTypes {
+ h = getHash(ct)
+ generatedData["ChecksumType"] = ct
+ p.config.ctx.Data = generatedData
+
+ for _, art := range files {
+ checksumFile, err := interpolate.Render(p.config.OutputPath, &p.config.ctx)
+ if err != nil {
+ return nil, false, true, err
+ }
+
+ if _, err := os.Stat(checksumFile); err != nil {
+ newartifact.files = append(newartifact.files, checksumFile)
+ }
+ if err := os.MkdirAll(filepath.Dir(checksumFile), os.FileMode(0755)); err != nil {
+ return nil, false, true, fmt.Errorf("unable to create dir: %s", err.Error())
+ }
+ fw, err := os.OpenFile(checksumFile, os.O_WRONLY|os.O_APPEND|os.O_CREATE, os.FileMode(0644))
+ if err != nil {
+ return nil, false, true, fmt.Errorf("unable to create file %s: %s", checksumFile, err.Error())
+ }
+ fr, err := os.Open(art)
+ if err != nil {
+ fw.Close()
+ return nil, false, true, fmt.Errorf("unable to open file %s: %s", art, err.Error())
+ }
+
+ if _, err = io.Copy(h, fr); err != nil {
+ fr.Close()
+ fw.Close()
+ return nil, false, true, fmt.Errorf("unable to compute %s hash for %s", ct, art)
+ }
+ fr.Close()
+ fw.WriteString(fmt.Sprintf("%x\t%s\n", h.Sum(nil), filepath.Base(art)))
+ fw.Close()
+ h.Reset()
+ }
+ }
+
+ // sets keep and forceOverride to true because we don't want to accidentally
+ // delete the very artifact we're checksumming.
+ return newartifact, true, true, nil
+}
diff --git a/v1.9.4/post-processor/checksum/post-processor.hcl2spec.go b/v1.9.4/post-processor/checksum/post-processor.hcl2spec.go
new file mode 100644
index 0000000..52eed24
--- /dev/null
+++ b/v1.9.4/post-processor/checksum/post-processor.hcl2spec.go
@@ -0,0 +1,49 @@
+// Code generated by "packer-sdc mapstructure-to-hcl2"; DO NOT EDIT.
+
+package checksum
+
+import (
+ "github.com/hashicorp/hcl/v2/hcldec"
+ "github.com/zclconf/go-cty/cty"
+)
+
+// FlatConfig is an auto-generated flat version of Config.
+// Where the contents of a field with a `mapstructure:,squash` tag are bubbled up.
+type FlatConfig struct {
+ PackerBuildName *string `mapstructure:"packer_build_name" cty:"packer_build_name" 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"`
+ ChecksumTypes []string `mapstructure:"checksum_types" cty:"checksum_types" hcl:"checksum_types"`
+ OutputPath *string `mapstructure:"output" cty:"output" hcl:"output"`
+}
+
+// FlatMapstructure returns a new FlatConfig.
+// FlatConfig is an auto-generated flat version of Config.
+// Where the contents a fields with a `mapstructure:,squash` tag are bubbled up.
+func (*Config) FlatMapstructure() interface{ HCL2Spec() map[string]hcldec.Spec } {
+ return new(FlatConfig)
+}
+
+// HCL2Spec returns the hcl spec of a Config.
+// This spec is used by HCL to read the fields of Config.
+// The decoded values from this spec will then be applied to a FlatConfig.
+func (*FlatConfig) HCL2Spec() map[string]hcldec.Spec {
+ s := map[string]hcldec.Spec{
+ "packer_build_name": &hcldec.AttrSpec{Name: "packer_build_name", Type: cty.String, Required: false},
+ "packer_builder_type": &hcldec.AttrSpec{Name: "packer_builder_type", Type: cty.String, Required: false},
+ "packer_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_sensitive_variables": &hcldec.AttrSpec{Name: "packer_sensitive_variables", Type: cty.List(cty.String), Required: false},
+ "checksum_types": &hcldec.AttrSpec{Name: "checksum_types", Type: cty.List(cty.String), Required: false},
+ "output": &hcldec.AttrSpec{Name: "output", Type: cty.String, Required: false},
+ }
+ return s
+}
diff --git a/v1.9.4/post-processor/checksum/post-processor_test.go b/v1.9.4/post-processor/checksum/post-processor_test.go
new file mode 100644
index 0000000..97ab201
--- /dev/null
+++ b/v1.9.4/post-processor/checksum/post-processor_test.go
@@ -0,0 +1,111 @@
+// Copyright (c) HashiCorp, Inc.
+// SPDX-License-Identifier: MPL-2.0
+
+package checksum
+
+import (
+ "bytes"
+ "context"
+ "fmt"
+ "io/ioutil"
+ "os"
+ "strings"
+ "testing"
+
+ packersdk "github.com/hashicorp/packer-plugin-sdk/packer"
+ "github.com/hashicorp/packer-plugin-sdk/template"
+ "github.com/hashicorp/packer/builder/file"
+)
+
+const expectedFileContents = "Hello world!"
+
+func TestChecksumSHA1(t *testing.T) {
+ const config = `
+ {
+ "post-processors": [
+ {
+ "type": "checksum",
+ "checksum_types": ["sha1"],
+ "output": "sha1sums"
+ }
+ ]
+ }
+ `
+ artifact := testChecksum(t, config)
+ defer artifact.Destroy()
+
+ f, err := os.Open("sha1sums")
+ if err != nil {
+ t.Errorf("Unable to read checksum file: %s", err)
+ }
+ if buf, _ := ioutil.ReadAll(f); !bytes.Equal(buf, []byte("d3486ae9136e7856bc42212385ea797094475802\tpackage.txt\n")) {
+ t.Errorf("Failed to compute checksum: %s\n%s", buf, "d3486ae9136e7856bc42212385ea797094475802 package.txt")
+ }
+
+ defer f.Close()
+}
+
+// Test Helpers
+
+func setup(t *testing.T) (packersdk.Ui, packersdk.Artifact, error) {
+ // Create fake UI and Cache
+ ui := packersdk.TestUi(t)
+
+ // Create config for file builder
+ const fileConfig = `{"builders":[{"type":"file","target":"package.txt","content":"Hello world!"}]}`
+ tpl, err := template.Parse(strings.NewReader(fileConfig))
+ if err != nil {
+ return nil, nil, fmt.Errorf("Unable to parse setup configuration: %s", err)
+ }
+
+ // Prepare the file builder
+ builder := file.Builder{}
+ _, warnings, err := builder.Prepare(tpl.Builders["file"].Config)
+ if len(warnings) > 0 {
+ for _, warn := range warnings {
+ return nil, nil, fmt.Errorf("Configuration warning: %s", warn)
+ }
+ }
+ if err != nil {
+ return nil, nil, fmt.Errorf("Invalid configuration: %s", err)
+ }
+
+ // Run the file builder
+ artifact, err := builder.Run(context.Background(), ui, nil)
+ if err != nil {
+ return nil, nil, fmt.Errorf("Failed to build artifact: %s", err)
+ }
+
+ return ui, artifact, err
+}
+
+func testChecksum(t *testing.T, config string) packersdk.Artifact {
+ ui, artifact, err := setup(t)
+ if err != nil {
+ t.Fatalf("Error bootstrapping test: %s", err)
+ }
+ if artifact != nil {
+ defer artifact.Destroy()
+ }
+
+ tpl, err := template.Parse(strings.NewReader(config))
+ if err != nil {
+ t.Fatalf("Unable to parse test config: %s", err)
+ }
+
+ checksum := PostProcessor{}
+ checksum.Configure(tpl.PostProcessors[0][0].Config)
+
+ // I get the feeling these should be automatically available somewhere, but
+ // some of the post-processors construct this manually.
+ checksum.config.ctx.BuildName = "chocolate"
+ checksum.config.PackerBuildName = "vanilla"
+ checksum.config.PackerBuilderType = "file"
+
+ artifactOut, _, _, err := checksum.PostProcess(context.Background(), ui, artifact)
+ if err != nil {
+ t.Fatalf("Failed to checksum artifact: %s", err)
+ }
+
+ return artifactOut
+}
diff --git a/v1.9.4/post-processor/checksum/version/version.go b/v1.9.4/post-processor/checksum/version/version.go
new file mode 100644
index 0000000..74332d8
--- /dev/null
+++ b/v1.9.4/post-processor/checksum/version/version.go
@@ -0,0 +1,16 @@
+// Copyright (c) HashiCorp, Inc.
+// SPDX-License-Identifier: MPL-2.0
+
+package version
+
+import (
+ "github.com/hashicorp/packer-plugin-sdk/version"
+ packerVersion "github.com/hashicorp/packer/version"
+)
+
+var ChecksumPluginVersion *version.PluginVersion
+
+func init() {
+ ChecksumPluginVersion = version.InitializePluginVersion(
+ packerVersion.Version, packerVersion.VersionPrerelease)
+}
diff --git a/v1.9.4/post-processor/compress/LICENSE b/v1.9.4/post-processor/compress/LICENSE
new file mode 100644
index 0000000..38bbf26
--- /dev/null
+++ b/v1.9.4/post-processor/compress/LICENSE
@@ -0,0 +1,21 @@
+The MIT License (MIT)
+
+Copyright (c) 2014 Vasiliy Tolstov
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in all
+copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+SOFTWARE.
diff --git a/v1.9.4/post-processor/compress/artifact.go b/v1.9.4/post-processor/compress/artifact.go
new file mode 100644
index 0000000..20c7ef7
--- /dev/null
+++ b/v1.9.4/post-processor/compress/artifact.go
@@ -0,0 +1,39 @@
+// Copyright (c) HashiCorp, Inc.
+// SPDX-License-Identifier: MPL-2.0
+
+package compress
+
+import (
+ "fmt"
+ "os"
+)
+
+const BuilderId = "packer.post-processor.compress"
+
+type Artifact struct {
+ Path string
+}
+
+func (a *Artifact) BuilderId() string {
+ return BuilderId
+}
+
+func (*Artifact) Id() string {
+ return ""
+}
+
+func (a *Artifact) Files() []string {
+ return []string{a.Path}
+}
+
+func (a *Artifact) String() string {
+ return fmt.Sprintf("compressed artifacts in: %s", a.Path)
+}
+
+func (*Artifact) State(name string) interface{} {
+ return nil
+}
+
+func (a *Artifact) Destroy() error {
+ return os.Remove(a.Path)
+}
diff --git a/v1.9.4/post-processor/compress/artifact_test.go b/v1.9.4/post-processor/compress/artifact_test.go
new file mode 100644
index 0000000..d0c1da8
--- /dev/null
+++ b/v1.9.4/post-processor/compress/artifact_test.go
@@ -0,0 +1,18 @@
+// Copyright (c) HashiCorp, Inc.
+// SPDX-License-Identifier: MPL-2.0
+
+package compress
+
+import (
+ "testing"
+
+ packersdk "github.com/hashicorp/packer-plugin-sdk/packer"
+)
+
+func TestArtifact_ImplementsArtifact(t *testing.T) {
+ var raw interface{}
+ raw = &Artifact{}
+ if _, ok := raw.(packersdk.Artifact); !ok {
+ t.Fatalf("Artifact should be a Artifact!")
+ }
+}
diff --git a/v1.9.4/post-processor/compress/benchmark.go b/v1.9.4/post-processor/compress/benchmark.go
new file mode 100644
index 0000000..f853c85
--- /dev/null
+++ b/v1.9.4/post-processor/compress/benchmark.go
@@ -0,0 +1,234 @@
+// Copyright (c) HashiCorp, Inc.
+// SPDX-License-Identifier: MPL-2.0
+
+//go:build ignore
+// +build ignore
+
+package main
+
+import (
+ "compress/flate"
+ "compress/gzip"
+ "fmt"
+ "io"
+ "io/ioutil"
+ "os"
+ "runtime"
+ "testing"
+
+ "github.com/biogo/hts/bgzf"
+ "github.com/klauspost/pgzip"
+ "github.com/pierrec/lz4"
+ "github.com/ulikunitz/xz"
+)
+
+type Compressor struct {
+ r *os.File
+ w *os.File
+ sr int64
+ sw int64
+}
+
+func (c *Compressor) Close() error {
+ var err error
+
+ fi, _ := c.w.Stat()
+ c.sw = fi.Size()
+ if err = c.w.Close(); err != nil {
+ return err
+ }
+
+ fi, _ = c.r.Stat()
+ c.sr = fi.Size()
+ if err = c.r.Close(); err != nil {
+ return err
+ }
+
+ return nil
+}
+
+func NewCompressor(src, dst string) (*Compressor, error) {
+ r, err := os.Open(src)
+ if err != nil {
+ return nil, err
+ }
+
+ w, err := os.Create(dst)
+ if err != nil {
+ r.Close()
+ return nil, err
+ }
+
+ c := &Compressor{r: r, w: w}
+ return c, nil
+}
+
+func main() {
+
+ runtime.GOMAXPROCS(runtime.NumCPU())
+
+ var resw testing.BenchmarkResult
+ var resr testing.BenchmarkResult
+
+ c, err := NewCompressor("/tmp/image.r", "/tmp/image.w")
+ if err != nil {
+ panic(err)
+ }
+ resw = testing.Benchmark(c.BenchmarkGZIPWriter)
+ c.w.Seek(0, 0)
+ resr = testing.Benchmark(c.BenchmarkGZIPReader)
+ c.Close()
+ fmt.Printf("gzip:\twriter %s\treader %s\tsize %d\n", resw.T.String(), resr.T.String(), c.sw)
+
+ c, err = NewCompressor("/tmp/image.r", "/tmp/image.w")
+ if err != nil {
+ panic(err)
+ }
+ resw = testing.Benchmark(c.BenchmarkBGZFWriter)
+ c.w.Seek(0, 0)
+ resr = testing.Benchmark(c.BenchmarkBGZFReader)
+ c.Close()
+ fmt.Printf("bgzf:\twriter %s\treader %s\tsize %d\n", resw.T.String(), resr.T.String(), c.sw)
+
+ c, err = NewCompressor("/tmp/image.r", "/tmp/image.w")
+ if err != nil {
+ panic(err)
+ }
+ resw = testing.Benchmark(c.BenchmarkPGZIPWriter)
+ c.w.Seek(0, 0)
+ resr = testing.Benchmark(c.BenchmarkPGZIPReader)
+ c.Close()
+ fmt.Printf("pgzip:\twriter %s\treader %s\tsize %d\n", resw.T.String(), resr.T.String(), c.sw)
+
+ c, err = NewCompressor("/tmp/image.r", "/tmp/image.w")
+ if err != nil {
+ panic(err)
+ }
+ resw = testing.Benchmark(c.BenchmarkLZ4Writer)
+ c.w.Seek(0, 0)
+ resr = testing.Benchmark(c.BenchmarkLZ4Reader)
+ c.Close()
+ fmt.Printf("lz4:\twriter %s\treader %s\tsize %d\n", resw.T.String(), resr.T.String(), c.sw)
+
+ c, err = NewCompressor("/tmp/image.r", "/tmp/image.w")
+ if err != nil {
+ panic(err)
+ }
+ resw = testing.Benchmark(c.BenchmarkXZWriter)
+ c.w.Seek(0, 0)
+ resr = testing.Benchmark(c.BenchmarkXZReader)
+ c.Close()
+ fmt.Printf("xz:\twriter %s\treader %s\tsize %d\n", resw.T.String(), resr.T.String(), c.sw)
+
+}
+
+func (c *Compressor) BenchmarkGZIPWriter(b *testing.B) {
+ cw, _ := gzip.NewWriterLevel(c.w, flate.BestSpeed)
+ b.ResetTimer()
+
+ _, err := io.Copy(cw, c.r)
+ if err != nil {
+ b.Fatal(err)
+ }
+ cw.Close()
+ c.w.Sync()
+}
+
+func (c *Compressor) BenchmarkGZIPReader(b *testing.B) {
+ cr, _ := gzip.NewReader(c.w)
+ b.ResetTimer()
+
+ _, err := io.Copy(ioutil.Discard, cr)
+ if err != nil {
+ b.Fatal(err)
+ }
+}
+
+func (c *Compressor) BenchmarkBGZFWriter(b *testing.B) {
+ cw, _ := bgzf.NewWriterLevel(c.w, flate.BestSpeed, runtime.NumCPU())
+ b.ResetTimer()
+
+ _, err := io.Copy(cw, c.r)
+ if err != nil {
+ b.Fatal(err)
+ }
+ c.w.Sync()
+}
+
+func (c *Compressor) BenchmarkBGZFReader(b *testing.B) {
+ cr, _ := bgzf.NewReader(c.w, 0)
+ b.ResetTimer()
+
+ _, err := io.Copy(ioutil.Discard, cr)
+ if err != nil {
+ b.Fatal(err)
+ }
+}
+
+func (c *Compressor) BenchmarkPGZIPWriter(b *testing.B) {
+ cw, _ := pgzip.NewWriterLevel(c.w, flate.BestSpeed)
+ b.ResetTimer()
+
+ _, err := io.Copy(cw, c.r)
+ if err != nil {
+ b.Fatal(err)
+ }
+ cw.Close()
+ c.w.Sync()
+}
+
+func (c *Compressor) BenchmarkPGZIPReader(b *testing.B) {
+ cr, _ := pgzip.NewReader(c.w)
+ b.ResetTimer()
+
+ _, err := io.Copy(ioutil.Discard, cr)
+ if err != nil {
+ b.Fatal(err)
+ }
+}
+
+func (c *Compressor) BenchmarkLZ4Writer(b *testing.B) {
+ cw := lz4.NewWriter(c.w)
+ // cw.Header.HighCompression = true
+ cw.Header.NoChecksum = true
+ b.ResetTimer()
+
+ _, err := io.Copy(cw, c.r)
+ if err != nil {
+ b.Fatal(err)
+ }
+ cw.Close()
+ c.w.Sync()
+}
+
+func (c *Compressor) BenchmarkLZ4Reader(b *testing.B) {
+ cr := lz4.NewReader(c.w)
+ b.ResetTimer()
+
+ _, err := io.Copy(ioutil.Discard, cr)
+ if err != nil {
+ b.Fatal(err)
+ }
+}
+
+func (c *Compressor) BenchmarkXZWriter(b *testing.B) {
+ cw := xz.NewWriter(c.w)
+ b.ResetTimer()
+
+ _, err := io.Copy(cw, c.r)
+ if err != nil {
+ b.Fatal(err)
+ }
+ cw.Close()
+ c.w.Sync()
+}
+
+func (c *Compressor) BenchmarkXZReader(b *testing.B) {
+ cr := xz.NewReader(c.w)
+ b.ResetTimer()
+
+ _, err := io.Copy(ioutil.Discard, cr)
+ if err != nil {
+ b.Fatal(err)
+ }
+}
diff --git a/v1.9.4/post-processor/compress/notes.txt b/v1.9.4/post-processor/compress/notes.txt
new file mode 100644
index 0000000..51f9f7f
--- /dev/null
+++ b/v1.9.4/post-processor/compress/notes.txt
@@ -0,0 +1,3 @@
+* 1.9.6 => GNU tar format
+* 1.10.3 w/ patch => GNU tar format
+* 1.10.3 w/o patch => Posix tar format
diff --git a/v1.9.4/post-processor/compress/post-processor.go b/v1.9.4/post-processor/compress/post-processor.go
new file mode 100644
index 0000000..9d2a32e
--- /dev/null
+++ b/v1.9.4/post-processor/compress/post-processor.go
@@ -0,0 +1,418 @@
+// Copyright (c) HashiCorp, Inc.
+// SPDX-License-Identifier: MPL-2.0
+
+//go:generate packer-sdc mapstructure-to-hcl2 -type Config
+
+package compress
+
+import (
+ "archive/tar"
+ "archive/zip"
+ "context"
+ "fmt"
+ "io"
+ "os"
+ "path/filepath"
+ "regexp"
+ "runtime"
+
+ "github.com/biogo/hts/bgzf"
+ "github.com/dsnet/compress/bzip2"
+ "github.com/hashicorp/hcl/v2/hcldec"
+ "github.com/hashicorp/packer-plugin-sdk/common"
+ 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/klauspost/pgzip"
+ "github.com/pierrec/lz4"
+ "github.com/ulikunitz/xz"
+)
+
+var (
+ // ErrInvalidCompressionLevel is returned when the compression level passed
+ // to gzip is not in the expected range. See compress/flate for details.
+ ErrInvalidCompressionLevel = fmt.Errorf(
+ "Invalid compression level. Expected an integer from -1 to 9.")
+
+ ErrWrongInputCount = fmt.Errorf(
+ "Can only have 1 input file when not using tar/zip")
+
+ filenamePattern = regexp.MustCompile(`(?:\.([a-z0-9]+))`)
+)
+
+type Config struct {
+ common.PackerConfig `mapstructure:",squash"`
+
+ // Fields from config file
+ OutputPath string `mapstructure:"output"`
+ Format string `mapstructure:"format"`
+ CompressionLevel int `mapstructure:"compression_level"`
+
+ // Derived fields
+ Archive string
+ Algorithm string
+
+ ctx interpolate.Context
+}
+
+type PostProcessor struct {
+ config Config
+}
+
+func (p *PostProcessor) ConfigSpec() hcldec.ObjectSpec { return p.config.FlatMapstructure().HCL2Spec() }
+
+func (p *PostProcessor) Configure(raws ...interface{}) error {
+ err := config.Decode(&p.config, &config.DecodeOpts{
+ PluginType: "compress",
+ Interpolate: true,
+ InterpolateContext: &p.config.ctx,
+ InterpolateFilter: &interpolate.RenderFilter{
+ Exclude: []string{"output"},
+ },
+ }, raws...)
+ if err != nil {
+ return err
+ }
+
+ errs := new(packersdk.MultiError)
+
+ // If there is no explicit number of Go threads to use, then set it
+ if os.Getenv("GOMAXPROCS") == "" {
+ runtime.GOMAXPROCS(runtime.NumCPU())
+ }
+
+ if p.config.OutputPath == "" {
+ p.config.OutputPath = "packer_{{.BuildName}}_{{.BuilderType}}"
+ }
+
+ if p.config.CompressionLevel > pgzip.BestCompression {
+ p.config.CompressionLevel = pgzip.BestCompression
+ }
+ // Technically 0 means "don't compress" but I don't know how to
+ // differentiate between "user entered zero" and "user entered nothing".
+ // Also, why bother creating a compressed file with zero compression?
+ if p.config.CompressionLevel == -1 || p.config.CompressionLevel == 0 {
+ p.config.CompressionLevel = pgzip.DefaultCompression
+ }
+
+ if err = interpolate.Validate(p.config.OutputPath, &p.config.ctx); err != nil {
+ errs = packersdk.MultiErrorAppend(
+ errs, fmt.Errorf("Error parsing target template: %s", err))
+ }
+
+ p.config.detectFromFilename()
+
+ if len(errs.Errors) > 0 {
+ return errs
+ }
+
+ return nil
+}
+
+func (p *PostProcessor) PostProcess(
+ ctx context.Context,
+ ui packersdk.Ui,
+ artifact packersdk.Artifact,
+) (packersdk.Artifact, bool, bool, error) {
+ var generatedData map[interface{}]interface{}
+ stateData := artifact.State("generated_data")
+ if stateData != nil {
+ // Make sure it's not a nil map so we can assign to it later.
+ generatedData = stateData.(map[interface{}]interface{})
+ }
+ // If stateData has a nil map generatedData will be nil
+ // and we need to make sure it's not
+ if generatedData == nil {
+ generatedData = make(map[interface{}]interface{})
+ }
+
+ // These are extra variables that will be made available for interpolation.
+ generatedData["BuildName"] = p.config.PackerBuildName
+ generatedData["BuilderType"] = p.config.PackerBuilderType
+ p.config.ctx.Data = generatedData
+
+ target, err := interpolate.Render(p.config.OutputPath, &p.config.ctx)
+ if err != nil {
+ return nil, false, false, fmt.Errorf("Error interpolating output value: %s", err)
+ } else {
+ fmt.Println(target)
+ }
+
+ newArtifact := &Artifact{Path: target}
+
+ if err = os.MkdirAll(filepath.Dir(target), os.FileMode(0755)); err != nil {
+ return nil, false, false, fmt.Errorf(
+ "Unable to create dir for archive %s: %s", target, err)
+ }
+ outputFile, err := os.Create(target)
+ if err != nil {
+ return nil, false, false, fmt.Errorf(
+ "Unable to create archive %s: %s", target, err)
+ }
+ defer outputFile.Close()
+
+ // Setup output interface. If we're using compression, output is a
+ // compression writer. Otherwise it's just a file.
+ var output io.WriteCloser
+ errTmpl := "error creating %s writer: %s"
+ switch p.config.Algorithm {
+ case "bgzf":
+ ui.Say(fmt.Sprintf("Using bgzf compression with %d cores for %s",
+ runtime.GOMAXPROCS(-1), target))
+ output, err = makeBGZFWriter(outputFile, p.config.CompressionLevel)
+ if err != nil {
+ return nil, false, false, fmt.Errorf(errTmpl, p.config.Algorithm, err)
+ }
+ defer output.Close()
+ case "bzip2":
+ ui.Say(fmt.Sprintf("Using bzip2 compression with 1 core for %s (library does not support MT)",
+ target))
+ output, err = makeBZIP2Writer(outputFile, p.config.CompressionLevel)
+ if err != nil {
+ return nil, false, false, fmt.Errorf(errTmpl, p.config.Algorithm, err)
+ }
+ defer output.Close()
+ case "lz4":
+ ui.Say(fmt.Sprintf("Using lz4 compression with %d cores for %s",
+ runtime.GOMAXPROCS(-1), target))
+ output, err = makeLZ4Writer(outputFile, p.config.CompressionLevel)
+ if err != nil {
+ return nil, false, false, fmt.Errorf(errTmpl, p.config.Algorithm, err)
+ }
+ defer output.Close()
+ case "xz":
+ ui.Say(fmt.Sprintf("Using xz compression with 1 core for %s (library does not support MT)",
+ target))
+ output, err = makeXZWriter(outputFile)
+ if err != nil {
+ return nil, false, false, fmt.Errorf(errTmpl, p.config.Algorithm, err)
+ }
+ defer output.Close()
+ case "pgzip":
+ ui.Say(fmt.Sprintf("Using pgzip compression with %d cores for %s",
+ runtime.GOMAXPROCS(-1), target))
+ output, err = makePgzipWriter(outputFile, p.config.CompressionLevel)
+ if err != nil {
+ return nil, false, false,
+ fmt.Errorf(errTmpl, p.config.Algorithm, err)
+ }
+ defer output.Close()
+ default:
+ output = outputFile
+ }
+
+ compression := p.config.Algorithm
+ if compression == "" {
+ compression = "no compression"
+ }
+
+ // Build an archive, if we're supposed to do that.
+ switch p.config.Archive {
+ case "tar":
+ ui.Say(fmt.Sprintf("Tarring %s with %s", target, compression))
+ err = createTarArchive(artifact.Files(), output)
+ if err != nil {
+ return nil, false, false, fmt.Errorf("Error creating tar: %s", err)
+ }
+ case "zip":
+ ui.Say(fmt.Sprintf("Zipping %s", target))
+ err = createZipArchive(artifact.Files(), output)
+ if err != nil {
+ return nil, false, false, fmt.Errorf("Error creating zip: %s", err)
+ }
+ default:
+ // Filename indicates no tarball (just compress) so we'll do an io.Copy
+ // into our compressor.
+ if len(artifact.Files()) != 1 {
+ return nil, false, false, fmt.Errorf(
+ "Can only have 1 input file when not using tar/zip. Found %d "+
+ "files: %v", len(artifact.Files()), artifact.Files())
+ }
+ archiveFile := artifact.Files()[0]
+ ui.Say(fmt.Sprintf("Archiving %s with %s", archiveFile, compression))
+
+ source, err := os.Open(archiveFile)
+ if err != nil {
+ return nil, false, false, fmt.Errorf(
+ "Failed to open source file %s for reading: %s",
+ archiveFile, err)
+ }
+ defer source.Close()
+
+ if _, err = io.Copy(output, source); err != nil {
+ return nil, false, false, fmt.Errorf("Failed to compress %s: %s",
+ archiveFile, err)
+ }
+ }
+
+ ui.Say(fmt.Sprintf("Archive %s completed", target))
+
+ return newArtifact, false, false, nil
+}
+
+func (config *Config) detectFromFilename() {
+ var result [][]string
+
+ extensions := map[string]string{
+ "tar": "tar",
+ "zip": "zip",
+ "gz": "pgzip",
+ "lz4": "lz4",
+ "bgzf": "bgzf",
+ "xz": "xz",
+ "bzip2": "bzip2",
+ }
+
+ if config.Format == "" {
+ result = filenamePattern.FindAllStringSubmatch(config.OutputPath, -1)
+ } else {
+ result = filenamePattern.FindAllStringSubmatch(fmt.Sprintf("%s.%s", config.OutputPath, config.Format), -1)
+ }
+
+ // No dots. Bail out with defaults.
+ if len(result) == 0 {
+ config.Algorithm = "pgzip"
+ config.Archive = "tar"
+ return
+ }
+
+ // Parse the last two .groups, if they're there
+ lastItem := result[len(result)-1][1]
+ var nextToLastItem string
+ if len(result) == 1 {
+ nextToLastItem = ""
+ } else {
+ nextToLastItem = result[len(result)-2][1]
+ }
+
+ // Should we make an archive? E.g. tar or zip?
+ if nextToLastItem == "tar" {
+ config.Archive = "tar"
+ }
+ if lastItem == "zip" || lastItem == "tar" {
+ config.Archive = lastItem
+ // Tar or zip is our final artifact. Bail out.
+ return
+ }
+
+ // Should we compress the artifact?
+ algorithm, ok := extensions[lastItem]
+ if ok {
+ config.Algorithm = algorithm
+ // We found our compression algorithm. Bail out.
+ return
+ }
+
+ // We didn't match a known compression format. Default to tar + pgzip
+ config.Algorithm = "pgzip"
+ config.Archive = "tar"
+ return
+}
+
+func makeBGZFWriter(output io.WriteCloser, compressionLevel int) (io.WriteCloser, error) {
+ bgzfWriter, err := bgzf.NewWriterLevel(output, compressionLevel, runtime.GOMAXPROCS(-1))
+ if err != nil {
+ return nil, ErrInvalidCompressionLevel
+ }
+ return bgzfWriter, nil
+}
+
+func makeBZIP2Writer(output io.Writer, compressionLevel int) (io.WriteCloser, error) {
+ // Set the default to highest level compression
+ bzipCFG := &bzip2.WriterConfig{Level: 9}
+ // Override our set defaults
+ if compressionLevel > 0 {
+ bzipCFG.Level = compressionLevel
+ }
+ bzipWriter, err := bzip2.NewWriter(output, bzipCFG)
+ if err != nil {
+ return nil, err
+ }
+ return bzipWriter, nil
+}
+
+func makeLZ4Writer(output io.WriteCloser, compressionLevel int) (io.WriteCloser, error) {
+ lzwriter := lz4.NewWriter(output)
+ if compressionLevel > 0 {
+ lzwriter.Header.CompressionLevel = compressionLevel
+ }
+ return lzwriter, nil
+}
+
+func makeXZWriter(output io.WriteCloser) (io.WriteCloser, error) {
+ xzwriter, err := xz.NewWriter(output)
+ if err != nil {
+ return nil, err
+ }
+ return xzwriter, nil
+}
+
+func makePgzipWriter(output io.WriteCloser, compressionLevel int) (io.WriteCloser, error) {
+ gzipWriter, err := pgzip.NewWriterLevel(output, compressionLevel)
+ if err != nil {
+ return nil, ErrInvalidCompressionLevel
+ }
+ gzipWriter.SetConcurrency(500000, runtime.GOMAXPROCS(-1))
+ return gzipWriter, nil
+}
+
+func createTarArchive(files []string, output io.WriteCloser) error {
+ archive := tar.NewWriter(output)
+ defer archive.Close()
+
+ for _, path := range files {
+ file, err := os.Open(path)
+ if err != nil {
+ return fmt.Errorf("Unable to read file %s: %s", path, err)
+ }
+ defer file.Close()
+
+ fi, err := file.Stat()
+ if err != nil {
+ return fmt.Errorf("Unable to get fileinfo for %s: %s", path, err)
+ }
+
+ header, err := tar.FileInfoHeader(fi, path)
+ if err != nil {
+ return fmt.Errorf("Failed to create tar header for %s: %s", path, err)
+ }
+
+ // workaround for archive format on go >=1.10
+ setHeaderFormat(header)
+
+ if err := archive.WriteHeader(header); err != nil {
+ return fmt.Errorf("Failed to write tar header for %s: %s", path, err)
+ }
+
+ if _, err := io.Copy(archive, file); err != nil {
+ return fmt.Errorf("Failed to copy %s data to archive: %s", path, err)
+ }
+ }
+ return nil
+}
+
+func createZipArchive(files []string, output io.WriteCloser) error {
+ archive := zip.NewWriter(output)
+ defer archive.Close()
+
+ for _, path := range files {
+ path = filepath.ToSlash(path)
+
+ source, err := os.Open(path)
+ if err != nil {
+ return fmt.Errorf("Unable to read file %s: %s", path, err)
+ }
+ defer source.Close()
+
+ target, err := archive.Create(path)
+ if err != nil {
+ return fmt.Errorf("Failed to add zip header for %s: %s", path, err)
+ }
+
+ _, err = io.Copy(target, source)
+ if err != nil {
+ return fmt.Errorf("Failed to copy %s data to archive: %s", path, err)
+ }
+ }
+ return nil
+}
diff --git a/v1.9.4/post-processor/compress/post-processor.hcl2spec.go b/v1.9.4/post-processor/compress/post-processor.hcl2spec.go
new file mode 100644
index 0000000..0052106
--- /dev/null
+++ b/v1.9.4/post-processor/compress/post-processor.hcl2spec.go
@@ -0,0 +1,55 @@
+// Code generated by "packer-sdc mapstructure-to-hcl2"; DO NOT EDIT.
+
+package compress
+
+import (
+ "github.com/hashicorp/hcl/v2/hcldec"
+ "github.com/zclconf/go-cty/cty"
+)
+
+// FlatConfig is an auto-generated flat version of Config.
+// Where the contents of a field with a `mapstructure:,squash` tag are bubbled up.
+type FlatConfig struct {
+ PackerBuildName *string `mapstructure:"packer_build_name" cty:"packer_build_name" 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"`
+ OutputPath *string `mapstructure:"output" cty:"output" hcl:"output"`
+ Format *string `mapstructure:"format" cty:"format" hcl:"format"`
+ CompressionLevel *int `mapstructure:"compression_level" cty:"compression_level" hcl:"compression_level"`
+ Archive *string `cty:"archive" hcl:"archive"`
+ Algorithm *string `cty:"algorithm" hcl:"algorithm"`
+}
+
+// FlatMapstructure returns a new FlatConfig.
+// FlatConfig is an auto-generated flat version of Config.
+// Where the contents a fields with a `mapstructure:,squash` tag are bubbled up.
+func (*Config) FlatMapstructure() interface{ HCL2Spec() map[string]hcldec.Spec } {
+ return new(FlatConfig)
+}
+
+// HCL2Spec returns the hcl spec of a Config.
+// This spec is used by HCL to read the fields of Config.
+// The decoded values from this spec will then be applied to a FlatConfig.
+func (*FlatConfig) HCL2Spec() map[string]hcldec.Spec {
+ s := map[string]hcldec.Spec{
+ "packer_build_name": &hcldec.AttrSpec{Name: "packer_build_name", Type: cty.String, Required: false},
+ "packer_builder_type": &hcldec.AttrSpec{Name: "packer_builder_type", Type: cty.String, Required: false},
+ "packer_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_sensitive_variables": &hcldec.AttrSpec{Name: "packer_sensitive_variables", Type: cty.List(cty.String), Required: false},
+ "output": &hcldec.AttrSpec{Name: "output", Type: cty.String, Required: false},
+ "format": &hcldec.AttrSpec{Name: "format", Type: cty.String, Required: false},
+ "compression_level": &hcldec.AttrSpec{Name: "compression_level", Type: cty.Number, Required: false},
+ "archive": &hcldec.AttrSpec{Name: "archive", Type: cty.String, Required: false},
+ "algorithm": &hcldec.AttrSpec{Name: "algorithm", Type: cty.String, Required: false},
+ }
+ return s
+}
diff --git a/v1.9.4/post-processor/compress/post-processor_test.go b/v1.9.4/post-processor/compress/post-processor_test.go
new file mode 100644
index 0000000..f91a117
--- /dev/null
+++ b/v1.9.4/post-processor/compress/post-processor_test.go
@@ -0,0 +1,291 @@
+// Copyright (c) HashiCorp, Inc.
+// SPDX-License-Identifier: MPL-2.0
+
+package compress
+
+import (
+ "archive/tar"
+ "archive/zip"
+ "compress/gzip"
+ "context"
+ "fmt"
+ "io/ioutil"
+ "os"
+ "strings"
+ "testing"
+
+ "github.com/dsnet/compress/bzip2"
+ packersdk "github.com/hashicorp/packer-plugin-sdk/packer"
+ "github.com/hashicorp/packer-plugin-sdk/template"
+ "github.com/hashicorp/packer/builder/file"
+ "github.com/pierrec/lz4"
+)
+
+func TestDetectFilename(t *testing.T) {
+ // Test default / fallback with no file extension
+ nakedFilename := Config{OutputPath: "test"}
+ nakedFilename.detectFromFilename()
+ if nakedFilename.Archive != "tar" {
+ t.Error("Expected to find tar archive setting")
+ }
+ if nakedFilename.Algorithm != "pgzip" {
+ t.Error("Expected to find pgzip algorithm setting")
+ }
+
+ // Test .archive
+ zipFilename := Config{OutputPath: "test.zip"}
+ zipFilename.detectFromFilename()
+ if zipFilename.Archive != "zip" {
+ t.Error("Expected to find zip archive setting")
+ }
+ if zipFilename.Algorithm != "" {
+ t.Error("Expected to find empty algorithm setting")
+ }
+
+ // Test .compress
+ lz4Filename := Config{OutputPath: "test.lz4"}
+ lz4Filename.detectFromFilename()
+ if lz4Filename.Archive != "" {
+ t.Error("Expected to find empty archive setting")
+ }
+ if lz4Filename.Algorithm != "lz4" {
+ t.Error("Expected to find lz4 algorithm setting")
+ }
+
+ // Test .archive.compress with some.extra.dots...
+ lotsOfDots := Config{OutputPath: "test.blah.bloo.blee.tar.lz4"}
+ lotsOfDots.detectFromFilename()
+ if lotsOfDots.Archive != "tar" {
+ t.Error("Expected to find tar archive setting")
+ }
+ if lotsOfDots.Algorithm != "lz4" {
+ t.Error("Expected to find lz4 algorithm setting")
+ }
+}
+
+const expectedFileContents = "Hello world!"
+
+func TestCompressOptions(t *testing.T) {
+ const config = `
+ {
+ "post-processors": [
+ {
+ "type": "compress",
+ "output": "package.gz",
+ "compression_level": 9
+ }
+ ]
+ }
+ `
+
+ artifact := testArchive(t, config)
+ defer artifact.Destroy()
+
+ filename := "package.gz"
+ archive, _ := os.Open(filename)
+ gzipReader, _ := gzip.NewReader(archive)
+ data, _ := ioutil.ReadAll(gzipReader)
+
+ if string(data) != expectedFileContents {
+ t.Errorf("Expected:\n%s\nFound:\n%s\n", expectedFileContents, data)
+ }
+}
+
+func TestCompressInterpolation(t *testing.T) {
+ const config = `
+ {
+ "post-processors": [
+ {
+ "type": "compress",
+ "output": "{{ build_name}}-{{ .BuildName }}-{{.BuilderType}}.gz"
+ }
+ ]
+ }
+ `
+
+ artifact := testArchive(t, config)
+ defer artifact.Destroy()
+
+ // You can interpolate using the .BuildName variable or build_name global
+ // function. We'll check both.
+ filename := "chocolate-vanilla-file.gz"
+ archive, err := os.Open(filename)
+ if err != nil {
+ t.Fatalf("Unable to read %s: %s", filename, err)
+ }
+
+ gzipReader, _ := gzip.NewReader(archive)
+ data, _ := ioutil.ReadAll(gzipReader)
+
+ if string(data) != expectedFileContents {
+ t.Errorf("Expected:\n%s\nFound:\n%s\n", expectedFileContents, data)
+ }
+}
+
+// Test Helpers
+
+func setup(t *testing.T) (packersdk.Ui, packersdk.Artifact, error) {
+ // Create fake UI and Cache
+ ui := packersdk.TestUi(t)
+
+ // Create config for file builder
+ const fileConfig = `{"builders":[{"type":"file","target":"package.txt","content":"Hello world!"}]}`
+ tpl, err := template.Parse(strings.NewReader(fileConfig))
+ if err != nil {
+ return nil, nil, fmt.Errorf("Unable to parse setup configuration: %s", err)
+ }
+
+ // Prepare the file builder
+ builder := file.Builder{}
+ _, warnings, err := builder.Prepare(tpl.Builders["file"].Config)
+ if len(warnings) > 0 {
+ for _, warn := range warnings {
+ return nil, nil, fmt.Errorf("Configuration warning: %s", warn)
+ }
+ }
+ if err != nil {
+ return nil, nil, fmt.Errorf("Invalid configuration: %s", err)
+ }
+
+ // Run the file builder
+ artifact, err := builder.Run(context.Background(), ui, nil)
+ if err != nil {
+ return nil, nil, fmt.Errorf("Failed to build artifact: %s", err)
+ }
+
+ return ui, artifact, err
+}
+
+func testArchive(t *testing.T, config string) packersdk.Artifact {
+ ui, artifact, err := setup(t)
+ if err != nil {
+ t.Fatalf("Error bootstrapping test: %s", err)
+ }
+ if artifact != nil {
+ defer artifact.Destroy()
+ }
+
+ tpl, err := template.Parse(strings.NewReader(config))
+ if err != nil {
+ t.Fatalf("Unable to parse test config: %s", err)
+ }
+
+ compressor := PostProcessor{}
+ compressor.Configure(tpl.PostProcessors[0][0].Config)
+
+ // I get the feeling these should be automatically available somewhere, but
+ // some of the post-processors construct this manually.
+ compressor.config.ctx.BuildName = "chocolate"
+ compressor.config.PackerBuildName = "vanilla"
+ compressor.config.PackerBuilderType = "file"
+
+ artifactOut, _, _, err := compressor.PostProcess(context.Background(), ui, artifact)
+ if err != nil {
+ t.Fatalf("Failed to compress artifact: %s", err)
+ }
+
+ return artifactOut
+}
+
+func TestArchive(t *testing.T) {
+ tc := map[string]func(*os.File) ([]byte, error){
+ "bzip2": func(archive *os.File) ([]byte, error) {
+ bzipReader, err := bzip2.NewReader(archive, nil)
+ if err != nil {
+ return nil, err
+ }
+ return ioutil.ReadAll(bzipReader)
+ },
+ "zip": func(archive *os.File) ([]byte, error) {
+ fi, _ := archive.Stat()
+ zipReader, err := zip.NewReader(archive, fi.Size())
+ if err != nil {
+ return nil, err
+ }
+ ctt, err := zipReader.File[0].Open()
+ if err != nil {
+ return nil, err
+ }
+ return ioutil.ReadAll(ctt)
+ },
+ "tar": func(archive *os.File) ([]byte, error) {
+ tarReader := tar.NewReader(archive)
+ _, err := tarReader.Next()
+ if err != nil {
+ return nil, err
+ }
+ return ioutil.ReadAll(tarReader)
+ },
+ "tar.gz": func(archive *os.File) ([]byte, error) {
+ gzipReader, err := gzip.NewReader(archive)
+ if err != nil {
+ return nil, err
+ }
+ tarReader := tar.NewReader(gzipReader)
+ _, err = tarReader.Next()
+ if err != nil {
+ return nil, err
+ }
+ return ioutil.ReadAll(tarReader)
+ },
+ "gz": func(archive *os.File) ([]byte, error) {
+ gzipReader, _ := gzip.NewReader(archive)
+ return ioutil.ReadAll(gzipReader)
+ },
+ "lz4": func(archive *os.File) ([]byte, error) {
+ lz4Reader := lz4.NewReader(archive)
+ return ioutil.ReadAll(lz4Reader)
+ },
+ }
+
+ tmpArchiveFile := "temp-archive-package"
+ for format, unzip := range tc {
+ t.Run(format, func(t *testing.T) {
+ config := fmt.Sprintf(`
+ {
+ "post-processors": [
+ {
+ "type": "compress",
+ "output": "%s.%s"
+ }
+ ]
+ }
+ `, tmpArchiveFile, format)
+
+ artifact := testArchive(t, config)
+ defer func() {
+ err := artifact.Destroy()
+ if err != nil {
+ t.Fatal(err)
+ }
+ }()
+
+ filename := fmt.Sprintf("%s.%s", tmpArchiveFile, format)
+ // Verify things look good
+ _, err := os.Stat(filename)
+ if err != nil {
+ t.Errorf("Unable to read archive: %s", err)
+ }
+
+ archive, err := os.Open(filename)
+ if err != nil {
+ t.Fatal(err)
+ }
+ defer func() {
+ err := archive.Close()
+ if err != nil {
+ t.Fatal(err)
+ }
+ }()
+
+ found, err := unzip(archive)
+ if err != nil {
+ t.Fatal(err)
+ }
+ if string(found) != expectedFileContents {
+ t.Errorf("Expected:\n%s\nFound:\n%s\n", expectedFileContents, string(found))
+ }
+ })
+ }
+
+}
diff --git a/v1.9.4/post-processor/compress/tar_fix.go b/v1.9.4/post-processor/compress/tar_fix.go
new file mode 100644
index 0000000..ad58cb1
--- /dev/null
+++ b/v1.9.4/post-processor/compress/tar_fix.go
@@ -0,0 +1,13 @@
+// Copyright (c) HashiCorp, Inc.
+// SPDX-License-Identifier: MPL-2.0
+
+//go:build !go1.10
+// +build !go1.10
+
+package compress
+
+import "archive/tar"
+
+func setHeaderFormat(header *tar.Header) {
+ // no-op
+}
diff --git a/v1.9.4/post-processor/compress/tar_fix_go110.go b/v1.9.4/post-processor/compress/tar_fix_go110.go
new file mode 100644
index 0000000..5eac3de
--- /dev/null
+++ b/v1.9.4/post-processor/compress/tar_fix_go110.go
@@ -0,0 +1,21 @@
+// Copyright (c) HashiCorp, Inc.
+// SPDX-License-Identifier: MPL-2.0
+
+//go:build go1.10
+// +build go1.10
+
+package compress
+
+import (
+ "archive/tar"
+ "time"
+)
+
+func setHeaderFormat(header *tar.Header) {
+ // We have to set the Format explicitly for the googlecompute-import
+ // post-processor. Google Cloud only allows importing GNU tar format.
+ header.Format = tar.FormatGNU
+ header.AccessTime = time.Time{}
+ header.ModTime = time.Time{}
+ header.ChangeTime = time.Time{}
+}
diff --git a/v1.9.4/post-processor/compress/version/version.go b/v1.9.4/post-processor/compress/version/version.go
new file mode 100644
index 0000000..639290a
--- /dev/null
+++ b/v1.9.4/post-processor/compress/version/version.go
@@ -0,0 +1,16 @@
+// Copyright (c) HashiCorp, Inc.
+// SPDX-License-Identifier: MPL-2.0
+
+package version
+
+import (
+ "github.com/hashicorp/packer-plugin-sdk/version"
+ packerVersion "github.com/hashicorp/packer/version"
+)
+
+var CompressPluginVersion *version.PluginVersion
+
+func init() {
+ CompressPluginVersion = version.InitializePluginVersion(
+ packerVersion.Version, packerVersion.VersionPrerelease)
+}
diff --git a/v1.9.4/post-processor/manifest/artifact.go b/v1.9.4/post-processor/manifest/artifact.go
new file mode 100644
index 0000000..b70c7de
--- /dev/null
+++ b/v1.9.4/post-processor/manifest/artifact.go
@@ -0,0 +1,51 @@
+// Copyright (c) HashiCorp, Inc.
+// SPDX-License-Identifier: MPL-2.0
+
+package manifest
+
+import "fmt"
+
+const BuilderId = "packer.post-processor.manifest"
+
+type ArtifactFile struct {
+ Name string `json:"name"`
+ Size int64 `json:"size"`
+}
+
+type Artifact struct {
+ BuildName string `json:"name"`
+ BuilderType string `json:"builder_type"`
+ BuildTime int64 `json:"build_time,omitempty"`
+ ArtifactFiles []ArtifactFile `json:"files"`
+ ArtifactId string `json:"artifact_id"`
+ PackerRunUUID string `json:"packer_run_uuid"`
+ CustomData map[string]string `json:"custom_data"`
+}
+
+func (a *Artifact) BuilderId() string {
+ return BuilderId
+}
+
+func (a *Artifact) Files() []string {
+ var files []string
+ for _, af := range a.ArtifactFiles {
+ files = append(files, af.Name)
+ }
+ return files
+}
+
+func (a *Artifact) Id() string {
+ return a.ArtifactId
+}
+
+func (a *Artifact) String() string {
+ return fmt.Sprintf("%s-%s", a.BuildName, a.ArtifactId)
+}
+
+func (a *Artifact) State(name string) interface{} {
+ return nil
+}
+
+func (a *Artifact) Destroy() error {
+ return nil
+}
diff --git a/v1.9.4/post-processor/manifest/post-processor.go b/v1.9.4/post-processor/manifest/post-processor.go
new file mode 100644
index 0000000..f911f73
--- /dev/null
+++ b/v1.9.4/post-processor/manifest/post-processor.go
@@ -0,0 +1,188 @@
+// Copyright (c) HashiCorp, Inc.
+// SPDX-License-Identifier: MPL-2.0
+
+//go:generate packer-sdc mapstructure-to-hcl2 -type Config
+//go:generate packer-sdc struct-markdown
+
+package manifest
+
+import (
+ "context"
+ "encoding/json"
+ "fmt"
+ "io/ioutil"
+ "log"
+ "os"
+ "path/filepath"
+ "time"
+
+ "github.com/hashicorp/hcl/v2/hcldec"
+ "github.com/hashicorp/packer-plugin-sdk/common"
+ packersdk "github.com/hashicorp/packer-plugin-sdk/packer"
+ "github.com/hashicorp/packer-plugin-sdk/template/config"
+ "github.com/hashicorp/packer-plugin-sdk/template/interpolate"
+)
+
+type Config struct {
+ common.PackerConfig `mapstructure:",squash"`
+
+ // The manifest will be written to this file. This defaults to
+ // `packer-manifest.json`.
+ OutputPath string `mapstructure:"output"`
+ // Write only filename without the path to the manifest file. This defaults
+ // to false.
+ StripPath bool `mapstructure:"strip_path"`
+ // Don't write the `build_time` field from the output.
+ StripTime bool `mapstructure:"strip_time"`
+ // Arbitrary data to add to the manifest. This is a [template
+ // engine](/packer/docs/templates/legacy_json_templates/engine). Therefore, you
+ // may use user variables and template functions in this field.
+ CustomData map[string]string `mapstructure:"custom_data"`
+ ctx interpolate.Context
+}
+
+type PostProcessor struct {
+ config Config
+}
+
+type ManifestFile struct {
+ Builds []Artifact `json:"builds"`
+ LastRunUUID string `json:"last_run_uuid"`
+}
+
+func (p *PostProcessor) ConfigSpec() hcldec.ObjectSpec { return p.config.FlatMapstructure().HCL2Spec() }
+
+func (p *PostProcessor) Configure(raws ...interface{}) error {
+ err := config.Decode(&p.config, &config.DecodeOpts{
+ PluginType: "packer.post-processor.manifest",
+ Interpolate: true,
+ InterpolateContext: &p.config.ctx,
+ InterpolateFilter: &interpolate.RenderFilter{
+ Exclude: []string{},
+ },
+ }, raws...)
+ if err != nil {
+ return err
+ }
+
+ if p.config.OutputPath == "" {
+ p.config.OutputPath = "packer-manifest.json"
+ }
+
+ if err = interpolate.Validate(p.config.OutputPath, &p.config.ctx); err != nil {
+ return fmt.Errorf("Error parsing target template: %s", err)
+ }
+
+ return nil
+}
+
+func (p *PostProcessor) PostProcess(ctx context.Context, ui packersdk.Ui, source packersdk.Artifact) (packersdk.Artifact, bool, bool, error) {
+ generatedData := source.State("generated_data")
+ if generatedData == nil {
+ // Make sure it's not a nil map so we can assign to it later.
+ generatedData = make(map[string]interface{})
+ }
+ p.config.ctx.Data = generatedData
+
+ for key, data := range p.config.CustomData {
+ interpolatedData, err := createInterpolatedCustomData(&p.config, data)
+ if err != nil {
+ return nil, false, false, err
+ }
+ p.config.CustomData[key] = interpolatedData
+ }
+
+ artifact := &Artifact{}
+
+ var err error
+ var fi os.FileInfo
+
+ // Create the current artifact.
+ for _, name := range source.Files() {
+ af := ArtifactFile{}
+ if fi, err = os.Stat(name); err == nil {
+ af.Size = fi.Size()
+ }
+ if p.config.StripPath {
+ af.Name = filepath.Base(name)
+ } else {
+ af.Name = name
+ }
+ artifact.ArtifactFiles = append(artifact.ArtifactFiles, af)
+ }
+ artifact.ArtifactId = source.Id()
+ artifact.CustomData = p.config.CustomData
+ artifact.BuilderType = p.config.PackerBuilderType
+ artifact.BuildName = p.config.PackerBuildName
+ artifact.BuildTime = time.Now().Unix()
+ if p.config.StripTime {
+ artifact.BuildTime = 0
+ }
+ // Since each post-processor runs in a different process we need a way to
+ // coordinate between various post-processors in a single packer run. We do
+ // this by setting a UUID per run and tracking this in the manifest file.
+ // When we detect that the UUID in the file is the same, we know that we are
+ // part of the same run and we simply add our data to the list. If the UUID
+ // is different we will check the -force flag and decide whether to truncate
+ // the file before we proceed.
+ artifact.PackerRunUUID = os.Getenv("PACKER_RUN_UUID")
+
+ // Create a lock file with exclusive access. If this fails we will retry
+ // after a delay.
+ lockFilename := p.config.OutputPath + ".lock"
+ for i := 0; i < 3; i++ {
+ // The file should not be locked for very long so we'll keep this short.
+ time.Sleep((time.Duration(i) * 200 * time.Millisecond))
+ _, err = os.OpenFile(lockFilename, os.O_RDWR|os.O_CREATE|os.O_EXCL, 0600)
+ if err == nil {
+ break
+ }
+ log.Printf("Error locking manifest file for reading and writing. Will sleep and retry. %s", err)
+ }
+ defer os.Remove(lockFilename)
+
+ // Read the current manifest file from disk
+ contents := []byte{}
+ if contents, err = ioutil.ReadFile(p.config.OutputPath); err != nil && !os.IsNotExist(err) {
+ return source, true, true, fmt.Errorf("Unable to open %s for reading: %s", p.config.OutputPath, err)
+ }
+
+ // Parse the manifest file JSON, if we have one
+ manifestFile := &ManifestFile{}
+ if len(contents) > 0 {
+ if err = json.Unmarshal(contents, manifestFile); err != nil {
+ return source, true, true, fmt.Errorf("Unable to parse content from %s: %s", p.config.OutputPath, err)
+ }
+ }
+
+ // If -force is set and we are not on same run, truncate the file. Otherwise
+ // we will continue to add new builds to the existing manifest file.
+ if p.config.PackerForce && os.Getenv("PACKER_RUN_UUID") != manifestFile.LastRunUUID {
+ manifestFile = &ManifestFile{}
+ }
+
+ // Add the current artifact to the manifest file
+ manifestFile.Builds = append(manifestFile.Builds, *artifact)
+ manifestFile.LastRunUUID = os.Getenv("PACKER_RUN_UUID")
+
+ // Write JSON to disk
+ if out, err := json.MarshalIndent(manifestFile, "", " "); err == nil {
+ if err = ioutil.WriteFile(p.config.OutputPath, out, 0664); err != nil {
+ return source, true, true, fmt.Errorf("Unable to write %s: %s", p.config.OutputPath, err)
+ }
+ } else {
+ return source, true, true, fmt.Errorf("Unable to marshal JSON %s", err)
+ }
+
+ // The manifest should never delete the artifacts it is set to record, so it
+ // forcibly sets "keep" to true.
+ return source, true, true, nil
+}
+
+func createInterpolatedCustomData(config *Config, customData string) (string, error) {
+ interpolatedCmd, err := interpolate.Render(customData, &config.ctx)
+ if err != nil {
+ return "", fmt.Errorf("Error interpolating custom data: %s", err)
+ }
+ return interpolatedCmd, nil
+}
diff --git a/v1.9.4/post-processor/manifest/post-processor.hcl2spec.go b/v1.9.4/post-processor/manifest/post-processor.hcl2spec.go
new file mode 100644
index 0000000..86fb26a
--- /dev/null
+++ b/v1.9.4/post-processor/manifest/post-processor.hcl2spec.go
@@ -0,0 +1,53 @@
+// Code generated by "packer-sdc mapstructure-to-hcl2"; DO NOT EDIT.
+
+package manifest
+
+import (
+ "github.com/hashicorp/hcl/v2/hcldec"
+ "github.com/zclconf/go-cty/cty"
+)
+
+// FlatConfig is an auto-generated flat version of Config.
+// Where the contents of a field with a `mapstructure:,squash` tag are bubbled up.
+type FlatConfig struct {
+ PackerBuildName *string `mapstructure:"packer_build_name" cty:"packer_build_name" 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"`
+ OutputPath *string `mapstructure:"output" cty:"output" hcl:"output"`
+ StripPath *bool `mapstructure:"strip_path" cty:"strip_path" hcl:"strip_path"`
+ StripTime *bool `mapstructure:"strip_time" cty:"strip_time" hcl:"strip_time"`
+ CustomData map[string]string `mapstructure:"custom_data" cty:"custom_data" hcl:"custom_data"`
+}
+
+// FlatMapstructure returns a new FlatConfig.
+// FlatConfig is an auto-generated flat version of Config.
+// Where the contents a fields with a `mapstructure:,squash` tag are bubbled up.
+func (*Config) FlatMapstructure() interface{ HCL2Spec() map[string]hcldec.Spec } {
+ return new(FlatConfig)
+}
+
+// HCL2Spec returns the hcl spec of a Config.
+// This spec is used by HCL to read the fields of Config.
+// The decoded values from this spec will then be applied to a FlatConfig.
+func (*FlatConfig) HCL2Spec() map[string]hcldec.Spec {
+ s := map[string]hcldec.Spec{
+ "packer_build_name": &hcldec.AttrSpec{Name: "packer_build_name", Type: cty.String, Required: false},
+ "packer_builder_type": &hcldec.AttrSpec{Name: "packer_builder_type", Type: cty.String, Required: false},
+ "packer_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_sensitive_variables": &hcldec.AttrSpec{Name: "packer_sensitive_variables", Type: cty.List(cty.String), Required: false},
+ "output": &hcldec.AttrSpec{Name: "output", Type: cty.String, Required: false},
+ "strip_path": &hcldec.AttrSpec{Name: "strip_path", Type: cty.Bool, Required: false},
+ "strip_time": &hcldec.AttrSpec{Name: "strip_time", Type: cty.Bool, Required: false},
+ "custom_data": &hcldec.AttrSpec{Name: "custom_data", Type: cty.Map(cty.String), Required: false},
+ }
+ return s
+}
diff --git a/v1.9.4/post-processor/manifest/version/version.go b/v1.9.4/post-processor/manifest/version/version.go
new file mode 100644
index 0000000..20a5523
--- /dev/null
+++ b/v1.9.4/post-processor/manifest/version/version.go
@@ -0,0 +1,16 @@
+// Copyright (c) HashiCorp, Inc.
+// SPDX-License-Identifier: MPL-2.0
+
+package version
+
+import (
+ "github.com/hashicorp/packer-plugin-sdk/version"
+ packerVersion "github.com/hashicorp/packer/version"
+)
+
+var ManifestPluginVersion *version.PluginVersion
+
+func init() {
+ ManifestPluginVersion = version.InitializePluginVersion(
+ packerVersion.Version, packerVersion.VersionPrerelease)
+}
diff --git a/v1.9.4/post-processor/shell-local/post-processor.go b/v1.9.4/post-processor/shell-local/post-processor.go
new file mode 100644
index 0000000..334081e
--- /dev/null
+++ b/v1.9.4/post-processor/shell-local/post-processor.go
@@ -0,0 +1,65 @@
+// Copyright (c) HashiCorp, Inc.
+// SPDX-License-Identifier: MPL-2.0
+
+package shell_local
+
+import (
+ "context"
+
+ "github.com/hashicorp/hcl/v2/hcldec"
+ packersdk "github.com/hashicorp/packer-plugin-sdk/packer"
+ sl "github.com/hashicorp/packer-plugin-sdk/shell-local"
+)
+
+type PostProcessor struct {
+ config sl.Config
+}
+
+type ExecuteCommandTemplate struct {
+ Vars string
+ Script string
+}
+
+func (p *PostProcessor) ConfigSpec() hcldec.ObjectSpec { return p.config.FlatMapstructure().HCL2Spec() }
+
+func (p *PostProcessor) Configure(raws ...interface{}) error {
+ err := sl.Decode(&p.config, raws...)
+ if err != nil {
+ return err
+ }
+ if len(p.config.ExecuteCommand) == 1 {
+ // Backwards compatibility -- before we merged the shell-local
+ // post-processor and provisioners, the post-processor accepted
+ // execute_command as a string rather than a slice of strings. It didn't
+ // have a configurable call to shell program, automatically prepending
+ // the user-supplied execute_command string with "sh -c". If users are
+ // still using the old way of defining ExecuteCommand (by supplying a
+ // single string rather than a slice of strings) then we need to
+ // prepend this command with the call that the post-processor defaulted
+ // to before.
+ p.config.ExecuteCommand = append([]string{"sh", "-c"}, p.config.ExecuteCommand...)
+ }
+
+ return sl.Validate(&p.config)
+}
+
+func (p *PostProcessor) PostProcess(ctx context.Context, ui packersdk.Ui, artifact packersdk.Artifact) (packersdk.Artifact, bool, bool, error) {
+ generatedData := make(map[string]interface{})
+ artifactStateData := artifact.State("generated_data")
+ if artifactStateData != nil {
+ for k, v := range artifactStateData.(map[interface{}]interface{}) {
+ generatedData[k.(string)] = v
+ }
+ }
+
+ success, retErr := sl.Run(ctx, ui, &p.config, generatedData)
+ if !success {
+ return nil, false, false, retErr
+ }
+
+ // Force shell-local pp to keep the input artifact, because otherwise we'll
+ // lose it instead of being able to pass it through. If you want to delete
+ // the input artifact for a shell local pp, use the artifice pp to create a
+ // new artifact
+ return artifact, true, true, retErr
+}
diff --git a/v1.9.4/post-processor/shell-local/post-processor_test.go b/v1.9.4/post-processor/shell-local/post-processor_test.go
new file mode 100644
index 0000000..eb84817
--- /dev/null
+++ b/v1.9.4/post-processor/shell-local/post-processor_test.go
@@ -0,0 +1,268 @@
+// Copyright (c) HashiCorp, Inc.
+// SPDX-License-Identifier: MPL-2.0
+
+package shell_local
+
+import (
+ "io/ioutil"
+ "os"
+ "runtime"
+ "testing"
+
+ packersdk "github.com/hashicorp/packer-plugin-sdk/packer"
+ "github.com/stretchr/testify/assert"
+)
+
+func TestPostProcessor_ImplementsPostProcessor(t *testing.T) {
+ var _ packersdk.PostProcessor = new(PostProcessor)
+}
+
+func testConfig() map[string]interface{} {
+ return map[string]interface{}{
+ "inline": []interface{}{"foo", "bar"},
+ }
+}
+
+func TestPostProcessor_Impl(t *testing.T) {
+ var raw interface{}
+ raw = &PostProcessor{}
+ if _, ok := raw.(packersdk.PostProcessor); !ok {
+ t.Fatalf("must be a post processor")
+ }
+}
+
+func TestPostProcessorPrepare_Defaults(t *testing.T) {
+ var p PostProcessor
+ raws := testConfig()
+
+ err := p.Configure(raws)
+ if err != nil {
+ t.Fatalf("err: %s", err)
+ }
+}
+
+func TestPostProcessorPrepare_InlineShebang(t *testing.T) {
+ raws := testConfig()
+
+ delete(raws, "inline_shebang")
+ p := new(PostProcessor)
+ err := p.Configure(raws)
+ if err != nil {
+ t.Fatalf("should not have error: %s", err)
+ }
+ expected := ""
+ if runtime.GOOS != "windows" {
+ expected = "/bin/sh -e"
+ }
+ if p.config.InlineShebang != expected {
+ t.Fatalf("bad value: %s", p.config.InlineShebang)
+ }
+
+ // Test with a good one
+ raws["inline_shebang"] = "foo"
+ p = new(PostProcessor)
+ err = p.Configure(raws)
+ if err != nil {
+ t.Fatalf("should not have error: %s", err)
+ }
+
+ if p.config.InlineShebang != "foo" {
+ t.Fatalf("bad value: %s", p.config.InlineShebang)
+ }
+}
+
+func TestPostProcessorPrepare_InvalidKey(t *testing.T) {
+ var p PostProcessor
+ raws := testConfig()
+
+ // Add a random key
+ raws["i_should_not_be_valid"] = true
+ err := p.Configure(raws)
+ if err == nil {
+ t.Fatal("should have error")
+ }
+}
+
+func TestPostProcessorPrepare_Script(t *testing.T) {
+ raws := testConfig()
+ delete(raws, "inline")
+
+ raws["script"] = "/this/should/not/exist"
+ p := new(PostProcessor)
+ err := p.Configure(raws)
+ if err == nil {
+ t.Fatal("should have error")
+ }
+
+ // Test with a good one
+ tf, err := ioutil.TempFile("", "packer")
+ if err != nil {
+ t.Fatalf("error tempfile: %s", err)
+ }
+ defer os.Remove(tf.Name())
+
+ raws["script"] = tf.Name()
+ p = new(PostProcessor)
+ err = p.Configure(raws)
+ if err != nil {
+ t.Fatalf("should not have error: %s", err)
+ }
+}
+
+func TestPostProcessorPrepare_ExecuteCommand(t *testing.T) {
+ // Check that passing a string will work (Backwards Compatibility)
+ p := new(PostProcessor)
+ raws := testConfig()
+ raws["execute_command"] = "foo bar"
+ err := p.Configure(raws)
+ expected := []string{"sh", "-c", "foo bar"}
+ if err != nil {
+ t.Fatalf("should handle backwards compatibility: %s", err)
+ }
+ assert.Equal(t, p.config.ExecuteCommand, expected,
+ "Did not get expected execute_command: expected: %#v; received %#v", expected, p.config.ExecuteCommand)
+
+ // Check that passing a list will work
+ p = new(PostProcessor)
+ raws = testConfig()
+ raws["execute_command"] = []string{"foo", "bar"}
+ err = p.Configure(raws)
+ if err != nil {
+ t.Fatalf("should handle backwards compatibility: %s", err)
+ }
+ expected = []string{"foo", "bar"}
+ assert.Equal(t, p.config.ExecuteCommand, expected,
+ "Did not get expected execute_command: expected: %#v; received %#v", expected, p.config.ExecuteCommand)
+
+ // Check that default is as expected
+ raws = testConfig()
+ delete(raws, "execute_command")
+ p = new(PostProcessor)
+ p.Configure(raws)
+ if runtime.GOOS != "windows" {
+ expected = []string{"/bin/sh", "-c", "{{.Vars}} {{.Script}}"}
+ } else {
+ expected = []string{"cmd", "/V", "/C", "{{.Vars}}", "call", "{{.Script}}"}
+ }
+ assert.Equal(t, p.config.ExecuteCommand, expected,
+ "Did not get expected default: expected: %#v; received %#v", expected, p.config.ExecuteCommand)
+}
+
+func TestPostProcessorPrepare_ScriptAndInline(t *testing.T) {
+ var p PostProcessor
+ raws := testConfig()
+
+ // Error if no scripts/inline commands provided
+ delete(raws, "inline")
+ delete(raws, "script")
+ delete(raws, "command")
+ delete(raws, "scripts")
+ err := p.Configure(raws)
+ if err == nil {
+ t.Fatalf("should error when no scripts/inline commands are provided")
+ }
+
+ // Test with both
+ tf, err := ioutil.TempFile("", "packer")
+ if err != nil {
+ t.Fatalf("error tempfile: %s", err)
+ }
+ defer os.Remove(tf.Name())
+
+ raws["inline"] = []interface{}{"foo"}
+ raws["script"] = tf.Name()
+ err = p.Configure(raws)
+ if err == nil {
+ t.Fatal("should have error")
+ }
+}
+
+func TestPostProcessorPrepare_ScriptAndScripts(t *testing.T) {
+ var p PostProcessor
+ raws := testConfig()
+
+ // Test with both
+ tf, err := ioutil.TempFile("", "packer")
+ if err != nil {
+ t.Fatalf("error tempfile: %s", err)
+ }
+ defer os.Remove(tf.Name())
+
+ raws["inline"] = []interface{}{"foo"}
+ raws["scripts"] = []string{tf.Name()}
+ err = p.Configure(raws)
+ if err == nil {
+ t.Fatal("should have error")
+ }
+}
+
+func TestPostProcessorPrepare_Scripts(t *testing.T) {
+ raws := testConfig()
+ delete(raws, "inline")
+
+ raws["scripts"] = []string{}
+ p := new(PostProcessor)
+ err := p.Configure(raws)
+ if err == nil {
+ t.Fatal("should have error")
+ }
+
+ // Test with a good one
+ tf, err := ioutil.TempFile("", "packer")
+ if err != nil {
+ t.Fatalf("error tempfile: %s", err)
+ }
+ defer os.Remove(tf.Name())
+
+ raws["scripts"] = []string{tf.Name()}
+ p = new(PostProcessor)
+ err = p.Configure(raws)
+ if err != nil {
+ t.Fatalf("should not have error: %s", err)
+ }
+}
+
+func TestPostProcessorPrepare_EnvironmentVars(t *testing.T) {
+ raws := testConfig()
+
+ // Test with a bad case
+ raws["environment_vars"] = []string{"badvar", "good=var"}
+ p := new(PostProcessor)
+ err := p.Configure(raws)
+ if err == nil {
+ t.Fatal("should have error")
+ }
+
+ // Test with a trickier case
+ raws["environment_vars"] = []string{"=bad"}
+ p = new(PostProcessor)
+ err = p.Configure(raws)
+ if err == nil {
+ t.Fatal("should have error")
+ }
+
+ // Test with a good case
+ // Note: baz= is a real env variable, just empty
+ raws["environment_vars"] = []string{"FOO=bar", "baz="}
+ p = new(PostProcessor)
+ err = p.Configure(raws)
+ if err != nil {
+ t.Fatalf("should not have error: %s", err)
+ }
+
+ // Test when the env variable value contains an equals sign
+ raws["environment_vars"] = []string{"good=withequals=true"}
+ p = new(PostProcessor)
+ err = p.Configure(raws)
+ if err != nil {
+ t.Fatalf("should not have error: %s", err)
+ }
+
+ // Test when the env variable value starts with an equals sign
+ raws["environment_vars"] = []string{"good==true"}
+ p = new(PostProcessor)
+ err = p.Configure(raws)
+ if err != nil {
+ t.Fatalf("should not have error: %s", err)
+ }
+}
diff --git a/v1.9.4/post-processor/shell-local/version/version.go b/v1.9.4/post-processor/shell-local/version/version.go
new file mode 100644
index 0000000..1d02737
--- /dev/null
+++ b/v1.9.4/post-processor/shell-local/version/version.go
@@ -0,0 +1,16 @@
+// Copyright (c) HashiCorp, Inc.
+// SPDX-License-Identifier: MPL-2.0
+
+package version
+
+import (
+ "github.com/hashicorp/packer-plugin-sdk/version"
+ packerVersion "github.com/hashicorp/packer/version"
+)
+
+var ShellLocalPluginVersion *version.PluginVersion
+
+func init() {
+ ShellLocalPluginVersion = version.InitializePluginVersion(
+ packerVersion.Version, packerVersion.VersionPrerelease)
+}
diff --git a/v1.9.4/provisioner/breakpoint/provisioner.go b/v1.9.4/provisioner/breakpoint/provisioner.go
new file mode 100644
index 0000000..fc833fb
--- /dev/null
+++ b/v1.9.4/provisioner/breakpoint/provisioner.go
@@ -0,0 +1,89 @@
+// Copyright (c) HashiCorp, Inc.
+// SPDX-License-Identifier: MPL-2.0
+
+//go:generate packer-sdc mapstructure-to-hcl2 -type Config
+
+package breakpoint
+
+import (
+ "context"
+ "fmt"
+
+ "golang.org/x/sync/errgroup"
+
+ "github.com/hashicorp/hcl/v2/hcldec"
+ "github.com/hashicorp/packer-plugin-sdk/common"
+ packersdk "github.com/hashicorp/packer-plugin-sdk/packer"
+ "github.com/hashicorp/packer-plugin-sdk/template/config"
+ "github.com/hashicorp/packer-plugin-sdk/template/interpolate"
+)
+
+type Config struct {
+ common.PackerConfig `mapstructure:",squash"`
+
+ Note string `mapstructure:"note"`
+ Disable bool `mapstructure:"disable"`
+
+ ctx interpolate.Context
+}
+
+type Provisioner struct {
+ config Config
+}
+
+func (p *Provisioner) ConfigSpec() hcldec.ObjectSpec { return p.config.FlatMapstructure().HCL2Spec() }
+
+func (p *Provisioner) Prepare(raws ...interface{}) error {
+ err := config.Decode(&p.config, &config.DecodeOpts{
+ PluginType: "breakpoint",
+ Interpolate: true,
+ InterpolateContext: &p.config.ctx,
+ InterpolateFilter: &interpolate.RenderFilter{
+ Exclude: []string{},
+ },
+ }, raws...)
+ if err != nil {
+ return err
+ }
+
+ return nil
+}
+
+func (p *Provisioner) Provision(ctx context.Context, ui packersdk.Ui, comm packersdk.Communicator, _ map[string]interface{}) error {
+ if p.config.Disable {
+ if p.config.Note != "" {
+ ui.Say(fmt.Sprintf(
+ "Breakpoint provisioner with note \"%s\" disabled; continuing...",
+ p.config.Note))
+ } else {
+ ui.Say("Breakpoint provisioner disabled; continuing...")
+ }
+
+ return nil
+ }
+ if p.config.Note != "" {
+ ui.Say(fmt.Sprintf("Pausing at breakpoint provisioner with note \"%s\".", p.config.Note))
+ } else {
+ ui.Say("Pausing at breakpoint provisioner.")
+ }
+
+ message := fmt.Sprintf(
+ "Press enter to continue.")
+
+ var g errgroup.Group
+ result := make(chan string, 1)
+ g.Go(func() error {
+ line, err := ui.Ask(message)
+ if err != nil {
+ return fmt.Errorf("Error asking for input: %s", err)
+ }
+
+ result <- line
+ return nil
+ })
+
+ if err := g.Wait(); err != nil {
+ return err
+ }
+ return nil
+}
diff --git a/v1.9.4/provisioner/breakpoint/provisioner.hcl2spec.go b/v1.9.4/provisioner/breakpoint/provisioner.hcl2spec.go
new file mode 100644
index 0000000..6f6806c
--- /dev/null
+++ b/v1.9.4/provisioner/breakpoint/provisioner.hcl2spec.go
@@ -0,0 +1,49 @@
+// Code generated by "packer-sdc mapstructure-to-hcl2"; DO NOT EDIT.
+
+package breakpoint
+
+import (
+ "github.com/hashicorp/hcl/v2/hcldec"
+ "github.com/zclconf/go-cty/cty"
+)
+
+// FlatConfig is an auto-generated flat version of Config.
+// Where the contents of a field with a `mapstructure:,squash` tag are bubbled up.
+type FlatConfig struct {
+ PackerBuildName *string `mapstructure:"packer_build_name" cty:"packer_build_name" 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"`
+ Note *string `mapstructure:"note" cty:"note" hcl:"note"`
+ Disable *bool `mapstructure:"disable" cty:"disable" hcl:"disable"`
+}
+
+// FlatMapstructure returns a new FlatConfig.
+// FlatConfig is an auto-generated flat version of Config.
+// Where the contents a fields with a `mapstructure:,squash` tag are bubbled up.
+func (*Config) FlatMapstructure() interface{ HCL2Spec() map[string]hcldec.Spec } {
+ return new(FlatConfig)
+}
+
+// HCL2Spec returns the hcl spec of a Config.
+// This spec is used by HCL to read the fields of Config.
+// The decoded values from this spec will then be applied to a FlatConfig.
+func (*FlatConfig) HCL2Spec() map[string]hcldec.Spec {
+ s := map[string]hcldec.Spec{
+ "packer_build_name": &hcldec.AttrSpec{Name: "packer_build_name", Type: cty.String, Required: false},
+ "packer_builder_type": &hcldec.AttrSpec{Name: "packer_builder_type", Type: cty.String, Required: false},
+ "packer_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_sensitive_variables": &hcldec.AttrSpec{Name: "packer_sensitive_variables", Type: cty.List(cty.String), Required: false},
+ "note": &hcldec.AttrSpec{Name: "note", Type: cty.String, Required: false},
+ "disable": &hcldec.AttrSpec{Name: "disable", Type: cty.Bool, Required: false},
+ }
+ return s
+}
diff --git a/v1.9.4/provisioner/breakpoint/version/version.go b/v1.9.4/provisioner/breakpoint/version/version.go
new file mode 100644
index 0000000..008af95
--- /dev/null
+++ b/v1.9.4/provisioner/breakpoint/version/version.go
@@ -0,0 +1,16 @@
+// Copyright (c) HashiCorp, Inc.
+// SPDX-License-Identifier: MPL-2.0
+
+package version
+
+import (
+ "github.com/hashicorp/packer-plugin-sdk/version"
+ packerVersion "github.com/hashicorp/packer/version"
+)
+
+var BreakpointPluginVersion *version.PluginVersion
+
+func init() {
+ BreakpointPluginVersion = version.InitializePluginVersion(
+ packerVersion.Version, packerVersion.VersionPrerelease)
+}
diff --git a/v1.9.4/provisioner/file/provisioner.go b/v1.9.4/provisioner/file/provisioner.go
new file mode 100644
index 0000000..84e9c37
--- /dev/null
+++ b/v1.9.4/provisioner/file/provisioner.go
@@ -0,0 +1,269 @@
+// Copyright (c) HashiCorp, Inc.
+// SPDX-License-Identifier: MPL-2.0
+
+//go:generate packer-sdc mapstructure-to-hcl2 -type Config
+//go:generate packer-sdc struct-markdown
+
+package file
+
+import (
+ "context"
+ "errors"
+ "fmt"
+ "io"
+ "os"
+ "path/filepath"
+ "strings"
+
+ "github.com/hashicorp/hcl/v2/hcldec"
+ "github.com/hashicorp/packer-plugin-sdk/common"
+ 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-plugin-sdk/tmp"
+)
+
+type Config struct {
+ common.PackerConfig `mapstructure:",squash"`
+ // This is the content to copy to `destination`. If destination is a file,
+ // content will be written to that file, in case of a directory a file named
+ // `pkr-file-content` is created. It's recommended to use a file as the
+ // destination. The `templatefile` function might be used here, or any
+ // interpolation syntax. This attribute cannot be specified with source or
+ // sources.
+ Content string `mapstructure:"content" required:"true"`
+ // The path to a local file or directory to upload to the
+ // machine. The path can be absolute or relative. If it is relative, it is
+ // relative to the working directory when Packer is executed. If this is a
+ // directory, the existence of a trailing slash is important. Read below on
+ // uploading directories. Mandatory unless `sources` is set.
+ Source string `mapstructure:"source" required:"true"`
+ // A list of sources to upload. This can be used in place of the `source`
+ // option if you have several files that you want to upload to the same
+ // place. Note that the destination must be a directory with a trailing
+ // slash, and that all files listed in `sources` will be uploaded to the
+ // same directory with their file names preserved.
+ Sources []string `mapstructure:"sources" required:"false"`
+ // The path where the file will be uploaded to in the machine. This value
+ // must be a writable location and any parent directories
+ // must already exist. If the provisioning user (generally not root) cannot
+ // write to this directory, you will receive a "Permission Denied" error.
+ // If the source is a file, it's a good idea to make the destination a file
+ // as well, but if you set your destination as a directory, at least make
+ // sure that the destination ends in a trailing slash so that Packer knows
+ // to use the source's basename in the final upload path. Failure to do so
+ // may cause Packer to fail on file uploads. If the destination file
+ // already exists, it will be overwritten.
+ Destination string `mapstructure:"destination" required:"true"`
+ // The direction of the file transfer. This defaults to "upload". If it is
+ // set to "download" then the file "source" in the machine will be
+ // downloaded locally to "destination"
+ Direction string `mapstructure:"direction" required:"false"`
+ // For advanced users only. If true, check the file existence only before
+ // uploading, rather than upon pre-build validation. This allows users to
+ // upload files created on-the-fly. This defaults to false. We
+ // don't recommend using this feature, since it can cause Packer to become
+ // dependent on system state. We would prefer you generate your files before
+ // the Packer run, but realize that there are situations where this may be
+ // unavoidable.
+ Generated bool `mapstructure:"generated" required:"false"`
+
+ ctx interpolate.Context
+}
+
+type Provisioner struct {
+ config Config
+}
+
+func (p *Provisioner) ConfigSpec() hcldec.ObjectSpec { return p.config.FlatMapstructure().HCL2Spec() }
+
+func (p *Provisioner) Prepare(raws ...interface{}) error {
+ err := config.Decode(&p.config, &config.DecodeOpts{
+ PluginType: "file",
+ Interpolate: true,
+ InterpolateContext: &p.config.ctx,
+ InterpolateFilter: &interpolate.RenderFilter{
+ Exclude: []string{},
+ },
+ }, raws...)
+ if err != nil {
+ return err
+ }
+
+ if p.config.Direction == "" {
+ p.config.Direction = "upload"
+ }
+
+ var errs *packersdk.MultiError
+
+ if p.config.Direction != "download" && p.config.Direction != "upload" {
+ errs = packersdk.MultiErrorAppend(errs,
+ errors.New("Direction must be one of: download, upload."))
+ }
+ if p.config.Source != "" {
+ p.config.Sources = append(p.config.Sources, p.config.Source)
+ }
+
+ if p.config.Direction == "upload" {
+ for _, src := range p.config.Sources {
+ if _, err := os.Stat(src); p.config.Generated == false && err != nil {
+ errs = packersdk.MultiErrorAppend(errs,
+ fmt.Errorf("Bad source '%s': %s", src, err))
+ }
+ }
+ }
+
+ if len(p.config.Sources) > 0 && p.config.Content != "" {
+ errs = packersdk.MultiErrorAppend(errs,
+ errors.New("source(s) conflicts with content."))
+ }
+
+ if p.config.Destination == "" {
+ errs = packersdk.MultiErrorAppend(errs,
+ errors.New("Destination must be specified."))
+ }
+
+ if errs != nil && len(errs.Errors) > 0 {
+ return errs
+ }
+
+ return nil
+}
+
+func (p *Provisioner) Provision(ctx context.Context, ui packersdk.Ui, comm packersdk.Communicator, generatedData map[string]interface{}) error {
+ if generatedData == nil {
+ generatedData = make(map[string]interface{})
+ }
+ p.config.ctx.Data = generatedData
+
+ if p.config.Content != "" {
+ file, err := tmp.File("pkr-file-content")
+ if err != nil {
+ return err
+ }
+ defer file.Close()
+ if _, err := file.WriteString(p.config.Content); err != nil {
+ return err
+ }
+ p.config.Content = ""
+ p.config.Sources = append(p.config.Sources, file.Name())
+ }
+
+ if p.config.Direction == "download" {
+ return p.ProvisionDownload(ui, comm)
+ } else {
+ return p.ProvisionUpload(ui, comm)
+ }
+}
+
+func (p *Provisioner) ProvisionDownload(ui packersdk.Ui, comm packersdk.Communicator) error {
+ dst, err := interpolate.Render(p.config.Destination, &p.config.ctx)
+ if err != nil {
+ return fmt.Errorf("Error interpolating destination: %s", err)
+ }
+ for _, src := range p.config.Sources {
+ dst := dst
+ src, err := interpolate.Render(src, &p.config.ctx)
+ if err != nil {
+ return fmt.Errorf("Error interpolating source: %s", err)
+ }
+
+ // ensure destination dir exists. p.config.Destination may either be a file or a dir.
+ dir := dst
+ // if it doesn't end with a /, set dir as the parent dir
+ if !strings.HasSuffix(dst, "/") {
+ dir = filepath.Dir(dir)
+ } else if !strings.HasSuffix(src, "/") && !strings.HasSuffix(src, "*") {
+ dst = filepath.Join(dst, filepath.Base(src))
+ }
+ ui.Say(fmt.Sprintf("Downloading %s => %s", src, dst))
+
+ if dir != "" {
+ err := os.MkdirAll(dir, os.FileMode(0755))
+ if err != nil {
+ return err
+ }
+ }
+ // if the src was a dir, download the dir
+ if strings.HasSuffix(src, "/") || strings.ContainsAny(src, "*?[") {
+ return comm.DownloadDir(src, dst, nil)
+ }
+
+ f, err := os.OpenFile(dst, os.O_CREATE|os.O_WRONLY|os.O_TRUNC, 0644)
+ if err != nil {
+ return err
+ }
+ defer f.Close()
+
+ // Create MultiWriter for the current progress
+ pf := io.MultiWriter(f)
+
+ // Download the file
+ if err = comm.Download(src, pf); err != nil {
+ ui.Error(fmt.Sprintf("Download failed: %s", err))
+ return err
+ }
+ }
+ return nil
+}
+
+func (p *Provisioner) ProvisionUpload(ui packersdk.Ui, comm packersdk.Communicator) error {
+ dst, err := interpolate.Render(p.config.Destination, &p.config.ctx)
+ if err != nil {
+ return fmt.Errorf("Error interpolating destination: %s", err)
+ }
+ for _, src := range p.config.Sources {
+ src, err := interpolate.Render(src, &p.config.ctx)
+ if err != nil {
+ return fmt.Errorf("Error interpolating source: %s", err)
+ }
+
+ ui.Say(fmt.Sprintf("Uploading %s => %s", src, dst))
+
+ info, err := os.Stat(src)
+ if err != nil {
+ return err
+ }
+
+ // If we're uploading a directory, short circuit and do that
+ if info.IsDir() {
+ if err = comm.UploadDir(dst, src, nil); err != nil {
+ ui.Error(fmt.Sprintf("Upload failed: %s", err))
+ return err
+ }
+ continue
+ }
+
+ // We're uploading a file...
+ f, err := os.Open(src)
+ if err != nil {
+ return err
+ }
+ defer f.Close()
+
+ fi, err := f.Stat()
+ if err != nil {
+ return err
+ }
+
+ filedst := dst
+ if strings.HasSuffix(dst, "/") {
+ filedst = dst + filepath.Base(src)
+ }
+
+ pf := ui.TrackProgress(filepath.Base(src), 0, info.Size(), f)
+ defer pf.Close()
+
+ // Upload the file
+ if err = comm.Upload(filedst, pf, &fi); err != nil {
+ if strings.Contains(err.Error(), "Error restoring file") {
+ ui.Error(fmt.Sprintf("Upload failed: %s; this can occur when "+
+ "your file destination is a folder without a trailing "+
+ "slash.", err))
+ }
+ ui.Error(fmt.Sprintf("Upload failed: %s", err))
+ return err
+ }
+ }
+ return nil
+}
diff --git a/v1.9.4/provisioner/file/provisioner.hcl2spec.go b/v1.9.4/provisioner/file/provisioner.hcl2spec.go
new file mode 100644
index 0000000..3a90f0f
--- /dev/null
+++ b/v1.9.4/provisioner/file/provisioner.hcl2spec.go
@@ -0,0 +1,57 @@
+// Code generated by "packer-sdc mapstructure-to-hcl2"; DO NOT EDIT.
+
+package file
+
+import (
+ "github.com/hashicorp/hcl/v2/hcldec"
+ "github.com/zclconf/go-cty/cty"
+)
+
+// FlatConfig is an auto-generated flat version of Config.
+// Where the contents of a field with a `mapstructure:,squash` tag are bubbled up.
+type FlatConfig struct {
+ PackerBuildName *string `mapstructure:"packer_build_name" cty:"packer_build_name" 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"`
+ Content *string `mapstructure:"content" required:"true" cty:"content" hcl:"content"`
+ Source *string `mapstructure:"source" required:"true" cty:"source" hcl:"source"`
+ Sources []string `mapstructure:"sources" required:"false" cty:"sources" hcl:"sources"`
+ Destination *string `mapstructure:"destination" required:"true" cty:"destination" hcl:"destination"`
+ Direction *string `mapstructure:"direction" required:"false" cty:"direction" hcl:"direction"`
+ Generated *bool `mapstructure:"generated" required:"false" cty:"generated" hcl:"generated"`
+}
+
+// FlatMapstructure returns a new FlatConfig.
+// FlatConfig is an auto-generated flat version of Config.
+// Where the contents a fields with a `mapstructure:,squash` tag are bubbled up.
+func (*Config) FlatMapstructure() interface{ HCL2Spec() map[string]hcldec.Spec } {
+ return new(FlatConfig)
+}
+
+// HCL2Spec returns the hcl spec of a Config.
+// This spec is used by HCL to read the fields of Config.
+// The decoded values from this spec will then be applied to a FlatConfig.
+func (*FlatConfig) HCL2Spec() map[string]hcldec.Spec {
+ s := map[string]hcldec.Spec{
+ "packer_build_name": &hcldec.AttrSpec{Name: "packer_build_name", Type: cty.String, Required: false},
+ "packer_builder_type": &hcldec.AttrSpec{Name: "packer_builder_type", Type: cty.String, Required: false},
+ "packer_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_sensitive_variables": &hcldec.AttrSpec{Name: "packer_sensitive_variables", Type: cty.List(cty.String), Required: false},
+ "content": &hcldec.AttrSpec{Name: "content", Type: cty.String, Required: false},
+ "source": &hcldec.AttrSpec{Name: "source", Type: cty.String, Required: false},
+ "sources": &hcldec.AttrSpec{Name: "sources", Type: cty.List(cty.String), Required: false},
+ "destination": &hcldec.AttrSpec{Name: "destination", Type: cty.String, Required: false},
+ "direction": &hcldec.AttrSpec{Name: "direction", Type: cty.String, Required: false},
+ "generated": &hcldec.AttrSpec{Name: "generated", Type: cty.Bool, Required: false},
+ }
+ return s
+}
diff --git a/v1.9.4/provisioner/file/provisioner_test.go b/v1.9.4/provisioner/file/provisioner_test.go
new file mode 100644
index 0000000..e3ecd72
--- /dev/null
+++ b/v1.9.4/provisioner/file/provisioner_test.go
@@ -0,0 +1,505 @@
+// Copyright (c) HashiCorp, Inc.
+// SPDX-License-Identifier: MPL-2.0
+
+package file
+
+import (
+ "bytes"
+ "context"
+ "io/ioutil"
+ "os"
+ "path/filepath"
+ "regexp"
+ "strings"
+ "testing"
+
+ packersdk "github.com/hashicorp/packer-plugin-sdk/packer"
+)
+
+func testConfig() map[string]interface{} {
+ return map[string]interface{}{
+ "destination": "something",
+ }
+}
+
+func TestProvisioner_Impl(t *testing.T) {
+ var raw interface{}
+ raw = &Provisioner{}
+ if _, ok := raw.(packersdk.Provisioner); !ok {
+ t.Fatalf("must be a provisioner")
+ }
+}
+
+func TestProvisionerPrepare_InvalidKey(t *testing.T) {
+ var p Provisioner
+ config := testConfig()
+
+ // Add a random key
+ config["i_should_not_be_valid"] = true
+ err := p.Prepare(config)
+ if err == nil {
+ t.Fatal("should have error")
+ }
+}
+
+func TestProvisionerPrepare_InvalidSource(t *testing.T) {
+ var p Provisioner
+ config := testConfig()
+ config["source"] = "/this/should/not/exist"
+
+ err := p.Prepare(config)
+ if err == nil {
+ t.Fatalf("should require existing file")
+ }
+
+ config["generated"] = false
+ err = p.Prepare(config)
+ if err == nil {
+ t.Fatalf("should required existing file")
+ }
+}
+
+func TestProvisionerPrepare_ValidSource(t *testing.T) {
+ var p Provisioner
+
+ tf, err := ioutil.TempFile("", "packer")
+ if err != nil {
+ t.Fatalf("error tempfile: %s", err)
+ }
+ defer os.Remove(tf.Name())
+
+ config := testConfig()
+ config["source"] = tf.Name()
+ err = p.Prepare(config)
+ if err != nil {
+ t.Fatalf("should allow valid file: %s", err)
+ }
+
+ config["generated"] = false
+ err = p.Prepare(config)
+ if err != nil {
+ t.Fatalf("should allow valid file: %s", err)
+ }
+}
+
+func TestProvisionerPrepare_GeneratedSource(t *testing.T) {
+ var p Provisioner
+
+ config := testConfig()
+ config["source"] = "/this/should/not/exist"
+ config["generated"] = true
+ err := p.Prepare(config)
+ if err != nil {
+ t.Fatalf("should allow non-existing file: %s", err)
+ }
+}
+
+func TestProvisionerPrepare_EmptyDestination(t *testing.T) {
+ var p Provisioner
+
+ config := testConfig()
+ delete(config, "destination")
+ err := p.Prepare(config)
+ if err == nil {
+ t.Fatalf("should require destination path")
+ }
+}
+
+func TestProvisionerProvision_SendsFile(t *testing.T) {
+ var p Provisioner
+ tf, err := ioutil.TempFile("", "packer")
+ if err != nil {
+ t.Fatalf("error tempfile: %s", err)
+ }
+ defer os.Remove(tf.Name())
+
+ if _, err = tf.Write([]byte("hello")); err != nil {
+ t.Fatalf("error writing tempfile: %s", err)
+ }
+
+ config := map[string]interface{}{
+ "source": tf.Name(),
+ "destination": "something",
+ }
+
+ if err := p.Prepare(config); err != nil {
+ t.Fatalf("err: %s", err)
+ }
+
+ b := bytes.NewBuffer(nil)
+ ui := &packersdk.BasicUi{
+ Writer: b,
+ PB: &packersdk.NoopProgressTracker{},
+ }
+ comm := &packersdk.MockCommunicator{}
+ err = p.Provision(context.Background(), ui, comm, make(map[string]interface{}))
+ if err != nil {
+ t.Fatalf("should successfully provision: %s", err)
+ }
+
+ if !strings.Contains(b.String(), tf.Name()) {
+ t.Fatalf("should print source filename")
+ }
+
+ if !strings.Contains(b.String(), "something") {
+ t.Fatalf("should print destination filename")
+ }
+
+ if comm.UploadPath != "something" {
+ t.Fatalf("should upload to configured destination")
+ }
+
+ if comm.UploadData != "hello" {
+ t.Fatalf("should upload with source file's data")
+ }
+}
+
+func TestProvisionerProvision_SendsContent(t *testing.T) {
+ var p Provisioner
+
+ dst := "something.txt"
+ content := "hello"
+ config := map[string]interface{}{
+ "content": content,
+ "destination": dst,
+ }
+
+ if err := p.Prepare(config); err != nil {
+ t.Fatalf("err: %s", err)
+ }
+
+ b := bytes.NewBuffer(nil)
+ ui := &packersdk.BasicUi{
+ Writer: b,
+ PB: &packersdk.NoopProgressTracker{},
+ }
+ comm := &packersdk.MockCommunicator{}
+ err := p.Provision(context.Background(), ui, comm, make(map[string]interface{}))
+ if err != nil {
+ t.Fatalf("should successfully provision: %s", err)
+ }
+
+ if !strings.Contains(b.String(), "something") {
+ t.Fatalf("should print destination filename")
+ }
+
+ if comm.UploadPath != dst {
+ t.Fatalf("should upload to configured destination")
+ }
+
+ if comm.UploadData != content {
+ t.Fatalf("should upload with source file's data")
+ }
+
+}
+
+func TestProvisionerProvision_SendsFileMultipleFiles(t *testing.T) {
+ var p Provisioner
+ tf1, err := ioutil.TempFile("", "packer")
+ if err != nil {
+ t.Fatalf("error tempfile: %s", err)
+ }
+ defer os.Remove(tf1.Name())
+
+ if _, err = tf1.Write([]byte("hello")); err != nil {
+ t.Fatalf("error writing tempfile: %s", err)
+ }
+
+ tf2, err := ioutil.TempFile("", "packer")
+ if err != nil {
+ t.Fatalf("error tempfile: %s", err)
+ }
+ defer os.Remove(tf2.Name())
+
+ if _, err = tf2.Write([]byte("hello")); err != nil {
+ t.Fatalf("error writing tempfile: %s", err)
+ }
+
+ config := map[string]interface{}{
+ "sources": []string{tf1.Name(), tf2.Name()},
+ "destination": "something",
+ }
+
+ if err := p.Prepare(config); err != nil {
+ t.Fatalf("err: %s", err)
+ }
+
+ b := bytes.NewBuffer(nil)
+ ui := &packersdk.BasicUi{
+ Writer: b,
+ PB: &packersdk.NoopProgressTracker{},
+ }
+ comm := &packersdk.MockCommunicator{}
+ err = p.Provision(context.Background(), ui, comm, make(map[string]interface{}))
+ if err != nil {
+ t.Fatalf("should successfully provision: %s", err)
+ }
+
+ if !strings.Contains(b.String(), tf1.Name()) {
+ t.Fatalf("should print first source filename")
+ }
+
+ if !strings.Contains(b.String(), tf2.Name()) {
+ t.Fatalf("should print second source filename")
+ }
+}
+
+func TestProvisionerProvision_SendsFileMultipleDirs(t *testing.T) {
+ var p Provisioner
+
+ // Prepare the first directory
+ td1, err := ioutil.TempDir("", "packerdir")
+ if err != nil {
+ t.Fatalf("error temp folder 1: %s", err)
+ }
+ defer os.Remove(td1)
+
+ tf1, err := ioutil.TempFile(td1, "packer")
+ if err != nil {
+ t.Fatalf("error tempfile: %s", err)
+ }
+
+ if _, err = tf1.Write([]byte("hello")); err != nil {
+ t.Fatalf("error writing tempfile: %s", err)
+ }
+
+ // Prepare the second directory
+ td2, err := ioutil.TempDir("", "packerdir")
+ if err != nil {
+ t.Fatalf("error temp folder 1: %s", err)
+ }
+ defer os.Remove(td2)
+
+ tf2, err := ioutil.TempFile(td2, "packer")
+ if err != nil {
+ t.Fatalf("error tempfile: %s", err)
+ }
+
+ if _, err = tf2.Write([]byte("hello")); err != nil {
+ t.Fatalf("error writing tempfile: %s", err)
+ }
+
+ if _, err = tf1.Write([]byte("hello")); err != nil {
+ t.Fatalf("error writing tempfile: %s", err)
+ }
+
+ // Run Provision
+
+ config := map[string]interface{}{
+ "sources": []string{td1, td2},
+ "destination": "something",
+ }
+
+ if err := p.Prepare(config); err != nil {
+ t.Fatalf("err: %s", err)
+ }
+
+ b := bytes.NewBuffer(nil)
+ ui := &packersdk.BasicUi{
+ Writer: b,
+ PB: &packersdk.NoopProgressTracker{},
+ }
+ comm := &packersdk.MockCommunicator{}
+ err = p.Provision(context.Background(), ui, comm, make(map[string]interface{}))
+ if err != nil {
+ t.Fatalf("should successfully provision: %s", err)
+ }
+
+ if !strings.Contains(b.String(), td1) {
+ t.Fatalf("should print first directory")
+ }
+
+ if !strings.Contains(b.String(), td2) {
+ t.Fatalf("should print second directory")
+ }
+}
+
+func TestProvisionerProvision_DownloadsMultipleFilesToFolder(t *testing.T) {
+ var p Provisioner
+
+ tf1, err := ioutil.TempFile("", "packer")
+ if err != nil {
+ t.Fatalf("error tempfile: %s", err)
+ }
+ defer os.Remove(tf1.Name())
+
+ if _, err = tf1.Write([]byte("hello")); err != nil {
+ t.Fatalf("error writing tempfile: %s", err)
+ }
+
+ tf2, err := ioutil.TempFile("", "packer")
+ if err != nil {
+ t.Fatalf("error tempfile: %s", err)
+ }
+ defer os.Remove(tf2.Name())
+
+ if _, err = tf2.Write([]byte("hello")); err != nil {
+ t.Fatalf("error writing tempfile: %s", err)
+ }
+
+ config := map[string]interface{}{
+ "sources": []string{tf1.Name(), tf2.Name()},
+ "destination": "something/",
+ "direction": "download",
+ }
+
+ // Cleaning up destination directory
+ cwd, err := os.Getwd()
+ if err != nil {
+ t.Fatalf("Failed getting current working directory")
+ }
+ destinationDir := filepath.Join(cwd, "something")
+ defer os.RemoveAll(destinationDir)
+
+ if err := p.Prepare(config); err != nil {
+ t.Fatalf("err: %s", err)
+ }
+
+ b := bytes.NewBuffer(nil)
+ ui := &packersdk.BasicUi{
+ Writer: b,
+ PB: &packersdk.NoopProgressTracker{},
+ }
+ comm := &packersdk.MockCommunicator{}
+ err = p.Provision(context.Background(), ui, comm, make(map[string]interface{}))
+ if err != nil {
+ t.Fatalf("should successfully provision: %s", err)
+ }
+
+ if !strings.Contains(b.String(), tf1.Name()) {
+ t.Errorf("should print source filenam '%s'e; output: \n%s", tf1.Name(), b.String())
+ }
+
+ if !strings.Contains(b.String(), tf2.Name()) {
+ t.Errorf("should second source filename '%s'; output: \n%s", tf2.Name(), b.String())
+ }
+
+ dst1 := filepath.Join("something", filepath.Base(tf1.Name()))
+ if !strings.Contains(b.String(), dst1) {
+ t.Errorf("should print destination filename '%s'; output: \n%s", dst1, b.String())
+ }
+
+ dst2 := filepath.Join("something", filepath.Base(tf2.Name()))
+ if !strings.Contains(b.String(), dst2) {
+ t.Errorf("should print destination filename '%s'; output: \n%s", dst2, b.String())
+ }
+}
+
+func TestProvisionerProvision_SendsFileMultipleFilesToFolder(t *testing.T) {
+ var p Provisioner
+
+ tf1, err := ioutil.TempFile("", "packer")
+ if err != nil {
+ t.Fatalf("error tempfile: %s", err)
+ }
+ defer os.Remove(tf1.Name())
+
+ if _, err = tf1.Write([]byte("hello")); err != nil {
+ t.Fatalf("error writing tempfile: %s", err)
+ }
+
+ tf2, err := ioutil.TempFile("", "packer")
+ if err != nil {
+ t.Fatalf("error tempfile: %s", err)
+ }
+ defer os.Remove(tf2.Name())
+
+ if _, err = tf2.Write([]byte("hello")); err != nil {
+ t.Fatalf("error writing tempfile: %s", err)
+ }
+
+ config := map[string]interface{}{
+ "sources": []string{tf1.Name(), tf2.Name()},
+ "destination": "something/",
+ }
+
+ if err := p.Prepare(config); err != nil {
+ t.Fatalf("err: %s", err)
+ }
+
+ b := bytes.NewBuffer(nil)
+ ui := &packersdk.BasicUi{
+ Writer: b,
+ PB: &packersdk.NoopProgressTracker{},
+ }
+ comm := &packersdk.MockCommunicator{}
+ err = p.Provision(context.Background(), ui, comm, make(map[string]interface{}))
+ if err != nil {
+ t.Fatalf("should successfully provision: %s", err)
+ }
+
+ if !strings.Contains(b.String(), tf1.Name()) {
+ t.Fatalf("should print first source filename")
+ }
+
+ if !strings.Contains(b.String(), tf2.Name()) {
+ t.Fatalf("should print second source filename")
+ }
+
+ dstRegex := regexp.MustCompile("something/\n")
+ allDst := dstRegex.FindAllString(b.String(), -1)
+ if len(allDst) != 2 {
+ t.Fatalf("some destinations are broken; output: \n%s", b.String())
+ }
+}
+
+func TestProvisionDownloadMkdirAll(t *testing.T) {
+ tests := []struct {
+ path string
+ }{
+ {"dir"},
+ {"dir/"},
+ {"dir/subdir"},
+ {"dir/subdir/"},
+ {"path/to/dir"},
+ {"path/to/dir/"},
+ }
+ tmpDir, err := ioutil.TempDir("", "packer-file")
+ if err != nil {
+ t.Fatalf("error tempdir: %s", err)
+ }
+ defer os.RemoveAll(tmpDir)
+ tf, err := ioutil.TempFile(tmpDir, "packer")
+ if err != nil {
+ t.Fatalf("error tempfile: %s", err)
+ }
+ defer os.Remove(tf.Name())
+
+ config := map[string]interface{}{
+ "source": tf.Name(),
+ }
+ var p Provisioner
+ for _, test := range tests {
+ path := filepath.Join(tmpDir, test.path)
+ config["destination"] = filepath.Join(path, "something")
+ if err := p.Prepare(config); err != nil {
+ t.Fatalf("err: %s", err)
+ }
+ b := bytes.NewBuffer(nil)
+ ui := &packersdk.BasicUi{
+ Writer: b,
+ PB: &packersdk.NoopProgressTracker{},
+ }
+ comm := &packersdk.MockCommunicator{}
+ err = p.ProvisionDownload(ui, comm)
+ if err != nil {
+ t.Fatalf("should successfully provision: %s", err)
+ }
+
+ if !strings.Contains(b.String(), tf.Name()) {
+ t.Fatalf("should print source filename")
+ }
+
+ if !strings.Contains(b.String(), "something") {
+ t.Fatalf("should print destination filename")
+ }
+
+ if _, err := os.Stat(path); err != nil {
+ t.Fatalf("stat of download dir should not error: %s", err)
+ }
+
+ if _, err := os.Stat(config["destination"].(string)); err != nil {
+ t.Fatalf("stat of destination file should not error: %s", err)
+ }
+ }
+}
diff --git a/v1.9.4/provisioner/file/version/version.go b/v1.9.4/provisioner/file/version/version.go
new file mode 100644
index 0000000..e5b7923
--- /dev/null
+++ b/v1.9.4/provisioner/file/version/version.go
@@ -0,0 +1,16 @@
+// Copyright (c) HashiCorp, Inc.
+// SPDX-License-Identifier: MPL-2.0
+
+package version
+
+import (
+ "github.com/hashicorp/packer-plugin-sdk/version"
+ packerVersion "github.com/hashicorp/packer/version"
+)
+
+var FileProvisionerVersion *version.PluginVersion
+
+func init() {
+ FileProvisionerVersion = version.InitializePluginVersion(
+ packerVersion.Version, packerVersion.VersionPrerelease)
+}
diff --git a/v1.9.4/provisioner/powershell/execution_policy.go b/v1.9.4/provisioner/powershell/execution_policy.go
new file mode 100644
index 0000000..94463db
--- /dev/null
+++ b/v1.9.4/provisioner/powershell/execution_policy.go
@@ -0,0 +1,44 @@
+// Copyright (c) HashiCorp, Inc.
+// SPDX-License-Identifier: MPL-2.0
+
+//go:generate enumer -transform snake -trimprefix ExecutionPolicy -type ExecutionPolicy
+
+package powershell
+
+import (
+ "reflect"
+ "strconv"
+)
+
+// ExecutionPolicy setting to run the command(s).
+// For the powershell provider the default has historically been to bypass.
+type ExecutionPolicy int
+
+const (
+ ExecutionPolicyBypass ExecutionPolicy = iota
+ ExecutionPolicyAllsigned
+ ExecutionPolicyDefault
+ ExecutionPolicyRemotesigned
+ ExecutionPolicyRestricted
+ ExecutionPolicyUndefined
+ ExecutionPolicyUnrestricted
+ ExecutionPolicyNone // not set
+)
+
+func StringToExecutionPolicyHook(f reflect.Kind, t reflect.Kind, data interface{}) (interface{}, error) {
+ if f != reflect.String || t != reflect.Int {
+ return data, nil
+ }
+
+ raw := data.(string)
+ // It's possible that the thing being read is not supposed to be an
+ // execution policy; if the string provided is actally an int, just return
+ // the int.
+ i, err := strconv.Atoi(raw)
+ if err == nil {
+ return i, nil
+ }
+ // If it can't just be cast to an int, try to parse string into an
+ // execution policy.
+ return ExecutionPolicyString(raw)
+}
diff --git a/v1.9.4/provisioner/powershell/execution_policy_test.go b/v1.9.4/provisioner/powershell/execution_policy_test.go
new file mode 100644
index 0000000..8b82c97
--- /dev/null
+++ b/v1.9.4/provisioner/powershell/execution_policy_test.go
@@ -0,0 +1,24 @@
+// Copyright (c) HashiCorp, Inc.
+// SPDX-License-Identifier: MPL-2.0
+
+package powershell
+
+import (
+ "testing"
+)
+
+func TestExecutionPolicy_Decode(t *testing.T) {
+ config := map[string]interface{}{
+ "inline": []interface{}{"foo", "bar"},
+ "execution_policy": "allsigned",
+ }
+ p := new(Provisioner)
+ err := p.Prepare(config)
+ if err != nil {
+ t.Fatal(err)
+ }
+
+ if p.config.ExecutionPolicy != ExecutionPolicyAllsigned {
+ t.Fatalf("Expected AllSigned execution policy; got: %s", p.config.ExecutionPolicy)
+ }
+}
diff --git a/v1.9.4/provisioner/powershell/executionpolicy_enumer.go b/v1.9.4/provisioner/powershell/executionpolicy_enumer.go
new file mode 100644
index 0000000..eac9573
--- /dev/null
+++ b/v1.9.4/provisioner/powershell/executionpolicy_enumer.go
@@ -0,0 +1,55 @@
+// Code generated by "enumer -transform snake -trimprefix ExecutionPolicy -type ExecutionPolicy"; DO NOT EDIT.
+
+package powershell
+
+import (
+ "fmt"
+)
+
+const _ExecutionPolicyName = "bypassallsigneddefaultremotesignedrestrictedundefinedunrestrictednone"
+
+var _ExecutionPolicyIndex = [...]uint8{0, 6, 15, 22, 34, 44, 53, 65, 69}
+
+func (i ExecutionPolicy) String() string {
+ if i < 0 || i >= ExecutionPolicy(len(_ExecutionPolicyIndex)-1) {
+ return fmt.Sprintf("ExecutionPolicy(%d)", i)
+ }
+ return _ExecutionPolicyName[_ExecutionPolicyIndex[i]:_ExecutionPolicyIndex[i+1]]
+}
+
+var _ExecutionPolicyValues = []ExecutionPolicy{0, 1, 2, 3, 4, 5, 6, 7}
+
+var _ExecutionPolicyNameToValueMap = map[string]ExecutionPolicy{
+ _ExecutionPolicyName[0:6]: 0,
+ _ExecutionPolicyName[6:15]: 1,
+ _ExecutionPolicyName[15:22]: 2,
+ _ExecutionPolicyName[22:34]: 3,
+ _ExecutionPolicyName[34:44]: 4,
+ _ExecutionPolicyName[44:53]: 5,
+ _ExecutionPolicyName[53:65]: 6,
+ _ExecutionPolicyName[65:69]: 7,
+}
+
+// ExecutionPolicyString retrieves an enum value from the enum constants string name.
+// Throws an error if the param is not part of the enum.
+func ExecutionPolicyString(s string) (ExecutionPolicy, error) {
+ if val, ok := _ExecutionPolicyNameToValueMap[s]; ok {
+ return val, nil
+ }
+ return 0, fmt.Errorf("%s does not belong to ExecutionPolicy values", s)
+}
+
+// ExecutionPolicyValues returns all values of the enum
+func ExecutionPolicyValues() []ExecutionPolicy {
+ return _ExecutionPolicyValues
+}
+
+// IsAExecutionPolicy returns "true" if the value is listed in the enum definition. "false" otherwise
+func (i ExecutionPolicy) IsAExecutionPolicy() bool {
+ for _, v := range _ExecutionPolicyValues {
+ if i == v {
+ return true
+ }
+ }
+ return false
+}
diff --git a/v1.9.4/provisioner/powershell/provisioner.go b/v1.9.4/provisioner/powershell/provisioner.go
new file mode 100644
index 0000000..65ed16d
--- /dev/null
+++ b/v1.9.4/provisioner/powershell/provisioner.go
@@ -0,0 +1,577 @@
+// Copyright (c) HashiCorp, Inc.
+// SPDX-License-Identifier: MPL-2.0
+
+//go:generate packer-sdc mapstructure-to-hcl2 -type Config
+
+// This package implements a provisioner for Packer that executes powershell
+// scripts within the remote machine.
+package powershell
+
+import (
+ "bufio"
+ "context"
+ "errors"
+ "fmt"
+ "log"
+ "os"
+ "path/filepath"
+ "sort"
+ "strings"
+ "time"
+
+ "github.com/hashicorp/hcl/v2/hcldec"
+ "github.com/hashicorp/packer-plugin-sdk/guestexec"
+ "github.com/hashicorp/packer-plugin-sdk/multistep/commonsteps"
+ packersdk "github.com/hashicorp/packer-plugin-sdk/packer"
+ "github.com/hashicorp/packer-plugin-sdk/retry"
+ "github.com/hashicorp/packer-plugin-sdk/shell"
+ "github.com/hashicorp/packer-plugin-sdk/template/config"
+ "github.com/hashicorp/packer-plugin-sdk/template/interpolate"
+ "github.com/hashicorp/packer-plugin-sdk/tmp"
+ "github.com/hashicorp/packer-plugin-sdk/uuid"
+)
+
+var psEscape = strings.NewReplacer(
+ "$", "`$",
+ "\"", "`\"",
+ "`", "``",
+ "'", "`'",
+)
+
+type Config struct {
+ shell.Provisioner `mapstructure:",squash"`
+
+ shell.ProvisionerRemoteSpecific `mapstructure:",squash"`
+
+ // The remote path where the file containing the environment variables
+ // will be uploaded to. This should be set to a writable file that is in a
+ // pre-existing directory.
+ RemoteEnvVarPath string `mapstructure:"remote_env_var_path"`
+
+ // The command used to execute the elevated script. The '{{ .Path }}'
+ // variable should be used to specify where the script goes, {{ .Vars }}
+ // can be used to inject the environment_vars into the environment.
+ ElevatedExecuteCommand string `mapstructure:"elevated_execute_command"`
+
+ // Whether to clean scripts up after executing the provisioner.
+ // Defaults to false. When true any script created by a non-elevated Powershell
+ // provisioner will be removed from the remote machine. Elevated scripts,
+ // along with the scheduled tasks, will always be removed regardless of the
+ // value set for `skip_clean`.
+ SkipClean bool `mapstructure:"skip_clean"`
+
+ // The timeout for retrying to start the process. Until this timeout is
+ // reached, if the provisioner can't start a process, it retries. This
+ // can be set high to allow for reboots.
+ StartRetryTimeout time.Duration `mapstructure:"start_retry_timeout"`
+
+ // This is used in the template generation to format environment variables
+ // inside the `ElevatedExecuteCommand` template.
+ ElevatedEnvVarFormat string `mapstructure:"elevated_env_var_format"`
+
+ // Instructs the communicator to run the remote script as a Windows
+ // scheduled task, effectively elevating the remote user by impersonating
+ // a logged-in user
+ ElevatedUser string `mapstructure:"elevated_user"`
+ ElevatedPassword string `mapstructure:"elevated_password"`
+
+ ExecutionPolicy ExecutionPolicy `mapstructure:"execution_policy"`
+
+ remoteCleanUpScriptPath string
+
+ // If set, sets PowerShell's [PSDebug mode
+ // on](https://docs.microsoft.com/en-us/powershell/module/microsoft.powershell.core/set-psdebug?view=powershell-7)
+ // in order to make script debugging easier. For instance, setting the value
+ // to 1 results in adding this to the execute command:
+ //
+ // ``` powershell
+ // Set-PSDebug -Trace 1
+ // ```
+ DebugMode int `mapstructure:"debug_mode"`
+
+ // A duration of how long to pause after the provisioner
+ PauseAfter time.Duration `mapstructure:"pause_after"`
+
+ // Run pwsh.exe instead of powershell.exe - latest version of powershell.
+ UsePwsh bool `mapstructure:"use_pwsh"`
+
+ ctx interpolate.Context
+}
+
+type Provisioner struct {
+ config Config
+ communicator packersdk.Communicator
+ generatedData map[string]interface{}
+}
+
+func (p *Provisioner) defaultExecuteCommand() string {
+ baseCmd := `& { if (Test-Path variable:global:ProgressPreference)` +
+ `{set-variable -name variable:global:ProgressPreference -value 'SilentlyContinue'};`
+
+ if p.config.DebugMode != 0 {
+ baseCmd += fmt.Sprintf(`Set-PsDebug -Trace %d;`, p.config.DebugMode)
+ }
+
+ baseCmd += `. {{.Vars}}; &'{{.Path}}'; exit $LastExitCode }`
+
+ if p.config.ExecutionPolicy == ExecutionPolicyNone {
+ return baseCmd
+ }
+
+ if p.config.UsePwsh {
+ return fmt.Sprintf(`pwsh -executionpolicy %s -command "%s"`, p.config.ExecutionPolicy, baseCmd)
+ } else {
+ return fmt.Sprintf(`powershell -executionpolicy %s "%s"`, p.config.ExecutionPolicy, baseCmd)
+ }
+
+}
+
+func (p *Provisioner) ConfigSpec() hcldec.ObjectSpec { return p.config.FlatMapstructure().HCL2Spec() }
+
+func (p *Provisioner) Prepare(raws ...interface{}) error {
+ err := config.Decode(&p.config, &config.DecodeOpts{
+ PluginType: "powershell",
+ Interpolate: true,
+ InterpolateContext: &p.config.ctx,
+ InterpolateFilter: &interpolate.RenderFilter{
+ Exclude: []string{
+ "execute_command",
+ "elevated_execute_command",
+ },
+ },
+ DecodeHooks: append(config.DefaultDecodeHookFuncs, StringToExecutionPolicyHook),
+ }, raws...)
+
+ if err != nil {
+ return err
+ }
+
+ if p.config.EnvVarFormat == "" {
+ p.config.EnvVarFormat = `$env:%s="%s"; `
+ }
+
+ if p.config.ElevatedEnvVarFormat == "" {
+ p.config.ElevatedEnvVarFormat = `$env:%s="%s"; `
+ }
+
+ if p.config.ExecuteCommand == "" {
+ p.config.ExecuteCommand = p.defaultExecuteCommand()
+ }
+
+ if p.config.ElevatedExecuteCommand == "" {
+ p.config.ElevatedExecuteCommand = p.defaultExecuteCommand()
+ }
+
+ if p.config.Inline != nil && len(p.config.Inline) == 0 {
+ p.config.Inline = nil
+ }
+
+ if p.config.StartRetryTimeout == 0 {
+ p.config.StartRetryTimeout = 5 * time.Minute
+ }
+
+ if p.config.RemotePath == "" {
+ uuid := uuid.TimeOrderedUUID()
+ p.config.RemotePath = fmt.Sprintf(`c:/Windows/Temp/script-%s.ps1`, uuid)
+ }
+
+ if p.config.RemoteEnvVarPath == "" {
+ uuid := uuid.TimeOrderedUUID()
+ p.config.RemoteEnvVarPath = fmt.Sprintf(`c:/Windows/Temp/packer-ps-env-vars-%s.ps1`, uuid)
+ }
+
+ if p.config.Scripts == nil {
+ p.config.Scripts = make([]string, 0)
+ }
+
+ if p.config.Vars == nil {
+ p.config.Vars = make([]string, 0)
+ }
+
+ p.config.remoteCleanUpScriptPath = fmt.Sprintf(`c:/Windows/Temp/packer-cleanup-%s.ps1`, uuid.TimeOrderedUUID())
+
+ var errs error
+ if p.config.Script != "" && len(p.config.Scripts) > 0 {
+ errs = packersdk.MultiErrorAppend(errs,
+ errors.New("Only one of script or scripts can be specified."))
+ }
+
+ if p.config.ElevatedUser == "" && p.config.ElevatedPassword != "" {
+ errs = packersdk.MultiErrorAppend(errs,
+ errors.New("Must supply an 'elevated_user' if 'elevated_password' provided"))
+ }
+
+ if p.config.Script != "" {
+ p.config.Scripts = []string{p.config.Script}
+ }
+
+ if len(p.config.Scripts) == 0 && p.config.Inline == nil {
+ errs = packersdk.MultiErrorAppend(errs,
+ errors.New("Either a script file or inline script must be specified."))
+ } else if len(p.config.Scripts) > 0 && p.config.Inline != nil {
+ errs = packersdk.MultiErrorAppend(errs,
+ errors.New("Only a script file or an inline script can be specified, not both."))
+ }
+
+ for _, path := range p.config.Scripts {
+ if _, err := os.Stat(path); err != nil {
+ errs = packersdk.MultiErrorAppend(errs,
+ fmt.Errorf("Bad script '%s': %s", path, err))
+ }
+ }
+
+ // Do a check for bad environment variables, such as '=foo', 'foobar'
+ for _, kv := range p.config.Vars {
+ vs := strings.SplitN(kv, "=", 2)
+ if len(vs) != 2 || vs[0] == "" {
+ errs = packersdk.MultiErrorAppend(errs,
+ fmt.Errorf("Environment variable not in format 'key=value': %s", kv))
+ }
+ }
+
+ if p.config.ExecutionPolicy > 7 {
+ errs = packersdk.MultiErrorAppend(errs, fmt.Errorf(`Invalid execution `+
+ `policy provided. Please supply one of: "bypass", "allsigned",`+
+ ` "default", "remotesigned", "restricted", "undefined", `+
+ `"unrestricted", "none".`))
+ }
+
+ if !(p.config.DebugMode >= 0 && p.config.DebugMode <= 2) {
+ errs = packersdk.MultiErrorAppend(errs, fmt.Errorf("%d is an invalid Trace level for `debug_mode`; valid values are 0, 1, and 2", p.config.DebugMode))
+ }
+
+ if errs != nil {
+ return errs
+ }
+
+ return nil
+}
+
+// Takes the inline scripts, concatenates them into a temporary file and
+// returns a string containing the location of said file.
+func extractScript(p *Provisioner) (string, error) {
+ temp, err := tmp.File("powershell-provisioner")
+ if err != nil {
+ return "", err
+ }
+ defer temp.Close()
+ writer := bufio.NewWriter(temp)
+ for _, command := range p.config.Inline {
+ log.Printf("Found command: %s", command)
+ if _, err := writer.WriteString(command + "\n"); err != nil {
+ return "", fmt.Errorf("Error preparing powershell script: %s", err)
+ }
+ }
+
+ if err := writer.Flush(); err != nil {
+ return "", fmt.Errorf("Error preparing powershell script: %s", err)
+ }
+
+ return temp.Name(), nil
+}
+
+func (p *Provisioner) Provision(ctx context.Context, ui packersdk.Ui, comm packersdk.Communicator, generatedData map[string]interface{}) error {
+ ui.Say("Provisioning with Powershell...")
+ p.communicator = comm
+ p.generatedData = generatedData
+
+ scripts := make([]string, len(p.config.Scripts))
+ copy(scripts, p.config.Scripts)
+
+ if p.config.Inline != nil {
+ temp, err := extractScript(p)
+ if err != nil {
+ ui.Error(fmt.Sprintf("Unable to extract inline scripts into a file: %s", err))
+ }
+ scripts = append(scripts, temp)
+ // Remove temp script containing the inline commands when done
+ defer os.Remove(temp)
+ }
+
+ // every provisioner run will only have one env var script file so lets add it first
+ uploadedScripts := []string{p.config.RemoteEnvVarPath}
+ for _, path := range scripts {
+ ui.Say(fmt.Sprintf("Provisioning with powershell script: %s", path))
+
+ log.Printf("Opening %s for reading", path)
+ fi, err := os.Stat(path)
+ if err != nil {
+ return fmt.Errorf("Error stating powershell script: %s", err)
+ }
+ if os.IsPathSeparator(p.config.RemotePath[len(p.config.RemotePath)-1]) {
+ // path is a directory
+ p.config.RemotePath += filepath.Base(fi.Name())
+ }
+ f, err := os.Open(path)
+ if err != nil {
+ return fmt.Errorf("Error opening powershell script: %s", err)
+ }
+ defer f.Close()
+
+ command, err := p.createCommandText()
+ if err != nil {
+ return fmt.Errorf("Error processing command: %s", err)
+ }
+
+ // Upload the file and run the command. Do this in the context of a
+ // single retryable function so that we don't end up with the case
+ // that the upload succeeded, a restart is initiated, and then the
+ // command is executed but the file doesn't exist any longer.
+ var cmd *packersdk.RemoteCmd
+ err = retry.Config{StartTimeout: p.config.StartRetryTimeout}.Run(ctx, func(ctx context.Context) error {
+ if _, err := f.Seek(0, 0); err != nil {
+ return err
+ }
+ if err := comm.Upload(p.config.RemotePath, f, &fi); err != nil {
+ return fmt.Errorf("Error uploading script: %s", err)
+ }
+
+ cmd = &packersdk.RemoteCmd{Command: command}
+ return cmd.RunWithUi(ctx, comm, ui)
+ })
+ if err != nil {
+ return err
+ }
+
+ // Close the original file since we copied it
+ f.Close()
+
+ // Record every other uploaded script file so we can clean it up later
+ uploadedScripts = append(uploadedScripts, p.config.RemotePath)
+
+ log.Printf("%s returned with exit code %d", p.config.RemotePath, cmd.ExitStatus())
+ if err := p.config.ValidExitCode(cmd.ExitStatus()); err != nil {
+ return err
+ }
+ }
+
+ if p.config.SkipClean {
+ return nil
+ }
+
+ err := retry.Config{StartTimeout: time.Minute, RetryDelay: func() time.Duration { return 10 * time.Second }}.Run(ctx, func(ctx context.Context) error {
+ command, err := p.createRemoteCleanUpCommand(uploadedScripts)
+ if err != nil {
+ log.Printf("failed to upload the remote cleanup script: %q", err)
+ return err
+ }
+
+ cmd := &packersdk.RemoteCmd{Command: command}
+ return cmd.RunWithUi(ctx, comm, ui)
+ })
+ if err != nil {
+ log.Printf("remote cleanup script failed to upload; skipping the removal of temporary files: %s; ", strings.Join(uploadedScripts, ","))
+ }
+
+ if p.config.PauseAfter != 0 {
+ ui.Say(fmt.Sprintf("Pausing %s after this provisioner...", p.config.PauseAfter))
+ time.Sleep(p.config.PauseAfter)
+ }
+
+ return nil
+}
+
+// createRemoteCleanUpCommand will generated a powershell script that will remove remote files;
+// returning a command that can be executed remotely to do the cleanup.
+func (p *Provisioner) createRemoteCleanUpCommand(remoteFiles []string) (string, error) {
+ if len(remoteFiles) == 0 {
+ return "", fmt.Errorf("no remoteFiles provided for cleanup")
+ }
+
+ var b strings.Builder
+ // This script should self destruct.
+ remotePath := p.config.remoteCleanUpScriptPath
+ remoteFiles = append(remoteFiles, remotePath)
+ for _, filename := range remoteFiles {
+ fmt.Fprintf(&b, "if (Test-Path %[1]s) {Remove-Item %[1]s}\n", filename)
+ }
+
+ if err := p.communicator.Upload(remotePath, strings.NewReader(b.String()), nil); err != nil {
+ return "", fmt.Errorf("clean up script %q failed to upload: %s", remotePath, err)
+ }
+
+ data := p.generatedData
+ data["Path"] = remotePath
+ data["Vars"] = p.config.RemoteEnvVarPath
+ p.config.ctx.Data = data
+
+ p.config.ctx.Data = data
+ return interpolate.Render(p.config.ExecuteCommand, &p.config.ctx)
+}
+
+// Environment variables required within the remote environment are uploaded
+// within a PS script and then enabled by 'dot sourcing' the script
+// immediately prior to execution of the main command
+func (p *Provisioner) prepareEnvVars(elevated bool) (err error) {
+ // Collate all required env vars into a plain string with required
+ // formatting applied
+ flattenedEnvVars := p.createFlattenedEnvVars(elevated)
+ // Create a powershell script on the target build fs containing the
+ // flattened env vars
+ err = p.uploadEnvVars(flattenedEnvVars)
+ if err != nil {
+ return err
+ }
+ return
+}
+
+func (p *Provisioner) createFlattenedEnvVars(elevated bool) (flattened string) {
+ flattened = ""
+ envVars := make(map[string]string)
+
+ // Always available Packer provided env vars
+ envVars["PACKER_BUILD_NAME"] = p.config.PackerBuildName
+ envVars["PACKER_BUILDER_TYPE"] = p.config.PackerBuilderType
+
+ // expose ip address variables
+ httpAddr := p.generatedData["PackerHTTPAddr"]
+ if httpAddr != nil && httpAddr != commonsteps.HttpAddrNotImplemented {
+ envVars["PACKER_HTTP_ADDR"] = httpAddr.(string)
+ }
+ httpIP := p.generatedData["PackerHTTPIP"]
+ if httpIP != nil && httpIP != commonsteps.HttpIPNotImplemented {
+ envVars["PACKER_HTTP_IP"] = httpIP.(string)
+ }
+ httpPort := p.generatedData["PackerHTTPPort"]
+ if httpPort != nil && httpPort != commonsteps.HttpPortNotImplemented {
+ envVars["PACKER_HTTP_PORT"] = httpPort.(string)
+ }
+
+ // interpolate environment variables
+ p.config.ctx.Data = p.generatedData
+
+ // Split vars into key/value components
+ for _, envVar := range p.config.Vars {
+ envVar, err := interpolate.Render(envVar, &p.config.ctx)
+ if err != nil {
+ return
+ }
+ keyValue := strings.SplitN(envVar, "=", 2)
+ // Escape chars special to PS in each env var value
+ escapedEnvVarValue := psEscape.Replace(keyValue[1])
+ if escapedEnvVarValue != keyValue[1] {
+ log.Printf("Env var %s converted to %s after escaping chars special to PS", keyValue[1],
+ escapedEnvVarValue)
+ }
+ envVars[keyValue[0]] = escapedEnvVarValue
+ }
+
+ for k, v := range p.config.Env {
+ envVarName, err := interpolate.Render(k, &p.config.ctx)
+ if err != nil {
+ return
+ }
+ envVarValue, err := interpolate.Render(v, &p.config.ctx)
+ if err != nil {
+ return
+ }
+ envVars[envVarName] = psEscape.Replace(envVarValue)
+ }
+
+ // Create a list of env var keys in sorted order
+ var keys []string
+ for k := range envVars {
+ keys = append(keys, k)
+ }
+ sort.Strings(keys)
+ format := p.config.EnvVarFormat
+ if elevated {
+ format = p.config.ElevatedEnvVarFormat
+ }
+
+ // Re-assemble vars using OS specific format pattern and flatten
+ for _, key := range keys {
+ flattened += fmt.Sprintf(format, key, envVars[key])
+ }
+ return
+}
+
+func (p *Provisioner) uploadEnvVars(flattenedEnvVars string) (err error) {
+ ctx := context.TODO()
+ // Upload all env vars to a powershell script on the target build file
+ // system. Do this in the context of a single retryable function so that
+ // we gracefully handle any errors created by transient conditions such as
+ // a system restart
+ envVarReader := strings.NewReader(flattenedEnvVars)
+ log.Printf("Uploading env vars to %s", p.config.RemoteEnvVarPath)
+ err = retry.Config{StartTimeout: p.config.StartRetryTimeout}.Run(ctx, func(context.Context) error {
+ if err := p.communicator.Upload(p.config.RemoteEnvVarPath, envVarReader, nil); err != nil {
+ return fmt.Errorf("Error uploading ps script containing env vars: %s", err)
+ }
+ return err
+ })
+ return
+}
+
+func (p *Provisioner) createCommandText() (command string, err error) {
+ // Return the interpolated command
+ if p.config.ElevatedUser == "" {
+ return p.createCommandTextNonPrivileged()
+ } else {
+ return p.createCommandTextPrivileged()
+ }
+}
+
+func (p *Provisioner) createCommandTextNonPrivileged() (command string, err error) {
+ // Prepare everything needed to enable the required env vars within the
+ // remote environment
+ err = p.prepareEnvVars(false)
+ if err != nil {
+ return "", err
+ }
+
+ ctxData := p.generatedData
+ ctxData["Path"] = p.config.RemotePath
+ ctxData["Vars"] = p.config.RemoteEnvVarPath
+ p.config.ctx.Data = ctxData
+
+ command, err = interpolate.Render(p.config.ExecuteCommand, &p.config.ctx)
+
+ if err != nil {
+ return "", fmt.Errorf("Error processing command: %s", err)
+ }
+
+ // Return the interpolated command
+ return command, nil
+}
+
+func (p *Provisioner) createCommandTextPrivileged() (command string, err error) {
+ // Prepare everything needed to enable the required env vars within the
+ // remote environment
+ err = p.prepareEnvVars(true)
+ if err != nil {
+ return "", err
+ }
+ ctxData := p.generatedData
+ ctxData["Path"] = p.config.RemotePath
+ ctxData["Vars"] = p.config.RemoteEnvVarPath
+ p.config.ctx.Data = ctxData
+
+ command, err = interpolate.Render(p.config.ElevatedExecuteCommand, &p.config.ctx)
+ if err != nil {
+ return "", fmt.Errorf("Error processing command: %s", err)
+ }
+
+ command, err = guestexec.GenerateElevatedRunner(command, p)
+ if err != nil {
+ return "", fmt.Errorf("Error generating elevated runner: %s", err)
+ }
+
+ return command, err
+}
+
+func (p *Provisioner) Communicator() packersdk.Communicator {
+ return p.communicator
+}
+
+func (p *Provisioner) ElevatedUser() string {
+ return p.config.ElevatedUser
+}
+
+func (p *Provisioner) ElevatedPassword() string {
+ // Replace ElevatedPassword for winrm users who used this feature
+ p.config.ctx.Data = p.generatedData
+ elevatedPassword, _ := interpolate.Render(p.config.ElevatedPassword, &p.config.ctx)
+
+ return elevatedPassword
+}
diff --git a/v1.9.4/provisioner/powershell/provisioner.hcl2spec.go b/v1.9.4/provisioner/powershell/provisioner.hcl2spec.go
new file mode 100644
index 0000000..2cf0e26
--- /dev/null
+++ b/v1.9.4/provisioner/powershell/provisioner.hcl2spec.go
@@ -0,0 +1,87 @@
+// Code generated by "packer-sdc mapstructure-to-hcl2"; DO NOT EDIT.
+
+package powershell
+
+import (
+ "github.com/hashicorp/hcl/v2/hcldec"
+ "github.com/zclconf/go-cty/cty"
+)
+
+// FlatConfig is an auto-generated flat version of Config.
+// Where the contents of a field with a `mapstructure:,squash` tag are bubbled up.
+type FlatConfig struct {
+ PackerBuildName *string `mapstructure:"packer_build_name" cty:"packer_build_name" 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"`
+ Inline []string `cty:"inline" hcl:"inline"`
+ Script *string `cty:"script" hcl:"script"`
+ Scripts []string `cty:"scripts" hcl:"scripts"`
+ ValidExitCodes []int `mapstructure:"valid_exit_codes" cty:"valid_exit_codes" hcl:"valid_exit_codes"`
+ Vars []string `mapstructure:"environment_vars" cty:"environment_vars" hcl:"environment_vars"`
+ Env map[string]string `mapstructure:"env" cty:"env" hcl:"env"`
+ EnvVarFormat *string `mapstructure:"env_var_format" cty:"env_var_format" hcl:"env_var_format"`
+ Binary *bool `cty:"binary" hcl:"binary"`
+ RemotePath *string `mapstructure:"remote_path" cty:"remote_path" hcl:"remote_path"`
+ ExecuteCommand *string `mapstructure:"execute_command" cty:"execute_command" hcl:"execute_command"`
+ RemoteEnvVarPath *string `mapstructure:"remote_env_var_path" cty:"remote_env_var_path" hcl:"remote_env_var_path"`
+ ElevatedExecuteCommand *string `mapstructure:"elevated_execute_command" cty:"elevated_execute_command" hcl:"elevated_execute_command"`
+ SkipClean *bool `mapstructure:"skip_clean" cty:"skip_clean" hcl:"skip_clean"`
+ StartRetryTimeout *string `mapstructure:"start_retry_timeout" cty:"start_retry_timeout" hcl:"start_retry_timeout"`
+ ElevatedEnvVarFormat *string `mapstructure:"elevated_env_var_format" cty:"elevated_env_var_format" hcl:"elevated_env_var_format"`
+ ElevatedUser *string `mapstructure:"elevated_user" cty:"elevated_user" hcl:"elevated_user"`
+ ElevatedPassword *string `mapstructure:"elevated_password" cty:"elevated_password" hcl:"elevated_password"`
+ ExecutionPolicy *string `mapstructure:"execution_policy" cty:"execution_policy" hcl:"execution_policy"`
+ DebugMode *int `mapstructure:"debug_mode" cty:"debug_mode" hcl:"debug_mode"`
+ PauseAfter *string `mapstructure:"pause_after" cty:"pause_after" hcl:"pause_after"`
+ UsePwsh *bool `mapstructure:"use_pwsh" cty:"use_pwsh" hcl:"use_pwsh"`
+}
+
+// FlatMapstructure returns a new FlatConfig.
+// FlatConfig is an auto-generated flat version of Config.
+// Where the contents a fields with a `mapstructure:,squash` tag are bubbled up.
+func (*Config) FlatMapstructure() interface{ HCL2Spec() map[string]hcldec.Spec } {
+ return new(FlatConfig)
+}
+
+// HCL2Spec returns the hcl spec of a Config.
+// This spec is used by HCL to read the fields of Config.
+// The decoded values from this spec will then be applied to a FlatConfig.
+func (*FlatConfig) HCL2Spec() map[string]hcldec.Spec {
+ s := map[string]hcldec.Spec{
+ "packer_build_name": &hcldec.AttrSpec{Name: "packer_build_name", Type: cty.String, Required: false},
+ "packer_builder_type": &hcldec.AttrSpec{Name: "packer_builder_type", Type: cty.String, Required: false},
+ "packer_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_sensitive_variables": &hcldec.AttrSpec{Name: "packer_sensitive_variables", Type: cty.List(cty.String), Required: false},
+ "inline": &hcldec.AttrSpec{Name: "inline", Type: cty.List(cty.String), Required: false},
+ "script": &hcldec.AttrSpec{Name: "script", Type: cty.String, Required: false},
+ "scripts": &hcldec.AttrSpec{Name: "scripts", Type: cty.List(cty.String), Required: false},
+ "valid_exit_codes": &hcldec.AttrSpec{Name: "valid_exit_codes", Type: cty.List(cty.Number), Required: false},
+ "environment_vars": &hcldec.AttrSpec{Name: "environment_vars", Type: cty.List(cty.String), Required: false},
+ "env": &hcldec.AttrSpec{Name: "env", Type: cty.Map(cty.String), Required: false},
+ "env_var_format": &hcldec.AttrSpec{Name: "env_var_format", Type: cty.String, Required: false},
+ "binary": &hcldec.AttrSpec{Name: "binary", Type: cty.Bool, Required: false},
+ "remote_path": &hcldec.AttrSpec{Name: "remote_path", Type: cty.String, Required: false},
+ "execute_command": &hcldec.AttrSpec{Name: "execute_command", Type: cty.String, Required: false},
+ "remote_env_var_path": &hcldec.AttrSpec{Name: "remote_env_var_path", Type: cty.String, Required: false},
+ "elevated_execute_command": &hcldec.AttrSpec{Name: "elevated_execute_command", Type: cty.String, Required: false},
+ "skip_clean": &hcldec.AttrSpec{Name: "skip_clean", Type: cty.Bool, Required: false},
+ "start_retry_timeout": &hcldec.AttrSpec{Name: "start_retry_timeout", Type: cty.String, Required: false},
+ "elevated_env_var_format": &hcldec.AttrSpec{Name: "elevated_env_var_format", Type: cty.String, Required: false},
+ "elevated_user": &hcldec.AttrSpec{Name: "elevated_user", Type: cty.String, Required: false},
+ "elevated_password": &hcldec.AttrSpec{Name: "elevated_password", Type: cty.String, Required: false},
+ "execution_policy": &hcldec.AttrSpec{Name: "execution_policy", Type: cty.String, Required: false},
+ "debug_mode": &hcldec.AttrSpec{Name: "debug_mode", Type: cty.Number, Required: false},
+ "pause_after": &hcldec.AttrSpec{Name: "pause_after", Type: cty.String, Required: false},
+ "use_pwsh": &hcldec.AttrSpec{Name: "use_pwsh", Type: cty.Bool, Required: false},
+ }
+ return s
+}
diff --git a/v1.9.4/provisioner/powershell/provisioner_acc_test.go b/v1.9.4/provisioner/powershell/provisioner_acc_test.go
new file mode 100644
index 0000000..379b14f
--- /dev/null
+++ b/v1.9.4/provisioner/powershell/provisioner_acc_test.go
@@ -0,0 +1,113 @@
+// Copyright (c) HashiCorp, Inc.
+// SPDX-License-Identifier: MPL-2.0
+
+package powershell_test
+
+import (
+ "fmt"
+ "io/ioutil"
+ "os"
+ "os/exec"
+ "path/filepath"
+ "runtime"
+ "testing"
+
+ "github.com/hashicorp/packer-plugin-sdk/acctest/provisioneracc"
+)
+
+const TestProvisionerType = "powershell"
+
+func powershellIsCompatible(builder string, vmOS string) bool {
+ return vmOS == "windows"
+}
+
+func fixtureDir() string {
+ _, file, _, _ := runtime.Caller(0)
+ return filepath.Join(filepath.Dir(file), "test-fixtures")
+}
+
+func LoadProvisionerFragment(templateFragmentPath string) (string, error) {
+ dir := fixtureDir()
+ fragmentAbsPath := filepath.Join(dir, templateFragmentPath)
+ fragmentFile, err := os.Open(fragmentAbsPath)
+ if err != nil {
+ return "", fmt.Errorf("Unable find %s", fragmentAbsPath)
+ }
+ defer fragmentFile.Close()
+
+ fragmentString, err := ioutil.ReadAll(fragmentFile)
+ if err != nil {
+ return "", fmt.Errorf("Unable to read %s", fragmentAbsPath)
+ }
+
+ return string(fragmentString), nil
+}
+
+func TestAccPowershellProvisioner_basic(t *testing.T) {
+ templateString, err := LoadProvisionerFragment("powershell-provisioner-cleanup.txt")
+ if err != nil {
+ t.Fatalf("Couldn't load test fixture; %s", err.Error())
+ }
+ testCase := &provisioneracc.ProvisionerTestCase{
+ IsCompatible: powershellIsCompatible,
+ Name: "powershell-provisioner-cleanup",
+ Template: templateString,
+ Type: TestProvisionerType,
+ 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)
+ }
+ }
+ return nil
+ },
+ }
+
+ provisioneracc.TestProvisionersAgainstBuilders(testCase, t)
+}
+
+func TestAccPowershellProvisioner_Inline(t *testing.T) {
+ templateString, err := LoadProvisionerFragment("powershell-inline-provisioner.txt")
+ if err != nil {
+ t.Fatalf("Couldn't load test fixture; %s", err.Error())
+ }
+ testCase := &provisioneracc.ProvisionerTestCase{
+ IsCompatible: powershellIsCompatible,
+ Name: "powershell-provisioner-inline",
+ Template: templateString,
+ Type: TestProvisionerType,
+ 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)
+ }
+ }
+ return nil
+ },
+ }
+
+ provisioneracc.TestProvisionersAgainstBuilders(testCase, t)
+}
+
+func TestAccPowershellProvisioner_Script(t *testing.T) {
+ templateString, err := LoadProvisionerFragment("powershell-script-provisioner.txt")
+ if err != nil {
+ t.Fatalf("Couldn't load test fixture; %s", err.Error())
+ }
+ testCase := &provisioneracc.ProvisionerTestCase{
+ IsCompatible: powershellIsCompatible,
+ Name: "powershell-provisioner-script",
+ Template: templateString,
+ Type: TestProvisionerType,
+ 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)
+ }
+ }
+ return nil
+ },
+ }
+
+ provisioneracc.TestProvisionersAgainstBuilders(testCase, t)
+}
diff --git a/v1.9.4/provisioner/powershell/provisioner_test.go b/v1.9.4/provisioner/powershell/provisioner_test.go
new file mode 100644
index 0000000..d94a56f
--- /dev/null
+++ b/v1.9.4/provisioner/powershell/provisioner_test.go
@@ -0,0 +1,979 @@
+// Copyright (c) HashiCorp, Inc.
+// SPDX-License-Identifier: MPL-2.0
+
+package powershell
+
+import (
+ "bytes"
+ "context"
+ "fmt"
+ "io/ioutil"
+ "os"
+ "regexp"
+ "strings"
+ "testing"
+ "time"
+
+ "github.com/hashicorp/packer-plugin-sdk/common"
+ "github.com/hashicorp/packer-plugin-sdk/multistep/commonsteps"
+ packersdk "github.com/hashicorp/packer-plugin-sdk/packer"
+ "github.com/stretchr/testify/assert"
+)
+
+func TestProvisionerPrepare_extractScript(t *testing.T) {
+ config := testConfig()
+ p := new(Provisioner)
+ _ = p.Prepare(config)
+ file, err := extractScript(p)
+ defer os.Remove(file)
+ if err != nil {
+ t.Fatalf("Should not be error: %s", err)
+ }
+ t.Logf("File: %s", file)
+ if strings.Index(file, os.TempDir()) != 0 {
+ t.Fatalf("Temp file should reside in %s. File location: %s", os.TempDir(), file)
+ }
+
+ // File contents should contain 2 lines concatenated by newlines: foo\nbar
+ readFile, err := ioutil.ReadFile(file)
+ expectedContents := "foo\nbar\n"
+ if err != nil {
+ t.Fatalf("Should not be error: %s", err)
+ }
+ s := string(readFile[:])
+ if s != expectedContents {
+ t.Fatalf("Expected generated inlineScript to equal '%s', got '%s'", expectedContents, s)
+ }
+}
+
+func TestProvisioner_Impl(t *testing.T) {
+ var raw interface{}
+ raw = &Provisioner{}
+ if _, ok := raw.(packersdk.Provisioner); !ok {
+ t.Fatalf("must be a Provisioner")
+ }
+}
+
+func TestProvisionerPrepare_Defaults(t *testing.T) {
+ var p Provisioner
+ config := testConfig()
+
+ err := p.Prepare(config)
+ if err != nil {
+ t.Fatalf("err: %s", err)
+ }
+
+ matched, _ := regexp.MatchString("c:/Windows/Temp/script-.*.ps1", p.config.RemotePath)
+ if !matched {
+ t.Errorf("unexpected remote path: %s", p.config.RemotePath)
+ }
+
+ if p.config.ElevatedUser != "" {
+ t.Error("expected elevated_user to be empty")
+ }
+ if p.config.ElevatedPassword != "" {
+ t.Error("expected elevated_password to be empty")
+ }
+
+ if p.config.ExecuteCommand != `powershell -executionpolicy bypass "& { if (Test-Path variable:global:ProgressPreference){set-variable -name variable:global:ProgressPreference -value 'SilentlyContinue'};. {{.Vars}}; &'{{.Path}}'; exit $LastExitCode }"` {
+ t.Fatalf(`Default command should be 'powershell -executionpolicy bypass "& { if (Test-Path variable:global:ProgressPreference){set-variable -name variable:global:ProgressPreference -value 'SilentlyContinue'};. {{.Vars}}; &'{{.Path}}'; exit $LastExitCode }"', but got '%s'`, p.config.ExecuteCommand)
+ }
+
+ if p.config.ElevatedExecuteCommand != `powershell -executionpolicy bypass "& { if (Test-Path variable:global:ProgressPreference){set-variable -name variable:global:ProgressPreference -value 'SilentlyContinue'};. {{.Vars}}; &'{{.Path}}'; exit $LastExitCode }"` {
+ t.Fatalf(`Default command should be 'powershell -executionpolicy bypass "& { if (Test-Path variable:global:ProgressPreference){set-variable -name variable:global:ProgressPreference -value 'SilentlyContinue'};. {{.Vars}}; &'{{.Path}}'; exit $LastExitCode }"', but got '%s'`, p.config.ElevatedExecuteCommand)
+ }
+
+ if p.config.ElevatedEnvVarFormat != `$env:%s="%s"; ` {
+ t.Fatalf(`Default command should be powershell '$env:%%s="%%s"; ', but got %s`, p.config.ElevatedEnvVarFormat)
+ }
+}
+
+func TestProvisionerPrepare_Config(t *testing.T) {
+ config := testConfig()
+ config["elevated_user"] = "{{user `user`}}"
+ config["elevated_password"] = "{{user `password`}}"
+ config[common.UserVariablesConfigKey] = map[string]string{
+ "user": "myusername",
+ "password": "mypassword",
+ }
+
+ var p Provisioner
+ err := p.Prepare(config)
+ if err != nil {
+ t.Fatalf("err: %s", err)
+ }
+
+ if p.config.ElevatedUser != "myusername" {
+ t.Fatalf("Expected 'myusername' for key `elevated_user`: %s", p.config.ElevatedUser)
+ }
+ if p.config.ElevatedPassword != "mypassword" {
+ t.Fatalf("Expected 'mypassword' for key `elevated_password`: %s", p.config.ElevatedPassword)
+ }
+}
+
+func TestProvisionerPrepare_DebugMode(t *testing.T) {
+ config := testConfig()
+ config["debug_mode"] = 1
+
+ var p Provisioner
+ err := p.Prepare(config)
+ if err != nil {
+ t.Fatalf("err: %s", err)
+ }
+
+ command := `powershell -executionpolicy bypass "& { if (Test-Path variable:global:ProgressPreference){set-variable -name variable:global:ProgressPreference -value 'SilentlyContinue'};Set-PsDebug -Trace 1;. {{.Vars}}; &'{{.Path}}'; exit $LastExitCode }"`
+ if p.config.ExecuteCommand != command {
+ t.Fatalf(fmt.Sprintf(`Expected command should be '%s' but got '%s'`, command, p.config.ExecuteCommand))
+ }
+}
+
+func TestProvisionerPrepare_InvalidDebugMode(t *testing.T) {
+ config := testConfig()
+ config["debug_mode"] = -1
+
+ var p Provisioner
+ err := p.Prepare(config)
+ if err == nil {
+ t.Fatalf("should have error")
+ }
+
+ message := "invalid Trace level for `debug_mode`; valid values are 0, 1, and 2"
+ if !strings.Contains(err.Error(), message) {
+ t.Fatalf("expected Prepare() error %q to contain %q", err.Error(), message)
+ }
+}
+
+func TestProvisionerPrepare_InvalidKey(t *testing.T) {
+ var p Provisioner
+ config := testConfig()
+
+ // Add a random key
+ config["i_should_not_be_valid"] = true
+ err := p.Prepare(config)
+ if err == nil {
+ t.Fatal("should have error")
+ }
+}
+
+func TestProvisionerPrepare_Elevated(t *testing.T) {
+ var p Provisioner
+ config := testConfig()
+
+ // Add a random key
+ config["elevated_user"] = "vagrant"
+ err := p.Prepare(config)
+
+ if err != nil {
+ t.Fatal("should not have error")
+ }
+
+ config["elevated_password"] = "vagrant"
+ err = p.Prepare(config)
+
+ if err != nil {
+ t.Fatal("should not have error")
+ }
+}
+
+func TestProvisionerPrepare_Script(t *testing.T) {
+ config := testConfig()
+ delete(config, "inline")
+
+ config["script"] = "/this/should/not/exist"
+ p := new(Provisioner)
+ err := p.Prepare(config)
+ if err == nil {
+ t.Fatal("should have error")
+ }
+
+ // Test with a good one
+ tf, err := ioutil.TempFile("", "packer")
+ if err != nil {
+ t.Fatalf("error tempfile: %s", err)
+ }
+ defer os.Remove(tf.Name())
+ defer tf.Close()
+
+ config["script"] = tf.Name()
+ p = new(Provisioner)
+ err = p.Prepare(config)
+ if err != nil {
+ t.Fatalf("should not have error: %s", err)
+ }
+}
+
+func TestProvisionerPrepare_ScriptAndInline(t *testing.T) {
+ var p Provisioner
+ config := testConfig()
+
+ delete(config, "inline")
+ delete(config, "script")
+ err := p.Prepare(config)
+ if err == nil {
+ t.Fatal("should have error")
+ }
+
+ // Test with both
+ tf, err := ioutil.TempFile("", "packer")
+ if err != nil {
+ t.Fatalf("error tempfile: %s", err)
+ }
+ defer os.Remove(tf.Name())
+ defer tf.Close()
+
+ config["inline"] = []interface{}{"foo"}
+ config["script"] = tf.Name()
+ err = p.Prepare(config)
+ if err == nil {
+ t.Fatal("should have error")
+ }
+}
+
+func TestProvisionerPrepare_ScriptAndScripts(t *testing.T) {
+ var p Provisioner
+ config := testConfig()
+
+ // Test with both
+ tf, err := ioutil.TempFile("", "packer")
+ if err != nil {
+ t.Fatalf("error tempfile: %s", err)
+ }
+ defer os.Remove(tf.Name())
+ defer tf.Close()
+
+ config["inline"] = []interface{}{"foo"}
+ config["scripts"] = []string{tf.Name()}
+ err = p.Prepare(config)
+ if err == nil {
+ t.Fatal("should have error")
+ }
+}
+
+func TestProvisionerPrepare_Scripts(t *testing.T) {
+ config := testConfig()
+ delete(config, "inline")
+
+ config["scripts"] = []string{}
+ p := new(Provisioner)
+ err := p.Prepare(config)
+ if err == nil {
+ t.Fatal("should have error")
+ }
+
+ // Test with a good one
+ tf, err := ioutil.TempFile("", "packer")
+ if err != nil {
+ t.Fatalf("error tempfile: %s", err)
+ }
+ defer os.Remove(tf.Name())
+ defer tf.Close()
+
+ config["scripts"] = []string{tf.Name()}
+ p = new(Provisioner)
+ err = p.Prepare(config)
+ if err != nil {
+ t.Fatalf("should not have error: %s", err)
+ }
+}
+
+func TestProvisionerPrepare_Pwsh(t *testing.T) {
+
+ config := testConfig()
+
+ config["use_pwsh"] = true
+
+ p := new(Provisioner)
+ err := p.Prepare(config)
+
+ if err != nil {
+ t.Fatalf("Should not be error: %s", err)
+ }
+
+ if !p.config.UsePwsh {
+ t.Fatalf("Expected 'pwsh' to be: true")
+ }
+}
+
+func TestProvisionerPrepare_EnvironmentVars(t *testing.T) {
+ config := testConfig()
+
+ // Test with a bad case
+ config["environment_vars"] = []string{"badvar", "good=var"}
+ p := new(Provisioner)
+ err := p.Prepare(config)
+ if err == nil {
+ t.Fatal("should have error")
+ }
+
+ // Test with a trickier case
+ config["environment_vars"] = []string{"=bad"}
+ p = new(Provisioner)
+ err = p.Prepare(config)
+ if err == nil {
+ t.Fatal("should have error")
+ }
+
+ // Test with a good case
+ // Note: baz= is a real env variable, just empty
+ config["environment_vars"] = []string{"FOO=bar", "baz="}
+ p = new(Provisioner)
+ err = p.Prepare(config)
+ if err != nil {
+ t.Fatalf("should not have error: %s", err)
+ }
+
+ // Test when the env variable value contains an equals sign
+ config["environment_vars"] = []string{"good=withequals=true"}
+ p = new(Provisioner)
+ err = p.Prepare(config)
+ if err != nil {
+ t.Fatalf("should not have error: %s", err)
+ }
+
+ // Test when the env variable value starts with an equals sign
+ config["environment_vars"] = []string{"good==true"}
+ p = new(Provisioner)
+ err = p.Prepare(config)
+ if err != nil {
+ t.Fatalf("should not have error: %s", err)
+ }
+
+}
+
+func TestProvisionerQuote_EnvironmentVars(t *testing.T) {
+ config := testConfig()
+
+ config["environment_vars"] = []string{
+ "keyone=valueone",
+ "keytwo=value\ntwo",
+ "keythree='valuethree'",
+ "keyfour='value\nfour'",
+ "keyfive='value=five'",
+ "keysix='=six'",
+ }
+
+ expected := []string{
+ "keyone=valueone",
+ "keytwo=value\ntwo",
+ "keythree='valuethree'",
+ "keyfour='value\nfour'",
+ "keyfive='value=five'",
+ "keysix='=six'",
+ }
+
+ p := new(Provisioner)
+ p.Prepare(config)
+
+ for i, expectedValue := range expected {
+ if p.config.Vars[i] != expectedValue {
+ t.Fatalf("%s should be equal to %s", p.config.Vars[i], expectedValue)
+ }
+ }
+}
+
+func testUi() *packersdk.BasicUi {
+ return &packersdk.BasicUi{
+ Reader: new(bytes.Buffer),
+ Writer: new(bytes.Buffer),
+ ErrorWriter: new(bytes.Buffer),
+ }
+}
+
+func TestProvisionerProvision_ValidExitCodes(t *testing.T) {
+ config := testConfig()
+ delete(config, "inline")
+
+ // Defaults provided by Packer
+ config["remote_path"] = "c:/Windows/Temp/inlineScript.ps1"
+ config["inline"] = []string{"whoami"}
+ ui := testUi()
+ p := new(Provisioner)
+
+ // Defaults provided by Packer
+ p.config.PackerBuildName = "vmware"
+ p.config.PackerBuilderType = "iso"
+ p.config.ValidExitCodes = []int{0, 200}
+ comm := new(packersdk.MockCommunicator)
+ comm.StartExitStatus = 200
+ p.Prepare(config)
+ err := p.Provision(context.Background(), ui, comm, generatedData())
+ if err != nil {
+ t.Fatal("should not have error")
+ }
+}
+
+func TestProvisionerProvision_PauseAfter(t *testing.T) {
+ config := testConfig()
+ delete(config, "inline")
+
+ // Defaults provided by Packer
+ config["remote_path"] = "c:/Windows/Temp/inlineScript.ps1"
+ config["inline"] = []string{"whoami"}
+ ui := testUi()
+ p := new(Provisioner)
+
+ // Defaults provided by Packer
+ p.config.PackerBuildName = "vmware"
+ p.config.PackerBuilderType = "iso"
+ p.config.ValidExitCodes = []int{0, 200}
+ pause_amount := time.Second
+ p.config.PauseAfter = pause_amount
+ comm := new(packersdk.MockCommunicator)
+ comm.StartExitStatus = 200
+ err := p.Prepare(config)
+ if err != nil {
+ t.Fatalf("Prepar failed: %s", err)
+ }
+
+ start_time := time.Now()
+ err = p.Provision(context.Background(), ui, comm, generatedData())
+ end_time := time.Now()
+
+ if err != nil {
+ t.Fatal("should not have error")
+ }
+
+ if end_time.Sub(start_time) < pause_amount {
+ t.Fatal("Didn't wait pause_amount")
+ }
+}
+
+func TestProvisionerProvision_InvalidExitCodes(t *testing.T) {
+ config := testConfig()
+ delete(config, "inline")
+
+ // Defaults provided by Packer
+ config["remote_path"] = "c:/Windows/Temp/inlineScript.ps1"
+ config["inline"] = []string{"whoami"}
+ ui := testUi()
+ p := new(Provisioner)
+
+ // Defaults provided by Packer
+ p.config.PackerBuildName = "vmware"
+ p.config.PackerBuilderType = "iso"
+ p.config.ValidExitCodes = []int{0, 200}
+ comm := new(packersdk.MockCommunicator)
+ comm.StartExitStatus = 201 // Invalid!
+ p.Prepare(config)
+ err := p.Provision(context.Background(), ui, comm, generatedData())
+ if err == nil {
+ t.Fatal("should have error")
+ }
+}
+
+func TestProvisionerProvision_Inline(t *testing.T) {
+ // skip_clean is set to true otherwise the last command executed by the provisioner is the cleanup.
+ config := testConfigWithSkipClean()
+ delete(config, "inline")
+
+ // Defaults provided by Packer
+ config["remote_path"] = "c:/Windows/Temp/inlineScript.ps1"
+ config["inline"] = []string{"whoami"}
+ ui := testUi()
+ p := new(Provisioner)
+
+ // Defaults provided by Packer - env vars should not appear in cmd
+ p.config.PackerBuildName = "vmware"
+ p.config.PackerBuilderType = "iso"
+ comm := new(packersdk.MockCommunicator)
+ _ = p.Prepare(config)
+
+ err := p.Provision(context.Background(), ui, comm, generatedData())
+ if err != nil {
+ t.Fatal("should not have error")
+ }
+
+ cmd := comm.StartCmd.Command
+ re := regexp.MustCompile(`powershell -executionpolicy bypass "& { if \(Test-Path variable:global:ProgressPreference\){set-variable -name variable:global:ProgressPreference -value 'SilentlyContinue'};\. c:/Windows/Temp/packer-ps-env-vars-[[:alnum:]]{8}-[[:alnum:]]{4}-[[:alnum:]]{4}-[[:alnum:]]{4}-[[:alnum:]]{12}\.ps1; &'c:/Windows/Temp/inlineScript.ps1'; exit \$LastExitCode }"`)
+ matched := re.MatchString(cmd)
+ if !matched {
+ t.Fatalf("Got unexpected command: %s", cmd)
+ }
+
+ // User supplied env vars should not change things
+ envVars := make([]string, 2)
+ envVars[0] = "FOO=BAR"
+ envVars[1] = "BAR=BAZ"
+ config["environment_vars"] = envVars
+ config["remote_path"] = "c:/Windows/Temp/inlineScript.ps1"
+
+ p.Prepare(config)
+ err = p.Provision(context.Background(), ui, comm, generatedData())
+ if err != nil {
+ t.Fatal("should not have error")
+ }
+
+ cmd = comm.StartCmd.Command
+ re = regexp.MustCompile(`powershell -executionpolicy bypass "& { if \(Test-Path variable:global:ProgressPreference\){set-variable -name variable:global:ProgressPreference -value 'SilentlyContinue'};\. c:/Windows/Temp/packer-ps-env-vars-[[:alnum:]]{8}-[[:alnum:]]{4}-[[:alnum:]]{4}-[[:alnum:]]{4}-[[:alnum:]]{12}\.ps1; &'c:/Windows/Temp/inlineScript.ps1'; exit \$LastExitCode }"`)
+ matched = re.MatchString(cmd)
+ if !matched {
+ t.Fatalf("Got unexpected command: %s", cmd)
+ }
+}
+
+func TestProvisionerProvision_Scripts(t *testing.T) {
+ tempFile, _ := ioutil.TempFile("", "packer")
+ defer os.Remove(tempFile.Name())
+ defer tempFile.Close()
+
+ // skip_clean is set to true otherwise the last command executed by the provisioner is the cleanup.
+ config := testConfigWithSkipClean()
+ delete(config, "inline")
+ config["scripts"] = []string{tempFile.Name()}
+ config["packer_build_name"] = "foobuild"
+ config["packer_builder_type"] = "footype"
+ config["remote_path"] = "c:/Windows/Temp/script.ps1"
+ ui := testUi()
+
+ p := new(Provisioner)
+ comm := new(packersdk.MockCommunicator)
+ p.Prepare(config)
+ err := p.Provision(context.Background(), ui, comm, generatedData())
+ if err != nil {
+ t.Fatal("should not have error")
+ }
+
+ cmd := comm.StartCmd.Command
+ re := regexp.MustCompile(`powershell -executionpolicy bypass "& { if \(Test-Path variable:global:ProgressPreference\){set-variable -name variable:global:ProgressPreference -value 'SilentlyContinue'};\. c:/Windows/Temp/packer-ps-env-vars-[[:alnum:]]{8}-[[:alnum:]]{4}-[[:alnum:]]{4}-[[:alnum:]]{4}-[[:alnum:]]{12}\.ps1; &'c:/Windows/Temp/script.ps1'; exit \$LastExitCode }"`)
+ matched := re.MatchString(cmd)
+ if !matched {
+ t.Fatalf("Got unexpected command: %s", cmd)
+ }
+}
+
+func TestProvisionerProvision_ScriptsWithEnvVars(t *testing.T) {
+ tempFile, _ := ioutil.TempFile("", "packer")
+ ui := testUi()
+ defer os.Remove(tempFile.Name())
+ defer tempFile.Close()
+
+ // skip_clean is set to true otherwise the last command executed by the provisioner is the cleanup.
+ config := testConfigWithSkipClean()
+ delete(config, "inline")
+
+ config["scripts"] = []string{tempFile.Name()}
+ config["packer_build_name"] = "foobuild"
+ config["packer_builder_type"] = "footype"
+
+ // Env vars - currently should not effect them
+ envVars := make([]string, 2)
+ envVars[0] = "FOO=BAR"
+ envVars[1] = "BAR=BAZ"
+ config["environment_vars"] = envVars
+ config["remote_path"] = "c:/Windows/Temp/script.ps1"
+
+ p := new(Provisioner)
+ comm := new(packersdk.MockCommunicator)
+ p.Prepare(config)
+ err := p.Provision(context.Background(), ui, comm, generatedData())
+ if err != nil {
+ t.Fatal("should not have error")
+ }
+
+ cmd := comm.StartCmd.Command
+ re := regexp.MustCompile(`powershell -executionpolicy bypass "& { if \(Test-Path variable:global:ProgressPreference\){set-variable -name variable:global:ProgressPreference -value 'SilentlyContinue'};\. c:/Windows/Temp/packer-ps-env-vars-[[:alnum:]]{8}-[[:alnum:]]{4}-[[:alnum:]]{4}-[[:alnum:]]{4}-[[:alnum:]]{12}\.ps1; &'c:/Windows/Temp/script.ps1'; exit \$LastExitCode }"`)
+ matched := re.MatchString(cmd)
+ if !matched {
+ t.Fatalf("Got unexpected command: %s", cmd)
+ }
+}
+
+func TestProvisionerProvision_SkipClean(t *testing.T) {
+ tempFile, _ := ioutil.TempFile("", "packer")
+ defer func() {
+ tempFile.Close()
+ os.Remove(tempFile.Name())
+ }()
+
+ config := map[string]interface{}{
+ "scripts": []string{tempFile.Name()},
+ "remote_path": "c:/Windows/Temp/script.ps1",
+ }
+
+ tt := []struct {
+ SkipClean bool
+ LastExecutedCommandRegex string
+ }{
+ {
+ SkipClean: true,
+ LastExecutedCommandRegex: `powershell -executionpolicy bypass "& { if \(Test-Path variable:global:ProgressPreference\){set-variable -name variable:global:ProgressPreference -value 'SilentlyContinue'};\. c:/Windows/Temp/packer-ps-env-vars-[[:alnum:]]{8}-[[:alnum:]]{4}-[[:alnum:]]{4}-[[:alnum:]]{4}-[[:alnum:]]{12}\.ps1; &'c:/Windows/Temp/script.ps1'; exit \$LastExitCode }"`,
+ },
+ {
+ SkipClean: false,
+ LastExecutedCommandRegex: `powershell -executionpolicy bypass "& { if \(Test-Path variable:global:ProgressPreference\){set-variable -name variable:global:ProgressPreference -value 'SilentlyContinue'};\. c:/Windows/Temp/packer-ps-env-vars-[[:alnum:]]{8}-[[:alnum:]]{4}-[[:alnum:]]{4}-[[:alnum:]]{4}-[[:alnum:]]{12}\.ps1; &'c:/Windows/Temp/packer-cleanup-[[:alnum:]]{8}-[[:alnum:]]{4}-[[:alnum:]]{4}-[[:alnum:]]{4}-[[:alnum:]]{12}\.ps1'; exit \$LastExitCode }"`,
+ },
+ }
+
+ for _, tc := range tt {
+ tc := tc
+ p := new(Provisioner)
+ ui := testUi()
+ comm := new(packersdk.MockCommunicator)
+
+ config["skip_clean"] = tc.SkipClean
+ if err := p.Prepare(config); err != nil {
+ t.Fatalf("failed to prepare config when SkipClean is %t: %s", tc.SkipClean, err)
+ }
+ err := p.Provision(context.Background(), ui, comm, generatedData())
+ if err != nil {
+ t.Fatal("should not have error")
+ }
+
+ // When SkipClean is false the last executed command should be the clean up command;
+ // otherwise it will be the execution command for the provisioning script.
+ cmd := comm.StartCmd.Command
+ re := regexp.MustCompile(tc.LastExecutedCommandRegex)
+ matched := re.MatchString(cmd)
+ if !matched {
+ t.Fatalf(`Got unexpected command when SkipClean is %t: %s`, tc.SkipClean, cmd)
+ }
+ }
+}
+
+func TestProvisionerProvision_UploadFails(t *testing.T) {
+ config := testConfig()
+ ui := testUi()
+
+ p := new(Provisioner)
+ comm := new(packersdk.ScriptUploadErrorMockCommunicator)
+ p.Prepare(config)
+ p.config.StartRetryTimeout = 1 * time.Second
+ err := p.Provision(context.Background(), ui, comm, generatedData())
+ if !strings.Contains(err.Error(), packersdk.ScriptUploadErrorMockCommunicatorError.Error()) {
+ t.Fatalf("expected Provision() error %q to contain %q",
+ err.Error(),
+ packersdk.ScriptUploadErrorMockCommunicatorError.Error())
+ }
+}
+
+func TestProvisioner_createFlattenedElevatedEnvVars_windows(t *testing.T) {
+ var flattenedEnvVars string
+ config := testConfig()
+
+ userEnvVarTests := [][]string{
+ {}, // No user env var
+ {"FOO=bar"}, // Single user env var
+ {"FOO=bar", "BAZ=qux"}, // Multiple user env vars
+ {"FOO=bar=baz"}, // User env var with value containing equals
+ {"FOO==bar"}, // User env var with value starting with equals
+ // Test escaping of characters special to PowerShell
+ {"FOO=bar$baz"}, // User env var with value containing dollar
+ {"FOO=bar\"baz"}, // User env var with value containing a double quote
+ {"FOO=bar'baz"}, // User env var with value containing a single quote
+ {"FOO=bar`baz"}, // User env var with value containing a backtick
+
+ }
+ userEnvVarmapTests := []map[string]string{
+ {},
+ {
+ "BAR": "foo",
+ },
+ {
+ "BAR": "foo",
+ "YAR": "yaa",
+ },
+ {
+ "BAR": "foo=yaa",
+ },
+ {
+ "BAR": "=foo",
+ },
+ {
+ "BAR": "foo$yaa",
+ },
+ {
+ "BAR": "foo\"yaa",
+ },
+ {
+ "BAR": "foo'yaa",
+ },
+ {
+ "BAR": "foo`yaa",
+ },
+ }
+ expected := []string{
+ `$env:PACKER_BUILDER_TYPE="iso"; $env:PACKER_BUILD_NAME="vmware"; `,
+ `$env:BAR="foo"; $env:FOO="bar"; $env:PACKER_BUILDER_TYPE="iso"; $env:PACKER_BUILD_NAME="vmware"; `,
+ `$env:BAR="foo"; $env:BAZ="qux"; $env:FOO="bar"; $env:PACKER_BUILDER_TYPE="iso"; $env:PACKER_BUILD_NAME="vmware"; $env:YAR="yaa"; `,
+ `$env:BAR="foo=yaa"; $env:FOO="bar=baz"; $env:PACKER_BUILDER_TYPE="iso"; $env:PACKER_BUILD_NAME="vmware"; `,
+ `$env:BAR="=foo"; $env:FOO="=bar"; $env:PACKER_BUILDER_TYPE="iso"; $env:PACKER_BUILD_NAME="vmware"; `,
+ "$env:BAR=\"foo`$yaa\"; $env:FOO=\"bar`$baz\"; $env:PACKER_BUILDER_TYPE=\"iso\"; $env:PACKER_BUILD_NAME=\"vmware\"; ",
+ "$env:BAR=\"foo`\"yaa\"; $env:FOO=\"bar`\"baz\"; $env:PACKER_BUILDER_TYPE=\"iso\"; $env:PACKER_BUILD_NAME=\"vmware\"; ",
+ "$env:BAR=\"foo`'yaa\"; $env:FOO=\"bar`'baz\"; $env:PACKER_BUILDER_TYPE=\"iso\"; $env:PACKER_BUILD_NAME=\"vmware\"; ",
+ "$env:BAR=\"foo``yaa\"; $env:FOO=\"bar``baz\"; $env:PACKER_BUILDER_TYPE=\"iso\"; $env:PACKER_BUILD_NAME=\"vmware\"; ",
+ }
+
+ p := new(Provisioner)
+ p.generatedData = generatedData()
+ p.Prepare(config)
+
+ // Defaults provided by Packer
+ p.config.PackerBuildName = "vmware"
+ p.config.PackerBuilderType = "iso"
+
+ for i, expectedValue := range expected {
+ p.config.Vars = userEnvVarTests[i]
+ p.config.Env = userEnvVarmapTests[i]
+ flattenedEnvVars = p.createFlattenedEnvVars(true)
+ if flattenedEnvVars != expectedValue {
+ t.Fatalf("expected flattened env vars to be: %s, got %s.", expectedValue, flattenedEnvVars)
+ }
+ }
+}
+
+func TestProvisionerCorrectlyInterpolatesValidExitCodes(t *testing.T) {
+ type testCases struct {
+ Input interface{}
+ Expected []int
+ }
+ validExitCodeTests := []testCases{
+ {"0", []int{0}},
+ {[]string{"0"}, []int{0}},
+ {[]int{0, 12345}, []int{0, 12345}},
+ {[]string{"0", "12345"}, []int{0, 12345}},
+ {"0,12345", []int{0, 12345}},
+ }
+
+ for _, tc := range validExitCodeTests {
+ p := new(Provisioner)
+ config := testConfig()
+ config["valid_exit_codes"] = tc.Input
+ err := p.Prepare(config)
+
+ if err != nil {
+ t.Fatalf("Shouldn't have had error interpolating exit codes")
+ }
+ assert.ElementsMatchf(t, p.config.ValidExitCodes, tc.Expected,
+ fmt.Sprintf("expected exit codes to be: %#v, got %#v.", p.config.ValidExitCodes, tc.Expected))
+ }
+}
+
+func TestProvisionerCorrectlyInterpolatesExecutionPolicy(t *testing.T) {
+ type testCases struct {
+ Input interface{}
+ Expected ExecutionPolicy
+ ErrExpected bool
+ }
+ tests := []testCases{
+ {
+ Input: "bypass",
+ Expected: ExecutionPolicy(0),
+ ErrExpected: false,
+ },
+ {
+ Input: "allsigned",
+ Expected: ExecutionPolicy(1),
+ ErrExpected: false,
+ },
+ {
+ Input: "default",
+ Expected: ExecutionPolicy(2),
+ ErrExpected: false,
+ },
+ {
+ Input: "remotesigned",
+ Expected: ExecutionPolicy(3),
+ ErrExpected: false,
+ },
+ {
+ Input: "restricted",
+ Expected: ExecutionPolicy(4),
+ ErrExpected: false,
+ },
+ {
+ Input: "undefined",
+ Expected: ExecutionPolicy(5),
+ ErrExpected: false,
+ },
+ {
+ Input: "unrestricted",
+ Expected: ExecutionPolicy(6),
+ ErrExpected: false,
+ },
+ {
+ Input: "none",
+ Expected: ExecutionPolicy(7),
+ ErrExpected: false,
+ },
+ {
+ Input: "0", // User can supply a valid number for policy, too
+ Expected: 0,
+ ErrExpected: false,
+ },
+ {
+ Input: "invalid",
+ Expected: 0,
+ ErrExpected: true,
+ },
+ {
+ Input: "100", // If number is invalid policy, reject.
+ Expected: 100,
+ ErrExpected: true,
+ },
+ }
+
+ for _, tc := range tests {
+ p := new(Provisioner)
+ config := testConfig()
+ config["execution_policy"] = tc.Input
+ err := p.Prepare(config)
+
+ if (err != nil) != tc.ErrExpected {
+ t.Fatalf("Either err was expected, or shouldn't have happened: %#v", tc)
+ }
+ if err == nil {
+ assert.Equal(t, p.config.ExecutionPolicy, tc.Expected,
+ fmt.Sprintf("expected %#v, got %#v.", p.config.ExecutionPolicy, tc.Expected))
+ }
+ }
+}
+
+func TestProvisioner_createFlattenedEnvVars_windows(t *testing.T) {
+ var flattenedEnvVars string
+ config := testConfig()
+
+ userEnvVarTests := [][]string{
+ {}, // No user env var
+ {"FOO=bar"}, // Single user env var
+ {"FOO=bar", "BAZ=qux"}, // Multiple user env vars
+ {"FOO=bar=baz"}, // User env var with value containing equals
+ {"FOO==bar"}, // User env var with value starting with equals
+ // Test escaping of characters special to PowerShell
+ {"FOO=bar$baz"}, // User env var with value containing dollar
+ {"FOO=bar\"baz"}, // User env var with value containing a double quote
+ {"FOO=bar'baz"}, // User env var with value containing a single quote
+ {"FOO=bar`baz"}, // User env var with value containing a backtick
+ }
+ userEnvVarmapTests := []map[string]string{
+ {},
+ {
+ "BAR": "foo",
+ },
+ {
+ "BAR": "foo",
+ "YAR": "yaa",
+ },
+ {
+ "BAR": "foo=yaa",
+ },
+ {
+ "BAR": "=foo",
+ },
+ {
+ "BAR": "foo$yaa",
+ },
+ {
+ "BAR": "foo\"yaa",
+ },
+ {
+ "BAR": "foo'yaa",
+ },
+ {
+ "BAR": "foo`yaa",
+ },
+ }
+ expected := []string{
+ `$env:PACKER_BUILDER_TYPE="iso"; $env:PACKER_BUILD_NAME="vmware"; `,
+ `$env:BAR="foo"; $env:FOO="bar"; $env:PACKER_BUILDER_TYPE="iso"; $env:PACKER_BUILD_NAME="vmware"; `,
+ `$env:BAR="foo"; $env:BAZ="qux"; $env:FOO="bar"; $env:PACKER_BUILDER_TYPE="iso"; $env:PACKER_BUILD_NAME="vmware"; $env:YAR="yaa"; `,
+ `$env:BAR="foo=yaa"; $env:FOO="bar=baz"; $env:PACKER_BUILDER_TYPE="iso"; $env:PACKER_BUILD_NAME="vmware"; `,
+ `$env:BAR="=foo"; $env:FOO="=bar"; $env:PACKER_BUILDER_TYPE="iso"; $env:PACKER_BUILD_NAME="vmware"; `,
+ "$env:BAR=\"foo`$yaa\"; $env:FOO=\"bar`$baz\"; $env:PACKER_BUILDER_TYPE=\"iso\"; $env:PACKER_BUILD_NAME=\"vmware\"; ",
+ "$env:BAR=\"foo`\"yaa\"; $env:FOO=\"bar`\"baz\"; $env:PACKER_BUILDER_TYPE=\"iso\"; $env:PACKER_BUILD_NAME=\"vmware\"; ",
+ "$env:BAR=\"foo`'yaa\"; $env:FOO=\"bar`'baz\"; $env:PACKER_BUILDER_TYPE=\"iso\"; $env:PACKER_BUILD_NAME=\"vmware\"; ",
+ "$env:BAR=\"foo``yaa\"; $env:FOO=\"bar``baz\"; $env:PACKER_BUILDER_TYPE=\"iso\"; $env:PACKER_BUILD_NAME=\"vmware\"; ",
+ }
+
+ p := new(Provisioner)
+ p.generatedData = generatedData()
+ p.Prepare(config)
+
+ // Defaults provided by Packer
+ p.config.PackerBuildName = "vmware"
+ p.config.PackerBuilderType = "iso"
+
+ for i, expectedValue := range expected {
+ p.config.Vars = userEnvVarTests[i]
+ p.config.Env = userEnvVarmapTests[i]
+ flattenedEnvVars = p.createFlattenedEnvVars(false)
+ if flattenedEnvVars != expectedValue {
+ t.Fatalf("expected flattened env vars to be: %s, got %s.", expectedValue, flattenedEnvVars)
+ }
+ }
+}
+
+func TestProvision_createCommandText(t *testing.T) {
+ config := testConfig()
+ config["remote_path"] = "c:/Windows/Temp/script.ps1"
+ p := new(Provisioner)
+ comm := new(packersdk.MockCommunicator)
+ p.communicator = comm
+ _ = p.Prepare(config)
+
+ // Defaults provided by Packer
+ p.config.PackerBuildName = "vmware"
+ p.config.PackerBuilderType = "iso"
+
+ // Non-elevated
+ p.generatedData = make(map[string]interface{})
+ cmd, _ := p.createCommandText()
+
+ re := regexp.MustCompile(`powershell -executionpolicy bypass "& { if \(Test-Path variable:global:ProgressPreference\){set-variable -name variable:global:ProgressPreference -value 'SilentlyContinue'};\. c:/Windows/Temp/packer-ps-env-vars-[[:alnum:]]{8}-[[:alnum:]]{4}-[[:alnum:]]{4}-[[:alnum:]]{4}-[[:alnum:]]{12}\.ps1; &'c:/Windows/Temp/script.ps1'; exit \$LastExitCode }"`)
+ matched := re.MatchString(cmd)
+ if !matched {
+ t.Fatalf("Got unexpected command: %s", cmd)
+ }
+
+ // Elevated
+ p.config.ElevatedUser = "vagrant"
+ p.config.ElevatedPassword = "vagrant"
+ cmd, _ = p.createCommandText()
+ re = regexp.MustCompile(`powershell -executionpolicy bypass -file "C:/Windows/Temp/packer-elevated-shell-[[:alnum:]]{8}-[[:alnum:]]{4}-[[:alnum:]]{4}-[[:alnum:]]{4}-[[:alnum:]]{12}\.ps1"`)
+ matched = re.MatchString(cmd)
+ if !matched {
+ t.Fatalf("Got unexpected elevated command: %s", cmd)
+ }
+}
+
+func TestProvision_uploadEnvVars(t *testing.T) {
+ p := new(Provisioner)
+ comm := new(packersdk.MockCommunicator)
+ p.communicator = comm
+
+ flattenedEnvVars := `$env:PACKER_BUILDER_TYPE="footype"; $env:PACKER_BUILD_NAME="foobuild";`
+
+ err := p.uploadEnvVars(flattenedEnvVars)
+ if err != nil {
+ t.Fatalf("Did not expect error: %s", err.Error())
+ }
+
+ if comm.UploadCalled != true {
+ t.Fatalf("Failed to upload env var file")
+ }
+}
+
+func TestCancel(t *testing.T) {
+ // Don't actually call Cancel() as it performs an os.Exit(0)
+ // which kills the 'go test' tool
+}
+
+func testConfig() map[string]interface{} {
+ return map[string]interface{}{
+ "inline": []interface{}{"foo", "bar"},
+ }
+}
+
+func testConfigWithSkipClean() map[string]interface{} {
+ return map[string]interface{}{
+ "inline": []interface{}{"foo", "bar"},
+ "skip_clean": true,
+ }
+}
+
+func generatedData() map[string]interface{} {
+ return map[string]interface{}{
+ "PackerHTTPAddr": commonsteps.HttpAddrNotImplemented,
+ "PackerHTTPIP": commonsteps.HttpIPNotImplemented,
+ "PackerHTTPPort": commonsteps.HttpPortNotImplemented,
+ }
+}
diff --git a/v1.9.4/provisioner/powershell/test-fixtures/powershell-inline-provisioner.txt b/v1.9.4/provisioner/powershell/test-fixtures/powershell-inline-provisioner.txt
new file mode 100644
index 0000000..1b63c17
--- /dev/null
+++ b/v1.9.4/provisioner/powershell/test-fixtures/powershell-inline-provisioner.txt
@@ -0,0 +1,8 @@
+{
+ "type": "powershell",
+ "environment_vars": "PackerRunUUID={{build `PackerRunUUID`}},ID={{build `ID`}}",
+ "inline": [
+ "Write-Host \"$env:ID for provisioner.$env:PackerRunUUID\""
+ ]
+}
+
diff --git a/v1.9.4/provisioner/powershell/test-fixtures/powershell-provisioner-cleanup.txt b/v1.9.4/provisioner/powershell/test-fixtures/powershell-provisioner-cleanup.txt
new file mode 100644
index 0000000..da1408f
--- /dev/null
+++ b/v1.9.4/provisioner/powershell/test-fixtures/powershell-provisioner-cleanup.txt
@@ -0,0 +1,13 @@
+{
+ "type": "powershell",
+ "remote_path": "c:/Windows/Temp/packer-acc-test-script-test.ps1",
+ "remote_env_var_path": "C:/Windows/Temp/packer-acc-test-vars.ps1",
+ "inline": [
+ "Write-Host \"Total files found in Temp directory\" ( dir C:/Windows/Temp/packer-*.ps1 | measure).Count;"
+ ]
+},
+{
+ "type": "windows-shell",
+ "inline": ["dir C:\\Windows\\Temp\\packer-*.ps1"],
+ "valid_exit_codes": ["1"]
+}
diff --git a/v1.9.4/provisioner/powershell/test-fixtures/powershell-script-provisioner.txt b/v1.9.4/provisioner/powershell/test-fixtures/powershell-script-provisioner.txt
new file mode 100644
index 0000000..f0fc663
--- /dev/null
+++ b/v1.9.4/provisioner/powershell/test-fixtures/powershell-script-provisioner.txt
@@ -0,0 +1,11 @@
+{
+ "type": "powershell",
+ "script": "../../provisioner/powershell/test-fixtures/scripts/sample_script.ps1",
+ "environment_vars": [
+ "VAR1=A$Dollar",
+ "VAR2=A`Backtick",
+ "VAR3=A'SingleQuote",
+ "VAR4=A\"DoubleQuote"
+ ]
+}
+
diff --git a/v1.9.4/provisioner/powershell/test-fixtures/scripts/sample_script.ps1 b/v1.9.4/provisioner/powershell/test-fixtures/scripts/sample_script.ps1
new file mode 100644
index 0000000..0c146c9
--- /dev/null
+++ b/v1.9.4/provisioner/powershell/test-fixtures/scripts/sample_script.ps1
@@ -0,0 +1,5 @@
+write-output("packer_build_name is automatically set for you, or you can set it in your builder variables; the default for this builder is: " + $env:packer_build_name )
+write-output("remember that escaping variables in powershell requires backticks; for example var1 from our config is " + $env:var1 )
+write-output("likewise, var2 is " + $env:var2 )
+write-output("and var3 is " + $env:var3 )
+
diff --git a/v1.9.4/provisioner/powershell/version/version.go b/v1.9.4/provisioner/powershell/version/version.go
new file mode 100644
index 0000000..eb2cc7e
--- /dev/null
+++ b/v1.9.4/provisioner/powershell/version/version.go
@@ -0,0 +1,16 @@
+// Copyright (c) HashiCorp, Inc.
+// SPDX-License-Identifier: MPL-2.0
+
+package version
+
+import (
+ "github.com/hashicorp/packer-plugin-sdk/version"
+ packerVersion "github.com/hashicorp/packer/version"
+)
+
+var PowershellPluginVersion *version.PluginVersion
+
+func init() {
+ PowershellPluginVersion = version.InitializePluginVersion(
+ packerVersion.Version, packerVersion.VersionPrerelease)
+}
diff --git a/v1.9.4/provisioner/shell-local/provisioner.go b/v1.9.4/provisioner/shell-local/provisioner.go
new file mode 100644
index 0000000..d051b36
--- /dev/null
+++ b/v1.9.4/provisioner/shell-local/provisioner.go
@@ -0,0 +1,38 @@
+// Copyright (c) HashiCorp, Inc.
+// SPDX-License-Identifier: MPL-2.0
+
+package shell
+
+import (
+ "context"
+
+ "github.com/hashicorp/hcl/v2/hcldec"
+ packersdk "github.com/hashicorp/packer-plugin-sdk/packer"
+ sl "github.com/hashicorp/packer-plugin-sdk/shell-local"
+)
+
+type Provisioner struct {
+ config sl.Config
+}
+
+func (p *Provisioner) ConfigSpec() hcldec.ObjectSpec { return p.config.FlatMapstructure().HCL2Spec() }
+
+func (p *Provisioner) Prepare(raws ...interface{}) error {
+ err := sl.Decode(&p.config, raws...)
+ if err != nil {
+ return err
+ }
+
+ err = sl.Validate(&p.config)
+ if err != nil {
+ return err
+ }
+
+ return nil
+}
+
+func (p *Provisioner) Provision(ctx context.Context, ui packersdk.Ui, _ packersdk.Communicator, generatedData map[string]interface{}) error {
+ _, retErr := sl.Run(ctx, ui, &p.config, generatedData)
+
+ return retErr
+}
diff --git a/v1.9.4/provisioner/shell-local/provisioner_acc_test.go b/v1.9.4/provisioner/shell-local/provisioner_acc_test.go
new file mode 100644
index 0000000..f53990d
--- /dev/null
+++ b/v1.9.4/provisioner/shell-local/provisioner_acc_test.go
@@ -0,0 +1,79 @@
+// Copyright (c) HashiCorp, Inc.
+// SPDX-License-Identifier: MPL-2.0
+
+package shell_test
+
+import (
+ "fmt"
+ "io/ioutil"
+ "os"
+ "os/exec"
+ "path/filepath"
+ "runtime"
+ "strings"
+ "testing"
+
+ "github.com/hashicorp/packer-plugin-sdk/acctest/provisioneracc"
+ "github.com/hashicorp/packer-plugin-sdk/acctest/testutils"
+)
+
+func fixtureDir() string {
+ _, file, _, _ := runtime.Caller(0)
+ return filepath.Join(filepath.Dir(file), "test-fixtures")
+}
+
+func loadFile(templateFragmentPath string) (string, error) {
+ dir := fixtureDir()
+ fragmentAbsPath := filepath.Join(dir, templateFragmentPath)
+ fragmentFile, err := os.Open(fragmentAbsPath)
+ if err != nil {
+ return "", fmt.Errorf("Unable find %s", fragmentAbsPath)
+ }
+ defer fragmentFile.Close()
+
+ fragmentString, err := ioutil.ReadAll(fragmentFile)
+ if err != nil {
+ return "", fmt.Errorf("Unable to read %s", fragmentAbsPath)
+ }
+
+ return string(fragmentString), nil
+}
+
+func IsCompatible(builder string, vmOS string) bool {
+ return vmOS == "linux"
+}
+
+func TestAccShellProvisioner_basic(t *testing.T) {
+ templateString, err := loadFile("shell-local-provisioner.txt")
+ if err != nil {
+ t.Fatalf("Couldn't load test fixture; %s", err.Error())
+ }
+
+ testCase := &provisioneracc.ProvisionerTestCase{
+ IsCompatible: IsCompatible,
+ 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\n", 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)
+}
diff --git a/v1.9.4/provisioner/shell-local/provisioner_test.go b/v1.9.4/provisioner/shell-local/provisioner_test.go
new file mode 100644
index 0000000..ac7262b
--- /dev/null
+++ b/v1.9.4/provisioner/shell-local/provisioner_test.go
@@ -0,0 +1,70 @@
+// Copyright (c) HashiCorp, Inc.
+// SPDX-License-Identifier: MPL-2.0
+
+package shell
+
+import (
+ "testing"
+
+ packersdk "github.com/hashicorp/packer-plugin-sdk/packer"
+)
+
+func TestProvisioner_impl(t *testing.T) {
+ var _ packersdk.Provisioner = new(Provisioner)
+}
+
+func TestConfigPrepare(t *testing.T) {
+ cases := []struct {
+ Key string
+ Value interface{}
+ Err bool
+ }{
+ {
+ "unknown_key",
+ "bad",
+ true,
+ },
+
+ {
+ "command",
+ nil,
+ true,
+ },
+ }
+
+ for _, tc := range cases {
+ raw := testConfig(t)
+
+ if tc.Value == nil {
+ delete(raw, tc.Key)
+ } else {
+ raw[tc.Key] = tc.Value
+ }
+
+ var p Provisioner
+ err := p.Prepare(raw)
+ if tc.Err {
+ testConfigErr(t, err, tc.Key)
+ } else {
+ testConfigOk(t, err)
+ }
+ }
+}
+
+func testConfig(t *testing.T) map[string]interface{} {
+ return map[string]interface{}{
+ "command": "echo foo",
+ }
+}
+
+func testConfigErr(t *testing.T, err error, extra string) {
+ if err == nil {
+ t.Fatalf("should error: %s", extra)
+ }
+}
+
+func testConfigOk(t *testing.T, err error) {
+ if err != nil {
+ t.Fatalf("bad: %s", err)
+ }
+}
diff --git a/v1.9.4/provisioner/shell-local/test-fixtures/script.sh b/v1.9.4/provisioner/shell-local/test-fixtures/script.sh
new file mode 100755
index 0000000..9b17972
--- /dev/null
+++ b/v1.9.4/provisioner/shell-local/test-fixtures/script.sh
@@ -0,0 +1,7 @@
+#!/bin/bash
+
+# On first try, exits 1; on second try, passes.
+if [[ ! -f test-fixtures/file.txt ]] ; then
+ echo 'hello' > test-fixtures/file.txt
+ exit 1
+fi
\ No newline at end of file
diff --git a/v1.9.4/provisioner/shell-local/test-fixtures/shell-local-provisioner.txt b/v1.9.4/provisioner/shell-local/test-fixtures/shell-local-provisioner.txt
new file mode 100644
index 0000000..37929ad
--- /dev/null
+++ b/v1.9.4/provisioner/shell-local/test-fixtures/shell-local-provisioner.txt
@@ -0,0 +1,5 @@
+{
+ "type": "shell-local",
+ "script": "test-fixtures/script.sh",
+ "max_retries" : 5
+}
\ No newline at end of file
diff --git a/v1.9.4/provisioner/shell-local/version/version.go b/v1.9.4/provisioner/shell-local/version/version.go
new file mode 100644
index 0000000..205aea7
--- /dev/null
+++ b/v1.9.4/provisioner/shell-local/version/version.go
@@ -0,0 +1,16 @@
+// Copyright (c) HashiCorp, Inc.
+// SPDX-License-Identifier: MPL-2.0
+
+package version
+
+import (
+ "github.com/hashicorp/packer-plugin-sdk/version"
+ packerVersion "github.com/hashicorp/packer/version"
+)
+
+var ShellLocalProvisionerVersion *version.PluginVersion
+
+func init() {
+ ShellLocalProvisionerVersion = version.InitializePluginVersion(
+ packerVersion.Version, packerVersion.VersionPrerelease)
+}
diff --git a/v1.9.4/provisioner/shell/provisioner.go b/v1.9.4/provisioner/shell/provisioner.go
new file mode 100644
index 0000000..cc1e399
--- /dev/null
+++ b/v1.9.4/provisioner/shell/provisioner.go
@@ -0,0 +1,482 @@
+// Copyright (c) HashiCorp, Inc.
+// SPDX-License-Identifier: MPL-2.0
+
+//go:generate packer-sdc mapstructure-to-hcl2 -type Config
+
+// This package implements a provisioner for Packer that executes
+// shell scripts within the remote machine.
+package shell
+
+import (
+ "bufio"
+ "context"
+ "errors"
+ "fmt"
+ "io"
+ "log"
+ "math/rand"
+ "os"
+ "sort"
+ "strings"
+ "time"
+
+ "github.com/hashicorp/hcl/v2/hcldec"
+ "github.com/hashicorp/packer-plugin-sdk/multistep/commonsteps"
+ packersdk "github.com/hashicorp/packer-plugin-sdk/packer"
+ "github.com/hashicorp/packer-plugin-sdk/retry"
+ "github.com/hashicorp/packer-plugin-sdk/shell"
+ "github.com/hashicorp/packer-plugin-sdk/template/config"
+ "github.com/hashicorp/packer-plugin-sdk/template/interpolate"
+ "github.com/hashicorp/packer-plugin-sdk/tmp"
+)
+
+type Config struct {
+ shell.Provisioner `mapstructure:",squash"`
+
+ shell.ProvisionerRemoteSpecific `mapstructure:",squash"`
+
+ // The shebang value used when running inline scripts.
+ InlineShebang string `mapstructure:"inline_shebang"`
+
+ // A duration of how long to pause after the provisioner
+ PauseAfter time.Duration `mapstructure:"pause_after"`
+
+ // Write the Vars to a file and source them from there rather than declaring
+ // inline
+ UseEnvVarFile bool `mapstructure:"use_env_var_file"`
+
+ // The remote folder where the local shell script will be uploaded to.
+ // This should be set to a pre-existing directory, it defaults to /tmp
+ RemoteFolder string `mapstructure:"remote_folder"`
+
+ // The remote file name of the local shell script.
+ // This defaults to script_nnn.sh
+ RemoteFile string `mapstructure:"remote_file"`
+
+ // The timeout for retrying to start the process. Until this timeout
+ // is reached, if the provisioner can't start a process, it retries.
+ // This can be set high to allow for reboots.
+ StartRetryTimeout time.Duration `mapstructure:"start_retry_timeout"`
+
+ // Whether to clean scripts up
+ SkipClean bool `mapstructure:"skip_clean"`
+
+ ExpectDisconnect bool `mapstructure:"expect_disconnect"`
+
+ // name of the tmp environment variable file, if UseEnvVarFile is true
+ envVarFile string
+
+ ctx interpolate.Context
+}
+
+type Provisioner struct {
+ config Config
+ generatedData map[string]interface{}
+}
+
+func (p *Provisioner) ConfigSpec() hcldec.ObjectSpec { return p.config.FlatMapstructure().HCL2Spec() }
+
+func (p *Provisioner) Prepare(raws ...interface{}) error {
+ err := config.Decode(&p.config, &config.DecodeOpts{
+ PluginType: "shell",
+ Interpolate: true,
+ InterpolateContext: &p.config.ctx,
+ InterpolateFilter: &interpolate.RenderFilter{
+ Exclude: []string{
+ "execute_command",
+ },
+ },
+ }, raws...)
+
+ if err != nil {
+ return err
+ }
+
+ if p.config.EnvVarFormat == "" {
+ p.config.EnvVarFormat = "%s='%s' "
+
+ if p.config.UseEnvVarFile == true {
+ p.config.EnvVarFormat = "export %s='%s'\n"
+ }
+ }
+
+ if p.config.ExecuteCommand == "" {
+ p.config.ExecuteCommand = "chmod +x {{.Path}}; {{.Vars}} {{.Path}}"
+ if p.config.UseEnvVarFile == true {
+ p.config.ExecuteCommand = "chmod +x {{.Path}}; . {{.EnvVarFile}} && {{.Path}}"
+ }
+ }
+
+ if p.config.Inline != nil && len(p.config.Inline) == 0 {
+ p.config.Inline = nil
+ }
+
+ if p.config.InlineShebang == "" {
+ p.config.InlineShebang = "/bin/sh -e"
+ }
+
+ if p.config.StartRetryTimeout == 0 {
+ p.config.StartRetryTimeout = 5 * time.Minute
+ }
+
+ if p.config.RemoteFolder == "" {
+ p.config.RemoteFolder = "/tmp"
+ }
+
+ if p.config.RemoteFile == "" {
+ p.config.RemoteFile = fmt.Sprintf("script_%d.sh", rand.Intn(9999))
+ }
+
+ if p.config.RemotePath == "" {
+ p.config.RemotePath = fmt.Sprintf("%s/%s", p.config.RemoteFolder, p.config.RemoteFile)
+ }
+
+ if p.config.Scripts == nil {
+ p.config.Scripts = make([]string, 0)
+ }
+
+ if p.config.Vars == nil {
+ p.config.Vars = make([]string, 0)
+ }
+
+ var errs *packersdk.MultiError
+ if p.config.Script != "" && len(p.config.Scripts) > 0 {
+ errs = packersdk.MultiErrorAppend(errs,
+ errors.New("Only one of script or scripts can be specified."))
+ }
+
+ if p.config.Script != "" {
+ p.config.Scripts = []string{p.config.Script}
+ }
+
+ if len(p.config.Scripts) == 0 && p.config.Inline == nil {
+ errs = packersdk.MultiErrorAppend(errs,
+ errors.New("Either a script file or inline script must be specified."))
+ } else if len(p.config.Scripts) > 0 && p.config.Inline != nil {
+ errs = packersdk.MultiErrorAppend(errs,
+ errors.New("Only a script file or an inline script can be specified, not both."))
+ }
+
+ for _, path := range p.config.Scripts {
+ if _, err := os.Stat(path); err != nil {
+ errs = packersdk.MultiErrorAppend(errs,
+ fmt.Errorf("Bad script '%s': %s", path, err))
+ }
+ }
+
+ // Do a check for bad environment variables, such as '=foo', 'foobar'
+ for _, kv := range p.config.Vars {
+ vs := strings.SplitN(kv, "=", 2)
+ if len(vs) != 2 || vs[0] == "" {
+ errs = packersdk.MultiErrorAppend(errs,
+ fmt.Errorf("Environment variable not in format 'key=value': %s", kv))
+ }
+ }
+
+ if errs != nil && len(errs.Errors) > 0 {
+ return errs
+ }
+
+ return nil
+}
+
+func (p *Provisioner) Provision(ctx context.Context, ui packersdk.Ui, comm packersdk.Communicator, generatedData map[string]interface{}) error {
+ if generatedData == nil {
+ generatedData = make(map[string]interface{})
+ }
+ p.generatedData = generatedData
+
+ scripts := make([]string, len(p.config.Scripts))
+ copy(scripts, p.config.Scripts)
+
+ // If we have an inline script, then turn that into a temporary
+ // shell script and use that.
+ if p.config.Inline != nil {
+ tf, err := tmp.File("packer-shell")
+ if err != nil {
+ return fmt.Errorf("Error preparing shell script: %s", err)
+ }
+ defer os.Remove(tf.Name())
+
+ // Set the path to the temporary file
+ scripts = append(scripts, tf.Name())
+
+ // Write our contents to it
+ writer := bufio.NewWriter(tf)
+ writer.WriteString(fmt.Sprintf("#!%s\n", p.config.InlineShebang))
+ for _, command := range p.config.Inline {
+ p.config.ctx.Data = generatedData
+ command, err := interpolate.Render(command, &p.config.ctx)
+ if err != nil {
+ return fmt.Errorf("Error interpolating Inline: %s", err)
+ }
+ if _, err := writer.WriteString(command + "\n"); err != nil {
+ return fmt.Errorf("Error preparing shell script: %s", err)
+ }
+ }
+
+ if err := writer.Flush(); err != nil {
+ return fmt.Errorf("Error preparing shell script: %s", err)
+ }
+
+ tf.Close()
+ }
+
+ if p.config.UseEnvVarFile == true {
+ tf, err := tmp.File("packer-shell-vars")
+ if err != nil {
+ return fmt.Errorf("Error preparing shell script: %s", err)
+ }
+ defer os.Remove(tf.Name())
+
+ // Write our contents to it
+ writer := bufio.NewWriter(tf)
+ if _, err := writer.WriteString(p.createEnvVarFileContent()); err != nil {
+ return fmt.Errorf("Error preparing shell script: %s", err)
+ }
+
+ if err := writer.Flush(); err != nil {
+ return fmt.Errorf("Error preparing shell script: %s", err)
+ }
+
+ p.config.envVarFile = tf.Name()
+
+ // upload the var file
+ var cmd *packersdk.RemoteCmd
+ err = retry.Config{StartTimeout: p.config.StartRetryTimeout}.Run(ctx, func(ctx context.Context) error {
+ if _, err := tf.Seek(0, 0); err != nil {
+ return err
+ }
+
+ var r io.Reader = tf
+ if !p.config.Binary {
+ r = &UnixReader{Reader: r}
+ }
+ remoteVFName := fmt.Sprintf("%s/%s", p.config.RemoteFolder,
+ fmt.Sprintf("varfile_%d.sh", rand.Intn(9999)))
+ if err := comm.Upload(remoteVFName, r, nil); err != nil {
+ return fmt.Errorf("Error uploading envVarFile: %s", err)
+ }
+ tf.Close()
+
+ cmd = &packersdk.RemoteCmd{
+ Command: fmt.Sprintf("chmod 0600 %s", remoteVFName),
+ }
+ if err := comm.Start(ctx, cmd); err != nil {
+ return fmt.Errorf("Error chmodding script file to 0600 in remote machine: %s", err)
+ }
+ cmd.Wait()
+ p.config.envVarFile = remoteVFName
+ return nil
+ })
+ if err != nil {
+ return err
+ }
+ }
+
+ // Create environment variables to set before executing the command
+ flattenedEnvVars := p.createFlattenedEnvVars()
+
+ for _, path := range scripts {
+ ui.Say(fmt.Sprintf("Provisioning with shell script: %s", path))
+
+ log.Printf("Opening %s for reading", path)
+ f, err := os.Open(path)
+ if err != nil {
+ return fmt.Errorf("Error opening shell script: %s", err)
+ }
+ defer f.Close()
+
+ // Compile the command
+ // These are extra variables that will be made available for interpolation.
+ generatedData["Vars"] = flattenedEnvVars
+ generatedData["EnvVarFile"] = p.config.envVarFile
+ generatedData["Path"] = p.config.RemotePath
+ p.config.ctx.Data = generatedData
+
+ command, err := interpolate.Render(p.config.ExecuteCommand, &p.config.ctx)
+ if err != nil {
+ return fmt.Errorf("Error processing command: %s", err)
+ }
+
+ // Upload the file and run the command. Do this in the context of
+ // a single retryable function so that we don't end up with
+ // the case that the upload succeeded, a restart is initiated,
+ // and then the command is executed but the file doesn't exist
+ // any longer.
+ var cmd *packersdk.RemoteCmd
+ err = retry.Config{StartTimeout: p.config.StartRetryTimeout}.Run(ctx, func(ctx context.Context) error {
+ if _, err := f.Seek(0, 0); err != nil {
+ return err
+ }
+
+ var r io.Reader = f
+ if !p.config.Binary {
+ r = &UnixReader{Reader: r}
+ }
+
+ if err := comm.Upload(p.config.RemotePath, r, nil); err != nil {
+ return fmt.Errorf("Error uploading script: %s", err)
+ }
+
+ cmd = &packersdk.RemoteCmd{
+ Command: fmt.Sprintf("chmod 0755 %s", p.config.RemotePath),
+ }
+ if err := comm.Start(ctx, cmd); err != nil {
+ return fmt.Errorf(
+ "Error chmodding script file to 0755 in remote "+
+ "machine: %s", err)
+ }
+ cmd.Wait()
+
+ cmd = &packersdk.RemoteCmd{Command: command}
+ return cmd.RunWithUi(ctx, comm, ui)
+ })
+
+ if err != nil {
+ return err
+ }
+
+ // If the exit code indicates a remote disconnect, fail unless
+ // we were expecting it.
+ if cmd.ExitStatus() == packersdk.CmdDisconnect {
+ if !p.config.ExpectDisconnect {
+ return fmt.Errorf("Script disconnected unexpectedly. " +
+ "If you expected your script to disconnect, i.e. from a " +
+ "restart, you can try adding `\"expect_disconnect\": true` " +
+ "or `\"valid_exit_codes\": [0, 2300218]` to the shell " +
+ "provisioner parameters.")
+ }
+ } else if err := p.config.ValidExitCode(cmd.ExitStatus()); err != nil {
+ return err
+ }
+
+ if p.config.SkipClean {
+ continue
+ }
+
+ // Delete the temporary file we created. We retry this a few times
+ // since if the above rebooted we have to wait until the reboot
+ // completes.
+ if err := p.cleanupRemoteFile(p.config.RemotePath, comm); err != nil {
+ return err
+ }
+
+ }
+
+ if !p.config.SkipClean {
+ if err := p.cleanupRemoteFile(p.config.envVarFile, comm); err != nil {
+ return err
+ }
+ }
+
+ if p.config.PauseAfter != 0 {
+ ui.Say(fmt.Sprintf("Pausing %s after this provisioner...", p.config.PauseAfter))
+ select {
+ case <-time.After(p.config.PauseAfter):
+ return nil
+ }
+ }
+
+ return nil
+}
+
+func (p *Provisioner) cleanupRemoteFile(path string, comm packersdk.Communicator) error {
+ ctx := context.TODO()
+ err := retry.Config{StartTimeout: p.config.StartRetryTimeout}.Run(ctx, func(ctx context.Context) error {
+ cmd := &packersdk.RemoteCmd{
+ Command: fmt.Sprintf("rm -f %s", path),
+ }
+ if err := comm.Start(ctx, cmd); err != nil {
+ return fmt.Errorf(
+ "Error removing temporary script at %s: %s",
+ path, err)
+ }
+ cmd.Wait()
+ // treat disconnects as retryable by returning an error
+ if cmd.ExitStatus() == packersdk.CmdDisconnect {
+ return fmt.Errorf("Disconnect while removing temporary script.")
+ }
+ if cmd.ExitStatus() != 0 {
+ return fmt.Errorf(
+ "Error removing temporary script at %s!",
+ path)
+ }
+ return nil
+ })
+
+ if err != nil {
+ return err
+ }
+
+ return nil
+}
+
+func (p *Provisioner) escapeEnvVars() ([]string, map[string]string) {
+ envVars := make(map[string]string)
+
+ // Always available Packer provided env vars
+ envVars["PACKER_BUILD_NAME"] = p.config.PackerBuildName
+ envVars["PACKER_BUILDER_TYPE"] = p.config.PackerBuilderType
+
+ // expose ip address variables
+ httpAddr := p.generatedData["PackerHTTPAddr"]
+ if httpAddr != nil && httpAddr != commonsteps.HttpAddrNotImplemented {
+ envVars["PACKER_HTTP_ADDR"] = httpAddr.(string)
+ }
+ httpIP := p.generatedData["PackerHTTPIP"]
+ if httpIP != nil && httpIP != commonsteps.HttpIPNotImplemented {
+ envVars["PACKER_HTTP_IP"] = httpIP.(string)
+ }
+ httpPort := p.generatedData["PackerHTTPPort"]
+ if httpPort != nil && httpPort != commonsteps.HttpPortNotImplemented {
+ envVars["PACKER_HTTP_PORT"] = httpPort.(string)
+ }
+
+ // Split vars into key/value components
+ for _, envVar := range p.config.Vars {
+ keyValue := strings.SplitN(envVar, "=", 2)
+ // Store pair, replacing any single quotes in value so they parse
+ // correctly with required environment variable format
+ envVars[keyValue[0]] = strings.Replace(keyValue[1], "'", `'"'"'`, -1)
+ }
+
+ // Add the environment variables defined in the HCL specs
+ for k, v := range p.config.Env {
+ // As with p.config.Vars, we escape single-quotes so they're not
+ // misinterpreted by the remote shell.
+ envVars[k] = strings.Replace(v, "'", `'"'"'`, -1)
+ }
+
+ // Create a list of env var keys in sorted order
+ var keys []string
+ for k := range envVars {
+ keys = append(keys, k)
+ }
+ sort.Strings(keys)
+
+ return keys, envVars
+}
+
+func (p *Provisioner) createEnvVarFileContent() string {
+ keys, envVars := p.escapeEnvVars()
+
+ var flattened string
+ for _, key := range keys {
+ flattened += fmt.Sprintf(p.config.EnvVarFormat, key, envVars[key])
+ }
+
+ return flattened
+}
+
+func (p *Provisioner) createFlattenedEnvVars() string {
+ keys, envVars := p.escapeEnvVars()
+
+ // Re-assemble vars into specified format and flatten
+ var flattened string
+ for _, key := range keys {
+ flattened += fmt.Sprintf(p.config.EnvVarFormat, key, envVars[key])
+ }
+
+ return flattened
+}
diff --git a/v1.9.4/provisioner/shell/provisioner.hcl2spec.go b/v1.9.4/provisioner/shell/provisioner.hcl2spec.go
new file mode 100644
index 0000000..4ea77be
--- /dev/null
+++ b/v1.9.4/provisioner/shell/provisioner.hcl2spec.go
@@ -0,0 +1,81 @@
+// Code generated by "packer-sdc mapstructure-to-hcl2"; DO NOT EDIT.
+
+package shell
+
+import (
+ "github.com/hashicorp/hcl/v2/hcldec"
+ "github.com/zclconf/go-cty/cty"
+)
+
+// FlatConfig is an auto-generated flat version of Config.
+// Where the contents of a field with a `mapstructure:,squash` tag are bubbled up.
+type FlatConfig struct {
+ PackerBuildName *string `mapstructure:"packer_build_name" cty:"packer_build_name" 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"`
+ Inline []string `cty:"inline" hcl:"inline"`
+ Script *string `cty:"script" hcl:"script"`
+ Scripts []string `cty:"scripts" hcl:"scripts"`
+ ValidExitCodes []int `mapstructure:"valid_exit_codes" cty:"valid_exit_codes" hcl:"valid_exit_codes"`
+ Vars []string `mapstructure:"environment_vars" cty:"environment_vars" hcl:"environment_vars"`
+ Env map[string]string `mapstructure:"env" cty:"env" hcl:"env"`
+ EnvVarFormat *string `mapstructure:"env_var_format" cty:"env_var_format" hcl:"env_var_format"`
+ Binary *bool `cty:"binary" hcl:"binary"`
+ RemotePath *string `mapstructure:"remote_path" cty:"remote_path" hcl:"remote_path"`
+ ExecuteCommand *string `mapstructure:"execute_command" cty:"execute_command" hcl:"execute_command"`
+ InlineShebang *string `mapstructure:"inline_shebang" cty:"inline_shebang" hcl:"inline_shebang"`
+ PauseAfter *string `mapstructure:"pause_after" cty:"pause_after" hcl:"pause_after"`
+ UseEnvVarFile *bool `mapstructure:"use_env_var_file" cty:"use_env_var_file" hcl:"use_env_var_file"`
+ RemoteFolder *string `mapstructure:"remote_folder" cty:"remote_folder" hcl:"remote_folder"`
+ RemoteFile *string `mapstructure:"remote_file" cty:"remote_file" hcl:"remote_file"`
+ StartRetryTimeout *string `mapstructure:"start_retry_timeout" cty:"start_retry_timeout" hcl:"start_retry_timeout"`
+ SkipClean *bool `mapstructure:"skip_clean" cty:"skip_clean" hcl:"skip_clean"`
+ ExpectDisconnect *bool `mapstructure:"expect_disconnect" cty:"expect_disconnect" hcl:"expect_disconnect"`
+}
+
+// FlatMapstructure returns a new FlatConfig.
+// FlatConfig is an auto-generated flat version of Config.
+// Where the contents a fields with a `mapstructure:,squash` tag are bubbled up.
+func (*Config) FlatMapstructure() interface{ HCL2Spec() map[string]hcldec.Spec } {
+ return new(FlatConfig)
+}
+
+// HCL2Spec returns the hcl spec of a Config.
+// This spec is used by HCL to read the fields of Config.
+// The decoded values from this spec will then be applied to a FlatConfig.
+func (*FlatConfig) HCL2Spec() map[string]hcldec.Spec {
+ s := map[string]hcldec.Spec{
+ "packer_build_name": &hcldec.AttrSpec{Name: "packer_build_name", Type: cty.String, Required: false},
+ "packer_builder_type": &hcldec.AttrSpec{Name: "packer_builder_type", Type: cty.String, Required: false},
+ "packer_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_sensitive_variables": &hcldec.AttrSpec{Name: "packer_sensitive_variables", Type: cty.List(cty.String), Required: false},
+ "inline": &hcldec.AttrSpec{Name: "inline", Type: cty.List(cty.String), Required: false},
+ "script": &hcldec.AttrSpec{Name: "script", Type: cty.String, Required: false},
+ "scripts": &hcldec.AttrSpec{Name: "scripts", Type: cty.List(cty.String), Required: false},
+ "valid_exit_codes": &hcldec.AttrSpec{Name: "valid_exit_codes", Type: cty.List(cty.Number), Required: false},
+ "environment_vars": &hcldec.AttrSpec{Name: "environment_vars", Type: cty.List(cty.String), Required: false},
+ "env": &hcldec.AttrSpec{Name: "env", Type: cty.Map(cty.String), Required: false},
+ "env_var_format": &hcldec.AttrSpec{Name: "env_var_format", Type: cty.String, Required: false},
+ "binary": &hcldec.AttrSpec{Name: "binary", Type: cty.Bool, Required: false},
+ "remote_path": &hcldec.AttrSpec{Name: "remote_path", Type: cty.String, Required: false},
+ "execute_command": &hcldec.AttrSpec{Name: "execute_command", Type: cty.String, Required: false},
+ "inline_shebang": &hcldec.AttrSpec{Name: "inline_shebang", Type: cty.String, Required: false},
+ "pause_after": &hcldec.AttrSpec{Name: "pause_after", Type: cty.String, Required: false},
+ "use_env_var_file": &hcldec.AttrSpec{Name: "use_env_var_file", Type: cty.Bool, Required: false},
+ "remote_folder": &hcldec.AttrSpec{Name: "remote_folder", Type: cty.String, Required: false},
+ "remote_file": &hcldec.AttrSpec{Name: "remote_file", Type: cty.String, Required: false},
+ "start_retry_timeout": &hcldec.AttrSpec{Name: "start_retry_timeout", Type: cty.String, Required: false},
+ "skip_clean": &hcldec.AttrSpec{Name: "skip_clean", Type: cty.Bool, Required: false},
+ "expect_disconnect": &hcldec.AttrSpec{Name: "expect_disconnect", Type: cty.Bool, Required: false},
+ }
+ return s
+}
diff --git a/v1.9.4/provisioner/shell/provisioner_acc_test.go b/v1.9.4/provisioner/shell/provisioner_acc_test.go
new file mode 100644
index 0000000..8ffc58b
--- /dev/null
+++ b/v1.9.4/provisioner/shell/provisioner_acc_test.go
@@ -0,0 +1,80 @@
+// Copyright (c) HashiCorp, Inc.
+// SPDX-License-Identifier: MPL-2.0
+
+package shell_test
+
+import (
+ "fmt"
+ "io/ioutil"
+ "os"
+ "os/exec"
+ "path/filepath"
+ "regexp"
+ "runtime"
+ "testing"
+
+ "github.com/hashicorp/packer-plugin-sdk/acctest/provisioneracc"
+ "github.com/hashicorp/packer-plugin-sdk/acctest/testutils"
+)
+
+func fixtureDir() string {
+ _, file, _, _ := runtime.Caller(0)
+ return filepath.Join(filepath.Dir(file), "test-fixtures")
+}
+
+func loadFile(templateFragmentPath string) (string, error) {
+ dir := fixtureDir()
+ fragmentAbsPath := filepath.Join(dir, templateFragmentPath)
+ fragmentFile, err := os.Open(fragmentAbsPath)
+ if err != nil {
+ return "", fmt.Errorf("Unable find %s", fragmentAbsPath)
+ }
+ defer fragmentFile.Close()
+
+ fragmentString, err := ioutil.ReadAll(fragmentFile)
+ if err != nil {
+ return "", fmt.Errorf("Unable to read %s", fragmentAbsPath)
+ }
+
+ return string(fragmentString), nil
+}
+
+func IsCompatible(builder string, vmOS string) bool {
+ return vmOS == "linux"
+}
+
+func TestAccShellProvisioner_basic(t *testing.T) {
+ templateString, err := loadFile("shell-provisioner.txt")
+ if err != nil {
+ t.Fatalf("Couldn't load test fixture; %s", err.Error())
+ }
+
+ testCase := &provisioneracc.ProvisionerTestCase{
+ IsCompatible: IsCompatible,
+ Name: "shell-provisioner-basic",
+ Teardown: func() error {
+ testutils.CleanupFiles("test-fixtures/provisioner.shell.txt")
+ return nil
+ },
+ Template: templateString,
+ Type: "shell",
+ 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("provisioner.shell.txt")
+ if err != nil {
+ return err
+ }
+ re := regexp.MustCompile(`build ID is .* and build UUID is [[:alnum:]]{8}-[[:alnum:]]{4}-[[:alnum:]]{4}-[[:alnum:]]{4}-[[:alnum:]]{12}`)
+ if !re.MatchString(filecontents) {
+ return fmt.Errorf("Bad file contents \"%s\"", filecontents)
+ }
+ return nil
+ },
+ }
+
+ provisioneracc.TestProvisionersAgainstBuilders(testCase, t)
+}
diff --git a/v1.9.4/provisioner/shell/provisioner_test.go b/v1.9.4/provisioner/shell/provisioner_test.go
new file mode 100644
index 0000000..73a4ac2
--- /dev/null
+++ b/v1.9.4/provisioner/shell/provisioner_test.go
@@ -0,0 +1,657 @@
+// Copyright (c) HashiCorp, Inc.
+// SPDX-License-Identifier: MPL-2.0
+
+package shell
+
+import (
+ "io/ioutil"
+ "os"
+ "regexp"
+ "strings"
+ "testing"
+
+ "github.com/hashicorp/packer-plugin-sdk/multistep/commonsteps"
+ packersdk "github.com/hashicorp/packer-plugin-sdk/packer"
+)
+
+func testConfig() map[string]interface{} {
+ return map[string]interface{}{
+ "inline": []interface{}{"foo", "bar"},
+ }
+}
+
+func TestProvisioner_Impl(t *testing.T) {
+ var raw interface{}
+ raw = &Provisioner{}
+ if _, ok := raw.(packersdk.Provisioner); !ok {
+ t.Fatalf("must be a Provisioner")
+ }
+}
+
+func TestProvisionerPrepare_Defaults(t *testing.T) {
+ var p Provisioner
+ config := testConfig()
+
+ err := p.Prepare(config)
+ if err != nil {
+ t.Fatalf("err: %s", err)
+ }
+
+ if p.config.ExpectDisconnect != false {
+ t.Errorf("expected ExpectDisconnect to default to false")
+ }
+
+ if p.config.RemotePath == "" {
+ t.Errorf("unexpected remote path: %s", p.config.RemotePath)
+ }
+}
+
+func TestProvisionerPrepare_ExpectDisconnect(t *testing.T) {
+ config := testConfig()
+ p := new(Provisioner)
+ config["expect_disconnect"] = false
+
+ err := p.Prepare(config)
+ if err != nil {
+ t.Fatalf("err: %s", err)
+ }
+
+ if p.config.ExpectDisconnect != false {
+ t.Errorf("expected ExpectDisconnect to be false")
+ }
+
+ config["expect_disconnect"] = true
+ p = new(Provisioner)
+ err = p.Prepare(config)
+ if err != nil {
+ t.Fatalf("err: %s", err)
+ }
+
+ if p.config.ExpectDisconnect != true {
+ t.Errorf("expected ExpectDisconnect to be true")
+ }
+}
+
+func TestProvisionerPrepare_InlineShebang(t *testing.T) {
+ config := testConfig()
+
+ delete(config, "inline_shebang")
+ p := new(Provisioner)
+ err := p.Prepare(config)
+ if err != nil {
+ t.Fatalf("should not have error: %s", err)
+ }
+
+ if p.config.InlineShebang != "/bin/sh -e" {
+ t.Fatalf("bad value: %s", p.config.InlineShebang)
+ }
+
+ // Test with a good one
+ config["inline_shebang"] = "foo"
+ p = new(Provisioner)
+ err = p.Prepare(config)
+ if err != nil {
+ t.Fatalf("should not have error: %s", err)
+ }
+
+ if p.config.InlineShebang != "foo" {
+ t.Fatalf("bad value: %s", p.config.InlineShebang)
+ }
+}
+
+func TestProvisionerPrepare_InvalidKey(t *testing.T) {
+ var p Provisioner
+ config := testConfig()
+
+ // Add a random key
+ config["i_should_not_be_valid"] = true
+ err := p.Prepare(config)
+ if err == nil {
+ t.Fatal("should have error")
+ }
+}
+
+func TestProvisionerPrepare_Script(t *testing.T) {
+ config := testConfig()
+ delete(config, "inline")
+
+ config["script"] = "/this/should/not/exist"
+ p := new(Provisioner)
+ err := p.Prepare(config)
+ if err == nil {
+ t.Fatal("should have error")
+ }
+
+ // Test with a good one
+ tf, err := ioutil.TempFile("", "packer")
+ if err != nil {
+ t.Fatalf("error tempfile: %s", err)
+ }
+ defer os.Remove(tf.Name())
+
+ config["script"] = tf.Name()
+ p = new(Provisioner)
+ err = p.Prepare(config)
+ if err != nil {
+ t.Fatalf("should not have error: %s", err)
+ }
+}
+
+func TestProvisionerPrepare_ScriptAndInline(t *testing.T) {
+ var p Provisioner
+ config := testConfig()
+
+ delete(config, "inline")
+ delete(config, "script")
+ err := p.Prepare(config)
+ if err == nil {
+ t.Fatal("should have error")
+ }
+
+ // Test with both
+ tf, err := ioutil.TempFile("", "packer")
+ if err != nil {
+ t.Fatalf("error tempfile: %s", err)
+ }
+ defer os.Remove(tf.Name())
+
+ config["inline"] = []interface{}{"foo"}
+ config["script"] = tf.Name()
+ err = p.Prepare(config)
+ if err == nil {
+ t.Fatal("should have error")
+ }
+}
+
+func TestProvisionerPrepare_ScriptAndScripts(t *testing.T) {
+ var p Provisioner
+ config := testConfig()
+
+ // Test with both
+ tf, err := ioutil.TempFile("", "packer")
+ if err != nil {
+ t.Fatalf("error tempfile: %s", err)
+ }
+ defer os.Remove(tf.Name())
+
+ config["inline"] = []interface{}{"foo"}
+ config["scripts"] = []string{tf.Name()}
+ err = p.Prepare(config)
+ if err == nil {
+ t.Fatal("should have error")
+ }
+}
+
+func TestProvisionerPrepare_Scripts(t *testing.T) {
+ config := testConfig()
+ delete(config, "inline")
+
+ config["scripts"] = []string{}
+ p := new(Provisioner)
+ err := p.Prepare(config)
+ if err == nil {
+ t.Fatal("should have error")
+ }
+
+ // Test with a good one
+ tf, err := ioutil.TempFile("", "packer")
+ if err != nil {
+ t.Fatalf("error tempfile: %s", err)
+ }
+ defer os.Remove(tf.Name())
+
+ config["scripts"] = []string{tf.Name()}
+ p = new(Provisioner)
+ err = p.Prepare(config)
+ if err != nil {
+ t.Fatalf("should not have error: %s", err)
+ }
+}
+
+func TestProvisionerPrepare_EnvironmentVars(t *testing.T) {
+ config := testConfig()
+
+ // Test with a bad case
+ config["environment_vars"] = []string{"badvar", "good=var"}
+ p := new(Provisioner)
+ err := p.Prepare(config)
+ if err == nil {
+ t.Fatal("should have error")
+ }
+
+ // Test with a trickier case
+ config["environment_vars"] = []string{"=bad"}
+ p = new(Provisioner)
+ err = p.Prepare(config)
+ if err == nil {
+ t.Fatal("should have error")
+ }
+
+ // Test with a good case
+ // Note: baz= is a real env variable, just empty
+ config["environment_vars"] = []string{"FOO=bar", "baz="}
+ p = new(Provisioner)
+ err = p.Prepare(config)
+ if err != nil {
+ t.Fatalf("should not have error: %s", err)
+ }
+
+ // Test when the env variable value contains an equals sign
+ config["environment_vars"] = []string{"good=withequals=true"}
+ p = new(Provisioner)
+ err = p.Prepare(config)
+ if err != nil {
+ t.Fatalf("should not have error: %s", err)
+ }
+
+ // Test when the env variable value starts with an equals sign
+ config["environment_vars"] = []string{"good==true"}
+ p = new(Provisioner)
+ err = p.Prepare(config)
+ if err != nil {
+ t.Fatalf("should not have error: %s", err)
+ }
+}
+
+func TestProvisioner_createFlattenedEnvVars(t *testing.T) {
+ var flattenedEnvVars string
+ config := testConfig()
+
+ userEnvVarTests := [][]string{
+ {}, // No user env var
+ {"FOO=bar"}, // Single user env var
+ {"FOO=bar's"}, // User env var with single quote in value
+ {"FOO=bar", "BAZ=qux"}, // Multiple user env vars
+ {"FOO=bar=baz"}, // User env var with value containing equals
+ {"FOO==bar"}, // User env var with value starting with equals
+ }
+ userEnvVarEnvmapTests := []map[string]string{
+ {},
+ {
+ "BAR": "foo",
+ },
+ {
+ "BAR": "foo's",
+ },
+ {
+ "BAR": "foo",
+ "YAR": "yaa",
+ },
+ {
+ "BAR": "foo=yar",
+ },
+ {
+ "BAR": "=foo",
+ },
+ }
+ expected := []string{
+ `PACKER_BUILDER_TYPE='iso' PACKER_BUILD_NAME='vmware' `,
+ `BAR='foo' FOO='bar' PACKER_BUILDER_TYPE='iso' PACKER_BUILD_NAME='vmware' `,
+ `BAR='foo'"'"'s' FOO='bar'"'"'s' PACKER_BUILDER_TYPE='iso' PACKER_BUILD_NAME='vmware' `,
+ `BAR='foo' BAZ='qux' FOO='bar' PACKER_BUILDER_TYPE='iso' PACKER_BUILD_NAME='vmware' YAR='yaa' `,
+ `BAR='foo=yar' FOO='bar=baz' PACKER_BUILDER_TYPE='iso' PACKER_BUILD_NAME='vmware' `,
+ `BAR='=foo' FOO='=bar' PACKER_BUILDER_TYPE='iso' PACKER_BUILD_NAME='vmware' `,
+ }
+
+ p := new(Provisioner)
+ p.generatedData = generatedData()
+ p.Prepare(config)
+
+ // Defaults provided by Packer
+ p.config.PackerBuildName = "vmware"
+ p.config.PackerBuilderType = "iso"
+
+ for i, expectedValue := range expected {
+ p.config.Vars = userEnvVarTests[i]
+ p.config.Env = userEnvVarEnvmapTests[i]
+ flattenedEnvVars = p.createFlattenedEnvVars()
+ if flattenedEnvVars != expectedValue {
+ t.Fatalf("expected flattened env vars to be: %s, got %s.", expectedValue, flattenedEnvVars)
+ }
+ }
+}
+
+func TestProvisioner_createFlattenedEnvVars_withEnvVarFormat(t *testing.T) {
+ var flattenedEnvVars string
+ config := testConfig()
+
+ userEnvVarTests := [][]string{
+ {}, // No user env var
+ {"FOO=bar"}, // Single user env var
+ {"FOO=bar's"}, // User env var with single quote in value
+ {"FOO=bar", "BAZ=qux"}, // Multiple user env vars
+ {"FOO=bar=baz"}, // User env var with value containing equals
+ {"FOO==bar"}, // User env var with value starting with equals
+ }
+ userEnvVarEnvmapTests := []map[string]string{
+ {},
+ {
+ "BAR": "foo",
+ },
+ {
+ "BAR": "foo's",
+ },
+ {
+ "BAR": "foo",
+ "YAR": "yaa",
+ },
+ {
+ "BAR": "foo=yar",
+ },
+ {
+ "BAR": "=foo",
+ },
+ }
+ expected := []string{
+ `PACKER_BUILDER_TYPE=iso PACKER_BUILD_NAME=vmware `,
+ `BAR=foo FOO=bar PACKER_BUILDER_TYPE=iso PACKER_BUILD_NAME=vmware `,
+ `BAR=foo'"'"'s FOO=bar'"'"'s PACKER_BUILDER_TYPE=iso PACKER_BUILD_NAME=vmware `,
+ `BAR=foo BAZ=qux FOO=bar PACKER_BUILDER_TYPE=iso PACKER_BUILD_NAME=vmware YAR=yaa `,
+ `BAR=foo=yar FOO=bar=baz PACKER_BUILDER_TYPE=iso PACKER_BUILD_NAME=vmware `,
+ `BAR==foo FOO==bar PACKER_BUILDER_TYPE=iso PACKER_BUILD_NAME=vmware `,
+ }
+
+ p := new(Provisioner)
+ p.generatedData = generatedData()
+ p.config.EnvVarFormat = "%s=%s "
+ p.Prepare(config)
+
+ // Defaults provided by Packer
+ p.config.PackerBuildName = "vmware"
+ p.config.PackerBuilderType = "iso"
+
+ for i, expectedValue := range expected {
+ p.config.Vars = userEnvVarTests[i]
+ p.config.Env = userEnvVarEnvmapTests[i]
+ flattenedEnvVars = p.createFlattenedEnvVars()
+ if flattenedEnvVars != expectedValue {
+ t.Fatalf("expected flattened env vars to be: %s, got %s.", expectedValue, flattenedEnvVars)
+ }
+ }
+}
+
+func TestProvisioner_createEnvVarFileContent(t *testing.T) {
+ var flattenedEnvVars string
+ config := testConfig()
+
+ userEnvVarTests := [][]string{
+ {}, // No user env var
+ {"FOO=bar"}, // Single user env var
+ {"FOO=bar's"}, // User env var with single quote in value
+ {"FOO=bar", "BAZ=qux"}, // Multiple user env vars
+ {"FOO=bar=baz"}, // User env var with value containing equals
+ {"FOO==bar"}, // User env var with value starting with equals
+ }
+ userEnvVarEnvmapTests := []map[string]string{
+ {},
+ {
+ "BAR": "foo",
+ },
+ {
+ "BAR": "foo's",
+ },
+ {
+ "BAR": "foo",
+ "YAR": "yaa",
+ },
+ {
+ "BAR": "foo=yar",
+ },
+ {
+ "BAR": "=foo",
+ },
+ }
+ expected := []string{
+ `export PACKER_BUILDER_TYPE='iso'
+export PACKER_BUILD_NAME='vmware'
+`,
+ `export BAR='foo'
+export FOO='bar'
+export PACKER_BUILDER_TYPE='iso'
+export PACKER_BUILD_NAME='vmware'
+`,
+ `export BAR='foo'"'"'s'
+export FOO='bar'"'"'s'
+export PACKER_BUILDER_TYPE='iso'
+export PACKER_BUILD_NAME='vmware'
+`,
+ `export BAR='foo'
+export BAZ='qux'
+export FOO='bar'
+export PACKER_BUILDER_TYPE='iso'
+export PACKER_BUILD_NAME='vmware'
+export YAR='yaa'
+`,
+ `export BAR='foo=yar'
+export FOO='bar=baz'
+export PACKER_BUILDER_TYPE='iso'
+export PACKER_BUILD_NAME='vmware'
+`,
+ `export BAR='=foo'
+export FOO='=bar'
+export PACKER_BUILDER_TYPE='iso'
+export PACKER_BUILD_NAME='vmware'
+`,
+ }
+
+ p := new(Provisioner)
+ p.generatedData = generatedData()
+ p.config.UseEnvVarFile = true
+ p.Prepare(config)
+
+ // Defaults provided by Packer
+ p.config.PackerBuildName = "vmware"
+ p.config.PackerBuilderType = "iso"
+
+ for i, expectedValue := range expected {
+ p.config.Vars = userEnvVarTests[i]
+ p.config.Env = userEnvVarEnvmapTests[i]
+ flattenedEnvVars = p.createEnvVarFileContent()
+ if flattenedEnvVars != expectedValue {
+ t.Fatalf("expected flattened env vars to be: %s, got %s.", expectedValue, flattenedEnvVars)
+ }
+ }
+}
+
+func TestProvisioner_createEnvVarFileContent_withEnvVarFormat(t *testing.T) {
+ var flattenedEnvVars string
+ config := testConfig()
+
+ userEnvVarTests := [][]string{
+ {}, // No user env var
+ {"FOO=bar", "BAZ=qux"}, // Multiple user env vars
+ {"FOO=bar=baz"}, // User env var with value containing equals
+ {"FOO==bar"}, // User env var with value starting with equals
+ }
+ userEnvVarEnvmapTests := []map[string]string{
+ {},
+ {
+ "BAR": "foo",
+ "YAR": "yaa",
+ },
+ {
+ "BAR": "foo=yar",
+ },
+ {
+ "BAR": "=foo",
+ },
+ }
+ expected := []string{
+ `PACKER_BUILDER_TYPE=iso
+PACKER_BUILD_NAME=vmware
+`,
+ `BAR=foo
+BAZ=qux
+FOO=bar
+PACKER_BUILDER_TYPE=iso
+PACKER_BUILD_NAME=vmware
+YAR=yaa
+`,
+ `BAR=foo=yar
+FOO=bar=baz
+PACKER_BUILDER_TYPE=iso
+PACKER_BUILD_NAME=vmware
+`,
+ `BAR==foo
+FOO==bar
+PACKER_BUILDER_TYPE=iso
+PACKER_BUILD_NAME=vmware
+`,
+ }
+
+ p := new(Provisioner)
+ p.generatedData = generatedData()
+ p.config.UseEnvVarFile = true
+ //User provided env_var_format without export prefix
+ p.config.EnvVarFormat = "%s=%s\n"
+ p.Prepare(config)
+
+ // Defaults provided by Packer
+ p.config.PackerBuildName = "vmware"
+ p.config.PackerBuilderType = "iso"
+
+ for i, expectedValue := range expected {
+ p.config.Vars = userEnvVarTests[i]
+ p.config.Env = userEnvVarEnvmapTests[i]
+ flattenedEnvVars = p.createEnvVarFileContent()
+ if flattenedEnvVars != expectedValue {
+ t.Fatalf("expected flattened env vars to be: %q, got %q.", expectedValue, flattenedEnvVars)
+ }
+ }
+}
+
+func TestProvisioner_RemoteFolderSetSuccessfully(t *testing.T) {
+ config := testConfig()
+
+ expectedRemoteFolder := "/example/path"
+ config["remote_folder"] = expectedRemoteFolder
+
+ p := new(Provisioner)
+ err := p.Prepare(config)
+ if err != nil {
+ t.Fatalf("should not have error: %s", err)
+ }
+
+ if !strings.Contains(p.config.RemotePath, expectedRemoteFolder) {
+ t.Fatalf("remote path does not contain remote_folder")
+ }
+}
+
+func TestProvisioner_RemoteFolderDefaultsToTmp(t *testing.T) {
+ config := testConfig()
+
+ p := new(Provisioner)
+ err := p.Prepare(config)
+ if err != nil {
+ t.Fatalf("should not have error: %s", err)
+ }
+
+ if p.config.RemoteFolder != "/tmp" {
+ t.Fatalf("remote_folder did not default to /tmp")
+ }
+
+ if !strings.Contains(p.config.RemotePath, "/tmp") {
+ t.Fatalf("remote path does not contain remote_folder")
+ }
+}
+
+func TestProvisioner_RemoteFileSetSuccessfully(t *testing.T) {
+ config := testConfig()
+
+ expectedRemoteFile := "example.sh"
+ config["remote_file"] = expectedRemoteFile
+
+ p := new(Provisioner)
+ err := p.Prepare(config)
+ if err != nil {
+ t.Fatalf("should not have error: %s", err)
+ }
+
+ if !strings.Contains(p.config.RemotePath, expectedRemoteFile) {
+ t.Fatalf("remote path does not contain remote_file")
+ }
+}
+
+func TestProvisioner_RemoteFileDefaultsToScriptnnnn(t *testing.T) {
+ config := testConfig()
+
+ p := new(Provisioner)
+ err := p.Prepare(config)
+ if err != nil {
+ t.Fatalf("should not have error: %s", err)
+ }
+
+ remoteFileRegex := regexp.MustCompile("script_[0-9]{1,4}.sh")
+
+ if !remoteFileRegex.MatchString(p.config.RemoteFile) {
+ t.Fatalf("remote_file did not default to script_nnnn.sh: %q", p.config.RemoteFile)
+ }
+
+ if !remoteFileRegex.MatchString(p.config.RemotePath) {
+ t.Fatalf("remote_path did not match script_nnnn.sh: %q", p.config.RemotePath)
+ }
+}
+
+func TestProvisioner_RemotePathSetViaRemotePathAndRemoteFile(t *testing.T) {
+ config := testConfig()
+
+ expectedRemoteFile := "example.sh"
+ expectedRemoteFolder := "/example/path"
+ config["remote_file"] = expectedRemoteFile
+ config["remote_folder"] = expectedRemoteFolder
+
+ p := new(Provisioner)
+ err := p.Prepare(config)
+ if err != nil {
+ t.Fatalf("should not have error: %s", err)
+ }
+
+ if p.config.RemotePath != expectedRemoteFolder+"/"+expectedRemoteFile {
+ t.Fatalf("remote path does not contain remote_file: %q", p.config.RemotePath)
+ }
+}
+
+func TestProvisioner_RemotePathOverridesRemotePathAndRemoteFile(t *testing.T) {
+ config := testConfig()
+
+ expectedRemoteFile := "example.sh"
+ expectedRemoteFolder := "/example/path"
+ expectedRemotePath := "/example/remote/path/script.sh"
+ config["remote_file"] = expectedRemoteFile
+ config["remote_folder"] = expectedRemoteFolder
+ config["remote_path"] = expectedRemotePath
+
+ p := new(Provisioner)
+ err := p.Prepare(config)
+ if err != nil {
+ t.Fatalf("should not have error: %s", err)
+ }
+
+ if p.config.RemotePath != expectedRemotePath {
+ t.Fatalf("remote path does not contain remote_path: %q", p.config.RemotePath)
+ }
+}
+
+func TestProvisionerRemotePathDefaultsSuccessfully(t *testing.T) {
+ config := testConfig()
+
+ p := new(Provisioner)
+ err := p.Prepare(config)
+ if err != nil {
+ t.Fatalf("should not have error: %s", err)
+ }
+
+ remotePathRegex := regexp.MustCompile("/tmp/script_[0-9]{1,4}.sh")
+
+ if !remotePathRegex.MatchString(p.config.RemotePath) {
+ t.Fatalf("remote path does not match the expected default regex: %q", p.config.RemotePath)
+ }
+}
+
+func generatedData() map[string]interface{} {
+ return map[string]interface{}{
+ "PackerHTTPAddr": commonsteps.HttpAddrNotImplemented,
+ "PackerHTTPIP": commonsteps.HttpIPNotImplemented,
+ "PackerHTTPPort": commonsteps.HttpPortNotImplemented,
+ }
+}
diff --git a/v1.9.4/provisioner/shell/test-fixtures/shell-provisioner.txt b/v1.9.4/provisioner/shell/test-fixtures/shell-provisioner.txt
new file mode 100644
index 0000000..7bf3dcd
--- /dev/null
+++ b/v1.9.4/provisioner/shell/test-fixtures/shell-provisioner.txt
@@ -0,0 +1,12 @@
+{
+ "type": "shell",
+ "inline": [
+ "echo build ID is {{ build `ID`}} and build UUID is {{ build `PackerRunUUID` }}> provisioner.{{ build `PackerRunUUID`}}.txt"
+ ]
+},
+{
+ "type": "file",
+ "source": "provisioner.{{ build `PackerRunUUID`}}.txt",
+ "destination": "./test-fixtures/provisioner.shell.txt",
+ "direction": "download"
+}
\ No newline at end of file
diff --git a/v1.9.4/provisioner/shell/unix_reader.go b/v1.9.4/provisioner/shell/unix_reader.go
new file mode 100644
index 0000000..dc74647
--- /dev/null
+++ b/v1.9.4/provisioner/shell/unix_reader.go
@@ -0,0 +1,68 @@
+// Copyright (c) HashiCorp, Inc.
+// SPDX-License-Identifier: MPL-2.0
+
+package shell
+
+import (
+ "bufio"
+ "io"
+ "sync"
+)
+
+// UnixReader is a Reader implementation that automatically converts
+// Windows line endings to Unix line endings.
+type UnixReader struct {
+ Reader io.Reader
+
+ buf []byte
+ once sync.Once
+ scanner *bufio.Scanner
+}
+
+func (r *UnixReader) Read(p []byte) (n int, err error) {
+ // Create the buffered reader once
+ r.once.Do(func() {
+ r.scanner = bufio.NewScanner(r.Reader)
+ r.scanner.Split(scanUnixLine)
+ })
+
+ // If we have no data in our buffer, scan to the next token
+ if len(r.buf) == 0 {
+ if !r.scanner.Scan() {
+ err = r.scanner.Err()
+ if err == nil {
+ err = io.EOF
+ }
+
+ return 0, err
+ }
+
+ r.buf = r.scanner.Bytes()
+ }
+
+ // Write out as much data as we can to the buffer, storing the rest
+ // for the next read.
+ n = len(p)
+ if n > len(r.buf) {
+ n = len(r.buf)
+ }
+ copy(p, r.buf)
+ r.buf = r.buf[n:]
+
+ return
+}
+
+// scanUnixLine is a bufio.Scanner SplitFunc. It tokenizes on lines, but
+// only returns unix-style lines. So even if the line is "one\r\n", the
+// token returned will be "one\n".
+func scanUnixLine(data []byte, atEOF bool) (advance int, token []byte, err error) {
+ advance, token, err = bufio.ScanLines(data, atEOF)
+ if advance == 0 {
+ // If we reached the end of a line without a newline, then
+ // just return as it is. Otherwise the Scanner will keep trying
+ // to scan, blocking forever.
+ return
+ }
+
+ return advance, append(token, '\n'), err
+}
diff --git a/v1.9.4/provisioner/shell/unix_reader_test.go b/v1.9.4/provisioner/shell/unix_reader_test.go
new file mode 100644
index 0000000..96c470c
--- /dev/null
+++ b/v1.9.4/provisioner/shell/unix_reader_test.go
@@ -0,0 +1,54 @@
+// Copyright (c) HashiCorp, Inc.
+// SPDX-License-Identifier: MPL-2.0
+
+package shell
+
+import (
+ "bytes"
+ "io"
+ "testing"
+)
+
+func TestUnixReader_impl(t *testing.T) {
+ var raw interface{}
+ raw = new(UnixReader)
+ if _, ok := raw.(io.Reader); !ok {
+ t.Fatal("should be reader")
+ }
+}
+
+func TestUnixReader(t *testing.T) {
+ input := "one\r\ntwo\n\r\nthree\r\n"
+ expected := "one\ntwo\n\nthree\n"
+
+ unixReaderTest(t, input, expected)
+}
+
+func TestUnixReader_unixOnly(t *testing.T) {
+ input := "\none\n\ntwo\nthree\n\n"
+ expected := "\none\n\ntwo\nthree\n\n"
+
+ unixReaderTest(t, input, expected)
+}
+
+func TestUnixReader_readsLastLine(t *testing.T) {
+ input := "one\ntwo"
+ expected := "one\ntwo\n"
+
+ unixReaderTest(t, input, expected)
+}
+
+func unixReaderTest(t *testing.T, input string, expected string) {
+ r := &UnixReader{
+ Reader: bytes.NewReader([]byte(input)),
+ }
+
+ result := new(bytes.Buffer)
+ if _, err := io.Copy(result, r); err != nil {
+ t.Fatalf("err: %s", err)
+ }
+
+ if result.String() != expected {
+ t.Fatalf("bad: %#v", result.String())
+ }
+}
diff --git a/v1.9.4/provisioner/shell/version/version.go b/v1.9.4/provisioner/shell/version/version.go
new file mode 100644
index 0000000..f192bb3
--- /dev/null
+++ b/v1.9.4/provisioner/shell/version/version.go
@@ -0,0 +1,16 @@
+// Copyright (c) HashiCorp, Inc.
+// SPDX-License-Identifier: MPL-2.0
+
+package version
+
+import (
+ "github.com/hashicorp/packer-plugin-sdk/version"
+ packerVersion "github.com/hashicorp/packer/version"
+)
+
+var ShellPluginVersion *version.PluginVersion
+
+func init() {
+ ShellPluginVersion = version.InitializePluginVersion(
+ packerVersion.Version, packerVersion.VersionPrerelease)
+}
diff --git a/v1.9.4/provisioner/sleep/provisioner.go b/v1.9.4/provisioner/sleep/provisioner.go
new file mode 100644
index 0000000..8dfb4ce
--- /dev/null
+++ b/v1.9.4/provisioner/sleep/provisioner.go
@@ -0,0 +1,38 @@
+// Copyright (c) HashiCorp, Inc.
+// SPDX-License-Identifier: MPL-2.0
+
+//go:generate packer-sdc mapstructure-to-hcl2 -type Provisioner
+
+package sleep
+
+import (
+ "context"
+ "time"
+
+ "github.com/hashicorp/hcl/v2/hcldec"
+ packersdk "github.com/hashicorp/packer-plugin-sdk/packer"
+ "github.com/hashicorp/packer-plugin-sdk/template/config"
+)
+
+type Provisioner struct {
+ Duration time.Duration
+}
+
+var _ packersdk.Provisioner = new(Provisioner)
+
+func (p *Provisioner) ConfigSpec() hcldec.ObjectSpec { return p.FlatMapstructure().HCL2Spec() }
+
+func (p *Provisioner) FlatConfig() interface{} { return p.FlatMapstructure() }
+
+func (p *Provisioner) Prepare(raws ...interface{}) error {
+ return config.Decode(&p, &config.DecodeOpts{}, raws...)
+}
+
+func (p *Provisioner) Provision(ctx context.Context, _ packersdk.Ui, _ packersdk.Communicator, _ map[string]interface{}) error {
+ select {
+ case <-ctx.Done():
+ return ctx.Err()
+ case <-time.After(p.Duration):
+ return nil
+ }
+}
diff --git a/v1.9.4/provisioner/sleep/provisioner.hcl2spec.go b/v1.9.4/provisioner/sleep/provisioner.hcl2spec.go
new file mode 100644
index 0000000..2b73619
--- /dev/null
+++ b/v1.9.4/provisioner/sleep/provisioner.hcl2spec.go
@@ -0,0 +1,31 @@
+// Code generated by "packer-sdc mapstructure-to-hcl2"; DO NOT EDIT.
+
+package sleep
+
+import (
+ "github.com/hashicorp/hcl/v2/hcldec"
+ "github.com/zclconf/go-cty/cty"
+)
+
+// FlatProvisioner is an auto-generated flat version of Provisioner.
+// Where the contents of a field with a `mapstructure:,squash` tag are bubbled up.
+type FlatProvisioner struct {
+ Duration *string `cty:"duration" hcl:"duration"`
+}
+
+// FlatMapstructure returns a new FlatProvisioner.
+// FlatProvisioner is an auto-generated flat version of Provisioner.
+// Where the contents a fields with a `mapstructure:,squash` tag are bubbled up.
+func (*Provisioner) FlatMapstructure() interface{ HCL2Spec() map[string]hcldec.Spec } {
+ return new(FlatProvisioner)
+}
+
+// HCL2Spec returns the hcl spec of a Provisioner.
+// This spec is used by HCL to read the fields of Provisioner.
+// The decoded values from this spec will then be applied to a FlatProvisioner.
+func (*FlatProvisioner) HCL2Spec() map[string]hcldec.Spec {
+ s := map[string]hcldec.Spec{
+ "duration": &hcldec.AttrSpec{Name: "duration", Type: cty.String, Required: false},
+ }
+ return s
+}
diff --git a/v1.9.4/provisioner/sleep/provisioner_test.go b/v1.9.4/provisioner/sleep/provisioner_test.go
new file mode 100644
index 0000000..315849e
--- /dev/null
+++ b/v1.9.4/provisioner/sleep/provisioner_test.go
@@ -0,0 +1,59 @@
+// Copyright (c) HashiCorp, Inc.
+// SPDX-License-Identifier: MPL-2.0
+
+package sleep
+
+import (
+ "context"
+ "testing"
+ "time"
+)
+
+func test1sConfig() map[string]interface{} {
+ return map[string]interface{}{
+ "duration": "1s",
+ }
+}
+
+func TestConfigPrepare_1s(t *testing.T) {
+ raw := test1sConfig()
+ var p Provisioner
+ err := p.Prepare(raw)
+ if err != nil {
+ t.Fatalf("prerare failed: %v", err)
+ }
+
+ if p.Duration != time.Second {
+ t.Fatal("wrong duration")
+ }
+}
+
+func TestProvisioner_Provision(t *testing.T) {
+ ctxCancelled, cancel := context.WithCancel(context.Background())
+ cancel()
+ type fields struct {
+ Duration time.Duration
+ }
+ type args struct {
+ ctx context.Context
+ }
+ tests := []struct {
+ name string
+ fields fields
+ args args
+ wantErr bool
+ }{
+ {"valid sleep", fields{1 * time.Millisecond}, args{context.Background()}, false},
+ {"timeout", fields{1 * time.Millisecond}, args{ctxCancelled}, true},
+ }
+ for _, tt := range tests {
+ t.Run(tt.name, func(t *testing.T) {
+ p := &Provisioner{
+ Duration: tt.fields.Duration,
+ }
+ if err := p.Provision(tt.args.ctx, nil, nil, make(map[string]interface{})); (err != nil) != tt.wantErr {
+ t.Errorf("Provisioner.Provision() error = %v, wantErr %v", err, tt.wantErr)
+ }
+ })
+ }
+}
diff --git a/v1.9.4/provisioner/sleep/version/version.go b/v1.9.4/provisioner/sleep/version/version.go
new file mode 100644
index 0000000..bdad497
--- /dev/null
+++ b/v1.9.4/provisioner/sleep/version/version.go
@@ -0,0 +1,16 @@
+// Copyright (c) HashiCorp, Inc.
+// SPDX-License-Identifier: MPL-2.0
+
+package version
+
+import (
+ "github.com/hashicorp/packer-plugin-sdk/version"
+ packerVersion "github.com/hashicorp/packer/version"
+)
+
+var SleepProvisionerVersion *version.PluginVersion
+
+func init() {
+ SleepProvisionerVersion = version.InitializePluginVersion(
+ packerVersion.Version, packerVersion.VersionPrerelease)
+}
diff --git a/v1.9.4/provisioner/windows-restart/provisioner.go b/v1.9.4/provisioner/windows-restart/provisioner.go
new file mode 100644
index 0000000..8aaa359
--- /dev/null
+++ b/v1.9.4/provisioner/windows-restart/provisioner.go
@@ -0,0 +1,293 @@
+// Copyright (c) HashiCorp, Inc.
+// SPDX-License-Identifier: MPL-2.0
+
+//go:generate packer-sdc mapstructure-to-hcl2 -type Config
+
+package restart
+
+import (
+ "bytes"
+ "context"
+ "fmt"
+ "io"
+
+ "log"
+ "strings"
+ "sync"
+ "time"
+
+ "github.com/hashicorp/hcl/v2/hcldec"
+ "github.com/hashicorp/packer-plugin-sdk/common"
+ packersdk "github.com/hashicorp/packer-plugin-sdk/packer"
+ "github.com/hashicorp/packer-plugin-sdk/retry"
+ "github.com/hashicorp/packer-plugin-sdk/template/config"
+ "github.com/hashicorp/packer-plugin-sdk/template/interpolate"
+ "github.com/masterzen/winrm"
+)
+
+var DefaultRestartCommand = `shutdown /r /f /t 0 /c "packer restart"`
+var DefaultRestartCheckCommand = winrm.Powershell(`echo ("{0} restarted." -f [System.Net.Dns]::GetHostName())`)
+var retryableSleep = 5 * time.Second
+var TryCheckReboot = `shutdown /r /f /t 60 /c "packer restart test"`
+var AbortReboot = `shutdown /a`
+
+var DefaultRegistryKeys = []string{
+ "HKLM:SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Component Based Servicing\\RebootPending",
+ "HKLM:SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Component Based Servicing\\PackagesPending",
+ "HKLM:Software\\Microsoft\\Windows\\CurrentVersion\\Component Based Servicing\\RebootInProgress",
+}
+
+type Config struct {
+ common.PackerConfig `mapstructure:",squash"`
+
+ // The command used to restart the guest machine
+ RestartCommand string `mapstructure:"restart_command"`
+
+ // The command to run after executing `restart_command` to check if the guest machine has restarted.
+ // This command will retry until the connection to the guest machine has been restored or `restart_timeout` has exceeded.
+ // The output of this command will be displayed to the user.
+ RestartCheckCommand string `mapstructure:"restart_check_command"`
+
+ // The timeout for waiting for the machine to restart
+ RestartTimeout time.Duration `mapstructure:"restart_timeout"`
+
+ // Whether to check the registry (see RegistryKeys) for pending reboots
+ CheckKey bool `mapstructure:"check_registry"`
+
+ // custom keys to check for
+ RegistryKeys []string `mapstructure:"registry_keys"`
+
+ ctx interpolate.Context
+}
+
+type Provisioner struct {
+ config Config
+ comm packersdk.Communicator
+ ui packersdk.Ui
+ cancel chan struct{}
+ cancelLock sync.Mutex
+}
+
+func (p *Provisioner) ConfigSpec() hcldec.ObjectSpec { return p.config.FlatMapstructure().HCL2Spec() }
+
+func (p *Provisioner) Prepare(raws ...interface{}) error {
+ err := config.Decode(&p.config, &config.DecodeOpts{
+ PluginType: "windows-restart",
+ Interpolate: true,
+ InterpolateContext: &p.config.ctx,
+ InterpolateFilter: &interpolate.RenderFilter{
+ Exclude: []string{
+ "execute_command",
+ },
+ },
+ }, raws...)
+ if err != nil {
+ return err
+ }
+
+ if p.config.RestartCommand == "" {
+ p.config.RestartCommand = DefaultRestartCommand
+ }
+
+ if p.config.RestartCheckCommand == "" {
+ p.config.RestartCheckCommand = DefaultRestartCheckCommand
+ }
+
+ if p.config.RestartTimeout == 0 {
+ p.config.RestartTimeout = 5 * time.Minute
+ }
+
+ if len(p.config.RegistryKeys) == 0 {
+ p.config.RegistryKeys = DefaultRegistryKeys
+ }
+
+ return nil
+}
+
+func (p *Provisioner) Provision(ctx context.Context, ui packersdk.Ui, comm packersdk.Communicator, _ map[string]interface{}) error {
+ p.cancelLock.Lock()
+ p.cancel = make(chan struct{})
+ p.cancelLock.Unlock()
+
+ ui.Say("Restarting Machine")
+ p.comm = comm
+ p.ui = ui
+
+ var cmd *packersdk.RemoteCmd
+ command := p.config.RestartCommand
+ err := retry.Config{StartTimeout: p.config.RestartTimeout}.Run(ctx, func(context.Context) error {
+ cmd = &packersdk.RemoteCmd{Command: command}
+ return cmd.RunWithUi(ctx, comm, ui)
+ })
+
+ if err != nil {
+ return err
+ }
+
+ if cmd.ExitStatus() != 0 && cmd.ExitStatus() != 1115 && cmd.ExitStatus() != 1190 {
+ return fmt.Errorf("Restart script exited with non-zero exit status: %d", cmd.ExitStatus())
+ }
+
+ return waitForRestart(ctx, p, comm)
+}
+
+var waitForRestart = func(ctx context.Context, p *Provisioner, comm packersdk.Communicator) error {
+ ui := p.ui
+ ui.Say("Waiting for machine to restart...")
+ waitDone := make(chan bool, 1)
+ timeout := time.After(p.config.RestartTimeout)
+ var err error
+
+ p.comm = comm
+ var cmd *packersdk.RemoteCmd
+ trycommand := TryCheckReboot
+ abortcommand := AbortReboot
+
+ // Stolen from Vagrant reboot checker
+ for {
+ log.Printf("Check if machine is rebooting...")
+ cmd = &packersdk.RemoteCmd{Command: trycommand}
+ err = cmd.RunWithUi(ctx, comm, ui)
+ if err != nil {
+ // Couldn't execute, we assume machine is rebooting already
+ break
+ }
+ if cmd.ExitStatus() == 1 {
+ // SSH provisioner, and we're already rebooting. SSH can reconnect
+ // without our help; exit this wait loop.
+ break
+ }
+ if cmd.ExitStatus() == 1115 || cmd.ExitStatus() == 1190 || cmd.ExitStatus() == 1717 {
+ // Reboot already in progress but not completed
+ log.Printf("Reboot already in progress, waiting...")
+ time.Sleep(10 * time.Second)
+ }
+ if cmd.ExitStatus() == 0 {
+ // Cancel reboot we created to test if machine was already rebooting
+ cmd = &packersdk.RemoteCmd{Command: abortcommand}
+ cmd.RunWithUi(ctx, comm, ui)
+ break
+ }
+ }
+
+ go func() {
+ log.Printf("Waiting for machine to become available...")
+ err = waitForCommunicator(ctx, p)
+ waitDone <- true
+ }()
+
+ log.Printf("Waiting for machine to reboot with timeout: %s", p.config.RestartTimeout)
+
+WaitLoop:
+ for {
+ // Wait for either WinRM to become available, a timeout to occur,
+ // or an interrupt to come through.
+ select {
+ case <-waitDone:
+ if err != nil {
+ ui.Error(fmt.Sprintf("Error waiting for machine to restart: %s", err))
+ return err
+ }
+
+ ui.Say("Machine successfully restarted, moving on")
+ close(p.cancel)
+ break WaitLoop
+ case <-timeout:
+ err := fmt.Errorf("Timeout waiting for machine to restart.")
+ ui.Error(err.Error())
+ close(p.cancel)
+ return err
+ case <-p.cancel:
+ close(waitDone)
+ return fmt.Errorf("Interrupt detected, quitting waiting for machine to restart")
+ }
+ }
+ return nil
+
+}
+
+var waitForCommunicator = func(ctx context.Context, p *Provisioner) error {
+ runCustomRestartCheck := true
+ if p.config.RestartCheckCommand == DefaultRestartCheckCommand {
+ runCustomRestartCheck = false
+ }
+ // This command is configurable by the user to make sure that the
+ // vm has met their necessary criteria for having restarted. If the
+ // user doesn't set a special restart command, we just run the
+ // default as cmdModuleLoad below.
+ cmdRestartCheck := &packersdk.RemoteCmd{Command: p.config.RestartCheckCommand}
+ log.Printf("Checking that communicator is connected with: '%s'",
+ cmdRestartCheck.Command)
+ for {
+ select {
+ case <-ctx.Done():
+ log.Println("Communicator wait canceled, exiting loop")
+ return fmt.Errorf("Communicator wait canceled")
+ case <-time.After(retryableSleep):
+ }
+ if runCustomRestartCheck {
+ // run user-configured restart check
+ err := cmdRestartCheck.RunWithUi(ctx, p.comm, p.ui)
+ if err != nil {
+ log.Printf("Communication connection err: %s", err)
+ continue
+ }
+ log.Printf("Connected to machine")
+ runCustomRestartCheck = false
+ }
+ // This is the non-user-configurable check that powershell
+ // modules have loaded.
+
+ // If we catch the restart in just the right place, we will be able
+ // to run the restart check but the output will be an error message
+ // about how it needs powershell modules to load, and we will start
+ // provisioning before powershell is actually ready.
+ // In this next check, we parse stdout to make sure that the command is
+ // actually running as expected.
+ cmdModuleLoad := &packersdk.RemoteCmd{Command: DefaultRestartCheckCommand}
+ var buf, buf2 bytes.Buffer
+ cmdModuleLoad.Stdout = &buf
+ cmdModuleLoad.Stdout = io.MultiWriter(cmdModuleLoad.Stdout, &buf2)
+
+ cmdModuleLoad.RunWithUi(ctx, p.comm, p.ui)
+ stdoutToRead := buf2.String()
+
+ if !strings.Contains(stdoutToRead, "restarted.") {
+ log.Printf("echo didn't succeed; retrying...")
+ continue
+ }
+
+ if p.config.CheckKey {
+ log.Printf("Connected to machine")
+ shouldContinue := false
+ for _, RegKey := range p.config.RegistryKeys {
+ KeyTestCommand := winrm.Powershell(fmt.Sprintf(`Test-Path "%s"`, RegKey))
+ cmdKeyCheck := &packersdk.RemoteCmd{Command: KeyTestCommand}
+ log.Printf("Checking registry for pending reboots")
+ var buf, buf2 bytes.Buffer
+ cmdKeyCheck.Stdout = &buf
+ cmdKeyCheck.Stdout = io.MultiWriter(cmdKeyCheck.Stdout, &buf2)
+
+ err := cmdKeyCheck.RunWithUi(ctx, p.comm, p.ui)
+ if err != nil {
+ log.Printf("Communication connection err: %s", err)
+ shouldContinue = true
+ }
+
+ stdoutToRead := buf2.String()
+ if strings.Contains(stdoutToRead, "True") {
+ log.Printf("RegistryKey %s exists; waiting...", KeyTestCommand)
+ shouldContinue = true
+ } else {
+ log.Printf("No Registry keys found; exiting wait loop")
+ }
+ }
+ if shouldContinue {
+ continue
+ }
+ }
+ break
+ }
+
+ return nil
+}
diff --git a/v1.9.4/provisioner/windows-restart/provisioner.hcl2spec.go b/v1.9.4/provisioner/windows-restart/provisioner.hcl2spec.go
new file mode 100644
index 0000000..6383c2c
--- /dev/null
+++ b/v1.9.4/provisioner/windows-restart/provisioner.hcl2spec.go
@@ -0,0 +1,55 @@
+// Code generated by "packer-sdc mapstructure-to-hcl2"; DO NOT EDIT.
+
+package restart
+
+import (
+ "github.com/hashicorp/hcl/v2/hcldec"
+ "github.com/zclconf/go-cty/cty"
+)
+
+// FlatConfig is an auto-generated flat version of Config.
+// Where the contents of a field with a `mapstructure:,squash` tag are bubbled up.
+type FlatConfig struct {
+ PackerBuildName *string `mapstructure:"packer_build_name" cty:"packer_build_name" 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"`
+ RestartCommand *string `mapstructure:"restart_command" cty:"restart_command" hcl:"restart_command"`
+ RestartCheckCommand *string `mapstructure:"restart_check_command" cty:"restart_check_command" hcl:"restart_check_command"`
+ RestartTimeout *string `mapstructure:"restart_timeout" cty:"restart_timeout" hcl:"restart_timeout"`
+ CheckKey *bool `mapstructure:"check_registry" cty:"check_registry" hcl:"check_registry"`
+ RegistryKeys []string `mapstructure:"registry_keys" cty:"registry_keys" hcl:"registry_keys"`
+}
+
+// FlatMapstructure returns a new FlatConfig.
+// FlatConfig is an auto-generated flat version of Config.
+// Where the contents a fields with a `mapstructure:,squash` tag are bubbled up.
+func (*Config) FlatMapstructure() interface{ HCL2Spec() map[string]hcldec.Spec } {
+ return new(FlatConfig)
+}
+
+// HCL2Spec returns the hcl spec of a Config.
+// This spec is used by HCL to read the fields of Config.
+// The decoded values from this spec will then be applied to a FlatConfig.
+func (*FlatConfig) HCL2Spec() map[string]hcldec.Spec {
+ s := map[string]hcldec.Spec{
+ "packer_build_name": &hcldec.AttrSpec{Name: "packer_build_name", Type: cty.String, Required: false},
+ "packer_builder_type": &hcldec.AttrSpec{Name: "packer_builder_type", Type: cty.String, Required: false},
+ "packer_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_sensitive_variables": &hcldec.AttrSpec{Name: "packer_sensitive_variables", Type: cty.List(cty.String), Required: false},
+ "restart_command": &hcldec.AttrSpec{Name: "restart_command", Type: cty.String, Required: false},
+ "restart_check_command": &hcldec.AttrSpec{Name: "restart_check_command", Type: cty.String, Required: false},
+ "restart_timeout": &hcldec.AttrSpec{Name: "restart_timeout", Type: cty.String, Required: false},
+ "check_registry": &hcldec.AttrSpec{Name: "check_registry", Type: cty.Bool, Required: false},
+ "registry_keys": &hcldec.AttrSpec{Name: "registry_keys", Type: cty.List(cty.String), Required: false},
+ }
+ return s
+}
diff --git a/v1.9.4/provisioner/windows-restart/provisioner_test.go b/v1.9.4/provisioner/windows-restart/provisioner_test.go
new file mode 100644
index 0000000..bc68f16
--- /dev/null
+++ b/v1.9.4/provisioner/windows-restart/provisioner_test.go
@@ -0,0 +1,340 @@
+// Copyright (c) HashiCorp, Inc.
+// SPDX-License-Identifier: MPL-2.0
+
+package restart
+
+import (
+ "bytes"
+ "context"
+ "fmt"
+ "testing"
+ "time"
+
+ packersdk "github.com/hashicorp/packer-plugin-sdk/packer"
+)
+
+func testConfig() map[string]interface{} {
+ return map[string]interface{}{}
+}
+
+func TestProvisioner_Impl(t *testing.T) {
+ var raw interface{}
+ raw = &Provisioner{}
+ if _, ok := raw.(packersdk.Provisioner); !ok {
+ t.Fatalf("must be a Provisioner")
+ }
+}
+
+func TestProvisionerPrepare_Defaults(t *testing.T) {
+ var p Provisioner
+ config := testConfig()
+
+ err := p.Prepare(config)
+ if err != nil {
+ t.Fatalf("err: %s", err)
+ }
+
+ if p.config.RestartTimeout != 5*time.Minute {
+ t.Errorf("unexpected restart timeout: %s", p.config.RestartTimeout)
+ }
+
+ if p.config.RestartCommand != "shutdown /r /f /t 0 /c \"packer restart\"" {
+ t.Errorf("unexpected restart command: %s", p.config.RestartCommand)
+ }
+}
+
+func TestProvisionerPrepare_ConfigRetryTimeout(t *testing.T) {
+ var p Provisioner
+ config := testConfig()
+ config["restart_timeout"] = "1m"
+
+ err := p.Prepare(config)
+ if err != nil {
+ t.Fatalf("err: %s", err)
+ }
+
+ if p.config.RestartTimeout != 1*time.Minute {
+ t.Errorf("unexpected restart timeout: %s", p.config.RestartTimeout)
+ }
+}
+
+func TestProvisionerPrepare_ConfigErrors(t *testing.T) {
+ var p Provisioner
+ config := testConfig()
+ config["restart_timeout"] = "m"
+
+ err := p.Prepare(config)
+ if err == nil {
+ t.Fatal("Expected error parsing restart_timeout but did not receive one.")
+ }
+}
+
+func TestProvisionerPrepare_InvalidKey(t *testing.T) {
+ var p Provisioner
+ config := testConfig()
+
+ // Add a random key
+ config["i_should_not_be_valid"] = true
+ err := p.Prepare(config)
+ if err == nil {
+ t.Fatal("should have error")
+ }
+}
+
+func testUi() *packersdk.BasicUi {
+ return &packersdk.BasicUi{
+ Reader: new(bytes.Buffer),
+ Writer: new(bytes.Buffer),
+ ErrorWriter: new(bytes.Buffer),
+ }
+}
+
+func TestProvisionerProvision_Success(t *testing.T) {
+ config := testConfig()
+
+ // Defaults provided by Packer
+ ui := testUi()
+ p := new(Provisioner)
+
+ // Defaults provided by Packer
+ comm := new(packersdk.MockCommunicator)
+ p.Prepare(config)
+ waitForCommunicatorOld := waitForCommunicator
+ waitForCommunicator = func(context.Context, *Provisioner) error {
+ return nil
+ }
+ waitForRestartOld := waitForRestart
+ waitForRestart = func(context.Context, *Provisioner, packersdk.Communicator) error {
+ return nil
+ }
+ err := p.Provision(context.Background(), ui, comm, make(map[string]interface{}))
+ if err != nil {
+ t.Fatal("should not have error")
+ }
+
+ expectedCommand := DefaultRestartCommand
+
+ // Should run the command without alteration
+ if comm.StartCmd.Command != expectedCommand {
+ t.Fatalf("Expect command to be: %s, got %s", expectedCommand, comm.StartCmd.Command)
+ }
+ // Set this back!
+ waitForCommunicator = waitForCommunicatorOld
+ waitForRestart = waitForRestartOld
+}
+
+func TestProvisionerProvision_CustomCommand(t *testing.T) {
+ config := testConfig()
+
+ // Defaults provided by Packer
+ ui := testUi()
+ p := new(Provisioner)
+ expectedCommand := "specialrestart.exe -NOW"
+ config["restart_command"] = expectedCommand
+
+ // Defaults provided by Packer
+ comm := new(packersdk.MockCommunicator)
+ p.Prepare(config)
+ waitForCommunicatorOld := waitForCommunicator
+ waitForCommunicator = func(context.Context, *Provisioner) error {
+ return nil
+ }
+ waitForRestartOld := waitForRestart
+ waitForRestart = func(context.Context, *Provisioner, packersdk.Communicator) error {
+ return nil
+ }
+ err := p.Provision(context.Background(), ui, comm, make(map[string]interface{}))
+ if err != nil {
+ t.Fatal("should not have error")
+ }
+
+ // Should run the command without alteration
+ if comm.StartCmd.Command != expectedCommand {
+ t.Fatalf("Expect command to be: %s, got %s", expectedCommand, comm.StartCmd.Command)
+ }
+ // Set this back!
+ waitForCommunicator = waitForCommunicatorOld
+ waitForRestart = waitForRestartOld
+}
+
+func TestProvisionerProvision_RestartCommandFail(t *testing.T) {
+ config := testConfig()
+ ui := testUi()
+ p := new(Provisioner)
+ comm := new(packersdk.MockCommunicator)
+ comm.StartStderr = "WinRM terminated"
+ comm.StartExitStatus = 1
+
+ p.Prepare(config)
+ err := p.Provision(context.Background(), ui, comm, make(map[string]interface{}))
+ if err == nil {
+ t.Fatal("should have error")
+ }
+}
+func TestProvisionerProvision_WaitForRestartFail(t *testing.T) {
+ config := testConfig()
+
+ // Defaults provided by Packer
+ ui := testUi()
+ p := new(Provisioner)
+
+ // Defaults provided by Packer
+ comm := new(packersdk.MockCommunicator)
+ p.Prepare(config)
+ waitForCommunicatorOld := waitForCommunicator
+ waitForCommunicator = func(context.Context, *Provisioner) error {
+ return fmt.Errorf("Machine did not restart properly")
+ }
+ err := p.Provision(context.Background(), ui, comm, make(map[string]interface{}))
+ if err == nil {
+ t.Fatal("should have error")
+ }
+
+ // Set this back!
+ waitForCommunicator = waitForCommunicatorOld
+}
+
+func TestProvision_waitForRestartTimeout(t *testing.T) {
+ retryableSleep = 10 * time.Millisecond
+ config := testConfig()
+ config["restart_timeout"] = "1ms"
+ ui := testUi()
+ p := new(Provisioner)
+ comm := new(packersdk.MockCommunicator)
+ var err error
+
+ p.Prepare(config)
+ waitForCommunicatorOld := waitForCommunicator
+ waitDone := make(chan bool)
+ waitContinue := make(chan bool)
+
+ // Block until cancel comes through
+ waitForCommunicator = func(context.Context, *Provisioner) error {
+ for {
+ select {
+ case <-waitDone:
+ waitContinue <- true
+ }
+ }
+ }
+
+ go func() {
+ err = p.Provision(context.Background(), ui, comm, make(map[string]interface{}))
+ waitDone <- true
+ }()
+ <-waitContinue
+
+ if err == nil {
+ t.Fatal("should not have error")
+ }
+
+ // Set this back!
+ waitForCommunicator = waitForCommunicatorOld
+
+}
+
+func TestProvision_waitForCommunicator(t *testing.T) {
+ config := testConfig()
+
+ // Defaults provided by Packer
+ ui := testUi()
+ p := new(Provisioner)
+
+ // Defaults provided by Packer
+ comm := new(packersdk.MockCommunicator)
+ p.comm = comm
+ p.ui = ui
+ comm.StartStderr = "WinRM terminated"
+ comm.StartStdout = "WIN-V4CEJ7MC5SN restarted."
+ comm.StartExitStatus = 1
+ p.Prepare(config)
+ err := waitForCommunicator(context.Background(), p)
+
+ if err != nil {
+ t.Fatalf("should not have error, got: %s", err.Error())
+ }
+
+ expectedCommand := DefaultRestartCheckCommand
+
+ // Should run the command without alteration
+ if comm.StartCmd.Command != expectedCommand {
+ t.Fatalf("Expect command to be: %s, got %s", expectedCommand, comm.StartCmd.Command)
+ }
+}
+
+func TestProvision_waitForCommunicatorWithCancel(t *testing.T) {
+ config := testConfig()
+
+ // Defaults provided by Packer
+ ui := testUi()
+ p := new(Provisioner)
+
+ // Defaults provided by Packer
+ comm := new(packersdk.MockCommunicator)
+ p.comm = comm
+ p.ui = ui
+ retryableSleep = 5 * time.Second
+ p.cancel = make(chan struct{})
+ var err error
+
+ ctx, cancel := context.WithCancel(context.Background())
+
+ comm.StartStderr = "WinRM terminated"
+ comm.StartExitStatus = 1 // Always fail
+ p.Prepare(config)
+
+ // Run 2 goroutines;
+ // 1st to call waitForCommunicator (that will always fail)
+ // 2nd to cancel the operation
+ waitStart := make(chan bool)
+ waitDone := make(chan bool)
+ go func() {
+ waitStart <- true
+ err = waitForCommunicator(ctx, p)
+ waitDone <- true
+ }()
+
+ go func() {
+ time.Sleep(10 * time.Millisecond)
+ <-waitStart
+ cancel()
+ }()
+ <-waitDone
+
+ // Expect a Cancel error
+ if err == nil {
+ t.Fatalf("Should have err")
+ }
+}
+
+func TestProvision_Cancel(t *testing.T) {
+ config := testConfig()
+
+ // Defaults provided by Packer
+ ui := testUi()
+ p := new(Provisioner)
+
+ comm := new(packersdk.MockCommunicator)
+ p.Prepare(config)
+ done := make(chan error)
+
+ topCtx, cancelTopCtx := context.WithCancel(context.Background())
+
+ // Block until cancel comes through
+ waitForCommunicator = func(ctx context.Context, p *Provisioner) error {
+ cancelTopCtx()
+ <-ctx.Done()
+ return ctx.Err()
+ }
+
+ // Create two go routines to provision and cancel in parallel
+ // Provision will block until cancel happens
+ go func() {
+ done <- p.Provision(topCtx, ui, comm, make(map[string]interface{}))
+ }()
+
+ // Expect interrupt error
+ if err := <-done; err == nil {
+ t.Fatal("should have error")
+ }
+}
diff --git a/v1.9.4/provisioner/windows-restart/version/version.go b/v1.9.4/provisioner/windows-restart/version/version.go
new file mode 100644
index 0000000..5376f9e
--- /dev/null
+++ b/v1.9.4/provisioner/windows-restart/version/version.go
@@ -0,0 +1,16 @@
+// Copyright (c) HashiCorp, Inc.
+// SPDX-License-Identifier: MPL-2.0
+
+package version
+
+import (
+ "github.com/hashicorp/packer-plugin-sdk/version"
+ packerVersion "github.com/hashicorp/packer/version"
+)
+
+var WindowsRestartPluginVersion *version.PluginVersion
+
+func init() {
+ WindowsRestartPluginVersion = version.InitializePluginVersion(
+ packerVersion.Version, packerVersion.VersionPrerelease)
+}
diff --git a/v1.9.4/provisioner/windows-shell/provisioner.go b/v1.9.4/provisioner/windows-shell/provisioner.go
new file mode 100644
index 0000000..c6f22a3
--- /dev/null
+++ b/v1.9.4/provisioner/windows-shell/provisioner.go
@@ -0,0 +1,280 @@
+// Copyright (c) HashiCorp, Inc.
+// SPDX-License-Identifier: MPL-2.0
+
+//go:generate packer-sdc mapstructure-to-hcl2 -type Config
+
+// This package implements a provisioner for Packer that executes
+// shell scripts within the remote machine.
+package shell
+
+import (
+ "bufio"
+ "context"
+ "errors"
+ "fmt"
+ "log"
+ "os"
+ "sort"
+ "strings"
+ "time"
+
+ "github.com/hashicorp/hcl/v2/hcldec"
+ "github.com/hashicorp/packer-plugin-sdk/multistep/commonsteps"
+ packersdk "github.com/hashicorp/packer-plugin-sdk/packer"
+ "github.com/hashicorp/packer-plugin-sdk/retry"
+ "github.com/hashicorp/packer-plugin-sdk/shell"
+ "github.com/hashicorp/packer-plugin-sdk/template/config"
+ "github.com/hashicorp/packer-plugin-sdk/template/interpolate"
+ "github.com/hashicorp/packer-plugin-sdk/tmp"
+)
+
+// FIXME query remote host or use %SYSTEMROOT%, %TEMP% and more creative filename
+const DefaultRemotePath = "c:/Windows/Temp/script.bat"
+
+type Config struct {
+ shell.Provisioner `mapstructure:",squash"`
+
+ shell.ProvisionerRemoteSpecific `mapstructure:",squash"`
+
+ // The timeout for retrying to start the process. Until this timeout
+ // is reached, if the provisioner can't start a process, it retries.
+ // This can be set high to allow for reboots.
+ StartRetryTimeout time.Duration `mapstructure:"start_retry_timeout"`
+
+ ctx interpolate.Context
+}
+
+type Provisioner struct {
+ config Config
+ generatedData map[string]interface{}
+}
+
+type ExecuteCommandTemplate struct {
+ Vars string
+ Path string
+}
+
+func (p *Provisioner) ConfigSpec() hcldec.ObjectSpec { return p.config.FlatMapstructure().HCL2Spec() }
+
+func (p *Provisioner) Prepare(raws ...interface{}) error {
+ err := config.Decode(&p.config, &config.DecodeOpts{
+ PluginType: "windows-shell",
+ Interpolate: true,
+ InterpolateContext: &p.config.ctx,
+ InterpolateFilter: &interpolate.RenderFilter{
+ Exclude: []string{
+ "execute_command",
+ },
+ },
+ }, raws...)
+ if err != nil {
+ return err
+ }
+
+ if p.config.EnvVarFormat == "" {
+ p.config.EnvVarFormat = `set "%s=%s" && `
+ }
+
+ if p.config.ExecuteCommand == "" {
+ p.config.ExecuteCommand = `{{.Vars}}"{{.Path}}"`
+ }
+
+ if p.config.Inline != nil && len(p.config.Inline) == 0 {
+ p.config.Inline = nil
+ }
+
+ if p.config.StartRetryTimeout == 0 {
+ p.config.StartRetryTimeout = 5 * time.Minute
+ }
+
+ if p.config.RemotePath == "" {
+ p.config.RemotePath = DefaultRemotePath
+ }
+
+ if p.config.Scripts == nil {
+ p.config.Scripts = make([]string, 0)
+ }
+
+ if p.config.Vars == nil {
+ p.config.Vars = make([]string, 0)
+ }
+
+ var errs error
+ if p.config.Script != "" && len(p.config.Scripts) > 0 {
+ errs = packersdk.MultiErrorAppend(errs,
+ errors.New("Only one of script or scripts can be specified."))
+ }
+
+ if p.config.Script != "" {
+ p.config.Scripts = []string{p.config.Script}
+ }
+
+ if len(p.config.Scripts) == 0 && p.config.Inline == nil {
+ errs = packersdk.MultiErrorAppend(errs,
+ errors.New("Either a script file or inline script must be specified."))
+ } else if len(p.config.Scripts) > 0 && p.config.Inline != nil {
+ errs = packersdk.MultiErrorAppend(errs,
+ errors.New("Only a script file or an inline script can be specified, not both."))
+ }
+
+ for _, path := range p.config.Scripts {
+ if _, err := os.Stat(path); err != nil {
+ errs = packersdk.MultiErrorAppend(errs,
+ fmt.Errorf("Bad script '%s': %s", path, err))
+ }
+ }
+
+ // Do a check for bad environment variables, such as '=foo', 'foobar'
+ for _, kv := range p.config.Vars {
+ vs := strings.SplitN(kv, "=", 2)
+ if len(vs) != 2 || vs[0] == "" {
+ errs = packersdk.MultiErrorAppend(errs,
+ fmt.Errorf("Environment variable not in format 'key=value': %s", kv))
+ }
+ }
+
+ return errs
+}
+
+// This function takes the inline scripts, concatenates them
+// into a temporary file and returns a string containing the location
+// of said file.
+func extractScript(p *Provisioner) (string, error) {
+ temp, err := tmp.File("windows-shell-provisioner")
+ if err != nil {
+ log.Printf("Unable to create temporary file for inline scripts: %s", err)
+ return "", err
+ }
+ writer := bufio.NewWriter(temp)
+ for _, command := range p.config.Inline {
+ log.Printf("Found command: %s", command)
+ if _, err := writer.WriteString(command + "\n"); err != nil {
+ return "", fmt.Errorf("Error preparing shell script: %s", err)
+ }
+ }
+
+ if err := writer.Flush(); err != nil {
+ return "", fmt.Errorf("Error preparing shell script: %s", err)
+ }
+
+ temp.Close()
+
+ return temp.Name(), nil
+}
+
+func (p *Provisioner) Provision(ctx context.Context, ui packersdk.Ui, comm packersdk.Communicator, generatedData map[string]interface{}) error {
+ ui.Say("Provisioning with windows-shell...")
+ scripts := make([]string, len(p.config.Scripts))
+ copy(scripts, p.config.Scripts)
+ p.generatedData = generatedData
+
+ if p.config.Inline != nil {
+ temp, err := extractScript(p)
+ if err != nil {
+ ui.Error(fmt.Sprintf("Unable to extract inline scripts into a file: %s", err))
+ }
+ scripts = append(scripts, temp)
+ // Remove temp script containing the inline commands when done
+ defer os.Remove(temp)
+ }
+
+ for _, path := range scripts {
+ ui.Say(fmt.Sprintf("Provisioning with shell script: %s", path))
+
+ log.Printf("Opening %s for reading", path)
+ f, err := os.Open(path)
+ if err != nil {
+ return fmt.Errorf("Error opening shell script: %s", err)
+ }
+ defer f.Close()
+
+ // Create environment variables to set before executing the command
+ flattenedVars := p.createFlattenedEnvVars()
+
+ // Compile the command
+ p.config.ctx.Data = &ExecuteCommandTemplate{
+ Vars: flattenedVars,
+ Path: p.config.RemotePath,
+ }
+ command, err := interpolate.Render(p.config.ExecuteCommand, &p.config.ctx)
+ if err != nil {
+ return fmt.Errorf("Error processing command: %s", err)
+ }
+
+ // Upload the file and run the command. Do this in the context of
+ // a single retryable function so that we don't end up with
+ // the case that the upload succeeded, a restart is initiated,
+ // and then the command is executed but the file doesn't exist
+ // any longer.
+ var cmd *packersdk.RemoteCmd
+ err = retry.Config{StartTimeout: p.config.StartRetryTimeout}.Run(ctx, func(ctx context.Context) error {
+ if _, err := f.Seek(0, 0); err != nil {
+ return err
+ }
+
+ if err := comm.Upload(p.config.RemotePath, f, nil); err != nil {
+ return fmt.Errorf("Error uploading script: %s", err)
+ }
+
+ cmd = &packersdk.RemoteCmd{Command: command}
+ return cmd.RunWithUi(ctx, comm, ui)
+ })
+ if err != nil {
+ return err
+ }
+
+ // Close the original file since we copied it
+ f.Close()
+
+ if err := p.config.ValidExitCode(cmd.ExitStatus()); err != nil {
+ return err
+ }
+ }
+
+ return nil
+}
+
+func (p *Provisioner) createFlattenedEnvVars() (flattened string) {
+ flattened = ""
+ envVars := make(map[string]string)
+
+ // Always available Packer provided env vars
+ envVars["PACKER_BUILD_NAME"] = p.config.PackerBuildName
+ envVars["PACKER_BUILDER_TYPE"] = p.config.PackerBuilderType
+
+ // expose ip address variables
+ httpAddr := p.generatedData["PackerHTTPAddr"]
+ if httpAddr != nil && httpAddr != commonsteps.HttpAddrNotImplemented {
+ envVars["PACKER_HTTP_ADDR"] = httpAddr.(string)
+ }
+ httpIP := p.generatedData["PackerHTTPIP"]
+ if httpIP != nil && httpIP != commonsteps.HttpIPNotImplemented {
+ envVars["PACKER_HTTP_IP"] = httpIP.(string)
+ }
+ httpPort := p.generatedData["PackerHTTPPort"]
+ if httpPort != nil && httpPort != commonsteps.HttpPortNotImplemented {
+ envVars["PACKER_HTTP_PORT"] = httpPort.(string)
+ }
+
+ // Split vars into key/value components
+ for _, envVar := range p.config.Vars {
+ keyValue := strings.SplitN(envVar, "=", 2)
+ envVars[keyValue[0]] = keyValue[1]
+ }
+
+ for k, v := range p.config.Env {
+ envVars[k] = v
+ }
+
+ // Create a list of env var keys in sorted order
+ var keys []string
+ for k := range envVars {
+ keys = append(keys, k)
+ }
+ sort.Strings(keys)
+ // Re-assemble vars using OS specific format pattern and flatten
+ for _, key := range keys {
+ flattened += fmt.Sprintf(p.config.EnvVarFormat, key, envVars[key])
+ }
+ return
+}
diff --git a/v1.9.4/provisioner/windows-shell/provisioner.hcl2spec.go b/v1.9.4/provisioner/windows-shell/provisioner.hcl2spec.go
new file mode 100644
index 0000000..34e7e19
--- /dev/null
+++ b/v1.9.4/provisioner/windows-shell/provisioner.hcl2spec.go
@@ -0,0 +1,67 @@
+// Code generated by "packer-sdc mapstructure-to-hcl2"; DO NOT EDIT.
+
+package shell
+
+import (
+ "github.com/hashicorp/hcl/v2/hcldec"
+ "github.com/zclconf/go-cty/cty"
+)
+
+// FlatConfig is an auto-generated flat version of Config.
+// Where the contents of a field with a `mapstructure:,squash` tag are bubbled up.
+type FlatConfig struct {
+ PackerBuildName *string `mapstructure:"packer_build_name" cty:"packer_build_name" 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"`
+ Inline []string `cty:"inline" hcl:"inline"`
+ Script *string `cty:"script" hcl:"script"`
+ Scripts []string `cty:"scripts" hcl:"scripts"`
+ ValidExitCodes []int `mapstructure:"valid_exit_codes" cty:"valid_exit_codes" hcl:"valid_exit_codes"`
+ Vars []string `mapstructure:"environment_vars" cty:"environment_vars" hcl:"environment_vars"`
+ Env map[string]string `mapstructure:"env" cty:"env" hcl:"env"`
+ EnvVarFormat *string `mapstructure:"env_var_format" cty:"env_var_format" hcl:"env_var_format"`
+ Binary *bool `cty:"binary" hcl:"binary"`
+ RemotePath *string `mapstructure:"remote_path" cty:"remote_path" hcl:"remote_path"`
+ ExecuteCommand *string `mapstructure:"execute_command" cty:"execute_command" hcl:"execute_command"`
+ StartRetryTimeout *string `mapstructure:"start_retry_timeout" cty:"start_retry_timeout" hcl:"start_retry_timeout"`
+}
+
+// FlatMapstructure returns a new FlatConfig.
+// FlatConfig is an auto-generated flat version of Config.
+// Where the contents a fields with a `mapstructure:,squash` tag are bubbled up.
+func (*Config) FlatMapstructure() interface{ HCL2Spec() map[string]hcldec.Spec } {
+ return new(FlatConfig)
+}
+
+// HCL2Spec returns the hcl spec of a Config.
+// This spec is used by HCL to read the fields of Config.
+// The decoded values from this spec will then be applied to a FlatConfig.
+func (*FlatConfig) HCL2Spec() map[string]hcldec.Spec {
+ s := map[string]hcldec.Spec{
+ "packer_build_name": &hcldec.AttrSpec{Name: "packer_build_name", Type: cty.String, Required: false},
+ "packer_builder_type": &hcldec.AttrSpec{Name: "packer_builder_type", Type: cty.String, Required: false},
+ "packer_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_sensitive_variables": &hcldec.AttrSpec{Name: "packer_sensitive_variables", Type: cty.List(cty.String), Required: false},
+ "inline": &hcldec.AttrSpec{Name: "inline", Type: cty.List(cty.String), Required: false},
+ "script": &hcldec.AttrSpec{Name: "script", Type: cty.String, Required: false},
+ "scripts": &hcldec.AttrSpec{Name: "scripts", Type: cty.List(cty.String), Required: false},
+ "valid_exit_codes": &hcldec.AttrSpec{Name: "valid_exit_codes", Type: cty.List(cty.Number), Required: false},
+ "environment_vars": &hcldec.AttrSpec{Name: "environment_vars", Type: cty.List(cty.String), Required: false},
+ "env": &hcldec.AttrSpec{Name: "env", Type: cty.Map(cty.String), Required: false},
+ "env_var_format": &hcldec.AttrSpec{Name: "env_var_format", Type: cty.String, Required: false},
+ "binary": &hcldec.AttrSpec{Name: "binary", Type: cty.Bool, Required: false},
+ "remote_path": &hcldec.AttrSpec{Name: "remote_path", Type: cty.String, Required: false},
+ "execute_command": &hcldec.AttrSpec{Name: "execute_command", Type: cty.String, Required: false},
+ "start_retry_timeout": &hcldec.AttrSpec{Name: "start_retry_timeout", Type: cty.String, Required: false},
+ }
+ return s
+}
diff --git a/v1.9.4/provisioner/windows-shell/provisioner_test.go b/v1.9.4/provisioner/windows-shell/provisioner_test.go
new file mode 100644
index 0000000..e01af9e
--- /dev/null
+++ b/v1.9.4/provisioner/windows-shell/provisioner_test.go
@@ -0,0 +1,460 @@
+// Copyright (c) HashiCorp, Inc.
+// SPDX-License-Identifier: MPL-2.0
+
+package shell
+
+import (
+ "bytes"
+ "context"
+ "io/ioutil"
+ "log"
+ "os"
+ "strings"
+ "testing"
+
+ "github.com/hashicorp/packer-plugin-sdk/multistep/commonsteps"
+ packersdk "github.com/hashicorp/packer-plugin-sdk/packer"
+)
+
+func testConfig() map[string]interface{} {
+ return map[string]interface{}{
+ "inline": []interface{}{"foo", "bar"},
+ }
+}
+
+func TestProvisionerPrepare_extractScript(t *testing.T) {
+ config := testConfig()
+ p := new(Provisioner)
+ _ = p.Prepare(config)
+ file, err := extractScript(p)
+ defer os.Remove(file)
+ if err != nil {
+ t.Fatalf("Should not be error: %s", err)
+ }
+ log.Printf("File: %s", file)
+ if strings.Index(file, os.TempDir()) != 0 {
+ t.Fatalf("Temp file should reside in %s. File location: %s", os.TempDir(), file)
+ }
+
+ // File contents should contain 2 lines concatenated by newlines: foo\nbar
+ readFile, err := ioutil.ReadFile(file)
+ if err != nil {
+ t.Fatalf("Should not be error: %s", err)
+ }
+ expectedContents := "foo\nbar\n"
+ s := string(readFile[:])
+ if s != expectedContents {
+ t.Fatalf("Expected generated inlineScript to equal '%s', got '%s'", expectedContents, s)
+ }
+}
+
+func TestProvisioner_Impl(t *testing.T) {
+ var raw interface{}
+ raw = &Provisioner{}
+ if _, ok := raw.(packersdk.Provisioner); !ok {
+ t.Fatalf("must be a Provisioner")
+ }
+}
+
+func TestProvisionerPrepare_Defaults(t *testing.T) {
+ var p Provisioner
+ config := testConfig()
+
+ err := p.Prepare(config)
+ if err != nil {
+ t.Fatalf("err: %s", err)
+ }
+
+ if p.config.RemotePath != DefaultRemotePath {
+ t.Errorf("unexpected remote path: %s", p.config.RemotePath)
+ }
+
+ if p.config.ExecuteCommand != "{{.Vars}}\"{{.Path}}\"" {
+ t.Fatalf("Default command should be powershell {{.Vars}}\"{{.Path}}\", but got %s", p.config.ExecuteCommand)
+ }
+}
+
+func TestProvisionerPrepare_Config(t *testing.T) {
+
+}
+
+func TestProvisionerPrepare_InvalidKey(t *testing.T) {
+ var p Provisioner
+ config := testConfig()
+
+ // Add a random key
+ config["i_should_not_be_valid"] = true
+ err := p.Prepare(config)
+ if err == nil {
+ t.Fatal("should have error")
+ }
+}
+
+func TestProvisionerPrepare_Script(t *testing.T) {
+ config := testConfig()
+ delete(config, "inline")
+
+ config["script"] = "/this/should/not/exist"
+ p := new(Provisioner)
+ err := p.Prepare(config)
+ if err == nil {
+ t.Fatal("should have error")
+ }
+
+ // Test with a good one
+ tf, err := ioutil.TempFile("", "packer")
+ if err != nil {
+ t.Fatalf("error tempfile: %s", err)
+ }
+ defer os.Remove(tf.Name())
+ defer tf.Close()
+
+ config["script"] = tf.Name()
+ p = new(Provisioner)
+ err = p.Prepare(config)
+ if err != nil {
+ t.Fatalf("should not have error: %s", err)
+ }
+}
+
+func TestProvisionerPrepare_ScriptAndInline(t *testing.T) {
+ var p Provisioner
+ config := testConfig()
+
+ delete(config, "inline")
+ delete(config, "script")
+ err := p.Prepare(config)
+ if err == nil {
+ t.Fatal("should have error")
+ }
+
+ // Test with both
+ tf, err := ioutil.TempFile("", "packer")
+ if err != nil {
+ t.Fatalf("error tempfile: %s", err)
+ }
+ defer os.Remove(tf.Name())
+ defer tf.Close()
+
+ config["inline"] = []interface{}{"foo"}
+ config["script"] = tf.Name()
+ err = p.Prepare(config)
+ if err == nil {
+ t.Fatal("should have error")
+ }
+}
+
+func TestProvisionerPrepare_ScriptAndScripts(t *testing.T) {
+ var p Provisioner
+ config := testConfig()
+
+ // Test with both
+ tf, err := ioutil.TempFile("", "packer")
+ if err != nil {
+ t.Fatalf("error tempfile: %s", err)
+ }
+ defer os.Remove(tf.Name())
+ defer tf.Close()
+
+ config["inline"] = []interface{}{"foo"}
+ config["scripts"] = []string{tf.Name()}
+ err = p.Prepare(config)
+ if err == nil {
+ t.Fatal("should have error")
+ }
+}
+
+func TestProvisionerPrepare_Scripts(t *testing.T) {
+ config := testConfig()
+ delete(config, "inline")
+
+ config["scripts"] = []string{}
+ p := new(Provisioner)
+ err := p.Prepare(config)
+ if err == nil {
+ t.Fatal("should have error")
+ }
+
+ // Test with a good one
+ tf, err := ioutil.TempFile("", "packer")
+ if err != nil {
+ t.Fatalf("error tempfile: %s", err)
+ }
+ defer os.Remove(tf.Name())
+ defer tf.Close()
+
+ config["scripts"] = []string{tf.Name()}
+ p = new(Provisioner)
+ err = p.Prepare(config)
+ if err != nil {
+ t.Fatalf("should not have error: %s", err)
+ }
+}
+
+func TestProvisionerPrepare_EnvironmentVars(t *testing.T) {
+ config := testConfig()
+
+ // Test with a bad case
+ config["environment_vars"] = []string{"badvar", "good=var"}
+ p := new(Provisioner)
+ err := p.Prepare(config)
+ if err == nil {
+ t.Fatal("should have error")
+ }
+
+ // Test with a trickier case
+ config["environment_vars"] = []string{"=bad"}
+ p = new(Provisioner)
+ err = p.Prepare(config)
+ if err == nil {
+ t.Fatal("should have error")
+ }
+
+ // Test with a good case
+ // Note: baz= is a real env variable, just empty
+ config["environment_vars"] = []string{"FOO=bar", "baz="}
+ p = new(Provisioner)
+ err = p.Prepare(config)
+ if err != nil {
+ t.Fatalf("should not have error: %s", err)
+ }
+
+ // Test when the env variable value contains an equals sign
+ config["environment_vars"] = []string{"good=withequals=true"}
+ p = new(Provisioner)
+ err = p.Prepare(config)
+ if err != nil {
+ t.Fatalf("should not have error: %s", err)
+ }
+
+ // Test when the env variable value starts with an equals sign
+ config["environment_vars"] = []string{"good==true"}
+ p = new(Provisioner)
+ err = p.Prepare(config)
+ if err != nil {
+ t.Fatalf("should not have error: %s", err)
+ }
+}
+
+func TestProvisionerQuote_EnvironmentVars(t *testing.T) {
+ config := testConfig()
+
+ config["environment_vars"] = []string{
+ "keyone=valueone",
+ "keytwo=value\ntwo",
+ "keythree='valuethree'",
+ "keyfour='value\nfour'",
+ "keyfive='value=five'",
+ "keysix='=six'",
+ }
+
+ expected := []string{
+ "keyone=valueone",
+ "keytwo=value\ntwo",
+ "keythree='valuethree'",
+ "keyfour='value\nfour'",
+ "keyfive='value=five'",
+ "keysix='=six'",
+ }
+
+ p := new(Provisioner)
+ p.Prepare(config)
+
+ for i, expectedValue := range expected {
+ if p.config.Vars[i] != expectedValue {
+ t.Fatalf("%s should be equal to %s", p.config.Vars[i], expectedValue)
+ }
+ }
+
+}
+
+func testUi() *packersdk.BasicUi {
+ return &packersdk.BasicUi{
+ Reader: new(bytes.Buffer),
+ Writer: new(bytes.Buffer),
+ ErrorWriter: new(bytes.Buffer),
+ }
+}
+
+func TestProvisionerProvision_Inline(t *testing.T) {
+ config := testConfig()
+ delete(config, "inline")
+
+ // Defaults provided by Packer
+ config["remote_path"] = "c:/Windows/Temp/inlineScript.bat"
+ config["inline"] = []string{"whoami"}
+ ui := testUi()
+ p := new(Provisioner)
+
+ // Defaults provided by Packer
+ p.config.PackerBuildName = "vmware"
+ p.config.PackerBuilderType = "iso"
+ comm := new(packersdk.MockCommunicator)
+ p.Prepare(config)
+
+ err := p.Provision(context.Background(), ui, comm, generatedData())
+ if err != nil {
+ t.Fatal("should not have error")
+ }
+
+ expectedCommand := `set "PACKER_BUILDER_TYPE=iso" && set "PACKER_BUILD_NAME=vmware" && "c:/Windows/Temp/inlineScript.bat"`
+
+ // Should run the command without alteration
+ if comm.StartCmd.Command != expectedCommand {
+ t.Fatalf("Expect command to be: %s, got %s", expectedCommand, comm.StartCmd.Command)
+ }
+
+ envVars := make([]string, 2)
+ envVars[0] = "FOO=BAR"
+ envVars[1] = "BAR=BAZ"
+ config["environment_vars"] = envVars
+ config["remote_path"] = "c:/Windows/Temp/inlineScript.bat"
+
+ p.Prepare(config)
+ err = p.Provision(context.Background(), ui, comm, generatedData())
+ if err != nil {
+ t.Fatal("should not have error")
+ }
+
+ expectedCommand = `set "BAR=BAZ" && set "FOO=BAR" && set "PACKER_BUILDER_TYPE=iso" && set "PACKER_BUILD_NAME=vmware" && "c:/Windows/Temp/inlineScript.bat"`
+
+ // Should run the command without alteration
+ if comm.StartCmd.Command != expectedCommand {
+ t.Fatalf("Expect command to be: %s, got: %s", expectedCommand, comm.StartCmd.Command)
+ }
+}
+
+func TestProvisionerProvision_Scripts(t *testing.T) {
+ tf, err := ioutil.TempFile("", "packer")
+ if err != nil {
+ t.Fatalf("error tempfile: %s", err)
+ }
+ defer os.Remove(tf.Name())
+ defer tf.Close()
+
+ config := testConfig()
+ delete(config, "inline")
+ config["scripts"] = []string{tf.Name()}
+ config["packer_build_name"] = "foobuild"
+ config["packer_builder_type"] = "footype"
+ ui := testUi()
+
+ p := new(Provisioner)
+ comm := new(packersdk.MockCommunicator)
+ p.Prepare(config)
+ err = p.Provision(context.Background(), ui, comm, generatedData())
+ if err != nil {
+ t.Fatal("should not have error")
+ }
+
+ //powershell -Command "$env:PACKER_BUILDER_TYPE=''"; powershell -Command "$env:PACKER_BUILD_NAME='foobuild'"; powershell -Command c:/Windows/Temp/script.ps1
+ expectedCommand := `set "PACKER_BUILDER_TYPE=footype" && set "PACKER_BUILD_NAME=foobuild" && "c:/Windows/Temp/script.bat"`
+
+ // Should run the command without alteration
+ if comm.StartCmd.Command != expectedCommand {
+ t.Fatalf("Expect command to be %s NOT %s", expectedCommand, comm.StartCmd.Command)
+ }
+}
+
+func TestProvisionerProvision_ScriptsWithEnvVars(t *testing.T) {
+ tf, err := ioutil.TempFile("", "packer")
+ if err != nil {
+ t.Fatalf("error tempfile: %s", err)
+ }
+ defer os.Remove(tf.Name())
+ defer tf.Close()
+
+ config := testConfig()
+ ui := testUi()
+ delete(config, "inline")
+
+ config["scripts"] = []string{tf.Name()}
+ config["packer_build_name"] = "foobuild"
+ config["packer_builder_type"] = "footype"
+
+ // Env vars - currently should not effect them
+ envVars := make([]string, 2)
+ envVars[0] = "FOO=BAR"
+ envVars[1] = "BAR=BAZ"
+ config["environment_vars"] = envVars
+
+ p := new(Provisioner)
+ comm := new(packersdk.MockCommunicator)
+ p.Prepare(config)
+ err = p.Provision(context.Background(), ui, comm, generatedData())
+ if err != nil {
+ t.Fatal("should not have error")
+ }
+
+ expectedCommand := `set "BAR=BAZ" && set "FOO=BAR" && set "PACKER_BUILDER_TYPE=footype" && set "PACKER_BUILD_NAME=foobuild" && "c:/Windows/Temp/script.bat"`
+
+ // Should run the command without alteration
+ if comm.StartCmd.Command != expectedCommand {
+ t.Fatalf("Expect command to be %s NOT %s", expectedCommand, comm.StartCmd.Command)
+ }
+}
+
+func TestProvisioner_createFlattenedEnvVars_windows(t *testing.T) {
+ var flattenedEnvVars string
+ config := testConfig()
+
+ userEnvVarTests := [][]string{
+ {}, // No user env var
+ {"FOO=bar"}, // Single user env var
+ {"FOO=bar", "BAZ=qux"}, // Multiple user env vars
+ {"FOO=bar=baz"}, // User env var with value containing equals
+ {"FOO==bar"}, // User env var with value starting with equals
+ }
+ userEnvVarmapTests := []map[string]string{
+ {},
+ {
+ "BAR": "foo",
+ },
+ {
+ "BAR": "foo",
+ "YAR": "yaa",
+ },
+ {
+ "BAR": "foo=yar",
+ },
+ {
+ "BAR": "=foo",
+ },
+ }
+ expected := []string{
+ `set "PACKER_BUILDER_TYPE=iso" && set "PACKER_BUILD_NAME=vmware" && `,
+ `set "BAR=foo" && set "FOO=bar" && set "PACKER_BUILDER_TYPE=iso" && set "PACKER_BUILD_NAME=vmware" && `,
+ `set "BAR=foo" && set "BAZ=qux" && set "FOO=bar" && set "PACKER_BUILDER_TYPE=iso" && set "PACKER_BUILD_NAME=vmware" && set "YAR=yaa" && `,
+ `set "BAR=foo=yar" && set "FOO=bar=baz" && set "PACKER_BUILDER_TYPE=iso" && set "PACKER_BUILD_NAME=vmware" && `,
+ `set "BAR==foo" && set "FOO==bar" && set "PACKER_BUILDER_TYPE=iso" && set "PACKER_BUILD_NAME=vmware" && `,
+ }
+
+ p := new(Provisioner)
+ p.generatedData = generatedData()
+ p.Prepare(config)
+
+ // Defaults provided by Packer
+ p.config.PackerBuildName = "vmware"
+ p.config.PackerBuilderType = "iso"
+
+ for i, expectedValue := range expected {
+ p.config.Vars = userEnvVarTests[i]
+ p.config.Env = userEnvVarmapTests[i]
+ flattenedEnvVars = p.createFlattenedEnvVars()
+ if flattenedEnvVars != expectedValue {
+ t.Fatalf("expected flattened env vars to be: %s, got %s.", expectedValue, flattenedEnvVars)
+ }
+ }
+}
+
+func TestCancel(t *testing.T) {
+ // Don't actually call Cancel() as it performs an os.Exit(0)
+ // which kills the 'go test' tool
+}
+func generatedData() map[string]interface{} {
+ return map[string]interface{}{
+ "PackerHTTPAddr": commonsteps.HttpAddrNotImplemented,
+ "PackerHTTPIP": commonsteps.HttpIPNotImplemented,
+ "PackerHTTPPort": commonsteps.HttpPortNotImplemented,
+ }
+}
diff --git a/v1.9.4/provisioner/windows-shell/version/version.go b/v1.9.4/provisioner/windows-shell/version/version.go
new file mode 100644
index 0000000..18ad34f
--- /dev/null
+++ b/v1.9.4/provisioner/windows-shell/version/version.go
@@ -0,0 +1,16 @@
+// Copyright (c) HashiCorp, Inc.
+// SPDX-License-Identifier: MPL-2.0
+
+package version
+
+import (
+ "github.com/hashicorp/packer-plugin-sdk/version"
+ packerVersion "github.com/hashicorp/packer/version"
+)
+
+var WindowsShellPluginVersion *version.PluginVersion
+
+func init() {
+ WindowsShellPluginVersion = version.InitializePluginVersion(
+ packerVersion.Version, packerVersion.VersionPrerelease)
+}
diff --git a/v1.9.4/scripts/build.ps1 b/v1.9.4/scripts/build.ps1
new file mode 100644
index 0000000..4f1abd3
--- /dev/null
+++ b/v1.9.4/scripts/build.ps1
@@ -0,0 +1,106 @@
+# Copyright (c) HashiCorp, Inc.
+# SPDX-License-Identifier: MPL-2.0
+
+<#
+ .Synopsis
+ Build script for Packer.
+
+ .Description
+ Build script for Packer for all supported platforms and architectures.
+ By default the following OSs and architectures are targeted.
+
+ OS:
+ * linux
+ * darwin
+ * windows
+ * freebsd
+ * openbsd
+
+ Architecture:
+ * 386
+ * amd64
+ * arm
+
+ If the environment variable PACKER_DEV is defined, then the OS and
+ architecture of the go binary in the path is used.
+
+ The built binary is stamped with the current version number of Packer,
+ the latest git commit, and +CHANGES if there are any outstanding
+ changes in the current repository, e.g.
+
+ Packer v0.10.1.dev (3c736322ba3a5fcb3a4e92394011a2e56f396da6+CHANGES)
+
+ The build artifacts for the current OS and architecture are copied to
+ bin and $GOPATH\bin.
+
+ .Example
+ .\scripts\build.ps1
+#>
+
+# This script builds the application from source for multiple platforms.
+
+# Get the parent directory of where this script is.
+$DIR = [System.IO.Path]::GetDirectoryName($PSScriptRoot)
+
+# Change into that directory
+Push-Location $DIR | Out-Null
+
+# Get the git commit
+$GIT_COMMIT = $(git.exe rev-parse HEAD)
+git.exe status --porcelain | Out-Null
+if ($LastExitCode -eq 0) {
+ $GIT_DIRTY = "+CHANGES"
+}
+
+# If its dev mode, only build for ourself
+if (Test-Path env:PACKER_DEV) {
+ $XC_OS=$(go.exe env GOOS)
+ $XC_ARCH=$(go.exe env GOARCH)
+} else {
+ if (Test-Path env:XC_ARCH) {
+ $XC_ARCH = $(Get-Content env:XC_ARCH)
+ } else {
+ $XC_ARCH="386 amd64 arm arm64 ppc64le"
+ }
+
+ if (Test-Path env:XC_OS) {
+ $XC_OS = $(Get-Content env:XC_OS)
+ } else {
+ $XC_OS = "linux darwin windows freebsd openbsd solaris"
+ }
+}
+
+# Delete the old dir
+echo "==> Removing old directory..."
+Remove-Item -Recurse -ErrorAction Ignore -Force "bin\"
+Remove-Item -Recurse -ErrorAction Ignore -Force "pkg\"
+New-Item -Type Directory -Name bin | Out-Null
+
+# Delete the old dir
+echo "==> Building..."
+gox.exe `
+ -os="${XC_OS}" `
+ -arch="${XC_ARCH}" `
+ -ldflags "-X github.com/hashicorp/packer/version.GitCommit=${GIT_COMMIT}${GIT_DIRTY}" `
+ -output "pkg/{{.OS}}_{{.Arch}}/packer" `
+ .
+
+if ($LastExitCode -ne 0) {
+ exit 1
+}
+
+# Move all the compiled things to the $GOPATH/bin
+$GOPATH=$(go.exe env GOPATH)
+
+# Copy our OS/Arch to the bin/ directory
+echo "==> Copying binaries for this platform..."
+Get-ChildItem ".\pkg\$(go env GOOS)_$(go env GOARCH)\" `
+ |? { !($_.PSIsContainer) } `
+ |% {
+ Copy-Item $_.FullName "bin\"
+ Copy-Item $_.FullName "${GOPATH}\bin\"
+ }
+
+# Done!
+echo "`r`n==> Results:"
+Get-ChildItem bin\
diff --git a/v1.9.4/scripts/build.sh b/v1.9.4/scripts/build.sh
new file mode 100755
index 0000000..8b65f50
--- /dev/null
+++ b/v1.9.4/scripts/build.sh
@@ -0,0 +1,159 @@
+#!/usr/bin/env bash
+# Copyright (c) HashiCorp, Inc.
+# SPDX-License-Identifier: MPL-2.0
+
+
+# This script builds the application from source for multiple platforms.
+# Determine the arch/os combos we're building for
+ALL_XC_ARCH="386 amd64 arm arm64 ppc64le mips mips64 mipsle mipsle64 s390x"
+ALL_XC_OS="linux darwin windows freebsd openbsd solaris"
+SKIPPED_OSARCH="!darwin/arm !freebsd/arm !freebsd/arm64"
+
+# Exit immediately if a command fails
+set -e
+
+# Validates that a necessary tool is on the PATH
+function validateToolPresence
+{
+ local TOOLNAME=$1
+ if ! which ${TOOLNAME} >/dev/null; then
+ echo "${TOOLNAME} is not on the path. Exiting..."
+ exit 1
+ fi
+}
+
+# Validates that all used tools are present; exits when any is not found
+function validatePreconditions
+{
+ echo "==> Checking for necessary tools..."
+ validateToolPresence realpath
+ validateToolPresence dirname
+ validateToolPresence tr
+ validateToolPresence find
+}
+
+# Get the parent directory of where this script is.
+# NOTE: I'm unsure why you don't just use realpath like below
+function enterPackerSourceDir
+{
+ echo "==> Entering Packer source dir..."
+ local BUILD_SCRIPT_PATH="${BASH_SOURCE[0]}"
+ SOURCEDIR=$(dirname $(dirname $(realpath "${BUILD_SCRIPT_PATH}")))
+ cd ${SOURCEDIR}
+}
+
+function ensureOutputStructure {
+ echo "==> Ensuring output directories are present..."
+ mkdir -p bin/
+ mkdir -p pkg/
+}
+
+function cleanOutputDirs {
+ echo "==> Removing old builds..."
+ rm -f bin/*
+ rm -fr pkg/*
+}
+
+function lowerCaseOSType {
+ local OS_TYPE=${OSTYPE:=`uname`}
+ echo "${OS_TYPE}" | tr "[:upper:]" "[:lower:]"
+}
+
+# Returns the OS appropriate path separator
+function getPathSeparator {
+ # helpers for Cygwin-hosted builds
+ case "$(lowerCaseOSType)" in
+ mingw*|msys*|cygwin*)
+ # cygwin only translates ';' to ':' on select environment variables
+ echo ';'
+ ;;
+ *) echo ':'
+ esac
+}
+
+function convertPathOnCygwin() {
+ local flag
+ local somePath
+ if [ "${1:0:1}" = '-' ]; then
+ flag=$1
+ somePath=$2
+ else
+ somePath=$1
+ fi
+
+ [ -n "${somePath}" ] || return 0
+ case "$(lowerCaseOSType)" in
+ cygwin*)
+ cygpath ${flag} -- "${somePath}"
+ ;;
+ *) echo "${somePath}"
+ esac
+}
+
+validatePreconditions
+enterPackerSourceDir
+ensureOutputStructure
+cleanOutputDirs
+
+PATHSEP=$(getPathSeparator)
+
+# XXX works in MINGW?
+# FIXME: What if go is not in the PATH and GOROOT isn't set?
+which go &>/dev/null || PATH+=":`convertPathOnCygwin "${GOROOT:?}"`/bin"
+
+OLDIFS="${IFS}"
+
+# make sure GOPATH is consistent - Windows binaries can't handle Cygwin-style paths
+IFS="${PATHSEP}"
+for d in ${GOPATH:-$(go env GOPATH)}; do
+ _GOPATH+="${_GOPATH:+${PATHSEP}}$(convertPathOnCygwin --windows "${d}")"
+done
+GOPATH="$_GOPATH"
+
+# locate 'gox' and traverse GOPATH if needed
+which "${GOX:=gox}" &>/dev/null || {
+ for d in ${GOPATH}; do
+ GOX="$(convertPathOnCygwin --unix "${d}")/bin/gox"
+ [ -x "${GOX}" ] && break || unset GOX
+ done
+}
+IFS="$OLDIFS"
+
+# Build!
+echo "==> Building..."
+
+# If in dev mode, only build for ourself
+if [ -n "${PACKER_DEV+x}" ]; then
+ XC_OS=$(go env GOOS)
+ XC_ARCH=$(go env GOARCH)
+fi
+
+export CGO_ENABLED=0
+
+${GOX:?command not found} \
+ -os="${XC_OS:-$ALL_XC_OS}" \
+ -arch="${XC_ARCH:-$ALL_XC_ARCH}" \
+ -osarch="${SKIPPED_OSARCH}" \
+ -ldflags "${GOLDFLAGS}" \
+ -output "pkg/{{.OS}}_{{.Arch}}/packer" \
+ .
+
+# trim GOPATH to first element
+IFS="${PATHSEP}"
+# FIXME: How do you know that the first path of GOPATH is the main GOPATH? Or is the main GOPATH meant to be the first path in GOPATH?
+MAIN_GOPATH=(${GOPATH})
+MAIN_GOPATH="$(convertPathOnCygwin --unix "${MAIN_GOPATH[0]}")"
+IFS="${OLDIFS}"
+
+# Copy our OS/Arch to the bin/ directory
+echo "==> Copying binaries for this platform..."
+DEV_PLATFORM="./pkg/$(go env GOOS)_$(go env GOARCH)"
+for F in $(find ${DEV_PLATFORM} -mindepth 1 -maxdepth 1 -type f); do
+ cp -v ${F} bin/
+ cp -v ${F} "${MAIN_GOPATH}/bin/"
+done
+
+# Done!
+echo
+echo "==> Results:"
+ls -hl bin/
diff --git a/v1.9.4/scripts/codesign_example.sh b/v1.9.4/scripts/codesign_example.sh
new file mode 100755
index 0000000..2e1a169
--- /dev/null
+++ b/v1.9.4/scripts/codesign_example.sh
@@ -0,0 +1,167 @@
+#! /usr/bin/env bash
+# Copyright (c) HashiCorp, Inc.
+# SPDX-License-Identifier: MPL-2.0
+
+set -euo pipefail
+
+# first makes some assertions about the environment and set some shared
+# variables before starting the script.
+if ! command -v jq > /dev/null 2>&1; then
+ echo "This script requires jq to work properly."
+ exit 1
+fi
+
+if ! command -v sha256sum > /dev/null 2>&1; then
+ if !command -v gsha256sum > /dev/null 2>&1; then
+ echo "This script requires sha256sum (linux) or gsha256sum (osx) to work properly."
+ exit 1
+ else
+ SHASUM_PROG=gsha256sum
+ fi
+else
+ SHASUM_PROG=sha256sum
+fi
+
+PRODUCT_NAME="${PRODUCT_NAME:-""}"
+if [ -z "$PRODUCT_NAME" ]; then
+ echo "Missing required product name: ${PRODUCT_NAME}"
+ exit 1
+fi
+
+TARGET_ZIP="${TARGET_ZIP:-""}"
+if [ -z "$TARGET_ZIP" ]; then
+ echo "Missing required target path"
+ exit 1
+fi
+
+# Artifactory configuration
+ARTIFACTORY_ENDPOINT="${ARTIFACTORY_ENDPOINT:-"https://artifactory.hashicorp.engineering/artifactory"}"
+ARTIFACTORY_INPUT_REPO="${ARTIFACTORY_INPUT_REPO:-"hc-signing-input"}"
+ARTIFACTORY_OUTPUT_REPO="${ARTIFACTORY_OUTPUT_REPO:-"hc-signing-output"}"
+
+ARTIFACTORY_TOKEN="${ARTIFACTORY_TOKEN:-""}"
+ARTIFACTORY_USER="${ARTIFACTORY_USER:-""}"
+
+if [[ -z "$ARTIFACTORY_TOKEN" || -z "$ARTIFACTORY_USER" ]]; then
+ echo "Missing required Artifactory credentials"
+ exit 1
+fi
+
+# Create the sign/notarize ID "SN_ID"
+if command -v uuidgen > /dev/null 2>&1; then
+ uuid="$(uuidgen)"
+elif [ -f /proc/sys/kernel/random/uuid ]; then
+ uuid="$(cat /proc/sys/kernel/random/uuid)"
+else
+ echo "This script needs some way to generate a uuid."
+ exit 1
+fi
+SN_ID="$uuid"
+
+# CircleCI configuration
+CIRCLE_ENDPOINT="${CIRCLE_ENDPOINT:-"https://circleci.com/api/v2"}"
+CIRCLE_PROJECT="${CIRCLE_PROJECT:-"project/github/hashicorp/circle-codesign"}"
+
+CIRCLE_TOKEN="${CIRCLE_TOKEN:-""}"
+if [ -z "$CIRCLE_TOKEN" ]; then
+ echo "Missing required CircleCI credentials"
+ exit 1
+fi
+
+# Next, upload an unsigned zip file to the Artifactory at
+# https://artifactory.hashicorp.engineering/artifactory/hc-signing-input/{PRODUCT}/{ID}.zip
+echo "Uploading unsigned zip to ${ARTIFACTORY_ENDPOINT}/${ARTIFACTORY_INPUT_REPO}/${PRODUCT_NAME}/${SN_ID}.zip"
+
+curl --show-error --silent --fail \
+ --user "${ARTIFACTORY_USER}:${ARTIFACTORY_TOKEN}" \
+ --request PUT \
+ "${ARTIFACTORY_ENDPOINT}/${ARTIFACTORY_INPUT_REPO}/${PRODUCT_NAME}/${SN_ID}.zip" \
+ --upload-file "$TARGET_ZIP" > /dev/null
+
+# Next, start the CircleCI Pipeline, then wait for a Workflow
+# to start.
+echo "Executing CircleCI job"
+
+res="$(curl --show-error --silent --fail --user "${CIRCLE_TOKEN}:" \
+ --request POST \
+ --header 'Content-Type: application/json' \
+ --header 'Accept: application/json' \
+ --data "{ \"branch\": \"main\" ,\"parameters\": { \"PRODUCT\": \"${PRODUCT_NAME}\", \"PKG_NAME\": \"${SN_ID}.zip\" } }" \
+ "${CIRCLE_ENDPOINT}/${CIRCLE_PROJECT}/pipeline")"
+pipeline_id="$(echo "$res" | jq -r '.id')"
+echo "CircleCI Pipeline $pipeline_id started"
+
+echo -n "Retrieving CircleCI Workflow ID"
+# 24 * 5 seconds = 2 minutes
+counter=12
+workflow_id=""
+# wait until a Workflow ID is found
+until [ "$workflow_id" != "" ]; do
+ echo -n "."
+ workflow_id=$(curl --silent --fail --user "${CIRCLE_TOKEN}:" \
+ --request GET \
+ --header 'Accept: application/json' \
+ "${CIRCLE_ENDPOINT}/pipeline/${pipeline_id}/workflow" \
+ | jq -r '.items[].id'
+ )
+ if [ "$counter" -eq "0" ]; then
+ echo "Tried too many times, but Pipeline ${pipeline_id} still has no Workflows"
+ exit 1
+ fi
+ counter=$((counter - 1))
+ sleep 5
+done
+echo ""
+
+echo "CircleCI Workflow $workflow_id started"
+
+# Next, wait for the Workflow to reach a terminal state, then fails if it isn't
+# "success"
+echo -n "Waiting for CircleCI Workflow ID: ${workflow_id}"
+# 360 * 5 seconds = 30 minutes
+counter=360
+finished="not_run"
+# wait for one of the terminal states: ["success", "failed", "error", "canceled"]
+until [[ "$finished" == "success" || "$finished" == "failed" || "$finished" == "error" || "$finished" == "canceled" ]]; do
+ echo -n "."
+ finished=$(curl --silent --fail --user "${CIRCLE_TOKEN}:" \
+ --header 'Accept: application/json' \
+ "${CIRCLE_ENDPOINT}/workflow/${workflow_id}" \
+ | jq -r '.status'
+ )
+ if [ "$counter" -eq "0" ]; then
+ echo "Tried too many times, but workflow is still in state ${finished}"
+ exit 1
+ fi
+ counter=$((counter - 1))
+ sleep 5
+done
+echo ""
+
+if [ "$finished" != "success" ]; then
+ echo "Workflow ID ${workflow_id} ${finished}"
+ exit 1
+fi
+
+# Next, download the signed zip from Artifactory at
+# https://artifactory.hashicorp.engineering/artifactory/hc-signing-output/{PRODUCT}/{ID}.zip
+echo "Retrieving signed zip from ${ARTIFACTORY_ENDPOINT}/${ARTIFACTORY_OUTPUT_REPO}/${PRODUCT_NAME}/${SN_ID}.zip"
+
+curl --show-error --silent --fail --user "${ARTIFACTORY_USER}:${ARTIFACTORY_TOKEN}" \
+ --request GET \
+ "${ARTIFACTORY_ENDPOINT}/${ARTIFACTORY_OUTPUT_REPO}/${PRODUCT_NAME}/${SN_ID}.zip" \
+ --output "signed_${SN_ID}.zip"
+
+signed_checksum=$(
+ curl --silent --show-error --fail --user "${ARTIFACTORY_USER}:${ARTIFACTORY_TOKEN}" \
+ --head \
+ "${ARTIFACTORY_ENDPOINT}/${ARTIFACTORY_OUTPUT_REPO}/${PRODUCT_NAME}/${SN_ID}.zip" \
+ | grep -i "x-checksum-sha256" | awk 'gsub("[\r\n]", "", $2) {print $2;}'
+)
+
+echo "${signed_checksum} signed_${SN_ID}.zip" | $SHASUM_PROG -c
+if [ $? -ne 0 ]; then
+ exit 1
+fi
+
+mv "signed_${SN_ID}.zip" "$TARGET_ZIP"
diff --git a/v1.9.4/scripts/dist.sh b/v1.9.4/scripts/dist.sh
new file mode 100755
index 0000000..113af57
--- /dev/null
+++ b/v1.9.4/scripts/dist.sh
@@ -0,0 +1,62 @@
+#!/usr/bin/env bash
+# Copyright (c) HashiCorp, Inc.
+# SPDX-License-Identifier: MPL-2.0
+
+set -e
+
+# Get the parent directory of where this script is.
+SOURCE="${BASH_SOURCE[0]}"
+while [ -h "$SOURCE" ] ; do SOURCE="$(readlink "$SOURCE")"; done
+DIR="$( cd -P "$( dirname "$SOURCE" )/.." && pwd )"
+
+# Change into that dir because we expect that
+cd $DIR
+
+# Get the version from the command line
+VERSION=$1
+if [ -z $VERSION ]; then
+ echo "Please specify version"
+ exit 1
+fi
+
+# Tag, unless told not to
+if [ -z $NOTAG ]; then
+ echo "==> Tagging..."
+ git commit --allow-empty -a --gpg-sign=348FFC4C -m "Cut version $VERSION"
+ git tag -a -m "Version $VERSION" -s -u 348FFC4C "v${VERSION}" $RELBRANCH
+fi
+
+# Zip all the files
+rm -rf ./pkg/dist
+mkdir -p ./pkg/dist
+for PLATFORM in $(find ./pkg -mindepth 1 -maxdepth 1 -type d); do
+ OSARCH=$(basename ${PLATFORM})
+
+ if [ $OSARCH = "dist" ]; then
+ continue
+ fi
+
+ echo "--> ${OSARCH}"
+ pushd $PLATFORM >/dev/null 2>&1
+ zip ../dist/packer_${VERSION}_${OSARCH}.zip ./*
+ popd >/dev/null 2>&1
+done
+
+./scripts/sign.sh
+if [ $? -ne 0 ]; then
+ exit 1
+fi
+
+if [ -z $NOSIGN ]; then
+ echo "==> Signing..."
+ pushd ./pkg/dist
+ rm -f ./packer_${VERSION}_SHA256SUMS*
+ shasum -a256 * > ./packer_${VERSION}_SHA256SUMS
+ gpg --default-key 348FFC4C --detach-sig ./packer_${VERSION}_SHA256SUMS
+ popd
+fi
+
+hc-releases upload $DIR/pkg/dist/
+hc-releases publish
+
+exit 0
diff --git a/v1.9.4/scripts/generate-plugins.go b/v1.9.4/scripts/generate-plugins.go
new file mode 100755
index 0000000..e52c063
--- /dev/null
+++ b/v1.9.4/scripts/generate-plugins.go
@@ -0,0 +1,372 @@
+// Copyright (c) HashiCorp, Inc.
+// SPDX-License-Identifier: MPL-2.0
+
+// Generate Plugins is a small program that updates the lists of plugins in
+// command/plugin.go so they will be compiled into the main packer binary.
+//
+// See https://github.com/hashicorp/packer/pull/2608 for details.
+package main
+
+import (
+ "fmt"
+ "go/ast"
+ "go/parser"
+ "go/token"
+ "io/ioutil"
+ "log"
+ "os"
+ "path/filepath"
+ "sort"
+ "strings"
+
+ "golang.org/x/tools/imports"
+)
+
+const target = "command/plugin.go"
+
+func main() {
+ wd, _ := os.Getwd()
+ if filepath.Base(wd) != "packer" {
+ log.Fatalf("This program must be invoked in the packer project root; in %s", wd)
+ }
+
+ // Collect all of the data we need about plugins we have in the project
+ builders, err := discoverBuilders()
+ if err != nil {
+ log.Fatalf("Failed to discover builders: %s", err)
+ }
+
+ provisioners, err := discoverProvisioners()
+ if err != nil {
+ log.Fatalf("Failed to discover provisioners: %s", err)
+ }
+
+ postProcessors, err := discoverPostProcessors()
+ if err != nil {
+ log.Fatalf("Failed to discover post processors: %s", err)
+ }
+
+ datasources, err := discoverDatasources()
+ if err != nil {
+ log.Fatalf("Failed to discover Datasources: %s", err)
+ }
+
+ // Do some simple code generation and templating
+ output := source
+ output = strings.Replace(output, "IMPORTS", makeImports(builders, provisioners, postProcessors, datasources), 1)
+ output = strings.Replace(output, "BUILDERS", makeMap("Builders", "Builder", builders), 1)
+ output = strings.Replace(output, "PROVISIONERS", makeMap("Provisioners", "Provisioner", provisioners), 1)
+ output = strings.Replace(output, "POSTPROCESSORS", makeMap("PostProcessors", "PostProcessor", postProcessors), 1)
+ output = strings.Replace(output, "DATASOURCES", makeMap("Datasources", "Datasource", datasources), 1)
+
+ // TODO sort the lists of plugins so we are not subjected to random OS ordering of the plugin lists
+ // TODO format the file
+
+ // Write our generated code to the command/plugin.go file
+ file, err := os.Create(target)
+ if err != nil {
+ log.Fatalf("Failed to open %s for writing: %s", target, err)
+ }
+ defer file.Close()
+
+ output = string(goFmt(target, []byte(output)))
+
+ _, err = file.WriteString(output)
+ if err != nil {
+ log.Fatalf("Failed writing to %s: %s", target, err)
+ }
+
+ log.Printf("Generated %s", target)
+}
+
+func goFmt(filename string, b []byte) []byte {
+ fb, err := imports.Process(filename, b, nil)
+ if err != nil {
+ log.Printf("formatting err: %v", err)
+ return b
+ }
+ return fb
+}
+
+type plugin struct {
+ Package string // This plugin's package name (iso)
+ PluginName string // Name of plugin (vmware-iso)
+ TypeName string // Type of plugin (builder)
+ Path string // Path relative to packer root (builder/vmware/iso)
+ ImportName string // PluginName+TypeName (vmwareisobuilder)
+}
+
+// makeMap creates a map named Name with type packer.Name that looks something
+// like this:
+//
+// var Builders = map[string]packersdk.Builder{
+// "amazon-chroot": new(chroot.Builder),
+// "amazon-ebs": new(ebs.Builder),
+// "amazon-instance": new(instance.Builder),
+func makeMap(varName, varType string, items []plugin) string {
+ output := ""
+
+ output += fmt.Sprintf("var %s = map[string]packersdk.%s{\n", varName, varType)
+ for _, item := range items {
+ output += fmt.Sprintf("\t\"%s\": new(%s.%s),\n", item.PluginName, item.ImportName, item.TypeName)
+ }
+ output += "}\n"
+ return output
+}
+
+func makeImports(builders, provisioners, postProcessors, Datasources []plugin) string {
+ plugins := []string{}
+
+ for _, builder := range builders {
+ plugins = append(plugins, fmt.Sprintf("\t%s \"github.com/hashicorp/packer/%s\"\n", builder.ImportName, filepath.ToSlash(builder.Path)))
+ }
+
+ for _, provisioner := range provisioners {
+ plugins = append(plugins, fmt.Sprintf("\t%s \"github.com/hashicorp/packer/%s\"\n", provisioner.ImportName, filepath.ToSlash(provisioner.Path)))
+ }
+
+ for _, postProcessor := range postProcessors {
+ plugins = append(plugins, fmt.Sprintf("\t%s \"github.com/hashicorp/packer/%s\"\n", postProcessor.ImportName, filepath.ToSlash(postProcessor.Path)))
+ }
+
+ for _, datasource := range Datasources {
+ plugins = append(plugins, fmt.Sprintf("\t%s \"github.com/hashicorp/packer/%s\"\n", datasource.ImportName, filepath.ToSlash(datasource.Path)))
+ }
+
+ // Make things pretty
+ sort.Strings(plugins)
+
+ return strings.Join(plugins, "")
+}
+
+// listDirectories recursively lists directories under the specified path
+func listDirectories(path string) ([]string, error) {
+ names := []string{}
+ items, err := ioutil.ReadDir(path)
+ if err != nil {
+ return names, err
+ }
+
+ for _, item := range items {
+ // We only want directories
+ if !item.IsDir() ||
+ item.Name() == "common" {
+ continue
+ }
+ currentDir := filepath.Join(path, item.Name())
+ names = append(names, currentDir)
+
+ // Do some recursion
+ subNames, err := listDirectories(currentDir)
+ if err == nil {
+ names = append(names, subNames...)
+ }
+ }
+
+ return names, nil
+}
+
+// deriveName determines the name of the plugin (what you'll see in a packer
+// template) based on the filesystem path. We use two rules:
+//
+// Start with -> builder/virtualbox/iso
+//
+// 1. Strip the root -> virtualbox/iso
+// 2. Switch slash / to dash - -> virtualbox-iso
+func deriveName(root, full string) string {
+ short, _ := filepath.Rel(root, full)
+ bits := strings.Split(short, string(os.PathSeparator))
+ return strings.Join(bits, "-")
+}
+
+// deriveImport will build a unique import identifier based on packageName and
+// the result of deriveName()
+//
+// This will be something like -> virtualboxisobuilder
+//
+// Which is long, but deterministic and unique.
+func deriveImport(typeName, derivedName string) string {
+ return strings.Replace(derivedName, "-", "", -1) + strings.ToLower(typeName)
+}
+
+// discoverTypesInPath searches for types of typeID in path and returns a list
+// of plugins it finds.
+func discoverTypesInPath(path, typeID string) ([]plugin, error) {
+ postProcessors := []plugin{}
+
+ dirs, err := listDirectories(path)
+ if err != nil {
+ return postProcessors, err
+ }
+
+ for _, dir := range dirs {
+ fset := token.NewFileSet()
+ goPackages, err := parser.ParseDir(fset, dir, nil, parser.AllErrors)
+ if err != nil {
+ return postProcessors, fmt.Errorf("Failed parsing directory %s: %s", dir, err)
+ }
+
+ for _, goPackage := range goPackages {
+ ast.PackageExports(goPackage)
+ ast.Inspect(goPackage, func(n ast.Node) bool {
+ switch x := n.(type) {
+ case *ast.TypeSpec:
+ if x.Name.Name == typeID {
+ derivedName := deriveName(path, dir)
+ postProcessors = append(postProcessors, plugin{
+ Package: goPackage.Name,
+ PluginName: derivedName,
+ ImportName: deriveImport(x.Name.Name, derivedName),
+ TypeName: x.Name.Name,
+ Path: dir,
+ })
+ // The AST stops parsing when we return false. Once we
+ // find the symbol we want we can stop parsing.
+
+ // DEBUG:
+ // fmt.Printf("package %#v\n", goPackage)
+ return false
+ }
+ }
+ return true
+ })
+ }
+ }
+
+ return postProcessors, nil
+}
+
+func discoverBuilders() ([]plugin, error) {
+ path := "./builder"
+ typeID := "Builder"
+ return discoverTypesInPath(path, typeID)
+}
+
+func discoverDatasources() ([]plugin, error) {
+ path := "./datasource"
+ typeID := "Datasource"
+ return discoverTypesInPath(path, typeID)
+}
+
+func discoverProvisioners() ([]plugin, error) {
+ path := "./provisioner"
+ typeID := "Provisioner"
+ return discoverTypesInPath(path, typeID)
+}
+
+func discoverPostProcessors() ([]plugin, error) {
+ path := "./post-processor"
+ typeID := "PostProcessor"
+ return discoverTypesInPath(path, typeID)
+}
+
+const source = `//
+// This file is automatically generated by scripts/generate-plugins.go -- Do not edit!
+//
+
+package command
+
+import (
+ "fmt"
+ "log"
+ "regexp"
+ "strings"
+
+ "github.com/hashicorp/packer/packer"
+packersdk "github.com/hashicorp/packer-plugin-sdk/packer"
+ "github.com/hashicorp/packer-plugin-sdk/plugin"
+
+IMPORTS
+)
+
+type PluginCommand struct {
+ Meta
+}
+
+BUILDERS
+
+PROVISIONERS
+
+POSTPROCESSORS
+
+DATASOURCES
+
+var pluginRegexp = regexp.MustCompile("packer-(builder|post-processor|provisioner|datasource)-(.+)")
+
+func (c *PluginCommand) Run(args []string) int {
+ // This is an internal call (users should not call this directly) so we're
+ // not going to do much input validation. If there's a problem we'll often
+ // just crash. Error handling should be added to facilitate debugging.
+ log.Printf("args: %#v", args)
+ if len(args) != 1 {
+ c.Ui.Error("Wrong number of args")
+ return 1
+ }
+
+ // Plugin will match something like "packer-builder-amazon-ebs"
+ parts := pluginRegexp.FindStringSubmatch(args[0])
+ if len(parts) != 3 {
+ c.Ui.Error(fmt.Sprintf("Error parsing plugin argument [DEBUG]: %#v", parts))
+ return 1
+ }
+ pluginType := parts[1] // capture group 1 (builder|post-processor|provisioner)
+ pluginName := parts[2] // capture group 2 (.+)
+
+ server, err := plugin.Server()
+ if err != nil {
+ c.Ui.Error(fmt.Sprintf("Error starting plugin server: %s", err))
+ return 1
+ }
+
+ switch pluginType {
+ case "builder":
+ builder, found := Builders[pluginName]
+ if !found {
+ c.Ui.Error(fmt.Sprintf("Could not load builder: %s", pluginName))
+ return 1
+ }
+ server.RegisterBuilder(builder)
+ case "provisioner":
+ provisioner, found := Provisioners[pluginName]
+ if !found {
+ c.Ui.Error(fmt.Sprintf("Could not load provisioner: %s", pluginName))
+ return 1
+ }
+ server.RegisterProvisioner(provisioner)
+ case "post-processor":
+ postProcessor, found := PostProcessors[pluginName]
+ if !found {
+ c.Ui.Error(fmt.Sprintf("Could not load post-processor: %s", pluginName))
+ return 1
+ }
+ server.RegisterPostProcessor(postProcessor)
+ case "datasource":
+ datasource, found := Datasources[pluginName]
+ if !found {
+ c.Ui.Error(fmt.Sprintf("Could not load datasource: %s", pluginName))
+ return 1
+ }
+ server.RegisterDatasource(datasource)
+ }
+
+ server.Serve()
+
+ return 0
+}
+
+func (*PluginCommand) Help() string {
+ helpText := ` + "`" + `
+Usage: packer plugin PLUGIN
+
+ Runs an internally-compiled version of a plugin from the packer binary.
+
+ NOTE: this is an internal command and you should not call it yourself.
+` + "`" + `
+
+ return strings.TrimSpace(helpText)
+}
+
+func (c *PluginCommand) Synopsis() string {
+ return "internal plugin command"
+}
+`
diff --git a/v1.9.4/scripts/off_gopath.sh b/v1.9.4/scripts/off_gopath.sh
new file mode 100755
index 0000000..beb1433
--- /dev/null
+++ b/v1.9.4/scripts/off_gopath.sh
@@ -0,0 +1,25 @@
+#! /usr/bin/env bash
+# Copyright (c) HashiCorp, Inc.
+# SPDX-License-Identifier: MPL-2.0
+
+
+set -eu -o pipefail
+
+gpath=${GOPATH:-}
+if [ -z "$gpath" ]; then
+ gpath=$HOME/go
+fi
+
+reldir=`dirname $0`
+curdir=`pwd`
+cd $reldir
+CUR_GO_DIR=`pwd`
+cd $curdir
+
+if [[ $CUR_GO_DIR == *"$gpath"* ]]; then
+ # echo "You're on the gopath"
+ exit 1
+else
+ # echo "You're not on the gopath"
+ exit 0
+fi
\ No newline at end of file
diff --git a/v1.9.4/scripts/prepare_changelog.sh b/v1.9.4/scripts/prepare_changelog.sh
new file mode 100755
index 0000000..3f77603
--- /dev/null
+++ b/v1.9.4/scripts/prepare_changelog.sh
@@ -0,0 +1,81 @@
+#!/bin/zsh
+# Copyright (c) HashiCorp, Inc.
+# SPDX-License-Identifier: MPL-2.0
+
+
+LAST_RELEASE=$1
+DO_PR_CHECK=1
+
+set -o pipefail
+
+is_doc_or_tech_debt_pr(){
+ if ! (($+commands[jq])); then
+ DO_PR_CHECK=0
+ echo "jq not found"
+ return 1
+ fi
+ out=$(python3 -m json.tool < pull.json \
+ | jq '[.labels[].name == "docs" or .labels[].name == "tech-debt" or .labels[].name == "website"] | any')
+ grep -q true <<< $out
+ return $?
+}
+
+if [ -z $LAST_RELEASE ]; then
+ echo "you need to give the previous release version. prepare_changelog.sh v<version>"
+ exit 1
+fi
+
+get_prs(){
+ # git log v0.10.2...c3861d167533fb797b0fae0c380806625712e5f7 |
+ git log HEAD...${LAST_RELEASE} --first-parent --oneline --grep="Merge pull request #[0-9]\+" --grep="(#[0-9]\+)$" |
+ grep -o "#\([0-9]\+\)" | awk -F\# '{print $2}' | while read line
+ do
+ grep -q "GH-${line}" CHANGELOG.md
+ if [ $? -ne 0 ]; then
+ echo $line
+ fi
+ done | while read PR_NUM
+ do
+ if [[ -z "${GITHUB_TOKEN}" ]] || [[ -z "${GITHUB_USERNAME}" ]] ; then
+ out=$(curl -fsS "https://api.github.com/repos/hashicorp/packer/issues/${PR_NUM}" -o pull.json)
+ else
+ # authenticated call
+ out=$(curl -u ${GITHUB_USERNAME}:${GITHUB_TOKEN} -fsS "https://api.github.com/repos/hashicorp/packer/issues/${PR_NUM}" -o pull.json)
+ fi
+ exy="$?"
+ if [ $exy -ne 0 ]; then
+ echo "bad response from github: manually check PR ${PR_NUM}"
+ continue
+ fi
+
+ if (($DO_PR_CHECK)) && is_doc_or_tech_debt_pr; then
+ echo "Skipping PR ${PR_NUM}: labeled as tech debt, docs or website. (waiting a second so we don't get rate-limited...)"
+ continue
+ fi
+ echo "$(python3 -m json.tool < pull.json | jq -r '.title') - [GH-${PR_NUM}](https://github.com/hashicorp/packer/pull/${PR_NUM})"
+ done
+}
+
+#is_doc_or_tech_debt_pr 52061111
+# is_doc_or_tech_debt_pr 5206 # non-doc pr
+#is_doc_or_tech_debt_pr 5434 # doc pr
+#echo $?
+#exit
+
+# prpid=$!
+# trap 'kill -9 ${prpid}; exit' INT TERM
+
+get_prs | while read line; do
+ echo $line
+ if [[ "$line" =~ "bad" ]]; then
+ exit 1
+ elif [[ "$line" =~ "Skipping" ]]; then
+ sleep 1 # GH will rate limit us if we have several in a row
+ continue
+ fi
+ rm -f pull.json
+ vared -ch ok
+done
+
+
+#TODO: just generate it automatically using PR titles and tags
diff --git a/v1.9.4/scripts/sign.sh b/v1.9.4/scripts/sign.sh
new file mode 100755
index 0000000..f7d18ac
--- /dev/null
+++ b/v1.9.4/scripts/sign.sh
@@ -0,0 +1,44 @@
+# Copyright (c) HashiCorp, Inc.
+# SPDX-License-Identifier: MPL-2.0
+
+
+#!/usr/bin/env bash
+
+# This script uploads the Darwin builds to artifactory, then triggers the
+# circle ci job that signs them.
+
+# ARTIFACTORY_USER="sa-circle-codesign"
+# export PRODUCT_NAME="packer"
+# export ARTIFACTORY_TOKEN=$ARTIFACTORY_TOKEN
+
+ARTIFACTORY_TOKEN="${ARTIFACTORY_TOKEN:-""}"
+
+if [ -z "$ARTIFACTORY_TOKEN" ]; then
+ echo "Missing required Artifactory credentials"
+ exit 1
+fi
+
+# Get the parent directory of where this script is.
+SOURCE="${BASH_SOURCE[0]}"
+while [ -h "$SOURCE" ] ; do SOURCE="$(readlink "$SOURCE")"; done
+DIR="$( cd -P "$( dirname "$SOURCE" )/.." && pwd )"
+# Change into that dir because we expect that
+cd $DIR
+
+BIN_UUIDS=()
+BUILD_NUMBERS=()
+for DARWIN_BIN in $(find ./pkg/dist/*darwin_*.zip); do
+ echo "signing $DARWIN_BIN"
+ export ARTIFACTORY_USER="sa-circle-codesign"
+ export PRODUCT_NAME="packer"
+ export ARTIFACTORY_TOKEN=$ARTIFACTORY_TOKEN
+ export TARGET_ZIP=$DARWIN_BIN
+
+ echo $TARGET_ZIP
+ ./scripts/codesign_example.sh
+ if [ $? -ne 0 ]; then
+ exit 1
+ fi
+done
+
+exit 0
diff --git a/v1.9.4/scripts/sort-md-list.py b/v1.9.4/scripts/sort-md-list.py
new file mode 100755
index 0000000..9842977
--- /dev/null
+++ b/v1.9.4/scripts/sort-md-list.py
@@ -0,0 +1,76 @@
+#!/usr/bin/env python3
+# Copyright (c) HashiCorp, Inc.
+# SPDX-License-Identifier: MPL-2.0
+
+"""
+sort-md-list.py sorts markdown lists
+
+Use this script to prepare sections of the changelog.
+
+this script expects a bulleted markdown list in stdout
+
+for example
+
+./sort-md-list.py - <<EOF
+* builder/amazon: Only delete temporary key if we created one. [GH-4850]
+* core: Correctly reject config files which have junk after valid json.
+ [GH-4906]
+ * builder/azure: Replace calls to panic with error returns. [GH-4846]
+* communicator/winrm: Use KeepAlive to keep long-running connections open. [GH-4952]
+EOF
+
+output:
+
+* builder/amazon: Only delete temporary key if we created one. [GH-4850]
+* builder/azure: Replace calls to panic with error returns. [GH-4846]
+* communicator/winrm: Use KeepAlive to keep long-running connections open.
+ [GH-4952]
+* core: Correctly reject config files which have junk after valid json.
+ [GH-4906]
+
+As you can see, the output is sorted and spaced appropriately.
+
+Limitations:
+ * nested lists are not supported
+ * must be passed a list to stdin, it does not process the changelog
+ * whitespace within the list is elided
+"""
+
+import fileinput
+import sys
+import textwrap
+
+
+if __name__ == '__main__':
+ lines = []
+ working = []
+ for line in fileinput.input():
+ line = line.strip()
+ if line.startswith('*'):
+ if len(working):
+ lines.append( " ".join(working))
+ working = [line]
+ else:
+ working.append(line)
+ if len(working):
+ lines.append( " ".join(working))
+
+ # take care of blank line at start of selection
+ sys.stdin.seek(0)
+ if sys.stdin.readlines()[0].strip() == "":
+ print()
+
+ for line in sorted(lines, key=lambda s: s.lower()):
+ if line.strip() == "":
+ continue
+ # print "-"*79
+ wrapped = textwrap.wrap(line, 79)
+ print( wrapped[0] )
+ indented = " ".join([s.strip() for s in wrapped[1:]])
+ for iline in textwrap.wrap(indented, 79-4):
+ print(" " + iline)
+
+ # take care of blank line at end of selection
+ sys.stdin.seek(0)
+ if sys.stdin.readlines()[-1].strip() == "":
+ print()
diff --git a/v1.9.4/scripts/upgrade_plugins.sh b/v1.9.4/scripts/upgrade_plugins.sh
new file mode 100755
index 0000000..3ca2885
--- /dev/null
+++ b/v1.9.4/scripts/upgrade_plugins.sh
@@ -0,0 +1,68 @@
+#!/bin/zsh
+# Copyright (c) HashiCorp, Inc.
+# SPDX-License-Identifier: MPL-2.0
+
+
+## This script is to be run before a Packer release in order to update
+## all vendored plugins to the latest available release.
+## The SDK is included in the plugin list and will be upgraded as well if a
+## newest version is available.
+## This script should be run in packer's root.
+
+declare -a plugins=(
+ "hashicorp/packer-plugin-alicloud"
+ "hashicorp/packer-plugin-amazon"
+ "hashicorp/packer-plugin-ansible"
+ "hashicorp/packer-plugin-azure"
+ "hashicorp/packer-plugin-chef"
+ "hashicorp/packer-plugin-cloudstack"
+ "hashicorp/packer-plugin-converge"
+ "digitalocean/packer-plugin-digitalocean"
+ "hashicorp/packer-plugin-docker"
+ "hashicorp/packer-plugin-googlecompute"
+ "hashicorp/packer-plugin-hcloud"
+ "hashicorp/packer-plugin-hyperone"
+ "hashicorp/packer-plugin-hyperv"
+ "hashicorp/packer-plugin-jdcloud"
+ "hashicorp/packer-plugin-linode"
+ "hashicorp/packer-plugin-lxc"
+ "hashicorp/packer-plugin-lxd"
+ "hashicorp/packer-plugin-ncloud"
+ "hashicorp/packer-plugin-openstack"
+ "hashicorp/packer-plugin-oneandone"
+ "hashicorp/packer-plugin-parallels"
+ "hashicorp/packer-plugin-profitbricks"
+ "hashicorp/packer-plugin-proxmox"
+ "hashicorp/packer-plugin-puppet"
+ "hashicorp/packer-plugin-qemu"
+ "hashicorp/packer-plugin-sdk"
+ "hashicorp/packer-plugin-tencentcloud"
+ "hashicorp/packer-plugin-triton"
+ "hashicorp/packer-plugin-ucloud"
+ "hashicorp/packer-plugin-vagrant"
+ "hashicorp/packer-plugin-virtualbox"
+ "hashicorp/packer-plugin-vmware"
+ "hashicorp/packer-plugin-vsphere"
+ "hashicorp/packer-plugin-yandex"
+)
+
+## now loop through the above plugin array
+## update the plugins and the SDK to the latest available version
+for i in "${plugins[@]}"
+do
+ happy=false
+ while ! $happy
+ do
+ echo "upgrading $i"
+ output=$(go get -d github.com/$i)
+ happy=true
+ if [[ $output == *"443: Connection refused"* ]]; then
+ echo "Try again after 5 seconds"
+ sleep 5
+ happy=false
+ fi
+ done
+ sleep 1
+done
+
+go mod tidy -compat=1.18
diff --git a/v1.9.4/scripts/vagrant-freebsd-priv-config.sh b/v1.9.4/scripts/vagrant-freebsd-priv-config.sh
new file mode 100755
index 0000000..9d5f076
--- /dev/null
+++ b/v1.9.4/scripts/vagrant-freebsd-priv-config.sh
@@ -0,0 +1,38 @@
+#!/bin/sh
+# Copyright (c) HashiCorp, Inc.
+# SPDX-License-Identifier: MPL-2.0
+
+
+chown vagrant:wheel \
+ /opt/gopath \
+ /opt/gopath/src \
+ /opt/gopath/src/github.com \
+ /opt/gopath/src/github.com/hashicorp
+
+mkdir -p /usr/local/etc/pkg/repos
+
+cat <<EOT > /usr/local/etc/pkg/repos/FreeBSD.conf
+FreeBSD: {
+ url: "pkg+http://pkg.FreeBSD.org/\${ABI}/latest"
+}
+EOT
+
+pkg update
+
+pkg install -y \
+ editors/vim-console \
+ devel/git \
+ devel/gmake \
+ lang/go \
+ security/ca_root_nss \
+ shells/bash
+
+chsh -s /usr/local/bin/bash vagrant
+chsh -s /usr/local/bin/bash root
+
+cat <<EOT >> /home/vagrant/.profile
+export GOPATH=/opt/gopath
+export PATH=\$GOPATH/bin:\$PATH
+
+cd /opt/gopath/src/github.com/hashicorp/packer
+EOT
diff --git a/v1.9.4/scripts/vagrant-freebsd-unpriv-bootstrap.sh b/v1.9.4/scripts/vagrant-freebsd-unpriv-bootstrap.sh
new file mode 100755
index 0000000..89fc9fc
--- /dev/null
+++ b/v1.9.4/scripts/vagrant-freebsd-unpriv-bootstrap.sh
@@ -0,0 +1,11 @@
+#!/bin/sh
+# Copyright (c) HashiCorp, Inc.
+# SPDX-License-Identifier: MPL-2.0
+
+
+export GOPATH=/opt/gopath
+
+PATH=$GOPATH/bin:$PATH
+export PATH
+
+cd /opt/gopath/src/github.com/hashicorp/packer && gmake deps
diff --git a/v1.9.4/scripts/vagrant-linux-priv-config.sh b/v1.9.4/scripts/vagrant-linux-priv-config.sh
new file mode 100755
index 0000000..d89e10e
--- /dev/null
+++ b/v1.9.4/scripts/vagrant-linux-priv-config.sh
@@ -0,0 +1,23 @@
+#!/usr/bin/env bash
+# Copyright (c) HashiCorp, Inc.
+# SPDX-License-Identifier: MPL-2.0
+
+
+export DEBIAN_FRONTEND=noninteractive
+
+# Update and ensure we have apt-add-repository
+apt-get update
+apt-get install -y software-properties-common
+
+apt-get install -y bzr \
+ curl \
+ gcc \
+ git \
+ make \
+ mercurial \
+ zip
+
+# Ensure we cd into the working directory on login
+if ! grep "cd /opt/gopath/src/github.com/hashicorp/packer" /home/vagrant/.profile ; then
+ echo 'cd /opt/gopath/src/github.com/hashicorp/packer' >> /home/vagrant/.profile
+fi
diff --git a/v1.9.4/scripts/vagrant-linux-priv-go.sh b/v1.9.4/scripts/vagrant-linux-priv-go.sh
new file mode 100755
index 0000000..2d99bc1
--- /dev/null
+++ b/v1.9.4/scripts/vagrant-linux-priv-go.sh
@@ -0,0 +1,44 @@
+#!/usr/bin/env bash
+# Copyright (c) HashiCorp, Inc.
+# SPDX-License-Identifier: MPL-2.0
+
+
+function install_go() {
+ local go_version=1.13
+ local download=
+ download="https://dl.google.com/go/go${go_version}.linux-amd64.tar.gz"
+
+ if [ -d /usr/local/go ] ; then
+ return
+ fi
+
+ wget -q -O /tmp/go.tar.gz ${download}
+
+ tar -C /tmp -xf /tmp/go.tar.gz
+ sudo mv /tmp/go /usr/local
+ sudo chown -R root:root /usr/local/go
+}
+
+install_go
+
+# Ensure that the GOPATH tree is owned by vagrant:vagrant
+mkdir -p /opt/gopath
+chown -R vagrant:vagrant /opt/gopath
+
+# Ensure Go is on PATH
+if [ ! -e /usr/bin/go ] ; then
+ ln -s /usr/local/go/bin/go /usr/bin/go
+fi
+if [ ! -e /usr/bin/gofmt ] ; then
+ ln -s /usr/local/go/bin/gofmt /usr/bin/gofmt
+fi
+
+
+# Ensure new sessions know about GOPATH
+if [ ! -f /etc/profile.d/gopath.sh ] ; then
+ cat <<EOT > /etc/profile.d/gopath.sh
+export GOPATH="/opt/gopath"
+export PATH="/opt/gopath/bin:\$PATH"
+EOT
+ chmod 755 /etc/profile.d/gopath.sh
+fi
diff --git a/v1.9.4/scripts/vagrant-linux-unpriv-bootstrap.sh b/v1.9.4/scripts/vagrant-linux-unpriv-bootstrap.sh
new file mode 100755
index 0000000..ca7f004
--- /dev/null
+++ b/v1.9.4/scripts/vagrant-linux-unpriv-bootstrap.sh
@@ -0,0 +1,6 @@
+#!/usr/bin/env bash
+# Copyright (c) HashiCorp, Inc.
+# SPDX-License-Identifier: MPL-2.0
+
+
+cd /opt/gopath/src/github.com/hashicorp/packer && make dev
diff --git a/v1.9.4/test/README.md b/v1.9.4/test/README.md
new file mode 100644
index 0000000..1c8949f
--- /dev/null
+++ b/v1.9.4/test/README.md
@@ -0,0 +1,74 @@
+# Packer Black-Box Tests
+
+This folder contains tests that test Packer using a black-box approach:
+`packer` is executed directly (with whatever is on the PATH) and certain
+results are expected.
+
+Tests are run using [Bats](https://github.com/sstephenson/bats), and therefore
+Bash is required to run any tests.
+
+**Warning:** Many of these tests run using cloud infrastructure, and therefore have
+a real-world cost associated with running the tests. Be aware of that prior
+to running the tests. Additionally, many tests will leave left-over artifacts
+(AMIs) that you'll have to manually clean up.
+
+## Running Tests
+
+### Required Software
+
+Before running the tests, you'll need the following installed. If you're
+running on macOS, most of these are available with `brew`:
+
+* [Bats](https://github.com/sstephenson/bats)
+
+* [AWS cli](http://aws.amazon.com/cli/) for AWS tests as well as most
+ of the components.
+
+* [gcutil](https://developers.google.com/compute/docs/gcutil/#install) for
+ Google Compute Engine tests.
+
+* [h1-cli](https://github.com/hyperonecom/h1-client-go) for HyperOne tests.
+
+### Configuring Tests
+
+**For tests that require AWS credentials:**
+
+Set the following self-explanatory environmental variables:
+
+* `AWS_ACCESS_KEY_ID`
+* `AWS_SECRET_ACCESS_KEY`
+
+**For tests that test Google Compute Engine:**
+
+Set the following environmental variables:
+
+* `GC_BUCKET_NAME`
+* `GC_ACCOUNT_FILE`
+* `GC_PROJECT_ID`
+
+**For tests that test HyperOne:**
+
+Set the following environmental variables:
+
+* `HYPERONE_TOKEN`
+* `HYPERONE_PROJECT`
+
+You have to be authenticated within the `h1` tool (use `h1 login`).
+
+### Running
+
+These tests are meant to be run _one file at a time_. There are some
+test files (such as the amazon-chroot builder test) that simply won't
+run except in special environments, so running all test files will probably
+never work.
+
+If you're working on Packer and want to test that your change didn't
+adversely affect something, try running only the test that is related to
+your change.
+
+```
+$ bats builder_amazon_ebs.bats
+```
+
+Note: Working directory doesn't matter. You can call the bats test file
+from any directory.
diff --git a/v1.9.4/test/builder_googlecompute.bats b/v1.9.4/test/builder_googlecompute.bats
new file mode 100755
index 0000000..1051bb9
--- /dev/null
+++ b/v1.9.4/test/builder_googlecompute.bats
@@ -0,0 +1,36 @@
+#!/usr/bin/env bats
+#
+# This tests the googlecompute builder. The teardown function will
+# delete any images with the text "packerbats" within the name.
+
+load test_helper
+fixtures builder-googlecompute
+
+# Required parameters
+: ${GC_ACCOUNT_FILE:?}
+: ${GC_PROJECT_ID:?}
+command -v gcloud >/dev/null 2>&1 || {
+ echo "'gcloud' must be installed" >&2
+ exit 1
+}
+
+USER_VARS="${USER_VARS} -var account_file=${GC_ACCOUNT_FILE}"
+USER_VARS="${USER_VARS} -var project_id=${GC_PROJECT_ID}"
+
+# This tests if GCE has an image that contains the given parameter.
+gc_has_image() {
+ gcloud compute --format='table[no-heading](name)' --project=${GC_PROJECT_ID} images list \
+ | grep $1 | wc -l
+}
+
+teardown() {
+ gcloud compute --format='table[no-heading](name)' --project=${GC_PROJECT_ID} images list \
+ | grep packerbats \
+ | xargs -n1 gcloud compute --project=${GC_PROJECT_ID} images delete
+}
+
+@test "googlecompute: build minimal.json" {
+ run packer build ${USER_VARS} $FIXTURE_ROOT/minimal.json
+ [ "$status" -eq 0 ]
+ [ "$(gc_has_image "packerbats-minimal")" -eq 1 ]
+}
diff --git a/v1.9.4/test/builder_hyperone.bats b/v1.9.4/test/builder_hyperone.bats
new file mode 100755
index 0000000..66ae5e3
--- /dev/null
+++ b/v1.9.4/test/builder_hyperone.bats
@@ -0,0 +1,48 @@
+#!/usr/bin/env bats
+#
+# This tests the hyperone builder. The teardown function will
+# delete any images with the text "packerbats" within the name.
+
+load test_helper
+fixtures builder-hyperone
+
+# Required parameters
+: ${HYPERONE_TOKEN:?}
+: ${HYPERONE_PROJECT:?}
+command -v h1 >/dev/null 2>&1 || {
+ echo "'h1' must be installed" >&2
+ exit 1
+}
+
+USER_VARS="${USER_VARS} -var token=${HYPERONE_TOKEN}"
+USER_VARS="${USER_VARS} -var project=${HYPERONE_PROJECT}"
+
+hyperone_has_image() {
+ h1 image list --project-select=${HYPERONE_PROJECT} --query "[?tag.${2}=='${3}']" --output=tsv | grep $1 -c
+}
+
+teardown() {
+ h1 image list --project-select=${HYPERONE_PROJECT} --output=tsv \
+ | grep packerbats \
+ | awk '{print $1}' \
+ | xargs -n1 h1 image delete --project-select=${HYPERONE_PROJECT} --yes --image
+}
+
+@test "hyperone: build minimal.json" {
+ run packer build ${USER_VARS} $FIXTURE_ROOT/minimal.json
+ [ "$status" -eq 0 ]
+ [ "$(hyperone_has_image "packerbats-minimal" "key" "value")" -eq 1 ]
+}
+
+@test "hyperone: build new-syntax.pkr.hcl" {
+ run packer build ${USER_VARS} $FIXTURE_ROOT/new-syntax.pkr.hcl
+ [ "$status" -eq 0 ]
+ [ "$(hyperone_has_image "packerbats-hcl" "key" "value")" -eq 1 ]
+}
+
+
+@test "hyperone: build chroot.json" {
+ run packer build ${USER_VARS} $FIXTURE_ROOT/chroot.json
+ [ "$status" -eq 0 ]
+ [ "$(hyperone_has_image "packerbats-chroot" "key2" "value2")" -eq 1 ]
+}
diff --git a/v1.9.4/test/builder_lxc.bats b/v1.9.4/test/builder_lxc.bats
new file mode 100644
index 0000000..7173d0f
--- /dev/null
+++ b/v1.9.4/test/builder_lxc.bats
@@ -0,0 +1,106 @@
+#!/usr/bin/env bats
+#
+# This tests the lxc builder by creating minimal containers and checking that
+# custom lxc container configuration files are successfully applied. The
+# teardown function will delete any images in the output-lxc-* folders along
+# with the auto-generated lxc container configuration files and hook scripts.
+
+#load test_helper
+#fixtures builder-lxc
+FIXTURE_ROOT="$BATS_TEST_DIRNAME/fixtures/builder-lxc"
+
+have_command() {
+ command -v "$1" >/dev/null 2>&1
+}
+
+# Required parameters
+have_command lxc-create || {
+ echo "'lxc-create' must be installed via the lxc (or lxc1 for ubuntu >=16.04) package" >&2
+ exit 1
+}
+
+DESTROY_HOOK_SCRIPT=$FIXTURE_ROOT/destroy-hook.sh
+DESTROY_HOOK_LOG=$FIXTURE_ROOT/destroy-hook.log
+printf > "$DESTROY_HOOK_SCRIPT" '
+echo "$LXC_NAME" > "%s"
+' "$DESTROY_HOOK_LOG"
+chmod +x "$DESTROY_HOOK_SCRIPT"
+
+INIT_CONFIG=$FIXTURE_ROOT/lxc.custom.conf
+printf > "$INIT_CONFIG" '
+lxc.hook.destroy = %s
+' "$DESTROY_HOOK_SCRIPT"
+
+teardown() {
+ for f in "$INIT_CONFIG" "$DESTROY_HOOK_SCRIPT" "$DESTROY_HOOK_LOG"; do
+ [ -e "$f" ] && rm -f "$f"
+ done
+
+ rm -rf output-lxc-*
+}
+
+assert_build() {
+ local template_name="$1"
+ shift
+
+ local build_status=0
+
+ run packer build -var template_name="$template_name" "$@"
+
+ [ "$status" -eq 0 ] || {
+ echo "${template_name} build exited badly: $status" >&2
+ echo "$output" >&2
+ build_status="$status"
+ }
+
+ for expected in "output-lxc-${template_name}"/{rootfs.tar.gz,lxc-config}; do
+ [ -f "$expected" ] || {
+ echo "missing expected artifact '${expected}'" >&2
+ build_status=1
+ }
+ done
+
+ return $build_status
+}
+
+assert_container_name() {
+ local container_name="$1"
+
+ [ -f "$DESTROY_HOOK_LOG" ] || {
+ echo "missing expected lxc.hook.destroy logfile '$DESTROY_HOOK_LOG'"
+ return 1
+ }
+
+ read -r lxc_name < "$DESTROY_HOOK_LOG"
+
+ [ "$lxc_name" = "$container_name" ]
+}
+
+@test "lxc: build centos minimal.json" {
+ have_command yum || skip "'yum' must be installed to build centos containers"
+ local container_name=packer-lxc-centos
+ assert_build centos -var init_config="$INIT_CONFIG" \
+ -var container_name="$container_name" \
+ $FIXTURE_ROOT/minimal.json
+ assert_container_name "$container_name"
+}
+
+@test "lxc: build trusty minimal.json" {
+ have_command debootstrap || skip "'debootstrap' must be installed to build ubuntu containers"
+ local container_name=packer-lxc-ubuntu
+ assert_build ubuntu -var init_config="$INIT_CONFIG" \
+ -var container_name="$container_name" \
+ -var template_parameters="SUITE=trusty" \
+ $FIXTURE_ROOT/minimal.json
+ assert_container_name "$container_name"
+}
+
+@test "lxc: build debian minimal.json" {
+ have_command debootstrap || skip "'debootstrap' must be installed to build debian containers"
+ local container_name=packer-lxc-debian
+ assert_build debian -var init_config="$INIT_CONFIG" \
+ -var container_name="$container_name" \
+ -var template_parameters="SUITE=jessie" \
+ $FIXTURE_ROOT/minimal.json
+ assert_container_name "$container_name"
+}
diff --git a/v1.9.4/test/cli.bats b/v1.9.4/test/cli.bats
new file mode 100755
index 0000000..0284dd3
--- /dev/null
+++ b/v1.9.4/test/cli.bats
@@ -0,0 +1,36 @@
+#!/usr/bin/env bats
+#
+# This tests the basic CLI functionality of Packer. It makes no network
+# requests and should be very fast.
+
+load test_helper
+
+@test "cli: packer should show help" {
+ run packer
+ [ "$status" -eq 1 ]
+ [[ "$output" == *"usage: packer"* ]]
+}
+
+@test "cli: packer version" {
+ run packer version
+ [ "$status" -eq 0 ]
+ [[ "$output" == *"Packer v"* ]]
+
+ run packer -v
+ [ "$status" -eq 1 ]
+ [[ "$output" =~ ([0-9]+\.[0-9]+) ]]
+
+ run packer --version
+ [ "$status" -eq 1 ]
+ [[ "$output" =~ ([0-9]+\.[0-9]+) ]]
+}
+
+@test "cli: packer version show help" {
+ run packer version -h
+ [ "$status" -eq 0 ]
+ [[ "$output" == *"Packer v"* ]]
+
+ run packer version --help
+ [ "$status" -eq 0 ]
+ [[ "$output" == *"Packer v"* ]]
+}
diff --git a/v1.9.4/test/communicator_ssh.bats b/v1.9.4/test/communicator_ssh.bats
new file mode 100644
index 0000000..eb466c9
--- /dev/null
+++ b/v1.9.4/test/communicator_ssh.bats
@@ -0,0 +1,30 @@
+#!/usr/bin/env bats
+#
+# This tests the ssh communicator using AWS builder. The teardown function will automatically
+# delete any AMIs with a tag of `packer-test` being equal to "true" so
+# be sure any test cases set this.
+
+load test_helper
+verify_aws_cli
+fixtures communicator-ssh
+
+setup() {
+ cd $FIXTURE_ROOT
+}
+
+teardown() {
+ aws_ami_cleanup
+}
+
+@test "shell provisioner: local port tunneling" {
+ run packer build $FIXTURE_ROOT/local-tunnel.json
+ [ "$status" -eq 0 ]
+ [[ "$output" == *"Connection to localhost port 10022 [tcp/*] succeeded"* ]]
+}
+
+@test "shell provisioner: remote port tunneling" {
+ run packer build $FIXTURE_ROOT/remote-tunnel.json
+ [ "$status" -eq 0 ]
+ MY_LOCAL_IP=$(curl -s https://ifconfig.co/)
+ [[ "$output" == *"$MY_LOCAL_IP"* ]]
+}
diff --git a/v1.9.4/test/fixtures/amazon-ebs/ami_region_copy.json b/v1.9.4/test/fixtures/amazon-ebs/ami_region_copy.json
new file mode 100644
index 0000000..6f591b6
--- /dev/null
+++ b/v1.9.4/test/fixtures/amazon-ebs/ami_region_copy.json
@@ -0,0 +1,15 @@
+{
+ "builders": [{
+ "type": "amazon-ebs",
+ "ami_name": "packer-test {{timestamp}}",
+ "instance_type": "m1.small",
+ "region": "us-east-1",
+ "ssh_username": "ubuntu",
+ "source_ami": "ami-0568456c",
+ "tags": {
+ "packer-test": "true",
+ "packer-id": "ami_region_copy"
+ },
+ "ami_regions": ["us-west-1", "us-west-2"]
+ }]
+}
diff --git a/v1.9.4/test/fixtures/amazon-ebs/minimal.json b/v1.9.4/test/fixtures/amazon-ebs/minimal.json
new file mode 100644
index 0000000..bfe7cab
--- /dev/null
+++ b/v1.9.4/test/fixtures/amazon-ebs/minimal.json
@@ -0,0 +1,13 @@
+{
+ "builders": [{
+ "type": "amazon-ebs",
+ "ami_name": "packer-test {{timestamp}}",
+ "instance_type": "m1.small",
+ "region": "us-east-1",
+ "ssh_username": "ubuntu",
+ "source_ami": "ami-0568456c",
+ "tags": {
+ "packer-test": "true"
+ }
+ }]
+}
diff --git a/v1.9.4/test/fixtures/builder-googlecompute/minimal.json b/v1.9.4/test/fixtures/builder-googlecompute/minimal.json
new file mode 100644
index 0000000..95dd992
--- /dev/null
+++ b/v1.9.4/test/fixtures/builder-googlecompute/minimal.json
@@ -0,0 +1,16 @@
+{
+ "variables": {
+ "account_file": null,
+ "project_id": null
+ },
+
+ "builders": [{
+ "type": "googlecompute",
+ "account_file": "{{user `account_file`}}",
+ "project_id": "{{user `project_id`}}",
+
+ "image_name": "packerbats-minimal-{{timestamp}}",
+ "source_image": "debian-7-wheezy-v20141108",
+ "zone": "us-central1-a"
+ }]
+}
diff --git a/v1.9.4/test/fixtures/builder-hyperone/chroot.json b/v1.9.4/test/fixtures/builder-hyperone/chroot.json
new file mode 100644
index 0000000..ccf7a8b
--- /dev/null
+++ b/v1.9.4/test/fixtures/builder-hyperone/chroot.json
@@ -0,0 +1,30 @@
+{
+ "variables": {
+ "token": null,
+ "project": null
+ },
+ "builders": [{
+ "token": "{{ user `token` }}",
+ "project": "{{ user `project` }}",
+ "type": "hyperone",
+ "source_image": "ubuntu",
+ "disk_size": 10,
+ "vm_type": "a1.nano",
+ "chroot_disk": true,
+ "chroot_command_wrapper": "sudo {{.Command}}",
+ "pre_mount_commands": [
+ "parted {{.Device}} mklabel msdos mkpart primary 1M 100% set 1 boot on print",
+ "mkfs.ext4 {{.Device}}1"
+ ],
+ "post_mount_commands": [
+ "apt-get update",
+ "apt-get install debootstrap",
+ "debootstrap --arch amd64 bionic {{.MountPath}}"
+ ],
+ "image_name": "packerbats-chroot-{{timestamp}}",
+ "image_tags": {
+ "key2":"value2"
+ }
+ }],
+ "provisioners": []
+}
diff --git a/v1.9.4/test/fixtures/builder-hyperone/minimal.json b/v1.9.4/test/fixtures/builder-hyperone/minimal.json
new file mode 100644
index 0000000..eb5411d
--- /dev/null
+++ b/v1.9.4/test/fixtures/builder-hyperone/minimal.json
@@ -0,0 +1,18 @@
+{
+ "variables": {
+ "token": null,
+ "project": null
+ },
+ "builders": [{
+ "token": "{{ user `token` }}",
+ "project": "{{ user `project` }}",
+ "type": "hyperone",
+ "source_image": "ubuntu",
+ "disk_size": 10,
+ "vm_type": "a1.nano",
+ "image_name": "packerbats-minimal-{{timestamp}}",
+ "image_tags": {
+ "key":"value"
+ }
+ }]
+}
diff --git a/v1.9.4/test/fixtures/builder-hyperone/new-syntax.pkr.hcl b/v1.9.4/test/fixtures/builder-hyperone/new-syntax.pkr.hcl
new file mode 100644
index 0000000..14e8d7e
--- /dev/null
+++ b/v1.9.4/test/fixtures/builder-hyperone/new-syntax.pkr.hcl
@@ -0,0 +1,29 @@
+variable "token" {
+ type = string
+}
+
+variable "project" {
+ type = string
+}
+
+source "hyperone" "new-syntax" {
+ token = var.token
+ project = var.project
+ source_image = "debian"
+ disk_size = 10
+ vm_type = "a1.nano"
+ image_name = "packerbats-hcl-{{timestamp}}"
+ image_tags = {
+ key="value"
+ }
+}
+
+build {
+ sources = [
+ "source.hyperone.new-syntax"
+ ]
+
+ provisioner "shell" {
+ inline = ["sleep 5"]
+ }
+}
\ No newline at end of file
diff --git a/v1.9.4/test/fixtures/builder-linode/minimal.json b/v1.9.4/test/fixtures/builder-linode/minimal.json
new file mode 100644
index 0000000..400cfa6
--- /dev/null
+++ b/v1.9.4/test/fixtures/builder-linode/minimal.json
@@ -0,0 +1,28 @@
+{
+ "variables": {
+ "linode_token": "{{env `LINODE_TOKEN`}}"
+ },
+ "builders": [
+ {
+ "type": "linode",
+ "linode_token": "{{user `linode_token`}}",
+
+ "region": "us-central",
+ "swap_size": 256,
+ "image": "linode/debian9",
+ "instance_type": "g6-nanode-1",
+ "instance_label": "packerbats-minimal-{{timestamp}}",
+
+ "image_label": "packerbats-minimal-image-{{timestamp}}",
+ "image_description": "packerbats",
+
+ "ssh_username": "root"
+ }
+ ],
+ "provisioners": [
+ {
+ "type": "shell",
+ "inline": ["echo Hello > /root/message.txt"]
+ }
+ ]
+ }
diff --git a/v1.9.4/test/fixtures/builder-lxc/minimal.json b/v1.9.4/test/fixtures/builder-lxc/minimal.json
new file mode 100644
index 0000000..997e48c
--- /dev/null
+++ b/v1.9.4/test/fixtures/builder-lxc/minimal.json
@@ -0,0 +1,31 @@
+{
+ "variables": {
+ "template_name": "debian",
+ "template_parameters": "SUITE=jessie",
+ "container_name": "packer-lxc",
+ "set_var": "hello"
+ },
+ "provisioners": [
+ {
+ "type": "shell",
+ "inline": [
+ "if [ \"$SET_VAR\" != \"{{user `set_var`}}\" ]; then",
+ " echo \"Got unexpected value '$SET_VAR' for SET_VAR\" 1>&2",
+ " exit 1",
+ "fi"
+ ]
+ }
+ ],
+ "builders": [
+ {
+ "type": "lxc",
+ "name": "lxc-{{user `template_name`}}",
+ "template_name": "{{user `template_name`}}",
+ "container_name": "{{user `container_name`}}",
+ "create_options": [ "-f", "{{user `init_config`}}" ],
+ "attach_options": [ "--clear-env", "--set-var", "SET_VAR={{user `set_var`}}" ],
+ "config_file": "/usr/share/lxc/config/{{user `template_name`}}.common.conf",
+ "template_environment_vars": [ "{{user `template_parameters`}}" ]
+ }
+ ]
+}
diff --git a/v1.9.4/test/fixtures/communicator-ssh/local-tunnel.json b/v1.9.4/test/fixtures/communicator-ssh/local-tunnel.json
new file mode 100644
index 0000000..2db4ebc
--- /dev/null
+++ b/v1.9.4/test/fixtures/communicator-ssh/local-tunnel.json
@@ -0,0 +1,21 @@
+{
+ "builders": [{
+ "type": "amazon-ebs",
+ "ami_name": "packer-test {{timestamp}}",
+ "instance_type": "m1.small",
+ "region": "us-east-1",
+ "ssh_username": "ubuntu",
+ "ssh_local_tunnels": ["10022:localhost:22"],
+ "source_ami": "ami-0568456c",
+ "tags": {
+ "packer-test": "true"
+ }
+ }],
+
+ "provisioners": [{
+ "type": "shell-local",
+ "inline": [
+ "echo | nc -G 5 -w 5 -v localhost 10022 2>&1"
+ ]
+ }]
+}
diff --git a/v1.9.4/test/fixtures/communicator-ssh/remote-tunnel.json b/v1.9.4/test/fixtures/communicator-ssh/remote-tunnel.json
new file mode 100644
index 0000000..8f69be8
--- /dev/null
+++ b/v1.9.4/test/fixtures/communicator-ssh/remote-tunnel.json
@@ -0,0 +1,22 @@
+{
+ "builders": [{
+ "type": "amazon-ebs",
+ "ami_name": "packer-test {{timestamp}}",
+ "instance_type": "t2.micro",
+ "region": "us-east-1",
+ "ssh_username": "ubuntu",
+ "ssh_remote_tunnels": ["8443:ifconfig.co:443"],
+ "source_ami": "ami-0111e8c43a763eb71",
+ "tags": {
+ "packer-test": "true"
+ }
+ }],
+ "provisioners": [{
+ "inline": [
+ "curl -kvs --connect-to ifconfig.co:443:localhost:8443 https://ifconfig.co/"
+ ],
+ "type": "shell"
+ }
+ ]
+ }
+
\ No newline at end of file
diff --git a/v1.9.4/test/fixtures/provisioner-file/dir/file.txt b/v1.9.4/test/fixtures/provisioner-file/dir/file.txt
new file mode 100644
index 0000000..806dddb
--- /dev/null
+++ b/v1.9.4/test/fixtures/provisioner-file/dir/file.txt
@@ -0,0 +1 @@
+337 miles
diff --git a/v1.9.4/test/fixtures/provisioner-file/dir_no_trailing.json b/v1.9.4/test/fixtures/provisioner-file/dir_no_trailing.json
new file mode 100644
index 0000000..e48a2f1
--- /dev/null
+++ b/v1.9.4/test/fixtures/provisioner-file/dir_no_trailing.json
@@ -0,0 +1,22 @@
+{
+ "builders": [{
+ "type": "amazon-ebs",
+ "ami_name": "packer-test {{timestamp}}",
+ "instance_type": "m1.small",
+ "region": "us-east-1",
+ "ssh_username": "ubuntu",
+ "source_ami": "ami-0568456c",
+ "tags": {
+ "packer-test": "true"
+ }
+ }],
+
+ "provisioners": [{
+ "type": "file",
+ "source": "dir",
+ "destination": "/tmp"
+ }, {
+ "type": "shell",
+ "inline": ["cat /tmp/dir/file.txt"]
+ }]
+}
diff --git a/v1.9.4/test/fixtures/provisioner-file/dir_no_trailing_sftp.json b/v1.9.4/test/fixtures/provisioner-file/dir_no_trailing_sftp.json
new file mode 100644
index 0000000..2837516
--- /dev/null
+++ b/v1.9.4/test/fixtures/provisioner-file/dir_no_trailing_sftp.json
@@ -0,0 +1,23 @@
+{
+ "builders": [{
+ "type": "amazon-ebs",
+ "ami_name": "packer-test {{timestamp}}",
+ "instance_type": "t2.micro",
+ "region": "us-east-1",
+ "ssh_username": "ec2-user",
+ "ssh_file_transfer_method": "sftp",
+ "source_ami": "ami-8da458e6",
+ "tags": {
+ "packer-test": "true"
+ }
+ }],
+
+ "provisioners": [{
+ "type": "file",
+ "source": "dir",
+ "destination": "/tmp"
+ }, {
+ "type": "shell",
+ "inline": ["cat /tmp/dir/file.txt"]
+ }]
+}
diff --git a/v1.9.4/test/fixtures/provisioner-file/dir_with_trailing.json b/v1.9.4/test/fixtures/provisioner-file/dir_with_trailing.json
new file mode 100644
index 0000000..bf5f754
--- /dev/null
+++ b/v1.9.4/test/fixtures/provisioner-file/dir_with_trailing.json
@@ -0,0 +1,22 @@
+{
+ "builders": [{
+ "type": "amazon-ebs",
+ "ami_name": "packer-test {{timestamp}}",
+ "instance_type": "m1.small",
+ "region": "us-east-1",
+ "ssh_username": "ubuntu",
+ "source_ami": "ami-0568456c",
+ "tags": {
+ "packer-test": "true"
+ }
+ }],
+
+ "provisioners": [{
+ "type": "file",
+ "source": "dir/",
+ "destination": "/tmp"
+ }, {
+ "type": "shell",
+ "inline": ["cat /tmp/file.txt"]
+ }]
+}
diff --git a/v1.9.4/test/fixtures/provisioner-file/dir_with_trailing_sftp.json b/v1.9.4/test/fixtures/provisioner-file/dir_with_trailing_sftp.json
new file mode 100644
index 0000000..f263654
--- /dev/null
+++ b/v1.9.4/test/fixtures/provisioner-file/dir_with_trailing_sftp.json
@@ -0,0 +1,23 @@
+{
+ "builders": [{
+ "type": "amazon-ebs",
+ "ami_name": "packer-test {{timestamp}}",
+ "instance_type": "t2.micro",
+ "region": "us-east-1",
+ "ssh_username": "ec2-user",
+ "ssh_file_transfer_method": "sftp",
+ "source_ami": "ami-8da458e6",
+ "tags": {
+ "packer-test": "true"
+ }
+ }],
+
+ "provisioners": [{
+ "type": "file",
+ "source": "dir/",
+ "destination": "/tmp"
+ }, {
+ "type": "shell",
+ "inline": ["cat /tmp/file.txt"]
+ }]
+}
diff --git a/v1.9.4/test/fixtures/provisioner-file/file.json b/v1.9.4/test/fixtures/provisioner-file/file.json
new file mode 100644
index 0000000..e8287ab
--- /dev/null
+++ b/v1.9.4/test/fixtures/provisioner-file/file.json
@@ -0,0 +1,22 @@
+{
+ "builders": [{
+ "type": "amazon-ebs",
+ "ami_name": "packer-test {{timestamp}}",
+ "instance_type": "m1.small",
+ "region": "us-east-1",
+ "ssh_username": "ubuntu",
+ "source_ami": "ami-0568456c",
+ "tags": {
+ "packer-test": "true"
+ }
+ }],
+
+ "provisioners": [{
+ "type": "file",
+ "source": "file.txt",
+ "destination": "/tmp/file.txt"
+ }, {
+ "type": "shell",
+ "inline": ["cat /tmp/file.txt"]
+ }]
+}
diff --git a/v1.9.4/test/fixtures/provisioner-file/file.txt b/v1.9.4/test/fixtures/provisioner-file/file.txt
new file mode 100644
index 0000000..e8a85b0
--- /dev/null
+++ b/v1.9.4/test/fixtures/provisioner-file/file.txt
@@ -0,0 +1 @@
+24901 miles
diff --git a/v1.9.4/test/fixtures/provisioner-file/file_sftp.json b/v1.9.4/test/fixtures/provisioner-file/file_sftp.json
new file mode 100644
index 0000000..19a8a98
--- /dev/null
+++ b/v1.9.4/test/fixtures/provisioner-file/file_sftp.json
@@ -0,0 +1,23 @@
+{
+ "builders": [{
+ "type": "amazon-ebs",
+ "ami_name": "packer-test {{timestamp}}",
+ "instance_type": "t2.micro",
+ "region": "us-east-1",
+ "ssh_username": "ec2-user",
+ "ssh_file_transfer_method": "sftp",
+ "source_ami": "ami-8da458e6",
+ "tags": {
+ "packer-test": "true"
+ }
+ }],
+
+ "provisioners": [{
+ "type": "file",
+ "source": "file.txt",
+ "destination": "/tmp/file.txt"
+ }, {
+ "type": "shell",
+ "inline": ["cat /tmp/file.txt"]
+ }]
+}
diff --git a/v1.9.4/test/fixtures/provisioner-shell/inline.json b/v1.9.4/test/fixtures/provisioner-shell/inline.json
new file mode 100644
index 0000000..25afae1
--- /dev/null
+++ b/v1.9.4/test/fixtures/provisioner-shell/inline.json
@@ -0,0 +1,21 @@
+{
+ "builders": [{
+ "type": "amazon-ebs",
+ "ami_name": "packer-test {{timestamp}}",
+ "instance_type": "m1.small",
+ "region": "us-east-1",
+ "ssh_username": "ubuntu",
+ "source_ami": "ami-0568456c",
+ "tags": {
+ "packer-test": "true"
+ }
+ }],
+
+ "provisioners": [{
+ "type": "shell",
+ "inline": [
+ "bash -c 'echo HELLO I AM `whoami`'",
+ "echo AND ANOTHER"
+ ]
+ }]
+}
diff --git a/v1.9.4/test/fixtures/provisioner-shell/script.json b/v1.9.4/test/fixtures/provisioner-shell/script.json
new file mode 100644
index 0000000..dc8ad50
--- /dev/null
+++ b/v1.9.4/test/fixtures/provisioner-shell/script.json
@@ -0,0 +1,18 @@
+{
+ "builders": [{
+ "type": "amazon-ebs",
+ "ami_name": "packer-test {{timestamp}}",
+ "instance_type": "m1.small",
+ "region": "us-east-1",
+ "ssh_username": "ubuntu",
+ "source_ami": "ami-0568456c",
+ "tags": {
+ "packer-test": "true"
+ }
+ }],
+
+ "provisioners": [{
+ "type": "shell",
+ "script": "script.sh"
+ }]
+}
diff --git a/v1.9.4/test/fixtures/provisioner-shell/script.sh b/v1.9.4/test/fixtures/provisioner-shell/script.sh
new file mode 100755
index 0000000..e4e504f
--- /dev/null
+++ b/v1.9.4/test/fixtures/provisioner-shell/script.sh
@@ -0,0 +1,3 @@
+#!/usr/bin/env bash
+
+echo HELLO I AM DOG
diff --git a/v1.9.4/test/fixtures/provisioner-shell/scripts.json b/v1.9.4/test/fixtures/provisioner-shell/scripts.json
new file mode 100644
index 0000000..290c6f5
--- /dev/null
+++ b/v1.9.4/test/fixtures/provisioner-shell/scripts.json
@@ -0,0 +1,20 @@
+{
+ "builders": [{
+ "type": "amazon-ebs",
+ "ami_name": "packer-test {{timestamp}}",
+ "instance_type": "m1.small",
+ "region": "us-east-1",
+ "ssh_username": "ubuntu",
+ "source_ami": "ami-0568456c",
+ "tags": {
+ "packer-test": "true"
+ }
+ }],
+
+ "provisioners": [{
+ "type": "shell",
+ "scripts": [
+ "script.sh"
+ ]
+ }]
+}
diff --git a/v1.9.4/test/provisioner_file.bats b/v1.9.4/test/provisioner_file.bats
new file mode 100755
index 0000000..3c84698
--- /dev/null
+++ b/v1.9.4/test/provisioner_file.bats
@@ -0,0 +1,53 @@
+#!/usr/bin/env bats
+#
+# This tests the amazon-ebs builder. The teardown function will automatically
+# delete any AMIs with a tag of `packer-test` being equal to "true" so
+# be sure any test cases set this.
+
+load test_helper
+verify_aws_cli
+fixtures provisioner-file
+
+setup() {
+ cd $FIXTURE_ROOT
+}
+
+teardown() {
+ aws_ami_cleanup
+}
+
+@test "file provisioner: single file" {
+ run packer build $FIXTURE_ROOT/file.json
+ [ "$status" -eq 0 ]
+ [[ "$output" == *"24901 miles"* ]]
+}
+
+@test "file provisioner: directory (no trailing slash)" {
+ run packer build $FIXTURE_ROOT/dir_no_trailing.json
+ [ "$status" -eq 0 ]
+ [[ "$output" == *"337 miles"* ]]
+}
+
+@test "file provisioner: directory (with trailing slash)" {
+ run packer build $FIXTURE_ROOT/dir_with_trailing.json
+ [ "$status" -eq 0 ]
+ [[ "$output" == *"337 miles"* ]]
+}
+
+@test "file provisioner: single file through sftp" {
+ run packer build $FIXTURE_ROOT/file_sftp.json
+ [ "$status" -eq 0 ]
+ [[ "$output" == *"24901 miles"* ]]
+}
+
+@test "file provisioner: directory through sftp (no trailing slash)" {
+ run packer build $FIXTURE_ROOT/dir_no_trailing_sftp.json
+ [ "$status" -eq 0 ]
+ [[ "$output" == *"337 miles"* ]]
+}
+
+@test "file provisioner: directory through sftp (with trailing slash)" {
+ run packer build $FIXTURE_ROOT/dir_with_trailing_sftp.json
+ [ "$status" -eq 0 ]
+ [[ "$output" == *"337 miles"* ]]
+}
diff --git a/v1.9.4/test/provisioner_shell.bats b/v1.9.4/test/provisioner_shell.bats
new file mode 100755
index 0000000..016c209
--- /dev/null
+++ b/v1.9.4/test/provisioner_shell.bats
@@ -0,0 +1,36 @@
+#!/usr/bin/env bats
+#
+# This tests the amazon-ebs builder. The teardown function will automatically
+# delete any AMIs with a tag of `packer-test` being equal to "true" so
+# be sure any test cases set this.
+
+load test_helper
+verify_aws_cli
+fixtures provisioner-shell
+
+setup() {
+ cd $FIXTURE_ROOT
+}
+
+teardown() {
+ aws_ami_cleanup
+}
+
+@test "shell provisioner: inline scripts" {
+ run packer build $FIXTURE_ROOT/inline.json
+ [ "$status" -eq 0 ]
+ [[ "$output" == *"HELLO I AM ubuntu"* ]]
+ [[ "$output" == *"AND ANOTHER"* ]]
+}
+
+@test "shell provisioner: script" {
+ run packer build $FIXTURE_ROOT/script.json
+ [ "$status" -eq 0 ]
+ [[ "$output" == *"HELLO I AM DOG"* ]]
+}
+
+@test "shell provisioner: scripts" {
+ run packer build $FIXTURE_ROOT/scripts.json
+ [ "$status" -eq 0 ]
+ [[ "$output" == *"HELLO I AM DOG"* ]]
+}
diff --git a/v1.9.4/test/test_helper.bash b/v1.9.4/test/test_helper.bash
new file mode 100644
index 0000000..a9dbc38
--- /dev/null
+++ b/v1.9.4/test/test_helper.bash
@@ -0,0 +1,52 @@
+# Let's verify that the tools we need are installed
+verify_aws_cli() {
+ declare -a required=(aws)
+ for cmd in "${required[@]}"; do
+ command -v $cmd >/dev/null 2>&1 || {
+ echo "'$cmd' must be installed" >&2
+ exit 1
+ }
+ done
+}
+
+#--------------------------------------------------------------------
+# Bats modification
+#--------------------------------------------------------------------
+# This allows us to override a function in Bash
+save_function() {
+ local ORIG_FUNC=$(declare -f $1)
+ local NEWNAME_FUNC="$2${ORIG_FUNC#$1}"
+ eval "$NEWNAME_FUNC"
+}
+
+# Override the run function so that we always output the output
+save_function run old_run
+run() {
+ old_run $@
+
+ # Output the command we ran
+ echo "Executing: " $@
+
+ # "$output" gets rid of newlines. This will bring them back.
+ for line in "${lines[@]}"; do
+ echo $line
+ done
+}
+
+#--------------------------------------------------------------------
+# Helper functions
+#--------------------------------------------------------------------
+# This sets the directory for fixtures by specifying the name of
+# the folder with fixtures.
+fixtures() {
+ FIXTURE_ROOT="$BATS_TEST_DIRNAME/fixtures/$1"
+}
+
+# This deletes any AMIs with a tag "packer-test" of "true"
+aws_ami_cleanup() {
+ local region=${1:-us-east-1}
+ aws ec2 describe-images --region ${region} --owners self --output text \
+ --filters 'Name=tag:packer-test,Values=true' \
+ --query 'Images[*].ImageId' \
+ | xargs -n1 aws ec2 deregister-image --region ${region} --image-id
+}
diff --git a/v1.9.4/tty.go b/v1.9.4/tty.go
new file mode 100644
index 0000000..a6f16d1
--- /dev/null
+++ b/v1.9.4/tty.go
@@ -0,0 +1,13 @@
+// Copyright (c) HashiCorp, Inc.
+// SPDX-License-Identifier: MPL-2.0
+
+//go:build !solaris
+// +build !solaris
+
+package main
+
+import (
+ "github.com/mattn/go-tty"
+)
+
+var openTTY = tty.Open
diff --git a/v1.9.4/tty_solaris.go b/v1.9.4/tty_solaris.go
new file mode 100644
index 0000000..257db94
--- /dev/null
+++ b/v1.9.4/tty_solaris.go
@@ -0,0 +1,14 @@
+// Copyright (c) HashiCorp, Inc.
+// SPDX-License-Identifier: MPL-2.0
+
+package main
+
+import (
+ "fmt"
+
+ packersdk "github.com/hashicorp/packer-plugin-sdk/packer"
+)
+
+func openTTY() (packersdk.TTY, error) {
+ return nil, fmt.Errorf("no TTY available on solaris")
+}
diff --git a/v1.9.4/version/VERSION b/v1.9.4/version/VERSION
new file mode 100644
index 0000000..70b02ff
--- /dev/null
+++ b/v1.9.4/version/VERSION
@@ -0,0 +1 @@
+1.9.4
\ No newline at end of file
diff --git a/v1.9.4/version/version.go b/v1.9.4/version/version.go
new file mode 100644
index 0000000..8e8805e
--- /dev/null
+++ b/v1.9.4/version/version.go
@@ -0,0 +1,55 @@
+// Copyright (c) HashiCorp, Inc.
+// SPDX-License-Identifier: MPL-2.0
+
+package version
+
+import (
+ "github.com/hashicorp/go-version"
+ pluginVersion "github.com/hashicorp/packer-plugin-sdk/version"
+)
+
+var (
+ // The git commit that was compiled. This will be filled in by the compiler.
+ GitCommit string
+ GitDescribe string
+
+ // Whether cgo is enabled or not; set at build time
+ CgoEnabled bool
+
+ // The next version number that will be released. This will be updated after every release
+ // Version must conform to the format expected by github.com/hashicorp/go-version
+ // for tests to work.
+ // A pre-release marker for the version can also be specified (e.g -dev). If this is omitted
+ // The main version number that is being run at the moment.
+
+ Version = "1.9.4"
+
+ // A pre-release marker for the version. If this is "" (empty string)
+ // then it means that it is a final release. Otherwise, this is a pre-release
+ // such as "dev" (in development), "beta", "rc1", etc.
+
+ VersionPrerelease = ""
+
+ VersionMetadata = ""
+)
+
+var PackerVersion *pluginVersion.PluginVersion
+
+func FormattedVersion() string {
+ return PackerVersion.FormattedVersion()
+}
+
+// SemVer is an instance of version.Version. This has the secondary
+// benefit of verifying during tests and init time that our version is a
+// proper semantic version, which should always be the case.
+var SemVer *version.Version
+
+func init() {
+ PackerVersion = pluginVersion.InitializePluginVersion(Version, VersionPrerelease)
+ SemVer = PackerVersion.SemVer()
+}
+
+// String returns the complete version string, including prerelease
+func String() string {
+ return PackerVersion.String()
+}
diff --git a/v1.9.4/website/.editorconfig b/v1.9.4/website/.editorconfig
new file mode 100644
index 0000000..36bf83f
--- /dev/null
+++ b/v1.9.4/website/.editorconfig
@@ -0,0 +1,18 @@
+# This file is for unifying the coding style for different editors and IDEs
+# editorconfig.org
+
+root = true
+
+[*]
+end_of_line = lf
+charset = utf-8
+insert_final_newline = true
+trim_trailing_whitespace = true
+indent_style = space
+indent_size = 2
+
+[Makefile]
+indent_style = tab
+
+[{*.md,*.json}]
+max_line_length = null
diff --git a/v1.9.4/website/.env b/v1.9.4/website/.env
new file mode 100644
index 0000000..5a1a7b3
--- /dev/null
+++ b/v1.9.4/website/.env
@@ -0,0 +1,3 @@
+NEXT_PUBLIC_ALGOLIA_APP_ID=YY0FFNI7MF
+NEXT_PUBLIC_ALGOLIA_INDEX=product_PACKER
+NEXT_PUBLIC_ALGOLIA_SEARCH_ONLY_API_KEY=4e1ea7f4bf4335ac43d9f28463e42148
diff --git a/v1.9.4/website/.env.production b/v1.9.4/website/.env.production
new file mode 100644
index 0000000..83825a8
--- /dev/null
+++ b/v1.9.4/website/.env.production
@@ -0,0 +1 @@
+HASHI_ENV=production
diff --git a/v1.9.4/website/.eslintrc.js b/v1.9.4/website/.eslintrc.js
new file mode 100644
index 0000000..17cba24
--- /dev/null
+++ b/v1.9.4/website/.eslintrc.js
@@ -0,0 +1,4 @@
+module.exports = {
+ ...require('@hashicorp/platform-cli/config/.eslintrc'),
+ ignorePatterns: ['public/']
+}
diff --git a/v1.9.4/website/.gitignore b/v1.9.4/website/.gitignore
new file mode 100644
index 0000000..e906627
--- /dev/null
+++ b/v1.9.4/website/.gitignore
@@ -0,0 +1,11 @@
+node_modules
+.DS_Store
+.next
+out
+.mdx-data
+
+# As per Next.js conventions (https://nextjs.org/docs/basic-features/environment-variables#default-environment-variables)
+!.env
+.env*.local
+
+website-preview
diff --git a/v1.9.4/website/.nvmrc b/v1.9.4/website/.nvmrc
new file mode 100644
index 0000000..6f7f377
--- /dev/null
+++ b/v1.9.4/website/.nvmrc
@@ -0,0 +1 @@
+v16
diff --git a/v1.9.4/website/.stylelintrc.js b/v1.9.4/website/.stylelintrc.js
new file mode 100644
index 0000000..497a1c9
--- /dev/null
+++ b/v1.9.4/website/.stylelintrc.js
@@ -0,0 +1,4 @@
+module.exports = {
+ ...require('@hashicorp/platform-cli/config/stylelint.config'),
+ /* Specify overrides here */
+}
diff --git a/v1.9.4/website/Dockerfile b/v1.9.4/website/Dockerfile
new file mode 100644
index 0000000..f8cbf41
--- /dev/null
+++ b/v1.9.4/website/Dockerfile
@@ -0,0 +1,8 @@
+FROM docker.mirror.hashicorp.services/node:14.17.0-alpine
+RUN apk add --update --no-cache git make g++ automake autoconf libtool nasm libpng-dev
+
+COPY ./package.json /website/package.json
+COPY ./package-lock.json /website/package-lock.json
+WORKDIR /website
+RUN npm install -g npm@latest
+RUN npm install
diff --git a/v1.9.4/website/LICENSE.md b/v1.9.4/website/LICENSE.md
new file mode 100644
index 0000000..3189f43
--- /dev/null
+++ b/v1.9.4/website/LICENSE.md
@@ -0,0 +1,10 @@
+# Proprietary License
+
+This license is temporary while a more official one is drafted. However,
+this should make it clear:
+
+The text contents of this website are MPL 2.0 licensed.
+
+The design contents of this website are proprietary and may not be reproduced
+or reused in any way other than to run the website locally. The license for
+the design is owned solely by HashiCorp, Inc.
diff --git a/v1.9.4/website/Makefile b/v1.9.4/website/Makefile
new file mode 100644
index 0000000..3d4fbb2
--- /dev/null
+++ b/v1.9.4/website/Makefile
@@ -0,0 +1,60 @@
+######################################################
+# NOTE: This file is managed by the Digital Team's #
+# Terraform configuration @ hashicorp/mktg-terraform #
+######################################################
+
+.DEFAULT_GOAL := website
+
+# Set the preview mode for the website shell to "developer" or "io"
+PREVIEW_MODE ?= developer
+REPO ?= packer
+
+# Enable setting alternate docker tool, e.g. 'make DOCKER_CMD=podman'
+DOCKER_CMD ?= docker
+
+CURRENT_GIT_BRANCH=$$(git rev-parse --abbrev-ref HEAD)
+LOCAL_CONTENT_DIR=
+PWD=$$(pwd)
+
+DOCKER_IMAGE="hashicorp/dev-portal"
+DOCKER_IMAGE_LOCAL="dev-portal-local"
+DOCKER_RUN_FLAGS=-it \
+ --publish "3000:3000" \
+ --rm \
+ --tty \
+ --volume "$(PWD)/content:/app/content" \
+ --volume "$(PWD)/public:/app/public" \
+ --volume "$(PWD)/data:/app/data" \
+ --volume "$(PWD)/redirects.js:/app/redirects.js" \
+ --volume "next-dir:/app/website-preview/.next" \
+ --volume "$(PWD)/.env:/app/.env" \
+ --volume "$(PWD)/.env.development:/app/website-preview/.env.development" \
+ --volume "$(PWD)/.env.local:/app/website-preview/.env.local" \
+ -e "REPO=$(REPO)" \
+ -e "PREVIEW_FROM_REPO=$(REPO)" \
+ -e "IS_CONTENT_PREVIEW=true" \
+ -e "LOCAL_CONTENT_DIR=$(LOCAL_CONTENT_DIR)" \
+ -e "CURRENT_GIT_BRANCH=$(CURRENT_GIT_BRANCH)" \
+ -e "PREVIEW_MODE=$(PREVIEW_MODE)"
+
+# Default: run this if working on the website locally to run in watch mode.
+.PHONY: website
+website:
+ @echo "==> Downloading latest Docker image..."
+ @$(DOCKER_CMD) pull $(DOCKER_IMAGE)
+ @echo "==> Starting website..."
+ @$(DOCKER_CMD) run $(DOCKER_RUN_FLAGS) $(DOCKER_IMAGE)
+
+# Use this if you have run `website/build-local` to use the locally built image.
+.PHONY: website/local
+website/local:
+ @echo "==> Starting website from local image..."
+ @$(DOCKER_CMD) run $(DOCKER_RUN_FLAGS) $(DOCKER_IMAGE_LOCAL)
+
+# Run this to generate a new local Docker image.
+.PHONY: website/build-local
+website/build-local:
+ @echo "==> Building local Docker image"
+ @$(DOCKER_CMD) build https://github.com/hashicorp/dev-portal.git\#main \
+ -t $(DOCKER_IMAGE_LOCAL)
+
diff --git a/v1.9.4/website/README.md b/v1.9.4/website/README.md
new file mode 100644
index 0000000..12d457c
--- /dev/null
+++ b/v1.9.4/website/README.md
@@ -0,0 +1,615 @@
+# Packer Documentation Website
+
+This subdirectory contains the content for the [Packer Website](https://packer.io/).
+
+<!--
+ This readme file contains several blocks of generated text, to make it easier to share common information
+ across documentation website readmes. To generate these blocks from their source, run `npm run generate:readme`
+
+ Any edits to the readme are welcome outside the clearly noted boundaries of the blocks. Alternately, a
+ block itself can be safely "forked" from the central implementation simply by removing the "BEGIN" and
+ "END" comments from around it.
+-->
+
+## Table of Contents
+
+- [Contributions](#contributions-welcome)
+- [Running the Site Locally](#running-the-site-locally)
+- [Editing Markdown Content](#editing-markdown-content)
+- [Editing Navigation Sidebars](#editing-navigation-sidebars)
+- [Changing the Release Version](#changing-the-release-version)
+- [Link Validation](#link-validation)
+- [Redirects](#redirects)
+- [Browser Support](#browser-support)
+- [Deployment](#deployment)
+
+<!-- BEGIN: contributions -->
+<!-- Generated text, do not edit directly -->
+
+## Contributions Welcome!
+
+If you find a typo or you feel like you can improve the HTML, CSS, or JavaScript, we welcome contributions. Feel free to open issues or pull requests like any normal GitHub project, and we'll merge it in 🚀
+
+<!-- END: contributions -->
+
+<!-- BEGIN: local-development -->
+<!-- Generated text, do not edit directly -->
+
+## Running the Site Locally
+
+The website can be run locally through node.js or [Docker](https://www.docker.com/get-started). If you choose to run through Docker, everything will be a little bit slower due to the additional overhead, so for frequent contributors it may be worth it to use node.
+
+> **Note:** If you are using a text editor that uses a "safe write" save style such as **vim** or **goland**, this can cause issues with the live reload in development. If you turn off safe write, this should solve the problem. In vim, this can be done by running `:set backupcopy=yes`. In goland, search the settings for "safe write" and turn that setting off.
+
+### With Docker
+
+Running the site locally is simple. Provided you have Docker installed, clone this repo, run `make`, and then visit `http://localhost:3000`.
+
+The Docker image is pre-built with all the website dependencies installed, which is what makes it so quick and simple, but also means if you need to change dependencies and test the changes within Docker, you'll need a new image. If this is something you need to do, you can run `make build-image` to generate a local Docker image with updated dependencies, then `make website-local` to use that image and preview.
+
+### With Node
+
+If your local development environment has a supported version (v16+) of [node installed](https://nodejs.org/en/) you can run:
+
+- `npm install`
+- `npm start`
+
+...and then visit `http://localhost:3000`.
+
+If you pull down new code from GitHub, you should run `npm install` again. Otherwise, there's no need to re-run `npm install` each time the site is run, you can just run `npm start` to get it going.
+
+<!-- END: local-development -->
+
+<!-- BEGIN: editing-markdown -->
+<!-- Generated text, do not edit directly -->
+
+## Editing Markdown Content
+
+Documentation content is written in [Markdown](https://www.markdownguide.org/cheat-sheet/) and you'll find all files listed under the `/content` directory.
+
+To create a new page with Markdown, create a file ending in `.mdx` in a `content/<subdirectory>`. The path in the content directory will be the URL route. For example, `content/docs/hello.mdx` will be served from the `/docs/hello` URL.
+
+> **Important**: Files and directories will only be rendered and published to the website if they are [included in sidebar data](#editing-navigation-sidebars). Any file not included in sidebar data will not be rendered or published.
+
+This file can be standard Markdown and also supports [YAML frontmatter](https://middlemanapp.com/basics/frontmatter/). YAML frontmatter is optional, there are defaults for all keys.
+
+```yaml
+---
+title: 'My Title'
+description: "A thorough, yet succinct description of the page's contents"
+---
+```
+
+The significant keys in the YAML frontmatter are:
+
+- `title` `(string)` - This is the title of the page that will be set in the HTML title.
+- `description` `(string)` - This is a description of the page that will be set in the HTML description.
+
+> ⚠️ If there is a need for a `/api/*` url on this website, the url will be changed to `/api-docs/*`, as the `api` folder is reserved by next.js.
+
+### Validating Content
+
+Content changes are automatically validated against a set of rules as part of the pull request process. If you want to run these checks locally to validate your content before committing your changes, you can run the following command:
+
+```
+npm run content-check
+```
+
+If the validation fails, actionable error messages will be displayed to help you address detected issues.
+
+### Creating New Pages
+
+There is currently a small bug with new page creation - if you create a new page and link it up via subnav data while the server is running, it will report an error saying the page was not found. This can be resolved by restarting the server.
+
+### Markdown Enhancements
+
+There are several custom Markdown plugins that are available by default that enhance [standard markdown](https://commonmark.org/) to fit our use cases. This set of plugins introduces a couple instances of custom syntax, and a couple specific pitfalls that are not present by default with markdown, detailed below:
+
+- > **Warning**: We are deprecating the current [paragraph alerts](https://github.com/hashicorp/remark-plugins/tree/master/plugins/paragraph-custom-alerts#paragraph-custom-alerts), in favor of the newer [MDX Inline Alert](#inline-alerts) components. The legacy paragraph alerts are represented by the symbols `~>`, `->`, `=>`, or `!>`.
+- If you see `@include '/some/path.mdx'`, this is a [markdown include](https://github.com/hashicorp/remark-plugins/tree/master/plugins/include-markdown#include-markdown-plugin). It's worth noting as well that all includes resolve from `website/content/partials` by default, and that changes to partials will not live-reload the website.
+- If you see `# Headline ((#slug))`, this is an example of an [anchor link alias](https://github.com/hashicorp/remark-plugins/tree/je.anchor-link-adjustments/plugins/anchor-links#anchor-link-aliases). It adds an extra permalink to a headline for compatibility and is removed from the output.
+- Due to [automatically generated permalinks](https://github.com/hashicorp/remark-plugins/tree/je.anchor-link-adjustments/plugins/anchor-links#anchor-links), any text changes to _headlines_ or _list items that begin with inline code_ can and will break existing permalinks. Be very cautious when changing either of these two text items.
+
+ Headlines are fairly self-explanatory, but here's an example of how to list items that begin with inline code look.
+
+ ```markdown
+ - this is a normal list item
+ - `this` is a list item that begins with inline code
+ ```
+
+ Its worth noting that _only the inline code at the beginning of the list item_ will cause problems if changed. So if you changed the above markup to...
+
+ ```markdown
+ - lsdhfhksdjf
+ - `this` jsdhfkdsjhkdsfjh
+ ```
+
+ ...while it perhaps would not be an improved user experience, no links would break because of it. The best approach is to **avoid changing headlines and inline code at the start of a list item**. If you must change one of these items, make sure to tag someone from the digital marketing development team on your pull request, they will help to ensure as much compatibility as possible.
+
+### Custom Components
+
+A number of custom [mdx components](https://mdxjs.com/) are available for use within any `.mdx` file. Each one is documented below:
+
+#### Inline Alerts
+
+There are custom MDX components available to author alert data. [See the full documentation here](https://developer.hashicorp.com/swingset/components/mdxinlinealert). They render as colored boxes to draw the user's attention to some type of aside.
+
+```mdx
+## Alert types
+
+### Tip
+
+<Tip>
+ To provide general information to the user regarding the current context or
+ relevant actions.
+</Tip>
+
+### Highlight
+
+<Highlight>
+ To provide general or promotional information to the user prominently.
+</Highlight>
+
+### Note
+
+<Note>
+ To help users avoid an issue. Provide guidance and actions if possible.
+</Note>
+
+### Warning
+
+<Warning>
+ To indicate critical issues that need immediate action or help users
+ understand something critical.
+</Warning>
+
+## Title override prop
+
+<Note title="Hashiconf 2027">To provide general information.</Note>
+```
+
+#### Tabs
+
+The `Tabs` component creates tabbed content of any type, but is often used for code examples given in different languages. Here's an example of how it looks from the Vagrant documentation website:
+
+![Tabs Component](https://p176.p0.n0.cdn.getcloudapp.com/items/WnubALZ4/Screen%20Recording%202020-06-11%20at%2006.03%20PM.gif?v=1de81ea720a8cc8ade83ca64fb0b9edd)
+
+> Please refer to the [Swingset](https://react-components.vercel.app/?component=Tabs) documentation for the latest examples and API reference.
+
+It can be used as such within a markdown file:
+
+````mdx
+Normal **markdown** content.
+
+<Tabs>
+<Tab heading="CLI command">
+ <!-- Intentionally skipped line.. -->
+```shell-session
+$ command ...
+```
+ <!-- Intentionally skipped line.. -->
+</Tab>
+<Tab heading="API call using cURL">
+
+```shell-session
+$ curl ...
+```
+
+</Tab>
+</Tabs>
+
+Continued normal markdown content
+````
+
+The intentionally skipped line is a limitation of the mdx parser which is being actively worked on. All tabs must have a heading, and there is no limit to the number of tabs, though it is recommended to go for a maximum of three or four.
+
+#### Enterprise Alert
+
+This component provides a standard way to call out functionality as being present only in the enterprise version of the software. It can be presented in two contexts, inline or standalone. Here's an example of standalone usage from the Consul docs website:
+
+![Enterprise Alert Component - Standalone](https://p176.p0.n0.cdn.getcloudapp.com/items/WnubALp8/Screen%20Shot%202020-06-11%20at%206.06.03%20PM.png?v=d1505b90bdcbde6ed664831a885ea5fb)
+
+The standalone component can be used as such in markdown files:
+
+```mdx
+# Page Headline
+
+<EnterpriseAlert />
+
+Continued markdown content...
+```
+
+It can also receive custom text contents if you need to change the messaging but wish to retain the style. This will replace the text `This feature is available in all versions of Consul Enterprise.` with whatever you add. For example:
+
+```mdx
+# Page Headline
+
+<EnterpriseAlert>
+ My custom text here, and <a href="#">a link</a>!
+</EnterpriseAlert>
+
+Continued markdown content...
+```
+
+It's important to note that once you are adding custom content, it must be html and can not be markdown, as demonstrated above with the link.
+
+Now let's look at inline usage, here's an example:
+
+![Enterprise Alert Component - Inline](https://p176.p0.n0.cdn.getcloudapp.com/items/L1upYLEJ/Screen%20Shot%202020-06-11%20at%206.07.50%20PM.png?v=013ba439263de8292befbc851d31dd78)
+
+And here's how it could be used in your Markdown document:
+
+```mdx
+### Some Enterprise Feature <EnterpriseAlert inline />
+
+Continued markdown content...
+```
+
+It's also worth noting that this component will automatically adjust to the correct product colors depending on the context.
+
+#### Other Components
+
+Other custom components can be made available on a per-site basis, the above are the standards. If you have questions about custom components that are not documented here, or have a request for a new custom component, please reach out to @hashicorp/digital-marketing.
+
+### Syntax Highlighting
+
+When using fenced code blocks, the recommendation is to tag the code block with a language so that it can be syntax highlighted. For example:
+
+````
+```
+// BAD: Code block with no language tag
+```
+
+```javascript
+// GOOD: Code block with a language tag
+```
+````
+
+Check out the [supported languages list](https://prismjs.com/#supported-languages) for the syntax highlighter we use if you want to double-check the language name.
+
+It is also worth noting specifically that if you are using a code block that is an example of a terminal command, the correct language tag is `shell-session`. For example:
+
+🚫**BAD**: Using `shell`, `sh`, `bash`, or `plaintext` to represent a terminal command
+
+````
+```shell
+$ terraform apply
+```
+````
+
+✅**GOOD**: Using `shell-session` to represent a terminal command
+
+````
+```shell-session
+$ terraform apply
+```
+````
+
+<!-- END: editing-markdown -->
+
+<!-- BEGIN: editing-docs-sidebars -->
+<!-- Generated text, do not edit directly -->
+
+## Editing Navigation Sidebars
+
+The structure of the sidebars are controlled by files in the [`/data` directory](data). For example, [data/docs-nav-data.json](data/docs-nav-data.json) controls the **docs** sidebar. Within the `data` folder, any file with `-nav-data` after it controls the navigation for the given section.
+
+The sidebar uses a simple recursive data structure to represent _files_ and _directories_. The sidebar is meant to reflect the structure of the docs within the filesystem while also allowing custom ordering. Let's look at an example. First, here's our example folder structure:
+
+```text
+.
+├── docs
+│ └── directory
+│ ├── index.mdx
+│ ├── file.mdx
+│ ├── another-file.mdx
+│ └── nested-directory
+│ ├── index.mdx
+│ └── nested-file.mdx
+```
+
+Here's how this folder structure could be represented as a sidebar navigation, in this example it would be the file `website/data/docs-nav-data.json`:
+
+```json
+[
+ {
+ "title": "Directory",
+ "routes": [
+ {
+ "title": "Overview",
+ "path": "directory"
+ },
+ {
+ "title": "File",
+ "path": "directory/file"
+ },
+ {
+ "title": "Another File",
+ "path": "directory/another-file"
+ },
+ {
+ "title": "Nested Directory",
+ "routes": [
+ {
+ "title": "Overview",
+ "path": "directory/nested-directory"
+ },
+ {
+ "title": "Nested File",
+ "path": "directory/nested-directory/nested-file"
+ }
+ ]
+ }
+ ]
+ }
+]
+```
+
+A couple more important notes:
+
+- Within this data structure, ordering is flexible, but hierarchy is not. The structure of the sidebar must correspond to the structure of the content directory. So while you could put `file` and `another-file` in any order in the sidebar, or even leave one or both of them out, you could not decide to un-nest the `nested-directory` object without also un-nesting it in the filesystem.
+- The `title` property on each node in the `nav-data` tree is the human-readable name in the navigation.
+- The `path` property on each leaf node in the `nav-data` tree is the URL path where the `.mdx` document will be rendered, and the
+- Note that "index" files must be explicitly added. These will be automatically resolved, so the `path` value should be, as above, `directory` rather than `directory/index`. A common convention is to set the `title` of an "index" node to be `"Overview"`.
+
+Below we will discuss a couple of more unusual but still helpful patterns.
+
+### Index-less Categories
+
+Sometimes you may want to include a category but not have a need for an index page for the category. This can be accomplished, but as with other branch and leaf nodes, a human-readable `title` needs to be set manually. Here's an example of how an index-less category might look:
+
+```text
+.
+├── docs
+│ └── indexless-category
+│ └── file.mdx
+```
+
+```json
+// website/data/docs-nav-data.json
+[
+ {
+ "title": "Indexless Category",
+ "routes": [
+ {
+ "title": "File",
+ "path": "indexless-category/file"
+ }
+ ]
+ }
+]
+```
+
+### Custom or External Links
+
+Sometimes you may have a need to include a link that is not directly to a file within the docs hierarchy. This can also be supported using a different pattern. For example:
+
+```json
+[
+ {
+ "name": "Directory",
+ "routes": [
+ {
+ "title": "File",
+ "path": "directory/file"
+ },
+ {
+ "title": "Another File",
+ "path": "directory/another-file"
+ },
+ {
+ "title": "Tao of HashiCorp",
+ "href": "https://www.hashicorp.com/tao-of-hashicorp"
+ }
+ ]
+ }
+]
+```
+
+If the link provided in the `href` property is external, it will display a small icon indicating this. If it's internal, it will appear the same way as any other direct file link.
+
+<!-- END: editing-docs-sidebars -->
+
+### Plugin Docs
+
+Plugin documentation may be located within the `packer` repository, or split out into separate `packer-plugin-` repositories. For plugin docs within the `packer` repository, the process for authoring files and managing sidebar data is identical to the process for other documentation.
+
+For plugins in separate repositories, additional configuration is required.
+
+#### Setting up remote plugin docs
+
+Some setup is required to include docs from remote plugin repositories on the [packer.io/docs](https://www.packer.io/docs) site.
+
+1. The plugin repository needs to include a `docs.zip` asset in its release
+2. The `packer` repository must have a corresponding entry in `website/data/docs-remote-plugins.json` which points to the plugin repository.
+
+The `docs.zip` release asset is expected to be generated as part of the standard release process for `packer-plugin-*` repositories. Additional details on this process can be found in [the `packer-plugin-scaffolding` `README`](https://github.com/hashicorp/packer-plugin-scaffolding#registering-documentation-on-packerio).
+
+The `docs-remote-plugins.json` file contains an array of entries. Each entry points to a plugin repository. The `{ title, path, repo, version }` properties are required for each entry.
+
+```json5
+[
+ {
+ // ALL FIELDS ARE REQUIRED.
+ // "title" sets the human-readable title shown in navigation
+ title: 'Scaffolding',
+ // "path" sets the URL subpath under the component URL (eg `docs/builders`)
+ path: 'scaffolding',
+ // "repo" points to the plugin repo, in the format "organization/repo-name"
+ // if the organization == hashicorp, the plugin docs will be labelled "official".
+ // for all other organizations or users, plugin docs will be labelled "community".
+ repo: 'hashicorp/packer-plugin-scaffolding',
+ // "version" is used to fetch "docs.zip" from the matching tagged release.
+ // version: "latest" is permitted, but please be aware that it
+ // may fetch incompatible or unintended versions of plugin docs.
+ // if version is NOT "latest", and if "docs.zip" is unavailable, then
+ // we fall back to fetching docs from the source "{version}.zip"
+ version: 'v0.0.5',
+ },
+]
+```
+
+#### Updating remote plugin docs
+
+Documentation from plugin repositories is fetched and rendered every time the Packer website builds. So, to update plugin documentation on the live site:
+
+1. In the plugin repository, publish a new release that includes a `docs.zip` release asset
+2. In the `packer` repository, update `website/data/docs-remote-plugins.json` to ensure the corresponding entry points to the correct release `version` (which should correspond to the release's tag name). This may not be necessary if the `version` is set to `"latest"`.
+3. Rebuild the website. This will happen automatically on commits to `stable-website`. In exceptional cases, the site can also be [manually re-deployed through Vercel](https://vercel.com/hashicorp/packer).
+
+<!-- BEGIN: releases -->
+<!-- Generated text, do not edit directly -->
+
+## Changing the Release Version
+
+To change the version displayed for download on the website, head over to `data/version.js` and change the number there. It's important to note that the version number must match a version that has been released and is live on `releases.hashicorp.com` -- if it does not, the website will be unable to fetch links to the binaries and will not compile. So this version number should be changed _only after a release_.
+
+### Displaying a Prerelease
+
+If there is a prerelease of any type that should be displayed on the downloads page, this can be done by editing `pages/downloads/index.jsx`. By default, the download component might look something like this:
+
+```jsx
+<ProductDownloader
+ product="<Product>"
+ version={VERSION}
+ downloads={downloadData}
+ community="/resources"
+/>
+```
+
+To add a prerelease, an extra `prerelease` property can be added to the component as such:
+
+```jsx
+<ProductDownloader
+ product="<Product>"
+ version={VERSION}
+ downloads={downloadData}
+ community="/resources"
+ prerelease={{
+ type: 'release candidate', // the type of prerelease: beta, release candidate, etc.
+ name: 'v1.0.0', // the name displayed in text on the website
+ version: '1.0.0-rc1', // the actual version tag that was pushed to releases.hashicorp.com
+ }}
+/>
+```
+
+This configuration would display something like the following text on the website, emphasis added to the configurable parameters:
+
+```
+A {{ release candidate }} for <Product> {{ v1.0.0 }} is available! The release can be <a href='https://releases.hashicorp.com/<product>/{{ 1.0.0-rc1 }}'>downloaded here</a>.
+```
+
+You may customize the parameters in any way you'd like. To remove a prerelease from the website, simply delete the `prerelease` parameter from the above component.
+
+<!-- END: releases -->
+
+<!--
+
+NOTE: The "Redirects" section is forked from redirects.
+
+There are minor changes related to sidebar navigation format changes.
+
+We plan on rolling these changes back into our "readme partials" source once all docs sites
+have been transitioned to the JSON navigation format. See MKTG_032 for details:
+
+https://docs.google.com/document/d/1kYvbyd6njHFSscoE1dtDNHQ3U8IzaMdcjOS0jg87rHg/
+
+-->
+
+## Link Validation
+
+The Packer GitHub repository is configured to run a [Markdown Link Check](https://github.com/gaurav-nelson/github-action-markdown-link-check#github-action---markdown-link-check-%EF%B8%8F) on a nightly basis to check for potential broken links within the Packer documentation. All checks on master will be executed using the BASE_URL set to https://packer.io/.
+
+There is also a GitHub action that will check any modified `website/content/**/*.mdx` files on new pull-requests. The link checker action for pull-requests will only run when there is a new Vercel deployment; checks will be executed against the Vercel deployment URL. If no deployment is made the check will run but will timeout after 3 minutes since it needs a valid Vercel deployment URL.
+
+The master configuration file for the markdown-link-checker is called `mlc_config.json` and is located under the project's root directory.
+The configuration helps with relative links in the documentation that will be valid once deployed, and configures a few ignored URLs which are valid but may not return a valid 200 HTTP response code due to permissions or DDoS protection settings on the domain.
+
+**Potential False Negatives**
+The link checker will prepend the BASEURL `https://packer.io/` to any relative links found within the documentation, which can be an issue when adding new `/docs` or `/guides` documents as the pages have not been deployed. To help mitigate this issue check the site preview to ensure newly added documentation pages work as expected.
+
+## Redirects
+
+This website structures URLs based on the filesystem layout. This means that if a file is moved, removed, or a folder is re-organized, links will break. If a path change is necessary, it can be mitigated using redirects.
+
+To add a redirect, head over to the `_redirects` file - the format is fairly simple. On the left is the current path, and on the right is the path that should be redirected to. It's important to note that if there are links to a `.html` version of a page, that must also be explicitly redirected. For example:
+
+```
+/foo /bar 301!
+/foo.html /bar 301!
+```
+
+This redirect rule will send all incoming links to `/foo` and `/foo.html` to `/bar`. For more details on the redirects file format, [check out the docs on netlify](https://docs.netlify.com/routing/redirects/rewrites-proxies). Note that it is critical that `301!` is added to every one-to-one redirect - if it is left off the redirect may not work.
+
+There are a couple important caveats with redirects. First, redirects are applied at the hosting layer, and therefore will not work by default in local dev mode. To test in local dev mode, you can use [`netlify dev`](https://www.netlify.com/products/dev/), or just push a commit and check using the deploy preview.
+
+Second, redirects do not apply to client-side navigation. By default, all links in the navigation and docs sidebar will navigate purely on the client side, which makes navigation through the docs significantly faster, especially for those with low-end devices and/or weak internet connections. In the future, we plan to convert all internal links within docs pages to behave this way as well. This means that if there is a link on this website to a given piece of content that has changed locations in some way, we need to also _directly change existing links to the content_. This way, if a user clicks a link that navigates on the client side, or if they hit the url directly and the page renders from the server side, either one will work perfectly.
+
+Let's look at an example. Say you have a page called `/docs/foo` which needs to be moved to `/docs/nested/foo`. Additionally, this is a page that has been around for a while and we know there are links into `/docs/foo.html` left over from our previous website structure. First, we move the page, then adjust the docs sidenav, in `data/docs-nav-data.json`. Find the category the page is in, and move it into the appropriate subcategory. Next, we add to `_redirects` as such:
+
+```
+/foo /nested/foo 301!
+/foo.html /nested/foo 301!
+```
+
+Finally, we run a global search for internal links to `/foo`, and make sure to adjust them to be `/nested/foo` - this is to ensure that client-side navigation still works correctly. _Adding a redirect alone is not enough_.
+
+One more example - let's say that content is being moved to an external website. A common example is guides moving to `learn.hashicorp.com`. In this case, we take all the same steps, except that we need to make a different type of change to the `docs-nav-data` file. If previously the structure looked like:
+
+```json
+[
+ {
+ "name": "Docs",
+ "routes": [
+ {
+ "title": "Foo",
+ "path": "docs/foo"
+ }
+ ]
+ }
+]
+```
+
+If we no longer want the link to be in the side nav, we can simply remove it. If we do still want the link in the side nav, but pointing to an external destination, we need to slightly change the structure as such:
+
+```json
+[
+ {
+ "name": "Docs",
+ "routes": [
+ {
+ "title": "Foo",
+ "href": "https://learn.hashicorp.com/<product>/foo"
+ }
+ ]
+ }
+]
+```
+
+As the majority of items in the side nav are internal links, the structure makes it as easy as possible to represent these links. This alternate syntax is the most concise manner than an external link can be represented. External links can be used anywhere within the docs sidenav.
+
+It's also worth noting that it is possible to do glob-based redirects, for example matching `/docs/*`, and you may see this pattern in the `_redirects` file. This type of redirect is much higher risk and the behavior is a bit more nuanced, so if you need to add a glob redirect, please reach out to the website maintainers and ask about it first.
+
+<!-- END: redirects -->
+
+<!-- BEGIN: browser-support -->
+<!-- Generated text, do not edit directly -->
+
+## Browser Support
+
+We support the following browsers targeting roughly the versions specified.
+
+| ![Chrome](https://raw.githubusercontent.com/alrra/browser-logos/main/src/chrome/chrome.svg) | ![Edge](https://raw.githubusercontent.com/alrra/browser-logos/main/src/edge/edge.svg) | ![Opera](https://raw.githubusercontent.com/alrra/browser-logos/main/src/opera/opera.svg) | ![Firefox](https://raw.githubusercontent.com/alrra/browser-logos/main/src/firefox/firefox.svg) | ![Safari](https://raw.githubusercontent.com/alrra/browser-logos/main/src/safari/safari.svg) |
+| ------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------- | ---------------------------------------------------------------------------------------- | ---------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------- |
+| **Latest** | **Latest** | **Latest** | **Latest** | **Latest** |
+
+<!-- END: browser-support -->
+
+<!-- BEGIN: deployment -->
+<!-- Generated text, do not edit directly -->
+
+## Deployment
+
+This website is hosted on Vercel and configured to automatically deploy anytime you push code to the `stable-website` branch. Any time a pull request is submitted that changes files within the `website` folder, a deployment preview will appear in the GitHub checks which can be used to validate the way docs changes will look live. Deployments from `stable-website` will look and behave the same way as deployment previews.
+
+<!-- END: deployment -->
diff --git a/v1.9.4/website/content/community-plugins.mdx b/v1.9.4/website/content/community-plugins.mdx
new file mode 100644
index 0000000..fa245b7
--- /dev/null
+++ b/v1.9.4/website/content/community-plugins.mdx
@@ -0,0 +1,41 @@
+---
+page_title: Community vs HashiCorp Maintained Plugins
+description: Packer maintains these core plugins.
+---
+
+# HashiCorp Maintained Plugins
+
+The following plugins (i.e. Builders, Provisioners, and Post-Processors) are
+maintained by HashiCorp. Any plugins not on this list are maintained by the
+community, and not actively contributed to by HashiCorp, although they are
+still distributed with Packer. If you are interested in seeing features or
+bugfixes to these plugins, please consider making a pull request, or asking the
+HashiCorp maintainers for advice on how to get started contributing.
+
+## Builders
+
+- Amazon EC2
+- Azure
+- Docker
+- Google Cloud
+- VMware
+- VirtualBox
+
+## Provisioners
+
+- File
+- InSpec
+- PowerShell
+- Shell
+- Windows Restart
+- Windows Shell
+
+## Post-Processors
+
+- Amazon Import
+- Artifice
+- Docker
+- Local Shell
+- Manifest
+- Vagrant
+- Vagrant Cloud
diff --git a/v1.9.4/website/content/docs/builders/community-supported.mdx b/v1.9.4/website/content/docs/builders/community-supported.mdx
new file mode 100644
index 0000000..6ce89fb
--- /dev/null
+++ b/v1.9.4/website/content/docs/builders/community-supported.mdx
@@ -0,0 +1,14 @@
+---
+description: |
+ Community-maintained builders are not part of the core Packer binary, but
+ can run alongside Packer with minimal extra effort.
+page_title: Community - Builders
+---
+
+# Community Builders
+
+The following builders are developed and maintained by various members of the
+Packer community, not by HashiCorp. For more information on how to use community
+builders, see our docs on [extending Packer](/packer/docs/plugins/creation).
+
+@include 'builders/community_builders.mdx'
diff --git a/v1.9.4/website/content/docs/builders/custom.mdx b/v1.9.4/website/content/docs/builders/custom.mdx
new file mode 100644
index 0000000..4445cf0
--- /dev/null
+++ b/v1.9.4/website/content/docs/builders/custom.mdx
@@ -0,0 +1,15 @@
+---
+description: |
+ Packer is extensible, allowing you to write new builders without having to
+ modify the core source code of Packer itself. Documentation for creating new
+ builders is covered in the custom builders page of the Packer plugin section.
+page_title: Custom - Builders
+---
+
+# Custom Builder
+
+Packer is extensible, allowing you to write new builders without having to
+modify the core source code of Packer itself. Documentation for creating new
+builders is covered in the [custom
+builders](/packer/docs/plugins/creation/custom-builders) page of the Packer plugin
+section.
diff --git a/v1.9.4/website/content/docs/builders/file.mdx b/v1.9.4/website/content/docs/builders/file.mdx
new file mode 100644
index 0000000..55f73d9
--- /dev/null
+++ b/v1.9.4/website/content/docs/builders/file.mdx
@@ -0,0 +1,76 @@
+---
+description: |
+ The file Packer builder is not really a builder, it just creates an artifact
+ from a file. It can be used to debug post-processors without incurring high
+ wait times.
+page_title: File - Builders
+---
+
+<BadgesHeader>
+ <PluginBadge type="official" />
+</BadgesHeader>
+
+# File Builder
+
+Type: `file`
+Artifact BuilderId: `packer.file`
+
+The `file` Packer builder is not really a builder, it just creates an artifact
+from a file. It can be used to debug post-processors without incurring high
+wait times.
+
+## Basic Example
+
+Below is a fully functioning example. It create a file at `target` with the
+specified `content`.
+
+<Tabs>
+<Tab heading="JSON">
+
+```json
+{
+ "type": "file",
+ "content": "Lorem ipsum dolor sit amet",
+ "target": "dummy_artifact"
+}
+```
+
+</Tab>
+<Tab heading="HCL2">
+
+```hcl
+source "file" "basic-example" {
+ content = "Lorem ipsum dolor sit amet"
+ target = "dummy_artifact"
+}
+
+build {
+ sources = ["sources.file.basic-example"]
+}
+```
+
+</Tab>
+</Tabs>
+
+## Configuration Reference
+
+Configuration options are organized below into two categories: required and
+optional. Within each category, the available options are alphabetized and
+described.
+
+Any [communicator](/packer/docs/templates/legacy_json_templates/communicator) defined is ignored.
+
+### Required:
+
+- `target` (string) - The path for the artifact file that will be created. If
+ the path contains directories that don't exist, Packer will create them, too.
+
+### Optional:
+
+You can only define one of `source` or `content`. If none of them is defined
+the artifact will be empty.
+
+- `source` (string) - The path for a file which will be copied as the
+ artifact.
+
+- `content` (string) - The content that will be put into the artifact.
diff --git a/v1.9.4/website/content/docs/builders/index.mdx b/v1.9.4/website/content/docs/builders/index.mdx
new file mode 100644
index 0000000..f440105
--- /dev/null
+++ b/v1.9.4/website/content/docs/builders/index.mdx
@@ -0,0 +1,22 @@
+---
+description: |
+ Builders are responsible for creating machines and generating images from them
+ for various platforms.
+page_title: Builders
+---
+
+# Builders
+
+Builders create machines and generate images from those machines for various platforms. Packer also has some builders that perform helper tasks, like running provisioners.
+
+Packer has the following types of builders:
+
+- [Plugin](/packer/plugins): Each plugin has its own associated set of builders. For example, there are separate builders for EC2, VMware, VirtualBox, etc.
+- [File](/packer/docs/builders/file): The `file` builder creates an artifact from a file.
+- [Null](/packer/docs/builders/null): The `null` builder sets up an SSH connection and runs the provisioners.
+- [Custom](/packer/docs/plugins/creation/custom-builders): You can write new builders for new or existing platforms.
+- [Community-Supported](/packer/docs/builders/community-supported): The Packer community develops and maintains builders for several additional platforms.
+
+Refer to the [`source`](/packer/docs/templates/hcl_templates/blocks/source) block documentation to learn more about configuring builders in the Packer templating language.
+
+
diff --git a/v1.9.4/website/content/docs/builders/null.mdx b/v1.9.4/website/content/docs/builders/null.mdx
new file mode 100644
index 0000000..2098fec
--- /dev/null
+++ b/v1.9.4/website/content/docs/builders/null.mdx
@@ -0,0 +1,61 @@
+---
+description: |
+ The null Packer builder is not really a builder, it just sets up an SSH
+ connection and runs the provisioners. It can be used to debug provisioners
+ without incurring high wait times. It does not create any kind of image or
+ artifact.
+page_title: Null - Builders
+---
+
+<BadgesHeader>
+ <PluginBadge type="official" />
+</BadgesHeader>
+
+# Null Builder
+
+Type: `null`
+
+The `null` Packer builder is not really a builder, it just sets up an SSH
+connection and runs the provisioners. It can be used to debug provisioners
+without incurring high wait times. It does not create any kind of image or
+artifact.
+
+## Basic Example
+
+Below is a fully functioning example. It doesn't do anything useful, since no
+provisioners are defined, but it will connect to the specified host via ssh.
+
+<Tabs>
+<Tab heading="JSON">
+
+```json
+{
+ "type": "null",
+ "ssh_host": "127.0.0.1",
+ "ssh_username": "foo",
+ "ssh_password": "bar"
+}
+```
+
+</Tab>
+<Tab heading="HCL2">
+
+```hcl
+source "null" "basic-example" {
+ ssh_host = "127.0.0.1"
+ ssh_username = "foo"
+ ssh_password = "bar"
+}
+
+build {
+ sources = ["sources.null.basic-example"]
+}
+```
+
+</Tab>
+</Tabs>
+
+## Configuration Reference
+
+The null builder has no configuration parameters other than the
+[communicator](/packer/docs/templates/legacy_json_templates/communicator) settings.
diff --git a/v1.9.4/website/content/docs/commands/build.mdx b/v1.9.4/website/content/docs/commands/build.mdx
new file mode 100644
index 0000000..60c2f7c
--- /dev/null
+++ b/v1.9.4/website/content/docs/commands/build.mdx
@@ -0,0 +1,68 @@
+---
+description: |
+ The `packer build` command takes a template and runs all the builds within it
+ in order to generate a set of artifacts. The various builds specified within a
+ template are executed in parallel, unless otherwise specified. And the
+ artifacts that are created will be outputted at the end of the build.
+page_title: packer build - Commands
+---
+
+# `build` Command
+
+The `packer build` command takes a template and runs all the builds within it
+in order to generate a set of artifacts. The various builds specified within a
+template are executed in parallel, unless otherwise specified. And the
+artifacts that are created will be outputted at the end of the build.
+
+## Options
+
+- `-color=false` - Disables colorized output. Enabled by default.
+
+- `-debug` - Disables parallelization and enables debug mode. Debug mode
+ flags the builders that they should output debugging information. The exact
+ behavior of debug mode is left to the builder. In general, builders usually
+ will stop between each step, waiting for keyboard input before continuing.
+ This will allow the user to inspect state and so on.
+
+`@include 'commands/except.mdx'`
+
+- `-force` - Forces a builder to run when artifacts from a previous build
+ prevent a build from running. The exact behavior of a forced build is left
+ to the builder. In general, a builder supporting the forced build will
+ remove the artifacts from the previous build. This will allow the user to
+ repeat a build without having to manually clean these artifacts beforehand.
+
+- `-on-error=cleanup` (default), `-on-error=abort`, `-on-error=ask`, `-on-error=run-cleanup-provisioner` -
+ Selects what to do when the build fails during provisioning. Please note that
+ this only affects the build during the provisioner run, not during the
+ post-processor run, because it is related to whether or not to keep the
+ instance running and related artifacts like generated SSH keys on the system
+ when a provisioner fails.
+
+ - `cleanup` cleans up after the previous steps, deleting temporary files and virtual machines.
+ - `abort` exits without any cleanup, which might require the next build to use `-force`.
+ - `ask` presents a prompt and waits for you to decide to clean up, abort, or retry
+ the failed step.
+ - `run-cleanup-provisioner` aborts and exits without any cleanup besides
+ the [error-cleanup-provisioner](/packer/docs/templates/legacy_json_templates/provisioners#on-error-provisioner) if one is defined.
+
+`@include 'commands/only.mdx'`
+
+- `-parallel-builds=N` - Limit the number of builds to run in parallel, 0
+ means no limit (defaults to 0).
+
+- `-timestamp-ui` - Enable prefixing of each ui output with an RFC3339
+ timestamp.
+
+- `-var` - Set a variable in your Packer template. This option can be used
+ multiple times. This is useful for setting version numbers for your build.
+
+- `-var-file` - Set template variables from a file.
+
+- `-warn-on-undeclared-var` - Setting this flag will yield a warning for each assignment within
+ a variable definitions file (*.pkrvars.hcl | *.pkrvars.json) that does not have an accompanying
+ variable block. This can occur when using a var-file that contains a large amount of unused variables
+ for a given HCL2 template. For HCL2 template builds defining a value for a variable in a var-file is
+ not enough on its own for Packer to function, as there also needs to be a variable block definition in
+ the template files `pkr.hcl` for the variable. By default `packer build` will not warn when a var-file
+ contains one or more undeclared variables.
diff --git a/v1.9.4/website/content/docs/commands/console.mdx b/v1.9.4/website/content/docs/commands/console.mdx
new file mode 100644
index 0000000..f61a7a1
--- /dev/null
+++ b/v1.9.4/website/content/docs/commands/console.mdx
@@ -0,0 +1,156 @@
+---
+description: |
+ The `packer console` command allows you to experiment with Packer variable
+ interpolations.
+page_title: packer console - Commands
+---
+
+# `console` Command
+
+The `packer console` command allows you to experiment with Packer variable
+interpolations. You may access variables in the Packer config you called the
+console with, or provide variables when you call console using the -var or
+-var-file command line options.
+
+~> **Note:** `console` is available from version 1.4.2 and above.
+
+~> **Note:** For HCL2 `console` is available from version 1.6.0 and above, use
+`packer console --config-type=hcl2` to try it without a config file. Go
+templating ( or `{{..}}` calls ) will not work in HCL2 mode.
+
+Type in the interpolation to test and hit `<enter>` to see the result.
+
+To exit the console, type "exit" and hit `<enter>`, or use Control-C.
+
+```shell-session
+$ packer console my_template.json
+```
+
+The full list of options that the console command will accept is visible in the
+help output, which can be seen via `packer console -h`.
+
+## Options
+
+- `-var` - Set a variable in your Packer template. This option can be used
+ multiple times. This is useful for setting version numbers for your build.
+ example: `-var "myvar=asdf"`
+
+- `-var-file` - Set template variables from a file.
+ example: `-var-file myvars.json`
+
+## REPL commands
+
+- `help` - displays help text for Packer console.
+
+- `exit` - exits the console
+
+- `variables` - prints a list of all variables read into the console from the
+ `-var` option, `-var-files` option, and template.
+
+## Usage Examples - repl session ( JSON )
+
+Let's say you launch a console using a Packer template `example_template.json`:
+
+```shell-session
+$ packer console example_template.json
+```
+
+You'll be dropped into a prompt that allows you to enter template functions and
+see how they're evaluated; for example, if the variable `myvar` is defined in
+your example_template's variable section:
+
+```json
+"variables":{
+ "myvar": "asdfasdf"
+},
+...
+```
+
+and you enter `` {{user `myvar`}} `` in the Packer console, you'll see the value of
+myvar:
+
+```shell-session
+> {{user `myvar`}}
+asdfasdf
+```
+
+From there you can test more complicated interpolations:
+
+```shell-session
+> {{user `myvar`}}-{{timestamp}}
+asdfasdf-1559854396
+```
+
+And when you're done using the console, just type "exit" or CTRL-C
+
+```shell-session
+> exit
+$
+```
+
+If you'd like to provide a variable or variable files, you'd do this:
+
+```shell-session
+$ packer console -var "myvar=fdsafdsa" -var-file myvars.json example_template.json
+```
+
+If you don't have specific variables or var files you want to test, and just
+want to experiment with a particular template engine, you can do so by simply
+calling `packer console` without a template file.
+
+## Usage Examples - piped commands ( JSON )
+
+If you'd like to just see a specific single interpolation without launching
+the REPL, you can do so by echoing and piping the string into the console
+command:
+
+```shell-session
+$ echo {{timestamp}} | packer console
+1559855090
+```
+
+## Usage Examples - repl session ( HCL2 )
+
+~> **Note:** For HCL2 `console` is available from version 1.6.0 and above, use
+`packer console --config-type=hcl2` to try it without a config file. Go
+templating ( or `{{..}}` calls ) will not work in HCL2 mode.
+
+Without a config file, `packer console` can be used to experiment with the
+expression syntax and [built-in functions](/packer/docs/templates/hcl_templates/functions).
+
+### Starting
+
+To start a session on a folder containing HCL2 config files, run:
+
+```shell-session
+packer console folder/
+```
+
+Because `folder/` is a folder Packer will start in HCL2 mode, you can also
+directly pass an HCL2 formatted config file:
+
+```shell-session
+packer console file.pkr.hcl
+```
+
+Because the file is suffixed with `.pkr.hcl` Packer will start in HCL2 mode.
+
+When you just want to play around without a config file you can set the
+`--config-type=hcl2` option and Packer will start in HCL2 mode:
+
+```shell-session
+packer console --config-type=hcl2
+```
+
+### Scripting
+
+The `packer console` command can be used in non-interactive scripts by piping
+newline-separated commands to it. Only the output from the final command is
+printed unless an error occurs earlier.
+
+For example:
+
+```shell-session
+$ echo "1 + 5" | packer console
+6
+```
diff --git a/v1.9.4/website/content/docs/commands/fix.mdx b/v1.9.4/website/content/docs/commands/fix.mdx
new file mode 100644
index 0000000..a888660
--- /dev/null
+++ b/v1.9.4/website/content/docs/commands/fix.mdx
@@ -0,0 +1,42 @@
+---
+description: |
+ The `packer fix` command takes a template and finds backwards incompatible
+ parts of it and brings it up to date so it can be used with the latest version
+ of Packer. After you update to a new Packer release, you should run the fix
+ command to make sure your templates work with the new release.
+page_title: packer fix - Commands
+---
+
+# `fix` Command
+
+-> **Note** This command is not available on HCL2 templates yet, it will be added when we need to introduce the first 'fix'.
+
+The `packer fix` command takes a template and finds backwards incompatible
+parts of it and brings it up to date so it can be used with the latest version
+of Packer. After you update to a new Packer release, you should run the fix
+command to make sure your templates work with the new release.
+
+The fix command will output the changed template to standard out, so you should
+redirect standard out using standard OS-specific techniques if you want to save it
+to a file. For example, on Linux systems, you may want to do this:
+
+```shell-session
+$ packer fix old.json > new.json
+```
+
+If fixing fails for any reason, the fix command will exit with a non-zero exit
+status. Error messages appear on standard error, so if you're redirecting
+output, you'll still see error messages.
+
+-> **Even when Packer fix doesn't do anything** to the template, the
+template will be outputted to standard out. Things such as configuration key
+ordering and indentation may be changed. The output format however, is
+pretty-printed for human readability.
+
+The full list of fixes that the fix command performs is visible in the help
+output, which can be seen via `packer fix -h`.
+
+## Options
+
+- `-validate=false` - Disables validation of the fixed template. True by
+ default.
diff --git a/v1.9.4/website/content/docs/commands/fmt.mdx b/v1.9.4/website/content/docs/commands/fmt.mdx
new file mode 100644
index 0000000..be66e3e
--- /dev/null
+++ b/v1.9.4/website/content/docs/commands/fmt.mdx
@@ -0,0 +1,55 @@
+---
+description: |
+ The `packer fmt` Packer command is used to format HCL2
+ configuration files to a canonical format and style.
+page_title: packer fmt - Commands
+---
+
+# `fmt` Command
+
+The `packer fmt` Packer command is used to format HCL2 configuration files to
+a canonical format and style. JSON files (.json) are not modified. This command
+applies a subset of HCL language style conventions, along with other minor
+adjustments for readability.
+
+`packer fmt` will display the name of the configuration file(s) that need formatting,
+and write any formatted changes back to the original configuration file(s).
+
+Example usage:
+
+Check if configuration file(s) need to be formatted, but don't write the changes.
+
+```shell-session
+$ packer fmt -check .
+my-template.pkr.hcl
+
+```
+
+Format a configuration file, writing the changes back to the original file.
+
+```shell-session
+$ packer fmt my-template.pkr.hcl
+my-template.pkr.hcl
+
+```
+
+Format a configuration file, reading from stdin and writing to stdout.
+
+```shell-session
+$ packer fmt -
+
+// You can use pipes to combine this feature with other command line options
+$ cat my-template.pkr.hcl | packer fmt -
+```
+
+## Options
+
+- `-check` - Checks if the input is formatted. Exit status will be 0 if all
+ input is properly formatted and non-zero otherwise.
+
+- `-diff` - Display diffs of any formatting change
+
+- `-write=false` - Don't write formatting changes to source files
+ (always disabled if using -check)
+
+- `-` - read formatting changes from stdin and write them to stdout.
\ No newline at end of file
diff --git a/v1.9.4/website/content/docs/commands/hcl2_upgrade.mdx b/v1.9.4/website/content/docs/commands/hcl2_upgrade.mdx
new file mode 100644
index 0000000..baaee63
--- /dev/null
+++ b/v1.9.4/website/content/docs/commands/hcl2_upgrade.mdx
@@ -0,0 +1,139 @@
+---
+description: |
+ The `packer hcl2_upgrade` Packer command is used to transpile a JSON
+ configuration template to its formatted HCL2 counterpart. The command will
+ return a zero exit status on success, and a non-zero exit status on failure.
+page_title: packer hcl2_upgrade - Commands
+---
+
+-> **Note:** This command is Beta, and currently being improved upon; do not
+hesitate [opening a new
+issue](https://github.com/hashicorp/packer/issues/new/choose) if you find
+something wrong.
+
+# `hcl2_upgrade` Command
+
+The `packer hcl2_upgrade` Packer command is used to transpile a JSON
+configuration template to it's formatted HCL2 counterpart. The command will
+return a zero exit status on success, and a non-zero exit status on failure.
+
+Example usage:
+
+```shell-session
+$ packer hcl2_upgrade my-template.json
+
+Successfully created my-template.json.pkr.hcl
+```
+
+## Upgrading variables file
+
+From **v1.7.1**, the `hcl2_upgrade` command can upgrade a variables file.
+
+<Tabs>
+<Tab heading="Original file (variables.json)">
+
+```json
+{
+ "variables": {
+ "aws_region": null,
+ "aws_secondary_region": "{{ env `AWS_DEFAULT_REGION` }}",
+ "aws_secret_key": "",
+ "aws_access_key": ""
+ },
+ "sensitive-variables": ["aws_secret_key", "aws_access_key"]
+}
+```
+
+</Tab>
+<Tab heading="Result file (variables.pkr.hcl)">
+
+```hcl
+variable "aws_access_key" {
+ type = string
+ default = ""
+ sensitive = true
+}
+
+variable "aws_region" {
+ type = string
+}
+
+variable "aws_secondary_region" {
+ type = string
+ default = "${env("AWS_DEFAULT_REGION")}"
+}
+
+variable "aws_secret_key" {
+ type = string
+ default = ""
+ sensitive = true
+}
+```
+
+</Tab>
+</Tabs>
+
+## Go template functions
+
+`hcl2_upgrade` will do its best to transform your Go _template calls_ to HCL2,
+here is the list of calls that should get transformed:
+
+- `` {{ user `my_var` }} `` becomes `${var.my_var}`.
+- `` {{ env `my_var` }} `` becomes `${var.my_var}`. Packer HCL2 supports
+ environment variables through input variables. See
+ [docs](/packer/docs/templates/hcl_templates/variables#environment-variables)
+ for more info.
+- `{{ timestamp }}` becomes `${local.timestamp}`, the local variable
+ will be created for all generated files.
+- `` {{ build `ID` }} `` becomes `${build.ID}`.
+
+The rest of the calls should remain Go template calls for now, this will be
+improved over time.
+
+-> **Note**: The `hcl2_upgrade` command does its best to transform template
+calls to their JSON counterpart, but it might fail. In that case the
+`hcl2_upgrade` command will simply output the local HCL2 block without
+transformation and with the error message in a comment. We are currently
+working on improving this part of the transformer.
+
+## Options
+
+- `-output-file` - Filename of the hcl2 generated template. Defaults to
+ JSON_TEMPLATE.pkr.hcl; for example, if the file is called
+ "packerparty.json", the default output-file is "packerparty.json.pkr.hcl".
+- `-with-annotations` - Adds helpful comments to the HCL template with
+ information about the generated HCL2 blocks.
+
+## User variables using other user variables
+
+Packer JSON recently started allowing using user variables from variables. In
+HCL2, input variables cannot use functions nor other variables and are
+virtually static, local variables must be used instead to craft more dynamic
+variables.
+
+For v1.7.0 and lower, `hcl2_upgrade` doesn't upgrade variables to local variables,
+and it is up to you to upgrade them manually. Upgrade to **v1.7.1** to let the command do it
+automatically for you.
+
+Here is an example of a local variable using a string input variables:
+
+```hcl
+variable "foo" {
+ default = "Hello,"
+}
+
+variable "bar" {
+ default = "World!"
+}
+
+locals {
+ baz = "${var.foo} ${var.bar}"
+}
+```
+
+## Upgrading templates that use third-party community plugins
+
+If your template references a plugin that is not bundled with the main Packer
+binary, you need to make sure that the [plugin is installed](/packer/docs/plugins#installing-plugins)
+or you will get an `unknown builder type` error. Packer needs to load the plugin
+to transpose the template.
diff --git a/v1.9.4/website/content/docs/commands/index.mdx b/v1.9.4/website/content/docs/commands/index.mdx
new file mode 100644
index 0000000..bd2a810
--- /dev/null
+++ b/v1.9.4/website/content/docs/commands/index.mdx
@@ -0,0 +1,166 @@
+---
+description: |
+ Packer is controlled using a command-line interface. All interaction with
+ Packer is done via the `packer` tool. Like many other command-line tools, the
+ `packer` tool takes a subcommand to execute, and that subcommand may have
+ additional options as well. Subcommands are executed with `packer SUBCOMMAND`,
+ where "SUBCOMMAND" is the actual command you wish to execute.
+page_title: Commands
+---
+
+# Packer Commands (CLI)
+
+Packer is controlled using a command-line interface. All interaction with
+Packer is done via the `packer` tool. Like many other command-line tools, the
+`packer` tool takes a subcommand to execute, and that subcommand may have
+additional options as well. Subcommands are executed with `packer SUBCOMMAND`,
+where "SUBCOMMAND" is the actual command you wish to execute.
+
+If you run `packer` by itself, help will be displayed showing all available
+subcommands and a brief synopsis of what they do. In addition to this, you can
+run any `packer` command with the `-h` flag to output more detailed help for a
+specific subcommand.
+
+The documentation contains information about each subcommand.
+
+## Machine-Readable Output
+
+By default, the output of Packer is very human-readable. It uses nice
+formatting, spacing, and colors in order to make Packer a pleasure to use.
+However, Packer was built with automation in mind. To that end, Packer supports
+a fully machine-readable output setting, allowing you to use Packer in
+automated environments.
+
+Because the machine-readable output format was made with Unix tools in mind, it
+is `awk`/`sed`/`grep`/etc. friendly and provides a familiar interface without
+requiring you to learn a new format.
+
+### Enabling Machine-Readable Output
+
+The machine-readable output format can be enabled by passing the
+`-machine-readable` flag to any Packer command. This immediately enables all
+output to become machine-readable on stdout. Logging, if enabled, continues to
+appear on stderr. An example of the output is shown below:
+
+```shell-session
+$ packer -machine-readable version
+1498365963,,version,1.0.2
+1498365963,,version-prelease,
+1498365963,,version-commit,3ead2750b+CHANGES
+1498365963,,ui,say,Packer v1.0.2
+```
+
+The format will be covered in more detail later. But as you can see, the output
+immediately becomes machine-friendly. Try some other commands with the
+`-machine-readable` flag to see!
+
+~>; The `-machine-readable` flag is designed for automated environments and
+is mutually-exclusive with the `-debug` flag, which is designed for interactive
+environments.
+
+### Format for Machine-Readable Output
+
+The machine readable format is a line-oriented, comma-delimited text format.
+This makes it more convenient to parse using standard Unix tools such as `awk`
+or `grep` in addition to full programming languages like Ruby or Python.
+
+The format is:
+
+```text
+timestamp,target,type,data...
+```
+
+Each component is explained below:
+
+- `timestamp` is a Unix timestamp in UTC of when the message was printed.
+
+- `target` When you call `packer build` this can be either empty or
+ individual build names, e.g. `amazon-ebs`. It is normally empty when builds
+ are in progress, and the build name when artifacts of particular builds are
+ being referred to.
+
+- `type` is the type of machine-readable message being outputted. The two
+ most common `type`s are `ui` and `artifact`
+
+- `data` is zero or more comma-separated values associated with the prior
+ type. The exact amount and meaning of this data is type-dependent, so you
+ must read the documentation associated with the type to understand fully.
+
+Within the format, if data contains a comma, it is replaced with
+`%!(PACKER_COMMA)`. This was preferred over an escape character such as `\'`
+because it is more friendly to tools like `awk`.
+
+Newlines within the format are replaced with their respective standard escape
+sequence. Newlines become a literal `\n` within the output. Carriage returns
+become a literal `\r`.
+
+### Machine-Readable Message Types
+
+Here's an incomplete list of types you may see in the machine-readable output:
+
+You'll see these data types when you run `packer build`:
+
+- `ui`: this means that the information being provided is a human-readable
+ string that would be sent to stdout even if we aren't in machine-readable
+ mode. There are three "data" subtypes associated with this type:
+
+ - `say`: in a non-machine-readable format, this would be bolded. Normally
+ it is used for announcements about beginning new steps in the build
+ process
+
+ - `message`: the most commonly used message type, used for basic updates
+ during the build process.
+
+ - `error`: reserved for errors
+
+- `artifact-count`: This data type tells you how many artifacts a particular
+ build produced.
+
+- `artifact`: This data type tells you information about what Packer created
+ during its build. An example of output follows the pattern
+ `timestamp, buildname, artifact, artifact_number, key, value` where `key`
+ and `value` contain information about the artifact.
+
+ For example:
+
+ ```text
+ 1539967803,,ui,say,\n==> Builds finished. The artifacts of successful builds are:
+ 1539967803,amazon-ebs,artifact-count,2
+ 1539967803,amazon-ebs,artifact,0,builder-id,mitchellh.amazonebs
+ 1539967803,amazon-ebs,artifact,0,id,eu-west-1:ami-04d23aca8bdd36e30
+ 1539967803,amazon-ebs,artifact,0,string,AMIs were created:\neu-west-1: ami-04d23aca8bdd36e30\n
+ 1539967803,amazon-ebs,artifact,0,files-count,0
+ 1539967803,amazon-ebs,artifact,0,end
+ 1539967803,,ui,say,--> amazon-ebs: AMIs were created:\neu-west-1: ami-04d23aca8bdd36e30\n
+ 1539967803,amazon-ebs,artifact,1,builder-id,
+ 1539967803,amazon-ebs,artifact,1,id,
+ 1539967803,amazon-ebs,artifact,1,string,
+ 1539967803,amazon-ebs,artifact,1,files-count,0
+ 2018/10/19 09:50:03 waiting for all plugin processes to complete...
+ 1539967803,amazon-ebs,artifact,1,end
+ ```
+
+You'll see these data types when you run `packer version`:
+
+- `version`: what version of Packer is running
+
+- `version-prerelease`: Data will contain `dev` if version is prerelease, and
+ otherwise will be blank.
+
+- `version-commit`: The git hash for the commit that the branch of Packer is
+ currently on; most useful for Packer developers.
+
+## Autocompletion
+
+The `packer` command features opt-in subcommand autocompletion that you can
+enable for your shell with `packer -autocomplete-install`. After doing so, you
+can invoke a new shell and use the feature.
+
+For example, assume a tab is typed at the end of each prompt line:
+
+```shell-session
+$ packer p
+plugin build
+$ packer build -
+-color -debug -except -force -machine-readable -on-error -only -parallel -timestamp -var -var-file
+```
diff --git a/v1.9.4/website/content/docs/commands/init.mdx b/v1.9.4/website/content/docs/commands/init.mdx
new file mode 100644
index 0000000..32008db
--- /dev/null
+++ b/v1.9.4/website/content/docs/commands/init.mdx
@@ -0,0 +1,94 @@
+---
+description: |
+ The `packer init` Packer command is used to download Packer plugin binaries.
+page_title: packer init - Commands
+---
+
+# `init` Command
+
+-> **Note:** Packer init does not work with legacy JSON templates. You can
+upgrade your JSON config files to HCL using the [hcl2_upgrade](/packer/docs/commands/hcl2_upgrade) command.
+
+-> **Note:** Packer init will only work with multi-component plugins -- that is
+plugins that are named `packer-plugin-*`. To install a single-component plugin --
+that is `packer-provisioner-*`, `packer-builder-*`, etc. -- nothing changes, you will
+have to [install the plugin manually](/packer/docs/plugins#installing-plugins).
+
+The `packer init` command is used to download Packer plugin binaries. This is
+the first command that should be executed when working with a new or existing
+template. This command is always safe to run multiple times. Though subsequent
+runs may give errors, this command will never delete anything.
+
+You should invoke `packer init` on either an HCL2 template, or a directory that contains
+at least a valid HCL2 template, and eventually other related dependencies like varfiles
+for example.
+
+Example:
+
+```sh
+$ ls .
+template.pkr.hcl varfile.pkrvars.pkr.hcl
+
+$ packer init template.pkr.hcl # You can invoke packer init on a single template in this case
+ # This works if the template is self-contained, but may fail if
+ # the template is meant to be built as a bundle of partials.
+
+$ packer init . # Alternatively, you can invoke packer init on a directory instead,
+ # which behaves the same in a configuration like this one, but if
+ # the target is a collection ofHCL2 templates, this is the
+ # preferred way to invoke it.
+```
+
+Packer does not currently have the notion of a state like Terraform has. In other words,
+currently `packer init` is only in charge of installing Packer plugins.
+
+Currently, `packer init` can only fetch binaries from public projects on **GitHub**. GitHub's public API, [limits the number of unauthenticated requests
+per hour one IP can
+do](https://docs.github.com/en/developers/apps/rate-limits-for-github-apps#normal-user-to-server-rate-limits).
+Packer will do its best to avoid hitting those limits and in an average local
+usage this should not be an issue. Otherwise you can set the
+`PACKER_GITHUB_API_TOKEN` env var in order to get more requests per hour. Go to
+your personal [access token page](https://github.com/settings/tokens) to
+generate a new token.
+
+`packer init` will list all installed plugins then download the latest versions
+for the ones that are missing.
+
+`packer init -upgrade` will try to get the latest versions for all plugins.
+
+Import a plugin using the [`required_plugin`](/packer/docs/templates/hcl_templates/blocks/packer#specifying-plugin-requirements)
+block :
+
+```hcl
+packer {
+ required_plugins {
+ happycloud = {
+ version = ">= 2.7.0"
+ source = "github.com/azr/happycloud"
+ }
+ }
+}
+```
+
+HashiCorp does not officially verify third party Packer plugins, plugins not under the HashiCorp namespace `hashicorp/*`; as with all open source tools, please do your own due diligence when using a new tool.
+
+## Plugin Selection
+
+Plugin selection depends on the source and version constraints defined within the `required_plugins` block.
+For each of the required plugins Packer will query the source repository `github.com/azr/happycloud` whose fully qualified address
+is `https://github.com/azr/packer-plugin-happycloud` for a plugin matching the version constraints for the host operating system.
+
+Packer init will install the latest found version matching the version selection
+in the `required_plugins` section. Make sure to set a correct [version
+constraint
+string](/packer/docs/templates/hcl_templates/blocks/packer#version-constraints). The
+plugins will be installed in the [Plugin
+Directory](/packer/docs/configure#packer-s-plugin-directory).
+
+See [Installing Plugins](/packer/docs/plugins#installing-plugins) for more information on how plugin installation works.
+
+## Options
+
+- `-upgrade` - On top of installing missing plugins, update installed plugins to
+ the latest available version, if there is a new higher one. Note that this
+ still takes into consideration the version constraint of the config.
diff --git a/v1.9.4/website/content/docs/commands/inspect.mdx b/v1.9.4/website/content/docs/commands/inspect.mdx
new file mode 100644
index 0000000..9cebe60
--- /dev/null
+++ b/v1.9.4/website/content/docs/commands/inspect.mdx
@@ -0,0 +1,62 @@
+---
+description: >
+ The `packer inspect` command takes a template and outputs the various
+
+ components a template defines. This can help you quickly learn about a
+ template
+
+ without having to dive into the HCL itself. The command will tell you things
+
+ like what variables a template accepts, the builders it defines, the
+
+ provisioners it defines and the order they'll run, and more.
+page_title: packer inspect - Commands
+---
+
+# `inspect` Command
+
+The `packer inspect` command takes a template and outputs the various
+components a template defines. This can help you quickly learn about a template
+without having to dive into the HCL itself. The command will tell you things
+like what variables a template accepts, the builders it defines, the
+provisioners it defines and the order they'll run, and more.
+
+This command is extra useful when used with [machine-readable
+output](/packer/docs/commands) enabled. The command outputs the components
+in a way that is parseable by machines.
+
+The command doesn't validate the actual configuration of the various components
+(that is what the `validate` command is for), but it will validate the syntax
+of your template by necessity.
+
+## Usage Example
+
+Given a basic template, here is an example of what the output might look like:
+
+```shell-session
+$ packer inspect template.pkr.hcl
+> input-variables:
+
+var.aws_access_key: "<sensitive>"
+var.aws_secret_key: "<sensitive>"
+
+> local-variables:
+
+> builds:
+
+ > <unnamed build 0>:
+
+ sources:
+
+ amazon-ebs.foo
+ amazon-instance.bar
+ virtualbox-iso.basic
+
+ provisioners:
+
+ shell
+
+ post-processors:
+
+ <no post-processor>
+```
diff --git a/v1.9.4/website/content/docs/commands/plugins/index.mdx b/v1.9.4/website/content/docs/commands/plugins/index.mdx
new file mode 100644
index 0000000..551cbff
--- /dev/null
+++ b/v1.9.4/website/content/docs/commands/plugins/index.mdx
@@ -0,0 +1,30 @@
+---
+description: |
+ The "plugin" command groups subcommands for interacting with
+ Packer's plugin and the plugin catalog.
+page_title: plugins Command
+---
+
+# `plugins`
+
+The `plugins` command groups subcommands for interacting with Packers' plugins.
+
+```shell-session
+$ packer plugins -h
+Usage: packer plugins <subcommand> [options] [args]
+ This command groups subcommands for interacting with Packer plugins.
+
+Related but not under the "plugins" command :
+
+- "packer init <path>" will install all plugins required by a config.
+
+Subcommands:
+ install Install latest Packer plugin [matching version constraint]
+ installed List all installed Packer plugin binaries
+ remove Remove Packer plugins [matching a version]
+ required List plugins required by a config
+```
+
+## Related
+
+- [`packer init`](/packer/docs/commands/init) will install all required plugins.
diff --git a/v1.9.4/website/content/docs/commands/plugins/install.mdx b/v1.9.4/website/content/docs/commands/plugins/install.mdx
new file mode 100644
index 0000000..711bfc3
--- /dev/null
+++ b/v1.9.4/website/content/docs/commands/plugins/install.mdx
@@ -0,0 +1,24 @@
+---
+description: |
+ The "plugins install" command can install a plugin at a version constraint.
+page_title: plugins Command
+---
+
+# `plugins install`
+
+The `plugins install` subcommand installs a Packer plugin at a version constraint
+
+```shell-session
+$ packer plugins install -h
+Usage: packer plugins install <plugin> [<version constraint>]
+
+ This command will install the most recent compatible Packer plugin matching
+ version constraint. When the version constraint is omitted, the most recent
+ version will be installed.
+
+ Ex: packer plugins install github.com/hashicorp/happycloud v1.2.3
+```
+
+## Related
+
+- [`packer init`](/packer/docs/commands/init) will install all required plugins.
diff --git a/v1.9.4/website/content/docs/commands/plugins/installed.mdx b/v1.9.4/website/content/docs/commands/plugins/installed.mdx
new file mode 100644
index 0000000..164da29
--- /dev/null
+++ b/v1.9.4/website/content/docs/commands/plugins/installed.mdx
@@ -0,0 +1,21 @@
+---
+description: |
+ The "plugins installed" command will list installed plugins.
+page_title: plugins Command
+---
+
+# `plugins installed`
+
+The `plugins installed` subcommand lists installed Packer plugins
+
+```shell-session
+$ packer plugins installed -h
+Usage: packer plugins installed
+
+ This command lists all installed plugin binaries that match with the current
+ OS and architecture. Packer's API version will be ignored.
+```
+
+## Related
+
+- [`packer init`](/packer/docs/commands/init) will install all required plugins.
diff --git a/v1.9.4/website/content/docs/commands/plugins/remove.mdx b/v1.9.4/website/content/docs/commands/plugins/remove.mdx
new file mode 100644
index 0000000..4a5ea6d
--- /dev/null
+++ b/v1.9.4/website/content/docs/commands/plugins/remove.mdx
@@ -0,0 +1,24 @@
+---
+description: |
+ The "plugins remove" command can remove a plugin at a version constraint.
+page_title: plugins Command
+---
+
+# `plugins remove`
+
+The `plugins remove` subcommand removes a Packer plugin at a version constraint
+
+```shell-session
+$ packer plugins remove -h
+Usage: packer plugins remove <plugin> [<version constraint>]
+
+ This command will remove all Packer plugins matching the version constraint
+ for the current OS and architecture.
+ When the version is omitted all installed versions will be removed.
+
+ Ex: packer plugins remove github.com/hashicorp/happycloud v1.2.3
+```
+
+## Related
+
+- [`packer init`](/packer/docs/commands/init) will install all required plugins.
diff --git a/v1.9.4/website/content/docs/commands/plugins/required.mdx b/v1.9.4/website/content/docs/commands/plugins/required.mdx
new file mode 100644
index 0000000..3852310
--- /dev/null
+++ b/v1.9.4/website/content/docs/commands/plugins/required.mdx
@@ -0,0 +1,30 @@
+---
+description: |
+ The "plugins required" command lists all plugins required in a Packer configuration.
+page_title: plugins Command
+---
+
+# `plugins required`
+
+The `plugins required` command lists all plugins required by a Packer config and
+all the installed binaries that match the constraint. The first binary
+is the most up-to-date installed version and will be the one picked by Packer in a build.
+
+```shell-session
+$ packer plugins required -h
+Usage: packer plugins required <path>
+
+ This command will list every Packer plugin required by a Packer config, in
+ packer.required_plugins blocks. All binaries matching the required version
+ constrain and the current OS and Architecture will be listed. The most recent
+ version (and the first of the list) will be the one picked by Packer during a
+ build.
+
+
+ Ex: packer plugins required require.pkr.hcl
+ Ex: packer plugins required path/to/folder/
+```
+
+## Related
+
+- [`packer init`](/packer/docs/commands/init) will install all required plugins.
diff --git a/v1.9.4/website/content/docs/commands/validate.mdx b/v1.9.4/website/content/docs/commands/validate.mdx
new file mode 100644
index 0000000..0827f5b
--- /dev/null
+++ b/v1.9.4/website/content/docs/commands/validate.mdx
@@ -0,0 +1,73 @@
+---
+description: |
+ The `packer validate` Packer command is used to validate the syntax and
+ configuration of a template. The command will return a zero exit status on
+ success, and a non-zero exit status on failure. Additionally, if a template
+ doesn't validate, any error messages will be outputted.
+page_title: packer validate - Commands
+---
+
+# `validate` Command
+
+The `packer validate` Packer command is used to validate the syntax and
+configuration of a [template](/packer/docs/templates). The command will
+return a zero exit status on success, and a non-zero exit status on failure.
+Additionally, if a template doesn't validate, any error messages will be
+outputted.
+
+Example usage:
+
+```shell-session
+$ packer validate my-template.pkr.hcl
+Template validation failed. Errors are shown below.
+
+Errors validating build 'vmware'. 1 error(s) occurred:
+
+* Either a path or inline script must be specified.
+```
+
+## Options
+
+- `-syntax-only` - Only the syntax of the template is checked. The
+ configuration is not validated.
+
+- `-evaluate-datasources` - Evaluate all data sources when validating a template.
+ This is only valid on HCL2 templates, since JSON templates do not feature
+ datasources, this option will be ignored.
+
+ ~> **Warning:** Data sources may rely on external services for fetching data,
+ which can incur some costs at validation if the services being contacted are
+ billing per operation.
+
+- `-except=foo,bar,baz` - Validates all the builds except those with the
+ comma-separated names. In legacy JSON templates, build names default to the
+ types of their builders (e.g. `docker` or
+ `amazon-ebs` or `virtualbox-iso`), unless a specific `name` attribute is
+ specified within the configuration. In HCL2 templates, the "name" is the
+ source block's "name" label, unless an in-build source definition adds the
+ "name" configuration option.
+
+- `-no-warn-undeclared-var` - Silence warnings when the variable definition
+ file contains variable assignments for undeclared variables. This can occur
+ when using a var-file that contains a large amount of unused variables for a
+ given HCL2 template. For HCL2 template defining a value for a variable in a
+ var-file is not enough on its own for Packer to function, as there also needs
+ to be a variable block definition in the template files `pkr.hcl` for the
+ variable. By default `packer validate` will warn when a var-file contains one
+ or more undeclared variables.
+
+- `-only=foo,bar,baz` - Only validate the builds with the given comma-separated
+ names. In legacy JSON templates, build names default to the
+ types of their builders (e.g. `docker` or
+ `amazon-ebs` or `virtualbox-iso`), unless a specific `name` attribute is
+ specified within the configuration. In HCL2 templates, the "name" is the
+ source block's "name" label, unless an in-build source definition adds the
+ "name" configuration option.
+
+- `-machine-readable` Sets all output to become machine-readable on stdout.
+ Logging, if enabled, continues to appear on stderr.
+
+- `-var` - Set a variable in your Packer template. This option can be used
+ multiple times. This is useful for setting version numbers for your build.
+
+- `-var-file` - Set template variables from a file.
diff --git a/v1.9.4/website/content/docs/communicators/index.mdx b/v1.9.4/website/content/docs/communicators/index.mdx
new file mode 100644
index 0000000..d6564fa
--- /dev/null
+++ b/v1.9.4/website/content/docs/communicators/index.mdx
@@ -0,0 +1,30 @@
+---
+description: |
+ Communicators are the mechanism Packer uses to upload files, execute
+ scripts, etc. with the machine being created.
+page_title: Communicators
+---
+
+# Communicators
+
+Communicators are the mechanism Packer uses to upload files, execute scripts,
+etc. with the machine being created.
+
+Communicators are configured within the
+[builder](/packer/docs/templates/legacy_json_templates/builders) section. Packer currently supports
+three kinds of communicators:
+
+- `none` - No communicator will be used. If this is set, most provisioners
+ also can't be used.
+
+- [ssh](/packer/docs/communicators/ssh) - An SSH connection will be established to the machine. This is
+ usually the default.
+
+- [winrm](/packer/docs/communicators/winrm) - A WinRM connection will be established.
+
+In addition to the above, some builders have custom communicators they can use.
+For example, the Docker builder has a "docker" communicator that uses
+`docker exec` and `docker cp` to execute scripts and copy files.
+
+For more details on how to use each communicator, click the links above to be
+taken to each communicator's page.
diff --git a/v1.9.4/website/content/docs/communicators/ssh.mdx b/v1.9.4/website/content/docs/communicators/ssh.mdx
new file mode 100644
index 0000000..f3b48e5
--- /dev/null
+++ b/v1.9.4/website/content/docs/communicators/ssh.mdx
@@ -0,0 +1,82 @@
+---
+description: |
+ The SSH communicator uses SSH to upload files, execute scripts, etc. on
+ the machine being created.
+page_title: Communicators - SSH
+---
+
+# SSH Communicator
+
+Communicators are the mechanism Packer uses to upload files, execute scripts,
+etc. on the machine being created, and are configured within the
+[builder](/packer/docs/templates/legacy_json_templates/builders) section.
+
+The SSH communicator does this by using the SSH protocol. It is the default
+communicator for a majority of builders.
+
+If you have an SSH agent configured on the host running Packer, and SSH agent
+authentication is enabled in the communicator config, Packer will automatically
+forward the SSH agent to the remote host.
+
+## Getting Ready to Use the SSH Communicator
+
+The SSH communicator is the default communicator for a majority of builders, but
+depending on your builder it may not work "out of the box".
+
+If you are building from a cloud image (for example, building on Amazon), there
+is a good chance that your cloud provider has already preconfigured SSH on the
+image for you, meaning that all you have to do is configure the communicator in
+the Packer template.
+
+However, if you are building from a brand-new and unconfigured operating system
+image, you will almost always have to perform some extra work to configure SSH
+on the guest machine. For most operating system distributions, this work will
+be performed by a [boot command](/packer/plugins/builders/vmware/iso#boot-configuration)
+that references a file which provides answers to the normally-interactive
+questions you get asked when installing an operating system. The name of this
+file varies by operating system; some common examples are the "preseed" file
+required by Debian, the "kickstart" file required by CentOS or the
+"answer file", also known as the Autounattend.xml file, required by Windows.
+For simplicity's sake, we'll refer to this file as the "preseed" file in the
+rest of the documentation.
+
+If you are unfamiliar with how to use a preseed file for automatic
+bootstrapping of an image, please either take a look at our
+[quick guides](/packer/guides/automatic-operating-system-installs) to
+image bootstrapping, or research automatic configuration for your specific
+guest operating system. Knowing how to automatically initalize your operating
+system is critical for being able to successfully use Packer.
+
+## SSH Communicator
+
+The SSH communicator connects to the host via SSH. If you have an SSH agent
+configured on the host running Packer, and SSH agent authentication is enabled
+in the communicator config, Packer will automatically forward the SSH agent to
+the remote host.
+
+The SSH communicator has the following options:
+
+@include "packer-plugin-sdk/communicator/SSH-not-required.mdx"
+
+~> Note: SSH communicator options: `ssh_keypair_name`, `ssh_agent_auth`,
+`temporary_key_pair_name` and `ssh_private_key_file` are also supported by
+the communicator. But they may not be supported for every builder. Please check
+the builder specific documentation for additional SSH supported options.
+
+### SSH Communicator Details
+
+Packer will only use one authentication method, either `publickey` or if
+`ssh_password` is used packer will offer `password` and `keyboard-interactive`
+both sending the password. In other words Packer will not work with _sshd_
+configured with more than one configured authentication method using
+`AuthenticationMethods`.
+
+Packer supports the following MACs:
+
+- hmac-sha1
+- hmac-sha1-96
+- hmac-sha2-256
+- `hmac-sha2-256-etm@openssh.com`
+
+For more information on the ciphers that Packer supports, check the docs for
+the [ssh_ciphers](/packer/docs/communicators/ssh#ssh_ciphers) template option.
diff --git a/v1.9.4/website/content/docs/communicators/winrm.mdx b/v1.9.4/website/content/docs/communicators/winrm.mdx
new file mode 100644
index 0000000..1036372
--- /dev/null
+++ b/v1.9.4/website/content/docs/communicators/winrm.mdx
@@ -0,0 +1,197 @@
+---
+description: |
+ Communicators are the mechanism Packer uses to upload files, execute scripts,
+ etc. with the machine being created.
+page_title: Communicators - Templates
+---
+
+# WinRM Communicator
+
+Communicators are the mechanism Packer uses to upload files, execute scripts,
+etc. with the machine being created. The WinRM communicator uses the
+Windows Remote Management protocol to do this.
+
+## Getting Ready to Use the WinRM Communicator
+
+The WinRM communicator is not the default communicator, so you will always have
+to set the `"communicator": "winrm",` template option explicitly. In addition,
+you will almost always have to provide a pre-run script that enables and
+configures WinRM on the guest machine. This will generally be in the form of a
+PowerShell script or a batch file.
+
+If you are building from a brand-new and unconfigured operating system
+image, you will need to provide this pre-run script as part of your
+Autounattend.xml file, required by Windows for automatic operating system
+installation. If you are building in a cloud or from a pre-installed image, your
+method for providing this pre-run script will vary based on the builder. Please
+refer to each builder's documentation for more information on how to supply the
+winrm configuration script.
+
+If you are unfamiliar with how to use an autounattend file, take a look at our
+[quick guides](/packer/guides/automatic-operating-system-installs); knowing
+how to automatically initalize your operating system is critical for being able
+to successfully use Packer to build from an iso.
+
+## WinRM Communicator Options
+
+@include "packer-plugin-sdk/communicator/WinRM-not-required.mdx"
+
+## Examples
+
+### Basics of WinRM Connection
+
+Please note that WinRM is not a Packer-specific protocol. Microsoft has a great
+deal of documentation about WinRM. If you find after reading this guide that
+you are still not able to connect via WinRM, check the
+[Microsoft documentation](https://docs.microsoft.com/en-us/windows/win32/winrm/installation-and-configuration-for-windows-remote-management)
+to make sure there isn't anything you're missing.
+
+There are some steps that you will normally need to take in order for Packer
+to be able to connect via WinRM
+
+1. Set up a username and password that Packer to connect with.
+2. Make any necesary registry edits to enable remote execution
+ (and remote execution with elevated privileges, if needed)
+3. Start WinRM, setting any config needed for allowing basic auth
+4. Open ports 5985 and/or 5986 depending on how you're connecting
+5. launch WinRM and set it to automatically launch when the computer restarts
+6. If necessary, generate a self-signed certificate or provide a real certificate
+ to the WinRM listener.
+
+#### Configuring WinRM in VMware
+
+If you are configuring WinRM using an Autounattend.xml, the simplest way to set
+up WinRM is to put the configuration commands directly into the Autounattend
+file as shown [here](https://github.com/StefanScherer/packer-windows/blob/6e603e904e9b280eeb97f7eb542940a043954112/answer_files/2008_r2_core/Autounattend.xml#L157-L234)
+
+Instead of entering each line individually, you can also add a batch file to
+your autounattend that contains the commands for configuring winrm. Depending
+on your winrm setup, this could be a complex batch file, or a very simple one.
+
+Below is an example of how we would call a batch file from inside the
+Autounattend file.
+
+```xml
+<FirstLogonCommands>
+ ...
+ <SynchronousCommand wcm:action="add">
+ <CommandLine>cmd.exe /c a:\winrmConfig.bat</CommandLine>
+ <Description>Configure WinRM</Description>
+ <Order>3</Order>
+ <RequiresUserInput>true</RequiresUserInput>
+ </SynchronousCommand>
+ ...
+</FirstLogonCommands>
+```
+
+It is also possible to call PowerShell scripts in a similar manner.
+
+The winrmConfig.bat referenced above can be as simple as
+
+```powershell
+rem basic config for winrm
+cmd.exe /c winrm quickconfig -q
+
+rem allow unencrypted traffic, and configure auth to use basic username/password auth
+cmd.exe /c winrm set winrm/config/service @{AllowUnencrypted="true"}
+cmd.exe /c winrm set winrm/config/service/auth @{Basic="true"}
+
+rem update firewall rules to open the right port and to allow remote administration
+cmd.exe /c netsh advfirewall firewall set rule group="remote administration" new enable=yes
+
+rem restart winrm
+cmd.exe /c net stop winrm
+cmd.exe /c net start winrm
+```
+
+Please note that the above batch file is _extremely_ simplistic, and not secure.
+It is intended to be an example of the bare minimum configuration. Below, you'll
+find a more complicated example of a more secure WinRM configuration process.
+
+This batch file will only work for HTTP connections, not HTTPS, but will enable
+you to connect using only the username and password created earlier in the
+Autounattend file. The above batchfile will allow you to connect using a very
+simple Packer config:
+
+```json
+ "communicator": "winrm",
+ "winrm_username": "packeruser",
+ "winrm_password": "SecretPassword"
+```
+
+A more complex example of a PowerShell script used for configuration can be seen
+below.
+
+```powershell
+# A Packer config that works with this example would be:
+#
+#
+# "winrm_username": "Administrator",
+# "winrm_password": "SuperS3cr3t!!!",
+# "winrm_insecure": true,
+# "winrm_use_ssl": true
+#
+#
+
+# Create username and password
+net user Administrator SuperS3cr3t!!!
+wmic useraccount where "name='Administrator'" set PasswordExpires=FALSE
+
+Set-ExecutionPolicy Unrestricted -Scope LocalMachine -Force -ErrorAction Ignore
+
+# Don't set this before Set-ExecutionPolicy as it throws an error
+$ErrorActionPreference = "stop"
+
+# Remove HTTP listener
+Remove-Item -Path WSMan:\Localhost\listener\listener* -Recurse
+
+# Create a self-signed certificate to let ssl work
+$Cert = New-SelfSignedCertificate -CertstoreLocation Cert:\LocalMachine\My -DnsName "packer"
+New-Item -Path WSMan:\LocalHost\Listener -Transport HTTPS -Address * -CertificateThumbPrint $Cert.Thumbprint -Force
+
+# WinRM
+write-output "Setting up WinRM"
+write-host "(host) setting up WinRM"
+
+# Configure WinRM to allow unencrypted communication, and provide the
+# self-signed cert to the WinRM listener.
+cmd.exe /c winrm quickconfig -q
+cmd.exe /c winrm set "winrm/config/service" '@{AllowUnencrypted="true"}'
+cmd.exe /c winrm set "winrm/config/client" '@{AllowUnencrypted="true"}'
+cmd.exe /c winrm set "winrm/config/service/auth" '@{Basic="true"}'
+cmd.exe /c winrm set "winrm/config/client/auth" '@{Basic="true"}'
+cmd.exe /c winrm set "winrm/config/service/auth" '@{CredSSP="true"}'
+cmd.exe /c winrm set "winrm/config/listener?Address=*+Transport=HTTPS" "@{Port=`"5986`";Hostname=`"packer`";CertificateThumbprint=`"$($Cert.Thumbprint)`"}"
+
+# Make sure appropriate firewall port openings exist
+cmd.exe /c netsh advfirewall firewall set rule group="remote administration" new enable=yes
+cmd.exe /c netsh firewall add portopening TCP 5986 "Port 5986"
+
+# Restart WinRM, and set it so that it auto-launches on startup.
+cmd.exe /c net stop winrm
+cmd.exe /c sc config winrm start= auto
+cmd.exe /c net start winrm
+```
+
+Please note that having WinRM auto-launch on all start ups may not be the right
+choice for you, if you don't need the server to recieve WinRM connections in the
+future. Clean up after yourself and close unnecesary firewall ports at a final
+provisioning step to make sure your image is secure.
+
+#### Configuring WinRM in the Cloud
+
+Most clouds allow you to provide a configuration script that runs when the
+instance is launched. In AWS, this is the
+[user_data_file](/packer/plugins/builders/amazon/ebs#user_data_file). In Google
+Cloud, this is provided using the `windows-startup-script-cmd`
+[metadata](/packer/plugins/builders/googlecompute#metadata) tag.
+[Example](/packer/plugins/builders/googlecompute#windows-example)
+
+Essentially, these files are powershell or cmd scripts that configure winrm,
+without having to be wrapped in an Autounattend. Provide the script in the
+format requested by each cloud, and make sure you manually configure any
+firewall rules that the cloud doesn't allow you to manage internally. More
+specific details for each cloud can be found in the builder sections.
+
+The above examples will work in cloud prep too, but may be overkill depending on
+how much preconfiguration the cloud has done for you.
diff --git a/v1.9.4/website/content/docs/community-tools.mdx b/v1.9.4/website/content/docs/community-tools.mdx
new file mode 100644
index 0000000..ea75ef3
--- /dev/null
+++ b/v1.9.4/website/content/docs/community-tools.mdx
@@ -0,0 +1,77 @@
+---
+page_title: Download Packer Community Projects
+description: >-
+ Packer has a vibrant community of contributors who have built a number of
+ great tools on top of Packer. There are also quite a few projects
+ demonstrating the power of Packer templates.
+---
+
+# Download Community Projects
+
+Packer has a vibrant community of contributors who have built a number of great
+tools on top of Packer. There are also quite a few projects demonstrating the
+power of Packer templates.
+
+## Third-Party plugins
+
+The plugins listed below have been built by the community of Packer users and
+vendors. These plugins are not officially tested nor officially maintained by
+HashiCorp, and are listed here in order to help users find them easily.
+
+To learn more about how to use community plugins, or how to build your own,
+check out the docs on [extending Packer](https://developer.hashicorp.com/packer/docs/plugins/install-plugins)
+
+If you have built a plugin and would like to add it to this community list,
+please make a pull request so that we can document your
+contribution here!
+
+@include "builders/community_builders.mdx"
+
+@include "provisioners/community_provisioners.mdx"
+
+@include "post-processors/community_post-processors.mdx"
+
+## Templates
+
+- [bento](https://github.com/chef/bento) - Packer templates for building minimal
+ Vagrant base boxes
+
+- [boxcutter](https://github.com/boxcutter) - Community-driven templates and
+ tools for creating cloud, virtual machines, containers and metal operating
+ system environments
+
+- [cbednarski/packer-ubuntu](https://github.com/cbednarski/packer-ubuntu) -
+ Ubuntu LTS Virtual Machines for Vagrant
+
+- [geerlingguy/packer-ubuntu-1604](https://github.com/geerlingguy/packer-ubuntu-1604)
+ \- Ubuntu 16.04 minimal Vagrant Box using Ansible provisioner
+
+- [jakobadam/packer-qemu-templates](https://github.com/jakobadam/packer-qemu-templates)
+ \- QEMU templates for various operating systems
+
+- [lucidone/baseliner](https://git.sr.ht/~lucidone/baseliner) - Example of using
+ QEMU + Ansible with Packer
+
+- [packer-build](https://github.com/tylert/packer-build) - Build fresh Debian
+ and Ubuntu virtual machine images for Vagrant, VirtualBox and QEMU
+
+- [packer-windows](https://github.com/joefitzgerald/packer-windows) - Windows
+ Packer Templates
+
+- [packer-baseboxes](https://github.com/taliesins/packer-baseboxes) - Templates
+ for Packer to build base boxes
+
+- [vmware-samples/packer-examples-for-vsphere](https://github.com/vmware-samples/packer-examples-for-vsphere) - Examples
+ to automate the creation of virtual machine images and their guest operating systems on VMware vSphere using HashiCorp Packer
+ and the Packer Plugin for VMware vSphere (vsphere-iso).
+
+## Wrappers
+
+- [packer-config](https://github.com/ianchesal/packer-config) - a Ruby model that lets you build Packer configurations in Ruby
+- [packerlicious](https://github.com/mayn/packerlicious) - a Python library for generating Packer templates
+- [packer.py](https://github.com/mayn/packer.py) - a Python library for executing Packer CLI commands
+- [racker](https://github.com/aspring/racker) - an opinionated Ruby DSL for generating Packer templates
+
+## Other
+
+- [suitcase](https://github.com/tmclaugh/suitcase) - Packer based build system for CentOS OS images
diff --git a/v1.9.4/website/content/docs/configure.mdx b/v1.9.4/website/content/docs/configure.mdx
new file mode 100644
index 0000000..18eeb40
--- /dev/null
+++ b/v1.9.4/website/content/docs/configure.mdx
@@ -0,0 +1,146 @@
+---
+description: |
+ There are various ways to configure Packer. By default Packer will use known folders,
+ which can be changed by using environment variables.
+page_title: Configuring Packer
+---
+
+# Configuring Packer
+
+-> **Note:** There are a few configuration settings that affect Packer globally
+by configuring the core of Packer. These settings all have reasonable defaults,
+so you generally don't have to worry about it until you want to tweak a
+configuration. If you're just getting started with Packer, don't worry about
+core configuration for now.
+
+## Packer's config directory
+
+Packer's configuration directory can potentially contain plugins and internal
+Packer files. The Packer config directory will be looked up on the following paths:
+
+| Unix | Windows |
+| --------------------------- | --------------------------- |
+| `${HOME}/.config/packer/` | `%APPDATA%\packer.d\` |
+
+-> **Note:** On Unix systems, Packer defaults to using the XDG base directory specification.
+When the environment variable `PACKER_CONFIG_DIR` is unset or empty a default equal to `$HOME/.config/packer` should be used.
+In all other cases, where there is an existing older style `.packer.d` directory (e.g `$HOME/.packer.d/`) or PACKER_CONFIG_DIR is not empty
+the older configuration directory will be used.
+
+Examples:
+
+- On a Unix system, if the `$PACKER_CONFIG_DIR` environment variable is set to
+ `/home/packer`, the config directory will be: `/home/packer/.packer.d/` and
+ other values will not be checked.
+- On a Windows system, if the `PACKER_CONFIG_DIR` environment variable is set to `C:/`,the
+ config directory will be: `C:/packer.d/` and other values will not be checked.
+
+<a id="packer-s-config-file"></a>
+
+## Packer's config file (deprecated)
+
+Packer can optionally read a JSON file for the end user to set core settings.
+The config file of Packer will be looked up on the following paths:
+
+| Unix | Windows |
+| -------------------------------- | --------------------------------- |
+| `${PACKER_CONFIG}` | `%PACKER_CONFIG%` |
+| `${HOME}/.packerconfig` | `%APPDATA%\packer.config\` |
+
+The format of the configuration file is basic JSON.
+
+### Packer config file configuration Reference
+
+Below is the list of all available configuration parameters for the core
+configuration file. None of these are required, since all have defaults.
+
+- `plugin_min_port` and `plugin_max_port` (number) - These are the minimum
+ and maximum ports that Packer uses for communication with plugins, since
+ plugin communication happens over TCP connections on your local host. By
+ default these are 10,000 and 25,000, respectively. Be sure to set a fairly
+ wide range here, since Packer can easily use over 25 ports on a single run.
+
+- `builders`, `commands`, `post-processors`, and `provisioners` are objects
+ that are used to install plugins. The details of how exactly these are set is
+ covered in more detail in the [installing plugins documentation
+ page](/packer/docs/plugins/install-plugins). It is instead recommended to use [HCL2
+ `required_plugins`](/packer/docs/templates/hcl_templates/blocks/packer#specifying-plugin-requirements)
+ and the [`packer init`](/packer/docs/commands/init) command to install plugins; if
+ you are using both, the `required_plugin` config will take precedence.
+
+## Packer's plugin directory
+
+@include "plugins/plugin-location.mdx"
+
+## Packer's cache directory
+
+Packer uses a cache directory to download large files and for logistics around
+large file download. By default, Packer caches things in the current directory,
+under: `./packer_cache/`. This can be changed by setting the `PACKER_CACHE_DIR`
+env var. It is recommended to share the same Packer cache directory across your
+builds if you have multiple builds doing similar things to avoid downloading the
+same ISO twice for example.
+
+## Environment Variables usable for Packer
+
+Packer uses a variety of environmental variables. A listing and description of
+each can be found below:
+
+- `PACKER_CACHE_DIR` - The location of the Packer cache. This defaults to
+ `./packer_cache/`. Relative paths can be used. Some plugins can cache large
+ files like ISOs in the cache dir.
+
+- `PACKER_CONFIG` - The location of the core configuration file. The format
+ of the configuration file is basic JSON. See [Packer's Config
+ file](#packer-s-config-file).
+
+- `PACKER_CONFIG_DIR` - The location for the home directory of Packer. See
+ [Packer's home directory](#packer-s-home-directory) for more.
+
+- `PACKER_GITHUB_API_TOKEN` - When using Packer init on HCL2 templates, Packer
+ queries the public API from Github which limits the amount of queries on can
+ set the `PACKER_GITHUB_API_TOKEN` with a Github Token to make it higher.
+
+- `PACKER_LOG` - Setting this to any value other than "" (empty string) or
+ "0" will enable the logger. See the [debugging
+ page](/packer/docs/debugging).
+
+- `PACKER_LOG_PATH` - The location of the log file. Note: `PACKER_LOG` must
+ be set for any logging to occur. See the [debugging
+ page](/packer/docs/debugging).
+
+- `PACKER_NO_COLOR` - Setting this to any value will disable color in the
+ terminal.
+
+- `PACKER_PLUGIN_MAX_PORT` - The maximum port that Packer uses for
+ communication with plugins, since plugin communication happens over TCP
+ connections on your local host. The default is 25,000. This can also be set
+ using the Packer's config file, see the [config file configuration
+ reference](#packer-config-file-configuration-reference) for more.
+
+- `PACKER_PLUGIN_MIN_PORT` - The minimum port that Packer uses for
+ communication with plugins, since plugin communication happens over TCP
+ connections on your local host. The default is 10,000. This can also be set
+ using the Packer's config file, see the [config file configuration
+ reference](#packer-config-file-configuration-reference) for more.
+
+- `PACKER_PLUGIN_PATH` - a PATH variable for finding third-party packer
+ plugins. For example: `~/custom-dir-1:~/custom-dir-2`. Separate directories in
+ the PATH string using a colon (`:`) on POSIX systems and a semicolon (`;`) on
+ Windows systems. The above example path would be able to find a provisioner
+ named `packer-provisioner-foo` in either
+ `~/custom-dir-1/packer-provisioner-foo` or
+ `~/custom-dir-2/packer-provisioner-foo`. See the documentation on [plugin
+ directories](#packer-s-plugin-directory) for more.
+
+- `CHECKPOINT_DISABLE` - When Packer is invoked it sometimes calls out to
+ [checkpoint.hashicorp.com](https://checkpoint.hashicorp.com/) to look for
+ new versions of Packer. If you want to disable this for security or privacy
+ reasons, you can set this environment variable to `1`.
+
+- `TMPDIR` (Unix) / `TMP` `TEMP` `USERPROFILE` (Windows) - The
+ location of the directory used for temporary files (defaults to `/tmp` on
+ Linux/Unix and `%USERPROFILE%\AppData\Local\Temp` on Windows Vista and above).
+ It might be necessary to customize it when working with large files since
+ `/tmp` is a memory-backed filesystem in some Linux distributions in which case
+ `/var/tmp` might be preferred.
diff --git a/v1.9.4/website/content/docs/datasources/hcp/hcp-packer-image.mdx b/v1.9.4/website/content/docs/datasources/hcp/hcp-packer-image.mdx
new file mode 100644
index 0000000..8e1bf82
--- /dev/null
+++ b/v1.9.4/website/content/docs/datasources/hcp/hcp-packer-image.mdx
@@ -0,0 +1,98 @@
+---
+description: |
+ The HCP Packer Image Data Source retrieves information about an
+ image from the HCP Packer registry. This information can be used to
+ provide a source image to various Packer builders.
+page_title: HCP Packer Image - Data Sources
+---
+
+<BadgesHeader>
+ <PluginBadge type="official" />
+ <PluginBadge type="hcp_packer_ready" />
+</BadgesHeader>
+
+# HCP Packer Image Data Source
+
+Type: `hcp-packer-image`
+
+The `HCP Packer Image` Data Source retrieves information about an
+image from the HCP Packer registry. This information can be used to
+provide a source image to various Packer builders.
+
+To get started with HCP Packer, refer to the [HCP Packer documentation](/hcp/docs/packer) or try the [Get Started with HCP Packer tutorials](/packer/tutorials/hcp-get-started).
+
+~> **Note:** You will receive an error if you try to reference metadata from a deactivated or deleted registry. An administrator can manually deactivate or delete a registry, and HCP Packer automatically deactivates registries with billing issues. Contact [HashiCorp Support](https://support.hashicorp.com/) with questions.
+
+## Revoked Iterations
+
+If an iteration is revoked, the `hcp-packer-iteration` data source will fail and Packer won't proceed with the build. Building new images from a revoked image is not compliant.
+Iterations that are scheduled to be revoked will still be considered valid until the revocation date.
+
+## Basic Example
+
+Below is a fully functioning example. It stores information about an image,
+which can then be parsed and accessed as a variable.
+
+```hcl
+data "hcp-packer-image" "example" {
+ bucket_name = "hardened-ubuntu-16-04"
+ iteration_id = "${data.hcp-packer-iteration.hardened-source.id}"
+ cloud_provider = "aws"
+ region = "us-east-1"
+}
+```
+
+## Full Example
+
+This data source can be used in conjunction with the hcp-packer-iteration
+data source to retrieve an image ID using a channel. You provide the channel
+name to the iteration data source, then use the iteration source in the image
+data source, then use the image data source inside your source block.
+
+```hcl
+# Retrieves information about the HCP Packer "iteration"; an "iteration" can be
+# thought of as all the metadata created by a single call of `packer build`.
+data "hcp-packer-iteration" "hardened-source" {
+ bucket_name = "hardened-ubuntu-16-04"
+ channel = "packer-test"
+}
+
+# Retrieves information about the HCP Packer "image"; an image can be thought
+# of as all the metadata (including the artifact names) created by a single
+# "source" builder; this can include multiple images so we provide a cloud
+# region to disambiguate.
+data "hcp-packer-image" "foo" {
+ bucket_name = "hardened-ubuntu-16-04"
+ iteration_id = data.hcp-packer-iteration.hardened-source.id
+ cloud_provider = "aws"
+ region = "us-east-1"
+}
+
+# This source uses the output from a previous Packer build. By using the
+# HCP Packer registry in this way, you can easily create build pipelines where
+# a single base image can be customized in multiple secondary layers.
+source "amazon-ebs" "packer-secondary" {
+ source_ami = data.hcp-packer-image.foo.id
+ # ...
+}
+```
+
+## Configuration Reference
+
+Configuration options are organized below into two categories: required and
+optional. Within each category, the available options are alphabetized and
+described.
+
+### Required:
+
+@include 'datasource/hcp-packer-image/Config-required.mdx'
+
+### Optional:
+
+~> **Note:** This data source only returns the first found image's metadata filtered by the given options, from the returned list of images associated with the specified iteration. Therefore, if multiple images exist in the same region, it will only pick one of them. In this case, you can filter images by a source build name (Ex: `amazon-ebs.example`) using the `component_type` option.
+
+@include 'datasource/hcp-packer-image/Config-not-required.mdx'
+
+### Output Fields:
+
+@include 'datasource/hcp-packer-image/DatasourceOutput.mdx'
diff --git a/v1.9.4/website/content/docs/datasources/hcp/hcp-packer-iteration.mdx b/v1.9.4/website/content/docs/datasources/hcp/hcp-packer-iteration.mdx
new file mode 100644
index 0000000..38c6125
--- /dev/null
+++ b/v1.9.4/website/content/docs/datasources/hcp/hcp-packer-iteration.mdx
@@ -0,0 +1,93 @@
+---
+description: |
+ The HCP Packer Iteration Data Source retrieves information about an
+ iteration from the HCP Packer registry. This information can be used to
+ query HCP for a source image for various Packer builders.
+page_title: HCP Packer Iteration - Data Sources
+---
+
+<BadgesHeader>
+ <PluginBadge type="official" />
+ <PluginBadge type="hcp_packer_ready" />
+</BadgesHeader>
+
+# HCP Packer Iteration Data Source
+
+Type: `hcp-packer-iteration`
+
+The `HCP Packer Iteration` Data Source retrieves information about an
+iteration from the HCP Packer registry. This information can be used to query
+HCP for a source image for various Packer builders.
+
+To get started with HCP Packer, refer to the [HCP Packer documentation](/hcp/docs/packer) or try the [Get Started with HCP Packer tutorials](/packer/tutorials/hcp-get-started).
+
+~> **Note:** You will receive an error if you try to reference metadata from a deactivated or deleted registry. An administrator can manually deactivate or delete a registry, and HCP Packer automatically deactivates registries with billing issues. Contact [HashiCorp Support](https://support.hashicorp.com/) with questions.
+
+## Revoked Iterations
+
+If an iteration is revoked, the `hcp-packer-iteration` data source will fail and Packer won't proceed with the build. Building new images from a revoked image is not compliant.
+Iterations that are scheduled to be revoked will still be considered valid until the revocation date.
+
+## Basic Example
+
+Below is a fully functioning example. It stores information about an image
+iteration, which can then be accessed as a variable.
+
+```hcl
+data "hcp-packer-iteration" "hardened-source" {
+ bucket_name = "hardened-ubuntu-16-04"
+ channel = "packer-test"
+}
+```
+
+## Full Example
+
+This data source can be used in conjunction with the hcp-packer-image
+data source to retrieve an image ID using a channel. You provide the channel
+name to the iteration data source, then use the iteration source inside the
+image data source, then use the image data source inside your source block.
+
+```hcl
+# Retrieves information about the HCP Packer "iteration"; an "iteration" can be
+# thought of as all the metadata created by a single call of `packer build`.
+data "hcp-packer-iteration" "hardened-source" {
+ bucket_name = "hardened-ubuntu-16-04"
+ channel = "packer-test"
+}
+
+# Retrieves information about the HCP Packer "image"; an image can be thought
+# of as all the metadata (including the artifact names) created by a single
+# "source" builder; this can include multiple images so we provide a cloud
+# region to disambiguate.
+data "hcp-packer-image" "foo" {
+ bucket_name = "hardened-ubuntu-16-04"
+ iteration_id = data.hcp-packer-iteration.hardened-source.id
+ cloud_provider = "aws"
+ region = "us-east-1"
+}
+
+# This source uses the output from a previous Packer build. By using the
+# HCP Packer registry in this way, you can easily create build pipelines where
+# a single base image can be customized in multiple secondary layers.
+source "amazon-ebs" "packer-secondary" {
+ source_ami = data.hcp-packer-image.foo.id
+ ...
+}
+```
+
+## Configuration Reference
+
+Configuration options are organized below into two categories: required and
+optional. Within each category, the available options are alphabetized and
+described.
+
+### Required:
+
+@include 'datasource/hcp-packer-iteration/Config-required.mdx'
+
+There are currently no optional fields for this datasource, though we intend
+to add filtering fields in the future.
+
+### Output Fields:
+
+@include 'datasource/hcp-packer-iteration/DatasourceOutput.mdx'
diff --git a/v1.9.4/website/content/docs/datasources/hcp/index.mdx b/v1.9.4/website/content/docs/datasources/hcp/index.mdx
new file mode 100644
index 0000000..989d3d8
--- /dev/null
+++ b/v1.9.4/website/content/docs/datasources/hcp/index.mdx
@@ -0,0 +1,41 @@
+---
+description: |
+ Data sources used to data from the HCP Packer registry.
+page_title: HCP - Data sources
+sidebar_title: Overview
+---
+
+<BadgesHeader>
+ <PluginBadge type="official" />
+</BadgesHeader>
+
+# HCP Packer Registry Data sources
+
+The HCP Packer registry bridges the gap between image factories and image
+deployments, allowing development and security teams to work together to create,
+manage, and consume images in a centralized way.
+
+The HCP Packer registry stores metadata about your images, including when they
+were created, where the image exists in the cloud, and what (if any) git commit
+is associated with your image build. You can use the registry to track
+information about the golden images your Packer builds produce, clearly
+designate which images are appropriate for test and production environments,
+and query for the right golden images to use in both Packer and Terraform
+configurations.
+
+Packer has two data sources that work together to retrieve information from the
+HCP Packer registry:
+
+- [hcp-packer-iteration](/packer/docs/datasources/hcp/hcp-packer-iteration) -
+ retrieves information about an iteration in HCP Packer registry
+- [hcp-packer-image](/packer/docs/datasources/hcp/hcp-packer-image) - retrieves
+ information about a specific image created in the HCP Packer registry
+
+These data sources are intended to be used together to determine source images
+for pipelined Packer builds.
+
+## How to use this plugin
+
+This plugin comes bundled with the Packer core, so you do not need to install
+it separately. Please install Packer v1.7.7 or above to use the latest version
+of the HCP Packer registry datasources.
diff --git a/v1.9.4/website/content/docs/datasources/http.mdx b/v1.9.4/website/content/docs/datasources/http.mdx
new file mode 100644
index 0000000..f11e5c6
--- /dev/null
+++ b/v1.9.4/website/content/docs/datasources/http.mdx
@@ -0,0 +1,50 @@
+---
+description: |
+ The HTTP Data Source retrieves information from an HTTP endpoint to be used
+ during Packer builds
+page_title: HTTP - Data Sources
+---
+
+<BadgesHeader>
+ <PluginBadge type="official" />
+ <PluginBadge type="hcp_packer_ready" />
+</BadgesHeader>
+
+# HTTP Data Source
+
+Type: `http`
+
+The `http` data source makes an HTTP GET request to the given URL and exports information about the response.
+
+
+## Basic Example
+
+```hcl
+data "http" "example" {
+ url = "https://checkpoint-api.hashicorp.com/v1/check/terraform"
+
+ # Optional request headers
+ request_headers = {
+ Accept = "application/json"
+ }
+}
+```
+
+## Configuration Reference
+
+Configuration options are organized below into two categories: required and
+optional. Within each category, the available options are alphabetized and
+described.
+
+### Required:
+
+@include 'datasource/http/Config-required.mdx'
+
+### Not Required:
+@include 'datasource/http/Config-not-required.mdx'
+
+## Datasource outputs
+
+The outputs for this datasource are as follows:
+
+@include 'datasource/http/DatasourceOutput.mdx'
diff --git a/v1.9.4/website/content/docs/datasources/index.mdx b/v1.9.4/website/content/docs/datasources/index.mdx
new file mode 100644
index 0000000..cf70bde
--- /dev/null
+++ b/v1.9.4/website/content/docs/datasources/index.mdx
@@ -0,0 +1,15 @@
+---
+description: |
+ Data sources allow data to be fetched for use in Packer configuration. Use of data sources
+ allows a build to use information defined outside of Packer.
+page_title: Data Sources
+---
+
+# Data Sources
+
+Data sources let Packer fetch data to use in a template, including information defined outside of Packer.
+
+Refer to the [`data`](/packer/docs/templates/hcl_templates/datasources) block documentation to learn more about working with data sources. The documentation also contains details about each type of data source.
+
+-> **Note:** Data sources is a feature exclusively available to HCL2 templates included in Packer `v1.7.0` (and newer).
+
diff --git a/v1.9.4/website/content/docs/debugging.mdx b/v1.9.4/website/content/docs/debugging.mdx
new file mode 100644
index 0000000..0adad6c
--- /dev/null
+++ b/v1.9.4/website/content/docs/debugging.mdx
@@ -0,0 +1,151 @@
+---
+description: |
+ Packer strives to be stable and bug-free, but issues inevitably arise where
+ certain things may not work entirely correctly, or may not appear to work
+ correctly.
+page_title: Debugging - Other
+---
+
+# Debugging Packer Builds
+
+Using `packer build -on-error=ask` allows you to inspect failures and try out
+solutions before restarting the build.
+
+For remote builds with cloud providers like Amazon Web Services AMIs, debugging
+a Packer build can be eased greatly with `packer build -debug`. This disables
+parallelization and enables debug mode.
+
+Debug mode informs the builders that they should output debugging information.
+The exact behavior of debug mode is left to the builder. In general, builders
+usually will stop between each step, waiting for keyboard input before
+continuing. This will allow you to inspect state and so on.
+
+In debug mode once the remote instance is instantiated, Packer will emit to the
+current directory an ephemeral private SSH key as a .pem file. Using that you
+can `ssh -i <key.pem>` into the remote build instance and see what is going on
+for debugging. The key will only be emitted for cloud-based builders. The
+ephemeral key will be deleted at the end of the Packer run during cleanup.
+
+For a local builder, the SSH session initiated will be visible in the detail
+provided when `PACKER_LOG=1` environment variable is set prior to a build, and
+you can connect to the local machine using the userid and password defined in
+the kickstart or preseed associated with initializing the local VM.
+
+It should be noted that one of the options `-on-error` is to `retry`, the retry
+of the step in question has limitations:
+
+- the template Packer is building is **not** reloaded from file.
+- the resources specified from builders **are** reloaded from file.
+
+Check the specifics on your builder to confirm their behavior.
+
+### Windows
+
+As of Packer 0.8.1 the default WinRM communicator will emit the password for a
+Remote Desktop Connection into your instance. This happens following the
+several minute pause as the instance is booted. Note a .pem key is still
+created for securely transmitting the password. Packer automatically decrypts
+the password for you in debug mode.
+
+## Debugging Packer
+
+Issues occasionally arise where certain things may not work entirely correctly,
+or may not appear to work correctly. In these cases, it is sometimes helpful to
+see more details about what Packer is actually doing.
+
+Packer has detailed logs which can be enabled by setting the `PACKER_LOG`
+environmental variable to any value but `""` (empty string) and `"0"` like this
+`PACKER_LOG=1 packer build <config.json>`. This will cause detailed logs to
+appear on stderr. The logs contain log messages from Packer as well as any
+plugins that are being used. Log messages from plugins are prefixed by their
+application name.
+
+Note that because Packer is highly parallelized, log messages sometimes appear
+out of order, especially with respect to plugins. In this case, it is important
+to pay attention to the timestamp of the log messages to determine order.
+
+In addition to simply enabling the log, you can set `PACKER_LOG_PATH` in order
+to force the log to always go to a specific file when logging is enabled. Note
+that even when `PACKER_LOG_PATH` is set, `PACKER_LOG` must be set in order for
+any logging to be enabled.
+
+### Debugging Plugins
+
+Each packer plugin runs in a separate process and communicates with RPC over a
+socket therefore using a debugger will not work (be complicated at least).
+
+But most of the Packer code is really simple and easy to follow with PACKER_LOG
+turned on. If that doesn't work adding some extra debug print outs when you have
+homed in on the problem is usually enough.
+
+### Debugging Packer in Powershell/Windows
+
+In Windows you can set the detailed logs environmental variable `PACKER_LOG` or
+the log variable `PACKER_LOG_PATH` using PowerShell environment variables. For
+example:
+
+```powershell
+$env:PACKER_LOG=1
+$env:PACKER_LOG_PATH="packerlog.txt"
+```
+
+If you find a bug with Packer, please include the detailed log by using a
+service such as [gist](https://gist.github.com).
+
+## Issues Installing Ubuntu Packages
+
+Issues may arise using and building Ubuntu AMIs where common packages that
+_should_ be installed from Ubuntu's Main repository are not found during a
+provisioner step:
+
+```text
+amazon-ebs: No candidate version found for build-essential
+amazon-ebs: No candidate version found for build-essential
+```
+
+This, obviously can cause problems where a build is unable to finish
+successfully as the proper packages cannot be provisioned correctly. The
+problem arises when cloud-init has not finished fully running on the source AMI
+by the time that packer starts any provisioning steps.
+
+Adding the following provisioner to the Packer template, allows for the
+cloud-init process to fully finish before packer starts provisioning the source
+AMI.
+
+```json
+{
+ "type": "shell",
+ "inline": [
+ "cloud-init status --wait"
+ ]
+}
+```
+
+## Issues when using numerous Builders/Provisioners/Post-Processors
+
+Packer uses a separate process for each builder, provisioner, post-processor,
+and plugin. In certain cases, if you have too many of these, you can run out of
+[file descriptors](https://en.wikipedia.org/wiki/File_descriptor). This results
+in an error that might look like
+
+```text
+error initializing provisioner 'powershell': fork/exec /files/go/bin/packer:
+too many open files
+```
+
+On Unix systems, you can check what your file descriptor limit is with
+`ulimit -Sn`. You should check with your OS vendor on how to raise this limit.
+
+## Issues when using long temp directory
+
+Packer uses Unix sockets internally, which are created inside the default
+directory for temporary files. Some operating systems place a limit on the
+length of the socket name, usually between 80 and 110 characters. If you get an
+error like this (for any builder, not just Docker):
+
+```text
+Failed to initialize build 'docker': error initializing builder 'docker': plugin exited before we could connect
+```
+
+you should try setting your temp directory to something shorter. This can be
+done through the `TMPDIR` environment variable.
diff --git a/v1.9.4/website/content/docs/hcp/index.mdx b/v1.9.4/website/content/docs/hcp/index.mdx
new file mode 100644
index 0000000..d908cca
--- /dev/null
+++ b/v1.9.4/website/content/docs/hcp/index.mdx
@@ -0,0 +1,72 @@
+---
+description: |
+ Packer can publish metadata for completed builds to an HCP Packer registry. Legacy JSON templates can connect to the registry using environment variables. HCL2 templates can connect using an hcp_packer_registry block.
+page_title: HCP Packer
+---
+
+-> **Note:** On May 16th 2023, HCP introduced multi-project support to the platform. In order to use multiple projects in your organization, you will need to update Packer to version 1.9.1 or above. Starting with 1.9.1, you may specify a project ID to push builds to with the `HCP_PROJECT_ID` environment variable. If no project ID is specified, Packer will pick the project with the oldest creation date. Older versions of Packer are incompatible with multi-project support on HCP, and builds will fail for HCP organizations with multiple projects on versions before 1.9.1.
+
+# HCP Packer
+
+The HCP Packer registry bridges the gap between image factories and image deployments, allowing development and security teams to work together to create, manage, and consume images in a centralized way.
+
+The HCP Packer registry stores metadata about your images, including when they were created, where the image exists in the cloud, and what (if any) git commit is associated with your image build. You can use the registry to track information about the golden images your Packer builds produce, clearly designate which images are appropriate for test and production environments, and query for the right golden images to use in both Packer and Terraform configurations.
+
+You can use HCP Packer with both JSON and HCL2 templates. If you are using JSON templates, we recommend getting started with
+the [HCP Packer environment variables](#hcp-packer-environment-variables) and then migrating to HCL when possible.
+
+This page summarizes the methods you can use to connect JSON and HCL2 templates to the HCP Packer registry. It also provides a full list of HCP Packer environment variables. Refer to the [Packer Template Configuration](/hcp/docs/packer/store-image-metadata/packer-template-configuration) page in the HCP Packer documentation for full configuration details and examples.
+
+### HCP Packer Environment Variables
+
+The following environment variables let you configure Packer to push image metadata to an active registry without changing your template. You can use environment variables with both JSON and HCL2 templates. Refer to [Basic Configuration With Environment Variables](/hcp/docs/packer/store-image-metadata/packer-template-configuration#basic-configuration-with-environment-variables) in the HCP Packer documentation for complete instructions and examples.
+
+You must set the following environment variables to enable Packer to push metadata to a registry.
+
+- `HCP_CLIENT_ID` - The HCP client ID of a HashiCorp Cloud Platform service principle that Packer can use to authenticate to an HCP Packer registry.
+
+- `HCP_CLIENT_SECRET` - The HCP client secret of the HashiCorp Cloud Platform service principle that Packer can use to authenticate to an HCP Packer registry.
+
+- `HCP_PACKER_BUCKET_NAME` - The name of the image bucket where you want HCP Packer to store image metadata from builds associated with your template. HCP Packer automatically creates the image bucket if it does not already exist. If your HCL2 template contains an `hcp_packer_registry` block, the bucket name specified in the configuration will be overwritten by this environment variable.
+
+You can set these additional environment variables to control how metadata is pushed to the registry.
+
+- `HCP_PACKER_BUILD_FINGERPRINT` - A unique identifier assigned to each iteration. To reuse a fingerprint that is associated with an existing incomplete iteration you must set this environment variable. Refer to [Iteration Fingerprinting](#iteration-fingerprinting) for usage details.
+
+- `HCP_PACKER_REGISTRY` - When set, Packer does not push image metadata to HCP Packer from an otherwise configured template. Allowed values are [0|OFF].
+
+- `HCP_ORGANIZATION_ID` - The ID of the HCP organization linked to your service principal. This is environment variable is not required and available for the sole purpose of keeping parity with the HCP SDK authentication options. Its use may change in a future release.
+
+- `HCP_PROJECT_ID` - The ID of the HCP project to use. This is useful if your service principal has access to multiple projects, as by default Packer will pick the one created first as target.
+
+-> **Note**: The HCP_PROJECT_ID environment variable must be set if you're authenticating with a project-level service principal, otherwise Packer will attempt to get the list of projects for an organization and error due to a lack of permissions for a project-level service principal. This is supported starting with Packer 1.9.3; older versions of Packer do not support using project-level service principals.
+
+### HCP Packer Registry Block
+
+The only metadata that Packer can infer from a template with the basic configuration are the build name and build fingerprint. For HCL2 templates, we recommend adding the `hcp_packer_registry` block to your template so that you can customize the metadata that Packer sends to the registry.
+
+The `hcp_packer_registry` block is only available for HCL2 Packer templates. There is no [`PACKER_CONFIG`](/packer/docs/configure#packer-s-config-file) equivalent for JSON.
+
+Refer to [`hcp_packer_registry`](/packer/docs/templates/hcl_templates/blocks/build/hcp_packer_registry) for a full list of configuration arguments. Refer to [Custom Configuration](/hcp/docs/packer/store-image-metadata/packer-template-configuration#custom-configuration) in the HCP Packer documentation for information and examples about how to customize image metadata.
+
+### Iteration Fingerprinting
+
+Packer uses a unique fingerprint for tracking the completion of builds associated to an iteration. By default a fingerprint is automatically generated by Packer during each invocation of `packer build`, unless a fingerprint is manually provided via the `HCP_PACKER_BUILD_FINGERPRINT` environment variable.
+
+In versions before 1.9.0, this fingerprint was computed from the Git SHA of the current HEAD in which your template is stored. If you were running builds using a non Git managed template, you had to set the `HCP_PACKER_BUILD_FINGERPRINT` environment variable prior to invoking `packer build`.
+Starting with Packer 1.9.0, fingerprint generation does not rely on Git at all, and instead Packer now generates a Unique Lexicographically sortable Identifier (ULID) as the fingerprint for every `packer build` invocation.
+
+#### Fingerprints and Incomplete Iterations
+
+When you build a template with Packer, there's always a chance that it does not succeed because of a network issue, a provisioning failure, or some upstream error. When that happens, Packer will output the generated fingerprint associated with the incomplete iteration so that you can resume building that iteration using the `HCP_PACKER_BUILD_FINGERPRINT` environment variable; an iteration can be resumed until it is marked as complete. This environment variable is necessary for resuming an incomplete iteration, otherwise Packer will create a new iteration for the build.
+
+There are two alternatives for when and how to set your own fingerprint:
+
+* You can set it prior to invoking `packer build` for the first time on this template. This will require the fingerprint to be unique, otherwise Packer will attempt to continue the iteration with the same fingerprint.
+* You can invoke `packer build` on the template, and if it fails, you can then get the fingerprint from the output of the command and set it for subsequent runs, Packer will then continue building this iteration.
+
+The first alternative is recommended for CI environments, as you can use environment variables from the CI to generate a unique, deterministic, fingerprint, and then re-use this in case the step fails for any reason. This will let you continue building the same iteration, rather than creating a new one on each invocation.
+
+The second alternative is good for local builds, as you can interact with the build environment directly, and therefore can decide if you want to continue building an iteration by setting the fingerprint provided by Packer in case of failure.
+
+Please note that in all cases, an iteration can only be continued if it has not completed yet. Once an iteration is complete, it cannot be modified, and you will have to create a new one.
diff --git a/v1.9.4/website/content/docs/index.mdx b/v1.9.4/website/content/docs/index.mdx
new file mode 100644
index 0000000..ad32aa8
--- /dev/null
+++ b/v1.9.4/website/content/docs/index.mdx
@@ -0,0 +1,17 @@
+---
+description: |
+ Packer allows you to create identical machine images for multiple platforms from a single source template.
+page_title: Documentation
+---
+
+# Packer Documentation
+
+[Packer](https://www.packer.io/) is an open source tool that enables you to create identical machine images for multiple platforms from a single source template. A common use case is creating "golden images" that teams across an organization can use in cloud infrastructure.
+
+To install Packer and learn the standard Packer workflow, try the [Get Started tutorials](/packer/tutorials).
+
+## HCP Packer
+
+The HCP Packer registry stores metadata about your images. You can use the registry to track information about golden images from your Packer builds, clearly designate which images are appropriate for test and production environments, and query for the right images to use in both Packer and Terraform configurations.
+
+To get started, visit the [HCP Packer documentation](/hcp/docs/packer) or try the [Get Started with HCP Packer tutorials](/packer/tutorials/hcp-get-started).
diff --git a/v1.9.4/website/content/docs/install.mdx b/v1.9.4/website/content/docs/install.mdx
new file mode 100644
index 0000000..548049d
--- /dev/null
+++ b/v1.9.4/website/content/docs/install.mdx
@@ -0,0 +1,13 @@
+---
+description: |
+ Installing Packer is simple. You can download a precompiled binary or compile
+ from source. This page details both methods.
+page_title: Install
+---
+
+# Install Packer
+
+For detailed instructions on how to install Packer, see [this
+Getting Started guide][install].
+
+[install]: /packer/tutorials/docker-get-started/get-started-install-cli 'Install Packer'
diff --git a/v1.9.4/website/content/docs/intro/index.mdx b/v1.9.4/website/content/docs/intro/index.mdx
new file mode 100644
index 0000000..99f8175
--- /dev/null
+++ b/v1.9.4/website/content/docs/intro/index.mdx
@@ -0,0 +1,31 @@
+---
+page_title: Introduction
+description: |-
+ Welcome to the world of Packer! This introduction guide will show you what
+ Packer is, explain why it exists, the benefits it has to offer, and how you
+ can get started with it. If you're already familiar with Packer, the
+ documentation provides more of a reference for all available features.
+---
+
+# Introduction to Packer
+
+Welcome to the world of Packer! This introduction guide will show you what
+Packer is, explain why it exists, the benefits it has to offer, and how you can
+get started with it. If you're already familiar with Packer, the
+[documentation](/packer/docs) provides more of a reference for all available
+features.
+
+## What is Packer?
+
+Packer is an open source tool for creating identical machine images for multiple
+platforms 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 does not replace configuration
+management like Chef or Puppet. In fact, when building images, Packer is able to
+use tools like Chef or Puppet to install software onto the image.
+
+A _machine image_ is a single static unit that contains a pre-configured
+operating system and installed software which is used to quickly create new
+running machines. Machine image formats change for each platform. Some examples
+include [AMIs](https://en.wikipedia.org/wiki/Amazon_Machine_Image) for EC2,
+VMDK/VMX files for VMware, OVF exports for VirtualBox, etc.
diff --git a/v1.9.4/website/content/docs/intro/use-cases.mdx b/v1.9.4/website/content/docs/intro/use-cases.mdx
new file mode 100644
index 0000000..e6e3c63
--- /dev/null
+++ b/v1.9.4/website/content/docs/intro/use-cases.mdx
@@ -0,0 +1,54 @@
+---
+page_title: Use Cases - Introduction
+description: |-
+ By now you should know what Packer does and what the benefits of image
+ creation are. In this section, we'll enumerate *some* of the use cases for
+ Packer. Note that this is not an exhaustive list by any means. There are
+ definitely use cases for Packer not listed here. This list is just meant to
+ give you an idea of how Packer may improve your processes.
+---
+
+# Use Cases
+
+By now you should know what Packer does and what the benefits of image creation
+are. In this section, we'll enumerate _some_ of the use cases for Packer. Note
+that this is not an exhaustive list by any means. There are definitely use cases
+for Packer not listed here. This list is just meant to give you an idea of how
+Packer may improve your processes.
+
+### Continuous Delivery
+
+Packer is lightweight, portable, and command-line driven. This makes it the
+perfect tool to put in the middle of your continuous delivery pipeline. Packer
+can be used to generate new machine images for multiple platforms on every
+change to Chef/Puppet.
+
+As part of this pipeline, the newly created images can then be launched and
+tested, verifying the infrastructure changes work. If the tests pass, you can be
+confident that the image will work when deployed. This brings a new level of
+stability and testability to infrastructure changes.
+
+### Dev/Prod Parity
+
+Packer helps [keep development, staging, and production as similar as
+possible](http://www.12factor.net/dev-prod-parity). Packer can be used to
+generate images for multiple platforms at the same time. So if you use AWS for
+production and VMware (perhaps with [Vagrant](https://www.vagrantup.com/)) for
+development, you can generate both an AMI and a VMware machine using Packer at
+the same time from the same template.
+
+Mix this in with the continuous delivery use case above, and you have a pretty
+slick system for consistent work environments from development all the way
+through to production.
+
+### Appliance/Demo Creation
+
+Since Packer creates consistent images for multiple platforms in parallel, it is
+perfect for creating
+[appliances](https://en.wikipedia.org/wiki/Software_appliance) and disposable
+product demos. As your software changes, you can automatically create appliances
+with the software pre-installed. Potential users can then get started with your
+software by deploying it to the environment of their choice.
+
+Packaging up software with complex requirements has never been so easy. Or
+enjoyable, if you ask me.
diff --git a/v1.9.4/website/content/docs/intro/why.mdx b/v1.9.4/website/content/docs/intro/why.mdx
new file mode 100644
index 0000000..ff8a317
--- /dev/null
+++ b/v1.9.4/website/content/docs/intro/why.mdx
@@ -0,0 +1,55 @@
+---
+page_title: Why Packer - Introduction
+description: |-
+ Pre-baked machine images have a lot of advantages, but most have been unable
+ to benefit from them because images have been too tedious to create and
+ manage. There were either no existing tools to automate the creation of
+ machine images or they had too high of a learning curve. The result is that,
+ prior to Packer, creating machine images threatened the agility of operations
+ teams, and therefore aren't used, despite the massive benefits.
+---
+
+# Why Use Packer?
+
+Pre-baked machine images have a lot of advantages, but most have been unable to
+benefit from them because images have been too tedious to create and manage.
+There were either no existing tools to automate the creation of machine images
+or they had too high of a learning curve. The result is that, prior to Packer,
+creating machine images threatened the agility of operations teams, and
+therefore aren't used, despite the massive benefits.
+
+Packer changes all of this. Packer automates the creation of
+any type of machine image. It embraces modern configuration management by
+encouraging you to use a framework such as Chef or Puppet to install and
+configure the software within your Packer-made images.
+
+In other words: Packer brings pre-baked images into the modern age, unlocking
+untapped potential and opening new opportunities.
+
+## Advantages of Using Packer
+
+**_Super fast infrastructure deployment_**. Packer images allow you to launch
+completely provisioned and configured machines in seconds, rather than several
+minutes or hours. This benefits not only production, but development as well,
+since development virtual machines can also be launched in seconds, without
+waiting for a typically much longer provisioning time.
+
+**_Multi-provider portability_**. Because Packer creates identical images for
+multiple platforms, you can run production in AWS, staging/QA in a private cloud
+like OpenStack, and development in desktop virtualization solutions such as
+VMware or VirtualBox. Each environment is running an identical machine image,
+giving ultimate portability.
+
+**_Improved stability_**. Packer installs and configures all the software for a
+machine at the time the image is built. If there are bugs in these scripts,
+they'll be caught early, rather than several minutes after a machine is
+launched.
+
+**_Greater testability_**. After a machine image is built, that machine image
+can be quickly launched and smoke tested to verify that things appear to be
+working. If they are, you can be confident that any other machines launched from
+that image will function properly.
+
+Packer makes it extremely easy to take advantage of all these benefits.
+
+What are you waiting for? Let's get started!
diff --git a/v1.9.4/website/content/docs/partnerships.mdx b/v1.9.4/website/content/docs/partnerships.mdx
new file mode 100644
index 0000000..2e87dfd
--- /dev/null
+++ b/v1.9.4/website/content/docs/partnerships.mdx
@@ -0,0 +1,147 @@
+---
+description: |
+ The HashiCorp Packer Integration Program allows vendors to integrate
+ their products to work with Packer.
+page_title: Integration Program
+---
+
+# Packer Integration Program
+
+The HashiCorp Packer Integration Program allows vendors to integrate their products to work with Packer.
+
+Vendors integrating their solutions via the Packer Integration Process provide their customers a verified and seamless user experience. The Packer Integration Program currently only supports coding with the Go programming language.
+
+This program is intended to be largely a self-service process with links and guidance to information sources, clearly defined steps, and checkpoints.
+
+### Types of Packer Integrations
+
+Packer is an open source tool for creating identical machine images for multiple platforms 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 does not replace configuration management like Chef or Puppet. In fact, when building images, Packer is able to use tools like Chef or Puppet to install software onto the image.
+
+A machine image is a single static unit that contains a pre-configured operating system and installed software which is used to quickly create new running machines. Machine image formats change for each platform. Some examples include AMIs for EC2, VMDK/VMX files for VMware, OVF exports for VirtualBox, etc. To know more about use cases of Packer click ([Use Cases - Introduction | Packer by HashiCorp](/packer/docs/intro/use-cases))
+
+The diagram below depicts the key Packer integration categories and types.
+
+<ImageConfig width={460} caption="Packer Ecosystem Integration Diagram">
+
+![Packer Ecosystem Integration Diagram](/img/docs/packer-ecosystem-diagram.png)
+
+</ImageConfig>
+
+Main Packer categories for partners to integrate with include:
+
+- **Data Sources**
+ - Data Sources allow users to retrieve values from a remote API and store them as variables in the Packer configuration template. An example is the [AWS secrets manager](/packer/plugins/datasources/amazon/secretsmanager) data source.
+- **Builders**
+ - Builders manage the VM lifecycle. They manage launching a VM/instance, running provisioners against that instance, shutting the instance down, and saving an artifact image from that instance. Your builder handles all of the setup and cleanup costs associated with creating the output image artifact.
+- **Provisioners**
+ - Provisioners are run against the instance launched by the builder. They generally provide an interface for interacting with a particular provisioning tool, such as Ansible, Puppet, or Chef.
+- **Post-Processors**
+ - Post-Processors manage the image artifact after it has been created. This can be something general like running a compression tool against the artifact, or something specific like uploading it to a particular cloud service.
+
+### Development Process
+
+The Packer integration development process is divided into six steps. By following these steps, Packer integrations can be developed alongside HashiCorp to ensure that the integrations are able to be verified and supported in Packer as quickly as possible. A visual representation of the self-guided steps is depicted below.
+
+![Packer Integration Program Steps](/img/docs/packer-integration-steps-diagram.png 'Packer Integration Program Steps')
+
+The individual Packer integration steps include:
+
+1. Engage: Initial contact between vendor and HashiCorp
+1. Enable: Information and articles to aid with the development of the integration
+1. Dev/Test: Integration development and test process
+1. Review: HashiCorp code review and verification of integration (iterative process)
+1. Release: Verified integration made available and listed on the HashiCorp website once the HashiCorp technology partnership agreement has been executed
+1. Support: Ongoing maintenance and support of the provider by the vendor.
+
+#### 1. Engage
+
+Please begin by providing some basic information about the integration that is being built via a simple [webform](https://docs.google.com/forms/d/e/1FAIpQLSfgq3HJ9Rfsi7LgPLFln28ZrmarATGlD_6A47-Io-bPUftKUw/viewform)
+
+This information is recorded and used by HashiCorp to track the integration through various stages. The information is also used to notify the integration developer of any overlapping work, perhaps coming from the community so you may better focus resources.
+
+Packer has an active community and ecosystem of partners that may have already started working on a similar integration. We'll do our best to connect similar parties to avoid duplicate work.
+
+#### 2. Enable
+
+While not mandatory, HashiCorp encourages vendors to sign an MNDA (Mutual Non-Disclosure Agreement) to allow for open dialog and sharing of ideas during the integration process.
+
+In an effort to support our self-serve model we’ve included links to resources, documentation, examples and best practices to guide you through the Packer integration development and testing process.
+
+- [Writing vendor extension guide](/packer/docs/plugins/creation)
+- Sample development implemented by a [partner](https://github.com/exoscale/packer-plugin-exoscale)
+- [Scaffolding plugin repository](https://github.com/hashicorp/packer-plugin-scaffolding) to help bootstrap a new contribution:
+- Contributing to Packer [guidelines](https://github.com/hashicorp/packer/blob/main/.github/CONTRIBUTING.md)
+- [Packer developer community forum](https://discuss.hashicorp.com/c/packer/23)
+- [Packer's source code](https://github.com/hashicorp/packer)
+
+We encourage vendors to closely follow the above guidance. Adopting the same structure and coding patterns helps expedite the review and release cycles.
+
+#### 3. Dev & Test
+
+Packer requires all code-level integrations to be written in the [Go](https://go.dev/) programming language and contain an [MPL-2.0](https://en.wikipedia.org/wiki/Mozilla_Public_License) open source license. The only knowledge necessary to write a plugin is basic command-line skills and knowledge of the Go programming language. When writing in Go, HashiCorp has found the integration development process to be straightforward and simple when vendors pay close attention and follow the resources and by adopting the same structure and coding patterns helps expedite the review and release cycles. Please remember that all integration major steps should contain acceptance testing and the appropriate documentation.
+
+Data Sources
+
+- [Custom Data Sources documentation](/packer/docs/plugins/creation/custom-datasources)
+- [Example Data Source](https://github.com/hashicorp/packer-plugin-hashicups/tree/main/datasource)
+
+Builders
+
+- [Custom Builders documentation](/packer/docs/plugins/creation/custom-builders)
+- [Example Builder](https://github.com/hashicorp/packer-plugin-hashicups/tree/main/builder/order)
+
+Provisioners
+
+- [Custom Provisioners documentation](/packer/docs/plugins/creation/custom-provisioners)
+- [Example Provisioner](https://github.com/hashicorp/packer-plugin-hashicups/tree/main/provisioner/toppings)
+
+Post-Processors
+
+- [Custom Post-Processors documentation](/packer/docs/plugins/creation/custom-post-processors)
+- [Example Post-Processor](https://github.com/hashicorp/packer-plugin-hashicups/tree/main/post-processor/receipt)
+
+Packer-Plugin-SDK
+
+- The [Packer-plugin SDK](https://github.com/hashicorp/packer-plugin-sdk) contains tools to help plugin developers with common needs, like handling SSH connections or basic plugin architecture.
+
+#### 4. Review
+
+During the review process, HashiCorp will provide feedback on the newly developed integration. This is an important step to allow HashiCorp to review and verify your Packer integration. Please send the integration code and other relevant logs for verification to: [Packer-integration-dev@hashicorp.com](mailto:packer-integration-dev@hashicorp.com).
+
+In order to document your plugins with Packer, please submit a GitHub pull request (PR) against the [Packer project](https://github.com/hashicorp/packer). See [Registering Plugin Documentation](/packer/docs/plugins/creation#registering-plugin-documentation) for instructions on how to register your remote plugin documentation with Packer.
+The review process can take a while to complete and may require some iterations through the code to address any problems identified by the HashiCorp team.
+
+#### 5. Release
+
+At this stage, it is expected that the integration is fully complete, the necessary documentation has been written, the acceptance tests have all passed, and that HashiCorp has reviewed the integration. Once the plugin has been validated and accepted by HashiCorp, the plugin can be hosted on GitHub so it can easily be [downloaded then installed within Packer](/packer/docs/plugins/creation#creating-a-github-release).
+
+Once the integration has been released the vendor is requested to sign the HashiCorp Technology Partner Agreement so that we can have their integration be listed on the HashiCorp website.
+
+#### 6. Support
+
+Many vendors view the release step to be the end of the journey, while at HashiCorp we view it to be the beginning of the journey. Getting the integration built is just the first step in enabling users to leverage it against their infrastructure. Once development is completed, on-going effort is required to support the developed integration, maintain the plugin and address any issues in a timely manner.
+
+The expectation from the vendor/partner is to create a mechanism for them to track and resolve all issues on an ongoing basis. Vendors who choose to not support their integration will not be considered a verified integration and cannot be listed on the website.
+
+### Checklist
+
+Below is an ordered checklist of steps that should be followed during the integration process. This just reiterates the steps already documented in the sections above.
+
+<Checklist>
+
+- Fill out the Packer integration [webform](https://docs.google.com/forms/d/e/1FAIpQLSfgq3HJ9Rfsi7LgPLFln28ZrmarATGlD_6A47-Io-bPUftKUw/viewform)
+- Execute the HashiCorp MNDA (Mutual Non-Disclosure Agreement) if needed
+- Develop and test Packer integration along with the acceptance tests and documentation
+- Send email to [packer-integration-dev@hashicorp.com](mailto:packer-integration-dev@hashicorp.com) to schedule an initial review
+- Address review feedback and finalize the development process
+- Provide HashiCorp with credentials for underlying infrastructure for test purposes
+- Demo the integration and/or send the test logs to HashiCorp at: [packer-integration-dev@hashicorp.com](mailto:packer-integration-dev@hashicorp.com)
+- Execute HashiCorp Partner Agreement Documents, review logo guidelines, partner listing and more
+- Plan to continue supporting the integration with additional functionality and responding to customer issues.
+
+</Checklist>
+
+### Contact Us
+
+For any questions or feedback, please contact us at: packer-integration-dev@hashicorp.com.
diff --git a/v1.9.4/website/content/docs/plugins/creation/custom-builders.mdx b/v1.9.4/website/content/docs/plugins/creation/custom-builders.mdx
new file mode 100644
index 0000000..efad53a
--- /dev/null
+++ b/v1.9.4/website/content/docs/plugins/creation/custom-builders.mdx
@@ -0,0 +1,310 @@
+---
+description: |
+ It is possible to write custom builders using the Packer plugin interface, and
+ this page documents how to do that.
+page_title: Custom Builders - Extending
+---
+
+# Custom Builders
+
+Packer builders are responsible for creating a virtual machine, setting the virtual machine up for provisioning, and then turning that provisioned virtual machine into a machine image. We officially maintain and distribute several builders, including builders to create images on Amazon EC2, VMware, Google
+Compute Engine, and many more. Refer to the [Builders](/packer/docs/builders) documentation for details.
+
+This page explains how to use the Packer plugin interface to write custom builders. If you want your builder to support HashiCorp Cloud Platform (HCP) Packer, you should also review the [HCP Packer Support](/packer/docs/plugins/creation/hcp-support) documentation.
+
+~> **Warning:** This is an advanced topic that requires strong knowledge of Packer and Packer plugins.
+
+## Before You Begin
+
+We recommend reviewing the following resources before you begin development:
+
+- [Developing Plugins - Overview](/packer/docs/plugins/creation)
+- The [Go](https://go.dev/) language. You must write custom plugins in Go, so this guide assumes you are familiar with the language.
+
+## The Interface
+
+To create your own builder, you must create a struct that implements the
+[`packer.Builder`](https://pkg.go.dev/github.com/hashicorp/packer-plugin-sdk/packer#Builder) interface. It is reproduced below for reference.
+
+```go
+type Builder interface {
+ ConfigSpec() hcldec.ObjectSpec
+ Prepare(...interface{}) ([]string, []string, error)
+ Run(context.Context, ui Ui, hook Hook) (Artifact, error)
+}
+```
+
+### The "ConfigSpec" Method
+
+This method returns a hcldec.ObjectSpec, which is a spec necessary for using
+HCL2 templates with Packer. For information on how to use and implement this
+function, check our
+[object spec docs](/packer/guides/hcl/component-object-spec)
+
+### The "Prepare" Method
+
+The `Prepare` method for each builder will be called by the Packer core
+at the beginning of the build. Its purpose is to parse and validate the
+configuration template provided to Packer with `packer build your_packer_template.json`, but not to execute API calls or begin creating any
+resources or artifacts.
+
+The configuration from your Packer template is passed into the Prepare() method
+as an array of `interface{}` types, but is generally `map[string]interface{}`.
+The Prepare method is responsible for translating this configuration into an
+internal structure, validating it, and returning any errors.
+
+If multiple parameters are passed into Prepare(), they should be merged together
+into the final configuration, with later parameters overwriting any previous
+configuration. The exact semantics of the merge are left to the builder author.
+
+We recommend that you use the
+[mapstructure](https://godoc.org/github.com/mitchellh/mapstructure) library to
+decode the interface{} into a meaningful structure. Mapstructure will take an
+`interface{}` and decode it into an arbitrarily complex struct. If there are any
+errors, it generates very human friendly errors that can be returned directly
+from the prepare method. You can find many usage examples of this library within
+the Prepare() methods of HashiCorp-maintained Packer plugins.
+
+While Packer does not actively enforce this, **no side effects** should occur
+from running the `Prepare` method. Specifically: don't create files, don't
+launch virtual machines, etc. Prepare's purpose is solely to load the
+configuration from the template into a format usable by your builder, to
+validate that configuration, and to apply necessary defaults to that
+configuration.
+
+In addition to the configuration provided in the Packer template, Packer will
+also supply a [common.PackerConfig](https://github.com/hashicorp/packer-plugin-sdk/blob/8a28198491f70deca3824ce452adf6f9bd507880/common/packer_config.go#L44)
+containing meta-information such as the build name, builder type, core version,
+etc, and coded into a `map[string]interface{}`. One important piece of
+meta information in this map is the `packer.DebugConfigKey` set to boolean
+`true` if debug mode is enabled for the build. If this is set to true, then the
+builder should enable a debug mode which assists builder developers and
+advanced users to introspect what is going on during a build. During debug
+builds, parallelism is strictly disabled, so it is safe to request input from
+stdin and so on.
+
+Prepare() returns an array of strings and an error. The array of strings is a
+special list of keys for variables created at runtime which your builder will
+make accessible to provisioners using the generatedData mechanism (see below for
+more details) An example could be an instance ID for the cloud instance created
+by your builder. If you do not plan to make use of the generatedData feature,
+just return an empty list. The error should be used if there is something wrong
+with the user-provided configuration and the build should not proceed.
+
+### The "Run" Method
+
+`Run` is executed, often in parallel for multiple builders, to actually build
+the machine, provision it, and create the resulting machine image, which is
+returned as an implementation of the `packer.Artifact` interface.
+
+The `Run` method takes three parameters. The context.Context used to cancel the
+build. The `packer.Ui` object is used to send output to the console.
+`packer.Hook` is used to execute hooks, which are covered in more detail in the
+Provisioning section below.
+
+Because builder runs are typically a complex set of many steps, the
+packer-plugin-sdk contains a
+[multistep](https://godoc.org/github.com/hashicorp/packer-plugin-sdk/multistep)
+module. Multistep allows you to separate your build logic into multiple distinct
+"steps" with separate run and cleanup phases, and run them in order. It
+supports cancellation mid-step, pausing between steps when debugging, the CLI's
+on-error flag, and more. All of the HashiCorp maintained builders make use of
+this module, and while it is not required for builder implementation, it will
+help you create your builder in a way that matches user and Packer Core
+assumptions. The SDK also provides a number of "helper" generic steps that may
+prevent you from having to re-implement work that has already been done by the
+HashiCorp maintainers. Examples include sending boot commands, connecting to
+SSH, and creating virtual CDs to mount on your VM. Take a look at the
+[communicator](https://github.com/hashicorp/packer-plugin-sdk/tree/main/communicator)
+and
+[multistep/commonsteps](https://github.com/hashicorp/packer-plugin-sdk/tree/main/multistep/commonsteps)
+modules in the SDK to see what tools are available to you.
+
+Finally, `Run` should return an implementation of `packer.Artifact`. More
+details on creating a `packer.Artifact` are covered in the artifact section
+below. If something goes wrong during the build that prevents an artifact from
+being correctly created, `Run` should return an error and a nil artifact. Note
+that your builder is allowed to produce no artifact and no error, although this
+is a rare use case.
+
+### Cancellation
+
+#### With the "Cancel" Method ( for plugins for Packer < v1.3 )
+
+The `Cancel` method can be called at any time and requests cancellation of any
+builder run in progress. This method should block until the run actually stops.
+Note that the Cancel method will not be called by Packer versions >= 1.4.0.
+
+#### Context cancellation ( from Packer v1.4 )
+
+The `<-ctx.Done()` can unblock at any time and signifies request for
+cancellation of any builder run in progress.
+
+Cancels are most commonly triggered by external interrupts, such as the user
+pressing `Ctrl-C`. Packer will only exit once all the builders clean up, so it
+is important that you architect your builder in a way that it is quick to
+respond to these cancellations and clean up after itself. If your builder makes
+a long-running call, you should consider the possibility that a user may cancel
+the build during that call, and make sure that such a cancellation is not
+blocked.
+
+## Creating an Artifact
+
+The `Run` method is expected to return an implementation of the
+`packer.Artifact` interface. Each builder must create its own implementation of
+this interface.
+
+Most of the pieces of an artifact should be fairly self-explanatory by reading
+the [packer.Artifact interface
+documentation](https://godoc.org/github.com/hashicorp/packer-plugin-sdk/packer#Artifact).
+
+However one part of an artifact that may be confusing is the `BuilderId` method.
+This method must return an absolutely unique ID for the builder. In general, a
+reasonable ID would be the github username or organization that created the
+builder, followed by the platform it is building for. For example, the builder
+ID of the VMware builder is "hashicorp.vmware".
+
+Post-processors use the builder ID value in order to make some assumptions
+about the artifact results and to determine whether they are even able to run
+against a given artifact, so it is important that this ID never changes once
+the builder is published.
+
+The builder ID for each builder is included on the associated documentation page.
+
+## Provisioning
+
+Packer has built-in support for provisioning using the Provisioner plugins. But
+builders themselves, rather than the Packer core, must determine when to invoke
+the provisioners since only the builder knows when the machine is running and
+ready for communication.
+
+When the machine is ready to be provisioned, run the `packer.HookProvision`
+hook, making sure the communicator is not nil, since this is required for
+provisioners. An example of calling the hook is shown below:
+
+```go
+hook.Run(context.Context, packer.HookProvision, ui, comm, nil)
+```
+
+At this point, Packer will run the provisioners and no additional work is
+necessary.
+
+If you are using the multistep tooling, the Packer plugin SDK contains a
+generic StepProvision which handles execution the provision hook for you and
+automatically supplies any custom builder generatedData you would like to
+provide to provisioners (see below for more details on generatedData.)
+
+## Template Engine
+
+~> Note: In HCL2 the JSON template engine and generated data is slowly going to
+be deprecated in favor of using HCL2 objects, we will keep on supporting those
+but it is recommended to avoid using them if you can.
+
+### Build variables
+
+Packer JSON makes it possible to provide custom template engine variables to be
+shared with provisioners and post-processors using the `build` function.
+JSON template `build` docs are [here](/packer/docs/templates/legacy_json_templates/engine#build)
+and HCL template build docs are [here](/packer/docs/templates/hcl_templates/contextual-variables#build-variables).
+
+As of Packer v1.5.0, builder Prepare() methods return a list of custom variables
+which we call `generated data`. We use that list of variables to generate a
+custom placeholder map per builder that combines custom variables with the
+placeholder map of default build variables created by Packer. Here's an example
+snippet telling packer what will be made available by the builder:
+
+```go
+func (b *Builder) Prepare(raws ...interface{}) ([]string, []string, error) {
+ // ...
+
+ generatedData := []string{"SourceImageName"}
+ return generatedData, warns, nil
+}
+```
+
+When a user provides a Packer template that uses a `build` function, Packer
+validates that the key in the `build` function exists for a given builder using
+this generatedData array. If it does not exist, then Packer validation will
+fail.
+
+Once the placeholder is set, it's necessary to pass the variables' real values
+when calling the provisioner. This can be done as the example below:
+
+```go
+func (b *Builder) Run(ctx context.Context, ui packer.Ui, hook packer.Hook) (packer.Artifact, error) {
+ // ...
+
+ // Create map of custom variable
+ generatedData := map[string]interface{}{"SourceImageName": "the source image name value"}
+ // Pass map to provisioner
+ hook.Run(context.Context, packer.HookProvision, ui, comm, generatedData)
+
+ // ...
+}
+```
+
+In order to make these same variables and the Packer default ones also available
+to post-processors, your builder will need to add them to its Artifact.
+This can be done by adding an attribute of type `map[string]interface{}` to the
+Artifact and putting the generated data in it. The post-processor will access
+this data later via the Artifact's `State` method.
+
+The Artifact code should be implemented similar to the below:
+
+```go
+type Artifact struct {
+ // ...
+
+ // StateData should store data such as GeneratedData
+ // to be shared with post-processors
+ StateData map[string]interface{}
+}
+
+// ...
+
+func (a *Artifact) State(name string) interface{} {
+ return a.StateData[name]
+}
+
+// ...
+```
+
+The builder should return the above Artifact containing the generated data and
+the code should be similar to the example snippet below:
+
+```go
+func (b *Builder) Run(ctx context.Context, ui packer.Ui, hook packer.Hook) (packer.Artifact, error) {
+ // ...
+
+ return &Artifact{
+ // ...
+ StateData: map[string]interface{}{"generated_data": state.Get("generated_data")},
+ }, nil
+}
+```
+
+The code above assigns the `generated_data` state to the `StateData` map with
+the key `generated_data`.
+
+Here some example of how this data will be used by post-processors:
+
+```go
+func (p *PostProcessor) PostProcess(ctx context.Context, ui packer.Ui, source packer.Artifact) (packer.Artifact, bool, bool, error) {
+ generatedData := source.State("generated_data")
+
+ // generatedData will then be used for interpolation
+
+ // ...
+}
+```
+
+## Putting it all together
+
+This page has focused up until now on the implementation details for the Builder
+interface. You will need to create a server and store the builder in a binary in
+order to make it available to the Packer core as a plugin. We have created a
+[scaffolding](https://github.com/hashicorp/packer-plugin-scaffolding/blob/main/builder/scaffolding/builder.go)
+repo to give you an idea of the relationship between the builder
+implementation and the server implementation within a repository, and then read
+[basics of how Plugins work](/packer/docs/plugins/install-plugins), which breaks down all the
+server details.
diff --git a/v1.9.4/website/content/docs/plugins/creation/custom-datasources.mdx b/v1.9.4/website/content/docs/plugins/creation/custom-datasources.mdx
new file mode 100644
index 0000000..1111ac2
--- /dev/null
+++ b/v1.9.4/website/content/docs/plugins/creation/custom-datasources.mdx
@@ -0,0 +1,95 @@
+---
+description: >
+ Packer Data Sources are the components of Packer that allow data to be fetched for use within the Packer configuration.
+ Use of data sources allows a build to use information defined outside of Packer.
+page_title: Custom Data Sources - Extending
+---
+
+# Custom Data Sources
+
+Packer data sources let Packer fetch data to use within the configuration, including information defined outside of Packer. For example, the [amazon-ami data source](/packer/plugins/datasources/amazon/ami), outputs the data from an Amazon AMI.
+
+Data Source plugins implement the `packersdk.Datasource` interface and are registered within a plugin Set
+with `set.RegisterDatasource(...)` function and served using the `set.Run()`.
+
+~> **Warning:** This is an advanced topic that requires strong knowledge of Packer and Packer plugins.
+
+## Before You Begin
+
+We recommend reviewing the following resources before you begin development:
+
+- [Developing Plugins - Overview](/packer/docs/plugins/creation)
+- The [Go](https://go.dev/) language. You must write custom plugins in Go, so this guide assumes you are familiar with the language.
+
+## The Interface
+
+The interface that must be implemented for a datasource is the
+`packersdk.Datasource` interface. It is reproduced below for reference. The
+actual interface in the source code contains some basic documentation as well
+explaining what each method should do.
+
+```go
+type Datasource interface {
+ ConfigSpec() hcldec.ObjectSpec
+ OutputSpec() hcldec.ObjectSpec
+ Configure(...interface{}) error
+ Execute() (cty.Value, error)
+}
+```
+
+### The "ConfigSpec" Method
+
+This method returns a hcldec.ObjectSpec, which is a spec necessary for using
+HCL2 templates with Packer. For information on how to use and implement this
+function, check our
+[object spec docs](/packer/guides/hcl/component-object-spec)
+
+### The "OutputSpec" Method
+
+This method returns a [hcldec.ObjectSpec](/packer/guides/hcl/component-object-spec) of the data source output.
+The object spec can be generated using the command [`packer-sdc mapstructure-to-hcl2`](https://github.com/hashicorp/packer-plugin-sdk/tree/main/cmd/packer-sdc)
+just like the configuration spec for the `ConfigSpec` method.
+
+This method is used in `packer validate` command. Packer will use the spec to assign
+unknown values to the data source, instead of executing it and fetching real values.
+
+### The "Configure" Method
+
+The `Configure` method is called prior to any runs with the configuration that was given in the template.
+This is passed in as an array of `interface{}` types, but is generally `map[string]interface{}`. The Configure
+method is responsible for translating this configuration into an internal structure, validating it,
+and returning any errors.
+
+For multiple parameters, they should be merged together into the final
+configuration, with later parameters overwriting any previous configuration.
+The exact semantics of the merge are left to the builder author.
+
+For decoding the `interface{}` into a meaningful structure, the
+[mapstructure](https://github.com/mitchellh/mapstructure) library is
+recommended. Mapstructure will take an `interface{}` and decode it into an
+arbitrarily complex struct. If there are any errors, it generates very human
+friendly errors that can be returned directly from the Configure method.
+
+While it is not actively enforced, **no side effects** should occur from
+running the `Configure` method. Specifically, don't create files, don't launch
+virtual machines, etc. Configure's purpose is solely to configure the data source and
+validate the configuration.
+
+The `Configure` method is called very early in the build process so that errors
+may be displayed to the user before anything actually happens.
+
+### The "Execute" Method
+
+This method returns an HCL cty.Value and an error. Packer will run the Execute method on `packer build` command
+so that the data source output will be available prior to evaluating build and locals blocks. Is expected that the
+Execute command will fetch the data and return it as a cty.Value.
+
+To get the equivalent cty.Value from an output config, we suggest using our
+[packer-plugin-sdk hcl2helper functions](https://github.com/hashicorp/packer-plugin-sdk/blob/v0.0.7/hcl2helper/values.go).
+
+## Scaffolding template
+
+To make your experience easier when developing your new data source plugin, we provide you a
+[Packer plugin scaffolding](https://github.com/hashicorp/packer-plugin-scaffolding)
+to use as a template to your plugin repository. The template is structure with the basics and contain the necessary
+configuration to start creating your own plugin.
diff --git a/v1.9.4/website/content/docs/plugins/creation/custom-post-processors.mdx b/v1.9.4/website/content/docs/plugins/creation/custom-post-processors.mdx
new file mode 100644
index 0000000..4a20496
--- /dev/null
+++ b/v1.9.4/website/content/docs/plugins/creation/custom-post-processors.mdx
@@ -0,0 +1,107 @@
+---
+description: >
+ Packer Post-processors are the components of Packer that transform one
+ artifact
+
+ into another, for example by compressing files, or uploading them.
+page_title: Custom Post-Processors - Extending
+---
+
+# Custom Post-Processors
+
+Packer post-processors transform one artifact into another. For example, a post-processor might compress or upload files.
+
+In the compression example, the transformation would be taking an artifact with
+a set of files, compressing those files, and returning a new artifact with only
+a single file (the compressed archive). For the upload example, the
+transformation would be taking an artifact with some set of files, uploading
+those files, and returning an artifact with a single ID: the URL of the upload.
+
+Post-processor plugins implement the [`packer.PostProcessor`](https://pkg.go.dev/github.com/hashicorp/packer-plugin-sdk/packer#PostProcessor) interface and are
+served using the `plugin.ServePostProcessor` function.
+
+This page explains how to implement and serve custom post-processors. If you want your post-processor to support HashiCorp Cloud Platform (HCP) Packer, you should also review the [HCP Packer Support](/packer/docs/plugins/creation/hcp-support) documentation.
+
+~> **Warning:** This is an advanced topic that requires strong knowledge of Packer and Packer plugins.
+
+## Before You Begin
+
+We recommend reviewing the following resources before you begin development:
+- [Developing Plugins - Overview](/packer/docs/plugins/creation)
+- The [Go](https://go.dev/) language. You must write custom plugins in Go, so this guide assumes you are familiar with the language.
+
+## The Interface
+
+The interface that must be implemented for a post-processor is the
+[`packer.PostProcessor`](https://pkg.go.dev/github.com/hashicorp/packer-plugin-sdk/packer#PostProcessor) interface. It is reproduced below for reference. The
+actual interface in the source code contains some basic documentation as well
+explaining what each method should do.
+
+```go
+type PostProcessor interface {
+ ConfigSpec() hcldec.ObjectSpec
+ Configure(interface{}) error
+ PostProcess(context.Context, Ui, Artifact) (a Artifact, keep, mustKeep bool, err error)
+}
+```
+
+### The "ConfigSpec" Method
+
+This method returns a hcldec.ObjectSpec, which is a spec necessary for using
+HCL2 templates with Packer. For information on how to use and implement this
+function, check our
+[object spec docs](/packer/guides/hcl/component-object-spec)
+
+### The "Configure" Method
+
+The `Configure` method for each post-processor is called early in the build
+process to configure the post-processor. The configuration is passed in as a
+raw `interface{}`. The configure method is responsible for translating this
+configuration into an internal structure, validating it, and returning any
+errors.
+
+For decoding the `interface{}` into a meaningful structure, the
+[mapstructure](https://github.com/mitchellh/mapstructure) library is
+recommended. Mapstructure will take an `interface{}` and decode it into an
+arbitrarily complex struct. If there are any errors, it generates very
+human-friendly errors that can be returned directly from the configure method.
+
+While it is not actively enforced, **no side effects** should occur from
+running the `Configure` method. Specifically, don't create files, don't create
+network connections, etc. Configure's purpose is solely to setup internal state
+and validate the configuration as much as possible.
+
+`Configure` being run is not an indication that `PostProcess` will ever run.
+For example, `packer validate` will run `Configure` to verify the configuration
+validates, but will never actually run the build.
+
+### The "PostProcess" Method
+
+The `PostProcess` method is where the real work goes. PostProcess is
+responsible for taking one `packer.Artifact` implementation, and transforming
+it into another.
+A `PostProcess` call can be cancelled at any moment. Cancellation is triggered
+when the done chan of the context struct (`<-ctx.Done()`) unblocks .
+
+When we say "transform," we don't mean actually modifying the existing
+`packer.Artifact` value itself. We mean taking the contents of the artifact and
+creating a new artifact from that. For example, if we were creating a
+"compress" post-processor that is responsible for compressing files, the
+transformation would be taking the `Files()` from the original artifact,
+compressing them, and creating a new artifact with a single file: the
+compressed archive.
+
+The result signature of this method is `(Artifact, bool, bool, error)`. Each
+return value is explained below:
+
+- `Artifact` - The newly created artifact if no errors occurred.
+- `bool` - If keep true, the input artifact will forcefully be kept. By default,
+ Packer typically deletes all input artifacts, since the user doesn't
+ generally want intermediary artifacts. However, some post-processors depend
+ on the previous artifact existing. If this is `true`, it forces packer to
+ keep the artifact around.
+- `bool` - If forceOverride is true, then any user input for
+ keep_input_artifact is ignored and the artifact is either kept or discarded
+ according to the value set in `keep`.
+- `error` - Non-nil if there was an error in any way. If this is the case,
+ the other two return values are ignored.
diff --git a/v1.9.4/website/content/docs/plugins/creation/custom-provisioners.mdx b/v1.9.4/website/content/docs/plugins/creation/custom-provisioners.mdx
new file mode 100644
index 0000000..30bb831
--- /dev/null
+++ b/v1.9.4/website/content/docs/plugins/creation/custom-provisioners.mdx
@@ -0,0 +1,127 @@
+---
+description: >
+ Packer Provisioners are the components of Packer that install and configure
+
+ software into a running machine prior to turning that machine into an image.
+ An
+
+ example of a provisioner is the shell provisioner, which runs shell scripts
+
+ within the machines.
+page_title: Custom Provisioners - Extending
+---
+
+# Custom Provisioners
+
+Packer provisioners install and configure software into a running machine prior to turning that machine into an image. For example, the [shell
+provisioner](/packer/docs/provisioners/shell), which runs shell scripts within
+the machines.
+
+Provisioner plugins implement the [`packer.Provisioner`](https://pkg.go.dev/github.com/hashicorp/packer-plugin-sdk/packer#Provisioner) interface and are served
+using the `plugin.ServeProvisioner` function.
+
+~> **Warning:** This is an advanced topic that requires strong knowledge of Packer and Packer plugins.
+
+## Before You Begin
+
+We recommend reviewing the following resources before you begin development:
+- [Developing Plugins - Overview](/packer/docs/plugins/creation)
+- The [Go](https://go.dev/) language. You must write custom plugins in Go, so this guide assumes you are familiar with the language.
+
+## The Interface
+
+The interface that must be implemented for a provisioner is the
+[`packer.Provisioner`](https://pkg.go.dev/github.com/hashicorp/packer-plugin-sdk/packer#Provisioner) interface. It is reproduced below for reference. The
+actual interface in the source code contains some basic documentation as well
+explaining what each method should do.
+
+```go
+type Provisioner interface {
+ ConfigSpec() hcldec.ObjectSpec
+ Prepare(...interface{}) error
+ Provision(context.Context, Ui, Communicator, map[string]interface{}) error
+}
+```
+
+### The "Prepare" Method
+
+The `Prepare` method for each provisioner is called prior to any runs with the
+configuration that was given in the template. This is passed in as an array of
+`interface{}` types, but is generally `map[string]interface{}`. The prepare
+method is responsible for translating this configuration into an internal
+structure, validating it, and returning any errors.
+
+For multiple parameters, they should be merged together into the final
+configuration, with later parameters overwriting any previous configuration.
+The exact semantics of the merge are left to the builder author.
+
+For decoding the `interface{}` into a meaningful structure, the
+[mapstructure](https://github.com/mitchellh/mapstructure) library is
+recommended. Mapstructure will take an `interface{}` and decode it into an
+arbitrarily complex struct. If there are any errors, it generates very human
+friendly errors that can be returned directly from the prepare method.
+
+While it is not actively enforced, **no side effects** should occur from
+running the `Prepare` method. Specifically, don't create files, don't launch
+virtual machines, etc. Prepare's purpose is solely to configure the builder and
+validate the configuration.
+
+The `Prepare` method is called very early in the build process so that errors
+may be displayed to the user before anything actually happens.
+
+### The "ConfigSpec" Method
+
+This method returns a hcldec.ObjectSpec, which is a spec necessary for using
+HCL2 templates with Packer. For information on how to use and implement this
+function, check our
+[object spec docs](/packer/guides/hcl/component-object-spec)
+
+### The "Provision" Method
+
+The `Provision` method is called when a machine is running and ready to be
+provisioned. The provisioner should do its real work here.
+
+The method takes two parameters: a `packer.Ui` and a `packer.Communicator`. The
+UI can be used to communicate with the user what is going on. The communicator
+is used to communicate with the running machine, and is guaranteed to be
+connected at this point.
+
+The provision method should not return until provisioning is complete.
+
+The map[string]interface{} provides users with build-specific information,
+like host and IP, provided by the `build` template engine. Provisioners may use
+this information however they please, or not use it.
+
+## Using the Communicator
+
+The `packer.Communicator` parameter and interface is used to communicate with
+running machine. The machine may be local (in a virtual machine or container of
+some sort) or it may be remote (in a cloud). The communicator interface
+abstracts this away so that communication is the same overall.
+
+The documentation around the [code
+itself](https://godoc.org/github.com/hashicorp/packer-plugin-sdk/packer#Communicator)
+is really great as an overview of how to use the interface. You should begin by
+reading this. Once you have read it, you can see some example usage below:
+
+```go
+// Build the remote command.
+var cmd packer.RemoteCmd
+cmd.Command = "echo foo"
+
+// We care about stdout, so lets collect that into a buffer. Since
+// we don't set stderr, that will just be discarded.
+var stdout bytes.Buffer
+cmd.Stdout = &stdout
+
+// Start the command
+if err := comm.Start(&cmd); err != nil {
+ panic(err)
+}
+
+// Wait for it to complete
+cmd.Wait()
+
+// Read the stdout!
+fmt.Printf("Command output: %s", stdout.String())
+```
diff --git a/v1.9.4/website/content/docs/plugins/creation/hcp-support.mdx b/v1.9.4/website/content/docs/plugins/creation/hcp-support.mdx
new file mode 100644
index 0000000..ed65ae1
--- /dev/null
+++ b/v1.9.4/website/content/docs/plugins/creation/hcp-support.mdx
@@ -0,0 +1,115 @@
+---
+description: |
+ HCP Packer support allows plugins to manage image metadata that can be stored in a HCP Packer registry.
+page_title: HCP Packer Support
+---
+
+# HCP Packer Support
+
+~> **Note:** HCP Packer is under active development, and we suggest plugin maintainers to keep up with the SDK changes
+for more on HCP Packer support.
+
+This page explains how to update a custom plugin so that it can publish image metadata to the [HCP Packer registry](/hcp/docs/packer). Refer to [Custom Builders](/packer/docs/plugins/creation/custom-builders) and [Custom Post-Processors](/packer/docs/plugins/creation/custom-post-processors) for details about creating an external Packer plugin.
+
+Before pushing metadata to the HCP Packer registry, Packer uses the [`par.artifact.metadata` key](https://pkg.go.dev/github.com/hashicorp/packer-plugin-sdk/packer/registry/image#pkg-constants)
+to query a builder artifact for the image metadata that a particular component would like to have stored in the registry.
+
+For details and examples of how to manage image metadata, refer to the [HCP Packer GitHub documentation](https://pkg.go.dev/github.com/hashicorp/packer-plugin-sdk/packer/registry/image).
+
+## Builder Artifact
+
+To support HCP Packer, changes must be made to the plugin's build artifact. The artifact should keep the appropriate
+Image metadata in state under the key `par.artifact.metadata`. The expected key is provided by the [image.ArtifactStateURI](https://pkg.go.dev/github.com/hashicorp/packer-plugin-sdk/packer/registry/image#pkg-constants) constant.
+
+To make HCP Packer support easier, we ship an Image package with the [packer-plugin-sdk](https://pkg.go.dev/github.com/hashicorp/packer-plugin-sdk/packer/registry/image#pkg-overview).
+We provide the [`FromArtifact`](https://pkg.go.dev/github.com/hashicorp/packer-plugin-sdk/packer/registry/image#FromArtifact) function
+to easily create an Image with the basic information contained in the Artifact. If customization is necessary, the `FromArtifact` accepts
+override functions as the second argument, and that can be used to set different values for the metadata.
+
+The [Image metadata](https://pkg.go.dev/github.com/hashicorp/packer-plugin-sdk/packer/registry/image#Image) must contain every
+metadata HCP Packer should store about this component. The structure is:
+```go
+// Image represents the metadata for some Artifact in the HCP Packer Registry.
+type Image struct {
+ // ImageID is a unique reference identifier stored on the HCP Packer registry
+ // that can be used to get back the built artifact of a builder or post-processor.
+ ImageID string
+ // ProviderName represents the name of the top level cloud or service where the built artifact resides.
+ // For example "aws, azure, docker, gcp, and vsphere".
+ ProviderName string
+ // ProviderRegion represents the location of the built artifact.
+ // For cloud providers region usually maps to a cloud region or zone, but for things like the file builder,
+ // S3 bucket or vsphere cluster region can represent a path on the upstream datastore, or cluster.
+ ProviderRegion string
+ // Labels represents additional details about an image that a builder or post-processor may with to provide for a given build.
+ // Any additional metadata will be made available as build labels within a HCP Packer registry iteration.
+ Labels map[string]string
+ // SourceImageID is the cloud image ID of the image that was used as the
+ // source for this image. If set, the HCP Packer registry will be able
+ // link the parent and child images for ancestry visualizations and
+ // dependency tracking.
+ SourceImageID string
+}
+```
+
+Where `ImageID`, `ProviderName`, and `SourceImageID` are mandatory fields.
+
+Examples using the `FromArtifact` method:
+
+- Simple form:
+```go
+func (a *Artifact) State(name string) interface{} {
+ if name == registryimage.ArtifactStateURI {
+ img, err := registryimage.FromArtifact(a)
+ if err != nil {
+ log.Printf("[DEBUG] error encountered when creating a registry image %v", err)
+ return nil
+ }
+ return img
+ }
+ return a.StateData[name]
+}
+```
+
+- Using overrides:
+```go
+func (a *Artifact) State(name string) interface{} {
+ if name == registryimage.ArtifactStateURI {
+ img, err := registryimage.FromArtifact(a,
+ registryimage.WithID(a.Name),
+ registryimage.WithRegion(a.Region.Name()),
+ registryimage.WithProvider("happy-cloud"),
+ registryimage.WithSourceID(a.SourceID),
+ registryimage.SetLabels(a.Labels),
+ )
+ if err != nil {
+ log.Printf("[DEBUG] error encountered when creating a registry image %v", err)
+ return nil
+ }
+ return img
+ }
+ return a.StateData[name]
+}
+```
+
+See [packer-plugin-sdk/packer/registry/image](https://pkg.go.dev/github.com/hashicorp/packer-plugin-sdk/packer/registry/image#pkg-examples) for additional examples.
+
+### SDK Version
+
+- The HCP Packer support is available from packer-plugin-sdk >= v0.2.7
+
+## Plugins Example
+
+The following plugins currently support HCP Packer and are great references for development:
+
+- [packer-plugin-amazon](https://github.com/hashicorp/packer-plugin-amazon)
+- [packer-plugin-azure](https://github.com/hashicorp/packer-plugin-azure)
+- [packer-plugin-vsphere](https://github.com/hashicorp/packer-plugin-vsphere)
+- [packer-plugin-docker](https://github.com/hashicorp/packer-plugin-docker)
+- [packer-plugin-googlecompute](https://github.com/hashicorp/packer-plugin-googlecompute)
+
+## HCP Packer
+
+To get to know HCP Packer, visit the
+[HCP Packer documentation](/hcp/docs/packer) or try the
+[Get Started with HCP Packer tutorials](/packer/tutorials/hcp-get-started).
diff --git a/v1.9.4/website/content/docs/plugins/creation/index.mdx b/v1.9.4/website/content/docs/plugins/creation/index.mdx
new file mode 100644
index 0000000..32537f1
--- /dev/null
+++ b/v1.9.4/website/content/docs/plugins/creation/index.mdx
@@ -0,0 +1,339 @@
+---
+description: |
+ Packer is designed to be extensible. Because the surface area for workloads is
+ infinite, Packer supports plugins for builders, provisioners, and
+ post-processors.
+page_title: Extending
+---
+
+# Developing Plugins
+
+Packer is extensible and supports plugins that let you
+create and use custom builders, provisioners, post-processors, and data sources. This page explains how to develop Packer plugins. Before you begin, we recommend reviewing the Packer documentation and the instructions for [installing external plugins](/packer/docs/plugins/install-plugins).
+
+~> **Warning** This is an advanced topic. You should have strong knowledge of Packer before you start writing plugins.
+
+## Language Requirements
+
+You must write Packer plugins in [Go](https://go.dev/).
+
+
+## Plugin System Architecture
+
+A Packer plugin is just a Go binary. Instead of loading plugins directly into a
+running application, Packer runs each plugin as a _separate application_.
+The multiple separate Packer plugin processes communicate with the Core using
+an RPC defined in the packer-plugin SDK. The Packer core itself is responsible
+launching and cleaning up the plugin processes.
+
+## Plugin Development Basics
+
+The components that can be created and used in a Packer plugin are builders,
+provisioners, post-processors, and data sources.
+
+Each of these components has a corresponding [interface](https://go.dev/doc/effective_go.html#interfaces_and_types).
+
+All you need to do to create a plugin is:
+
+1. create an implementation of the desired interface, and
+2. serve it using the server provided in the [packer-plugin-sdk](https://github.com/hashicorp/packer-plugin-sdk).
+
+The core and the SDK handle all of the communication details inside the server.
+
+Your plugin must use two packages from the SDK to implement the server and
+interfaces. You're encouraged to use whatever other packages you want in your
+plugin implementation. Because plugins are their own processes, there is no
+danger of colliding dependencies.
+
+- [`github.com/hashicorp/packer-plugin-sdk/packer`](https://pkg.go.dev/github.com/hashicorp/packer-plugin-sdk/packer) - Contains all the interfaces that you have to implement for any given plugin.
+
+- [`github.com/hashicorp/packer-plugin-sdk/plugin`](https://pkg.go.dev/github.com/hashicorp/packer-plugin-sdk/plugin) - Contains the code to serve the plugin. This handles all the inter-process communication.
+
+Basic examples of serving your component are shown below. Note that if you
+define a multi-component plugin, you can (but do not need to) add more than one
+component per plugin binary. The multi-component plugin is also compatible with
+download and installation via `packer init`, whereas the single-component plugin
+is not.
+
+<Tabs>
+
+<Tab heading="Multi-component Plugin (recommended) ">
+
+```go
+// main.go
+
+import (
+ "github.com/hashicorp/packer-plugin-sdk/plugin"
+)
+
+// Assume this implements the packer.Builder interface
+type ExampleBuilder struct{}
+
+// Assume this implements the packer.PostProcessor interface
+type FooPostProcessor struct{}
+
+// Assume this implements the packer.Provisioner interface
+type BarProvisioner struct{}
+
+func main() {
+ pps := plugin.NewSet()
+ pps.RegisterBuilder("example", new(ExampleBuilder))
+ pps.RegisterBuilder(plugin.DEFAULT_NAME, new(AnotherBuilder))
+ pps.RegisterPostProcessor("foo", new(FooPostProcessor))
+ pps.RegisterProvisioner("bar", new(BarProvisioner))
+ err := pps.Run()
+ if err != nil {
+ fmt.Fprintln(os.Stderr, err.Error())
+ os.Exit(1)
+ }
+}
+```
+
+This `plugin.NewSet` invocation handles all the details of communicating with
+Packer core and serving your component over RPC. As long as your struct being
+registered implements one of the component interfaces, Packer will now be able
+to launch your plugin and use it.
+
+If you register a component with its own name, the component name will be
+appended to the plugin name to create a unique name. If you register a component
+using the special string constant `plugin.DEFAULT_NAME`, then the component will
+be referenced by using only the plugin name. For example:
+
+If your plugin is named `packer-plugin-my`, the above set definition would make
+the following components available:
+
+- the `my-example` builder
+- the `my` builder
+- the `my-foo` post-processor
+- the `my-bar` provisioner
+
+</Tab>
+
+<Tab heading="Single Component Plugin (deprecated)">
+
+```go
+// main.go
+
+import (
+ "github.com/hashicorp/packer-plugin-sdk/plugin"
+)
+
+// Assume this implements the packer.Builder interface
+type Builder struct{}
+
+func main() {
+ server, err := plugin.Server()
+ if err != nil {
+ panic(err)
+ }
+ server.RegisterBuilder(new(Builder))
+ server.Serve()
+}
+```
+
+This `server.Serve()` invocation handles all the details of communicating with
+Packer core and serving your component over RPC. As long as your struct being
+registered implements one of the component interfaces, Packer will now be able
+to launch your plugin and use it.
+
+Please note that single-component plugins exist for backwards-compatability. We
+would rather you register your component using the multi-component method shown
+in the other tab, even if you only have one component in your binary. This is
+because the `packer init` command only supports multi-component plugins.
+
+</Tab>
+</Tabs>
+
+Next, build your plugin as you would any other Go application. The resulting
+binary is the plugin that can be installed using
+[standard installation procedures](/packer/docs/plugins#installing-plugins).
+
+This documentation explains how to implement each type of plugin interface: builders, data sources, provisioners, and post-processors.
+
+~> **Lock your dependencies!** Using `go mod` is highly recommended since
+the Packer codebase will continue to improve, potentially breaking APIs along
+the way until there is a stable release. By locking your dependencies, your
+plugins will continue to work with the version of Packer you lock to.
+
+## Logging and Debugging
+
+Plugins can use the standard Go `log` package to log. Anything logged using
+this will be available in the Packer log files automatically. The Packer log is
+visible on stderr when the `PACKER_LOG` environment var is set.
+
+Packer will prefix any logs from plugins with the path to that plugin to make
+it identifiable where the logs come from. Some example logs are shown below:
+
+```text
+2013/06/10 21:44:43 Loading builder: custom
+2013/06/10 21:44:43 packer-builder-custom: 2013/06/10 21:44:43 Plugin minimum port: 10000
+2013/06/10 21:44:43 packer-builder-custom: 2013/06/10 21:44:43 Plugin maximum port: 25000
+2013/06/10 21:44:43 packer-builder-custom: 2013/06/10 21:44:43 Plugin address: :10000
+```
+
+As you can see, the log messages from the custom builder plugin are prefixed
+with "packer-builder-custom". Log output is _extremely_ helpful in debugging
+issues and you're encouraged to be as verbose as you need to be in order for
+the logs to be helpful.
+
+### Creating a GitHub Release
+
+`packer init` does not work using a centralized registry. Instead, it requires
+you to publish your plugin in a GitHub repo with the name
+`packer-plugin-*` where \* represents the name of your plugin. You also need to
+create a GitHub release of your plugin with specific assets for the
+`packer init` download to work. We provide a pre-defined release workflow
+configuration using
+[GitHub Actions](https://docs.github.com/en/free-pro-team@latest/actions). We
+strongly encourage maintainers to use this configuration to make sure the
+release contains the right assets with the right names for Packer to leverage
+`packer init` installation.
+
+Here's what you need to create releases using GitHub Actions:
+
+1. Generate a GPG key to be used when signing releases (See [GitHub's detailed instructions](https://docs.github.com/en/free-pro-team@latest/github/authenticating-to-github/generating-a-new-gpg-key)
+ for help with this step)
+2. Copy the [GoReleaser configuration from the packer-plugin-scaffolding repository](https://github.com/hashicorp/packer-plugin-scaffolding/blob/main/.goreleaser.yml) to the root of your repository.
+ ```sh
+ curl -L -o .goreleaser.yml \
+ https://raw.githubusercontent.com/hashicorp/packer-plugin-scaffolding/main/.goreleaser.yml
+ ```
+3. Copy the [GitHub Actions workflow from the packer-plugin-scaffolding repository](https://github.com/hashicorp/packer-plugin-scaffolding/blob/main/.github/workflows/release.yml) to `.github/workflows/release.yml` in your repository.
+ ```sh
+ mkdir -p .github/workflows &&
+ curl -L -o .github/workflows/release.yml \
+ https://raw.githubusercontent.com/hashicorp/packer-plugin-scaffolding/main/.github/workflows/release.yml
+ ```
+4. Go to your repository page on GitHub and navigate to Settings > Secrets. Add
+ the following secrets:
+ - `GPG_PRIVATE_KEY` - Your ASCII-armored GPG private key. You can export this with `gpg --armor --export-secret-keys [key ID or email]`.
+ - `GPG_PASSPHRASE` - The passphrase for your GPG private key.
+5. Push a new valid version tag (e.g. `v1.2.3`) to test that the GitHub Actions
+ releaser is working. The tag must be a valid
+ [Semantic Version](https://semver.org/) preceded with a `v`. Once the tag is pushed, the github actions you just configured will automatically build release binaries that Packer can download using `packer init`. For more details on how
+ to install a plugin using `packer init`, see the
+ [init docs](/packer/docs/commands/init).
+
+## Registering Plugin Documentation
+
+~> Note: Registering a remote plugin's plugin documentation requires the use of [Packer's plugin docs configuration](https://github.com/hashicorp/packer-plugin-scaffolding/tree/main/docs).
+
+`packer init` allows users to require and install remote Packer plugins, those not bundled with Packer core, that have been published to GitHub automatically.
+To help with the discovery of remote Packer plugins on GitHub, plugins maintainers can choose to register plugin documentation for each component directly on the [Packer Documentation Page](/packer/docs).
+
+The registration process requires the creation of a `docs.zip` file archive containing the `.mdx` files for each of the plugin components in the remote plugin's repository. A working example can be seen at the [packer-plugin-docker repository](https://github.com/hashicorp/packer-plugin-docker/releases/latest).
+
+Once in place the remote plugin can be added to Packer's website builds by opening a pull-request against [hashicorp/packer](https://github.com/hashicorp/packer), with the needed configuration for pulling in the remote documentation.
+
+Remote plugins will have their components listed under the respected types (i.e builders, provisioners, etc) using the names specified in the remote block configuration, and labeled with their respective [tier and namespace](/packer/docs/plugins#tiers-and-namespaces).
+
+To register a plugin follow one of the following setups
+
+<Tabs>
+<Tab heading="Generating docs.zip on plugin release">
+
+Documentation for a plugin is maintained within the `docs` directory and served on GitHub.
+
+To include plugin docs on the website, a global pre-hook has been added to the main scaffolding [.goreleaser.yml](https://github.com/hashicorp/packer-plugin-scaffolding/blob/42e5b0b1e575879b0477cb6d4291e027f4d92f85/.goreleaser.yml#L10) file, that if uncommented will generate and include a docs.zip file as part of the plugin release.
+
+The `docs.zip` file contains all of the `.mdx` files under the plugins root `docs/` directory that the website can consume remotely.
+
+</Tab>
+
+<Tab heading="Manually generating docs.zip">
+
+You can generate the required documentation structure manually by creating a zip file called `docs.zip` of the docs directory and including that zip file in the plugin release.
+
+```/bin/bash
+[[ -d docs/ ]] && zip -r docs.zip docs/
+```
+
+</Tab>
+</Tabs>
+
+Once the first `docs.zip` file has been included into a release you will need to open a one time pull-request against [hashicorp/packer](https://github.com/hashicorp/packer) to register the plugin docs.
+
+This is done by adding the block below for the respective plugin to the file [website/data/plugins-manifest.json](https://github.com/hashicorp/packer/blob/main/website/data/plugins-manifest.json).
+
+```json
+{
+ "title": "Scaffolding",
+ "path": "scaffolding",
+ "repo": "hashicorp/packer-plugin-scaffolding",
+ "version": "latest",
+ "sourceBranch": "main"
+}
+```
+
+If a plugin maintainer wishes to only include a specific version of released docs, then the `"version"` key in the above configuration should be set to a released version of the plugin. Otherwise it should be set to `"latest"`.
+
+The `"sourceBranch"` key in the above configuration ensures potential contributors can link back to source files in the plugin repository from the Packer docs site. If a `"sourceBranch"` value is not present, it will default to `"main"`.
+
+### Testing Plugin Documentation
+
+Before publishing the `docs.zip` file, you might want to preview your documentation changes.
+We provide a mechanism that allows to preview how the docs will look like within
+the Packer documentation.
+
+Follow the next steps to get the Packer website running and preview the documentation changes:
+
+- Get the [Packer source code](https://github.com/hashicorp/packer). Our website code is under the [website folder](https://github.com/hashicorp/packer/tree/main/website).
+- Generate the `docs.zip` file. You can find above the steps to do so.
+- Add the `zipFile` attribute to the plugin entry in `plugins-manifest.json`. The value should be the full path of the `docs.zip` generated. For example:
+
+```json
+{
+ "title": "Scaffolding",
+ "path": "scaffolding",
+ "repo": "hashicorp/packer-plugin-scaffolding",
+ "version": "latest",
+ "sourceBranch": "main",
+ "zipFile": "/Users/myuser/Packer/plugins/packer-plugin-scaffolding/docs.zip"
+}
+```
+
+- Go to the [website folder](https://github.com/hashicorp/packer/tree/main/website).
+ In the website README, follow the steps to [run the website with node](https://github.com/hashicorp/packer/tree/main/website#with-node).
+- Once the website is up and running, the plugin documentation should be available in `http://localhost:3000/docs`.
+
+## Plugin Development Tips and FAQs
+
+### Working Examples
+
+Here's a non-exhaustive list of Packer plugins that you can check out:
+
+- [github.com/hashicorp/packer-plugin-docker](https://github.com/hashicorp/packer-plugin-docker)
+- [github.com/exoscale/packer-plugin-exoscale](https://github.com/exoscale/packer-plugin-exoscale)
+- [github.com/sylviamoss/packer-plugin-comment](https://github.com/sylviamoss/packer-plugin-comment)
+
+Looking at their code will give you good examples.
+
+### Naming Conventions
+
+It is standard practice to name the resulting plugin application in the format
+of `packer-plugin-NAME`. For example, if you're building a new builder for
+CustomCloud, it would be standard practice to name the resulting plugin
+`packer-plugin-customcloud`. This naming convention helps users identify the
+scope of a plugin.
+
+### Testing Plugins
+
+Making your unpublished plugin available to Packer is possible by either:
+
+- Starting Packer from the directory where the plugin binary is located.
+- Putting the plugin binary in the same directory as Packer.
+
+In both these cases, if the binary is called `packer-plugin-myawesomecloud` and
+defines an `ebs` builder then you will be able to use an `myawesomecloud-ebs`
+builder or source without needing to have a `required_plugin` block.
+
+This is extremely useful during development.
+
+### Distributing Plugins
+
+We recommend that you use a tool like the GoReleaser in order to cross-compile
+your plugin for every platform that Packer supports, since Go applications are
+platform-specific. If you have created your plugin from the
+[packer-plugin-scaffolding](https://github.com/hashicorp/packer-plugin-scaffolding)
+repo, simply tagging a commit and pushing the tag to GitHub will correctly build
+and release the binaries using GoReleaser.
diff --git a/v1.9.4/website/content/docs/plugins/index.mdx b/v1.9.4/website/content/docs/plugins/index.mdx
new file mode 100644
index 0000000..4a11840
--- /dev/null
+++ b/v1.9.4/website/content/docs/plugins/index.mdx
@@ -0,0 +1,21 @@
+---
+description: |
+ Packer plugins let you add Packer functionality without modifying
+ the core source code. Packer plugins are able to add new builders,
+ provisioners, hooks, and more.
+page_title: Plugins
+---
+
+# Packer Plugins
+
+Packer plugins are separate, standalone applications that perform tasks during each build.
+
+During a `packer build`, the process list shows `packer-` prefixed applications. One of those applications is the Packer binary, and the rest are plugins. Packer launches one plugin process for each component in the build.
+
+The Packer binary has a set of built-in plugins that it can find and run automatically. You can also define a list of external plugins in your template for Packer to run and communicate with throughout the build. These external plugins extend Packer functionality without modifying the core source code.
+
+Refer to the following plugin documentation:
+- **Built-in Plugins:** Use [builders](/packer/docs/builders) to create machines and images, [data sources](/packer/docs/datasources) to fetch data, [provisioners](/packer/docs/provisioners) to install and configure machine images, and [post-processors](/packer/docs/post-processors) to perform additional tasks after provisioning
+- **External Plugins:** Review the documentation for [available external plugins](/packer/plugins) not included with the Packer binary
+- **Installing Plugins:** [Installation Guides](/packer/docs/plugins/install-plugins) to add external plugins to your Packer template and install the binaries
+- **Developing Plugins:** Get started [creating custom external plugins](/packer/docs/plugins/creation)
\ No newline at end of file
diff --git a/v1.9.4/website/content/docs/plugins/install-plugins.mdx b/v1.9.4/website/content/docs/plugins/install-plugins.mdx
new file mode 100644
index 0000000..0460e6c
--- /dev/null
+++ b/v1.9.4/website/content/docs/plugins/install-plugins.mdx
@@ -0,0 +1,269 @@
+---
+description: |
+ Install external Packer plugins that extend Packer functionality.
+page_title: Install Plugins
+---
+
+# Installing Plugins
+
+Packer plugins are separate, standalone applications that perform tasks during each build.
+
+You do not need to install the builder, provisioner, or
+post-processor components that ship with the Packer binary. Packer automatically knows how to find and launch these built-in plugins.
+
+This page explains how to install custom external plugins. Refer to [External Plugins](/packer/plugins) for a list of available plugins and their documentation.
+
+## Plugin Loading Order
+
+@include "plugins/plugin-location.mdx"
+
+## Installation Guides
+
+Choose the tab that corresponds to the type of plugin you want to install. If you are not sure, check the plugin's name.
+- Multi-component plugin names have the prefix `packer-plugin-`.
+- Single-component plugin names have a prefix containing the component type, like `packer-provisioner-` or `packer-builder`.
+
+<Tabs>
+<Tab heading="Packer init (recommended from Packer v1.7.0)">
+
+-> **Note:** Only _multi-component plugin binaries_ -- plugins named
+packer-plugin-\*, like the `packer-plugin-amazon` -- are expected to work with
+Packer init. The legacy `builder`, `post-processor` and `provisioner` plugin
+types will continue to be detected but Packer cannot install them automatically.
+If a plugin you use has not been upgraded to use the multi-component plugin
+architecture, contact your maintainer to request an upgrade.
+
+## Create a required_plugins block
+
+1. Add a
+ [`required_plugins`](/packer/docs/templates/hcl_templates/blocks/packer#specifying-plugin-requirements)
+ block to your [packer block](/packer/docs/templates/hcl_templates/blocks/packer). Each block will tell Packer what version(s) of a
+ particular plugin can be installed. Make sure to set a valid [version
+ constraint string](/packer/docs/templates/hcl_templates/blocks/packer#version-constraints).
+
+Here is an example `required_plugins` block:
+
+```hcl
+packer {
+ required_plugins {
+ myawesomecloud = {
+ version = ">= 2.7.0"
+ source = "github.com/azr/myawesomecloud"
+ }
+ happycloud = {
+ version = ">= 1.1.3"
+ source = "github.com/azr/happycloud"
+ }
+ }
+}
+```
+
+2. Run [`packer init`](/packer/docs/commands/init) from your project directory (the
+ directory containing your Packer templates) to install all missing plugin
+ binaries. Given the above example, Packer will try to look for a GitHub
+ repository owned by user or organization `azr` named
+ `packer-plugin-myawesomecloud` and `packer-plugin-happycloud`.
+
+## Names and Addresses
+
+Each plugin has two identifiers:
+
+- A `source` address, which is necessary when requiring a plugin not bundled with the Packer binary.
+- A unique **local name**, which is used everywhere else in a Packer configuration.
+
+## Local Names
+
+Local names allow you to access the components of a plugin and must be unique
+per configuration.
+
+This is best explained using an example. In the above `required_plugins` block,
+we declared the local name "myawesomecloud" for the plugin `azr/myawesomecloud`.
+If the "myawesomecloud" plugin contains both an "ebs" builder and an "import"
+post-processor, then the builder will be accessed in a source block by using:
+
+```hcl
+source "myawesomecloud-ebs" "example" {
+ // builder configuration...
+}
+```
+
+similarly, the import post-processor would be accessed by declaring the
+post-processor block:
+
+```hcl
+post-processor "myawesomecloud-import" {
+ // post-processor configuration...
+}
+```
+
+If we change the required_plugins block to use a different local name "foo":
+
+```hcl
+ required_plugins {
+ foo = {
+ version = ">= 2.7.0"
+ source = "github.com/azr/myawesomecloud"
+ }
+ }
+```
+
+Then we'd instead access that builder using the source:
+
+```hcl
+source "foo-ebs" "example" {
+ // builder configuration...
+}
+```
+
+## Source Addresses
+
+A plugin's source address is its global identifier. It also tells Packer where
+to download it.
+
+Source addresses consist of three parts delimited by slashes (`/`), as
+follows:
+
+`<HOSTNAME>/<NAMESPACE>/<TYPE>`
+
+- **Hostname:** The hostname of the location/service that
+ distributes the plugin. Currently, the only valid "hostname" is github.com,
+ but we plan to eventually support plugins downloaded from other domains.
+
+- **Namespace:** An organizational namespace within the specified host.
+ This often is the organization that publishes the plugin.
+
+- **Type:** A short name for the platform or system the plugin manages. The
+ type is usually the plugin's preferred local name.
+
+For example, the fictional `myawesomecloud` plugin could belong to the
+`hashicorp` namespace on `github.com`, so its `source` could be
+`github.com/hashicorp/myawesomecloud`,
+
+-> Note: the actual _repository_ that myawesomecloud comes from must always have
+the name format `github.com/hashicorp/packer-plugin-myawesomecloud`, but the
+`required_plugins` block omits the redundant `packer-plugin-` repository prefix
+for brevity.
+
+The source address with all three components given explicitly is called the
+plugin's _fully-qualified address_. You will see fully-qualified address in
+various outputs, like error messages.
+
+## Plugin Installation Workflow
+
+* [`packer init`](/packer/docs/commands/init) will install plugins in the **last** directory
+in the following numbered list.
+
+1. `PACKER_PLUGIN_PATH` if set will be the sole location for installing plugins. All other
+plugin directories will be ignored.
+1. `PACKER_CONFIG_DIR`\plugins on Windows systems, or `PACKER_CONFIG_DIR`/plugins on all other systems.
+
+* During the initialization of Packer, any plugin required in the
+**`required_plugins`** section will be looked up in all entries of the following
+list. **First** plugin found takes precedence. Two binaries of the same plugin
+with two different version will be considered as two different plugins. Highest
+found version matching `required_plugins` will be taken into consideration.
+
+During initialization, on a `darwin_amd64` system, Packer will look-up for the
+following files:
+
+* `PACKER_PLUGIN_PATH/github.com/azr/happycloud/packer-plugin-happycloud_*_x5.0_darwin_amd64`
+* `PACKER_CONFIG_DIR/plugins/github.com/azr/happycloud/packer-plugin-happycloud_*_x5.0_darwin_amd64`
+
+The first plugin-name/version files found will take precedence.
+
+For plugins located under the `github.com/azr/happycloud/` directory structure an accompanying SHA256SUM file
+will be required in order for `packer init` to ensure the plugin being loaded has not been tampered with.
+The SHA256SUM file will be automatically generated when a plugin is installed via `packer init` if the plugin
+was installed manually into `PACKER_CONFIG_DIR/plugins/github.com/azr/happycloud/` then the file
+`PACKER_CONFIG_DIR/plugins/github.com/azr/happycloud/packer-plugin-happycloud_*_x5.0_darwin_amd64_SHA256SUM` must be generated manually as well.
+
+## Implicit Github urls
+
+Using the following example :
+
+```hcl
+ required_plugins {
+ happycloud = {
+ version = ">= 2.7.0"
+ source = "github.com/azr/happycloud"
+ }
+ }
+```
+
+The plugin getter will look for plugins located at:
+
+- github.com/azr/packer-plugin-happycloud
+
+Packer will error if you set the `packer-plugin-` prefix in a `source`. This
+will avoid conflicting with other plugins for other tools, like Terraform.
+
+</Tab>
+<Tab heading="manually (multi-component plugin)">
+
+-> The [`packer plugins`](/packer/docs/commands/plugins), available from Packer v1.8.0, command allows
+you to install plugins without going through `init`.
+
+```shell
+packer plugins install github.com/hashicorp/vagrant
+```
+
+## Plugin Installation Workflow
+Plugin installation via `packer plugins install` works similar to that of the `packer init` command, with the following
+exceptions no `required_plugins` block required and can be used with both legacy JSON and HCL2 templates.
+
+* [`packer plugins install`](/packer/docs/commands/plugins) will install plugins in the **last** directory
+in the following numbered list.
+
+1. `PACKER_PLUGINS_PATH` if set will be the sole location for installing plugins. All other
+plugin directories will be ignored.
+1. `PACKER_CONFIG_DIR`\plugins on Windows systems, or `PACKER_CONFIG_DIR`/plugins on all other systems.
+
+
+For manual installation of plugin binaries, without the `packer plugins` command, please continue reading.
+
+The easiest way to manually install a plugin is to name it correctly, then place
+it in the proper directory. To name a plugin correctly, make sure the binary is
+named `packer-plugin-NAME`. For example, `packer-plugin-amazon` for a "plugin"
+binary named "amazon". This binary will make one or more components available to
+use. Valid types for plugins are down this page.
+
+The valid types for plugins are:
+
+- `plugin` - A plugin binary that can contain one or more of each Packer component
+ type.
+
+- `builder` - Plugins responsible for building images for a specific
+ platform.
+
+- `post-processor` - A post-processor responsible for taking an artifact from
+ a builder and turning it into something else.
+
+- `provisioner` - A provisioner to install software on images created by a
+ builder.
+
+
+</Tab>
+<Tab heading="manually (single-component plugin)">
+
+The easiest way to manually install a plugin is to name it correctly, then place
+it in the proper directory. To name a plugin correctly, make sure the binary is
+named `packer-COMPONENT-NAME`. For example, `packer-provisioner-comment` for a "plugin"
+binary named "comment". This binary will make a single provisioner named `comment` available to
+use. Valid types for plugins are down this page.
+
+The valid types for plugins are:
+
+- `plugin` - A plugin binary that can contain one or more of each Packer component
+ type.
+
+- `builder` - Plugins responsible for building images for a specific
+ platform.
+
+- `post-processor` - A post-processor responsible for taking an artifact from
+ a builder and turning it into something else.
+
+- `provisioner` - A provisioner to install software on images created by a
+ builder.
+
+</Tab>
+</Tabs>
diff --git a/v1.9.4/website/content/docs/post-processors/artifice.mdx b/v1.9.4/website/content/docs/post-processors/artifice.mdx
new file mode 100644
index 0000000..e47fbf0
--- /dev/null
+++ b/v1.9.4/website/content/docs/post-processors/artifice.mdx
@@ -0,0 +1,173 @@
+---
+description: >
+ The artifice post-processor overrides the artifact list from an upstream
+
+ builder or post-processor. All downstream post-processors will see the new
+
+ artifacts you specify. The primary use-case is to build artifacts inside a
+
+ packer builder -- for example, spinning up an EC2 instance to build a Docker
+
+ container -- and then extracting the Docker container and throwing away the
+ EC2
+
+ instance.
+page_title: Artifice - Post-Processors
+---
+
+<BadgesHeader>
+ <PluginBadge type="official" />
+</BadgesHeader>
+
+# Artifice Post-Processor
+
+Type: `artifice`
+Artifact BuilderId: `packer.post-processor.artifice`
+
+The artifice post-processor overrides the artifact list from an upstream
+builder or post-processor. All downstream post-processors will see the new
+artifacts you specify.
+
+After overriding the artifact with artifice, you can use it with other
+post-processors, including most of the core post-processors and third-party
+post-processors.
+
+A major benefit of this is that you can modify builder
+artifacts using shell-local and pass those modified artifacts into
+post-processors that may not have worked with the original builder.
+For example, maybe you want to export a Docker container from an amazon-ebs
+builder and then use Docker-push to put that Docker container into your Docker
+Hub account.
+
+Artifice allows you to use the familiar packer workflow to create a fresh,
+stateless build environment for each build on the infrastructure of your
+choosing. You can use this to build just about anything: buildpacks,
+containers, jars, binaries, tarballs, msi installers, and more.
+
+Please note that the artifice post-processor will _not_ delete your old artifact
+files, even if it removes them from the artifact. If you want to delete the
+old artifact files, you can use the shell-local post-processor to do so.
+
+## Workflow
+
+Artifice helps you tie together a few other packer features:
+
+- A builder, which spins up a VM (or container) to build your artifact
+- A provisioner, which performs the steps to create your artifact
+- A file provisioner, which downloads the artifact from the VM
+- The artifice post-processor, which identifies which files have been
+ downloaded from the VM
+- Additional post-processors, which push the artifact to Docker hub, etc.
+
+You will want to perform as much work as possible inside the VM. Ideally the
+only other post-processor you need after artifice is one that uploads your
+artifact to the appropriate repository.
+
+## Configuration
+
+The configuration allows you to specify which files comprise your artifact.
+
+### Required:
+
+- `files` (array of strings) - A list of files that comprise your artifact.
+ These files must exist on your local disk after the provisioning phase of
+ packer is complete. These will replace any of the builder's original
+ artifacts (such as a VM snapshot).
+
+### Optional:
+
+- `keep_input_artifact` (boolean) - if true, do not delete the original
+ artifact files after creating your new artifact. Defaults to true.
+
+### Example Configuration
+
+This minimal example:
+
+1. Spins up a cloned VMware virtual machine
+2. Installs a [consul](https://www.consul.io/) release
+3. Downloads the consul binary
+4. Packages it into a `.tar.gz` file
+5. Uploads it to S3.
+
+VMX is a fast way to build and test locally, but you can easily substitute
+another builder.
+
+```json
+{
+ "builders": [
+ {
+ "type": "vmware-vmx",
+ "source_path": "/opt/ubuntu-1404-vmware.vmx",
+ "ssh_username": "vagrant",
+ "ssh_password": "vagrant",
+ "shutdown_command": "sudo shutdown -h now",
+ "headless": "true",
+ "skip_compaction": "true"
+ }
+ ],
+ "provisioners": [
+ {
+ "type": "shell",
+ "inline": [
+ "sudo apt-get install -y python-pip",
+ "sudo pip install ifs",
+ "sudo ifs install consul --version=0.5.2"
+ ]
+ },
+ {
+ "type": "file",
+ "source": "/usr/local/bin/consul",
+ "destination": "consul",
+ "direction": "download"
+ }
+ ],
+ "post-processors": [
+ [
+ {
+ "type": "artifice",
+ "files": ["consul"]
+ },
+ {
+ "type": "compress",
+ "output": "consul-0.5.2.tar.gz"
+ },
+ {
+ "type": "shell-local",
+ "inline": [
+ "/usr/local/bin/aws s3 cp consul-0.5.2.tar.gz s3://<s3 path>"
+ ]
+ }
+ ]
+ ]
+}
+```
+
+**Notice that there are two sets of square brackets in the post-processor
+section.** This creates a post-processor chain, where the output of the
+proceeding artifact is passed to subsequent post-processors. If you use only
+one set of square braces the post-processors will run individually against the
+build artifact (the vmx file in this case) and it will not have the desired
+result.
+
+```json
+{
+ "post-processors": [
+ [ // <--- Start post-processor chain
+ {
+ "type": "artifice",
+ "files": ["consul"]
+ },
+ {
+ "type": "compress",
+ ...
+ }
+ ], // <--- End post-processor chain
+ {
+ "type":"compress" // <-- Standalone post-processor
+ }
+ ]
+}
+```
+
+You can create multiple post-processor chains to handle multiple builders (for
+example, building Linux and Windows binaries during the same build).
diff --git a/v1.9.4/website/content/docs/post-processors/checksum.mdx b/v1.9.4/website/content/docs/post-processors/checksum.mdx
new file mode 100644
index 0000000..0f8056c
--- /dev/null
+++ b/v1.9.4/website/content/docs/post-processors/checksum.mdx
@@ -0,0 +1,85 @@
+---
+description: >
+ The checksum post-processor computes specified checksum for the artifact list
+ from an upstream builder or post-processor. All downstream post-processors
+ will see the new artifacts. The primary use-case is compute checksum for
+ artifacts allows to verify it later. So firstly this post-processor get
+ artifact, compute it checksum and pass to next post-processor original
+ artifacts and checksum files.
+page_title: Checksum - Post-Processors
+---
+
+<BadgesHeader>
+ <PluginBadge type="official" />
+</BadgesHeader>
+
+# Checksum Post-Processor
+
+Type: `checksum`
+Artifact BuilderId: `packer.post-processor.checksum`
+
+The checksum post-processor computes specified checksum for the artifact list
+from an upstream builder or post-processor. All downstream post-processors will
+see the new artifacts. The primary use-case is compute checksum for artifact to
+verify it later.
+
+After computes checksum for artifacts, you can use new artifacts with other
+post-processors like
+[artifice](/packer/docs/post-processors/artifice),
+[compress](/packer/docs/post-processors/compress),
+[docker-push](/packer/plugins/post-processors/docker/docker-push), or
+a third-party post-processor.
+
+## Basic example
+
+<Tabs>
+<Tab heading="JSON">
+
+```json
+{
+ "type": "checksum",
+ "checksum_types": ["sha1", "sha256"],
+ "output": "packer_{{.BuildName}}_{{.ChecksumType}}.checksum"
+}
+```
+
+</Tab>
+<Tab heading="HCL2">
+
+```hcl
+post-processor "checksum" {
+ checksum_types = ["sha1", "sha256"]
+ output = "packer_{{.BuildName}}_{{.ChecksumType}}.checksum"
+}
+```
+
+</Tab>
+</Tabs>
+
+## Configuration Reference
+
+Optional parameters:
+
+- `checksum_types` (array of strings) - An array of strings of checksum types
+ to compute. If empty, Defaults to md5. Allowed values are:
+
+ - md5
+ - sha1
+ - sha224
+ - sha256
+ - sha384
+ - sha512
+
+- `output` (string) - Specify filename to store checksums. This defaults to
+ `packer_{{.BuildName}}_{{.BuilderType}}_{{.ChecksumType}}.checksum`. For
+ example, if you had a builder named `database`, you might see the file
+ written as `packer_database_docker_md5.checksum`. This is treated as a
+ [template engine](/packer/docs/templates/legacy_json_templates/engine). Therefore, you
+ may use user variables and template functions in this field.
+ The following special variables are also available to use in the output
+ template:
+
+ - `BuildName`: The name of the builder that produced the artifact.
+ - `BuilderType`: The type of builder used to produce the artifact.
+ - `ChecksumType`: The type of checksums the file contains. This should be
+ used if you have more than one value in `checksum_types`.
diff --git a/v1.9.4/website/content/docs/post-processors/community-supported.mdx b/v1.9.4/website/content/docs/post-processors/community-supported.mdx
new file mode 100644
index 0000000..1be070e
--- /dev/null
+++ b/v1.9.4/website/content/docs/post-processors/community-supported.mdx
@@ -0,0 +1,16 @@
+---
+description: >
+ Community-maintained post-processors are not part of the core Packer binary,
+ but
+
+ can run alongside Packer with minimal extra effort.
+page_title: Community - Post-Processors
+---
+
+# Community Post-Processors
+
+The following post-processors are developed and maintained by various members of the
+Packer community, not by HashiCorp. For more information on how to use community
+post-processors, see our docs on [extending Packer](/packer/docs/plugins/creation).
+
+@include 'post-processors/community_post-processors.mdx'
diff --git a/v1.9.4/website/content/docs/post-processors/compress.mdx b/v1.9.4/website/content/docs/post-processors/compress.mdx
new file mode 100644
index 0000000..0a45ad1
--- /dev/null
+++ b/v1.9.4/website/content/docs/post-processors/compress.mdx
@@ -0,0 +1,87 @@
+---
+description: |
+ The Packer compress post-processor takes an artifact with files (such as from
+ VMware or VirtualBox) and compresses the artifact into a single archive.
+page_title: Compress - Post-Processors
+---
+
+<BadgesHeader>
+ <PluginBadge type="official" />
+</BadgesHeader>
+
+# Compress Post-Processor
+
+Type: `compress`
+Artifact BuilderId: `packer.post-processor.compress`
+
+The Packer compress post-processor takes an artifact with files (such as from
+VMware or VirtualBox) and compresses the artifact into a single archive.
+
+## Configuration
+
+### Optional:
+
+By default, packer will build archives in `.tar.gz` format with the following
+filename: `packer_{{.BuildName}}_{{.BuilderType}}`. If you want to change this
+you will need to specify the `output` option.
+
+- `output` (string) - The path to save the compressed archive. The archive
+ format is inferred from the filename. E.g. `.tar.gz` will be a gzipped
+ tarball. `.zip` will be a zip file. If the extension can't be detected
+ packer defaults to `.tar.gz` behavior but will not change the filename.
+
+ This is treated as a
+ [template engine](/packer/docs/templates/legacy_json_templates/engine). Therefore, you
+ may use user variables and template functions in this field.
+ The following special variables are also available to use in the output
+ template:
+
+ - `{{.BuildName}}`
+ - `{{.BuilderType}}`
+
+ If you are executing multiple builders in parallel you should make sure
+ `output` is unique for each one. For example `packer_{{.BuildName}}.zip`.
+
+- `format` (string) - Disable archive format autodetection and use provided
+ string.
+
+- `compression_level` (number) - Specify the compression level, for
+ algorithms that support it, from 1 through 9 inclusive. Typically higher
+ compression levels take longer but produce smaller files. Defaults to `6`
+
+- `keep_input_artifact` (boolean) - if `true`, keep both the source files and
+ the compressed file; if `false`, discard the source files. Defaults to
+ `false`
+
+### Supported Formats
+
+Supported file extensions include `.zip`, `.tar`, `.gz`, `.tar.gz`, `.lz4` and
+`.tar.lz4`. Note that `.gz` and `.lz4` will fail if you have multiple files to
+compress.
+
+## Examples
+
+Some minimal examples are shown below, showing only the post-processor
+configuration:
+
+```json
+{
+ "type": "compress",
+ "output": "archive.tar.lz4"
+}
+```
+
+```json
+{
+ "type": "compress",
+ "output": "{{.BuildName}}_bundle.zip"
+}
+```
+
+```json
+{
+ "type": "compress",
+ "output": "log_{{.BuildName}}.gz",
+ "compression_level": 9
+}
+```
diff --git a/v1.9.4/website/content/docs/post-processors/index.mdx b/v1.9.4/website/content/docs/post-processors/index.mdx
new file mode 100644
index 0000000..0db8b5c
--- /dev/null
+++ b/v1.9.4/website/content/docs/post-processors/index.mdx
@@ -0,0 +1,14 @@
+---
+description: |
+ Post-processors run after the image is built by the builder and provisioned by
+ the provisioner(s).
+page_title: Post-Processors
+---
+
+# Post-Processors
+
+Post-processors run after builders and provisioners. Post-processors are optional, and you can use them to upload artifacts, re-package files, and more. The documentation includes a page for each type of post-processor.
+
+Refer to the [`post-processor`](/packer/docs/templates/hcl_templates/blocks/build/post-processor) and
+[`post-processors`](/packer/docs/templates/hcl_templates/blocks/build/post-processors)
+blocks documentation to learn more about working with post-processors.
diff --git a/v1.9.4/website/content/docs/post-processors/manifest.mdx b/v1.9.4/website/content/docs/post-processors/manifest.mdx
new file mode 100644
index 0000000..6752243
--- /dev/null
+++ b/v1.9.4/website/content/docs/post-processors/manifest.mdx
@@ -0,0 +1,207 @@
+---
+description: >
+ The manifest post-processor writes a JSON file with the build artifacts and
+ IDs from a packer run.
+page_title: Manifest - Post-Processors
+---
+
+<BadgesHeader>
+ <PluginBadge type="official" />
+</BadgesHeader>
+
+# Manifest Post-Processor
+
+Type: `manifest`
+Artifact BuilderId: `packer.post-processor.manifest`
+
+The manifest post-processor writes a JSON file with a list of all of the
+artifacts packer produces during a run. If your Packer template includes
+multiple builds, this helps you keep track of which output artifacts (files,
+AMI IDs, Docker containers, etc.) correspond to each build.
+
+The manifest post-processor is invoked each time a build completes and
+_updates_ data in the manifest file. Builds are identified by name and type,
+and include their build time, artifact ID, and file list.
+
+If packer is run with the `-force` flag the manifest file will be truncated
+automatically during each packer run. Otherwise, subsequent builds will be
+added to the file. You can use the timestamps to see which is the latest
+artifact.
+
+You can specify manifest more than once and write each build to its own file,
+or write all builds to the same file. For simple builds manifest only needs to
+be specified once (see below) but you can also chain it together with other
+post-processors such as Docker and Artifice.
+
+## Configuration
+
+### Optional:
+
+@include 'post-processor/manifest/Config-not-required.mdx'
+
+~> **Note**: Unlike most other post-processors, the keep_input_artifact option doesn't apply for the manifest
+post-processor. We will always retain the input artifact for manifest, since deleting the files we just recorded
+is not a behavior anyone should ever expect.
+
+### Example Configuration
+
+The minimal way to use the manifest post-processor is by just writing its definition, like:
+
+<Tabs>
+<Tab heading="JSON">
+
+```json
+{
+ "post-processors": [
+ {
+ "type": "manifest"
+ }
+ ]
+}
+```
+
+</Tab>
+<Tab heading="HCL2">
+
+```hcl
+post-processor "manifest" {}
+```
+
+</Tab>
+</Tabs>
+
+A more complete example:
+
+<Tabs>
+<Tab heading="JSON">
+
+```json
+{
+ "post-processors": [
+ {
+ "type": "manifest",
+ "output": "manifest.json",
+ "strip_path": true,
+ "custom_data": {
+ "my_custom_data": "example"
+ }
+ }
+ ]
+}
+```
+
+</Tab>
+<Tab heading="HCL2">
+
+```hcl
+post-processor "manifest" {
+ output = "manifest.json"
+ strip_path = true
+ custom_data = {
+ my_custom_data = "example"
+ }
+}
+```
+
+</Tab>
+</Tabs>
+
+An example manifest file looks like:
+
+```json
+{
+ "builds": [
+ {
+ "name": "docker",
+ "builder_type": "docker",
+ "build_time": 1507245986,
+ "files": [
+ {
+ "name": "packer_example",
+ "size": 102219776
+ }
+ ],
+ "artifact_id": "Container",
+ "packer_run_uuid": "6d5d3185-fa95-44e1-8775-9e64fe2e2d8f",
+ "custom_data": {
+ "my_custom_data": "example"
+ }
+ }
+ ],
+ "last_run_uuid": "6d5d3185-fa95-44e1-8775-9e64fe2e2d8f"
+}
+```
+
+If the build is run again, the new build artifacts will be added to the
+manifest file rather than replacing it. It is possible to grab specific build
+artifacts from the manifest by using `packer_run_uuid`.
+
+The above manifest was generated with the following template:
+
+<Tabs>
+<Tab heading="JSON">
+
+```json
+{
+ "builders": [
+ {
+ "type": "docker",
+ "image": "ubuntu:latest",
+ "export_path": "packer_example",
+ "run_command": ["-d", "-i", "-t", "--entrypoint=/bin/bash", "{{.Image}}"]
+ }
+ ],
+ "post-processors": [
+ {
+ "type": "manifest",
+ "output": "manifest.json",
+ "strip_path": true,
+ "custom_data": {
+ "my_custom_data": "example"
+ }
+ }
+ ]
+}
+```
+
+</Tab>
+<Tab heading="HCL2">
+
+```hcl
+source "docker" "docker"{
+ image = "ubuntu:latest"
+ export_path = "packer_example"
+ run_command = ["-d", "-i", "-t", "--entrypoint=/bin/bash", "{{.Image}}"]
+}
+
+build {
+ sources = ["docker.docker"]
+
+ post-processor "manifest" {
+ output = "manifest.json"
+ strip_path = true
+ custom_data = {
+ my_custom_data = "example"
+ }
+ }
+}
+```
+
+</Tab>
+</Tabs>
+
+Example usage:
+
+The manifest can be very useful for cleaning up old artifacts, or printing
+important values to logs. The following example uses jq, a command-line tool for
+parsing json output, to find and echo the AWS ami-id of an AMI created by a
+build.
+
+```bash
+
+#!/bin/bash
+
+AMI_ID=$(jq -r '.builds[-1].artifact_id' manifest.json | cut -d ":" -f2)
+echo $AMI_ID
+
+```
diff --git a/v1.9.4/website/content/docs/post-processors/shell-local.mdx b/v1.9.4/website/content/docs/post-processors/shell-local.mdx
new file mode 100644
index 0000000..e04cd51
--- /dev/null
+++ b/v1.9.4/website/content/docs/post-processors/shell-local.mdx
@@ -0,0 +1,649 @@
+---
+description: |
+ The shell-local Packer post processor enables users to do some post processing
+ after artifacts have been built.
+page_title: Local Shell - Post-Processors
+---
+
+<BadgesHeader>
+ <PluginBadge type="official" />
+</BadgesHeader>
+
+# Local Shell Post Processor
+
+Type: `shell-local`
+
+The local shell post processor executes scripts locally during the post
+processing stage. Shell local provides a convenient way to automate executing
+some task with packer outputs and variables.
+
+## Basic example
+
+The example below is a fully functional self-contained build.
+
+<Tabs>
+<Tab heading="HCL2">
+
+```hcl
+source "file" "example" {
+ content = "example content"
+}
+
+build {
+ source "source.file.example" {
+ target = "./test_artifact.txt"
+ }
+
+ post-processor "shell-local" {
+ inline = ["echo foo"]
+ }
+}
+```
+
+</Tab>
+<Tab heading="JSON">
+
+```json
+{
+ "builders": [
+ {
+ "type": "file",
+ "name": "example",
+ "target": "./test_artifact.txt",
+ "content": "example content"
+ }
+ ],
+ "post-processors": [
+ {
+ "type": "shell-local",
+ "inline": ["echo foo"]
+ }
+ ]
+}
+```
+
+</Tab>
+</Tabs>
+
+## Configuration Reference
+
+The reference of available configuration options is listed below. The only
+required element is either "inline" or "script". Every other option is
+optional.
+
+Exactly _one_ of the following is required:
+
+- `command` (string) - This is a single command to execute. It will be
+ written to a temporary file and run using the `execute_command` call below.
+
+- `inline` (array of strings) - This is an array of commands to execute. The
+ commands are concatenated by newlines and turned into a single file, so
+ they are all executed within the same context. This allows you to change
+ directories in one command and use something in the directory in the next
+ and so on. Inline scripts are the easiest way to pull off simple tasks
+ within the machine.
+
+- `script` (string) - The path to a script to execute. This path can be
+ absolute or relative. If it is relative, it is relative to the working
+ directory when Packer is executed.
+
+- `scripts` (array of strings) - An array of scripts to execute. The scripts
+ will be executed in the order specified. Each script is executed in
+ isolation, so state such as variables from one script won't carry on to the
+ next.
+
+Optional parameters:
+
+- `env` (map of strings) - A map of key/value pairs to inject prior to the
+ execute_command. Packer injects some environmental variables by default into
+ the environment, as well, which are covered in the section below. Duplicate
+ `env` settings override `environment_vars` settings.
+
+- `environment_vars` (array of strings) - An array of key/value pairs to
+ inject prior to the `execute_command`. The format should be `key=value`.
+ Packer injects some environmental variables by default into the
+ environment, as well, which are covered in the section below.
+
+- `env_var_format` (string) - When we parse the environment_vars that you
+ provide, this gives us a string template to use in order to make sure that
+ we are setting the environment vars correctly. By default on Windows hosts
+ this format is `set %s=%s &&` and on Unix, it is `%s='%s'`. You probably
+ won't need to change this format, but you can see usage examples for where
+ it is necessary below.
+
+- `execute_command` (array of strings) - The command used to execute the
+ script. By default, on \*nix systems this is:
+
+ ```text
+ ["/bin/sh", "-c", "{{.Vars}} {{.Script}}"]
+ ```
+
+ While on Windows, `execute_command` defaults to:
+
+ ```text
+ ["cmd", "/V", "/C", "{{.Vars}}", "call", "{{.Script}}"]
+ ```
+
+ This is treated as a [template engine](/packer/docs/templates/legacy_json_templates/engine).
+ There are several available variables: `Script`, which is the path to the
+ script to run, and `Vars`, which is the list of `environment_vars`, if
+ configured. In addition, you may access any of the variables stored in the
+ generated data using the [build](/packer/docs/templates/legacy_json_templates/engine) template
+ function. If you choose to set this option, make sure that the first
+ element in the array is the shell program you want to use (for example,
+ "sh" or "/usr/local/bin/zsh" or even "powershell.exe" although anything
+ other than a flavor of the shell command language is not explicitly
+ supported and may be broken by assumptions made within Packer). It's
+ worth noting that if you choose to try to use shell-local for
+ Powershell or other Windows commands, the environment variables will
+ not be set properly for your environment.
+
+ For backwards compatibility, `execute_command` will accept a string instead
+ of an array of strings. If a single string or an array of strings with only
+ one element is provided, Packer will replicate past behavior by appending
+ your `execute_command` to the array of strings `["sh", "-c"]`. For example,
+ if you set `"execute_command": "foo bar"`, the final `execute_command` that
+ Packer runs will be \["sh", "-c", "foo bar"\]. If you set
+ `"execute_command": ["foo", "bar"]`, the final execute_command will remain
+ `["foo", "bar"]`.
+
+ Again, the above is only provided as a backwards compatibility fix; we
+ strongly recommend that you set execute_command as an array of strings.
+
+- `inline_shebang` (string) - The
+ [shebang](http://en.wikipedia.org/wiki/Shebang_%28Unix%29) value to use
+ when running commands specified by `inline`. By default, this is
+ `/bin/sh -e`. If you're not using `inline`, then this configuration has no
+ effect. **Important:** If you customize this, be sure to include something
+ like the `-e` flag, otherwise individual steps failing won't fail the
+ provisioner.
+
+- `keep_input_artifact` (boolean) - Unlike most other post-processors, the
+ keep_input_artifact option will have no effect for the shell-local
+ post-processor. Packer will always retain the input artifact for
+ shell-local, since the shell-local post-processor merely passes forward the
+ artifact it receives. If your shell-local post-processor produces a file or
+ files which you would like to have replace the input artifact, you may
+ overwrite the input artifact using the [artifice](/packer/docs/post-processors/artifice)
+ post-processor after your shell-local processor has run.
+
+- `only_on` (array of strings) - This is an array of [runtime operating
+ systems](https://go.dev/doc/install/source#environment) where
+ `shell-local` will execute. This allows you to execute `shell-local` _only_
+ on specific operating systems. By default, shell-local will always run if
+ `only_on` is not set."
+
+- `use_linux_pathing` (bool) - This is only relevant to Windows hosts. If you
+ are running Packer in a Windows environment with the Windows Subsystem for
+ Linux feature enabled, and would like to invoke a bash script rather than
+ invoking a Cmd script, you'll need to set this flag to true; it tells
+ Packer to use the Linux subsystem path for your script rather than the
+ Windows path. (e.g. /mnt/c/path/to/your/file instead of
+ C:/path/to/your/file). Please see the example below for more guidance on
+ how to use this feature. If you are not on a Windows host, or you do not
+ intend to use the shell-local post-processor to run a bash script, please
+ ignore this option. If you set this flag to true, you still need to provide
+ the standard Windows path to the script when providing a `script`. This is
+ a beta feature.
+
+- `valid_exit_codes` (list of ints) - Valid exit codes for the script. By
+ default this is `0`.
+
+## Execute Command
+
+To many new users, the `execute_command` is puzzling. However, it provides an
+important function: customization of how the command is executed. The most
+common use case for this is dealing with **sudo password prompts**. You may
+also need to customize this if you use a non-POSIX shell, such as `tcsh` on
+FreeBSD.
+
+### The Windows Linux Subsystem
+
+The shell-local post-processor was designed with the idea of allowing you to
+run commands in your local operating system's native shell. For Windows, we've
+assumed in our defaults that this is Cmd. However, it is possible to run a bash
+script as part of the Windows Linux Subsystem from the shell-local
+post-processor, by modifying the `execute_command` and the `use_linux_pathing`
+options in the post-processor config.
+
+The example below is a fully functional test config.
+
+One limitation of this offering is that "inline" and "command" options are not
+available to you; please limit yourself to using the "script" or "scripts"
+options instead.
+
+Please note that this feature is still in beta, as the underlying WSL is also
+still in beta. There will be some limitations as a result. For example, it will
+likely not work unless both Packer and the scripts you want to run are both on
+the C drive.
+
+<Tabs>
+<Tab heading="HCL2">
+
+```hcl
+source "null" "example" {
+ communicator = "none"
+}
+
+build {
+ sources = [
+ "source.null.example"
+ ]
+
+ post-processor "shell-local"{
+ environment_vars = ["PROVISIONERTEST=ProvisionerTest1"]
+ execute_command = ["bash", "-c", "{{.Vars}} {{.Script}}"]
+ use_linux_pathing = true
+ scripts = ["C:/Users/me/scripts/example_bash.sh"]
+ }
+ post-processor "shell-local"{
+ environment_vars = ["PROVISIONERTEST=ProvisionerTest2"]
+ execute_command = ["bash", "-c", "{{.Vars}} {{.Script}}"]
+ use_linux_pathing = true
+ script = "C:/Users/me/scripts/example_bash.sh"
+ }
+}
+```
+
+</Tab>
+<Tab heading="JSON">
+
+```json
+{
+ "builders": [
+ {
+ "type": "null",
+ "communicator": "none"
+ }
+ ],
+ "post-processors": [
+ {
+ "type": "shell-local",
+ "environment_vars": ["PROVISIONERTEST=ProvisionerTest1"],
+ "execute_command": ["bash", "-c", "{{.Vars}} {{.Script}}"],
+ "use_linux_pathing": true,
+ "scripts": ["C:/Users/me/scripts/example_bash.sh"]
+ },
+ {
+ "type": "shell-local",
+ "environment_vars": ["PROVISIONERTEST=ProvisionerTest2"],
+ "execute_command": ["bash", "-c", "{{.Vars}} {{.Script}}"],
+ "use_linux_pathing": true,
+ "script": "C:/Users/me/scripts/example_bash.sh"
+ }
+ ]
+}
+```
+
+</Tab>
+</Tabs>
+
+## Default Environmental Variables
+
+In addition to being able to specify custom environmental variables using the
+`environment_vars` configuration, the provisioner automatically defines certain
+commonly useful environmental variables:
+
+- `PACKER_BUILD_NAME` is set to the [name of the
+ build](/packer/docs/templates/legacy_json_templates/builders#named-builds) that Packer is running.
+ This is most useful when Packer is making multiple builds and you want to
+ distinguish them slightly from a common provisioning script.
+
+- `PACKER_BUILDER_TYPE` is the type of the builder that was used to create
+ the machine that the script is running on. This is useful if you want to
+ run only certain parts of the script on systems built with certain
+ builders.
+
+## Safely Writing A Script
+
+Whether you use the `inline` option, or pass it a direct `script` or `scripts`,
+it is important to understand a few things about how the shell-local
+post-processor works to run it safely and easily. This understanding will save
+you much time in the process.
+
+### Once Per Builder
+
+The `shell-local` script(s) you pass are run once per builder. This means that
+if you have an `amazon-ebs` builder and a `docker` builder, your script will be
+run twice. If you have 3 builders, it will run 3 times, once for each builder.
+
+### Interacting with Build Artifacts
+
+In order to interact with build artifacts, you may want to use the [manifest
+post-processor](/packer/docs/post-processors/manifest). This will write the list
+of files produced by a `builder` to a json file after each `builder` is run.
+
+For example, if you wanted to package a file from the file builder into a
+tarball, you might write this:
+
+<Tabs>
+<Tab heading="JSON">
+
+```json
+{
+ "builders": [
+ {
+ "content": "Lorem ipsum dolor sit amet",
+ "target": "dummy_artifact",
+ "type": "file"
+ }
+ ],
+ "post-processors": [
+ [
+ {
+ "output": "manifest.json",
+ "strip_path": true,
+ "type": "manifest"
+ },
+ {
+ "inline": [
+ "jq \".builds[].files[].name\" manifest.json | xargs tar cfz artifacts.tgz"
+ ],
+ "type": "shell-local"
+ }
+ ]
+ ]
+}
+```
+
+</Tab>
+<Tab heading="HCL2">
+
+```hcl
+source "file" "example" {
+ content = "Lorem ipsum dolor sit amet"
+ target = "dummy_artifact.txt"
+}
+build {
+ sources = [
+ "source.file.example"
+ ]
+ post-processor "manifest" {
+ output = "manifest.json"
+ strip_path = true
+ }
+
+ post-processor "shell-local" {
+ inline = [
+ "jq \".builds[].files[].name\" manifest.json | xargs tar cfz artifacts.tgz"
+ ]
+ }
+}
+```
+
+</Tab>
+</Tabs>
+
+This uses the [jq](https://stedolan.github.io/jq/) tool to extract all of the
+file names from the manifest file and passes them to tar.
+
+### Always Exit Intentionally
+
+If any post-processor fails, the `packer build` stops and all interim artifacts
+are cleaned up.
+
+For a shell script, that means the script **must** exit with a zero code. You
+_must_ be extra careful to `exit 0` when necessary.
+
+## Usage Examples:
+
+### Windows Host
+
+Example of running a .cmd file on Windows:
+
+<Tabs>
+<Tab heading="HCL2">
+
+```hcl
+post-processor "shell-local" {
+ environment_vars = ["SHELLLOCALTEST=ShellTest1"]
+ scripts = ["./scripts/test_cmd.cmd"]
+}
+```
+
+</Tab>
+<Tab heading="JSON">
+
+```json
+{
+ "type": "shell-local",
+ "environment_vars": ["SHELLLOCALTEST=ShellTest1"],
+ "scripts": ["./scripts/test_cmd.cmd"]
+}
+```
+
+</Tab>
+</Tabs>
+
+Contents of `test_cmd.cmd`:
+
+ echo %SHELLLOCALTEST%
+
+Example of running an inline command on Windows: Required customization:
+tempfile_extension
+
+<Tabs>
+<Tab heading="HCL2">
+
+```hcl
+post-processor "shell-local" {
+ environment_vars = ["SHELLLOCALTEST=ShellTest2"],
+ tempfile_extension = ".cmd",
+ inline = ["echo %SHELLLOCALTEST%"]
+}
+```
+
+</Tab>
+<Tab heading="JSON">
+
+```json
+{
+ "type": "shell-local",
+ "environment_vars": ["SHELLLOCALTEST=ShellTest2"],
+ "tempfile_extension": ".cmd",
+ "inline": ["echo %SHELLLOCALTEST%"]
+}
+```
+
+</Tab>
+</Tabs>
+
+Example of running a bash command on Windows using WSL: Required
+customizations: `use_linux_pathing` and `execute_command`:
+
+<Tabs>
+<Tab heading="HCL2">
+
+```hcl
+post-processor "shell-local" {
+ environment_vars = ["SHELLLOCALTEST=ShellTest3"],
+ execute_command = ["bash", "-c", "{{.Vars}} {{.Script}}"]
+ use_linux_pathing = true
+ script = "./scripts/example_bash.sh"
+}
+```
+
+</Tab>
+<Tab heading="JSON">
+
+```json
+{
+ "type": "shell-local",
+ "environment_vars": ["SHELLLOCALTEST=ShellTest3"],
+ "execute_command": ["bash", "-c", "{{.Vars}} {{.Script}}"],
+ "use_linux_pathing": true,
+ "script": "./scripts/example_bash.sh"
+}
+```
+
+</Tab>
+</Tabs>
+
+Contents of `example_bash.sh`:
+
+ #!/bin/bash
+ echo $SHELLLOCALTEST
+
+Example of running a PowerShell script on Windows:
+Required customizations: `env_var_format` and `execute_command`.
+
+<Tabs>
+<Tab heading="HCL2">
+
+```hcl
+post-processor "shell-local" {
+ environment_vars = ["SHELLLOCALTEST=ShellTest4"]
+ execute_command = ["powershell.exe", "{{.Vars}} {{.Script}}"]
+ env_var_format = "$env:%s=\"%s\"; "
+ script = "./scripts/example_ps.ps1"
+}
+```
+
+</Tab>
+<Tab heading="JSON">
+
+```json
+{
+ "type": "shell-local",
+ "environment_vars": ["SHELLLOCALTEST=ShellTest4"],
+ "execute_command": ["powershell.exe", "{{.Vars}} {{.Script}}"],
+ "env_var_format": "$env:%s=\"%s\"; ",
+ "script": "./scripts/example_ps.ps1"
+}
+```
+
+</Tab>
+</Tabs>
+
+Example of running a PowerShell script on Windows as "inline": Required
+customizations: `env_var_format`, `tempfile_extension`, and `execute_command`
+
+<Tabs>
+<Tab heading="HCL2">
+
+```hcl
+post-processor "shell-local" {
+ tempfile_extension = ".ps1"
+ environment_vars = ["SHELLLOCALTEST=ShellTest5"]
+ execute_command = ["powershell.exe", "{{.Vars}} {{.Script}}"]
+ env_var_format = "$env:%s=\"%s\"; "
+ inline = ["write-output $env:SHELLLOCALTEST"]
+}
+```
+
+</Tab>
+<Tab heading="JSON">
+
+```json
+{
+ "type": "shell-local",
+ "tempfile_extension": ".ps1",
+ "environment_vars": ["SHELLLOCALTEST=ShellTest5"],
+ "execute_command": ["powershell.exe", "{{.Vars}} {{.Script}}"],
+ "env_var_format": "$env:%s=\"%s\"; ",
+ "inline": ["write-output $env:SHELLLOCALTEST"]
+}
+```
+
+</Tab>
+</Tabs>
+
+### Unix Host
+
+Example of running a Shell script on Unix:
+
+<Tabs>
+<Tab heading="HCL2">
+
+```hcl
+post-processor "shell-local" {
+ environment_vars = ["PROVISIONERTEST=ProvisionerTest1"]
+ scripts = ["./scripts/example_bash.sh"]
+}
+```
+
+</Tab>
+<Tab heading="JSON">
+
+```json
+{
+ "type": "shell-local",
+ "environment_vars": ["PROVISIONERTEST=ProvisionerTest1"],
+ "scripts": ["./scripts/example_bash.sh"]
+}
+```
+
+</Tab>
+</Tabs>
+
+Example of running a bash "inline" on Unix:
+
+<Tabs>
+<Tab heading="HCL2">
+
+```hcl
+post-processor "shell-local" {
+ environment_vars = ["PROVISIONERTEST=ProvisionerTest2"]
+ inline = ["echo hello", "echo $PROVISIONERTEST"]
+}
+
+```
+
+</Tab>
+<Tab heading="JSON">
+
+```json
+{
+ "type": "shell-local",
+ "environment_vars": ["PROVISIONERTEST=ProvisionerTest2"],
+ "inline": ["echo hello", "echo $PROVISIONERTEST"]
+}
+```
+
+</Tab>
+</Tabs>
+
+Example of running a Python script on Unix:
+
+<Tabs>
+<Tab heading="HCL2">
+
+```hcl
+post-processor "shell-local" {
+ script = "hello.py"
+ environment_vars = ["HELLO_USER=packeruser"]
+ execute_command = [
+ "/bin/sh",
+ "-c",
+ "{{.Vars}} /usr/local/bin/python {{.Script}}"
+ ]
+}
+
+```
+
+</Tab>
+<Tab heading="JSON">
+
+```json
+{
+ "type": "shell-local",
+ "script": "hello.py",
+ "environment_vars": ["HELLO_USER=packeruser"],
+ "execute_command": [
+ "/bin/sh",
+ "-c",
+ "{{.Vars}} /usr/local/bin/python {{.Script}}"
+ ]
+}
+```
+
+</Tab>
+</Tabs>
+
+```text
+Where "hello.py" contains:
+
+ import os
+
+ print('Hello, %s!' % os.getenv("HELLO_USER"))
+```
diff --git a/v1.9.4/website/content/docs/provisioners/breakpoint.mdx b/v1.9.4/website/content/docs/provisioners/breakpoint.mdx
new file mode 100644
index 0000000..b7585fd
--- /dev/null
+++ b/v1.9.4/website/content/docs/provisioners/breakpoint.mdx
@@ -0,0 +1,113 @@
+---
+description: >
+ The breakpoint provisioner will pause until the user presses "enter" to resume
+
+ the build. This is intended for debugging purposes, and allows you to halt at
+ a
+
+ particular part of the provisioning process.
+page_title: breakpoint - Provisioners
+---
+
+<BadgesHeader>
+ <PluginBadge type="official" />
+</BadgesHeader>
+
+# Breakpoint Provisioner
+
+Type: `breakpoint`
+
+The breakpoint provisioner will pause until the user presses "enter" to resume
+the build. This is intended for debugging purposes, and allows you to halt at a
+particular part of the provisioning process.
+
+This is independent of the `-debug` flag, which will instead halt at every step
+and between every provisioner.
+
+## Basic Example
+
+<Tabs>
+<Tab heading="JSON">
+
+```json
+{
+ "builders": [
+ {
+ "type": "null",
+ "communicator": "none"
+ }
+ ],
+ "provisioners": [
+ {
+ "type": "shell-local",
+ "inline": "echo hi"
+ },
+ {
+ "type": "breakpoint",
+ "disable": false,
+ "note": "this is a breakpoint"
+ },
+ {
+ "type": "shell-local",
+ "inline": "echo hi 2"
+ }
+ ]
+}
+```
+
+</Tab>
+<Tab heading="HCL2">
+
+```hcl
+source "null" "example" {
+ communicator = "none"
+}
+
+build {
+ sources = ["source.null.example"]
+
+ provisioner "shell-local" {
+ inline = ["echo hi"]
+ }
+ provisioner "breakpoint" {
+ disable = false
+ note = "this is a breakpoint"
+ }
+ provisioner "shell-local" {
+ inline = ["echo hi 2"]
+ }
+}
+```
+
+</Tab>
+</Tabs>
+
+## Configuration Reference
+
+### Optional
+
+- `disable` (boolean) - If `true`, skip the breakpoint. Useful for when you
+ have set multiple breakpoints and want to toggle them off or on. Default:
+ `false`
+
+- `note` (string) - a string to include explaining the purpose or location of
+ the breakpoint. For example, you may find it useful to number your
+ breakpoints or label them with information about where in the build they
+ occur
+
+@include 'provisioners/common-config.mdx'
+
+## Usage
+
+Insert this provisioner wherever you want the build to pause. You'll see ui
+output prompting you to press "enter" to continue the build when you are ready.
+
+For example:
+
+```shell-session
+==> docker: Pausing at breakpoint provisioner with note "foo bar baz".
+==> docker: Press enter to continue.
+```
+
+Once you press enter, the build will resume and run normally until it either
+completes or errors.
diff --git a/v1.9.4/website/content/docs/provisioners/community-supported.mdx b/v1.9.4/website/content/docs/provisioners/community-supported.mdx
new file mode 100644
index 0000000..1cb14aa
--- /dev/null
+++ b/v1.9.4/website/content/docs/provisioners/community-supported.mdx
@@ -0,0 +1,14 @@
+---
+description: |
+ Community-maintained provisioners are not part of the core Packer binary, but
+ can run alongside Packer with minimal extra effort.
+page_title: Community - Provisioners
+---
+
+# Community Provisioners
+
+The following provisioners are developed and maintained by various members of the
+Packer community, not by HashiCorp. For more information on how to use community
+provisioners, see our docs on [extending Packer](/packer/docs/plugins/creation).
+
+@include 'provisioners/community_provisioners.mdx'
diff --git a/v1.9.4/website/content/docs/provisioners/custom.mdx b/v1.9.4/website/content/docs/provisioners/custom.mdx
new file mode 100644
index 0000000..5606844
--- /dev/null
+++ b/v1.9.4/website/content/docs/provisioners/custom.mdx
@@ -0,0 +1,16 @@
+---
+description: |
+ Packer is extensible, allowing you to write new provisioners without having to
+ modify the core source code of Packer itself. Documentation for creating new
+ provisioners is covered in the custom provisioners page of the Packer plugin
+ section.
+page_title: Custom - Provisioners
+---
+
+# Custom Provisioner
+
+Packer is extensible, allowing you to write new provisioners without having to
+modify the core source code of Packer itself. Documentation for creating new
+provisioners is covered in the [custom
+provisioners](/packer/docs/plugins/creation/custom-provisioners) page of the Packer
+plugin section.
diff --git a/v1.9.4/website/content/docs/provisioners/file.mdx b/v1.9.4/website/content/docs/provisioners/file.mdx
new file mode 100644
index 0000000..e123be9
--- /dev/null
+++ b/v1.9.4/website/content/docs/provisioners/file.mdx
@@ -0,0 +1,192 @@
+---
+description: |
+ The file Packer provisioner uploads files to machines built by Packer. The
+ recommended usage of the file provisioner is to use it to upload files, and
+ then use shell provisioner to move them to the proper place, set permissions,
+ etc.
+page_title: File - Provisioners
+---
+
+<BadgesHeader>
+ <PluginBadge type="official" />
+</BadgesHeader>
+
+# File Provisioner
+
+Type: `file`
+
+The file Packer provisioner uploads files to machines built by Packer. The
+recommended usage of the file provisioner is to use it to upload files, and
+then use [shell provisioner](/packer/docs/provisioners/shell) to move them to the
+proper place, set permissions, etc.
+
+Warning: You can only upload files to locations that the provisioning user
+(generally not root) has permission to access. Creating files in /tmp and
+using a shell provisioner to move them into the final location is the only
+way to upload files to root owned locations.
+
+The file provisioner can upload both single files and complete directories.
+
+## Basic Example
+
+<Tabs>
+<Tab heading="JSON">
+
+```json
+{
+ "type": "file",
+ "source": "app.tar.gz",
+ "destination": "/tmp/app.tar.gz"
+}
+```
+
+</Tab>
+<Tab heading="HCL2">
+
+```hcl
+provisioner "file" {
+ source = "app.tar.gz"
+ destination = "/tmp/app.tar.gz"
+}
+```
+
+</Tab>
+</Tabs>
+
+## Configuration Reference
+
+The available configuration options are listed below.
+
+## Configuration Reference
+
+Required Parameters:
+
+@include 'provisioner/file/Config-required.mdx'
+
+Optional Parameters:
+
+@include '/provisioner/file/Config-not-required.mdx'
+
+@include 'provisioners/common-config.mdx'
+
+## Directory Uploads
+
+The file provisioner is also able to upload a complete directory to the remote
+machine. When uploading a directory, there are a few important things you
+should know.
+
+First, the destination directory must already exist. If you need to create it,
+use a shell provisioner just prior to the file provisioner in order to create
+the directory. If the destination directory does not exist, the file
+provisioner may succeed, but it will have undefined results.
+
+Next, the existence of a trailing slash on the source path will determine
+whether the directory name will be embedded within the destination, or whether
+the destination will be created. An example explains this best:
+
+If the source is `/foo` (no trailing slash), and the destination is `/tmp`,
+then the contents of `/foo` on the local machine will be uploaded to `/tmp/foo`
+on the remote machine. The `foo` directory on the remote machine will be
+created by Packer.
+
+If the source, however, is `/foo/` (a trailing slash is present), and the
+destination is `/tmp`, then the contents of `/foo` will be uploaded into `/tmp`
+directly.
+
+This behavior was adopted from the standard behavior of rsync. Note that under
+the covers, rsync may or may not be used.
+
+## Uploading files that don't exist before Packer starts
+
+In general, local files used as the source **must** exist before Packer is run.
+This is great for catching typos and ensuring that once a build is started,
+that it will succeed. However, this also means that you can't generate a file
+during your build and then upload it using the file provisioner later. A
+convenient workaround is to upload a directory instead of a file. The directory
+still must exist, but its contents don't. You can write your generated file to
+the directory during the Packer run, and have it be uploaded later.
+
+## Symbolic link uploads
+
+The behavior when uploading symbolic links depends on the communicator. The
+Docker communicator will preserve symlinks, but all other communicators will
+treat local symlinks as regular files. If you wish to preserve symlinks when
+uploading, it's recommended that you use `tar`. Below is an example of what
+that might look like:
+
+```shell-session
+$ ls -l files
+total 16
+drwxr-xr-x 3 mwhooker staff 102 Jan 27 17:10 a
+lrwxr-xr-x 1 mwhooker staff 1 Jan 27 17:10 b -> a
+-rw-r--r-- 1 mwhooker staff 0 Jan 27 17:10 file1
+lrwxr-xr-x 1 mwhooker staff 5 Jan 27 17:10 file1link -> file1
+$ ls -l toupload
+total 0
+-rw-r--r-- 1 mwhooker staff 0 Jan 27 17:10 files.tar
+```
+
+<Tabs>
+<Tab heading="JSON">
+
+```json
+{
+ "provisioners": [
+ {
+ "type": "shell-local",
+ "command": "tar cf toupload/files.tar files"
+ },
+ {
+ "destination": "/tmp/",
+ "source": "./toupload",
+ "type": "file"
+ },
+ {
+ "inline": [
+ "cd /tmp && tar xf toupload/files.tar",
+ "rm toupload/files.tar"
+ ],
+ "type": "shell"
+ }
+ ]
+}
+```
+
+</Tab>
+<Tab heading="HCL2">
+
+```hcl
+build {
+ sources = [
+ "source.docker.example"
+ ]
+
+ provisioner "shell-local" {
+ command = "tar cf toupload/files.tar files"
+ }
+ provisioner "file" {
+ destination = "/tmp/"
+ source = "./toupload"
+ }
+ provisioner "shell" {
+ inline = [
+ "cd /tmp && tar xf toupload/files.tar",
+ "rm toupload/files.tar"
+ ]
+ }
+}
+```
+
+</Tab>
+</Tabs>
+
+## Slowness when transferring large files over WinRM.
+
+Because of the way our WinRM transfers works, it can take a very long time to
+upload and download even moderately sized files. If you're experiencing slowness
+using the file provisioner on Windows, it's suggested that you set up an SSH
+server and use the [ssh communicator](/packer/docs/communicators/ssh). If you only want
+to transfer files to your guest, and if your builder supports it, you may also
+use the `http_directory` or `http_content` directives. This will cause that
+directory to be available to the guest over HTTP, and set the environment
+variable `PACKER_HTTP_ADDR` to the address.
diff --git a/v1.9.4/website/content/docs/provisioners/index.mdx b/v1.9.4/website/content/docs/provisioners/index.mdx
new file mode 100644
index 0000000..e9fb2f8
--- /dev/null
+++ b/v1.9.4/website/content/docs/provisioners/index.mdx
@@ -0,0 +1,19 @@
+---
+description: |
+ Provisioners use builtin and third-party software to install and configure the
+ machine image after booting.
+page_title: Provisioners
+---
+
+# Provisioners
+
+Provisioners use built-in and third-party software to install and configure the
+machine image after booting. Provisioners prepare the system, so you may want to use them for the following use cases:
+
+- installing packages
+- patching the kernel
+- creating users
+- downloading application code
+
+Refer to the [`provisioner`](/packer/docs/templates/hcl_templates/blocks/build/provisioner) block documentation to learn more
+about working with provisioners. The documentation includes details about each type of provisioner.
diff --git a/v1.9.4/website/content/docs/provisioners/powershell.mdx b/v1.9.4/website/content/docs/provisioners/powershell.mdx
new file mode 100644
index 0000000..c50b851
--- /dev/null
+++ b/v1.9.4/website/content/docs/provisioners/powershell.mdx
@@ -0,0 +1,483 @@
+---
+description: |
+ The PowerShell Packer provisioner runs PowerShell scripts on Windows machines.
+ It assumes that the communicator in use is WinRM.
+page_title: PowerShell - Provisioners
+---
+
+<BadgesHeader>
+ <PluginBadge type="official" />
+</BadgesHeader>
+
+# PowerShell Provisioner
+
+Type: `powershell`
+
+The PowerShell Packer provisioner runs PowerShell scripts on Windows machines.
+It assumes that the communicator in use is WinRM. However, the provisioner can
+work equally well (with a few caveats) when combined with the SSH communicator.
+See the [section
+below](#combining-the-powershell-provisioner-with-the-ssh-communicator) for
+details.
+
+`@include 'path/separator-note.mdx'`
+
+## Basic Example
+
+The example below is fully functional.
+
+<Tabs>
+<Tab heading="HCL2">
+
+```hcl
+provisioner "powershell" {
+ inline = ["dir c:/"]
+}
+```
+
+</Tab>
+<Tab heading="JSON">
+
+```json
+{
+ "type": "powershell",
+ "inline": ["dir c:/"]
+}
+```
+
+</Tab>
+</Tabs>
+
+## Configuration Reference
+
+@include 'provisioners/shell-config.mdx'
+
+- `debug_mode` - If set, sets PowerShell's [PSDebug mode](https://docs.microsoft.com/en-us/powershell/module/microsoft.powershell.core/set-psdebug?view=powershell-7)
+ in order to make script debugging easier. For instance, setting the value to 1
+ results in adding this to the execute command:
+
+ ```powershell
+ Set-PSDebug -Trace 1
+ ```
+
+- `elevated_execute_command` (string) - The command to use to execute the
+ elevated script. By default this is as follows:
+
+ ```powershell
+ powershell -executionpolicy bypass "& { if (Test-Path variable:global:ProgressPreference){$ProgressPreference='SilentlyContinue'};. {{.Vars}}; &'{{.Path}}'; exit $LastExitCode }"
+ ```
+
+ This is a [template engine](/packer/docs/templates/legacy_json_templates/engine).
+ Therefore, you may use user variables and template functions in this field. In
+ addition, you may use two extra variables:
+
+ - `Path`: The path to the script to run
+ - `Vars`: The location of a temp file containing the list of
+ `environment_vars`, if configured.
+
+- `env` (map of strings) - A map of key/value pairs to inject prior to the
+ execute_command. Packer injects some environmental variables by default into
+ the environment, as well, which are covered in the section below. Duplicate
+ `env` settings override `environment_vars` settings. This is not a JSON
+ template engine enabled function. HCL interpolation works as usual.
+
+- `environment_vars` (array of strings) - An array of key/value pairs to
+ inject prior to the execute_command. The format should be `key=value`.
+ Packer injects some environmental variables by default into the
+ environment, as well, which are covered in the section below.
+
+- `use_pwsh` (boolean) - Run `pwsh.exe` instead of `powershell.exe`. Defaults to false.
+
+ This is a [template engine](/packer/docs/templates/legacy_json_templates/engine). Therefore, you
+ may use user variables and template functions in this field. If you are
+ running on AWS, Azure, Google Compute, or OpenStack and would like to access
+ the autogenerated password that Packer uses to connect to the instance via
+ WinRM, you can use the `build` template engine to inject it using
+ `` {{ build `Password` }} ``. In HCL templates, you can do the same thing by
+ accessing the `build` variables For example:
+
+<Tabs>
+<Tab heading="HCL2">
+
+```hcl
+provisioner "powershell" {
+ environment_vars = ["WINRMPASS=${build.Password}"]
+ inline = ["Write-Host \"Automatically generated aws password is: $Env:WINRMPASS\""]
+}
+```
+
+</Tab>
+<Tab heading="JSON">
+
+```json
+{
+ "type": "powershell",
+ "environment_vars": ["WINRMPASS={{ build `Password` }}"],
+ "inline": ["Write-Host \"Automatically generated aws password is: $Env:WINRMPASS\""]
+},
+```
+
+</Tab>
+</Tabs>
+
+- `execute_command` (string) - The command to use to execute the script. By
+ default this is as follows:
+
+ ```powershell
+ powershell -executionpolicy bypass "& { if (Test-Path variable:global:ProgressPreference){$ProgressPreference='SilentlyContinue'};. {{.Vars}}; &'{{.Path}}'; exit $LastExitCode }"
+ ```
+
+ This is a [template engine](/packer/docs/templates/legacy_json_templates/engine).
+ Therefore, you may use user variables and template functions in this field. In
+ addition, you may use two extra variables:
+
+ - `Path`: The path to the script to run
+ - `Vars`: The location of a temp file containing the list of
+ `environment_vars`, if configured.
+ The value of both `Path` and `Vars` can be manually configured by setting
+ the values for `remote_path` and `remote_env_var_path` respectively.
+
+ If you use the SSH communicator and have changed your default shell, you
+ may need to modify your `execute_command` to make sure that the command is
+ valid and properly escaped; the default assumes that you have not changed
+ the default shell away from cmd.
+
+- `elevated_user` and `elevated_password` (string) - If specified, the
+ PowerShell script will be run with elevated privileges using the given
+ Windows user.
+
+ This is a [template engine](/packer/docs/templates/legacy_json_templates/engine). Therefore, you
+ may use user variables and template functions in this field. If you are
+ running on AWS, Azure, Google Compute, or OpenStack and would like to access
+ the autogenerated password that Packer uses to connect to the instance via
+ WinRM, you can use the `build` template engine to inject it using
+ `` {{ build `Password` }} ``. In HCL templates, you can do the same thing by
+ accessing the `build` variables For example:
+
+<Tabs>
+<Tab heading="HCL2">
+
+```hcl
+provisioner "powershell" {
+ elevated_user = "Administrator"
+ elevated_password = build.Password
+}
+```
+
+</Tab>
+<Tab heading="JSON">
+
+```json
+{
+ "type": "powershell",
+ "elevated_user": "Administrator",
+ "elevated_password": "{{ build `Password` }}",
+ ...
+},
+```
+
+</Tab>
+</Tabs>
+
+If you specify an empty `elevated_password` value then the PowerShell
+script is run as a service account. For example:
+
+<Tabs>
+<Tab heading="HCL2">
+
+```hcl
+provisioner "powershell" {
+ elevated_user = "SYSTEM"
+ elevated_password = ""
+}
+```
+
+</Tab>
+<Tab heading="JSON">
+
+```json
+{
+ "type": "powershell",
+ "elevated_user": "SYSTEM",
+ "elevated_password": "",
+ ...
+},
+```
+
+</Tab>
+</Tabs>
+
+- `execution_policy` - To run ps scripts on Windows, Packer defaults this to
+ "bypass" and wraps the command to run. Setting this to "none" will prevent
+ wrapping, allowing to see exit codes on Docker for Windows. Possible values
+ are `bypass`, `allsigned`, `default`, `remotesigned`, `restricted`,
+ `undefined`, `unrestricted`, and `none`.
+
+- `remote_path` (string) - The path where the PowerShell script will be
+ uploaded to within the target build machine. This defaults to
+ `C:/Windows/Temp/script-UUID.ps1` where UUID is replaced with a dynamically
+ generated string that uniquely identifies the script.
+
+ This setting allows users to override the default upload location. The
+ value must be a writable location and any parent directories must already
+ exist.
+
+- `remote_env_var_path` (string) - Environment variables required within the
+ remote environment are uploaded within a PowerShell script and then enabled
+ by 'dot sourcing' the script immediately prior to execution of the main
+ command or script.
+
+ The path the environment variables script will be uploaded to defaults to
+ `C:/Windows/Temp/packer-ps-env-vars-UUID.ps1` where UUID is replaced with a
+ dynamically generated string that uniquely identifies the script.
+
+ This setting allows users to override the location the environment variable
+ script is uploaded to. The value must be a writable location and any parent
+ directories must already exist.
+
+- `skip_clean` (bool) - Whether to clean scripts up after executing the provisioner.
+ Defaults to false. When true any script created by a non-elevated Powershell
+ provisioner will be removed from the remote machine. Elevated scripts,
+ along with the scheduled tasks, will always be removed regardless of the
+ value set for `skip_clean`.
+
+- `start_retry_timeout` (string) - The amount of time to attempt to _start_
+ the remote process. By default this is `5m` or 5 minutes. This setting
+ exists in order to deal with times when SSH may restart, such as a system
+ reboot. Set this to a higher value if reboots take a longer amount of time.
+
+- `pause_after` (string) - Wait the amount of time after provisioning a PowerShell
+ script, this pause be taken if all previous steps were successful.
+
+@include 'provisioners/common-config.mdx'
+
+## Default Environmental Variables
+
+In addition to being able to specify custom environmental variables using the
+`environment_vars` configuration, the provisioner automatically defines certain
+commonly useful environmental variables:
+
+- `PACKER_BUILD_NAME` is set to the [name of the
+ build](/packer/docs/templates/legacy_json_templates/builders#named-builds) that Packer is running.
+ This is most useful when Packer is making multiple builds and you want to
+ distinguish them slightly from a common provisioning script.
+
+- `PACKER_BUILDER_TYPE` is the type of the builder that was used to create
+ the machine that the script is running on. This is useful if you want to
+ run only certain parts of the script on systems built with certain
+ builders.
+
+- `PACKER_HTTP_ADDR` If using a builder that provides an HTTP server for file
+ transfer (such as `hyperv`, `parallels`, `qemu`, `virtualbox`, and `vmware`), this
+ will be set to the address. You can use this address in your provisioner to
+ download large files over HTTP. This may be useful if you're experiencing
+ slower speeds using the default file provisioner. A file provisioner using
+ the `winrm` communicator may experience these types of difficulties.
+
+## Combining the PowerShell Provisioner with the SSH Communicator
+
+The good news first. If you are using the [Microsoft port of
+OpenSSH](https://github.com/PowerShell/Win32-OpenSSH/wiki) then the provisioner
+should just work as expected - no extra configuration effort is required.
+
+Now the caveats. If you are using an alternative configuration, and your SSH
+connection lands you in a \*nix shell on the remote host, then you will most
+likely need to manually set the `execute_command`; The default
+`execute_command` used by Packer will not work for you. When configuring the
+command you will need to ensure that any dollar signs or other characters that
+may be incorrectly interpreted by the remote shell are escaped accordingly.
+
+The following example shows how the standard `execute_command` can be
+reconfigured to work on a remote system with
+[Cygwin/OpenSSH](https://cygwin.com/) installed. The `execute_command` has each
+dollar sign backslash escaped so that it is not interpreted by the remote Bash
+shell - Bash being the default shell for Cygwin environments.
+
+<Tabs>
+<Tab heading="HCL2">
+
+```hcl
+provisioner "powershell" {
+ execute_command = "powershell -executionpolicy bypass \"& { if (Test-Path variable:global:ProgressPreference){\\$ProgressPreference='SilentlyContinue'};. {{.Vars}}; &'{{.Path}}'; exit \\$LastExitCode }\""
+ inline = [ "Write-Host \"Hello from PowerShell\""]
+}
+```
+
+</Tab>
+<Tab heading="JSON">
+
+```json
+"provisioners": [
+ {
+ "type": "powershell",
+ "execute_command": "powershell -executionpolicy bypass \"& { if (Test-Path variable:global:ProgressPreference){\\$ProgressPreference='SilentlyContinue'};. {{.Vars}}; &'{{.Path}}'; exit \\$LastExitCode }\"",
+ "inline": ["Write-Host \"Hello from PowerShell\""]
+ }
+]
+```
+
+</Tab>
+</Tabs>
+
+## Packer's Handling of Characters Special to PowerShell
+
+The escape character in PowerShell is the `backtick`, also sometimes referred
+to as the `grave accent`. When, and when not, to escape characters special to
+PowerShell is probably best demonstrated with a series of examples.
+
+### When To Escape...
+
+Users need to deal with escaping characters special to PowerShell when they
+appear _directly_ in commands used in the `inline` PowerShell provisioner and
+when they appear _directly_ in the users own scripts. Note that where double
+quotes appear within double quotes, the addition of a backslash escape is
+required for the JSON template to be parsed correctly.
+
+<Tabs>
+<Tab heading="HCL2">
+
+```hcl
+provisioner "powershell" {
+ inline = [
+ "Write-Host \"A literal dollar `$ must be escaped\"",
+ "Write-Host \"A literal backtick `` must be escaped\"",
+ "Write-Host \"Here `\"double quotes`\" must be escaped\"",
+ "Write-Host \"Here `'single quotes`' don`'t really need to be\"",
+ "Write-Host \"escaped... but it doesn`'t hurt to do so.\"",
+ ]
+}
+```
+
+</Tab>
+<Tab heading="JSON">
+
+```json
+ "provisioners": [
+ {
+ "type": "powershell",
+ "inline": [
+ "Write-Host \"A literal dollar `$ must be escaped\"",
+ "Write-Host \"A literal backtick `` must be escaped\"",
+ "Write-Host \"Here `\"double quotes`\" must be escaped\"",
+ "Write-Host \"Here `'single quotes`' don`'t really need to be\"",
+ "Write-Host \"escaped... but it doesn`'t hurt to do so.\""
+ ]
+ }
+ ]
+```
+
+</Tab>
+</Tabs>
+
+The above snippet should result in the following output on the Packer console:
+
+```shell-session
+==> amazon-ebs: Provisioning with Powershell...
+==> amazon-ebs: Provisioning with PowerShell script: /var/folders/15/d0f7gdg13rnd1cxp7tgmr55c0000gn/T/packer-powershell-provisioner508190439
+ amazon-ebs: A literal dollar $ must be escaped
+ amazon-ebs: A literal backtick ` must be escaped
+ amazon-ebs: Here "double quotes" must be escaped
+ amazon-ebs: Here 'single quotes' don't really need to be
+ amazon-ebs: escaped... but it doesn't hurt to do so.
+```
+
+### When Not To Escape...
+
+Special characters appearing in user environment variable values and in the
+`elevated_user` and `elevated_password` fields will be automatically dealt with
+for the user. There is no need to use escapes in these instances.
+
+<Tabs>
+<Tab heading="HCL2">
+
+```hcl
+variable "psvar" {
+ type = string
+ default = "My$tring"
+}
+
+build {
+ sources = ["source.amazon-ebs.example"]
+
+ provisioner "powershell" {
+ elevated_user = "Administrator"
+ elevated_password = "Super$3cr3t!"
+ inline = ["Write-Output \"The dollar in the elevated_password is interpreted correctly\""]
+ }
+ provisioner "powershell" {
+ environment_vars = [
+ "VAR1=A$Dollar",
+ "VAR2=A`Backtick",
+ "VAR3=A'SingleQuote",
+ "VAR4=A\"DoubleQuote",
+ "VAR5=${var.psvar}",
+ ]
+ inline = [
+ "Write-Output \"In the following examples the special character is interpreted correctly:\"",
+ "Write-Output \"The dollar in VAR1: $Env:VAR1\"",
+ "Write-Output \"The backtick in VAR2: $Env:VAR2\"",
+ "Write-Output \"The single quote in VAR3: $Env:VAR3\"",
+ "Write-Output \"The double quote in VAR4: $Env:VAR4\"",
+ "Write-Output \"The dollar in VAR5 (expanded from a user var): $Env:VAR5\"",
+ ]
+ }
+}
+```
+
+</Tab>
+<Tab heading="JSON">
+
+```json
+{
+ "variables": {
+ "psvar": "My$tring"
+ },
+ ...
+ "provisioners": [
+ {
+ "type": "powershell",
+ "elevated_user": "Administrator",
+ "elevated_password": "Super$3cr3t!",
+ "inline": "Write-Output \"The dollar in the elevated_password is interpreted correctly\""
+ },
+ {
+ "type": "powershell",
+ "environment_vars": [
+ "VAR1=A$Dollar",
+ "VAR2=A`Backtick",
+ "VAR3=A'SingleQuote",
+ "VAR4=A\"DoubleQuote",
+ "VAR5={{user `psvar`}}"
+ ],
+ "inline": [
+ "Write-Output \"In the following examples the special character is interpreted correctly:\"",
+ "Write-Output \"The dollar in VAR1: $Env:VAR1\"",
+ "Write-Output \"The backtick in VAR2: $Env:VAR2\"",
+ "Write-Output \"The single quote in VAR3: $Env:VAR3\"",
+ "Write-Output \"The double quote in VAR4: $Env:VAR4\"",
+ "Write-Output \"The dollar in VAR5 (expanded from a user var): $Env:VAR5\""
+ ]
+ }
+ ]
+ ...
+}
+```
+
+</Tab>
+</Tabs>
+
+The above snippet should result in the following output on the Packer console:
+
+```shell-session
+==> amazon-ebs: Provisioning with Powershell...
+==> amazon-ebs: Provisioning with PowerShell script: /var/folders/15/d0f7gdg13rnd1cxp7tgmr55c0000gn/T/packer-powershell-provisioner961728919
+ amazon-ebs: The dollar in the elevated_password is interpreted correctly
+==> amazon-ebs: Provisioning with Powershell...
+==> amazon-ebs: Provisioning with PowerShell script: /var/folders/15/d0f7gdg13rnd1cxp7tgmr55c0000gn/T/packer-powershell-provisioner142826554
+ amazon-ebs: In the following examples the special character is interpreted correctly:
+ amazon-ebs: The dollar in VAR1: A$Dollar
+ amazon-ebs: The backtick in VAR2: A`Backtick
+ amazon-ebs: The single quote in VAR3: A'SingleQuote
+ amazon-ebs: The double quote in VAR4: A"DoubleQuote
+ amazon-ebs: The dollar in VAR5 (expanded from a user var): My$tring
+```
diff --git a/v1.9.4/website/content/docs/provisioners/shell-local.mdx b/v1.9.4/website/content/docs/provisioners/shell-local.mdx
new file mode 100644
index 0000000..a8bbea4
--- /dev/null
+++ b/v1.9.4/website/content/docs/provisioners/shell-local.mdx
@@ -0,0 +1,576 @@
+---
+description: |
+ shell-local will run a shell script of your choosing on the machine where
+ Packer is being run - in other words, shell-local will run the shell script on
+ your build server, or your desktop, etc., rather than the remote/guest machine
+ being provisioned by Packer.
+page_title: Shell (Local) - Provisioners
+---
+
+<BadgesHeader>
+ <PluginBadge type="official" />
+</BadgesHeader>
+
+# Local Shell Provisioner
+
+Type: `shell-local`
+
+shell-local will run a shell script of your choosing on the machine where
+Packer is being run - in other words, shell-local will run the shell script on
+your build server, or your desktop, etc., rather than the remote/guest machine
+being provisioned by Packer.
+
+The [remote shell](/packer/docs/provisioners/shell) provisioner executes shell
+scripts on a remote machine.
+
+## Basic Example
+
+The example below is fully functional.
+
+<Tabs>
+<Tab heading="HCL2">
+
+```hcl
+source "file" "example" {
+ content = "example content"
+}
+
+build {
+ source "source.file.example" {
+ target = "./test_artifact.txt"
+ }
+
+ provisioner "shell-local" {
+ inline = ["echo foo"]
+ }
+}
+```
+
+</Tab>
+<Tab heading="JSON">
+
+```json
+{
+ "builders": [
+ {
+ "type": "file",
+ "name": "example",
+ "target": "./test_artifact.txt",
+ "content": "example content"
+ }
+ ],
+ "provisioners": [
+ {
+ "type": "shell-local",
+ "inline": ["echo foo"]
+ }
+ ]
+}
+```
+
+</Tab>
+</Tabs>
+
+## Configuration Reference
+
+The reference of available configuration options is listed below. The only
+required element is `command`.
+
+Exactly _one_ of the following is required:
+
+- `command` (string) - This is a single command to execute. It will be
+ written to a temporary file and run using the `execute_command` call below.
+ If you are building a Windows VM on AWS, Azure, Google Compute, or OpenStack
+ and would like to access the generated password that Packer uses to connect
+ to the instance via WinRM, you can use the template variable `{{.WinRMPassword}}`
+ to set this as an environment variable.
+
+- `inline` (array of strings) - This is an array of commands to execute. The
+ commands are concatenated by newlines and turned into a single file, so
+ they are all executed within the same context. This allows you to change
+ directories in one command and use something in the directory in the next
+ and so on. Inline scripts are the easiest way to pull off simple tasks
+ within the machine in which Packer is running.
+
+- `script` (string) - The path to a script to execute. This path can be
+ absolute or relative. If it is relative, it is relative to the working
+ directory when Packer is executed.
+
+- `scripts` (array of strings) - An array of scripts to execute. The scripts
+ will be executed in the order specified. Each script is executed in
+ isolation, so state such as variables from one script won't carry on to the
+ next.
+
+Optional parameters:
+
+- `env` (map of strings) - A map of key/value pairs to inject prior to the
+ execute_command. Packer injects some environmental variables by default into
+ the environment, as well, which are covered in the section below. Duplicate
+ `env` settings override `environment_vars` settings.
+
+- `environment_vars` (array of strings) - An array of key/value pairs to
+ inject prior to the `execute_command`. The format should be `key=value`.
+ Packer injects some environmental variables by default into the
+ environment, as well, which are covered in the section below. If you are
+ building a Windows VM on AWS, Azure, Google Compute, or OpenStack and would
+ like to access the generated password that Packer uses to connect to the
+ instance via WinRM, you can use the template variable `{{.WinRMPassword}}`
+ to set this as an environment variable. For example:
+ `"environment_vars": "WINRMPASS={{.WinRMPassword}}"`
+
+- `env_var_format` (string) - When we parse the environment_vars that you
+ provide, this gives us a string template to use in order to make sure that
+ we are setting the environment vars correctly. By default on Windows hosts
+ this format is `set %s=%s &&` and on Unix, it is `%s='%s'`. You probably
+ won't need to change this format, but you can see usage examples for where
+ it is necessary below.
+
+- `execute_command` (array of strings) - The command used to execute the
+ script. By default this is `["/bin/sh", "-c", "{{.Vars}}", "{{.Script}}"]`
+ on Unix and `["cmd", "/c", "{{.Vars}}", "{{.Script}}"]` on Windows. This is
+ treated as a [template engine](/packer/docs/templates/legacy_json_templates/engine). There are two
+ available variables: `Script`, which is the path to the script to run, and
+ `Vars`, which is the list of `environment_vars`, if configured.
+
+ If you choose to set this option, make sure that the first element in the
+ array is the shell program you want to use (for example, "sh"), and a later
+ element in the array must be `{{.Script}}`.
+
+ This option provides you a great deal of flexibility. You may choose to
+ provide your own shell program, for example "/usr/local/bin/zsh" or even
+ "powershell.exe". However, with great power comes great responsibility -
+ these commands are not officially supported and things like environment
+ variables may not work if you use a different shell than the default.
+
+ For backwards compatibility, you may also use `{{.Command}}`, but it is
+ decoded the same way as `{{.Script}}`. We recommend using `{{.Script}}` for the
+ sake of clarity, as even when you set only a single `command` to run,
+ Packer writes it to a temporary file and then runs it as a script.
+
+ If you are building a Windows VM on AWS, Azure, Google Compute, or OpenStack
+ and would like to access the generated password that Packer uses to connect
+ to the instance via WinRM, you can use the template variable `{{.WinRMPassword}}`
+ to set this as an environment variable.
+
+- `inline_shebang` (string) - The
+ [shebang](http://en.wikipedia.org/wiki/Shebang_%28Unix%29) value to use
+ when running commands specified by `inline`. By default, this is
+ `/bin/sh -e`. If you're not using `inline`, then this configuration has no
+ effect. **Important:** If you customize this, be sure to include something
+ like the `-e` flag, otherwise individual steps failing won't fail the
+ provisioner.
+
+- `only_on` (array of strings) - This is an array of [runtime operating
+ systems](https://go.dev/doc/install/source#environment) where
+ `shell-local` will execute. This allows you to execute `shell-local` _only_
+ on specific operating systems. By default, shell-local will always run if
+ `only_on` is not set."
+
+- `use_linux_pathing` (bool) - This is only relevant to Windows hosts. If you
+ are running Packer in a Windows environment with the Windows Subsystem for
+ Linux feature enabled, and would like to invoke a bash script rather than
+ invoking a Cmd script, you'll need to set this flag to true; it tells
+ Packer to use the Linux subsystem path for your script rather than the
+ Windows path. (e.g. /mnt/c/path/to/your/file instead of
+ C:/path/to/your/file). Please see the example below for more guidance on
+ how to use this feature. If you are not on a Windows host, or you do not
+ intend to use the shell-local provisioner to run a bash script, please
+ ignore this option.
+
+- `valid_exit_codes` (list of ints) - Valid exit codes for the script. By
+ default this is `0`.
+
+@include 'provisioners/common-config.mdx'
+
+## Execute Command
+
+To many new users, the `execute_command` is puzzling. However, it provides an
+important function: customization of how the command is executed. The most
+common use case for this is dealing with **sudo password prompts**. You may
+also need to customize this if you use a non-POSIX shell, such as `tcsh` on
+FreeBSD.
+
+### The Windows Linux Subsystem
+
+The shell-local provisioner was designed with the idea of allowing you to run
+commands in your local operating system's native shell. For Windows, we've
+assumed in our defaults that this is Cmd. However, it is possible to run a bash
+script as part of the Windows Linux Subsystem from the shell-local provisioner,
+by modifying the `execute_command` and the `use_linux_pathing` options in the
+provisioner config.
+
+The example below is a fully functional test config.
+
+One limitation of this offering is that "inline" and "command" options are not
+available to you; please limit yourself to using the "script" or "scripts"
+options instead.
+
+Please note that the WSL is a beta feature, and this tool is not guaranteed to
+work as you expect it to.
+
+<Tabs>
+<Tab heading="HCL2">
+
+```hcl
+source "null" "example" {
+ communicator = "none"
+}
+
+build {
+ sources = [
+ "source.null.example"
+ ]
+
+ provisioner "shell-local"{
+ environment_vars = ["PROVISIONERTEST=ProvisionerTest1"]
+ execute_command = ["bash", "-c", "{{.Vars}} {{.Script}}"]
+ use_linux_pathing = true
+ scripts = ["C:/Users/me/scripts/example_bash.sh"]
+ }
+ provisioner "shell-local"{
+ environment_vars = ["PROVISIONERTEST=ProvisionerTest2"]
+ execute_command = ["bash", "-c", "{{.Vars}} {{.Script}}"]
+ use_linux_pathing = true
+ script = "C:/Users/me/scripts/example_bash.sh"
+ }
+}
+```
+
+</Tab>
+<Tab heading="JSON">
+
+```json
+{
+ "builders": [
+ {
+ "type": "null",
+ "communicator": "none"
+ }
+ ],
+ "provisioners": [
+ {
+ "type": "shell-local",
+ "environment_vars": ["PROVISIONERTEST=ProvisionerTest1"],
+ "execute_command": ["bash", "-c", "{{.Vars}} {{.Script}}"],
+ "use_linux_pathing": true,
+ "scripts": ["C:/Users/me/scripts/example_bash.sh"]
+ },
+ {
+ "type": "shell-local",
+ "environment_vars": ["PROVISIONERTEST=ProvisionerTest2"],
+ "execute_command": ["bash", "-c", "{{.Vars}} {{.Script}}"],
+ "use_linux_pathing": true,
+ "script": "C:/Users/me/scripts/example_bash.sh"
+ }
+ ]
+}
+```
+
+</Tab>
+</Tabs>
+
+## Default Environmental Variables
+
+In addition to being able to specify custom environmental variables using the
+`environment_vars` configuration, the provisioner automatically defines certain
+commonly useful environmental variables:
+
+- `PACKER_BUILD_NAME` is set to the name of the build that Packer is running.
+ This is most useful when Packer is making multiple builds and you want to
+ distinguish them slightly from a common provisioning script.
+
+- `PACKER_BUILDER_TYPE` is the type of the builder that was used to create
+ the machine that the script is running on. This is useful if you want to
+ run only certain parts of the script on systems built with certain
+ builders.
+
+- `PACKER_HTTP_ADDR` If using a builder that provides an HTTP server for file
+ transfer (such as `hyperv`, `parallels`, `qemu`, `virtualbox`, and `vmware`), this
+ will be set to the address. You can use this address in your provisioner to
+ download large files over HTTP. This may be useful if you're experiencing
+ slower speeds using the default file provisioner. A file provisioner using
+ the `winrm` communicator may experience these types of difficulties.
+
+## Safely Writing A Script
+
+Whether you use the `inline` option, or pass it a direct `script` or `scripts`,
+it is important to understand a few things about how the `shell-local`
+provisioner works to run it safely and easily. This understanding will save you
+much time in the process.
+
+### Once Per Builder
+
+The `shell-local` script(s) you pass are run once per builder. That means that
+if you have an `amazon-ebs` builder and a `docker` builder, your script will be
+run twice. If you have 3 builders, it will run 3 times, once for each builder.
+
+### Always Exit Intentionally
+
+If any provisioner fails, the `packer build` stops and all interim artifacts
+are cleaned up.
+
+For a shell script, that means the script **must** exit with a zero code. You
+_must_ be extra careful to `exit 0` when necessary.
+
+## Usage Examples:
+
+### Windows Host
+
+Example of running a .cmd file on Windows:
+
+<Tabs>
+<Tab heading="HCL2">
+
+```hcl
+provisioner "shell-local" {
+ environment_vars = ["SHELLLOCALTEST=ShellTest1"]
+ scripts = ["./scripts/test_cmd.cmd"]
+}
+```
+
+</Tab>
+<Tab heading="JSON">
+
+```json
+{
+ "type": "shell-local",
+ "environment_vars": ["SHELLLOCALTEST=ShellTest1"],
+ "scripts": ["./scripts/test_cmd.cmd"]
+}
+```
+
+</Tab>
+</Tabs>
+
+Contents of "test_cmd.cmd":
+
+ echo %SHELLLOCALTEST%
+
+Example of running an inline command on Windows: Required customization:
+tempfile_extension
+
+<Tabs>
+<Tab heading="HCL2">
+
+```hcl
+provisioner "shell-local" {
+ environment_vars = ["SHELLLOCALTEST=ShellTest2"],
+ tempfile_extension = ".cmd",
+ inline = [echo "%SHELLLOCALTEST%"]
+}
+```
+
+</Tab>
+<Tab heading="JSON">
+
+```json
+{
+ "type": "shell-local",
+ "environment_vars": ["SHELLLOCALTEST=ShellTest2"],
+ "tempfile_extension": ".cmd",
+ "inline": ["echo %SHELLLOCALTEST%"]
+}
+```
+
+</Tab>
+</Tabs>
+
+Example of running a bash command on Windows using WSL: Required
+customizations: use_linux_pathing and execute_command
+
+<Tabs>
+<Tab heading="HCL2">
+
+```hcl
+provisioner "shell-local" {
+ environment_vars = ["SHELLLOCALTEST=ShellTest3"],
+ execute_command = ["bash", "-c", "{{.Vars}} {{.Script}}"]
+ use_linux_pathing = true
+ script = "./scripts/example_bash.sh"
+}
+```
+
+</Tab>
+<Tab heading="JSON">
+
+```json
+{
+ "type": "shell-local",
+ "environment_vars": ["SHELLLOCALTEST=ShellTest3"],
+ "execute_command": ["bash", "-c", "{{.Vars}} {{.Script}}"],
+ "use_linux_pathing": true,
+ "script": "./scripts/example_bash.sh"
+}
+```
+
+</Tab>
+</Tabs>
+
+Contents of `example_bash.sh`:
+
+ #!/bin/bash
+ echo $SHELLLOCALTEST
+
+Example of running a PowerShell script on Windows: Required customizations:
+`env_var_format` and `execute_command`
+
+<Tabs>
+<Tab heading="HCL2">
+
+```hcl
+provisioner "shell-local" {
+ environment_vars = ["SHELLLOCALTEST=ShellTest4"]
+ execute_command = ["powershell.exe", "{{.Vars}} {{.Script}}"]
+ env_var_format = "$env:%s=\"%s\"; "
+ script = "./scripts/example_ps.ps1"
+}
+```
+
+</Tab>
+<Tab heading="JSON">
+
+```json
+{
+ "type": "shell-local",
+ "environment_vars": ["SHELLLOCALTEST=ShellTest4"],
+ "execute_command": ["powershell.exe", "{{.Vars}} {{.Script}}"],
+ "env_var_format": "$env:%s=\"%s\"; ",
+ "script": "./scripts/example_ps.ps1"
+}
+```
+
+</Tab>
+</Tabs>
+
+Example of running a PowerShell script on Windows as "inline": Required
+customizations: `env_var_format`, `tempfile_extension`, and `execute_command`
+
+<Tabs>
+<Tab heading="HCL2">
+
+```hcl
+provisioner "shell-local" {
+ tempfile_extension = ".ps1"
+ environment_vars = ["SHELLLOCALTEST=ShellTest5"]
+ execute_command = ["powershell.exe", "{{.Vars}} {{.Script}}"]
+ env_var_format = "$env:%s=\"%s\"; "
+ inline = ["write-output $env:SHELLLOCALTEST"]
+}
+```
+
+</Tab>
+<Tab heading="JSON">
+
+```json
+{
+ "type": "shell-local",
+ "tempfile_extension": ".ps1",
+ "environment_vars": ["SHELLLOCALTEST=ShellTest5"],
+ "execute_command": ["powershell.exe", "{{.Vars}} {{.Script}}"],
+ "env_var_format": "$env:%s=\"%s\"; ",
+ "inline": ["write-output $env:SHELLLOCALTEST"]
+}
+```
+
+</Tab>
+</Tabs>
+
+### Unix Host
+
+Example of running a Shell script on Unix:
+
+<Tabs>
+<Tab heading="HCL2">
+
+```hcl
+provisioner "shell-local" {
+ environment_vars = ["PROVISIONERTEST=ProvisionerTest1"]
+ scripts = ["./scripts/example_bash.sh"]
+}
+```
+
+</Tab>
+<Tab heading="JSON">
+
+```json
+{
+ "type": "shell-local",
+ "environment_vars": ["PROVISIONERTEST=ProvisionerTest1"],
+ "scripts": ["./scripts/example_bash.sh"]
+}
+```
+
+</Tab>
+</Tabs>
+
+Example of running a Shell script "inline" on Unix:
+
+<Tabs>
+<Tab heading="HCL2">
+
+```hcl
+provisioner "shell-local" {
+ environment_vars = ["PROVISIONERTEST=ProvisionerTest2"]
+ inline = ["echo hello", "echo $PROVISIONERTEST"]
+}
+
+```
+
+</Tab>
+<Tab heading="JSON">
+
+```json
+{
+ "type": "shell-local",
+ "environment_vars": ["PROVISIONERTEST=ProvisionerTest2"],
+ "inline": ["echo hello", "echo $PROVISIONERTEST"]
+}
+```
+
+</Tab>
+</Tabs>
+
+Example of running a Python script on Unix:
+
+<Tabs>
+<Tab heading="HCL2">
+
+```hcl
+provisioner "shell-local" {
+ script = "hello.py"
+ environment_vars = ["HELLO_USER=packeruser"]
+ execute_command = [
+ "/bin/sh",
+ "-c",
+ "{{.Vars}} /usr/local/bin/python {{.Script}}"
+ ]
+}
+
+```
+
+</Tab>
+<Tab heading="JSON">
+
+```json
+{
+ "type": "shell-local",
+ "script": "hello.py",
+ "environment_vars": ["HELLO_USER=packeruser"],
+ "execute_command": [
+ "/bin/sh",
+ "-c",
+ "{{.Vars}} /usr/local/bin/python {{.Script}}"
+ ]
+}
+```
+
+</Tab>
+</Tabs>
+
+```text
+Where "hello.py" contains:
+
+ import os
+
+ print('Hello, %s!' % os.getenv("HELLO_USER"))
+```
diff --git a/v1.9.4/website/content/docs/provisioners/shell.mdx b/v1.9.4/website/content/docs/provisioners/shell.mdx
new file mode 100644
index 0000000..ca10852
--- /dev/null
+++ b/v1.9.4/website/content/docs/provisioners/shell.mdx
@@ -0,0 +1,413 @@
+---
+description: |
+ The shell Packer provisioner provisions machines built by Packer using shell
+ scripts. Shell provisioning is the easiest way to get software installed and
+ configured on a machine.
+page_title: Shell - Provisioners
+---
+
+<BadgesHeader>
+ <PluginBadge type="official" />
+</BadgesHeader>
+
+# Shell Provisioner
+
+Type: `shell`
+
+The shell Packer provisioner provisions machines built by Packer using shell
+scripts. Shell provisioning is the easiest way to get software installed and
+configured on a machine.
+
+-> **Building Windows images?** You probably want to use the
+[PowerShell](/packer/docs/provisioners/powershell) or [Windows
+Shell](/packer/docs/provisioners/windows-shell) provisioners.
+
+## Basic Example
+
+The example below is fully functional.
+
+<Tabs>
+<Tab heading="HCL2">
+
+```hcl
+provisioner "shell" {
+ inline = ["echo foo"]
+}
+```
+
+</Tab>
+<Tab heading="JSON">
+
+```json
+{
+ "type": "shell",
+ "inline": ["echo foo"]
+}
+```
+
+</Tab>
+</Tabs>
+
+## Configuration Reference
+
+@include 'provisioners/shell-config.mdx'
+
+- `env` (map of strings) - A map of key/value pairs to inject prior to the
+ execute_command. Packer injects some environmental variables by default into
+ the environment, as well, which are covered in the section below. Duplicate
+ `env` settings override `environment_vars` settings.
+
+- `environment_vars` (array of strings) - An array of key/value pairs to
+ inject prior to the execute_command. The format should be `key=value`.
+ Packer injects some environmental variables by default into the
+ environment, as well, which are covered in the section below.
+
+- `env_var_format` (string) - When we parse the environment_vars that you
+ provide, this gives us a string template to use in order to make sure that
+ we are setting the environment vars correctly. By default it is `"%s='%s' "`.
+ When used in conjunction with `use_env_var_file` the default is `"export %s='%s'\n"`
+
+- `use_env_var_file` (boolean) - If true, Packer will write your environment
+ variables to a tempfile and source them from that file, rather than
+ declaring them inline in our execute_command. The default
+ `execute_command` will be
+ `chmod +x {{.Path}}; . {{.EnvVarFile}} && {{.Path}}`. This option is
+ unnecessary for most cases, but if you have extra quoting in your custom
+ `execute_command`, then this may be required for proper script
+ execution. Default: `false`.
+
+- `execute_command` (string) - The command to use to execute the script. By
+ default this is `chmod +x {{ .Path }}; {{ .Vars }} {{ .Path }}`, unless the
+ user has set `"use_env_var_file": true` -- in that case, the default
+ `execute_command` is `chmod +x {{.Path}}; . {{.EnvVarFile}} && {{.Path}}`.
+ This is a [template engine](/packer/docs/templates/legacy_json_templates/engine). Therefore, you may
+ use user variables and template functions in this field. In addition, there
+ are three available extra variables:
+
+ - `Path` is the path to the script to run
+ - `Vars` is the list of `environment_vars`, if configured.
+ - `EnvVarFile` is the path to the file containing env vars, if
+ `use_env_var_file` is true.
+
+- `expect_disconnect` (boolean) - Defaults to `false`. When `true`, allow the
+ server to disconnect from Packer without throwing an error. A disconnect
+ might happen if you restart the SSH server or reboot the host.
+
+- `inline_shebang` (string) - The
+ [shebang](https://en.wikipedia.org/wiki/Shebang_%28Unix%29) value to use
+ when running commands specified by `inline`. By default, this is
+ `/bin/sh -e`. If you're not using `inline`, then this configuration has no
+ effect. **Important:** If you customize this, be sure to include something
+ like the `-e` flag, otherwise individual steps failing won't fail the
+ provisioner.
+
+- `remote_folder` (string) - The folder where the uploaded script will reside
+ on the machine. This defaults to `/tmp`.
+
+- `remote_file` (string) - The filename the uploaded script will have on the
+ machine. This defaults to `script_nnn.sh`.
+
+- `remote_path` (string) - The full path to the uploaded script will have on
+ the machine. By default this is `remote_folder/remote_file`, if set this
+ option will override both `remote_folder` and `remote_file`.
+
+- `skip_clean` (boolean) - If true, specifies that the helper scripts
+ uploaded to the system will not be removed by Packer. This defaults to
+ `false` (clean scripts from the system).
+
+- `start_retry_timeout` (string) - The amount of time to attempt to _start_
+ the remote process. By default this is `5m` or 5 minutes. This setting
+ exists in order to deal with times when SSH may restart, such as a system
+ reboot. Set this to a higher value if reboots take a longer amount of time.
+
+- `pause_after` (string) - Wait the amount of time after provisioning a shell
+ script, this pause be taken if all previous steps were successful.
+
+@include 'provisioners/common-config.mdx'
+
+## Execute Command Example
+
+To many new users, the `execute_command` is puzzling. However, it provides an
+important function: customization of how the command is executed. The most
+common use case for this is dealing with **sudo password prompts**. You may
+also need to customize this if you use a non-POSIX shell, such as `tcsh` on
+FreeBSD.
+
+### Sudo Example
+
+Some operating systems default to a non-root user. For example if you login as
+`ubuntu` and can sudo using the password `packer`, then you'll want to change
+`execute_command` to be:
+
+```text
+"echo 'packer' | sudo -S sh -c '{{ .Vars }} {{ .Path }}'"
+```
+
+The `-S` flag tells `sudo` to read the password from stdin, which in this case
+is being piped in with the value of `packer`.
+
+The above example won't work if your environment vars contain spaces or single
+quotes; in these cases try removing the single quotes:
+
+```text
+"echo 'packer' | sudo -S env {{ .Vars }} {{ .Path }}"
+```
+
+By setting the `execute_command` to this, your script(s) can run with root
+privileges without worrying about password prompts.
+
+### FreeBSD Example
+
+FreeBSD's default shell is `tcsh`, which deviates from POSIX semantics. In
+order for packer to pass environment variables you will need to change the
+`execute_command` to:
+
+```text
+chmod +x {{ .Path }}; env {{ .Vars }} {{ .Path }}
+```
+
+Note the addition of `env` before `{{ .Vars }}`.
+
+## Default Environmental Variables
+
+In addition to being able to specify custom environmental variables using the
+`environment_vars` configuration, the provisioner automatically defines certain
+commonly useful environmental variables:
+
+- `PACKER_BUILD_NAME` is set to the [name of the
+ build](/packer/docs/templates/legacy_json_templates/builders#named-builds) that Packer is running.
+ This is most useful when Packer is making multiple builds and you want to
+ distinguish them slightly from a common provisioning script.
+
+- `PACKER_BUILDER_TYPE` is the type of the builder that was used to create
+ the machine that the script is running on. This is useful if you want to
+ run only certain parts of the script on systems built with certain
+ builders.
+
+- `PACKER_HTTP_ADDR` If using a builder that provides an HTTP server for file
+ transfer (such as `hyperv`, `parallels`, `qemu`, `virtualbox`, and `vmware`), this
+ will be set to the address. You can use this address in your provisioner to
+ download large files over HTTP. This may be useful if you're experiencing
+ slower speeds using the default file provisioner. A file provisioner using
+ the `winrm` communicator may experience these types of difficulties.
+
+## Handling Reboots
+
+Provisioning sometimes involves restarts, usually when updating the operating
+system. Packer is able to tolerate restarts via the shell provisioner.
+
+Packer handles this by retrying to start scripts for a period of time before
+failing. This allows time for the machine to start up and be ready to run
+scripts. The amount of time the provisioner will wait is configured using
+`start_retry_timeout`, which defaults to a few minutes.
+
+Sometimes, when executing a command like `reboot`, the shell script will return
+and Packer will start executing the next one before SSH actually quits and the
+machine restarts. For this, use `pause_before` to make Packer wait before
+executing the next script:
+
+<Tabs>
+<Tab heading="HCL2">
+
+```hcl
+provisioner "shell" {
+ script = "script.sh"
+ pause_before = "10s"
+ timeout = "10s"
+}
+```
+
+</Tab>
+<Tab heading="JSON">
+
+```json
+{
+ "type": "shell",
+ "script": "script.sh",
+ "pause_before": "10s",
+ "timeout": "10s"
+}
+```
+
+</Tab>
+</Tabs>
+
+Some OS configurations don't properly kill all network connections on reboot,
+causing the provisioner to hang despite a reboot occurring. In this case, make
+sure you shut down the network interfaces on reboot or in your shell script.
+For example, on Gentoo:
+
+```text
+/etc/init.d/net.eth0 stop
+```
+
+## SSH Agent Forwarding
+
+Some provisioning requires connecting to remote SSH servers from within the
+packer instance. The below example is for pulling code from a private git
+repository utilizing openssh on the client. Make sure you are running
+`ssh-agent` and add your git repo SSH keys into it using
+`ssh-add /path/to/key`. When the Packer instance needs access to the SSH keys
+the agent will forward the request back to your `ssh-agent`.
+
+Note: when provisioning via git you should add the git server keys into the
+`~/.ssh/known_hosts` file otherwise the git command could hang awaiting input.
+This can be done by copying the file in via the [file
+provisioner](/packer/docs/provisioners/file) (more secure) or using `ssh-keyscan`
+to populate the file (less secure). An example of the latter accessing github
+would be:
+
+<Tabs>
+<Tab heading="HCL2">
+
+```hcl
+provisioner "shell" {
+ inline = [
+ "sudo apt-get install -y git",
+ "ssh-keyscan github.com >> ~/.ssh/known_hosts",
+ "git clone git@github.com:exampleorg/myprivaterepo.git"
+ ]
+}
+```
+
+</Tab>
+<Tab heading="JSON">
+
+```json
+{
+ "type": "shell",
+ "inline": [
+ "sudo apt-get install -y git",
+ "ssh-keyscan github.com >> ~/.ssh/known_hosts",
+ "git clone git@github.com:exampleorg/myprivaterepo.git"
+ ]
+}
+```
+
+</Tab>
+</Tabs>
+
+## Troubleshooting
+
+_My shell script doesn't work correctly on Ubuntu_
+
+- On Ubuntu, the `/bin/sh` shell is
+ [dash](https://en.wikipedia.org/wiki/Debian_Almquist_shell). If your script
+ has [bash](<https://en.wikipedia.org/wiki/Bash_(Unix_shell)>)-specific
+ commands in it, then put `#!/bin/bash -e` at the top of your script.
+ Differences between dash and bash can be found on the
+ [DashAsBinSh](https://wiki.ubuntu.com/DashAsBinSh) Ubuntu wiki page.
+
+_My shell works when I login but fails with the shell provisioner_
+
+- See the above tip. More than likely, your login shell is using `/bin/bash`
+ while the provisioner is using `/bin/sh`.
+
+_My installs hang when using `apt-get` or `yum`_
+
+- Make sure you add a `-y` to the command to prevent it from requiring user
+ input before proceeding.
+
+_How do I tell what my shell script is doing?_
+
+- Adding a `-x` flag to the shebang at the top of the script (`#!/bin/sh -x`)
+ will echo the script statements as it is executing.
+
+_My builds don't always work the same_
+
+- Some distributions start the SSH daemon before other core services which
+ can create race conditions. Your first provisioner can tell the machine to
+ wait until it completely boots.
+
+<Tabs>
+<Tab heading="HCL2">
+
+```hcl
+provisioner "shell" {
+ inline = ["sleep 10"]
+}
+```
+
+</Tab>
+<Tab heading="JSON">
+
+```json
+{
+ "type": "shell",
+ "inline": ["sleep 10"]
+}
+```
+
+</Tab>
+</Tabs>
+
+## Quoting Environment Variables
+
+Packer manages quoting for you, so you shouldn't have to worry about it. Below
+is an example of Packer template inputs and what you should expect to get out:
+
+<Tabs>
+<Tab heading="HCL2">
+
+```hcl
+provisioner "shell" {
+ environment_vars = [
+ "FOO=foo",
+ "BAR=bar's",
+ "BAZ=baz=baz",
+ "QUX==qux",
+ "FOOBAR=foo bar",
+ "FOOBARBAZ='foo bar baz'",
+ "QUX2=\"qux\""
+ ]
+ inline = [
+ "echo \"FOO is $FOO\"",
+ "echo \"BAR is $BAR\"",
+ "echo \"BAZ is $BAZ\"",
+ "echo \"QUX is $QUX\"",
+ "echo \"FOOBAR is $FOOBAR\"",
+ "echo \"FOOBARBAZ is $FOOBARBAZ\"",
+ "echo \"QUX2 is $QUX2\""
+ ]
+}
+```
+
+</Tab>
+<Tab heading="JSON">
+
+```json
+"provisioners": [
+ {
+ "type": "shell",
+ "environment_vars": ["FOO=foo",
+ "BAR=bar's",
+ "BAZ=baz=baz",
+ "QUX==qux",
+ "FOOBAR=foo bar",
+ "FOOBARBAZ='foo bar baz'",
+ "QUX2=\"qux\""],
+ "inline": ["echo \"FOO is $FOO\"",
+ "echo \"BAR is $BAR\"",
+ "echo \"BAZ is $BAZ\"",
+ "echo \"QUX is $QUX\"",
+ "echo \"FOOBAR is $FOOBAR\"",
+ "echo \"FOOBARBAZ is $FOOBARBAZ\"",
+ "echo \"QUX2 is $QUX2\""]
+ }
+]
+```
+
+</Tab>
+</Tabs>
+
+Output:
+
+```text
+docker: FOO is foo
+docker: BAR is bar's
+docker: BAZ is baz=baz
+docker: QUX is =qux
+docker: FOOBAR is foo bar
+docker: FOOBARBAZ is 'foo bar baz'
+docker: QUX2 is "qux"
+```
diff --git a/v1.9.4/website/content/docs/provisioners/windows-restart.mdx b/v1.9.4/website/content/docs/provisioners/windows-restart.mdx
new file mode 100644
index 0000000..9c78bce
--- /dev/null
+++ b/v1.9.4/website/content/docs/provisioners/windows-restart.mdx
@@ -0,0 +1,112 @@
+---
+description: |
+ The Windows restart provisioner restarts a Windows machine and waits for it to
+ come back up.
+page_title: Windows Restart - Provisioners
+---
+
+<BadgesHeader>
+ <PluginBadge type="official" />
+</BadgesHeader>
+
+# Windows Restart Provisioner
+
+Type: `windows-restart`
+
+The Windows restart provisioner initiates a reboot on a Windows machine and
+waits for the machine to come back online.
+
+The Windows provisioning process often requires multiple reboots, and this
+provisioner helps to ease that process.
+
+Packer expects the machine to be ready to continue provisioning after it
+reboots. Packer detects that the reboot has completed by making an RPC call
+through the Windows Remote Management (WinRM) service, not by ACPI functions,
+so Windows must be completely booted in order to continue.
+
+## Basic Example
+
+The example below is fully functional.
+
+<Tabs>
+<Tab heading="HCL2">
+
+```hcl
+provisioner "windows-restart" {}
+```
+
+</Tab>
+<Tab heading="JSON">
+
+```json
+{
+ "type": "windows-restart"
+}
+```
+
+</Tab>
+</Tabs>
+
+## Configuration Reference
+
+The reference of available configuration options is listed below.
+
+Optional parameters:
+
+- `check_registry` (bool) - if `true`, checks for several registry keys that
+ indicate that the system is going to reboot. This is useful if an
+ installation kicks off a reboot and you want the provisioner to wait for
+ that reboot to complete before reconnecting. Please note that this option
+ is a beta feature, and we generally recommend that you finish installs that
+ auto-reboot (like Windows Updates) during your _autounattend_ phase before
+ the `winrm` provisioner connects.
+
+- `registry_keys` (array of strings) - if `check-registry` is `true`,
+ `windows-restart` will not reconnect until after all of the listed keys are
+ no longer present in the registry.
+
+```
+ default:
+
+ var DefaultRegistryKeys = []string{
+ "HKLM:SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Component Based Servicing\\RebootPending",
+ "HKLM:SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Component Based Servicing\\PackagesPending",
+ "HKLM:Software\\Microsoft\\Windows\\CurrentVersion\\Component Based Servicing\\RebootInProgress",
+ }
+```
+
+- `restart_command` (string) - The command to execute to initiate the
+ restart. By default this is `shutdown /r /f /t 0 /c "packer restart"`.
+
+- `restart_check_command` (string) - The command to run after executing `restart_command`
+ to check if the guest machine has restarted. This command will retry until the connection
+ to the guest machine has been restored or `restart_timeout` has exceeded.
+
+<Tabs>
+<Tab heading="HCL2">
+
+```hcl
+provisioner "windows-restart" {
+ restart_check_command = "powershell -command \"& {Write-Output 'restarted.'}\""
+}
+```
+
+</Tab>
+<Tab heading="JSON">
+
+```json
+{
+ "type": "windows-restart",
+ "restart_check_command": "powershell -command \"& {Write-Output 'restarted.'}\""
+}
+```
+
+</Tab>
+</Tabs>
+
+- `restart_timeout` (string) - The timeout to wait for the restart. By
+ default this is 5 minutes. Example value: `5m`. If you are installing
+ updates or have a lot of startup services, you will probably need to
+ increase this duration.
+
+@include 'provisioners/common-config.mdx'
diff --git a/v1.9.4/website/content/docs/provisioners/windows-shell.mdx b/v1.9.4/website/content/docs/provisioners/windows-shell.mdx
new file mode 100644
index 0000000..2663aed
--- /dev/null
+++ b/v1.9.4/website/content/docs/provisioners/windows-shell.mdx
@@ -0,0 +1,101 @@
+---
+description: |
+ The windows-shell Packer provisioner runs commands on Windows using the cmd
+ shell.
+page_title: Windows Shell - Provisioners
+---
+
+<BadgesHeader>
+ <PluginBadge type="official" />
+</BadgesHeader>
+
+# Windows Shell Provisioner
+
+Type: `windows-shell`
+
+The windows-shell Packer provisioner runs commands on a Windows machine using
+`cmd`. It assumes it is running over WinRM.
+
+## Basic Example
+
+The example below is fully functional.
+
+<Tabs>
+<Tab heading="HCL2">
+
+```hcl
+provisioner "windows-shell" {
+ inline = ["dir c:\\"]
+}
+```
+
+</Tab>
+<Tab heading="JSON">
+
+```json
+{
+ "type": "windows-shell",
+ "inline": ["dir c:\\"]
+}
+```
+
+</Tab>
+</Tabs>
+
+## Configuration Reference
+
+@include 'provisioners/shell-config.mdx'
+
+- `env` (map of strings) - A map of key/value pairs to inject prior to the
+ execute_command. Packer injects some environmental variables by default into
+ the environment, as well, which are covered in the section below. Duplicate
+ `env` settings override `environment_vars` settings.
+
+- `environment_vars` (array of strings) - An array of key/value pairs to
+ inject prior to the execute_command. The format should be `key=value`.
+ Packer injects some environmental variables by default into the
+ environment, as well, which are covered in the section below.
+
+- `execute_command` (string) - The command to use to execute the script. By
+ default this is `{{ .Vars }}"{{ .Path }}"`. The value of this is treated as
+ [template engine](/packer/docs/templates/legacy_json_templates/engine). This is a
+ [template engine](/packer/docs/templates/legacy_json_templates/engine). Therefore, you may
+ use user variables and template functions in this field. In addition, there
+ are two available extra variables:
+
+ - `Path` is the path to the script to run
+ - `Vars` is the list of `environment_vars`, if configured.
+
+- `remote_path` (string) - The path where the script will be uploaded to in
+ the machine. This defaults to "c:/Windows/Temp/script.bat". This value must
+ be a writable location and any parent directories must already exist.
+
+- `start_retry_timeout` (string) - The amount of time to attempt to _start_
+ the remote process. By default this is "5m" or 5 minutes. This setting
+ exists in order to deal with times when SSH may restart, such as a system
+ reboot. Set this to a higher value if reboots take a longer amount of time.
+
+@include 'provisioners/common-config.mdx'
+
+## Default Environmental Variables
+
+In addition to being able to specify custom environmental variables using the
+`environment_vars` configuration, the provisioner automatically defines certain
+commonly useful environmental variables:
+
+- `PACKER_BUILD_NAME` is set to the [name of the
+ build](/packer/docs/templates/legacy_json_templates/builders#named-builds) that Packer is running.
+ This is most useful when Packer is making multiple builds and you want to
+ distinguish them slightly from a common provisioning script.
+
+- `PACKER_BUILDER_TYPE` is the type of the builder that was used to create
+ the machine that the script is running on. This is useful if you want to
+ run only certain parts of the script on systems built with certain
+ builders.
+
+- `PACKER_HTTP_ADDR` If using a builder that provides an HTTP server for file
+ transfer (such as `hyperv`, `parallels`, `qemu`, `virtualbox`, and `vmware`), this
+ will be set to the address. You can use this address in your provisioner to
+ download large files over HTTP. This may be useful if you're experiencing
+ slower speeds using the default file provisioner. A file provisioner using
+ the `winrm` communicator may experience these types of difficulties.
diff --git a/v1.9.4/website/content/docs/templates/hcl_templates/blocks/build/hcp_packer_registry.mdx b/v1.9.4/website/content/docs/templates/hcl_templates/blocks/build/hcp_packer_registry.mdx
new file mode 100644
index 0000000..e374af6
--- /dev/null
+++ b/v1.9.4/website/content/docs/templates/hcl_templates/blocks/build/hcp_packer_registry.mdx
@@ -0,0 +1,79 @@
+---
+description: >
+ The hcp_packer_registry allows operators the ability to customize the metadata sent to HCP Packer Registry.
+ It configures the base details of an image that is created or updated within HCP Packer.
+page_title: hcp_packer_registry - build - Blocks
+---
+
+# The `hcp_packer_registry` block
+
+The `hcp_packer_registry` block lets you customize the metadata Packer sends to HCP Packer Registry. It configures the details of an image that is created or updated within the HCP Packer registry.
+
+To get started with HCP Packer, refer to the [HCP Packer documentation](/hcp/docs/packer) or try the [Get Started with HCP Packer tutorials](/packer/tutorials/hcp-get-started).
+
+## Usage
+
+This block is available from version 1.7.7 of Packer.
+
+The presence of a `hcp_packer_registry` block in a build block will enable HCP
+Packer mode. Packer will push all builds within that build block to the remote
+registry if the appropriate HCP credentials are set (`HCP_CLIENT_ID` and
+`HCP_CLIENT_SECRET`). If no HCP credentials are set, Packer will fail the build
+and exit immediately to avoid any potential artifact drift between the defined
+builders (source blocks) and the HCP Packer registry.
+
+~> **Note:** You will receive an error if you try to reference metadata from a deactivated or deleted registry. An administrator can manually deactivate or delete a registry, and HCP Packer automatically deactivates registries with billing issues. Contact [HashiCorp Support](https://support.hashicorp.com/) with questions.
+
+```hcl
+# file: builds.pkr.hcl
+source "happycloud" "macos" {
+ os = "macos_amd64"
+}
+
+build {
+ hcp_packer_registry {
+ bucket_name = "ios-dev"
+
+ description = <<EOT
+Some nice description about the image which artifact is being published to HCP Packer Registry. =D
+ EOT
+
+ bucket_labels = {
+ "team" = "ios-development",
+ "os" = "macos"
+ }
+
+ build_labels = {
+ "xcode" = "11.3.0"
+ "version" = "Big Sur"
+ }
+ }
+
+ sources = ["source.happycloud.macos"]
+}
+```
+
+- `bucket_name` (string) - The image name when published to the HCP Packer
+ registry. Should always be the same, otherwise a new image will be created.
+ Defaults to `build.name` if not set. Will be overwritten if
+ `HCP_PACKER_BUCKET_NAME` is set.
+
+- `bucket_labels` (map[string]string) - Map of labels. Can provide any information,
+ such as tools versions (e.g. Go 1.17, Python 3.5, etc...). The bucket labels will
+ appear at the image's main page and will be updated whenever it is changed
+ and a new iteration for the bucket is pushed to the HCP Packer registry.
+
+- `build_labels` (map[string]string) - Map of labels. Can provide any information,
+ such as tools versions (e.g. Go 1.17, Python 3.5, etc...). The build labels will
+ appear in the build section of an iteration. Build labels are specific to an iteration
+ and will be added to a build when is pushed to the HCP Packer registry.
+ Updates to build labels on a completed iteration is not allowed.
+
+- `description` (string) - The image description. Useful to provide a summary
+ about the image. The description will appear at the image's main page and
+ will be updated whenever it is changed and a new build is pushed to the HCP
+ Packer registry. Should contain a maximum of 255 characters. Defaults to
+ `build.description` if not set.
+
+- `labels` (map[string]string) - Deprecated in Packer 1.7.9. See [`bucket_labels`](#bucket_labels) for details.
+
diff --git a/v1.9.4/website/content/docs/templates/hcl_templates/blocks/build/index.mdx b/v1.9.4/website/content/docs/templates/hcl_templates/blocks/build/index.mdx
new file mode 100644
index 0000000..1ddef67
--- /dev/null
+++ b/v1.9.4/website/content/docs/templates/hcl_templates/blocks/build/index.mdx
@@ -0,0 +1,97 @@
+---
+description: |
+ The source block defines what builders are started.
+page_title: build - Blocks
+---
+
+# The `build` block
+
+`@include 'from-1.5/beta-hcl2-note.mdx'`
+
+The `build` block defines what builders are started, how to `provision` them
+and if necessary what to do with their artifacts using `post-process`.
+
+To use builders in a `build` block you can either:
+
+- Set the `sources` array of string with references to pre-defined sources.
+
+- Define [build-level `source` blocks](/packer/docs/templates/hcl_templates/blocks/build/source).
+ This also allows you to set specific fields.
+
+`@include 'from-1.5/builds/example-block.mdx'`
+
+Define [top-level `source` blocks](/packer/docs/templates/hcl_templates/blocks/source) to configure
+your builders. The list of available builders can be found in the
+[builders](/packer/docs/builders) section.
+
+## Naming your builds
+
+The optional `name` field of the `build` block can be used to set the name of a
+build. Named builds will prefix the log lines in a `packer build` with the name
+of the build block. For example:
+
+```hcl
+source "null" "first-example" {
+ communicator = "none"
+}
+
+source "null" "second-example" {
+ communicator = "none"
+}
+
+build {
+ name = "a"
+
+ sources = [
+ "sources.null.first-example",
+ "sources.null.second-example",
+ ]
+}
+
+
+build {
+ sources = ["sources.null.second-example"]
+}
+```
+
+Will output:
+
+```shell-session
+> packer build ./folder
+Build 'a.null.first-example' finished.
+Build 'a.null.second-example' finished.
+Build 'null.second-example' finished.
+
+==> Builds finished. The artifacts of successful builds are:
+--> a.null.first-example: Did not export anything. This is the null builder
+--> a.null.second-example: Did not export anything. This is the null builder
+--> null.second-example: Did not export anything. This is the null builder
+```
+
+### Running only specific builds
+
+The `-only`/`-except` flags will match a source's `type.name` and run 'only'
+matching **builders** (source) or all referenced builders 'except' the matching
+ones, for example with the same config file:
+
+```shell-session
+> packer build -only "*.second-example" ./folder
+Build 'null.second-example' finished.
+Build 'a.null.second-example' finished.
+
+==> Builds finished. The artifacts of successful builds are:
+--> a.null.second-example: Did not export anything. This is the null builder
+--> null.second-example: Did not export anything. This is the null builder
+```
+
+Here `'a.null.first-example'` was skipped.
+
+-> Note: It is not yet possible to match a named `build` block to do this, but
+this is soon going to be possible. So here "a.\*" will match nothing.
+
+## Related
+
+- A list of [community
+ builders](https://packer.io/community-tools#community-builders) is available.
+
+- Create your own [custom builder](/packer/docs/plugins/creation/custom-builders) !
diff --git a/v1.9.4/website/content/docs/templates/hcl_templates/blocks/build/post-processor.mdx b/v1.9.4/website/content/docs/templates/hcl_templates/blocks/build/post-processor.mdx
new file mode 100644
index 0000000..9f7e981
--- /dev/null
+++ b/v1.9.4/website/content/docs/templates/hcl_templates/blocks/build/post-processor.mdx
@@ -0,0 +1,108 @@
+---
+description: |
+ The post-processor block defines how a post-processor is configured.
+page_title: post-processor - build - Blocks
+---
+
+# The `post-processor` block
+
+`@include 'from-1.5/beta-hcl2-note.mdx'`
+
+The `post-processor` block defines how a post-processor is configured.
+
+```hcl
+# builds.pkr.hcl
+build {
+ # ... build image
+ post-processor "checksum" { # checksum image
+ checksum_types = [ "md5", "sha512" ] # checksum the artifact
+ keep_input_artifact = true # keep the artifact
+ }
+
+ post-processor "amazon-import" { # upload image to amazon
+ }
+}
+```
+
+Each `post-processor` runs after each defined build. A post-processor takes the
+`Artifact` from a build. Post-processors are optional, and they can be used to
+upload artifacts, re-package, or more. The list of available post-processors
+can be found in the [post-processors](/packer/docs/post-processors) section.
+
+A `post-processor` can also take the `Artifact` from another post-processor
+when it is defined in a [`post-processors`
+block](/packer/docs/templates/hcl_templates/blocks/build/post-processor) list, that is a list of
+chained post processors.
+
+-> Note: The input 'artifact' received by a post-processor will be automatically
+deleted by default.
+
+# Keep an input artifact
+
+To prevent an input artifact from being deleted, you can set the
+`keep_input_artifact` field to true to make Packer keep both artifacts. For
+example if we want to checksum an artifact and keep the artifact:
+
+```hcl
+# builds.pkr.hcl
+build {
+ # ...
+ post-processor "checksum" {
+ checksum_types = [ "md5", "sha512" ]
+ keep_input_artifact = true
+ }
+}
+```
+
+# Run on Specific Builds
+
+You can use the `only` or `except` configurations to run a post-processor only
+with specific sources. These two configurations do what you expect: `only` will
+only run the post-processor on the specified sources and `except` will run the
+post-processor on anything other than the specified sources.
+
+An example of `only` being used is shown below, but the usage of `except` is
+effectively the same:
+
+```hcl
+# builds.pkr.hcl
+build {
+ # ...
+ post-processor "checksum" {
+ checksum_types = [ "md5", "sha512" ]
+ keep_input_artifact = true
+ only = ["amazon-ebs.example"]
+ }
+}
+```
+
+The values within `only` or `except` are _source names_, not builder types.
+
+If you want to exclude certain post-processors when running `packer build`
+from the command line, you can do so:
+
+`packer build --except=checksum mytemplate.pkr.hcl` will not run the checksum
+post-processor. This command line exclusion works by referencing post-processor
+_name_. By default, the post-processor is named after is its type, as
+demonstrated above in the `checksum` example. You can make a post-processor's
+name unique by adding a "name" field to each post-processor block.
+
+While the `-except` flag can be used to filter out post-processors on the
+command line, the `-only` flag does not work for post-processors. If you wish
+to only run a post-processor for a given source build you must use the
+`only=[source]` syntax inside of your hcl templates, as described above.
+
+
+## Build Contextual Variables
+
+Packer allows to access connection information and basic instance state
+information from a post-processor. These information are stored in the `build`
+variable. Check out the [Contextual
+Variables](/packer/docs/templates/hcl_templates/contextual-variables) documentation to learn more
+about and see some examples of how to use them.
+
+### Related
+
+- The [`post-processors` block](/packer/docs/templates/hcl_templates/blocks/build/post-processors)
+ allows to define one or more chain of `post-processor`s that will take the
+ output from the build and provision steps.
diff --git a/v1.9.4/website/content/docs/templates/hcl_templates/blocks/build/post-processors.mdx b/v1.9.4/website/content/docs/templates/hcl_templates/blocks/build/post-processors.mdx
new file mode 100644
index 0000000..181ac03
--- /dev/null
+++ b/v1.9.4/website/content/docs/templates/hcl_templates/blocks/build/post-processors.mdx
@@ -0,0 +1,85 @@
+---
+description: >
+ The post-processors block allows to define lists of post-processors to apply
+ to an artifact.
+page_title: post-processors - build - Blocks
+---
+
+# The `post-processors` block
+
+`@include 'from-1.5/beta-hcl2-note.mdx'`
+
+The `post-processors` block allows to define lists of
+[`post-processors`](/packer/docs/templates/hcl_templates/blocks/build/post-processor), that will run
+from the artifact of each build.
+
+```hcl
+# builds.pkr.hcl
+build {
+ # ...
+ post-processors {
+ post-processor "shell-local" { # create an artifice.txt file containing "hello"
+ inline = [ "echo hello > artifice.txt" ]
+ }
+ post-processor "artifice" { # tell packer this is now the new artifact
+ files = ["artifice.txt"]
+ }
+ post-processor "checksum" { # checksum artifice.txt
+ checksum_types = [ "md5", "sha512" ] # checksum the artifact
+ keep_input_artifact = true # keep the artifact
+ }
+ }
+
+}
+```
+
+The [`post-processor` block](/packer/docs/templates/hcl_templates/blocks/build/post-processor)
+allows to define multiple post-processors that will run from the `Artifact` of
+each build. Read the `post-processor` documentation to know how to use a
+post-processor.
+
+### Difference between a `post-processor` and a `post-processors` block
+
+These two templates are doing the same thing:
+
+```hcl
+# builds.pkr.hcl
+build {
+ # ... build image
+ post-processor "checksum" { # checksum image
+ checksum_types = [ "md5", "sha512" ] # checksum the artifact
+ }
+
+ post-processor "amazon-import" { # upload image to AWS
+ }
+
+ post-processor "googlecompute-import" { # upload image to GCP
+ }
+}
+```
+
+```hcl
+# builds.pkr.hcl
+build {
+ # ... build image
+ post-processors {
+ post-processor "checksum" { # checksum image
+ checksum_types = [ "md5", "sha512" ] # checksum the artifact
+ }
+ }
+
+ post-processors {
+ post-processor "amazon-import" { # upload image to AWS
+ }
+ }
+
+ post-processors {
+ post-processor "googlecompute-import" { # upload image to GCP
+ }
+ }
+}
+```
+
+Each of these `post-processors` will start after each build -- that is, after
+each provision step has run on each source --. In all cases the source image is
+going to be deleted.
diff --git a/v1.9.4/website/content/docs/templates/hcl_templates/blocks/build/provisioner.mdx b/v1.9.4/website/content/docs/templates/hcl_templates/blocks/build/provisioner.mdx
new file mode 100644
index 0000000..fdf3648
--- /dev/null
+++ b/v1.9.4/website/content/docs/templates/hcl_templates/blocks/build/provisioner.mdx
@@ -0,0 +1,262 @@
+---
+description: |
+ The provisioner block defines how a provisioner is configured.
+page_title: provisioner - build - Blocks
+---
+
+# The `provisioner` block
+
+`@include 'from-1.5/beta-hcl2-note.mdx'`
+
+The `provisioner` block defines how a provisioner is configured.
+
+```hcl
+# builds.pkr.hcl
+build {
+ # ...
+ provisioner "shell" {
+ inline = [
+ "echo provisioning all the things",
+ "echo the value of 'foo' is '${var.foo}'",
+ ]
+ }
+}
+```
+
+Provisioners use builtin and third-party software to install and configure the
+machine image after booting. Provisioners prepare the system for use.
+
+The list of available provisioners can be found in the
+[provisioners](/packer/docs/provisioners) section.
+
+## Run on Specific Sources
+
+You can use the `only` or `except` configurations to run a provisioner only
+with specific sources. These two configurations do what you expect: `only` will
+only run the provisioner on the specified sources and `except` will run the
+provisioner on anything other than the specified sources.
+
+An example of `only` being used is shown below, but the usage of `except` is
+effectively the same:
+
+```hcl
+# builds.pkr.hcl
+
+source "amazon-ebs" "first-example" {
+ #...
+}
+
+source "amazon-ebs" "second-example" {
+ #...
+}
+
+build {
+ sources = [
+ "source.amazon-ebs.first-example",
+ "source.amazon-ebs.second-example",
+ ]
+ provisioner "shell" {
+ # This provisioner only runs for the 'first-example' source.
+ only = ["amazon-ebs.first-example"]
+
+ inline = [
+ "echo provisioning all the things",
+ "echo the value of 'foo' is '${var.foo}'",
+ ]
+ }
+ provisioner "shell" {
+ # This runs with all sources.
+ inline = [
+ "echo Hi World!"
+ ]
+ }
+}
+```
+
+The source names within `only` and `except` must suppress `source.` prefix.
+
+The values within `only` or `except` are _source names_, not builder types nor build names.
+
+-> Note: In the cli `only` and `except` will match against **build names** (for
+example:`my_build.amazon-ebs.first-example`) but in a provisioner they will
+match on the **source name** (for example:`amazon-ebs.third-example`).
+
+## Build-Specific Overrides
+
+While the goal of Packer is to produce identical machine images, it sometimes
+requires periods of time where the machines are different before they
+eventually converge to be identical. In these cases, different configurations
+for provisioners may be necessary depending on the build. This can be done
+using build-specific overrides.
+
+An example of where this might be necessary is when building both an EC2 AMI
+and a VMware machine. The source EC2 AMI may setup a user with administrative
+privileges by default, whereas the VMware machine doesn't have these
+privileges. In this case, the shell script may need to be executed differently.
+Of course, the goal is that hopefully the shell script converges these two
+images to be identical. However, they may initially need to be run differently.
+
+This example is shown below:
+
+```hcl
+source "null" "example1" {
+ communicator = "none"
+}
+
+source "null" "example2" {
+ communicator = "none"
+}
+
+source "null" "example3" {
+ communicator = "none"
+}
+
+build {
+ sources = ["source.null.example2", "source.null.example3"]
+
+ source "source.null.example1" {
+ // Give a name to this source
+ name = "renamed"
+ }
+
+ provisioner "shell-local" {
+ inline = ["echo not overridden"]
+ override = {
+ example3 = {
+ inline = ["echo overrides for example3"]
+ }
+ // Refer to the source with the given name
+ renamed = {
+ inline = ["echo overrides for renamed"]
+ }
+ }
+ }
+}
+```
+
+As you can see, the `override` key is used. The value of this key is another
+HCL attribute map where the key is the name of a [source
+definition](/packer/docs/templates/hcl_templates/blocks/source). The value of this is in turn
+another HCL attribute map. This HCL attribute map simply contains the provisioner
+configuration as normal. This configuration is merged into the default
+provisioner configuration.
+
+## On Error Provisioner
+
+You can optionally create a single specialized provisioner called an
+`error-cleanup-provisioner`. This provisioner will not run unless the normal
+provisioning run fails. If the normal provisioning run does fail, this special
+error provisioner will run _before the instance is shut down_. This allows you
+to make last minute changes and clean up behaviors that Packer may not be able
+to clean up on its own.
+
+For examples, users may use this provisioner to make sure that the instance is
+properly unsubscribed from any services that it connected to during the build
+run.
+
+Toy usage example for the error cleanup script:
+
+```hcl
+source "null" "example" {
+ communicator = "none"
+}
+
+build {
+ sources = ["source.null.example"]
+
+ provisioner "shell-local" {
+ inline = ["exit 2"]
+ }
+
+ error-cleanup-provisioner "shell-local" {
+ inline = ["echo 'rubber ducky'> ducky.txt"]
+ }
+}
+```
+
+## Pausing Before Running
+
+With certain provisioners it is sometimes desirable to pause for some period of
+time before running it. Specifically, in cases where a provisioner reboots the
+machine, you may want to wait for some period of time before starting the next
+provisioner.
+
+Every provisioner definition in a Packer template can take a special
+configuration `pause_before` that is the amount of time to pause before running
+that provisioner. By default, there is no pause. An example is shown below:
+
+```hcl
+# builds.pkr.hcl
+build {
+ # ...
+ provisioner "shell" {
+ inline = [
+ "echo provisioning all the things",
+ "echo the value of 'foo' is '${var.foo}'",
+ ]
+ pause_before = "10s"
+ }
+}
+```
+
+For the above provisioner, Packer will wait 10 seconds before uploading and
+executing the shell script.
+
+## Retry on error
+
+With certain provisioners it is sometimes desirable to retry when it fails.
+Specifically, in cases where the provisioner depends on external processes that are not done yet.
+
+Every provisioner definition in a Packer template can take a special
+configuration `max_retries` that is the maximum number of times a provisioner will retry on error.
+By default, there `max_retries` is zero and there is no retry on error. An example is shown below:
+
+```hcl
+# builds.pkr.hcl
+build {
+ # ...
+ provisioner "shell" {
+ inline = [
+ "echo provisioning all the things",
+ "echo the value of 'foo' is '${var.foo}'",
+ ]
+ max_retries = 5
+ }
+}
+```
+
+For the above provisioner, Packer will retry maximum five times until stops failing.
+If after five retries the provisioner still fails, then the complete build will fail.
+
+## Timeout
+
+Sometimes a command can take much more time than expected
+
+Every provisioner definition in a Packer template can take a special
+configuration `timeout` that is the amount of time to wait before
+considering that the provisioner failed. By default, there is no timeout. An
+example is shown below:
+
+```hcl
+# builds.pkr.hcl
+build {
+ # ...
+ provisioner "shell" {
+ inline = [
+ "echo provisioning all the things",
+ "echo the value of 'foo' is '${var.foo}'",
+ ]
+ timeout = "5m"
+ }
+}
+```
+
+For the above provisioner, Packer will cancel the script if it takes more than
+5 minutes.
+
+Timeout has no effect in debug mode.
+
+## Build Contextual Variables
+
+Packer allows to access connection information and basic instance state information from a provisioner. These information are stored in the `build` variable.
+Check out the [Contextual Variables](/packer/docs/templates/hcl_templates/contextual-variables) documentation to learn more about and see some examples of how to use them.
diff --git a/v1.9.4/website/content/docs/templates/hcl_templates/blocks/build/source.mdx b/v1.9.4/website/content/docs/templates/hcl_templates/blocks/build/source.mdx
new file mode 100644
index 0000000..07663f8
--- /dev/null
+++ b/v1.9.4/website/content/docs/templates/hcl_templates/blocks/build/source.mdx
@@ -0,0 +1,56 @@
+---
+description: >
+ A source block nested in a build block allows you to use an already defined
+ source and to set specific fields which aren't already set in the top-level
+ source block.
+page_title: source - build - Blocks
+---
+
+# The `source` block
+
+`@include 'from-1.5/beta-hcl2-note.mdx'`
+
+A `source` block nested in a `build` block allows you to use an already defined
+source and to "fill in" those fields _which aren't already set in the top-level
+source block_.
+
+Build-level source blocks are implemented by merging their contents with the
+corresponding top-level source block, and a packer build will fail when it
+encounters the ambiguity that arises when a source parameter is defined twice.
+For example, in the below example, if the top-level "lxd.arch" source block
+also defined an `output_image` field (or if one of the build-level source blocks
+redefined and image field), Packer would error.
+
+```hcl
+# file: builds.pkr.hcl
+source "lxd" "arch" {
+ image = "archlinux"
+}
+
+build {
+ # Use the singular `source` block set specific fields.
+ # Note that fields cannot be overwritten, in other words, you cannot
+ # set the 'image' field from the top-level source block in here, as well as
+ # the 'name' and 'output_image' fields cannot be set in the top-level source block.
+ source "lxd.arch" {
+ # Setting the name field allows to rename the source only for this build section.
+ name = "nomad"
+ output_image = "nomad"
+ }
+
+ provisioner "shell" {
+ inline = [ "echo installing nomad" ]
+ }
+}
+
+build {
+ source "lxd.arch" {
+ name = "consul"
+ output_image = "consul"
+ }
+
+ provisioner "shell" {
+ inline = [ "echo installing consul" ]
+ }
+}
+```
diff --git a/v1.9.4/website/content/docs/templates/hcl_templates/blocks/data.mdx b/v1.9.4/website/content/docs/templates/hcl_templates/blocks/data.mdx
new file mode 100644
index 0000000..b5a8e0f
--- /dev/null
+++ b/v1.9.4/website/content/docs/templates/hcl_templates/blocks/data.mdx
@@ -0,0 +1,16 @@
+---
+description: >
+ The data block defines data sources within your Packer configuration.
+page_title: data - Blocks
+---
+
+# The `data` block
+
+The `data` block defines data sources within your Packer configuration.
+
+`@include 'from-1.5/datasources/example-block.mdx'`
+
+# More on data sources
+
+- Read the [full Data Sources](/packer/docs/templates/hcl_templates/datasources) description for a more
+ thorough read.
diff --git a/v1.9.4/website/content/docs/templates/hcl_templates/blocks/index.mdx b/v1.9.4/website/content/docs/templates/hcl_templates/blocks/index.mdx
new file mode 100644
index 0000000..9d2cb2f
--- /dev/null
+++ b/v1.9.4/website/content/docs/templates/hcl_templates/blocks/index.mdx
@@ -0,0 +1,62 @@
+---
+page_title: Blocks - Configuration Language
+description: The HCL language has a number of blocks that can be used to configure builds.
+---
+
+# Built-in Blocks
+
+`@include 'from-1.5/beta-hcl2-note.mdx'`
+
+The Packer - HCL2 language includes a number of built-in blocks that you can
+use to configure builds. A block is a container for configuration.
+
+The most important blocks can be broken into a couple of major types:
+
+- `build` blocks contain configuration for a specific combination of builders,
+ provisioners, and post-processors used to create a specific image artifact.
+- `source` blocks contain configuration for builder plugins. Once defined,
+ sources can be used and further configured by the "build" block.
+- `provisioner` blocks contain configuration for provisioner plugins. These
+ blocks are nested inside of a build block.
+- `post-processor` and `post-processors` blocks contain configuration for
+ post-processor plugins and post-processor plugin sequences. They are also
+ nested within `build` blocks.
+- `variable` blocks contain configuration for variables that can either be
+ defaulted in configuration or set by the user at runtime.
+- `locals` blocks contain configuration for variables that can be created using
+ HCL functions or data sources, or composited from variables created in the
+ variables blocks.
+
+The documentation contains information for each block type.
+
+Other blocks, such as the "packer" block, provide information to the Packer core
+about what version it is allowed to run. The "required_plugins" block helps the
+Packer core
+
+Blocks can be defined in multiple files and `packer build folder` will build
+using solely the files from a directory named `folder`.
+
+Packer does not support user-defined blocks and so only the blocks built in to
+the language are available for use. The documentation includes all of the available built-in HCL2 blocks.
+
+## Config example:
+
+`@include 'from-1.5/variables/foo-block.mdx'`
+
+- [Variable block documentation](/packer/docs/templates/hcl_templates/blocks/variable).
+
+`@include 'from-1.5/locals/example-block.mdx'`
+
+- [Locals block documentation](/packer/docs/templates/hcl_templates/blocks/locals).
+
+`@include 'from-1.5/sources/example-block.mdx'`
+
+- [source block documentation](/packer/docs/templates/hcl_templates/blocks/source).
+
+`@include 'from-1.5/builds/example-block.mdx'`
+
+- [build block documentation](/packer/docs/templates/hcl_templates/blocks/build).
+
+`@include 'from-1.5/datasources/example-block.mdx'`
+
+- [data block documentation](/packer/docs/templates/hcl_templates/blocks/data).
diff --git a/v1.9.4/website/content/docs/templates/hcl_templates/blocks/locals.mdx b/v1.9.4/website/content/docs/templates/hcl_templates/blocks/locals.mdx
new file mode 100644
index 0000000..be45efb
--- /dev/null
+++ b/v1.9.4/website/content/docs/templates/hcl_templates/blocks/locals.mdx
@@ -0,0 +1,21 @@
+---
+description: >
+ The locals block also called the local-variable block defines locals within
+ your Packer configuration.
+page_title: locals - Blocks
+---
+
+# The `locals` block
+
+`@include 'from-1.5/beta-hcl2-note.mdx'`
+
+The `locals` block, also called the `local-variable` block, defines locals within
+your Packer configuration.
+
+`@include 'from-1.5/locals/example-block.mdx'`
+
+# More on variables
+
+- Read the [full locals](/packer/docs/templates/hcl_templates/locals) description for a more
+ thorough read.
+- Read the [variables guide](/packer/guides/hcl/variables) for more examples.
diff --git a/v1.9.4/website/content/docs/templates/hcl_templates/blocks/packer.mdx b/v1.9.4/website/content/docs/templates/hcl_templates/blocks/packer.mdx
new file mode 100644
index 0000000..b3e590e
--- /dev/null
+++ b/v1.9.4/website/content/docs/templates/hcl_templates/blocks/packer.mdx
@@ -0,0 +1,121 @@
+---
+page_title: packer - Blocks
+description: |-
+ The "packer" configuration section is used to configure some behaviors
+ of Packer itself.
+---
+
+# Packer Settings
+
+`@include 'from-1.5/beta-hcl2-note.mdx'`
+
+-> **Note:** The `packer` block is only available in Packer v1.6.5 and later.
+
+The `packer` configuration block type is used to configure some
+behaviors of Packer itself, such as the minimum required Packer version needed to
+apply your configuration.
+
+## Packer Block Syntax
+
+Packer settings are gathered together into `packer` blocks:
+
+```hcl
+packer {
+ # ...
+}
+```
+
+Each `packer` block can contain a number of settings related to Packer's
+behavior. Within a `packer` block, only constant values can be used;
+arguments may not refer to named objects such as resources, input variables,
+etc, and may not use any of the Packer language built-in functions.
+
+The various options supported within a `packer` block are described in the
+following sections.
+
+## Specifying a Required Packer Version
+
+The `required_version` setting accepts a [version constraint
+string,](#version-constraints) which specifies which versions of Packer
+can be used with your configuration.
+
+If the running version of Packer doesn't match the constraints specified,
+Packer will produce an error and exit without taking any further actions.
+
+Use Packer version constraints in a collaborative environment to
+ensure that everyone is using a specific Packer version, or using at least
+a minimum Packer version that has behavior expected by the configuration.
+
+## Specifying Plugin Requirements
+
+-> **Note:** The `required_plugins` block is only available in Packer v1.7.0 and
+later.
+
+The `required_plugins` block specifies all of the plugins required by the
+current config, mapping each local plugin name to a source address and a
+version constraint.
+
+```hcl
+packer {
+ required_plugins {
+ happycloud = {
+ version = ">= 2.7.0"
+ source = "github.com/hashicorp/happycloud"
+ }
+ }
+}
+```
+
+For more information, see [Plugins](/packer/docs/plugins).
+
+## Version Constraints
+
+Anywhere that Packer lets you specify a range of acceptable versions for
+something, it expects a specially formatted string known as a version
+constraint.
+
+### Version Constraint Syntax
+
+Packer's syntax for version constraints is very similar to the syntax used by
+other dependency management systems like Bundler and NPM.
+
+```hcl
+required_version = ">= 1.2.0, < 2.0.0"
+```
+
+A version constraint is a [string literal](/packer/docs/templates/hcl_templates/expressions#string-literals)
+containing one or more conditions, which are separated by commas.
+
+Each condition consists of an operator and a version number.
+
+Version numbers should be a series of numbers separated by periods (like
+`1.2.0`), optionally with a suffix to indicate a beta release.
+
+The following operators are valid:
+
+- `=` (or no operator): Allows only one exact version number. Cannot be combined
+ with other conditions.
+
+- `!=`: Excludes an exact version number.
+
+- `>`, `>=`, `<`, `<=`: Comparisons against a specified version, allowing
+ versions for which the comparison is true. "Greater-than" requests newer
+ versions, and "less-than" requests older versions.
+
+- `~>`: Allows the specified version, plus newer versions that only
+ increase the _most specific_ segment of the specified version number. For
+ example, `~> 0.9` is equivalent to `>= 0.9, < 1.0`, and `~> 0.8.4`, is
+ equivalent to `>= 0.8.4, < 0.9`. This is usually called the pessimistic
+ constraint operator.
+
+### Version Constraint Behavior
+
+A version number that meets every applicable constraint is considered acceptable.
+
+Packer consults version constraints to determine whether it has acceptable
+versions of itself.
+
+A prerelease version is a version number that contains a suffix introduced by
+a dash, like `1.2.0-beta`. A prerelease version can be selected only by an
+_exact_ version constraint (the `=` operator or no operator). Prerelease
+versions do not match inexact operators such as `>=`, `~>`, etc.
diff --git a/v1.9.4/website/content/docs/templates/hcl_templates/blocks/source.mdx b/v1.9.4/website/content/docs/templates/hcl_templates/blocks/source.mdx
new file mode 100644
index 0000000..d4b1070
--- /dev/null
+++ b/v1.9.4/website/content/docs/templates/hcl_templates/blocks/source.mdx
@@ -0,0 +1,61 @@
+---
+description: |
+ The top-level source block defines reusable builder configuration blocks
+page_title: source - Blocks
+---
+
+# The `source` block
+
+`@include 'from-1.5/beta-hcl2-note.mdx'`
+
+The top-level `source` block defines reusable builder configuration blocks:
+
+`@include 'from-1.5/sources/example-block.mdx'`
+
+The first label — `happycloud` here — is the builder type. The second label is
+the unique name or identifier you want to give to the source. There can be only one
+`source.happycloud.foo` top-level source block; but it can be used more than
+once. Builders are usually found in plugins, except for the `file` and the
+`null` builders that will remain in Packer core.
+
+You can start builders by referring to those source blocks from a [`build`
+block](/packer/docs/templates/hcl_templates/blocks/build) :
+
+```hcl
+build {
+ sources = [
+ # Here Packer will use a default ami_name when saving the image.
+ "source.happycloud.example",
+ "source.happycloud.foo",
+ ]
+}
+```
+
+The build-level [`source`
+block](/packer/docs/templates/hcl_templates/blocks/build/source) allows to set specific
+source fields. Each field must be defined only once and it is currently not
+allowed to override a value.
+
+```hcl
+build {
+ source "source.happycloud.example" {
+ # Here Packer will use the provided image_name instead of defaulting it.
+ # Note that fields cannot be overwritten, in other words, you cannot
+ # set the 'image_name' field in the top-level source block and here at the
+ # same time
+ image_name = "build_specific_field"
+ }
+}
+```
+
+`@include 'from-1.5/contextual-source-variables.mdx'`
+
+## Related
+
+- The list of available builders can be found in the [builders](/packer/docs/builders)
+ section.
+
+- A list of [community
+ builders](https://packer.io/community-tools#community-builders) is available.
+
+- Create your own [custom builder](/packer/docs/plugins/creation/custom-builders) !
diff --git a/v1.9.4/website/content/docs/templates/hcl_templates/blocks/variable.mdx b/v1.9.4/website/content/docs/templates/hcl_templates/blocks/variable.mdx
new file mode 100644
index 0000000..38b21aa
--- /dev/null
+++ b/v1.9.4/website/content/docs/templates/hcl_templates/blocks/variable.mdx
@@ -0,0 +1,39 @@
+---
+description: >
+ The variable block, also called the input-variable block, defines variables
+ within your Packer configuration.
+page_title: variable - Blocks
+---
+
+# The `variable` block
+
+`@include 'from-1.5/beta-hcl2-note.mdx'`
+
+The `variable` block, also called the `input-variable` block, defines variables
+within your Packer configuration. An input-variable cannot be used in another
+input variable: we recommend using [locals](/packer/docs/templates/hcl_templates/blocks/locals) for that instead.
+
+`@include 'from-1.5/variables/foo-block.mdx'`
+
+## Default value
+
+If a default value is set, the variable is optional. Otherwise, the variable
+**must** be set.
+
+`@include 'from-1.5/variables/assignment.mdx'`
+
+`@include 'from-1.5/variables/custom-validation.mdx'`
+
+Example of a variable assignment from a file:
+
+`@include 'from-1.5/variables/foo-pkrvar.mdx'`
+
+`@include 'from-1.5/variables/must-be-set.mdx'`
+
+`@include 'from-1.5/variables/sensitive.mdx'`
+
+# More on variables
+
+- Read the [full variables](/packer/docs/templates/hcl_templates/variables) description for a more
+ thorough read.
+- Read the [variables guide](/packer/guides/hcl/variables) for more examples.
diff --git a/v1.9.4/website/content/docs/templates/hcl_templates/contextual-variables.mdx b/v1.9.4/website/content/docs/templates/hcl_templates/contextual-variables.mdx
new file mode 100644
index 0000000..b755e10
--- /dev/null
+++ b/v1.9.4/website/content/docs/templates/hcl_templates/contextual-variables.mdx
@@ -0,0 +1,165 @@
+---
+page_title: Contextual Variables - HCL Configuration Language
+description: >-
+ Special variables provide connection information and basic instance state
+ information.
+
+ This page covers all existing special variables.
+---
+
+`@include 'from-1.5/beta-hcl2-note.mdx'`
+
+`@include 'from-1.5/contextual-source-variables.mdx'`
+
+# Build Variables
+
+Build variables will allow you to access connection information and basic instance state information for a builder.
+All special build variables are stored in the `build` variable:
+
+```hcl
+source "null" "first-example" {
+ communicator = "none"
+}
+
+build {
+ name = "my-build-name"
+ sources = ["null.first-example"]
+
+ provisioner "shell-local" {
+ environment_vars = ["TESTVAR=${build.PackerRunUUID}"]
+ inline = ["echo source.name is ${source.name}.",
+ "echo build.name is ${build.name}.",
+ "echo build.PackerRunUUID is $TESTVAR"]
+ }
+}
+```
+
+Here is the list of available build variables:
+
+- **name** Represents the name of the build block being run. This is different
+ than the name of the source block being run.
+
+- **ID**: Represents the VM being provisioned. For example, in Amazon it is the instance ID; in DigitalOcean,
+ it is the Droplet ID; in VMware, it is the VM name.
+
+- **Host**, **Port**, **User** and **Password**: The host, port, user, and password that Packer uses to access the machine.
+ Useful for using the shell local provisioner to run Ansible or Inspec against the provisioned instance.
+
+- **ConnType**: Type of communicator being used. For example, for SSH communicator this will be "ssh".
+
+- **PackerRunUUID**: Current build's unique ID. Can be used to specify build artifacts.
+ An example of that, is when multiple builds runs at the same time producing the same artifact.
+ It's possible to differentiate these artifacts by naming them with the builds' unique IDs.
+
+- **PackerHTTPIP**, **PackerHTTPPort**, and **PackerHTTPAddr**: HTTP IP, port, and address of the file server Packer creates to serve items in the "http" dir to the VM. The HTTP address is displayed in the format `IP:PORT`.
+
+- **SSHPublicKey** and **SSHPrivateKey**: The public and private key that Packer uses to connect to the instance.
+ These are unique to the SSH communicator and are unset when using other communicators.
+ **SSHPublicKey** and **SSHPrivateKey** can have escape sequences and special characters so their output should be single quoted to avoid surprises. For example:
+
+ ```hcl
+ provisioner "shell" {
+ inline = ["echo '${build.SSHPrivateKey}' > /tmp/packer-session.pem"]
+ }
+ ```
+
+For backwards compatibility, `WinRMPassword` is also available through this
+engine, though it is no different than using the more general `Password`.
+
+All build variables are valid to use with any of the [HCL2 functions](/packer/docs/templates/hcl_templates/functions).
+Example of using [upper](/packer/docs/templates/hcl_templates/functions/string/upper) to upper case the build ID:
+
+```hcl
+ post-processor "shell-local" {
+ inline = ["echo ${upper(build.ID)}"]
+ }
+```
+
+For builder-specific builder variables, please also refer to the builder docs:
+
+- Amazon EC2: [chroot](/packer/plugins/builders/amazon/chroot#build-shared-information-variables),
+ [EBS Volume](/packer/plugins/builders/amazon/ebsvolume#build-shared-information-variables),
+ [EBS](/packer/plugins/builders/amazon/ebs#build-shared-information-variables),
+ [EBS Surrogate](/packer/plugins/builders/amazon/ebssurrogate#build-shared-information-variables),
+ [Instance](/packer/plugins/builders/amazon/instance#build-shared-information-variables).
+
+The HCL2 Special Build Variables is in beta; please report any issues or requests on the Packer
+issue tracker on GitHub.
+
+# Packer Version
+
+This variable is set to the Packer version currently running.
+
+```hcl
+source "null" "first-example" {
+ communicator = "none"
+}
+
+build {
+ sources = ["null.first-example"]
+
+ provisioner "shell-local" {
+ inline = ["echo packer_version is '${packer.version}'"]
+ }
+}
+```
+
+If you are running a development version of Packer, the version variable will
+contain the released version number, dev flag, and current commit.
+
+```shell-session
+PACKER_LOG=0 packer build packer_version_demo.pkr.hcl
+null.first-example: output will be in this color.
+
+==> null.first-example: Running local shell script: /var/folders/8t/0yb5q0_x6mb2jldqq_vjn3lr0000gn/T/packer-shell083160352
+ null.first-example: packer_version is 1.6.5-dev (a69392129+CHANGES)
+```
+
+If you are running a released version of Packer, the version variable will
+contain the released version number only:
+
+```shell-session
+PACKER_LOG=0 packer build packer_version_demo.pkr.hcl
+null.first-example: output will be in this color.
+
+==> null.first-example: Running local shell script: /var/folders/8t/0yb5q0_x6mb2jldqq_vjn3lr0000gn/T/packer-shell718995312
+ null.first-example: packer_version is 1.6.5
+```
+
+Make sure to wrap your variable in single quotes in order to escape the
+string that is returned; if you are running a dev version of packer the
+parenthesis may through off your shell escaping otherwise.
+
+# HCP Packer Iteration ID
+
+If your build is pushing metadata to the HCP Packer registry, this variable is
+set to the value of the Iteration ID associated with this run.
+
+```hcl
+source "amazon-ebs" "cannonical-ubuntu-server" {
+ ami_name = "packer-example"
+ // ...
+ run_volume_tags = {
+ hcp_iteration_id = packer.iterationID
+ }
+}
+```
+
+```shell-session
+==> vanilla.amazon-ebs.cannonical-ubuntu-server: Adding tags to source instance
+ vanilla.amazon-ebs.cannonical-ubuntu-server: Adding tag: "Name": "Packer Builder"
+ vanilla.amazon-ebs.cannonical-ubuntu-server: Adding tag: "hcp_iteration_id": "01FHGF3M2AK4TS6PCZES4VX5E7"
+```
+
+You can also add this value to post-processors, for example to add to a manifest file:
+
+```hcl
+ post-processor "manifest" {
+ output = "manifest.json"
+ strip_path = true
+ custom_data = {
+ iteration = "${packer.iterationID}"
+ }
+ }
+
+```
diff --git a/v1.9.4/website/content/docs/templates/hcl_templates/datasources.mdx b/v1.9.4/website/content/docs/templates/hcl_templates/datasources.mdx
new file mode 100644
index 0000000..d596c61
--- /dev/null
+++ b/v1.9.4/website/content/docs/templates/hcl_templates/datasources.mdx
@@ -0,0 +1,86 @@
+---
+page_title: Data Sources
+description: >-
+ Data sources allow data to be fetched or computed for use elsewhere in local variables and
+ build sources configuration. Use of data sources
+ allows a Builder to make use of information defined outside of Packer.
+---
+
+# Data Sources
+
+-> **Note:** Data Sources is a feature included in Packer 1.7 and later.
+
+Data sources allow data to be fetched or computed for use elsewhere in [locals](/packer/docs/templates/hcl_templates/blocks/locals) and
+[sources](/packer/docs/templates/hcl_templates/blocks/source) configuration.
+Use of data sources allows a Builder to make use of information defined outside of Packer.
+
+# Using Data Sources
+
+A data source is declared using a data block, and the configuration looks like the following:
+
+```hcl
+data "amazon-ami" "example" {
+ filters = {
+ virtualization-type = "hvm"
+ name = "ubuntu/images/*ubuntu-xenial-16.04-amd64-server-*"
+ root-device-type = "ebs"
+ }
+ owners = ["099720109477"]
+ most_recent = true
+}
+```
+
+A data block requests that Packer read from a given data source ("amazon-ami") and export the result under the given
+local name ("example"). The name is used to refer to this data source from elsewhere in the same Packer configuration.
+
+The data block creates a data instance of the given _type_ (first block label) and _name_ (second block label).
+The combination of the type and name must be unique within a configuration.
+
+Within the block (the `{ }`) is the configuration for the data instance. The configuration is dependent on the data source type,
+and is documented for each data source. For example the configuration of the `amazon-ami` data source can be found at [plugins/datasources/amazon/ami](/packer/plugins/datasources/amazon/ami#configuration-reference).
+
+A data source can output one or more attributes, which can be used by adding their key name to the data source unique
+identifier, like `data.<TYPE>.<NAME>.<ATTRIBUTE>`.
+
+The output from the `amazon-ami.example` above can be accessed as follows:
+
+Output data:
+
+```
+"data.amazon-ami.example" {
+ id = "ami12345"
+ name = "MyAMI"
+ creation_date = "01/01/2021"
+ owner = "123456789"
+ owner_name = "Some Name"
+ tags = {"tag1": "value"}
+}
+```
+
+Usage:
+
+```hcl
+// in a local
+locals {
+ source_ami_id = data.amazon-ami.example.id
+ source_ami_name = data.amazon-ami.example.name
+ }
+```
+
+```hcl
+// in a source
+source "amazon-ebs" "basic-example" {
+ source_ami = locals.source_ami
+ // ...
+}
+```
+
+## Known Limitations
+`@include 'datasources/local-dependency-limitation.mdx'`
+
+
+## Related
+
+- The list of available data sources can be found in the [data sources](/packer/docs/datasources)
+ section.
+- Create your own [custom data source](/packer/docs/plugins/creation/custom-datasources) !
diff --git a/v1.9.4/website/content/docs/templates/hcl_templates/expressions.mdx b/v1.9.4/website/content/docs/templates/hcl_templates/expressions.mdx
new file mode 100644
index 0000000..4fb5012
--- /dev/null
+++ b/v1.9.4/website/content/docs/templates/hcl_templates/expressions.mdx
@@ -0,0 +1,431 @@
+---
+page_title: Expressions - Configuration Language
+description: |-
+ HCL allows the use of expressions to access data exported
+ by sources and to transform and combine that data to produce other values.
+---
+
+# Expressions
+
+`@include 'from-1.5/beta-hcl2-note.mdx'`
+
+_Expressions_ are used to refer to or compute values within a configuration.
+The simplest expressions are just literal values, like `"hello"` or `5`, but
+HCL also allows more complex expressions such as references to data exported by
+sources, arithmetic, conditional evaluation, and a number of built-in
+functions.
+
+Expressions can be used in a number of places in HCL, but some contexts limit
+which expression constructs are allowed, such as requiring a literal value of a
+particular type or forbidding. Each language feature's documentation describes
+any restrictions it places on expressions.
+
+The rest of this page describes all of the features of Packer's
+expression syntax.
+
+## Types and Values
+
+The result of an expression is a _value_. All values have a _type_, which
+dictates where that value can be used and what transformations can be
+applied to it.
+
+HCL uses the following types for its values:
+
+- `string`: a sequence of Unicode characters representing some text, like
+ `"hello"`.
+- `number`: a numeric value. The `number` type can represent both whole
+ numbers like `15` and fractional values like `6.283185`.
+- `bool`: either `true` or `false`. `bool` values can be used in conditional
+ logic.
+- `list` (or `tuple`): a sequence of values, like
+ `["us-west-1a", "us-west-1c"]`. Elements in a list or tuple are identified by
+ consecutive whole numbers, starting with zero.
+- `map` (or `object`): a group of values identified by named labels, like
+ `{name = "Mabel", age = 52}`.
+
+Strings, numbers, and bools are sometimes called _primitive types._
+Lists/tuples and maps/objects are sometimes called _complex types,_ _structural
+types,_ or _collection types._
+
+Finally, there is one special value that has _no_ type:
+
+- `null`: a value that represents _absence_ or _omission._ If you set an
+ argument of a source or module to `null`, Packer behaves as though you
+ had completely omitted it — it will use the argument's default value if it has
+ one, or raise an error if the argument is mandatory. `null` is most useful in
+ conditional expressions, so you can dynamically omit an argument if a
+ condition isn't met.
+
+### Advanced Type Details
+
+In most situations, lists and tuples behave identically, as do maps and objects.
+Whenever the distinction isn't relevant, the Packer documentation uses each
+pair of terms interchangeably (with a historical preference for "list" and
+"map").
+
+However, plugin authors should understand the differences between these similar
+types (and the related `set` type), since they offer different ways to restrict
+the allowed values for input variables and source arguments.
+
+### Type Conversion
+
+Expressions are most often used to set values for arguments. In these cases,
+the argument has an expected type and the given expression must produce a value
+of that type.
+
+Where possible, Packer automatically converts values from one type to
+another in order to produce the expected type. If this isn't possible, Packer
+will produce a type mismatch error and you must update the configuration with a
+more suitable expression.
+
+Packer automatically converts number and bool values to strings when needed.
+It also converts strings to numbers or bools, as long as the string contains a
+valid representation of a number or bool value.
+
+- `true` converts to `"true"`, and vice-versa
+- `false` converts to `"false"`, and vice-versa
+- `15` converts to `"15"`, and vice-versa
+
+## Literal Expressions
+
+A _literal expression_ is an expression that directly represents a particular
+constant value. Packer has a literal expression syntax for each of the value
+types described above:
+
+- Strings are usually represented by a double-quoted sequence of Unicode
+ characters, `"like this"`. There is also a "heredoc" syntax for more complex
+ strings. String literals are the most complex kind of literal expression in
+ Packer, and have additional documentation on this page:
+ - See [String Literals](#string-literals) below for information about escape
+ sequences and the heredoc syntax.
+ - See [String Templates](#string-templates) below for information about
+ interpolation and template directives.
+- Numbers are represented by unquoted sequences of digits with or without a
+ decimal point, like `15` or `6.283185`.
+- Bools are represented by the unquoted symbols `true` and `false`.
+- The null value is represented by the unquoted symbol `null`.
+- Lists/tuples are represented by a pair of square brackets containing a
+ comma-separated sequence of values, like `["a", 15, true]`.
+
+ List literals can be split into multiple lines for readability, but always
+ require a comma between values. A comma after the final value is allowed,
+ but not required. Values in a list can be arbitrary expressions.
+
+- Maps/objects are represented by a pair of curly braces containing a series of
+ `<KEY> = <VALUE>` pairs:
+
+ ```hcl
+ {
+ name = "John"
+ age = 52
+ }
+ ```
+
+ Key/value pairs can be separated by either a comma or a line break. Values
+ can be arbitrary expressions. Keys are strings; they can be left unquoted if
+ they are a valid [identifier](/packer/docs/templates/hcl_templates/syntax#identifiers), but must be quoted
+ otherwise. You can use a non-literal expression as a key by wrapping it in
+ parentheses, like `(var.business_unit_tag_name) = "SRE"`.
+
+## References to Named Values
+
+Packer makes one named values available.
+
+The following named values are available:
+
+- `source.<SOURCE TYPE>.<NAME>` is an object representing a
+ [source](/packer/docs/templates/hcl_templates/blocks/source) of the given type
+ and name.
+
+### Available Functions
+
+For a full list of available functions, see [the function
+reference](/packer/docs/templates/hcl_templates/functions).
+
+## `for` Expressions
+
+A _`for` expression_ creates a complex type value by transforming
+another complex type value. Each element in the input value
+can correspond to either one or zero values in the result, and an arbitrary
+expression can be used to transform each input element into an output element.
+
+For example, if `var.list` is a list of strings, then the following expression
+produces a list of strings with all-uppercase letters:
+
+```hcl
+[for s in var.list : upper(s)]
+```
+
+This `for` expression iterates over each element of `var.list`, and then
+evaluates the expression `upper(s)` with `s` set to each respective element.
+It then builds a new tuple value with all of the results of executing that
+expression in the same order.
+
+The type of brackets around the `for` expression decide what type of result
+it produces. The above example uses `[` and `]`, which produces a tuple. If
+`{` and `}` are used instead, the result is an object, and two result
+expressions must be provided separated by the `=>` symbol:
+
+```hcl
+{for s in var.list : s => upper(s)}
+```
+
+This expression produces an object whose attributes are the original elements
+from `var.list` and their corresponding values are the uppercase versions.
+
+A `for` expression can also include an optional `if` clause to filter elements
+from the source collection, which can produce a value with fewer elements than
+the source:
+
+```text
+[for s in var.list : upper(s) if s != ""]
+```
+
+The source value can also be an object or map value, in which case two
+temporary variable names can be provided to access the keys and values
+respectively:
+
+```text
+[for k, v in var.map : length(k) + length(v)]
+```
+
+Finally, if the result type is an object (using `{` and `}` delimiters) then
+the value result expression can be followed by the `...` symbol to group
+together results that have a common key:
+
+```text
+{for s in var.list : substr(s, 0, 1) => s... if s != ""}
+```
+
+## Splat Expressions
+
+A _splat expression_ provides a more concise way to express a common operation
+that could otherwise be performed with a `for` expression.
+
+If `var.list` is a list of objects that all have an attribute `id`, then a list
+of the IDs could be produced with the following `for` expression:
+
+```hcl
+[for o in var.list : o.id]
+```
+
+This is equivalent to the following _splat expression:_
+
+```hcl
+var.list[*].id
+```
+
+The special `[*]` symbol iterates over all of the elements of the list given to
+its left and accesses from each one the attribute name given on its right. A
+splat expression can also be used to access attributes and indexes from lists
+of complex types by extending the sequence of operations to the right of the
+symbol:
+
+```hcl
+var.list[*].interfaces[0].name
+```
+
+The above expression is equivalent to the following `for` expression:
+
+```hcl
+[for o in var.list : o.interfaces[0].name]
+```
+
+Splat expressions are for lists only (and thus cannot be used [to reference
+resources created with
+`for_each`](/terraform/docs/configuration/resources#referring-to-instances), which
+are represented as maps). However, if a splat expression is applied to a value
+that is _not_ a list or tuple then the value is automatically wrapped in a
+single-element list before processing.
+
+For example, `var.single_object[*].id` is equivalent to
+`[var.single_object][*].id`, or effectively `[var.single_object.id]`. This
+behavior is not interesting in most cases, but it is particularly useful when
+referring to resources that may or may not have `count` set, and thus may or
+may not produce a tuple value:
+
+```hcl
+aws_instance.example[*].id
+```
+
+The above will produce a list of IDs whether `aws_instance.example` has `count`
+set or not, avoiding the need to revise various other expressions in the
+configuration when a particular resource switches to and from having `count`
+set.
+
+## `dynamic` blocks
+
+Within top-level block constructs like [source](/packer/docs/templates/hcl_templates/blocks/source), expressions
+can usually be used only when assigning a value to an argument using the `name = expression` or `key = expression` form.
+This covers many uses, but some source types include repeatable _nested blocks_ in their arguments, which do not accept expressions:
+
+```hcl
+source "amazon-ebs" "example" {
+ name = "pkr-test-name" # can use expressions here
+
+ tag {
+ # but the "tag" block is always a literal block
+ }
+}
+```
+
+You can dynamically construct repeatable nested blocks like `tag` using a
+special `dynamic` block type, which is supported in top-level block constructs, example:
+
+```hcl
+locals {
+ standard_tags = {
+ Component = "user-service"
+ Environment = "production"
+ }
+}
+
+source "amazon-ebs" "example" {
+ # ...
+
+ tag {
+ key = "Name"
+ value = "example-asg-name"
+ }
+
+ dynamic "tag" {
+ for_each = local.standard_tags
+
+ content {
+ key = tag.key
+ value = tag.value
+ }
+ }
+}
+```
+
+A `dynamic` block acts much like a `for` expression, but produces nested blocks
+instead of a complex typed value. It iterates over a given complex value, and
+generates a nested block for each element of that complex value.
+
+- The label of the dynamic block (`"tag"` in the example above) specifies
+ what kind of nested block to generate.
+- The `for_each` argument provides the complex value to iterate over.
+- The `iterator` argument (optional) sets the name of a temporary variable
+ that represents the current element of the complex value. If omitted, the name
+ of the variable defaults to the label of the `dynamic` block (`"tag"` in
+ the example above).
+- The `labels` argument (optional) is a list of strings that specifies the block
+ labels, in order, to use for each generated block. You can use the temporary
+ iterator variable in this value.
+- The nested `content` block defines the body of each generated block. You can
+ use the temporary iterator variable inside this block.
+
+Since the `for_each` argument accepts any collection or structural value,
+you can use a `for` expression or splat expression to transform an existing
+collection.
+
+The iterator object (`tag` in the example above) has two attributes:
+
+- `key` is the map key or list element index for the current element. If the
+ `for_each` expression produces a _set_ value then `key` is identical to
+ `value` and should not be used.
+- `value` is the value of the current element.
+
+A `dynamic` block can only generate arguments for nested blocks that belong to
+the source type, data source, or provisioner being configured.
+
+The `for_each` value must be a map or set with one element per desired nested
+block. If you need to declare resource instances based on a nested data
+structure or combinations of elements from multiple data structures you can use
+expressions and functions to derive a suitable value. For some common examples
+of such situations, see the
+[`flatten`](/packer/docs/templates/hcl_templates/functions/collection/flatten) and
+[`setproduct`](/packer/docs/templates/hcl_templates/functions/collection/setproduct)
+functions.
+
+### Best Practices for `dynamic` Blocks
+
+Overuse of `dynamic` blocks can make configuration hard to read and maintain,
+so we recommend using them only when you need to hide details in order to build
+a clean user interface for a re-usable code. Always write nested blocks out
+literally where possible.
+
+## String Literals
+
+HCL has two different syntaxes for string literals. The
+most common is to delimit the string with quote characters (`"`), like
+`"hello"`. In quoted strings, the backslash character serves as an escape
+sequence, with the following characters selecting the escape behavior:
+
+| Sequence | Replacement |
+| ------------ | ----------------------------------------------------------------------------- |
+| `\n` | Newline |
+| `\r` | Carriage Return |
+| `\t` | Tab |
+| `\"` | Literal quote (without terminating the string) |
+| `\\` | Literal backslash |
+| `\uNNNN` | Unicode character from the basic multilingual plane (NNNN is four hex digits) |
+| `\UNNNNNNNN` | Unicode character from supplementary planes (NNNNNNNN is eight hex digits) |
+
+The alternative syntax for string literals is the so-called Here Documents or
+"heredoc" style, inspired by Unix shell languages. This style allows multi-line
+strings to be expressed more clearly by using a custom delimiter word on a line
+of its own to close the string:
+
+```hcl
+<<EOF
+hello
+world
+EOF
+```
+
+The `<<` marker followed by any identifier at the end of a line introduces the
+sequence. Packer then processes the following lines until it finds one that
+consists entirely of the identifier given in the introducer. In the above
+example, `EOF` is the identifier selected. Any identifier is allowed, but
+conventionally this identifier is in all-uppercase and begins with `EO`, meaning
+"end of". `EOF` in this case stands for "end of text".
+
+The "heredoc" form shown above requires that the lines following be flush with
+the left margin, which can be awkward when an expression is inside an indented
+block:
+
+```hcl
+block {
+ value = <<EOF
+hello
+world
+EOF
+}
+```
+
+To improve on this, Packer also accepts an _indented_ heredoc string variant
+that is introduced by the `<<-` sequence:
+
+```hcl
+block {
+ value = <<-EOF
+ hello
+ world
+ EOF
+}
+```
+
+In this case, Packer analyses the lines in the sequence to find the one
+with the smallest number of leading spaces, and then trims that many spaces
+from the beginning of all of the lines, leading to the following result:
+
+```text
+hello
+ world
+```
+
+Backslash sequences are not interpreted in a heredoc string expression.
+Instead, the backslash character is interpreted literally.
+
+In both quoted and heredoc string expressions, Packer supports template
+sequences that begin with `${` and `%{`. These are described in more detail
+in the following section. To include these sequences _literally_ without
+beginning a template sequence, double the leading character: `$${` or `%%{`.
+
+## String Templates
+
+Within quoted and heredoc string expressions, the sequences `${` and `%{` begin
+_template sequences_. Templates let you directly embed expressions into a string
+literal, to dynamically construct strings from other values.
diff --git a/v1.9.4/website/content/docs/templates/hcl_templates/functions/collection/chunklist.mdx b/v1.9.4/website/content/docs/templates/hcl_templates/functions/collection/chunklist.mdx
new file mode 100644
index 0000000..66658bf
--- /dev/null
+++ b/v1.9.4/website/content/docs/templates/hcl_templates/functions/collection/chunklist.mdx
@@ -0,0 +1,34 @@
+---
+page_title: chunklist - Functions - Configuration Language
+description: |-
+ The chunklist function splits a single list into fixed-size chunks, returning
+ a list of lists.
+---
+
+# `chunklist` Function
+
+`chunklist` splits a single list into fixed-size chunks, returning a list
+of lists.
+
+```hcl
+chunklist(list, chunk_size)
+```
+
+## Examples
+
+```shell-session
+> chunklist(["a", "b", "c", "d", "e"], 2)
+[
+ ["a", "b"],
+ ["c", "d"],
+ ["e"]
+]
+> chunklist(["a", "b", "c", "d", "e"], 1)
+[
+ ["a"],
+ ["b"],
+ ["c"],
+ ["d"],
+ ["e"]
+]
+```
diff --git a/v1.9.4/website/content/docs/templates/hcl_templates/functions/collection/coalesce.mdx b/v1.9.4/website/content/docs/templates/hcl_templates/functions/collection/coalesce.mdx
new file mode 100644
index 0000000..f46673c
--- /dev/null
+++ b/v1.9.4/website/content/docs/templates/hcl_templates/functions/collection/coalesce.mdx
@@ -0,0 +1,35 @@
+---
+page_title: coalesce - Functions - Configuration Language
+description: |-
+ The coalesce function takes any number of arguments and returns the
+ first one that isn't null nor empty.
+---
+
+# `coalesce` Function
+
+`coalesce` takes any number of arguments and returns the first one
+that isn't null or an empty string.
+
+## Examples
+
+```shell-session
+> coalesce("a", "b")
+a
+> coalesce("", "b")
+b
+> coalesce(1,2)
+1
+```
+
+To perform the `coalesce` operation with a list of strings, use the `...`
+symbol to expand the list as arguments:
+
+```shell-session
+> coalesce(["", "b"]...)
+b
+```
+
+## Related Functions
+
+- [`coalescelist`](/packer/docs/templates/hcl_templates/functions/collection/coalescelist) performs a similar operation with
+ list arguments rather than individual arguments.
diff --git a/v1.9.4/website/content/docs/templates/hcl_templates/functions/collection/coalescelist.mdx b/v1.9.4/website/content/docs/templates/hcl_templates/functions/collection/coalescelist.mdx
new file mode 100644
index 0000000..79d9d85
--- /dev/null
+++ b/v1.9.4/website/content/docs/templates/hcl_templates/functions/collection/coalescelist.mdx
@@ -0,0 +1,42 @@
+---
+page_title: coalescelist - Functions - Configuration Language
+description: |-
+ The coalescelist function takes any number of list arguments and returns the
+ first one that isn't empty.
+---
+
+# `coalescelist` Function
+
+`coalescelist` takes any number of list arguments and returns the first one
+that isn't empty.
+
+## Examples
+
+```shell-session
+> coalescelist(["a", "b"], ["c", "d"])
+[
+ "a",
+ "b",
+]
+> coalescelist([], ["c", "d"])
+[
+ "c",
+ "d",
+]
+```
+
+To perform the `coalescelist` operation with a list of lists, use the `...`
+symbol to expand the outer list as arguments:
+
+```shell-session
+> coalescelist([[], ["c", "d"]]...)
+[
+ "c",
+ "d",
+]
+```
+
+## Related Functions
+
+- [`coalesce`](/packer/docs/templates/hcl_templates/functions/collection/coalesce) performs a similar operation with string
+ arguments rather than list arguments.
diff --git a/v1.9.4/website/content/docs/templates/hcl_templates/functions/collection/compact.mdx b/v1.9.4/website/content/docs/templates/hcl_templates/functions/collection/compact.mdx
new file mode 100644
index 0000000..df8b79e
--- /dev/null
+++ b/v1.9.4/website/content/docs/templates/hcl_templates/functions/collection/compact.mdx
@@ -0,0 +1,20 @@
+---
+page_title: compact - Functions - Configuration Language
+description: The compact function removes empty string elements from a list.
+---
+
+# `compact` Function
+
+`compact` takes a list of strings and returns a new list with any empty string
+elements removed.
+
+## Examples
+
+```shell-session
+> compact(["a", "", "b", "c"])
+[
+ "a",
+ "b",
+ "c",
+]
+```
diff --git a/v1.9.4/website/content/docs/templates/hcl_templates/functions/collection/concat.mdx b/v1.9.4/website/content/docs/templates/hcl_templates/functions/collection/concat.mdx
new file mode 100644
index 0000000..318b72f
--- /dev/null
+++ b/v1.9.4/website/content/docs/templates/hcl_templates/functions/collection/concat.mdx
@@ -0,0 +1,20 @@
+---
+page_title: concat - Functions - Configuration Language
+description: The concat function combines two or more lists into a single list.
+---
+
+# `concat` Function
+
+`concat` takes two or more lists and combines them into a single list.
+
+## Examples
+
+```shell-session
+> concat(["a", ""], ["b", "c"])
+[
+ "a",
+ "",
+ "b",
+ "c",
+]
+```
diff --git a/v1.9.4/website/content/docs/templates/hcl_templates/functions/collection/contains.mdx b/v1.9.4/website/content/docs/templates/hcl_templates/functions/collection/contains.mdx
new file mode 100644
index 0000000..43cdd5c
--- /dev/null
+++ b/v1.9.4/website/content/docs/templates/hcl_templates/functions/collection/contains.mdx
@@ -0,0 +1,22 @@
+---
+page_title: contains - Functions - Configuration Language
+description: The contains function determines whether a list or set contains a given value.
+---
+
+# `contains` Function
+
+`contains` determines whether a given list or set contains a given single value
+as one of its elements.
+
+```hcl
+contains(list, value)
+```
+
+## Examples
+
+```shell-session
+> contains(["a", "b", "c"], "a")
+true
+> contains(["a", "b", "c"], "d")
+false
+```
diff --git a/v1.9.4/website/content/docs/templates/hcl_templates/functions/collection/distinct.mdx b/v1.9.4/website/content/docs/templates/hcl_templates/functions/collection/distinct.mdx
new file mode 100644
index 0000000..28fe7a4
--- /dev/null
+++ b/v1.9.4/website/content/docs/templates/hcl_templates/functions/collection/distinct.mdx
@@ -0,0 +1,24 @@
+---
+page_title: distinct - Functions - Configuration Language
+description: The distinct function removes duplicate elements from a list.
+---
+
+# `distinct` Function
+
+`distinct` takes a list and returns a new list with any duplicate elements
+removed.
+
+The first occurrence of each value is retained and the relative ordering of
+these elements is preserved.
+
+## Examples
+
+```shell-session
+> distinct(["a", "b", "a", "c", "d", "b"])
+[
+ "a",
+ "b",
+ "c",
+ "d",
+]
+```
diff --git a/v1.9.4/website/content/docs/templates/hcl_templates/functions/collection/element.mdx b/v1.9.4/website/content/docs/templates/hcl_templates/functions/collection/element.mdx
new file mode 100644
index 0000000..6373cc3
--- /dev/null
+++ b/v1.9.4/website/content/docs/templates/hcl_templates/functions/collection/element.mdx
@@ -0,0 +1,38 @@
+---
+page_title: element - Functions - Configuration Language
+description: The element function retrieves a single element from a list.
+---
+
+# `element` Function
+
+`element` retrieves a single element from a list.
+
+```hcl
+element(list, index)
+```
+
+The index is zero-based. This function produces an error if used with an
+empty list.
+
+Use the built-in index syntax `list[index]` in most cases. Use this function
+only for the special additional "wrap-around" behavior described below.
+
+## Examples
+
+```shell-session
+> element(["a", "b", "c"], 1)
+b
+```
+
+If the given index is greater than the length of the list then the index is
+"wrapped around" by taking the index modulo the length of the list:
+
+```shell-session
+> element(["a", "b", "c"], 3)
+a
+```
+
+## Related Functions
+
+- [`index`](/packer/docs/templates/hcl_templates/functions/collection/index-fn) finds the index for a particular element value.
+- [`lookup`](/packer/docs/templates/hcl_templates/functions/collection/lookup) retrieves a value from a _map_ given its _key_.
diff --git a/v1.9.4/website/content/docs/templates/hcl_templates/functions/collection/flatten.mdx b/v1.9.4/website/content/docs/templates/hcl_templates/functions/collection/flatten.mdx
new file mode 100644
index 0000000..a3bc2f4
--- /dev/null
+++ b/v1.9.4/website/content/docs/templates/hcl_templates/functions/collection/flatten.mdx
@@ -0,0 +1,108 @@
+---
+page_title: flatten - Functions - Configuration Language
+description: The flatten function eliminates nested lists from a list.
+---
+
+# `flatten` Function
+
+`flatten` takes a list and replaces any elements that are lists with a
+flattened sequence of the list contents.
+
+## Examples
+
+```shell-session
+> flatten([["a", "b"], [], ["c"]])
+["a", "b", "c"]
+```
+
+If any of the nested lists also contain directly-nested lists, these too are
+flattened recursively:
+
+```shell-session
+> flatten([[["a", "b"], []], ["c"]])
+["a", "b", "c"]
+```
+
+Indirectly-nested lists, such as those in maps, are _not_ flattened.
+
+## Flattening nested structures for `for_each`
+
+The
+[resource `for_each`](/terraform/docs/configuration/resources#for_each-multiple-resource-instances-defined-by-a-map-or-set-of-strings)
+and
+[`dynamic` block](/packer/docs/templates/hcl_templates/expressions#dynamic-blocks)
+language features both require a collection value that has one element for
+each repetition.
+
+Sometimes your input data structure isn't naturally in a suitable shape for
+use in a `for_each` argument, and `flatten` can be a useful helper function
+when reducing a nested data structure into a flat one.
+
+For example, consider a folder that declares a variable like the following:
+
+```hcl
+variable "networks" {
+ type = map(object({
+ cidr_block = string
+ subnets = map(object({
+ cidr_block = string
+ })
+ })
+}
+```
+
+The above is a reasonable way to model objects that naturally form a tree,
+such as top-level networks and their subnets. The repetition for the top-level
+networks can use this variable directly, because it's already in a form
+where the resulting instances match one-to-one with map elements:
+
+```hcl
+resource "aws_vpc" "example" {
+ for_each = var.networks
+
+ cidr_block = each.value.cidr_block
+}
+```
+
+However, in order to declare all of the _subnets_ with a single `resource`
+block, we must first flatten the structure to produce a collection where each
+top-level element represents a single subnet:
+
+```hcl
+locals {
+ # flatten ensures that this local value is a flat list of objects, rather
+ # than a list of lists of objects.
+ network_subnets = flatten([
+ for network_key, network in var.networks : [
+ for subnet_key, subnet in network.subnets : {
+ network_key = network_key
+ subnet_key = subnet_key
+ network_id = aws_vpc.example[network_key].id
+ cidr_block = subnet.cidr_block
+ }
+ ]
+ ])
+}
+
+resource "aws_subnet" "example" {
+ # local.network_subnets is a list, so we must now project it into a map
+ # where each key is unique. We'll combine the network and subnet keys to
+ # produce a single unique key per instance.
+ for_each = {
+ for subnet in local.network_subnets : "${subnet.network_key}.${subnet.subnet_key}" => subnet
+ }
+
+ vpc_id = each.value.network_id
+ availability_zone = each.value.subnet_key
+ cidr_block = each.value_cidr_block
+}
+```
+
+The above results in one subnet instance per subnet object, while retaining
+the associations between the subnets and their containing networks.
+
+## Related Functions
+
+- [`setproduct`](/packer/docs/templates/hcl_templates/functions/collection/setproduct) finds all of the combinations of multiple
+ lists or sets of values, which can also be useful when preparing collections
+ for use with `for_each` constructs.
diff --git a/v1.9.4/website/content/docs/templates/hcl_templates/functions/collection/index-fn.mdx b/v1.9.4/website/content/docs/templates/hcl_templates/functions/collection/index-fn.mdx
new file mode 100644
index 0000000..80c80ca
--- /dev/null
+++ b/v1.9.4/website/content/docs/templates/hcl_templates/functions/collection/index-fn.mdx
@@ -0,0 +1,27 @@
+---
+page_title: index - Functions - Configuration Language
+description: The index function finds the element index for a given value in a list.
+---
+
+# `index` Function
+
+`index` finds the element index for a given value in a list.
+
+```hcl
+index(list, value)
+```
+
+The returned index is zero-based. This function produces an error if the given
+value is not present in the list.
+
+## Examples
+
+```shell-session
+> index(["a", "b", "c"], "b")
+1
+```
+
+## Related Functions
+
+- [`element`](/packer/docs/templates/hcl_templates/functions/collection/element) retrieves a particular element from a list given
+ its index.
diff --git a/v1.9.4/website/content/docs/templates/hcl_templates/functions/collection/keys.mdx b/v1.9.4/website/content/docs/templates/hcl_templates/functions/collection/keys.mdx
new file mode 100644
index 0000000..cd955f9
--- /dev/null
+++ b/v1.9.4/website/content/docs/templates/hcl_templates/functions/collection/keys.mdx
@@ -0,0 +1,26 @@
+---
+page_title: keys - Functions - Configuration Language
+description: The keys function returns a list of the keys in a given map.
+---
+
+# `keys` Function
+
+`keys` takes a map and returns a list containing the keys from that map.
+
+The keys are returned in lexicographical order, ensuring that the result will
+be identical as long as the keys in the map don't change.
+
+## Examples
+
+```shell-session
+> keys({a=1, c=2, d=3})
+[
+ "a",
+ "c",
+ "d",
+]
+```
+
+## Related Functions
+
+- [`values`](/packer/docs/templates/hcl_templates/functions/collection/values) returns a list of the _values_ from a map.
diff --git a/v1.9.4/website/content/docs/templates/hcl_templates/functions/collection/length.mdx b/v1.9.4/website/content/docs/templates/hcl_templates/functions/collection/length.mdx
new file mode 100644
index 0000000..71eacc8
--- /dev/null
+++ b/v1.9.4/website/content/docs/templates/hcl_templates/functions/collection/length.mdx
@@ -0,0 +1,39 @@
+---
+page_title: length - Functions - Configuration Language
+description: The length function determines the length of a collection or string.
+---
+
+# `length` Function
+
+`length` determines the length of a given list, map, or string.
+
+If given a list or map, the result is the number of elements in that collection.
+If given a string, the result is the number of characters in the string.
+
+## Examples
+
+```shell-session
+> length([])
+0
+> length(["a", "b"])
+2
+> length({"a" = "b"})
+1
+> length("hello")
+5
+```
+
+When given a string, the result is the number of characters, rather than the
+number of bytes or Unicode sequences that form them:
+
+```shell-session
+> length("👾🕹️")
+2
+```
+
+A "character" is a _grapheme cluster_, as defined by
+[Unicode Standard Annex #29](http://unicode.org/reports/tr29/). Note that
+remote APIs may have a different definition of "character" for the purpose of
+length limits on string arguments; a Packer provider is responsible for
+translating Packer's string representation into that used by its respective
+remote system and applying any additional validation rules to it.
diff --git a/v1.9.4/website/content/docs/templates/hcl_templates/functions/collection/lookup.mdx b/v1.9.4/website/content/docs/templates/hcl_templates/functions/collection/lookup.mdx
new file mode 100644
index 0000000..0eb6860
--- /dev/null
+++ b/v1.9.4/website/content/docs/templates/hcl_templates/functions/collection/lookup.mdx
@@ -0,0 +1,26 @@
+---
+page_title: lookup - Functions - Configuration Language
+description: The lookup function retrieves an element value from a map given its key.
+---
+
+# `lookup` Function
+
+`lookup` retrieves the value of a single element from a map, given its key.
+If the given key does not exist, the given default value is returned instead.
+
+```hcl
+lookup(map, key, default)
+```
+
+## Examples
+
+```shell-session
+> lookup({a="ay", b="bee"}, "a", "what?")
+ay
+> lookup({a="ay", b="bee"}, "c", "what?")
+what?
+```
+
+## Related Functions
+
+- [`element`](/packer/docs/templates/hcl_templates/functions/collection/element) retrieves a value from a _list_ given its _index_.
diff --git a/v1.9.4/website/content/docs/templates/hcl_templates/functions/collection/merge.mdx b/v1.9.4/website/content/docs/templates/hcl_templates/functions/collection/merge.mdx
new file mode 100644
index 0000000..e6ac8b7
--- /dev/null
+++ b/v1.9.4/website/content/docs/templates/hcl_templates/functions/collection/merge.mdx
@@ -0,0 +1,25 @@
+---
+page_title: merge - Functions - Configuration Language
+description: |-
+ The merge function takes an arbitrary number of maps and returns a single
+ map after merging the keys from each argument.
+---
+
+# `merge` Function
+
+`merge` takes an arbitrary number of maps and returns a single map that
+contains a merged set of elements from all of the maps.
+
+If more than one given map defines the same key then the one that is later
+in the argument sequence takes precedence.
+
+## Examples
+
+```shell-session
+> merge({"a"="b", "c"="d"}, {"e"="f", "c"="z"})
+{
+ "a" = "b"
+ "c" = "z"
+ "e" = "f"
+}
+```
diff --git a/v1.9.4/website/content/docs/templates/hcl_templates/functions/collection/range.mdx b/v1.9.4/website/content/docs/templates/hcl_templates/functions/collection/range.mdx
new file mode 100644
index 0000000..9ddf0af
--- /dev/null
+++ b/v1.9.4/website/content/docs/templates/hcl_templates/functions/collection/range.mdx
@@ -0,0 +1,139 @@
+---
+page_title: range - Functions - Configuration Language
+description: The range function generates sequences of numbers.
+---
+
+# `range` Function
+
+`range` generates a list of numbers using a start value, a limit value,
+and a step value.
+
+```hcl
+range(max)
+range(start, limit)
+range(start, limit, step)
+```
+
+The `start` and `step` arguments can be omitted, in which case `start` defaults
+to zero and `step` defaults to either one or negative one depending on whether
+`limit` is greater than or less than `start`.
+
+The resulting list is created by starting with the given `start` value and
+repeatedly adding `step` to it until the result is equal to or beyond `limit`.
+
+The interpretation of `limit` depends on the direction of `step`: for a positive
+step, the sequence is complete when the next number is greater than or equal
+to `limit`. For a negative step, it's complete when less than or equal.
+
+The sequence-building algorithm follows the following pseudocode:
+
+```text
+let num = start
+while num < limit: (or, for negative step, num >= limit)
+ append num to the sequence
+ num = num + step
+return the sequence
+```
+
+Because the sequence is created as a physical list in memory, Packer imposes
+an artificial limit of 1024 numbers in the resulting sequence in order to avoid
+unbounded memory usage if, for example, a very large value were accidentally
+passed as the limit or a very small value as the step. If the algorithm above
+would append the 1025th number to the sequence, the function immediately exits
+with an error.
+
+We recommend iterating over existing collections where possible, rather than
+creating ranges. However, creating small numerical sequences can sometimes
+be useful when combined with other collections in collection-manipulation
+functions or `for` expressions.
+
+## Examples
+
+```shell-session
+> range(3)
+[
+ 0,
+ 1,
+ 2,
+]
+
+> range(1, 4)
+[
+ 1,
+ 2,
+ 3,
+]
+
+> range(1, 8, 2)
+[
+ 1,
+ 3,
+ 5,
+ 7,
+]
+
+> range(1, 4, 0.5)
+[
+ 1,
+ 1.5,
+ 2,
+ 2.5,
+ 3,
+ 3.5,
+]
+
+> range(4, 1)
+[
+ 4,
+ 3,
+ 2,
+]
+
+> range(10, 5, -2)
+[
+ 10,
+ 8,
+ 6,
+]
+```
+
+The `range` function is primarily useful when working with other collections
+to produce a certain number of instances of something. For example:
+
+```hcl
+variable "name_counts" {
+ type = map(number)
+ default = {
+ "foo" = 2
+ "bar" = 4
+ }
+}
+
+locals {
+ expanded_names = {
+ for name, count in var.name_counts : name => [
+ for i in range(count) : format("%s%02d", name, i)
+ ]
+ }
+}
+
+output "expanded_names" {
+ value = local.expanded_names
+}
+
+# Produces the following expanded_names value when run with the default
+# "name_counts":
+#
+# {
+# "bar" = [
+# "bar00",
+# "bar01",
+# "bar02",
+# "bar03",
+# ]
+# "foo" = [
+# "foo00",
+# "foo01",
+# ]
+# }
+```
diff --git a/v1.9.4/website/content/docs/templates/hcl_templates/functions/collection/reverse.mdx b/v1.9.4/website/content/docs/templates/hcl_templates/functions/collection/reverse.mdx
new file mode 100644
index 0000000..743a97a
--- /dev/null
+++ b/v1.9.4/website/content/docs/templates/hcl_templates/functions/collection/reverse.mdx
@@ -0,0 +1,24 @@
+---
+page_title: reverse - Functions - Configuration Language
+description: The reverse function reverses a sequence.
+---
+
+# `reverse` Function
+
+`reverse` takes a sequence and produces a new sequence of the same length
+with all of the same elements as the given sequence but in reverse order.
+
+## Examples
+
+```shell-session
+> reverse([1, 2, 3])
+[
+ 3,
+ 2,
+ 1,
+]
+```
+
+## Related Functions
+
+- [`strrev`](/packer/docs/templates/hcl_templates/functions/string/strrev) reverses a string.
diff --git a/v1.9.4/website/content/docs/templates/hcl_templates/functions/collection/setintersection.mdx b/v1.9.4/website/content/docs/templates/hcl_templates/functions/collection/setintersection.mdx
new file mode 100644
index 0000000..924b9a8
--- /dev/null
+++ b/v1.9.4/website/content/docs/templates/hcl_templates/functions/collection/setintersection.mdx
@@ -0,0 +1,38 @@
+---
+page_title: setintersection - Functions - Configuration Language
+description: |-
+ The setintersection function takes multiple sets and produces a single set
+ containing only the elements that all of the given sets have in common.
+---
+
+# `setintersection` Function
+
+The `setintersection` function takes multiple sets and produces a single set
+containing only the elements that all of the given sets have in common.
+In other words, it computes the
+[intersection](<https://en.wikipedia.org/wiki/Intersection_(set_theory)>) of the sets.
+
+```hcl
+setintersection(sets...)
+```
+
+## Examples
+
+```shell-session
+> setintersection(["a", "b"], ["b", "c"], ["b", "d"])
+[
+ "b",
+]
+```
+
+The given arguments are converted to sets, so the result is also a set and
+the ordering of the given elements is not preserved.
+
+## Related Functions
+
+- [`contains`](/packer/docs/templates/hcl_templates/functions/collection/contains) tests whether a given list or set contains
+ a given element value.
+- [`setproduct`](/packer/docs/templates/hcl_templates/functions/collection/setproduct) computes the _Cartesian product_ of multiple
+ sets.
+- [`setunion`](/packer/docs/templates/hcl_templates/functions/collection/setunion) computes the _union_ of
+ multiple sets.
diff --git a/v1.9.4/website/content/docs/templates/hcl_templates/functions/collection/setproduct.mdx b/v1.9.4/website/content/docs/templates/hcl_templates/functions/collection/setproduct.mdx
new file mode 100644
index 0000000..d9425f1
--- /dev/null
+++ b/v1.9.4/website/content/docs/templates/hcl_templates/functions/collection/setproduct.mdx
@@ -0,0 +1,222 @@
+---
+page_title: setproduct - Functions - Configuration Language
+description: |-
+ The setproduct function finds all of the possible combinations of elements
+ from all of the given sets by computing the cartesian product.
+---
+
+# `setproduct` Function
+
+The `setproduct` function finds all of the possible combinations of elements
+from all of the given sets by computing the
+[Cartesian product](https://en.wikipedia.org/wiki/Cartesian_product).
+
+```hcl
+setproduct(sets...)
+```
+
+This function is particularly useful for finding the exhaustive set of all
+combinations of members of multiple sets, such as per-application-per-environment
+resources.
+
+```shell-session
+> setproduct(["development", "staging", "production"], ["app1", "app2"])
+[
+ [
+ "development",
+ "app1",
+ ],
+ [
+ "development",
+ "app2",
+ ],
+ [
+ "staging",
+ "app1",
+ ],
+ [
+ "staging",
+ "app2",
+ ],
+ [
+ "production",
+ "app1",
+ ],
+ [
+ "production",
+ "app2",
+ ],
+]
+```
+
+You must past at least two arguments to this function.
+
+Although defined primarily for sets, this function can also work with lists.
+If all of the given arguments are lists then the result is a list, preserving
+the ordering of the given lists. Otherwise the result is a set. In either case,
+the result's element type is a list of values corresponding to each given
+argument in turn.
+
+## Examples
+
+There is an example of the common usage of this function above. There are some
+other situations that are less common when hand-writing but may arise in
+reusable folder situations.
+
+If any of the arguments is empty then the result is always empty itself,
+similar to how multiplying any number by zero gives zero:
+
+```shell-session
+> setproduct(["development", "staging", "production"], [])
+[]
+```
+
+Similarly, if all of the arguments have only one element then the result has
+only one element, which is the first element of each argument:
+
+```shell-session
+> setproduct(["a"], ["b"])
+[
+ [
+ "a",
+ "b",
+ ],
+]
+```
+
+Each argument must have a consistent type for all of its elements. If not,
+Packer will attempt to convert to the most general type, or produce an
+error if such a conversion is impossible. For example, mixing both strings and
+numbers results in the numbers being converted to strings so that the result
+elements all have a consistent type:
+
+```shell-session
+> setproduct(["staging", "production"], ["a", 2])
+[
+ [
+ "staging",
+ "a",
+ ],
+ [
+ "staging",
+ "2",
+ ],
+ [
+ "production",
+ "a",
+ ],
+ [
+ "production",
+ "2",
+ ],
+]
+```
+
+## Finding combinations for `for_each`
+
+The
+[resource `for_each`](/terraform/docs/configuration/resources#for_each-multiple-resource-instances-defined-by-a-map-or-set-of-strings)
+and
+[`dynamic` block](/packer/docs/templates/hcl_templates/expressions/#dynamic-blocks)
+language features both require a collection value that has one element for
+each repetition.
+
+Sometimes your input data comes in separate values that cannot be directly
+used in a `for_each` argument, and `setproduct` can be a useful helper function
+for the situation where you want to find all unique combinations of elements in
+a number of different collections.
+
+For example, consider a folder that declares variables like the following:
+
+```hcl
+variable "networks" {
+ type = map(object({
+ base_cidr_block = string
+ }))
+}
+
+variable "subnets" {
+ type = map(object({
+ number = number
+ }))
+}
+```
+
+If the goal is to create each of the defined subnets per each of the defined
+networks, creating the top-level networks can directly use `var.networks`
+because it's already in a form where the resulting instances match one-to-one
+with map elements:
+
+```hcl
+resource "aws_vpc" "example" {
+ for_each = var.networks
+
+ cidr_block = each.value.base_cidr_block
+}
+```
+
+However, in order to declare all of the _subnets_ with a single `resource`
+block, we must first produce a collection whose elements represent all of
+the combinations of networks and subnets, so that each element itself
+represents a subnet:
+
+```hcl
+locals {
+ # setproduct works with sets and lists, but our variables are both maps
+ # so we'll need to convert them first.
+ networks = [
+ for key, network in var.networks : {
+ key = key
+ cidr_block = network.cidr_block
+ }
+ ]
+ subnets = [
+ for key, subnet in var.subnets : {
+ key = key
+ number = subnet.number
+ }
+ ]
+
+ network_subnets = [
+ # in pair, element zero is a network and element one is a subnet,
+ # in all unique combinations.
+ for pair in setproduct(local.networks, local.subnets) : {
+ network_key = pair[0].key
+ subnet_key = pair[1].key
+ network_id = aws_vpc.example[pair[0].key].id
+
+ # The cidr_block is derived from the corresponding network. See the
+ # cidrsubnet function for more information on how this calculation works.
+ cidr_block = cidrsubnet(pair[0].cidr_block, 4, pair[1].number)
+ }
+ ]
+}
+
+resource "aws_subnet" "example" {
+ # local.network_subnets is a list, so we must now project it into a map
+ # where each key is unique. We'll combine the network and subnet keys to
+ # produce a single unique key per instance.
+ for_each = {
+ for subnet in local.network_subnets : "${subnet.network_key}.${subnet.subnet_key}" => subnet
+ }
+
+ vpc_id = each.value.network_id
+ availability_zone = each.value.subnet_key
+ cidr_block = each.value_cidr_block
+}
+```
+
+The above results in one subnet instance per combination of network and subnet
+elements in the input variables.
+
+## Related Functions
+
+- [`contains`](/packer/docs/templates/hcl_templates/functions/collection/contains) tests whether a given list or set contains
+ a given element value.
+- [`flatten`](/packer/docs/templates/hcl_templates/functions/collection/flatten) is useful for flattening hierarchical data
+ into a single list, for situations where the relationships between two
+ object types are defined explicitly.
+- [`setintersection`](/packer/docs/templates/hcl_templates/functions/collection/setintersection) computes the _intersection_ of
+ multiple sets.
+- [`setunion`](/packer/docs/templates/hcl_templates/functions/collection/setunion) computes the _union_ of multiple
+ sets.
diff --git a/v1.9.4/website/content/docs/templates/hcl_templates/functions/collection/setunion.mdx b/v1.9.4/website/content/docs/templates/hcl_templates/functions/collection/setunion.mdx
new file mode 100644
index 0000000..a78e2d4
--- /dev/null
+++ b/v1.9.4/website/content/docs/templates/hcl_templates/functions/collection/setunion.mdx
@@ -0,0 +1,41 @@
+---
+page_title: setunion - Functions - Configuration Language
+description: |-
+ The setunion function takes multiple sets and produces a single set
+ containing the elements from all of the given sets.
+---
+
+# `setunion` Function
+
+The `setunion` function takes multiple sets and produces a single set
+containing the elements from all of the given sets. In other words, it
+computes the [union](<https://en.wikipedia.org/wiki/Union_(set_theory)>) of
+the sets.
+
+```hcl
+setunion(sets...)
+```
+
+## Examples
+
+```shell-session
+> setunion(["a", "b"], ["b", "c"], ["d"])
+[
+ "d",
+ "b",
+ "c",
+ "a",
+]
+```
+
+The given arguments are converted to sets, so the result is also a set and
+the ordering of the given elements is not preserved.
+
+## Related Functions
+
+- [`contains`](/packer/docs/templates/hcl_templates/functions/collection/contains) tests whether a given list or set contains
+ a given element value.
+- [`setintersection`](/packer/docs/templates/hcl_templates/functions/collection/setintersection) computes the _intersection_ of
+ multiple sets.
+- [`setproduct`](/packer/docs/templates/hcl_templates/functions/collection/setproduct) computes the _Cartesian product_ of multiple
+ sets.
diff --git a/v1.9.4/website/content/docs/templates/hcl_templates/functions/collection/slice.mdx b/v1.9.4/website/content/docs/templates/hcl_templates/functions/collection/slice.mdx
new file mode 100644
index 0000000..f92ebc2
--- /dev/null
+++ b/v1.9.4/website/content/docs/templates/hcl_templates/functions/collection/slice.mdx
@@ -0,0 +1,31 @@
+---
+page_title: slice - Functions - Configuration Language
+description: The slice function extracts some consecutive elements from within a list.
+---
+
+# `slice` Function
+
+`slice` extracts some consecutive elements from within a list.
+
+```hcl
+slice(list, startindex, endindex)
+```
+
+`startindex` is inclusive, while `endindex` is exclusive. This function returns
+an error if either index is outside the bounds of valid indices for the given
+list.
+
+## Examples
+
+```shell-session
+> slice(["a", "b", "c", "d"], 1, 3)
+[
+ "b",
+ "c",
+]
+```
+
+## Related Functions
+
+- [`substr`](/packer/docs/templates/hcl_templates/functions/string/substr) performs a similar function for characters in a
+ string, although it uses a length instead of an end index.
diff --git a/v1.9.4/website/content/docs/templates/hcl_templates/functions/collection/sort.mdx b/v1.9.4/website/content/docs/templates/hcl_templates/functions/collection/sort.mdx
new file mode 100644
index 0000000..edc3dd9
--- /dev/null
+++ b/v1.9.4/website/content/docs/templates/hcl_templates/functions/collection/sort.mdx
@@ -0,0 +1,26 @@
+---
+page_title: sort - Functions - Configuration Language
+description: |-
+ The sort function takes a list of strings and returns a new list with those
+ strings sorted lexicographically.
+---
+
+# `sort` Function
+
+`sort` takes a list of strings and returns a new list with those strings
+sorted lexicographically.
+
+The sort is in terms of Unicode codepoints, with higher codepoints appearing
+after lower ones in the result.
+
+## Examples
+
+```shell-session
+> sort(["e", "d", "a", "x"])
+[
+ "a",
+ "d",
+ "e",
+ "x",
+]
+```
diff --git a/v1.9.4/website/content/docs/templates/hcl_templates/functions/collection/values.mdx b/v1.9.4/website/content/docs/templates/hcl_templates/functions/collection/values.mdx
new file mode 100644
index 0000000..0fced24
--- /dev/null
+++ b/v1.9.4/website/content/docs/templates/hcl_templates/functions/collection/values.mdx
@@ -0,0 +1,28 @@
+---
+page_title: values - Functions - Configuration Language
+description: The values function returns a list of the element values in a given map.
+---
+
+# `values` Function
+
+`values` takes a map and returns a list containing the values of the elements
+in that map.
+
+The values are returned in lexicographical order by their corresponding _keys_,
+so the values will be returned in the same order as their keys would be
+returned from [`keys`](/packer/docs/templates/hcl_templates/functions/collection/keys).
+
+## Examples
+
+```shell-session
+> values({a=3, c=2, d=1})
+[
+ 3,
+ 2,
+ 1,
+]
+```
+
+## Related Functions
+
+- [`keys`](/packer/docs/templates/hcl_templates/functions/collection/keys) returns a list of the _keys_ from a map.
diff --git a/v1.9.4/website/content/docs/templates/hcl_templates/functions/collection/zipmap.mdx b/v1.9.4/website/content/docs/templates/hcl_templates/functions/collection/zipmap.mdx
new file mode 100644
index 0000000..fbdcb6a
--- /dev/null
+++ b/v1.9.4/website/content/docs/templates/hcl_templates/functions/collection/zipmap.mdx
@@ -0,0 +1,33 @@
+---
+page_title: zipmap - Functions - Configuration Language
+description: |-
+ The zipmap function constructs a map from a list of keys and a corresponding
+ list of values.
+---
+
+# `zipmap` Function
+
+`zipmap` constructs a map from a list of keys and a corresponding list of
+values.
+
+```hcl
+zipmap(keyslist, valueslist)
+```
+
+Both `keyslist` and `valueslist` must be of the same length. `keyslist` must
+be a list of strings, while `valueslist` can be a list of any type.
+
+Each pair of elements with the same index from the two lists will be used
+as the key and value of an element in the resulting map. If the same value
+appears multiple times in `keyslist` then the value with the highest index
+is used in the resulting map.
+
+## Examples
+
+```shell-session
+> zipmap(["a", "b"], [1, 2])
+{
+ "a" = 1,
+ "b" = 2,
+}
+```
diff --git a/v1.9.4/website/content/docs/templates/hcl_templates/functions/contextual/aws_secretsmanager.mdx b/v1.9.4/website/content/docs/templates/hcl_templates/functions/contextual/aws_secretsmanager.mdx
new file mode 100644
index 0000000..edc0905
--- /dev/null
+++ b/v1.9.4/website/content/docs/templates/hcl_templates/functions/contextual/aws_secretsmanager.mdx
@@ -0,0 +1,91 @@
+---
+page_title: aws_secretsmanager - Functions - Configuration Language
+description: >-
+ The aws_secretsmanager function retrieves secrets from Amazon secretsmanager
+ stores.
+---
+
+# `aws_secretsmanager_key` Function
+
+Secrets can be read from the [AWS Secrets
+Manager](https://aws.amazon.com/secrets-manager/) and used within your template
+as locals.
+
+~> Note: Support for AWS secrets will always obtain the latest version of a secret, essentially
+AWSCURRENT. Support for previous versions of a secret is not supported.
+
+```hcl
+aws_secretsmanager(name, key)
+```
+
+When key is not set (`null` or empty: `""`) then `aws_secretsmanager` returns
+the first secret key stored in secret `name`.
+
+You can either use this function in a `locals` block or directly inline where
+you want to use the value.
+
+```hcl
+locals {
+ secret = aws_secretsmanager("my_secret", null)
+}
+
+source "null" "first-example" {
+ communicator = "none"
+}
+
+build {
+ name = "my-build-name"
+ sources = ["null.first-example"]
+
+ provisioner "shell-local" {
+ environment_vars = ["TESTVAR=${build.PackerRunUUID}"]
+ inline = ["echo my_secret is '${local.secret}'",
+ "echo my_secret using an inline call is '${aws_secretsmanager("my_secret", null)}'."]
+ }
+}
+```
+
+This will load the key stored behind `my_secret` from aws secrets manager.
+
+The retrieval of single key secrets or plaintext secrets can be obtained by specifying (`null` or empty: `""`) as the `key`.
+
+When obtaining secrets that have multiple keys you can set `key` to the specific key you would like
+to fetch. For example, given the following secret with two keys if `key` is set to "shell" `aws_secretsmanager` will
+return only its value.
+
+```json
+{
+ "test": "kitchen",
+ "shell": "powershell"
+}
+```
+
+```hcl
+locals {
+ secret = aws_secretsmanager("multikey/secret", "shell")
+}
+
+source "null" "first-example" {
+ communicator = "none"
+}
+
+build {
+ name = "my-build-name"
+ sources = ["null.first-example"]
+
+ provisioner "shell-local" {
+ environment_vars = ["TESTVAR=${build.PackerRunUUID}"]
+ inline = ["echo my_secret is '${local.secret}'"]
+ }
+}
+```
+
+This will load the value `"powershell"` stored in the key `"shell"` behind `multikey/secret`.
+
+In order to use this function you have to configure valid AWS credentials using
+one of the following methods:
+
+- [Environment Variables](https://docs.aws.amazon.com/cli/latest/userguide/cli-configure-envvars.html)
+- [CLI Configuration Files](https://docs.aws.amazon.com/cli/latest/userguide/cli-configure-files.html)
+- [Container Credentials](https://docs.aws.amazon.com/AmazonECS/latest/developerguide/task-iam-roles.html)
+- [Instance Profile Credentials](https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/iam-roles-for-amazon-ec2.html)
diff --git a/v1.9.4/website/content/docs/templates/hcl_templates/functions/contextual/consul.mdx b/v1.9.4/website/content/docs/templates/hcl_templates/functions/contextual/consul.mdx
new file mode 100644
index 0000000..da66b1b
--- /dev/null
+++ b/v1.9.4/website/content/docs/templates/hcl_templates/functions/contextual/consul.mdx
@@ -0,0 +1,39 @@
+---
+page_title: consul - Functions - Configuration Language
+description: The consul function retrieves secrets from HashiCorp consul KV stores.
+---
+
+# `consul_key` Function
+
+[Consul](https://www.consul.io/) keys can be used within your template using the
+`consul_key` function.
+
+You can either use this function in a locals block or directly inline where you
+want to use the value.
+
+```hcl
+locals {
+ my_version = "${consul_key("myservice/version")}"
+}
+
+source "null" "first-example" {
+ communicator = "none"
+}
+
+build {
+ name = "my-build-name"
+ sources = ["null.first-example"]
+
+ provisioner "shell-local" {
+ environment_vars = ["TESTVAR=${build.PackerRunUUID}"]
+ inline = ["echo my_version is '${local.my_version}'",
+ "echo version is '${consul_key("myservice/version")}'."]
+ }
+}
+```
+
+This will load the key stored at the path `myservice/version` from consul.
+
+The configuration for consul (address, tokens, ...) must be specified as
+environment variables, as specified in the
+[Documentation](/consul/docs/commands#environment-variables).
diff --git a/v1.9.4/website/content/docs/templates/hcl_templates/functions/contextual/env.mdx b/v1.9.4/website/content/docs/templates/hcl_templates/functions/contextual/env.mdx
new file mode 100644
index 0000000..a7e2351
--- /dev/null
+++ b/v1.9.4/website/content/docs/templates/hcl_templates/functions/contextual/env.mdx
@@ -0,0 +1,49 @@
+---
+page_title: env - Functions - Configuration Language
+description: The env function retrieves environment values for input variables.
+---
+
+# `env` Function
+
+```hcl
+variable "aws_region" {
+ default = env("AWS_DEFAULT_REGION")
+}
+```
+
+`env` allows you to get the value for an environment variable inside input
+variables _only_. This is the only function that is callable from a variable
+block and it can only be used in the default input. `env` cannot be called from
+other places.
+
+In the previous example, the value of `aws_region` will be what's stored in the
+`AWS_DEFAULT_REGION` env var, unless aws_region is also set in a [manner that takes
+precedence](/packer/docs/templates/hcl_templates/variables#variable-definition-precedence).
+
+-> **Why can't I use environment variables elsewhere?** User variables are the
+single source of configurable input. We felt that having environment variables
+used _anywhere_ in a configuration would confuse the user about the possible inputs
+to a template. By allowing environment variables only within default values for
+input variables, input variables remain as the single source of input to a
+template that a user can easily discover using `packer inspect`.
+
+When the environment variable is not set at all -- not even with the empty
+string -- the value returned by `env` will be an an empty string. It will still
+be possible to set it using other means but you could use [custom validation
+rules](/packer/docs/templates/hcl_templates/variables#custom-validation-rules) to error in that case
+to make sure it is set, for example:
+
+```hcl
+variable "aws_region" {
+ default = env("AWS_DEFAULT_REGION")
+
+ validation {
+ condition = length(var.aws_region) > 0
+ error_message = <<EOF
+The aws_region var is not set: make sure to at least set the AWS_DEFAULT_REGION env var.
+To fix this you could also set the aws_region variable from the arguments, for example:
+$ packer build -var=aws_region=us-something-1...
+EOF
+ }
+}
+```
diff --git a/v1.9.4/website/content/docs/templates/hcl_templates/functions/contextual/vault.mdx b/v1.9.4/website/content/docs/templates/hcl_templates/functions/contextual/vault.mdx
new file mode 100644
index 0000000..8136a10
--- /dev/null
+++ b/v1.9.4/website/content/docs/templates/hcl_templates/functions/contextual/vault.mdx
@@ -0,0 +1,92 @@
+---
+page_title: vault - Functions - Configuration Language
+description: The vault function retrieves secrets from HashiCorp Vault KV stores.
+---
+
+# `vault` Function
+
+Secrets can be read from [Vault](https://www.vaultproject.io/) and used within
+your template as user variables. the `vault` function is available _only_
+within the default value of a user variable, allowing you to default a user
+variable to a vault secret.
+
+An example of using a v2 kv engine:
+
+If you store a value in vault using `vault kv put secret/hello foo=world`, you
+can access it using the following:
+
+```hcl
+locals {
+ foo = vault("/secret/data/hello", "foo")
+}
+```
+
+which will assign `local.foo` with the value "world"
+
+An example of using a v1 kv engine:
+
+If you store a value in vault using:
+
+ vault secrets enable -version=1 -path=secrets kv
+ vault kv put secrets/hello foo=world
+
+You can access it using the following:
+
+```hcl
+locals {
+ foo = vault("secrets/hello", "foo")
+}
+```
+
+This example accesses the Vault path `secret/foo` and returns the value
+stored at the key `foo`, storing it as the local variable `local.foo`.
+
+If the Vault secret contains a highly sensitive value the `local` block, not to be confused with
+the `locals` block, can be used to mark the value as sensitive.
+
+```hcl
+local "foo" {
+ expression = vault("secrets/hello", "foo")
+ sensitive = true
+}
+```
+
+The `local` block example accesses the Vault path `secrets/foo` and returns the value
+stored at the key `foo`, storing it as the local variable `local.foo`. However, the output of
+the newly stored local variable will be filtered from the Packer build output, and replaced
+with the value `<sensitive>`. See [Local Values](/packer/docs/templates/hcl_templates/locals) for more details.
+
+
+## Usage
+
+In order for the Vault function to work, you must set the environment variables `VAULT_TOKEN`
+and `VAULT_ADDR` to valid values.
+
+-> **NOTE:** HCL functions can be used in local variable definitions or inline
+with a provisioner/post-processor. They cannot be used in global variable definitions.
+
+The api tool we use allows for more custom configuration of the Vault client via
+environment variables.
+
+The full list of available environment variables is:
+
+```text
+"VAULT_ADDR"
+"VAULT_AGENT_ADDR"
+"VAULT_CACERT"
+"VAULT_CAPATH"
+"VAULT_CLIENT_CERT"
+"VAULT_CLIENT_KEY"
+"VAULT_CLIENT_TIMEOUT"
+"VAULT_SKIP_VERIFY"
+"VAULT_NAMESPACE"
+"VAULT_TLS_SERVER_NAME"
+"VAULT_WRAP_TTL"
+"VAULT_MAX_RETRIES"
+"VAULT_TOKEN"
+"VAULT_MFA"
+"VAULT_RATE_LIMIT"
+```
+
+and detailed documentation for usage of each of those variables can be found
+[here](/vault/docs/commands#environment-variables).
diff --git a/v1.9.4/website/content/docs/templates/hcl_templates/functions/conversion/can.mdx b/v1.9.4/website/content/docs/templates/hcl_templates/functions/conversion/can.mdx
new file mode 100644
index 0000000..4272cbb
--- /dev/null
+++ b/v1.9.4/website/content/docs/templates/hcl_templates/functions/conversion/can.mdx
@@ -0,0 +1,57 @@
+---
+page_title: can - Functions - Configuration Language
+description: |-
+ The can function tries to evaluate an expression given as an argument and
+ indicates whether the evaluation succeeded.
+---
+
+# `can` Function
+
+`can` evaluates the given expression and returns a boolean value indicating
+whether the expression produced a result without any errors.
+
+This is a special function that is able to catch errors produced when evaluating
+its argument. For most situations where you could use `can` it's better to use
+[`try`](/packer/docs/templates/hcl_templates/functions/conversion/try) instead, because it allows for more concise definition of
+fallback values for failing expressions.
+
+The `can` function can only catch and handle _dynamic_ errors resulting from
+access to data that isn't known until runtime. It will not catch errors
+relating to expressions that can be proven to be invalid for any input, such
+as a malformed resource reference.
+
+~> **Warning:** The `can` function is intended only for simple tests in
+variable validation rules. Although it can technically accept any sort of
+expression and be used elsewhere in the configuration, we recommend against
+using it in other contexts. For error handling elsewhere in the configuration,
+prefer to use [`try`](/packer/docs/templates/hcl_templates/functions/conversion/try).
+
+## Examples
+
+```shell-session
+> local.foo
+{
+ "bar" = "baz"
+}
+> can(local.foo.bar)
+true
+> can(local.foo.boop)
+false
+```
+
+The `can` function will _not_ catch errors relating to constructs that are
+provably invalid even before dynamic expression evaluation, such as a malformed
+reference or a reference to a top-level object that has not been declared:
+
+```shell-session
+> can(local.nonexist)
+
+Error: Reference to undeclared local value
+
+A local value with the name "nonexist" has not been declared.
+```
+
+## Related Functions
+
+- [`try`](/packer/docs/templates/hcl_templates/functions/conversion/try), which tries evaluating a sequence of expressions and
+ returns the result of the first one that succeeds.
diff --git a/v1.9.4/website/content/docs/templates/hcl_templates/functions/conversion/convert.mdx b/v1.9.4/website/content/docs/templates/hcl_templates/functions/conversion/convert.mdx
new file mode 100644
index 0000000..5cb90d1
--- /dev/null
+++ b/v1.9.4/website/content/docs/templates/hcl_templates/functions/conversion/convert.mdx
@@ -0,0 +1,52 @@
+---
+page_title: convert - Functions - Configuration Language
+description: 'The convert function converts a value or an expression to a given type. '
+---
+
+# `convert` Function
+
+`convert` converts a value or an expression to a given type.
+
+Explicit type conversions are rarely necessary in HCL because it will convert
+types automatically where required. Use the explicit type conversion functions
+only to normalize types returned in outputs.
+
+Only numbers and strings containing decimal representations of numbers can be
+converted to number. All other values will produce an error.
+
+Only boolean values and the exact strings "true" and "false" can be converted
+to boolean. All other values will produce an error.
+
+Only the primitive types (string, number, and bool) can be converted to string.
+All other values will produce an error.
+
+`convert(value, type_constraint)`
+
+## Examples
+
+```shell-session
+> convert(3, string)
+"3"
+> convert("3", number)
+3
+> convert("false", bool)
+false
+> convert(false, string)
+"false"
+> convert(["a", "b", 3], list)
+[
+ "a",
+ "b",
+ "3",
+]
+> convert(["c", "b", "b"], set)
+[
+ "b",
+ "c",
+]
+> convert({"a" = "foo", "b" = true}, map)
+{
+ "a" = "foo"
+ "b" = "true"
+}
+```
diff --git a/v1.9.4/website/content/docs/templates/hcl_templates/functions/conversion/try.mdx b/v1.9.4/website/content/docs/templates/hcl_templates/functions/conversion/try.mdx
new file mode 100644
index 0000000..a34e6e2
--- /dev/null
+++ b/v1.9.4/website/content/docs/templates/hcl_templates/functions/conversion/try.mdx
@@ -0,0 +1,111 @@
+---
+page_title: try - Functions - Configuration Language
+description: |-
+ The try function tries to evaluate a sequence of expressions given as
+ arguments and returns the result of the first one that does not produce
+ any errors.
+---
+
+# `try` Function
+
+`try` evaluates all of its argument expressions in turn and returns the result
+of the first one that does not produce any errors.
+
+This is a special function that is able to catch errors produced when evaluating
+its arguments, which is particularly useful when working with complex data
+structures whose shape is not well-known at implementation time.
+
+For example, if some data is retrieved from an external system in JSON or YAML
+format and then decoded, the result may have attributes that are not guaranteed
+to be set. We can use `try` to produce a normalized data structure which has
+a predictable type that can therefore be used more conveniently elsewhere in
+the configuration:
+
+```hcl
+locals {
+ raw_value = yamldecode("${path.folder}/example.yaml")
+ normalized_value = {
+ name = tostring(try(local.raw_value.name, null))
+ groups = try(local.raw_value.groups, [])
+ }
+}
+```
+
+With the above local value expressions, configuration elsewhere in the folder
+can refer to `local.normalized_value` attributes without the need to repeatedly
+check for and handle absent attributes that would otherwise produce errors.
+
+We can also use `try` to deal with situations where a value might be provided
+in two different forms, allowing us to normalize to the most general form:
+
+```hcl
+variable "example" {
+ type = any
+}
+
+locals {
+ example = try(
+ [tostring(var.example)],
+ tolist(var.example),
+ )
+}
+```
+
+The above permits `var.example` to be either a list or a single string. If it's
+a single string then it'll be normalized to a single-element list containing
+that string, again allowing expressions elsewhere in the configuration to just
+assume that `local.example` is always a list.
+
+This second example contains two expressions that can both potentially fail.
+For example, if `var.example` were set to `{}` then it could be converted to
+neither a string nor a list. If `try` exhausts all of the given expressions
+without any succeeding, it will return an error describing all of the problems
+it encountered.
+
+We strongly suggest using `try` only in special local values whose expressions
+perform normalization, so that the error handling is confined to a single
+location in the folder and the rest of the folder can just use straightforward
+references to the normalized structure and thus be more readable for future
+maintainers.
+
+The `try` function can only catch and handle _dynamic_ errors resulting from
+access to data that isn't known until runtime. It will not catch errors
+relating to expressions that can be proven to be invalid for any input, such
+as a malformed resource reference.
+
+~> **Warning:** The `try` function is intended only for concise testing of the
+presence of and types of object attributes. Although it can technically accept
+any sort of expression, we recommend using it only with simple attribute
+references and type conversion functions as shown in the examples above.
+Overuse of `try` to suppress errors will lead to a configuration that is hard
+to understand and maintain.
+
+## Examples
+
+```shell-session
+> local.foo
+{
+ "bar" = "baz"
+}
+> try(local.foo.bar, "fallback")
+baz
+> try(local.foo.boop, "fallback")
+fallback
+```
+
+The `try` function will _not_ catch errors relating to constructs that are
+provably invalid even before dynamic expression evaluation, such as a malformed
+reference or a reference to a top-level object that has not been declared:
+
+```shell-session
+> try(local.nonexist, "fallback")
+
+Error: Reference to undeclared local value
+
+A local value with the name "nonexist" has not been declared.
+```
+
+## Related Functions
+
+- [`can`](/packer/docs/templates/hcl_templates/functions/conversion/can), which tries evaluating an expression and returns a
+ boolean value indicating whether it succeeded.
diff --git a/v1.9.4/website/content/docs/templates/hcl_templates/functions/crypto/bcrypt.mdx b/v1.9.4/website/content/docs/templates/hcl_templates/functions/crypto/bcrypt.mdx
new file mode 100644
index 0000000..c49779c
--- /dev/null
+++ b/v1.9.4/website/content/docs/templates/hcl_templates/functions/crypto/bcrypt.mdx
@@ -0,0 +1,36 @@
+---
+page_title: bcrypt - Functions - Configuration Language
+description: |-
+ The bcrypt function computes a hash of the given string using the Blowfish
+ cipher.
+---
+
+# `bcrypt` Function
+
+`bcrypt` computes a hash of the given string using the Blowfish cipher,
+returning a string in [the _Modular Crypt
+Format_](https://passlib.readthedocs.io/en/stable/modular_crypt_format.html)
+usually expected in the shadow password file on many Unix systems.
+
+```hcl
+bcrypt(string, cost)
+```
+
+The `cost` argument is optional and will default to 10 if unspecified.
+
+Since a bcrypt hash value includes a randomly selected salt, each call to this
+function will return a different value, even if the given string and cost are
+the same. Using this function directly with resource arguments will therefore
+cause spurious diffs. We recommend using this function only in `provisioner` or
+`post-processor` blocks, or in data resources whose results are only used in
+those blocks.
+
+The version prefix on the generated string (e.g. `$2a$`) may change in future
+versions of Packer.
+
+## Examples
+
+```shell-session
+> bcrypt("hello world")
+$2a$10$D5grTTzcsqyvAeIAnY/mYOIqliCoG7eAMX0/oFcuD.iErkksEbcAa
+```
diff --git a/v1.9.4/website/content/docs/templates/hcl_templates/functions/crypto/md5.mdx b/v1.9.4/website/content/docs/templates/hcl_templates/functions/crypto/md5.mdx
new file mode 100644
index 0000000..f777aa6
--- /dev/null
+++ b/v1.9.4/website/content/docs/templates/hcl_templates/functions/crypto/md5.mdx
@@ -0,0 +1,26 @@
+---
+page_title: md5 - Functions - Configuration Language
+description: |-
+ The md5 function computes the MD5 hash of a given string and encodes it
+ with hexadecimal digits.
+---
+
+# `md5` Function
+
+`md5` computes the MD5 hash of a given string and encodes it with
+hexadecimal digits.
+
+The given string is first encoded as UTF-8 and then the MD5 algorithm is applied
+as defined in [RFC 1321](https://tools.ietf.org/html/rfc1321). The raw hash is
+then encoded to lowercase hexadecimal digits before returning.
+
+Before using this function for anything security-sensitive, refer to
+[RFC 6151](https://tools.ietf.org/html/rfc6151) for updated security
+considerations applying to the MD5 algorithm.
+
+## Examples
+
+```shell-session
+> md5("hello world")
+5eb63bbbe01eeed093cb22bb8f5acdc3
+```
diff --git a/v1.9.4/website/content/docs/templates/hcl_templates/functions/crypto/rsadecrypt.mdx b/v1.9.4/website/content/docs/templates/hcl_templates/functions/crypto/rsadecrypt.mdx
new file mode 100644
index 0000000..59339c6
--- /dev/null
+++ b/v1.9.4/website/content/docs/templates/hcl_templates/functions/crypto/rsadecrypt.mdx
@@ -0,0 +1,31 @@
+---
+page_title: rsadecrypt - Functions - Configuration Language
+description: The rsadecrypt function decrypts an RSA-encrypted message.
+---
+
+# `rsadecrypt` Function
+
+`rsadecrypt` decrypts an RSA-encrypted ciphertext, returning the corresponding
+cleartext.
+
+```hcl
+rsadecrypt(ciphertext, privatekey)
+```
+
+`ciphertext` must be a base64-encoded representation of the ciphertext, using
+the PKCS #1 v1.5 padding scheme. Packer uses the "standard" Base64 alphabet
+as defined in [RFC 4648 section 4](https://tools.ietf.org/html/rfc4648#section-4).
+
+`privatekey` must be a PEM-encoded RSA private key that is not itself
+encrypted.
+
+Packer has no corresponding function for _encrypting_ a message. Use this
+function to decrypt ciphertexts returned by remote services using a keypair
+negotiated out-of-band.
+
+## Examples
+
+```shell-session
+> rsadecrypt(base64(file("${path.folder}/ciphertext")), file("privatekey.pem"))
+Hello, world!
+```
diff --git a/v1.9.4/website/content/docs/templates/hcl_templates/functions/crypto/sha1.mdx b/v1.9.4/website/content/docs/templates/hcl_templates/functions/crypto/sha1.mdx
new file mode 100644
index 0000000..a001654
--- /dev/null
+++ b/v1.9.4/website/content/docs/templates/hcl_templates/functions/crypto/sha1.mdx
@@ -0,0 +1,26 @@
+---
+page_title: sha1 - Functions - Configuration Language
+description: |-
+ The sha1 function computes the SHA1 hash of a given string and encodes it
+ with hexadecimal digits.
+---
+
+# `sha1` Function
+
+`sha1` computes the SHA1 hash of a given string and encodes it with
+hexadecimal digits.
+
+The given string is first encoded as UTF-8 and then the SHA1 algorithm is applied
+as defined in [RFC 3174](https://tools.ietf.org/html/rfc3174). The raw hash is
+then encoded to lowercase hexadecimal digits before returning.
+
+Collision attacks have been successfully performed against this hashing
+function. Before using this function for anything security-sensitive, review
+relevant literature to understand the security implications.
+
+## Examples
+
+```shell-session
+> sha1("hello world")
+2aae6c35c94fcfb415dbe95f408b9ce91ee846ed
+```
diff --git a/v1.9.4/website/content/docs/templates/hcl_templates/functions/crypto/sha256.mdx b/v1.9.4/website/content/docs/templates/hcl_templates/functions/crypto/sha256.mdx
new file mode 100644
index 0000000..06133db
--- /dev/null
+++ b/v1.9.4/website/content/docs/templates/hcl_templates/functions/crypto/sha256.mdx
@@ -0,0 +1,22 @@
+---
+page_title: sha256 - Functions - Configuration Language
+description: |-
+ The sha256 function computes the SHA256 hash of a given string and encodes it
+ with hexadecimal digits.
+---
+
+# `sha256` Function
+
+`sha256` computes the SHA256 hash of a given string and encodes it with
+hexadecimal digits.
+
+The given string is first encoded as UTF-8 and then the SHA256 algorithm is applied
+as defined in [RFC 4634](https://tools.ietf.org/html/rfc4634). The raw hash is
+then encoded to lowercase hexadecimal digits before returning.
+
+## Examples
+
+```shell-session
+> sha256("hello world")
+b94d27b9934d3e08a52e52d7da7dabfac484efe37a5380ee9088f7ace2efcde9
+```
diff --git a/v1.9.4/website/content/docs/templates/hcl_templates/functions/crypto/sha512.mdx b/v1.9.4/website/content/docs/templates/hcl_templates/functions/crypto/sha512.mdx
new file mode 100644
index 0000000..3d58ecf
--- /dev/null
+++ b/v1.9.4/website/content/docs/templates/hcl_templates/functions/crypto/sha512.mdx
@@ -0,0 +1,22 @@
+---
+page_title: sha512 - Functions - Configuration Language
+description: |-
+ The sha512 function computes the SHA512 hash of a given string and encodes it
+ with hexadecimal digits.
+---
+
+# `sha512` Function
+
+`sha512` computes the SHA512 hash of a given string and encodes it with
+hexadecimal digits.
+
+The given string is first encoded as UTF-8 and then the SHA512 algorithm is applied
+as defined in [RFC 4634](https://tools.ietf.org/html/rfc4634). The raw hash is
+then encoded to lowercase hexadecimal digits before returning.
+
+## Examples
+
+```shell-session
+> sha512("hello world")
+309ecc489c12d6eb4cc40f50c902f2b4d0ed77ee511a7c7a9bcd3ca86d4cd86f989dd35bc5ff499670da34255b45b0cfd830e81f605dcf7dc5542e93ae9cd76f
+```
diff --git a/v1.9.4/website/content/docs/templates/hcl_templates/functions/datetime/formatdate.mdx b/v1.9.4/website/content/docs/templates/hcl_templates/functions/datetime/formatdate.mdx
new file mode 100644
index 0000000..708b6a6
--- /dev/null
+++ b/v1.9.4/website/content/docs/templates/hcl_templates/functions/datetime/formatdate.mdx
@@ -0,0 +1,105 @@
+---
+page_title: formatdate - Functions - Configuration Language
+description: The formatdate function converts a timestamp into a different time format.
+---
+
+# `formatdate` Function
+
+`formatdate` converts a timestamp into a different time format.
+
+```hcl
+formatdate(spec, timestamp)
+```
+
+In Packer, timestamps are conventionally represented as strings using [RFC
+3339](https://tools.ietf.org/html/rfc3339) "Date and Time format" syntax.
+`formatdate` requires the `timestamp` argument to be a string conforming to
+this syntax.
+
+## Examples
+
+```shell-session
+> formatdate("DD MMM YYYY hh:mm ZZZ", "2018-01-02T23:12:01Z")
+02 Jan 2018 23:12 UTC
+> formatdate("EEEE, DD-MMM-YY hh:mm:ss ZZZ", "2018-01-02T23:12:01Z")
+Tuesday, 02-Jan-18 23:12:01 UTC
+> formatdate("EEE, DD MMM YYYY hh:mm:ss ZZZ", "2018-01-02T23:12:01-08:00")
+Tue, 02 Jan 2018 23:12:01 -0800
+> formatdate("MMM DD, YYYY", "2018-01-02T23:12:01Z")
+Jan 02, 2018
+> formatdate("HH:mmaa", "2018-01-02T23:12:01Z")
+11:12pm
+```
+
+## Specification Syntax
+
+The format specification is a string that includes formatting sequences from
+the following table. This function is intended for producing common
+_machine-oriented_ timestamp formats such as those defined in RFC822, RFC850,
+and RFC1123. It is not suitable for truly human-oriented date formatting
+because it is not locale-aware. In particular, it can produce month and day
+names only in English.
+
+The specification may contain the following sequences:
+
+| Sequence | Result |
+| -------- | ----------------------------------------------------------------------- |
+| `YYYY` | Four (or more) digit year, like "2006". |
+| `YY` | The year modulo 100, zero padded to at least two digits, like "06". |
+| `MMMM` | English month name unabbreviated, like "January". |
+| `MMM` | English month name abbreviated to three letters, like "Jan". |
+| `MM` | Month number zero-padded to two digits, like "01" for January. |
+| `M` | Month number with no padding, like "1" for January. |
+| `DD` | Day of month number zero-padded to two digits, like "02". |
+| `D` | Day of month number with no padding, like "2". |
+| `EEEE` | English day of week name unabbreviated, like "Monday". |
+| `EEE` | English day of week name abbreviated to three letters, like "Mon". |
+| `hh` | 24-hour number zero-padded to two digits, like "02". |
+| `h` | 24-hour number unpadded, like "2". |
+| `HH` | 12-hour number zero-padded to two digits, like "02". |
+| `H` | 12-hour number unpadded, like "2". |
+| `AA` | Hour AM/PM marker in uppercase, like "AM". |
+| `aa` | Hour AM/PM marker in lowercase, like "am". |
+| `mm` | Minute within hour zero-padded to two digits, like "05". |
+| `m` | Minute within hour unpadded, like "5". |
+| `ss` | Second within minute zero-padded to two digits, like "09". |
+| `s` | Second within minute, like "9". |
+| `ZZZZZ` | Timezone offset with colon separating hours and minutes, like "-08:00". |
+| `ZZZZ` | Timezone offset with just sign and digit, like "-0800". |
+| `ZZZ` | Like `ZZZZ` but with a special case "UTC" for UTC. |
+| `Z` | Like `ZZZZZ` but with a special case "Z" for UTC. |
+
+Any non-letter characters, such as punctuation, are reproduced verbatim in the
+output. To include literal letters in the format string, enclose them in single
+quotes `'`. To include a literal quote, escape it by doubling the quotes.
+
+```shell-session
+> formatdate("h'h'mm", "2018-01-02T23:12:01-08:00")
+23h12
+> formatdate("H 'o''clock'", "2018-01-02T23:12:01-08:00")
+11 o'clock
+```
+
+This format specification syntax is intended to make it easy for a reader
+to guess which format will result even if they are not experts on the syntax.
+Therefore there are no predefined shorthands for common formats, but format
+strings for various RFC-specified formats are given below to be copied into your
+configuration as needed:
+
+- [RFC 822](https://tools.ietf.org/html/rfc822#section-5) and
+ [RFC RFC 2822](https://tools.ietf.org/html/rfc2822#section-3.3):
+ `"DD MMM YYYY hh:mm ZZZ"`
+- [RFC 850](https://tools.ietf.org/html/rfc850#section-2.1.4):
+ `"EEEE, DD-MMM-YY hh:mm:ss ZZZ"`
+- [RFC 1123](https://tools.ietf.org/html/rfc1123#section-5.2.14):
+ `"EEE, DD MMM YYYY hh:mm:ss ZZZ"`
+- [RFC 3339](https://tools.ietf.org/html/rfc3339):
+ `"YYYY-MM-DD'T'hh:mm:ssZ"` (but this is also the input format, so such a
+ conversion is redundant.)
+
+## Related Functions
+
+- [`format`](/packer/docs/templates/hcl_templates/functions/string/format) is a more general formatting function for arbitrary
+ data.
+- [`timestamp`](/packer/docs/templates/hcl_templates/functions/datetime/timestamp) returns the current date and time in a format
+ suitable for input to `formatdate`.
diff --git a/v1.9.4/website/content/docs/templates/hcl_templates/functions/datetime/legacy_isotime.mdx b/v1.9.4/website/content/docs/templates/hcl_templates/functions/datetime/legacy_isotime.mdx
new file mode 100644
index 0000000..37217a5
--- /dev/null
+++ b/v1.9.4/website/content/docs/templates/hcl_templates/functions/datetime/legacy_isotime.mdx
@@ -0,0 +1,41 @@
+---
+page_title: legacy_isotime - Functions - Configuration Language
+description: |-
+ The legacy_isotime function returns a string representation of the current date
+ and time.
+---
+
+# `legacy_isotime` Function
+
+The `legacy_isotime` function returns the current date and time using the given format string.
+The format string follows Go's datetime formatting. See
+[isotime-function-format-reference](/packer/docs/templates/legacy_json_templates/engine#isotime-function-format-reference)
+for more details.
+
+This function has been provided to create backwards compatibility with
+Packer's legacy JSON templates. However, we recommend that you upgrade your
+HCL Packer template to use [`timestamp`](/packer/docs/templates/hcl_templates/functions/datetime/timestamp)
+and [`formatdate`](/packer/docs/templates/hcl_templates/functions/datetime/formatdate) together as soon as is convenient.
+
+-> **Note:** If you are using a large number of builders, provisioners
+or post-processors, the isotime may be slightly different for each one
+because it is from when the plugin is launched not the initial Packer
+process. In order to avoid this and make the timestamp consistent across all
+plugins, set it as a user variable and then access the user variable within
+your plugins.
+
+## Examples
+
+```shell-session
+> legacy_isotime("2006-01-02")
+2021-04-19
+```
+
+## Related Functions
+
+- [`format`](/packer/docs/templates/hcl_templates/functions/string/format) is a more general formatting function for arbitrary
+data.
+- [`timestamp`](/packer/docs/templates/hcl_templates/functions/datetime/timestamp) returns the current date and time in a format
+suitable for input to `formatdate`.
+- [`formatdate`](/packer/docs/templates/hcl_templates/functions/datetime/formatdate) can convert the resulting timestamp to
+ other date and time formats.
diff --git a/v1.9.4/website/content/docs/templates/hcl_templates/functions/datetime/legacy_strftime.mdx b/v1.9.4/website/content/docs/templates/hcl_templates/functions/datetime/legacy_strftime.mdx
new file mode 100644
index 0000000..c993315
--- /dev/null
+++ b/v1.9.4/website/content/docs/templates/hcl_templates/functions/datetime/legacy_strftime.mdx
@@ -0,0 +1,40 @@
+---
+page_title: legacy_strftime - Functions - Configuration Language
+description: |-
+ The legacy_strftime function returns a string representation of the current date
+ and time.
+---
+
+# `legacy_strftime` — UTC time, formated using the ISO C standard format
+
+The `legacy_strftime` function returns the current date and time using the given
+format string. The format string follows strftime's datetime formatting.
+
+This function has been provided to create backwards compatibility with Packer's
+legacy JSON templates. However, we recommend that you upgrade your HCL Packer
+template to use
+[`timestamp`](/packer/docs/templates/hcl_templates/functions/datetime/timestamp) and
+[`formatdate`](/packer/docs/templates/hcl_templates/functions/datetime/formatdate)
+together as soon as is convenient.
+
+-> **Note:** If you are using a large number of builders, provisioners or
+post-processors, the strftime may be slightly different for each one because it
+is from when the plugin is launched not the initial Packer process. In order to
+avoid this and make the timestamp consistent across all plugins, set it as a
+user variable and then access the user variable within your plugins.
+
+## Examples
+
+```shell-session
+> legacy_strftime("%Y-%m")
+2021-08
+```
+
+## Related Functions
+
+- [`format`](/packer/docs/templates/hcl_templates/functions/string/format) is a more general formatting function for arbitrary
+data.
+- [`timestamp`](/packer/docs/templates/hcl_templates/functions/datetime/timestamp) returns the current date and time in a format
+suitable for input to `formatdate`.
+- [`formatdate`](/packer/docs/templates/hcl_templates/functions/datetime/formatdate) can convert the resulting timestamp to
+ other date and time formats.
diff --git a/v1.9.4/website/content/docs/templates/hcl_templates/functions/datetime/timeadd.mdx b/v1.9.4/website/content/docs/templates/hcl_templates/functions/datetime/timeadd.mdx
new file mode 100644
index 0000000..0a19c56
--- /dev/null
+++ b/v1.9.4/website/content/docs/templates/hcl_templates/functions/datetime/timeadd.mdx
@@ -0,0 +1,40 @@
+---
+page_title: timeadd - Functions - Configuration Language
+description: |-
+ The timeadd function adds a duration to a timestamp, returning a new
+ timestamp.
+---
+
+# `timeadd` Function
+
+`timeadd` adds a duration to a timestamp, returning a new timestamp.
+
+```hcl
+timeadd(timestamp, duration)
+```
+
+In the Packer language, timestamps are conventionally represented as
+strings using [RFC 3339](https://tools.ietf.org/html/rfc3339)
+"Date and Time format" syntax. `timeadd` requires the `timestamp` argument
+to be a string conforming to this syntax.
+
+`duration` is a string representation of a time difference, consisting of
+sequences of number and unit pairs, like `"1.5h"` or `"1h30m"`. The accepted
+units are `"ns"`, `"us"` (or `"µs"`), `"ms"`, `"s"`, `"m"`, and `"h"`. The first
+number may be negative to indicate a negative duration, like `"-2h5m"`.
+
+The result is a string, also in RFC 3339 format, representing the result
+of adding the given direction to the given timestamp.
+
+-> **Breaking change note:** Packer previously let you decide your own "Date
+and Time format" syntax. With HCL2 and for parity with Terraform, Packer will
+be using the [RFC 3339](https://tools.ietf.org/html/rfc3339) "Date and Time
+format" syntax. As a string. [`formatdate`](/packer/docs/templates/hcl_templates/functions/datetime/formatdate) still allows you
+to format a date.
+
+## Examples
+
+```shell-session
+> timeadd("2017-11-22T00:00:00Z", "10m")
+2017-11-22T00:10:00Z
+```
diff --git a/v1.9.4/website/content/docs/templates/hcl_templates/functions/datetime/timestamp.mdx b/v1.9.4/website/content/docs/templates/hcl_templates/functions/datetime/timestamp.mdx
new file mode 100644
index 0000000..b27eb11
--- /dev/null
+++ b/v1.9.4/website/content/docs/templates/hcl_templates/functions/datetime/timestamp.mdx
@@ -0,0 +1,37 @@
+---
+page_title: timestamp - Functions - Configuration Language
+description: |-
+ The timestamp function returns a string representation of the current date
+ and time.
+---
+
+# `timestamp` Function
+
+`timestamp` returns the current date and time.
+
+In the Packer language, timestamps are conventionally represented as
+strings using [RFC 3339](https://tools.ietf.org/html/rfc3339)
+"Date and Time format" syntax, and so `timestamp` returns a string
+in this format.
+
+The result of this function will change every second, so using this function
+directly with resource attributes will cause a diff to be detected on every
+Packer run.
+
+-> **Breaking change note:** Packer previously let you decide your own "Date
+and Time format" syntax. With HCL2 and for parity with Terraform, Packer will
+be using the [RFC 3339](https://tools.ietf.org/html/rfc3339) "Date and Time
+format" syntax. As a string. [`formatdate`](/packer/docs/templates/hcl_templates/functions/datetime/formatdate) still allows you
+to format a date.
+
+## Examples
+
+```shell-session
+> timestamp()
+2018-05-13T07:44:12Z
+```
+
+## Related Functions
+
+- [`formatdate`](/packer/docs/templates/hcl_templates/functions/datetime/formatdate) can convert the resulting timestamp to
+ other date and time formats.
diff --git a/v1.9.4/website/content/docs/templates/hcl_templates/functions/encoding/base64decode.mdx b/v1.9.4/website/content/docs/templates/hcl_templates/functions/encoding/base64decode.mdx
new file mode 100644
index 0000000..8d91882
--- /dev/null
+++ b/v1.9.4/website/content/docs/templates/hcl_templates/functions/encoding/base64decode.mdx
@@ -0,0 +1,36 @@
+---
+page_title: base64decode - Functions - Configuration Language
+description: The base64decode function decodes a string containing a base64 sequence.
+---
+
+# `base64decode` Function
+
+`base64decode` takes a string containing a Base64 character sequence and
+returns the original string.
+
+Packer uses the "standard" Base64 alphabet as defined in
+[RFC 4648 section 4](https://tools.ietf.org/html/rfc4648#section-4).
+
+Strings in the Packer language are sequences of unicode characters rather
+than bytes, so this function will also interpret the resulting bytes as
+UTF-8. If the bytes after Base64 decoding are _not_ valid UTF-8, this function
+produces an error.
+
+While we do not recommend manipulating large, raw binary data in the Packer
+language, Base64 encoding is the standard way to represent arbitrary byte
+sequences, and so resource types that accept or return binary data will use
+Base64 themselves, which avoids the need to encode or decode it directly in
+most cases. Various other functions with names containing "base64" can generate
+or manipulate Base64 data directly.
+
+## Examples
+
+```shell-session
+> base64decode("SGVsbG8gV29ybGQ=")
+Hello World
+```
+
+## Related Functions
+
+- [`base64encode`](/packer/docs/templates/hcl_templates/functions/encoding/base64encode) performs the opposite operation,
+ encoding the UTF-8 bytes for a string as Base64.
diff --git a/v1.9.4/website/content/docs/templates/hcl_templates/functions/encoding/base64encode.mdx b/v1.9.4/website/content/docs/templates/hcl_templates/functions/encoding/base64encode.mdx
new file mode 100644
index 0000000..2d3441d
--- /dev/null
+++ b/v1.9.4/website/content/docs/templates/hcl_templates/functions/encoding/base64encode.mdx
@@ -0,0 +1,37 @@
+---
+page_title: base64encode - Functions - Configuration Language
+description: The base64encode function applies Base64 encoding to a string.
+---
+
+# `base64encode` Function
+
+`base64encode` applies Base64 encoding to a string.
+
+Packer uses the "standard" Base64 alphabet as defined in
+[RFC 4648 section 4](https://tools.ietf.org/html/rfc4648#section-4).
+
+Strings in the Packer language are sequences of unicode characters rather
+than bytes, so this function will first encode the characters from the string
+as UTF-8, and then apply Base64 encoding to the result.
+
+The Packer language applies Unicode normalization to all strings, and so
+passing a string through `base64decode` and then `base64encode` may not yield
+the original result exactly.
+
+While we do not recommend manipulating large, raw binary data in the Packer
+language, Base64 encoding is the standard way to represent arbitrary byte
+sequences, and so resource types that accept or return binary data will use
+Base64 themselves, and so this function exists primarily to allow string
+data to be easily provided to resource types that expect Base64 bytes.
+
+## Examples
+
+```shell-session
+> base64encode("Hello World")
+SGVsbG8gV29ybGQ=
+```
+
+## Related Functions
+
+- [`base64decode`](/packer/docs/templates/hcl_templates/functions/encoding/base64decode) performs the opposite operation,
+ decoding Base64 data and interpreting it as a UTF-8 string.
diff --git a/v1.9.4/website/content/docs/templates/hcl_templates/functions/encoding/csvdecode.mdx b/v1.9.4/website/content/docs/templates/hcl_templates/functions/encoding/csvdecode.mdx
new file mode 100644
index 0000000..88cb42d
--- /dev/null
+++ b/v1.9.4/website/content/docs/templates/hcl_templates/functions/encoding/csvdecode.mdx
@@ -0,0 +1,95 @@
+---
+page_title: csvdecode - Functions - Configuration Language
+description: The csvdecode function decodes CSV data into a list of maps.
+---
+
+# `csvdecode` Function
+
+`csvdecode` decodes a string containing CSV-formatted data and produces a
+list of maps representing that data.
+
+CSV is _Comma-separated Values_, an encoding format for tabular data. There
+are many variants of CSV, but this function implements the format defined
+in [RFC 4180](https://tools.ietf.org/html/rfc4180).
+
+The first line of the CSV data is interpreted as a "header" row: the values
+given are used as the keys in the resulting maps. Each subsequent line becomes
+a single map in the resulting list, matching the keys from the header row
+with the given values by index. All lines in the file must contain the same
+number of fields, or this function will produce an error.
+
+## Examples
+
+```shell-session
+> csvdecode("a,b,c\n1,2,3\n4,5,6")
+[
+ {
+ "a" = "1"
+ "b" = "2"
+ "c" = "3"
+ },
+ {
+ "a" = "4"
+ "b" = "5"
+ "c" = "6"
+ }
+]
+```
+
+## Use with the `for_each` meta-argument
+
+You can use the result of `csvdecode` with
+[the `for_each` meta-argument](/terraform/docs/configuration/resources#for_each-multiple-resource-instances-defined-by-a-map-or-set-of-strings)
+to describe a collection of similar objects whose differences are
+described by the rows in the given CSV file.
+
+There must be one column in the CSV file that can serve as a unique ID for each
+row, which we can then use as the tracking key for the individual instances in
+the `for_each` expression. For example:
+
+```hcl
+locals {
+ # We've included this inline to create a complete example, but in practice
+ # this is more likely to be loaded from a file using the "file" function.
+ csv_data = <<-CSV
+ local_id,instance_type,ami
+ foo1,t2.micro,ami-54d2a63b
+ foo2,t2.micro,ami-54d2a63b
+ foo3,t2.micro,ami-54d2a63b
+ bar1,m3.large,ami-54d2a63b
+ CSV
+
+ instances = csvdecode(local.csv_data)
+}
+
+resource "aws_instance" "example" {
+ for_each = { for inst in local.instances : inst.local_id => inst }
+
+ instance_type = each.value.instance_type
+ ami = each.value.ami
+}
+```
+
+The `for` expression in our `for_each` argument transforms the list produced
+by `csvdecode` into a map using the `local_id` as a key, which tells
+Packer to use the `local_id` value to track each instance it creates.
+Packer will create and manage the following instance addresses:
+
+- `aws_instance.example["foo1"]`
+- `aws_instance.example["foo2"]`
+- `aws_instance.example["foo3"]`
+- `aws_instance.example["bar1"]`
+
+If you modify a row in the CSV on a subsequent plan, Packer will interpret
+that as an update to the existing object as long as the `local_id` value is
+unchanged. If you add or remove rows from the CSV then Packer will plan to
+create or destroy associated instances as appropriate.
+
+If there is no reasonable value you can use as a unique identifier in your CSV
+then you could instead use
+[the `count` meta-argument](/terraform/docs/configuration/resources#count-multiple-resource-instances-by-count)
+to define an object for each CSV row, with each one identified by its index into
+the list returned by `csvdecode`. However, in that case any future updates to
+the CSV may be disruptive if they change the positions of particular objects in
+the list. We recommend using `for_each` with a unique ID column to make
+behavior more predictable on future changes.
diff --git a/v1.9.4/website/content/docs/templates/hcl_templates/functions/encoding/jsondecode.mdx b/v1.9.4/website/content/docs/templates/hcl_templates/functions/encoding/jsondecode.mdx
new file mode 100644
index 0000000..ade3fd2
--- /dev/null
+++ b/v1.9.4/website/content/docs/templates/hcl_templates/functions/encoding/jsondecode.mdx
@@ -0,0 +1,46 @@
+---
+page_title: jsondecode - Functions - Configuration Language
+description: |-
+ The jsondecode function decodes a JSON string into a representation of its
+ value.
+---
+
+# `jsondecode` Function
+
+`jsondecode` interprets a given string as JSON, returning a representation
+of the result of decoding that string.
+
+The JSON encoding is defined in [RFC 7159](https://tools.ietf.org/html/rfc7159).
+
+This function maps JSON values to
+[Packer language values](/packer/docs/templates/hcl_templates/expressions#types-and-values)
+in the following way:
+
+| JSON type | Packer type |
+| --------- | ------------------------------------------------------------ |
+| String | `string` |
+| Number | `number` |
+| Boolean | `bool` |
+| Object | `object(...)` with attribute types determined per this table |
+| Array | `tuple(...)` with element types determined per this table |
+| Null | The Packer language `null` value |
+
+The Packer language automatic type conversion rules mean that you don't
+usually need to worry about exactly what type is produced for a given value,
+and can just use the result in an intuitive way.
+
+## Examples
+
+```shell-session
+> jsondecode("{\"hello\": \"world\"}")
+{
+ "hello" = "world"
+}
+> jsondecode("true")
+true
+```
+
+## Related Functions
+
+- [`jsonencode`](/packer/docs/templates/hcl_templates/functions/encoding/jsonencode) performs the opposite operation, _encoding_
+ a value as JSON.
diff --git a/v1.9.4/website/content/docs/templates/hcl_templates/functions/encoding/jsonencode.mdx b/v1.9.4/website/content/docs/templates/hcl_templates/functions/encoding/jsonencode.mdx
new file mode 100644
index 0000000..fb75ee7
--- /dev/null
+++ b/v1.9.4/website/content/docs/templates/hcl_templates/functions/encoding/jsonencode.mdx
@@ -0,0 +1,43 @@
+---
+page_title: jsonencode - Functions - Configuration Language
+description: The jsonencode function encodes a given value as a JSON string.
+---
+
+# `jsonencode` Function
+
+`jsonencode` encodes a given value to a string using JSON syntax.
+
+The JSON encoding is defined in [RFC 7159](https://tools.ietf.org/html/rfc7159).
+
+This function maps
+[Packer language values](/packer/docs/templates/hcl_templates/expressions#types-and-values)
+to JSON values in the following way:
+
+| Packer type | JSON type |
+| ------------- | --------- |
+| `string` | String |
+| `number` | Number |
+| `bool` | Bool |
+| `list(...)` | Array |
+| `set(...)` | Array |
+| `tuple(...)` | Array |
+| `map(...)` | Object |
+| `object(...)` | Object |
+| Null value | `null` |
+
+Since the JSON format cannot fully represent all of the Packer language
+types, passing the `jsonencode` result to `jsondecode` will not produce an
+identical value, but the automatic type conversion rules mean that this is
+rarely a problem in practice.
+
+## Examples
+
+```shell-session
+> jsonencode({"hello"="world"})
+{"hello":"world"}
+```
+
+## Related Functions
+
+- [`jsondecode`](/packer/docs/templates/hcl_templates/functions/encoding/jsondecode) performs the opposite operation, _decoding_
+ a JSON string to obtain its represented value.
diff --git a/v1.9.4/website/content/docs/templates/hcl_templates/functions/encoding/urlencode.mdx b/v1.9.4/website/content/docs/templates/hcl_templates/functions/encoding/urlencode.mdx
new file mode 100644
index 0000000..a2b8de5
--- /dev/null
+++ b/v1.9.4/website/content/docs/templates/hcl_templates/functions/encoding/urlencode.mdx
@@ -0,0 +1,31 @@
+---
+page_title: urlencode - Functions - Configuration Language
+description: The urlencode function applies URL encoding to a given string.
+---
+
+# `urlencode` Function
+
+`urlencode` applies URL encoding to a given string.
+
+This function identifies characters in the given string that would have a
+special meaning when included as a query string argument in a URL and
+escapes them using
+[RFC 3986 "percent encoding"](https://tools.ietf.org/html/rfc3986#section-2.1).
+
+The exact set of characters escaped may change over time, but the result
+is guaranteed to be interpolatable into a query string argument without
+inadvertently introducing additional delimiters.
+
+If the given string contains non-ASCII characters, these are first encoded as
+UTF-8 and then percent encoding is applied separately to each UTF-8 byte.
+
+## Examples
+
+```shell-session
+> urlencode("Hello World")
+Hello%20World
+> urlencode("☃")
+%E2%98%83
+> "http://example.com/search?q=${urlencode("packer urlencode")}"
+http://example.com/search?q=packer%20urlencode
+```
diff --git a/v1.9.4/website/content/docs/templates/hcl_templates/functions/encoding/yamldecode.mdx b/v1.9.4/website/content/docs/templates/hcl_templates/functions/encoding/yamldecode.mdx
new file mode 100644
index 0000000..ea787ca
--- /dev/null
+++ b/v1.9.4/website/content/docs/templates/hcl_templates/functions/encoding/yamldecode.mdx
@@ -0,0 +1,99 @@
+---
+page_title: yamldecode - Functions - Configuration Language
+description: |-
+ The yamldecode function decodes a YAML string into a representation of its
+ value.
+---
+
+# `yamldecode` Function
+
+`yamldecode` parses a string as a subset of YAML, and produces a representation
+of its value.
+
+This function supports a subset of [YAML 1.2](https://yaml.org/spec/1.2/spec.html),
+as described below.
+
+This function maps YAML values to
+[Packer language values](/packer/docs/templates/hcl_templates/expressions#types-and-values)
+in the following way:
+
+| YAML type | Packer type |
+| ------------- | ------------------------------------------------------------------ |
+| `!!str` | `string` |
+| `!!float` | `number` |
+| `!!int` | `number` |
+| `!!bool` | `bool` |
+| `!!map` | `object(...)` with attribute types determined per this table |
+| `!!seq` | `tuple(...)` with element types determined per this table |
+| `!!null` | The Packer language `null` value |
+| `!!timestamp` | `string` in [RFC 3339](https://tools.ietf.org/html/rfc3339) format |
+| `!!binary` | `string` containing base64-encoded representation |
+
+The Packer language automatic type conversion rules mean that you don't
+usually need to worry about exactly what type is produced for a given value,
+and can just use the result in an intuitive way.
+
+Note though that the mapping above is ambiguous -- several different source
+types map to the same target type -- and so round-tripping through `yamldecode`
+and then `yamlencode` cannot produce an identical result.
+
+YAML is a complex language and it supports a number of possibilities that the
+Packer language's type system cannot represent. Therefore this YAML decoder
+supports only a subset of YAML 1.2, with restrictions including the following:
+
+- Although aliases to earlier anchors are supported, cyclic data structures
+ (where a reference to a collection appears inside that collection) are not.
+ If `yamldecode` detects such a structure then it will return an error.
+
+- Only the type tags shown in the above table (or equivalent alternative
+ representations of those same tags) are supported. Any other tags will
+ result in an error.
+
+- Only one YAML document is permitted. If multiple documents are present in
+ the given string then this function will return an error.
+
+## Examples
+
+```shell-session
+> yamldecode("{\"hello\": \"world\"}")
+{
+ "hello" = "world"
+}
+
+> yamldecode("true")
+true
+
+> yamldecode("{a: &foo [1, 2, 3], b: *foo}")
+{
+ "a" = [
+ 1,
+ 2,
+ 3,
+ ]
+ "b" = [
+ 1,
+ 2,
+ 3,
+ ]
+}
+
+> yamldecode("{a: &foo [1, *foo, 3]}")
+
+Error: Error in function call
+
+Call to function "yamldecode" failed: cannot refer to anchor "foo" from inside
+its own definition.
+
+> yamldecode("{a: !not-supported foo}")
+
+Error: Error in function call
+
+Call to function "yamldecode" failed: unsupported tag "!not-supported".
+```
+
+## Related Functions
+
+- [`jsondecode`](/packer/docs/templates/hcl_templates/functions/encoding/jsondecode) is a similar operation using JSON instead
+ of YAML.
+- [`yamlencode`](/packer/docs/templates/hcl_templates/functions/encoding/yamlencode) performs the opposite operation, _encoding_
+ a value as YAML.
diff --git a/v1.9.4/website/content/docs/templates/hcl_templates/functions/encoding/yamlencode.mdx b/v1.9.4/website/content/docs/templates/hcl_templates/functions/encoding/yamlencode.mdx
new file mode 100644
index 0000000..2aa0174
--- /dev/null
+++ b/v1.9.4/website/content/docs/templates/hcl_templates/functions/encoding/yamlencode.mdx
@@ -0,0 +1,85 @@
+---
+page_title: yamlencode - Functions - Configuration Language
+description: The yamlencode function encodes a given value as a YAML string.
+---
+
+# `yamlencode` Function
+
+`yamlencode` encodes a given value to a string using
+[YAML 1.2](https://yaml.org/spec/1.2/spec) block syntax.
+
+~> **Warning:** This function is currently **experimental** and its exact
+result format may change in future versions of Packer, based on feedback.
+Do not use `yamldecode` to construct a value for any resource argument where
+changes to the result would be disruptive. To get a consistent string
+representation of a value use [`jsonencode`](/packer/docs/templates/hcl_templates/functions/encoding/jsonencode) instead; its
+results are also valid YAML because YAML is a JSON superset.
+
+<!--
+ The condition for removing the above warning is that the underlying
+ go-cty-yaml folder makes a stable release with a commitment to guarantee
+ that the representation of particular input will not change without a
+ major release. It is not making that commitment at the time of writing to
+ allow for responding to user feedback about its output format, since YAML
+ is a very flexible format and its initial decisions may prove to be
+ sub-optimal when generating YAML intended for specific external consumers.
+-->
+
+This function maps
+[Packer language values](/packer/docs/templates/hcl_templates/expressions#types-and-values)
+to YAML tags in the following way:
+
+| Packer type | YAML type |
+| ------------- | -------------------- |
+| `string` | `!!str` |
+| `number` | `!!float` or `!!int` |
+| `bool` | `!!bool` |
+| `list(...)` | `!!seq` |
+| `set(...)` | `!!seq` |
+| `tuple(...)` | `!!seq` |
+| `map(...)` | `!!map` |
+| `object(...)` | `!!map` |
+| Null value | `!!null` |
+
+`yamlencode` uses the implied syntax for all of the above types, so it does
+not generate explicit YAML tags.
+
+Because the YAML format cannot fully represent all of the Packer language
+types, passing the `yamlencode` result to `yamldecode` will not produce an
+identical value, but the Packer language automatic type conversion rules
+mean that this is rarely a problem in practice.
+
+## Examples
+
+```shell-session
+> yamlencode({"a":"b", "c":"d"})
+"a": "b"
+"c": "d"
+
+> yamlencode({"foo":[1, 2, 3], "bar": "baz"})
+"bar": "baz"
+"foo":
+- 1
+- 2
+- 3
+
+> yamlencode({"foo":[1, {"a":"b","c":"d"}, 3], "bar": "baz"})
+"bar": "baz"
+"foo":
+- 1
+- "a": "b"
+ "c": "d"
+- 3
+```
+
+`yamlencode` always uses YAML's "block style" for mappings and sequences, unless
+the mapping or sequence is empty. To generate flow-style YAML, use
+[`jsonencode`](/packer/docs/templates/hcl_templates/functions/encoding/jsonencode) instead: YAML flow-style is a superset
+of JSON syntax.
+
+## Related Functions
+
+- [`jsonencode`](/packer/docs/templates/hcl_templates/functions/encoding/jsonencode) is a similar operation using JSON instead
+ of YAML.
+- [`yamldecode`](/packer/docs/templates/hcl_templates/functions/encoding/yamldecode) performs the opposite operation, _decoding_
+ a YAML string to obtain its represented value.
diff --git a/v1.9.4/website/content/docs/templates/hcl_templates/functions/file/abspath.mdx b/v1.9.4/website/content/docs/templates/hcl_templates/functions/file/abspath.mdx
new file mode 100644
index 0000000..b9c28ca
--- /dev/null
+++ b/v1.9.4/website/content/docs/templates/hcl_templates/functions/file/abspath.mdx
@@ -0,0 +1,24 @@
+---
+page_title: abspath - Functions - Configuration Language
+description: The abspath function converts the argument to an absolute filesystem path.
+---
+
+# `abspath` Function
+
+`abspath` takes a string containing a filesystem path and converts it
+to an absolute path. That is, if the path is not absolute, it will be joined
+with the current working directory.
+
+Referring directly to filesystem paths in resource arguments may cause spurious
+diffs if the same configuration is applied from multiple systems or on
+different host operating systems. We recommend using filesystem paths only for
+transient values, such as the argument to
+[`file`](/packer/docs/templates/hcl_templates/functions/file) (where only the contents are then
+stored).
+
+## Examples
+
+```shell-session
+> abspath(path.root)
+/home/user/some/packer/root
+```
diff --git a/v1.9.4/website/content/docs/templates/hcl_templates/functions/file/basename.mdx b/v1.9.4/website/content/docs/templates/hcl_templates/functions/file/basename.mdx
new file mode 100644
index 0000000..70a05e0
--- /dev/null
+++ b/v1.9.4/website/content/docs/templates/hcl_templates/functions/file/basename.mdx
@@ -0,0 +1,41 @@
+---
+page_title: basename - Functions - Configuration Language
+description: |-
+ The basename function removes all except the last portion from a filesystem
+ path.
+---
+
+# `basename` Function
+
+`basename` takes a string containing a filesystem path and removes all except
+the last portion from it.
+
+This function works only with the path string and does not access the
+filesystem itself. It is therefore unable to take into account filesystem
+features such as symlinks.
+
+If the path is empty then the result is `"."`, representing the current
+working directory.
+
+The behavior of this function depends on the host platform. On Windows systems,
+it uses backslash `\` as the path segment separator. On Unix systems, the slash
+`/` is used.
+
+Referring directly to filesystem paths in resource arguments may cause
+spurious diffs if the same configuration is applied from multiple systems or on
+different host operating systems. We recommend using filesystem paths only
+for transient values, such as the argument to [`file`](/packer/docs/templates/hcl_templates/functions/file) (where
+only the contents are then stored) or in `connection` and `provisioner` blocks.
+
+## Examples
+
+```shell-session
+> basename("foo/bar/baz.txt")
+baz.txt
+```
+
+## Related Functions
+
+- [`dirname`](/packer/docs/templates/hcl_templates/functions/file/dirname) returns all of the segments of a filesystem path
+ _except_ the last, discarding the portion that would be returned by
+ `basename`.
diff --git a/v1.9.4/website/content/docs/templates/hcl_templates/functions/file/dirname.mdx b/v1.9.4/website/content/docs/templates/hcl_templates/functions/file/dirname.mdx
new file mode 100644
index 0000000..348c036
--- /dev/null
+++ b/v1.9.4/website/content/docs/templates/hcl_templates/functions/file/dirname.mdx
@@ -0,0 +1,39 @@
+---
+page_title: dirname - Functions - Configuration Language
+description: The dirname function removes the last portion from a filesystem path.
+---
+
+# `dirname` Function
+
+`dirname` takes a string containing a filesystem path and removes the last
+portion from it.
+
+This function works only with the path string and does not access the
+filesystem itself. It is therefore unable to take into account filesystem
+features such as symlinks.
+
+If the path is empty then the result is `"."`, representing the current
+working directory.
+
+The behavior of this function depends on the host platform. On Windows systems,
+it uses backslash `\` as the path segment separator. On Unix systems, the slash
+`/` is used. The result of this function is normalized, so on a Windows system
+any slashes in the given path will be replaced by backslashes before returning.
+
+Referring directly to filesystem paths in resource arguments may cause
+spurious diffs if the same configuration is applied from multiple systems or on
+different host operating systems. We recommend using filesystem paths only
+for transient values, such as the argument to [`file`](/packer/docs/templates/hcl_templates/functions/file) (where
+only the contents are then stored) or in `connection` and `provisioner` blocks.
+
+## Examples
+
+```shell-session
+> dirname("foo/bar/baz.txt")
+foo/bar
+```
+
+## Related Functions
+
+- [`basename`](/packer/docs/templates/hcl_templates/functions/file/basename) returns _only_ the last portion of a filesystem
+ path, discarding the portion that would be returned by `dirname`.
diff --git a/v1.9.4/website/content/docs/templates/hcl_templates/functions/file/file.mdx b/v1.9.4/website/content/docs/templates/hcl_templates/functions/file/file.mdx
new file mode 100644
index 0000000..6dd36ee
--- /dev/null
+++ b/v1.9.4/website/content/docs/templates/hcl_templates/functions/file/file.mdx
@@ -0,0 +1,37 @@
+---
+page_title: file - Functions - Configuration Language
+description: |-
+ The file function reads the contents of the file at the given path and
+ returns them as a string.
+---
+
+# `file` Function
+
+`file` reads the contents of a file at the given path and returns them as
+a string.
+
+```hcl
+file(path)
+```
+
+Strings in the Packer language are sequences of Unicode characters, so
+this function will interpret the file contents as UTF-8 encoded text and
+return the resulting Unicode characters. If the file contains invalid UTF-8
+sequences then this function will produce an error.
+
+This function can be used only with files that already exist on disk
+at the beginning of a Packer run. Functions do not participate in the
+dependency graph, so this function cannot be used with files that are generated
+dynamically during a Packer operation.
+
+## Examples
+
+```shell-session
+> file("${path.folder}/hello.txt")
+Hello World
+```
+
+## Related Functions
+
+- [`fileexists`](/packer/docs/templates/hcl_templates/functions/file/fileexists) determines whether a file exists
+ at a given path.
diff --git a/v1.9.4/website/content/docs/templates/hcl_templates/functions/file/fileexists.mdx b/v1.9.4/website/content/docs/templates/hcl_templates/functions/file/fileexists.mdx
new file mode 100644
index 0000000..b8b0b3f
--- /dev/null
+++ b/v1.9.4/website/content/docs/templates/hcl_templates/functions/file/fileexists.mdx
@@ -0,0 +1,35 @@
+---
+page_title: fileexists - Functions - Configuration Language
+description: The fileexists function determines whether a file exists at a given path.
+---
+
+# `fileexists` Function
+
+`fileexists` determines whether a file exists at a given path.
+
+```hcl
+fileexists(path)
+```
+
+Functions are evaluated during configuration parsing rather than at apply time,
+so this function can only be used with files that are already present on disk
+before Packer takes any actions.
+
+This function works only with regular files. If used with a directory, FIFO,
+or other special mode, it will return an error.
+
+## Examples
+
+```shell-session
+> fileexists("${path.folder}/hello.txt")
+true
+```
+
+```hcl
+fileexists("custom-section.sh") ? file("custom-section.sh") : local.default_content
+```
+
+## Related Functions
+
+- [`file`](/packer/docs/templates/hcl_templates/functions/file/file) reads the contents
+ of a file at a given path.
diff --git a/v1.9.4/website/content/docs/templates/hcl_templates/functions/file/fileset.mdx b/v1.9.4/website/content/docs/templates/hcl_templates/functions/file/fileset.mdx
new file mode 100644
index 0000000..e60dd12
--- /dev/null
+++ b/v1.9.4/website/content/docs/templates/hcl_templates/functions/file/fileset.mdx
@@ -0,0 +1,102 @@
+---
+page_title: fileset - Functions - Configuration Language
+description: The fileset function enumerates a set of regular file names given a pattern.
+---
+
+# `fileset` Function
+
+`fileset` enumerates a set of regular file names given a path and pattern.
+The path is automatically removed from the resulting set of file names and any
+result still containing path separators always returns forward slash (`/`) as
+the path separator for cross-system compatibility.
+
+```hcl
+fileset(path, pattern)
+```
+
+Supported pattern matches:
+
+- `*` - matches any sequence of non-separator characters
+- `**` - matches any sequence of characters, including separator characters
+- `?` - matches any single non-separator character
+- `{alternative1,...}` - matches a sequence of characters if one of the comma-separated alternatives matches
+- `[CLASS]` - matches any single non-separator character inside a class of characters (see below)
+- `[^CLASS]` - matches any single non-separator character outside a class of characters (see below)
+
+Character classes support the following:
+
+- `[abc]` - matches any single character within the set
+- `[a-z]` - matches any single character within the range
+
+Functions are evaluated during configuration parsing rather than at apply time,
+so this function can only be used with files that are already present on disk
+before Packer takes any actions.
+
+## Examples
+
+```shell-session
+> tree pkr-consul
+pkr-consul
+├── build-linux.pkr.hcl
+└── linux
+ ├── files
+ │ ├── hello.txt
+ │ └── world.txt
+ └── scripts
+ ├── script-1-install.sh
+ └── script-2-setup.sh
+
+3 directories, 5 files
+
+> fileset(".", "*") | packer console pkr-consul
+[
+ "build-linux.pkr.hcl",
+]
+
+> echo 'fileset(".", "linux/scripts/*")' | packer console pkr-consul
+[
+ "linux/scripts/script-1-install.sh",
+ "linux/scripts/script-2-setup.sh",
+]
+
+> echo 'fileset("linux", "files/{hello,world}.txt")' | packer console pkr-consul
+[
+ "files/hello.txt",
+ "files/world.txt",
+]
+
+> echo 'fileset("./linux/files", "*")' | packer console pkr-consul
+[
+ "hello.txt",
+ "world.txt",
+]
+
+> echo 'fileset("./linux", "**")' | packer console pkr-consul
+[
+ "files/hello.txt",
+ "files/world.txt",
+ "scripts/script-1-install.sh",
+ "scripts/script-2-setup.sh",
+]
+```
+
+A common use of `fileset` is to set the `scripts` field of a `shell`
+provisioner with a list of matching scripts to run.
+
+```hcl
+build {
+ sources = [
+ "source.amazon-ebs.linux",
+ ]
+
+ provisioner "shell" {
+ scripts = fileset(".", "linux/scripts/*")
+ }
+```
+
+List of provisioners with a `scripts` field:
+
+- [`shell`](/packer/docs/provisioners/shell)
+- [`powershell`](/packer/docs/provisioners/powershell)
+- [`shell-local`](/packer/docs/provisioners/shell-local)
+- [`windows-shell`](/packer/docs/provisioners/windows-shell)
diff --git a/v1.9.4/website/content/docs/templates/hcl_templates/functions/file/pathexpand.mdx b/v1.9.4/website/content/docs/templates/hcl_templates/functions/file/pathexpand.mdx
new file mode 100644
index 0000000..974716c
--- /dev/null
+++ b/v1.9.4/website/content/docs/templates/hcl_templates/functions/file/pathexpand.mdx
@@ -0,0 +1,54 @@
+---
+page_title: pathexpand - Functions - Configuration Language
+description: |-
+ The pathexpand function expands a leading ~ character to the current user's
+ home directory.
+---
+
+# `pathexpand` Function
+
+`pathexpand` takes a filesystem path that might begin with a `~` segment,
+and if so it replaces that segment with the current user's home directory
+path.
+
+This function works only with the path string and does not access the
+filesystem itself. It is therefore unable to take into account filesystem
+features such as symlinks.
+
+If the leading segment in the path is not `~` then the given path is returned
+unmodified.
+
+Using this function in resource arguments will cause spurious diffs if the
+same configuration is run by multiple users with different home directory
+paths, or used on different host operating systems. We recommend using this
+function only for transient values, such as in `connection` and `provisioner`
+blocks to locate SSH keys, etc.
+
+The rules for determining the "home directory" for the current user vary
+depending on host operating system.
+
+**For Unix systems**, the following sources are consulted, in order of preference:
+
+- The `HOME` environment variable.
+- The result of running `getent passwd` followed by the Packer process uid.
+- The result of running `cd && pwd` in `sh`.
+
+**For Windows systems**, there is not really the concept of a home directory
+in the same sense as on Unix, but the following sources are consulted in
+order of preference:
+
+- The `HOME` environment variable.
+- The `HOMEDRIVE` and `HOMEPATH` environment variables, if both are set.
+- The `USERPROFILE` environment variable.
+
+The exact rules employed for each operating system may change in future
+releases of Packer.
+
+## Examples
+
+```shell-session
+> pathexpand("~/.ssh/id_rsa")
+/home/steve/.ssh/id_rsa
+> pathexpand("/etc/resolv.conf")
+/etc/resolv.conf
+```
diff --git a/v1.9.4/website/content/docs/templates/hcl_templates/functions/file/templatefile.mdx b/v1.9.4/website/content/docs/templates/hcl_templates/functions/file/templatefile.mdx
new file mode 100644
index 0000000..68cc8cf
--- /dev/null
+++ b/v1.9.4/website/content/docs/templates/hcl_templates/functions/file/templatefile.mdx
@@ -0,0 +1,138 @@
+---
+page_title: templatefile - Functions - Configuration Language
+description: |-
+ The templatefile function reads the file at the given path and renders its
+ content as a template using a supplied set of template variables.
+---
+
+# `templatefile` Function
+
+-> _Recommendation:_ we recommend using the `.pkrtpl.hcl` file extension when
+using the `templatefile` function. Template files _are_ hcl treated as files but
+also templates and therefore have slightly different set of features
+than the ones offered in a `.pkr.hcl` Packer template. While you are not
+required to use this extension, doing so will enable syntax highlighters to
+properly understand your file.
+
+`templatefile` reads the file at the given path and renders its content as a
+template using a supplied set of template variables.
+
+```hcl
+templatefile(path, vars)
+```
+
+The template syntax is the same as for string templates in the main HCL2
+language, including interpolation sequences delimited with `${ ... }`. This
+function just allows longer template sequences to be factored out into a
+separate file for readability.
+
+The "vars" argument must be a map. Within the template file, each of the keys in
+the map is available as a variable for interpolation. The template may also use
+any other function available in Packer, except that recursive calls to
+templatefile are not permitted. Variable names must each start with a letter,
+followed by zero or more letters, digits, or underscores.
+
+Strings in HCL2 are sequences of Unicode characters, so this function will
+interpret the file contents as UTF-8 encoded text and return the resulting
+Unicode characters. If the file contains invalid UTF-8 sequences then this
+function will produce an error.
+
+This function can be used only with files that already exist on disk at the
+beginning of a run.
+
+## Examples
+
+### Lists
+
+Given a template file backends.tpl with the following content:
+
+```hcl
+%{ for addr in ip_addrs ~}
+backend ${addr}:${port}
+%{ endfor ~}
+```
+
+The templatefile function renders the template:
+
+```shell-session
+> templatefile("${path.root}/backends.tmpl", { port = 8080, ip_addrs = ["10.0.0.1", "10.0.0.2"] })
+backend 10.0.0.1:8080
+backend 10.0.0.2:8080
+```
+
+### Maps
+
+Given a template file config.tmpl with the following content:
+
+```hcl
+%{ for config_key, config_value in config }
+set ${config_key} = ${config_value}
+%{ endfor ~}
+```
+
+The templatefile function renders the template:
+
+```shell-session
+> templatefile(
+ "${path.root}/config.tmpl",
+ {
+ config = {
+ "x" = "y"
+ "foo" = "bar"
+ "key" = "value"
+ }
+ }
+ )
+set foo = bar
+set key = value
+set x = y
+```
+
+### Generating JSON or YAML from a template
+
+If the string you want to generate will be in JSON or YAML syntax, it's often
+tricky and tedious to write a template that will generate valid JSON or YAML
+that will be interpreted correctly when using lots of individual interpolation
+sequences and directives.
+
+Instead, you can write a template that consists only of a single interpolated
+call to either jsonencode or yamlencode, specifying the value to encode using
+normal expression syntax as in the following examples:
+
+```hcl
+${jsonencode({
+ "backends": [for addr in ip_addrs : "${addr}:${port}"],
+})}
+${yamlencode({
+ "backends": [for addr in ip_addrs : "${addr}:${port}"],
+})}
+```
+
+Given the same input as the `backends.tmpl` example in the previous section,
+this will produce a valid JSON or YAML representation of the given data
+structure, without the need to manually handle escaping or delimiters. In the
+latest examples above, the repetition based on elements of ip_addrs is achieved
+by using a for expression rather than by using template directives.
+
+```
+{"backends":["10.0.0.1:8080","10.0.0.2:8080"]}
+```
+
+If the resulting template is small, you can choose instead to write jsonencode or yamlencode calls inline in your main configuration files, and avoid creating separate template files at all:
+
+```hcl
+locals {
+ backend_config_json = jsonencode({
+ "backends": [for addr in ip_addrs : "${addr}:${port}"],
+ })
+}
+```
+
+For more information, see the main documentation for jsonencode and yamlencode.
+
+## Related Functions
+
+- [`file`](/packer/docs/templates/hcl_templates/functions/file/file) reads the contents
+ of a file at a given path.
+- [`fileexists`](/packer/docs/templates/hcl_templates/functions/file/fileexists)
+ determines whether a file exists at a given path.
diff --git a/v1.9.4/website/content/docs/templates/hcl_templates/functions/index.mdx b/v1.9.4/website/content/docs/templates/hcl_templates/functions/index.mdx
new file mode 100644
index 0000000..eb64615
--- /dev/null
+++ b/v1.9.4/website/content/docs/templates/hcl_templates/functions/index.mdx
@@ -0,0 +1,26 @@
+---
+page_title: Functions - Configuration Language
+description: |-
+ The HCL language has a number of built-in functions that can be called
+ from within expressions to transform and combine values.
+---
+
+# Built-in Functions
+
+`@include 'from-1.5/beta-hcl2-note.mdx'`
+
+The HCL language includes a number of built-in functions that you can
+call from within expressions to transform and combine values. The general
+syntax for function calls is a function name followed by comma-separated
+arguments in parentheses:
+
+```hcl
+max(5, 12, 9)
+```
+
+For more details on syntax, see
+[_Function Calls_](/packer/docs/templates/hcl_templates/expressions#function-calls)
+on the Expressions page.
+
+The HCL language does not support user-defined functions, and so only
+the functions built in to the language are available for use. The documentation includes all of the available built-in functions.
diff --git a/v1.9.4/website/content/docs/templates/hcl_templates/functions/ipnet/cidrhost.mdx b/v1.9.4/website/content/docs/templates/hcl_templates/functions/ipnet/cidrhost.mdx
new file mode 100644
index 0000000..77c5679
--- /dev/null
+++ b/v1.9.4/website/content/docs/templates/hcl_templates/functions/ipnet/cidrhost.mdx
@@ -0,0 +1,49 @@
+---
+page_title: cidrhost - Functions - Configuration Language
+description: |-
+ The cidrhost function calculates a full host IP address within a given
+ IP network address prefix.
+---
+
+# `cidrhost` Function
+
+`cidrhost` calculates a full host IP address for a given host number within
+a given IP network address prefix.
+
+```hcl
+cidrhost(prefix, hostnum)
+```
+
+`prefix` must be given in CIDR notation, as defined in
+[RFC 4632 section 3.1](https://tools.ietf.org/html/rfc4632#section-3.1).
+
+`hostnum` is a whole number that can be represented as a binary integer with
+no more than the number of digits remaining in the address after the given
+prefix. For more details on how this function interprets CIDR prefixes and
+populates host numbers, see the worked example for
+[`cidrsubnet`](/packer/docs/templates/hcl_templates/functions/ipnet/cidrsubnet).
+
+Conventionally host number zero is used to represent the address of the
+network itself and the host number that would fill all the host bits with
+binary 1 represents the network's broadcast address. These numbers should
+generally not be used to identify individual hosts except in unusual
+situations, such as point-to-point links.
+
+This function accepts both IPv6 and IPv4 prefixes, and the result always uses
+the same addressing scheme as the given prefix.
+
+## Examples
+
+```shell-session
+> cidrhost("10.12.127.0/20", 16)
+10.12.112.16
+> cidrhost("10.12.127.0/20", 268)
+10.12.113.12
+> cidrhost("fd00:fd12:3456:7890:00a2::/72", 34)
+fd00:fd12:3456:7890::22
+```
+
+## Related Functions
+
+- [`cidrsubnet`](/packer/docs/templates/hcl_templates/functions/ipnet/cidrsubnet) calculates a subnet address under a given
+ network address prefix.
diff --git a/v1.9.4/website/content/docs/templates/hcl_templates/functions/ipnet/cidrnetmask.mdx b/v1.9.4/website/content/docs/templates/hcl_templates/functions/ipnet/cidrnetmask.mdx
new file mode 100644
index 0000000..fbb43ee
--- /dev/null
+++ b/v1.9.4/website/content/docs/templates/hcl_templates/functions/ipnet/cidrnetmask.mdx
@@ -0,0 +1,31 @@
+---
+page_title: cidrnetmask - Functions - Configuration Language
+description: |-
+ The cidrnetmask function converts an IPv4 address prefix given in CIDR
+ notation into a subnet mask address.
+---
+
+# `cidrnetmask` Function
+
+`cidrnetmask` converts an IPv4 address prefix given in CIDR notation into
+a subnet mask address.
+
+```hcl
+cidrnetmask(prefix)
+```
+
+`prefix` must be given in IPv4 CIDR notation, as defined in
+[RFC 4632 section 3.1](https://tools.ietf.org/html/rfc4632#section-3.1).
+
+The result is a subnet address formatted in the conventional dotted-decimal
+IPv4 address syntax, as expected by some software.
+
+CIDR notation is the only valid notation for IPv6 addresses, so `cidrnetmask`
+produces an error if given an IPv6 address.
+
+## Examples
+
+```shell-session
+> cidrnetmask("172.16.0.0/12")
+255.240.0.0
+```
diff --git a/v1.9.4/website/content/docs/templates/hcl_templates/functions/ipnet/cidrsubnet.mdx b/v1.9.4/website/content/docs/templates/hcl_templates/functions/ipnet/cidrsubnet.mdx
new file mode 100644
index 0000000..fbe916d
--- /dev/null
+++ b/v1.9.4/website/content/docs/templates/hcl_templates/functions/ipnet/cidrsubnet.mdx
@@ -0,0 +1,166 @@
+---
+page_title: cidrsubnet - Functions - Configuration Language
+description: |-
+ The cidrsubnet function calculates a subnet address within a given IP network
+ address prefix.
+---
+
+# `cidrsubnet` Function
+
+`cidrsubnet` calculates a subnet address within given IP network address prefix.
+
+```hcl
+cidrsubnet(prefix, newbits, netnum)
+```
+
+`prefix` must be given in CIDR notation, as defined in
+[RFC 4632 section 3.1](https://tools.ietf.org/html/rfc4632#section-3.1).
+
+`newbits` is the number of additional bits with which to extend the prefix.
+For example, if given a prefix ending in `/16` and a `newbits` value of
+`4`, the resulting subnet address will have length `/20`.
+
+`netnum` is a whole number that can be represented as a binary integer with
+no more than `newbits` binary digits, which will be used to populate the
+additional bits added to the prefix.
+
+This function accepts both IPv6 and IPv4 prefixes, and the result always uses
+the same addressing scheme as the given prefix.
+
+Unlike the related function [`cidrsubnets`](/packer/docs/templates/hcl_templates/functions/ipnet/cidrsubnets), `cidrsubnet`
+allows you to give a specific network number to use. `cidrsubnets` can allocate
+multiple network addresses at once, but numbers them automatically starting
+with zero.
+
+## Examples
+
+```shell-session
+> cidrsubnet("172.16.0.0/12", 4, 2)
+172.18.0.0/16
+> cidrsubnet("10.1.2.0/24", 4, 15)
+10.1.2.240/28
+> cidrsubnet("fd00:fd12:3456:7890::/56", 16, 162)
+fd00:fd12:3456:7800:a200::/72
+```
+
+## Netmasks and Subnets
+
+Using `cidrsubnet` requires familiarity with some network addressing concepts.
+
+The most important idea is that an IP address (whether IPv4 or IPv6) is
+fundamentally constructed from binary digits, even though we conventionally
+represent it as either four decimal octets (for IPv4) or a sequence of 16-bit
+hexadecimal numbers (for IPv6).
+
+Taking our example above of `cidrsubnet("10.1.2.0/24", 4, 15)`, the function
+will first convert the given IP address string into an equivalent binary
+representation:
+
+```text
+ 10 . 1 . 2 . 0
+00001010 00000001 00000010 | 00000000
+ network | host
+```
+
+The `/24` at the end of the prefix string specifies that the first 24
+bits -- or, the first three octets -- of the address identify the network
+while the remaining bits (32 - 24 = 8 bits in this case) identify hosts
+within the network.
+
+The CLI tool [`ipcalc`](https://gitlab.com/ipcalc/ipcalc) is useful for
+visualizing CIDR prefixes as binary numbers. We can confirm the conversion
+above by providing the same prefix string to `ipcalc`:
+
+```shell-session
+$ ipcalc 10.1.2.0/24
+Address: 10.1.2.0 00001010.00000001.00000010. 00000000
+Netmask: 255.255.255.0 = 24 11111111.11111111.11111111. 00000000
+Wildcard: 0.0.0.255 00000000.00000000.00000000. 11111111
+=>
+Network: 10.1.2.0/24 00001010.00000001.00000010. 00000000
+HostMin: 10.1.2.1 00001010.00000001.00000010. 00000001
+HostMax: 10.1.2.254 00001010.00000001.00000010. 11111110
+Broadcast: 10.1.2.255 00001010.00000001.00000010. 11111111
+Hosts/Net: 254 Class A, Private Internet
+```
+
+This gives us some additional information but also confirms (using a slightly
+different notation) the conversion from decimal to binary and shows the range
+of possible host addresses in this network.
+
+While [`cidrhost`](/packer/docs/templates/hcl_templates/functions/ipnet/cidrhost) allows calculating single host IP addresses,
+`cidrsubnet` on the other hand creates a new network prefix _within_ the given
+network prefix. In other words, it creates a subnet.
+
+When we call `cidrsubnet` we also pass two additional arguments: `newbits` and
+`netnum`. `newbits` decides how much longer the resulting prefix will be in
+bits; in our example here we specified `4`, which means that the resulting
+subnet will have a prefix length of 24 + 4 = 28 bits. We can imagine these
+bits breaking down as follows:
+
+```text
+ 10 . 1 . 2 . ? 0
+00001010 00000001 00000010 | XXXX | 0000
+ parent network | netnum | host
+```
+
+Four of the eight bits that were originally the "host number" are now being
+repurposed as the subnet number. The network prefix no longer falls on an
+exact octet boundary, so in effect we are now splitting the last decimal number
+in the IP address into two parts, using half of it to represent the subnet
+number and the other half to represent the host number.
+
+The `netnum` argument then decides what number value to encode into those
+four new subnet bits. In our current example we passed `15`, which is
+represented in binary as `1111`, allowing us to fill in the `XXXX` segment
+in the above:
+
+```text
+ 10 . 1 . 2 . 15 0
+00001010 00000001 00000010 | 1111 | 0000
+ parent network | netnum | host
+```
+
+To convert this back into normal decimal notation we need to recombine the
+two portions of the final octet. Converting `11110000` from binary to decimal
+gives 240, which can then be combined with our new prefix length of 28 to
+produce the result `10.1.2.240/28`. Again we can pass this prefix string to
+`ipcalc` to visualize it:
+
+```shell-session
+$ ipcalc 10.1.2.240/28
+Address: 10.1.2.240 00001010.00000001.00000010.1111 0000
+Netmask: 255.255.255.240 = 28 11111111.11111111.11111111.1111 0000
+Wildcard: 0.0.0.15 00000000.00000000.00000000.0000 1111
+=>
+Network: 10.1.2.240/28 00001010.00000001.00000010.1111 0000
+HostMin: 10.1.2.241 00001010.00000001.00000010.1111 0001
+HostMax: 10.1.2.254 00001010.00000001.00000010.1111 1110
+Broadcast: 10.1.2.255 00001010.00000001.00000010.1111 1111
+Hosts/Net: 14 Class A, Private Internet
+```
+
+The new subnet has four bits available for host numbering, which means
+that there are 14 host addresses available for assignment once we subtract
+the network's own address and the broadcast address. You can thus use
+[`cidrhost`](/packer/docs/templates/hcl_templates/functions/ipnet/cidrhost) function to calculate those host addresses by
+providing it a value between 1 and 14:
+
+```shell-session
+> cidrhost("10.1.2.240/28", 1)
+10.1.2.241
+> cidrhost("10.1.2.240/28", 14)
+10.1.2.254
+```
+
+For more information on CIDR notation and subnetting, see
+[Classless Inter-domain Routing](https://en.wikipedia.org/wiki/Classless_Inter-Domain_Routing).
+
+## Related Functions
+
+- [`cidrhost`](/packer/docs/templates/hcl_templates/functions/ipnet/cidrhost) calculates the IP address for a single host
+ within a given network address prefix.
+- [`cidrnetmask`](/packer/docs/templates/hcl_templates/functions/ipnet/cidrnetmask) converts an IPv4 network prefix in CIDR
+ notation into netmask notation.
+- [`cidrsubnets`](/packer/docs/templates/hcl_templates/functions/ipnet/cidrsubnets) can allocate multiple consecutive
+ addresses under a prefix at once, numbering them automatically.
diff --git a/v1.9.4/website/content/docs/templates/hcl_templates/functions/ipnet/cidrsubnets.mdx b/v1.9.4/website/content/docs/templates/hcl_templates/functions/ipnet/cidrsubnets.mdx
new file mode 100644
index 0000000..faac15f
--- /dev/null
+++ b/v1.9.4/website/content/docs/templates/hcl_templates/functions/ipnet/cidrsubnets.mdx
@@ -0,0 +1,93 @@
+---
+page_title: cidrsubnets - Functions - Configuration Language
+description: |-
+ The cidrsubnets function calculates a sequence of consecutive IP address
+ ranges within a particular CIDR prefix.
+---
+
+# `cidrsubnets` Function
+
+`cidrsubnets` calculates a sequence of consecutive IP address ranges within
+a particular CIDR prefix.
+
+```hcl
+cidrsubnets(prefix, newbits...)
+```
+
+`prefix` must be given in CIDR notation, as defined in
+[RFC 4632 section 3.1](https://tools.ietf.org/html/rfc4632#section-3.1).
+
+The remaining arguments, indicated as `newbits` above, each specify the number
+of additional network prefix bits for one returned address range. The return
+value is therefore a list with one element per `newbits` argument, each
+a string containing an address range in CIDR notation.
+
+For more information on IP addressing concepts, see the documentation for the
+related function [`cidrsubnet`](/packer/docs/templates/hcl_templates/functions/ipnet/cidrsubnet). `cidrsubnet` calculates
+a single subnet address within a prefix while allowing you to specify its
+subnet number, while `cidrsubnets` can calculate many at once, potentially of
+different sizes, and assigns subnet numbers automatically.
+
+When using this function to partition an address space as part of a network
+address plan, you must not change any of the existing arguments once network
+addresses have been assigned to real infrastructure, or else later address
+assignments will be invalidated. However, you _can_ append new arguments to
+existing calls safely, as long as there is sufficient address space available.
+
+This function accepts both IPv6 and IPv4 prefixes, and the result always uses
+the same addressing scheme as the given prefix.
+
+## Examples
+
+```shell-session
+> cidrsubnets("10.1.0.0/16", 4, 4, 8, 4)
+[
+ "10.1.0.0/20",
+ "10.1.16.0/20",
+ "10.1.32.0/24",
+ "10.1.48.0/20",
+]
+
+> cidrsubnets("fd00:fd12:3456:7890::/56", 16, 16, 16, 32)
+[
+ "fd00:fd12:3456:7800::/72",
+ "fd00:fd12:3456:7800:100::/72",
+ "fd00:fd12:3456:7800:200::/72",
+ "fd00:fd12:3456:7800:300::/88",
+]
+```
+
+You can use nested `cidrsubnets` calls with
+[`for` expressions](/packer/docs/templates/hcl_templates/expressions#for-expressions)
+to concisely allocate groups of network address blocks:
+
+```shell-session
+> [for cidr_block in cidrsubnets("10.0.0.0/8", 8, 8, 8, 8) : cidrsubnets(cidr_block, 4, 4)]
+[
+ [
+ "10.0.0.0/20",
+ "10.0.16.0/20",
+ ],
+ [
+ "10.1.0.0/20",
+ "10.1.16.0/20",
+ ],
+ [
+ "10.2.0.0/20",
+ "10.2.16.0/20",
+ ],
+ [
+ "10.3.0.0/20",
+ "10.3.16.0/20",
+ ],
+]
+```
+
+## Related Functions
+
+- [`cidrhost`](/packer/docs/templates/hcl_templates/functions/ipnet/cidrhost) calculates the IP address for a single host
+ within a given network address prefix.
+- [`cidrnetmask`](/packer/docs/templates/hcl_templates/functions/ipnet/cidrnetmask) converts an IPv4 network prefix in CIDR
+ notation into netmask notation.
+- [`cidrsubnet`](/packer/docs/templates/hcl_templates/functions/ipnet/cidrsubnet) calculates a single subnet address, allowing
+ you to specify its network number.
diff --git a/v1.9.4/website/content/docs/templates/hcl_templates/functions/numeric/abs.mdx b/v1.9.4/website/content/docs/templates/hcl_templates/functions/numeric/abs.mdx
new file mode 100644
index 0000000..023b415
--- /dev/null
+++ b/v1.9.4/website/content/docs/templates/hcl_templates/functions/numeric/abs.mdx
@@ -0,0 +1,21 @@
+---
+page_title: abs - Functions - Configuration Language
+description: The abs function returns the absolute value of the given number.
+---
+
+# `abs` Function
+
+`abs` returns the absolute value of the given number. In other words, if the
+number is zero or positive then it is returned as-is, but if it is negative
+then it is multiplied by -1 to make it positive before returning it.
+
+## Examples
+
+```shell-session
+> abs(23)
+23
+> abs(0)
+0
+> abs(-12.4)
+12.4
+```
diff --git a/v1.9.4/website/content/docs/templates/hcl_templates/functions/numeric/ceil.mdx b/v1.9.4/website/content/docs/templates/hcl_templates/functions/numeric/ceil.mdx
new file mode 100644
index 0000000..2c3e9a7
--- /dev/null
+++ b/v1.9.4/website/content/docs/templates/hcl_templates/functions/numeric/ceil.mdx
@@ -0,0 +1,25 @@
+---
+page_title: ceil - Functions - Configuration Language
+description: |-
+ The ceil function returns the closest whole number greater than or equal to
+ the given value.
+---
+
+# `ceil` Function
+
+`ceil` returns the closest whole number that is greater than or equal to the
+given value, which may be a fraction.
+
+## Examples
+
+```shell-session
+> ceil(5)
+5
+> ceil(5.1)
+6
+```
+
+## Related Functions
+
+- [`floor`](/packer/docs/templates/hcl_templates/functions/numeric/floor), which rounds to the nearest whole number _less than_
+ or equal.
diff --git a/v1.9.4/website/content/docs/templates/hcl_templates/functions/numeric/floor.mdx b/v1.9.4/website/content/docs/templates/hcl_templates/functions/numeric/floor.mdx
new file mode 100644
index 0000000..66faf73
--- /dev/null
+++ b/v1.9.4/website/content/docs/templates/hcl_templates/functions/numeric/floor.mdx
@@ -0,0 +1,25 @@
+---
+page_title: floor - Functions - Configuration Language
+description: |-
+ The floor function returns the closest whole number less than or equal to
+ the given value.
+---
+
+# `floor` Function
+
+`floor` returns the closest whole number that is less than or equal to the
+given value, which may be a fraction.
+
+## Examples
+
+```shell-session
+> floor(5)
+5
+> floor(4.9)
+4
+```
+
+## Related Functions
+
+- [`ceil`](/packer/docs/templates/hcl_templates/functions/numeric/ceil), which rounds to the nearest whole number _greater than_
+ or equal.
diff --git a/v1.9.4/website/content/docs/templates/hcl_templates/functions/numeric/log.mdx b/v1.9.4/website/content/docs/templates/hcl_templates/functions/numeric/log.mdx
new file mode 100644
index 0000000..c63952e
--- /dev/null
+++ b/v1.9.4/website/content/docs/templates/hcl_templates/functions/numeric/log.mdx
@@ -0,0 +1,33 @@
+---
+page_title: log - Functions - Configuration Language
+description: The log function returns the logarithm of a given number in a given base.
+---
+
+# `log` Function
+
+`log` returns the logarithm of a given number in a given base.
+
+```hcl
+log(number, base)
+```
+
+## Examples
+
+```shell-session
+> log(50, 10)
+1.6989700043360185
+> log(16, 2)
+4
+```
+
+`log` and `ceil` can be used together to find the minimum number of binary
+digits required to represent a given number of distinct values:
+
+```shell-session
+> ceil(log(15, 2))
+4
+> ceil(log(16, 2))
+4
+> ceil(log(17, 2))
+5
+```
diff --git a/v1.9.4/website/content/docs/templates/hcl_templates/functions/numeric/max.mdx b/v1.9.4/website/content/docs/templates/hcl_templates/functions/numeric/max.mdx
new file mode 100644
index 0000000..36f8ac2
--- /dev/null
+++ b/v1.9.4/website/content/docs/templates/hcl_templates/functions/numeric/max.mdx
@@ -0,0 +1,27 @@
+---
+page_title: max - Functions - Configuration Language
+description: The max function takes one or more numbers and returns the greatest number.
+---
+
+# `max` Function
+
+`max` takes one or more numbers and returns the greatest number from the set.
+
+## Examples
+
+```shell-session
+> max(12, 54, 3)
+54
+```
+
+If the numbers are in a list or set value, use `...` to expand the collection
+to individual arguments:
+
+```shell-session
+> max([12, 54, 3]...)
+54
+```
+
+## Related Functions
+
+- [`min`](/packer/docs/templates/hcl_templates/functions/numeric/min), which returns the _smallest_ number from a set.
diff --git a/v1.9.4/website/content/docs/templates/hcl_templates/functions/numeric/min.mdx b/v1.9.4/website/content/docs/templates/hcl_templates/functions/numeric/min.mdx
new file mode 100644
index 0000000..64e6971
--- /dev/null
+++ b/v1.9.4/website/content/docs/templates/hcl_templates/functions/numeric/min.mdx
@@ -0,0 +1,27 @@
+---
+page_title: min - Functions - Configuration Language
+description: The min function takes one or more numbers and returns the smallest number.
+---
+
+# `min` Function
+
+`min` takes one or more numbers and returns the smallest number from the set.
+
+## Examples
+
+```shell-session
+> min(12, 54, 3)
+3
+```
+
+If the numbers are in a list or set value, use `...` to expand the collection
+to individual arguments:
+
+```shell-session
+> min([12, 54, 3]...)
+3
+```
+
+## Related Functions
+
+- [`max`](/packer/docs/templates/hcl_templates/functions/numeric/max), which returns the _greatest_ number from a set.
diff --git a/v1.9.4/website/content/docs/templates/hcl_templates/functions/numeric/parseint.mdx b/v1.9.4/website/content/docs/templates/hcl_templates/functions/numeric/parseint.mdx
new file mode 100644
index 0000000..3b8ac24
--- /dev/null
+++ b/v1.9.4/website/content/docs/templates/hcl_templates/functions/numeric/parseint.mdx
@@ -0,0 +1,50 @@
+---
+page_title: parseint - Functions - Configuration Language
+description: >-
+ The parseint function parses the given string as a representation of an
+ integer.
+---
+
+# `parseint` Function
+
+`parseint` parses the given string as a representation of an integer in
+the specified base and returns the resulting number. The base must be between 2
+and 62 inclusive.
+
+All bases use the arabic numerals 0 through 9 first. Bases between 11 and 36
+inclusive use case-insensitive latin letters to represent higher unit values.
+Bases 37 and higher use lowercase latin letters and then uppercase latin
+letters.
+
+If the given string contains any non-digit characters or digit characters that
+are too large for the given base then `parseint` will produce an error.
+
+## Examples
+
+```shell-session
+> parseint("100", 10)
+100
+
+> parseint("FF", 16)
+255
+
+> parseint("-10", 16)
+-16
+
+> parseint("1011111011101111", 2)
+48879
+
+> parseint("aA", 62)
+656
+
+> parseint("12", 2)
+
+Error: Invalid function argument
+
+Invalid value for "number" parameter: cannot parse "12" as a base 2 integer.
+```
+
+## Related Functions
+
+- [`format`](/packer/docs/templates/hcl_templates/functions/string/format) can format numbers and other values into strings,
+ with optional zero padding, alignment, etc.
diff --git a/v1.9.4/website/content/docs/templates/hcl_templates/functions/numeric/pow.mdx b/v1.9.4/website/content/docs/templates/hcl_templates/functions/numeric/pow.mdx
new file mode 100644
index 0000000..e8702cb
--- /dev/null
+++ b/v1.9.4/website/content/docs/templates/hcl_templates/functions/numeric/pow.mdx
@@ -0,0 +1,17 @@
+---
+page_title: pow - Functions - Configuration Language
+description: The pow function raises a number to a power.
+---
+
+# `pow` Function
+
+`pow` calculates an exponent, by raising its first argument to the power of the second argument.
+
+## Examples
+
+```shell-session
+> pow(3, 2)
+9
+> pow(4, 0)
+1
+```
diff --git a/v1.9.4/website/content/docs/templates/hcl_templates/functions/numeric/signum.mdx b/v1.9.4/website/content/docs/templates/hcl_templates/functions/numeric/signum.mdx
new file mode 100644
index 0000000..1caf698
--- /dev/null
+++ b/v1.9.4/website/content/docs/templates/hcl_templates/functions/numeric/signum.mdx
@@ -0,0 +1,20 @@
+---
+page_title: signum - Functions - Configuration Language
+description: The signum function determines the sign of a number.
+---
+
+# `signum` Function
+
+`signum` determines the sign of a number, returning a number between -1 and
+1 to represent the sign.
+
+## Examples
+
+```shell-session
+> signum(-13)
+-1
+> signum(0)
+0
+> signum(344)
+1
+```
diff --git a/v1.9.4/website/content/docs/templates/hcl_templates/functions/string/chomp.mdx b/v1.9.4/website/content/docs/templates/hcl_templates/functions/string/chomp.mdx
new file mode 100644
index 0000000..9586ab2
--- /dev/null
+++ b/v1.9.4/website/content/docs/templates/hcl_templates/functions/string/chomp.mdx
@@ -0,0 +1,27 @@
+---
+page_title: chomp - Functions - Configuration Language
+description: The chomp function removes newline characters at the end of a string.
+---
+
+# `chomp` Function
+
+`chomp` removes newline characters at the end of a string.
+
+This can be useful if, for example, the string was read from a file that has
+a newline character at the end.
+
+## Examples
+
+```shell-session
+> chomp("hello\n")
+hello
+> chomp("hello\r\n")
+hello
+> chomp("hello\n\n")
+hello
+```
+
+## Related Functions
+
+- [`trimspace`](/packer/docs/templates/hcl_templates/functions/string/trimspace), which removes all types of whitespace from
+ both the start and the end of a string.
diff --git a/v1.9.4/website/content/docs/templates/hcl_templates/functions/string/format.mdx b/v1.9.4/website/content/docs/templates/hcl_templates/functions/string/format.mdx
new file mode 100644
index 0000000..7ac645f
--- /dev/null
+++ b/v1.9.4/website/content/docs/templates/hcl_templates/functions/string/format.mdx
@@ -0,0 +1,119 @@
+---
+page_title: format - Functions - Configuration Language
+description: |-
+ The format function produces a string by formatting a number of other values
+ according to a specification string.
+---
+
+# `format` Function
+
+`format` produces a string by formatting a number of other values according
+to a specification string. It is similar to the `printf` function in C, and
+other similar functions in other programming languages.
+
+```hcl
+format(spec, values...)
+```
+
+## Examples
+
+```shell-session
+> format("Hello, %s!", "Ander")
+Hello, Ander!
+> format("There are %d lights", 4)
+There are 4 lights
+```
+
+Simple format verbs like `%s` and `%d` behave similarly to template
+interpolation syntax, which is often more readable:
+
+```shell-session
+> format("Hello, %s!", var.name)
+Hello, Valentina!
+> "Hello, ${var.name}!"
+Hello, Valentina!
+```
+
+The `format` function is therefore more useful when you use more complex format
+specifications, as described in the following section.
+
+## Specification Syntax
+
+The specification is a string that includes formatting verbs that are introduced
+with the `%` character. The function call must then have one additional argument
+for each verb sequence in the specification. The verbs are matched with
+consecutive arguments and formatted as directed, as long as each given argument
+is convertible to the type required by the format verb.
+
+The specification may contain the following verbs:
+
+| Verb | Result |
+| ----- | ----------------------------------------------------------------------------------------- |
+| `%%` | Literal percent sign, consuming no value. |
+| `%v` | Default formatting based on the value type, as described below. |
+| `%#v` | JSON serialization of the value, as with `jsonencode`. |
+| `%t` | Convert to boolean and produce `true` or `false`. |
+| `%b` | Convert to integer number and produce binary representation. |
+| `%d` | Convert to integer number and produce decimal representation. |
+| `%o` | Convert to integer number and produce octal representation. |
+| `%x` | Convert to integer number and produce hexadecimal representation with lowercase letters. |
+| `%X` | Like `%x`, but use uppercase letters. |
+| `%e` | Convert to number and produce scientific notation, like `-1.234456e+78`. |
+| `%E` | Like `%e`, but use an uppercase `E` to introduce the exponent. |
+| `%f` | Convert to number and produce decimal fraction notation with no exponent, like `123.456`. |
+| `%g` | Like `%e` for large exponents or like `%f` otherwise. |
+| `%G` | Like `%E` for large exponents or like `%f` otherwise. |
+| `%s` | Convert to string and insert the string's characters. |
+| `%q` | Convert to string and produce a JSON quoted string representation. |
+
+When `%v` is used, one of the following format verbs is chosen based on the value type:
+
+| Type | Verb |
+| --------- | ----- |
+| `string` | `%s` |
+| `number` | `%g` |
+| `bool` | `%t` |
+| any other | `%#v` |
+
+Null values produce the string `null` if formatted with `%v` or `%#v`, and
+cause an error for other verbs.
+
+A width modifier can be included with an optional decimal number immediately
+preceding the verb letter, to specify how many characters will be used to
+represent the value. Precision can be specified after the (optional) width
+with a period (`.`) followed by a decimal number. If width or precision are
+omitted then default values are selected based on the given value. For example:
+
+| Sequence | Result |
+| -------- | ---------------------------- |
+| `%f` | Default width and precision. |
+| `%9f` | Width 9, default precision. |
+| `%.2f` | Default width, precision 2. |
+| `%9.2f` | Width 9, precision 2. |
+
+The following additional symbols can be used immediately after the `%` symbol
+to set additional flags:
+
+| Symbol | Result |
+| ------ | -------------------------------------------------------------- |
+| space | Leave a space where the sign would be if a number is positive. |
+| `+` | Show the sign of a number even if it is positive. |
+| `-` | Pad the width with spaces on the left rather than the right. |
+| `0` | Pad the width with leading zeros rather than spaces. |
+
+By default, `%` sequences consume successive arguments starting with the first.
+Introducing a `[n]` sequence immediately before the verb letter, where `n` is a
+decimal integer, explicitly chooses a particular value argument by its
+one-based index. Subsequent calls without an explicit index will then proceed
+with `n`+1, `n`+2, etc.
+
+The function produces an error if the format string requests an impossible
+conversion or access more arguments than are given. An error is produced also
+for an unsupported format verb.
+
+## Related Functions
+
+- [`formatdate`](/packer/docs/templates/hcl_templates/functions/datetime/formatdate) is a specialized formatting function for
+ human-readable timestamps.
+- [`formatlist`](/packer/docs/templates/hcl_templates/functions/string/formatlist) uses the same specification syntax to
+ produce a list of strings.
diff --git a/v1.9.4/website/content/docs/templates/hcl_templates/functions/string/formatlist.mdx b/v1.9.4/website/content/docs/templates/hcl_templates/functions/string/formatlist.mdx
new file mode 100644
index 0000000..6d110ae
--- /dev/null
+++ b/v1.9.4/website/content/docs/templates/hcl_templates/functions/string/formatlist.mdx
@@ -0,0 +1,49 @@
+---
+page_title: formatlist - Functions - Configuration Language
+description: |-
+ The formatlist function produces a list of strings by formatting a number of
+ other values according to a specification string.
+---
+
+# `formatlist` Function
+
+`formatlist` produces a list of strings by formatting a number of other
+values according to a specification string.
+
+```hcl
+formatlist(spec, values...)
+```
+
+The specification string uses
+[the same syntax as `format`](/packer/docs/templates/hcl_templates/functions/string/format#specification-syntax).
+
+The given values can be a mixture of list and non-list arguments. Any given
+lists must be the same length, which decides the length of the resulting list.
+
+The list arguments are iterated together in order by index, while the non-list
+arguments are used repeatedly for each iteration. The format string is evaluated
+once per element of the list arguments.
+
+## Examples
+
+```shell-session
+> formatlist("Hello, %s!", ["Valentina", "Ander", "Olivia", "Sam"])
+[
+ "Hello, Valentina!",
+ "Hello, Ander!",
+ "Hello, Olivia!",
+ "Hello, Sam!",
+]
+> formatlist("%s, %s!", "Salutations", ["Valentina", "Ander", "Olivia", "Sam"])
+[
+ "Salutations, Valentina!",
+ "Salutations, Ander!",
+ "Salutations, Olivia!",
+ "Salutations, Sam!",
+]
+```
+
+## Related Functions
+
+- [`format`](/packer/docs/templates/hcl_templates/functions/string/format) defines the specification syntax used by this
+ function and produces a single string as its result.
diff --git a/v1.9.4/website/content/docs/templates/hcl_templates/functions/string/indent.mdx b/v1.9.4/website/content/docs/templates/hcl_templates/functions/string/indent.mdx
new file mode 100644
index 0000000..158a22a
--- /dev/null
+++ b/v1.9.4/website/content/docs/templates/hcl_templates/functions/string/indent.mdx
@@ -0,0 +1,31 @@
+---
+page_title: indent - Functions - Configuration Language
+description: |-
+ The indent function adds a number of spaces to the beginnings of all but the
+ first line of a given multi-line string.
+---
+
+# `indent` Function
+
+`indent` adds a given number of spaces to the beginnings of all but the first
+line in a given multi-line string.
+
+```hcl
+indent(num_spaces, string)
+```
+
+## Examples
+
+This function is useful for inserting a multi-line string into an
+already-indented context in another string:
+
+```shell-session
+> " items: %{indent(2, "[\n foo,\n bar,\n]\n")}"
+ items: [
+ foo,
+ bar,
+ ]
+```
+
+The first line of the string is not indented so that, as above, it can be
+placed after an introduction sequence that has already begun the line.
diff --git a/v1.9.4/website/content/docs/templates/hcl_templates/functions/string/join.mdx b/v1.9.4/website/content/docs/templates/hcl_templates/functions/string/join.mdx
new file mode 100644
index 0000000..acdbaa8
--- /dev/null
+++ b/v1.9.4/website/content/docs/templates/hcl_templates/functions/string/join.mdx
@@ -0,0 +1,29 @@
+---
+page_title: join - Functions - Configuration Language
+description: |-
+ The join function produces a string by concatenating the elements of a list
+ with a given delimiter.
+---
+
+# `join` Function
+
+`join` produces a string by concatenating together all elements of a given
+list of strings with the given delimiter.
+
+```hcl
+join(separator, list)
+```
+
+## Examples
+
+```shell-session
+> join(", ", ["foo", "bar", "baz"])
+foo, bar, baz
+> join(", ", ["foo"])
+foo
+```
+
+## Related Functions
+
+- [`split`](/packer/docs/templates/hcl_templates/functions/string/split) performs the opposite operation: producing a list
+ by separating a single string using a given delimiter.
diff --git a/v1.9.4/website/content/docs/templates/hcl_templates/functions/string/lower.mdx b/v1.9.4/website/content/docs/templates/hcl_templates/functions/string/lower.mdx
new file mode 100644
index 0000000..6548248
--- /dev/null
+++ b/v1.9.4/website/content/docs/templates/hcl_templates/functions/string/lower.mdx
@@ -0,0 +1,26 @@
+---
+page_title: lower - Functions - Configuration Language
+description: >-
+ The lower function converts all cased letters in the given string to
+ lowercase.
+---
+
+# `lower` Function
+
+`lower` converts all cased letters in the given string to lowercase.
+
+## Examples
+
+```shell-session
+> lower("HELLO")
+hello
+> lower("АЛЛО!")
+алло!
+```
+
+This function uses Unicode's definition of letters and of upper- and lowercase.
+
+## Related Functions
+
+- [`upper`](/packer/docs/templates/hcl_templates/functions/string/upper) converts letters in a string to _uppercase_.
+- [`title`](/packer/docs/templates/hcl_templates/functions/string/title) converts the first letter of each word in a string to uppercase.
diff --git a/v1.9.4/website/content/docs/templates/hcl_templates/functions/string/regex.mdx b/v1.9.4/website/content/docs/templates/hcl_templates/functions/string/regex.mdx
new file mode 100644
index 0000000..74d55a6
--- /dev/null
+++ b/v1.9.4/website/content/docs/templates/hcl_templates/functions/string/regex.mdx
@@ -0,0 +1,161 @@
+---
+page_title: regex - Functions - Configuration Language
+description: |-
+ The regex function applies a regular expression to a string and returns the
+ matching substrings.
+---
+
+# `regex` Function
+
+`regex` applies a
+[regular expression](https://en.wikipedia.org/wiki/Regular_expression)
+to a string and returns the matching substrings.
+
+```hcl
+regex(pattern, string)
+```
+
+The return type of `regex` depends on the capture groups, if any, in the
+pattern:
+
+- If the pattern has no capture groups at all, the result is a single string
+ covering the substring matched by the pattern as a whole.
+- If the pattern has one or more _unnamed_ capture groups, the result is a
+ list of the captured substrings in the same order as the definition of
+ the capture groups.
+- If the pattern has one or more _named_ capture groups, the result is a
+ map of the captured substrings, using the capture group names as map keys.
+
+It's not valid to mix both named and unnamed capture groups in the same pattern.
+
+If the given pattern does not match at all, the `regex` raises an error. To
+_test_ whether a given pattern matches a string, use
+[`regexall`](/packer/docs/templates/hcl_templates/functions/string/regexall) and test that the result has length greater than
+zero.
+
+The pattern is a string containing a mixture of literal characters and special
+matching operators as described in the following table. Note that when giving a
+regular expression pattern as a literal quoted string in the Packer
+language, the quoted string itself already uses backslash `\` as an escape
+character for the string, so any backslashes intended to be recognized as part
+of the pattern must be escaped as `\\`.
+
+| Sequence | Matches |
+| --------------------- | -------------------------------------------------------------------------------- |
+| `.` | Any character except newline |
+| `[xyz]` | Any character listed between the brackets (`x`, `y`, and `z` in this example) |
+| `[a-z]` | Any character between `a` and `z`, inclusive |
+| `[^xyz]` | The opposite of `[xyz]` |
+| `\d` | ASCII digits (0 through 9, inclusive) |
+| `\D` | Anything except ASCII digits |
+| `\s` | ASCII spaces (space, tab, newline, carriage return, form feed) |
+| `\S` | Anything except ASCII spaces |
+| `\w` | The same as `[0-9A-Za-z_]` |
+| `\W` | Anything except the characters matched by `\w` |
+| `[[:alnum:]]` | The same as `[0-9A-Za-z]` |
+| `[[:alpha:]]` | The same as `[A-Za-z]` |
+| `[[:ascii:]]` | Any ASCII character |
+| `[[:blank:]]` | ASCII tab or space |
+| `[[:cntrl:]]` | ASCII/Unicode control characters |
+| `[[:digit:]]` | The same as `[0-9]` |
+| `[[:graph:]]` | All "graphical" (printable) ASCII characters |
+| `[[:lower:]]` | The same as `[a-z]` |
+| `[[:print:]]` | The same as `[[:graph:]]` |
+| `[[:punct:]]` | The same as `` [!-/:-@[-`{-~] `` |
+| `[[:space:]]` | The same as `[\t\n\v\f\r ]` |
+| `[[:upper:]]` | The same as `[A-Z]` |
+| `[[:word:]]` | The same as `\w` |
+| `[[:xdigit:]]` | The same as `[0-9A-Fa-f]` |
+| `\pN` | Unicode character class by using single-letter class names ("N" in this example) |
+| `\p{Greek}` | Unicode character class by unicode name ("Greek" in this example) |
+| `\PN` | The opposite of `\pN` |
+| `\P{Greek}` | The opposite of `\p{Greek}` |
+| `xy` | `x` followed immediately by `y` |
+| <code>x|y</code> | either `x` or `y`, preferring `x` |
+| `x*` | zero or more `x`, preferring more |
+| `x*?` | zero or more `x`, preferring fewer |
+| `x+` | one or more `x`, preferring more |
+| `x+?` | one or more `x`, preferring fewer |
+| `x?` | zero or one `x`, preferring one |
+| `x??` | zero or one `x`, preferring zero |
+| `x{n,m}` | between `n` and `m` repetitions of `x`, preferring more |
+| `x{n,m}?` | between `n` and `m` repetitions of `x`, preferring fewer |
+| `x{n,}` | at least `n` repetitions of `x`, preferring more |
+| `x{n,}?` | at least `n` repetitions of `x`, preferring fewer |
+| `x{n}` | exactly `n` repetitions of `x` |
+| `(x)` | unnamed capture group for sub-pattern `x` |
+| `(?P<name>x)` | named capture group, named `name`, for sub-pattern `x` |
+| `(?:x)` | non-capturing sub-pattern `x` |
+| `\*` | Literal `*` for any punctuation character `*` |
+| `\Q...\E` | Literal `...` for any text `...` as long as it does not include literally `\E` |
+
+In addition to the above matching operators that consume the characters they
+match, there are some additional operators that _only_ match, but consume
+no characters. These are "zero-width" matching operators:
+
+| Sequence | Matches |
+| -------- | ------------------------------------------------------------------------------------------------ |
+| `^` | At the beginning of the given string |
+| `$` | At the end of the given string |
+| `\A` | At the beginning of the given string |
+| `\z` | At the end of the given string |
+| `\b` | At an ASCII word boundary (transition between `\w` and either `\W`, `\A` or `\z`, or vice-versa) |
+| `\B` | Not at an ASCII word boundary |
+
+Packer uses the
+[RE2](https://github.com/google/re2/wiki/Syntax) regular expression language.
+This engine does not support all of the features found in some other regular
+expression engines; in particular, it does not support backreferences.
+
+## Matching Flags
+
+Some of the matching behaviors described above can be modified by setting
+matching flags, activated using either the `(?flags)` operator (to activate
+within the current sub-pattern) or the `(?flags:x)` operator (to match `x` with
+the modified flags). Each flag is a single letter, and multiple flags can be
+set at once by listing multiple letters in the `flags` position.
+The available flags are listed in the table below:
+
+| Flag | Meaning |
+| ---- | ----------------------------------------------------------------------------------------------------------------------------------------------------------- |
+| `i` | Case insensitive: a literal letter in the pattern matches both lowercase and uppercase versions of that letter |
+| `m` | The `^` and `$` operators also match the beginning and end of lines within the string, marked by newline characters; behavior of `\A` and `\z` is unchanged |
+| `s` | The `.` operator also matches newline |
+| `U` | The meaning of presence or absense `?` after a repetition operator is inverted. For example, `x*` is interpreted like `x*?` and vice-versa. |
+
+## Examples
+
+```
+> regex("[a-z]+", "53453453.345345aaabbbccc23454")
+aaabbbccc
+
+> regex("(\\d\\d\\d\\d)-(\\d\\d)-(\\d\\d)", "2019-02-01")
+[
+ "2019",
+ "02",
+ "01",
+]
+
+> regex("^(?:(?P<scheme>[^:/?#]+):)?(?://(?P<authority>[^/?#]*))?", "https://packer.io/docs/")
+{
+ "packer" = "packer.io"
+ "scheme" = "https"
+}
+
+> regex("[a-z]+", "53453453.34534523454")
+
+Error: Error in function call
+
+Call to function "regex" failed: pattern did not match any part of the given
+string.
+```
+
+## Related Functions
+
+- [`regexall`](/packer/docs/templates/hcl_templates/functions/string/regexall) searches for potentially multiple matches of a given pattern in a string.
+- [`replace`](/packer/docs/templates/hcl_templates/functions/string/replace) replaces a substring of a string with another string, optionally matching using the same regular expression syntax as `regex`.
+
+If Packer already has a more specialized function to parse the syntax you
+are trying to match, prefer to use that function instead. Regular expressions
+can be hard to read and can obscure your intent, making a configuration harder
+to read and understand.
diff --git a/v1.9.4/website/content/docs/templates/hcl_templates/functions/string/regex_replace.mdx b/v1.9.4/website/content/docs/templates/hcl_templates/functions/string/regex_replace.mdx
new file mode 100644
index 0000000..29d10b8
--- /dev/null
+++ b/v1.9.4/website/content/docs/templates/hcl_templates/functions/string/regex_replace.mdx
@@ -0,0 +1,47 @@
+---
+page_title: regex_replace - Functions - Configuration Language
+description: >-
+ The regex_replace function searches a given string for another given
+ substring,
+
+ and replaces all occurrences with a given replacement string. The substring
+
+ argument can be a valid regular expression or a string.
+---
+
+# `regex_replace` Function
+
+`regex_replace` searches a given string for another given substring, and
+replaces each occurrence with a given replacement string. The substring
+argument can be a valid regular expression or a string.
+
+```hcl
+regex_replace(string, substring, replacement)
+```
+
+`substring` should not be wrapped in forward slashes, it is always treated as a
+regular expression. The `replacement` string can incorporate captured strings
+from the input by using an `$n` or `${n}` sequence, where `n` is the index or
+name of a capture group.
+
+## Examples
+
+```shell-session
+> regex_replace("hello world", "world", "everybody")
+hello everybody
+
+
+> regex_replace("hello world", "w.*d", "everybody")
+hello everybody
+
+> regex_replace("-ab-axxb-", "a(x*)b", "$1W")
+---
+
+> regex_replace("-ab-axxb-", "a(x*)b", "${1}W")
+-W-xxW-
+```
+
+## Related Functions
+
+- [`replace`](/packer/docs/templates/hcl_templates/functions/string/replace) searches a given string for another given
+ substring, and replaces all occurrences with a given replacement string.
diff --git a/v1.9.4/website/content/docs/templates/hcl_templates/functions/string/regexall.mdx b/v1.9.4/website/content/docs/templates/hcl_templates/functions/string/regexall.mdx
new file mode 100644
index 0000000..9690069
--- /dev/null
+++ b/v1.9.4/website/content/docs/templates/hcl_templates/functions/string/regexall.mdx
@@ -0,0 +1,56 @@
+---
+page_title: regexall - Functions - Configuration Language
+description: |-
+ The regexall function applies a regular expression to a string and returns a list of all matches.
+---
+
+# `regexall` Function
+
+`regexall` applies a
+[regular expression](https://en.wikipedia.org/wiki/Regular_expression)
+to a string and returns a list of all matches.
+
+```hcl
+regexall(pattern, string)
+```
+
+`regexall` is a variant of [`regex`](/packer/docs/templates/hcl_templates/functions/string/regex) and uses the same pattern
+syntax. For any given input to `regex`, `regexall` returns a list of whatever
+type `regex` would've returned, with one element per match. That is:
+
+- If the pattern has no capture groups at all, the result is a list of
+ strings.
+- If the pattern has one or more _unnamed_ capture groups, the result is a
+ list of lists.
+- If the pattern has one or more _named_ capture groups, the result is a
+ list of maps.
+
+`regexall` can also be used to test whether a particular string matches a
+given pattern, by testing whether the length of the resulting list of matches
+is greater than zero.
+
+## Examples
+
+```
+> regexall("[a-z]+", "1234abcd5678efgh9")
+[
+ "abcd",
+ "efgh",
+]
+
+> length(regexall("[a-z]+", "1234abcd5678efgh9"))
+2
+
+> length(regexall("[a-z]+", "123456789")) > 0
+false
+```
+
+## Related Functions
+
+- [`regex`](/packer/docs/templates/hcl_templates/functions/string/regex) searches for a single match of a given pattern, and
+ returns an error if no match is found.
+
+If Packer already has a more specialized function to parse the syntax you
+are trying to match, prefer to use that function instead. Regular expressions
+can be hard to read and can obscure your intent, making a configuration harder
+to read and understand.
diff --git a/v1.9.4/website/content/docs/templates/hcl_templates/functions/string/replace.mdx b/v1.9.4/website/content/docs/templates/hcl_templates/functions/string/replace.mdx
new file mode 100644
index 0000000..4097756
--- /dev/null
+++ b/v1.9.4/website/content/docs/templates/hcl_templates/functions/string/replace.mdx
@@ -0,0 +1,30 @@
+---
+page_title: replace - Functions - Configuration Language
+description: |-
+ The replace function searches a given string for another given substring,
+ and replaces all occurrences with a given replacement string.
+---
+
+# `replace` Function
+
+`replace` searches a given string for another given substring, and replaces
+each occurrence with a given replacement string.
+
+```hcl
+replace(string, substring, replacement)
+```
+
+## Examples
+
+```shell-session
+> replace("1 + 2 + 3", "+", "-")
+1 - 2 - 3
+
+> replace("hello world", "world", "everybody")
+hello everybody
+```
+
+## Related Functions
+
+- [`regex_replace`](/packer/docs/templates/hcl_templates/functions/string/regex_replace) searches a given string for another given substring,
+ and replaces each occurrence with a given replacement string.
diff --git a/v1.9.4/website/content/docs/templates/hcl_templates/functions/string/split.mdx b/v1.9.4/website/content/docs/templates/hcl_templates/functions/string/split.mdx
new file mode 100644
index 0000000..677b10a
--- /dev/null
+++ b/v1.9.4/website/content/docs/templates/hcl_templates/functions/string/split.mdx
@@ -0,0 +1,39 @@
+---
+page_title: split - Functions - Configuration Language
+description: |-
+ The split function produces a list by dividing a given string at all
+ occurrences of a given separator.
+---
+
+# `split` Function
+
+`split` produces a list by dividing a given string at all occurrences of a
+given separator.
+
+```hcl
+split(separator, string)
+```
+
+## Examples
+
+```shell-session
+> split(",", "foo,bar,baz")
+[
+ "foo",
+ "bar",
+ "baz",
+]
+> split(",", "foo")
+[
+ "foo",
+]
+> split(",", "")
+[
+ "",
+]
+```
+
+## Related Functions
+
+- [`join`](/packer/docs/templates/hcl_templates/functions/string/join) performs the opposite operation: producing a string
+ joining together a list of strings with a given separator.
diff --git a/v1.9.4/website/content/docs/templates/hcl_templates/functions/string/strrev.mdx b/v1.9.4/website/content/docs/templates/hcl_templates/functions/string/strrev.mdx
new file mode 100644
index 0000000..c543bfe
--- /dev/null
+++ b/v1.9.4/website/content/docs/templates/hcl_templates/functions/string/strrev.mdx
@@ -0,0 +1,26 @@
+---
+page_title: strrev - Functions - Configuration Language
+description: The strrev function reverses a string.
+---
+
+# `strrev` Function
+
+`strrev` reverses the characters in a string.
+Note that the characters are treated as _Unicode characters_ (in technical terms, Unicode [grapheme cluster boundaries](https://unicode.org/reports/tr29/#Grapheme_Cluster_Boundaries) are respected).
+
+```hcl
+strrev(string)
+```
+
+## Examples
+
+```shell-session
+> strrev("hello")
+olleh
+> strrev("a ☃")
+☃ a
+```
+
+## Related Functions
+
+- [`reverse`](/packer/docs/templates/hcl_templates/functions/collection/reverse) reverses a sequence.
diff --git a/v1.9.4/website/content/docs/templates/hcl_templates/functions/string/substr.mdx b/v1.9.4/website/content/docs/templates/hcl_templates/functions/string/substr.mdx
new file mode 100644
index 0000000..594feb2
--- /dev/null
+++ b/v1.9.4/website/content/docs/templates/hcl_templates/functions/string/substr.mdx
@@ -0,0 +1,29 @@
+---
+page_title: substr - Functions - Configuration Language
+description: |-
+ The substr function extracts a substring from a given string by offset and
+ length.
+---
+
+# `substr` Function
+
+`substr` extracts a substring from a given string by offset and length.
+
+```hcl
+substr(string, offset, length)
+```
+
+## Examples
+
+```shell-session
+> substr("hello world", 1, 4)
+ello
+```
+
+The offset and length are both counted in _unicode characters_ rather than
+bytes:
+
+```shell-session
+> substr("🤔🤷", 0, 1)
+🤔
+```
diff --git a/v1.9.4/website/content/docs/templates/hcl_templates/functions/string/title.mdx b/v1.9.4/website/content/docs/templates/hcl_templates/functions/string/title.mdx
new file mode 100644
index 0000000..15d40f3
--- /dev/null
+++ b/v1.9.4/website/content/docs/templates/hcl_templates/functions/string/title.mdx
@@ -0,0 +1,24 @@
+---
+page_title: title - Functions - Configuration Language
+description: |-
+ The title function converts the first letter of each word in a given string
+ to uppercase.
+---
+
+# `title` Function
+
+`title` converts the first letter of each word in the given string to uppercase.
+
+## Examples
+
+```shell-session
+> title("hello world")
+Hello World
+```
+
+This function uses Unicode's definition of letters and of upper- and lowercase.
+
+## Related Functions
+
+- [`upper`](/packer/docs/templates/hcl_templates/functions/string/upper) converts _all_ letters in a string to uppercase.
+- [`lower`](/packer/docs/templates/hcl_templates/functions/string/lower) converts all letters in a string to lowercase.
diff --git a/v1.9.4/website/content/docs/templates/hcl_templates/functions/string/trim.mdx b/v1.9.4/website/content/docs/templates/hcl_templates/functions/string/trim.mdx
new file mode 100644
index 0000000..321a46e
--- /dev/null
+++ b/v1.9.4/website/content/docs/templates/hcl_templates/functions/string/trim.mdx
@@ -0,0 +1,25 @@
+---
+page_title: trim - Functions - Configuration Language
+description: |-
+ The trim function removes the specified characters from the start and end of
+ a given string.
+---
+
+# `trim` Function
+
+`trim` removes the specified characters from the start and end of the given
+string.
+
+## Examples
+
+```shell-session
+> trim("?!hello?!", "!?")
+hello
+```
+
+## Related Functions
+
+- [`trimprefix`](/packer/docs/templates/hcl_templates/functions/string/trimprefix) removes a word from the start of a string.
+- [`trimsuffix`](/packer/docs/templates/hcl_templates/functions/string/trimsuffix) removes a word from the end of a string.
+- [`trimspace`](/packer/docs/templates/hcl_templates/functions/string/trimspace) removes all types of whitespace from
+ both the start and the end of a string.
diff --git a/v1.9.4/website/content/docs/templates/hcl_templates/functions/string/trimprefix.mdx b/v1.9.4/website/content/docs/templates/hcl_templates/functions/string/trimprefix.mdx
new file mode 100644
index 0000000..f9396ed
--- /dev/null
+++ b/v1.9.4/website/content/docs/templates/hcl_templates/functions/string/trimprefix.mdx
@@ -0,0 +1,24 @@
+---
+page_title: trimprefix - Functions - Configuration Language
+description: |-
+ The trimprefix function removes the specified prefix from the start of a
+ given string.
+---
+
+# `trimprefix` Function
+
+`trimprefix` removes the specified prefix from the start of the given string.
+
+## Examples
+
+```shell-session
+> trimprefix("helloworld", "hello")
+world
+```
+
+## Related Functions
+
+- [`trim`](/packer/docs/templates/hcl_templates/functions/string/trim) removes characters at the start and end of a string.
+- [`trimsuffix`](/packer/docs/templates/hcl_templates/functions/string/trimsuffix) removes a word from the end of a string.
+- [`trimspace`](/packer/docs/templates/hcl_templates/functions/string/trimspace) removes all types of whitespace from
+ both the start and the end of a string.
diff --git a/v1.9.4/website/content/docs/templates/hcl_templates/functions/string/trimspace.mdx b/v1.9.4/website/content/docs/templates/hcl_templates/functions/string/trimspace.mdx
new file mode 100644
index 0000000..a1f6190
--- /dev/null
+++ b/v1.9.4/website/content/docs/templates/hcl_templates/functions/string/trimspace.mdx
@@ -0,0 +1,27 @@
+---
+page_title: trimspace - Functions - Configuration Language
+description: |-
+ The trimspace function removes space characters from the start and end of
+ a given string.
+---
+
+# `trimspace` Function
+
+`trimspace` removes any space characters from the start and end of the given
+string.
+
+This function follows the Unicode definition of "space", which includes
+regular spaces, tabs, newline characters, and various other space-like
+characters.
+
+## Examples
+
+```shell-session
+> trimspace(" hello\n\n")
+hello
+```
+
+## Related Functions
+
+- [`chomp`](/packer/docs/templates/hcl_templates/functions/string/chomp) removes just line ending characters from the _end_ of
+ a string.
diff --git a/v1.9.4/website/content/docs/templates/hcl_templates/functions/string/trimsuffix.mdx b/v1.9.4/website/content/docs/templates/hcl_templates/functions/string/trimsuffix.mdx
new file mode 100644
index 0000000..e69644c
--- /dev/null
+++ b/v1.9.4/website/content/docs/templates/hcl_templates/functions/string/trimsuffix.mdx
@@ -0,0 +1,24 @@
+---
+page_title: trimsuffix - Functions - Configuration Language
+description: |-
+ The trimsuffix function removes the specified suffix from the end of a
+ given string.
+---
+
+# `trimsuffix` Function
+
+`trimsuffix` removes the specified suffix from the end of the given string.
+
+## Examples
+
+```shell-session
+> trimsuffix("helloworld", "world")
+hello
+```
+
+## Related Functions
+
+- [`trim`](/packer/docs/templates/hcl_templates/functions/string/trim) removes characters at the start and end of a string.
+- [`trimprefix`](/packer/docs/templates/hcl_templates/functions/string/trimprefix) removes a word from the start of a string.
+- [`trimspace`](/packer/docs/templates/hcl_templates/functions/string/trimspace) removes all types of whitespace from
+ both the start and the end of a string.
diff --git a/v1.9.4/website/content/docs/templates/hcl_templates/functions/string/upper.mdx b/v1.9.4/website/content/docs/templates/hcl_templates/functions/string/upper.mdx
new file mode 100644
index 0000000..7a6bb0a
--- /dev/null
+++ b/v1.9.4/website/content/docs/templates/hcl_templates/functions/string/upper.mdx
@@ -0,0 +1,26 @@
+---
+page_title: upper - Functions - Configuration Language
+description: >-
+ The upper function converts all cased letters in the given string to
+ uppercase.
+---
+
+# `upper` Function
+
+`upper` converts all cased letters in the given string to uppercase.
+
+## Examples
+
+```shell-session
+> upper("hello")
+HELLO
+> upper("алло!")
+АЛЛО!
+```
+
+This function uses Unicode's definition of letters and of upper- and lowercase.
+
+## Related Functions
+
+- [`lower`](/packer/docs/templates/hcl_templates/functions/string/lower) converts letters in a string to _lowercase_.
+- [`title`](/packer/docs/templates/hcl_templates/functions/string/title) converts the first letter of each word in a string to uppercase.
diff --git a/v1.9.4/website/content/docs/templates/hcl_templates/functions/uuid/uuidv4.mdx b/v1.9.4/website/content/docs/templates/hcl_templates/functions/uuid/uuidv4.mdx
new file mode 100644
index 0000000..d3135ae
--- /dev/null
+++ b/v1.9.4/website/content/docs/templates/hcl_templates/functions/uuid/uuidv4.mdx
@@ -0,0 +1,27 @@
+---
+page_title: v4 - uuid - Functions - Configuration Language
+description: The uuidv4 function generates a unique ID.
+---
+
+# `uuidv4` Function
+
+`uuidv4` generates a unique identifier string.
+
+The ID is a generated and formatted as required by [RFC 4122 section
+4.4](https://tools.ietf.org/html/rfc4122#section-4.4), producing a Version 4
+UUID. The result is a UUID generated only from pseudo-random numbers.
+
+This function produces a new value each time it is called, and so using it
+directly in resource arguments will result in spurious diffs. We do not
+recommend using the `uuidv4` function in resource configurations.
+
+## Examples
+
+```shell-session
+> uuidv4()
+b5ee72a3-54dd-c4b8-551c-4bdc0204cedb
+```
+
+## Related Functions
+
+- [`uuidv5`](/packer/docs/templates/hcl_templates/functions/uuid/uuidv5), which generates name-based UUIDs.
diff --git a/v1.9.4/website/content/docs/templates/hcl_templates/functions/uuid/uuidv5.mdx b/v1.9.4/website/content/docs/templates/hcl_templates/functions/uuid/uuidv5.mdx
new file mode 100644
index 0000000..310b4b1
--- /dev/null
+++ b/v1.9.4/website/content/docs/templates/hcl_templates/functions/uuid/uuidv5.mdx
@@ -0,0 +1,78 @@
+---
+page_title: uuidv5 - Functions - Configuration Language
+description: |-
+ The uuidv5 function generates a uuid v5 string representation of the value in
+ the specified namespace.
+---
+
+# `uuidv5` Function
+
+`uuidv5` generates a _name-based_ UUID, as described in [RFC 4122 section
+4.3](https://tools.ietf.org/html/rfc4122#section-4.3), also known as a "version
+5" UUID.
+
+```hcl
+uuidv5(namespace, name)
+```
+
+Unlike the pseudo-random UUIDs generated by [`uuidv4`](/packer/docs/templates/hcl_templates/functions/uuid/uuidv4),
+name-based UUIDs derive from namespace and an name, producing the same UUID
+value every time if the namespace and name are unchanged.
+
+Name-based UUID namespaces are themselves UUIDs, but for readability this
+function accepts some keywords as aliases for the namespaces that were assigned
+by RFC 4122:
+
+| Keyword | Namespace ID | Name format |
+| -------- | -------------------------------------- | ---------------------------------------------------------------------------- |
+| `"dns"` | `6ba7b810-9dad-11d1-80b4-00c04fd430c8` | A fully-qualified DNS domain name. |
+| `"url"` | `6ba7b811-9dad-11d1-80b4-00c04fd430c8` | Any valid URL as defined in [RFC 3986](https://tools.ietf.org/html/rfc3986). |
+| `"oid"` | `6ba7b812-9dad-11d1-80b4-00c04fd430c8` | An [ISO/IEC object identifier](https://oidref.com/) |
+| `"x500"` | `6ba7b814-9dad-11d1-80b4-00c04fd430c8` | [X.500 Distinguished Name](https://tools.ietf.org/html/rfc1779) |
+
+To use any other namespace not included in the above table, pass its assigned
+namespace ID directly in the first argument in the usual UUID string format.
+
+## Examples
+
+Use the namespace keywords where possible, to make the intent more obvious to
+a future reader:
+
+```shell-session
+> uuidv5("dns", "www.packer.io")
+a5008fae-b28c-5ba5-96cd-82b4c53552d6
+
+> uuidv5("url", "https://www.packer.io/")
+9db6f67c-dd95-5ea0-aa5b-e70e5c5f7cf5
+
+> uuidv5("oid", "1.3.6.1.4")
+af9d40a5-7a36-5c07-b23a-851cd99fbfa5
+
+> uuidv5("x500", "CN=Example,C=GB")
+84e09961-4aa4-57f8-95b7-03edb1073253
+```
+
+The namespace keywords treated as equivalent to their corresponding namespace
+UUIDs, and in some special cases it may be more appropriate to use the
+UUID form:
+
+```shell-session
+> uuidv5("6ba7b810-9dad-11d1-80b4-00c04fd430c8", "www.packer.io")
+a5008fae-b28c-5ba5-96cd-82b4c53552d6
+```
+
+If you wish to use a namespace defined outside of RFC 4122, using the namespace
+UUID is required because no corresponding keyword is available:
+
+```shell-session
+> uuidv5("743ac3c0-3bf7-4a5b-9e6c-59360447c757", "LIBS:diskfont.library")
+ede1a974-df7e-5f17-84b9-76208818b2c8
+```
+
+When using raw UUID namespaces, consider including a comment alongside the
+expression that indicates which namespace this represents in a
+human-significant manner, such as by reference to the standard that defined it.
+
+## Related Functions
+
+- [`uuidv4`](/packer/docs/templates/hcl_templates/functions/uuid/uuidv4), which generates pseudorandom UUIDs.
diff --git a/v1.9.4/website/content/docs/templates/hcl_templates/index.mdx b/v1.9.4/website/content/docs/templates/hcl_templates/index.mdx
new file mode 100644
index 0000000..72d845f
--- /dev/null
+++ b/v1.9.4/website/content/docs/templates/hcl_templates/index.mdx
@@ -0,0 +1,76 @@
+---
+page_title: HCL Templates
+description: |-
+ Packer uses text files to describe infrastructure and to set variables.
+ These text files are called Packer _configurations_ and are
+ written in the HCL2 HashiCorp Configuration Language.
+---
+
+# HCL Configuration Language
+
+`@include 'from-1.5/beta-hcl2-note.mdx'`
+
+Packer uses the HashiCorp Configuration Language - HCL - designed to allow
+concise descriptions of the required steps to get to a build file. This page
+describes the features of HCL2 exhaustively, if you would like to give a quick
+try to HCL2, you can also read the quicker [HCL2 getting started
+guide](/packer/guides/hcl).
+
+## Builds
+
+The main purpose of the HCL language is defining builds and sources. All other
+language features exist only to make the definition of builds more flexible and
+convenient.
+
+`packer build` takes one argument. When a directory is passed, all files in the
+folder with a name ending with `.pkr.hcl` or `.pkr.json` will be parsed using
+the HCL2 format. When a file ending with `.pkr.hcl` or `.pkr.json` is passed it
+will be parsed using the HCL2 schema. For every other case; the _JSON only_ old
+packer schema will be used.
+
+## Arguments, Blocks, and Expressions
+
+The syntax of the HCL language consists of only a few basic elements:
+
+```hcl
+source "amazon-ebs" "main" {
+ ami_name = "main-ami"
+}
+
+<BLOCK TYPE> "<BLOCK LABEL>" "<BLOCK LABEL>" {
+ # Block body
+ <IDENTIFIER> = <EXPRESSION> # Argument
+}
+```
+
+- _Blocks_ are containers for other content and usually represent the
+ configuration of some kind of object, like a source. Blocks have a
+ _block type,_ can have zero or more _labels,_ and have a _body_ that contains
+ any number of arguments and nested blocks. Most of Packer's features are
+ controlled by top-level blocks in a configuration file.
+- _Arguments_ assign a value to a name. They appear within blocks.
+- _Expressions_ represent a value, either literally or by referencing and
+ combining other values. They appear as values for arguments, or within other
+ expressions.
+
+For full details about Packer's syntax, see:
+
+- [Configuration Syntax](/packer/docs/templates/hcl_templates/syntax)
+- [Expressions](/packer/docs/templates/hcl_templates/expressions)
+
+## Code Organization
+
+The HCL language uses configuration files that are named with the `.pkr.hcl`
+file extension. There is also [a JSON-based variant of the
+language](/packer/docs/templates/hcl_templates/syntax-json) that is named with the `.pkr.json` file
+extension.
+
+Configuration files must always use UTF-8 encoding, and by convention are
+usually maintained with Unix-style line endings (LF) rather than Windows-style
+line endings (CRLF), though both are accepted.
+
+## Configuration Ordering
+
+The ordering of root blocks is not significant. The order of `provisioner` or
+`post-processor` blocks within a `build` is the only major feature where block
+order matters.
diff --git a/v1.9.4/website/content/docs/templates/hcl_templates/locals.mdx b/v1.9.4/website/content/docs/templates/hcl_templates/locals.mdx
new file mode 100644
index 0000000..456f6af
--- /dev/null
+++ b/v1.9.4/website/content/docs/templates/hcl_templates/locals.mdx
@@ -0,0 +1,132 @@
+---
+page_title: Local Variables - HCL Configuration Language
+description: >-
+ Local variables assign a name to an expression that you can use multiple
+ times within a folder.
+---
+
+# Local Variables
+
+`@include 'from-1.5/beta-hcl2-note.mdx'`
+
+There are two kinds of variables in HCL Packer templates: Input variables,
+sometimes simply called "variables", and Local variables, also known as
+"locals". Input variables may have defaults, but those defaults can be
+overridden using command line options, environment variables, or variable
+definitions files. Local variables can not be overridden.
+
+This page is about local variables. To learn about input variables, see the
+[input variables](/packer/docs/templates/hcl_templates/variables) page.
+
+Local variables assign a name to an expression, which you can use multiple
+times within a folder. The expression is evaluated at run time, and can
+reference input variables, other local variables, data sources, and HCL
+functions.
+
+Input variable and local variable usage are introduced in the [_Variables
+Guide_](/packer/guides/hcl/variables).
+
+## Examples
+
+Local variables are defined in a `local` or `locals` block:
+
+```hcl
+# Using the local block allows you to mark locals as sensitive, which will
+# filter their values from logs.
+local "mylocal" {
+ expression = "${var.secret_api_key}"
+ sensitive = true
+}
+
+# Using the locals block is more compact and efficient for declaring many locals
+# Ids for multiple sets of EC2 instances, merged together
+locals {
+ instance_ids = "${concat(aws_instance.blue.*.id, aws_instance.green.*.id)}"
+}
+
+# A computed default name prefix
+locals {
+ default_name_prefix = "${var.project_name}-web"
+ name_prefix = "${var.name_prefix != "" ? var.name_prefix : local.default_name_prefix}"
+}
+
+# Local variables can be referenced using the "local." prefix.
+source "virtualbox-iso" "example" {
+ output = "${local.name_prefix}-files"
+ # ...
+}
+```
+
+Named local maps can be merged with local maps to implement common or default
+values:
+
+```hcl
+# Define the common tags for all resources
+locals {
+ common_tags = {
+ Component = "awesome-app"
+ Environment = "production"
+ }
+}
+
+# Create a resource that blends the common tags with instance-specific tags.
+source "amazon-ebs" "server" {
+ source_ami = "ami-123456"
+ instance_type = "t2.micro"
+
+ tags = "${merge(
+ local.common_tags,
+ {
+ "Name" = "awesome-app-server",
+ "Role" = "server"
+ }
+ )}"
+ # ...
+}
+```
+
+## Single `local` block
+
+The `local` block defines exactly one local variable within a folder. The block
+label is the name of the local, and the "expression" is the expression that
+should be evaluated to create the local. Using this block, you can optionally
+supply a "sensitive" boolean to mark the variable as sensitive and filter it
+from logs.
+
+```hcl
+local "mylocal" {
+ expression = "${var.secret_api_key}"
+ sensitive = true
+}
+```
+
+This block is also very useful for defining complex locals. Packer might take some time to expand and evaluate `locals`
+with complex expressions dependent on other locals. The `locals` block is read as a map. Maps are not sorted, and therefore
+the evaluation time is not deterministic.
+
+To avoid that, singular `local` blocks should be used instead. These will be
+evaluated in the order they are defined, and the evaluation order and time will always be the same.
+
+## `locals` block
+
+The `locals` block defines one or more local variables within a folder.
+
+The names given for the items in the `locals` block must be unique throughout a
+folder. The given value can be any expression that is valid within the current
+folder.
+
+The expression of a local value can refer to other locals, but reference cycles
+are not allowed. That is, a local cannot refer to itself or to a variable that
+refers (directly or indirectly) back to it.
+
+It's recommended to group together logically-related local variables into a single
+block, particularly if they depend on each other. This will help the reader
+understand the relationships between variables. Conversely, prefer to define
+_unrelated_ local variables in _separate_ blocks, and consider annotating each
+block with a comment describing any context common to all of the enclosed
+locals.
+
+## Known Limitations
+`@include 'datasources/local-dependency-limitation.mdx'`
+
+
diff --git a/v1.9.4/website/content/docs/templates/hcl_templates/onlyexcept.mdx b/v1.9.4/website/content/docs/templates/hcl_templates/onlyexcept.mdx
new file mode 100644
index 0000000..3aab108
--- /dev/null
+++ b/v1.9.4/website/content/docs/templates/hcl_templates/onlyexcept.mdx
@@ -0,0 +1,80 @@
+---
+page_title: Only Except - HCL Configuration Language
+description: >-
+ Only and Except can be used as a command line argument to selectively run
+ builds. Only and Except can also be used in a provisioner to not run it for a
+ source.
+---
+
+# Only and Except
+
+`only` and `except` are keywords used to filter what runs in your Packer build,
+they can be seen as a command line argument:
+
+`@include 'commands/except.mdx'`
+
+`@include 'commands/only.mdx'`
+
+They can also be seen in a template to run or skip provisioners and/or
+post-processors for a specific source:
+
+```hcl
+source "amazon-ebs" "first-example" {
+}
+
+source "amazon-ebs" "second-example" {
+}
+
+source "amazon-ebs" "third-example" {
+}
+
+build {
+ name = "my_build"
+ sources = [
+ "source.amazon-ebs.first-example",
+ ]
+ source "source.amazon-ebs.second-example" {
+ // setting the name field allows you to rename the source only for this
+ // build section. To match this builder, you need to use
+ // second-example-local-name, not second-example
+ name = "second-example-local-name"
+ }
+
+ provisioner "shell-local" {
+ only = ["amazon-ebs.first-example"]
+ inline = ["echo I will only run for the first example source"]
+ }
+
+ provisioner "shell-local" {
+ except = ["amazon-ebs.second-example-local-name"]
+ inline = ["echo I will never run for the second example source"]
+ }
+}
+
+build {
+ sources = [
+ "source.amazon-ebs.third-example",
+ ]
+}
+
+# this file will result in Packer creating three builds named:
+# my_build.amazon-ebs.first-example
+# my_build.amazon-ebs.second-example
+# amazon-ebs.third-example
+```
+
+Note that cli arguments can be used with a glob operator, using the previous
+configuration:
+
+- `packer build -only 'my_build.*' dir`: will only run the builds in blocks
+ named `my_build`.
+
+- `packer build -only '*.amazon-ebs.*' dir`: will only run the builds with a
+ source of type `amazon-ebs`.
+
+- `packer build -only '*.second-example-local-name' dir`: will only run that
+ specifically named build.
+
+-> Note: In the cli `only` and `except` will match against **build names** (for
+example:`my_build.amazon-ebs.first-example`) but in a provisioner they will
+match on the **source name** (for example:`amazon-ebs.third-example`).
diff --git a/v1.9.4/website/content/docs/templates/hcl_templates/path-variables.mdx b/v1.9.4/website/content/docs/templates/hcl_templates/path-variables.mdx
new file mode 100644
index 0000000..fb9b74d
--- /dev/null
+++ b/v1.9.4/website/content/docs/templates/hcl_templates/path-variables.mdx
@@ -0,0 +1,40 @@
+---
+page_title: Path Variables - HCL Configuration Language
+description: |-
+ Special variables provide directory information. This page covers all path
+ variables.
+---
+
+`@include 'path/separator-note.mdx'`
+
+# Path variables
+
+- `path.cwd`: the directory from where Packer was started.
+
+- `path.root`: the directory of the input HCL file or the input folder.
+
+## Examples
+
+```HCL
+locals {
+ settings_file = "${path.cwd}/settings.txt"
+ scripts_folder = "${path.root}/scripts"
+ root = path.root
+}
+```
+
+## Related Functions
+
+- [`abspath`](/packer/docs/templates/hcl_templates/functions/file/abspath) takes a string containing
+ a filesystem path and converts it to an absolute path.
+
+- [`basename`](/packer/docs/templates/hcl_templates/functions/file/basename) returns _only_ the last
+ portion of a filesystem path, discarding the portion that would be returned
+ by `dirname`.
+
+- [`fileset`](/packer/docs/templates/hcl_templates/functions/file/fileset) enumerates a set of
+ regular file names given a path and pattern.
+
+- [`dirname`](/packer/docs/templates/hcl_templates/functions/file/dirname) returns all of the
+ segments of a filesystem path _except_ the last, discarding the portion that
+ would be returned by `basename`.
diff --git a/v1.9.4/website/content/docs/templates/hcl_templates/syntax-json.mdx b/v1.9.4/website/content/docs/templates/hcl_templates/syntax-json.mdx
new file mode 100644
index 0000000..414f864
--- /dev/null
+++ b/v1.9.4/website/content/docs/templates/hcl_templates/syntax-json.mdx
@@ -0,0 +1,308 @@
+---
+page_title: JSON Configuration Syntax - Configuration Language
+description: |-
+ In addition to the native syntax that is most commonly used with Packer,
+ the HCL language can also be expressed in a JSON-compatible syntax.
+---
+
+# JSON Configuration Syntax
+
+`@include 'from-1.5/beta-hcl2-note.mdx'`
+
+Most Packer configurations are written in [the native HCL
+syntax](/packer/docs/templates/hcl_templates/syntax), which is designed to be easy for humans to read and
+update.
+
+Packer also supports an alternative syntax that is JSON-compatible. This
+syntax is useful when generating portions of a configuration programmatically,
+since existing JSON libraries can be used to prepare the generated
+configuration files.
+
+This syntax is not to be confused with the pre-version-1.5 "legacy" Packer
+templates, which were exclusively JSON and follow a different format.
+
+The JSON syntax is defined in terms of the native syntax. Everything that can
+be expressed in native syntax can also be expressed in JSON syntax, but some
+constructs are more complex to represent in JSON due to limitations of the
+JSON grammar.
+
+Packer expects native syntax for files named with a `.pkr.hcl` suffix, and JSON
+syntax for files named with a `.pkr.json` suffix. If you leave out the `.pkr`
+portion of suffix, Packer will try to read your json file as a legacy Packer
+template.
+
+The low-level JSON syntax, just as with the native syntax, is defined in terms
+of a specification called _HCL_. It is not necessary to know all of the details
+of HCL syntax or its JSON mapping in order to use Packer, and so this page
+summarizes the most important differences between native and JSON syntax. If
+you are interested, you can find a full definition of HCL's JSON syntax in [its
+specification](https://github.com/hashicorp/hcl/blob/hcl2/hclsyntax/spec.md).
+
+## JSON File Structure
+
+At the root of any JSON-based Packer configuration is a JSON object. The
+properties of this object correspond to the top-level block types of the
+Packer language. For example:
+
+```json
+{
+ "variables": {
+ "example": "value"
+ }
+}
+```
+
+Each top-level object property must match the name of one of the expected
+top-level block types. Block types that expect labels, such as `variable` shown
+above, are represented by one nested object value for each level of label.
+`source` blocks expect two labels, so two levels of nesting are required:
+
+```json
+{
+ "source": {
+ "amazon-ebs": {
+ "example": {
+ "instance_type": "t2.micro",
+ "ami_name": "ami-abc123"
+ }
+ }
+ }
+}
+```
+
+After any nested objects representing the labels, finally one more nested
+object represents the body of the block itself. In the above example the
+`instance_type` and `ami_name` arguments for `source "amazon-ebs" "example"`
+are specified.
+
+Taken together, the above two configuration files are equivalent to the
+following blocks in the native syntax:
+
+```hcl
+variables {
+ example = "value"
+}
+
+source "amazon-ebs" "example" {
+ instance_type = "t2.micro"
+ ami_name = "ami-abc123"
+}
+```
+
+Within each top-level block type the rules for mapping to JSON are slightly
+different (see [block-type-specific exceptions](#block-type-specific-exceptions) below), but the following general rules apply in most cases:
+
+- The JSON object representing the block body contains properties that
+ correspond either to argument names or to nested block type names.
+
+- Where a property corresponds to an argument that accepts
+ [arbitrary expressions](/packer/docs/templates/hcl_templates/expressions) in the native syntax, the
+ property value is mapped to an expression as described under
+ [_Expression Mapping_](#expression-mapping) below. For arguments that
+ do _not_ accept arbitrary expressions, the interpretation of the property
+ value depends on the argument, as described in the
+ [block-type-specific exceptions](#block-type-specific-exceptions)
+ given later in this page.
+
+- Where a property name corresponds to an expected nested block type name,
+ the value is interpreted as described under
+ [_Nested Block Mapping_](#nested-block-mapping) below, unless otherwise
+ stated in [the block-type-specific exceptions](#block-type-specific-exceptions)
+ given later in this page.
+
+## Expression Mapping
+
+Since JSON grammar is not able to represent all of the Packer language
+[expression syntax](/packer/docs/templates/hcl_templates/expressions), JSON values interpreted as expressions
+are mapped as follows:
+
+| JSON | Packer Language Interpretation |
+| ------- | -------------------------------------------------------------------------------------------------------------------------------- |
+| Boolean | A literal `bool` value. |
+| Number | A literal `number` value. |
+| String | Parsed as a [string template](/packer/docs/templates/hcl_templates/expressions#string-templates) and then evaluated as described below. |
+| Object | Each property value is mapped per this table, producing an `object(...)` value with suitable attribute types. |
+| Array | Each element is mapped per this table, producing a `tuple(...)` value with suitable element types. |
+| Null | A literal `null`. |
+
+When a JSON string is encountered in a location where arbitrary expressions are
+expected, its value is first parsed as a [string template](/packer/docs/templates/hcl_templates/expressions#string-templates)
+and then it is evaluated to produce the final result.
+
+If the given template consists _only_ of a single interpolation sequence,
+the result of its expression is taken directly, without first converting it
+to a string. This allows non-string expressions to be used within the
+JSON syntax.
+
+## Nested Block Mapping
+
+When a JSON object property is named after a nested block type, the value
+of this property represents one or more blocks of that type. The value of
+the property must be either a JSON object or a JSON array.
+
+The simplest situation is representing only a single block of the given type
+when that type expects no labels, as with the `tags` nested block used
+within `source` blocks:
+
+```json
+{
+ "source": {
+ "amazon-ebs": {
+ "example": {
+ "tags": {
+ "key": "value"
+ }
+ }
+ }
+ }
+}
+```
+
+The above is equivalent to the following native syntax configuration:
+
+```hcl
+source "amazon-ebs" "example" {
+ tags = {
+ key = "value"
+ }
+}
+```
+
+When the nested block type requires one or more labels, or when multiple
+blocks of the same type can be given, the mapping gets a little more
+complicated. For example, the `provisioner` nested block type used
+within `build` blocks expects a label giving the provisioner to use,
+and the ordering of provisioner blocks is significant to decide the order
+of operations.
+
+The following native syntax example shows a `build` block with a number
+of provisioners of different types:
+
+```hcl
+build {
+ # (source configuration omitted for brevity)
+
+ provisioner "shell-local" {
+ inline = ["echo 'Hello World' >example.txt"]
+ }
+ provisioner "file" {
+ source = "example.txt"
+ destination = "/tmp/example.txt"
+ }
+ provisioner "shell" {
+ inline = [
+ "sudo install-something -f /tmp/example.txt",
+ ]
+ }
+}
+```
+
+In order to preserve the order of these blocks, you must use a JSON array
+as the direct value of the property representing this block type, as in
+this JSON equivalent of the above:
+
+```json
+{
+ "build": {
+ "//": "(source configuration omitted for brevity)",
+
+ "provisioner": [
+ {
+ "shell-local": {
+ "inline": ["echo 'Hello World' >example.txt"]
+ }
+ },
+ {
+ "file": {
+ "source": "example.txt",
+ "destination": "/tmp/example.txt"
+ }
+ },
+ {
+ "shell": {
+ "inline": ["sudo install-something -f /tmp/example.txt"]
+ }
+ }
+ ]
+ }
+}
+```
+
+Each element of the `provisioner` array is an object with a single property
+whose name represents the label for each `provisioner` block. For block types
+that expect multiple labels, this pattern of alternating array and object
+nesting can be used for each additional level.
+
+If a nested block type requires labels but the order does _not_ matter, you
+may omit the array and provide just a single object whose property names
+correspond to unique block labels. This is allowed as a shorthand for the above
+for simple cases, but the alternating array and object approach is the most
+general. We recommend using the most general form if systematically converting
+from native syntax to JSON, to ensure that the meaning of the configuration is
+preserved exactly.
+
+### Comment Properties
+
+Although we do not recommend hand-editing of JSON syntax configuration files
+-- this format is primarily intended for programmatic generation and consumption --
+a limited form of _comments_ are allowed inside JSON objects that represent
+block bodies using a special property name:
+
+```json
+{
+ "source": {
+ "amazon-ebs": {
+ "example": {
+ "//": "This instance runs the scheduled tasks for backup",
+
+ "instance_type": "t2.micro",
+ "ami_name": "ami-abc123"
+ }
+ }
+ }
+}
+```
+
+In any object that represents a block body, properties named `"//"` are
+ignored by Packer entirely. This exception does _not_ apply to objects
+that are being [interpreted as expressions](#expression-mapping), where this
+would be interpreted as an object type attribute named `"//"`.
+
+This special property name can also be used at the root of a JSON-based
+configuration file. This can be useful to note which program created the file.
+
+```json
+{
+ "//": "This file is generated by generate-outputs.py. DO NOT HAND-EDIT!"
+}
+```
+
+## Block-type-specific Exceptions
+
+[inpage-block]: #block-type-specific-exceptions
+
+Certain arguments within specific block types are processed in a special way,
+and so their mapping to the JSON syntax does not follow the general rules
+described above. The following sub-sections describe the special mapping rules
+that apply to each top-level block type.
+
+### `variable` blocks
+
+All arguments inside `variable` blocks have non-standard mappings to JSON:
+
+- `type`: a string containing a type expression, like `"string"` or `"list(string)"`.
+- `default`: a literal JSON value that can be converted to the given type.
+ Strings within this value are taken literally and _not_ interpreted as
+ string templates.
+- `description`: a literal JSON string, _not_ interpreted as a template.
+
+```json
+{
+ "variable": {
+ "example": {
+ "type": "string",
+ "default": "hello"
+ }
+ }
+}
+```
diff --git a/v1.9.4/website/content/docs/templates/hcl_templates/syntax.mdx b/v1.9.4/website/content/docs/templates/hcl_templates/syntax.mdx
new file mode 100644
index 0000000..7ed024e
--- /dev/null
+++ b/v1.9.4/website/content/docs/templates/hcl_templates/syntax.mdx
@@ -0,0 +1,119 @@
+---
+page_title: Syntax - Configuration Language
+description: |-
+ HCL has its own syntax, intended to combine declarative
+ structure with expressions in a way that is easy for humans to read and
+ understand.
+---
+
+# HCL Configuration Syntax
+
+`@include 'from-1.5/beta-hcl2-note.mdx'`
+
+Other pages in this section have described various configuration constructs
+that can appear in HCL. This page describes the lower-level syntax of the
+language in more detail, revealing the building blocks that those constructs
+are built from.
+
+This page describes the _native syntax_ of HCL, which is a rich language
+designed to be easy for humans to read and write. The constructs in HCL can
+also be expressed in [JSON syntax](/packer/docs/templates/hcl_templates/syntax-json), which is harder for
+humans to read and edit but easier to generate and parse programmatically.
+
+This low-level syntax of HCL is defined in terms of a syntax called _HCL_,
+which is also used by configuration languages in other applications, and in
+particular other HashiCorp products. It is not necessary to know all of the
+details of HCL in order to use Packer, and so this page summarizes the most
+important details. If you are interested, you can find a full definition of HCL
+syntax in [the HCL native syntax
+specification](https://github.com/hashicorp/hcl/blob/hcl2/hclsyntax/spec.md).
+
+## Arguments and Blocks
+
+HCL syntax is built around two key syntax constructs:
+arguments and blocks.
+
+### Arguments
+
+An _argument_ assigns a value to a particular name:
+
+```hcl
+image_id = "abc123"
+```
+
+The identifier before the equals sign is the _argument name_, and the expression
+after the equals sign is the argument's value.
+
+The context where the argument appears determines what value types are valid
+(for example, each source type has a schema that defines the types of its
+arguments), but many arguments accept arbitrary
+[expressions](/packer/docs/templates/hcl_templates/expressions), which allow the value to
+either be specified literally or generated from other values programmatically.
+
+### Blocks
+
+A _block_ is a container for other content:
+
+```hcl
+source "amazon-ebs" "example" {
+ ami_name = "abc123"
+
+ tags = {
+ # ...
+ }
+}
+```
+
+A block has a _type_ (`source` in this example). Each block type defines
+how many _labels_ must follow the type keyword. The `source` block type
+expects two labels, which are `amazon-ebs` and `example` in the example above.
+A particular block type may have any number of required labels, or it may
+require none as with the nested `tags` block type.
+
+After the block type keyword and any labels, the block _body_ is delimited
+by the `{` and `}` characters. Within the block body, further arguments
+and blocks may be nested, creating a hierarchy of blocks and their associated
+arguments.
+
+HCL uses a limited number of _top-level block types,_ which
+are blocks that can appear outside of any other block in a configuration file.
+Most of Packer's features (including resources, input variables, output
+values, data sources, etc.) are implemented as top-level blocks.
+
+## Identifiers
+
+Argument names, block type names, and the names of most Packer-specific
+constructs like resources, input variables, etc. are all _identifiers_.
+
+Identifiers can contain letters, digits, underscores (`_`), and hyphens (`-`).
+The first character of an identifier must not be a digit, to avoid ambiguity
+with literal numbers.
+
+For complete identifier rules, Packer implements
+[the Unicode identifier syntax](http://unicode.org/reports/tr31/), extended to
+include the ASCII hyphen character `-`.
+
+## Comments
+
+HCL supports three different syntaxes for comments:
+
+- `#` begins a single-line comment, ending at the end of the line.
+- `//` also begins a single-line comment, as an alternative to `#`.
+- `/*` and `*/` are start and end delimiters for a comment that might span
+ over multiple lines.
+
+The `#` single-line comment style is the default comment style and should be
+used in most cases. Automatic configuration formatting tools may automatically
+transform `//` comments into `#` comments, since the double-slash style is
+not idiomatic.
+
+## Character Encoding and Line Endings
+
+Packer configuration files must always be UTF-8 encoded. While the
+delimiters of the language are all ASCII characters, Packer accepts
+non-ASCII characters in identifiers, comments, and string values.
+
+Packer accepts configuration files with either Unix-style line endings
+(LF only) or Windows-style line endings (CR then LF), but the idiomatic style
+is to use the Unix convention, and so automatic configuration formatting tools
+may automatically transform CRLF endings to LF.
diff --git a/v1.9.4/website/content/docs/templates/hcl_templates/variables.mdx b/v1.9.4/website/content/docs/templates/hcl_templates/variables.mdx
new file mode 100644
index 0000000..4c8f856
--- /dev/null
+++ b/v1.9.4/website/content/docs/templates/hcl_templates/variables.mdx
@@ -0,0 +1,339 @@
+---
+page_title: Input Variables - HCL Configuration Language
+description: |-
+ Input variables are parameters for Packer modules.
+ This page covers configuration syntax for variables.
+---
+
+# Input Variables
+
+`@include 'from-1.5/beta-hcl2-note.mdx'`
+
+There are two kinds of variables in HCL Packer templates: Input variables,
+sometimes simply called "variables", and Local variables, also known as
+"locals". Input variables may have defaults, but those defaults can be
+overridden using command line options, environment variables, or variable
+definitions files. However, nothing can change the value of an input variable
+after the initial override.
+
+This page is about input variables. To learn about local variables, see the
+[locals](/packer/docs/templates/hcl_templates/locals) page.
+
+Input variables serve as parameters for a Packer build, allowing aspects of the
+build to be customized without altering the build's own source code.
+
+Input variable and local variable usage are introduced in the [_Variables
+Guide_](/packer/guides/hcl/variables).
+
+-> **Note:** For brevity, input variables are often referred to as just
+"variables" or "Packer variables" when it is clear from context what sort of
+variable is being discussed. Other kinds of variables in Packer include
+_environment variables_ (set by the shell where Packer runs) and _expression
+variables_ (used to indirectly represent a value in an
+[expression](/packer/docs/templates/hcl_templates/expressions)).
+
+## Declaring an Input Variable
+
+Each input variable accepted by a build must be declared using a `variable`
+block :
+
+```hcl
+variable "image_id" {
+ type = string
+}
+
+variable "availability_zone_names" {
+ type = list(string)
+ default = ["us-west-1a"]
+}
+
+variable "docker_ports" {
+ type = list(object({
+ internal = number
+ external = number
+ protocol = string
+ }))
+ default = [
+ {
+ internal = 8300
+ external = 8300
+ protocol = "tcp"
+ }
+ ]
+}
+```
+
+Or a less precise variables block:
+
+```hcl
+variables {
+ foo = "value"
+ my_secret = "foo"
+}
+```
+
+The label after the `variable` keyword or a label of a `variables` block is a
+name for the variable, which must be unique among all variables in the same
+build. This name is used to assign a value to the variable from outside and to
+reference the variable's value from within the build.
+
+
+## Arguments
+
+Packer defines the following arguments for variable declarations:
+
+* [`default`][inpage-default] - A default value which then makes the variable optional.
+* [`type`][inpage-type] - This argument specifies what value types are accepted for the variable.
+* [`description`][inpage-description] - This specifies the input variable's documentation.
+* [`validation`][inpage-validation] - A block to define validation rules, usually in addition to type constraints.
+* [`sensitive`][inpage-sensitive] - This causes string-values from that variable to be obfuscated from Packer's output.
+
+
+
+### Default values
+
+[inpage-default]: #default-values
+
+The variable declaration can also include a `default` argument. If present,
+the variable is considered to be _optional_ and the default value will be used
+if no value is set when running Packer. The `default`
+argument requires a literal value and cannot reference other objects in the
+configuration.
+
+
+### Type Constraints
+[inpage-type]: #type-constraints
+
+The `type` argument in a `variable` block allows you to restrict the [type of
+value](/packer/docs/templates/hcl_templates/expressions#types-and-values) that will be accepted as the value
+for a variable. If no type constraint is set then a value of any type is
+accepted.
+
+While type constraints are optional, we recommend specifying them; they serve
+as easy reminders for users of the build, and allow Packer to return a helpful
+error message if the wrong type is used.
+
+Type constraints are created from a mixture of type keywords and type
+constructors. The supported type keywords are:
+
+- `string`
+- `number`
+- `bool`
+
+The type constructors allow you to specify complex types such as collections:
+
+- `list(<TYPE>)`
+- `set(<TYPE>)`
+- `map(<TYPE>)`
+- `object({<ATTR NAME> = <TYPE>, ... })`
+- `tuple([<TYPE>, ...])`
+
+The keyword `any` may be used to indicate that any type is acceptable. For more
+information on the meaning and behavior of these different types, as well as
+detailed information about automatic conversion of complex types, see [Type
+Constraints](/terraform/docs/configuration/types).
+
+If both the `type` and `default` arguments are specified, the given default
+value must be convertible to the specified type.
+
+If only `default` is specified, the type of the default value will be used.
+
+When the `type` and `default` are both _not_ specified and you try to set a
+variable [from env vars](#environment-variables) or [from the command
+line](#variables-on-the-command-line), the variable will always be interpreted
+as a string.
+
+### Input Variable Documentation
+
+[inpage-description]: #input-variable-documentation
+
+Because the input variables of a build are part of its user interface, you can
+briefly describe the purpose of each variable using the optional `description`
+argument:
+
+```hcl
+variable "image_id" {
+ type = string
+ description = "The ID of the machine image (AMI) to use for the server."
+}
+```
+
+The description should concisely explain the purpose of the variable and what
+kind of value is expected. This description string might be included in
+documentation about the build, and so it should be written from the perspective
+of the user of the build rather than its maintainer. For commentary for build
+maintainers, use comments.
+
+`@include 'from-1.5/variables/custom-validation.mdx'`
+
+`@include 'from-1.5/variables/sensitive.mdx'`
+
+
+## Using Input Variable Values
+
+Within the build that declared a variable, its value can be accessed from
+within [expressions](/packer/docs/templates/hcl_templates/expressions) as `var.<NAME>`, where `<NAME>`
+matches the label given in the declaration block:
+
+```hcl
+source "googlecompute" "debian" {
+ zone = var.gcp_zone
+ tags = var.gcp_debian_tags
+}
+```
+
+The value assigned to a variable can be accessed only from expressions within
+the folder where it was declared.
+
+
+`@include 'from-1.5/variables/assignment.mdx'`
+
+The following sections describe these options in more detail.
+
+### Variables on the Command Line
+
+To specify individual variables on the command line, use the `-var` option when
+running the `packer build` command:
+
+```shell-session
+$ packer build -var="image_id=ami-abc123"
+$ packer build -var='image_id_list=["ami-abc123","ami-def456"]'
+$ packer build -var='image_id_map={"us-east-1":"ami-abc123","us-east-2":"ami-def456"}'
+```
+
+The `-var` option can be used any number of times in a single command.
+
+If you plan to assign variables via the command line, we strongly recommend that
+you at least set a default type instead of using empty blocks; this helps the
+HCL parser understand what is being set. Otherwise, the interpreter will assume
+that any variable set on the command line is a string.
+
+### Standard Variable Definitions Files
+
+To set lots of variables, it is more convenient to specify their values in a
+_variable definitions file_ with a filename ending in either `.pkrvars.hcl` or
+`.pkrvars.json` and then specify that file on the command line with
+`-var-file`:
+
+```shell-session
+$ packer build -var-file="testing.pkrvars.hcl"
+```
+
+A variable definitions file uses the same basic syntax as Packer language
+files, but consists only of variable name and its assigned values:
+
+```hcl
+image_id = "ami-abc123"
+availability_zone_names = [
+ "us-east-1a",
+ "us-west-1c",
+]
+```
+
+~> **Important**: Unlike legacy JSON templates the input variables within a variable definitions file must be declared
+via a variables block within a standard HCL2 template file `*.pkr.hcl` before it can be assigned a value.
+Failure to do so will result in an unknown variable error during Packer's runtime.
+
+### Auto-loaded Variable Definitions Files
+
+Packer also has the ability automatically load one or more variable definitions files if they
+are present:
+
+- Any files with names ending in `.auto.pkrvars.hcl` or `.auto.pkrvars.json`.
+
+Files whose names end with `.json` are parsed as JSON objects instead of HCL,
+with the root object properties corresponding to variable names:
+
+```json
+{
+ "image_id": "ami-abc123",
+ "availability_zone_names": ["us-west-1a", "us-west-1c"]
+}
+```
+
+~> **Important**: Unlike legacy JSON templates the input variables within a variable definitions file must be declared
+via a variables block within a standard HCL2 template file `*.pkr.hcl` before it can be assigned a value.
+Failure to do so will result in an unknown variable error during Packer's runtime.
+
+
+### Environment Variables
+
+As a fallback for the other ways of defining variables, Packer searches the
+environment of its own process for environment variables named `PKR_VAR_`
+followed by the name of a declared variable.
+
+This can be useful when running Packer in automation, or when running a
+sequence of Packer commands in succession with the same variables. For example,
+at a `bash` prompt on a Unix system:
+
+```shell-session
+$ export PKR_VAR_image_id=ami-abc123
+$ packer build gcp/debian/
+...
+```
+
+On operating systems where environment variable names are case-sensitive,
+Packer matches the variable name exactly as given in configuration, and so the
+required environment variable name will usually have a mix of upper and lower
+case letters as in the above example.
+
+### Complex-typed Values
+
+When variable values are provided in a variable definitions file, Packer's
+[usual syntax](/packer/docs/templates/hcl_templates/expressions) can be used to assign
+complex-typed values, like lists and maps.
+
+Some special rules apply to the `-var` command line option and to environment
+variables. For convenience, Packer defaults to interpreting `-var` and
+environment variable values as literal strings, which do not need to be quoted:
+
+```shell-session
+$ export PKR_VAR_image_id=ami-abc123
+```
+
+However, if a build variable uses a [type constraint](#type-constraints) to
+require a complex value (list, set, map, object, or tuple), Packer will instead
+attempt to parse its value using the same syntax used within variable
+definitions files, which requires careful attention to the string escaping
+rules in your shell:
+
+```shell-session
+$ export PKR_VAR_availability_zone_names='["us-west-1b","us-west-1d"]'
+```
+
+For readability, and to avoid the need to worry about shell escaping, we
+recommend always setting complex variable values via variable definitions
+files.
+
+### Variable Definition Precedence
+
+The above mechanisms for setting variables can be used together in any
+combination.
+
+Packer loads variables in the following order, with later sources taking
+precedence over earlier ones:
+
+- Environment variables (lowest priority)
+- Any `*.auto.pkrvars.hcl` or `*.auto.pkrvars.json` files, processed in lexical
+ order of their filenames.
+- Any `-var` and `-var-file` options on the command line, in the order they are
+ provided. (highest priority)
+
+If the same variable is assigned multiple values using different mechanisms,
+Packer uses the _last_ value it finds, overriding any previous values. Note
+that the same variable cannot be assigned multiple values within a single source.
+
+~> **Important:** Variables with map and object values behave the same way as
+other variables: the last value found overrides the previous values.
+
+`@include 'from-1.5/variables/must-be-set.mdx'`
+
+### Setting an unknown variable will not always fail:
+
+| Usage | packer validate | any other packer command |
+| :----------------------------: | :---------------------: | :-----------------------: |
+| `bar=yz` in .pkrvars.hcl file. | error, "bar undeclared" | warning, "bar undeclared" |
+| `var.bar` in .pkr.hcl file | error, "bar undeclared" | error, "bar undeclared" |
+| `-var bar=yz` argument | error, "bar undeclared" | error, "bar undeclared" |
+| `export PKR_VAR_bar=yz` | - | - |
+
diff --git a/v1.9.4/website/content/docs/templates/index.mdx b/v1.9.4/website/content/docs/templates/index.mdx
new file mode 100644
index 0000000..b3c0ccd
--- /dev/null
+++ b/v1.9.4/website/content/docs/templates/index.mdx
@@ -0,0 +1,31 @@
+---
+description: |
+ This section describes the configuration language used to create Packer
+ templates.
+page_title: Templates
+---
+
+# Packer Templates
+
+Packer's behavior is determined by the Packer template, which consists of a
+series of declarations and commands for Packer to follow. This template tells
+Packer what plugins (builders, provisioners, post-processors) to use, how to
+configure each of those plugins, and what order to run them in.
+
+The template contains flexible variable injection tools, as well as built-in
+functions to help you customize your builds.
+
+Historically, Packer has used a JSON template for its configuration, but Packer
+is transitioning to a new template configuration format that uses HCL2 -- the
+same configuration language used by Terraform and HashiCorp's other products.
+This format is more flexible, more modular, and more concise than the original
+JSON template format. While the JSON format is still supported, certain
+new features in the Packer core will only be implemented for the newer HCL
+format. Please use the side bar to find documentation for the different
+template formats.
+
+From version **1.7.0**, HCL2 becomes officially the preferred way to write Packer
+configuration(s).
+
+If you need help upgrading a JSON template to an HCL template, check
+our upgrade guide [here](/packer/tutorials/configuration-language/hcl2-upgrade).
diff --git a/v1.9.4/website/content/docs/templates/json_to_hcl.mdx b/v1.9.4/website/content/docs/templates/json_to_hcl.mdx
new file mode 100644
index 0000000..2be5668
--- /dev/null
+++ b/v1.9.4/website/content/docs/templates/json_to_hcl.mdx
@@ -0,0 +1,158 @@
+---
+description: |
+ This section highlights the differences between JSON and HCL2 templates and explains the parallels between the specifications.
+page_title: JSON to HCL
+---
+
+# Packer templates
+
+Packer uses templates to orchestrate builds for one or more images.
+In [legacy JSON templates](/packer/docs/templates/legacy_json_templates), you would declare a series of builders, provisioners and post-processors to build images.
+In [HCL2 templates](/packer/docs/templates/hcl_templates), things are different, as the configuration language allows you to specify builders through sources, and weave them in build blocks.
+
+This document aims to explain the parallels between the two configuration template types, and what you
+should expect when moving a template away from JSON to HCL2.
+
+In addition to this document, you may find the `packer hcl2_upgrade` command useful when converting your existing JSON templates to HCL2.
+Refer to the [hcl2_upgrade](/packer/docs/commands/hcl2_upgrade) page for more information on its usage.
+
+## Builders
+
+Builders are components that are specialized for a platform.
+Their role is to set the stage for the steps that will let you build the final image from your configuration template.
+
+### JSON
+
+In JSON, the `builders` attribute declares how a builder will be invoked to build an image.
+
+```json
+{
+ "builders": [
+ {
+ "type": "null",
+ "name": "test",
+ "communicator": "none"
+ }
+ ]
+}
+```
+
+### HCL2
+
+In HCL2, builders are declared through a `source` block. Sources on their own are not enough, and must be invoked in a `build` block.
+The `build` block serves as a container for all the steps (i.e. `source`, `provisioners` and `post-processors`) to go from a blank image to a finished one.
+
+```hcl
+source "null" "test" {
+ communicator = "none"
+}
+
+build {
+ sources = ["null.test"]
+}
+```
+
+## Provisioners
+
+Provisioners are components that modify the state of the machine image you are building.
+They can be used for installing packages, writing data to the remote file system, or executing remote commands.
+They can be defined in both JSON or HCL templates.
+
+### JSON
+
+In a JSON template, provisioners are declared at the top-level of the template as an array of sequentially
+invoked components to provision the image you are building. They apply to all the builders defined in the template.
+
+```json
+{
+ "builders": [
+ {
+ "type": "null",
+ "name": "test",
+ "communicator": "none"
+ }
+ ],
+ "provisioners": [
+ {
+ "type": "shell-local",
+ "inline": ["echo test"]
+ }
+ ]
+}
+```
+
+### HCL2
+
+In HCL2, provisioners are declared in the `build` block, and apply only to the sources invoked as
+part of this build block.
+This lets you declare multiple build blocks, each with its own set of provisioners, which will
+result in multiple different builds executed in parallel.
+
+```hcl
+source "null" "test" {
+ communicator = "none"
+}
+
+build {
+ sources = ["null.test"]
+
+ provisioner "shell-local" {
+ inline = ["echo test"]
+ }
+}
+```
+
+## Post-processors
+
+Post-processors are components that are invoked after the image was produced. Their
+role is to consume an artifact produced by a builder, or another post-processor, and
+build a new artifact from that.
+
+### JSON
+
+As with provisioners, in JSON templates, post-processors are sequentially invoked after a
+build finished provisioning, and are declared in the template under "post-processors".
+
+```json
+{
+ "builders": [
+ {
+ "type": "null",
+ "name": "test",
+ "communicator": "none"
+ }
+ ],
+ "provisioners": [
+ {
+ "type": "shell-local",
+ "inline": ["echo test"]
+ }
+ ],
+ "post-processors": [
+ {
+ "type": "manifest"
+ }
+ ]
+}
+```
+
+### HCL2
+
+In HCL2, much like provisioners, they are also part of the `build` block, and similar rules
+apply as with provisioners.
+
+```hcl
+source "null" "test" {
+ communicator = "none"
+}
+
+build {
+ sources = ["null.test"]
+
+ provisioner "shell-local" {
+ inline = ["echo test"]
+ }
+
+ post-processor "manifest" {}
+}
+```
diff --git a/v1.9.4/website/content/docs/templates/legacy_json_templates/builders.mdx b/v1.9.4/website/content/docs/templates/legacy_json_templates/builders.mdx
new file mode 100644
index 0000000..42d3afa
--- /dev/null
+++ b/v1.9.4/website/content/docs/templates/legacy_json_templates/builders.mdx
@@ -0,0 +1,78 @@
+---
+description: >
+ Within the template, the builders section contains an array of all the
+ builders
+
+ that Packer should use to generate machine images for the template.
+page_title: Builders - Templates
+---
+
+`@include 'from-1.5/legacy-json-warning.mdx'`
+
+# Template Builders
+
+Within the template, the builders section contains an array of all the builders
+that Packer should use to generate machine images for the template.
+
+Builders are responsible for creating machines and generating images from them
+for various platforms. For example, there are separate builders for EC2,
+VMware, VirtualBox, etc. Packer comes with many builders by default, and can
+also be extended to add new builders.
+
+This documentation page will cover how to configure a builder in a template.
+The specific configuration options available for each builder, however, must be
+referenced from the documentation for that specific builder.
+
+Within a template, a section of builder definitions looks like this:
+
+```json
+{
+ "builders": [
+ // ... one or more builder definitions here
+ ]
+}
+```
+
+## Builder Definition
+
+A single builder definition maps to exactly one
+[build](/packer/docs/terminology#builds). A builder definition is a
+JSON object that requires at least a `type` key. The `type` is the name of the
+builder that will be used to create a machine image for the build.
+
+In addition to the `type`, other keys configure the builder itself. For
+example, the AWS builder requires an `access_key`, `secret_key`, and some other
+settings. These are placed directly within the builder definition.
+
+An example builder definition is shown below, in this case configuring the AWS
+builder:
+
+```json
+{
+ "type": "amazon-ebs",
+ "access_key": "...",
+ "secret_key": "..."
+}
+```
+
+## Named Builds
+
+Each build in Packer has a name. By default, the name is just the name of the
+builder being used. In general, this is good enough. Names only serve as an
+indicator in the output of what is happening. If you want, however, you can
+specify a custom name using the `name` key within the builder definition.
+
+This is particularly useful if you have multiple builds defined that use the
+same underlying builder. In this case, you must specify a name for at least one
+of them since the names must be unique.
+
+## Communicators
+
+Every build is associated with a single
+[communicator](/packer/docs/templates/legacy_json_templates/communicator). Communicators are used to
+establish a connection for provisioning a remote machine (such as an AWS
+instance or local virtual machine).
+
+All the examples for the various builders show some communicator (usually SSH),
+but the communicators are highly customizable so we recommend reading the
+[communicator documentation](/packer/docs/templates/legacy_json_templates/communicator).
diff --git a/v1.9.4/website/content/docs/templates/legacy_json_templates/communicator.mdx b/v1.9.4/website/content/docs/templates/legacy_json_templates/communicator.mdx
new file mode 100644
index 0000000..a1c32a9
--- /dev/null
+++ b/v1.9.4/website/content/docs/templates/legacy_json_templates/communicator.mdx
@@ -0,0 +1,52 @@
+---
+description: |
+ Communicators are the mechanism Packer uses to upload files, execute scripts,
+ etc. with the machine being created.
+page_title: Communicators - Templates
+---
+
+`@include 'from-1.5/legacy-json-warning.mdx'`
+
+# Template Communicators
+
+Communicators are the mechanism Packer uses to upload files, execute scripts,
+etc. with the machine being created.
+
+Communicators are configured within the
+[builder](/packer/docs/templates/legacy_json_templates/builders) section.
+
+All communicators have the following options:
+
+@include 'packer-plugin-sdk/communicator/Config-not-required.mdx'
+
+## Getting Ready to Use the Communicator
+
+Depending on your builder, your communicator may not have all it needs in order
+to work "out of the box".
+
+If you are building from a cloud image (for example, building on Amazon), there
+is a good chance that your cloud provider has already preconfigured SSH on the
+image for you, meaning that all you have to do is configure the communicator in
+the Packer template.
+
+However, if you are building from a brand-new and unconfigured operating system
+image, you will almost always have to perform some extra work to configure SSH
+on the guest machine. For most operating system distributions, this work will
+be performed by a [boot_command](/packer/plugins/builders/vmware/iso#boot-configuration) that references a file which
+provides answers to the normally-interactive questions you get asked when
+installing an operating system. The name of this file varies by operating
+system; some common examples are the "preseed" file required by Debian, the
+"kickstart" file required by CentOS or the "answer file", also known as the
+Autounattend.xml file, required by Windows. For simplicity's sake, we'll refer
+to this file as the "preseed" file in the rest of the documentation.
+
+If you are unfamiliar with how to use a preseed file for automatic
+bootstrapping of an image, please either take a look at our quick guides to
+image bootstrapping, or research automatic configuration for your specific
+guest operating system. Knowing how to automatically initalize your operating
+system is critical for being able to successfully use Packer.
+
+## Communicator-Specific Options
+
+For more details on how to use each communicator, visit the
+[communicators](/packer/docs/communicators) page.
diff --git a/v1.9.4/website/content/docs/templates/legacy_json_templates/engine.mdx b/v1.9.4/website/content/docs/templates/legacy_json_templates/engine.mdx
new file mode 100644
index 0000000..e603320
--- /dev/null
+++ b/v1.9.4/website/content/docs/templates/legacy_json_templates/engine.mdx
@@ -0,0 +1,382 @@
+---
+description: |
+ All strings within templates are processed by a common Packer templating
+ engine, where variables and functions can be used to modify the value of a
+ configuration parameter at runtime.
+page_title: Template Engine - Templates
+---
+
+# Template Engine
+
+All strings within templates are processed by a common Packer templating
+engine, where variables and functions can be used to modify the value of a
+configuration parameter at runtime.
+
+`@include 'from-1.5/legacy-json-warning.mdx'`
+
+The syntax of templates uses the following conventions:
+
+- Anything template related happens within double-braces: `{{ }}`.
+- Functions are specified directly within the braces, such as
+ `{{timestamp}}`.
+- Template variables are prefixed with a period and capitalized, such as
+ `{{.Variable}}`.
+
+## Functions
+
+Functions perform operations on and within strings, for example the
+`{{timestamp}}` function can be used in any string to generate the current
+timestamp. This is useful for configurations that require unique keys, such as
+AMI names. By setting the AMI name to something like `My Packer AMI {{timestamp}}`, the AMI name will be unique down to the second. If you need
+greater than one second granularity, you should use `{{uuid}}`, for example
+when you have multiple builders in the same template.
+
+Here is a full list of the available functions for reference.
+
+- `build_name` - The name of the build being run.
+- `build_type` - The type of the builder being used currently.
+- `clean_resource_name` - Image names can only contain certain characters and
+ have a maximum length, eg 63 on GCE & 80 on Azure. `clean_resource_name`
+ will convert upper cases to lower cases and replace illegal characters with
+ a "-" character. Example:
+
+ `"mybuild-{{isotime | clean_resource_name}}"` will become `mybuild-2017-10-18t02-06-30z`.
+
+ Note: Valid Azure image names must match the regex
+ `^[^_\\W][\\w-._)]{0,79}$`
+
+ Note: Valid GCE image names must match the regex
+ `(?:[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?)`
+
+ This engine does not guarantee that the final image name will match the
+ regex; it will not truncate your name if it exceeds the maximum number of
+ allowed characters, and it will not validate that the beginning and end of
+ the engine's output are valid. For example, `"image_name": {{isotime | clean_resource_name}}"` will cause your build to fail because the image
+ name will start with a number, which is why in the above example we prepend
+ the isotime with "mybuild".
+ Exact behavior of `clean_resource_name` will depend on which builder it is
+ being applied to; refer to build-specific docs below for more detail on how
+ each function will behave.
+
+- `env` - Returns environment variables. See example in [using home
+ variable](/packer/docs/templates/legacy_json_templates/user-variables#using-home-variable)
+- `build` - This engine will allow you to access, from provisioners and post-processors, special variables that
+ provide connection information and basic instance state information.
+ Usage example:
+
+ ```json
+ {
+ "type": "shell-local",
+ "environment_vars": ["TESTVAR={{ build `PackerRunUUID`}}"],
+ "inline": ["echo $TESTVAR"]
+ }
+ ```
+
+ Valid variables to request are:
+
+ - **ID**: Represents the VM being provisioned. For example, in Amazon it is the instance ID; in DigitalOcean,
+ it is the Droplet ID; in VMware, it is the VM name.
+
+ - **Host**, **Port**, **User** and **Password**: The host, port, user, and password that Packer uses to access the machine.
+ Useful for using the shell local provisioner to run Ansible or Inspec against the provisioned instance.
+
+ - **ConnType**: Type of communicator being used. For example, for SSH communicator this will be "ssh".
+
+ - **PackerRunUUID**: Current build's unique ID. Can be used to specify build artifacts.
+ An example of that, is when multiple builds runs at the same time producing the same artifact.
+ It's possible to differentiate these artifacts by naming them with the builds' unique IDs.
+
+ - **PackerHTTPIP**, **PackerHTTPPort**, and **PackerHTTPAddr**: HTTP IP, port, and address of the file server Packer creates to serve items in the "http" dir to the VM. The HTTP address is displayed in the format `IP:PORT`.
+
+ - **SSHPublicKey** and **SSHPrivateKey**: The public and private key that Packer uses to connect to the instance.
+ These are unique to the SSH communicator and are unset when using other communicators.
+ **SSHPublicKey** and **SSHPrivateKey** can have escape sequences and special characters so their output should be single quoted to avoid surprises. For example:
+
+ ```json
+ { ... "provisioners": [{
+ "type": "shell",
+ "inline": [ "echo '{{ build `SSHPrivateKey`}}' > /tmp/packer-session.pem" ]
+ }]
+ }
+ ```
+
+ For backwards compatibility, `WinRMPassword` is also available through this
+ engine, though it is no different than using the more general `Password`.
+
+ This function is only for use within specific options inside of
+ _provisioners_ -- these options will be listed as being template engines
+ in the provisioner documentation.
+
+ For builder-specific builder variables, please also refer to the builder docs:
+
+ - Amazon EC2: [chroot](/packer/plugins/builders/amazon/chroot#build-shared-information-variables),
+ [EBS Volume](/packer/plugins/builders/amazon/ebsvolume#build-shared-information-variables),
+ [EBS](/packer/plugins/builders/amazon/ebs#build-shared-information-variables),
+ [EBS Surrogate](/packer/plugins/builders/amazon/ebssurrogate#build-shared-information-variables),
+ [Instance](/packer/plugins/builders/amazon/instance#build-shared-information-variables).
+
+ This engine is in beta; please report any issues or requests on the Packer
+ issue tracker on GitHub.
+
+- `isotime [FORMAT]` - UTC time, which can be
+ [formatted](https://pkg.go.dev/time#example_Time_Format). See more
+ examples below in [the `isotime` format
+ reference](/packer/docs/templates/legacy_json_templates/engine#isotime-function-format-reference).
+ `strftime FORMAT` - UTC time, formated using the ISO C standard format
+ `FORMAT`. See
+ [jehiah/go-strftime](https://github.com/jehiah/go-strftime) for a list
+ of available format specifiers.
+
+ Please note that if you are using a large number of builders,
+ provisioners or post-processors, using the isotime engine directly in the
+ plugin configuration may cause the timestamp to be slightly diffferent for
+ each plugin. This is because the timestamp is generated when each plugin is
+ launched rather than in the initial Packer process. In order to avoid this
+ and make sure the timestamp is consistent across all plugins, set it as a user
+ variable and then access the user variable within your plugins.
+
+- `lower` - Lowercases the string.
+- `packer_version` - Returns Packer version.
+- `pwd` - The working directory while executing Packer.
+- `replace` - ( old, new string, n int, s ) Replace returns a copy of the
+ string s with the first n non-overlapping instances of old replaced by new.
+- `replace_all` - ( old, new string, s ) ReplaceAll returns a copy of the
+ string s with all non-overlapping instances of old replaced by new.
+- `split` - Split an input string using separator and return the requested
+ substring.
+- `template_dir` - The directory to the template for the build.
+- `timestamp` - The Unix timestamp in UTC when the Packer process was
+ launched. Please note that if you are using a large number of builders,
+ provisioners or post-processors, the timestamp may be slightly
+ different for each one because it is from when the plugin is
+ launched not the initial Packer process. In order to avoid this and make
+ the timestamp consistent across all plugins, set it as a user variable
+ and then access the user variable within your plugins.
+- `uuid` - Returns a random UUID.
+- `upper` - Uppercases the string.
+- `user` - Specifies a user variable.
+
+#### Specific to Amazon builders:
+
+- `clean_resource_name` - AMI names
+ can only contain certain characters. This function will replace illegal
+ characters with a '-" character. Example usage since ":" is not a legal AMI
+ name is: `{{isotime | clean_resource_name}}`.
+
+#### Specific to Google Compute builders:
+
+- `clean_resource_name` - GCE
+ image names can only contain certain characters and the maximum length is
+
+ 63. This function will convert upper cases to lower cases and replace
+ illegal characters with a "-" character. Example:
+
+ `"mybuild-{{isotime | clean_resource_name}}"` will become
+ `mybuild-2017-10-18t02-06-30z`.
+
+ Note: Valid GCE image names must match the regex
+ `(?:[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?)`
+
+ This engine does not guarantee that the final image name will match the
+ regex; it will not truncate your name if it exceeds 63 characters, and it
+ will not validate that the beginning and end of the engine's output are
+ valid. For example, `"image_name": {{isotime | clean_resource_name}}"` will
+ cause your build to fail because the image name will start with a number,
+ which is why in the above example we prepend the isotime with "mybuild".
+
+#### Specific to Azure builders:
+
+- `clean_resource_name` - Azure
+ managed image names can only contain certain characters and the maximum
+ length is 80. This function will replace illegal characters with a "-"
+ character. Example:
+
+ `"mybuild-{{isotime | clean_resource_name}}"` will become
+ `mybuild-2017-10-18t02-06-30z`.
+
+ Note: Valid Azure image names must match the regex
+ `^[^_\\W][\\w-._)]{0,79}$`
+
+ This engine does not guarantee that the final image name will match the
+ regex; it will not truncate your name if it exceeds 80 characters, and it
+ will not validate that the beginning and end of the engine's output are
+ valid. It will truncate invalid characters from the end of the name when
+ converting illegal characters. For example, `"managed_image_name: "My-Name::"` will be converted to `"managed_image_name: "My-Name"`
+
+## Template variables
+
+Template variables are special variables automatically set by Packer at build
+time. Some builders, provisioners and other components have template variables
+that are available only for that component. Template variables are recognizable
+because they're prefixed by a period, such as `{{ .Name }}`. For example, when
+using the [`shell`](/packer/plugins/builders/vmware/iso) builder template variables
+are available to customize the
+[`execute_command`](/packer/docs/provisioners/shell#execute_command) parameter
+used to determine how Packer will run the shell command.
+
+```json
+{
+ "provisioners": [
+ {
+ "type": "shell",
+ "execute_command": "{{.Vars}} sudo -E -S bash '{{.Path}}'",
+ "scripts": ["scripts/bootstrap.sh"]
+ }
+ ]
+}
+```
+
+The `{{ .Vars }}` and `{{ .Path }}` template variables will be replaced with
+the list of the environment variables and the path to the script to be executed
+respectively.
+
+-> **Note:** In addition to template variables, you can specify your own
+user variables. See the [user variable](/packer/docs/templates/legacy_json_templates/user-variables)
+documentation for more information on user variables.
+
+# isotime Function Format Reference
+
+The isotime template engine uses Go to generate timestamps. If you're
+unfamiliar with Go, then the way you format the timestamp is going to
+feel a bit unusual compared to how you may be used to formatting
+datetime strings.
+
+Full docs and examples for the Go time formatting function can be found
+[here](https://pkg.go.dev/time#example_Time_Format)
+
+However, the formatting basics are worth describing here. From the [Go docs](https://pkg.go.dev/time#pkg-constants):
+
+> These are predefined layouts for use in Time.Format and time.Parse. The
+> reference time used in the layouts is the specific time:
+>
+> Mon Jan 2 15:04:05 MST 2006
+>
+> which is Unix time 1136239445. Since MST is GMT-0700, the reference time
+> can be thought of as
+>
+> 01/02 03:04:05PM '06 -0700
+>
+> To define your own format, write down what the reference time would look like
+> formatted your way; see the values of constants like ANSIC, StampMicro or
+> Kitchen for examples. The model is to demonstrate what the reference time
+> looks like so that the Format and Parse methods can apply the same
+> transformation to a general time value.
+
+So what does that look like in a Packer template function? Here's an example
+of how you'd declare a variable using the isotime function.
+
+```json
+"variables": {
+ "myvar": "packer-{{isotime `2006-01-02 03:04:05`}}"
+}
+```
+
+You can try and modify the following examples in a packer template or in
+`packer console` to get an idea of how to set different timestamps:
+
+| Input | Output |
+| ------------------------------------------------ | ---------------------------- |
+| `` "packer-{{isotime `2006-01-02`}}" `` | "packer-2021-05-17" |
+| `` "packer-{{isotime `Jan-_2-15:04:05.000`}}" `` | "packer-May-17-23:40:16.786" |
+| `` "packer-{{isotime `3:04PM`}}" `` | "packer-11:40PM" |
+| `"{{ isotime }}"` | "June 7, 7:22:43pm 2014" |
+| `` "{{isotime `2006-01-02`}}" `` | "2014-06-07" |
+| `` "{{isotime `Mon 1504`}}" `` | "Sat 1922" |
+| `` "{{isotime `02-Jan-06 03\_04\_05`}}" `` | "07-Jun-2014 07_22_43" |
+| `` "{{isotime `Hour15Year200603`}}" `` | "Hour19Year201407" |
+
+Formatting for the function `isotime` uses the magic reference date **Mon Jan 2
+15:04:05 -0700 MST 2006**, which breaks down to the following:
+
+<table class="table table-bordered table-condensed">
+ <thead>
+ <tr>
+ <th></th>
+ <th align="center">Day of Week</th>
+ <th align="center">Month</th>
+ <th align="center">Date</th>
+ <th align="center">Hour</th>
+ <th align="center">Minute</th>
+ <th align="center">Second</th>
+ <th align="center">Year</th>
+ <th align="center">Timezone</th>
+ </tr>
+ </thead>
+ <tr>
+ <th>Numeric</th>
+ <td align="center">-</td>
+ <td align="center">01</td>
+ <td align="center">02</td>
+ <td align="center">03 (15)</td>
+ <td align="center">04</td>
+ <td align="center">05</td>
+ <td align="center">06</td>
+ <td align="center">-0700</td>
+ </tr>
+ <tr>
+ <th>Textual</th>
+ <td align="center">Monday (Mon)</td>
+ <td align="center">January (Jan)</td>
+ <td align="center">-</td>
+ <td align="center">-</td>
+ <td align="center">-</td>
+ <td align="center">-</td>
+ <td align="center">-</td>
+ <td align="center">MST</td>
+ </tr>
+</table>
+
+_The values in parentheses are the abbreviated, or 24-hour clock values_
+
+Note that "-0700" is always formatted into "+0000" because `isotime` is always
+UTC time.
+
+# split Function Format Reference
+
+The function `split` takes an input string, a seperator string, and a numeric
+component value and returns the requested substring.
+
+Please note that you cannot use the `split` function on user variables, because
+we can't nest the functions currently. This function is intended to be used on
+builder variables like build_name. If you need a split user variable, the best
+way to do it is to create a separate variable.
+
+Here are some examples using the above options:
+
+```liquid
+build_name = foo-bar-provider
+
+{{split build_name "-" 0}} = foo
+{{split "fixed-string" "-" 1}} = string
+```
+
+Please note that double quote characters need escaping inside of templates (in
+this case, on the `fixed-string` value):
+
+```json
+{
+ "post-processors": [
+ [
+ {
+ "type": "vagrant",
+ "compression_level": 9,
+ "keep_input_artifact": false,
+ "vagrantfile_template": "tpl/{{split build_name \"-\" 1}}.rb",
+ "output": "output/{{build_name}}.box",
+ "only": ["org-name-provider"]
+ }
+ ]
+ ]
+}
+```
+
+# replace Function Format Reference
+
+Here are some examples using the replace options:
+
+```liquid
+build_name = foo-bar-provider
+
+{{ replace_all "-" "/" build_name }} = foo/bar/provider
+{{ build_name | replace "-" "/" 1 }} = foo/bar-provider
+```
diff --git a/v1.9.4/website/content/docs/templates/legacy_json_templates/index.mdx b/v1.9.4/website/content/docs/templates/legacy_json_templates/index.mdx
new file mode 100644
index 0000000..3a01ca7
--- /dev/null
+++ b/v1.9.4/website/content/docs/templates/legacy_json_templates/index.mdx
@@ -0,0 +1,183 @@
+---
+description: >
+ The JSON templates are JSON files that configure the various components
+ of Packer in order to create one or more machine images. Templates are
+ portable, static, and readable and writable by both humans and computers.
+ This has the added benefit of being able to not only create and modify
+ templates by hand, but also write scripts to dynamically create or modify
+ templates.
+page_title: JSON Templates
+---
+
+`@include 'from-1.5/legacy-json-warning.mdx'`
+
+# JSON Templates
+
+These Packer templates are JSON files that configure the various components
+of Packer in order to create one or more machine images. Templates are portable,
+static, and readable and writable by both humans and computers.
+
+Templates are given to commands such as `packer build`, which will take the
+template and actually run the builds within it, producing any resulting machine
+images.
+
+## JSON Template Structure
+
+The template is a JSON object that has a set of keys configuring various
+components of Packer. The available keys within a template are listed below.
+Along with each key, it is noted whether it is required or not.
+
+- `builders` (_required_) is an array of one or more objects that defines the
+ builders that will be used to create machine images for this template, and
+ configures each of those builders. For more information on how to define
+ and configure a builder, read the sub-section on [configuring builders in
+ templates](/packer/docs/templates/legacy_json_templates/builders).
+
+- `description` (optional) is a string providing a description of what the
+ template does. This output is used only in the [inspect
+ command](/packer/docs/commands/inspect).
+
+- `min_packer_version` (optional) is a string that has a minimum Packer
+ version that is required to parse the template. This can be used to ensure
+ that proper versions of Packer are used with the template. A max version
+ can't be specified because Packer retains backwards compatibility with
+ `packer fix`.
+
+- `post-processors` (optional) is an array of one or more objects that
+ defines the various post-processing steps to take with the built images. If
+ not specified, then no post-processing will be done. For more information
+ on what post-processors do and how they're defined, read the sub-section on
+ [configuring post-processors in
+ templates](/packer/docs/templates/legacy_json_templates/post-processors).
+
+- `provisioners` (optional) is an array of one or more objects that defines
+ the provisioners that will be used to install and configure software for
+ the machines created by each of the builders. If it is not specified, then
+ no provisioners will be run. For more information on how to define and
+ configure a provisioner, read the sub-section on [configuring provisioners
+ in templates](/packer/docs/templates/legacy_json_templates/provisioners).
+
+- `variables` (optional) is an object of one or more key/value strings that
+ defines user variables contained in the template. If it is not specified,
+ then no variables are defined. For more information on how to define and
+ use user variables, read the sub-section on [user variables in
+ templates](/packer/docs/templates/legacy_json_templates/user-variables).
+
+## Comments
+
+JSON doesn't support comments and Packer reports unknown keys as validation
+errors. If you'd like to comment your template, you can prefix a _root level_
+key with an underscore. Example:
+
+```json
+{
+ "_comment": "This is a comment",
+ "builders": [{}]
+}
+```
+
+**Important:** Only _root level_ keys can be underscore prefixed. Keys within
+builders, provisioners, etc. will still result in validation errors.
+
+-> **Note:** Packer supports HCL2 from version 1.6.0. The HashiCorp
+Configuration Language does support comments anywhere in template files.
+If comments are important to you, consider upgrading your
+JSON template to HCL2 using the `packer hcl2_upgrade` command.
+
+One workaround if you are not ready to upgrade to HCL is to use jq to strip
+unsupported comments from a Packer template before you run `packer build`.
+
+For example, here is a file named `commented_template.json`:
+
+```json
+{
+ "_comment": ["this is", "a multi-line", "comment"],
+ "builders": [
+ {
+ "_comment": "this is a comment inside a builder",
+ "type": "null",
+ "communicator": "none"
+ }
+ ],
+ "_comment": "this is a root level comment",
+ "provisioners": [
+ {
+ "_comment": "this is a different comment",
+ "type": "shell",
+ "_comment": "this is yet another comment",
+ "inline": ["echo hellooooo"]
+ }
+ ]
+}
+```
+
+If you use the following jq command:
+
+```shell-session
+$ jq 'walk(if type == "object" then del(._comment) else . end)' commented_template.json > uncommented_template.json
+```
+
+The tool will produce a new file containing:
+
+```json
+{
+ "builders": [
+ {
+ "type": "null",
+ "communicator": "none"
+ }
+ ],
+ "provisioners": [
+ {
+ "type": "shell",
+ "inline": ["echo hellooooo"]
+ }
+ ]
+}
+```
+
+Once you've got your uncommented file, you can call `packer build` on it like
+you normally would.
+
+If your install of jq does not have the walk function and you get an error like
+
+```text
+jq: error: walk/1 is not defined at <top-level>,
+```
+
+You can create a file `~/.jq` and add the [walk function](https://github.com/stedolan/jq/blob/ad9fc9f559e78a764aac20f669f23cdd020cd943/src/builtin.jq#L255-L262) to it by hand.
+
+## Example Template
+
+Below is an example of a basic template that could be invoked with
+`packer build`. It would create an instance in AWS, and once running copy a
+script to it and run that script using SSH.
+
+-> **Note:** This example requires an account with Amazon Web Services.
+There are a number of parameters which need to be provided for a functional
+build to take place. See the [Amazon builder](/packer/plugins/builders/amazon)
+documentation for more information.
+
+```json
+{
+ "builders": [
+ {
+ "type": "amazon-ebs",
+ "access_key": "...",
+ "secret_key": "...",
+ "region": "us-east-1",
+ "source_ami": "ami-fce3c696",
+ "instance_type": "t2.micro",
+ "ssh_username": "ubuntu",
+ "ami_name": "packer {{timestamp}}"
+ }
+ ],
+
+ "provisioners": [
+ {
+ "type": "shell",
+ "script": "setup_things.sh"
+ }
+ ]
+}
+```
diff --git a/v1.9.4/website/content/docs/templates/legacy_json_templates/post-processors.mdx b/v1.9.4/website/content/docs/templates/legacy_json_templates/post-processors.mdx
new file mode 100644
index 0000000..b694d8e
--- /dev/null
+++ b/v1.9.4/website/content/docs/templates/legacy_json_templates/post-processors.mdx
@@ -0,0 +1,175 @@
+---
+description: |
+ The post-processor section within a template configures any post-processing
+ that will be done to images built by the builders. Examples of post-processing
+ would be compressing files, uploading artifacts, etc.
+page_title: Post-Processors - Templates
+---
+
+`@include 'from-1.5/legacy-json-warning.mdx'`
+
+# Template Post-Processors
+
+The post-processor section within a template configures any post-processing
+that will be done to images built by the builders. Examples of post-processing
+would be compressing files, uploading artifacts, etc.
+
+Post-processors are _optional_. If no post-processors are defined within a
+template, then no post-processing will be done to the image. The resulting
+artifact of a build is just the image outputted by the builder.
+
+This documentation page will cover how to configure a post-processor in a
+template. The specific configuration options available for each post-processor,
+however, must be referenced from the documentation for that specific
+post-processor.
+
+Within a template, a section of post-processor definitions looks like this:
+
+```json
+{
+ "post-processors": [
+ // ... one or more post-processor definitions here
+ ]
+}
+```
+
+For each post-processor definition, Packer will take the result of each of the
+defined builders and send it through the post-processors. This means that if
+you have one post-processor defined and two builders defined in a template, the
+post-processor will run twice (once for each builder), by default. There are
+ways, which will be covered later, to control what builders post-processors
+apply to, if you wish. It is also possible to prevent a post-processor from
+running.
+
+## Post-Processor Definition
+
+Within the `post-processors` array in a template, there are three ways to
+define a post-processor. There are _simple_ definitions, _detailed_
+definitions, and _sequence_ definitions. Another way to think about this is
+that the "simple" and "detailed" definitions are shortcuts for the "sequence"
+definition.
+
+A **simple definition** is just a string; the name of the post-processor. An
+example is shown below. Simple definitions are used when no additional
+configuration is needed for the post-processor.
+
+```json
+{
+ "post-processors": ["compress"]
+}
+```
+
+A **detailed definition** is a JSON object. It is very similar to a builder or
+provisioner definition. It contains a `type` field to denote the type of the
+post-processor, but may also contain additional configuration for the
+post-processor. A detailed definition is used when additional configuration is
+needed beyond simply the type for the post-processor. An example is shown
+below.
+
+```json
+{
+ "post-processors": [
+ {
+ "type": "compress",
+ "format": "tar.gz"
+ }
+ ]
+}
+```
+
+A **sequence definition** is a JSON array comprised of other **simple** or
+**detailed** definitions. The post-processors defined in the array are run in
+order, with the artifact of each feeding into the next, and any intermediary
+artifacts being discarded. A sequence definition may not contain another
+sequence definition. Sequence definitions are used to chain together multiple
+post-processors. An example is shown below, where the artifact of a build is
+compressed then uploaded, but the compressed result is not kept.
+
+It is very important that any post processors that need to be run in order, be
+sequenced!
+
+```json
+{
+ "post-processors": [
+ ["compress", { "type": "upload", "endpoint": "http://example.com" }]
+ ]
+}
+```
+
+As you may be able to imagine, the **simple** and **detailed** definitions are
+simply shortcuts for a **sequence** definition of only one element.
+
+## Input Artifacts
+
+When using post-processors, the input artifact (coming from a builder or
+another post-processor) is discarded by default after the post-processor runs.
+This is because generally, you don't want the intermediary artifacts on the way
+to the final artifact created.
+
+In some cases, however, you may want to keep the intermediary artifacts. You
+can tell Packer to keep these artifacts by setting the `keep_input_artifact`
+configuration to `true`. An example is shown below:
+
+```json
+{
+ "post-processors": [
+ {
+ "type": "compress",
+ "keep_input_artifact": true
+ }
+ ]
+}
+```
+
+This setting will only keep the input artifact to _that specific_
+post-processor. If you're specifying a sequence of post-processors, then all
+intermediaries are discarded by default except for the input artifacts to
+post-processors that explicitly state to keep the input artifact.
+
+-> **Note:** The intuitive reader may be wondering what happens if multiple
+post-processors are specified (not in a sequence). Does Packer require the
+configuration to keep the input artifact on all the post-processors? The answer
+is no, of course not. Packer is smart enough to figure out that at least one
+post-processor requested that the input be kept, so it will keep it around.
+
+## Run on Specific Builds
+
+You can use the `only` or `except` fields to run a post-processor only with
+specific builds. These two fields do what you expect: `only` will only run the
+post-processor on the specified builds and `except` will run the post-processor
+on anything other than the specified builds. A sequence of post-processors will
+execute until a skipped post-processor.
+
+An example of `only` being used is shown below, but the usage of `except` is
+effectively the same. `only` and `except` can only be specified on "detailed"
+fields. If you have a sequence of post-processors to run, `only` and `except`
+will affect that post-processor and stop the sequence.
+
+The `-except` option can specifically skip a named post processor. The `-only`
+option _ignores_ post-processors.
+
+```json
+([
+ {
+ "name": "vbox",
+ "type": "vagrant",
+ "only": ["virtualbox-iso"]
+ },
+ {
+ "type": "compress"
+ }
+],
+[
+ "compress",
+ {
+ "type": "upload",
+ "endpoint": "http://example.com"
+ }
+])
+```
+
+The values within `only` or `except` are _build names_, not builder types.
+Name is a required block label in HCL, but in legacy JSON, build names default
+to the types of their builders (e.g. `docker` or `amazon-ebs` or
+`virtualbox-iso`), unless a specific `name` attribute is specified within the
+configuration.
diff --git a/v1.9.4/website/content/docs/templates/legacy_json_templates/provisioners.mdx b/v1.9.4/website/content/docs/templates/legacy_json_templates/provisioners.mdx
new file mode 100644
index 0000000..5ecf660
--- /dev/null
+++ b/v1.9.4/website/content/docs/templates/legacy_json_templates/provisioners.mdx
@@ -0,0 +1,220 @@
+---
+description: |
+ Within the template, the provisioners section contains an array of all the
+ provisioners that Packer should use to install and configure software within
+ running machines prior to turning them into machine images.
+page_title: Provisioners - Templates
+---
+
+`@include 'from-1.5/legacy-json-warning.mdx'`
+
+# Template Provisioners
+
+Within the template, the provisioners section contains an array of all the
+provisioners that Packer should use to install and configure software within
+running machines prior to turning them into machine images.
+
+Provisioners are _optional_. If no provisioners are defined within a template,
+then no software other than the defaults will be installed within the resulting
+machine images. This is not typical, however, since much of the value of Packer
+is to produce multiple identical images of pre-configured software.
+
+This documentation page will cover how to configure a provisioner in a
+template. The specific configuration options available for each provisioner,
+however, must be referenced from the documentation for that specific
+provisioner.
+
+Within a template, a section of provisioner definitions looks like this:
+
+```json
+{
+ "provisioners": [
+ // ... one or more provisioner definitions here
+ ]
+}
+```
+
+For each of the definitions, Packer will run the provisioner for each of the
+configured builds. The provisioners will be run in the order they are defined
+within the template.
+
+## Provisioner Definition
+
+A provisioner definition is a JSON object that must contain at least the `type`
+key. This key specifies the name of the provisioner to use. Additional keys
+within the object are used to configure the provisioner, with the exception of
+a handful of special keys, covered later.
+
+As an example, the "shell" provisioner requires a key such as `script` which
+specifies a path to a shell script to execute within the machines being
+created.
+
+An example provisioner definition is shown below, configuring the shell
+provisioner to run a local script within the machines:
+
+```json
+{
+ "type": "shell",
+ "script": "script.sh"
+}
+```
+
+## Run on Specific Builds
+
+You can use the `only` or `except` configurations to run a provisioner only
+with specific builds. These two configurations do what you expect: `only` will
+only run the provisioner on the specified builds and `except` will run the
+provisioner on anything other than the specified builds.
+
+An example of `only` being used is shown below, but the usage of `except` is
+effectively the same:
+
+```json
+{
+ "type": "shell",
+ "script": "script.sh",
+ "only": ["virtualbox-iso"]
+}
+```
+
+The values within `only` or `except` are _build names_, not builder types. If
+you recall, build names by default are just their builder type, but if you
+specify a custom `name` parameter, then you should use that as the value
+instead of the type.
+Values within `except` could also be a _post-processor_ name.
+
+## On Error Provisioner
+
+You can optionally create a single specialized provisioner field called an
+`error-cleanup-provisioner`. This provisioner will not run unless the normal
+provisioning run fails. If the normal provisioning run does fail, this special
+error provisioner will run _before the instance is shut down_. This allows you
+to make last minute changes and clean up behaviors that Packer may not be able
+to clean up on its own.
+
+For examples, users may use this provisioner to make sure that the instance is
+properly unsubscribed from any services that it connected to during the build
+run.
+
+Toy usage example for the error cleanup script:
+
+```json
+{
+ "builders": [
+ {
+ "type": "null",
+ "communicator": "none"
+ }
+ ],
+ "provisioners": [
+ {
+ "type": "shell-local",
+ "inline": ["exit 2"]
+ }
+ ],
+ "error-cleanup-provisioner": {
+ "type": "shell-local",
+ "inline": ["echo 'rubber ducky'> ducky.txt"]
+ }
+}
+```
+
+## Build-Specific Overrides
+
+While the goal of Packer is to produce identical machine images, it sometimes
+requires periods of time where the machines are different before they
+eventually converge to be identical. In these cases, different configurations
+for provisioners may be necessary depending on the build. This can be done
+using build-specific overrides.
+
+An example of where this might be necessary is when building both an EC2 AMI
+and a VMware machine. The source EC2 AMI may setup a user with administrative
+privileges by default, whereas the VMware machine doesn't have these
+privileges. In this case, the shell script may need to be executed differently.
+Of course, the goal is that hopefully the shell script converges these two
+images to be identical. However, they may initially need to be run differently.
+
+This example is shown below:
+
+```json
+{
+ "type": "shell",
+ "script": "script.sh",
+ "override": {
+ "vmware-iso": {
+ "execute_command": "echo 'password' | sudo -S bash {{.Path}}"
+ }
+ }
+}
+```
+
+As you can see, the `override` key is used. The value of this key is another
+JSON object where the key is the name of a [builder
+definition](/packer/docs/templates/legacy_json_templates/builders). The value of this is in turn
+another JSON object. This JSON object simply contains the provisioner
+configuration as normal. This configuration is merged into the default
+provisioner configuration.
+
+## Pausing Before Running
+
+With certain provisioners it is sometimes desirable to pause for some period of
+time before running it. Specifically, in cases where a provisioner reboots the
+machine, you may want to wait for some period of time before starting the next
+provisioner.
+
+Every provisioner definition in a Packer template can take a special
+configuration `pause_before` that is the amount of time to pause before running
+that provisioner. By default, there is no pause. An example is shown below:
+
+```json
+{
+ "type": "shell",
+ "script": "script.sh",
+ "pause_before": "10s"
+}
+```
+
+For the above provisioner, Packer will wait 10 seconds before uploading and
+executing the shell script.
+
+## Retry on error
+
+With certain provisioners it is sometimes desirable to retry when it fails.
+Specifically, in cases where the provisioner depends on external processes that are not done yet.
+
+Every provisioner definition in a Packer template can take a special
+configuration `max_retries` that is the maximum number of times a provisioner will retry on error.
+By default, there `max_retries` is zero and there is no retry on error. An example is shown below:
+
+```json
+{
+ "type": "shell",
+ "script": "script.sh",
+ "max_retries": 5
+}
+```
+
+For the above provisioner, Packer will retry maximum five times until stops failing.
+If after five retries the provisioner still fails, then the complete build will fail.
+
+## Timeout
+
+Sometimes a command can take much more time than expected
+
+Every provisioner definition in a Packer template can take a special
+configuration `timeout` that is the amount of time to wait before
+considering that the provisioner failed. By default, there is no timeout. An
+example is shown below:
+
+```json
+{
+ "type": "shell",
+ "script": "script.sh",
+ "timeout": "5m"
+}
+```
+
+For the above provisioner, Packer will cancel the script if it takes more than
+5 minutes.
+
+Timeout has no effect in debug mode.
diff --git a/v1.9.4/website/content/docs/templates/legacy_json_templates/user-variables.mdx b/v1.9.4/website/content/docs/templates/legacy_json_templates/user-variables.mdx
new file mode 100644
index 0000000..b3c00d6
--- /dev/null
+++ b/v1.9.4/website/content/docs/templates/legacy_json_templates/user-variables.mdx
@@ -0,0 +1,423 @@
+---
+description: |
+ User variables allow your templates to be further configured with variables
+ from the command-line, environment variables, or files. This lets you
+ parameterize your templates so that you can keep secret tokens,
+ environment-specific data, and other types of information out of your
+ templates. This maximizes the portability and shareability of the template.
+page_title: User Variables - Templates
+---
+
+`@include 'from-1.5/legacy-json-warning.mdx'`
+
+# Template User Variables
+
+User variables allow your templates to be further configured with variables
+from the command-line, environment variables, Vault, or files. This lets you
+parameterize your templates so that you can keep secret tokens,
+environment-specific data, and other types of information out of your
+templates. This maximizes the portability of the template.
+
+Using user variables expects you to know how [configuration
+templates](/packer/docs/templates/legacy_json_templates/engine) work. If you don't know how
+configuration templates work yet, please read that page first.
+
+## Usage
+
+In order to set a user variable, you must define it either within the
+`variables` section within your template, or using the command-line `-var` or
+`-var-file` flags.
+
+Even if you want a user variable to default to an empty string, it is best to
+explicitly define it. This explicitness helps reduce the time it takes for
+newcomers to understand what can be modified using variables in your template.
+
+The `variables` section is a key/value mapping of the user variable name to a
+default value. A default value can be the empty string. An example is shown
+below:
+
+```json
+{
+ "variables": {
+ "aws_access_key": "",
+ "aws_secret_key": ""
+ },
+
+ "builders": [
+ {
+ "type": "amazon-ebs",
+ "access_key": "{{user `aws_access_key`}}",
+ "secret_key": "{{user `aws_secret_key`}}"
+ // ...
+ }
+ ]
+}
+```
+
+In the above example, the template defines two user variables: `aws_access_key`
+and `aws_secret_key`. They default to empty values. Later, the variables are
+used within the builder we defined in order to configure the actual keys for
+the Amazon builder.
+
+If the default value is `null`, then the user variable will be _required_. This
+means that the user must specify a value for this variable or template
+validation will fail.
+
+User variables are used by calling the `{{user}}` function in the form of
+`{{user 'variable'}}`. This function can be used in _any value_ but `type`
+within the template: in builders, provisioners, _anywhere outside the `variables` section_.
+User variables are available globally within the rest of the template.
+
+## Environment Variables
+
+Environment variables can be used within your template using user variables.
+The `env` function is available _only_ within the default value of a user
+variable, allowing you to default a user variable to an environment variable.
+An example is shown below:
+
+```json
+{
+ "variables": {
+ "my_secret": "{{env `MY_SECRET`}}"
+ }
+}
+```
+
+This will default "my_secret" to be the value of the "MY_SECRET" environment
+variable (or an empty string if it does not exist).
+
+-> **Why can't I use environment variables elsewhere?** User variables are
+the single source of configurable input to a template. We felt that having
+environment variables used _anywhere_ in a template would confuse the user
+about the possible inputs to a template. By allowing environment variables only
+within default values for user variables, user variables remain as the single
+source of input to a template that a user can easily discover using
+`packer inspect`.
+
+-> **Why can't I use `~` for home variable?** `~` is an special variable
+that is evaluated by shell during a variable expansion. As Packer doesn't run
+inside a shell, it won't expand `~`.
+
+## Consul keys
+
+Consul keys can be used within your template using the `consul_key` function.
+This function is available _only_ within the default value of a user variable,
+for reasons similar to environment variables above.
+
+```json
+{
+ "variables": {
+ "soft_versions": "{{ consul_key `my_image/softs_versions/next` }}"
+ }
+}
+```
+
+This will default `soft_versions` to the value of the key
+`my_image/softs_versions/next` in consul.
+
+The configuration for consul (address, tokens, ...) must be specified as
+environment variables, as specified in the
+[Documentation](/consul/docs/commands#environment-variables).
+
+## Vault Variables
+
+Secrets can be read from [Vault](https://www.vaultproject.io/) and used within
+your template as user variables. the `vault` function is available _only_
+within the default value of a user variable, allowing you to default a user
+variable to a vault secret.
+
+An example of using a v2 kv engine:
+
+If you store a value in vault using `vault kv put secret/hello foo=world`, you
+can access it using the following template engine:
+
+```json
+{
+ "variables": {
+ "my_secret": "{{ vault `/secret/data/hello` `foo`}}"
+ }
+}
+```
+
+which will assign "my_secret": "world"
+
+An example of using a v1 kv engine:
+
+If you store a value in vault using:
+
+ vault secrets enable -version=1 -path=secrets kv
+ vault kv put secrets/hello foo=world
+
+You can access it using the following template engine:
+
+ {
+ "variables": {
+ "VAULT_SECRETY_SECRET": "{{ vault `secrets/hello` `foo`}}"
+ }
+ }
+
+This example accesses the Vault path `secret/data/foo` and returns the value
+stored at the key `bar`, storing it as "my_secret".
+
+In order for this to work, you must set the environment variables `VAULT_TOKEN`
+and `VAULT_ADDR` to valid values.
+
+The api tool we use allows for more custom configuration of the Vault client via
+environment variables.
+
+The full list of available environment variables is:
+
+```text
+"VAULT_ADDR"
+"VAULT_AGENT_ADDR"
+"VAULT_CACERT"
+"VAULT_CAPATH"
+"VAULT_CLIENT_CERT"
+"VAULT_CLIENT_KEY"
+"VAULT_CLIENT_TIMEOUT"
+"VAULT_SKIP_VERIFY"
+"VAULT_NAMESPACE"
+"VAULT_TLS_SERVER_NAME"
+"VAULT_WRAP_TTL"
+"VAULT_MAX_RETRIES"
+"VAULT_TOKEN"
+"VAULT_MFA"
+"VAULT_RATE_LIMIT"
+```
+
+and detailed documentation for usage of each of those variables can be found
+[here](/vault/docs/commands#environment-variables).
+
+## AWS Secrets Manager Variables
+
+Secrets can be read from [AWS Secrets Manager](https://aws.amazon.com/secrets-manager/)
+and used within your template as user variables. The `aws_secretsmanager` function is
+available _only_ within the default value of a user variable, allowing you to default
+a user variable to an AWS Secrets Manager secret.
+
+### Plaintext Secrets
+
+```json
+{
+ "variables": {
+ "password": "{{ aws_secretsmanager `globalpassword` }}"
+ }
+}
+```
+
+In the example above it is assumed that the secret `globalpassword` is not
+stored as a key pair but as a single non-JSON string value. Which the
+`aws_secretsmanager` function will return as a raw string.
+
+### Single Key Secrets
+
+```json
+{
+ "variables": {
+ "password": "{{ aws_secretsmanager `sample/app/password` }}"
+ }
+}
+```
+
+In the example above it is assumed that only one key is stored in
+`sample/app/password` if there are multiple keys stored in it then you need
+to indicate the specific key you want to fetch as shown below.
+
+### Multiple Key Secrets
+
+```json
+{
+ "variables": {
+ "db_password": "{{ aws_secretsmanager `sample/app/passwords` `db` }}",
+ "api_key": "{{ aws_secretsmanager `sample/app/passwords` `api_key` }}"
+ }
+}
+```
+
+In order to use this function you have to configure valid AWS credentials using
+one of the following methods:
+
+- [Environment Variables](https://docs.aws.amazon.com/cli/latest/userguide/cli-configure-envvars.html)
+- [CLI Configuration Files](https://docs.aws.amazon.com/cli/latest/userguide/cli-configure-files.html)
+- [Container Credentials](https://docs.aws.amazon.com/AmazonECS/latest/developerguide/task-iam-roles.html)
+- [Instance Profile Credentials](https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/iam-roles-for-amazon-ec2.html)
+
+## Using array values
+
+Some templates call for array values. You can use template variables for these,
+too. For example, the `amazon-ebs` builder has a configuration parameter called
+`ami_regions`, which takes an array of regions that it will copy the AMI to.
+You can parameterize this by using a variable that is a list of regions, joined
+by a `,`. For example:
+
+```json
+{
+ "variables": {
+ "destination_regions": "us-west-1,us-west-2"
+ },
+ "builders": [
+ {
+ "ami_name": "packer-qs-{{timestamp}}",
+ "instance_type": "t2.micro",
+ "region": "us-east-1",
+ "source_ami_filter": {
+ "filters": {
+ "name": "*ubuntu-xenial-16.04-amd64-server-*",
+ "root-device-type": "ebs",
+ "virtualization-type": "hvm"
+ },
+ "most_recent": true,
+ "owners": ["099720109477"]
+ },
+ "ami_regions": "{{user `destination_regions`}}",
+ "ssh_username": "ubuntu",
+ "type": "amazon-ebs"
+ }
+ ]
+}
+```
+
+## Setting Variables
+
+Now that we covered how to define and use user variables within a template, the
+next important point is how to actually set these variables. Packer exposes two
+methods for setting user variables: from the command line or from a file.
+
+### From the Command Line
+
+To set user variables from the command line, the `-var` flag is used as a
+parameter to `packer build` (and some other commands). Continuing our example
+above, we could build our template using the command below. The command is
+split across multiple lines for readability, but can of course be a single
+line.
+
+```shell-session
+$ packer build \
+ -var 'aws_access_key=foo' \
+ -var 'aws_secret_key=bar' \
+ template.json
+```
+
+As you can see, the `-var` flag can be specified multiple times in order to set
+multiple variables. Also, variables set later on the command-line override any
+earlier set variable of the same name.
+
+**warning** If you are calling Packer from cmd.exe, you should double-quote
+your variables rather than single-quoting them. For example:
+
+`packer build -var "aws_secret_key=foo" template.json`
+
+### From a File
+
+Variables can also be set from an external JSON file. The `-var-file` flag
+reads a file containing a key/value mapping of variables to values and sets
+those variables. An example JSON file may look like this:
+
+```json
+{
+ "aws_access_key": "foo",
+ "aws_secret_key": "bar"
+}
+```
+
+It is a single JSON object where the keys are variables and the values are the
+variable values. Assuming this file is in `variables.json`, we can build our
+template using the following command:
+
+```text
+On Linux :
+$ packer build -var-file=variables.json template.json
+On Windows :
+packer build -var-file variables.json template.json
+```
+
+The `-var-file` flag can be specified multiple times and variables from
+multiple files will be read and applied. As you'd expect, variables read from
+files specified later override a variable set earlier.
+
+Combining the `-var` and `-var-file` flags together also works how you'd
+expect. Variables set later in the command override variables set earlier. So,
+for example, in the following command with the above `variables.json` file:
+
+```shell-session
+$ packer build \
+ -var 'aws_access_key=bar' \
+ -var-file=variables.json \
+ -var 'aws_secret_key=baz' \
+ template.json
+```
+
+Results in the following variables:
+
+| Variable | Value |
+| -------------- | ----- |
+| aws_access_key | foo |
+| aws_secret_key | baz |
+
+# Sensitive Variables
+
+If you use the environment to set a variable that is sensitive, you probably
+don't want that variable printed to the Packer logs. You can make sure that
+sensitive variables won't get printed to the logs by adding them to the
+"sensitive-variables" list within the Packer template:
+
+```json
+{
+ "variables": {
+ "my_secret": "{{env `MY_SECRET`}}",
+ "not_a_secret": "plaintext",
+ "foo": "bar"
+ },
+
+ "sensitive-variables": ["my_secret", "foo"],
+ ...
+}
+```
+
+The above snippet of code will function exactly the same as if you did not set
+"sensitive-variables", except that the Packer UI and logs will replace all
+instances of "bar" and of whatever the value of "my_secret" is with
+`<sensitive>`. This allows you to be confident that you are not printing
+secrets in plaintext to our logs by accident.
+
+# Recipes
+
+## Making a provisioner step conditional on the value of a variable
+
+There is no specific syntax in Packer templates for making a provisioner step
+conditional, depending on the value of a variable. However, you may be able to
+do this by referencing the variable within a command that you execute. For
+example, here is how to make a `shell-local` provisioner only run if the
+`do_nexpose_scan` variable is non-empty.
+
+```json
+{
+ "type": "shell-local",
+ "command": "if [ ! -z \"{{user `do_nexpose_scan`}}\" ]; then python -u trigger_nexpose_scan.py; fi"
+}
+```
+
+## Using HOME Variable
+
+In order to use `$HOME` variable, you can create a `home` variable in Packer:
+
+```json
+{
+ "variables": {
+ "home": "{{env `HOME`}}"
+ }
+}
+```
+
+And this will be available to be used in the rest of the template, i.e.:
+
+```json
+{
+ "builders": [
+ {
+ "type": "google",
+ "account_file": "{{ user `home` }}/.secrets/gcp-{{ user `env` }}.json"
+ }
+ ]
+}
+```
diff --git a/v1.9.4/website/content/docs/terminology.mdx b/v1.9.4/website/content/docs/terminology.mdx
new file mode 100644
index 0000000..d7ddeff
--- /dev/null
+++ b/v1.9.4/website/content/docs/terminology.mdx
@@ -0,0 +1,64 @@
+---
+description: >
+ There are a handful of terms used throughout the Packer documentation where
+ the
+
+ meaning may not be immediately obvious if you haven't used Packer before.
+
+ Luckily, there are relatively few. This page documents all the terminology
+
+ required to understand and use Packer. The terminology is in alphabetical
+ order
+
+ for quick referencing.
+page_title: Terminology
+---
+
+# Packer Terminology
+
+There are a handful of terms used throughout the Packer documentation where the
+meaning may not be immediately obvious if you haven't used Packer before.
+Luckily, there are relatively few. This page documents all the terminology
+required to understand and use Packer. The terminology is in alphabetical order
+for quick referencing.
+
+- `Artifacts` are the results of a single build, and are usually a set of IDs
+ or files to represent a machine image. Every builder produces a single
+ artifact. As an example, in the case of the Amazon EC2 builder, the
+ artifact is a set of AMI IDs (one per region). For the VMware builder, the
+ artifact is a directory of files comprising the created virtual machine.
+
+- `Builds` are a single task that eventually produces an image for a single
+ platform. Multiple builds run in parallel. Example usage in a sentence:
+ "The Packer build produced an AMI to run our web application." Or: "Packer
+ is running the builds now for VMware, AWS, and VirtualBox."
+
+- `Builders` are components of Packer that are able to create a machine image
+ for a single platform. Builders read in some configuration and use that to
+ run and generate a machine image. A builder is invoked as part of a build
+ in order to create the actual resulting images. Example builders include
+ VirtualBox, VMware, and Amazon EC2.
+
+- `Commands` are sub-commands for the `packer` program that perform some job.
+ An example command is "build", which is invoked as `packer build`. Packer
+ ships with a set of commands out of the box in order to define its
+ command-line interface.
+
+- `Data Sources` are components of Packer that fetch data from outside Packer
+ and make it available to use within the template.
+ Example of data sources include Amazon AMI, and Amazon Secrets Manager.
+
+- `Post-processors` are components of Packer that take the result of a
+ builder or another post-processor and process that to create a new
+ artifact. Examples of post-processors are compress to compress artifacts,
+ upload to upload artifacts, etc.
+
+- `Provisioners` are components of Packer that install and configure software
+ within a running machine prior to that machine being turned into a static
+ image. They perform the major work of making the image contain useful
+ software. Example provisioners include shell scripts, Chef, Puppet, etc.
+
+- `Templates` are either [HCL](https://packer.io/templates/hcl_templates) or JSON files which
+ define one or more builds by configuring the various components of Packer.
+ Packer is able to read a template and use that information to create
+ multiple machine images in parallel.
diff --git a/v1.9.4/website/content/guides/1.7-plugin-upgrade.mdx b/v1.9.4/website/content/guides/1.7-plugin-upgrade.mdx
new file mode 100644
index 0000000..9739d05
--- /dev/null
+++ b/v1.9.4/website/content/guides/1.7-plugin-upgrade.mdx
@@ -0,0 +1,118 @@
+---
+page_title: Upgrading your plugin to use the Packer plugin sdk
+description: >-
+ Learn how to upgrade your plugin to support v1.7.0 and later.
+---
+
+# Upgrading your plugin to be compatible with Packer v1.7.0 and later
+
+In version v1.7.0 the Packer plugin development model was split into two separate packages: the Packer core
+and the Packer plugin SDK. Prior to version 1.7.0, the Packer core repository (https://github.com/hashicorp/packer) contained the libraries and interfaces used by Packer plugins. In version 1.7.0, these libraries were moved into their own repository (https://github.com/hashicorp/packer-plugin-sdk). If you authored a plugin prior to the v1.7.0 release using the API version 4, you should switch to the Packer Plugin SDK.
+
+## Update plugins to use the new SDK
+
+### Why update to the new SDK?
+
+The goal of the SDK is to clearly separate the Packer core from the Packer plugins; as a plugin maintainer, you should only have to import the SDK and not the core. The SDK will allow us to use semantic versioning to express the changes to the API that our maintainers are expected to use, and will help us keep a clearer promise to you about the location and functionality of our helper tools.
+
+### How to update plugins to use the Packer plugin SDK
+
+We have created a [packer-sdk-migrator](https://github.com/hashicorp/packer-sdk-migrator) cli tool to help you migrate your plugin to use the new import paths. To use it, follow the installation instructions for the migration tool, then call `packer-sdk-migrator migrate` from the root of your plugin directory. More details can be found in the migrator's [README](https://github.com/hashicorp/packer-sdk-migrator/blob/main/README.md).
+
+Once you have migrated your plugin to the new SDK, your users can continue using your plugin as they always have, manually installing it in their `plugins` directories. However, Packer v1.7 also introduced the `packer init` command, and since you're here anyway it's a great time to upgrade your plugin so it can be found by `packer init`. Keep reading for more details!
+
+## Upgrade Plugins to use the new multi-component RPC server
+
+### Why is there a new RPC server?
+
+There are two main reasons we wrote the new server type.
+
+First, it enables multiple related components, for example a builder and a post-processor that share a hypervisor or cloud, to live together in the same plugin. This helps maintainers who are experts in a specific technology to focus on that technology without having to maintain several repositories that submodule the same common code. You can think of a multi-component plugin as being in some ways analogous to Terraform providers, in the sense that both frequently bundle common resources or components by hypervisor or cloud.
+
+Second, the new server provides the Packer core with structured metadata that allows the new `packer init` feature to work. This data includes semantic versioning that we need to implement the new [`required_plugins`](/packer/docs/templates/hcl_templates/blocks/packer#specifying-plugin-requirements) block, which allows us to ensure that users are using the correct _version_ of their plugin for a given Packer template. If you don't upgrade, your users cannot take advantage of the `packer init` tooling.
+
+### How to upgrade the plugin
+
+We've created a [scaffolding repository](https://github.com/hashicorp/packer-plugin-scaffolding/) that you can either clone or use as a reference example. If you already have a working plugin, it should look pretty familiar. You'll notice, however, that there are some changes to main.go.
+
+Previously, you may have had a main.go that looks something like:
+
+```go
+package main
+
+import (
+ "github.com/hashicorp/packer-plugin-sdk/plugin"
+)
+
+func main() {
+ server, err := plugin.Server()
+ if err != nil {
+ panic(err)
+ }
+
+ // MyProvisioner fulfils the Provisioner interface and is defined elsewhere
+ server.RegisterProvisioner(new(MyProvisioner))
+ server.Serve()
+}
+
+```
+
+With this single-component plugin binary you'd install it by putting it into the plugin directory with the name `packer-provisioner-foo`, and to access your provisioner in your Packer template, you would use the type `foo`.
+
+To use the new multi-component server, you'll want to use the NewSet() function to create a server:
+
+```go
+package main
+
+import (
+ "fmt"
+ "os"
+
+ "github.com/hashicorp/packer-plugin-sdk/plugin"
+)
+
+func main() {
+ pps := plugin.NewSet()
+ pps.RegisterProvisioner(plugin.DEFAULT_NAME, new(MyProvisioner))
+ err := pps.Run()
+ if err != nil {
+ fmt.Fprintln(os.Stderr, err.Error())
+ os.Exit(1)
+ }
+}
+
+```
+
+The implementation is similar, but now we use the "NewSet" function to create the component Server, and call Run() instead of Serve().
+
+You build it as you would any Go binary:
+
+```go
+go build -o packer-plugin-bar
+```
+
+Then you install it by putting it into the plugin directory with the name `packer-plugin-foo`, and reference it in your template using the type "foo".
+
+Notice that the new naming convention uses the generic name "plugin" as opposed to saying the specific component type like the old style did; `packer-pluign-name` instead of `packer-provisioner-name`. You need to respect this new convention when installing the plugin, or Packer will not register it as a multi-component plugin.
+
+What does that `plugin.DEFAULT_NAME` do? It tells the Packer core that in your template you'll be using the root plugin name instead of a compound name composed of the plugin name and the component name. If you are only serving a single component, you may want to use `plugin.DEFAULT_NAME` to prevent your templates from stuttering.
+
+Here's an example using a custom string instead of `plugin.DEFAULT_NAME`:
+
+```go
+pps.RegisterProvisioner("bar", new(MyProvisioner))
+```
+
+When you do this, if you install your plugin as `packer-plugin-foo`, the Packer core expects you to access the provisioner in your template using the type `foo-bar`, where "foo" is the last portion of the plugin name as installed and "bar" is the name of the provisioner that you registered.
+
+## Registering multiple components
+
+The goal of this guide is to help you upgrade a single-component plugin to use the new SDK and plugin server; check out our [Plugin Development Basics](/packer/docs/plugins/creation#plugin-development-basics) guide for details on how to add new components to your plugin.
+
+## Distributing migrated plugins
+
+Once a plugin has been migrated to use the `packer-plugin-sdk` it can be released as it normally would and used by Packer by [installing the plugin](/packer/docs/plugins#installing-plugins) manually into the Packer plugin directory. But this method will not allow your users to take advantage of the `packer init` command.
+
+If you want Packer to be able to automatically install your plugin for your users via`packer init` -- the preferred method of installation -- you need to make the plugin available on GitHub in a repository named after the multi-component plugin. `https://github.com/<yourorg>/packer-plugin-name`. We recognize that this may require you to rename or fork your plugin repository, but we think that it is worth the inconvenience to reduce ambiguity in the `init` call.
+
+See our documentation on [Creating a GitHub Release](/packer/docs/plugins/creation#creating-a-github-release) for details on the recommended practice for releasing Packer plugins on GitHub.
diff --git a/v1.9.4/website/content/guides/1.7-template-upgrade.mdx b/v1.9.4/website/content/guides/1.7-template-upgrade.mdx
new file mode 100644
index 0000000..e30bc1e
--- /dev/null
+++ b/v1.9.4/website/content/guides/1.7-template-upgrade.mdx
@@ -0,0 +1,185 @@
+---
+page_title: Upgrading your template to use Packer init
+description: >-
+ Use packer init and the required_plugins block to better control plugin usage within Packer templates. Learn how to update your template to work with these new features.
+---
+
+# Upgrading your template to be compatible with `packer init`
+
+The `packer init` command introduced in version v1.7.0 benefits Packer users by providing better control of plugin
+usage within a Packer template configuration.
+
+In short, `packer init` will look at the `required_plugins` block definition within a template, and download the correct
+binaries for that template. For details about how the command works and where the plugins will be installed, please
+refer to the [`packer init`](/packer/docs/commands/init) documentation.
+
+-> **Note:** `packer init` is only supported for HCL templates. You can
+upgrade legacy JSON templates to HCL using the [hcl2_upgrade](/packer/docs/commands/hcl2_upgrade) command.
+
+## Updating your template with the `required_plugins` block
+
+## FAQs
+
+### Why do you need to upgrade your template?
+
+To use the `packer init` command, you must upgrade your template to use the `required_plugins` block. The `init` command
+won't work if no `required_plugins` is provided.
+
+We strongly encourage you to upgrade and start using `required_plugins` block within your templates to manage plugin
+installation, but if you prefer not to use the `required_plugins` block you can continue to
+[install plugins manually](/packer/docs/plugins#installing-plugins).
+
+### What if you only use components that are built into the Packer core?
+
+You don't need `packer init` for this, as of v1.7.0. But it's a good idea to get familiar with the required_plugins
+block anyway, because we are going to start splitting popular HashiCorp-maintained components like the amazon-ebs
+builder out of the core into their own multi-component plugins. When we do split these plugins out of the core, we will
+provide a tool to help you create the correct required_plugins block.
+
+### When should you upgrade your template?
+
+The `packer init` command can only install plugins that have been upgraded to use the latest version of the
+[Packer Plugin SDK](https://github.com/hashicorp/packer-plugin-sdk), and therefore are compatible with Packer's API
+version v5.0. The plugin repository on GitHub also needs to use a specific release format. If you are not sure whether
+the plugin you use fits those requirements, you can reach out to your maintainer to ask. You can also look for clues
+that the plugin is ready for use with `packer init`:
+
+- Check the plugin's CHANGELOG for notes about migrating to the packer-plugin-sdk.
+- Check the name of the repository the plugin resides in. Chances are that if the repository follows the naming
+ convention `packer-plugin-*` (e.g. `packer-plugin-comment`), then the plugin has been upgraded to be compatible with
+ `packer init`. If the repository has a name that references a specific Packer component (for example,
+ `packer-provisioner-*`, `packer-builder-*`, or `packer-post-processor-*`) then the plugin likely still needs to be
+ upgraded to be compatible with `packer init`. Reach out to your plugin maintainer to request that they upgrade; the
+ Packer team has written a maintainer-focused guide [here](/packer/guides/1.7-plugin-upgrade).
+
+If the plugin(s) have been upgraded, then they can be used with the `required_plugins` block in your upgraded template.
+
+#### What if the plugin you need is not upgraded to API v5.0?
+
+Since the SDK is being released at the same time as the `init` command, plugin users may face a gap between when the
+Packer core v1.7.0 is released, and the plugins you use are upgraded by their maintainers. The Packer team is getting
+in touch with all currently known plugin maintainers to provide support during their upgrade process.
+
+If you are willing to upgrade your template but found out that the plugin you are using hasn't been upgraded yet,
+we suggest you reach out to the plugin maintainers and ask for an upgrade; the Packer team has written a
+maintainer-focused guide [here](/packer/guides/1.7-plugin-upgrade).
+
+Check the table below to better understand whether your plugin is compatible with `packer init`, with manual
+installation, or with both for the the Packer version you are using.
+
+| Packer Core Version | Single Component Plugin - API v4 | Single Component Plugin - API v5.0 | Multi Component Plugin - API v5.0 |
+| ------------------- | ------------------------------------------------- | ------------------------------------------------- | --------------------------------------------------------- |
+| v1.5.0 to v1.6.6 | ✋ Plugin must be manually installed | ⛔ Plugin cannot be used with this Packer version | ⛔ Plugin cannot be used with this Packer version |
+| v1.7.0 | ⛔ Plugin cannot be used with this Packer version | ✋ Plugin must be manually installed | 📦 Plugin can be installed manually or with `packer init` |
+
+### How to upgrade your template
+
+Let's use the following template as an example:
+
+```hcl
+# file: example.pkr.hcl
+
+source "null" "basic-example" {
+ communicator = "none"
+}
+
+build {
+ sources = ["sources.null.basic-example"]
+
+ provisioner "comment" {
+ comment = "Hello from comment plugin"
+ ui = true
+ bubble_text = true
+ }
+}
+```
+
+This template uses the example [packer-provisioner-comment](https://github.com/sylviamoss/packer-plugin-comment) plugin.
+Until Packer v1.7.0, the binaries were installed manually.
+
+Since the Packer v1.7.0 release, the plugin has been upgraded by its maintainers and is now called
+`packer-plugin-comment`. with its latest version being v0.2.23. Knowing that, our example template can be upgraded to
+use the `required_plugins` block.
+
+```hcl
+# file: example.pkr.hcl
+
+packer {
+ required_plugins {
+ comment = {
+ version = ">=v0.2.23"
+ source = "github.com/sylviamoss/comment"
+ }
+ }
+}
+
+source "null" "basic-example" {
+ communicator = "none"
+}
+
+build {
+ sources = ["sources.null.basic-example"]
+
+ provisioner "comment" {
+ comment = "Hello from comment plugin"
+ ui = true
+ bubble_text = true
+ }
+}
+```
+
+The upgraded template is now telling Packer that it requires a plugin named `comment` stored in a github repository
+owned by the user `sylviamoss`. It also says that the template needs to use a version of the plugin equal to or greater
+than `v0.2.23`. Finally, the local_name of the plugin will be `comment`, which means it will be referred to as `comment`
+in the rest of the template.
+
+Here it is a brief explanation of each field:
+
+- `version` - Should follow the [version constraints](/packer/docs/templates/hcl_templates/blocks/packer#version-constraints).
+- `source` - Should have the GitHub hostname, the plugin's organizational namespace, and its short name.
+ Packer will be responsible for determining the full GitHub
+ address. For example, if the source is `github.com/sylviamoss/comment`, Packer
+ will download the binaries from `github.com/sylviamoss/packer-plugin-comment`.
+ To learn more about the source field, check out the [Source
+ Address](/packer/docs/plugins#source-addresses) documentation.
+- `local_name`- Can be replaced with whatever you want, and the new value will become the name of the plugin.
+ For example:
+
+ ```hcl
+ packer {
+ required_plugins {
+ bubbled_up = {
+ # ...
+ }
+ }
+ }
+
+ # ...
+
+ build {
+ # ...
+
+ provisioner "bubbled_up" {
+ # ...
+ }
+ }
+ ```
+
+Once the template is upgraded, you can run `packer init example.pkr.hcl` and the output should tell you the installed
+plugin, and the place where it was installed.
+
+```shell
+➜ packerdev init example.pkr.hcl
+Installed plugin sylviamoss/comment v0.2.23 in "/Users/<user>/.packer.d/plugins/github.com/sylviamoss/comment/packer-plugin-comment_v0.2.23_x5.0_darwin_amd64"
+```
+
+`packer init` will only download plugin binaries and never delete existing ones. If all the required plugins are installed,
+the command won't do anything unless you set the `-upgrade` flag to force download newer versions of the existing plugins.
+
+You can uninstall a plugin by deleting it from the `.packer.d/plugins/` directory on your computer.
+
+Now that the required comment plugin is installed via `packer init`, you can run `packer build example.pkr.hcl` as usual
+and won't need to run `init` again unless you want to upgrade the plugin version.
+
+A template with a `required_plugins` block should **always** be initialised at least once with `packer init` before
+`packer build`. If the template is built before init, Packer will fail and ask for initialisation.
diff --git a/v1.9.4/website/content/guides/automatic-operating-system-installs/autounattend_windows.mdx b/v1.9.4/website/content/guides/automatic-operating-system-installs/autounattend_windows.mdx
new file mode 100644
index 0000000..e36354d
--- /dev/null
+++ b/v1.9.4/website/content/guides/automatic-operating-system-installs/autounattend_windows.mdx
@@ -0,0 +1,89 @@
+---
+page_title: Unattended Windows Installation
+description: |-
+ Learn how to use an autounattend file to automatically answer installation
+ questions and enable Packer to connect to your Windows instance.
+---
+
+# Unattended Installation for Windows
+
+Unattended Windows installation is done via "Answer Files", or "Unattend files".
+
+These files are generally named "autounattend.xml". They are not
+Packer-specific tools, though we do make use of them.
+
+If, after following this guide, you're still having issues getting an answer
+file working, We recommend you read the official documentation on
+[answer files](https://docs.microsoft.com/en-us/windows-hardware/manufacture/desktop/update-windows-settings-and-scripts-create-your-own-answer-file-sxs).
+
+The guide here is hopefully enough to get you started, but isn't a replacement
+for the official documentation.
+
+## When To Use an Answer File
+
+If you are installing the Windows Operating System from a mounted iso as part of
+your Packer build, you will need to use an Answer file. For example, you're
+building an image from scratch using the [vmware-iso](/packer/plugins/builders/vmware/iso),
+[virtualbox-iso](/packer/plugins/builders/virtualbox/iso), or
+[hyperv-iso](/packer/plugins/builders/hyperv/iso) builders.
+
+If you are not installing the operating system, you won't need to provide an
+answer file. If you are using a pre-built image
+in a cloud, you don't need to worry about Answer files.
+
+## How to make an Answer File
+
+You can either start from an example answer file from a known repo (take a look
+at the examples links below), or you can generate one using an answer file
+wizard by selecting New File > New Answer file on a Windows machine.
+A comprehensive list of all the options you can set in an answer file can be
+found [here](https://docs.microsoft.com/en-us/windows-hardware/customize/desktop/unattend/components-b-unattend)
+
+## Where to put the Answer File
+
+Windows will automatically look for an autounattend.xml file on mounted drives.
+Many users use the `floppy_files` option or a secondary mounted iso for
+providing the answer file to their iso builders.
+
+You can also specify an unattend file to use by using the /unattend: option when
+running Windows Setup (setup.exe) in your `boot_command`.
+
+## What does Packer _need_ the Answer File to do?
+
+Packer needs the Answer File to handle any questions that would normally be
+answered interactively during a Windows installation.
+
+If you want to be able to use provisioners, the Answer file must also contain
+a script that sets up SSH or WinRM so that Packer can connect to the instance.
+
+Finally, your Packer build will be much smoother if the Answer File handles or
+disables Windows updates rather than you trying to run them using a Packer
+provisioner. This is because the winrm communicator does not handle the
+disconnects caused by automatic reboots in Windows updates well, and the
+disconnections can fail a build.
+
+## Examples
+
+The chef-maintained bento boxes are a great example of a Windows build that
+sets up openssh as part of the unattended installation so that Packer can
+connect using the SSH communicator. The functioning answer files for every
+modern Windows version can be found [here](https://github.com/chef/bento/tree/master/packer_templates/win_answer_files).
+
+Stefan Scherer's [packer-windows repo](https://github.com/StefanScherer/packer-windows)
+is a great example of Windows builds that set up WinRM as part of the unattended
+installation so that Packer can connect using the `winrm` communicator:
+
+```json
+{
+ "type": "virtualbox-iso",
+ "guest_os_type": "Windows2008_64",
+ "iso_url": "https://download.microsoft.com/download/7/5/E/75EC4E54-5B02-42D6-8879-D8D3A25FBEF7/7601.17514.101119-1850_x64fre_server_eval_en-us-GRMSXEVAL_EN_DVD.iso",
+ "iso_checksum": "sha256:30832AD76CCFA4CE48CCB936EDEFE02079D42FB1DA32201BF9E3A880C8ED6312",
+ "shutdown_command": "shutdown /s /t 10 /f /d p:4:1 /c Packer_Provisioning_Shutdown",
+ "guest_additions_mode": "attach",
+ "floppy_files": ["./scripts/Autounattend.xml", "./scripts/openssh.ps1"],
+ "communicator": "winrm",
+ "winrm_username": "vagrant",
+ "winrm_password": "vagrant"
+}
+```
diff --git a/v1.9.4/website/content/guides/automatic-operating-system-installs/index.mdx b/v1.9.4/website/content/guides/automatic-operating-system-installs/index.mdx
new file mode 100644
index 0000000..872df2d
--- /dev/null
+++ b/v1.9.4/website/content/guides/automatic-operating-system-installs/index.mdx
@@ -0,0 +1,23 @@
+---
+page_title: Automatic OS Installs
+description: |-
+ Learn how to use preseed, kickstart, and autounattend files to automatically
+ answer installation questions and enable Packer to connect to your instance.
+---
+
+# Automatic OS Installs
+
+If you are building from a brand-new and unconfigured operating system
+image, Packer will need you to perform the operating system install before it
+can connect to and configure your image using its provisioners. Most operating
+system distributions have a mechanism for performing the normally-interactive
+installation in an automated way. For Debian operating systems, this is done
+using a preseed file; for Windows, it's done using an Autounattend.xml. We have
+compiled some simple guides here for common operating system distributions.
+
+These guides are meant to give you a quick introduction to how to use automated
+installation answer files in order to perfom those installs; we don't mean to
+be a comprehensive guide on each operating system, but we hope to give you
+enough context to be able to more easily find any further information you need.
+
+Refer to the instructions for your operating system.
diff --git a/v1.9.4/website/content/guides/automatic-operating-system-installs/preseed_ubuntu.mdx b/v1.9.4/website/content/guides/automatic-operating-system-installs/preseed_ubuntu.mdx
new file mode 100644
index 0000000..c5c9ea2
--- /dev/null
+++ b/v1.9.4/website/content/guides/automatic-operating-system-installs/preseed_ubuntu.mdx
@@ -0,0 +1,176 @@
+---
+page_title: Unattended Debian/Ubuntu Installation
+description: |-
+ Learn how to use a preseed file to automatically answer installation
+ questions and enable Packer to connect to your Debian instance.
+---
+
+# Unattended Installation for Debian
+
+Unattended Debian/Ubuntu installation is done via "preseed" files
+
+These files are generally named "preseed.cfg". They are not
+Packer-specific tools, though we do make use of them.
+
+If, after following this guide, you're still having issues getting a preseed
+file working, We recommend you read the official documentation on
+[preseed files](https://wiki.debian.org/DebianInstaller/Preseed).
+
+The guide here is hopefully enough to get you started, but isn't a replacement
+for the official documentation.
+
+## When To Use a Preseed File
+
+If you are installing the operating system from a mounted iso as part of
+your Packer build, you will need to use a preseed file. For example, you're
+building an image from scratch using the [vmware-iso](/packer/plugins/builders/vmware/iso),
+[virtualbox-iso](/packer/plugins/builders/virtualbox/iso), or
+[hyperv-iso](/packer/plugins/builders/hyperv/iso) builders.
+
+If you are not installing the operating system, you won't need to provide a
+preseed file. If you are using a pre-built image in a cloud, you don't need to
+worry about preseed files.
+
+## How to make a Preseed File
+
+You can either start from an example preseed file from a known repo (take a look
+at the examples links below), or you can start with the official [example
+preseed](https://www.debian.org/releases/stable/example-preseed.txt), and
+comment or uncomment the options as you need them.
+
+## Where to put the preseed file
+
+The `-iso` builders mentioned above all have an `http_dir` or an `http_content`
+option. Any file inside of your `http_dir` or `http_content` will be served on a
+local fileserver for your virtual machine to be able to access. One very common
+use for this directory is to use it to provide your preseed file.
+
+You then reference the file using a `boot_command` to kick off the installation.
+In the example below, see how the `preseed/url` command line option is being
+used in the `/install/vmlinuz command`. The `{{ .HTTPIP }}` and
+`{{ .HTTPPort }}` options are special Packer template options that will get set
+by Packer to point to the HTTP server we create, so that your boot command can
+access it. For an example of a working boot_command, see the Examples section
+below. For more information on how boot_command works, see the
+boot_command section of the docs for whatever builder you are using.
+
+## What does Packer _need_ the preseed file to do?
+
+Packer needs the preseed file to handle any questions that would normally be
+answered interactively during a Debian installation.
+
+If you want to be able to use provisioners, the preseed file must also install
+SSH so that Packer can connect to the instance.
+
+## Examples
+
+A very minimal example of a preseed file can be found below. Much of this was
+copied from the official example-preseed shared above. Notice that we are
+installing ssh via `d-i pkgsel/include string openssh-server` and configuring
+a username so that Packer will be able to connect.
+
+You need to make sure that your mirror settings are properly configured for your
+specific distribution of Debian.
+
+```shell
+# Preseeding only locale sets language, country and locale.
+d-i debian-installer/locale string en_US
+
+# Keyboard selection.
+d-i console-setup/ask_detect boolean false
+d-i keyboard-configuration/xkb-keymap select us
+
+choose-mirror-bin mirror/http/proxy string
+
+### Clock and time zone setup
+d-i clock-setup/utc boolean true
+d-i time/zone string UTC
+
+# Avoid that last message about the install being complete.
+d-i finish-install/reboot_in_progress note
+
+# This is fairly safe to set, it makes grub install automatically to the MBR
+# if no other operating system is detected on the machine.
+d-i grub-installer/only_debian boolean true
+
+# This one makes grub-installer install to the MBR if it also finds some other
+# OS, which is less safe as it might not be able to boot that other OS.
+d-i grub-installer/with_other_os boolean true
+
+### Mirror settings
+# If you select ftp, the mirror/country string does not need to be set.
+d-i mirror/country string manual
+d-i mirror/http/directory string /ubuntu/
+d-i mirror/http/hostname string archive.ubuntu.com
+d-i mirror/http/proxy string
+
+### Partitioning
+d-i partman-auto/method string lvm
+
+# This makes partman automatically partition without confirmation.
+d-i partman-md/confirm boolean true
+d-i partman-partitioning/confirm_write_new_label boolean true
+d-i partman/choose_partition select finish
+d-i partman/confirm boolean true
+d-i partman/confirm_nooverwrite boolean true
+
+### Account setup
+d-i passwd/user-fullname string vagrant
+d-i passwd/user-uid string 1000
+d-i passwd/user-password password vagrant
+d-i passwd/user-password-again password vagrant
+d-i passwd/username string vagrant
+
+# The installer will warn about weak passwords. If you are sure you know
+# what you're doing and want to override it, uncomment this.
+d-i user-setup/allow-password-weak boolean true
+d-i user-setup/encrypt-home boolean false
+
+### Package selection
+tasksel tasksel/first standard
+d-i pkgsel/include string openssh-server build-essential
+d-i pkgsel/install-language-support boolean false
+
+# disable automatic package updates
+d-i pkgsel/update-policy select none
+d-i pkgsel/upgrade select full-upgrade
+```
+
+Here's an example of the vmware-iso builder being used to call this preseed.
+In this case, it is assumed that the file is saved as preseed.cfg inside of a
+directory called "http", and Packer is being called from the directory
+containing the "http" directory.
+
+```hcl
+ "builders": [
+ {
+ "boot_command": [
+ "<esc><wait>",
+ "<esc><wait>",
+ "<enter><wait>",
+ "/install/vmlinuz<wait>",
+ " initrd=/install/initrd.gz",
+ " auto-install/enable=true",
+ " debconf/priority=critical",
+ " preseed/url=http://{{ .HTTPIP }}:{{ .HTTPPort }}/preseed_2.cfg<wait>",
+ " -- <wait>",
+ "<enter><wait>"
+ ],
+ "boot_wait": "10s",
+ "guest_os_type": "ubuntu-64",
+ "http_directory": "http",
+ "iso_checksum": "file:///Users/mmarsh/dev/repro_cases/packer_cache/shasums.txt",
+ "iso_url": "http://old-releases.ubuntu.com/releases/14.04.1/ubuntu-14.04.1-server-amd64.iso",
+ "shutdown_command": "echo 'vagrant' | sudo -S shutdown -P now",
+ "ssh_password": "vagrant",
+ "ssh_username": "vagrant",
+ "ssh_wait_timeout": "10000s",
+ "tools_upload_flavor": "linux",
+ "type": "vmware-iso"
+ }
+ ],
+```
+
+For more functional examples of a debian preseeded installation, you can see the
+Chef-maintained bento boxes for [Debian](https://github.com/chef/bento/tree/master/packer_templates/debian)
+and [Ubuntu](https://github.com/chef/bento/tree/master/packer_templates/ubuntu)
diff --git a/v1.9.4/website/content/guides/hcl/component-object-spec.mdx b/v1.9.4/website/content/guides/hcl/component-object-spec.mdx
new file mode 100644
index 0000000..9ca8c29
--- /dev/null
+++ b/v1.9.4/website/content/guides/hcl/component-object-spec.mdx
@@ -0,0 +1,41 @@
+---
+page_title: Generating code for config spec.
+description: Learn how to generate the HCL2 configuration of your component easily.
+---
+
+# Auto Generate the HCL2 code of a plugin
+
+From v1.5, Packer can be configured using HCL2. Because Packer has so many
+builders, provisioners, and post-processors, we created a on code generation
+tool to add the HCL2-enabling code more easily. You can use this code generator
+to create the HCL2 spec code of your custom plugin simply.
+It's a Go binary package made available through the Packer plugin SDK
+
+Say you want to configure the `Config` struct of a `Builder` in a package
+located in `my/example-plugin/config.go`. Here are some simple steps you can
+follow to make it HCL2 enabled:
+
+- run `go install github.com/hashicorp/packer-plugin-sdk/cmd/packer-sdc@latest`
+
+- Add `//go:generate packer-sdc mapstructure-to-hcl2 -type Config` at the top of
+ `config.go`
+
+- run `go generate ./my/example-plugin/...`
+
+ This will generate a `my/example-plugin/config.hcl2spec.go` file containing
+ the configuration fields of `Config`.
+
+- Make sure that all the nested structs of `Config` are also auto generated the
+ same way.
+
+- Now we only need to make your Builder implement the interface by adding the
+ following snippet:
+
+ ```go
+ func (b *Builder) ConfigSpec() hcldec.ObjectSpec { return b.config.FlatMapstructure().HCL2Spec() }
+ ```
+
+ From now on every time you add or change a field of Config you will need to
+ run the `go generate` command again.
+
+A good example of this is the [Config struct of the amazon-ebs builder](https://github.com/hashicorp/packer-plugin-amazon/blob/main/builder/ebs/builder.go)
diff --git a/v1.9.4/website/content/guides/hcl/index.mdx b/v1.9.4/website/content/guides/hcl/index.mdx
new file mode 100644
index 0000000..aa8d779
--- /dev/null
+++ b/v1.9.4/website/content/guides/hcl/index.mdx
@@ -0,0 +1,90 @@
+---
+page_title: Getting started configuring Packer with HCL2 files
+description: >-
+ Use the HCL2 syntax for your Packer templates. Learn about arguments and blocks, comments, and multi-line strings.
+---
+
+# Introduction to Packer HCL2
+
+@include 'guides/hcl2-beta-note.mdx'
+
+It is not necessary to know all of the details of the HCL syntax in order to
+use Packer, and so this page summarizes the most important details to get you
+started. If you are interested, you can find a [full definition of HCL
+syntax](https://github.com/hashicorp/hcl2/blob/master/hcl/hclsyntax/spec.md) in
+the HCL native syntax specification.
+
+## Arguments and Blocks
+
+The HCL syntax is built around two key syntax constructs: arguments and blocks.
+
+```hcl
+# block
+source "amazon-ebs" "example" {
+
+ # argument
+ ami_name = "abc123"
+}
+```
+
+## Comments
+
+The HCL language supports three different syntaxes for comments:
+
+- `#` begins a single-line comment, ending at the end of the line.
+- `//` also begins a single-line comment, as an alternative to `#`.
+- `/*` and `*/` are start and end delimiters for a comment that might
+ span over multiple lines.
+
+## Multi-line strings
+
+A multi-line string value can be provided using heredoc syntax.
+
+```hcl
+variable "long_key" {
+ type = "string"
+ default = <<EOF
+This is a long key.
+Running over several lines.
+It could be super handy for a boot_command.
+EOF
+}
+```
+
+## Building blocks can be split in files
+
+Currently Packer offers the `source` and the `build` root blocks. These two
+building blocks can be defined in any order and a `build` can import one or more
+`source`. Usually a `source` defines what we currently call a builder and a
+`build` can apply multiple provisioning steps to a source. For example:
+
+```hcl
+# folder/sources.pkr.hcl
+source "amazon-ebs" "example-1" {
+ ami_name = "example-1-ami"
+}
+
+source "virtualbox-iso" "example-2" {
+ boot_command = <<EOF
+<esc><esc><enter><wait>
+/install/vmlinuz noapic
+...
+EOF
+}
+```
+
+```hcl
+# folder/build.pkr.hcl
+build {
+ sources = [
+ "source.amazon-ebs.example-1",
+ "source.virtualbox-iso.example-2"
+ ]
+
+ provisioner "shell" {
+ inline = [
+ "echo 'it is alive !'"
+ ]
+ }
+}
+```
diff --git a/v1.9.4/website/content/guides/hcl/variables.mdx b/v1.9.4/website/content/guides/hcl/variables.mdx
new file mode 100644
index 0000000..b8952c7
--- /dev/null
+++ b/v1.9.4/website/content/guides/hcl/variables.mdx
@@ -0,0 +1,373 @@
+---
+page_title: Input and Local Variables guide
+description: |-
+ This page introduces input variables and local variables as a way to
+ parameterize a configuration.
+---
+
+# Input Variables and local variables
+
+@include 'guides/hcl2-beta-note.mdx'
+
+This page introduces input variables and local variables as a way to
+parameterize a configuration. Once defined, input variables are settable from a
+default value, environment, special var files, and command line arguments.
+Local variables can be a compound of input variables and local variables.
+
+## Defining Variables and locals
+
+In the legacy JSON Packer templates, any variables we hadn't already defined in
+the "variables" stanza of our json template could simply be passed in via the
+command line or a `var-file`; if a variable was never defined it would generally
+be interpolated to an empty string.
+
+_In the HCL2 Packer templates, we must always pre-define our variables in the
+HCL equivalent of the "variables" stanza._
+
+Another difference between JSON and HCL Packer templates is that in JSON packer
+templates, the "variables" stanza, if used, was always in the same .json file
+as the builds and builders. In HCL, it can exist in its own file if you want it
+to.
+
+To demonstrate, let's create a file `variables.pkr.hcl` with the following
+contents.
+
+-> **Note**: that the file can be named anything, since Packer loads all
+files ending in `.pkr.hcl` in a directory. If you split your configuration
+across multiple files, use
+`packer build <command line flags> <source directory>` to initiate a build.
+
+```hcl
+// variables.pkr.hcl
+
+// For those variables that you don't provide a default for, you must
+// set them from the command line, a var-file, or the environment.
+
+variable "weekday" {}
+
+variable "sudo_password" {
+ type = string
+ default = "mypassword"
+ // Sensitive vars are hidden from output as of Packer v1.6.5
+ sensitive = true
+}
+
+variable "flavor" {
+ type = string
+ default = "strawberry"
+}
+
+variable "exit_codes" {
+ type = list(number)
+ default = [0]
+}
+
+locals {
+ ice_cream_flavor = "${var.flavor}-ice-cream"
+ foo = "bar"
+}
+```
+
+This defines several variables within your Packer configuration, each showing
+off a different way to set them. The first variable, "weekday", is an empty
+block `{}`, without a type or a default.
+
+However, it's generally best to provide the type in your variable definition,
+as you can see in variable "flavor", which we have given a type of "string",
+and variable "exit_codes", which we have given a type of "list(number)",
+meaning it is a list/array of numbers.
+
+When a variable is passed from the cli or environment and the variable's type
+is not set, Packer will expect it to be a string. But if it is passed from a
+var-file where Packer can interpret HCL properly it can be a slice or any
+supported type.
+
+In addition to setting the type, the "flavor" and "exit_codes" variables also
+provide a default. If you set a default value, then you don't need to set the
+variable at run time. Packer will use a provided command-line var,
+var-file, or environment var if it exists, but if not Packer will fall back to
+this default value.
+
+If you do not set a default value, Packer will fail immediately when you try to
+run a `build` if you have not provided the missing variable via the
+command-line, a var-file, or the environment. The `validate`, `inspect` and
+`console` commands will work, but variables with unknown values will be
+`<unknown>`.
+
+This also defines two locals: `ice_cream_flavor` and `foo`.
+
+-> **Note**: that it is _not_ possible to reference a variable in the
+definition of another variable. But it _is_ possible to use locals and
+variables in the definition of a local, as shown in the ice_cream_flavor
+definition.
+
+## Using Variables and locals in Configuration
+
+For simplicity's sake, we're going to put a null source in the same file as
+we are putting the build configuration. This file demonstrates how to use the
+variables we previously defined.
+
+```hcl
+// null_example.pkr.hcl
+
+source "null" "example" {
+ communicator = "none"
+}
+
+build {
+ sources = [
+ "source.null.example"
+ ]
+ provisioner "shell-local" {
+ // Note that for options that are documented as template engines,
+ // we still have to use the Go template engine syntax rather than our
+ // specialized HCL2 variable syntax. This example shows a combination of
+ // an HCL2 variable and the Go template engines built into the
+ // execute_command option
+ execute_command = ["/bin/sh", "-c", "echo ${var.sudo_password}| {{.Vars}} {{.Script}}"]
+ environment_vars = ["HELLO_USER=packeruser", "UUID=${build.PackerRunUUID}"]
+ inline = ["echo the Packer run uuid is $UUID"]
+ }
+ provisioner "shell-local" {
+ inline = ["echo var.flavor is: ${var.flavor}",
+ "echo local.ice_cream_flavor is: ${local.ice_cream_flavor}"]
+ valid_exit_codes = var.exit_codes
+ }
+}
+```
+
+As you can see in the example, you can access your variables directly by
+giving them the `var.` or `local.` prefix. If you want to embed the variables
+in a string, you can do so with the `${}` HCL interpolation syntax. If you are
+using an option that is a template engine, you still need to use the Go
+templating engine syntax `{{ .OPTION }}` for those engines.
+
+## Assigning Variables
+
+There are multiple ways to assign variables. Below is also the order
+in which variable values are chosen. The following is the descending order
+of precedence in which variables are considered. So first defined; first used.
+
+#### Command-line flags
+
+You can set variables directly on the command-line with the
+`-var` flag.:
+
+```shell-session
+$ packer build \
+ -var "weekday=Sunday" \
+ -var "flavor=chocolate" \
+ -var "sudo_password=hunter42" .
+```
+
+Once again, setting variables this way will not save them, and they'll
+have to be input repeatedly as commands are executed.
+
+If you plan to assign variables via the command line, we strongly recommend that
+you at least set a default type instead of using empty blocks; this helps the
+HCL parser understand what is being set. Otherwise it will interpret all of your
+command line variables as strings.
+
+#### From a file
+
+To persist variable values, create a file and assign variables within
+this file. A variable definitions file uses the same basic syntax as Packer language files,
+but consists only of variable name assignments.
+
+```hcl
+sudo_password = "partyparrot"
+weekday = "Sunday"
+```
+
+When assigning values in a variable definitions file please make sure to quote any string values,
+wrap list values within brackets `[...]`, and wrap maps within curly-braces `{...}`.
+
+Given a file named `variables.pkrvars.hcl` Packer can be instructed to use the
+variable definitions file by using the `-var-file` command line flag.
+
+```shell-session
+$ packer build -var-file="variables.pkrvars.hcl" .
+```
+
+Packer will automatically load any var file that matches the name
+`*.auto.pkrvars.hcl`, without the need to pass the file via the command line.
+If we rename the above variable definitions file from `variables.pkrvars.hcl` to
+`variables.auto.pkrvars.hcl`, then we can run our build simply by calling
+
+```shell-session
+$ packer build .
+```
+
+You may provide as many -var-file flags as you would like:
+
+```shell-session
+$ packer build \
+ -var-file="secret.pkrvars.hcl" \
+ -var-file="production.pkrvars.hcl" .
+```
+
+These files can also be JSON:
+
+variables.json:
+
+```json
+{
+ "weekday": "sunday",
+ "flavor": "mint"
+}
+```
+
+```shell-session
+$ packer build -var-file=variables.json
+```
+
+We don't recommend saving sensitive information to version control, but you
+can create a local secret variables file and use `-var-file` to load it.
+
+You can use multiple `-var-file` arguments in a single command, with some
+checked in to version control and others not checked in. For example:
+
+```shell-session
+$ packer build \
+ -var-file="secret.pkrvars.hcl" \
+ -var-file="production.pkrvars.hcl" .
+```
+
+#### From environment variables
+
+Packer will read environment variables in the form of `PKR_VAR_name` to find
+the value for a variable. For example, the `PKR_VAR_access_key` variable can be
+set to set the `access_key` variable.
+
+```shell-session
+$ export PKR_VAR_weekday=Monday
+$ packer build .
+```
+
+#### Variable Defaults
+
+If no value is assigned to a variable via any of these methods and the
+variable has a `default` key in its declaration, that value will be used
+for the variable.
+
+If all of your variables have defaults, then you can call a packer build using:
+
+```shell-session
+$ packer build .
+```
+
+You can make this work for yourself using the variable example file above by
+commenting out or removing the "weekday" variable declaration, since it is not
+actually used in the example build.
+
+If your variable definitions are stored in the same file as your source and
+build, you can call the build against that specific file:
+
+```shell-session
+$ packer build self_contained_example.pkr.hcl
+```
+
+#### Unspecified Values Fail
+
+If you call `packer build` with any variables defined but not set, Packer will
+error.
+
+## Variable Type Reference
+
+### Lists
+
+Lists are defined either explicitly or implicitly
+
+```hcl
+# implicitly by using brackets [...]
+variable "cidrs" { default = [] }
+
+# explicitly
+variable "cidrs" { type = list }
+```
+
+You can specify lists in a `variables.pkrvars.hcl` file:
+
+```hcl
+cidrs = [ "10.0.0.0/16", "10.1.0.0/16" ]
+```
+
+### Maps
+
+Maps are a way to create variables that are lookup tables. An example
+will show this best. Let's extract our AMIs into a map and add
+support for the `us-west-2` region as well:
+
+```hcl
+variable "amis" {
+ type = map(string)
+ default = {
+ "us-east-1" = "ami-b374d5a5"
+ "us-west-2" = "ami-4b32be2b"
+ }
+}
+```
+
+A variable can have a `map` type assigned explicitly, or it can be implicitly
+declared as a map by specifying a default value that is a map. The above
+demonstrates both.
+
+Then we can `lookup` in maps like in the following:
+
+```hcl
+source "amazon-ebs" "example" {
+ source_ami = "${lookup(var.amis, var.region)}"
+ instance_type = "t2.micro"
+}
+```
+
+This introduces a new type of interpolation: a function call. The
+`lookup` function does a dynamic lookup in a map for a key. The
+key is `var.region`, which specifies that the value of the region
+variables is the key.
+
+You can also do a static lookup of a map directly with
+`${var.amis["us-east-1"]}`.
+
+## Assigning Maps
+
+We set defaults above, but maps can also be set using the `-var` and
+`-var-file` values. For example:
+
+```shell-session
+$ packer build -var 'amis={ us-east-1 = "foo", us-west-2 = "bar" }'
+# ...
+```
+
+Here is an example of setting a map's keys from a file. Starting with these
+variable definitions:
+
+```hcl
+variable "region" {}
+variable "amis" {
+ type = map
+}
+```
+
+You can specify keys in a `variables.pkrvars.hcl` file:
+
+```hcl
+amis = {
+ "us-east-1" = "ami-abc123"
+ "us-west-2" = "ami-def456"
+}
+```
+
+And access them via `lookup()`:
+
+```hcl
+output "ami" {
+ value = "${lookup(var.amis, var.region)}"
+}
+```
+
+Like so:
+
+```shell-session
+$ packer build -var region=us-west-2
+```
diff --git a/v1.9.4/website/content/guides/index.mdx b/v1.9.4/website/content/guides/index.mdx
new file mode 100644
index 0000000..347e876
--- /dev/null
+++ b/v1.9.4/website/content/guides/index.mdx
@@ -0,0 +1,17 @@
+---
+page_title: Guides
+description: |-
+ Welcome to the Packer guides. If you are just getting started with Packer,
+ please see the Packer introduction instead and then continue on to the guides.
+ These guides provide examples for common Packer workflows and actions for
+ users of Packer.
+---
+
+# Packer
+
+Welcome to the Packer guides. If you are just getting started with Packer,
+please see the [Packer introduction][intro] instead and then continue on to the
+guides. These guides provide examples for common Packer workflows and actions
+for users of Packer.
+
+[intro]: /packer/docs/intro
diff --git a/v1.9.4/website/content/guides/packer-on-cicd/build-image-in-cicd.mdx b/v1.9.4/website/content/guides/packer-on-cicd/build-image-in-cicd.mdx
new file mode 100644
index 0000000..4efc595
--- /dev/null
+++ b/v1.9.4/website/content/guides/packer-on-cicd/build-image-in-cicd.mdx
@@ -0,0 +1,29 @@
+---
+page_title: Build Images in CI/CD
+description: >-
+ Learn how to build Packer images within a continuous integration / continuous delivery pipeline.
+---
+
+# Build Images in CI/CD
+
+The following guides from our partners show how to use their services to build
+images with Packer.
+
+- [How to Build Immutable Infrastructure with Packer and CircleCI Workflows](https://circleci.com/blog/how-to-build-immutable-infrastructure-with-packer-and-circleci-workflows/)
+- [Using Packer and Ansible to Build Immutable Infrastructure in CodeShip](https://blog.codeship.com/packer-ansible/)
+
+The majority of the [Packer Builders](/packer/docs/builders) can run just fine in a
+container, a common model used by most CI/CD services. However, while it is
+possible to run many builders in containers or nested virtualization, this may
+require advanced configuration; examples include the [QEMU
+builder](/packer/plugins/builders/qemu) for
+[KVM](https://www.linux-kvm.org/page/Main_Page) or
+[Xen](https://www.xenproject.org/), the [VirtualBox
+builder](/packer/plugins/builders/virtualbox) for OVA or OVF virtual machines, and the
+[VMware builder](/packer/plugins/builders/vmware) for use with VMware products that are
+all designed to run on a bare-metal machine or within nested virtualization.
+
+The [Building a VirtualBox Image with Packer in
+TeamCity](/packer/guides/packer-on-cicd/build-virtualbox-image) guide shows
+how to create a VirtualBox image using TeamCity's support for running scripts
+on bare-metal machines.
diff --git a/v1.9.4/website/content/guides/packer-on-cicd/build-virtualbox-image.mdx b/v1.9.4/website/content/guides/packer-on-cicd/build-virtualbox-image.mdx
new file mode 100644
index 0000000..69e4701
--- /dev/null
+++ b/v1.9.4/website/content/guides/packer-on-cicd/build-virtualbox-image.mdx
@@ -0,0 +1,149 @@
+---
+page_title: Build a VirtualBox Image with Packer in TeamCity
+description: >-
+ Use Packer to build VirtualBox images in TeamCity. Learn how to provision a bare-metal machine, install dependencies, and create and run a build in TeamCity.
+---
+
+# Build a VirtualBox Image with Packer in TeamCity
+
+This guide walks through the process of building a VirtualBox image using
+Packer on a new TeamCity Agent. Before getting started you should have access
+to a TeamCity Server.
+
+The Packer VirtualBox builder requires access to VirtualBox. Virtualization is
+not universally supported on cloud instances, so we recommend you run these
+builds on either a bare metal server, or cloud instances which support nested
+virtualization, such as Azure or GCP. This is also true for the
+[VMware](/packer/plugins/builders/vmware) and the [QEMU](/packer/plugins/builders/qemu)
+Packer builders.
+
+We will use Chef's [Bento boxes](https://github.com/chef/bento) to provision an
+Ubuntu image on VirtualBox. For this example, we will use the repository
+directly, but you may also fork it for the same results.
+
+## 1. Provision a Bare-metal Machine
+
+For the purposes of this example, we will run on a bare-metal instance from
+[Packet](https://www.packet.net/). If you are a first time user of Packet, the
+Packet team has provided HashiCorp the coupon code `hashi25` which you can use
+for `$25` off to test out this guide and up to 30% if you decide to
+reserve ongoing servers (email help@packet.net for details). You can use
+a `baremetal_0` server type for testing, but for regular use, the `baremetal_1`
+instance may be a better option.
+
+There is also a [Packet
+Provider](https://registry.terraform.io/providers/packethost/packet/latest/docs) in
+Terraform you can use to provision the project and instance.
+
+```hcl
+provider "packet" { }
+
+resource "packet_project" "teamcity_agents" {
+ name = "TeamCity"
+}
+
+resource "packet_device" "agent" {
+ hostname = "teamcity-agent"
+ plan = "baremetal_0"
+ facility = "ams1"
+ operating_system = "ubuntu_16_04"
+ billing_cycle = "hourly"
+ project_id = "${packet_project.teamcity_project.id}"
+}
+```
+
+## 2. Install VirtualBox and TeamCity dependencies
+
+VirtualBox must be installed on the new instance, and TeamCity requires the JDK
+prior to installation. This guide uses Ubuntu as the Linux distribution, so you
+may need to adjust these commands for your distribution of choice.
+
+**Install Teamcity Dependencies**
+
+```shell-session
+$ apt-get upgrade
+$ apt-get install -y zip linux-headers-generic linux-headers-4.13.0-16-generic build-essential openjdk-8-jdk
+```
+
+**Install VirtualBox**
+
+```shell-session
+$ curl -OL "https://download.virtualbox.org/virtualbox/5.2.2/virtualbox-5.2_5.2.2-119230~Ubuntu~xenial_amd64.deb"
+$ dpkg -i virtualbox-5.2_5.2.2-119230~Ubuntu~xenial_amd64.deb
+```
+
+You can also use the [`remote-exec`
+provisioner](/terraform/docs/provisioners/remote-exec) in
+your Terraform configuration to automatically run these commands when
+provisioning the new instance.
+
+## 3. Install Packer
+
+The TeamCity Agent machine will also need Packer Installed. You can find the
+latest download link from the [Packer
+Download](/packer/downloads) page.
+
+```shell-session
+$ curl -OL "https://releases.hashicorp.com/packer/1.1.2/packer_1.1.2_linux_amd64.zip"
+$ unzip ./packer_1.1.2_linux_amd64.zip
+```
+
+Packer is installed at the `/root/packer` path which is used in subsequent
+steps. If it is installed elsewhere, take note of the path.
+
+## 4. Install TeamCity Agent
+
+This guide assume you already have a running instance of TeamCity Server. The
+new TeamCity Agent can be installed by [downloading a zip file and installing
+manually](https://confluence.jetbrains.com/display/TCD10//Setting+up+and+Running+Additional+Build+Agents#SettingupandRunningAdditionalBuildAgents-InstallingAdditionalBuildAgents),
+or using [Agent
+Push](https://confluence.jetbrains.com/display/TCD10//Setting+up+and+Running+Additional+Build+Agents#SettingupandRunningAdditionalBuildAgents-InstallingviaAgentPush).
+Once it is installed it should appear in TeamCity as a new Agent.
+
+Create a new Agent Pool for agents responsible for VirtualBox Packer builds and
+assign the new Agent to it.
+
+## 5. Create a New Build in TeamCity
+
+In TeamCity Server, create a new build. To use the upstream Bento repository,
+we'll choose _From a repository URL_, and enter
+`https://github.com/chef/bento.git` as the **Repository URL**.
+
+![TeamCity screenshot: New Build](/img/guides/teamcity_create_project_from_url-1.png)
+
+Click **Proceed**.
+
+![TeamCity screenshot: New Build](/img/guides/teamcity_create_project_from_url-2.png)
+
+And **Proceed** again.
+
+We won't use the _Auto-detected Build Steps_. Instead, click _configure build
+steps manually_. For the _runner type_, pick **Command Line**, and enter the
+following values. Make sure to click _Show advanced options_, as we need to set
+the working directory.
+
+![TeamCity screenshot: Build Step](/img/guides/teamcity_build_configuration.png)
+
+This will use the `build` command in Packer to build the image defined in
+`ubuntu/ubuntu-16.04-amd64.json`. It assumes that the VCS repository you're
+using is a fork of [Chef/Bento](https://github.com/chef/bento). Packer defaults
+to building VirtualBox machines by launching a GUI that shows the console.
+Since this will run in CI/CD, use the [`headless`
+variable](/packer/plugins/builders/virtualbox/iso#headless) to instruct Packer to
+start the machine without the console. Packer can build multiple image types,
+so the [`-only=virtualbox-iso`
+option](/packer/docs/commands/build#only-foo-bar-baz) instructs Packer to only
+build the builds with the name `virtualbox-iso`.
+
+## 6. Run a build in TeamCity
+
+The entire configuration is ready for a new build. Start a new run in TeamCity
+by pressing “Run”.
+
+The new run should be triggered and the virtual box image will be built.
+
+![TeamCity screenshot: Build log](/img/guides/teamcity_build_log.png)
+
+Once complete, the build status should be updated to complete and successful.
+
+![TeamCity screenshot: Build log complete](/img/guides/teamcity_build_log_complete.png)
diff --git a/v1.9.4/website/content/guides/packer-on-cicd/index.mdx b/v1.9.4/website/content/guides/packer-on-cicd/index.mdx
new file mode 100644
index 0000000..d083ed4
--- /dev/null
+++ b/v1.9.4/website/content/guides/packer-on-cicd/index.mdx
@@ -0,0 +1,17 @@
+---
+page_title: Build Immutable Infrastructure with Packer in CI/CD
+description: >-
+ Learn how to use Packer to build immutable infrastructure within a continuous integration / continuous delivery pipeline.
+---
+
+# Build Immutable Infrastructure with Packer in CI/CD
+
+This guide focuses on the following workflow for building immutable
+infrastructure. This workflow can be manual or automated and it can be
+implemented with a variety of technologies. The goal of this guide is to show
+how this workflow can be fully automated using Packer for building images from
+a continuous integration/continuous deployment (CI/CD) pipeline.
+
+1. [Build Images using Packer in CI/CD](/packer/guides/packer-on-cicd/build-image-in-cicd)
+2. [Upload the new image to S3](/packer/guides/packer-on-cicd/upload-images-to-artifact) for future deployment or use during development
+3. [Create new Terraform Enterprise runs](/packer/guides/packer-on-cicd/trigger-tfe) to provision new instances with the images
diff --git a/v1.9.4/website/content/guides/packer-on-cicd/pipelineing-builds.mdx b/v1.9.4/website/content/guides/packer-on-cicd/pipelineing-builds.mdx
new file mode 100644
index 0000000..2a7e692
--- /dev/null
+++ b/v1.9.4/website/content/guides/packer-on-cicd/pipelineing-builds.mdx
@@ -0,0 +1,354 @@
+---
+page_title: Packer Build Pipelines
+description: >-
+ Learn how to shorten Packer build times and improve reliability. Start from an ISO, customize using the virtualbox-ovf builder, and improve efficiency.
+---
+
+# Why Create a Template Pipeline?
+
+A common issue users face when beginning to create their Packer templates is
+that while they may need several specialized images, the early provisioning
+steps are all the same. It can feel tedious to copy all of those images' basic
+configuraton into each build template. It can feel even more tedious to wait a
+long time for similar builds to run duplicate steps.
+
+This is one reason why Packer recommends breaking your builds into small,
+discrete steps. Not only does it allow you to create "base" images that you can
+build from to create further customizations, but it also allows you to save
+time in your build process because the "base" images are likely to change less
+than your customizations.
+
+It also makes it so that a failing build takes less time to debug and re-run.
+
+In this example, we will use the Virtualbox builders, but the concepts from
+this example can be applied to other builders as well.
+
+## Starting from an ISO
+
+Here is an extremely basic virtualbox-iso template:
+
+<Tabs>
+<Tab heading="JSON">
+
+```json
+{
+ "builders": [
+ {
+ "type": "virtualbox-iso",
+ "vm_name": "vbox-example",
+ "boot_command": [
+ "<esc><wait>",
+ "<esc><wait>",
+ "<enter><wait>",
+ "/install/vmlinuz<wait>",
+ " initrd=/install/initrd.gz",
+ " auto-install/enable=true",
+ " debconf/priority=critical",
+ " preseed/url=http://{{ .HTTPIP }}:{{ .HTTPPort }}/ubuntu_preseed.cfg<wait>",
+ " -- <wait>",
+ "<enter><wait>"
+ ],
+ "http_directory": "./http",
+
+ "disk_size": "40960",
+ "guest_os_type": "Ubuntu_64",
+ "iso_checksum": "sha256:946a6077af6f5f95a51f82fdc44051c7aa19f9cfc5f737954845a6050543d7c2",
+ "iso_url": "http://old-releases.ubuntu.com/releases/14.04.1/ubuntu-14.04-server-amd64.iso",
+
+ "shutdown_command": "echo 'vagrant' | sudo -S shutdown -P now",
+
+ "ssh_port": 22,
+ "ssh_username": "vagrant",
+ "ssh_password": "vagrant"
+ }
+ ],
+ "provisioners": [
+ {
+ "type": "shell",
+ "inline": ["echo initial provisioning"]
+ }
+ ],
+ "post-processors": [
+ {
+ "type": "manifest",
+ "output": "stage-1-manifest.json"
+ }
+ ]
+}
+```
+
+</Tab>
+<Tab heading="HCL2">
+
+```hcl
+source "virtualbox-iso" "step_1" {
+ boot_command = ["<esc><wait>", "<esc><wait>", "<enter><wait>",
+ "/install/vmlinuz<wait>", " initrd=/install/initrd.gz",
+ " auto-install/enable=true", " debconf/priority=critical",
+ " preseed/url=http://{{ .HTTPIP }}:{{ .HTTPPort }}/ubuntu_preseed.cfg<wait>",
+ " -- <wait>", "<enter><wait>"]
+ disk_size = "40960"
+ guest_os_type = "Ubuntu_64"
+ http_directory = "./http"
+ iso_checksum = "sha256:946a6077af6f5f95a51f82fdc44051c7aa19f9cfc5f737954845a6050543d7c2"
+ iso_url = "http://old-releases.ubuntu.com/releases/14.04.1/ubuntu-14.04-server-amd64.iso"
+ shutdown_command = "echo 'vagrant' | sudo -S shutdown -P now"
+ ssh_password = "vagrant"
+ ssh_port = 22
+ ssh_username = "vagrant"
+ vm_name = "vbox-example"
+}
+build {
+ sources = ["source.virtualbox-iso.step_1"]
+
+
+ provisioner "shell" {
+ inline = ["echo initial provisioning"]
+ }
+ post-processor "manifest" {
+ output = "stage-1-manifest.json"
+ }
+}
+```
+
+</Tab>
+</Tabs>
+
+In order to build using this template, create a directory named "http" in your
+current working directory. Copy the minimal example from our
+[preseed guide](/packer/guides/automatic-operating-system-installs/preseed_ubuntu#examples)
+into a file in your http directory and name it "ubuntu_preseed.cfg". Copy the
+above json template into your current working directory and save it as
+"example_virtualbox_iso.json"
+
+To run the build, call `packer build example_virtualbox_iso.json`.
+
+This example does not set the output_directory or output_filename, so the file
+will be placed in a default name of "output-virtualbox-iso/vbox-example.ovf" --
+the builder will print this file name to the UI output, but in this example the
+[manifest](/packer/docs/post-processors/manifest) post-processor
+to will store build information, including the names of the output files, in a
+json file named "stage-1-manifest.json". From there, you can programmatically
+look up the output file information.
+
+## Customizing the iso using the virtualbox-ovf builder
+
+That output filename generated in the first stage can be used as the
+[source_path](/packer/plugins/builders/virtualbox/ovf#source_path)
+for the virtualbox-ovf builder.
+
+<Tabs>
+<Tab heading="JSON">
+
+```json
+{
+ "builders": [
+ {
+ "type": "virtualbox-ovf",
+ "vm_name": "virtualbox-example-ovf",
+
+ "shutdown_command": "echo 'vagrant' | sudo -S shutdown -P now",
+ "source_path": "output-virtualbox-iso/vbox-example.ovf",
+
+ "ssh_password": "vagrant",
+ "ssh_port": 22,
+ "ssh_username": "vagrant"
+ }
+ ],
+ "provisioners": [
+ {
+ "inline": ["echo secondary provisioning"],
+ "type": "shell"
+ }
+ ]
+}
+```
+
+</Tab>
+<Tab heading="HCL2">
+
+```hcl
+source "virtualbox-ovf" "step_2" {
+ shutdown_command = "echo 'vagrant' | sudo -S shutdown -P now"
+ source_path = "output-virtualbox-iso/vbox-example.ovf"
+ ssh_password = "vagrant"
+ ssh_port = 22
+ ssh_username = "vagrant"
+ vm_name = "virtualbox-example-ovf"
+}
+
+build {
+ sources = ["source.virtualbox-ovf.step_2"]
+
+ provisioner "shell" {
+ inline = ["echo secondary provisioning"]
+ }
+}
+
+```
+
+</Tab>
+</Tabs>
+
+## More efficiencies
+
+You may find that you want to run time-consuming import post-processors like
+the "amazon-import" post-processor independently of the build that produces
+the artifacts you want to process.
+
+In this case, you can use a null builder
+and manually modify the input to the post-processing chain so that you can get
+the behavior you want. The below example shows a "vagrant" post-processor
+being used with a null builder, and manually sets the artifact from our
+stage-2 ovf build:
+
+<Tabs>
+<Tab heading="JSON">
+
+```json
+{
+ "builders": [
+ {
+ "type": "null",
+ "communicator": "none"
+ }
+ ],
+ "post-processors": [
+ [
+ {
+ "type": "artifice",
+ "files": [
+ "output-virtualbox-ovf/virtualbox-example-ovf.ovf",
+ "output-virtualbox-ovf/virtualbox-example-ovf-disk001.vmdk"
+ ]
+ },
+ {
+ "type": "vagrant",
+ "provider_override": "virtualbox"
+ }
+ ]
+ ]
+}
+```
+
+</Tab>
+<Tab heading="HCL2">
+
+```hcl
+source "null" "step_3" {
+ communicator = "none"
+}
+
+build {
+ sources = ["source.null.step_3"]
+
+ post-processors {
+ post-processor "artifice" {
+ files = ["output-virtualbox-ovf/virtualbox-example-ovf.ovf", "output-virtualbox-ovf/virtualbox-example-ovf-disk001.vmdk"]
+ }
+ post-processor "vagrant" {
+ provider_override = "virtualbox"
+ }
+ }
+}
+```
+
+</Tab>
+</Tabs>
+
+By using the null builder instead of just running an ovf builder, we can spare
+ourselves all of the time Packer would normally spend launching and destroying
+VMs.
+
+## Putting it all together
+
+Packer templates don't come with a custom "glue" to bind them together. We
+recommend using your CI system or wrapping scripts to connect the templates
+into a chain.
+
+## Chaining together several of the same builders to make "save points"
+
+If you want to use the same builder for several builds in a row, this can feel
+tedious to implement in json. We recommend you try using HCL configs so that
+you can reuse the same source in several builds:
+
+HCL templates work by allowing you to draw sources and variables from multiple
+different files in a single directory, so the following files are assumed to
+exist in their own folder:
+
+sources.pkr.hcl
+
+```hcl
+// In your sources file, you can create a configuration for a builder that you
+// want to reuse between multiple steps in the build. Just leave the source
+// and destination images out of this source, and set them specifically in each
+// step without having to set all of the other options over and over again.
+
+source "docker" "example" {
+ commit = true
+ // any other configuration you want for your Docker containers
+}
+```
+
+build.pkr.hcl
+
+```hcl
+build {
+ // Make sure to name your builds so that you can selectively run them one at
+ // a time.
+ name = "step1"
+
+ source "source.docker.example" {
+ image = "ubuntu"
+ }
+
+ provisioner "shell" {
+ inline = ["echo example provisioner"]
+ }
+ provisioner "shell" {
+ inline = ["echo another example provisioner"]
+ }
+ provisioner "shell" {
+ inline = ["echo a third example provisioner"]
+ }
+
+ // Make sure that the output from your build can be used in the next build.
+ // In this example, we're tagging the Docker image so that the step-2
+ // builder can find it without us having to track it down in a manifest.
+ post-processor "docker-tag" {
+ repository = "ubuntu"
+ tag = ["step-1-output"]
+ }
+}
+
+build {
+ name = "step2"
+
+ source "source.docker.example" {
+ // This is the tagged artifact from the stage 1 build. You can retrieve
+ // this from a manifest file and setting it as a variable on the command
+ // line, or by making sure you define and know the output of the build,
+ // if it's something you can define like an output name or directory.
+ image = "ubuntu:step-1-output"
+ // disable the pull if your image tag only exists locally
+ pull = false
+ }
+
+ provisioner "shell" {
+ inline = ["echo another provision!"]
+ }
+}
+```
+
+pipeline.sh
+
+```sh
+#!/bin/bash
+set -e # abort if there is an issue with any build
+packer build -only='step1.docker.example' .
+packer build -only='step2.docker.example' .
+```
+
+To run the pipeline, call pipeline.sh. You can create as many build steps as
+you want. Each can either inhabit one file, or you can put multiple steps in
+a single file like shown in the example above.
diff --git a/v1.9.4/website/content/guides/packer-on-cicd/trigger-tfe.mdx b/v1.9.4/website/content/guides/packer-on-cicd/trigger-tfe.mdx
new file mode 100644
index 0000000..b43e282
--- /dev/null
+++ b/v1.9.4/website/content/guides/packer-on-cicd/trigger-tfe.mdx
@@ -0,0 +1,60 @@
+---
+page_title: Trigger Terraform Enterprise runs
+description: >-
+ Learn how to Terraform Enterprise from your CI/CD pipeline to provision infrastructure.
+---
+
+# Create Terraform Enterprise Runs
+
+Once an image is built and uploaded to an artifact store, the next step is to
+use this new image. In some cases the image will be downloaded by the dev team
+and used locally in development, like is often done with VirtualBox images with
+Vagrant. In most other cases, the new image will be used to provision new
+infrastructure.
+
+[Terraform](https://www.terraform.io/) is an open source tool that is ideal for
+provisioning new infrastructure with images generated by Packer, and [Terraform
+Enterprise](https://www.hashicorp.com/products/terraform/) is the best way to
+perform automated Terraform runs.
+
+## Create a Terraform Configuration and Workspace
+
+The following is a sample Terraform configuration which provisions a new AWS
+EC2 instance. The `aws_ami_id` is a variable which will be provided when
+running `terraform plan` and `terraform apply`. This variable references the
+latest AMI generated with the Packer build in CI/CD.
+
+```hcl
+variable "aws_ami_id" { }
+
+provider "aws" {
+ region = "us-west-2"
+}
+
+resource "aws_instance" "web" {
+ ami = "${var.aws_ami_id}"
+ instance_type = "t2.micro"
+}
+```
+
+Terraform Enterprise should have a workspace with this terraform configuration
+and a placeholder variable `aws_ami_id`.
+
+## Include Terraform Enterprise in Your CI Builds
+
+Follow these steps to create a new run from CI/CD after a Packer build is
+complete and uploaded.
+
+1. Add a new step to the CI/CD pipeline.
+2. In the new step add a `curl` call to update the variables in the workspace
+ using the [update variables
+ API](/terraform/docs/enterprise/api/variables#update-variables),
+ so that Terraform has a reference to the latest image. For the sample
+ configuration above, the `aws_ami_id` variable should be updated to the AMI
+ ID of the latest image.
+3. In that same step, add another `curl` call to [create a new run via the
+ API](/terraform/docs/enterprise/api/run#create-a-run).
+ A run performs a plan and apply on the last configuration version created,
+ using the variables set in the workspace. In the previous step we update the
+ variables, so the new run can be created using the previous configuration
+ version.
diff --git a/v1.9.4/website/content/guides/packer-on-cicd/upload-images-to-artifact.mdx b/v1.9.4/website/content/guides/packer-on-cicd/upload-images-to-artifact.mdx
new file mode 100644
index 0000000..6728a19
--- /dev/null
+++ b/v1.9.4/website/content/guides/packer-on-cicd/upload-images-to-artifact.mdx
@@ -0,0 +1,45 @@
+---
+page_title: Upload VirtualBox Image to S3
+description: >-
+ Learn how to upload a VirtualBox image built with Packer to S3 within a TeamCity build.
+---
+
+# Upload VirtualBox Image to S3
+
+Once the image is generated it will be used by other parts of your operations
+workflow. For example, it is common to build VirtualBox images with Packer to
+be used as base boxes in Vagrant.
+
+The exact process for uploading images depends on the artifact store and CI
+system you use. TeamCity provides a [Build
+Artifacts](https://confluence.jetbrains.com/display/TCD9/Build+Artifact)
+feature which can be used to store the newly generated image. Other CI/CD
+services also have similar build artifacts features built in, like [Circle CI
+Build Artifacts](https://circleci.com/docs/2.0/artifacts/). In addition to the
+built in artifact stores in CI/CD tools, there are also dedicated universal
+artifact storage services like
+[Artifactory](https://confluence.jetbrains.com/display/TCD9/Build+Artifact).
+All of these are great options for image artifact storage.
+
+The following example uses TeamCity and Amazon S3.
+
+## Example: Uploading to S3 in a TeamCity Build
+
+On the agent machine responsible for building images, install the [AWS Command
+Line Tool](https://aws.amazon.com/cli/). Since this is a one-time operation,
+this can be incorporated into the initial agent provisioning step when
+installing other dependencies. The AWS Command Line tool may require installing
+additional
+[dependencies](http://docs.aws.amazon.com/cli/latest/userguide/installing.html)
+prior.
+
+```shell-session
+$ pip install awscli
+```
+
+In your build configuration in TeamCity Server, add an additional **Build Step:
+Command Line** and set the **Script content** field to the following:
+
+```shell-session
+$ awscli s3 cp . s3://bucket/ --exclude “*” --include “*.ovf"
+```
diff --git a/v1.9.4/website/content/partials/builders/community_builders.mdx b/v1.9.4/website/content/partials/builders/community_builders.mdx
new file mode 100644
index 0000000..ad9482b
--- /dev/null
+++ b/v1.9.4/website/content/partials/builders/community_builders.mdx
@@ -0,0 +1,12 @@
+### Community Builders
+
+- ARM builders
+
+ - [packer-plugin-arm-image](https://github.com/solo-io/packer-plugin-arm-image) - simple builder lets you extend on existing system images.
+ - [packer-builder-arm](https://github.com/mkaczanowski/packer-builder-arm) - flexible builder lets you extend or build images from scratch with variety of options (ie. custom partition table).
+
+- [Exoscale builder](https://github.com/exoscale/packer-plugin-exoscale) - A builder to create Exoscale custom templates based on a Compute instance snapshot.
+
+- [Citrix XenServer/Citrix Hypervisor](https://github.com/xenserver/packer-builder-xenserver) - Plugin for creating [Citrix XenServer/Citrix Hypervisor](https://xenserver.org/) images from an iso image or from an existing template.
+
+- [XCP-NG/Citrix XenServer/Citrix Hypervisor/Updated Fork](https://github.com/ddelnano/packer-plugin-xenserver) - Plugin for creating [XCP-NG/Citrix XenServer/Citrix Hypervisor](https://xcp-ng.org/) images from an iso image or from an existing template. This is a fork of the orginal, and reccomended by the developers of XCP-NG.
diff --git a/v1.9.4/website/content/partials/commands/except.mdx b/v1.9.4/website/content/partials/commands/except.mdx
new file mode 100644
index 0000000..5677c0e
--- /dev/null
+++ b/v1.9.4/website/content/partials/commands/except.mdx
@@ -0,0 +1,10 @@
+- `-except=foo,bar,baz` - Run all the builds and post-processors except those
+ with the given comma-separated names. In legacy JSON templates, build names default to the
+ types of their builders (e.g. `docker` or
+ `amazon-ebs` or `virtualbox-iso`), unless a specific `name` attribute is
+ specified within the configuration. In HCL2 templates, the "name" is the
+ source block's "name" label, unless an in-build source definition adds the
+ "name" configuration option. Any post-processor following
+ a skipped post-processor will not run. Because post-processors can be nested
+ in arrays a different post-processor chain can still run. A post-processor
+ with an empty name will be ignored.
diff --git a/v1.9.4/website/content/partials/commands/only.mdx b/v1.9.4/website/content/partials/commands/only.mdx
new file mode 100644
index 0000000..a6c901c
--- /dev/null
+++ b/v1.9.4/website/content/partials/commands/only.mdx
@@ -0,0 +1,7 @@
+- `-only=foo,bar,baz` - Only run the builds with the given comma-separated
+ names. In legacy JSON templates, build names default to the
+ types of their builders (e.g. `docker` or
+ `amazon-ebs` or `virtualbox-iso`), unless a specific `name` attribute is
+ specified within the configuration. In HCL2 templates, the "name" is the
+ source block's "name" label, unless an in-build source definition adds the
+ "name" configuration option.
diff --git a/v1.9.4/website/content/partials/datasource/hcp-packer-image/Config-not-required.mdx b/v1.9.4/website/content/partials/datasource/hcp-packer-image/Config-not-required.mdx
new file mode 100644
index 0000000..70e7cd0
--- /dev/null
+++ b/v1.9.4/website/content/partials/datasource/hcp-packer-image/Config-not-required.mdx
@@ -0,0 +1,6 @@
+<!-- Code generated from the comments of the Config struct in datasource/hcp-packer-image/data.go; DO NOT EDIT MANUALLY -->
+
+- `component_type` (string) - The specific Packer builder used to create the image.
+ For example, "amazon-ebs.example"
+
+<!-- End of code generated from the comments of the Config struct in datasource/hcp-packer-image/data.go; -->
diff --git a/v1.9.4/website/content/partials/datasource/hcp-packer-image/Config-required.mdx b/v1.9.4/website/content/partials/datasource/hcp-packer-image/Config-required.mdx
new file mode 100644
index 0000000..cca6bec
--- /dev/null
+++ b/v1.9.4/website/content/partials/datasource/hcp-packer-image/Config-required.mdx
@@ -0,0 +1,24 @@
+<!-- Code generated from the comments of the Config struct in datasource/hcp-packer-image/data.go; DO NOT EDIT MANUALLY -->
+
+- `bucket_name` (string) - The name of the bucket your image is in.
+
+- `channel` (string) - The name of the channel to use when retrieving your image.
+ Either this or `iteration_id` MUST be set.
+ Mutually exclusive with `iteration_id`.
+ If using several images from a single iteration, you may prefer
+ sourcing an iteration first, and referencing it for subsequent uses,
+ as every `hcp_packer_image` with the channel set will generate a
+ potentially billable HCP Packer request, but if several
+ `hcp_packer_image`s use a shared `hcp_packer_iteration` that will
+ only generate one potentially billable request.
+
+- `iteration_id` (string) - The ID of the iteration to use when retrieving your image
+ Either this or `channel` MUST be set.
+ Mutually exclusive with `channel`
+
+- `cloud_provider` (string) - The name of the cloud provider that your image is for. For example,
+ "aws" or "gce".
+
+- `region` (string) - The name of the cloud region your image is in. For example "us-east-1".
+
+<!-- End of code generated from the comments of the Config struct in datasource/hcp-packer-image/data.go; -->
diff --git a/v1.9.4/website/content/partials/datasource/hcp-packer-image/DatasourceOutput.mdx b/v1.9.4/website/content/partials/datasource/hcp-packer-image/DatasourceOutput.mdx
new file mode 100644
index 0000000..07e53af
--- /dev/null
+++ b/v1.9.4/website/content/partials/datasource/hcp-packer-image/DatasourceOutput.mdx
@@ -0,0 +1,31 @@
+<!-- Code generated from the comments of the DatasourceOutput struct in datasource/hcp-packer-image/data.go; DO NOT EDIT MANUALLY -->
+
+- `cloud_provider` (string) - The name of the cloud provider that the image exists in. For example,
+ "aws", "azure", or "gce".
+
+- `component_type` (string) - The specific Packer builder or post-processor used to create the image.
+
+- `created_at` (string) - The date and time at which the image was created.
+
+- `build_id` (string) - The ID of the build that created the image. This is a ULID, which is a
+ unique identifier similar to a UUID. It is created by the HCP Packer
+ Registry when an build is first created, and is unique to this build.
+
+- `iteration_id` (string) - The iteration ID. This is a ULID, which is a unique identifier similar
+ to a UUID. It is created by the HCP Packer Registry when an iteration is
+ first created, and is unique to this iteration.
+
+- `channel_id` (string) - The ID of the channel used to query the image iteration. This value will be empty if the `iteration_id` was used
+ directly instead of a channel.
+
+- `packer_run_uuid` (string) - The UUID associated with the Packer run that created this image.
+
+- `id` (string) - ID or URL of the remote cloud image as given by a build.
+
+- `region` (string) - The cloud region as given by `packer build`. eg. "ap-east-1".
+ For locally managed clouds, this may map instead to a cluster, server
+ or datastore.
+
+- `labels` (map[string]string) - The key:value metadata labels associated with this build.
+
+<!-- End of code generated from the comments of the DatasourceOutput struct in datasource/hcp-packer-image/data.go; -->
diff --git a/v1.9.4/website/content/partials/datasource/hcp-packer-iteration/Config-required.mdx b/v1.9.4/website/content/partials/datasource/hcp-packer-iteration/Config-required.mdx
new file mode 100644
index 0000000..582bb82
--- /dev/null
+++ b/v1.9.4/website/content/partials/datasource/hcp-packer-iteration/Config-required.mdx
@@ -0,0 +1,7 @@
+<!-- Code generated from the comments of the Config struct in datasource/hcp-packer-iteration/data.go; DO NOT EDIT MANUALLY -->
+
+- `bucket_name` (string) - The name of the bucket your image is in.
+
+- `channel` (string) - The name of the channel to use when retrieving your image
+
+<!-- End of code generated from the comments of the Config struct in datasource/hcp-packer-iteration/data.go; -->
diff --git a/v1.9.4/website/content/partials/datasource/hcp-packer-iteration/DatasourceOutput.mdx b/v1.9.4/website/content/partials/datasource/hcp-packer-iteration/DatasourceOutput.mdx
new file mode 100644
index 0000000..469a09f
--- /dev/null
+++ b/v1.9.4/website/content/partials/datasource/hcp-packer-iteration/DatasourceOutput.mdx
@@ -0,0 +1,32 @@
+<!-- Code generated from the comments of the DatasourceOutput struct in datasource/hcp-packer-iteration/data.go; DO NOT EDIT MANUALLY -->
+
+- `author_id` (string) - who created the iteration
+
+- `bucket_name` (string) - Name of the bucket that the iteration was retrieved from
+
+- `complete` (bool) - If true, this iteration is considered "ready to use" and will be
+ returned even if the include_incomplete flag is "false" in the
+ list iterations request. Note that if you are retrieving an iteration
+ using a channel, this will always be "true"; channels cannot be assigned
+ to incomplete iterations.
+
+- `created_at` (string) - The date the iteration was created.
+
+- `fingerprint` (string) - The fingerprint of the build; this could be a git sha or other unique
+ identifier as set by the Packer build that created this iteration.
+
+- `id` (string) - The iteration ID. This is a ULID, which is a unique identifier similar
+ to a UUID. It is created by the HCP Packer Registry when an iteration is
+ first created, and is unique to this iteration.
+
+- `incremental_version` (int32) - The version number assigned to an iteration. This number is an integer,
+ and is created by the HCP Packer Registry once an iteration is
+ marked "complete". If a new iteration is marked "complete", the version
+ that HCP Packer assigns to it will always be the highest previous
+ iteration version plus one.
+
+- `updated_at` (string) - The date when this iteration was last updated.
+
+- `channel_id` (string) - The ID of the channel used to query the image iteration.
+
+<!-- End of code generated from the comments of the DatasourceOutput struct in datasource/hcp-packer-iteration/data.go; -->
diff --git a/v1.9.4/website/content/partials/datasource/http/Config-not-required.mdx b/v1.9.4/website/content/partials/datasource/http/Config-not-required.mdx
new file mode 100644
index 0000000..2481462
--- /dev/null
+++ b/v1.9.4/website/content/partials/datasource/http/Config-not-required.mdx
@@ -0,0 +1,5 @@
+<!-- Code generated from the comments of the Config struct in datasource/http/data.go; DO NOT EDIT MANUALLY -->
+
+- `request_headers` (map[string]string) - A map of strings representing additional HTTP headers to include in the request.
+
+<!-- End of code generated from the comments of the Config struct in datasource/http/data.go; -->
diff --git a/v1.9.4/website/content/partials/datasource/http/Config-required.mdx b/v1.9.4/website/content/partials/datasource/http/Config-required.mdx
new file mode 100644
index 0000000..a9cc518
--- /dev/null
+++ b/v1.9.4/website/content/partials/datasource/http/Config-required.mdx
@@ -0,0 +1,5 @@
+<!-- Code generated from the comments of the Config struct in datasource/http/data.go; DO NOT EDIT MANUALLY -->
+
+- `url` (string) - The URL to request data from. This URL must respond with a `200 OK` response and a `text/*` or `application/json` Content-Type.
+
+<!-- End of code generated from the comments of the Config struct in datasource/http/data.go; -->
diff --git a/v1.9.4/website/content/partials/datasource/http/DatasourceOutput.mdx b/v1.9.4/website/content/partials/datasource/http/DatasourceOutput.mdx
new file mode 100644
index 0000000..8581fa9
--- /dev/null
+++ b/v1.9.4/website/content/partials/datasource/http/DatasourceOutput.mdx
@@ -0,0 +1,10 @@
+<!-- Code generated from the comments of the DatasourceOutput struct in datasource/http/data.go; DO NOT EDIT MANUALLY -->
+
+- `url` (string) - The URL the data was requested from.
+
+- `body` (string) - The raw body of the HTTP response.
+
+- `request_headers` (map[string]string) - A map of strings representing the response HTTP headers.
+ Duplicate headers are concatenated with, according to [RFC2616](https://www.w3.org/Protocols/rfc2616/rfc2616-sec4.html#sec4.2).
+
+<!-- End of code generated from the comments of the DatasourceOutput struct in datasource/http/data.go; -->
diff --git a/v1.9.4/website/content/partials/datasource/null/Config-required.mdx b/v1.9.4/website/content/partials/datasource/null/Config-required.mdx
new file mode 100644
index 0000000..c1b02ed
--- /dev/null
+++ b/v1.9.4/website/content/partials/datasource/null/Config-required.mdx
@@ -0,0 +1,5 @@
+<!-- Code generated from the comments of the Config struct in datasource/null/data.go; DO NOT EDIT MANUALLY -->
+
+- `input` (string) - This variable will get stored as "output" in the output spec.
+
+<!-- End of code generated from the comments of the Config struct in datasource/null/data.go; -->
diff --git a/v1.9.4/website/content/partials/datasource/null/Config.mdx b/v1.9.4/website/content/partials/datasource/null/Config.mdx
new file mode 100644
index 0000000..7160ef4
--- /dev/null
+++ b/v1.9.4/website/content/partials/datasource/null/Config.mdx
@@ -0,0 +1,7 @@
+<!-- Code generated from the comments of the Config struct in datasource/null/data.go; DO NOT EDIT MANUALLY -->
+
+The Null data source is designed to demonstrate how data sources work, and
+to provide a test plugin. It does not do anything useful; you assign an
+input string and it gets returned as an output string.
+
+<!-- End of code generated from the comments of the Config struct in datasource/null/data.go; -->
diff --git a/v1.9.4/website/content/partials/datasource/null/DatasourceOutput.mdx b/v1.9.4/website/content/partials/datasource/null/DatasourceOutput.mdx
new file mode 100644
index 0000000..99cb081
--- /dev/null
+++ b/v1.9.4/website/content/partials/datasource/null/DatasourceOutput.mdx
@@ -0,0 +1,5 @@
+<!-- Code generated from the comments of the DatasourceOutput struct in datasource/null/data.go; DO NOT EDIT MANUALLY -->
+
+- `output` (string) - Output will return the input variable, as output.
+
+<!-- End of code generated from the comments of the DatasourceOutput struct in datasource/null/data.go; -->
diff --git a/v1.9.4/website/content/partials/datasources/local-dependency-limitation.mdx b/v1.9.4/website/content/partials/datasources/local-dependency-limitation.mdx
new file mode 100644
index 0000000..8da7f51
--- /dev/null
+++ b/v1.9.4/website/content/partials/datasources/local-dependency-limitation.mdx
@@ -0,0 +1,42 @@
+
+At this present time the use of locals within data sources such as the example below is not supported.
+
+```hcl
+locals {
+ cloud_owners = ["happycloud"]
+ cloud_base_filter_name = "cloud-hvm-2.0.*-x86_64-gp2"
+}
+
+data "happycloud" "happycloud-linux2-east" {
+ filters = {
+ name = local.cloud_base_filter_name
+ }
+ most_recent = true
+ owners = local.cloud_owners
+}
+```
+
+Locals can reference data sources but data sources can not reference locals to avoid cyclic dependencies, where a local
+may reference a data source that references the same local or some other locals variable. The preferred method, at this time,
+for referencing user input data within a data source is to use the `variable` block.
+
+```hcl
+variable "cloud_base_filter_name" {
+ type = string
+ default = "cloud-hvm-2.0.*-x86_64-gp2"
+}
+
+variable "cloud_owners" {
+ type = string
+ default = "happycloud"
+}
+
+data "happycloud" "happycloud-linux2-east" {
+ filters = {
+ name = var.cloud_base_filter_name
+ }
+ most_recent = true
+ owners = var.cloud_owners
+}
+```
+
diff --git a/v1.9.4/website/content/partials/from-1.5/beta-hcl2-note.mdx b/v1.9.4/website/content/partials/from-1.5/beta-hcl2-note.mdx
new file mode 100644
index 0000000..190ee93
--- /dev/null
+++ b/v1.9.4/website/content/partials/from-1.5/beta-hcl2-note.mdx
@@ -0,0 +1,7 @@
+-> **Note:** This page is about HCL2 Packer templates. HCL2 templates
+were first introduced as a beta feature into Packer version 1.5. As of v1.7,
+HCL2 support is no longer in beta, and is the preferred way to write Packer
+configuration. For the old-style stable configuration language see
+[template docs](/packer/docs/templates/legacy_json_templates). As of v1.6.2, you can
+convert your legacy JSON template into an HCL2 config file using the
+[hcl2_upgrade command](/packer/docs/commands/hcl2_upgrade).
diff --git a/v1.9.4/website/content/partials/from-1.5/builds/example-block.mdx b/v1.9.4/website/content/partials/from-1.5/builds/example-block.mdx
new file mode 100644
index 0000000..2eb34b5
--- /dev/null
+++ b/v1.9.4/website/content/partials/from-1.5/builds/example-block.mdx
@@ -0,0 +1,31 @@
+```hcl
+# build.pkr.hcl
+build {
+ # use the `name` field to name a build in the logs.
+ # For example this present config will display
+ # "buildname.amazon-ebs.example-1" and "buildname.amazon-ebs.example-2"
+ name = "buildname"
+
+ sources = [
+ # use the optional plural `sources` list to simply use a `source`
+ # without changing any field.
+ "source.amazon-ebs.example-1",
+ ]
+
+ source "source.amazon-ebs.example-2" {
+ # Use the singular `source` block set specific fields.
+ # Note that fields cannot be overwritten, in other words, you cannot
+ # set the 'output' field from the top-level source block and here.
+ output = "different value"
+ name = "differentname"
+ }
+
+ provisioner "shell" {
+ scripts = fileset(".", "scripts/{install,secure}.sh")
+ }
+
+ post-processor "shell-local" {
+ inline = ["echo Hello World from ${source.type}.${source.name}"]
+ }
+}
+```
diff --git a/v1.9.4/website/content/partials/from-1.5/contextual-source-variables.mdx b/v1.9.4/website/content/partials/from-1.5/contextual-source-variables.mdx
new file mode 100644
index 0000000..db375ef
--- /dev/null
+++ b/v1.9.4/website/content/partials/from-1.5/contextual-source-variables.mdx
@@ -0,0 +1,36 @@
+# Source Variables
+
+It is possible to access the `name` and `type` of your `source` from
+provisioners and post-processors:
+
+```hcl
+source "null" "first-example" {
+ communicator = "none"
+}
+
+build {
+ name = "roles"
+
+ source "null.first-example" {
+ name = "consul"
+ }
+ source "null.first-example" {
+ name = "nomad"
+ }
+ source "null.first-example" {
+ name = "vault"
+ }
+ sources = ["null.first-example"]
+
+ provisioner "shell-local" {
+ inline = ["echo ${source.name} and ${source.type}"]
+ }
+}
+
+# This will echo something like:
+#
+# roles.null.consul: consul and null
+# roles.null.nomad: nomad and null
+# roles.null.vault: vault and null
+# roles.null.first-example: first-example and null
+```
diff --git a/v1.9.4/website/content/partials/from-1.5/datasources/example-block.mdx b/v1.9.4/website/content/partials/from-1.5/datasources/example-block.mdx
new file mode 100644
index 0000000..b77bae8
--- /dev/null
+++ b/v1.9.4/website/content/partials/from-1.5/datasources/example-block.mdx
@@ -0,0 +1,6 @@
+```hcl
+# datasource.pkr.hcl
+data "amazon-ami" "basic-example" {
+ // ...
+}
+```
diff --git a/v1.9.4/website/content/partials/from-1.5/legacy-json-warning.mdx b/v1.9.4/website/content/partials/from-1.5/legacy-json-warning.mdx
new file mode 100644
index 0000000..026ac23
--- /dev/null
+++ b/v1.9.4/website/content/partials/from-1.5/legacy-json-warning.mdx
@@ -0,0 +1,6 @@
+-> **Note:** This page is about older-style JSON Packer templates. JSON
+templates are still supported by the Packer core, but new features added to the
+Packer core may not be implemented for JSON templates. We recommend you
+transition to HCL templates as soon as is convenient for you, in order to have
+the best possible experience with Packer. To help you upgrade your templates,
+we have written an [hcl2_upgrade command](/packer/docs/commands/hcl2_upgrade) command.
diff --git a/v1.9.4/website/content/partials/from-1.5/locals/example-block.mdx b/v1.9.4/website/content/partials/from-1.5/locals/example-block.mdx
new file mode 100644
index 0000000..ed151e7
--- /dev/null
+++ b/v1.9.4/website/content/partials/from-1.5/locals/example-block.mdx
@@ -0,0 +1,15 @@
+```hcl
+# locals.pkr.hcl
+locals {
+ # locals can be bare values like:
+ wee = local.baz
+ # locals can also be set with other variables :
+ baz = "Foo is '${var.foo}' but not '${local.wee}'"
+}
+
+# Use the singular local block if you need to mark a local as sensitive
+local "mylocal" {
+ expression = "${var.secret_api_key}"
+ sensitive = true
+}
+```
diff --git a/v1.9.4/website/content/partials/from-1.5/sources/example-block.mdx b/v1.9.4/website/content/partials/from-1.5/sources/example-block.mdx
new file mode 100644
index 0000000..652371c
--- /dev/null
+++ b/v1.9.4/website/content/partials/from-1.5/sources/example-block.mdx
@@ -0,0 +1,6 @@
+```hcl
+# sources.pkr.hcl
+source "happycloud" "foo" {
+ // ...
+}
+```
diff --git a/v1.9.4/website/content/partials/from-1.5/variables/assignment.mdx b/v1.9.4/website/content/partials/from-1.5/variables/assignment.mdx
new file mode 100644
index 0000000..737508a
--- /dev/null
+++ b/v1.9.4/website/content/partials/from-1.5/variables/assignment.mdx
@@ -0,0 +1,7 @@
+## Assigning Values to input Variables
+
+Once a variable is declared in your configuration, you can set it:
+
+- Individually, with the `-var foo=bar` command line option.
+- In variable definitions files, either specified on the command line with the `-var-files values.pkrvars.hcl` or automatically loaded (`*.auto.pkrvars.hcl`).
+- As environment variables, for example: `PKR_VAR_foo=bar`
diff --git a/v1.9.4/website/content/partials/from-1.5/variables/custom-validation.mdx b/v1.9.4/website/content/partials/from-1.5/variables/custom-validation.mdx
new file mode 100644
index 0000000..c89806f
--- /dev/null
+++ b/v1.9.4/website/content/partials/from-1.5/variables/custom-validation.mdx
@@ -0,0 +1,75 @@
+### Custom Validation Rules
+
+[inpage-validation]: #custom-validation-rules
+
+In addition to Type Constraints, you can specify arbitrary custom validation
+rules for a particular variable using one or more `validation` block nested
+within the corresponding `variable` block:
+
+```hcl
+variable "image_id" {
+ type = string
+ description = "The ID of the machine image (AMI) to use for the server."
+
+ validation {
+ condition = length(var.image_id) > 4 && substr(var.image_id, 0, 4) == "ami-"
+ error_message = "The image_id value must be a valid AMI ID, starting with \"ami-\"."
+ }
+}
+```
+
+The `condition` argument is an expression that must use the value of the
+variable to return `true` if the value is valid or `false` if it is invalid.
+The expression can refer only to the variable that the condition applies to,
+and _must not_ produce errors.
+
+If the failure of an expression is the basis of the validation decision, use
+[the `can` function](/packer/docs/templates/hcl_templates/functions/conversion/can) to detect such errors. For example:
+
+```hcl
+variable "image_id" {
+ type = string
+ description = "The ID of the machine image (AMI) to use for the server."
+
+ validation {
+ # regex(...) fails if it cannot find a match
+ condition = can(regex("^ami-", var.image_id))
+ error_message = "The image_id value must be a valid AMI ID, starting with \"ami-\"."
+ }
+}
+```
+
+If `condition` evaluates to `false`, an error message including the sentences
+given in `error_message` will be produced. The error message string should be
+at least one full sentence explaining the constraint that failed, using a
+sentence structure similar to the above examples.
+
+Validation also works with more complex cases:
+
+```hcl
+variable "image_metadata" {
+
+ default = {
+ key: "value",
+ something: {
+ foo: "bar",
+ }
+ }
+
+ validation {
+ condition = length(var.image_metadata.key) > 4
+ error_message = "The image_metadata.key field must be more than 4 runes."
+ }
+
+ validation {
+ condition = can(var.image_metadata.something.foo)
+ error_message = "The image_metadata.something.foo field must exist."
+ }
+
+ validation {
+ condition = substr(var.image_metadata.something.foo, 0, 3) == "bar"
+ error_message = "The image_metadata.something.foo field must start with \"bar\"."
+ }
+
+}
+```
diff --git a/v1.9.4/website/content/partials/from-1.5/variables/foo-block.mdx b/v1.9.4/website/content/partials/from-1.5/variables/foo-block.mdx
new file mode 100644
index 0000000..5b68c1c
--- /dev/null
+++ b/v1.9.4/website/content/partials/from-1.5/variables/foo-block.mdx
@@ -0,0 +1,11 @@
+```hcl
+# variables.pkr.hcl
+variable "foo" {
+ type = string
+ default = "the default value of the `foo` variable"
+ description = "description of the `foo` variable"
+ sensitive = false
+ # When a variable is sensitive all string-values from that variable will be
+ # obfuscated from Packer's output.
+}
+```
diff --git a/v1.9.4/website/content/partials/from-1.5/variables/foo-pkrvar.mdx b/v1.9.4/website/content/partials/from-1.5/variables/foo-pkrvar.mdx
new file mode 100644
index 0000000..04f44e1
--- /dev/null
+++ b/v1.9.4/website/content/partials/from-1.5/variables/foo-pkrvar.mdx
@@ -0,0 +1,4 @@
+```hcl
+# foo.pkrvars.hcl
+foo = "value"
+```
diff --git a/v1.9.4/website/content/partials/from-1.5/variables/must-be-set.mdx b/v1.9.4/website/content/partials/from-1.5/variables/must-be-set.mdx
new file mode 100644
index 0000000..ecf8873
--- /dev/null
+++ b/v1.9.4/website/content/partials/from-1.5/variables/must-be-set.mdx
@@ -0,0 +1,35 @@
+## A variable value must be known:
+
+Take the following variable for example:
+
+```hcl
+variable "foo" {
+ type = string
+}
+```
+
+Here `foo` must have a known value but you can default it to `null` to make
+this behavior optional :
+
+| | no default | `default = null` | `default = "xy"` |
+| :---------------------------: | :--------------------------: | :--------------: | :--------------: |
+| foo unused | error, "foo needs to be set" | - | - |
+| var.foo | error, "foo needs to be set" | null¹ | xy |
+| `PKR_VAR_foo=yz`<br />var.foo | yz | yz | yz |
+| `-var foo=yz`<br />var.foo | yz | yz | yz |
+
+1: Null is a valid value. Packer will only error when the receiving field needs
+a value, example:
+
+```hcl
+variable "example" {
+ type = string
+ default = null
+}
+
+source "example" "foo" {
+ arg = var.example
+}
+```
+
+In the above case, as long as "arg" is optional for an "example" source, there is no error and arg won’t be set.
diff --git a/v1.9.4/website/content/partials/from-1.5/variables/sensitive.mdx b/v1.9.4/website/content/partials/from-1.5/variables/sensitive.mdx
new file mode 100644
index 0000000..5e53f4c
--- /dev/null
+++ b/v1.9.4/website/content/partials/from-1.5/variables/sensitive.mdx
@@ -0,0 +1,26 @@
+### Suppressing Sensitive Variables
+
+[inpage-sensitive]: #suppressing-sensitive-variables
+
+
+When a variable is sensitive all string-values from that variable will be
+obfuscated from Packer's output :
+
+```hcl
+# var-foo.pkr.hcl
+variable "foo" {
+ sensitive = true
+ default = {
+ key = "SECR3TP4SSW0RD"
+ }
+}
+```
+
+```shell-session
+$ packer inspect var-foo.pkr.hcl
+Packer Inspect: HCL2 mode
+
+> input-variables:
+var.foo: "{\n \"key\" = \"<sensitive>\"\n }"
+...
+```
diff --git a/v1.9.4/website/content/partials/guides/hcl2-beta-note.mdx b/v1.9.4/website/content/partials/guides/hcl2-beta-note.mdx
new file mode 100644
index 0000000..6b8a621
--- /dev/null
+++ b/v1.9.4/website/content/partials/guides/hcl2-beta-note.mdx
@@ -0,0 +1 @@
+-> **Note:** Packer version **1.5.0** introduced support for HCL2 templates as a beta feature. As of version **1.7.0**, HCL2 support is no longer in beta and is the preferred way to write Packer configuration(s).
diff --git a/v1.9.4/website/content/partials/helper/communicator/SSH-Agent-Auth-not-required.mdx b/v1.9.4/website/content/partials/helper/communicator/SSH-Agent-Auth-not-required.mdx
new file mode 100644
index 0000000..efc409d
--- /dev/null
+++ b/v1.9.4/website/content/partials/helper/communicator/SSH-Agent-Auth-not-required.mdx
@@ -0,0 +1,6 @@
+- `ssh_agent_auth` (bool) - If true, the local SSH agent will be used to authenticate connections to
+ the source instance. No temporary keypair will be created, and the
+ values of [`ssh_password`](#ssh_password) and
+ [`ssh_private_key_file`](#ssh_private_key_file) will be ignored. The
+ environment variable `SSH_AUTH_SOCK` must be set for this option to work
+ properly.
diff --git a/v1.9.4/website/content/partials/helper/communicator/SSH-Key-Pair-Name-not-required.mdx b/v1.9.4/website/content/partials/helper/communicator/SSH-Key-Pair-Name-not-required.mdx
new file mode 100644
index 0000000..88e5a7a
--- /dev/null
+++ b/v1.9.4/website/content/partials/helper/communicator/SSH-Key-Pair-Name-not-required.mdx
@@ -0,0 +1,7 @@
+- `ssh_keypair_name` (string) - If specified, this is the key that will be used for SSH with the
+ machine. The key must match a key pair name loaded up into the remote.
+ By default, this is blank, and Packer will generate a temporary keypair
+ unless [`ssh_password`](#ssh_password) is used.
+ [`ssh_private_key_file`](#ssh_private_key_file) or
+ [`ssh_agent_auth`](#ssh_agent_auth) must be specified when
+ [`ssh_keypair_name`](#ssh_keypair_name) is utilized.
diff --git a/v1.9.4/website/content/partials/helper/communicator/SSH-Private-Key-File-not-required.mdx b/v1.9.4/website/content/partials/helper/communicator/SSH-Private-Key-File-not-required.mdx
new file mode 100644
index 0000000..a192598
--- /dev/null
+++ b/v1.9.4/website/content/partials/helper/communicator/SSH-Private-Key-File-not-required.mdx
@@ -0,0 +1,3 @@
+- `ssh_private_key_file` (string) - Path to a PEM encoded private key file to use to authenticate with SSH.
+ The `~` can be used in path and will be expanded to the home directory
+ of current user.
diff --git a/v1.9.4/website/content/partials/helper/communicator/SSH-Temporary-Key-Pair-not-required.mdx b/v1.9.4/website/content/partials/helper/communicator/SSH-Temporary-Key-Pair-not-required.mdx
new file mode 100644
index 0000000..98c2a76
--- /dev/null
+++ b/v1.9.4/website/content/partials/helper/communicator/SSH-Temporary-Key-Pair-not-required.mdx
@@ -0,0 +1,3 @@
+- `temporary_key_pair_name` (string) - 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.
diff --git a/v1.9.4/website/content/partials/packer-plugin-sdk/bootcommand/BootConfig-not-required.mdx b/v1.9.4/website/content/partials/packer-plugin-sdk/bootcommand/BootConfig-not-required.mdx
new file mode 100644
index 0000000..74a6556
--- /dev/null
+++ b/v1.9.4/website/content/partials/packer-plugin-sdk/bootcommand/BootConfig-not-required.mdx
@@ -0,0 +1,22 @@
+<!-- Code generated from the comments of the BootConfig struct in bootcommand/config.go; DO NOT EDIT MANUALLY -->
+
+- `boot_keygroup_interval` (duration string | ex: "1h5m2s") - Time to wait after sending a group of key pressses. 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
+ this isn't specified, a sensible default value is picked depending on
+ the builder type.
+
+- `boot_wait` (duration string | ex: "1h5m2s") - The time to wait after booting the initial virtual machine before typing
+ the `boot_command`. 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 this isn't specified, the default is
+ `10s` or 10 seconds. To set boot_wait to 0s, use a negative number, such
+ as "-1s"
+
+- `boot_command` ([]string) - This is an array of commands to type when the virtual machine is first
+ booted. The goal of these commands should be to type just enough to
+ initialize the operating system installer. Special keys can be typed as
+ well, and are covered in the section below on the boot command. If this
+ is not specified, it is assumed the installer will start itself.
+
+<!-- End of code generated from the comments of the BootConfig struct in bootcommand/config.go; -->
diff --git a/v1.9.4/website/content/partials/packer-plugin-sdk/bootcommand/BootConfig.mdx b/v1.9.4/website/content/partials/packer-plugin-sdk/bootcommand/BootConfig.mdx
new file mode 100644
index 0000000..3faa491
--- /dev/null
+++ b/v1.9.4/website/content/partials/packer-plugin-sdk/bootcommand/BootConfig.mdx
@@ -0,0 +1,130 @@
+<!-- Code generated from the comments of the BootConfig struct in bootcommand/config.go; DO NOT EDIT MANUALLY -->
+
+The boot configuration is very important: `boot_command` specifies the keys
+to type when the virtual machine is first booted in order to start the OS
+installer. This command is typed after boot_wait, which gives the virtual
+machine some time to actually load.
+
+The boot_command is an array of strings. The strings are all typed in
+sequence. It is an array only to improve readability within the template.
+
+There are a set of special keys available. If these are in your boot
+command, they will be replaced by the proper key:
+
+- `<bs>` - Backspace
+
+- `<del>` - Delete
+
+- `<enter> <return>` - Simulates an actual "enter" or "return" keypress.
+
+- `<esc>` - Simulates pressing the escape key.
+
+- `<tab>` - Simulates pressing the tab key.
+
+- `<f1> - <f12>` - Simulates pressing a function key.
+
+- `<up> <down> <left> <right>` - Simulates pressing an arrow key.
+
+- `<spacebar>` - Simulates pressing the spacebar.
+
+- `<insert>` - Simulates pressing the insert key.
+
+- `<home> <end>` - Simulates pressing the home and end keys.
+
+- `<pageUp> <pageDown>` - Simulates pressing the page up and page down
+ keys.
+
+- `<menu>` - Simulates pressing the Menu key.
+
+- `<leftAlt> <rightAlt>` - Simulates pressing the alt key.
+
+- `<leftCtrl> <rightCtrl>` - Simulates pressing the ctrl key.
+
+- `<leftShift> <rightShift>` - Simulates pressing the shift key.
+
+- `<leftSuper> <rightSuper>` - Simulates pressing the ⌘ or Windows key.
+
+- `<wait> <wait5> <wait10>` - Adds a 1, 5 or 10 second pause before
+ sending any additional keys. This is useful if you have to generally
+ wait for the UI to update before typing more.
+
+- `<waitXX>` - Add an arbitrary pause before sending any additional keys.
+ The format of `XX` is a sequence of positive decimal numbers, each with
+ optional fraction and a unit suffix, such as `300ms`, `1.5h` or `2h45m`.
+ Valid time units are `ns`, `us` (or `µs`), `ms`, `s`, `m`, `h`. For
+ example `<wait10m>` or `<wait1m20s>`.
+
+- `<XXXOn> <XXXOff>` - Any printable keyboard character, and of these
+ "special" expressions, with the exception of the `<wait>` types, can
+ also be toggled on or off. For example, to simulate ctrl+c, use
+ `<leftCtrlOn>c<leftCtrlOff>`. Be sure to release them, otherwise they
+ will be held down until the machine reboots. To hold the `c` key down,
+ you would use `<cOn>`. Likewise, `<cOff>` to release.
+
+- `{{ .HTTPIP }} {{ .HTTPPort }}` - The IP and port, respectively of an
+ HTTP server that is started serving the directory specified by the
+ `http_directory` configuration parameter. If `http_directory` isn't
+ specified, these will be blank!
+
+- `{{ .Name }}` - The name of the VM.
+
+Example boot command. This is actually a working boot command used to start an
+CentOS 6.4 installer:
+
+In JSON:
+
+```json
+"boot_command": [
+ "<tab><wait>",
+ " ks=http://{{ .HTTPIP }}:{{ .HTTPPort }}/centos6-ks.cfg<enter>"
+ ]
+```
+
+In HCL2:
+
+```hcl
+boot_command = [
+ "<tab><wait>",
+ " ks=http://{{ .HTTPIP }}:{{ .HTTPPort }}/centos6-ks.cfg<enter>"
+ ]
+```
+
+The example shown below is a working boot command used to start an Ubuntu
+12.04 installer:
+
+In JSON:
+
+```json
+"boot_command": [
+ "<esc><esc><enter><wait>",
+ "/install/vmlinuz noapic ",
+ "preseed/url=http://{{ .HTTPIP }}:{{ .HTTPPort }}/preseed.cfg ",
+ "debian-installer=en_US auto locale=en_US kbd-chooser/method=us ",
+ "hostname={{ .Name }} ",
+ "fb=false debconf/frontend=noninteractive ",
+ "keyboard-configuration/modelcode=SKIP keyboard-configuration/layout=USA ",
+ "keyboard-configuration/variant=USA console-setup/ask_detect=false ",
+ "initrd=/install/initrd.gz -- <enter>"
+]
+```
+
+In HCL2:
+
+```hcl
+boot_command = [
+ "<esc><esc><enter><wait>",
+ "/install/vmlinuz noapic ",
+ "preseed/url=http://{{ .HTTPIP }}:{{ .HTTPPort }}/preseed.cfg ",
+ "debian-installer=en_US auto locale=en_US kbd-chooser/method=us ",
+ "hostname={{ .Name }} ",
+ "fb=false debconf/frontend=noninteractive ",
+ "keyboard-configuration/modelcode=SKIP keyboard-configuration/layout=USA ",
+ "keyboard-configuration/variant=USA console-setup/ask_detect=false ",
+ "initrd=/install/initrd.gz -- <enter>"
+]
+```
+
+For more examples of various boot commands, see the sample projects from our
+[community templates page](https://packer.io/community-tools#templates).
+
+<!-- End of code generated from the comments of the BootConfig struct in bootcommand/config.go; -->
diff --git a/v1.9.4/website/content/partials/packer-plugin-sdk/bootcommand/VNCConfig-not-required.mdx b/v1.9.4/website/content/partials/packer-plugin-sdk/bootcommand/VNCConfig-not-required.mdx
new file mode 100644
index 0000000..c65d8ae
--- /dev/null
+++ b/v1.9.4/website/content/partials/packer-plugin-sdk/bootcommand/VNCConfig-not-required.mdx
@@ -0,0 +1,8 @@
+<!-- Code generated from the comments of the VNCConfig struct in bootcommand/config.go; DO NOT EDIT MANUALLY -->
+
+- `disable_vnc` (bool) - Whether to create a VNC connection or not. A boot_command cannot be used
+ when this is true. Defaults to false.
+
+- `boot_key_interval` (duration string | ex: "1h5m2s") - Time in ms to wait between each key press
+
+<!-- End of code generated from the comments of the VNCConfig struct in bootcommand/config.go; -->
diff --git a/v1.9.4/website/content/partials/packer-plugin-sdk/bootcommand/VNCConfig.mdx b/v1.9.4/website/content/partials/packer-plugin-sdk/bootcommand/VNCConfig.mdx
new file mode 100644
index 0000000..d699fda
--- /dev/null
+++ b/v1.9.4/website/content/partials/packer-plugin-sdk/bootcommand/VNCConfig.mdx
@@ -0,0 +1,11 @@
+<!-- Code generated from the comments of the VNCConfig struct in bootcommand/config.go; DO NOT EDIT MANUALLY -->
+
+The boot command "typed" character for character over a VNC connection to
+the machine, simulating a human actually typing the keyboard.
+
+Keystrokes are typed as separate key up/down events over VNC with a default
+100ms delay. The delay alleviates issues with latency and CPU contention.
+You can tune this delay on a per-builder basis by specifying
+"boot_key_interval" in your Packer template.
+
+<!-- End of code generated from the comments of the VNCConfig struct in bootcommand/config.go; -->
diff --git a/v1.9.4/website/content/partials/packer-plugin-sdk/communicator/Config-not-required.mdx b/v1.9.4/website/content/partials/packer-plugin-sdk/communicator/Config-not-required.mdx
new file mode 100644
index 0000000..d7a9db5
--- /dev/null
+++ b/v1.9.4/website/content/partials/packer-plugin-sdk/communicator/Config-not-required.mdx
@@ -0,0 +1,30 @@
+<!-- Code generated from the comments of the Config struct in communicator/config.go; DO NOT EDIT MANUALLY -->
+
+- `communicator` (string) - Packer currently supports three kinds of communicators:
+
+ - `none` - No communicator will be used. If this is set, most
+ provisioners also can't be used.
+
+ - `ssh` - An SSH connection will be established to the machine. This
+ is usually the default.
+
+ - `winrm` - A WinRM connection will be established.
+
+ In addition to the above, some builders have custom communicators they
+ can use. For example, the Docker builder has a "docker" communicator
+ that uses `docker exec` and `docker cp` to execute scripts and copy
+ files.
+
+- `pause_before_connecting` (duration string | ex: "1h5m2s") - We recommend that you enable SSH or WinRM as the very last step in your
+ guest's bootstrap script, but sometimes you may have a race condition
+ where you need Packer to wait before attempting to connect to your
+ guest.
+
+ If you end up in this situation, you can use the template option
+ `pause_before_connecting`. By default, there is no pause. For example if
+ you set `pause_before_connecting` to `10m` Packer will check whether it
+ can connect, as normal. But once a connection attempt is successful, it
+ will disconnect and then wait 10 minutes before connecting to the guest
+ and beginning provisioning.
+
+<!-- End of code generated from the comments of the Config struct in communicator/config.go; -->
diff --git a/v1.9.4/website/content/partials/packer-plugin-sdk/communicator/Config.mdx b/v1.9.4/website/content/partials/packer-plugin-sdk/communicator/Config.mdx
new file mode 100644
index 0000000..adc4de3
--- /dev/null
+++ b/v1.9.4/website/content/partials/packer-plugin-sdk/communicator/Config.mdx
@@ -0,0 +1,7 @@
+<!-- Code generated from the comments of the Config struct in communicator/config.go; DO NOT EDIT MANUALLY -->
+
+Config is the common configuration a builder uses to define and configure a Packer
+communicator. Embed this struct in your builder config to implement
+communicator support.
+
+<!-- End of code generated from the comments of the Config struct in communicator/config.go; -->
diff --git a/v1.9.4/website/content/partials/packer-plugin-sdk/communicator/SSH-Agent-Auth-not-required.mdx b/v1.9.4/website/content/partials/packer-plugin-sdk/communicator/SSH-Agent-Auth-not-required.mdx
new file mode 100644
index 0000000..efc409d
--- /dev/null
+++ b/v1.9.4/website/content/partials/packer-plugin-sdk/communicator/SSH-Agent-Auth-not-required.mdx
@@ -0,0 +1,6 @@
+- `ssh_agent_auth` (bool) - If true, the local SSH agent will be used to authenticate connections to
+ the source instance. No temporary keypair will be created, and the
+ values of [`ssh_password`](#ssh_password) and
+ [`ssh_private_key_file`](#ssh_private_key_file) will be ignored. The
+ environment variable `SSH_AUTH_SOCK` must be set for this option to work
+ properly.
diff --git a/v1.9.4/website/content/partials/packer-plugin-sdk/communicator/SSH-Key-Pair-Name-not-required.mdx b/v1.9.4/website/content/partials/packer-plugin-sdk/communicator/SSH-Key-Pair-Name-not-required.mdx
new file mode 100644
index 0000000..88e5a7a
--- /dev/null
+++ b/v1.9.4/website/content/partials/packer-plugin-sdk/communicator/SSH-Key-Pair-Name-not-required.mdx
@@ -0,0 +1,7 @@
+- `ssh_keypair_name` (string) - If specified, this is the key that will be used for SSH with the
+ machine. The key must match a key pair name loaded up into the remote.
+ By default, this is blank, and Packer will generate a temporary keypair
+ unless [`ssh_password`](#ssh_password) is used.
+ [`ssh_private_key_file`](#ssh_private_key_file) or
+ [`ssh_agent_auth`](#ssh_agent_auth) must be specified when
+ [`ssh_keypair_name`](#ssh_keypair_name) is utilized.
diff --git a/v1.9.4/website/content/partials/packer-plugin-sdk/communicator/SSH-Private-Key-File-not-required.mdx b/v1.9.4/website/content/partials/packer-plugin-sdk/communicator/SSH-Private-Key-File-not-required.mdx
new file mode 100644
index 0000000..a192598
--- /dev/null
+++ b/v1.9.4/website/content/partials/packer-plugin-sdk/communicator/SSH-Private-Key-File-not-required.mdx
@@ -0,0 +1,3 @@
+- `ssh_private_key_file` (string) - Path to a PEM encoded private key file to use to authenticate with SSH.
+ The `~` can be used in path and will be expanded to the home directory
+ of current user.
diff --git a/v1.9.4/website/content/partials/packer-plugin-sdk/communicator/SSH-Temporary-Key-Pair-not-required.mdx b/v1.9.4/website/content/partials/packer-plugin-sdk/communicator/SSH-Temporary-Key-Pair-not-required.mdx
new file mode 100644
index 0000000..98c2a76
--- /dev/null
+++ b/v1.9.4/website/content/partials/packer-plugin-sdk/communicator/SSH-Temporary-Key-Pair-not-required.mdx
@@ -0,0 +1,3 @@
+- `temporary_key_pair_name` (string) - 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.
diff --git a/v1.9.4/website/content/partials/packer-plugin-sdk/communicator/SSH-not-required.mdx b/v1.9.4/website/content/partials/packer-plugin-sdk/communicator/SSH-not-required.mdx
new file mode 100644
index 0000000..99706b6
--- /dev/null
+++ b/v1.9.4/website/content/partials/packer-plugin-sdk/communicator/SSH-not-required.mdx
@@ -0,0 +1,102 @@
+<!-- Code generated from the comments of the SSH struct in communicator/config.go; DO NOT EDIT MANUALLY -->
+
+- `ssh_host` (string) - The address to SSH to. This usually is automatically configured by the
+ builder.
+
+- `ssh_port` (int) - The port to connect to SSH. This defaults to `22`.
+
+- `ssh_username` (string) - The username to connect to SSH with. Required if using SSH.
+
+- `ssh_password` (string) - A plaintext password to use to authenticate with SSH.
+
+- `ssh_ciphers` ([]string) - This overrides the value of ciphers supported by default by Golang.
+ The default value is [
+ "aes128-gcm@openssh.com",
+ "chacha20-poly1305@openssh.com",
+ "aes128-ctr", "aes192-ctr", "aes256-ctr",
+ ]
+
+ Valid options for ciphers include:
+ "aes128-ctr", "aes192-ctr", "aes256-ctr", "aes128-gcm@openssh.com",
+ "chacha20-poly1305@openssh.com",
+ "arcfour256", "arcfour128", "arcfour", "aes128-cbc", "3des-cbc",
+
+- `ssh_clear_authorized_keys` (bool) - If true, Packer will attempt to remove its temporary key from
+ `~/.ssh/authorized_keys` and `/root/.ssh/authorized_keys`. This is a
+ mostly cosmetic option, since Packer will delete the temporary private
+ key from the host system regardless of whether this is set to true
+ (unless the user has set the `-debug` flag). Defaults to "false";
+ currently only works on guests with `sed` installed.
+
+- `ssh_key_exchange_algorithms` ([]string) - If set, Packer will override the value of key exchange (kex) algorithms
+ supported by default by Golang. Acceptable values include:
+ "curve25519-sha256@libssh.org", "ecdh-sha2-nistp256",
+ "ecdh-sha2-nistp384", "ecdh-sha2-nistp521",
+ "diffie-hellman-group14-sha1", and "diffie-hellman-group1-sha1".
+
+- `ssh_certificate_file` (string) - Path to user certificate used to authenticate with SSH.
+ The `~` can be used in path and will be expanded to the
+ home directory of current user.
+
+- `ssh_pty` (bool) - If `true`, a PTY will be requested for the SSH connection. This defaults
+ to `false`.
+
+- `ssh_timeout` (duration string | ex: "1h5m2s") - The time to wait for SSH to become available. Packer uses this to
+ determine when the machine has booted so this is usually quite long.
+ Example value: `10m`.
+ This defaults to `5m`, unless `ssh_handshake_attempts` is set.
+
+- `ssh_disable_agent_forwarding` (bool) - If true, SSH agent forwarding will be disabled. Defaults to `false`.
+
+- `ssh_handshake_attempts` (int) - The number of handshakes to attempt with SSH once it can connect.
+ This defaults to `10`, unless a `ssh_timeout` is set.
+
+- `ssh_bastion_host` (string) - A bastion host to use for the actual SSH connection.
+
+- `ssh_bastion_port` (int) - The port of the bastion host. Defaults to `22`.
+
+- `ssh_bastion_agent_auth` (bool) - If `true`, the local SSH agent will be used to authenticate with the
+ bastion host. Defaults to `false`.
+
+- `ssh_bastion_username` (string) - The username to connect to the bastion host.
+
+- `ssh_bastion_password` (string) - The password to use to authenticate with the bastion host.
+
+- `ssh_bastion_interactive` (bool) - If `true`, the keyboard-interactive used to authenticate with bastion host.
+
+- `ssh_bastion_private_key_file` (string) - Path to a PEM encoded private key file to use to authenticate with the
+ bastion host. The `~` can be used in path and will be expanded to the
+ home directory of current user.
+
+- `ssh_bastion_certificate_file` (string) - Path to user certificate used to authenticate with bastion host.
+ The `~` can be used in path and will be expanded to the
+ home directory of current user.
+
+- `ssh_file_transfer_method` (string) - `scp` or `sftp` - How to transfer files, Secure copy (default) or SSH
+ File Transfer Protocol.
+
+ **NOTE**: Guests using Windows with Win32-OpenSSH v9.1.0.0p1-Beta, scp
+ (the default protocol for copying data) returns a a non-zero error code since the MOTW
+ cannot be set, which cause any file transfer to fail. As a workaround you can override the transfer protocol
+ with SFTP instead `ssh_file_transfer_protocol = "sftp"`.
+
+- `ssh_proxy_host` (string) - A SOCKS proxy host to use for SSH connection
+
+- `ssh_proxy_port` (int) - A port of the SOCKS proxy. Defaults to `1080`.
+
+- `ssh_proxy_username` (string) - The optional username to authenticate with the proxy server.
+
+- `ssh_proxy_password` (string) - The optional password to use to authenticate with the proxy server.
+
+- `ssh_keep_alive_interval` (duration string | ex: "1h5m2s") - How often to send "keep alive" messages to the server. Set to a negative
+ value (`-1s`) to disable. Example value: `10s`. Defaults to `5s`.
+
+- `ssh_read_write_timeout` (duration string | ex: "1h5m2s") - The amount of time to wait for a remote command to end. This might be
+ useful if, for example, packer hangs on a connection after a reboot.
+ Example: `5m`. Disabled by default.
+
+- `ssh_remote_tunnels` ([]string) -
+
+- `ssh_local_tunnels` ([]string) -
+
+<!-- End of code generated from the comments of the SSH struct in communicator/config.go; -->
diff --git a/v1.9.4/website/content/partials/packer-plugin-sdk/communicator/SSH.mdx b/v1.9.4/website/content/partials/packer-plugin-sdk/communicator/SSH.mdx
new file mode 100644
index 0000000..1749b71
--- /dev/null
+++ b/v1.9.4/website/content/partials/packer-plugin-sdk/communicator/SSH.mdx
@@ -0,0 +1,5 @@
+<!-- Code generated from the comments of the SSH struct in communicator/config.go; DO NOT EDIT MANUALLY -->
+
+The SSH config defines configuration for the SSH communicator.
+
+<!-- End of code generated from the comments of the SSH struct in communicator/config.go; -->
diff --git a/v1.9.4/website/content/partials/packer-plugin-sdk/communicator/SSHInterface-not-required.mdx b/v1.9.4/website/content/partials/packer-plugin-sdk/communicator/SSHInterface-not-required.mdx
new file mode 100644
index 0000000..8a85348
--- /dev/null
+++ b/v1.9.4/website/content/partials/packer-plugin-sdk/communicator/SSHInterface-not-required.mdx
@@ -0,0 +1,20 @@
+<!-- Code generated from the comments of the SSHInterface struct in communicator/config.go; DO NOT EDIT MANUALLY -->
+
+- `ssh_interface` (string) - 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 used as the host for SSH. The default behaviour
+ if inside a VPC is to use the public IP address if available, otherwise
+ the private IP address will be used. If not in a VPC the public DNS name
+ will be used. Also works for WinRM.
+
+ Where Packer is configured for an outbound proxy but WinRM traffic
+ should be direct, `ssh_interface` must be set to `private_dns` and
+ `<region>.compute.internal` included in the `NO_PROXY` environment
+ variable.
+
+- `ssh_ip_version` (string) - The IP version to use for SSH connections, valid values are `4` and `6`.
+ Useful on dual stacked instances where the default behavior is to
+ connect via whichever IP address is returned first from the OpenStack
+ API.
+
+<!-- End of code generated from the comments of the SSHInterface struct in communicator/config.go; -->
diff --git a/v1.9.4/website/content/partials/packer-plugin-sdk/communicator/SSHInterface.mdx b/v1.9.4/website/content/partials/packer-plugin-sdk/communicator/SSHInterface.mdx
new file mode 100644
index 0000000..2a49158
--- /dev/null
+++ b/v1.9.4/website/content/partials/packer-plugin-sdk/communicator/SSHInterface.mdx
@@ -0,0 +1,6 @@
+<!-- Code generated from the comments of the SSHInterface struct in communicator/config.go; DO NOT EDIT MANUALLY -->
+
+SSHInterface defines whether to use public or private, addresses, and whether
+to use IPv4 or IPv6.
+
+<!-- End of code generated from the comments of the SSHInterface struct in communicator/config.go; -->
diff --git a/v1.9.4/website/content/partials/packer-plugin-sdk/communicator/SSHTemporaryKeyPair-not-required.mdx b/v1.9.4/website/content/partials/packer-plugin-sdk/communicator/SSHTemporaryKeyPair-not-required.mdx
new file mode 100644
index 0000000..f0f5813
--- /dev/null
+++ b/v1.9.4/website/content/partials/packer-plugin-sdk/communicator/SSHTemporaryKeyPair-not-required.mdx
@@ -0,0 +1,17 @@
+<!-- Code generated from the comments of the SSHTemporaryKeyPair struct in communicator/config.go; DO NOT EDIT MANUALLY -->
+
+- `temporary_key_pair_type` (string) - `dsa` | `ecdsa` | `ed25519` | `rsa` ( the default )
+
+ Specifies the type of key to create. The possible values are 'dsa',
+ 'ecdsa', 'ed25519', or 'rsa'.
+
+- `temporary_key_pair_bits` (int) - Specifies the number of bits in the key to create. For RSA keys, the
+ minimum size is 1024 bits and the default is 4096 bits. Generally, 3072
+ bits is considered sufficient. DSA keys must be exactly 1024 bits as
+ specified by FIPS 186-2. For ECDSA keys, bits determines the key length
+ by selecting from one of three elliptic curve sizes: 256, 384 or 521
+ bits. Attempting to use bit lengths other than these three values for
+ ECDSA keys will fail. Ed25519 keys have a fixed length and bits will be
+ ignored.
+
+<!-- End of code generated from the comments of the SSHTemporaryKeyPair struct in communicator/config.go; -->
diff --git a/v1.9.4/website/content/partials/packer-plugin-sdk/communicator/SSHTemporaryKeyPair.mdx b/v1.9.4/website/content/partials/packer-plugin-sdk/communicator/SSHTemporaryKeyPair.mdx
new file mode 100644
index 0000000..61a6e43
--- /dev/null
+++ b/v1.9.4/website/content/partials/packer-plugin-sdk/communicator/SSHTemporaryKeyPair.mdx
@@ -0,0 +1,7 @@
+<!-- Code generated from the comments of the SSHTemporaryKeyPair struct in communicator/config.go; DO NOT EDIT MANUALLY -->
+
+When no ssh credentials are specified, Packer will generate a temporary SSH
+keypair for the instance. You can change the algorithm type and bits
+settings.
+
+<!-- End of code generated from the comments of the SSHTemporaryKeyPair struct in communicator/config.go; -->
diff --git a/v1.9.4/website/content/partials/packer-plugin-sdk/communicator/WinRM-not-required.mdx b/v1.9.4/website/content/partials/packer-plugin-sdk/communicator/WinRM-not-required.mdx
new file mode 100644
index 0000000..f6b5de0
--- /dev/null
+++ b/v1.9.4/website/content/partials/packer-plugin-sdk/communicator/WinRM-not-required.mdx
@@ -0,0 +1,35 @@
+<!-- Code generated from the comments of the WinRM struct in communicator/config.go; DO NOT EDIT MANUALLY -->
+
+- `winrm_username` (string) - The username to use to connect to WinRM.
+
+- `winrm_password` (string) - The password to use to connect to WinRM.
+
+- `winrm_host` (string) - The address for WinRM to connect to.
+
+ NOTE: If using an Amazon EBS builder, you can specify the interface
+ WinRM connects to via
+ [`ssh_interface`](/packer/plugins/builders/amazon/ebs#ssh_interface)
+
+- `winrm_no_proxy` (bool) - Setting this to `true` adds the remote
+ `host:port` to the `NO_PROXY` environment variable. This has the effect of
+ bypassing any configured proxies when connecting to the remote host.
+ Default to `false`.
+
+- `winrm_port` (int) - The WinRM port to connect to. This defaults to `5985` for plain
+ unencrypted connection and `5986` for SSL when `winrm_use_ssl` is set to
+ true.
+
+- `winrm_timeout` (duration string | ex: "1h5m2s") - The amount of time to wait for WinRM to become available. This defaults
+ to `30m` since setting up a Windows machine generally takes a long time.
+
+- `winrm_use_ssl` (bool) - If `true`, use HTTPS for WinRM.
+
+- `winrm_insecure` (bool) - If `true`, do not check server certificate chain and host name.
+
+- `winrm_use_ntlm` (bool) - If `true`, NTLMv2 authentication (with session security) will be used
+ for WinRM, rather than default (basic authentication), removing the
+ requirement for basic authentication to be enabled within the target
+ guest. Further reading for remote connection authentication can be found
+ [here](https://msdn.microsoft.com/en-us/library/aa384295(v=vs.85).aspx).
+
+<!-- End of code generated from the comments of the WinRM struct in communicator/config.go; -->
diff --git a/v1.9.4/website/content/partials/packer-plugin-sdk/communicator/WinRM.mdx b/v1.9.4/website/content/partials/packer-plugin-sdk/communicator/WinRM.mdx
new file mode 100644
index 0000000..82309b7
--- /dev/null
+++ b/v1.9.4/website/content/partials/packer-plugin-sdk/communicator/WinRM.mdx
@@ -0,0 +1,5 @@
+<!-- Code generated from the comments of the WinRM struct in communicator/config.go; DO NOT EDIT MANUALLY -->
+
+The WinRM config defines configuration for the WinRM communicator.
+
+<!-- End of code generated from the comments of the WinRM struct in communicator/config.go; -->
diff --git a/v1.9.4/website/content/partials/packer-plugin-sdk/multistep/commonsteps/CDConfig-not-required.mdx b/v1.9.4/website/content/partials/packer-plugin-sdk/multistep/commonsteps/CDConfig-not-required.mdx
new file mode 100644
index 0000000..686caf3
--- /dev/null
+++ b/v1.9.4/website/content/partials/packer-plugin-sdk/multistep/commonsteps/CDConfig-not-required.mdx
@@ -0,0 +1,65 @@
+<!-- Code generated from the comments of the CDConfig struct in multistep/commonsteps/extra_iso_config.go; DO NOT EDIT MANUALLY -->
+
+- `cd_files` ([]string) - A list of files to place onto a CD that is attached when the VM is
+ booted. This can include either files or directories; any directories
+ will be copied onto the CD recursively, preserving directory structure
+ hierarchy. Symlinks will have the link's target copied into the directory
+ tree on the CD where the symlink was. File globbing is allowed.
+
+ Usage example (JSON):
+
+ ```json
+ "cd_files": ["./somedirectory/meta-data", "./somedirectory/user-data"],
+ "cd_label": "cidata",
+ ```
+
+ Usage example (HCL):
+
+ ```hcl
+ cd_files = ["./somedirectory/meta-data", "./somedirectory/user-data"]
+ cd_label = "cidata"
+ ```
+
+ The above will create a CD with two files, user-data and meta-data in the
+ CD root. This specific example is how you would create a CD that can be
+ used for an Ubuntu 20.04 autoinstall.
+
+ Since globbing is also supported,
+
+ ```hcl
+ cd_files = ["./somedirectory/*"]
+ cd_label = "cidata"
+ ```
+
+ Would also be an acceptable way to define the above cd. The difference
+ between providing the directory with or without the glob is whether the
+ directory itself or its contents will be at the CD root.
+
+ Use of this option assumes that you have a command line tool installed
+ that can handle the iso creation. Packer will use one of the following
+ tools:
+
+ * xorriso
+ * mkisofs
+ * hdiutil (normally found in macOS)
+ * oscdimg (normally found in Windows as part of the Windows ADK)
+
+- `cd_content` (map[string]string) - Key/Values to add to the CD. The keys represent the paths, and the values
+ contents. It can be used alongside `cd_files`, which is useful to add large
+ files without loading them into memory. If any paths are specified by both,
+ the contents in `cd_content` will take precedence.
+
+ Usage example (HCL):
+
+ ```hcl
+ cd_files = ["vendor-data"]
+ cd_content = {
+ "meta-data" = jsonencode(local.instance_data)
+ "user-data" = templatefile("user-data", { packages = ["nginx"] })
+ }
+ cd_label = "cidata"
+ ```
+
+- `cd_label` (string) - CD Label
+
+<!-- End of code generated from the comments of the CDConfig struct in multistep/commonsteps/extra_iso_config.go; -->
diff --git a/v1.9.4/website/content/partials/packer-plugin-sdk/multistep/commonsteps/CDConfig.mdx b/v1.9.4/website/content/partials/packer-plugin-sdk/multistep/commonsteps/CDConfig.mdx
new file mode 100644
index 0000000..087804a
--- /dev/null
+++ b/v1.9.4/website/content/partials/packer-plugin-sdk/multistep/commonsteps/CDConfig.mdx
@@ -0,0 +1,13 @@
+<!-- Code generated from the comments of the CDConfig struct in multistep/commonsteps/extra_iso_config.go; DO NOT EDIT MANUALLY -->
+
+An iso (CD) containing custom files can be made available for your build.
+
+By default, no extra CD will be attached. All files listed in this setting
+get placed into the root directory of the CD and the CD is attached as the
+second CD device.
+
+This config exists to work around modern operating systems that have no
+way to mount floppy disks, which was our previous go-to for adding files at
+boot time.
+
+<!-- End of code generated from the comments of the CDConfig struct in multistep/commonsteps/extra_iso_config.go; -->
diff --git a/v1.9.4/website/content/partials/packer-plugin-sdk/multistep/commonsteps/FloppyConfig-not-required.mdx b/v1.9.4/website/content/partials/packer-plugin-sdk/multistep/commonsteps/FloppyConfig-not-required.mdx
new file mode 100644
index 0000000..325b13f
--- /dev/null
+++ b/v1.9.4/website/content/partials/packer-plugin-sdk/multistep/commonsteps/FloppyConfig-not-required.mdx
@@ -0,0 +1,35 @@
+<!-- Code generated from the comments of the FloppyConfig struct in multistep/commonsteps/floppy_config.go; DO NOT EDIT MANUALLY -->
+
+- `floppy_files` ([]string) - A list of files to place onto a floppy disk that is attached when the VM
+ is booted. Currently, no support exists for creating sub-directories on
+ the floppy. Wildcard characters (\\*, ?, and \[\]) are allowed. Directory
+ names are also allowed, which will add all the files found in the
+ directory to the floppy.
+
+- `floppy_dirs` ([]string) - A list of directories to place onto the floppy disk recursively. This is
+ similar to the `floppy_files` option except that the directory structure
+ is preserved. This is useful for when your floppy disk includes drivers
+ or if you just want to organize it's contents as a hierarchy. Wildcard
+ characters (\\*, ?, and \[\]) are allowed. The maximum summary size of
+ all files in the listed directories are the same as in `floppy_files`.
+
+- `floppy_content` (map[string]string) - Key/Values to add to the floppy disk. The keys represent the paths, and
+ the values contents. It can be used alongside `floppy_files` or
+ `floppy_dirs`, which is useful to add large files without loading them
+ into memory. If any paths are specified by both, the contents in
+ `floppy_content` will take precedence.
+
+ Usage example (HCL):
+
+ ```hcl
+ floppy_files = ["vendor-data"]
+ floppy_content = {
+ "meta-data" = jsonencode(local.instance_data)
+ "user-data" = templatefile("user-data", { packages = ["nginx"] })
+ }
+ floppy_label = "cidata"
+ ```
+
+- `floppy_label` (string) - Floppy Label
+
+<!-- End of code generated from the comments of the FloppyConfig struct in multistep/commonsteps/floppy_config.go; -->
diff --git a/v1.9.4/website/content/partials/packer-plugin-sdk/multistep/commonsteps/FloppyConfig.mdx b/v1.9.4/website/content/partials/packer-plugin-sdk/multistep/commonsteps/FloppyConfig.mdx
new file mode 100644
index 0000000..b7c307c
--- /dev/null
+++ b/v1.9.4/website/content/partials/packer-plugin-sdk/multistep/commonsteps/FloppyConfig.mdx
@@ -0,0 +1,12 @@
+<!-- Code generated from the comments of the FloppyConfig struct in multistep/commonsteps/floppy_config.go; DO NOT EDIT MANUALLY -->
+
+A floppy can be made available for your build. This is most useful for
+unattended Windows installs, which look for an Autounattend.xml file on
+removable media. By default, no floppy will be attached. All files listed in
+this setting get placed into the root directory of the floppy and the floppy
+is attached as the first floppy device. The summary size of the listed files
+must not exceed 1.44 MB. The supported ways to move large files into the OS
+are using `http_directory` or [the file
+provisioner](/packer/docs/provisioners/file).
+
+<!-- End of code generated from the comments of the FloppyConfig struct in multistep/commonsteps/floppy_config.go; -->
diff --git a/v1.9.4/website/content/partials/packer-plugin-sdk/multistep/commonsteps/HTTPConfig-not-required.mdx b/v1.9.4/website/content/partials/packer-plugin-sdk/multistep/commonsteps/HTTPConfig-not-required.mdx
new file mode 100644
index 0000000..83f8a4c
--- /dev/null
+++ b/v1.9.4/website/content/partials/packer-plugin-sdk/multistep/commonsteps/HTTPConfig-not-required.mdx
@@ -0,0 +1,37 @@
+<!-- Code generated from the comments of the HTTPConfig struct in multistep/commonsteps/http_config.go; DO NOT EDIT MANUALLY -->
+
+- `http_directory` (string) - Path to a directory to serve using an HTTP server. The files in this
+ directory will be available over HTTP that will be requestable from the
+ virtual machine. This is useful for hosting kickstart files and so on.
+ By default this is an empty string, which means no HTTP server will be
+ started. The address and port of the HTTP server will be available as
+ variables in `boot_command`. This is covered in more detail below.
+
+- `http_content` (map[string]string) - Key/Values to serve using an HTTP server. `http_content` works like and
+ conflicts with `http_directory`. The keys represent the paths and the
+ values contents, the keys must start with a slash, ex: `/path/to/file`.
+ `http_content` is useful for hosting kickstart files and so on. By
+ default this is empty, which means no HTTP server will be started. The
+ address and port of the HTTP server will be available as variables in
+ `boot_command`. This is covered in more detail below.
+ Example:
+ ```hcl
+ http_content = {
+ "/a/b" = file("http/b")
+ "/foo/bar" = templatefile("${path.root}/preseed.cfg", { packages = ["nginx"] })
+ }
+ ```
+
+- `http_port_min` (int) - These are the minimum and maximum port to use for the HTTP server
+ started to serve the `http_directory`. Because Packer often runs in
+ parallel, Packer will choose a randomly available port in this range to
+ run the HTTP server. If you want to force the HTTP server to be on one
+ port, make this minimum and maximum port the same. By default the values
+ are `8000` and `9000`, respectively.
+
+- `http_port_max` (int) - HTTP Port Max
+
+- `http_bind_address` (string) - This is the bind address for the HTTP server. Defaults to 0.0.0.0 so that
+ it will work with any network interface.
+
+<!-- End of code generated from the comments of the HTTPConfig struct in multistep/commonsteps/http_config.go; -->
diff --git a/v1.9.4/website/content/partials/packer-plugin-sdk/multistep/commonsteps/HTTPConfig.mdx b/v1.9.4/website/content/partials/packer-plugin-sdk/multistep/commonsteps/HTTPConfig.mdx
new file mode 100644
index 0000000..b3cdfc9
--- /dev/null
+++ b/v1.9.4/website/content/partials/packer-plugin-sdk/multistep/commonsteps/HTTPConfig.mdx
@@ -0,0 +1,11 @@
+<!-- Code generated from the comments of the HTTPConfig struct in multistep/commonsteps/http_config.go; DO NOT EDIT MANUALLY -->
+
+Packer will create an http server serving `http_directory` when it is set, a
+random free port will be selected and the architecture of the directory
+referenced will be available in your builder.
+
+Example usage from a builder:
+
+ `wget http://{{ .HTTPIP }}:{{ .HTTPPort }}/foo/bar/preseed.cfg`
+
+<!-- End of code generated from the comments of the HTTPConfig struct in multistep/commonsteps/http_config.go; -->
diff --git a/v1.9.4/website/content/partials/packer-plugin-sdk/multistep/commonsteps/ISOConfig-not-required.mdx b/v1.9.4/website/content/partials/packer-plugin-sdk/multistep/commonsteps/ISOConfig-not-required.mdx
new file mode 100644
index 0000000..6395017
--- /dev/null
+++ b/v1.9.4/website/content/partials/packer-plugin-sdk/multistep/commonsteps/ISOConfig-not-required.mdx
@@ -0,0 +1,15 @@
+<!-- Code generated from the comments of the ISOConfig struct in multistep/commonsteps/iso_config.go; DO NOT EDIT MANUALLY -->
+
+- `iso_urls` ([]string) - Multiple URLs for the ISO to download. Packer will try these in order.
+ If anything goes wrong attempting to download or while downloading a
+ single URL, it will move on to the next. All URLs must point to the same
+ file (same checksum). By default this is empty and `iso_url` is used.
+ Only one of `iso_url` or `iso_urls` can be specified.
+
+- `iso_target_path` (string) - The path where the iso should be saved after download. By default will
+ go in the packer cache, with a hash of the original filename and
+ checksum as its name.
+
+- `iso_target_extension` (string) - The extension of the iso file after download. This defaults to `iso`.
+
+<!-- End of code generated from the comments of the ISOConfig struct in multistep/commonsteps/iso_config.go; -->
diff --git a/v1.9.4/website/content/partials/packer-plugin-sdk/multistep/commonsteps/ISOConfig-required.mdx b/v1.9.4/website/content/partials/packer-plugin-sdk/multistep/commonsteps/ISOConfig-required.mdx
new file mode 100644
index 0000000..b8598ce
--- /dev/null
+++ b/v1.9.4/website/content/partials/packer-plugin-sdk/multistep/commonsteps/ISOConfig-required.mdx
@@ -0,0 +1,27 @@
+<!-- Code generated from the comments of the ISOConfig struct in multistep/commonsteps/iso_config.go; DO NOT EDIT MANUALLY -->
+
+- `iso_checksum` (string) - The checksum for the ISO file or virtual hard drive file. The type of
+ the checksum is specified within the checksum field as a prefix, ex:
+ "md5:{$checksum}". The type of the checksum can also be omitted and
+ Packer will try to infer it based on string length. Valid values are
+ "none", "{$checksum}", "md5:{$checksum}", "sha1:{$checksum}",
+ "sha256:{$checksum}", "sha512:{$checksum}" or "file:{$path}". Here is a
+ list of valid checksum values:
+ * md5:090992ba9fd140077b0661cb75f7ce13
+ * 090992ba9fd140077b0661cb75f7ce13
+ * sha1:ebfb681885ddf1234c18094a45bbeafd91467911
+ * ebfb681885ddf1234c18094a45bbeafd91467911
+ * sha256:ed363350696a726b7932db864dda019bd2017365c9e299627830f06954643f93
+ * ed363350696a726b7932db864dda019bd2017365c9e299627830f06954643f93
+ * file:http://releases.ubuntu.com/20.04/SHA256SUMS
+ * file:file://./local/path/file.sum
+ * file:./local/path/file.sum
+ * none
+ Although the checksum will not be verified when it is set to "none",
+ this is not recommended since these files can be very large and
+ corruption does happen from time to time.
+
+- `iso_url` (string) - A URL to the ISO containing the installation image or virtual hard drive
+ (VHD or VHDX) file to clone.
+
+<!-- End of code generated from the comments of the ISOConfig struct in multistep/commonsteps/iso_config.go; -->
diff --git a/v1.9.4/website/content/partials/packer-plugin-sdk/multistep/commonsteps/ISOConfig.mdx b/v1.9.4/website/content/partials/packer-plugin-sdk/multistep/commonsteps/ISOConfig.mdx
new file mode 100644
index 0000000..58293cd
--- /dev/null
+++ b/v1.9.4/website/content/partials/packer-plugin-sdk/multistep/commonsteps/ISOConfig.mdx
@@ -0,0 +1,64 @@
+<!-- Code generated from the comments of the ISOConfig struct in multistep/commonsteps/iso_config.go; DO NOT EDIT MANUALLY -->
+
+By default, Packer will symlink, download or copy image files to the Packer
+cache into a "`hash($iso_url+$iso_checksum).$iso_target_extension`" file.
+Packer uses [hashicorp/go-getter](https://github.com/hashicorp/go-getter) in
+file mode in order to perform a download.
+
+go-getter supports the following protocols:
+
+* Local files
+* Git
+* Mercurial
+* HTTP
+* Amazon S3
+
+Examples:
+go-getter can guess the checksum type based on `iso_checksum` length, and it is
+also possible to specify the checksum type.
+
+In JSON:
+
+```json
+ "iso_checksum": "946a6077af6f5f95a51f82fdc44051c7aa19f9cfc5f737954845a6050543d7c2",
+ "iso_url": "ubuntu.org/.../ubuntu-14.04.1-server-amd64.iso"
+```
+
+```json
+ "iso_checksum": "file:ubuntu.org/..../ubuntu-14.04.1-server-amd64.iso.sum",
+ "iso_url": "ubuntu.org/.../ubuntu-14.04.1-server-amd64.iso"
+```
+
+```json
+ "iso_checksum": "file://./shasums.txt",
+ "iso_url": "ubuntu.org/.../ubuntu-14.04.1-server-amd64.iso"
+```
+
+```json
+ "iso_checksum": "file:./shasums.txt",
+ "iso_url": "ubuntu.org/.../ubuntu-14.04.1-server-amd64.iso"
+```
+
+In HCL2:
+
+```hcl
+ iso_checksum = "946a6077af6f5f95a51f82fdc44051c7aa19f9cfc5f737954845a6050543d7c2"
+ iso_url = "ubuntu.org/.../ubuntu-14.04.1-server-amd64.iso"
+```
+
+```hcl
+ iso_checksum = "file:ubuntu.org/..../ubuntu-14.04.1-server-amd64.iso.sum"
+ iso_url = "ubuntu.org/.../ubuntu-14.04.1-server-amd64.iso"
+```
+
+```hcl
+ iso_checksum = "file://./shasums.txt"
+ iso_url = "ubuntu.org/.../ubuntu-14.04.1-server-amd64.iso"
+```
+
+```hcl
+ iso_checksum = "file:./shasums.txt",
+ iso_url = "ubuntu.org/.../ubuntu-14.04.1-server-amd64.iso"
+```
+
+<!-- End of code generated from the comments of the ISOConfig struct in multistep/commonsteps/iso_config.go; -->
diff --git a/v1.9.4/website/content/partials/packer-plugin-sdk/provisioners/common-config.mdx b/v1.9.4/website/content/partials/packer-plugin-sdk/provisioners/common-config.mdx
new file mode 100644
index 0000000..15cd1b8
--- /dev/null
+++ b/v1.9.4/website/content/partials/packer-plugin-sdk/provisioners/common-config.mdx
@@ -0,0 +1,68 @@
+Parameters common to all provisioners:
+
+- `pause_before` (duration) - Sleep for duration before execution.
+
+- `max_retries` (int) - Max times the provisioner will retry in case of failure. Defaults to zero (0). Zero means an error will not be retried.
+
+- `only` (array of string) - Only run the provisioner for listed builder(s)
+ by name.
+
+- `override` (object) - Override the builder with different settings for a
+ specific builder, eg :
+
+ In HCL2:
+
+ ```hcl
+ source "null" "example1" {
+ communicator = "none"
+ }
+
+ source "null" "example2" {
+ communicator = "none"
+ }
+
+ build {
+ sources = ["source.null.example1", "source.null.example2"]
+ provisioner "shell-local" {
+ inline = ["echo not overridden"]
+ override = {
+ example1 = {
+ inline = ["echo yes overridden"]
+ }
+ }
+ }
+ }
+ ```
+
+ In JSON:
+
+ ```json
+ {
+ "builders": [
+ {
+ "type": "null",
+ "name": "example1",
+ "communicator": "none"
+ },
+ {
+ "type": "null",
+ "name": "example2",
+ "communicator": "none"
+ }
+ ],
+ "provisioners": [
+ {
+ "type": "shell-local",
+ "inline": ["echo not overridden"],
+ "override": {
+ "example1": {
+ "inline": ["echo yes overridden"]
+ }
+ }
+ }
+ ]
+ }
+ ```
+
+- `timeout` (duration) - If the provisioner takes more than for example
+ `1h10m1s` or `10m` to finish, the provisioner will timeout and fail.
diff --git a/v1.9.4/website/content/partials/packer-plugin-sdk/provisioners/shell-config.mdx b/v1.9.4/website/content/partials/packer-plugin-sdk/provisioners/shell-config.mdx
new file mode 100644
index 0000000..009040c
--- /dev/null
+++ b/v1.9.4/website/content/partials/packer-plugin-sdk/provisioners/shell-config.mdx
@@ -0,0 +1,30 @@
+The reference of available configuration options is listed below. The only
+required element is either "inline" or "script". Every other option is
+optional.
+
+Exactly _one_ of the following is required:
+
+- `inline` (array of strings) - This is an array of commands to execute. The
+ commands are concatenated by newlines and turned into a single file, so
+ they are all executed within the same context. This allows you to change
+ directories in one command and use something in the directory in the next
+ and so on. Inline scripts are the easiest way to pull off simple tasks
+ within the machine.
+
+- `script` (string) - The path to a script to upload and execute in the
+ machine. This path can be absolute or relative. If it is relative, it is
+ relative to the working directory when Packer is executed.
+
+- `scripts` (array of strings) - An array of scripts to execute. The scripts
+ will be uploaded and executed in the order specified. Each script is
+ executed in isolation, so state such as variables from one script won't
+ carry on to the next.
+
+Optional parameters:
+
+- `binary` (boolean) - If true, specifies that the script(s) are binary
+ files, and Packer should therefore not convert Windows line endings to Unix
+ line endings (if there are any). By default this is false.
+
+- `valid_exit_codes` (list of ints) - Valid exit codes for the script. By
+ default this is just 0.
diff --git a/v1.9.4/website/content/partials/packer-plugin-sdk/provisioners/unmaintained-plugin.mdx b/v1.9.4/website/content/partials/packer-plugin-sdk/provisioners/unmaintained-plugin.mdx
new file mode 100644
index 0000000..f59f4b3
--- /dev/null
+++ b/v1.9.4/website/content/partials/packer-plugin-sdk/provisioners/unmaintained-plugin.mdx
@@ -0,0 +1 @@
+~> **This community maintained provisioner is currently unmaintained**; if you are interested in contributing or taking ownership of it, please reach out to us at [packer@hashicorp.com](mailto://packer@hashicorp.com). More details can be found in the [README](https://github.com/hashicorp/packer/blob/master/README.md#unmaintained-plugins).
diff --git a/v1.9.4/website/content/partials/packer-plugin-sdk/shutdowncommand/ShutdownConfig-not-required.mdx b/v1.9.4/website/content/partials/packer-plugin-sdk/shutdowncommand/ShutdownConfig-not-required.mdx
new file mode 100644
index 0000000..9cabd8e
--- /dev/null
+++ b/v1.9.4/website/content/partials/packer-plugin-sdk/shutdowncommand/ShutdownConfig-not-required.mdx
@@ -0,0 +1,17 @@
+<!-- Code generated from the comments of the ShutdownConfig struct in shutdowncommand/config.go; DO NOT EDIT MANUALLY -->
+
+- `shutdown_command` (string) - The command to use to gracefully shut down the machine once all
+ provisioning is complete. By default this is an empty string, which
+ tells Packer to just forcefully shut down the machine. This setting can
+ be safely omitted if for example, a shutdown command to gracefully halt
+ the machine is configured inside a provisioning script. If one or more
+ scripts require a reboot it is suggested to leave this blank (since
+ reboots may fail) and instead specify the final shutdown command in your
+ last script.
+
+- `shutdown_timeout` (duration string | ex: "1h5m2s") - The amount of time to wait after executing the shutdown_command for the
+ virtual machine to actually shut down. If the machine doesn't shut down
+ in this time it is considered an error. By default, the time out is "5m"
+ (five minutes).
+
+<!-- End of code generated from the comments of the ShutdownConfig struct in shutdowncommand/config.go; -->
diff --git a/v1.9.4/website/content/partials/packer-plugin-sdk/shutdowncommand/ShutdownConfig.mdx b/v1.9.4/website/content/partials/packer-plugin-sdk/shutdowncommand/ShutdownConfig.mdx
new file mode 100644
index 0000000..51ceae9
--- /dev/null
+++ b/v1.9.4/website/content/partials/packer-plugin-sdk/shutdowncommand/ShutdownConfig.mdx
@@ -0,0 +1,12 @@
+<!-- Code generated from the comments of the ShutdownConfig struct in shutdowncommand/config.go; DO NOT EDIT MANUALLY -->
+
+ShutdownConfig defines implementation details for shutting down a VM once it
+is done being provisioned.
+
+It is provided as a convenience to encourage builder developers to
+consider implementing these options, which we believe are valuable for all
+builders. It also helps guarantee that option names for similar options
+are the same across the various builders. Embed it in your builder config
+using the `mapstructure:",squash"` struct tag.
+
+<!-- End of code generated from the comments of the ShutdownConfig struct in shutdowncommand/config.go; -->
diff --git a/v1.9.4/website/content/partials/path/separator-note.mdx b/v1.9.4/website/content/partials/path/separator-note.mdx
new file mode 100644
index 0000000..de383cc
--- /dev/null
+++ b/v1.9.4/website/content/partials/path/separator-note.mdx
@@ -0,0 +1,6 @@
+~> **Note:** If possible, try to always use a forward slash `/` as the path separator,
+especially when dealing with relative paths. A backward slash `\` will work on
+Windows and is the official Windows path separator, but when building from any
+system that is not Windows, Packer will only treat slashes `/` as path
+separators, and treat backslashes as plain text. Which could lead to pathing
+errors.
diff --git a/v1.9.4/website/content/partials/plugins/plugin-location.mdx b/v1.9.4/website/content/partials/plugins/plugin-location.mdx
new file mode 100644
index 0000000..d8e997c
--- /dev/null
+++ b/v1.9.4/website/content/partials/plugins/plugin-location.mdx
@@ -0,0 +1,25 @@
+Upon the initialization of Packer, any externally installed plugin will be automatically
+discovered and loaded.
+
+Packer plugins will usually be located within a plugins sub-directory under Packer's main config directory
+[PACKER_CONFIG_DIR](/packer/docs/configure#packer-s-config-directory). If `PACKER_CONFIG_DIR` is
+either not set or empty, a default equal to `$HOME/.config/packer/plugins` on UNIX, or `%APPDATA%\packer.d\plugins`
+for Windows, will be used.
+
+Where applicable, some installation processes such as `packer init` may override the plugin loading process.
+Refer to the specific installation guides for any plugin loading overrides.
+
+Packer uses the following process for loading the correct plugin:
+
+1. All directories under the `PACKER_PLUGIN_PATH` environment variable, if `PACKER_PLUGIN_PATH`
+is set. The `PACKER_PLUGIN_PATH` takes precedences over all other plugin directories; no other directories will be checked.
+1. The directory where `packer` is installed, or the executable directory.
+1. The current working directory, where `packer build` is being invoked. (`"."`)
+1. The `PACKER_CONFIG_DIR/plugins` directory. `PACKER_CONFIG_DIR` refers to *[Packer's config
+directory](/packer/docs/configure#packer-s-config-directory)*, if it could be found.
+
+-> **Note:** The `PACKER_PLUGIN_PATH` environment variable can be set to more that one directories;
+for example, ~/custom-dir-1:~/custom-dir-2. Separate directories in the PATH string using a colon (:) on UNIX systems
+and a semicolon (;) on Windows systems. The above example path would be able to find a single or multi-component plugin
+in either `~/custom-dir-1/packer/` or `~/custom-dir-2/`.
+
diff --git a/v1.9.4/website/content/partials/plugins/plugin-tiers-and-namespaces.mdx b/v1.9.4/website/content/partials/plugins/plugin-tiers-and-namespaces.mdx
new file mode 100644
index 0000000..6d4d780
--- /dev/null
+++ b/v1.9.4/website/content/partials/plugins/plugin-tiers-and-namespaces.mdx
@@ -0,0 +1,18 @@
+## Tiers and Namespaces
+
+Packer plugins are published and maintained by a variety of sources, including
+HashiCorp, and the Packer community. We use tiers and badges to
+denote the source of a plugin. Additionally, namespaces are used to help users
+identify the organization or publisher responsible for the integration, as shown
+in the table below.
+
+| Tier | Description | Namespace |
+| -------------------------------- | ----------------------------------------------------------------------------------------------------------------------------- | ----------------------------------------------------------- |
+| <PluginBadge type="official" /> | Official plugins are owned and maintained by HashiCorp. | hashicorp |
+| <PluginBadge type="verified" /> | Verified plugins are owned and maintained by third-party technology partners. Plugins in this tier indicate HashiCorp has verified the authenticity of the Plugin’s publisher, and that the partner is a member of the [HashiCorp Technology Partner Program](https://www.hashicorp.com/partners).| Third-party organization |
+| <PluginBadge type="community" /> | Community providers are published by individual maintainers, groups of maintainers, or other members of the Packer community. | Third-party organization or maintainer's individual account |
+| <PluginBadge type="archived" /> | Archived plugins are plugins that are no longer maintained by HashiCorp, a partner, or the community. This may occur if an API is deprecated or interest was low. | hashicorp or third-party |
+
+
+## HCP Packer Badge
+<PluginBadge type="hcp_packer_ready" /> is present for plugins that HashiCorp has verified to communicate build status to the HCP Packer registry.
diff --git a/v1.9.4/website/content/partials/post-processor/manifest/Config-not-required.mdx b/v1.9.4/website/content/partials/post-processor/manifest/Config-not-required.mdx
new file mode 100644
index 0000000..060a79a
--- /dev/null
+++ b/v1.9.4/website/content/partials/post-processor/manifest/Config-not-required.mdx
@@ -0,0 +1,15 @@
+<!-- Code generated from the comments of the Config struct in post-processor/manifest/post-processor.go; DO NOT EDIT MANUALLY -->
+
+- `output` (string) - The manifest will be written to this file. This defaults to
+ `packer-manifest.json`.
+
+- `strip_path` (bool) - Write only filename without the path to the manifest file. This defaults
+ to false.
+
+- `strip_time` (bool) - Don't write the `build_time` field from the output.
+
+- `custom_data` (map[string]string) - Arbitrary data to add to the manifest. This is a [template
+ engine](/packer/docs/templates/legacy_json_templates/engine). Therefore, you
+ may use user variables and template functions in this field.
+
+<!-- End of code generated from the comments of the Config struct in post-processor/manifest/post-processor.go; -->
diff --git a/v1.9.4/website/content/partials/post-processors/community_post-processors.mdx b/v1.9.4/website/content/partials/post-processors/community_post-processors.mdx
new file mode 100644
index 0000000..af4e3ae
--- /dev/null
+++ b/v1.9.4/website/content/partials/post-processors/community_post-processors.mdx
@@ -0,0 +1,4 @@
+### Community Post-Processors
+
+- [Exoscale Import post-processor](https://github.com/exoscale/packer-plugin-exoscale) - A post-processor to import Exoscale custom templates from disk image files.
+
diff --git a/v1.9.4/website/content/partials/provisioner/file/Config-not-required.mdx b/v1.9.4/website/content/partials/provisioner/file/Config-not-required.mdx
new file mode 100644
index 0000000..1d30c35
--- /dev/null
+++ b/v1.9.4/website/content/partials/provisioner/file/Config-not-required.mdx
@@ -0,0 +1,21 @@
+<!-- Code generated from the comments of the Config struct in provisioner/file/provisioner.go; DO NOT EDIT MANUALLY -->
+
+- `sources` ([]string) - A list of sources to upload. This can be used in place of the `source`
+ option if you have several files that you want to upload to the same
+ place. Note that the destination must be a directory with a trailing
+ slash, and that all files listed in `sources` will be uploaded to the
+ same directory with their file names preserved.
+
+- `direction` (string) - The direction of the file transfer. This defaults to "upload". If it is
+ set to "download" then the file "source" in the machine will be
+ downloaded locally to "destination"
+
+- `generated` (bool) - For advanced users only. If true, check the file existence only before
+ uploading, rather than upon pre-build validation. This allows users to
+ upload files created on-the-fly. This defaults to false. We
+ don't recommend using this feature, since it can cause Packer to become
+ dependent on system state. We would prefer you generate your files before
+ the Packer run, but realize that there are situations where this may be
+ unavoidable.
+
+<!-- End of code generated from the comments of the Config struct in provisioner/file/provisioner.go; -->
diff --git a/v1.9.4/website/content/partials/provisioner/file/Config-required.mdx b/v1.9.4/website/content/partials/provisioner/file/Config-required.mdx
new file mode 100644
index 0000000..1128182
--- /dev/null
+++ b/v1.9.4/website/content/partials/provisioner/file/Config-required.mdx
@@ -0,0 +1,27 @@
+<!-- Code generated from the comments of the Config struct in provisioner/file/provisioner.go; DO NOT EDIT MANUALLY -->
+
+- `content` (string) - This is the content to copy to `destination`. If destination is a file,
+ content will be written to that file, in case of a directory a file named
+ `pkr-file-content` is created. It's recommended to use a file as the
+ destination. The `templatefile` function might be used here, or any
+ interpolation syntax. This attribute cannot be specified with source or
+ sources.
+
+- `source` (string) - The path to a local file or directory to upload to the
+ machine. The path can be absolute or relative. If it is relative, it is
+ relative to the working directory when Packer is executed. If this is a
+ directory, the existence of a trailing slash is important. Read below on
+ uploading directories. Mandatory unless `sources` is set.
+
+- `destination` (string) - The path where the file will be uploaded to in the machine. This value
+ must be a writable location and any parent directories
+ must already exist. If the provisioning user (generally not root) cannot
+ write to this directory, you will receive a "Permission Denied" error.
+ If the source is a file, it's a good idea to make the destination a file
+ as well, but if you set your destination as a directory, at least make
+ sure that the destination ends in a trailing slash so that Packer knows
+ to use the source's basename in the final upload path. Failure to do so
+ may cause Packer to fail on file uploads. If the destination file
+ already exists, it will be overwritten.
+
+<!-- End of code generated from the comments of the Config struct in provisioner/file/provisioner.go; -->
diff --git a/v1.9.4/website/content/partials/provisioners/common-config.mdx b/v1.9.4/website/content/partials/provisioners/common-config.mdx
new file mode 100644
index 0000000..15cd1b8
--- /dev/null
+++ b/v1.9.4/website/content/partials/provisioners/common-config.mdx
@@ -0,0 +1,68 @@
+Parameters common to all provisioners:
+
+- `pause_before` (duration) - Sleep for duration before execution.
+
+- `max_retries` (int) - Max times the provisioner will retry in case of failure. Defaults to zero (0). Zero means an error will not be retried.
+
+- `only` (array of string) - Only run the provisioner for listed builder(s)
+ by name.
+
+- `override` (object) - Override the builder with different settings for a
+ specific builder, eg :
+
+ In HCL2:
+
+ ```hcl
+ source "null" "example1" {
+ communicator = "none"
+ }
+
+ source "null" "example2" {
+ communicator = "none"
+ }
+
+ build {
+ sources = ["source.null.example1", "source.null.example2"]
+ provisioner "shell-local" {
+ inline = ["echo not overridden"]
+ override = {
+ example1 = {
+ inline = ["echo yes overridden"]
+ }
+ }
+ }
+ }
+ ```
+
+ In JSON:
+
+ ```json
+ {
+ "builders": [
+ {
+ "type": "null",
+ "name": "example1",
+ "communicator": "none"
+ },
+ {
+ "type": "null",
+ "name": "example2",
+ "communicator": "none"
+ }
+ ],
+ "provisioners": [
+ {
+ "type": "shell-local",
+ "inline": ["echo not overridden"],
+ "override": {
+ "example1": {
+ "inline": ["echo yes overridden"]
+ }
+ }
+ }
+ ]
+ }
+ ```
+
+- `timeout` (duration) - If the provisioner takes more than for example
+ `1h10m1s` or `10m` to finish, the provisioner will timeout and fail.
diff --git a/v1.9.4/website/content/partials/provisioners/community_provisioners.mdx b/v1.9.4/website/content/partials/provisioners/community_provisioners.mdx
new file mode 100644
index 0000000..e01f48a
--- /dev/null
+++ b/v1.9.4/website/content/partials/provisioners/community_provisioners.mdx
@@ -0,0 +1,9 @@
+### Community Provisioners
+
+- [Comment Provisioner](https://github.com/SwampDragons/packer-provisioner-comment) -
+ Example provisioner that allows you to annotate your build with bubble-text
+ comments.
+
+- [Windows Update provisioner](https://github.com/rgl/packer-plugin-windows-update) -
+ A provisioner for gracefully handling Windows updates and the reboots they
+ cause.
diff --git a/v1.9.4/website/content/partials/provisioners/shell-config.mdx b/v1.9.4/website/content/partials/provisioners/shell-config.mdx
new file mode 100644
index 0000000..009040c
--- /dev/null
+++ b/v1.9.4/website/content/partials/provisioners/shell-config.mdx
@@ -0,0 +1,30 @@
+The reference of available configuration options is listed below. The only
+required element is either "inline" or "script". Every other option is
+optional.
+
+Exactly _one_ of the following is required:
+
+- `inline` (array of strings) - This is an array of commands to execute. The
+ commands are concatenated by newlines and turned into a single file, so
+ they are all executed within the same context. This allows you to change
+ directories in one command and use something in the directory in the next
+ and so on. Inline scripts are the easiest way to pull off simple tasks
+ within the machine.
+
+- `script` (string) - The path to a script to upload and execute in the
+ machine. This path can be absolute or relative. If it is relative, it is
+ relative to the working directory when Packer is executed.
+
+- `scripts` (array of strings) - An array of scripts to execute. The scripts
+ will be uploaded and executed in the order specified. Each script is
+ executed in isolation, so state such as variables from one script won't
+ carry on to the next.
+
+Optional parameters:
+
+- `binary` (boolean) - If true, specifies that the script(s) are binary
+ files, and Packer should therefore not convert Windows line endings to Unix
+ line endings (if there are any). By default this is false.
+
+- `valid_exit_codes` (list of ints) - Valid exit codes for the script. By
+ default this is just 0.
diff --git a/v1.9.4/website/content/partials/provisioners/unmaintained-plugin.mdx b/v1.9.4/website/content/partials/provisioners/unmaintained-plugin.mdx
new file mode 100644
index 0000000..f7ddebc
--- /dev/null
+++ b/v1.9.4/website/content/partials/provisioners/unmaintained-plugin.mdx
@@ -0,0 +1,5 @@
+~> **This community maintained provisioner is currently unmaintained**; if you
+are interested in contributing or taking ownership of it, please reach out to us
+at [packer@hashicorp.com](mailto://packer@hashicorp.com). More details can be
+found in the
+[README](https://github.com/hashicorp/packer/blob/main/README.md#unmaintained-plugins).
diff --git a/v1.9.4/website/content/plugins/index.mdx b/v1.9.4/website/content/plugins/index.mdx
new file mode 100644
index 0000000..92414fc
--- /dev/null
+++ b/v1.9.4/website/content/plugins/index.mdx
@@ -0,0 +1,13 @@
+---
+description: |
+ Plugins are installable components of Packer
+page_title: Packer plugins
+---
+
+# External Packer Plugins
+
+External Packer plugins are standalone applications that extend Packer functionality without modifying the core source code. Plugins can add new components to Packer, such as builders, provisioners, post-processors, and data sources. Refer to [Packer Plugins](/packer/docs/plugins) for details about installing and developing external plugins.
+
+This section contains the documentation for available external Packer plugins.
+
+@include "plugins/plugin-tiers-and-namespaces.mdx"
diff --git a/v1.9.4/website/content/security.mdx b/v1.9.4/website/content/security.mdx
new file mode 100644
index 0000000..887f7ff
--- /dev/null
+++ b/v1.9.4/website/content/security.mdx
@@ -0,0 +1,16 @@
+---
+page_title: Security
+description: >-
+ Packer takes security very seriously. Please responsibly disclose any security
+ vulnerabilities found and we'll handle it quickly.
+---
+
+# Packer Security
+
+We understand that many users place a high level of trust in HashiCorp and the tools we build. We apply best practices and focus on security to make sure we can maintain the trust of the community.
+
+We deeply appreciate any effort to disclose vulnerabilities responsibly.
+
+If you would like to report a vulnerability, please see the [HashiCorp security page](https://www.hashicorp.com/security), which has the proper email to communicate with as well as our PGP key. Please **do not create a GitHub issue for security concerns**.
+
+If you are not reporting a security sensitive vulnerability, please open an issue on the [Packer GitHub repository](https://github.com/hashicorp/packer).
diff --git a/v1.9.4/website/data/docs-nav-data.json b/v1.9.4/website/data/docs-nav-data.json
new file mode 100644
index 0000000..7c7e110
--- /dev/null
+++ b/v1.9.4/website/data/docs-nav-data.json
@@ -0,0 +1,901 @@
+[
+ {
+ "title": "What is Packer?",
+ "routes": [
+ {
+ "title": "Overview",
+ "path": "intro"
+ },
+ {
+ "title": "Why Use Packer?",
+ "path": "intro/why"
+ },
+ {
+ "title": "Use Cases",
+ "path": "intro/use-cases"
+ }
+ ]
+ },
+ {
+ "title": "HCP Packer",
+ "path": "hcp"
+ },
+ {
+ "divider": true
+ },
+ {
+ "title": "Terminology",
+ "path": "terminology"
+ },
+ {
+ "title": "Commands (CLI)",
+ "routes": [
+ {
+ "title": "Overview",
+ "path": "commands"
+ },
+ {
+ "title": "<code>init</code>",
+ "path": "commands/init"
+ },
+ {
+ "title": "<code>plugins</code>",
+ "routes": [
+ {
+ "title": "Overview",
+ "path": "commands/plugins"
+ },
+ {
+ "title": "<code>install</code>",
+ "path": "commands/plugins/install"
+ },
+ {
+ "title": "<code>installed</code>",
+ "path": "commands/plugins/installed"
+ },
+ {
+ "title": "<code>remove</code>",
+ "path": "commands/plugins/remove"
+ },
+ {
+ "title": "<code>required</code>",
+ "path": "commands/plugins/required"
+ }
+ ]
+ },
+ {
+ "title": "<code>build</code>",
+ "path": "commands/build"
+ },
+ {
+ "title": "<code>console</code>",
+ "path": "commands/console"
+ },
+ {
+ "title": "<code>fix</code>",
+ "path": "commands/fix"
+ },
+ {
+ "title": "<code>fmt</code>",
+ "path": "commands/fmt"
+ },
+ {
+ "title": "<code>inspect</code>",
+ "path": "commands/inspect"
+ },
+ {
+ "title": "<code>validate</code>",
+ "path": "commands/validate"
+ },
+ {
+ "title": "<code>hcl2_upgrade</code>",
+ "path": "commands/hcl2_upgrade"
+ }
+ ]
+ },
+ {
+ "title": "Templates",
+ "routes": [
+ {
+ "title": "Overview",
+ "path": "templates"
+ },
+ {
+ "title": "JSON to HCL2",
+ "path": "templates/json_to_hcl"
+ },
+ {
+ "title": "HCL Templates",
+ "routes": [
+ {
+ "title": "Overview",
+ "path": "templates/hcl_templates"
+ },
+ {
+ "title": "Blocks",
+ "routes": [
+ {
+ "title": "Overview",
+ "path": "templates/hcl_templates/blocks"
+ },
+ {
+ "title": "<code>build</code>",
+ "routes": [
+ {
+ "title": "Overview",
+ "path": "templates/hcl_templates/blocks/build"
+ },
+ {
+ "title": "<code>hcp_packer_registry</code>",
+ "path": "templates/hcl_templates/blocks/build/hcp_packer_registry"
+ },
+ {
+ "title": "<code>source</code>",
+ "path": "templates/hcl_templates/blocks/build/source"
+ },
+ {
+ "title": "<code>provisioner</code>",
+ "path": "templates/hcl_templates/blocks/build/provisioner"
+ },
+ {
+ "title": "<code>post-processor</code>",
+ "path": "templates/hcl_templates/blocks/build/post-processor"
+ },
+ {
+ "title": "<code>post-processors</code>",
+ "path": "templates/hcl_templates/blocks/build/post-processors"
+ }
+ ]
+ },
+ {
+ "title": "<code>locals</code>",
+ "path": "templates/hcl_templates/blocks/locals"
+ },
+ {
+ "title": "<code>source</code>",
+ "path": "templates/hcl_templates/blocks/source"
+ },
+ {
+ "title": "<code>variable</code>",
+ "path": "templates/hcl_templates/blocks/variable"
+ },
+ {
+ "title": "<code>packer</code>",
+ "path": "templates/hcl_templates/blocks/packer"
+ },
+ {
+ "title": "<code>data</code>",
+ "path": "templates/hcl_templates/blocks/data"
+ }
+ ]
+ },
+ {
+ "title": "Functions",
+ "routes": [
+ {
+ "title": "Overview",
+ "path": "templates/hcl_templates/functions"
+ },
+ {
+ "title": "Contextual Functions",
+ "routes": [
+ {
+ "title": "aws_secretsmanager",
+ "path": "templates/hcl_templates/functions/contextual/aws_secretsmanager"
+ },
+ {
+ "title": "consul",
+ "path": "templates/hcl_templates/functions/contextual/consul"
+ },
+ {
+ "title": "env",
+ "path": "templates/hcl_templates/functions/contextual/env"
+ },
+ {
+ "title": "vault",
+ "path": "templates/hcl_templates/functions/contextual/vault"
+ }
+ ]
+ },
+ {
+ "title": "Numeric Functions",
+ "routes": [
+ {
+ "title": "abs",
+ "path": "templates/hcl_templates/functions/numeric/abs"
+ },
+ {
+ "title": "ceil",
+ "path": "templates/hcl_templates/functions/numeric/ceil"
+ },
+ {
+ "title": "floor",
+ "path": "templates/hcl_templates/functions/numeric/floor"
+ },
+ {
+ "title": "log",
+ "path": "templates/hcl_templates/functions/numeric/log"
+ },
+ {
+ "title": "max",
+ "path": "templates/hcl_templates/functions/numeric/max"
+ },
+ {
+ "title": "min",
+ "path": "templates/hcl_templates/functions/numeric/min"
+ },
+ {
+ "title": "parseint",
+ "path": "templates/hcl_templates/functions/numeric/parseint"
+ },
+ {
+ "title": "pow",
+ "path": "templates/hcl_templates/functions/numeric/pow"
+ },
+ {
+ "title": "signum",
+ "path": "templates/hcl_templates/functions/numeric/signum"
+ }
+ ]
+ },
+ {
+ "title": "String Functions",
+ "routes": [
+ {
+ "title": "chomp",
+ "path": "templates/hcl_templates/functions/string/chomp"
+ },
+ {
+ "title": "format",
+ "path": "templates/hcl_templates/functions/string/format"
+ },
+ {
+ "title": "formatlist",
+ "path": "templates/hcl_templates/functions/string/formatlist"
+ },
+ {
+ "title": "indent",
+ "path": "templates/hcl_templates/functions/string/indent"
+ },
+ {
+ "title": "join",
+ "path": "templates/hcl_templates/functions/string/join"
+ },
+ {
+ "title": "lower",
+ "path": "templates/hcl_templates/functions/string/lower"
+ },
+ {
+ "title": "replace",
+ "path": "templates/hcl_templates/functions/string/replace"
+ },
+ {
+ "title": "regex_replace",
+ "path": "templates/hcl_templates/functions/string/regex_replace"
+ },
+ {
+ "title": "regex",
+ "path": "templates/hcl_templates/functions/string/regex"
+ },
+ {
+ "title": "regexall",
+ "path": "templates/hcl_templates/functions/string/regexall"
+ },
+ {
+ "title": "split",
+ "path": "templates/hcl_templates/functions/string/split"
+ },
+ {
+ "title": "strrev",
+ "path": "templates/hcl_templates/functions/string/strrev"
+ },
+ {
+ "title": "substr",
+ "path": "templates/hcl_templates/functions/string/substr"
+ },
+ {
+ "title": "title",
+ "path": "templates/hcl_templates/functions/string/title"
+ },
+ {
+ "title": "trim",
+ "path": "templates/hcl_templates/functions/string/trim"
+ },
+ {
+ "title": "trimprefix",
+ "path": "templates/hcl_templates/functions/string/trimprefix"
+ },
+ {
+ "title": "trimsuffix",
+ "path": "templates/hcl_templates/functions/string/trimsuffix"
+ },
+ {
+ "title": "trimspace",
+ "path": "templates/hcl_templates/functions/string/trimspace"
+ },
+ {
+ "title": "upper",
+ "path": "templates/hcl_templates/functions/string/upper"
+ }
+ ]
+ },
+ {
+ "title": "Collection Functions",
+ "routes": [
+ {
+ "title": "chunklist",
+ "path": "templates/hcl_templates/functions/collection/chunklist"
+ },
+ {
+ "title": "coalesce",
+ "path": "templates/hcl_templates/functions/collection/coalesce"
+ },
+ {
+ "title": "coalescelist",
+ "path": "templates/hcl_templates/functions/collection/coalescelist"
+ },
+ {
+ "title": "compact",
+ "path": "templates/hcl_templates/functions/collection/compact"
+ },
+ {
+ "title": "concat",
+ "path": "templates/hcl_templates/functions/collection/concat"
+ },
+ {
+ "title": "contains",
+ "path": "templates/hcl_templates/functions/collection/contains"
+ },
+ {
+ "title": "distinct",
+ "path": "templates/hcl_templates/functions/collection/distinct"
+ },
+ {
+ "title": "element",
+ "path": "templates/hcl_templates/functions/collection/element"
+ },
+ {
+ "title": "flatten",
+ "path": "templates/hcl_templates/functions/collection/flatten"
+ },
+ {
+ "title": "index",
+ "path": "templates/hcl_templates/functions/collection/index-fn"
+ },
+ {
+ "title": "keys",
+ "path": "templates/hcl_templates/functions/collection/keys"
+ },
+ {
+ "title": "length",
+ "path": "templates/hcl_templates/functions/collection/length"
+ },
+ {
+ "title": "lookup",
+ "path": "templates/hcl_templates/functions/collection/lookup"
+ },
+ {
+ "title": "merge",
+ "path": "templates/hcl_templates/functions/collection/merge"
+ },
+ {
+ "title": "range",
+ "path": "templates/hcl_templates/functions/collection/range"
+ },
+ {
+ "title": "reverse",
+ "path": "templates/hcl_templates/functions/collection/reverse"
+ },
+ {
+ "title": "setintersection",
+ "path": "templates/hcl_templates/functions/collection/setintersection"
+ },
+ {
+ "title": "setproduct",
+ "path": "templates/hcl_templates/functions/collection/setproduct"
+ },
+ {
+ "title": "setunion",
+ "path": "templates/hcl_templates/functions/collection/setunion"
+ },
+ {
+ "title": "slice",
+ "path": "templates/hcl_templates/functions/collection/slice"
+ },
+ {
+ "title": "sort",
+ "path": "templates/hcl_templates/functions/collection/sort"
+ },
+ {
+ "title": "values",
+ "path": "templates/hcl_templates/functions/collection/values"
+ },
+ {
+ "title": "zipmap",
+ "path": "templates/hcl_templates/functions/collection/zipmap"
+ }
+ ]
+ },
+ {
+ "title": "Encoding Functions",
+ "routes": [
+ {
+ "title": "base64decode",
+ "path": "templates/hcl_templates/functions/encoding/base64decode"
+ },
+ {
+ "title": "base64encode",
+ "path": "templates/hcl_templates/functions/encoding/base64encode"
+ },
+ {
+ "title": "csvdecode",
+ "path": "templates/hcl_templates/functions/encoding/csvdecode"
+ },
+ {
+ "title": "jsondecode",
+ "path": "templates/hcl_templates/functions/encoding/jsondecode"
+ },
+ {
+ "title": "jsonencode",
+ "path": "templates/hcl_templates/functions/encoding/jsonencode"
+ },
+ {
+ "title": "urlencode",
+ "path": "templates/hcl_templates/functions/encoding/urlencode"
+ },
+ {
+ "title": "yamldecode",
+ "path": "templates/hcl_templates/functions/encoding/yamldecode"
+ },
+ {
+ "title": "yamlencode",
+ "path": "templates/hcl_templates/functions/encoding/yamlencode"
+ }
+ ]
+ },
+ {
+ "title": "Filesystem Functions",
+ "routes": [
+ {
+ "title": "abspath",
+ "path": "templates/hcl_templates/functions/file/abspath"
+ },
+ {
+ "title": "basename",
+ "path": "templates/hcl_templates/functions/file/basename"
+ },
+ {
+ "title": "dirname",
+ "path": "templates/hcl_templates/functions/file/dirname"
+ },
+ {
+ "title": "file",
+ "path": "templates/hcl_templates/functions/file/file"
+ },
+ {
+ "title": "fileexists",
+ "path": "templates/hcl_templates/functions/file/fileexists"
+ },
+ {
+ "title": "fileset",
+ "path": "templates/hcl_templates/functions/file/fileset"
+ },
+ {
+ "title": "pathexpand",
+ "path": "templates/hcl_templates/functions/file/pathexpand"
+ },
+ {
+ "title": "templatefile",
+ "path": "templates/hcl_templates/functions/file/templatefile"
+ }
+ ]
+ },
+ {
+ "title": "Date and Time Functions",
+ "routes": [
+ {
+ "title": "formatdate",
+ "path": "templates/hcl_templates/functions/datetime/formatdate"
+ },
+ {
+ "title": "timeadd",
+ "path": "templates/hcl_templates/functions/datetime/timeadd"
+ },
+ {
+ "title": "timestamp",
+ "path": "templates/hcl_templates/functions/datetime/timestamp"
+ },
+ {
+ "title": "legacy_isotime",
+ "path": "templates/hcl_templates/functions/datetime/legacy_isotime"
+ },
+ {
+ "title": "legacy_strftime",
+ "path": "templates/hcl_templates/functions/datetime/legacy_strftime"
+ }
+ ]
+ },
+ {
+ "title": "Hash and Crypto Functions",
+ "routes": [
+ {
+ "title": "bcrypt",
+ "path": "templates/hcl_templates/functions/crypto/bcrypt"
+ },
+ {
+ "title": "md5",
+ "path": "templates/hcl_templates/functions/crypto/md5"
+ },
+ {
+ "title": "rsadecrypt",
+ "path": "templates/hcl_templates/functions/crypto/rsadecrypt"
+ },
+ {
+ "title": "sha1",
+ "path": "templates/hcl_templates/functions/crypto/sha1"
+ },
+ {
+ "title": "sha256",
+ "path": "templates/hcl_templates/functions/crypto/sha256"
+ },
+ {
+ "title": "sha512",
+ "path": "templates/hcl_templates/functions/crypto/sha512"
+ }
+ ]
+ },
+ {
+ "title": "UUID Functions",
+ "routes": [
+ {
+ "title": "uuidv4",
+ "path": "templates/hcl_templates/functions/uuid/uuidv4"
+ },
+ {
+ "title": "uuidv5",
+ "path": "templates/hcl_templates/functions/uuid/uuidv5"
+ }
+ ]
+ },
+ {
+ "title": "IP Network Functions",
+ "routes": [
+ {
+ "title": "cidrhost",
+ "path": "templates/hcl_templates/functions/ipnet/cidrhost"
+ },
+ {
+ "title": "cidrnetmask",
+ "path": "templates/hcl_templates/functions/ipnet/cidrnetmask"
+ },
+ {
+ "title": "cidrsubnet",
+ "path": "templates/hcl_templates/functions/ipnet/cidrsubnet"
+ },
+ {
+ "title": "cidrsubnets",
+ "path": "templates/hcl_templates/functions/ipnet/cidrsubnets"
+ }
+ ]
+ },
+ {
+ "title": "Type Conversion Functions",
+ "routes": [
+ {
+ "title": "can",
+ "path": "templates/hcl_templates/functions/conversion/can"
+ },
+ {
+ "title": "convert",
+ "path": "templates/hcl_templates/functions/conversion/convert"
+ },
+ {
+ "title": "try",
+ "path": "templates/hcl_templates/functions/conversion/try"
+ }
+ ]
+ }
+ ]
+ },
+ {
+ "title": "Variables",
+ "path": "templates/hcl_templates/variables"
+ },
+ {
+ "title": "Locals",
+ "path": "templates/hcl_templates/locals"
+ },
+ {
+ "title": "Contextual Variables",
+ "path": "templates/hcl_templates/contextual-variables"
+ },
+ {
+ "title": "Data Sources",
+ "path": "templates/hcl_templates/datasources"
+ },
+ {
+ "title": "Path Variables",
+ "path": "templates/hcl_templates/path-variables"
+ },
+ {
+ "title": "Syntax",
+ "path": "templates/hcl_templates/syntax"
+ },
+ {
+ "title": "Only Except",
+ "path": "templates/hcl_templates/onlyexcept"
+ },
+ {
+ "title": "Expressions",
+ "path": "templates/hcl_templates/expressions"
+ },
+ {
+ "title": "JSON Syntax",
+ "path": "templates/hcl_templates/syntax-json"
+ }
+ ]
+ },
+ {
+ "title": "JSON Templates",
+ "routes": [
+ {
+ "title": "Overview",
+ "path": "templates/legacy_json_templates"
+ },
+ {
+ "title": "Builders",
+ "path": "templates/legacy_json_templates/builders"
+ },
+ {
+ "title": "Communicators",
+ "path": "templates/legacy_json_templates/communicator"
+ },
+ {
+ "title": "Engine",
+ "path": "templates/legacy_json_templates/engine"
+ },
+ {
+ "title": "Post-Processors",
+ "path": "templates/legacy_json_templates/post-processors"
+ },
+ {
+ "title": "Provisioners",
+ "path": "templates/legacy_json_templates/provisioners"
+ },
+ {
+ "title": "User Variables",
+ "path": "templates/legacy_json_templates/user-variables"
+ }
+ ]
+ }
+ ]
+ },
+ {
+ "divider": true
+ },
+ {
+ "title": "Communicators",
+ "routes": [
+ {
+ "title": "Overview",
+ "path": "communicators"
+ },
+ {
+ "title": "SSH",
+ "path": "communicators/ssh"
+ },
+ {
+ "title": "WINRM",
+ "path": "communicators/winrm"
+ }
+ ]
+ },
+ {
+ "title": "Builders",
+ "routes": [
+ {
+ "title": "Overview",
+ "path": "builders"
+ },
+ {
+ "title": "File",
+ "path": "builders/file"
+ },
+ {
+ "title": "Null",
+ "path": "builders/null"
+ },
+ {
+ "title": "Custom",
+ "path": "builders/custom"
+ },
+ {
+ "title": "Community-Supported",
+ "path": "builders/community-supported"
+ }
+ ]
+ },
+ {
+ "title": "Data Sources",
+ "routes": [
+ {
+ "title": "Overview",
+ "path": "datasources"
+ },
+ {
+ "title": "HCP Packer",
+ "routes": [
+ {
+ "title": "Overview",
+ "path": "datasources/hcp"
+ },
+ {
+ "title": "Iteration",
+ "path": "datasources/hcp/hcp-packer-iteration"
+ },
+ {
+ "title": "Image",
+ "path": "datasources/hcp/hcp-packer-image"
+ }
+ ]
+ },
+ {
+ "title": "HTTP",
+ "path": "datasources/http"
+ }
+ ]
+ },
+ {
+ "title": "Provisioners",
+ "routes": [
+ {
+ "title": "Overview",
+ "path": "provisioners"
+ },
+ {
+ "title": "Breakpoint",
+ "path": "provisioners/breakpoint"
+ },
+ {
+ "title": "File",
+ "path": "provisioners/file"
+ },
+ {
+ "title": "PowerShell",
+ "path": "provisioners/powershell"
+ },
+ {
+ "title": "Shell",
+ "path": "provisioners/shell"
+ },
+ {
+ "title": "Shell (Local)",
+ "path": "provisioners/shell-local"
+ },
+ {
+ "title": "Windows Shell",
+ "path": "provisioners/windows-shell"
+ },
+ {
+ "title": "Windows Restart",
+ "path": "provisioners/windows-restart"
+ },
+ {
+ "title": "Custom",
+ "path": "provisioners/custom"
+ },
+ {
+ "title": "Community-Supported",
+ "path": "provisioners/community-supported"
+ }
+ ]
+ },
+ {
+ "title": "Post-Processors",
+ "routes": [
+ {
+ "title": "Overview",
+ "path": "post-processors"
+ },
+ {
+ "title": "Artifice",
+ "path": "post-processors/artifice"
+ },
+ {
+ "title": "Compress",
+ "path": "post-processors/compress"
+ },
+ {
+ "title": "Checksum",
+ "path": "post-processors/checksum"
+ },
+ {
+ "title": "Manifest",
+ "path": "post-processors/manifest"
+ },
+ {
+ "title": "Shell (Local)",
+ "path": "post-processors/shell-local"
+ },
+ {
+ "title": "Community-Supported",
+ "path": "post-processors/community-supported"
+ }
+ ]
+ },
+ {
+ "divider": true
+ },
+ {
+ "title": "Installing Packer",
+ "path": "install"
+ },
+ {
+ "title": "Configuring Packer",
+ "path": "configure"
+ },
+ {
+ "divider": true
+ },
+ {
+ "title": "Plugins",
+ "routes": [
+ {
+ "title": "Overview",
+ "path": "plugins"
+ },
+ {
+ "title": "Installing Plugins",
+ "path": "plugins/install-plugins"
+ },
+ {
+ "title": "External Plugins",
+ "href": "/plugins"
+ },
+ {
+ "title": "Developing Plugins",
+ "routes": [
+ {
+ "title": "Overview",
+ "path": "plugins/creation"
+ },
+ {
+ "title": "Custom Builders",
+ "path": "plugins/creation/custom-builders"
+ },
+ {
+ "title": "Custom Post-Processors",
+ "path": "plugins/creation/custom-post-processors"
+ },
+ {
+ "title": "Custom Provisioners",
+ "path": "plugins/creation/custom-provisioners"
+ },
+ {
+ "title": "Custom Data Sources",
+ "path": "plugins/creation/custom-datasources"
+ },
+ {
+ "title": "HCP Packer Support",
+ "path": "plugins/creation/hcp-support"
+ }
+ ]
+ }
+ ]
+ },
+ {
+ "title": "Integration Program",
+ "path": "partnerships"
+ },
+ {
+ "title": "Community Tools",
+ "path": "community-tools"
+ },
+ {
+ "divider": true
+ },
+ {
+ "title": "Debugging",
+ "path": "debugging"
+ }
+]
diff --git a/v1.9.4/website/data/guides-nav-data.json b/v1.9.4/website/data/guides-nav-data.json
new file mode 100644
index 0000000..b063116
--- /dev/null
+++ b/v1.9.4/website/data/guides-nav-data.json
@@ -0,0 +1,77 @@
+[
+ {
+ "title": "Upgrade Your Plugin to use the Packer plugin sdk",
+ "path": "1.7-plugin-upgrade"
+ },
+ {
+ "title": "Upgrade Your Template to use Packer init",
+ "path": "1.7-template-upgrade"
+ },
+ {
+ "title": "HCL guides",
+ "routes": [
+ {
+ "title": "Overview",
+ "path": "hcl"
+ },
+ {
+ "title": "Variables",
+ "path": "hcl/variables"
+ },
+ {
+ "title": "Upgrade Packer JSON Template to HCL2",
+ "href": "https://learn.hashicorp.com/tutorials/packer/hcl2-upgrade"
+ },
+ {
+ "title": "Making a plugin HCL2 enabled",
+ "path": "hcl/component-object-spec"
+ }
+ ]
+ },
+ {
+ "title": "Automatic OS Installs",
+ "routes": [
+ {
+ "title": "Overview",
+ "path": "automatic-operating-system-installs"
+ },
+ {
+ "title": "Unattended Installation for Windows",
+ "path": "automatic-operating-system-installs/autounattend_windows"
+ },
+ {
+ "title": "Unattended Installation for Debian",
+ "path": "automatic-operating-system-installs/preseed_ubuntu"
+ }
+ ]
+ },
+ {
+ "title": "Build Immutable Infrastructure with Packer in CI/CD",
+ "routes": [
+ {
+ "title": "Overview",
+ "path": "packer-on-cicd"
+ },
+ {
+ "title": "Build Images in CI/CD",
+ "path": "packer-on-cicd/build-image-in-cicd"
+ },
+ {
+ "title": "Build a VirtualBox Image with Packer in TeamCity",
+ "path": "packer-on-cicd/build-virtualbox-image"
+ },
+ {
+ "title": "Pipelineing Builds",
+ "path": "packer-on-cicd/pipelineing-builds"
+ },
+ {
+ "title": "Trigger Terraform Enterprise runs",
+ "path": "packer-on-cicd/trigger-tfe"
+ },
+ {
+ "title": "Upload a VirtualBox Image to S3",
+ "path": "packer-on-cicd/upload-images-to-artifact"
+ }
+ ]
+ }
+]
diff --git a/v1.9.4/website/data/plugins-manifest.json b/v1.9.4/website/data/plugins-manifest.json
new file mode 100644
index 0000000..675c8e7
--- /dev/null
+++ b/v1.9.4/website/data/plugins-manifest.json
@@ -0,0 +1,377 @@
+[
+ {
+ "title": "1&1",
+ "path": "oneandone",
+ "repo": "hashicorp/packer-plugin-oneandone",
+ "pluginTier": "community",
+ "version": "latest"
+ },
+ {
+ "title": "Alibaba Cloud",
+ "path": "alicloud",
+ "repo": "hashicorp/packer-plugin-alicloud",
+ "pluginTier": "community",
+ "version": "latest"
+ },
+ {
+ "title": "Anka",
+ "path": "anka",
+ "repo": "veertuinc/packer-plugin-veertu-anka",
+ "pluginTier": "community",
+ "sourceBranch": "master",
+ "version": "latest"
+ },
+ {
+ "title": "Ansible",
+ "path": "ansible",
+ "repo": "hashicorp/packer-plugin-ansible",
+ "version": "latest"
+ },
+ {
+ "title": "Amazon EC2",
+ "path": "amazon",
+ "repo": "hashicorp/packer-plugin-amazon",
+ "version": "latest",
+ "isHcpPackerReady": true
+ },
+ {
+ "title": "Azure",
+ "path": "azure",
+ "repo": "hashicorp/packer-plugin-azure",
+ "version": "latest",
+ "isHcpPackerReady": true
+ },
+ {
+ "title": "Chef",
+ "path": "chef",
+ "repo": "hashicorp/packer-plugin-chef",
+ "pluginTier": "community",
+ "version": "latest",
+ "archived": true
+ },
+ {
+ "title": "CloudStack",
+ "path": "cloudstack",
+ "repo": "hashicorp/packer-plugin-cloudstack",
+ "pluginTier": "community",
+ "version": "latest"
+ },
+ {
+ "title": "Converge",
+ "path": "converge",
+ "repo": "hashicorp/packer-plugin-converge",
+ "pluginTier": "community",
+ "version": "latest",
+ "archived": true
+ },
+ {
+ "title": "DigitalOcean",
+ "path": "digitalocean",
+ "repo": "digitalocean/packer-plugin-digitalocean",
+ "pluginTier": "verified",
+ "version": "latest",
+ "isHcpPackerReady": true
+ },
+ {
+ "title": "Docker",
+ "path": "docker",
+ "repo": "hashicorp/packer-plugin-docker",
+ "version": "latest",
+ "isHcpPackerReady": true
+ },
+ {
+ "title": "External",
+ "path": "external",
+ "repo": "joomcode/packer-plugin-external",
+ "version": "latest",
+ "sourceBranch": "main"
+ },
+ {
+ "title": "Git",
+ "path": "git",
+ "repo": "ethanmdavidson/packer-plugin-git",
+ "version": "latest",
+ "sourceBranch": "main"
+ },
+ {
+ "title": "Google Cloud Platform",
+ "path": "googlecompute",
+ "repo": "hashicorp/packer-plugin-googlecompute",
+ "version": "latest",
+ "isHcpPackerReady": true
+ },
+ {
+ "title": "Gridscale",
+ "path": "gridscale",
+ "repo": "gridscale/packer-plugin-gridscale",
+ "version": "latest",
+ "pluginTier": "verified",
+ "isHcpPackerReady": false
+ },
+ {
+ "title": "HashiCups",
+ "path": "hashicups",
+ "repo": "hashicorp/packer-plugin-hashicups",
+ "version": "latest",
+ "isHcpPackerReady": false
+ },
+ {
+ "title": "Hetzner Cloud",
+ "path": "hetzner-cloud",
+ "repo": "hashicorp/packer-plugin-hcloud",
+ "version": "latest",
+ "pluginTier": "community"
+ },
+ {
+ "title": "HyperOne",
+ "path": "hyperone",
+ "repo": "hashicorp/packer-plugin-hyperone",
+ "version": "latest",
+ "pluginTier": "community"
+ },
+ {
+ "title": "Hyper-V",
+ "path": "hyperv",
+ "repo": "hashicorp/packer-plugin-hyperv",
+ "version": "latest",
+ "pluginTier": "community"
+ },
+ {
+ "title": "InSpec",
+ "path": "inspec",
+ "repo": "hashicorp/packer-plugin-inspec",
+ "pluginTier": "community",
+ "version": "latest",
+ "archived": true
+ },
+ {
+ "title": "JD Cloud",
+ "path": "jdcloud",
+ "repo": "hashicorp/packer-plugin-jdcloud",
+ "pluginTier": "community",
+ "version": "latest"
+ },
+ {
+ "title": "Kamatera",
+ "path": "kamatera",
+ "repo": "kamatera/packer-plugin-kamatera",
+ "pluginTier": "community",
+ "version": "latest"
+ },
+ {
+ "title": "Linode",
+ "path": "linode",
+ "repo": "linode/packer-plugin-linode",
+ "pluginTier": "verified",
+ "version": "latest",
+ "isHcpPackerReady": true
+ },
+ {
+ "title": "Libvirt",
+ "path": "libvirt",
+ "repo": "thomasklein94/packer-plugin-libvirt",
+ "pluginTier": "community",
+ "version": "latest"
+ },
+ {
+ "title": "LXC",
+ "path": "lxc",
+ "repo": "hashicorp/packer-plugin-lxc",
+ "pluginTier": "community",
+ "version": "latest"
+ },
+ {
+ "title": "LXD",
+ "path": "lxd",
+ "repo": "hashicorp/packer-plugin-lxd",
+ "pluginTier": "community",
+ "version": "latest"
+ },
+ {
+ "title": "Mondoo",
+ "path": "mondoo",
+ "repo": "mondoohq/packer-plugin-mondoo",
+ "pluginTier": "verified",
+ "version": "latest"
+ },
+ {
+ "title": "Naver Cloud",
+ "path": "ncloud",
+ "repo": "hashicorp/packer-plugin-ncloud",
+ "pluginTier": "community",
+ "version": "latest"
+ },
+ {
+ "title": "Nutanix",
+ "path": "nutanix",
+ "repo": "nutanix-cloud-native/packer-plugin-nutanix",
+ "version": "latest",
+ "pluginTier": "verified",
+ "sourceBranch": "main"
+ },
+ {
+ "title": "OpenStack",
+ "path": "openstack",
+ "repo": "hashicorp/packer-plugin-openstack",
+ "pluginTier": "community",
+ "version": "latest"
+ },
+ {
+ "title": "Oracle",
+ "path": "oracle",
+ "repo": "hashicorp/packer-plugin-oracle",
+ "pluginTier": "community",
+ "version": "latest",
+ "isHcpPackerReady": true
+ },
+ {
+ "title": "Outscale",
+ "path": "outscale",
+ "repo": "outscale/packer-plugin-outscale",
+ "version": "latest",
+ "pluginTier": "verified",
+ "isHcpPackerReady": true
+ },
+ {
+ "title": "Parallels",
+ "path": "parallels",
+ "repo": "parallels/packer-plugin-parallels",
+ "version": "latest",
+ "pluginTier": "verified"
+ },
+ {
+ "title": "Profitbricks",
+ "path": "profitbricks",
+ "repo": "hashicorp/packer-plugin-profitbricks",
+ "pluginTier": "community",
+ "version": "latest"
+ },
+ {
+ "title": "Proxmox",
+ "path": "proxmox",
+ "repo": "hashicorp/packer-plugin-proxmox",
+ "pluginTier": "community",
+ "version": "latest"
+ },
+ {
+ "title": "Puppet",
+ "path": "puppet",
+ "repo": "hashicorp/packer-plugin-puppet",
+ "version": "latest",
+ "pluginTier": "community",
+ "archived": true
+ },
+ {
+ "title": "QEMU",
+ "path": "qemu",
+ "repo": "hashicorp/packer-plugin-qemu",
+ "version": "latest"
+ },
+ {
+ "title": "Salt",
+ "path": "salt",
+ "repo": "hashicorp/packer-plugin-salt",
+ "pluginTier": "community",
+ "version": "latest",
+ "archived": true
+ },
+ {
+ "title": "Scaleway",
+ "path": "scaleway",
+ "repo": "scaleway/packer-plugin-scaleway",
+ "pluginTier": "verified",
+ "version": "latest"
+ },
+ {
+ "title": "SSH Key",
+ "path": "sshkey",
+ "repo": "ivoronin/packer-plugin-sshkey",
+ "pluginTier": "community",
+ "version": "v1.0.1"
+ },
+ {
+ "title": "Tart",
+ "path": "tart",
+ "repo": "cirruslabs/packer-plugin-tart",
+ "pluginTier": "community",
+ "version": "latest"
+ },
+ {
+ "title": "Tencent Cloud",
+ "path": "tencentcloud",
+ "repo": "hashicorp/packer-plugin-tencentcloud",
+ "pluginTier": "community",
+ "version": "latest"
+ },
+ {
+ "title": "Triton",
+ "path": "triton",
+ "repo": "hashicorp/packer-plugin-triton",
+ "pluginTier": "community",
+ "version": "latest"
+ },
+ {
+ "title": "UCloud",
+ "path": "ucloud",
+ "repo": "ucloud/packer-plugin-ucloud",
+ "version": "latest",
+ "pluginTier": "community"
+ },
+ {
+ "title": "UpCloud",
+ "path": "upcloud",
+ "repo": "UpCloudLtd/packer-plugin-upcloud",
+ "version": "latest",
+ "pluginTier": "verified",
+ "sourceBranch": "master",
+ "isHcpPackerReady": true
+ },
+ {
+ "title": "Vagrant",
+ "path": "vagrant",
+ "repo": "hashicorp/packer-plugin-vagrant",
+ "pluginTier": "official",
+ "version": "latest"
+ },
+ {
+ "title": "VirtualBox",
+ "path": "virtualbox",
+ "repo": "hashicorp/packer-plugin-virtualbox",
+ "pluginTier": "official",
+ "version": "latest"
+ },
+ {
+ "title": "Volcengine",
+ "path": "volcengine",
+ "repo": "volcengine/packer-plugin-volcengine",
+ "pluginTier": "community",
+ "version": "latest"
+ },
+ {
+ "title": "VMware vSphere",
+ "path": "vsphere",
+ "repo": "hashicorp/packer-plugin-vsphere",
+ "version": "latest",
+ "isHcpPackerReady": true
+ },
+ {
+ "title": "VMware",
+ "path": "vmware",
+ "repo": "hashicorp/packer-plugin-vmware",
+ "version": "latest"
+ },
+ {
+ "title": "Vultr",
+ "path": "vultr",
+ "repo": "vultr/packer-plugin-vultr",
+ "pluginTier": "community",
+ "version": "latest"
+ },
+ {
+ "title": "Yandex",
+ "path": "yandex",
+ "repo": "hashicorp/packer-plugin-yandex",
+ "version": "latest",
+ "pluginTier": "community"
+ }
+]
diff --git a/v1.9.4/website/data/plugins-nav-data.json b/v1.9.4/website/data/plugins-nav-data.json
new file mode 100644
index 0000000..e82e0e2
--- /dev/null
+++ b/v1.9.4/website/data/plugins-nav-data.json
@@ -0,0 +1,10 @@
+[
+ { "heading": "External Plugins" },
+ {
+ "title": "Overview",
+ "path": ""
+ },
+ {
+ "divider": true
+ }
+]
diff --git a/v1.9.4/website/package-lock.json b/v1.9.4/website/package-lock.json
new file mode 100644
index 0000000..09bd084
--- /dev/null
+++ b/v1.9.4/website/package-lock.json
@@ -0,0 +1,24572 @@
+{
+ "name": "packer-docs",
+ "version": "1.0.0",
+ "lockfileVersion": 2,
+ "requires": true,
+ "packages": {
+ "": {
+ "name": "packer-docs",
+ "version": "1.0.0",
+ "devDependencies": {
+ "@hashicorp/platform-cli": "^2.6.0",
+ "@hashicorp/platform-content-conformance": "^0.0.10",
+ "dart-linkcheck": "2.0.15",
+ "husky": "4.3.8",
+ "next": "^12.3.1",
+ "prettier": "2.2.1"
+ },
+ "engines": {
+ "npm": ">=7.0.0"
+ }
+ },
+ "node_modules/@ampproject/remapping": {
+ "version": "2.1.2",
+ "resolved": "https://registry.npmjs.org/@ampproject/remapping/-/remapping-2.1.2.tgz",
+ "integrity": "sha512-hoyByceqwKirw7w3Z7gnIIZC3Wx3J484Y3L/cMpXFbr7d9ZQj2mODrirNzcJa+SM3UlpWXYvKV4RlRpFXlWgXg==",
+ "dev": true,
+ "dependencies": {
+ "@jridgewell/trace-mapping": "^0.3.0"
+ },
+ "engines": {
+ "node": ">=6.0.0"
+ }
+ },
+ "node_modules/@babel/code-frame": {
+ "version": "7.16.7",
+ "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.16.7.tgz",
+ "integrity": "sha512-iAXqUn8IIeBTNd72xsFlgaXHkMBMt6y4HJp1tIaK465CWLT/fG1aqB7ykr95gHHmlBdGbFeWWfyB4NJJ0nmeIg==",
+ "dev": true,
+ "dependencies": {
+ "@babel/highlight": "^7.16.7"
+ },
+ "engines": {
+ "node": ">=6.9.0"
+ }
+ },
+ "node_modules/@babel/compat-data": {
+ "version": "7.17.7",
+ "resolved": "https://registry.npmjs.org/@babel/compat-data/-/compat-data-7.17.7.tgz",
+ "integrity": "sha512-p8pdE6j0a29TNGebNm7NzYZWB3xVZJBZ7XGs42uAKzQo8VQ3F0By/cQCtUEABwIqw5zo6WA4NbmxsfzADzMKnQ==",
+ "dev": true,
+ "engines": {
+ "node": ">=6.9.0"
+ }
+ },
+ "node_modules/@babel/core": {
+ "version": "7.17.9",
+ "resolved": "https://registry.npmjs.org/@babel/core/-/core-7.17.9.tgz",
+ "integrity": "sha512-5ug+SfZCpDAkVp9SFIZAzlW18rlzsOcJGaetCjkySnrXXDUw9AR8cDUm1iByTmdWM6yxX6/zycaV76w3YTF2gw==",
+ "dev": true,
+ "dependencies": {
+ "@ampproject/remapping": "^2.1.0",
+ "@babel/code-frame": "^7.16.7",
+ "@babel/generator": "^7.17.9",
+ "@babel/helper-compilation-targets": "^7.17.7",
+ "@babel/helper-module-transforms": "^7.17.7",
+ "@babel/helpers": "^7.17.9",
+ "@babel/parser": "^7.17.9",
+ "@babel/template": "^7.16.7",
+ "@babel/traverse": "^7.17.9",
+ "@babel/types": "^7.17.0",
+ "convert-source-map": "^1.7.0",
+ "debug": "^4.1.0",
+ "gensync": "^1.0.0-beta.2",
+ "json5": "^2.2.1",
+ "semver": "^6.3.0"
+ },
+ "engines": {
+ "node": ">=6.9.0"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/babel"
+ }
+ },
+ "node_modules/@babel/core/node_modules/semver": {
+ "version": "6.3.0",
+ "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz",
+ "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==",
+ "dev": true,
+ "bin": {
+ "semver": "bin/semver.js"
+ }
+ },
+ "node_modules/@babel/generator": {
+ "version": "7.17.9",
+ "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.17.9.tgz",
+ "integrity": "sha512-rAdDousTwxbIxbz5I7GEQ3lUip+xVCXooZNbsydCWs3xA7ZsYOv+CFRdzGxRX78BmQHu9B1Eso59AOZQOJDEdQ==",
+ "dev": true,
+ "dependencies": {
+ "@babel/types": "^7.17.0",
+ "jsesc": "^2.5.1",
+ "source-map": "^0.5.0"
+ },
+ "engines": {
+ "node": ">=6.9.0"
+ }
+ },
+ "node_modules/@babel/generator/node_modules/source-map": {
+ "version": "0.5.7",
+ "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz",
+ "integrity": "sha1-igOdLRAh0i0eoUyA2OpGi6LvP8w=",
+ "dev": true,
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
+ "node_modules/@babel/helper-compilation-targets": {
+ "version": "7.17.7",
+ "resolved": "https://registry.npmjs.org/@babel/helper-compilation-targets/-/helper-compilation-targets-7.17.7.tgz",
+ "integrity": "sha512-UFzlz2jjd8kroj0hmCFV5zr+tQPi1dpC2cRsDV/3IEW8bJfCPrPpmcSN6ZS8RqIq4LXcmpipCQFPddyFA5Yc7w==",
+ "dev": true,
+ "dependencies": {
+ "@babel/compat-data": "^7.17.7",
+ "@babel/helper-validator-option": "^7.16.7",
+ "browserslist": "^4.17.5",
+ "semver": "^6.3.0"
+ },
+ "engines": {
+ "node": ">=6.9.0"
+ },
+ "peerDependencies": {
+ "@babel/core": "^7.0.0"
+ }
+ },
+ "node_modules/@babel/helper-compilation-targets/node_modules/semver": {
+ "version": "6.3.0",
+ "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz",
+ "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==",
+ "dev": true,
+ "bin": {
+ "semver": "bin/semver.js"
+ }
+ },
+ "node_modules/@babel/helper-environment-visitor": {
+ "version": "7.16.7",
+ "resolved": "https://registry.npmjs.org/@babel/helper-environment-visitor/-/helper-environment-visitor-7.16.7.tgz",
+ "integrity": "sha512-SLLb0AAn6PkUeAfKJCCOl9e1R53pQlGAfc4y4XuMRZfqeMYLE0dM1LMhqbGAlGQY0lfw5/ohoYWAe9V1yibRag==",
+ "dev": true,
+ "dependencies": {
+ "@babel/types": "^7.16.7"
+ },
+ "engines": {
+ "node": ">=6.9.0"
+ }
+ },
+ "node_modules/@babel/helper-function-name": {
+ "version": "7.17.9",
+ "resolved": "https://registry.npmjs.org/@babel/helper-function-name/-/helper-function-name-7.17.9.tgz",
+ "integrity": "sha512-7cRisGlVtiVqZ0MW0/yFB4atgpGLWEHUVYnb448hZK4x+vih0YO5UoS11XIYtZYqHd0dIPMdUSv8q5K4LdMnIg==",
+ "dev": true,
+ "dependencies": {
+ "@babel/template": "^7.16.7",
+ "@babel/types": "^7.17.0"
+ },
+ "engines": {
+ "node": ">=6.9.0"
+ }
+ },
+ "node_modules/@babel/helper-hoist-variables": {
+ "version": "7.16.7",
+ "resolved": "https://registry.npmjs.org/@babel/helper-hoist-variables/-/helper-hoist-variables-7.16.7.tgz",
+ "integrity": "sha512-m04d/0Op34H5v7pbZw6pSKP7weA6lsMvfiIAMeIvkY/R4xQtBSMFEigu9QTZ2qB/9l22vsxtM8a+Q8CzD255fg==",
+ "dev": true,
+ "dependencies": {
+ "@babel/types": "^7.16.7"
+ },
+ "engines": {
+ "node": ">=6.9.0"
+ }
+ },
+ "node_modules/@babel/helper-module-imports": {
+ "version": "7.16.7",
+ "resolved": "https://registry.npmjs.org/@babel/helper-module-imports/-/helper-module-imports-7.16.7.tgz",
+ "integrity": "sha512-LVtS6TqjJHFc+nYeITRo6VLXve70xmq7wPhWTqDJusJEgGmkAACWwMiTNrvfoQo6hEhFwAIixNkvB0jPXDL8Wg==",
+ "dev": true,
+ "dependencies": {
+ "@babel/types": "^7.16.7"
+ },
+ "engines": {
+ "node": ">=6.9.0"
+ }
+ },
+ "node_modules/@babel/helper-module-transforms": {
+ "version": "7.17.7",
+ "resolved": "https://registry.npmjs.org/@babel/helper-module-transforms/-/helper-module-transforms-7.17.7.tgz",
+ "integrity": "sha512-VmZD99F3gNTYB7fJRDTi+u6l/zxY0BE6OIxPSU7a50s6ZUQkHwSDmV92FfM+oCG0pZRVojGYhkR8I0OGeCVREw==",
+ "dev": true,
+ "dependencies": {
+ "@babel/helper-environment-visitor": "^7.16.7",
+ "@babel/helper-module-imports": "^7.16.7",
+ "@babel/helper-simple-access": "^7.17.7",
+ "@babel/helper-split-export-declaration": "^7.16.7",
+ "@babel/helper-validator-identifier": "^7.16.7",
+ "@babel/template": "^7.16.7",
+ "@babel/traverse": "^7.17.3",
+ "@babel/types": "^7.17.0"
+ },
+ "engines": {
+ "node": ">=6.9.0"
+ }
+ },
+ "node_modules/@babel/helper-plugin-utils": {
+ "version": "7.20.2",
+ "resolved": "https://registry.npmjs.org/@babel/helper-plugin-utils/-/helper-plugin-utils-7.20.2.tgz",
+ "integrity": "sha512-8RvlJG2mj4huQ4pZ+rU9lqKi9ZKiRmuvGuM2HlWmkmgOhbs6zEAw6IEiJ5cQqGbDzGZOhwuOQNtZMi/ENLjZoQ==",
+ "dev": true,
+ "engines": {
+ "node": ">=6.9.0"
+ }
+ },
+ "node_modules/@babel/helper-simple-access": {
+ "version": "7.17.7",
+ "resolved": "https://registry.npmjs.org/@babel/helper-simple-access/-/helper-simple-access-7.17.7.tgz",
+ "integrity": "sha512-txyMCGroZ96i+Pxr3Je3lzEJjqwaRC9buMUgtomcrLe5Nd0+fk1h0LLA+ixUF5OW7AhHuQ7Es1WcQJZmZsz2XA==",
+ "dev": true,
+ "dependencies": {
+ "@babel/types": "^7.17.0"
+ },
+ "engines": {
+ "node": ">=6.9.0"
+ }
+ },
+ "node_modules/@babel/helper-split-export-declaration": {
+ "version": "7.16.7",
+ "resolved": "https://registry.npmjs.org/@babel/helper-split-export-declaration/-/helper-split-export-declaration-7.16.7.tgz",
+ "integrity": "sha512-xbWoy/PFoxSWazIToT9Sif+jJTlrMcndIsaOKvTA6u7QEo7ilkRZpjew18/W3c7nm8fXdUDXh02VXTbZ0pGDNw==",
+ "dev": true,
+ "dependencies": {
+ "@babel/types": "^7.16.7"
+ },
+ "engines": {
+ "node": ">=6.9.0"
+ }
+ },
+ "node_modules/@babel/helper-validator-identifier": {
+ "version": "7.16.7",
+ "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.16.7.tgz",
+ "integrity": "sha512-hsEnFemeiW4D08A5gUAZxLBTXpZ39P+a+DGDsHw1yxqyQ/jzFEnxf5uTEGp+3bzAbNOxU1paTgYS4ECU/IgfDw==",
+ "dev": true,
+ "engines": {
+ "node": ">=6.9.0"
+ }
+ },
+ "node_modules/@babel/helper-validator-option": {
+ "version": "7.16.7",
+ "resolved": "https://registry.npmjs.org/@babel/helper-validator-option/-/helper-validator-option-7.16.7.tgz",
+ "integrity": "sha512-TRtenOuRUVo9oIQGPC5G9DgK4743cdxvtOw0weQNpZXaS16SCBi5MNjZF8vba3ETURjZpTbVn7Vvcf2eAwFozQ==",
+ "dev": true,
+ "engines": {
+ "node": ">=6.9.0"
+ }
+ },
+ "node_modules/@babel/helpers": {
+ "version": "7.17.9",
+ "resolved": "https://registry.npmjs.org/@babel/helpers/-/helpers-7.17.9.tgz",
+ "integrity": "sha512-cPCt915ShDWUEzEp3+UNRktO2n6v49l5RSnG9M5pS24hA+2FAc5si+Pn1i4VVbQQ+jh+bIZhPFQOJOzbrOYY1Q==",
+ "dev": true,
+ "dependencies": {
+ "@babel/template": "^7.16.7",
+ "@babel/traverse": "^7.17.9",
+ "@babel/types": "^7.17.0"
+ },
+ "engines": {
+ "node": ">=6.9.0"
+ }
+ },
+ "node_modules/@babel/highlight": {
+ "version": "7.17.9",
+ "resolved": "https://registry.npmjs.org/@babel/highlight/-/highlight-7.17.9.tgz",
+ "integrity": "sha512-J9PfEKCbFIv2X5bjTMiZu6Vf341N05QIY+d6FvVKynkG1S7G0j3I0QoRtWIrXhZ+/Nlb5Q0MzqL7TokEJ5BNHg==",
+ "dev": true,
+ "dependencies": {
+ "@babel/helper-validator-identifier": "^7.16.7",
+ "chalk": "^2.0.0",
+ "js-tokens": "^4.0.0"
+ },
+ "engines": {
+ "node": ">=6.9.0"
+ }
+ },
+ "node_modules/@babel/highlight/node_modules/ansi-styles": {
+ "version": "3.2.1",
+ "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz",
+ "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==",
+ "dev": true,
+ "dependencies": {
+ "color-convert": "^1.9.0"
+ },
+ "engines": {
+ "node": ">=4"
+ }
+ },
+ "node_modules/@babel/highlight/node_modules/chalk": {
+ "version": "2.4.2",
+ "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz",
+ "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==",
+ "dev": true,
+ "dependencies": {
+ "ansi-styles": "^3.2.1",
+ "escape-string-regexp": "^1.0.5",
+ "supports-color": "^5.3.0"
+ },
+ "engines": {
+ "node": ">=4"
+ }
+ },
+ "node_modules/@babel/highlight/node_modules/color-convert": {
+ "version": "1.9.3",
+ "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz",
+ "integrity": "sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==",
+ "dev": true,
+ "dependencies": {
+ "color-name": "1.1.3"
+ }
+ },
+ "node_modules/@babel/highlight/node_modules/color-name": {
+ "version": "1.1.3",
+ "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz",
+ "integrity": "sha1-p9BVi9icQveV3UIyj3QIMcpTvCU=",
+ "dev": true
+ },
+ "node_modules/@babel/highlight/node_modules/has-flag": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz",
+ "integrity": "sha1-tdRU3CGZriJWmfNGfloH87lVuv0=",
+ "dev": true,
+ "engines": {
+ "node": ">=4"
+ }
+ },
+ "node_modules/@babel/highlight/node_modules/supports-color": {
+ "version": "5.5.0",
+ "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz",
+ "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==",
+ "dev": true,
+ "dependencies": {
+ "has-flag": "^3.0.0"
+ },
+ "engines": {
+ "node": ">=4"
+ }
+ },
+ "node_modules/@babel/parser": {
+ "version": "7.17.9",
+ "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.17.9.tgz",
+ "integrity": "sha512-vqUSBLP8dQHFPdPi9bc5GK9vRkYHJ49fsZdtoJ8EQ8ibpwk5rPKfvNIwChB0KVXcIjcepEBBd2VHC5r9Gy8ueg==",
+ "dev": true,
+ "bin": {
+ "parser": "bin/babel-parser.js"
+ },
+ "engines": {
+ "node": ">=6.0.0"
+ }
+ },
+ "node_modules/@babel/plugin-proposal-object-rest-spread": {
+ "version": "7.12.1",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-object-rest-spread/-/plugin-proposal-object-rest-spread-7.12.1.tgz",
+ "integrity": "sha512-s6SowJIjzlhx8o7lsFx5zmY4At6CTtDvgNQDdPzkBQucle58A6b/TTeEBYtyDgmcXjUTM+vE8YOGHZzzbc/ioA==",
+ "dev": true,
+ "dependencies": {
+ "@babel/helper-plugin-utils": "^7.10.4",
+ "@babel/plugin-syntax-object-rest-spread": "^7.8.0",
+ "@babel/plugin-transform-parameters": "^7.12.1"
+ },
+ "peerDependencies": {
+ "@babel/core": "^7.0.0-0"
+ }
+ },
+ "node_modules/@babel/plugin-syntax-async-generators": {
+ "version": "7.8.4",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-async-generators/-/plugin-syntax-async-generators-7.8.4.tgz",
+ "integrity": "sha512-tycmZxkGfZaxhMRbXlPXuVFpdWlXpir2W4AMhSJgRKzk/eDlIXOhb2LHWoLpDF7TEHylV5zNhykX6KAgHJmTNw==",
+ "dev": true,
+ "peer": true,
+ "dependencies": {
+ "@babel/helper-plugin-utils": "^7.8.0"
+ },
+ "peerDependencies": {
+ "@babel/core": "^7.0.0-0"
+ }
+ },
+ "node_modules/@babel/plugin-syntax-bigint": {
+ "version": "7.8.3",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-bigint/-/plugin-syntax-bigint-7.8.3.tgz",
+ "integrity": "sha512-wnTnFlG+YxQm3vDxpGE57Pj0srRU4sHE/mDkt1qv2YJJSeUAec2ma4WLUnUPeKjyrfntVwe/N6dCXpU+zL3Npg==",
+ "dev": true,
+ "peer": true,
+ "dependencies": {
+ "@babel/helper-plugin-utils": "^7.8.0"
+ },
+ "peerDependencies": {
+ "@babel/core": "^7.0.0-0"
+ }
+ },
+ "node_modules/@babel/plugin-syntax-class-properties": {
+ "version": "7.12.13",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-class-properties/-/plugin-syntax-class-properties-7.12.13.tgz",
+ "integrity": "sha512-fm4idjKla0YahUNgFNLCB0qySdsoPiZP3iQE3rky0mBUtMZ23yDJ9SJdg6dXTSDnulOVqiF3Hgr9nbXvXTQZYA==",
+ "dev": true,
+ "peer": true,
+ "dependencies": {
+ "@babel/helper-plugin-utils": "^7.12.13"
+ },
+ "peerDependencies": {
+ "@babel/core": "^7.0.0-0"
+ }
+ },
+ "node_modules/@babel/plugin-syntax-import-meta": {
+ "version": "7.10.4",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-import-meta/-/plugin-syntax-import-meta-7.10.4.tgz",
+ "integrity": "sha512-Yqfm+XDx0+Prh3VSeEQCPU81yC+JWZ2pDPFSS4ZdpfZhp4MkFMaDC1UqseovEKwSUpnIL7+vK+Clp7bfh0iD7g==",
+ "dev": true,
+ "peer": true,
+ "dependencies": {
+ "@babel/helper-plugin-utils": "^7.10.4"
+ },
+ "peerDependencies": {
+ "@babel/core": "^7.0.0-0"
+ }
+ },
+ "node_modules/@babel/plugin-syntax-json-strings": {
+ "version": "7.8.3",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-json-strings/-/plugin-syntax-json-strings-7.8.3.tgz",
+ "integrity": "sha512-lY6kdGpWHvjoe2vk4WrAapEuBR69EMxZl+RoGRhrFGNYVK8mOPAW8VfbT/ZgrFbXlDNiiaxQnAtgVCZ6jv30EA==",
+ "dev": true,
+ "peer": true,
+ "dependencies": {
+ "@babel/helper-plugin-utils": "^7.8.0"
+ },
+ "peerDependencies": {
+ "@babel/core": "^7.0.0-0"
+ }
+ },
+ "node_modules/@babel/plugin-syntax-jsx": {
+ "version": "7.12.1",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-jsx/-/plugin-syntax-jsx-7.12.1.tgz",
+ "integrity": "sha512-1yRi7yAtB0ETgxdY9ti/p2TivUxJkTdhu/ZbF9MshVGqOx1TdB3b7xCXs49Fupgg50N45KcAsRP/ZqWjs9SRjg==",
+ "dev": true,
+ "dependencies": {
+ "@babel/helper-plugin-utils": "^7.10.4"
+ },
+ "peerDependencies": {
+ "@babel/core": "^7.0.0-0"
+ }
+ },
+ "node_modules/@babel/plugin-syntax-logical-assignment-operators": {
+ "version": "7.10.4",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-logical-assignment-operators/-/plugin-syntax-logical-assignment-operators-7.10.4.tgz",
+ "integrity": "sha512-d8waShlpFDinQ5MtvGU9xDAOzKH47+FFoney2baFIoMr952hKOLp1HR7VszoZvOsV/4+RRszNY7D17ba0te0ig==",
+ "dev": true,
+ "peer": true,
+ "dependencies": {
+ "@babel/helper-plugin-utils": "^7.10.4"
+ },
+ "peerDependencies": {
+ "@babel/core": "^7.0.0-0"
+ }
+ },
+ "node_modules/@babel/plugin-syntax-nullish-coalescing-operator": {
+ "version": "7.8.3",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-nullish-coalescing-operator/-/plugin-syntax-nullish-coalescing-operator-7.8.3.tgz",
+ "integrity": "sha512-aSff4zPII1u2QD7y+F8oDsz19ew4IGEJg9SVW+bqwpwtfFleiQDMdzA/R+UlWDzfnHFCxxleFT0PMIrR36XLNQ==",
+ "dev": true,
+ "peer": true,
+ "dependencies": {
+ "@babel/helper-plugin-utils": "^7.8.0"
+ },
+ "peerDependencies": {
+ "@babel/core": "^7.0.0-0"
+ }
+ },
+ "node_modules/@babel/plugin-syntax-numeric-separator": {
+ "version": "7.10.4",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-numeric-separator/-/plugin-syntax-numeric-separator-7.10.4.tgz",
+ "integrity": "sha512-9H6YdfkcK/uOnY/K7/aA2xpzaAgkQn37yzWUMRK7OaPOqOpGS1+n0H5hxT9AUw9EsSjPW8SVyMJwYRtWs3X3ug==",
+ "dev": true,
+ "peer": true,
+ "dependencies": {
+ "@babel/helper-plugin-utils": "^7.10.4"
+ },
+ "peerDependencies": {
+ "@babel/core": "^7.0.0-0"
+ }
+ },
+ "node_modules/@babel/plugin-syntax-object-rest-spread": {
+ "version": "7.8.3",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-object-rest-spread/-/plugin-syntax-object-rest-spread-7.8.3.tgz",
+ "integrity": "sha512-XoqMijGZb9y3y2XskN+P1wUGiVwWZ5JmoDRwx5+3GmEplNyVM2s2Dg8ILFQm8rWM48orGy5YpI5Bl8U1y7ydlA==",
+ "dev": true,
+ "dependencies": {
+ "@babel/helper-plugin-utils": "^7.8.0"
+ },
+ "peerDependencies": {
+ "@babel/core": "^7.0.0-0"
+ }
+ },
+ "node_modules/@babel/plugin-syntax-optional-catch-binding": {
+ "version": "7.8.3",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-optional-catch-binding/-/plugin-syntax-optional-catch-binding-7.8.3.tgz",
+ "integrity": "sha512-6VPD0Pc1lpTqw0aKoeRTMiB+kWhAoT24PA+ksWSBrFtl5SIRVpZlwN3NNPQjehA2E/91FV3RjLWoVTglWcSV3Q==",
+ "dev": true,
+ "peer": true,
+ "dependencies": {
+ "@babel/helper-plugin-utils": "^7.8.0"
+ },
+ "peerDependencies": {
+ "@babel/core": "^7.0.0-0"
+ }
+ },
+ "node_modules/@babel/plugin-syntax-optional-chaining": {
+ "version": "7.8.3",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-optional-chaining/-/plugin-syntax-optional-chaining-7.8.3.tgz",
+ "integrity": "sha512-KoK9ErH1MBlCPxV0VANkXW2/dw4vlbGDrFgz8bmUsBGYkFRcbRwMh6cIJubdPrkxRwuGdtCk0v/wPTKbQgBjkg==",
+ "dev": true,
+ "peer": true,
+ "dependencies": {
+ "@babel/helper-plugin-utils": "^7.8.0"
+ },
+ "peerDependencies": {
+ "@babel/core": "^7.0.0-0"
+ }
+ },
+ "node_modules/@babel/plugin-syntax-top-level-await": {
+ "version": "7.14.5",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-top-level-await/-/plugin-syntax-top-level-await-7.14.5.tgz",
+ "integrity": "sha512-hx++upLv5U1rgYfwe1xBQUhRmU41NEvpUvrp8jkrSCdvGSnM5/qdRMtylJ6PG5OFkBaHkbTAKTnd3/YyESRHFw==",
+ "dev": true,
+ "peer": true,
+ "dependencies": {
+ "@babel/helper-plugin-utils": "^7.14.5"
+ },
+ "engines": {
+ "node": ">=6.9.0"
+ },
+ "peerDependencies": {
+ "@babel/core": "^7.0.0-0"
+ }
+ },
+ "node_modules/@babel/plugin-transform-parameters": {
+ "version": "7.21.3",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-transform-parameters/-/plugin-transform-parameters-7.21.3.tgz",
+ "integrity": "sha512-Wxc+TvppQG9xWFYatvCGPvZ6+SIUxQ2ZdiBP+PHYMIjnPXD+uThCshaz4NZOnODAtBjjcVQQ/3OKs9LW28purQ==",
+ "dev": true,
+ "dependencies": {
+ "@babel/helper-plugin-utils": "^7.20.2"
+ },
+ "engines": {
+ "node": ">=6.9.0"
+ },
+ "peerDependencies": {
+ "@babel/core": "^7.0.0-0"
+ }
+ },
+ "node_modules/@babel/runtime": {
+ "version": "7.21.0",
+ "resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.21.0.tgz",
+ "integrity": "sha512-xwII0//EObnq89Ji5AKYQaRYiW/nZ3llSv29d49IuxPhKbtJoLP+9QUUZ4nVragQVtaVGeZrpB+ZtG/Pdy/POw==",
+ "dev": true,
+ "dependencies": {
+ "regenerator-runtime": "^0.13.11"
+ },
+ "engines": {
+ "node": ">=6.9.0"
+ }
+ },
+ "node_modules/@babel/template": {
+ "version": "7.16.7",
+ "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.16.7.tgz",
+ "integrity": "sha512-I8j/x8kHUrbYRTUxXrrMbfCa7jxkE7tZre39x3kjr9hvI82cK1FfqLygotcWN5kdPGWcLdWMHpSBavse5tWw3w==",
+ "dev": true,
+ "dependencies": {
+ "@babel/code-frame": "^7.16.7",
+ "@babel/parser": "^7.16.7",
+ "@babel/types": "^7.16.7"
+ },
+ "engines": {
+ "node": ">=6.9.0"
+ }
+ },
+ "node_modules/@babel/traverse": {
+ "version": "7.17.9",
+ "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.17.9.tgz",
+ "integrity": "sha512-PQO8sDIJ8SIwipTPiR71kJQCKQYB5NGImbOviK8K+kg5xkNSYXLBupuX9QhatFowrsvo9Hj8WgArg3W7ijNAQw==",
+ "dev": true,
+ "dependencies": {
+ "@babel/code-frame": "^7.16.7",
+ "@babel/generator": "^7.17.9",
+ "@babel/helper-environment-visitor": "^7.16.7",
+ "@babel/helper-function-name": "^7.17.9",
+ "@babel/helper-hoist-variables": "^7.16.7",
+ "@babel/helper-split-export-declaration": "^7.16.7",
+ "@babel/parser": "^7.17.9",
+ "@babel/types": "^7.17.0",
+ "debug": "^4.1.0",
+ "globals": "^11.1.0"
+ },
+ "engines": {
+ "node": ">=6.9.0"
+ }
+ },
+ "node_modules/@babel/traverse/node_modules/globals": {
+ "version": "11.12.0",
+ "resolved": "https://registry.npmjs.org/globals/-/globals-11.12.0.tgz",
+ "integrity": "sha512-WOBp/EEGUiIsJSp7wcv/y6MO+lV9UoncWqxuFfm8eBwzWNgyfBd6Gz+IeKQ9jCmyhoH99g15M3T+QaVHFjizVA==",
+ "dev": true,
+ "engines": {
+ "node": ">=4"
+ }
+ },
+ "node_modules/@babel/types": {
+ "version": "7.17.0",
+ "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.17.0.tgz",
+ "integrity": "sha512-TmKSNO4D5rzhL5bjWFcVHHLETzfQ/AmbKpKPOSjlP0WoHZ6L911fgoOKY4Alp/emzG4cHJdyN49zpgkbXFEHHw==",
+ "dev": true,
+ "dependencies": {
+ "@babel/helper-validator-identifier": "^7.16.7",
+ "to-fast-properties": "^2.0.0"
+ },
+ "engines": {
+ "node": ">=6.9.0"
+ }
+ },
+ "node_modules/@bcoe/v8-coverage": {
+ "version": "0.2.3",
+ "resolved": "https://registry.npmjs.org/@bcoe/v8-coverage/-/v8-coverage-0.2.3.tgz",
+ "integrity": "sha512-0hYQ8SB4Db5zvZB4axdMHGwEaQjkZzFjQiN9LVYvIFB2nSUHW9tYpxWriPrWDASIxiaXax83REcLxuSdnGPZtw==",
+ "dev": true,
+ "peer": true
+ },
+ "node_modules/@cnakazawa/watch": {
+ "version": "1.0.4",
+ "resolved": "https://registry.npmjs.org/@cnakazawa/watch/-/watch-1.0.4.tgz",
+ "integrity": "sha512-v9kIhKwjeZThiWrLmj0y17CWoyddASLj9O2yvbZkbvw/N3rWOYy9zkV66ursAoVr0mV15bL8g0c4QZUE6cdDoQ==",
+ "dev": true,
+ "peer": true,
+ "dependencies": {
+ "exec-sh": "^0.3.2",
+ "minimist": "^1.2.0"
+ },
+ "bin": {
+ "watch": "cli.js"
+ },
+ "engines": {
+ "node": ">=0.1.95"
+ }
+ },
+ "node_modules/@eslint-community/eslint-utils": {
+ "version": "4.2.0",
+ "resolved": "https://registry.npmjs.org/@eslint-community/eslint-utils/-/eslint-utils-4.2.0.tgz",
+ "integrity": "sha512-gB8T4H4DEfX2IV9zGDJPOBgP1e/DbfCPDTtEqUMckpvzS1OYtva8JdFYBqMwYk7xAQ429WGF/UPqn8uQ//h2vQ==",
+ "dev": true,
+ "dependencies": {
+ "eslint-visitor-keys": "^3.3.0"
+ },
+ "engines": {
+ "node": "^12.22.0 || ^14.17.0 || >=16.0.0"
+ },
+ "peerDependencies": {
+ "eslint": "^6.0.0 || ^7.0.0 || >=8.0.0"
+ }
+ },
+ "node_modules/@eslint-community/regexpp": {
+ "version": "4.4.0",
+ "resolved": "https://registry.npmjs.org/@eslint-community/regexpp/-/regexpp-4.4.0.tgz",
+ "integrity": "sha512-A9983Q0LnDGdLPjxyXQ00sbV+K+O+ko2Dr+CZigbHWtX9pNfxlaBkMR8X1CztI73zuEyEBXTVjx7CE+/VSwDiQ==",
+ "dev": true,
+ "engines": {
+ "node": "^12.0.0 || ^14.0.0 || >=16.0.0"
+ }
+ },
+ "node_modules/@eslint/eslintrc": {
+ "version": "2.0.1",
+ "resolved": "https://registry.npmjs.org/@eslint/eslintrc/-/eslintrc-2.0.1.tgz",
+ "integrity": "sha512-eFRmABvW2E5Ho6f5fHLqgena46rOj7r7OKHYfLElqcBfGFHHpjBhivyi5+jOEQuSpdc/1phIZJlbC2te+tZNIw==",
+ "dev": true,
+ "dependencies": {
+ "ajv": "^6.12.4",
+ "debug": "^4.3.2",
+ "espree": "^9.5.0",
+ "globals": "^13.19.0",
+ "ignore": "^5.2.0",
+ "import-fresh": "^3.2.1",
+ "js-yaml": "^4.1.0",
+ "minimatch": "^3.1.2",
+ "strip-json-comments": "^3.1.1"
+ },
+ "engines": {
+ "node": "^12.22.0 || ^14.17.0 || >=16.0.0"
+ },
+ "funding": {
+ "url": "https://opencollective.com/eslint"
+ }
+ },
+ "node_modules/@eslint/js": {
+ "version": "8.36.0",
+ "resolved": "https://registry.npmjs.org/@eslint/js/-/js-8.36.0.tgz",
+ "integrity": "sha512-lxJ9R5ygVm8ZWgYdUweoq5ownDlJ4upvoWmO4eLxBYHdMo+vZ/Rx0EN6MbKWDJOSUGrqJy2Gt+Dyv/VKml0fjg==",
+ "dev": true,
+ "engines": {
+ "node": "^12.22.0 || ^14.17.0 || >=16.0.0"
+ }
+ },
+ "node_modules/@hashicorp/platform-cli": {
+ "version": "2.6.0",
+ "resolved": "https://registry.npmjs.org/@hashicorp/platform-cli/-/platform-cli-2.6.0.tgz",
+ "integrity": "sha512-nMO7Uiy/A5CT/BCE9RyQt6/Uci7bxwTesxCNWkXlciyqlIrz9WmBa9hr710IiMoDzrzQ1tL6AgFIeTbXs4RTqA==",
+ "dev": true,
+ "dependencies": {
+ "@hashicorp/platform-cms": "0.3.0",
+ "@typescript-eslint/eslint-plugin": "^5.48.0",
+ "@typescript-eslint/parser": "^5.48.0",
+ "chalk": "4.1.0",
+ "commander": "7.2.0",
+ "ejs": "3.1.5",
+ "eslint": "^8.31.0",
+ "eslint-config-next": "^13.1.1",
+ "eslint-config-prettier": "^8.6.0",
+ "eslint-plugin-jsx-a11y": "^6.6.1",
+ "eslint-plugin-prettier": "^4.2.1",
+ "fs-extra": "9.0.1",
+ "globby": "11.0.1",
+ "inquirer": "7.3.3",
+ "lint-staged": "11.1.2",
+ "open": "7.3.0",
+ "prettier": "2.5.1",
+ "readdirp": "3.5.0",
+ "signale": "1.4.0",
+ "slugify": "1.4.6",
+ "stylelint": "13.8.0",
+ "stylelint-config-css-modules": "2.2.0",
+ "stylelint-config-prettier": "8.0.2",
+ "stylelint-config-standard": "20.0.0",
+ "stylelint-media-use-custom-media": "2.0.0",
+ "stylelint-order": "4.1.0",
+ "stylelint-use-nesting": "3.0.0",
+ "stylelint-value-no-unknown-custom-properties": "3.0.0",
+ "ts-jest": "^26.4.4"
+ },
+ "bin": {
+ "next-hashicorp": "next-hashicorp"
+ }
+ },
+ "node_modules/@hashicorp/platform-cli/node_modules/prettier": {
+ "version": "2.5.1",
+ "resolved": "https://registry.npmjs.org/prettier/-/prettier-2.5.1.tgz",
+ "integrity": "sha512-vBZcPRUR5MZJwoyi3ZoyQlc1rXeEck8KgeC9AwwOn+exuxLxq5toTRDTSaVrXHxelDMHy9zlicw8u66yxoSUFg==",
+ "dev": true,
+ "bin": {
+ "prettier": "bin-prettier.js"
+ },
+ "engines": {
+ "node": ">=10.13.0"
+ }
+ },
+ "node_modules/@hashicorp/platform-cms": {
+ "version": "0.3.0",
+ "resolved": "https://registry.npmjs.org/@hashicorp/platform-cms/-/platform-cms-0.3.0.tgz",
+ "integrity": "sha512-sRX9A+kDEZvfZy8PvGFbEaHjn5G1mEsHwTri1vDnrmKG8apE+ELlug83b0iEkD5wIJi9OqaewMIb0NrLxg9s5A==",
+ "dev": true,
+ "dependencies": {
+ "rivet-graphql": "0.3.1"
+ }
+ },
+ "node_modules/@hashicorp/platform-content-conformance": {
+ "version": "0.0.10",
+ "resolved": "https://registry.npmjs.org/@hashicorp/platform-content-conformance/-/platform-content-conformance-0.0.10.tgz",
+ "integrity": "sha512-vXLbd2w9phS4JfFyh17jCiyu+LXVonTfb7WEUK2eMlOL/wxe2umyJvEQaJNzD5bwyYC8LuXGA5JkbnPXnU5ZQg==",
+ "dev": true,
+ "dependencies": {
+ "find-up": "^6.3.0",
+ "flat": "^5.0.2",
+ "globby": "^13.1.2",
+ "mdast-util-to-string": "^3.1.0",
+ "remark": "12.0.1",
+ "remark-mdx": "^1.6.22",
+ "unified-lint-rule": "^2.1.1",
+ "unist-util-stringify-position": "^3.0.2",
+ "unist-util-visit": "^4.1.1",
+ "vfile": "^5.3.6",
+ "vfile-matter": "^4.0.0",
+ "vfile-reporter": "^7.0.4",
+ "vfile-reporter-json": "^3.2.0",
+ "vfile-statistics": "^2.0.0",
+ "yaml": "^2.1.3",
+ "yargs": "^17.4.1",
+ "zod": "^3.19.1"
+ },
+ "bin": {
+ "hc-content": "dist/cli.js"
+ }
+ },
+ "node_modules/@hashicorp/platform-content-conformance/node_modules/cliui": {
+ "version": "8.0.1",
+ "resolved": "https://registry.npmjs.org/cliui/-/cliui-8.0.1.tgz",
+ "integrity": "sha512-BSeNnyus75C4//NQ9gQt1/csTXyo/8Sb+afLAkzAptFuMsod9HFokGNudZpi/oQV73hnVK+sR+5PVRMd+Dr7YQ==",
+ "dev": true,
+ "dependencies": {
+ "string-width": "^4.2.0",
+ "strip-ansi": "^6.0.1",
+ "wrap-ansi": "^7.0.0"
+ },
+ "engines": {
+ "node": ">=12"
+ }
+ },
+ "node_modules/@hashicorp/platform-content-conformance/node_modules/find-up": {
+ "version": "6.3.0",
+ "resolved": "https://registry.npmjs.org/find-up/-/find-up-6.3.0.tgz",
+ "integrity": "sha512-v2ZsoEuVHYy8ZIlYqwPe/39Cy+cFDzp4dXPaxNvkEuouymu+2Jbz0PxpKarJHYJTmv2HWT3O382qY8l4jMWthw==",
+ "dev": true,
+ "dependencies": {
+ "locate-path": "^7.1.0",
+ "path-exists": "^5.0.0"
+ },
+ "engines": {
+ "node": "^12.20.0 || ^14.13.1 || >=16.0.0"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
+ "node_modules/@hashicorp/platform-content-conformance/node_modules/globby": {
+ "version": "13.1.3",
+ "resolved": "https://registry.npmjs.org/globby/-/globby-13.1.3.tgz",
+ "integrity": "sha512-8krCNHXvlCgHDpegPzleMq07yMYTO2sXKASmZmquEYWEmCx6J5UTRbp5RwMJkTJGtcQ44YpiUYUiN0b9mzy8Bw==",
+ "dev": true,
+ "dependencies": {
+ "dir-glob": "^3.0.1",
+ "fast-glob": "^3.2.11",
+ "ignore": "^5.2.0",
+ "merge2": "^1.4.1",
+ "slash": "^4.0.0"
+ },
+ "engines": {
+ "node": "^12.20.0 || ^14.13.1 || >=16.0.0"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
+ "node_modules/@hashicorp/platform-content-conformance/node_modules/locate-path": {
+ "version": "7.2.0",
+ "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-7.2.0.tgz",
+ "integrity": "sha512-gvVijfZvn7R+2qyPX8mAuKcFGDf6Nc61GdvGafQsHL0sBIxfKzA+usWn4GFC/bk+QdwPUD4kWFJLhElipq+0VA==",
+ "dev": true,
+ "dependencies": {
+ "p-locate": "^6.0.0"
+ },
+ "engines": {
+ "node": "^12.20.0 || ^14.13.1 || >=16.0.0"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
+ "node_modules/@hashicorp/platform-content-conformance/node_modules/mdast-util-to-string": {
+ "version": "3.1.1",
+ "resolved": "https://registry.npmjs.org/mdast-util-to-string/-/mdast-util-to-string-3.1.1.tgz",
+ "integrity": "sha512-tGvhT94e+cVnQt8JWE9/b3cUQZWS732TJxXHktvP+BYo62PpYD53Ls/6cC60rW21dW+txxiM4zMdc6abASvZKA==",
+ "dev": true,
+ "dependencies": {
+ "@types/mdast": "^3.0.0"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/unified"
+ }
+ },
+ "node_modules/@hashicorp/platform-content-conformance/node_modules/p-limit": {
+ "version": "4.0.0",
+ "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-4.0.0.tgz",
+ "integrity": "sha512-5b0R4txpzjPWVw/cXXUResoD4hb6U/x9BH08L7nw+GN1sezDzPdxeRvpc9c433fZhBan/wusjbCsqwqm4EIBIQ==",
+ "dev": true,
+ "dependencies": {
+ "yocto-queue": "^1.0.0"
+ },
+ "engines": {
+ "node": "^12.20.0 || ^14.13.1 || >=16.0.0"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
+ "node_modules/@hashicorp/platform-content-conformance/node_modules/p-locate": {
+ "version": "6.0.0",
+ "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-6.0.0.tgz",
+ "integrity": "sha512-wPrq66Llhl7/4AGC6I+cqxT07LhXvWL08LNXz1fENOw0Ap4sRZZ/gZpTTJ5jpurzzzfS2W/Ge9BY3LgLjCShcw==",
+ "dev": true,
+ "dependencies": {
+ "p-limit": "^4.0.0"
+ },
+ "engines": {
+ "node": "^12.20.0 || ^14.13.1 || >=16.0.0"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
+ "node_modules/@hashicorp/platform-content-conformance/node_modules/path-exists": {
+ "version": "5.0.0",
+ "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-5.0.0.tgz",
+ "integrity": "sha512-RjhtfwJOxzcFmNOi6ltcbcu4Iu+FL3zEj83dk4kAS+fVpTxXLO1b38RvJgT/0QwvV/L3aY9TAnyv0EOqW4GoMQ==",
+ "dev": true,
+ "engines": {
+ "node": "^12.20.0 || ^14.13.1 || >=16.0.0"
+ }
+ },
+ "node_modules/@hashicorp/platform-content-conformance/node_modules/remark": {
+ "version": "12.0.1",
+ "resolved": "https://registry.npmjs.org/remark/-/remark-12.0.1.tgz",
+ "integrity": "sha512-gS7HDonkdIaHmmP/+shCPejCEEW+liMp/t/QwmF0Xt47Rpuhl32lLtDV1uKWvGoq+kxr5jSgg5oAIpGuyULjUw==",
+ "dev": true,
+ "dependencies": {
+ "remark-parse": "^8.0.0",
+ "remark-stringify": "^8.0.0",
+ "unified": "^9.0.0"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/unified"
+ }
+ },
+ "node_modules/@hashicorp/platform-content-conformance/node_modules/remark-parse": {
+ "version": "8.0.3",
+ "resolved": "https://registry.npmjs.org/remark-parse/-/remark-parse-8.0.3.tgz",
+ "integrity": "sha512-E1K9+QLGgggHxCQtLt++uXltxEprmWzNfg+MxpfHsZlrddKzZ/hZyWHDbK3/Ap8HJQqYJRXP+jHczdL6q6i85Q==",
+ "dev": true,
+ "dependencies": {
+ "ccount": "^1.0.0",
+ "collapse-white-space": "^1.0.2",
+ "is-alphabetical": "^1.0.0",
+ "is-decimal": "^1.0.0",
+ "is-whitespace-character": "^1.0.0",
+ "is-word-character": "^1.0.0",
+ "markdown-escapes": "^1.0.0",
+ "parse-entities": "^2.0.0",
+ "repeat-string": "^1.5.4",
+ "state-toggle": "^1.0.0",
+ "trim": "0.0.1",
+ "trim-trailing-lines": "^1.0.0",
+ "unherit": "^1.0.4",
+ "unist-util-remove-position": "^2.0.0",
+ "vfile-location": "^3.0.0",
+ "xtend": "^4.0.1"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/unified"
+ }
+ },
+ "node_modules/@hashicorp/platform-content-conformance/node_modules/remark-stringify": {
+ "version": "8.1.1",
+ "resolved": "https://registry.npmjs.org/remark-stringify/-/remark-stringify-8.1.1.tgz",
+ "integrity": "sha512-q4EyPZT3PcA3Eq7vPpT6bIdokXzFGp9i85igjmhRyXWmPs0Y6/d2FYwUNotKAWyLch7g0ASZJn/KHHcHZQ163A==",
+ "dev": true,
+ "dependencies": {
+ "ccount": "^1.0.0",
+ "is-alphanumeric": "^1.0.0",
+ "is-decimal": "^1.0.0",
+ "is-whitespace-character": "^1.0.0",
+ "longest-streak": "^2.0.1",
+ "markdown-escapes": "^1.0.0",
+ "markdown-table": "^2.0.0",
+ "mdast-util-compact": "^2.0.0",
+ "parse-entities": "^2.0.0",
+ "repeat-string": "^1.5.4",
+ "state-toggle": "^1.0.0",
+ "stringify-entities": "^3.0.0",
+ "unherit": "^1.0.4",
+ "xtend": "^4.0.1"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/unified"
+ }
+ },
+ "node_modules/@hashicorp/platform-content-conformance/node_modules/slash": {
+ "version": "4.0.0",
+ "resolved": "https://registry.npmjs.org/slash/-/slash-4.0.0.tgz",
+ "integrity": "sha512-3dOsAHXXUkQTpOYcoAxLIorMTp4gIQr5IW3iVb7A7lFIp0VHhnynm9izx6TssdrIcVIESAlVjtnO2K8bg+Coew==",
+ "dev": true,
+ "engines": {
+ "node": ">=12"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
+ "node_modules/@hashicorp/platform-content-conformance/node_modules/unist-util-stringify-position": {
+ "version": "3.0.3",
+ "resolved": "https://registry.npmjs.org/unist-util-stringify-position/-/unist-util-stringify-position-3.0.3.tgz",
+ "integrity": "sha512-k5GzIBZ/QatR8N5X2y+drfpWG8IDBzdnVj6OInRNWm1oXrzydiaAT2OQiA8DPRRZyAKb9b6I2a6PxYklZD0gKg==",
+ "dev": true,
+ "dependencies": {
+ "@types/unist": "^2.0.0"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/unified"
+ }
+ },
+ "node_modules/@hashicorp/platform-content-conformance/node_modules/vfile": {
+ "version": "5.3.7",
+ "resolved": "https://registry.npmjs.org/vfile/-/vfile-5.3.7.tgz",
+ "integrity": "sha512-r7qlzkgErKjobAmyNIkkSpizsFPYiUPuJb5pNW1RB4JcYVZhs4lIbVqk8XPk033CV/1z8ss5pkax8SuhGpcG8g==",
+ "dev": true,
+ "dependencies": {
+ "@types/unist": "^2.0.0",
+ "is-buffer": "^2.0.0",
+ "unist-util-stringify-position": "^3.0.0",
+ "vfile-message": "^3.0.0"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/unified"
+ }
+ },
+ "node_modules/@hashicorp/platform-content-conformance/node_modules/vfile-message": {
+ "version": "3.1.4",
+ "resolved": "https://registry.npmjs.org/vfile-message/-/vfile-message-3.1.4.tgz",
+ "integrity": "sha512-fa0Z6P8HUrQN4BZaX05SIVXic+7kE3b05PWAtPuYP9QLHsLKYR7/AlLW3NtOrpXRLeawpDLMsVkmk5DG0NXgWw==",
+ "dev": true,
+ "dependencies": {
+ "@types/unist": "^2.0.0",
+ "unist-util-stringify-position": "^3.0.0"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/unified"
+ }
+ },
+ "node_modules/@hashicorp/platform-content-conformance/node_modules/y18n": {
+ "version": "5.0.8",
+ "resolved": "https://registry.npmjs.org/y18n/-/y18n-5.0.8.tgz",
+ "integrity": "sha512-0pfFzegeDWJHJIAmTLRP2DwHjdF5s7jo9tuztdQxAhINCdvS+3nGINqPd00AphqJR/0LhANUS6/+7SCb98YOfA==",
+ "dev": true,
+ "engines": {
+ "node": ">=10"
+ }
+ },
+ "node_modules/@hashicorp/platform-content-conformance/node_modules/yaml": {
+ "version": "2.2.1",
+ "resolved": "https://registry.npmjs.org/yaml/-/yaml-2.2.1.tgz",
+ "integrity": "sha512-e0WHiYql7+9wr4cWMx3TVQrNwejKaEe7/rHNmQmqRjazfOP5W8PB6Jpebb5o6fIapbz9o9+2ipcaTM2ZwDI6lw==",
+ "dev": true,
+ "engines": {
+ "node": ">= 14"
+ }
+ },
+ "node_modules/@hashicorp/platform-content-conformance/node_modules/yargs": {
+ "version": "17.7.1",
+ "resolved": "https://registry.npmjs.org/yargs/-/yargs-17.7.1.tgz",
+ "integrity": "sha512-cwiTb08Xuv5fqF4AovYacTFNxk62th7LKJ6BL9IGUpTJrWoU7/7WdQGTP2SjKf1dUNBGzDd28p/Yfs/GI6JrLw==",
+ "dev": true,
+ "dependencies": {
+ "cliui": "^8.0.1",
+ "escalade": "^3.1.1",
+ "get-caller-file": "^2.0.5",
+ "require-directory": "^2.1.1",
+ "string-width": "^4.2.3",
+ "y18n": "^5.0.5",
+ "yargs-parser": "^21.1.1"
+ },
+ "engines": {
+ "node": ">=12"
+ }
+ },
+ "node_modules/@hashicorp/platform-content-conformance/node_modules/yargs-parser": {
+ "version": "21.1.1",
+ "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-21.1.1.tgz",
+ "integrity": "sha512-tVpsJW7DdjecAiFpbIB1e3qxIQsE6NoPc5/eTdrbbIC4h0LVsWhnoa3g+m2HclBIujHzsxZ4VJVA+GUuc2/LBw==",
+ "dev": true,
+ "engines": {
+ "node": ">=12"
+ }
+ },
+ "node_modules/@hashicorp/platform-content-conformance/node_modules/yocto-queue": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/yocto-queue/-/yocto-queue-1.0.0.tgz",
+ "integrity": "sha512-9bnSc/HEW2uRy67wc+T8UwauLuPJVn28jb+GtJY16iiKWyvmYJRXVT4UamsAEGQfPohgr2q4Tq0sQbQlxTfi1g==",
+ "dev": true,
+ "engines": {
+ "node": ">=12.20"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
+ "node_modules/@humanwhocodes/config-array": {
+ "version": "0.11.8",
+ "resolved": "https://registry.npmjs.org/@humanwhocodes/config-array/-/config-array-0.11.8.tgz",
+ "integrity": "sha512-UybHIJzJnR5Qc/MsD9Kr+RpO2h+/P1GhOwdiLPXK5TWk5sgTdu88bTD9UP+CKbPPh5Rni1u0GjAdYQLemG8g+g==",
+ "dev": true,
+ "dependencies": {
+ "@humanwhocodes/object-schema": "^1.2.1",
+ "debug": "^4.1.1",
+ "minimatch": "^3.0.5"
+ },
+ "engines": {
+ "node": ">=10.10.0"
+ }
+ },
+ "node_modules/@humanwhocodes/module-importer": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/@humanwhocodes/module-importer/-/module-importer-1.0.1.tgz",
+ "integrity": "sha512-bxveV4V8v5Yb4ncFTT3rPSgZBOpCkjfK0y4oVVVJwIuDVBRMDXrPyXRL988i5ap9m9bnyEEjWfm5WkBmtffLfA==",
+ "dev": true,
+ "engines": {
+ "node": ">=12.22"
+ },
+ "funding": {
+ "type": "github",
+ "url": "https://github.com/sponsors/nzakas"
+ }
+ },
+ "node_modules/@humanwhocodes/object-schema": {
+ "version": "1.2.1",
+ "resolved": "https://registry.npmjs.org/@humanwhocodes/object-schema/-/object-schema-1.2.1.tgz",
+ "integrity": "sha512-ZnQMnLV4e7hDlUvw8H+U8ASL02SS2Gn6+9Ac3wGGLIe7+je2AeAOxPY+izIPJDfFDb7eDjev0Us8MO1iFRN8hA==",
+ "dev": true
+ },
+ "node_modules/@istanbuljs/load-nyc-config": {
+ "version": "1.1.0",
+ "resolved": "https://registry.npmjs.org/@istanbuljs/load-nyc-config/-/load-nyc-config-1.1.0.tgz",
+ "integrity": "sha512-VjeHSlIzpv/NyD3N0YuHfXOPDIixcA1q2ZV98wsMqcYlPmv2n3Yb2lYP9XMElnaFVXg5A7YLTeLu6V84uQDjmQ==",
+ "dev": true,
+ "peer": true,
+ "dependencies": {
+ "camelcase": "^5.3.1",
+ "find-up": "^4.1.0",
+ "get-package-type": "^0.1.0",
+ "js-yaml": "^3.13.1",
+ "resolve-from": "^5.0.0"
+ },
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/@istanbuljs/load-nyc-config/node_modules/argparse": {
+ "version": "1.0.10",
+ "resolved": "https://registry.npmjs.org/argparse/-/argparse-1.0.10.tgz",
+ "integrity": "sha512-o5Roy6tNG4SL/FOkCAN6RzjiakZS25RLYFrcMttJqbdd8BWrnA+fGz57iN5Pb06pvBGvl5gQ0B48dJlslXvoTg==",
+ "dev": true,
+ "peer": true,
+ "dependencies": {
+ "sprintf-js": "~1.0.2"
+ }
+ },
+ "node_modules/@istanbuljs/load-nyc-config/node_modules/find-up": {
+ "version": "4.1.0",
+ "resolved": "https://registry.npmjs.org/find-up/-/find-up-4.1.0.tgz",
+ "integrity": "sha512-PpOwAdQ/YlXQ2vj8a3h8IipDuYRi3wceVQQGYWxNINccq40Anw7BlsEXCMbt1Zt+OLA6Fq9suIpIWD0OsnISlw==",
+ "dev": true,
+ "peer": true,
+ "dependencies": {
+ "locate-path": "^5.0.0",
+ "path-exists": "^4.0.0"
+ },
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/@istanbuljs/load-nyc-config/node_modules/js-yaml": {
+ "version": "3.14.1",
+ "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-3.14.1.tgz",
+ "integrity": "sha512-okMH7OXXJ7YrN9Ok3/SXrnu4iX9yOk+25nqX4imS2npuvTYDmo/QEZoqwZkYaIDk3jVvBOTOIEgEhaLOynBS9g==",
+ "dev": true,
+ "peer": true,
+ "dependencies": {
+ "argparse": "^1.0.7",
+ "esprima": "^4.0.0"
+ },
+ "bin": {
+ "js-yaml": "bin/js-yaml.js"
+ }
+ },
+ "node_modules/@istanbuljs/load-nyc-config/node_modules/locate-path": {
+ "version": "5.0.0",
+ "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-5.0.0.tgz",
+ "integrity": "sha512-t7hw9pI+WvuwNJXwk5zVHpyhIqzg2qTlklJOf0mVxGSbe3Fp2VieZcduNYjaLDoy6p9uGpQEGWG87WpMKlNq8g==",
+ "dev": true,
+ "peer": true,
+ "dependencies": {
+ "p-locate": "^4.1.0"
+ },
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/@istanbuljs/load-nyc-config/node_modules/p-limit": {
+ "version": "2.3.0",
+ "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-2.3.0.tgz",
+ "integrity": "sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w==",
+ "dev": true,
+ "peer": true,
+ "dependencies": {
+ "p-try": "^2.0.0"
+ },
+ "engines": {
+ "node": ">=6"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
+ "node_modules/@istanbuljs/load-nyc-config/node_modules/p-locate": {
+ "version": "4.1.0",
+ "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-4.1.0.tgz",
+ "integrity": "sha512-R79ZZ/0wAxKGu3oYMlz8jy/kbhsNrS7SKZ7PxEHBgJ5+F2mtFW2fK2cOtBh1cHYkQsbzFV7I+EoRKe6Yt0oK7A==",
+ "dev": true,
+ "peer": true,
+ "dependencies": {
+ "p-limit": "^2.2.0"
+ },
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/@istanbuljs/load-nyc-config/node_modules/resolve-from": {
+ "version": "5.0.0",
+ "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-5.0.0.tgz",
+ "integrity": "sha512-qYg9KP24dD5qka9J47d0aVky0N+b4fTU89LN9iDnjB5waksiC49rvMB0PrUJQGoTmH50XPiqOvAjDfaijGxYZw==",
+ "dev": true,
+ "peer": true,
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/@istanbuljs/schema": {
+ "version": "0.1.3",
+ "resolved": "https://registry.npmjs.org/@istanbuljs/schema/-/schema-0.1.3.tgz",
+ "integrity": "sha512-ZXRY4jNvVgSVQ8DL3LTcakaAtXwTVUxE81hslsyD2AtoXW/wVob10HkOJ1X/pAlcI7D+2YoZKg5do8G/w6RYgA==",
+ "dev": true,
+ "peer": true,
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/@jest/console": {
+ "version": "26.6.2",
+ "resolved": "https://registry.npmjs.org/@jest/console/-/console-26.6.2.tgz",
+ "integrity": "sha512-IY1R2i2aLsLr7Id3S6p2BA82GNWryt4oSvEXLAKc+L2zdi89dSkE8xC1C+0kpATG4JhBJREnQOH7/zmccM2B0g==",
+ "dev": true,
+ "peer": true,
+ "dependencies": {
+ "@jest/types": "^26.6.2",
+ "@types/node": "*",
+ "chalk": "^4.0.0",
+ "jest-message-util": "^26.6.2",
+ "jest-util": "^26.6.2",
+ "slash": "^3.0.0"
+ },
+ "engines": {
+ "node": ">= 10.14.2"
+ }
+ },
+ "node_modules/@jest/core": {
+ "version": "26.6.3",
+ "resolved": "https://registry.npmjs.org/@jest/core/-/core-26.6.3.tgz",
+ "integrity": "sha512-xvV1kKbhfUqFVuZ8Cyo+JPpipAHHAV3kcDBftiduK8EICXmTFddryy3P7NfZt8Pv37rA9nEJBKCCkglCPt/Xjw==",
+ "dev": true,
+ "peer": true,
+ "dependencies": {
+ "@jest/console": "^26.6.2",
+ "@jest/reporters": "^26.6.2",
+ "@jest/test-result": "^26.6.2",
+ "@jest/transform": "^26.6.2",
+ "@jest/types": "^26.6.2",
+ "@types/node": "*",
+ "ansi-escapes": "^4.2.1",
+ "chalk": "^4.0.0",
+ "exit": "^0.1.2",
+ "graceful-fs": "^4.2.4",
+ "jest-changed-files": "^26.6.2",
+ "jest-config": "^26.6.3",
+ "jest-haste-map": "^26.6.2",
+ "jest-message-util": "^26.6.2",
+ "jest-regex-util": "^26.0.0",
+ "jest-resolve": "^26.6.2",
+ "jest-resolve-dependencies": "^26.6.3",
+ "jest-runner": "^26.6.3",
+ "jest-runtime": "^26.6.3",
+ "jest-snapshot": "^26.6.2",
+ "jest-util": "^26.6.2",
+ "jest-validate": "^26.6.2",
+ "jest-watcher": "^26.6.2",
+ "micromatch": "^4.0.2",
+ "p-each-series": "^2.1.0",
+ "rimraf": "^3.0.0",
+ "slash": "^3.0.0",
+ "strip-ansi": "^6.0.0"
+ },
+ "engines": {
+ "node": ">= 10.14.2"
+ }
+ },
+ "node_modules/@jest/environment": {
+ "version": "26.6.2",
+ "resolved": "https://registry.npmjs.org/@jest/environment/-/environment-26.6.2.tgz",
+ "integrity": "sha512-nFy+fHl28zUrRsCeMB61VDThV1pVTtlEokBRgqPrcT1JNq4yRNIyTHfyht6PqtUvY9IsuLGTrbG8kPXjSZIZwA==",
+ "dev": true,
+ "peer": true,
+ "dependencies": {
+ "@jest/fake-timers": "^26.6.2",
+ "@jest/types": "^26.6.2",
+ "@types/node": "*",
+ "jest-mock": "^26.6.2"
+ },
+ "engines": {
+ "node": ">= 10.14.2"
+ }
+ },
+ "node_modules/@jest/fake-timers": {
+ "version": "26.6.2",
+ "resolved": "https://registry.npmjs.org/@jest/fake-timers/-/fake-timers-26.6.2.tgz",
+ "integrity": "sha512-14Uleatt7jdzefLPYM3KLcnUl1ZNikaKq34enpb5XG9i81JpppDb5muZvonvKyrl7ftEHkKS5L5/eB/kxJ+bvA==",
+ "dev": true,
+ "peer": true,
+ "dependencies": {
+ "@jest/types": "^26.6.2",
+ "@sinonjs/fake-timers": "^6.0.1",
+ "@types/node": "*",
+ "jest-message-util": "^26.6.2",
+ "jest-mock": "^26.6.2",
+ "jest-util": "^26.6.2"
+ },
+ "engines": {
+ "node": ">= 10.14.2"
+ }
+ },
+ "node_modules/@jest/globals": {
+ "version": "26.6.2",
+ "resolved": "https://registry.npmjs.org/@jest/globals/-/globals-26.6.2.tgz",
+ "integrity": "sha512-85Ltnm7HlB/KesBUuALwQ68YTU72w9H2xW9FjZ1eL1U3lhtefjjl5c2MiUbpXt/i6LaPRvoOFJ22yCBSfQ0JIA==",
+ "dev": true,
+ "peer": true,
+ "dependencies": {
+ "@jest/environment": "^26.6.2",
+ "@jest/types": "^26.6.2",
+ "expect": "^26.6.2"
+ },
+ "engines": {
+ "node": ">= 10.14.2"
+ }
+ },
+ "node_modules/@jest/reporters": {
+ "version": "26.6.2",
+ "resolved": "https://registry.npmjs.org/@jest/reporters/-/reporters-26.6.2.tgz",
+ "integrity": "sha512-h2bW53APG4HvkOnVMo8q3QXa6pcaNt1HkwVsOPMBV6LD/q9oSpxNSYZQYkAnjdMjrJ86UuYeLo+aEZClV6opnw==",
+ "dev": true,
+ "peer": true,
+ "dependencies": {
+ "@bcoe/v8-coverage": "^0.2.3",
+ "@jest/console": "^26.6.2",
+ "@jest/test-result": "^26.6.2",
+ "@jest/transform": "^26.6.2",
+ "@jest/types": "^26.6.2",
+ "chalk": "^4.0.0",
+ "collect-v8-coverage": "^1.0.0",
+ "exit": "^0.1.2",
+ "glob": "^7.1.2",
+ "graceful-fs": "^4.2.4",
+ "istanbul-lib-coverage": "^3.0.0",
+ "istanbul-lib-instrument": "^4.0.3",
+ "istanbul-lib-report": "^3.0.0",
+ "istanbul-lib-source-maps": "^4.0.0",
+ "istanbul-reports": "^3.0.2",
+ "jest-haste-map": "^26.6.2",
+ "jest-resolve": "^26.6.2",
+ "jest-util": "^26.6.2",
+ "jest-worker": "^26.6.2",
+ "slash": "^3.0.0",
+ "source-map": "^0.6.0",
+ "string-length": "^4.0.1",
+ "terminal-link": "^2.0.0",
+ "v8-to-istanbul": "^7.0.0"
+ },
+ "engines": {
+ "node": ">= 10.14.2"
+ },
+ "optionalDependencies": {
+ "node-notifier": "^8.0.0"
+ }
+ },
+ "node_modules/@jest/source-map": {
+ "version": "26.6.2",
+ "resolved": "https://registry.npmjs.org/@jest/source-map/-/source-map-26.6.2.tgz",
+ "integrity": "sha512-YwYcCwAnNmOVsZ8mr3GfnzdXDAl4LaenZP5z+G0c8bzC9/dugL8zRmxZzdoTl4IaS3CryS1uWnROLPFmb6lVvA==",
+ "dev": true,
+ "peer": true,
+ "dependencies": {
+ "callsites": "^3.0.0",
+ "graceful-fs": "^4.2.4",
+ "source-map": "^0.6.0"
+ },
+ "engines": {
+ "node": ">= 10.14.2"
+ }
+ },
+ "node_modules/@jest/test-result": {
+ "version": "26.6.2",
+ "resolved": "https://registry.npmjs.org/@jest/test-result/-/test-result-26.6.2.tgz",
+ "integrity": "sha512-5O7H5c/7YlojphYNrK02LlDIV2GNPYisKwHm2QTKjNZeEzezCbwYs9swJySv2UfPMyZ0VdsmMv7jIlD/IKYQpQ==",
+ "dev": true,
+ "peer": true,
+ "dependencies": {
+ "@jest/console": "^26.6.2",
+ "@jest/types": "^26.6.2",
+ "@types/istanbul-lib-coverage": "^2.0.0",
+ "collect-v8-coverage": "^1.0.0"
+ },
+ "engines": {
+ "node": ">= 10.14.2"
+ }
+ },
+ "node_modules/@jest/test-sequencer": {
+ "version": "26.6.3",
+ "resolved": "https://registry.npmjs.org/@jest/test-sequencer/-/test-sequencer-26.6.3.tgz",
+ "integrity": "sha512-YHlVIjP5nfEyjlrSr8t/YdNfU/1XEt7c5b4OxcXCjyRhjzLYu/rO69/WHPuYcbCWkz8kAeZVZp2N2+IOLLEPGw==",
+ "dev": true,
+ "peer": true,
+ "dependencies": {
+ "@jest/test-result": "^26.6.2",
+ "graceful-fs": "^4.2.4",
+ "jest-haste-map": "^26.6.2",
+ "jest-runner": "^26.6.3",
+ "jest-runtime": "^26.6.3"
+ },
+ "engines": {
+ "node": ">= 10.14.2"
+ }
+ },
+ "node_modules/@jest/transform": {
+ "version": "26.6.2",
+ "resolved": "https://registry.npmjs.org/@jest/transform/-/transform-26.6.2.tgz",
+ "integrity": "sha512-E9JjhUgNzvuQ+vVAL21vlyfy12gP0GhazGgJC4h6qUt1jSdUXGWJ1wfu/X7Sd8etSgxV4ovT1pb9v5D6QW4XgA==",
+ "dev": true,
+ "peer": true,
+ "dependencies": {
+ "@babel/core": "^7.1.0",
+ "@jest/types": "^26.6.2",
+ "babel-plugin-istanbul": "^6.0.0",
+ "chalk": "^4.0.0",
+ "convert-source-map": "^1.4.0",
+ "fast-json-stable-stringify": "^2.0.0",
+ "graceful-fs": "^4.2.4",
+ "jest-haste-map": "^26.6.2",
+ "jest-regex-util": "^26.0.0",
+ "jest-util": "^26.6.2",
+ "micromatch": "^4.0.2",
+ "pirates": "^4.0.1",
+ "slash": "^3.0.0",
+ "source-map": "^0.6.1",
+ "write-file-atomic": "^3.0.0"
+ },
+ "engines": {
+ "node": ">= 10.14.2"
+ }
+ },
+ "node_modules/@jest/types": {
+ "version": "26.6.2",
+ "resolved": "https://registry.npmjs.org/@jest/types/-/types-26.6.2.tgz",
+ "integrity": "sha512-fC6QCp7Sc5sX6g8Tvbmj4XUTbyrik0akgRy03yjXbQaBWWNWGE7SGtJk98m0N8nzegD/7SggrUlivxo5ax4KWQ==",
+ "dev": true,
+ "dependencies": {
+ "@types/istanbul-lib-coverage": "^2.0.0",
+ "@types/istanbul-reports": "^3.0.0",
+ "@types/node": "*",
+ "@types/yargs": "^15.0.0",
+ "chalk": "^4.0.0"
+ },
+ "engines": {
+ "node": ">= 10.14.2"
+ }
+ },
+ "node_modules/@jridgewell/resolve-uri": {
+ "version": "3.0.5",
+ "resolved": "https://registry.npmjs.org/@jridgewell/resolve-uri/-/resolve-uri-3.0.5.tgz",
+ "integrity": "sha512-VPeQ7+wH0itvQxnG+lIzWgkysKIr3L9sslimFW55rHMdGu/qCQ5z5h9zq4gI8uBtqkpHhsF4Z/OwExufUCThew==",
+ "dev": true,
+ "engines": {
+ "node": ">=6.0.0"
+ }
+ },
+ "node_modules/@jridgewell/sourcemap-codec": {
+ "version": "1.4.11",
+ "resolved": "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.4.11.tgz",
+ "integrity": "sha512-Fg32GrJo61m+VqYSdRSjRXMjQ06j8YIYfcTqndLYVAaHmroZHLJZCydsWBOTDqXS2v+mjxohBWEMfg97GXmYQg==",
+ "dev": true
+ },
+ "node_modules/@jridgewell/trace-mapping": {
+ "version": "0.3.8",
+ "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.8.tgz",
+ "integrity": "sha512-zdpaWDz5IEyHlu1EO+B+qRHmJkSxMVV6SXngDry9n1ZqslLXFH9Dw6lRqDidm/sOJAWdRltJsmZ1SK28/uZKsw==",
+ "dev": true,
+ "dependencies": {
+ "@jridgewell/resolve-uri": "^3.0.3",
+ "@jridgewell/sourcemap-codec": "^1.4.10"
+ }
+ },
+ "node_modules/@mdx-js/util": {
+ "version": "1.6.22",
+ "resolved": "https://registry.npmjs.org/@mdx-js/util/-/util-1.6.22.tgz",
+ "integrity": "sha512-H1rQc1ZOHANWBvPcW+JpGwr+juXSxM8Q8YCkm3GhZd8REu1fHR3z99CErO1p9pkcfcxZnMdIZdIsXkOHY0NilA==",
+ "dev": true,
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/unified"
+ }
+ },
+ "node_modules/@next/env": {
+ "version": "12.3.1",
+ "resolved": "https://registry.npmjs.org/@next/env/-/env-12.3.1.tgz",
+ "integrity": "sha512-9P9THmRFVKGKt9DYqeC2aKIxm8rlvkK38V1P1sRE7qyoPBIs8l9oo79QoSdPtOWfzkbDAVUqvbQGgTMsb8BtJg==",
+ "dev": true
+ },
+ "node_modules/@next/eslint-plugin-next": {
+ "version": "13.2.4",
+ "resolved": "https://registry.npmjs.org/@next/eslint-plugin-next/-/eslint-plugin-next-13.2.4.tgz",
+ "integrity": "sha512-ck1lI+7r1mMJpqLNa3LJ5pxCfOB1lfJncKmRJeJxcJqcngaFwylreLP7da6Rrjr6u2gVRTfmnkSkjc80IiQCwQ==",
+ "dev": true,
+ "dependencies": {
+ "glob": "7.1.7"
+ }
+ },
+ "node_modules/@next/swc-android-arm-eabi": {
+ "version": "12.3.1",
+ "resolved": "https://registry.npmjs.org/@next/swc-android-arm-eabi/-/swc-android-arm-eabi-12.3.1.tgz",
+ "integrity": "sha512-i+BvKA8tB//srVPPQxIQN5lvfROcfv4OB23/L1nXznP+N/TyKL8lql3l7oo2LNhnH66zWhfoemg3Q4VJZSruzQ==",
+ "cpu": [
+ "arm"
+ ],
+ "dev": true,
+ "optional": true,
+ "os": [
+ "android"
+ ],
+ "engines": {
+ "node": ">= 10"
+ }
+ },
+ "node_modules/@next/swc-android-arm64": {
+ "version": "12.3.1",
+ "resolved": "https://registry.npmjs.org/@next/swc-android-arm64/-/swc-android-arm64-12.3.1.tgz",
+ "integrity": "sha512-CmgU2ZNyBP0rkugOOqLnjl3+eRpXBzB/I2sjwcGZ7/Z6RcUJXK5Evz+N0ucOxqE4cZ3gkTeXtSzRrMK2mGYV8Q==",
+ "cpu": [
+ "arm64"
+ ],
+ "dev": true,
+ "optional": true,
+ "os": [
+ "android"
+ ],
+ "engines": {
+ "node": ">= 10"
+ }
+ },
+ "node_modules/@next/swc-darwin-arm64": {
+ "version": "12.3.1",
+ "resolved": "https://registry.npmjs.org/@next/swc-darwin-arm64/-/swc-darwin-arm64-12.3.1.tgz",
+ "integrity": "sha512-hT/EBGNcu0ITiuWDYU9ur57Oa4LybD5DOQp4f22T6zLfpoBMfBibPtR8XktXmOyFHrL/6FC2p9ojdLZhWhvBHg==",
+ "cpu": [
+ "arm64"
+ ],
+ "dev": true,
+ "optional": true,
+ "os": [
+ "darwin"
+ ],
+ "engines": {
+ "node": ">= 10"
+ }
+ },
+ "node_modules/@next/swc-darwin-x64": {
+ "version": "12.3.1",
+ "resolved": "https://registry.npmjs.org/@next/swc-darwin-x64/-/swc-darwin-x64-12.3.1.tgz",
+ "integrity": "sha512-9S6EVueCVCyGf2vuiLiGEHZCJcPAxglyckTZcEwLdJwozLqN0gtS0Eq0bQlGS3dH49Py/rQYpZ3KVWZ9BUf/WA==",
+ "cpu": [
+ "x64"
+ ],
+ "dev": true,
+ "optional": true,
+ "os": [
+ "darwin"
+ ],
+ "engines": {
+ "node": ">= 10"
+ }
+ },
+ "node_modules/@next/swc-freebsd-x64": {
+ "version": "12.3.1",
+ "resolved": "https://registry.npmjs.org/@next/swc-freebsd-x64/-/swc-freebsd-x64-12.3.1.tgz",
+ "integrity": "sha512-qcuUQkaBZWqzM0F1N4AkAh88lLzzpfE6ImOcI1P6YeyJSsBmpBIV8o70zV+Wxpc26yV9vpzb+e5gCyxNjKJg5Q==",
+ "cpu": [
+ "x64"
+ ],
+ "dev": true,
+ "optional": true,
+ "os": [
+ "freebsd"
+ ],
+ "engines": {
+ "node": ">= 10"
+ }
+ },
+ "node_modules/@next/swc-linux-arm-gnueabihf": {
+ "version": "12.3.1",
+ "resolved": "https://registry.npmjs.org/@next/swc-linux-arm-gnueabihf/-/swc-linux-arm-gnueabihf-12.3.1.tgz",
+ "integrity": "sha512-diL9MSYrEI5nY2wc/h/DBewEDUzr/DqBjIgHJ3RUNtETAOB3spMNHvJk2XKUDjnQuluLmFMloet9tpEqU2TT9w==",
+ "cpu": [
+ "arm"
+ ],
+ "dev": true,
+ "optional": true,
+ "os": [
+ "linux"
+ ],
+ "engines": {
+ "node": ">= 10"
+ }
+ },
+ "node_modules/@next/swc-linux-arm64-gnu": {
+ "version": "12.3.1",
+ "resolved": "https://registry.npmjs.org/@next/swc-linux-arm64-gnu/-/swc-linux-arm64-gnu-12.3.1.tgz",
+ "integrity": "sha512-o/xB2nztoaC7jnXU3Q36vGgOolJpsGG8ETNjxM1VAPxRwM7FyGCPHOMk1XavG88QZSQf+1r+POBW0tLxQOJ9DQ==",
+ "cpu": [
+ "arm64"
+ ],
+ "dev": true,
+ "optional": true,
+ "os": [
+ "linux"
+ ],
+ "engines": {
+ "node": ">= 10"
+ }
+ },
+ "node_modules/@next/swc-linux-arm64-musl": {
+ "version": "12.3.1",
+ "resolved": "https://registry.npmjs.org/@next/swc-linux-arm64-musl/-/swc-linux-arm64-musl-12.3.1.tgz",
+ "integrity": "sha512-2WEasRxJzgAmP43glFNhADpe8zB7kJofhEAVNbDJZANp+H4+wq+/cW1CdDi8DqjkShPEA6/ejJw+xnEyDID2jg==",
+ "cpu": [
+ "arm64"
+ ],
+ "dev": true,
+ "optional": true,
+ "os": [
+ "linux"
+ ],
+ "engines": {
+ "node": ">= 10"
+ }
+ },
+ "node_modules/@next/swc-linux-x64-gnu": {
+ "version": "12.3.1",
+ "resolved": "https://registry.npmjs.org/@next/swc-linux-x64-gnu/-/swc-linux-x64-gnu-12.3.1.tgz",
+ "integrity": "sha512-JWEaMyvNrXuM3dyy9Pp5cFPuSSvG82+yABqsWugjWlvfmnlnx9HOQZY23bFq3cNghy5V/t0iPb6cffzRWylgsA==",
+ "cpu": [
+ "x64"
+ ],
+ "dev": true,
+ "optional": true,
+ "os": [
+ "linux"
+ ],
+ "engines": {
+ "node": ">= 10"
+ }
+ },
+ "node_modules/@next/swc-linux-x64-musl": {
+ "version": "12.3.1",
+ "resolved": "https://registry.npmjs.org/@next/swc-linux-x64-musl/-/swc-linux-x64-musl-12.3.1.tgz",
+ "integrity": "sha512-xoEWQQ71waWc4BZcOjmatuvPUXKTv6MbIFzpm4LFeCHsg2iwai0ILmNXf81rJR+L1Wb9ifEke2sQpZSPNz1Iyg==",
+ "cpu": [
+ "x64"
+ ],
+ "dev": true,
+ "optional": true,
+ "os": [
+ "linux"
+ ],
+ "engines": {
+ "node": ">= 10"
+ }
+ },
+ "node_modules/@next/swc-win32-arm64-msvc": {
+ "version": "12.3.1",
+ "resolved": "https://registry.npmjs.org/@next/swc-win32-arm64-msvc/-/swc-win32-arm64-msvc-12.3.1.tgz",
+ "integrity": "sha512-hswVFYQYIeGHE2JYaBVtvqmBQ1CppplQbZJS/JgrVI3x2CurNhEkmds/yqvDONfwfbttTtH4+q9Dzf/WVl3Opw==",
+ "cpu": [
+ "arm64"
+ ],
+ "dev": true,
+ "optional": true,
+ "os": [
+ "win32"
+ ],
+ "engines": {
+ "node": ">= 10"
+ }
+ },
+ "node_modules/@next/swc-win32-ia32-msvc": {
+ "version": "12.3.1",
+ "resolved": "https://registry.npmjs.org/@next/swc-win32-ia32-msvc/-/swc-win32-ia32-msvc-12.3.1.tgz",
+ "integrity": "sha512-Kny5JBehkTbKPmqulr5i+iKntO5YMP+bVM8Hf8UAmjSMVo3wehyLVc9IZkNmcbxi+vwETnQvJaT5ynYBkJ9dWA==",
+ "cpu": [
+ "ia32"
+ ],
+ "dev": true,
+ "optional": true,
+ "os": [
+ "win32"
+ ],
+ "engines": {
+ "node": ">= 10"
+ }
+ },
+ "node_modules/@next/swc-win32-x64-msvc": {
+ "version": "12.3.1",
+ "resolved": "https://registry.npmjs.org/@next/swc-win32-x64-msvc/-/swc-win32-x64-msvc-12.3.1.tgz",
+ "integrity": "sha512-W1ijvzzg+kPEX6LAc+50EYYSEo0FVu7dmTE+t+DM4iOLqgGHoW9uYSz9wCVdkXOEEMP9xhXfGpcSxsfDucyPkA==",
+ "cpu": [
+ "x64"
+ ],
+ "dev": true,
+ "optional": true,
+ "os": [
+ "win32"
+ ],
+ "engines": {
+ "node": ">= 10"
+ }
+ },
+ "node_modules/@nodelib/fs.scandir": {
+ "version": "2.1.5",
+ "resolved": "https://registry.npmjs.org/@nodelib/fs.scandir/-/fs.scandir-2.1.5.tgz",
+ "integrity": "sha512-vq24Bq3ym5HEQm2NKCr3yXDwjc7vTsEThRDnkp2DK9p1uqLR+DHurm/NOTo0KG7HYHU7eppKZj3MyqYuMBf62g==",
+ "dev": true,
+ "dependencies": {
+ "@nodelib/fs.stat": "2.0.5",
+ "run-parallel": "^1.1.9"
+ },
+ "engines": {
+ "node": ">= 8"
+ }
+ },
+ "node_modules/@nodelib/fs.stat": {
+ "version": "2.0.5",
+ "resolved": "https://registry.npmjs.org/@nodelib/fs.stat/-/fs.stat-2.0.5.tgz",
+ "integrity": "sha512-RkhPPp2zrqDAQA/2jNhnztcPAlv64XdhIp7a7454A5ovI7Bukxgt7MX7udwAu3zg1DcpPU0rz3VV1SeaqvY4+A==",
+ "dev": true,
+ "engines": {
+ "node": ">= 8"
+ }
+ },
+ "node_modules/@nodelib/fs.walk": {
+ "version": "1.2.8",
+ "resolved": "https://registry.npmjs.org/@nodelib/fs.walk/-/fs.walk-1.2.8.tgz",
+ "integrity": "sha512-oGB+UxlgWcgQkgwo8GcEGwemoTFt3FIO9ababBmaGwXIoBKZ+GTy0pP185beGg7Llih/NSHSV2XAs1lnznocSg==",
+ "dev": true,
+ "dependencies": {
+ "@nodelib/fs.scandir": "2.1.5",
+ "fastq": "^1.6.0"
+ },
+ "engines": {
+ "node": ">= 8"
+ }
+ },
+ "node_modules/@pkgr/utils": {
+ "version": "2.3.1",
+ "resolved": "https://registry.npmjs.org/@pkgr/utils/-/utils-2.3.1.tgz",
+ "integrity": "sha512-wfzX8kc1PMyUILA+1Z/EqoE4UCXGy0iRGMhPwdfae1+f0OXlLqCk+By+aMzgJBzR9AzS4CDizioG6Ss1gvAFJw==",
+ "dev": true,
+ "dependencies": {
+ "cross-spawn": "^7.0.3",
+ "is-glob": "^4.0.3",
+ "open": "^8.4.0",
+ "picocolors": "^1.0.0",
+ "tiny-glob": "^0.2.9",
+ "tslib": "^2.4.0"
+ },
+ "engines": {
+ "node": "^12.20.0 || ^14.18.0 || >=16.0.0"
+ },
+ "funding": {
+ "url": "https://opencollective.com/unts"
+ }
+ },
+ "node_modules/@pkgr/utils/node_modules/open": {
+ "version": "8.4.2",
+ "resolved": "https://registry.npmjs.org/open/-/open-8.4.2.tgz",
+ "integrity": "sha512-7x81NCL719oNbsq/3mh+hVrAWmFuEYUqrq/Iw3kUzH8ReypT9QQ0BLoJS7/G9k6N81XjW4qHWtjWwe/9eLy1EQ==",
+ "dev": true,
+ "dependencies": {
+ "define-lazy-prop": "^2.0.0",
+ "is-docker": "^2.1.1",
+ "is-wsl": "^2.2.0"
+ },
+ "engines": {
+ "node": ">=12"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
+ "node_modules/@pkgr/utils/node_modules/tslib": {
+ "version": "2.5.0",
+ "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.5.0.tgz",
+ "integrity": "sha512-336iVw3rtn2BUK7ORdIAHTyxHGRIHVReokCR3XjbckJMK7ms8FysBfhLR8IXnAgy7T0PTPNBWKiH514FOW/WSg==",
+ "dev": true
+ },
+ "node_modules/@rushstack/eslint-patch": {
+ "version": "1.2.0",
+ "resolved": "https://registry.npmjs.org/@rushstack/eslint-patch/-/eslint-patch-1.2.0.tgz",
+ "integrity": "sha512-sXo/qW2/pAcmT43VoRKOJbDOfV3cYpq3szSVfIThQXNt+E4DfKj361vaAt3c88U5tPUxzEswam7GW48PJqtKAg==",
+ "dev": true
+ },
+ "node_modules/@sinonjs/commons": {
+ "version": "1.8.3",
+ "resolved": "https://registry.npmjs.org/@sinonjs/commons/-/commons-1.8.3.tgz",
+ "integrity": "sha512-xkNcLAn/wZaX14RPlwizcKicDk9G3F8m2nU3L7Ukm5zBgTwiT0wsoFAHx9Jq56fJA1z/7uKGtCRu16sOUCLIHQ==",
+ "dev": true,
+ "peer": true,
+ "dependencies": {
+ "type-detect": "4.0.8"
+ }
+ },
+ "node_modules/@sinonjs/fake-timers": {
+ "version": "6.0.1",
+ "resolved": "https://registry.npmjs.org/@sinonjs/fake-timers/-/fake-timers-6.0.1.tgz",
+ "integrity": "sha512-MZPUxrmFubI36XS1DI3qmI0YdN1gks62JtFZvxR67ljjSNCeK6U08Zx4msEWOXuofgqUt6zPHSi1H9fbjR/NRA==",
+ "dev": true,
+ "peer": true,
+ "dependencies": {
+ "@sinonjs/commons": "^1.7.0"
+ }
+ },
+ "node_modules/@stylelint/postcss-css-in-js": {
+ "version": "0.37.2",
+ "resolved": "https://registry.npmjs.org/@stylelint/postcss-css-in-js/-/postcss-css-in-js-0.37.2.tgz",
+ "integrity": "sha512-nEhsFoJurt8oUmieT8qy4nk81WRHmJynmVwn/Vts08PL9fhgIsMhk1GId5yAN643OzqEEb5S/6At2TZW7pqPDA==",
+ "dev": true,
+ "dependencies": {
+ "@babel/core": ">=7.9.0"
+ },
+ "peerDependencies": {
+ "postcss": ">=7.0.0",
+ "postcss-syntax": ">=0.36.2"
+ }
+ },
+ "node_modules/@stylelint/postcss-markdown": {
+ "version": "0.36.2",
+ "resolved": "https://registry.npmjs.org/@stylelint/postcss-markdown/-/postcss-markdown-0.36.2.tgz",
+ "integrity": "sha512-2kGbqUVJUGE8dM+bMzXG/PYUWKkjLIkRLWNh39OaADkiabDRdw8ATFCgbMz5xdIcvwspPAluSL7uY+ZiTWdWmQ==",
+ "deprecated": "Use the original unforked package instead: postcss-markdown",
+ "dev": true,
+ "dependencies": {
+ "remark": "^13.0.0",
+ "unist-util-find-all-after": "^3.0.2"
+ },
+ "peerDependencies": {
+ "postcss": ">=7.0.0",
+ "postcss-syntax": ">=0.36.2"
+ }
+ },
+ "node_modules/@swc/helpers": {
+ "version": "0.4.11",
+ "resolved": "https://registry.npmjs.org/@swc/helpers/-/helpers-0.4.11.tgz",
+ "integrity": "sha512-rEUrBSGIoSFuYxwBYtlUFMlE2CwGhmW+w9355/5oduSw8e5h2+Tj4UrAGNNgP9915++wj5vkQo0UuOBqOAq4nw==",
+ "dev": true,
+ "dependencies": {
+ "tslib": "^2.4.0"
+ }
+ },
+ "node_modules/@swc/helpers/node_modules/tslib": {
+ "version": "2.4.0",
+ "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.4.0.tgz",
+ "integrity": "sha512-d6xOpEDfsi2CZVlPQzGeux8XMwLT9hssAsaPYExaQMuYskwb+x1x7J371tWlbBdWHroy99KnVB6qIkUbs5X3UQ==",
+ "dev": true
+ },
+ "node_modules/@tootallnate/once": {
+ "version": "1.1.2",
+ "resolved": "https://registry.npmjs.org/@tootallnate/once/-/once-1.1.2.tgz",
+ "integrity": "sha512-RbzJvlNzmRq5c3O09UipeuXno4tA1FE6ikOjxZK0tuxVv3412l64l5t1W5pj4+rJq9vpkm/kwiR07aZXnsKPxw==",
+ "dev": true,
+ "peer": true,
+ "engines": {
+ "node": ">= 6"
+ }
+ },
+ "node_modules/@types/babel__core": {
+ "version": "7.1.19",
+ "resolved": "https://registry.npmjs.org/@types/babel__core/-/babel__core-7.1.19.tgz",
+ "integrity": "sha512-WEOTgRsbYkvA/KCsDwVEGkd7WAr1e3g31VHQ8zy5gul/V1qKullU/BU5I68X5v7V3GnB9eotmom4v5a5gjxorw==",
+ "dev": true,
+ "peer": true,
+ "dependencies": {
+ "@babel/parser": "^7.1.0",
+ "@babel/types": "^7.0.0",
+ "@types/babel__generator": "*",
+ "@types/babel__template": "*",
+ "@types/babel__traverse": "*"
+ }
+ },
+ "node_modules/@types/babel__generator": {
+ "version": "7.6.4",
+ "resolved": "https://registry.npmjs.org/@types/babel__generator/-/babel__generator-7.6.4.tgz",
+ "integrity": "sha512-tFkciB9j2K755yrTALxD44McOrk+gfpIpvC3sxHjRawj6PfnQxrse4Clq5y/Rq+G3mrBurMax/lG8Qn2t9mSsg==",
+ "dev": true,
+ "peer": true,
+ "dependencies": {
+ "@babel/types": "^7.0.0"
+ }
+ },
+ "node_modules/@types/babel__template": {
+ "version": "7.4.1",
+ "resolved": "https://registry.npmjs.org/@types/babel__template/-/babel__template-7.4.1.tgz",
+ "integrity": "sha512-azBFKemX6kMg5Io+/rdGT0dkGreboUVR0Cdm3fz9QJWpaQGJRQXl7C+6hOTCZcMll7KFyEQpgbYI2lHdsS4U7g==",
+ "dev": true,
+ "peer": true,
+ "dependencies": {
+ "@babel/parser": "^7.1.0",
+ "@babel/types": "^7.0.0"
+ }
+ },
+ "node_modules/@types/babel__traverse": {
+ "version": "7.17.0",
+ "resolved": "https://registry.npmjs.org/@types/babel__traverse/-/babel__traverse-7.17.0.tgz",
+ "integrity": "sha512-r8aveDbd+rzGP+ykSdF3oPuTVRWRfbBiHl0rVDM2yNEmSMXfkObQLV46b4RnCv3Lra51OlfnZhkkFaDl2MIRaA==",
+ "dev": true,
+ "peer": true,
+ "dependencies": {
+ "@babel/types": "^7.3.0"
+ }
+ },
+ "node_modules/@types/graceful-fs": {
+ "version": "4.1.5",
+ "resolved": "https://registry.npmjs.org/@types/graceful-fs/-/graceful-fs-4.1.5.tgz",
+ "integrity": "sha512-anKkLmZZ+xm4p8JWBf4hElkM4XR+EZeA2M9BAkkTldmcyDY4mbdIJnRghDJH3Ov5ooY7/UAoENtmdMSkaAd7Cw==",
+ "dev": true,
+ "peer": true,
+ "dependencies": {
+ "@types/node": "*"
+ }
+ },
+ "node_modules/@types/istanbul-lib-coverage": {
+ "version": "2.0.4",
+ "resolved": "https://registry.npmjs.org/@types/istanbul-lib-coverage/-/istanbul-lib-coverage-2.0.4.tgz",
+ "integrity": "sha512-z/QT1XN4K4KYuslS23k62yDIDLwLFkzxOuMplDtObz0+y7VqJCaO2o+SPwHCvLFZh7xazvvoor2tA/hPz9ee7g==",
+ "dev": true
+ },
+ "node_modules/@types/istanbul-lib-report": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/@types/istanbul-lib-report/-/istanbul-lib-report-3.0.0.tgz",
+ "integrity": "sha512-plGgXAPfVKFoYfa9NpYDAkseG+g6Jr294RqeqcqDixSbU34MZVJRi/P+7Y8GDpzkEwLaGZZOpKIEmeVZNtKsrg==",
+ "dev": true,
+ "dependencies": {
+ "@types/istanbul-lib-coverage": "*"
+ }
+ },
+ "node_modules/@types/istanbul-reports": {
+ "version": "3.0.1",
+ "resolved": "https://registry.npmjs.org/@types/istanbul-reports/-/istanbul-reports-3.0.1.tgz",
+ "integrity": "sha512-c3mAZEuK0lvBp8tmuL74XRKn1+y2dcwOUpH7x4WrF6gk1GIgiluDRgMYQtw2OFcBvAJWlt6ASU3tSqxp0Uu0Aw==",
+ "dev": true,
+ "dependencies": {
+ "@types/istanbul-lib-report": "*"
+ }
+ },
+ "node_modules/@types/json-schema": {
+ "version": "7.0.11",
+ "resolved": "https://registry.npmjs.org/@types/json-schema/-/json-schema-7.0.11.tgz",
+ "integrity": "sha512-wOuvG1SN4Us4rez+tylwwwCV1psiNVOkJeM3AUWUNWg/jDQY2+HE/444y5gc+jBmRqASOm2Oeh5c1axHobwRKQ==",
+ "dev": true
+ },
+ "node_modules/@types/json5": {
+ "version": "0.0.29",
+ "resolved": "https://registry.npmjs.org/@types/json5/-/json5-0.0.29.tgz",
+ "integrity": "sha512-dRLjCWHYg4oaA77cxO64oO+7JwCwnIzkZPdrrC71jQmQtlhM556pwKo5bUzqvZndkVbeFLIIi+9TC40JNF5hNQ==",
+ "dev": true
+ },
+ "node_modules/@types/mdast": {
+ "version": "3.0.10",
+ "resolved": "https://registry.npmjs.org/@types/mdast/-/mdast-3.0.10.tgz",
+ "integrity": "sha512-W864tg/Osz1+9f4lrGTZpCSO5/z4608eUp19tbozkq2HJK6i3z1kT0H9tlADXuYIb1YYOBByU4Jsqkk75q48qA==",
+ "dev": true,
+ "dependencies": {
+ "@types/unist": "*"
+ }
+ },
+ "node_modules/@types/minimist": {
+ "version": "1.2.2",
+ "resolved": "https://registry.npmjs.org/@types/minimist/-/minimist-1.2.2.tgz",
+ "integrity": "sha512-jhuKLIRrhvCPLqwPcx6INqmKeiA5EWrsCOPhrlFSrbrmU4ZMPjj5Ul/oLCMDO98XRUIwVm78xICz4EPCektzeQ==",
+ "dev": true
+ },
+ "node_modules/@types/node": {
+ "version": "17.0.25",
+ "resolved": "https://registry.npmjs.org/@types/node/-/node-17.0.25.tgz",
+ "integrity": "sha512-wANk6fBrUwdpY4isjWrKTufkrXdu1D2YHCot2fD/DfWxF5sMrVSA+KN7ydckvaTCh0HiqX9IVl0L5/ZoXg5M7w==",
+ "dev": true
+ },
+ "node_modules/@types/normalize-package-data": {
+ "version": "2.4.1",
+ "resolved": "https://registry.npmjs.org/@types/normalize-package-data/-/normalize-package-data-2.4.1.tgz",
+ "integrity": "sha512-Gj7cI7z+98M282Tqmp2K5EIsoouUEzbBJhQQzDE3jSIRk6r9gsz0oUokqIUR4u1R3dMHo0pDHM7sNOHyhulypw==",
+ "dev": true
+ },
+ "node_modules/@types/parse-json": {
+ "version": "4.0.0",
+ "resolved": "https://registry.npmjs.org/@types/parse-json/-/parse-json-4.0.0.tgz",
+ "integrity": "sha512-//oorEZjL6sbPcKUaCdIGlIUeH26mgzimjBB77G6XRgnDl/L5wOnpyBGRe/Mmf5CVW3PwEBE1NjiMZ/ssFh4wA==",
+ "dev": true
+ },
+ "node_modules/@types/prettier": {
+ "version": "2.6.0",
+ "resolved": "https://registry.npmjs.org/@types/prettier/-/prettier-2.6.0.tgz",
+ "integrity": "sha512-G/AdOadiZhnJp0jXCaBQU449W2h716OW/EoXeYkCytxKL06X1WCXB4DZpp8TpZ8eyIJVS1cw4lrlkkSYU21cDw==",
+ "dev": true,
+ "peer": true
+ },
+ "node_modules/@types/semver": {
+ "version": "7.3.13",
+ "resolved": "https://registry.npmjs.org/@types/semver/-/semver-7.3.13.tgz",
+ "integrity": "sha512-21cFJr9z3g5dW8B0CVI9g2O9beqaThGQ6ZFBqHfwhzLDKUxaqTIy3vnfah/UPkfOiF2pLq+tGz+W8RyCskuslw==",
+ "dev": true
+ },
+ "node_modules/@types/stack-utils": {
+ "version": "2.0.1",
+ "resolved": "https://registry.npmjs.org/@types/stack-utils/-/stack-utils-2.0.1.tgz",
+ "integrity": "sha512-Hl219/BT5fLAaz6NDkSuhzasy49dwQS/DSdu4MdggFB8zcXv7vflBI3xp7FEmkmdDkBUI2bPUNeMttp2knYdxw==",
+ "dev": true,
+ "peer": true
+ },
+ "node_modules/@types/supports-color": {
+ "version": "8.1.1",
+ "resolved": "https://registry.npmjs.org/@types/supports-color/-/supports-color-8.1.1.tgz",
+ "integrity": "sha512-dPWnWsf+kzIG140B8z2w3fr5D03TLWbOAFQl45xUpI3vcizeXriNR5VYkWZ+WTMsUHqZ9Xlt3hrxGNANFyNQfw==",
+ "dev": true
+ },
+ "node_modules/@types/unist": {
+ "version": "2.0.6",
+ "resolved": "https://registry.npmjs.org/@types/unist/-/unist-2.0.6.tgz",
+ "integrity": "sha512-PBjIUxZHOuj0R15/xuwJYjFi+KZdNFrehocChv4g5hu6aFroHue8m0lBP0POdK2nKzbw0cgV1mws8+V/JAcEkQ==",
+ "dev": true
+ },
+ "node_modules/@types/yargs": {
+ "version": "15.0.14",
+ "resolved": "https://registry.npmjs.org/@types/yargs/-/yargs-15.0.14.tgz",
+ "integrity": "sha512-yEJzHoxf6SyQGhBhIYGXQDSCkJjB6HohDShto7m8vaKg9Yp0Yn8+71J9eakh2bnPg6BfsH9PRMhiRTZnd4eXGQ==",
+ "dev": true,
+ "dependencies": {
+ "@types/yargs-parser": "*"
+ }
+ },
+ "node_modules/@types/yargs-parser": {
+ "version": "21.0.0",
+ "resolved": "https://registry.npmjs.org/@types/yargs-parser/-/yargs-parser-21.0.0.tgz",
+ "integrity": "sha512-iO9ZQHkZxHn4mSakYV0vFHAVDyEOIJQrV2uZ06HxEPcx+mt8swXoZHIbaaJ2crJYFfErySgktuTZ3BeLz+XmFA==",
+ "dev": true
+ },
+ "node_modules/@typescript-eslint/eslint-plugin": {
+ "version": "5.55.0",
+ "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-5.55.0.tgz",
+ "integrity": "sha512-IZGc50rtbjk+xp5YQoJvmMPmJEYoC53SiKPXyqWfv15XoD2Y5Kju6zN0DwlmaGJp1Iw33JsWJcQ7nw0lGCGjVg==",
+ "dev": true,
+ "dependencies": {
+ "@eslint-community/regexpp": "^4.4.0",
+ "@typescript-eslint/scope-manager": "5.55.0",
+ "@typescript-eslint/type-utils": "5.55.0",
+ "@typescript-eslint/utils": "5.55.0",
+ "debug": "^4.3.4",
+ "grapheme-splitter": "^1.0.4",
+ "ignore": "^5.2.0",
+ "natural-compare-lite": "^1.4.0",
+ "semver": "^7.3.7",
+ "tsutils": "^3.21.0"
+ },
+ "engines": {
+ "node": "^12.22.0 || ^14.17.0 || >=16.0.0"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/typescript-eslint"
+ },
+ "peerDependencies": {
+ "@typescript-eslint/parser": "^5.0.0",
+ "eslint": "^6.0.0 || ^7.0.0 || ^8.0.0"
+ },
+ "peerDependenciesMeta": {
+ "typescript": {
+ "optional": true
+ }
+ }
+ },
+ "node_modules/@typescript-eslint/parser": {
+ "version": "5.55.0",
+ "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-5.55.0.tgz",
+ "integrity": "sha512-ppvmeF7hvdhUUZWSd2EEWfzcFkjJzgNQzVST22nzg958CR+sphy8A6K7LXQZd6V75m1VKjp+J4g/PCEfSCmzhw==",
+ "dev": true,
+ "dependencies": {
+ "@typescript-eslint/scope-manager": "5.55.0",
+ "@typescript-eslint/types": "5.55.0",
+ "@typescript-eslint/typescript-estree": "5.55.0",
+ "debug": "^4.3.4"
+ },
+ "engines": {
+ "node": "^12.22.0 || ^14.17.0 || >=16.0.0"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/typescript-eslint"
+ },
+ "peerDependencies": {
+ "eslint": "^6.0.0 || ^7.0.0 || ^8.0.0"
+ },
+ "peerDependenciesMeta": {
+ "typescript": {
+ "optional": true
+ }
+ }
+ },
+ "node_modules/@typescript-eslint/scope-manager": {
+ "version": "5.55.0",
+ "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-5.55.0.tgz",
+ "integrity": "sha512-OK+cIO1ZGhJYNCL//a3ROpsd83psf4dUJ4j7pdNVzd5DmIk+ffkuUIX2vcZQbEW/IR41DYsfJTB19tpCboxQuw==",
+ "dev": true,
+ "dependencies": {
+ "@typescript-eslint/types": "5.55.0",
+ "@typescript-eslint/visitor-keys": "5.55.0"
+ },
+ "engines": {
+ "node": "^12.22.0 || ^14.17.0 || >=16.0.0"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/typescript-eslint"
+ }
+ },
+ "node_modules/@typescript-eslint/type-utils": {
+ "version": "5.55.0",
+ "resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-5.55.0.tgz",
+ "integrity": "sha512-ObqxBgHIXj8rBNm0yh8oORFrICcJuZPZTqtAFh0oZQyr5DnAHZWfyw54RwpEEH+fD8suZaI0YxvWu5tYE/WswA==",
+ "dev": true,
+ "dependencies": {
+ "@typescript-eslint/typescript-estree": "5.55.0",
+ "@typescript-eslint/utils": "5.55.0",
+ "debug": "^4.3.4",
+ "tsutils": "^3.21.0"
+ },
+ "engines": {
+ "node": "^12.22.0 || ^14.17.0 || >=16.0.0"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/typescript-eslint"
+ },
+ "peerDependencies": {
+ "eslint": "*"
+ },
+ "peerDependenciesMeta": {
+ "typescript": {
+ "optional": true
+ }
+ }
+ },
+ "node_modules/@typescript-eslint/types": {
+ "version": "5.55.0",
+ "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-5.55.0.tgz",
+ "integrity": "sha512-M4iRh4AG1ChrOL6Y+mETEKGeDnT7Sparn6fhZ5LtVJF1909D5O4uqK+C5NPbLmpfZ0XIIxCdwzKiijpZUOvOug==",
+ "dev": true,
+ "engines": {
+ "node": "^12.22.0 || ^14.17.0 || >=16.0.0"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/typescript-eslint"
+ }
+ },
+ "node_modules/@typescript-eslint/typescript-estree": {
+ "version": "5.55.0",
+ "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-5.55.0.tgz",
+ "integrity": "sha512-I7X4A9ovA8gdpWMpr7b1BN9eEbvlEtWhQvpxp/yogt48fy9Lj3iE3ild/1H3jKBBIYj5YYJmS2+9ystVhC7eaQ==",
+ "dev": true,
+ "dependencies": {
+ "@typescript-eslint/types": "5.55.0",
+ "@typescript-eslint/visitor-keys": "5.55.0",
+ "debug": "^4.3.4",
+ "globby": "^11.1.0",
+ "is-glob": "^4.0.3",
+ "semver": "^7.3.7",
+ "tsutils": "^3.21.0"
+ },
+ "engines": {
+ "node": "^12.22.0 || ^14.17.0 || >=16.0.0"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/typescript-eslint"
+ },
+ "peerDependenciesMeta": {
+ "typescript": {
+ "optional": true
+ }
+ }
+ },
+ "node_modules/@typescript-eslint/typescript-estree/node_modules/globby": {
+ "version": "11.1.0",
+ "resolved": "https://registry.npmjs.org/globby/-/globby-11.1.0.tgz",
+ "integrity": "sha512-jhIXaOzy1sb8IyocaruWSn1TjmnBVs8Ayhcy83rmxNJ8q2uWKCAj3CnJY+KpGSXCueAPc0i05kVvVKtP1t9S3g==",
+ "dev": true,
+ "dependencies": {
+ "array-union": "^2.1.0",
+ "dir-glob": "^3.0.1",
+ "fast-glob": "^3.2.9",
+ "ignore": "^5.2.0",
+ "merge2": "^1.4.1",
+ "slash": "^3.0.0"
+ },
+ "engines": {
+ "node": ">=10"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
+ "node_modules/@typescript-eslint/utils": {
+ "version": "5.55.0",
+ "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-5.55.0.tgz",
+ "integrity": "sha512-FkW+i2pQKcpDC3AY6DU54yl8Lfl14FVGYDgBTyGKB75cCwV3KpkpTMFi9d9j2WAJ4271LR2HeC5SEWF/CZmmfw==",
+ "dev": true,
+ "dependencies": {
+ "@eslint-community/eslint-utils": "^4.2.0",
+ "@types/json-schema": "^7.0.9",
+ "@types/semver": "^7.3.12",
+ "@typescript-eslint/scope-manager": "5.55.0",
+ "@typescript-eslint/types": "5.55.0",
+ "@typescript-eslint/typescript-estree": "5.55.0",
+ "eslint-scope": "^5.1.1",
+ "semver": "^7.3.7"
+ },
+ "engines": {
+ "node": "^12.22.0 || ^14.17.0 || >=16.0.0"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/typescript-eslint"
+ },
+ "peerDependencies": {
+ "eslint": "^6.0.0 || ^7.0.0 || ^8.0.0"
+ }
+ },
+ "node_modules/@typescript-eslint/visitor-keys": {
+ "version": "5.55.0",
+ "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-5.55.0.tgz",
+ "integrity": "sha512-q2dlHHwWgirKh1D3acnuApXG+VNXpEY5/AwRxDVuEQpxWaB0jCDe0jFMVMALJ3ebSfuOVE8/rMS+9ZOYGg1GWw==",
+ "dev": true,
+ "dependencies": {
+ "@typescript-eslint/types": "5.55.0",
+ "eslint-visitor-keys": "^3.3.0"
+ },
+ "engines": {
+ "node": "^12.22.0 || ^14.17.0 || >=16.0.0"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/typescript-eslint"
+ }
+ },
+ "node_modules/abab": {
+ "version": "2.0.6",
+ "resolved": "https://registry.npmjs.org/abab/-/abab-2.0.6.tgz",
+ "integrity": "sha512-j2afSsaIENvHZN2B8GOpF566vZ5WVk5opAiMTvWgaQT8DkbOqsTfvNAvHoRGU2zzP8cPoqys+xHTRDWW8L+/BA==",
+ "dev": true,
+ "peer": true
+ },
+ "node_modules/acorn": {
+ "version": "8.8.2",
+ "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.8.2.tgz",
+ "integrity": "sha512-xjIYgE8HBrkpd/sJqOGNspf8uHG+NOHGOw6a/Urj8taM2EXfdNAH2oFcPeIFfsv3+kz/mJrS5VuMqbNLjCa2vw==",
+ "dev": true,
+ "bin": {
+ "acorn": "bin/acorn"
+ },
+ "engines": {
+ "node": ">=0.4.0"
+ }
+ },
+ "node_modules/acorn-globals": {
+ "version": "6.0.0",
+ "resolved": "https://registry.npmjs.org/acorn-globals/-/acorn-globals-6.0.0.tgz",
+ "integrity": "sha512-ZQl7LOWaF5ePqqcX4hLuv/bLXYQNfNWw2c0/yX/TsPRKamzHcTGQnlCjHT3TsmkOUVEPS3crCxiPfdzE/Trlhg==",
+ "dev": true,
+ "peer": true,
+ "dependencies": {
+ "acorn": "^7.1.1",
+ "acorn-walk": "^7.1.1"
+ }
+ },
+ "node_modules/acorn-globals/node_modules/acorn": {
+ "version": "7.4.1",
+ "resolved": "https://registry.npmjs.org/acorn/-/acorn-7.4.1.tgz",
+ "integrity": "sha512-nQyp0o1/mNdbTO1PO6kHkwSrmgZ0MT/jCCpNiwbUjGoRN4dlBhqJtoQuCnEOKzgTVwg0ZWiCoQy6SxMebQVh8A==",
+ "dev": true,
+ "peer": true,
+ "bin": {
+ "acorn": "bin/acorn"
+ },
+ "engines": {
+ "node": ">=0.4.0"
+ }
+ },
+ "node_modules/acorn-jsx": {
+ "version": "5.3.2",
+ "resolved": "https://registry.npmjs.org/acorn-jsx/-/acorn-jsx-5.3.2.tgz",
+ "integrity": "sha512-rq9s+JNhf0IChjtDXxllJ7g41oZk5SlXtp0LHwyA5cejwn7vKmKp4pPri6YEePv2PU65sAsegbXtIinmDFDXgQ==",
+ "dev": true,
+ "peerDependencies": {
+ "acorn": "^6.0.0 || ^7.0.0 || ^8.0.0"
+ }
+ },
+ "node_modules/acorn-walk": {
+ "version": "7.2.0",
+ "resolved": "https://registry.npmjs.org/acorn-walk/-/acorn-walk-7.2.0.tgz",
+ "integrity": "sha512-OPdCF6GsMIP+Az+aWfAAOEt2/+iVDKE7oy6lJ098aoe59oAmK76qV6Gw60SbZ8jHuG2wH058GF4pLFbYamYrVA==",
+ "dev": true,
+ "peer": true,
+ "engines": {
+ "node": ">=0.4.0"
+ }
+ },
+ "node_modules/agent-base": {
+ "version": "6.0.2",
+ "resolved": "https://registry.npmjs.org/agent-base/-/agent-base-6.0.2.tgz",
+ "integrity": "sha512-RZNwNclF7+MS/8bDg70amg32dyeZGZxiDuQmZxKLAlQjr3jGyLx+4Kkk58UO7D2QdgFIQCovuSuZESne6RG6XQ==",
+ "dev": true,
+ "peer": true,
+ "dependencies": {
+ "debug": "4"
+ },
+ "engines": {
+ "node": ">= 6.0.0"
+ }
+ },
+ "node_modules/aggregate-error": {
+ "version": "3.1.0",
+ "resolved": "https://registry.npmjs.org/aggregate-error/-/aggregate-error-3.1.0.tgz",
+ "integrity": "sha512-4I7Td01quW/RpocfNayFdFVk1qSuoh0E7JrbRJ16nH01HhKFQ88INq9Sd+nd72zqRySlr9BmDA8xlEJ6vJMrYA==",
+ "dev": true,
+ "dependencies": {
+ "clean-stack": "^2.0.0",
+ "indent-string": "^4.0.0"
+ },
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/ajv": {
+ "version": "6.12.6",
+ "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz",
+ "integrity": "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==",
+ "dev": true,
+ "dependencies": {
+ "fast-deep-equal": "^3.1.1",
+ "fast-json-stable-stringify": "^2.0.0",
+ "json-schema-traverse": "^0.4.1",
+ "uri-js": "^4.2.2"
+ },
+ "funding": {
+ "type": "github",
+ "url": "https://github.com/sponsors/epoberezkin"
+ }
+ },
+ "node_modules/ansi-colors": {
+ "version": "4.1.1",
+ "resolved": "https://registry.npmjs.org/ansi-colors/-/ansi-colors-4.1.1.tgz",
+ "integrity": "sha512-JoX0apGbHaUJBNl6yF+p6JAFYZ666/hhCGKN5t9QFjbJQKUU/g8MNbFDbvfrgKXvI1QpZplPOnwIo99lX/AAmA==",
+ "dev": true,
+ "engines": {
+ "node": ">=6"
+ }
+ },
+ "node_modules/ansi-escapes": {
+ "version": "4.3.2",
+ "resolved": "https://registry.npmjs.org/ansi-escapes/-/ansi-escapes-4.3.2.tgz",
+ "integrity": "sha512-gKXj5ALrKWQLsYG9jlTRmR/xKluxHV+Z9QEwNIgCfM1/uwPMCuzVVnh5mwTd+OuBZcwSIMbqssNWRm1lE51QaQ==",
+ "dev": true,
+ "dependencies": {
+ "type-fest": "^0.21.3"
+ },
+ "engines": {
+ "node": ">=8"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
+ "node_modules/ansi-escapes/node_modules/type-fest": {
+ "version": "0.21.3",
+ "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.21.3.tgz",
+ "integrity": "sha512-t0rzBq87m3fVcduHDUFhKmyyX+9eo6WQjZvf51Ea/M0Q7+T374Jp1aUiyUl0GKxp8M/OETVHSDvmkyPgvX+X2w==",
+ "dev": true,
+ "engines": {
+ "node": ">=10"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
+ "node_modules/ansi-regex": {
+ "version": "5.0.1",
+ "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz",
+ "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==",
+ "dev": true,
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/ansi-styles": {
+ "version": "4.3.0",
+ "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz",
+ "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==",
+ "dev": true,
+ "dependencies": {
+ "color-convert": "^2.0.1"
+ },
+ "engines": {
+ "node": ">=8"
+ },
+ "funding": {
+ "url": "https://github.com/chalk/ansi-styles?sponsor=1"
+ }
+ },
+ "node_modules/anymatch": {
+ "version": "3.1.2",
+ "resolved": "https://registry.npmjs.org/anymatch/-/anymatch-3.1.2.tgz",
+ "integrity": "sha512-P43ePfOAIupkguHUycrc4qJ9kz8ZiuOUijaETwX7THt0Y/GNK7v0aa8rY816xWjZ7rJdA5XdMcpVFTKMq+RvWg==",
+ "dev": true,
+ "peer": true,
+ "dependencies": {
+ "normalize-path": "^3.0.0",
+ "picomatch": "^2.0.4"
+ },
+ "engines": {
+ "node": ">= 8"
+ }
+ },
+ "node_modules/argparse": {
+ "version": "2.0.1",
+ "resolved": "https://registry.npmjs.org/argparse/-/argparse-2.0.1.tgz",
+ "integrity": "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==",
+ "dev": true
+ },
+ "node_modules/aria-query": {
+ "version": "5.1.3",
+ "resolved": "https://registry.npmjs.org/aria-query/-/aria-query-5.1.3.tgz",
+ "integrity": "sha512-R5iJ5lkuHybztUfuOAznmboyjWq8O6sqNqtK7CLOqdydi54VNbORp49mb14KbWgG1QD3JFO9hJdZ+y4KutfdOQ==",
+ "dev": true,
+ "dependencies": {
+ "deep-equal": "^2.0.5"
+ }
+ },
+ "node_modules/arr-diff": {
+ "version": "4.0.0",
+ "resolved": "https://registry.npmjs.org/arr-diff/-/arr-diff-4.0.0.tgz",
+ "integrity": "sha1-1kYQdP6/7HHn4VI1dhoyml3HxSA=",
+ "dev": true,
+ "peer": true,
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
+ "node_modules/arr-flatten": {
+ "version": "1.1.0",
+ "resolved": "https://registry.npmjs.org/arr-flatten/-/arr-flatten-1.1.0.tgz",
+ "integrity": "sha512-L3hKV5R/p5o81R7O02IGnwpDmkp6E982XhtbuwSe3O4qOtMMMtodicASA1Cny2U+aCXcNpml+m4dPsvsJ3jatg==",
+ "dev": true,
+ "peer": true,
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
+ "node_modules/arr-union": {
+ "version": "3.1.0",
+ "resolved": "https://registry.npmjs.org/arr-union/-/arr-union-3.1.0.tgz",
+ "integrity": "sha1-45sJrqne+Gao8gbiiK9jkZuuOcQ=",
+ "dev": true,
+ "peer": true,
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
+ "node_modules/array-buffer-byte-length": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/array-buffer-byte-length/-/array-buffer-byte-length-1.0.0.tgz",
+ "integrity": "sha512-LPuwb2P+NrQw3XhxGc36+XSvuBPopovXYTR9Ew++Du9Yb/bx5AzBfrIsBoj0EZUifjQU+sHL21sseZ3jerWO/A==",
+ "dev": true,
+ "dependencies": {
+ "call-bind": "^1.0.2",
+ "is-array-buffer": "^3.0.1"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/array-includes": {
+ "version": "3.1.6",
+ "resolved": "https://registry.npmjs.org/array-includes/-/array-includes-3.1.6.tgz",
+ "integrity": "sha512-sgTbLvL6cNnw24FnbaDyjmvddQ2ML8arZsgaJhoABMoplz/4QRhtrYS+alr1BUM1Bwp6dhx8vVCBSLG+StwOFw==",
+ "dev": true,
+ "dependencies": {
+ "call-bind": "^1.0.2",
+ "define-properties": "^1.1.4",
+ "es-abstract": "^1.20.4",
+ "get-intrinsic": "^1.1.3",
+ "is-string": "^1.0.7"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/array-union": {
+ "version": "2.1.0",
+ "resolved": "https://registry.npmjs.org/array-union/-/array-union-2.1.0.tgz",
+ "integrity": "sha512-HGyxoOTYUyCM6stUe6EJgnd4EoewAI7zMdfqO+kGjnlZmBDz/cR5pf8r/cR4Wq60sL/p0IkcjUEEPwS3GFrIyw==",
+ "dev": true,
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/array-unique": {
+ "version": "0.3.2",
+ "resolved": "https://registry.npmjs.org/array-unique/-/array-unique-0.3.2.tgz",
+ "integrity": "sha1-qJS3XUvE9s1nnvMkSp/Y9Gri1Cg=",
+ "dev": true,
+ "peer": true,
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
+ "node_modules/array.prototype.flat": {
+ "version": "1.3.1",
+ "resolved": "https://registry.npmjs.org/array.prototype.flat/-/array.prototype.flat-1.3.1.tgz",
+ "integrity": "sha512-roTU0KWIOmJ4DRLmwKd19Otg0/mT3qPNt0Qb3GWW8iObuZXxrjB/pzn0R3hqpRSWg4HCwqx+0vwOnWnvlOyeIA==",
+ "dev": true,
+ "dependencies": {
+ "call-bind": "^1.0.2",
+ "define-properties": "^1.1.4",
+ "es-abstract": "^1.20.4",
+ "es-shim-unscopables": "^1.0.0"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/array.prototype.flatmap": {
+ "version": "1.3.1",
+ "resolved": "https://registry.npmjs.org/array.prototype.flatmap/-/array.prototype.flatmap-1.3.1.tgz",
+ "integrity": "sha512-8UGn9O1FDVvMNB0UlLv4voxRMze7+FpHyF5mSMRjWHUMlpoDViniy05870VlxhfgTnLbpuwTzvD76MTtWxB/mQ==",
+ "dev": true,
+ "dependencies": {
+ "call-bind": "^1.0.2",
+ "define-properties": "^1.1.4",
+ "es-abstract": "^1.20.4",
+ "es-shim-unscopables": "^1.0.0"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/array.prototype.tosorted": {
+ "version": "1.1.1",
+ "resolved": "https://registry.npmjs.org/array.prototype.tosorted/-/array.prototype.tosorted-1.1.1.tgz",
+ "integrity": "sha512-pZYPXPRl2PqWcsUs6LOMn+1f1532nEoPTYowBtqLwAW+W8vSVhkIGnmOX1t/UQjD6YGI0vcD2B1U7ZFGQH9jnQ==",
+ "dev": true,
+ "dependencies": {
+ "call-bind": "^1.0.2",
+ "define-properties": "^1.1.4",
+ "es-abstract": "^1.20.4",
+ "es-shim-unscopables": "^1.0.0",
+ "get-intrinsic": "^1.1.3"
+ }
+ },
+ "node_modules/arrify": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/arrify/-/arrify-1.0.1.tgz",
+ "integrity": "sha1-iYUI2iIm84DfkEcoRWhJwVAaSw0=",
+ "dev": true,
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
+ "node_modules/assign-symbols": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/assign-symbols/-/assign-symbols-1.0.0.tgz",
+ "integrity": "sha1-WWZ/QfrdTyDMvCu5a41Pf3jsA2c=",
+ "dev": true,
+ "peer": true,
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
+ "node_modules/ast-types-flow": {
+ "version": "0.0.7",
+ "resolved": "https://registry.npmjs.org/ast-types-flow/-/ast-types-flow-0.0.7.tgz",
+ "integrity": "sha512-eBvWn1lvIApYMhzQMsu9ciLfkBY499mFZlNqG+/9WR7PVlroQw0vG30cOQQbaKz3sCEc44TAOu2ykzqXSNnwag==",
+ "dev": true
+ },
+ "node_modules/astral-regex": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/astral-regex/-/astral-regex-2.0.0.tgz",
+ "integrity": "sha512-Z7tMw1ytTXt5jqMcOP+OQteU1VuNK9Y02uuJtKQ1Sv69jXQKKg5cibLwGJow8yzZP+eAc18EmLGPal0bp36rvQ==",
+ "dev": true,
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/async": {
+ "version": "3.2.3",
+ "resolved": "https://registry.npmjs.org/async/-/async-3.2.3.tgz",
+ "integrity": "sha512-spZRyzKL5l5BZQrr/6m/SqFdBN0q3OCI0f9rjfBzCMBIP4p75P620rR3gTmaksNOhmzgdxcaxdNfMy6anrbM0g==",
+ "dev": true
+ },
+ "node_modules/asynckit": {
+ "version": "0.4.0",
+ "resolved": "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz",
+ "integrity": "sha1-x57Zf380y48robyXkLzDZkdLS3k=",
+ "dev": true
+ },
+ "node_modules/at-least-node": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/at-least-node/-/at-least-node-1.0.0.tgz",
+ "integrity": "sha512-+q/t7Ekv1EDY2l6Gda6LLiX14rU9TV20Wa3ofeQmwPFZbOMo9DXrLbOjFaaclkXKWidIaopwAObQDqwWtGUjqg==",
+ "dev": true,
+ "engines": {
+ "node": ">= 4.0.0"
+ }
+ },
+ "node_modules/atob": {
+ "version": "2.1.2",
+ "resolved": "https://registry.npmjs.org/atob/-/atob-2.1.2.tgz",
+ "integrity": "sha512-Wm6ukoaOGJi/73p/cl2GvLjTI5JM1k/O14isD73YML8StrH/7/lRFgmg8nICZgD3bZZvjwCGxtMOD3wWNAu8cg==",
+ "dev": true,
+ "peer": true,
+ "bin": {
+ "atob": "bin/atob.js"
+ },
+ "engines": {
+ "node": ">= 4.5.0"
+ }
+ },
+ "node_modules/autoprefixer": {
+ "version": "9.8.8",
+ "resolved": "https://registry.npmjs.org/autoprefixer/-/autoprefixer-9.8.8.tgz",
+ "integrity": "sha512-eM9d/swFopRt5gdJ7jrpCwgvEMIayITpojhkkSMRsFHYuH5bkSQ4p/9qTEHtmNudUZh22Tehu7I6CxAW0IXTKA==",
+ "dev": true,
+ "dependencies": {
+ "browserslist": "^4.12.0",
+ "caniuse-lite": "^1.0.30001109",
+ "normalize-range": "^0.1.2",
+ "num2fraction": "^1.2.2",
+ "picocolors": "^0.2.1",
+ "postcss": "^7.0.32",
+ "postcss-value-parser": "^4.1.0"
+ },
+ "bin": {
+ "autoprefixer": "bin/autoprefixer"
+ },
+ "funding": {
+ "type": "tidelift",
+ "url": "https://tidelift.com/funding/github/npm/autoprefixer"
+ }
+ },
+ "node_modules/autoprefixer/node_modules/picocolors": {
+ "version": "0.2.1",
+ "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-0.2.1.tgz",
+ "integrity": "sha512-cMlDqaLEqfSaW8Z7N5Jw+lyIW869EzT73/F5lhtY9cLGoVxSXznfgfXMO0Z5K0o0Q2TkTXq+0KFsdnSe3jDViA==",
+ "dev": true
+ },
+ "node_modules/autoprefixer/node_modules/postcss": {
+ "version": "7.0.39",
+ "resolved": "https://registry.npmjs.org/postcss/-/postcss-7.0.39.tgz",
+ "integrity": "sha512-yioayjNbHn6z1/Bywyb2Y4s3yvDAeXGOyxqD+LnVOinq6Mdmd++SW2wUNVzavyyHxd6+DxzWGIuosg6P1Rj8uA==",
+ "dev": true,
+ "dependencies": {
+ "picocolors": "^0.2.1",
+ "source-map": "^0.6.1"
+ },
+ "engines": {
+ "node": ">=6.0.0"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/postcss/"
+ }
+ },
+ "node_modules/available-typed-arrays": {
+ "version": "1.0.5",
+ "resolved": "https://registry.npmjs.org/available-typed-arrays/-/available-typed-arrays-1.0.5.tgz",
+ "integrity": "sha512-DMD0KiN46eipeziST1LPP/STfDU0sufISXmjSgvVsoU2tqxctQeASejWcfNtxYKqETM1UxQ8sp2OrSBWpHY6sw==",
+ "dev": true,
+ "engines": {
+ "node": ">= 0.4"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/axe-core": {
+ "version": "4.6.3",
+ "resolved": "https://registry.npmjs.org/axe-core/-/axe-core-4.6.3.tgz",
+ "integrity": "sha512-/BQzOX780JhsxDnPpH4ZiyrJAzcd8AfzFPkv+89veFSr1rcMjuq2JDCwypKaPeB6ljHp9KjXhPpjgCvQlWYuqg==",
+ "dev": true,
+ "engines": {
+ "node": ">=4"
+ }
+ },
+ "node_modules/axobject-query": {
+ "version": "3.1.1",
+ "resolved": "https://registry.npmjs.org/axobject-query/-/axobject-query-3.1.1.tgz",
+ "integrity": "sha512-goKlv8DZrK9hUh975fnHzhNIO4jUnFCfv/dszV5VwUGDFjI6vQ2VwoyjYjYNEbBE8AH87TduWP5uyDR1D+Iteg==",
+ "dev": true,
+ "dependencies": {
+ "deep-equal": "^2.0.5"
+ }
+ },
+ "node_modules/babel-jest": {
+ "version": "26.6.3",
+ "resolved": "https://registry.npmjs.org/babel-jest/-/babel-jest-26.6.3.tgz",
+ "integrity": "sha512-pl4Q+GAVOHwvjrck6jKjvmGhnO3jHX/xuB9d27f+EJZ/6k+6nMuPjorrYp7s++bKKdANwzElBWnLWaObvTnaZA==",
+ "dev": true,
+ "peer": true,
+ "dependencies": {
+ "@jest/transform": "^26.6.2",
+ "@jest/types": "^26.6.2",
+ "@types/babel__core": "^7.1.7",
+ "babel-plugin-istanbul": "^6.0.0",
+ "babel-preset-jest": "^26.6.2",
+ "chalk": "^4.0.0",
+ "graceful-fs": "^4.2.4",
+ "slash": "^3.0.0"
+ },
+ "engines": {
+ "node": ">= 10.14.2"
+ },
+ "peerDependencies": {
+ "@babel/core": "^7.0.0"
+ }
+ },
+ "node_modules/babel-plugin-istanbul": {
+ "version": "6.1.1",
+ "resolved": "https://registry.npmjs.org/babel-plugin-istanbul/-/babel-plugin-istanbul-6.1.1.tgz",
+ "integrity": "sha512-Y1IQok9821cC9onCx5otgFfRm7Lm+I+wwxOx738M/WLPZ9Q42m4IG5W0FNX8WLL2gYMZo3JkuXIH2DOpWM+qwA==",
+ "dev": true,
+ "peer": true,
+ "dependencies": {
+ "@babel/helper-plugin-utils": "^7.0.0",
+ "@istanbuljs/load-nyc-config": "^1.0.0",
+ "@istanbuljs/schema": "^0.1.2",
+ "istanbul-lib-instrument": "^5.0.4",
+ "test-exclude": "^6.0.0"
+ },
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/babel-plugin-istanbul/node_modules/istanbul-lib-instrument": {
+ "version": "5.2.0",
+ "resolved": "https://registry.npmjs.org/istanbul-lib-instrument/-/istanbul-lib-instrument-5.2.0.tgz",
+ "integrity": "sha512-6Lthe1hqXHBNsqvgDzGO6l03XNeu3CrG4RqQ1KM9+l5+jNGpEJfIELx1NS3SEHmJQA8np/u+E4EPRKRiu6m19A==",
+ "dev": true,
+ "peer": true,
+ "dependencies": {
+ "@babel/core": "^7.12.3",
+ "@babel/parser": "^7.14.7",
+ "@istanbuljs/schema": "^0.1.2",
+ "istanbul-lib-coverage": "^3.2.0",
+ "semver": "^6.3.0"
+ },
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/babel-plugin-istanbul/node_modules/semver": {
+ "version": "6.3.0",
+ "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz",
+ "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==",
+ "dev": true,
+ "peer": true,
+ "bin": {
+ "semver": "bin/semver.js"
+ }
+ },
+ "node_modules/babel-plugin-jest-hoist": {
+ "version": "26.6.2",
+ "resolved": "https://registry.npmjs.org/babel-plugin-jest-hoist/-/babel-plugin-jest-hoist-26.6.2.tgz",
+ "integrity": "sha512-PO9t0697lNTmcEHH69mdtYiOIkkOlj9fySqfO3K1eCcdISevLAE0xY59VLLUj0SoiPiTX/JU2CYFpILydUa5Lw==",
+ "dev": true,
+ "peer": true,
+ "dependencies": {
+ "@babel/template": "^7.3.3",
+ "@babel/types": "^7.3.3",
+ "@types/babel__core": "^7.0.0",
+ "@types/babel__traverse": "^7.0.6"
+ },
+ "engines": {
+ "node": ">= 10.14.2"
+ }
+ },
+ "node_modules/babel-preset-current-node-syntax": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/babel-preset-current-node-syntax/-/babel-preset-current-node-syntax-1.0.1.tgz",
+ "integrity": "sha512-M7LQ0bxarkxQoN+vz5aJPsLBn77n8QgTFmo8WK0/44auK2xlCXrYcUxHFxgU7qW5Yzw/CjmLRK2uJzaCd7LvqQ==",
+ "dev": true,
+ "peer": true,
+ "dependencies": {
+ "@babel/plugin-syntax-async-generators": "^7.8.4",
+ "@babel/plugin-syntax-bigint": "^7.8.3",
+ "@babel/plugin-syntax-class-properties": "^7.8.3",
+ "@babel/plugin-syntax-import-meta": "^7.8.3",
+ "@babel/plugin-syntax-json-strings": "^7.8.3",
+ "@babel/plugin-syntax-logical-assignment-operators": "^7.8.3",
+ "@babel/plugin-syntax-nullish-coalescing-operator": "^7.8.3",
+ "@babel/plugin-syntax-numeric-separator": "^7.8.3",
+ "@babel/plugin-syntax-object-rest-spread": "^7.8.3",
+ "@babel/plugin-syntax-optional-catch-binding": "^7.8.3",
+ "@babel/plugin-syntax-optional-chaining": "^7.8.3",
+ "@babel/plugin-syntax-top-level-await": "^7.8.3"
+ },
+ "peerDependencies": {
+ "@babel/core": "^7.0.0"
+ }
+ },
+ "node_modules/babel-preset-jest": {
+ "version": "26.6.2",
+ "resolved": "https://registry.npmjs.org/babel-preset-jest/-/babel-preset-jest-26.6.2.tgz",
+ "integrity": "sha512-YvdtlVm9t3k777c5NPQIv6cxFFFapys25HiUmuSgHwIZhfifweR5c5Sf5nwE3MAbfu327CYSvps8Yx6ANLyleQ==",
+ "dev": true,
+ "peer": true,
+ "dependencies": {
+ "babel-plugin-jest-hoist": "^26.6.2",
+ "babel-preset-current-node-syntax": "^1.0.0"
+ },
+ "engines": {
+ "node": ">= 10.14.2"
+ },
+ "peerDependencies": {
+ "@babel/core": "^7.0.0"
+ }
+ },
+ "node_modules/bail": {
+ "version": "1.0.5",
+ "resolved": "https://registry.npmjs.org/bail/-/bail-1.0.5.tgz",
+ "integrity": "sha512-xFbRxM1tahm08yHBP16MMjVUAvDaBMD38zsM9EMAUN61omwLmKlOpB/Zku5QkjZ8TZ4vn53pj+t518cH0S03RQ==",
+ "dev": true,
+ "funding": {
+ "type": "github",
+ "url": "https://github.com/sponsors/wooorm"
+ }
+ },
+ "node_modules/balanced-match": {
+ "version": "1.0.2",
+ "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz",
+ "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==",
+ "dev": true
+ },
+ "node_modules/base": {
+ "version": "0.11.2",
+ "resolved": "https://registry.npmjs.org/base/-/base-0.11.2.tgz",
+ "integrity": "sha512-5T6P4xPgpp0YDFvSWwEZ4NoE3aM4QBQXDzmVbraCkFj8zHM+mba8SyqB5DbZWyR7mYHo6Y7BdQo3MoA4m0TeQg==",
+ "dev": true,
+ "peer": true,
+ "dependencies": {
+ "cache-base": "^1.0.1",
+ "class-utils": "^0.3.5",
+ "component-emitter": "^1.2.1",
+ "define-property": "^1.0.0",
+ "isobject": "^3.0.1",
+ "mixin-deep": "^1.2.0",
+ "pascalcase": "^0.1.1"
+ },
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
+ "node_modules/base/node_modules/define-property": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/define-property/-/define-property-1.0.0.tgz",
+ "integrity": "sha1-dp66rz9KY6rTr56NMEybvnm/sOY=",
+ "dev": true,
+ "peer": true,
+ "dependencies": {
+ "is-descriptor": "^1.0.0"
+ },
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
+ "node_modules/brace-expansion": {
+ "version": "1.1.11",
+ "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz",
+ "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==",
+ "dev": true,
+ "dependencies": {
+ "balanced-match": "^1.0.0",
+ "concat-map": "0.0.1"
+ }
+ },
+ "node_modules/braces": {
+ "version": "3.0.2",
+ "resolved": "https://registry.npmjs.org/braces/-/braces-3.0.2.tgz",
+ "integrity": "sha512-b8um+L1RzM3WDSzvhm6gIz1yfTbBt6YTlcEKAvsmqCZZFw46z626lVj9j1yEPW33H5H+lBQpZMP1k8l+78Ha0A==",
+ "dev": true,
+ "dependencies": {
+ "fill-range": "^7.0.1"
+ },
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/browser-process-hrtime": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/browser-process-hrtime/-/browser-process-hrtime-1.0.0.tgz",
+ "integrity": "sha512-9o5UecI3GhkpM6DrXr69PblIuWxPKk9Y0jHBRhdocZ2y7YECBFCsHm79Pr3OyR2AvjhDkabFJaDJMYRazHgsow==",
+ "dev": true,
+ "peer": true
+ },
+ "node_modules/browserslist": {
+ "version": "4.20.2",
+ "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.20.2.tgz",
+ "integrity": "sha512-CQOBCqp/9pDvDbx3xfMi+86pr4KXIf2FDkTTdeuYw8OxS9t898LA1Khq57gtufFILXpfgsSx5woNgsBgvGjpsA==",
+ "dev": true,
+ "funding": [
+ {
+ "type": "opencollective",
+ "url": "https://opencollective.com/browserslist"
+ },
+ {
+ "type": "tidelift",
+ "url": "https://tidelift.com/funding/github/npm/browserslist"
+ }
+ ],
+ "dependencies": {
+ "caniuse-lite": "^1.0.30001317",
+ "electron-to-chromium": "^1.4.84",
+ "escalade": "^3.1.1",
+ "node-releases": "^2.0.2",
+ "picocolors": "^1.0.0"
+ },
+ "bin": {
+ "browserslist": "cli.js"
+ },
+ "engines": {
+ "node": "^6 || ^7 || ^8 || ^9 || ^10 || ^11 || ^12 || >=13.7"
+ }
+ },
+ "node_modules/bs-logger": {
+ "version": "0.2.6",
+ "resolved": "https://registry.npmjs.org/bs-logger/-/bs-logger-0.2.6.tgz",
+ "integrity": "sha512-pd8DCoxmbgc7hyPKOvxtqNcjYoOsABPQdcCUjGp3d42VR2CX1ORhk2A87oqqu5R1kk+76nsxZupkmyd+MVtCog==",
+ "dev": true,
+ "dependencies": {
+ "fast-json-stable-stringify": "2.x"
+ },
+ "engines": {
+ "node": ">= 6"
+ }
+ },
+ "node_modules/bser": {
+ "version": "2.1.1",
+ "resolved": "https://registry.npmjs.org/bser/-/bser-2.1.1.tgz",
+ "integrity": "sha512-gQxTNE/GAfIIrmHLUE3oJyp5FO6HRBfhjnw4/wMmA63ZGDJnWBmgY/lyQBpnDUkGmAhbSe39tx2d/iTOAfglwQ==",
+ "dev": true,
+ "peer": true,
+ "dependencies": {
+ "node-int64": "^0.4.0"
+ }
+ },
+ "node_modules/buffer-from": {
+ "version": "1.1.2",
+ "resolved": "https://registry.npmjs.org/buffer-from/-/buffer-from-1.1.2.tgz",
+ "integrity": "sha512-E+XQCRwSbaaiChtv6k6Dwgc+bx+Bs6vuKJHHl5kox/BaKbhiXzqQOwK4cO22yElGp2OCmjwVhT3HmxgyPGnJfQ==",
+ "dev": true
+ },
+ "node_modules/cache-base": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/cache-base/-/cache-base-1.0.1.tgz",
+ "integrity": "sha512-AKcdTnFSWATd5/GCPRxr2ChwIJ85CeyrEyjRHlKxQ56d4XJMGym0uAiKn0xbLOGOl3+yRpOTi484dVCEc5AUzQ==",
+ "dev": true,
+ "peer": true,
+ "dependencies": {
+ "collection-visit": "^1.0.0",
+ "component-emitter": "^1.2.1",
+ "get-value": "^2.0.6",
+ "has-value": "^1.0.0",
+ "isobject": "^3.0.1",
+ "set-value": "^2.0.0",
+ "to-object-path": "^0.3.0",
+ "union-value": "^1.0.0",
+ "unset-value": "^1.0.0"
+ },
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
+ "node_modules/call-bind": {
+ "version": "1.0.2",
+ "resolved": "https://registry.npmjs.org/call-bind/-/call-bind-1.0.2.tgz",
+ "integrity": "sha512-7O+FbCihrB5WGbFYesctwmTKae6rOiIzmz1icreWJ+0aA7LJfuqhEso2T9ncpcFtzMQtzXf2QGGueWJGTYsqrA==",
+ "dev": true,
+ "dependencies": {
+ "function-bind": "^1.1.1",
+ "get-intrinsic": "^1.0.2"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/callsites": {
+ "version": "3.1.0",
+ "resolved": "https://registry.npmjs.org/callsites/-/callsites-3.1.0.tgz",
+ "integrity": "sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ==",
+ "dev": true,
+ "engines": {
+ "node": ">=6"
+ }
+ },
+ "node_modules/camelcase": {
+ "version": "5.3.1",
+ "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-5.3.1.tgz",
+ "integrity": "sha512-L28STB170nwWS63UjtlEOE3dldQApaJXZkOI1uMFfzf3rRuPegHaHesyee+YxQ+W6SvRDQV6UrdOdRiR153wJg==",
+ "dev": true,
+ "engines": {
+ "node": ">=6"
+ }
+ },
+ "node_modules/camelcase-keys": {
+ "version": "6.2.2",
+ "resolved": "https://registry.npmjs.org/camelcase-keys/-/camelcase-keys-6.2.2.tgz",
+ "integrity": "sha512-YrwaA0vEKazPBkn0ipTiMpSajYDSe+KjQfrjhcBMxJt/znbvlHd8Pw/Vamaz5EB4Wfhs3SUR3Z9mwRu/P3s3Yg==",
+ "dev": true,
+ "dependencies": {
+ "camelcase": "^5.3.1",
+ "map-obj": "^4.0.0",
+ "quick-lru": "^4.0.1"
+ },
+ "engines": {
+ "node": ">=8"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
+ "node_modules/caniuse-lite": {
+ "version": "1.0.30001416",
+ "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001416.tgz",
+ "integrity": "sha512-06wzzdAkCPZO+Qm4e/eNghZBDfVNDsCgw33T27OwBH9unE9S478OYw//Q2L7Npf/zBzs7rjZOszIFQkwQKAEqA==",
+ "dev": true,
+ "funding": [
+ {
+ "type": "opencollective",
+ "url": "https://opencollective.com/browserslist"
+ },
+ {
+ "type": "tidelift",
+ "url": "https://tidelift.com/funding/github/npm/caniuse-lite"
+ }
+ ]
+ },
+ "node_modules/capture-exit": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/capture-exit/-/capture-exit-2.0.0.tgz",
+ "integrity": "sha512-PiT/hQmTonHhl/HFGN+Lx3JJUznrVYJ3+AQsnthneZbvW7x+f08Tk7yLJTLEOUvBTbduLeeBkxEaYXUOUrRq6g==",
+ "dev": true,
+ "peer": true,
+ "dependencies": {
+ "rsvp": "^4.8.4"
+ },
+ "engines": {
+ "node": "6.* || 8.* || >= 10.*"
+ }
+ },
+ "node_modules/ccount": {
+ "version": "1.1.0",
+ "resolved": "https://registry.npmjs.org/ccount/-/ccount-1.1.0.tgz",
+ "integrity": "sha512-vlNK021QdI7PNeiUh/lKkC/mNHHfV0m/Ad5JoI0TYtlBnJAslM/JIkm/tGC88bkLIwO6OQ5uV6ztS6kVAtCDlg==",
+ "dev": true,
+ "funding": {
+ "type": "github",
+ "url": "https://github.com/sponsors/wooorm"
+ }
+ },
+ "node_modules/chalk": {
+ "version": "4.1.0",
+ "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.0.tgz",
+ "integrity": "sha512-qwx12AxXe2Q5xQ43Ac//I6v5aXTipYrSESdOgzrN+9XjgEpyjpKuvSGaN4qE93f7TQTlerQQ8S+EQ0EyDoVL1A==",
+ "dev": true,
+ "dependencies": {
+ "ansi-styles": "^4.1.0",
+ "supports-color": "^7.1.0"
+ },
+ "engines": {
+ "node": ">=10"
+ },
+ "funding": {
+ "url": "https://github.com/chalk/chalk?sponsor=1"
+ }
+ },
+ "node_modules/char-regex": {
+ "version": "1.0.2",
+ "resolved": "https://registry.npmjs.org/char-regex/-/char-regex-1.0.2.tgz",
+ "integrity": "sha512-kWWXztvZ5SBQV+eRgKFeh8q5sLuZY2+8WUIzlxWVTg+oGwY14qylx1KbKzHd8P6ZYkAg0xyIDU9JMHhyJMZ1jw==",
+ "dev": true,
+ "peer": true,
+ "engines": {
+ "node": ">=10"
+ }
+ },
+ "node_modules/character-entities": {
+ "version": "1.2.4",
+ "resolved": "https://registry.npmjs.org/character-entities/-/character-entities-1.2.4.tgz",
+ "integrity": "sha512-iBMyeEHxfVnIakwOuDXpVkc54HijNgCyQB2w0VfGQThle6NXn50zU6V/u+LDhxHcDUPojn6Kpga3PTAD8W1bQw==",
+ "dev": true,
+ "funding": {
+ "type": "github",
+ "url": "https://github.com/sponsors/wooorm"
+ }
+ },
+ "node_modules/character-entities-html4": {
+ "version": "1.1.4",
+ "resolved": "https://registry.npmjs.org/character-entities-html4/-/character-entities-html4-1.1.4.tgz",
+ "integrity": "sha512-HRcDxZuZqMx3/a+qrzxdBKBPUpxWEq9xw2OPZ3a/174ihfrQKVsFhqtthBInFy1zZ9GgZyFXOatNujm8M+El3g==",
+ "dev": true,
+ "funding": {
+ "type": "github",
+ "url": "https://github.com/sponsors/wooorm"
+ }
+ },
+ "node_modules/character-entities-legacy": {
+ "version": "1.1.4",
+ "resolved": "https://registry.npmjs.org/character-entities-legacy/-/character-entities-legacy-1.1.4.tgz",
+ "integrity": "sha512-3Xnr+7ZFS1uxeiUDvV02wQ+QDbc55o97tIV5zHScSPJpcLm/r0DFPcoY3tYRp+VZukxuMeKgXYmsXQHO05zQeA==",
+ "dev": true,
+ "funding": {
+ "type": "github",
+ "url": "https://github.com/sponsors/wooorm"
+ }
+ },
+ "node_modules/character-reference-invalid": {
+ "version": "1.1.4",
+ "resolved": "https://registry.npmjs.org/character-reference-invalid/-/character-reference-invalid-1.1.4.tgz",
+ "integrity": "sha512-mKKUkUbhPpQlCOfIuZkvSEgktjPFIsZKRRbC6KWVEMvlzblj3i3asQv5ODsrwt0N3pHAEvjP8KTQPHkp0+6jOg==",
+ "dev": true,
+ "funding": {
+ "type": "github",
+ "url": "https://github.com/sponsors/wooorm"
+ }
+ },
+ "node_modules/chardet": {
+ "version": "0.7.0",
+ "resolved": "https://registry.npmjs.org/chardet/-/chardet-0.7.0.tgz",
+ "integrity": "sha512-mT8iDcrh03qDGRRmoA2hmBJnxpllMR+0/0qlzjqZES6NdiWDcZkCNAk4rPFZ9Q85r27unkiNNg8ZOiwZXBHwcA==",
+ "dev": true
+ },
+ "node_modules/ci-info": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/ci-info/-/ci-info-2.0.0.tgz",
+ "integrity": "sha512-5tK7EtrZ0N+OLFMthtqOj4fI2Jeb88C4CAZPu25LDVUgXJ0A3Js4PMGqrn0JU1W0Mh1/Z8wZzYPxqUrXeBboCQ==",
+ "dev": true
+ },
+ "node_modules/cjs-module-lexer": {
+ "version": "0.6.0",
+ "resolved": "https://registry.npmjs.org/cjs-module-lexer/-/cjs-module-lexer-0.6.0.tgz",
+ "integrity": "sha512-uc2Vix1frTfnuzxxu1Hp4ktSvM3QaI4oXl4ZUqL1wjTu/BGki9TrCWoqLTg/drR1KwAEarXuRFCG2Svr1GxPFw==",
+ "dev": true,
+ "peer": true
+ },
+ "node_modules/class-utils": {
+ "version": "0.3.6",
+ "resolved": "https://registry.npmjs.org/class-utils/-/class-utils-0.3.6.tgz",
+ "integrity": "sha512-qOhPa/Fj7s6TY8H8esGu5QNpMMQxz79h+urzrNYN6mn+9BnxlDGf5QZ+XeCDsxSjPqsSR56XOZOJmpeurnLMeg==",
+ "dev": true,
+ "peer": true,
+ "dependencies": {
+ "arr-union": "^3.1.0",
+ "define-property": "^0.2.5",
+ "isobject": "^3.0.0",
+ "static-extend": "^0.1.1"
+ },
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
+ "node_modules/class-utils/node_modules/define-property": {
+ "version": "0.2.5",
+ "resolved": "https://registry.npmjs.org/define-property/-/define-property-0.2.5.tgz",
+ "integrity": "sha1-w1se+RjsPJkPmlvFe+BKrOxcgRY=",
+ "dev": true,
+ "peer": true,
+ "dependencies": {
+ "is-descriptor": "^0.1.0"
+ },
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
+ "node_modules/class-utils/node_modules/is-accessor-descriptor": {
+ "version": "0.1.6",
+ "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-0.1.6.tgz",
+ "integrity": "sha1-qeEss66Nh2cn7u84Q/igiXtcmNY=",
+ "dev": true,
+ "peer": true,
+ "dependencies": {
+ "kind-of": "^3.0.2"
+ },
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
+ "node_modules/class-utils/node_modules/is-accessor-descriptor/node_modules/kind-of": {
+ "version": "3.2.2",
+ "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz",
+ "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=",
+ "dev": true,
+ "peer": true,
+ "dependencies": {
+ "is-buffer": "^1.1.5"
+ },
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
+ "node_modules/class-utils/node_modules/is-buffer": {
+ "version": "1.1.6",
+ "resolved": "https://registry.npmjs.org/is-buffer/-/is-buffer-1.1.6.tgz",
+ "integrity": "sha512-NcdALwpXkTm5Zvvbk7owOUSvVvBKDgKP5/ewfXEznmQFfs4ZRmanOeKBTjRVjka3QFoN6XJ+9F3USqfHqTaU5w==",
+ "dev": true,
+ "peer": true
+ },
+ "node_modules/class-utils/node_modules/is-data-descriptor": {
+ "version": "0.1.4",
+ "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-0.1.4.tgz",
+ "integrity": "sha1-C17mSDiOLIYCgueT8YVv7D8wG1Y=",
+ "dev": true,
+ "peer": true,
+ "dependencies": {
+ "kind-of": "^3.0.2"
+ },
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
+ "node_modules/class-utils/node_modules/is-data-descriptor/node_modules/kind-of": {
+ "version": "3.2.2",
+ "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz",
+ "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=",
+ "dev": true,
+ "peer": true,
+ "dependencies": {
+ "is-buffer": "^1.1.5"
+ },
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
+ "node_modules/class-utils/node_modules/is-descriptor": {
+ "version": "0.1.6",
+ "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-0.1.6.tgz",
+ "integrity": "sha512-avDYr0SB3DwO9zsMov0gKCESFYqCnE4hq/4z3TdUlukEy5t9C0YRq7HLrsN52NAcqXKaepeCD0n+B0arnVG3Hg==",
+ "dev": true,
+ "peer": true,
+ "dependencies": {
+ "is-accessor-descriptor": "^0.1.6",
+ "is-data-descriptor": "^0.1.4",
+ "kind-of": "^5.0.0"
+ },
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
+ "node_modules/class-utils/node_modules/kind-of": {
+ "version": "5.1.0",
+ "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-5.1.0.tgz",
+ "integrity": "sha512-NGEErnH6F2vUuXDh+OlbcKW7/wOcfdRHaZ7VWtqCztfHri/++YKmP51OdWeGPuqCOba6kk2OTe5d02VmTB80Pw==",
+ "dev": true,
+ "peer": true,
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
+ "node_modules/clean-stack": {
+ "version": "2.2.0",
+ "resolved": "https://registry.npmjs.org/clean-stack/-/clean-stack-2.2.0.tgz",
+ "integrity": "sha512-4diC9HaTE+KRAMWhDhrGOECgWZxoevMc5TlkObMqNSsVU62PYzXZ/SMTjzyGAFF1YusgxGcSWTEXBhp0CPwQ1A==",
+ "dev": true,
+ "engines": {
+ "node": ">=6"
+ }
+ },
+ "node_modules/cli-cursor": {
+ "version": "3.1.0",
+ "resolved": "https://registry.npmjs.org/cli-cursor/-/cli-cursor-3.1.0.tgz",
+ "integrity": "sha512-I/zHAwsKf9FqGoXM4WWRACob9+SNukZTd94DWF57E4toouRulbCxcUh6RKUEOQlYTHJnzkPMySvPNaaSLNfLZw==",
+ "dev": true,
+ "dependencies": {
+ "restore-cursor": "^3.1.0"
+ },
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/cli-truncate": {
+ "version": "2.1.0",
+ "resolved": "https://registry.npmjs.org/cli-truncate/-/cli-truncate-2.1.0.tgz",
+ "integrity": "sha512-n8fOixwDD6b/ObinzTrp1ZKFzbgvKZvuz/TvejnLn1aQfC6r52XEx85FmuC+3HI+JM7coBRXUvNqEU2PHVrHpg==",
+ "dev": true,
+ "dependencies": {
+ "slice-ansi": "^3.0.0",
+ "string-width": "^4.2.0"
+ },
+ "engines": {
+ "node": ">=8"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
+ "node_modules/cli-width": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/cli-width/-/cli-width-3.0.0.tgz",
+ "integrity": "sha512-FxqpkPPwu1HjuN93Omfm4h8uIanXofW0RxVEW3k5RKx+mJJYSthzNhp32Kzxxy3YAEZ/Dc/EWN1vZRY0+kOhbw==",
+ "dev": true,
+ "engines": {
+ "node": ">= 10"
+ }
+ },
+ "node_modules/cliui": {
+ "version": "6.0.0",
+ "resolved": "https://registry.npmjs.org/cliui/-/cliui-6.0.0.tgz",
+ "integrity": "sha512-t6wbgtoCXvAzst7QgXxJYqPt0usEfbgQdftEPbLL/cvv6HPE5VgvqCuAIDR0NgU52ds6rFwqrgakNLrHEjCbrQ==",
+ "dev": true,
+ "peer": true,
+ "dependencies": {
+ "string-width": "^4.2.0",
+ "strip-ansi": "^6.0.0",
+ "wrap-ansi": "^6.2.0"
+ }
+ },
+ "node_modules/cliui/node_modules/wrap-ansi": {
+ "version": "6.2.0",
+ "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-6.2.0.tgz",
+ "integrity": "sha512-r6lPcBGxZXlIcymEu7InxDMhdW0KDxpLgoFLcguasxCaJ/SOIZwINatK9KY/tf+ZrlywOKU0UDj3ATXUBfxJXA==",
+ "dev": true,
+ "peer": true,
+ "dependencies": {
+ "ansi-styles": "^4.0.0",
+ "string-width": "^4.1.0",
+ "strip-ansi": "^6.0.0"
+ },
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/clone-regexp": {
+ "version": "2.2.0",
+ "resolved": "https://registry.npmjs.org/clone-regexp/-/clone-regexp-2.2.0.tgz",
+ "integrity": "sha512-beMpP7BOtTipFuW8hrJvREQ2DrRu3BE7by0ZpibtfBA+qfHYvMGTc2Yb1JMYPKg/JUw0CHYvpg796aNTSW9z7Q==",
+ "dev": true,
+ "dependencies": {
+ "is-regexp": "^2.0.0"
+ },
+ "engines": {
+ "node": ">=6"
+ }
+ },
+ "node_modules/clone-regexp/node_modules/is-regexp": {
+ "version": "2.1.0",
+ "resolved": "https://registry.npmjs.org/is-regexp/-/is-regexp-2.1.0.tgz",
+ "integrity": "sha512-OZ4IlER3zmRIoB9AqNhEggVxqIH4ofDns5nRrPS6yQxXE1TPCUpFznBfRQmQa8uC+pXqjMnukiJBxCisIxiLGA==",
+ "dev": true,
+ "engines": {
+ "node": ">=6"
+ }
+ },
+ "node_modules/co": {
+ "version": "4.6.0",
+ "resolved": "https://registry.npmjs.org/co/-/co-4.6.0.tgz",
+ "integrity": "sha1-bqa989hTrlTMuOR7+gvz+QMfsYQ=",
+ "dev": true,
+ "peer": true,
+ "engines": {
+ "iojs": ">= 1.0.0",
+ "node": ">= 0.12.0"
+ }
+ },
+ "node_modules/collapse-white-space": {
+ "version": "1.0.6",
+ "resolved": "https://registry.npmjs.org/collapse-white-space/-/collapse-white-space-1.0.6.tgz",
+ "integrity": "sha512-jEovNnrhMuqyCcjfEJA56v0Xq8SkIoPKDyaHahwo3POf4qcSXqMYuwNcOTzp74vTsR9Tn08z4MxWqAhcekogkQ==",
+ "dev": true,
+ "funding": {
+ "type": "github",
+ "url": "https://github.com/sponsors/wooorm"
+ }
+ },
+ "node_modules/collect-v8-coverage": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/collect-v8-coverage/-/collect-v8-coverage-1.0.1.tgz",
+ "integrity": "sha512-iBPtljfCNcTKNAto0KEtDfZ3qzjJvqE3aTGZsbhjSBlorqpXJlaWWtPO35D+ZImoC3KWejX64o+yPGxhWSTzfg==",
+ "dev": true,
+ "peer": true
+ },
+ "node_modules/collection-visit": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/collection-visit/-/collection-visit-1.0.0.tgz",
+ "integrity": "sha1-S8A3PBZLwykbTTaMgpzxqApZ3KA=",
+ "dev": true,
+ "peer": true,
+ "dependencies": {
+ "map-visit": "^1.0.0",
+ "object-visit": "^1.0.0"
+ },
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
+ "node_modules/color-convert": {
+ "version": "2.0.1",
+ "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz",
+ "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==",
+ "dev": true,
+ "dependencies": {
+ "color-name": "~1.1.4"
+ },
+ "engines": {
+ "node": ">=7.0.0"
+ }
+ },
+ "node_modules/color-name": {
+ "version": "1.1.4",
+ "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz",
+ "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==",
+ "dev": true
+ },
+ "node_modules/colorette": {
+ "version": "2.0.16",
+ "resolved": "https://registry.npmjs.org/colorette/-/colorette-2.0.16.tgz",
+ "integrity": "sha512-hUewv7oMjCp+wkBv5Rm0v87eJhq4woh5rSR+42YSQJKecCqgIqNkZ6lAlQms/BwHPJA5NKMRlpxPRv0n8HQW6g==",
+ "dev": true
+ },
+ "node_modules/combined-stream": {
+ "version": "1.0.8",
+ "resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.8.tgz",
+ "integrity": "sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg==",
+ "dev": true,
+ "dependencies": {
+ "delayed-stream": "~1.0.0"
+ },
+ "engines": {
+ "node": ">= 0.8"
+ }
+ },
+ "node_modules/commander": {
+ "version": "7.2.0",
+ "resolved": "https://registry.npmjs.org/commander/-/commander-7.2.0.tgz",
+ "integrity": "sha512-QrWXB+ZQSVPmIWIhtEO9H+gwHaMGYiF5ChvoJ+K9ZGHG/sVsa6yiesAD1GC/x46sET00Xlwo1u49RVVVzvcSkw==",
+ "dev": true,
+ "engines": {
+ "node": ">= 10"
+ }
+ },
+ "node_modules/compare-versions": {
+ "version": "3.6.0",
+ "resolved": "https://registry.npmjs.org/compare-versions/-/compare-versions-3.6.0.tgz",
+ "integrity": "sha512-W6Af2Iw1z4CB7q4uU4hv646dW9GQuBM+YpC0UvUCWSD8w90SJjp+ujJuXaEMtAXBtSqGfMPuFOVn4/+FlaqfBA==",
+ "dev": true
+ },
+ "node_modules/component-emitter": {
+ "version": "1.3.0",
+ "resolved": "https://registry.npmjs.org/component-emitter/-/component-emitter-1.3.0.tgz",
+ "integrity": "sha512-Rd3se6QB+sO1TwqZjscQrurpEPIfO0/yYnSin6Q/rD3mOutHvUrCAhJub3r90uNb+SESBuE0QYoB90YdfatsRg==",
+ "dev": true,
+ "peer": true
+ },
+ "node_modules/concat-map": {
+ "version": "0.0.1",
+ "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz",
+ "integrity": "sha1-2Klr13/Wjfd5OnMDajug1UBdR3s=",
+ "dev": true
+ },
+ "node_modules/convert-source-map": {
+ "version": "1.8.0",
+ "resolved": "https://registry.npmjs.org/convert-source-map/-/convert-source-map-1.8.0.tgz",
+ "integrity": "sha512-+OQdjP49zViI/6i7nIJpA8rAl4sV/JdPfU9nZs3VqOwGIgizICvuN2ru6fMd+4llL0tar18UYJXfZ/TWtmhUjA==",
+ "dev": true,
+ "dependencies": {
+ "safe-buffer": "~5.1.1"
+ }
+ },
+ "node_modules/copy-descriptor": {
+ "version": "0.1.1",
+ "resolved": "https://registry.npmjs.org/copy-descriptor/-/copy-descriptor-0.1.1.tgz",
+ "integrity": "sha1-Z29us8OZl8LuGsOpJP1hJHSPV40=",
+ "dev": true,
+ "peer": true,
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
+ "node_modules/cosmiconfig": {
+ "version": "7.0.0",
+ "resolved": "https://registry.npmjs.org/cosmiconfig/-/cosmiconfig-7.0.0.tgz",
+ "integrity": "sha512-pondGvTuVYDk++upghXJabWzL6Kxu6f26ljFw64Swq9v6sQPUL3EUlVDV56diOjpCayKihL6hVe8exIACU4XcA==",
+ "dev": true,
+ "dependencies": {
+ "@types/parse-json": "^4.0.0",
+ "import-fresh": "^3.2.1",
+ "parse-json": "^5.0.0",
+ "path-type": "^4.0.0",
+ "yaml": "^1.10.0"
+ },
+ "engines": {
+ "node": ">=10"
+ }
+ },
+ "node_modules/cross-fetch": {
+ "version": "3.1.5",
+ "resolved": "https://registry.npmjs.org/cross-fetch/-/cross-fetch-3.1.5.tgz",
+ "integrity": "sha512-lvb1SBsI0Z7GDwmuid+mU3kWVBwTVUbe7S0H52yaaAdQOXq2YktTCZdlAcNKFzE6QtRz0snpw9bNiPeOIkkQvw==",
+ "dev": true,
+ "dependencies": {
+ "node-fetch": "2.6.7"
+ }
+ },
+ "node_modules/cross-spawn": {
+ "version": "7.0.3",
+ "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.3.tgz",
+ "integrity": "sha512-iRDPJKUPVEND7dHPO8rkbOnPpyDygcDFtWjpeWNCgy8WP2rXcxXL8TskReQl6OrB2G7+UJrags1q15Fudc7G6w==",
+ "dev": true,
+ "dependencies": {
+ "path-key": "^3.1.0",
+ "shebang-command": "^2.0.0",
+ "which": "^2.0.1"
+ },
+ "engines": {
+ "node": ">= 8"
+ }
+ },
+ "node_modules/cssesc": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/cssesc/-/cssesc-3.0.0.tgz",
+ "integrity": "sha512-/Tb/JcjK111nNScGob5MNtsntNM1aCNUDipB/TkwZFhyDrrE47SOx/18wF2bbjgc3ZzCSKW1T5nt5EbFoAz/Vg==",
+ "dev": true,
+ "bin": {
+ "cssesc": "bin/cssesc"
+ },
+ "engines": {
+ "node": ">=4"
+ }
+ },
+ "node_modules/cssom": {
+ "version": "0.4.4",
+ "resolved": "https://registry.npmjs.org/cssom/-/cssom-0.4.4.tgz",
+ "integrity": "sha512-p3pvU7r1MyyqbTk+WbNJIgJjG2VmTIaB10rI93LzVPrmDJKkzKYMtxxyAvQXR/NS6otuzveI7+7BBq3SjBS2mw==",
+ "dev": true,
+ "peer": true
+ },
+ "node_modules/cssstyle": {
+ "version": "2.3.0",
+ "resolved": "https://registry.npmjs.org/cssstyle/-/cssstyle-2.3.0.tgz",
+ "integrity": "sha512-AZL67abkUzIuvcHqk7c09cezpGNcxUxU4Ioi/05xHk4DQeTkWmGYftIE6ctU6AEt+Gn4n1lDStOtj7FKycP71A==",
+ "dev": true,
+ "peer": true,
+ "dependencies": {
+ "cssom": "~0.3.6"
+ },
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/cssstyle/node_modules/cssom": {
+ "version": "0.3.8",
+ "resolved": "https://registry.npmjs.org/cssom/-/cssom-0.3.8.tgz",
+ "integrity": "sha512-b0tGHbfegbhPJpxpiBPU2sCkigAqtM9O121le6bbOlgyV+NyGyCmVfJ6QW9eRjz8CpNfWEOYBIMIGRYkLwsIYg==",
+ "dev": true,
+ "peer": true
+ },
+ "node_modules/damerau-levenshtein": {
+ "version": "1.0.8",
+ "resolved": "https://registry.npmjs.org/damerau-levenshtein/-/damerau-levenshtein-1.0.8.tgz",
+ "integrity": "sha512-sdQSFB7+llfUcQHUQO3+B8ERRj0Oa4w9POWMI/puGtuf7gFywGmkaLCElnudfTiKZV+NvHqL0ifzdrI8Ro7ESA==",
+ "dev": true
+ },
+ "node_modules/dart-linkcheck": {
+ "version": "2.0.15",
+ "resolved": "https://registry.npmjs.org/dart-linkcheck/-/dart-linkcheck-2.0.15.tgz",
+ "integrity": "sha512-ZMvxkAyEpBTvBFk+DPjcK0ObNy8GM4gmrGG1qIu0EXb/zj25vjRWNnhLHKZw4JlOLo02oWlwDeqo98GuBlJcIg==",
+ "dev": true,
+ "bin": {
+ "linkcheck": "bin/linkcheck",
+ "linkcheck-linux": "bin/linkcheck-linux",
+ "linkcheck-win": "bin/linkcheck-win"
+ }
+ },
+ "node_modules/data-urls": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/data-urls/-/data-urls-2.0.0.tgz",
+ "integrity": "sha512-X5eWTSXO/BJmpdIKCRuKUgSCgAN0OwliVK3yPKbwIWU1Tdw5BRajxlzMidvh+gwko9AfQ9zIj52pzF91Q3YAvQ==",
+ "dev": true,
+ "peer": true,
+ "dependencies": {
+ "abab": "^2.0.3",
+ "whatwg-mimetype": "^2.3.0",
+ "whatwg-url": "^8.0.0"
+ },
+ "engines": {
+ "node": ">=10"
+ }
+ },
+ "node_modules/debug": {
+ "version": "4.3.4",
+ "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz",
+ "integrity": "sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==",
+ "dev": true,
+ "dependencies": {
+ "ms": "2.1.2"
+ },
+ "engines": {
+ "node": ">=6.0"
+ },
+ "peerDependenciesMeta": {
+ "supports-color": {
+ "optional": true
+ }
+ }
+ },
+ "node_modules/decamelize": {
+ "version": "1.2.0",
+ "resolved": "https://registry.npmjs.org/decamelize/-/decamelize-1.2.0.tgz",
+ "integrity": "sha1-9lNNFRSCabIDUue+4m9QH5oZEpA=",
+ "dev": true,
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
+ "node_modules/decamelize-keys": {
+ "version": "1.1.0",
+ "resolved": "https://registry.npmjs.org/decamelize-keys/-/decamelize-keys-1.1.0.tgz",
+ "integrity": "sha1-0XGoeTMlKAfrPLYdwcFEXQeN8tk=",
+ "dev": true,
+ "dependencies": {
+ "decamelize": "^1.1.0",
+ "map-obj": "^1.0.0"
+ },
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
+ "node_modules/decamelize-keys/node_modules/map-obj": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/map-obj/-/map-obj-1.0.1.tgz",
+ "integrity": "sha1-2TPOuSBdgr3PSIb2dCvcK03qFG0=",
+ "dev": true,
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
+ "node_modules/decimal.js": {
+ "version": "10.3.1",
+ "resolved": "https://registry.npmjs.org/decimal.js/-/decimal.js-10.3.1.tgz",
+ "integrity": "sha512-V0pfhfr8suzyPGOx3nmq4aHqabehUZn6Ch9kyFpV79TGDTWFmHqUqXdabR7QHqxzrYolF4+tVmJhUG4OURg5dQ==",
+ "dev": true,
+ "peer": true
+ },
+ "node_modules/decode-uri-component": {
+ "version": "0.2.0",
+ "resolved": "https://registry.npmjs.org/decode-uri-component/-/decode-uri-component-0.2.0.tgz",
+ "integrity": "sha1-6zkTMzRYd1y4TNGh+uBiEGu4dUU=",
+ "dev": true,
+ "peer": true,
+ "engines": {
+ "node": ">=0.10"
+ }
+ },
+ "node_modules/deep-equal": {
+ "version": "2.2.0",
+ "resolved": "https://registry.npmjs.org/deep-equal/-/deep-equal-2.2.0.tgz",
+ "integrity": "sha512-RdpzE0Hv4lhowpIUKKMJfeH6C1pXdtT1/it80ubgWqwI3qpuxUBpC1S4hnHg+zjnuOoDkzUtUCEEkG+XG5l3Mw==",
+ "dev": true,
+ "dependencies": {
+ "call-bind": "^1.0.2",
+ "es-get-iterator": "^1.1.2",
+ "get-intrinsic": "^1.1.3",
+ "is-arguments": "^1.1.1",
+ "is-array-buffer": "^3.0.1",
+ "is-date-object": "^1.0.5",
+ "is-regex": "^1.1.4",
+ "is-shared-array-buffer": "^1.0.2",
+ "isarray": "^2.0.5",
+ "object-is": "^1.1.5",
+ "object-keys": "^1.1.1",
+ "object.assign": "^4.1.4",
+ "regexp.prototype.flags": "^1.4.3",
+ "side-channel": "^1.0.4",
+ "which-boxed-primitive": "^1.0.2",
+ "which-collection": "^1.0.1",
+ "which-typed-array": "^1.1.9"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/deep-equal/node_modules/isarray": {
+ "version": "2.0.5",
+ "resolved": "https://registry.npmjs.org/isarray/-/isarray-2.0.5.tgz",
+ "integrity": "sha512-xHjhDr3cNBK0BzdUJSPXZntQUx/mwMS5Rw4A7lPJ90XGAO6ISP/ePDNuo0vhqOZU+UD5JoodwCAAoZQd3FeAKw==",
+ "dev": true
+ },
+ "node_modules/deep-is": {
+ "version": "0.1.4",
+ "resolved": "https://registry.npmjs.org/deep-is/-/deep-is-0.1.4.tgz",
+ "integrity": "sha512-oIPzksmTg4/MriiaYGO+okXDT7ztn/w3Eptv/+gSIdMdKsJo0u4CfYNFJPy+4SKMuCqGw2wxnA+URMg3t8a/bQ==",
+ "dev": true
+ },
+ "node_modules/deepmerge": {
+ "version": "4.2.2",
+ "resolved": "https://registry.npmjs.org/deepmerge/-/deepmerge-4.2.2.tgz",
+ "integrity": "sha512-FJ3UgI4gIl+PHZm53knsuSFpE+nESMr7M4v9QcgB7S63Kj/6WqMiFQJpBBYz1Pt+66bZpP3Q7Lye0Oo9MPKEdg==",
+ "dev": true,
+ "peer": true,
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
+ "node_modules/define-lazy-prop": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/define-lazy-prop/-/define-lazy-prop-2.0.0.tgz",
+ "integrity": "sha512-Ds09qNh8yw3khSjiJjiUInaGX9xlqZDY7JVryGxdxV7NPeuqQfplOpQ66yJFZut3jLa5zOwkXw1g9EI2uKh4Og==",
+ "dev": true,
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/define-properties": {
+ "version": "1.2.0",
+ "resolved": "https://registry.npmjs.org/define-properties/-/define-properties-1.2.0.tgz",
+ "integrity": "sha512-xvqAVKGfT1+UAvPwKTVw/njhdQ8ZhXK4lI0bCIuCMrp2up9nPnaDftrLtmpTazqd1o+UY4zgzU+avtMbDP+ldA==",
+ "dev": true,
+ "dependencies": {
+ "has-property-descriptors": "^1.0.0",
+ "object-keys": "^1.1.1"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/define-property": {
+ "version": "2.0.2",
+ "resolved": "https://registry.npmjs.org/define-property/-/define-property-2.0.2.tgz",
+ "integrity": "sha512-jwK2UV4cnPpbcG7+VRARKTZPUWowwXA8bzH5NP6ud0oeAxyYPuGZUAC7hMugpCdz4BeSZl2Dl9k66CHJ/46ZYQ==",
+ "dev": true,
+ "peer": true,
+ "dependencies": {
+ "is-descriptor": "^1.0.2",
+ "isobject": "^3.0.1"
+ },
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
+ "node_modules/delayed-stream": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz",
+ "integrity": "sha1-3zrhmayt+31ECqrgsp4icrJOxhk=",
+ "dev": true,
+ "engines": {
+ "node": ">=0.4.0"
+ }
+ },
+ "node_modules/detect-newline": {
+ "version": "3.1.0",
+ "resolved": "https://registry.npmjs.org/detect-newline/-/detect-newline-3.1.0.tgz",
+ "integrity": "sha512-TLz+x/vEXm/Y7P7wn1EJFNLxYpUD4TgMosxY6fAVJUnJMbupHBOncxyWUG9OpTaH9EBD7uFI5LfEgmMOc54DsA==",
+ "dev": true,
+ "peer": true,
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/diff-sequences": {
+ "version": "26.6.2",
+ "resolved": "https://registry.npmjs.org/diff-sequences/-/diff-sequences-26.6.2.tgz",
+ "integrity": "sha512-Mv/TDa3nZ9sbc5soK+OoA74BsS3mL37yixCvUAQkiuA4Wz6YtwP/K47n2rv2ovzHZvoiQeA5FTQOschKkEwB0Q==",
+ "dev": true,
+ "peer": true,
+ "engines": {
+ "node": ">= 10.14.2"
+ }
+ },
+ "node_modules/dir-glob": {
+ "version": "3.0.1",
+ "resolved": "https://registry.npmjs.org/dir-glob/-/dir-glob-3.0.1.tgz",
+ "integrity": "sha512-WkrWp9GR4KXfKGYzOLmTuGVi1UWFfws377n9cc55/tb6DuqyF6pcQ5AbiHEshaDpY9v6oaSr2XCDidGmMwdzIA==",
+ "dev": true,
+ "dependencies": {
+ "path-type": "^4.0.0"
+ },
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/doctrine": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/doctrine/-/doctrine-3.0.0.tgz",
+ "integrity": "sha512-yS+Q5i3hBf7GBkd4KG8a7eBNNWNGLTaEwwYWUijIYM7zrlYDM0BFXHjjPWlWZ1Rg7UaddZeIDmi9jF3HmqiQ2w==",
+ "dev": true,
+ "dependencies": {
+ "esutils": "^2.0.2"
+ },
+ "engines": {
+ "node": ">=6.0.0"
+ }
+ },
+ "node_modules/dom-serializer": {
+ "version": "0.2.2",
+ "resolved": "https://registry.npmjs.org/dom-serializer/-/dom-serializer-0.2.2.tgz",
+ "integrity": "sha512-2/xPb3ORsQ42nHYiSunXkDjPLBaEj/xTwUO4B7XCZQTRk7EBtTOPaygh10YAAh2OI1Qrp6NWfpAhzswj0ydt9g==",
+ "dev": true,
+ "dependencies": {
+ "domelementtype": "^2.0.1",
+ "entities": "^2.0.0"
+ }
+ },
+ "node_modules/dom-serializer/node_modules/domelementtype": {
+ "version": "2.3.0",
+ "resolved": "https://registry.npmjs.org/domelementtype/-/domelementtype-2.3.0.tgz",
+ "integrity": "sha512-OLETBj6w0OsagBwdXnPdN0cnMfF9opN69co+7ZrbfPGrdpPVNBUj02spi6B1N7wChLQiPn4CSH/zJvXw56gmHw==",
+ "dev": true,
+ "funding": [
+ {
+ "type": "github",
+ "url": "https://github.com/sponsors/fb55"
+ }
+ ]
+ },
+ "node_modules/dom-serializer/node_modules/entities": {
+ "version": "2.2.0",
+ "resolved": "https://registry.npmjs.org/entities/-/entities-2.2.0.tgz",
+ "integrity": "sha512-p92if5Nz619I0w+akJrLZH0MX0Pb5DX39XOwQTtXSdQQOaYH03S1uIQp4mhOZtAXrxq4ViO67YTiLBo2638o9A==",
+ "dev": true,
+ "funding": {
+ "url": "https://github.com/fb55/entities?sponsor=1"
+ }
+ },
+ "node_modules/domelementtype": {
+ "version": "1.3.1",
+ "resolved": "https://registry.npmjs.org/domelementtype/-/domelementtype-1.3.1.tgz",
+ "integrity": "sha512-BSKB+TSpMpFI/HOxCNr1O8aMOTZ8hT3pM3GQ0w/mWRmkhEDSFJkkyzz4XQsBV44BChwGkrDfMyjVD0eA2aFV3w==",
+ "dev": true
+ },
+ "node_modules/domexception": {
+ "version": "2.0.1",
+ "resolved": "https://registry.npmjs.org/domexception/-/domexception-2.0.1.tgz",
+ "integrity": "sha512-yxJ2mFy/sibVQlu5qHjOkf9J3K6zgmCxgJ94u2EdvDOV09H+32LtRswEcUsmUWN72pVLOEnTSRaIVVzVQgS0dg==",
+ "dev": true,
+ "peer": true,
+ "dependencies": {
+ "webidl-conversions": "^5.0.0"
+ },
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/domexception/node_modules/webidl-conversions": {
+ "version": "5.0.0",
+ "resolved": "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-5.0.0.tgz",
+ "integrity": "sha512-VlZwKPCkYKxQgeSbH5EyngOmRp7Ww7I9rQLERETtf5ofd9pGeswWiOtogpEO850jziPRarreGxn5QIiTqpb2wA==",
+ "dev": true,
+ "peer": true,
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/domhandler": {
+ "version": "2.4.2",
+ "resolved": "https://registry.npmjs.org/domhandler/-/domhandler-2.4.2.tgz",
+ "integrity": "sha512-JiK04h0Ht5u/80fdLMCEmV4zkNh2BcoMFBmZ/91WtYZ8qVXSKjiw7fXMgFPnHcSZgOo3XdinHvmnDUeMf5R4wA==",
+ "dev": true,
+ "dependencies": {
+ "domelementtype": "1"
+ }
+ },
+ "node_modules/domutils": {
+ "version": "1.7.0",
+ "resolved": "https://registry.npmjs.org/domutils/-/domutils-1.7.0.tgz",
+ "integrity": "sha512-Lgd2XcJ/NjEw+7tFvfKxOzCYKZsdct5lczQ2ZaQY8Djz7pfAD3Gbp8ySJWtreII/vDlMVmxwa6pHmdxIYgttDg==",
+ "dev": true,
+ "dependencies": {
+ "dom-serializer": "0",
+ "domelementtype": "1"
+ }
+ },
+ "node_modules/eastasianwidth": {
+ "version": "0.2.0",
+ "resolved": "https://registry.npmjs.org/eastasianwidth/-/eastasianwidth-0.2.0.tgz",
+ "integrity": "sha512-I88TYZWc9XiYHRQ4/3c5rjjfgkjhLyW2luGIheGERbNQ6OY7yTybanSpDXZa8y7VUP9YmDcYa+eyq4ca7iLqWA==",
+ "dev": true
+ },
+ "node_modules/ejs": {
+ "version": "3.1.5",
+ "resolved": "https://registry.npmjs.org/ejs/-/ejs-3.1.5.tgz",
+ "integrity": "sha512-dldq3ZfFtgVTJMLjOe+/3sROTzALlL9E34V4/sDtUd/KlBSS0s6U1/+WPE1B4sj9CXHJpL1M6rhNJnc9Wbal9w==",
+ "dev": true,
+ "dependencies": {
+ "jake": "^10.6.1"
+ },
+ "bin": {
+ "ejs": "bin/cli.js"
+ },
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
+ "node_modules/electron-to-chromium": {
+ "version": "1.4.114",
+ "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.4.114.tgz",
+ "integrity": "sha512-gRwLpVYWHGbERPU6o8pKfR168V6enWEXzZc6zQNNXbgJ7UJna+9qzAIHY94+9KOv71D/CH+QebLA9pChD2q8zA==",
+ "dev": true
+ },
+ "node_modules/emittery": {
+ "version": "0.7.2",
+ "resolved": "https://registry.npmjs.org/emittery/-/emittery-0.7.2.tgz",
+ "integrity": "sha512-A8OG5SR/ij3SsJdWDJdkkSYUjQdCUx6APQXem0SaEePBSRg4eymGYwBkKo1Y6DU+af/Jn2dBQqDBvjnr9Vi8nQ==",
+ "dev": true,
+ "peer": true,
+ "engines": {
+ "node": ">=10"
+ },
+ "funding": {
+ "url": "https://github.com/sindresorhus/emittery?sponsor=1"
+ }
+ },
+ "node_modules/emoji-regex": {
+ "version": "9.2.2",
+ "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-9.2.2.tgz",
+ "integrity": "sha512-L18DaJsXSUk2+42pv8mLs5jJT2hqFkFE4j21wOmgbUqsZ2hL72NsUU785g9RXgo3s0ZNgVl42TiHp3ZtOv/Vyg==",
+ "dev": true
+ },
+ "node_modules/end-of-stream": {
+ "version": "1.4.4",
+ "resolved": "https://registry.npmjs.org/end-of-stream/-/end-of-stream-1.4.4.tgz",
+ "integrity": "sha512-+uw1inIHVPQoaVuHzRyXd21icM+cnt4CzD5rW+NC1wjOUSTOs+Te7FOv7AhN7vS9x/oIyhLP5PR1H+phQAHu5Q==",
+ "dev": true,
+ "peer": true,
+ "dependencies": {
+ "once": "^1.4.0"
+ }
+ },
+ "node_modules/enhanced-resolve": {
+ "version": "5.12.0",
+ "resolved": "https://registry.npmjs.org/enhanced-resolve/-/enhanced-resolve-5.12.0.tgz",
+ "integrity": "sha512-QHTXI/sZQmko1cbDoNAa3mJ5qhWUUNAq3vR0/YiD379fWQrcfuoX1+HW2S0MTt7XmoPLapdaDKUtelUSPic7hQ==",
+ "dev": true,
+ "dependencies": {
+ "graceful-fs": "^4.2.4",
+ "tapable": "^2.2.0"
+ },
+ "engines": {
+ "node": ">=10.13.0"
+ }
+ },
+ "node_modules/enquirer": {
+ "version": "2.3.6",
+ "resolved": "https://registry.npmjs.org/enquirer/-/enquirer-2.3.6.tgz",
+ "integrity": "sha512-yjNnPr315/FjS4zIsUxYguYUPP2e1NK4d7E7ZOLiyYCcbFBiTMyID+2wvm2w6+pZ/odMA7cRkjhsPbltwBOrLg==",
+ "dev": true,
+ "dependencies": {
+ "ansi-colors": "^4.1.1"
+ },
+ "engines": {
+ "node": ">=8.6"
+ }
+ },
+ "node_modules/entities": {
+ "version": "1.1.2",
+ "resolved": "https://registry.npmjs.org/entities/-/entities-1.1.2.tgz",
+ "integrity": "sha512-f2LZMYl1Fzu7YSBKg+RoROelpOaNrcGmE9AZubeDfrCEia483oW4MI4VyFd5VNHIgQ/7qm1I0wUHK1eJnn2y2w==",
+ "dev": true
+ },
+ "node_modules/error-ex": {
+ "version": "1.3.2",
+ "resolved": "https://registry.npmjs.org/error-ex/-/error-ex-1.3.2.tgz",
+ "integrity": "sha512-7dFHNmqeFSEt2ZBsCriorKnn3Z2pj+fd9kmI6QoWw4//DL+icEBfc0U7qJCisqrTsKTjw4fNFy2pW9OqStD84g==",
+ "dev": true,
+ "dependencies": {
+ "is-arrayish": "^0.2.1"
+ }
+ },
+ "node_modules/es-abstract": {
+ "version": "1.21.2",
+ "resolved": "https://registry.npmjs.org/es-abstract/-/es-abstract-1.21.2.tgz",
+ "integrity": "sha512-y/B5POM2iBnIxCiernH1G7rC9qQoM77lLIMQLuob0zhp8C56Po81+2Nj0WFKnd0pNReDTnkYryc+zhOzpEIROg==",
+ "dev": true,
+ "dependencies": {
+ "array-buffer-byte-length": "^1.0.0",
+ "available-typed-arrays": "^1.0.5",
+ "call-bind": "^1.0.2",
+ "es-set-tostringtag": "^2.0.1",
+ "es-to-primitive": "^1.2.1",
+ "function.prototype.name": "^1.1.5",
+ "get-intrinsic": "^1.2.0",
+ "get-symbol-description": "^1.0.0",
+ "globalthis": "^1.0.3",
+ "gopd": "^1.0.1",
+ "has": "^1.0.3",
+ "has-property-descriptors": "^1.0.0",
+ "has-proto": "^1.0.1",
+ "has-symbols": "^1.0.3",
+ "internal-slot": "^1.0.5",
+ "is-array-buffer": "^3.0.2",
+ "is-callable": "^1.2.7",
+ "is-negative-zero": "^2.0.2",
+ "is-regex": "^1.1.4",
+ "is-shared-array-buffer": "^1.0.2",
+ "is-string": "^1.0.7",
+ "is-typed-array": "^1.1.10",
+ "is-weakref": "^1.0.2",
+ "object-inspect": "^1.12.3",
+ "object-keys": "^1.1.1",
+ "object.assign": "^4.1.4",
+ "regexp.prototype.flags": "^1.4.3",
+ "safe-regex-test": "^1.0.0",
+ "string.prototype.trim": "^1.2.7",
+ "string.prototype.trimend": "^1.0.6",
+ "string.prototype.trimstart": "^1.0.6",
+ "typed-array-length": "^1.0.4",
+ "unbox-primitive": "^1.0.2",
+ "which-typed-array": "^1.1.9"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/es-get-iterator": {
+ "version": "1.1.3",
+ "resolved": "https://registry.npmjs.org/es-get-iterator/-/es-get-iterator-1.1.3.tgz",
+ "integrity": "sha512-sPZmqHBe6JIiTfN5q2pEi//TwxmAFHwj/XEuYjTuse78i8KxaqMTTzxPoFKuzRpDpTJ+0NAbpfenkmH2rePtuw==",
+ "dev": true,
+ "dependencies": {
+ "call-bind": "^1.0.2",
+ "get-intrinsic": "^1.1.3",
+ "has-symbols": "^1.0.3",
+ "is-arguments": "^1.1.1",
+ "is-map": "^2.0.2",
+ "is-set": "^2.0.2",
+ "is-string": "^1.0.7",
+ "isarray": "^2.0.5",
+ "stop-iteration-iterator": "^1.0.0"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/es-get-iterator/node_modules/isarray": {
+ "version": "2.0.5",
+ "resolved": "https://registry.npmjs.org/isarray/-/isarray-2.0.5.tgz",
+ "integrity": "sha512-xHjhDr3cNBK0BzdUJSPXZntQUx/mwMS5Rw4A7lPJ90XGAO6ISP/ePDNuo0vhqOZU+UD5JoodwCAAoZQd3FeAKw==",
+ "dev": true
+ },
+ "node_modules/es-set-tostringtag": {
+ "version": "2.0.1",
+ "resolved": "https://registry.npmjs.org/es-set-tostringtag/-/es-set-tostringtag-2.0.1.tgz",
+ "integrity": "sha512-g3OMbtlwY3QewlqAiMLI47KywjWZoEytKr8pf6iTC8uJq5bIAH52Z9pnQ8pVL6whrCto53JZDuUIsifGeLorTg==",
+ "dev": true,
+ "dependencies": {
+ "get-intrinsic": "^1.1.3",
+ "has": "^1.0.3",
+ "has-tostringtag": "^1.0.0"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ }
+ },
+ "node_modules/es-shim-unscopables": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/es-shim-unscopables/-/es-shim-unscopables-1.0.0.tgz",
+ "integrity": "sha512-Jm6GPcCdC30eMLbZ2x8z2WuRwAws3zTBBKuusffYVUrNj/GVSUAZ+xKMaUpfNDR5IbyNA5LJbaecoUVbmUcB1w==",
+ "dev": true,
+ "dependencies": {
+ "has": "^1.0.3"
+ }
+ },
+ "node_modules/es-to-primitive": {
+ "version": "1.2.1",
+ "resolved": "https://registry.npmjs.org/es-to-primitive/-/es-to-primitive-1.2.1.tgz",
+ "integrity": "sha512-QCOllgZJtaUo9miYBcLChTUaHNjJF3PYs1VidD7AwiEj1kYxKeQTctLAezAOH5ZKRH0g2IgPn6KwB4IT8iRpvA==",
+ "dev": true,
+ "dependencies": {
+ "is-callable": "^1.1.4",
+ "is-date-object": "^1.0.1",
+ "is-symbol": "^1.0.2"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/escalade": {
+ "version": "3.1.1",
+ "resolved": "https://registry.npmjs.org/escalade/-/escalade-3.1.1.tgz",
+ "integrity": "sha512-k0er2gUkLf8O0zKJiAhmkTnJlTvINGv7ygDNPbeIsX/TJjGJZHuh9B2UxbsaEkmlEo9MfhrSzmhIlhRlI2GXnw==",
+ "dev": true,
+ "engines": {
+ "node": ">=6"
+ }
+ },
+ "node_modules/escape-string-regexp": {
+ "version": "1.0.5",
+ "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz",
+ "integrity": "sha1-G2HAViGQqN/2rjuyzwIAyhMLhtQ=",
+ "dev": true,
+ "engines": {
+ "node": ">=0.8.0"
+ }
+ },
+ "node_modules/escodegen": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/escodegen/-/escodegen-2.0.0.tgz",
+ "integrity": "sha512-mmHKys/C8BFUGI+MAWNcSYoORYLMdPzjrknd2Vc+bUsjN5bXcr8EhrNB+UTqfL1y3I9c4fw2ihgtMPQLBRiQxw==",
+ "dev": true,
+ "peer": true,
+ "dependencies": {
+ "esprima": "^4.0.1",
+ "estraverse": "^5.2.0",
+ "esutils": "^2.0.2",
+ "optionator": "^0.8.1"
+ },
+ "bin": {
+ "escodegen": "bin/escodegen.js",
+ "esgenerate": "bin/esgenerate.js"
+ },
+ "engines": {
+ "node": ">=6.0"
+ },
+ "optionalDependencies": {
+ "source-map": "~0.6.1"
+ }
+ },
+ "node_modules/escodegen/node_modules/levn": {
+ "version": "0.3.0",
+ "resolved": "https://registry.npmjs.org/levn/-/levn-0.3.0.tgz",
+ "integrity": "sha1-OwmSTt+fCDwEkP3UwLxEIeBHZO4=",
+ "dev": true,
+ "peer": true,
+ "dependencies": {
+ "prelude-ls": "~1.1.2",
+ "type-check": "~0.3.2"
+ },
+ "engines": {
+ "node": ">= 0.8.0"
+ }
+ },
+ "node_modules/escodegen/node_modules/optionator": {
+ "version": "0.8.3",
+ "resolved": "https://registry.npmjs.org/optionator/-/optionator-0.8.3.tgz",
+ "integrity": "sha512-+IW9pACdk3XWmmTXG8m3upGUJst5XRGzxMRjXzAuJ1XnIFNvfhjjIuYkDvysnPQ7qzqVzLt78BCruntqRhWQbA==",
+ "dev": true,
+ "peer": true,
+ "dependencies": {
+ "deep-is": "~0.1.3",
+ "fast-levenshtein": "~2.0.6",
+ "levn": "~0.3.0",
+ "prelude-ls": "~1.1.2",
+ "type-check": "~0.3.2",
+ "word-wrap": "~1.2.3"
+ },
+ "engines": {
+ "node": ">= 0.8.0"
+ }
+ },
+ "node_modules/escodegen/node_modules/prelude-ls": {
+ "version": "1.1.2",
+ "resolved": "https://registry.npmjs.org/prelude-ls/-/prelude-ls-1.1.2.tgz",
+ "integrity": "sha1-IZMqVJ9eUv/ZqCf1cOBL5iqX2lQ=",
+ "dev": true,
+ "peer": true,
+ "engines": {
+ "node": ">= 0.8.0"
+ }
+ },
+ "node_modules/escodegen/node_modules/type-check": {
+ "version": "0.3.2",
+ "resolved": "https://registry.npmjs.org/type-check/-/type-check-0.3.2.tgz",
+ "integrity": "sha1-WITKtRLPHTVeP7eE8wgEsrUg23I=",
+ "dev": true,
+ "peer": true,
+ "dependencies": {
+ "prelude-ls": "~1.1.2"
+ },
+ "engines": {
+ "node": ">= 0.8.0"
+ }
+ },
+ "node_modules/eslint": {
+ "version": "8.36.0",
+ "resolved": "https://registry.npmjs.org/eslint/-/eslint-8.36.0.tgz",
+ "integrity": "sha512-Y956lmS7vDqomxlaaQAHVmeb4tNMp2FWIvU/RnU5BD3IKMD/MJPr76xdyr68P8tV1iNMvN2mRK0yy3c+UjL+bw==",
+ "dev": true,
+ "dependencies": {
+ "@eslint-community/eslint-utils": "^4.2.0",
+ "@eslint-community/regexpp": "^4.4.0",
+ "@eslint/eslintrc": "^2.0.1",
+ "@eslint/js": "8.36.0",
+ "@humanwhocodes/config-array": "^0.11.8",
+ "@humanwhocodes/module-importer": "^1.0.1",
+ "@nodelib/fs.walk": "^1.2.8",
+ "ajv": "^6.10.0",
+ "chalk": "^4.0.0",
+ "cross-spawn": "^7.0.2",
+ "debug": "^4.3.2",
+ "doctrine": "^3.0.0",
+ "escape-string-regexp": "^4.0.0",
+ "eslint-scope": "^7.1.1",
+ "eslint-visitor-keys": "^3.3.0",
+ "espree": "^9.5.0",
+ "esquery": "^1.4.2",
+ "esutils": "^2.0.2",
+ "fast-deep-equal": "^3.1.3",
+ "file-entry-cache": "^6.0.1",
+ "find-up": "^5.0.0",
+ "glob-parent": "^6.0.2",
+ "globals": "^13.19.0",
+ "grapheme-splitter": "^1.0.4",
+ "ignore": "^5.2.0",
+ "import-fresh": "^3.0.0",
+ "imurmurhash": "^0.1.4",
+ "is-glob": "^4.0.0",
+ "is-path-inside": "^3.0.3",
+ "js-sdsl": "^4.1.4",
+ "js-yaml": "^4.1.0",
+ "json-stable-stringify-without-jsonify": "^1.0.1",
+ "levn": "^0.4.1",
+ "lodash.merge": "^4.6.2",
+ "minimatch": "^3.1.2",
+ "natural-compare": "^1.4.0",
+ "optionator": "^0.9.1",
+ "strip-ansi": "^6.0.1",
+ "strip-json-comments": "^3.1.0",
+ "text-table": "^0.2.0"
+ },
+ "bin": {
+ "eslint": "bin/eslint.js"
+ },
+ "engines": {
+ "node": "^12.22.0 || ^14.17.0 || >=16.0.0"
+ },
+ "funding": {
+ "url": "https://opencollective.com/eslint"
+ }
+ },
+ "node_modules/eslint-config-next": {
+ "version": "13.2.4",
+ "resolved": "https://registry.npmjs.org/eslint-config-next/-/eslint-config-next-13.2.4.tgz",
+ "integrity": "sha512-lunIBhsoeqw6/Lfkd6zPt25w1bn0znLA/JCL+au1HoEpSb4/PpsOYsYtgV/q+YPsoKIOzFyU5xnb04iZnXjUvg==",
+ "dev": true,
+ "dependencies": {
+ "@next/eslint-plugin-next": "13.2.4",
+ "@rushstack/eslint-patch": "^1.1.3",
+ "@typescript-eslint/parser": "^5.42.0",
+ "eslint-import-resolver-node": "^0.3.6",
+ "eslint-import-resolver-typescript": "^3.5.2",
+ "eslint-plugin-import": "^2.26.0",
+ "eslint-plugin-jsx-a11y": "^6.5.1",
+ "eslint-plugin-react": "^7.31.7",
+ "eslint-plugin-react-hooks": "^4.5.0"
+ },
+ "peerDependencies": {
+ "eslint": "^7.23.0 || ^8.0.0",
+ "typescript": ">=3.3.1"
+ },
+ "peerDependenciesMeta": {
+ "typescript": {
+ "optional": true
+ }
+ }
+ },
+ "node_modules/eslint-config-prettier": {
+ "version": "8.7.0",
+ "resolved": "https://registry.npmjs.org/eslint-config-prettier/-/eslint-config-prettier-8.7.0.tgz",
+ "integrity": "sha512-HHVXLSlVUhMSmyW4ZzEuvjpwqamgmlfkutD53cYXLikh4pt/modINRcCIApJ84czDxM4GZInwUrromsDdTImTA==",
+ "dev": true,
+ "bin": {
+ "eslint-config-prettier": "bin/cli.js"
+ },
+ "peerDependencies": {
+ "eslint": ">=7.0.0"
+ }
+ },
+ "node_modules/eslint-import-resolver-node": {
+ "version": "0.3.7",
+ "resolved": "https://registry.npmjs.org/eslint-import-resolver-node/-/eslint-import-resolver-node-0.3.7.tgz",
+ "integrity": "sha512-gozW2blMLJCeFpBwugLTGyvVjNoeo1knonXAcatC6bjPBZitotxdWf7Gimr25N4c0AAOo4eOUfaG82IJPDpqCA==",
+ "dev": true,
+ "dependencies": {
+ "debug": "^3.2.7",
+ "is-core-module": "^2.11.0",
+ "resolve": "^1.22.1"
+ }
+ },
+ "node_modules/eslint-import-resolver-node/node_modules/debug": {
+ "version": "3.2.7",
+ "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.7.tgz",
+ "integrity": "sha512-CFjzYYAi4ThfiQvizrFQevTTXHtnCqWfe7x1AhgEscTz6ZbLbfoLRLPugTQyBth6f8ZERVUSyWHFD/7Wu4t1XQ==",
+ "dev": true,
+ "dependencies": {
+ "ms": "^2.1.1"
+ }
+ },
+ "node_modules/eslint-import-resolver-node/node_modules/resolve": {
+ "version": "1.22.1",
+ "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.22.1.tgz",
+ "integrity": "sha512-nBpuuYuY5jFsli/JIs1oldw6fOQCBioohqWZg/2hiaOybXOft4lonv85uDOKXdf8rhyK159cxU5cDcK/NKk8zw==",
+ "dev": true,
+ "dependencies": {
+ "is-core-module": "^2.9.0",
+ "path-parse": "^1.0.7",
+ "supports-preserve-symlinks-flag": "^1.0.0"
+ },
+ "bin": {
+ "resolve": "bin/resolve"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/eslint-import-resolver-typescript": {
+ "version": "3.5.3",
+ "resolved": "https://registry.npmjs.org/eslint-import-resolver-typescript/-/eslint-import-resolver-typescript-3.5.3.tgz",
+ "integrity": "sha512-njRcKYBc3isE42LaTcJNVANR3R99H9bAxBDMNDr2W7yq5gYPxbU3MkdhsQukxZ/Xg9C2vcyLlDsbKfRDg0QvCQ==",
+ "dev": true,
+ "dependencies": {
+ "debug": "^4.3.4",
+ "enhanced-resolve": "^5.10.0",
+ "get-tsconfig": "^4.2.0",
+ "globby": "^13.1.2",
+ "is-core-module": "^2.10.0",
+ "is-glob": "^4.0.3",
+ "synckit": "^0.8.4"
+ },
+ "engines": {
+ "node": "^14.18.0 || >=16.0.0"
+ },
+ "funding": {
+ "url": "https://opencollective.com/unts/projects/eslint-import-resolver-ts"
+ },
+ "peerDependencies": {
+ "eslint": "*",
+ "eslint-plugin-import": "*"
+ }
+ },
+ "node_modules/eslint-import-resolver-typescript/node_modules/globby": {
+ "version": "13.1.3",
+ "resolved": "https://registry.npmjs.org/globby/-/globby-13.1.3.tgz",
+ "integrity": "sha512-8krCNHXvlCgHDpegPzleMq07yMYTO2sXKASmZmquEYWEmCx6J5UTRbp5RwMJkTJGtcQ44YpiUYUiN0b9mzy8Bw==",
+ "dev": true,
+ "dependencies": {
+ "dir-glob": "^3.0.1",
+ "fast-glob": "^3.2.11",
+ "ignore": "^5.2.0",
+ "merge2": "^1.4.1",
+ "slash": "^4.0.0"
+ },
+ "engines": {
+ "node": "^12.20.0 || ^14.13.1 || >=16.0.0"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
+ "node_modules/eslint-import-resolver-typescript/node_modules/slash": {
+ "version": "4.0.0",
+ "resolved": "https://registry.npmjs.org/slash/-/slash-4.0.0.tgz",
+ "integrity": "sha512-3dOsAHXXUkQTpOYcoAxLIorMTp4gIQr5IW3iVb7A7lFIp0VHhnynm9izx6TssdrIcVIESAlVjtnO2K8bg+Coew==",
+ "dev": true,
+ "engines": {
+ "node": ">=12"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
+ "node_modules/eslint-module-utils": {
+ "version": "2.7.4",
+ "resolved": "https://registry.npmjs.org/eslint-module-utils/-/eslint-module-utils-2.7.4.tgz",
+ "integrity": "sha512-j4GT+rqzCoRKHwURX7pddtIPGySnX9Si/cgMI5ztrcqOPtk5dDEeZ34CQVPphnqkJytlc97Vuk05Um2mJ3gEQA==",
+ "dev": true,
+ "dependencies": {
+ "debug": "^3.2.7"
+ },
+ "engines": {
+ "node": ">=4"
+ },
+ "peerDependenciesMeta": {
+ "eslint": {
+ "optional": true
+ }
+ }
+ },
+ "node_modules/eslint-module-utils/node_modules/debug": {
+ "version": "3.2.7",
+ "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.7.tgz",
+ "integrity": "sha512-CFjzYYAi4ThfiQvizrFQevTTXHtnCqWfe7x1AhgEscTz6ZbLbfoLRLPugTQyBth6f8ZERVUSyWHFD/7Wu4t1XQ==",
+ "dev": true,
+ "dependencies": {
+ "ms": "^2.1.1"
+ }
+ },
+ "node_modules/eslint-plugin-import": {
+ "version": "2.27.5",
+ "resolved": "https://registry.npmjs.org/eslint-plugin-import/-/eslint-plugin-import-2.27.5.tgz",
+ "integrity": "sha512-LmEt3GVofgiGuiE+ORpnvP+kAm3h6MLZJ4Q5HCyHADofsb4VzXFsRiWj3c0OFiV+3DWFh0qg3v9gcPlfc3zRow==",
+ "dev": true,
+ "dependencies": {
+ "array-includes": "^3.1.6",
+ "array.prototype.flat": "^1.3.1",
+ "array.prototype.flatmap": "^1.3.1",
+ "debug": "^3.2.7",
+ "doctrine": "^2.1.0",
+ "eslint-import-resolver-node": "^0.3.7",
+ "eslint-module-utils": "^2.7.4",
+ "has": "^1.0.3",
+ "is-core-module": "^2.11.0",
+ "is-glob": "^4.0.3",
+ "minimatch": "^3.1.2",
+ "object.values": "^1.1.6",
+ "resolve": "^1.22.1",
+ "semver": "^6.3.0",
+ "tsconfig-paths": "^3.14.1"
+ },
+ "engines": {
+ "node": ">=4"
+ },
+ "peerDependencies": {
+ "eslint": "^2 || ^3 || ^4 || ^5 || ^6 || ^7.2.0 || ^8"
+ }
+ },
+ "node_modules/eslint-plugin-import/node_modules/debug": {
+ "version": "3.2.7",
+ "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.7.tgz",
+ "integrity": "sha512-CFjzYYAi4ThfiQvizrFQevTTXHtnCqWfe7x1AhgEscTz6ZbLbfoLRLPugTQyBth6f8ZERVUSyWHFD/7Wu4t1XQ==",
+ "dev": true,
+ "dependencies": {
+ "ms": "^2.1.1"
+ }
+ },
+ "node_modules/eslint-plugin-import/node_modules/doctrine": {
+ "version": "2.1.0",
+ "resolved": "https://registry.npmjs.org/doctrine/-/doctrine-2.1.0.tgz",
+ "integrity": "sha512-35mSku4ZXK0vfCuHEDAwt55dg2jNajHZ1odvF+8SSr82EsZY4QmXfuWso8oEd8zRhVObSN18aM0CjSdoBX7zIw==",
+ "dev": true,
+ "dependencies": {
+ "esutils": "^2.0.2"
+ },
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
+ "node_modules/eslint-plugin-import/node_modules/resolve": {
+ "version": "1.22.1",
+ "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.22.1.tgz",
+ "integrity": "sha512-nBpuuYuY5jFsli/JIs1oldw6fOQCBioohqWZg/2hiaOybXOft4lonv85uDOKXdf8rhyK159cxU5cDcK/NKk8zw==",
+ "dev": true,
+ "dependencies": {
+ "is-core-module": "^2.9.0",
+ "path-parse": "^1.0.7",
+ "supports-preserve-symlinks-flag": "^1.0.0"
+ },
+ "bin": {
+ "resolve": "bin/resolve"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/eslint-plugin-import/node_modules/semver": {
+ "version": "6.3.0",
+ "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz",
+ "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==",
+ "dev": true,
+ "bin": {
+ "semver": "bin/semver.js"
+ }
+ },
+ "node_modules/eslint-plugin-jsx-a11y": {
+ "version": "6.7.1",
+ "resolved": "https://registry.npmjs.org/eslint-plugin-jsx-a11y/-/eslint-plugin-jsx-a11y-6.7.1.tgz",
+ "integrity": "sha512-63Bog4iIethyo8smBklORknVjB0T2dwB8Mr/hIC+fBS0uyHdYYpzM/Ed+YC8VxTjlXHEWFOdmgwcDn1U2L9VCA==",
+ "dev": true,
+ "dependencies": {
+ "@babel/runtime": "^7.20.7",
+ "aria-query": "^5.1.3",
+ "array-includes": "^3.1.6",
+ "array.prototype.flatmap": "^1.3.1",
+ "ast-types-flow": "^0.0.7",
+ "axe-core": "^4.6.2",
+ "axobject-query": "^3.1.1",
+ "damerau-levenshtein": "^1.0.8",
+ "emoji-regex": "^9.2.2",
+ "has": "^1.0.3",
+ "jsx-ast-utils": "^3.3.3",
+ "language-tags": "=1.0.5",
+ "minimatch": "^3.1.2",
+ "object.entries": "^1.1.6",
+ "object.fromentries": "^2.0.6",
+ "semver": "^6.3.0"
+ },
+ "engines": {
+ "node": ">=4.0"
+ },
+ "peerDependencies": {
+ "eslint": "^3 || ^4 || ^5 || ^6 || ^7 || ^8"
+ }
+ },
+ "node_modules/eslint-plugin-jsx-a11y/node_modules/semver": {
+ "version": "6.3.0",
+ "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz",
+ "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==",
+ "dev": true,
+ "bin": {
+ "semver": "bin/semver.js"
+ }
+ },
+ "node_modules/eslint-plugin-prettier": {
+ "version": "4.2.1",
+ "resolved": "https://registry.npmjs.org/eslint-plugin-prettier/-/eslint-plugin-prettier-4.2.1.tgz",
+ "integrity": "sha512-f/0rXLXUt0oFYs8ra4w49wYZBG5GKZpAYsJSm6rnYL5uVDjd+zowwMwVZHnAjf4edNrKpCDYfXDgmRE/Ak7QyQ==",
+ "dev": true,
+ "dependencies": {
+ "prettier-linter-helpers": "^1.0.0"
+ },
+ "engines": {
+ "node": ">=12.0.0"
+ },
+ "peerDependencies": {
+ "eslint": ">=7.28.0",
+ "prettier": ">=2.0.0"
+ },
+ "peerDependenciesMeta": {
+ "eslint-config-prettier": {
+ "optional": true
+ }
+ }
+ },
+ "node_modules/eslint-plugin-react": {
+ "version": "7.32.2",
+ "resolved": "https://registry.npmjs.org/eslint-plugin-react/-/eslint-plugin-react-7.32.2.tgz",
+ "integrity": "sha512-t2fBMa+XzonrrNkyVirzKlvn5RXzzPwRHtMvLAtVZrt8oxgnTQaYbU6SXTOO1mwQgp1y5+toMSKInnzGr0Knqg==",
+ "dev": true,
+ "dependencies": {
+ "array-includes": "^3.1.6",
+ "array.prototype.flatmap": "^1.3.1",
+ "array.prototype.tosorted": "^1.1.1",
+ "doctrine": "^2.1.0",
+ "estraverse": "^5.3.0",
+ "jsx-ast-utils": "^2.4.1 || ^3.0.0",
+ "minimatch": "^3.1.2",
+ "object.entries": "^1.1.6",
+ "object.fromentries": "^2.0.6",
+ "object.hasown": "^1.1.2",
+ "object.values": "^1.1.6",
+ "prop-types": "^15.8.1",
+ "resolve": "^2.0.0-next.4",
+ "semver": "^6.3.0",
+ "string.prototype.matchall": "^4.0.8"
+ },
+ "engines": {
+ "node": ">=4"
+ },
+ "peerDependencies": {
+ "eslint": "^3 || ^4 || ^5 || ^6 || ^7 || ^8"
+ }
+ },
+ "node_modules/eslint-plugin-react-hooks": {
+ "version": "4.6.0",
+ "resolved": "https://registry.npmjs.org/eslint-plugin-react-hooks/-/eslint-plugin-react-hooks-4.6.0.tgz",
+ "integrity": "sha512-oFc7Itz9Qxh2x4gNHStv3BqJq54ExXmfC+a1NjAta66IAN87Wu0R/QArgIS9qKzX3dXKPI9H5crl9QchNMY9+g==",
+ "dev": true,
+ "engines": {
+ "node": ">=10"
+ },
+ "peerDependencies": {
+ "eslint": "^3.0.0 || ^4.0.0 || ^5.0.0 || ^6.0.0 || ^7.0.0 || ^8.0.0-0"
+ }
+ },
+ "node_modules/eslint-plugin-react/node_modules/doctrine": {
+ "version": "2.1.0",
+ "resolved": "https://registry.npmjs.org/doctrine/-/doctrine-2.1.0.tgz",
+ "integrity": "sha512-35mSku4ZXK0vfCuHEDAwt55dg2jNajHZ1odvF+8SSr82EsZY4QmXfuWso8oEd8zRhVObSN18aM0CjSdoBX7zIw==",
+ "dev": true,
+ "dependencies": {
+ "esutils": "^2.0.2"
+ },
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
+ "node_modules/eslint-plugin-react/node_modules/resolve": {
+ "version": "2.0.0-next.4",
+ "resolved": "https://registry.npmjs.org/resolve/-/resolve-2.0.0-next.4.tgz",
+ "integrity": "sha512-iMDbmAWtfU+MHpxt/I5iWI7cY6YVEZUQ3MBgPQ++XD1PELuJHIl82xBmObyP2KyQmkNB2dsqF7seoQQiAn5yDQ==",
+ "dev": true,
+ "dependencies": {
+ "is-core-module": "^2.9.0",
+ "path-parse": "^1.0.7",
+ "supports-preserve-symlinks-flag": "^1.0.0"
+ },
+ "bin": {
+ "resolve": "bin/resolve"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/eslint-plugin-react/node_modules/semver": {
+ "version": "6.3.0",
+ "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz",
+ "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==",
+ "dev": true,
+ "bin": {
+ "semver": "bin/semver.js"
+ }
+ },
+ "node_modules/eslint-scope": {
+ "version": "5.1.1",
+ "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-5.1.1.tgz",
+ "integrity": "sha512-2NxwbF/hZ0KpepYN0cNbo+FN6XoK7GaHlQhgx/hIZl6Va0bF45RQOOwhLIy8lQDbuCiadSLCBnH2CFYquit5bw==",
+ "dev": true,
+ "dependencies": {
+ "esrecurse": "^4.3.0",
+ "estraverse": "^4.1.1"
+ },
+ "engines": {
+ "node": ">=8.0.0"
+ }
+ },
+ "node_modules/eslint-scope/node_modules/estraverse": {
+ "version": "4.3.0",
+ "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-4.3.0.tgz",
+ "integrity": "sha512-39nnKffWz8xN1BU/2c79n9nB9HDzo0niYUqx6xyqUnyoAnQyyWpOTdZEeiCch8BBu515t4wp9ZmgVfVhn9EBpw==",
+ "dev": true,
+ "engines": {
+ "node": ">=4.0"
+ }
+ },
+ "node_modules/eslint-visitor-keys": {
+ "version": "3.3.0",
+ "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-3.3.0.tgz",
+ "integrity": "sha512-mQ+suqKJVyeuwGYHAdjMFqjCyfl8+Ldnxuyp3ldiMBFKkvytrXUZWaiPCEav8qDHKty44bD+qV1IP4T+w+xXRA==",
+ "dev": true,
+ "engines": {
+ "node": "^12.22.0 || ^14.17.0 || >=16.0.0"
+ }
+ },
+ "node_modules/eslint/node_modules/escape-string-regexp": {
+ "version": "4.0.0",
+ "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz",
+ "integrity": "sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA==",
+ "dev": true,
+ "engines": {
+ "node": ">=10"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
+ "node_modules/eslint/node_modules/eslint-scope": {
+ "version": "7.1.1",
+ "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-7.1.1.tgz",
+ "integrity": "sha512-QKQM/UXpIiHcLqJ5AOyIW7XZmzjkzQXYE54n1++wb0u9V/abW3l9uQnxX8Z5Xd18xyKIMTUAyQ0k1e8pz6LUrw==",
+ "dev": true,
+ "dependencies": {
+ "esrecurse": "^4.3.0",
+ "estraverse": "^5.2.0"
+ },
+ "engines": {
+ "node": "^12.22.0 || ^14.17.0 || >=16.0.0"
+ }
+ },
+ "node_modules/eslint/node_modules/find-up": {
+ "version": "5.0.0",
+ "resolved": "https://registry.npmjs.org/find-up/-/find-up-5.0.0.tgz",
+ "integrity": "sha512-78/PXT1wlLLDgTzDs7sjq9hzz0vXD+zn+7wypEe4fXQxCmdmqfGsEPQxmiCSQI3ajFV91bVSsvNtrJRiW6nGng==",
+ "dev": true,
+ "dependencies": {
+ "locate-path": "^6.0.0",
+ "path-exists": "^4.0.0"
+ },
+ "engines": {
+ "node": ">=10"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
+ "node_modules/eslint/node_modules/locate-path": {
+ "version": "6.0.0",
+ "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-6.0.0.tgz",
+ "integrity": "sha512-iPZK6eYjbxRu3uB4/WZ3EsEIMJFMqAoopl3R+zuq0UjcAm/MO6KCweDgPfP3elTztoKP3KtnVHxTn2NHBSDVUw==",
+ "dev": true,
+ "dependencies": {
+ "p-locate": "^5.0.0"
+ },
+ "engines": {
+ "node": ">=10"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
+ "node_modules/eslint/node_modules/p-locate": {
+ "version": "5.0.0",
+ "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-5.0.0.tgz",
+ "integrity": "sha512-LaNjtRWUBY++zB5nE/NwcaoMylSPk+S+ZHNB1TzdbMJMny6dynpAGt7X/tl/QYq3TIeE6nxHppbo2LGymrG5Pw==",
+ "dev": true,
+ "dependencies": {
+ "p-limit": "^3.0.2"
+ },
+ "engines": {
+ "node": ">=10"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
+ "node_modules/espree": {
+ "version": "9.5.0",
+ "resolved": "https://registry.npmjs.org/espree/-/espree-9.5.0.tgz",
+ "integrity": "sha512-JPbJGhKc47++oo4JkEoTe2wjy4fmMwvFpgJT9cQzmfXKp22Dr6Hf1tdCteLz1h0P3t+mGvWZ+4Uankvh8+c6zw==",
+ "dev": true,
+ "dependencies": {
+ "acorn": "^8.8.0",
+ "acorn-jsx": "^5.3.2",
+ "eslint-visitor-keys": "^3.3.0"
+ },
+ "engines": {
+ "node": "^12.22.0 || ^14.17.0 || >=16.0.0"
+ },
+ "funding": {
+ "url": "https://opencollective.com/eslint"
+ }
+ },
+ "node_modules/esprima": {
+ "version": "4.0.1",
+ "resolved": "https://registry.npmjs.org/esprima/-/esprima-4.0.1.tgz",
+ "integrity": "sha512-eGuFFw7Upda+g4p+QHvnW0RyTX/SVeJBDM/gCtMARO0cLuT2HcEKnTPvhjV6aGeqrCB/sbNop0Kszm0jsaWU4A==",
+ "dev": true,
+ "peer": true,
+ "bin": {
+ "esparse": "bin/esparse.js",
+ "esvalidate": "bin/esvalidate.js"
+ },
+ "engines": {
+ "node": ">=4"
+ }
+ },
+ "node_modules/esquery": {
+ "version": "1.5.0",
+ "resolved": "https://registry.npmjs.org/esquery/-/esquery-1.5.0.tgz",
+ "integrity": "sha512-YQLXUplAwJgCydQ78IMJywZCceoqk1oH01OERdSAJc/7U2AylwjhSCLDEtqwg811idIS/9fIU5GjG73IgjKMVg==",
+ "dev": true,
+ "dependencies": {
+ "estraverse": "^5.1.0"
+ },
+ "engines": {
+ "node": ">=0.10"
+ }
+ },
+ "node_modules/esrecurse": {
+ "version": "4.3.0",
+ "resolved": "https://registry.npmjs.org/esrecurse/-/esrecurse-4.3.0.tgz",
+ "integrity": "sha512-KmfKL3b6G+RXvP8N1vr3Tq1kL/oCFgn2NYXEtqP8/L3pKapUA4G8cFVaoF3SU323CD4XypR/ffioHmkti6/Tag==",
+ "dev": true,
+ "dependencies": {
+ "estraverse": "^5.2.0"
+ },
+ "engines": {
+ "node": ">=4.0"
+ }
+ },
+ "node_modules/estraverse": {
+ "version": "5.3.0",
+ "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-5.3.0.tgz",
+ "integrity": "sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA==",
+ "dev": true,
+ "engines": {
+ "node": ">=4.0"
+ }
+ },
+ "node_modules/esutils": {
+ "version": "2.0.3",
+ "resolved": "https://registry.npmjs.org/esutils/-/esutils-2.0.3.tgz",
+ "integrity": "sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g==",
+ "dev": true,
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
+ "node_modules/exec-sh": {
+ "version": "0.3.6",
+ "resolved": "https://registry.npmjs.org/exec-sh/-/exec-sh-0.3.6.tgz",
+ "integrity": "sha512-nQn+hI3yp+oD0huYhKwvYI32+JFeq+XkNcD1GAo3Y/MjxsfVGmrrzrnzjWiNY6f+pUCP440fThsFh5gZrRAU/w==",
+ "dev": true,
+ "peer": true
+ },
+ "node_modules/execa": {
+ "version": "4.1.0",
+ "resolved": "https://registry.npmjs.org/execa/-/execa-4.1.0.tgz",
+ "integrity": "sha512-j5W0//W7f8UxAn8hXVnwG8tLwdiUy4FJLcSupCg6maBYZDpyBvTApK7KyuI4bKj8KOh1r2YH+6ucuYtJv1bTZA==",
+ "dev": true,
+ "peer": true,
+ "dependencies": {
+ "cross-spawn": "^7.0.0",
+ "get-stream": "^5.0.0",
+ "human-signals": "^1.1.1",
+ "is-stream": "^2.0.0",
+ "merge-stream": "^2.0.0",
+ "npm-run-path": "^4.0.0",
+ "onetime": "^5.1.0",
+ "signal-exit": "^3.0.2",
+ "strip-final-newline": "^2.0.0"
+ },
+ "engines": {
+ "node": ">=10"
+ },
+ "funding": {
+ "url": "https://github.com/sindresorhus/execa?sponsor=1"
+ }
+ },
+ "node_modules/execall": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/execall/-/execall-2.0.0.tgz",
+ "integrity": "sha512-0FU2hZ5Hh6iQnarpRtQurM/aAvp3RIbfvgLHrcqJYzhXyV2KFruhuChf9NC6waAhiUR7FFtlugkI4p7f2Fqlow==",
+ "dev": true,
+ "dependencies": {
+ "clone-regexp": "^2.1.0"
+ },
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/exit": {
+ "version": "0.1.2",
+ "resolved": "https://registry.npmjs.org/exit/-/exit-0.1.2.tgz",
+ "integrity": "sha1-BjJjj42HfMghB9MKD/8aF8uhzQw=",
+ "dev": true,
+ "peer": true,
+ "engines": {
+ "node": ">= 0.8.0"
+ }
+ },
+ "node_modules/expand-brackets": {
+ "version": "2.1.4",
+ "resolved": "https://registry.npmjs.org/expand-brackets/-/expand-brackets-2.1.4.tgz",
+ "integrity": "sha1-t3c14xXOMPa27/D4OwQVGiJEliI=",
+ "dev": true,
+ "peer": true,
+ "dependencies": {
+ "debug": "^2.3.3",
+ "define-property": "^0.2.5",
+ "extend-shallow": "^2.0.1",
+ "posix-character-classes": "^0.1.0",
+ "regex-not": "^1.0.0",
+ "snapdragon": "^0.8.1",
+ "to-regex": "^3.0.1"
+ },
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
+ "node_modules/expand-brackets/node_modules/debug": {
+ "version": "2.6.9",
+ "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz",
+ "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==",
+ "dev": true,
+ "peer": true,
+ "dependencies": {
+ "ms": "2.0.0"
+ }
+ },
+ "node_modules/expand-brackets/node_modules/define-property": {
+ "version": "0.2.5",
+ "resolved": "https://registry.npmjs.org/define-property/-/define-property-0.2.5.tgz",
+ "integrity": "sha1-w1se+RjsPJkPmlvFe+BKrOxcgRY=",
+ "dev": true,
+ "peer": true,
+ "dependencies": {
+ "is-descriptor": "^0.1.0"
+ },
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
+ "node_modules/expand-brackets/node_modules/extend-shallow": {
+ "version": "2.0.1",
+ "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz",
+ "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=",
+ "dev": true,
+ "peer": true,
+ "dependencies": {
+ "is-extendable": "^0.1.0"
+ },
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
+ "node_modules/expand-brackets/node_modules/is-accessor-descriptor": {
+ "version": "0.1.6",
+ "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-0.1.6.tgz",
+ "integrity": "sha1-qeEss66Nh2cn7u84Q/igiXtcmNY=",
+ "dev": true,
+ "peer": true,
+ "dependencies": {
+ "kind-of": "^3.0.2"
+ },
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
+ "node_modules/expand-brackets/node_modules/is-accessor-descriptor/node_modules/kind-of": {
+ "version": "3.2.2",
+ "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz",
+ "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=",
+ "dev": true,
+ "peer": true,
+ "dependencies": {
+ "is-buffer": "^1.1.5"
+ },
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
+ "node_modules/expand-brackets/node_modules/is-buffer": {
+ "version": "1.1.6",
+ "resolved": "https://registry.npmjs.org/is-buffer/-/is-buffer-1.1.6.tgz",
+ "integrity": "sha512-NcdALwpXkTm5Zvvbk7owOUSvVvBKDgKP5/ewfXEznmQFfs4ZRmanOeKBTjRVjka3QFoN6XJ+9F3USqfHqTaU5w==",
+ "dev": true,
+ "peer": true
+ },
+ "node_modules/expand-brackets/node_modules/is-data-descriptor": {
+ "version": "0.1.4",
+ "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-0.1.4.tgz",
+ "integrity": "sha1-C17mSDiOLIYCgueT8YVv7D8wG1Y=",
+ "dev": true,
+ "peer": true,
+ "dependencies": {
+ "kind-of": "^3.0.2"
+ },
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
+ "node_modules/expand-brackets/node_modules/is-data-descriptor/node_modules/kind-of": {
+ "version": "3.2.2",
+ "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz",
+ "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=",
+ "dev": true,
+ "peer": true,
+ "dependencies": {
+ "is-buffer": "^1.1.5"
+ },
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
+ "node_modules/expand-brackets/node_modules/is-descriptor": {
+ "version": "0.1.6",
+ "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-0.1.6.tgz",
+ "integrity": "sha512-avDYr0SB3DwO9zsMov0gKCESFYqCnE4hq/4z3TdUlukEy5t9C0YRq7HLrsN52NAcqXKaepeCD0n+B0arnVG3Hg==",
+ "dev": true,
+ "peer": true,
+ "dependencies": {
+ "is-accessor-descriptor": "^0.1.6",
+ "is-data-descriptor": "^0.1.4",
+ "kind-of": "^5.0.0"
+ },
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
+ "node_modules/expand-brackets/node_modules/is-extendable": {
+ "version": "0.1.1",
+ "resolved": "https://registry.npmjs.org/is-extendable/-/is-extendable-0.1.1.tgz",
+ "integrity": "sha1-YrEQ4omkcUGOPsNqYX1HLjAd/Ik=",
+ "dev": true,
+ "peer": true,
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
+ "node_modules/expand-brackets/node_modules/kind-of": {
+ "version": "5.1.0",
+ "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-5.1.0.tgz",
+ "integrity": "sha512-NGEErnH6F2vUuXDh+OlbcKW7/wOcfdRHaZ7VWtqCztfHri/++YKmP51OdWeGPuqCOba6kk2OTe5d02VmTB80Pw==",
+ "dev": true,
+ "peer": true,
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
+ "node_modules/expand-brackets/node_modules/ms": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz",
+ "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=",
+ "dev": true,
+ "peer": true
+ },
+ "node_modules/expect": {
+ "version": "26.6.2",
+ "resolved": "https://registry.npmjs.org/expect/-/expect-26.6.2.tgz",
+ "integrity": "sha512-9/hlOBkQl2l/PLHJx6JjoDF6xPKcJEsUlWKb23rKE7KzeDqUZKXKNMW27KIue5JMdBV9HgmoJPcc8HtO85t9IA==",
+ "dev": true,
+ "peer": true,
+ "dependencies": {
+ "@jest/types": "^26.6.2",
+ "ansi-styles": "^4.0.0",
+ "jest-get-type": "^26.3.0",
+ "jest-matcher-utils": "^26.6.2",
+ "jest-message-util": "^26.6.2",
+ "jest-regex-util": "^26.0.0"
+ },
+ "engines": {
+ "node": ">= 10.14.2"
+ }
+ },
+ "node_modules/extend": {
+ "version": "3.0.2",
+ "resolved": "https://registry.npmjs.org/extend/-/extend-3.0.2.tgz",
+ "integrity": "sha512-fjquC59cD7CyW6urNXK0FBufkZcoiGG80wTuPujX590cB5Ttln20E2UB4S/WARVqhXffZl2LNgS+gQdPIIim/g==",
+ "dev": true
+ },
+ "node_modules/extend-shallow": {
+ "version": "3.0.2",
+ "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-3.0.2.tgz",
+ "integrity": "sha1-Jqcarwc7OfshJxcnRhMcJwQCjbg=",
+ "dev": true,
+ "peer": true,
+ "dependencies": {
+ "assign-symbols": "^1.0.0",
+ "is-extendable": "^1.0.1"
+ },
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
+ "node_modules/external-editor": {
+ "version": "3.1.0",
+ "resolved": "https://registry.npmjs.org/external-editor/-/external-editor-3.1.0.tgz",
+ "integrity": "sha512-hMQ4CX1p1izmuLYyZqLMO/qGNw10wSv9QDCPfzXfyFrOaCSSoRfqE1Kf1s5an66J5JZC62NewG+mK49jOCtQew==",
+ "dev": true,
+ "dependencies": {
+ "chardet": "^0.7.0",
+ "iconv-lite": "^0.4.24",
+ "tmp": "^0.0.33"
+ },
+ "engines": {
+ "node": ">=4"
+ }
+ },
+ "node_modules/extglob": {
+ "version": "2.0.4",
+ "resolved": "https://registry.npmjs.org/extglob/-/extglob-2.0.4.tgz",
+ "integrity": "sha512-Nmb6QXkELsuBr24CJSkilo6UHHgbekK5UiZgfE6UHD3Eb27YC6oD+bhcT+tJ6cl8dmsgdQxnWlcry8ksBIBLpw==",
+ "dev": true,
+ "peer": true,
+ "dependencies": {
+ "array-unique": "^0.3.2",
+ "define-property": "^1.0.0",
+ "expand-brackets": "^2.1.4",
+ "extend-shallow": "^2.0.1",
+ "fragment-cache": "^0.2.1",
+ "regex-not": "^1.0.0",
+ "snapdragon": "^0.8.1",
+ "to-regex": "^3.0.1"
+ },
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
+ "node_modules/extglob/node_modules/define-property": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/define-property/-/define-property-1.0.0.tgz",
+ "integrity": "sha1-dp66rz9KY6rTr56NMEybvnm/sOY=",
+ "dev": true,
+ "peer": true,
+ "dependencies": {
+ "is-descriptor": "^1.0.0"
+ },
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
+ "node_modules/extglob/node_modules/extend-shallow": {
+ "version": "2.0.1",
+ "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz",
+ "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=",
+ "dev": true,
+ "peer": true,
+ "dependencies": {
+ "is-extendable": "^0.1.0"
+ },
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
+ "node_modules/extglob/node_modules/is-extendable": {
+ "version": "0.1.1",
+ "resolved": "https://registry.npmjs.org/is-extendable/-/is-extendable-0.1.1.tgz",
+ "integrity": "sha1-YrEQ4omkcUGOPsNqYX1HLjAd/Ik=",
+ "dev": true,
+ "peer": true,
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
+ "node_modules/extract-files": {
+ "version": "9.0.0",
+ "resolved": "https://registry.npmjs.org/extract-files/-/extract-files-9.0.0.tgz",
+ "integrity": "sha512-CvdFfHkC95B4bBBk36hcEmvdR2awOdhhVUYH6S/zrVj3477zven/fJMYg7121h4T1xHZC+tetUpubpAhxwI7hQ==",
+ "dev": true,
+ "engines": {
+ "node": "^10.17.0 || ^12.0.0 || >= 13.7.0"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/jaydenseric"
+ }
+ },
+ "node_modules/fast-deep-equal": {
+ "version": "3.1.3",
+ "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz",
+ "integrity": "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==",
+ "dev": true
+ },
+ "node_modules/fast-diff": {
+ "version": "1.2.0",
+ "resolved": "https://registry.npmjs.org/fast-diff/-/fast-diff-1.2.0.tgz",
+ "integrity": "sha512-xJuoT5+L99XlZ8twedaRf6Ax2TgQVxvgZOYoPKqZufmJib0tL2tegPBOZb1pVNgIhlqDlA0eO0c3wBvQcmzx4w==",
+ "dev": true
+ },
+ "node_modules/fast-glob": {
+ "version": "3.2.11",
+ "resolved": "https://registry.npmjs.org/fast-glob/-/fast-glob-3.2.11.tgz",
+ "integrity": "sha512-xrO3+1bxSo3ZVHAnqzyuewYT6aMFHRAd4Kcs92MAonjwQZLsK9d0SF1IyQ3k5PoirxTW0Oe/RqFgMQ6TcNE5Ew==",
+ "dev": true,
+ "dependencies": {
+ "@nodelib/fs.stat": "^2.0.2",
+ "@nodelib/fs.walk": "^1.2.3",
+ "glob-parent": "^5.1.2",
+ "merge2": "^1.3.0",
+ "micromatch": "^4.0.4"
+ },
+ "engines": {
+ "node": ">=8.6.0"
+ }
+ },
+ "node_modules/fast-glob/node_modules/glob-parent": {
+ "version": "5.1.2",
+ "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz",
+ "integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==",
+ "dev": true,
+ "dependencies": {
+ "is-glob": "^4.0.1"
+ },
+ "engines": {
+ "node": ">= 6"
+ }
+ },
+ "node_modules/fast-json-stable-stringify": {
+ "version": "2.1.0",
+ "resolved": "https://registry.npmjs.org/fast-json-stable-stringify/-/fast-json-stable-stringify-2.1.0.tgz",
+ "integrity": "sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw==",
+ "dev": true
+ },
+ "node_modules/fast-levenshtein": {
+ "version": "2.0.6",
+ "resolved": "https://registry.npmjs.org/fast-levenshtein/-/fast-levenshtein-2.0.6.tgz",
+ "integrity": "sha1-PYpcZog6FqMMqGQ+hR8Zuqd5eRc=",
+ "dev": true
+ },
+ "node_modules/fastest-levenshtein": {
+ "version": "1.0.12",
+ "resolved": "https://registry.npmjs.org/fastest-levenshtein/-/fastest-levenshtein-1.0.12.tgz",
+ "integrity": "sha512-On2N+BpYJ15xIC974QNVuYGMOlEVt4s0EOI3wwMqOmK1fdDY+FN/zltPV8vosq4ad4c/gJ1KHScUn/6AWIgiow==",
+ "dev": true
+ },
+ "node_modules/fastq": {
+ "version": "1.13.0",
+ "resolved": "https://registry.npmjs.org/fastq/-/fastq-1.13.0.tgz",
+ "integrity": "sha512-YpkpUnK8od0o1hmeSc7UUs/eB/vIPWJYjKck2QKIzAf71Vm1AAQ3EbuZB3g2JIy+pg+ERD0vqI79KyZiB2e2Nw==",
+ "dev": true,
+ "dependencies": {
+ "reusify": "^1.0.4"
+ }
+ },
+ "node_modules/fb-watchman": {
+ "version": "2.0.1",
+ "resolved": "https://registry.npmjs.org/fb-watchman/-/fb-watchman-2.0.1.tgz",
+ "integrity": "sha512-DkPJKQeY6kKwmuMretBhr7G6Vodr7bFwDYTXIkfG1gjvNpaxBTQV3PbXg6bR1c1UP4jPOX0jHUbbHANL9vRjVg==",
+ "dev": true,
+ "peer": true,
+ "dependencies": {
+ "bser": "2.1.1"
+ }
+ },
+ "node_modules/figures": {
+ "version": "3.2.0",
+ "resolved": "https://registry.npmjs.org/figures/-/figures-3.2.0.tgz",
+ "integrity": "sha512-yaduQFRKLXYOGgEn6AZau90j3ggSOyiqXU0F9JZfeXYhNa+Jk4X+s45A2zg5jns87GAFa34BBm2kXw4XpNcbdg==",
+ "dev": true,
+ "dependencies": {
+ "escape-string-regexp": "^1.0.5"
+ },
+ "engines": {
+ "node": ">=8"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
+ "node_modules/file-entry-cache": {
+ "version": "6.0.1",
+ "resolved": "https://registry.npmjs.org/file-entry-cache/-/file-entry-cache-6.0.1.tgz",
+ "integrity": "sha512-7Gps/XWymbLk2QLYK4NzpMOrYjMhdIxXuIvy2QBsLE6ljuodKvdkWs/cpyJJ3CVIVpH0Oi1Hvg1ovbMzLdFBBg==",
+ "dev": true,
+ "dependencies": {
+ "flat-cache": "^3.0.4"
+ },
+ "engines": {
+ "node": "^10.12.0 || >=12.0.0"
+ }
+ },
+ "node_modules/filelist": {
+ "version": "1.0.3",
+ "resolved": "https://registry.npmjs.org/filelist/-/filelist-1.0.3.tgz",
+ "integrity": "sha512-LwjCsruLWQULGYKy7TX0OPtrL9kLpojOFKc5VCTxdFTV7w5zbsgqVKfnkKG7Qgjtq50gKfO56hJv88OfcGb70Q==",
+ "dev": true,
+ "dependencies": {
+ "minimatch": "^5.0.1"
+ }
+ },
+ "node_modules/filelist/node_modules/brace-expansion": {
+ "version": "2.0.1",
+ "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.1.tgz",
+ "integrity": "sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==",
+ "dev": true,
+ "dependencies": {
+ "balanced-match": "^1.0.0"
+ }
+ },
+ "node_modules/filelist/node_modules/minimatch": {
+ "version": "5.0.1",
+ "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-5.0.1.tgz",
+ "integrity": "sha512-nLDxIFRyhDblz3qMuq+SoRZED4+miJ/G+tdDrjkkkRnjAsBexeGpgjLEQ0blJy7rHhR2b93rhQY4SvyWu9v03g==",
+ "dev": true,
+ "dependencies": {
+ "brace-expansion": "^2.0.1"
+ },
+ "engines": {
+ "node": ">=10"
+ }
+ },
+ "node_modules/fill-range": {
+ "version": "7.0.1",
+ "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.0.1.tgz",
+ "integrity": "sha512-qOo9F+dMUmC2Lcb4BbVvnKJxTPjCm+RRpe4gDuGrzkL7mEVl/djYSu2OdQ2Pa302N4oqkSg9ir6jaLWJ2USVpQ==",
+ "dev": true,
+ "dependencies": {
+ "to-regex-range": "^5.0.1"
+ },
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/find-up": {
+ "version": "2.1.0",
+ "resolved": "https://registry.npmjs.org/find-up/-/find-up-2.1.0.tgz",
+ "integrity": "sha1-RdG35QbHF93UgndaK3eSCjwMV6c=",
+ "dev": true,
+ "dependencies": {
+ "locate-path": "^2.0.0"
+ },
+ "engines": {
+ "node": ">=4"
+ }
+ },
+ "node_modules/flat": {
+ "version": "5.0.2",
+ "resolved": "https://registry.npmjs.org/flat/-/flat-5.0.2.tgz",
+ "integrity": "sha512-b6suED+5/3rTpUBdG1gupIl8MPFCAMA0QXwmljLhvCUKcUvdE4gWky9zpuGCcXHOsz4J9wPGNWq6OKpmIzz3hQ==",
+ "dev": true,
+ "bin": {
+ "flat": "cli.js"
+ }
+ },
+ "node_modules/flat-cache": {
+ "version": "3.0.4",
+ "resolved": "https://registry.npmjs.org/flat-cache/-/flat-cache-3.0.4.tgz",
+ "integrity": "sha512-dm9s5Pw7Jc0GvMYbshN6zchCA9RgQlzzEZX3vylR9IqFfS8XciblUXOKfW6SiuJ0e13eDYZoZV5wdrev7P3Nwg==",
+ "dev": true,
+ "dependencies": {
+ "flatted": "^3.1.0",
+ "rimraf": "^3.0.2"
+ },
+ "engines": {
+ "node": "^10.12.0 || >=12.0.0"
+ }
+ },
+ "node_modules/flatted": {
+ "version": "3.2.5",
+ "resolved": "https://registry.npmjs.org/flatted/-/flatted-3.2.5.tgz",
+ "integrity": "sha512-WIWGi2L3DyTUvUrwRKgGi9TwxQMUEqPOPQBVi71R96jZXJdFskXEmf54BoZaS1kknGODoIGASGEzBUYdyMCBJg==",
+ "dev": true
+ },
+ "node_modules/for-each": {
+ "version": "0.3.3",
+ "resolved": "https://registry.npmjs.org/for-each/-/for-each-0.3.3.tgz",
+ "integrity": "sha512-jqYfLp7mo9vIyQf8ykW2v7A+2N4QjeCeI5+Dz9XraiO1ign81wjiH7Fb9vSOWvQfNtmSa4H2RoQTrrXivdUZmw==",
+ "dev": true,
+ "dependencies": {
+ "is-callable": "^1.1.3"
+ }
+ },
+ "node_modules/for-in": {
+ "version": "1.0.2",
+ "resolved": "https://registry.npmjs.org/for-in/-/for-in-1.0.2.tgz",
+ "integrity": "sha1-gQaNKVqBQuwKxybG4iAMMPttXoA=",
+ "dev": true,
+ "peer": true,
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
+ "node_modules/form-data": {
+ "version": "3.0.1",
+ "resolved": "https://registry.npmjs.org/form-data/-/form-data-3.0.1.tgz",
+ "integrity": "sha512-RHkBKtLWUVwd7SqRIvCZMEvAMoGUp0XU+seQiZejj0COz3RI3hWP4sCv3gZWWLjJTd7rGwcsF5eKZGii0r/hbg==",
+ "dev": true,
+ "dependencies": {
+ "asynckit": "^0.4.0",
+ "combined-stream": "^1.0.8",
+ "mime-types": "^2.1.12"
+ },
+ "engines": {
+ "node": ">= 6"
+ }
+ },
+ "node_modules/fragment-cache": {
+ "version": "0.2.1",
+ "resolved": "https://registry.npmjs.org/fragment-cache/-/fragment-cache-0.2.1.tgz",
+ "integrity": "sha1-QpD60n8T6Jvn8zeZxrxaCr//DRk=",
+ "dev": true,
+ "peer": true,
+ "dependencies": {
+ "map-cache": "^0.2.2"
+ },
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
+ "node_modules/fs-extra": {
+ "version": "9.0.1",
+ "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-9.0.1.tgz",
+ "integrity": "sha512-h2iAoN838FqAFJY2/qVpzFXy+EBxfVE220PalAqQLDVsFOHLJrZvut5puAbCdNv6WJk+B8ihI+k0c7JK5erwqQ==",
+ "dev": true,
+ "dependencies": {
+ "at-least-node": "^1.0.0",
+ "graceful-fs": "^4.2.0",
+ "jsonfile": "^6.0.1",
+ "universalify": "^1.0.0"
+ },
+ "engines": {
+ "node": ">=10"
+ }
+ },
+ "node_modules/fs.realpath": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz",
+ "integrity": "sha1-FQStJSMVjKpA20onh8sBQRmU6k8=",
+ "dev": true
+ },
+ "node_modules/fsevents": {
+ "version": "2.3.2",
+ "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.2.tgz",
+ "integrity": "sha512-xiqMQR4xAeHTuB9uWm+fFRcIOgKBMiOBP+eXiyT7jsgVCq1bkVygt00oASowB7EdtpOHaaPgKt812P9ab+DDKA==",
+ "dev": true,
+ "hasInstallScript": true,
+ "optional": true,
+ "os": [
+ "darwin"
+ ],
+ "peer": true,
+ "engines": {
+ "node": "^8.16.0 || ^10.6.0 || >=11.0.0"
+ }
+ },
+ "node_modules/function-bind": {
+ "version": "1.1.1",
+ "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.1.tgz",
+ "integrity": "sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A==",
+ "dev": true
+ },
+ "node_modules/function.prototype.name": {
+ "version": "1.1.5",
+ "resolved": "https://registry.npmjs.org/function.prototype.name/-/function.prototype.name-1.1.5.tgz",
+ "integrity": "sha512-uN7m/BzVKQnCUF/iW8jYea67v++2u7m5UgENbHRtdDVclOUP+FMPlCNdmk0h/ysGyo2tavMJEDqJAkJdRa1vMA==",
+ "dev": true,
+ "dependencies": {
+ "call-bind": "^1.0.2",
+ "define-properties": "^1.1.3",
+ "es-abstract": "^1.19.0",
+ "functions-have-names": "^1.2.2"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/functions-have-names": {
+ "version": "1.2.3",
+ "resolved": "https://registry.npmjs.org/functions-have-names/-/functions-have-names-1.2.3.tgz",
+ "integrity": "sha512-xckBUXyTIqT97tq2x2AMb+g163b5JFysYk0x4qxNFwbfQkmNZoiRHb6sPzI9/QV33WeuvVYBUIiD4NzNIyqaRQ==",
+ "dev": true,
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/gensync": {
+ "version": "1.0.0-beta.2",
+ "resolved": "https://registry.npmjs.org/gensync/-/gensync-1.0.0-beta.2.tgz",
+ "integrity": "sha512-3hN7NaskYvMDLQY55gnW3NQ+mesEAepTqlg+VEbj7zzqEMBVNhzcGYYeqFo/TlYz6eQiFcp1HcsCZO+nGgS8zg==",
+ "dev": true,
+ "engines": {
+ "node": ">=6.9.0"
+ }
+ },
+ "node_modules/get-caller-file": {
+ "version": "2.0.5",
+ "resolved": "https://registry.npmjs.org/get-caller-file/-/get-caller-file-2.0.5.tgz",
+ "integrity": "sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg==",
+ "dev": true,
+ "engines": {
+ "node": "6.* || 8.* || >= 10.*"
+ }
+ },
+ "node_modules/get-intrinsic": {
+ "version": "1.2.0",
+ "resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.2.0.tgz",
+ "integrity": "sha512-L049y6nFOuom5wGyRc3/gdTLO94dySVKRACj1RmJZBQXlbTMhtNIgkWkUHq+jYmZvKf14EW1EoJnnjbmoHij0Q==",
+ "dev": true,
+ "dependencies": {
+ "function-bind": "^1.1.1",
+ "has": "^1.0.3",
+ "has-symbols": "^1.0.3"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/get-own-enumerable-property-symbols": {
+ "version": "3.0.2",
+ "resolved": "https://registry.npmjs.org/get-own-enumerable-property-symbols/-/get-own-enumerable-property-symbols-3.0.2.tgz",
+ "integrity": "sha512-I0UBV/XOz1XkIJHEUDMZAbzCThU/H8DxmSfmdGcKPnVhu2VfFqr34jr9777IyaTYvxjedWhqVIilEDsCdP5G6g==",
+ "dev": true
+ },
+ "node_modules/get-package-type": {
+ "version": "0.1.0",
+ "resolved": "https://registry.npmjs.org/get-package-type/-/get-package-type-0.1.0.tgz",
+ "integrity": "sha512-pjzuKtY64GYfWizNAJ0fr9VqttZkNiK2iS430LtIHzjBEr6bX8Am2zm4sW4Ro5wjWW5cAlRL1qAMTcXbjNAO2Q==",
+ "dev": true,
+ "peer": true,
+ "engines": {
+ "node": ">=8.0.0"
+ }
+ },
+ "node_modules/get-stdin": {
+ "version": "8.0.0",
+ "resolved": "https://registry.npmjs.org/get-stdin/-/get-stdin-8.0.0.tgz",
+ "integrity": "sha512-sY22aA6xchAzprjyqmSEQv4UbAAzRN0L2dQB0NlN5acTTK9Don6nhoc3eAbUnpZiCANAMfd/+40kVdKfFygohg==",
+ "dev": true,
+ "engines": {
+ "node": ">=10"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
+ "node_modules/get-stream": {
+ "version": "5.2.0",
+ "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-5.2.0.tgz",
+ "integrity": "sha512-nBF+F1rAZVCu/p7rjzgA+Yb4lfYXrpl7a6VmJrU8wF9I1CKvP/QwPNZHnOlwbTkY6dvtFIzFMSyQXbLoTQPRpA==",
+ "dev": true,
+ "peer": true,
+ "dependencies": {
+ "pump": "^3.0.0"
+ },
+ "engines": {
+ "node": ">=8"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
+ "node_modules/get-symbol-description": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/get-symbol-description/-/get-symbol-description-1.0.0.tgz",
+ "integrity": "sha512-2EmdH1YvIQiZpltCNgkuiUnyukzxM/R6NDJX31Ke3BG1Nq5b0S2PhX59UKi9vZpPDQVdqn+1IcaAwnzTT5vCjw==",
+ "dev": true,
+ "dependencies": {
+ "call-bind": "^1.0.2",
+ "get-intrinsic": "^1.1.1"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/get-tsconfig": {
+ "version": "4.4.0",
+ "resolved": "https://registry.npmjs.org/get-tsconfig/-/get-tsconfig-4.4.0.tgz",
+ "integrity": "sha512-0Gdjo/9+FzsYhXCEFueo2aY1z1tpXrxWZzP7k8ul9qt1U5o8rYJwTJYmaeHdrVosYIVYkOy2iwCJ9FdpocJhPQ==",
+ "dev": true,
+ "funding": {
+ "url": "https://github.com/privatenumber/get-tsconfig?sponsor=1"
+ }
+ },
+ "node_modules/get-value": {
+ "version": "2.0.6",
+ "resolved": "https://registry.npmjs.org/get-value/-/get-value-2.0.6.tgz",
+ "integrity": "sha1-3BXKHGcjh8p2vTesCjlbogQqLCg=",
+ "dev": true,
+ "peer": true,
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
+ "node_modules/glob": {
+ "version": "7.1.7",
+ "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.7.tgz",
+ "integrity": "sha512-OvD9ENzPLbegENnYP5UUfJIirTg4+XwMWGaQfQTY0JenxNvvIKP3U3/tAQSPIu/lHxXYSZmpXlUHeqAIdKzBLQ==",
+ "dev": true,
+ "dependencies": {
+ "fs.realpath": "^1.0.0",
+ "inflight": "^1.0.4",
+ "inherits": "2",
+ "minimatch": "^3.0.4",
+ "once": "^1.3.0",
+ "path-is-absolute": "^1.0.0"
+ },
+ "engines": {
+ "node": "*"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/isaacs"
+ }
+ },
+ "node_modules/glob-parent": {
+ "version": "6.0.2",
+ "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-6.0.2.tgz",
+ "integrity": "sha512-XxwI8EOhVQgWp6iDL+3b0r86f4d6AX6zSU55HfB4ydCEuXLXc5FcYeOu+nnGftS4TEju/11rt4KJPTMgbfmv4A==",
+ "dev": true,
+ "dependencies": {
+ "is-glob": "^4.0.3"
+ },
+ "engines": {
+ "node": ">=10.13.0"
+ }
+ },
+ "node_modules/global-modules": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/global-modules/-/global-modules-2.0.0.tgz",
+ "integrity": "sha512-NGbfmJBp9x8IxyJSd1P+otYK8vonoJactOogrVfFRIAEY1ukil8RSKDz2Yo7wh1oihl51l/r6W4epkeKJHqL8A==",
+ "dev": true,
+ "dependencies": {
+ "global-prefix": "^3.0.0"
+ },
+ "engines": {
+ "node": ">=6"
+ }
+ },
+ "node_modules/global-prefix": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/global-prefix/-/global-prefix-3.0.0.tgz",
+ "integrity": "sha512-awConJSVCHVGND6x3tmMaKcQvwXLhjdkmomy2W+Goaui8YPgYgXJZewhg3fWC+DlfqqQuWg8AwqjGTD2nAPVWg==",
+ "dev": true,
+ "dependencies": {
+ "ini": "^1.3.5",
+ "kind-of": "^6.0.2",
+ "which": "^1.3.1"
+ },
+ "engines": {
+ "node": ">=6"
+ }
+ },
+ "node_modules/global-prefix/node_modules/which": {
+ "version": "1.3.1",
+ "resolved": "https://registry.npmjs.org/which/-/which-1.3.1.tgz",
+ "integrity": "sha512-HxJdYWq1MTIQbJ3nw0cqssHoTNU267KlrDuGZ1WYlxDStUtKUhOaJmh112/TZmHxxUfuJqPXSOm7tDyas0OSIQ==",
+ "dev": true,
+ "dependencies": {
+ "isexe": "^2.0.0"
+ },
+ "bin": {
+ "which": "bin/which"
+ }
+ },
+ "node_modules/globals": {
+ "version": "13.20.0",
+ "resolved": "https://registry.npmjs.org/globals/-/globals-13.20.0.tgz",
+ "integrity": "sha512-Qg5QtVkCy/kv3FUSlu4ukeZDVf9ee0iXLAUYX13gbR17bnejFTzr4iS9bY7kwCf1NztRNm1t91fjOiyx4CSwPQ==",
+ "dev": true,
+ "dependencies": {
+ "type-fest": "^0.20.2"
+ },
+ "engines": {
+ "node": ">=8"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
+ "node_modules/globalthis": {
+ "version": "1.0.3",
+ "resolved": "https://registry.npmjs.org/globalthis/-/globalthis-1.0.3.tgz",
+ "integrity": "sha512-sFdI5LyBiNTHjRd7cGPWapiHWMOXKyuBNX/cWJ3NfzrZQVa8GI/8cofCl74AOVqq9W5kNmguTIzJ/1s2gyI9wA==",
+ "dev": true,
+ "dependencies": {
+ "define-properties": "^1.1.3"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/globalyzer": {
+ "version": "0.1.0",
+ "resolved": "https://registry.npmjs.org/globalyzer/-/globalyzer-0.1.0.tgz",
+ "integrity": "sha512-40oNTM9UfG6aBmuKxk/giHn5nQ8RVz/SS4Ir6zgzOv9/qC3kKZ9v4etGTcJbEl/NyVQH7FGU7d+X1egr57Md2Q==",
+ "dev": true
+ },
+ "node_modules/globby": {
+ "version": "11.0.1",
+ "resolved": "https://registry.npmjs.org/globby/-/globby-11.0.1.tgz",
+ "integrity": "sha512-iH9RmgwCmUJHi2z5o2l3eTtGBtXek1OYlHrbcxOYugyHLmAsZrPj43OtHThd62Buh/Vv6VyCBD2bdyWcGNQqoQ==",
+ "dev": true,
+ "dependencies": {
+ "array-union": "^2.1.0",
+ "dir-glob": "^3.0.1",
+ "fast-glob": "^3.1.1",
+ "ignore": "^5.1.4",
+ "merge2": "^1.3.0",
+ "slash": "^3.0.0"
+ },
+ "engines": {
+ "node": ">=10"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
+ "node_modules/globjoin": {
+ "version": "0.1.4",
+ "resolved": "https://registry.npmjs.org/globjoin/-/globjoin-0.1.4.tgz",
+ "integrity": "sha1-L0SUrIkZ43Z8XLtpHp9GMyQoXUM=",
+ "dev": true
+ },
+ "node_modules/globrex": {
+ "version": "0.1.2",
+ "resolved": "https://registry.npmjs.org/globrex/-/globrex-0.1.2.tgz",
+ "integrity": "sha512-uHJgbwAMwNFf5mLst7IWLNg14x1CkeqglJb/K3doi4dw6q2IvAAmM/Y81kevy83wP+Sst+nutFTYOGg3d1lsxg==",
+ "dev": true
+ },
+ "node_modules/gonzales-pe": {
+ "version": "4.3.0",
+ "resolved": "https://registry.npmjs.org/gonzales-pe/-/gonzales-pe-4.3.0.tgz",
+ "integrity": "sha512-otgSPpUmdWJ43VXyiNgEYE4luzHCL2pz4wQ0OnDluC6Eg4Ko3Vexy/SrSynglw/eR+OhkzmqFCZa/OFa/RgAOQ==",
+ "dev": true,
+ "dependencies": {
+ "minimist": "^1.2.5"
+ },
+ "bin": {
+ "gonzales": "bin/gonzales.js"
+ },
+ "engines": {
+ "node": ">=0.6.0"
+ }
+ },
+ "node_modules/gopd": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/gopd/-/gopd-1.0.1.tgz",
+ "integrity": "sha512-d65bNlIadxvpb/A2abVdlqKqV563juRnZ1Wtk6s1sIR8uNsXR70xqIzVqxVf1eTqDunwT2MkczEeaezCKTZhwA==",
+ "dev": true,
+ "dependencies": {
+ "get-intrinsic": "^1.1.3"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/graceful-fs": {
+ "version": "4.2.10",
+ "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.10.tgz",
+ "integrity": "sha512-9ByhssR2fPVsNZj478qUUbKfmL0+t5BDVyjShtyZZLiK7ZDAArFFfopyOTj0M05wE2tJPisA4iTnnXl2YoPvOA==",
+ "dev": true
+ },
+ "node_modules/grapheme-splitter": {
+ "version": "1.0.4",
+ "resolved": "https://registry.npmjs.org/grapheme-splitter/-/grapheme-splitter-1.0.4.tgz",
+ "integrity": "sha512-bzh50DW9kTPM00T8y4o8vQg89Di9oLJVLW/KaOGIXJWP/iqCN6WKYkbNOF04vFLJhwcpYUh9ydh/+5vpOqV4YQ==",
+ "dev": true
+ },
+ "node_modules/graphql": {
+ "version": "15.8.0",
+ "resolved": "https://registry.npmjs.org/graphql/-/graphql-15.8.0.tgz",
+ "integrity": "sha512-5gghUc24tP9HRznNpV2+FIoq3xKkj5dTQqf4v0CpdPbFVwFkWoxOM+o+2OC9ZSvjEMTjfmG9QT+gcvggTwW1zw==",
+ "dev": true,
+ "engines": {
+ "node": ">= 10.x"
+ }
+ },
+ "node_modules/graphql-request": {
+ "version": "3.7.0",
+ "resolved": "https://registry.npmjs.org/graphql-request/-/graphql-request-3.7.0.tgz",
+ "integrity": "sha512-dw5PxHCgBneN2DDNqpWu8QkbbJ07oOziy8z+bK/TAXufsOLaETuVO4GkXrbs0WjhdKhBMN3BkpN/RIvUHkmNUQ==",
+ "dev": true,
+ "dependencies": {
+ "cross-fetch": "^3.0.6",
+ "extract-files": "^9.0.0",
+ "form-data": "^3.0.0"
+ },
+ "peerDependencies": {
+ "graphql": "14 - 16"
+ }
+ },
+ "node_modules/growly": {
+ "version": "1.3.0",
+ "resolved": "https://registry.npmjs.org/growly/-/growly-1.3.0.tgz",
+ "integrity": "sha1-8QdIy+dq+WS3yWyTxrzCivEgwIE=",
+ "dev": true,
+ "optional": true,
+ "peer": true
+ },
+ "node_modules/hard-rejection": {
+ "version": "2.1.0",
+ "resolved": "https://registry.npmjs.org/hard-rejection/-/hard-rejection-2.1.0.tgz",
+ "integrity": "sha512-VIZB+ibDhx7ObhAe7OVtoEbuP4h/MuOTHJ+J8h/eBXotJYl0fBgR72xDFCKgIh22OJZIOVNxBMWuhAr10r8HdA==",
+ "dev": true,
+ "engines": {
+ "node": ">=6"
+ }
+ },
+ "node_modules/has": {
+ "version": "1.0.3",
+ "resolved": "https://registry.npmjs.org/has/-/has-1.0.3.tgz",
+ "integrity": "sha512-f2dvO0VU6Oej7RkWJGrehjbzMAjFp5/VKPp5tTpWIV4JHHZK1/BxbFRtf/siA2SWTe09caDmVtYYzWEIbBS4zw==",
+ "dev": true,
+ "dependencies": {
+ "function-bind": "^1.1.1"
+ },
+ "engines": {
+ "node": ">= 0.4.0"
+ }
+ },
+ "node_modules/has-bigints": {
+ "version": "1.0.2",
+ "resolved": "https://registry.npmjs.org/has-bigints/-/has-bigints-1.0.2.tgz",
+ "integrity": "sha512-tSvCKtBr9lkF0Ex0aQiP9N+OpV4zi2r/Nee5VkRDbaqv35RLYMzbwQfFSZZH0kR+Rd6302UJZ2p/bJCEoR3VoQ==",
+ "dev": true,
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/has-flag": {
+ "version": "4.0.0",
+ "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz",
+ "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==",
+ "dev": true,
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/has-property-descriptors": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/has-property-descriptors/-/has-property-descriptors-1.0.0.tgz",
+ "integrity": "sha512-62DVLZGoiEBDHQyqG4w9xCuZ7eJEwNmJRWw2VY84Oedb7WFcA27fiEVe8oUQx9hAUJ4ekurquucTGwsyO1XGdQ==",
+ "dev": true,
+ "dependencies": {
+ "get-intrinsic": "^1.1.1"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/has-proto": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/has-proto/-/has-proto-1.0.1.tgz",
+ "integrity": "sha512-7qE+iP+O+bgF9clE5+UoBFzE65mlBiVj3tKCrlNQ0Ogwm0BjpT/gK4SlLYDMybDh5I3TCTKnPPa0oMG7JDYrhg==",
+ "dev": true,
+ "engines": {
+ "node": ">= 0.4"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/has-symbols": {
+ "version": "1.0.3",
+ "resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.0.3.tgz",
+ "integrity": "sha512-l3LCuF6MgDNwTDKkdYGEihYjt5pRPbEg46rtlmnSPlUbgmB8LOIrKJbYYFBSbnPaJexMKtiPO8hmeRjRz2Td+A==",
+ "dev": true,
+ "engines": {
+ "node": ">= 0.4"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/has-tostringtag": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/has-tostringtag/-/has-tostringtag-1.0.0.tgz",
+ "integrity": "sha512-kFjcSNhnlGV1kyoGk7OXKSawH5JOb/LzUc5w9B02hOTO0dfFRjbHQKvg1d6cf3HbeUmtU9VbbV3qzZ2Teh97WQ==",
+ "dev": true,
+ "dependencies": {
+ "has-symbols": "^1.0.2"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/has-value": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/has-value/-/has-value-1.0.0.tgz",
+ "integrity": "sha1-GLKB2lhbHFxR3vJMkw7SmgvmsXc=",
+ "dev": true,
+ "peer": true,
+ "dependencies": {
+ "get-value": "^2.0.6",
+ "has-values": "^1.0.0",
+ "isobject": "^3.0.0"
+ },
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
+ "node_modules/has-values": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/has-values/-/has-values-1.0.0.tgz",
+ "integrity": "sha1-lbC2P+whRmGab+V/51Yo1aOe/k8=",
+ "dev": true,
+ "peer": true,
+ "dependencies": {
+ "is-number": "^3.0.0",
+ "kind-of": "^4.0.0"
+ },
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
+ "node_modules/has-values/node_modules/is-buffer": {
+ "version": "1.1.6",
+ "resolved": "https://registry.npmjs.org/is-buffer/-/is-buffer-1.1.6.tgz",
+ "integrity": "sha512-NcdALwpXkTm5Zvvbk7owOUSvVvBKDgKP5/ewfXEznmQFfs4ZRmanOeKBTjRVjka3QFoN6XJ+9F3USqfHqTaU5w==",
+ "dev": true,
+ "peer": true
+ },
+ "node_modules/has-values/node_modules/is-number": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/is-number/-/is-number-3.0.0.tgz",
+ "integrity": "sha1-JP1iAaR4LPUFYcgQJ2r8fRLXEZU=",
+ "dev": true,
+ "peer": true,
+ "dependencies": {
+ "kind-of": "^3.0.2"
+ },
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
+ "node_modules/has-values/node_modules/is-number/node_modules/kind-of": {
+ "version": "3.2.2",
+ "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz",
+ "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=",
+ "dev": true,
+ "peer": true,
+ "dependencies": {
+ "is-buffer": "^1.1.5"
+ },
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
+ "node_modules/has-values/node_modules/kind-of": {
+ "version": "4.0.0",
+ "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-4.0.0.tgz",
+ "integrity": "sha1-IIE989cSkosgc3hpGkUGb65y3Vc=",
+ "dev": true,
+ "peer": true,
+ "dependencies": {
+ "is-buffer": "^1.1.5"
+ },
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
+ "node_modules/hosted-git-info": {
+ "version": "2.8.9",
+ "resolved": "https://registry.npmjs.org/hosted-git-info/-/hosted-git-info-2.8.9.tgz",
+ "integrity": "sha512-mxIDAb9Lsm6DoOJ7xH+5+X4y1LU/4Hi50L9C5sIswK3JzULS4bwk1FvjdBgvYR4bzT4tuUQiC15FE2f5HbLvYw==",
+ "dev": true
+ },
+ "node_modules/html-encoding-sniffer": {
+ "version": "2.0.1",
+ "resolved": "https://registry.npmjs.org/html-encoding-sniffer/-/html-encoding-sniffer-2.0.1.tgz",
+ "integrity": "sha512-D5JbOMBIR/TVZkubHT+OyT2705QvogUW4IBn6nHd756OwieSF9aDYFj4dv6HHEVGYbHaLETa3WggZYWWMyy3ZQ==",
+ "dev": true,
+ "peer": true,
+ "dependencies": {
+ "whatwg-encoding": "^1.0.5"
+ },
+ "engines": {
+ "node": ">=10"
+ }
+ },
+ "node_modules/html-escaper": {
+ "version": "2.0.2",
+ "resolved": "https://registry.npmjs.org/html-escaper/-/html-escaper-2.0.2.tgz",
+ "integrity": "sha512-H2iMtd0I4Mt5eYiapRdIDjp+XzelXQ0tFE4JS7YFwFevXXMmOp9myNrUvCg0D6ws8iqkRPBfKHgbwig1SmlLfg==",
+ "dev": true,
+ "peer": true
+ },
+ "node_modules/html-tags": {
+ "version": "3.2.0",
+ "resolved": "https://registry.npmjs.org/html-tags/-/html-tags-3.2.0.tgz",
+ "integrity": "sha512-vy7ClnArOZwCnqZgvv+ddgHgJiAFXe3Ge9ML5/mBctVJoUoYPCdxVucOywjDARn6CVoh3dRSFdPHy2sX80L0Wg==",
+ "dev": true,
+ "engines": {
+ "node": ">=8"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
+ "node_modules/htmlparser2": {
+ "version": "3.10.1",
+ "resolved": "https://registry.npmjs.org/htmlparser2/-/htmlparser2-3.10.1.tgz",
+ "integrity": "sha512-IgieNijUMbkDovyoKObU1DUhm1iwNYE/fuifEoEHfd1oZKZDaONBSkal7Y01shxsM49R4XaMdGez3WnF9UfiCQ==",
+ "dev": true,
+ "dependencies": {
+ "domelementtype": "^1.3.1",
+ "domhandler": "^2.3.0",
+ "domutils": "^1.5.1",
+ "entities": "^1.1.1",
+ "inherits": "^2.0.1",
+ "readable-stream": "^3.1.1"
+ }
+ },
+ "node_modules/http-proxy-agent": {
+ "version": "4.0.1",
+ "resolved": "https://registry.npmjs.org/http-proxy-agent/-/http-proxy-agent-4.0.1.tgz",
+ "integrity": "sha512-k0zdNgqWTGA6aeIRVpvfVob4fL52dTfaehylg0Y4UvSySvOq/Y+BOyPrgpUrA7HylqvU8vIZGsRuXmspskV0Tg==",
+ "dev": true,
+ "peer": true,
+ "dependencies": {
+ "@tootallnate/once": "1",
+ "agent-base": "6",
+ "debug": "4"
+ },
+ "engines": {
+ "node": ">= 6"
+ }
+ },
+ "node_modules/https-proxy-agent": {
+ "version": "5.0.1",
+ "resolved": "https://registry.npmjs.org/https-proxy-agent/-/https-proxy-agent-5.0.1.tgz",
+ "integrity": "sha512-dFcAjpTQFgoLMzC2VwU+C/CbS7uRL0lWmxDITmqm7C+7F0Odmj6s9l6alZc6AELXhrnggM2CeWSXHGOdX2YtwA==",
+ "dev": true,
+ "peer": true,
+ "dependencies": {
+ "agent-base": "6",
+ "debug": "4"
+ },
+ "engines": {
+ "node": ">= 6"
+ }
+ },
+ "node_modules/human-signals": {
+ "version": "1.1.1",
+ "resolved": "https://registry.npmjs.org/human-signals/-/human-signals-1.1.1.tgz",
+ "integrity": "sha512-SEQu7vl8KjNL2eoGBLF3+wAjpsNfA9XMlXAYj/3EdaNfAlxKthD1xjEQfGOUhllCGGJVNY34bRr6lPINhNjyZw==",
+ "dev": true,
+ "peer": true,
+ "engines": {
+ "node": ">=8.12.0"
+ }
+ },
+ "node_modules/husky": {
+ "version": "4.3.8",
+ "resolved": "https://registry.npmjs.org/husky/-/husky-4.3.8.tgz",
+ "integrity": "sha512-LCqqsB0PzJQ/AlCgfrfzRe3e3+NvmefAdKQhRYpxS4u6clblBoDdzzvHi8fmxKRzvMxPY/1WZWzomPZww0Anow==",
+ "dev": true,
+ "hasInstallScript": true,
+ "dependencies": {
+ "chalk": "^4.0.0",
+ "ci-info": "^2.0.0",
+ "compare-versions": "^3.6.0",
+ "cosmiconfig": "^7.0.0",
+ "find-versions": "^4.0.0",
+ "opencollective-postinstall": "^2.0.2",
+ "pkg-dir": "^5.0.0",
+ "please-upgrade-node": "^3.2.0",
+ "slash": "^3.0.0",
+ "which-pm-runs": "^1.0.0"
+ },
+ "bin": {
+ "husky-run": "bin/run.js",
+ "husky-upgrade": "lib/upgrader/bin.js"
+ },
+ "engines": {
+ "node": ">=10"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/husky"
+ }
+ },
+ "node_modules/husky/node_modules/find-up": {
+ "version": "5.0.0",
+ "resolved": "https://registry.npmjs.org/find-up/-/find-up-5.0.0.tgz",
+ "integrity": "sha512-78/PXT1wlLLDgTzDs7sjq9hzz0vXD+zn+7wypEe4fXQxCmdmqfGsEPQxmiCSQI3ajFV91bVSsvNtrJRiW6nGng==",
+ "dev": true,
+ "dependencies": {
+ "locate-path": "^6.0.0",
+ "path-exists": "^4.0.0"
+ },
+ "engines": {
+ "node": ">=10"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
+ "node_modules/husky/node_modules/find-versions": {
+ "version": "4.0.0",
+ "resolved": "https://registry.npmjs.org/find-versions/-/find-versions-4.0.0.tgz",
+ "integrity": "sha512-wgpWy002tA+wgmO27buH/9KzyEOQnKsG/R0yrcjPT9BOFm0zRBVQbZ95nRGXWMywS8YR5knRbpohio0bcJABxQ==",
+ "dev": true,
+ "dependencies": {
+ "semver-regex": "^3.1.2"
+ },
+ "engines": {
+ "node": ">=10"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
+ "node_modules/husky/node_modules/locate-path": {
+ "version": "6.0.0",
+ "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-6.0.0.tgz",
+ "integrity": "sha512-iPZK6eYjbxRu3uB4/WZ3EsEIMJFMqAoopl3R+zuq0UjcAm/MO6KCweDgPfP3elTztoKP3KtnVHxTn2NHBSDVUw==",
+ "dev": true,
+ "dependencies": {
+ "p-locate": "^5.0.0"
+ },
+ "engines": {
+ "node": ">=10"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
+ "node_modules/husky/node_modules/p-locate": {
+ "version": "5.0.0",
+ "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-5.0.0.tgz",
+ "integrity": "sha512-LaNjtRWUBY++zB5nE/NwcaoMylSPk+S+ZHNB1TzdbMJMny6dynpAGt7X/tl/QYq3TIeE6nxHppbo2LGymrG5Pw==",
+ "dev": true,
+ "dependencies": {
+ "p-limit": "^3.0.2"
+ },
+ "engines": {
+ "node": ">=10"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
+ "node_modules/husky/node_modules/pkg-dir": {
+ "version": "5.0.0",
+ "resolved": "https://registry.npmjs.org/pkg-dir/-/pkg-dir-5.0.0.tgz",
+ "integrity": "sha512-NPE8TDbzl/3YQYY7CSS228s3g2ollTFnc+Qi3tqmqJp9Vg2ovUpixcJEo2HJScN2Ez+kEaal6y70c0ehqJBJeA==",
+ "dev": true,
+ "dependencies": {
+ "find-up": "^5.0.0"
+ },
+ "engines": {
+ "node": ">=10"
+ }
+ },
+ "node_modules/iconv-lite": {
+ "version": "0.4.24",
+ "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.24.tgz",
+ "integrity": "sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA==",
+ "dev": true,
+ "dependencies": {
+ "safer-buffer": ">= 2.1.2 < 3"
+ },
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
+ "node_modules/ignore": {
+ "version": "5.2.0",
+ "resolved": "https://registry.npmjs.org/ignore/-/ignore-5.2.0.tgz",
+ "integrity": "sha512-CmxgYGiEPCLhfLnpPp1MoRmifwEIOgjcHXxOBjv7mY96c+eWScsOP9c112ZyLdWHi0FxHjI+4uVhKYp/gcdRmQ==",
+ "dev": true,
+ "engines": {
+ "node": ">= 4"
+ }
+ },
+ "node_modules/import-fresh": {
+ "version": "3.3.0",
+ "resolved": "https://registry.npmjs.org/import-fresh/-/import-fresh-3.3.0.tgz",
+ "integrity": "sha512-veYYhQa+D1QBKznvhUHxb8faxlrwUnxseDAbAp457E0wLNio2bOSKnjYDhMj+YiAq61xrMGhQk9iXVk5FzgQMw==",
+ "dev": true,
+ "dependencies": {
+ "parent-module": "^1.0.0",
+ "resolve-from": "^4.0.0"
+ },
+ "engines": {
+ "node": ">=6"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
+ "node_modules/import-lazy": {
+ "version": "4.0.0",
+ "resolved": "https://registry.npmjs.org/import-lazy/-/import-lazy-4.0.0.tgz",
+ "integrity": "sha512-rKtvo6a868b5Hu3heneU+L4yEQ4jYKLtjpnPeUdK7h0yzXGmyBTypknlkCvHFBqfX9YlorEiMM6Dnq/5atfHkw==",
+ "dev": true,
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/import-local": {
+ "version": "3.1.0",
+ "resolved": "https://registry.npmjs.org/import-local/-/import-local-3.1.0.tgz",
+ "integrity": "sha512-ASB07uLtnDs1o6EHjKpX34BKYDSqnFerfTOJL2HvMqF70LnxpjkzDB8J44oT9pu4AMPkQwf8jl6szgvNd2tRIg==",
+ "dev": true,
+ "peer": true,
+ "dependencies": {
+ "pkg-dir": "^4.2.0",
+ "resolve-cwd": "^3.0.0"
+ },
+ "bin": {
+ "import-local-fixture": "fixtures/cli.js"
+ },
+ "engines": {
+ "node": ">=8"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
+ "node_modules/imurmurhash": {
+ "version": "0.1.4",
+ "resolved": "https://registry.npmjs.org/imurmurhash/-/imurmurhash-0.1.4.tgz",
+ "integrity": "sha1-khi5srkoojixPcT7a21XbyMUU+o=",
+ "dev": true,
+ "engines": {
+ "node": ">=0.8.19"
+ }
+ },
+ "node_modules/indent-string": {
+ "version": "4.0.0",
+ "resolved": "https://registry.npmjs.org/indent-string/-/indent-string-4.0.0.tgz",
+ "integrity": "sha512-EdDDZu4A2OyIK7Lr/2zG+w5jmbuk1DVBnEwREQvBzspBJkCEbRa8GxU1lghYcaGJCnRWibjDXlq779X1/y5xwg==",
+ "dev": true,
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/inflight": {
+ "version": "1.0.6",
+ "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz",
+ "integrity": "sha1-Sb1jMdfQLQwJvJEKEHW6gWW1bfk=",
+ "dev": true,
+ "dependencies": {
+ "once": "^1.3.0",
+ "wrappy": "1"
+ }
+ },
+ "node_modules/inherits": {
+ "version": "2.0.4",
+ "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz",
+ "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==",
+ "dev": true
+ },
+ "node_modules/ini": {
+ "version": "1.3.8",
+ "resolved": "https://registry.npmjs.org/ini/-/ini-1.3.8.tgz",
+ "integrity": "sha512-JV/yugV2uzW5iMRSiZAyDtQd+nxtUnjeLt0acNdw98kKLrvuRVyB80tsREOE7yvGVgalhZ6RNXCmEHkUKBKxew==",
+ "dev": true
+ },
+ "node_modules/inquirer": {
+ "version": "7.3.3",
+ "resolved": "https://registry.npmjs.org/inquirer/-/inquirer-7.3.3.tgz",
+ "integrity": "sha512-JG3eIAj5V9CwcGvuOmoo6LB9kbAYT8HXffUl6memuszlwDC/qvFAJw49XJ5NROSFNPxp3iQg1GqkFhaY/CR0IA==",
+ "dev": true,
+ "dependencies": {
+ "ansi-escapes": "^4.2.1",
+ "chalk": "^4.1.0",
+ "cli-cursor": "^3.1.0",
+ "cli-width": "^3.0.0",
+ "external-editor": "^3.0.3",
+ "figures": "^3.0.0",
+ "lodash": "^4.17.19",
+ "mute-stream": "0.0.8",
+ "run-async": "^2.4.0",
+ "rxjs": "^6.6.0",
+ "string-width": "^4.1.0",
+ "strip-ansi": "^6.0.0",
+ "through": "^2.3.6"
+ },
+ "engines": {
+ "node": ">=8.0.0"
+ }
+ },
+ "node_modules/internal-slot": {
+ "version": "1.0.5",
+ "resolved": "https://registry.npmjs.org/internal-slot/-/internal-slot-1.0.5.tgz",
+ "integrity": "sha512-Y+R5hJrzs52QCG2laLn4udYVnxsfny9CpOhNhUvk/SSSVyF6T27FzRbF0sroPidSu3X8oEAkOn2K804mjpt6UQ==",
+ "dev": true,
+ "dependencies": {
+ "get-intrinsic": "^1.2.0",
+ "has": "^1.0.3",
+ "side-channel": "^1.0.4"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ }
+ },
+ "node_modules/ip-regex": {
+ "version": "4.3.0",
+ "resolved": "https://registry.npmjs.org/ip-regex/-/ip-regex-4.3.0.tgz",
+ "integrity": "sha512-B9ZWJxHHOHUhUjCPrMpLD4xEq35bUTClHM1S6CBU5ixQnkZmwipwgc96vAd7AAGM9TGHvJR+Uss+/Ak6UphK+Q==",
+ "dev": true,
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/is-accessor-descriptor": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-1.0.0.tgz",
+ "integrity": "sha512-m5hnHTkcVsPfqx3AKlyttIPb7J+XykHvJP2B9bZDjlhLIoEq4XoK64Vg7boZlVWYK6LUY94dYPEE7Lh0ZkZKcQ==",
+ "dev": true,
+ "peer": true,
+ "dependencies": {
+ "kind-of": "^6.0.0"
+ },
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
+ "node_modules/is-alphabetical": {
+ "version": "1.0.4",
+ "resolved": "https://registry.npmjs.org/is-alphabetical/-/is-alphabetical-1.0.4.tgz",
+ "integrity": "sha512-DwzsA04LQ10FHTZuL0/grVDk4rFoVH1pjAToYwBrHSxcrBIGQuXrQMtD5U1b0U2XVgKZCTLLP8u2Qxqhy3l2Vg==",
+ "dev": true,
+ "funding": {
+ "type": "github",
+ "url": "https://github.com/sponsors/wooorm"
+ }
+ },
+ "node_modules/is-alphanumeric": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/is-alphanumeric/-/is-alphanumeric-1.0.0.tgz",
+ "integrity": "sha512-ZmRL7++ZkcMOfDuWZuMJyIVLr2keE1o/DeNWh1EmgqGhUcV+9BIVsx0BcSBOHTZqzjs4+dISzr2KAeBEWGgXeA==",
+ "dev": true,
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
+ "node_modules/is-alphanumerical": {
+ "version": "1.0.4",
+ "resolved": "https://registry.npmjs.org/is-alphanumerical/-/is-alphanumerical-1.0.4.tgz",
+ "integrity": "sha512-UzoZUr+XfVz3t3v4KyGEniVL9BDRoQtY7tOyrRybkVNjDFWyo1yhXNGrrBTQxp3ib9BLAWs7k2YKBQsFRkZG9A==",
+ "dev": true,
+ "dependencies": {
+ "is-alphabetical": "^1.0.0",
+ "is-decimal": "^1.0.0"
+ },
+ "funding": {
+ "type": "github",
+ "url": "https://github.com/sponsors/wooorm"
+ }
+ },
+ "node_modules/is-arguments": {
+ "version": "1.1.1",
+ "resolved": "https://registry.npmjs.org/is-arguments/-/is-arguments-1.1.1.tgz",
+ "integrity": "sha512-8Q7EARjzEnKpt/PCD7e1cgUS0a6X8u5tdSiMqXhojOdoV9TsMsiO+9VLC5vAmO8N7/GmXn7yjR8qnA6bVAEzfA==",
+ "dev": true,
+ "dependencies": {
+ "call-bind": "^1.0.2",
+ "has-tostringtag": "^1.0.0"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/is-array-buffer": {
+ "version": "3.0.2",
+ "resolved": "https://registry.npmjs.org/is-array-buffer/-/is-array-buffer-3.0.2.tgz",
+ "integrity": "sha512-y+FyyR/w8vfIRq4eQcM1EYgSTnmHXPqaF+IgzgraytCFq5Xh8lllDVmAZolPJiZttZLeFSINPYMaEJ7/vWUa1w==",
+ "dev": true,
+ "dependencies": {
+ "call-bind": "^1.0.2",
+ "get-intrinsic": "^1.2.0",
+ "is-typed-array": "^1.1.10"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/is-arrayish": {
+ "version": "0.2.1",
+ "resolved": "https://registry.npmjs.org/is-arrayish/-/is-arrayish-0.2.1.tgz",
+ "integrity": "sha1-d8mYQFJ6qOyxqLppe4BkWnqSap0=",
+ "dev": true
+ },
+ "node_modules/is-bigint": {
+ "version": "1.0.4",
+ "resolved": "https://registry.npmjs.org/is-bigint/-/is-bigint-1.0.4.tgz",
+ "integrity": "sha512-zB9CruMamjym81i2JZ3UMn54PKGsQzsJeo6xvN3HJJ4CAsQNB6iRutp2To77OfCNuoxspsIhzaPoO1zyCEhFOg==",
+ "dev": true,
+ "dependencies": {
+ "has-bigints": "^1.0.1"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/is-boolean-object": {
+ "version": "1.1.2",
+ "resolved": "https://registry.npmjs.org/is-boolean-object/-/is-boolean-object-1.1.2.tgz",
+ "integrity": "sha512-gDYaKHJmnj4aWxyj6YHyXVpdQawtVLHU5cb+eztPGczf6cjuTdwve5ZIEfgXqH4e57An1D1AKf8CZ3kYrQRqYA==",
+ "dev": true,
+ "dependencies": {
+ "call-bind": "^1.0.2",
+ "has-tostringtag": "^1.0.0"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/is-buffer": {
+ "version": "2.0.5",
+ "resolved": "https://registry.npmjs.org/is-buffer/-/is-buffer-2.0.5.tgz",
+ "integrity": "sha512-i2R6zNFDwgEHJyQUtJEk0XFi1i0dPFn/oqjK3/vPCcDeJvW5NQ83V8QbicfF1SupOaB0h8ntgBC2YiE7dfyctQ==",
+ "dev": true,
+ "funding": [
+ {
+ "type": "github",
+ "url": "https://github.com/sponsors/feross"
+ },
+ {
+ "type": "patreon",
+ "url": "https://www.patreon.com/feross"
+ },
+ {
+ "type": "consulting",
+ "url": "https://feross.org/support"
+ }
+ ],
+ "engines": {
+ "node": ">=4"
+ }
+ },
+ "node_modules/is-callable": {
+ "version": "1.2.7",
+ "resolved": "https://registry.npmjs.org/is-callable/-/is-callable-1.2.7.tgz",
+ "integrity": "sha512-1BC0BVFhS/p0qtw6enp8e+8OD0UrK0oFLztSjNzhcKA3WDuJxxAPXzPuPtKkjEY9UUoEWlX/8fgKeu2S8i9JTA==",
+ "dev": true,
+ "engines": {
+ "node": ">= 0.4"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/is-ci": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/is-ci/-/is-ci-2.0.0.tgz",
+ "integrity": "sha512-YfJT7rkpQB0updsdHLGWrvhBJfcfzNNawYDNIyQXJz0IViGf75O8EBPKSdvw2rF+LGCsX4FZ8tcr3b19LcZq4w==",
+ "dev": true,
+ "dependencies": {
+ "ci-info": "^2.0.0"
+ },
+ "bin": {
+ "is-ci": "bin.js"
+ }
+ },
+ "node_modules/is-core-module": {
+ "version": "2.11.0",
+ "resolved": "https://registry.npmjs.org/is-core-module/-/is-core-module-2.11.0.tgz",
+ "integrity": "sha512-RRjxlvLDkD1YJwDbroBHMb+cukurkDWNyHx7D3oNB5x9rb5ogcksMC5wHCadcXoo67gVr/+3GFySh3134zi6rw==",
+ "dev": true,
+ "dependencies": {
+ "has": "^1.0.3"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/is-data-descriptor": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-1.0.0.tgz",
+ "integrity": "sha512-jbRXy1FmtAoCjQkVmIVYwuuqDFUbaOeDjmed1tOGPrsMhtJA4rD9tkgA0F1qJ3gRFRXcHYVkdeaP50Q5rE/jLQ==",
+ "dev": true,
+ "peer": true,
+ "dependencies": {
+ "kind-of": "^6.0.0"
+ },
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
+ "node_modules/is-date-object": {
+ "version": "1.0.5",
+ "resolved": "https://registry.npmjs.org/is-date-object/-/is-date-object-1.0.5.tgz",
+ "integrity": "sha512-9YQaSxsAiSwcvS33MBk3wTCVnWK+HhF8VZR2jRxehM16QcVOdHqPn4VPHmRK4lSr38n9JriurInLcP90xsYNfQ==",
+ "dev": true,
+ "dependencies": {
+ "has-tostringtag": "^1.0.0"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/is-decimal": {
+ "version": "1.0.4",
+ "resolved": "https://registry.npmjs.org/is-decimal/-/is-decimal-1.0.4.tgz",
+ "integrity": "sha512-RGdriMmQQvZ2aqaQq3awNA6dCGtKpiDFcOzrTWrDAT2MiWrKQVPmxLGHl7Y2nNu6led0kEyoX0enY0qXYsv9zw==",
+ "dev": true,
+ "funding": {
+ "type": "github",
+ "url": "https://github.com/sponsors/wooorm"
+ }
+ },
+ "node_modules/is-descriptor": {
+ "version": "1.0.2",
+ "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-1.0.2.tgz",
+ "integrity": "sha512-2eis5WqQGV7peooDyLmNEPUrps9+SXX5c9pL3xEB+4e9HnGuDa7mB7kHxHw4CbqS9k1T2hOH3miL8n8WtiYVtg==",
+ "dev": true,
+ "peer": true,
+ "dependencies": {
+ "is-accessor-descriptor": "^1.0.0",
+ "is-data-descriptor": "^1.0.0",
+ "kind-of": "^6.0.2"
+ },
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
+ "node_modules/is-docker": {
+ "version": "2.2.1",
+ "resolved": "https://registry.npmjs.org/is-docker/-/is-docker-2.2.1.tgz",
+ "integrity": "sha512-F+i2BKsFrH66iaUFc0woD8sLy8getkwTwtOBjvs56Cx4CgJDeKQeqfz8wAYiSb8JOprWhHH5p77PbmYCvvUuXQ==",
+ "dev": true,
+ "bin": {
+ "is-docker": "cli.js"
+ },
+ "engines": {
+ "node": ">=8"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
+ "node_modules/is-extendable": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/is-extendable/-/is-extendable-1.0.1.tgz",
+ "integrity": "sha512-arnXMxT1hhoKo9k1LZdmlNyJdDDfy2v0fXjFlmok4+i8ul/6WlbVge9bhM74OpNPQPMGUToDtz+KXa1PneJxOA==",
+ "dev": true,
+ "peer": true,
+ "dependencies": {
+ "is-plain-object": "^2.0.4"
+ },
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
+ "node_modules/is-extglob": {
+ "version": "2.1.1",
+ "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz",
+ "integrity": "sha1-qIwCU1eR8C7TfHahueqXc8gz+MI=",
+ "dev": true,
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
+ "node_modules/is-fullwidth-code-point": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz",
+ "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==",
+ "dev": true,
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/is-generator-fn": {
+ "version": "2.1.0",
+ "resolved": "https://registry.npmjs.org/is-generator-fn/-/is-generator-fn-2.1.0.tgz",
+ "integrity": "sha512-cTIB4yPYL/Grw0EaSzASzg6bBy9gqCofvWN8okThAYIxKJZC+udlRAmGbM0XLeniEJSs8uEgHPGuHSe1XsOLSQ==",
+ "dev": true,
+ "peer": true,
+ "engines": {
+ "node": ">=6"
+ }
+ },
+ "node_modules/is-glob": {
+ "version": "4.0.3",
+ "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.3.tgz",
+ "integrity": "sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==",
+ "dev": true,
+ "dependencies": {
+ "is-extglob": "^2.1.1"
+ },
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
+ "node_modules/is-hexadecimal": {
+ "version": "1.0.4",
+ "resolved": "https://registry.npmjs.org/is-hexadecimal/-/is-hexadecimal-1.0.4.tgz",
+ "integrity": "sha512-gyPJuv83bHMpocVYoqof5VDiZveEoGoFL8m3BXNb2VW8Xs+rz9kqO8LOQ5DH6EsuvilT1ApazU0pyl+ytbPtlw==",
+ "dev": true,
+ "funding": {
+ "type": "github",
+ "url": "https://github.com/sponsors/wooorm"
+ }
+ },
+ "node_modules/is-map": {
+ "version": "2.0.2",
+ "resolved": "https://registry.npmjs.org/is-map/-/is-map-2.0.2.tgz",
+ "integrity": "sha512-cOZFQQozTha1f4MxLFzlgKYPTyj26picdZTx82hbc/Xf4K/tZOOXSCkMvU4pKioRXGDLJRn0GM7Upe7kR721yg==",
+ "dev": true,
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/is-negative-zero": {
+ "version": "2.0.2",
+ "resolved": "https://registry.npmjs.org/is-negative-zero/-/is-negative-zero-2.0.2.tgz",
+ "integrity": "sha512-dqJvarLawXsFbNDeJW7zAz8ItJ9cd28YufuuFzh0G8pNHjJMnY08Dv7sYX2uF5UpQOwieAeOExEYAWWfu7ZZUA==",
+ "dev": true,
+ "engines": {
+ "node": ">= 0.4"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/is-number": {
+ "version": "7.0.0",
+ "resolved": "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz",
+ "integrity": "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==",
+ "dev": true,
+ "engines": {
+ "node": ">=0.12.0"
+ }
+ },
+ "node_modules/is-number-object": {
+ "version": "1.0.7",
+ "resolved": "https://registry.npmjs.org/is-number-object/-/is-number-object-1.0.7.tgz",
+ "integrity": "sha512-k1U0IRzLMo7ZlYIfzRu23Oh6MiIFasgpb9X76eqfFZAqwH44UI4KTBvBYIZ1dSL9ZzChTB9ShHfLkR4pdW5krQ==",
+ "dev": true,
+ "dependencies": {
+ "has-tostringtag": "^1.0.0"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/is-obj": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/is-obj/-/is-obj-1.0.1.tgz",
+ "integrity": "sha1-PkcprB9f3gJc19g6iW2rn09n2w8=",
+ "dev": true,
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
+ "node_modules/is-path-inside": {
+ "version": "3.0.3",
+ "resolved": "https://registry.npmjs.org/is-path-inside/-/is-path-inside-3.0.3.tgz",
+ "integrity": "sha512-Fd4gABb+ycGAmKou8eMftCupSir5lRxqf4aD/vd0cD2qc4HL07OjCeuHMr8Ro4CoMaeCKDB0/ECBOVWjTwUvPQ==",
+ "dev": true,
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/is-plain-obj": {
+ "version": "1.1.0",
+ "resolved": "https://registry.npmjs.org/is-plain-obj/-/is-plain-obj-1.1.0.tgz",
+ "integrity": "sha1-caUMhCnfync8kqOQpKA7OfzVHT4=",
+ "dev": true,
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
+ "node_modules/is-plain-object": {
+ "version": "2.0.4",
+ "resolved": "https://registry.npmjs.org/is-plain-object/-/is-plain-object-2.0.4.tgz",
+ "integrity": "sha512-h5PpgXkWitc38BBMYawTYMWJHFZJVnBquFE57xFpjB8pJFiF6gZ+bU+WyI/yqXiFR5mdLsgYNaPe8uao6Uv9Og==",
+ "dev": true,
+ "peer": true,
+ "dependencies": {
+ "isobject": "^3.0.1"
+ },
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
+ "node_modules/is-potential-custom-element-name": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/is-potential-custom-element-name/-/is-potential-custom-element-name-1.0.1.tgz",
+ "integrity": "sha512-bCYeRA2rVibKZd+s2625gGnGF/t7DSqDs4dP7CrLA1m7jKWz6pps0LpYLJN8Q64HtmPKJ1hrN3nzPNKFEKOUiQ==",
+ "dev": true,
+ "peer": true
+ },
+ "node_modules/is-regex": {
+ "version": "1.1.4",
+ "resolved": "https://registry.npmjs.org/is-regex/-/is-regex-1.1.4.tgz",
+ "integrity": "sha512-kvRdxDsxZjhzUX07ZnLydzS1TU/TJlTUHHY4YLL87e37oUA49DfkLqgy+VjFocowy29cKvcSiu+kIv728jTTVg==",
+ "dev": true,
+ "dependencies": {
+ "call-bind": "^1.0.2",
+ "has-tostringtag": "^1.0.0"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/is-regexp": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/is-regexp/-/is-regexp-1.0.0.tgz",
+ "integrity": "sha1-/S2INUXEa6xaYz57mgnof6LLUGk=",
+ "dev": true,
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
+ "node_modules/is-set": {
+ "version": "2.0.2",
+ "resolved": "https://registry.npmjs.org/is-set/-/is-set-2.0.2.tgz",
+ "integrity": "sha512-+2cnTEZeY5z/iXGbLhPrOAaK/Mau5k5eXq9j14CpRTftq0pAJu2MwVRSZhyZWBzx3o6X795Lz6Bpb6R0GKf37g==",
+ "dev": true,
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/is-shared-array-buffer": {
+ "version": "1.0.2",
+ "resolved": "https://registry.npmjs.org/is-shared-array-buffer/-/is-shared-array-buffer-1.0.2.tgz",
+ "integrity": "sha512-sqN2UDu1/0y6uvXyStCOzyhAjCSlHceFoMKJW8W9EU9cvic/QdsZ0kEU93HEy3IUEFZIiH/3w+AH/UQbPHNdhA==",
+ "dev": true,
+ "dependencies": {
+ "call-bind": "^1.0.2"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/is-stream": {
+ "version": "2.0.1",
+ "resolved": "https://registry.npmjs.org/is-stream/-/is-stream-2.0.1.tgz",
+ "integrity": "sha512-hFoiJiTl63nn+kstHGBtewWSKnQLpyb155KHheA1l39uvtO9nWIop1p3udqPcUd/xbF1VLMO4n7OI6p7RbngDg==",
+ "dev": true,
+ "engines": {
+ "node": ">=8"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
+ "node_modules/is-string": {
+ "version": "1.0.7",
+ "resolved": "https://registry.npmjs.org/is-string/-/is-string-1.0.7.tgz",
+ "integrity": "sha512-tE2UXzivje6ofPW7l23cjDOMa09gb7xlAqG6jG5ej6uPV32TlWP3NKPigtaGeHNu9fohccRYvIiZMfOOnOYUtg==",
+ "dev": true,
+ "dependencies": {
+ "has-tostringtag": "^1.0.0"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/is-symbol": {
+ "version": "1.0.4",
+ "resolved": "https://registry.npmjs.org/is-symbol/-/is-symbol-1.0.4.tgz",
+ "integrity": "sha512-C/CPBqKWnvdcxqIARxyOh4v1UUEOCHpgDa0WYgpKDFMszcrPcffg5uhwSgPCLD2WWxmq6isisz87tzT01tuGhg==",
+ "dev": true,
+ "dependencies": {
+ "has-symbols": "^1.0.2"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/is-typed-array": {
+ "version": "1.1.10",
+ "resolved": "https://registry.npmjs.org/is-typed-array/-/is-typed-array-1.1.10.tgz",
+ "integrity": "sha512-PJqgEHiWZvMpaFZ3uTc8kHPM4+4ADTlDniuQL7cU/UDA0Ql7F70yGfHph3cLNe+c9toaigv+DFzTJKhc2CtO6A==",
+ "dev": true,
+ "dependencies": {
+ "available-typed-arrays": "^1.0.5",
+ "call-bind": "^1.0.2",
+ "for-each": "^0.3.3",
+ "gopd": "^1.0.1",
+ "has-tostringtag": "^1.0.0"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/is-typedarray": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/is-typedarray/-/is-typedarray-1.0.0.tgz",
+ "integrity": "sha1-5HnICFjfDBsR3dppQPlgEfzaSpo=",
+ "dev": true
+ },
+ "node_modules/is-unicode-supported": {
+ "version": "0.1.0",
+ "resolved": "https://registry.npmjs.org/is-unicode-supported/-/is-unicode-supported-0.1.0.tgz",
+ "integrity": "sha512-knxG2q4UC3u8stRGyAVJCOdxFmv5DZiRcdlIaAQXAbSfJya+OhopNotLQrstBhququ4ZpuKbDc/8S6mgXgPFPw==",
+ "dev": true,
+ "engines": {
+ "node": ">=10"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
+ "node_modules/is-url-superb": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/is-url-superb/-/is-url-superb-3.0.0.tgz",
+ "integrity": "sha512-3faQP+wHCGDQT1qReM5zCPx2mxoal6DzbzquFlCYJLWyy4WPTved33ea2xFbX37z4NoriEwZGIYhFtx8RUB5wQ==",
+ "dev": true,
+ "dependencies": {
+ "url-regex": "^5.0.0"
+ },
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/is-weakmap": {
+ "version": "2.0.1",
+ "resolved": "https://registry.npmjs.org/is-weakmap/-/is-weakmap-2.0.1.tgz",
+ "integrity": "sha512-NSBR4kH5oVj1Uwvv970ruUkCV7O1mzgVFO4/rev2cLRda9Tm9HrL70ZPut4rOHgY0FNrUu9BCbXA2sdQ+x0chA==",
+ "dev": true,
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/is-weakref": {
+ "version": "1.0.2",
+ "resolved": "https://registry.npmjs.org/is-weakref/-/is-weakref-1.0.2.tgz",
+ "integrity": "sha512-qctsuLZmIQ0+vSSMfoVvyFe2+GSEvnmZ2ezTup1SBse9+twCCeial6EEi3Nc2KFcf6+qz2FBPnjXsk8xhKSaPQ==",
+ "dev": true,
+ "dependencies": {
+ "call-bind": "^1.0.2"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/is-weakset": {
+ "version": "2.0.2",
+ "resolved": "https://registry.npmjs.org/is-weakset/-/is-weakset-2.0.2.tgz",
+ "integrity": "sha512-t2yVvttHkQktwnNNmBQ98AhENLdPUTDTE21uPqAQ0ARwQfGeQKRVS0NNurH7bTf7RrvcVn1OOge45CnBeHCSmg==",
+ "dev": true,
+ "dependencies": {
+ "call-bind": "^1.0.2",
+ "get-intrinsic": "^1.1.1"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/is-whitespace-character": {
+ "version": "1.0.4",
+ "resolved": "https://registry.npmjs.org/is-whitespace-character/-/is-whitespace-character-1.0.4.tgz",
+ "integrity": "sha512-SDweEzfIZM0SJV0EUga669UTKlmL0Pq8Lno0QDQsPnvECB3IM2aP0gdx5TrU0A01MAPfViaZiI2V1QMZLaKK5w==",
+ "dev": true,
+ "funding": {
+ "type": "github",
+ "url": "https://github.com/sponsors/wooorm"
+ }
+ },
+ "node_modules/is-windows": {
+ "version": "1.0.2",
+ "resolved": "https://registry.npmjs.org/is-windows/-/is-windows-1.0.2.tgz",
+ "integrity": "sha512-eXK1UInq2bPmjyX6e3VHIzMLobc4J94i4AWn+Hpq3OU5KkrRC96OAcR3PRJ/pGu6m8TRnBHP9dkXQVsT/COVIA==",
+ "dev": true,
+ "peer": true,
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
+ "node_modules/is-word-character": {
+ "version": "1.0.4",
+ "resolved": "https://registry.npmjs.org/is-word-character/-/is-word-character-1.0.4.tgz",
+ "integrity": "sha512-5SMO8RVennx3nZrqtKwCGyyetPE9VDba5ugvKLaD4KopPG5kR4mQ7tNt/r7feL5yt5h3lpuBbIUmCOG2eSzXHA==",
+ "dev": true,
+ "funding": {
+ "type": "github",
+ "url": "https://github.com/sponsors/wooorm"
+ }
+ },
+ "node_modules/is-wsl": {
+ "version": "2.2.0",
+ "resolved": "https://registry.npmjs.org/is-wsl/-/is-wsl-2.2.0.tgz",
+ "integrity": "sha512-fKzAra0rGJUUBwGBgNkHZuToZcn+TtXHpeCgmkMJMMYx1sQDYaCSyjJBSCa2nH1DGm7s3n1oBnohoVTBaN7Lww==",
+ "dev": true,
+ "dependencies": {
+ "is-docker": "^2.0.0"
+ },
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/isarray": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz",
+ "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=",
+ "dev": true,
+ "peer": true
+ },
+ "node_modules/isexe": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz",
+ "integrity": "sha1-6PvzdNxVb/iUehDcsFctYz8s+hA=",
+ "dev": true
+ },
+ "node_modules/isobject": {
+ "version": "3.0.1",
+ "resolved": "https://registry.npmjs.org/isobject/-/isobject-3.0.1.tgz",
+ "integrity": "sha1-TkMekrEalzFjaqH5yNHMvP2reN8=",
+ "dev": true,
+ "peer": true,
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
+ "node_modules/istanbul-lib-coverage": {
+ "version": "3.2.0",
+ "resolved": "https://registry.npmjs.org/istanbul-lib-coverage/-/istanbul-lib-coverage-3.2.0.tgz",
+ "integrity": "sha512-eOeJ5BHCmHYvQK7xt9GkdHuzuCGS1Y6g9Gvnx3Ym33fz/HpLRYxiS0wHNr+m/MBC8B647Xt608vCDEvhl9c6Mw==",
+ "dev": true,
+ "peer": true,
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/istanbul-lib-instrument": {
+ "version": "4.0.3",
+ "resolved": "https://registry.npmjs.org/istanbul-lib-instrument/-/istanbul-lib-instrument-4.0.3.tgz",
+ "integrity": "sha512-BXgQl9kf4WTCPCCpmFGoJkz/+uhvm7h7PFKUYxh7qarQd3ER33vHG//qaE8eN25l07YqZPpHXU9I09l/RD5aGQ==",
+ "dev": true,
+ "peer": true,
+ "dependencies": {
+ "@babel/core": "^7.7.5",
+ "@istanbuljs/schema": "^0.1.2",
+ "istanbul-lib-coverage": "^3.0.0",
+ "semver": "^6.3.0"
+ },
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/istanbul-lib-instrument/node_modules/semver": {
+ "version": "6.3.0",
+ "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz",
+ "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==",
+ "dev": true,
+ "peer": true,
+ "bin": {
+ "semver": "bin/semver.js"
+ }
+ },
+ "node_modules/istanbul-lib-report": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/istanbul-lib-report/-/istanbul-lib-report-3.0.0.tgz",
+ "integrity": "sha512-wcdi+uAKzfiGT2abPpKZ0hSU1rGQjUQnLvtY5MpQ7QCTahD3VODhcu4wcfY1YtkGaDD5yuydOLINXsfbus9ROw==",
+ "dev": true,
+ "peer": true,
+ "dependencies": {
+ "istanbul-lib-coverage": "^3.0.0",
+ "make-dir": "^3.0.0",
+ "supports-color": "^7.1.0"
+ },
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/istanbul-lib-source-maps": {
+ "version": "4.0.1",
+ "resolved": "https://registry.npmjs.org/istanbul-lib-source-maps/-/istanbul-lib-source-maps-4.0.1.tgz",
+ "integrity": "sha512-n3s8EwkdFIJCG3BPKBYvskgXGoy88ARzvegkitk60NxRdwltLOTaH7CUiMRXvwYorl0Q712iEjcWB+fK/MrWVw==",
+ "dev": true,
+ "peer": true,
+ "dependencies": {
+ "debug": "^4.1.1",
+ "istanbul-lib-coverage": "^3.0.0",
+ "source-map": "^0.6.1"
+ },
+ "engines": {
+ "node": ">=10"
+ }
+ },
+ "node_modules/istanbul-reports": {
+ "version": "3.1.4",
+ "resolved": "https://registry.npmjs.org/istanbul-reports/-/istanbul-reports-3.1.4.tgz",
+ "integrity": "sha512-r1/DshN4KSE7xWEknZLLLLDn5CJybV3nw01VTkp6D5jzLuELlcbudfj/eSQFvrKsJuTVCGnePO7ho82Nw9zzfw==",
+ "dev": true,
+ "peer": true,
+ "dependencies": {
+ "html-escaper": "^2.0.0",
+ "istanbul-lib-report": "^3.0.0"
+ },
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/jake": {
+ "version": "10.8.5",
+ "resolved": "https://registry.npmjs.org/jake/-/jake-10.8.5.tgz",
+ "integrity": "sha512-sVpxYeuAhWt0OTWITwT98oyV0GsXyMlXCF+3L1SuafBVUIr/uILGRB+NqwkzhgXKvoJpDIpQvqkUALgdmQsQxw==",
+ "dev": true,
+ "dependencies": {
+ "async": "^3.2.3",
+ "chalk": "^4.0.2",
+ "filelist": "^1.0.1",
+ "minimatch": "^3.0.4"
+ },
+ "bin": {
+ "jake": "bin/cli.js"
+ },
+ "engines": {
+ "node": ">=10"
+ }
+ },
+ "node_modules/jest": {
+ "version": "26.6.3",
+ "resolved": "https://registry.npmjs.org/jest/-/jest-26.6.3.tgz",
+ "integrity": "sha512-lGS5PXGAzR4RF7V5+XObhqz2KZIDUA1yD0DG6pBVmy10eh0ZIXQImRuzocsI/N2XZ1GrLFwTS27In2i2jlpq1Q==",
+ "dev": true,
+ "peer": true,
+ "dependencies": {
+ "@jest/core": "^26.6.3",
+ "import-local": "^3.0.2",
+ "jest-cli": "^26.6.3"
+ },
+ "bin": {
+ "jest": "bin/jest.js"
+ },
+ "engines": {
+ "node": ">= 10.14.2"
+ }
+ },
+ "node_modules/jest-changed-files": {
+ "version": "26.6.2",
+ "resolved": "https://registry.npmjs.org/jest-changed-files/-/jest-changed-files-26.6.2.tgz",
+ "integrity": "sha512-fDS7szLcY9sCtIip8Fjry9oGf3I2ht/QT21bAHm5Dmf0mD4X3ReNUf17y+bO6fR8WgbIZTlbyG1ak/53cbRzKQ==",
+ "dev": true,
+ "peer": true,
+ "dependencies": {
+ "@jest/types": "^26.6.2",
+ "execa": "^4.0.0",
+ "throat": "^5.0.0"
+ },
+ "engines": {
+ "node": ">= 10.14.2"
+ }
+ },
+ "node_modules/jest-cli": {
+ "version": "26.6.3",
+ "resolved": "https://registry.npmjs.org/jest-cli/-/jest-cli-26.6.3.tgz",
+ "integrity": "sha512-GF9noBSa9t08pSyl3CY4frMrqp+aQXFGFkf5hEPbh/pIUFYWMK6ZLTfbmadxJVcJrdRoChlWQsA2VkJcDFK8hg==",
+ "dev": true,
+ "peer": true,
+ "dependencies": {
+ "@jest/core": "^26.6.3",
+ "@jest/test-result": "^26.6.2",
+ "@jest/types": "^26.6.2",
+ "chalk": "^4.0.0",
+ "exit": "^0.1.2",
+ "graceful-fs": "^4.2.4",
+ "import-local": "^3.0.2",
+ "is-ci": "^2.0.0",
+ "jest-config": "^26.6.3",
+ "jest-util": "^26.6.2",
+ "jest-validate": "^26.6.2",
+ "prompts": "^2.0.1",
+ "yargs": "^15.4.1"
+ },
+ "bin": {
+ "jest": "bin/jest.js"
+ },
+ "engines": {
+ "node": ">= 10.14.2"
+ }
+ },
+ "node_modules/jest-config": {
+ "version": "26.6.3",
+ "resolved": "https://registry.npmjs.org/jest-config/-/jest-config-26.6.3.tgz",
+ "integrity": "sha512-t5qdIj/bCj2j7NFVHb2nFB4aUdfucDn3JRKgrZnplb8nieAirAzRSHP8uDEd+qV6ygzg9Pz4YG7UTJf94LPSyg==",
+ "dev": true,
+ "peer": true,
+ "dependencies": {
+ "@babel/core": "^7.1.0",
+ "@jest/test-sequencer": "^26.6.3",
+ "@jest/types": "^26.6.2",
+ "babel-jest": "^26.6.3",
+ "chalk": "^4.0.0",
+ "deepmerge": "^4.2.2",
+ "glob": "^7.1.1",
+ "graceful-fs": "^4.2.4",
+ "jest-environment-jsdom": "^26.6.2",
+ "jest-environment-node": "^26.6.2",
+ "jest-get-type": "^26.3.0",
+ "jest-jasmine2": "^26.6.3",
+ "jest-regex-util": "^26.0.0",
+ "jest-resolve": "^26.6.2",
+ "jest-util": "^26.6.2",
+ "jest-validate": "^26.6.2",
+ "micromatch": "^4.0.2",
+ "pretty-format": "^26.6.2"
+ },
+ "engines": {
+ "node": ">= 10.14.2"
+ },
+ "peerDependencies": {
+ "ts-node": ">=9.0.0"
+ },
+ "peerDependenciesMeta": {
+ "ts-node": {
+ "optional": true
+ }
+ }
+ },
+ "node_modules/jest-diff": {
+ "version": "26.6.2",
+ "resolved": "https://registry.npmjs.org/jest-diff/-/jest-diff-26.6.2.tgz",
+ "integrity": "sha512-6m+9Z3Gv9wN0WFVasqjCL/06+EFCMTqDEUl/b87HYK2rAPTyfz4ZIuSlPhY51PIQRWx5TaxeF1qmXKe9gfN3sA==",
+ "dev": true,
+ "peer": true,
+ "dependencies": {
+ "chalk": "^4.0.0",
+ "diff-sequences": "^26.6.2",
+ "jest-get-type": "^26.3.0",
+ "pretty-format": "^26.6.2"
+ },
+ "engines": {
+ "node": ">= 10.14.2"
+ }
+ },
+ "node_modules/jest-docblock": {
+ "version": "26.0.0",
+ "resolved": "https://registry.npmjs.org/jest-docblock/-/jest-docblock-26.0.0.tgz",
+ "integrity": "sha512-RDZ4Iz3QbtRWycd8bUEPxQsTlYazfYn/h5R65Fc6gOfwozFhoImx+affzky/FFBuqISPTqjXomoIGJVKBWoo0w==",
+ "dev": true,
+ "peer": true,
+ "dependencies": {
+ "detect-newline": "^3.0.0"
+ },
+ "engines": {
+ "node": ">= 10.14.2"
+ }
+ },
+ "node_modules/jest-each": {
+ "version": "26.6.2",
+ "resolved": "https://registry.npmjs.org/jest-each/-/jest-each-26.6.2.tgz",
+ "integrity": "sha512-Mer/f0KaATbjl8MCJ+0GEpNdqmnVmDYqCTJYTvoo7rqmRiDllmp2AYN+06F93nXcY3ur9ShIjS+CO/uD+BbH4A==",
+ "dev": true,
+ "peer": true,
+ "dependencies": {
+ "@jest/types": "^26.6.2",
+ "chalk": "^4.0.0",
+ "jest-get-type": "^26.3.0",
+ "jest-util": "^26.6.2",
+ "pretty-format": "^26.6.2"
+ },
+ "engines": {
+ "node": ">= 10.14.2"
+ }
+ },
+ "node_modules/jest-environment-jsdom": {
+ "version": "26.6.2",
+ "resolved": "https://registry.npmjs.org/jest-environment-jsdom/-/jest-environment-jsdom-26.6.2.tgz",
+ "integrity": "sha512-jgPqCruTlt3Kwqg5/WVFyHIOJHsiAvhcp2qiR2QQstuG9yWox5+iHpU3ZrcBxW14T4fe5Z68jAfLRh7joCSP2Q==",
+ "dev": true,
+ "peer": true,
+ "dependencies": {
+ "@jest/environment": "^26.6.2",
+ "@jest/fake-timers": "^26.6.2",
+ "@jest/types": "^26.6.2",
+ "@types/node": "*",
+ "jest-mock": "^26.6.2",
+ "jest-util": "^26.6.2",
+ "jsdom": "^16.4.0"
+ },
+ "engines": {
+ "node": ">= 10.14.2"
+ }
+ },
+ "node_modules/jest-environment-node": {
+ "version": "26.6.2",
+ "resolved": "https://registry.npmjs.org/jest-environment-node/-/jest-environment-node-26.6.2.tgz",
+ "integrity": "sha512-zhtMio3Exty18dy8ee8eJ9kjnRyZC1N4C1Nt/VShN1apyXc8rWGtJ9lI7vqiWcyyXS4BVSEn9lxAM2D+07/Tag==",
+ "dev": true,
+ "peer": true,
+ "dependencies": {
+ "@jest/environment": "^26.6.2",
+ "@jest/fake-timers": "^26.6.2",
+ "@jest/types": "^26.6.2",
+ "@types/node": "*",
+ "jest-mock": "^26.6.2",
+ "jest-util": "^26.6.2"
+ },
+ "engines": {
+ "node": ">= 10.14.2"
+ }
+ },
+ "node_modules/jest-get-type": {
+ "version": "26.3.0",
+ "resolved": "https://registry.npmjs.org/jest-get-type/-/jest-get-type-26.3.0.tgz",
+ "integrity": "sha512-TpfaviN1R2pQWkIihlfEanwOXK0zcxrKEE4MlU6Tn7keoXdN6/3gK/xl0yEh8DOunn5pOVGKf8hB4R9gVh04ig==",
+ "dev": true,
+ "peer": true,
+ "engines": {
+ "node": ">= 10.14.2"
+ }
+ },
+ "node_modules/jest-haste-map": {
+ "version": "26.6.2",
+ "resolved": "https://registry.npmjs.org/jest-haste-map/-/jest-haste-map-26.6.2.tgz",
+ "integrity": "sha512-easWIJXIw71B2RdR8kgqpjQrbMRWQBgiBwXYEhtGUTaX+doCjBheluShdDMeR8IMfJiTqH4+zfhtg29apJf/8w==",
+ "dev": true,
+ "peer": true,
+ "dependencies": {
+ "@jest/types": "^26.6.2",
+ "@types/graceful-fs": "^4.1.2",
+ "@types/node": "*",
+ "anymatch": "^3.0.3",
+ "fb-watchman": "^2.0.0",
+ "graceful-fs": "^4.2.4",
+ "jest-regex-util": "^26.0.0",
+ "jest-serializer": "^26.6.2",
+ "jest-util": "^26.6.2",
+ "jest-worker": "^26.6.2",
+ "micromatch": "^4.0.2",
+ "sane": "^4.0.3",
+ "walker": "^1.0.7"
+ },
+ "engines": {
+ "node": ">= 10.14.2"
+ },
+ "optionalDependencies": {
+ "fsevents": "^2.1.2"
+ }
+ },
+ "node_modules/jest-jasmine2": {
+ "version": "26.6.3",
+ "resolved": "https://registry.npmjs.org/jest-jasmine2/-/jest-jasmine2-26.6.3.tgz",
+ "integrity": "sha512-kPKUrQtc8aYwBV7CqBg5pu+tmYXlvFlSFYn18ev4gPFtrRzB15N2gW/Roew3187q2w2eHuu0MU9TJz6w0/nPEg==",
+ "dev": true,
+ "peer": true,
+ "dependencies": {
+ "@babel/traverse": "^7.1.0",
+ "@jest/environment": "^26.6.2",
+ "@jest/source-map": "^26.6.2",
+ "@jest/test-result": "^26.6.2",
+ "@jest/types": "^26.6.2",
+ "@types/node": "*",
+ "chalk": "^4.0.0",
+ "co": "^4.6.0",
+ "expect": "^26.6.2",
+ "is-generator-fn": "^2.0.0",
+ "jest-each": "^26.6.2",
+ "jest-matcher-utils": "^26.6.2",
+ "jest-message-util": "^26.6.2",
+ "jest-runtime": "^26.6.3",
+ "jest-snapshot": "^26.6.2",
+ "jest-util": "^26.6.2",
+ "pretty-format": "^26.6.2",
+ "throat": "^5.0.0"
+ },
+ "engines": {
+ "node": ">= 10.14.2"
+ }
+ },
+ "node_modules/jest-leak-detector": {
+ "version": "26.6.2",
+ "resolved": "https://registry.npmjs.org/jest-leak-detector/-/jest-leak-detector-26.6.2.tgz",
+ "integrity": "sha512-i4xlXpsVSMeKvg2cEKdfhh0H39qlJlP5Ex1yQxwF9ubahboQYMgTtz5oML35AVA3B4Eu+YsmwaiKVev9KCvLxg==",
+ "dev": true,
+ "peer": true,
+ "dependencies": {
+ "jest-get-type": "^26.3.0",
+ "pretty-format": "^26.6.2"
+ },
+ "engines": {
+ "node": ">= 10.14.2"
+ }
+ },
+ "node_modules/jest-matcher-utils": {
+ "version": "26.6.2",
+ "resolved": "https://registry.npmjs.org/jest-matcher-utils/-/jest-matcher-utils-26.6.2.tgz",
+ "integrity": "sha512-llnc8vQgYcNqDrqRDXWwMr9i7rS5XFiCwvh6DTP7Jqa2mqpcCBBlpCbn+trkG0KNhPu/h8rzyBkriOtBstvWhw==",
+ "dev": true,
+ "peer": true,
+ "dependencies": {
+ "chalk": "^4.0.0",
+ "jest-diff": "^26.6.2",
+ "jest-get-type": "^26.3.0",
+ "pretty-format": "^26.6.2"
+ },
+ "engines": {
+ "node": ">= 10.14.2"
+ }
+ },
+ "node_modules/jest-message-util": {
+ "version": "26.6.2",
+ "resolved": "https://registry.npmjs.org/jest-message-util/-/jest-message-util-26.6.2.tgz",
+ "integrity": "sha512-rGiLePzQ3AzwUshu2+Rn+UMFk0pHN58sOG+IaJbk5Jxuqo3NYO1U2/MIR4S1sKgsoYSXSzdtSa0TgrmtUwEbmA==",
+ "dev": true,
+ "peer": true,
+ "dependencies": {
+ "@babel/code-frame": "^7.0.0",
+ "@jest/types": "^26.6.2",
+ "@types/stack-utils": "^2.0.0",
+ "chalk": "^4.0.0",
+ "graceful-fs": "^4.2.4",
+ "micromatch": "^4.0.2",
+ "pretty-format": "^26.6.2",
+ "slash": "^3.0.0",
+ "stack-utils": "^2.0.2"
+ },
+ "engines": {
+ "node": ">= 10.14.2"
+ }
+ },
+ "node_modules/jest-mock": {
+ "version": "26.6.2",
+ "resolved": "https://registry.npmjs.org/jest-mock/-/jest-mock-26.6.2.tgz",
+ "integrity": "sha512-YyFjePHHp1LzpzYcmgqkJ0nm0gg/lJx2aZFzFy1S6eUqNjXsOqTK10zNRff2dNfssgokjkG65OlWNcIlgd3zew==",
+ "dev": true,
+ "peer": true,
+ "dependencies": {
+ "@jest/types": "^26.6.2",
+ "@types/node": "*"
+ },
+ "engines": {
+ "node": ">= 10.14.2"
+ }
+ },
+ "node_modules/jest-pnp-resolver": {
+ "version": "1.2.2",
+ "resolved": "https://registry.npmjs.org/jest-pnp-resolver/-/jest-pnp-resolver-1.2.2.tgz",
+ "integrity": "sha512-olV41bKSMm8BdnuMsewT4jqlZ8+3TCARAXjZGT9jcoSnrfUnRCqnMoF9XEeoWjbzObpqF9dRhHQj0Xb9QdF6/w==",
+ "dev": true,
+ "peer": true,
+ "engines": {
+ "node": ">=6"
+ },
+ "peerDependencies": {
+ "jest-resolve": "*"
+ },
+ "peerDependenciesMeta": {
+ "jest-resolve": {
+ "optional": true
+ }
+ }
+ },
+ "node_modules/jest-regex-util": {
+ "version": "26.0.0",
+ "resolved": "https://registry.npmjs.org/jest-regex-util/-/jest-regex-util-26.0.0.tgz",
+ "integrity": "sha512-Gv3ZIs/nA48/Zvjrl34bf+oD76JHiGDUxNOVgUjh3j890sblXryjY4rss71fPtD/njchl6PSE2hIhvyWa1eT0A==",
+ "dev": true,
+ "peer": true,
+ "engines": {
+ "node": ">= 10.14.2"
+ }
+ },
+ "node_modules/jest-resolve": {
+ "version": "26.6.2",
+ "resolved": "https://registry.npmjs.org/jest-resolve/-/jest-resolve-26.6.2.tgz",
+ "integrity": "sha512-sOxsZOq25mT1wRsfHcbtkInS+Ek7Q8jCHUB0ZUTP0tc/c41QHriU/NunqMfCUWsL4H3MHpvQD4QR9kSYhS7UvQ==",
+ "dev": true,
+ "peer": true,
+ "dependencies": {
+ "@jest/types": "^26.6.2",
+ "chalk": "^4.0.0",
+ "graceful-fs": "^4.2.4",
+ "jest-pnp-resolver": "^1.2.2",
+ "jest-util": "^26.6.2",
+ "read-pkg-up": "^7.0.1",
+ "resolve": "^1.18.1",
+ "slash": "^3.0.0"
+ },
+ "engines": {
+ "node": ">= 10.14.2"
+ }
+ },
+ "node_modules/jest-resolve-dependencies": {
+ "version": "26.6.3",
+ "resolved": "https://registry.npmjs.org/jest-resolve-dependencies/-/jest-resolve-dependencies-26.6.3.tgz",
+ "integrity": "sha512-pVwUjJkxbhe4RY8QEWzN3vns2kqyuldKpxlxJlzEYfKSvY6/bMvxoFrYYzUO1Gx28yKWN37qyV7rIoIp2h8fTg==",
+ "dev": true,
+ "peer": true,
+ "dependencies": {
+ "@jest/types": "^26.6.2",
+ "jest-regex-util": "^26.0.0",
+ "jest-snapshot": "^26.6.2"
+ },
+ "engines": {
+ "node": ">= 10.14.2"
+ }
+ },
+ "node_modules/jest-runner": {
+ "version": "26.6.3",
+ "resolved": "https://registry.npmjs.org/jest-runner/-/jest-runner-26.6.3.tgz",
+ "integrity": "sha512-atgKpRHnaA2OvByG/HpGA4g6CSPS/1LK0jK3gATJAoptC1ojltpmVlYC3TYgdmGp+GLuhzpH30Gvs36szSL2JQ==",
+ "dev": true,
+ "peer": true,
+ "dependencies": {
+ "@jest/console": "^26.6.2",
+ "@jest/environment": "^26.6.2",
+ "@jest/test-result": "^26.6.2",
+ "@jest/types": "^26.6.2",
+ "@types/node": "*",
+ "chalk": "^4.0.0",
+ "emittery": "^0.7.1",
+ "exit": "^0.1.2",
+ "graceful-fs": "^4.2.4",
+ "jest-config": "^26.6.3",
+ "jest-docblock": "^26.0.0",
+ "jest-haste-map": "^26.6.2",
+ "jest-leak-detector": "^26.6.2",
+ "jest-message-util": "^26.6.2",
+ "jest-resolve": "^26.6.2",
+ "jest-runtime": "^26.6.3",
+ "jest-util": "^26.6.2",
+ "jest-worker": "^26.6.2",
+ "source-map-support": "^0.5.6",
+ "throat": "^5.0.0"
+ },
+ "engines": {
+ "node": ">= 10.14.2"
+ }
+ },
+ "node_modules/jest-runtime": {
+ "version": "26.6.3",
+ "resolved": "https://registry.npmjs.org/jest-runtime/-/jest-runtime-26.6.3.tgz",
+ "integrity": "sha512-lrzyR3N8sacTAMeonbqpnSka1dHNux2uk0qqDXVkMv2c/A3wYnvQ4EXuI013Y6+gSKSCxdaczvf4HF0mVXHRdw==",
+ "dev": true,
+ "peer": true,
+ "dependencies": {
+ "@jest/console": "^26.6.2",
+ "@jest/environment": "^26.6.2",
+ "@jest/fake-timers": "^26.6.2",
+ "@jest/globals": "^26.6.2",
+ "@jest/source-map": "^26.6.2",
+ "@jest/test-result": "^26.6.2",
+ "@jest/transform": "^26.6.2",
+ "@jest/types": "^26.6.2",
+ "@types/yargs": "^15.0.0",
+ "chalk": "^4.0.0",
+ "cjs-module-lexer": "^0.6.0",
+ "collect-v8-coverage": "^1.0.0",
+ "exit": "^0.1.2",
+ "glob": "^7.1.3",
+ "graceful-fs": "^4.2.4",
+ "jest-config": "^26.6.3",
+ "jest-haste-map": "^26.6.2",
+ "jest-message-util": "^26.6.2",
+ "jest-mock": "^26.6.2",
+ "jest-regex-util": "^26.0.0",
+ "jest-resolve": "^26.6.2",
+ "jest-snapshot": "^26.6.2",
+ "jest-util": "^26.6.2",
+ "jest-validate": "^26.6.2",
+ "slash": "^3.0.0",
+ "strip-bom": "^4.0.0",
+ "yargs": "^15.4.1"
+ },
+ "bin": {
+ "jest-runtime": "bin/jest-runtime.js"
+ },
+ "engines": {
+ "node": ">= 10.14.2"
+ }
+ },
+ "node_modules/jest-serializer": {
+ "version": "26.6.2",
+ "resolved": "https://registry.npmjs.org/jest-serializer/-/jest-serializer-26.6.2.tgz",
+ "integrity": "sha512-S5wqyz0DXnNJPd/xfIzZ5Xnp1HrJWBczg8mMfMpN78OJ5eDxXyf+Ygld9wX1DnUWbIbhM1YDY95NjR4CBXkb2g==",
+ "dev": true,
+ "peer": true,
+ "dependencies": {
+ "@types/node": "*",
+ "graceful-fs": "^4.2.4"
+ },
+ "engines": {
+ "node": ">= 10.14.2"
+ }
+ },
+ "node_modules/jest-snapshot": {
+ "version": "26.6.2",
+ "resolved": "https://registry.npmjs.org/jest-snapshot/-/jest-snapshot-26.6.2.tgz",
+ "integrity": "sha512-OLhxz05EzUtsAmOMzuupt1lHYXCNib0ECyuZ/PZOx9TrZcC8vL0x+DUG3TL+GLX3yHG45e6YGjIm0XwDc3q3og==",
+ "dev": true,
+ "peer": true,
+ "dependencies": {
+ "@babel/types": "^7.0.0",
+ "@jest/types": "^26.6.2",
+ "@types/babel__traverse": "^7.0.4",
+ "@types/prettier": "^2.0.0",
+ "chalk": "^4.0.0",
+ "expect": "^26.6.2",
+ "graceful-fs": "^4.2.4",
+ "jest-diff": "^26.6.2",
+ "jest-get-type": "^26.3.0",
+ "jest-haste-map": "^26.6.2",
+ "jest-matcher-utils": "^26.6.2",
+ "jest-message-util": "^26.6.2",
+ "jest-resolve": "^26.6.2",
+ "natural-compare": "^1.4.0",
+ "pretty-format": "^26.6.2",
+ "semver": "^7.3.2"
+ },
+ "engines": {
+ "node": ">= 10.14.2"
+ }
+ },
+ "node_modules/jest-util": {
+ "version": "26.6.2",
+ "resolved": "https://registry.npmjs.org/jest-util/-/jest-util-26.6.2.tgz",
+ "integrity": "sha512-MDW0fKfsn0OI7MS7Euz6h8HNDXVQ0gaM9uW6RjfDmd1DAFcaxX9OqIakHIqhbnmF08Cf2DLDG+ulq8YQQ0Lp0Q==",
+ "dev": true,
+ "dependencies": {
+ "@jest/types": "^26.6.2",
+ "@types/node": "*",
+ "chalk": "^4.0.0",
+ "graceful-fs": "^4.2.4",
+ "is-ci": "^2.0.0",
+ "micromatch": "^4.0.2"
+ },
+ "engines": {
+ "node": ">= 10.14.2"
+ }
+ },
+ "node_modules/jest-validate": {
+ "version": "26.6.2",
+ "resolved": "https://registry.npmjs.org/jest-validate/-/jest-validate-26.6.2.tgz",
+ "integrity": "sha512-NEYZ9Aeyj0i5rQqbq+tpIOom0YS1u2MVu6+euBsvpgIme+FOfRmoC4R5p0JiAUpaFvFy24xgrpMknarR/93XjQ==",
+ "dev": true,
+ "peer": true,
+ "dependencies": {
+ "@jest/types": "^26.6.2",
+ "camelcase": "^6.0.0",
+ "chalk": "^4.0.0",
+ "jest-get-type": "^26.3.0",
+ "leven": "^3.1.0",
+ "pretty-format": "^26.6.2"
+ },
+ "engines": {
+ "node": ">= 10.14.2"
+ }
+ },
+ "node_modules/jest-validate/node_modules/camelcase": {
+ "version": "6.3.0",
+ "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-6.3.0.tgz",
+ "integrity": "sha512-Gmy6FhYlCY7uOElZUSbxo2UCDH8owEk996gkbrpsgGtrJLM3J7jGxl9Ic7Qwwj4ivOE5AWZWRMecDdF7hqGjFA==",
+ "dev": true,
+ "peer": true,
+ "engines": {
+ "node": ">=10"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
+ "node_modules/jest-watcher": {
+ "version": "26.6.2",
+ "resolved": "https://registry.npmjs.org/jest-watcher/-/jest-watcher-26.6.2.tgz",
+ "integrity": "sha512-WKJob0P/Em2csiVthsI68p6aGKTIcsfjH9Gsx1f0A3Italz43e3ho0geSAVsmj09RWOELP1AZ/DXyJgOgDKxXQ==",
+ "dev": true,
+ "peer": true,
+ "dependencies": {
+ "@jest/test-result": "^26.6.2",
+ "@jest/types": "^26.6.2",
+ "@types/node": "*",
+ "ansi-escapes": "^4.2.1",
+ "chalk": "^4.0.0",
+ "jest-util": "^26.6.2",
+ "string-length": "^4.0.1"
+ },
+ "engines": {
+ "node": ">= 10.14.2"
+ }
+ },
+ "node_modules/jest-worker": {
+ "version": "26.6.2",
+ "resolved": "https://registry.npmjs.org/jest-worker/-/jest-worker-26.6.2.tgz",
+ "integrity": "sha512-KWYVV1c4i+jbMpaBC+U++4Va0cp8OisU185o73T1vo99hqi7w8tSJfUXYswwqqrjzwxa6KpRK54WhPvwf5w6PQ==",
+ "dev": true,
+ "peer": true,
+ "dependencies": {
+ "@types/node": "*",
+ "merge-stream": "^2.0.0",
+ "supports-color": "^7.0.0"
+ },
+ "engines": {
+ "node": ">= 10.13.0"
+ }
+ },
+ "node_modules/js-sdsl": {
+ "version": "4.3.0",
+ "resolved": "https://registry.npmjs.org/js-sdsl/-/js-sdsl-4.3.0.tgz",
+ "integrity": "sha512-mifzlm2+5nZ+lEcLJMoBK0/IH/bDg8XnJfd/Wq6IP+xoCjLZsTOnV2QpxlVbX9bMnkl5PdEjNtBJ9Cj1NjifhQ==",
+ "dev": true,
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/js-sdsl"
+ }
+ },
+ "node_modules/js-tokens": {
+ "version": "4.0.0",
+ "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz",
+ "integrity": "sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==",
+ "dev": true
+ },
+ "node_modules/js-yaml": {
+ "version": "4.1.0",
+ "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-4.1.0.tgz",
+ "integrity": "sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA==",
+ "dev": true,
+ "dependencies": {
+ "argparse": "^2.0.1"
+ },
+ "bin": {
+ "js-yaml": "bin/js-yaml.js"
+ }
+ },
+ "node_modules/jsdom": {
+ "version": "16.7.0",
+ "resolved": "https://registry.npmjs.org/jsdom/-/jsdom-16.7.0.tgz",
+ "integrity": "sha512-u9Smc2G1USStM+s/x1ru5Sxrl6mPYCbByG1U/hUmqaVsm4tbNyS7CicOSRyuGQYZhTu0h84qkZZQ/I+dzizSVw==",
+ "dev": true,
+ "peer": true,
+ "dependencies": {
+ "abab": "^2.0.5",
+ "acorn": "^8.2.4",
+ "acorn-globals": "^6.0.0",
+ "cssom": "^0.4.4",
+ "cssstyle": "^2.3.0",
+ "data-urls": "^2.0.0",
+ "decimal.js": "^10.2.1",
+ "domexception": "^2.0.1",
+ "escodegen": "^2.0.0",
+ "form-data": "^3.0.0",
+ "html-encoding-sniffer": "^2.0.1",
+ "http-proxy-agent": "^4.0.1",
+ "https-proxy-agent": "^5.0.0",
+ "is-potential-custom-element-name": "^1.0.1",
+ "nwsapi": "^2.2.0",
+ "parse5": "6.0.1",
+ "saxes": "^5.0.1",
+ "symbol-tree": "^3.2.4",
+ "tough-cookie": "^4.0.0",
+ "w3c-hr-time": "^1.0.2",
+ "w3c-xmlserializer": "^2.0.0",
+ "webidl-conversions": "^6.1.0",
+ "whatwg-encoding": "^1.0.5",
+ "whatwg-mimetype": "^2.3.0",
+ "whatwg-url": "^8.5.0",
+ "ws": "^7.4.6",
+ "xml-name-validator": "^3.0.0"
+ },
+ "engines": {
+ "node": ">=10"
+ },
+ "peerDependencies": {
+ "canvas": "^2.5.0"
+ },
+ "peerDependenciesMeta": {
+ "canvas": {
+ "optional": true
+ }
+ }
+ },
+ "node_modules/jsesc": {
+ "version": "2.5.2",
+ "resolved": "https://registry.npmjs.org/jsesc/-/jsesc-2.5.2.tgz",
+ "integrity": "sha512-OYu7XEzjkCQ3C5Ps3QIZsQfNpqoJyZZA99wd9aWd05NCtC5pWOkShK2mkL6HXQR6/Cy2lbNdPlZBpuQHXE63gA==",
+ "dev": true,
+ "bin": {
+ "jsesc": "bin/jsesc"
+ },
+ "engines": {
+ "node": ">=4"
+ }
+ },
+ "node_modules/json-parse-better-errors": {
+ "version": "1.0.2",
+ "resolved": "https://registry.npmjs.org/json-parse-better-errors/-/json-parse-better-errors-1.0.2.tgz",
+ "integrity": "sha512-mrqyZKfX5EhL7hvqcV6WG1yYjnjeuYDzDhhcAAUrq8Po85NBQBJP+ZDUT75qZQ98IkUoBqdkExkukOU7Ts2wrw==",
+ "dev": true
+ },
+ "node_modules/json-parse-even-better-errors": {
+ "version": "2.3.1",
+ "resolved": "https://registry.npmjs.org/json-parse-even-better-errors/-/json-parse-even-better-errors-2.3.1.tgz",
+ "integrity": "sha512-xyFwyhro/JEof6Ghe2iz2NcXoj2sloNsWr/XsERDK/oiPCfaNhl5ONfp+jQdAZRQQ0IJWNzH9zIZF7li91kh2w==",
+ "dev": true
+ },
+ "node_modules/json-schema-traverse": {
+ "version": "0.4.1",
+ "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz",
+ "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==",
+ "dev": true
+ },
+ "node_modules/json-stable-stringify-without-jsonify": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/json-stable-stringify-without-jsonify/-/json-stable-stringify-without-jsonify-1.0.1.tgz",
+ "integrity": "sha512-Bdboy+l7tA3OGW6FjyFHWkP5LuByj1Tk33Ljyq0axyzdk9//JSi2u3fP1QSmd1KNwq6VOKYGlAu87CisVir6Pw==",
+ "dev": true
+ },
+ "node_modules/json5": {
+ "version": "2.2.3",
+ "resolved": "https://registry.npmjs.org/json5/-/json5-2.2.3.tgz",
+ "integrity": "sha512-XmOWe7eyHYH14cLdVPoyg+GOH3rYX++KpzrylJwSW98t3Nk+U8XOl8FWKOgwtzdb8lXGf6zYwDUzeHMWfxasyg==",
+ "dev": true,
+ "bin": {
+ "json5": "lib/cli.js"
+ },
+ "engines": {
+ "node": ">=6"
+ }
+ },
+ "node_modules/jsonfile": {
+ "version": "6.1.0",
+ "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-6.1.0.tgz",
+ "integrity": "sha512-5dgndWOriYSm5cnYaJNhalLNDKOqFwyDB/rr1E9ZsGciGvKPs8R2xYGCacuf3z6K1YKDz182fd+fY3cn3pMqXQ==",
+ "dev": true,
+ "dependencies": {
+ "universalify": "^2.0.0"
+ },
+ "optionalDependencies": {
+ "graceful-fs": "^4.1.6"
+ }
+ },
+ "node_modules/jsonfile/node_modules/universalify": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/universalify/-/universalify-2.0.0.tgz",
+ "integrity": "sha512-hAZsKq7Yy11Zu1DE0OzWjw7nnLZmJZYTDZZyEFHZdUhV8FkH5MCfoU1XMaxXovpyW5nq5scPqq0ZDP9Zyl04oQ==",
+ "dev": true,
+ "engines": {
+ "node": ">= 10.0.0"
+ }
+ },
+ "node_modules/jsx-ast-utils": {
+ "version": "3.3.3",
+ "resolved": "https://registry.npmjs.org/jsx-ast-utils/-/jsx-ast-utils-3.3.3.tgz",
+ "integrity": "sha512-fYQHZTZ8jSfmWZ0iyzfwiU4WDX4HpHbMCZ3gPlWYiCl3BoeOTsqKBqnTVfH2rYT7eP5c3sVbeSPHnnJOaTrWiw==",
+ "dev": true,
+ "dependencies": {
+ "array-includes": "^3.1.5",
+ "object.assign": "^4.1.3"
+ },
+ "engines": {
+ "node": ">=4.0"
+ }
+ },
+ "node_modules/kind-of": {
+ "version": "6.0.3",
+ "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-6.0.3.tgz",
+ "integrity": "sha512-dcS1ul+9tmeD95T+x28/ehLgd9mENa3LsvDTtzm3vyBEO7RPptvAD+t44WVXaUjTBRcrpFeFlC8WCruUR456hw==",
+ "dev": true,
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
+ "node_modules/kleur": {
+ "version": "3.0.3",
+ "resolved": "https://registry.npmjs.org/kleur/-/kleur-3.0.3.tgz",
+ "integrity": "sha512-eTIzlVOSUR+JxdDFepEYcBMtZ9Qqdef+rnzWdRZuMbOywu5tO2w2N7rqjoANZ5k9vywhL6Br1VRjUIgTQx4E8w==",
+ "dev": true,
+ "peer": true,
+ "engines": {
+ "node": ">=6"
+ }
+ },
+ "node_modules/known-css-properties": {
+ "version": "0.20.0",
+ "resolved": "https://registry.npmjs.org/known-css-properties/-/known-css-properties-0.20.0.tgz",
+ "integrity": "sha512-URvsjaA9ypfreqJ2/ylDr5MUERhJZ+DhguoWRr2xgS5C7aGCalXo+ewL+GixgKBfhT2vuL02nbIgNGqVWgTOYw==",
+ "dev": true
+ },
+ "node_modules/language-subtag-registry": {
+ "version": "0.3.22",
+ "resolved": "https://registry.npmjs.org/language-subtag-registry/-/language-subtag-registry-0.3.22.tgz",
+ "integrity": "sha512-tN0MCzyWnoz/4nHS6uxdlFWoUZT7ABptwKPQ52Ea7URk6vll88bWBVhodtnlfEuCcKWNGoc+uGbw1cwa9IKh/w==",
+ "dev": true
+ },
+ "node_modules/language-tags": {
+ "version": "1.0.5",
+ "resolved": "https://registry.npmjs.org/language-tags/-/language-tags-1.0.5.tgz",
+ "integrity": "sha512-qJhlO9cGXi6hBGKoxEG/sKZDAHD5Hnu9Hs4WbOY3pCWXDhw0N8x1NenNzm2EnNLkLkk7J2SdxAkDSbb6ftT+UQ==",
+ "dev": true,
+ "dependencies": {
+ "language-subtag-registry": "~0.3.2"
+ }
+ },
+ "node_modules/leven": {
+ "version": "3.1.0",
+ "resolved": "https://registry.npmjs.org/leven/-/leven-3.1.0.tgz",
+ "integrity": "sha512-qsda+H8jTaUaN/x5vzW2rzc+8Rw4TAQ/4KjB46IwK5VH+IlVeeeje/EoZRpiXvIqjFgK84QffqPztGI3VBLG1A==",
+ "dev": true,
+ "peer": true,
+ "engines": {
+ "node": ">=6"
+ }
+ },
+ "node_modules/levn": {
+ "version": "0.4.1",
+ "resolved": "https://registry.npmjs.org/levn/-/levn-0.4.1.tgz",
+ "integrity": "sha512-+bT2uH4E5LGE7h/n3evcS/sQlJXCpIp6ym8OWJ5eV6+67Dsql/LaaT7qJBAt2rzfoa/5QBGBhxDix1dMt2kQKQ==",
+ "dev": true,
+ "dependencies": {
+ "prelude-ls": "^1.2.1",
+ "type-check": "~0.4.0"
+ },
+ "engines": {
+ "node": ">= 0.8.0"
+ }
+ },
+ "node_modules/lines-and-columns": {
+ "version": "1.1.6",
+ "resolved": "https://registry.npmjs.org/lines-and-columns/-/lines-and-columns-1.1.6.tgz",
+ "integrity": "sha1-HADHQ7QzzQpOgHWPe2SldEDZ/wA=",
+ "dev": true
+ },
+ "node_modules/lint-staged": {
+ "version": "11.1.2",
+ "resolved": "https://registry.npmjs.org/lint-staged/-/lint-staged-11.1.2.tgz",
+ "integrity": "sha512-6lYpNoA9wGqkL6Hew/4n1H6lRqF3qCsujVT0Oq5Z4hiSAM7S6NksPJ3gnr7A7R52xCtiZMcEUNNQ6d6X5Bvh9w==",
+ "dev": true,
+ "dependencies": {
+ "chalk": "^4.1.1",
+ "cli-truncate": "^2.1.0",
+ "commander": "^7.2.0",
+ "cosmiconfig": "^7.0.0",
+ "debug": "^4.3.1",
+ "enquirer": "^2.3.6",
+ "execa": "^5.0.0",
+ "listr2": "^3.8.2",
+ "log-symbols": "^4.1.0",
+ "micromatch": "^4.0.4",
+ "normalize-path": "^3.0.0",
+ "please-upgrade-node": "^3.2.0",
+ "string-argv": "0.3.1",
+ "stringify-object": "^3.3.0"
+ },
+ "bin": {
+ "lint-staged": "bin/lint-staged.js"
+ },
+ "funding": {
+ "url": "https://opencollective.com/lint-staged"
+ }
+ },
+ "node_modules/lint-staged/node_modules/chalk": {
+ "version": "4.1.2",
+ "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz",
+ "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==",
+ "dev": true,
+ "dependencies": {
+ "ansi-styles": "^4.1.0",
+ "supports-color": "^7.1.0"
+ },
+ "engines": {
+ "node": ">=10"
+ },
+ "funding": {
+ "url": "https://github.com/chalk/chalk?sponsor=1"
+ }
+ },
+ "node_modules/lint-staged/node_modules/execa": {
+ "version": "5.1.1",
+ "resolved": "https://registry.npmjs.org/execa/-/execa-5.1.1.tgz",
+ "integrity": "sha512-8uSpZZocAZRBAPIEINJj3Lo9HyGitllczc27Eh5YYojjMFMn8yHMDMaUHE2Jqfq05D/wucwI4JGURyXt1vchyg==",
+ "dev": true,
+ "dependencies": {
+ "cross-spawn": "^7.0.3",
+ "get-stream": "^6.0.0",
+ "human-signals": "^2.1.0",
+ "is-stream": "^2.0.0",
+ "merge-stream": "^2.0.0",
+ "npm-run-path": "^4.0.1",
+ "onetime": "^5.1.2",
+ "signal-exit": "^3.0.3",
+ "strip-final-newline": "^2.0.0"
+ },
+ "engines": {
+ "node": ">=10"
+ },
+ "funding": {
+ "url": "https://github.com/sindresorhus/execa?sponsor=1"
+ }
+ },
+ "node_modules/lint-staged/node_modules/get-stream": {
+ "version": "6.0.1",
+ "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-6.0.1.tgz",
+ "integrity": "sha512-ts6Wi+2j3jQjqi70w5AlN8DFnkSwC+MqmxEzdEALB2qXZYV3X/b1CTfgPLGJNMeAWxdPfU8FO1ms3NUfaHCPYg==",
+ "dev": true,
+ "engines": {
+ "node": ">=10"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
+ "node_modules/lint-staged/node_modules/human-signals": {
+ "version": "2.1.0",
+ "resolved": "https://registry.npmjs.org/human-signals/-/human-signals-2.1.0.tgz",
+ "integrity": "sha512-B4FFZ6q/T2jhhksgkbEW3HBvWIfDW85snkQgawt07S7J5QXTk6BkNV+0yAeZrM5QpMAdYlocGoljn0sJ/WQkFw==",
+ "dev": true,
+ "engines": {
+ "node": ">=10.17.0"
+ }
+ },
+ "node_modules/listr2": {
+ "version": "3.14.0",
+ "resolved": "https://registry.npmjs.org/listr2/-/listr2-3.14.0.tgz",
+ "integrity": "sha512-TyWI8G99GX9GjE54cJ+RrNMcIFBfwMPxc3XTFiAYGN4s10hWROGtOg7+O6u6LE3mNkyld7RSLE6nrKBvTfcs3g==",
+ "dev": true,
+ "dependencies": {
+ "cli-truncate": "^2.1.0",
+ "colorette": "^2.0.16",
+ "log-update": "^4.0.0",
+ "p-map": "^4.0.0",
+ "rfdc": "^1.3.0",
+ "rxjs": "^7.5.1",
+ "through": "^2.3.8",
+ "wrap-ansi": "^7.0.0"
+ },
+ "engines": {
+ "node": ">=10.0.0"
+ },
+ "peerDependencies": {
+ "enquirer": ">= 2.3.0 < 3"
+ },
+ "peerDependenciesMeta": {
+ "enquirer": {
+ "optional": true
+ }
+ }
+ },
+ "node_modules/listr2/node_modules/rxjs": {
+ "version": "7.5.5",
+ "resolved": "https://registry.npmjs.org/rxjs/-/rxjs-7.5.5.tgz",
+ "integrity": "sha512-sy+H0pQofO95VDmFLzyaw9xNJU4KTRSwQIGM6+iG3SypAtCiLDzpeG8sJrNCWn2Up9km+KhkvTdbkrdy+yzZdw==",
+ "dev": true,
+ "dependencies": {
+ "tslib": "^2.1.0"
+ }
+ },
+ "node_modules/listr2/node_modules/tslib": {
+ "version": "2.3.1",
+ "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.3.1.tgz",
+ "integrity": "sha512-77EbyPPpMz+FRFRuAFlWMtmgUWGe9UOG2Z25NqCwiIjRhOf5iKGuzSe5P2w1laq+FkRy4p+PCuVkJSGkzTEKVw==",
+ "dev": true
+ },
+ "node_modules/load-json-file": {
+ "version": "4.0.0",
+ "resolved": "https://registry.npmjs.org/load-json-file/-/load-json-file-4.0.0.tgz",
+ "integrity": "sha1-L19Fq5HjMhYjT9U62rZo607AmTs=",
+ "dev": true,
+ "dependencies": {
+ "graceful-fs": "^4.1.2",
+ "parse-json": "^4.0.0",
+ "pify": "^3.0.0",
+ "strip-bom": "^3.0.0"
+ },
+ "engines": {
+ "node": ">=4"
+ }
+ },
+ "node_modules/load-json-file/node_modules/parse-json": {
+ "version": "4.0.0",
+ "resolved": "https://registry.npmjs.org/parse-json/-/parse-json-4.0.0.tgz",
+ "integrity": "sha1-vjX1Qlvh9/bHRxhPmKeIy5lHfuA=",
+ "dev": true,
+ "dependencies": {
+ "error-ex": "^1.3.1",
+ "json-parse-better-errors": "^1.0.1"
+ },
+ "engines": {
+ "node": ">=4"
+ }
+ },
+ "node_modules/load-json-file/node_modules/strip-bom": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/strip-bom/-/strip-bom-3.0.0.tgz",
+ "integrity": "sha1-IzTBjpx1n3vdVv3vfprj1YjmjtM=",
+ "dev": true,
+ "engines": {
+ "node": ">=4"
+ }
+ },
+ "node_modules/locate-path": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-2.0.0.tgz",
+ "integrity": "sha1-K1aLJl7slExtnA3pw9u7ygNUzY4=",
+ "dev": true,
+ "dependencies": {
+ "p-locate": "^2.0.0",
+ "path-exists": "^3.0.0"
+ },
+ "engines": {
+ "node": ">=4"
+ }
+ },
+ "node_modules/locate-path/node_modules/path-exists": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-3.0.0.tgz",
+ "integrity": "sha1-zg6+ql94yxiSXqfYENe1mwEP1RU=",
+ "dev": true,
+ "engines": {
+ "node": ">=4"
+ }
+ },
+ "node_modules/lodash": {
+ "version": "4.17.21",
+ "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.21.tgz",
+ "integrity": "sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==",
+ "dev": true
+ },
+ "node_modules/lodash.merge": {
+ "version": "4.6.2",
+ "resolved": "https://registry.npmjs.org/lodash.merge/-/lodash.merge-4.6.2.tgz",
+ "integrity": "sha512-0KpjqXRVvrYyCsX1swR/XTK0va6VQkQM6MNo7PqW77ByjAhoARA8EfrP1N4+KlKj8YS0ZUCtRT/YUuhyYDujIQ==",
+ "dev": true
+ },
+ "node_modules/lodash.truncate": {
+ "version": "4.4.2",
+ "resolved": "https://registry.npmjs.org/lodash.truncate/-/lodash.truncate-4.4.2.tgz",
+ "integrity": "sha1-WjUNoLERO4N+z//VgSy+WNbq4ZM=",
+ "dev": true
+ },
+ "node_modules/log-symbols": {
+ "version": "4.1.0",
+ "resolved": "https://registry.npmjs.org/log-symbols/-/log-symbols-4.1.0.tgz",
+ "integrity": "sha512-8XPvpAA8uyhfteu8pIvQxpJZ7SYYdpUivZpGy6sFsBuKRY/7rQGavedeB8aK+Zkyq6upMFVL/9AW6vOYzfRyLg==",
+ "dev": true,
+ "dependencies": {
+ "chalk": "^4.1.0",
+ "is-unicode-supported": "^0.1.0"
+ },
+ "engines": {
+ "node": ">=10"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
+ "node_modules/log-update": {
+ "version": "4.0.0",
+ "resolved": "https://registry.npmjs.org/log-update/-/log-update-4.0.0.tgz",
+ "integrity": "sha512-9fkkDevMefjg0mmzWFBW8YkFP91OrizzkW3diF7CpG+S2EYdy4+TVfGwz1zeF8x7hCx1ovSPTOE9Ngib74qqUg==",
+ "dev": true,
+ "dependencies": {
+ "ansi-escapes": "^4.3.0",
+ "cli-cursor": "^3.1.0",
+ "slice-ansi": "^4.0.0",
+ "wrap-ansi": "^6.2.0"
+ },
+ "engines": {
+ "node": ">=10"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
+ "node_modules/log-update/node_modules/slice-ansi": {
+ "version": "4.0.0",
+ "resolved": "https://registry.npmjs.org/slice-ansi/-/slice-ansi-4.0.0.tgz",
+ "integrity": "sha512-qMCMfhY040cVHT43K9BFygqYbUPFZKHOg7K73mtTWJRb8pyP3fzf4Ixd5SzdEJQ6MRUg/WBnOLxghZtKKurENQ==",
+ "dev": true,
+ "dependencies": {
+ "ansi-styles": "^4.0.0",
+ "astral-regex": "^2.0.0",
+ "is-fullwidth-code-point": "^3.0.0"
+ },
+ "engines": {
+ "node": ">=10"
+ },
+ "funding": {
+ "url": "https://github.com/chalk/slice-ansi?sponsor=1"
+ }
+ },
+ "node_modules/log-update/node_modules/wrap-ansi": {
+ "version": "6.2.0",
+ "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-6.2.0.tgz",
+ "integrity": "sha512-r6lPcBGxZXlIcymEu7InxDMhdW0KDxpLgoFLcguasxCaJ/SOIZwINatK9KY/tf+ZrlywOKU0UDj3ATXUBfxJXA==",
+ "dev": true,
+ "dependencies": {
+ "ansi-styles": "^4.0.0",
+ "string-width": "^4.1.0",
+ "strip-ansi": "^6.0.0"
+ },
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/longest-streak": {
+ "version": "2.0.4",
+ "resolved": "https://registry.npmjs.org/longest-streak/-/longest-streak-2.0.4.tgz",
+ "integrity": "sha512-vM6rUVCVUJJt33bnmHiZEvr7wPT78ztX7rojL+LW51bHtLh6HTjx84LA5W4+oa6aKEJA7jJu5LR6vQRBpA5DVg==",
+ "dev": true,
+ "funding": {
+ "type": "github",
+ "url": "https://github.com/sponsors/wooorm"
+ }
+ },
+ "node_modules/loose-envify": {
+ "version": "1.4.0",
+ "resolved": "https://registry.npmjs.org/loose-envify/-/loose-envify-1.4.0.tgz",
+ "integrity": "sha512-lyuxPGr/Wfhrlem2CL/UcnUc1zcqKAImBDzukY7Y5F/yQiNdko6+fRLevlw1HgMySw7f611UIY408EtxRSoK3Q==",
+ "dev": true,
+ "dependencies": {
+ "js-tokens": "^3.0.0 || ^4.0.0"
+ },
+ "bin": {
+ "loose-envify": "cli.js"
+ }
+ },
+ "node_modules/lru-cache": {
+ "version": "6.0.0",
+ "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz",
+ "integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==",
+ "dev": true,
+ "dependencies": {
+ "yallist": "^4.0.0"
+ },
+ "engines": {
+ "node": ">=10"
+ }
+ },
+ "node_modules/make-dir": {
+ "version": "3.1.0",
+ "resolved": "https://registry.npmjs.org/make-dir/-/make-dir-3.1.0.tgz",
+ "integrity": "sha512-g3FeP20LNwhALb/6Cz6Dd4F2ngze0jz7tbzrD2wAV+o9FeNHe4rL+yK2md0J/fiSf1sa1ADhXqi5+oVwOM/eGw==",
+ "dev": true,
+ "peer": true,
+ "dependencies": {
+ "semver": "^6.0.0"
+ },
+ "engines": {
+ "node": ">=8"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
+ "node_modules/make-dir/node_modules/semver": {
+ "version": "6.3.0",
+ "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz",
+ "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==",
+ "dev": true,
+ "peer": true,
+ "bin": {
+ "semver": "bin/semver.js"
+ }
+ },
+ "node_modules/make-error": {
+ "version": "1.3.6",
+ "resolved": "https://registry.npmjs.org/make-error/-/make-error-1.3.6.tgz",
+ "integrity": "sha512-s8UhlNe7vPKomQhC1qFelMokr/Sc3AgNbso3n74mVPA5LTZwkB9NlXf4XPamLxJE8h0gh73rM94xvwRT2CVInw==",
+ "dev": true
+ },
+ "node_modules/makeerror": {
+ "version": "1.0.12",
+ "resolved": "https://registry.npmjs.org/makeerror/-/makeerror-1.0.12.tgz",
+ "integrity": "sha512-JmqCvUhmt43madlpFzG4BQzG2Z3m6tvQDNKdClZnO3VbIudJYmxsT0FNJMeiB2+JTSlTQTSbU8QdesVmwJcmLg==",
+ "dev": true,
+ "peer": true,
+ "dependencies": {
+ "tmpl": "1.0.5"
+ }
+ },
+ "node_modules/map-cache": {
+ "version": "0.2.2",
+ "resolved": "https://registry.npmjs.org/map-cache/-/map-cache-0.2.2.tgz",
+ "integrity": "sha1-wyq9C9ZSXZsFFkW7TyasXcmKDb8=",
+ "dev": true,
+ "peer": true,
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
+ "node_modules/map-obj": {
+ "version": "4.3.0",
+ "resolved": "https://registry.npmjs.org/map-obj/-/map-obj-4.3.0.tgz",
+ "integrity": "sha512-hdN1wVrZbb29eBGiGjJbeP8JbKjq1urkHJ/LIP/NY48MZ1QVXUsQBV1G1zvYFHn1XE06cwjBsOI2K3Ulnj1YXQ==",
+ "dev": true,
+ "engines": {
+ "node": ">=8"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
+ "node_modules/map-visit": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/map-visit/-/map-visit-1.0.0.tgz",
+ "integrity": "sha1-7Nyo8TFE5mDxtb1B8S80edmN+48=",
+ "dev": true,
+ "peer": true,
+ "dependencies": {
+ "object-visit": "^1.0.0"
+ },
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
+ "node_modules/markdown-escapes": {
+ "version": "1.0.4",
+ "resolved": "https://registry.npmjs.org/markdown-escapes/-/markdown-escapes-1.0.4.tgz",
+ "integrity": "sha512-8z4efJYk43E0upd0NbVXwgSTQs6cT3T06etieCMEg7dRbzCbxUCK/GHlX8mhHRDcp+OLlHkPKsvqQTCvsRl2cg==",
+ "dev": true,
+ "funding": {
+ "type": "github",
+ "url": "https://github.com/sponsors/wooorm"
+ }
+ },
+ "node_modules/markdown-table": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/markdown-table/-/markdown-table-2.0.0.tgz",
+ "integrity": "sha512-Ezda85ToJUBhM6WGaG6veasyym+Tbs3cMAw/ZhOPqXiYsr0jgocBV3j3nx+4lk47plLlIqjwuTm/ywVI+zjJ/A==",
+ "dev": true,
+ "dependencies": {
+ "repeat-string": "^1.0.0"
+ },
+ "funding": {
+ "type": "github",
+ "url": "https://github.com/sponsors/wooorm"
+ }
+ },
+ "node_modules/mathml-tag-names": {
+ "version": "2.1.3",
+ "resolved": "https://registry.npmjs.org/mathml-tag-names/-/mathml-tag-names-2.1.3.tgz",
+ "integrity": "sha512-APMBEanjybaPzUrfqU0IMU5I0AswKMH7k8OTLs0vvV4KZpExkTkY87nR/zpbuTPj+gARop7aGUbl11pnDfW6xg==",
+ "dev": true,
+ "funding": {
+ "type": "github",
+ "url": "https://github.com/sponsors/wooorm"
+ }
+ },
+ "node_modules/mdast-util-compact": {
+ "version": "2.0.1",
+ "resolved": "https://registry.npmjs.org/mdast-util-compact/-/mdast-util-compact-2.0.1.tgz",
+ "integrity": "sha512-7GlnT24gEwDrdAwEHrU4Vv5lLWrEer4KOkAiKT9nYstsTad7Oc1TwqT2zIMKRdZF7cTuaf+GA1E4Kv7jJh8mPA==",
+ "dev": true,
+ "dependencies": {
+ "unist-util-visit": "^2.0.0"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/unified"
+ }
+ },
+ "node_modules/mdast-util-compact/node_modules/unist-util-visit": {
+ "version": "2.0.3",
+ "resolved": "https://registry.npmjs.org/unist-util-visit/-/unist-util-visit-2.0.3.tgz",
+ "integrity": "sha512-iJ4/RczbJMkD0712mGktuGpm/U4By4FfDonL7N/9tATGIF4imikjOuagyMY53tnZq3NP6BcmlrHhEKAfGWjh7Q==",
+ "dev": true,
+ "dependencies": {
+ "@types/unist": "^2.0.0",
+ "unist-util-is": "^4.0.0",
+ "unist-util-visit-parents": "^3.0.0"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/unified"
+ }
+ },
+ "node_modules/mdast-util-compact/node_modules/unist-util-visit-parents": {
+ "version": "3.1.1",
+ "resolved": "https://registry.npmjs.org/unist-util-visit-parents/-/unist-util-visit-parents-3.1.1.tgz",
+ "integrity": "sha512-1KROIZWo6bcMrZEwiH2UrXDyalAa0uqzWCxCJj6lPOvTve2WkfgCytoDTPaMnodXh1WrXOq0haVYHj99ynJlsg==",
+ "dev": true,
+ "dependencies": {
+ "@types/unist": "^2.0.0",
+ "unist-util-is": "^4.0.0"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/unified"
+ }
+ },
+ "node_modules/mdast-util-from-markdown": {
+ "version": "0.8.5",
+ "resolved": "https://registry.npmjs.org/mdast-util-from-markdown/-/mdast-util-from-markdown-0.8.5.tgz",
+ "integrity": "sha512-2hkTXtYYnr+NubD/g6KGBS/0mFmBcifAsI0yIWRiRo0PjVs6SSOSOdtzbp6kSGnShDN6G5aWZpKQ2lWRy27mWQ==",
+ "dev": true,
+ "dependencies": {
+ "@types/mdast": "^3.0.0",
+ "mdast-util-to-string": "^2.0.0",
+ "micromark": "~2.11.0",
+ "parse-entities": "^2.0.0",
+ "unist-util-stringify-position": "^2.0.0"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/unified"
+ }
+ },
+ "node_modules/mdast-util-to-markdown": {
+ "version": "0.6.5",
+ "resolved": "https://registry.npmjs.org/mdast-util-to-markdown/-/mdast-util-to-markdown-0.6.5.tgz",
+ "integrity": "sha512-XeV9sDE7ZlOQvs45C9UKMtfTcctcaj/pGwH8YLbMHoMOXNNCn2LsqVQOqrF1+/NU8lKDAqozme9SCXWyo9oAcQ==",
+ "dev": true,
+ "dependencies": {
+ "@types/unist": "^2.0.0",
+ "longest-streak": "^2.0.0",
+ "mdast-util-to-string": "^2.0.0",
+ "parse-entities": "^2.0.0",
+ "repeat-string": "^1.0.0",
+ "zwitch": "^1.0.0"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/unified"
+ }
+ },
+ "node_modules/mdast-util-to-string": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/mdast-util-to-string/-/mdast-util-to-string-2.0.0.tgz",
+ "integrity": "sha512-AW4DRS3QbBayY/jJmD8437V1Gombjf8RSOUCMFBuo5iHi58AGEgVCKQ+ezHkZZDpAQS75hcBMpLqjpJTjtUL7w==",
+ "dev": true,
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/unified"
+ }
+ },
+ "node_modules/meow": {
+ "version": "8.1.2",
+ "resolved": "https://registry.npmjs.org/meow/-/meow-8.1.2.tgz",
+ "integrity": "sha512-r85E3NdZ+mpYk1C6RjPFEMSE+s1iZMuHtsHAqY0DT3jZczl0diWUZ8g6oU7h0M9cD2EL+PzaYghhCLzR0ZNn5Q==",
+ "dev": true,
+ "dependencies": {
+ "@types/minimist": "^1.2.0",
+ "camelcase-keys": "^6.2.2",
+ "decamelize-keys": "^1.1.0",
+ "hard-rejection": "^2.1.0",
+ "minimist-options": "4.1.0",
+ "normalize-package-data": "^3.0.0",
+ "read-pkg-up": "^7.0.1",
+ "redent": "^3.0.0",
+ "trim-newlines": "^3.0.0",
+ "type-fest": "^0.18.0",
+ "yargs-parser": "^20.2.3"
+ },
+ "engines": {
+ "node": ">=10"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
+ "node_modules/meow/node_modules/hosted-git-info": {
+ "version": "4.1.0",
+ "resolved": "https://registry.npmjs.org/hosted-git-info/-/hosted-git-info-4.1.0.tgz",
+ "integrity": "sha512-kyCuEOWjJqZuDbRHzL8V93NzQhwIB71oFWSyzVo+KPZI+pnQPPxucdkrOZvkLRnrf5URsQM+IJ09Dw29cRALIA==",
+ "dev": true,
+ "dependencies": {
+ "lru-cache": "^6.0.0"
+ },
+ "engines": {
+ "node": ">=10"
+ }
+ },
+ "node_modules/meow/node_modules/normalize-package-data": {
+ "version": "3.0.3",
+ "resolved": "https://registry.npmjs.org/normalize-package-data/-/normalize-package-data-3.0.3.tgz",
+ "integrity": "sha512-p2W1sgqij3zMMyRC067Dg16bfzVH+w7hyegmpIvZ4JNjqtGOVAIvLmjBx3yP7YTe9vKJgkoNOPjwQGogDoMXFA==",
+ "dev": true,
+ "dependencies": {
+ "hosted-git-info": "^4.0.1",
+ "is-core-module": "^2.5.0",
+ "semver": "^7.3.4",
+ "validate-npm-package-license": "^3.0.1"
+ },
+ "engines": {
+ "node": ">=10"
+ }
+ },
+ "node_modules/meow/node_modules/type-fest": {
+ "version": "0.18.1",
+ "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.18.1.tgz",
+ "integrity": "sha512-OIAYXk8+ISY+qTOwkHtKqzAuxchoMiD9Udx+FSGQDuiRR+PJKJHc2NJAXlbhkGwTt/4/nKZxELY1w3ReWOL8mw==",
+ "dev": true,
+ "engines": {
+ "node": ">=10"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
+ "node_modules/merge-stream": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/merge-stream/-/merge-stream-2.0.0.tgz",
+ "integrity": "sha512-abv/qOcuPfk3URPfDzmZU1LKmuw8kT+0nIHvKrKgFrwifol/doWcdA4ZqsWQ8ENrFKkd67Mfpo/LovbIUsbt3w==",
+ "dev": true
+ },
+ "node_modules/merge2": {
+ "version": "1.4.1",
+ "resolved": "https://registry.npmjs.org/merge2/-/merge2-1.4.1.tgz",
+ "integrity": "sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg==",
+ "dev": true,
+ "engines": {
+ "node": ">= 8"
+ }
+ },
+ "node_modules/micromark": {
+ "version": "2.11.4",
+ "resolved": "https://registry.npmjs.org/micromark/-/micromark-2.11.4.tgz",
+ "integrity": "sha512-+WoovN/ppKolQOFIAajxi7Lu9kInbPxFuTBVEavFcL8eAfVstoc5MocPmqBeAdBOJV00uaVjegzH4+MA0DN/uA==",
+ "dev": true,
+ "funding": [
+ {
+ "type": "GitHub Sponsors",
+ "url": "https://github.com/sponsors/unifiedjs"
+ },
+ {
+ "type": "OpenCollective",
+ "url": "https://opencollective.com/unified"
+ }
+ ],
+ "dependencies": {
+ "debug": "^4.0.0",
+ "parse-entities": "^2.0.0"
+ }
+ },
+ "node_modules/micromatch": {
+ "version": "4.0.5",
+ "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-4.0.5.tgz",
+ "integrity": "sha512-DMy+ERcEW2q8Z2Po+WNXuw3c5YaUSFjAO5GsJqfEl7UjvtIuFKO6ZrKvcItdy98dwFI2N1tg3zNIdKaQT+aNdA==",
+ "dev": true,
+ "dependencies": {
+ "braces": "^3.0.2",
+ "picomatch": "^2.3.1"
+ },
+ "engines": {
+ "node": ">=8.6"
+ }
+ },
+ "node_modules/mime-db": {
+ "version": "1.52.0",
+ "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.52.0.tgz",
+ "integrity": "sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg==",
+ "dev": true,
+ "engines": {
+ "node": ">= 0.6"
+ }
+ },
+ "node_modules/mime-types": {
+ "version": "2.1.35",
+ "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.35.tgz",
+ "integrity": "sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw==",
+ "dev": true,
+ "dependencies": {
+ "mime-db": "1.52.0"
+ },
+ "engines": {
+ "node": ">= 0.6"
+ }
+ },
+ "node_modules/mimic-fn": {
+ "version": "2.1.0",
+ "resolved": "https://registry.npmjs.org/mimic-fn/-/mimic-fn-2.1.0.tgz",
+ "integrity": "sha512-OqbOk5oEQeAZ8WXWydlu9HJjz9WVdEIvamMCcXmuqUYjTknH/sqsWvhQ3vgwKFRR1HpjvNBKQ37nbJgYzGqGcg==",
+ "dev": true,
+ "engines": {
+ "node": ">=6"
+ }
+ },
+ "node_modules/min-indent": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/min-indent/-/min-indent-1.0.1.tgz",
+ "integrity": "sha512-I9jwMn07Sy/IwOj3zVkVik2JTvgpaykDZEigL6Rx6N9LbMywwUSMtxET+7lVoDLLd3O3IXwJwvuuns8UB/HeAg==",
+ "dev": true,
+ "engines": {
+ "node": ">=4"
+ }
+ },
+ "node_modules/minimatch": {
+ "version": "3.1.2",
+ "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz",
+ "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==",
+ "dev": true,
+ "dependencies": {
+ "brace-expansion": "^1.1.7"
+ },
+ "engines": {
+ "node": "*"
+ }
+ },
+ "node_modules/minimist": {
+ "version": "1.2.6",
+ "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.6.tgz",
+ "integrity": "sha512-Jsjnk4bw3YJqYzbdyBiNsPWHPfO++UGG749Cxs6peCu5Xg4nrena6OVxOYxrQTqww0Jmwt+Ref8rggumkTLz9Q==",
+ "dev": true
+ },
+ "node_modules/minimist-options": {
+ "version": "4.1.0",
+ "resolved": "https://registry.npmjs.org/minimist-options/-/minimist-options-4.1.0.tgz",
+ "integrity": "sha512-Q4r8ghd80yhO/0j1O3B2BjweX3fiHg9cdOwjJd2J76Q135c+NDxGCqdYKQ1SKBuFfgWbAUzBfvYjPUEeNgqN1A==",
+ "dev": true,
+ "dependencies": {
+ "arrify": "^1.0.1",
+ "is-plain-obj": "^1.1.0",
+ "kind-of": "^6.0.3"
+ },
+ "engines": {
+ "node": ">= 6"
+ }
+ },
+ "node_modules/mixin-deep": {
+ "version": "1.3.2",
+ "resolved": "https://registry.npmjs.org/mixin-deep/-/mixin-deep-1.3.2.tgz",
+ "integrity": "sha512-WRoDn//mXBiJ1H40rqa3vH0toePwSsGb45iInWlTySa+Uu4k3tYUSxa2v1KqAiLtvlrSzaExqS1gtk96A9zvEA==",
+ "dev": true,
+ "peer": true,
+ "dependencies": {
+ "for-in": "^1.0.2",
+ "is-extendable": "^1.0.1"
+ },
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
+ "node_modules/mkdirp": {
+ "version": "1.0.4",
+ "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-1.0.4.tgz",
+ "integrity": "sha512-vVqVZQyf3WLx2Shd0qJ9xuvqgAyKPLAiqITEtqW0oIUjzo3PePDd6fW9iFz30ef7Ysp/oiWqbhszeGWW2T6Gzw==",
+ "dev": true,
+ "bin": {
+ "mkdirp": "bin/cmd.js"
+ },
+ "engines": {
+ "node": ">=10"
+ }
+ },
+ "node_modules/ms": {
+ "version": "2.1.2",
+ "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz",
+ "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==",
+ "dev": true
+ },
+ "node_modules/mute-stream": {
+ "version": "0.0.8",
+ "resolved": "https://registry.npmjs.org/mute-stream/-/mute-stream-0.0.8.tgz",
+ "integrity": "sha512-nnbWWOkoWyUsTjKrhgD0dcz22mdkSnpYqbEjIm2nhwhuxlSkpywJmBo8h0ZqJdkp73mb90SssHkN4rsRaBAfAA==",
+ "dev": true
+ },
+ "node_modules/nanoid": {
+ "version": "3.3.4",
+ "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.4.tgz",
+ "integrity": "sha512-MqBkQh/OHTS2egovRtLk45wEyNXwF+cokD+1YPf9u5VfJiRdAiRwB2froX5Co9Rh20xs4siNPm8naNotSD6RBw==",
+ "dev": true,
+ "bin": {
+ "nanoid": "bin/nanoid.cjs"
+ },
+ "engines": {
+ "node": "^10 || ^12 || ^13.7 || ^14 || >=15.0.1"
+ }
+ },
+ "node_modules/nanomatch": {
+ "version": "1.2.13",
+ "resolved": "https://registry.npmjs.org/nanomatch/-/nanomatch-1.2.13.tgz",
+ "integrity": "sha512-fpoe2T0RbHwBTBUOftAfBPaDEi06ufaUai0mE6Yn1kacc3SnTErfb/h+X94VXzI64rKFHYImXSvdwGGCmwOqCA==",
+ "dev": true,
+ "peer": true,
+ "dependencies": {
+ "arr-diff": "^4.0.0",
+ "array-unique": "^0.3.2",
+ "define-property": "^2.0.2",
+ "extend-shallow": "^3.0.2",
+ "fragment-cache": "^0.2.1",
+ "is-windows": "^1.0.2",
+ "kind-of": "^6.0.2",
+ "object.pick": "^1.3.0",
+ "regex-not": "^1.0.0",
+ "snapdragon": "^0.8.1",
+ "to-regex": "^3.0.1"
+ },
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
+ "node_modules/natural-compare": {
+ "version": "1.4.0",
+ "resolved": "https://registry.npmjs.org/natural-compare/-/natural-compare-1.4.0.tgz",
+ "integrity": "sha1-Sr6/7tdUHywnrPspvbvRXI1bpPc=",
+ "dev": true
+ },
+ "node_modules/natural-compare-lite": {
+ "version": "1.4.0",
+ "resolved": "https://registry.npmjs.org/natural-compare-lite/-/natural-compare-lite-1.4.0.tgz",
+ "integrity": "sha512-Tj+HTDSJJKaZnfiuw+iaF9skdPpTo2GtEly5JHnWV/hfv2Qj/9RKsGISQtLh2ox3l5EAGw487hnBee0sIJ6v2g==",
+ "dev": true
+ },
+ "node_modules/next": {
+ "version": "12.3.1",
+ "resolved": "https://registry.npmjs.org/next/-/next-12.3.1.tgz",
+ "integrity": "sha512-l7bvmSeIwX5lp07WtIiP9u2ytZMv7jIeB8iacR28PuUEFG5j0HGAPnMqyG5kbZNBG2H7tRsrQ4HCjuMOPnANZw==",
+ "dev": true,
+ "dependencies": {
+ "@next/env": "12.3.1",
+ "@swc/helpers": "0.4.11",
+ "caniuse-lite": "^1.0.30001406",
+ "postcss": "8.4.14",
+ "styled-jsx": "5.0.7",
+ "use-sync-external-store": "1.2.0"
+ },
+ "bin": {
+ "next": "dist/bin/next"
+ },
+ "engines": {
+ "node": ">=12.22.0"
+ },
+ "optionalDependencies": {
+ "@next/swc-android-arm-eabi": "12.3.1",
+ "@next/swc-android-arm64": "12.3.1",
+ "@next/swc-darwin-arm64": "12.3.1",
+ "@next/swc-darwin-x64": "12.3.1",
+ "@next/swc-freebsd-x64": "12.3.1",
+ "@next/swc-linux-arm-gnueabihf": "12.3.1",
+ "@next/swc-linux-arm64-gnu": "12.3.1",
+ "@next/swc-linux-arm64-musl": "12.3.1",
+ "@next/swc-linux-x64-gnu": "12.3.1",
+ "@next/swc-linux-x64-musl": "12.3.1",
+ "@next/swc-win32-arm64-msvc": "12.3.1",
+ "@next/swc-win32-ia32-msvc": "12.3.1",
+ "@next/swc-win32-x64-msvc": "12.3.1"
+ },
+ "peerDependencies": {
+ "fibers": ">= 3.1.0",
+ "node-sass": "^6.0.0 || ^7.0.0",
+ "react": "^17.0.2 || ^18.0.0-0",
+ "react-dom": "^17.0.2 || ^18.0.0-0",
+ "sass": "^1.3.0"
+ },
+ "peerDependenciesMeta": {
+ "fibers": {
+ "optional": true
+ },
+ "node-sass": {
+ "optional": true
+ },
+ "sass": {
+ "optional": true
+ }
+ }
+ },
+ "node_modules/nice-try": {
+ "version": "1.0.5",
+ "resolved": "https://registry.npmjs.org/nice-try/-/nice-try-1.0.5.tgz",
+ "integrity": "sha512-1nh45deeb5olNY7eX82BkPO7SSxR5SSYJiPTrTdFUVYwAl8CKMA5N9PjTYkHiRjisVcxcQ1HXdLhx2qxxJzLNQ==",
+ "dev": true,
+ "peer": true
+ },
+ "node_modules/node-fetch": {
+ "version": "2.6.7",
+ "resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-2.6.7.tgz",
+ "integrity": "sha512-ZjMPFEfVx5j+y2yF35Kzx5sF7kDzxuDj6ziH4FFbOp87zKDZNx8yExJIb05OGF4Nlt9IHFIMBkRl41VdvcNdbQ==",
+ "dev": true,
+ "dependencies": {
+ "whatwg-url": "^5.0.0"
+ },
+ "engines": {
+ "node": "4.x || >=6.0.0"
+ },
+ "peerDependencies": {
+ "encoding": "^0.1.0"
+ },
+ "peerDependenciesMeta": {
+ "encoding": {
+ "optional": true
+ }
+ }
+ },
+ "node_modules/node-fetch/node_modules/tr46": {
+ "version": "0.0.3",
+ "resolved": "https://registry.npmjs.org/tr46/-/tr46-0.0.3.tgz",
+ "integrity": "sha1-gYT9NH2snNwYWZLzpmIuFLnZq2o=",
+ "dev": true
+ },
+ "node_modules/node-fetch/node_modules/webidl-conversions": {
+ "version": "3.0.1",
+ "resolved": "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-3.0.1.tgz",
+ "integrity": "sha1-JFNCdeKnvGvnvIZhHMFq4KVlSHE=",
+ "dev": true
+ },
+ "node_modules/node-fetch/node_modules/whatwg-url": {
+ "version": "5.0.0",
+ "resolved": "https://registry.npmjs.org/whatwg-url/-/whatwg-url-5.0.0.tgz",
+ "integrity": "sha1-lmRU6HZUYuN2RNNib2dCzotwll0=",
+ "dev": true,
+ "dependencies": {
+ "tr46": "~0.0.3",
+ "webidl-conversions": "^3.0.0"
+ }
+ },
+ "node_modules/node-int64": {
+ "version": "0.4.0",
+ "resolved": "https://registry.npmjs.org/node-int64/-/node-int64-0.4.0.tgz",
+ "integrity": "sha1-h6kGXNs1XTGC2PlM4RGIuCXGijs=",
+ "dev": true,
+ "peer": true
+ },
+ "node_modules/node-notifier": {
+ "version": "8.0.2",
+ "resolved": "https://registry.npmjs.org/node-notifier/-/node-notifier-8.0.2.tgz",
+ "integrity": "sha512-oJP/9NAdd9+x2Q+rfphB2RJCHjod70RcRLjosiPMMu5gjIfwVnOUGq2nbTjTUbmy0DJ/tFIVT30+Qe3nzl4TJg==",
+ "dev": true,
+ "optional": true,
+ "peer": true,
+ "dependencies": {
+ "growly": "^1.3.0",
+ "is-wsl": "^2.2.0",
+ "semver": "^7.3.2",
+ "shellwords": "^0.1.1",
+ "uuid": "^8.3.0",
+ "which": "^2.0.2"
+ }
+ },
+ "node_modules/node-releases": {
+ "version": "2.0.3",
+ "resolved": "https://registry.npmjs.org/node-releases/-/node-releases-2.0.3.tgz",
+ "integrity": "sha512-maHFz6OLqYxz+VQyCAtA3PTX4UP/53pa05fyDNc9CwjvJ0yEh6+xBwKsgCxMNhS8taUKBFYxfuiaD9U/55iFaw==",
+ "dev": true
+ },
+ "node_modules/normalize-package-data": {
+ "version": "2.5.0",
+ "resolved": "https://registry.npmjs.org/normalize-package-data/-/normalize-package-data-2.5.0.tgz",
+ "integrity": "sha512-/5CMN3T0R4XTj4DcGaexo+roZSdSFW/0AOOTROrjxzCG1wrWXEsGbRKevjlIL+ZDE4sZlJr5ED4YW0yqmkK+eA==",
+ "dev": true,
+ "dependencies": {
+ "hosted-git-info": "^2.1.4",
+ "resolve": "^1.10.0",
+ "semver": "2 || 3 || 4 || 5",
+ "validate-npm-package-license": "^3.0.1"
+ }
+ },
+ "node_modules/normalize-package-data/node_modules/semver": {
+ "version": "5.7.1",
+ "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz",
+ "integrity": "sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==",
+ "dev": true,
+ "bin": {
+ "semver": "bin/semver"
+ }
+ },
+ "node_modules/normalize-path": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-3.0.0.tgz",
+ "integrity": "sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==",
+ "dev": true,
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
+ "node_modules/normalize-range": {
+ "version": "0.1.2",
+ "resolved": "https://registry.npmjs.org/normalize-range/-/normalize-range-0.1.2.tgz",
+ "integrity": "sha1-LRDAa9/TEuqXd2laTShDlFa3WUI=",
+ "dev": true,
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
+ "node_modules/normalize-selector": {
+ "version": "0.2.0",
+ "resolved": "https://registry.npmjs.org/normalize-selector/-/normalize-selector-0.2.0.tgz",
+ "integrity": "sha1-0LFF62kRicY6eNIB3E/bEpPvDAM=",
+ "dev": true
+ },
+ "node_modules/npm-run-path": {
+ "version": "4.0.1",
+ "resolved": "https://registry.npmjs.org/npm-run-path/-/npm-run-path-4.0.1.tgz",
+ "integrity": "sha512-S48WzZW777zhNIrn7gxOlISNAqi9ZC/uQFnRdbeIHhZhCA6UqpkOT8T1G7BvfdgP4Er8gF4sUbaS0i7QvIfCWw==",
+ "dev": true,
+ "dependencies": {
+ "path-key": "^3.0.0"
+ },
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/num2fraction": {
+ "version": "1.2.2",
+ "resolved": "https://registry.npmjs.org/num2fraction/-/num2fraction-1.2.2.tgz",
+ "integrity": "sha1-b2gragJ6Tp3fpFZM0lidHU5mnt4=",
+ "dev": true
+ },
+ "node_modules/nwsapi": {
+ "version": "2.2.0",
+ "resolved": "https://registry.npmjs.org/nwsapi/-/nwsapi-2.2.0.tgz",
+ "integrity": "sha512-h2AatdwYH+JHiZpv7pt/gSX1XoRGb7L/qSIeuqA6GwYoF9w1vP1cw42TO0aI2pNyshRK5893hNSl+1//vHK7hQ==",
+ "dev": true,
+ "peer": true
+ },
+ "node_modules/object-assign": {
+ "version": "4.1.1",
+ "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz",
+ "integrity": "sha512-rJgTQnkUnH1sFw8yT6VSU3zD3sWmu6sZhIseY8VX+GRu3P6F7Fu+JNDoXfklElbLJSnc3FUQHVe4cU5hj+BcUg==",
+ "dev": true,
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
+ "node_modules/object-copy": {
+ "version": "0.1.0",
+ "resolved": "https://registry.npmjs.org/object-copy/-/object-copy-0.1.0.tgz",
+ "integrity": "sha1-fn2Fi3gb18mRpBupde04EnVOmYw=",
+ "dev": true,
+ "peer": true,
+ "dependencies": {
+ "copy-descriptor": "^0.1.0",
+ "define-property": "^0.2.5",
+ "kind-of": "^3.0.3"
+ },
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
+ "node_modules/object-copy/node_modules/define-property": {
+ "version": "0.2.5",
+ "resolved": "https://registry.npmjs.org/define-property/-/define-property-0.2.5.tgz",
+ "integrity": "sha1-w1se+RjsPJkPmlvFe+BKrOxcgRY=",
+ "dev": true,
+ "peer": true,
+ "dependencies": {
+ "is-descriptor": "^0.1.0"
+ },
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
+ "node_modules/object-copy/node_modules/is-accessor-descriptor": {
+ "version": "0.1.6",
+ "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-0.1.6.tgz",
+ "integrity": "sha1-qeEss66Nh2cn7u84Q/igiXtcmNY=",
+ "dev": true,
+ "peer": true,
+ "dependencies": {
+ "kind-of": "^3.0.2"
+ },
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
+ "node_modules/object-copy/node_modules/is-buffer": {
+ "version": "1.1.6",
+ "resolved": "https://registry.npmjs.org/is-buffer/-/is-buffer-1.1.6.tgz",
+ "integrity": "sha512-NcdALwpXkTm5Zvvbk7owOUSvVvBKDgKP5/ewfXEznmQFfs4ZRmanOeKBTjRVjka3QFoN6XJ+9F3USqfHqTaU5w==",
+ "dev": true,
+ "peer": true
+ },
+ "node_modules/object-copy/node_modules/is-data-descriptor": {
+ "version": "0.1.4",
+ "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-0.1.4.tgz",
+ "integrity": "sha1-C17mSDiOLIYCgueT8YVv7D8wG1Y=",
+ "dev": true,
+ "peer": true,
+ "dependencies": {
+ "kind-of": "^3.0.2"
+ },
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
+ "node_modules/object-copy/node_modules/is-descriptor": {
+ "version": "0.1.6",
+ "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-0.1.6.tgz",
+ "integrity": "sha512-avDYr0SB3DwO9zsMov0gKCESFYqCnE4hq/4z3TdUlukEy5t9C0YRq7HLrsN52NAcqXKaepeCD0n+B0arnVG3Hg==",
+ "dev": true,
+ "peer": true,
+ "dependencies": {
+ "is-accessor-descriptor": "^0.1.6",
+ "is-data-descriptor": "^0.1.4",
+ "kind-of": "^5.0.0"
+ },
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
+ "node_modules/object-copy/node_modules/is-descriptor/node_modules/kind-of": {
+ "version": "5.1.0",
+ "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-5.1.0.tgz",
+ "integrity": "sha512-NGEErnH6F2vUuXDh+OlbcKW7/wOcfdRHaZ7VWtqCztfHri/++YKmP51OdWeGPuqCOba6kk2OTe5d02VmTB80Pw==",
+ "dev": true,
+ "peer": true,
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
+ "node_modules/object-copy/node_modules/kind-of": {
+ "version": "3.2.2",
+ "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz",
+ "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=",
+ "dev": true,
+ "peer": true,
+ "dependencies": {
+ "is-buffer": "^1.1.5"
+ },
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
+ "node_modules/object-inspect": {
+ "version": "1.12.3",
+ "resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.12.3.tgz",
+ "integrity": "sha512-geUvdk7c+eizMNUDkRpW1wJwgfOiOeHbxBR/hLXK1aT6zmVSO0jsQcs7fj6MGw89jC/cjGfLcNOrtMYtGqm81g==",
+ "dev": true,
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/object-is": {
+ "version": "1.1.5",
+ "resolved": "https://registry.npmjs.org/object-is/-/object-is-1.1.5.tgz",
+ "integrity": "sha512-3cyDsyHgtmi7I7DfSSI2LDp6SK2lwvtbg0p0R1e0RvTqF5ceGx+K2dfSjm1bKDMVCFEDAQvy+o8c6a7VujOddw==",
+ "dev": true,
+ "dependencies": {
+ "call-bind": "^1.0.2",
+ "define-properties": "^1.1.3"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/object-keys": {
+ "version": "1.1.1",
+ "resolved": "https://registry.npmjs.org/object-keys/-/object-keys-1.1.1.tgz",
+ "integrity": "sha512-NuAESUOUMrlIXOfHKzD6bpPu3tYt3xvjNdRIQ+FeT0lNb4K8WR70CaDxhuNguS2XG+GjkyMwOzsN5ZktImfhLA==",
+ "dev": true,
+ "engines": {
+ "node": ">= 0.4"
+ }
+ },
+ "node_modules/object-visit": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/object-visit/-/object-visit-1.0.1.tgz",
+ "integrity": "sha1-95xEk68MU3e1n+OdOV5BBC3QRbs=",
+ "dev": true,
+ "peer": true,
+ "dependencies": {
+ "isobject": "^3.0.0"
+ },
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
+ "node_modules/object.assign": {
+ "version": "4.1.4",
+ "resolved": "https://registry.npmjs.org/object.assign/-/object.assign-4.1.4.tgz",
+ "integrity": "sha512-1mxKf0e58bvyjSCtKYY4sRe9itRk3PJpquJOjeIkz885CczcI4IvJJDLPS72oowuSh+pBxUFROpX+TU++hxhZQ==",
+ "dev": true,
+ "dependencies": {
+ "call-bind": "^1.0.2",
+ "define-properties": "^1.1.4",
+ "has-symbols": "^1.0.3",
+ "object-keys": "^1.1.1"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/object.entries": {
+ "version": "1.1.6",
+ "resolved": "https://registry.npmjs.org/object.entries/-/object.entries-1.1.6.tgz",
+ "integrity": "sha512-leTPzo4Zvg3pmbQ3rDK69Rl8GQvIqMWubrkxONG9/ojtFE2rD9fjMKfSI5BxW3osRH1m6VdzmqK8oAY9aT4x5w==",
+ "dev": true,
+ "dependencies": {
+ "call-bind": "^1.0.2",
+ "define-properties": "^1.1.4",
+ "es-abstract": "^1.20.4"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ }
+ },
+ "node_modules/object.fromentries": {
+ "version": "2.0.6",
+ "resolved": "https://registry.npmjs.org/object.fromentries/-/object.fromentries-2.0.6.tgz",
+ "integrity": "sha512-VciD13dswC4j1Xt5394WR4MzmAQmlgN72phd/riNp9vtD7tp4QQWJ0R4wvclXcafgcYK8veHRed2W6XeGBvcfg==",
+ "dev": true,
+ "dependencies": {
+ "call-bind": "^1.0.2",
+ "define-properties": "^1.1.4",
+ "es-abstract": "^1.20.4"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/object.hasown": {
+ "version": "1.1.2",
+ "resolved": "https://registry.npmjs.org/object.hasown/-/object.hasown-1.1.2.tgz",
+ "integrity": "sha512-B5UIT3J1W+WuWIU55h0mjlwaqxiE5vYENJXIXZ4VFe05pNYrkKuK0U/6aFcb0pKywYJh7IhfoqUfKVmrJJHZHw==",
+ "dev": true,
+ "dependencies": {
+ "define-properties": "^1.1.4",
+ "es-abstract": "^1.20.4"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/object.pick": {
+ "version": "1.3.0",
+ "resolved": "https://registry.npmjs.org/object.pick/-/object.pick-1.3.0.tgz",
+ "integrity": "sha1-h6EKxMFpS9Lhy/U1kaZhQftd10c=",
+ "dev": true,
+ "peer": true,
+ "dependencies": {
+ "isobject": "^3.0.1"
+ },
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
+ "node_modules/object.values": {
+ "version": "1.1.6",
+ "resolved": "https://registry.npmjs.org/object.values/-/object.values-1.1.6.tgz",
+ "integrity": "sha512-FVVTkD1vENCsAcwNs9k6jea2uHC/X0+JcjG8YA60FN5CMaJmG95wT9jek/xX9nornqGRrBkKtzuAu2wuHpKqvw==",
+ "dev": true,
+ "dependencies": {
+ "call-bind": "^1.0.2",
+ "define-properties": "^1.1.4",
+ "es-abstract": "^1.20.4"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/once": {
+ "version": "1.4.0",
+ "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz",
+ "integrity": "sha1-WDsap3WWHUsROsF9nFC6753Xa9E=",
+ "dev": true,
+ "dependencies": {
+ "wrappy": "1"
+ }
+ },
+ "node_modules/onetime": {
+ "version": "5.1.2",
+ "resolved": "https://registry.npmjs.org/onetime/-/onetime-5.1.2.tgz",
+ "integrity": "sha512-kbpaSSGJTWdAY5KPVeMOKXSrPtr8C8C7wodJbcsd51jRnmD+GZu8Y0VoU6Dm5Z4vWr0Ig/1NKuWRKf7j5aaYSg==",
+ "dev": true,
+ "dependencies": {
+ "mimic-fn": "^2.1.0"
+ },
+ "engines": {
+ "node": ">=6"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
+ "node_modules/open": {
+ "version": "7.3.0",
+ "resolved": "https://registry.npmjs.org/open/-/open-7.3.0.tgz",
+ "integrity": "sha512-mgLwQIx2F/ye9SmbrUkurZCnkoXyXyu9EbHtJZrICjVAJfyMArdHp3KkixGdZx1ZHFPNIwl0DDM1dFFqXbTLZw==",
+ "dev": true,
+ "dependencies": {
+ "is-docker": "^2.0.0",
+ "is-wsl": "^2.1.1"
+ },
+ "engines": {
+ "node": ">=8"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
+ "node_modules/opencollective-postinstall": {
+ "version": "2.0.3",
+ "resolved": "https://registry.npmjs.org/opencollective-postinstall/-/opencollective-postinstall-2.0.3.tgz",
+ "integrity": "sha512-8AV/sCtuzUeTo8gQK5qDZzARrulB3egtLzFgteqB2tcT4Mw7B8Kt7JcDHmltjz6FOAHsvTevk70gZEbhM4ZS9Q==",
+ "dev": true,
+ "bin": {
+ "opencollective-postinstall": "index.js"
+ }
+ },
+ "node_modules/optionator": {
+ "version": "0.9.1",
+ "resolved": "https://registry.npmjs.org/optionator/-/optionator-0.9.1.tgz",
+ "integrity": "sha512-74RlY5FCnhq4jRxVUPKDaRwrVNXMqsGsiW6AJw4XK8hmtm10wC0ypZBLw5IIp85NZMr91+qd1RvvENwg7jjRFw==",
+ "dev": true,
+ "dependencies": {
+ "deep-is": "^0.1.3",
+ "fast-levenshtein": "^2.0.6",
+ "levn": "^0.4.1",
+ "prelude-ls": "^1.2.1",
+ "type-check": "^0.4.0",
+ "word-wrap": "^1.2.3"
+ },
+ "engines": {
+ "node": ">= 0.8.0"
+ }
+ },
+ "node_modules/os-tmpdir": {
+ "version": "1.0.2",
+ "resolved": "https://registry.npmjs.org/os-tmpdir/-/os-tmpdir-1.0.2.tgz",
+ "integrity": "sha1-u+Z0BseaqFxc/sdm/lc0VV36EnQ=",
+ "dev": true,
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
+ "node_modules/p-each-series": {
+ "version": "2.2.0",
+ "resolved": "https://registry.npmjs.org/p-each-series/-/p-each-series-2.2.0.tgz",
+ "integrity": "sha512-ycIL2+1V32th+8scbpTvyHNaHe02z0sjgh91XXjAk+ZeXoPN4Z46DVUnzdso0aX4KckKw0FNNFHdjZ2UsZvxiA==",
+ "dev": true,
+ "peer": true,
+ "engines": {
+ "node": ">=8"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
+ "node_modules/p-finally": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/p-finally/-/p-finally-1.0.0.tgz",
+ "integrity": "sha1-P7z7FbiZpEEjs0ttzBi3JDNqLK4=",
+ "dev": true,
+ "peer": true,
+ "engines": {
+ "node": ">=4"
+ }
+ },
+ "node_modules/p-limit": {
+ "version": "3.1.0",
+ "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-3.1.0.tgz",
+ "integrity": "sha512-TYOanM3wGwNGsZN2cVTYPArw454xnXj5qmWF1bEoAc4+cU/ol7GVh7odevjp1FNHduHc3KZMcFduxU5Xc6uJRQ==",
+ "dev": true,
+ "dependencies": {
+ "yocto-queue": "^0.1.0"
+ },
+ "engines": {
+ "node": ">=10"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
+ "node_modules/p-locate": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-2.0.0.tgz",
+ "integrity": "sha1-IKAQOyIqcMj9OcwuWAaA893l7EM=",
+ "dev": true,
+ "dependencies": {
+ "p-limit": "^1.1.0"
+ },
+ "engines": {
+ "node": ">=4"
+ }
+ },
+ "node_modules/p-locate/node_modules/p-limit": {
+ "version": "1.3.0",
+ "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-1.3.0.tgz",
+ "integrity": "sha512-vvcXsLAJ9Dr5rQOPk7toZQZJApBl2K4J6dANSsEuh6QI41JYcsS/qhTGa9ErIUUgK3WNQoJYvylxvjqmiqEA9Q==",
+ "dev": true,
+ "dependencies": {
+ "p-try": "^1.0.0"
+ },
+ "engines": {
+ "node": ">=4"
+ }
+ },
+ "node_modules/p-locate/node_modules/p-try": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/p-try/-/p-try-1.0.0.tgz",
+ "integrity": "sha1-y8ec26+P1CKOE/Yh8rGiN8GyB7M=",
+ "dev": true,
+ "engines": {
+ "node": ">=4"
+ }
+ },
+ "node_modules/p-map": {
+ "version": "4.0.0",
+ "resolved": "https://registry.npmjs.org/p-map/-/p-map-4.0.0.tgz",
+ "integrity": "sha512-/bjOqmgETBYB5BoEeGVea8dmvHb2m9GLy1E9W43yeyfP6QQCZGFNa+XRceJEuDB6zqr+gKpIAmlLebMpykw/MQ==",
+ "dev": true,
+ "dependencies": {
+ "aggregate-error": "^3.0.0"
+ },
+ "engines": {
+ "node": ">=10"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
+ "node_modules/p-try": {
+ "version": "2.2.0",
+ "resolved": "https://registry.npmjs.org/p-try/-/p-try-2.2.0.tgz",
+ "integrity": "sha512-R4nPAVTAU0B9D35/Gk3uJf/7XYbQcyohSKdvAxIRSNghFl4e71hVoGnBNQz9cWaXxO2I10KTC+3jMdvvoKw6dQ==",
+ "dev": true,
+ "engines": {
+ "node": ">=6"
+ }
+ },
+ "node_modules/parent-module": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/parent-module/-/parent-module-1.0.1.tgz",
+ "integrity": "sha512-GQ2EWRpQV8/o+Aw8YqtfZZPfNRWZYkbidE9k5rpl/hC3vtHHBfGm2Ifi6qWV+coDGkrUKZAxE3Lot5kcsRlh+g==",
+ "dev": true,
+ "dependencies": {
+ "callsites": "^3.0.0"
+ },
+ "engines": {
+ "node": ">=6"
+ }
+ },
+ "node_modules/parse-entities": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/parse-entities/-/parse-entities-2.0.0.tgz",
+ "integrity": "sha512-kkywGpCcRYhqQIchaWqZ875wzpS/bMKhz5HnN3p7wveJTkTtyAB/AlnS0f8DFSqYW1T82t6yEAkEcB+A1I3MbQ==",
+ "dev": true,
+ "dependencies": {
+ "character-entities": "^1.0.0",
+ "character-entities-legacy": "^1.0.0",
+ "character-reference-invalid": "^1.0.0",
+ "is-alphanumerical": "^1.0.0",
+ "is-decimal": "^1.0.0",
+ "is-hexadecimal": "^1.0.0"
+ },
+ "funding": {
+ "type": "github",
+ "url": "https://github.com/sponsors/wooorm"
+ }
+ },
+ "node_modules/parse-json": {
+ "version": "5.2.0",
+ "resolved": "https://registry.npmjs.org/parse-json/-/parse-json-5.2.0.tgz",
+ "integrity": "sha512-ayCKvm/phCGxOkYRSCM82iDwct8/EonSEgCSxWxD7ve6jHggsFl4fZVQBPRNgQoKiuV/odhFrGzQXZwbifC8Rg==",
+ "dev": true,
+ "dependencies": {
+ "@babel/code-frame": "^7.0.0",
+ "error-ex": "^1.3.1",
+ "json-parse-even-better-errors": "^2.3.0",
+ "lines-and-columns": "^1.1.6"
+ },
+ "engines": {
+ "node": ">=8"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
+ "node_modules/parse5": {
+ "version": "6.0.1",
+ "resolved": "https://registry.npmjs.org/parse5/-/parse5-6.0.1.tgz",
+ "integrity": "sha512-Ofn/CTFzRGTTxwpNEs9PP93gXShHcTq255nzRYSKe8AkVpZY7e1fpmTfOyoIvjP5HG7Z2ZM7VS9PPhQGW2pOpw==",
+ "dev": true,
+ "peer": true
+ },
+ "node_modules/pascalcase": {
+ "version": "0.1.1",
+ "resolved": "https://registry.npmjs.org/pascalcase/-/pascalcase-0.1.1.tgz",
+ "integrity": "sha1-s2PlXoAGym/iF4TS2yK9FdeRfxQ=",
+ "dev": true,
+ "peer": true,
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
+ "node_modules/path-exists": {
+ "version": "4.0.0",
+ "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-4.0.0.tgz",
+ "integrity": "sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==",
+ "dev": true,
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/path-is-absolute": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz",
+ "integrity": "sha1-F0uSaHNVNP+8es5r9TpanhtcX18=",
+ "dev": true,
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
+ "node_modules/path-key": {
+ "version": "3.1.1",
+ "resolved": "https://registry.npmjs.org/path-key/-/path-key-3.1.1.tgz",
+ "integrity": "sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==",
+ "dev": true,
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/path-parse": {
+ "version": "1.0.7",
+ "resolved": "https://registry.npmjs.org/path-parse/-/path-parse-1.0.7.tgz",
+ "integrity": "sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw==",
+ "dev": true
+ },
+ "node_modules/path-type": {
+ "version": "4.0.0",
+ "resolved": "https://registry.npmjs.org/path-type/-/path-type-4.0.0.tgz",
+ "integrity": "sha512-gDKb8aZMDeD/tZWs9P6+q0J9Mwkdl6xMV8TjnGP3qJVJ06bdMgkbBlLU8IdfOsIsFz2BW1rNVT3XuNEl8zPAvw==",
+ "dev": true,
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/picocolors": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.0.0.tgz",
+ "integrity": "sha512-1fygroTLlHu66zi26VoTDv8yRgm0Fccecssto+MhsZ0D/DGW2sm8E8AjW7NU5VVTRt5GxbeZ5qBuJr+HyLYkjQ==",
+ "dev": true
+ },
+ "node_modules/picomatch": {
+ "version": "2.3.1",
+ "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.1.tgz",
+ "integrity": "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==",
+ "dev": true,
+ "engines": {
+ "node": ">=8.6"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/jonschlinkert"
+ }
+ },
+ "node_modules/pify": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/pify/-/pify-3.0.0.tgz",
+ "integrity": "sha1-5aSs0sEB/fPZpNB/DbxNtJ3SgXY=",
+ "dev": true,
+ "engines": {
+ "node": ">=4"
+ }
+ },
+ "node_modules/pirates": {
+ "version": "4.0.5",
+ "resolved": "https://registry.npmjs.org/pirates/-/pirates-4.0.5.tgz",
+ "integrity": "sha512-8V9+HQPupnaXMA23c5hvl69zXvTwTzyAYasnkb0Tts4XvO4CliqONMOnvlq26rkhLC3nWDFBJf73LU1e1VZLaQ==",
+ "dev": true,
+ "peer": true,
+ "engines": {
+ "node": ">= 6"
+ }
+ },
+ "node_modules/pkg-conf": {
+ "version": "2.1.0",
+ "resolved": "https://registry.npmjs.org/pkg-conf/-/pkg-conf-2.1.0.tgz",
+ "integrity": "sha1-ISZRTKbyq/69FoWW3xi6V4Z/AFg=",
+ "dev": true,
+ "dependencies": {
+ "find-up": "^2.0.0",
+ "load-json-file": "^4.0.0"
+ },
+ "engines": {
+ "node": ">=4"
+ }
+ },
+ "node_modules/pkg-dir": {
+ "version": "4.2.0",
+ "resolved": "https://registry.npmjs.org/pkg-dir/-/pkg-dir-4.2.0.tgz",
+ "integrity": "sha512-HRDzbaKjC+AOWVXxAU/x54COGeIv9eb+6CkDSQoNTt4XyWoIJvuPsXizxu/Fr23EiekbtZwmh1IcIG/l/a10GQ==",
+ "dev": true,
+ "peer": true,
+ "dependencies": {
+ "find-up": "^4.0.0"
+ },
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/pkg-dir/node_modules/find-up": {
+ "version": "4.1.0",
+ "resolved": "https://registry.npmjs.org/find-up/-/find-up-4.1.0.tgz",
+ "integrity": "sha512-PpOwAdQ/YlXQ2vj8a3h8IipDuYRi3wceVQQGYWxNINccq40Anw7BlsEXCMbt1Zt+OLA6Fq9suIpIWD0OsnISlw==",
+ "dev": true,
+ "peer": true,
+ "dependencies": {
+ "locate-path": "^5.0.0",
+ "path-exists": "^4.0.0"
+ },
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/pkg-dir/node_modules/locate-path": {
+ "version": "5.0.0",
+ "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-5.0.0.tgz",
+ "integrity": "sha512-t7hw9pI+WvuwNJXwk5zVHpyhIqzg2qTlklJOf0mVxGSbe3Fp2VieZcduNYjaLDoy6p9uGpQEGWG87WpMKlNq8g==",
+ "dev": true,
+ "peer": true,
+ "dependencies": {
+ "p-locate": "^4.1.0"
+ },
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/pkg-dir/node_modules/p-limit": {
+ "version": "2.3.0",
+ "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-2.3.0.tgz",
+ "integrity": "sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w==",
+ "dev": true,
+ "peer": true,
+ "dependencies": {
+ "p-try": "^2.0.0"
+ },
+ "engines": {
+ "node": ">=6"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
+ "node_modules/pkg-dir/node_modules/p-locate": {
+ "version": "4.1.0",
+ "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-4.1.0.tgz",
+ "integrity": "sha512-R79ZZ/0wAxKGu3oYMlz8jy/kbhsNrS7SKZ7PxEHBgJ5+F2mtFW2fK2cOtBh1cHYkQsbzFV7I+EoRKe6Yt0oK7A==",
+ "dev": true,
+ "peer": true,
+ "dependencies": {
+ "p-limit": "^2.2.0"
+ },
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/please-upgrade-node": {
+ "version": "3.2.0",
+ "resolved": "https://registry.npmjs.org/please-upgrade-node/-/please-upgrade-node-3.2.0.tgz",
+ "integrity": "sha512-gQR3WpIgNIKwBMVLkpMUeR3e1/E1y42bqDQZfql+kDeXd8COYfM8PQA4X6y7a8u9Ua9FHmsrrmirW2vHs45hWg==",
+ "dev": true,
+ "dependencies": {
+ "semver-compare": "^1.0.0"
+ }
+ },
+ "node_modules/posix-character-classes": {
+ "version": "0.1.1",
+ "resolved": "https://registry.npmjs.org/posix-character-classes/-/posix-character-classes-0.1.1.tgz",
+ "integrity": "sha1-AerA/jta9xoqbAL+q7jB/vfgDqs=",
+ "dev": true,
+ "peer": true,
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
+ "node_modules/postcss": {
+ "version": "8.4.14",
+ "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.4.14.tgz",
+ "integrity": "sha512-E398TUmfAYFPBSdzgeieK2Y1+1cpdxJx8yXbK/m57nRhKSmk1GB2tO4lbLBtlkfPQTDKfe4Xqv1ASWPpayPEig==",
+ "dev": true,
+ "funding": [
+ {
+ "type": "opencollective",
+ "url": "https://opencollective.com/postcss/"
+ },
+ {
+ "type": "tidelift",
+ "url": "https://tidelift.com/funding/github/npm/postcss"
+ }
+ ],
+ "dependencies": {
+ "nanoid": "^3.3.4",
+ "picocolors": "^1.0.0",
+ "source-map-js": "^1.0.2"
+ },
+ "engines": {
+ "node": "^10 || ^12 || >=14"
+ }
+ },
+ "node_modules/postcss-html": {
+ "version": "0.36.0",
+ "resolved": "https://registry.npmjs.org/postcss-html/-/postcss-html-0.36.0.tgz",
+ "integrity": "sha512-HeiOxGcuwID0AFsNAL0ox3mW6MHH5cstWN1Z3Y+n6H+g12ih7LHdYxWwEA/QmrebctLjo79xz9ouK3MroHwOJw==",
+ "dev": true,
+ "dependencies": {
+ "htmlparser2": "^3.10.0"
+ },
+ "peerDependencies": {
+ "postcss": ">=5.0.0",
+ "postcss-syntax": ">=0.36.0"
+ }
+ },
+ "node_modules/postcss-less": {
+ "version": "3.1.4",
+ "resolved": "https://registry.npmjs.org/postcss-less/-/postcss-less-3.1.4.tgz",
+ "integrity": "sha512-7TvleQWNM2QLcHqvudt3VYjULVB49uiW6XzEUFmvwHzvsOEF5MwBrIXZDJQvJNFGjJQTzSzZnDoCJ8h/ljyGXA==",
+ "dev": true,
+ "dependencies": {
+ "postcss": "^7.0.14"
+ },
+ "engines": {
+ "node": ">=6.14.4"
+ }
+ },
+ "node_modules/postcss-less/node_modules/picocolors": {
+ "version": "0.2.1",
+ "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-0.2.1.tgz",
+ "integrity": "sha512-cMlDqaLEqfSaW8Z7N5Jw+lyIW869EzT73/F5lhtY9cLGoVxSXznfgfXMO0Z5K0o0Q2TkTXq+0KFsdnSe3jDViA==",
+ "dev": true
+ },
+ "node_modules/postcss-less/node_modules/postcss": {
+ "version": "7.0.39",
+ "resolved": "https://registry.npmjs.org/postcss/-/postcss-7.0.39.tgz",
+ "integrity": "sha512-yioayjNbHn6z1/Bywyb2Y4s3yvDAeXGOyxqD+LnVOinq6Mdmd++SW2wUNVzavyyHxd6+DxzWGIuosg6P1Rj8uA==",
+ "dev": true,
+ "dependencies": {
+ "picocolors": "^0.2.1",
+ "source-map": "^0.6.1"
+ },
+ "engines": {
+ "node": ">=6.0.0"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/postcss/"
+ }
+ },
+ "node_modules/postcss-media-query-parser": {
+ "version": "0.2.3",
+ "resolved": "https://registry.npmjs.org/postcss-media-query-parser/-/postcss-media-query-parser-0.2.3.tgz",
+ "integrity": "sha1-J7Ocb02U+Bsac7j3Y1HGCeXO8kQ=",
+ "dev": true
+ },
+ "node_modules/postcss-resolve-nested-selector": {
+ "version": "0.1.1",
+ "resolved": "https://registry.npmjs.org/postcss-resolve-nested-selector/-/postcss-resolve-nested-selector-0.1.1.tgz",
+ "integrity": "sha1-Kcy8fDfe36wwTp//C/FZaz9qDk4=",
+ "dev": true
+ },
+ "node_modules/postcss-safe-parser": {
+ "version": "4.0.2",
+ "resolved": "https://registry.npmjs.org/postcss-safe-parser/-/postcss-safe-parser-4.0.2.tgz",
+ "integrity": "sha512-Uw6ekxSWNLCPesSv/cmqf2bY/77z11O7jZGPax3ycZMFU/oi2DMH9i89AdHc1tRwFg/arFoEwX0IS3LCUxJh1g==",
+ "dev": true,
+ "dependencies": {
+ "postcss": "^7.0.26"
+ },
+ "engines": {
+ "node": ">=6.0.0"
+ }
+ },
+ "node_modules/postcss-safe-parser/node_modules/picocolors": {
+ "version": "0.2.1",
+ "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-0.2.1.tgz",
+ "integrity": "sha512-cMlDqaLEqfSaW8Z7N5Jw+lyIW869EzT73/F5lhtY9cLGoVxSXznfgfXMO0Z5K0o0Q2TkTXq+0KFsdnSe3jDViA==",
+ "dev": true
+ },
+ "node_modules/postcss-safe-parser/node_modules/postcss": {
+ "version": "7.0.39",
+ "resolved": "https://registry.npmjs.org/postcss/-/postcss-7.0.39.tgz",
+ "integrity": "sha512-yioayjNbHn6z1/Bywyb2Y4s3yvDAeXGOyxqD+LnVOinq6Mdmd++SW2wUNVzavyyHxd6+DxzWGIuosg6P1Rj8uA==",
+ "dev": true,
+ "dependencies": {
+ "picocolors": "^0.2.1",
+ "source-map": "^0.6.1"
+ },
+ "engines": {
+ "node": ">=6.0.0"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/postcss/"
+ }
+ },
+ "node_modules/postcss-sass": {
+ "version": "0.4.4",
+ "resolved": "https://registry.npmjs.org/postcss-sass/-/postcss-sass-0.4.4.tgz",
+ "integrity": "sha512-BYxnVYx4mQooOhr+zer0qWbSPYnarAy8ZT7hAQtbxtgVf8gy+LSLT/hHGe35h14/pZDTw1DsxdbrwxBN++H+fg==",
+ "dev": true,
+ "dependencies": {
+ "gonzales-pe": "^4.3.0",
+ "postcss": "^7.0.21"
+ }
+ },
+ "node_modules/postcss-sass/node_modules/picocolors": {
+ "version": "0.2.1",
+ "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-0.2.1.tgz",
+ "integrity": "sha512-cMlDqaLEqfSaW8Z7N5Jw+lyIW869EzT73/F5lhtY9cLGoVxSXznfgfXMO0Z5K0o0Q2TkTXq+0KFsdnSe3jDViA==",
+ "dev": true
+ },
+ "node_modules/postcss-sass/node_modules/postcss": {
+ "version": "7.0.39",
+ "resolved": "https://registry.npmjs.org/postcss/-/postcss-7.0.39.tgz",
+ "integrity": "sha512-yioayjNbHn6z1/Bywyb2Y4s3yvDAeXGOyxqD+LnVOinq6Mdmd++SW2wUNVzavyyHxd6+DxzWGIuosg6P1Rj8uA==",
+ "dev": true,
+ "dependencies": {
+ "picocolors": "^0.2.1",
+ "source-map": "^0.6.1"
+ },
+ "engines": {
+ "node": ">=6.0.0"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/postcss/"
+ }
+ },
+ "node_modules/postcss-scss": {
+ "version": "2.1.1",
+ "resolved": "https://registry.npmjs.org/postcss-scss/-/postcss-scss-2.1.1.tgz",
+ "integrity": "sha512-jQmGnj0hSGLd9RscFw9LyuSVAa5Bl1/KBPqG1NQw9w8ND55nY4ZEsdlVuYJvLPpV+y0nwTV5v/4rHPzZRihQbA==",
+ "dev": true,
+ "dependencies": {
+ "postcss": "^7.0.6"
+ },
+ "engines": {
+ "node": ">=6.0.0"
+ }
+ },
+ "node_modules/postcss-scss/node_modules/picocolors": {
+ "version": "0.2.1",
+ "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-0.2.1.tgz",
+ "integrity": "sha512-cMlDqaLEqfSaW8Z7N5Jw+lyIW869EzT73/F5lhtY9cLGoVxSXznfgfXMO0Z5K0o0Q2TkTXq+0KFsdnSe3jDViA==",
+ "dev": true
+ },
+ "node_modules/postcss-scss/node_modules/postcss": {
+ "version": "7.0.39",
+ "resolved": "https://registry.npmjs.org/postcss/-/postcss-7.0.39.tgz",
+ "integrity": "sha512-yioayjNbHn6z1/Bywyb2Y4s3yvDAeXGOyxqD+LnVOinq6Mdmd++SW2wUNVzavyyHxd6+DxzWGIuosg6P1Rj8uA==",
+ "dev": true,
+ "dependencies": {
+ "picocolors": "^0.2.1",
+ "source-map": "^0.6.1"
+ },
+ "engines": {
+ "node": ">=6.0.0"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/postcss/"
+ }
+ },
+ "node_modules/postcss-selector-parser": {
+ "version": "6.0.10",
+ "resolved": "https://registry.npmjs.org/postcss-selector-parser/-/postcss-selector-parser-6.0.10.tgz",
+ "integrity": "sha512-IQ7TZdoaqbT+LCpShg46jnZVlhWD2w6iQYAcYXfHARZ7X1t/UGhhceQDs5X0cGqKvYlHNOuv7Oa1xmb0oQuA3w==",
+ "dev": true,
+ "dependencies": {
+ "cssesc": "^3.0.0",
+ "util-deprecate": "^1.0.2"
+ },
+ "engines": {
+ "node": ">=4"
+ }
+ },
+ "node_modules/postcss-sorting": {
+ "version": "5.0.1",
+ "resolved": "https://registry.npmjs.org/postcss-sorting/-/postcss-sorting-5.0.1.tgz",
+ "integrity": "sha512-Y9fUFkIhfrm6i0Ta3n+89j56EFqaNRdUKqXyRp6kvTcSXnmgEjaVowCXH+JBe9+YKWqd4nc28r2sgwnzJalccA==",
+ "dev": true,
+ "dependencies": {
+ "lodash": "^4.17.14",
+ "postcss": "^7.0.17"
+ },
+ "engines": {
+ "node": ">=8.7.0"
+ }
+ },
+ "node_modules/postcss-sorting/node_modules/picocolors": {
+ "version": "0.2.1",
+ "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-0.2.1.tgz",
+ "integrity": "sha512-cMlDqaLEqfSaW8Z7N5Jw+lyIW869EzT73/F5lhtY9cLGoVxSXznfgfXMO0Z5K0o0Q2TkTXq+0KFsdnSe3jDViA==",
+ "dev": true
+ },
+ "node_modules/postcss-sorting/node_modules/postcss": {
+ "version": "7.0.39",
+ "resolved": "https://registry.npmjs.org/postcss/-/postcss-7.0.39.tgz",
+ "integrity": "sha512-yioayjNbHn6z1/Bywyb2Y4s3yvDAeXGOyxqD+LnVOinq6Mdmd++SW2wUNVzavyyHxd6+DxzWGIuosg6P1Rj8uA==",
+ "dev": true,
+ "dependencies": {
+ "picocolors": "^0.2.1",
+ "source-map": "^0.6.1"
+ },
+ "engines": {
+ "node": ">=6.0.0"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/postcss/"
+ }
+ },
+ "node_modules/postcss-syntax": {
+ "version": "0.36.2",
+ "resolved": "https://registry.npmjs.org/postcss-syntax/-/postcss-syntax-0.36.2.tgz",
+ "integrity": "sha512-nBRg/i7E3SOHWxF3PpF5WnJM/jQ1YpY9000OaVXlAQj6Zp/kIqJxEDWIZ67tAd7NLuk7zqN4yqe9nc0oNAOs1w==",
+ "dev": true,
+ "peerDependencies": {
+ "postcss": ">=5.0.0"
+ }
+ },
+ "node_modules/postcss-value-parser": {
+ "version": "4.2.0",
+ "resolved": "https://registry.npmjs.org/postcss-value-parser/-/postcss-value-parser-4.2.0.tgz",
+ "integrity": "sha512-1NNCs6uurfkVbeXG4S8JFT9t19m45ICnif8zWLd5oPSZ50QnwMfK+H3jv408d4jw/7Bttv5axS5IiHoLaVNHeQ==",
+ "dev": true
+ },
+ "node_modules/postcss-values-parser": {
+ "version": "3.2.1",
+ "resolved": "https://registry.npmjs.org/postcss-values-parser/-/postcss-values-parser-3.2.1.tgz",
+ "integrity": "sha512-SQ7/88VE9LhJh9gc27/hqnSU/aZaREVJcRVccXBmajgP2RkjdJzNyH/a9GCVMI5nsRhT0jC5HpUMwfkz81DVVg==",
+ "dev": true,
+ "dependencies": {
+ "color-name": "^1.1.4",
+ "is-url-superb": "^3.0.0",
+ "postcss": "^7.0.5",
+ "url-regex": "^5.0.0"
+ },
+ "engines": {
+ "node": ">=6.14.4"
+ }
+ },
+ "node_modules/postcss-values-parser/node_modules/picocolors": {
+ "version": "0.2.1",
+ "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-0.2.1.tgz",
+ "integrity": "sha512-cMlDqaLEqfSaW8Z7N5Jw+lyIW869EzT73/F5lhtY9cLGoVxSXznfgfXMO0Z5K0o0Q2TkTXq+0KFsdnSe3jDViA==",
+ "dev": true
+ },
+ "node_modules/postcss-values-parser/node_modules/postcss": {
+ "version": "7.0.39",
+ "resolved": "https://registry.npmjs.org/postcss/-/postcss-7.0.39.tgz",
+ "integrity": "sha512-yioayjNbHn6z1/Bywyb2Y4s3yvDAeXGOyxqD+LnVOinq6Mdmd++SW2wUNVzavyyHxd6+DxzWGIuosg6P1Rj8uA==",
+ "dev": true,
+ "dependencies": {
+ "picocolors": "^0.2.1",
+ "source-map": "^0.6.1"
+ },
+ "engines": {
+ "node": ">=6.0.0"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/postcss/"
+ }
+ },
+ "node_modules/prelude-ls": {
+ "version": "1.2.1",
+ "resolved": "https://registry.npmjs.org/prelude-ls/-/prelude-ls-1.2.1.tgz",
+ "integrity": "sha512-vkcDPrRZo1QZLbn5RLGPpg/WmIQ65qoWWhcGKf/b5eplkkarX0m9z8ppCat4mlOqUsWpyNuYgO3VRyrYHSzX5g==",
+ "dev": true,
+ "engines": {
+ "node": ">= 0.8.0"
+ }
+ },
+ "node_modules/prettier": {
+ "version": "2.2.1",
+ "resolved": "https://registry.npmjs.org/prettier/-/prettier-2.2.1.tgz",
+ "integrity": "sha512-PqyhM2yCjg/oKkFPtTGUojv7gnZAoG80ttl45O6x2Ug/rMJw4wcc9k6aaf2hibP7BGVCCM33gZoGjyvt9mm16Q==",
+ "dev": true,
+ "bin": {
+ "prettier": "bin-prettier.js"
+ },
+ "engines": {
+ "node": ">=10.13.0"
+ }
+ },
+ "node_modules/prettier-linter-helpers": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/prettier-linter-helpers/-/prettier-linter-helpers-1.0.0.tgz",
+ "integrity": "sha512-GbK2cP9nraSSUF9N2XwUwqfzlAFlMNYYl+ShE/V+H8a9uNl/oUqB1w2EL54Jh0OlyRSd8RfWYJ3coVS4TROP2w==",
+ "dev": true,
+ "dependencies": {
+ "fast-diff": "^1.1.2"
+ },
+ "engines": {
+ "node": ">=6.0.0"
+ }
+ },
+ "node_modules/pretty-format": {
+ "version": "26.6.2",
+ "resolved": "https://registry.npmjs.org/pretty-format/-/pretty-format-26.6.2.tgz",
+ "integrity": "sha512-7AeGuCYNGmycyQbCqd/3PWH4eOoX/OiCa0uphp57NVTeAGdJGaAliecxwBDHYQCIvrW7aDBZCYeNTP/WX69mkg==",
+ "dev": true,
+ "peer": true,
+ "dependencies": {
+ "@jest/types": "^26.6.2",
+ "ansi-regex": "^5.0.0",
+ "ansi-styles": "^4.0.0",
+ "react-is": "^17.0.1"
+ },
+ "engines": {
+ "node": ">= 10"
+ }
+ },
+ "node_modules/prompts": {
+ "version": "2.4.2",
+ "resolved": "https://registry.npmjs.org/prompts/-/prompts-2.4.2.tgz",
+ "integrity": "sha512-NxNv/kLguCA7p3jE8oL2aEBsrJWgAakBpgmgK6lpPWV+WuOmY6r2/zbAVnP+T8bQlA0nzHXSJSJW0Hq7ylaD2Q==",
+ "dev": true,
+ "peer": true,
+ "dependencies": {
+ "kleur": "^3.0.3",
+ "sisteransi": "^1.0.5"
+ },
+ "engines": {
+ "node": ">= 6"
+ }
+ },
+ "node_modules/prop-types": {
+ "version": "15.8.1",
+ "resolved": "https://registry.npmjs.org/prop-types/-/prop-types-15.8.1.tgz",
+ "integrity": "sha512-oj87CgZICdulUohogVAR7AjlC0327U4el4L6eAvOqCeudMDVU0NThNaV+b9Df4dXgSP1gXMTnPdhfe/2qDH5cg==",
+ "dev": true,
+ "dependencies": {
+ "loose-envify": "^1.4.0",
+ "object-assign": "^4.1.1",
+ "react-is": "^16.13.1"
+ }
+ },
+ "node_modules/prop-types/node_modules/react-is": {
+ "version": "16.13.1",
+ "resolved": "https://registry.npmjs.org/react-is/-/react-is-16.13.1.tgz",
+ "integrity": "sha512-24e6ynE2H+OKt4kqsOvNd8kBpV65zoxbA4BVsEOB3ARVWQki/DHzaUoC5KuON/BiccDaCCTZBuOcfZs70kR8bQ==",
+ "dev": true
+ },
+ "node_modules/psl": {
+ "version": "1.8.0",
+ "resolved": "https://registry.npmjs.org/psl/-/psl-1.8.0.tgz",
+ "integrity": "sha512-RIdOzyoavK+hA18OGGWDqUTsCLhtA7IcZ/6NCs4fFJaHBDab+pDDmDIByWFRQJq2Cd7r1OoQxBGKOaztq+hjIQ==",
+ "dev": true,
+ "peer": true
+ },
+ "node_modules/pump": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/pump/-/pump-3.0.0.tgz",
+ "integrity": "sha512-LwZy+p3SFs1Pytd/jYct4wpv49HiYCqd9Rlc5ZVdk0V+8Yzv6jR5Blk3TRmPL1ft69TxP0IMZGJ+WPFU2BFhww==",
+ "dev": true,
+ "peer": true,
+ "dependencies": {
+ "end-of-stream": "^1.1.0",
+ "once": "^1.3.1"
+ }
+ },
+ "node_modules/punycode": {
+ "version": "2.1.1",
+ "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.1.1.tgz",
+ "integrity": "sha512-XRsRjdf+j5ml+y/6GKHPZbrF/8p2Yga0JPtdqTIY2Xe5ohJPD9saDJJLPvp9+NSBprVvevdXZybnj2cv8OEd0A==",
+ "dev": true,
+ "engines": {
+ "node": ">=6"
+ }
+ },
+ "node_modules/querystringify": {
+ "version": "2.2.0",
+ "resolved": "https://registry.npmjs.org/querystringify/-/querystringify-2.2.0.tgz",
+ "integrity": "sha512-FIqgj2EUvTa7R50u0rGsyTftzjYmv/a3hO345bZNrqabNqjtgiDMgmo4mkUjd+nzU5oF3dClKqFIPUKybUyqoQ==",
+ "dev": true,
+ "peer": true
+ },
+ "node_modules/queue-microtask": {
+ "version": "1.2.3",
+ "resolved": "https://registry.npmjs.org/queue-microtask/-/queue-microtask-1.2.3.tgz",
+ "integrity": "sha512-NuaNSa6flKT5JaSYQzJok04JzTL1CA6aGhv5rfLW3PgqA+M2ChpZQnAC8h8i4ZFkBS8X5RqkDBHA7r4hej3K9A==",
+ "dev": true,
+ "funding": [
+ {
+ "type": "github",
+ "url": "https://github.com/sponsors/feross"
+ },
+ {
+ "type": "patreon",
+ "url": "https://www.patreon.com/feross"
+ },
+ {
+ "type": "consulting",
+ "url": "https://feross.org/support"
+ }
+ ]
+ },
+ "node_modules/quick-lru": {
+ "version": "4.0.1",
+ "resolved": "https://registry.npmjs.org/quick-lru/-/quick-lru-4.0.1.tgz",
+ "integrity": "sha512-ARhCpm70fzdcvNQfPoy49IaanKkTlRWF2JMzqhcJbhSFRZv7nPTvZJdcY7301IPmvW+/p0RgIWnQDLJxifsQ7g==",
+ "dev": true,
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/react": {
+ "version": "18.0.0",
+ "resolved": "https://registry.npmjs.org/react/-/react-18.0.0.tgz",
+ "integrity": "sha512-x+VL6wbT4JRVPm7EGxXhZ8w8LTROaxPXOqhlGyVSrv0sB1jkyFGgXxJ8LVoPRLvPR6/CIZGFmfzqUa2NYeMr2A==",
+ "dev": true,
+ "peer": true,
+ "dependencies": {
+ "loose-envify": "^1.1.0"
+ },
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
+ "node_modules/react-dom": {
+ "version": "18.0.0",
+ "resolved": "https://registry.npmjs.org/react-dom/-/react-dom-18.0.0.tgz",
+ "integrity": "sha512-XqX7uzmFo0pUceWFCt7Gff6IyIMzFUn7QMZrbrQfGxtaxXZIcGQzoNpRLE3fQLnS4XzLLPMZX2T9TRcSrasicw==",
+ "dev": true,
+ "peer": true,
+ "dependencies": {
+ "loose-envify": "^1.1.0",
+ "scheduler": "^0.21.0"
+ },
+ "peerDependencies": {
+ "react": "^18.0.0"
+ }
+ },
+ "node_modules/react-is": {
+ "version": "17.0.2",
+ "resolved": "https://registry.npmjs.org/react-is/-/react-is-17.0.2.tgz",
+ "integrity": "sha512-w2GsyukL62IJnlaff/nRegPQR94C/XXamvMWmSHRJ4y7Ts/4ocGRmTHvOs8PSE6pB3dWOrD/nueuU5sduBsQ4w==",
+ "dev": true,
+ "peer": true
+ },
+ "node_modules/read-pkg": {
+ "version": "5.2.0",
+ "resolved": "https://registry.npmjs.org/read-pkg/-/read-pkg-5.2.0.tgz",
+ "integrity": "sha512-Ug69mNOpfvKDAc2Q8DRpMjjzdtrnv9HcSMX+4VsZxD1aZ6ZzrIE7rlzXBtWTyhULSMKg076AW6WR5iZpD0JiOg==",
+ "dev": true,
+ "dependencies": {
+ "@types/normalize-package-data": "^2.4.0",
+ "normalize-package-data": "^2.5.0",
+ "parse-json": "^5.0.0",
+ "type-fest": "^0.6.0"
+ },
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/read-pkg-up": {
+ "version": "7.0.1",
+ "resolved": "https://registry.npmjs.org/read-pkg-up/-/read-pkg-up-7.0.1.tgz",
+ "integrity": "sha512-zK0TB7Xd6JpCLmlLmufqykGE+/TlOePD6qKClNW7hHDKFh/J7/7gCWGR7joEQEW1bKq3a3yUZSObOoWLFQ4ohg==",
+ "dev": true,
+ "dependencies": {
+ "find-up": "^4.1.0",
+ "read-pkg": "^5.2.0",
+ "type-fest": "^0.8.1"
+ },
+ "engines": {
+ "node": ">=8"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
+ "node_modules/read-pkg-up/node_modules/find-up": {
+ "version": "4.1.0",
+ "resolved": "https://registry.npmjs.org/find-up/-/find-up-4.1.0.tgz",
+ "integrity": "sha512-PpOwAdQ/YlXQ2vj8a3h8IipDuYRi3wceVQQGYWxNINccq40Anw7BlsEXCMbt1Zt+OLA6Fq9suIpIWD0OsnISlw==",
+ "dev": true,
+ "dependencies": {
+ "locate-path": "^5.0.0",
+ "path-exists": "^4.0.0"
+ },
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/read-pkg-up/node_modules/locate-path": {
+ "version": "5.0.0",
+ "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-5.0.0.tgz",
+ "integrity": "sha512-t7hw9pI+WvuwNJXwk5zVHpyhIqzg2qTlklJOf0mVxGSbe3Fp2VieZcduNYjaLDoy6p9uGpQEGWG87WpMKlNq8g==",
+ "dev": true,
+ "dependencies": {
+ "p-locate": "^4.1.0"
+ },
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/read-pkg-up/node_modules/p-limit": {
+ "version": "2.3.0",
+ "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-2.3.0.tgz",
+ "integrity": "sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w==",
+ "dev": true,
+ "dependencies": {
+ "p-try": "^2.0.0"
+ },
+ "engines": {
+ "node": ">=6"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
+ "node_modules/read-pkg-up/node_modules/p-locate": {
+ "version": "4.1.0",
+ "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-4.1.0.tgz",
+ "integrity": "sha512-R79ZZ/0wAxKGu3oYMlz8jy/kbhsNrS7SKZ7PxEHBgJ5+F2mtFW2fK2cOtBh1cHYkQsbzFV7I+EoRKe6Yt0oK7A==",
+ "dev": true,
+ "dependencies": {
+ "p-limit": "^2.2.0"
+ },
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/read-pkg-up/node_modules/type-fest": {
+ "version": "0.8.1",
+ "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.8.1.tgz",
+ "integrity": "sha512-4dbzIzqvjtgiM5rw1k5rEHtBANKmdudhGyBEajN01fEyhaAIhsoKNy6y7+IN93IfpFtwY9iqi7kD+xwKhQsNJA==",
+ "dev": true,
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/read-pkg/node_modules/type-fest": {
+ "version": "0.6.0",
+ "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.6.0.tgz",
+ "integrity": "sha512-q+MB8nYR1KDLrgr4G5yemftpMC7/QLqVndBmEEdqzmNj5dcFOO4Oo8qlwZE3ULT3+Zim1F8Kq4cBnikNhlCMlg==",
+ "dev": true,
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/readable-stream": {
+ "version": "3.6.0",
+ "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.0.tgz",
+ "integrity": "sha512-BViHy7LKeTz4oNnkcLJ+lVSL6vpiFeX6/d3oSH8zCW7UxP2onchk+vTGB143xuFjHS3deTgkKoXXymXqymiIdA==",
+ "dev": true,
+ "dependencies": {
+ "inherits": "^2.0.3",
+ "string_decoder": "^1.1.1",
+ "util-deprecate": "^1.0.1"
+ },
+ "engines": {
+ "node": ">= 6"
+ }
+ },
+ "node_modules/readdirp": {
+ "version": "3.5.0",
+ "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-3.5.0.tgz",
+ "integrity": "sha512-cMhu7c/8rdhkHXWsY+osBhfSy0JikwpHK/5+imo+LpeasTF8ouErHrlYkwT0++njiyuDvc7OFY5T3ukvZ8qmFQ==",
+ "dev": true,
+ "dependencies": {
+ "picomatch": "^2.2.1"
+ },
+ "engines": {
+ "node": ">=8.10.0"
+ }
+ },
+ "node_modules/redent": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/redent/-/redent-3.0.0.tgz",
+ "integrity": "sha512-6tDA8g98We0zd0GvVeMT9arEOnTw9qM03L9cJXaCjrip1OO764RDBLBfrB4cwzNGDj5OA5ioymC9GkizgWJDUg==",
+ "dev": true,
+ "dependencies": {
+ "indent-string": "^4.0.0",
+ "strip-indent": "^3.0.0"
+ },
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/regenerator-runtime": {
+ "version": "0.13.11",
+ "resolved": "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.13.11.tgz",
+ "integrity": "sha512-kY1AZVr2Ra+t+piVaJ4gxaFaReZVH40AKNo7UCX6W+dEwBo/2oZJzqfuN1qLq1oL45o56cPaTXELwrTh8Fpggg==",
+ "dev": true
+ },
+ "node_modules/regex-not": {
+ "version": "1.0.2",
+ "resolved": "https://registry.npmjs.org/regex-not/-/regex-not-1.0.2.tgz",
+ "integrity": "sha512-J6SDjUgDxQj5NusnOtdFxDwN/+HWykR8GELwctJ7mdqhcyy1xEc4SRFHUXvxTp661YaVKAjfRLZ9cCqS6tn32A==",
+ "dev": true,
+ "peer": true,
+ "dependencies": {
+ "extend-shallow": "^3.0.2",
+ "safe-regex": "^1.1.0"
+ },
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
+ "node_modules/regexp.prototype.flags": {
+ "version": "1.4.3",
+ "resolved": "https://registry.npmjs.org/regexp.prototype.flags/-/regexp.prototype.flags-1.4.3.tgz",
+ "integrity": "sha512-fjggEOO3slI6Wvgjwflkc4NFRCTZAu5CnNfBd5qOMYhWdn67nJBBu34/TkD++eeFmd8C9r9jfXJ27+nSiRkSUA==",
+ "dev": true,
+ "dependencies": {
+ "call-bind": "^1.0.2",
+ "define-properties": "^1.1.3",
+ "functions-have-names": "^1.2.2"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/remark": {
+ "version": "13.0.0",
+ "resolved": "https://registry.npmjs.org/remark/-/remark-13.0.0.tgz",
+ "integrity": "sha512-HDz1+IKGtOyWN+QgBiAT0kn+2s6ovOxHyPAFGKVE81VSzJ+mq7RwHFledEvB5F1p4iJvOah/LOKdFuzvRnNLCA==",
+ "dev": true,
+ "dependencies": {
+ "remark-parse": "^9.0.0",
+ "remark-stringify": "^9.0.0",
+ "unified": "^9.1.0"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/unified"
+ }
+ },
+ "node_modules/remark-mdx": {
+ "version": "1.6.22",
+ "resolved": "https://registry.npmjs.org/remark-mdx/-/remark-mdx-1.6.22.tgz",
+ "integrity": "sha512-phMHBJgeV76uyFkH4rvzCftLfKCr2RZuF+/gmVcaKrpsihyzmhXjA0BEMDaPTXG5y8qZOKPVo83NAOX01LPnOQ==",
+ "dev": true,
+ "dependencies": {
+ "@babel/core": "7.12.9",
+ "@babel/helper-plugin-utils": "7.10.4",
+ "@babel/plugin-proposal-object-rest-spread": "7.12.1",
+ "@babel/plugin-syntax-jsx": "7.12.1",
+ "@mdx-js/util": "1.6.22",
+ "is-alphabetical": "1.0.4",
+ "remark-parse": "8.0.3",
+ "unified": "9.2.0"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/unified"
+ }
+ },
+ "node_modules/remark-mdx/node_modules/@babel/core": {
+ "version": "7.12.9",
+ "resolved": "https://registry.npmjs.org/@babel/core/-/core-7.12.9.tgz",
+ "integrity": "sha512-gTXYh3M5wb7FRXQy+FErKFAv90BnlOuNn1QkCK2lREoPAjrQCO49+HVSrFoe5uakFAF5eenS75KbO2vQiLrTMQ==",
+ "dev": true,
+ "dependencies": {
+ "@babel/code-frame": "^7.10.4",
+ "@babel/generator": "^7.12.5",
+ "@babel/helper-module-transforms": "^7.12.1",
+ "@babel/helpers": "^7.12.5",
+ "@babel/parser": "^7.12.7",
+ "@babel/template": "^7.12.7",
+ "@babel/traverse": "^7.12.9",
+ "@babel/types": "^7.12.7",
+ "convert-source-map": "^1.7.0",
+ "debug": "^4.1.0",
+ "gensync": "^1.0.0-beta.1",
+ "json5": "^2.1.2",
+ "lodash": "^4.17.19",
+ "resolve": "^1.3.2",
+ "semver": "^5.4.1",
+ "source-map": "^0.5.0"
+ },
+ "engines": {
+ "node": ">=6.9.0"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/babel"
+ }
+ },
+ "node_modules/remark-mdx/node_modules/@babel/helper-plugin-utils": {
+ "version": "7.10.4",
+ "resolved": "https://registry.npmjs.org/@babel/helper-plugin-utils/-/helper-plugin-utils-7.10.4.tgz",
+ "integrity": "sha512-O4KCvQA6lLiMU9l2eawBPMf1xPP8xPfB3iEQw150hOVTqj/rfXz0ThTb4HEzqQfs2Bmo5Ay8BzxfzVtBrr9dVg==",
+ "dev": true
+ },
+ "node_modules/remark-mdx/node_modules/is-plain-obj": {
+ "version": "2.1.0",
+ "resolved": "https://registry.npmjs.org/is-plain-obj/-/is-plain-obj-2.1.0.tgz",
+ "integrity": "sha512-YWnfyRwxL/+SsrWYfOpUtz5b3YD+nyfkHvjbcanzk8zgyO4ASD67uVMRt8k5bM4lLMDnXfriRhOpemw+NfT1eA==",
+ "dev": true,
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/remark-mdx/node_modules/remark-parse": {
+ "version": "8.0.3",
+ "resolved": "https://registry.npmjs.org/remark-parse/-/remark-parse-8.0.3.tgz",
+ "integrity": "sha512-E1K9+QLGgggHxCQtLt++uXltxEprmWzNfg+MxpfHsZlrddKzZ/hZyWHDbK3/Ap8HJQqYJRXP+jHczdL6q6i85Q==",
+ "dev": true,
+ "dependencies": {
+ "ccount": "^1.0.0",
+ "collapse-white-space": "^1.0.2",
+ "is-alphabetical": "^1.0.0",
+ "is-decimal": "^1.0.0",
+ "is-whitespace-character": "^1.0.0",
+ "is-word-character": "^1.0.0",
+ "markdown-escapes": "^1.0.0",
+ "parse-entities": "^2.0.0",
+ "repeat-string": "^1.5.4",
+ "state-toggle": "^1.0.0",
+ "trim": "0.0.1",
+ "trim-trailing-lines": "^1.0.0",
+ "unherit": "^1.0.4",
+ "unist-util-remove-position": "^2.0.0",
+ "vfile-location": "^3.0.0",
+ "xtend": "^4.0.1"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/unified"
+ }
+ },
+ "node_modules/remark-mdx/node_modules/semver": {
+ "version": "5.7.1",
+ "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz",
+ "integrity": "sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==",
+ "dev": true,
+ "bin": {
+ "semver": "bin/semver"
+ }
+ },
+ "node_modules/remark-mdx/node_modules/source-map": {
+ "version": "0.5.7",
+ "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz",
+ "integrity": "sha512-LbrmJOMUSdEVxIKvdcJzQC+nQhe8FUZQTXQy6+I75skNgn3OoQ0DZA8YnFa7gp8tqtL3KPf1kmo0R5DoApeSGQ==",
+ "dev": true,
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
+ "node_modules/remark-mdx/node_modules/unified": {
+ "version": "9.2.0",
+ "resolved": "https://registry.npmjs.org/unified/-/unified-9.2.0.tgz",
+ "integrity": "sha512-vx2Z0vY+a3YoTj8+pttM3tiJHCwY5UFbYdiWrwBEbHmK8pvsPj2rtAX2BFfgXen8T39CJWblWRDT4L5WGXtDdg==",
+ "dev": true,
+ "dependencies": {
+ "bail": "^1.0.0",
+ "extend": "^3.0.0",
+ "is-buffer": "^2.0.0",
+ "is-plain-obj": "^2.0.0",
+ "trough": "^1.0.0",
+ "vfile": "^4.0.0"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/unified"
+ }
+ },
+ "node_modules/remark-parse": {
+ "version": "9.0.0",
+ "resolved": "https://registry.npmjs.org/remark-parse/-/remark-parse-9.0.0.tgz",
+ "integrity": "sha512-geKatMwSzEXKHuzBNU1z676sGcDcFoChMK38TgdHJNAYfFtsfHDQG7MoJAjs6sgYMqyLduCYWDIWZIxiPeafEw==",
+ "dev": true,
+ "dependencies": {
+ "mdast-util-from-markdown": "^0.8.0"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/unified"
+ }
+ },
+ "node_modules/remark-stringify": {
+ "version": "9.0.1",
+ "resolved": "https://registry.npmjs.org/remark-stringify/-/remark-stringify-9.0.1.tgz",
+ "integrity": "sha512-mWmNg3ZtESvZS8fv5PTvaPckdL4iNlCHTt8/e/8oN08nArHRHjNZMKzA/YW3+p7/lYqIw4nx1XsjCBo/AxNChg==",
+ "dev": true,
+ "dependencies": {
+ "mdast-util-to-markdown": "^0.6.0"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/unified"
+ }
+ },
+ "node_modules/remove-trailing-separator": {
+ "version": "1.1.0",
+ "resolved": "https://registry.npmjs.org/remove-trailing-separator/-/remove-trailing-separator-1.1.0.tgz",
+ "integrity": "sha1-wkvOKig62tW8P1jg1IJJuSN52O8=",
+ "dev": true,
+ "peer": true
+ },
+ "node_modules/repeat-element": {
+ "version": "1.1.4",
+ "resolved": "https://registry.npmjs.org/repeat-element/-/repeat-element-1.1.4.tgz",
+ "integrity": "sha512-LFiNfRcSu7KK3evMyYOuCzv3L10TW7yC1G2/+StMjK8Y6Vqd2MG7r/Qjw4ghtuCOjFvlnms/iMmLqpvW/ES/WQ==",
+ "dev": true,
+ "peer": true,
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
+ "node_modules/repeat-string": {
+ "version": "1.6.1",
+ "resolved": "https://registry.npmjs.org/repeat-string/-/repeat-string-1.6.1.tgz",
+ "integrity": "sha1-jcrkcOHIirwtYA//Sndihtp15jc=",
+ "dev": true,
+ "engines": {
+ "node": ">=0.10"
+ }
+ },
+ "node_modules/require-directory": {
+ "version": "2.1.1",
+ "resolved": "https://registry.npmjs.org/require-directory/-/require-directory-2.1.1.tgz",
+ "integrity": "sha1-jGStX9MNqxyXbiNE/+f3kqam30I=",
+ "dev": true,
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
+ "node_modules/require-from-string": {
+ "version": "2.0.2",
+ "resolved": "https://registry.npmjs.org/require-from-string/-/require-from-string-2.0.2.tgz",
+ "integrity": "sha512-Xf0nWe6RseziFMu+Ap9biiUbmplq6S9/p+7w7YXP/JBHhrUDDUhwa+vANyubuqfZWTveU//DYVGsDG7RKL/vEw==",
+ "dev": true,
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
+ "node_modules/require-main-filename": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/require-main-filename/-/require-main-filename-2.0.0.tgz",
+ "integrity": "sha512-NKN5kMDylKuldxYLSUfrbo5Tuzh4hd+2E8NPPX02mZtn1VuREQToYe/ZdlJy+J3uCpfaiGF05e7B8W0iXbQHmg==",
+ "dev": true,
+ "peer": true
+ },
+ "node_modules/requires-port": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/requires-port/-/requires-port-1.0.0.tgz",
+ "integrity": "sha512-KigOCHcocU3XODJxsu8i/j8T9tzT4adHiecwORRQ0ZZFcp7ahwXuRU1m+yuO90C5ZUyGeGfocHDI14M3L3yDAQ==",
+ "dev": true,
+ "peer": true
+ },
+ "node_modules/resolve": {
+ "version": "1.22.0",
+ "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.22.0.tgz",
+ "integrity": "sha512-Hhtrw0nLeSrFQ7phPp4OOcVjLPIeMnRlr5mcnVuMe7M/7eBn98A3hmFRLoFo3DLZkivSYwhRUJTyPyWAk56WLw==",
+ "dev": true,
+ "dependencies": {
+ "is-core-module": "^2.8.1",
+ "path-parse": "^1.0.7",
+ "supports-preserve-symlinks-flag": "^1.0.0"
+ },
+ "bin": {
+ "resolve": "bin/resolve"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/resolve-cwd": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/resolve-cwd/-/resolve-cwd-3.0.0.tgz",
+ "integrity": "sha512-OrZaX2Mb+rJCpH/6CpSqt9xFVpN++x01XnN2ie9g6P5/3xelLAkXWVADpdz1IHD/KFfEXyE6V0U01OQ3UO2rEg==",
+ "dev": true,
+ "peer": true,
+ "dependencies": {
+ "resolve-from": "^5.0.0"
+ },
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/resolve-cwd/node_modules/resolve-from": {
+ "version": "5.0.0",
+ "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-5.0.0.tgz",
+ "integrity": "sha512-qYg9KP24dD5qka9J47d0aVky0N+b4fTU89LN9iDnjB5waksiC49rvMB0PrUJQGoTmH50XPiqOvAjDfaijGxYZw==",
+ "dev": true,
+ "peer": true,
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/resolve-from": {
+ "version": "4.0.0",
+ "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-4.0.0.tgz",
+ "integrity": "sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g==",
+ "dev": true,
+ "engines": {
+ "node": ">=4"
+ }
+ },
+ "node_modules/resolve-url": {
+ "version": "0.2.1",
+ "resolved": "https://registry.npmjs.org/resolve-url/-/resolve-url-0.2.1.tgz",
+ "integrity": "sha1-LGN/53yJOv0qZj/iGqkIAGjiBSo=",
+ "deprecated": "https://github.com/lydell/resolve-url#deprecated",
+ "dev": true,
+ "peer": true
+ },
+ "node_modules/restore-cursor": {
+ "version": "3.1.0",
+ "resolved": "https://registry.npmjs.org/restore-cursor/-/restore-cursor-3.1.0.tgz",
+ "integrity": "sha512-l+sSefzHpj5qimhFSE5a8nufZYAM3sBSVMAPtYkmC+4EH2anSGaEMXSD0izRQbu9nfyQ9y5JrVmp7E8oZrUjvA==",
+ "dev": true,
+ "dependencies": {
+ "onetime": "^5.1.0",
+ "signal-exit": "^3.0.2"
+ },
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/ret": {
+ "version": "0.1.15",
+ "resolved": "https://registry.npmjs.org/ret/-/ret-0.1.15.tgz",
+ "integrity": "sha512-TTlYpa+OL+vMMNG24xSlQGEJ3B/RzEfUlLct7b5G/ytav+wPrplCpVMFuwzXbkecJrb6IYo1iFb0S9v37754mg==",
+ "dev": true,
+ "peer": true,
+ "engines": {
+ "node": ">=0.12"
+ }
+ },
+ "node_modules/reusify": {
+ "version": "1.0.4",
+ "resolved": "https://registry.npmjs.org/reusify/-/reusify-1.0.4.tgz",
+ "integrity": "sha512-U9nH88a3fc/ekCF1l0/UP1IosiuIjyTh7hBvXVMHYgVcfGvt897Xguj2UOLDeI5BG2m7/uwyaLVT6fbtCwTyzw==",
+ "dev": true,
+ "engines": {
+ "iojs": ">=1.0.0",
+ "node": ">=0.10.0"
+ }
+ },
+ "node_modules/rfdc": {
+ "version": "1.3.0",
+ "resolved": "https://registry.npmjs.org/rfdc/-/rfdc-1.3.0.tgz",
+ "integrity": "sha512-V2hovdzFbOi77/WajaSMXk2OLm+xNIeQdMMuB7icj7bk6zi2F8GGAxigcnDFpJHbNyNcgyJDiP+8nOrY5cZGrA==",
+ "dev": true
+ },
+ "node_modules/rimraf": {
+ "version": "3.0.2",
+ "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-3.0.2.tgz",
+ "integrity": "sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA==",
+ "dev": true,
+ "dependencies": {
+ "glob": "^7.1.3"
+ },
+ "bin": {
+ "rimraf": "bin.js"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/isaacs"
+ }
+ },
+ "node_modules/rivet-graphql": {
+ "version": "0.3.1",
+ "resolved": "https://registry.npmjs.org/rivet-graphql/-/rivet-graphql-0.3.1.tgz",
+ "integrity": "sha512-HEov02XhZ6H1jOME+mO8CZwliu/UtgZSHixYUwvQ7HSx3gk8EOVaQY5c3zscOYjZECvP8cR4+1Ob3KHWJRWEMw==",
+ "dev": true,
+ "dependencies": {
+ "graphql": "^15.3.0",
+ "graphql-request": "^3.0.0"
+ }
+ },
+ "node_modules/rsvp": {
+ "version": "4.8.5",
+ "resolved": "https://registry.npmjs.org/rsvp/-/rsvp-4.8.5.tgz",
+ "integrity": "sha512-nfMOlASu9OnRJo1mbEk2cz0D56a1MBNrJ7orjRZQG10XDyuvwksKbuXNp6qa+kbn839HwjwhBzhFmdsaEAfauA==",
+ "dev": true,
+ "peer": true,
+ "engines": {
+ "node": "6.* || >= 7.*"
+ }
+ },
+ "node_modules/run-async": {
+ "version": "2.4.1",
+ "resolved": "https://registry.npmjs.org/run-async/-/run-async-2.4.1.tgz",
+ "integrity": "sha512-tvVnVv01b8c1RrA6Ep7JkStj85Guv/YrMcwqYQnwjsAS2cTmmPGBBjAjpCW7RrSodNSoE2/qg9O4bceNvUuDgQ==",
+ "dev": true,
+ "engines": {
+ "node": ">=0.12.0"
+ }
+ },
+ "node_modules/run-parallel": {
+ "version": "1.2.0",
+ "resolved": "https://registry.npmjs.org/run-parallel/-/run-parallel-1.2.0.tgz",
+ "integrity": "sha512-5l4VyZR86LZ/lDxZTR6jqL8AFE2S0IFLMP26AbjsLVADxHdhB/c0GUsH+y39UfCi3dzz8OlQuPmnaJOMoDHQBA==",
+ "dev": true,
+ "funding": [
+ {
+ "type": "github",
+ "url": "https://github.com/sponsors/feross"
+ },
+ {
+ "type": "patreon",
+ "url": "https://www.patreon.com/feross"
+ },
+ {
+ "type": "consulting",
+ "url": "https://feross.org/support"
+ }
+ ],
+ "dependencies": {
+ "queue-microtask": "^1.2.2"
+ }
+ },
+ "node_modules/rxjs": {
+ "version": "6.6.7",
+ "resolved": "https://registry.npmjs.org/rxjs/-/rxjs-6.6.7.tgz",
+ "integrity": "sha512-hTdwr+7yYNIT5n4AMYp85KA6yw2Va0FLa3Rguvbpa4W3I5xynaBZo41cM3XM+4Q6fRMj3sBYIR1VAmZMXYJvRQ==",
+ "dev": true,
+ "dependencies": {
+ "tslib": "^1.9.0"
+ },
+ "engines": {
+ "npm": ">=2.0.0"
+ }
+ },
+ "node_modules/safe-buffer": {
+ "version": "5.1.2",
+ "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz",
+ "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==",
+ "dev": true
+ },
+ "node_modules/safe-regex": {
+ "version": "1.1.0",
+ "resolved": "https://registry.npmjs.org/safe-regex/-/safe-regex-1.1.0.tgz",
+ "integrity": "sha1-QKNmnzsHfR6UPURinhV91IAjvy4=",
+ "dev": true,
+ "peer": true,
+ "dependencies": {
+ "ret": "~0.1.10"
+ }
+ },
+ "node_modules/safe-regex-test": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/safe-regex-test/-/safe-regex-test-1.0.0.tgz",
+ "integrity": "sha512-JBUUzyOgEwXQY1NuPtvcj/qcBDbDmEvWufhlnXZIm75DEHp+afM1r1ujJpJsV/gSM4t59tpDyPi1sd6ZaPFfsA==",
+ "dev": true,
+ "dependencies": {
+ "call-bind": "^1.0.2",
+ "get-intrinsic": "^1.1.3",
+ "is-regex": "^1.1.4"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/safer-buffer": {
+ "version": "2.1.2",
+ "resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz",
+ "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==",
+ "dev": true
+ },
+ "node_modules/sane": {
+ "version": "4.1.0",
+ "resolved": "https://registry.npmjs.org/sane/-/sane-4.1.0.tgz",
+ "integrity": "sha512-hhbzAgTIX8O7SHfp2c8/kREfEn4qO/9q8C9beyY6+tvZ87EpoZ3i1RIEvp27YBswnNbY9mWd6paKVmKbAgLfZA==",
+ "deprecated": "some dependency vulnerabilities fixed, support for node < 10 dropped, and newer ECMAScript syntax/features added",
+ "dev": true,
+ "peer": true,
+ "dependencies": {
+ "@cnakazawa/watch": "^1.0.3",
+ "anymatch": "^2.0.0",
+ "capture-exit": "^2.0.0",
+ "exec-sh": "^0.3.2",
+ "execa": "^1.0.0",
+ "fb-watchman": "^2.0.0",
+ "micromatch": "^3.1.4",
+ "minimist": "^1.1.1",
+ "walker": "~1.0.5"
+ },
+ "bin": {
+ "sane": "src/cli.js"
+ },
+ "engines": {
+ "node": "6.* || 8.* || >= 10.*"
+ }
+ },
+ "node_modules/sane/node_modules/anymatch": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/anymatch/-/anymatch-2.0.0.tgz",
+ "integrity": "sha512-5teOsQWABXHHBFP9y3skS5P3d/WfWXpv3FUpy+LorMrNYaT9pI4oLMQX7jzQ2KklNpGpWHzdCXTDT2Y3XGlZBw==",
+ "dev": true,
+ "peer": true,
+ "dependencies": {
+ "micromatch": "^3.1.4",
+ "normalize-path": "^2.1.1"
+ }
+ },
+ "node_modules/sane/node_modules/braces": {
+ "version": "2.3.2",
+ "resolved": "https://registry.npmjs.org/braces/-/braces-2.3.2.tgz",
+ "integrity": "sha512-aNdbnj9P8PjdXU4ybaWLK2IF3jc/EoDYbC7AazW6to3TRsfXxscC9UXOB5iDiEQrkyIbWp2SLQda4+QAa7nc3w==",
+ "dev": true,
+ "peer": true,
+ "dependencies": {
+ "arr-flatten": "^1.1.0",
+ "array-unique": "^0.3.2",
+ "extend-shallow": "^2.0.1",
+ "fill-range": "^4.0.0",
+ "isobject": "^3.0.1",
+ "repeat-element": "^1.1.2",
+ "snapdragon": "^0.8.1",
+ "snapdragon-node": "^2.0.1",
+ "split-string": "^3.0.2",
+ "to-regex": "^3.0.1"
+ },
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
+ "node_modules/sane/node_modules/braces/node_modules/extend-shallow": {
+ "version": "2.0.1",
+ "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz",
+ "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=",
+ "dev": true,
+ "peer": true,
+ "dependencies": {
+ "is-extendable": "^0.1.0"
+ },
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
+ "node_modules/sane/node_modules/cross-spawn": {
+ "version": "6.0.5",
+ "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-6.0.5.tgz",
+ "integrity": "sha512-eTVLrBSt7fjbDygz805pMnstIs2VTBNkRm0qxZd+M7A5XDdxVRWO5MxGBXZhjY4cqLYLdtrGqRf8mBPmzwSpWQ==",
+ "dev": true,
+ "peer": true,
+ "dependencies": {
+ "nice-try": "^1.0.4",
+ "path-key": "^2.0.1",
+ "semver": "^5.5.0",
+ "shebang-command": "^1.2.0",
+ "which": "^1.2.9"
+ },
+ "engines": {
+ "node": ">=4.8"
+ }
+ },
+ "node_modules/sane/node_modules/execa": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/execa/-/execa-1.0.0.tgz",
+ "integrity": "sha512-adbxcyWV46qiHyvSp50TKt05tB4tK3HcmF7/nxfAdhnox83seTDbwnaqKO4sXRy7roHAIFqJP/Rw/AuEbX61LA==",
+ "dev": true,
+ "peer": true,
+ "dependencies": {
+ "cross-spawn": "^6.0.0",
+ "get-stream": "^4.0.0",
+ "is-stream": "^1.1.0",
+ "npm-run-path": "^2.0.0",
+ "p-finally": "^1.0.0",
+ "signal-exit": "^3.0.0",
+ "strip-eof": "^1.0.0"
+ },
+ "engines": {
+ "node": ">=6"
+ }
+ },
+ "node_modules/sane/node_modules/fill-range": {
+ "version": "4.0.0",
+ "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-4.0.0.tgz",
+ "integrity": "sha1-1USBHUKPmOsGpj3EAtJAPDKMOPc=",
+ "dev": true,
+ "peer": true,
+ "dependencies": {
+ "extend-shallow": "^2.0.1",
+ "is-number": "^3.0.0",
+ "repeat-string": "^1.6.1",
+ "to-regex-range": "^2.1.0"
+ },
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
+ "node_modules/sane/node_modules/fill-range/node_modules/extend-shallow": {
+ "version": "2.0.1",
+ "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz",
+ "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=",
+ "dev": true,
+ "peer": true,
+ "dependencies": {
+ "is-extendable": "^0.1.0"
+ },
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
+ "node_modules/sane/node_modules/get-stream": {
+ "version": "4.1.0",
+ "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-4.1.0.tgz",
+ "integrity": "sha512-GMat4EJ5161kIy2HevLlr4luNjBgvmj413KaQA7jt4V8B4RDsfpHk7WQ9GVqfYyyx8OS/L66Kox+rJRNklLK7w==",
+ "dev": true,
+ "peer": true,
+ "dependencies": {
+ "pump": "^3.0.0"
+ },
+ "engines": {
+ "node": ">=6"
+ }
+ },
+ "node_modules/sane/node_modules/is-buffer": {
+ "version": "1.1.6",
+ "resolved": "https://registry.npmjs.org/is-buffer/-/is-buffer-1.1.6.tgz",
+ "integrity": "sha512-NcdALwpXkTm5Zvvbk7owOUSvVvBKDgKP5/ewfXEznmQFfs4ZRmanOeKBTjRVjka3QFoN6XJ+9F3USqfHqTaU5w==",
+ "dev": true,
+ "peer": true
+ },
+ "node_modules/sane/node_modules/is-extendable": {
+ "version": "0.1.1",
+ "resolved": "https://registry.npmjs.org/is-extendable/-/is-extendable-0.1.1.tgz",
+ "integrity": "sha1-YrEQ4omkcUGOPsNqYX1HLjAd/Ik=",
+ "dev": true,
+ "peer": true,
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
+ "node_modules/sane/node_modules/is-number": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/is-number/-/is-number-3.0.0.tgz",
+ "integrity": "sha1-JP1iAaR4LPUFYcgQJ2r8fRLXEZU=",
+ "dev": true,
+ "peer": true,
+ "dependencies": {
+ "kind-of": "^3.0.2"
+ },
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
+ "node_modules/sane/node_modules/is-number/node_modules/kind-of": {
+ "version": "3.2.2",
+ "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz",
+ "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=",
+ "dev": true,
+ "peer": true,
+ "dependencies": {
+ "is-buffer": "^1.1.5"
+ },
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
+ "node_modules/sane/node_modules/is-stream": {
+ "version": "1.1.0",
+ "resolved": "https://registry.npmjs.org/is-stream/-/is-stream-1.1.0.tgz",
+ "integrity": "sha1-EtSj3U5o4Lec6428hBc66A2RykQ=",
+ "dev": true,
+ "peer": true,
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
+ "node_modules/sane/node_modules/micromatch": {
+ "version": "3.1.10",
+ "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-3.1.10.tgz",
+ "integrity": "sha512-MWikgl9n9M3w+bpsY3He8L+w9eF9338xRl8IAO5viDizwSzziFEyUzo2xrrloB64ADbTf8uA8vRqqttDTOmccg==",
+ "dev": true,
+ "peer": true,
+ "dependencies": {
+ "arr-diff": "^4.0.0",
+ "array-unique": "^0.3.2",
+ "braces": "^2.3.1",
+ "define-property": "^2.0.2",
+ "extend-shallow": "^3.0.2",
+ "extglob": "^2.0.4",
+ "fragment-cache": "^0.2.1",
+ "kind-of": "^6.0.2",
+ "nanomatch": "^1.2.9",
+ "object.pick": "^1.3.0",
+ "regex-not": "^1.0.0",
+ "snapdragon": "^0.8.1",
+ "to-regex": "^3.0.2"
+ },
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
+ "node_modules/sane/node_modules/normalize-path": {
+ "version": "2.1.1",
+ "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-2.1.1.tgz",
+ "integrity": "sha1-GrKLVW4Zg2Oowab35vogE3/mrtk=",
+ "dev": true,
+ "peer": true,
+ "dependencies": {
+ "remove-trailing-separator": "^1.0.1"
+ },
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
+ "node_modules/sane/node_modules/npm-run-path": {
+ "version": "2.0.2",
+ "resolved": "https://registry.npmjs.org/npm-run-path/-/npm-run-path-2.0.2.tgz",
+ "integrity": "sha1-NakjLfo11wZ7TLLd8jV7GHFTbF8=",
+ "dev": true,
+ "peer": true,
+ "dependencies": {
+ "path-key": "^2.0.0"
+ },
+ "engines": {
+ "node": ">=4"
+ }
+ },
+ "node_modules/sane/node_modules/path-key": {
+ "version": "2.0.1",
+ "resolved": "https://registry.npmjs.org/path-key/-/path-key-2.0.1.tgz",
+ "integrity": "sha1-QRyttXTFoUDTpLGRDUDYDMn0C0A=",
+ "dev": true,
+ "peer": true,
+ "engines": {
+ "node": ">=4"
+ }
+ },
+ "node_modules/sane/node_modules/semver": {
+ "version": "5.7.1",
+ "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz",
+ "integrity": "sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==",
+ "dev": true,
+ "peer": true,
+ "bin": {
+ "semver": "bin/semver"
+ }
+ },
+ "node_modules/sane/node_modules/shebang-command": {
+ "version": "1.2.0",
+ "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-1.2.0.tgz",
+ "integrity": "sha1-RKrGW2lbAzmJaMOfNj/uXer98eo=",
+ "dev": true,
+ "peer": true,
+ "dependencies": {
+ "shebang-regex": "^1.0.0"
+ },
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
+ "node_modules/sane/node_modules/shebang-regex": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-1.0.0.tgz",
+ "integrity": "sha1-2kL0l0DAtC2yypcoVxyxkMmO/qM=",
+ "dev": true,
+ "peer": true,
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
+ "node_modules/sane/node_modules/to-regex-range": {
+ "version": "2.1.1",
+ "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-2.1.1.tgz",
+ "integrity": "sha1-fIDBe53+vlmeJzZ+DU3VWQFB2zg=",
+ "dev": true,
+ "peer": true,
+ "dependencies": {
+ "is-number": "^3.0.0",
+ "repeat-string": "^1.6.1"
+ },
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
+ "node_modules/sane/node_modules/which": {
+ "version": "1.3.1",
+ "resolved": "https://registry.npmjs.org/which/-/which-1.3.1.tgz",
+ "integrity": "sha512-HxJdYWq1MTIQbJ3nw0cqssHoTNU267KlrDuGZ1WYlxDStUtKUhOaJmh112/TZmHxxUfuJqPXSOm7tDyas0OSIQ==",
+ "dev": true,
+ "peer": true,
+ "dependencies": {
+ "isexe": "^2.0.0"
+ },
+ "bin": {
+ "which": "bin/which"
+ }
+ },
+ "node_modules/saxes": {
+ "version": "5.0.1",
+ "resolved": "https://registry.npmjs.org/saxes/-/saxes-5.0.1.tgz",
+ "integrity": "sha512-5LBh1Tls8c9xgGjw3QrMwETmTMVk0oFgvrFSvWx62llR2hcEInrKNZ2GZCCuuy2lvWrdl5jhbpeqc5hRYKFOcw==",
+ "dev": true,
+ "peer": true,
+ "dependencies": {
+ "xmlchars": "^2.2.0"
+ },
+ "engines": {
+ "node": ">=10"
+ }
+ },
+ "node_modules/scheduler": {
+ "version": "0.21.0",
+ "resolved": "https://registry.npmjs.org/scheduler/-/scheduler-0.21.0.tgz",
+ "integrity": "sha512-1r87x5fz9MXqswA2ERLo0EbOAU74DpIUO090gIasYTqlVoJeMcl+Z1Rg7WHz+qtPujhS/hGIt9kxZOYBV3faRQ==",
+ "dev": true,
+ "peer": true,
+ "dependencies": {
+ "loose-envify": "^1.1.0"
+ }
+ },
+ "node_modules/semver": {
+ "version": "7.3.7",
+ "resolved": "https://registry.npmjs.org/semver/-/semver-7.3.7.tgz",
+ "integrity": "sha512-QlYTucUYOews+WeEujDoEGziz4K6c47V/Bd+LjSSYcA94p+DmINdf7ncaUinThfvZyu13lN9OY1XDxt8C0Tw0g==",
+ "dev": true,
+ "dependencies": {
+ "lru-cache": "^6.0.0"
+ },
+ "bin": {
+ "semver": "bin/semver.js"
+ },
+ "engines": {
+ "node": ">=10"
+ }
+ },
+ "node_modules/semver-compare": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/semver-compare/-/semver-compare-1.0.0.tgz",
+ "integrity": "sha1-De4hahyUGrN+nvsXiPavxf9VN/w=",
+ "dev": true
+ },
+ "node_modules/semver-regex": {
+ "version": "3.1.4",
+ "resolved": "https://registry.npmjs.org/semver-regex/-/semver-regex-3.1.4.tgz",
+ "integrity": "sha512-6IiqeZNgq01qGf0TId0t3NvKzSvUsjcpdEO3AQNeIjR6A2+ckTnQlDpl4qu1bjRv0RzN3FP9hzFmws3lKqRWkA==",
+ "dev": true,
+ "engines": {
+ "node": ">=8"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
+ "node_modules/set-blocking": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/set-blocking/-/set-blocking-2.0.0.tgz",
+ "integrity": "sha1-BF+XgtARrppoA93TgrJDkrPYkPc=",
+ "dev": true,
+ "peer": true
+ },
+ "node_modules/set-value": {
+ "version": "2.0.1",
+ "resolved": "https://registry.npmjs.org/set-value/-/set-value-2.0.1.tgz",
+ "integrity": "sha512-JxHc1weCN68wRY0fhCoXpyK55m/XPHafOmK4UWD7m2CI14GMcFypt4w/0+NV5f/ZMby2F6S2wwA7fgynh9gWSw==",
+ "dev": true,
+ "peer": true,
+ "dependencies": {
+ "extend-shallow": "^2.0.1",
+ "is-extendable": "^0.1.1",
+ "is-plain-object": "^2.0.3",
+ "split-string": "^3.0.1"
+ },
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
+ "node_modules/set-value/node_modules/extend-shallow": {
+ "version": "2.0.1",
+ "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz",
+ "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=",
+ "dev": true,
+ "peer": true,
+ "dependencies": {
+ "is-extendable": "^0.1.0"
+ },
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
+ "node_modules/set-value/node_modules/is-extendable": {
+ "version": "0.1.1",
+ "resolved": "https://registry.npmjs.org/is-extendable/-/is-extendable-0.1.1.tgz",
+ "integrity": "sha1-YrEQ4omkcUGOPsNqYX1HLjAd/Ik=",
+ "dev": true,
+ "peer": true,
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
+ "node_modules/shebang-command": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-2.0.0.tgz",
+ "integrity": "sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==",
+ "dev": true,
+ "dependencies": {
+ "shebang-regex": "^3.0.0"
+ },
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/shebang-regex": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-3.0.0.tgz",
+ "integrity": "sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==",
+ "dev": true,
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/shellwords": {
+ "version": "0.1.1",
+ "resolved": "https://registry.npmjs.org/shellwords/-/shellwords-0.1.1.tgz",
+ "integrity": "sha512-vFwSUfQvqybiICwZY5+DAWIPLKsWO31Q91JSKl3UYv+K5c2QRPzn0qzec6QPu1Qc9eHYItiP3NdJqNVqetYAww==",
+ "dev": true,
+ "optional": true,
+ "peer": true
+ },
+ "node_modules/side-channel": {
+ "version": "1.0.4",
+ "resolved": "https://registry.npmjs.org/side-channel/-/side-channel-1.0.4.tgz",
+ "integrity": "sha512-q5XPytqFEIKHkGdiMIrY10mvLRvnQh42/+GoBlFW3b2LXLE2xxJpZFdm94we0BaoV3RwJyGqg5wS7epxTv0Zvw==",
+ "dev": true,
+ "dependencies": {
+ "call-bind": "^1.0.0",
+ "get-intrinsic": "^1.0.2",
+ "object-inspect": "^1.9.0"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/signal-exit": {
+ "version": "3.0.7",
+ "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.7.tgz",
+ "integrity": "sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ==",
+ "dev": true
+ },
+ "node_modules/signale": {
+ "version": "1.4.0",
+ "resolved": "https://registry.npmjs.org/signale/-/signale-1.4.0.tgz",
+ "integrity": "sha512-iuh+gPf28RkltuJC7W5MRi6XAjTDCAPC/prJUpQoG4vIP3MJZ+GTydVnodXA7pwvTKb2cA0m9OFZW/cdWy/I/w==",
+ "dev": true,
+ "dependencies": {
+ "chalk": "^2.3.2",
+ "figures": "^2.0.0",
+ "pkg-conf": "^2.1.0"
+ },
+ "engines": {
+ "node": ">=6"
+ }
+ },
+ "node_modules/signale/node_modules/ansi-styles": {
+ "version": "3.2.1",
+ "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz",
+ "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==",
+ "dev": true,
+ "dependencies": {
+ "color-convert": "^1.9.0"
+ },
+ "engines": {
+ "node": ">=4"
+ }
+ },
+ "node_modules/signale/node_modules/chalk": {
+ "version": "2.4.2",
+ "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz",
+ "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==",
+ "dev": true,
+ "dependencies": {
+ "ansi-styles": "^3.2.1",
+ "escape-string-regexp": "^1.0.5",
+ "supports-color": "^5.3.0"
+ },
+ "engines": {
+ "node": ">=4"
+ }
+ },
+ "node_modules/signale/node_modules/color-convert": {
+ "version": "1.9.3",
+ "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz",
+ "integrity": "sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==",
+ "dev": true,
+ "dependencies": {
+ "color-name": "1.1.3"
+ }
+ },
+ "node_modules/signale/node_modules/color-name": {
+ "version": "1.1.3",
+ "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz",
+ "integrity": "sha1-p9BVi9icQveV3UIyj3QIMcpTvCU=",
+ "dev": true
+ },
+ "node_modules/signale/node_modules/figures": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/figures/-/figures-2.0.0.tgz",
+ "integrity": "sha1-OrGi0qYsi/tDGgyUy3l6L84nyWI=",
+ "dev": true,
+ "dependencies": {
+ "escape-string-regexp": "^1.0.5"
+ },
+ "engines": {
+ "node": ">=4"
+ }
+ },
+ "node_modules/signale/node_modules/has-flag": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz",
+ "integrity": "sha1-tdRU3CGZriJWmfNGfloH87lVuv0=",
+ "dev": true,
+ "engines": {
+ "node": ">=4"
+ }
+ },
+ "node_modules/signale/node_modules/supports-color": {
+ "version": "5.5.0",
+ "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz",
+ "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==",
+ "dev": true,
+ "dependencies": {
+ "has-flag": "^3.0.0"
+ },
+ "engines": {
+ "node": ">=4"
+ }
+ },
+ "node_modules/sisteransi": {
+ "version": "1.0.5",
+ "resolved": "https://registry.npmjs.org/sisteransi/-/sisteransi-1.0.5.tgz",
+ "integrity": "sha512-bLGGlR1QxBcynn2d5YmDX4MGjlZvy2MRBDRNHLJ8VI6l6+9FUiyTFNJ0IveOSP0bcXgVDPRcfGqA0pjaqUpfVg==",
+ "dev": true,
+ "peer": true
+ },
+ "node_modules/slash": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/slash/-/slash-3.0.0.tgz",
+ "integrity": "sha512-g9Q1haeby36OSStwb4ntCGGGaKsaVSjQ68fBxoQcutl5fS1vuY18H3wSt3jFyFtrkx+Kz0V1G85A4MyAdDMi2Q==",
+ "dev": true,
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/slice-ansi": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/slice-ansi/-/slice-ansi-3.0.0.tgz",
+ "integrity": "sha512-pSyv7bSTC7ig9Dcgbw9AuRNUb5k5V6oDudjZoMBSr13qpLBG7tB+zgCkARjq7xIUgdz5P1Qe8u+rSGdouOOIyQ==",
+ "dev": true,
+ "dependencies": {
+ "ansi-styles": "^4.0.0",
+ "astral-regex": "^2.0.0",
+ "is-fullwidth-code-point": "^3.0.0"
+ },
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/slugify": {
+ "version": "1.4.6",
+ "resolved": "https://registry.npmjs.org/slugify/-/slugify-1.4.6.tgz",
+ "integrity": "sha512-ZdJIgv9gdrYwhXqxsH9pv7nXxjUEyQ6nqhngRxoAAOlmMGA28FDq5O4/5US4G2/Nod7d1ovNcgURQJ7kHq50KQ==",
+ "dev": true,
+ "engines": {
+ "node": ">=8.0.0"
+ }
+ },
+ "node_modules/snapdragon": {
+ "version": "0.8.2",
+ "resolved": "https://registry.npmjs.org/snapdragon/-/snapdragon-0.8.2.tgz",
+ "integrity": "sha512-FtyOnWN/wCHTVXOMwvSv26d+ko5vWlIDD6zoUJ7LW8vh+ZBC8QdljveRP+crNrtBwioEUWy/4dMtbBjA4ioNlg==",
+ "dev": true,
+ "peer": true,
+ "dependencies": {
+ "base": "^0.11.1",
+ "debug": "^2.2.0",
+ "define-property": "^0.2.5",
+ "extend-shallow": "^2.0.1",
+ "map-cache": "^0.2.2",
+ "source-map": "^0.5.6",
+ "source-map-resolve": "^0.5.0",
+ "use": "^3.1.0"
+ },
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
+ "node_modules/snapdragon-node": {
+ "version": "2.1.1",
+ "resolved": "https://registry.npmjs.org/snapdragon-node/-/snapdragon-node-2.1.1.tgz",
+ "integrity": "sha512-O27l4xaMYt/RSQ5TR3vpWCAB5Kb/czIcqUFOM/C4fYcLnbZUc1PkjTAMjof2pBWaSTwOUd6qUHcFGVGj7aIwnw==",
+ "dev": true,
+ "peer": true,
+ "dependencies": {
+ "define-property": "^1.0.0",
+ "isobject": "^3.0.0",
+ "snapdragon-util": "^3.0.1"
+ },
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
+ "node_modules/snapdragon-node/node_modules/define-property": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/define-property/-/define-property-1.0.0.tgz",
+ "integrity": "sha1-dp66rz9KY6rTr56NMEybvnm/sOY=",
+ "dev": true,
+ "peer": true,
+ "dependencies": {
+ "is-descriptor": "^1.0.0"
+ },
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
+ "node_modules/snapdragon-util": {
+ "version": "3.0.1",
+ "resolved": "https://registry.npmjs.org/snapdragon-util/-/snapdragon-util-3.0.1.tgz",
+ "integrity": "sha512-mbKkMdQKsjX4BAL4bRYTj21edOf8cN7XHdYUJEe+Zn99hVEYcMvKPct1IqNe7+AZPirn8BCDOQBHQZknqmKlZQ==",
+ "dev": true,
+ "peer": true,
+ "dependencies": {
+ "kind-of": "^3.2.0"
+ },
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
+ "node_modules/snapdragon-util/node_modules/is-buffer": {
+ "version": "1.1.6",
+ "resolved": "https://registry.npmjs.org/is-buffer/-/is-buffer-1.1.6.tgz",
+ "integrity": "sha512-NcdALwpXkTm5Zvvbk7owOUSvVvBKDgKP5/ewfXEznmQFfs4ZRmanOeKBTjRVjka3QFoN6XJ+9F3USqfHqTaU5w==",
+ "dev": true,
+ "peer": true
+ },
+ "node_modules/snapdragon-util/node_modules/kind-of": {
+ "version": "3.2.2",
+ "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz",
+ "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=",
+ "dev": true,
+ "peer": true,
+ "dependencies": {
+ "is-buffer": "^1.1.5"
+ },
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
+ "node_modules/snapdragon/node_modules/debug": {
+ "version": "2.6.9",
+ "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz",
+ "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==",
+ "dev": true,
+ "peer": true,
+ "dependencies": {
+ "ms": "2.0.0"
+ }
+ },
+ "node_modules/snapdragon/node_modules/define-property": {
+ "version": "0.2.5",
+ "resolved": "https://registry.npmjs.org/define-property/-/define-property-0.2.5.tgz",
+ "integrity": "sha1-w1se+RjsPJkPmlvFe+BKrOxcgRY=",
+ "dev": true,
+ "peer": true,
+ "dependencies": {
+ "is-descriptor": "^0.1.0"
+ },
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
+ "node_modules/snapdragon/node_modules/extend-shallow": {
+ "version": "2.0.1",
+ "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz",
+ "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=",
+ "dev": true,
+ "peer": true,
+ "dependencies": {
+ "is-extendable": "^0.1.0"
+ },
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
+ "node_modules/snapdragon/node_modules/is-accessor-descriptor": {
+ "version": "0.1.6",
+ "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-0.1.6.tgz",
+ "integrity": "sha1-qeEss66Nh2cn7u84Q/igiXtcmNY=",
+ "dev": true,
+ "peer": true,
+ "dependencies": {
+ "kind-of": "^3.0.2"
+ },
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
+ "node_modules/snapdragon/node_modules/is-accessor-descriptor/node_modules/kind-of": {
+ "version": "3.2.2",
+ "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz",
+ "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=",
+ "dev": true,
+ "peer": true,
+ "dependencies": {
+ "is-buffer": "^1.1.5"
+ },
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
+ "node_modules/snapdragon/node_modules/is-buffer": {
+ "version": "1.1.6",
+ "resolved": "https://registry.npmjs.org/is-buffer/-/is-buffer-1.1.6.tgz",
+ "integrity": "sha512-NcdALwpXkTm5Zvvbk7owOUSvVvBKDgKP5/ewfXEznmQFfs4ZRmanOeKBTjRVjka3QFoN6XJ+9F3USqfHqTaU5w==",
+ "dev": true,
+ "peer": true
+ },
+ "node_modules/snapdragon/node_modules/is-data-descriptor": {
+ "version": "0.1.4",
+ "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-0.1.4.tgz",
+ "integrity": "sha1-C17mSDiOLIYCgueT8YVv7D8wG1Y=",
+ "dev": true,
+ "peer": true,
+ "dependencies": {
+ "kind-of": "^3.0.2"
+ },
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
+ "node_modules/snapdragon/node_modules/is-data-descriptor/node_modules/kind-of": {
+ "version": "3.2.2",
+ "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz",
+ "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=",
+ "dev": true,
+ "peer": true,
+ "dependencies": {
+ "is-buffer": "^1.1.5"
+ },
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
+ "node_modules/snapdragon/node_modules/is-descriptor": {
+ "version": "0.1.6",
+ "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-0.1.6.tgz",
+ "integrity": "sha512-avDYr0SB3DwO9zsMov0gKCESFYqCnE4hq/4z3TdUlukEy5t9C0YRq7HLrsN52NAcqXKaepeCD0n+B0arnVG3Hg==",
+ "dev": true,
+ "peer": true,
+ "dependencies": {
+ "is-accessor-descriptor": "^0.1.6",
+ "is-data-descriptor": "^0.1.4",
+ "kind-of": "^5.0.0"
+ },
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
+ "node_modules/snapdragon/node_modules/is-extendable": {
+ "version": "0.1.1",
+ "resolved": "https://registry.npmjs.org/is-extendable/-/is-extendable-0.1.1.tgz",
+ "integrity": "sha1-YrEQ4omkcUGOPsNqYX1HLjAd/Ik=",
+ "dev": true,
+ "peer": true,
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
+ "node_modules/snapdragon/node_modules/kind-of": {
+ "version": "5.1.0",
+ "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-5.1.0.tgz",
+ "integrity": "sha512-NGEErnH6F2vUuXDh+OlbcKW7/wOcfdRHaZ7VWtqCztfHri/++YKmP51OdWeGPuqCOba6kk2OTe5d02VmTB80Pw==",
+ "dev": true,
+ "peer": true,
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
+ "node_modules/snapdragon/node_modules/ms": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz",
+ "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=",
+ "dev": true,
+ "peer": true
+ },
+ "node_modules/snapdragon/node_modules/source-map": {
+ "version": "0.5.7",
+ "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz",
+ "integrity": "sha1-igOdLRAh0i0eoUyA2OpGi6LvP8w=",
+ "dev": true,
+ "peer": true,
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
+ "node_modules/source-map": {
+ "version": "0.6.1",
+ "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz",
+ "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==",
+ "dev": true,
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
+ "node_modules/source-map-js": {
+ "version": "1.0.2",
+ "resolved": "https://registry.npmjs.org/source-map-js/-/source-map-js-1.0.2.tgz",
+ "integrity": "sha512-R0XvVJ9WusLiqTCEiGCmICCMplcCkIwwR11mOSD9CR5u+IXYdiseeEuXCVAjS54zqwkLcPNnmU4OeJ6tUrWhDw==",
+ "dev": true,
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
+ "node_modules/source-map-resolve": {
+ "version": "0.5.3",
+ "resolved": "https://registry.npmjs.org/source-map-resolve/-/source-map-resolve-0.5.3.tgz",
+ "integrity": "sha512-Htz+RnsXWk5+P2slx5Jh3Q66vhQj1Cllm0zvnaY98+NFx+Dv2CF/f5O/t8x+KaNdrdIAsruNzoh/KpialbqAnw==",
+ "deprecated": "See https://github.com/lydell/source-map-resolve#deprecated",
+ "dev": true,
+ "peer": true,
+ "dependencies": {
+ "atob": "^2.1.2",
+ "decode-uri-component": "^0.2.0",
+ "resolve-url": "^0.2.1",
+ "source-map-url": "^0.4.0",
+ "urix": "^0.1.0"
+ }
+ },
+ "node_modules/source-map-support": {
+ "version": "0.5.21",
+ "resolved": "https://registry.npmjs.org/source-map-support/-/source-map-support-0.5.21.tgz",
+ "integrity": "sha512-uBHU3L3czsIyYXKX88fdrGovxdSCoTGDRZ6SYXtSRxLZUzHg5P/66Ht6uoUlHu9EZod+inXhKo3qQgwXUT/y1w==",
+ "dev": true,
+ "peer": true,
+ "dependencies": {
+ "buffer-from": "^1.0.0",
+ "source-map": "^0.6.0"
+ }
+ },
+ "node_modules/source-map-url": {
+ "version": "0.4.1",
+ "resolved": "https://registry.npmjs.org/source-map-url/-/source-map-url-0.4.1.tgz",
+ "integrity": "sha512-cPiFOTLUKvJFIg4SKVScy4ilPPW6rFgMgfuZJPNoDuMs3nC1HbMUycBoJw77xFIp6z1UJQJOfx6C9GMH80DiTw==",
+ "deprecated": "See https://github.com/lydell/source-map-url#deprecated",
+ "dev": true,
+ "peer": true
+ },
+ "node_modules/spdx-correct": {
+ "version": "3.1.1",
+ "resolved": "https://registry.npmjs.org/spdx-correct/-/spdx-correct-3.1.1.tgz",
+ "integrity": "sha512-cOYcUWwhCuHCXi49RhFRCyJEK3iPj1Ziz9DpViV3tbZOwXD49QzIN3MpOLJNxh2qwq2lJJZaKMVw9qNi4jTC0w==",
+ "dev": true,
+ "dependencies": {
+ "spdx-expression-parse": "^3.0.0",
+ "spdx-license-ids": "^3.0.0"
+ }
+ },
+ "node_modules/spdx-exceptions": {
+ "version": "2.3.0",
+ "resolved": "https://registry.npmjs.org/spdx-exceptions/-/spdx-exceptions-2.3.0.tgz",
+ "integrity": "sha512-/tTrYOC7PPI1nUAgx34hUpqXuyJG+DTHJTnIULG4rDygi4xu/tfgmq1e1cIRwRzwZgo4NLySi+ricLkZkw4i5A==",
+ "dev": true
+ },
+ "node_modules/spdx-expression-parse": {
+ "version": "3.0.1",
+ "resolved": "https://registry.npmjs.org/spdx-expression-parse/-/spdx-expression-parse-3.0.1.tgz",
+ "integrity": "sha512-cbqHunsQWnJNE6KhVSMsMeH5H/L9EpymbzqTQ3uLwNCLZ1Q481oWaofqH7nO6V07xlXwY6PhQdQ2IedWx/ZK4Q==",
+ "dev": true,
+ "dependencies": {
+ "spdx-exceptions": "^2.1.0",
+ "spdx-license-ids": "^3.0.0"
+ }
+ },
+ "node_modules/spdx-license-ids": {
+ "version": "3.0.11",
+ "resolved": "https://registry.npmjs.org/spdx-license-ids/-/spdx-license-ids-3.0.11.tgz",
+ "integrity": "sha512-Ctl2BrFiM0X3MANYgj3CkygxhRmr9mi6xhejbdO960nF6EDJApTYpn0BQnDKlnNBULKiCN1n3w9EBkHK8ZWg+g==",
+ "dev": true
+ },
+ "node_modules/specificity": {
+ "version": "0.4.1",
+ "resolved": "https://registry.npmjs.org/specificity/-/specificity-0.4.1.tgz",
+ "integrity": "sha512-1klA3Gi5PD1Wv9Q0wUoOQN1IWAuPu0D1U03ThXTr0cJ20+/iq2tHSDnK7Kk/0LXJ1ztUB2/1Os0wKmfyNgUQfg==",
+ "dev": true,
+ "bin": {
+ "specificity": "bin/specificity"
+ }
+ },
+ "node_modules/split-string": {
+ "version": "3.1.0",
+ "resolved": "https://registry.npmjs.org/split-string/-/split-string-3.1.0.tgz",
+ "integrity": "sha512-NzNVhJDYpwceVVii8/Hu6DKfD2G+NrQHlS/V/qgv763EYudVwEcMQNxd2lh+0VrUByXN/oJkl5grOhYWvQUYiw==",
+ "dev": true,
+ "peer": true,
+ "dependencies": {
+ "extend-shallow": "^3.0.0"
+ },
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
+ "node_modules/sprintf-js": {
+ "version": "1.0.3",
+ "resolved": "https://registry.npmjs.org/sprintf-js/-/sprintf-js-1.0.3.tgz",
+ "integrity": "sha1-BOaSb2YolTVPPdAVIDYzuFcpfiw=",
+ "dev": true,
+ "peer": true
+ },
+ "node_modules/stack-utils": {
+ "version": "2.0.5",
+ "resolved": "https://registry.npmjs.org/stack-utils/-/stack-utils-2.0.5.tgz",
+ "integrity": "sha512-xrQcmYhOsn/1kX+Vraq+7j4oE2j/6BFscZ0etmYg81xuM8Gq0022Pxb8+IqgOFUIaxHs0KaSb7T1+OegiNrNFA==",
+ "dev": true,
+ "peer": true,
+ "dependencies": {
+ "escape-string-regexp": "^2.0.0"
+ },
+ "engines": {
+ "node": ">=10"
+ }
+ },
+ "node_modules/stack-utils/node_modules/escape-string-regexp": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-2.0.0.tgz",
+ "integrity": "sha512-UpzcLCXolUWcNu5HtVMHYdXJjArjsF9C0aNnquZYY4uW/Vu0miy5YoWvbV345HauVvcAUnpRuhMMcqTcGOY2+w==",
+ "dev": true,
+ "peer": true,
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/state-toggle": {
+ "version": "1.0.3",
+ "resolved": "https://registry.npmjs.org/state-toggle/-/state-toggle-1.0.3.tgz",
+ "integrity": "sha512-d/5Z4/2iiCnHw6Xzghyhb+GcmF89bxwgXG60wjIiZaxnymbyOmI8Hk4VqHXiVVp6u2ysaskFfXg3ekCj4WNftQ==",
+ "dev": true,
+ "funding": {
+ "type": "github",
+ "url": "https://github.com/sponsors/wooorm"
+ }
+ },
+ "node_modules/static-extend": {
+ "version": "0.1.2",
+ "resolved": "https://registry.npmjs.org/static-extend/-/static-extend-0.1.2.tgz",
+ "integrity": "sha1-YICcOcv/VTNyJv1eC1IPNB8ftcY=",
+ "dev": true,
+ "peer": true,
+ "dependencies": {
+ "define-property": "^0.2.5",
+ "object-copy": "^0.1.0"
+ },
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
+ "node_modules/static-extend/node_modules/define-property": {
+ "version": "0.2.5",
+ "resolved": "https://registry.npmjs.org/define-property/-/define-property-0.2.5.tgz",
+ "integrity": "sha1-w1se+RjsPJkPmlvFe+BKrOxcgRY=",
+ "dev": true,
+ "peer": true,
+ "dependencies": {
+ "is-descriptor": "^0.1.0"
+ },
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
+ "node_modules/static-extend/node_modules/is-accessor-descriptor": {
+ "version": "0.1.6",
+ "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-0.1.6.tgz",
+ "integrity": "sha1-qeEss66Nh2cn7u84Q/igiXtcmNY=",
+ "dev": true,
+ "peer": true,
+ "dependencies": {
+ "kind-of": "^3.0.2"
+ },
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
+ "node_modules/static-extend/node_modules/is-accessor-descriptor/node_modules/kind-of": {
+ "version": "3.2.2",
+ "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz",
+ "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=",
+ "dev": true,
+ "peer": true,
+ "dependencies": {
+ "is-buffer": "^1.1.5"
+ },
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
+ "node_modules/static-extend/node_modules/is-buffer": {
+ "version": "1.1.6",
+ "resolved": "https://registry.npmjs.org/is-buffer/-/is-buffer-1.1.6.tgz",
+ "integrity": "sha512-NcdALwpXkTm5Zvvbk7owOUSvVvBKDgKP5/ewfXEznmQFfs4ZRmanOeKBTjRVjka3QFoN6XJ+9F3USqfHqTaU5w==",
+ "dev": true,
+ "peer": true
+ },
+ "node_modules/static-extend/node_modules/is-data-descriptor": {
+ "version": "0.1.4",
+ "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-0.1.4.tgz",
+ "integrity": "sha1-C17mSDiOLIYCgueT8YVv7D8wG1Y=",
+ "dev": true,
+ "peer": true,
+ "dependencies": {
+ "kind-of": "^3.0.2"
+ },
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
+ "node_modules/static-extend/node_modules/is-data-descriptor/node_modules/kind-of": {
+ "version": "3.2.2",
+ "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz",
+ "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=",
+ "dev": true,
+ "peer": true,
+ "dependencies": {
+ "is-buffer": "^1.1.5"
+ },
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
+ "node_modules/static-extend/node_modules/is-descriptor": {
+ "version": "0.1.6",
+ "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-0.1.6.tgz",
+ "integrity": "sha512-avDYr0SB3DwO9zsMov0gKCESFYqCnE4hq/4z3TdUlukEy5t9C0YRq7HLrsN52NAcqXKaepeCD0n+B0arnVG3Hg==",
+ "dev": true,
+ "peer": true,
+ "dependencies": {
+ "is-accessor-descriptor": "^0.1.6",
+ "is-data-descriptor": "^0.1.4",
+ "kind-of": "^5.0.0"
+ },
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
+ "node_modules/static-extend/node_modules/kind-of": {
+ "version": "5.1.0",
+ "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-5.1.0.tgz",
+ "integrity": "sha512-NGEErnH6F2vUuXDh+OlbcKW7/wOcfdRHaZ7VWtqCztfHri/++YKmP51OdWeGPuqCOba6kk2OTe5d02VmTB80Pw==",
+ "dev": true,
+ "peer": true,
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
+ "node_modules/stop-iteration-iterator": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/stop-iteration-iterator/-/stop-iteration-iterator-1.0.0.tgz",
+ "integrity": "sha512-iCGQj+0l0HOdZ2AEeBADlsRC+vsnDsZsbdSiH1yNSjcfKM7fdpCMfqAL/dwF5BLiw/XhRft/Wax6zQbhq2BcjQ==",
+ "dev": true,
+ "dependencies": {
+ "internal-slot": "^1.0.4"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ }
+ },
+ "node_modules/string_decoder": {
+ "version": "1.3.0",
+ "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.3.0.tgz",
+ "integrity": "sha512-hkRX8U1WjJFd8LsDJ2yQ/wWWxaopEsABU1XfkM8A+j0+85JAGppt16cr1Whg6KIbb4okU6Mql6BOj+uup/wKeA==",
+ "dev": true,
+ "dependencies": {
+ "safe-buffer": "~5.2.0"
+ }
+ },
+ "node_modules/string_decoder/node_modules/safe-buffer": {
+ "version": "5.2.1",
+ "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz",
+ "integrity": "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==",
+ "dev": true,
+ "funding": [
+ {
+ "type": "github",
+ "url": "https://github.com/sponsors/feross"
+ },
+ {
+ "type": "patreon",
+ "url": "https://www.patreon.com/feross"
+ },
+ {
+ "type": "consulting",
+ "url": "https://feross.org/support"
+ }
+ ]
+ },
+ "node_modules/string-argv": {
+ "version": "0.3.1",
+ "resolved": "https://registry.npmjs.org/string-argv/-/string-argv-0.3.1.tgz",
+ "integrity": "sha512-a1uQGz7IyVy9YwhqjZIZu1c8JO8dNIe20xBmSS6qu9kv++k3JGzCVmprbNN5Kn+BgzD5E7YYwg1CcjuJMRNsvg==",
+ "dev": true,
+ "engines": {
+ "node": ">=0.6.19"
+ }
+ },
+ "node_modules/string-length": {
+ "version": "4.0.2",
+ "resolved": "https://registry.npmjs.org/string-length/-/string-length-4.0.2.tgz",
+ "integrity": "sha512-+l6rNN5fYHNhZZy41RXsYptCjA2Igmq4EG7kZAYFQI1E1VTXarr6ZPXBg6eq7Y6eK4FEhY6AJlyuFIb/v/S0VQ==",
+ "dev": true,
+ "peer": true,
+ "dependencies": {
+ "char-regex": "^1.0.2",
+ "strip-ansi": "^6.0.0"
+ },
+ "engines": {
+ "node": ">=10"
+ }
+ },
+ "node_modules/string-width": {
+ "version": "4.2.3",
+ "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz",
+ "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==",
+ "dev": true,
+ "dependencies": {
+ "emoji-regex": "^8.0.0",
+ "is-fullwidth-code-point": "^3.0.0",
+ "strip-ansi": "^6.0.1"
+ },
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/string-width/node_modules/emoji-regex": {
+ "version": "8.0.0",
+ "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz",
+ "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==",
+ "dev": true
+ },
+ "node_modules/string.prototype.matchall": {
+ "version": "4.0.8",
+ "resolved": "https://registry.npmjs.org/string.prototype.matchall/-/string.prototype.matchall-4.0.8.tgz",
+ "integrity": "sha512-6zOCOcJ+RJAQshcTvXPHoxoQGONa3e/Lqx90wUA+wEzX78sg5Bo+1tQo4N0pohS0erG9qtCqJDjNCQBjeWVxyg==",
+ "dev": true,
+ "dependencies": {
+ "call-bind": "^1.0.2",
+ "define-properties": "^1.1.4",
+ "es-abstract": "^1.20.4",
+ "get-intrinsic": "^1.1.3",
+ "has-symbols": "^1.0.3",
+ "internal-slot": "^1.0.3",
+ "regexp.prototype.flags": "^1.4.3",
+ "side-channel": "^1.0.4"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/string.prototype.trim": {
+ "version": "1.2.7",
+ "resolved": "https://registry.npmjs.org/string.prototype.trim/-/string.prototype.trim-1.2.7.tgz",
+ "integrity": "sha512-p6TmeT1T3411M8Cgg9wBTMRtY2q9+PNy9EV1i2lIXUN/btt763oIfxwN3RR8VU6wHX8j/1CFy0L+YuThm6bgOg==",
+ "dev": true,
+ "dependencies": {
+ "call-bind": "^1.0.2",
+ "define-properties": "^1.1.4",
+ "es-abstract": "^1.20.4"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/string.prototype.trimend": {
+ "version": "1.0.6",
+ "resolved": "https://registry.npmjs.org/string.prototype.trimend/-/string.prototype.trimend-1.0.6.tgz",
+ "integrity": "sha512-JySq+4mrPf9EsDBEDYMOb/lM7XQLulwg5R/m1r0PXEFqrV0qHvl58sdTilSXtKOflCsK2E8jxf+GKC0T07RWwQ==",
+ "dev": true,
+ "dependencies": {
+ "call-bind": "^1.0.2",
+ "define-properties": "^1.1.4",
+ "es-abstract": "^1.20.4"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/string.prototype.trimstart": {
+ "version": "1.0.6",
+ "resolved": "https://registry.npmjs.org/string.prototype.trimstart/-/string.prototype.trimstart-1.0.6.tgz",
+ "integrity": "sha512-omqjMDaY92pbn5HOX7f9IccLA+U1tA9GvtU4JrodiXFfYB7jPzzHpRzpglLAjtUV6bB557zwClJezTqnAiYnQA==",
+ "dev": true,
+ "dependencies": {
+ "call-bind": "^1.0.2",
+ "define-properties": "^1.1.4",
+ "es-abstract": "^1.20.4"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/stringify-entities": {
+ "version": "3.1.0",
+ "resolved": "https://registry.npmjs.org/stringify-entities/-/stringify-entities-3.1.0.tgz",
+ "integrity": "sha512-3FP+jGMmMV/ffZs86MoghGqAoqXAdxLrJP4GUdrDN1aIScYih5tuIO3eF4To5AJZ79KDZ8Fpdy7QJnK8SsL1Vg==",
+ "dev": true,
+ "dependencies": {
+ "character-entities-html4": "^1.0.0",
+ "character-entities-legacy": "^1.0.0",
+ "xtend": "^4.0.0"
+ },
+ "funding": {
+ "type": "github",
+ "url": "https://github.com/sponsors/wooorm"
+ }
+ },
+ "node_modules/stringify-object": {
+ "version": "3.3.0",
+ "resolved": "https://registry.npmjs.org/stringify-object/-/stringify-object-3.3.0.tgz",
+ "integrity": "sha512-rHqiFh1elqCQ9WPLIC8I0Q/g/wj5J1eMkyoiD6eoQApWHP0FtlK7rqnhmabL5VUY9JQCcqwwvlOaSuutekgyrw==",
+ "dev": true,
+ "dependencies": {
+ "get-own-enumerable-property-symbols": "^3.0.0",
+ "is-obj": "^1.0.1",
+ "is-regexp": "^1.0.0"
+ },
+ "engines": {
+ "node": ">=4"
+ }
+ },
+ "node_modules/strip-ansi": {
+ "version": "6.0.1",
+ "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz",
+ "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==",
+ "dev": true,
+ "dependencies": {
+ "ansi-regex": "^5.0.1"
+ },
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/strip-bom": {
+ "version": "4.0.0",
+ "resolved": "https://registry.npmjs.org/strip-bom/-/strip-bom-4.0.0.tgz",
+ "integrity": "sha512-3xurFv5tEgii33Zi8Jtp55wEIILR9eh34FAW00PZf+JnSsTmV/ioewSgQl97JHvgjoRGwPShsWm+IdrxB35d0w==",
+ "dev": true,
+ "peer": true,
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/strip-eof": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/strip-eof/-/strip-eof-1.0.0.tgz",
+ "integrity": "sha1-u0P/VZim6wXYm1n80SnJgzE2Br8=",
+ "dev": true,
+ "peer": true,
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
+ "node_modules/strip-final-newline": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/strip-final-newline/-/strip-final-newline-2.0.0.tgz",
+ "integrity": "sha512-BrpvfNAE3dcvq7ll3xVumzjKjZQ5tI1sEUIKr3Uoks0XUl45St3FlatVqef9prk4jRDzhW6WZg+3bk93y6pLjA==",
+ "dev": true,
+ "engines": {
+ "node": ">=6"
+ }
+ },
+ "node_modules/strip-indent": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/strip-indent/-/strip-indent-3.0.0.tgz",
+ "integrity": "sha512-laJTa3Jb+VQpaC6DseHhF7dXVqHTfJPCRDaEbid/drOhgitgYku/letMUqOXFoWV0zIIUbjpdH2t+tYj4bQMRQ==",
+ "dev": true,
+ "dependencies": {
+ "min-indent": "^1.0.0"
+ },
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/strip-json-comments": {
+ "version": "3.1.1",
+ "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-3.1.1.tgz",
+ "integrity": "sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig==",
+ "dev": true,
+ "engines": {
+ "node": ">=8"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
+ "node_modules/style-search": {
+ "version": "0.1.0",
+ "resolved": "https://registry.npmjs.org/style-search/-/style-search-0.1.0.tgz",
+ "integrity": "sha1-eVjHk+R+MuB9K1yv5cC/jhLneQI=",
+ "dev": true
+ },
+ "node_modules/styled-jsx": {
+ "version": "5.0.7",
+ "resolved": "https://registry.npmjs.org/styled-jsx/-/styled-jsx-5.0.7.tgz",
+ "integrity": "sha512-b3sUzamS086YLRuvnaDigdAewz1/EFYlHpYBP5mZovKEdQQOIIYq8lApylub3HHZ6xFjV051kkGU7cudJmrXEA==",
+ "dev": true,
+ "engines": {
+ "node": ">= 12.0.0"
+ },
+ "peerDependencies": {
+ "react": ">= 16.8.0 || 17.x.x || ^18.0.0-0"
+ },
+ "peerDependenciesMeta": {
+ "@babel/core": {
+ "optional": true
+ },
+ "babel-plugin-macros": {
+ "optional": true
+ }
+ }
+ },
+ "node_modules/stylelint": {
+ "version": "13.8.0",
+ "resolved": "https://registry.npmjs.org/stylelint/-/stylelint-13.8.0.tgz",
+ "integrity": "sha512-iHH3dv3UI23SLDrH4zMQDjLT9/dDIz/IpoFeuNxZmEx86KtfpjDOscxLTFioQyv+2vQjPlRZnK0UoJtfxLICXQ==",
+ "dev": true,
+ "dependencies": {
+ "@stylelint/postcss-css-in-js": "^0.37.2",
+ "@stylelint/postcss-markdown": "^0.36.2",
+ "autoprefixer": "^9.8.6",
+ "balanced-match": "^1.0.0",
+ "chalk": "^4.1.0",
+ "cosmiconfig": "^7.0.0",
+ "debug": "^4.2.0",
+ "execall": "^2.0.0",
+ "fast-glob": "^3.2.4",
+ "fastest-levenshtein": "^1.0.12",
+ "file-entry-cache": "^6.0.0",
+ "get-stdin": "^8.0.0",
+ "global-modules": "^2.0.0",
+ "globby": "^11.0.1",
+ "globjoin": "^0.1.4",
+ "html-tags": "^3.1.0",
+ "ignore": "^5.1.8",
+ "import-lazy": "^4.0.0",
+ "imurmurhash": "^0.1.4",
+ "known-css-properties": "^0.20.0",
+ "lodash": "^4.17.20",
+ "log-symbols": "^4.0.0",
+ "mathml-tag-names": "^2.1.3",
+ "meow": "^8.0.0",
+ "micromatch": "^4.0.2",
+ "normalize-selector": "^0.2.0",
+ "postcss": "^7.0.35",
+ "postcss-html": "^0.36.0",
+ "postcss-less": "^3.1.4",
+ "postcss-media-query-parser": "^0.2.3",
+ "postcss-resolve-nested-selector": "^0.1.1",
+ "postcss-safe-parser": "^4.0.2",
+ "postcss-sass": "^0.4.4",
+ "postcss-scss": "^2.1.1",
+ "postcss-selector-parser": "^6.0.4",
+ "postcss-syntax": "^0.36.2",
+ "postcss-value-parser": "^4.1.0",
+ "resolve-from": "^5.0.0",
+ "slash": "^3.0.0",
+ "specificity": "^0.4.1",
+ "string-width": "^4.2.0",
+ "strip-ansi": "^6.0.0",
+ "style-search": "^0.1.0",
+ "sugarss": "^2.0.0",
+ "svg-tags": "^1.0.0",
+ "table": "^6.0.3",
+ "v8-compile-cache": "^2.2.0",
+ "write-file-atomic": "^3.0.3"
+ },
+ "bin": {
+ "stylelint": "bin/stylelint.js"
+ },
+ "engines": {
+ "node": ">=10.13.0"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/stylelint"
+ }
+ },
+ "node_modules/stylelint-config-css-modules": {
+ "version": "2.2.0",
+ "resolved": "https://registry.npmjs.org/stylelint-config-css-modules/-/stylelint-config-css-modules-2.2.0.tgz",
+ "integrity": "sha512-+zjcDbot+zbuxy1UA31k4G2lUG+nHUwnLyii3uT2F09B8kT2YrT9LZYNfMtAWlDidrxr7sFd5HX9EqPHGU3WKA==",
+ "dev": true,
+ "peerDependencies": {
+ "stylelint": "11.x - 13.x"
+ }
+ },
+ "node_modules/stylelint-config-prettier": {
+ "version": "8.0.2",
+ "resolved": "https://registry.npmjs.org/stylelint-config-prettier/-/stylelint-config-prettier-8.0.2.tgz",
+ "integrity": "sha512-TN1l93iVTXpF9NJstlvP7nOu9zY2k+mN0NSFQ/VEGz15ZIP9ohdDZTtCWHs5LjctAhSAzaILULGbgiM0ItId3A==",
+ "dev": true,
+ "bin": {
+ "stylelint-config-prettier": "bin/check.js",
+ "stylelint-config-prettier-check": "bin/check.js"
+ },
+ "engines": {
+ "node": ">= 10",
+ "npm": ">= 5"
+ },
+ "peerDependencies": {
+ "stylelint": ">=11.0.0"
+ }
+ },
+ "node_modules/stylelint-config-recommended": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/stylelint-config-recommended/-/stylelint-config-recommended-3.0.0.tgz",
+ "integrity": "sha512-F6yTRuc06xr1h5Qw/ykb2LuFynJ2IxkKfCMf+1xqPffkxh0S09Zc902XCffcsw/XMFq/OzQ1w54fLIDtmRNHnQ==",
+ "dev": true,
+ "peerDependencies": {
+ "stylelint": ">=10.1.0"
+ }
+ },
+ "node_modules/stylelint-config-standard": {
+ "version": "20.0.0",
+ "resolved": "https://registry.npmjs.org/stylelint-config-standard/-/stylelint-config-standard-20.0.0.tgz",
+ "integrity": "sha512-IB2iFdzOTA/zS4jSVav6z+wGtin08qfj+YyExHB3LF9lnouQht//YyB0KZq9gGz5HNPkddHOzcY8HsUey6ZUlA==",
+ "dev": true,
+ "dependencies": {
+ "stylelint-config-recommended": "^3.0.0"
+ },
+ "peerDependencies": {
+ "stylelint": ">=10.1.0"
+ }
+ },
+ "node_modules/stylelint-media-use-custom-media": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/stylelint-media-use-custom-media/-/stylelint-media-use-custom-media-2.0.0.tgz",
+ "integrity": "sha512-G7Hwma8HIMFJOChqrX9ie8hAGbtEMUbEjuiaR3olHIXjloDWqYlFHIJKsCyyckigkm+4LtCwtZDQASrVY4pRBg==",
+ "dev": true,
+ "engines": {
+ "node": ">=10.0.0"
+ },
+ "peerDependencies": {
+ "stylelint": "10 - 13"
+ }
+ },
+ "node_modules/stylelint-order": {
+ "version": "4.1.0",
+ "resolved": "https://registry.npmjs.org/stylelint-order/-/stylelint-order-4.1.0.tgz",
+ "integrity": "sha512-sVTikaDvMqg2aJjh4r48jsdfmqLT+nqB1MOsaBnvM3OwLx4S+WXcsxsgk5w18h/OZoxZCxuyXMh61iBHcj9Qiw==",
+ "dev": true,
+ "dependencies": {
+ "lodash": "^4.17.15",
+ "postcss": "^7.0.31",
+ "postcss-sorting": "^5.0.1"
+ },
+ "peerDependencies": {
+ "stylelint": "^10.0.1 || ^11.0.0 || ^12.0.0 || ^13.0.0"
+ }
+ },
+ "node_modules/stylelint-order/node_modules/picocolors": {
+ "version": "0.2.1",
+ "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-0.2.1.tgz",
+ "integrity": "sha512-cMlDqaLEqfSaW8Z7N5Jw+lyIW869EzT73/F5lhtY9cLGoVxSXznfgfXMO0Z5K0o0Q2TkTXq+0KFsdnSe3jDViA==",
+ "dev": true
+ },
+ "node_modules/stylelint-order/node_modules/postcss": {
+ "version": "7.0.39",
+ "resolved": "https://registry.npmjs.org/postcss/-/postcss-7.0.39.tgz",
+ "integrity": "sha512-yioayjNbHn6z1/Bywyb2Y4s3yvDAeXGOyxqD+LnVOinq6Mdmd++SW2wUNVzavyyHxd6+DxzWGIuosg6P1Rj8uA==",
+ "dev": true,
+ "dependencies": {
+ "picocolors": "^0.2.1",
+ "source-map": "^0.6.1"
+ },
+ "engines": {
+ "node": ">=6.0.0"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/postcss/"
+ }
+ },
+ "node_modules/stylelint-use-nesting": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/stylelint-use-nesting/-/stylelint-use-nesting-3.0.0.tgz",
+ "integrity": "sha512-BMzhXWbK5DdAYtZMQULn7VmWZXpy8Rwlx2PgeNYqKInQrKTJWM/TFKPScc+xvsGUc/6JPiUDeQQij9gFnOo8Kg==",
+ "dev": true,
+ "engines": {
+ "node": ">=10.0.0"
+ },
+ "peerDependencies": {
+ "stylelint": "10 - 13"
+ }
+ },
+ "node_modules/stylelint-value-no-unknown-custom-properties": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/stylelint-value-no-unknown-custom-properties/-/stylelint-value-no-unknown-custom-properties-3.0.0.tgz",
+ "integrity": "sha512-8WoOnZ4ELTxA1cDbhwolIVOutxHwbjpXmd0lL0Li3Iye078jSnEb1KO6pJ/ig5oDVGRApFeA25Fyy4qqmqwGgg==",
+ "dev": true,
+ "dependencies": {
+ "postcss-values-parser": "^3.2.1"
+ },
+ "engines": {
+ "node": ">=10.0.0"
+ },
+ "peerDependencies": {
+ "stylelint": "10 - 13"
+ }
+ },
+ "node_modules/stylelint/node_modules/picocolors": {
+ "version": "0.2.1",
+ "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-0.2.1.tgz",
+ "integrity": "sha512-cMlDqaLEqfSaW8Z7N5Jw+lyIW869EzT73/F5lhtY9cLGoVxSXznfgfXMO0Z5K0o0Q2TkTXq+0KFsdnSe3jDViA==",
+ "dev": true
+ },
+ "node_modules/stylelint/node_modules/postcss": {
+ "version": "7.0.39",
+ "resolved": "https://registry.npmjs.org/postcss/-/postcss-7.0.39.tgz",
+ "integrity": "sha512-yioayjNbHn6z1/Bywyb2Y4s3yvDAeXGOyxqD+LnVOinq6Mdmd++SW2wUNVzavyyHxd6+DxzWGIuosg6P1Rj8uA==",
+ "dev": true,
+ "dependencies": {
+ "picocolors": "^0.2.1",
+ "source-map": "^0.6.1"
+ },
+ "engines": {
+ "node": ">=6.0.0"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/postcss/"
+ }
+ },
+ "node_modules/stylelint/node_modules/resolve-from": {
+ "version": "5.0.0",
+ "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-5.0.0.tgz",
+ "integrity": "sha512-qYg9KP24dD5qka9J47d0aVky0N+b4fTU89LN9iDnjB5waksiC49rvMB0PrUJQGoTmH50XPiqOvAjDfaijGxYZw==",
+ "dev": true,
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/sugarss": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/sugarss/-/sugarss-2.0.0.tgz",
+ "integrity": "sha512-WfxjozUk0UVA4jm+U1d736AUpzSrNsQcIbyOkoE364GrtWmIrFdk5lksEupgWMD4VaT/0kVx1dobpiDumSgmJQ==",
+ "dev": true,
+ "dependencies": {
+ "postcss": "^7.0.2"
+ }
+ },
+ "node_modules/sugarss/node_modules/picocolors": {
+ "version": "0.2.1",
+ "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-0.2.1.tgz",
+ "integrity": "sha512-cMlDqaLEqfSaW8Z7N5Jw+lyIW869EzT73/F5lhtY9cLGoVxSXznfgfXMO0Z5K0o0Q2TkTXq+0KFsdnSe3jDViA==",
+ "dev": true
+ },
+ "node_modules/sugarss/node_modules/postcss": {
+ "version": "7.0.39",
+ "resolved": "https://registry.npmjs.org/postcss/-/postcss-7.0.39.tgz",
+ "integrity": "sha512-yioayjNbHn6z1/Bywyb2Y4s3yvDAeXGOyxqD+LnVOinq6Mdmd++SW2wUNVzavyyHxd6+DxzWGIuosg6P1Rj8uA==",
+ "dev": true,
+ "dependencies": {
+ "picocolors": "^0.2.1",
+ "source-map": "^0.6.1"
+ },
+ "engines": {
+ "node": ">=6.0.0"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/postcss/"
+ }
+ },
+ "node_modules/supports-color": {
+ "version": "7.2.0",
+ "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz",
+ "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==",
+ "dev": true,
+ "dependencies": {
+ "has-flag": "^4.0.0"
+ },
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/supports-hyperlinks": {
+ "version": "2.2.0",
+ "resolved": "https://registry.npmjs.org/supports-hyperlinks/-/supports-hyperlinks-2.2.0.tgz",
+ "integrity": "sha512-6sXEzV5+I5j8Bmq9/vUphGRM/RJNT9SCURJLjwfOg51heRtguGWDzcaBlgAzKhQa0EVNpPEKzQuBwZ8S8WaCeQ==",
+ "dev": true,
+ "peer": true,
+ "dependencies": {
+ "has-flag": "^4.0.0",
+ "supports-color": "^7.0.0"
+ },
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/supports-preserve-symlinks-flag": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/supports-preserve-symlinks-flag/-/supports-preserve-symlinks-flag-1.0.0.tgz",
+ "integrity": "sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w==",
+ "dev": true,
+ "engines": {
+ "node": ">= 0.4"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/svg-tags": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/svg-tags/-/svg-tags-1.0.0.tgz",
+ "integrity": "sha1-WPcc7jvVGbWdSyqEO2x95krAR2Q=",
+ "dev": true
+ },
+ "node_modules/symbol-tree": {
+ "version": "3.2.4",
+ "resolved": "https://registry.npmjs.org/symbol-tree/-/symbol-tree-3.2.4.tgz",
+ "integrity": "sha512-9QNk5KwDF+Bvz+PyObkmSYjI5ksVUYtjW7AU22r2NKcfLJcXp96hkDWU3+XndOsUb+AQ9QhfzfCT2O+CNWT5Tw==",
+ "dev": true,
+ "peer": true
+ },
+ "node_modules/synckit": {
+ "version": "0.8.5",
+ "resolved": "https://registry.npmjs.org/synckit/-/synckit-0.8.5.tgz",
+ "integrity": "sha512-L1dapNV6vu2s/4Sputv8xGsCdAVlb5nRDMFU/E27D44l5U6cw1g0dGd45uLc+OXjNMmF4ntiMdCimzcjFKQI8Q==",
+ "dev": true,
+ "dependencies": {
+ "@pkgr/utils": "^2.3.1",
+ "tslib": "^2.5.0"
+ },
+ "engines": {
+ "node": "^14.18.0 || >=16.0.0"
+ },
+ "funding": {
+ "url": "https://opencollective.com/unts"
+ }
+ },
+ "node_modules/synckit/node_modules/tslib": {
+ "version": "2.5.0",
+ "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.5.0.tgz",
+ "integrity": "sha512-336iVw3rtn2BUK7ORdIAHTyxHGRIHVReokCR3XjbckJMK7ms8FysBfhLR8IXnAgy7T0PTPNBWKiH514FOW/WSg==",
+ "dev": true
+ },
+ "node_modules/table": {
+ "version": "6.8.0",
+ "resolved": "https://registry.npmjs.org/table/-/table-6.8.0.tgz",
+ "integrity": "sha512-s/fitrbVeEyHKFa7mFdkuQMWlH1Wgw/yEXMt5xACT4ZpzWFluehAxRtUUQKPuWhaLAWhFcVx6w3oC8VKaUfPGA==",
+ "dev": true,
+ "dependencies": {
+ "ajv": "^8.0.1",
+ "lodash.truncate": "^4.4.2",
+ "slice-ansi": "^4.0.0",
+ "string-width": "^4.2.3",
+ "strip-ansi": "^6.0.1"
+ },
+ "engines": {
+ "node": ">=10.0.0"
+ }
+ },
+ "node_modules/table/node_modules/ajv": {
+ "version": "8.11.0",
+ "resolved": "https://registry.npmjs.org/ajv/-/ajv-8.11.0.tgz",
+ "integrity": "sha512-wGgprdCvMalC0BztXvitD2hC04YffAvtsUn93JbGXYLAtCUO4xd17mCCZQxUOItiBwZvJScWo8NIvQMQ71rdpg==",
+ "dev": true,
+ "dependencies": {
+ "fast-deep-equal": "^3.1.1",
+ "json-schema-traverse": "^1.0.0",
+ "require-from-string": "^2.0.2",
+ "uri-js": "^4.2.2"
+ },
+ "funding": {
+ "type": "github",
+ "url": "https://github.com/sponsors/epoberezkin"
+ }
+ },
+ "node_modules/table/node_modules/json-schema-traverse": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-1.0.0.tgz",
+ "integrity": "sha512-NM8/P9n3XjXhIZn1lLhkFaACTOURQXjWhV4BA/RnOv8xvgqtqpAX9IO4mRQxSx1Rlo4tqzeqb0sOlruaOy3dug==",
+ "dev": true
+ },
+ "node_modules/table/node_modules/slice-ansi": {
+ "version": "4.0.0",
+ "resolved": "https://registry.npmjs.org/slice-ansi/-/slice-ansi-4.0.0.tgz",
+ "integrity": "sha512-qMCMfhY040cVHT43K9BFygqYbUPFZKHOg7K73mtTWJRb8pyP3fzf4Ixd5SzdEJQ6MRUg/WBnOLxghZtKKurENQ==",
+ "dev": true,
+ "dependencies": {
+ "ansi-styles": "^4.0.0",
+ "astral-regex": "^2.0.0",
+ "is-fullwidth-code-point": "^3.0.0"
+ },
+ "engines": {
+ "node": ">=10"
+ },
+ "funding": {
+ "url": "https://github.com/chalk/slice-ansi?sponsor=1"
+ }
+ },
+ "node_modules/tapable": {
+ "version": "2.2.1",
+ "resolved": "https://registry.npmjs.org/tapable/-/tapable-2.2.1.tgz",
+ "integrity": "sha512-GNzQvQTOIP6RyTfE2Qxb8ZVlNmw0n88vp1szwWRimP02mnTsx3Wtn5qRdqY9w2XduFNUgvOwhNnQsjwCp+kqaQ==",
+ "dev": true,
+ "engines": {
+ "node": ">=6"
+ }
+ },
+ "node_modules/terminal-link": {
+ "version": "2.1.1",
+ "resolved": "https://registry.npmjs.org/terminal-link/-/terminal-link-2.1.1.tgz",
+ "integrity": "sha512-un0FmiRUQNr5PJqy9kP7c40F5BOfpGlYTrxonDChEZB7pzZxRNp/bt+ymiy9/npwXya9KH99nJ/GXFIiUkYGFQ==",
+ "dev": true,
+ "peer": true,
+ "dependencies": {
+ "ansi-escapes": "^4.2.1",
+ "supports-hyperlinks": "^2.0.0"
+ },
+ "engines": {
+ "node": ">=8"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
+ "node_modules/test-exclude": {
+ "version": "6.0.0",
+ "resolved": "https://registry.npmjs.org/test-exclude/-/test-exclude-6.0.0.tgz",
+ "integrity": "sha512-cAGWPIyOHU6zlmg88jwm7VRyXnMN7iV68OGAbYDk/Mh/xC/pzVPlQtY6ngoIH/5/tciuhGfvESU8GrHrcxD56w==",
+ "dev": true,
+ "peer": true,
+ "dependencies": {
+ "@istanbuljs/schema": "^0.1.2",
+ "glob": "^7.1.4",
+ "minimatch": "^3.0.4"
+ },
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/text-table": {
+ "version": "0.2.0",
+ "resolved": "https://registry.npmjs.org/text-table/-/text-table-0.2.0.tgz",
+ "integrity": "sha512-N+8UisAXDGk8PFXP4HAzVR9nbfmVJ3zYLAWiTIoqC5v5isinhr+r5uaO8+7r3BMfuNIufIsA7RdpVgacC2cSpw==",
+ "dev": true
+ },
+ "node_modules/throat": {
+ "version": "5.0.0",
+ "resolved": "https://registry.npmjs.org/throat/-/throat-5.0.0.tgz",
+ "integrity": "sha512-fcwX4mndzpLQKBS1DVYhGAcYaYt7vsHNIvQV+WXMvnow5cgjPphq5CaayLaGsjRdSCKZFNGt7/GYAuXaNOiYCA==",
+ "dev": true,
+ "peer": true
+ },
+ "node_modules/through": {
+ "version": "2.3.8",
+ "resolved": "https://registry.npmjs.org/through/-/through-2.3.8.tgz",
+ "integrity": "sha1-DdTJ/6q8NXlgsbckEV1+Doai4fU=",
+ "dev": true
+ },
+ "node_modules/tiny-glob": {
+ "version": "0.2.9",
+ "resolved": "https://registry.npmjs.org/tiny-glob/-/tiny-glob-0.2.9.tgz",
+ "integrity": "sha512-g/55ssRPUjShh+xkfx9UPDXqhckHEsHr4Vd9zX55oSdGZc/MD0m3sferOkwWtp98bv+kcVfEHtRJgBVJzelrzg==",
+ "dev": true,
+ "dependencies": {
+ "globalyzer": "0.1.0",
+ "globrex": "^0.1.2"
+ }
+ },
+ "node_modules/tlds": {
+ "version": "1.231.0",
+ "resolved": "https://registry.npmjs.org/tlds/-/tlds-1.231.0.tgz",
+ "integrity": "sha512-L7UQwueHSkGxZHQBXHVmXW64oi+uqNtzFt2x6Ssk7NVnpIbw16CRs4eb/jmKOZ9t2JnqZ/b3Cfvo97lnXqKrhw==",
+ "dev": true,
+ "bin": {
+ "tlds": "bin.js"
+ }
+ },
+ "node_modules/tmp": {
+ "version": "0.0.33",
+ "resolved": "https://registry.npmjs.org/tmp/-/tmp-0.0.33.tgz",
+ "integrity": "sha512-jRCJlojKnZ3addtTOjdIqoRuPEKBvNXcGYqzO6zWZX8KfKEpnGY5jfggJQ3EjKuu8D4bJRr0y+cYJFmYbImXGw==",
+ "dev": true,
+ "dependencies": {
+ "os-tmpdir": "~1.0.2"
+ },
+ "engines": {
+ "node": ">=0.6.0"
+ }
+ },
+ "node_modules/tmpl": {
+ "version": "1.0.5",
+ "resolved": "https://registry.npmjs.org/tmpl/-/tmpl-1.0.5.tgz",
+ "integrity": "sha512-3f0uOEAQwIqGuWW2MVzYg8fV/QNnc/IpuJNG837rLuczAaLVHslWHZQj4IGiEl5Hs3kkbhwL9Ab7Hrsmuj+Smw==",
+ "dev": true,
+ "peer": true
+ },
+ "node_modules/to-fast-properties": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/to-fast-properties/-/to-fast-properties-2.0.0.tgz",
+ "integrity": "sha1-3F5pjL0HkmW8c+A3doGk5Og/YW4=",
+ "dev": true,
+ "engines": {
+ "node": ">=4"
+ }
+ },
+ "node_modules/to-object-path": {
+ "version": "0.3.0",
+ "resolved": "https://registry.npmjs.org/to-object-path/-/to-object-path-0.3.0.tgz",
+ "integrity": "sha1-KXWIt7Dn4KwI4E5nL4XB9JmeF68=",
+ "dev": true,
+ "peer": true,
+ "dependencies": {
+ "kind-of": "^3.0.2"
+ },
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
+ "node_modules/to-object-path/node_modules/is-buffer": {
+ "version": "1.1.6",
+ "resolved": "https://registry.npmjs.org/is-buffer/-/is-buffer-1.1.6.tgz",
+ "integrity": "sha512-NcdALwpXkTm5Zvvbk7owOUSvVvBKDgKP5/ewfXEznmQFfs4ZRmanOeKBTjRVjka3QFoN6XJ+9F3USqfHqTaU5w==",
+ "dev": true,
+ "peer": true
+ },
+ "node_modules/to-object-path/node_modules/kind-of": {
+ "version": "3.2.2",
+ "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz",
+ "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=",
+ "dev": true,
+ "peer": true,
+ "dependencies": {
+ "is-buffer": "^1.1.5"
+ },
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
+ "node_modules/to-regex": {
+ "version": "3.0.2",
+ "resolved": "https://registry.npmjs.org/to-regex/-/to-regex-3.0.2.tgz",
+ "integrity": "sha512-FWtleNAtZ/Ki2qtqej2CXTOayOH9bHDQF+Q48VpWyDXjbYxA4Yz8iDB31zXOBUlOHHKidDbqGVrTUvQMPmBGBw==",
+ "dev": true,
+ "peer": true,
+ "dependencies": {
+ "define-property": "^2.0.2",
+ "extend-shallow": "^3.0.2",
+ "regex-not": "^1.0.2",
+ "safe-regex": "^1.1.0"
+ },
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
+ "node_modules/to-regex-range": {
+ "version": "5.0.1",
+ "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz",
+ "integrity": "sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==",
+ "dev": true,
+ "dependencies": {
+ "is-number": "^7.0.0"
+ },
+ "engines": {
+ "node": ">=8.0"
+ }
+ },
+ "node_modules/tough-cookie": {
+ "version": "4.1.3",
+ "resolved": "https://registry.npmjs.org/tough-cookie/-/tough-cookie-4.1.3.tgz",
+ "integrity": "sha512-aX/y5pVRkfRnfmuX+OdbSdXvPe6ieKX/G2s7e98f4poJHnqH3281gDPm/metm6E/WRamfx7WC4HUqkWHfQHprw==",
+ "dev": true,
+ "peer": true,
+ "dependencies": {
+ "psl": "^1.1.33",
+ "punycode": "^2.1.1",
+ "universalify": "^0.2.0",
+ "url-parse": "^1.5.3"
+ },
+ "engines": {
+ "node": ">=6"
+ }
+ },
+ "node_modules/tough-cookie/node_modules/universalify": {
+ "version": "0.2.0",
+ "resolved": "https://registry.npmjs.org/universalify/-/universalify-0.2.0.tgz",
+ "integrity": "sha512-CJ1QgKmNg3CwvAv/kOFmtnEN05f0D/cn9QntgNOQlQF9dgvVTHj3t+8JPdjqawCHk7V/KA+fbUqzZ9XWhcqPUg==",
+ "dev": true,
+ "peer": true,
+ "engines": {
+ "node": ">= 4.0.0"
+ }
+ },
+ "node_modules/tr46": {
+ "version": "2.1.0",
+ "resolved": "https://registry.npmjs.org/tr46/-/tr46-2.1.0.tgz",
+ "integrity": "sha512-15Ih7phfcdP5YxqiB+iDtLoaTz4Nd35+IiAv0kQ5FNKHzXgdWqPoTIqEDDJmXceQt4JZk6lVPT8lnDlPpGDppw==",
+ "dev": true,
+ "peer": true,
+ "dependencies": {
+ "punycode": "^2.1.1"
+ },
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/trim": {
+ "version": "0.0.1",
+ "resolved": "https://registry.npmjs.org/trim/-/trim-0.0.1.tgz",
+ "integrity": "sha512-YzQV+TZg4AxpKxaTHK3c3D+kRDCGVEE7LemdlQZoQXn0iennk10RsIoY6ikzAqJTc9Xjl9C1/waHom/J86ziAQ==",
+ "deprecated": "Use String.prototype.trim() instead",
+ "dev": true
+ },
+ "node_modules/trim-newlines": {
+ "version": "3.0.1",
+ "resolved": "https://registry.npmjs.org/trim-newlines/-/trim-newlines-3.0.1.tgz",
+ "integrity": "sha512-c1PTsA3tYrIsLGkJkzHF+w9F2EyxfXGo4UyJc4pFL++FMjnq0HJS69T3M7d//gKrFKwy429bouPescbjecU+Zw==",
+ "dev": true,
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/trim-trailing-lines": {
+ "version": "1.1.4",
+ "resolved": "https://registry.npmjs.org/trim-trailing-lines/-/trim-trailing-lines-1.1.4.tgz",
+ "integrity": "sha512-rjUWSqnfTNrjbB9NQWfPMH/xRK1deHeGsHoVfpxJ++XeYXE0d6B1En37AHfw3jtfTU7dzMzZL2jjpe8Qb5gLIQ==",
+ "dev": true,
+ "funding": {
+ "type": "github",
+ "url": "https://github.com/sponsors/wooorm"
+ }
+ },
+ "node_modules/trough": {
+ "version": "1.0.5",
+ "resolved": "https://registry.npmjs.org/trough/-/trough-1.0.5.tgz",
+ "integrity": "sha512-rvuRbTarPXmMb79SmzEp8aqXNKcK+y0XaB298IXueQ8I2PsrATcPBCSPyK/dDNa2iWOhKlfNnOjdAOTBU/nkFA==",
+ "dev": true,
+ "funding": {
+ "type": "github",
+ "url": "https://github.com/sponsors/wooorm"
+ }
+ },
+ "node_modules/ts-jest": {
+ "version": "26.5.6",
+ "resolved": "https://registry.npmjs.org/ts-jest/-/ts-jest-26.5.6.tgz",
+ "integrity": "sha512-rua+rCP8DxpA8b4DQD/6X2HQS8Zy/xzViVYfEs2OQu68tkCuKLV0Md8pmX55+W24uRIyAsf/BajRfxOs+R2MKA==",
+ "dev": true,
+ "dependencies": {
+ "bs-logger": "0.x",
+ "buffer-from": "1.x",
+ "fast-json-stable-stringify": "2.x",
+ "jest-util": "^26.1.0",
+ "json5": "2.x",
+ "lodash": "4.x",
+ "make-error": "1.x",
+ "mkdirp": "1.x",
+ "semver": "7.x",
+ "yargs-parser": "20.x"
+ },
+ "bin": {
+ "ts-jest": "cli.js"
+ },
+ "engines": {
+ "node": ">= 10"
+ },
+ "peerDependencies": {
+ "jest": ">=26 <27",
+ "typescript": ">=3.8 <5.0"
+ }
+ },
+ "node_modules/tsconfig-paths": {
+ "version": "3.14.2",
+ "resolved": "https://registry.npmjs.org/tsconfig-paths/-/tsconfig-paths-3.14.2.tgz",
+ "integrity": "sha512-o/9iXgCYc5L/JxCHPe3Hvh8Q/2xm5Z+p18PESBU6Ff33695QnCHBEjcytY2q19ua7Mbl/DavtBOLq+oG0RCL+g==",
+ "dev": true,
+ "dependencies": {
+ "@types/json5": "^0.0.29",
+ "json5": "^1.0.2",
+ "minimist": "^1.2.6",
+ "strip-bom": "^3.0.0"
+ }
+ },
+ "node_modules/tsconfig-paths/node_modules/json5": {
+ "version": "1.0.2",
+ "resolved": "https://registry.npmjs.org/json5/-/json5-1.0.2.tgz",
+ "integrity": "sha512-g1MWMLBiz8FKi1e4w0UyVL3w+iJceWAFBAaBnnGKOpNa5f8TLktkbre1+s6oICydWAm+HRUGTmI+//xv2hvXYA==",
+ "dev": true,
+ "dependencies": {
+ "minimist": "^1.2.0"
+ },
+ "bin": {
+ "json5": "lib/cli.js"
+ }
+ },
+ "node_modules/tsconfig-paths/node_modules/strip-bom": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/strip-bom/-/strip-bom-3.0.0.tgz",
+ "integrity": "sha512-vavAMRXOgBVNF6nyEEmL3DBK19iRpDcoIwW+swQ+CbGiu7lju6t+JklA1MHweoWtadgt4ISVUsXLyDq34ddcwA==",
+ "dev": true,
+ "engines": {
+ "node": ">=4"
+ }
+ },
+ "node_modules/tslib": {
+ "version": "1.14.1",
+ "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.14.1.tgz",
+ "integrity": "sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg==",
+ "dev": true
+ },
+ "node_modules/tsutils": {
+ "version": "3.21.0",
+ "resolved": "https://registry.npmjs.org/tsutils/-/tsutils-3.21.0.tgz",
+ "integrity": "sha512-mHKK3iUXL+3UF6xL5k0PEhKRUBKPBCv/+RkEOpjRWxxx27KKRBmmA60A9pgOUvMi8GKhRMPEmjBRPzs2W7O1OA==",
+ "dev": true,
+ "dependencies": {
+ "tslib": "^1.8.1"
+ },
+ "engines": {
+ "node": ">= 6"
+ },
+ "peerDependencies": {
+ "typescript": ">=2.8.0 || >= 3.2.0-dev || >= 3.3.0-dev || >= 3.4.0-dev || >= 3.5.0-dev || >= 3.6.0-dev || >= 3.6.0-beta || >= 3.7.0-dev || >= 3.7.0-beta"
+ }
+ },
+ "node_modules/type-check": {
+ "version": "0.4.0",
+ "resolved": "https://registry.npmjs.org/type-check/-/type-check-0.4.0.tgz",
+ "integrity": "sha512-XleUoc9uwGXqjWwXaUTZAmzMcFZ5858QA2vvx1Ur5xIcixXIP+8LnFDgRplU30us6teqdlskFfu+ae4K79Ooew==",
+ "dev": true,
+ "dependencies": {
+ "prelude-ls": "^1.2.1"
+ },
+ "engines": {
+ "node": ">= 0.8.0"
+ }
+ },
+ "node_modules/type-detect": {
+ "version": "4.0.8",
+ "resolved": "https://registry.npmjs.org/type-detect/-/type-detect-4.0.8.tgz",
+ "integrity": "sha512-0fr/mIH1dlO+x7TlcMy+bIDqKPsw/70tVyeHW787goQjhmqaZe10uwLujubK9q9Lg6Fiho1KUKDYz0Z7k7g5/g==",
+ "dev": true,
+ "peer": true,
+ "engines": {
+ "node": ">=4"
+ }
+ },
+ "node_modules/type-fest": {
+ "version": "0.20.2",
+ "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.20.2.tgz",
+ "integrity": "sha512-Ne+eE4r0/iWnpAxD852z3A+N0Bt5RN//NjJwRd2VFHEmrywxf5vsZlh4R6lixl6B+wz/8d+maTSAkN1FIkI3LQ==",
+ "dev": true,
+ "engines": {
+ "node": ">=10"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
+ "node_modules/typed-array-length": {
+ "version": "1.0.4",
+ "resolved": "https://registry.npmjs.org/typed-array-length/-/typed-array-length-1.0.4.tgz",
+ "integrity": "sha512-KjZypGq+I/H7HI5HlOoGHkWUUGq+Q0TPhQurLbyrVrvnKTBgzLhIJ7j6J/XTQOi0d1RjyZ0wdas8bKs2p0x3Ng==",
+ "dev": true,
+ "dependencies": {
+ "call-bind": "^1.0.2",
+ "for-each": "^0.3.3",
+ "is-typed-array": "^1.1.9"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/typedarray-to-buffer": {
+ "version": "3.1.5",
+ "resolved": "https://registry.npmjs.org/typedarray-to-buffer/-/typedarray-to-buffer-3.1.5.tgz",
+ "integrity": "sha512-zdu8XMNEDepKKR+XYOXAVPtWui0ly0NtohUscw+UmaHiAWT8hrV1rr//H6V+0DvJ3OQ19S979M0laLfX8rm82Q==",
+ "dev": true,
+ "dependencies": {
+ "is-typedarray": "^1.0.0"
+ }
+ },
+ "node_modules/typescript": {
+ "version": "4.6.3",
+ "resolved": "https://registry.npmjs.org/typescript/-/typescript-4.6.3.tgz",
+ "integrity": "sha512-yNIatDa5iaofVozS/uQJEl3JRWLKKGJKh6Yaiv0GLGSuhpFJe7P3SbHZ8/yjAHRQwKRoA6YZqlfjXWmVzoVSMw==",
+ "dev": true,
+ "peer": true,
+ "bin": {
+ "tsc": "bin/tsc",
+ "tsserver": "bin/tsserver"
+ },
+ "engines": {
+ "node": ">=4.2.0"
+ }
+ },
+ "node_modules/unbox-primitive": {
+ "version": "1.0.2",
+ "resolved": "https://registry.npmjs.org/unbox-primitive/-/unbox-primitive-1.0.2.tgz",
+ "integrity": "sha512-61pPlCD9h51VoreyJ0BReideM3MDKMKnh6+V9L08331ipq6Q8OFXZYiqP6n/tbHx4s5I9uRhcye6BrbkizkBDw==",
+ "dev": true,
+ "dependencies": {
+ "call-bind": "^1.0.2",
+ "has-bigints": "^1.0.2",
+ "has-symbols": "^1.0.3",
+ "which-boxed-primitive": "^1.0.2"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/unherit": {
+ "version": "1.1.3",
+ "resolved": "https://registry.npmjs.org/unherit/-/unherit-1.1.3.tgz",
+ "integrity": "sha512-Ft16BJcnapDKp0+J/rqFC3Rrk6Y/Ng4nzsC028k2jdDII/rdZ7Wd3pPT/6+vIIxRagwRc9K0IUX0Ra4fKvw+WQ==",
+ "dev": true,
+ "dependencies": {
+ "inherits": "^2.0.0",
+ "xtend": "^4.0.0"
+ },
+ "funding": {
+ "type": "github",
+ "url": "https://github.com/sponsors/wooorm"
+ }
+ },
+ "node_modules/unified": {
+ "version": "9.2.2",
+ "resolved": "https://registry.npmjs.org/unified/-/unified-9.2.2.tgz",
+ "integrity": "sha512-Sg7j110mtefBD+qunSLO1lqOEKdrwBFBrR6Qd8f4uwkhWNlbkaqwHse6e7QvD3AP/MNoJdEDLaf8OxYyoWgorQ==",
+ "dev": true,
+ "dependencies": {
+ "bail": "^1.0.0",
+ "extend": "^3.0.0",
+ "is-buffer": "^2.0.0",
+ "is-plain-obj": "^2.0.0",
+ "trough": "^1.0.0",
+ "vfile": "^4.0.0"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/unified"
+ }
+ },
+ "node_modules/unified-lint-rule": {
+ "version": "2.1.1",
+ "resolved": "https://registry.npmjs.org/unified-lint-rule/-/unified-lint-rule-2.1.1.tgz",
+ "integrity": "sha512-vsLHyLZFstqtGse2gvrGwasOmH8M2y+r2kQMoDSWzSqUkQx2MjHjvZuGSv5FUaiv4RQO1bHRajy7lSGp7XWq5A==",
+ "dev": true,
+ "dependencies": {
+ "@types/unist": "^2.0.0",
+ "trough": "^2.0.0",
+ "unified": "^10.0.0",
+ "vfile": "^5.0.0"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/unified"
+ }
+ },
+ "node_modules/unified-lint-rule/node_modules/bail": {
+ "version": "2.0.2",
+ "resolved": "https://registry.npmjs.org/bail/-/bail-2.0.2.tgz",
+ "integrity": "sha512-0xO6mYd7JB2YesxDKplafRpsiOzPt9V02ddPCLbY1xYGPOX24NTyN50qnUxgCPcSoYMhKpAuBTjQoRZCAkUDRw==",
+ "dev": true,
+ "funding": {
+ "type": "github",
+ "url": "https://github.com/sponsors/wooorm"
+ }
+ },
+ "node_modules/unified-lint-rule/node_modules/is-plain-obj": {
+ "version": "4.1.0",
+ "resolved": "https://registry.npmjs.org/is-plain-obj/-/is-plain-obj-4.1.0.tgz",
+ "integrity": "sha512-+Pgi+vMuUNkJyExiMBt5IlFoMyKnr5zhJ4Uspz58WOhBF5QoIZkFyNHIbBAtHwzVAgk5RtndVNsDRN61/mmDqg==",
+ "dev": true,
+ "engines": {
+ "node": ">=12"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
+ "node_modules/unified-lint-rule/node_modules/trough": {
+ "version": "2.1.0",
+ "resolved": "https://registry.npmjs.org/trough/-/trough-2.1.0.tgz",
+ "integrity": "sha512-AqTiAOLcj85xS7vQ8QkAV41hPDIJ71XJB4RCUrzo/1GM2CQwhkJGaf9Hgr7BOugMRpgGUrqRg/DrBDl4H40+8g==",
+ "dev": true,
+ "funding": {
+ "type": "github",
+ "url": "https://github.com/sponsors/wooorm"
+ }
+ },
+ "node_modules/unified-lint-rule/node_modules/unified": {
+ "version": "10.1.2",
+ "resolved": "https://registry.npmjs.org/unified/-/unified-10.1.2.tgz",
+ "integrity": "sha512-pUSWAi/RAnVy1Pif2kAoeWNBa3JVrx0MId2LASj8G+7AiHWoKZNTomq6LG326T68U7/e263X6fTdcXIy7XnF7Q==",
+ "dev": true,
+ "dependencies": {
+ "@types/unist": "^2.0.0",
+ "bail": "^2.0.0",
+ "extend": "^3.0.0",
+ "is-buffer": "^2.0.0",
+ "is-plain-obj": "^4.0.0",
+ "trough": "^2.0.0",
+ "vfile": "^5.0.0"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/unified"
+ }
+ },
+ "node_modules/unified-lint-rule/node_modules/unist-util-stringify-position": {
+ "version": "3.0.3",
+ "resolved": "https://registry.npmjs.org/unist-util-stringify-position/-/unist-util-stringify-position-3.0.3.tgz",
+ "integrity": "sha512-k5GzIBZ/QatR8N5X2y+drfpWG8IDBzdnVj6OInRNWm1oXrzydiaAT2OQiA8DPRRZyAKb9b6I2a6PxYklZD0gKg==",
+ "dev": true,
+ "dependencies": {
+ "@types/unist": "^2.0.0"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/unified"
+ }
+ },
+ "node_modules/unified-lint-rule/node_modules/vfile": {
+ "version": "5.3.7",
+ "resolved": "https://registry.npmjs.org/vfile/-/vfile-5.3.7.tgz",
+ "integrity": "sha512-r7qlzkgErKjobAmyNIkkSpizsFPYiUPuJb5pNW1RB4JcYVZhs4lIbVqk8XPk033CV/1z8ss5pkax8SuhGpcG8g==",
+ "dev": true,
+ "dependencies": {
+ "@types/unist": "^2.0.0",
+ "is-buffer": "^2.0.0",
+ "unist-util-stringify-position": "^3.0.0",
+ "vfile-message": "^3.0.0"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/unified"
+ }
+ },
+ "node_modules/unified-lint-rule/node_modules/vfile-message": {
+ "version": "3.1.4",
+ "resolved": "https://registry.npmjs.org/vfile-message/-/vfile-message-3.1.4.tgz",
+ "integrity": "sha512-fa0Z6P8HUrQN4BZaX05SIVXic+7kE3b05PWAtPuYP9QLHsLKYR7/AlLW3NtOrpXRLeawpDLMsVkmk5DG0NXgWw==",
+ "dev": true,
+ "dependencies": {
+ "@types/unist": "^2.0.0",
+ "unist-util-stringify-position": "^3.0.0"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/unified"
+ }
+ },
+ "node_modules/unified/node_modules/is-plain-obj": {
+ "version": "2.1.0",
+ "resolved": "https://registry.npmjs.org/is-plain-obj/-/is-plain-obj-2.1.0.tgz",
+ "integrity": "sha512-YWnfyRwxL/+SsrWYfOpUtz5b3YD+nyfkHvjbcanzk8zgyO4ASD67uVMRt8k5bM4lLMDnXfriRhOpemw+NfT1eA==",
+ "dev": true,
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/union-value": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/union-value/-/union-value-1.0.1.tgz",
+ "integrity": "sha512-tJfXmxMeWYnczCVs7XAEvIV7ieppALdyepWMkHkwciRpZraG/xwT+s2JN8+pr1+8jCRf80FFzvr+MpQeeoF4Xg==",
+ "dev": true,
+ "peer": true,
+ "dependencies": {
+ "arr-union": "^3.1.0",
+ "get-value": "^2.0.6",
+ "is-extendable": "^0.1.1",
+ "set-value": "^2.0.1"
+ },
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
+ "node_modules/union-value/node_modules/is-extendable": {
+ "version": "0.1.1",
+ "resolved": "https://registry.npmjs.org/is-extendable/-/is-extendable-0.1.1.tgz",
+ "integrity": "sha1-YrEQ4omkcUGOPsNqYX1HLjAd/Ik=",
+ "dev": true,
+ "peer": true,
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
+ "node_modules/unist-util-find-all-after": {
+ "version": "3.0.2",
+ "resolved": "https://registry.npmjs.org/unist-util-find-all-after/-/unist-util-find-all-after-3.0.2.tgz",
+ "integrity": "sha512-xaTC/AGZ0rIM2gM28YVRAFPIZpzbpDtU3dRmp7EXlNVA8ziQc4hY3H7BHXM1J49nEmiqc3svnqMReW+PGqbZKQ==",
+ "dev": true,
+ "dependencies": {
+ "unist-util-is": "^4.0.0"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/unified"
+ }
+ },
+ "node_modules/unist-util-is": {
+ "version": "4.1.0",
+ "resolved": "https://registry.npmjs.org/unist-util-is/-/unist-util-is-4.1.0.tgz",
+ "integrity": "sha512-ZOQSsnce92GrxSqlnEEseX0gi7GH9zTJZ0p9dtu87WRb/37mMPO2Ilx1s/t9vBHrFhbgweUwb+t7cIn5dxPhZg==",
+ "dev": true,
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/unified"
+ }
+ },
+ "node_modules/unist-util-remove-position": {
+ "version": "2.0.1",
+ "resolved": "https://registry.npmjs.org/unist-util-remove-position/-/unist-util-remove-position-2.0.1.tgz",
+ "integrity": "sha512-fDZsLYIe2uT+oGFnuZmy73K6ZxOPG/Qcm+w7jbEjaFcJgbQ6cqjs/eSPzXhsmGpAsWPkqZM9pYjww5QTn3LHMA==",
+ "dev": true,
+ "dependencies": {
+ "unist-util-visit": "^2.0.0"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/unified"
+ }
+ },
+ "node_modules/unist-util-remove-position/node_modules/unist-util-visit": {
+ "version": "2.0.3",
+ "resolved": "https://registry.npmjs.org/unist-util-visit/-/unist-util-visit-2.0.3.tgz",
+ "integrity": "sha512-iJ4/RczbJMkD0712mGktuGpm/U4By4FfDonL7N/9tATGIF4imikjOuagyMY53tnZq3NP6BcmlrHhEKAfGWjh7Q==",
+ "dev": true,
+ "dependencies": {
+ "@types/unist": "^2.0.0",
+ "unist-util-is": "^4.0.0",
+ "unist-util-visit-parents": "^3.0.0"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/unified"
+ }
+ },
+ "node_modules/unist-util-remove-position/node_modules/unist-util-visit-parents": {
+ "version": "3.1.1",
+ "resolved": "https://registry.npmjs.org/unist-util-visit-parents/-/unist-util-visit-parents-3.1.1.tgz",
+ "integrity": "sha512-1KROIZWo6bcMrZEwiH2UrXDyalAa0uqzWCxCJj6lPOvTve2WkfgCytoDTPaMnodXh1WrXOq0haVYHj99ynJlsg==",
+ "dev": true,
+ "dependencies": {
+ "@types/unist": "^2.0.0",
+ "unist-util-is": "^4.0.0"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/unified"
+ }
+ },
+ "node_modules/unist-util-stringify-position": {
+ "version": "2.0.3",
+ "resolved": "https://registry.npmjs.org/unist-util-stringify-position/-/unist-util-stringify-position-2.0.3.tgz",
+ "integrity": "sha512-3faScn5I+hy9VleOq/qNbAd6pAx7iH5jYBMS9I1HgQVijz/4mv5Bvw5iw1sC/90CODiKo81G/ps8AJrISn687g==",
+ "dev": true,
+ "dependencies": {
+ "@types/unist": "^2.0.2"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/unified"
+ }
+ },
+ "node_modules/unist-util-visit": {
+ "version": "4.1.2",
+ "resolved": "https://registry.npmjs.org/unist-util-visit/-/unist-util-visit-4.1.2.tgz",
+ "integrity": "sha512-MSd8OUGISqHdVvfY9TPhyK2VdUrPgxkUtWSuMHF6XAAFuL4LokseigBnZtPnJMu+FbynTkFNnFlyjxpVKujMRg==",
+ "dev": true,
+ "dependencies": {
+ "@types/unist": "^2.0.0",
+ "unist-util-is": "^5.0.0",
+ "unist-util-visit-parents": "^5.1.1"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/unified"
+ }
+ },
+ "node_modules/unist-util-visit-parents": {
+ "version": "5.1.3",
+ "resolved": "https://registry.npmjs.org/unist-util-visit-parents/-/unist-util-visit-parents-5.1.3.tgz",
+ "integrity": "sha512-x6+y8g7wWMyQhL1iZfhIPhDAs7Xwbn9nRosDXl7qoPTSCy0yNxnKc+hWokFifWQIDGi154rdUqKvbCa4+1kLhg==",
+ "dev": true,
+ "dependencies": {
+ "@types/unist": "^2.0.0",
+ "unist-util-is": "^5.0.0"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/unified"
+ }
+ },
+ "node_modules/unist-util-visit-parents/node_modules/unist-util-is": {
+ "version": "5.2.1",
+ "resolved": "https://registry.npmjs.org/unist-util-is/-/unist-util-is-5.2.1.tgz",
+ "integrity": "sha512-u9njyyfEh43npf1M+yGKDGVPbY/JWEemg5nH05ncKPfi+kBbKBJoTdsogMu33uhytuLlv9y0O7GH7fEdwLdLQw==",
+ "dev": true,
+ "dependencies": {
+ "@types/unist": "^2.0.0"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/unified"
+ }
+ },
+ "node_modules/unist-util-visit/node_modules/unist-util-is": {
+ "version": "5.2.1",
+ "resolved": "https://registry.npmjs.org/unist-util-is/-/unist-util-is-5.2.1.tgz",
+ "integrity": "sha512-u9njyyfEh43npf1M+yGKDGVPbY/JWEemg5nH05ncKPfi+kBbKBJoTdsogMu33uhytuLlv9y0O7GH7fEdwLdLQw==",
+ "dev": true,
+ "dependencies": {
+ "@types/unist": "^2.0.0"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/unified"
+ }
+ },
+ "node_modules/universalify": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/universalify/-/universalify-1.0.0.tgz",
+ "integrity": "sha512-rb6X1W158d7pRQBg5gkR8uPaSfiids68LTJQYOtEUhoJUWBdaQHsuT/EUduxXYxcrt4r5PJ4fuHW1MHT6p0qug==",
+ "dev": true,
+ "engines": {
+ "node": ">= 10.0.0"
+ }
+ },
+ "node_modules/unset-value": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/unset-value/-/unset-value-1.0.0.tgz",
+ "integrity": "sha1-g3aHP30jNRef+x5vw6jtDfyKtVk=",
+ "dev": true,
+ "peer": true,
+ "dependencies": {
+ "has-value": "^0.3.1",
+ "isobject": "^3.0.0"
+ },
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
+ "node_modules/unset-value/node_modules/has-value": {
+ "version": "0.3.1",
+ "resolved": "https://registry.npmjs.org/has-value/-/has-value-0.3.1.tgz",
+ "integrity": "sha1-ex9YutpiyoJ+wKIHgCVlSEWZXh8=",
+ "dev": true,
+ "peer": true,
+ "dependencies": {
+ "get-value": "^2.0.3",
+ "has-values": "^0.1.4",
+ "isobject": "^2.0.0"
+ },
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
+ "node_modules/unset-value/node_modules/has-value/node_modules/isobject": {
+ "version": "2.1.0",
+ "resolved": "https://registry.npmjs.org/isobject/-/isobject-2.1.0.tgz",
+ "integrity": "sha1-8GVWEJaj8dou9GJy+BXIQNh+DIk=",
+ "dev": true,
+ "peer": true,
+ "dependencies": {
+ "isarray": "1.0.0"
+ },
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
+ "node_modules/unset-value/node_modules/has-values": {
+ "version": "0.1.4",
+ "resolved": "https://registry.npmjs.org/has-values/-/has-values-0.1.4.tgz",
+ "integrity": "sha1-bWHeldkd/Km5oCCJrThL/49it3E=",
+ "dev": true,
+ "peer": true,
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
+ "node_modules/uri-js": {
+ "version": "4.4.1",
+ "resolved": "https://registry.npmjs.org/uri-js/-/uri-js-4.4.1.tgz",
+ "integrity": "sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg==",
+ "dev": true,
+ "dependencies": {
+ "punycode": "^2.1.0"
+ }
+ },
+ "node_modules/urix": {
+ "version": "0.1.0",
+ "resolved": "https://registry.npmjs.org/urix/-/urix-0.1.0.tgz",
+ "integrity": "sha1-2pN/emLiH+wf0Y1Js1wpNQZ6bHI=",
+ "deprecated": "Please see https://github.com/lydell/urix#deprecated",
+ "dev": true,
+ "peer": true
+ },
+ "node_modules/url-parse": {
+ "version": "1.5.10",
+ "resolved": "https://registry.npmjs.org/url-parse/-/url-parse-1.5.10.tgz",
+ "integrity": "sha512-WypcfiRhfeUP9vvF0j6rw0J3hrWrw6iZv3+22h6iRMJ/8z1Tj6XfLP4DsUix5MhMPnXpiHDoKyoZ/bdCkwBCiQ==",
+ "dev": true,
+ "peer": true,
+ "dependencies": {
+ "querystringify": "^2.1.1",
+ "requires-port": "^1.0.0"
+ }
+ },
+ "node_modules/url-regex": {
+ "version": "5.0.0",
+ "resolved": "https://registry.npmjs.org/url-regex/-/url-regex-5.0.0.tgz",
+ "integrity": "sha512-O08GjTiAFNsSlrUWfqF1jH0H1W3m35ZyadHrGv5krdnmPPoxP27oDTqux/579PtaroiSGm5yma6KT1mHFH6Y/g==",
+ "dev": true,
+ "dependencies": {
+ "ip-regex": "^4.1.0",
+ "tlds": "^1.203.0"
+ },
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/use": {
+ "version": "3.1.1",
+ "resolved": "https://registry.npmjs.org/use/-/use-3.1.1.tgz",
+ "integrity": "sha512-cwESVXlO3url9YWlFW/TA9cshCEhtu7IKJ/p5soJ/gGpj7vbvFrAY/eIioQ6Dw23KjZhYgiIo8HOs1nQ2vr/oQ==",
+ "dev": true,
+ "peer": true,
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
+ "node_modules/use-sync-external-store": {
+ "version": "1.2.0",
+ "resolved": "https://registry.npmjs.org/use-sync-external-store/-/use-sync-external-store-1.2.0.tgz",
+ "integrity": "sha512-eEgnFxGQ1Ife9bzYs6VLi8/4X6CObHMw9Qr9tPY43iKwsPw8xE8+EFsf/2cFZ5S3esXgpWgtSCtLNS41F+sKPA==",
+ "dev": true,
+ "peerDependencies": {
+ "react": "^16.8.0 || ^17.0.0 || ^18.0.0"
+ }
+ },
+ "node_modules/util-deprecate": {
+ "version": "1.0.2",
+ "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz",
+ "integrity": "sha1-RQ1Nyfpw3nMnYvvS1KKJgUGaDM8=",
+ "dev": true
+ },
+ "node_modules/uuid": {
+ "version": "8.3.2",
+ "resolved": "https://registry.npmjs.org/uuid/-/uuid-8.3.2.tgz",
+ "integrity": "sha512-+NYs2QeMWy+GWFOEm9xnn6HCDp0l7QBD7ml8zLUmJ+93Q5NF0NocErnwkTkXVFNiX3/fpC6afS8Dhb/gz7R7eg==",
+ "dev": true,
+ "optional": true,
+ "peer": true,
+ "bin": {
+ "uuid": "dist/bin/uuid"
+ }
+ },
+ "node_modules/v8-compile-cache": {
+ "version": "2.3.0",
+ "resolved": "https://registry.npmjs.org/v8-compile-cache/-/v8-compile-cache-2.3.0.tgz",
+ "integrity": "sha512-l8lCEmLcLYZh4nbunNZvQCJc5pv7+RCwa8q/LdUx8u7lsWvPDKmpodJAJNwkAhJC//dFY48KuIEmjtd4RViDrA==",
+ "dev": true
+ },
+ "node_modules/v8-to-istanbul": {
+ "version": "7.1.2",
+ "resolved": "https://registry.npmjs.org/v8-to-istanbul/-/v8-to-istanbul-7.1.2.tgz",
+ "integrity": "sha512-TxNb7YEUwkLXCQYeudi6lgQ/SZrzNO4kMdlqVxaZPUIUjCv6iSSypUQX70kNBSERpQ8fk48+d61FXk+tgqcWow==",
+ "dev": true,
+ "peer": true,
+ "dependencies": {
+ "@types/istanbul-lib-coverage": "^2.0.1",
+ "convert-source-map": "^1.6.0",
+ "source-map": "^0.7.3"
+ },
+ "engines": {
+ "node": ">=10.10.0"
+ }
+ },
+ "node_modules/v8-to-istanbul/node_modules/source-map": {
+ "version": "0.7.3",
+ "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.7.3.tgz",
+ "integrity": "sha512-CkCj6giN3S+n9qrYiBTX5gystlENnRW5jZeNLHpe6aue+SrHcG5VYwujhW9s4dY31mEGsxBDrHR6oI69fTXsaQ==",
+ "dev": true,
+ "peer": true,
+ "engines": {
+ "node": ">= 8"
+ }
+ },
+ "node_modules/validate-npm-package-license": {
+ "version": "3.0.4",
+ "resolved": "https://registry.npmjs.org/validate-npm-package-license/-/validate-npm-package-license-3.0.4.tgz",
+ "integrity": "sha512-DpKm2Ui/xN7/HQKCtpZxoRWBhZ9Z0kqtygG8XCgNQ8ZlDnxuQmWhj566j8fN4Cu3/JmbhsDo7fcAJq4s9h27Ew==",
+ "dev": true,
+ "dependencies": {
+ "spdx-correct": "^3.0.0",
+ "spdx-expression-parse": "^3.0.0"
+ }
+ },
+ "node_modules/vfile": {
+ "version": "4.2.1",
+ "resolved": "https://registry.npmjs.org/vfile/-/vfile-4.2.1.tgz",
+ "integrity": "sha512-O6AE4OskCG5S1emQ/4gl8zK586RqA3srz3nfK/Viy0UPToBc5Trp9BVFb1u0CjsKrAWwnpr4ifM/KBXPWwJbCA==",
+ "dev": true,
+ "dependencies": {
+ "@types/unist": "^2.0.0",
+ "is-buffer": "^2.0.0",
+ "unist-util-stringify-position": "^2.0.0",
+ "vfile-message": "^2.0.0"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/unified"
+ }
+ },
+ "node_modules/vfile-location": {
+ "version": "3.2.0",
+ "resolved": "https://registry.npmjs.org/vfile-location/-/vfile-location-3.2.0.tgz",
+ "integrity": "sha512-aLEIZKv/oxuCDZ8lkJGhuhztf/BW4M+iHdCwglA/eWc+vtuRFJj8EtgceYFX4LRjOhCAAiNHsKGssC6onJ+jbA==",
+ "dev": true,
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/unified"
+ }
+ },
+ "node_modules/vfile-matter": {
+ "version": "4.0.1",
+ "resolved": "https://registry.npmjs.org/vfile-matter/-/vfile-matter-4.0.1.tgz",
+ "integrity": "sha512-ZeACdaxCOxhePpoLO4A5y/VgI9EuWBXu+sUk65aQ7lXBZDFg7X0tuOzigLJUtsQzazFt6K2m9SdlDxZdfL5vVg==",
+ "dev": true,
+ "dependencies": {
+ "is-buffer": "^2.0.0",
+ "vfile": "^5.0.0",
+ "yaml": "^2.0.0"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/unified"
+ }
+ },
+ "node_modules/vfile-matter/node_modules/unist-util-stringify-position": {
+ "version": "3.0.3",
+ "resolved": "https://registry.npmjs.org/unist-util-stringify-position/-/unist-util-stringify-position-3.0.3.tgz",
+ "integrity": "sha512-k5GzIBZ/QatR8N5X2y+drfpWG8IDBzdnVj6OInRNWm1oXrzydiaAT2OQiA8DPRRZyAKb9b6I2a6PxYklZD0gKg==",
+ "dev": true,
+ "dependencies": {
+ "@types/unist": "^2.0.0"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/unified"
+ }
+ },
+ "node_modules/vfile-matter/node_modules/vfile": {
+ "version": "5.3.7",
+ "resolved": "https://registry.npmjs.org/vfile/-/vfile-5.3.7.tgz",
+ "integrity": "sha512-r7qlzkgErKjobAmyNIkkSpizsFPYiUPuJb5pNW1RB4JcYVZhs4lIbVqk8XPk033CV/1z8ss5pkax8SuhGpcG8g==",
+ "dev": true,
+ "dependencies": {
+ "@types/unist": "^2.0.0",
+ "is-buffer": "^2.0.0",
+ "unist-util-stringify-position": "^3.0.0",
+ "vfile-message": "^3.0.0"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/unified"
+ }
+ },
+ "node_modules/vfile-matter/node_modules/vfile-message": {
+ "version": "3.1.4",
+ "resolved": "https://registry.npmjs.org/vfile-message/-/vfile-message-3.1.4.tgz",
+ "integrity": "sha512-fa0Z6P8HUrQN4BZaX05SIVXic+7kE3b05PWAtPuYP9QLHsLKYR7/AlLW3NtOrpXRLeawpDLMsVkmk5DG0NXgWw==",
+ "dev": true,
+ "dependencies": {
+ "@types/unist": "^2.0.0",
+ "unist-util-stringify-position": "^3.0.0"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/unified"
+ }
+ },
+ "node_modules/vfile-matter/node_modules/yaml": {
+ "version": "2.2.1",
+ "resolved": "https://registry.npmjs.org/yaml/-/yaml-2.2.1.tgz",
+ "integrity": "sha512-e0WHiYql7+9wr4cWMx3TVQrNwejKaEe7/rHNmQmqRjazfOP5W8PB6Jpebb5o6fIapbz9o9+2ipcaTM2ZwDI6lw==",
+ "dev": true,
+ "engines": {
+ "node": ">= 14"
+ }
+ },
+ "node_modules/vfile-message": {
+ "version": "2.0.4",
+ "resolved": "https://registry.npmjs.org/vfile-message/-/vfile-message-2.0.4.tgz",
+ "integrity": "sha512-DjssxRGkMvifUOJre00juHoP9DPWuzjxKuMDrhNbk2TdaYYBNMStsNhEOt3idrtI12VQYM/1+iM0KOzXi4pxwQ==",
+ "dev": true,
+ "dependencies": {
+ "@types/unist": "^2.0.0",
+ "unist-util-stringify-position": "^2.0.0"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/unified"
+ }
+ },
+ "node_modules/vfile-reporter": {
+ "version": "7.0.5",
+ "resolved": "https://registry.npmjs.org/vfile-reporter/-/vfile-reporter-7.0.5.tgz",
+ "integrity": "sha512-NdWWXkv6gcd7AZMvDomlQbK3MqFWL1RlGzMn++/O2TI+68+nqxCPTvLugdOtfSzXmjh+xUyhp07HhlrbJjT+mw==",
+ "dev": true,
+ "dependencies": {
+ "@types/supports-color": "^8.0.0",
+ "string-width": "^5.0.0",
+ "supports-color": "^9.0.0",
+ "unist-util-stringify-position": "^3.0.0",
+ "vfile": "^5.0.0",
+ "vfile-message": "^3.0.0",
+ "vfile-sort": "^3.0.0",
+ "vfile-statistics": "^2.0.0"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/unified"
+ }
+ },
+ "node_modules/vfile-reporter-json": {
+ "version": "3.3.0",
+ "resolved": "https://registry.npmjs.org/vfile-reporter-json/-/vfile-reporter-json-3.3.0.tgz",
+ "integrity": "sha512-/zgRtjxQ2UGJn+HViiZ7+nIXtUzkkXFQum3BmaS/bSyr10P0X41ETRqqwMJ95RtbKUah3m7pKb6oS1eZeXXHzQ==",
+ "dev": true,
+ "dependencies": {
+ "vfile": "^5.0.0",
+ "vfile-message": "^3.0.0"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/unified"
+ }
+ },
+ "node_modules/vfile-reporter-json/node_modules/unist-util-stringify-position": {
+ "version": "3.0.3",
+ "resolved": "https://registry.npmjs.org/unist-util-stringify-position/-/unist-util-stringify-position-3.0.3.tgz",
+ "integrity": "sha512-k5GzIBZ/QatR8N5X2y+drfpWG8IDBzdnVj6OInRNWm1oXrzydiaAT2OQiA8DPRRZyAKb9b6I2a6PxYklZD0gKg==",
+ "dev": true,
+ "dependencies": {
+ "@types/unist": "^2.0.0"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/unified"
+ }
+ },
+ "node_modules/vfile-reporter-json/node_modules/vfile": {
+ "version": "5.3.7",
+ "resolved": "https://registry.npmjs.org/vfile/-/vfile-5.3.7.tgz",
+ "integrity": "sha512-r7qlzkgErKjobAmyNIkkSpizsFPYiUPuJb5pNW1RB4JcYVZhs4lIbVqk8XPk033CV/1z8ss5pkax8SuhGpcG8g==",
+ "dev": true,
+ "dependencies": {
+ "@types/unist": "^2.0.0",
+ "is-buffer": "^2.0.0",
+ "unist-util-stringify-position": "^3.0.0",
+ "vfile-message": "^3.0.0"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/unified"
+ }
+ },
+ "node_modules/vfile-reporter-json/node_modules/vfile-message": {
+ "version": "3.1.4",
+ "resolved": "https://registry.npmjs.org/vfile-message/-/vfile-message-3.1.4.tgz",
+ "integrity": "sha512-fa0Z6P8HUrQN4BZaX05SIVXic+7kE3b05PWAtPuYP9QLHsLKYR7/AlLW3NtOrpXRLeawpDLMsVkmk5DG0NXgWw==",
+ "dev": true,
+ "dependencies": {
+ "@types/unist": "^2.0.0",
+ "unist-util-stringify-position": "^3.0.0"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/unified"
+ }
+ },
+ "node_modules/vfile-reporter/node_modules/ansi-regex": {
+ "version": "6.0.1",
+ "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-6.0.1.tgz",
+ "integrity": "sha512-n5M855fKb2SsfMIiFFoVrABHJC8QtHwVx+mHWP3QcEqBHYienj5dHSgjbxtC0WEZXYt4wcD6zrQElDPhFuZgfA==",
+ "dev": true,
+ "engines": {
+ "node": ">=12"
+ },
+ "funding": {
+ "url": "https://github.com/chalk/ansi-regex?sponsor=1"
+ }
+ },
+ "node_modules/vfile-reporter/node_modules/string-width": {
+ "version": "5.1.2",
+ "resolved": "https://registry.npmjs.org/string-width/-/string-width-5.1.2.tgz",
+ "integrity": "sha512-HnLOCR3vjcY8beoNLtcjZ5/nxn2afmME6lhrDrebokqMap+XbeW8n9TXpPDOqdGK5qcI3oT0GKTW6wC7EMiVqA==",
+ "dev": true,
+ "dependencies": {
+ "eastasianwidth": "^0.2.0",
+ "emoji-regex": "^9.2.2",
+ "strip-ansi": "^7.0.1"
+ },
+ "engines": {
+ "node": ">=12"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
+ "node_modules/vfile-reporter/node_modules/strip-ansi": {
+ "version": "7.0.1",
+ "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-7.0.1.tgz",
+ "integrity": "sha512-cXNxvT8dFNRVfhVME3JAe98mkXDYN2O1l7jmcwMnOslDeESg1rF/OZMtK0nRAhiari1unG5cD4jG3rapUAkLbw==",
+ "dev": true,
+ "dependencies": {
+ "ansi-regex": "^6.0.1"
+ },
+ "engines": {
+ "node": ">=12"
+ },
+ "funding": {
+ "url": "https://github.com/chalk/strip-ansi?sponsor=1"
+ }
+ },
+ "node_modules/vfile-reporter/node_modules/supports-color": {
+ "version": "9.3.1",
+ "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-9.3.1.tgz",
+ "integrity": "sha512-knBY82pjmnIzK3NifMo3RxEIRD9E0kIzV4BKcyTZ9+9kWgLMxd4PrsTSMoFQUabgRBbF8KOLRDCyKgNV+iK44Q==",
+ "dev": true,
+ "engines": {
+ "node": ">=12"
+ },
+ "funding": {
+ "url": "https://github.com/chalk/supports-color?sponsor=1"
+ }
+ },
+ "node_modules/vfile-reporter/node_modules/unist-util-stringify-position": {
+ "version": "3.0.3",
+ "resolved": "https://registry.npmjs.org/unist-util-stringify-position/-/unist-util-stringify-position-3.0.3.tgz",
+ "integrity": "sha512-k5GzIBZ/QatR8N5X2y+drfpWG8IDBzdnVj6OInRNWm1oXrzydiaAT2OQiA8DPRRZyAKb9b6I2a6PxYklZD0gKg==",
+ "dev": true,
+ "dependencies": {
+ "@types/unist": "^2.0.0"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/unified"
+ }
+ },
+ "node_modules/vfile-reporter/node_modules/vfile": {
+ "version": "5.3.7",
+ "resolved": "https://registry.npmjs.org/vfile/-/vfile-5.3.7.tgz",
+ "integrity": "sha512-r7qlzkgErKjobAmyNIkkSpizsFPYiUPuJb5pNW1RB4JcYVZhs4lIbVqk8XPk033CV/1z8ss5pkax8SuhGpcG8g==",
+ "dev": true,
+ "dependencies": {
+ "@types/unist": "^2.0.0",
+ "is-buffer": "^2.0.0",
+ "unist-util-stringify-position": "^3.0.0",
+ "vfile-message": "^3.0.0"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/unified"
+ }
+ },
+ "node_modules/vfile-reporter/node_modules/vfile-message": {
+ "version": "3.1.4",
+ "resolved": "https://registry.npmjs.org/vfile-message/-/vfile-message-3.1.4.tgz",
+ "integrity": "sha512-fa0Z6P8HUrQN4BZaX05SIVXic+7kE3b05PWAtPuYP9QLHsLKYR7/AlLW3NtOrpXRLeawpDLMsVkmk5DG0NXgWw==",
+ "dev": true,
+ "dependencies": {
+ "@types/unist": "^2.0.0",
+ "unist-util-stringify-position": "^3.0.0"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/unified"
+ }
+ },
+ "node_modules/vfile-sort": {
+ "version": "3.0.1",
+ "resolved": "https://registry.npmjs.org/vfile-sort/-/vfile-sort-3.0.1.tgz",
+ "integrity": "sha512-1os1733XY6y0D5x0ugqSeaVJm9lYgj0j5qdcZQFyxlZOSy1jYarL77lLyb5gK4Wqr1d5OxmuyflSO3zKyFnTFw==",
+ "dev": true,
+ "dependencies": {
+ "vfile": "^5.0.0",
+ "vfile-message": "^3.0.0"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/unified"
+ }
+ },
+ "node_modules/vfile-sort/node_modules/unist-util-stringify-position": {
+ "version": "3.0.3",
+ "resolved": "https://registry.npmjs.org/unist-util-stringify-position/-/unist-util-stringify-position-3.0.3.tgz",
+ "integrity": "sha512-k5GzIBZ/QatR8N5X2y+drfpWG8IDBzdnVj6OInRNWm1oXrzydiaAT2OQiA8DPRRZyAKb9b6I2a6PxYklZD0gKg==",
+ "dev": true,
+ "dependencies": {
+ "@types/unist": "^2.0.0"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/unified"
+ }
+ },
+ "node_modules/vfile-sort/node_modules/vfile": {
+ "version": "5.3.7",
+ "resolved": "https://registry.npmjs.org/vfile/-/vfile-5.3.7.tgz",
+ "integrity": "sha512-r7qlzkgErKjobAmyNIkkSpizsFPYiUPuJb5pNW1RB4JcYVZhs4lIbVqk8XPk033CV/1z8ss5pkax8SuhGpcG8g==",
+ "dev": true,
+ "dependencies": {
+ "@types/unist": "^2.0.0",
+ "is-buffer": "^2.0.0",
+ "unist-util-stringify-position": "^3.0.0",
+ "vfile-message": "^3.0.0"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/unified"
+ }
+ },
+ "node_modules/vfile-sort/node_modules/vfile-message": {
+ "version": "3.1.4",
+ "resolved": "https://registry.npmjs.org/vfile-message/-/vfile-message-3.1.4.tgz",
+ "integrity": "sha512-fa0Z6P8HUrQN4BZaX05SIVXic+7kE3b05PWAtPuYP9QLHsLKYR7/AlLW3NtOrpXRLeawpDLMsVkmk5DG0NXgWw==",
+ "dev": true,
+ "dependencies": {
+ "@types/unist": "^2.0.0",
+ "unist-util-stringify-position": "^3.0.0"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/unified"
+ }
+ },
+ "node_modules/vfile-statistics": {
+ "version": "2.0.1",
+ "resolved": "https://registry.npmjs.org/vfile-statistics/-/vfile-statistics-2.0.1.tgz",
+ "integrity": "sha512-W6dkECZmP32EG/l+dp2jCLdYzmnDBIw6jwiLZSER81oR5AHRcVqL+k3Z+pfH1R73le6ayDkJRMk0sutj1bMVeg==",
+ "dev": true,
+ "dependencies": {
+ "vfile": "^5.0.0",
+ "vfile-message": "^3.0.0"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/unified"
+ }
+ },
+ "node_modules/vfile-statistics/node_modules/unist-util-stringify-position": {
+ "version": "3.0.3",
+ "resolved": "https://registry.npmjs.org/unist-util-stringify-position/-/unist-util-stringify-position-3.0.3.tgz",
+ "integrity": "sha512-k5GzIBZ/QatR8N5X2y+drfpWG8IDBzdnVj6OInRNWm1oXrzydiaAT2OQiA8DPRRZyAKb9b6I2a6PxYklZD0gKg==",
+ "dev": true,
+ "dependencies": {
+ "@types/unist": "^2.0.0"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/unified"
+ }
+ },
+ "node_modules/vfile-statistics/node_modules/vfile": {
+ "version": "5.3.7",
+ "resolved": "https://registry.npmjs.org/vfile/-/vfile-5.3.7.tgz",
+ "integrity": "sha512-r7qlzkgErKjobAmyNIkkSpizsFPYiUPuJb5pNW1RB4JcYVZhs4lIbVqk8XPk033CV/1z8ss5pkax8SuhGpcG8g==",
+ "dev": true,
+ "dependencies": {
+ "@types/unist": "^2.0.0",
+ "is-buffer": "^2.0.0",
+ "unist-util-stringify-position": "^3.0.0",
+ "vfile-message": "^3.0.0"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/unified"
+ }
+ },
+ "node_modules/vfile-statistics/node_modules/vfile-message": {
+ "version": "3.1.4",
+ "resolved": "https://registry.npmjs.org/vfile-message/-/vfile-message-3.1.4.tgz",
+ "integrity": "sha512-fa0Z6P8HUrQN4BZaX05SIVXic+7kE3b05PWAtPuYP9QLHsLKYR7/AlLW3NtOrpXRLeawpDLMsVkmk5DG0NXgWw==",
+ "dev": true,
+ "dependencies": {
+ "@types/unist": "^2.0.0",
+ "unist-util-stringify-position": "^3.0.0"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/unified"
+ }
+ },
+ "node_modules/w3c-hr-time": {
+ "version": "1.0.2",
+ "resolved": "https://registry.npmjs.org/w3c-hr-time/-/w3c-hr-time-1.0.2.tgz",
+ "integrity": "sha512-z8P5DvDNjKDoFIHK7q8r8lackT6l+jo/Ye3HOle7l9nICP9lf1Ci25fy9vHd0JOWewkIFzXIEig3TdKT7JQ5fQ==",
+ "dev": true,
+ "peer": true,
+ "dependencies": {
+ "browser-process-hrtime": "^1.0.0"
+ }
+ },
+ "node_modules/w3c-xmlserializer": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/w3c-xmlserializer/-/w3c-xmlserializer-2.0.0.tgz",
+ "integrity": "sha512-4tzD0mF8iSiMiNs30BiLO3EpfGLZUT2MSX/G+o7ZywDzliWQ3OPtTZ0PTC3B3ca1UAf4cJMHB+2Bf56EriJuRA==",
+ "dev": true,
+ "peer": true,
+ "dependencies": {
+ "xml-name-validator": "^3.0.0"
+ },
+ "engines": {
+ "node": ">=10"
+ }
+ },
+ "node_modules/walker": {
+ "version": "1.0.8",
+ "resolved": "https://registry.npmjs.org/walker/-/walker-1.0.8.tgz",
+ "integrity": "sha512-ts/8E8l5b7kY0vlWLewOkDXMmPdLcVV4GmOQLyxuSswIJsweeFZtAsMF7k1Nszz+TYBQrlYRmzOnr398y1JemQ==",
+ "dev": true,
+ "peer": true,
+ "dependencies": {
+ "makeerror": "1.0.12"
+ }
+ },
+ "node_modules/webidl-conversions": {
+ "version": "6.1.0",
+ "resolved": "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-6.1.0.tgz",
+ "integrity": "sha512-qBIvFLGiBpLjfwmYAaHPXsn+ho5xZnGvyGvsarywGNc8VyQJUMHJ8OBKGGrPER0okBeMDaan4mNBlgBROxuI8w==",
+ "dev": true,
+ "peer": true,
+ "engines": {
+ "node": ">=10.4"
+ }
+ },
+ "node_modules/whatwg-encoding": {
+ "version": "1.0.5",
+ "resolved": "https://registry.npmjs.org/whatwg-encoding/-/whatwg-encoding-1.0.5.tgz",
+ "integrity": "sha512-b5lim54JOPN9HtzvK9HFXvBma/rnfFeqsic0hSpjtDbVxR3dJKLc+KB4V6GgiGOvl7CY/KNh8rxSo9DKQrnUEw==",
+ "dev": true,
+ "peer": true,
+ "dependencies": {
+ "iconv-lite": "0.4.24"
+ }
+ },
+ "node_modules/whatwg-mimetype": {
+ "version": "2.3.0",
+ "resolved": "https://registry.npmjs.org/whatwg-mimetype/-/whatwg-mimetype-2.3.0.tgz",
+ "integrity": "sha512-M4yMwr6mAnQz76TbJm914+gPpB/nCwvZbJU28cUD6dR004SAxDLOOSUaB1JDRqLtaOV/vi0IC5lEAGFgrjGv/g==",
+ "dev": true,
+ "peer": true
+ },
+ "node_modules/whatwg-url": {
+ "version": "8.7.0",
+ "resolved": "https://registry.npmjs.org/whatwg-url/-/whatwg-url-8.7.0.tgz",
+ "integrity": "sha512-gAojqb/m9Q8a5IV96E3fHJM70AzCkgt4uXYX2O7EmuyOnLrViCQlsEBmF9UQIu3/aeAIp2U17rtbpZWNntQqdg==",
+ "dev": true,
+ "peer": true,
+ "dependencies": {
+ "lodash": "^4.7.0",
+ "tr46": "^2.1.0",
+ "webidl-conversions": "^6.1.0"
+ },
+ "engines": {
+ "node": ">=10"
+ }
+ },
+ "node_modules/which": {
+ "version": "2.0.2",
+ "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz",
+ "integrity": "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==",
+ "dev": true,
+ "dependencies": {
+ "isexe": "^2.0.0"
+ },
+ "bin": {
+ "node-which": "bin/node-which"
+ },
+ "engines": {
+ "node": ">= 8"
+ }
+ },
+ "node_modules/which-boxed-primitive": {
+ "version": "1.0.2",
+ "resolved": "https://registry.npmjs.org/which-boxed-primitive/-/which-boxed-primitive-1.0.2.tgz",
+ "integrity": "sha512-bwZdv0AKLpplFY2KZRX6TvyuN7ojjr7lwkg6ml0roIy9YeuSr7JS372qlNW18UQYzgYK9ziGcerWqZOmEn9VNg==",
+ "dev": true,
+ "dependencies": {
+ "is-bigint": "^1.0.1",
+ "is-boolean-object": "^1.1.0",
+ "is-number-object": "^1.0.4",
+ "is-string": "^1.0.5",
+ "is-symbol": "^1.0.3"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/which-collection": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/which-collection/-/which-collection-1.0.1.tgz",
+ "integrity": "sha512-W8xeTUwaln8i3K/cY1nGXzdnVZlidBcagyNFtBdD5kxnb4TvGKR7FfSIS3mYpwWS1QUCutfKz8IY8RjftB0+1A==",
+ "dev": true,
+ "dependencies": {
+ "is-map": "^2.0.1",
+ "is-set": "^2.0.1",
+ "is-weakmap": "^2.0.1",
+ "is-weakset": "^2.0.1"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/which-module": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/which-module/-/which-module-2.0.0.tgz",
+ "integrity": "sha1-2e8H3Od7mQK4o6j6SzHD4/fm6Ho=",
+ "dev": true,
+ "peer": true
+ },
+ "node_modules/which-pm-runs": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/which-pm-runs/-/which-pm-runs-1.0.0.tgz",
+ "integrity": "sha1-Zws6+8VS4LVd9rd4DKdGFfI60cs=",
+ "dev": true
+ },
+ "node_modules/which-typed-array": {
+ "version": "1.1.9",
+ "resolved": "https://registry.npmjs.org/which-typed-array/-/which-typed-array-1.1.9.tgz",
+ "integrity": "sha512-w9c4xkx6mPidwp7180ckYWfMmvxpjlZuIudNtDf4N/tTAUB8VJbX25qZoAsrtGuYNnGw3pa0AXgbGKRB8/EceA==",
+ "dev": true,
+ "dependencies": {
+ "available-typed-arrays": "^1.0.5",
+ "call-bind": "^1.0.2",
+ "for-each": "^0.3.3",
+ "gopd": "^1.0.1",
+ "has-tostringtag": "^1.0.0",
+ "is-typed-array": "^1.1.10"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/word-wrap": {
+ "version": "1.2.3",
+ "resolved": "https://registry.npmjs.org/word-wrap/-/word-wrap-1.2.3.tgz",
+ "integrity": "sha512-Hz/mrNwitNRh/HUAtM/VT/5VH+ygD6DV7mYKZAtHOrbs8U7lvPS6xf7EJKMF0uW1KJCl0H701g3ZGus+muE5vQ==",
+ "dev": true,
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
+ "node_modules/wrap-ansi": {
+ "version": "7.0.0",
+ "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-7.0.0.tgz",
+ "integrity": "sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==",
+ "dev": true,
+ "dependencies": {
+ "ansi-styles": "^4.0.0",
+ "string-width": "^4.1.0",
+ "strip-ansi": "^6.0.0"
+ },
+ "engines": {
+ "node": ">=10"
+ },
+ "funding": {
+ "url": "https://github.com/chalk/wrap-ansi?sponsor=1"
+ }
+ },
+ "node_modules/wrappy": {
+ "version": "1.0.2",
+ "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz",
+ "integrity": "sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8=",
+ "dev": true
+ },
+ "node_modules/write-file-atomic": {
+ "version": "3.0.3",
+ "resolved": "https://registry.npmjs.org/write-file-atomic/-/write-file-atomic-3.0.3.tgz",
+ "integrity": "sha512-AvHcyZ5JnSfq3ioSyjrBkH9yW4m7Ayk8/9My/DD9onKeu/94fwrMocemO2QAJFAlnnDN+ZDS+ZjAR5ua1/PV/Q==",
+ "dev": true,
+ "dependencies": {
+ "imurmurhash": "^0.1.4",
+ "is-typedarray": "^1.0.0",
+ "signal-exit": "^3.0.2",
+ "typedarray-to-buffer": "^3.1.5"
+ }
+ },
+ "node_modules/ws": {
+ "version": "7.5.7",
+ "resolved": "https://registry.npmjs.org/ws/-/ws-7.5.7.tgz",
+ "integrity": "sha512-KMvVuFzpKBuiIXW3E4u3mySRO2/mCHSyZDJQM5NQ9Q9KHWHWh0NHgfbRMLLrceUK5qAL4ytALJbpRMjixFZh8A==",
+ "dev": true,
+ "peer": true,
+ "engines": {
+ "node": ">=8.3.0"
+ },
+ "peerDependencies": {
+ "bufferutil": "^4.0.1",
+ "utf-8-validate": "^5.0.2"
+ },
+ "peerDependenciesMeta": {
+ "bufferutil": {
+ "optional": true
+ },
+ "utf-8-validate": {
+ "optional": true
+ }
+ }
+ },
+ "node_modules/xml-name-validator": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/xml-name-validator/-/xml-name-validator-3.0.0.tgz",
+ "integrity": "sha512-A5CUptxDsvxKJEU3yO6DuWBSJz/qizqzJKOMIfUJHETbBw/sFaDxgd6fxm1ewUaM0jZ444Fc5vC5ROYurg/4Pw==",
+ "dev": true,
+ "peer": true
+ },
+ "node_modules/xmlchars": {
+ "version": "2.2.0",
+ "resolved": "https://registry.npmjs.org/xmlchars/-/xmlchars-2.2.0.tgz",
+ "integrity": "sha512-JZnDKK8B0RCDw84FNdDAIpZK+JuJw+s7Lz8nksI7SIuU3UXJJslUthsi+uWBUYOwPFwW7W7PRLRfUKpxjtjFCw==",
+ "dev": true,
+ "peer": true
+ },
+ "node_modules/xtend": {
+ "version": "4.0.2",
+ "resolved": "https://registry.npmjs.org/xtend/-/xtend-4.0.2.tgz",
+ "integrity": "sha512-LKYU1iAXJXUgAXn9URjiu+MWhyUXHsvfp7mcuYm9dSUKK0/CjtrUwFAxD82/mCWbtLsGjFIad0wIsod4zrTAEQ==",
+ "dev": true,
+ "engines": {
+ "node": ">=0.4"
+ }
+ },
+ "node_modules/y18n": {
+ "version": "4.0.3",
+ "resolved": "https://registry.npmjs.org/y18n/-/y18n-4.0.3.tgz",
+ "integrity": "sha512-JKhqTOwSrqNA1NY5lSztJ1GrBiUodLMmIZuLiDaMRJ+itFd+ABVE8XBjOvIWL+rSqNDC74LCSFmlb/U4UZ4hJQ==",
+ "dev": true,
+ "peer": true
+ },
+ "node_modules/yallist": {
+ "version": "4.0.0",
+ "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz",
+ "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==",
+ "dev": true
+ },
+ "node_modules/yaml": {
+ "version": "1.10.2",
+ "resolved": "https://registry.npmjs.org/yaml/-/yaml-1.10.2.tgz",
+ "integrity": "sha512-r3vXyErRCYJ7wg28yvBY5VSoAF8ZvlcW9/BwUzEtUsjvX/DKs24dIkuwjtuprwJJHsbyUbLApepYTR1BN4uHrg==",
+ "dev": true,
+ "engines": {
+ "node": ">= 6"
+ }
+ },
+ "node_modules/yargs": {
+ "version": "15.4.1",
+ "resolved": "https://registry.npmjs.org/yargs/-/yargs-15.4.1.tgz",
+ "integrity": "sha512-aePbxDmcYW++PaqBsJ+HYUFwCdv4LVvdnhBy78E57PIor8/OVvhMrADFFEDh8DHDFRv/O9i3lPhsENjO7QX0+A==",
+ "dev": true,
+ "peer": true,
+ "dependencies": {
+ "cliui": "^6.0.0",
+ "decamelize": "^1.2.0",
+ "find-up": "^4.1.0",
+ "get-caller-file": "^2.0.1",
+ "require-directory": "^2.1.1",
+ "require-main-filename": "^2.0.0",
+ "set-blocking": "^2.0.0",
+ "string-width": "^4.2.0",
+ "which-module": "^2.0.0",
+ "y18n": "^4.0.0",
+ "yargs-parser": "^18.1.2"
+ },
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/yargs-parser": {
+ "version": "20.2.9",
+ "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-20.2.9.tgz",
+ "integrity": "sha512-y11nGElTIV+CT3Zv9t7VKl+Q3hTQoT9a1Qzezhhl6Rp21gJ/IVTW7Z3y9EWXhuUBC2Shnf+DX0antecpAwSP8w==",
+ "dev": true,
+ "engines": {
+ "node": ">=10"
+ }
+ },
+ "node_modules/yargs/node_modules/find-up": {
+ "version": "4.1.0",
+ "resolved": "https://registry.npmjs.org/find-up/-/find-up-4.1.0.tgz",
+ "integrity": "sha512-PpOwAdQ/YlXQ2vj8a3h8IipDuYRi3wceVQQGYWxNINccq40Anw7BlsEXCMbt1Zt+OLA6Fq9suIpIWD0OsnISlw==",
+ "dev": true,
+ "peer": true,
+ "dependencies": {
+ "locate-path": "^5.0.0",
+ "path-exists": "^4.0.0"
+ },
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/yargs/node_modules/locate-path": {
+ "version": "5.0.0",
+ "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-5.0.0.tgz",
+ "integrity": "sha512-t7hw9pI+WvuwNJXwk5zVHpyhIqzg2qTlklJOf0mVxGSbe3Fp2VieZcduNYjaLDoy6p9uGpQEGWG87WpMKlNq8g==",
+ "dev": true,
+ "peer": true,
+ "dependencies": {
+ "p-locate": "^4.1.0"
+ },
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/yargs/node_modules/p-limit": {
+ "version": "2.3.0",
+ "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-2.3.0.tgz",
+ "integrity": "sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w==",
+ "dev": true,
+ "peer": true,
+ "dependencies": {
+ "p-try": "^2.0.0"
+ },
+ "engines": {
+ "node": ">=6"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
+ "node_modules/yargs/node_modules/p-locate": {
+ "version": "4.1.0",
+ "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-4.1.0.tgz",
+ "integrity": "sha512-R79ZZ/0wAxKGu3oYMlz8jy/kbhsNrS7SKZ7PxEHBgJ5+F2mtFW2fK2cOtBh1cHYkQsbzFV7I+EoRKe6Yt0oK7A==",
+ "dev": true,
+ "peer": true,
+ "dependencies": {
+ "p-limit": "^2.2.0"
+ },
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/yargs/node_modules/yargs-parser": {
+ "version": "18.1.3",
+ "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-18.1.3.tgz",
+ "integrity": "sha512-o50j0JeToy/4K6OZcaQmW6lyXXKhq7csREXcDwk2omFPJEwUNOVtJKvmDr9EI1fAJZUyZcRF7kxGBWmRXudrCQ==",
+ "dev": true,
+ "peer": true,
+ "dependencies": {
+ "camelcase": "^5.0.0",
+ "decamelize": "^1.2.0"
+ },
+ "engines": {
+ "node": ">=6"
+ }
+ },
+ "node_modules/yocto-queue": {
+ "version": "0.1.0",
+ "resolved": "https://registry.npmjs.org/yocto-queue/-/yocto-queue-0.1.0.tgz",
+ "integrity": "sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q==",
+ "dev": true,
+ "engines": {
+ "node": ">=10"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
+ "node_modules/zod": {
+ "version": "3.21.4",
+ "resolved": "https://registry.npmjs.org/zod/-/zod-3.21.4.tgz",
+ "integrity": "sha512-m46AKbrzKVzOzs/DZgVnG5H55N1sv1M8qZU3A8RIKbs3mrACDNeIOeilDymVb2HdmP8uwshOCF4uJ8uM9rCqJw==",
+ "dev": true,
+ "funding": {
+ "url": "https://github.com/sponsors/colinhacks"
+ }
+ },
+ "node_modules/zwitch": {
+ "version": "1.0.5",
+ "resolved": "https://registry.npmjs.org/zwitch/-/zwitch-1.0.5.tgz",
+ "integrity": "sha512-V50KMwwzqJV0NpZIZFwfOD5/lyny3WlSzRiXgA0G7VUnRlqttta1L6UQIHzd6EuBY/cHGfwTIck7w1yH6Q5zUw==",
+ "dev": true,
+ "funding": {
+ "type": "github",
+ "url": "https://github.com/sponsors/wooorm"
+ }
+ }
+ },
+ "dependencies": {
+ "@ampproject/remapping": {
+ "version": "2.1.2",
+ "resolved": "https://registry.npmjs.org/@ampproject/remapping/-/remapping-2.1.2.tgz",
+ "integrity": "sha512-hoyByceqwKirw7w3Z7gnIIZC3Wx3J484Y3L/cMpXFbr7d9ZQj2mODrirNzcJa+SM3UlpWXYvKV4RlRpFXlWgXg==",
+ "dev": true,
+ "requires": {
+ "@jridgewell/trace-mapping": "^0.3.0"
+ }
+ },
+ "@babel/code-frame": {
+ "version": "7.16.7",
+ "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.16.7.tgz",
+ "integrity": "sha512-iAXqUn8IIeBTNd72xsFlgaXHkMBMt6y4HJp1tIaK465CWLT/fG1aqB7ykr95gHHmlBdGbFeWWfyB4NJJ0nmeIg==",
+ "dev": true,
+ "requires": {
+ "@babel/highlight": "^7.16.7"
+ }
+ },
+ "@babel/compat-data": {
+ "version": "7.17.7",
+ "resolved": "https://registry.npmjs.org/@babel/compat-data/-/compat-data-7.17.7.tgz",
+ "integrity": "sha512-p8pdE6j0a29TNGebNm7NzYZWB3xVZJBZ7XGs42uAKzQo8VQ3F0By/cQCtUEABwIqw5zo6WA4NbmxsfzADzMKnQ==",
+ "dev": true
+ },
+ "@babel/core": {
+ "version": "7.17.9",
+ "resolved": "https://registry.npmjs.org/@babel/core/-/core-7.17.9.tgz",
+ "integrity": "sha512-5ug+SfZCpDAkVp9SFIZAzlW18rlzsOcJGaetCjkySnrXXDUw9AR8cDUm1iByTmdWM6yxX6/zycaV76w3YTF2gw==",
+ "dev": true,
+ "requires": {
+ "@ampproject/remapping": "^2.1.0",
+ "@babel/code-frame": "^7.16.7",
+ "@babel/generator": "^7.17.9",
+ "@babel/helper-compilation-targets": "^7.17.7",
+ "@babel/helper-module-transforms": "^7.17.7",
+ "@babel/helpers": "^7.17.9",
+ "@babel/parser": "^7.17.9",
+ "@babel/template": "^7.16.7",
+ "@babel/traverse": "^7.17.9",
+ "@babel/types": "^7.17.0",
+ "convert-source-map": "^1.7.0",
+ "debug": "^4.1.0",
+ "gensync": "^1.0.0-beta.2",
+ "json5": "^2.2.1",
+ "semver": "^6.3.0"
+ },
+ "dependencies": {
+ "semver": {
+ "version": "6.3.0",
+ "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz",
+ "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==",
+ "dev": true
+ }
+ }
+ },
+ "@babel/generator": {
+ "version": "7.17.9",
+ "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.17.9.tgz",
+ "integrity": "sha512-rAdDousTwxbIxbz5I7GEQ3lUip+xVCXooZNbsydCWs3xA7ZsYOv+CFRdzGxRX78BmQHu9B1Eso59AOZQOJDEdQ==",
+ "dev": true,
+ "requires": {
+ "@babel/types": "^7.17.0",
+ "jsesc": "^2.5.1",
+ "source-map": "^0.5.0"
+ },
+ "dependencies": {
+ "source-map": {
+ "version": "0.5.7",
+ "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz",
+ "integrity": "sha1-igOdLRAh0i0eoUyA2OpGi6LvP8w=",
+ "dev": true
+ }
+ }
+ },
+ "@babel/helper-compilation-targets": {
+ "version": "7.17.7",
+ "resolved": "https://registry.npmjs.org/@babel/helper-compilation-targets/-/helper-compilation-targets-7.17.7.tgz",
+ "integrity": "sha512-UFzlz2jjd8kroj0hmCFV5zr+tQPi1dpC2cRsDV/3IEW8bJfCPrPpmcSN6ZS8RqIq4LXcmpipCQFPddyFA5Yc7w==",
+ "dev": true,
+ "requires": {
+ "@babel/compat-data": "^7.17.7",
+ "@babel/helper-validator-option": "^7.16.7",
+ "browserslist": "^4.17.5",
+ "semver": "^6.3.0"
+ },
+ "dependencies": {
+ "semver": {
+ "version": "6.3.0",
+ "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz",
+ "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==",
+ "dev": true
+ }
+ }
+ },
+ "@babel/helper-environment-visitor": {
+ "version": "7.16.7",
+ "resolved": "https://registry.npmjs.org/@babel/helper-environment-visitor/-/helper-environment-visitor-7.16.7.tgz",
+ "integrity": "sha512-SLLb0AAn6PkUeAfKJCCOl9e1R53pQlGAfc4y4XuMRZfqeMYLE0dM1LMhqbGAlGQY0lfw5/ohoYWAe9V1yibRag==",
+ "dev": true,
+ "requires": {
+ "@babel/types": "^7.16.7"
+ }
+ },
+ "@babel/helper-function-name": {
+ "version": "7.17.9",
+ "resolved": "https://registry.npmjs.org/@babel/helper-function-name/-/helper-function-name-7.17.9.tgz",
+ "integrity": "sha512-7cRisGlVtiVqZ0MW0/yFB4atgpGLWEHUVYnb448hZK4x+vih0YO5UoS11XIYtZYqHd0dIPMdUSv8q5K4LdMnIg==",
+ "dev": true,
+ "requires": {
+ "@babel/template": "^7.16.7",
+ "@babel/types": "^7.17.0"
+ }
+ },
+ "@babel/helper-hoist-variables": {
+ "version": "7.16.7",
+ "resolved": "https://registry.npmjs.org/@babel/helper-hoist-variables/-/helper-hoist-variables-7.16.7.tgz",
+ "integrity": "sha512-m04d/0Op34H5v7pbZw6pSKP7weA6lsMvfiIAMeIvkY/R4xQtBSMFEigu9QTZ2qB/9l22vsxtM8a+Q8CzD255fg==",
+ "dev": true,
+ "requires": {
+ "@babel/types": "^7.16.7"
+ }
+ },
+ "@babel/helper-module-imports": {
+ "version": "7.16.7",
+ "resolved": "https://registry.npmjs.org/@babel/helper-module-imports/-/helper-module-imports-7.16.7.tgz",
+ "integrity": "sha512-LVtS6TqjJHFc+nYeITRo6VLXve70xmq7wPhWTqDJusJEgGmkAACWwMiTNrvfoQo6hEhFwAIixNkvB0jPXDL8Wg==",
+ "dev": true,
+ "requires": {
+ "@babel/types": "^7.16.7"
+ }
+ },
+ "@babel/helper-module-transforms": {
+ "version": "7.17.7",
+ "resolved": "https://registry.npmjs.org/@babel/helper-module-transforms/-/helper-module-transforms-7.17.7.tgz",
+ "integrity": "sha512-VmZD99F3gNTYB7fJRDTi+u6l/zxY0BE6OIxPSU7a50s6ZUQkHwSDmV92FfM+oCG0pZRVojGYhkR8I0OGeCVREw==",
+ "dev": true,
+ "requires": {
+ "@babel/helper-environment-visitor": "^7.16.7",
+ "@babel/helper-module-imports": "^7.16.7",
+ "@babel/helper-simple-access": "^7.17.7",
+ "@babel/helper-split-export-declaration": "^7.16.7",
+ "@babel/helper-validator-identifier": "^7.16.7",
+ "@babel/template": "^7.16.7",
+ "@babel/traverse": "^7.17.3",
+ "@babel/types": "^7.17.0"
+ }
+ },
+ "@babel/helper-plugin-utils": {
+ "version": "7.20.2",
+ "resolved": "https://registry.npmjs.org/@babel/helper-plugin-utils/-/helper-plugin-utils-7.20.2.tgz",
+ "integrity": "sha512-8RvlJG2mj4huQ4pZ+rU9lqKi9ZKiRmuvGuM2HlWmkmgOhbs6zEAw6IEiJ5cQqGbDzGZOhwuOQNtZMi/ENLjZoQ==",
+ "dev": true
+ },
+ "@babel/helper-simple-access": {
+ "version": "7.17.7",
+ "resolved": "https://registry.npmjs.org/@babel/helper-simple-access/-/helper-simple-access-7.17.7.tgz",
+ "integrity": "sha512-txyMCGroZ96i+Pxr3Je3lzEJjqwaRC9buMUgtomcrLe5Nd0+fk1h0LLA+ixUF5OW7AhHuQ7Es1WcQJZmZsz2XA==",
+ "dev": true,
+ "requires": {
+ "@babel/types": "^7.17.0"
+ }
+ },
+ "@babel/helper-split-export-declaration": {
+ "version": "7.16.7",
+ "resolved": "https://registry.npmjs.org/@babel/helper-split-export-declaration/-/helper-split-export-declaration-7.16.7.tgz",
+ "integrity": "sha512-xbWoy/PFoxSWazIToT9Sif+jJTlrMcndIsaOKvTA6u7QEo7ilkRZpjew18/W3c7nm8fXdUDXh02VXTbZ0pGDNw==",
+ "dev": true,
+ "requires": {
+ "@babel/types": "^7.16.7"
+ }
+ },
+ "@babel/helper-validator-identifier": {
+ "version": "7.16.7",
+ "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.16.7.tgz",
+ "integrity": "sha512-hsEnFemeiW4D08A5gUAZxLBTXpZ39P+a+DGDsHw1yxqyQ/jzFEnxf5uTEGp+3bzAbNOxU1paTgYS4ECU/IgfDw==",
+ "dev": true
+ },
+ "@babel/helper-validator-option": {
+ "version": "7.16.7",
+ "resolved": "https://registry.npmjs.org/@babel/helper-validator-option/-/helper-validator-option-7.16.7.tgz",
+ "integrity": "sha512-TRtenOuRUVo9oIQGPC5G9DgK4743cdxvtOw0weQNpZXaS16SCBi5MNjZF8vba3ETURjZpTbVn7Vvcf2eAwFozQ==",
+ "dev": true
+ },
+ "@babel/helpers": {
+ "version": "7.17.9",
+ "resolved": "https://registry.npmjs.org/@babel/helpers/-/helpers-7.17.9.tgz",
+ "integrity": "sha512-cPCt915ShDWUEzEp3+UNRktO2n6v49l5RSnG9M5pS24hA+2FAc5si+Pn1i4VVbQQ+jh+bIZhPFQOJOzbrOYY1Q==",
+ "dev": true,
+ "requires": {
+ "@babel/template": "^7.16.7",
+ "@babel/traverse": "^7.17.9",
+ "@babel/types": "^7.17.0"
+ }
+ },
+ "@babel/highlight": {
+ "version": "7.17.9",
+ "resolved": "https://registry.npmjs.org/@babel/highlight/-/highlight-7.17.9.tgz",
+ "integrity": "sha512-J9PfEKCbFIv2X5bjTMiZu6Vf341N05QIY+d6FvVKynkG1S7G0j3I0QoRtWIrXhZ+/Nlb5Q0MzqL7TokEJ5BNHg==",
+ "dev": true,
+ "requires": {
+ "@babel/helper-validator-identifier": "^7.16.7",
+ "chalk": "^2.0.0",
+ "js-tokens": "^4.0.0"
+ },
+ "dependencies": {
+ "ansi-styles": {
+ "version": "3.2.1",
+ "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz",
+ "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==",
+ "dev": true,
+ "requires": {
+ "color-convert": "^1.9.0"
+ }
+ },
+ "chalk": {
+ "version": "2.4.2",
+ "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz",
+ "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==",
+ "dev": true,
+ "requires": {
+ "ansi-styles": "^3.2.1",
+ "escape-string-regexp": "^1.0.5",
+ "supports-color": "^5.3.0"
+ }
+ },
+ "color-convert": {
+ "version": "1.9.3",
+ "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz",
+ "integrity": "sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==",
+ "dev": true,
+ "requires": {
+ "color-name": "1.1.3"
+ }
+ },
+ "color-name": {
+ "version": "1.1.3",
+ "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz",
+ "integrity": "sha1-p9BVi9icQveV3UIyj3QIMcpTvCU=",
+ "dev": true
+ },
+ "has-flag": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz",
+ "integrity": "sha1-tdRU3CGZriJWmfNGfloH87lVuv0=",
+ "dev": true
+ },
+ "supports-color": {
+ "version": "5.5.0",
+ "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz",
+ "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==",
+ "dev": true,
+ "requires": {
+ "has-flag": "^3.0.0"
+ }
+ }
+ }
+ },
+ "@babel/parser": {
+ "version": "7.17.9",
+ "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.17.9.tgz",
+ "integrity": "sha512-vqUSBLP8dQHFPdPi9bc5GK9vRkYHJ49fsZdtoJ8EQ8ibpwk5rPKfvNIwChB0KVXcIjcepEBBd2VHC5r9Gy8ueg==",
+ "dev": true
+ },
+ "@babel/plugin-proposal-object-rest-spread": {
+ "version": "7.12.1",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-object-rest-spread/-/plugin-proposal-object-rest-spread-7.12.1.tgz",
+ "integrity": "sha512-s6SowJIjzlhx8o7lsFx5zmY4At6CTtDvgNQDdPzkBQucle58A6b/TTeEBYtyDgmcXjUTM+vE8YOGHZzzbc/ioA==",
+ "dev": true,
+ "requires": {
+ "@babel/helper-plugin-utils": "^7.10.4",
+ "@babel/plugin-syntax-object-rest-spread": "^7.8.0",
+ "@babel/plugin-transform-parameters": "^7.12.1"
+ }
+ },
+ "@babel/plugin-syntax-async-generators": {
+ "version": "7.8.4",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-async-generators/-/plugin-syntax-async-generators-7.8.4.tgz",
+ "integrity": "sha512-tycmZxkGfZaxhMRbXlPXuVFpdWlXpir2W4AMhSJgRKzk/eDlIXOhb2LHWoLpDF7TEHylV5zNhykX6KAgHJmTNw==",
+ "dev": true,
+ "peer": true,
+ "requires": {
+ "@babel/helper-plugin-utils": "^7.8.0"
+ }
+ },
+ "@babel/plugin-syntax-bigint": {
+ "version": "7.8.3",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-bigint/-/plugin-syntax-bigint-7.8.3.tgz",
+ "integrity": "sha512-wnTnFlG+YxQm3vDxpGE57Pj0srRU4sHE/mDkt1qv2YJJSeUAec2ma4WLUnUPeKjyrfntVwe/N6dCXpU+zL3Npg==",
+ "dev": true,
+ "peer": true,
+ "requires": {
+ "@babel/helper-plugin-utils": "^7.8.0"
+ }
+ },
+ "@babel/plugin-syntax-class-properties": {
+ "version": "7.12.13",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-class-properties/-/plugin-syntax-class-properties-7.12.13.tgz",
+ "integrity": "sha512-fm4idjKla0YahUNgFNLCB0qySdsoPiZP3iQE3rky0mBUtMZ23yDJ9SJdg6dXTSDnulOVqiF3Hgr9nbXvXTQZYA==",
+ "dev": true,
+ "peer": true,
+ "requires": {
+ "@babel/helper-plugin-utils": "^7.12.13"
+ }
+ },
+ "@babel/plugin-syntax-import-meta": {
+ "version": "7.10.4",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-import-meta/-/plugin-syntax-import-meta-7.10.4.tgz",
+ "integrity": "sha512-Yqfm+XDx0+Prh3VSeEQCPU81yC+JWZ2pDPFSS4ZdpfZhp4MkFMaDC1UqseovEKwSUpnIL7+vK+Clp7bfh0iD7g==",
+ "dev": true,
+ "peer": true,
+ "requires": {
+ "@babel/helper-plugin-utils": "^7.10.4"
+ }
+ },
+ "@babel/plugin-syntax-json-strings": {
+ "version": "7.8.3",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-json-strings/-/plugin-syntax-json-strings-7.8.3.tgz",
+ "integrity": "sha512-lY6kdGpWHvjoe2vk4WrAapEuBR69EMxZl+RoGRhrFGNYVK8mOPAW8VfbT/ZgrFbXlDNiiaxQnAtgVCZ6jv30EA==",
+ "dev": true,
+ "peer": true,
+ "requires": {
+ "@babel/helper-plugin-utils": "^7.8.0"
+ }
+ },
+ "@babel/plugin-syntax-jsx": {
+ "version": "7.12.1",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-jsx/-/plugin-syntax-jsx-7.12.1.tgz",
+ "integrity": "sha512-1yRi7yAtB0ETgxdY9ti/p2TivUxJkTdhu/ZbF9MshVGqOx1TdB3b7xCXs49Fupgg50N45KcAsRP/ZqWjs9SRjg==",
+ "dev": true,
+ "requires": {
+ "@babel/helper-plugin-utils": "^7.10.4"
+ }
+ },
+ "@babel/plugin-syntax-logical-assignment-operators": {
+ "version": "7.10.4",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-logical-assignment-operators/-/plugin-syntax-logical-assignment-operators-7.10.4.tgz",
+ "integrity": "sha512-d8waShlpFDinQ5MtvGU9xDAOzKH47+FFoney2baFIoMr952hKOLp1HR7VszoZvOsV/4+RRszNY7D17ba0te0ig==",
+ "dev": true,
+ "peer": true,
+ "requires": {
+ "@babel/helper-plugin-utils": "^7.10.4"
+ }
+ },
+ "@babel/plugin-syntax-nullish-coalescing-operator": {
+ "version": "7.8.3",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-nullish-coalescing-operator/-/plugin-syntax-nullish-coalescing-operator-7.8.3.tgz",
+ "integrity": "sha512-aSff4zPII1u2QD7y+F8oDsz19ew4IGEJg9SVW+bqwpwtfFleiQDMdzA/R+UlWDzfnHFCxxleFT0PMIrR36XLNQ==",
+ "dev": true,
+ "peer": true,
+ "requires": {
+ "@babel/helper-plugin-utils": "^7.8.0"
+ }
+ },
+ "@babel/plugin-syntax-numeric-separator": {
+ "version": "7.10.4",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-numeric-separator/-/plugin-syntax-numeric-separator-7.10.4.tgz",
+ "integrity": "sha512-9H6YdfkcK/uOnY/K7/aA2xpzaAgkQn37yzWUMRK7OaPOqOpGS1+n0H5hxT9AUw9EsSjPW8SVyMJwYRtWs3X3ug==",
+ "dev": true,
+ "peer": true,
+ "requires": {
+ "@babel/helper-plugin-utils": "^7.10.4"
+ }
+ },
+ "@babel/plugin-syntax-object-rest-spread": {
+ "version": "7.8.3",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-object-rest-spread/-/plugin-syntax-object-rest-spread-7.8.3.tgz",
+ "integrity": "sha512-XoqMijGZb9y3y2XskN+P1wUGiVwWZ5JmoDRwx5+3GmEplNyVM2s2Dg8ILFQm8rWM48orGy5YpI5Bl8U1y7ydlA==",
+ "dev": true,
+ "requires": {
+ "@babel/helper-plugin-utils": "^7.8.0"
+ }
+ },
+ "@babel/plugin-syntax-optional-catch-binding": {
+ "version": "7.8.3",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-optional-catch-binding/-/plugin-syntax-optional-catch-binding-7.8.3.tgz",
+ "integrity": "sha512-6VPD0Pc1lpTqw0aKoeRTMiB+kWhAoT24PA+ksWSBrFtl5SIRVpZlwN3NNPQjehA2E/91FV3RjLWoVTglWcSV3Q==",
+ "dev": true,
+ "peer": true,
+ "requires": {
+ "@babel/helper-plugin-utils": "^7.8.0"
+ }
+ },
+ "@babel/plugin-syntax-optional-chaining": {
+ "version": "7.8.3",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-optional-chaining/-/plugin-syntax-optional-chaining-7.8.3.tgz",
+ "integrity": "sha512-KoK9ErH1MBlCPxV0VANkXW2/dw4vlbGDrFgz8bmUsBGYkFRcbRwMh6cIJubdPrkxRwuGdtCk0v/wPTKbQgBjkg==",
+ "dev": true,
+ "peer": true,
+ "requires": {
+ "@babel/helper-plugin-utils": "^7.8.0"
+ }
+ },
+ "@babel/plugin-syntax-top-level-await": {
+ "version": "7.14.5",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-top-level-await/-/plugin-syntax-top-level-await-7.14.5.tgz",
+ "integrity": "sha512-hx++upLv5U1rgYfwe1xBQUhRmU41NEvpUvrp8jkrSCdvGSnM5/qdRMtylJ6PG5OFkBaHkbTAKTnd3/YyESRHFw==",
+ "dev": true,
+ "peer": true,
+ "requires": {
+ "@babel/helper-plugin-utils": "^7.14.5"
+ }
+ },
+ "@babel/plugin-transform-parameters": {
+ "version": "7.21.3",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-transform-parameters/-/plugin-transform-parameters-7.21.3.tgz",
+ "integrity": "sha512-Wxc+TvppQG9xWFYatvCGPvZ6+SIUxQ2ZdiBP+PHYMIjnPXD+uThCshaz4NZOnODAtBjjcVQQ/3OKs9LW28purQ==",
+ "dev": true,
+ "requires": {
+ "@babel/helper-plugin-utils": "^7.20.2"
+ }
+ },
+ "@babel/runtime": {
+ "version": "7.21.0",
+ "resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.21.0.tgz",
+ "integrity": "sha512-xwII0//EObnq89Ji5AKYQaRYiW/nZ3llSv29d49IuxPhKbtJoLP+9QUUZ4nVragQVtaVGeZrpB+ZtG/Pdy/POw==",
+ "dev": true,
+ "requires": {
+ "regenerator-runtime": "^0.13.11"
+ }
+ },
+ "@babel/template": {
+ "version": "7.16.7",
+ "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.16.7.tgz",
+ "integrity": "sha512-I8j/x8kHUrbYRTUxXrrMbfCa7jxkE7tZre39x3kjr9hvI82cK1FfqLygotcWN5kdPGWcLdWMHpSBavse5tWw3w==",
+ "dev": true,
+ "requires": {
+ "@babel/code-frame": "^7.16.7",
+ "@babel/parser": "^7.16.7",
+ "@babel/types": "^7.16.7"
+ }
+ },
+ "@babel/traverse": {
+ "version": "7.17.9",
+ "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.17.9.tgz",
+ "integrity": "sha512-PQO8sDIJ8SIwipTPiR71kJQCKQYB5NGImbOviK8K+kg5xkNSYXLBupuX9QhatFowrsvo9Hj8WgArg3W7ijNAQw==",
+ "dev": true,
+ "requires": {
+ "@babel/code-frame": "^7.16.7",
+ "@babel/generator": "^7.17.9",
+ "@babel/helper-environment-visitor": "^7.16.7",
+ "@babel/helper-function-name": "^7.17.9",
+ "@babel/helper-hoist-variables": "^7.16.7",
+ "@babel/helper-split-export-declaration": "^7.16.7",
+ "@babel/parser": "^7.17.9",
+ "@babel/types": "^7.17.0",
+ "debug": "^4.1.0",
+ "globals": "^11.1.0"
+ },
+ "dependencies": {
+ "globals": {
+ "version": "11.12.0",
+ "resolved": "https://registry.npmjs.org/globals/-/globals-11.12.0.tgz",
+ "integrity": "sha512-WOBp/EEGUiIsJSp7wcv/y6MO+lV9UoncWqxuFfm8eBwzWNgyfBd6Gz+IeKQ9jCmyhoH99g15M3T+QaVHFjizVA==",
+ "dev": true
+ }
+ }
+ },
+ "@babel/types": {
+ "version": "7.17.0",
+ "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.17.0.tgz",
+ "integrity": "sha512-TmKSNO4D5rzhL5bjWFcVHHLETzfQ/AmbKpKPOSjlP0WoHZ6L911fgoOKY4Alp/emzG4cHJdyN49zpgkbXFEHHw==",
+ "dev": true,
+ "requires": {
+ "@babel/helper-validator-identifier": "^7.16.7",
+ "to-fast-properties": "^2.0.0"
+ }
+ },
+ "@bcoe/v8-coverage": {
+ "version": "0.2.3",
+ "resolved": "https://registry.npmjs.org/@bcoe/v8-coverage/-/v8-coverage-0.2.3.tgz",
+ "integrity": "sha512-0hYQ8SB4Db5zvZB4axdMHGwEaQjkZzFjQiN9LVYvIFB2nSUHW9tYpxWriPrWDASIxiaXax83REcLxuSdnGPZtw==",
+ "dev": true,
+ "peer": true
+ },
+ "@cnakazawa/watch": {
+ "version": "1.0.4",
+ "resolved": "https://registry.npmjs.org/@cnakazawa/watch/-/watch-1.0.4.tgz",
+ "integrity": "sha512-v9kIhKwjeZThiWrLmj0y17CWoyddASLj9O2yvbZkbvw/N3rWOYy9zkV66ursAoVr0mV15bL8g0c4QZUE6cdDoQ==",
+ "dev": true,
+ "peer": true,
+ "requires": {
+ "exec-sh": "^0.3.2",
+ "minimist": "^1.2.0"
+ }
+ },
+ "@eslint-community/eslint-utils": {
+ "version": "4.2.0",
+ "resolved": "https://registry.npmjs.org/@eslint-community/eslint-utils/-/eslint-utils-4.2.0.tgz",
+ "integrity": "sha512-gB8T4H4DEfX2IV9zGDJPOBgP1e/DbfCPDTtEqUMckpvzS1OYtva8JdFYBqMwYk7xAQ429WGF/UPqn8uQ//h2vQ==",
+ "dev": true,
+ "requires": {
+ "eslint-visitor-keys": "^3.3.0"
+ }
+ },
+ "@eslint-community/regexpp": {
+ "version": "4.4.0",
+ "resolved": "https://registry.npmjs.org/@eslint-community/regexpp/-/regexpp-4.4.0.tgz",
+ "integrity": "sha512-A9983Q0LnDGdLPjxyXQ00sbV+K+O+ko2Dr+CZigbHWtX9pNfxlaBkMR8X1CztI73zuEyEBXTVjx7CE+/VSwDiQ==",
+ "dev": true
+ },
+ "@eslint/eslintrc": {
+ "version": "2.0.1",
+ "resolved": "https://registry.npmjs.org/@eslint/eslintrc/-/eslintrc-2.0.1.tgz",
+ "integrity": "sha512-eFRmABvW2E5Ho6f5fHLqgena46rOj7r7OKHYfLElqcBfGFHHpjBhivyi5+jOEQuSpdc/1phIZJlbC2te+tZNIw==",
+ "dev": true,
+ "requires": {
+ "ajv": "^6.12.4",
+ "debug": "^4.3.2",
+ "espree": "^9.5.0",
+ "globals": "^13.19.0",
+ "ignore": "^5.2.0",
+ "import-fresh": "^3.2.1",
+ "js-yaml": "^4.1.0",
+ "minimatch": "^3.1.2",
+ "strip-json-comments": "^3.1.1"
+ }
+ },
+ "@eslint/js": {
+ "version": "8.36.0",
+ "resolved": "https://registry.npmjs.org/@eslint/js/-/js-8.36.0.tgz",
+ "integrity": "sha512-lxJ9R5ygVm8ZWgYdUweoq5ownDlJ4upvoWmO4eLxBYHdMo+vZ/Rx0EN6MbKWDJOSUGrqJy2Gt+Dyv/VKml0fjg==",
+ "dev": true
+ },
+ "@hashicorp/platform-cli": {
+ "version": "2.6.0",
+ "resolved": "https://registry.npmjs.org/@hashicorp/platform-cli/-/platform-cli-2.6.0.tgz",
+ "integrity": "sha512-nMO7Uiy/A5CT/BCE9RyQt6/Uci7bxwTesxCNWkXlciyqlIrz9WmBa9hr710IiMoDzrzQ1tL6AgFIeTbXs4RTqA==",
+ "dev": true,
+ "requires": {
+ "@hashicorp/platform-cms": "0.3.0",
+ "@typescript-eslint/eslint-plugin": "^5.48.0",
+ "@typescript-eslint/parser": "^5.48.0",
+ "chalk": "4.1.0",
+ "commander": "7.2.0",
+ "ejs": "3.1.5",
+ "eslint": "^8.31.0",
+ "eslint-config-next": "^13.1.1",
+ "eslint-config-prettier": "^8.6.0",
+ "eslint-plugin-jsx-a11y": "^6.6.1",
+ "eslint-plugin-prettier": "^4.2.1",
+ "fs-extra": "9.0.1",
+ "globby": "11.0.1",
+ "inquirer": "7.3.3",
+ "lint-staged": "11.1.2",
+ "open": "7.3.0",
+ "prettier": "2.5.1",
+ "readdirp": "3.5.0",
+ "signale": "1.4.0",
+ "slugify": "1.4.6",
+ "stylelint": "13.8.0",
+ "stylelint-config-css-modules": "2.2.0",
+ "stylelint-config-prettier": "8.0.2",
+ "stylelint-config-standard": "20.0.0",
+ "stylelint-media-use-custom-media": "2.0.0",
+ "stylelint-order": "4.1.0",
+ "stylelint-use-nesting": "3.0.0",
+ "stylelint-value-no-unknown-custom-properties": "3.0.0",
+ "ts-jest": "^26.4.4"
+ },
+ "dependencies": {
+ "prettier": {
+ "version": "2.5.1",
+ "resolved": "https://registry.npmjs.org/prettier/-/prettier-2.5.1.tgz",
+ "integrity": "sha512-vBZcPRUR5MZJwoyi3ZoyQlc1rXeEck8KgeC9AwwOn+exuxLxq5toTRDTSaVrXHxelDMHy9zlicw8u66yxoSUFg==",
+ "dev": true
+ }
+ }
+ },
+ "@hashicorp/platform-cms": {
+ "version": "0.3.0",
+ "resolved": "https://registry.npmjs.org/@hashicorp/platform-cms/-/platform-cms-0.3.0.tgz",
+ "integrity": "sha512-sRX9A+kDEZvfZy8PvGFbEaHjn5G1mEsHwTri1vDnrmKG8apE+ELlug83b0iEkD5wIJi9OqaewMIb0NrLxg9s5A==",
+ "dev": true,
+ "requires": {
+ "rivet-graphql": "0.3.1"
+ }
+ },
+ "@hashicorp/platform-content-conformance": {
+ "version": "0.0.10",
+ "resolved": "https://registry.npmjs.org/@hashicorp/platform-content-conformance/-/platform-content-conformance-0.0.10.tgz",
+ "integrity": "sha512-vXLbd2w9phS4JfFyh17jCiyu+LXVonTfb7WEUK2eMlOL/wxe2umyJvEQaJNzD5bwyYC8LuXGA5JkbnPXnU5ZQg==",
+ "dev": true,
+ "requires": {
+ "find-up": "^6.3.0",
+ "flat": "^5.0.2",
+ "globby": "^13.1.2",
+ "mdast-util-to-string": "^3.1.0",
+ "remark": "12.0.1",
+ "remark-mdx": "^1.6.22",
+ "unified-lint-rule": "^2.1.1",
+ "unist-util-stringify-position": "^3.0.2",
+ "unist-util-visit": "^4.1.1",
+ "vfile": "^5.3.6",
+ "vfile-matter": "^4.0.0",
+ "vfile-reporter": "^7.0.4",
+ "vfile-reporter-json": "^3.2.0",
+ "vfile-statistics": "^2.0.0",
+ "yaml": "^2.1.3",
+ "yargs": "^17.4.1",
+ "zod": "^3.19.1"
+ },
+ "dependencies": {
+ "cliui": {
+ "version": "8.0.1",
+ "resolved": "https://registry.npmjs.org/cliui/-/cliui-8.0.1.tgz",
+ "integrity": "sha512-BSeNnyus75C4//NQ9gQt1/csTXyo/8Sb+afLAkzAptFuMsod9HFokGNudZpi/oQV73hnVK+sR+5PVRMd+Dr7YQ==",
+ "dev": true,
+ "requires": {
+ "string-width": "^4.2.0",
+ "strip-ansi": "^6.0.1",
+ "wrap-ansi": "^7.0.0"
+ }
+ },
+ "find-up": {
+ "version": "6.3.0",
+ "resolved": "https://registry.npmjs.org/find-up/-/find-up-6.3.0.tgz",
+ "integrity": "sha512-v2ZsoEuVHYy8ZIlYqwPe/39Cy+cFDzp4dXPaxNvkEuouymu+2Jbz0PxpKarJHYJTmv2HWT3O382qY8l4jMWthw==",
+ "dev": true,
+ "requires": {
+ "locate-path": "^7.1.0",
+ "path-exists": "^5.0.0"
+ }
+ },
+ "globby": {
+ "version": "13.1.3",
+ "resolved": "https://registry.npmjs.org/globby/-/globby-13.1.3.tgz",
+ "integrity": "sha512-8krCNHXvlCgHDpegPzleMq07yMYTO2sXKASmZmquEYWEmCx6J5UTRbp5RwMJkTJGtcQ44YpiUYUiN0b9mzy8Bw==",
+ "dev": true,
+ "requires": {
+ "dir-glob": "^3.0.1",
+ "fast-glob": "^3.2.11",
+ "ignore": "^5.2.0",
+ "merge2": "^1.4.1",
+ "slash": "^4.0.0"
+ }
+ },
+ "locate-path": {
+ "version": "7.2.0",
+ "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-7.2.0.tgz",
+ "integrity": "sha512-gvVijfZvn7R+2qyPX8mAuKcFGDf6Nc61GdvGafQsHL0sBIxfKzA+usWn4GFC/bk+QdwPUD4kWFJLhElipq+0VA==",
+ "dev": true,
+ "requires": {
+ "p-locate": "^6.0.0"
+ }
+ },
+ "mdast-util-to-string": {
+ "version": "3.1.1",
+ "resolved": "https://registry.npmjs.org/mdast-util-to-string/-/mdast-util-to-string-3.1.1.tgz",
+ "integrity": "sha512-tGvhT94e+cVnQt8JWE9/b3cUQZWS732TJxXHktvP+BYo62PpYD53Ls/6cC60rW21dW+txxiM4zMdc6abASvZKA==",
+ "dev": true,
+ "requires": {
+ "@types/mdast": "^3.0.0"
+ }
+ },
+ "p-limit": {
+ "version": "4.0.0",
+ "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-4.0.0.tgz",
+ "integrity": "sha512-5b0R4txpzjPWVw/cXXUResoD4hb6U/x9BH08L7nw+GN1sezDzPdxeRvpc9c433fZhBan/wusjbCsqwqm4EIBIQ==",
+ "dev": true,
+ "requires": {
+ "yocto-queue": "^1.0.0"
+ }
+ },
+ "p-locate": {
+ "version": "6.0.0",
+ "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-6.0.0.tgz",
+ "integrity": "sha512-wPrq66Llhl7/4AGC6I+cqxT07LhXvWL08LNXz1fENOw0Ap4sRZZ/gZpTTJ5jpurzzzfS2W/Ge9BY3LgLjCShcw==",
+ "dev": true,
+ "requires": {
+ "p-limit": "^4.0.0"
+ }
+ },
+ "path-exists": {
+ "version": "5.0.0",
+ "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-5.0.0.tgz",
+ "integrity": "sha512-RjhtfwJOxzcFmNOi6ltcbcu4Iu+FL3zEj83dk4kAS+fVpTxXLO1b38RvJgT/0QwvV/L3aY9TAnyv0EOqW4GoMQ==",
+ "dev": true
+ },
+ "remark": {
+ "version": "12.0.1",
+ "resolved": "https://registry.npmjs.org/remark/-/remark-12.0.1.tgz",
+ "integrity": "sha512-gS7HDonkdIaHmmP/+shCPejCEEW+liMp/t/QwmF0Xt47Rpuhl32lLtDV1uKWvGoq+kxr5jSgg5oAIpGuyULjUw==",
+ "dev": true,
+ "requires": {
+ "remark-parse": "^8.0.0",
+ "remark-stringify": "^8.0.0",
+ "unified": "^9.0.0"
+ }
+ },
+ "remark-parse": {
+ "version": "8.0.3",
+ "resolved": "https://registry.npmjs.org/remark-parse/-/remark-parse-8.0.3.tgz",
+ "integrity": "sha512-E1K9+QLGgggHxCQtLt++uXltxEprmWzNfg+MxpfHsZlrddKzZ/hZyWHDbK3/Ap8HJQqYJRXP+jHczdL6q6i85Q==",
+ "dev": true,
+ "requires": {
+ "ccount": "^1.0.0",
+ "collapse-white-space": "^1.0.2",
+ "is-alphabetical": "^1.0.0",
+ "is-decimal": "^1.0.0",
+ "is-whitespace-character": "^1.0.0",
+ "is-word-character": "^1.0.0",
+ "markdown-escapes": "^1.0.0",
+ "parse-entities": "^2.0.0",
+ "repeat-string": "^1.5.4",
+ "state-toggle": "^1.0.0",
+ "trim": "0.0.1",
+ "trim-trailing-lines": "^1.0.0",
+ "unherit": "^1.0.4",
+ "unist-util-remove-position": "^2.0.0",
+ "vfile-location": "^3.0.0",
+ "xtend": "^4.0.1"
+ }
+ },
+ "remark-stringify": {
+ "version": "8.1.1",
+ "resolved": "https://registry.npmjs.org/remark-stringify/-/remark-stringify-8.1.1.tgz",
+ "integrity": "sha512-q4EyPZT3PcA3Eq7vPpT6bIdokXzFGp9i85igjmhRyXWmPs0Y6/d2FYwUNotKAWyLch7g0ASZJn/KHHcHZQ163A==",
+ "dev": true,
+ "requires": {
+ "ccount": "^1.0.0",
+ "is-alphanumeric": "^1.0.0",
+ "is-decimal": "^1.0.0",
+ "is-whitespace-character": "^1.0.0",
+ "longest-streak": "^2.0.1",
+ "markdown-escapes": "^1.0.0",
+ "markdown-table": "^2.0.0",
+ "mdast-util-compact": "^2.0.0",
+ "parse-entities": "^2.0.0",
+ "repeat-string": "^1.5.4",
+ "state-toggle": "^1.0.0",
+ "stringify-entities": "^3.0.0",
+ "unherit": "^1.0.4",
+ "xtend": "^4.0.1"
+ }
+ },
+ "slash": {
+ "version": "4.0.0",
+ "resolved": "https://registry.npmjs.org/slash/-/slash-4.0.0.tgz",
+ "integrity": "sha512-3dOsAHXXUkQTpOYcoAxLIorMTp4gIQr5IW3iVb7A7lFIp0VHhnynm9izx6TssdrIcVIESAlVjtnO2K8bg+Coew==",
+ "dev": true
+ },
+ "unist-util-stringify-position": {
+ "version": "3.0.3",
+ "resolved": "https://registry.npmjs.org/unist-util-stringify-position/-/unist-util-stringify-position-3.0.3.tgz",
+ "integrity": "sha512-k5GzIBZ/QatR8N5X2y+drfpWG8IDBzdnVj6OInRNWm1oXrzydiaAT2OQiA8DPRRZyAKb9b6I2a6PxYklZD0gKg==",
+ "dev": true,
+ "requires": {
+ "@types/unist": "^2.0.0"
+ }
+ },
+ "vfile": {
+ "version": "5.3.7",
+ "resolved": "https://registry.npmjs.org/vfile/-/vfile-5.3.7.tgz",
+ "integrity": "sha512-r7qlzkgErKjobAmyNIkkSpizsFPYiUPuJb5pNW1RB4JcYVZhs4lIbVqk8XPk033CV/1z8ss5pkax8SuhGpcG8g==",
+ "dev": true,
+ "requires": {
+ "@types/unist": "^2.0.0",
+ "is-buffer": "^2.0.0",
+ "unist-util-stringify-position": "^3.0.0",
+ "vfile-message": "^3.0.0"
+ }
+ },
+ "vfile-message": {
+ "version": "3.1.4",
+ "resolved": "https://registry.npmjs.org/vfile-message/-/vfile-message-3.1.4.tgz",
+ "integrity": "sha512-fa0Z6P8HUrQN4BZaX05SIVXic+7kE3b05PWAtPuYP9QLHsLKYR7/AlLW3NtOrpXRLeawpDLMsVkmk5DG0NXgWw==",
+ "dev": true,
+ "requires": {
+ "@types/unist": "^2.0.0",
+ "unist-util-stringify-position": "^3.0.0"
+ }
+ },
+ "y18n": {
+ "version": "5.0.8",
+ "resolved": "https://registry.npmjs.org/y18n/-/y18n-5.0.8.tgz",
+ "integrity": "sha512-0pfFzegeDWJHJIAmTLRP2DwHjdF5s7jo9tuztdQxAhINCdvS+3nGINqPd00AphqJR/0LhANUS6/+7SCb98YOfA==",
+ "dev": true
+ },
+ "yaml": {
+ "version": "2.2.1",
+ "resolved": "https://registry.npmjs.org/yaml/-/yaml-2.2.1.tgz",
+ "integrity": "sha512-e0WHiYql7+9wr4cWMx3TVQrNwejKaEe7/rHNmQmqRjazfOP5W8PB6Jpebb5o6fIapbz9o9+2ipcaTM2ZwDI6lw==",
+ "dev": true
+ },
+ "yargs": {
+ "version": "17.7.1",
+ "resolved": "https://registry.npmjs.org/yargs/-/yargs-17.7.1.tgz",
+ "integrity": "sha512-cwiTb08Xuv5fqF4AovYacTFNxk62th7LKJ6BL9IGUpTJrWoU7/7WdQGTP2SjKf1dUNBGzDd28p/Yfs/GI6JrLw==",
+ "dev": true,
+ "requires": {
+ "cliui": "^8.0.1",
+ "escalade": "^3.1.1",
+ "get-caller-file": "^2.0.5",
+ "require-directory": "^2.1.1",
+ "string-width": "^4.2.3",
+ "y18n": "^5.0.5",
+ "yargs-parser": "^21.1.1"
+ }
+ },
+ "yargs-parser": {
+ "version": "21.1.1",
+ "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-21.1.1.tgz",
+ "integrity": "sha512-tVpsJW7DdjecAiFpbIB1e3qxIQsE6NoPc5/eTdrbbIC4h0LVsWhnoa3g+m2HclBIujHzsxZ4VJVA+GUuc2/LBw==",
+ "dev": true
+ },
+ "yocto-queue": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/yocto-queue/-/yocto-queue-1.0.0.tgz",
+ "integrity": "sha512-9bnSc/HEW2uRy67wc+T8UwauLuPJVn28jb+GtJY16iiKWyvmYJRXVT4UamsAEGQfPohgr2q4Tq0sQbQlxTfi1g==",
+ "dev": true
+ }
+ }
+ },
+ "@humanwhocodes/config-array": {
+ "version": "0.11.8",
+ "resolved": "https://registry.npmjs.org/@humanwhocodes/config-array/-/config-array-0.11.8.tgz",
+ "integrity": "sha512-UybHIJzJnR5Qc/MsD9Kr+RpO2h+/P1GhOwdiLPXK5TWk5sgTdu88bTD9UP+CKbPPh5Rni1u0GjAdYQLemG8g+g==",
+ "dev": true,
+ "requires": {
+ "@humanwhocodes/object-schema": "^1.2.1",
+ "debug": "^4.1.1",
+ "minimatch": "^3.0.5"
+ }
+ },
+ "@humanwhocodes/module-importer": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/@humanwhocodes/module-importer/-/module-importer-1.0.1.tgz",
+ "integrity": "sha512-bxveV4V8v5Yb4ncFTT3rPSgZBOpCkjfK0y4oVVVJwIuDVBRMDXrPyXRL988i5ap9m9bnyEEjWfm5WkBmtffLfA==",
+ "dev": true
+ },
+ "@humanwhocodes/object-schema": {
+ "version": "1.2.1",
+ "resolved": "https://registry.npmjs.org/@humanwhocodes/object-schema/-/object-schema-1.2.1.tgz",
+ "integrity": "sha512-ZnQMnLV4e7hDlUvw8H+U8ASL02SS2Gn6+9Ac3wGGLIe7+je2AeAOxPY+izIPJDfFDb7eDjev0Us8MO1iFRN8hA==",
+ "dev": true
+ },
+ "@istanbuljs/load-nyc-config": {
+ "version": "1.1.0",
+ "resolved": "https://registry.npmjs.org/@istanbuljs/load-nyc-config/-/load-nyc-config-1.1.0.tgz",
+ "integrity": "sha512-VjeHSlIzpv/NyD3N0YuHfXOPDIixcA1q2ZV98wsMqcYlPmv2n3Yb2lYP9XMElnaFVXg5A7YLTeLu6V84uQDjmQ==",
+ "dev": true,
+ "peer": true,
+ "requires": {
+ "camelcase": "^5.3.1",
+ "find-up": "^4.1.0",
+ "get-package-type": "^0.1.0",
+ "js-yaml": "^3.13.1",
+ "resolve-from": "^5.0.0"
+ },
+ "dependencies": {
+ "argparse": {
+ "version": "1.0.10",
+ "resolved": "https://registry.npmjs.org/argparse/-/argparse-1.0.10.tgz",
+ "integrity": "sha512-o5Roy6tNG4SL/FOkCAN6RzjiakZS25RLYFrcMttJqbdd8BWrnA+fGz57iN5Pb06pvBGvl5gQ0B48dJlslXvoTg==",
+ "dev": true,
+ "peer": true,
+ "requires": {
+ "sprintf-js": "~1.0.2"
+ }
+ },
+ "find-up": {
+ "version": "4.1.0",
+ "resolved": "https://registry.npmjs.org/find-up/-/find-up-4.1.0.tgz",
+ "integrity": "sha512-PpOwAdQ/YlXQ2vj8a3h8IipDuYRi3wceVQQGYWxNINccq40Anw7BlsEXCMbt1Zt+OLA6Fq9suIpIWD0OsnISlw==",
+ "dev": true,
+ "peer": true,
+ "requires": {
+ "locate-path": "^5.0.0",
+ "path-exists": "^4.0.0"
+ }
+ },
+ "js-yaml": {
+ "version": "3.14.1",
+ "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-3.14.1.tgz",
+ "integrity": "sha512-okMH7OXXJ7YrN9Ok3/SXrnu4iX9yOk+25nqX4imS2npuvTYDmo/QEZoqwZkYaIDk3jVvBOTOIEgEhaLOynBS9g==",
+ "dev": true,
+ "peer": true,
+ "requires": {
+ "argparse": "^1.0.7",
+ "esprima": "^4.0.0"
+ }
+ },
+ "locate-path": {
+ "version": "5.0.0",
+ "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-5.0.0.tgz",
+ "integrity": "sha512-t7hw9pI+WvuwNJXwk5zVHpyhIqzg2qTlklJOf0mVxGSbe3Fp2VieZcduNYjaLDoy6p9uGpQEGWG87WpMKlNq8g==",
+ "dev": true,
+ "peer": true,
+ "requires": {
+ "p-locate": "^4.1.0"
+ }
+ },
+ "p-limit": {
+ "version": "2.3.0",
+ "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-2.3.0.tgz",
+ "integrity": "sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w==",
+ "dev": true,
+ "peer": true,
+ "requires": {
+ "p-try": "^2.0.0"
+ }
+ },
+ "p-locate": {
+ "version": "4.1.0",
+ "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-4.1.0.tgz",
+ "integrity": "sha512-R79ZZ/0wAxKGu3oYMlz8jy/kbhsNrS7SKZ7PxEHBgJ5+F2mtFW2fK2cOtBh1cHYkQsbzFV7I+EoRKe6Yt0oK7A==",
+ "dev": true,
+ "peer": true,
+ "requires": {
+ "p-limit": "^2.2.0"
+ }
+ },
+ "resolve-from": {
+ "version": "5.0.0",
+ "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-5.0.0.tgz",
+ "integrity": "sha512-qYg9KP24dD5qka9J47d0aVky0N+b4fTU89LN9iDnjB5waksiC49rvMB0PrUJQGoTmH50XPiqOvAjDfaijGxYZw==",
+ "dev": true,
+ "peer": true
+ }
+ }
+ },
+ "@istanbuljs/schema": {
+ "version": "0.1.3",
+ "resolved": "https://registry.npmjs.org/@istanbuljs/schema/-/schema-0.1.3.tgz",
+ "integrity": "sha512-ZXRY4jNvVgSVQ8DL3LTcakaAtXwTVUxE81hslsyD2AtoXW/wVob10HkOJ1X/pAlcI7D+2YoZKg5do8G/w6RYgA==",
+ "dev": true,
+ "peer": true
+ },
+ "@jest/console": {
+ "version": "26.6.2",
+ "resolved": "https://registry.npmjs.org/@jest/console/-/console-26.6.2.tgz",
+ "integrity": "sha512-IY1R2i2aLsLr7Id3S6p2BA82GNWryt4oSvEXLAKc+L2zdi89dSkE8xC1C+0kpATG4JhBJREnQOH7/zmccM2B0g==",
+ "dev": true,
+ "peer": true,
+ "requires": {
+ "@jest/types": "^26.6.2",
+ "@types/node": "*",
+ "chalk": "^4.0.0",
+ "jest-message-util": "^26.6.2",
+ "jest-util": "^26.6.2",
+ "slash": "^3.0.0"
+ }
+ },
+ "@jest/core": {
+ "version": "26.6.3",
+ "resolved": "https://registry.npmjs.org/@jest/core/-/core-26.6.3.tgz",
+ "integrity": "sha512-xvV1kKbhfUqFVuZ8Cyo+JPpipAHHAV3kcDBftiduK8EICXmTFddryy3P7NfZt8Pv37rA9nEJBKCCkglCPt/Xjw==",
+ "dev": true,
+ "peer": true,
+ "requires": {
+ "@jest/console": "^26.6.2",
+ "@jest/reporters": "^26.6.2",
+ "@jest/test-result": "^26.6.2",
+ "@jest/transform": "^26.6.2",
+ "@jest/types": "^26.6.2",
+ "@types/node": "*",
+ "ansi-escapes": "^4.2.1",
+ "chalk": "^4.0.0",
+ "exit": "^0.1.2",
+ "graceful-fs": "^4.2.4",
+ "jest-changed-files": "^26.6.2",
+ "jest-config": "^26.6.3",
+ "jest-haste-map": "^26.6.2",
+ "jest-message-util": "^26.6.2",
+ "jest-regex-util": "^26.0.0",
+ "jest-resolve": "^26.6.2",
+ "jest-resolve-dependencies": "^26.6.3",
+ "jest-runner": "^26.6.3",
+ "jest-runtime": "^26.6.3",
+ "jest-snapshot": "^26.6.2",
+ "jest-util": "^26.6.2",
+ "jest-validate": "^26.6.2",
+ "jest-watcher": "^26.6.2",
+ "micromatch": "^4.0.2",
+ "p-each-series": "^2.1.0",
+ "rimraf": "^3.0.0",
+ "slash": "^3.0.0",
+ "strip-ansi": "^6.0.0"
+ }
+ },
+ "@jest/environment": {
+ "version": "26.6.2",
+ "resolved": "https://registry.npmjs.org/@jest/environment/-/environment-26.6.2.tgz",
+ "integrity": "sha512-nFy+fHl28zUrRsCeMB61VDThV1pVTtlEokBRgqPrcT1JNq4yRNIyTHfyht6PqtUvY9IsuLGTrbG8kPXjSZIZwA==",
+ "dev": true,
+ "peer": true,
+ "requires": {
+ "@jest/fake-timers": "^26.6.2",
+ "@jest/types": "^26.6.2",
+ "@types/node": "*",
+ "jest-mock": "^26.6.2"
+ }
+ },
+ "@jest/fake-timers": {
+ "version": "26.6.2",
+ "resolved": "https://registry.npmjs.org/@jest/fake-timers/-/fake-timers-26.6.2.tgz",
+ "integrity": "sha512-14Uleatt7jdzefLPYM3KLcnUl1ZNikaKq34enpb5XG9i81JpppDb5muZvonvKyrl7ftEHkKS5L5/eB/kxJ+bvA==",
+ "dev": true,
+ "peer": true,
+ "requires": {
+ "@jest/types": "^26.6.2",
+ "@sinonjs/fake-timers": "^6.0.1",
+ "@types/node": "*",
+ "jest-message-util": "^26.6.2",
+ "jest-mock": "^26.6.2",
+ "jest-util": "^26.6.2"
+ }
+ },
+ "@jest/globals": {
+ "version": "26.6.2",
+ "resolved": "https://registry.npmjs.org/@jest/globals/-/globals-26.6.2.tgz",
+ "integrity": "sha512-85Ltnm7HlB/KesBUuALwQ68YTU72w9H2xW9FjZ1eL1U3lhtefjjl5c2MiUbpXt/i6LaPRvoOFJ22yCBSfQ0JIA==",
+ "dev": true,
+ "peer": true,
+ "requires": {
+ "@jest/environment": "^26.6.2",
+ "@jest/types": "^26.6.2",
+ "expect": "^26.6.2"
+ }
+ },
+ "@jest/reporters": {
+ "version": "26.6.2",
+ "resolved": "https://registry.npmjs.org/@jest/reporters/-/reporters-26.6.2.tgz",
+ "integrity": "sha512-h2bW53APG4HvkOnVMo8q3QXa6pcaNt1HkwVsOPMBV6LD/q9oSpxNSYZQYkAnjdMjrJ86UuYeLo+aEZClV6opnw==",
+ "dev": true,
+ "peer": true,
+ "requires": {
+ "@bcoe/v8-coverage": "^0.2.3",
+ "@jest/console": "^26.6.2",
+ "@jest/test-result": "^26.6.2",
+ "@jest/transform": "^26.6.2",
+ "@jest/types": "^26.6.2",
+ "chalk": "^4.0.0",
+ "collect-v8-coverage": "^1.0.0",
+ "exit": "^0.1.2",
+ "glob": "^7.1.2",
+ "graceful-fs": "^4.2.4",
+ "istanbul-lib-coverage": "^3.0.0",
+ "istanbul-lib-instrument": "^4.0.3",
+ "istanbul-lib-report": "^3.0.0",
+ "istanbul-lib-source-maps": "^4.0.0",
+ "istanbul-reports": "^3.0.2",
+ "jest-haste-map": "^26.6.2",
+ "jest-resolve": "^26.6.2",
+ "jest-util": "^26.6.2",
+ "jest-worker": "^26.6.2",
+ "node-notifier": "^8.0.0",
+ "slash": "^3.0.0",
+ "source-map": "^0.6.0",
+ "string-length": "^4.0.1",
+ "terminal-link": "^2.0.0",
+ "v8-to-istanbul": "^7.0.0"
+ }
+ },
+ "@jest/source-map": {
+ "version": "26.6.2",
+ "resolved": "https://registry.npmjs.org/@jest/source-map/-/source-map-26.6.2.tgz",
+ "integrity": "sha512-YwYcCwAnNmOVsZ8mr3GfnzdXDAl4LaenZP5z+G0c8bzC9/dugL8zRmxZzdoTl4IaS3CryS1uWnROLPFmb6lVvA==",
+ "dev": true,
+ "peer": true,
+ "requires": {
+ "callsites": "^3.0.0",
+ "graceful-fs": "^4.2.4",
+ "source-map": "^0.6.0"
+ }
+ },
+ "@jest/test-result": {
+ "version": "26.6.2",
+ "resolved": "https://registry.npmjs.org/@jest/test-result/-/test-result-26.6.2.tgz",
+ "integrity": "sha512-5O7H5c/7YlojphYNrK02LlDIV2GNPYisKwHm2QTKjNZeEzezCbwYs9swJySv2UfPMyZ0VdsmMv7jIlD/IKYQpQ==",
+ "dev": true,
+ "peer": true,
+ "requires": {
+ "@jest/console": "^26.6.2",
+ "@jest/types": "^26.6.2",
+ "@types/istanbul-lib-coverage": "^2.0.0",
+ "collect-v8-coverage": "^1.0.0"
+ }
+ },
+ "@jest/test-sequencer": {
+ "version": "26.6.3",
+ "resolved": "https://registry.npmjs.org/@jest/test-sequencer/-/test-sequencer-26.6.3.tgz",
+ "integrity": "sha512-YHlVIjP5nfEyjlrSr8t/YdNfU/1XEt7c5b4OxcXCjyRhjzLYu/rO69/WHPuYcbCWkz8kAeZVZp2N2+IOLLEPGw==",
+ "dev": true,
+ "peer": true,
+ "requires": {
+ "@jest/test-result": "^26.6.2",
+ "graceful-fs": "^4.2.4",
+ "jest-haste-map": "^26.6.2",
+ "jest-runner": "^26.6.3",
+ "jest-runtime": "^26.6.3"
+ }
+ },
+ "@jest/transform": {
+ "version": "26.6.2",
+ "resolved": "https://registry.npmjs.org/@jest/transform/-/transform-26.6.2.tgz",
+ "integrity": "sha512-E9JjhUgNzvuQ+vVAL21vlyfy12gP0GhazGgJC4h6qUt1jSdUXGWJ1wfu/X7Sd8etSgxV4ovT1pb9v5D6QW4XgA==",
+ "dev": true,
+ "peer": true,
+ "requires": {
+ "@babel/core": "^7.1.0",
+ "@jest/types": "^26.6.2",
+ "babel-plugin-istanbul": "^6.0.0",
+ "chalk": "^4.0.0",
+ "convert-source-map": "^1.4.0",
+ "fast-json-stable-stringify": "^2.0.0",
+ "graceful-fs": "^4.2.4",
+ "jest-haste-map": "^26.6.2",
+ "jest-regex-util": "^26.0.0",
+ "jest-util": "^26.6.2",
+ "micromatch": "^4.0.2",
+ "pirates": "^4.0.1",
+ "slash": "^3.0.0",
+ "source-map": "^0.6.1",
+ "write-file-atomic": "^3.0.0"
+ }
+ },
+ "@jest/types": {
+ "version": "26.6.2",
+ "resolved": "https://registry.npmjs.org/@jest/types/-/types-26.6.2.tgz",
+ "integrity": "sha512-fC6QCp7Sc5sX6g8Tvbmj4XUTbyrik0akgRy03yjXbQaBWWNWGE7SGtJk98m0N8nzegD/7SggrUlivxo5ax4KWQ==",
+ "dev": true,
+ "requires": {
+ "@types/istanbul-lib-coverage": "^2.0.0",
+ "@types/istanbul-reports": "^3.0.0",
+ "@types/node": "*",
+ "@types/yargs": "^15.0.0",
+ "chalk": "^4.0.0"
+ }
+ },
+ "@jridgewell/resolve-uri": {
+ "version": "3.0.5",
+ "resolved": "https://registry.npmjs.org/@jridgewell/resolve-uri/-/resolve-uri-3.0.5.tgz",
+ "integrity": "sha512-VPeQ7+wH0itvQxnG+lIzWgkysKIr3L9sslimFW55rHMdGu/qCQ5z5h9zq4gI8uBtqkpHhsF4Z/OwExufUCThew==",
+ "dev": true
+ },
+ "@jridgewell/sourcemap-codec": {
+ "version": "1.4.11",
+ "resolved": "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.4.11.tgz",
+ "integrity": "sha512-Fg32GrJo61m+VqYSdRSjRXMjQ06j8YIYfcTqndLYVAaHmroZHLJZCydsWBOTDqXS2v+mjxohBWEMfg97GXmYQg==",
+ "dev": true
+ },
+ "@jridgewell/trace-mapping": {
+ "version": "0.3.8",
+ "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.8.tgz",
+ "integrity": "sha512-zdpaWDz5IEyHlu1EO+B+qRHmJkSxMVV6SXngDry9n1ZqslLXFH9Dw6lRqDidm/sOJAWdRltJsmZ1SK28/uZKsw==",
+ "dev": true,
+ "requires": {
+ "@jridgewell/resolve-uri": "^3.0.3",
+ "@jridgewell/sourcemap-codec": "^1.4.10"
+ }
+ },
+ "@mdx-js/util": {
+ "version": "1.6.22",
+ "resolved": "https://registry.npmjs.org/@mdx-js/util/-/util-1.6.22.tgz",
+ "integrity": "sha512-H1rQc1ZOHANWBvPcW+JpGwr+juXSxM8Q8YCkm3GhZd8REu1fHR3z99CErO1p9pkcfcxZnMdIZdIsXkOHY0NilA==",
+ "dev": true
+ },
+ "@next/env": {
+ "version": "12.3.1",
+ "resolved": "https://registry.npmjs.org/@next/env/-/env-12.3.1.tgz",
+ "integrity": "sha512-9P9THmRFVKGKt9DYqeC2aKIxm8rlvkK38V1P1sRE7qyoPBIs8l9oo79QoSdPtOWfzkbDAVUqvbQGgTMsb8BtJg==",
+ "dev": true
+ },
+ "@next/eslint-plugin-next": {
+ "version": "13.2.4",
+ "resolved": "https://registry.npmjs.org/@next/eslint-plugin-next/-/eslint-plugin-next-13.2.4.tgz",
+ "integrity": "sha512-ck1lI+7r1mMJpqLNa3LJ5pxCfOB1lfJncKmRJeJxcJqcngaFwylreLP7da6Rrjr6u2gVRTfmnkSkjc80IiQCwQ==",
+ "dev": true,
+ "requires": {
+ "glob": "7.1.7"
+ }
+ },
+ "@next/swc-android-arm-eabi": {
+ "version": "12.3.1",
+ "resolved": "https://registry.npmjs.org/@next/swc-android-arm-eabi/-/swc-android-arm-eabi-12.3.1.tgz",
+ "integrity": "sha512-i+BvKA8tB//srVPPQxIQN5lvfROcfv4OB23/L1nXznP+N/TyKL8lql3l7oo2LNhnH66zWhfoemg3Q4VJZSruzQ==",
+ "dev": true,
+ "optional": true
+ },
+ "@next/swc-android-arm64": {
+ "version": "12.3.1",
+ "resolved": "https://registry.npmjs.org/@next/swc-android-arm64/-/swc-android-arm64-12.3.1.tgz",
+ "integrity": "sha512-CmgU2ZNyBP0rkugOOqLnjl3+eRpXBzB/I2sjwcGZ7/Z6RcUJXK5Evz+N0ucOxqE4cZ3gkTeXtSzRrMK2mGYV8Q==",
+ "dev": true,
+ "optional": true
+ },
+ "@next/swc-darwin-arm64": {
+ "version": "12.3.1",
+ "resolved": "https://registry.npmjs.org/@next/swc-darwin-arm64/-/swc-darwin-arm64-12.3.1.tgz",
+ "integrity": "sha512-hT/EBGNcu0ITiuWDYU9ur57Oa4LybD5DOQp4f22T6zLfpoBMfBibPtR8XktXmOyFHrL/6FC2p9ojdLZhWhvBHg==",
+ "dev": true,
+ "optional": true
+ },
+ "@next/swc-darwin-x64": {
+ "version": "12.3.1",
+ "resolved": "https://registry.npmjs.org/@next/swc-darwin-x64/-/swc-darwin-x64-12.3.1.tgz",
+ "integrity": "sha512-9S6EVueCVCyGf2vuiLiGEHZCJcPAxglyckTZcEwLdJwozLqN0gtS0Eq0bQlGS3dH49Py/rQYpZ3KVWZ9BUf/WA==",
+ "dev": true,
+ "optional": true
+ },
+ "@next/swc-freebsd-x64": {
+ "version": "12.3.1",
+ "resolved": "https://registry.npmjs.org/@next/swc-freebsd-x64/-/swc-freebsd-x64-12.3.1.tgz",
+ "integrity": "sha512-qcuUQkaBZWqzM0F1N4AkAh88lLzzpfE6ImOcI1P6YeyJSsBmpBIV8o70zV+Wxpc26yV9vpzb+e5gCyxNjKJg5Q==",
+ "dev": true,
+ "optional": true
+ },
+ "@next/swc-linux-arm-gnueabihf": {
+ "version": "12.3.1",
+ "resolved": "https://registry.npmjs.org/@next/swc-linux-arm-gnueabihf/-/swc-linux-arm-gnueabihf-12.3.1.tgz",
+ "integrity": "sha512-diL9MSYrEI5nY2wc/h/DBewEDUzr/DqBjIgHJ3RUNtETAOB3spMNHvJk2XKUDjnQuluLmFMloet9tpEqU2TT9w==",
+ "dev": true,
+ "optional": true
+ },
+ "@next/swc-linux-arm64-gnu": {
+ "version": "12.3.1",
+ "resolved": "https://registry.npmjs.org/@next/swc-linux-arm64-gnu/-/swc-linux-arm64-gnu-12.3.1.tgz",
+ "integrity": "sha512-o/xB2nztoaC7jnXU3Q36vGgOolJpsGG8ETNjxM1VAPxRwM7FyGCPHOMk1XavG88QZSQf+1r+POBW0tLxQOJ9DQ==",
+ "dev": true,
+ "optional": true
+ },
+ "@next/swc-linux-arm64-musl": {
+ "version": "12.3.1",
+ "resolved": "https://registry.npmjs.org/@next/swc-linux-arm64-musl/-/swc-linux-arm64-musl-12.3.1.tgz",
+ "integrity": "sha512-2WEasRxJzgAmP43glFNhADpe8zB7kJofhEAVNbDJZANp+H4+wq+/cW1CdDi8DqjkShPEA6/ejJw+xnEyDID2jg==",
+ "dev": true,
+ "optional": true
+ },
+ "@next/swc-linux-x64-gnu": {
+ "version": "12.3.1",
+ "resolved": "https://registry.npmjs.org/@next/swc-linux-x64-gnu/-/swc-linux-x64-gnu-12.3.1.tgz",
+ "integrity": "sha512-JWEaMyvNrXuM3dyy9Pp5cFPuSSvG82+yABqsWugjWlvfmnlnx9HOQZY23bFq3cNghy5V/t0iPb6cffzRWylgsA==",
+ "dev": true,
+ "optional": true
+ },
+ "@next/swc-linux-x64-musl": {
+ "version": "12.3.1",
+ "resolved": "https://registry.npmjs.org/@next/swc-linux-x64-musl/-/swc-linux-x64-musl-12.3.1.tgz",
+ "integrity": "sha512-xoEWQQ71waWc4BZcOjmatuvPUXKTv6MbIFzpm4LFeCHsg2iwai0ILmNXf81rJR+L1Wb9ifEke2sQpZSPNz1Iyg==",
+ "dev": true,
+ "optional": true
+ },
+ "@next/swc-win32-arm64-msvc": {
+ "version": "12.3.1",
+ "resolved": "https://registry.npmjs.org/@next/swc-win32-arm64-msvc/-/swc-win32-arm64-msvc-12.3.1.tgz",
+ "integrity": "sha512-hswVFYQYIeGHE2JYaBVtvqmBQ1CppplQbZJS/JgrVI3x2CurNhEkmds/yqvDONfwfbttTtH4+q9Dzf/WVl3Opw==",
+ "dev": true,
+ "optional": true
+ },
+ "@next/swc-win32-ia32-msvc": {
+ "version": "12.3.1",
+ "resolved": "https://registry.npmjs.org/@next/swc-win32-ia32-msvc/-/swc-win32-ia32-msvc-12.3.1.tgz",
+ "integrity": "sha512-Kny5JBehkTbKPmqulr5i+iKntO5YMP+bVM8Hf8UAmjSMVo3wehyLVc9IZkNmcbxi+vwETnQvJaT5ynYBkJ9dWA==",
+ "dev": true,
+ "optional": true
+ },
+ "@next/swc-win32-x64-msvc": {
+ "version": "12.3.1",
+ "resolved": "https://registry.npmjs.org/@next/swc-win32-x64-msvc/-/swc-win32-x64-msvc-12.3.1.tgz",
+ "integrity": "sha512-W1ijvzzg+kPEX6LAc+50EYYSEo0FVu7dmTE+t+DM4iOLqgGHoW9uYSz9wCVdkXOEEMP9xhXfGpcSxsfDucyPkA==",
+ "dev": true,
+ "optional": true
+ },
+ "@nodelib/fs.scandir": {
+ "version": "2.1.5",
+ "resolved": "https://registry.npmjs.org/@nodelib/fs.scandir/-/fs.scandir-2.1.5.tgz",
+ "integrity": "sha512-vq24Bq3ym5HEQm2NKCr3yXDwjc7vTsEThRDnkp2DK9p1uqLR+DHurm/NOTo0KG7HYHU7eppKZj3MyqYuMBf62g==",
+ "dev": true,
+ "requires": {
+ "@nodelib/fs.stat": "2.0.5",
+ "run-parallel": "^1.1.9"
+ }
+ },
+ "@nodelib/fs.stat": {
+ "version": "2.0.5",
+ "resolved": "https://registry.npmjs.org/@nodelib/fs.stat/-/fs.stat-2.0.5.tgz",
+ "integrity": "sha512-RkhPPp2zrqDAQA/2jNhnztcPAlv64XdhIp7a7454A5ovI7Bukxgt7MX7udwAu3zg1DcpPU0rz3VV1SeaqvY4+A==",
+ "dev": true
+ },
+ "@nodelib/fs.walk": {
+ "version": "1.2.8",
+ "resolved": "https://registry.npmjs.org/@nodelib/fs.walk/-/fs.walk-1.2.8.tgz",
+ "integrity": "sha512-oGB+UxlgWcgQkgwo8GcEGwemoTFt3FIO9ababBmaGwXIoBKZ+GTy0pP185beGg7Llih/NSHSV2XAs1lnznocSg==",
+ "dev": true,
+ "requires": {
+ "@nodelib/fs.scandir": "2.1.5",
+ "fastq": "^1.6.0"
+ }
+ },
+ "@pkgr/utils": {
+ "version": "2.3.1",
+ "resolved": "https://registry.npmjs.org/@pkgr/utils/-/utils-2.3.1.tgz",
+ "integrity": "sha512-wfzX8kc1PMyUILA+1Z/EqoE4UCXGy0iRGMhPwdfae1+f0OXlLqCk+By+aMzgJBzR9AzS4CDizioG6Ss1gvAFJw==",
+ "dev": true,
+ "requires": {
+ "cross-spawn": "^7.0.3",
+ "is-glob": "^4.0.3",
+ "open": "^8.4.0",
+ "picocolors": "^1.0.0",
+ "tiny-glob": "^0.2.9",
+ "tslib": "^2.4.0"
+ },
+ "dependencies": {
+ "open": {
+ "version": "8.4.2",
+ "resolved": "https://registry.npmjs.org/open/-/open-8.4.2.tgz",
+ "integrity": "sha512-7x81NCL719oNbsq/3mh+hVrAWmFuEYUqrq/Iw3kUzH8ReypT9QQ0BLoJS7/G9k6N81XjW4qHWtjWwe/9eLy1EQ==",
+ "dev": true,
+ "requires": {
+ "define-lazy-prop": "^2.0.0",
+ "is-docker": "^2.1.1",
+ "is-wsl": "^2.2.0"
+ }
+ },
+ "tslib": {
+ "version": "2.5.0",
+ "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.5.0.tgz",
+ "integrity": "sha512-336iVw3rtn2BUK7ORdIAHTyxHGRIHVReokCR3XjbckJMK7ms8FysBfhLR8IXnAgy7T0PTPNBWKiH514FOW/WSg==",
+ "dev": true
+ }
+ }
+ },
+ "@rushstack/eslint-patch": {
+ "version": "1.2.0",
+ "resolved": "https://registry.npmjs.org/@rushstack/eslint-patch/-/eslint-patch-1.2.0.tgz",
+ "integrity": "sha512-sXo/qW2/pAcmT43VoRKOJbDOfV3cYpq3szSVfIThQXNt+E4DfKj361vaAt3c88U5tPUxzEswam7GW48PJqtKAg==",
+ "dev": true
+ },
+ "@sinonjs/commons": {
+ "version": "1.8.3",
+ "resolved": "https://registry.npmjs.org/@sinonjs/commons/-/commons-1.8.3.tgz",
+ "integrity": "sha512-xkNcLAn/wZaX14RPlwizcKicDk9G3F8m2nU3L7Ukm5zBgTwiT0wsoFAHx9Jq56fJA1z/7uKGtCRu16sOUCLIHQ==",
+ "dev": true,
+ "peer": true,
+ "requires": {
+ "type-detect": "4.0.8"
+ }
+ },
+ "@sinonjs/fake-timers": {
+ "version": "6.0.1",
+ "resolved": "https://registry.npmjs.org/@sinonjs/fake-timers/-/fake-timers-6.0.1.tgz",
+ "integrity": "sha512-MZPUxrmFubI36XS1DI3qmI0YdN1gks62JtFZvxR67ljjSNCeK6U08Zx4msEWOXuofgqUt6zPHSi1H9fbjR/NRA==",
+ "dev": true,
+ "peer": true,
+ "requires": {
+ "@sinonjs/commons": "^1.7.0"
+ }
+ },
+ "@stylelint/postcss-css-in-js": {
+ "version": "0.37.2",
+ "resolved": "https://registry.npmjs.org/@stylelint/postcss-css-in-js/-/postcss-css-in-js-0.37.2.tgz",
+ "integrity": "sha512-nEhsFoJurt8oUmieT8qy4nk81WRHmJynmVwn/Vts08PL9fhgIsMhk1GId5yAN643OzqEEb5S/6At2TZW7pqPDA==",
+ "dev": true,
+ "requires": {
+ "@babel/core": ">=7.9.0"
+ }
+ },
+ "@stylelint/postcss-markdown": {
+ "version": "0.36.2",
+ "resolved": "https://registry.npmjs.org/@stylelint/postcss-markdown/-/postcss-markdown-0.36.2.tgz",
+ "integrity": "sha512-2kGbqUVJUGE8dM+bMzXG/PYUWKkjLIkRLWNh39OaADkiabDRdw8ATFCgbMz5xdIcvwspPAluSL7uY+ZiTWdWmQ==",
+ "dev": true,
+ "requires": {
+ "remark": "^13.0.0",
+ "unist-util-find-all-after": "^3.0.2"
+ }
+ },
+ "@swc/helpers": {
+ "version": "0.4.11",
+ "resolved": "https://registry.npmjs.org/@swc/helpers/-/helpers-0.4.11.tgz",
+ "integrity": "sha512-rEUrBSGIoSFuYxwBYtlUFMlE2CwGhmW+w9355/5oduSw8e5h2+Tj4UrAGNNgP9915++wj5vkQo0UuOBqOAq4nw==",
+ "dev": true,
+ "requires": {
+ "tslib": "^2.4.0"
+ },
+ "dependencies": {
+ "tslib": {
+ "version": "2.4.0",
+ "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.4.0.tgz",
+ "integrity": "sha512-d6xOpEDfsi2CZVlPQzGeux8XMwLT9hssAsaPYExaQMuYskwb+x1x7J371tWlbBdWHroy99KnVB6qIkUbs5X3UQ==",
+ "dev": true
+ }
+ }
+ },
+ "@tootallnate/once": {
+ "version": "1.1.2",
+ "resolved": "https://registry.npmjs.org/@tootallnate/once/-/once-1.1.2.tgz",
+ "integrity": "sha512-RbzJvlNzmRq5c3O09UipeuXno4tA1FE6ikOjxZK0tuxVv3412l64l5t1W5pj4+rJq9vpkm/kwiR07aZXnsKPxw==",
+ "dev": true,
+ "peer": true
+ },
+ "@types/babel__core": {
+ "version": "7.1.19",
+ "resolved": "https://registry.npmjs.org/@types/babel__core/-/babel__core-7.1.19.tgz",
+ "integrity": "sha512-WEOTgRsbYkvA/KCsDwVEGkd7WAr1e3g31VHQ8zy5gul/V1qKullU/BU5I68X5v7V3GnB9eotmom4v5a5gjxorw==",
+ "dev": true,
+ "peer": true,
+ "requires": {
+ "@babel/parser": "^7.1.0",
+ "@babel/types": "^7.0.0",
+ "@types/babel__generator": "*",
+ "@types/babel__template": "*",
+ "@types/babel__traverse": "*"
+ }
+ },
+ "@types/babel__generator": {
+ "version": "7.6.4",
+ "resolved": "https://registry.npmjs.org/@types/babel__generator/-/babel__generator-7.6.4.tgz",
+ "integrity": "sha512-tFkciB9j2K755yrTALxD44McOrk+gfpIpvC3sxHjRawj6PfnQxrse4Clq5y/Rq+G3mrBurMax/lG8Qn2t9mSsg==",
+ "dev": true,
+ "peer": true,
+ "requires": {
+ "@babel/types": "^7.0.0"
+ }
+ },
+ "@types/babel__template": {
+ "version": "7.4.1",
+ "resolved": "https://registry.npmjs.org/@types/babel__template/-/babel__template-7.4.1.tgz",
+ "integrity": "sha512-azBFKemX6kMg5Io+/rdGT0dkGreboUVR0Cdm3fz9QJWpaQGJRQXl7C+6hOTCZcMll7KFyEQpgbYI2lHdsS4U7g==",
+ "dev": true,
+ "peer": true,
+ "requires": {
+ "@babel/parser": "^7.1.0",
+ "@babel/types": "^7.0.0"
+ }
+ },
+ "@types/babel__traverse": {
+ "version": "7.17.0",
+ "resolved": "https://registry.npmjs.org/@types/babel__traverse/-/babel__traverse-7.17.0.tgz",
+ "integrity": "sha512-r8aveDbd+rzGP+ykSdF3oPuTVRWRfbBiHl0rVDM2yNEmSMXfkObQLV46b4RnCv3Lra51OlfnZhkkFaDl2MIRaA==",
+ "dev": true,
+ "peer": true,
+ "requires": {
+ "@babel/types": "^7.3.0"
+ }
+ },
+ "@types/graceful-fs": {
+ "version": "4.1.5",
+ "resolved": "https://registry.npmjs.org/@types/graceful-fs/-/graceful-fs-4.1.5.tgz",
+ "integrity": "sha512-anKkLmZZ+xm4p8JWBf4hElkM4XR+EZeA2M9BAkkTldmcyDY4mbdIJnRghDJH3Ov5ooY7/UAoENtmdMSkaAd7Cw==",
+ "dev": true,
+ "peer": true,
+ "requires": {
+ "@types/node": "*"
+ }
+ },
+ "@types/istanbul-lib-coverage": {
+ "version": "2.0.4",
+ "resolved": "https://registry.npmjs.org/@types/istanbul-lib-coverage/-/istanbul-lib-coverage-2.0.4.tgz",
+ "integrity": "sha512-z/QT1XN4K4KYuslS23k62yDIDLwLFkzxOuMplDtObz0+y7VqJCaO2o+SPwHCvLFZh7xazvvoor2tA/hPz9ee7g==",
+ "dev": true
+ },
+ "@types/istanbul-lib-report": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/@types/istanbul-lib-report/-/istanbul-lib-report-3.0.0.tgz",
+ "integrity": "sha512-plGgXAPfVKFoYfa9NpYDAkseG+g6Jr294RqeqcqDixSbU34MZVJRi/P+7Y8GDpzkEwLaGZZOpKIEmeVZNtKsrg==",
+ "dev": true,
+ "requires": {
+ "@types/istanbul-lib-coverage": "*"
+ }
+ },
+ "@types/istanbul-reports": {
+ "version": "3.0.1",
+ "resolved": "https://registry.npmjs.org/@types/istanbul-reports/-/istanbul-reports-3.0.1.tgz",
+ "integrity": "sha512-c3mAZEuK0lvBp8tmuL74XRKn1+y2dcwOUpH7x4WrF6gk1GIgiluDRgMYQtw2OFcBvAJWlt6ASU3tSqxp0Uu0Aw==",
+ "dev": true,
+ "requires": {
+ "@types/istanbul-lib-report": "*"
+ }
+ },
+ "@types/json-schema": {
+ "version": "7.0.11",
+ "resolved": "https://registry.npmjs.org/@types/json-schema/-/json-schema-7.0.11.tgz",
+ "integrity": "sha512-wOuvG1SN4Us4rez+tylwwwCV1psiNVOkJeM3AUWUNWg/jDQY2+HE/444y5gc+jBmRqASOm2Oeh5c1axHobwRKQ==",
+ "dev": true
+ },
+ "@types/json5": {
+ "version": "0.0.29",
+ "resolved": "https://registry.npmjs.org/@types/json5/-/json5-0.0.29.tgz",
+ "integrity": "sha512-dRLjCWHYg4oaA77cxO64oO+7JwCwnIzkZPdrrC71jQmQtlhM556pwKo5bUzqvZndkVbeFLIIi+9TC40JNF5hNQ==",
+ "dev": true
+ },
+ "@types/mdast": {
+ "version": "3.0.10",
+ "resolved": "https://registry.npmjs.org/@types/mdast/-/mdast-3.0.10.tgz",
+ "integrity": "sha512-W864tg/Osz1+9f4lrGTZpCSO5/z4608eUp19tbozkq2HJK6i3z1kT0H9tlADXuYIb1YYOBByU4Jsqkk75q48qA==",
+ "dev": true,
+ "requires": {
+ "@types/unist": "*"
+ }
+ },
+ "@types/minimist": {
+ "version": "1.2.2",
+ "resolved": "https://registry.npmjs.org/@types/minimist/-/minimist-1.2.2.tgz",
+ "integrity": "sha512-jhuKLIRrhvCPLqwPcx6INqmKeiA5EWrsCOPhrlFSrbrmU4ZMPjj5Ul/oLCMDO98XRUIwVm78xICz4EPCektzeQ==",
+ "dev": true
+ },
+ "@types/node": {
+ "version": "17.0.25",
+ "resolved": "https://registry.npmjs.org/@types/node/-/node-17.0.25.tgz",
+ "integrity": "sha512-wANk6fBrUwdpY4isjWrKTufkrXdu1D2YHCot2fD/DfWxF5sMrVSA+KN7ydckvaTCh0HiqX9IVl0L5/ZoXg5M7w==",
+ "dev": true
+ },
+ "@types/normalize-package-data": {
+ "version": "2.4.1",
+ "resolved": "https://registry.npmjs.org/@types/normalize-package-data/-/normalize-package-data-2.4.1.tgz",
+ "integrity": "sha512-Gj7cI7z+98M282Tqmp2K5EIsoouUEzbBJhQQzDE3jSIRk6r9gsz0oUokqIUR4u1R3dMHo0pDHM7sNOHyhulypw==",
+ "dev": true
+ },
+ "@types/parse-json": {
+ "version": "4.0.0",
+ "resolved": "https://registry.npmjs.org/@types/parse-json/-/parse-json-4.0.0.tgz",
+ "integrity": "sha512-//oorEZjL6sbPcKUaCdIGlIUeH26mgzimjBB77G6XRgnDl/L5wOnpyBGRe/Mmf5CVW3PwEBE1NjiMZ/ssFh4wA==",
+ "dev": true
+ },
+ "@types/prettier": {
+ "version": "2.6.0",
+ "resolved": "https://registry.npmjs.org/@types/prettier/-/prettier-2.6.0.tgz",
+ "integrity": "sha512-G/AdOadiZhnJp0jXCaBQU449W2h716OW/EoXeYkCytxKL06X1WCXB4DZpp8TpZ8eyIJVS1cw4lrlkkSYU21cDw==",
+ "dev": true,
+ "peer": true
+ },
+ "@types/semver": {
+ "version": "7.3.13",
+ "resolved": "https://registry.npmjs.org/@types/semver/-/semver-7.3.13.tgz",
+ "integrity": "sha512-21cFJr9z3g5dW8B0CVI9g2O9beqaThGQ6ZFBqHfwhzLDKUxaqTIy3vnfah/UPkfOiF2pLq+tGz+W8RyCskuslw==",
+ "dev": true
+ },
+ "@types/stack-utils": {
+ "version": "2.0.1",
+ "resolved": "https://registry.npmjs.org/@types/stack-utils/-/stack-utils-2.0.1.tgz",
+ "integrity": "sha512-Hl219/BT5fLAaz6NDkSuhzasy49dwQS/DSdu4MdggFB8zcXv7vflBI3xp7FEmkmdDkBUI2bPUNeMttp2knYdxw==",
+ "dev": true,
+ "peer": true
+ },
+ "@types/supports-color": {
+ "version": "8.1.1",
+ "resolved": "https://registry.npmjs.org/@types/supports-color/-/supports-color-8.1.1.tgz",
+ "integrity": "sha512-dPWnWsf+kzIG140B8z2w3fr5D03TLWbOAFQl45xUpI3vcizeXriNR5VYkWZ+WTMsUHqZ9Xlt3hrxGNANFyNQfw==",
+ "dev": true
+ },
+ "@types/unist": {
+ "version": "2.0.6",
+ "resolved": "https://registry.npmjs.org/@types/unist/-/unist-2.0.6.tgz",
+ "integrity": "sha512-PBjIUxZHOuj0R15/xuwJYjFi+KZdNFrehocChv4g5hu6aFroHue8m0lBP0POdK2nKzbw0cgV1mws8+V/JAcEkQ==",
+ "dev": true
+ },
+ "@types/yargs": {
+ "version": "15.0.14",
+ "resolved": "https://registry.npmjs.org/@types/yargs/-/yargs-15.0.14.tgz",
+ "integrity": "sha512-yEJzHoxf6SyQGhBhIYGXQDSCkJjB6HohDShto7m8vaKg9Yp0Yn8+71J9eakh2bnPg6BfsH9PRMhiRTZnd4eXGQ==",
+ "dev": true,
+ "requires": {
+ "@types/yargs-parser": "*"
+ }
+ },
+ "@types/yargs-parser": {
+ "version": "21.0.0",
+ "resolved": "https://registry.npmjs.org/@types/yargs-parser/-/yargs-parser-21.0.0.tgz",
+ "integrity": "sha512-iO9ZQHkZxHn4mSakYV0vFHAVDyEOIJQrV2uZ06HxEPcx+mt8swXoZHIbaaJ2crJYFfErySgktuTZ3BeLz+XmFA==",
+ "dev": true
+ },
+ "@typescript-eslint/eslint-plugin": {
+ "version": "5.55.0",
+ "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-5.55.0.tgz",
+ "integrity": "sha512-IZGc50rtbjk+xp5YQoJvmMPmJEYoC53SiKPXyqWfv15XoD2Y5Kju6zN0DwlmaGJp1Iw33JsWJcQ7nw0lGCGjVg==",
+ "dev": true,
+ "requires": {
+ "@eslint-community/regexpp": "^4.4.0",
+ "@typescript-eslint/scope-manager": "5.55.0",
+ "@typescript-eslint/type-utils": "5.55.0",
+ "@typescript-eslint/utils": "5.55.0",
+ "debug": "^4.3.4",
+ "grapheme-splitter": "^1.0.4",
+ "ignore": "^5.2.0",
+ "natural-compare-lite": "^1.4.0",
+ "semver": "^7.3.7",
+ "tsutils": "^3.21.0"
+ }
+ },
+ "@typescript-eslint/parser": {
+ "version": "5.55.0",
+ "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-5.55.0.tgz",
+ "integrity": "sha512-ppvmeF7hvdhUUZWSd2EEWfzcFkjJzgNQzVST22nzg958CR+sphy8A6K7LXQZd6V75m1VKjp+J4g/PCEfSCmzhw==",
+ "dev": true,
+ "requires": {
+ "@typescript-eslint/scope-manager": "5.55.0",
+ "@typescript-eslint/types": "5.55.0",
+ "@typescript-eslint/typescript-estree": "5.55.0",
+ "debug": "^4.3.4"
+ }
+ },
+ "@typescript-eslint/scope-manager": {
+ "version": "5.55.0",
+ "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-5.55.0.tgz",
+ "integrity": "sha512-OK+cIO1ZGhJYNCL//a3ROpsd83psf4dUJ4j7pdNVzd5DmIk+ffkuUIX2vcZQbEW/IR41DYsfJTB19tpCboxQuw==",
+ "dev": true,
+ "requires": {
+ "@typescript-eslint/types": "5.55.0",
+ "@typescript-eslint/visitor-keys": "5.55.0"
+ }
+ },
+ "@typescript-eslint/type-utils": {
+ "version": "5.55.0",
+ "resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-5.55.0.tgz",
+ "integrity": "sha512-ObqxBgHIXj8rBNm0yh8oORFrICcJuZPZTqtAFh0oZQyr5DnAHZWfyw54RwpEEH+fD8suZaI0YxvWu5tYE/WswA==",
+ "dev": true,
+ "requires": {
+ "@typescript-eslint/typescript-estree": "5.55.0",
+ "@typescript-eslint/utils": "5.55.0",
+ "debug": "^4.3.4",
+ "tsutils": "^3.21.0"
+ }
+ },
+ "@typescript-eslint/types": {
+ "version": "5.55.0",
+ "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-5.55.0.tgz",
+ "integrity": "sha512-M4iRh4AG1ChrOL6Y+mETEKGeDnT7Sparn6fhZ5LtVJF1909D5O4uqK+C5NPbLmpfZ0XIIxCdwzKiijpZUOvOug==",
+ "dev": true
+ },
+ "@typescript-eslint/typescript-estree": {
+ "version": "5.55.0",
+ "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-5.55.0.tgz",
+ "integrity": "sha512-I7X4A9ovA8gdpWMpr7b1BN9eEbvlEtWhQvpxp/yogt48fy9Lj3iE3ild/1H3jKBBIYj5YYJmS2+9ystVhC7eaQ==",
+ "dev": true,
+ "requires": {
+ "@typescript-eslint/types": "5.55.0",
+ "@typescript-eslint/visitor-keys": "5.55.0",
+ "debug": "^4.3.4",
+ "globby": "^11.1.0",
+ "is-glob": "^4.0.3",
+ "semver": "^7.3.7",
+ "tsutils": "^3.21.0"
+ },
+ "dependencies": {
+ "globby": {
+ "version": "11.1.0",
+ "resolved": "https://registry.npmjs.org/globby/-/globby-11.1.0.tgz",
+ "integrity": "sha512-jhIXaOzy1sb8IyocaruWSn1TjmnBVs8Ayhcy83rmxNJ8q2uWKCAj3CnJY+KpGSXCueAPc0i05kVvVKtP1t9S3g==",
+ "dev": true,
+ "requires": {
+ "array-union": "^2.1.0",
+ "dir-glob": "^3.0.1",
+ "fast-glob": "^3.2.9",
+ "ignore": "^5.2.0",
+ "merge2": "^1.4.1",
+ "slash": "^3.0.0"
+ }
+ }
+ }
+ },
+ "@typescript-eslint/utils": {
+ "version": "5.55.0",
+ "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-5.55.0.tgz",
+ "integrity": "sha512-FkW+i2pQKcpDC3AY6DU54yl8Lfl14FVGYDgBTyGKB75cCwV3KpkpTMFi9d9j2WAJ4271LR2HeC5SEWF/CZmmfw==",
+ "dev": true,
+ "requires": {
+ "@eslint-community/eslint-utils": "^4.2.0",
+ "@types/json-schema": "^7.0.9",
+ "@types/semver": "^7.3.12",
+ "@typescript-eslint/scope-manager": "5.55.0",
+ "@typescript-eslint/types": "5.55.0",
+ "@typescript-eslint/typescript-estree": "5.55.0",
+ "eslint-scope": "^5.1.1",
+ "semver": "^7.3.7"
+ }
+ },
+ "@typescript-eslint/visitor-keys": {
+ "version": "5.55.0",
+ "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-5.55.0.tgz",
+ "integrity": "sha512-q2dlHHwWgirKh1D3acnuApXG+VNXpEY5/AwRxDVuEQpxWaB0jCDe0jFMVMALJ3ebSfuOVE8/rMS+9ZOYGg1GWw==",
+ "dev": true,
+ "requires": {
+ "@typescript-eslint/types": "5.55.0",
+ "eslint-visitor-keys": "^3.3.0"
+ }
+ },
+ "abab": {
+ "version": "2.0.6",
+ "resolved": "https://registry.npmjs.org/abab/-/abab-2.0.6.tgz",
+ "integrity": "sha512-j2afSsaIENvHZN2B8GOpF566vZ5WVk5opAiMTvWgaQT8DkbOqsTfvNAvHoRGU2zzP8cPoqys+xHTRDWW8L+/BA==",
+ "dev": true,
+ "peer": true
+ },
+ "acorn": {
+ "version": "8.8.2",
+ "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.8.2.tgz",
+ "integrity": "sha512-xjIYgE8HBrkpd/sJqOGNspf8uHG+NOHGOw6a/Urj8taM2EXfdNAH2oFcPeIFfsv3+kz/mJrS5VuMqbNLjCa2vw==",
+ "dev": true
+ },
+ "acorn-globals": {
+ "version": "6.0.0",
+ "resolved": "https://registry.npmjs.org/acorn-globals/-/acorn-globals-6.0.0.tgz",
+ "integrity": "sha512-ZQl7LOWaF5ePqqcX4hLuv/bLXYQNfNWw2c0/yX/TsPRKamzHcTGQnlCjHT3TsmkOUVEPS3crCxiPfdzE/Trlhg==",
+ "dev": true,
+ "peer": true,
+ "requires": {
+ "acorn": "^7.1.1",
+ "acorn-walk": "^7.1.1"
+ },
+ "dependencies": {
+ "acorn": {
+ "version": "7.4.1",
+ "resolved": "https://registry.npmjs.org/acorn/-/acorn-7.4.1.tgz",
+ "integrity": "sha512-nQyp0o1/mNdbTO1PO6kHkwSrmgZ0MT/jCCpNiwbUjGoRN4dlBhqJtoQuCnEOKzgTVwg0ZWiCoQy6SxMebQVh8A==",
+ "dev": true,
+ "peer": true
+ }
+ }
+ },
+ "acorn-jsx": {
+ "version": "5.3.2",
+ "resolved": "https://registry.npmjs.org/acorn-jsx/-/acorn-jsx-5.3.2.tgz",
+ "integrity": "sha512-rq9s+JNhf0IChjtDXxllJ7g41oZk5SlXtp0LHwyA5cejwn7vKmKp4pPri6YEePv2PU65sAsegbXtIinmDFDXgQ==",
+ "dev": true,
+ "requires": {}
+ },
+ "acorn-walk": {
+ "version": "7.2.0",
+ "resolved": "https://registry.npmjs.org/acorn-walk/-/acorn-walk-7.2.0.tgz",
+ "integrity": "sha512-OPdCF6GsMIP+Az+aWfAAOEt2/+iVDKE7oy6lJ098aoe59oAmK76qV6Gw60SbZ8jHuG2wH058GF4pLFbYamYrVA==",
+ "dev": true,
+ "peer": true
+ },
+ "agent-base": {
+ "version": "6.0.2",
+ "resolved": "https://registry.npmjs.org/agent-base/-/agent-base-6.0.2.tgz",
+ "integrity": "sha512-RZNwNclF7+MS/8bDg70amg32dyeZGZxiDuQmZxKLAlQjr3jGyLx+4Kkk58UO7D2QdgFIQCovuSuZESne6RG6XQ==",
+ "dev": true,
+ "peer": true,
+ "requires": {
+ "debug": "4"
+ }
+ },
+ "aggregate-error": {
+ "version": "3.1.0",
+ "resolved": "https://registry.npmjs.org/aggregate-error/-/aggregate-error-3.1.0.tgz",
+ "integrity": "sha512-4I7Td01quW/RpocfNayFdFVk1qSuoh0E7JrbRJ16nH01HhKFQ88INq9Sd+nd72zqRySlr9BmDA8xlEJ6vJMrYA==",
+ "dev": true,
+ "requires": {
+ "clean-stack": "^2.0.0",
+ "indent-string": "^4.0.0"
+ }
+ },
+ "ajv": {
+ "version": "6.12.6",
+ "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz",
+ "integrity": "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==",
+ "dev": true,
+ "requires": {
+ "fast-deep-equal": "^3.1.1",
+ "fast-json-stable-stringify": "^2.0.0",
+ "json-schema-traverse": "^0.4.1",
+ "uri-js": "^4.2.2"
+ }
+ },
+ "ansi-colors": {
+ "version": "4.1.1",
+ "resolved": "https://registry.npmjs.org/ansi-colors/-/ansi-colors-4.1.1.tgz",
+ "integrity": "sha512-JoX0apGbHaUJBNl6yF+p6JAFYZ666/hhCGKN5t9QFjbJQKUU/g8MNbFDbvfrgKXvI1QpZplPOnwIo99lX/AAmA==",
+ "dev": true
+ },
+ "ansi-escapes": {
+ "version": "4.3.2",
+ "resolved": "https://registry.npmjs.org/ansi-escapes/-/ansi-escapes-4.3.2.tgz",
+ "integrity": "sha512-gKXj5ALrKWQLsYG9jlTRmR/xKluxHV+Z9QEwNIgCfM1/uwPMCuzVVnh5mwTd+OuBZcwSIMbqssNWRm1lE51QaQ==",
+ "dev": true,
+ "requires": {
+ "type-fest": "^0.21.3"
+ },
+ "dependencies": {
+ "type-fest": {
+ "version": "0.21.3",
+ "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.21.3.tgz",
+ "integrity": "sha512-t0rzBq87m3fVcduHDUFhKmyyX+9eo6WQjZvf51Ea/M0Q7+T374Jp1aUiyUl0GKxp8M/OETVHSDvmkyPgvX+X2w==",
+ "dev": true
+ }
+ }
+ },
+ "ansi-regex": {
+ "version": "5.0.1",
+ "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz",
+ "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==",
+ "dev": true
+ },
+ "ansi-styles": {
+ "version": "4.3.0",
+ "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz",
+ "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==",
+ "dev": true,
+ "requires": {
+ "color-convert": "^2.0.1"
+ }
+ },
+ "anymatch": {
+ "version": "3.1.2",
+ "resolved": "https://registry.npmjs.org/anymatch/-/anymatch-3.1.2.tgz",
+ "integrity": "sha512-P43ePfOAIupkguHUycrc4qJ9kz8ZiuOUijaETwX7THt0Y/GNK7v0aa8rY816xWjZ7rJdA5XdMcpVFTKMq+RvWg==",
+ "dev": true,
+ "peer": true,
+ "requires": {
+ "normalize-path": "^3.0.0",
+ "picomatch": "^2.0.4"
+ }
+ },
+ "argparse": {
+ "version": "2.0.1",
+ "resolved": "https://registry.npmjs.org/argparse/-/argparse-2.0.1.tgz",
+ "integrity": "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==",
+ "dev": true
+ },
+ "aria-query": {
+ "version": "5.1.3",
+ "resolved": "https://registry.npmjs.org/aria-query/-/aria-query-5.1.3.tgz",
+ "integrity": "sha512-R5iJ5lkuHybztUfuOAznmboyjWq8O6sqNqtK7CLOqdydi54VNbORp49mb14KbWgG1QD3JFO9hJdZ+y4KutfdOQ==",
+ "dev": true,
+ "requires": {
+ "deep-equal": "^2.0.5"
+ }
+ },
+ "arr-diff": {
+ "version": "4.0.0",
+ "resolved": "https://registry.npmjs.org/arr-diff/-/arr-diff-4.0.0.tgz",
+ "integrity": "sha1-1kYQdP6/7HHn4VI1dhoyml3HxSA=",
+ "dev": true,
+ "peer": true
+ },
+ "arr-flatten": {
+ "version": "1.1.0",
+ "resolved": "https://registry.npmjs.org/arr-flatten/-/arr-flatten-1.1.0.tgz",
+ "integrity": "sha512-L3hKV5R/p5o81R7O02IGnwpDmkp6E982XhtbuwSe3O4qOtMMMtodicASA1Cny2U+aCXcNpml+m4dPsvsJ3jatg==",
+ "dev": true,
+ "peer": true
+ },
+ "arr-union": {
+ "version": "3.1.0",
+ "resolved": "https://registry.npmjs.org/arr-union/-/arr-union-3.1.0.tgz",
+ "integrity": "sha1-45sJrqne+Gao8gbiiK9jkZuuOcQ=",
+ "dev": true,
+ "peer": true
+ },
+ "array-buffer-byte-length": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/array-buffer-byte-length/-/array-buffer-byte-length-1.0.0.tgz",
+ "integrity": "sha512-LPuwb2P+NrQw3XhxGc36+XSvuBPopovXYTR9Ew++Du9Yb/bx5AzBfrIsBoj0EZUifjQU+sHL21sseZ3jerWO/A==",
+ "dev": true,
+ "requires": {
+ "call-bind": "^1.0.2",
+ "is-array-buffer": "^3.0.1"
+ }
+ },
+ "array-includes": {
+ "version": "3.1.6",
+ "resolved": "https://registry.npmjs.org/array-includes/-/array-includes-3.1.6.tgz",
+ "integrity": "sha512-sgTbLvL6cNnw24FnbaDyjmvddQ2ML8arZsgaJhoABMoplz/4QRhtrYS+alr1BUM1Bwp6dhx8vVCBSLG+StwOFw==",
+ "dev": true,
+ "requires": {
+ "call-bind": "^1.0.2",
+ "define-properties": "^1.1.4",
+ "es-abstract": "^1.20.4",
+ "get-intrinsic": "^1.1.3",
+ "is-string": "^1.0.7"
+ }
+ },
+ "array-union": {
+ "version": "2.1.0",
+ "resolved": "https://registry.npmjs.org/array-union/-/array-union-2.1.0.tgz",
+ "integrity": "sha512-HGyxoOTYUyCM6stUe6EJgnd4EoewAI7zMdfqO+kGjnlZmBDz/cR5pf8r/cR4Wq60sL/p0IkcjUEEPwS3GFrIyw==",
+ "dev": true
+ },
+ "array-unique": {
+ "version": "0.3.2",
+ "resolved": "https://registry.npmjs.org/array-unique/-/array-unique-0.3.2.tgz",
+ "integrity": "sha1-qJS3XUvE9s1nnvMkSp/Y9Gri1Cg=",
+ "dev": true,
+ "peer": true
+ },
+ "array.prototype.flat": {
+ "version": "1.3.1",
+ "resolved": "https://registry.npmjs.org/array.prototype.flat/-/array.prototype.flat-1.3.1.tgz",
+ "integrity": "sha512-roTU0KWIOmJ4DRLmwKd19Otg0/mT3qPNt0Qb3GWW8iObuZXxrjB/pzn0R3hqpRSWg4HCwqx+0vwOnWnvlOyeIA==",
+ "dev": true,
+ "requires": {
+ "call-bind": "^1.0.2",
+ "define-properties": "^1.1.4",
+ "es-abstract": "^1.20.4",
+ "es-shim-unscopables": "^1.0.0"
+ }
+ },
+ "array.prototype.flatmap": {
+ "version": "1.3.1",
+ "resolved": "https://registry.npmjs.org/array.prototype.flatmap/-/array.prototype.flatmap-1.3.1.tgz",
+ "integrity": "sha512-8UGn9O1FDVvMNB0UlLv4voxRMze7+FpHyF5mSMRjWHUMlpoDViniy05870VlxhfgTnLbpuwTzvD76MTtWxB/mQ==",
+ "dev": true,
+ "requires": {
+ "call-bind": "^1.0.2",
+ "define-properties": "^1.1.4",
+ "es-abstract": "^1.20.4",
+ "es-shim-unscopables": "^1.0.0"
+ }
+ },
+ "array.prototype.tosorted": {
+ "version": "1.1.1",
+ "resolved": "https://registry.npmjs.org/array.prototype.tosorted/-/array.prototype.tosorted-1.1.1.tgz",
+ "integrity": "sha512-pZYPXPRl2PqWcsUs6LOMn+1f1532nEoPTYowBtqLwAW+W8vSVhkIGnmOX1t/UQjD6YGI0vcD2B1U7ZFGQH9jnQ==",
+ "dev": true,
+ "requires": {
+ "call-bind": "^1.0.2",
+ "define-properties": "^1.1.4",
+ "es-abstract": "^1.20.4",
+ "es-shim-unscopables": "^1.0.0",
+ "get-intrinsic": "^1.1.3"
+ }
+ },
+ "arrify": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/arrify/-/arrify-1.0.1.tgz",
+ "integrity": "sha1-iYUI2iIm84DfkEcoRWhJwVAaSw0=",
+ "dev": true
+ },
+ "assign-symbols": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/assign-symbols/-/assign-symbols-1.0.0.tgz",
+ "integrity": "sha1-WWZ/QfrdTyDMvCu5a41Pf3jsA2c=",
+ "dev": true,
+ "peer": true
+ },
+ "ast-types-flow": {
+ "version": "0.0.7",
+ "resolved": "https://registry.npmjs.org/ast-types-flow/-/ast-types-flow-0.0.7.tgz",
+ "integrity": "sha512-eBvWn1lvIApYMhzQMsu9ciLfkBY499mFZlNqG+/9WR7PVlroQw0vG30cOQQbaKz3sCEc44TAOu2ykzqXSNnwag==",
+ "dev": true
+ },
+ "astral-regex": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/astral-regex/-/astral-regex-2.0.0.tgz",
+ "integrity": "sha512-Z7tMw1ytTXt5jqMcOP+OQteU1VuNK9Y02uuJtKQ1Sv69jXQKKg5cibLwGJow8yzZP+eAc18EmLGPal0bp36rvQ==",
+ "dev": true
+ },
+ "async": {
+ "version": "3.2.3",
+ "resolved": "https://registry.npmjs.org/async/-/async-3.2.3.tgz",
+ "integrity": "sha512-spZRyzKL5l5BZQrr/6m/SqFdBN0q3OCI0f9rjfBzCMBIP4p75P620rR3gTmaksNOhmzgdxcaxdNfMy6anrbM0g==",
+ "dev": true
+ },
+ "asynckit": {
+ "version": "0.4.0",
+ "resolved": "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz",
+ "integrity": "sha1-x57Zf380y48robyXkLzDZkdLS3k=",
+ "dev": true
+ },
+ "at-least-node": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/at-least-node/-/at-least-node-1.0.0.tgz",
+ "integrity": "sha512-+q/t7Ekv1EDY2l6Gda6LLiX14rU9TV20Wa3ofeQmwPFZbOMo9DXrLbOjFaaclkXKWidIaopwAObQDqwWtGUjqg==",
+ "dev": true
+ },
+ "atob": {
+ "version": "2.1.2",
+ "resolved": "https://registry.npmjs.org/atob/-/atob-2.1.2.tgz",
+ "integrity": "sha512-Wm6ukoaOGJi/73p/cl2GvLjTI5JM1k/O14isD73YML8StrH/7/lRFgmg8nICZgD3bZZvjwCGxtMOD3wWNAu8cg==",
+ "dev": true,
+ "peer": true
+ },
+ "autoprefixer": {
+ "version": "9.8.8",
+ "resolved": "https://registry.npmjs.org/autoprefixer/-/autoprefixer-9.8.8.tgz",
+ "integrity": "sha512-eM9d/swFopRt5gdJ7jrpCwgvEMIayITpojhkkSMRsFHYuH5bkSQ4p/9qTEHtmNudUZh22Tehu7I6CxAW0IXTKA==",
+ "dev": true,
+ "requires": {
+ "browserslist": "^4.12.0",
+ "caniuse-lite": "^1.0.30001109",
+ "normalize-range": "^0.1.2",
+ "num2fraction": "^1.2.2",
+ "picocolors": "^0.2.1",
+ "postcss": "^7.0.32",
+ "postcss-value-parser": "^4.1.0"
+ },
+ "dependencies": {
+ "picocolors": {
+ "version": "0.2.1",
+ "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-0.2.1.tgz",
+ "integrity": "sha512-cMlDqaLEqfSaW8Z7N5Jw+lyIW869EzT73/F5lhtY9cLGoVxSXznfgfXMO0Z5K0o0Q2TkTXq+0KFsdnSe3jDViA==",
+ "dev": true
+ },
+ "postcss": {
+ "version": "7.0.39",
+ "resolved": "https://registry.npmjs.org/postcss/-/postcss-7.0.39.tgz",
+ "integrity": "sha512-yioayjNbHn6z1/Bywyb2Y4s3yvDAeXGOyxqD+LnVOinq6Mdmd++SW2wUNVzavyyHxd6+DxzWGIuosg6P1Rj8uA==",
+ "dev": true,
+ "requires": {
+ "picocolors": "^0.2.1",
+ "source-map": "^0.6.1"
+ }
+ }
+ }
+ },
+ "available-typed-arrays": {
+ "version": "1.0.5",
+ "resolved": "https://registry.npmjs.org/available-typed-arrays/-/available-typed-arrays-1.0.5.tgz",
+ "integrity": "sha512-DMD0KiN46eipeziST1LPP/STfDU0sufISXmjSgvVsoU2tqxctQeASejWcfNtxYKqETM1UxQ8sp2OrSBWpHY6sw==",
+ "dev": true
+ },
+ "axe-core": {
+ "version": "4.6.3",
+ "resolved": "https://registry.npmjs.org/axe-core/-/axe-core-4.6.3.tgz",
+ "integrity": "sha512-/BQzOX780JhsxDnPpH4ZiyrJAzcd8AfzFPkv+89veFSr1rcMjuq2JDCwypKaPeB6ljHp9KjXhPpjgCvQlWYuqg==",
+ "dev": true
+ },
+ "axobject-query": {
+ "version": "3.1.1",
+ "resolved": "https://registry.npmjs.org/axobject-query/-/axobject-query-3.1.1.tgz",
+ "integrity": "sha512-goKlv8DZrK9hUh975fnHzhNIO4jUnFCfv/dszV5VwUGDFjI6vQ2VwoyjYjYNEbBE8AH87TduWP5uyDR1D+Iteg==",
+ "dev": true,
+ "requires": {
+ "deep-equal": "^2.0.5"
+ }
+ },
+ "babel-jest": {
+ "version": "26.6.3",
+ "resolved": "https://registry.npmjs.org/babel-jest/-/babel-jest-26.6.3.tgz",
+ "integrity": "sha512-pl4Q+GAVOHwvjrck6jKjvmGhnO3jHX/xuB9d27f+EJZ/6k+6nMuPjorrYp7s++bKKdANwzElBWnLWaObvTnaZA==",
+ "dev": true,
+ "peer": true,
+ "requires": {
+ "@jest/transform": "^26.6.2",
+ "@jest/types": "^26.6.2",
+ "@types/babel__core": "^7.1.7",
+ "babel-plugin-istanbul": "^6.0.0",
+ "babel-preset-jest": "^26.6.2",
+ "chalk": "^4.0.0",
+ "graceful-fs": "^4.2.4",
+ "slash": "^3.0.0"
+ }
+ },
+ "babel-plugin-istanbul": {
+ "version": "6.1.1",
+ "resolved": "https://registry.npmjs.org/babel-plugin-istanbul/-/babel-plugin-istanbul-6.1.1.tgz",
+ "integrity": "sha512-Y1IQok9821cC9onCx5otgFfRm7Lm+I+wwxOx738M/WLPZ9Q42m4IG5W0FNX8WLL2gYMZo3JkuXIH2DOpWM+qwA==",
+ "dev": true,
+ "peer": true,
+ "requires": {
+ "@babel/helper-plugin-utils": "^7.0.0",
+ "@istanbuljs/load-nyc-config": "^1.0.0",
+ "@istanbuljs/schema": "^0.1.2",
+ "istanbul-lib-instrument": "^5.0.4",
+ "test-exclude": "^6.0.0"
+ },
+ "dependencies": {
+ "istanbul-lib-instrument": {
+ "version": "5.2.0",
+ "resolved": "https://registry.npmjs.org/istanbul-lib-instrument/-/istanbul-lib-instrument-5.2.0.tgz",
+ "integrity": "sha512-6Lthe1hqXHBNsqvgDzGO6l03XNeu3CrG4RqQ1KM9+l5+jNGpEJfIELx1NS3SEHmJQA8np/u+E4EPRKRiu6m19A==",
+ "dev": true,
+ "peer": true,
+ "requires": {
+ "@babel/core": "^7.12.3",
+ "@babel/parser": "^7.14.7",
+ "@istanbuljs/schema": "^0.1.2",
+ "istanbul-lib-coverage": "^3.2.0",
+ "semver": "^6.3.0"
+ }
+ },
+ "semver": {
+ "version": "6.3.0",
+ "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz",
+ "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==",
+ "dev": true,
+ "peer": true
+ }
+ }
+ },
+ "babel-plugin-jest-hoist": {
+ "version": "26.6.2",
+ "resolved": "https://registry.npmjs.org/babel-plugin-jest-hoist/-/babel-plugin-jest-hoist-26.6.2.tgz",
+ "integrity": "sha512-PO9t0697lNTmcEHH69mdtYiOIkkOlj9fySqfO3K1eCcdISevLAE0xY59VLLUj0SoiPiTX/JU2CYFpILydUa5Lw==",
+ "dev": true,
+ "peer": true,
+ "requires": {
+ "@babel/template": "^7.3.3",
+ "@babel/types": "^7.3.3",
+ "@types/babel__core": "^7.0.0",
+ "@types/babel__traverse": "^7.0.6"
+ }
+ },
+ "babel-preset-current-node-syntax": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/babel-preset-current-node-syntax/-/babel-preset-current-node-syntax-1.0.1.tgz",
+ "integrity": "sha512-M7LQ0bxarkxQoN+vz5aJPsLBn77n8QgTFmo8WK0/44auK2xlCXrYcUxHFxgU7qW5Yzw/CjmLRK2uJzaCd7LvqQ==",
+ "dev": true,
+ "peer": true,
+ "requires": {
+ "@babel/plugin-syntax-async-generators": "^7.8.4",
+ "@babel/plugin-syntax-bigint": "^7.8.3",
+ "@babel/plugin-syntax-class-properties": "^7.8.3",
+ "@babel/plugin-syntax-import-meta": "^7.8.3",
+ "@babel/plugin-syntax-json-strings": "^7.8.3",
+ "@babel/plugin-syntax-logical-assignment-operators": "^7.8.3",
+ "@babel/plugin-syntax-nullish-coalescing-operator": "^7.8.3",
+ "@babel/plugin-syntax-numeric-separator": "^7.8.3",
+ "@babel/plugin-syntax-object-rest-spread": "^7.8.3",
+ "@babel/plugin-syntax-optional-catch-binding": "^7.8.3",
+ "@babel/plugin-syntax-optional-chaining": "^7.8.3",
+ "@babel/plugin-syntax-top-level-await": "^7.8.3"
+ }
+ },
+ "babel-preset-jest": {
+ "version": "26.6.2",
+ "resolved": "https://registry.npmjs.org/babel-preset-jest/-/babel-preset-jest-26.6.2.tgz",
+ "integrity": "sha512-YvdtlVm9t3k777c5NPQIv6cxFFFapys25HiUmuSgHwIZhfifweR5c5Sf5nwE3MAbfu327CYSvps8Yx6ANLyleQ==",
+ "dev": true,
+ "peer": true,
+ "requires": {
+ "babel-plugin-jest-hoist": "^26.6.2",
+ "babel-preset-current-node-syntax": "^1.0.0"
+ }
+ },
+ "bail": {
+ "version": "1.0.5",
+ "resolved": "https://registry.npmjs.org/bail/-/bail-1.0.5.tgz",
+ "integrity": "sha512-xFbRxM1tahm08yHBP16MMjVUAvDaBMD38zsM9EMAUN61omwLmKlOpB/Zku5QkjZ8TZ4vn53pj+t518cH0S03RQ==",
+ "dev": true
+ },
+ "balanced-match": {
+ "version": "1.0.2",
+ "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz",
+ "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==",
+ "dev": true
+ },
+ "base": {
+ "version": "0.11.2",
+ "resolved": "https://registry.npmjs.org/base/-/base-0.11.2.tgz",
+ "integrity": "sha512-5T6P4xPgpp0YDFvSWwEZ4NoE3aM4QBQXDzmVbraCkFj8zHM+mba8SyqB5DbZWyR7mYHo6Y7BdQo3MoA4m0TeQg==",
+ "dev": true,
+ "peer": true,
+ "requires": {
+ "cache-base": "^1.0.1",
+ "class-utils": "^0.3.5",
+ "component-emitter": "^1.2.1",
+ "define-property": "^1.0.0",
+ "isobject": "^3.0.1",
+ "mixin-deep": "^1.2.0",
+ "pascalcase": "^0.1.1"
+ },
+ "dependencies": {
+ "define-property": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/define-property/-/define-property-1.0.0.tgz",
+ "integrity": "sha1-dp66rz9KY6rTr56NMEybvnm/sOY=",
+ "dev": true,
+ "peer": true,
+ "requires": {
+ "is-descriptor": "^1.0.0"
+ }
+ }
+ }
+ },
+ "brace-expansion": {
+ "version": "1.1.11",
+ "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz",
+ "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==",
+ "dev": true,
+ "requires": {
+ "balanced-match": "^1.0.0",
+ "concat-map": "0.0.1"
+ }
+ },
+ "braces": {
+ "version": "3.0.2",
+ "resolved": "https://registry.npmjs.org/braces/-/braces-3.0.2.tgz",
+ "integrity": "sha512-b8um+L1RzM3WDSzvhm6gIz1yfTbBt6YTlcEKAvsmqCZZFw46z626lVj9j1yEPW33H5H+lBQpZMP1k8l+78Ha0A==",
+ "dev": true,
+ "requires": {
+ "fill-range": "^7.0.1"
+ }
+ },
+ "browser-process-hrtime": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/browser-process-hrtime/-/browser-process-hrtime-1.0.0.tgz",
+ "integrity": "sha512-9o5UecI3GhkpM6DrXr69PblIuWxPKk9Y0jHBRhdocZ2y7YECBFCsHm79Pr3OyR2AvjhDkabFJaDJMYRazHgsow==",
+ "dev": true,
+ "peer": true
+ },
+ "browserslist": {
+ "version": "4.20.2",
+ "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.20.2.tgz",
+ "integrity": "sha512-CQOBCqp/9pDvDbx3xfMi+86pr4KXIf2FDkTTdeuYw8OxS9t898LA1Khq57gtufFILXpfgsSx5woNgsBgvGjpsA==",
+ "dev": true,
+ "requires": {
+ "caniuse-lite": "^1.0.30001317",
+ "electron-to-chromium": "^1.4.84",
+ "escalade": "^3.1.1",
+ "node-releases": "^2.0.2",
+ "picocolors": "^1.0.0"
+ }
+ },
+ "bs-logger": {
+ "version": "0.2.6",
+ "resolved": "https://registry.npmjs.org/bs-logger/-/bs-logger-0.2.6.tgz",
+ "integrity": "sha512-pd8DCoxmbgc7hyPKOvxtqNcjYoOsABPQdcCUjGp3d42VR2CX1ORhk2A87oqqu5R1kk+76nsxZupkmyd+MVtCog==",
+ "dev": true,
+ "requires": {
+ "fast-json-stable-stringify": "2.x"
+ }
+ },
+ "bser": {
+ "version": "2.1.1",
+ "resolved": "https://registry.npmjs.org/bser/-/bser-2.1.1.tgz",
+ "integrity": "sha512-gQxTNE/GAfIIrmHLUE3oJyp5FO6HRBfhjnw4/wMmA63ZGDJnWBmgY/lyQBpnDUkGmAhbSe39tx2d/iTOAfglwQ==",
+ "dev": true,
+ "peer": true,
+ "requires": {
+ "node-int64": "^0.4.0"
+ }
+ },
+ "buffer-from": {
+ "version": "1.1.2",
+ "resolved": "https://registry.npmjs.org/buffer-from/-/buffer-from-1.1.2.tgz",
+ "integrity": "sha512-E+XQCRwSbaaiChtv6k6Dwgc+bx+Bs6vuKJHHl5kox/BaKbhiXzqQOwK4cO22yElGp2OCmjwVhT3HmxgyPGnJfQ==",
+ "dev": true
+ },
+ "cache-base": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/cache-base/-/cache-base-1.0.1.tgz",
+ "integrity": "sha512-AKcdTnFSWATd5/GCPRxr2ChwIJ85CeyrEyjRHlKxQ56d4XJMGym0uAiKn0xbLOGOl3+yRpOTi484dVCEc5AUzQ==",
+ "dev": true,
+ "peer": true,
+ "requires": {
+ "collection-visit": "^1.0.0",
+ "component-emitter": "^1.2.1",
+ "get-value": "^2.0.6",
+ "has-value": "^1.0.0",
+ "isobject": "^3.0.1",
+ "set-value": "^2.0.0",
+ "to-object-path": "^0.3.0",
+ "union-value": "^1.0.0",
+ "unset-value": "^1.0.0"
+ }
+ },
+ "call-bind": {
+ "version": "1.0.2",
+ "resolved": "https://registry.npmjs.org/call-bind/-/call-bind-1.0.2.tgz",
+ "integrity": "sha512-7O+FbCihrB5WGbFYesctwmTKae6rOiIzmz1icreWJ+0aA7LJfuqhEso2T9ncpcFtzMQtzXf2QGGueWJGTYsqrA==",
+ "dev": true,
+ "requires": {
+ "function-bind": "^1.1.1",
+ "get-intrinsic": "^1.0.2"
+ }
+ },
+ "callsites": {
+ "version": "3.1.0",
+ "resolved": "https://registry.npmjs.org/callsites/-/callsites-3.1.0.tgz",
+ "integrity": "sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ==",
+ "dev": true
+ },
+ "camelcase": {
+ "version": "5.3.1",
+ "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-5.3.1.tgz",
+ "integrity": "sha512-L28STB170nwWS63UjtlEOE3dldQApaJXZkOI1uMFfzf3rRuPegHaHesyee+YxQ+W6SvRDQV6UrdOdRiR153wJg==",
+ "dev": true
+ },
+ "camelcase-keys": {
+ "version": "6.2.2",
+ "resolved": "https://registry.npmjs.org/camelcase-keys/-/camelcase-keys-6.2.2.tgz",
+ "integrity": "sha512-YrwaA0vEKazPBkn0ipTiMpSajYDSe+KjQfrjhcBMxJt/znbvlHd8Pw/Vamaz5EB4Wfhs3SUR3Z9mwRu/P3s3Yg==",
+ "dev": true,
+ "requires": {
+ "camelcase": "^5.3.1",
+ "map-obj": "^4.0.0",
+ "quick-lru": "^4.0.1"
+ }
+ },
+ "caniuse-lite": {
+ "version": "1.0.30001416",
+ "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001416.tgz",
+ "integrity": "sha512-06wzzdAkCPZO+Qm4e/eNghZBDfVNDsCgw33T27OwBH9unE9S478OYw//Q2L7Npf/zBzs7rjZOszIFQkwQKAEqA==",
+ "dev": true
+ },
+ "capture-exit": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/capture-exit/-/capture-exit-2.0.0.tgz",
+ "integrity": "sha512-PiT/hQmTonHhl/HFGN+Lx3JJUznrVYJ3+AQsnthneZbvW7x+f08Tk7yLJTLEOUvBTbduLeeBkxEaYXUOUrRq6g==",
+ "dev": true,
+ "peer": true,
+ "requires": {
+ "rsvp": "^4.8.4"
+ }
+ },
+ "ccount": {
+ "version": "1.1.0",
+ "resolved": "https://registry.npmjs.org/ccount/-/ccount-1.1.0.tgz",
+ "integrity": "sha512-vlNK021QdI7PNeiUh/lKkC/mNHHfV0m/Ad5JoI0TYtlBnJAslM/JIkm/tGC88bkLIwO6OQ5uV6ztS6kVAtCDlg==",
+ "dev": true
+ },
+ "chalk": {
+ "version": "4.1.0",
+ "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.0.tgz",
+ "integrity": "sha512-qwx12AxXe2Q5xQ43Ac//I6v5aXTipYrSESdOgzrN+9XjgEpyjpKuvSGaN4qE93f7TQTlerQQ8S+EQ0EyDoVL1A==",
+ "dev": true,
+ "requires": {
+ "ansi-styles": "^4.1.0",
+ "supports-color": "^7.1.0"
+ }
+ },
+ "char-regex": {
+ "version": "1.0.2",
+ "resolved": "https://registry.npmjs.org/char-regex/-/char-regex-1.0.2.tgz",
+ "integrity": "sha512-kWWXztvZ5SBQV+eRgKFeh8q5sLuZY2+8WUIzlxWVTg+oGwY14qylx1KbKzHd8P6ZYkAg0xyIDU9JMHhyJMZ1jw==",
+ "dev": true,
+ "peer": true
+ },
+ "character-entities": {
+ "version": "1.2.4",
+ "resolved": "https://registry.npmjs.org/character-entities/-/character-entities-1.2.4.tgz",
+ "integrity": "sha512-iBMyeEHxfVnIakwOuDXpVkc54HijNgCyQB2w0VfGQThle6NXn50zU6V/u+LDhxHcDUPojn6Kpga3PTAD8W1bQw==",
+ "dev": true
+ },
+ "character-entities-html4": {
+ "version": "1.1.4",
+ "resolved": "https://registry.npmjs.org/character-entities-html4/-/character-entities-html4-1.1.4.tgz",
+ "integrity": "sha512-HRcDxZuZqMx3/a+qrzxdBKBPUpxWEq9xw2OPZ3a/174ihfrQKVsFhqtthBInFy1zZ9GgZyFXOatNujm8M+El3g==",
+ "dev": true
+ },
+ "character-entities-legacy": {
+ "version": "1.1.4",
+ "resolved": "https://registry.npmjs.org/character-entities-legacy/-/character-entities-legacy-1.1.4.tgz",
+ "integrity": "sha512-3Xnr+7ZFS1uxeiUDvV02wQ+QDbc55o97tIV5zHScSPJpcLm/r0DFPcoY3tYRp+VZukxuMeKgXYmsXQHO05zQeA==",
+ "dev": true
+ },
+ "character-reference-invalid": {
+ "version": "1.1.4",
+ "resolved": "https://registry.npmjs.org/character-reference-invalid/-/character-reference-invalid-1.1.4.tgz",
+ "integrity": "sha512-mKKUkUbhPpQlCOfIuZkvSEgktjPFIsZKRRbC6KWVEMvlzblj3i3asQv5ODsrwt0N3pHAEvjP8KTQPHkp0+6jOg==",
+ "dev": true
+ },
+ "chardet": {
+ "version": "0.7.0",
+ "resolved": "https://registry.npmjs.org/chardet/-/chardet-0.7.0.tgz",
+ "integrity": "sha512-mT8iDcrh03qDGRRmoA2hmBJnxpllMR+0/0qlzjqZES6NdiWDcZkCNAk4rPFZ9Q85r27unkiNNg8ZOiwZXBHwcA==",
+ "dev": true
+ },
+ "ci-info": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/ci-info/-/ci-info-2.0.0.tgz",
+ "integrity": "sha512-5tK7EtrZ0N+OLFMthtqOj4fI2Jeb88C4CAZPu25LDVUgXJ0A3Js4PMGqrn0JU1W0Mh1/Z8wZzYPxqUrXeBboCQ==",
+ "dev": true
+ },
+ "cjs-module-lexer": {
+ "version": "0.6.0",
+ "resolved": "https://registry.npmjs.org/cjs-module-lexer/-/cjs-module-lexer-0.6.0.tgz",
+ "integrity": "sha512-uc2Vix1frTfnuzxxu1Hp4ktSvM3QaI4oXl4ZUqL1wjTu/BGki9TrCWoqLTg/drR1KwAEarXuRFCG2Svr1GxPFw==",
+ "dev": true,
+ "peer": true
+ },
+ "class-utils": {
+ "version": "0.3.6",
+ "resolved": "https://registry.npmjs.org/class-utils/-/class-utils-0.3.6.tgz",
+ "integrity": "sha512-qOhPa/Fj7s6TY8H8esGu5QNpMMQxz79h+urzrNYN6mn+9BnxlDGf5QZ+XeCDsxSjPqsSR56XOZOJmpeurnLMeg==",
+ "dev": true,
+ "peer": true,
+ "requires": {
+ "arr-union": "^3.1.0",
+ "define-property": "^0.2.5",
+ "isobject": "^3.0.0",
+ "static-extend": "^0.1.1"
+ },
+ "dependencies": {
+ "define-property": {
+ "version": "0.2.5",
+ "resolved": "https://registry.npmjs.org/define-property/-/define-property-0.2.5.tgz",
+ "integrity": "sha1-w1se+RjsPJkPmlvFe+BKrOxcgRY=",
+ "dev": true,
+ "peer": true,
+ "requires": {
+ "is-descriptor": "^0.1.0"
+ }
+ },
+ "is-accessor-descriptor": {
+ "version": "0.1.6",
+ "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-0.1.6.tgz",
+ "integrity": "sha1-qeEss66Nh2cn7u84Q/igiXtcmNY=",
+ "dev": true,
+ "peer": true,
+ "requires": {
+ "kind-of": "^3.0.2"
+ },
+ "dependencies": {
+ "kind-of": {
+ "version": "3.2.2",
+ "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz",
+ "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=",
+ "dev": true,
+ "peer": true,
+ "requires": {
+ "is-buffer": "^1.1.5"
+ }
+ }
+ }
+ },
+ "is-buffer": {
+ "version": "1.1.6",
+ "resolved": "https://registry.npmjs.org/is-buffer/-/is-buffer-1.1.6.tgz",
+ "integrity": "sha512-NcdALwpXkTm5Zvvbk7owOUSvVvBKDgKP5/ewfXEznmQFfs4ZRmanOeKBTjRVjka3QFoN6XJ+9F3USqfHqTaU5w==",
+ "dev": true,
+ "peer": true
+ },
+ "is-data-descriptor": {
+ "version": "0.1.4",
+ "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-0.1.4.tgz",
+ "integrity": "sha1-C17mSDiOLIYCgueT8YVv7D8wG1Y=",
+ "dev": true,
+ "peer": true,
+ "requires": {
+ "kind-of": "^3.0.2"
+ },
+ "dependencies": {
+ "kind-of": {
+ "version": "3.2.2",
+ "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz",
+ "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=",
+ "dev": true,
+ "peer": true,
+ "requires": {
+ "is-buffer": "^1.1.5"
+ }
+ }
+ }
+ },
+ "is-descriptor": {
+ "version": "0.1.6",
+ "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-0.1.6.tgz",
+ "integrity": "sha512-avDYr0SB3DwO9zsMov0gKCESFYqCnE4hq/4z3TdUlukEy5t9C0YRq7HLrsN52NAcqXKaepeCD0n+B0arnVG3Hg==",
+ "dev": true,
+ "peer": true,
+ "requires": {
+ "is-accessor-descriptor": "^0.1.6",
+ "is-data-descriptor": "^0.1.4",
+ "kind-of": "^5.0.0"
+ }
+ },
+ "kind-of": {
+ "version": "5.1.0",
+ "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-5.1.0.tgz",
+ "integrity": "sha512-NGEErnH6F2vUuXDh+OlbcKW7/wOcfdRHaZ7VWtqCztfHri/++YKmP51OdWeGPuqCOba6kk2OTe5d02VmTB80Pw==",
+ "dev": true,
+ "peer": true
+ }
+ }
+ },
+ "clean-stack": {
+ "version": "2.2.0",
+ "resolved": "https://registry.npmjs.org/clean-stack/-/clean-stack-2.2.0.tgz",
+ "integrity": "sha512-4diC9HaTE+KRAMWhDhrGOECgWZxoevMc5TlkObMqNSsVU62PYzXZ/SMTjzyGAFF1YusgxGcSWTEXBhp0CPwQ1A==",
+ "dev": true
+ },
+ "cli-cursor": {
+ "version": "3.1.0",
+ "resolved": "https://registry.npmjs.org/cli-cursor/-/cli-cursor-3.1.0.tgz",
+ "integrity": "sha512-I/zHAwsKf9FqGoXM4WWRACob9+SNukZTd94DWF57E4toouRulbCxcUh6RKUEOQlYTHJnzkPMySvPNaaSLNfLZw==",
+ "dev": true,
+ "requires": {
+ "restore-cursor": "^3.1.0"
+ }
+ },
+ "cli-truncate": {
+ "version": "2.1.0",
+ "resolved": "https://registry.npmjs.org/cli-truncate/-/cli-truncate-2.1.0.tgz",
+ "integrity": "sha512-n8fOixwDD6b/ObinzTrp1ZKFzbgvKZvuz/TvejnLn1aQfC6r52XEx85FmuC+3HI+JM7coBRXUvNqEU2PHVrHpg==",
+ "dev": true,
+ "requires": {
+ "slice-ansi": "^3.0.0",
+ "string-width": "^4.2.0"
+ }
+ },
+ "cli-width": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/cli-width/-/cli-width-3.0.0.tgz",
+ "integrity": "sha512-FxqpkPPwu1HjuN93Omfm4h8uIanXofW0RxVEW3k5RKx+mJJYSthzNhp32Kzxxy3YAEZ/Dc/EWN1vZRY0+kOhbw==",
+ "dev": true
+ },
+ "cliui": {
+ "version": "6.0.0",
+ "resolved": "https://registry.npmjs.org/cliui/-/cliui-6.0.0.tgz",
+ "integrity": "sha512-t6wbgtoCXvAzst7QgXxJYqPt0usEfbgQdftEPbLL/cvv6HPE5VgvqCuAIDR0NgU52ds6rFwqrgakNLrHEjCbrQ==",
+ "dev": true,
+ "peer": true,
+ "requires": {
+ "string-width": "^4.2.0",
+ "strip-ansi": "^6.0.0",
+ "wrap-ansi": "^6.2.0"
+ },
+ "dependencies": {
+ "wrap-ansi": {
+ "version": "6.2.0",
+ "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-6.2.0.tgz",
+ "integrity": "sha512-r6lPcBGxZXlIcymEu7InxDMhdW0KDxpLgoFLcguasxCaJ/SOIZwINatK9KY/tf+ZrlywOKU0UDj3ATXUBfxJXA==",
+ "dev": true,
+ "peer": true,
+ "requires": {
+ "ansi-styles": "^4.0.0",
+ "string-width": "^4.1.0",
+ "strip-ansi": "^6.0.0"
+ }
+ }
+ }
+ },
+ "clone-regexp": {
+ "version": "2.2.0",
+ "resolved": "https://registry.npmjs.org/clone-regexp/-/clone-regexp-2.2.0.tgz",
+ "integrity": "sha512-beMpP7BOtTipFuW8hrJvREQ2DrRu3BE7by0ZpibtfBA+qfHYvMGTc2Yb1JMYPKg/JUw0CHYvpg796aNTSW9z7Q==",
+ "dev": true,
+ "requires": {
+ "is-regexp": "^2.0.0"
+ },
+ "dependencies": {
+ "is-regexp": {
+ "version": "2.1.0",
+ "resolved": "https://registry.npmjs.org/is-regexp/-/is-regexp-2.1.0.tgz",
+ "integrity": "sha512-OZ4IlER3zmRIoB9AqNhEggVxqIH4ofDns5nRrPS6yQxXE1TPCUpFznBfRQmQa8uC+pXqjMnukiJBxCisIxiLGA==",
+ "dev": true
+ }
+ }
+ },
+ "co": {
+ "version": "4.6.0",
+ "resolved": "https://registry.npmjs.org/co/-/co-4.6.0.tgz",
+ "integrity": "sha1-bqa989hTrlTMuOR7+gvz+QMfsYQ=",
+ "dev": true,
+ "peer": true
+ },
+ "collapse-white-space": {
+ "version": "1.0.6",
+ "resolved": "https://registry.npmjs.org/collapse-white-space/-/collapse-white-space-1.0.6.tgz",
+ "integrity": "sha512-jEovNnrhMuqyCcjfEJA56v0Xq8SkIoPKDyaHahwo3POf4qcSXqMYuwNcOTzp74vTsR9Tn08z4MxWqAhcekogkQ==",
+ "dev": true
+ },
+ "collect-v8-coverage": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/collect-v8-coverage/-/collect-v8-coverage-1.0.1.tgz",
+ "integrity": "sha512-iBPtljfCNcTKNAto0KEtDfZ3qzjJvqE3aTGZsbhjSBlorqpXJlaWWtPO35D+ZImoC3KWejX64o+yPGxhWSTzfg==",
+ "dev": true,
+ "peer": true
+ },
+ "collection-visit": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/collection-visit/-/collection-visit-1.0.0.tgz",
+ "integrity": "sha1-S8A3PBZLwykbTTaMgpzxqApZ3KA=",
+ "dev": true,
+ "peer": true,
+ "requires": {
+ "map-visit": "^1.0.0",
+ "object-visit": "^1.0.0"
+ }
+ },
+ "color-convert": {
+ "version": "2.0.1",
+ "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz",
+ "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==",
+ "dev": true,
+ "requires": {
+ "color-name": "~1.1.4"
+ }
+ },
+ "color-name": {
+ "version": "1.1.4",
+ "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz",
+ "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==",
+ "dev": true
+ },
+ "colorette": {
+ "version": "2.0.16",
+ "resolved": "https://registry.npmjs.org/colorette/-/colorette-2.0.16.tgz",
+ "integrity": "sha512-hUewv7oMjCp+wkBv5Rm0v87eJhq4woh5rSR+42YSQJKecCqgIqNkZ6lAlQms/BwHPJA5NKMRlpxPRv0n8HQW6g==",
+ "dev": true
+ },
+ "combined-stream": {
+ "version": "1.0.8",
+ "resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.8.tgz",
+ "integrity": "sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg==",
+ "dev": true,
+ "requires": {
+ "delayed-stream": "~1.0.0"
+ }
+ },
+ "commander": {
+ "version": "7.2.0",
+ "resolved": "https://registry.npmjs.org/commander/-/commander-7.2.0.tgz",
+ "integrity": "sha512-QrWXB+ZQSVPmIWIhtEO9H+gwHaMGYiF5ChvoJ+K9ZGHG/sVsa6yiesAD1GC/x46sET00Xlwo1u49RVVVzvcSkw==",
+ "dev": true
+ },
+ "compare-versions": {
+ "version": "3.6.0",
+ "resolved": "https://registry.npmjs.org/compare-versions/-/compare-versions-3.6.0.tgz",
+ "integrity": "sha512-W6Af2Iw1z4CB7q4uU4hv646dW9GQuBM+YpC0UvUCWSD8w90SJjp+ujJuXaEMtAXBtSqGfMPuFOVn4/+FlaqfBA==",
+ "dev": true
+ },
+ "component-emitter": {
+ "version": "1.3.0",
+ "resolved": "https://registry.npmjs.org/component-emitter/-/component-emitter-1.3.0.tgz",
+ "integrity": "sha512-Rd3se6QB+sO1TwqZjscQrurpEPIfO0/yYnSin6Q/rD3mOutHvUrCAhJub3r90uNb+SESBuE0QYoB90YdfatsRg==",
+ "dev": true,
+ "peer": true
+ },
+ "concat-map": {
+ "version": "0.0.1",
+ "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz",
+ "integrity": "sha1-2Klr13/Wjfd5OnMDajug1UBdR3s=",
+ "dev": true
+ },
+ "convert-source-map": {
+ "version": "1.8.0",
+ "resolved": "https://registry.npmjs.org/convert-source-map/-/convert-source-map-1.8.0.tgz",
+ "integrity": "sha512-+OQdjP49zViI/6i7nIJpA8rAl4sV/JdPfU9nZs3VqOwGIgizICvuN2ru6fMd+4llL0tar18UYJXfZ/TWtmhUjA==",
+ "dev": true,
+ "requires": {
+ "safe-buffer": "~5.1.1"
+ }
+ },
+ "copy-descriptor": {
+ "version": "0.1.1",
+ "resolved": "https://registry.npmjs.org/copy-descriptor/-/copy-descriptor-0.1.1.tgz",
+ "integrity": "sha1-Z29us8OZl8LuGsOpJP1hJHSPV40=",
+ "dev": true,
+ "peer": true
+ },
+ "cosmiconfig": {
+ "version": "7.0.0",
+ "resolved": "https://registry.npmjs.org/cosmiconfig/-/cosmiconfig-7.0.0.tgz",
+ "integrity": "sha512-pondGvTuVYDk++upghXJabWzL6Kxu6f26ljFw64Swq9v6sQPUL3EUlVDV56diOjpCayKihL6hVe8exIACU4XcA==",
+ "dev": true,
+ "requires": {
+ "@types/parse-json": "^4.0.0",
+ "import-fresh": "^3.2.1",
+ "parse-json": "^5.0.0",
+ "path-type": "^4.0.0",
+ "yaml": "^1.10.0"
+ }
+ },
+ "cross-fetch": {
+ "version": "3.1.5",
+ "resolved": "https://registry.npmjs.org/cross-fetch/-/cross-fetch-3.1.5.tgz",
+ "integrity": "sha512-lvb1SBsI0Z7GDwmuid+mU3kWVBwTVUbe7S0H52yaaAdQOXq2YktTCZdlAcNKFzE6QtRz0snpw9bNiPeOIkkQvw==",
+ "dev": true,
+ "requires": {
+ "node-fetch": "2.6.7"
+ }
+ },
+ "cross-spawn": {
+ "version": "7.0.3",
+ "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.3.tgz",
+ "integrity": "sha512-iRDPJKUPVEND7dHPO8rkbOnPpyDygcDFtWjpeWNCgy8WP2rXcxXL8TskReQl6OrB2G7+UJrags1q15Fudc7G6w==",
+ "dev": true,
+ "requires": {
+ "path-key": "^3.1.0",
+ "shebang-command": "^2.0.0",
+ "which": "^2.0.1"
+ }
+ },
+ "cssesc": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/cssesc/-/cssesc-3.0.0.tgz",
+ "integrity": "sha512-/Tb/JcjK111nNScGob5MNtsntNM1aCNUDipB/TkwZFhyDrrE47SOx/18wF2bbjgc3ZzCSKW1T5nt5EbFoAz/Vg==",
+ "dev": true
+ },
+ "cssom": {
+ "version": "0.4.4",
+ "resolved": "https://registry.npmjs.org/cssom/-/cssom-0.4.4.tgz",
+ "integrity": "sha512-p3pvU7r1MyyqbTk+WbNJIgJjG2VmTIaB10rI93LzVPrmDJKkzKYMtxxyAvQXR/NS6otuzveI7+7BBq3SjBS2mw==",
+ "dev": true,
+ "peer": true
+ },
+ "cssstyle": {
+ "version": "2.3.0",
+ "resolved": "https://registry.npmjs.org/cssstyle/-/cssstyle-2.3.0.tgz",
+ "integrity": "sha512-AZL67abkUzIuvcHqk7c09cezpGNcxUxU4Ioi/05xHk4DQeTkWmGYftIE6ctU6AEt+Gn4n1lDStOtj7FKycP71A==",
+ "dev": true,
+ "peer": true,
+ "requires": {
+ "cssom": "~0.3.6"
+ },
+ "dependencies": {
+ "cssom": {
+ "version": "0.3.8",
+ "resolved": "https://registry.npmjs.org/cssom/-/cssom-0.3.8.tgz",
+ "integrity": "sha512-b0tGHbfegbhPJpxpiBPU2sCkigAqtM9O121le6bbOlgyV+NyGyCmVfJ6QW9eRjz8CpNfWEOYBIMIGRYkLwsIYg==",
+ "dev": true,
+ "peer": true
+ }
+ }
+ },
+ "damerau-levenshtein": {
+ "version": "1.0.8",
+ "resolved": "https://registry.npmjs.org/damerau-levenshtein/-/damerau-levenshtein-1.0.8.tgz",
+ "integrity": "sha512-sdQSFB7+llfUcQHUQO3+B8ERRj0Oa4w9POWMI/puGtuf7gFywGmkaLCElnudfTiKZV+NvHqL0ifzdrI8Ro7ESA==",
+ "dev": true
+ },
+ "dart-linkcheck": {
+ "version": "2.0.15",
+ "resolved": "https://registry.npmjs.org/dart-linkcheck/-/dart-linkcheck-2.0.15.tgz",
+ "integrity": "sha512-ZMvxkAyEpBTvBFk+DPjcK0ObNy8GM4gmrGG1qIu0EXb/zj25vjRWNnhLHKZw4JlOLo02oWlwDeqo98GuBlJcIg==",
+ "dev": true
+ },
+ "data-urls": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/data-urls/-/data-urls-2.0.0.tgz",
+ "integrity": "sha512-X5eWTSXO/BJmpdIKCRuKUgSCgAN0OwliVK3yPKbwIWU1Tdw5BRajxlzMidvh+gwko9AfQ9zIj52pzF91Q3YAvQ==",
+ "dev": true,
+ "peer": true,
+ "requires": {
+ "abab": "^2.0.3",
+ "whatwg-mimetype": "^2.3.0",
+ "whatwg-url": "^8.0.0"
+ }
+ },
+ "debug": {
+ "version": "4.3.4",
+ "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz",
+ "integrity": "sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==",
+ "dev": true,
+ "requires": {
+ "ms": "2.1.2"
+ }
+ },
+ "decamelize": {
+ "version": "1.2.0",
+ "resolved": "https://registry.npmjs.org/decamelize/-/decamelize-1.2.0.tgz",
+ "integrity": "sha1-9lNNFRSCabIDUue+4m9QH5oZEpA=",
+ "dev": true
+ },
+ "decamelize-keys": {
+ "version": "1.1.0",
+ "resolved": "https://registry.npmjs.org/decamelize-keys/-/decamelize-keys-1.1.0.tgz",
+ "integrity": "sha1-0XGoeTMlKAfrPLYdwcFEXQeN8tk=",
+ "dev": true,
+ "requires": {
+ "decamelize": "^1.1.0",
+ "map-obj": "^1.0.0"
+ },
+ "dependencies": {
+ "map-obj": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/map-obj/-/map-obj-1.0.1.tgz",
+ "integrity": "sha1-2TPOuSBdgr3PSIb2dCvcK03qFG0=",
+ "dev": true
+ }
+ }
+ },
+ "decimal.js": {
+ "version": "10.3.1",
+ "resolved": "https://registry.npmjs.org/decimal.js/-/decimal.js-10.3.1.tgz",
+ "integrity": "sha512-V0pfhfr8suzyPGOx3nmq4aHqabehUZn6Ch9kyFpV79TGDTWFmHqUqXdabR7QHqxzrYolF4+tVmJhUG4OURg5dQ==",
+ "dev": true,
+ "peer": true
+ },
+ "decode-uri-component": {
+ "version": "0.2.0",
+ "resolved": "https://registry.npmjs.org/decode-uri-component/-/decode-uri-component-0.2.0.tgz",
+ "integrity": "sha1-6zkTMzRYd1y4TNGh+uBiEGu4dUU=",
+ "dev": true,
+ "peer": true
+ },
+ "deep-equal": {
+ "version": "2.2.0",
+ "resolved": "https://registry.npmjs.org/deep-equal/-/deep-equal-2.2.0.tgz",
+ "integrity": "sha512-RdpzE0Hv4lhowpIUKKMJfeH6C1pXdtT1/it80ubgWqwI3qpuxUBpC1S4hnHg+zjnuOoDkzUtUCEEkG+XG5l3Mw==",
+ "dev": true,
+ "requires": {
+ "call-bind": "^1.0.2",
+ "es-get-iterator": "^1.1.2",
+ "get-intrinsic": "^1.1.3",
+ "is-arguments": "^1.1.1",
+ "is-array-buffer": "^3.0.1",
+ "is-date-object": "^1.0.5",
+ "is-regex": "^1.1.4",
+ "is-shared-array-buffer": "^1.0.2",
+ "isarray": "^2.0.5",
+ "object-is": "^1.1.5",
+ "object-keys": "^1.1.1",
+ "object.assign": "^4.1.4",
+ "regexp.prototype.flags": "^1.4.3",
+ "side-channel": "^1.0.4",
+ "which-boxed-primitive": "^1.0.2",
+ "which-collection": "^1.0.1",
+ "which-typed-array": "^1.1.9"
+ },
+ "dependencies": {
+ "isarray": {
+ "version": "2.0.5",
+ "resolved": "https://registry.npmjs.org/isarray/-/isarray-2.0.5.tgz",
+ "integrity": "sha512-xHjhDr3cNBK0BzdUJSPXZntQUx/mwMS5Rw4A7lPJ90XGAO6ISP/ePDNuo0vhqOZU+UD5JoodwCAAoZQd3FeAKw==",
+ "dev": true
+ }
+ }
+ },
+ "deep-is": {
+ "version": "0.1.4",
+ "resolved": "https://registry.npmjs.org/deep-is/-/deep-is-0.1.4.tgz",
+ "integrity": "sha512-oIPzksmTg4/MriiaYGO+okXDT7ztn/w3Eptv/+gSIdMdKsJo0u4CfYNFJPy+4SKMuCqGw2wxnA+URMg3t8a/bQ==",
+ "dev": true
+ },
+ "deepmerge": {
+ "version": "4.2.2",
+ "resolved": "https://registry.npmjs.org/deepmerge/-/deepmerge-4.2.2.tgz",
+ "integrity": "sha512-FJ3UgI4gIl+PHZm53knsuSFpE+nESMr7M4v9QcgB7S63Kj/6WqMiFQJpBBYz1Pt+66bZpP3Q7Lye0Oo9MPKEdg==",
+ "dev": true,
+ "peer": true
+ },
+ "define-lazy-prop": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/define-lazy-prop/-/define-lazy-prop-2.0.0.tgz",
+ "integrity": "sha512-Ds09qNh8yw3khSjiJjiUInaGX9xlqZDY7JVryGxdxV7NPeuqQfplOpQ66yJFZut3jLa5zOwkXw1g9EI2uKh4Og==",
+ "dev": true
+ },
+ "define-properties": {
+ "version": "1.2.0",
+ "resolved": "https://registry.npmjs.org/define-properties/-/define-properties-1.2.0.tgz",
+ "integrity": "sha512-xvqAVKGfT1+UAvPwKTVw/njhdQ8ZhXK4lI0bCIuCMrp2up9nPnaDftrLtmpTazqd1o+UY4zgzU+avtMbDP+ldA==",
+ "dev": true,
+ "requires": {
+ "has-property-descriptors": "^1.0.0",
+ "object-keys": "^1.1.1"
+ }
+ },
+ "define-property": {
+ "version": "2.0.2",
+ "resolved": "https://registry.npmjs.org/define-property/-/define-property-2.0.2.tgz",
+ "integrity": "sha512-jwK2UV4cnPpbcG7+VRARKTZPUWowwXA8bzH5NP6ud0oeAxyYPuGZUAC7hMugpCdz4BeSZl2Dl9k66CHJ/46ZYQ==",
+ "dev": true,
+ "peer": true,
+ "requires": {
+ "is-descriptor": "^1.0.2",
+ "isobject": "^3.0.1"
+ }
+ },
+ "delayed-stream": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz",
+ "integrity": "sha1-3zrhmayt+31ECqrgsp4icrJOxhk=",
+ "dev": true
+ },
+ "detect-newline": {
+ "version": "3.1.0",
+ "resolved": "https://registry.npmjs.org/detect-newline/-/detect-newline-3.1.0.tgz",
+ "integrity": "sha512-TLz+x/vEXm/Y7P7wn1EJFNLxYpUD4TgMosxY6fAVJUnJMbupHBOncxyWUG9OpTaH9EBD7uFI5LfEgmMOc54DsA==",
+ "dev": true,
+ "peer": true
+ },
+ "diff-sequences": {
+ "version": "26.6.2",
+ "resolved": "https://registry.npmjs.org/diff-sequences/-/diff-sequences-26.6.2.tgz",
+ "integrity": "sha512-Mv/TDa3nZ9sbc5soK+OoA74BsS3mL37yixCvUAQkiuA4Wz6YtwP/K47n2rv2ovzHZvoiQeA5FTQOschKkEwB0Q==",
+ "dev": true,
+ "peer": true
+ },
+ "dir-glob": {
+ "version": "3.0.1",
+ "resolved": "https://registry.npmjs.org/dir-glob/-/dir-glob-3.0.1.tgz",
+ "integrity": "sha512-WkrWp9GR4KXfKGYzOLmTuGVi1UWFfws377n9cc55/tb6DuqyF6pcQ5AbiHEshaDpY9v6oaSr2XCDidGmMwdzIA==",
+ "dev": true,
+ "requires": {
+ "path-type": "^4.0.0"
+ }
+ },
+ "doctrine": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/doctrine/-/doctrine-3.0.0.tgz",
+ "integrity": "sha512-yS+Q5i3hBf7GBkd4KG8a7eBNNWNGLTaEwwYWUijIYM7zrlYDM0BFXHjjPWlWZ1Rg7UaddZeIDmi9jF3HmqiQ2w==",
+ "dev": true,
+ "requires": {
+ "esutils": "^2.0.2"
+ }
+ },
+ "dom-serializer": {
+ "version": "0.2.2",
+ "resolved": "https://registry.npmjs.org/dom-serializer/-/dom-serializer-0.2.2.tgz",
+ "integrity": "sha512-2/xPb3ORsQ42nHYiSunXkDjPLBaEj/xTwUO4B7XCZQTRk7EBtTOPaygh10YAAh2OI1Qrp6NWfpAhzswj0ydt9g==",
+ "dev": true,
+ "requires": {
+ "domelementtype": "^2.0.1",
+ "entities": "^2.0.0"
+ },
+ "dependencies": {
+ "domelementtype": {
+ "version": "2.3.0",
+ "resolved": "https://registry.npmjs.org/domelementtype/-/domelementtype-2.3.0.tgz",
+ "integrity": "sha512-OLETBj6w0OsagBwdXnPdN0cnMfF9opN69co+7ZrbfPGrdpPVNBUj02spi6B1N7wChLQiPn4CSH/zJvXw56gmHw==",
+ "dev": true
+ },
+ "entities": {
+ "version": "2.2.0",
+ "resolved": "https://registry.npmjs.org/entities/-/entities-2.2.0.tgz",
+ "integrity": "sha512-p92if5Nz619I0w+akJrLZH0MX0Pb5DX39XOwQTtXSdQQOaYH03S1uIQp4mhOZtAXrxq4ViO67YTiLBo2638o9A==",
+ "dev": true
+ }
+ }
+ },
+ "domelementtype": {
+ "version": "1.3.1",
+ "resolved": "https://registry.npmjs.org/domelementtype/-/domelementtype-1.3.1.tgz",
+ "integrity": "sha512-BSKB+TSpMpFI/HOxCNr1O8aMOTZ8hT3pM3GQ0w/mWRmkhEDSFJkkyzz4XQsBV44BChwGkrDfMyjVD0eA2aFV3w==",
+ "dev": true
+ },
+ "domexception": {
+ "version": "2.0.1",
+ "resolved": "https://registry.npmjs.org/domexception/-/domexception-2.0.1.tgz",
+ "integrity": "sha512-yxJ2mFy/sibVQlu5qHjOkf9J3K6zgmCxgJ94u2EdvDOV09H+32LtRswEcUsmUWN72pVLOEnTSRaIVVzVQgS0dg==",
+ "dev": true,
+ "peer": true,
+ "requires": {
+ "webidl-conversions": "^5.0.0"
+ },
+ "dependencies": {
+ "webidl-conversions": {
+ "version": "5.0.0",
+ "resolved": "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-5.0.0.tgz",
+ "integrity": "sha512-VlZwKPCkYKxQgeSbH5EyngOmRp7Ww7I9rQLERETtf5ofd9pGeswWiOtogpEO850jziPRarreGxn5QIiTqpb2wA==",
+ "dev": true,
+ "peer": true
+ }
+ }
+ },
+ "domhandler": {
+ "version": "2.4.2",
+ "resolved": "https://registry.npmjs.org/domhandler/-/domhandler-2.4.2.tgz",
+ "integrity": "sha512-JiK04h0Ht5u/80fdLMCEmV4zkNh2BcoMFBmZ/91WtYZ8qVXSKjiw7fXMgFPnHcSZgOo3XdinHvmnDUeMf5R4wA==",
+ "dev": true,
+ "requires": {
+ "domelementtype": "1"
+ }
+ },
+ "domutils": {
+ "version": "1.7.0",
+ "resolved": "https://registry.npmjs.org/domutils/-/domutils-1.7.0.tgz",
+ "integrity": "sha512-Lgd2XcJ/NjEw+7tFvfKxOzCYKZsdct5lczQ2ZaQY8Djz7pfAD3Gbp8ySJWtreII/vDlMVmxwa6pHmdxIYgttDg==",
+ "dev": true,
+ "requires": {
+ "dom-serializer": "0",
+ "domelementtype": "1"
+ }
+ },
+ "eastasianwidth": {
+ "version": "0.2.0",
+ "resolved": "https://registry.npmjs.org/eastasianwidth/-/eastasianwidth-0.2.0.tgz",
+ "integrity": "sha512-I88TYZWc9XiYHRQ4/3c5rjjfgkjhLyW2luGIheGERbNQ6OY7yTybanSpDXZa8y7VUP9YmDcYa+eyq4ca7iLqWA==",
+ "dev": true
+ },
+ "ejs": {
+ "version": "3.1.5",
+ "resolved": "https://registry.npmjs.org/ejs/-/ejs-3.1.5.tgz",
+ "integrity": "sha512-dldq3ZfFtgVTJMLjOe+/3sROTzALlL9E34V4/sDtUd/KlBSS0s6U1/+WPE1B4sj9CXHJpL1M6rhNJnc9Wbal9w==",
+ "dev": true,
+ "requires": {
+ "jake": "^10.6.1"
+ }
+ },
+ "electron-to-chromium": {
+ "version": "1.4.114",
+ "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.4.114.tgz",
+ "integrity": "sha512-gRwLpVYWHGbERPU6o8pKfR168V6enWEXzZc6zQNNXbgJ7UJna+9qzAIHY94+9KOv71D/CH+QebLA9pChD2q8zA==",
+ "dev": true
+ },
+ "emittery": {
+ "version": "0.7.2",
+ "resolved": "https://registry.npmjs.org/emittery/-/emittery-0.7.2.tgz",
+ "integrity": "sha512-A8OG5SR/ij3SsJdWDJdkkSYUjQdCUx6APQXem0SaEePBSRg4eymGYwBkKo1Y6DU+af/Jn2dBQqDBvjnr9Vi8nQ==",
+ "dev": true,
+ "peer": true
+ },
+ "emoji-regex": {
+ "version": "9.2.2",
+ "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-9.2.2.tgz",
+ "integrity": "sha512-L18DaJsXSUk2+42pv8mLs5jJT2hqFkFE4j21wOmgbUqsZ2hL72NsUU785g9RXgo3s0ZNgVl42TiHp3ZtOv/Vyg==",
+ "dev": true
+ },
+ "end-of-stream": {
+ "version": "1.4.4",
+ "resolved": "https://registry.npmjs.org/end-of-stream/-/end-of-stream-1.4.4.tgz",
+ "integrity": "sha512-+uw1inIHVPQoaVuHzRyXd21icM+cnt4CzD5rW+NC1wjOUSTOs+Te7FOv7AhN7vS9x/oIyhLP5PR1H+phQAHu5Q==",
+ "dev": true,
+ "peer": true,
+ "requires": {
+ "once": "^1.4.0"
+ }
+ },
+ "enhanced-resolve": {
+ "version": "5.12.0",
+ "resolved": "https://registry.npmjs.org/enhanced-resolve/-/enhanced-resolve-5.12.0.tgz",
+ "integrity": "sha512-QHTXI/sZQmko1cbDoNAa3mJ5qhWUUNAq3vR0/YiD379fWQrcfuoX1+HW2S0MTt7XmoPLapdaDKUtelUSPic7hQ==",
+ "dev": true,
+ "requires": {
+ "graceful-fs": "^4.2.4",
+ "tapable": "^2.2.0"
+ }
+ },
+ "enquirer": {
+ "version": "2.3.6",
+ "resolved": "https://registry.npmjs.org/enquirer/-/enquirer-2.3.6.tgz",
+ "integrity": "sha512-yjNnPr315/FjS4zIsUxYguYUPP2e1NK4d7E7ZOLiyYCcbFBiTMyID+2wvm2w6+pZ/odMA7cRkjhsPbltwBOrLg==",
+ "dev": true,
+ "requires": {
+ "ansi-colors": "^4.1.1"
+ }
+ },
+ "entities": {
+ "version": "1.1.2",
+ "resolved": "https://registry.npmjs.org/entities/-/entities-1.1.2.tgz",
+ "integrity": "sha512-f2LZMYl1Fzu7YSBKg+RoROelpOaNrcGmE9AZubeDfrCEia483oW4MI4VyFd5VNHIgQ/7qm1I0wUHK1eJnn2y2w==",
+ "dev": true
+ },
+ "error-ex": {
+ "version": "1.3.2",
+ "resolved": "https://registry.npmjs.org/error-ex/-/error-ex-1.3.2.tgz",
+ "integrity": "sha512-7dFHNmqeFSEt2ZBsCriorKnn3Z2pj+fd9kmI6QoWw4//DL+icEBfc0U7qJCisqrTsKTjw4fNFy2pW9OqStD84g==",
+ "dev": true,
+ "requires": {
+ "is-arrayish": "^0.2.1"
+ }
+ },
+ "es-abstract": {
+ "version": "1.21.2",
+ "resolved": "https://registry.npmjs.org/es-abstract/-/es-abstract-1.21.2.tgz",
+ "integrity": "sha512-y/B5POM2iBnIxCiernH1G7rC9qQoM77lLIMQLuob0zhp8C56Po81+2Nj0WFKnd0pNReDTnkYryc+zhOzpEIROg==",
+ "dev": true,
+ "requires": {
+ "array-buffer-byte-length": "^1.0.0",
+ "available-typed-arrays": "^1.0.5",
+ "call-bind": "^1.0.2",
+ "es-set-tostringtag": "^2.0.1",
+ "es-to-primitive": "^1.2.1",
+ "function.prototype.name": "^1.1.5",
+ "get-intrinsic": "^1.2.0",
+ "get-symbol-description": "^1.0.0",
+ "globalthis": "^1.0.3",
+ "gopd": "^1.0.1",
+ "has": "^1.0.3",
+ "has-property-descriptors": "^1.0.0",
+ "has-proto": "^1.0.1",
+ "has-symbols": "^1.0.3",
+ "internal-slot": "^1.0.5",
+ "is-array-buffer": "^3.0.2",
+ "is-callable": "^1.2.7",
+ "is-negative-zero": "^2.0.2",
+ "is-regex": "^1.1.4",
+ "is-shared-array-buffer": "^1.0.2",
+ "is-string": "^1.0.7",
+ "is-typed-array": "^1.1.10",
+ "is-weakref": "^1.0.2",
+ "object-inspect": "^1.12.3",
+ "object-keys": "^1.1.1",
+ "object.assign": "^4.1.4",
+ "regexp.prototype.flags": "^1.4.3",
+ "safe-regex-test": "^1.0.0",
+ "string.prototype.trim": "^1.2.7",
+ "string.prototype.trimend": "^1.0.6",
+ "string.prototype.trimstart": "^1.0.6",
+ "typed-array-length": "^1.0.4",
+ "unbox-primitive": "^1.0.2",
+ "which-typed-array": "^1.1.9"
+ }
+ },
+ "es-get-iterator": {
+ "version": "1.1.3",
+ "resolved": "https://registry.npmjs.org/es-get-iterator/-/es-get-iterator-1.1.3.tgz",
+ "integrity": "sha512-sPZmqHBe6JIiTfN5q2pEi//TwxmAFHwj/XEuYjTuse78i8KxaqMTTzxPoFKuzRpDpTJ+0NAbpfenkmH2rePtuw==",
+ "dev": true,
+ "requires": {
+ "call-bind": "^1.0.2",
+ "get-intrinsic": "^1.1.3",
+ "has-symbols": "^1.0.3",
+ "is-arguments": "^1.1.1",
+ "is-map": "^2.0.2",
+ "is-set": "^2.0.2",
+ "is-string": "^1.0.7",
+ "isarray": "^2.0.5",
+ "stop-iteration-iterator": "^1.0.0"
+ },
+ "dependencies": {
+ "isarray": {
+ "version": "2.0.5",
+ "resolved": "https://registry.npmjs.org/isarray/-/isarray-2.0.5.tgz",
+ "integrity": "sha512-xHjhDr3cNBK0BzdUJSPXZntQUx/mwMS5Rw4A7lPJ90XGAO6ISP/ePDNuo0vhqOZU+UD5JoodwCAAoZQd3FeAKw==",
+ "dev": true
+ }
+ }
+ },
+ "es-set-tostringtag": {
+ "version": "2.0.1",
+ "resolved": "https://registry.npmjs.org/es-set-tostringtag/-/es-set-tostringtag-2.0.1.tgz",
+ "integrity": "sha512-g3OMbtlwY3QewlqAiMLI47KywjWZoEytKr8pf6iTC8uJq5bIAH52Z9pnQ8pVL6whrCto53JZDuUIsifGeLorTg==",
+ "dev": true,
+ "requires": {
+ "get-intrinsic": "^1.1.3",
+ "has": "^1.0.3",
+ "has-tostringtag": "^1.0.0"
+ }
+ },
+ "es-shim-unscopables": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/es-shim-unscopables/-/es-shim-unscopables-1.0.0.tgz",
+ "integrity": "sha512-Jm6GPcCdC30eMLbZ2x8z2WuRwAws3zTBBKuusffYVUrNj/GVSUAZ+xKMaUpfNDR5IbyNA5LJbaecoUVbmUcB1w==",
+ "dev": true,
+ "requires": {
+ "has": "^1.0.3"
+ }
+ },
+ "es-to-primitive": {
+ "version": "1.2.1",
+ "resolved": "https://registry.npmjs.org/es-to-primitive/-/es-to-primitive-1.2.1.tgz",
+ "integrity": "sha512-QCOllgZJtaUo9miYBcLChTUaHNjJF3PYs1VidD7AwiEj1kYxKeQTctLAezAOH5ZKRH0g2IgPn6KwB4IT8iRpvA==",
+ "dev": true,
+ "requires": {
+ "is-callable": "^1.1.4",
+ "is-date-object": "^1.0.1",
+ "is-symbol": "^1.0.2"
+ }
+ },
+ "escalade": {
+ "version": "3.1.1",
+ "resolved": "https://registry.npmjs.org/escalade/-/escalade-3.1.1.tgz",
+ "integrity": "sha512-k0er2gUkLf8O0zKJiAhmkTnJlTvINGv7ygDNPbeIsX/TJjGJZHuh9B2UxbsaEkmlEo9MfhrSzmhIlhRlI2GXnw==",
+ "dev": true
+ },
+ "escape-string-regexp": {
+ "version": "1.0.5",
+ "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz",
+ "integrity": "sha1-G2HAViGQqN/2rjuyzwIAyhMLhtQ=",
+ "dev": true
+ },
+ "escodegen": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/escodegen/-/escodegen-2.0.0.tgz",
+ "integrity": "sha512-mmHKys/C8BFUGI+MAWNcSYoORYLMdPzjrknd2Vc+bUsjN5bXcr8EhrNB+UTqfL1y3I9c4fw2ihgtMPQLBRiQxw==",
+ "dev": true,
+ "peer": true,
+ "requires": {
+ "esprima": "^4.0.1",
+ "estraverse": "^5.2.0",
+ "esutils": "^2.0.2",
+ "optionator": "^0.8.1",
+ "source-map": "~0.6.1"
+ },
+ "dependencies": {
+ "levn": {
+ "version": "0.3.0",
+ "resolved": "https://registry.npmjs.org/levn/-/levn-0.3.0.tgz",
+ "integrity": "sha1-OwmSTt+fCDwEkP3UwLxEIeBHZO4=",
+ "dev": true,
+ "peer": true,
+ "requires": {
+ "prelude-ls": "~1.1.2",
+ "type-check": "~0.3.2"
+ }
+ },
+ "optionator": {
+ "version": "0.8.3",
+ "resolved": "https://registry.npmjs.org/optionator/-/optionator-0.8.3.tgz",
+ "integrity": "sha512-+IW9pACdk3XWmmTXG8m3upGUJst5XRGzxMRjXzAuJ1XnIFNvfhjjIuYkDvysnPQ7qzqVzLt78BCruntqRhWQbA==",
+ "dev": true,
+ "peer": true,
+ "requires": {
+ "deep-is": "~0.1.3",
+ "fast-levenshtein": "~2.0.6",
+ "levn": "~0.3.0",
+ "prelude-ls": "~1.1.2",
+ "type-check": "~0.3.2",
+ "word-wrap": "~1.2.3"
+ }
+ },
+ "prelude-ls": {
+ "version": "1.1.2",
+ "resolved": "https://registry.npmjs.org/prelude-ls/-/prelude-ls-1.1.2.tgz",
+ "integrity": "sha1-IZMqVJ9eUv/ZqCf1cOBL5iqX2lQ=",
+ "dev": true,
+ "peer": true
+ },
+ "type-check": {
+ "version": "0.3.2",
+ "resolved": "https://registry.npmjs.org/type-check/-/type-check-0.3.2.tgz",
+ "integrity": "sha1-WITKtRLPHTVeP7eE8wgEsrUg23I=",
+ "dev": true,
+ "peer": true,
+ "requires": {
+ "prelude-ls": "~1.1.2"
+ }
+ }
+ }
+ },
+ "eslint": {
+ "version": "8.36.0",
+ "resolved": "https://registry.npmjs.org/eslint/-/eslint-8.36.0.tgz",
+ "integrity": "sha512-Y956lmS7vDqomxlaaQAHVmeb4tNMp2FWIvU/RnU5BD3IKMD/MJPr76xdyr68P8tV1iNMvN2mRK0yy3c+UjL+bw==",
+ "dev": true,
+ "requires": {
+ "@eslint-community/eslint-utils": "^4.2.0",
+ "@eslint-community/regexpp": "^4.4.0",
+ "@eslint/eslintrc": "^2.0.1",
+ "@eslint/js": "8.36.0",
+ "@humanwhocodes/config-array": "^0.11.8",
+ "@humanwhocodes/module-importer": "^1.0.1",
+ "@nodelib/fs.walk": "^1.2.8",
+ "ajv": "^6.10.0",
+ "chalk": "^4.0.0",
+ "cross-spawn": "^7.0.2",
+ "debug": "^4.3.2",
+ "doctrine": "^3.0.0",
+ "escape-string-regexp": "^4.0.0",
+ "eslint-scope": "^7.1.1",
+ "eslint-visitor-keys": "^3.3.0",
+ "espree": "^9.5.0",
+ "esquery": "^1.4.2",
+ "esutils": "^2.0.2",
+ "fast-deep-equal": "^3.1.3",
+ "file-entry-cache": "^6.0.1",
+ "find-up": "^5.0.0",
+ "glob-parent": "^6.0.2",
+ "globals": "^13.19.0",
+ "grapheme-splitter": "^1.0.4",
+ "ignore": "^5.2.0",
+ "import-fresh": "^3.0.0",
+ "imurmurhash": "^0.1.4",
+ "is-glob": "^4.0.0",
+ "is-path-inside": "^3.0.3",
+ "js-sdsl": "^4.1.4",
+ "js-yaml": "^4.1.0",
+ "json-stable-stringify-without-jsonify": "^1.0.1",
+ "levn": "^0.4.1",
+ "lodash.merge": "^4.6.2",
+ "minimatch": "^3.1.2",
+ "natural-compare": "^1.4.0",
+ "optionator": "^0.9.1",
+ "strip-ansi": "^6.0.1",
+ "strip-json-comments": "^3.1.0",
+ "text-table": "^0.2.0"
+ },
+ "dependencies": {
+ "escape-string-regexp": {
+ "version": "4.0.0",
+ "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz",
+ "integrity": "sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA==",
+ "dev": true
+ },
+ "eslint-scope": {
+ "version": "7.1.1",
+ "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-7.1.1.tgz",
+ "integrity": "sha512-QKQM/UXpIiHcLqJ5AOyIW7XZmzjkzQXYE54n1++wb0u9V/abW3l9uQnxX8Z5Xd18xyKIMTUAyQ0k1e8pz6LUrw==",
+ "dev": true,
+ "requires": {
+ "esrecurse": "^4.3.0",
+ "estraverse": "^5.2.0"
+ }
+ },
+ "find-up": {
+ "version": "5.0.0",
+ "resolved": "https://registry.npmjs.org/find-up/-/find-up-5.0.0.tgz",
+ "integrity": "sha512-78/PXT1wlLLDgTzDs7sjq9hzz0vXD+zn+7wypEe4fXQxCmdmqfGsEPQxmiCSQI3ajFV91bVSsvNtrJRiW6nGng==",
+ "dev": true,
+ "requires": {
+ "locate-path": "^6.0.0",
+ "path-exists": "^4.0.0"
+ }
+ },
+ "locate-path": {
+ "version": "6.0.0",
+ "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-6.0.0.tgz",
+ "integrity": "sha512-iPZK6eYjbxRu3uB4/WZ3EsEIMJFMqAoopl3R+zuq0UjcAm/MO6KCweDgPfP3elTztoKP3KtnVHxTn2NHBSDVUw==",
+ "dev": true,
+ "requires": {
+ "p-locate": "^5.0.0"
+ }
+ },
+ "p-locate": {
+ "version": "5.0.0",
+ "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-5.0.0.tgz",
+ "integrity": "sha512-LaNjtRWUBY++zB5nE/NwcaoMylSPk+S+ZHNB1TzdbMJMny6dynpAGt7X/tl/QYq3TIeE6nxHppbo2LGymrG5Pw==",
+ "dev": true,
+ "requires": {
+ "p-limit": "^3.0.2"
+ }
+ }
+ }
+ },
+ "eslint-config-next": {
+ "version": "13.2.4",
+ "resolved": "https://registry.npmjs.org/eslint-config-next/-/eslint-config-next-13.2.4.tgz",
+ "integrity": "sha512-lunIBhsoeqw6/Lfkd6zPt25w1bn0znLA/JCL+au1HoEpSb4/PpsOYsYtgV/q+YPsoKIOzFyU5xnb04iZnXjUvg==",
+ "dev": true,
+ "requires": {
+ "@next/eslint-plugin-next": "13.2.4",
+ "@rushstack/eslint-patch": "^1.1.3",
+ "@typescript-eslint/parser": "^5.42.0",
+ "eslint-import-resolver-node": "^0.3.6",
+ "eslint-import-resolver-typescript": "^3.5.2",
+ "eslint-plugin-import": "^2.26.0",
+ "eslint-plugin-jsx-a11y": "^6.5.1",
+ "eslint-plugin-react": "^7.31.7",
+ "eslint-plugin-react-hooks": "^4.5.0"
+ }
+ },
+ "eslint-config-prettier": {
+ "version": "8.7.0",
+ "resolved": "https://registry.npmjs.org/eslint-config-prettier/-/eslint-config-prettier-8.7.0.tgz",
+ "integrity": "sha512-HHVXLSlVUhMSmyW4ZzEuvjpwqamgmlfkutD53cYXLikh4pt/modINRcCIApJ84czDxM4GZInwUrromsDdTImTA==",
+ "dev": true,
+ "requires": {}
+ },
+ "eslint-import-resolver-node": {
+ "version": "0.3.7",
+ "resolved": "https://registry.npmjs.org/eslint-import-resolver-node/-/eslint-import-resolver-node-0.3.7.tgz",
+ "integrity": "sha512-gozW2blMLJCeFpBwugLTGyvVjNoeo1knonXAcatC6bjPBZitotxdWf7Gimr25N4c0AAOo4eOUfaG82IJPDpqCA==",
+ "dev": true,
+ "requires": {
+ "debug": "^3.2.7",
+ "is-core-module": "^2.11.0",
+ "resolve": "^1.22.1"
+ },
+ "dependencies": {
+ "debug": {
+ "version": "3.2.7",
+ "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.7.tgz",
+ "integrity": "sha512-CFjzYYAi4ThfiQvizrFQevTTXHtnCqWfe7x1AhgEscTz6ZbLbfoLRLPugTQyBth6f8ZERVUSyWHFD/7Wu4t1XQ==",
+ "dev": true,
+ "requires": {
+ "ms": "^2.1.1"
+ }
+ },
+ "resolve": {
+ "version": "1.22.1",
+ "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.22.1.tgz",
+ "integrity": "sha512-nBpuuYuY5jFsli/JIs1oldw6fOQCBioohqWZg/2hiaOybXOft4lonv85uDOKXdf8rhyK159cxU5cDcK/NKk8zw==",
+ "dev": true,
+ "requires": {
+ "is-core-module": "^2.9.0",
+ "path-parse": "^1.0.7",
+ "supports-preserve-symlinks-flag": "^1.0.0"
+ }
+ }
+ }
+ },
+ "eslint-import-resolver-typescript": {
+ "version": "3.5.3",
+ "resolved": "https://registry.npmjs.org/eslint-import-resolver-typescript/-/eslint-import-resolver-typescript-3.5.3.tgz",
+ "integrity": "sha512-njRcKYBc3isE42LaTcJNVANR3R99H9bAxBDMNDr2W7yq5gYPxbU3MkdhsQukxZ/Xg9C2vcyLlDsbKfRDg0QvCQ==",
+ "dev": true,
+ "requires": {
+ "debug": "^4.3.4",
+ "enhanced-resolve": "^5.10.0",
+ "get-tsconfig": "^4.2.0",
+ "globby": "^13.1.2",
+ "is-core-module": "^2.10.0",
+ "is-glob": "^4.0.3",
+ "synckit": "^0.8.4"
+ },
+ "dependencies": {
+ "globby": {
+ "version": "13.1.3",
+ "resolved": "https://registry.npmjs.org/globby/-/globby-13.1.3.tgz",
+ "integrity": "sha512-8krCNHXvlCgHDpegPzleMq07yMYTO2sXKASmZmquEYWEmCx6J5UTRbp5RwMJkTJGtcQ44YpiUYUiN0b9mzy8Bw==",
+ "dev": true,
+ "requires": {
+ "dir-glob": "^3.0.1",
+ "fast-glob": "^3.2.11",
+ "ignore": "^5.2.0",
+ "merge2": "^1.4.1",
+ "slash": "^4.0.0"
+ }
+ },
+ "slash": {
+ "version": "4.0.0",
+ "resolved": "https://registry.npmjs.org/slash/-/slash-4.0.0.tgz",
+ "integrity": "sha512-3dOsAHXXUkQTpOYcoAxLIorMTp4gIQr5IW3iVb7A7lFIp0VHhnynm9izx6TssdrIcVIESAlVjtnO2K8bg+Coew==",
+ "dev": true
+ }
+ }
+ },
+ "eslint-module-utils": {
+ "version": "2.7.4",
+ "resolved": "https://registry.npmjs.org/eslint-module-utils/-/eslint-module-utils-2.7.4.tgz",
+ "integrity": "sha512-j4GT+rqzCoRKHwURX7pddtIPGySnX9Si/cgMI5ztrcqOPtk5dDEeZ34CQVPphnqkJytlc97Vuk05Um2mJ3gEQA==",
+ "dev": true,
+ "requires": {
+ "debug": "^3.2.7"
+ },
+ "dependencies": {
+ "debug": {
+ "version": "3.2.7",
+ "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.7.tgz",
+ "integrity": "sha512-CFjzYYAi4ThfiQvizrFQevTTXHtnCqWfe7x1AhgEscTz6ZbLbfoLRLPugTQyBth6f8ZERVUSyWHFD/7Wu4t1XQ==",
+ "dev": true,
+ "requires": {
+ "ms": "^2.1.1"
+ }
+ }
+ }
+ },
+ "eslint-plugin-import": {
+ "version": "2.27.5",
+ "resolved": "https://registry.npmjs.org/eslint-plugin-import/-/eslint-plugin-import-2.27.5.tgz",
+ "integrity": "sha512-LmEt3GVofgiGuiE+ORpnvP+kAm3h6MLZJ4Q5HCyHADofsb4VzXFsRiWj3c0OFiV+3DWFh0qg3v9gcPlfc3zRow==",
+ "dev": true,
+ "requires": {
+ "array-includes": "^3.1.6",
+ "array.prototype.flat": "^1.3.1",
+ "array.prototype.flatmap": "^1.3.1",
+ "debug": "^3.2.7",
+ "doctrine": "^2.1.0",
+ "eslint-import-resolver-node": "^0.3.7",
+ "eslint-module-utils": "^2.7.4",
+ "has": "^1.0.3",
+ "is-core-module": "^2.11.0",
+ "is-glob": "^4.0.3",
+ "minimatch": "^3.1.2",
+ "object.values": "^1.1.6",
+ "resolve": "^1.22.1",
+ "semver": "^6.3.0",
+ "tsconfig-paths": "^3.14.1"
+ },
+ "dependencies": {
+ "debug": {
+ "version": "3.2.7",
+ "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.7.tgz",
+ "integrity": "sha512-CFjzYYAi4ThfiQvizrFQevTTXHtnCqWfe7x1AhgEscTz6ZbLbfoLRLPugTQyBth6f8ZERVUSyWHFD/7Wu4t1XQ==",
+ "dev": true,
+ "requires": {
+ "ms": "^2.1.1"
+ }
+ },
+ "doctrine": {
+ "version": "2.1.0",
+ "resolved": "https://registry.npmjs.org/doctrine/-/doctrine-2.1.0.tgz",
+ "integrity": "sha512-35mSku4ZXK0vfCuHEDAwt55dg2jNajHZ1odvF+8SSr82EsZY4QmXfuWso8oEd8zRhVObSN18aM0CjSdoBX7zIw==",
+ "dev": true,
+ "requires": {
+ "esutils": "^2.0.2"
+ }
+ },
+ "resolve": {
+ "version": "1.22.1",
+ "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.22.1.tgz",
+ "integrity": "sha512-nBpuuYuY5jFsli/JIs1oldw6fOQCBioohqWZg/2hiaOybXOft4lonv85uDOKXdf8rhyK159cxU5cDcK/NKk8zw==",
+ "dev": true,
+ "requires": {
+ "is-core-module": "^2.9.0",
+ "path-parse": "^1.0.7",
+ "supports-preserve-symlinks-flag": "^1.0.0"
+ }
+ },
+ "semver": {
+ "version": "6.3.0",
+ "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz",
+ "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==",
+ "dev": true
+ }
+ }
+ },
+ "eslint-plugin-jsx-a11y": {
+ "version": "6.7.1",
+ "resolved": "https://registry.npmjs.org/eslint-plugin-jsx-a11y/-/eslint-plugin-jsx-a11y-6.7.1.tgz",
+ "integrity": "sha512-63Bog4iIethyo8smBklORknVjB0T2dwB8Mr/hIC+fBS0uyHdYYpzM/Ed+YC8VxTjlXHEWFOdmgwcDn1U2L9VCA==",
+ "dev": true,
+ "requires": {
+ "@babel/runtime": "^7.20.7",
+ "aria-query": "^5.1.3",
+ "array-includes": "^3.1.6",
+ "array.prototype.flatmap": "^1.3.1",
+ "ast-types-flow": "^0.0.7",
+ "axe-core": "^4.6.2",
+ "axobject-query": "^3.1.1",
+ "damerau-levenshtein": "^1.0.8",
+ "emoji-regex": "^9.2.2",
+ "has": "^1.0.3",
+ "jsx-ast-utils": "^3.3.3",
+ "language-tags": "=1.0.5",
+ "minimatch": "^3.1.2",
+ "object.entries": "^1.1.6",
+ "object.fromentries": "^2.0.6",
+ "semver": "^6.3.0"
+ },
+ "dependencies": {
+ "semver": {
+ "version": "6.3.0",
+ "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz",
+ "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==",
+ "dev": true
+ }
+ }
+ },
+ "eslint-plugin-prettier": {
+ "version": "4.2.1",
+ "resolved": "https://registry.npmjs.org/eslint-plugin-prettier/-/eslint-plugin-prettier-4.2.1.tgz",
+ "integrity": "sha512-f/0rXLXUt0oFYs8ra4w49wYZBG5GKZpAYsJSm6rnYL5uVDjd+zowwMwVZHnAjf4edNrKpCDYfXDgmRE/Ak7QyQ==",
+ "dev": true,
+ "requires": {
+ "prettier-linter-helpers": "^1.0.0"
+ }
+ },
+ "eslint-plugin-react": {
+ "version": "7.32.2",
+ "resolved": "https://registry.npmjs.org/eslint-plugin-react/-/eslint-plugin-react-7.32.2.tgz",
+ "integrity": "sha512-t2fBMa+XzonrrNkyVirzKlvn5RXzzPwRHtMvLAtVZrt8oxgnTQaYbU6SXTOO1mwQgp1y5+toMSKInnzGr0Knqg==",
+ "dev": true,
+ "requires": {
+ "array-includes": "^3.1.6",
+ "array.prototype.flatmap": "^1.3.1",
+ "array.prototype.tosorted": "^1.1.1",
+ "doctrine": "^2.1.0",
+ "estraverse": "^5.3.0",
+ "jsx-ast-utils": "^2.4.1 || ^3.0.0",
+ "minimatch": "^3.1.2",
+ "object.entries": "^1.1.6",
+ "object.fromentries": "^2.0.6",
+ "object.hasown": "^1.1.2",
+ "object.values": "^1.1.6",
+ "prop-types": "^15.8.1",
+ "resolve": "^2.0.0-next.4",
+ "semver": "^6.3.0",
+ "string.prototype.matchall": "^4.0.8"
+ },
+ "dependencies": {
+ "doctrine": {
+ "version": "2.1.0",
+ "resolved": "https://registry.npmjs.org/doctrine/-/doctrine-2.1.0.tgz",
+ "integrity": "sha512-35mSku4ZXK0vfCuHEDAwt55dg2jNajHZ1odvF+8SSr82EsZY4QmXfuWso8oEd8zRhVObSN18aM0CjSdoBX7zIw==",
+ "dev": true,
+ "requires": {
+ "esutils": "^2.0.2"
+ }
+ },
+ "resolve": {
+ "version": "2.0.0-next.4",
+ "resolved": "https://registry.npmjs.org/resolve/-/resolve-2.0.0-next.4.tgz",
+ "integrity": "sha512-iMDbmAWtfU+MHpxt/I5iWI7cY6YVEZUQ3MBgPQ++XD1PELuJHIl82xBmObyP2KyQmkNB2dsqF7seoQQiAn5yDQ==",
+ "dev": true,
+ "requires": {
+ "is-core-module": "^2.9.0",
+ "path-parse": "^1.0.7",
+ "supports-preserve-symlinks-flag": "^1.0.0"
+ }
+ },
+ "semver": {
+ "version": "6.3.0",
+ "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz",
+ "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==",
+ "dev": true
+ }
+ }
+ },
+ "eslint-plugin-react-hooks": {
+ "version": "4.6.0",
+ "resolved": "https://registry.npmjs.org/eslint-plugin-react-hooks/-/eslint-plugin-react-hooks-4.6.0.tgz",
+ "integrity": "sha512-oFc7Itz9Qxh2x4gNHStv3BqJq54ExXmfC+a1NjAta66IAN87Wu0R/QArgIS9qKzX3dXKPI9H5crl9QchNMY9+g==",
+ "dev": true,
+ "requires": {}
+ },
+ "eslint-scope": {
+ "version": "5.1.1",
+ "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-5.1.1.tgz",
+ "integrity": "sha512-2NxwbF/hZ0KpepYN0cNbo+FN6XoK7GaHlQhgx/hIZl6Va0bF45RQOOwhLIy8lQDbuCiadSLCBnH2CFYquit5bw==",
+ "dev": true,
+ "requires": {
+ "esrecurse": "^4.3.0",
+ "estraverse": "^4.1.1"
+ },
+ "dependencies": {
+ "estraverse": {
+ "version": "4.3.0",
+ "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-4.3.0.tgz",
+ "integrity": "sha512-39nnKffWz8xN1BU/2c79n9nB9HDzo0niYUqx6xyqUnyoAnQyyWpOTdZEeiCch8BBu515t4wp9ZmgVfVhn9EBpw==",
+ "dev": true
+ }
+ }
+ },
+ "eslint-visitor-keys": {
+ "version": "3.3.0",
+ "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-3.3.0.tgz",
+ "integrity": "sha512-mQ+suqKJVyeuwGYHAdjMFqjCyfl8+Ldnxuyp3ldiMBFKkvytrXUZWaiPCEav8qDHKty44bD+qV1IP4T+w+xXRA==",
+ "dev": true
+ },
+ "espree": {
+ "version": "9.5.0",
+ "resolved": "https://registry.npmjs.org/espree/-/espree-9.5.0.tgz",
+ "integrity": "sha512-JPbJGhKc47++oo4JkEoTe2wjy4fmMwvFpgJT9cQzmfXKp22Dr6Hf1tdCteLz1h0P3t+mGvWZ+4Uankvh8+c6zw==",
+ "dev": true,
+ "requires": {
+ "acorn": "^8.8.0",
+ "acorn-jsx": "^5.3.2",
+ "eslint-visitor-keys": "^3.3.0"
+ }
+ },
+ "esprima": {
+ "version": "4.0.1",
+ "resolved": "https://registry.npmjs.org/esprima/-/esprima-4.0.1.tgz",
+ "integrity": "sha512-eGuFFw7Upda+g4p+QHvnW0RyTX/SVeJBDM/gCtMARO0cLuT2HcEKnTPvhjV6aGeqrCB/sbNop0Kszm0jsaWU4A==",
+ "dev": true,
+ "peer": true
+ },
+ "esquery": {
+ "version": "1.5.0",
+ "resolved": "https://registry.npmjs.org/esquery/-/esquery-1.5.0.tgz",
+ "integrity": "sha512-YQLXUplAwJgCydQ78IMJywZCceoqk1oH01OERdSAJc/7U2AylwjhSCLDEtqwg811idIS/9fIU5GjG73IgjKMVg==",
+ "dev": true,
+ "requires": {
+ "estraverse": "^5.1.0"
+ }
+ },
+ "esrecurse": {
+ "version": "4.3.0",
+ "resolved": "https://registry.npmjs.org/esrecurse/-/esrecurse-4.3.0.tgz",
+ "integrity": "sha512-KmfKL3b6G+RXvP8N1vr3Tq1kL/oCFgn2NYXEtqP8/L3pKapUA4G8cFVaoF3SU323CD4XypR/ffioHmkti6/Tag==",
+ "dev": true,
+ "requires": {
+ "estraverse": "^5.2.0"
+ }
+ },
+ "estraverse": {
+ "version": "5.3.0",
+ "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-5.3.0.tgz",
+ "integrity": "sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA==",
+ "dev": true
+ },
+ "esutils": {
+ "version": "2.0.3",
+ "resolved": "https://registry.npmjs.org/esutils/-/esutils-2.0.3.tgz",
+ "integrity": "sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g==",
+ "dev": true
+ },
+ "exec-sh": {
+ "version": "0.3.6",
+ "resolved": "https://registry.npmjs.org/exec-sh/-/exec-sh-0.3.6.tgz",
+ "integrity": "sha512-nQn+hI3yp+oD0huYhKwvYI32+JFeq+XkNcD1GAo3Y/MjxsfVGmrrzrnzjWiNY6f+pUCP440fThsFh5gZrRAU/w==",
+ "dev": true,
+ "peer": true
+ },
+ "execa": {
+ "version": "4.1.0",
+ "resolved": "https://registry.npmjs.org/execa/-/execa-4.1.0.tgz",
+ "integrity": "sha512-j5W0//W7f8UxAn8hXVnwG8tLwdiUy4FJLcSupCg6maBYZDpyBvTApK7KyuI4bKj8KOh1r2YH+6ucuYtJv1bTZA==",
+ "dev": true,
+ "peer": true,
+ "requires": {
+ "cross-spawn": "^7.0.0",
+ "get-stream": "^5.0.0",
+ "human-signals": "^1.1.1",
+ "is-stream": "^2.0.0",
+ "merge-stream": "^2.0.0",
+ "npm-run-path": "^4.0.0",
+ "onetime": "^5.1.0",
+ "signal-exit": "^3.0.2",
+ "strip-final-newline": "^2.0.0"
+ }
+ },
+ "execall": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/execall/-/execall-2.0.0.tgz",
+ "integrity": "sha512-0FU2hZ5Hh6iQnarpRtQurM/aAvp3RIbfvgLHrcqJYzhXyV2KFruhuChf9NC6waAhiUR7FFtlugkI4p7f2Fqlow==",
+ "dev": true,
+ "requires": {
+ "clone-regexp": "^2.1.0"
+ }
+ },
+ "exit": {
+ "version": "0.1.2",
+ "resolved": "https://registry.npmjs.org/exit/-/exit-0.1.2.tgz",
+ "integrity": "sha1-BjJjj42HfMghB9MKD/8aF8uhzQw=",
+ "dev": true,
+ "peer": true
+ },
+ "expand-brackets": {
+ "version": "2.1.4",
+ "resolved": "https://registry.npmjs.org/expand-brackets/-/expand-brackets-2.1.4.tgz",
+ "integrity": "sha1-t3c14xXOMPa27/D4OwQVGiJEliI=",
+ "dev": true,
+ "peer": true,
+ "requires": {
+ "debug": "^2.3.3",
+ "define-property": "^0.2.5",
+ "extend-shallow": "^2.0.1",
+ "posix-character-classes": "^0.1.0",
+ "regex-not": "^1.0.0",
+ "snapdragon": "^0.8.1",
+ "to-regex": "^3.0.1"
+ },
+ "dependencies": {
+ "debug": {
+ "version": "2.6.9",
+ "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz",
+ "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==",
+ "dev": true,
+ "peer": true,
+ "requires": {
+ "ms": "2.0.0"
+ }
+ },
+ "define-property": {
+ "version": "0.2.5",
+ "resolved": "https://registry.npmjs.org/define-property/-/define-property-0.2.5.tgz",
+ "integrity": "sha1-w1se+RjsPJkPmlvFe+BKrOxcgRY=",
+ "dev": true,
+ "peer": true,
+ "requires": {
+ "is-descriptor": "^0.1.0"
+ }
+ },
+ "extend-shallow": {
+ "version": "2.0.1",
+ "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz",
+ "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=",
+ "dev": true,
+ "peer": true,
+ "requires": {
+ "is-extendable": "^0.1.0"
+ }
+ },
+ "is-accessor-descriptor": {
+ "version": "0.1.6",
+ "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-0.1.6.tgz",
+ "integrity": "sha1-qeEss66Nh2cn7u84Q/igiXtcmNY=",
+ "dev": true,
+ "peer": true,
+ "requires": {
+ "kind-of": "^3.0.2"
+ },
+ "dependencies": {
+ "kind-of": {
+ "version": "3.2.2",
+ "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz",
+ "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=",
+ "dev": true,
+ "peer": true,
+ "requires": {
+ "is-buffer": "^1.1.5"
+ }
+ }
+ }
+ },
+ "is-buffer": {
+ "version": "1.1.6",
+ "resolved": "https://registry.npmjs.org/is-buffer/-/is-buffer-1.1.6.tgz",
+ "integrity": "sha512-NcdALwpXkTm5Zvvbk7owOUSvVvBKDgKP5/ewfXEznmQFfs4ZRmanOeKBTjRVjka3QFoN6XJ+9F3USqfHqTaU5w==",
+ "dev": true,
+ "peer": true
+ },
+ "is-data-descriptor": {
+ "version": "0.1.4",
+ "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-0.1.4.tgz",
+ "integrity": "sha1-C17mSDiOLIYCgueT8YVv7D8wG1Y=",
+ "dev": true,
+ "peer": true,
+ "requires": {
+ "kind-of": "^3.0.2"
+ },
+ "dependencies": {
+ "kind-of": {
+ "version": "3.2.2",
+ "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz",
+ "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=",
+ "dev": true,
+ "peer": true,
+ "requires": {
+ "is-buffer": "^1.1.5"
+ }
+ }
+ }
+ },
+ "is-descriptor": {
+ "version": "0.1.6",
+ "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-0.1.6.tgz",
+ "integrity": "sha512-avDYr0SB3DwO9zsMov0gKCESFYqCnE4hq/4z3TdUlukEy5t9C0YRq7HLrsN52NAcqXKaepeCD0n+B0arnVG3Hg==",
+ "dev": true,
+ "peer": true,
+ "requires": {
+ "is-accessor-descriptor": "^0.1.6",
+ "is-data-descriptor": "^0.1.4",
+ "kind-of": "^5.0.0"
+ }
+ },
+ "is-extendable": {
+ "version": "0.1.1",
+ "resolved": "https://registry.npmjs.org/is-extendable/-/is-extendable-0.1.1.tgz",
+ "integrity": "sha1-YrEQ4omkcUGOPsNqYX1HLjAd/Ik=",
+ "dev": true,
+ "peer": true
+ },
+ "kind-of": {
+ "version": "5.1.0",
+ "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-5.1.0.tgz",
+ "integrity": "sha512-NGEErnH6F2vUuXDh+OlbcKW7/wOcfdRHaZ7VWtqCztfHri/++YKmP51OdWeGPuqCOba6kk2OTe5d02VmTB80Pw==",
+ "dev": true,
+ "peer": true
+ },
+ "ms": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz",
+ "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=",
+ "dev": true,
+ "peer": true
+ }
+ }
+ },
+ "expect": {
+ "version": "26.6.2",
+ "resolved": "https://registry.npmjs.org/expect/-/expect-26.6.2.tgz",
+ "integrity": "sha512-9/hlOBkQl2l/PLHJx6JjoDF6xPKcJEsUlWKb23rKE7KzeDqUZKXKNMW27KIue5JMdBV9HgmoJPcc8HtO85t9IA==",
+ "dev": true,
+ "peer": true,
+ "requires": {
+ "@jest/types": "^26.6.2",
+ "ansi-styles": "^4.0.0",
+ "jest-get-type": "^26.3.0",
+ "jest-matcher-utils": "^26.6.2",
+ "jest-message-util": "^26.6.2",
+ "jest-regex-util": "^26.0.0"
+ }
+ },
+ "extend": {
+ "version": "3.0.2",
+ "resolved": "https://registry.npmjs.org/extend/-/extend-3.0.2.tgz",
+ "integrity": "sha512-fjquC59cD7CyW6urNXK0FBufkZcoiGG80wTuPujX590cB5Ttln20E2UB4S/WARVqhXffZl2LNgS+gQdPIIim/g==",
+ "dev": true
+ },
+ "extend-shallow": {
+ "version": "3.0.2",
+ "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-3.0.2.tgz",
+ "integrity": "sha1-Jqcarwc7OfshJxcnRhMcJwQCjbg=",
+ "dev": true,
+ "peer": true,
+ "requires": {
+ "assign-symbols": "^1.0.0",
+ "is-extendable": "^1.0.1"
+ }
+ },
+ "external-editor": {
+ "version": "3.1.0",
+ "resolved": "https://registry.npmjs.org/external-editor/-/external-editor-3.1.0.tgz",
+ "integrity": "sha512-hMQ4CX1p1izmuLYyZqLMO/qGNw10wSv9QDCPfzXfyFrOaCSSoRfqE1Kf1s5an66J5JZC62NewG+mK49jOCtQew==",
+ "dev": true,
+ "requires": {
+ "chardet": "^0.7.0",
+ "iconv-lite": "^0.4.24",
+ "tmp": "^0.0.33"
+ }
+ },
+ "extglob": {
+ "version": "2.0.4",
+ "resolved": "https://registry.npmjs.org/extglob/-/extglob-2.0.4.tgz",
+ "integrity": "sha512-Nmb6QXkELsuBr24CJSkilo6UHHgbekK5UiZgfE6UHD3Eb27YC6oD+bhcT+tJ6cl8dmsgdQxnWlcry8ksBIBLpw==",
+ "dev": true,
+ "peer": true,
+ "requires": {
+ "array-unique": "^0.3.2",
+ "define-property": "^1.0.0",
+ "expand-brackets": "^2.1.4",
+ "extend-shallow": "^2.0.1",
+ "fragment-cache": "^0.2.1",
+ "regex-not": "^1.0.0",
+ "snapdragon": "^0.8.1",
+ "to-regex": "^3.0.1"
+ },
+ "dependencies": {
+ "define-property": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/define-property/-/define-property-1.0.0.tgz",
+ "integrity": "sha1-dp66rz9KY6rTr56NMEybvnm/sOY=",
+ "dev": true,
+ "peer": true,
+ "requires": {
+ "is-descriptor": "^1.0.0"
+ }
+ },
+ "extend-shallow": {
+ "version": "2.0.1",
+ "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz",
+ "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=",
+ "dev": true,
+ "peer": true,
+ "requires": {
+ "is-extendable": "^0.1.0"
+ }
+ },
+ "is-extendable": {
+ "version": "0.1.1",
+ "resolved": "https://registry.npmjs.org/is-extendable/-/is-extendable-0.1.1.tgz",
+ "integrity": "sha1-YrEQ4omkcUGOPsNqYX1HLjAd/Ik=",
+ "dev": true,
+ "peer": true
+ }
+ }
+ },
+ "extract-files": {
+ "version": "9.0.0",
+ "resolved": "https://registry.npmjs.org/extract-files/-/extract-files-9.0.0.tgz",
+ "integrity": "sha512-CvdFfHkC95B4bBBk36hcEmvdR2awOdhhVUYH6S/zrVj3477zven/fJMYg7121h4T1xHZC+tetUpubpAhxwI7hQ==",
+ "dev": true
+ },
+ "fast-deep-equal": {
+ "version": "3.1.3",
+ "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz",
+ "integrity": "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==",
+ "dev": true
+ },
+ "fast-diff": {
+ "version": "1.2.0",
+ "resolved": "https://registry.npmjs.org/fast-diff/-/fast-diff-1.2.0.tgz",
+ "integrity": "sha512-xJuoT5+L99XlZ8twedaRf6Ax2TgQVxvgZOYoPKqZufmJib0tL2tegPBOZb1pVNgIhlqDlA0eO0c3wBvQcmzx4w==",
+ "dev": true
+ },
+ "fast-glob": {
+ "version": "3.2.11",
+ "resolved": "https://registry.npmjs.org/fast-glob/-/fast-glob-3.2.11.tgz",
+ "integrity": "sha512-xrO3+1bxSo3ZVHAnqzyuewYT6aMFHRAd4Kcs92MAonjwQZLsK9d0SF1IyQ3k5PoirxTW0Oe/RqFgMQ6TcNE5Ew==",
+ "dev": true,
+ "requires": {
+ "@nodelib/fs.stat": "^2.0.2",
+ "@nodelib/fs.walk": "^1.2.3",
+ "glob-parent": "^5.1.2",
+ "merge2": "^1.3.0",
+ "micromatch": "^4.0.4"
+ },
+ "dependencies": {
+ "glob-parent": {
+ "version": "5.1.2",
+ "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz",
+ "integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==",
+ "dev": true,
+ "requires": {
+ "is-glob": "^4.0.1"
+ }
+ }
+ }
+ },
+ "fast-json-stable-stringify": {
+ "version": "2.1.0",
+ "resolved": "https://registry.npmjs.org/fast-json-stable-stringify/-/fast-json-stable-stringify-2.1.0.tgz",
+ "integrity": "sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw==",
+ "dev": true
+ },
+ "fast-levenshtein": {
+ "version": "2.0.6",
+ "resolved": "https://registry.npmjs.org/fast-levenshtein/-/fast-levenshtein-2.0.6.tgz",
+ "integrity": "sha1-PYpcZog6FqMMqGQ+hR8Zuqd5eRc=",
+ "dev": true
+ },
+ "fastest-levenshtein": {
+ "version": "1.0.12",
+ "resolved": "https://registry.npmjs.org/fastest-levenshtein/-/fastest-levenshtein-1.0.12.tgz",
+ "integrity": "sha512-On2N+BpYJ15xIC974QNVuYGMOlEVt4s0EOI3wwMqOmK1fdDY+FN/zltPV8vosq4ad4c/gJ1KHScUn/6AWIgiow==",
+ "dev": true
+ },
+ "fastq": {
+ "version": "1.13.0",
+ "resolved": "https://registry.npmjs.org/fastq/-/fastq-1.13.0.tgz",
+ "integrity": "sha512-YpkpUnK8od0o1hmeSc7UUs/eB/vIPWJYjKck2QKIzAf71Vm1AAQ3EbuZB3g2JIy+pg+ERD0vqI79KyZiB2e2Nw==",
+ "dev": true,
+ "requires": {
+ "reusify": "^1.0.4"
+ }
+ },
+ "fb-watchman": {
+ "version": "2.0.1",
+ "resolved": "https://registry.npmjs.org/fb-watchman/-/fb-watchman-2.0.1.tgz",
+ "integrity": "sha512-DkPJKQeY6kKwmuMretBhr7G6Vodr7bFwDYTXIkfG1gjvNpaxBTQV3PbXg6bR1c1UP4jPOX0jHUbbHANL9vRjVg==",
+ "dev": true,
+ "peer": true,
+ "requires": {
+ "bser": "2.1.1"
+ }
+ },
+ "figures": {
+ "version": "3.2.0",
+ "resolved": "https://registry.npmjs.org/figures/-/figures-3.2.0.tgz",
+ "integrity": "sha512-yaduQFRKLXYOGgEn6AZau90j3ggSOyiqXU0F9JZfeXYhNa+Jk4X+s45A2zg5jns87GAFa34BBm2kXw4XpNcbdg==",
+ "dev": true,
+ "requires": {
+ "escape-string-regexp": "^1.0.5"
+ }
+ },
+ "file-entry-cache": {
+ "version": "6.0.1",
+ "resolved": "https://registry.npmjs.org/file-entry-cache/-/file-entry-cache-6.0.1.tgz",
+ "integrity": "sha512-7Gps/XWymbLk2QLYK4NzpMOrYjMhdIxXuIvy2QBsLE6ljuodKvdkWs/cpyJJ3CVIVpH0Oi1Hvg1ovbMzLdFBBg==",
+ "dev": true,
+ "requires": {
+ "flat-cache": "^3.0.4"
+ }
+ },
+ "filelist": {
+ "version": "1.0.3",
+ "resolved": "https://registry.npmjs.org/filelist/-/filelist-1.0.3.tgz",
+ "integrity": "sha512-LwjCsruLWQULGYKy7TX0OPtrL9kLpojOFKc5VCTxdFTV7w5zbsgqVKfnkKG7Qgjtq50gKfO56hJv88OfcGb70Q==",
+ "dev": true,
+ "requires": {
+ "minimatch": "^5.0.1"
+ },
+ "dependencies": {
+ "brace-expansion": {
+ "version": "2.0.1",
+ "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.1.tgz",
+ "integrity": "sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==",
+ "dev": true,
+ "requires": {
+ "balanced-match": "^1.0.0"
+ }
+ },
+ "minimatch": {
+ "version": "5.0.1",
+ "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-5.0.1.tgz",
+ "integrity": "sha512-nLDxIFRyhDblz3qMuq+SoRZED4+miJ/G+tdDrjkkkRnjAsBexeGpgjLEQ0blJy7rHhR2b93rhQY4SvyWu9v03g==",
+ "dev": true,
+ "requires": {
+ "brace-expansion": "^2.0.1"
+ }
+ }
+ }
+ },
+ "fill-range": {
+ "version": "7.0.1",
+ "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.0.1.tgz",
+ "integrity": "sha512-qOo9F+dMUmC2Lcb4BbVvnKJxTPjCm+RRpe4gDuGrzkL7mEVl/djYSu2OdQ2Pa302N4oqkSg9ir6jaLWJ2USVpQ==",
+ "dev": true,
+ "requires": {
+ "to-regex-range": "^5.0.1"
+ }
+ },
+ "find-up": {
+ "version": "2.1.0",
+ "resolved": "https://registry.npmjs.org/find-up/-/find-up-2.1.0.tgz",
+ "integrity": "sha1-RdG35QbHF93UgndaK3eSCjwMV6c=",
+ "dev": true,
+ "requires": {
+ "locate-path": "^2.0.0"
+ }
+ },
+ "flat": {
+ "version": "5.0.2",
+ "resolved": "https://registry.npmjs.org/flat/-/flat-5.0.2.tgz",
+ "integrity": "sha512-b6suED+5/3rTpUBdG1gupIl8MPFCAMA0QXwmljLhvCUKcUvdE4gWky9zpuGCcXHOsz4J9wPGNWq6OKpmIzz3hQ==",
+ "dev": true
+ },
+ "flat-cache": {
+ "version": "3.0.4",
+ "resolved": "https://registry.npmjs.org/flat-cache/-/flat-cache-3.0.4.tgz",
+ "integrity": "sha512-dm9s5Pw7Jc0GvMYbshN6zchCA9RgQlzzEZX3vylR9IqFfS8XciblUXOKfW6SiuJ0e13eDYZoZV5wdrev7P3Nwg==",
+ "dev": true,
+ "requires": {
+ "flatted": "^3.1.0",
+ "rimraf": "^3.0.2"
+ }
+ },
+ "flatted": {
+ "version": "3.2.5",
+ "resolved": "https://registry.npmjs.org/flatted/-/flatted-3.2.5.tgz",
+ "integrity": "sha512-WIWGi2L3DyTUvUrwRKgGi9TwxQMUEqPOPQBVi71R96jZXJdFskXEmf54BoZaS1kknGODoIGASGEzBUYdyMCBJg==",
+ "dev": true
+ },
+ "for-each": {
+ "version": "0.3.3",
+ "resolved": "https://registry.npmjs.org/for-each/-/for-each-0.3.3.tgz",
+ "integrity": "sha512-jqYfLp7mo9vIyQf8ykW2v7A+2N4QjeCeI5+Dz9XraiO1ign81wjiH7Fb9vSOWvQfNtmSa4H2RoQTrrXivdUZmw==",
+ "dev": true,
+ "requires": {
+ "is-callable": "^1.1.3"
+ }
+ },
+ "for-in": {
+ "version": "1.0.2",
+ "resolved": "https://registry.npmjs.org/for-in/-/for-in-1.0.2.tgz",
+ "integrity": "sha1-gQaNKVqBQuwKxybG4iAMMPttXoA=",
+ "dev": true,
+ "peer": true
+ },
+ "form-data": {
+ "version": "3.0.1",
+ "resolved": "https://registry.npmjs.org/form-data/-/form-data-3.0.1.tgz",
+ "integrity": "sha512-RHkBKtLWUVwd7SqRIvCZMEvAMoGUp0XU+seQiZejj0COz3RI3hWP4sCv3gZWWLjJTd7rGwcsF5eKZGii0r/hbg==",
+ "dev": true,
+ "requires": {
+ "asynckit": "^0.4.0",
+ "combined-stream": "^1.0.8",
+ "mime-types": "^2.1.12"
+ }
+ },
+ "fragment-cache": {
+ "version": "0.2.1",
+ "resolved": "https://registry.npmjs.org/fragment-cache/-/fragment-cache-0.2.1.tgz",
+ "integrity": "sha1-QpD60n8T6Jvn8zeZxrxaCr//DRk=",
+ "dev": true,
+ "peer": true,
+ "requires": {
+ "map-cache": "^0.2.2"
+ }
+ },
+ "fs-extra": {
+ "version": "9.0.1",
+ "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-9.0.1.tgz",
+ "integrity": "sha512-h2iAoN838FqAFJY2/qVpzFXy+EBxfVE220PalAqQLDVsFOHLJrZvut5puAbCdNv6WJk+B8ihI+k0c7JK5erwqQ==",
+ "dev": true,
+ "requires": {
+ "at-least-node": "^1.0.0",
+ "graceful-fs": "^4.2.0",
+ "jsonfile": "^6.0.1",
+ "universalify": "^1.0.0"
+ }
+ },
+ "fs.realpath": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz",
+ "integrity": "sha1-FQStJSMVjKpA20onh8sBQRmU6k8=",
+ "dev": true
+ },
+ "fsevents": {
+ "version": "2.3.2",
+ "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.2.tgz",
+ "integrity": "sha512-xiqMQR4xAeHTuB9uWm+fFRcIOgKBMiOBP+eXiyT7jsgVCq1bkVygt00oASowB7EdtpOHaaPgKt812P9ab+DDKA==",
+ "dev": true,
+ "optional": true,
+ "peer": true
+ },
+ "function-bind": {
+ "version": "1.1.1",
+ "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.1.tgz",
+ "integrity": "sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A==",
+ "dev": true
+ },
+ "function.prototype.name": {
+ "version": "1.1.5",
+ "resolved": "https://registry.npmjs.org/function.prototype.name/-/function.prototype.name-1.1.5.tgz",
+ "integrity": "sha512-uN7m/BzVKQnCUF/iW8jYea67v++2u7m5UgENbHRtdDVclOUP+FMPlCNdmk0h/ysGyo2tavMJEDqJAkJdRa1vMA==",
+ "dev": true,
+ "requires": {
+ "call-bind": "^1.0.2",
+ "define-properties": "^1.1.3",
+ "es-abstract": "^1.19.0",
+ "functions-have-names": "^1.2.2"
+ }
+ },
+ "functions-have-names": {
+ "version": "1.2.3",
+ "resolved": "https://registry.npmjs.org/functions-have-names/-/functions-have-names-1.2.3.tgz",
+ "integrity": "sha512-xckBUXyTIqT97tq2x2AMb+g163b5JFysYk0x4qxNFwbfQkmNZoiRHb6sPzI9/QV33WeuvVYBUIiD4NzNIyqaRQ==",
+ "dev": true
+ },
+ "gensync": {
+ "version": "1.0.0-beta.2",
+ "resolved": "https://registry.npmjs.org/gensync/-/gensync-1.0.0-beta.2.tgz",
+ "integrity": "sha512-3hN7NaskYvMDLQY55gnW3NQ+mesEAepTqlg+VEbj7zzqEMBVNhzcGYYeqFo/TlYz6eQiFcp1HcsCZO+nGgS8zg==",
+ "dev": true
+ },
+ "get-caller-file": {
+ "version": "2.0.5",
+ "resolved": "https://registry.npmjs.org/get-caller-file/-/get-caller-file-2.0.5.tgz",
+ "integrity": "sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg==",
+ "dev": true
+ },
+ "get-intrinsic": {
+ "version": "1.2.0",
+ "resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.2.0.tgz",
+ "integrity": "sha512-L049y6nFOuom5wGyRc3/gdTLO94dySVKRACj1RmJZBQXlbTMhtNIgkWkUHq+jYmZvKf14EW1EoJnnjbmoHij0Q==",
+ "dev": true,
+ "requires": {
+ "function-bind": "^1.1.1",
+ "has": "^1.0.3",
+ "has-symbols": "^1.0.3"
+ }
+ },
+ "get-own-enumerable-property-symbols": {
+ "version": "3.0.2",
+ "resolved": "https://registry.npmjs.org/get-own-enumerable-property-symbols/-/get-own-enumerable-property-symbols-3.0.2.tgz",
+ "integrity": "sha512-I0UBV/XOz1XkIJHEUDMZAbzCThU/H8DxmSfmdGcKPnVhu2VfFqr34jr9777IyaTYvxjedWhqVIilEDsCdP5G6g==",
+ "dev": true
+ },
+ "get-package-type": {
+ "version": "0.1.0",
+ "resolved": "https://registry.npmjs.org/get-package-type/-/get-package-type-0.1.0.tgz",
+ "integrity": "sha512-pjzuKtY64GYfWizNAJ0fr9VqttZkNiK2iS430LtIHzjBEr6bX8Am2zm4sW4Ro5wjWW5cAlRL1qAMTcXbjNAO2Q==",
+ "dev": true,
+ "peer": true
+ },
+ "get-stdin": {
+ "version": "8.0.0",
+ "resolved": "https://registry.npmjs.org/get-stdin/-/get-stdin-8.0.0.tgz",
+ "integrity": "sha512-sY22aA6xchAzprjyqmSEQv4UbAAzRN0L2dQB0NlN5acTTK9Don6nhoc3eAbUnpZiCANAMfd/+40kVdKfFygohg==",
+ "dev": true
+ },
+ "get-stream": {
+ "version": "5.2.0",
+ "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-5.2.0.tgz",
+ "integrity": "sha512-nBF+F1rAZVCu/p7rjzgA+Yb4lfYXrpl7a6VmJrU8wF9I1CKvP/QwPNZHnOlwbTkY6dvtFIzFMSyQXbLoTQPRpA==",
+ "dev": true,
+ "peer": true,
+ "requires": {
+ "pump": "^3.0.0"
+ }
+ },
+ "get-symbol-description": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/get-symbol-description/-/get-symbol-description-1.0.0.tgz",
+ "integrity": "sha512-2EmdH1YvIQiZpltCNgkuiUnyukzxM/R6NDJX31Ke3BG1Nq5b0S2PhX59UKi9vZpPDQVdqn+1IcaAwnzTT5vCjw==",
+ "dev": true,
+ "requires": {
+ "call-bind": "^1.0.2",
+ "get-intrinsic": "^1.1.1"
+ }
+ },
+ "get-tsconfig": {
+ "version": "4.4.0",
+ "resolved": "https://registry.npmjs.org/get-tsconfig/-/get-tsconfig-4.4.0.tgz",
+ "integrity": "sha512-0Gdjo/9+FzsYhXCEFueo2aY1z1tpXrxWZzP7k8ul9qt1U5o8rYJwTJYmaeHdrVosYIVYkOy2iwCJ9FdpocJhPQ==",
+ "dev": true
+ },
+ "get-value": {
+ "version": "2.0.6",
+ "resolved": "https://registry.npmjs.org/get-value/-/get-value-2.0.6.tgz",
+ "integrity": "sha1-3BXKHGcjh8p2vTesCjlbogQqLCg=",
+ "dev": true,
+ "peer": true
+ },
+ "glob": {
+ "version": "7.1.7",
+ "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.7.tgz",
+ "integrity": "sha512-OvD9ENzPLbegENnYP5UUfJIirTg4+XwMWGaQfQTY0JenxNvvIKP3U3/tAQSPIu/lHxXYSZmpXlUHeqAIdKzBLQ==",
+ "dev": true,
+ "requires": {
+ "fs.realpath": "^1.0.0",
+ "inflight": "^1.0.4",
+ "inherits": "2",
+ "minimatch": "^3.0.4",
+ "once": "^1.3.0",
+ "path-is-absolute": "^1.0.0"
+ }
+ },
+ "glob-parent": {
+ "version": "6.0.2",
+ "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-6.0.2.tgz",
+ "integrity": "sha512-XxwI8EOhVQgWp6iDL+3b0r86f4d6AX6zSU55HfB4ydCEuXLXc5FcYeOu+nnGftS4TEju/11rt4KJPTMgbfmv4A==",
+ "dev": true,
+ "requires": {
+ "is-glob": "^4.0.3"
+ }
+ },
+ "global-modules": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/global-modules/-/global-modules-2.0.0.tgz",
+ "integrity": "sha512-NGbfmJBp9x8IxyJSd1P+otYK8vonoJactOogrVfFRIAEY1ukil8RSKDz2Yo7wh1oihl51l/r6W4epkeKJHqL8A==",
+ "dev": true,
+ "requires": {
+ "global-prefix": "^3.0.0"
+ }
+ },
+ "global-prefix": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/global-prefix/-/global-prefix-3.0.0.tgz",
+ "integrity": "sha512-awConJSVCHVGND6x3tmMaKcQvwXLhjdkmomy2W+Goaui8YPgYgXJZewhg3fWC+DlfqqQuWg8AwqjGTD2nAPVWg==",
+ "dev": true,
+ "requires": {
+ "ini": "^1.3.5",
+ "kind-of": "^6.0.2",
+ "which": "^1.3.1"
+ },
+ "dependencies": {
+ "which": {
+ "version": "1.3.1",
+ "resolved": "https://registry.npmjs.org/which/-/which-1.3.1.tgz",
+ "integrity": "sha512-HxJdYWq1MTIQbJ3nw0cqssHoTNU267KlrDuGZ1WYlxDStUtKUhOaJmh112/TZmHxxUfuJqPXSOm7tDyas0OSIQ==",
+ "dev": true,
+ "requires": {
+ "isexe": "^2.0.0"
+ }
+ }
+ }
+ },
+ "globals": {
+ "version": "13.20.0",
+ "resolved": "https://registry.npmjs.org/globals/-/globals-13.20.0.tgz",
+ "integrity": "sha512-Qg5QtVkCy/kv3FUSlu4ukeZDVf9ee0iXLAUYX13gbR17bnejFTzr4iS9bY7kwCf1NztRNm1t91fjOiyx4CSwPQ==",
+ "dev": true,
+ "requires": {
+ "type-fest": "^0.20.2"
+ }
+ },
+ "globalthis": {
+ "version": "1.0.3",
+ "resolved": "https://registry.npmjs.org/globalthis/-/globalthis-1.0.3.tgz",
+ "integrity": "sha512-sFdI5LyBiNTHjRd7cGPWapiHWMOXKyuBNX/cWJ3NfzrZQVa8GI/8cofCl74AOVqq9W5kNmguTIzJ/1s2gyI9wA==",
+ "dev": true,
+ "requires": {
+ "define-properties": "^1.1.3"
+ }
+ },
+ "globalyzer": {
+ "version": "0.1.0",
+ "resolved": "https://registry.npmjs.org/globalyzer/-/globalyzer-0.1.0.tgz",
+ "integrity": "sha512-40oNTM9UfG6aBmuKxk/giHn5nQ8RVz/SS4Ir6zgzOv9/qC3kKZ9v4etGTcJbEl/NyVQH7FGU7d+X1egr57Md2Q==",
+ "dev": true
+ },
+ "globby": {
+ "version": "11.0.1",
+ "resolved": "https://registry.npmjs.org/globby/-/globby-11.0.1.tgz",
+ "integrity": "sha512-iH9RmgwCmUJHi2z5o2l3eTtGBtXek1OYlHrbcxOYugyHLmAsZrPj43OtHThd62Buh/Vv6VyCBD2bdyWcGNQqoQ==",
+ "dev": true,
+ "requires": {
+ "array-union": "^2.1.0",
+ "dir-glob": "^3.0.1",
+ "fast-glob": "^3.1.1",
+ "ignore": "^5.1.4",
+ "merge2": "^1.3.0",
+ "slash": "^3.0.0"
+ }
+ },
+ "globjoin": {
+ "version": "0.1.4",
+ "resolved": "https://registry.npmjs.org/globjoin/-/globjoin-0.1.4.tgz",
+ "integrity": "sha1-L0SUrIkZ43Z8XLtpHp9GMyQoXUM=",
+ "dev": true
+ },
+ "globrex": {
+ "version": "0.1.2",
+ "resolved": "https://registry.npmjs.org/globrex/-/globrex-0.1.2.tgz",
+ "integrity": "sha512-uHJgbwAMwNFf5mLst7IWLNg14x1CkeqglJb/K3doi4dw6q2IvAAmM/Y81kevy83wP+Sst+nutFTYOGg3d1lsxg==",
+ "dev": true
+ },
+ "gonzales-pe": {
+ "version": "4.3.0",
+ "resolved": "https://registry.npmjs.org/gonzales-pe/-/gonzales-pe-4.3.0.tgz",
+ "integrity": "sha512-otgSPpUmdWJ43VXyiNgEYE4luzHCL2pz4wQ0OnDluC6Eg4Ko3Vexy/SrSynglw/eR+OhkzmqFCZa/OFa/RgAOQ==",
+ "dev": true,
+ "requires": {
+ "minimist": "^1.2.5"
+ }
+ },
+ "gopd": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/gopd/-/gopd-1.0.1.tgz",
+ "integrity": "sha512-d65bNlIadxvpb/A2abVdlqKqV563juRnZ1Wtk6s1sIR8uNsXR70xqIzVqxVf1eTqDunwT2MkczEeaezCKTZhwA==",
+ "dev": true,
+ "requires": {
+ "get-intrinsic": "^1.1.3"
+ }
+ },
+ "graceful-fs": {
+ "version": "4.2.10",
+ "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.10.tgz",
+ "integrity": "sha512-9ByhssR2fPVsNZj478qUUbKfmL0+t5BDVyjShtyZZLiK7ZDAArFFfopyOTj0M05wE2tJPisA4iTnnXl2YoPvOA==",
+ "dev": true
+ },
+ "grapheme-splitter": {
+ "version": "1.0.4",
+ "resolved": "https://registry.npmjs.org/grapheme-splitter/-/grapheme-splitter-1.0.4.tgz",
+ "integrity": "sha512-bzh50DW9kTPM00T8y4o8vQg89Di9oLJVLW/KaOGIXJWP/iqCN6WKYkbNOF04vFLJhwcpYUh9ydh/+5vpOqV4YQ==",
+ "dev": true
+ },
+ "graphql": {
+ "version": "15.8.0",
+ "resolved": "https://registry.npmjs.org/graphql/-/graphql-15.8.0.tgz",
+ "integrity": "sha512-5gghUc24tP9HRznNpV2+FIoq3xKkj5dTQqf4v0CpdPbFVwFkWoxOM+o+2OC9ZSvjEMTjfmG9QT+gcvggTwW1zw==",
+ "dev": true
+ },
+ "graphql-request": {
+ "version": "3.7.0",
+ "resolved": "https://registry.npmjs.org/graphql-request/-/graphql-request-3.7.0.tgz",
+ "integrity": "sha512-dw5PxHCgBneN2DDNqpWu8QkbbJ07oOziy8z+bK/TAXufsOLaETuVO4GkXrbs0WjhdKhBMN3BkpN/RIvUHkmNUQ==",
+ "dev": true,
+ "requires": {
+ "cross-fetch": "^3.0.6",
+ "extract-files": "^9.0.0",
+ "form-data": "^3.0.0"
+ }
+ },
+ "growly": {
+ "version": "1.3.0",
+ "resolved": "https://registry.npmjs.org/growly/-/growly-1.3.0.tgz",
+ "integrity": "sha1-8QdIy+dq+WS3yWyTxrzCivEgwIE=",
+ "dev": true,
+ "optional": true,
+ "peer": true
+ },
+ "hard-rejection": {
+ "version": "2.1.0",
+ "resolved": "https://registry.npmjs.org/hard-rejection/-/hard-rejection-2.1.0.tgz",
+ "integrity": "sha512-VIZB+ibDhx7ObhAe7OVtoEbuP4h/MuOTHJ+J8h/eBXotJYl0fBgR72xDFCKgIh22OJZIOVNxBMWuhAr10r8HdA==",
+ "dev": true
+ },
+ "has": {
+ "version": "1.0.3",
+ "resolved": "https://registry.npmjs.org/has/-/has-1.0.3.tgz",
+ "integrity": "sha512-f2dvO0VU6Oej7RkWJGrehjbzMAjFp5/VKPp5tTpWIV4JHHZK1/BxbFRtf/siA2SWTe09caDmVtYYzWEIbBS4zw==",
+ "dev": true,
+ "requires": {
+ "function-bind": "^1.1.1"
+ }
+ },
+ "has-bigints": {
+ "version": "1.0.2",
+ "resolved": "https://registry.npmjs.org/has-bigints/-/has-bigints-1.0.2.tgz",
+ "integrity": "sha512-tSvCKtBr9lkF0Ex0aQiP9N+OpV4zi2r/Nee5VkRDbaqv35RLYMzbwQfFSZZH0kR+Rd6302UJZ2p/bJCEoR3VoQ==",
+ "dev": true
+ },
+ "has-flag": {
+ "version": "4.0.0",
+ "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz",
+ "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==",
+ "dev": true
+ },
+ "has-property-descriptors": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/has-property-descriptors/-/has-property-descriptors-1.0.0.tgz",
+ "integrity": "sha512-62DVLZGoiEBDHQyqG4w9xCuZ7eJEwNmJRWw2VY84Oedb7WFcA27fiEVe8oUQx9hAUJ4ekurquucTGwsyO1XGdQ==",
+ "dev": true,
+ "requires": {
+ "get-intrinsic": "^1.1.1"
+ }
+ },
+ "has-proto": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/has-proto/-/has-proto-1.0.1.tgz",
+ "integrity": "sha512-7qE+iP+O+bgF9clE5+UoBFzE65mlBiVj3tKCrlNQ0Ogwm0BjpT/gK4SlLYDMybDh5I3TCTKnPPa0oMG7JDYrhg==",
+ "dev": true
+ },
+ "has-symbols": {
+ "version": "1.0.3",
+ "resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.0.3.tgz",
+ "integrity": "sha512-l3LCuF6MgDNwTDKkdYGEihYjt5pRPbEg46rtlmnSPlUbgmB8LOIrKJbYYFBSbnPaJexMKtiPO8hmeRjRz2Td+A==",
+ "dev": true
+ },
+ "has-tostringtag": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/has-tostringtag/-/has-tostringtag-1.0.0.tgz",
+ "integrity": "sha512-kFjcSNhnlGV1kyoGk7OXKSawH5JOb/LzUc5w9B02hOTO0dfFRjbHQKvg1d6cf3HbeUmtU9VbbV3qzZ2Teh97WQ==",
+ "dev": true,
+ "requires": {
+ "has-symbols": "^1.0.2"
+ }
+ },
+ "has-value": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/has-value/-/has-value-1.0.0.tgz",
+ "integrity": "sha1-GLKB2lhbHFxR3vJMkw7SmgvmsXc=",
+ "dev": true,
+ "peer": true,
+ "requires": {
+ "get-value": "^2.0.6",
+ "has-values": "^1.0.0",
+ "isobject": "^3.0.0"
+ }
+ },
+ "has-values": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/has-values/-/has-values-1.0.0.tgz",
+ "integrity": "sha1-lbC2P+whRmGab+V/51Yo1aOe/k8=",
+ "dev": true,
+ "peer": true,
+ "requires": {
+ "is-number": "^3.0.0",
+ "kind-of": "^4.0.0"
+ },
+ "dependencies": {
+ "is-buffer": {
+ "version": "1.1.6",
+ "resolved": "https://registry.npmjs.org/is-buffer/-/is-buffer-1.1.6.tgz",
+ "integrity": "sha512-NcdALwpXkTm5Zvvbk7owOUSvVvBKDgKP5/ewfXEznmQFfs4ZRmanOeKBTjRVjka3QFoN6XJ+9F3USqfHqTaU5w==",
+ "dev": true,
+ "peer": true
+ },
+ "is-number": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/is-number/-/is-number-3.0.0.tgz",
+ "integrity": "sha1-JP1iAaR4LPUFYcgQJ2r8fRLXEZU=",
+ "dev": true,
+ "peer": true,
+ "requires": {
+ "kind-of": "^3.0.2"
+ },
+ "dependencies": {
+ "kind-of": {
+ "version": "3.2.2",
+ "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz",
+ "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=",
+ "dev": true,
+ "peer": true,
+ "requires": {
+ "is-buffer": "^1.1.5"
+ }
+ }
+ }
+ },
+ "kind-of": {
+ "version": "4.0.0",
+ "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-4.0.0.tgz",
+ "integrity": "sha1-IIE989cSkosgc3hpGkUGb65y3Vc=",
+ "dev": true,
+ "peer": true,
+ "requires": {
+ "is-buffer": "^1.1.5"
+ }
+ }
+ }
+ },
+ "hosted-git-info": {
+ "version": "2.8.9",
+ "resolved": "https://registry.npmjs.org/hosted-git-info/-/hosted-git-info-2.8.9.tgz",
+ "integrity": "sha512-mxIDAb9Lsm6DoOJ7xH+5+X4y1LU/4Hi50L9C5sIswK3JzULS4bwk1FvjdBgvYR4bzT4tuUQiC15FE2f5HbLvYw==",
+ "dev": true
+ },
+ "html-encoding-sniffer": {
+ "version": "2.0.1",
+ "resolved": "https://registry.npmjs.org/html-encoding-sniffer/-/html-encoding-sniffer-2.0.1.tgz",
+ "integrity": "sha512-D5JbOMBIR/TVZkubHT+OyT2705QvogUW4IBn6nHd756OwieSF9aDYFj4dv6HHEVGYbHaLETa3WggZYWWMyy3ZQ==",
+ "dev": true,
+ "peer": true,
+ "requires": {
+ "whatwg-encoding": "^1.0.5"
+ }
+ },
+ "html-escaper": {
+ "version": "2.0.2",
+ "resolved": "https://registry.npmjs.org/html-escaper/-/html-escaper-2.0.2.tgz",
+ "integrity": "sha512-H2iMtd0I4Mt5eYiapRdIDjp+XzelXQ0tFE4JS7YFwFevXXMmOp9myNrUvCg0D6ws8iqkRPBfKHgbwig1SmlLfg==",
+ "dev": true,
+ "peer": true
+ },
+ "html-tags": {
+ "version": "3.2.0",
+ "resolved": "https://registry.npmjs.org/html-tags/-/html-tags-3.2.0.tgz",
+ "integrity": "sha512-vy7ClnArOZwCnqZgvv+ddgHgJiAFXe3Ge9ML5/mBctVJoUoYPCdxVucOywjDARn6CVoh3dRSFdPHy2sX80L0Wg==",
+ "dev": true
+ },
+ "htmlparser2": {
+ "version": "3.10.1",
+ "resolved": "https://registry.npmjs.org/htmlparser2/-/htmlparser2-3.10.1.tgz",
+ "integrity": "sha512-IgieNijUMbkDovyoKObU1DUhm1iwNYE/fuifEoEHfd1oZKZDaONBSkal7Y01shxsM49R4XaMdGez3WnF9UfiCQ==",
+ "dev": true,
+ "requires": {
+ "domelementtype": "^1.3.1",
+ "domhandler": "^2.3.0",
+ "domutils": "^1.5.1",
+ "entities": "^1.1.1",
+ "inherits": "^2.0.1",
+ "readable-stream": "^3.1.1"
+ }
+ },
+ "http-proxy-agent": {
+ "version": "4.0.1",
+ "resolved": "https://registry.npmjs.org/http-proxy-agent/-/http-proxy-agent-4.0.1.tgz",
+ "integrity": "sha512-k0zdNgqWTGA6aeIRVpvfVob4fL52dTfaehylg0Y4UvSySvOq/Y+BOyPrgpUrA7HylqvU8vIZGsRuXmspskV0Tg==",
+ "dev": true,
+ "peer": true,
+ "requires": {
+ "@tootallnate/once": "1",
+ "agent-base": "6",
+ "debug": "4"
+ }
+ },
+ "https-proxy-agent": {
+ "version": "5.0.1",
+ "resolved": "https://registry.npmjs.org/https-proxy-agent/-/https-proxy-agent-5.0.1.tgz",
+ "integrity": "sha512-dFcAjpTQFgoLMzC2VwU+C/CbS7uRL0lWmxDITmqm7C+7F0Odmj6s9l6alZc6AELXhrnggM2CeWSXHGOdX2YtwA==",
+ "dev": true,
+ "peer": true,
+ "requires": {
+ "agent-base": "6",
+ "debug": "4"
+ }
+ },
+ "human-signals": {
+ "version": "1.1.1",
+ "resolved": "https://registry.npmjs.org/human-signals/-/human-signals-1.1.1.tgz",
+ "integrity": "sha512-SEQu7vl8KjNL2eoGBLF3+wAjpsNfA9XMlXAYj/3EdaNfAlxKthD1xjEQfGOUhllCGGJVNY34bRr6lPINhNjyZw==",
+ "dev": true,
+ "peer": true
+ },
+ "husky": {
+ "version": "4.3.8",
+ "resolved": "https://registry.npmjs.org/husky/-/husky-4.3.8.tgz",
+ "integrity": "sha512-LCqqsB0PzJQ/AlCgfrfzRe3e3+NvmefAdKQhRYpxS4u6clblBoDdzzvHi8fmxKRzvMxPY/1WZWzomPZww0Anow==",
+ "dev": true,
+ "requires": {
+ "chalk": "^4.0.0",
+ "ci-info": "^2.0.0",
+ "compare-versions": "^3.6.0",
+ "cosmiconfig": "^7.0.0",
+ "find-versions": "^4.0.0",
+ "opencollective-postinstall": "^2.0.2",
+ "pkg-dir": "^5.0.0",
+ "please-upgrade-node": "^3.2.0",
+ "slash": "^3.0.0",
+ "which-pm-runs": "^1.0.0"
+ },
+ "dependencies": {
+ "find-up": {
+ "version": "5.0.0",
+ "resolved": "https://registry.npmjs.org/find-up/-/find-up-5.0.0.tgz",
+ "integrity": "sha512-78/PXT1wlLLDgTzDs7sjq9hzz0vXD+zn+7wypEe4fXQxCmdmqfGsEPQxmiCSQI3ajFV91bVSsvNtrJRiW6nGng==",
+ "dev": true,
+ "requires": {
+ "locate-path": "^6.0.0",
+ "path-exists": "^4.0.0"
+ }
+ },
+ "find-versions": {
+ "version": "4.0.0",
+ "resolved": "https://registry.npmjs.org/find-versions/-/find-versions-4.0.0.tgz",
+ "integrity": "sha512-wgpWy002tA+wgmO27buH/9KzyEOQnKsG/R0yrcjPT9BOFm0zRBVQbZ95nRGXWMywS8YR5knRbpohio0bcJABxQ==",
+ "dev": true,
+ "requires": {
+ "semver-regex": "^3.1.2"
+ }
+ },
+ "locate-path": {
+ "version": "6.0.0",
+ "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-6.0.0.tgz",
+ "integrity": "sha512-iPZK6eYjbxRu3uB4/WZ3EsEIMJFMqAoopl3R+zuq0UjcAm/MO6KCweDgPfP3elTztoKP3KtnVHxTn2NHBSDVUw==",
+ "dev": true,
+ "requires": {
+ "p-locate": "^5.0.0"
+ }
+ },
+ "p-locate": {
+ "version": "5.0.0",
+ "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-5.0.0.tgz",
+ "integrity": "sha512-LaNjtRWUBY++zB5nE/NwcaoMylSPk+S+ZHNB1TzdbMJMny6dynpAGt7X/tl/QYq3TIeE6nxHppbo2LGymrG5Pw==",
+ "dev": true,
+ "requires": {
+ "p-limit": "^3.0.2"
+ }
+ },
+ "pkg-dir": {
+ "version": "5.0.0",
+ "resolved": "https://registry.npmjs.org/pkg-dir/-/pkg-dir-5.0.0.tgz",
+ "integrity": "sha512-NPE8TDbzl/3YQYY7CSS228s3g2ollTFnc+Qi3tqmqJp9Vg2ovUpixcJEo2HJScN2Ez+kEaal6y70c0ehqJBJeA==",
+ "dev": true,
+ "requires": {
+ "find-up": "^5.0.0"
+ }
+ }
+ }
+ },
+ "iconv-lite": {
+ "version": "0.4.24",
+ "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.24.tgz",
+ "integrity": "sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA==",
+ "dev": true,
+ "requires": {
+ "safer-buffer": ">= 2.1.2 < 3"
+ }
+ },
+ "ignore": {
+ "version": "5.2.0",
+ "resolved": "https://registry.npmjs.org/ignore/-/ignore-5.2.0.tgz",
+ "integrity": "sha512-CmxgYGiEPCLhfLnpPp1MoRmifwEIOgjcHXxOBjv7mY96c+eWScsOP9c112ZyLdWHi0FxHjI+4uVhKYp/gcdRmQ==",
+ "dev": true
+ },
+ "import-fresh": {
+ "version": "3.3.0",
+ "resolved": "https://registry.npmjs.org/import-fresh/-/import-fresh-3.3.0.tgz",
+ "integrity": "sha512-veYYhQa+D1QBKznvhUHxb8faxlrwUnxseDAbAp457E0wLNio2bOSKnjYDhMj+YiAq61xrMGhQk9iXVk5FzgQMw==",
+ "dev": true,
+ "requires": {
+ "parent-module": "^1.0.0",
+ "resolve-from": "^4.0.0"
+ }
+ },
+ "import-lazy": {
+ "version": "4.0.0",
+ "resolved": "https://registry.npmjs.org/import-lazy/-/import-lazy-4.0.0.tgz",
+ "integrity": "sha512-rKtvo6a868b5Hu3heneU+L4yEQ4jYKLtjpnPeUdK7h0yzXGmyBTypknlkCvHFBqfX9YlorEiMM6Dnq/5atfHkw==",
+ "dev": true
+ },
+ "import-local": {
+ "version": "3.1.0",
+ "resolved": "https://registry.npmjs.org/import-local/-/import-local-3.1.0.tgz",
+ "integrity": "sha512-ASB07uLtnDs1o6EHjKpX34BKYDSqnFerfTOJL2HvMqF70LnxpjkzDB8J44oT9pu4AMPkQwf8jl6szgvNd2tRIg==",
+ "dev": true,
+ "peer": true,
+ "requires": {
+ "pkg-dir": "^4.2.0",
+ "resolve-cwd": "^3.0.0"
+ }
+ },
+ "imurmurhash": {
+ "version": "0.1.4",
+ "resolved": "https://registry.npmjs.org/imurmurhash/-/imurmurhash-0.1.4.tgz",
+ "integrity": "sha1-khi5srkoojixPcT7a21XbyMUU+o=",
+ "dev": true
+ },
+ "indent-string": {
+ "version": "4.0.0",
+ "resolved": "https://registry.npmjs.org/indent-string/-/indent-string-4.0.0.tgz",
+ "integrity": "sha512-EdDDZu4A2OyIK7Lr/2zG+w5jmbuk1DVBnEwREQvBzspBJkCEbRa8GxU1lghYcaGJCnRWibjDXlq779X1/y5xwg==",
+ "dev": true
+ },
+ "inflight": {
+ "version": "1.0.6",
+ "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz",
+ "integrity": "sha1-Sb1jMdfQLQwJvJEKEHW6gWW1bfk=",
+ "dev": true,
+ "requires": {
+ "once": "^1.3.0",
+ "wrappy": "1"
+ }
+ },
+ "inherits": {
+ "version": "2.0.4",
+ "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz",
+ "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==",
+ "dev": true
+ },
+ "ini": {
+ "version": "1.3.8",
+ "resolved": "https://registry.npmjs.org/ini/-/ini-1.3.8.tgz",
+ "integrity": "sha512-JV/yugV2uzW5iMRSiZAyDtQd+nxtUnjeLt0acNdw98kKLrvuRVyB80tsREOE7yvGVgalhZ6RNXCmEHkUKBKxew==",
+ "dev": true
+ },
+ "inquirer": {
+ "version": "7.3.3",
+ "resolved": "https://registry.npmjs.org/inquirer/-/inquirer-7.3.3.tgz",
+ "integrity": "sha512-JG3eIAj5V9CwcGvuOmoo6LB9kbAYT8HXffUl6memuszlwDC/qvFAJw49XJ5NROSFNPxp3iQg1GqkFhaY/CR0IA==",
+ "dev": true,
+ "requires": {
+ "ansi-escapes": "^4.2.1",
+ "chalk": "^4.1.0",
+ "cli-cursor": "^3.1.0",
+ "cli-width": "^3.0.0",
+ "external-editor": "^3.0.3",
+ "figures": "^3.0.0",
+ "lodash": "^4.17.19",
+ "mute-stream": "0.0.8",
+ "run-async": "^2.4.0",
+ "rxjs": "^6.6.0",
+ "string-width": "^4.1.0",
+ "strip-ansi": "^6.0.0",
+ "through": "^2.3.6"
+ }
+ },
+ "internal-slot": {
+ "version": "1.0.5",
+ "resolved": "https://registry.npmjs.org/internal-slot/-/internal-slot-1.0.5.tgz",
+ "integrity": "sha512-Y+R5hJrzs52QCG2laLn4udYVnxsfny9CpOhNhUvk/SSSVyF6T27FzRbF0sroPidSu3X8oEAkOn2K804mjpt6UQ==",
+ "dev": true,
+ "requires": {
+ "get-intrinsic": "^1.2.0",
+ "has": "^1.0.3",
+ "side-channel": "^1.0.4"
+ }
+ },
+ "ip-regex": {
+ "version": "4.3.0",
+ "resolved": "https://registry.npmjs.org/ip-regex/-/ip-regex-4.3.0.tgz",
+ "integrity": "sha512-B9ZWJxHHOHUhUjCPrMpLD4xEq35bUTClHM1S6CBU5ixQnkZmwipwgc96vAd7AAGM9TGHvJR+Uss+/Ak6UphK+Q==",
+ "dev": true
+ },
+ "is-accessor-descriptor": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-1.0.0.tgz",
+ "integrity": "sha512-m5hnHTkcVsPfqx3AKlyttIPb7J+XykHvJP2B9bZDjlhLIoEq4XoK64Vg7boZlVWYK6LUY94dYPEE7Lh0ZkZKcQ==",
+ "dev": true,
+ "peer": true,
+ "requires": {
+ "kind-of": "^6.0.0"
+ }
+ },
+ "is-alphabetical": {
+ "version": "1.0.4",
+ "resolved": "https://registry.npmjs.org/is-alphabetical/-/is-alphabetical-1.0.4.tgz",
+ "integrity": "sha512-DwzsA04LQ10FHTZuL0/grVDk4rFoVH1pjAToYwBrHSxcrBIGQuXrQMtD5U1b0U2XVgKZCTLLP8u2Qxqhy3l2Vg==",
+ "dev": true
+ },
+ "is-alphanumeric": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/is-alphanumeric/-/is-alphanumeric-1.0.0.tgz",
+ "integrity": "sha512-ZmRL7++ZkcMOfDuWZuMJyIVLr2keE1o/DeNWh1EmgqGhUcV+9BIVsx0BcSBOHTZqzjs4+dISzr2KAeBEWGgXeA==",
+ "dev": true
+ },
+ "is-alphanumerical": {
+ "version": "1.0.4",
+ "resolved": "https://registry.npmjs.org/is-alphanumerical/-/is-alphanumerical-1.0.4.tgz",
+ "integrity": "sha512-UzoZUr+XfVz3t3v4KyGEniVL9BDRoQtY7tOyrRybkVNjDFWyo1yhXNGrrBTQxp3ib9BLAWs7k2YKBQsFRkZG9A==",
+ "dev": true,
+ "requires": {
+ "is-alphabetical": "^1.0.0",
+ "is-decimal": "^1.0.0"
+ }
+ },
+ "is-arguments": {
+ "version": "1.1.1",
+ "resolved": "https://registry.npmjs.org/is-arguments/-/is-arguments-1.1.1.tgz",
+ "integrity": "sha512-8Q7EARjzEnKpt/PCD7e1cgUS0a6X8u5tdSiMqXhojOdoV9TsMsiO+9VLC5vAmO8N7/GmXn7yjR8qnA6bVAEzfA==",
+ "dev": true,
+ "requires": {
+ "call-bind": "^1.0.2",
+ "has-tostringtag": "^1.0.0"
+ }
+ },
+ "is-array-buffer": {
+ "version": "3.0.2",
+ "resolved": "https://registry.npmjs.org/is-array-buffer/-/is-array-buffer-3.0.2.tgz",
+ "integrity": "sha512-y+FyyR/w8vfIRq4eQcM1EYgSTnmHXPqaF+IgzgraytCFq5Xh8lllDVmAZolPJiZttZLeFSINPYMaEJ7/vWUa1w==",
+ "dev": true,
+ "requires": {
+ "call-bind": "^1.0.2",
+ "get-intrinsic": "^1.2.0",
+ "is-typed-array": "^1.1.10"
+ }
+ },
+ "is-arrayish": {
+ "version": "0.2.1",
+ "resolved": "https://registry.npmjs.org/is-arrayish/-/is-arrayish-0.2.1.tgz",
+ "integrity": "sha1-d8mYQFJ6qOyxqLppe4BkWnqSap0=",
+ "dev": true
+ },
+ "is-bigint": {
+ "version": "1.0.4",
+ "resolved": "https://registry.npmjs.org/is-bigint/-/is-bigint-1.0.4.tgz",
+ "integrity": "sha512-zB9CruMamjym81i2JZ3UMn54PKGsQzsJeo6xvN3HJJ4CAsQNB6iRutp2To77OfCNuoxspsIhzaPoO1zyCEhFOg==",
+ "dev": true,
+ "requires": {
+ "has-bigints": "^1.0.1"
+ }
+ },
+ "is-boolean-object": {
+ "version": "1.1.2",
+ "resolved": "https://registry.npmjs.org/is-boolean-object/-/is-boolean-object-1.1.2.tgz",
+ "integrity": "sha512-gDYaKHJmnj4aWxyj6YHyXVpdQawtVLHU5cb+eztPGczf6cjuTdwve5ZIEfgXqH4e57An1D1AKf8CZ3kYrQRqYA==",
+ "dev": true,
+ "requires": {
+ "call-bind": "^1.0.2",
+ "has-tostringtag": "^1.0.0"
+ }
+ },
+ "is-buffer": {
+ "version": "2.0.5",
+ "resolved": "https://registry.npmjs.org/is-buffer/-/is-buffer-2.0.5.tgz",
+ "integrity": "sha512-i2R6zNFDwgEHJyQUtJEk0XFi1i0dPFn/oqjK3/vPCcDeJvW5NQ83V8QbicfF1SupOaB0h8ntgBC2YiE7dfyctQ==",
+ "dev": true
+ },
+ "is-callable": {
+ "version": "1.2.7",
+ "resolved": "https://registry.npmjs.org/is-callable/-/is-callable-1.2.7.tgz",
+ "integrity": "sha512-1BC0BVFhS/p0qtw6enp8e+8OD0UrK0oFLztSjNzhcKA3WDuJxxAPXzPuPtKkjEY9UUoEWlX/8fgKeu2S8i9JTA==",
+ "dev": true
+ },
+ "is-ci": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/is-ci/-/is-ci-2.0.0.tgz",
+ "integrity": "sha512-YfJT7rkpQB0updsdHLGWrvhBJfcfzNNawYDNIyQXJz0IViGf75O8EBPKSdvw2rF+LGCsX4FZ8tcr3b19LcZq4w==",
+ "dev": true,
+ "requires": {
+ "ci-info": "^2.0.0"
+ }
+ },
+ "is-core-module": {
+ "version": "2.11.0",
+ "resolved": "https://registry.npmjs.org/is-core-module/-/is-core-module-2.11.0.tgz",
+ "integrity": "sha512-RRjxlvLDkD1YJwDbroBHMb+cukurkDWNyHx7D3oNB5x9rb5ogcksMC5wHCadcXoo67gVr/+3GFySh3134zi6rw==",
+ "dev": true,
+ "requires": {
+ "has": "^1.0.3"
+ }
+ },
+ "is-data-descriptor": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-1.0.0.tgz",
+ "integrity": "sha512-jbRXy1FmtAoCjQkVmIVYwuuqDFUbaOeDjmed1tOGPrsMhtJA4rD9tkgA0F1qJ3gRFRXcHYVkdeaP50Q5rE/jLQ==",
+ "dev": true,
+ "peer": true,
+ "requires": {
+ "kind-of": "^6.0.0"
+ }
+ },
+ "is-date-object": {
+ "version": "1.0.5",
+ "resolved": "https://registry.npmjs.org/is-date-object/-/is-date-object-1.0.5.tgz",
+ "integrity": "sha512-9YQaSxsAiSwcvS33MBk3wTCVnWK+HhF8VZR2jRxehM16QcVOdHqPn4VPHmRK4lSr38n9JriurInLcP90xsYNfQ==",
+ "dev": true,
+ "requires": {
+ "has-tostringtag": "^1.0.0"
+ }
+ },
+ "is-decimal": {
+ "version": "1.0.4",
+ "resolved": "https://registry.npmjs.org/is-decimal/-/is-decimal-1.0.4.tgz",
+ "integrity": "sha512-RGdriMmQQvZ2aqaQq3awNA6dCGtKpiDFcOzrTWrDAT2MiWrKQVPmxLGHl7Y2nNu6led0kEyoX0enY0qXYsv9zw==",
+ "dev": true
+ },
+ "is-descriptor": {
+ "version": "1.0.2",
+ "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-1.0.2.tgz",
+ "integrity": "sha512-2eis5WqQGV7peooDyLmNEPUrps9+SXX5c9pL3xEB+4e9HnGuDa7mB7kHxHw4CbqS9k1T2hOH3miL8n8WtiYVtg==",
+ "dev": true,
+ "peer": true,
+ "requires": {
+ "is-accessor-descriptor": "^1.0.0",
+ "is-data-descriptor": "^1.0.0",
+ "kind-of": "^6.0.2"
+ }
+ },
+ "is-docker": {
+ "version": "2.2.1",
+ "resolved": "https://registry.npmjs.org/is-docker/-/is-docker-2.2.1.tgz",
+ "integrity": "sha512-F+i2BKsFrH66iaUFc0woD8sLy8getkwTwtOBjvs56Cx4CgJDeKQeqfz8wAYiSb8JOprWhHH5p77PbmYCvvUuXQ==",
+ "dev": true
+ },
+ "is-extendable": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/is-extendable/-/is-extendable-1.0.1.tgz",
+ "integrity": "sha512-arnXMxT1hhoKo9k1LZdmlNyJdDDfy2v0fXjFlmok4+i8ul/6WlbVge9bhM74OpNPQPMGUToDtz+KXa1PneJxOA==",
+ "dev": true,
+ "peer": true,
+ "requires": {
+ "is-plain-object": "^2.0.4"
+ }
+ },
+ "is-extglob": {
+ "version": "2.1.1",
+ "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz",
+ "integrity": "sha1-qIwCU1eR8C7TfHahueqXc8gz+MI=",
+ "dev": true
+ },
+ "is-fullwidth-code-point": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz",
+ "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==",
+ "dev": true
+ },
+ "is-generator-fn": {
+ "version": "2.1.0",
+ "resolved": "https://registry.npmjs.org/is-generator-fn/-/is-generator-fn-2.1.0.tgz",
+ "integrity": "sha512-cTIB4yPYL/Grw0EaSzASzg6bBy9gqCofvWN8okThAYIxKJZC+udlRAmGbM0XLeniEJSs8uEgHPGuHSe1XsOLSQ==",
+ "dev": true,
+ "peer": true
+ },
+ "is-glob": {
+ "version": "4.0.3",
+ "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.3.tgz",
+ "integrity": "sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==",
+ "dev": true,
+ "requires": {
+ "is-extglob": "^2.1.1"
+ }
+ },
+ "is-hexadecimal": {
+ "version": "1.0.4",
+ "resolved": "https://registry.npmjs.org/is-hexadecimal/-/is-hexadecimal-1.0.4.tgz",
+ "integrity": "sha512-gyPJuv83bHMpocVYoqof5VDiZveEoGoFL8m3BXNb2VW8Xs+rz9kqO8LOQ5DH6EsuvilT1ApazU0pyl+ytbPtlw==",
+ "dev": true
+ },
+ "is-map": {
+ "version": "2.0.2",
+ "resolved": "https://registry.npmjs.org/is-map/-/is-map-2.0.2.tgz",
+ "integrity": "sha512-cOZFQQozTha1f4MxLFzlgKYPTyj26picdZTx82hbc/Xf4K/tZOOXSCkMvU4pKioRXGDLJRn0GM7Upe7kR721yg==",
+ "dev": true
+ },
+ "is-negative-zero": {
+ "version": "2.0.2",
+ "resolved": "https://registry.npmjs.org/is-negative-zero/-/is-negative-zero-2.0.2.tgz",
+ "integrity": "sha512-dqJvarLawXsFbNDeJW7zAz8ItJ9cd28YufuuFzh0G8pNHjJMnY08Dv7sYX2uF5UpQOwieAeOExEYAWWfu7ZZUA==",
+ "dev": true
+ },
+ "is-number": {
+ "version": "7.0.0",
+ "resolved": "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz",
+ "integrity": "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==",
+ "dev": true
+ },
+ "is-number-object": {
+ "version": "1.0.7",
+ "resolved": "https://registry.npmjs.org/is-number-object/-/is-number-object-1.0.7.tgz",
+ "integrity": "sha512-k1U0IRzLMo7ZlYIfzRu23Oh6MiIFasgpb9X76eqfFZAqwH44UI4KTBvBYIZ1dSL9ZzChTB9ShHfLkR4pdW5krQ==",
+ "dev": true,
+ "requires": {
+ "has-tostringtag": "^1.0.0"
+ }
+ },
+ "is-obj": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/is-obj/-/is-obj-1.0.1.tgz",
+ "integrity": "sha1-PkcprB9f3gJc19g6iW2rn09n2w8=",
+ "dev": true
+ },
+ "is-path-inside": {
+ "version": "3.0.3",
+ "resolved": "https://registry.npmjs.org/is-path-inside/-/is-path-inside-3.0.3.tgz",
+ "integrity": "sha512-Fd4gABb+ycGAmKou8eMftCupSir5lRxqf4aD/vd0cD2qc4HL07OjCeuHMr8Ro4CoMaeCKDB0/ECBOVWjTwUvPQ==",
+ "dev": true
+ },
+ "is-plain-obj": {
+ "version": "1.1.0",
+ "resolved": "https://registry.npmjs.org/is-plain-obj/-/is-plain-obj-1.1.0.tgz",
+ "integrity": "sha1-caUMhCnfync8kqOQpKA7OfzVHT4=",
+ "dev": true
+ },
+ "is-plain-object": {
+ "version": "2.0.4",
+ "resolved": "https://registry.npmjs.org/is-plain-object/-/is-plain-object-2.0.4.tgz",
+ "integrity": "sha512-h5PpgXkWitc38BBMYawTYMWJHFZJVnBquFE57xFpjB8pJFiF6gZ+bU+WyI/yqXiFR5mdLsgYNaPe8uao6Uv9Og==",
+ "dev": true,
+ "peer": true,
+ "requires": {
+ "isobject": "^3.0.1"
+ }
+ },
+ "is-potential-custom-element-name": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/is-potential-custom-element-name/-/is-potential-custom-element-name-1.0.1.tgz",
+ "integrity": "sha512-bCYeRA2rVibKZd+s2625gGnGF/t7DSqDs4dP7CrLA1m7jKWz6pps0LpYLJN8Q64HtmPKJ1hrN3nzPNKFEKOUiQ==",
+ "dev": true,
+ "peer": true
+ },
+ "is-regex": {
+ "version": "1.1.4",
+ "resolved": "https://registry.npmjs.org/is-regex/-/is-regex-1.1.4.tgz",
+ "integrity": "sha512-kvRdxDsxZjhzUX07ZnLydzS1TU/TJlTUHHY4YLL87e37oUA49DfkLqgy+VjFocowy29cKvcSiu+kIv728jTTVg==",
+ "dev": true,
+ "requires": {
+ "call-bind": "^1.0.2",
+ "has-tostringtag": "^1.0.0"
+ }
+ },
+ "is-regexp": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/is-regexp/-/is-regexp-1.0.0.tgz",
+ "integrity": "sha1-/S2INUXEa6xaYz57mgnof6LLUGk=",
+ "dev": true
+ },
+ "is-set": {
+ "version": "2.0.2",
+ "resolved": "https://registry.npmjs.org/is-set/-/is-set-2.0.2.tgz",
+ "integrity": "sha512-+2cnTEZeY5z/iXGbLhPrOAaK/Mau5k5eXq9j14CpRTftq0pAJu2MwVRSZhyZWBzx3o6X795Lz6Bpb6R0GKf37g==",
+ "dev": true
+ },
+ "is-shared-array-buffer": {
+ "version": "1.0.2",
+ "resolved": "https://registry.npmjs.org/is-shared-array-buffer/-/is-shared-array-buffer-1.0.2.tgz",
+ "integrity": "sha512-sqN2UDu1/0y6uvXyStCOzyhAjCSlHceFoMKJW8W9EU9cvic/QdsZ0kEU93HEy3IUEFZIiH/3w+AH/UQbPHNdhA==",
+ "dev": true,
+ "requires": {
+ "call-bind": "^1.0.2"
+ }
+ },
+ "is-stream": {
+ "version": "2.0.1",
+ "resolved": "https://registry.npmjs.org/is-stream/-/is-stream-2.0.1.tgz",
+ "integrity": "sha512-hFoiJiTl63nn+kstHGBtewWSKnQLpyb155KHheA1l39uvtO9nWIop1p3udqPcUd/xbF1VLMO4n7OI6p7RbngDg==",
+ "dev": true
+ },
+ "is-string": {
+ "version": "1.0.7",
+ "resolved": "https://registry.npmjs.org/is-string/-/is-string-1.0.7.tgz",
+ "integrity": "sha512-tE2UXzivje6ofPW7l23cjDOMa09gb7xlAqG6jG5ej6uPV32TlWP3NKPigtaGeHNu9fohccRYvIiZMfOOnOYUtg==",
+ "dev": true,
+ "requires": {
+ "has-tostringtag": "^1.0.0"
+ }
+ },
+ "is-symbol": {
+ "version": "1.0.4",
+ "resolved": "https://registry.npmjs.org/is-symbol/-/is-symbol-1.0.4.tgz",
+ "integrity": "sha512-C/CPBqKWnvdcxqIARxyOh4v1UUEOCHpgDa0WYgpKDFMszcrPcffg5uhwSgPCLD2WWxmq6isisz87tzT01tuGhg==",
+ "dev": true,
+ "requires": {
+ "has-symbols": "^1.0.2"
+ }
+ },
+ "is-typed-array": {
+ "version": "1.1.10",
+ "resolved": "https://registry.npmjs.org/is-typed-array/-/is-typed-array-1.1.10.tgz",
+ "integrity": "sha512-PJqgEHiWZvMpaFZ3uTc8kHPM4+4ADTlDniuQL7cU/UDA0Ql7F70yGfHph3cLNe+c9toaigv+DFzTJKhc2CtO6A==",
+ "dev": true,
+ "requires": {
+ "available-typed-arrays": "^1.0.5",
+ "call-bind": "^1.0.2",
+ "for-each": "^0.3.3",
+ "gopd": "^1.0.1",
+ "has-tostringtag": "^1.0.0"
+ }
+ },
+ "is-typedarray": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/is-typedarray/-/is-typedarray-1.0.0.tgz",
+ "integrity": "sha1-5HnICFjfDBsR3dppQPlgEfzaSpo=",
+ "dev": true
+ },
+ "is-unicode-supported": {
+ "version": "0.1.0",
+ "resolved": "https://registry.npmjs.org/is-unicode-supported/-/is-unicode-supported-0.1.0.tgz",
+ "integrity": "sha512-knxG2q4UC3u8stRGyAVJCOdxFmv5DZiRcdlIaAQXAbSfJya+OhopNotLQrstBhququ4ZpuKbDc/8S6mgXgPFPw==",
+ "dev": true
+ },
+ "is-url-superb": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/is-url-superb/-/is-url-superb-3.0.0.tgz",
+ "integrity": "sha512-3faQP+wHCGDQT1qReM5zCPx2mxoal6DzbzquFlCYJLWyy4WPTved33ea2xFbX37z4NoriEwZGIYhFtx8RUB5wQ==",
+ "dev": true,
+ "requires": {
+ "url-regex": "^5.0.0"
+ }
+ },
+ "is-weakmap": {
+ "version": "2.0.1",
+ "resolved": "https://registry.npmjs.org/is-weakmap/-/is-weakmap-2.0.1.tgz",
+ "integrity": "sha512-NSBR4kH5oVj1Uwvv970ruUkCV7O1mzgVFO4/rev2cLRda9Tm9HrL70ZPut4rOHgY0FNrUu9BCbXA2sdQ+x0chA==",
+ "dev": true
+ },
+ "is-weakref": {
+ "version": "1.0.2",
+ "resolved": "https://registry.npmjs.org/is-weakref/-/is-weakref-1.0.2.tgz",
+ "integrity": "sha512-qctsuLZmIQ0+vSSMfoVvyFe2+GSEvnmZ2ezTup1SBse9+twCCeial6EEi3Nc2KFcf6+qz2FBPnjXsk8xhKSaPQ==",
+ "dev": true,
+ "requires": {
+ "call-bind": "^1.0.2"
+ }
+ },
+ "is-weakset": {
+ "version": "2.0.2",
+ "resolved": "https://registry.npmjs.org/is-weakset/-/is-weakset-2.0.2.tgz",
+ "integrity": "sha512-t2yVvttHkQktwnNNmBQ98AhENLdPUTDTE21uPqAQ0ARwQfGeQKRVS0NNurH7bTf7RrvcVn1OOge45CnBeHCSmg==",
+ "dev": true,
+ "requires": {
+ "call-bind": "^1.0.2",
+ "get-intrinsic": "^1.1.1"
+ }
+ },
+ "is-whitespace-character": {
+ "version": "1.0.4",
+ "resolved": "https://registry.npmjs.org/is-whitespace-character/-/is-whitespace-character-1.0.4.tgz",
+ "integrity": "sha512-SDweEzfIZM0SJV0EUga669UTKlmL0Pq8Lno0QDQsPnvECB3IM2aP0gdx5TrU0A01MAPfViaZiI2V1QMZLaKK5w==",
+ "dev": true
+ },
+ "is-windows": {
+ "version": "1.0.2",
+ "resolved": "https://registry.npmjs.org/is-windows/-/is-windows-1.0.2.tgz",
+ "integrity": "sha512-eXK1UInq2bPmjyX6e3VHIzMLobc4J94i4AWn+Hpq3OU5KkrRC96OAcR3PRJ/pGu6m8TRnBHP9dkXQVsT/COVIA==",
+ "dev": true,
+ "peer": true
+ },
+ "is-word-character": {
+ "version": "1.0.4",
+ "resolved": "https://registry.npmjs.org/is-word-character/-/is-word-character-1.0.4.tgz",
+ "integrity": "sha512-5SMO8RVennx3nZrqtKwCGyyetPE9VDba5ugvKLaD4KopPG5kR4mQ7tNt/r7feL5yt5h3lpuBbIUmCOG2eSzXHA==",
+ "dev": true
+ },
+ "is-wsl": {
+ "version": "2.2.0",
+ "resolved": "https://registry.npmjs.org/is-wsl/-/is-wsl-2.2.0.tgz",
+ "integrity": "sha512-fKzAra0rGJUUBwGBgNkHZuToZcn+TtXHpeCgmkMJMMYx1sQDYaCSyjJBSCa2nH1DGm7s3n1oBnohoVTBaN7Lww==",
+ "dev": true,
+ "requires": {
+ "is-docker": "^2.0.0"
+ }
+ },
+ "isarray": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz",
+ "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=",
+ "dev": true,
+ "peer": true
+ },
+ "isexe": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz",
+ "integrity": "sha1-6PvzdNxVb/iUehDcsFctYz8s+hA=",
+ "dev": true
+ },
+ "isobject": {
+ "version": "3.0.1",
+ "resolved": "https://registry.npmjs.org/isobject/-/isobject-3.0.1.tgz",
+ "integrity": "sha1-TkMekrEalzFjaqH5yNHMvP2reN8=",
+ "dev": true,
+ "peer": true
+ },
+ "istanbul-lib-coverage": {
+ "version": "3.2.0",
+ "resolved": "https://registry.npmjs.org/istanbul-lib-coverage/-/istanbul-lib-coverage-3.2.0.tgz",
+ "integrity": "sha512-eOeJ5BHCmHYvQK7xt9GkdHuzuCGS1Y6g9Gvnx3Ym33fz/HpLRYxiS0wHNr+m/MBC8B647Xt608vCDEvhl9c6Mw==",
+ "dev": true,
+ "peer": true
+ },
+ "istanbul-lib-instrument": {
+ "version": "4.0.3",
+ "resolved": "https://registry.npmjs.org/istanbul-lib-instrument/-/istanbul-lib-instrument-4.0.3.tgz",
+ "integrity": "sha512-BXgQl9kf4WTCPCCpmFGoJkz/+uhvm7h7PFKUYxh7qarQd3ER33vHG//qaE8eN25l07YqZPpHXU9I09l/RD5aGQ==",
+ "dev": true,
+ "peer": true,
+ "requires": {
+ "@babel/core": "^7.7.5",
+ "@istanbuljs/schema": "^0.1.2",
+ "istanbul-lib-coverage": "^3.0.0",
+ "semver": "^6.3.0"
+ },
+ "dependencies": {
+ "semver": {
+ "version": "6.3.0",
+ "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz",
+ "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==",
+ "dev": true,
+ "peer": true
+ }
+ }
+ },
+ "istanbul-lib-report": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/istanbul-lib-report/-/istanbul-lib-report-3.0.0.tgz",
+ "integrity": "sha512-wcdi+uAKzfiGT2abPpKZ0hSU1rGQjUQnLvtY5MpQ7QCTahD3VODhcu4wcfY1YtkGaDD5yuydOLINXsfbus9ROw==",
+ "dev": true,
+ "peer": true,
+ "requires": {
+ "istanbul-lib-coverage": "^3.0.0",
+ "make-dir": "^3.0.0",
+ "supports-color": "^7.1.0"
+ }
+ },
+ "istanbul-lib-source-maps": {
+ "version": "4.0.1",
+ "resolved": "https://registry.npmjs.org/istanbul-lib-source-maps/-/istanbul-lib-source-maps-4.0.1.tgz",
+ "integrity": "sha512-n3s8EwkdFIJCG3BPKBYvskgXGoy88ARzvegkitk60NxRdwltLOTaH7CUiMRXvwYorl0Q712iEjcWB+fK/MrWVw==",
+ "dev": true,
+ "peer": true,
+ "requires": {
+ "debug": "^4.1.1",
+ "istanbul-lib-coverage": "^3.0.0",
+ "source-map": "^0.6.1"
+ }
+ },
+ "istanbul-reports": {
+ "version": "3.1.4",
+ "resolved": "https://registry.npmjs.org/istanbul-reports/-/istanbul-reports-3.1.4.tgz",
+ "integrity": "sha512-r1/DshN4KSE7xWEknZLLLLDn5CJybV3nw01VTkp6D5jzLuELlcbudfj/eSQFvrKsJuTVCGnePO7ho82Nw9zzfw==",
+ "dev": true,
+ "peer": true,
+ "requires": {
+ "html-escaper": "^2.0.0",
+ "istanbul-lib-report": "^3.0.0"
+ }
+ },
+ "jake": {
+ "version": "10.8.5",
+ "resolved": "https://registry.npmjs.org/jake/-/jake-10.8.5.tgz",
+ "integrity": "sha512-sVpxYeuAhWt0OTWITwT98oyV0GsXyMlXCF+3L1SuafBVUIr/uILGRB+NqwkzhgXKvoJpDIpQvqkUALgdmQsQxw==",
+ "dev": true,
+ "requires": {
+ "async": "^3.2.3",
+ "chalk": "^4.0.2",
+ "filelist": "^1.0.1",
+ "minimatch": "^3.0.4"
+ }
+ },
+ "jest": {
+ "version": "26.6.3",
+ "resolved": "https://registry.npmjs.org/jest/-/jest-26.6.3.tgz",
+ "integrity": "sha512-lGS5PXGAzR4RF7V5+XObhqz2KZIDUA1yD0DG6pBVmy10eh0ZIXQImRuzocsI/N2XZ1GrLFwTS27In2i2jlpq1Q==",
+ "dev": true,
+ "peer": true,
+ "requires": {
+ "@jest/core": "^26.6.3",
+ "import-local": "^3.0.2",
+ "jest-cli": "^26.6.3"
+ }
+ },
+ "jest-changed-files": {
+ "version": "26.6.2",
+ "resolved": "https://registry.npmjs.org/jest-changed-files/-/jest-changed-files-26.6.2.tgz",
+ "integrity": "sha512-fDS7szLcY9sCtIip8Fjry9oGf3I2ht/QT21bAHm5Dmf0mD4X3ReNUf17y+bO6fR8WgbIZTlbyG1ak/53cbRzKQ==",
+ "dev": true,
+ "peer": true,
+ "requires": {
+ "@jest/types": "^26.6.2",
+ "execa": "^4.0.0",
+ "throat": "^5.0.0"
+ }
+ },
+ "jest-cli": {
+ "version": "26.6.3",
+ "resolved": "https://registry.npmjs.org/jest-cli/-/jest-cli-26.6.3.tgz",
+ "integrity": "sha512-GF9noBSa9t08pSyl3CY4frMrqp+aQXFGFkf5hEPbh/pIUFYWMK6ZLTfbmadxJVcJrdRoChlWQsA2VkJcDFK8hg==",
+ "dev": true,
+ "peer": true,
+ "requires": {
+ "@jest/core": "^26.6.3",
+ "@jest/test-result": "^26.6.2",
+ "@jest/types": "^26.6.2",
+ "chalk": "^4.0.0",
+ "exit": "^0.1.2",
+ "graceful-fs": "^4.2.4",
+ "import-local": "^3.0.2",
+ "is-ci": "^2.0.0",
+ "jest-config": "^26.6.3",
+ "jest-util": "^26.6.2",
+ "jest-validate": "^26.6.2",
+ "prompts": "^2.0.1",
+ "yargs": "^15.4.1"
+ }
+ },
+ "jest-config": {
+ "version": "26.6.3",
+ "resolved": "https://registry.npmjs.org/jest-config/-/jest-config-26.6.3.tgz",
+ "integrity": "sha512-t5qdIj/bCj2j7NFVHb2nFB4aUdfucDn3JRKgrZnplb8nieAirAzRSHP8uDEd+qV6ygzg9Pz4YG7UTJf94LPSyg==",
+ "dev": true,
+ "peer": true,
+ "requires": {
+ "@babel/core": "^7.1.0",
+ "@jest/test-sequencer": "^26.6.3",
+ "@jest/types": "^26.6.2",
+ "babel-jest": "^26.6.3",
+ "chalk": "^4.0.0",
+ "deepmerge": "^4.2.2",
+ "glob": "^7.1.1",
+ "graceful-fs": "^4.2.4",
+ "jest-environment-jsdom": "^26.6.2",
+ "jest-environment-node": "^26.6.2",
+ "jest-get-type": "^26.3.0",
+ "jest-jasmine2": "^26.6.3",
+ "jest-regex-util": "^26.0.0",
+ "jest-resolve": "^26.6.2",
+ "jest-util": "^26.6.2",
+ "jest-validate": "^26.6.2",
+ "micromatch": "^4.0.2",
+ "pretty-format": "^26.6.2"
+ }
+ },
+ "jest-diff": {
+ "version": "26.6.2",
+ "resolved": "https://registry.npmjs.org/jest-diff/-/jest-diff-26.6.2.tgz",
+ "integrity": "sha512-6m+9Z3Gv9wN0WFVasqjCL/06+EFCMTqDEUl/b87HYK2rAPTyfz4ZIuSlPhY51PIQRWx5TaxeF1qmXKe9gfN3sA==",
+ "dev": true,
+ "peer": true,
+ "requires": {
+ "chalk": "^4.0.0",
+ "diff-sequences": "^26.6.2",
+ "jest-get-type": "^26.3.0",
+ "pretty-format": "^26.6.2"
+ }
+ },
+ "jest-docblock": {
+ "version": "26.0.0",
+ "resolved": "https://registry.npmjs.org/jest-docblock/-/jest-docblock-26.0.0.tgz",
+ "integrity": "sha512-RDZ4Iz3QbtRWycd8bUEPxQsTlYazfYn/h5R65Fc6gOfwozFhoImx+affzky/FFBuqISPTqjXomoIGJVKBWoo0w==",
+ "dev": true,
+ "peer": true,
+ "requires": {
+ "detect-newline": "^3.0.0"
+ }
+ },
+ "jest-each": {
+ "version": "26.6.2",
+ "resolved": "https://registry.npmjs.org/jest-each/-/jest-each-26.6.2.tgz",
+ "integrity": "sha512-Mer/f0KaATbjl8MCJ+0GEpNdqmnVmDYqCTJYTvoo7rqmRiDllmp2AYN+06F93nXcY3ur9ShIjS+CO/uD+BbH4A==",
+ "dev": true,
+ "peer": true,
+ "requires": {
+ "@jest/types": "^26.6.2",
+ "chalk": "^4.0.0",
+ "jest-get-type": "^26.3.0",
+ "jest-util": "^26.6.2",
+ "pretty-format": "^26.6.2"
+ }
+ },
+ "jest-environment-jsdom": {
+ "version": "26.6.2",
+ "resolved": "https://registry.npmjs.org/jest-environment-jsdom/-/jest-environment-jsdom-26.6.2.tgz",
+ "integrity": "sha512-jgPqCruTlt3Kwqg5/WVFyHIOJHsiAvhcp2qiR2QQstuG9yWox5+iHpU3ZrcBxW14T4fe5Z68jAfLRh7joCSP2Q==",
+ "dev": true,
+ "peer": true,
+ "requires": {
+ "@jest/environment": "^26.6.2",
+ "@jest/fake-timers": "^26.6.2",
+ "@jest/types": "^26.6.2",
+ "@types/node": "*",
+ "jest-mock": "^26.6.2",
+ "jest-util": "^26.6.2",
+ "jsdom": "^16.4.0"
+ }
+ },
+ "jest-environment-node": {
+ "version": "26.6.2",
+ "resolved": "https://registry.npmjs.org/jest-environment-node/-/jest-environment-node-26.6.2.tgz",
+ "integrity": "sha512-zhtMio3Exty18dy8ee8eJ9kjnRyZC1N4C1Nt/VShN1apyXc8rWGtJ9lI7vqiWcyyXS4BVSEn9lxAM2D+07/Tag==",
+ "dev": true,
+ "peer": true,
+ "requires": {
+ "@jest/environment": "^26.6.2",
+ "@jest/fake-timers": "^26.6.2",
+ "@jest/types": "^26.6.2",
+ "@types/node": "*",
+ "jest-mock": "^26.6.2",
+ "jest-util": "^26.6.2"
+ }
+ },
+ "jest-get-type": {
+ "version": "26.3.0",
+ "resolved": "https://registry.npmjs.org/jest-get-type/-/jest-get-type-26.3.0.tgz",
+ "integrity": "sha512-TpfaviN1R2pQWkIihlfEanwOXK0zcxrKEE4MlU6Tn7keoXdN6/3gK/xl0yEh8DOunn5pOVGKf8hB4R9gVh04ig==",
+ "dev": true,
+ "peer": true
+ },
+ "jest-haste-map": {
+ "version": "26.6.2",
+ "resolved": "https://registry.npmjs.org/jest-haste-map/-/jest-haste-map-26.6.2.tgz",
+ "integrity": "sha512-easWIJXIw71B2RdR8kgqpjQrbMRWQBgiBwXYEhtGUTaX+doCjBheluShdDMeR8IMfJiTqH4+zfhtg29apJf/8w==",
+ "dev": true,
+ "peer": true,
+ "requires": {
+ "@jest/types": "^26.6.2",
+ "@types/graceful-fs": "^4.1.2",
+ "@types/node": "*",
+ "anymatch": "^3.0.3",
+ "fb-watchman": "^2.0.0",
+ "fsevents": "^2.1.2",
+ "graceful-fs": "^4.2.4",
+ "jest-regex-util": "^26.0.0",
+ "jest-serializer": "^26.6.2",
+ "jest-util": "^26.6.2",
+ "jest-worker": "^26.6.2",
+ "micromatch": "^4.0.2",
+ "sane": "^4.0.3",
+ "walker": "^1.0.7"
+ }
+ },
+ "jest-jasmine2": {
+ "version": "26.6.3",
+ "resolved": "https://registry.npmjs.org/jest-jasmine2/-/jest-jasmine2-26.6.3.tgz",
+ "integrity": "sha512-kPKUrQtc8aYwBV7CqBg5pu+tmYXlvFlSFYn18ev4gPFtrRzB15N2gW/Roew3187q2w2eHuu0MU9TJz6w0/nPEg==",
+ "dev": true,
+ "peer": true,
+ "requires": {
+ "@babel/traverse": "^7.1.0",
+ "@jest/environment": "^26.6.2",
+ "@jest/source-map": "^26.6.2",
+ "@jest/test-result": "^26.6.2",
+ "@jest/types": "^26.6.2",
+ "@types/node": "*",
+ "chalk": "^4.0.0",
+ "co": "^4.6.0",
+ "expect": "^26.6.2",
+ "is-generator-fn": "^2.0.0",
+ "jest-each": "^26.6.2",
+ "jest-matcher-utils": "^26.6.2",
+ "jest-message-util": "^26.6.2",
+ "jest-runtime": "^26.6.3",
+ "jest-snapshot": "^26.6.2",
+ "jest-util": "^26.6.2",
+ "pretty-format": "^26.6.2",
+ "throat": "^5.0.0"
+ }
+ },
+ "jest-leak-detector": {
+ "version": "26.6.2",
+ "resolved": "https://registry.npmjs.org/jest-leak-detector/-/jest-leak-detector-26.6.2.tgz",
+ "integrity": "sha512-i4xlXpsVSMeKvg2cEKdfhh0H39qlJlP5Ex1yQxwF9ubahboQYMgTtz5oML35AVA3B4Eu+YsmwaiKVev9KCvLxg==",
+ "dev": true,
+ "peer": true,
+ "requires": {
+ "jest-get-type": "^26.3.0",
+ "pretty-format": "^26.6.2"
+ }
+ },
+ "jest-matcher-utils": {
+ "version": "26.6.2",
+ "resolved": "https://registry.npmjs.org/jest-matcher-utils/-/jest-matcher-utils-26.6.2.tgz",
+ "integrity": "sha512-llnc8vQgYcNqDrqRDXWwMr9i7rS5XFiCwvh6DTP7Jqa2mqpcCBBlpCbn+trkG0KNhPu/h8rzyBkriOtBstvWhw==",
+ "dev": true,
+ "peer": true,
+ "requires": {
+ "chalk": "^4.0.0",
+ "jest-diff": "^26.6.2",
+ "jest-get-type": "^26.3.0",
+ "pretty-format": "^26.6.2"
+ }
+ },
+ "jest-message-util": {
+ "version": "26.6.2",
+ "resolved": "https://registry.npmjs.org/jest-message-util/-/jest-message-util-26.6.2.tgz",
+ "integrity": "sha512-rGiLePzQ3AzwUshu2+Rn+UMFk0pHN58sOG+IaJbk5Jxuqo3NYO1U2/MIR4S1sKgsoYSXSzdtSa0TgrmtUwEbmA==",
+ "dev": true,
+ "peer": true,
+ "requires": {
+ "@babel/code-frame": "^7.0.0",
+ "@jest/types": "^26.6.2",
+ "@types/stack-utils": "^2.0.0",
+ "chalk": "^4.0.0",
+ "graceful-fs": "^4.2.4",
+ "micromatch": "^4.0.2",
+ "pretty-format": "^26.6.2",
+ "slash": "^3.0.0",
+ "stack-utils": "^2.0.2"
+ }
+ },
+ "jest-mock": {
+ "version": "26.6.2",
+ "resolved": "https://registry.npmjs.org/jest-mock/-/jest-mock-26.6.2.tgz",
+ "integrity": "sha512-YyFjePHHp1LzpzYcmgqkJ0nm0gg/lJx2aZFzFy1S6eUqNjXsOqTK10zNRff2dNfssgokjkG65OlWNcIlgd3zew==",
+ "dev": true,
+ "peer": true,
+ "requires": {
+ "@jest/types": "^26.6.2",
+ "@types/node": "*"
+ }
+ },
+ "jest-pnp-resolver": {
+ "version": "1.2.2",
+ "resolved": "https://registry.npmjs.org/jest-pnp-resolver/-/jest-pnp-resolver-1.2.2.tgz",
+ "integrity": "sha512-olV41bKSMm8BdnuMsewT4jqlZ8+3TCARAXjZGT9jcoSnrfUnRCqnMoF9XEeoWjbzObpqF9dRhHQj0Xb9QdF6/w==",
+ "dev": true,
+ "peer": true,
+ "requires": {}
+ },
+ "jest-regex-util": {
+ "version": "26.0.0",
+ "resolved": "https://registry.npmjs.org/jest-regex-util/-/jest-regex-util-26.0.0.tgz",
+ "integrity": "sha512-Gv3ZIs/nA48/Zvjrl34bf+oD76JHiGDUxNOVgUjh3j890sblXryjY4rss71fPtD/njchl6PSE2hIhvyWa1eT0A==",
+ "dev": true,
+ "peer": true
+ },
+ "jest-resolve": {
+ "version": "26.6.2",
+ "resolved": "https://registry.npmjs.org/jest-resolve/-/jest-resolve-26.6.2.tgz",
+ "integrity": "sha512-sOxsZOq25mT1wRsfHcbtkInS+Ek7Q8jCHUB0ZUTP0tc/c41QHriU/NunqMfCUWsL4H3MHpvQD4QR9kSYhS7UvQ==",
+ "dev": true,
+ "peer": true,
+ "requires": {
+ "@jest/types": "^26.6.2",
+ "chalk": "^4.0.0",
+ "graceful-fs": "^4.2.4",
+ "jest-pnp-resolver": "^1.2.2",
+ "jest-util": "^26.6.2",
+ "read-pkg-up": "^7.0.1",
+ "resolve": "^1.18.1",
+ "slash": "^3.0.0"
+ }
+ },
+ "jest-resolve-dependencies": {
+ "version": "26.6.3",
+ "resolved": "https://registry.npmjs.org/jest-resolve-dependencies/-/jest-resolve-dependencies-26.6.3.tgz",
+ "integrity": "sha512-pVwUjJkxbhe4RY8QEWzN3vns2kqyuldKpxlxJlzEYfKSvY6/bMvxoFrYYzUO1Gx28yKWN37qyV7rIoIp2h8fTg==",
+ "dev": true,
+ "peer": true,
+ "requires": {
+ "@jest/types": "^26.6.2",
+ "jest-regex-util": "^26.0.0",
+ "jest-snapshot": "^26.6.2"
+ }
+ },
+ "jest-runner": {
+ "version": "26.6.3",
+ "resolved": "https://registry.npmjs.org/jest-runner/-/jest-runner-26.6.3.tgz",
+ "integrity": "sha512-atgKpRHnaA2OvByG/HpGA4g6CSPS/1LK0jK3gATJAoptC1ojltpmVlYC3TYgdmGp+GLuhzpH30Gvs36szSL2JQ==",
+ "dev": true,
+ "peer": true,
+ "requires": {
+ "@jest/console": "^26.6.2",
+ "@jest/environment": "^26.6.2",
+ "@jest/test-result": "^26.6.2",
+ "@jest/types": "^26.6.2",
+ "@types/node": "*",
+ "chalk": "^4.0.0",
+ "emittery": "^0.7.1",
+ "exit": "^0.1.2",
+ "graceful-fs": "^4.2.4",
+ "jest-config": "^26.6.3",
+ "jest-docblock": "^26.0.0",
+ "jest-haste-map": "^26.6.2",
+ "jest-leak-detector": "^26.6.2",
+ "jest-message-util": "^26.6.2",
+ "jest-resolve": "^26.6.2",
+ "jest-runtime": "^26.6.3",
+ "jest-util": "^26.6.2",
+ "jest-worker": "^26.6.2",
+ "source-map-support": "^0.5.6",
+ "throat": "^5.0.0"
+ }
+ },
+ "jest-runtime": {
+ "version": "26.6.3",
+ "resolved": "https://registry.npmjs.org/jest-runtime/-/jest-runtime-26.6.3.tgz",
+ "integrity": "sha512-lrzyR3N8sacTAMeonbqpnSka1dHNux2uk0qqDXVkMv2c/A3wYnvQ4EXuI013Y6+gSKSCxdaczvf4HF0mVXHRdw==",
+ "dev": true,
+ "peer": true,
+ "requires": {
+ "@jest/console": "^26.6.2",
+ "@jest/environment": "^26.6.2",
+ "@jest/fake-timers": "^26.6.2",
+ "@jest/globals": "^26.6.2",
+ "@jest/source-map": "^26.6.2",
+ "@jest/test-result": "^26.6.2",
+ "@jest/transform": "^26.6.2",
+ "@jest/types": "^26.6.2",
+ "@types/yargs": "^15.0.0",
+ "chalk": "^4.0.0",
+ "cjs-module-lexer": "^0.6.0",
+ "collect-v8-coverage": "^1.0.0",
+ "exit": "^0.1.2",
+ "glob": "^7.1.3",
+ "graceful-fs": "^4.2.4",
+ "jest-config": "^26.6.3",
+ "jest-haste-map": "^26.6.2",
+ "jest-message-util": "^26.6.2",
+ "jest-mock": "^26.6.2",
+ "jest-regex-util": "^26.0.0",
+ "jest-resolve": "^26.6.2",
+ "jest-snapshot": "^26.6.2",
+ "jest-util": "^26.6.2",
+ "jest-validate": "^26.6.2",
+ "slash": "^3.0.0",
+ "strip-bom": "^4.0.0",
+ "yargs": "^15.4.1"
+ }
+ },
+ "jest-serializer": {
+ "version": "26.6.2",
+ "resolved": "https://registry.npmjs.org/jest-serializer/-/jest-serializer-26.6.2.tgz",
+ "integrity": "sha512-S5wqyz0DXnNJPd/xfIzZ5Xnp1HrJWBczg8mMfMpN78OJ5eDxXyf+Ygld9wX1DnUWbIbhM1YDY95NjR4CBXkb2g==",
+ "dev": true,
+ "peer": true,
+ "requires": {
+ "@types/node": "*",
+ "graceful-fs": "^4.2.4"
+ }
+ },
+ "jest-snapshot": {
+ "version": "26.6.2",
+ "resolved": "https://registry.npmjs.org/jest-snapshot/-/jest-snapshot-26.6.2.tgz",
+ "integrity": "sha512-OLhxz05EzUtsAmOMzuupt1lHYXCNib0ECyuZ/PZOx9TrZcC8vL0x+DUG3TL+GLX3yHG45e6YGjIm0XwDc3q3og==",
+ "dev": true,
+ "peer": true,
+ "requires": {
+ "@babel/types": "^7.0.0",
+ "@jest/types": "^26.6.2",
+ "@types/babel__traverse": "^7.0.4",
+ "@types/prettier": "^2.0.0",
+ "chalk": "^4.0.0",
+ "expect": "^26.6.2",
+ "graceful-fs": "^4.2.4",
+ "jest-diff": "^26.6.2",
+ "jest-get-type": "^26.3.0",
+ "jest-haste-map": "^26.6.2",
+ "jest-matcher-utils": "^26.6.2",
+ "jest-message-util": "^26.6.2",
+ "jest-resolve": "^26.6.2",
+ "natural-compare": "^1.4.0",
+ "pretty-format": "^26.6.2",
+ "semver": "^7.3.2"
+ }
+ },
+ "jest-util": {
+ "version": "26.6.2",
+ "resolved": "https://registry.npmjs.org/jest-util/-/jest-util-26.6.2.tgz",
+ "integrity": "sha512-MDW0fKfsn0OI7MS7Euz6h8HNDXVQ0gaM9uW6RjfDmd1DAFcaxX9OqIakHIqhbnmF08Cf2DLDG+ulq8YQQ0Lp0Q==",
+ "dev": true,
+ "requires": {
+ "@jest/types": "^26.6.2",
+ "@types/node": "*",
+ "chalk": "^4.0.0",
+ "graceful-fs": "^4.2.4",
+ "is-ci": "^2.0.0",
+ "micromatch": "^4.0.2"
+ }
+ },
+ "jest-validate": {
+ "version": "26.6.2",
+ "resolved": "https://registry.npmjs.org/jest-validate/-/jest-validate-26.6.2.tgz",
+ "integrity": "sha512-NEYZ9Aeyj0i5rQqbq+tpIOom0YS1u2MVu6+euBsvpgIme+FOfRmoC4R5p0JiAUpaFvFy24xgrpMknarR/93XjQ==",
+ "dev": true,
+ "peer": true,
+ "requires": {
+ "@jest/types": "^26.6.2",
+ "camelcase": "^6.0.0",
+ "chalk": "^4.0.0",
+ "jest-get-type": "^26.3.0",
+ "leven": "^3.1.0",
+ "pretty-format": "^26.6.2"
+ },
+ "dependencies": {
+ "camelcase": {
+ "version": "6.3.0",
+ "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-6.3.0.tgz",
+ "integrity": "sha512-Gmy6FhYlCY7uOElZUSbxo2UCDH8owEk996gkbrpsgGtrJLM3J7jGxl9Ic7Qwwj4ivOE5AWZWRMecDdF7hqGjFA==",
+ "dev": true,
+ "peer": true
+ }
+ }
+ },
+ "jest-watcher": {
+ "version": "26.6.2",
+ "resolved": "https://registry.npmjs.org/jest-watcher/-/jest-watcher-26.6.2.tgz",
+ "integrity": "sha512-WKJob0P/Em2csiVthsI68p6aGKTIcsfjH9Gsx1f0A3Italz43e3ho0geSAVsmj09RWOELP1AZ/DXyJgOgDKxXQ==",
+ "dev": true,
+ "peer": true,
+ "requires": {
+ "@jest/test-result": "^26.6.2",
+ "@jest/types": "^26.6.2",
+ "@types/node": "*",
+ "ansi-escapes": "^4.2.1",
+ "chalk": "^4.0.0",
+ "jest-util": "^26.6.2",
+ "string-length": "^4.0.1"
+ }
+ },
+ "jest-worker": {
+ "version": "26.6.2",
+ "resolved": "https://registry.npmjs.org/jest-worker/-/jest-worker-26.6.2.tgz",
+ "integrity": "sha512-KWYVV1c4i+jbMpaBC+U++4Va0cp8OisU185o73T1vo99hqi7w8tSJfUXYswwqqrjzwxa6KpRK54WhPvwf5w6PQ==",
+ "dev": true,
+ "peer": true,
+ "requires": {
+ "@types/node": "*",
+ "merge-stream": "^2.0.0",
+ "supports-color": "^7.0.0"
+ }
+ },
+ "js-sdsl": {
+ "version": "4.3.0",
+ "resolved": "https://registry.npmjs.org/js-sdsl/-/js-sdsl-4.3.0.tgz",
+ "integrity": "sha512-mifzlm2+5nZ+lEcLJMoBK0/IH/bDg8XnJfd/Wq6IP+xoCjLZsTOnV2QpxlVbX9bMnkl5PdEjNtBJ9Cj1NjifhQ==",
+ "dev": true
+ },
+ "js-tokens": {
+ "version": "4.0.0",
+ "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz",
+ "integrity": "sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==",
+ "dev": true
+ },
+ "js-yaml": {
+ "version": "4.1.0",
+ "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-4.1.0.tgz",
+ "integrity": "sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA==",
+ "dev": true,
+ "requires": {
+ "argparse": "^2.0.1"
+ }
+ },
+ "jsdom": {
+ "version": "16.7.0",
+ "resolved": "https://registry.npmjs.org/jsdom/-/jsdom-16.7.0.tgz",
+ "integrity": "sha512-u9Smc2G1USStM+s/x1ru5Sxrl6mPYCbByG1U/hUmqaVsm4tbNyS7CicOSRyuGQYZhTu0h84qkZZQ/I+dzizSVw==",
+ "dev": true,
+ "peer": true,
+ "requires": {
+ "abab": "^2.0.5",
+ "acorn": "^8.2.4",
+ "acorn-globals": "^6.0.0",
+ "cssom": "^0.4.4",
+ "cssstyle": "^2.3.0",
+ "data-urls": "^2.0.0",
+ "decimal.js": "^10.2.1",
+ "domexception": "^2.0.1",
+ "escodegen": "^2.0.0",
+ "form-data": "^3.0.0",
+ "html-encoding-sniffer": "^2.0.1",
+ "http-proxy-agent": "^4.0.1",
+ "https-proxy-agent": "^5.0.0",
+ "is-potential-custom-element-name": "^1.0.1",
+ "nwsapi": "^2.2.0",
+ "parse5": "6.0.1",
+ "saxes": "^5.0.1",
+ "symbol-tree": "^3.2.4",
+ "tough-cookie": "^4.0.0",
+ "w3c-hr-time": "^1.0.2",
+ "w3c-xmlserializer": "^2.0.0",
+ "webidl-conversions": "^6.1.0",
+ "whatwg-encoding": "^1.0.5",
+ "whatwg-mimetype": "^2.3.0",
+ "whatwg-url": "^8.5.0",
+ "ws": "^7.4.6",
+ "xml-name-validator": "^3.0.0"
+ }
+ },
+ "jsesc": {
+ "version": "2.5.2",
+ "resolved": "https://registry.npmjs.org/jsesc/-/jsesc-2.5.2.tgz",
+ "integrity": "sha512-OYu7XEzjkCQ3C5Ps3QIZsQfNpqoJyZZA99wd9aWd05NCtC5pWOkShK2mkL6HXQR6/Cy2lbNdPlZBpuQHXE63gA==",
+ "dev": true
+ },
+ "json-parse-better-errors": {
+ "version": "1.0.2",
+ "resolved": "https://registry.npmjs.org/json-parse-better-errors/-/json-parse-better-errors-1.0.2.tgz",
+ "integrity": "sha512-mrqyZKfX5EhL7hvqcV6WG1yYjnjeuYDzDhhcAAUrq8Po85NBQBJP+ZDUT75qZQ98IkUoBqdkExkukOU7Ts2wrw==",
+ "dev": true
+ },
+ "json-parse-even-better-errors": {
+ "version": "2.3.1",
+ "resolved": "https://registry.npmjs.org/json-parse-even-better-errors/-/json-parse-even-better-errors-2.3.1.tgz",
+ "integrity": "sha512-xyFwyhro/JEof6Ghe2iz2NcXoj2sloNsWr/XsERDK/oiPCfaNhl5ONfp+jQdAZRQQ0IJWNzH9zIZF7li91kh2w==",
+ "dev": true
+ },
+ "json-schema-traverse": {
+ "version": "0.4.1",
+ "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz",
+ "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==",
+ "dev": true
+ },
+ "json-stable-stringify-without-jsonify": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/json-stable-stringify-without-jsonify/-/json-stable-stringify-without-jsonify-1.0.1.tgz",
+ "integrity": "sha512-Bdboy+l7tA3OGW6FjyFHWkP5LuByj1Tk33Ljyq0axyzdk9//JSi2u3fP1QSmd1KNwq6VOKYGlAu87CisVir6Pw==",
+ "dev": true
+ },
+ "json5": {
+ "version": "2.2.3",
+ "resolved": "https://registry.npmjs.org/json5/-/json5-2.2.3.tgz",
+ "integrity": "sha512-XmOWe7eyHYH14cLdVPoyg+GOH3rYX++KpzrylJwSW98t3Nk+U8XOl8FWKOgwtzdb8lXGf6zYwDUzeHMWfxasyg==",
+ "dev": true
+ },
+ "jsonfile": {
+ "version": "6.1.0",
+ "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-6.1.0.tgz",
+ "integrity": "sha512-5dgndWOriYSm5cnYaJNhalLNDKOqFwyDB/rr1E9ZsGciGvKPs8R2xYGCacuf3z6K1YKDz182fd+fY3cn3pMqXQ==",
+ "dev": true,
+ "requires": {
+ "graceful-fs": "^4.1.6",
+ "universalify": "^2.0.0"
+ },
+ "dependencies": {
+ "universalify": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/universalify/-/universalify-2.0.0.tgz",
+ "integrity": "sha512-hAZsKq7Yy11Zu1DE0OzWjw7nnLZmJZYTDZZyEFHZdUhV8FkH5MCfoU1XMaxXovpyW5nq5scPqq0ZDP9Zyl04oQ==",
+ "dev": true
+ }
+ }
+ },
+ "jsx-ast-utils": {
+ "version": "3.3.3",
+ "resolved": "https://registry.npmjs.org/jsx-ast-utils/-/jsx-ast-utils-3.3.3.tgz",
+ "integrity": "sha512-fYQHZTZ8jSfmWZ0iyzfwiU4WDX4HpHbMCZ3gPlWYiCl3BoeOTsqKBqnTVfH2rYT7eP5c3sVbeSPHnnJOaTrWiw==",
+ "dev": true,
+ "requires": {
+ "array-includes": "^3.1.5",
+ "object.assign": "^4.1.3"
+ }
+ },
+ "kind-of": {
+ "version": "6.0.3",
+ "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-6.0.3.tgz",
+ "integrity": "sha512-dcS1ul+9tmeD95T+x28/ehLgd9mENa3LsvDTtzm3vyBEO7RPptvAD+t44WVXaUjTBRcrpFeFlC8WCruUR456hw==",
+ "dev": true
+ },
+ "kleur": {
+ "version": "3.0.3",
+ "resolved": "https://registry.npmjs.org/kleur/-/kleur-3.0.3.tgz",
+ "integrity": "sha512-eTIzlVOSUR+JxdDFepEYcBMtZ9Qqdef+rnzWdRZuMbOywu5tO2w2N7rqjoANZ5k9vywhL6Br1VRjUIgTQx4E8w==",
+ "dev": true,
+ "peer": true
+ },
+ "known-css-properties": {
+ "version": "0.20.0",
+ "resolved": "https://registry.npmjs.org/known-css-properties/-/known-css-properties-0.20.0.tgz",
+ "integrity": "sha512-URvsjaA9ypfreqJ2/ylDr5MUERhJZ+DhguoWRr2xgS5C7aGCalXo+ewL+GixgKBfhT2vuL02nbIgNGqVWgTOYw==",
+ "dev": true
+ },
+ "language-subtag-registry": {
+ "version": "0.3.22",
+ "resolved": "https://registry.npmjs.org/language-subtag-registry/-/language-subtag-registry-0.3.22.tgz",
+ "integrity": "sha512-tN0MCzyWnoz/4nHS6uxdlFWoUZT7ABptwKPQ52Ea7URk6vll88bWBVhodtnlfEuCcKWNGoc+uGbw1cwa9IKh/w==",
+ "dev": true
+ },
+ "language-tags": {
+ "version": "1.0.5",
+ "resolved": "https://registry.npmjs.org/language-tags/-/language-tags-1.0.5.tgz",
+ "integrity": "sha512-qJhlO9cGXi6hBGKoxEG/sKZDAHD5Hnu9Hs4WbOY3pCWXDhw0N8x1NenNzm2EnNLkLkk7J2SdxAkDSbb6ftT+UQ==",
+ "dev": true,
+ "requires": {
+ "language-subtag-registry": "~0.3.2"
+ }
+ },
+ "leven": {
+ "version": "3.1.0",
+ "resolved": "https://registry.npmjs.org/leven/-/leven-3.1.0.tgz",
+ "integrity": "sha512-qsda+H8jTaUaN/x5vzW2rzc+8Rw4TAQ/4KjB46IwK5VH+IlVeeeje/EoZRpiXvIqjFgK84QffqPztGI3VBLG1A==",
+ "dev": true,
+ "peer": true
+ },
+ "levn": {
+ "version": "0.4.1",
+ "resolved": "https://registry.npmjs.org/levn/-/levn-0.4.1.tgz",
+ "integrity": "sha512-+bT2uH4E5LGE7h/n3evcS/sQlJXCpIp6ym8OWJ5eV6+67Dsql/LaaT7qJBAt2rzfoa/5QBGBhxDix1dMt2kQKQ==",
+ "dev": true,
+ "requires": {
+ "prelude-ls": "^1.2.1",
+ "type-check": "~0.4.0"
+ }
+ },
+ "lines-and-columns": {
+ "version": "1.1.6",
+ "resolved": "https://registry.npmjs.org/lines-and-columns/-/lines-and-columns-1.1.6.tgz",
+ "integrity": "sha1-HADHQ7QzzQpOgHWPe2SldEDZ/wA=",
+ "dev": true
+ },
+ "lint-staged": {
+ "version": "11.1.2",
+ "resolved": "https://registry.npmjs.org/lint-staged/-/lint-staged-11.1.2.tgz",
+ "integrity": "sha512-6lYpNoA9wGqkL6Hew/4n1H6lRqF3qCsujVT0Oq5Z4hiSAM7S6NksPJ3gnr7A7R52xCtiZMcEUNNQ6d6X5Bvh9w==",
+ "dev": true,
+ "requires": {
+ "chalk": "^4.1.1",
+ "cli-truncate": "^2.1.0",
+ "commander": "^7.2.0",
+ "cosmiconfig": "^7.0.0",
+ "debug": "^4.3.1",
+ "enquirer": "^2.3.6",
+ "execa": "^5.0.0",
+ "listr2": "^3.8.2",
+ "log-symbols": "^4.1.0",
+ "micromatch": "^4.0.4",
+ "normalize-path": "^3.0.0",
+ "please-upgrade-node": "^3.2.0",
+ "string-argv": "0.3.1",
+ "stringify-object": "^3.3.0"
+ },
+ "dependencies": {
+ "chalk": {
+ "version": "4.1.2",
+ "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz",
+ "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==",
+ "dev": true,
+ "requires": {
+ "ansi-styles": "^4.1.0",
+ "supports-color": "^7.1.0"
+ }
+ },
+ "execa": {
+ "version": "5.1.1",
+ "resolved": "https://registry.npmjs.org/execa/-/execa-5.1.1.tgz",
+ "integrity": "sha512-8uSpZZocAZRBAPIEINJj3Lo9HyGitllczc27Eh5YYojjMFMn8yHMDMaUHE2Jqfq05D/wucwI4JGURyXt1vchyg==",
+ "dev": true,
+ "requires": {
+ "cross-spawn": "^7.0.3",
+ "get-stream": "^6.0.0",
+ "human-signals": "^2.1.0",
+ "is-stream": "^2.0.0",
+ "merge-stream": "^2.0.0",
+ "npm-run-path": "^4.0.1",
+ "onetime": "^5.1.2",
+ "signal-exit": "^3.0.3",
+ "strip-final-newline": "^2.0.0"
+ }
+ },
+ "get-stream": {
+ "version": "6.0.1",
+ "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-6.0.1.tgz",
+ "integrity": "sha512-ts6Wi+2j3jQjqi70w5AlN8DFnkSwC+MqmxEzdEALB2qXZYV3X/b1CTfgPLGJNMeAWxdPfU8FO1ms3NUfaHCPYg==",
+ "dev": true
+ },
+ "human-signals": {
+ "version": "2.1.0",
+ "resolved": "https://registry.npmjs.org/human-signals/-/human-signals-2.1.0.tgz",
+ "integrity": "sha512-B4FFZ6q/T2jhhksgkbEW3HBvWIfDW85snkQgawt07S7J5QXTk6BkNV+0yAeZrM5QpMAdYlocGoljn0sJ/WQkFw==",
+ "dev": true
+ }
+ }
+ },
+ "listr2": {
+ "version": "3.14.0",
+ "resolved": "https://registry.npmjs.org/listr2/-/listr2-3.14.0.tgz",
+ "integrity": "sha512-TyWI8G99GX9GjE54cJ+RrNMcIFBfwMPxc3XTFiAYGN4s10hWROGtOg7+O6u6LE3mNkyld7RSLE6nrKBvTfcs3g==",
+ "dev": true,
+ "requires": {
+ "cli-truncate": "^2.1.0",
+ "colorette": "^2.0.16",
+ "log-update": "^4.0.0",
+ "p-map": "^4.0.0",
+ "rfdc": "^1.3.0",
+ "rxjs": "^7.5.1",
+ "through": "^2.3.8",
+ "wrap-ansi": "^7.0.0"
+ },
+ "dependencies": {
+ "rxjs": {
+ "version": "7.5.5",
+ "resolved": "https://registry.npmjs.org/rxjs/-/rxjs-7.5.5.tgz",
+ "integrity": "sha512-sy+H0pQofO95VDmFLzyaw9xNJU4KTRSwQIGM6+iG3SypAtCiLDzpeG8sJrNCWn2Up9km+KhkvTdbkrdy+yzZdw==",
+ "dev": true,
+ "requires": {
+ "tslib": "^2.1.0"
+ }
+ },
+ "tslib": {
+ "version": "2.3.1",
+ "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.3.1.tgz",
+ "integrity": "sha512-77EbyPPpMz+FRFRuAFlWMtmgUWGe9UOG2Z25NqCwiIjRhOf5iKGuzSe5P2w1laq+FkRy4p+PCuVkJSGkzTEKVw==",
+ "dev": true
+ }
+ }
+ },
+ "load-json-file": {
+ "version": "4.0.0",
+ "resolved": "https://registry.npmjs.org/load-json-file/-/load-json-file-4.0.0.tgz",
+ "integrity": "sha1-L19Fq5HjMhYjT9U62rZo607AmTs=",
+ "dev": true,
+ "requires": {
+ "graceful-fs": "^4.1.2",
+ "parse-json": "^4.0.0",
+ "pify": "^3.0.0",
+ "strip-bom": "^3.0.0"
+ },
+ "dependencies": {
+ "parse-json": {
+ "version": "4.0.0",
+ "resolved": "https://registry.npmjs.org/parse-json/-/parse-json-4.0.0.tgz",
+ "integrity": "sha1-vjX1Qlvh9/bHRxhPmKeIy5lHfuA=",
+ "dev": true,
+ "requires": {
+ "error-ex": "^1.3.1",
+ "json-parse-better-errors": "^1.0.1"
+ }
+ },
+ "strip-bom": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/strip-bom/-/strip-bom-3.0.0.tgz",
+ "integrity": "sha1-IzTBjpx1n3vdVv3vfprj1YjmjtM=",
+ "dev": true
+ }
+ }
+ },
+ "locate-path": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-2.0.0.tgz",
+ "integrity": "sha1-K1aLJl7slExtnA3pw9u7ygNUzY4=",
+ "dev": true,
+ "requires": {
+ "p-locate": "^2.0.0",
+ "path-exists": "^3.0.0"
+ },
+ "dependencies": {
+ "path-exists": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-3.0.0.tgz",
+ "integrity": "sha1-zg6+ql94yxiSXqfYENe1mwEP1RU=",
+ "dev": true
+ }
+ }
+ },
+ "lodash": {
+ "version": "4.17.21",
+ "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.21.tgz",
+ "integrity": "sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==",
+ "dev": true
+ },
+ "lodash.merge": {
+ "version": "4.6.2",
+ "resolved": "https://registry.npmjs.org/lodash.merge/-/lodash.merge-4.6.2.tgz",
+ "integrity": "sha512-0KpjqXRVvrYyCsX1swR/XTK0va6VQkQM6MNo7PqW77ByjAhoARA8EfrP1N4+KlKj8YS0ZUCtRT/YUuhyYDujIQ==",
+ "dev": true
+ },
+ "lodash.truncate": {
+ "version": "4.4.2",
+ "resolved": "https://registry.npmjs.org/lodash.truncate/-/lodash.truncate-4.4.2.tgz",
+ "integrity": "sha1-WjUNoLERO4N+z//VgSy+WNbq4ZM=",
+ "dev": true
+ },
+ "log-symbols": {
+ "version": "4.1.0",
+ "resolved": "https://registry.npmjs.org/log-symbols/-/log-symbols-4.1.0.tgz",
+ "integrity": "sha512-8XPvpAA8uyhfteu8pIvQxpJZ7SYYdpUivZpGy6sFsBuKRY/7rQGavedeB8aK+Zkyq6upMFVL/9AW6vOYzfRyLg==",
+ "dev": true,
+ "requires": {
+ "chalk": "^4.1.0",
+ "is-unicode-supported": "^0.1.0"
+ }
+ },
+ "log-update": {
+ "version": "4.0.0",
+ "resolved": "https://registry.npmjs.org/log-update/-/log-update-4.0.0.tgz",
+ "integrity": "sha512-9fkkDevMefjg0mmzWFBW8YkFP91OrizzkW3diF7CpG+S2EYdy4+TVfGwz1zeF8x7hCx1ovSPTOE9Ngib74qqUg==",
+ "dev": true,
+ "requires": {
+ "ansi-escapes": "^4.3.0",
+ "cli-cursor": "^3.1.0",
+ "slice-ansi": "^4.0.0",
+ "wrap-ansi": "^6.2.0"
+ },
+ "dependencies": {
+ "slice-ansi": {
+ "version": "4.0.0",
+ "resolved": "https://registry.npmjs.org/slice-ansi/-/slice-ansi-4.0.0.tgz",
+ "integrity": "sha512-qMCMfhY040cVHT43K9BFygqYbUPFZKHOg7K73mtTWJRb8pyP3fzf4Ixd5SzdEJQ6MRUg/WBnOLxghZtKKurENQ==",
+ "dev": true,
+ "requires": {
+ "ansi-styles": "^4.0.0",
+ "astral-regex": "^2.0.0",
+ "is-fullwidth-code-point": "^3.0.0"
+ }
+ },
+ "wrap-ansi": {
+ "version": "6.2.0",
+ "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-6.2.0.tgz",
+ "integrity": "sha512-r6lPcBGxZXlIcymEu7InxDMhdW0KDxpLgoFLcguasxCaJ/SOIZwINatK9KY/tf+ZrlywOKU0UDj3ATXUBfxJXA==",
+ "dev": true,
+ "requires": {
+ "ansi-styles": "^4.0.0",
+ "string-width": "^4.1.0",
+ "strip-ansi": "^6.0.0"
+ }
+ }
+ }
+ },
+ "longest-streak": {
+ "version": "2.0.4",
+ "resolved": "https://registry.npmjs.org/longest-streak/-/longest-streak-2.0.4.tgz",
+ "integrity": "sha512-vM6rUVCVUJJt33bnmHiZEvr7wPT78ztX7rojL+LW51bHtLh6HTjx84LA5W4+oa6aKEJA7jJu5LR6vQRBpA5DVg==",
+ "dev": true
+ },
+ "loose-envify": {
+ "version": "1.4.0",
+ "resolved": "https://registry.npmjs.org/loose-envify/-/loose-envify-1.4.0.tgz",
+ "integrity": "sha512-lyuxPGr/Wfhrlem2CL/UcnUc1zcqKAImBDzukY7Y5F/yQiNdko6+fRLevlw1HgMySw7f611UIY408EtxRSoK3Q==",
+ "dev": true,
+ "requires": {
+ "js-tokens": "^3.0.0 || ^4.0.0"
+ }
+ },
+ "lru-cache": {
+ "version": "6.0.0",
+ "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz",
+ "integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==",
+ "dev": true,
+ "requires": {
+ "yallist": "^4.0.0"
+ }
+ },
+ "make-dir": {
+ "version": "3.1.0",
+ "resolved": "https://registry.npmjs.org/make-dir/-/make-dir-3.1.0.tgz",
+ "integrity": "sha512-g3FeP20LNwhALb/6Cz6Dd4F2ngze0jz7tbzrD2wAV+o9FeNHe4rL+yK2md0J/fiSf1sa1ADhXqi5+oVwOM/eGw==",
+ "dev": true,
+ "peer": true,
+ "requires": {
+ "semver": "^6.0.0"
+ },
+ "dependencies": {
+ "semver": {
+ "version": "6.3.0",
+ "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz",
+ "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==",
+ "dev": true,
+ "peer": true
+ }
+ }
+ },
+ "make-error": {
+ "version": "1.3.6",
+ "resolved": "https://registry.npmjs.org/make-error/-/make-error-1.3.6.tgz",
+ "integrity": "sha512-s8UhlNe7vPKomQhC1qFelMokr/Sc3AgNbso3n74mVPA5LTZwkB9NlXf4XPamLxJE8h0gh73rM94xvwRT2CVInw==",
+ "dev": true
+ },
+ "makeerror": {
+ "version": "1.0.12",
+ "resolved": "https://registry.npmjs.org/makeerror/-/makeerror-1.0.12.tgz",
+ "integrity": "sha512-JmqCvUhmt43madlpFzG4BQzG2Z3m6tvQDNKdClZnO3VbIudJYmxsT0FNJMeiB2+JTSlTQTSbU8QdesVmwJcmLg==",
+ "dev": true,
+ "peer": true,
+ "requires": {
+ "tmpl": "1.0.5"
+ }
+ },
+ "map-cache": {
+ "version": "0.2.2",
+ "resolved": "https://registry.npmjs.org/map-cache/-/map-cache-0.2.2.tgz",
+ "integrity": "sha1-wyq9C9ZSXZsFFkW7TyasXcmKDb8=",
+ "dev": true,
+ "peer": true
+ },
+ "map-obj": {
+ "version": "4.3.0",
+ "resolved": "https://registry.npmjs.org/map-obj/-/map-obj-4.3.0.tgz",
+ "integrity": "sha512-hdN1wVrZbb29eBGiGjJbeP8JbKjq1urkHJ/LIP/NY48MZ1QVXUsQBV1G1zvYFHn1XE06cwjBsOI2K3Ulnj1YXQ==",
+ "dev": true
+ },
+ "map-visit": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/map-visit/-/map-visit-1.0.0.tgz",
+ "integrity": "sha1-7Nyo8TFE5mDxtb1B8S80edmN+48=",
+ "dev": true,
+ "peer": true,
+ "requires": {
+ "object-visit": "^1.0.0"
+ }
+ },
+ "markdown-escapes": {
+ "version": "1.0.4",
+ "resolved": "https://registry.npmjs.org/markdown-escapes/-/markdown-escapes-1.0.4.tgz",
+ "integrity": "sha512-8z4efJYk43E0upd0NbVXwgSTQs6cT3T06etieCMEg7dRbzCbxUCK/GHlX8mhHRDcp+OLlHkPKsvqQTCvsRl2cg==",
+ "dev": true
+ },
+ "markdown-table": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/markdown-table/-/markdown-table-2.0.0.tgz",
+ "integrity": "sha512-Ezda85ToJUBhM6WGaG6veasyym+Tbs3cMAw/ZhOPqXiYsr0jgocBV3j3nx+4lk47plLlIqjwuTm/ywVI+zjJ/A==",
+ "dev": true,
+ "requires": {
+ "repeat-string": "^1.0.0"
+ }
+ },
+ "mathml-tag-names": {
+ "version": "2.1.3",
+ "resolved": "https://registry.npmjs.org/mathml-tag-names/-/mathml-tag-names-2.1.3.tgz",
+ "integrity": "sha512-APMBEanjybaPzUrfqU0IMU5I0AswKMH7k8OTLs0vvV4KZpExkTkY87nR/zpbuTPj+gARop7aGUbl11pnDfW6xg==",
+ "dev": true
+ },
+ "mdast-util-compact": {
+ "version": "2.0.1",
+ "resolved": "https://registry.npmjs.org/mdast-util-compact/-/mdast-util-compact-2.0.1.tgz",
+ "integrity": "sha512-7GlnT24gEwDrdAwEHrU4Vv5lLWrEer4KOkAiKT9nYstsTad7Oc1TwqT2zIMKRdZF7cTuaf+GA1E4Kv7jJh8mPA==",
+ "dev": true,
+ "requires": {
+ "unist-util-visit": "^2.0.0"
+ },
+ "dependencies": {
+ "unist-util-visit": {
+ "version": "2.0.3",
+ "resolved": "https://registry.npmjs.org/unist-util-visit/-/unist-util-visit-2.0.3.tgz",
+ "integrity": "sha512-iJ4/RczbJMkD0712mGktuGpm/U4By4FfDonL7N/9tATGIF4imikjOuagyMY53tnZq3NP6BcmlrHhEKAfGWjh7Q==",
+ "dev": true,
+ "requires": {
+ "@types/unist": "^2.0.0",
+ "unist-util-is": "^4.0.0",
+ "unist-util-visit-parents": "^3.0.0"
+ }
+ },
+ "unist-util-visit-parents": {
+ "version": "3.1.1",
+ "resolved": "https://registry.npmjs.org/unist-util-visit-parents/-/unist-util-visit-parents-3.1.1.tgz",
+ "integrity": "sha512-1KROIZWo6bcMrZEwiH2UrXDyalAa0uqzWCxCJj6lPOvTve2WkfgCytoDTPaMnodXh1WrXOq0haVYHj99ynJlsg==",
+ "dev": true,
+ "requires": {
+ "@types/unist": "^2.0.0",
+ "unist-util-is": "^4.0.0"
+ }
+ }
+ }
+ },
+ "mdast-util-from-markdown": {
+ "version": "0.8.5",
+ "resolved": "https://registry.npmjs.org/mdast-util-from-markdown/-/mdast-util-from-markdown-0.8.5.tgz",
+ "integrity": "sha512-2hkTXtYYnr+NubD/g6KGBS/0mFmBcifAsI0yIWRiRo0PjVs6SSOSOdtzbp6kSGnShDN6G5aWZpKQ2lWRy27mWQ==",
+ "dev": true,
+ "requires": {
+ "@types/mdast": "^3.0.0",
+ "mdast-util-to-string": "^2.0.0",
+ "micromark": "~2.11.0",
+ "parse-entities": "^2.0.0",
+ "unist-util-stringify-position": "^2.0.0"
+ }
+ },
+ "mdast-util-to-markdown": {
+ "version": "0.6.5",
+ "resolved": "https://registry.npmjs.org/mdast-util-to-markdown/-/mdast-util-to-markdown-0.6.5.tgz",
+ "integrity": "sha512-XeV9sDE7ZlOQvs45C9UKMtfTcctcaj/pGwH8YLbMHoMOXNNCn2LsqVQOqrF1+/NU8lKDAqozme9SCXWyo9oAcQ==",
+ "dev": true,
+ "requires": {
+ "@types/unist": "^2.0.0",
+ "longest-streak": "^2.0.0",
+ "mdast-util-to-string": "^2.0.0",
+ "parse-entities": "^2.0.0",
+ "repeat-string": "^1.0.0",
+ "zwitch": "^1.0.0"
+ }
+ },
+ "mdast-util-to-string": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/mdast-util-to-string/-/mdast-util-to-string-2.0.0.tgz",
+ "integrity": "sha512-AW4DRS3QbBayY/jJmD8437V1Gombjf8RSOUCMFBuo5iHi58AGEgVCKQ+ezHkZZDpAQS75hcBMpLqjpJTjtUL7w==",
+ "dev": true
+ },
+ "meow": {
+ "version": "8.1.2",
+ "resolved": "https://registry.npmjs.org/meow/-/meow-8.1.2.tgz",
+ "integrity": "sha512-r85E3NdZ+mpYk1C6RjPFEMSE+s1iZMuHtsHAqY0DT3jZczl0diWUZ8g6oU7h0M9cD2EL+PzaYghhCLzR0ZNn5Q==",
+ "dev": true,
+ "requires": {
+ "@types/minimist": "^1.2.0",
+ "camelcase-keys": "^6.2.2",
+ "decamelize-keys": "^1.1.0",
+ "hard-rejection": "^2.1.0",
+ "minimist-options": "4.1.0",
+ "normalize-package-data": "^3.0.0",
+ "read-pkg-up": "^7.0.1",
+ "redent": "^3.0.0",
+ "trim-newlines": "^3.0.0",
+ "type-fest": "^0.18.0",
+ "yargs-parser": "^20.2.3"
+ },
+ "dependencies": {
+ "hosted-git-info": {
+ "version": "4.1.0",
+ "resolved": "https://registry.npmjs.org/hosted-git-info/-/hosted-git-info-4.1.0.tgz",
+ "integrity": "sha512-kyCuEOWjJqZuDbRHzL8V93NzQhwIB71oFWSyzVo+KPZI+pnQPPxucdkrOZvkLRnrf5URsQM+IJ09Dw29cRALIA==",
+ "dev": true,
+ "requires": {
+ "lru-cache": "^6.0.0"
+ }
+ },
+ "normalize-package-data": {
+ "version": "3.0.3",
+ "resolved": "https://registry.npmjs.org/normalize-package-data/-/normalize-package-data-3.0.3.tgz",
+ "integrity": "sha512-p2W1sgqij3zMMyRC067Dg16bfzVH+w7hyegmpIvZ4JNjqtGOVAIvLmjBx3yP7YTe9vKJgkoNOPjwQGogDoMXFA==",
+ "dev": true,
+ "requires": {
+ "hosted-git-info": "^4.0.1",
+ "is-core-module": "^2.5.0",
+ "semver": "^7.3.4",
+ "validate-npm-package-license": "^3.0.1"
+ }
+ },
+ "type-fest": {
+ "version": "0.18.1",
+ "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.18.1.tgz",
+ "integrity": "sha512-OIAYXk8+ISY+qTOwkHtKqzAuxchoMiD9Udx+FSGQDuiRR+PJKJHc2NJAXlbhkGwTt/4/nKZxELY1w3ReWOL8mw==",
+ "dev": true
+ }
+ }
+ },
+ "merge-stream": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/merge-stream/-/merge-stream-2.0.0.tgz",
+ "integrity": "sha512-abv/qOcuPfk3URPfDzmZU1LKmuw8kT+0nIHvKrKgFrwifol/doWcdA4ZqsWQ8ENrFKkd67Mfpo/LovbIUsbt3w==",
+ "dev": true
+ },
+ "merge2": {
+ "version": "1.4.1",
+ "resolved": "https://registry.npmjs.org/merge2/-/merge2-1.4.1.tgz",
+ "integrity": "sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg==",
+ "dev": true
+ },
+ "micromark": {
+ "version": "2.11.4",
+ "resolved": "https://registry.npmjs.org/micromark/-/micromark-2.11.4.tgz",
+ "integrity": "sha512-+WoovN/ppKolQOFIAajxi7Lu9kInbPxFuTBVEavFcL8eAfVstoc5MocPmqBeAdBOJV00uaVjegzH4+MA0DN/uA==",
+ "dev": true,
+ "requires": {
+ "debug": "^4.0.0",
+ "parse-entities": "^2.0.0"
+ }
+ },
+ "micromatch": {
+ "version": "4.0.5",
+ "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-4.0.5.tgz",
+ "integrity": "sha512-DMy+ERcEW2q8Z2Po+WNXuw3c5YaUSFjAO5GsJqfEl7UjvtIuFKO6ZrKvcItdy98dwFI2N1tg3zNIdKaQT+aNdA==",
+ "dev": true,
+ "requires": {
+ "braces": "^3.0.2",
+ "picomatch": "^2.3.1"
+ }
+ },
+ "mime-db": {
+ "version": "1.52.0",
+ "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.52.0.tgz",
+ "integrity": "sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg==",
+ "dev": true
+ },
+ "mime-types": {
+ "version": "2.1.35",
+ "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.35.tgz",
+ "integrity": "sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw==",
+ "dev": true,
+ "requires": {
+ "mime-db": "1.52.0"
+ }
+ },
+ "mimic-fn": {
+ "version": "2.1.0",
+ "resolved": "https://registry.npmjs.org/mimic-fn/-/mimic-fn-2.1.0.tgz",
+ "integrity": "sha512-OqbOk5oEQeAZ8WXWydlu9HJjz9WVdEIvamMCcXmuqUYjTknH/sqsWvhQ3vgwKFRR1HpjvNBKQ37nbJgYzGqGcg==",
+ "dev": true
+ },
+ "min-indent": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/min-indent/-/min-indent-1.0.1.tgz",
+ "integrity": "sha512-I9jwMn07Sy/IwOj3zVkVik2JTvgpaykDZEigL6Rx6N9LbMywwUSMtxET+7lVoDLLd3O3IXwJwvuuns8UB/HeAg==",
+ "dev": true
+ },
+ "minimatch": {
+ "version": "3.1.2",
+ "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz",
+ "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==",
+ "dev": true,
+ "requires": {
+ "brace-expansion": "^1.1.7"
+ }
+ },
+ "minimist": {
+ "version": "1.2.6",
+ "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.6.tgz",
+ "integrity": "sha512-Jsjnk4bw3YJqYzbdyBiNsPWHPfO++UGG749Cxs6peCu5Xg4nrena6OVxOYxrQTqww0Jmwt+Ref8rggumkTLz9Q==",
+ "dev": true
+ },
+ "minimist-options": {
+ "version": "4.1.0",
+ "resolved": "https://registry.npmjs.org/minimist-options/-/minimist-options-4.1.0.tgz",
+ "integrity": "sha512-Q4r8ghd80yhO/0j1O3B2BjweX3fiHg9cdOwjJd2J76Q135c+NDxGCqdYKQ1SKBuFfgWbAUzBfvYjPUEeNgqN1A==",
+ "dev": true,
+ "requires": {
+ "arrify": "^1.0.1",
+ "is-plain-obj": "^1.1.0",
+ "kind-of": "^6.0.3"
+ }
+ },
+ "mixin-deep": {
+ "version": "1.3.2",
+ "resolved": "https://registry.npmjs.org/mixin-deep/-/mixin-deep-1.3.2.tgz",
+ "integrity": "sha512-WRoDn//mXBiJ1H40rqa3vH0toePwSsGb45iInWlTySa+Uu4k3tYUSxa2v1KqAiLtvlrSzaExqS1gtk96A9zvEA==",
+ "dev": true,
+ "peer": true,
+ "requires": {
+ "for-in": "^1.0.2",
+ "is-extendable": "^1.0.1"
+ }
+ },
+ "mkdirp": {
+ "version": "1.0.4",
+ "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-1.0.4.tgz",
+ "integrity": "sha512-vVqVZQyf3WLx2Shd0qJ9xuvqgAyKPLAiqITEtqW0oIUjzo3PePDd6fW9iFz30ef7Ysp/oiWqbhszeGWW2T6Gzw==",
+ "dev": true
+ },
+ "ms": {
+ "version": "2.1.2",
+ "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz",
+ "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==",
+ "dev": true
+ },
+ "mute-stream": {
+ "version": "0.0.8",
+ "resolved": "https://registry.npmjs.org/mute-stream/-/mute-stream-0.0.8.tgz",
+ "integrity": "sha512-nnbWWOkoWyUsTjKrhgD0dcz22mdkSnpYqbEjIm2nhwhuxlSkpywJmBo8h0ZqJdkp73mb90SssHkN4rsRaBAfAA==",
+ "dev": true
+ },
+ "nanoid": {
+ "version": "3.3.4",
+ "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.4.tgz",
+ "integrity": "sha512-MqBkQh/OHTS2egovRtLk45wEyNXwF+cokD+1YPf9u5VfJiRdAiRwB2froX5Co9Rh20xs4siNPm8naNotSD6RBw==",
+ "dev": true
+ },
+ "nanomatch": {
+ "version": "1.2.13",
+ "resolved": "https://registry.npmjs.org/nanomatch/-/nanomatch-1.2.13.tgz",
+ "integrity": "sha512-fpoe2T0RbHwBTBUOftAfBPaDEi06ufaUai0mE6Yn1kacc3SnTErfb/h+X94VXzI64rKFHYImXSvdwGGCmwOqCA==",
+ "dev": true,
+ "peer": true,
+ "requires": {
+ "arr-diff": "^4.0.0",
+ "array-unique": "^0.3.2",
+ "define-property": "^2.0.2",
+ "extend-shallow": "^3.0.2",
+ "fragment-cache": "^0.2.1",
+ "is-windows": "^1.0.2",
+ "kind-of": "^6.0.2",
+ "object.pick": "^1.3.0",
+ "regex-not": "^1.0.0",
+ "snapdragon": "^0.8.1",
+ "to-regex": "^3.0.1"
+ }
+ },
+ "natural-compare": {
+ "version": "1.4.0",
+ "resolved": "https://registry.npmjs.org/natural-compare/-/natural-compare-1.4.0.tgz",
+ "integrity": "sha1-Sr6/7tdUHywnrPspvbvRXI1bpPc=",
+ "dev": true
+ },
+ "natural-compare-lite": {
+ "version": "1.4.0",
+ "resolved": "https://registry.npmjs.org/natural-compare-lite/-/natural-compare-lite-1.4.0.tgz",
+ "integrity": "sha512-Tj+HTDSJJKaZnfiuw+iaF9skdPpTo2GtEly5JHnWV/hfv2Qj/9RKsGISQtLh2ox3l5EAGw487hnBee0sIJ6v2g==",
+ "dev": true
+ },
+ "next": {
+ "version": "12.3.1",
+ "resolved": "https://registry.npmjs.org/next/-/next-12.3.1.tgz",
+ "integrity": "sha512-l7bvmSeIwX5lp07WtIiP9u2ytZMv7jIeB8iacR28PuUEFG5j0HGAPnMqyG5kbZNBG2H7tRsrQ4HCjuMOPnANZw==",
+ "dev": true,
+ "requires": {
+ "@next/env": "12.3.1",
+ "@next/swc-android-arm-eabi": "12.3.1",
+ "@next/swc-android-arm64": "12.3.1",
+ "@next/swc-darwin-arm64": "12.3.1",
+ "@next/swc-darwin-x64": "12.3.1",
+ "@next/swc-freebsd-x64": "12.3.1",
+ "@next/swc-linux-arm-gnueabihf": "12.3.1",
+ "@next/swc-linux-arm64-gnu": "12.3.1",
+ "@next/swc-linux-arm64-musl": "12.3.1",
+ "@next/swc-linux-x64-gnu": "12.3.1",
+ "@next/swc-linux-x64-musl": "12.3.1",
+ "@next/swc-win32-arm64-msvc": "12.3.1",
+ "@next/swc-win32-ia32-msvc": "12.3.1",
+ "@next/swc-win32-x64-msvc": "12.3.1",
+ "@swc/helpers": "0.4.11",
+ "caniuse-lite": "^1.0.30001406",
+ "postcss": "8.4.14",
+ "styled-jsx": "5.0.7",
+ "use-sync-external-store": "1.2.0"
+ }
+ },
+ "nice-try": {
+ "version": "1.0.5",
+ "resolved": "https://registry.npmjs.org/nice-try/-/nice-try-1.0.5.tgz",
+ "integrity": "sha512-1nh45deeb5olNY7eX82BkPO7SSxR5SSYJiPTrTdFUVYwAl8CKMA5N9PjTYkHiRjisVcxcQ1HXdLhx2qxxJzLNQ==",
+ "dev": true,
+ "peer": true
+ },
+ "node-fetch": {
+ "version": "2.6.7",
+ "resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-2.6.7.tgz",
+ "integrity": "sha512-ZjMPFEfVx5j+y2yF35Kzx5sF7kDzxuDj6ziH4FFbOp87zKDZNx8yExJIb05OGF4Nlt9IHFIMBkRl41VdvcNdbQ==",
+ "dev": true,
+ "requires": {
+ "whatwg-url": "^5.0.0"
+ },
+ "dependencies": {
+ "tr46": {
+ "version": "0.0.3",
+ "resolved": "https://registry.npmjs.org/tr46/-/tr46-0.0.3.tgz",
+ "integrity": "sha1-gYT9NH2snNwYWZLzpmIuFLnZq2o=",
+ "dev": true
+ },
+ "webidl-conversions": {
+ "version": "3.0.1",
+ "resolved": "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-3.0.1.tgz",
+ "integrity": "sha1-JFNCdeKnvGvnvIZhHMFq4KVlSHE=",
+ "dev": true
+ },
+ "whatwg-url": {
+ "version": "5.0.0",
+ "resolved": "https://registry.npmjs.org/whatwg-url/-/whatwg-url-5.0.0.tgz",
+ "integrity": "sha1-lmRU6HZUYuN2RNNib2dCzotwll0=",
+ "dev": true,
+ "requires": {
+ "tr46": "~0.0.3",
+ "webidl-conversions": "^3.0.0"
+ }
+ }
+ }
+ },
+ "node-int64": {
+ "version": "0.4.0",
+ "resolved": "https://registry.npmjs.org/node-int64/-/node-int64-0.4.0.tgz",
+ "integrity": "sha1-h6kGXNs1XTGC2PlM4RGIuCXGijs=",
+ "dev": true,
+ "peer": true
+ },
+ "node-notifier": {
+ "version": "8.0.2",
+ "resolved": "https://registry.npmjs.org/node-notifier/-/node-notifier-8.0.2.tgz",
+ "integrity": "sha512-oJP/9NAdd9+x2Q+rfphB2RJCHjod70RcRLjosiPMMu5gjIfwVnOUGq2nbTjTUbmy0DJ/tFIVT30+Qe3nzl4TJg==",
+ "dev": true,
+ "optional": true,
+ "peer": true,
+ "requires": {
+ "growly": "^1.3.0",
+ "is-wsl": "^2.2.0",
+ "semver": "^7.3.2",
+ "shellwords": "^0.1.1",
+ "uuid": "^8.3.0",
+ "which": "^2.0.2"
+ }
+ },
+ "node-releases": {
+ "version": "2.0.3",
+ "resolved": "https://registry.npmjs.org/node-releases/-/node-releases-2.0.3.tgz",
+ "integrity": "sha512-maHFz6OLqYxz+VQyCAtA3PTX4UP/53pa05fyDNc9CwjvJ0yEh6+xBwKsgCxMNhS8taUKBFYxfuiaD9U/55iFaw==",
+ "dev": true
+ },
+ "normalize-package-data": {
+ "version": "2.5.0",
+ "resolved": "https://registry.npmjs.org/normalize-package-data/-/normalize-package-data-2.5.0.tgz",
+ "integrity": "sha512-/5CMN3T0R4XTj4DcGaexo+roZSdSFW/0AOOTROrjxzCG1wrWXEsGbRKevjlIL+ZDE4sZlJr5ED4YW0yqmkK+eA==",
+ "dev": true,
+ "requires": {
+ "hosted-git-info": "^2.1.4",
+ "resolve": "^1.10.0",
+ "semver": "2 || 3 || 4 || 5",
+ "validate-npm-package-license": "^3.0.1"
+ },
+ "dependencies": {
+ "semver": {
+ "version": "5.7.1",
+ "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz",
+ "integrity": "sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==",
+ "dev": true
+ }
+ }
+ },
+ "normalize-path": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-3.0.0.tgz",
+ "integrity": "sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==",
+ "dev": true
+ },
+ "normalize-range": {
+ "version": "0.1.2",
+ "resolved": "https://registry.npmjs.org/normalize-range/-/normalize-range-0.1.2.tgz",
+ "integrity": "sha1-LRDAa9/TEuqXd2laTShDlFa3WUI=",
+ "dev": true
+ },
+ "normalize-selector": {
+ "version": "0.2.0",
+ "resolved": "https://registry.npmjs.org/normalize-selector/-/normalize-selector-0.2.0.tgz",
+ "integrity": "sha1-0LFF62kRicY6eNIB3E/bEpPvDAM=",
+ "dev": true
+ },
+ "npm-run-path": {
+ "version": "4.0.1",
+ "resolved": "https://registry.npmjs.org/npm-run-path/-/npm-run-path-4.0.1.tgz",
+ "integrity": "sha512-S48WzZW777zhNIrn7gxOlISNAqi9ZC/uQFnRdbeIHhZhCA6UqpkOT8T1G7BvfdgP4Er8gF4sUbaS0i7QvIfCWw==",
+ "dev": true,
+ "requires": {
+ "path-key": "^3.0.0"
+ }
+ },
+ "num2fraction": {
+ "version": "1.2.2",
+ "resolved": "https://registry.npmjs.org/num2fraction/-/num2fraction-1.2.2.tgz",
+ "integrity": "sha1-b2gragJ6Tp3fpFZM0lidHU5mnt4=",
+ "dev": true
+ },
+ "nwsapi": {
+ "version": "2.2.0",
+ "resolved": "https://registry.npmjs.org/nwsapi/-/nwsapi-2.2.0.tgz",
+ "integrity": "sha512-h2AatdwYH+JHiZpv7pt/gSX1XoRGb7L/qSIeuqA6GwYoF9w1vP1cw42TO0aI2pNyshRK5893hNSl+1//vHK7hQ==",
+ "dev": true,
+ "peer": true
+ },
+ "object-assign": {
+ "version": "4.1.1",
+ "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz",
+ "integrity": "sha512-rJgTQnkUnH1sFw8yT6VSU3zD3sWmu6sZhIseY8VX+GRu3P6F7Fu+JNDoXfklElbLJSnc3FUQHVe4cU5hj+BcUg==",
+ "dev": true
+ },
+ "object-copy": {
+ "version": "0.1.0",
+ "resolved": "https://registry.npmjs.org/object-copy/-/object-copy-0.1.0.tgz",
+ "integrity": "sha1-fn2Fi3gb18mRpBupde04EnVOmYw=",
+ "dev": true,
+ "peer": true,
+ "requires": {
+ "copy-descriptor": "^0.1.0",
+ "define-property": "^0.2.5",
+ "kind-of": "^3.0.3"
+ },
+ "dependencies": {
+ "define-property": {
+ "version": "0.2.5",
+ "resolved": "https://registry.npmjs.org/define-property/-/define-property-0.2.5.tgz",
+ "integrity": "sha1-w1se+RjsPJkPmlvFe+BKrOxcgRY=",
+ "dev": true,
+ "peer": true,
+ "requires": {
+ "is-descriptor": "^0.1.0"
+ }
+ },
+ "is-accessor-descriptor": {
+ "version": "0.1.6",
+ "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-0.1.6.tgz",
+ "integrity": "sha1-qeEss66Nh2cn7u84Q/igiXtcmNY=",
+ "dev": true,
+ "peer": true,
+ "requires": {
+ "kind-of": "^3.0.2"
+ }
+ },
+ "is-buffer": {
+ "version": "1.1.6",
+ "resolved": "https://registry.npmjs.org/is-buffer/-/is-buffer-1.1.6.tgz",
+ "integrity": "sha512-NcdALwpXkTm5Zvvbk7owOUSvVvBKDgKP5/ewfXEznmQFfs4ZRmanOeKBTjRVjka3QFoN6XJ+9F3USqfHqTaU5w==",
+ "dev": true,
+ "peer": true
+ },
+ "is-data-descriptor": {
+ "version": "0.1.4",
+ "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-0.1.4.tgz",
+ "integrity": "sha1-C17mSDiOLIYCgueT8YVv7D8wG1Y=",
+ "dev": true,
+ "peer": true,
+ "requires": {
+ "kind-of": "^3.0.2"
+ }
+ },
+ "is-descriptor": {
+ "version": "0.1.6",
+ "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-0.1.6.tgz",
+ "integrity": "sha512-avDYr0SB3DwO9zsMov0gKCESFYqCnE4hq/4z3TdUlukEy5t9C0YRq7HLrsN52NAcqXKaepeCD0n+B0arnVG3Hg==",
+ "dev": true,
+ "peer": true,
+ "requires": {
+ "is-accessor-descriptor": "^0.1.6",
+ "is-data-descriptor": "^0.1.4",
+ "kind-of": "^5.0.0"
+ },
+ "dependencies": {
+ "kind-of": {
+ "version": "5.1.0",
+ "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-5.1.0.tgz",
+ "integrity": "sha512-NGEErnH6F2vUuXDh+OlbcKW7/wOcfdRHaZ7VWtqCztfHri/++YKmP51OdWeGPuqCOba6kk2OTe5d02VmTB80Pw==",
+ "dev": true,
+ "peer": true
+ }
+ }
+ },
+ "kind-of": {
+ "version": "3.2.2",
+ "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz",
+ "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=",
+ "dev": true,
+ "peer": true,
+ "requires": {
+ "is-buffer": "^1.1.5"
+ }
+ }
+ }
+ },
+ "object-inspect": {
+ "version": "1.12.3",
+ "resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.12.3.tgz",
+ "integrity": "sha512-geUvdk7c+eizMNUDkRpW1wJwgfOiOeHbxBR/hLXK1aT6zmVSO0jsQcs7fj6MGw89jC/cjGfLcNOrtMYtGqm81g==",
+ "dev": true
+ },
+ "object-is": {
+ "version": "1.1.5",
+ "resolved": "https://registry.npmjs.org/object-is/-/object-is-1.1.5.tgz",
+ "integrity": "sha512-3cyDsyHgtmi7I7DfSSI2LDp6SK2lwvtbg0p0R1e0RvTqF5ceGx+K2dfSjm1bKDMVCFEDAQvy+o8c6a7VujOddw==",
+ "dev": true,
+ "requires": {
+ "call-bind": "^1.0.2",
+ "define-properties": "^1.1.3"
+ }
+ },
+ "object-keys": {
+ "version": "1.1.1",
+ "resolved": "https://registry.npmjs.org/object-keys/-/object-keys-1.1.1.tgz",
+ "integrity": "sha512-NuAESUOUMrlIXOfHKzD6bpPu3tYt3xvjNdRIQ+FeT0lNb4K8WR70CaDxhuNguS2XG+GjkyMwOzsN5ZktImfhLA==",
+ "dev": true
+ },
+ "object-visit": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/object-visit/-/object-visit-1.0.1.tgz",
+ "integrity": "sha1-95xEk68MU3e1n+OdOV5BBC3QRbs=",
+ "dev": true,
+ "peer": true,
+ "requires": {
+ "isobject": "^3.0.0"
+ }
+ },
+ "object.assign": {
+ "version": "4.1.4",
+ "resolved": "https://registry.npmjs.org/object.assign/-/object.assign-4.1.4.tgz",
+ "integrity": "sha512-1mxKf0e58bvyjSCtKYY4sRe9itRk3PJpquJOjeIkz885CczcI4IvJJDLPS72oowuSh+pBxUFROpX+TU++hxhZQ==",
+ "dev": true,
+ "requires": {
+ "call-bind": "^1.0.2",
+ "define-properties": "^1.1.4",
+ "has-symbols": "^1.0.3",
+ "object-keys": "^1.1.1"
+ }
+ },
+ "object.entries": {
+ "version": "1.1.6",
+ "resolved": "https://registry.npmjs.org/object.entries/-/object.entries-1.1.6.tgz",
+ "integrity": "sha512-leTPzo4Zvg3pmbQ3rDK69Rl8GQvIqMWubrkxONG9/ojtFE2rD9fjMKfSI5BxW3osRH1m6VdzmqK8oAY9aT4x5w==",
+ "dev": true,
+ "requires": {
+ "call-bind": "^1.0.2",
+ "define-properties": "^1.1.4",
+ "es-abstract": "^1.20.4"
+ }
+ },
+ "object.fromentries": {
+ "version": "2.0.6",
+ "resolved": "https://registry.npmjs.org/object.fromentries/-/object.fromentries-2.0.6.tgz",
+ "integrity": "sha512-VciD13dswC4j1Xt5394WR4MzmAQmlgN72phd/riNp9vtD7tp4QQWJ0R4wvclXcafgcYK8veHRed2W6XeGBvcfg==",
+ "dev": true,
+ "requires": {
+ "call-bind": "^1.0.2",
+ "define-properties": "^1.1.4",
+ "es-abstract": "^1.20.4"
+ }
+ },
+ "object.hasown": {
+ "version": "1.1.2",
+ "resolved": "https://registry.npmjs.org/object.hasown/-/object.hasown-1.1.2.tgz",
+ "integrity": "sha512-B5UIT3J1W+WuWIU55h0mjlwaqxiE5vYENJXIXZ4VFe05pNYrkKuK0U/6aFcb0pKywYJh7IhfoqUfKVmrJJHZHw==",
+ "dev": true,
+ "requires": {
+ "define-properties": "^1.1.4",
+ "es-abstract": "^1.20.4"
+ }
+ },
+ "object.pick": {
+ "version": "1.3.0",
+ "resolved": "https://registry.npmjs.org/object.pick/-/object.pick-1.3.0.tgz",
+ "integrity": "sha1-h6EKxMFpS9Lhy/U1kaZhQftd10c=",
+ "dev": true,
+ "peer": true,
+ "requires": {
+ "isobject": "^3.0.1"
+ }
+ },
+ "object.values": {
+ "version": "1.1.6",
+ "resolved": "https://registry.npmjs.org/object.values/-/object.values-1.1.6.tgz",
+ "integrity": "sha512-FVVTkD1vENCsAcwNs9k6jea2uHC/X0+JcjG8YA60FN5CMaJmG95wT9jek/xX9nornqGRrBkKtzuAu2wuHpKqvw==",
+ "dev": true,
+ "requires": {
+ "call-bind": "^1.0.2",
+ "define-properties": "^1.1.4",
+ "es-abstract": "^1.20.4"
+ }
+ },
+ "once": {
+ "version": "1.4.0",
+ "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz",
+ "integrity": "sha1-WDsap3WWHUsROsF9nFC6753Xa9E=",
+ "dev": true,
+ "requires": {
+ "wrappy": "1"
+ }
+ },
+ "onetime": {
+ "version": "5.1.2",
+ "resolved": "https://registry.npmjs.org/onetime/-/onetime-5.1.2.tgz",
+ "integrity": "sha512-kbpaSSGJTWdAY5KPVeMOKXSrPtr8C8C7wodJbcsd51jRnmD+GZu8Y0VoU6Dm5Z4vWr0Ig/1NKuWRKf7j5aaYSg==",
+ "dev": true,
+ "requires": {
+ "mimic-fn": "^2.1.0"
+ }
+ },
+ "open": {
+ "version": "7.3.0",
+ "resolved": "https://registry.npmjs.org/open/-/open-7.3.0.tgz",
+ "integrity": "sha512-mgLwQIx2F/ye9SmbrUkurZCnkoXyXyu9EbHtJZrICjVAJfyMArdHp3KkixGdZx1ZHFPNIwl0DDM1dFFqXbTLZw==",
+ "dev": true,
+ "requires": {
+ "is-docker": "^2.0.0",
+ "is-wsl": "^2.1.1"
+ }
+ },
+ "opencollective-postinstall": {
+ "version": "2.0.3",
+ "resolved": "https://registry.npmjs.org/opencollective-postinstall/-/opencollective-postinstall-2.0.3.tgz",
+ "integrity": "sha512-8AV/sCtuzUeTo8gQK5qDZzARrulB3egtLzFgteqB2tcT4Mw7B8Kt7JcDHmltjz6FOAHsvTevk70gZEbhM4ZS9Q==",
+ "dev": true
+ },
+ "optionator": {
+ "version": "0.9.1",
+ "resolved": "https://registry.npmjs.org/optionator/-/optionator-0.9.1.tgz",
+ "integrity": "sha512-74RlY5FCnhq4jRxVUPKDaRwrVNXMqsGsiW6AJw4XK8hmtm10wC0ypZBLw5IIp85NZMr91+qd1RvvENwg7jjRFw==",
+ "dev": true,
+ "requires": {
+ "deep-is": "^0.1.3",
+ "fast-levenshtein": "^2.0.6",
+ "levn": "^0.4.1",
+ "prelude-ls": "^1.2.1",
+ "type-check": "^0.4.0",
+ "word-wrap": "^1.2.3"
+ }
+ },
+ "os-tmpdir": {
+ "version": "1.0.2",
+ "resolved": "https://registry.npmjs.org/os-tmpdir/-/os-tmpdir-1.0.2.tgz",
+ "integrity": "sha1-u+Z0BseaqFxc/sdm/lc0VV36EnQ=",
+ "dev": true
+ },
+ "p-each-series": {
+ "version": "2.2.0",
+ "resolved": "https://registry.npmjs.org/p-each-series/-/p-each-series-2.2.0.tgz",
+ "integrity": "sha512-ycIL2+1V32th+8scbpTvyHNaHe02z0sjgh91XXjAk+ZeXoPN4Z46DVUnzdso0aX4KckKw0FNNFHdjZ2UsZvxiA==",
+ "dev": true,
+ "peer": true
+ },
+ "p-finally": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/p-finally/-/p-finally-1.0.0.tgz",
+ "integrity": "sha1-P7z7FbiZpEEjs0ttzBi3JDNqLK4=",
+ "dev": true,
+ "peer": true
+ },
+ "p-limit": {
+ "version": "3.1.0",
+ "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-3.1.0.tgz",
+ "integrity": "sha512-TYOanM3wGwNGsZN2cVTYPArw454xnXj5qmWF1bEoAc4+cU/ol7GVh7odevjp1FNHduHc3KZMcFduxU5Xc6uJRQ==",
+ "dev": true,
+ "requires": {
+ "yocto-queue": "^0.1.0"
+ }
+ },
+ "p-locate": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-2.0.0.tgz",
+ "integrity": "sha1-IKAQOyIqcMj9OcwuWAaA893l7EM=",
+ "dev": true,
+ "requires": {
+ "p-limit": "^1.1.0"
+ },
+ "dependencies": {
+ "p-limit": {
+ "version": "1.3.0",
+ "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-1.3.0.tgz",
+ "integrity": "sha512-vvcXsLAJ9Dr5rQOPk7toZQZJApBl2K4J6dANSsEuh6QI41JYcsS/qhTGa9ErIUUgK3WNQoJYvylxvjqmiqEA9Q==",
+ "dev": true,
+ "requires": {
+ "p-try": "^1.0.0"
+ }
+ },
+ "p-try": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/p-try/-/p-try-1.0.0.tgz",
+ "integrity": "sha1-y8ec26+P1CKOE/Yh8rGiN8GyB7M=",
+ "dev": true
+ }
+ }
+ },
+ "p-map": {
+ "version": "4.0.0",
+ "resolved": "https://registry.npmjs.org/p-map/-/p-map-4.0.0.tgz",
+ "integrity": "sha512-/bjOqmgETBYB5BoEeGVea8dmvHb2m9GLy1E9W43yeyfP6QQCZGFNa+XRceJEuDB6zqr+gKpIAmlLebMpykw/MQ==",
+ "dev": true,
+ "requires": {
+ "aggregate-error": "^3.0.0"
+ }
+ },
+ "p-try": {
+ "version": "2.2.0",
+ "resolved": "https://registry.npmjs.org/p-try/-/p-try-2.2.0.tgz",
+ "integrity": "sha512-R4nPAVTAU0B9D35/Gk3uJf/7XYbQcyohSKdvAxIRSNghFl4e71hVoGnBNQz9cWaXxO2I10KTC+3jMdvvoKw6dQ==",
+ "dev": true
+ },
+ "parent-module": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/parent-module/-/parent-module-1.0.1.tgz",
+ "integrity": "sha512-GQ2EWRpQV8/o+Aw8YqtfZZPfNRWZYkbidE9k5rpl/hC3vtHHBfGm2Ifi6qWV+coDGkrUKZAxE3Lot5kcsRlh+g==",
+ "dev": true,
+ "requires": {
+ "callsites": "^3.0.0"
+ }
+ },
+ "parse-entities": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/parse-entities/-/parse-entities-2.0.0.tgz",
+ "integrity": "sha512-kkywGpCcRYhqQIchaWqZ875wzpS/bMKhz5HnN3p7wveJTkTtyAB/AlnS0f8DFSqYW1T82t6yEAkEcB+A1I3MbQ==",
+ "dev": true,
+ "requires": {
+ "character-entities": "^1.0.0",
+ "character-entities-legacy": "^1.0.0",
+ "character-reference-invalid": "^1.0.0",
+ "is-alphanumerical": "^1.0.0",
+ "is-decimal": "^1.0.0",
+ "is-hexadecimal": "^1.0.0"
+ }
+ },
+ "parse-json": {
+ "version": "5.2.0",
+ "resolved": "https://registry.npmjs.org/parse-json/-/parse-json-5.2.0.tgz",
+ "integrity": "sha512-ayCKvm/phCGxOkYRSCM82iDwct8/EonSEgCSxWxD7ve6jHggsFl4fZVQBPRNgQoKiuV/odhFrGzQXZwbifC8Rg==",
+ "dev": true,
+ "requires": {
+ "@babel/code-frame": "^7.0.0",
+ "error-ex": "^1.3.1",
+ "json-parse-even-better-errors": "^2.3.0",
+ "lines-and-columns": "^1.1.6"
+ }
+ },
+ "parse5": {
+ "version": "6.0.1",
+ "resolved": "https://registry.npmjs.org/parse5/-/parse5-6.0.1.tgz",
+ "integrity": "sha512-Ofn/CTFzRGTTxwpNEs9PP93gXShHcTq255nzRYSKe8AkVpZY7e1fpmTfOyoIvjP5HG7Z2ZM7VS9PPhQGW2pOpw==",
+ "dev": true,
+ "peer": true
+ },
+ "pascalcase": {
+ "version": "0.1.1",
+ "resolved": "https://registry.npmjs.org/pascalcase/-/pascalcase-0.1.1.tgz",
+ "integrity": "sha1-s2PlXoAGym/iF4TS2yK9FdeRfxQ=",
+ "dev": true,
+ "peer": true
+ },
+ "path-exists": {
+ "version": "4.0.0",
+ "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-4.0.0.tgz",
+ "integrity": "sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==",
+ "dev": true
+ },
+ "path-is-absolute": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz",
+ "integrity": "sha1-F0uSaHNVNP+8es5r9TpanhtcX18=",
+ "dev": true
+ },
+ "path-key": {
+ "version": "3.1.1",
+ "resolved": "https://registry.npmjs.org/path-key/-/path-key-3.1.1.tgz",
+ "integrity": "sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==",
+ "dev": true
+ },
+ "path-parse": {
+ "version": "1.0.7",
+ "resolved": "https://registry.npmjs.org/path-parse/-/path-parse-1.0.7.tgz",
+ "integrity": "sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw==",
+ "dev": true
+ },
+ "path-type": {
+ "version": "4.0.0",
+ "resolved": "https://registry.npmjs.org/path-type/-/path-type-4.0.0.tgz",
+ "integrity": "sha512-gDKb8aZMDeD/tZWs9P6+q0J9Mwkdl6xMV8TjnGP3qJVJ06bdMgkbBlLU8IdfOsIsFz2BW1rNVT3XuNEl8zPAvw==",
+ "dev": true
+ },
+ "picocolors": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.0.0.tgz",
+ "integrity": "sha512-1fygroTLlHu66zi26VoTDv8yRgm0Fccecssto+MhsZ0D/DGW2sm8E8AjW7NU5VVTRt5GxbeZ5qBuJr+HyLYkjQ==",
+ "dev": true
+ },
+ "picomatch": {
+ "version": "2.3.1",
+ "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.1.tgz",
+ "integrity": "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==",
+ "dev": true
+ },
+ "pify": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/pify/-/pify-3.0.0.tgz",
+ "integrity": "sha1-5aSs0sEB/fPZpNB/DbxNtJ3SgXY=",
+ "dev": true
+ },
+ "pirates": {
+ "version": "4.0.5",
+ "resolved": "https://registry.npmjs.org/pirates/-/pirates-4.0.5.tgz",
+ "integrity": "sha512-8V9+HQPupnaXMA23c5hvl69zXvTwTzyAYasnkb0Tts4XvO4CliqONMOnvlq26rkhLC3nWDFBJf73LU1e1VZLaQ==",
+ "dev": true,
+ "peer": true
+ },
+ "pkg-conf": {
+ "version": "2.1.0",
+ "resolved": "https://registry.npmjs.org/pkg-conf/-/pkg-conf-2.1.0.tgz",
+ "integrity": "sha1-ISZRTKbyq/69FoWW3xi6V4Z/AFg=",
+ "dev": true,
+ "requires": {
+ "find-up": "^2.0.0",
+ "load-json-file": "^4.0.0"
+ }
+ },
+ "pkg-dir": {
+ "version": "4.2.0",
+ "resolved": "https://registry.npmjs.org/pkg-dir/-/pkg-dir-4.2.0.tgz",
+ "integrity": "sha512-HRDzbaKjC+AOWVXxAU/x54COGeIv9eb+6CkDSQoNTt4XyWoIJvuPsXizxu/Fr23EiekbtZwmh1IcIG/l/a10GQ==",
+ "dev": true,
+ "peer": true,
+ "requires": {
+ "find-up": "^4.0.0"
+ },
+ "dependencies": {
+ "find-up": {
+ "version": "4.1.0",
+ "resolved": "https://registry.npmjs.org/find-up/-/find-up-4.1.0.tgz",
+ "integrity": "sha512-PpOwAdQ/YlXQ2vj8a3h8IipDuYRi3wceVQQGYWxNINccq40Anw7BlsEXCMbt1Zt+OLA6Fq9suIpIWD0OsnISlw==",
+ "dev": true,
+ "peer": true,
+ "requires": {
+ "locate-path": "^5.0.0",
+ "path-exists": "^4.0.0"
+ }
+ },
+ "locate-path": {
+ "version": "5.0.0",
+ "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-5.0.0.tgz",
+ "integrity": "sha512-t7hw9pI+WvuwNJXwk5zVHpyhIqzg2qTlklJOf0mVxGSbe3Fp2VieZcduNYjaLDoy6p9uGpQEGWG87WpMKlNq8g==",
+ "dev": true,
+ "peer": true,
+ "requires": {
+ "p-locate": "^4.1.0"
+ }
+ },
+ "p-limit": {
+ "version": "2.3.0",
+ "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-2.3.0.tgz",
+ "integrity": "sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w==",
+ "dev": true,
+ "peer": true,
+ "requires": {
+ "p-try": "^2.0.0"
+ }
+ },
+ "p-locate": {
+ "version": "4.1.0",
+ "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-4.1.0.tgz",
+ "integrity": "sha512-R79ZZ/0wAxKGu3oYMlz8jy/kbhsNrS7SKZ7PxEHBgJ5+F2mtFW2fK2cOtBh1cHYkQsbzFV7I+EoRKe6Yt0oK7A==",
+ "dev": true,
+ "peer": true,
+ "requires": {
+ "p-limit": "^2.2.0"
+ }
+ }
+ }
+ },
+ "please-upgrade-node": {
+ "version": "3.2.0",
+ "resolved": "https://registry.npmjs.org/please-upgrade-node/-/please-upgrade-node-3.2.0.tgz",
+ "integrity": "sha512-gQR3WpIgNIKwBMVLkpMUeR3e1/E1y42bqDQZfql+kDeXd8COYfM8PQA4X6y7a8u9Ua9FHmsrrmirW2vHs45hWg==",
+ "dev": true,
+ "requires": {
+ "semver-compare": "^1.0.0"
+ }
+ },
+ "posix-character-classes": {
+ "version": "0.1.1",
+ "resolved": "https://registry.npmjs.org/posix-character-classes/-/posix-character-classes-0.1.1.tgz",
+ "integrity": "sha1-AerA/jta9xoqbAL+q7jB/vfgDqs=",
+ "dev": true,
+ "peer": true
+ },
+ "postcss": {
+ "version": "8.4.14",
+ "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.4.14.tgz",
+ "integrity": "sha512-E398TUmfAYFPBSdzgeieK2Y1+1cpdxJx8yXbK/m57nRhKSmk1GB2tO4lbLBtlkfPQTDKfe4Xqv1ASWPpayPEig==",
+ "dev": true,
+ "requires": {
+ "nanoid": "^3.3.4",
+ "picocolors": "^1.0.0",
+ "source-map-js": "^1.0.2"
+ }
+ },
+ "postcss-html": {
+ "version": "0.36.0",
+ "resolved": "https://registry.npmjs.org/postcss-html/-/postcss-html-0.36.0.tgz",
+ "integrity": "sha512-HeiOxGcuwID0AFsNAL0ox3mW6MHH5cstWN1Z3Y+n6H+g12ih7LHdYxWwEA/QmrebctLjo79xz9ouK3MroHwOJw==",
+ "dev": true,
+ "requires": {
+ "htmlparser2": "^3.10.0"
+ }
+ },
+ "postcss-less": {
+ "version": "3.1.4",
+ "resolved": "https://registry.npmjs.org/postcss-less/-/postcss-less-3.1.4.tgz",
+ "integrity": "sha512-7TvleQWNM2QLcHqvudt3VYjULVB49uiW6XzEUFmvwHzvsOEF5MwBrIXZDJQvJNFGjJQTzSzZnDoCJ8h/ljyGXA==",
+ "dev": true,
+ "requires": {
+ "postcss": "^7.0.14"
+ },
+ "dependencies": {
+ "picocolors": {
+ "version": "0.2.1",
+ "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-0.2.1.tgz",
+ "integrity": "sha512-cMlDqaLEqfSaW8Z7N5Jw+lyIW869EzT73/F5lhtY9cLGoVxSXznfgfXMO0Z5K0o0Q2TkTXq+0KFsdnSe3jDViA==",
+ "dev": true
+ },
+ "postcss": {
+ "version": "7.0.39",
+ "resolved": "https://registry.npmjs.org/postcss/-/postcss-7.0.39.tgz",
+ "integrity": "sha512-yioayjNbHn6z1/Bywyb2Y4s3yvDAeXGOyxqD+LnVOinq6Mdmd++SW2wUNVzavyyHxd6+DxzWGIuosg6P1Rj8uA==",
+ "dev": true,
+ "requires": {
+ "picocolors": "^0.2.1",
+ "source-map": "^0.6.1"
+ }
+ }
+ }
+ },
+ "postcss-media-query-parser": {
+ "version": "0.2.3",
+ "resolved": "https://registry.npmjs.org/postcss-media-query-parser/-/postcss-media-query-parser-0.2.3.tgz",
+ "integrity": "sha1-J7Ocb02U+Bsac7j3Y1HGCeXO8kQ=",
+ "dev": true
+ },
+ "postcss-resolve-nested-selector": {
+ "version": "0.1.1",
+ "resolved": "https://registry.npmjs.org/postcss-resolve-nested-selector/-/postcss-resolve-nested-selector-0.1.1.tgz",
+ "integrity": "sha1-Kcy8fDfe36wwTp//C/FZaz9qDk4=",
+ "dev": true
+ },
+ "postcss-safe-parser": {
+ "version": "4.0.2",
+ "resolved": "https://registry.npmjs.org/postcss-safe-parser/-/postcss-safe-parser-4.0.2.tgz",
+ "integrity": "sha512-Uw6ekxSWNLCPesSv/cmqf2bY/77z11O7jZGPax3ycZMFU/oi2DMH9i89AdHc1tRwFg/arFoEwX0IS3LCUxJh1g==",
+ "dev": true,
+ "requires": {
+ "postcss": "^7.0.26"
+ },
+ "dependencies": {
+ "picocolors": {
+ "version": "0.2.1",
+ "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-0.2.1.tgz",
+ "integrity": "sha512-cMlDqaLEqfSaW8Z7N5Jw+lyIW869EzT73/F5lhtY9cLGoVxSXznfgfXMO0Z5K0o0Q2TkTXq+0KFsdnSe3jDViA==",
+ "dev": true
+ },
+ "postcss": {
+ "version": "7.0.39",
+ "resolved": "https://registry.npmjs.org/postcss/-/postcss-7.0.39.tgz",
+ "integrity": "sha512-yioayjNbHn6z1/Bywyb2Y4s3yvDAeXGOyxqD+LnVOinq6Mdmd++SW2wUNVzavyyHxd6+DxzWGIuosg6P1Rj8uA==",
+ "dev": true,
+ "requires": {
+ "picocolors": "^0.2.1",
+ "source-map": "^0.6.1"
+ }
+ }
+ }
+ },
+ "postcss-sass": {
+ "version": "0.4.4",
+ "resolved": "https://registry.npmjs.org/postcss-sass/-/postcss-sass-0.4.4.tgz",
+ "integrity": "sha512-BYxnVYx4mQooOhr+zer0qWbSPYnarAy8ZT7hAQtbxtgVf8gy+LSLT/hHGe35h14/pZDTw1DsxdbrwxBN++H+fg==",
+ "dev": true,
+ "requires": {
+ "gonzales-pe": "^4.3.0",
+ "postcss": "^7.0.21"
+ },
+ "dependencies": {
+ "picocolors": {
+ "version": "0.2.1",
+ "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-0.2.1.tgz",
+ "integrity": "sha512-cMlDqaLEqfSaW8Z7N5Jw+lyIW869EzT73/F5lhtY9cLGoVxSXznfgfXMO0Z5K0o0Q2TkTXq+0KFsdnSe3jDViA==",
+ "dev": true
+ },
+ "postcss": {
+ "version": "7.0.39",
+ "resolved": "https://registry.npmjs.org/postcss/-/postcss-7.0.39.tgz",
+ "integrity": "sha512-yioayjNbHn6z1/Bywyb2Y4s3yvDAeXGOyxqD+LnVOinq6Mdmd++SW2wUNVzavyyHxd6+DxzWGIuosg6P1Rj8uA==",
+ "dev": true,
+ "requires": {
+ "picocolors": "^0.2.1",
+ "source-map": "^0.6.1"
+ }
+ }
+ }
+ },
+ "postcss-scss": {
+ "version": "2.1.1",
+ "resolved": "https://registry.npmjs.org/postcss-scss/-/postcss-scss-2.1.1.tgz",
+ "integrity": "sha512-jQmGnj0hSGLd9RscFw9LyuSVAa5Bl1/KBPqG1NQw9w8ND55nY4ZEsdlVuYJvLPpV+y0nwTV5v/4rHPzZRihQbA==",
+ "dev": true,
+ "requires": {
+ "postcss": "^7.0.6"
+ },
+ "dependencies": {
+ "picocolors": {
+ "version": "0.2.1",
+ "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-0.2.1.tgz",
+ "integrity": "sha512-cMlDqaLEqfSaW8Z7N5Jw+lyIW869EzT73/F5lhtY9cLGoVxSXznfgfXMO0Z5K0o0Q2TkTXq+0KFsdnSe3jDViA==",
+ "dev": true
+ },
+ "postcss": {
+ "version": "7.0.39",
+ "resolved": "https://registry.npmjs.org/postcss/-/postcss-7.0.39.tgz",
+ "integrity": "sha512-yioayjNbHn6z1/Bywyb2Y4s3yvDAeXGOyxqD+LnVOinq6Mdmd++SW2wUNVzavyyHxd6+DxzWGIuosg6P1Rj8uA==",
+ "dev": true,
+ "requires": {
+ "picocolors": "^0.2.1",
+ "source-map": "^0.6.1"
+ }
+ }
+ }
+ },
+ "postcss-selector-parser": {
+ "version": "6.0.10",
+ "resolved": "https://registry.npmjs.org/postcss-selector-parser/-/postcss-selector-parser-6.0.10.tgz",
+ "integrity": "sha512-IQ7TZdoaqbT+LCpShg46jnZVlhWD2w6iQYAcYXfHARZ7X1t/UGhhceQDs5X0cGqKvYlHNOuv7Oa1xmb0oQuA3w==",
+ "dev": true,
+ "requires": {
+ "cssesc": "^3.0.0",
+ "util-deprecate": "^1.0.2"
+ }
+ },
+ "postcss-sorting": {
+ "version": "5.0.1",
+ "resolved": "https://registry.npmjs.org/postcss-sorting/-/postcss-sorting-5.0.1.tgz",
+ "integrity": "sha512-Y9fUFkIhfrm6i0Ta3n+89j56EFqaNRdUKqXyRp6kvTcSXnmgEjaVowCXH+JBe9+YKWqd4nc28r2sgwnzJalccA==",
+ "dev": true,
+ "requires": {
+ "lodash": "^4.17.14",
+ "postcss": "^7.0.17"
+ },
+ "dependencies": {
+ "picocolors": {
+ "version": "0.2.1",
+ "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-0.2.1.tgz",
+ "integrity": "sha512-cMlDqaLEqfSaW8Z7N5Jw+lyIW869EzT73/F5lhtY9cLGoVxSXznfgfXMO0Z5K0o0Q2TkTXq+0KFsdnSe3jDViA==",
+ "dev": true
+ },
+ "postcss": {
+ "version": "7.0.39",
+ "resolved": "https://registry.npmjs.org/postcss/-/postcss-7.0.39.tgz",
+ "integrity": "sha512-yioayjNbHn6z1/Bywyb2Y4s3yvDAeXGOyxqD+LnVOinq6Mdmd++SW2wUNVzavyyHxd6+DxzWGIuosg6P1Rj8uA==",
+ "dev": true,
+ "requires": {
+ "picocolors": "^0.2.1",
+ "source-map": "^0.6.1"
+ }
+ }
+ }
+ },
+ "postcss-syntax": {
+ "version": "0.36.2",
+ "resolved": "https://registry.npmjs.org/postcss-syntax/-/postcss-syntax-0.36.2.tgz",
+ "integrity": "sha512-nBRg/i7E3SOHWxF3PpF5WnJM/jQ1YpY9000OaVXlAQj6Zp/kIqJxEDWIZ67tAd7NLuk7zqN4yqe9nc0oNAOs1w==",
+ "dev": true,
+ "requires": {}
+ },
+ "postcss-value-parser": {
+ "version": "4.2.0",
+ "resolved": "https://registry.npmjs.org/postcss-value-parser/-/postcss-value-parser-4.2.0.tgz",
+ "integrity": "sha512-1NNCs6uurfkVbeXG4S8JFT9t19m45ICnif8zWLd5oPSZ50QnwMfK+H3jv408d4jw/7Bttv5axS5IiHoLaVNHeQ==",
+ "dev": true
+ },
+ "postcss-values-parser": {
+ "version": "3.2.1",
+ "resolved": "https://registry.npmjs.org/postcss-values-parser/-/postcss-values-parser-3.2.1.tgz",
+ "integrity": "sha512-SQ7/88VE9LhJh9gc27/hqnSU/aZaREVJcRVccXBmajgP2RkjdJzNyH/a9GCVMI5nsRhT0jC5HpUMwfkz81DVVg==",
+ "dev": true,
+ "requires": {
+ "color-name": "^1.1.4",
+ "is-url-superb": "^3.0.0",
+ "postcss": "^7.0.5",
+ "url-regex": "^5.0.0"
+ },
+ "dependencies": {
+ "picocolors": {
+ "version": "0.2.1",
+ "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-0.2.1.tgz",
+ "integrity": "sha512-cMlDqaLEqfSaW8Z7N5Jw+lyIW869EzT73/F5lhtY9cLGoVxSXznfgfXMO0Z5K0o0Q2TkTXq+0KFsdnSe3jDViA==",
+ "dev": true
+ },
+ "postcss": {
+ "version": "7.0.39",
+ "resolved": "https://registry.npmjs.org/postcss/-/postcss-7.0.39.tgz",
+ "integrity": "sha512-yioayjNbHn6z1/Bywyb2Y4s3yvDAeXGOyxqD+LnVOinq6Mdmd++SW2wUNVzavyyHxd6+DxzWGIuosg6P1Rj8uA==",
+ "dev": true,
+ "requires": {
+ "picocolors": "^0.2.1",
+ "source-map": "^0.6.1"
+ }
+ }
+ }
+ },
+ "prelude-ls": {
+ "version": "1.2.1",
+ "resolved": "https://registry.npmjs.org/prelude-ls/-/prelude-ls-1.2.1.tgz",
+ "integrity": "sha512-vkcDPrRZo1QZLbn5RLGPpg/WmIQ65qoWWhcGKf/b5eplkkarX0m9z8ppCat4mlOqUsWpyNuYgO3VRyrYHSzX5g==",
+ "dev": true
+ },
+ "prettier": {
+ "version": "2.2.1",
+ "resolved": "https://registry.npmjs.org/prettier/-/prettier-2.2.1.tgz",
+ "integrity": "sha512-PqyhM2yCjg/oKkFPtTGUojv7gnZAoG80ttl45O6x2Ug/rMJw4wcc9k6aaf2hibP7BGVCCM33gZoGjyvt9mm16Q==",
+ "dev": true
+ },
+ "prettier-linter-helpers": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/prettier-linter-helpers/-/prettier-linter-helpers-1.0.0.tgz",
+ "integrity": "sha512-GbK2cP9nraSSUF9N2XwUwqfzlAFlMNYYl+ShE/V+H8a9uNl/oUqB1w2EL54Jh0OlyRSd8RfWYJ3coVS4TROP2w==",
+ "dev": true,
+ "requires": {
+ "fast-diff": "^1.1.2"
+ }
+ },
+ "pretty-format": {
+ "version": "26.6.2",
+ "resolved": "https://registry.npmjs.org/pretty-format/-/pretty-format-26.6.2.tgz",
+ "integrity": "sha512-7AeGuCYNGmycyQbCqd/3PWH4eOoX/OiCa0uphp57NVTeAGdJGaAliecxwBDHYQCIvrW7aDBZCYeNTP/WX69mkg==",
+ "dev": true,
+ "peer": true,
+ "requires": {
+ "@jest/types": "^26.6.2",
+ "ansi-regex": "^5.0.0",
+ "ansi-styles": "^4.0.0",
+ "react-is": "^17.0.1"
+ }
+ },
+ "prompts": {
+ "version": "2.4.2",
+ "resolved": "https://registry.npmjs.org/prompts/-/prompts-2.4.2.tgz",
+ "integrity": "sha512-NxNv/kLguCA7p3jE8oL2aEBsrJWgAakBpgmgK6lpPWV+WuOmY6r2/zbAVnP+T8bQlA0nzHXSJSJW0Hq7ylaD2Q==",
+ "dev": true,
+ "peer": true,
+ "requires": {
+ "kleur": "^3.0.3",
+ "sisteransi": "^1.0.5"
+ }
+ },
+ "prop-types": {
+ "version": "15.8.1",
+ "resolved": "https://registry.npmjs.org/prop-types/-/prop-types-15.8.1.tgz",
+ "integrity": "sha512-oj87CgZICdulUohogVAR7AjlC0327U4el4L6eAvOqCeudMDVU0NThNaV+b9Df4dXgSP1gXMTnPdhfe/2qDH5cg==",
+ "dev": true,
+ "requires": {
+ "loose-envify": "^1.4.0",
+ "object-assign": "^4.1.1",
+ "react-is": "^16.13.1"
+ },
+ "dependencies": {
+ "react-is": {
+ "version": "16.13.1",
+ "resolved": "https://registry.npmjs.org/react-is/-/react-is-16.13.1.tgz",
+ "integrity": "sha512-24e6ynE2H+OKt4kqsOvNd8kBpV65zoxbA4BVsEOB3ARVWQki/DHzaUoC5KuON/BiccDaCCTZBuOcfZs70kR8bQ==",
+ "dev": true
+ }
+ }
+ },
+ "psl": {
+ "version": "1.8.0",
+ "resolved": "https://registry.npmjs.org/psl/-/psl-1.8.0.tgz",
+ "integrity": "sha512-RIdOzyoavK+hA18OGGWDqUTsCLhtA7IcZ/6NCs4fFJaHBDab+pDDmDIByWFRQJq2Cd7r1OoQxBGKOaztq+hjIQ==",
+ "dev": true,
+ "peer": true
+ },
+ "pump": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/pump/-/pump-3.0.0.tgz",
+ "integrity": "sha512-LwZy+p3SFs1Pytd/jYct4wpv49HiYCqd9Rlc5ZVdk0V+8Yzv6jR5Blk3TRmPL1ft69TxP0IMZGJ+WPFU2BFhww==",
+ "dev": true,
+ "peer": true,
+ "requires": {
+ "end-of-stream": "^1.1.0",
+ "once": "^1.3.1"
+ }
+ },
+ "punycode": {
+ "version": "2.1.1",
+ "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.1.1.tgz",
+ "integrity": "sha512-XRsRjdf+j5ml+y/6GKHPZbrF/8p2Yga0JPtdqTIY2Xe5ohJPD9saDJJLPvp9+NSBprVvevdXZybnj2cv8OEd0A==",
+ "dev": true
+ },
+ "querystringify": {
+ "version": "2.2.0",
+ "resolved": "https://registry.npmjs.org/querystringify/-/querystringify-2.2.0.tgz",
+ "integrity": "sha512-FIqgj2EUvTa7R50u0rGsyTftzjYmv/a3hO345bZNrqabNqjtgiDMgmo4mkUjd+nzU5oF3dClKqFIPUKybUyqoQ==",
+ "dev": true,
+ "peer": true
+ },
+ "queue-microtask": {
+ "version": "1.2.3",
+ "resolved": "https://registry.npmjs.org/queue-microtask/-/queue-microtask-1.2.3.tgz",
+ "integrity": "sha512-NuaNSa6flKT5JaSYQzJok04JzTL1CA6aGhv5rfLW3PgqA+M2ChpZQnAC8h8i4ZFkBS8X5RqkDBHA7r4hej3K9A==",
+ "dev": true
+ },
+ "quick-lru": {
+ "version": "4.0.1",
+ "resolved": "https://registry.npmjs.org/quick-lru/-/quick-lru-4.0.1.tgz",
+ "integrity": "sha512-ARhCpm70fzdcvNQfPoy49IaanKkTlRWF2JMzqhcJbhSFRZv7nPTvZJdcY7301IPmvW+/p0RgIWnQDLJxifsQ7g==",
+ "dev": true
+ },
+ "react": {
+ "version": "18.0.0",
+ "resolved": "https://registry.npmjs.org/react/-/react-18.0.0.tgz",
+ "integrity": "sha512-x+VL6wbT4JRVPm7EGxXhZ8w8LTROaxPXOqhlGyVSrv0sB1jkyFGgXxJ8LVoPRLvPR6/CIZGFmfzqUa2NYeMr2A==",
+ "dev": true,
+ "peer": true,
+ "requires": {
+ "loose-envify": "^1.1.0"
+ }
+ },
+ "react-dom": {
+ "version": "18.0.0",
+ "resolved": "https://registry.npmjs.org/react-dom/-/react-dom-18.0.0.tgz",
+ "integrity": "sha512-XqX7uzmFo0pUceWFCt7Gff6IyIMzFUn7QMZrbrQfGxtaxXZIcGQzoNpRLE3fQLnS4XzLLPMZX2T9TRcSrasicw==",
+ "dev": true,
+ "peer": true,
+ "requires": {
+ "loose-envify": "^1.1.0",
+ "scheduler": "^0.21.0"
+ }
+ },
+ "react-is": {
+ "version": "17.0.2",
+ "resolved": "https://registry.npmjs.org/react-is/-/react-is-17.0.2.tgz",
+ "integrity": "sha512-w2GsyukL62IJnlaff/nRegPQR94C/XXamvMWmSHRJ4y7Ts/4ocGRmTHvOs8PSE6pB3dWOrD/nueuU5sduBsQ4w==",
+ "dev": true,
+ "peer": true
+ },
+ "read-pkg": {
+ "version": "5.2.0",
+ "resolved": "https://registry.npmjs.org/read-pkg/-/read-pkg-5.2.0.tgz",
+ "integrity": "sha512-Ug69mNOpfvKDAc2Q8DRpMjjzdtrnv9HcSMX+4VsZxD1aZ6ZzrIE7rlzXBtWTyhULSMKg076AW6WR5iZpD0JiOg==",
+ "dev": true,
+ "requires": {
+ "@types/normalize-package-data": "^2.4.0",
+ "normalize-package-data": "^2.5.0",
+ "parse-json": "^5.0.0",
+ "type-fest": "^0.6.0"
+ },
+ "dependencies": {
+ "type-fest": {
+ "version": "0.6.0",
+ "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.6.0.tgz",
+ "integrity": "sha512-q+MB8nYR1KDLrgr4G5yemftpMC7/QLqVndBmEEdqzmNj5dcFOO4Oo8qlwZE3ULT3+Zim1F8Kq4cBnikNhlCMlg==",
+ "dev": true
+ }
+ }
+ },
+ "read-pkg-up": {
+ "version": "7.0.1",
+ "resolved": "https://registry.npmjs.org/read-pkg-up/-/read-pkg-up-7.0.1.tgz",
+ "integrity": "sha512-zK0TB7Xd6JpCLmlLmufqykGE+/TlOePD6qKClNW7hHDKFh/J7/7gCWGR7joEQEW1bKq3a3yUZSObOoWLFQ4ohg==",
+ "dev": true,
+ "requires": {
+ "find-up": "^4.1.0",
+ "read-pkg": "^5.2.0",
+ "type-fest": "^0.8.1"
+ },
+ "dependencies": {
+ "find-up": {
+ "version": "4.1.0",
+ "resolved": "https://registry.npmjs.org/find-up/-/find-up-4.1.0.tgz",
+ "integrity": "sha512-PpOwAdQ/YlXQ2vj8a3h8IipDuYRi3wceVQQGYWxNINccq40Anw7BlsEXCMbt1Zt+OLA6Fq9suIpIWD0OsnISlw==",
+ "dev": true,
+ "requires": {
+ "locate-path": "^5.0.0",
+ "path-exists": "^4.0.0"
+ }
+ },
+ "locate-path": {
+ "version": "5.0.0",
+ "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-5.0.0.tgz",
+ "integrity": "sha512-t7hw9pI+WvuwNJXwk5zVHpyhIqzg2qTlklJOf0mVxGSbe3Fp2VieZcduNYjaLDoy6p9uGpQEGWG87WpMKlNq8g==",
+ "dev": true,
+ "requires": {
+ "p-locate": "^4.1.0"
+ }
+ },
+ "p-limit": {
+ "version": "2.3.0",
+ "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-2.3.0.tgz",
+ "integrity": "sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w==",
+ "dev": true,
+ "requires": {
+ "p-try": "^2.0.0"
+ }
+ },
+ "p-locate": {
+ "version": "4.1.0",
+ "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-4.1.0.tgz",
+ "integrity": "sha512-R79ZZ/0wAxKGu3oYMlz8jy/kbhsNrS7SKZ7PxEHBgJ5+F2mtFW2fK2cOtBh1cHYkQsbzFV7I+EoRKe6Yt0oK7A==",
+ "dev": true,
+ "requires": {
+ "p-limit": "^2.2.0"
+ }
+ },
+ "type-fest": {
+ "version": "0.8.1",
+ "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.8.1.tgz",
+ "integrity": "sha512-4dbzIzqvjtgiM5rw1k5rEHtBANKmdudhGyBEajN01fEyhaAIhsoKNy6y7+IN93IfpFtwY9iqi7kD+xwKhQsNJA==",
+ "dev": true
+ }
+ }
+ },
+ "readable-stream": {
+ "version": "3.6.0",
+ "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.0.tgz",
+ "integrity": "sha512-BViHy7LKeTz4oNnkcLJ+lVSL6vpiFeX6/d3oSH8zCW7UxP2onchk+vTGB143xuFjHS3deTgkKoXXymXqymiIdA==",
+ "dev": true,
+ "requires": {
+ "inherits": "^2.0.3",
+ "string_decoder": "^1.1.1",
+ "util-deprecate": "^1.0.1"
+ }
+ },
+ "readdirp": {
+ "version": "3.5.0",
+ "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-3.5.0.tgz",
+ "integrity": "sha512-cMhu7c/8rdhkHXWsY+osBhfSy0JikwpHK/5+imo+LpeasTF8ouErHrlYkwT0++njiyuDvc7OFY5T3ukvZ8qmFQ==",
+ "dev": true,
+ "requires": {
+ "picomatch": "^2.2.1"
+ }
+ },
+ "redent": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/redent/-/redent-3.0.0.tgz",
+ "integrity": "sha512-6tDA8g98We0zd0GvVeMT9arEOnTw9qM03L9cJXaCjrip1OO764RDBLBfrB4cwzNGDj5OA5ioymC9GkizgWJDUg==",
+ "dev": true,
+ "requires": {
+ "indent-string": "^4.0.0",
+ "strip-indent": "^3.0.0"
+ }
+ },
+ "regenerator-runtime": {
+ "version": "0.13.11",
+ "resolved": "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.13.11.tgz",
+ "integrity": "sha512-kY1AZVr2Ra+t+piVaJ4gxaFaReZVH40AKNo7UCX6W+dEwBo/2oZJzqfuN1qLq1oL45o56cPaTXELwrTh8Fpggg==",
+ "dev": true
+ },
+ "regex-not": {
+ "version": "1.0.2",
+ "resolved": "https://registry.npmjs.org/regex-not/-/regex-not-1.0.2.tgz",
+ "integrity": "sha512-J6SDjUgDxQj5NusnOtdFxDwN/+HWykR8GELwctJ7mdqhcyy1xEc4SRFHUXvxTp661YaVKAjfRLZ9cCqS6tn32A==",
+ "dev": true,
+ "peer": true,
+ "requires": {
+ "extend-shallow": "^3.0.2",
+ "safe-regex": "^1.1.0"
+ }
+ },
+ "regexp.prototype.flags": {
+ "version": "1.4.3",
+ "resolved": "https://registry.npmjs.org/regexp.prototype.flags/-/regexp.prototype.flags-1.4.3.tgz",
+ "integrity": "sha512-fjggEOO3slI6Wvgjwflkc4NFRCTZAu5CnNfBd5qOMYhWdn67nJBBu34/TkD++eeFmd8C9r9jfXJ27+nSiRkSUA==",
+ "dev": true,
+ "requires": {
+ "call-bind": "^1.0.2",
+ "define-properties": "^1.1.3",
+ "functions-have-names": "^1.2.2"
+ }
+ },
+ "remark": {
+ "version": "13.0.0",
+ "resolved": "https://registry.npmjs.org/remark/-/remark-13.0.0.tgz",
+ "integrity": "sha512-HDz1+IKGtOyWN+QgBiAT0kn+2s6ovOxHyPAFGKVE81VSzJ+mq7RwHFledEvB5F1p4iJvOah/LOKdFuzvRnNLCA==",
+ "dev": true,
+ "requires": {
+ "remark-parse": "^9.0.0",
+ "remark-stringify": "^9.0.0",
+ "unified": "^9.1.0"
+ }
+ },
+ "remark-mdx": {
+ "version": "1.6.22",
+ "resolved": "https://registry.npmjs.org/remark-mdx/-/remark-mdx-1.6.22.tgz",
+ "integrity": "sha512-phMHBJgeV76uyFkH4rvzCftLfKCr2RZuF+/gmVcaKrpsihyzmhXjA0BEMDaPTXG5y8qZOKPVo83NAOX01LPnOQ==",
+ "dev": true,
+ "requires": {
+ "@babel/core": "7.12.9",
+ "@babel/helper-plugin-utils": "7.10.4",
+ "@babel/plugin-proposal-object-rest-spread": "7.12.1",
+ "@babel/plugin-syntax-jsx": "7.12.1",
+ "@mdx-js/util": "1.6.22",
+ "is-alphabetical": "1.0.4",
+ "remark-parse": "8.0.3",
+ "unified": "9.2.0"
+ },
+ "dependencies": {
+ "@babel/core": {
+ "version": "7.12.9",
+ "resolved": "https://registry.npmjs.org/@babel/core/-/core-7.12.9.tgz",
+ "integrity": "sha512-gTXYh3M5wb7FRXQy+FErKFAv90BnlOuNn1QkCK2lREoPAjrQCO49+HVSrFoe5uakFAF5eenS75KbO2vQiLrTMQ==",
+ "dev": true,
+ "requires": {
+ "@babel/code-frame": "^7.10.4",
+ "@babel/generator": "^7.12.5",
+ "@babel/helper-module-transforms": "^7.12.1",
+ "@babel/helpers": "^7.12.5",
+ "@babel/parser": "^7.12.7",
+ "@babel/template": "^7.12.7",
+ "@babel/traverse": "^7.12.9",
+ "@babel/types": "^7.12.7",
+ "convert-source-map": "^1.7.0",
+ "debug": "^4.1.0",
+ "gensync": "^1.0.0-beta.1",
+ "json5": "^2.1.2",
+ "lodash": "^4.17.19",
+ "resolve": "^1.3.2",
+ "semver": "^5.4.1",
+ "source-map": "^0.5.0"
+ }
+ },
+ "@babel/helper-plugin-utils": {
+ "version": "7.10.4",
+ "resolved": "https://registry.npmjs.org/@babel/helper-plugin-utils/-/helper-plugin-utils-7.10.4.tgz",
+ "integrity": "sha512-O4KCvQA6lLiMU9l2eawBPMf1xPP8xPfB3iEQw150hOVTqj/rfXz0ThTb4HEzqQfs2Bmo5Ay8BzxfzVtBrr9dVg==",
+ "dev": true
+ },
+ "is-plain-obj": {
+ "version": "2.1.0",
+ "resolved": "https://registry.npmjs.org/is-plain-obj/-/is-plain-obj-2.1.0.tgz",
+ "integrity": "sha512-YWnfyRwxL/+SsrWYfOpUtz5b3YD+nyfkHvjbcanzk8zgyO4ASD67uVMRt8k5bM4lLMDnXfriRhOpemw+NfT1eA==",
+ "dev": true
+ },
+ "remark-parse": {
+ "version": "8.0.3",
+ "resolved": "https://registry.npmjs.org/remark-parse/-/remark-parse-8.0.3.tgz",
+ "integrity": "sha512-E1K9+QLGgggHxCQtLt++uXltxEprmWzNfg+MxpfHsZlrddKzZ/hZyWHDbK3/Ap8HJQqYJRXP+jHczdL6q6i85Q==",
+ "dev": true,
+ "requires": {
+ "ccount": "^1.0.0",
+ "collapse-white-space": "^1.0.2",
+ "is-alphabetical": "^1.0.0",
+ "is-decimal": "^1.0.0",
+ "is-whitespace-character": "^1.0.0",
+ "is-word-character": "^1.0.0",
+ "markdown-escapes": "^1.0.0",
+ "parse-entities": "^2.0.0",
+ "repeat-string": "^1.5.4",
+ "state-toggle": "^1.0.0",
+ "trim": "0.0.1",
+ "trim-trailing-lines": "^1.0.0",
+ "unherit": "^1.0.4",
+ "unist-util-remove-position": "^2.0.0",
+ "vfile-location": "^3.0.0",
+ "xtend": "^4.0.1"
+ }
+ },
+ "semver": {
+ "version": "5.7.1",
+ "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz",
+ "integrity": "sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==",
+ "dev": true
+ },
+ "source-map": {
+ "version": "0.5.7",
+ "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz",
+ "integrity": "sha512-LbrmJOMUSdEVxIKvdcJzQC+nQhe8FUZQTXQy6+I75skNgn3OoQ0DZA8YnFa7gp8tqtL3KPf1kmo0R5DoApeSGQ==",
+ "dev": true
+ },
+ "unified": {
+ "version": "9.2.0",
+ "resolved": "https://registry.npmjs.org/unified/-/unified-9.2.0.tgz",
+ "integrity": "sha512-vx2Z0vY+a3YoTj8+pttM3tiJHCwY5UFbYdiWrwBEbHmK8pvsPj2rtAX2BFfgXen8T39CJWblWRDT4L5WGXtDdg==",
+ "dev": true,
+ "requires": {
+ "bail": "^1.0.0",
+ "extend": "^3.0.0",
+ "is-buffer": "^2.0.0",
+ "is-plain-obj": "^2.0.0",
+ "trough": "^1.0.0",
+ "vfile": "^4.0.0"
+ }
+ }
+ }
+ },
+ "remark-parse": {
+ "version": "9.0.0",
+ "resolved": "https://registry.npmjs.org/remark-parse/-/remark-parse-9.0.0.tgz",
+ "integrity": "sha512-geKatMwSzEXKHuzBNU1z676sGcDcFoChMK38TgdHJNAYfFtsfHDQG7MoJAjs6sgYMqyLduCYWDIWZIxiPeafEw==",
+ "dev": true,
+ "requires": {
+ "mdast-util-from-markdown": "^0.8.0"
+ }
+ },
+ "remark-stringify": {
+ "version": "9.0.1",
+ "resolved": "https://registry.npmjs.org/remark-stringify/-/remark-stringify-9.0.1.tgz",
+ "integrity": "sha512-mWmNg3ZtESvZS8fv5PTvaPckdL4iNlCHTt8/e/8oN08nArHRHjNZMKzA/YW3+p7/lYqIw4nx1XsjCBo/AxNChg==",
+ "dev": true,
+ "requires": {
+ "mdast-util-to-markdown": "^0.6.0"
+ }
+ },
+ "remove-trailing-separator": {
+ "version": "1.1.0",
+ "resolved": "https://registry.npmjs.org/remove-trailing-separator/-/remove-trailing-separator-1.1.0.tgz",
+ "integrity": "sha1-wkvOKig62tW8P1jg1IJJuSN52O8=",
+ "dev": true,
+ "peer": true
+ },
+ "repeat-element": {
+ "version": "1.1.4",
+ "resolved": "https://registry.npmjs.org/repeat-element/-/repeat-element-1.1.4.tgz",
+ "integrity": "sha512-LFiNfRcSu7KK3evMyYOuCzv3L10TW7yC1G2/+StMjK8Y6Vqd2MG7r/Qjw4ghtuCOjFvlnms/iMmLqpvW/ES/WQ==",
+ "dev": true,
+ "peer": true
+ },
+ "repeat-string": {
+ "version": "1.6.1",
+ "resolved": "https://registry.npmjs.org/repeat-string/-/repeat-string-1.6.1.tgz",
+ "integrity": "sha1-jcrkcOHIirwtYA//Sndihtp15jc=",
+ "dev": true
+ },
+ "require-directory": {
+ "version": "2.1.1",
+ "resolved": "https://registry.npmjs.org/require-directory/-/require-directory-2.1.1.tgz",
+ "integrity": "sha1-jGStX9MNqxyXbiNE/+f3kqam30I=",
+ "dev": true
+ },
+ "require-from-string": {
+ "version": "2.0.2",
+ "resolved": "https://registry.npmjs.org/require-from-string/-/require-from-string-2.0.2.tgz",
+ "integrity": "sha512-Xf0nWe6RseziFMu+Ap9biiUbmplq6S9/p+7w7YXP/JBHhrUDDUhwa+vANyubuqfZWTveU//DYVGsDG7RKL/vEw==",
+ "dev": true
+ },
+ "require-main-filename": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/require-main-filename/-/require-main-filename-2.0.0.tgz",
+ "integrity": "sha512-NKN5kMDylKuldxYLSUfrbo5Tuzh4hd+2E8NPPX02mZtn1VuREQToYe/ZdlJy+J3uCpfaiGF05e7B8W0iXbQHmg==",
+ "dev": true,
+ "peer": true
+ },
+ "requires-port": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/requires-port/-/requires-port-1.0.0.tgz",
+ "integrity": "sha512-KigOCHcocU3XODJxsu8i/j8T9tzT4adHiecwORRQ0ZZFcp7ahwXuRU1m+yuO90C5ZUyGeGfocHDI14M3L3yDAQ==",
+ "dev": true,
+ "peer": true
+ },
+ "resolve": {
+ "version": "1.22.0",
+ "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.22.0.tgz",
+ "integrity": "sha512-Hhtrw0nLeSrFQ7phPp4OOcVjLPIeMnRlr5mcnVuMe7M/7eBn98A3hmFRLoFo3DLZkivSYwhRUJTyPyWAk56WLw==",
+ "dev": true,
+ "requires": {
+ "is-core-module": "^2.8.1",
+ "path-parse": "^1.0.7",
+ "supports-preserve-symlinks-flag": "^1.0.0"
+ }
+ },
+ "resolve-cwd": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/resolve-cwd/-/resolve-cwd-3.0.0.tgz",
+ "integrity": "sha512-OrZaX2Mb+rJCpH/6CpSqt9xFVpN++x01XnN2ie9g6P5/3xelLAkXWVADpdz1IHD/KFfEXyE6V0U01OQ3UO2rEg==",
+ "dev": true,
+ "peer": true,
+ "requires": {
+ "resolve-from": "^5.0.0"
+ },
+ "dependencies": {
+ "resolve-from": {
+ "version": "5.0.0",
+ "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-5.0.0.tgz",
+ "integrity": "sha512-qYg9KP24dD5qka9J47d0aVky0N+b4fTU89LN9iDnjB5waksiC49rvMB0PrUJQGoTmH50XPiqOvAjDfaijGxYZw==",
+ "dev": true,
+ "peer": true
+ }
+ }
+ },
+ "resolve-from": {
+ "version": "4.0.0",
+ "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-4.0.0.tgz",
+ "integrity": "sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g==",
+ "dev": true
+ },
+ "resolve-url": {
+ "version": "0.2.1",
+ "resolved": "https://registry.npmjs.org/resolve-url/-/resolve-url-0.2.1.tgz",
+ "integrity": "sha1-LGN/53yJOv0qZj/iGqkIAGjiBSo=",
+ "dev": true,
+ "peer": true
+ },
+ "restore-cursor": {
+ "version": "3.1.0",
+ "resolved": "https://registry.npmjs.org/restore-cursor/-/restore-cursor-3.1.0.tgz",
+ "integrity": "sha512-l+sSefzHpj5qimhFSE5a8nufZYAM3sBSVMAPtYkmC+4EH2anSGaEMXSD0izRQbu9nfyQ9y5JrVmp7E8oZrUjvA==",
+ "dev": true,
+ "requires": {
+ "onetime": "^5.1.0",
+ "signal-exit": "^3.0.2"
+ }
+ },
+ "ret": {
+ "version": "0.1.15",
+ "resolved": "https://registry.npmjs.org/ret/-/ret-0.1.15.tgz",
+ "integrity": "sha512-TTlYpa+OL+vMMNG24xSlQGEJ3B/RzEfUlLct7b5G/ytav+wPrplCpVMFuwzXbkecJrb6IYo1iFb0S9v37754mg==",
+ "dev": true,
+ "peer": true
+ },
+ "reusify": {
+ "version": "1.0.4",
+ "resolved": "https://registry.npmjs.org/reusify/-/reusify-1.0.4.tgz",
+ "integrity": "sha512-U9nH88a3fc/ekCF1l0/UP1IosiuIjyTh7hBvXVMHYgVcfGvt897Xguj2UOLDeI5BG2m7/uwyaLVT6fbtCwTyzw==",
+ "dev": true
+ },
+ "rfdc": {
+ "version": "1.3.0",
+ "resolved": "https://registry.npmjs.org/rfdc/-/rfdc-1.3.0.tgz",
+ "integrity": "sha512-V2hovdzFbOi77/WajaSMXk2OLm+xNIeQdMMuB7icj7bk6zi2F8GGAxigcnDFpJHbNyNcgyJDiP+8nOrY5cZGrA==",
+ "dev": true
+ },
+ "rimraf": {
+ "version": "3.0.2",
+ "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-3.0.2.tgz",
+ "integrity": "sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA==",
+ "dev": true,
+ "requires": {
+ "glob": "^7.1.3"
+ }
+ },
+ "rivet-graphql": {
+ "version": "0.3.1",
+ "resolved": "https://registry.npmjs.org/rivet-graphql/-/rivet-graphql-0.3.1.tgz",
+ "integrity": "sha512-HEov02XhZ6H1jOME+mO8CZwliu/UtgZSHixYUwvQ7HSx3gk8EOVaQY5c3zscOYjZECvP8cR4+1Ob3KHWJRWEMw==",
+ "dev": true,
+ "requires": {
+ "graphql": "^15.3.0",
+ "graphql-request": "^3.0.0"
+ }
+ },
+ "rsvp": {
+ "version": "4.8.5",
+ "resolved": "https://registry.npmjs.org/rsvp/-/rsvp-4.8.5.tgz",
+ "integrity": "sha512-nfMOlASu9OnRJo1mbEk2cz0D56a1MBNrJ7orjRZQG10XDyuvwksKbuXNp6qa+kbn839HwjwhBzhFmdsaEAfauA==",
+ "dev": true,
+ "peer": true
+ },
+ "run-async": {
+ "version": "2.4.1",
+ "resolved": "https://registry.npmjs.org/run-async/-/run-async-2.4.1.tgz",
+ "integrity": "sha512-tvVnVv01b8c1RrA6Ep7JkStj85Guv/YrMcwqYQnwjsAS2cTmmPGBBjAjpCW7RrSodNSoE2/qg9O4bceNvUuDgQ==",
+ "dev": true
+ },
+ "run-parallel": {
+ "version": "1.2.0",
+ "resolved": "https://registry.npmjs.org/run-parallel/-/run-parallel-1.2.0.tgz",
+ "integrity": "sha512-5l4VyZR86LZ/lDxZTR6jqL8AFE2S0IFLMP26AbjsLVADxHdhB/c0GUsH+y39UfCi3dzz8OlQuPmnaJOMoDHQBA==",
+ "dev": true,
+ "requires": {
+ "queue-microtask": "^1.2.2"
+ }
+ },
+ "rxjs": {
+ "version": "6.6.7",
+ "resolved": "https://registry.npmjs.org/rxjs/-/rxjs-6.6.7.tgz",
+ "integrity": "sha512-hTdwr+7yYNIT5n4AMYp85KA6yw2Va0FLa3Rguvbpa4W3I5xynaBZo41cM3XM+4Q6fRMj3sBYIR1VAmZMXYJvRQ==",
+ "dev": true,
+ "requires": {
+ "tslib": "^1.9.0"
+ }
+ },
+ "safe-buffer": {
+ "version": "5.1.2",
+ "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz",
+ "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==",
+ "dev": true
+ },
+ "safe-regex": {
+ "version": "1.1.0",
+ "resolved": "https://registry.npmjs.org/safe-regex/-/safe-regex-1.1.0.tgz",
+ "integrity": "sha1-QKNmnzsHfR6UPURinhV91IAjvy4=",
+ "dev": true,
+ "peer": true,
+ "requires": {
+ "ret": "~0.1.10"
+ }
+ },
+ "safe-regex-test": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/safe-regex-test/-/safe-regex-test-1.0.0.tgz",
+ "integrity": "sha512-JBUUzyOgEwXQY1NuPtvcj/qcBDbDmEvWufhlnXZIm75DEHp+afM1r1ujJpJsV/gSM4t59tpDyPi1sd6ZaPFfsA==",
+ "dev": true,
+ "requires": {
+ "call-bind": "^1.0.2",
+ "get-intrinsic": "^1.1.3",
+ "is-regex": "^1.1.4"
+ }
+ },
+ "safer-buffer": {
+ "version": "2.1.2",
+ "resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz",
+ "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==",
+ "dev": true
+ },
+ "sane": {
+ "version": "4.1.0",
+ "resolved": "https://registry.npmjs.org/sane/-/sane-4.1.0.tgz",
+ "integrity": "sha512-hhbzAgTIX8O7SHfp2c8/kREfEn4qO/9q8C9beyY6+tvZ87EpoZ3i1RIEvp27YBswnNbY9mWd6paKVmKbAgLfZA==",
+ "dev": true,
+ "peer": true,
+ "requires": {
+ "@cnakazawa/watch": "^1.0.3",
+ "anymatch": "^2.0.0",
+ "capture-exit": "^2.0.0",
+ "exec-sh": "^0.3.2",
+ "execa": "^1.0.0",
+ "fb-watchman": "^2.0.0",
+ "micromatch": "^3.1.4",
+ "minimist": "^1.1.1",
+ "walker": "~1.0.5"
+ },
+ "dependencies": {
+ "anymatch": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/anymatch/-/anymatch-2.0.0.tgz",
+ "integrity": "sha512-5teOsQWABXHHBFP9y3skS5P3d/WfWXpv3FUpy+LorMrNYaT9pI4oLMQX7jzQ2KklNpGpWHzdCXTDT2Y3XGlZBw==",
+ "dev": true,
+ "peer": true,
+ "requires": {
+ "micromatch": "^3.1.4",
+ "normalize-path": "^2.1.1"
+ }
+ },
+ "braces": {
+ "version": "2.3.2",
+ "resolved": "https://registry.npmjs.org/braces/-/braces-2.3.2.tgz",
+ "integrity": "sha512-aNdbnj9P8PjdXU4ybaWLK2IF3jc/EoDYbC7AazW6to3TRsfXxscC9UXOB5iDiEQrkyIbWp2SLQda4+QAa7nc3w==",
+ "dev": true,
+ "peer": true,
+ "requires": {
+ "arr-flatten": "^1.1.0",
+ "array-unique": "^0.3.2",
+ "extend-shallow": "^2.0.1",
+ "fill-range": "^4.0.0",
+ "isobject": "^3.0.1",
+ "repeat-element": "^1.1.2",
+ "snapdragon": "^0.8.1",
+ "snapdragon-node": "^2.0.1",
+ "split-string": "^3.0.2",
+ "to-regex": "^3.0.1"
+ },
+ "dependencies": {
+ "extend-shallow": {
+ "version": "2.0.1",
+ "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz",
+ "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=",
+ "dev": true,
+ "peer": true,
+ "requires": {
+ "is-extendable": "^0.1.0"
+ }
+ }
+ }
+ },
+ "cross-spawn": {
+ "version": "6.0.5",
+ "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-6.0.5.tgz",
+ "integrity": "sha512-eTVLrBSt7fjbDygz805pMnstIs2VTBNkRm0qxZd+M7A5XDdxVRWO5MxGBXZhjY4cqLYLdtrGqRf8mBPmzwSpWQ==",
+ "dev": true,
+ "peer": true,
+ "requires": {
+ "nice-try": "^1.0.4",
+ "path-key": "^2.0.1",
+ "semver": "^5.5.0",
+ "shebang-command": "^1.2.0",
+ "which": "^1.2.9"
+ }
+ },
+ "execa": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/execa/-/execa-1.0.0.tgz",
+ "integrity": "sha512-adbxcyWV46qiHyvSp50TKt05tB4tK3HcmF7/nxfAdhnox83seTDbwnaqKO4sXRy7roHAIFqJP/Rw/AuEbX61LA==",
+ "dev": true,
+ "peer": true,
+ "requires": {
+ "cross-spawn": "^6.0.0",
+ "get-stream": "^4.0.0",
+ "is-stream": "^1.1.0",
+ "npm-run-path": "^2.0.0",
+ "p-finally": "^1.0.0",
+ "signal-exit": "^3.0.0",
+ "strip-eof": "^1.0.0"
+ }
+ },
+ "fill-range": {
+ "version": "4.0.0",
+ "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-4.0.0.tgz",
+ "integrity": "sha1-1USBHUKPmOsGpj3EAtJAPDKMOPc=",
+ "dev": true,
+ "peer": true,
+ "requires": {
+ "extend-shallow": "^2.0.1",
+ "is-number": "^3.0.0",
+ "repeat-string": "^1.6.1",
+ "to-regex-range": "^2.1.0"
+ },
+ "dependencies": {
+ "extend-shallow": {
+ "version": "2.0.1",
+ "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz",
+ "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=",
+ "dev": true,
+ "peer": true,
+ "requires": {
+ "is-extendable": "^0.1.0"
+ }
+ }
+ }
+ },
+ "get-stream": {
+ "version": "4.1.0",
+ "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-4.1.0.tgz",
+ "integrity": "sha512-GMat4EJ5161kIy2HevLlr4luNjBgvmj413KaQA7jt4V8B4RDsfpHk7WQ9GVqfYyyx8OS/L66Kox+rJRNklLK7w==",
+ "dev": true,
+ "peer": true,
+ "requires": {
+ "pump": "^3.0.0"
+ }
+ },
+ "is-buffer": {
+ "version": "1.1.6",
+ "resolved": "https://registry.npmjs.org/is-buffer/-/is-buffer-1.1.6.tgz",
+ "integrity": "sha512-NcdALwpXkTm5Zvvbk7owOUSvVvBKDgKP5/ewfXEznmQFfs4ZRmanOeKBTjRVjka3QFoN6XJ+9F3USqfHqTaU5w==",
+ "dev": true,
+ "peer": true
+ },
+ "is-extendable": {
+ "version": "0.1.1",
+ "resolved": "https://registry.npmjs.org/is-extendable/-/is-extendable-0.1.1.tgz",
+ "integrity": "sha1-YrEQ4omkcUGOPsNqYX1HLjAd/Ik=",
+ "dev": true,
+ "peer": true
+ },
+ "is-number": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/is-number/-/is-number-3.0.0.tgz",
+ "integrity": "sha1-JP1iAaR4LPUFYcgQJ2r8fRLXEZU=",
+ "dev": true,
+ "peer": true,
+ "requires": {
+ "kind-of": "^3.0.2"
+ },
+ "dependencies": {
+ "kind-of": {
+ "version": "3.2.2",
+ "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz",
+ "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=",
+ "dev": true,
+ "peer": true,
+ "requires": {
+ "is-buffer": "^1.1.5"
+ }
+ }
+ }
+ },
+ "is-stream": {
+ "version": "1.1.0",
+ "resolved": "https://registry.npmjs.org/is-stream/-/is-stream-1.1.0.tgz",
+ "integrity": "sha1-EtSj3U5o4Lec6428hBc66A2RykQ=",
+ "dev": true,
+ "peer": true
+ },
+ "micromatch": {
+ "version": "3.1.10",
+ "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-3.1.10.tgz",
+ "integrity": "sha512-MWikgl9n9M3w+bpsY3He8L+w9eF9338xRl8IAO5viDizwSzziFEyUzo2xrrloB64ADbTf8uA8vRqqttDTOmccg==",
+ "dev": true,
+ "peer": true,
+ "requires": {
+ "arr-diff": "^4.0.0",
+ "array-unique": "^0.3.2",
+ "braces": "^2.3.1",
+ "define-property": "^2.0.2",
+ "extend-shallow": "^3.0.2",
+ "extglob": "^2.0.4",
+ "fragment-cache": "^0.2.1",
+ "kind-of": "^6.0.2",
+ "nanomatch": "^1.2.9",
+ "object.pick": "^1.3.0",
+ "regex-not": "^1.0.0",
+ "snapdragon": "^0.8.1",
+ "to-regex": "^3.0.2"
+ }
+ },
+ "normalize-path": {
+ "version": "2.1.1",
+ "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-2.1.1.tgz",
+ "integrity": "sha1-GrKLVW4Zg2Oowab35vogE3/mrtk=",
+ "dev": true,
+ "peer": true,
+ "requires": {
+ "remove-trailing-separator": "^1.0.1"
+ }
+ },
+ "npm-run-path": {
+ "version": "2.0.2",
+ "resolved": "https://registry.npmjs.org/npm-run-path/-/npm-run-path-2.0.2.tgz",
+ "integrity": "sha1-NakjLfo11wZ7TLLd8jV7GHFTbF8=",
+ "dev": true,
+ "peer": true,
+ "requires": {
+ "path-key": "^2.0.0"
+ }
+ },
+ "path-key": {
+ "version": "2.0.1",
+ "resolved": "https://registry.npmjs.org/path-key/-/path-key-2.0.1.tgz",
+ "integrity": "sha1-QRyttXTFoUDTpLGRDUDYDMn0C0A=",
+ "dev": true,
+ "peer": true
+ },
+ "semver": {
+ "version": "5.7.1",
+ "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz",
+ "integrity": "sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==",
+ "dev": true,
+ "peer": true
+ },
+ "shebang-command": {
+ "version": "1.2.0",
+ "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-1.2.0.tgz",
+ "integrity": "sha1-RKrGW2lbAzmJaMOfNj/uXer98eo=",
+ "dev": true,
+ "peer": true,
+ "requires": {
+ "shebang-regex": "^1.0.0"
+ }
+ },
+ "shebang-regex": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-1.0.0.tgz",
+ "integrity": "sha1-2kL0l0DAtC2yypcoVxyxkMmO/qM=",
+ "dev": true,
+ "peer": true
+ },
+ "to-regex-range": {
+ "version": "2.1.1",
+ "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-2.1.1.tgz",
+ "integrity": "sha1-fIDBe53+vlmeJzZ+DU3VWQFB2zg=",
+ "dev": true,
+ "peer": true,
+ "requires": {
+ "is-number": "^3.0.0",
+ "repeat-string": "^1.6.1"
+ }
+ },
+ "which": {
+ "version": "1.3.1",
+ "resolved": "https://registry.npmjs.org/which/-/which-1.3.1.tgz",
+ "integrity": "sha512-HxJdYWq1MTIQbJ3nw0cqssHoTNU267KlrDuGZ1WYlxDStUtKUhOaJmh112/TZmHxxUfuJqPXSOm7tDyas0OSIQ==",
+ "dev": true,
+ "peer": true,
+ "requires": {
+ "isexe": "^2.0.0"
+ }
+ }
+ }
+ },
+ "saxes": {
+ "version": "5.0.1",
+ "resolved": "https://registry.npmjs.org/saxes/-/saxes-5.0.1.tgz",
+ "integrity": "sha512-5LBh1Tls8c9xgGjw3QrMwETmTMVk0oFgvrFSvWx62llR2hcEInrKNZ2GZCCuuy2lvWrdl5jhbpeqc5hRYKFOcw==",
+ "dev": true,
+ "peer": true,
+ "requires": {
+ "xmlchars": "^2.2.0"
+ }
+ },
+ "scheduler": {
+ "version": "0.21.0",
+ "resolved": "https://registry.npmjs.org/scheduler/-/scheduler-0.21.0.tgz",
+ "integrity": "sha512-1r87x5fz9MXqswA2ERLo0EbOAU74DpIUO090gIasYTqlVoJeMcl+Z1Rg7WHz+qtPujhS/hGIt9kxZOYBV3faRQ==",
+ "dev": true,
+ "peer": true,
+ "requires": {
+ "loose-envify": "^1.1.0"
+ }
+ },
+ "semver": {
+ "version": "7.3.7",
+ "resolved": "https://registry.npmjs.org/semver/-/semver-7.3.7.tgz",
+ "integrity": "sha512-QlYTucUYOews+WeEujDoEGziz4K6c47V/Bd+LjSSYcA94p+DmINdf7ncaUinThfvZyu13lN9OY1XDxt8C0Tw0g==",
+ "dev": true,
+ "requires": {
+ "lru-cache": "^6.0.0"
+ }
+ },
+ "semver-compare": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/semver-compare/-/semver-compare-1.0.0.tgz",
+ "integrity": "sha1-De4hahyUGrN+nvsXiPavxf9VN/w=",
+ "dev": true
+ },
+ "semver-regex": {
+ "version": "3.1.4",
+ "resolved": "https://registry.npmjs.org/semver-regex/-/semver-regex-3.1.4.tgz",
+ "integrity": "sha512-6IiqeZNgq01qGf0TId0t3NvKzSvUsjcpdEO3AQNeIjR6A2+ckTnQlDpl4qu1bjRv0RzN3FP9hzFmws3lKqRWkA==",
+ "dev": true
+ },
+ "set-blocking": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/set-blocking/-/set-blocking-2.0.0.tgz",
+ "integrity": "sha1-BF+XgtARrppoA93TgrJDkrPYkPc=",
+ "dev": true,
+ "peer": true
+ },
+ "set-value": {
+ "version": "2.0.1",
+ "resolved": "https://registry.npmjs.org/set-value/-/set-value-2.0.1.tgz",
+ "integrity": "sha512-JxHc1weCN68wRY0fhCoXpyK55m/XPHafOmK4UWD7m2CI14GMcFypt4w/0+NV5f/ZMby2F6S2wwA7fgynh9gWSw==",
+ "dev": true,
+ "peer": true,
+ "requires": {
+ "extend-shallow": "^2.0.1",
+ "is-extendable": "^0.1.1",
+ "is-plain-object": "^2.0.3",
+ "split-string": "^3.0.1"
+ },
+ "dependencies": {
+ "extend-shallow": {
+ "version": "2.0.1",
+ "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz",
+ "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=",
+ "dev": true,
+ "peer": true,
+ "requires": {
+ "is-extendable": "^0.1.0"
+ }
+ },
+ "is-extendable": {
+ "version": "0.1.1",
+ "resolved": "https://registry.npmjs.org/is-extendable/-/is-extendable-0.1.1.tgz",
+ "integrity": "sha1-YrEQ4omkcUGOPsNqYX1HLjAd/Ik=",
+ "dev": true,
+ "peer": true
+ }
+ }
+ },
+ "shebang-command": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-2.0.0.tgz",
+ "integrity": "sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==",
+ "dev": true,
+ "requires": {
+ "shebang-regex": "^3.0.0"
+ }
+ },
+ "shebang-regex": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-3.0.0.tgz",
+ "integrity": "sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==",
+ "dev": true
+ },
+ "shellwords": {
+ "version": "0.1.1",
+ "resolved": "https://registry.npmjs.org/shellwords/-/shellwords-0.1.1.tgz",
+ "integrity": "sha512-vFwSUfQvqybiICwZY5+DAWIPLKsWO31Q91JSKl3UYv+K5c2QRPzn0qzec6QPu1Qc9eHYItiP3NdJqNVqetYAww==",
+ "dev": true,
+ "optional": true,
+ "peer": true
+ },
+ "side-channel": {
+ "version": "1.0.4",
+ "resolved": "https://registry.npmjs.org/side-channel/-/side-channel-1.0.4.tgz",
+ "integrity": "sha512-q5XPytqFEIKHkGdiMIrY10mvLRvnQh42/+GoBlFW3b2LXLE2xxJpZFdm94we0BaoV3RwJyGqg5wS7epxTv0Zvw==",
+ "dev": true,
+ "requires": {
+ "call-bind": "^1.0.0",
+ "get-intrinsic": "^1.0.2",
+ "object-inspect": "^1.9.0"
+ }
+ },
+ "signal-exit": {
+ "version": "3.0.7",
+ "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.7.tgz",
+ "integrity": "sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ==",
+ "dev": true
+ },
+ "signale": {
+ "version": "1.4.0",
+ "resolved": "https://registry.npmjs.org/signale/-/signale-1.4.0.tgz",
+ "integrity": "sha512-iuh+gPf28RkltuJC7W5MRi6XAjTDCAPC/prJUpQoG4vIP3MJZ+GTydVnodXA7pwvTKb2cA0m9OFZW/cdWy/I/w==",
+ "dev": true,
+ "requires": {
+ "chalk": "^2.3.2",
+ "figures": "^2.0.0",
+ "pkg-conf": "^2.1.0"
+ },
+ "dependencies": {
+ "ansi-styles": {
+ "version": "3.2.1",
+ "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz",
+ "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==",
+ "dev": true,
+ "requires": {
+ "color-convert": "^1.9.0"
+ }
+ },
+ "chalk": {
+ "version": "2.4.2",
+ "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz",
+ "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==",
+ "dev": true,
+ "requires": {
+ "ansi-styles": "^3.2.1",
+ "escape-string-regexp": "^1.0.5",
+ "supports-color": "^5.3.0"
+ }
+ },
+ "color-convert": {
+ "version": "1.9.3",
+ "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz",
+ "integrity": "sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==",
+ "dev": true,
+ "requires": {
+ "color-name": "1.1.3"
+ }
+ },
+ "color-name": {
+ "version": "1.1.3",
+ "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz",
+ "integrity": "sha1-p9BVi9icQveV3UIyj3QIMcpTvCU=",
+ "dev": true
+ },
+ "figures": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/figures/-/figures-2.0.0.tgz",
+ "integrity": "sha1-OrGi0qYsi/tDGgyUy3l6L84nyWI=",
+ "dev": true,
+ "requires": {
+ "escape-string-regexp": "^1.0.5"
+ }
+ },
+ "has-flag": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz",
+ "integrity": "sha1-tdRU3CGZriJWmfNGfloH87lVuv0=",
+ "dev": true
+ },
+ "supports-color": {
+ "version": "5.5.0",
+ "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz",
+ "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==",
+ "dev": true,
+ "requires": {
+ "has-flag": "^3.0.0"
+ }
+ }
+ }
+ },
+ "sisteransi": {
+ "version": "1.0.5",
+ "resolved": "https://registry.npmjs.org/sisteransi/-/sisteransi-1.0.5.tgz",
+ "integrity": "sha512-bLGGlR1QxBcynn2d5YmDX4MGjlZvy2MRBDRNHLJ8VI6l6+9FUiyTFNJ0IveOSP0bcXgVDPRcfGqA0pjaqUpfVg==",
+ "dev": true,
+ "peer": true
+ },
+ "slash": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/slash/-/slash-3.0.0.tgz",
+ "integrity": "sha512-g9Q1haeby36OSStwb4ntCGGGaKsaVSjQ68fBxoQcutl5fS1vuY18H3wSt3jFyFtrkx+Kz0V1G85A4MyAdDMi2Q==",
+ "dev": true
+ },
+ "slice-ansi": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/slice-ansi/-/slice-ansi-3.0.0.tgz",
+ "integrity": "sha512-pSyv7bSTC7ig9Dcgbw9AuRNUb5k5V6oDudjZoMBSr13qpLBG7tB+zgCkARjq7xIUgdz5P1Qe8u+rSGdouOOIyQ==",
+ "dev": true,
+ "requires": {
+ "ansi-styles": "^4.0.0",
+ "astral-regex": "^2.0.0",
+ "is-fullwidth-code-point": "^3.0.0"
+ }
+ },
+ "slugify": {
+ "version": "1.4.6",
+ "resolved": "https://registry.npmjs.org/slugify/-/slugify-1.4.6.tgz",
+ "integrity": "sha512-ZdJIgv9gdrYwhXqxsH9pv7nXxjUEyQ6nqhngRxoAAOlmMGA28FDq5O4/5US4G2/Nod7d1ovNcgURQJ7kHq50KQ==",
+ "dev": true
+ },
+ "snapdragon": {
+ "version": "0.8.2",
+ "resolved": "https://registry.npmjs.org/snapdragon/-/snapdragon-0.8.2.tgz",
+ "integrity": "sha512-FtyOnWN/wCHTVXOMwvSv26d+ko5vWlIDD6zoUJ7LW8vh+ZBC8QdljveRP+crNrtBwioEUWy/4dMtbBjA4ioNlg==",
+ "dev": true,
+ "peer": true,
+ "requires": {
+ "base": "^0.11.1",
+ "debug": "^2.2.0",
+ "define-property": "^0.2.5",
+ "extend-shallow": "^2.0.1",
+ "map-cache": "^0.2.2",
+ "source-map": "^0.5.6",
+ "source-map-resolve": "^0.5.0",
+ "use": "^3.1.0"
+ },
+ "dependencies": {
+ "debug": {
+ "version": "2.6.9",
+ "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz",
+ "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==",
+ "dev": true,
+ "peer": true,
+ "requires": {
+ "ms": "2.0.0"
+ }
+ },
+ "define-property": {
+ "version": "0.2.5",
+ "resolved": "https://registry.npmjs.org/define-property/-/define-property-0.2.5.tgz",
+ "integrity": "sha1-w1se+RjsPJkPmlvFe+BKrOxcgRY=",
+ "dev": true,
+ "peer": true,
+ "requires": {
+ "is-descriptor": "^0.1.0"
+ }
+ },
+ "extend-shallow": {
+ "version": "2.0.1",
+ "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz",
+ "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=",
+ "dev": true,
+ "peer": true,
+ "requires": {
+ "is-extendable": "^0.1.0"
+ }
+ },
+ "is-accessor-descriptor": {
+ "version": "0.1.6",
+ "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-0.1.6.tgz",
+ "integrity": "sha1-qeEss66Nh2cn7u84Q/igiXtcmNY=",
+ "dev": true,
+ "peer": true,
+ "requires": {
+ "kind-of": "^3.0.2"
+ },
+ "dependencies": {
+ "kind-of": {
+ "version": "3.2.2",
+ "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz",
+ "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=",
+ "dev": true,
+ "peer": true,
+ "requires": {
+ "is-buffer": "^1.1.5"
+ }
+ }
+ }
+ },
+ "is-buffer": {
+ "version": "1.1.6",
+ "resolved": "https://registry.npmjs.org/is-buffer/-/is-buffer-1.1.6.tgz",
+ "integrity": "sha512-NcdALwpXkTm5Zvvbk7owOUSvVvBKDgKP5/ewfXEznmQFfs4ZRmanOeKBTjRVjka3QFoN6XJ+9F3USqfHqTaU5w==",
+ "dev": true,
+ "peer": true
+ },
+ "is-data-descriptor": {
+ "version": "0.1.4",
+ "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-0.1.4.tgz",
+ "integrity": "sha1-C17mSDiOLIYCgueT8YVv7D8wG1Y=",
+ "dev": true,
+ "peer": true,
+ "requires": {
+ "kind-of": "^3.0.2"
+ },
+ "dependencies": {
+ "kind-of": {
+ "version": "3.2.2",
+ "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz",
+ "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=",
+ "dev": true,
+ "peer": true,
+ "requires": {
+ "is-buffer": "^1.1.5"
+ }
+ }
+ }
+ },
+ "is-descriptor": {
+ "version": "0.1.6",
+ "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-0.1.6.tgz",
+ "integrity": "sha512-avDYr0SB3DwO9zsMov0gKCESFYqCnE4hq/4z3TdUlukEy5t9C0YRq7HLrsN52NAcqXKaepeCD0n+B0arnVG3Hg==",
+ "dev": true,
+ "peer": true,
+ "requires": {
+ "is-accessor-descriptor": "^0.1.6",
+ "is-data-descriptor": "^0.1.4",
+ "kind-of": "^5.0.0"
+ }
+ },
+ "is-extendable": {
+ "version": "0.1.1",
+ "resolved": "https://registry.npmjs.org/is-extendable/-/is-extendable-0.1.1.tgz",
+ "integrity": "sha1-YrEQ4omkcUGOPsNqYX1HLjAd/Ik=",
+ "dev": true,
+ "peer": true
+ },
+ "kind-of": {
+ "version": "5.1.0",
+ "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-5.1.0.tgz",
+ "integrity": "sha512-NGEErnH6F2vUuXDh+OlbcKW7/wOcfdRHaZ7VWtqCztfHri/++YKmP51OdWeGPuqCOba6kk2OTe5d02VmTB80Pw==",
+ "dev": true,
+ "peer": true
+ },
+ "ms": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz",
+ "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=",
+ "dev": true,
+ "peer": true
+ },
+ "source-map": {
+ "version": "0.5.7",
+ "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz",
+ "integrity": "sha1-igOdLRAh0i0eoUyA2OpGi6LvP8w=",
+ "dev": true,
+ "peer": true
+ }
+ }
+ },
+ "snapdragon-node": {
+ "version": "2.1.1",
+ "resolved": "https://registry.npmjs.org/snapdragon-node/-/snapdragon-node-2.1.1.tgz",
+ "integrity": "sha512-O27l4xaMYt/RSQ5TR3vpWCAB5Kb/czIcqUFOM/C4fYcLnbZUc1PkjTAMjof2pBWaSTwOUd6qUHcFGVGj7aIwnw==",
+ "dev": true,
+ "peer": true,
+ "requires": {
+ "define-property": "^1.0.0",
+ "isobject": "^3.0.0",
+ "snapdragon-util": "^3.0.1"
+ },
+ "dependencies": {
+ "define-property": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/define-property/-/define-property-1.0.0.tgz",
+ "integrity": "sha1-dp66rz9KY6rTr56NMEybvnm/sOY=",
+ "dev": true,
+ "peer": true,
+ "requires": {
+ "is-descriptor": "^1.0.0"
+ }
+ }
+ }
+ },
+ "snapdragon-util": {
+ "version": "3.0.1",
+ "resolved": "https://registry.npmjs.org/snapdragon-util/-/snapdragon-util-3.0.1.tgz",
+ "integrity": "sha512-mbKkMdQKsjX4BAL4bRYTj21edOf8cN7XHdYUJEe+Zn99hVEYcMvKPct1IqNe7+AZPirn8BCDOQBHQZknqmKlZQ==",
+ "dev": true,
+ "peer": true,
+ "requires": {
+ "kind-of": "^3.2.0"
+ },
+ "dependencies": {
+ "is-buffer": {
+ "version": "1.1.6",
+ "resolved": "https://registry.npmjs.org/is-buffer/-/is-buffer-1.1.6.tgz",
+ "integrity": "sha512-NcdALwpXkTm5Zvvbk7owOUSvVvBKDgKP5/ewfXEznmQFfs4ZRmanOeKBTjRVjka3QFoN6XJ+9F3USqfHqTaU5w==",
+ "dev": true,
+ "peer": true
+ },
+ "kind-of": {
+ "version": "3.2.2",
+ "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz",
+ "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=",
+ "dev": true,
+ "peer": true,
+ "requires": {
+ "is-buffer": "^1.1.5"
+ }
+ }
+ }
+ },
+ "source-map": {
+ "version": "0.6.1",
+ "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz",
+ "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==",
+ "dev": true
+ },
+ "source-map-js": {
+ "version": "1.0.2",
+ "resolved": "https://registry.npmjs.org/source-map-js/-/source-map-js-1.0.2.tgz",
+ "integrity": "sha512-R0XvVJ9WusLiqTCEiGCmICCMplcCkIwwR11mOSD9CR5u+IXYdiseeEuXCVAjS54zqwkLcPNnmU4OeJ6tUrWhDw==",
+ "dev": true
+ },
+ "source-map-resolve": {
+ "version": "0.5.3",
+ "resolved": "https://registry.npmjs.org/source-map-resolve/-/source-map-resolve-0.5.3.tgz",
+ "integrity": "sha512-Htz+RnsXWk5+P2slx5Jh3Q66vhQj1Cllm0zvnaY98+NFx+Dv2CF/f5O/t8x+KaNdrdIAsruNzoh/KpialbqAnw==",
+ "dev": true,
+ "peer": true,
+ "requires": {
+ "atob": "^2.1.2",
+ "decode-uri-component": "^0.2.0",
+ "resolve-url": "^0.2.1",
+ "source-map-url": "^0.4.0",
+ "urix": "^0.1.0"
+ }
+ },
+ "source-map-support": {
+ "version": "0.5.21",
+ "resolved": "https://registry.npmjs.org/source-map-support/-/source-map-support-0.5.21.tgz",
+ "integrity": "sha512-uBHU3L3czsIyYXKX88fdrGovxdSCoTGDRZ6SYXtSRxLZUzHg5P/66Ht6uoUlHu9EZod+inXhKo3qQgwXUT/y1w==",
+ "dev": true,
+ "peer": true,
+ "requires": {
+ "buffer-from": "^1.0.0",
+ "source-map": "^0.6.0"
+ }
+ },
+ "source-map-url": {
+ "version": "0.4.1",
+ "resolved": "https://registry.npmjs.org/source-map-url/-/source-map-url-0.4.1.tgz",
+ "integrity": "sha512-cPiFOTLUKvJFIg4SKVScy4ilPPW6rFgMgfuZJPNoDuMs3nC1HbMUycBoJw77xFIp6z1UJQJOfx6C9GMH80DiTw==",
+ "dev": true,
+ "peer": true
+ },
+ "spdx-correct": {
+ "version": "3.1.1",
+ "resolved": "https://registry.npmjs.org/spdx-correct/-/spdx-correct-3.1.1.tgz",
+ "integrity": "sha512-cOYcUWwhCuHCXi49RhFRCyJEK3iPj1Ziz9DpViV3tbZOwXD49QzIN3MpOLJNxh2qwq2lJJZaKMVw9qNi4jTC0w==",
+ "dev": true,
+ "requires": {
+ "spdx-expression-parse": "^3.0.0",
+ "spdx-license-ids": "^3.0.0"
+ }
+ },
+ "spdx-exceptions": {
+ "version": "2.3.0",
+ "resolved": "https://registry.npmjs.org/spdx-exceptions/-/spdx-exceptions-2.3.0.tgz",
+ "integrity": "sha512-/tTrYOC7PPI1nUAgx34hUpqXuyJG+DTHJTnIULG4rDygi4xu/tfgmq1e1cIRwRzwZgo4NLySi+ricLkZkw4i5A==",
+ "dev": true
+ },
+ "spdx-expression-parse": {
+ "version": "3.0.1",
+ "resolved": "https://registry.npmjs.org/spdx-expression-parse/-/spdx-expression-parse-3.0.1.tgz",
+ "integrity": "sha512-cbqHunsQWnJNE6KhVSMsMeH5H/L9EpymbzqTQ3uLwNCLZ1Q481oWaofqH7nO6V07xlXwY6PhQdQ2IedWx/ZK4Q==",
+ "dev": true,
+ "requires": {
+ "spdx-exceptions": "^2.1.0",
+ "spdx-license-ids": "^3.0.0"
+ }
+ },
+ "spdx-license-ids": {
+ "version": "3.0.11",
+ "resolved": "https://registry.npmjs.org/spdx-license-ids/-/spdx-license-ids-3.0.11.tgz",
+ "integrity": "sha512-Ctl2BrFiM0X3MANYgj3CkygxhRmr9mi6xhejbdO960nF6EDJApTYpn0BQnDKlnNBULKiCN1n3w9EBkHK8ZWg+g==",
+ "dev": true
+ },
+ "specificity": {
+ "version": "0.4.1",
+ "resolved": "https://registry.npmjs.org/specificity/-/specificity-0.4.1.tgz",
+ "integrity": "sha512-1klA3Gi5PD1Wv9Q0wUoOQN1IWAuPu0D1U03ThXTr0cJ20+/iq2tHSDnK7Kk/0LXJ1ztUB2/1Os0wKmfyNgUQfg==",
+ "dev": true
+ },
+ "split-string": {
+ "version": "3.1.0",
+ "resolved": "https://registry.npmjs.org/split-string/-/split-string-3.1.0.tgz",
+ "integrity": "sha512-NzNVhJDYpwceVVii8/Hu6DKfD2G+NrQHlS/V/qgv763EYudVwEcMQNxd2lh+0VrUByXN/oJkl5grOhYWvQUYiw==",
+ "dev": true,
+ "peer": true,
+ "requires": {
+ "extend-shallow": "^3.0.0"
+ }
+ },
+ "sprintf-js": {
+ "version": "1.0.3",
+ "resolved": "https://registry.npmjs.org/sprintf-js/-/sprintf-js-1.0.3.tgz",
+ "integrity": "sha1-BOaSb2YolTVPPdAVIDYzuFcpfiw=",
+ "dev": true,
+ "peer": true
+ },
+ "stack-utils": {
+ "version": "2.0.5",
+ "resolved": "https://registry.npmjs.org/stack-utils/-/stack-utils-2.0.5.tgz",
+ "integrity": "sha512-xrQcmYhOsn/1kX+Vraq+7j4oE2j/6BFscZ0etmYg81xuM8Gq0022Pxb8+IqgOFUIaxHs0KaSb7T1+OegiNrNFA==",
+ "dev": true,
+ "peer": true,
+ "requires": {
+ "escape-string-regexp": "^2.0.0"
+ },
+ "dependencies": {
+ "escape-string-regexp": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-2.0.0.tgz",
+ "integrity": "sha512-UpzcLCXolUWcNu5HtVMHYdXJjArjsF9C0aNnquZYY4uW/Vu0miy5YoWvbV345HauVvcAUnpRuhMMcqTcGOY2+w==",
+ "dev": true,
+ "peer": true
+ }
+ }
+ },
+ "state-toggle": {
+ "version": "1.0.3",
+ "resolved": "https://registry.npmjs.org/state-toggle/-/state-toggle-1.0.3.tgz",
+ "integrity": "sha512-d/5Z4/2iiCnHw6Xzghyhb+GcmF89bxwgXG60wjIiZaxnymbyOmI8Hk4VqHXiVVp6u2ysaskFfXg3ekCj4WNftQ==",
+ "dev": true
+ },
+ "static-extend": {
+ "version": "0.1.2",
+ "resolved": "https://registry.npmjs.org/static-extend/-/static-extend-0.1.2.tgz",
+ "integrity": "sha1-YICcOcv/VTNyJv1eC1IPNB8ftcY=",
+ "dev": true,
+ "peer": true,
+ "requires": {
+ "define-property": "^0.2.5",
+ "object-copy": "^0.1.0"
+ },
+ "dependencies": {
+ "define-property": {
+ "version": "0.2.5",
+ "resolved": "https://registry.npmjs.org/define-property/-/define-property-0.2.5.tgz",
+ "integrity": "sha1-w1se+RjsPJkPmlvFe+BKrOxcgRY=",
+ "dev": true,
+ "peer": true,
+ "requires": {
+ "is-descriptor": "^0.1.0"
+ }
+ },
+ "is-accessor-descriptor": {
+ "version": "0.1.6",
+ "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-0.1.6.tgz",
+ "integrity": "sha1-qeEss66Nh2cn7u84Q/igiXtcmNY=",
+ "dev": true,
+ "peer": true,
+ "requires": {
+ "kind-of": "^3.0.2"
+ },
+ "dependencies": {
+ "kind-of": {
+ "version": "3.2.2",
+ "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz",
+ "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=",
+ "dev": true,
+ "peer": true,
+ "requires": {
+ "is-buffer": "^1.1.5"
+ }
+ }
+ }
+ },
+ "is-buffer": {
+ "version": "1.1.6",
+ "resolved": "https://registry.npmjs.org/is-buffer/-/is-buffer-1.1.6.tgz",
+ "integrity": "sha512-NcdALwpXkTm5Zvvbk7owOUSvVvBKDgKP5/ewfXEznmQFfs4ZRmanOeKBTjRVjka3QFoN6XJ+9F3USqfHqTaU5w==",
+ "dev": true,
+ "peer": true
+ },
+ "is-data-descriptor": {
+ "version": "0.1.4",
+ "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-0.1.4.tgz",
+ "integrity": "sha1-C17mSDiOLIYCgueT8YVv7D8wG1Y=",
+ "dev": true,
+ "peer": true,
+ "requires": {
+ "kind-of": "^3.0.2"
+ },
+ "dependencies": {
+ "kind-of": {
+ "version": "3.2.2",
+ "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz",
+ "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=",
+ "dev": true,
+ "peer": true,
+ "requires": {
+ "is-buffer": "^1.1.5"
+ }
+ }
+ }
+ },
+ "is-descriptor": {
+ "version": "0.1.6",
+ "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-0.1.6.tgz",
+ "integrity": "sha512-avDYr0SB3DwO9zsMov0gKCESFYqCnE4hq/4z3TdUlukEy5t9C0YRq7HLrsN52NAcqXKaepeCD0n+B0arnVG3Hg==",
+ "dev": true,
+ "peer": true,
+ "requires": {
+ "is-accessor-descriptor": "^0.1.6",
+ "is-data-descriptor": "^0.1.4",
+ "kind-of": "^5.0.0"
+ }
+ },
+ "kind-of": {
+ "version": "5.1.0",
+ "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-5.1.0.tgz",
+ "integrity": "sha512-NGEErnH6F2vUuXDh+OlbcKW7/wOcfdRHaZ7VWtqCztfHri/++YKmP51OdWeGPuqCOba6kk2OTe5d02VmTB80Pw==",
+ "dev": true,
+ "peer": true
+ }
+ }
+ },
+ "stop-iteration-iterator": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/stop-iteration-iterator/-/stop-iteration-iterator-1.0.0.tgz",
+ "integrity": "sha512-iCGQj+0l0HOdZ2AEeBADlsRC+vsnDsZsbdSiH1yNSjcfKM7fdpCMfqAL/dwF5BLiw/XhRft/Wax6zQbhq2BcjQ==",
+ "dev": true,
+ "requires": {
+ "internal-slot": "^1.0.4"
+ }
+ },
+ "string_decoder": {
+ "version": "1.3.0",
+ "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.3.0.tgz",
+ "integrity": "sha512-hkRX8U1WjJFd8LsDJ2yQ/wWWxaopEsABU1XfkM8A+j0+85JAGppt16cr1Whg6KIbb4okU6Mql6BOj+uup/wKeA==",
+ "dev": true,
+ "requires": {
+ "safe-buffer": "~5.2.0"
+ },
+ "dependencies": {
+ "safe-buffer": {
+ "version": "5.2.1",
+ "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz",
+ "integrity": "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==",
+ "dev": true
+ }
+ }
+ },
+ "string-argv": {
+ "version": "0.3.1",
+ "resolved": "https://registry.npmjs.org/string-argv/-/string-argv-0.3.1.tgz",
+ "integrity": "sha512-a1uQGz7IyVy9YwhqjZIZu1c8JO8dNIe20xBmSS6qu9kv++k3JGzCVmprbNN5Kn+BgzD5E7YYwg1CcjuJMRNsvg==",
+ "dev": true
+ },
+ "string-length": {
+ "version": "4.0.2",
+ "resolved": "https://registry.npmjs.org/string-length/-/string-length-4.0.2.tgz",
+ "integrity": "sha512-+l6rNN5fYHNhZZy41RXsYptCjA2Igmq4EG7kZAYFQI1E1VTXarr6ZPXBg6eq7Y6eK4FEhY6AJlyuFIb/v/S0VQ==",
+ "dev": true,
+ "peer": true,
+ "requires": {
+ "char-regex": "^1.0.2",
+ "strip-ansi": "^6.0.0"
+ }
+ },
+ "string-width": {
+ "version": "4.2.3",
+ "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz",
+ "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==",
+ "dev": true,
+ "requires": {
+ "emoji-regex": "^8.0.0",
+ "is-fullwidth-code-point": "^3.0.0",
+ "strip-ansi": "^6.0.1"
+ },
+ "dependencies": {
+ "emoji-regex": {
+ "version": "8.0.0",
+ "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz",
+ "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==",
+ "dev": true
+ }
+ }
+ },
+ "string.prototype.matchall": {
+ "version": "4.0.8",
+ "resolved": "https://registry.npmjs.org/string.prototype.matchall/-/string.prototype.matchall-4.0.8.tgz",
+ "integrity": "sha512-6zOCOcJ+RJAQshcTvXPHoxoQGONa3e/Lqx90wUA+wEzX78sg5Bo+1tQo4N0pohS0erG9qtCqJDjNCQBjeWVxyg==",
+ "dev": true,
+ "requires": {
+ "call-bind": "^1.0.2",
+ "define-properties": "^1.1.4",
+ "es-abstract": "^1.20.4",
+ "get-intrinsic": "^1.1.3",
+ "has-symbols": "^1.0.3",
+ "internal-slot": "^1.0.3",
+ "regexp.prototype.flags": "^1.4.3",
+ "side-channel": "^1.0.4"
+ }
+ },
+ "string.prototype.trim": {
+ "version": "1.2.7",
+ "resolved": "https://registry.npmjs.org/string.prototype.trim/-/string.prototype.trim-1.2.7.tgz",
+ "integrity": "sha512-p6TmeT1T3411M8Cgg9wBTMRtY2q9+PNy9EV1i2lIXUN/btt763oIfxwN3RR8VU6wHX8j/1CFy0L+YuThm6bgOg==",
+ "dev": true,
+ "requires": {
+ "call-bind": "^1.0.2",
+ "define-properties": "^1.1.4",
+ "es-abstract": "^1.20.4"
+ }
+ },
+ "string.prototype.trimend": {
+ "version": "1.0.6",
+ "resolved": "https://registry.npmjs.org/string.prototype.trimend/-/string.prototype.trimend-1.0.6.tgz",
+ "integrity": "sha512-JySq+4mrPf9EsDBEDYMOb/lM7XQLulwg5R/m1r0PXEFqrV0qHvl58sdTilSXtKOflCsK2E8jxf+GKC0T07RWwQ==",
+ "dev": true,
+ "requires": {
+ "call-bind": "^1.0.2",
+ "define-properties": "^1.1.4",
+ "es-abstract": "^1.20.4"
+ }
+ },
+ "string.prototype.trimstart": {
+ "version": "1.0.6",
+ "resolved": "https://registry.npmjs.org/string.prototype.trimstart/-/string.prototype.trimstart-1.0.6.tgz",
+ "integrity": "sha512-omqjMDaY92pbn5HOX7f9IccLA+U1tA9GvtU4JrodiXFfYB7jPzzHpRzpglLAjtUV6bB557zwClJezTqnAiYnQA==",
+ "dev": true,
+ "requires": {
+ "call-bind": "^1.0.2",
+ "define-properties": "^1.1.4",
+ "es-abstract": "^1.20.4"
+ }
+ },
+ "stringify-entities": {
+ "version": "3.1.0",
+ "resolved": "https://registry.npmjs.org/stringify-entities/-/stringify-entities-3.1.0.tgz",
+ "integrity": "sha512-3FP+jGMmMV/ffZs86MoghGqAoqXAdxLrJP4GUdrDN1aIScYih5tuIO3eF4To5AJZ79KDZ8Fpdy7QJnK8SsL1Vg==",
+ "dev": true,
+ "requires": {
+ "character-entities-html4": "^1.0.0",
+ "character-entities-legacy": "^1.0.0",
+ "xtend": "^4.0.0"
+ }
+ },
+ "stringify-object": {
+ "version": "3.3.0",
+ "resolved": "https://registry.npmjs.org/stringify-object/-/stringify-object-3.3.0.tgz",
+ "integrity": "sha512-rHqiFh1elqCQ9WPLIC8I0Q/g/wj5J1eMkyoiD6eoQApWHP0FtlK7rqnhmabL5VUY9JQCcqwwvlOaSuutekgyrw==",
+ "dev": true,
+ "requires": {
+ "get-own-enumerable-property-symbols": "^3.0.0",
+ "is-obj": "^1.0.1",
+ "is-regexp": "^1.0.0"
+ }
+ },
+ "strip-ansi": {
+ "version": "6.0.1",
+ "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz",
+ "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==",
+ "dev": true,
+ "requires": {
+ "ansi-regex": "^5.0.1"
+ }
+ },
+ "strip-bom": {
+ "version": "4.0.0",
+ "resolved": "https://registry.npmjs.org/strip-bom/-/strip-bom-4.0.0.tgz",
+ "integrity": "sha512-3xurFv5tEgii33Zi8Jtp55wEIILR9eh34FAW00PZf+JnSsTmV/ioewSgQl97JHvgjoRGwPShsWm+IdrxB35d0w==",
+ "dev": true,
+ "peer": true
+ },
+ "strip-eof": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/strip-eof/-/strip-eof-1.0.0.tgz",
+ "integrity": "sha1-u0P/VZim6wXYm1n80SnJgzE2Br8=",
+ "dev": true,
+ "peer": true
+ },
+ "strip-final-newline": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/strip-final-newline/-/strip-final-newline-2.0.0.tgz",
+ "integrity": "sha512-BrpvfNAE3dcvq7ll3xVumzjKjZQ5tI1sEUIKr3Uoks0XUl45St3FlatVqef9prk4jRDzhW6WZg+3bk93y6pLjA==",
+ "dev": true
+ },
+ "strip-indent": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/strip-indent/-/strip-indent-3.0.0.tgz",
+ "integrity": "sha512-laJTa3Jb+VQpaC6DseHhF7dXVqHTfJPCRDaEbid/drOhgitgYku/letMUqOXFoWV0zIIUbjpdH2t+tYj4bQMRQ==",
+ "dev": true,
+ "requires": {
+ "min-indent": "^1.0.0"
+ }
+ },
+ "strip-json-comments": {
+ "version": "3.1.1",
+ "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-3.1.1.tgz",
+ "integrity": "sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig==",
+ "dev": true
+ },
+ "style-search": {
+ "version": "0.1.0",
+ "resolved": "https://registry.npmjs.org/style-search/-/style-search-0.1.0.tgz",
+ "integrity": "sha1-eVjHk+R+MuB9K1yv5cC/jhLneQI=",
+ "dev": true
+ },
+ "styled-jsx": {
+ "version": "5.0.7",
+ "resolved": "https://registry.npmjs.org/styled-jsx/-/styled-jsx-5.0.7.tgz",
+ "integrity": "sha512-b3sUzamS086YLRuvnaDigdAewz1/EFYlHpYBP5mZovKEdQQOIIYq8lApylub3HHZ6xFjV051kkGU7cudJmrXEA==",
+ "dev": true,
+ "requires": {}
+ },
+ "stylelint": {
+ "version": "13.8.0",
+ "resolved": "https://registry.npmjs.org/stylelint/-/stylelint-13.8.0.tgz",
+ "integrity": "sha512-iHH3dv3UI23SLDrH4zMQDjLT9/dDIz/IpoFeuNxZmEx86KtfpjDOscxLTFioQyv+2vQjPlRZnK0UoJtfxLICXQ==",
+ "dev": true,
+ "requires": {
+ "@stylelint/postcss-css-in-js": "^0.37.2",
+ "@stylelint/postcss-markdown": "^0.36.2",
+ "autoprefixer": "^9.8.6",
+ "balanced-match": "^1.0.0",
+ "chalk": "^4.1.0",
+ "cosmiconfig": "^7.0.0",
+ "debug": "^4.2.0",
+ "execall": "^2.0.0",
+ "fast-glob": "^3.2.4",
+ "fastest-levenshtein": "^1.0.12",
+ "file-entry-cache": "^6.0.0",
+ "get-stdin": "^8.0.0",
+ "global-modules": "^2.0.0",
+ "globby": "^11.0.1",
+ "globjoin": "^0.1.4",
+ "html-tags": "^3.1.0",
+ "ignore": "^5.1.8",
+ "import-lazy": "^4.0.0",
+ "imurmurhash": "^0.1.4",
+ "known-css-properties": "^0.20.0",
+ "lodash": "^4.17.20",
+ "log-symbols": "^4.0.0",
+ "mathml-tag-names": "^2.1.3",
+ "meow": "^8.0.0",
+ "micromatch": "^4.0.2",
+ "normalize-selector": "^0.2.0",
+ "postcss": "^7.0.35",
+ "postcss-html": "^0.36.0",
+ "postcss-less": "^3.1.4",
+ "postcss-media-query-parser": "^0.2.3",
+ "postcss-resolve-nested-selector": "^0.1.1",
+ "postcss-safe-parser": "^4.0.2",
+ "postcss-sass": "^0.4.4",
+ "postcss-scss": "^2.1.1",
+ "postcss-selector-parser": "^6.0.4",
+ "postcss-syntax": "^0.36.2",
+ "postcss-value-parser": "^4.1.0",
+ "resolve-from": "^5.0.0",
+ "slash": "^3.0.0",
+ "specificity": "^0.4.1",
+ "string-width": "^4.2.0",
+ "strip-ansi": "^6.0.0",
+ "style-search": "^0.1.0",
+ "sugarss": "^2.0.0",
+ "svg-tags": "^1.0.0",
+ "table": "^6.0.3",
+ "v8-compile-cache": "^2.2.0",
+ "write-file-atomic": "^3.0.3"
+ },
+ "dependencies": {
+ "picocolors": {
+ "version": "0.2.1",
+ "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-0.2.1.tgz",
+ "integrity": "sha512-cMlDqaLEqfSaW8Z7N5Jw+lyIW869EzT73/F5lhtY9cLGoVxSXznfgfXMO0Z5K0o0Q2TkTXq+0KFsdnSe3jDViA==",
+ "dev": true
+ },
+ "postcss": {
+ "version": "7.0.39",
+ "resolved": "https://registry.npmjs.org/postcss/-/postcss-7.0.39.tgz",
+ "integrity": "sha512-yioayjNbHn6z1/Bywyb2Y4s3yvDAeXGOyxqD+LnVOinq6Mdmd++SW2wUNVzavyyHxd6+DxzWGIuosg6P1Rj8uA==",
+ "dev": true,
+ "requires": {
+ "picocolors": "^0.2.1",
+ "source-map": "^0.6.1"
+ }
+ },
+ "resolve-from": {
+ "version": "5.0.0",
+ "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-5.0.0.tgz",
+ "integrity": "sha512-qYg9KP24dD5qka9J47d0aVky0N+b4fTU89LN9iDnjB5waksiC49rvMB0PrUJQGoTmH50XPiqOvAjDfaijGxYZw==",
+ "dev": true
+ }
+ }
+ },
+ "stylelint-config-css-modules": {
+ "version": "2.2.0",
+ "resolved": "https://registry.npmjs.org/stylelint-config-css-modules/-/stylelint-config-css-modules-2.2.0.tgz",
+ "integrity": "sha512-+zjcDbot+zbuxy1UA31k4G2lUG+nHUwnLyii3uT2F09B8kT2YrT9LZYNfMtAWlDidrxr7sFd5HX9EqPHGU3WKA==",
+ "dev": true,
+ "requires": {}
+ },
+ "stylelint-config-prettier": {
+ "version": "8.0.2",
+ "resolved": "https://registry.npmjs.org/stylelint-config-prettier/-/stylelint-config-prettier-8.0.2.tgz",
+ "integrity": "sha512-TN1l93iVTXpF9NJstlvP7nOu9zY2k+mN0NSFQ/VEGz15ZIP9ohdDZTtCWHs5LjctAhSAzaILULGbgiM0ItId3A==",
+ "dev": true,
+ "requires": {}
+ },
+ "stylelint-config-recommended": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/stylelint-config-recommended/-/stylelint-config-recommended-3.0.0.tgz",
+ "integrity": "sha512-F6yTRuc06xr1h5Qw/ykb2LuFynJ2IxkKfCMf+1xqPffkxh0S09Zc902XCffcsw/XMFq/OzQ1w54fLIDtmRNHnQ==",
+ "dev": true,
+ "requires": {}
+ },
+ "stylelint-config-standard": {
+ "version": "20.0.0",
+ "resolved": "https://registry.npmjs.org/stylelint-config-standard/-/stylelint-config-standard-20.0.0.tgz",
+ "integrity": "sha512-IB2iFdzOTA/zS4jSVav6z+wGtin08qfj+YyExHB3LF9lnouQht//YyB0KZq9gGz5HNPkddHOzcY8HsUey6ZUlA==",
+ "dev": true,
+ "requires": {
+ "stylelint-config-recommended": "^3.0.0"
+ }
+ },
+ "stylelint-media-use-custom-media": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/stylelint-media-use-custom-media/-/stylelint-media-use-custom-media-2.0.0.tgz",
+ "integrity": "sha512-G7Hwma8HIMFJOChqrX9ie8hAGbtEMUbEjuiaR3olHIXjloDWqYlFHIJKsCyyckigkm+4LtCwtZDQASrVY4pRBg==",
+ "dev": true,
+ "requires": {}
+ },
+ "stylelint-order": {
+ "version": "4.1.0",
+ "resolved": "https://registry.npmjs.org/stylelint-order/-/stylelint-order-4.1.0.tgz",
+ "integrity": "sha512-sVTikaDvMqg2aJjh4r48jsdfmqLT+nqB1MOsaBnvM3OwLx4S+WXcsxsgk5w18h/OZoxZCxuyXMh61iBHcj9Qiw==",
+ "dev": true,
+ "requires": {
+ "lodash": "^4.17.15",
+ "postcss": "^7.0.31",
+ "postcss-sorting": "^5.0.1"
+ },
+ "dependencies": {
+ "picocolors": {
+ "version": "0.2.1",
+ "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-0.2.1.tgz",
+ "integrity": "sha512-cMlDqaLEqfSaW8Z7N5Jw+lyIW869EzT73/F5lhtY9cLGoVxSXznfgfXMO0Z5K0o0Q2TkTXq+0KFsdnSe3jDViA==",
+ "dev": true
+ },
+ "postcss": {
+ "version": "7.0.39",
+ "resolved": "https://registry.npmjs.org/postcss/-/postcss-7.0.39.tgz",
+ "integrity": "sha512-yioayjNbHn6z1/Bywyb2Y4s3yvDAeXGOyxqD+LnVOinq6Mdmd++SW2wUNVzavyyHxd6+DxzWGIuosg6P1Rj8uA==",
+ "dev": true,
+ "requires": {
+ "picocolors": "^0.2.1",
+ "source-map": "^0.6.1"
+ }
+ }
+ }
+ },
+ "stylelint-use-nesting": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/stylelint-use-nesting/-/stylelint-use-nesting-3.0.0.tgz",
+ "integrity": "sha512-BMzhXWbK5DdAYtZMQULn7VmWZXpy8Rwlx2PgeNYqKInQrKTJWM/TFKPScc+xvsGUc/6JPiUDeQQij9gFnOo8Kg==",
+ "dev": true,
+ "requires": {}
+ },
+ "stylelint-value-no-unknown-custom-properties": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/stylelint-value-no-unknown-custom-properties/-/stylelint-value-no-unknown-custom-properties-3.0.0.tgz",
+ "integrity": "sha512-8WoOnZ4ELTxA1cDbhwolIVOutxHwbjpXmd0lL0Li3Iye078jSnEb1KO6pJ/ig5oDVGRApFeA25Fyy4qqmqwGgg==",
+ "dev": true,
+ "requires": {
+ "postcss-values-parser": "^3.2.1"
+ }
+ },
+ "sugarss": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/sugarss/-/sugarss-2.0.0.tgz",
+ "integrity": "sha512-WfxjozUk0UVA4jm+U1d736AUpzSrNsQcIbyOkoE364GrtWmIrFdk5lksEupgWMD4VaT/0kVx1dobpiDumSgmJQ==",
+ "dev": true,
+ "requires": {
+ "postcss": "^7.0.2"
+ },
+ "dependencies": {
+ "picocolors": {
+ "version": "0.2.1",
+ "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-0.2.1.tgz",
+ "integrity": "sha512-cMlDqaLEqfSaW8Z7N5Jw+lyIW869EzT73/F5lhtY9cLGoVxSXznfgfXMO0Z5K0o0Q2TkTXq+0KFsdnSe3jDViA==",
+ "dev": true
+ },
+ "postcss": {
+ "version": "7.0.39",
+ "resolved": "https://registry.npmjs.org/postcss/-/postcss-7.0.39.tgz",
+ "integrity": "sha512-yioayjNbHn6z1/Bywyb2Y4s3yvDAeXGOyxqD+LnVOinq6Mdmd++SW2wUNVzavyyHxd6+DxzWGIuosg6P1Rj8uA==",
+ "dev": true,
+ "requires": {
+ "picocolors": "^0.2.1",
+ "source-map": "^0.6.1"
+ }
+ }
+ }
+ },
+ "supports-color": {
+ "version": "7.2.0",
+ "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz",
+ "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==",
+ "dev": true,
+ "requires": {
+ "has-flag": "^4.0.0"
+ }
+ },
+ "supports-hyperlinks": {
+ "version": "2.2.0",
+ "resolved": "https://registry.npmjs.org/supports-hyperlinks/-/supports-hyperlinks-2.2.0.tgz",
+ "integrity": "sha512-6sXEzV5+I5j8Bmq9/vUphGRM/RJNT9SCURJLjwfOg51heRtguGWDzcaBlgAzKhQa0EVNpPEKzQuBwZ8S8WaCeQ==",
+ "dev": true,
+ "peer": true,
+ "requires": {
+ "has-flag": "^4.0.0",
+ "supports-color": "^7.0.0"
+ }
+ },
+ "supports-preserve-symlinks-flag": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/supports-preserve-symlinks-flag/-/supports-preserve-symlinks-flag-1.0.0.tgz",
+ "integrity": "sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w==",
+ "dev": true
+ },
+ "svg-tags": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/svg-tags/-/svg-tags-1.0.0.tgz",
+ "integrity": "sha1-WPcc7jvVGbWdSyqEO2x95krAR2Q=",
+ "dev": true
+ },
+ "symbol-tree": {
+ "version": "3.2.4",
+ "resolved": "https://registry.npmjs.org/symbol-tree/-/symbol-tree-3.2.4.tgz",
+ "integrity": "sha512-9QNk5KwDF+Bvz+PyObkmSYjI5ksVUYtjW7AU22r2NKcfLJcXp96hkDWU3+XndOsUb+AQ9QhfzfCT2O+CNWT5Tw==",
+ "dev": true,
+ "peer": true
+ },
+ "synckit": {
+ "version": "0.8.5",
+ "resolved": "https://registry.npmjs.org/synckit/-/synckit-0.8.5.tgz",
+ "integrity": "sha512-L1dapNV6vu2s/4Sputv8xGsCdAVlb5nRDMFU/E27D44l5U6cw1g0dGd45uLc+OXjNMmF4ntiMdCimzcjFKQI8Q==",
+ "dev": true,
+ "requires": {
+ "@pkgr/utils": "^2.3.1",
+ "tslib": "^2.5.0"
+ },
+ "dependencies": {
+ "tslib": {
+ "version": "2.5.0",
+ "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.5.0.tgz",
+ "integrity": "sha512-336iVw3rtn2BUK7ORdIAHTyxHGRIHVReokCR3XjbckJMK7ms8FysBfhLR8IXnAgy7T0PTPNBWKiH514FOW/WSg==",
+ "dev": true
+ }
+ }
+ },
+ "table": {
+ "version": "6.8.0",
+ "resolved": "https://registry.npmjs.org/table/-/table-6.8.0.tgz",
+ "integrity": "sha512-s/fitrbVeEyHKFa7mFdkuQMWlH1Wgw/yEXMt5xACT4ZpzWFluehAxRtUUQKPuWhaLAWhFcVx6w3oC8VKaUfPGA==",
+ "dev": true,
+ "requires": {
+ "ajv": "^8.0.1",
+ "lodash.truncate": "^4.4.2",
+ "slice-ansi": "^4.0.0",
+ "string-width": "^4.2.3",
+ "strip-ansi": "^6.0.1"
+ },
+ "dependencies": {
+ "ajv": {
+ "version": "8.11.0",
+ "resolved": "https://registry.npmjs.org/ajv/-/ajv-8.11.0.tgz",
+ "integrity": "sha512-wGgprdCvMalC0BztXvitD2hC04YffAvtsUn93JbGXYLAtCUO4xd17mCCZQxUOItiBwZvJScWo8NIvQMQ71rdpg==",
+ "dev": true,
+ "requires": {
+ "fast-deep-equal": "^3.1.1",
+ "json-schema-traverse": "^1.0.0",
+ "require-from-string": "^2.0.2",
+ "uri-js": "^4.2.2"
+ }
+ },
+ "json-schema-traverse": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-1.0.0.tgz",
+ "integrity": "sha512-NM8/P9n3XjXhIZn1lLhkFaACTOURQXjWhV4BA/RnOv8xvgqtqpAX9IO4mRQxSx1Rlo4tqzeqb0sOlruaOy3dug==",
+ "dev": true
+ },
+ "slice-ansi": {
+ "version": "4.0.0",
+ "resolved": "https://registry.npmjs.org/slice-ansi/-/slice-ansi-4.0.0.tgz",
+ "integrity": "sha512-qMCMfhY040cVHT43K9BFygqYbUPFZKHOg7K73mtTWJRb8pyP3fzf4Ixd5SzdEJQ6MRUg/WBnOLxghZtKKurENQ==",
+ "dev": true,
+ "requires": {
+ "ansi-styles": "^4.0.0",
+ "astral-regex": "^2.0.0",
+ "is-fullwidth-code-point": "^3.0.0"
+ }
+ }
+ }
+ },
+ "tapable": {
+ "version": "2.2.1",
+ "resolved": "https://registry.npmjs.org/tapable/-/tapable-2.2.1.tgz",
+ "integrity": "sha512-GNzQvQTOIP6RyTfE2Qxb8ZVlNmw0n88vp1szwWRimP02mnTsx3Wtn5qRdqY9w2XduFNUgvOwhNnQsjwCp+kqaQ==",
+ "dev": true
+ },
+ "terminal-link": {
+ "version": "2.1.1",
+ "resolved": "https://registry.npmjs.org/terminal-link/-/terminal-link-2.1.1.tgz",
+ "integrity": "sha512-un0FmiRUQNr5PJqy9kP7c40F5BOfpGlYTrxonDChEZB7pzZxRNp/bt+ymiy9/npwXya9KH99nJ/GXFIiUkYGFQ==",
+ "dev": true,
+ "peer": true,
+ "requires": {
+ "ansi-escapes": "^4.2.1",
+ "supports-hyperlinks": "^2.0.0"
+ }
+ },
+ "test-exclude": {
+ "version": "6.0.0",
+ "resolved": "https://registry.npmjs.org/test-exclude/-/test-exclude-6.0.0.tgz",
+ "integrity": "sha512-cAGWPIyOHU6zlmg88jwm7VRyXnMN7iV68OGAbYDk/Mh/xC/pzVPlQtY6ngoIH/5/tciuhGfvESU8GrHrcxD56w==",
+ "dev": true,
+ "peer": true,
+ "requires": {
+ "@istanbuljs/schema": "^0.1.2",
+ "glob": "^7.1.4",
+ "minimatch": "^3.0.4"
+ }
+ },
+ "text-table": {
+ "version": "0.2.0",
+ "resolved": "https://registry.npmjs.org/text-table/-/text-table-0.2.0.tgz",
+ "integrity": "sha512-N+8UisAXDGk8PFXP4HAzVR9nbfmVJ3zYLAWiTIoqC5v5isinhr+r5uaO8+7r3BMfuNIufIsA7RdpVgacC2cSpw==",
+ "dev": true
+ },
+ "throat": {
+ "version": "5.0.0",
+ "resolved": "https://registry.npmjs.org/throat/-/throat-5.0.0.tgz",
+ "integrity": "sha512-fcwX4mndzpLQKBS1DVYhGAcYaYt7vsHNIvQV+WXMvnow5cgjPphq5CaayLaGsjRdSCKZFNGt7/GYAuXaNOiYCA==",
+ "dev": true,
+ "peer": true
+ },
+ "through": {
+ "version": "2.3.8",
+ "resolved": "https://registry.npmjs.org/through/-/through-2.3.8.tgz",
+ "integrity": "sha1-DdTJ/6q8NXlgsbckEV1+Doai4fU=",
+ "dev": true
+ },
+ "tiny-glob": {
+ "version": "0.2.9",
+ "resolved": "https://registry.npmjs.org/tiny-glob/-/tiny-glob-0.2.9.tgz",
+ "integrity": "sha512-g/55ssRPUjShh+xkfx9UPDXqhckHEsHr4Vd9zX55oSdGZc/MD0m3sferOkwWtp98bv+kcVfEHtRJgBVJzelrzg==",
+ "dev": true,
+ "requires": {
+ "globalyzer": "0.1.0",
+ "globrex": "^0.1.2"
+ }
+ },
+ "tlds": {
+ "version": "1.231.0",
+ "resolved": "https://registry.npmjs.org/tlds/-/tlds-1.231.0.tgz",
+ "integrity": "sha512-L7UQwueHSkGxZHQBXHVmXW64oi+uqNtzFt2x6Ssk7NVnpIbw16CRs4eb/jmKOZ9t2JnqZ/b3Cfvo97lnXqKrhw==",
+ "dev": true
+ },
+ "tmp": {
+ "version": "0.0.33",
+ "resolved": "https://registry.npmjs.org/tmp/-/tmp-0.0.33.tgz",
+ "integrity": "sha512-jRCJlojKnZ3addtTOjdIqoRuPEKBvNXcGYqzO6zWZX8KfKEpnGY5jfggJQ3EjKuu8D4bJRr0y+cYJFmYbImXGw==",
+ "dev": true,
+ "requires": {
+ "os-tmpdir": "~1.0.2"
+ }
+ },
+ "tmpl": {
+ "version": "1.0.5",
+ "resolved": "https://registry.npmjs.org/tmpl/-/tmpl-1.0.5.tgz",
+ "integrity": "sha512-3f0uOEAQwIqGuWW2MVzYg8fV/QNnc/IpuJNG837rLuczAaLVHslWHZQj4IGiEl5Hs3kkbhwL9Ab7Hrsmuj+Smw==",
+ "dev": true,
+ "peer": true
+ },
+ "to-fast-properties": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/to-fast-properties/-/to-fast-properties-2.0.0.tgz",
+ "integrity": "sha1-3F5pjL0HkmW8c+A3doGk5Og/YW4=",
+ "dev": true
+ },
+ "to-object-path": {
+ "version": "0.3.0",
+ "resolved": "https://registry.npmjs.org/to-object-path/-/to-object-path-0.3.0.tgz",
+ "integrity": "sha1-KXWIt7Dn4KwI4E5nL4XB9JmeF68=",
+ "dev": true,
+ "peer": true,
+ "requires": {
+ "kind-of": "^3.0.2"
+ },
+ "dependencies": {
+ "is-buffer": {
+ "version": "1.1.6",
+ "resolved": "https://registry.npmjs.org/is-buffer/-/is-buffer-1.1.6.tgz",
+ "integrity": "sha512-NcdALwpXkTm5Zvvbk7owOUSvVvBKDgKP5/ewfXEznmQFfs4ZRmanOeKBTjRVjka3QFoN6XJ+9F3USqfHqTaU5w==",
+ "dev": true,
+ "peer": true
+ },
+ "kind-of": {
+ "version": "3.2.2",
+ "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz",
+ "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=",
+ "dev": true,
+ "peer": true,
+ "requires": {
+ "is-buffer": "^1.1.5"
+ }
+ }
+ }
+ },
+ "to-regex": {
+ "version": "3.0.2",
+ "resolved": "https://registry.npmjs.org/to-regex/-/to-regex-3.0.2.tgz",
+ "integrity": "sha512-FWtleNAtZ/Ki2qtqej2CXTOayOH9bHDQF+Q48VpWyDXjbYxA4Yz8iDB31zXOBUlOHHKidDbqGVrTUvQMPmBGBw==",
+ "dev": true,
+ "peer": true,
+ "requires": {
+ "define-property": "^2.0.2",
+ "extend-shallow": "^3.0.2",
+ "regex-not": "^1.0.2",
+ "safe-regex": "^1.1.0"
+ }
+ },
+ "to-regex-range": {
+ "version": "5.0.1",
+ "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz",
+ "integrity": "sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==",
+ "dev": true,
+ "requires": {
+ "is-number": "^7.0.0"
+ }
+ },
+ "tough-cookie": {
+ "version": "4.1.3",
+ "resolved": "https://registry.npmjs.org/tough-cookie/-/tough-cookie-4.1.3.tgz",
+ "integrity": "sha512-aX/y5pVRkfRnfmuX+OdbSdXvPe6ieKX/G2s7e98f4poJHnqH3281gDPm/metm6E/WRamfx7WC4HUqkWHfQHprw==",
+ "dev": true,
+ "peer": true,
+ "requires": {
+ "psl": "^1.1.33",
+ "punycode": "^2.1.1",
+ "universalify": "^0.2.0",
+ "url-parse": "^1.5.3"
+ },
+ "dependencies": {
+ "universalify": {
+ "version": "0.2.0",
+ "resolved": "https://registry.npmjs.org/universalify/-/universalify-0.2.0.tgz",
+ "integrity": "sha512-CJ1QgKmNg3CwvAv/kOFmtnEN05f0D/cn9QntgNOQlQF9dgvVTHj3t+8JPdjqawCHk7V/KA+fbUqzZ9XWhcqPUg==",
+ "dev": true,
+ "peer": true
+ }
+ }
+ },
+ "tr46": {
+ "version": "2.1.0",
+ "resolved": "https://registry.npmjs.org/tr46/-/tr46-2.1.0.tgz",
+ "integrity": "sha512-15Ih7phfcdP5YxqiB+iDtLoaTz4Nd35+IiAv0kQ5FNKHzXgdWqPoTIqEDDJmXceQt4JZk6lVPT8lnDlPpGDppw==",
+ "dev": true,
+ "peer": true,
+ "requires": {
+ "punycode": "^2.1.1"
+ }
+ },
+ "trim": {
+ "version": "0.0.1",
+ "resolved": "https://registry.npmjs.org/trim/-/trim-0.0.1.tgz",
+ "integrity": "sha512-YzQV+TZg4AxpKxaTHK3c3D+kRDCGVEE7LemdlQZoQXn0iennk10RsIoY6ikzAqJTc9Xjl9C1/waHom/J86ziAQ==",
+ "dev": true
+ },
+ "trim-newlines": {
+ "version": "3.0.1",
+ "resolved": "https://registry.npmjs.org/trim-newlines/-/trim-newlines-3.0.1.tgz",
+ "integrity": "sha512-c1PTsA3tYrIsLGkJkzHF+w9F2EyxfXGo4UyJc4pFL++FMjnq0HJS69T3M7d//gKrFKwy429bouPescbjecU+Zw==",
+ "dev": true
+ },
+ "trim-trailing-lines": {
+ "version": "1.1.4",
+ "resolved": "https://registry.npmjs.org/trim-trailing-lines/-/trim-trailing-lines-1.1.4.tgz",
+ "integrity": "sha512-rjUWSqnfTNrjbB9NQWfPMH/xRK1deHeGsHoVfpxJ++XeYXE0d6B1En37AHfw3jtfTU7dzMzZL2jjpe8Qb5gLIQ==",
+ "dev": true
+ },
+ "trough": {
+ "version": "1.0.5",
+ "resolved": "https://registry.npmjs.org/trough/-/trough-1.0.5.tgz",
+ "integrity": "sha512-rvuRbTarPXmMb79SmzEp8aqXNKcK+y0XaB298IXueQ8I2PsrATcPBCSPyK/dDNa2iWOhKlfNnOjdAOTBU/nkFA==",
+ "dev": true
+ },
+ "ts-jest": {
+ "version": "26.5.6",
+ "resolved": "https://registry.npmjs.org/ts-jest/-/ts-jest-26.5.6.tgz",
+ "integrity": "sha512-rua+rCP8DxpA8b4DQD/6X2HQS8Zy/xzViVYfEs2OQu68tkCuKLV0Md8pmX55+W24uRIyAsf/BajRfxOs+R2MKA==",
+ "dev": true,
+ "requires": {
+ "bs-logger": "0.x",
+ "buffer-from": "1.x",
+ "fast-json-stable-stringify": "2.x",
+ "jest-util": "^26.1.0",
+ "json5": "2.x",
+ "lodash": "4.x",
+ "make-error": "1.x",
+ "mkdirp": "1.x",
+ "semver": "7.x",
+ "yargs-parser": "20.x"
+ }
+ },
+ "tsconfig-paths": {
+ "version": "3.14.2",
+ "resolved": "https://registry.npmjs.org/tsconfig-paths/-/tsconfig-paths-3.14.2.tgz",
+ "integrity": "sha512-o/9iXgCYc5L/JxCHPe3Hvh8Q/2xm5Z+p18PESBU6Ff33695QnCHBEjcytY2q19ua7Mbl/DavtBOLq+oG0RCL+g==",
+ "dev": true,
+ "requires": {
+ "@types/json5": "^0.0.29",
+ "json5": "^1.0.2",
+ "minimist": "^1.2.6",
+ "strip-bom": "^3.0.0"
+ },
+ "dependencies": {
+ "json5": {
+ "version": "1.0.2",
+ "resolved": "https://registry.npmjs.org/json5/-/json5-1.0.2.tgz",
+ "integrity": "sha512-g1MWMLBiz8FKi1e4w0UyVL3w+iJceWAFBAaBnnGKOpNa5f8TLktkbre1+s6oICydWAm+HRUGTmI+//xv2hvXYA==",
+ "dev": true,
+ "requires": {
+ "minimist": "^1.2.0"
+ }
+ },
+ "strip-bom": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/strip-bom/-/strip-bom-3.0.0.tgz",
+ "integrity": "sha512-vavAMRXOgBVNF6nyEEmL3DBK19iRpDcoIwW+swQ+CbGiu7lju6t+JklA1MHweoWtadgt4ISVUsXLyDq34ddcwA==",
+ "dev": true
+ }
+ }
+ },
+ "tslib": {
+ "version": "1.14.1",
+ "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.14.1.tgz",
+ "integrity": "sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg==",
+ "dev": true
+ },
+ "tsutils": {
+ "version": "3.21.0",
+ "resolved": "https://registry.npmjs.org/tsutils/-/tsutils-3.21.0.tgz",
+ "integrity": "sha512-mHKK3iUXL+3UF6xL5k0PEhKRUBKPBCv/+RkEOpjRWxxx27KKRBmmA60A9pgOUvMi8GKhRMPEmjBRPzs2W7O1OA==",
+ "dev": true,
+ "requires": {
+ "tslib": "^1.8.1"
+ }
+ },
+ "type-check": {
+ "version": "0.4.0",
+ "resolved": "https://registry.npmjs.org/type-check/-/type-check-0.4.0.tgz",
+ "integrity": "sha512-XleUoc9uwGXqjWwXaUTZAmzMcFZ5858QA2vvx1Ur5xIcixXIP+8LnFDgRplU30us6teqdlskFfu+ae4K79Ooew==",
+ "dev": true,
+ "requires": {
+ "prelude-ls": "^1.2.1"
+ }
+ },
+ "type-detect": {
+ "version": "4.0.8",
+ "resolved": "https://registry.npmjs.org/type-detect/-/type-detect-4.0.8.tgz",
+ "integrity": "sha512-0fr/mIH1dlO+x7TlcMy+bIDqKPsw/70tVyeHW787goQjhmqaZe10uwLujubK9q9Lg6Fiho1KUKDYz0Z7k7g5/g==",
+ "dev": true,
+ "peer": true
+ },
+ "type-fest": {
+ "version": "0.20.2",
+ "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.20.2.tgz",
+ "integrity": "sha512-Ne+eE4r0/iWnpAxD852z3A+N0Bt5RN//NjJwRd2VFHEmrywxf5vsZlh4R6lixl6B+wz/8d+maTSAkN1FIkI3LQ==",
+ "dev": true
+ },
+ "typed-array-length": {
+ "version": "1.0.4",
+ "resolved": "https://registry.npmjs.org/typed-array-length/-/typed-array-length-1.0.4.tgz",
+ "integrity": "sha512-KjZypGq+I/H7HI5HlOoGHkWUUGq+Q0TPhQurLbyrVrvnKTBgzLhIJ7j6J/XTQOi0d1RjyZ0wdas8bKs2p0x3Ng==",
+ "dev": true,
+ "requires": {
+ "call-bind": "^1.0.2",
+ "for-each": "^0.3.3",
+ "is-typed-array": "^1.1.9"
+ }
+ },
+ "typedarray-to-buffer": {
+ "version": "3.1.5",
+ "resolved": "https://registry.npmjs.org/typedarray-to-buffer/-/typedarray-to-buffer-3.1.5.tgz",
+ "integrity": "sha512-zdu8XMNEDepKKR+XYOXAVPtWui0ly0NtohUscw+UmaHiAWT8hrV1rr//H6V+0DvJ3OQ19S979M0laLfX8rm82Q==",
+ "dev": true,
+ "requires": {
+ "is-typedarray": "^1.0.0"
+ }
+ },
+ "typescript": {
+ "version": "4.6.3",
+ "resolved": "https://registry.npmjs.org/typescript/-/typescript-4.6.3.tgz",
+ "integrity": "sha512-yNIatDa5iaofVozS/uQJEl3JRWLKKGJKh6Yaiv0GLGSuhpFJe7P3SbHZ8/yjAHRQwKRoA6YZqlfjXWmVzoVSMw==",
+ "dev": true,
+ "peer": true
+ },
+ "unbox-primitive": {
+ "version": "1.0.2",
+ "resolved": "https://registry.npmjs.org/unbox-primitive/-/unbox-primitive-1.0.2.tgz",
+ "integrity": "sha512-61pPlCD9h51VoreyJ0BReideM3MDKMKnh6+V9L08331ipq6Q8OFXZYiqP6n/tbHx4s5I9uRhcye6BrbkizkBDw==",
+ "dev": true,
+ "requires": {
+ "call-bind": "^1.0.2",
+ "has-bigints": "^1.0.2",
+ "has-symbols": "^1.0.3",
+ "which-boxed-primitive": "^1.0.2"
+ }
+ },
+ "unherit": {
+ "version": "1.1.3",
+ "resolved": "https://registry.npmjs.org/unherit/-/unherit-1.1.3.tgz",
+ "integrity": "sha512-Ft16BJcnapDKp0+J/rqFC3Rrk6Y/Ng4nzsC028k2jdDII/rdZ7Wd3pPT/6+vIIxRagwRc9K0IUX0Ra4fKvw+WQ==",
+ "dev": true,
+ "requires": {
+ "inherits": "^2.0.0",
+ "xtend": "^4.0.0"
+ }
+ },
+ "unified": {
+ "version": "9.2.2",
+ "resolved": "https://registry.npmjs.org/unified/-/unified-9.2.2.tgz",
+ "integrity": "sha512-Sg7j110mtefBD+qunSLO1lqOEKdrwBFBrR6Qd8f4uwkhWNlbkaqwHse6e7QvD3AP/MNoJdEDLaf8OxYyoWgorQ==",
+ "dev": true,
+ "requires": {
+ "bail": "^1.0.0",
+ "extend": "^3.0.0",
+ "is-buffer": "^2.0.0",
+ "is-plain-obj": "^2.0.0",
+ "trough": "^1.0.0",
+ "vfile": "^4.0.0"
+ },
+ "dependencies": {
+ "is-plain-obj": {
+ "version": "2.1.0",
+ "resolved": "https://registry.npmjs.org/is-plain-obj/-/is-plain-obj-2.1.0.tgz",
+ "integrity": "sha512-YWnfyRwxL/+SsrWYfOpUtz5b3YD+nyfkHvjbcanzk8zgyO4ASD67uVMRt8k5bM4lLMDnXfriRhOpemw+NfT1eA==",
+ "dev": true
+ }
+ }
+ },
+ "unified-lint-rule": {
+ "version": "2.1.1",
+ "resolved": "https://registry.npmjs.org/unified-lint-rule/-/unified-lint-rule-2.1.1.tgz",
+ "integrity": "sha512-vsLHyLZFstqtGse2gvrGwasOmH8M2y+r2kQMoDSWzSqUkQx2MjHjvZuGSv5FUaiv4RQO1bHRajy7lSGp7XWq5A==",
+ "dev": true,
+ "requires": {
+ "@types/unist": "^2.0.0",
+ "trough": "^2.0.0",
+ "unified": "^10.0.0",
+ "vfile": "^5.0.0"
+ },
+ "dependencies": {
+ "bail": {
+ "version": "2.0.2",
+ "resolved": "https://registry.npmjs.org/bail/-/bail-2.0.2.tgz",
+ "integrity": "sha512-0xO6mYd7JB2YesxDKplafRpsiOzPt9V02ddPCLbY1xYGPOX24NTyN50qnUxgCPcSoYMhKpAuBTjQoRZCAkUDRw==",
+ "dev": true
+ },
+ "is-plain-obj": {
+ "version": "4.1.0",
+ "resolved": "https://registry.npmjs.org/is-plain-obj/-/is-plain-obj-4.1.0.tgz",
+ "integrity": "sha512-+Pgi+vMuUNkJyExiMBt5IlFoMyKnr5zhJ4Uspz58WOhBF5QoIZkFyNHIbBAtHwzVAgk5RtndVNsDRN61/mmDqg==",
+ "dev": true
+ },
+ "trough": {
+ "version": "2.1.0",
+ "resolved": "https://registry.npmjs.org/trough/-/trough-2.1.0.tgz",
+ "integrity": "sha512-AqTiAOLcj85xS7vQ8QkAV41hPDIJ71XJB4RCUrzo/1GM2CQwhkJGaf9Hgr7BOugMRpgGUrqRg/DrBDl4H40+8g==",
+ "dev": true
+ },
+ "unified": {
+ "version": "10.1.2",
+ "resolved": "https://registry.npmjs.org/unified/-/unified-10.1.2.tgz",
+ "integrity": "sha512-pUSWAi/RAnVy1Pif2kAoeWNBa3JVrx0MId2LASj8G+7AiHWoKZNTomq6LG326T68U7/e263X6fTdcXIy7XnF7Q==",
+ "dev": true,
+ "requires": {
+ "@types/unist": "^2.0.0",
+ "bail": "^2.0.0",
+ "extend": "^3.0.0",
+ "is-buffer": "^2.0.0",
+ "is-plain-obj": "^4.0.0",
+ "trough": "^2.0.0",
+ "vfile": "^5.0.0"
+ }
+ },
+ "unist-util-stringify-position": {
+ "version": "3.0.3",
+ "resolved": "https://registry.npmjs.org/unist-util-stringify-position/-/unist-util-stringify-position-3.0.3.tgz",
+ "integrity": "sha512-k5GzIBZ/QatR8N5X2y+drfpWG8IDBzdnVj6OInRNWm1oXrzydiaAT2OQiA8DPRRZyAKb9b6I2a6PxYklZD0gKg==",
+ "dev": true,
+ "requires": {
+ "@types/unist": "^2.0.0"
+ }
+ },
+ "vfile": {
+ "version": "5.3.7",
+ "resolved": "https://registry.npmjs.org/vfile/-/vfile-5.3.7.tgz",
+ "integrity": "sha512-r7qlzkgErKjobAmyNIkkSpizsFPYiUPuJb5pNW1RB4JcYVZhs4lIbVqk8XPk033CV/1z8ss5pkax8SuhGpcG8g==",
+ "dev": true,
+ "requires": {
+ "@types/unist": "^2.0.0",
+ "is-buffer": "^2.0.0",
+ "unist-util-stringify-position": "^3.0.0",
+ "vfile-message": "^3.0.0"
+ }
+ },
+ "vfile-message": {
+ "version": "3.1.4",
+ "resolved": "https://registry.npmjs.org/vfile-message/-/vfile-message-3.1.4.tgz",
+ "integrity": "sha512-fa0Z6P8HUrQN4BZaX05SIVXic+7kE3b05PWAtPuYP9QLHsLKYR7/AlLW3NtOrpXRLeawpDLMsVkmk5DG0NXgWw==",
+ "dev": true,
+ "requires": {
+ "@types/unist": "^2.0.0",
+ "unist-util-stringify-position": "^3.0.0"
+ }
+ }
+ }
+ },
+ "union-value": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/union-value/-/union-value-1.0.1.tgz",
+ "integrity": "sha512-tJfXmxMeWYnczCVs7XAEvIV7ieppALdyepWMkHkwciRpZraG/xwT+s2JN8+pr1+8jCRf80FFzvr+MpQeeoF4Xg==",
+ "dev": true,
+ "peer": true,
+ "requires": {
+ "arr-union": "^3.1.0",
+ "get-value": "^2.0.6",
+ "is-extendable": "^0.1.1",
+ "set-value": "^2.0.1"
+ },
+ "dependencies": {
+ "is-extendable": {
+ "version": "0.1.1",
+ "resolved": "https://registry.npmjs.org/is-extendable/-/is-extendable-0.1.1.tgz",
+ "integrity": "sha1-YrEQ4omkcUGOPsNqYX1HLjAd/Ik=",
+ "dev": true,
+ "peer": true
+ }
+ }
+ },
+ "unist-util-find-all-after": {
+ "version": "3.0.2",
+ "resolved": "https://registry.npmjs.org/unist-util-find-all-after/-/unist-util-find-all-after-3.0.2.tgz",
+ "integrity": "sha512-xaTC/AGZ0rIM2gM28YVRAFPIZpzbpDtU3dRmp7EXlNVA8ziQc4hY3H7BHXM1J49nEmiqc3svnqMReW+PGqbZKQ==",
+ "dev": true,
+ "requires": {
+ "unist-util-is": "^4.0.0"
+ }
+ },
+ "unist-util-is": {
+ "version": "4.1.0",
+ "resolved": "https://registry.npmjs.org/unist-util-is/-/unist-util-is-4.1.0.tgz",
+ "integrity": "sha512-ZOQSsnce92GrxSqlnEEseX0gi7GH9zTJZ0p9dtu87WRb/37mMPO2Ilx1s/t9vBHrFhbgweUwb+t7cIn5dxPhZg==",
+ "dev": true
+ },
+ "unist-util-remove-position": {
+ "version": "2.0.1",
+ "resolved": "https://registry.npmjs.org/unist-util-remove-position/-/unist-util-remove-position-2.0.1.tgz",
+ "integrity": "sha512-fDZsLYIe2uT+oGFnuZmy73K6ZxOPG/Qcm+w7jbEjaFcJgbQ6cqjs/eSPzXhsmGpAsWPkqZM9pYjww5QTn3LHMA==",
+ "dev": true,
+ "requires": {
+ "unist-util-visit": "^2.0.0"
+ },
+ "dependencies": {
+ "unist-util-visit": {
+ "version": "2.0.3",
+ "resolved": "https://registry.npmjs.org/unist-util-visit/-/unist-util-visit-2.0.3.tgz",
+ "integrity": "sha512-iJ4/RczbJMkD0712mGktuGpm/U4By4FfDonL7N/9tATGIF4imikjOuagyMY53tnZq3NP6BcmlrHhEKAfGWjh7Q==",
+ "dev": true,
+ "requires": {
+ "@types/unist": "^2.0.0",
+ "unist-util-is": "^4.0.0",
+ "unist-util-visit-parents": "^3.0.0"
+ }
+ },
+ "unist-util-visit-parents": {
+ "version": "3.1.1",
+ "resolved": "https://registry.npmjs.org/unist-util-visit-parents/-/unist-util-visit-parents-3.1.1.tgz",
+ "integrity": "sha512-1KROIZWo6bcMrZEwiH2UrXDyalAa0uqzWCxCJj6lPOvTve2WkfgCytoDTPaMnodXh1WrXOq0haVYHj99ynJlsg==",
+ "dev": true,
+ "requires": {
+ "@types/unist": "^2.0.0",
+ "unist-util-is": "^4.0.0"
+ }
+ }
+ }
+ },
+ "unist-util-stringify-position": {
+ "version": "2.0.3",
+ "resolved": "https://registry.npmjs.org/unist-util-stringify-position/-/unist-util-stringify-position-2.0.3.tgz",
+ "integrity": "sha512-3faScn5I+hy9VleOq/qNbAd6pAx7iH5jYBMS9I1HgQVijz/4mv5Bvw5iw1sC/90CODiKo81G/ps8AJrISn687g==",
+ "dev": true,
+ "requires": {
+ "@types/unist": "^2.0.2"
+ }
+ },
+ "unist-util-visit": {
+ "version": "4.1.2",
+ "resolved": "https://registry.npmjs.org/unist-util-visit/-/unist-util-visit-4.1.2.tgz",
+ "integrity": "sha512-MSd8OUGISqHdVvfY9TPhyK2VdUrPgxkUtWSuMHF6XAAFuL4LokseigBnZtPnJMu+FbynTkFNnFlyjxpVKujMRg==",
+ "dev": true,
+ "requires": {
+ "@types/unist": "^2.0.0",
+ "unist-util-is": "^5.0.0",
+ "unist-util-visit-parents": "^5.1.1"
+ },
+ "dependencies": {
+ "unist-util-is": {
+ "version": "5.2.1",
+ "resolved": "https://registry.npmjs.org/unist-util-is/-/unist-util-is-5.2.1.tgz",
+ "integrity": "sha512-u9njyyfEh43npf1M+yGKDGVPbY/JWEemg5nH05ncKPfi+kBbKBJoTdsogMu33uhytuLlv9y0O7GH7fEdwLdLQw==",
+ "dev": true,
+ "requires": {
+ "@types/unist": "^2.0.0"
+ }
+ }
+ }
+ },
+ "unist-util-visit-parents": {
+ "version": "5.1.3",
+ "resolved": "https://registry.npmjs.org/unist-util-visit-parents/-/unist-util-visit-parents-5.1.3.tgz",
+ "integrity": "sha512-x6+y8g7wWMyQhL1iZfhIPhDAs7Xwbn9nRosDXl7qoPTSCy0yNxnKc+hWokFifWQIDGi154rdUqKvbCa4+1kLhg==",
+ "dev": true,
+ "requires": {
+ "@types/unist": "^2.0.0",
+ "unist-util-is": "^5.0.0"
+ },
+ "dependencies": {
+ "unist-util-is": {
+ "version": "5.2.1",
+ "resolved": "https://registry.npmjs.org/unist-util-is/-/unist-util-is-5.2.1.tgz",
+ "integrity": "sha512-u9njyyfEh43npf1M+yGKDGVPbY/JWEemg5nH05ncKPfi+kBbKBJoTdsogMu33uhytuLlv9y0O7GH7fEdwLdLQw==",
+ "dev": true,
+ "requires": {
+ "@types/unist": "^2.0.0"
+ }
+ }
+ }
+ },
+ "universalify": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/universalify/-/universalify-1.0.0.tgz",
+ "integrity": "sha512-rb6X1W158d7pRQBg5gkR8uPaSfiids68LTJQYOtEUhoJUWBdaQHsuT/EUduxXYxcrt4r5PJ4fuHW1MHT6p0qug==",
+ "dev": true
+ },
+ "unset-value": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/unset-value/-/unset-value-1.0.0.tgz",
+ "integrity": "sha1-g3aHP30jNRef+x5vw6jtDfyKtVk=",
+ "dev": true,
+ "peer": true,
+ "requires": {
+ "has-value": "^0.3.1",
+ "isobject": "^3.0.0"
+ },
+ "dependencies": {
+ "has-value": {
+ "version": "0.3.1",
+ "resolved": "https://registry.npmjs.org/has-value/-/has-value-0.3.1.tgz",
+ "integrity": "sha1-ex9YutpiyoJ+wKIHgCVlSEWZXh8=",
+ "dev": true,
+ "peer": true,
+ "requires": {
+ "get-value": "^2.0.3",
+ "has-values": "^0.1.4",
+ "isobject": "^2.0.0"
+ },
+ "dependencies": {
+ "isobject": {
+ "version": "2.1.0",
+ "resolved": "https://registry.npmjs.org/isobject/-/isobject-2.1.0.tgz",
+ "integrity": "sha1-8GVWEJaj8dou9GJy+BXIQNh+DIk=",
+ "dev": true,
+ "peer": true,
+ "requires": {
+ "isarray": "1.0.0"
+ }
+ }
+ }
+ },
+ "has-values": {
+ "version": "0.1.4",
+ "resolved": "https://registry.npmjs.org/has-values/-/has-values-0.1.4.tgz",
+ "integrity": "sha1-bWHeldkd/Km5oCCJrThL/49it3E=",
+ "dev": true,
+ "peer": true
+ }
+ }
+ },
+ "uri-js": {
+ "version": "4.4.1",
+ "resolved": "https://registry.npmjs.org/uri-js/-/uri-js-4.4.1.tgz",
+ "integrity": "sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg==",
+ "dev": true,
+ "requires": {
+ "punycode": "^2.1.0"
+ }
+ },
+ "urix": {
+ "version": "0.1.0",
+ "resolved": "https://registry.npmjs.org/urix/-/urix-0.1.0.tgz",
+ "integrity": "sha1-2pN/emLiH+wf0Y1Js1wpNQZ6bHI=",
+ "dev": true,
+ "peer": true
+ },
+ "url-parse": {
+ "version": "1.5.10",
+ "resolved": "https://registry.npmjs.org/url-parse/-/url-parse-1.5.10.tgz",
+ "integrity": "sha512-WypcfiRhfeUP9vvF0j6rw0J3hrWrw6iZv3+22h6iRMJ/8z1Tj6XfLP4DsUix5MhMPnXpiHDoKyoZ/bdCkwBCiQ==",
+ "dev": true,
+ "peer": true,
+ "requires": {
+ "querystringify": "^2.1.1",
+ "requires-port": "^1.0.0"
+ }
+ },
+ "url-regex": {
+ "version": "5.0.0",
+ "resolved": "https://registry.npmjs.org/url-regex/-/url-regex-5.0.0.tgz",
+ "integrity": "sha512-O08GjTiAFNsSlrUWfqF1jH0H1W3m35ZyadHrGv5krdnmPPoxP27oDTqux/579PtaroiSGm5yma6KT1mHFH6Y/g==",
+ "dev": true,
+ "requires": {
+ "ip-regex": "^4.1.0",
+ "tlds": "^1.203.0"
+ }
+ },
+ "use": {
+ "version": "3.1.1",
+ "resolved": "https://registry.npmjs.org/use/-/use-3.1.1.tgz",
+ "integrity": "sha512-cwESVXlO3url9YWlFW/TA9cshCEhtu7IKJ/p5soJ/gGpj7vbvFrAY/eIioQ6Dw23KjZhYgiIo8HOs1nQ2vr/oQ==",
+ "dev": true,
+ "peer": true
+ },
+ "use-sync-external-store": {
+ "version": "1.2.0",
+ "resolved": "https://registry.npmjs.org/use-sync-external-store/-/use-sync-external-store-1.2.0.tgz",
+ "integrity": "sha512-eEgnFxGQ1Ife9bzYs6VLi8/4X6CObHMw9Qr9tPY43iKwsPw8xE8+EFsf/2cFZ5S3esXgpWgtSCtLNS41F+sKPA==",
+ "dev": true,
+ "requires": {}
+ },
+ "util-deprecate": {
+ "version": "1.0.2",
+ "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz",
+ "integrity": "sha1-RQ1Nyfpw3nMnYvvS1KKJgUGaDM8=",
+ "dev": true
+ },
+ "uuid": {
+ "version": "8.3.2",
+ "resolved": "https://registry.npmjs.org/uuid/-/uuid-8.3.2.tgz",
+ "integrity": "sha512-+NYs2QeMWy+GWFOEm9xnn6HCDp0l7QBD7ml8zLUmJ+93Q5NF0NocErnwkTkXVFNiX3/fpC6afS8Dhb/gz7R7eg==",
+ "dev": true,
+ "optional": true,
+ "peer": true
+ },
+ "v8-compile-cache": {
+ "version": "2.3.0",
+ "resolved": "https://registry.npmjs.org/v8-compile-cache/-/v8-compile-cache-2.3.0.tgz",
+ "integrity": "sha512-l8lCEmLcLYZh4nbunNZvQCJc5pv7+RCwa8q/LdUx8u7lsWvPDKmpodJAJNwkAhJC//dFY48KuIEmjtd4RViDrA==",
+ "dev": true
+ },
+ "v8-to-istanbul": {
+ "version": "7.1.2",
+ "resolved": "https://registry.npmjs.org/v8-to-istanbul/-/v8-to-istanbul-7.1.2.tgz",
+ "integrity": "sha512-TxNb7YEUwkLXCQYeudi6lgQ/SZrzNO4kMdlqVxaZPUIUjCv6iSSypUQX70kNBSERpQ8fk48+d61FXk+tgqcWow==",
+ "dev": true,
+ "peer": true,
+ "requires": {
+ "@types/istanbul-lib-coverage": "^2.0.1",
+ "convert-source-map": "^1.6.0",
+ "source-map": "^0.7.3"
+ },
+ "dependencies": {
+ "source-map": {
+ "version": "0.7.3",
+ "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.7.3.tgz",
+ "integrity": "sha512-CkCj6giN3S+n9qrYiBTX5gystlENnRW5jZeNLHpe6aue+SrHcG5VYwujhW9s4dY31mEGsxBDrHR6oI69fTXsaQ==",
+ "dev": true,
+ "peer": true
+ }
+ }
+ },
+ "validate-npm-package-license": {
+ "version": "3.0.4",
+ "resolved": "https://registry.npmjs.org/validate-npm-package-license/-/validate-npm-package-license-3.0.4.tgz",
+ "integrity": "sha512-DpKm2Ui/xN7/HQKCtpZxoRWBhZ9Z0kqtygG8XCgNQ8ZlDnxuQmWhj566j8fN4Cu3/JmbhsDo7fcAJq4s9h27Ew==",
+ "dev": true,
+ "requires": {
+ "spdx-correct": "^3.0.0",
+ "spdx-expression-parse": "^3.0.0"
+ }
+ },
+ "vfile": {
+ "version": "4.2.1",
+ "resolved": "https://registry.npmjs.org/vfile/-/vfile-4.2.1.tgz",
+ "integrity": "sha512-O6AE4OskCG5S1emQ/4gl8zK586RqA3srz3nfK/Viy0UPToBc5Trp9BVFb1u0CjsKrAWwnpr4ifM/KBXPWwJbCA==",
+ "dev": true,
+ "requires": {
+ "@types/unist": "^2.0.0",
+ "is-buffer": "^2.0.0",
+ "unist-util-stringify-position": "^2.0.0",
+ "vfile-message": "^2.0.0"
+ }
+ },
+ "vfile-location": {
+ "version": "3.2.0",
+ "resolved": "https://registry.npmjs.org/vfile-location/-/vfile-location-3.2.0.tgz",
+ "integrity": "sha512-aLEIZKv/oxuCDZ8lkJGhuhztf/BW4M+iHdCwglA/eWc+vtuRFJj8EtgceYFX4LRjOhCAAiNHsKGssC6onJ+jbA==",
+ "dev": true
+ },
+ "vfile-matter": {
+ "version": "4.0.1",
+ "resolved": "https://registry.npmjs.org/vfile-matter/-/vfile-matter-4.0.1.tgz",
+ "integrity": "sha512-ZeACdaxCOxhePpoLO4A5y/VgI9EuWBXu+sUk65aQ7lXBZDFg7X0tuOzigLJUtsQzazFt6K2m9SdlDxZdfL5vVg==",
+ "dev": true,
+ "requires": {
+ "is-buffer": "^2.0.0",
+ "vfile": "^5.0.0",
+ "yaml": "^2.0.0"
+ },
+ "dependencies": {
+ "unist-util-stringify-position": {
+ "version": "3.0.3",
+ "resolved": "https://registry.npmjs.org/unist-util-stringify-position/-/unist-util-stringify-position-3.0.3.tgz",
+ "integrity": "sha512-k5GzIBZ/QatR8N5X2y+drfpWG8IDBzdnVj6OInRNWm1oXrzydiaAT2OQiA8DPRRZyAKb9b6I2a6PxYklZD0gKg==",
+ "dev": true,
+ "requires": {
+ "@types/unist": "^2.0.0"
+ }
+ },
+ "vfile": {
+ "version": "5.3.7",
+ "resolved": "https://registry.npmjs.org/vfile/-/vfile-5.3.7.tgz",
+ "integrity": "sha512-r7qlzkgErKjobAmyNIkkSpizsFPYiUPuJb5pNW1RB4JcYVZhs4lIbVqk8XPk033CV/1z8ss5pkax8SuhGpcG8g==",
+ "dev": true,
+ "requires": {
+ "@types/unist": "^2.0.0",
+ "is-buffer": "^2.0.0",
+ "unist-util-stringify-position": "^3.0.0",
+ "vfile-message": "^3.0.0"
+ }
+ },
+ "vfile-message": {
+ "version": "3.1.4",
+ "resolved": "https://registry.npmjs.org/vfile-message/-/vfile-message-3.1.4.tgz",
+ "integrity": "sha512-fa0Z6P8HUrQN4BZaX05SIVXic+7kE3b05PWAtPuYP9QLHsLKYR7/AlLW3NtOrpXRLeawpDLMsVkmk5DG0NXgWw==",
+ "dev": true,
+ "requires": {
+ "@types/unist": "^2.0.0",
+ "unist-util-stringify-position": "^3.0.0"
+ }
+ },
+ "yaml": {
+ "version": "2.2.1",
+ "resolved": "https://registry.npmjs.org/yaml/-/yaml-2.2.1.tgz",
+ "integrity": "sha512-e0WHiYql7+9wr4cWMx3TVQrNwejKaEe7/rHNmQmqRjazfOP5W8PB6Jpebb5o6fIapbz9o9+2ipcaTM2ZwDI6lw==",
+ "dev": true
+ }
+ }
+ },
+ "vfile-message": {
+ "version": "2.0.4",
+ "resolved": "https://registry.npmjs.org/vfile-message/-/vfile-message-2.0.4.tgz",
+ "integrity": "sha512-DjssxRGkMvifUOJre00juHoP9DPWuzjxKuMDrhNbk2TdaYYBNMStsNhEOt3idrtI12VQYM/1+iM0KOzXi4pxwQ==",
+ "dev": true,
+ "requires": {
+ "@types/unist": "^2.0.0",
+ "unist-util-stringify-position": "^2.0.0"
+ }
+ },
+ "vfile-reporter": {
+ "version": "7.0.5",
+ "resolved": "https://registry.npmjs.org/vfile-reporter/-/vfile-reporter-7.0.5.tgz",
+ "integrity": "sha512-NdWWXkv6gcd7AZMvDomlQbK3MqFWL1RlGzMn++/O2TI+68+nqxCPTvLugdOtfSzXmjh+xUyhp07HhlrbJjT+mw==",
+ "dev": true,
+ "requires": {
+ "@types/supports-color": "^8.0.0",
+ "string-width": "^5.0.0",
+ "supports-color": "^9.0.0",
+ "unist-util-stringify-position": "^3.0.0",
+ "vfile": "^5.0.0",
+ "vfile-message": "^3.0.0",
+ "vfile-sort": "^3.0.0",
+ "vfile-statistics": "^2.0.0"
+ },
+ "dependencies": {
+ "ansi-regex": {
+ "version": "6.0.1",
+ "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-6.0.1.tgz",
+ "integrity": "sha512-n5M855fKb2SsfMIiFFoVrABHJC8QtHwVx+mHWP3QcEqBHYienj5dHSgjbxtC0WEZXYt4wcD6zrQElDPhFuZgfA==",
+ "dev": true
+ },
+ "string-width": {
+ "version": "5.1.2",
+ "resolved": "https://registry.npmjs.org/string-width/-/string-width-5.1.2.tgz",
+ "integrity": "sha512-HnLOCR3vjcY8beoNLtcjZ5/nxn2afmME6lhrDrebokqMap+XbeW8n9TXpPDOqdGK5qcI3oT0GKTW6wC7EMiVqA==",
+ "dev": true,
+ "requires": {
+ "eastasianwidth": "^0.2.0",
+ "emoji-regex": "^9.2.2",
+ "strip-ansi": "^7.0.1"
+ }
+ },
+ "strip-ansi": {
+ "version": "7.0.1",
+ "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-7.0.1.tgz",
+ "integrity": "sha512-cXNxvT8dFNRVfhVME3JAe98mkXDYN2O1l7jmcwMnOslDeESg1rF/OZMtK0nRAhiari1unG5cD4jG3rapUAkLbw==",
+ "dev": true,
+ "requires": {
+ "ansi-regex": "^6.0.1"
+ }
+ },
+ "supports-color": {
+ "version": "9.3.1",
+ "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-9.3.1.tgz",
+ "integrity": "sha512-knBY82pjmnIzK3NifMo3RxEIRD9E0kIzV4BKcyTZ9+9kWgLMxd4PrsTSMoFQUabgRBbF8KOLRDCyKgNV+iK44Q==",
+ "dev": true
+ },
+ "unist-util-stringify-position": {
+ "version": "3.0.3",
+ "resolved": "https://registry.npmjs.org/unist-util-stringify-position/-/unist-util-stringify-position-3.0.3.tgz",
+ "integrity": "sha512-k5GzIBZ/QatR8N5X2y+drfpWG8IDBzdnVj6OInRNWm1oXrzydiaAT2OQiA8DPRRZyAKb9b6I2a6PxYklZD0gKg==",
+ "dev": true,
+ "requires": {
+ "@types/unist": "^2.0.0"
+ }
+ },
+ "vfile": {
+ "version": "5.3.7",
+ "resolved": "https://registry.npmjs.org/vfile/-/vfile-5.3.7.tgz",
+ "integrity": "sha512-r7qlzkgErKjobAmyNIkkSpizsFPYiUPuJb5pNW1RB4JcYVZhs4lIbVqk8XPk033CV/1z8ss5pkax8SuhGpcG8g==",
+ "dev": true,
+ "requires": {
+ "@types/unist": "^2.0.0",
+ "is-buffer": "^2.0.0",
+ "unist-util-stringify-position": "^3.0.0",
+ "vfile-message": "^3.0.0"
+ }
+ },
+ "vfile-message": {
+ "version": "3.1.4",
+ "resolved": "https://registry.npmjs.org/vfile-message/-/vfile-message-3.1.4.tgz",
+ "integrity": "sha512-fa0Z6P8HUrQN4BZaX05SIVXic+7kE3b05PWAtPuYP9QLHsLKYR7/AlLW3NtOrpXRLeawpDLMsVkmk5DG0NXgWw==",
+ "dev": true,
+ "requires": {
+ "@types/unist": "^2.0.0",
+ "unist-util-stringify-position": "^3.0.0"
+ }
+ }
+ }
+ },
+ "vfile-reporter-json": {
+ "version": "3.3.0",
+ "resolved": "https://registry.npmjs.org/vfile-reporter-json/-/vfile-reporter-json-3.3.0.tgz",
+ "integrity": "sha512-/zgRtjxQ2UGJn+HViiZ7+nIXtUzkkXFQum3BmaS/bSyr10P0X41ETRqqwMJ95RtbKUah3m7pKb6oS1eZeXXHzQ==",
+ "dev": true,
+ "requires": {
+ "vfile": "^5.0.0",
+ "vfile-message": "^3.0.0"
+ },
+ "dependencies": {
+ "unist-util-stringify-position": {
+ "version": "3.0.3",
+ "resolved": "https://registry.npmjs.org/unist-util-stringify-position/-/unist-util-stringify-position-3.0.3.tgz",
+ "integrity": "sha512-k5GzIBZ/QatR8N5X2y+drfpWG8IDBzdnVj6OInRNWm1oXrzydiaAT2OQiA8DPRRZyAKb9b6I2a6PxYklZD0gKg==",
+ "dev": true,
+ "requires": {
+ "@types/unist": "^2.0.0"
+ }
+ },
+ "vfile": {
+ "version": "5.3.7",
+ "resolved": "https://registry.npmjs.org/vfile/-/vfile-5.3.7.tgz",
+ "integrity": "sha512-r7qlzkgErKjobAmyNIkkSpizsFPYiUPuJb5pNW1RB4JcYVZhs4lIbVqk8XPk033CV/1z8ss5pkax8SuhGpcG8g==",
+ "dev": true,
+ "requires": {
+ "@types/unist": "^2.0.0",
+ "is-buffer": "^2.0.0",
+ "unist-util-stringify-position": "^3.0.0",
+ "vfile-message": "^3.0.0"
+ }
+ },
+ "vfile-message": {
+ "version": "3.1.4",
+ "resolved": "https://registry.npmjs.org/vfile-message/-/vfile-message-3.1.4.tgz",
+ "integrity": "sha512-fa0Z6P8HUrQN4BZaX05SIVXic+7kE3b05PWAtPuYP9QLHsLKYR7/AlLW3NtOrpXRLeawpDLMsVkmk5DG0NXgWw==",
+ "dev": true,
+ "requires": {
+ "@types/unist": "^2.0.0",
+ "unist-util-stringify-position": "^3.0.0"
+ }
+ }
+ }
+ },
+ "vfile-sort": {
+ "version": "3.0.1",
+ "resolved": "https://registry.npmjs.org/vfile-sort/-/vfile-sort-3.0.1.tgz",
+ "integrity": "sha512-1os1733XY6y0D5x0ugqSeaVJm9lYgj0j5qdcZQFyxlZOSy1jYarL77lLyb5gK4Wqr1d5OxmuyflSO3zKyFnTFw==",
+ "dev": true,
+ "requires": {
+ "vfile": "^5.0.0",
+ "vfile-message": "^3.0.0"
+ },
+ "dependencies": {
+ "unist-util-stringify-position": {
+ "version": "3.0.3",
+ "resolved": "https://registry.npmjs.org/unist-util-stringify-position/-/unist-util-stringify-position-3.0.3.tgz",
+ "integrity": "sha512-k5GzIBZ/QatR8N5X2y+drfpWG8IDBzdnVj6OInRNWm1oXrzydiaAT2OQiA8DPRRZyAKb9b6I2a6PxYklZD0gKg==",
+ "dev": true,
+ "requires": {
+ "@types/unist": "^2.0.0"
+ }
+ },
+ "vfile": {
+ "version": "5.3.7",
+ "resolved": "https://registry.npmjs.org/vfile/-/vfile-5.3.7.tgz",
+ "integrity": "sha512-r7qlzkgErKjobAmyNIkkSpizsFPYiUPuJb5pNW1RB4JcYVZhs4lIbVqk8XPk033CV/1z8ss5pkax8SuhGpcG8g==",
+ "dev": true,
+ "requires": {
+ "@types/unist": "^2.0.0",
+ "is-buffer": "^2.0.0",
+ "unist-util-stringify-position": "^3.0.0",
+ "vfile-message": "^3.0.0"
+ }
+ },
+ "vfile-message": {
+ "version": "3.1.4",
+ "resolved": "https://registry.npmjs.org/vfile-message/-/vfile-message-3.1.4.tgz",
+ "integrity": "sha512-fa0Z6P8HUrQN4BZaX05SIVXic+7kE3b05PWAtPuYP9QLHsLKYR7/AlLW3NtOrpXRLeawpDLMsVkmk5DG0NXgWw==",
+ "dev": true,
+ "requires": {
+ "@types/unist": "^2.0.0",
+ "unist-util-stringify-position": "^3.0.0"
+ }
+ }
+ }
+ },
+ "vfile-statistics": {
+ "version": "2.0.1",
+ "resolved": "https://registry.npmjs.org/vfile-statistics/-/vfile-statistics-2.0.1.tgz",
+ "integrity": "sha512-W6dkECZmP32EG/l+dp2jCLdYzmnDBIw6jwiLZSER81oR5AHRcVqL+k3Z+pfH1R73le6ayDkJRMk0sutj1bMVeg==",
+ "dev": true,
+ "requires": {
+ "vfile": "^5.0.0",
+ "vfile-message": "^3.0.0"
+ },
+ "dependencies": {
+ "unist-util-stringify-position": {
+ "version": "3.0.3",
+ "resolved": "https://registry.npmjs.org/unist-util-stringify-position/-/unist-util-stringify-position-3.0.3.tgz",
+ "integrity": "sha512-k5GzIBZ/QatR8N5X2y+drfpWG8IDBzdnVj6OInRNWm1oXrzydiaAT2OQiA8DPRRZyAKb9b6I2a6PxYklZD0gKg==",
+ "dev": true,
+ "requires": {
+ "@types/unist": "^2.0.0"
+ }
+ },
+ "vfile": {
+ "version": "5.3.7",
+ "resolved": "https://registry.npmjs.org/vfile/-/vfile-5.3.7.tgz",
+ "integrity": "sha512-r7qlzkgErKjobAmyNIkkSpizsFPYiUPuJb5pNW1RB4JcYVZhs4lIbVqk8XPk033CV/1z8ss5pkax8SuhGpcG8g==",
+ "dev": true,
+ "requires": {
+ "@types/unist": "^2.0.0",
+ "is-buffer": "^2.0.0",
+ "unist-util-stringify-position": "^3.0.0",
+ "vfile-message": "^3.0.0"
+ }
+ },
+ "vfile-message": {
+ "version": "3.1.4",
+ "resolved": "https://registry.npmjs.org/vfile-message/-/vfile-message-3.1.4.tgz",
+ "integrity": "sha512-fa0Z6P8HUrQN4BZaX05SIVXic+7kE3b05PWAtPuYP9QLHsLKYR7/AlLW3NtOrpXRLeawpDLMsVkmk5DG0NXgWw==",
+ "dev": true,
+ "requires": {
+ "@types/unist": "^2.0.0",
+ "unist-util-stringify-position": "^3.0.0"
+ }
+ }
+ }
+ },
+ "w3c-hr-time": {
+ "version": "1.0.2",
+ "resolved": "https://registry.npmjs.org/w3c-hr-time/-/w3c-hr-time-1.0.2.tgz",
+ "integrity": "sha512-z8P5DvDNjKDoFIHK7q8r8lackT6l+jo/Ye3HOle7l9nICP9lf1Ci25fy9vHd0JOWewkIFzXIEig3TdKT7JQ5fQ==",
+ "dev": true,
+ "peer": true,
+ "requires": {
+ "browser-process-hrtime": "^1.0.0"
+ }
+ },
+ "w3c-xmlserializer": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/w3c-xmlserializer/-/w3c-xmlserializer-2.0.0.tgz",
+ "integrity": "sha512-4tzD0mF8iSiMiNs30BiLO3EpfGLZUT2MSX/G+o7ZywDzliWQ3OPtTZ0PTC3B3ca1UAf4cJMHB+2Bf56EriJuRA==",
+ "dev": true,
+ "peer": true,
+ "requires": {
+ "xml-name-validator": "^3.0.0"
+ }
+ },
+ "walker": {
+ "version": "1.0.8",
+ "resolved": "https://registry.npmjs.org/walker/-/walker-1.0.8.tgz",
+ "integrity": "sha512-ts/8E8l5b7kY0vlWLewOkDXMmPdLcVV4GmOQLyxuSswIJsweeFZtAsMF7k1Nszz+TYBQrlYRmzOnr398y1JemQ==",
+ "dev": true,
+ "peer": true,
+ "requires": {
+ "makeerror": "1.0.12"
+ }
+ },
+ "webidl-conversions": {
+ "version": "6.1.0",
+ "resolved": "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-6.1.0.tgz",
+ "integrity": "sha512-qBIvFLGiBpLjfwmYAaHPXsn+ho5xZnGvyGvsarywGNc8VyQJUMHJ8OBKGGrPER0okBeMDaan4mNBlgBROxuI8w==",
+ "dev": true,
+ "peer": true
+ },
+ "whatwg-encoding": {
+ "version": "1.0.5",
+ "resolved": "https://registry.npmjs.org/whatwg-encoding/-/whatwg-encoding-1.0.5.tgz",
+ "integrity": "sha512-b5lim54JOPN9HtzvK9HFXvBma/rnfFeqsic0hSpjtDbVxR3dJKLc+KB4V6GgiGOvl7CY/KNh8rxSo9DKQrnUEw==",
+ "dev": true,
+ "peer": true,
+ "requires": {
+ "iconv-lite": "0.4.24"
+ }
+ },
+ "whatwg-mimetype": {
+ "version": "2.3.0",
+ "resolved": "https://registry.npmjs.org/whatwg-mimetype/-/whatwg-mimetype-2.3.0.tgz",
+ "integrity": "sha512-M4yMwr6mAnQz76TbJm914+gPpB/nCwvZbJU28cUD6dR004SAxDLOOSUaB1JDRqLtaOV/vi0IC5lEAGFgrjGv/g==",
+ "dev": true,
+ "peer": true
+ },
+ "whatwg-url": {
+ "version": "8.7.0",
+ "resolved": "https://registry.npmjs.org/whatwg-url/-/whatwg-url-8.7.0.tgz",
+ "integrity": "sha512-gAojqb/m9Q8a5IV96E3fHJM70AzCkgt4uXYX2O7EmuyOnLrViCQlsEBmF9UQIu3/aeAIp2U17rtbpZWNntQqdg==",
+ "dev": true,
+ "peer": true,
+ "requires": {
+ "lodash": "^4.7.0",
+ "tr46": "^2.1.0",
+ "webidl-conversions": "^6.1.0"
+ }
+ },
+ "which": {
+ "version": "2.0.2",
+ "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz",
+ "integrity": "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==",
+ "dev": true,
+ "requires": {
+ "isexe": "^2.0.0"
+ }
+ },
+ "which-boxed-primitive": {
+ "version": "1.0.2",
+ "resolved": "https://registry.npmjs.org/which-boxed-primitive/-/which-boxed-primitive-1.0.2.tgz",
+ "integrity": "sha512-bwZdv0AKLpplFY2KZRX6TvyuN7ojjr7lwkg6ml0roIy9YeuSr7JS372qlNW18UQYzgYK9ziGcerWqZOmEn9VNg==",
+ "dev": true,
+ "requires": {
+ "is-bigint": "^1.0.1",
+ "is-boolean-object": "^1.1.0",
+ "is-number-object": "^1.0.4",
+ "is-string": "^1.0.5",
+ "is-symbol": "^1.0.3"
+ }
+ },
+ "which-collection": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/which-collection/-/which-collection-1.0.1.tgz",
+ "integrity": "sha512-W8xeTUwaln8i3K/cY1nGXzdnVZlidBcagyNFtBdD5kxnb4TvGKR7FfSIS3mYpwWS1QUCutfKz8IY8RjftB0+1A==",
+ "dev": true,
+ "requires": {
+ "is-map": "^2.0.1",
+ "is-set": "^2.0.1",
+ "is-weakmap": "^2.0.1",
+ "is-weakset": "^2.0.1"
+ }
+ },
+ "which-module": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/which-module/-/which-module-2.0.0.tgz",
+ "integrity": "sha1-2e8H3Od7mQK4o6j6SzHD4/fm6Ho=",
+ "dev": true,
+ "peer": true
+ },
+ "which-pm-runs": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/which-pm-runs/-/which-pm-runs-1.0.0.tgz",
+ "integrity": "sha1-Zws6+8VS4LVd9rd4DKdGFfI60cs=",
+ "dev": true
+ },
+ "which-typed-array": {
+ "version": "1.1.9",
+ "resolved": "https://registry.npmjs.org/which-typed-array/-/which-typed-array-1.1.9.tgz",
+ "integrity": "sha512-w9c4xkx6mPidwp7180ckYWfMmvxpjlZuIudNtDf4N/tTAUB8VJbX25qZoAsrtGuYNnGw3pa0AXgbGKRB8/EceA==",
+ "dev": true,
+ "requires": {
+ "available-typed-arrays": "^1.0.5",
+ "call-bind": "^1.0.2",
+ "for-each": "^0.3.3",
+ "gopd": "^1.0.1",
+ "has-tostringtag": "^1.0.0",
+ "is-typed-array": "^1.1.10"
+ }
+ },
+ "word-wrap": {
+ "version": "1.2.3",
+ "resolved": "https://registry.npmjs.org/word-wrap/-/word-wrap-1.2.3.tgz",
+ "integrity": "sha512-Hz/mrNwitNRh/HUAtM/VT/5VH+ygD6DV7mYKZAtHOrbs8U7lvPS6xf7EJKMF0uW1KJCl0H701g3ZGus+muE5vQ==",
+ "dev": true
+ },
+ "wrap-ansi": {
+ "version": "7.0.0",
+ "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-7.0.0.tgz",
+ "integrity": "sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==",
+ "dev": true,
+ "requires": {
+ "ansi-styles": "^4.0.0",
+ "string-width": "^4.1.0",
+ "strip-ansi": "^6.0.0"
+ }
+ },
+ "wrappy": {
+ "version": "1.0.2",
+ "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz",
+ "integrity": "sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8=",
+ "dev": true
+ },
+ "write-file-atomic": {
+ "version": "3.0.3",
+ "resolved": "https://registry.npmjs.org/write-file-atomic/-/write-file-atomic-3.0.3.tgz",
+ "integrity": "sha512-AvHcyZ5JnSfq3ioSyjrBkH9yW4m7Ayk8/9My/DD9onKeu/94fwrMocemO2QAJFAlnnDN+ZDS+ZjAR5ua1/PV/Q==",
+ "dev": true,
+ "requires": {
+ "imurmurhash": "^0.1.4",
+ "is-typedarray": "^1.0.0",
+ "signal-exit": "^3.0.2",
+ "typedarray-to-buffer": "^3.1.5"
+ }
+ },
+ "ws": {
+ "version": "7.5.7",
+ "resolved": "https://registry.npmjs.org/ws/-/ws-7.5.7.tgz",
+ "integrity": "sha512-KMvVuFzpKBuiIXW3E4u3mySRO2/mCHSyZDJQM5NQ9Q9KHWHWh0NHgfbRMLLrceUK5qAL4ytALJbpRMjixFZh8A==",
+ "dev": true,
+ "peer": true,
+ "requires": {}
+ },
+ "xml-name-validator": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/xml-name-validator/-/xml-name-validator-3.0.0.tgz",
+ "integrity": "sha512-A5CUptxDsvxKJEU3yO6DuWBSJz/qizqzJKOMIfUJHETbBw/sFaDxgd6fxm1ewUaM0jZ444Fc5vC5ROYurg/4Pw==",
+ "dev": true,
+ "peer": true
+ },
+ "xmlchars": {
+ "version": "2.2.0",
+ "resolved": "https://registry.npmjs.org/xmlchars/-/xmlchars-2.2.0.tgz",
+ "integrity": "sha512-JZnDKK8B0RCDw84FNdDAIpZK+JuJw+s7Lz8nksI7SIuU3UXJJslUthsi+uWBUYOwPFwW7W7PRLRfUKpxjtjFCw==",
+ "dev": true,
+ "peer": true
+ },
+ "xtend": {
+ "version": "4.0.2",
+ "resolved": "https://registry.npmjs.org/xtend/-/xtend-4.0.2.tgz",
+ "integrity": "sha512-LKYU1iAXJXUgAXn9URjiu+MWhyUXHsvfp7mcuYm9dSUKK0/CjtrUwFAxD82/mCWbtLsGjFIad0wIsod4zrTAEQ==",
+ "dev": true
+ },
+ "y18n": {
+ "version": "4.0.3",
+ "resolved": "https://registry.npmjs.org/y18n/-/y18n-4.0.3.tgz",
+ "integrity": "sha512-JKhqTOwSrqNA1NY5lSztJ1GrBiUodLMmIZuLiDaMRJ+itFd+ABVE8XBjOvIWL+rSqNDC74LCSFmlb/U4UZ4hJQ==",
+ "dev": true,
+ "peer": true
+ },
+ "yallist": {
+ "version": "4.0.0",
+ "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz",
+ "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==",
+ "dev": true
+ },
+ "yaml": {
+ "version": "1.10.2",
+ "resolved": "https://registry.npmjs.org/yaml/-/yaml-1.10.2.tgz",
+ "integrity": "sha512-r3vXyErRCYJ7wg28yvBY5VSoAF8ZvlcW9/BwUzEtUsjvX/DKs24dIkuwjtuprwJJHsbyUbLApepYTR1BN4uHrg==",
+ "dev": true
+ },
+ "yargs": {
+ "version": "15.4.1",
+ "resolved": "https://registry.npmjs.org/yargs/-/yargs-15.4.1.tgz",
+ "integrity": "sha512-aePbxDmcYW++PaqBsJ+HYUFwCdv4LVvdnhBy78E57PIor8/OVvhMrADFFEDh8DHDFRv/O9i3lPhsENjO7QX0+A==",
+ "dev": true,
+ "peer": true,
+ "requires": {
+ "cliui": "^6.0.0",
+ "decamelize": "^1.2.0",
+ "find-up": "^4.1.0",
+ "get-caller-file": "^2.0.1",
+ "require-directory": "^2.1.1",
+ "require-main-filename": "^2.0.0",
+ "set-blocking": "^2.0.0",
+ "string-width": "^4.2.0",
+ "which-module": "^2.0.0",
+ "y18n": "^4.0.0",
+ "yargs-parser": "^18.1.2"
+ },
+ "dependencies": {
+ "find-up": {
+ "version": "4.1.0",
+ "resolved": "https://registry.npmjs.org/find-up/-/find-up-4.1.0.tgz",
+ "integrity": "sha512-PpOwAdQ/YlXQ2vj8a3h8IipDuYRi3wceVQQGYWxNINccq40Anw7BlsEXCMbt1Zt+OLA6Fq9suIpIWD0OsnISlw==",
+ "dev": true,
+ "peer": true,
+ "requires": {
+ "locate-path": "^5.0.0",
+ "path-exists": "^4.0.0"
+ }
+ },
+ "locate-path": {
+ "version": "5.0.0",
+ "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-5.0.0.tgz",
+ "integrity": "sha512-t7hw9pI+WvuwNJXwk5zVHpyhIqzg2qTlklJOf0mVxGSbe3Fp2VieZcduNYjaLDoy6p9uGpQEGWG87WpMKlNq8g==",
+ "dev": true,
+ "peer": true,
+ "requires": {
+ "p-locate": "^4.1.0"
+ }
+ },
+ "p-limit": {
+ "version": "2.3.0",
+ "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-2.3.0.tgz",
+ "integrity": "sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w==",
+ "dev": true,
+ "peer": true,
+ "requires": {
+ "p-try": "^2.0.0"
+ }
+ },
+ "p-locate": {
+ "version": "4.1.0",
+ "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-4.1.0.tgz",
+ "integrity": "sha512-R79ZZ/0wAxKGu3oYMlz8jy/kbhsNrS7SKZ7PxEHBgJ5+F2mtFW2fK2cOtBh1cHYkQsbzFV7I+EoRKe6Yt0oK7A==",
+ "dev": true,
+ "peer": true,
+ "requires": {
+ "p-limit": "^2.2.0"
+ }
+ },
+ "yargs-parser": {
+ "version": "18.1.3",
+ "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-18.1.3.tgz",
+ "integrity": "sha512-o50j0JeToy/4K6OZcaQmW6lyXXKhq7csREXcDwk2omFPJEwUNOVtJKvmDr9EI1fAJZUyZcRF7kxGBWmRXudrCQ==",
+ "dev": true,
+ "peer": true,
+ "requires": {
+ "camelcase": "^5.0.0",
+ "decamelize": "^1.2.0"
+ }
+ }
+ }
+ },
+ "yargs-parser": {
+ "version": "20.2.9",
+ "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-20.2.9.tgz",
+ "integrity": "sha512-y11nGElTIV+CT3Zv9t7VKl+Q3hTQoT9a1Qzezhhl6Rp21gJ/IVTW7Z3y9EWXhuUBC2Shnf+DX0antecpAwSP8w==",
+ "dev": true
+ },
+ "yocto-queue": {
+ "version": "0.1.0",
+ "resolved": "https://registry.npmjs.org/yocto-queue/-/yocto-queue-0.1.0.tgz",
+ "integrity": "sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q==",
+ "dev": true
+ },
+ "zod": {
+ "version": "3.21.4",
+ "resolved": "https://registry.npmjs.org/zod/-/zod-3.21.4.tgz",
+ "integrity": "sha512-m46AKbrzKVzOzs/DZgVnG5H55N1sv1M8qZU3A8RIKbs3mrACDNeIOeilDymVb2HdmP8uwshOCF4uJ8uM9rCqJw==",
+ "dev": true
+ },
+ "zwitch": {
+ "version": "1.0.5",
+ "resolved": "https://registry.npmjs.org/zwitch/-/zwitch-1.0.5.tgz",
+ "integrity": "sha512-V50KMwwzqJV0NpZIZFwfOD5/lyny3WlSzRiXgA0G7VUnRlqttta1L6UQIHzd6EuBY/cHGfwTIck7w1yH6Q5zUw==",
+ "dev": true
+ }
+ }
+}
diff --git a/v1.9.4/website/package.json b/v1.9.4/website/package.json
new file mode 100644
index 0000000..fe977d4
--- /dev/null
+++ b/v1.9.4/website/package.json
@@ -0,0 +1,31 @@
+{
+ "name": "packer-docs",
+ "description": "Documentation website for HashiCorp Packer",
+ "version": "1.0.0",
+ "author": "HashiCorp",
+ "devDependencies": {
+ "@hashicorp/platform-cli": "^2.6.0",
+ "@hashicorp/platform-content-conformance": "^0.0.10",
+ "dart-linkcheck": "2.0.15",
+ "husky": "4.3.8",
+ "next": "^12.3.1",
+ "prettier": "2.2.1"
+ },
+ "husky": {
+ "hooks": {
+ "pre-commit": "next-hashicorp precommit"
+ }
+ },
+ "main": "index.js",
+ "scripts": {
+ "build": "./scripts/website-build.sh",
+ "format": "next-hashicorp format",
+ "lint": "next-hashicorp lint",
+ "start": "./scripts/website-start.sh",
+ "linkcheck": "linkcheck https://packer.io",
+ "content-check": "hc-content --config base-docs"
+ },
+ "engines": {
+ "npm": ">=7.0.0"
+ }
+}
diff --git a/v1.9.4/website/prettier.config.js b/v1.9.4/website/prettier.config.js
new file mode 100644
index 0000000..b3ac14a
--- /dev/null
+++ b/v1.9.4/website/prettier.config.js
@@ -0,0 +1,3 @@
+module.exports = {
+ ...require('@hashicorp/platform-cli/config/prettier.config'),
+}
diff --git a/v1.9.4/website/public/favicon.ico b/v1.9.4/website/public/favicon.ico
new file mode 100644
index 0000000..b5409b5
--- /dev/null
+++ b/v1.9.4/website/public/favicon.ico
Binary files differ
diff --git a/v1.9.4/website/public/files/press-kit.zip b/v1.9.4/website/public/files/press-kit.zip
new file mode 100644
index 0000000..23bc7cc
--- /dev/null
+++ b/v1.9.4/website/public/files/press-kit.zip
Binary files differ
diff --git a/v1.9.4/website/public/ie-warning.js b/v1.9.4/website/public/ie-warning.js
new file mode 100644
index 0000000..db619bf
--- /dev/null
+++ b/v1.9.4/website/public/ie-warning.js
@@ -0,0 +1,40 @@
+!(function () {
+ 'use strict'
+
+ function applyStyles(e, s) {
+ e.style.cssText = s
+ .map(function (r) {
+ return r.join(':')
+ })
+ .join(';')
+ }
+
+ const el = document.createElement('div')
+ const containerStyles = [
+ ['background-color', '#FCF0F2'],
+ ['border-bottom', '1px solid #FFD4D6'],
+ ['color', '#BA2226'],
+ ['text-align', 'center'],
+ ['font-family', '"Segoe UI", sans-serif'],
+ ['font-weight', 'bold'],
+ ]
+ applyStyles(el, containerStyles)
+
+ const message = document.createElement('p')
+ const textStyles = [
+ ['padding', '16px 0'],
+ ['margin', '0'],
+ ['color', '#BA2226'],
+ ]
+ applyStyles(message, textStyles)
+ message.textContent = 'Internet Explorer is no longer supported. '
+
+ const link = document.createElement('a')
+ link.textContent = 'Learn more.'
+ link.href = 'https://www.microsoft.com/en-us/edge?form=MA13DL&OCID=MA13DL'
+
+ message.appendChild(link)
+ el.appendChild(message)
+
+ document.body.insertBefore(el, document.body.childNodes[0])
+})()
diff --git a/v1.9.4/website/public/img/branded-cta/cta-right.svg b/v1.9.4/website/public/img/branded-cta/cta-right.svg
new file mode 100644
index 0000000..aa8de3c
--- /dev/null
+++ b/v1.9.4/website/public/img/branded-cta/cta-right.svg
@@ -0,0 +1 @@
+<svg width="388" height="335" viewBox="0 0 388 335" fill="none" xmlns="http://www.w3.org/2000/svg"><path d="M285.752 167h-2.754L195 116.758v-1.572l90.542 51.694.21.12zm-81.25 0L195 161.574v1.572l6.749 3.854h2.753zm64.791-.12L195 124.463v1.573L266.749 167h2.753l-.209-.12zm-16.25 0L195 133.74v1.573L250.499 167h2.754l-.21-.12zm-32.5 0L195 152.296v1.573L217.998 167h2.754l-.209-.12zm16.249 0L195 143.018v1.573L234.249 167h2.753l-.21-.12zM299.248 0h2.754L390 50.242v1.572L299.457.12l-.209-.12zm81.25 0L390 5.426V3.854L383.251 0h-2.753zm-64.791.12L390 42.537v-1.573L318.251 0h-2.754l.21.12zm16.25 0L390 33.26v-1.573L334.501 0h-2.754l.21.12zm32.5 0L390 14.704V13.13L367.001 0h-2.754l.21.12zm-16.25 0L390 23.982v-1.573L350.751 0h-2.753l.209.12z" fill="#63D0FF"/><path d="M217.88 167h2.74L389 264.209v1.582l-170.911-98.67-.209-.121zm-15.958.121L389 275.124v-1.581L204.453 167h-2.74l.209.121zm48.5 0L389 247.125v-1.582L252.953 167h-2.74l.209.121zm-16.166 0L389 256.458v-1.581L236.786 167h-2.739l.209.121zm32.333 0L389 237.792v-1.582L269.12 167h-2.74l.209.121zm16.166 0L389 228.459v-1.582L285.286 167h-2.74l.209.121zM366.12 335h-2.74L195 237.791v-1.582l170.911 98.67.209.121zm15.958-.121L195 226.876v1.581L379.547 335h2.739l-.208-.121zm-48.5 0L195 254.875v1.582L331.047 335h2.739l-.208-.121zm16.166 0L195 245.542v1.581L347.214 335h2.739l-.209-.121zm-32.333 0L195 264.208v1.582L314.88 335h2.74l-.209-.121zm-16.166 0L195 273.541v1.582L298.714 335h2.739l-.208-.121zM285.287 335h-2.74L195 284.457v-1.582l90.078 52.004.209.121zm-80.834 0L195 329.542v1.581l6.714 3.877h2.739zm64.459-.121L195 292.209v1.581L266.381 335h2.739l-.208-.121zm-16.167 0L195 301.541v1.582L250.214 335h2.74l-.209-.121zm-32.333 0L195 320.208v1.583L217.88 335h2.74l-.208-.121zm16.166 0L195 310.875v1.581L234.047 335h2.74l-.209-.121zM388.93 293.751L195 181.79v-1.58l.07.04L389 292.209v1.582l-.07-.04zm.07 9.373v-1.582l-193.93-111.96-.07-.04v1.582l193.93 111.96.07.04zm0-18.666v-1.583L195.07 170.916l-.07-.04v1.581l193.93 111.961.07.04zm0 27.999v-1.581l-193.93-111.96-.07-.04v1.581l193.93 111.96.07.04zm0 9.334v-1.582l-193.93-111.96-.07-.04v1.582L388.93 321.75l.07.041zm0 9.333v-1.581l-193.93-111.96-.07-.041v1.582l193.93 111.96.07.04zM1 273.647a.684.684 0 00-.67.821.687.687 0 00.537.539.676.676 0 00.701-.292.69.69 0 00-.306-1.016.654.654 0 00-.262-.052zm0-9.334a.685.685 0 00-.67.821.69.69 0 00.537.54.684.684 0 00.765-.937.693.693 0 00-.37-.372.69.69 0 00-.262-.052zm0 18.667a.677.677 0 00-.631.424.691.691 0 00.498.937.684.684 0 00.765-.937.683.683 0 00-.632-.424zm0-37.334a.688.688 0 00-.133 1.361.684.684 0 00.765-.937.679.679 0 00-.37-.371.673.673 0 00-.262-.053zm0 9.334a.685.685 0 00-.67.821.678.678 0 00.932.5.684.684 0 00.422-.634.69.69 0 00-.422-.635.69.69 0 00-.262-.052zm0 65.333a.685.685 0 00-.67.821.69.69 0 00.537.54.684.684 0 00.765-.937.693.693 0 00-.37-.372.69.69 0 00-.262-.052zm0-9.333a.68.68 0 00-.631.424.69.69 0 00.148.748.68.68 0 001.051-.104A.687.687 0 001 310.98zm0-18.667a.685.685 0 00-.67.821.69.69 0 00.537.54.684.684 0 00.765-.937.693.693 0 00-.37-.372.69.69 0 00-.262-.052zm0 9.333a.685.685 0 00-.67.821.686.686 0 00.932.501.684.684 0 00.37-.897.672.672 0 00-.37-.372.673.673 0 00-.262-.053zm0-74.666a.68.68 0 00-.631.424.69.69 0 00.148.748.68.68 0 001.051-.104A.687.687 0 001 226.98zm0-37.333a.684.684 0 00-.67.821.687.687 0 00.537.539.676.676 0 00.701-.292.69.69 0 00-.306-1.016.654.654 0 00-.262-.052zm0-9.334a.685.685 0 00-.67.821.69.69 0 00.537.54.684.684 0 00.765-.937.693.693 0 00-.37-.372.69.69 0 00-.262-.052zm0-9.333a.685.685 0 00-.67.821.678.678 0 00.932.5.684.684 0 00.422-.634.69.69 0 00-.422-.635.69.69 0 00-.262-.052zm0 28a.677.677 0 00-.631.424.691.691 0 00.498.937.684.684 0 00.765-.937.683.683 0 00-.632-.424zm0 18.666a.685.685 0 00-.67.821.686.686 0 00.932.501.684.684 0 00.37-.897.672.672 0 00-.37-.372.673.673 0 00-.262-.053zm0-9.333a.685.685 0 00-.67.821.69.69 0 00.537.54.684.684 0 00.765-.937.693.693 0 00-.37-.372.69.69 0 00-.262-.052zm0 121.333a.688.688 0 00-.133 1.361.684.684 0 00.765-.937.679.679 0 00-.37-.371.673.673 0 00-.262-.053zm0-93.333a.685.685 0 00-.67.821.69.69 0 00.537.54.684.684 0 00.765-.937.693.693 0 00-.37-.372.69.69 0 00-.262-.052zm72.375-70a.685.685 0 00-.67.821.69.69 0 00.537.54.684.684 0 00.764-.937.693.693 0 00-.37-.372.69.69 0 00-.261-.052zm16.084 0a.686.686 0 00-.67.821.689.689 0 00.536.54.684.684 0 00.817-.674.684.684 0 00-.683-.687zm16.083 0a.688.688 0 00-.631.424.684.684 0 00.148.749.687.687 0 00.745.149.686.686 0 00.369-.898.68.68 0 00-.631-.424zm80.417 0a.69.69 0 00-.484 1.173.687.687 0 00.745.149.684.684 0 00.422-.635.684.684 0 00-.683-.687zm-144.75 0a.686.686 0 00-.67.821.689.689 0 00.536.54.684.684 0 00.817-.674.684.684 0 00-.683-.687zm128.666 0a.688.688 0 00-.631.424.692.692 0 00.148.749.687.687 0 00.745.149.684.684 0 00.221-1.121.679.679 0 00-.483-.201zm-144.75 0a.686.686 0 00-.67.821.689.689 0 00.537.54.684.684 0 00.817-.674.684.684 0 00-.683-.687zm96.5 0a.688.688 0 00-.631.424.692.692 0 00.148.749.687.687 0 00.745.149.684.684 0 00.221-1.121.692.692 0 00-.483-.201zm-64.333 0a.684.684 0 00-.67.821.69.69 0 00.537.54.684.684 0 00.764-.937.693.693 0 00-.37-.372.69.69 0 00-.261-.052zm80.417 0a.69.69 0 00-.484 1.173.687.687 0 00.745.149.684.684 0 00.422-.635.684.684 0 00-.683-.687zm-128.667 0a.685.685 0 00-.67.821.69.69 0 00.537.54.684.684 0 00.764-.937.693.693 0 00-.37-.372.69.69 0 00-.261-.052zm144.75 0a.688.688 0 00-.631.424.684.684 0 00.148.749.687.687 0 00.745.149.686.686 0 00.369-.898.68.68 0 00-.631-.424zm-88.458 98a.68.68 0 00-.631.424.69.69 0 00.497.937.684.684 0 00.817-.674.684.684 0 00-.683-.687zm0 56a.685.685 0 00-.67.821.689.689 0 00.536.54.684.684 0 00.617-1.159.681.681 0 00-.483-.202zm0-28a.685.685 0 00-.67.821.689.689 0 00.536.54.684.684 0 00.817-.674.684.684 0 00-.683-.687zm0 18.667a.684.684 0 00-.67.821.686.686 0 00.93.5.684.684 0 00.423-.634.69.69 0 00-.2-.486.68.68 0 00-.483-.201zm0-28a.677.677 0 00-.632.424.69.69 0 00.148.748.676.676 0 001.052-.104.69.69 0 00-.085-.867.68.68 0 00-.483-.201zm0-9.333a.676.676 0 00-.632.423.69.69 0 00.498.937.676.676 0 00.702-.292.69.69 0 00-.085-.867.68.68 0 00-.483-.201zm0 27.999a.685.685 0 00-.67.821.689.689 0 00.536.54.684.684 0 00.817-.674.688.688 0 00-.683-.687zm0-130.666a.68.68 0 00-.631.424.689.689 0 00.497.936.676.676 0 00.702-.292.687.687 0 00-.568-1.068zm8.041 154a.677.677 0 00-.631.424.691.691 0 00.498.937.684.684 0 00.764-.937.683.683 0 00-.631-.424zm-8.041-144.667a.68.68 0 00-.631.424.69.69 0 00.497.937.684.684 0 00.817-.674.684.684 0 00-.683-.687zm8.041 126a.677.677 0 00-.631.424.693.693 0 00.148.749.687.687 0 00.745.149.69.69 0 000-1.27.69.69 0 00-.262-.052zm-8.041-116.666a.676.676 0 00-.632.423.69.69 0 00.498.937.676.676 0 00.702-.292.69.69 0 00-.085-.867.68.68 0 00-.483-.201zm8.041 126a.684.684 0 00-.67.821.687.687 0 00.932.5.684.684 0 00.422-.635.684.684 0 00-.684-.686zM65.334 198.98a.677.677 0 00-.632.424.69.69 0 00.148.748.676.676 0 001.052-.104.69.69 0 00-.085-.867.68.68 0 00-.483-.201zm0 37.333a.685.685 0 00-.67.821.689.689 0 00.536.54.684.684 0 00.617-1.159.681.681 0 00-.483-.202zm0 18.667a.68.68 0 00-.631.424.689.689 0 00.497.936.676.676 0 00.702-.292.687.687 0 00-.568-1.068zm0-28a.684.684 0 00-.67.821.686.686 0 00.93.5.684.684 0 00.423-.634.69.69 0 00-.2-.486.68.68 0 00-.483-.201zm0 18.666a.685.685 0 00-.67.821.689.689 0 00.536.54.684.684 0 00.617-1.159.685.685 0 00-.483-.202zm0-28a.685.685 0 00-.67.821.689.689 0 00.536.54.684.684 0 00.817-.674.688.688 0 00-.683-.687zm0-9.333a.685.685 0 00-.67.821.689.689 0 00.536.54.684.684 0 00.817-.674.684.684 0 00-.683-.687zm-16.084-28a.68.68 0 00-.632.424.69.69 0 00.499.937.684.684 0 00.817-.674.684.684 0 00-.683-.687zm8.042 144.667a.677.677 0 00-.631.424.691.691 0 00.498.937.684.684 0 00.764-.937.682.682 0 00-.631-.424zm0-18.667a.685.685 0 00-.67.821.69.69 0 00.537.54.684.684 0 00.764-.937.694.694 0 00-.37-.372.69.69 0 00-.261-.052zm0-28a.684.684 0 00-.67.821.69.69 0 00.537.54.684.684 0 00.764-.937.693.693 0 00-.37-.372.69.69 0 00-.261-.052zm0 9.333a.688.688 0 10.262 1.322.684.684 0 00.421-.635.693.693 0 00-.2-.486.684.684 0 00-.483-.201zm0 9.334a.685.685 0 00-.67.821.678.678 0 00.932.5.684.684 0 00.37-.897.683.683 0 00-.632-.424zm0 18.667a.683.683 0 00-.67.821.687.687 0 00.537.539.676.676 0 00.701-.292.691.691 0 00-.307-1.016.654.654 0 00-.261-.052zM49.25 170.98a.68.68 0 00-.632.424.69.69 0 00.498.936.676.676 0 00.701-.292.687.687 0 00-.567-1.068zm0 37.333a.686.686 0 00-.67.821.689.689 0 00.536.54.684.684 0 00.817-.674.684.684 0 00-.683-.687zm0 9.333a.685.685 0 00-.671.821.689.689 0 00.537.54.684.684 0 00.817-.674.688.688 0 00-.683-.687zm0-27.999a.676.676 0 00-.632.423.691.691 0 00.148.749.679.679 0 001.051-.104.69.69 0 00-.084-.867.68.68 0 00-.483-.201zm0 9.333a.678.678 0 00-.632.424.69.69 0 00.148.749.678.678 0 00.745.148.684.684 0 00.422-.634.69.69 0 00-.2-.486.68.68 0 00-.483-.201zm8.04 42a.677.677 0 00-.63.424.691.691 0 00.498.937.684.684 0 00.764-.937.682.682 0 00-.631-.424zm0-46.667a.684.684 0 00-.67.821.69.69 0 00.538.54.684.684 0 00.764-.937.693.693 0 00-.37-.372.69.69 0 00-.261-.052zm0 74.667a.68.68 0 00-.631.424.691.691 0 00.149.748.68.68 0 001.051-.104.688.688 0 00-.568-1.068zm0-84a.68.68 0 00-.631.424.69.69 0 00.149.748.68.68 0 001.051-.104.688.688 0 00-.568-1.068zm0 28a.685.685 0 00-.67.821.678.678 0 00.932.5.684.684 0 00.37-.897.683.683 0 00-.631-.424zm0-37.334a.684.684 0 00-.67.821.685.685 0 00.932.501.684.684 0 00.422-.635.693.693 0 00-.2-.485.673.673 0 00-.483-.202zm0 28a.688.688 0 10.262 1.322.684.684 0 00.422-.635.693.693 0 00-.2-.486.684.684 0 00-.483-.201zm0 46.667a.684.684 0 00-.67.821.69.69 0 00.538.54.684.684 0 00.764-.937.694.694 0 00-.37-.372.69.69 0 00-.261-.052zm0 9.333a.684.684 0 00-.67.821.685.685 0 00.932.501.684.684 0 00.37-.897.673.673 0 00-.37-.372.673.673 0 00-.261-.053zm0-37.333a.685.685 0 00-.67.821.69.69 0 00.538.54.684.684 0 00.764-.937.694.694 0 00-.37-.372.69.69 0 00-.261-.052zm0 9.334a.683.683 0 00-.67.821.687.687 0 00.538.539.676.676 0 00.701-.292.691.691 0 00-.307-1.016.654.654 0 00-.261-.052zm8.043 97.999a.685.685 0 00-.67.821.689.689 0 00.536.54.684.684 0 00.617-1.159.685.685 0 00-.483-.202zm16.083-46.666a.677.677 0 00-.631.424.691.691 0 00.498.937.684.684 0 00.764-.937.682.682 0 00-.631-.424zm8.042 23.333a.68.68 0 00-.631.424.69.69 0 00.497.937.684.684 0 00.817-.674.684.684 0 00-.683-.687zm0-37.333a.684.684 0 00-.67.821.686.686 0 00.93.5.684.684 0 00.423-.634.69.69 0 00-.2-.486.68.68 0 00-.483-.201zm0 28a.68.68 0 00-.631.424.689.689 0 00.497.936.676.676 0 00.702-.292.687.687 0 00-.568-1.068zm0-9.334a.685.685 0 00-.67.821.69.69 0 00.536.54.684.684 0 00.617-1.159.685.685 0 00-.483-.202zm0 37.334a.677.677 0 00-.632.424.69.69 0 00.498.936.676.676 0 00.702-.292.69.69 0 00-.085-.867.68.68 0 00-.483-.201zm0-46.667a.685.685 0 00-.67.821.69.69 0 00.536.54.684.684 0 00.617-1.159.681.681 0 00-.483-.202zm0 37.334a.684.684 0 00-.67.82.686.686 0 00.93.501.684.684 0 00.423-.635.688.688 0 00-.683-.686zM81.417 170.98a.685.685 0 00-.67.821.678.678 0 00.932.5.684.684 0 00.37-.897.683.683 0 00-.632-.424zm0 37.333a.684.684 0 00-.67.821.69.69 0 00.537.54.684.684 0 00.764-.937.694.694 0 00-.37-.372.69.69 0 00-.261-.052zm0 9.333a.684.684 0 00-.67.821.685.685 0 00.931.501.684.684 0 00.37-.897.673.673 0 00-.37-.372.673.673 0 00-.261-.053zm0-37.333a.685.685 0 00-.67.821.69.69 0 00.537.54.684.684 0 00.764-.937.694.694 0 00-.37-.372.69.69 0 00-.261-.052zm0 18.667a.677.677 0 00-.631.424.691.691 0 00.498.937.684.684 0 00.764-.937.682.682 0 00-.631-.424zm8.042-4.667a.685.685 0 00-.67.821.69.69 0 00.536.54.684.684 0 00.617-1.159.681.681 0 00-.483-.202zm0 65.333a.685.685 0 00-.67.821.689.689 0 00.536.54.684.684 0 00.817-.674.688.688 0 00-.683-.687zm0-74.666a.684.684 0 00-.67.821.686.686 0 00.93.5.684.684 0 00.423-.634.69.69 0 00-.2-.486.68.68 0 00-.483-.201zm-8.042 42a.68.68 0 00-.631.424.691.691 0 00.148.748.68.68 0 001.051-.104.688.688 0 00-.568-1.068zm-8.042 70a.677.677 0 00-.631.424.692.692 0 00.148.749.678.678 0 00.745.148.683.683 0 00.422-.634.69.69 0 00-.684-.687zm-24.124-70a.684.684 0 00-.671.821.686.686 0 00.932.5.684.684 0 00.422-.634.69.69 0 00-.2-.486.68.68 0 00-.483-.201zm40.208-23.334a.685.685 0 00-.67.821.69.69 0 00.536.54.684.684 0 00.617-1.159.685.685 0 00-.483-.202zm0 46.667a.685.685 0 00-.67.821.69.69 0 00.536.54.684.684 0 00.817-.674.684.684 0 00-.683-.687zm0-9.333a.677.677 0 00-.632.424.69.69 0 00.498.936.676.676 0 00.702-.292.69.69 0 00-.085-.867.68.68 0 00-.483-.201zm0-18.667a.68.68 0 00-.631.424.69.69 0 00.497.937.684.684 0 00.817-.674.684.684 0 00-.683-.687zm0 9.334a.676.676 0 00-.632.423.69.69 0 00.498.937.676.676 0 00.702-.292.69.69 0 00-.085-.867.68.68 0 00-.483-.201zm0-18.667a.68.68 0 00-.631.424.689.689 0 00.497.936.676.676 0 00.702-.292.687.687 0 00-.568-1.068zm0-37.334a.685.685 0 00-.67.821.689.689 0 00.536.54.684.684 0 00.817-.674.688.688 0 00-.683-.687zm-16.084 46.667a.677.677 0 00-.631.424.693.693 0 00.148.749.687.687 0 00.745.149.69.69 0 000-1.27.69.69 0 00-.262-.052zm0 9.334a.684.684 0 00-.67.821.687.687 0 00.932.5.684.684 0 00.422-.635.684.684 0 00-.684-.686zm0-18.667a.677.677 0 00-.631.424.693.693 0 00.148.749.678.678 0 00.745.148.684.684 0 00.422-.634.69.69 0 00-.684-.687zm0-9.334a.688.688 0 00-.133 1.361.684.684 0 00.764-.937.678.678 0 00-.37-.371.672.672 0 00-.261-.053zm0-9.333a.685.685 0 00-.67.821.69.69 0 00.537.54.684.684 0 00.764-.937.693.693 0 00-.37-.371.672.672 0 00-.261-.053zm0 46.667a.677.677 0 00-.631.424.691.691 0 00.498.937.684.684 0 00.764-.937.683.683 0 00-.631-.424zm0 46.666a.688.688 0 00-.133 1.361.684.684 0 00.764-.937.678.678 0 00-.37-.371.672.672 0 00-.261-.053zm0-9.333a.685.685 0 00-.67.821.69.69 0 00.537.54.684.684 0 00.764-.937.693.693 0 00-.37-.371.672.672 0 00-.261-.053zm0-18.667a.684.684 0 00-.67.821.686.686 0 00.537.54.684.684 0 00.817-.674.688.688 0 00-.684-.687zm0-9.333a.685.685 0 00-.67.821.69.69 0 00.537.54.684.684 0 00.764-.937.693.693 0 00-.37-.372.69.69 0 00-.261-.052zm0 18.667a.677.677 0 00-.631.424.692.692 0 00.148.748.68.68 0 001.051-.104.687.687 0 00-.568-1.068zm8.042-23.334a.688.688 0 10.262 1.322.684.684 0 00.421-.635.693.693 0 00-.2-.485.67.67 0 00-.483-.202zm0 46.667a.685.685 0 00-.67.821.69.69 0 00.537.54.684.684 0 00.764-.937.693.693 0 00-.37-.372.69.69 0 00-.261-.052zm0-28a.677.677 0 00-.631.424.691.691 0 00.498.937c.132.026.27.012.395-.039a.69.69 0 00.221-1.121.686.686 0 00-.483-.201zm0 9.334a.684.684 0 00-.67.821.687.687 0 00.537.539.676.676 0 00.701-.292.691.691 0 00-.307-1.016.654.654 0 00-.261-.052zm-8.042-88.667a.677.677 0 00-.631.424.691.691 0 00.148.748.68.68 0 001.051-.104.687.687 0 00-.568-1.068zm8.042 70a.685.685 0 00-.67.821.678.678 0 00.932.5.684.684 0 00.37-.897.683.683 0 00-.632-.424zm0-18.667a.684.684 0 00-.67.821.69.69 0 00.537.54.684.684 0 00.764-.937.693.693 0 00-.37-.372.69.69 0 00-.261-.052zm0 65.333a.684.684 0 00-.67.821.685.685 0 00.931.501.684.684 0 00.37-.897.673.673 0 00-.37-.372.673.673 0 00-.261-.053zm-8.042-126a.684.684 0 00-.67.821.686.686 0 00.537.54.684.684 0 00.817-.674.686.686 0 00-.684-.687zm8.042 154a.688.688 0 10.262 1.322.684.684 0 00.421-.635.693.693 0 00-.2-.485.67.67 0 00-.483-.202zm0-9.333a.684.684 0 00-.67.821.69.69 0 00.537.54.684.684 0 00.764-.937.693.693 0 00-.37-.372.69.69 0 00-.261-.052zm0-9.333a.68.68 0 00-.631.424.691.691 0 00.148.748.68.68 0 001.051-.104.688.688 0 00-.568-1.068zm0-121.333a.683.683 0 00-.67.821.687.687 0 00.537.539.676.676 0 00.701-.292.691.691 0 00-.307-1.016.654.654 0 00-.261-.052zm-56.291 13.999a.685.685 0 00-.671.821.689.689 0 00.537.54.684.684 0 00.616-1.159.685.685 0 00-.483-.202zm-8.042 60.667a.685.685 0 00-.67.821.69.69 0 00.537.54.684.684 0 00.816-.674.681.681 0 00-.683-.687zm0-65.333a.677.677 0 00-.631.424.691.691 0 00.498.937.684.684 0 00.816-.674.688.688 0 00-.683-.687zm0-28a.685.685 0 00-.67.821.678.678 0 00.932.5.684.684 0 00.421-.634.681.681 0 00-.683-.687zm0 37.333a.684.684 0 00-.67.821.69.69 0 00.537.54.684.684 0 00.816-.674.685.685 0 00-.683-.687zm8.041 116.667a.678.678 0 00-.631.424.69.69 0 00.148.748.676.676 0 001.052-.104.69.69 0 00-.086-.867.68.68 0 00-.483-.201zm-8.041-107.334a.684.684 0 00-.67.821.685.685 0 00.931.501.684.684 0 00.422-.635.688.688 0 00-.683-.687zm0 28a.688.688 0 10.262 1.322.684.684 0 00.421-.635.686.686 0 00-.683-.687zm8.041 70.001a.684.684 0 00-.67.82.689.689 0 00.537.54.676.676 0 00.701-.292.69.69 0 00-.085-.867.68.68 0 00-.483-.201zm24.126-79.334a.686.686 0 00-.67.821.689.689 0 00.536.54.684.684 0 00.617-1.159.681.681 0 00-.483-.202zm-32.167-9.333a.68.68 0 00-.631.424.69.69 0 00.148.748.68.68 0 001.051-.104.687.687 0 00-.568-1.068zm0 9.333a.684.684 0 00-.67.821.69.69 0 00.537.54.684.684 0 00.816-.674.685.685 0 00-.683-.687zm0-46.666a.683.683 0 00-.67.821.687.687 0 00.537.539.676.676 0 00.701-.292.69.69 0 00-.085-.867.68.68 0 00-.483-.201zm8.041 60.666a.686.686 0 00-.67.821.689.689 0 00.537.54.684.684 0 00.817-.674.684.684 0 00-.683-.687zm0-9.333a.678.678 0 00-.631.424.69.69 0 00.148.749.678.678 0 00.745.148.684.684 0 00.422-.634.69.69 0 00-.2-.486.68.68 0 00-.484-.201zm0-9.333a.676.676 0 00-.631.423.691.691 0 00.148.749.679.679 0 001.051-.104.69.69 0 00-.085-.867.68.68 0 00-.483-.201zm0-9.334a.68.68 0 00-.631.424.69.69 0 00.498.937.684.684 0 00.817-.674.684.684 0 00-.683-.687zm0-9.333a.68.68 0 00-.631.424.69.69 0 00.498.936.676.676 0 00.701-.292.687.687 0 00-.568-1.068zm0 93.333a.68.68 0 00-.631.424.69.69 0 00.498.937.684.684 0 00.817-.674.684.684 0 00-.683-.687zm0-18.667a.685.685 0 00-.67.821.689.689 0 00.537.54.684.684 0 00.616-1.159.685.685 0 00-.483-.202zm0 9.334a.68.68 0 00-.631.424.69.69 0 00.498.936.676.676 0 00.701-.292.687.687 0 00-.568-1.068zm0-18.667a.686.686 0 00-.67.821.689.689 0 00.537.54.684.684 0 00.616-1.159.681.681 0 00-.483-.202zm0-9.333a.684.684 0 00-.67.821.686.686 0 00.932.5.684.684 0 00.422-.634.69.69 0 00-.2-.486.68.68 0 00-.484-.201zm0-9.334a.685.685 0 00-.67.821.689.689 0 00.537.54.684.684 0 00.817-.674.688.688 0 00-.684-.687zm-8.041-79.333a.685.685 0 00-.67.821.69.69 0 00.537.54.684.684 0 00.816-.674.681.681 0 00-.683-.687zm-8.042 79.333a.685.685 0 00-.67.821.686.686 0 00.931.501.684.684 0 00.37-.897.672.672 0 00-.37-.372.673.673 0 00-.261-.053zm0 9.334a.68.68 0 00-.631.424.691.691 0 00.148.748.68.68 0 001.051-.104.687.687 0 00-.568-1.068zm0-28a.677.677 0 00-.631.424.691.691 0 00.498.937.684.684 0 00.764-.937.683.683 0 00-.631-.424zm0 37.333a.685.685 0 00-.67.821.69.69 0 00.537.54.684.684 0 00.764-.937.693.693 0 00-.37-.372.69.69 0 00-.261-.052zm0-28a.685.685 0 00-.67.821.69.69 0 00.537.54.684.684 0 00.764-.937.693.693 0 00-.37-.372.69.69 0 00-.261-.052zm0 65.334a.684.684 0 00-.67.821.687.687 0 00.537.539.676.676 0 00.701-.292.69.69 0 00-.307-1.016.654.654 0 00-.261-.052zm0-93.334a.685.685 0 00-.67.821.69.69 0 00.537.54.684.684 0 00.764-.937.693.693 0 00-.37-.372.69.69 0 00-.261-.052zm0 102.667a.677.677 0 00-.631.424.691.691 0 00.498.937.684.684 0 00.764-.937.683.683 0 00-.631-.424zm0-28a.685.685 0 00-.67.821.678.678 0 00.932.5.684.684 0 00.421-.634.69.69 0 00-.422-.635.69.69 0 00-.261-.052zm0-9.334a.688.688 0 00-.133 1.361.684.684 0 00.764-.937.693.693 0 00-.37-.371.673.673 0 00-.261-.053zm0 18.667a.685.685 0 00-.67.821.69.69 0 00.537.54.684.684 0 00.764-.937.693.693 0 00-.37-.372.69.69 0 00-.261-.052zm8.042-14a.684.684 0 00-.67.821.69.69 0 00.537.54.684.684 0 00.816-.674.685.685 0 00-.683-.687zm0 28a.684.684 0 00-.67.821.69.69 0 00.537.54.684.684 0 00.816-.674.685.685 0 00-.683-.687zm0-9.333a.68.68 0 00-.631.424.69.69 0 00.148.748.68.68 0 001.051-.104.687.687 0 00-.568-1.068zm0-9.334a.684.684 0 00-.67.821.685.685 0 00.931.501.684.684 0 00.422-.635.688.688 0 00-.683-.687zm0-18.666a.677.677 0 00-.631.424.691.691 0 00.498.937.684.684 0 00.816-.674.688.688 0 00-.683-.687zm-8.042-70a.685.685 0 00-.67.821.678.678 0 00.932.5.684.684 0 00.421-.634.69.69 0 00-.422-.635.69.69 0 00-.261-.052zm8.042 60.667a.683.683 0 00-.67.821.687.687 0 00.537.539.676.676 0 00.701-.292.69.69 0 00-.085-.867.68.68 0 00-.483-.201zm-8.042-79.334a.685.685 0 00-.67.821.69.69 0 00.537.54.684.684 0 00.764-.937.693.693 0 00-.37-.372.69.69 0 00-.261-.052zm0 9.333a.688.688 0 00-.133 1.361.684.684 0 00.764-.937.693.693 0 00-.37-.371.673.673 0 00-.261-.053zm8.042 126a.688.688 0 10.262 1.322.684.684 0 00.421-.635.686.686 0 00-.683-.687zm-8.042-154a.685.685 0 00-.67.821.686.686 0 00.931.501.684.684 0 00.422-.635.693.693 0 00-.2-.485.672.672 0 00-.483-.202zm0 9.334a.68.68 0 00-.631.424.69.69 0 00.148.748.68.68 0 001.051-.104.687.687 0 00-.568-1.068zm8.042 70a.685.685 0 00-.67.821.678.678 0 00.932.5.684.684 0 00.421-.634.681.681 0 00-.683-.687zm24.125-42a.678.678 0 00-.632.424.689.689 0 00.498.936.676.676 0 00.702-.292.687.687 0 00-.568-1.068zm0 84a.678.678 0 00-.632.424.689.689 0 00.498.936.676.676 0 00.702-.292.687.687 0 00-.568-1.068zm0-65.333a.677.677 0 00-.632.423.69.69 0 00.498.937.676.676 0 00.702-.292.69.69 0 00-.085-.867.68.68 0 00-.483-.201zm0-28.001a.686.686 0 00-.484 1.173.686.686 0 00.745.149.684.684 0 00.422-.635.688.688 0 00-.683-.687zm0-9.333a.678.678 0 00-.632.424.69.69 0 00.498.937.684.684 0 00.617-1.159.681.681 0 00-.483-.202zm0 46.667a.677.677 0 00-.632.424.69.69 0 00.148.749.678.678 0 00.745.148.684.684 0 00.422-.634.69.69 0 00-.2-.486.68.68 0 00-.483-.201zm0 9.333a.678.678 0 00-.632.424.69.69 0 00.498.937.684.684 0 00.817-.674.684.684 0 00-.683-.687zm0 28a.678.678 0 00-.632.424.69.69 0 00.498.937.684.684 0 00.617-1.159.681.681 0 00-.483-.202zm0 9.333a.686.686 0 00-.484 1.173.686.686 0 00.745.149.684.684 0 00.422-.635.688.688 0 00-.683-.687zm0-28a.685.685 0 00-.67.821.689.689 0 00.536.54.684.684 0 00.817-.674.688.688 0 00-.683-.687zm0-74.666a.685.685 0 00-.484 1.172.679.679 0 001.052-.104.687.687 0 00-.568-1.068zm0 84a.685.685 0 00-.484 1.172.679.679 0 001.052-.104.687.687 0 00-.568-1.068zm0-46.667a.678.678 0 00-.632.424.69.69 0 00.498.937.684.684 0 00.817-.674.684.684 0 00-.683-.687zm0-46.667a.685.685 0 00-.67.821.689.689 0 00.536.54.684.684 0 00.817-.674.688.688 0 00-.683-.687zm8.041 98.001a.676.676 0 00-.631.423.691.691 0 00.148.749.679.679 0 001.051-.104.69.69 0 00-.084-.867.68.68 0 00-.483-.201zm0 9.333a.678.678 0 00-.631.424.69.69 0 00.148.748.676.676 0 001.051-.104.69.69 0 00-.085-.867.68.68 0 00-.482-.201zm0-37.334a.685.685 0 00-.67.821.689.689 0 00.537.54.684.684 0 00.617-1.159.685.685 0 00-.483-.202zm0 9.334a.68.68 0 00-.632.424.69.69 0 00.499.936.676.676 0 00.701-.292.687.687 0 00-.567-1.068zm0 9.333a.68.68 0 00-.632.424.69.69 0 00.499.937.684.684 0 00.817-.674.684.684 0 00-.683-.687zm0 28a.686.686 0 00-.67.821.689.689 0 00.537.54.684.684 0 00.817-.674.684.684 0 00-.683-.687zm0 28a.686.686 0 00-.67.821.689.689 0 00.537.54.684.684 0 00.617-1.159.681.681 0 00-.483-.202zm0 9.333a.685.685 0 00-.67.821.689.689 0 00.537.54.684.684 0 00.617-1.159.685.685 0 00-.483-.202zm0-28a.685.685 0 00-.67.821.689.689 0 00.537.54.684.684 0 00.817-.674.688.688 0 00-.683-.687zm0 9.334a.684.684 0 00-.67.821.686.686 0 00.932.5.684.684 0 00.422-.634.69.69 0 00-.2-.486.68.68 0 00-.483-.201zm-16.083-9.334a.684.684 0 00-.67.821.685.685 0 00.931.501.684.684 0 00.37-.897.673.673 0 00-.37-.372.673.673 0 00-.261-.053zm0-18.666a.677.677 0 00-.631.424.691.691 0 00.498.937.684.684 0 00.764-.937.682.682 0 00-.631-.424zm0 9.333a.684.684 0 00-.67.821.69.69 0 00.537.54.684.684 0 00.764-.937.694.694 0 00-.37-.372.69.69 0 00-.261-.052zm0-37.333a.685.685 0 00-.67.821.678.678 0 00.932.5.684.684 0 00.37-.897.683.683 0 00-.632-.424zm0 9.333a.685.685 0 00-.67.821.69.69 0 00.537.54c.132.026.27.012.395-.039a.69.69 0 00.221-1.121.689.689 0 00-.483-.201zm-8.042-70a.686.686 0 00-.67.821.689.689 0 00.537.54.684.684 0 00.616-1.159.681.681 0 00-.483-.202zm8.042 79.334a.683.683 0 00-.67.821.687.687 0 00.537.539.676.676 0 00.701-.292.691.691 0 00-.307-1.016.654.654 0 00-.261-.052zm-8.042-88.667a.684.684 0 00-.67.821.686.686 0 00.932.5.684.684 0 00.422-.634.69.69 0 00-.2-.486.68.68 0 00-.484-.201zm0-9.334a.685.685 0 00-.67.821.689.689 0 00.537.54.684.684 0 00.817-.674.688.688 0 00-.684-.687zm8.042 135.334a.68.68 0 00-.631.424.691.691 0 00.148.748.68.68 0 001.051-.104.688.688 0 00-.568-1.068zm0 9.333a.684.684 0 00-.67.821.69.69 0 00.537.54.684.684 0 00.764-.937.693.693 0 00-.37-.372.69.69 0 00-.261-.052zm0 9.333a.688.688 0 10.262 1.322.684.684 0 00.421-.635.693.693 0 00-.2-.485.67.67 0 00-.483-.202zm0-139.999a.683.683 0 00-.67.821.687.687 0 00.537.539.676.676 0 00.701-.292.691.691 0 00-.307-1.016.654.654 0 00-.261-.052zm8.042 116.666a.678.678 0 00-.632.424.69.69 0 00.498.937.684.684 0 00.817-.674.684.684 0 00-.683-.687zM33.167 170.98a.685.685 0 00-.67.821.678.678 0 00.932.5.684.684 0 00.37-.897.683.683 0 00-.632-.424zm0 9.333a.685.685 0 00-.67.821.69.69 0 00.537.54.684.684 0 00.764-.937.694.694 0 00-.37-.372.69.69 0 00-.261-.052zm8.042 135.334a.685.685 0 00-.484 1.172.679.679 0 001.052-.104.69.69 0 00-.085-.867.68.68 0 00-.483-.201zm0 9.333a.677.677 0 00-.632.424.69.69 0 00.148.749.678.678 0 00.745.148.684.684 0 00.422-.634.69.69 0 00-.2-.486.68.68 0 00-.483-.201zm-8.042-107.334a.684.684 0 00-.67.821.685.685 0 00.931.501.684.684 0 00.37-.897.673.673 0 00-.37-.372.673.673 0 00-.261-.053zm0 9.334a.68.68 0 00-.631.424.691.691 0 00.148.748.68.68 0 001.051-.104.688.688 0 00-.568-1.068zm0 9.333a.684.684 0 00-.67.821.69.69 0 00.537.54.684.684 0 00.764-.937.693.693 0 00-.37-.372.69.69 0 00-.261-.052zm0 9.333a.688.688 0 10.262 1.322.684.684 0 00.421-.635.693.693 0 00-.2-.486.684.684 0 00-.483-.201zm0-37.333a.684.684 0 00-.67.821.69.69 0 00.537.54.684.684 0 00.764-.937.694.694 0 00-.37-.372.69.69 0 00-.261-.052zm0-9.333a.677.677 0 00-.631.424.691.691 0 00.498.937.684.684 0 00.764-.937.682.682 0 00-.631-.424zM9.042 231.647a.684.684 0 00-.67.821.687.687 0 00.537.539.676.676 0 00.701-.292.69.69 0 00-.307-1.016.654.654 0 00-.261-.052zm144.75-28.001a.685.685 0 00-.67.821.68.68 0 00.537.54.685.685 0 00.394-1.308.665.665 0 00-.261-.053zm0-18.666a.68.68 0 00-.631.424.683.683 0 00.148.748.68.68 0 001.051-.104.688.688 0 00-.568-1.068zm0 9.333a.688.688 0 00-.631.424.684.684 0 00.148.749.687.687 0 00.745.149.686.686 0 00.369-.898.68.68 0 00-.631-.424zm0-18.667a.688.688 0 00-.631.424.684.684 0 00.148.749.683.683 0 001.114-.749.665.665 0 00-.148-.222.668.668 0 00-.222-.149.665.665 0 00-.261-.053zm8.042 154a.685.685 0 00-.671.821.687.687 0 00.932.501.684.684 0 00.422-.635.688.688 0 00-.683-.687zm0-9.333a.69.69 0 00-.484 1.173.687.687 0 00.745.149.684.684 0 00.422-.635.686.686 0 00-.683-.687zm-8.042-107.333a.68.68 0 00-.631.424.684.684 0 00.148.749.678.678 0 00.745.148.686.686 0 00.221-1.12.683.683 0 00-.483-.201zm0 37.333a.688.688 0 00-.631.424.684.684 0 00.148.749.687.687 0 00.745.149.686.686 0 00.369-.898.68.68 0 00-.631-.424zm0 9.333a.688.688 0 00-.631.425.68.68 0 00-.039.396.68.68 0 00.537.54.681.681 0 00.816-.674.673.673 0 00-.052-.262.66.66 0 00-.148-.223.668.668 0 00-.222-.149.665.665 0 00-.261-.053zm8.042 51.334a.684.684 0 00-.484 1.172.68.68 0 001.052-.104.688.688 0 00-.568-1.068zm0-130.667a.685.685 0 00-.671.821.687.687 0 00.932.501.684.684 0 00.422-.635.684.684 0 00-.683-.687zm-8.042 42a.68.68 0 00-.631.424.684.684 0 00.148.749.687.687 0 00.745.149.693.693 0 00.421-.635.678.678 0 00-.2-.486.683.683 0 00-.483-.201zm0 9.334a.685.685 0 00-.67.821.68.68 0 00.537.539.677.677 0 00.701-.292.691.691 0 00-.307-1.016.647.647 0 00-.261-.052zm8.042 42a.684.684 0 00-.484 1.172.68.68 0 001.052-.104.691.691 0 00-.085-.867.68.68 0 00-.483-.201zm0-65.334a.69.69 0 00-.484 1.173.687.687 0 00.745.149.684.684 0 00.422-.635.684.684 0 00-.683-.687zm0 9.333a.685.685 0 00-.671.821.687.687 0 00.932.501.684.684 0 00.222-1.12.685.685 0 00-.483-.202zm0 9.334a.684.684 0 00-.484 1.172.68.68 0 001.052-.104.688.688 0 00-.568-1.068zm0-28a.685.685 0 00-.671.821.682.682 0 001.239.247.69.69 0 00-.085-.867.68.68 0 00-.483-.201zm0-9.333a.677.677 0 00-.632.423.692.692 0 00.148.749.68.68 0 001.052-.104.691.691 0 00-.085-.867.68.68 0 00-.483-.201zm0 46.666a.69.69 0 00-.484 1.173.687.687 0 00.745.149.684.684 0 00.422-.635.686.686 0 00-.683-.687zm0 56a.69.69 0 00-.484 1.173.687.687 0 00.745.149.684.684 0 00.422-.635.684.684 0 00-.683-.687zm-8.042-23.333a.68.68 0 00-.631.424.684.684 0 00.148.748.68.68 0 001.051-.104.688.688 0 00-.568-1.068zm8.042-23.334a.685.685 0 00-.671.821.687.687 0 00.932.501.684.684 0 00.422-.635.688.688 0 00-.683-.687zm0 56a.685.685 0 00-.671.821.687.687 0 00.932.501.684.684 0 00.222-1.12.685.685 0 00-.483-.202zm0-18.666a.685.685 0 00-.671.821.682.682 0 001.239.247.69.69 0 00-.085-.867.68.68 0 00-.483-.201zm0-28a.685.685 0 00-.484 1.172.68.68 0 001.052-.104.688.688 0 00-.568-1.068zm0 9.333a.685.685 0 00-.671.821.687.687 0 00.932.501.684.684 0 00.422-.635.684.684 0 00-.683-.687zm-8.042-23.333a.68.68 0 00-.631.424.684.684 0 00.148.749.685.685 0 001.114-.749.669.669 0 00-.37-.372.687.687 0 00-.261-.052zm-8.042 32.667a.687.687 0 00-.38.115.691.691 0 00-.103 1.057.68.68 0 001.051-.104.684.684 0 00-.085-.867.664.664 0 00-.483-.201zm0 18.666a.688.688 0 00-.631.424.692.692 0 00.148.749.687.687 0 00.745.149.684.684 0 00.221-1.121.692.692 0 00-.483-.201zm0-28a.68.68 0 00-.631.424.692.692 0 00.148.749.687.687 0 00.745.149.687.687 0 00-.262-1.322zm0 18.667a.68.68 0 00-.631.424.692.692 0 00.148.749.685.685 0 001.115-.749.687.687 0 00-.632-.424zm0-37.334a.696.696 0 00-.38.116.691.691 0 00-.103 1.057.68.68 0 001.051-.104.684.684 0 00-.085-.867.674.674 0 00-.483-.202zm0-9.333a.688.688 0 00-.631.424.692.692 0 00.148.749.687.687 0 00.745.149.684.684 0 00.221-1.121.676.676 0 00-.483-.201zm0 18.667a.68.68 0 00-.631.424.692.692 0 00.148.749.678.678 0 00.745.148.681.681 0 00.306-.253.68.68 0 00.064-.644.698.698 0 00-.37-.372.692.692 0 00-.262-.052zm-8.041-79.334a.685.685 0 00-.671.821.687.687 0 00.932.501.689.689 0 00-.261-1.322zm0 9.334a.684.684 0 00-.484 1.172.68.68 0 001.052-.104.688.688 0 00-.568-1.068zm8.041 144.666a.696.696 0 00-.38.116.691.691 0 00-.103 1.057.687.687 0 00.745.149.684.684 0 00.221-1.12.674.674 0 00-.483-.202zm0-18.666a.68.68 0 00-.631.424.691.691 0 00.148.748.68.68 0 001.051-.104.68.68 0 00.064-.644.687.687 0 00-.632-.424zm0-9.334a.688.688 0 00-.631.424.692.692 0 00.148.749.687.687 0 00.745.149.692.692 0 00.422-.635.683.683 0 00-.201-.485.681.681 0 00-.483-.202zm8.042-23.333a.688.688 0 00-.631.424.684.684 0 00.148.749.687.687 0 00.745.149.686.686 0 00.369-.898.68.68 0 00-.631-.424zm-8.042 42a.688.688 0 00-.631.424.692.692 0 00.148.749.687.687 0 00.745.149.684.684 0 00.221-1.121.676.676 0 00-.483-.201zm8.042-4.666a.685.685 0 00-.67.821.68.68 0 00.537.539.677.677 0 00.701-.292.691.691 0 00-.307-1.016.647.647 0 00-.261-.052zm-8.042-88.667a.68.68 0 00-.631.424.691.691 0 00.148.748.68.68 0 001.051-.104.68.68 0 00.064-.644.687.687 0 00-.632-.424zm8.042 98a.68.68 0 00-.631.424.684.684 0 00.148.749.685.685 0 001.114-.749.669.669 0 00-.37-.372.687.687 0 00-.261-.052zm0-37.334a.685.685 0 00-.67.821.68.68 0 00.537.54.685.685 0 00.394-1.308.665.665 0 00-.261-.053zM145.75 170.98a.68.68 0 00-.631.424.692.692 0 00.148.749.678.678 0 00.745.148.681.681 0 00.306-.253.68.68 0 00.064-.644.698.698 0 00-.37-.372.692.692 0 00-.262-.052zm-8.041 23.333a.69.69 0 00-.484 1.173.687.687 0 00.745.149.684.684 0 00.422-.635.686.686 0 00-.683-.687zm16.083 112a.68.68 0 00-.631.424.684.684 0 00.148.749.687.687 0 00.745.149.693.693 0 00.421-.635.678.678 0 00-.2-.486.683.683 0 00-.483-.201zm-8.042-98a.688.688 0 00-.631.424.692.692 0 00.148.749.687.687 0 00.745.149.684.684 0 00.221-1.121.692.692 0 00-.483-.201zm0 9.333a.688.688 0 00-.631.424.692.692 0 00.148.749.687.687 0 00.745.149.692.692 0 00.422-.635.683.683 0 00-.201-.485.681.681 0 00-.483-.202zm0-27.999a.687.687 0 00-.38.115.691.691 0 00-.103 1.057.68.68 0 001.051-.104.684.684 0 00-.085-.867.664.664 0 00-.483-.201zm0 9.333a.68.68 0 00-.631.424.692.692 0 00.148.749.685.685 0 001.115-.749.687.687 0 00-.632-.424zm0-18.667a.68.68 0 00-.631.424.692.692 0 00.148.749.687.687 0 00.745.149.687.687 0 00-.262-1.322zm8.042 116.667a.68.68 0 00-.631.424.684.684 0 00.148.749.678.678 0 00.745.148.686.686 0 00.221-1.12.683.683 0 00-.483-.201zm32.167 28a.685.685 0 00-.484 1.172.676.676 0 00.745.149.684.684 0 00.422-.634.69.69 0 00-.2-.486.68.68 0 00-.483-.201zm0-9.333a.677.677 0 00-.632.423.692.692 0 00.148.749.68.68 0 001.052-.104.691.691 0 00-.085-.867.68.68 0 00-.483-.201zm-8.042-144.667a.68.68 0 00-.631.424.684.684 0 00.148.749.678.678 0 00.745.148.686.686 0 00.221-1.12.683.683 0 00-.483-.201zm8.042 116.666a.685.685 0 00-.671.821.687.687 0 00.932.501.684.684 0 00.422-.635.688.688 0 00-.683-.687zm0 9.334a.685.685 0 00-.484 1.172.68.68 0 001.052-.104.688.688 0 00-.568-1.068zm-8.042-116.667a.68.68 0 00-.631.424.684.684 0 00.148.749.686.686 0 00.966-.972.683.683 0 00-.483-.201zm8.042 126a.685.685 0 00-.671.821.687.687 0 00.932.501.684.684 0 00.422-.635.684.684 0 00-.683-.687zm-8.042-79.333a.68.68 0 00-.631.424.683.683 0 00.148.748.68.68 0 001.051-.104.688.688 0 00-.568-1.068zm0-37.333a.685.685 0 00-.67.821.68.68 0 00.537.539.677.677 0 00.701-.292.691.691 0 00-.307-1.016.647.647 0 00-.261-.052zm0 46.666a.688.688 0 00-.631.424.684.684 0 00.148.749.687.687 0 00.745.149.686.686 0 00.369-.898.68.68 0 00-.631-.424zm0-18.667a.688.688 0 00-.631.424.684.684 0 00.148.749.683.683 0 001.114-.749.665.665 0 00-.148-.222.668.668 0 00-.222-.149.665.665 0 00-.261-.053zm0-9.333a.688.688 0 00-.631.424.684.684 0 00.148.749.687.687 0 00.745.149.686.686 0 00.369-.898.68.68 0 00-.631-.424zm0-9.333a.68.68 0 00-.631.424.684.684 0 00.148.749.685.685 0 001.114-.749.669.669 0 00-.37-.372.687.687 0 00-.261-.052zm8.042-14a.684.684 0 00-.484 1.172.68.68 0 001.052-.104.688.688 0 00-.568-1.068zm0 18.666a.685.685 0 00-.671.821.687.687 0 00.932.501.684.684 0 00.422-.635.688.688 0 00-.683-.687zm0 18.667a.685.685 0 00-.671.821.687.687 0 00.932.501.684.684 0 00.422-.635.684.684 0 00-.683-.687zm0-9.333a.685.685 0 00-.484 1.172.68.68 0 001.052-.104.688.688 0 00-.568-1.068zm0-18.667a.69.69 0 00-.484 1.173.687.687 0 00.745.149.684.684 0 00.422-.635.686.686 0 00-.683-.687zm-8.042 51.333a.685.685 0 00-.67.821.68.68 0 00.537.54.685.685 0 00.394-1.308.665.665 0 00-.261-.053zm8.042 32.667a.69.69 0 00-.484 1.173.687.687 0 00.745.149.684.684 0 00.422-.635.686.686 0 00-.683-.687zm0-102.667a.685.685 0 00-.671.821.687.687 0 00.932.501.684.684 0 00.222-1.12.685.685 0 00-.483-.202zm0 84a.685.685 0 00-.671.821.687.687 0 00.932.501.684.684 0 00.222-1.12.685.685 0 00-.483-.202zm0-27.999a.677.677 0 00-.632.423.692.692 0 00.148.749.68.68 0 001.052-.104.691.691 0 00-.085-.867.68.68 0 00-.483-.201zm0 37.333a.684.684 0 00-.484 1.172.68.68 0 001.052-.104.688.688 0 00-.568-1.068zm0-18.667a.69.69 0 00-.484 1.173.687.687 0 00.745.149.684.684 0 00.422-.635.684.684 0 00-.683-.687zm0-9.333a.685.685 0 00-.484 1.172.676.676 0 00.745.149.684.684 0 00.422-.634.69.69 0 00-.2-.486.68.68 0 00-.483-.201zm-16.084-65.334a.688.688 0 00-.631.424.692.692 0 00.148.749.687.687 0 00.745.149.692.692 0 00.37-.898.683.683 0 00-.37-.371.674.674 0 00-.262-.053zm0 65.334a.68.68 0 00-.631.424.692.692 0 00.148.749.685.685 0 001.115-.749.687.687 0 00-.632-.424zm0 9.333a.688.688 0 00-.631.424.692.692 0 00.148.749.687.687 0 00.745.149.684.684 0 00.221-1.121.679.679 0 00-.483-.201zm0 9.333a.688.688 0 00-.631.424.692.692 0 00.148.749.687.687 0 00.745.149.692.692 0 00.37-.897.677.677 0 00-.37-.372.674.674 0 00-.262-.053zm0-27.999a.687.687 0 00-.38.115.691.691 0 00-.103 1.057.68.68 0 001.051-.104.684.684 0 00-.085-.867.664.664 0 00-.483-.201zm0-9.334a.68.68 0 00-.631.424.692.692 0 00.148.749.687.687 0 00.745.149.687.687 0 00-.262-1.322zm0 46.667a.68.68 0 00-.631.424.691.691 0 00.148.748.68.68 0 001.051-.104.68.68 0 00.064-.644.687.687 0 00-.632-.424zm0 18.666a.688.688 0 00-.631.425.688.688 0 00.498.936.684.684 0 00.616-1.159.674.674 0 00-.483-.202zm0 28.001a.687.687 0 00-.38.115.691.691 0 00-.103 1.057.68.68 0 001.051-.104.684.684 0 00-.085-.867.664.664 0 00-.483-.201zm8.042-60.667a.68.68 0 00-.631.424.684.684 0 00.148.749.678.678 0 00.745.148.686.686 0 00.221-1.12.683.683 0 00-.483-.201zm-8.042 51.333a.68.68 0 00-.631.424.692.692 0 00.148.749.687.687 0 00.745.149.687.687 0 00-.262-1.322zm0-9.333a.68.68 0 00-.631.424.692.692 0 00.148.749.678.678 0 00.745.148.681.681 0 00.306-.253.68.68 0 00.064-.644.687.687 0 00-.632-.424zm0-84a.68.68 0 00-.631.424.692.692 0 00.148.749.678.678 0 00.745.148.681.681 0 00.306-.253.68.68 0 00.064-.644.687.687 0 00-.632-.424zm0 65.333a.688.688 0 00-.631.424.692.692 0 00.148.749.687.687 0 00.745.149.684.684 0 00.221-1.121.692.692 0 00-.483-.201zm0 46.667a.68.68 0 00-.631.424.692.692 0 00.148.749.685.685 0 001.115-.749.687.687 0 00-.632-.424zm8.042-14a.68.68 0 00-.631.424.683.683 0 00.148.748.68.68 0 001.051-.104.688.688 0 00-.568-1.068zm0-18.667a.688.688 0 00-.631.424.684.684 0 00.148.749.687.687 0 00.745.149.686.686 0 00.369-.898.68.68 0 00-.631-.424zm0 9.333a.688.688 0 00-.631.424.684.684 0 00.148.749.683.683 0 001.114-.748.66.66 0 00-.148-.223.668.668 0 00-.222-.149.665.665 0 00-.261-.053zm0-18.666a.68.68 0 00-.631.424.684.684 0 00.148.749.685.685 0 001.114-.749.669.669 0 00-.37-.372.687.687 0 00-.261-.052zm0-9.333a.685.685 0 00-.67.821.68.68 0 00.537.539.677.677 0 00.701-.292.691.691 0 00-.307-1.016.647.647 0 00-.261-.052zm0-9.334a.68.68 0 00-.631.424.684.684 0 00.148.749.687.687 0 00.745.149.693.693 0 00.421-.635.678.678 0 00-.2-.486.683.683 0 00-.483-.201zm-8.042-70a.688.688 0 00-.631.424.692.692 0 00.148.749.687.687 0 00.745.149.684.684 0 00.221-1.121.692.692 0 00-.483-.201zm8.042 126a.688.688 0 00-.631.424.684.684 0 00.148.749.687.687 0 00.745.149.686.686 0 00.369-.898.68.68 0 00-.631-.424zm-8.042-116.667a.696.696 0 00-.38.116.691.691 0 00-.103 1.057.68.68 0 001.051-.104.684.684 0 00-.085-.867.674.674 0 00-.483-.202zm0-18.666a.68.68 0 00-.631.424.691.691 0 00.148.748.68.68 0 001.051-.104.68.68 0 00.064-.644.687.687 0 00-.632-.424zm8.042 144.666a.685.685 0 00-.67.821.68.68 0 00.537.54.685.685 0 00.394-1.308.665.665 0 00-.261-.053zM161.834 170.98a.685.685 0 00-.484 1.172.68.68 0 001.052-.104.688.688 0 00-.568-1.068zm-48.25 112a.685.685 0 00-.671.821.682.682 0 001.239.247.69.69 0 00-.085-.867.68.68 0 00-.483-.201zm0 46.666a.685.685 0 00-.671.821.687.687 0 00.932.501.684.684 0 00.422-.635.688.688 0 00-.683-.687zm0-9.333a.69.69 0 00-.484 1.173.687.687 0 00.745.149.684.684 0 00.422-.635.686.686 0 00-.683-.687zm-8.042-144.667a.688.688 0 00-.631.424.684.684 0 00.148.749.683.683 0 001.114-.749.665.665 0 00-.148-.222.668.668 0 00-.222-.149.665.665 0 00-.261-.053zm0 9.334a.68.68 0 00-.631.424.683.683 0 00.148.748.68.68 0 001.051-.104.688.688 0 00-.568-1.068zm8.042 126a.684.684 0 00-.484 1.172.68.68 0 001.052-.104.688.688 0 00-.568-1.068zm0-9.334a.685.685 0 00-.671.821.691.691 0 00.537.54.685.685 0 00.617-1.159.685.685 0 00-.483-.202zm-8.042-79.333a.68.68 0 00-.631.424.684.684 0 00.148.749.687.687 0 00.745.149.693.693 0 00.421-.635.678.678 0 00-.2-.486.683.683 0 00-.483-.201zm0-28a.688.688 0 00-.631.424.684.684 0 00.148.749.687.687 0 00.745.149.686.686 0 00.369-.898.68.68 0 00-.631-.424zm0 37.334a.685.685 0 00-.67.821.68.68 0 00.537.539.677.677 0 00.701-.292.691.691 0 00-.307-1.016.647.647 0 00-.261-.052zm0 9.333a.68.68 0 00-.631.424.684.684 0 00.148.749.685.685 0 001.114-.749.669.669 0 00-.37-.372.687.687 0 00-.261-.052zm8.042 51.333a.69.69 0 00-.484 1.173.687.687 0 00.745.149.684.684 0 00.422-.635.684.684 0 00-.683-.687zm-8.042-42a.688.688 0 00-.631.424.684.684 0 00.148.749.687.687 0 00.745.149.686.686 0 00.369-.898.68.68 0 00-.631-.424zm0-46.667a.685.685 0 00-.67.821.68.68 0 00.537.54.685.685 0 00.394-1.308.665.665 0 00-.261-.053zm0 9.334a.68.68 0 00-.631.424.684.684 0 00.148.749.678.678 0 00.745.148.686.686 0 00.221-1.12.683.683 0 00-.483-.201zm8.042-4.667a.69.69 0 00-.484 1.173.687.687 0 00.745.149.684.684 0 00.422-.635.684.684 0 00-.683-.687zm0-9.333a.685.685 0 00-.671.821.682.682 0 001.239.247.69.69 0 00-.085-.867.68.68 0 00-.483-.201zm0 28a.684.684 0 00-.484 1.172.68.68 0 001.052-.104.688.688 0 00-.568-1.068zm0-9.334a.685.685 0 00-.671.821.691.691 0 00.537.54.685.685 0 00.617-1.159.685.685 0 00-.483-.202zm0-37.333a.685.685 0 00-.671.821.687.687 0 00.932.501.684.684 0 00.422-.635.684.684 0 00-.683-.687zm0 9.334a.677.677 0 00-.632.423.692.692 0 00.148.749.68.68 0 001.052-.104.691.691 0 00-.085-.867.68.68 0 00-.483-.201zM97.5 329.646a.688.688 0 00-.133 1.361.684.684 0 00.764-.937.678.678 0 00-.37-.371.672.672 0 00-.261-.053zm16.084-65.333a.685.685 0 00-.671.821.687.687 0 00.932.501.684.684 0 00.422-.635.684.684 0 00-.683-.687zm0-28a.69.69 0 00-.484 1.173.687.687 0 00.745.149.684.684 0 00.422-.635.686.686 0 00-.683-.687zm0 37.334a.684.684 0 00-.484 1.172.68.68 0 001.052-.104.691.691 0 00-.085-.867.68.68 0 00-.483-.201zm0-18.667a.685.685 0 00-.484 1.172.68.68 0 001.052-.104.688.688 0 00-.568-1.068zm0-9.334a.685.685 0 00-.671.821.687.687 0 00.932.501.684.684 0 00.422-.635.688.688 0 00-.683-.687zm-8.042 51.334a.68.68 0 00-.631.424.684.684 0 00.148.749.678.678 0 00.745.148.686.686 0 00.221-1.12.683.683 0 00-.483-.201zM97.5 245.646a.688.688 0 10.262 1.322.683.683 0 00.422-.635.693.693 0 00-.2-.485.672.672 0 00-.484-.202zm0 9.334a.677.677 0 00-.631.424.692.692 0 00.148.749.678.678 0 00.745.148.683.683 0 00.422-.634.69.69 0 00-.684-.687zm0 9.333a.677.677 0 00-.631.424.692.692 0 00.148.749.687.687 0 00.745.149.69.69 0 000-1.27.69.69 0 00-.262-.052zm0 9.334a.684.684 0 00-.67.821.687.687 0 00.932.5.683.683 0 00.422-.635.684.684 0 00-.684-.686zm0-37.334a.685.685 0 00-.67.821.69.69 0 00.537.54.684.684 0 00.764-.937.693.693 0 00-.37-.371.672.672 0 00-.261-.053zm0-9.333a.677.677 0 00-.631.424.691.691 0 00.148.748.68.68 0 001.051-.104.687.687 0 00-.568-1.068zm0 74.666a.684.684 0 00-.67.821.686.686 0 00.537.54.684.684 0 00.817-.674.686.686 0 00-.684-.687zm0-18.666a.677.677 0 00-.631.424.691.691 0 00.498.937.684.684 0 00.764-.937.682.682 0 00-.631-.424zm0 28a.677.677 0 00-.631.424.691.691 0 00.148.748.68.68 0 001.051-.104.687.687 0 00-.568-1.068zm0 9.333a.685.685 0 00-.67.821.69.69 0 00.537.54.684.684 0 00.764-.937.693.693 0 00-.37-.371.672.672 0 00-.261-.053zm0-28a.685.685 0 00-.67.821.69.69 0 00.537.54.684.684 0 00.764-.937.694.694 0 00-.37-.372.69.69 0 00-.261-.052zm0-74.667a.684.684 0 00-.67.821.686.686 0 00.537.54.684.684 0 00.817-.674.688.688 0 00-.684-.687zm0-9.333a.685.685 0 00-.67.821.69.69 0 00.537.54.684.684 0 00.764-.937.694.694 0 00-.37-.372.69.69 0 00-.261-.052zm8.042 107.334a.685.685 0 00-.67.821.68.68 0 00.537.539.677.677 0 00.701-.292.691.691 0 00-.307-1.016.647.647 0 00-.261-.052zm0-28.001a.685.685 0 00-.67.821.68.68 0 00.537.54.685.685 0 00.394-1.308.665.665 0 00-.261-.053zm0-28a.688.688 0 00-.631.425.68.68 0 00-.039.396.68.68 0 00.537.54.681.681 0 00.816-.674.673.673 0 00-.052-.262.66.66 0 00-.148-.223.668.668 0 00-.222-.149.665.665 0 00-.261-.053zm8.042-88.666a.685.685 0 00-.484 1.172.68.68 0 001.052-.104.688.688 0 00-.568-1.068zm-8.042 107.333a.688.688 0 00-.631.424.684.684 0 00.148.749.687.687 0 00.745.149.686.686 0 00.369-.898.68.68 0 00-.631-.424zm0-9.333a.68.68 0 00-.631.424.684.684 0 00.148.748.68.68 0 001.051-.104.688.688 0 00-.568-1.068zm0 37.333a.68.68 0 00-.631.424.684.684 0 00.148.749.687.687 0 00.745.149.693.693 0 00.421-.635.678.678 0 00-.2-.486.683.683 0 00-.483-.201zM97.5 198.98a.677.677 0 00-.631.424.691.691 0 00.498.937.684.684 0 00.764-.937.682.682 0 00-.631-.424zm0-9.333a.684.684 0 00-.67.821.687.687 0 00.932.5.683.683 0 00.422-.635.684.684 0 00-.684-.686zm0-9.334a.677.677 0 00-.631.424.692.692 0 00.148.749.687.687 0 00.745.149.69.69 0 000-1.27.69.69 0 00-.262-.052zm0-9.333a.677.677 0 00-.631.424.692.692 0 00.148.749.678.678 0 00.745.148.683.683 0 00.422-.634.69.69 0 00-.684-.687zm8.042 154a.68.68 0 00-.631.424.684.684 0 00.148.749.685.685 0 001.114-.749.669.669 0 00-.37-.372.687.687 0 00-.261-.052zm16.083-28a.68.68 0 00-.631.424.692.692 0 00.148.749.678.678 0 00.745.148.681.681 0 00.306-.253.68.68 0 00.064-.644.698.698 0 00-.37-.372.692.692 0 00-.262-.052zm8.042-98a.68.68 0 00-.631.424.684.684 0 00.148.749.685.685 0 001.114-.749.669.669 0 00-.37-.372.687.687 0 00-.261-.052zm0-9.333a.685.685 0 00-.67.821.68.68 0 00.537.539.677.677 0 00.701-.292.691.691 0 00-.307-1.016.647.647 0 00-.261-.052zm0 27.999a.688.688 0 00-.631.425.68.68 0 00-.039.396.68.68 0 00.537.54.681.681 0 00.816-.674.673.673 0 00-.052-.262.66.66 0 00-.148-.223.668.668 0 00-.222-.149.665.665 0 00-.261-.053zm0-9.333a.688.688 0 00-.631.424.684.684 0 00.148.749.687.687 0 00.745.149.686.686 0 00.369-.898.68.68 0 00-.631-.424zm0-37.333a.68.68 0 00-.631.424.684.684 0 00.148.749.678.678 0 00.745.148.686.686 0 00.221-1.12.683.683 0 00-.483-.201zm0 9.333a.68.68 0 00-.631.424.684.684 0 00.148.749.687.687 0 00.745.149.693.693 0 00.421-.635.678.678 0 00-.2-.486.683.683 0 00-.483-.201zm0 93.334a.685.685 0 00-.67.821.68.68 0 00.537.539.677.677 0 00.701-.292.691.691 0 00-.307-1.016.647.647 0 00-.261-.052zm0-9.334a.68.68 0 00-.631.424.684.684 0 00.148.749.687.687 0 00.745.149.693.693 0 00.421-.635.678.678 0 00-.2-.486.683.683 0 00-.483-.201zm8.042 60.667a.685.685 0 00-.671.821.682.682 0 001.239.247.69.69 0 00-.085-.867.68.68 0 00-.483-.201zm-8.042-98a.68.68 0 00-.631.424.684.684 0 00.148.748.68.68 0 001.051-.104.688.688 0 00-.568-1.068zm0 28a.68.68 0 00-.631.424.684.684 0 00.148.749.678.678 0 00.745.148.686.686 0 00.221-1.12.683.683 0 00-.483-.201zm0-18.667a.688.688 0 00-.631.424.684.684 0 00.148.749.687.687 0 00.745.149.686.686 0 00.369-.898.68.68 0 00-.631-.424zm8.042 14a.69.69 0 00-.484 1.173.687.687 0 00.745.149.684.684 0 00.422-.635.684.684 0 00-.683-.687zm0-9.333a.685.685 0 00-.671.821.682.682 0 001.239.247.69.69 0 00-.085-.867.68.68 0 00-.483-.201zm-8.042 42a.68.68 0 00-.631.424.684.684 0 00.148.749.685.685 0 001.114-.749.669.669 0 00-.37-.372.687.687 0 00-.261-.052zm8.042-51.333a.677.677 0 00-.632.423.692.692 0 00.148.749.68.68 0 001.052-.104.691.691 0 00-.085-.867.68.68 0 00-.483-.201zm0 84a.684.684 0 00-.484 1.172.68.68 0 001.052-.104.691.691 0 00-.085-.867.68.68 0 00-.483-.201zm0-56.001a.685.685 0 00-.671.821.687.687 0 00.932.501.684.684 0 00.222-1.12.685.685 0 00-.483-.202zm0-46.666a.685.685 0 00-.484 1.172.68.68 0 001.052-.104.688.688 0 00-.568-1.068zm0 9.333a.685.685 0 00-.671.821.687.687 0 00.932.501.684.684 0 00.422-.635.684.684 0 00-.683-.687zm0 74.667a.685.685 0 00-.484 1.172.68.68 0 001.052-.104.688.688 0 00-.568-1.068zm0 9.333a.685.685 0 00-.671.821.687.687 0 00.932.501.684.684 0 00.422-.635.684.684 0 00-.683-.687zm0-28a.69.69 0 00-.484 1.173.687.687 0 00.745.149.684.684 0 00.422-.635.686.686 0 00-.683-.687zm0 9.333a.685.685 0 00-.671.821.687.687 0 00.932.501.684.684 0 00.422-.635.688.688 0 00-.683-.687zm0-18.666a.684.684 0 00-.484 1.172.68.68 0 001.052-.104.688.688 0 00-.568-1.068zm-8.042-23.334a.685.685 0 00-.67.821.68.68 0 00.537.54.685.685 0 00.394-1.308.665.665 0 00-.261-.053zm-8.042-13.999a.687.687 0 00-.38.115.691.691 0 00-.103 1.057.68.68 0 001.051-.104.684.684 0 00-.085-.867.664.664 0 00-.483-.201zm0 55.999a.696.696 0 00-.38.116.691.691 0 00-.103 1.057.687.687 0 00.745.149.684.684 0 00.221-1.12.674.674 0 00-.483-.202zm0 18.667a.68.68 0 00-.631.424.692.692 0 00.148.749.687.687 0 00.745.149.687.687 0 00-.262-1.322zm16.084-102.667a.685.685 0 00-.671.821.687.687 0 00.932.501.684.684 0 00.422-.635.688.688 0 00-.683-.687zm-16.084 112.001a.687.687 0 00-.38.115.691.691 0 00-.103 1.057.68.68 0 001.051-.104.684.684 0 00-.085-.867.664.664 0 00-.483-.201zm0-93.334a.68.68 0 00-.631.424.692.692 0 00.148.749.687.687 0 00.745.149.687.687 0 00-.262-1.322zm0-9.333a.68.68 0 00-.631.424.692.692 0 00.148.749.678.678 0 00.745.148.681.681 0 00.306-.253.68.68 0 00.064-.644.698.698 0 00-.37-.372.692.692 0 00-.262-.052zm0 56a.68.68 0 00-.631.424.691.691 0 00.148.748.68.68 0 001.051-.104.68.68 0 00.064-.644.687.687 0 00-.632-.424zm0-9.334a.688.688 0 00-.631.424.692.692 0 00.148.749.687.687 0 00.745.149.692.692 0 00.422-.635.685.685 0 00-.684-.687zm0-18.666a.68.68 0 00-.631.424.692.692 0 00.148.749.685.685 0 001.115-.749.687.687 0 00-.632-.424zm0 9.333a.688.688 0 00-.631.424.692.692 0 00.148.749.687.687 0 00.745.149.684.684 0 00.221-1.121.692.692 0 00-.483-.201zm8.042 42a.688.688 0 00-.631.424.684.684 0 00.148.749.687.687 0 00.745.149.686.686 0 00.369-.898.68.68 0 00-.631-.424zm-8.042-98a.688.688 0 00-.631.424.692.692 0 00.148.749.687.687 0 00.745.149.684.684 0 00.221-1.121.676.676 0 00-.483-.201zm8.042 126a.688.688 0 00-.631.424.684.684 0 00.148.749.687.687 0 00.745.149.686.686 0 00.369-.898.68.68 0 00-.631-.424zm-8.042 4.667a.68.68 0 00-.631.424.692.692 0 00.148.749.685.685 0 001.115-.749.687.687 0 00-.632-.424zm8.042 4.666a.685.685 0 00-.67.821.68.68 0 00.537.54.685.685 0 00.394-1.308.665.665 0 00-.261-.053zm0-28a.688.688 0 00-.631.425.68.68 0 00-.039.396.68.68 0 00.537.54.681.681 0 00.816-.674.673.673 0 00-.052-.262.66.66 0 00-.148-.223.668.668 0 00-.222-.149.665.665 0 00-.261-.053zm0 9.334a.68.68 0 00-.631.424.684.684 0 00.148.748.68.68 0 001.051-.104.688.688 0 00-.568-1.068zm-8.042-135.334a.688.688 0 00-.631.424.692.692 0 00.148.749.687.687 0 00.745.149.692.692 0 00.422-.635.683.683 0 00-.201-.485.681.681 0 00-.483-.202zm0 28a.696.696 0 00-.38.116.691.691 0 00-.103 1.057.68.68 0 001.051-.104.684.684 0 00-.085-.867.674.674 0 00-.483-.202zm0 74.667a.688.688 0 00-.631.424.692.692 0 00.148.749.687.687 0 00.745.149.684.684 0 00.221-1.121.676.676 0 00-.483-.201zm0-93.333a.68.68 0 00-.631.424.691.691 0 00.148.748.68.68 0 001.051-.104.68.68 0 00.064-.644.687.687 0 00-.632-.424z" fill="#63D0FF"/></svg>
\ No newline at end of file
diff --git a/v1.9.4/website/public/img/docs/atlas-workflow.png b/v1.9.4/website/public/img/docs/atlas-workflow.png
new file mode 100644
index 0000000..aead95f
--- /dev/null
+++ b/v1.9.4/website/public/img/docs/atlas-workflow.png
Binary files differ
diff --git a/v1.9.4/website/public/img/docs/packer-ecosystem-diagram.png b/v1.9.4/website/public/img/docs/packer-ecosystem-diagram.png
new file mode 100644
index 0000000..33f20b9
--- /dev/null
+++ b/v1.9.4/website/public/img/docs/packer-ecosystem-diagram.png
Binary files differ
diff --git a/v1.9.4/website/public/img/docs/packer-integration-steps-diagram.png b/v1.9.4/website/public/img/docs/packer-integration-steps-diagram.png
new file mode 100644
index 0000000..f7e5169
--- /dev/null
+++ b/v1.9.4/website/public/img/docs/packer-integration-steps-diagram.png
Binary files differ
diff --git a/v1.9.4/website/public/img/favicons/android-chrome-192x192.png b/v1.9.4/website/public/img/favicons/android-chrome-192x192.png
new file mode 100644
index 0000000..fde7568
--- /dev/null
+++ b/v1.9.4/website/public/img/favicons/android-chrome-192x192.png
Binary files differ
diff --git a/v1.9.4/website/public/img/favicons/android-chrome-512x512.png b/v1.9.4/website/public/img/favicons/android-chrome-512x512.png
new file mode 100644
index 0000000..e1394bc
--- /dev/null
+++ b/v1.9.4/website/public/img/favicons/android-chrome-512x512.png
Binary files differ
diff --git a/v1.9.4/website/public/img/favicons/apple-touch-icon.png b/v1.9.4/website/public/img/favicons/apple-touch-icon.png
new file mode 100644
index 0000000..979793c
--- /dev/null
+++ b/v1.9.4/website/public/img/favicons/apple-touch-icon.png
Binary files differ
diff --git a/v1.9.4/website/public/img/favicons/favicon-16x16.png b/v1.9.4/website/public/img/favicons/favicon-16x16.png
new file mode 100644
index 0000000..8f55c98
--- /dev/null
+++ b/v1.9.4/website/public/img/favicons/favicon-16x16.png
Binary files differ
diff --git a/v1.9.4/website/public/img/favicons/favicon-32x32.png b/v1.9.4/website/public/img/favicons/favicon-32x32.png
new file mode 100644
index 0000000..a7d8f66
--- /dev/null
+++ b/v1.9.4/website/public/img/favicons/favicon-32x32.png
Binary files differ
diff --git a/v1.9.4/website/public/img/favicons/mstile-150x150.png b/v1.9.4/website/public/img/favicons/mstile-150x150.png
new file mode 100644
index 0000000..f74d169
--- /dev/null
+++ b/v1.9.4/website/public/img/favicons/mstile-150x150.png
Binary files differ
diff --git a/v1.9.4/website/public/img/favicons/safari-pinned-tab.svg b/v1.9.4/website/public/img/favicons/safari-pinned-tab.svg
new file mode 100644
index 0000000..5b8bf90
--- /dev/null
+++ b/v1.9.4/website/public/img/favicons/safari-pinned-tab.svg
@@ -0,0 +1,20 @@
+<?xml version="1.0" standalone="no"?>
+<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 20010904//EN"
+ "http://www.w3.org/TR/2001/REC-SVG-20010904/DTD/svg10.dtd">
+<svg version="1.0" xmlns="http://www.w3.org/2000/svg"
+ width="16.000000pt" height="16.000000pt" viewBox="0 0 16.000000 16.000000"
+ preserveAspectRatio="xMidYMid meet">
+<metadata>
+Created by potrace 1.11, written by Peter Selinger 2001-2013
+</metadata>
+<g transform="translate(0.000000,16.000000) scale(0.001739,-0.001739)"
+fill="#000000" stroke="none">
+<path d="M3022 8509 l3 -633 1087 -621 1087 -620 3 -1910 3 -1910 560 -318
+c589 -334 690 -383 860 -418 171 -35 346 -17 468 48 79 43 168 138 211 224 77
+157 71 19 71 1769 0 1767 7 1612 -81 1876 -166 503 -568 1014 -1014 1291 -78
+49 -3224 1841 -3245 1849 -13 6 -15 -70 -13 -627z"/>
+<path d="M1812 4929 l3 -3112 1460 -834 c803 -459 1466 -837 1473 -840 9 -4
+12 621 12 3105 l0 3111 -1471 840 c-809 463 -1473 841 -1475 841 -2 0 -3
+-1400 -2 -3111z"/>
+</g>
+</svg>
diff --git a/v1.9.4/website/public/img/guides/teamcity_build_configuration.png b/v1.9.4/website/public/img/guides/teamcity_build_configuration.png
new file mode 100644
index 0000000..bcdcbb5
--- /dev/null
+++ b/v1.9.4/website/public/img/guides/teamcity_build_configuration.png
Binary files differ
diff --git a/v1.9.4/website/public/img/guides/teamcity_build_log.png b/v1.9.4/website/public/img/guides/teamcity_build_log.png
new file mode 100644
index 0000000..13d23e1
--- /dev/null
+++ b/v1.9.4/website/public/img/guides/teamcity_build_log.png
Binary files differ
diff --git a/v1.9.4/website/public/img/guides/teamcity_build_log_complete.png b/v1.9.4/website/public/img/guides/teamcity_build_log_complete.png
new file mode 100644
index 0000000..a05b2a6
--- /dev/null
+++ b/v1.9.4/website/public/img/guides/teamcity_build_log_complete.png
Binary files differ
diff --git a/v1.9.4/website/public/img/guides/teamcity_create_project_from_url-1.png b/v1.9.4/website/public/img/guides/teamcity_create_project_from_url-1.png
new file mode 100644
index 0000000..dc1ab30
--- /dev/null
+++ b/v1.9.4/website/public/img/guides/teamcity_create_project_from_url-1.png
Binary files differ
diff --git a/v1.9.4/website/public/img/guides/teamcity_create_project_from_url-2.png b/v1.9.4/website/public/img/guides/teamcity_create_project_from_url-2.png
new file mode 100644
index 0000000..5b98b16
--- /dev/null
+++ b/v1.9.4/website/public/img/guides/teamcity_create_project_from_url-2.png
Binary files differ
diff --git a/v1.9.4/website/public/img/hcp-callout.svg b/v1.9.4/website/public/img/hcp-callout.svg
new file mode 100644
index 0000000..c4b862b
--- /dev/null
+++ b/v1.9.4/website/public/img/hcp-callout.svg
@@ -0,0 +1,138 @@
+<svg width="646" height="441" viewBox="0 0 646 441" fill="none" xmlns="http://www.w3.org/2000/svg">
+<g clip-path="url(#clip0)">
+<path d="M795 101.5H10C5.85786 101.5 2.5 104.858 2.5 109V568C2.5 572.142 5.85786 575.5 10 575.5H795C799.142 575.5 802.5 572.142 802.5 568V109C802.5 104.858 799.142 101.5 795 101.5Z" fill="url(#paint0_linear)" stroke="#F2F2F3"/>
+<path d="M93.5545 146.182V159H96.2371V154.958H98.7686C101.469 154.958 103.343 153.2 103.343 150.588C103.343 147.941 101.54 146.182 98.9019 146.182H93.5545ZM96.2371 148.314H98.1913C99.7369 148.314 100.616 149.105 100.616 150.597C100.616 152.054 99.7191 152.853 98.1824 152.853H96.2371V148.314ZM107.791 159.151C109.062 159.151 110.128 158.609 110.634 157.703H110.794V159H113.299V152.32C113.299 150.233 111.833 149.007 109.239 149.007C106.779 149.007 105.118 150.135 104.949 151.929H107.329C107.543 151.316 108.164 150.988 109.097 150.988C110.163 150.988 110.749 151.476 110.749 152.32V153.129L108.378 153.271C105.944 153.413 104.585 154.443 104.585 156.211C104.585 157.996 105.908 159.151 107.791 159.151ZM108.644 157.259C107.747 157.259 107.116 156.806 107.116 156.051C107.116 155.331 107.658 154.914 108.768 154.843L110.749 154.71V155.438C110.749 156.468 109.843 157.259 108.644 157.259ZM124.418 152.631C124.205 150.446 122.65 149.007 120.056 149.007C116.992 149.007 115.269 150.863 115.269 154.088C115.269 157.348 117.001 159.204 120.056 159.204C122.606 159.204 124.205 157.801 124.418 155.651H122.002C121.806 156.628 121.113 157.152 120.056 157.152C118.671 157.152 117.88 156.06 117.88 154.088C117.88 152.143 118.662 151.068 120.056 151.068C121.158 151.068 121.824 151.69 122.002 152.631H124.418ZM129.186 153.084H129.026V145.48H126.441V159H129.026V155.713L129.736 154.976L132.597 159H135.661L131.673 153.413L135.404 149.22H132.463L129.186 153.084ZM142.952 156.237C142.676 156.904 141.975 157.277 140.953 157.277C139.603 157.277 138.75 156.344 138.715 154.852V154.719H145.439V153.946C145.439 150.855 143.733 149.007 140.847 149.007C137.933 149.007 136.139 150.979 136.139 154.159C136.139 157.321 137.897 159.204 140.882 159.204C143.28 159.204 144.977 158.058 145.359 156.237H142.952ZM140.855 150.934C142.063 150.934 142.845 151.769 142.898 153.111H138.724C138.812 151.796 139.656 150.934 140.855 150.934ZM147.471 159H150.056V153.528C150.056 152.151 151.024 151.308 152.436 151.308C152.854 151.308 153.458 151.379 153.662 151.45V149.176C153.44 149.105 153.005 149.06 152.65 149.06C151.406 149.06 150.393 149.797 150.136 150.775H149.976V149.22H147.471V159ZM168.394 159H171.299L166.849 146.182H163.695L159.245 159H161.937L162.923 155.891H167.426L168.394 159ZM165.108 148.785H165.268L166.858 153.884H163.5L165.108 148.785ZM173.136 159H175.72V153.528C175.72 152.151 176.689 151.308 178.101 151.308C178.519 151.308 179.123 151.379 179.327 151.45V149.176C179.105 149.105 178.67 149.06 178.314 149.06C177.071 149.06 176.058 149.797 175.8 150.775H175.641V149.22H173.136V159ZM182.114 146.884V149.309H180.586V151.272H182.114V156.362C182.114 158.263 183.056 159.036 185.436 159.036C185.934 159.036 186.413 158.982 186.733 158.92V157.01C186.484 157.037 186.307 157.055 185.969 157.055C185.09 157.055 184.699 156.646 184.699 155.767V151.272H186.733V149.309H184.699V146.884H182.114ZM190.115 147.719C190.915 147.719 191.572 147.079 191.572 146.28C191.572 145.472 190.915 144.832 190.115 144.832C189.316 144.832 188.649 145.472 188.649 146.28C188.649 147.079 189.316 147.719 190.115 147.719ZM188.818 159H191.403V149.22H188.818V159ZM194.688 159H197.272V151.272H199.298V149.309H197.219V148.483C197.219 147.63 197.592 147.213 198.605 147.213C198.942 147.213 199.209 147.239 199.378 147.266V145.48C199.005 145.427 198.569 145.383 198.045 145.383C195.682 145.383 194.688 146.36 194.688 148.305V149.309H193.106V151.272H194.688V159ZM203.63 159.151C204.901 159.151 205.967 158.609 206.473 157.703H206.633V159H209.138V152.32C209.138 150.233 207.672 149.007 205.078 149.007C202.618 149.007 200.957 150.135 200.788 151.929H203.169C203.382 151.316 204.003 150.988 204.936 150.988C206.002 150.988 206.588 151.476 206.588 152.32V153.129L204.217 153.271C201.783 153.413 200.424 154.443 200.424 156.211C200.424 157.996 201.747 159.151 203.63 159.151ZM204.483 157.259C203.586 157.259 202.955 156.806 202.955 156.051C202.955 155.331 203.497 154.914 204.608 154.843L206.588 154.71V155.438C206.588 156.468 205.682 157.259 204.483 157.259ZM220.257 152.631C220.044 150.446 218.489 149.007 215.895 149.007C212.831 149.007 211.108 150.863 211.108 154.088C211.108 157.348 212.84 159.204 215.895 159.204C218.445 159.204 220.044 157.801 220.257 155.651H217.841C217.645 156.628 216.952 157.152 215.895 157.152C214.51 157.152 213.719 156.06 213.719 154.088C213.719 152.143 214.501 151.068 215.895 151.068C216.997 151.068 217.663 151.69 217.841 152.631H220.257ZM223.017 146.884V149.309H221.489V151.272H223.017V156.362C223.017 158.263 223.959 159.036 226.339 159.036C226.837 159.036 227.316 158.982 227.636 158.92V157.01C227.387 157.037 227.21 157.055 226.872 157.055C225.993 157.055 225.602 156.646 225.602 155.767V151.272H227.636V149.309H225.602V146.884H223.017ZM237.243 154.31H239.437L241.827 159H244.864L242.164 153.91C243.639 153.333 244.491 151.912 244.491 150.268C244.491 147.737 242.759 146.182 239.943 146.182H234.56V159H237.243V154.31ZM237.243 148.279H239.57C240.903 148.279 241.738 149.06 241.738 150.304C241.738 151.574 240.947 152.311 239.597 152.311H237.243V148.279ZM252.857 156.237C252.581 156.904 251.88 157.277 250.858 157.277C249.508 157.277 248.655 156.344 248.62 154.852V154.719H255.344V153.946C255.344 150.855 253.638 149.007 250.752 149.007C247.838 149.007 246.044 150.979 246.044 154.159C246.044 157.321 247.802 159.204 250.787 159.204C253.185 159.204 254.882 158.058 255.264 156.237H252.857ZM250.76 150.934C251.968 150.934 252.75 151.769 252.803 153.111H248.629C248.717 151.796 249.561 150.934 250.76 150.934ZM261.693 162.704C264.651 162.704 266.525 161.265 266.525 158.982V149.22H264.02V150.783H263.86C263.336 149.718 262.208 149.06 260.885 149.06C258.397 149.06 256.87 150.997 256.87 154.026C256.87 156.957 258.389 158.858 260.831 158.858C262.208 158.858 263.239 158.298 263.78 157.268H263.94V159.089C263.94 160.217 263.132 160.874 261.746 160.874C260.627 160.874 259.899 160.483 259.765 159.862H257.207C257.367 161.576 259.09 162.704 261.693 162.704ZM261.728 156.877C260.325 156.877 259.526 155.776 259.526 154.017C259.526 152.258 260.334 151.157 261.728 151.157C263.123 151.157 263.967 152.258 263.967 154.017C263.967 155.776 263.132 156.877 261.728 156.877ZM270.343 147.719C271.142 147.719 271.799 147.079 271.799 146.28C271.799 145.472 271.142 144.832 270.343 144.832C269.543 144.832 268.877 145.472 268.877 146.28C268.877 147.079 269.543 147.719 270.343 147.719ZM269.046 159H271.631V149.22H269.046V159ZM273.938 152.071C273.938 153.573 274.862 154.47 276.763 154.887L278.539 155.287C279.401 155.482 279.774 155.784 279.774 156.282C279.774 156.93 279.081 157.374 278.077 157.374C277.047 157.374 276.416 156.975 276.221 156.3H273.698C273.876 158.147 275.439 159.204 278.024 159.204C280.591 159.204 282.341 157.943 282.341 156.007C282.341 154.55 281.488 153.75 279.587 153.333L277.749 152.933C276.843 152.729 276.425 152.418 276.425 151.92C276.425 151.281 277.109 150.846 278.033 150.846C278.992 150.846 279.587 151.245 279.721 151.894H282.11C281.968 150.046 280.502 149.007 278.015 149.007C275.572 149.007 273.938 150.242 273.938 152.071ZM285.057 146.884V149.309H283.529V151.272H285.057V156.362C285.057 158.263 285.999 159.036 288.379 159.036C288.877 159.036 289.356 158.982 289.676 158.92V157.01C289.427 157.037 289.25 157.055 288.912 157.055C288.033 157.055 287.642 156.646 287.642 155.767V151.272H289.676V149.309H287.642V146.884H285.057ZM291.744 159H294.328V153.528C294.328 152.151 295.297 151.308 296.709 151.308C297.127 151.308 297.731 151.379 297.935 151.45V149.176C297.713 149.105 297.278 149.06 296.922 149.06C295.679 149.06 294.666 149.797 294.408 150.775H294.249V149.22H291.744V159ZM300.935 162.553C303.378 162.553 304.577 161.683 305.412 159.187L308.787 149.22H306.052L303.991 156.682H303.831L301.77 149.22H298.919L302.356 159.053L302.268 159.426C302.054 160.217 301.504 160.537 300.535 160.537C300.429 160.537 300.038 160.528 299.949 160.51V162.526C300.056 162.544 300.837 162.553 300.935 162.553Z" fill="#1D1E1F"/>
+<path d="M92.8545 120.954V128H94.3291V125.778H95.7207C97.2051 125.778 98.2354 124.812 98.2354 123.376C98.2354 121.921 97.2441 120.954 95.7939 120.954H92.8545ZM94.3291 122.126H95.4033C96.2529 122.126 96.7363 122.561 96.7363 123.381C96.7363 124.182 96.2432 124.621 95.3984 124.621H94.3291V122.126ZM100.68 128.083C101.379 128.083 101.965 127.785 102.243 127.287H102.331V128H103.708V124.328C103.708 123.181 102.902 122.507 101.476 122.507C100.124 122.507 99.2107 123.127 99.118 124.113H100.427C100.544 123.776 100.886 123.596 101.398 123.596C101.984 123.596 102.306 123.864 102.306 124.328V124.772L101.003 124.851C99.6648 124.929 98.9178 125.495 98.9178 126.467C98.9178 127.448 99.6453 128.083 100.68 128.083ZM101.149 127.043C100.656 127.043 100.309 126.794 100.309 126.379C100.309 125.983 100.607 125.754 101.218 125.715L102.306 125.642V126.042C102.306 126.608 101.808 127.043 101.149 127.043ZM109.82 124.499C109.703 123.298 108.848 122.507 107.422 122.507C105.738 122.507 104.791 123.527 104.791 125.3C104.791 127.092 105.743 128.112 107.422 128.112C108.824 128.112 109.703 127.341 109.82 126.159H108.492C108.384 126.696 108.004 126.984 107.422 126.984C106.661 126.984 106.226 126.384 106.226 125.3C106.226 124.23 106.656 123.64 107.422 123.64C108.028 123.64 108.394 123.981 108.492 124.499H109.82ZM112.441 124.748H112.353V120.568H110.932V128H112.353V126.193L112.744 125.788L114.316 128H116L113.808 124.929L115.859 122.624H114.243L112.441 124.748ZM120.008 126.481C119.857 126.848 119.471 127.053 118.909 127.053C118.167 127.053 117.698 126.54 117.679 125.72V125.646H121.375V125.222C121.375 123.522 120.438 122.507 118.851 122.507C117.249 122.507 116.263 123.591 116.263 125.339C116.263 127.077 117.23 128.112 118.87 128.112C120.189 128.112 121.121 127.482 121.331 126.481H120.008ZM118.856 123.566C119.52 123.566 119.949 124.025 119.979 124.763H117.684C117.733 124.04 118.196 123.566 118.856 123.566ZM122.492 128H123.913V124.992C123.913 124.235 124.445 123.771 125.222 123.771C125.451 123.771 125.783 123.811 125.896 123.85V122.6C125.773 122.561 125.534 122.536 125.339 122.536C124.655 122.536 124.099 122.941 123.957 123.479H123.869V122.624H122.492V128Z" fill="#BFBFC0"/>
+<path d="M95.7949 210V201.545H94.0254V210H95.7949ZM97.6158 210H99.3209V206.109C99.3209 205.371 99.7955 204.832 100.463 204.832C101.131 204.832 101.53 205.23 101.53 205.922V210H103.17V206.033C103.17 205.336 103.616 204.832 104.307 204.832C105.028 204.832 105.385 205.219 105.385 205.998V210H107.09V205.57C107.09 204.24 106.288 203.408 104.999 203.408C104.096 203.408 103.352 203.883 103.053 204.598H102.948C102.69 203.859 102.069 203.408 101.161 203.408C100.311 203.408 99.6373 203.859 99.3736 204.598H99.2681V203.549H97.6158V210ZM110.458 210.1C111.296 210.1 111.999 209.742 112.333 209.145H112.439V210H114.091V205.594C114.091 204.217 113.124 203.408 111.413 203.408C109.79 203.408 108.694 204.152 108.583 205.336H110.153C110.294 204.932 110.704 204.715 111.319 204.715C112.023 204.715 112.409 205.037 112.409 205.594V206.127L110.845 206.221C109.239 206.314 108.343 206.994 108.343 208.16C108.343 209.338 109.216 210.1 110.458 210.1ZM111.021 208.852C110.429 208.852 110.013 208.553 110.013 208.055C110.013 207.58 110.37 207.305 111.103 207.258L112.409 207.17V207.65C112.409 208.33 111.812 208.852 111.021 208.852ZM118.554 212.443C120.506 212.443 121.742 211.494 121.742 209.988V203.549H120.09V204.58H119.984C119.638 203.877 118.894 203.443 118.021 203.443C116.381 203.443 115.373 204.721 115.373 206.719C115.373 208.652 116.375 209.906 117.986 209.906C118.894 209.906 119.574 209.537 119.931 208.857H120.037V210.059C120.037 210.803 119.504 211.236 118.59 211.236C117.851 211.236 117.371 210.979 117.283 210.568H115.595C115.701 211.699 116.838 212.443 118.554 212.443ZM118.578 208.6C117.652 208.6 117.125 207.873 117.125 206.713C117.125 205.553 117.658 204.826 118.578 204.826C119.498 204.826 120.054 205.553 120.054 206.713C120.054 207.873 119.504 208.6 118.578 208.6ZM127.571 208.178C127.389 208.617 126.926 208.863 126.252 208.863C125.362 208.863 124.799 208.248 124.776 207.264V207.176H129.211V206.666C129.211 204.627 128.086 203.408 126.182 203.408C124.26 203.408 123.076 204.709 123.076 206.807C123.076 208.893 124.237 210.135 126.205 210.135C127.787 210.135 128.906 209.379 129.158 208.178H127.571ZM126.188 204.68C126.985 204.68 127.5 205.23 127.535 206.115H124.781C124.84 205.248 125.397 204.68 126.188 204.68ZM130.405 205.43C130.405 206.42 131.014 207.012 132.268 207.287L133.44 207.551C134.009 207.68 134.255 207.879 134.255 208.207C134.255 208.635 133.798 208.928 133.136 208.928C132.456 208.928 132.04 208.664 131.911 208.219H130.247C130.364 209.438 131.395 210.135 133.1 210.135C134.794 210.135 135.948 209.303 135.948 208.025C135.948 207.064 135.386 206.537 134.132 206.262L132.919 205.998C132.321 205.863 132.046 205.658 132.046 205.33C132.046 204.908 132.497 204.621 133.106 204.621C133.739 204.621 134.132 204.885 134.22 205.312H135.796C135.702 204.094 134.735 203.408 133.095 203.408C131.483 203.408 130.405 204.223 130.405 205.43Z" fill="#1D1E1F"/>
+<path opacity="0.3" d="M771 233H94C92.8954 233 92 233.895 92 235V261C92 262.105 92.8954 263 94 263H771C772.105 263 773 262.105 773 261V235C773 233.895 772.105 233 771 233Z" fill="#F2F2F3"/>
+<path d="M101.777 252V244.954H100.898V252H101.777ZM103.524 244.954V252H105.941C108.036 252 109.266 250.696 109.266 248.475C109.266 246.258 108.031 244.954 105.941 244.954H103.524ZM104.403 245.745H105.883C107.445 245.745 108.368 246.761 108.368 248.484C108.368 250.203 107.455 251.209 105.883 251.209H104.403V245.745Z" fill="#1D1E1F"/>
+<path d="M258.176 251.209H254.777V244.954H253.898V252H258.176V251.209ZM260.889 252.093C261.593 252.093 262.169 251.785 262.511 251.224H262.589V252H263.389V248.396C263.389 247.303 262.672 246.644 261.387 246.644C260.264 246.644 259.434 247.2 259.322 248.045H260.172C260.289 247.63 260.728 247.391 261.358 247.391C262.144 247.391 262.55 247.747 262.55 248.396V248.875L261.031 248.968C259.805 249.041 259.112 249.583 259.112 250.525C259.112 251.487 259.869 252.093 260.889 252.093ZM261.046 251.355C260.435 251.355 259.981 251.043 259.981 250.506C259.981 249.979 260.333 249.7 261.134 249.646L262.55 249.554V250.037C262.55 250.789 261.91 251.355 261.046 251.355ZM265.244 245.374V246.736H264.394V247.439H265.244V250.633C265.244 251.639 265.678 252.039 266.762 252.039C266.928 252.039 267.089 252.02 267.255 251.99V251.282C267.099 251.297 267.016 251.302 266.865 251.302C266.318 251.302 266.084 251.038 266.084 250.418V247.439H267.255V246.736H266.084V245.374H265.244ZM271.883 250.638C271.663 251.102 271.204 251.351 270.526 251.351C269.632 251.351 269.051 250.691 269.007 249.651V249.612H272.791V249.29C272.791 247.654 271.927 246.644 270.506 246.644C269.061 246.644 268.133 247.718 268.133 249.373C268.133 251.038 269.046 252.093 270.506 252.093C271.659 252.093 272.479 251.536 272.723 250.638H271.883ZM270.496 247.386C271.331 247.386 271.888 248.001 271.908 248.934H269.007C269.071 248.001 269.657 247.386 270.496 247.386ZM273.938 248.177C273.938 248.938 274.387 249.363 275.373 249.603L276.277 249.822C276.838 249.959 277.112 250.203 277.112 250.564C277.112 251.048 276.604 251.385 275.896 251.385C275.222 251.385 274.802 251.102 274.66 250.657H273.796C273.889 251.531 274.695 252.093 275.866 252.093C277.063 252.093 277.976 251.443 277.976 250.501C277.976 249.744 277.497 249.314 276.506 249.075L275.696 248.88C275.075 248.729 274.782 248.504 274.782 248.143C274.782 247.674 275.271 247.356 275.896 247.356C276.53 247.356 276.941 247.635 277.053 248.055H277.883C277.771 247.19 277.004 246.644 275.901 246.644C274.782 246.644 273.938 247.303 273.938 248.177ZM279.547 245.374V246.736H278.697V247.439H279.547V250.633C279.547 251.639 279.981 252.039 281.065 252.039C281.231 252.039 281.393 252.02 281.559 251.99V251.282C281.402 251.297 281.319 251.302 281.168 251.302C280.621 251.302 280.387 251.038 280.387 250.418V247.439H281.559V246.736H280.387V245.374H279.547ZM288.563 252L291.161 244.954H290.238L288.168 250.862H288.089L286.019 244.954H285.096L287.694 252H288.563ZM295.237 250.638C295.017 251.102 294.558 251.351 293.879 251.351C292.986 251.351 292.405 250.691 292.361 249.651V249.612H296.145V249.29C296.145 247.654 295.281 246.644 293.86 246.644C292.414 246.644 291.487 247.718 291.487 249.373C291.487 251.038 292.4 252.093 293.86 252.093C295.012 252.093 295.832 251.536 296.077 250.638H295.237ZM293.85 247.386C294.685 247.386 295.242 248.001 295.261 248.934H292.361C292.424 248.001 293.01 247.386 293.85 247.386ZM297.413 252H298.253V248.738C298.253 247.996 298.834 247.459 299.635 247.459C299.801 247.459 300.104 247.488 300.172 247.508V246.668C300.065 246.653 299.889 246.644 299.752 246.644C299.054 246.644 298.448 247.005 298.292 247.518H298.214V246.736H297.413V252ZM300.952 248.177C300.952 248.938 301.401 249.363 302.388 249.603L303.291 249.822C303.853 249.959 304.126 250.203 304.126 250.564C304.126 251.048 303.618 251.385 302.91 251.385C302.236 251.385 301.816 251.102 301.675 250.657H300.811C300.903 251.531 301.709 252.093 302.881 252.093C304.077 252.093 304.99 251.443 304.99 250.501C304.99 249.744 304.512 249.314 303.521 249.075L302.71 248.88C302.09 248.729 301.797 248.504 301.797 248.143C301.797 247.674 302.285 247.356 302.91 247.356C303.545 247.356 303.955 247.635 304.067 248.055H304.897C304.785 247.19 304.019 246.644 302.915 246.644C301.797 246.644 300.952 247.303 300.952 248.177ZM306.698 245.721C307.02 245.721 307.284 245.457 307.284 245.135C307.284 244.812 307.02 244.549 306.698 244.549C306.376 244.549 306.112 244.812 306.112 245.135C306.112 245.457 306.376 245.721 306.698 245.721ZM306.278 252H307.118V246.736H306.278V252ZM310.833 252.093C312.332 252.093 313.259 251.058 313.259 249.368C313.259 247.674 312.332 246.644 310.833 246.644C309.334 246.644 308.406 247.674 308.406 249.368C308.406 251.058 309.334 252.093 310.833 252.093ZM310.833 251.336C309.837 251.336 309.275 250.613 309.275 249.368C309.275 248.118 309.837 247.4 310.833 247.4C311.829 247.4 312.39 248.118 312.39 249.368C312.39 250.613 311.829 251.336 310.833 251.336ZM314.528 252H315.368V248.885C315.368 247.962 315.91 247.4 316.749 247.4C317.589 247.4 317.99 247.85 317.99 248.797V252H318.829V248.592C318.829 247.342 318.17 246.644 316.989 246.644C316.183 246.644 315.67 246.985 315.407 247.566H315.329V246.736H314.528V252Z" fill="#1D1E1F"/>
+<path d="M537.479 252H538.401L535.804 244.954H534.935L532.337 252H533.26L533.968 249.983H536.771L537.479 252ZM535.33 246.092H535.408L536.512 249.236H534.227L535.33 246.092ZM543.493 246.736H542.653V249.852C542.653 250.774 542.145 251.326 541.218 251.326C540.378 251.326 540.026 250.887 540.026 249.939V246.736H539.186V250.145C539.186 251.39 539.802 252.093 540.983 252.093C541.789 252.093 542.35 251.761 542.614 251.175H542.692V252H543.493V246.736ZM545.377 245.374V246.736H544.527V247.439H545.377V250.633C545.377 251.639 545.811 252.039 546.895 252.039C547.061 252.039 547.222 252.02 547.388 251.99V251.282C547.232 251.297 547.149 251.302 546.998 251.302C546.451 251.302 546.216 251.038 546.216 250.418V247.439H547.388V246.736H546.216V245.374H545.377ZM548.657 252H549.496V248.885C549.496 247.996 550.014 247.4 550.956 247.4C551.752 247.4 552.172 247.864 552.172 248.797V252H553.012V248.592C553.012 247.356 552.309 246.644 551.196 246.644C550.39 246.644 549.838 246.985 549.575 247.566H549.496V244.646H548.657V252ZM556.658 252.093C558.157 252.093 559.085 251.058 559.085 249.368C559.085 247.674 558.157 246.644 556.658 246.644C555.159 246.644 554.232 247.674 554.232 249.368C554.232 251.058 555.159 252.093 556.658 252.093ZM556.658 251.336C555.662 251.336 555.101 250.613 555.101 249.368C555.101 248.118 555.662 247.4 556.658 247.4C557.654 247.4 558.216 248.118 558.216 249.368C558.216 250.613 557.654 251.336 556.658 251.336ZM560.354 252H561.193V248.738C561.193 247.996 561.774 247.459 562.575 247.459C562.741 247.459 563.044 247.488 563.112 247.508V246.668C563.005 246.653 562.829 246.644 562.692 246.644C561.994 246.644 561.389 247.005 561.232 247.518H561.154V246.736H560.354V252Z" fill="#1D1E1F"/>
+<path d="M407.898 244.954V252H408.777V249.485H410.55C411.873 249.485 412.815 248.553 412.815 247.234C412.815 245.892 411.893 244.954 410.56 244.954H407.898ZM408.777 245.735H410.33C411.351 245.735 411.912 246.268 411.912 247.234C411.912 248.167 411.331 248.704 410.33 248.704H408.777V245.735ZM414.147 252H414.987V244.646H414.147V252ZM418.033 252.093C418.736 252.093 419.312 251.785 419.654 251.224H419.732V252H420.533V248.396C420.533 247.303 419.815 246.644 418.531 246.644C417.408 246.644 416.578 247.2 416.465 248.045H417.315C417.432 247.63 417.872 247.391 418.502 247.391C419.288 247.391 419.693 247.747 419.693 248.396V248.875L418.174 248.968C416.949 249.041 416.255 249.583 416.255 250.525C416.255 251.487 417.012 252.093 418.033 252.093ZM418.189 251.355C417.579 251.355 417.125 251.043 417.125 250.506C417.125 249.979 417.476 249.7 418.277 249.646L419.693 249.554V250.037C419.693 250.789 419.053 251.355 418.189 251.355ZM422.387 245.374V246.736H421.538V247.439H422.387V250.633C422.387 251.639 422.822 252.039 423.906 252.039C424.072 252.039 424.233 252.02 424.399 251.99V251.282C424.243 251.297 424.16 251.302 424.008 251.302C423.461 251.302 423.227 251.038 423.227 250.418V247.439H424.399V246.736H423.227V245.374H422.387ZM425.97 252H426.81V247.439H428.016V246.736H426.81V246.175C426.81 245.599 427.064 245.306 427.669 245.306C427.821 245.306 427.962 245.311 428.065 245.33V244.646C427.889 244.612 427.703 244.598 427.498 244.598C426.497 244.598 425.97 245.101 425.97 246.15V246.736H425.096V247.439H425.97V252ZM431.13 252.093C432.629 252.093 433.557 251.058 433.557 249.368C433.557 247.674 432.629 246.644 431.13 246.644C429.631 246.644 428.703 247.674 428.703 249.368C428.703 251.058 429.631 252.093 431.13 252.093ZM431.13 251.336C430.134 251.336 429.572 250.613 429.572 249.368C429.572 248.118 430.134 247.4 431.13 247.4C432.126 247.4 432.688 248.118 432.688 249.368C432.688 250.613 432.126 251.336 431.13 251.336ZM434.825 252H435.665V248.738C435.665 247.996 436.246 247.459 437.047 247.459C437.213 247.459 437.515 247.488 437.584 247.508V246.668C437.476 246.653 437.301 246.644 437.164 246.644C436.466 246.644 435.86 247.005 435.704 247.518H435.626V246.736H434.825V252ZM438.681 252H439.521V248.738C439.521 247.996 440.053 247.4 440.742 247.4C441.406 247.4 441.84 247.801 441.84 248.426V252H442.68V248.616C442.68 247.947 443.169 247.4 443.901 247.4C444.643 247.4 445.009 247.781 445.009 248.558V252H445.849V248.362C445.849 247.259 445.249 246.644 444.174 246.644C443.447 246.644 442.846 247.01 442.563 247.566H442.485C442.241 247.02 441.743 246.644 441.03 246.644C440.327 246.644 439.799 246.98 439.56 247.566H439.482V246.736H438.681V252ZM447.21 248.177C447.21 248.938 447.66 249.363 448.646 249.603L449.549 249.822C450.111 249.959 450.384 250.203 450.384 250.564C450.384 251.048 449.876 251.385 449.168 251.385C448.495 251.385 448.075 251.102 447.933 250.657H447.069C447.162 251.531 447.967 252.093 449.139 252.093C450.335 252.093 451.248 251.443 451.248 250.501C451.248 249.744 450.77 249.314 449.779 249.075L448.968 248.88C448.348 248.729 448.055 248.504 448.055 248.143C448.055 247.674 448.543 247.356 449.168 247.356C449.803 247.356 450.213 247.635 450.326 248.055H451.156C451.043 247.19 450.277 246.644 449.173 246.644C448.055 246.644 447.21 247.303 447.21 248.177Z" fill="#1D1E1F"/>
+<path d="M0 109C0 104.582 3.58172 101 8 101H56V576H8C3.58172 576 0 572.418 0 568V109Z" fill="url(#paint1_linear)"/>
+<path d="M56 195H0V247H56V195Z" fill="#63D0FF"/>
+<path fill-rule="evenodd" clip-rule="evenodd" d="M18.7725 209.595L28.555 215.25V236.095L18.7725 230.44V209.595Z" fill="black"/>
+<path d="M33.3997 212.032L22.7646 205.905V210.155L29.9997 214.335V227.097L33.4022 229.052C35.5072 230.267 37.2297 229.552 37.2297 227.435V218.07C37.2272 215.965 35.4997 213.25 33.3997 212.032Z" fill="black"/>
+<path d="M200 273H95C93.8954 273 93 273.895 93 275V295C93 296.105 93.8954 297 95 297H200C201.105 297 202 296.105 202 295V275C202 273.895 201.105 273 200 273Z" fill="#D4F2FF"/>
+<path d="M100.791 289H102.002V285.899C102.002 285.118 102.446 284.596 103.242 284.596C103.945 284.596 104.316 285.016 104.316 285.841V289H105.527V285.558C105.527 284.288 104.834 283.565 103.691 283.565C102.896 283.565 102.324 283.927 102.07 284.527H101.982V281.598H100.791V289ZM108.383 289.088C109.081 289.088 109.667 288.785 109.965 288.268H110.048V289H111.215V285.353C111.215 284.225 110.443 283.561 109.071 283.561C107.802 283.561 106.918 284.156 106.82 285.089H107.963C108.075 284.723 108.456 284.522 109.012 284.522C109.667 284.522 110.018 284.82 110.018 285.353V285.812L108.641 285.895C107.343 285.968 106.615 286.529 106.615 287.486C106.615 288.463 107.352 289.088 108.383 289.088ZM108.739 288.155C108.202 288.155 107.816 287.887 107.816 287.428C107.816 286.983 108.134 286.734 108.812 286.69L110.018 286.607V287.042C110.018 287.677 109.471 288.155 108.739 288.155ZM112.503 285.187C112.503 285.987 112.986 286.456 114.011 286.69L114.959 286.91C115.466 287.027 115.696 287.223 115.696 287.525C115.696 287.931 115.271 288.209 114.661 288.209C114.055 288.209 113.679 287.965 113.562 287.569H112.366C112.459 288.531 113.298 289.107 114.631 289.107C115.964 289.107 116.907 288.429 116.907 287.408C116.907 286.622 116.433 286.188 115.413 285.953L114.47 285.743C113.933 285.616 113.679 285.426 113.679 285.123C113.679 284.728 114.094 284.459 114.646 284.459C115.212 284.459 115.569 284.703 115.657 285.079H116.795C116.707 284.117 115.911 283.561 114.641 283.561C113.381 283.561 112.503 284.229 112.503 285.187ZM118.131 289H119.342V285.899C119.342 285.118 119.787 284.596 120.582 284.596C121.286 284.596 121.657 285.016 121.657 285.841V289H122.868V285.558C122.868 284.288 122.174 283.565 121.032 283.565C120.236 283.565 119.664 283.927 119.411 284.527H119.323V281.598H118.131V289ZM124.868 282.77C125.269 282.77 125.596 282.452 125.596 282.052C125.596 281.656 125.269 281.334 124.868 281.334C124.473 281.334 124.146 281.656 124.146 282.052C124.146 282.452 124.473 282.77 124.868 282.77ZM124.268 289H125.474V283.663H124.268V289ZM131.542 285.445C131.415 284.342 130.585 283.561 129.213 283.561C127.606 283.561 126.664 284.591 126.664 286.319C126.664 288.067 127.611 289.107 129.218 289.107C130.57 289.107 131.41 288.355 131.542 287.252H130.39C130.263 287.813 129.843 288.111 129.213 288.111C128.388 288.111 127.89 287.452 127.89 286.319C127.89 285.206 128.383 284.552 129.213 284.552C129.877 284.552 130.277 284.928 130.39 285.445H131.542ZM134.954 289.107C136.551 289.107 137.522 288.062 137.522 286.329C137.522 284.605 136.546 283.561 134.954 283.561C133.367 283.561 132.386 284.61 132.386 286.329C132.386 288.062 133.352 289.107 134.954 289.107ZM134.954 288.116C134.109 288.116 133.626 287.462 133.626 286.334C133.626 285.206 134.109 284.552 134.954 284.552C135.794 284.552 136.277 285.206 136.277 286.334C136.277 287.462 135.799 288.116 134.954 288.116ZM138.693 289H139.904V285.899C139.904 285.147 140.451 284.659 141.237 284.659C141.442 284.659 141.764 284.693 141.857 284.728V283.624C141.745 283.595 141.53 283.575 141.354 283.575C140.666 283.575 140.089 283.966 139.943 284.493H139.86V283.663H138.693V289ZM145.782 283.575C145.049 283.575 144.429 283.941 144.121 284.547H144.038V283.663H142.871V290.772H144.082V288.189H144.165C144.439 288.756 145.03 289.088 145.796 289.088C147.144 289.088 147.984 288.028 147.984 286.334C147.984 284.625 147.134 283.575 145.782 283.575ZM145.401 288.082C144.576 288.082 144.063 287.413 144.058 286.334C144.063 285.255 144.58 284.586 145.406 284.586C146.236 284.586 146.739 285.24 146.739 286.334C146.739 287.428 146.241 288.082 145.401 288.082ZM149.526 290.509L152.055 281.598H150.966L148.432 290.509H149.526ZM157.396 285.445C157.269 284.342 156.438 283.561 155.066 283.561C153.46 283.561 152.518 284.591 152.518 286.319C152.518 288.067 153.465 289.107 155.071 289.107C156.424 289.107 157.264 288.355 157.396 287.252H156.243C156.116 287.813 155.696 288.111 155.066 288.111C154.241 288.111 153.743 287.452 153.743 286.319C153.743 285.206 154.236 284.552 155.066 284.552C155.73 284.552 156.131 284.928 156.243 285.445H157.396ZM160.807 289.107C162.404 289.107 163.376 288.062 163.376 286.329C163.376 284.605 162.399 283.561 160.807 283.561C159.221 283.561 158.239 284.61 158.239 286.329C158.239 288.062 159.206 289.107 160.807 289.107ZM160.807 288.116C159.963 288.116 159.479 287.462 159.479 286.334C159.479 285.206 159.963 284.552 160.807 284.552C161.647 284.552 162.131 285.206 162.131 286.334C162.131 287.462 161.652 288.116 160.807 288.116ZM164.546 289H165.757V285.753C165.757 285.089 166.202 284.586 166.802 284.586C167.398 284.586 167.769 284.947 167.769 285.538V289H168.946V285.665C168.946 285.055 169.361 284.586 169.991 284.586C170.64 284.586 170.967 284.933 170.967 285.626V289H172.173V285.328C172.173 284.22 171.529 283.561 170.46 283.561C169.717 283.561 169.102 283.941 168.838 284.522H168.755C168.531 283.932 168.018 283.561 167.281 283.561C166.573 283.561 166.026 283.922 165.796 284.522H165.713V283.663H164.546V289ZM173.559 289H174.77V285.753C174.77 285.089 175.214 284.586 175.815 284.586C176.411 284.586 176.782 284.947 176.782 285.538V289H177.958V285.665C177.958 285.055 178.373 284.586 179.003 284.586C179.653 284.586 179.98 284.933 179.98 285.626V289H181.186V285.328C181.186 284.22 180.541 283.561 179.472 283.561C178.73 283.561 178.115 283.941 177.851 284.522H177.768C177.543 283.932 177.031 283.561 176.293 283.561C175.585 283.561 175.038 283.922 174.809 284.522H174.726V283.663H173.559V289ZM184.876 289.107C186.473 289.107 187.445 288.062 187.445 286.329C187.445 284.605 186.468 283.561 184.876 283.561C183.289 283.561 182.308 284.61 182.308 286.329C182.308 288.062 183.275 289.107 184.876 289.107ZM184.876 288.116C184.031 288.116 183.548 287.462 183.548 286.334C183.548 285.206 184.031 284.552 184.876 284.552C185.716 284.552 186.199 285.206 186.199 286.334C186.199 287.462 185.721 288.116 184.876 288.116ZM188.615 289H189.826V285.89C189.826 285.089 190.28 284.586 191.003 284.586C191.74 284.586 192.082 285.001 192.082 285.831V289H193.293V285.548C193.293 284.278 192.644 283.561 191.452 283.561C190.656 283.561 190.119 283.922 189.865 284.518H189.782V283.663H188.615V289Z" fill="black"/>
+<path d="M100 290.821H193.986V291.627H100V290.821Z" fill="black"/>
+<path d="M258.4 283.663H257.121L255.896 287.813H255.812L254.577 283.663H253.278L255.178 289H256.511L258.4 283.663ZM260.992 285.855H261.876C262.745 285.855 263.272 286.29 263.272 286.998C263.272 287.682 262.701 288.141 261.89 288.141C261.075 288.141 260.523 287.721 260.47 287.066H259.263C259.322 288.341 260.372 289.176 261.905 289.176C263.429 289.176 264.561 288.297 264.561 287.086C264.561 286.124 263.961 285.504 263.004 285.357V285.274C263.751 285.074 264.283 284.513 264.288 283.663C264.293 282.652 263.448 281.778 261.949 281.778C260.421 281.778 259.464 282.643 259.4 283.878H260.582C260.636 283.175 261.114 282.784 261.881 282.784C262.628 282.784 263.072 283.243 263.072 283.824C263.072 284.464 262.574 284.913 261.851 284.913H260.992V285.855ZM267.563 289H268.823V281.954H267.568L265.727 283.248V284.435L267.48 283.194H267.563V289ZM277.087 287.638C276.867 288.102 276.408 288.351 275.73 288.351C274.836 288.351 274.255 287.691 274.211 286.651V286.612H277.995V286.29C277.995 284.654 277.131 283.644 275.71 283.644C274.265 283.644 273.337 284.718 273.337 286.373C273.337 288.038 274.25 289.093 275.71 289.093C276.862 289.093 277.683 288.536 277.927 287.638H277.087ZM275.7 284.386C276.535 284.386 277.092 285.001 277.112 285.934H274.211C274.275 285.001 274.861 284.386 275.7 284.386ZM282.75 287.638C282.53 288.102 282.071 288.351 281.393 288.351C280.499 288.351 279.918 287.691 279.874 286.651V286.612H283.658V286.29C283.658 284.654 282.794 283.644 281.373 283.644C279.928 283.644 279 284.718 279 286.373C279 288.038 279.913 289.093 281.373 289.093C282.525 289.093 283.346 288.536 283.59 287.638H282.75ZM281.363 284.386C282.198 284.386 282.755 285.001 282.774 285.934H279.874C279.938 285.001 280.523 284.386 281.363 284.386ZM285.278 289H286.118V284.439H287.324V283.736H286.118V283.175C286.118 282.599 286.372 282.306 286.977 282.306C287.129 282.306 287.27 282.311 287.373 282.33V281.646C287.197 281.612 287.012 281.598 286.806 281.598C285.805 281.598 285.278 282.101 285.278 283.15V283.736H284.404V284.439H285.278V289ZM290.746 289.161C292.469 289.161 293.456 287.774 293.456 285.353C293.456 282.955 292.323 281.788 290.804 281.788C289.359 281.788 288.334 282.799 288.334 284.215C288.334 285.582 289.305 286.573 290.648 286.573C291.488 286.573 292.176 286.173 292.523 285.489H292.601C292.552 287.364 291.903 288.38 290.755 288.38C290.062 288.38 289.525 287.994 289.339 287.359H288.436C288.656 288.468 289.549 289.161 290.746 289.161ZM290.804 285.812C289.872 285.812 289.222 285.147 289.222 284.186C289.222 283.263 289.911 282.56 290.814 282.56C291.717 282.56 292.406 283.272 292.406 284.215C292.406 285.147 291.737 285.812 290.804 285.812ZM296.291 289.093C296.995 289.093 297.571 288.785 297.912 288.224H297.991V289H298.791V285.396C298.791 284.303 298.074 283.644 296.789 283.644C295.666 283.644 294.836 284.2 294.724 285.045H295.574C295.691 284.63 296.13 284.391 296.76 284.391C297.546 284.391 297.952 284.747 297.952 285.396V285.875L296.433 285.968C295.207 286.041 294.514 286.583 294.514 287.525C294.514 288.487 295.271 289.093 296.291 289.093ZM296.448 288.355C295.837 288.355 295.383 288.043 295.383 287.506C295.383 286.979 295.735 286.7 296.536 286.646L297.952 286.554V287.037C297.952 287.789 297.312 288.355 296.448 288.355ZM304.65 285.348C304.503 284.41 303.722 283.644 302.443 283.644C300.968 283.644 300.03 284.708 300.03 286.349C300.03 288.023 300.973 289.093 302.447 289.093C303.712 289.093 304.498 288.38 304.65 287.413H303.8C303.644 288.009 303.151 288.336 302.443 288.336C301.505 288.336 300.9 287.564 300.9 286.349C300.9 285.157 301.495 284.4 302.443 284.4C303.199 284.4 303.663 284.825 303.8 285.348H304.65ZM307.52 289H308.398V281.954H307.524L305.649 283.302V284.229L307.441 282.931H307.52V289Z" fill="#727274"/>
+<path d="M413.641 283.352C413.641 283.601 413.668 283.802 413.714 283.95C413.768 284.098 413.835 284.259 413.928 284.434C413.961 284.488 413.975 284.542 413.975 284.589C413.975 284.656 413.935 284.723 413.848 284.79L413.427 285.073C413.367 285.113 413.307 285.133 413.254 285.133C413.187 285.133 413.12 285.099 413.054 285.039C412.96 284.938 412.88 284.831 412.813 284.723C412.746 284.609 412.68 284.481 412.606 284.326C412.086 284.945 411.431 285.254 410.644 285.254C410.083 285.254 409.636 285.093 409.308 284.77C408.981 284.447 408.814 284.017 408.814 283.48C408.814 282.908 409.015 282.445 409.422 282.095C409.829 281.746 410.37 281.571 411.058 281.571C411.284 281.571 411.518 281.591 411.765 281.625C412.012 281.658 412.266 281.712 412.533 281.772V281.282C412.533 280.771 412.426 280.415 412.219 280.206C412.005 279.998 411.645 279.897 411.131 279.897C410.897 279.897 410.657 279.924 410.41 279.985C410.163 280.045 409.923 280.119 409.689 280.213C409.582 280.26 409.502 280.287 409.455 280.301C409.409 280.314 409.375 280.321 409.349 280.321C409.255 280.321 409.208 280.254 409.208 280.112V279.783C409.208 279.676 409.222 279.595 409.255 279.548C409.288 279.501 409.349 279.454 409.442 279.407C409.676 279.286 409.956 279.185 410.283 279.104C410.61 279.017 410.957 278.977 411.325 278.977C412.119 278.977 412.7 279.158 413.074 279.521C413.441 279.884 413.628 280.435 413.628 281.174V283.352H413.641ZM410.931 284.374C411.151 284.374 411.378 284.333 411.618 284.253C411.859 284.172 412.072 284.024 412.252 283.822C412.359 283.695 412.439 283.554 412.479 283.392C412.52 283.231 412.546 283.036 412.546 282.808V282.525C412.353 282.478 412.146 282.438 411.932 282.411C411.718 282.384 411.511 282.371 411.305 282.371C410.857 282.371 410.53 282.458 410.31 282.64C410.09 282.821 409.983 283.076 409.983 283.412C409.983 283.728 410.063 283.964 410.23 284.125C410.39 284.293 410.624 284.374 410.931 284.374ZM416.291 285.099C416.171 285.099 416.091 285.079 416.038 285.032C415.984 284.992 415.938 284.898 415.897 284.77L414.329 279.575C414.289 279.44 414.269 279.353 414.269 279.306C414.269 279.198 414.322 279.138 414.429 279.138H415.083C415.21 279.138 415.297 279.158 415.343 279.205C415.397 279.245 415.437 279.339 415.477 279.467L416.598 283.917L417.64 279.467C417.673 279.333 417.713 279.245 417.767 279.205C417.82 279.165 417.914 279.138 418.034 279.138H418.568C418.695 279.138 418.781 279.158 418.835 279.205C418.888 279.245 418.935 279.339 418.962 279.467L420.016 283.97L421.171 279.467C421.211 279.333 421.258 279.245 421.305 279.205C421.358 279.165 421.445 279.138 421.565 279.138H422.186C422.293 279.138 422.353 279.192 422.353 279.306C422.353 279.339 422.346 279.373 422.34 279.413C422.333 279.454 422.32 279.507 422.293 279.581L420.684 284.777C420.644 284.911 420.597 284.999 420.544 285.039C420.49 285.079 420.404 285.106 420.29 285.106H419.716C419.589 285.106 419.502 285.086 419.449 285.039C419.396 284.992 419.349 284.905 419.322 284.77L418.287 280.435L417.259 284.763C417.226 284.898 417.186 284.985 417.132 285.032C417.079 285.079 416.986 285.099 416.865 285.099H416.291ZM424.87 285.281C424.523 285.281 424.175 285.241 423.842 285.16C423.508 285.079 423.248 284.992 423.074 284.891C422.967 284.831 422.894 284.763 422.867 284.703C422.84 284.642 422.827 284.575 422.827 284.515V284.172C422.827 284.031 422.88 283.964 422.98 283.964C423.021 283.964 423.061 283.97 423.101 283.984C423.141 283.997 423.201 284.024 423.268 284.051C423.495 284.152 423.742 284.232 424.002 284.286C424.269 284.34 424.529 284.367 424.796 284.367C425.217 284.367 425.544 284.293 425.771 284.145C425.998 283.997 426.118 283.782 426.118 283.507C426.118 283.318 426.058 283.164 425.938 283.036C425.818 282.908 425.591 282.794 425.264 282.687L424.296 282.384C423.808 282.23 423.448 282.001 423.227 281.699C423.007 281.403 422.894 281.073 422.894 280.724C422.894 280.442 422.954 280.193 423.074 279.978C423.194 279.763 423.354 279.575 423.555 279.427C423.755 279.272 423.982 279.158 424.249 279.077C424.516 278.997 424.796 278.963 425.09 278.963C425.237 278.963 425.39 278.97 425.537 278.99C425.691 279.01 425.831 279.037 425.971 279.064C426.105 279.097 426.232 279.131 426.352 279.171C426.472 279.212 426.565 279.252 426.632 279.292C426.726 279.346 426.792 279.4 426.832 279.46C426.872 279.514 426.892 279.588 426.892 279.682V279.998C426.892 280.139 426.839 280.213 426.739 280.213C426.686 280.213 426.599 280.186 426.485 280.133C426.105 279.958 425.677 279.87 425.204 279.87C424.823 279.87 424.523 279.931 424.316 280.059C424.109 280.186 424.002 280.381 424.002 280.657C424.002 280.845 424.069 281.006 424.202 281.134C424.336 281.262 424.583 281.389 424.936 281.504L425.884 281.806C426.365 281.961 426.712 282.176 426.919 282.451C427.126 282.727 427.226 283.043 427.226 283.392C427.226 283.681 427.166 283.943 427.053 284.172C426.933 284.4 426.772 284.602 426.565 284.763C426.358 284.931 426.111 285.052 425.824 285.14C425.524 285.234 425.21 285.281 424.87 285.281Z" fill="#252F3E"/>
+<path fill-rule="evenodd" clip-rule="evenodd" d="M426.131 288.547C423.935 290.181 420.744 291.048 418 291.048C414.155 291.048 410.69 289.616 408.073 287.237C407.866 287.049 408.053 286.793 408.3 286.941C411.131 288.594 414.622 289.596 418.234 289.596C420.671 289.596 423.348 289.085 425.811 288.037C426.178 287.869 426.492 288.279 426.131 288.547Z" fill="#FF9900"/>
+<path fill-rule="evenodd" clip-rule="evenodd" d="M427.046 287.499C426.766 287.136 425.19 287.324 424.476 287.411C424.262 287.438 424.229 287.25 424.423 287.109C425.678 286.222 427.741 286.477 427.981 286.773C428.221 287.075 427.914 289.152 426.739 290.147C426.559 290.302 426.385 290.221 426.465 290.019C426.732 289.354 427.327 287.855 427.046 287.499Z" fill="#FF9900"/>
+<path d="M442.317 282.621C441.449 282.629 440.605 282.907 439.903 283.414C439.201 283.922 438.675 284.634 438.399 285.453C438.123 286.272 438.109 287.156 438.361 287.983C438.613 288.809 439.117 289.537 439.804 290.065L441.645 288.238C441.4 288.135 441.199 287.95 441.031 287.744C440.863 287.539 440.748 287.296 440.697 287.036C440.646 286.776 440.66 286.507 440.737 286.254C440.815 286.001 440.954 285.77 441.143 285.583C441.331 285.396 441.563 285.258 441.817 285.181C442.072 285.104 442.341 285.091 442.602 285.142C442.863 285.194 443.108 285.308 443.314 285.476C443.52 285.643 443.681 285.859 443.784 286.103L445.64 284.251C445.25 283.743 444.747 283.331 444.17 283.048C443.594 282.765 442.959 282.619 442.317 282.621Z" fill="#FBBC05"/>
+<path d="M449.339 280.531C450.182 281.276 450.809 282.265 451.103 283.347C451.841 283.848 452.397 284.571 452.691 285.41C452.985 286.249 453 287.16 452.735 288.009C452.47 288.858 451.939 289.599 451.219 290.125C450.499 290.65 449.629 290.932 448.736 290.928H445.527H445.526V288.379L445.527 288.378H448.736C449.123 288.324 449.476 288.132 449.732 287.838C449.988 287.545 450.129 287.169 450.129 286.781C450.129 286.392 449.988 286.017 449.732 285.723C449.476 285.43 449.123 285.238 448.736 285.183V284.868C448.743 284.386 448.641 283.908 448.437 283.471C448.234 283.033 447.925 282.674 447.552 282.366L449.339 280.531Z" fill="#4285F4"/>
+<path d="M441.642 288.236C441.848 288.33 442.09 288.374 442.316 288.371H445.526V290.929H442.316C441.41 290.931 440.523 290.607 439.799 290.065L441.642 288.236Z" fill="#34A853"/>
+<path d="M449.339 280.53L447.553 282.367C446.919 281.855 446.112 281.604 445.298 281.665C444.484 281.727 443.725 282.096 443.176 282.698C443.175 282.701 443.174 282.704 443.172 282.707C442.892 282.649 442.605 282.62 442.317 282.621C441.474 282.629 440.654 282.891 439.964 283.371C439.963 283.359 439.962 283.345 439.962 283.331C440.218 282.39 440.711 281.528 441.395 280.829C442.079 280.13 442.93 279.616 443.869 279.336C444.808 279.055 445.803 279.018 446.76 279.227C447.717 279.436 448.605 279.885 449.339 280.53Z" fill="#EA4335"/>
+<path d="M468.731 279.176H463.058V284.759H468.731V279.176Z" fill="#F25022"/>
+<path d="M474.995 279.176H469.321V284.759H474.995V279.176Z" fill="#7FBA00"/>
+<path d="M468.731 285.34H463.058V290.924H468.731V285.34Z" fill="#00A4EF"/>
+<path d="M474.995 285.34H469.321V290.924H474.995V285.34Z" fill="#FFB900"/>
+<path d="M535.758 286.036H535.68V281.646H534.84V289H535.68V287.003L536.183 286.534L538.155 289H539.225L536.808 285.992L539.073 283.736H538.043L535.758 286.036ZM540.171 289H541.011V285.738C541.011 284.996 541.592 284.459 542.392 284.459C542.558 284.459 542.861 284.488 542.929 284.508V283.668C542.822 283.653 542.646 283.644 542.51 283.644C541.811 283.644 541.206 284.005 541.05 284.518H540.971V283.736H540.171V289ZM544.369 282.721C544.691 282.721 544.955 282.457 544.955 282.135C544.955 281.812 544.691 281.549 544.369 281.549C544.046 281.549 543.783 281.812 543.783 282.135C543.783 282.457 544.046 282.721 544.369 282.721ZM543.949 289H544.789V283.736H543.949V289ZM546.218 285.177C546.218 285.938 546.667 286.363 547.654 286.603L548.557 286.822C549.119 286.959 549.392 287.203 549.392 287.564C549.392 288.048 548.884 288.385 548.176 288.385C547.502 288.385 547.082 288.102 546.941 287.657H546.077C546.169 288.531 546.975 289.093 548.147 289.093C549.343 289.093 550.256 288.443 550.256 287.501C550.256 286.744 549.778 286.314 548.787 286.075L547.976 285.88C547.356 285.729 547.063 285.504 547.063 285.143C547.063 284.674 547.551 284.356 548.176 284.356C548.811 284.356 549.221 284.635 549.333 285.055H550.163C550.051 284.19 549.285 283.644 548.181 283.644C547.063 283.644 546.218 284.303 546.218 285.177ZM555.465 281.993C553.072 281.993 551.432 283.648 551.432 286.065C551.432 288.561 553.029 290.143 555.548 290.143C556.163 290.143 556.754 290.055 557.194 289.903V289.288C556.886 289.43 556.227 289.522 555.558 289.522C553.468 289.522 552.12 288.18 552.12 286.095C552.12 284.063 553.492 282.608 555.402 282.608C557.355 282.608 558.693 283.814 558.693 285.577C558.693 286.778 558.297 287.555 557.682 287.555C557.33 287.555 557.13 287.354 557.13 287.013V284.146H556.393V284.742H556.315C556.124 284.317 555.685 284.054 555.172 284.054C554.171 284.054 553.473 284.884 553.473 286.07C553.473 287.311 554.156 288.146 555.172 288.146C555.743 288.146 556.183 287.867 556.393 287.369H556.471C556.529 287.848 556.974 288.189 557.545 288.189C558.668 288.189 559.381 287.179 559.381 285.587C559.381 283.468 557.775 281.993 555.465 281.993ZM555.294 284.728C555.958 284.728 556.383 285.255 556.383 286.09C556.383 286.925 555.953 287.457 555.284 287.457C554.645 287.457 554.254 286.939 554.254 286.09C554.254 285.235 554.64 284.728 555.294 284.728ZM560.703 289H561.543V285.885C561.543 284.996 562.061 284.4 563.003 284.4C563.799 284.4 564.219 284.864 564.219 285.797V289H565.059V285.592C565.059 284.356 564.355 283.644 563.242 283.644C562.437 283.644 561.885 283.985 561.621 284.566H561.543V281.646H560.703V289ZM568.007 289.093C568.71 289.093 569.286 288.785 569.628 288.224H569.706V289H570.507V285.396C570.507 284.303 569.789 283.644 568.505 283.644C567.382 283.644 566.552 284.2 566.439 285.045H567.289C567.406 284.63 567.846 284.391 568.475 284.391C569.262 284.391 569.667 284.747 569.667 285.396V285.875L568.148 285.968C566.923 286.041 566.229 286.583 566.229 287.525C566.229 288.487 566.986 289.093 568.007 289.093ZM568.163 288.355C567.553 288.355 567.098 288.043 567.098 287.506C567.098 286.979 567.45 286.7 568.251 286.646L569.667 286.554V287.037C569.667 287.789 569.027 288.355 568.163 288.355ZM571.887 285.177C571.887 285.938 572.337 286.363 573.323 286.603L574.226 286.822C574.788 286.959 575.061 287.203 575.061 287.564C575.061 288.048 574.553 288.385 573.845 288.385C573.171 288.385 572.752 288.102 572.61 287.657H571.746C571.838 288.531 572.644 289.093 573.816 289.093C575.012 289.093 575.925 288.443 575.925 287.501C575.925 286.744 575.447 286.314 574.456 286.075L573.645 285.88C573.025 285.729 572.732 285.504 572.732 285.143C572.732 284.674 573.22 284.356 573.845 284.356C574.48 284.356 574.89 284.635 575.003 285.055H575.833C575.72 284.19 574.954 283.644 573.85 283.644C572.732 283.644 571.887 284.303 571.887 285.177ZM577.243 289H578.082V285.885C578.082 284.996 578.6 284.4 579.542 284.4C580.338 284.4 580.758 284.864 580.758 285.797V289H581.598V285.592C581.598 284.356 580.895 283.644 579.782 283.644C578.976 283.644 578.424 283.985 578.161 284.566H578.082V281.646H577.243V289ZM583.521 282.721C583.843 282.721 584.107 282.457 584.107 282.135C584.107 281.812 583.843 281.549 583.521 281.549C583.198 281.549 582.935 281.812 582.935 282.135C582.935 282.457 583.198 282.721 583.521 282.721ZM583.101 289H583.941V283.736H583.101V289ZM589.848 285.348C589.701 284.41 588.92 283.644 587.641 283.644C586.166 283.644 585.229 284.708 585.229 286.349C585.229 288.023 586.171 289.093 587.646 289.093C588.91 289.093 589.696 288.38 589.848 287.413H588.998C588.842 288.009 588.349 288.336 587.641 288.336C586.703 288.336 586.098 287.564 586.098 286.349C586.098 285.157 586.693 284.4 587.641 284.4C588.397 284.4 588.861 284.825 588.998 285.348H589.848ZM593.201 289.093C594.7 289.093 595.628 288.058 595.628 286.368C595.628 284.674 594.7 283.644 593.201 283.644C591.702 283.644 590.774 284.674 590.774 286.368C590.774 288.058 591.702 289.093 593.201 289.093ZM593.201 288.336C592.205 288.336 591.643 287.613 591.643 286.368C591.643 285.118 592.205 284.4 593.201 284.4C594.197 284.4 594.759 285.118 594.759 286.368C594.759 287.613 594.197 288.336 593.201 288.336ZM596.896 289H597.736V285.738C597.736 284.996 598.317 284.459 599.118 284.459C599.284 284.459 599.587 284.488 599.655 284.508V283.668C599.547 283.653 599.372 283.644 599.235 283.644C598.537 283.644 597.931 284.005 597.775 284.518H597.697V283.736H596.896V289ZM603.316 283.644C602.598 283.644 601.968 284.01 601.631 284.615H601.553V283.736H600.752V290.758H601.592V288.209H601.67C601.958 288.766 602.564 289.093 603.316 289.093C604.654 289.093 605.528 288.014 605.528 286.368C605.528 284.713 604.659 283.644 603.316 283.644ZM603.116 288.336C602.168 288.336 601.568 287.574 601.568 286.368C601.568 285.157 602.168 284.4 603.121 284.4C604.082 284.4 604.659 285.138 604.659 286.368C604.659 287.599 604.082 288.336 603.116 288.336ZM607.392 289.049C607.743 289.049 608.027 288.761 608.027 288.414C608.027 288.062 607.743 287.779 607.392 287.779C607.045 287.779 606.757 288.062 606.757 288.414C606.757 288.761 607.045 289.049 607.392 289.049ZM613.777 285.348C613.631 284.41 612.85 283.644 611.57 283.644C610.096 283.644 609.158 284.708 609.158 286.349C609.158 288.023 610.101 289.093 611.575 289.093C612.84 289.093 613.626 288.38 613.777 287.413H612.928C612.771 288.009 612.278 288.336 611.57 288.336C610.633 288.336 610.027 287.564 610.027 286.349C610.027 285.157 610.623 284.4 611.57 284.4C612.327 284.4 612.791 284.825 612.928 285.348H613.777ZM617.131 289.093C618.63 289.093 619.557 288.058 619.557 286.368C619.557 284.674 618.63 283.644 617.131 283.644C615.632 283.644 614.704 284.674 614.704 286.368C614.704 288.058 615.632 289.093 617.131 289.093ZM617.131 288.336C616.135 288.336 615.573 287.613 615.573 286.368C615.573 285.118 616.135 284.4 617.131 284.4C618.127 284.4 618.688 285.118 618.688 286.368C618.688 287.613 618.127 288.336 617.131 288.336ZM620.826 289H621.666V285.738C621.666 284.996 622.198 284.4 622.886 284.4C623.55 284.4 623.985 284.801 623.985 285.426V289H624.825V285.616C624.825 284.947 625.313 284.4 626.046 284.4C626.788 284.4 627.154 284.781 627.154 285.558V289H627.994V285.362C627.994 284.259 627.393 283.644 626.319 283.644C625.591 283.644 624.991 284.01 624.708 284.566H624.629C624.385 284.02 623.887 283.644 623.174 283.644C622.471 283.644 621.944 283.98 621.705 284.566H621.627V283.736H620.826V289Z" fill="#727274"/>
+<path d="M100.791 332H102.002V328.899C102.002 328.118 102.446 327.596 103.242 327.596C103.945 327.596 104.316 328.016 104.316 328.841V332H105.527V328.558C105.527 327.288 104.834 326.565 103.691 326.565C102.896 326.565 102.324 326.927 102.07 327.527H101.982V324.598H100.791V332ZM108.383 332.088C109.081 332.088 109.667 331.785 109.965 331.268H110.048V332H111.215V328.353C111.215 327.225 110.443 326.561 109.071 326.561C107.802 326.561 106.918 327.156 106.82 328.089H107.963C108.075 327.723 108.456 327.522 109.012 327.522C109.667 327.522 110.018 327.82 110.018 328.353V328.812L108.641 328.895C107.343 328.968 106.615 329.529 106.615 330.486C106.615 331.463 107.352 332.088 108.383 332.088ZM108.739 331.155C108.202 331.155 107.816 330.887 107.816 330.428C107.816 329.983 108.134 329.734 108.812 329.69L110.018 329.607V330.042C110.018 330.677 109.471 331.155 108.739 331.155ZM112.503 328.187C112.503 328.987 112.986 329.456 114.011 329.69L114.959 329.91C115.466 330.027 115.696 330.223 115.696 330.525C115.696 330.931 115.271 331.209 114.661 331.209C114.055 331.209 113.679 330.965 113.562 330.569H112.366C112.459 331.531 113.298 332.107 114.631 332.107C115.964 332.107 116.907 331.429 116.907 330.408C116.907 329.622 116.433 329.188 115.413 328.953L114.47 328.743C113.933 328.616 113.679 328.426 113.679 328.123C113.679 327.728 114.094 327.459 114.646 327.459C115.212 327.459 115.569 327.703 115.657 328.079H116.795C116.707 327.117 115.911 326.561 114.641 326.561C113.381 326.561 112.503 327.229 112.503 328.187ZM118.131 332H119.342V328.899C119.342 328.118 119.787 327.596 120.582 327.596C121.286 327.596 121.657 328.016 121.657 328.841V332H122.868V328.558C122.868 327.288 122.174 326.565 121.032 326.565C120.236 326.565 119.664 326.927 119.411 327.527H119.323V324.598H118.131V332ZM124.868 325.77C125.269 325.77 125.596 325.452 125.596 325.052C125.596 324.656 125.269 324.334 124.868 324.334C124.473 324.334 124.146 324.656 124.146 325.052C124.146 325.452 124.473 325.77 124.868 325.77ZM124.268 332H125.474V326.663H124.268V332ZM131.542 328.445C131.415 327.342 130.585 326.561 129.213 326.561C127.606 326.561 126.664 327.591 126.664 329.319C126.664 331.067 127.611 332.107 129.218 332.107C130.57 332.107 131.41 331.355 131.542 330.252H130.39C130.263 330.813 129.843 331.111 129.213 331.111C128.388 331.111 127.89 330.452 127.89 329.319C127.89 328.206 128.383 327.552 129.213 327.552C129.877 327.552 130.277 327.928 130.39 328.445H131.542ZM134.954 332.107C136.551 332.107 137.522 331.062 137.522 329.329C137.522 327.605 136.546 326.561 134.954 326.561C133.367 326.561 132.386 327.61 132.386 329.329C132.386 331.062 133.352 332.107 134.954 332.107ZM134.954 331.116C134.109 331.116 133.626 330.462 133.626 329.334C133.626 328.206 134.109 327.552 134.954 327.552C135.794 327.552 136.277 328.206 136.277 329.334C136.277 330.462 135.799 331.116 134.954 331.116ZM138.693 332H139.904V328.899C139.904 328.147 140.451 327.659 141.237 327.659C141.442 327.659 141.764 327.693 141.857 327.728V326.624C141.745 326.595 141.53 326.575 141.354 326.575C140.666 326.575 140.089 326.966 139.943 327.493H139.86V326.663H138.693V332ZM145.782 326.575C145.049 326.575 144.429 326.941 144.121 327.547H144.038V326.663H142.871V333.772H144.082V331.189H144.165C144.439 331.756 145.03 332.088 145.796 332.088C147.144 332.088 147.984 331.028 147.984 329.334C147.984 327.625 147.134 326.575 145.782 326.575ZM145.401 331.082C144.576 331.082 144.063 330.413 144.058 329.334C144.063 328.255 144.58 327.586 145.406 327.586C146.236 327.586 146.739 328.24 146.739 329.334C146.739 330.428 146.241 331.082 145.401 331.082ZM149.526 333.509L152.055 324.598H150.966L148.432 333.509H149.526ZM154.251 332.088C154.949 332.088 155.535 331.785 155.833 331.268H155.916V332H157.083V328.353C157.083 327.225 156.312 326.561 154.939 326.561C153.67 326.561 152.786 327.156 152.688 328.089H153.831C153.943 327.723 154.324 327.522 154.881 327.522C155.535 327.522 155.887 327.82 155.887 328.353V328.812L154.51 328.895C153.211 328.968 152.483 329.529 152.483 330.486C152.483 331.463 153.221 332.088 154.251 332.088ZM154.607 331.155C154.07 331.155 153.685 330.887 153.685 330.428C153.685 329.983 154.002 329.734 154.681 329.69L155.887 329.607V330.042C155.887 330.677 155.34 331.155 154.607 331.155ZM158.493 332H159.704V328.89C159.704 328.089 160.158 327.586 160.881 327.586C161.618 327.586 161.96 328.001 161.96 328.831V332H163.171V328.548C163.171 327.278 162.521 326.561 161.33 326.561C160.534 326.561 159.997 326.922 159.743 327.518H159.66V326.663H158.493V332ZM166.861 332.107C168.458 332.107 169.429 331.062 169.429 329.329C169.429 327.605 168.453 326.561 166.861 326.561C165.274 326.561 164.293 327.61 164.293 329.329C164.293 331.062 165.259 332.107 166.861 332.107ZM166.861 331.116C166.016 331.116 165.533 330.462 165.533 329.334C165.533 328.206 166.016 327.552 166.861 327.552C167.701 327.552 168.184 328.206 168.184 329.334C168.184 330.462 167.706 331.116 166.861 331.116ZM170.986 325.354V326.697H170.141V327.64H170.986V330.584C170.986 331.614 171.474 332.024 172.7 332.024C172.934 332.024 173.159 332.005 173.334 331.971V331.043C173.188 331.058 173.095 331.067 172.924 331.067C172.416 331.067 172.192 330.828 172.192 330.296V327.64H173.334V326.697H172.192V325.354H170.986ZM174.544 332H175.755V328.899C175.755 328.118 176.199 327.596 176.995 327.596C177.698 327.596 178.07 328.016 178.07 328.841V332H179.28V328.558C179.28 327.288 178.587 326.565 177.445 326.565C176.649 326.565 176.077 326.927 175.823 327.527H175.736V324.598H174.544V332ZM184.147 330.54C183.972 330.94 183.557 331.165 182.956 331.165C182.16 331.165 181.647 330.599 181.618 329.695V329.632H185.349V329.246C185.349 327.571 184.436 326.561 182.912 326.561C181.364 326.561 180.402 327.64 180.402 329.354C180.402 331.062 181.35 332.107 182.922 332.107C184.182 332.107 185.075 331.502 185.295 330.54H184.147ZM182.907 327.503C183.635 327.503 184.113 328.016 184.138 328.826H181.623C181.677 328.025 182.185 327.503 182.907 327.503ZM186.514 332H187.725V328.899C187.725 328.147 188.272 327.659 189.058 327.659C189.263 327.659 189.586 327.693 189.679 327.728V326.624C189.566 326.595 189.351 326.575 189.176 326.575C188.487 326.575 187.911 326.966 187.764 327.493H187.681V326.663H186.514V332Z" fill="black"/>
+<path d="M100 333.821H189.928V334.627H100V333.821Z" fill="black"/>
+<path d="M258.4 326.663H257.121L255.896 330.813H255.812L254.577 326.663H253.278L255.178 332H256.511L258.4 326.663ZM261.832 332.171C263.624 332.171 264.688 330.77 264.688 328.392C264.688 326.058 263.555 324.778 261.871 324.778C260.338 324.778 259.254 325.809 259.254 327.249C259.254 328.602 260.23 329.588 261.573 329.588C262.398 329.588 263.067 329.207 263.399 328.538H263.482C263.468 330.193 262.877 331.141 261.846 331.141C261.241 331.141 260.758 330.809 260.606 330.271H259.351C259.556 331.419 260.543 332.171 261.832 332.171ZM261.876 328.616C261.055 328.616 260.489 328.04 260.489 327.21C260.489 326.414 261.085 325.804 261.881 325.804C262.677 325.804 263.272 326.424 263.272 327.234C263.272 328.035 262.691 328.616 261.876 328.616ZM268.686 332.171C270.219 332.171 271.303 331.146 271.303 329.7C271.303 328.348 270.322 327.361 268.984 327.361C268.154 327.361 267.49 327.742 267.158 328.411H267.075C267.085 326.727 267.695 325.809 268.74 325.809C269.365 325.809 269.824 326.131 269.946 326.683H271.206C271.03 325.545 270.068 324.778 268.715 324.778C266.967 324.778 265.869 326.185 265.869 328.558C265.869 330.97 267.055 332.171 268.686 332.171ZM268.676 331.146C267.88 331.146 267.285 330.525 267.285 329.71C267.285 328.904 267.861 328.323 268.681 328.323C269.502 328.323 270.068 328.904 270.068 329.734C270.068 330.535 269.467 331.146 268.676 331.146ZM278.054 332.093C279.387 332.093 280.261 331.014 280.261 329.368C280.261 327.713 279.392 326.644 278.054 326.644C277.331 326.644 276.692 327 276.404 327.566H276.325V324.646H275.486V332H276.286V331.16H276.364C276.696 331.746 277.321 332.093 278.054 332.093ZM277.859 327.4C278.821 327.4 279.392 328.138 279.392 329.368C279.392 330.599 278.821 331.336 277.859 331.336C276.902 331.336 276.306 330.584 276.306 329.368C276.306 328.152 276.902 327.4 277.859 327.4ZM282.994 332.093C283.697 332.093 284.273 331.785 284.615 331.224H284.693V332H285.494V328.396C285.494 327.303 284.776 326.644 283.492 326.644C282.369 326.644 281.539 327.2 281.427 328.045H282.276C282.394 327.63 282.833 327.391 283.463 327.391C284.249 327.391 284.654 327.747 284.654 328.396V328.875L283.136 328.968C281.91 329.041 281.217 329.583 281.217 330.525C281.217 331.487 281.974 332.093 282.994 332.093ZM283.15 331.355C282.54 331.355 282.086 331.043 282.086 330.506C282.086 329.979 282.438 329.7 283.238 329.646L284.654 329.554V330.037C284.654 330.789 284.015 331.355 283.15 331.355ZM289.614 332.093C290.947 332.093 291.821 331.014 291.821 329.368C291.821 327.713 290.952 326.644 289.614 326.644C288.891 326.644 288.252 327 287.964 327.566H287.886V324.646H287.046V332H287.846V331.16H287.925C288.257 331.746 288.882 332.093 289.614 332.093ZM289.419 327.4C290.381 327.4 290.952 328.138 290.952 329.368C290.952 330.599 290.381 331.336 289.419 331.336C288.462 331.336 287.866 330.584 287.866 329.368C287.866 328.152 288.462 327.4 289.419 327.4ZM294.525 332H295.404V324.954H294.53L292.655 326.302V327.229L294.447 325.931H294.525V332ZM300.95 330.638C300.73 331.102 300.271 331.351 299.592 331.351C298.699 331.351 298.118 330.691 298.074 329.651V329.612H301.858V329.29C301.858 327.654 300.994 326.644 299.573 326.644C298.127 326.644 297.2 327.718 297.2 329.373C297.2 331.038 298.113 332.093 299.573 332.093C300.725 332.093 301.545 331.536 301.789 330.638H300.95ZM299.563 327.386C300.398 327.386 300.954 328.001 300.974 328.934H298.074C298.137 328.001 298.723 327.386 299.563 327.386ZM306.612 330.638C306.393 331.102 305.934 331.351 305.255 331.351C304.362 331.351 303.78 330.691 303.737 329.651V329.612H307.521V329.29C307.521 327.654 306.656 326.644 305.236 326.644C303.79 326.644 302.862 327.718 302.862 329.373C302.862 331.038 303.776 332.093 305.236 332.093C306.388 332.093 307.208 331.536 307.452 330.638H306.612ZM305.226 327.386C306.061 327.386 306.617 328.001 306.637 328.934H303.737C303.8 328.001 304.386 327.386 305.226 327.386ZM310.264 328.753H311.138C312.129 328.753 312.739 329.261 312.739 330.076C312.739 330.867 312.08 331.399 311.152 331.399C310.244 331.399 309.609 330.926 309.531 330.184H308.682C308.745 331.38 309.731 332.166 311.162 332.166C312.563 332.166 313.643 331.282 313.643 330.101C313.643 329.119 313.037 328.499 312.124 328.353V328.274C312.847 328.064 313.374 327.503 313.379 326.653C313.384 325.667 312.583 324.788 311.191 324.788C309.766 324.788 308.892 325.633 308.804 326.78H309.658C309.731 325.989 310.283 325.555 311.133 325.555C311.982 325.555 312.485 326.092 312.485 326.751C312.485 327.483 311.909 328.001 311.099 328.001H310.264V328.753Z" fill="#727274"/>
+<path d="M414.259 326.621C413.391 326.629 412.548 326.907 411.846 327.414C411.144 327.922 410.618 328.634 410.341 329.453C410.065 330.272 410.052 331.156 410.304 331.983C410.555 332.809 411.06 333.537 411.746 334.065L413.587 332.238C413.342 332.135 413.141 331.95 412.973 331.744C412.805 331.539 412.69 331.296 412.639 331.036C412.588 330.776 412.602 330.507 412.68 330.254C412.758 330.001 412.897 329.77 413.085 329.583C413.273 329.396 413.505 329.258 413.76 329.181C414.014 329.104 414.284 329.091 414.545 329.142C414.806 329.194 415.05 329.308 415.256 329.476C415.462 329.643 415.624 329.859 415.726 330.103L417.582 328.251C417.192 327.743 416.689 327.331 416.113 327.048C415.536 326.765 414.902 326.619 414.259 326.621Z" fill="#FBBC05"/>
+<path d="M421.282 324.531C422.124 325.276 422.751 326.265 423.046 327.347C423.783 327.848 424.34 328.571 424.633 329.41C424.927 330.249 424.943 331.16 424.678 332.009C424.413 332.858 423.881 333.599 423.162 334.125C422.442 334.65 421.571 334.932 420.679 334.928H417.469V332.379V332.378H420.679C421.065 332.324 421.419 332.132 421.675 331.838C421.93 331.545 422.071 331.169 422.071 330.781C422.071 330.392 421.93 330.017 421.675 329.723C421.419 329.43 421.065 329.238 420.679 329.183V328.868C420.685 328.386 420.583 327.908 420.38 327.471C420.176 327.033 419.868 326.674 419.494 326.366L421.282 324.531Z" fill="#4285F4"/>
+<path d="M413.584 332.236C413.79 332.33 414.032 332.374 414.259 332.371H417.469V334.929H414.259C413.353 334.931 412.466 334.607 411.741 334.065L413.584 332.236Z" fill="#34A853"/>
+<path d="M421.281 324.53L419.495 326.367C418.861 325.855 418.055 325.604 417.241 325.665C416.427 325.727 415.667 326.096 415.118 326.698C415.117 326.701 415.116 326.704 415.115 326.707C414.834 326.649 414.547 326.62 414.259 326.621C413.416 326.629 412.596 326.891 411.906 327.371C411.905 327.359 411.904 327.345 411.904 327.331C412.161 326.39 412.654 325.528 413.337 324.829C414.021 324.13 414.873 323.616 415.812 323.336C416.75 323.055 417.745 323.018 418.703 323.227C419.66 323.436 420.547 323.885 421.281 324.53Z" fill="#EA4335"/>
+<path d="M534.791 332H535.631V328.738C535.631 327.996 536.163 327.4 536.852 327.4C537.516 327.4 537.95 327.801 537.95 328.426V332H538.79V328.616C538.79 327.947 539.278 327.4 540.011 327.4C540.753 327.4 541.119 327.781 541.119 328.558V332H541.959V328.362C541.959 327.259 541.358 326.644 540.284 326.644C539.557 326.644 538.956 327.01 538.673 327.566H538.595C538.351 327.02 537.853 326.644 537.14 326.644C536.437 326.644 535.909 326.98 535.67 327.566H535.592V326.736H534.791V332ZM546.929 330.638C546.709 331.102 546.25 331.351 545.571 331.351C544.678 331.351 544.096 330.691 544.053 329.651V329.612H547.837V329.29C547.837 327.654 546.972 326.644 545.552 326.644C544.106 326.644 543.179 327.718 543.179 329.373C543.179 331.038 544.092 332.093 545.552 332.093C546.704 332.093 547.524 331.536 547.768 330.638H546.929ZM545.542 327.386C546.377 327.386 546.933 328.001 546.953 328.934H544.053C544.116 328.001 544.702 327.386 545.542 327.386ZM551.273 334.021C552.709 334.021 553.617 333.27 553.617 332.093V326.736H552.816V327.571H552.738C552.435 327.005 551.786 326.644 551.048 326.644C549.696 326.644 548.841 327.713 548.841 329.29C548.841 330.867 549.686 331.922 551.048 331.922C551.771 331.922 552.367 331.595 552.699 331.014H552.777V332.049C552.777 332.825 552.215 333.289 551.273 333.289C550.516 333.289 550.047 333.011 549.955 332.581H549.066C549.193 333.45 550.004 334.021 551.273 334.021ZM551.234 331.18C550.257 331.18 549.711 330.438 549.711 329.29C549.711 328.143 550.257 327.4 551.234 327.4C552.206 327.4 552.796 328.143 552.796 329.29C552.796 330.438 552.211 331.18 551.234 331.18ZM556.614 332.093C557.317 332.093 557.893 331.785 558.235 331.224H558.313V332H559.114V328.396C559.114 327.303 558.396 326.644 557.112 326.644C555.989 326.644 555.159 327.2 555.046 328.045H555.896C556.013 327.63 556.453 327.391 557.082 327.391C557.869 327.391 558.274 327.747 558.274 328.396V328.875L556.755 328.968C555.53 329.041 554.836 329.583 554.836 330.525C554.836 331.487 555.593 332.093 556.614 332.093ZM556.77 331.355C556.16 331.355 555.705 331.043 555.705 330.506C555.705 329.979 556.057 329.7 556.858 329.646L558.274 329.554V330.037C558.274 330.789 557.634 331.355 556.77 331.355ZM560.616 332H561.456V328.885C561.456 327.962 561.998 327.4 562.838 327.4C563.678 327.4 564.078 327.85 564.078 328.797V332H564.918V328.592C564.918 327.342 564.259 326.644 563.077 326.644C562.272 326.644 561.759 326.985 561.495 327.566H561.417V326.736H560.616V332ZM570.347 324.993C567.954 324.993 566.313 326.648 566.313 329.065C566.313 331.561 567.91 333.143 570.43 333.143C571.045 333.143 571.636 333.055 572.075 332.903V332.288C571.768 332.43 571.108 332.522 570.439 332.522C568.35 332.522 567.002 331.18 567.002 329.095C567.002 327.063 568.374 325.608 570.283 325.608C572.236 325.608 573.574 326.814 573.574 328.577C573.574 329.778 573.179 330.555 572.563 330.555C572.212 330.555 572.012 330.354 572.012 330.013V327.146H571.274V327.742H571.196C571.006 327.317 570.566 327.054 570.054 327.054C569.053 327.054 568.354 327.884 568.354 329.07C568.354 330.311 569.038 331.146 570.054 331.146C570.625 331.146 571.064 330.867 571.274 330.369H571.353C571.411 330.848 571.855 331.189 572.427 331.189C573.55 331.189 574.263 330.179 574.263 328.587C574.263 326.468 572.656 324.993 570.347 324.993ZM570.176 327.728C570.84 327.728 571.265 328.255 571.265 329.09C571.265 329.925 570.835 330.457 570.166 330.457C569.526 330.457 569.136 329.939 569.136 329.09C569.136 328.235 569.521 327.728 570.176 327.728ZM575.585 332H576.425V328.885C576.425 327.996 576.942 327.4 577.885 327.4C578.68 327.4 579.1 327.864 579.1 328.797V332H579.94V328.592C579.94 327.356 579.237 326.644 578.124 326.644C577.318 326.644 576.766 326.985 576.503 327.566H576.425V324.646H575.585V332ZM582.888 332.093C583.591 332.093 584.168 331.785 584.509 331.224H584.588V332H585.388V328.396C585.388 327.303 584.671 326.644 583.386 326.644C582.263 326.644 581.433 327.2 581.321 328.045H582.171C582.288 327.63 582.727 327.391 583.357 327.391C584.143 327.391 584.548 327.747 584.548 328.396V328.875L583.03 328.968C581.804 329.041 581.111 329.583 581.111 330.525C581.111 331.487 581.868 332.093 582.888 332.093ZM583.045 331.355C582.434 331.355 581.98 331.043 581.98 330.506C581.98 329.979 582.332 329.7 583.132 329.646L584.548 329.554V330.037C584.548 330.789 583.909 331.355 583.045 331.355ZM586.769 328.177C586.769 328.938 587.218 329.363 588.204 329.603L589.108 329.822C589.669 329.959 589.943 330.203 589.943 330.564C589.943 331.048 589.435 331.385 588.727 331.385C588.053 331.385 587.633 331.102 587.492 330.657H586.627C586.72 331.531 587.526 332.093 588.698 332.093C589.894 332.093 590.807 331.443 590.807 330.501C590.807 329.744 590.329 329.314 589.337 329.075L588.527 328.88C587.907 328.729 587.614 328.504 587.614 328.143C587.614 327.674 588.102 327.356 588.727 327.356C589.362 327.356 589.772 327.635 589.884 328.055H590.714C590.602 327.19 589.835 326.644 588.732 326.644C587.614 326.644 586.769 327.303 586.769 328.177ZM592.124 332H592.964V328.885C592.964 327.996 593.482 327.4 594.424 327.4C595.22 327.4 595.64 327.864 595.64 328.797V332H596.48V328.592C596.48 327.356 595.777 326.644 594.663 326.644C593.858 326.644 593.306 326.985 593.042 327.566H592.964V324.646H592.124V332ZM598.402 325.721C598.725 325.721 598.988 325.457 598.988 325.135C598.988 324.812 598.725 324.549 598.402 324.549C598.08 324.549 597.816 324.812 597.816 325.135C597.816 325.457 598.08 325.721 598.402 325.721ZM597.982 332H598.822V326.736H597.982V332ZM604.729 328.348C604.583 327.41 603.802 326.644 602.522 326.644C601.048 326.644 600.11 327.708 600.11 329.349C600.11 331.023 601.053 332.093 602.527 332.093C603.792 332.093 604.578 331.38 604.729 330.413H603.88C603.723 331.009 603.23 331.336 602.522 331.336C601.585 331.336 600.979 330.564 600.979 329.349C600.979 328.157 601.575 327.4 602.522 327.4C603.279 327.4 603.743 327.825 603.88 328.348H604.729ZM608.083 332.093C609.582 332.093 610.509 331.058 610.509 329.368C610.509 327.674 609.582 326.644 608.083 326.644C606.584 326.644 605.656 327.674 605.656 329.368C605.656 331.058 606.584 332.093 608.083 332.093ZM608.083 331.336C607.087 331.336 606.525 330.613 606.525 329.368C606.525 328.118 607.087 327.4 608.083 327.4C609.079 327.4 609.64 328.118 609.64 329.368C609.64 330.613 609.079 331.336 608.083 331.336ZM611.778 332H612.618V328.738C612.618 327.996 613.199 327.459 613.999 327.459C614.165 327.459 614.468 327.488 614.537 327.508V326.668C614.429 326.653 614.253 326.644 614.117 326.644C613.418 326.644 612.813 327.005 612.657 327.518H612.579V326.736H611.778V332ZM618.197 326.644C617.48 326.644 616.85 327.01 616.513 327.615H616.435V326.736H615.634V333.758H616.474V331.209H616.552C616.84 331.766 617.446 332.093 618.197 332.093C619.535 332.093 620.409 331.014 620.409 329.368C620.409 327.713 619.54 326.644 618.197 326.644ZM617.997 331.336C617.05 331.336 616.449 330.574 616.449 329.368C616.449 328.157 617.05 327.4 618.002 327.4C618.964 327.4 619.54 328.138 619.54 329.368C619.54 330.599 618.964 331.336 617.997 331.336ZM622.273 332.049C622.625 332.049 622.908 331.761 622.908 331.414C622.908 331.062 622.625 330.779 622.273 330.779C621.927 330.779 621.639 331.062 621.639 331.414C621.639 331.761 621.927 332.049 622.273 332.049ZM628.659 328.348C628.512 327.41 627.731 326.644 626.452 326.644C624.977 326.644 624.04 327.708 624.04 329.349C624.04 331.023 624.982 332.093 626.457 332.093C627.721 332.093 628.508 331.38 628.659 330.413H627.809C627.653 331.009 627.16 331.336 626.452 331.336C625.514 331.336 624.909 330.564 624.909 329.349C624.909 328.157 625.505 327.4 626.452 327.4C627.209 327.4 627.673 327.825 627.809 328.348H628.659ZM632.012 332.093C633.511 332.093 634.439 331.058 634.439 329.368C634.439 327.674 633.511 326.644 632.012 326.644C630.513 326.644 629.586 327.674 629.586 329.368C629.586 331.058 630.513 332.093 632.012 332.093ZM632.012 331.336C631.016 331.336 630.455 330.613 630.455 329.368C630.455 328.118 631.016 327.4 632.012 327.4C633.008 327.4 633.57 328.118 633.57 329.368C633.57 330.613 633.008 331.336 632.012 331.336ZM635.707 332H636.547V328.738C636.547 327.996 637.079 327.4 637.768 327.4C638.432 327.4 638.867 327.801 638.867 328.426V332H639.706V328.616C639.706 327.947 640.195 327.4 640.927 327.4C641.669 327.4 642.036 327.781 642.036 328.558V332H642.875V328.362C642.875 327.259 642.275 326.644 641.201 326.644C640.473 326.644 639.872 327.01 639.589 327.566H639.511C639.267 327.02 638.769 326.644 638.056 326.644C637.353 326.644 636.826 326.98 636.586 327.566H636.508V326.736H635.707V332Z" fill="#727274"/>
+<path d="M100.791 375H102.002V371.899C102.002 371.118 102.446 370.596 103.242 370.596C103.945 370.596 104.316 371.016 104.316 371.841V375H105.527V371.558C105.527 370.288 104.834 369.565 103.691 369.565C102.896 369.565 102.324 369.927 102.07 370.527H101.982V367.598H100.791V375ZM108.383 375.088C109.081 375.088 109.667 374.785 109.965 374.268H110.048V375H111.215V371.353C111.215 370.225 110.443 369.561 109.071 369.561C107.802 369.561 106.918 370.156 106.82 371.089H107.963C108.075 370.723 108.456 370.522 109.012 370.522C109.667 370.522 110.018 370.82 110.018 371.353V371.812L108.641 371.895C107.343 371.968 106.615 372.529 106.615 373.486C106.615 374.463 107.352 375.088 108.383 375.088ZM108.739 374.155C108.202 374.155 107.816 373.887 107.816 373.428C107.816 372.983 108.134 372.734 108.812 372.69L110.018 372.607V373.042C110.018 373.677 109.471 374.155 108.739 374.155ZM112.503 371.187C112.503 371.987 112.986 372.456 114.011 372.69L114.959 372.91C115.466 373.027 115.696 373.223 115.696 373.525C115.696 373.931 115.271 374.209 114.661 374.209C114.055 374.209 113.679 373.965 113.562 373.569H112.366C112.459 374.531 113.298 375.107 114.631 375.107C115.964 375.107 116.907 374.429 116.907 373.408C116.907 372.622 116.433 372.188 115.413 371.953L114.47 371.743C113.933 371.616 113.679 371.426 113.679 371.123C113.679 370.728 114.094 370.459 114.646 370.459C115.212 370.459 115.569 370.703 115.657 371.079H116.795C116.707 370.117 115.911 369.561 114.641 369.561C113.381 369.561 112.503 370.229 112.503 371.187ZM118.131 375H119.342V371.899C119.342 371.118 119.787 370.596 120.582 370.596C121.286 370.596 121.657 371.016 121.657 371.841V375H122.868V371.558C122.868 370.288 122.174 369.565 121.032 369.565C120.236 369.565 119.664 369.927 119.411 370.527H119.323V367.598H118.131V375ZM124.868 368.77C125.269 368.77 125.596 368.452 125.596 368.052C125.596 367.656 125.269 367.334 124.868 367.334C124.473 367.334 124.146 367.656 124.146 368.052C124.146 368.452 124.473 368.77 124.868 368.77ZM124.268 375H125.474V369.663H124.268V375ZM131.542 371.445C131.415 370.342 130.585 369.561 129.213 369.561C127.606 369.561 126.664 370.591 126.664 372.319C126.664 374.067 127.611 375.107 129.218 375.107C130.57 375.107 131.41 374.355 131.542 373.252H130.39C130.263 373.813 129.843 374.111 129.213 374.111C128.388 374.111 127.89 373.452 127.89 372.319C127.89 371.206 128.383 370.552 129.213 370.552C129.877 370.552 130.277 370.928 130.39 371.445H131.542ZM134.954 375.107C136.551 375.107 137.522 374.062 137.522 372.329C137.522 370.605 136.546 369.561 134.954 369.561C133.367 369.561 132.386 370.61 132.386 372.329C132.386 374.062 133.352 375.107 134.954 375.107ZM134.954 374.116C134.109 374.116 133.626 373.462 133.626 372.334C133.626 371.206 134.109 370.552 134.954 370.552C135.794 370.552 136.277 371.206 136.277 372.334C136.277 373.462 135.799 374.116 134.954 374.116ZM138.693 375H139.904V371.899C139.904 371.147 140.451 370.659 141.237 370.659C141.442 370.659 141.764 370.693 141.857 370.728V369.624C141.745 369.595 141.53 369.575 141.354 369.575C140.666 369.575 140.089 369.966 139.943 370.493H139.86V369.663H138.693V375ZM145.782 369.575C145.049 369.575 144.429 369.941 144.121 370.547H144.038V369.663H142.871V376.772H144.082V374.189H144.165C144.439 374.756 145.03 375.088 145.796 375.088C147.144 375.088 147.984 374.028 147.984 372.334C147.984 370.625 147.134 369.575 145.782 369.575ZM145.401 374.082C144.576 374.082 144.063 373.413 144.058 372.334C144.063 371.255 144.58 370.586 145.406 370.586C146.236 370.586 146.739 371.24 146.739 372.334C146.739 373.428 146.241 374.082 145.401 374.082ZM149.526 376.509L152.055 367.598H150.966L148.432 376.509H149.526ZM156.263 373.54C156.087 373.94 155.672 374.165 155.071 374.165C154.275 374.165 153.763 373.599 153.733 372.695V372.632H157.464V372.246C157.464 370.571 156.551 369.561 155.027 369.561C153.479 369.561 152.518 370.64 152.518 372.354C152.518 374.062 153.465 375.107 155.037 375.107C156.297 375.107 157.19 374.502 157.41 373.54H156.263ZM155.022 370.503C155.75 370.503 156.229 371.016 156.253 371.826H153.738C153.792 371.025 154.3 370.503 155.022 370.503ZM160.49 373.154L161.584 375.01H162.951L161.208 372.31L162.931 369.673H161.598L160.544 371.523H160.461L159.401 369.673H157.995L159.738 372.363L158.01 375.01H159.318L160.407 373.154H160.49ZM165.391 375.088C166.089 375.088 166.675 374.785 166.973 374.268H167.056V375H168.223V371.353C168.223 370.225 167.452 369.561 166.08 369.561C164.81 369.561 163.926 370.156 163.829 371.089H164.971C165.084 370.723 165.464 370.522 166.021 370.522C166.675 370.522 167.027 370.82 167.027 371.353V371.812L165.65 371.895C164.351 371.968 163.624 372.529 163.624 373.486C163.624 374.463 164.361 375.088 165.391 375.088ZM165.748 374.155C165.211 374.155 164.825 373.887 164.825 373.428C164.825 372.983 165.142 372.734 165.821 372.69L167.027 372.607V373.042C167.027 373.677 166.48 374.155 165.748 374.155ZM169.633 375H170.844V371.753C170.844 371.089 171.288 370.586 171.889 370.586C172.485 370.586 172.856 370.947 172.856 371.538V375H174.033V371.665C174.033 371.055 174.448 370.586 175.078 370.586C175.727 370.586 176.054 370.933 176.054 371.626V375H177.26V371.328C177.26 370.22 176.616 369.561 175.546 369.561C174.804 369.561 174.189 369.941 173.925 370.522H173.842C173.618 369.932 173.105 369.561 172.368 369.561C171.66 369.561 171.113 369.922 170.883 370.522H170.8V369.663H169.633V375ZM181.556 369.575C180.823 369.575 180.203 369.941 179.896 370.547H179.813V369.663H178.646V376.772H179.857V374.189H179.94C180.213 374.756 180.804 375.088 181.571 375.088C182.918 375.088 183.758 374.028 183.758 372.334C183.758 370.625 182.908 369.575 181.556 369.575ZM181.175 374.082C180.35 374.082 179.837 373.413 179.832 372.334C179.837 371.255 180.355 370.586 181.18 370.586C182.01 370.586 182.513 371.24 182.513 372.334C182.513 373.428 182.015 374.082 181.175 374.082ZM184.973 375H186.184V367.598H184.973V375ZM191.148 373.54C190.972 373.94 190.557 374.165 189.957 374.165C189.161 374.165 188.648 373.599 188.619 372.695V372.632H192.349V372.246C192.349 370.571 191.436 369.561 189.913 369.561C188.365 369.561 187.403 370.64 187.403 372.354C187.403 374.062 188.35 375.107 189.923 375.107C191.182 375.107 192.076 374.502 192.296 373.54H191.148ZM189.908 370.503C190.636 370.503 191.114 371.016 191.138 371.826H188.624C188.678 371.025 189.185 370.503 189.908 370.503Z" fill="black"/>
+<path d="M100 376.821H192.823V377.627H100V376.821Z" fill="black"/>
+<path d="M258.4 369.663H257.121L255.896 373.813H255.812L254.577 369.663H253.278L255.178 375H256.511L258.4 369.663ZM259.303 370.039H260.484C260.484 369.297 260.972 368.789 261.739 368.789C262.476 368.789 262.916 369.282 262.916 369.922C262.916 370.459 262.701 370.796 261.812 371.694L259.371 374.15V375H264.263V373.955H261.08V373.872L262.594 372.383C263.804 371.196 264.161 370.625 264.161 369.805C264.161 368.633 263.209 367.778 261.807 367.778C260.338 367.778 259.303 368.706 259.303 370.039ZM268.797 375H269.637V370.439H270.843V369.736H269.637V369.175C269.637 368.599 269.891 368.306 270.496 368.306C270.648 368.306 270.789 368.311 270.892 368.33V367.646C270.716 367.612 270.531 367.598 270.326 367.598C269.325 367.598 268.797 368.101 268.797 369.15V369.736H267.923V370.439H268.797V375ZM274.636 375.093C275.969 375.093 276.843 374.014 276.843 372.368C276.843 370.713 275.974 369.644 274.636 369.644C273.913 369.644 273.274 370 272.986 370.566H272.907V367.646H272.068V375H272.868V374.16H272.946C273.279 374.746 273.904 375.093 274.636 375.093ZM274.441 370.4C275.403 370.4 275.974 371.138 275.974 372.368C275.974 373.599 275.403 374.336 274.441 374.336C273.484 374.336 272.888 373.584 272.888 372.368C272.888 371.152 273.484 370.4 274.441 370.4ZM280.729 375.093C282.062 375.093 282.936 374.014 282.936 372.368C282.936 370.713 282.066 369.644 280.729 369.644C280.006 369.644 279.366 370 279.078 370.566H279V367.646H278.16V375H278.961V374.16H279.039C279.371 374.746 279.996 375.093 280.729 375.093ZM280.533 370.4C281.495 370.4 282.066 371.138 282.066 372.368C282.066 373.599 281.495 374.336 280.533 374.336C279.576 374.336 278.98 373.584 278.98 372.368C278.98 371.152 279.576 370.4 280.533 370.4ZM286.606 375.166C288.1 375.166 289.145 374.321 289.145 373.115C289.145 372.197 288.564 371.484 287.68 371.318V371.24C288.408 371.04 288.857 370.439 288.857 369.668C288.857 368.569 287.925 367.788 286.606 367.788C285.288 367.788 284.355 368.569 284.355 369.668C284.355 370.435 284.814 371.045 285.532 371.24V371.318C284.648 371.484 284.067 372.197 284.067 373.115C284.067 374.321 285.112 375.166 286.606 375.166ZM286.606 370.947C285.776 370.947 285.22 370.469 285.22 369.751C285.22 369.023 285.771 368.54 286.606 368.54C287.441 368.54 287.993 369.023 287.993 369.751C287.993 370.469 287.436 370.947 286.606 370.947ZM286.606 374.414C285.63 374.414 284.956 373.857 284.956 373.052C284.956 372.246 285.63 371.689 286.606 371.689C287.583 371.689 288.257 372.246 288.257 373.052C288.257 373.857 287.583 374.414 286.606 374.414ZM293.158 375.093C294.491 375.093 295.365 374.014 295.365 372.368C295.365 370.713 294.496 369.644 293.158 369.644C292.435 369.644 291.796 370 291.507 370.566H291.429V367.646H290.589V375H291.39V374.16H291.468C291.8 374.746 292.425 375.093 293.158 375.093ZM292.963 370.4C293.924 370.4 294.496 371.138 294.496 372.368C294.496 373.599 293.924 374.336 292.963 374.336C292.005 374.336 291.41 373.584 291.41 372.368C291.41 371.152 292.005 370.4 292.963 370.4ZM300.989 371.348C300.842 370.41 300.061 369.644 298.782 369.644C297.307 369.644 296.37 370.708 296.37 372.349C296.37 374.023 297.312 375.093 298.787 375.093C300.051 375.093 300.837 374.38 300.989 373.413H300.139C299.983 374.009 299.49 374.336 298.782 374.336C297.844 374.336 297.239 373.564 297.239 372.349C297.239 371.157 297.834 370.4 298.782 370.4C299.538 370.4 300.002 370.825 300.139 371.348H300.989ZM302.13 369.941H302.98C302.98 369.106 303.541 368.555 304.386 368.555C305.216 368.555 305.719 369.111 305.719 369.858C305.719 370.479 305.455 370.845 304.557 371.816L302.174 374.395V375H306.735V374.209H303.395V374.131L304.996 372.476C306.266 371.162 306.617 370.576 306.617 369.766C306.617 368.623 305.675 367.788 304.445 367.788C303.097 367.788 302.13 368.687 302.13 369.941Z" fill="#727274"/>
+<path d="M426.72 374.48L425.017 369.748C424.987 369.676 424.969 369.599 424.963 369.521C424.967 369.414 425.012 369.312 425.089 369.238C425.167 369.163 425.27 369.121 425.378 369.122C425.476 369.125 425.57 369.16 425.645 369.223C425.72 369.285 425.772 369.371 425.793 369.467L427.22 373.553L428.643 369.455C428.664 369.36 428.716 369.275 428.791 369.214C428.867 369.154 428.961 369.12 429.058 369.119H429.101C429.201 369.119 429.298 369.152 429.376 369.212C429.455 369.273 429.511 369.358 429.535 369.455L430.944 373.553L432.377 369.455C432.395 369.361 432.445 369.277 432.518 369.216C432.591 369.155 432.682 369.121 432.777 369.119C432.83 369.118 432.883 369.126 432.933 369.145C432.982 369.163 433.028 369.191 433.066 369.228C433.105 369.264 433.136 369.307 433.158 369.355C433.179 369.404 433.191 369.456 433.192 369.508C433.186 369.587 433.167 369.663 433.138 369.736L431.423 374.478C431.398 374.582 431.34 374.675 431.258 374.743C431.175 374.811 431.073 374.851 430.966 374.857H430.933C430.825 374.856 430.72 374.818 430.637 374.749C430.554 374.68 430.497 374.584 430.477 374.478L429.087 370.45L427.666 374.48C427.645 374.586 427.589 374.682 427.505 374.751C427.422 374.82 427.318 374.858 427.21 374.859H427.187C427.078 374.855 426.974 374.816 426.89 374.748C426.805 374.679 426.746 374.585 426.72 374.48Z" fill="#696566"/>
+<path d="M439.142 369.533C439.142 369.423 439.185 369.318 439.263 369.241C439.341 369.163 439.446 369.119 439.556 369.119C439.667 369.119 439.772 369.163 439.85 369.241C439.928 369.318 439.971 369.423 439.971 369.533V370.493C440.137 370.109 440.406 369.777 440.749 369.535C441.091 369.293 441.494 369.15 441.913 369.121C441.968 369.12 442.023 369.129 442.074 369.149C442.125 369.17 442.171 369.2 442.21 369.239C442.249 369.278 442.28 369.324 442.3 369.375C442.32 369.426 442.33 369.48 442.328 369.535C442.329 369.638 442.291 369.737 442.222 369.814C442.154 369.89 442.059 369.938 441.957 369.949C440.87 370.079 439.978 370.893 439.978 372.508V374.41C439.978 374.519 439.934 374.625 439.856 374.702C439.778 374.78 439.673 374.824 439.563 374.824C439.453 374.824 439.347 374.78 439.269 374.702C439.192 374.625 439.148 374.519 439.148 374.41V369.533H439.142Z" fill="#696566"/>
+<path d="M445.014 374.902C443.5 374.902 442.266 373.731 442.266 372.006V371.983C442.266 370.384 443.386 369.086 444.908 369.086C446.537 369.086 447.466 370.427 447.466 371.898C447.47 371.951 447.463 372.004 447.446 372.054C447.428 372.104 447.4 372.15 447.364 372.189C447.328 372.228 447.284 372.259 447.235 372.28C447.186 372.301 447.134 372.312 447.08 372.312H443.097C443.214 373.514 444.054 374.188 445.037 374.188C445.631 374.192 446.202 373.961 446.624 373.545C446.675 373.498 446.738 373.466 446.806 373.454C446.874 373.443 446.945 373.451 447.008 373.478C447.072 373.506 447.126 373.551 447.164 373.609C447.201 373.667 447.222 373.734 447.222 373.804C447.221 373.855 447.209 373.905 447.187 373.951C447.165 373.997 447.133 374.038 447.093 374.07C446.823 374.344 446.5 374.558 446.143 374.701C445.785 374.843 445.403 374.91 445.018 374.898L445.014 374.902ZM446.645 371.691C446.56 370.681 445.983 369.802 444.886 369.802C443.927 369.802 443.201 370.607 443.097 371.691H446.645Z" fill="#696566"/>
+<path d="M433.205 373.164V373.139C433.205 371.962 434.18 371.333 435.601 371.333C436.184 371.327 436.765 371.408 437.325 371.571V371.381C437.325 370.375 436.703 369.856 435.655 369.856C435.206 369.837 434.759 369.924 434.35 370.11C434.303 370.131 434.252 370.142 434.201 370.143C434.105 370.143 434.013 370.105 433.944 370.039C433.875 369.972 433.835 369.881 433.832 369.786C433.828 369.71 433.848 369.636 433.891 369.574C433.933 369.511 433.995 369.464 434.066 369.44C434.593 369.206 435.166 369.097 435.742 369.121C436.533 369.121 437.14 369.328 437.551 369.742C437.931 370.121 438.126 370.661 438.126 371.375V374.455C438.128 374.509 438.12 374.563 438.101 374.614C438.082 374.664 438.052 374.71 438.014 374.749C437.977 374.788 437.931 374.818 437.881 374.839C437.831 374.86 437.778 374.87 437.723 374.869C437.671 374.871 437.619 374.862 437.571 374.844C437.522 374.825 437.478 374.796 437.44 374.76C437.403 374.724 437.374 374.68 437.354 374.632C437.334 374.584 437.324 374.532 437.325 374.48V373.944C437.088 374.254 436.781 374.502 436.428 374.67C436.076 374.837 435.689 374.918 435.298 374.906C434.261 374.906 433.203 374.312 433.203 373.164H433.205ZM437.338 372.726V372.192C436.802 372.035 436.247 371.955 435.688 371.954C434.639 371.954 434.052 372.409 434.052 373.11V373.139C434.052 373.843 434.701 374.252 435.46 374.252C436.497 374.252 437.327 373.632 437.327 372.74" fill="#696566"/>
+<path d="M411.533 369.471C411.49 369.375 411.429 369.288 411.352 369.215C411.275 369.143 411.185 369.087 411.086 369.05C410.987 369.013 410.881 368.996 410.775 369.001C410.67 369.005 410.566 369.031 410.471 369.076C410.373 369.118 410.285 369.179 410.213 369.255C410.14 369.332 410.083 369.423 410.047 369.522C410.011 369.621 409.995 369.727 410.001 369.832C410.007 369.938 410.035 370.041 410.083 370.135L411.869 373.992C412.149 374.596 412.444 374.913 412.997 374.913C413.589 374.913 413.846 374.567 414.126 373.992L415.686 370.586C415.704 370.543 415.736 370.506 415.776 370.482C415.816 370.457 415.863 370.446 415.91 370.45C415.943 370.45 415.975 370.457 416.005 370.469C416.035 370.482 416.062 370.501 416.085 370.524C416.107 370.547 416.125 370.575 416.137 370.605C416.149 370.635 416.155 370.668 416.155 370.7V373.988C416.155 374.495 416.437 374.913 416.985 374.913C417.532 374.913 417.814 374.499 417.814 373.988V371.298C417.81 371.182 417.83 371.067 417.873 370.959C417.917 370.852 417.982 370.755 418.065 370.674C418.149 370.593 418.248 370.531 418.357 370.491C418.466 370.451 418.582 370.434 418.698 370.441C418.811 370.436 418.924 370.455 419.029 370.496C419.135 370.537 419.23 370.6 419.31 370.68C419.39 370.76 419.452 370.856 419.492 370.961C419.533 371.066 419.55 371.179 419.544 371.292V373.981C419.544 374.488 419.829 374.906 420.374 374.906C420.92 374.906 421.204 374.493 421.204 373.981V371.292C421.2 371.176 421.22 371.061 421.263 370.954C421.306 370.846 421.371 370.749 421.454 370.668C421.537 370.588 421.636 370.525 421.745 370.485C421.854 370.445 421.97 370.428 422.086 370.435C422.199 370.43 422.313 370.448 422.419 370.49C422.525 370.531 422.621 370.594 422.702 370.675C422.782 370.756 422.844 370.852 422.884 370.959C422.924 371.065 422.941 371.178 422.934 371.292V373.981C422.934 374.488 423.216 374.906 423.764 374.906C424.312 374.906 424.594 374.493 424.594 373.981V370.919C424.606 369.792 423.693 369.001 422.602 369.001C421.934 369.013 421.296 369.284 420.824 369.757C420.461 369.285 419.959 369.001 419.111 369.001C418.215 369.001 417.431 369.755 417.431 369.755C417.25 369.529 417.023 369.345 416.765 369.215C416.507 369.085 416.224 369.012 415.935 369.001C415.14 369.001 414.51 369.349 414.126 370.226L412.989 372.897L411.533 369.471Z" fill="#696566"/>
+<path d="M447.533 369.806C447.533 369.623 447.606 369.447 447.736 369.317C447.867 369.187 448.043 369.114 448.227 369.114C448.411 369.114 448.588 369.187 448.718 369.317C448.848 369.447 448.921 369.623 448.921 369.806C448.921 369.898 448.904 369.988 448.869 370.072C448.834 370.157 448.783 370.234 448.718 370.298C448.654 370.363 448.577 370.415 448.493 370.45C448.408 370.485 448.318 370.503 448.226 370.503C448.135 370.504 448.045 370.486 447.961 370.451C447.876 370.417 447.8 370.366 447.736 370.302C447.671 370.237 447.62 370.161 447.585 370.077C447.551 369.993 447.533 369.903 447.533 369.812V369.806ZM448.778 369.812C448.779 369.738 448.765 369.665 448.738 369.596C448.71 369.528 448.669 369.465 448.617 369.413C448.565 369.36 448.502 369.319 448.434 369.29C448.365 369.262 448.292 369.247 448.218 369.248C448.144 369.248 448.07 369.263 448.002 369.291C447.933 369.32 447.871 369.362 447.819 369.415C447.766 369.467 447.725 369.53 447.697 369.598C447.669 369.667 447.655 369.74 447.656 369.815C447.651 369.891 447.662 369.967 447.688 370.039C447.714 370.111 447.755 370.177 447.807 370.233C447.86 370.289 447.923 370.333 447.994 370.363C448.064 370.394 448.14 370.409 448.217 370.409C448.293 370.409 448.369 370.394 448.44 370.363C448.51 370.333 448.574 370.289 448.626 370.233C448.679 370.177 448.719 370.111 448.745 370.039C448.771 369.967 448.783 369.891 448.778 369.815" fill="#696566"/>
+<path d="M447.965 369.527C447.965 369.507 447.973 369.488 447.987 369.474C448.001 369.46 448.02 369.453 448.04 369.453H448.272C448.308 369.45 448.344 369.454 448.378 369.466C448.411 369.478 448.443 369.497 448.469 369.521C448.489 369.541 448.504 369.565 448.514 369.591C448.524 369.618 448.528 369.646 448.527 369.674C448.53 369.718 448.518 369.762 448.494 369.8C448.47 369.837 448.434 369.865 448.392 369.881L448.494 370.005C448.508 370.02 448.516 370.04 448.517 370.061C448.517 370.07 448.515 370.079 448.511 370.087C448.508 370.096 448.502 370.103 448.496 370.11C448.489 370.116 448.482 370.121 448.473 370.124C448.464 370.128 448.455 370.129 448.446 370.129C448.432 370.129 448.418 370.125 448.405 370.119C448.393 370.113 448.382 370.103 448.374 370.092L448.23 369.91H448.112V370.055C448.112 370.064 448.111 370.074 448.107 370.083C448.104 370.092 448.098 370.1 448.092 370.107C448.085 370.114 448.077 370.12 448.068 370.123C448.059 370.127 448.049 370.129 448.04 370.129C448.03 370.129 448.02 370.127 448.011 370.123C448.002 370.12 447.994 370.114 447.987 370.107C447.98 370.1 447.974 370.092 447.971 370.083C447.967 370.074 447.965 370.064 447.965 370.055V369.527ZM448.264 369.779C448.336 369.779 448.376 369.742 448.376 369.684C448.376 369.622 448.334 369.589 448.261 369.589H448.114V369.781H448.264V369.779Z" fill="#696566"/>
+<path d="M534.84 375H535.68V371.885C535.68 370.996 536.197 370.4 537.14 370.4C537.936 370.4 538.355 370.864 538.355 371.797V375H539.195V371.592C539.195 370.356 538.492 369.644 537.379 369.644C536.573 369.644 536.021 369.985 535.758 370.566H535.68V367.646H534.84V375ZM544.165 373.638C543.945 374.102 543.486 374.351 542.807 374.351C541.914 374.351 541.333 373.691 541.289 372.651V372.612H545.073V372.29C545.073 370.654 544.209 369.644 542.788 369.644C541.343 369.644 540.415 370.718 540.415 372.373C540.415 374.038 541.328 375.093 542.788 375.093C543.94 375.093 544.761 374.536 545.005 373.638H544.165ZM542.778 370.386C543.613 370.386 544.17 371.001 544.189 371.934H541.289C541.352 371.001 541.938 370.386 542.778 370.386ZM550.697 371.348C550.55 370.41 549.769 369.644 548.49 369.644C547.015 369.644 546.078 370.708 546.078 372.349C546.078 374.023 547.02 375.093 548.495 375.093C549.759 375.093 550.546 374.38 550.697 373.413H549.847C549.691 374.009 549.198 374.336 548.49 374.336C547.552 374.336 546.947 373.564 546.947 372.349C546.947 371.157 547.543 370.4 548.49 370.4C549.247 370.4 549.711 370.825 549.847 371.348H550.697ZM552.336 368.374V369.736H551.487V370.439H552.336V373.633C552.336 374.639 552.771 375.039 553.855 375.039C554.021 375.039 554.182 375.02 554.348 374.99V374.282C554.192 374.297 554.109 374.302 553.957 374.302C553.411 374.302 553.176 374.038 553.176 373.418V370.439H554.348V369.736H553.176V368.374H552.336ZM557.653 375.093C559.152 375.093 560.079 374.058 560.079 372.368C560.079 370.674 559.152 369.644 557.653 369.644C556.154 369.644 555.226 370.674 555.226 372.368C555.226 374.058 556.154 375.093 557.653 375.093ZM557.653 374.336C556.656 374.336 556.095 373.613 556.095 372.368C556.095 371.118 556.656 370.4 557.653 370.4C558.649 370.4 559.21 371.118 559.21 372.368C559.21 373.613 558.649 374.336 557.653 374.336ZM561.348 375H562.188V371.738C562.188 370.996 562.769 370.459 563.569 370.459C563.735 370.459 564.038 370.488 564.106 370.508V369.668C563.999 369.653 563.823 369.644 563.687 369.644C562.988 369.644 562.383 370.005 562.227 370.518H562.148V369.736H561.348V375ZM569.047 367.993C566.654 367.993 565.013 369.648 565.013 372.065C565.013 374.561 566.61 376.143 569.13 376.143C569.745 376.143 570.336 376.055 570.775 375.903V375.288C570.468 375.43 569.808 375.522 569.139 375.522C567.05 375.522 565.702 374.18 565.702 372.095C565.702 370.063 567.074 368.608 568.983 368.608C570.936 368.608 572.274 369.814 572.274 371.577C572.274 372.778 571.879 373.555 571.263 373.555C570.912 373.555 570.712 373.354 570.712 373.013V370.146H569.974V370.742H569.896C569.706 370.317 569.266 370.054 568.754 370.054C567.753 370.054 567.054 370.884 567.054 372.07C567.054 373.311 567.738 374.146 568.754 374.146C569.325 374.146 569.764 373.867 569.974 373.369H570.053C570.111 373.848 570.555 374.189 571.127 374.189C572.25 374.189 572.963 373.179 572.963 371.587C572.963 369.468 571.356 367.993 569.047 367.993ZM568.876 370.728C569.54 370.728 569.965 371.255 569.965 372.09C569.965 372.925 569.535 373.457 568.866 373.457C568.226 373.457 567.836 372.939 567.836 372.09C567.836 371.235 568.221 370.728 568.876 370.728ZM574.285 375H575.125V371.885C575.125 370.996 575.642 370.4 576.585 370.4C577.38 370.4 577.8 370.864 577.8 371.797V375H578.64V371.592C578.64 370.356 577.937 369.644 576.824 369.644C576.018 369.644 575.466 369.985 575.203 370.566H575.125V367.646H574.285V375ZM581.588 375.093C582.291 375.093 582.868 374.785 583.209 374.224H583.287V375H584.088V371.396C584.088 370.303 583.371 369.644 582.086 369.644C580.963 369.644 580.133 370.2 580.021 371.045H580.871C580.988 370.63 581.427 370.391 582.057 370.391C582.843 370.391 583.248 370.747 583.248 371.396V371.875L581.73 371.968C580.504 372.041 579.811 372.583 579.811 373.525C579.811 374.487 580.568 375.093 581.588 375.093ZM581.745 374.355C581.134 374.355 580.68 374.043 580.68 373.506C580.68 372.979 581.032 372.7 581.832 372.646L583.248 372.554V373.037C583.248 373.789 582.609 374.355 581.745 374.355ZM585.469 371.177C585.469 371.938 585.918 372.363 586.904 372.603L587.808 372.822C588.369 372.959 588.643 373.203 588.643 373.564C588.643 374.048 588.135 374.385 587.427 374.385C586.753 374.385 586.333 374.102 586.192 373.657H585.327C585.42 374.531 586.226 375.093 587.398 375.093C588.594 375.093 589.507 374.443 589.507 373.501C589.507 372.744 589.029 372.314 588.037 372.075L587.227 371.88C586.607 371.729 586.314 371.504 586.314 371.143C586.314 370.674 586.802 370.356 587.427 370.356C588.062 370.356 588.472 370.635 588.584 371.055H589.414C589.302 370.19 588.535 369.644 587.432 369.644C586.314 369.644 585.469 370.303 585.469 371.177ZM590.824 375H591.664V371.885C591.664 370.996 592.182 370.4 593.124 370.4C593.92 370.4 594.34 370.864 594.34 371.797V375H595.18V371.592C595.18 370.356 594.477 369.644 593.363 369.644C592.558 369.644 592.006 369.985 591.742 370.566H591.664V367.646H590.824V375ZM597.102 368.721C597.425 368.721 597.688 368.457 597.688 368.135C597.688 367.812 597.425 367.549 597.102 367.549C596.78 367.549 596.516 367.812 596.516 368.135C596.516 368.457 596.78 368.721 597.102 368.721ZM596.682 375H597.522V369.736H596.682V375ZM603.429 371.348C603.283 370.41 602.502 369.644 601.222 369.644C599.748 369.644 598.81 370.708 598.81 372.349C598.81 374.023 599.753 375.093 601.227 375.093C602.492 375.093 603.278 374.38 603.429 373.413H602.58C602.423 374.009 601.93 374.336 601.222 374.336C600.285 374.336 599.679 373.564 599.679 372.349C599.679 371.157 600.275 370.4 601.222 370.4C601.979 370.4 602.443 370.825 602.58 371.348H603.429ZM606.783 375.093C608.282 375.093 609.209 374.058 609.209 372.368C609.209 370.674 608.282 369.644 606.783 369.644C605.284 369.644 604.356 370.674 604.356 372.368C604.356 374.058 605.284 375.093 606.783 375.093ZM606.783 374.336C605.787 374.336 605.225 373.613 605.225 372.368C605.225 371.118 605.787 370.4 606.783 370.4C607.779 370.4 608.34 371.118 608.34 372.368C608.34 373.613 607.779 374.336 606.783 374.336ZM610.478 375H611.318V371.738C611.318 370.996 611.899 370.459 612.699 370.459C612.865 370.459 613.168 370.488 613.237 370.508V369.668C613.129 369.653 612.953 369.644 612.817 369.644C612.118 369.644 611.513 370.005 611.357 370.518H611.279V369.736H610.478V375ZM616.897 369.644C616.18 369.644 615.55 370.01 615.213 370.615H615.135V369.736H614.334V376.758H615.174V374.209H615.252C615.54 374.766 616.146 375.093 616.897 375.093C618.235 375.093 619.109 374.014 619.109 372.368C619.109 370.713 618.24 369.644 616.897 369.644ZM616.697 374.336C615.75 374.336 615.149 373.574 615.149 372.368C615.149 371.157 615.75 370.4 616.702 370.4C617.664 370.4 618.24 371.138 618.24 372.368C618.24 373.599 617.664 374.336 616.697 374.336ZM620.973 375.049C621.325 375.049 621.608 374.761 621.608 374.414C621.608 374.062 621.325 373.779 620.973 373.779C620.627 373.779 620.339 374.062 620.339 374.414C620.339 374.761 620.627 375.049 620.973 375.049ZM627.359 371.348C627.213 370.41 626.431 369.644 625.152 369.644C623.677 369.644 622.74 370.708 622.74 372.349C622.74 374.023 623.682 375.093 625.157 375.093C626.421 375.093 627.208 374.38 627.359 373.413H626.509C626.353 374.009 625.86 374.336 625.152 374.336C624.214 374.336 623.609 373.564 623.609 372.349C623.609 371.157 624.205 370.4 625.152 370.4C625.909 370.4 626.373 370.825 626.509 371.348H627.359ZM630.712 375.093C632.211 375.093 633.139 374.058 633.139 372.368C633.139 370.674 632.211 369.644 630.712 369.644C629.213 369.644 628.286 370.674 628.286 372.368C628.286 374.058 629.213 375.093 630.712 375.093ZM630.712 374.336C629.716 374.336 629.155 373.613 629.155 372.368C629.155 371.118 629.716 370.4 630.712 370.4C631.708 370.4 632.27 371.118 632.27 372.368C632.27 373.613 631.708 374.336 630.712 374.336ZM634.407 375H635.247V371.738C635.247 370.996 635.779 370.4 636.468 370.4C637.132 370.4 637.567 370.801 637.567 371.426V375H638.406V371.616C638.406 370.947 638.895 370.4 639.627 370.4C640.369 370.4 640.736 370.781 640.736 371.558V375H641.575V371.362C641.575 370.259 640.975 369.644 639.901 369.644C639.173 369.644 638.572 370.01 638.289 370.566H638.211C637.967 370.02 637.469 369.644 636.756 369.644C636.053 369.644 635.526 369.98 635.286 370.566H635.208V369.736H634.407V375Z" fill="#727274"/>
+<path d="M100.791 418H102.002V414.899C102.002 414.118 102.446 413.596 103.242 413.596C103.945 413.596 104.316 414.016 104.316 414.841V418H105.527V414.558C105.527 413.288 104.834 412.565 103.691 412.565C102.896 412.565 102.324 412.927 102.07 413.527H101.982V410.598H100.791V418ZM108.383 418.088C109.081 418.088 109.667 417.785 109.965 417.268H110.048V418H111.215V414.353C111.215 413.225 110.443 412.561 109.071 412.561C107.802 412.561 106.918 413.156 106.82 414.089H107.963C108.075 413.723 108.456 413.522 109.012 413.522C109.667 413.522 110.018 413.82 110.018 414.353V414.812L108.641 414.895C107.343 414.968 106.615 415.529 106.615 416.486C106.615 417.463 107.352 418.088 108.383 418.088ZM108.739 417.155C108.202 417.155 107.816 416.887 107.816 416.428C107.816 415.983 108.134 415.734 108.812 415.69L110.018 415.607V416.042C110.018 416.677 109.471 417.155 108.739 417.155ZM112.503 414.187C112.503 414.987 112.986 415.456 114.011 415.69L114.959 415.91C115.466 416.027 115.696 416.223 115.696 416.525C115.696 416.931 115.271 417.209 114.661 417.209C114.055 417.209 113.679 416.965 113.562 416.569H112.366C112.459 417.531 113.298 418.107 114.631 418.107C115.964 418.107 116.907 417.429 116.907 416.408C116.907 415.622 116.433 415.188 115.413 414.953L114.47 414.743C113.933 414.616 113.679 414.426 113.679 414.123C113.679 413.728 114.094 413.459 114.646 413.459C115.212 413.459 115.569 413.703 115.657 414.079H116.795C116.707 413.117 115.911 412.561 114.641 412.561C113.381 412.561 112.503 413.229 112.503 414.187ZM118.131 418H119.342V414.899C119.342 414.118 119.787 413.596 120.582 413.596C121.286 413.596 121.657 414.016 121.657 414.841V418H122.868V414.558C122.868 413.288 122.174 412.565 121.032 412.565C120.236 412.565 119.664 412.927 119.411 413.527H119.323V410.598H118.131V418ZM124.868 411.77C125.269 411.77 125.596 411.452 125.596 411.052C125.596 410.656 125.269 410.334 124.868 410.334C124.473 410.334 124.146 410.656 124.146 411.052C124.146 411.452 124.473 411.77 124.868 411.77ZM124.268 418H125.474V412.663H124.268V418ZM131.542 414.445C131.415 413.342 130.585 412.561 129.213 412.561C127.606 412.561 126.664 413.591 126.664 415.319C126.664 417.067 127.611 418.107 129.218 418.107C130.57 418.107 131.41 417.355 131.542 416.252H130.39C130.263 416.813 129.843 417.111 129.213 417.111C128.388 417.111 127.89 416.452 127.89 415.319C127.89 414.206 128.383 413.552 129.213 413.552C129.877 413.552 130.277 413.928 130.39 414.445H131.542ZM134.954 418.107C136.551 418.107 137.522 417.062 137.522 415.329C137.522 413.605 136.546 412.561 134.954 412.561C133.367 412.561 132.386 413.61 132.386 415.329C132.386 417.062 133.352 418.107 134.954 418.107ZM134.954 417.116C134.109 417.116 133.626 416.462 133.626 415.334C133.626 414.206 134.109 413.552 134.954 413.552C135.794 413.552 136.277 414.206 136.277 415.334C136.277 416.462 135.799 417.116 134.954 417.116ZM138.693 418H139.904V414.899C139.904 414.147 140.451 413.659 141.237 413.659C141.442 413.659 141.764 413.693 141.857 413.728V412.624C141.745 412.595 141.53 412.575 141.354 412.575C140.666 412.575 140.089 412.966 139.943 413.493H139.86V412.663H138.693V418ZM145.782 412.575C145.049 412.575 144.429 412.941 144.121 413.547H144.038V412.663H142.871V419.772H144.082V417.189H144.165C144.439 417.756 145.03 418.088 145.796 418.088C147.144 418.088 147.984 417.028 147.984 415.334C147.984 413.625 147.134 412.575 145.782 412.575ZM145.401 417.082C144.576 417.082 144.063 416.413 144.058 415.334C144.063 414.255 144.58 413.586 145.406 413.586C146.236 413.586 146.739 414.24 146.739 415.334C146.739 416.428 146.241 417.082 145.401 417.082ZM149.526 419.509L152.055 410.598H150.966L148.432 419.509H149.526ZM157.396 414.445C157.269 413.342 156.438 412.561 155.066 412.561C153.46 412.561 152.518 413.591 152.518 415.319C152.518 417.067 153.465 418.107 155.071 418.107C156.424 418.107 157.264 417.355 157.396 416.252H156.243C156.116 416.813 155.696 417.111 155.066 417.111C154.241 417.111 153.743 416.452 153.743 415.319C153.743 414.206 154.236 413.552 155.066 413.552C155.73 413.552 156.131 413.928 156.243 414.445H157.396ZM160.807 418.107C162.404 418.107 163.376 417.062 163.376 415.329C163.376 413.605 162.399 412.561 160.807 412.561C159.221 412.561 158.239 413.61 158.239 415.329C158.239 417.062 159.206 418.107 160.807 418.107ZM160.807 417.116C159.963 417.116 159.479 416.462 159.479 415.334C159.479 414.206 159.963 413.552 160.807 413.552C161.647 413.552 162.131 414.206 162.131 415.334C162.131 416.462 161.652 417.116 160.807 417.116ZM164.546 418H165.757V414.899C165.757 414.147 166.304 413.659 167.09 413.659C167.296 413.659 167.618 413.693 167.711 413.728V412.624C167.598 412.595 167.383 412.575 167.208 412.575C166.519 412.575 165.943 412.966 165.796 413.493H165.713V412.663H164.546V418ZM172.001 416.54C171.826 416.94 171.411 417.165 170.81 417.165C170.014 417.165 169.501 416.599 169.472 415.695V415.632H173.203V415.246C173.203 413.571 172.289 412.561 170.766 412.561C169.218 412.561 168.256 413.64 168.256 415.354C168.256 417.062 169.204 418.107 170.776 418.107C172.036 418.107 172.929 417.502 173.149 416.54H172.001ZM170.761 413.503C171.489 413.503 171.967 414.016 171.992 414.826H169.477C169.531 414.025 170.038 413.503 170.761 413.503Z" fill="black"/>
+<path d="M100 419.821H173.676V420.627H100V419.821Z" fill="black"/>
+<path d="M258.4 412.663H257.121L255.896 416.813H255.812L254.577 412.663H253.278L255.178 418H256.511L258.4 412.663ZM261.07 418H262.33V410.954H261.075L259.234 412.248V413.435L260.987 412.194H261.07V418ZM267.548 418H268.754V416.647H269.707V415.607H268.754V410.954H266.977C266.02 412.409 265.019 414.03 264.106 415.617V416.647H267.548V418ZM265.273 415.563C265.962 414.367 266.777 413.063 267.5 411.96H267.568V415.637H265.273V415.563ZM270.892 413.039H272.074C272.074 412.297 272.562 411.789 273.329 411.789C274.066 411.789 274.505 412.282 274.505 412.922C274.505 413.459 274.29 413.796 273.402 414.694L270.96 417.15V418H275.853V416.955H272.669V416.872L274.183 415.383C275.394 414.196 275.75 413.625 275.75 412.805C275.75 411.633 274.798 410.778 273.397 410.778C271.927 410.778 270.892 411.706 270.892 413.039ZM284.391 414.348C284.244 413.41 283.463 412.644 282.184 412.644C280.709 412.644 279.771 413.708 279.771 415.349C279.771 417.023 280.714 418.093 282.188 418.093C283.453 418.093 284.239 417.38 284.391 416.413H283.541C283.385 417.009 282.892 417.336 282.184 417.336C281.246 417.336 280.641 416.564 280.641 415.349C280.641 414.157 281.236 413.4 282.184 413.4C282.94 413.4 283.404 413.825 283.541 414.348H284.391ZM289.936 414.348C289.79 413.41 289.009 412.644 287.729 412.644C286.255 412.644 285.317 413.708 285.317 415.349C285.317 417.023 286.26 418.093 287.734 418.093C288.999 418.093 289.785 417.38 289.936 416.413H289.087C288.93 417.009 288.437 417.336 287.729 417.336C286.792 417.336 286.186 416.564 286.186 415.349C286.186 414.157 286.782 413.4 287.729 413.4C288.486 413.4 288.95 413.825 289.087 414.348H289.936ZM293.075 418.093C293.802 418.093 294.427 417.746 294.759 417.16H294.838V418H295.638V410.646H294.798V413.566H294.725C294.427 412.99 293.807 412.644 293.075 412.644C291.737 412.644 290.863 413.718 290.863 415.368C290.863 417.023 291.727 418.093 293.075 418.093ZM293.27 413.4C294.222 413.4 294.818 414.162 294.818 415.368C294.818 416.584 294.227 417.336 293.27 417.336C292.308 417.336 291.732 416.599 291.732 415.368C291.732 414.143 292.313 413.4 293.27 413.4ZM299.704 418.161C301.15 418.161 302.175 417.15 302.175 415.734C302.175 414.367 301.204 413.376 299.861 413.376C299.021 413.376 298.332 413.776 297.986 414.46H297.908C297.937 412.546 298.621 411.569 299.792 411.569C300.505 411.569 301.023 411.936 301.169 412.59H302.073C301.892 411.496 301.047 410.788 299.763 410.788C298.098 410.788 297.053 412.175 297.053 414.597C297.053 416.97 298.171 418.161 299.704 418.161ZM299.695 417.39C298.791 417.39 298.103 416.677 298.103 415.734C298.103 414.802 298.772 414.138 299.704 414.138C300.637 414.138 301.287 414.802 301.287 415.764C301.287 416.687 300.598 417.39 299.695 417.39ZM307.902 414.348C307.755 413.41 306.974 412.644 305.695 412.644C304.22 412.644 303.282 413.708 303.282 415.349C303.282 417.023 304.225 418.093 305.699 418.093C306.964 418.093 307.75 417.38 307.902 416.413H307.052C306.896 417.009 306.403 417.336 305.695 417.336C304.757 417.336 304.152 416.564 304.152 415.349C304.152 414.157 304.747 413.4 305.695 413.4C306.451 413.4 306.915 413.825 307.052 414.348H307.902ZM310.557 418.093C311.26 418.093 311.836 417.785 312.178 417.224H312.256V418H313.057V414.396C313.057 413.303 312.339 412.644 311.055 412.644C309.932 412.644 309.102 413.2 308.989 414.045H309.839C309.956 413.63 310.396 413.391 311.025 413.391C311.812 413.391 312.217 413.747 312.217 414.396V414.875L310.698 414.968C309.473 415.041 308.779 415.583 308.779 416.525C308.779 417.487 309.536 418.093 310.557 418.093ZM310.713 417.355C310.103 417.355 309.648 417.043 309.648 416.506C309.648 415.979 310 415.7 310.801 415.646L312.217 415.554V416.037C312.217 416.789 311.577 417.355 310.713 417.355ZM317.045 418.161C318.49 418.161 319.515 417.15 319.515 415.734C319.515 414.367 318.544 413.376 317.201 413.376C316.361 413.376 315.673 413.776 315.326 414.46H315.248C315.277 412.546 315.961 411.569 317.133 411.569C317.846 411.569 318.363 411.936 318.51 412.59H319.413C319.232 411.496 318.388 410.788 317.103 410.788C315.438 410.788 314.393 412.175 314.393 414.597C314.393 416.97 315.512 418.161 317.045 418.161ZM317.035 417.39C316.132 417.39 315.443 416.677 315.443 415.734C315.443 414.802 316.112 414.138 317.045 414.138C317.977 414.138 318.627 414.802 318.627 415.764C318.627 416.687 317.938 417.39 317.035 417.39Z" fill="#727274"/>
+<path d="M415.641 413.352C415.641 413.601 415.668 413.802 415.714 413.95C415.768 414.098 415.835 414.259 415.928 414.434C415.961 414.488 415.975 414.542 415.975 414.589C415.975 414.656 415.935 414.723 415.848 414.79L415.427 415.073C415.367 415.113 415.307 415.133 415.254 415.133C415.187 415.133 415.12 415.099 415.054 415.039C414.96 414.938 414.88 414.831 414.813 414.723C414.746 414.609 414.68 414.481 414.606 414.326C414.086 414.945 413.431 415.254 412.644 415.254C412.083 415.254 411.636 415.093 411.308 414.77C410.981 414.447 410.814 414.017 410.814 413.48C410.814 412.908 411.015 412.445 411.422 412.095C411.829 411.746 412.37 411.571 413.058 411.571C413.284 411.571 413.518 411.591 413.765 411.625C414.012 411.658 414.266 411.712 414.533 411.772V411.282C414.533 410.771 414.426 410.415 414.219 410.206C414.005 409.998 413.645 409.897 413.131 409.897C412.897 409.897 412.657 409.924 412.41 409.985C412.163 410.045 411.923 410.119 411.689 410.213C411.582 410.26 411.502 410.287 411.455 410.301C411.409 410.314 411.375 410.321 411.349 410.321C411.255 410.321 411.208 410.254 411.208 410.112V409.783C411.208 409.675 411.222 409.595 411.255 409.548C411.288 409.501 411.349 409.454 411.442 409.407C411.676 409.286 411.956 409.185 412.283 409.104C412.61 409.017 412.957 408.977 413.325 408.977C414.119 408.977 414.7 409.158 415.074 409.521C415.441 409.884 415.628 410.435 415.628 411.174V413.352H415.641ZM412.931 414.374C413.151 414.374 413.378 414.333 413.618 414.253C413.859 414.172 414.072 414.024 414.252 413.822C414.359 413.695 414.439 413.554 414.479 413.392C414.52 413.231 414.546 413.036 414.546 412.808V412.525C414.353 412.478 414.146 412.438 413.932 412.411C413.718 412.384 413.511 412.371 413.305 412.371C412.857 412.371 412.53 412.458 412.31 412.639C412.09 412.821 411.983 413.076 411.983 413.412C411.983 413.728 412.063 413.964 412.23 414.125C412.39 414.293 412.624 414.374 412.931 414.374ZM418.291 415.099C418.171 415.099 418.091 415.079 418.038 415.032C417.984 414.992 417.938 414.898 417.897 414.77L416.329 409.575C416.289 409.44 416.269 409.353 416.269 409.306C416.269 409.198 416.322 409.138 416.429 409.138H417.083C417.21 409.138 417.297 409.158 417.343 409.205C417.397 409.245 417.437 409.339 417.477 409.467L418.598 413.916L419.64 409.467C419.673 409.333 419.713 409.245 419.767 409.205C419.82 409.165 419.914 409.138 420.034 409.138H420.568C420.695 409.138 420.781 409.158 420.835 409.205C420.888 409.245 420.935 409.339 420.962 409.467L422.016 413.97L423.171 409.467C423.211 409.333 423.258 409.245 423.305 409.205C423.358 409.165 423.445 409.138 423.565 409.138H424.186C424.293 409.138 424.353 409.192 424.353 409.306C424.353 409.339 424.346 409.373 424.34 409.413C424.333 409.454 424.32 409.507 424.293 409.581L422.684 414.777C422.644 414.911 422.597 414.999 422.544 415.039C422.49 415.079 422.404 415.106 422.29 415.106H421.716C421.589 415.106 421.502 415.086 421.449 415.039C421.396 414.992 421.349 414.904 421.322 414.77L420.287 410.435L419.259 414.763C419.226 414.898 419.186 414.985 419.132 415.032C419.079 415.079 418.986 415.099 418.865 415.099H418.291ZM426.87 415.281C426.523 415.281 426.175 415.241 425.842 415.16C425.508 415.079 425.248 414.992 425.074 414.891C424.967 414.831 424.894 414.763 424.867 414.703C424.84 414.642 424.827 414.575 424.827 414.515V414.172C424.827 414.031 424.88 413.964 424.98 413.964C425.021 413.964 425.061 413.97 425.101 413.984C425.141 413.997 425.201 414.024 425.268 414.051C425.495 414.152 425.742 414.232 426.002 414.286C426.269 414.34 426.529 414.367 426.796 414.367C427.217 414.367 427.544 414.293 427.771 414.145C427.998 413.997 428.118 413.782 428.118 413.507C428.118 413.318 428.058 413.164 427.938 413.036C427.818 412.908 427.591 412.794 427.264 412.687L426.296 412.384C425.808 412.23 425.448 412.001 425.227 411.699C425.007 411.403 424.894 411.073 424.894 410.724C424.894 410.442 424.954 410.193 425.074 409.978C425.194 409.763 425.354 409.575 425.555 409.427C425.755 409.272 425.982 409.158 426.249 409.077C426.516 408.997 426.796 408.963 427.09 408.963C427.237 408.963 427.39 408.97 427.537 408.99C427.691 409.01 427.831 409.037 427.971 409.064C428.105 409.097 428.232 409.131 428.352 409.171C428.472 409.212 428.565 409.252 428.632 409.292C428.726 409.346 428.792 409.4 428.832 409.46C428.872 409.514 428.892 409.588 428.892 409.682V409.998C428.892 410.139 428.839 410.213 428.739 410.213C428.686 410.213 428.599 410.186 428.485 410.133C428.105 409.958 427.677 409.87 427.204 409.87C426.823 409.87 426.523 409.931 426.316 410.059C426.109 410.186 426.002 410.381 426.002 410.657C426.002 410.845 426.069 411.006 426.202 411.134C426.336 411.262 426.583 411.389 426.936 411.504L427.884 411.806C428.365 411.961 428.712 412.176 428.919 412.451C429.126 412.727 429.226 413.043 429.226 413.392C429.226 413.681 429.166 413.943 429.053 414.172C428.933 414.4 428.772 414.602 428.565 414.763C428.358 414.931 428.111 415.052 427.824 415.14C427.524 415.234 427.21 415.281 426.87 415.281Z" fill="#252F3E"/>
+<path fill-rule="evenodd" clip-rule="evenodd" d="M428.131 418.547C425.935 420.181 422.744 421.048 420 421.048C416.155 421.048 412.69 419.616 410.073 417.237C409.866 417.049 410.053 416.793 410.3 416.941C413.131 418.594 416.622 419.596 420.234 419.596C422.671 419.596 425.348 419.085 427.811 418.037C428.178 417.869 428.492 418.279 428.131 418.547Z" fill="#FF9900"/>
+<path fill-rule="evenodd" clip-rule="evenodd" d="M429.046 417.499C428.766 417.136 427.19 417.324 426.476 417.411C426.262 417.438 426.229 417.25 426.423 417.109C427.678 416.222 429.741 416.477 429.981 416.773C430.221 417.075 429.914 419.152 428.739 420.147C428.559 420.302 428.385 420.221 428.465 420.019C428.732 419.354 429.327 417.855 429.046 417.499Z" fill="#FF9900"/>
+<path d="M445.731 409.176H440.058V414.759H445.731V409.176Z" fill="#F25022"/>
+<path d="M451.995 409.176H446.321V414.759H451.995V409.176Z" fill="#7FBA00"/>
+<path d="M445.731 415.34H440.058V420.924H445.731V415.34Z" fill="#00A4EF"/>
+<path d="M451.995 415.34H446.321V420.924H451.995V415.34Z" fill="#FFB900"/>
+<path d="M535.24 411.721C535.562 411.721 535.826 411.457 535.826 411.135C535.826 410.812 535.562 410.549 535.24 410.549C534.918 410.549 534.654 410.812 534.654 411.135C534.654 411.457 534.918 411.721 535.24 411.721ZM535.65 412.736H534.811V418.273C534.811 418.854 534.615 419.089 534.02 419.089H533.893V419.807H534.039C535.143 419.807 535.65 419.343 535.65 418.259V412.736ZM538.667 418.093C539.37 418.093 539.946 417.785 540.288 417.224H540.366V418H541.167V414.396C541.167 413.303 540.449 412.644 539.165 412.644C538.042 412.644 537.212 413.2 537.099 414.045H537.949C538.066 413.63 538.506 413.391 539.136 413.391C539.922 413.391 540.327 413.747 540.327 414.396V414.875L538.808 414.968C537.583 415.041 536.889 415.583 536.889 416.525C536.889 417.487 537.646 418.093 538.667 418.093ZM538.823 417.355C538.213 417.355 537.759 417.043 537.759 416.506C537.759 415.979 538.11 415.7 538.911 415.646L540.327 415.554V416.037C540.327 416.789 539.687 417.355 538.823 417.355ZM547.025 414.348C546.879 413.41 546.097 412.644 544.818 412.644C543.343 412.644 542.406 413.708 542.406 415.349C542.406 417.023 543.348 418.093 544.823 418.093C546.088 418.093 546.874 417.38 547.025 416.413H546.175C546.019 417.009 545.526 417.336 544.818 417.336C543.88 417.336 543.275 416.564 543.275 415.349C543.275 414.157 543.871 413.4 544.818 413.4C545.575 413.4 546.039 413.825 546.175 414.348H547.025ZM549.182 415.036H549.104V410.646H548.264V418H549.104V416.003L549.607 415.534L551.579 418H552.649L550.232 414.992L552.497 412.736H551.467L549.182 415.036ZM557.535 410.993C555.143 410.993 553.502 412.648 553.502 415.065C553.502 417.561 555.099 419.143 557.618 419.143C558.234 419.143 558.824 419.055 559.264 418.903V418.288C558.956 418.43 558.297 418.522 557.628 418.522C555.538 418.522 554.191 417.18 554.191 415.095C554.191 413.063 555.563 411.608 557.472 411.608C559.425 411.608 560.763 412.814 560.763 414.577C560.763 415.778 560.367 416.555 559.752 416.555C559.401 416.555 559.2 416.354 559.2 416.013V413.146H558.463V413.742H558.385C558.195 413.317 557.755 413.054 557.242 413.054C556.241 413.054 555.543 413.884 555.543 415.07C555.543 416.311 556.227 417.146 557.242 417.146C557.814 417.146 558.253 416.867 558.463 416.369H558.541C558.6 416.848 559.044 417.189 559.615 417.189C560.738 417.189 561.451 416.179 561.451 414.587C561.451 412.468 559.845 410.993 557.535 410.993ZM557.364 413.728C558.029 413.728 558.453 414.255 558.453 415.09C558.453 415.925 558.024 416.457 557.355 416.457C556.715 416.457 556.324 415.939 556.324 415.09C556.324 414.235 556.71 413.728 557.364 413.728ZM562.773 418H563.613V414.885C563.613 413.996 564.131 413.4 565.073 413.4C565.869 413.4 566.289 413.864 566.289 414.797V418H567.129V414.592C567.129 413.356 566.426 412.644 565.312 412.644C564.507 412.644 563.955 412.985 563.691 413.566H563.613V410.646H562.773V418ZM570.077 418.093C570.78 418.093 571.356 417.785 571.698 417.224H571.776V418H572.577V414.396C572.577 413.303 571.859 412.644 570.575 412.644C569.452 412.644 568.622 413.2 568.51 414.045H569.359C569.476 413.63 569.916 413.391 570.546 413.391C571.332 413.391 571.737 413.747 571.737 414.396V414.875L570.219 414.968C568.993 415.041 568.3 415.583 568.3 416.525C568.3 417.487 569.056 418.093 570.077 418.093ZM570.233 417.355C569.623 417.355 569.169 417.043 569.169 416.506C569.169 415.979 569.52 415.7 570.321 415.646L571.737 415.554V416.037C571.737 416.789 571.097 417.355 570.233 417.355ZM573.958 414.177C573.958 414.938 574.407 415.363 575.393 415.603L576.296 415.822C576.858 415.959 577.131 416.203 577.131 416.564C577.131 417.048 576.624 417.385 575.916 417.385C575.242 417.385 574.822 417.102 574.68 416.657H573.816C573.909 417.531 574.714 418.093 575.886 418.093C577.083 418.093 577.996 417.443 577.996 416.501C577.996 415.744 577.517 415.314 576.526 415.075L575.715 414.88C575.095 414.729 574.802 414.504 574.802 414.143C574.802 413.674 575.291 413.356 575.916 413.356C576.55 413.356 576.961 413.635 577.073 414.055H577.903C577.791 413.19 577.024 412.644 575.921 412.644C574.802 412.644 573.958 413.303 573.958 414.177ZM579.313 418H580.153V414.885C580.153 413.996 580.67 413.4 581.613 413.4C582.409 413.4 582.829 413.864 582.829 414.797V418H583.668V414.592C583.668 413.356 582.965 412.644 581.852 412.644C581.046 412.644 580.495 412.985 580.231 413.566H580.153V410.646H579.313V418ZM585.591 411.721C585.913 411.721 586.177 411.457 586.177 411.135C586.177 410.812 585.913 410.549 585.591 410.549C585.269 410.549 585.005 410.812 585.005 411.135C585.005 411.457 585.269 411.721 585.591 411.721ZM585.171 418H586.011V412.736H585.171V418ZM591.918 414.348C591.771 413.41 590.99 412.644 589.711 412.644C588.236 412.644 587.299 413.708 587.299 415.349C587.299 417.023 588.241 418.093 589.716 418.093C590.98 418.093 591.767 417.38 591.918 416.413H591.068C590.912 417.009 590.419 417.336 589.711 417.336C588.773 417.336 588.168 416.564 588.168 415.349C588.168 414.157 588.764 413.4 589.711 413.4C590.468 413.4 590.932 413.825 591.068 414.348H591.918ZM595.271 418.093C596.77 418.093 597.698 417.058 597.698 415.368C597.698 413.674 596.77 412.644 595.271 412.644C593.772 412.644 592.845 413.674 592.845 415.368C592.845 417.058 593.772 418.093 595.271 418.093ZM595.271 417.336C594.275 417.336 593.714 416.613 593.714 415.368C593.714 414.118 594.275 413.4 595.271 413.4C596.267 413.4 596.829 414.118 596.829 415.368C596.829 416.613 596.267 417.336 595.271 417.336ZM598.966 418H599.806V414.738C599.806 413.996 600.387 413.459 601.188 413.459C601.354 413.459 601.657 413.488 601.725 413.508V412.668C601.618 412.653 601.442 412.644 601.305 412.644C600.607 412.644 600.002 413.005 599.845 413.518H599.767V412.736H598.966V418ZM605.386 412.644C604.668 412.644 604.038 413.01 603.702 413.615H603.623V412.736H602.823V419.758H603.662V417.209H603.741C604.029 417.766 604.634 418.093 605.386 418.093C606.724 418.093 607.598 417.014 607.598 415.368C607.598 413.713 606.729 412.644 605.386 412.644ZM605.186 417.336C604.239 417.336 603.638 416.574 603.638 415.368C603.638 414.157 604.239 413.4 605.191 413.4C606.153 413.4 606.729 414.138 606.729 415.368C606.729 416.599 606.153 417.336 605.186 417.336ZM609.462 418.049C609.814 418.049 610.097 417.761 610.097 417.414C610.097 417.062 609.814 416.779 609.462 416.779C609.115 416.779 608.827 417.062 608.827 417.414C608.827 417.761 609.115 418.049 609.462 418.049ZM615.848 414.348C615.701 413.41 614.92 412.644 613.641 412.644C612.166 412.644 611.229 413.708 611.229 415.349C611.229 417.023 612.171 418.093 613.646 418.093C614.91 418.093 615.696 417.38 615.848 416.413H614.998C614.842 417.009 614.349 417.336 613.641 417.336C612.703 417.336 612.098 416.564 612.098 415.349C612.098 414.157 612.693 413.4 613.641 413.4C614.397 413.4 614.861 413.825 614.998 414.348H615.848ZM619.201 418.093C620.7 418.093 621.628 417.058 621.628 415.368C621.628 413.674 620.7 412.644 619.201 412.644C617.702 412.644 616.774 413.674 616.774 415.368C616.774 417.058 617.702 418.093 619.201 418.093ZM619.201 417.336C618.205 417.336 617.643 416.613 617.643 415.368C617.643 414.118 618.205 413.4 619.201 413.4C620.197 413.4 620.759 414.118 620.759 415.368C620.759 416.613 620.197 417.336 619.201 417.336ZM622.896 418H623.736V414.738C623.736 413.996 624.268 413.4 624.957 413.4C625.621 413.4 626.055 413.801 626.055 414.426V418H626.895V414.616C626.895 413.947 627.383 413.4 628.116 413.4C628.858 413.4 629.224 413.781 629.224 414.558V418H630.064V414.362C630.064 413.259 629.463 412.644 628.389 412.644C627.662 412.644 627.061 413.01 626.778 413.566H626.7C626.456 413.02 625.958 412.644 625.245 412.644C624.542 412.644 624.014 412.98 623.775 413.566H623.697V412.736H622.896V418Z" fill="#727274"/>
+<g filter="url(#filter0_ddddd)">
+<path d="M659 0H187C182.582 0 179 3.58172 179 8V290C179 294.418 182.582 298 187 298H659C663.418 298 667 294.418 667 290V8C667 3.58172 663.418 0 659 0Z" fill="url(#paint2_linear)"/>
+</g>
+<path d="M208.626 82C210.731 82 212.037 80.9131 212.037 79.1768C212.037 77.9053 211.087 76.9277 209.781 76.8252V76.7021C210.793 76.5518 211.565 75.6426 211.565 74.5967C211.565 73.0723 210.424 72.1357 208.51 72.1357H204.196V82H208.626ZM206.261 73.667H207.983C208.968 73.667 209.535 74.1455 209.535 74.9521C209.535 75.7725 208.927 76.2373 207.812 76.2373H206.261V73.667ZM206.261 80.4619V77.5977H208.052C209.269 77.5977 209.932 78.0898 209.932 79.0127C209.932 79.9561 209.289 80.4619 208.1 80.4619H206.261ZM220.457 74.4736H218.468V78.8213C218.468 79.8535 217.935 80.4893 216.944 80.4893C216.028 80.4893 215.556 79.9492 215.556 78.8828V74.4736H213.567V79.375C213.567 81.125 214.578 82.1572 216.205 82.1572C217.347 82.1572 218.051 81.665 218.407 80.79H218.53V82H220.457V74.4736ZM223.395 73.3184C224.01 73.3184 224.516 72.8262 224.516 72.2109C224.516 71.5889 224.01 71.0967 223.395 71.0967C222.78 71.0967 222.267 71.5889 222.267 72.2109C222.267 72.8262 222.78 73.3184 223.395 73.3184ZM222.397 82H224.386V74.4736H222.397V82ZM226.401 82H228.391V71.5957H226.401V82ZM233.092 82.1162C234.138 82.1162 234.992 81.6309 235.396 80.8174H235.519V82H237.447V71.5957H235.457V75.6768H235.341C234.951 74.8428 234.111 74.3506 233.092 74.3506C231.199 74.3506 230.023 75.834 230.023 78.2266C230.023 80.626 231.192 82.1162 233.092 82.1162ZM233.769 75.9639C234.828 75.9639 235.478 76.832 235.478 78.2402C235.478 79.6484 234.835 80.5098 233.769 80.5098C232.702 80.5098 232.067 79.6553 232.067 78.2334C232.067 76.8184 232.709 75.9639 233.769 75.9639ZM239.27 76.668C239.27 77.8232 239.981 78.5137 241.444 78.835L242.811 79.1426C243.474 79.293 243.761 79.5254 243.761 79.9082C243.761 80.4072 243.228 80.749 242.456 80.749C241.663 80.749 241.177 80.4414 241.027 79.9219H239.086C239.222 81.3438 240.425 82.1572 242.415 82.1572C244.39 82.1572 245.737 81.1865 245.737 79.6963C245.737 78.5752 245.081 77.96 243.618 77.6387L242.203 77.3311C241.505 77.1738 241.184 76.9346 241.184 76.5518C241.184 76.0596 241.711 75.7246 242.421 75.7246C243.16 75.7246 243.618 76.0322 243.72 76.5312H245.559C245.45 75.1094 244.322 74.3096 242.408 74.3096C240.528 74.3096 239.27 75.2598 239.27 76.668Z" fill="#1D1E1F"/>
+<path d="M369.129 145V137.954H367.869V145H369.129ZM370.69 145H371.901V141.753C371.901 141.089 372.346 140.586 372.946 140.586C373.542 140.586 373.913 140.947 373.913 141.538V145H375.09V141.665C375.09 141.055 375.505 140.586 376.135 140.586C376.784 140.586 377.111 140.933 377.111 141.626V145H378.317V141.328C378.317 140.22 377.673 139.561 376.603 139.561C375.861 139.561 375.246 139.941 374.982 140.522H374.899C374.675 139.932 374.162 139.561 373.425 139.561C372.717 139.561 372.17 139.922 371.94 140.522H371.857V139.663H370.69V145ZM381.172 145.088C381.871 145.088 382.457 144.785 382.754 144.268H382.837V145H384.004V141.353C384.004 140.225 383.233 139.561 381.861 139.561C380.591 139.561 379.708 140.156 379.61 141.089H380.753C380.865 140.723 381.246 140.522 381.802 140.522C382.457 140.522 382.808 140.82 382.808 141.353V141.812L381.431 141.895C380.132 141.968 379.405 142.529 379.405 143.486C379.405 144.463 380.142 145.088 381.172 145.088ZM381.529 144.155C380.992 144.155 380.606 143.887 380.606 143.428C380.606 142.983 380.923 142.734 381.602 142.69L382.808 142.607V143.042C382.808 143.677 382.261 144.155 381.529 144.155ZM387.709 147.031C389.267 147.031 390.253 146.255 390.253 145.029V139.663H389.086V140.518H389.003C388.71 139.937 388.076 139.575 387.348 139.575C385.986 139.575 385.141 140.64 385.141 142.275C385.141 143.877 385.981 144.922 387.329 144.922C388.071 144.922 388.652 144.609 388.959 144.033H389.042V145.049C389.042 145.728 388.559 146.128 387.729 146.128C387.065 146.128 386.635 145.889 386.557 145.513H385.341C385.439 146.431 386.337 147.031 387.709 147.031ZM387.709 143.96C386.865 143.96 386.386 143.306 386.386 142.271C386.386 141.24 386.865 140.586 387.709 140.586C388.549 140.586 389.062 141.24 389.062 142.275C389.062 143.306 388.554 143.96 387.709 143.96ZM395.174 143.54C394.998 143.94 394.583 144.165 393.983 144.165C393.187 144.165 392.674 143.599 392.645 142.695V142.632H396.375V142.246C396.375 140.571 395.462 139.561 393.939 139.561C392.391 139.561 391.429 140.64 391.429 142.354C391.429 144.062 392.376 145.107 393.948 145.107C395.208 145.107 396.102 144.502 396.321 143.54H395.174ZM393.934 140.503C394.661 140.503 395.14 141.016 395.164 141.826H392.65C392.703 141.025 393.211 140.503 393.934 140.503ZM401.544 145V137.954H400.284V145H401.544ZM403.232 137.954V145H405.874C407.983 145 409.189 143.706 409.189 141.445C409.189 139.233 407.968 137.954 405.874 137.954H403.232ZM404.492 139.014H405.708C407.089 139.014 407.905 139.912 407.905 141.465C407.905 143.052 407.109 143.94 405.708 143.94H404.492V139.014ZM417.516 145.093C418.219 145.093 418.795 144.785 419.137 144.224H419.215V145H420.016V141.396C420.016 140.303 419.298 139.644 418.014 139.644C416.891 139.644 416.061 140.2 415.948 141.045H416.798C416.915 140.63 417.354 140.391 417.984 140.391C418.771 140.391 419.176 140.747 419.176 141.396V141.875L417.657 141.968C416.432 142.041 415.738 142.583 415.738 143.525C415.738 144.487 416.495 145.093 417.516 145.093ZM417.672 144.355C417.062 144.355 416.607 144.043 416.607 143.506C416.607 142.979 416.959 142.7 417.76 142.646L419.176 142.554V143.037C419.176 143.789 418.536 144.355 417.672 144.355ZM427.895 139.736H427.051L426.015 143.945H425.937L424.761 139.736H423.955L422.778 143.945H422.7L421.665 139.736H420.815L422.29 145H423.139L424.311 140.928H424.389L425.566 145H426.421L427.895 139.736ZM428.7 141.177C428.7 141.938 429.149 142.363 430.135 142.603L431.039 142.822C431.6 142.959 431.874 143.203 431.874 143.564C431.874 144.048 431.366 144.385 430.658 144.385C429.984 144.385 429.564 144.102 429.422 143.657H428.558C428.651 144.531 429.457 145.093 430.629 145.093C431.825 145.093 432.738 144.443 432.738 143.501C432.738 142.744 432.259 142.314 431.268 142.075L430.458 141.88C429.838 141.729 429.545 141.504 429.545 141.143C429.545 140.674 430.033 140.356 430.658 140.356C431.293 140.356 431.703 140.635 431.815 141.055H432.645C432.533 140.19 431.766 139.644 430.663 139.644C429.545 139.644 428.7 140.303 428.7 141.177ZM437.175 142.563V141.768H433.972V142.563H437.175ZM440.138 145.093C440.841 145.093 441.417 144.785 441.759 144.224H441.837V145H442.638V141.396C442.638 140.303 441.92 139.644 440.636 139.644C439.513 139.644 438.683 140.2 438.571 141.045H439.42C439.537 140.63 439.977 140.391 440.607 140.391C441.393 140.391 441.798 140.747 441.798 141.396V141.875L440.279 141.968C439.054 142.041 438.361 142.583 438.361 143.525C438.361 144.487 439.117 145.093 440.138 145.093ZM440.294 144.355C439.684 144.355 439.23 144.043 439.23 143.506C439.23 142.979 439.581 142.7 440.382 142.646L441.798 142.554V143.037C441.798 143.789 441.158 144.355 440.294 144.355ZM445.615 141.753H446.489C447.48 141.753 448.091 142.261 448.091 143.076C448.091 143.867 447.432 144.399 446.504 144.399C445.596 144.399 444.961 143.926 444.883 143.184H444.033C444.097 144.38 445.083 145.166 446.514 145.166C447.915 145.166 448.994 144.282 448.994 143.101C448.994 142.119 448.389 141.499 447.476 141.353V141.274C448.198 141.064 448.726 140.503 448.73 139.653C448.735 138.667 447.935 137.788 446.543 137.788C445.117 137.788 444.243 138.633 444.155 139.78H445.01C445.083 138.989 445.635 138.555 446.484 138.555C447.334 138.555 447.837 139.092 447.837 139.751C447.837 140.483 447.261 141.001 446.45 141.001H445.615V141.753ZM453.573 145H454.432V143.54H455.433V142.754H454.432V137.954H453.158C452.172 139.424 451.093 141.143 450.14 142.739V143.54H453.573V145ZM451.039 142.7C451.805 141.406 452.728 139.951 453.519 138.77H453.578V142.759H451.039V142.7ZM459.085 145.166C460.525 145.166 461.506 144.17 461.506 142.72C461.506 141.323 460.53 140.396 459.348 140.396C458.645 140.396 458.123 140.61 457.781 141.035H457.703L457.922 138.74H461.145V137.954H457.234L456.829 141.982H457.654C457.932 141.46 458.46 141.152 459.129 141.152C460.017 141.152 460.628 141.792 460.628 142.744C460.628 143.73 460.017 144.395 459.094 144.395C458.264 144.395 457.659 143.892 457.581 143.14H456.716C456.795 144.346 457.752 145.166 459.085 145.166ZM464.352 145.093C465.055 145.093 465.631 144.785 465.973 144.224H466.051V145H466.852V141.396C466.852 140.303 466.134 139.644 464.85 139.644C463.727 139.644 462.897 140.2 462.785 141.045H463.634C463.751 140.63 464.191 140.391 464.821 140.391C465.607 140.391 466.012 140.747 466.012 141.396V141.875L464.494 141.968C463.268 142.041 462.575 142.583 462.575 143.525C462.575 144.487 463.331 145.093 464.352 145.093ZM464.508 144.355C463.898 144.355 463.444 144.043 463.444 143.506C463.444 142.979 463.795 142.7 464.596 142.646L466.012 142.554V143.037C466.012 143.789 465.372 144.355 464.508 144.355ZM470.523 147.021C471.958 147.021 472.866 146.27 472.866 145.093V139.736H472.066V140.571H471.988C471.685 140.005 471.035 139.644 470.298 139.644C468.946 139.644 468.091 140.713 468.091 142.29C468.091 143.867 468.936 144.922 470.298 144.922C471.021 144.922 471.616 144.595 471.948 144.014H472.027V145.049C472.027 145.825 471.465 146.289 470.523 146.289C469.766 146.289 469.297 146.011 469.204 145.581H468.316C468.443 146.45 469.253 147.021 470.523 147.021ZM470.484 144.18C469.507 144.18 468.96 143.438 468.96 142.29C468.96 141.143 469.507 140.4 470.484 140.4C471.455 140.4 472.046 141.143 472.046 142.29C472.046 143.438 471.46 144.18 470.484 144.18ZM474.447 145H475.287V141.885C475.287 140.996 475.805 140.4 476.747 140.4C477.543 140.4 477.963 140.864 477.963 141.797V145H478.803V141.592C478.803 140.356 478.1 139.644 476.986 139.644C476.181 139.644 475.629 139.985 475.365 140.566H475.287V137.646H474.447V145ZM481.761 141.753H482.635C483.626 141.753 484.236 142.261 484.236 143.076C484.236 143.867 483.577 144.399 482.649 144.399C481.741 144.399 481.106 143.926 481.028 143.184H480.179C480.242 144.38 481.228 145.166 482.659 145.166C484.06 145.166 485.139 144.282 485.139 143.101C485.139 142.119 484.534 141.499 483.621 141.353V141.274C484.344 141.064 484.871 140.503 484.876 139.653C484.881 138.667 484.08 137.788 482.688 137.788C481.262 137.788 480.388 138.633 480.301 139.78H481.155C481.228 138.989 481.78 138.555 482.63 138.555C483.479 138.555 483.982 139.092 483.982 139.751C483.982 140.483 483.406 141.001 482.596 141.001H481.761V141.753ZM488.185 145H489.064V137.954H488.19L486.315 139.302V140.229L488.107 138.931H488.185V145Z" fill="#727274"/>
+<path d="M560.809 145.176C562.435 145.176 563.626 144.214 563.792 142.788H562.552C562.381 143.579 561.702 144.082 560.809 144.082C559.607 144.082 558.86 143.081 558.86 141.475C558.86 139.873 559.607 138.872 560.804 138.872C561.692 138.872 562.371 139.424 562.547 140.273H563.787C563.641 138.813 562.405 137.778 560.804 137.778C558.807 137.778 557.571 139.189 557.571 141.479C557.571 143.76 558.812 145.176 560.809 145.176ZM565.016 145H566.227V141.899C566.227 141.147 566.774 140.659 567.56 140.659C567.765 140.659 568.088 140.693 568.18 140.728V139.624C568.068 139.595 567.853 139.575 567.678 139.575C566.989 139.575 566.413 139.966 566.266 140.493H566.183V139.663H565.016V145ZM572.471 143.54C572.296 143.94 571.88 144.165 571.28 144.165C570.484 144.165 569.971 143.599 569.942 142.695V142.632H573.672V142.246C573.672 140.571 572.759 139.561 571.236 139.561C569.688 139.561 568.726 140.64 568.726 142.354C568.726 144.062 569.673 145.107 571.246 145.107C572.505 145.107 573.399 144.502 573.619 143.54H572.471ZM571.231 140.503C571.959 140.503 572.437 141.016 572.462 141.826H569.947C570.001 141.025 570.508 140.503 571.231 140.503ZM576.308 145.088C577.006 145.088 577.592 144.785 577.89 144.268H577.973V145H579.14V141.353C579.14 140.225 578.369 139.561 576.996 139.561C575.727 139.561 574.843 140.156 574.746 141.089H575.888C576 140.723 576.381 140.522 576.938 140.522C577.592 140.522 577.944 140.82 577.944 141.353V141.812L576.567 141.895C575.268 141.968 574.54 142.529 574.54 143.486C574.54 144.463 575.278 145.088 576.308 145.088ZM576.664 144.155C576.127 144.155 575.742 143.887 575.742 143.428C575.742 142.983 576.059 142.734 576.738 142.69L577.944 142.607V143.042C577.944 143.677 577.397 144.155 576.664 144.155ZM580.936 138.354V139.697H580.091V140.64H580.936V143.584C580.936 144.614 581.424 145.024 582.65 145.024C582.884 145.024 583.109 145.005 583.284 144.971V144.043C583.138 144.058 583.045 144.067 582.874 144.067C582.366 144.067 582.142 143.828 582.142 143.296V140.64H583.284V139.697H582.142V138.354H580.936ZM587.878 143.54C587.702 143.94 587.287 144.165 586.687 144.165C585.891 144.165 585.378 143.599 585.349 142.695V142.632H589.079V142.246C589.079 140.571 588.166 139.561 586.643 139.561C585.095 139.561 584.133 140.64 584.133 142.354C584.133 144.062 585.08 145.107 586.652 145.107C587.912 145.107 588.806 144.502 589.025 143.54H587.878ZM586.638 140.503C587.365 140.503 587.844 141.016 587.868 141.826H585.354C585.407 141.025 585.915 140.503 586.638 140.503ZM592.179 145.088C592.921 145.088 593.536 144.741 593.839 144.155H593.922V145H595.094V137.598H593.883V140.513H593.8C593.516 139.927 592.911 139.575 592.179 139.575C590.831 139.575 589.981 140.64 589.981 142.329C589.981 144.023 590.826 145.088 592.179 145.088ZM592.554 140.586C593.385 140.586 593.897 141.255 593.897 142.334C593.897 143.418 593.389 144.082 592.554 144.082C591.724 144.082 591.221 143.428 591.221 142.334C591.221 141.245 591.729 140.586 592.554 140.586ZM604.411 145.161C606.135 145.161 607.121 143.774 607.121 141.353C607.121 138.955 605.988 137.788 604.47 137.788C603.025 137.788 601.999 138.799 601.999 140.215C601.999 141.582 602.971 142.573 604.314 142.573C605.154 142.573 605.842 142.173 606.189 141.489H606.267C606.218 143.364 605.569 144.38 604.421 144.38C603.728 144.38 603.191 143.994 603.005 143.359H602.102C602.321 144.468 603.215 145.161 604.411 145.161ZM604.47 141.812C603.537 141.812 602.888 141.147 602.888 140.186C602.888 139.263 603.576 138.56 604.48 138.56C605.383 138.56 606.071 139.272 606.071 140.215C606.071 141.147 605.403 141.812 604.47 141.812ZM608.453 146.499L610.992 137.646H610.279L607.74 146.499H608.453ZM613.452 145H614.331V137.954H613.457L611.582 139.302V140.229L613.374 138.931H613.452V145ZM616.678 145H617.601L620.736 138.77V137.954H616.073V138.74H619.842V138.809L616.678 145ZM621.711 146.499L624.25 137.646H623.537L620.998 146.499H621.711ZM624.982 139.941H625.831C625.831 139.106 626.393 138.555 627.238 138.555C628.068 138.555 628.571 139.111 628.571 139.858C628.571 140.479 628.307 140.845 627.408 141.816L625.026 144.395V145H629.586V144.209H626.246V144.131L627.848 142.476C629.117 141.162 629.469 140.576 629.469 139.766C629.469 138.623 628.527 137.788 627.296 137.788C625.948 137.788 624.982 138.687 624.982 139.941ZM632.705 145H633.584V137.954H632.71L630.835 139.302V140.229L632.627 138.931H632.705V145Z" fill="#727274"/>
+<path d="M260.391 139.663H259.18V142.773C259.18 143.579 258.75 144.067 257.964 144.067C257.241 144.067 256.904 143.667 256.904 142.837V139.663H255.693V143.13C255.693 144.38 256.377 145.107 257.544 145.107C258.359 145.107 258.882 144.761 259.141 144.15H259.224V145H260.391V139.663ZM261.703 141.187C261.703 141.987 262.186 142.456 263.212 142.69L264.159 142.91C264.667 143.027 264.896 143.223 264.896 143.525C264.896 143.931 264.471 144.209 263.861 144.209C263.256 144.209 262.88 143.965 262.762 143.569H261.566C261.659 144.531 262.499 145.107 263.832 145.107C265.165 145.107 266.107 144.429 266.107 143.408C266.107 142.622 265.634 142.188 264.613 141.953L263.671 141.743C263.134 141.616 262.88 141.426 262.88 141.123C262.88 140.728 263.295 140.459 263.846 140.459C264.413 140.459 264.769 140.703 264.857 141.079H265.995C265.907 140.117 265.111 139.561 263.842 139.561C262.582 139.561 261.703 140.229 261.703 141.187ZM270.545 142.715V141.606H267.337V142.715H270.545ZM275.519 143.54C275.343 143.94 274.928 144.165 274.328 144.165C273.532 144.165 273.019 143.599 272.99 142.695V142.632H276.72V142.246C276.72 140.571 275.807 139.561 274.284 139.561C272.736 139.561 271.774 140.64 271.774 142.354C271.774 144.062 272.721 145.107 274.293 145.107C275.553 145.107 276.447 144.502 276.666 143.54H275.519ZM274.279 140.503C275.006 140.503 275.485 141.016 275.509 141.826H272.995C273.048 141.025 273.556 140.503 274.279 140.503ZM279.356 145.088C280.054 145.088 280.64 144.785 280.938 144.268H281.021V145H282.188V141.353C282.188 140.225 281.416 139.561 280.044 139.561C278.775 139.561 277.891 140.156 277.793 141.089H278.936C279.048 140.723 279.429 140.522 279.986 140.522C280.64 140.522 280.991 140.82 280.991 141.353V141.812L279.614 141.895C278.316 141.968 277.588 142.529 277.588 143.486C277.588 144.463 278.325 145.088 279.356 145.088ZM279.712 144.155C279.175 144.155 278.789 143.887 278.789 143.428C278.789 142.983 279.107 142.734 279.785 142.69L280.991 142.607V143.042C280.991 143.677 280.445 144.155 279.712 144.155ZM283.476 141.187C283.476 141.987 283.959 142.456 284.984 142.69L285.932 142.91C286.439 143.027 286.669 143.223 286.669 143.525C286.669 143.931 286.244 144.209 285.634 144.209C285.028 144.209 284.652 143.965 284.535 143.569H283.339C283.432 144.531 284.271 145.107 285.604 145.107C286.938 145.107 287.88 144.429 287.88 143.408C287.88 142.622 287.406 142.188 286.386 141.953L285.443 141.743C284.906 141.616 284.652 141.426 284.652 141.123C284.652 140.728 285.067 140.459 285.619 140.459C286.186 140.459 286.542 140.703 286.63 141.079H287.768C287.68 140.117 286.884 139.561 285.614 139.561C284.354 139.561 283.476 140.229 283.476 141.187ZM289.402 138.354V139.697H288.557V140.64H289.402V143.584C289.402 144.614 289.89 145.024 291.116 145.024C291.35 145.024 291.575 145.005 291.751 144.971V144.043C291.604 144.058 291.512 144.067 291.341 144.067C290.833 144.067 290.608 143.828 290.608 143.296V140.64H291.751V139.697H290.608V138.354H289.402ZM296.037 142.715V141.606H292.829V142.715H296.037ZM297.456 140.039H298.638C298.638 139.297 299.126 138.789 299.893 138.789C300.63 138.789 301.07 139.282 301.07 139.922C301.07 140.459 300.855 140.796 299.966 141.694L297.525 144.15V145H302.417V143.955H299.234V143.872L300.747 142.383C301.958 141.196 302.315 140.625 302.315 139.805C302.315 138.633 301.363 137.778 299.961 137.778C298.492 137.778 297.456 138.706 297.456 140.039Z" fill="#727274"/>
+<path d="M214.594 119.803C214.594 120.134 214.63 120.403 214.693 120.6C214.765 120.797 214.855 121.012 214.98 121.245C215.025 121.317 215.043 121.389 215.043 121.451C215.043 121.541 214.989 121.631 214.873 121.72L214.306 122.097C214.226 122.15 214.145 122.177 214.073 122.177C213.983 122.177 213.893 122.133 213.803 122.052C213.677 121.917 213.57 121.774 213.48 121.631C213.39 121.478 213.3 121.308 213.201 121.102C212.5 121.926 211.619 122.339 210.559 122.339C209.804 122.339 209.202 122.124 208.762 121.693C208.321 121.263 208.097 120.69 208.097 119.973C208.097 119.211 208.366 118.593 208.914 118.127C209.463 117.661 210.191 117.428 211.116 117.428C211.422 117.428 211.736 117.455 212.069 117.499C212.401 117.544 212.743 117.616 213.102 117.697V117.042C213.102 116.361 212.958 115.886 212.68 115.609C212.392 115.331 211.907 115.196 211.215 115.196C210.901 115.196 210.577 115.232 210.244 115.313C209.912 115.394 209.588 115.492 209.274 115.618C209.13 115.68 209.022 115.716 208.959 115.734C208.896 115.752 208.852 115.761 208.816 115.761C208.69 115.761 208.627 115.671 208.627 115.483V115.044C208.627 114.901 208.645 114.793 208.69 114.73C208.735 114.668 208.816 114.605 208.941 114.542C209.256 114.381 209.633 114.246 210.074 114.139C210.514 114.022 210.981 113.969 211.476 113.969C212.545 113.969 213.327 114.211 213.83 114.695C214.324 115.178 214.576 115.913 214.576 116.899V119.803H214.594ZM210.945 121.165C211.242 121.165 211.548 121.111 211.871 121.003C212.195 120.896 212.482 120.699 212.725 120.43C212.869 120.26 212.976 120.071 213.03 119.856C213.084 119.641 213.12 119.381 213.12 119.077V118.7C212.86 118.638 212.581 118.584 212.293 118.548C212.006 118.512 211.727 118.494 211.449 118.494C210.847 118.494 210.406 118.611 210.11 118.853C209.813 119.095 209.669 119.435 209.669 119.883C209.669 120.304 209.777 120.618 210.002 120.833C210.218 121.057 210.532 121.165 210.945 121.165ZM218.162 122.133C218 122.133 217.892 122.106 217.82 122.043C217.748 121.989 217.685 121.864 217.632 121.693L215.52 114.766C215.466 114.587 215.439 114.471 215.439 114.408C215.439 114.264 215.511 114.184 215.654 114.184H216.535C216.706 114.184 216.823 114.211 216.886 114.273C216.958 114.327 217.011 114.453 217.065 114.623L218.575 120.555L219.977 114.623C220.022 114.444 220.076 114.327 220.148 114.273C220.22 114.22 220.345 114.184 220.507 114.184H221.226C221.397 114.184 221.514 114.211 221.586 114.273C221.658 114.327 221.72 114.453 221.756 114.623L223.176 120.627L224.731 114.623C224.785 114.444 224.848 114.327 224.911 114.273C224.983 114.22 225.099 114.184 225.261 114.184H226.097C226.241 114.184 226.322 114.255 226.322 114.408C226.322 114.453 226.313 114.497 226.304 114.551C226.295 114.605 226.277 114.677 226.241 114.775L224.075 121.702C224.021 121.882 223.958 121.998 223.886 122.052C223.814 122.106 223.697 122.141 223.545 122.141H222.772C222.601 122.141 222.484 122.115 222.412 122.052C222.341 121.989 222.278 121.873 222.242 121.693L220.849 115.913L219.465 121.684C219.42 121.864 219.366 121.98 219.294 122.043C219.222 122.106 219.096 122.133 218.935 122.133H218.162ZM229.71 122.374C229.242 122.374 228.775 122.321 228.326 122.213C227.876 122.106 227.526 121.989 227.292 121.855C227.148 121.774 227.05 121.684 227.014 121.604C226.978 121.523 226.96 121.434 226.96 121.353V120.896C226.96 120.708 227.032 120.618 227.166 120.618C227.22 120.618 227.274 120.627 227.328 120.645C227.382 120.663 227.463 120.699 227.553 120.735C227.858 120.869 228.191 120.977 228.541 121.048C228.901 121.12 229.251 121.156 229.611 121.156C230.177 121.156 230.617 121.057 230.923 120.86C231.228 120.663 231.39 120.376 231.39 120.009C231.39 119.758 231.309 119.552 231.147 119.381C230.986 119.211 230.68 119.059 230.24 118.915L228.937 118.512C228.281 118.306 227.795 118.001 227.499 117.598C227.202 117.204 227.05 116.765 227.05 116.299C227.05 115.922 227.13 115.591 227.292 115.304C227.454 115.017 227.67 114.766 227.939 114.569C228.209 114.363 228.514 114.211 228.874 114.103C229.233 113.996 229.611 113.951 230.006 113.951C230.204 113.951 230.411 113.96 230.608 113.987C230.815 114.013 231.004 114.049 231.192 114.085C231.372 114.13 231.543 114.175 231.705 114.229C231.866 114.282 231.992 114.336 232.082 114.39C232.208 114.462 232.298 114.533 232.352 114.614C232.406 114.686 232.432 114.784 232.432 114.91V115.331C232.432 115.519 232.361 115.618 232.226 115.618C232.154 115.618 232.037 115.582 231.884 115.51C231.372 115.277 230.797 115.161 230.159 115.161C229.647 115.161 229.242 115.241 228.964 115.411C228.685 115.582 228.541 115.842 228.541 116.209C228.541 116.46 228.631 116.675 228.811 116.845C228.991 117.016 229.323 117.186 229.799 117.338L231.076 117.741C231.723 117.948 232.19 118.234 232.468 118.602C232.747 118.969 232.882 119.39 232.882 119.856C232.882 120.242 232.801 120.591 232.648 120.896C232.486 121.201 232.271 121.469 231.992 121.684C231.714 121.908 231.381 122.07 230.995 122.186C230.59 122.312 230.168 122.374 229.71 122.374Z" fill="#252F3E"/>
+<path fill-rule="evenodd" clip-rule="evenodd" d="M231.408 126.73C228.451 128.907 224.156 130.063 220.462 130.063C215.286 130.063 210.622 128.155 207.099 124.982C206.821 124.731 207.072 124.391 207.405 124.588C211.215 126.793 215.915 128.128 220.777 128.128C224.057 128.128 227.661 127.447 230.977 126.049C231.471 125.825 231.893 126.371 231.408 126.73Z" fill="#FF9900"/>
+<path fill-rule="evenodd" clip-rule="evenodd" d="M232.639 125.332C232.262 124.848 230.141 125.099 229.179 125.215C228.892 125.251 228.847 125 229.107 124.812C230.797 123.629 233.574 123.97 233.897 124.364C234.221 124.767 233.808 127.536 232.226 128.863C231.983 129.069 231.75 128.961 231.857 128.692C232.217 127.805 233.017 125.807 232.639 125.332Z" fill="#FF9900"/>
+<path d="M260.415 122H261.768L259.263 114.954H257.847L255.347 122H256.621L257.227 120.179H259.819L260.415 122ZM258.486 116.277H258.569L259.526 119.207H257.52L258.486 116.277ZM266.425 116.956H266.498L267.933 122H269.115L271.005 114.954H269.701L268.495 120.242H268.427L267.02 114.954H265.902L264.515 120.242H264.442L263.236 114.954H261.923L263.812 122H264.999L266.425 116.956ZM271.902 120.091C271.965 121.365 273.035 122.176 274.651 122.176C276.36 122.176 277.42 121.326 277.42 119.959C277.42 118.89 276.819 118.294 275.388 117.967L274.578 117.781C273.704 117.576 273.347 117.298 273.347 116.814C273.347 116.204 273.884 115.804 274.695 115.804C275.466 115.804 276.013 116.199 276.101 116.829H277.307C277.249 115.623 276.179 114.778 274.7 114.778C273.123 114.778 272.078 115.628 272.078 116.897C272.078 117.942 272.678 118.572 273.958 118.865L274.871 119.075C275.774 119.285 276.16 119.598 276.16 120.11C276.16 120.711 275.559 121.146 274.729 121.146C273.836 121.146 273.211 120.735 273.132 120.091H271.902ZM281.92 119.715V118.606H278.712V119.715H281.92ZM283.34 117.039H284.522C284.522 116.297 285.01 115.789 285.777 115.789C286.514 115.789 286.953 116.282 286.953 116.922C286.953 117.459 286.738 117.796 285.85 118.694L283.408 121.15V122H288.301V120.955H285.117V120.872L286.631 119.383C287.842 118.196 288.198 117.625 288.198 116.805C288.198 115.633 287.246 114.778 285.845 114.778C284.375 114.778 283.34 115.706 283.34 117.039ZM290.468 122.098C290.932 122.098 291.249 121.771 291.249 121.336C291.249 120.906 290.932 120.579 290.468 120.579C290.009 120.579 289.687 120.906 289.687 121.336C289.687 121.771 290.009 122.098 290.468 122.098ZM292.683 118.187C292.683 118.987 293.167 119.456 294.192 119.69L295.139 119.91C295.647 120.027 295.877 120.223 295.877 120.525C295.877 120.931 295.452 121.209 294.842 121.209C294.236 121.209 293.86 120.965 293.743 120.569H292.547C292.639 121.531 293.479 122.107 294.812 122.107C296.145 122.107 297.088 121.429 297.088 120.408C297.088 119.622 296.614 119.188 295.594 118.953L294.651 118.743C294.114 118.616 293.86 118.426 293.86 118.123C293.86 117.728 294.275 117.459 294.827 117.459C295.393 117.459 295.75 117.703 295.838 118.079H296.975C296.888 117.117 296.092 116.561 294.822 116.561C293.562 116.561 292.683 117.229 292.683 118.187ZM300.568 122.107C302.165 122.107 303.136 121.062 303.136 119.329C303.136 117.605 302.16 116.561 300.568 116.561C298.981 116.561 298 117.61 298 119.329C298 121.062 298.966 122.107 300.568 122.107ZM300.568 121.116C299.723 121.116 299.24 120.462 299.24 119.334C299.24 118.206 299.723 117.552 300.568 117.552C301.408 117.552 301.891 118.206 301.891 119.334C301.891 120.462 301.413 121.116 300.568 121.116ZM308.955 116.663H307.745V119.773C307.745 120.579 307.315 121.067 306.529 121.067C305.806 121.067 305.469 120.667 305.469 119.837V116.663H304.258V120.13C304.258 121.38 304.942 122.107 306.109 122.107C306.924 122.107 307.447 121.761 307.705 121.15H307.788V122H308.955V116.663ZM310.776 115.354V116.697H309.931V117.64H310.776V120.584C310.776 121.614 311.264 122.024 312.489 122.024C312.724 122.024 312.948 122.005 313.124 121.971V121.043C312.978 121.058 312.885 121.067 312.714 121.067C312.206 121.067 311.982 120.828 311.982 120.296V117.64H313.124V116.697H311.982V115.354H310.776ZM314.334 122H315.545V118.899C315.545 118.118 315.989 117.596 316.785 117.596C317.488 117.596 317.859 118.016 317.859 118.841V122H319.07V118.558C319.07 117.288 318.377 116.565 317.234 116.565C316.438 116.565 315.867 116.927 315.613 117.527H315.525V114.598H314.334V122Z" fill="black"/>
+<path d="M369.129 205V197.954H367.869V205H369.129ZM370.69 205H371.901V201.753C371.901 201.089 372.346 200.586 372.946 200.586C373.542 200.586 373.913 200.947 373.913 201.538V205H375.09V201.665C375.09 201.055 375.505 200.586 376.135 200.586C376.784 200.586 377.111 200.933 377.111 201.626V205H378.317V201.328C378.317 200.22 377.673 199.561 376.603 199.561C375.861 199.561 375.246 199.941 374.982 200.522H374.899C374.675 199.932 374.162 199.561 373.425 199.561C372.717 199.561 372.17 199.922 371.94 200.522H371.857V199.663H370.69V205ZM381.172 205.088C381.871 205.088 382.457 204.785 382.754 204.268H382.837V205H384.004V201.353C384.004 200.225 383.233 199.561 381.861 199.561C380.591 199.561 379.708 200.156 379.61 201.089H380.753C380.865 200.723 381.246 200.522 381.802 200.522C382.457 200.522 382.808 200.82 382.808 201.353V201.812L381.431 201.895C380.132 201.968 379.405 202.529 379.405 203.486C379.405 204.463 380.142 205.088 381.172 205.088ZM381.529 204.155C380.992 204.155 380.606 203.887 380.606 203.428C380.606 202.983 380.923 202.734 381.602 202.69L382.808 202.607V203.042C382.808 203.677 382.261 204.155 381.529 204.155ZM387.709 207.031C389.267 207.031 390.253 206.255 390.253 205.029V199.663H389.086V200.518H389.003C388.71 199.937 388.076 199.575 387.348 199.575C385.986 199.575 385.141 200.64 385.141 202.275C385.141 203.877 385.981 204.922 387.329 204.922C388.071 204.922 388.652 204.609 388.959 204.033H389.042V205.049C389.042 205.728 388.559 206.128 387.729 206.128C387.065 206.128 386.635 205.889 386.557 205.513H385.341C385.439 206.431 386.337 207.031 387.709 207.031ZM387.709 203.96C386.865 203.96 386.386 203.306 386.386 202.271C386.386 201.24 386.865 200.586 387.709 200.586C388.549 200.586 389.062 201.24 389.062 202.275C389.062 203.306 388.554 203.96 387.709 203.96ZM395.174 203.54C394.998 203.94 394.583 204.165 393.983 204.165C393.187 204.165 392.674 203.599 392.645 202.695V202.632H396.375V202.246C396.375 200.571 395.462 199.561 393.939 199.561C392.391 199.561 391.429 200.64 391.429 202.354C391.429 204.062 392.376 205.107 393.948 205.107C395.208 205.107 396.102 204.502 396.321 203.54H395.174ZM393.934 200.503C394.661 200.503 395.14 201.016 395.164 201.826H392.65C392.703 201.025 393.211 200.503 393.934 200.503ZM401.544 205V197.954H400.284V205H401.544ZM403.232 197.954V205H405.874C407.983 205 409.189 203.706 409.189 201.445C409.189 199.233 407.968 197.954 405.874 197.954H403.232ZM404.492 199.014H405.708C407.089 199.014 407.905 199.912 407.905 201.465C407.905 203.052 407.109 203.94 405.708 203.94H404.492V199.014ZM418.219 207.021C419.654 207.021 420.562 206.27 420.562 205.093V199.736H419.762V200.571H419.684C419.381 200.005 418.731 199.644 417.994 199.644C416.642 199.644 415.787 200.713 415.787 202.29C415.787 203.867 416.632 204.922 417.994 204.922C418.717 204.922 419.312 204.595 419.645 204.014H419.723V205.049C419.723 205.825 419.161 206.289 418.219 206.289C417.462 206.289 416.993 206.011 416.9 205.581H416.012C416.139 206.45 416.949 207.021 418.219 207.021ZM418.18 204.18C417.203 204.18 416.656 203.438 416.656 202.29C416.656 201.143 417.203 200.4 418.18 200.4C419.151 200.4 419.742 201.143 419.742 202.29C419.742 203.438 419.156 204.18 418.18 204.18ZM426.45 201.348C426.304 200.41 425.522 199.644 424.243 199.644C422.768 199.644 421.831 200.708 421.831 202.349C421.831 204.023 422.773 205.093 424.248 205.093C425.513 205.093 426.299 204.38 426.45 203.413H425.6C425.444 204.009 424.951 204.336 424.243 204.336C423.305 204.336 422.7 203.564 422.7 202.349C422.7 201.157 423.296 200.4 424.243 200.4C425 200.4 425.464 200.825 425.6 201.348H426.45ZM430.204 199.644C429.486 199.644 428.856 200.01 428.519 200.615H428.441V199.736H427.64V206.758H428.48V204.209H428.558C428.846 204.766 429.452 205.093 430.204 205.093C431.542 205.093 432.416 204.014 432.416 202.368C432.416 200.713 431.546 199.644 430.204 199.644ZM430.004 204.336C429.056 204.336 428.456 203.574 428.456 202.368C428.456 201.157 429.056 200.4 430.008 200.4C430.97 200.4 431.546 201.138 431.546 202.368C431.546 203.599 430.97 204.336 430.004 204.336ZM436.853 202.563V201.768H433.65V202.563H436.853ZM439.816 205.093C440.519 205.093 441.095 204.785 441.437 204.224H441.515V205H442.316V201.396C442.316 200.303 441.598 199.644 440.314 199.644C439.191 199.644 438.361 200.2 438.248 201.045H439.098C439.215 200.63 439.654 200.391 440.284 200.391C441.071 200.391 441.476 200.747 441.476 201.396V201.875L439.957 201.968C438.732 202.041 438.038 202.583 438.038 203.525C438.038 204.487 438.795 205.093 439.816 205.093ZM439.972 204.355C439.362 204.355 438.907 204.043 438.907 203.506C438.907 202.979 439.259 202.7 440.06 202.646L441.476 202.554V203.037C441.476 203.789 440.836 204.355 439.972 204.355ZM444.17 198.374V199.736H443.32V200.439H444.17V203.633C444.17 204.639 444.604 205.039 445.688 205.039C445.854 205.039 446.016 205.02 446.182 204.99V204.282C446.025 204.297 445.942 204.302 445.791 204.302C445.244 204.302 445.01 204.038 445.01 203.418V200.439H446.182V199.736H445.01V198.374H444.17ZM447.352 199.941H448.202C448.202 199.106 448.763 198.555 449.608 198.555C450.438 198.555 450.941 199.111 450.941 199.858C450.941 200.479 450.678 200.845 449.779 201.816L447.396 204.395V205H451.957V204.209H448.617V204.131L450.219 202.476C451.488 201.162 451.84 200.576 451.84 199.766C451.84 198.623 450.897 197.788 449.667 197.788C448.319 197.788 447.352 198.687 447.352 199.941ZM454.363 202.036H454.285V197.646H453.445V205H454.285V203.003L454.788 202.534L456.76 205H457.83L455.413 201.992L457.678 199.736H456.648L454.363 202.036ZM460.094 205.093C460.797 205.093 461.373 204.785 461.715 204.224H461.793V205H462.594V201.396C462.594 200.303 461.876 199.644 460.592 199.644C459.469 199.644 458.639 200.2 458.527 201.045H459.376C459.494 200.63 459.933 200.391 460.563 200.391C461.349 200.391 461.754 200.747 461.754 201.396V201.875L460.236 201.968C459.01 202.041 458.317 202.583 458.317 203.525C458.317 204.487 459.074 205.093 460.094 205.093ZM460.25 204.355C459.64 204.355 459.186 204.043 459.186 203.506C459.186 202.979 459.537 202.7 460.338 202.646L461.754 202.554V203.037C461.754 203.789 461.115 204.355 460.25 204.355ZM466.045 205.093C466.773 205.093 467.398 204.746 467.73 204.16H467.808V205H468.609V197.646H467.769V200.566H467.696C467.398 199.99 466.778 199.644 466.045 199.644C464.707 199.644 463.833 200.718 463.833 202.368C463.833 204.023 464.697 205.093 466.045 205.093ZM466.24 200.4C467.193 200.4 467.788 201.162 467.788 202.368C467.788 203.584 467.197 204.336 466.24 204.336C465.279 204.336 464.702 203.599 464.702 202.368C464.702 201.143 465.283 200.4 466.24 200.4ZM470.067 201.177C470.067 201.938 470.517 202.363 471.503 202.603L472.406 202.822C472.968 202.959 473.241 203.203 473.241 203.564C473.241 204.048 472.733 204.385 472.025 204.385C471.352 204.385 470.932 204.102 470.79 203.657H469.926C470.019 204.531 470.824 205.093 471.996 205.093C473.192 205.093 474.105 204.443 474.105 203.501C474.105 202.744 473.627 202.314 472.636 202.075L471.825 201.88C471.205 201.729 470.912 201.504 470.912 201.143C470.912 200.674 471.4 200.356 472.025 200.356C472.66 200.356 473.07 200.635 473.183 201.055H474.013C473.9 200.19 473.134 199.644 472.03 199.644C470.912 199.644 470.067 200.303 470.067 201.177ZM477.322 205.093C478.05 205.093 478.675 204.746 479.007 204.16H479.085V205H479.886V197.646H479.046V200.566H478.972C478.675 199.99 478.054 199.644 477.322 199.644C475.984 199.644 475.11 200.718 475.11 202.368C475.11 204.023 475.974 205.093 477.322 205.093ZM477.517 200.4C478.47 200.4 479.065 201.162 479.065 202.368C479.065 203.584 478.474 204.336 477.517 204.336C476.555 204.336 475.979 203.599 475.979 202.368C475.979 201.143 476.56 200.4 477.517 200.4ZM481.418 199.941H482.267C482.267 199.106 482.829 198.555 483.673 198.555C484.504 198.555 485.006 199.111 485.006 199.858C485.006 200.479 484.743 200.845 483.844 201.816L481.462 204.395V205H486.022V204.209H482.682V204.131L484.284 202.476C485.553 201.162 485.905 200.576 485.905 199.766C485.905 198.623 484.963 197.788 483.732 197.788C482.384 197.788 481.418 198.687 481.418 199.941ZM489.707 205.161C491.431 205.161 492.417 203.774 492.417 201.353C492.417 198.955 491.285 197.788 489.766 197.788C488.321 197.788 487.295 198.799 487.295 200.215C487.295 201.582 488.267 202.573 489.61 202.573C490.45 202.573 491.138 202.173 491.485 201.489H491.563C491.514 203.364 490.865 204.38 489.717 204.38C489.024 204.38 488.487 203.994 488.301 203.359H487.398C487.618 204.468 488.511 205.161 489.707 205.161ZM489.766 201.812C488.833 201.812 488.184 201.147 488.184 200.186C488.184 199.263 488.872 198.56 489.776 198.56C490.679 198.56 491.368 199.272 491.368 200.215C491.368 201.147 490.699 201.812 489.766 201.812Z" fill="#727274"/>
+<path d="M560.809 205.176C562.435 205.176 563.626 204.214 563.792 202.788H562.552C562.381 203.579 561.702 204.082 560.809 204.082C559.607 204.082 558.86 203.081 558.86 201.475C558.86 199.873 559.607 198.872 560.804 198.872C561.692 198.872 562.371 199.424 562.547 200.273H563.787C563.641 198.813 562.405 197.778 560.804 197.778C558.807 197.778 557.571 199.189 557.571 201.479C557.571 203.76 558.812 205.176 560.809 205.176ZM565.016 205H566.227V201.899C566.227 201.147 566.774 200.659 567.56 200.659C567.765 200.659 568.088 200.693 568.18 200.728V199.624C568.068 199.595 567.853 199.575 567.678 199.575C566.989 199.575 566.413 199.966 566.266 200.493H566.183V199.663H565.016V205ZM572.471 203.54C572.296 203.94 571.88 204.165 571.28 204.165C570.484 204.165 569.971 203.599 569.942 202.695V202.632H573.672V202.246C573.672 200.571 572.759 199.561 571.236 199.561C569.688 199.561 568.726 200.64 568.726 202.354C568.726 204.062 569.673 205.107 571.246 205.107C572.505 205.107 573.399 204.502 573.619 203.54H572.471ZM571.231 200.503C571.959 200.503 572.437 201.016 572.462 201.826H569.947C570.001 201.025 570.508 200.503 571.231 200.503ZM576.308 205.088C577.006 205.088 577.592 204.785 577.89 204.268H577.973V205H579.14V201.353C579.14 200.225 578.369 199.561 576.996 199.561C575.727 199.561 574.843 200.156 574.746 201.089H575.888C576 200.723 576.381 200.522 576.938 200.522C577.592 200.522 577.944 200.82 577.944 201.353V201.812L576.567 201.895C575.268 201.968 574.54 202.529 574.54 203.486C574.54 204.463 575.278 205.088 576.308 205.088ZM576.664 204.155C576.127 204.155 575.742 203.887 575.742 203.428C575.742 202.983 576.059 202.734 576.738 202.69L577.944 202.607V203.042C577.944 203.677 577.397 204.155 576.664 204.155ZM580.936 198.354V199.697H580.091V200.64H580.936V203.584C580.936 204.614 581.424 205.024 582.65 205.024C582.884 205.024 583.109 205.005 583.284 204.971V204.043C583.138 204.058 583.045 204.067 582.874 204.067C582.366 204.067 582.142 203.828 582.142 203.296V200.64H583.284V199.697H582.142V198.354H580.936ZM587.878 203.54C587.702 203.94 587.287 204.165 586.687 204.165C585.891 204.165 585.378 203.599 585.349 202.695V202.632H589.079V202.246C589.079 200.571 588.166 199.561 586.643 199.561C585.095 199.561 584.133 200.64 584.133 202.354C584.133 204.062 585.08 205.107 586.652 205.107C587.912 205.107 588.806 204.502 589.025 203.54H587.878ZM586.638 200.503C587.365 200.503 587.844 201.016 587.868 201.826H585.354C585.407 201.025 585.915 200.503 586.638 200.503ZM592.179 205.088C592.921 205.088 593.536 204.741 593.839 204.155H593.922V205H595.094V197.598H593.883V200.513H593.8C593.516 199.927 592.911 199.575 592.179 199.575C590.831 199.575 589.981 200.64 589.981 202.329C589.981 204.023 590.826 205.088 592.179 205.088ZM592.554 200.586C593.385 200.586 593.897 201.255 593.897 202.334C593.897 203.418 593.389 204.082 592.554 204.082C591.724 204.082 591.221 203.428 591.221 202.334C591.221 201.245 591.729 200.586 592.554 200.586ZM604.568 205.166C606.062 205.166 607.107 204.321 607.107 203.115C607.107 202.197 606.526 201.484 605.642 201.318V201.24C606.369 201.04 606.819 200.439 606.819 199.668C606.819 198.569 605.886 197.788 604.568 197.788C603.249 197.788 602.317 198.569 602.317 199.668C602.317 200.435 602.776 201.045 603.493 201.24V201.318C602.61 201.484 602.029 202.197 602.029 203.115C602.029 204.321 603.073 205.166 604.568 205.166ZM604.568 200.947C603.737 200.947 603.181 200.469 603.181 199.751C603.181 199.023 603.733 198.54 604.568 198.54C605.403 198.54 605.954 199.023 605.954 199.751C605.954 200.469 605.398 200.947 604.568 200.947ZM604.568 204.414C603.591 204.414 602.917 203.857 602.917 203.052C602.917 202.246 603.591 201.689 604.568 201.689C605.544 201.689 606.218 202.246 606.218 203.052C606.218 203.857 605.544 204.414 604.568 204.414ZM608.463 206.499L611.002 197.646H610.289L607.75 206.499H608.463ZM614.184 205.166C615.679 205.166 616.723 204.321 616.723 203.115C616.723 202.197 616.142 201.484 615.259 201.318V201.24C615.986 201.04 616.435 200.439 616.435 199.668C616.435 198.569 615.503 197.788 614.184 197.788C612.866 197.788 611.933 198.569 611.933 199.668C611.933 200.435 612.392 201.045 613.11 201.24V201.318C612.226 201.484 611.645 202.197 611.645 203.115C611.645 204.321 612.69 205.166 614.184 205.166ZM614.184 200.947C613.354 200.947 612.798 200.469 612.798 199.751C612.798 199.023 613.349 198.54 614.184 198.54C615.019 198.54 615.571 199.023 615.571 199.751C615.571 200.469 615.014 200.947 614.184 200.947ZM614.184 204.414C613.208 204.414 612.534 203.857 612.534 203.052C612.534 202.246 613.208 201.689 614.184 201.689C615.161 201.689 615.835 202.246 615.835 203.052C615.835 203.857 615.161 204.414 614.184 204.414ZM618.08 206.499L620.619 197.646H619.906L617.367 206.499H618.08ZM621.35 199.941H622.2C622.2 199.106 622.761 198.555 623.606 198.555C624.436 198.555 624.939 199.111 624.939 199.858C624.939 200.479 624.675 200.845 623.777 201.816L621.394 204.395V205H625.954V204.209H622.615V204.131L624.216 202.476C625.486 201.162 625.837 200.576 625.837 199.766C625.837 198.623 624.895 197.788 623.664 197.788C622.317 197.788 621.35 198.687 621.35 199.941ZM629.073 205H629.952V197.954H629.078L627.203 199.302V200.229L628.995 198.931H629.073V205Z" fill="#727274"/>
+<path d="M258.037 207.031C259.595 207.031 260.581 206.255 260.581 205.029V199.663H259.414V200.518H259.331C259.038 199.937 258.403 199.575 257.676 199.575C256.313 199.575 255.469 200.64 255.469 202.275C255.469 203.877 256.309 204.922 257.656 204.922C258.398 204.922 258.979 204.609 259.287 204.033H259.37V205.049C259.37 205.728 258.887 206.128 258.057 206.128C257.393 206.128 256.963 205.889 256.885 205.513H255.669C255.767 206.431 256.665 207.031 258.037 207.031ZM258.037 203.96C257.192 203.96 256.714 203.306 256.714 202.271C256.714 201.24 257.192 200.586 258.037 200.586C258.877 200.586 259.39 201.24 259.39 202.275C259.39 203.306 258.882 203.96 258.037 203.96ZM266.635 201.445C266.508 200.342 265.678 199.561 264.305 199.561C262.699 199.561 261.757 200.591 261.757 202.319C261.757 204.067 262.704 205.107 264.31 205.107C265.663 205.107 266.503 204.355 266.635 203.252H265.482C265.355 203.813 264.935 204.111 264.305 204.111C263.48 204.111 262.982 203.452 262.982 202.319C262.982 201.206 263.475 200.552 264.305 200.552C264.97 200.552 265.37 200.928 265.482 201.445H266.635ZM270.652 199.575C269.92 199.575 269.299 199.941 268.992 200.547H268.909V199.663H267.742V206.772H268.953V204.189H269.036C269.309 204.756 269.9 205.088 270.667 205.088C272.014 205.088 272.854 204.028 272.854 202.334C272.854 200.625 272.004 199.575 270.652 199.575ZM270.271 204.082C269.446 204.082 268.933 203.413 268.928 202.334C268.933 201.255 269.451 200.586 270.276 200.586C271.106 200.586 271.609 201.24 271.609 202.334C271.609 203.428 271.111 204.082 270.271 204.082ZM277.282 202.715V201.606H274.074V202.715H277.282ZM282.256 203.54C282.08 203.94 281.665 204.165 281.065 204.165C280.269 204.165 279.756 203.599 279.727 202.695V202.632H283.457V202.246C283.457 200.571 282.544 199.561 281.021 199.561C279.473 199.561 278.511 200.64 278.511 202.354C278.511 204.062 279.458 205.107 281.03 205.107C282.29 205.107 283.184 204.502 283.404 203.54H282.256ZM281.016 200.503C281.743 200.503 282.222 201.016 282.246 201.826H279.732C279.785 201.025 280.293 200.503 281.016 200.503ZM286.093 205.088C286.791 205.088 287.377 204.785 287.675 204.268H287.758V205H288.925V201.353C288.925 200.225 288.153 199.561 286.781 199.561C285.512 199.561 284.628 200.156 284.53 201.089H285.673C285.785 200.723 286.166 200.522 286.723 200.522C287.377 200.522 287.729 200.82 287.729 201.353V201.812L286.352 201.895C285.053 201.968 284.325 202.529 284.325 203.486C284.325 204.463 285.062 205.088 286.093 205.088ZM286.449 204.155C285.912 204.155 285.526 203.887 285.526 203.428C285.526 202.983 285.844 202.734 286.522 202.69L287.729 202.607V203.042C287.729 203.677 287.182 204.155 286.449 204.155ZM290.213 201.187C290.213 201.987 290.696 202.456 291.721 202.69L292.669 202.91C293.177 203.027 293.406 203.223 293.406 203.525C293.406 203.931 292.981 204.209 292.371 204.209C291.765 204.209 291.389 203.965 291.272 203.569H290.076C290.169 204.531 291.009 205.107 292.342 205.107C293.675 205.107 294.617 204.429 294.617 203.408C294.617 202.622 294.143 202.188 293.123 201.953L292.18 201.743C291.643 201.616 291.389 201.426 291.389 201.123C291.389 200.728 291.804 200.459 292.356 200.459C292.923 200.459 293.279 200.703 293.367 201.079H294.505C294.417 200.117 293.621 199.561 292.351 199.561C291.092 199.561 290.213 200.229 290.213 201.187ZM296.139 198.354V199.697H295.295V200.64H296.139V203.584C296.139 204.614 296.628 205.024 297.853 205.024C298.088 205.024 298.312 205.005 298.488 204.971V204.043C298.341 204.058 298.249 204.067 298.078 204.067C297.57 204.067 297.345 203.828 297.345 203.296V200.64H298.488V199.697H297.345V198.354H296.139Z" fill="#727274"/>
+<path d="M214.518 181.243C212.783 181.259 211.096 181.813 209.691 182.828C208.287 183.843 207.236 185.269 206.683 186.906C206.13 188.544 206.104 190.312 206.607 191.965C207.111 193.619 208.119 195.075 209.492 196.131L213.175 192.475C212.684 192.27 212.282 191.9 211.946 191.489C211.61 191.078 211.381 190.591 211.279 190.071C211.176 189.551 211.204 189.015 211.36 188.508C211.515 188.001 211.793 187.541 212.17 187.166C212.547 186.792 213.01 186.516 213.519 186.362C214.028 186.208 214.568 186.182 215.09 186.285C215.612 186.387 216.1 186.616 216.512 186.952C216.924 187.287 217.247 187.718 217.452 188.207L221.165 184.503C220.385 183.485 219.379 182.661 218.226 182.096C217.073 181.53 215.803 181.238 214.518 181.243Z" fill="#FBBC05"/>
+<path d="M228.564 177.063C230.249 178.552 231.502 180.529 232.091 182.694C233.566 183.696 234.679 185.142 235.267 186.821C235.854 188.499 235.886 190.321 235.356 192.018C234.826 193.715 233.763 195.198 232.323 196.249C230.883 197.3 229.143 197.864 227.358 197.857H220.938V192.757H227.358C228.131 192.647 228.838 192.264 229.349 191.677C229.861 191.09 230.143 190.339 230.143 189.561C230.143 188.784 229.861 188.033 229.349 187.446C228.838 186.859 228.131 186.475 227.358 186.366V185.736C227.37 184.772 227.166 183.817 226.759 182.941C226.352 182.065 225.735 181.348 224.989 180.733L228.564 177.063Z" fill="#4285F4"/>
+<path d="M213.169 192.472C213.581 192.659 214.065 192.748 214.517 192.741H220.937V197.857H214.517C212.705 197.863 210.931 197.215 209.482 196.131L213.169 192.472Z" fill="#34A853"/>
+<path d="M228.563 177.06L224.99 180.734C223.723 179.71 222.109 179.207 220.481 179.33C218.853 179.453 217.334 180.193 216.236 181.396C216.234 181.402 216.232 181.408 216.23 181.414C215.668 181.298 215.095 181.241 214.518 181.243C212.832 181.258 211.192 181.782 209.812 182.742C209.81 182.717 209.809 182.691 209.809 182.663C210.321 180.779 211.308 179.057 212.675 177.658C214.042 176.26 215.745 175.232 217.623 174.671C219.501 174.111 221.491 174.036 223.406 174.454C225.319 174.873 227.094 175.77 228.563 177.06Z" fill="#EA4335"/>
+<path d="M258.037 184.031C259.595 184.031 260.581 183.255 260.581 182.029V176.663H259.414V177.518H259.331C259.038 176.937 258.403 176.575 257.676 176.575C256.313 176.575 255.469 177.64 255.469 179.275C255.469 180.877 256.309 181.922 257.656 181.922C258.398 181.922 258.979 181.609 259.287 181.033H259.37V182.049C259.37 182.728 258.887 183.128 258.057 183.128C257.393 183.128 256.963 182.889 256.885 182.513H255.669C255.767 183.431 256.665 184.031 258.037 184.031ZM258.037 180.96C257.192 180.96 256.714 180.306 256.714 179.271C256.714 178.24 257.192 177.586 258.037 177.586C258.877 177.586 259.39 178.24 259.39 179.275C259.39 180.306 258.882 180.96 258.037 180.96ZM266.635 178.445C266.508 177.342 265.678 176.561 264.305 176.561C262.699 176.561 261.757 177.591 261.757 179.319C261.757 181.067 262.704 182.107 264.31 182.107C265.663 182.107 266.503 181.355 266.635 180.252H265.482C265.355 180.813 264.935 181.111 264.305 181.111C263.48 181.111 262.982 180.452 262.982 179.319C262.982 178.206 263.475 177.552 264.305 177.552C264.97 177.552 265.37 177.928 265.482 178.445H266.635ZM270.652 176.575C269.92 176.575 269.299 176.941 268.992 177.547H268.909V176.663H267.742V183.772H268.953V181.189H269.036C269.309 181.756 269.9 182.088 270.667 182.088C272.014 182.088 272.854 181.028 272.854 179.334C272.854 177.625 272.004 176.575 270.652 176.575ZM270.271 181.082C269.446 181.082 268.933 180.413 268.928 179.334C268.933 178.255 269.451 177.586 270.276 177.586C271.106 177.586 271.609 178.24 271.609 179.334C271.609 180.428 271.111 181.082 270.271 181.082ZM277.282 179.715V178.606H274.074V179.715H277.282ZM282.256 180.54C282.08 180.94 281.665 181.165 281.065 181.165C280.269 181.165 279.756 180.599 279.727 179.695V179.632H283.457V179.246C283.457 177.571 282.544 176.561 281.021 176.561C279.473 176.561 278.511 177.64 278.511 179.354C278.511 181.062 279.458 182.107 281.03 182.107C282.29 182.107 283.184 181.502 283.404 180.54H282.256ZM281.016 177.503C281.743 177.503 282.222 178.016 282.246 178.826H279.732C279.785 178.025 280.293 177.503 281.016 177.503ZM286.093 182.088C286.791 182.088 287.377 181.785 287.675 181.268H287.758V182H288.925V178.353C288.925 177.225 288.153 176.561 286.781 176.561C285.512 176.561 284.628 177.156 284.53 178.089H285.673C285.785 177.723 286.166 177.522 286.723 177.522C287.377 177.522 287.729 177.82 287.729 178.353V178.812L286.352 178.895C285.053 178.968 284.325 179.529 284.325 180.486C284.325 181.463 285.062 182.088 286.093 182.088ZM286.449 181.155C285.912 181.155 285.526 180.887 285.526 180.428C285.526 179.983 285.844 179.734 286.522 179.69L287.729 179.607V180.042C287.729 180.677 287.182 181.155 286.449 181.155ZM290.213 178.187C290.213 178.987 290.696 179.456 291.721 179.69L292.669 179.91C293.177 180.027 293.406 180.223 293.406 180.525C293.406 180.931 292.981 181.209 292.371 181.209C291.765 181.209 291.389 180.965 291.272 180.569H290.076C290.169 181.531 291.009 182.107 292.342 182.107C293.675 182.107 294.617 181.429 294.617 180.408C294.617 179.622 294.143 179.188 293.123 178.953L292.18 178.743C291.643 178.616 291.389 178.426 291.389 178.123C291.389 177.728 291.804 177.459 292.356 177.459C292.923 177.459 293.279 177.703 293.367 178.079H294.505C294.417 177.117 293.621 176.561 292.351 176.561C291.092 176.561 290.213 177.229 290.213 178.187ZM296.139 175.354V176.697H295.295V177.64H296.139V180.584C296.139 181.614 296.628 182.024 297.853 182.024C298.088 182.024 298.312 182.005 298.488 181.971V181.043C298.341 181.058 298.249 181.067 298.078 181.067C297.57 181.067 297.345 180.828 297.345 180.296V177.64H298.488V176.697H297.345V175.354H296.139ZM300.552 182.098C301.016 182.098 301.333 181.771 301.333 181.336C301.333 180.906 301.016 180.579 300.552 180.579C300.093 180.579 299.771 180.906 299.771 181.336C299.771 181.771 300.093 182.098 300.552 182.098ZM306.176 180.54C306 180.94 305.585 181.165 304.985 181.165C304.189 181.165 303.676 180.599 303.647 179.695V179.632H307.377V179.246C307.377 177.571 306.464 176.561 304.941 176.561C303.393 176.561 302.431 177.64 302.431 179.354C302.431 181.062 303.378 182.107 304.95 182.107C306.21 182.107 307.104 181.502 307.323 180.54H306.176ZM304.936 177.503C305.663 177.503 306.142 178.016 306.166 178.826H303.652C303.705 178.025 304.213 177.503 304.936 177.503ZM310.403 180.154L311.497 182.01H312.864L311.121 179.31L312.845 176.673H311.512L310.457 178.523H310.374L309.314 176.673H307.908L309.651 179.363L307.923 182.01H309.231L310.32 180.154H310.403ZM315.304 182.088C316.003 182.088 316.589 181.785 316.887 181.268H316.97V182H318.137V178.353C318.137 177.225 317.365 176.561 315.993 176.561C314.723 176.561 313.84 177.156 313.742 178.089H314.885C314.997 177.723 315.378 177.522 315.934 177.522C316.589 177.522 316.94 177.82 316.94 178.353V178.812L315.563 178.895C314.264 178.968 313.537 179.529 313.537 180.486C313.537 181.463 314.274 182.088 315.304 182.088ZM315.661 181.155C315.124 181.155 314.738 180.887 314.738 180.428C314.738 179.983 315.055 179.734 315.734 179.69L316.94 179.607V180.042C316.94 180.677 316.393 181.155 315.661 181.155ZM319.546 182H320.757V178.753C320.757 178.089 321.202 177.586 321.802 177.586C322.398 177.586 322.769 177.947 322.769 178.538V182H323.946V178.665C323.946 178.055 324.361 177.586 324.991 177.586C325.64 177.586 325.967 177.933 325.967 178.626V182H327.173V178.328C327.173 177.22 326.529 176.561 325.46 176.561C324.717 176.561 324.102 176.941 323.838 177.522H323.755C323.531 176.932 323.018 176.561 322.281 176.561C321.573 176.561 321.026 176.922 320.796 177.522H320.713V176.663H319.546V182ZM331.469 176.575C330.737 176.575 330.117 176.941 329.809 177.547H329.726V176.663H328.559V183.772H329.77V181.189H329.853C330.126 181.756 330.717 182.088 331.484 182.088C332.831 182.088 333.671 181.028 333.671 179.334C333.671 177.625 332.822 176.575 331.469 176.575ZM331.088 181.082C330.263 181.082 329.75 180.413 329.746 179.334C329.75 178.255 330.268 177.586 331.093 177.586C331.923 177.586 332.426 178.24 332.426 179.334C332.426 180.428 331.928 181.082 331.088 181.082ZM334.886 182H336.097V174.598H334.886V182ZM341.062 180.54C340.886 180.94 340.471 181.165 339.87 181.165C339.074 181.165 338.562 180.599 338.532 179.695V179.632H342.263V179.246C342.263 177.571 341.35 176.561 339.826 176.561C338.278 176.561 337.316 177.64 337.316 179.354C337.316 181.062 338.264 182.107 339.836 182.107C341.096 182.107 341.989 181.502 342.209 180.54H341.062ZM339.821 177.503C340.549 177.503 341.027 178.016 341.052 178.826H338.537C338.591 178.025 339.099 177.503 339.821 177.503Z" fill="black"/>
+<path d="M369.129 265V257.954H367.869V265H369.129ZM370.69 265H371.901V261.753C371.901 261.089 372.346 260.586 372.946 260.586C373.542 260.586 373.913 260.947 373.913 261.538V265H375.09V261.665C375.09 261.055 375.505 260.586 376.135 260.586C376.784 260.586 377.111 260.933 377.111 261.626V265H378.317V261.328C378.317 260.22 377.673 259.561 376.603 259.561C375.861 259.561 375.246 259.941 374.982 260.522H374.899C374.675 259.932 374.162 259.561 373.425 259.561C372.717 259.561 372.17 259.922 371.94 260.522H371.857V259.663H370.69V265ZM381.172 265.088C381.871 265.088 382.457 264.785 382.754 264.268H382.837V265H384.004V261.353C384.004 260.225 383.233 259.561 381.861 259.561C380.591 259.561 379.708 260.156 379.61 261.089H380.753C380.865 260.723 381.246 260.522 381.802 260.522C382.457 260.522 382.808 260.82 382.808 261.353V261.812L381.431 261.895C380.132 261.968 379.405 262.529 379.405 263.486C379.405 264.463 380.142 265.088 381.172 265.088ZM381.529 264.155C380.992 264.155 380.606 263.887 380.606 263.428C380.606 262.983 380.923 262.734 381.602 262.69L382.808 262.607V263.042C382.808 263.677 382.261 264.155 381.529 264.155ZM387.709 267.031C389.267 267.031 390.253 266.255 390.253 265.029V259.663H389.086V260.518H389.003C388.71 259.937 388.076 259.575 387.348 259.575C385.986 259.575 385.141 260.64 385.141 262.275C385.141 263.877 385.981 264.922 387.329 264.922C388.071 264.922 388.652 264.609 388.959 264.033H389.042V265.049C389.042 265.728 388.559 266.128 387.729 266.128C387.065 266.128 386.635 265.889 386.557 265.513H385.341C385.439 266.431 386.337 267.031 387.709 267.031ZM387.709 263.96C386.865 263.96 386.386 263.306 386.386 262.271C386.386 261.24 386.865 260.586 387.709 260.586C388.549 260.586 389.062 261.24 389.062 262.275C389.062 263.306 388.554 263.96 387.709 263.96ZM395.174 263.54C394.998 263.94 394.583 264.165 393.983 264.165C393.187 264.165 392.674 263.599 392.645 262.695V262.632H396.375V262.246C396.375 260.571 395.462 259.561 393.939 259.561C392.391 259.561 391.429 260.64 391.429 262.354C391.429 264.062 392.376 265.107 393.948 265.107C395.208 265.107 396.102 264.502 396.321 263.54H395.174ZM393.934 260.503C394.661 260.503 395.14 261.016 395.164 261.826H392.65C392.703 261.025 393.211 260.503 393.934 260.503ZM401.544 265V257.954H400.284V265H401.544ZM403.232 257.954V265H405.874C407.983 265 409.189 263.706 409.189 261.445C409.189 259.233 407.968 257.954 405.874 257.954H403.232ZM404.492 259.014H405.708C407.089 259.014 407.905 259.912 407.905 261.465C407.905 263.052 407.109 263.94 405.708 263.94H404.492V259.014ZM417.516 265.093C418.219 265.093 418.795 264.785 419.137 264.224H419.215V265H420.016V261.396C420.016 260.303 419.298 259.644 418.014 259.644C416.891 259.644 416.061 260.2 415.948 261.045H416.798C416.915 260.63 417.354 260.391 417.984 260.391C418.771 260.391 419.176 260.747 419.176 261.396V261.875L417.657 261.968C416.432 262.041 415.738 262.583 415.738 263.525C415.738 264.487 416.495 265.093 417.516 265.093ZM417.672 264.355C417.062 264.355 416.607 264.043 416.607 263.506C416.607 262.979 416.959 262.7 417.76 262.646L419.176 262.554V263.037C419.176 263.789 418.536 264.355 417.672 264.355ZM421.518 265H422.358V261.738C422.358 260.996 422.89 260.4 423.579 260.4C424.243 260.4 424.678 260.801 424.678 261.426V265H425.517V261.616C425.517 260.947 426.006 260.4 426.738 260.4C427.48 260.4 427.846 260.781 427.846 261.558V265H428.686V261.362C428.686 260.259 428.086 259.644 427.012 259.644C426.284 259.644 425.683 260.01 425.4 260.566H425.322C425.078 260.02 424.58 259.644 423.867 259.644C423.164 259.644 422.637 259.98 422.397 260.566H422.319V259.736H421.518V265ZM430.609 258.721C430.931 258.721 431.195 258.457 431.195 258.135C431.195 257.812 430.931 257.549 430.609 257.549C430.287 257.549 430.023 257.812 430.023 258.135C430.023 258.457 430.287 258.721 430.609 258.721ZM430.189 265H431.029V259.736H430.189V265ZM435.749 262.563V261.768H432.546V262.563H435.749ZM439.65 265.166C441.144 265.166 442.189 264.321 442.189 263.115C442.189 262.197 441.608 261.484 440.724 261.318V261.24C441.451 261.04 441.901 260.439 441.901 259.668C441.901 258.569 440.968 257.788 439.65 257.788C438.331 257.788 437.399 258.569 437.399 259.668C437.399 260.435 437.858 261.045 438.575 261.24V261.318C437.692 261.484 437.111 262.197 437.111 263.115C437.111 264.321 438.155 265.166 439.65 265.166ZM439.65 260.947C438.82 260.947 438.263 260.469 438.263 259.751C438.263 259.023 438.815 258.54 439.65 258.54C440.485 258.54 441.036 259.023 441.036 259.751C441.036 260.469 440.48 260.947 439.65 260.947ZM439.65 264.414C438.673 264.414 437.999 263.857 437.999 263.052C437.999 262.246 438.673 261.689 439.65 261.689C440.626 261.689 441.3 262.246 441.3 263.052C441.3 263.857 440.626 264.414 439.65 264.414ZM445.059 261.753H445.933C446.924 261.753 447.534 262.261 447.534 263.076C447.534 263.867 446.875 264.399 445.947 264.399C445.039 264.399 444.404 263.926 444.326 263.184H443.477C443.54 264.38 444.526 265.166 445.957 265.166C447.358 265.166 448.438 264.282 448.438 263.101C448.438 262.119 447.832 261.499 446.919 261.353V261.274C447.642 261.064 448.169 260.503 448.174 259.653C448.179 258.667 447.378 257.788 445.986 257.788C444.561 257.788 443.687 258.633 443.599 259.78H444.453C444.526 258.989 445.078 258.555 445.928 258.555C446.777 258.555 447.28 259.092 447.28 259.751C447.28 260.483 446.704 261.001 445.894 261.001H445.059V261.753ZM449.755 259.941H450.604C450.604 259.106 451.166 258.555 452.011 258.555C452.841 258.555 453.344 259.111 453.344 259.858C453.344 260.479 453.08 260.845 452.181 261.816L449.799 264.395V265H454.359V264.209H451.019V264.131L452.621 262.476C453.89 261.162 454.242 260.576 454.242 259.766C454.242 258.623 453.3 257.788 452.069 257.788C450.721 257.788 449.755 258.687 449.755 259.941ZM456.765 262.036H456.687V257.646H455.847V265H456.687V263.003L457.19 262.534L459.163 265H460.232L457.815 261.992L460.081 259.736H459.05L456.765 262.036ZM461.627 258.721C461.95 258.721 462.213 258.457 462.213 258.135C462.213 257.812 461.95 257.549 461.627 257.549C461.305 257.549 461.041 257.812 461.041 258.135C461.041 258.457 461.305 258.721 461.627 258.721ZM462.037 259.736H461.198V265.273C461.198 265.854 461.002 266.089 460.407 266.089H460.28V266.807H460.426C461.53 266.807 462.037 266.343 462.037 265.259V259.736ZM463.638 265H464.478V261.885C464.478 260.996 464.995 260.4 465.938 260.4C466.734 260.4 467.154 260.864 467.154 261.797V265H467.993V261.592C467.993 260.356 467.29 259.644 466.177 259.644C465.371 259.644 464.82 259.985 464.556 260.566H464.478V257.646H463.638V265ZM471.425 265.093C472.152 265.093 472.777 264.746 473.109 264.16H473.188V265H473.988V257.646H473.148V260.566H473.075C472.777 259.99 472.157 259.644 471.425 259.644C470.087 259.644 469.213 260.718 469.213 262.368C469.213 264.023 470.077 265.093 471.425 265.093ZM471.62 260.4C472.572 260.4 473.168 261.162 473.168 262.368C473.168 263.584 472.577 264.336 471.62 264.336C470.658 264.336 470.082 263.599 470.082 262.368C470.082 261.143 470.663 260.4 471.62 260.4ZM475.52 259.941H476.37C476.37 259.106 476.931 258.555 477.776 258.555C478.606 258.555 479.109 259.111 479.109 259.858C479.109 260.479 478.846 260.845 477.947 261.816L475.564 264.395V265H480.125V264.209H476.785V264.131L478.387 262.476C479.656 261.162 480.008 260.576 480.008 259.766C480.008 258.623 479.065 257.788 477.835 257.788C476.487 257.788 475.52 258.687 475.52 259.941ZM482.531 262.036H482.453V257.646H481.613V265H482.453V263.003L482.956 262.534L484.928 265H485.998L483.581 261.992L485.846 259.736H484.816L482.531 262.036ZM489.063 265.166C490.645 265.166 491.553 263.828 491.553 261.489C491.553 259.155 490.63 257.788 489.063 257.788C487.486 257.788 486.563 259.15 486.563 261.475C486.563 263.818 487.476 265.166 489.063 265.166ZM489.063 264.399C488.023 264.399 487.447 263.359 487.447 261.475C487.447 259.614 488.033 258.56 489.063 258.56C490.093 258.56 490.669 259.604 490.669 261.475C490.669 263.364 490.103 264.399 489.063 264.399Z" fill="#727274"/>
+<path d="M560.809 265.176C562.435 265.176 563.626 264.214 563.792 262.788H562.552C562.381 263.579 561.702 264.082 560.809 264.082C559.607 264.082 558.86 263.081 558.86 261.475C558.86 259.873 559.607 258.872 560.804 258.872C561.692 258.872 562.371 259.424 562.547 260.273H563.787C563.641 258.813 562.405 257.778 560.804 257.778C558.807 257.778 557.571 259.189 557.571 261.479C557.571 263.76 558.812 265.176 560.809 265.176ZM565.016 265H566.227V261.899C566.227 261.147 566.774 260.659 567.56 260.659C567.765 260.659 568.088 260.693 568.18 260.728V259.624C568.068 259.595 567.853 259.575 567.678 259.575C566.989 259.575 566.413 259.966 566.266 260.493H566.183V259.663H565.016V265ZM572.471 263.54C572.296 263.94 571.88 264.165 571.28 264.165C570.484 264.165 569.971 263.599 569.942 262.695V262.632H573.672V262.246C573.672 260.571 572.759 259.561 571.236 259.561C569.688 259.561 568.726 260.64 568.726 262.354C568.726 264.062 569.673 265.107 571.246 265.107C572.505 265.107 573.399 264.502 573.619 263.54H572.471ZM571.231 260.503C571.959 260.503 572.437 261.016 572.462 261.826H569.947C570.001 261.025 570.508 260.503 571.231 260.503ZM576.308 265.088C577.006 265.088 577.592 264.785 577.89 264.268H577.973V265H579.14V261.353C579.14 260.225 578.369 259.561 576.996 259.561C575.727 259.561 574.843 260.156 574.746 261.089H575.888C576 260.723 576.381 260.522 576.938 260.522C577.592 260.522 577.944 260.82 577.944 261.353V261.812L576.567 261.895C575.268 261.968 574.54 262.529 574.54 263.486C574.54 264.463 575.278 265.088 576.308 265.088ZM576.664 264.155C576.127 264.155 575.742 263.887 575.742 263.428C575.742 262.983 576.059 262.734 576.738 262.69L577.944 262.607V263.042C577.944 263.677 577.397 264.155 576.664 264.155ZM580.936 258.354V259.697H580.091V260.64H580.936V263.584C580.936 264.614 581.424 265.024 582.65 265.024C582.884 265.024 583.109 265.005 583.284 264.971V264.043C583.138 264.058 583.045 264.067 582.874 264.067C582.366 264.067 582.142 263.828 582.142 263.296V260.64H583.284V259.697H582.142V258.354H580.936ZM587.878 263.54C587.702 263.94 587.287 264.165 586.687 264.165C585.891 264.165 585.378 263.599 585.349 262.695V262.632H589.079V262.246C589.079 260.571 588.166 259.561 586.643 259.561C585.095 259.561 584.133 260.64 584.133 262.354C584.133 264.062 585.08 265.107 586.652 265.107C587.912 265.107 588.806 264.502 589.025 263.54H587.878ZM586.638 260.503C587.365 260.503 587.844 261.016 587.868 261.826H585.354C585.407 261.025 585.915 260.503 586.638 260.503ZM592.179 265.088C592.921 265.088 593.536 264.741 593.839 264.155H593.922V265H595.094V257.598H593.883V260.513H593.8C593.516 259.927 592.911 259.575 592.179 259.575C590.831 259.575 589.981 260.64 589.981 262.329C589.981 264.023 590.826 265.088 592.179 265.088ZM592.554 260.586C593.385 260.586 593.897 261.255 593.897 262.334C593.897 263.418 593.389 264.082 592.554 264.082C591.724 264.082 591.221 263.428 591.221 262.334C591.221 261.245 591.729 260.586 592.554 260.586ZM604.568 265.166C606.062 265.166 607.107 264.321 607.107 263.115C607.107 262.197 606.526 261.484 605.642 261.318V261.24C606.369 261.04 606.819 260.439 606.819 259.668C606.819 258.569 605.886 257.788 604.568 257.788C603.249 257.788 602.317 258.569 602.317 259.668C602.317 260.435 602.776 261.045 603.493 261.24V261.318C602.61 261.484 602.029 262.197 602.029 263.115C602.029 264.321 603.073 265.166 604.568 265.166ZM604.568 260.947C603.737 260.947 603.181 260.469 603.181 259.751C603.181 259.023 603.733 258.54 604.568 258.54C605.403 258.54 605.954 259.023 605.954 259.751C605.954 260.469 605.398 260.947 604.568 260.947ZM604.568 264.414C603.591 264.414 602.917 263.857 602.917 263.052C602.917 262.246 603.591 261.689 604.568 261.689C605.544 261.689 606.218 262.246 606.218 263.052C606.218 263.857 605.544 264.414 604.568 264.414ZM608.463 266.499L611.002 257.646H610.289L607.75 266.499H608.463ZM611.733 259.941H612.583C612.583 259.106 613.144 258.555 613.989 258.555C614.819 258.555 615.322 259.111 615.322 259.858C615.322 260.479 615.058 260.845 614.16 261.816L611.777 264.395V265H616.338V264.209H612.998V264.131L614.599 262.476C615.869 261.162 616.221 260.576 616.221 259.766C616.221 258.623 615.278 257.788 614.048 257.788C612.7 257.788 611.733 258.687 611.733 259.941ZM617.738 266.499L620.277 257.646H619.564L617.025 266.499H617.738ZM621.008 259.941H621.858C621.858 259.106 622.419 258.555 623.264 258.555C624.094 258.555 624.597 259.111 624.597 259.858C624.597 260.479 624.333 260.845 623.435 261.816L621.052 264.395V265H625.613V264.209H622.273V264.131L623.874 262.476C625.144 261.162 625.496 260.576 625.496 259.766C625.496 258.623 624.553 257.788 623.323 257.788C621.975 257.788 621.008 258.687 621.008 259.941ZM628.732 265H629.611V257.954H628.737L626.862 259.302V260.229L628.654 258.931H628.732V265Z" fill="#727274"/>
+<path d="M260.391 259.663H259.18V262.773C259.18 263.579 258.75 264.067 257.964 264.067C257.241 264.067 256.904 263.667 256.904 262.837V259.663H255.693V263.13C255.693 264.38 256.377 265.107 257.544 265.107C258.359 265.107 258.882 264.761 259.141 264.15H259.224V265H260.391V259.663ZM261.703 261.187C261.703 261.987 262.186 262.456 263.212 262.69L264.159 262.91C264.667 263.027 264.896 263.223 264.896 263.525C264.896 263.931 264.471 264.209 263.861 264.209C263.256 264.209 262.88 263.965 262.762 263.569H261.566C261.659 264.531 262.499 265.107 263.832 265.107C265.165 265.107 266.107 264.429 266.107 263.408C266.107 262.622 265.634 262.188 264.613 261.953L263.671 261.743C263.134 261.616 262.88 261.426 262.88 261.123C262.88 260.728 263.295 260.459 263.846 260.459C264.413 260.459 264.769 260.703 264.857 261.079H265.995C265.907 260.117 265.111 259.561 263.842 259.561C262.582 259.561 261.703 260.229 261.703 261.187ZM270.545 262.715V261.606H267.337V262.715H270.545ZM279.044 259.663H277.838L276.954 263.672H276.871L275.836 259.663H274.679L273.654 263.672H273.571L272.682 259.663H271.461L272.907 265H274.166L275.202 261.133H275.285L276.325 265H277.599L279.044 259.663ZM283.321 263.54C283.145 263.94 282.73 264.165 282.129 264.165C281.333 264.165 280.821 263.599 280.791 262.695V262.632H284.522V262.246C284.522 260.571 283.609 259.561 282.085 259.561C280.537 259.561 279.575 260.64 279.575 262.354C279.575 264.062 280.523 265.107 282.095 265.107C283.355 265.107 284.248 264.502 284.468 263.54H283.321ZM282.08 260.503C282.808 260.503 283.286 261.016 283.311 261.826H280.796C280.85 261.025 281.358 260.503 282.08 260.503ZM285.565 261.187C285.565 261.987 286.049 262.456 287.074 262.69L288.021 262.91C288.529 263.027 288.759 263.223 288.759 263.525C288.759 263.931 288.334 264.209 287.724 264.209C287.118 264.209 286.742 263.965 286.625 263.569H285.429C285.521 264.531 286.361 265.107 287.694 265.107C289.027 265.107 289.97 264.429 289.97 263.408C289.97 262.622 289.496 262.188 288.476 261.953L287.533 261.743C286.996 261.616 286.742 261.426 286.742 261.123C286.742 260.728 287.157 260.459 287.709 260.459C288.275 260.459 288.632 260.703 288.72 261.079H289.857C289.77 260.117 288.974 259.561 287.704 259.561C286.444 259.561 285.565 260.229 285.565 261.187ZM291.492 258.354V259.697H290.647V260.64H291.492V263.584C291.492 264.614 291.98 265.024 293.206 265.024C293.44 265.024 293.665 265.005 293.841 264.971V264.043C293.694 264.058 293.601 264.067 293.43 264.067C292.923 264.067 292.698 263.828 292.698 263.296V260.64H293.841V259.697H292.698V258.354H291.492ZM298.127 262.715V261.606H294.919V262.715H298.127ZM299.546 260.039H300.728C300.728 259.297 301.216 258.789 301.983 258.789C302.72 258.789 303.16 259.282 303.16 259.922C303.16 260.459 302.945 260.796 302.056 261.694L299.615 264.15V265H304.507V263.955H301.324V263.872L302.837 262.383C304.048 261.196 304.405 260.625 304.405 259.805C304.405 258.633 303.453 257.778 302.051 257.778C300.581 257.778 299.546 258.706 299.546 260.039Z" fill="#727274"/>
+<path d="M220.929 233.308H211V243.079H220.929V233.308Z" fill="#F25022"/>
+<path d="M231.891 233.308H221.962V243.079H231.891V233.308Z" fill="#7FBA00"/>
+<path d="M220.929 244.095H211V253.867H220.929V244.095Z" fill="#00A4EF"/>
+<path d="M231.891 244.095H221.962V253.867H231.891V244.095Z" fill="#FFB900"/>
+<path d="M257.212 242.088C257.91 242.088 258.496 241.785 258.794 241.268H258.877V242H260.044V238.353C260.044 237.225 259.272 236.561 257.9 236.561C256.631 236.561 255.747 237.156 255.649 238.089H256.792C256.904 237.723 257.285 237.522 257.842 237.522C258.496 237.522 258.848 237.82 258.848 238.353V238.812L257.471 238.895C256.172 238.968 255.444 239.529 255.444 240.486C255.444 241.463 256.182 242.088 257.212 242.088ZM257.568 241.155C257.031 241.155 256.646 240.887 256.646 240.428C256.646 239.983 256.963 239.734 257.642 239.69L258.848 239.607V240.042C258.848 240.677 258.301 241.155 257.568 241.155ZM261.332 242H265.658V241.048H262.88V240.965L265.614 237.474V236.663H261.356V237.615H264.169V237.703L261.332 241.258V242ZM271.619 236.663H270.408V239.773C270.408 240.579 269.978 241.067 269.192 241.067C268.469 241.067 268.132 240.667 268.132 239.837V236.663H266.921V240.13C266.921 241.38 267.605 242.107 268.772 242.107C269.587 242.107 270.11 241.761 270.369 241.15H270.452V242H271.619V236.663ZM273.053 242H274.264V238.899C274.264 238.147 274.811 237.659 275.597 237.659C275.802 237.659 276.124 237.693 276.217 237.728V236.624C276.105 236.595 275.89 236.575 275.714 236.575C275.026 236.575 274.45 236.966 274.303 237.493H274.22V236.663H273.053V242ZM280.508 240.54C280.332 240.94 279.917 241.165 279.317 241.165C278.521 241.165 278.008 240.599 277.979 239.695V239.632H281.709V239.246C281.709 237.571 280.796 236.561 279.273 236.561C277.725 236.561 276.763 237.64 276.763 239.354C276.763 241.062 277.71 242.107 279.282 242.107C280.542 242.107 281.436 241.502 281.655 240.54H280.508ZM279.268 237.503C279.995 237.503 280.474 238.016 280.498 238.826H277.984C278.037 238.025 278.545 237.503 279.268 237.503ZM283.778 242.098C284.242 242.098 284.56 241.771 284.56 241.336C284.56 240.906 284.242 240.579 283.778 240.579C283.319 240.579 282.997 240.906 282.997 241.336C282.997 241.771 283.319 242.098 283.778 242.098ZM289.085 242.088C290.432 242.088 291.277 241.028 291.277 239.334C291.277 237.63 290.437 236.575 289.085 236.575C288.352 236.575 287.737 236.932 287.459 237.513H287.376V234.598H286.165V242H287.332V241.155H287.415C287.718 241.741 288.338 242.088 289.085 242.088ZM288.704 237.586C289.529 237.586 290.032 238.245 290.032 239.334C290.032 240.423 289.534 241.082 288.704 241.082C287.874 241.082 287.356 240.413 287.356 239.334C287.356 238.255 287.879 237.586 288.704 237.586ZM293.913 242.088C294.611 242.088 295.197 241.785 295.495 241.268H295.578V242H296.745V238.353C296.745 237.225 295.973 236.561 294.601 236.561C293.332 236.561 292.448 237.156 292.35 238.089H293.493C293.605 237.723 293.986 237.522 294.543 237.522C295.197 237.522 295.548 237.82 295.548 238.353V238.812L294.171 238.895C292.873 238.968 292.145 239.529 292.145 240.486C292.145 241.463 292.882 242.088 293.913 242.088ZM294.269 241.155C293.732 241.155 293.346 240.887 293.346 240.428C293.346 239.983 293.664 239.734 294.342 239.69L295.548 239.607V240.042C295.548 240.677 295.002 241.155 294.269 241.155ZM298.033 238.187C298.033 238.987 298.516 239.456 299.541 239.69L300.489 239.91C300.996 240.027 301.226 240.223 301.226 240.525C301.226 240.931 300.801 241.209 300.191 241.209C299.585 241.209 299.209 240.965 299.092 240.569H297.896C297.989 241.531 298.829 242.107 300.162 242.107C301.495 242.107 302.437 241.429 302.437 240.408C302.437 239.622 301.963 239.188 300.943 238.953L300 238.743C299.463 238.616 299.209 238.426 299.209 238.123C299.209 237.728 299.624 237.459 300.176 237.459C300.743 237.459 301.099 237.703 301.187 238.079H302.325C302.237 237.117 301.441 236.561 300.171 236.561C298.912 236.561 298.033 237.229 298.033 238.187ZM304.228 235.77C304.628 235.77 304.955 235.452 304.955 235.052C304.955 234.656 304.628 234.334 304.228 234.334C303.832 234.334 303.505 234.656 303.505 235.052C303.505 235.452 303.832 235.77 304.228 235.77ZM303.627 242H304.833V236.663H303.627V242ZM310.901 238.445C310.774 237.342 309.944 236.561 308.572 236.561C306.966 236.561 306.023 237.591 306.023 239.319C306.023 241.067 306.971 242.107 308.577 242.107C309.93 242.107 310.77 241.355 310.901 240.252H309.749C309.622 240.813 309.202 241.111 308.572 241.111C307.747 241.111 307.249 240.452 307.249 239.319C307.249 238.206 307.742 237.552 308.572 237.552C309.236 237.552 309.637 237.928 309.749 238.445H310.901ZM315.27 239.715V238.606H312.062V239.715H315.27ZM320.245 240.54C320.069 240.94 319.654 241.165 319.053 241.165C318.257 241.165 317.745 240.599 317.715 239.695V239.632H321.446V239.246C321.446 237.571 320.533 236.561 319.009 236.561C317.462 236.561 316.5 237.64 316.5 239.354C316.5 241.062 317.447 242.107 319.019 242.107C320.279 242.107 321.172 241.502 321.392 240.54H320.245ZM319.004 237.503C319.732 237.503 320.211 238.016 320.235 238.826H317.72C317.774 238.025 318.282 237.503 319.004 237.503ZM324.472 240.154L325.566 242.01H326.933L325.19 239.31L326.913 236.673H325.58L324.526 238.523H324.443L323.383 236.673H321.977L323.72 239.363L321.992 242.01H323.3L324.389 240.154H324.472ZM329.373 242.088C330.071 242.088 330.657 241.785 330.955 241.268H331.038V242H332.205V238.353C332.205 237.225 331.434 236.561 330.062 236.561C328.792 236.561 327.908 237.156 327.811 238.089H328.953C329.066 237.723 329.446 237.522 330.003 237.522C330.657 237.522 331.009 237.82 331.009 238.353V238.812L329.632 238.895C328.333 238.968 327.606 239.529 327.606 240.486C327.606 241.463 328.343 242.088 329.373 242.088ZM329.73 241.155C329.193 241.155 328.807 240.887 328.807 240.428C328.807 239.983 329.124 239.734 329.803 239.69L331.009 239.607V240.042C331.009 240.677 330.462 241.155 329.73 241.155ZM333.615 242H334.826V238.753C334.826 238.089 335.271 237.586 335.871 237.586C336.467 237.586 336.838 237.947 336.838 238.538V242H338.015V238.665C338.015 238.055 338.43 237.586 339.06 237.586C339.709 237.586 340.036 237.933 340.036 238.626V242H341.242V238.328C341.242 237.22 340.598 236.561 339.528 236.561C338.786 236.561 338.171 236.941 337.907 237.522H337.824C337.6 236.932 337.087 236.561 336.35 236.561C335.642 236.561 335.095 236.922 334.865 237.522H334.782V236.663H333.615V242ZM345.538 236.575C344.805 236.575 344.185 236.941 343.878 237.547H343.795V236.663H342.628V243.772H343.839V241.189H343.922C344.195 241.756 344.786 242.088 345.553 242.088C346.9 242.088 347.74 241.028 347.74 239.334C347.74 237.625 346.89 236.575 345.538 236.575ZM345.157 241.082C344.332 241.082 343.819 240.413 343.814 239.334C343.819 238.255 344.337 237.586 345.162 237.586C345.992 237.586 346.495 238.24 346.495 239.334C346.495 240.428 345.997 241.082 345.157 241.082ZM348.955 242H350.166V234.598H348.955V242ZM355.13 240.54C354.954 240.94 354.539 241.165 353.939 241.165C353.143 241.165 352.63 240.599 352.601 239.695V239.632H356.331V239.246C356.331 237.571 355.418 236.561 353.895 236.561C352.347 236.561 351.385 237.64 351.385 239.354C351.385 241.062 352.332 242.107 353.905 242.107C355.164 242.107 356.058 241.502 356.278 240.54H355.13ZM353.89 237.503C354.618 237.503 355.096 238.016 355.121 238.826H352.606C352.66 238.025 353.167 237.503 353.89 237.503ZM360.759 239.715V238.606H357.551V239.715H360.759ZM369.259 236.663H368.053L367.169 240.672H367.086L366.051 236.663H364.894L363.868 240.672H363.785L362.896 236.663H361.676L363.121 242H364.381L365.416 238.133H365.499L366.539 242H367.813L369.259 236.663ZM373.535 240.54C373.359 240.94 372.944 241.165 372.344 241.165C371.548 241.165 371.035 240.599 371.006 239.695V239.632H374.736V239.246C374.736 237.571 373.823 236.561 372.3 236.561C370.752 236.561 369.79 237.64 369.79 239.354C369.79 241.062 370.737 242.107 372.309 242.107C373.569 242.107 374.463 241.502 374.682 240.54H373.535ZM372.295 237.503C373.022 237.503 373.501 238.016 373.525 238.826H371.011C371.064 238.025 371.572 237.503 372.295 237.503ZM375.78 238.187C375.78 238.987 376.263 239.456 377.289 239.69L378.236 239.91C378.744 240.027 378.973 240.223 378.973 240.525C378.973 240.931 378.548 241.209 377.938 241.209C377.333 241.209 376.957 240.965 376.839 240.569H375.643C375.736 241.531 376.576 242.107 377.909 242.107C379.242 242.107 380.184 241.429 380.184 240.408C380.184 239.622 379.711 239.188 378.69 238.953L377.748 238.743C377.211 238.616 376.957 238.426 376.957 238.123C376.957 237.728 377.372 237.459 377.923 237.459C378.49 237.459 378.846 237.703 378.934 238.079H380.072C379.984 237.117 379.188 236.561 377.919 236.561C376.659 236.561 375.78 237.229 375.78 238.187ZM381.706 235.354V236.697H380.862V237.64H381.706V240.584C381.706 241.614 382.195 242.024 383.42 242.024C383.655 242.024 383.879 242.005 384.055 241.971V241.043C383.909 241.058 383.816 241.067 383.645 241.067C383.137 241.067 382.912 240.828 382.912 240.296V237.64H384.055V236.697H382.912V235.354H381.706Z" fill="black"/>
+<path d="M567.109 42L570.033 33.5449H568.422L566.312 40.2715H566.213L564.086 33.5449H562.416L565.369 42H567.109ZM573.219 38.2266H574.28C575.323 38.2266 575.956 38.748 575.956 39.5977C575.956 40.418 575.27 40.9688 574.297 40.9688C573.319 40.9688 572.657 40.4648 572.592 39.6797H571.145C571.215 41.209 572.475 42.2109 574.315 42.2109C576.143 42.2109 577.502 41.1562 577.502 39.7031C577.502 38.5488 576.782 37.8047 575.633 37.6289V37.5293C576.53 37.2891 577.169 36.6152 577.174 35.5957C577.18 34.3828 576.167 33.334 574.368 33.334C572.534 33.334 571.385 34.3711 571.309 35.8535H572.727C572.792 35.0098 573.366 34.541 574.286 34.541C575.182 34.541 575.715 35.0918 575.715 35.7891C575.715 36.5566 575.118 37.0957 574.251 37.0957H573.219V38.2266ZM581.105 42H582.616V33.5449H581.11L578.901 35.0977V36.5215L581.005 35.0332H581.105V42ZM595.755 40.3652C595.491 40.9219 594.94 41.2207 594.126 41.2207C593.054 41.2207 592.356 40.4297 592.304 39.1816V39.1348H596.845V38.748C596.845 36.7852 595.807 35.5723 594.102 35.5723C592.368 35.5723 591.255 36.8613 591.255 38.8477C591.255 40.8457 592.35 42.1113 594.102 42.1113C595.485 42.1113 596.47 41.4434 596.763 40.3652H595.755ZM594.091 36.4629C595.093 36.4629 595.761 37.2012 595.784 38.3203H592.304C592.38 37.2012 593.083 36.4629 594.091 36.4629ZM602.55 40.3652C602.286 40.9219 601.736 41.2207 600.921 41.2207C599.849 41.2207 599.152 40.4297 599.099 39.1816V39.1348H603.64V38.748C603.64 36.7852 602.603 35.5723 600.898 35.5723C599.163 35.5723 598.05 36.8613 598.05 38.8477C598.05 40.8457 599.146 42.1113 600.898 42.1113C602.281 42.1113 603.265 41.4434 603.558 40.3652H602.55ZM600.886 36.4629C601.888 36.4629 602.556 37.2012 602.579 38.3203H599.099C599.175 37.2012 599.878 36.4629 600.886 36.4629ZM605.584 42H606.592V36.5273H608.039V35.6836H606.592V35.0098C606.592 34.3184 606.896 33.9668 607.623 33.9668C607.805 33.9668 607.975 33.9727 608.098 33.9961V33.1758C607.887 33.1348 607.664 33.1172 607.418 33.1172C606.217 33.1172 605.584 33.7207 605.584 34.9805V35.6836H604.535V36.5273H605.584V42ZM612.145 42.1934C614.213 42.1934 615.397 40.5293 615.397 37.623C615.397 34.7461 614.038 33.3457 612.215 33.3457C610.481 33.3457 609.25 34.5586 609.25 36.2578C609.25 37.8984 610.416 39.0879 612.028 39.0879C613.036 39.0879 613.862 38.6074 614.278 37.7871H614.372C614.313 40.0371 613.534 41.2559 612.157 41.2559C611.325 41.2559 610.68 40.793 610.458 40.0312H609.374C609.637 41.3613 610.709 42.1934 612.145 42.1934ZM612.215 38.1738C611.096 38.1738 610.317 37.377 610.317 36.2227C610.317 35.1152 611.143 34.2715 612.227 34.2715C613.311 34.2715 614.137 35.127 614.137 36.2578C614.137 37.377 613.334 38.1738 612.215 38.1738ZM618.8 42.1113C619.644 42.1113 620.335 41.7422 620.745 41.0684H620.839V42H621.8V37.6758C621.8 36.3633 620.939 35.5723 619.397 35.5723C618.05 35.5723 617.054 36.2402 616.919 37.2539H617.939C618.079 36.7559 618.606 36.4688 619.362 36.4688C620.306 36.4688 620.792 36.8965 620.792 37.6758V38.25L618.97 38.3613C617.499 38.4492 616.667 39.0996 616.667 40.2305C616.667 41.3848 617.575 42.1113 618.8 42.1113ZM618.987 41.2266C618.255 41.2266 617.71 40.8516 617.71 40.207C617.71 39.5742 618.132 39.2402 619.093 39.1758L620.792 39.0645V39.6445C620.792 40.5469 620.024 41.2266 618.987 41.2266ZM628.83 37.6172C628.654 36.4922 627.716 35.5723 626.181 35.5723C624.412 35.5723 623.287 36.8496 623.287 38.8184C623.287 40.8281 624.418 42.1113 626.187 42.1113C627.705 42.1113 628.648 41.2559 628.83 40.0957H627.81C627.623 40.8105 627.031 41.2031 626.181 41.2031C625.056 41.2031 624.33 40.2773 624.33 38.8184C624.33 37.3887 625.045 36.4805 626.181 36.4805C627.089 36.4805 627.646 36.9902 627.81 37.6172H628.83ZM632.274 42H633.328V33.5449H632.279L630.029 35.1621V36.2754L632.18 34.7168H632.274V42Z" fill="#343536"/>
+<path d="M215.693 42V29.1822H213.011V34.3875H207.237V29.1822H204.554V42H207.237V36.5993H213.011V42H215.693ZM221.136 42.151C222.407 42.151 223.473 41.6092 223.979 40.7031H224.139V42H226.644V35.3202C226.644 33.2327 225.178 32.0069 222.584 32.0069C220.124 32.0069 218.463 33.135 218.294 34.9293H220.675C220.888 34.3164 221.509 33.9878 222.442 33.9878C223.508 33.9878 224.094 34.4763 224.094 35.3202V36.1285L221.723 36.2706C219.289 36.4128 217.93 37.4432 217.93 39.2108C217.93 40.9963 219.253 42.151 221.136 42.151ZM221.989 40.259C221.092 40.259 220.461 39.806 220.461 39.0509C220.461 38.3314 221.003 37.9139 222.114 37.8429L224.094 37.7096V38.438C224.094 39.4684 223.188 40.259 221.989 40.259ZM228.871 35.0715C228.871 36.5726 229.795 37.4698 231.696 37.8873L233.472 38.287C234.334 38.4824 234.707 38.7844 234.707 39.2819C234.707 39.9303 234.014 40.3745 233.011 40.3745C231.98 40.3745 231.349 39.9747 231.154 39.2996H228.631C228.809 41.1473 230.372 42.2043 232.957 42.2043C235.524 42.2043 237.274 40.943 237.274 39.0065C237.274 37.5497 236.421 36.7503 234.521 36.3328L232.682 35.9331C231.776 35.7288 231.358 35.4179 231.358 34.9205C231.358 34.2809 232.042 33.8456 232.966 33.8456C233.925 33.8456 234.521 34.2454 234.654 34.8938H237.043C236.901 33.0462 235.435 32.0069 232.948 32.0069C230.506 32.0069 228.871 33.2416 228.871 35.0715ZM239.395 42H241.98V36.3683C241.98 35.0715 242.726 34.1921 244.023 34.1921C245.195 34.1921 245.826 34.9027 245.826 36.2884V42H248.411V35.7021C248.411 33.3571 247.159 32.0336 245.053 32.0336C243.614 32.0336 242.548 32.7087 242.095 33.819H241.936V28.4805H239.395V42ZM252.149 30.7189C252.948 30.7189 253.605 30.0794 253.605 29.2799C253.605 28.4716 252.948 27.832 252.149 27.832C251.349 27.832 250.683 28.4716 250.683 29.2799C250.683 30.0794 251.349 30.7189 252.149 30.7189ZM250.852 42H253.437V32.2201H250.852V42ZM264.636 35.6311C264.422 33.4459 262.868 32.0069 260.274 32.0069C257.21 32.0069 255.486 33.8634 255.486 37.0878C255.486 40.3478 257.218 42.2043 260.274 42.2043C262.823 42.2043 264.422 40.8008 264.636 38.6512H262.219C262.024 39.6283 261.331 40.1524 260.274 40.1524C258.888 40.1524 258.098 39.0598 258.098 37.0878C258.098 35.1425 258.88 34.0677 260.274 34.0677C261.376 34.0677 262.042 34.6895 262.219 35.6311H264.636ZM270.913 42.2043C273.925 42.2043 275.737 40.3034 275.737 37.1056C275.737 33.9345 273.898 32.0069 270.913 32.0069C267.929 32.0069 266.09 33.9434 266.09 37.1056C266.09 40.2945 267.902 42.2043 270.913 42.2043ZM270.913 40.1613C269.528 40.1613 268.746 39.042 268.746 37.1056C268.746 35.1869 269.537 34.0588 270.913 34.0588C272.281 34.0588 273.081 35.1869 273.081 37.1056C273.081 39.042 272.29 40.1613 270.913 40.1613ZM277.76 42H280.345V36.5282C280.345 35.1514 281.313 34.3076 282.725 34.3076C283.143 34.3076 283.747 34.3786 283.951 34.4497V32.1757C283.729 32.1046 283.294 32.0602 282.939 32.0602C281.695 32.0602 280.682 32.7975 280.425 33.7746H280.265V32.2201H277.76V42ZM291.34 32.0602C289.989 32.0602 288.879 32.7264 288.346 33.8279H288.186V32.2201H285.681V45.2422H288.266V40.5077H288.426C288.906 41.5381 289.98 42.151 291.384 42.151C293.836 42.151 295.337 40.2501 295.337 37.1056C295.337 33.9522 293.818 32.0602 291.34 32.0602ZM290.46 40.0636C289.092 40.0636 288.239 38.9443 288.239 37.1145C288.239 35.2847 289.092 34.1565 290.469 34.1565C291.846 34.1565 292.681 35.2669 292.681 37.1056C292.681 38.9532 291.855 40.0636 290.46 40.0636ZM298.47 44.7536L303.063 28.4805H300.682L296.09 44.7536H298.47ZM312.982 35.6311C312.769 33.4459 311.215 32.0069 308.621 32.0069C305.557 32.0069 303.833 33.8634 303.833 37.0878C303.833 40.3478 305.565 42.2043 308.621 42.2043C311.17 42.2043 312.769 40.8008 312.982 38.6512H310.566C310.371 39.6283 309.678 40.1524 308.621 40.1524C307.235 40.1524 306.445 39.0598 306.445 37.0878C306.445 35.1425 307.226 34.0677 308.621 34.0677C309.723 34.0677 310.389 34.6895 310.566 35.6311H312.982ZM319.26 42.2043C322.272 42.2043 324.084 40.3034 324.084 37.1056C324.084 33.9345 322.245 32.0069 319.26 32.0069C316.276 32.0069 314.437 33.9434 314.437 37.1056C314.437 40.2945 316.249 42.2043 319.26 42.2043ZM319.26 40.1613C317.875 40.1613 317.093 39.042 317.093 37.1056C317.093 35.1869 317.884 34.0588 319.26 34.0588C320.628 34.0588 321.428 35.1869 321.428 37.1056C321.428 39.042 320.637 40.1613 319.26 40.1613ZM326.107 42H328.692V36.1019C328.692 34.9826 329.411 34.1654 330.424 34.1654C331.437 34.1654 332.041 34.7695 332.041 35.8176V42H334.528V35.9864C334.528 34.9293 335.203 34.1654 336.251 34.1654C337.344 34.1654 337.885 34.7517 337.885 35.9331V42H340.47V35.2847C340.47 33.2683 339.253 32.0069 337.299 32.0069C335.931 32.0069 334.803 32.7264 334.35 33.8101H334.19C333.799 32.6909 332.858 32.0069 331.481 32.0069C330.193 32.0069 329.171 32.6909 328.772 33.8101H328.612V32.2201H326.107V42ZM342.893 42H345.478V36.1019C345.478 34.9826 346.198 34.1654 347.21 34.1654C348.223 34.1654 348.827 34.7695 348.827 35.8176V42H351.314V35.9864C351.314 34.9293 351.989 34.1654 353.037 34.1654C354.13 34.1654 354.672 34.7517 354.672 35.9331V42H357.257V35.2847C357.257 33.2683 356.04 32.0069 354.085 32.0069C352.717 32.0069 351.589 32.7264 351.136 33.8101H350.976C350.586 32.6909 349.644 32.0069 348.267 32.0069C346.979 32.0069 345.958 32.6909 345.558 33.8101H345.398V32.2201H342.893V42ZM364.023 42.2043C367.034 42.2043 368.846 40.3034 368.846 37.1056C368.846 33.9345 367.008 32.0069 364.023 32.0069C361.038 32.0069 359.2 33.9434 359.2 37.1056C359.2 40.2945 361.012 42.2043 364.023 42.2043ZM364.023 40.1613C362.637 40.1613 361.856 39.042 361.856 37.1056C361.856 35.1869 362.646 34.0588 364.023 34.0588C365.391 34.0588 366.19 35.1869 366.19 37.1056C366.19 39.042 365.4 40.1613 364.023 40.1613ZM370.869 42H373.454V36.3417C373.454 35.0182 374.192 34.1654 375.391 34.1654C376.617 34.1654 377.194 34.8849 377.194 36.2618V42H379.779V35.6755C379.779 33.3393 378.606 32.0069 376.43 32.0069C374.982 32.0069 373.987 32.6909 373.534 33.7924H373.374V32.2201H370.869V42Z" fill="#1D1E1F"/>
+</g>
+<defs>
+<filter id="filter0_ddddd" x="151.103" y="0" width="543.794" height="360.769" filterUnits="userSpaceOnUse" color-interpolation-filters="sRGB">
+<feFlood flood-opacity="0" result="BackgroundImageFix"/>
+<feColorMatrix in="SourceAlpha" type="matrix" values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 127 0" result="hardAlpha"/>
+<feOffset dy="2.30981"/>
+<feGaussianBlur stdDeviation="0.923924"/>
+<feColorMatrix type="matrix" values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0.0196802 0"/>
+<feBlend mode="multiply" in2="BackgroundImageFix" result="effect1_dropShadow"/>
+<feColorMatrix in="SourceAlpha" type="matrix" values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 127 0" result="hardAlpha"/>
+<feOffset dy="5.5508"/>
+<feGaussianBlur stdDeviation="2.22032"/>
+<feColorMatrix type="matrix" values="0 0 0 0 0.388235 0 0 0 0 0.815686 0 0 0 0 1 0 0 0 0.12 0"/>
+<feBlend mode="multiply" in2="effect1_dropShadow" result="effect2_dropShadow"/>
+<feColorMatrix in="SourceAlpha" type="matrix" values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 127 0" result="hardAlpha"/>
+<feOffset dy="10.4517"/>
+<feGaussianBlur stdDeviation="4.18066"/>
+<feColorMatrix type="matrix" values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0.035 0"/>
+<feBlend mode="multiply" in2="effect2_dropShadow" result="effect3_dropShadow"/>
+<feColorMatrix in="SourceAlpha" type="matrix" values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 127 0" result="hardAlpha"/>
+<feOffset dy="18.644"/>
+<feGaussianBlur stdDeviation="7.45759"/>
+<feColorMatrix type="matrix" values="0 0 0 0 0.388235 0 0 0 0 0.815686 0 0 0 0 1 0 0 0 0.02 0"/>
+<feBlend mode="multiply" in2="effect3_dropShadow" result="effect4_dropShadow"/>
+<feColorMatrix in="SourceAlpha" type="matrix" values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 127 0" result="hardAlpha"/>
+<feOffset dy="34.8715"/>
+<feGaussianBlur stdDeviation="13.9486"/>
+<feColorMatrix type="matrix" values="0 0 0 0 0.388235 0 0 0 0 0.815686 0 0 0 0 1 0 0 0 0.08 0"/>
+<feBlend mode="multiply" in2="effect4_dropShadow" result="effect5_dropShadow"/>
+<feBlend mode="normal" in="SourceGraphic" in2="effect5_dropShadow" result="shape"/>
+</filter>
+<linearGradient id="paint0_linear" x1="118.729" y1="193.979" x2="700.912" y2="816.135" gradientUnits="userSpaceOnUse">
+<stop stop-color="white"/>
+<stop offset="1" stop-color="#F7F7F7"/>
+</linearGradient>
+<linearGradient id="paint1_linear" x1="13" y1="101" x2="49.3376" y2="568.249" gradientUnits="userSpaceOnUse">
+<stop stop-color="#3D3E3F"/>
+<stop offset="1" stop-color="#1D1E23"/>
+</linearGradient>
+<linearGradient id="paint2_linear" x1="250.116" y1="58.3319" x2="615.913" y2="437.948" gradientUnits="userSpaceOnUse">
+<stop stop-color="white"/>
+<stop offset="1" stop-color="#F7F7F7"/>
+</linearGradient>
+<clipPath id="clip0">
+<rect width="646" height="441" fill="white"/>
+</clipPath>
+</defs>
+</svg>
diff --git a/v1.9.4/website/public/img/homepage-hero/hero-right.svg b/v1.9.4/website/public/img/homepage-hero/hero-right.svg
new file mode 100644
index 0000000..0fd30ef
--- /dev/null
+++ b/v1.9.4/website/public/img/homepage-hero/hero-right.svg
@@ -0,0 +1 @@
+<svg width="456" height="592" viewBox="0 0 456 592" fill="none" xmlns="http://www.w3.org/2000/svg"><path d="M429.11 198h-3.22L228 83.432v-1.864l200.865 116.289.245.143zm18.754-.143L228 70.567v1.865L444.89 198h3.22l-.246-.143zm-57 0L228 103.567v1.864L387.89 198h3.22l-.246-.143zm19 0L228 92.567v1.864L406.89 198h3.22l-.246-.143zm-37.999 0L228 114.567v1.864L368.89 198h3.22l-.245-.143zm-19 0L228 125.566v1.864L349.891 198h3.219l-.245-.143zM254.89 0h3.22L456 114.568v1.864L255.135.142 254.89 0zm-18.754.143L456 127.432v-1.864L239.11 0h-3.22l.246.143zm57 0L456 94.433v-1.864L296.11 0h-3.22l.246.143zm-19 0L456 105.433v-1.864L277.11 0h-3.22l.246.143zm37.999 0L456 83.433v-1.864L315.11 0h-3.22l.245.143zm19 0L456 72.433V70.57L334.109 0h-3.219l.245.143zM228.082 48.615L456 180.568v1.864l-.082-.048L228 50.432v-1.865l.082.048zM228 37.568v1.864l227.918 131.953.082.048v-1.865L228.082 37.616l-.082-.048zm0 22v1.864l227.918 131.952.082.048v-1.863L228.082 59.615l-.082-.048zm0-33v1.864l227.918 131.953.082.047v-1.864L228.082 26.616l-.082-.048zm0-11v1.864l227.918 131.953.082.047v-1.864L228.082 15.615l-.082-.047zm0-11v1.864l227.918 131.953.082.047v-1.864L228.082 4.615 228 4.568zM334.11 394h-3.22L228 335.033v-1.845l105.865 60.671.245.141zm-95 0L228 387.632v1.845l7.891 4.523h3.219zm75.755-.141L228 344.077v1.845L311.891 394h3.22l-.246-.141zm-19 0L228 354.965v1.845L292.891 394h3.22l-.246-.141zm-38 0L228 376.743v1.846L254.89 394h3.221l-.246-.141zm19 0L228 365.854v1.845L273.891 394h3.219l-.245-.141zM349.89 198h3.22L456 256.967v1.845l-105.865-60.671-.245-.141zm95 0l11.11 6.368v-1.845L448.109 198h-3.219zm-75.755.141L456 247.923v-1.845L372.109 198h-3.22l.246.141zm19 0L456 237.035v-1.845L391.109 198h-3.22l.246.141zm38 0L456 215.257v-1.846L429.11 198h-3.221l.246.141zm-19 0L456 226.146v-1.845L410.109 198h-3.219l.245.141zM201.11 394h-3.22L0 280.589v-1.845l200.865 115.115.245.141zm18.754-.141L0 267.855v1.845L216.89 394h3.22l-.246-.141zm-57 0L0 300.521v1.845L159.89 394h3.22l-.246-.141zm19 0L0 289.632v1.845L178.89 394h3.22l-.246-.141zm-37.999 0L0 311.41v1.845L140.89 394h3.22l-.245-.141zm-19 0L0 322.298v1.845L121.891 394h3.219l-.245-.141zM26.89 198h3.22L228 311.411v1.845L27.135 198.141 26.89 198zm-18.754.141L228 324.145V322.3L11.11 198H7.89l.246.141zm57 0L228 291.479v-1.845L68.11 198h-3.22l.246.141zm-19 0L228 302.368v-1.845L49.11 198h-3.22l.246.141zm38 0L228 280.59v-1.845L87.11 198h-3.22l.245.141zm18.999 0L228 269.702v-1.845L106.109 198h-3.219l.245.141z" fill="#63D0FF"/><path d="M.082 246.124L228 376.745v1.844l-.082-.047L0 247.923v-1.846l.082.047zM0 235.189v1.845l227.918 130.62.082.047v-1.845L.082 235.236 0 235.189zm0 21.777v1.846l227.918 130.619.082.047v-1.844L.082 257.013 0 256.966zM0 224.3v1.845l227.918 130.62.082.047v-1.845L.082 224.347 0 224.3zm0-10.889v1.845l227.918 130.62.082.047v-1.845L.082 213.458 0 213.411zm0-10.889v1.845l227.918 130.62.082.047v-1.845L.082 202.569 0 202.522zM229 519.69a.815.815 0 00-.746.5.815.815 0 00.175.882.8.8 0 00.88.176.81.81 0 00-.309-1.558zm0-11a.807.807 0 00-.792.968.814.814 0 00.635.636.808.808 0 00.728-1.367.814.814 0 00-.571-.237zm0 22.001a.806.806 0 00-.792.967.818.818 0 00.222.415.8.8 0 00.879.175.807.807 0 00.437-1.058.814.814 0 00-.746-.499zm0-44.001a.807.807 0 00-.792.968.814.814 0 00.635.636.808.808 0 00.728-1.367.814.814 0 00-.571-.237zm0 11.001a.806.806 0 00-.792.967.806.806 0 001.599-.158.804.804 0 00-.807-.809zm0 77a.806.806 0 00-.792.967.806.806 0 001.599-.158.804.804 0 00-.807-.809zm0-11.001a.807.807 0 00-.792.968.814.814 0 00.635.636.808.808 0 00.728-1.367.814.814 0 00-.571-.237zm0-22a.807.807 0 00-.792.968.814.814 0 00.635.636.808.808 0 00.728-1.367.814.814 0 00-.571-.237zm0 11a.807.807 0 00-.792.968.814.814 0 00.635.636.809.809 0 10.157-1.604zm0-88a.807.807 0 00-.792.968.814.814 0 00.635.636.808.808 0 00.728-1.367.814.814 0 00-.571-.237zm0-44a.815.815 0 00-.746.5.815.815 0 00.175.882.8.8 0 00.88.176.81.81 0 00-.309-1.558zm0-11a.807.807 0 00-.792.968.814.814 0 00.635.636.808.808 0 00.728-1.367.798.798 0 00-.571-.237zm0-10.999a.806.806 0 00-.792.967.806.806 0 001.599-.158.804.804 0 00-.807-.809zm0 33a.806.806 0 00-.792.967.818.818 0 00.222.415.8.8 0 00.879.175.807.807 0 00.437-1.058.814.814 0 00-.746-.499zm0 21.999a.807.807 0 00-.792.968.814.814 0 00.635.636.809.809 0 10.157-1.604zm0-11a.807.807 0 00-.792.968.814.814 0 00.635.636.808.808 0 00.728-1.367.814.814 0 00-.571-.237zm0 143a.807.807 0 00-.792.968.814.814 0 00.635.636.808.808 0 00.728-1.367.814.814 0 00-.571-.237zm0-109.999a.806.806 0 00-.792.967.806.806 0 001.599-.158.804.804 0 00-.807-.809zm85.5-82.501a.807.807 0 00-.792.968.814.814 0 00.635.636.808.808 0 00.728-1.367.814.814 0 00-.571-.237zm19 0a.804.804 0 00-.746.5.815.815 0 00.175.882.809.809 0 00.88.176.81.81 0 00-.309-1.558zm19 0a.814.814 0 00-.746.5.806.806 0 00.176.882.798.798 0 00.879.176.807.807 0 00.437-1.058.813.813 0 00-.437-.438.8.8 0 00-.309-.062zm95 0a.804.804 0 00-.746.5.815.815 0 00.175.882.809.809 0 00.88.176.81.81 0 00-.309-1.558zm-171 0a.804.804 0 00-.746.5.815.815 0 00.175.882.809.809 0 00.88.176.81.81 0 00-.309-1.558zm152 0a.807.807 0 00-.792.968.821.821 0 00.221.414.8.8 0 00.88.176.81.81 0 00-.309-1.558zm-171 0a.806.806 0 00-.746.5.815.815 0 00.175.882.808.808 0 101.142-1.144.81.81 0 00-.571-.238zm114 0a.807.807 0 00-.792.968.814.814 0 00.635.636.808.808 0 00.728-1.367.814.814 0 00-.571-.237zm-76 0a.807.807 0 00-.57 1.382.807.807 0 001.316-.882.813.813 0 00-.437-.438.8.8 0 00-.309-.062zm95 0a.804.804 0 00-.746.5.815.815 0 00.175.882.809.809 0 00.88.176.81.81 0 00-.309-1.558zm-152 0a.807.807 0 00-.57 1.382.798.798 0 00.879.176.807.807 0 00.437-1.058.813.813 0 00-.437-.438.8.8 0 00-.309-.062zm171 0a.814.814 0 00-.746.5.806.806 0 00.176.882.798.798 0 00.879.176.807.807 0 00.437-1.058.813.813 0 00-.437-.438.8.8 0 00-.309-.062zM305 508.69a.804.804 0 00-.746.5.815.815 0 00.175.882.809.809 0 00.88.176.81.81 0 00-.309-1.558zm0 66.001a.807.807 0 00-.571 1.381.802.802 0 00.88.176.81.81 0 00-.309-1.557zm0-33.001a.804.804 0 00-.746.5.815.815 0 00.175.882.809.809 0 00.88.176.81.81 0 00-.309-1.558zm0 22a.804.804 0 00-.746.5.815.815 0 00.175.882.809.809 0 00.88.176.81.81 0 00-.309-1.558zm0-32.999a.803.803 0 00-.746.499.815.815 0 00.175.882.8.8 0 00.88.176.812.812 0 00.262-1.32.807.807 0 00-.571-.237zm0-11.001a.804.804 0 00-.746.5.815.815 0 00.175.882.802.802 0 00.88.176.81.81 0 00-.309-1.558zm0 33a.804.804 0 00-.746.5.811.811 0 00.588 1.104.811.811 0 00.829-.344.81.81 0 00-.671-1.26zm0-154a.804.804 0 00-.746.5.815.815 0 00.175.882.802.802 0 00.88.176.81.81 0 00-.309-1.558zm9.5 181.501a.806.806 0 00-.792.967.806.806 0 001.599-.158.82.82 0 00-.236-.573.814.814 0 00-.571-.236zM305 409.69a.804.804 0 00-.746.5.815.815 0 00.175.882.809.809 0 00.88.176.81.81 0 00-.309-1.558zm9.5 148.5a.807.807 0 00-.792.968.814.814 0 00.635.636.808.808 0 00.728-1.367.814.814 0 00-.571-.237zm-9.5-137.5a.804.804 0 00-.746.5.815.815 0 00.175.882.802.802 0 00.88.176.81.81 0 00-.309-1.558zm9.5 148.5a.815.815 0 00-.746.5.815.815 0 00.175.882.8.8 0 00.88.176.81.81 0 00-.309-1.558zM305 431.691a.803.803 0 00-.746.499.815.815 0 00.175.882.8.8 0 00.88.176.812.812 0 00.262-1.32.807.807 0 00-.571-.237zm0 44a.807.807 0 00-.571 1.381.802.802 0 00.88.176.81.81 0 00-.309-1.557zm0 21.999a.804.804 0 00-.746.5.815.815 0 00.175.882.802.802 0 00.88.176.81.81 0 00-.309-1.558zm0-33a.804.804 0 00-.746.5.815.815 0 00.175.882.809.809 0 00.88.176.81.81 0 00-.309-1.558zm0 22a.804.804 0 00-.746.5.815.815 0 00.175.882.809.809 0 00.88.176.81.81 0 00-.309-1.558zm0-33a.804.804 0 00-.746.5.811.811 0 00.588 1.104.811.811 0 00.829-.344.81.81 0 00-.671-1.26zm0-11a.804.804 0 00-.746.5.815.815 0 00.175.882.809.809 0 00.88.176.81.81 0 00-.309-1.558zm-19-33a.806.806 0 00-.746.5.815.815 0 00.175.882.808.808 0 101.142-1.144.806.806 0 00-.571-.238zm9.5 170.501a.8.8 0 00-.746.5.81.81 0 001.056 1.057.81.81 0 00-.31-1.557zm0-22.001a.807.807 0 00-.57 1.382.807.807 0 001.316-.882.802.802 0 00-.746-.5zm0-32.999a.813.813 0 00-.791.967.813.813 0 00.634.636.807.807 0 00.903-1.104.813.813 0 00-.437-.438.781.781 0 00-.309-.061zm0 10.999a.807.807 0 00-.57 1.382.807.807 0 001.316-.882.802.802 0 00-.746-.5zm0 11.001a.807.807 0 00-.57 1.382.8.8 0 00.879.175.807.807 0 00.437-1.058.813.813 0 00-.437-.438.781.781 0 00-.309-.061zm0 21.999a.81.81 0 10.309 1.558.807.807 0 00.437-1.058.813.813 0 00-.437-.438.8.8 0 00-.309-.062zM286 398.691a.814.814 0 00-.792.967.806.806 0 001.599-.158.81.81 0 00-.807-.809zm0 43.999a.806.806 0 00-.746.5.815.815 0 00.175.882.808.808 0 101.142-1.144.81.81 0 00-.571-.238zm0 11a.806.806 0 00-.746.5.811.811 0 00.588 1.104.811.811 0 00.829-.344.81.81 0 00-.671-1.26zm0-33a.806.806 0 00-.746.5.815.815 0 00.175.882.8.8 0 00.88.176.81.81 0 00-.309-1.558zm0 11.001a.805.805 0 00-.746.499.815.815 0 00.175.882.8.8 0 00.88.176.812.812 0 00.262-1.32.805.805 0 00-.571-.237zm9.5 49.5a.8.8 0 00-.746.5.81.81 0 001.056 1.057.81.81 0 00-.31-1.557zm0-55a.813.813 0 00-.791.967.813.813 0 00.634.636.807.807 0 00.903-1.104.813.813 0 00-.437-.438.781.781 0 00-.309-.061zm0 87.999a.807.807 0 00-.57 1.382.807.807 0 001.316-.882.813.813 0 00-.437-.438.8.8 0 00-.309-.062zm0-99a.807.807 0 00-.57 1.382.807.807 0 001.316-.882.813.813 0 00-.437-.438.8.8 0 00-.309-.062zm0 33.001a.807.807 0 00-.57 1.382.8.8 0 00.879.175.807.807 0 00.437-1.058.813.813 0 00-.437-.438.781.781 0 00-.309-.061zm0-44.001a.814.814 0 00-.746.5.812.812 0 00.589 1.104.808.808 0 00.728-1.367.814.814 0 00-.571-.237zm0 33a.807.807 0 00-.57 1.382.807.807 0 001.316-.882.802.802 0 00-.746-.5zm0 55a.807.807 0 00-.57 1.382.807.807 0 001.316-.882.813.813 0 00-.437-.438.8.8 0 00-.309-.062zm0 11a.814.814 0 00-.746.5.812.812 0 00.589 1.104.808.808 0 00.728-1.367.814.814 0 00-.571-.237zm0-44a.807.807 0 00-.57 1.382.807.807 0 001.316-.882.802.802 0 00-.746-.5zm0 11a.81.81 0 10.309 1.558.807.807 0 00.437-1.058.813.813 0 00-.437-.438.8.8 0 00-.309-.062zm9.5 115.5a.804.804 0 00-.746.5.815.815 0 00.175.882.809.809 0 00.88.176.81.81 0 00-.309-1.558zm19-54.999a.8.8 0 00-.746.5.81.81 0 001.056 1.057.81.81 0 00-.31-1.557zm9.5 27.499a.804.804 0 00-.746.5.815.815 0 00.175.882.809.809 0 00.88.176.81.81 0 00-.309-1.558zm0-44a.804.804 0 00-.746.5.815.815 0 00.175.882.809.809 0 00.88.176.81.81 0 00-.309-1.558zm0 33.001a.807.807 0 00-.571 1.381.802.802 0 00.88.176.81.81 0 00-.309-1.557zm0-11.001a.804.804 0 00-.746.5.815.815 0 00.175.882.809.809 0 00.88.176.81.81 0 00-.309-1.558zm0 44.001a.803.803 0 00-.746.499.815.815 0 00.175.882.8.8 0 00.88.176.812.812 0 00.262-1.32.807.807 0 00-.571-.237zm0-55a.807.807 0 00-.571 1.381.802.802 0 00.88.176.81.81 0 00-.309-1.557zm0 43.999a.804.804 0 00-.746.5.815.815 0 00.175.882.802.802 0 00.88.176.81.81 0 00-.309-1.558zM324 398.691a.807.807 0 00-.57 1.382.803.803 0 00.879.175.807.807 0 00.437-1.058.813.813 0 00-.437-.438.781.781 0 00-.309-.061zm0 43.999a.807.807 0 00-.57 1.382.798.798 0 00.879.176.807.807 0 00.437-1.058.813.813 0 00-.437-.438.8.8 0 00-.309-.062zm0 11a.814.814 0 00-.746.5.812.812 0 00.589 1.104.808.808 0 00.728-1.367.814.814 0 00-.571-.237zm0-44a.807.807 0 00-.57 1.382.798.798 0 00.879.176.814.814 0 00.499-.748.805.805 0 00-.237-.573.798.798 0 00-.571-.237zm0 22.001a.8.8 0 00-.746.5.81.81 0 001.056 1.057.81.81 0 00-.31-1.557zm9.5-5.5a.807.807 0 00-.571 1.381.802.802 0 00.88.176.81.81 0 00-.309-1.557zm0 76.999a.804.804 0 00-.746.5.811.811 0 00.588 1.104.811.811 0 00.829-.344.81.81 0 00-.671-1.26zm0-88a.804.804 0 00-.746.5.815.815 0 00.175.882.809.809 0 00.88.176.81.81 0 00-.309-1.558zm-9.5 49.5a.807.807 0 00-.57 1.382.798.798 0 00.879.176.807.807 0 00.437-1.058.813.813 0 00-.437-.438.8.8 0 00-.309-.062zm-9.5 82.501a.806.806 0 00-.792.967.806.806 0 001.599-.158.804.804 0 00-.807-.809zM286 464.69a.806.806 0 00-.746.5.815.815 0 00.175.882.808.808 0 101.142-1.144.81.81 0 00-.571-.238zm47.5-27.5a.804.804 0 00-.746.5.815.815 0 00.175.882.809.809 0 00.88.176.81.81 0 00-.309-1.558zm0 55a.804.804 0 00-.746.5.815.815 0 00.175.882.809.809 0 00.88.176.81.81 0 00-.309-1.558zm0-10.999a.803.803 0 00-.746.499.815.815 0 00.175.882.8.8 0 00.88.176.812.812 0 00.262-1.32.807.807 0 00-.571-.237zm0-22.001a.804.804 0 00-.746.5.815.815 0 00.175.882.809.809 0 00.88.176.81.81 0 00-.309-1.558zm0 11a.804.804 0 00-.746.5.815.815 0 00.175.882.802.802 0 00.88.176.81.81 0 00-.309-1.558zm0-21.999a.807.807 0 00-.571 1.381.802.802 0 00.88.176.81.81 0 00-.309-1.557zm0-44.001a.804.804 0 00-.746.5.811.811 0 00.588 1.104.811.811 0 00.829-.344.81.81 0 00-.671-1.26zm-19 55a.807.807 0 00-.792.968.814.814 0 00.635.636.808.808 0 00.728-1.367.814.814 0 00-.571-.237zm0 11a.815.815 0 00-.746.5.815.815 0 00.175.882.8.8 0 00.88.176.81.81 0 00-.309-1.558zm0-21.999a.806.806 0 00-.792.967.806.806 0 001.599-.158.814.814 0 00-.807-.809zm0-11.001a.807.807 0 00-.792.968.814.814 0 00.635.636.808.808 0 00.728-1.367.814.814 0 00-.571-.237zm0-10.999a.806.806 0 00-.792.967.806.806 0 001.599-.158.814.814 0 00-.807-.809zm0 55a.806.806 0 00-.792.967.806.806 0 001.599-.158.823.823 0 00-.236-.573.814.814 0 00-.571-.236zm0 54.999a.807.807 0 00-.792.968.814.814 0 00.635.636.808.808 0 00.728-1.367.814.814 0 00-.571-.237zm0-10.999a.806.806 0 00-.792.967.806.806 0 001.599-.158.814.814 0 00-.807-.809zm0-22.001a.807.807 0 00-.792.968.814.814 0 00.635.636.809.809 0 10.157-1.604zm0-11a.807.807 0 00-.792.968.814.814 0 00.635.636.808.808 0 00.728-1.367.814.814 0 00-.571-.237zm0 22a.807.807 0 00-.792.968.814.814 0 00.635.636.808.808 0 00.728-1.367.814.814 0 00-.571-.237zm9.5-27.5a.807.807 0 00-.57 1.382.807.807 0 001.316-.882.802.802 0 00-.746-.5zm0 55a.807.807 0 00-.57 1.382.807.807 0 001.316-.882.813.813 0 00-.437-.438.8.8 0 00-.309-.062zm0-33a.807.807 0 00-.57 1.382.807.807 0 001.316-.882.802.802 0 00-.746-.5zm0 11a.81.81 0 10.309 1.558.807.807 0 00.437-1.058.813.813 0 00-.437-.438.8.8 0 00-.309-.062zm-9.5-104.5a.807.807 0 00-.792.968.814.814 0 00.635.636.808.808 0 00.728-1.367.814.814 0 00-.571-.237zm9.5 82.501a.807.807 0 00-.57 1.382.803.803 0 00.879.175.807.807 0 00.437-1.058.813.813 0 00-.437-.438.781.781 0 00-.309-.061zm0-22a.813.813 0 00-.791.967.813.813 0 00.634.636.807.807 0 00.903-1.104.813.813 0 00-.437-.438.781.781 0 00-.309-.061zm0 76.999a.814.814 0 00-.746.5.812.812 0 00.589 1.104.808.808 0 00.728-1.367.814.814 0 00-.571-.237zm-9.5-148.5a.807.807 0 00-.792.968.814.814 0 00.635.636.809.809 0 10.157-1.604zm9.5 181.5a.807.807 0 00-.57 1.382.798.798 0 00.879.176.814.814 0 00.499-.748.805.805 0 00-.237-.573.814.814 0 00-.571-.237zm0-10.999a.813.813 0 00-.791.967.813.813 0 00.634.636.807.807 0 00.903-1.104.813.813 0 00-.437-.438.781.781 0 00-.309-.061zm0-11.001a.807.807 0 00-.57 1.382.798.798 0 00.879.176.814.814 0 00.499-.748.805.805 0 00-.237-.573.814.814 0 00-.571-.237zm0-143a.81.81 0 10.309 1.558.807.807 0 00.437-1.058.813.813 0 00-.437-.438.8.8 0 00-.309-.062zm-66.5 16.5a.806.806 0 00-.746.5.815.815 0 00.175.882.808.808 0 101.142-1.144.81.81 0 00-.571-.238zm-9.5 71.5a.806.806 0 00-.745.5.815.815 0 00.175.882.802.802 0 00.879.176.814.814 0 00.499-.748.81.81 0 00-.808-.81zm0-76.999a.805.805 0 00-.791.967.81.81 0 001.101.59.81.81 0 00-.31-1.557zm0-33a.805.805 0 00-.791.967.813.813 0 00.634.636.807.807 0 00.965-.794.806.806 0 00-.808-.809zm0 43.999a.806.806 0 00-.745.5.815.815 0 00.175.882.802.802 0 00.879.176.807.807 0 00.262-1.32.806.806 0 00-.571-.238zm9.5 137.501a.805.805 0 00-.746.499.815.815 0 00.175.882.8.8 0 00.88.176.812.812 0 00.262-1.32.805.805 0 00-.571-.237zM248 453.69a.806.806 0 00-.745.5.815.815 0 00.175.882.807.807 0 001.378-.572.806.806 0 00-.237-.572.806.806 0 00-.571-.238zm0 33a.806.806 0 00-.745.5.815.815 0 00.175.882.802.802 0 00.879.176.814.814 0 00.499-.748.81.81 0 00-.808-.81zm9.5 82.5a.806.806 0 00-.746.5.815.815 0 00.175.882.8.8 0 00.88.176.81.81 0 00-.309-1.558zm28.5-93.499a.814.814 0 00-.792.967.806.806 0 001.599-.158.81.81 0 00-.807-.809zm-38-11.001a.806.806 0 00-.745.5.815.815 0 00.175.882.802.802 0 00.879.176.807.807 0 00.499-.748.81.81 0 00-.808-.81zm0 11.001a.805.805 0 00-.791.967.813.813 0 00.634.636.807.807 0 00.965-.794.806.806 0 00-.808-.809zm0-55.001a.815.815 0 00-.745.5.815.815 0 00.175.882.802.802 0 00.879.176.807.807 0 00.262-1.32.806.806 0 00-.571-.238zm9.5 71.5a.806.806 0 00-.746.5.815.815 0 00.175.882.808.808 0 101.142-1.144.81.81 0 00-.571-.238zm0-10.999a.805.805 0 00-.746.499.815.815 0 00.175.882.8.8 0 00.88.176.812.812 0 00.262-1.32.805.805 0 00-.571-.237zm0-11.001a.806.806 0 00-.746.5.815.815 0 00.175.882.8.8 0 00.88.176.81.81 0 00-.309-1.558zm0-11a.806.806 0 00-.746.5.815.815 0 00.175.882.808.808 0 101.142-1.144.806.806 0 00-.571-.238zm0-10.999a.814.814 0 00-.792.967.806.806 0 001.599-.158.81.81 0 00-.807-.809zm0 109.999a.806.806 0 00-.746.5.815.815 0 00.175.882.808.808 0 101.142-1.144.806.806 0 00-.571-.238zm0-22a.806.806 0 00-.746.5.815.815 0 00.175.882.808.808 0 101.142-1.144.81.81 0 00-.571-.238zm0 11.001a.814.814 0 00-.792.967.806.806 0 001.599-.158.81.81 0 00-.807-.809zm0-22a.814.814 0 00-.792.967.806.806 0 001.599-.158.81.81 0 00-.807-.809zm0-11.001a.806.806 0 00-.746.5.815.815 0 00.175.882.808.808 0 101.142-1.144.81.81 0 00-.571-.238zm0-11a.806.806 0 00-.746.5.811.811 0 00.588 1.104.811.811 0 00.829-.344.81.81 0 00-.671-1.26zm-9.5-93.5a.806.806 0 00-.745.5.815.815 0 00.175.882.802.802 0 00.879.176.814.814 0 00.499-.748.81.81 0 00-.808-.81zm-9.5 93.5a.814.814 0 00-.746.5.806.806 0 00.176.882.808.808 0 00.879.176.806.806 0 00.499-.748.805.805 0 00-.237-.573.814.814 0 00-.571-.237zm0 11a.807.807 0 00-.57 1.382.798.798 0 00.879.176.814.814 0 00.499-.748.805.805 0 00-.237-.573.814.814 0 00-.571-.237zm0-32.999a.8.8 0 00-.746.5.81.81 0 001.056 1.057.81.81 0 00-.31-1.557zm0 44a.813.813 0 00-.791.967.813.813 0 00.634.636.807.807 0 00.903-1.104.813.813 0 00-.437-.438.781.781 0 00-.309-.061zm0-33.001a.807.807 0 00-.57 1.382.798.798 0 00.879.176.807.807 0 00.437-1.058.813.813 0 00-.437-.438.8.8 0 00-.309-.062zm0 77a.81.81 0 10.309 1.558.807.807 0 00.437-1.058.813.813 0 00-.437-.438.8.8 0 00-.309-.062zm0-110a.807.807 0 00-.57 1.382.798.798 0 00.879.176.814.814 0 00.499-.748.805.805 0 00-.237-.573.798.798 0 00-.571-.237zm0 121.001a.8.8 0 00-.746.5.81.81 0 001.056 1.057.81.81 0 00-.31-1.557zm0-33a.807.807 0 00-.57 1.382.803.803 0 00.879.175.807.807 0 00.437-1.058.813.813 0 00-.437-.438.781.781 0 00-.309-.061zm0-11.001a.807.807 0 00-.57 1.382.798.798 0 00.879.176.814.814 0 00.499-.748.805.805 0 00-.237-.573.814.814 0 00-.571-.237zm0 22a.807.807 0 00-.57 1.382.798.798 0 00.879.176.814.814 0 00.499-.748.805.805 0 00-.237-.573.798.798 0 00-.571-.237zm9.5-16.5a.806.806 0 00-.745.5.815.815 0 00.175.882.802.802 0 00.879.176.807.807 0 00.262-1.32.806.806 0 00-.571-.238zm0 33.001a.805.805 0 00-.791.967.813.813 0 00.634.636.807.807 0 00.965-.794.806.806 0 00-.808-.809zm0-11.001a.806.806 0 00-.745.5.815.815 0 00.175.882.802.802 0 00.879.176.814.814 0 00.499-.748.81.81 0 00-.808-.81zm0-11a.806.806 0 00-.745.5.815.815 0 00.175.882.807.807 0 001.378-.572.806.806 0 00-.237-.572.806.806 0 00-.571-.238zm0-21.999a.805.805 0 00-.791.967.81.81 0 001.101.59.81.81 0 00-.31-1.557zm-9.5-82.5a.807.807 0 00-.57 1.382.803.803 0 00.879.175.807.807 0 00.437-1.058.813.813 0 00-.437-.438.781.781 0 00-.309-.061zm9.5 71.499a.815.815 0 00-.745.5.815.815 0 00.175.882.802.802 0 00.879.176.807.807 0 00.262-1.32.806.806 0 00-.571-.238zm-9.5-93.499a.813.813 0 00-.791.967.813.813 0 00.634.636.807.807 0 00.903-1.104.813.813 0 00-.437-.438.781.781 0 00-.309-.061zm0 10.999a.807.807 0 00-.57 1.382.798.798 0 00.879.176.814.814 0 00.499-.748.805.805 0 00-.237-.573.814.814 0 00-.571-.237zm9.5 148.5a.806.806 0 00-.745.5.815.815 0 00.175.882.802.802 0 00.879.176.814.814 0 00.499-.748.81.81 0 00-.808-.81zm-9.5-181.5a.814.814 0 00-.746.5.806.806 0 00.176.882.808.808 0 00.879.176.806.806 0 00.499-.748.805.805 0 00-.237-.573.814.814 0 00-.571-.237zm0 11a.807.807 0 00-.57 1.382.798.798 0 00.879.176.814.814 0 00.499-.748.805.805 0 00-.237-.573.814.814 0 00-.571-.237zm9.5 82.501a.805.805 0 00-.791.967.813.813 0 00.634.636.807.807 0 00.965-.794.806.806 0 00-.808-.809zm28.5-49.5a.807.807 0 00-.571 1.381.802.802 0 00.88.176.81.81 0 00-.309-1.557zm0 99a.807.807 0 00-.571 1.381.802.802 0 00.88.176.81.81 0 00-.309-1.557zm0-77.001a.804.804 0 00-.746.5.815.815 0 00.175.882.802.802 0 00.88.176.81.81 0 00-.309-1.558zm0-33a.804.804 0 00-.746.5.815.815 0 00.175.882.809.809 0 00.88.176.81.81 0 00-.309-1.558zm0-10.999a.807.807 0 00-.571 1.381.802.802 0 00.88.176.81.81 0 00-.309-1.557zm0 55a.803.803 0 00-.746.499.815.815 0 00.175.882.8.8 0 00.88.176.812.812 0 00.262-1.32.807.807 0 00-.571-.237zm0 10.999a.804.804 0 00-.746.5.815.815 0 00.175.882.809.809 0 00.88.176.81.81 0 00-.309-1.558zm0 33.001a.807.807 0 00-.571 1.381.802.802 0 00.88.176.81.81 0 00-.309-1.557zm0 10.999a.804.804 0 00-.746.5.815.815 0 00.175.882.809.809 0 00.88.176.81.81 0 00-.309-1.558zm0-33a.804.804 0 00-.746.5.811.811 0 00.588 1.104.811.811 0 00.829-.344.81.81 0 00-.671-1.26zm0-88a.804.804 0 00-.746.5.815.815 0 00.175.882.809.809 0 00.88.176.81.81 0 00-.309-1.558zm0 99a.804.804 0 00-.746.5.815.815 0 00.175.882.809.809 0 00.88.176.81.81 0 00-.309-1.558zm0-55a.804.804 0 00-.746.5.815.815 0 00.175.882.809.809 0 00.88.176.81.81 0 00-.309-1.558zm0-55a.804.804 0 00-.746.5.811.811 0 00.588 1.104.811.811 0 00.829-.344.81.81 0 00-.671-1.26zm9.5 115.5a.806.806 0 00-.746.5.815.815 0 00.175.882.8.8 0 00.88.176.81.81 0 00-.309-1.558zm0 11.001a.805.805 0 00-.746.499.815.815 0 00.175.882.8.8 0 00.88.176.812.812 0 00.262-1.32.805.805 0 00-.571-.237zm0-44.001a.806.806 0 00-.746.5.815.815 0 00.175.882.808.808 0 101.142-1.144.81.81 0 00-.571-.238zm0 11.001a.814.814 0 00-.792.967.806.806 0 001.599-.158.81.81 0 00-.807-.809zm0 10.999a.806.806 0 00-.746.5.815.815 0 00.175.882.808.808 0 101.142-1.144.806.806 0 00-.571-.238zm0 33a.806.806 0 00-.746.5.815.815 0 00.175.882.808.808 0 101.142-1.144.81.81 0 00-.571-.238zm0 33.001a.814.814 0 00-.792.967.806.806 0 001.599-.158.81.81 0 00-.807-.809zm0 10.999a.806.806 0 00-.746.5.815.815 0 00.175.882.808.808 0 101.142-1.144.81.81 0 00-.571-.238zm0-33a.806.806 0 00-.746.5.811.811 0 00.588 1.104.811.811 0 00.829-.344.81.81 0 00-.671-1.26zm0 11a.806.806 0 00-.746.5.815.815 0 00.175.882.808.808 0 101.142-1.144.81.81 0 00-.571-.238zm-19-11a.814.814 0 00-.746.5.812.812 0 00.589 1.104.808.808 0 00.728-1.367.814.814 0 00-.571-.237zm0-21.999a.8.8 0 00-.746.5.81.81 0 001.056 1.057.81.81 0 00-.31-1.557zm0 10.999a.807.807 0 00-.57 1.382.807.807 0 001.316-.882.813.813 0 00-.437-.438.8.8 0 00-.309-.062zm0-43.999a.807.807 0 00-.57 1.382.8.8 0 00.879.175.807.807 0 00.437-1.058.813.813 0 00-.437-.438.781.781 0 00-.309-.061zm0 10.999a.807.807 0 00-.57 1.382.807.807 0 001.316-.882.802.802 0 00-.746-.5zm-9.5-82.499a.814.814 0 00-.792.967.806.806 0 001.599-.158.81.81 0 00-.807-.809zm9.5 93.499a.81.81 0 10.309 1.558.807.807 0 00.437-1.058.813.813 0 00-.437-.438.8.8 0 00-.309-.062zm-9.5-104.5a.806.806 0 00-.746.5.815.815 0 00.175.882.808.808 0 101.142-1.144.81.81 0 00-.571-.238zm0-11a.806.806 0 00-.746.5.811.811 0 00.588 1.104.811.811 0 00.829-.344.81.81 0 00-.671-1.26zm9.5 159.5a.807.807 0 00-.57 1.382.807.807 0 001.316-.882.813.813 0 00-.437-.438.8.8 0 00-.309-.062zm0 11.001a.813.813 0 00-.791.967.813.813 0 00.634.636.807.807 0 00.903-1.104.813.813 0 00-.437-.438.781.781 0 00-.309-.061zm0 10.999a.807.807 0 00-.57 1.382.807.807 0 001.316-.882.802.802 0 00-.746-.5zm0-165a.81.81 0 10.309 1.558.807.807 0 00.437-1.058.813.813 0 00-.437-.438.8.8 0 00-.309-.062zm9.5 137.5a.804.804 0 00-.746.5.815.815 0 00.175.882.809.809 0 00.88.176.81.81 0 00-.309-1.558zM267 398.691a.807.807 0 00-.57 1.382.8.8 0 00.879.175.807.807 0 00.437-1.058.813.813 0 00-.437-.438.781.781 0 00-.309-.061zm0 10.999a.807.807 0 00-.57 1.382.807.807 0 001.316-.882.802.802 0 00-.746-.5zm9.5 159.5a.804.804 0 00-.746.5.815.815 0 00.175.882.802.802 0 00.88.176.81.81 0 00-.309-1.558zm0 11.001a.803.803 0 00-.746.499.815.815 0 00.175.882.8.8 0 00.88.176.812.812 0 00.262-1.32.807.807 0 00-.571-.237zM267 453.69a.814.814 0 00-.746.5.812.812 0 00.589 1.104.808.808 0 00.728-1.367.814.814 0 00-.571-.237zm0 11a.807.807 0 00-.57 1.382.807.807 0 001.316-.882.813.813 0 00-.437-.438.8.8 0 00-.309-.062zm0 11.001a.813.813 0 00-.791.967.813.813 0 00.634.636.807.807 0 00.903-1.104.813.813 0 00-.437-.438.781.781 0 00-.309-.061zm0 10.999a.807.807 0 00-.57 1.382.807.807 0 001.316-.882.802.802 0 00-.746-.5zm0-44a.807.807 0 00-.57 1.382.807.807 0 001.316-.882.813.813 0 00-.437-.438.8.8 0 00-.309-.062zm0-10.999a.8.8 0 00-.746.5.81.81 0 001.056 1.057.81.81 0 00-.31-1.557zm-28.5 38.499a.81.81 0 10.309 1.558.807.807 0 00.437-1.058.813.813 0 00-.437-.438.8.8 0 00-.309-.062zm171-33a.814.814 0 00-.746.5.806.806 0 00.176.882.798.798 0 00.879.176.814.814 0 00.499-.748.805.805 0 00-.237-.573.814.814 0 00-.571-.237zm0-22a.814.814 0 00-.746.5.806.806 0 00.176.882.798.798 0 00.879.176.814.814 0 00.499-.748.805.805 0 00-.237-.573.814.814 0 00-.571-.237zm0 11.001a.8.8 0 00-.448.136.806.806 0 00-.343.831.813.813 0 00.634.636.807.807 0 00.903-1.104.813.813 0 00-.437-.438.781.781 0 00-.309-.061zm0-22.001a.814.814 0 00-.746.5.806.806 0 00.176.882.808.808 0 00.879.176.806.806 0 00.499-.748.805.805 0 00-.237-.573.814.814 0 00-.571-.237zm9.5 181.5a.804.804 0 00-.746.5.815.815 0 00.175.882.809.809 0 00.88.176.81.81 0 00-.309-1.558zm0-10.999a.807.807 0 00-.571 1.381.802.802 0 00.88.176.81.81 0 00-.309-1.557zm-9.5-126.5a.814.814 0 00-.746.499.813.813 0 00.589 1.104.807.807 0 00.903-1.104.813.813 0 00-.437-.438.781.781 0 00-.309-.061zm0 43.999a.814.814 0 00-.746.5.806.806 0 00.176.882.798.798 0 00.879.176.807.807 0 00.437-1.058.813.813 0 00-.437-.438.8.8 0 00-.309-.062zm0 11a.814.814 0 00-.746.5.806.806 0 00.176.882.808.808 0 00.879.176.806.806 0 00.499-.748.805.805 0 00-.237-.573.814.814 0 00-.571-.237zm9.5 60.5a.804.804 0 00-.746.5.815.815 0 00.175.882.809.809 0 00.88.176.81.81 0 00-.309-1.558zm0-154a.804.804 0 00-.746.5.815.815 0 00.175.882.809.809 0 00.88.176.81.81 0 00-.309-1.558zm-9.5 49.5a.814.814 0 00-.746.5.806.806 0 00.176.882.798.798 0 00.879.176.814.814 0 00.499-.748.805.805 0 00-.237-.573.798.798 0 00-.571-.237zm0 11a.81.81 0 10.309 1.558.807.807 0 00.437-1.058.813.813 0 00-.437-.438.8.8 0 00-.309-.062zm9.5 49.5a.804.804 0 00-.746.5.815.815 0 00.175.882.802.802 0 00.88.176.81.81 0 00-.309-1.558zm0-77a.804.804 0 00-.746.5.815.815 0 00.175.882.809.809 0 00.88.176.81.81 0 00-.309-1.558zm0 11a.806.806 0 00-.746.5.811.811 0 00.588 1.104.811.811 0 00.829-.344.81.81 0 00-.671-1.26zm0 11a.804.804 0 00-.746.5.815.815 0 00.175.882.809.809 0 00.88.176.81.81 0 00-.309-1.558zm0-32.999a.803.803 0 00-.746.499.815.815 0 00.175.882.8.8 0 00.88.176.812.812 0 00.262-1.32.807.807 0 00-.571-.237zm0-11.001a.804.804 0 00-.746.5.815.815 0 00.175.882.802.802 0 00.88.176.81.81 0 00-.309-1.558zm0 55.001a.807.807 0 00-.571 1.381.802.802 0 00.88.176.81.81 0 00-.309-1.557zm0 65.999a.804.804 0 00-.746.5.815.815 0 00.175.882.809.809 0 00.88.176.81.81 0 00-.309-1.558zm-9.5-27.5a.814.814 0 00-.746.5.806.806 0 00.176.882.798.798 0 00.879.176.814.814 0 00.499-.748.805.805 0 00-.237-.573.814.814 0 00-.571-.237zm9.5-27.5a.804.804 0 00-.746.5.815.815 0 00.175.882.809.809 0 00.88.176.81.81 0 00-.309-1.558zm0 66a.806.806 0 00-.746.5.811.811 0 00.588 1.104.811.811 0 00.829-.344.81.81 0 00-.671-1.26zm0-21.999a.803.803 0 00-.746.499.815.815 0 00.175.882.8.8 0 00.88.176.812.812 0 00.262-1.32.807.807 0 00-.571-.237zm0-33a.807.807 0 00-.571 1.381.802.802 0 00.88.176.81.81 0 00-.309-1.557zm0 10.999a.804.804 0 00-.746.5.815.815 0 00.175.882.809.809 0 00.88.176.81.81 0 00-.309-1.558zm-9.5-27.499a.8.8 0 00-.746.5.81.81 0 001.056 1.057.81.81 0 00-.31-1.557zM400 519.69a.815.815 0 00-.746.5.815.815 0 00.175.882.8.8 0 00.88.176.81.81 0 00-.309-1.558zm0 22a.807.807 0 00-.792.968.821.821 0 00.221.414.8.8 0 00.88.176.81.81 0 00-.309-1.558zm0-33a.807.807 0 00-.792.968.821.821 0 00.221.414.8.8 0 00.88.176.806.806 0 00.498-.748.804.804 0 00-.498-.748.8.8 0 00-.309-.062zm0 22.001a.806.806 0 00-.792.967.818.818 0 00.222.415.8.8 0 00.879.175.807.807 0 00.437-1.058.814.814 0 00-.746-.499zm0-44.001a.807.807 0 00-.792.968.821.821 0 00.221.414.8.8 0 00.88.176.806.806 0 00.498-.748.804.804 0 00-.498-.748.8.8 0 00-.309-.062zm0-10.999a.806.806 0 00-.792.967.806.806 0 001.599-.158.804.804 0 00-.807-.809zm0 22a.806.806 0 00-.792.967.806.806 0 001.599-.158.804.804 0 00-.807-.809zm-9.5-93.501a.806.806 0 00-.746.5.811.811 0 00.588 1.104.811.811 0 00.829-.344.81.81 0 00-.671-1.26zm0 11a.804.804 0 00-.746.5.815.815 0 00.175.882.809.809 0 00.88.176.81.81 0 00-.309-1.558zm9.5 170.5a.807.807 0 00-.792.968.821.821 0 00.221.414.8.8 0 00.88.176.806.806 0 00.498-.748.804.804 0 00-.498-.748.8.8 0 00-.309-.062zm0-22a.807.807 0 00-.792.968.821.821 0 00.221.414.8.8 0 00.88.176.806.806 0 00.498-.748.804.804 0 00-.498-.748.8.8 0 00-.309-.062zm0-11a.807.807 0 00-.571 1.382.809.809 0 10.571-1.382zm9.5-27.499a.8.8 0 00-.448.136.806.806 0 00-.343.831.813.813 0 00.634.636.807.807 0 00.903-1.104.813.813 0 00-.437-.438.781.781 0 00-.309-.061zm-9.5 49.5a.806.806 0 00-.792.967.806.806 0 001.599-.158.804.804 0 00-.807-.809zm9.5-5.501a.81.81 0 10.309 1.558.807.807 0 00.437-1.058.813.813 0 00-.437-.438.8.8 0 00-.309-.062zm-9.5-104.5a.807.807 0 00-.792.968.821.821 0 00.221.414.8.8 0 00.88.176.81.81 0 00-.309-1.558zm9.5 115.501a.8.8 0 00-.746.5.81.81 0 001.056 1.057.81.81 0 00-.31-1.557zm0-44.001a.814.814 0 00-.746.5.806.806 0 00.176.882.798.798 0 00.879.176.814.814 0 00.499-.748.805.805 0 00-.237-.573.814.814 0 00-.571-.237zM400 398.691a.806.806 0 00-.792.967.806.806 0 001.599-.158.804.804 0 00-.807-.809zm-9.5 27.5a.807.807 0 00-.571 1.381.802.802 0 00.88.176.81.81 0 00-.309-1.557zm19 131.999a.814.814 0 00-.746.5.806.806 0 00.176.882.798.798 0 00.879.176.814.814 0 00.499-.748.805.805 0 00-.237-.573.798.798 0 00-.571-.237zm-9.5-115.5a.807.807 0 00-.792.968.821.821 0 00.221.414.8.8 0 00.88.176.81.81 0 00-.309-1.558zm0 11a.807.807 0 00-.571 1.382.809.809 0 10.571-1.382zm0-33a.815.815 0 00-.746.5.815.815 0 00.175.882.8.8 0 00.88.176.81.81 0 00-.309-1.558zm0 11.001a.806.806 0 00-.792.967.822.822 0 00.222.415.8.8 0 00.879.175.807.807 0 00.437-1.058.814.814 0 00-.746-.499zm0-22.001a.807.807 0 00-.792.968.821.821 0 00.221.414.8.8 0 00.88.176.806.806 0 00.498-.748.804.804 0 00-.498-.748.8.8 0 00-.309-.062zm9.5 137.501a.814.814 0 00-.746.499.806.806 0 00.176.882.798.798 0 00.879.176.807.807 0 00.437-1.058.813.813 0 00-.437-.438.781.781 0 00-.309-.061zm38 33a.803.803 0 00-.746.499.815.815 0 00.175.882.8.8 0 00.88.176.812.812 0 00.262-1.32.807.807 0 00-.571-.237zm0-11.001a.804.804 0 00-.746.5.815.815 0 00.175.882.802.802 0 00.88.176.81.81 0 00-.309-1.558zm-9.5-170.5a.81.81 0 10.309 1.558.807.807 0 00.437-1.058.813.813 0 00-.437-.438.8.8 0 00-.309-.062zm9.5 137.5a.804.804 0 00-.746.5.815.815 0 00.175.882.809.809 0 00.88.176.81.81 0 00-.309-1.558zm0 11.001a.807.807 0 00-.571 1.381.802.802 0 00.88.176.81.81 0 00-.309-1.557zM438 409.69a.814.814 0 00-.746.5.806.806 0 00.176.882.798.798 0 00.879.176.814.814 0 00.499-.748.805.805 0 00-.237-.573.798.798 0 00-.571-.237zm9.5 148.5a.804.804 0 00-.746.5.815.815 0 00.175.882.809.809 0 00.88.176.817.817 0 00.498-.748.809.809 0 00-.807-.81zm-9.5-93.5a.814.814 0 00-.746.5.806.806 0 00.176.882.798.798 0 00.879.176.814.814 0 00.499-.748.805.805 0 00-.237-.573.814.814 0 00-.571-.237zm0-44a.81.81 0 10.309 1.558.807.807 0 00.437-1.058.813.813 0 00-.437-.438.8.8 0 00-.309-.062zm0 55.001a.8.8 0 00-.448.136.806.806 0 00-.343.831.813.813 0 00.634.636.807.807 0 00.903-1.104.813.813 0 00-.437-.438.781.781 0 00-.309-.061zm0-22.001a.814.814 0 00-.746.5.806.806 0 00.176.882.808.808 0 00.879.176.806.806 0 00.499-.748.805.805 0 00-.237-.573.814.814 0 00-.571-.237zm0-11a.814.814 0 00-.746.5.806.806 0 00.176.882.798.798 0 00.879.176.807.807 0 00.437-1.058.813.813 0 00-.437-.438.8.8 0 00-.309-.062zm0-10.999a.8.8 0 00-.746.5.81.81 0 001.056 1.057.81.81 0 00-.31-1.557zm9.5-16.501a.804.804 0 00-.746.5.815.815 0 00.175.882.809.809 0 00.88.176.81.81 0 00-.309-1.558zm0 22a.804.804 0 00-.746.5.815.815 0 00.175.882.809.809 0 00.88.176.81.81 0 00-.309-1.558zm0 22a.804.804 0 00-.746.5.815.815 0 00.175.882.809.809 0 00.88.176.81.81 0 00-.309-1.558zm0-11a.804.804 0 00-.746.5.815.815 0 00.175.882.802.802 0 00.88.176.81.81 0 00-.309-1.558zm0-21.999a.807.807 0 00-.571 1.381.802.802 0 00.88.176.81.81 0 00-.309-1.557zM438 486.69a.814.814 0 00-.746.5.806.806 0 00.176.882.798.798 0 00.879.176.814.814 0 00.499-.748.805.805 0 00-.237-.573.814.814 0 00-.571-.237zm9.5 38.501a.807.807 0 00-.571 1.381.802.802 0 00.88.176.81.81 0 00-.309-1.557zm0-121.001a.806.806 0 00-.746.5.811.811 0 00.588 1.104.811.811 0 00.829-.344.81.81 0 00-.671-1.26zm0 99a.806.806 0 00-.746.5.811.811 0 00.588 1.104.811.811 0 00.829-.344.81.81 0 00-.671-1.26zm0-33a.804.804 0 00-.746.5.815.815 0 00.175.882.802.802 0 00.88.176.81.81 0 00-.309-1.558zm0 44a.804.804 0 00-.746.5.815.815 0 00.175.882.809.809 0 00.88.176.81.81 0 00-.309-1.558zm0-22a.804.804 0 00-.746.5.815.815 0 00.175.882.809.809 0 00.88.176.81.81 0 00-.309-1.558zm0-10.999a.803.803 0 00-.746.499.815.815 0 00.175.882.8.8 0 00.88.176.812.812 0 00.262-1.32.807.807 0 00-.571-.237zm-19-77.001a.807.807 0 00-.792.968.814.814 0 00.635.636.809.809 0 10.157-1.604zm0 77.001a.806.806 0 00-.792.967.822.822 0 00.222.415.8.8 0 00.879.175.807.807 0 00.437-1.058.814.814 0 00-.746-.499zm0 10.999a.807.807 0 00-.792.968.821.821 0 00.221.414.8.8 0 00.88.176.81.81 0 00-.309-1.558zm0 11a.807.807 0 00-.792.968.814.814 0 00.635.636.809.809 0 10.157-1.604zm0-33a.815.815 0 00-.746.5.815.815 0 00.175.882.8.8 0 00.88.176.81.81 0 00-.309-1.558zm0-11a.807.807 0 00-.792.968.821.821 0 00.221.414.8.8 0 00.88.176.806.806 0 00.498-.748.804.804 0 00-.498-.748.8.8 0 00-.309-.062zm0 55a.807.807 0 00-.792.968.821.821 0 00.221.414.8.8 0 00.88.176.806.806 0 00.498-.748.804.804 0 00-.498-.748.8.8 0 00-.309-.062zm0 22a.807.807 0 00-.792.968.821.821 0 00.221.414.8.8 0 00.88.176.806.806 0 00.498-.748.804.804 0 00-.498-.748.8.8 0 00-.309-.062zm0 33a.815.815 0 00-.746.5.815.815 0 00.175.882.8.8 0 00.88.176.81.81 0 00-.309-1.558zm9.5-71.5a.81.81 0 10.309 1.558.807.807 0 00.437-1.058.813.813 0 00-.437-.438.8.8 0 00-.309-.062zm-9.5 60.5a.807.807 0 00-.792.968.821.821 0 00.221.414.8.8 0 00.88.176.806.806 0 00.498-.748.804.804 0 00-.498-.748.8.8 0 00-.309-.062zm0-10.999a.806.806 0 00-.792.967.821.821 0 00.221.414.8.8 0 00.88.176.81.81 0 00-.309-1.557zm0-99.001a.815.815 0 00-.746.5.815.815 0 00.175.882.8.8 0 00.88.176.81.81 0 00-.309-1.558zm0 77.001a.806.806 0 00-.792.967.806.806 0 001.599-.158.804.804 0 00-.807-.809zm0 55a.806.806 0 00-.792.967.822.822 0 00.222.415.8.8 0 00.879.175.807.807 0 00.437-1.058.814.814 0 00-.746-.499zm9.5-16.501a.807.807 0 00-.57 1.382.798.798 0 00.879.176.814.814 0 00.499-.748.805.805 0 00-.237-.573.814.814 0 00-.571-.237zm0-22a.807.807 0 00-.57 1.382.798.798 0 00.879.176.807.807 0 00.437-1.058.813.813 0 00-.437-.438.8.8 0 00-.309-.062zm0 11a.814.814 0 00-.746.5.812.812 0 00.589 1.104.808.808 0 00.728-1.367.814.814 0 00-.571-.237zm0-21.999a.8.8 0 00-.746.5.813.813 0 00.589 1.103.811.811 0 00.829-.344.82.82 0 00.074-.76.813.813 0 00-.437-.438.781.781 0 00-.309-.061zm0-11.001a.81.81 0 10.309 1.558.807.807 0 00.437-1.058.813.813 0 00-.437-.438.8.8 0 00-.309-.062zm0-11a.807.807 0 00-.57 1.382.798.798 0 00.879.176.814.814 0 00.499-.748.805.805 0 00-.237-.573.798.798 0 00-.571-.237zm-9.5-82.499a.806.806 0 00-.792.967.806.806 0 001.599-.158.804.804 0 00-.807-.809zm9.5 148.5a.8.8 0 00-.448.136.806.806 0 00-.343.831.813.813 0 00.634.636.807.807 0 00.903-1.104.813.813 0 00-.437-.438.781.781 0 00-.309-.061zm-9.5-137.501a.807.807 0 00-.792.968.821.821 0 00.221.414.8.8 0 00.88.176.806.806 0 00.498-.748.804.804 0 00-.498-.748.8.8 0 00-.309-.062zm0-22a.807.807 0 00-.792.968.821.821 0 00.221.414.8.8 0 00.88.176.81.81 0 00-.309-1.558zm9.5 170.5a.814.814 0 00-.746.5.806.806 0 00.176.882.798.798 0 00.879.176.814.814 0 00.499-.748.805.805 0 00-.237-.573.814.814 0 00-.571-.237zm-19-186.999a.807.807 0 00-.571 1.381.802.802 0 00.88.176.81.81 0 00-.309-1.557zm-57 132a.803.803 0 00-.746.499.815.815 0 00.175.882.8.8 0 00.88.176.812.812 0 00.262-1.32.807.807 0 00-.571-.237zm0 54.999a.804.804 0 00-.746.5.815.815 0 00.175.882.809.809 0 00.88.176.81.81 0 00-.309-1.558zm0-10.999a.807.807 0 00-.571 1.381.802.802 0 00.88.176.81.81 0 00-.309-1.557zm-9.5-170.501a.814.814 0 00-.746.5.812.812 0 00.589 1.104.808.808 0 00.728-1.367.814.814 0 00-.571-.237zm0 11a.807.807 0 00-.57 1.382.798.798 0 00.879.176.814.814 0 00.499-.748.805.805 0 00-.237-.573.814.814 0 00-.571-.237zm9.5 148.5a.804.804 0 00-.746.5.815.815 0 00.175.882.809.809 0 00.88.176.81.81 0 00-.309-1.558zm0-11a.804.804 0 00-.746.5.811.811 0 00.588 1.104.811.811 0 00.829-.344.81.81 0 00-.671-1.26zm-9.5-93.5a.807.807 0 00-.57 1.382.798.798 0 00.879.176.814.814 0 00.499-.748.805.805 0 00-.237-.573.798.798 0 00-.571-.237zm0-32.999a.813.813 0 00-.791.967.813.813 0 00.634.636.807.807 0 00.903-1.104.813.813 0 00-.437-.438.781.781 0 00-.309-.061zm0 43.999a.81.81 0 10.309 1.558.807.807 0 00.437-1.058.813.813 0 00-.437-.438.8.8 0 00-.309-.062zm0 11.001a.8.8 0 00-.746.5.81.81 0 001.056 1.057.81.81 0 00-.31-1.557zm9.5 60.499a.804.804 0 00-.746.5.815.815 0 00.175.882.809.809 0 00.88.176.81.81 0 00-.309-1.558zm-9.5-49.5a.807.807 0 00-.57 1.382.798.798 0 00.879.176.807.807 0 00.437-1.058.813.813 0 00-.437-.438.8.8 0 00-.309-.062zm0-55a.807.807 0 00-.57 1.382.798.798 0 00.879.176.814.814 0 00.499-.748.805.805 0 00-.237-.573.814.814 0 00-.571-.237zm0 11.001a.807.807 0 00-.57 1.382.803.803 0 00.879.175.807.807 0 00.437-1.058.813.813 0 00-.437-.438.781.781 0 00-.309-.061zm9.5-5.501a.804.804 0 00-.746.5.815.815 0 00.175.882.809.809 0 00.88.176.81.81 0 00-.309-1.558zm0-10.999a.803.803 0 00-.746.499.815.815 0 00.175.882.8.8 0 00.88.176.812.812 0 00.262-1.32.807.807 0 00-.571-.237zm0 32.999a.804.804 0 00-.746.5.815.815 0 00.175.882.809.809 0 00.88.176.81.81 0 00-.309-1.558zm0-11a.804.804 0 00-.746.5.811.811 0 00.588 1.104.811.811 0 00.829-.344.81.81 0 00-.671-1.26zm0-44a.804.804 0 00-.746.5.815.815 0 00.175.882.809.809 0 00.88.176.81.81 0 00-.309-1.558zm0 11a.804.804 0 00-.746.5.815.815 0 00.175.882.802.802 0 00.88.176.81.81 0 00-.309-1.558zm-19 165a.807.807 0 00-.792.968.814.814 0 00.635.636.808.808 0 00.728-1.367.814.814 0 00-.571-.237zm19-77a.804.804 0 00-.746.5.815.815 0 00.175.882.809.809 0 00.88.176.81.81 0 00-.309-1.558zm0-32.999a.807.807 0 00-.571 1.381.802.802 0 00.88.176.81.81 0 00-.309-1.557zm0 43.999a.804.804 0 00-.746.5.815.815 0 00.175.882.802.802 0 00.88.176.81.81 0 00-.309-1.558zm0-21.999a.807.807 0 00-.571 1.381.802.802 0 00.88.176.81.81 0 00-.309-1.557zm0-11.001a.804.804 0 00-.746.5.815.815 0 00.175.882.809.809 0 00.88.176.81.81 0 00-.309-1.558zm-9.5 60.501a.807.807 0 00-.57 1.382.803.803 0 00.879.175.807.807 0 00.437-1.058.813.813 0 00-.437-.438.781.781 0 00-.309-.061zM343 486.69a.807.807 0 00-.792.968.814.814 0 00.635.636.808.808 0 00.728-1.367.814.814 0 00-.571-.237zm0 11.001a.806.806 0 00-.792.967.806.806 0 001.599-.158.804.804 0 00-.807-.809zm0 10.999a.807.807 0 00-.792.968.814.814 0 00.635.636.808.808 0 00.728-1.367.814.814 0 00-.571-.237zm0 11a.815.815 0 00-.746.5.815.815 0 00.175.882.8.8 0 00.88.176.81.81 0 00-.309-1.558zm0-43.999a.806.806 0 00-.792.967.806.806 0 001.599-.158.804.804 0 00-.807-.809zm0-11.001a.807.807 0 00-.792.968.814.814 0 00.635.636.808.808 0 00.728-1.367.814.814 0 00-.571-.237zm0 88a.807.807 0 00-.571 1.382.809.809 0 10.571-1.382zm0-21.999a.806.806 0 00-.792.967.818.818 0 00.222.415.8.8 0 00.879.175.807.807 0 00.437-1.058.814.814 0 00-.746-.499zm0 32.999a.807.807 0 00-.792.968.814.814 0 00.635.636.808.808 0 00.728-1.367.814.814 0 00-.571-.237zm0 11.001a.806.806 0 00-.792.967.806.806 0 001.599-.158.804.804 0 00-.807-.809zm0-33.001a.807.807 0 00-.792.968.814.814 0 00.635.636.808.808 0 00.728-1.367.814.814 0 00-.571-.237zm0-88a.807.807 0 00-.571 1.382.809.809 0 10.571-1.382zm0-11a.807.807 0 00-.792.968.814.814 0 00.635.636.808.808 0 00.728-1.367.814.814 0 00-.571-.237zm9.5 126.5a.81.81 0 10.309 1.558.807.807 0 00.437-1.058.813.813 0 00-.437-.438.8.8 0 00-.309-.062zm0-33a.807.807 0 00-.57 1.382.798.798 0 00.879.176.814.814 0 00.499-.748.805.805 0 00-.237-.573.814.814 0 00-.571-.237zm0-33a.814.814 0 00-.746.5.812.812 0 00.589 1.104.808.808 0 00.728-1.367.814.814 0 00-.571-.237zm9.5-104.499a.807.807 0 00-.571 1.381.802.802 0 00.88.176.81.81 0 00-.309-1.557zm-9.5 126.5a.813.813 0 00-.791.967.813.813 0 00.634.636.807.807 0 00.903-1.104.813.813 0 00-.437-.438.781.781 0 00-.309-.061zm0-11.001a.807.807 0 00-.57 1.382.798.798 0 00.879.176.814.814 0 00.499-.748.805.805 0 00-.237-.573.814.814 0 00-.571-.237zm0 44a.807.807 0 00-.57 1.382.798.798 0 00.879.176.814.814 0 00.499-.748.805.805 0 00-.237-.573.798.798 0 00-.571-.237zM343 431.691a.806.806 0 00-.792.967.818.818 0 00.222.415.8.8 0 00.879.175.807.807 0 00.437-1.058.814.814 0 00-.746-.499zm0-11.001a.815.815 0 00-.746.5.815.815 0 00.175.882.8.8 0 00.88.176.81.81 0 00-.309-1.558zm0-11a.807.807 0 00-.792.968.814.814 0 00.635.636.808.808 0 00.728-1.367.814.814 0 00-.571-.237zm0-10.999a.806.806 0 00-.792.967.806.806 0 001.599-.158.804.804 0 00-.807-.809zm9.5 181.5a.8.8 0 00-.746.5.81.81 0 001.056 1.057.81.81 0 00-.31-1.557zm19-33a.806.806 0 00-.792.967.806.806 0 001.599-.158.804.804 0 00-.807-.809zm9.5-115.5a.8.8 0 00-.746.5.81.81 0 001.056 1.057.81.81 0 00-.31-1.557zm0-11.001a.81.81 0 10.309 1.558.807.807 0 00.437-1.058.813.813 0 00-.437-.438.8.8 0 00-.309-.062zm0 33a.814.814 0 00-.746.5.806.806 0 00.176.882.808.808 0 00.879.176.806.806 0 00.499-.748.805.805 0 00-.237-.573.814.814 0 00-.571-.237zm0-11a.814.814 0 00-.746.5.806.806 0 00.176.882.798.798 0 00.879.176.807.807 0 00.437-1.058.813.813 0 00-.437-.438.8.8 0 00-.309-.062zm0-43.999a.814.814 0 00-.746.499.813.813 0 00.589 1.104.807.807 0 00.903-1.104.813.813 0 00-.437-.438.781.781 0 00-.309-.061zm0 10.999a.814.814 0 00-.746.5.806.806 0 00.176.882.798.798 0 00.879.176.814.814 0 00.499-.748.805.805 0 00-.237-.573.798.798 0 00-.571-.237zm0 110a.81.81 0 10.309 1.558.807.807 0 00.437-1.058.813.813 0 00-.437-.438.8.8 0 00-.309-.062zm0-11a.814.814 0 00-.746.5.806.806 0 00.176.882.798.798 0 00.879.176.814.814 0 00.499-.748.805.805 0 00-.237-.573.798.798 0 00-.571-.237zm9.5 71.501a.803.803 0 00-.746.499.815.815 0 00.175.882.8.8 0 00.88.176.812.812 0 00.262-1.32.807.807 0 00-.571-.237zM381 464.69a.814.814 0 00-.746.5.806.806 0 00.176.882.798.798 0 00.879.176.807.807 0 00.437-1.058.813.813 0 00-.437-.438.8.8 0 00-.309-.062zm0 33.001a.814.814 0 00-.746.499.813.813 0 00.589 1.104.807.807 0 00.903-1.104.813.813 0 00-.437-.438.781.781 0 00-.309-.061zm0-22a.8.8 0 00-.448.136.806.806 0 00-.343.831.813.813 0 00.634.636.807.807 0 00.903-1.104.813.813 0 00-.437-.438.781.781 0 00-.309-.061zm9.5 16.499a.804.804 0 00-.746.5.815.815 0 00.175.882.809.809 0 00.88.176.81.81 0 00-.309-1.558zm0-10.999a.803.803 0 00-.746.499.815.815 0 00.175.882.8.8 0 00.88.176.812.812 0 00.262-1.32.807.807 0 00-.571-.237zm-9.5 49.5a.8.8 0 00-.746.5.81.81 0 001.056 1.057.81.81 0 00-.31-1.557zm9.5-60.501a.804.804 0 00-.746.5.815.815 0 00.175.882.802.802 0 00.88.176.81.81 0 00-.309-1.558zm0 99a.804.804 0 00-.746.5.815.815 0 00.175.882.802.802 0 00.88.176.81.81 0 00-.309-1.558zm0-66a.806.806 0 00-.746.5.811.811 0 00.588 1.104.811.811 0 00.829-.344.81.81 0 00-.671-1.26zm0-54.999a.807.807 0 00-.571 1.381.802.802 0 00.88.176.81.81 0 00-.309-1.557zm0 10.999a.804.804 0 00-.746.5.815.815 0 00.175.882.809.809 0 00.88.176.81.81 0 00-.309-1.558zm0 88.001a.807.807 0 00-.571 1.381.802.802 0 00.88.176.81.81 0 00-.309-1.557zm0 10.999a.804.804 0 00-.746.5.815.815 0 00.175.882.809.809 0 00.88.176.81.81 0 00-.309-1.558zm0-32.999a.807.807 0 00-.571 1.381.802.802 0 00.88.176.81.81 0 00-.309-1.557zm0 10.999a.804.804 0 00-.746.5.815.815 0 00.175.882.809.809 0 00.88.176.81.81 0 00-.309-1.558zm0-22a.804.804 0 00-.746.5.815.815 0 00.175.882.809.809 0 00.88.176.81.81 0 00-.309-1.558zm-9.5-27.5a.814.814 0 00-.746.5.806.806 0 00.176.882.798.798 0 00.879.176.814.814 0 00.499-.748.805.805 0 00-.237-.573.814.814 0 00-.571-.237zm-9.5-16.5a.815.815 0 00-.746.5.815.815 0 00.175.882.8.8 0 00.88.176.81.81 0 00-.309-1.558zm0 66a.807.807 0 00-.792.968.814.814 0 00.635.636.808.808 0 00.728-1.367.814.814 0 00-.571-.237zm0 22a.807.807 0 00-.792.968.814.814 0 00.635.636.808.808 0 00.728-1.367.814.814 0 00-.571-.237zm19-121a.804.804 0 00-.746.5.815.815 0 00.175.882.809.809 0 00.88.176.81.81 0 00-.309-1.558zm-19 132a.815.815 0 00-.746.5.815.815 0 00.175.882.8.8 0 00.88.176.81.81 0 00-.309-1.558zm0-110a.807.807 0 00-.792.968.814.814 0 00.635.636.808.808 0 00.728-1.367.814.814 0 00-.571-.237zm0-10.999a.806.806 0 00-.792.967.806.806 0 001.599-.158.804.804 0 00-.807-.809zm0 65.999a.807.807 0 00-.792.968.814.814 0 00.635.636.808.808 0 00.728-1.367.814.814 0 00-.571-.237zm0-11a.807.807 0 00-.571 1.382.809.809 0 10.571-1.382zm0-21.999a.806.806 0 00-.792.967.818.818 0 00.222.415.8.8 0 00.879.175.807.807 0 00.437-1.058.814.814 0 00-.746-.499zm0 10.999a.807.807 0 00-.792.968.814.814 0 00.635.636.808.808 0 00.728-1.367.814.814 0 00-.571-.237zm9.5 49.5a.814.814 0 00-.746.5.806.806 0 00.176.882.798.798 0 00.879.176.807.807 0 00.437-1.058.813.813 0 00-.437-.438.8.8 0 00-.309-.062zm-9.5-115.499a.806.806 0 00-.792.967.806.806 0 001.599-.158.804.804 0 00-.807-.809zm9.5 148.5a.8.8 0 00-.448.136.806.806 0 00-.343.831.813.813 0 00.634.636.807.807 0 00.903-1.104.813.813 0 00-.437-.438.781.781 0 00-.309-.061zm-9.5 5.5a.806.806 0 00-.792.967.818.818 0 00.222.415.8.8 0 00.879.175.807.807 0 00.437-1.058.814.814 0 00-.746-.499zm9.5 5.499a.814.814 0 00-.746.5.806.806 0 00.176.882.798.798 0 00.879.176.814.814 0 00.499-.748.805.805 0 00-.237-.573.814.814 0 00-.571-.237zm0-33a.814.814 0 00-.746.5.806.806 0 00.176.882.808.808 0 00.879.176.806.806 0 00.499-.748.805.805 0 00-.237-.573.814.814 0 00-.571-.237zm0 11a.814.814 0 00-.746.5.806.806 0 00.176.882.798.798 0 00.879.176.814.814 0 00.499-.748.805.805 0 00-.237-.573.814.814 0 00-.571-.237zm-9.5-159.5a.807.807 0 00-.571 1.382.809.809 0 10.571-1.382zm0 33a.807.807 0 00-.792.968.814.814 0 00.635.636.808.808 0 00.728-1.367.814.814 0 00-.571-.237zm0 88.001a.806.806 0 00-.792.967.806.806 0 001.599-.158.804.804 0 00-.807-.809zm0-110.001a.807.807 0 00-.792.968.814.814 0 00.635.636.808.808 0 00.728-1.367.814.814 0 00-.571-.237zM107.11 592h-3.22L1 532.432v-1.865l105.865 61.29.245.143zm-95 0L1 585.567v1.864L8.89 592h3.22zm75.755-.143L1 541.567v1.865L84.891 592h3.22l-.246-.143zm-19 0L1 552.566v1.865L65.89 592h3.22l-.245-.143zm-38 0L1 574.567v1.865L27.89 592h3.22l-.245-.143zm19 0L1 563.567v1.864L46.89 592h3.22l-.245-.143z" fill="#63D0FF"/><path d="M122.89 394h3.22L229 453.568v1.865l-105.865-61.29-.245-.143zm95 0l11.11 6.433v-1.864L221.109 394h-3.219zm-75.755.143L229 444.433v-1.865L145.109 394h-3.22l.246.143zm19 0L229 433.434v-1.865L164.109 394h-3.22l.246.143zm38 0L229 411.433v-1.865L202.11 394h-3.221l.246.143zm-19 0L229 422.433v-1.864L183.109 394h-3.219l.245.143zM1.082 442.615L229 574.568v1.864l-.082-.048L1 444.432v-1.865l.082.048zM1 431.568v1.864l227.918 131.953.082.048v-1.865L1.082 431.616 1 431.568zm0 21.999v1.866l227.918 131.951.082.048v-1.863L1.082 453.615 1 453.567zm0-32.999v1.864l227.918 131.953.082.047v-1.864L1.082 420.616 1 420.568zm0-11v1.864l227.918 131.953.082.047v-1.864L1.082 409.616 1 409.568zm0-11v1.864l227.918 131.953.082.047v-1.864L1.082 398.615 1 398.568zM228 72.31a.808.808 0 00.792-.968.808.808 0 10-1.363.73.807.807 0 00.571.237zm0 11a.807.807 0 00.792-.968.808.808 0 10-1.363.73.807.807 0 00.571.238zm0-22a.808.808 0 00.792-.968.807.807 0 10-1.538.468.815.815 0 00.437.438c.098.04.203.062.309.061zm0 44a.807.807 0 00.792-.968.814.814 0 00-.635-.636.808.808 0 00-.728 1.367.814.814 0 00.571.237zm0-11a.808.808 0 00.792-.968.807.807 0 10-1.538.468.817.817 0 00.437.438c.098.04.203.062.309.061zm0-77a.808.808 0 00.792-.968.807.807 0 10-1.538.468.816.816 0 00.437.438c.098.04.203.061.309.061zm0 11a.808.808 0 00.792-.968.807.807 0 10-1.538.468.815.815 0 00.437.438c.098.04.203.062.309.062zm0 22a.808.808 0 00.792-.968.807.807 0 10-1.538.468.815.815 0 00.437.438c.098.04.203.062.309.062zm0-11a.808.808 0 00.792-.968.807.807 0 10-1.538.468.817.817 0 00.437.438c.098.04.203.062.309.062zm0 88a.807.807 0 00.792-.968.814.814 0 00-.635-.636.808.808 0 00-.728 1.367.814.814 0 00.571.237zm0 44a.815.815 0 00.746-.5.815.815 0 00-.175-.882.8.8 0 00-.88-.176.81.81 0 00.309 1.558zm0 11a.807.807 0 00.792-.968.814.814 0 00-.635-.636.808.808 0 00-.728 1.367.798.798 0 00.571.237zm0 10.999a.806.806 0 00.792-.967.806.806 0 00-1.599.158.804.804 0 00.807.809zm0-33a.806.806 0 00.792-.967.806.806 0 00-1.599.158.8.8 0 00.236.573.814.814 0 00.571.236zm0-21.999a.807.807 0 00.792-.968.814.814 0 00-.635-.636.809.809 0 10-.157 1.604zm0 11a.807.807 0 00.792-.968.814.814 0 00-.635-.636.808.808 0 00-.728 1.367.814.814 0 00.571.237zm0-143a.807.807 0 00.792-.968.807.807 0 10-1.538.468.816.816 0 00.437.438c.098.04.203.062.309.062zm0 109.999a.806.806 0 00.792-.967.806.806 0 00-1.599.158.804.804 0 00.807.809zm-85.5 82.501a.807.807 0 00.792-.968.821.821 0 00-.221-.414.8.8 0 00-.88-.176.81.81 0 00.309 1.558zm-19 0a.804.804 0 00.746-.5.815.815 0 00-.175-.882.809.809 0 00-.88-.176.81.81 0 00.309 1.558zm-19 0a.814.814 0 00.746-.5.806.806 0 00-.176-.882.798.798 0 00-.879-.176.807.807 0 00-.437 1.058.813.813 0 00.437.438.8.8 0 00.309.062zm-95 0a.806.806 0 00.746-.5.812.812 0 00-.588-1.104.81.81 0 10-.158 1.604zm171 0a.804.804 0 00.746-.5.815.815 0 00-.175-.882.809.809 0 00-.88-.176.81.81 0 00.309 1.558zm-152 0a.806.806 0 00.746-.5.812.812 0 00-.589-1.104.81.81 0 10-.157 1.604zm171 0a.806.806 0 00.746-.5.815.815 0 00-.175-.882.808.808 0 10-1.142 1.144.81.81 0 00.571.238zm-114 0a.806.806 0 00.746-.5.813.813 0 00-.589-1.104.81.81 0 10-.157 1.604zm76 0a.807.807 0 00.57-1.382.798.798 0 00-.879-.176.807.807 0 00-.437 1.058.813.813 0 00.437.438.8.8 0 00.309.062zm-95 0a.806.806 0 00.746-.5.812.812 0 00-.588-1.104.81.81 0 10-.158 1.604zm152 0a.807.807 0 00.57-1.382.798.798 0 00-.879-.176.807.807 0 00-.437 1.058.813.813 0 00.437.438.8.8 0 00.309.062zm-171 0a.806.806 0 00.745-.5.813.813 0 00-.588-1.104.81.81 0 10-.157 1.604zM152 83.31a.803.803 0 00.746-.5.814.814 0 00-.175-.882.809.809 0 00-.88-.176.812.812 0 00-.262 1.32.807.807 0 00.571.238zm0-66a.804.804 0 00.746-.5.814.814 0 00-.175-.882.808.808 0 00-.88-.176.81.81 0 00.309 1.557zm0 33a.804.804 0 00.746-.5.814.814 0 00-.175-.882.808.808 0 00-.88-.176.81.81 0 00.309 1.558zm0-22a.803.803 0 00.746-.5.814.814 0 00-.175-.882.808.808 0 10-1.142 1.144.807.807 0 00.571.238zm0 33a.803.803 0 00.746-.5.814.814 0 00-.175-.883.807.807 0 00-1.378.573.811.811 0 00.807.81zm0 11a.803.803 0 00.746-.5.814.814 0 00-.175-.882.808.808 0 00-1.242.122.809.809 0 00.671 1.26zm0-33a.803.803 0 00.746-.5.814.814 0 00-.175-.882.808.808 0 00-1.242.122.809.809 0 00.671 1.26zm0 153.999a.807.807 0 00.571-1.381.802.802 0 00-.88-.176.81.81 0 00.309 1.557zm-9.5-181.5a.807.807 0 00.792-.967.808.808 0 10-1.363.73.805.805 0 00.571.237zM152 182.31a.804.804 0 00.746-.5.815.815 0 00-.175-.882.809.809 0 00-.88-.176.81.81 0 00.309 1.558zm-9.5-148.5a.807.807 0 00.792-.968.815.815 0 00-.635-.636.804.804 0 00-.828.344.809.809 0 00.671 1.26zm9.5 137.5a.804.804 0 00.746-.5.815.815 0 00-.175-.882.802.802 0 00-.88-.176.81.81 0 00.309 1.558zm-9.5-148.5a.807.807 0 00.792-.968.807.807 0 10-1.538.468.816.816 0 00.437.438c.098.04.203.062.309.061zm9.5 137.499a.803.803 0 00.746-.499.815.815 0 00-.175-.882.8.8 0 00-.88-.176.812.812 0 00-.262 1.32.807.807 0 00.571.237zm0-44a.807.807 0 00.571-1.381.802.802 0 00-.88-.176.81.81 0 00.309 1.557zm0-22a.803.803 0 00.746-.499.814.814 0 00-.175-.882.808.808 0 10-1.142 1.144.807.807 0 00.571.237zm0 33.001a.804.804 0 00.746-.5.815.815 0 00-.175-.882.809.809 0 00-.88-.176.81.81 0 00.309 1.558zm0-22a.804.804 0 00.746-.5.815.815 0 00-.175-.882.809.809 0 00-.88-.176.81.81 0 00.309 1.558zm0 33a.804.804 0 00.746-.5.811.811 0 00-.588-1.104.811.811 0 00-.829.344.81.81 0 00.671 1.26zm0 11a.804.804 0 00.746-.5.815.815 0 00-.175-.882.809.809 0 00-.88-.176.81.81 0 00.309 1.558zm19 33a.806.806 0 00.746-.5.815.815 0 00-.175-.882.808.808 0 10-1.142 1.144.806.806 0 00.571.238zm-9.5-170.5a.808.808 0 10-.002-1.617.808.808 0 00.002 1.616zm0 22a.808.808 0 10-.002-1.617.808.808 0 00.002 1.617zm0 33a.808.808 0 10-.002-1.617.808.808 0 00.002 1.617zm0-11a.802.802 0 00.746-.5.808.808 0 00-1.418-.76.817.817 0 00-.074.76.8.8 0 00.437.438c.098.04.203.062.309.062zm0-11a.808.808 0 10-.002-1.617.808.808 0 00.002 1.616zm0-22a.802.802 0 00.746-.5.808.808 0 00-1.418-.76.817.817 0 00-.074.76.8.8 0 00.437.438c.098.04.203.062.309.061zm9.5 170.499a.814.814 0 00.792-.967.806.806 0 00-1.599.158.81.81 0 00.807.809zm0-43.999a.806.806 0 00.746-.5.815.815 0 00-.175-.882.808.808 0 10-1.142 1.144.81.81 0 00.571.238zm0-11a.806.806 0 00.746-.5.811.811 0 00-.588-1.104.811.811 0 00-.829.344.81.81 0 00.671 1.26zm0 33a.806.806 0 00.746-.5.815.815 0 00-.175-.882.8.8 0 00-.88-.176.81.81 0 00.309 1.558zm0-11.001a.805.805 0 00.746-.499.815.815 0 00-.175-.882.8.8 0 00-.88-.176.812.812 0 00-.262 1.32.805.805 0 00.571.237zm-9.5-49.5a.8.8 0 00.746-.5.81.81 0 00-1.056-1.057.81.81 0 00.31 1.557zm0 55a.813.813 0 00.791-.967.813.813 0 00-.634-.636.807.807 0 00-.903 1.104.813.813 0 00.437.438.781.781 0 00.309.061zm0-88a.809.809 0 10-.002-1.618.809.809 0 00.002 1.619zm0 99.001a.807.807 0 00.57-1.382.798.798 0 00-.879-.176.807.807 0 00-.437 1.058.813.813 0 00.437.438.8.8 0 00.309.062zm0-33.001a.807.807 0 00.57-1.382.8.8 0 00-.879-.175.807.807 0 00-.437 1.058.813.813 0 00.437.438.781.781 0 00.309.061zm0 44.001a.814.814 0 00.746-.5.806.806 0 00-.176-.882.808.808 0 00-.879-.176.806.806 0 00-.499.748.805.805 0 00.237.573.814.814 0 00.571.237zm0-33a.807.807 0 00.57-1.382.807.807 0 00-1.316.882.802.802 0 00.746.5zm0-55a.809.809 0 10-.002-1.618.809.809 0 00.002 1.617zm0-11a.803.803 0 00.746-.5.814.814 0 00-.175-.882.807.807 0 00-1.317.882.8.8 0 00.437.438c.098.04.203.062.309.062zm0 44a.807.807 0 00.57-1.382.807.807 0 00-1.316.882.802.802 0 00.746.5zm0-11a.81.81 0 10-.309-1.558.807.807 0 00-.437 1.058.813.813 0 00.437.438.8.8 0 00.309.062zM152 6.31a.803.803 0 00.746-.5.814.814 0 00-.175-.882.808.808 0 00-1.242.122.809.809 0 00.671 1.26zm-19 55a.808.808 0 10-.002-1.617.808.808 0 00.002 1.616zm-9.5-27.5a.803.803 0 00.746-.5.814.814 0 00-.175-.882.808.808 0 00-1.242.122.809.809 0 00.671 1.26zm0 44a.804.804 0 00.746-.5.814.814 0 00-.175-.882.808.808 0 10-1.142 1.144.807.807 0 00.571.238zm0-33a.804.804 0 00.746-.5.814.814 0 00-.175-.882.808.808 0 00-.88-.176.81.81 0 00.309 1.557zm0 11a.803.803 0 00.746-.5.814.814 0 00-.175-.882.808.808 0 00-1.242.122.81.81 0 00.671 1.26zm0-44a.803.803 0 00.746-.5.814.814 0 00-.175-.883.808.808 0 10-1.142 1.145.808.808 0 00.571.237zm0 55a.804.804 0 00.746-.5.814.814 0 00-.175-.882.809.809 0 00-.88-.176.81.81 0 00.309 1.558zm0-44a.803.803 0 00.746-.5.814.814 0 00-.175-.882.809.809 0 00-.88-.176.811.811 0 00.309 1.558zm9.5 170.499a.814.814 0 00.746-.499.813.813 0 00-.589-1.104.807.807 0 00-.903 1.104.813.813 0 00.437.438.781.781 0 00.309.061zm0-43.999a.81.81 0 10-.309-1.558.807.807 0 00-.437 1.058.813.813 0 00.437.438.8.8 0 00.309.062zm0-11a.814.814 0 00.746-.5.806.806 0 00-.176-.882.808.808 0 00-.879-.176.81.81 0 00.309 1.558zm0 44a.814.814 0 00.746-.5.806.806 0 00-.176-.882.798.798 0 00-.879-.176.814.814 0 00-.499.748.805.805 0 00.237.573.798.798 0 00.571.237zm0-22.001a.8.8 0 00.746-.5.81.81 0 00-1.056-1.057.81.81 0 00.31 1.557zm-9.5 5.5a.807.807 0 00.571-1.381.802.802 0 00-.88-.176.81.81 0 00.309 1.557zm0-77a.803.803 0 00.746-.499.814.814 0 00-.175-.882.808.808 0 00-1.242.122.809.809 0 00.671 1.26zm0 88.001a.804.804 0 00.746-.5.815.815 0 00-.175-.882.809.809 0 00-.88-.176.81.81 0 00.309 1.558zm9.5-49.5a.807.807 0 00.57-1.382.798.798 0 00-.879-.176.807.807 0 00-.437 1.058.813.813 0 00.437.438.8.8 0 00.309.062zm9.5-82.5a.808.808 0 00.792-.968.807.807 0 10-1.538.468.817.817 0 00.437.438c.098.04.203.062.309.062zm28.5 82.5a.806.806 0 00.746-.5.815.815 0 00-.175-.882.808.808 0 10-1.142 1.144.81.81 0 00.571.238zm-47.5 27.5a.804.804 0 00.746-.5.815.815 0 00-.175-.882.809.809 0 00-.88-.176.81.81 0 00.309 1.558zm0-55a.803.803 0 00.746-.5.814.814 0 00-.175-.882.809.809 0 00-.88-.176.812.812 0 00-.262 1.32.807.807 0 00.571.237zm0 10.999a.803.803 0 00.746-.499.815.815 0 00-.175-.883.806.806 0 00-1.378.573.809.809 0 00.807.809zm0 22.001a.804.804 0 00.746-.5.815.815 0 00-.175-.882.809.809 0 00-.88-.176.81.81 0 00.309 1.558zm0-11a.804.804 0 00.746-.5.815.815 0 00-.175-.882.802.802 0 00-.88-.176.81.81 0 00.309 1.558zm0 21.999a.807.807 0 00.571-1.381.802.802 0 00-.88-.176.81.81 0 00.309 1.557zm0 44.001a.806.806 0 00.746-.5.811.811 0 00-.588-1.104.811.811 0 00-.829.344.81.81 0 00.671 1.26zm19-55a.807.807 0 00.792-.968.814.814 0 00-.635-.636.808.808 0 00-.728 1.367.814.814 0 00.571.237zm0-11a.815.815 0 00.746-.5.815.815 0 00-.175-.882.8.8 0 00-.88-.176.81.81 0 00.309 1.558zm0 21.999a.806.806 0 00.792-.967.806.806 0 00-1.599.158.804.804 0 00.807.809zm0 11.001a.807.807 0 00.792-.968.814.814 0 00-.635-.636.808.808 0 00-.728 1.367.814.814 0 00.571.237zm0 10.999a.806.806 0 00.792-.967.806.806 0 00-1.599.158.804.804 0 00.807.809zm0-55a.806.806 0 00.792-.967.806.806 0 00-1.599.158.823.823 0 00.236.573.814.814 0 00.571.236zm0-55a.808.808 0 00.792-.967.807.807 0 10-1.538.468.816.816 0 00.437.438c.098.04.203.062.309.062zm0 11a.808.808 0 00.792-.967.807.807 0 10-1.538.468.816.816 0 00.437.438c.098.04.203.061.309.061zm0 22a.808.808 0 10-.001-1.616.808.808 0 00.001 1.617zm0 11a.807.807 0 00.792-.967.815.815 0 00-.635-.636.804.804 0 00-.828.344.809.809 0 00.671 1.26zm0-22a.808.808 0 00.792-.967.807.807 0 10-1.538.468.815.815 0 00.437.438c.098.04.203.062.309.062zM133 105.31a.807.807 0 00.57-1.382.807.807 0 00-1.316.882.813.813 0 00.437.438.8.8 0 00.309.062zm0-55a.809.809 0 10-.002-1.618.809.809 0 00.002 1.617zm0 33a.808.808 0 10-.002-1.617.808.808 0 00.002 1.617zm0-11a.802.802 0 00.746-.5.808.808 0 00-1.418-.76.817.817 0 00-.074.76.8.8 0 00.437.438c.098.04.203.062.309.061zm9.5 104.5a.807.807 0 00.792-.968.821.821 0 00-.221-.414.8.8 0 00-.88-.176.81.81 0 00.309 1.558zm-9.5-82.5a.808.808 0 10-.002-1.617.808.808 0 00.002 1.617zm0 21.999a.813.813 0 00.791-.967.813.813 0 00-.634-.636.807.807 0 00-.903 1.104.813.813 0 00.437.438.781.781 0 00.309.061zm0-77a.815.815 0 00.746-.5.814.814 0 00-.175-.882.807.807 0 00-1.317.883.8.8 0 00.437.438c.098.04.203.062.309.062zm9.5 148.501a.807.807 0 00.571-1.382.809.809 0 10-.571 1.382zM133 6.31a.809.809 0 10-.002-1.618A.809.809 0 00133 6.31zm0 11a.809.809 0 10-.002-1.618.809.809 0 00.002 1.618zm0 11a.809.809 0 10-.002-1.618.809.809 0 00.002 1.618zm0 143a.81.81 0 10-.309-1.558.807.807 0 00-.437 1.058.813.813 0 00.437.438.8.8 0 00.309.062zm66.5-16.5a.806.806 0 00.746-.5.815.815 0 00-.175-.882.808.808 0 10-1.142 1.144.81.81 0 00.571.238zm9.5-71.5a.806.806 0 00.791-.968.808.808 0 00-1.463-.292.809.809 0 00.672 1.26zm0 76.999a.805.805 0 00.791-.967.81.81 0 00-1.101-.59.81.81 0 00.31 1.557zm0 33a.805.805 0 00.791-.967.813.813 0 00-.634-.636.807.807 0 00-.965.794.806.806 0 00.808.809zm0-43.999a.806.806 0 00.745-.5.815.815 0 00-.175-.882.802.802 0 00-.879-.176.807.807 0 00-.262 1.32.806.806 0 00.571.238zm-9.5-137.5a.806.806 0 00.746-.5.814.814 0 00-.175-.883.808.808 0 10-1.142 1.145.807.807 0 00.571.237zm9.5 126.5a.806.806 0 00.745-.5.815.815 0 00-.175-.882.807.807 0 00-1.378.572c0 .215.085.421.237.572a.806.806 0 00.571.238zm0-33a.806.806 0 00.745-.5.815.815 0 00-.175-.882.802.802 0 00-.879-.176.814.814 0 00-.499.748.81.81 0 00.808.81zm-9.5-82.5a.805.805 0 00.746-.5.814.814 0 00-.175-.882.808.808 0 10-1.142 1.144.807.807 0 00.571.238zM171 116.308a.814.814 0 00.792-.967.806.806 0 00-1.599.158.81.81 0 00.807.809zm38 11.001a.806.806 0 00.745-.5.815.815 0 00-.175-.882.802.802 0 00-.879-.176.807.807 0 00-.499.748.81.81 0 00.808.81zm0-11.001a.805.805 0 00.791-.967.813.813 0 00-.634-.636.807.807 0 00-.965.794.806.806 0 00.808.809zm0 55.001a.815.815 0 00.745-.5.815.815 0 00-.175-.882.802.802 0 00-.879-.176.807.807 0 00-.262 1.32.806.806 0 00.571.238zm-9.5-71.5a.807.807 0 00.792-.968.809.809 0 00-1.463-.292.809.809 0 00.671 1.26zm0 10.999a.805.805 0 00.746-.499.815.815 0 00-.175-.882.8.8 0 00-.88-.176.812.812 0 00-.262 1.32.805.805 0 00.571.237zm0 11.001a.806.806 0 00.746-.5.815.815 0 00-.175-.882.8.8 0 00-.88-.176.81.81 0 00.309 1.558zm0 11a.806.806 0 00.746-.5.815.815 0 00-.175-.882.808.808 0 10-1.142 1.144.806.806 0 00.571.238zm0 10.999a.814.814 0 00.792-.967.806.806 0 00-1.599.158.81.81 0 00.807.809zm0-110a.806.806 0 00.746-.499.814.814 0 00-.175-.882.808.808 0 10-1.142 1.144.807.807 0 00.571.238zm0 22a.806.806 0 00.746-.499.814.814 0 00-.175-.882.807.807 0 10-1.142 1.144.807.807 0 00.571.238zm0-11a.806.806 0 00.746-.499.814.814 0 00-.175-.882.807.807 0 10-1.142 1.144.807.807 0 00.571.237zm0 22a.807.807 0 00.792-.967.809.809 0 00-1.463-.292.809.809 0 00.671 1.26zm0 11a.807.807 0 00.792-.967.809.809 0 00-1.463-.292.809.809 0 00.671 1.26zm0 11a.806.806 0 00.746-.499.813.813 0 00-.175-.882.808.808 0 00-1.242.122.809.809 0 00.671 1.26zm9.5 93.501a.806.806 0 00.745-.5.815.815 0 00-.175-.882.802.802 0 00-.879-.176.814.814 0 00-.499.748.81.81 0 00.808.81zm9.5-93.5a.815.815 0 00.746-.5.814.814 0 00-.175-.882.807.807 0 00-1.317.882.8.8 0 00.437.438c.098.04.203.062.309.062zm0-11a.808.808 0 10-.002-1.617.808.808 0 00.002 1.617zm0 32.999a.8.8 0 00.746-.5.81.81 0 00-.589-1.103.807.807 0 00-.903 1.104.813.813 0 00.437.438.781.781 0 00.309.061zm0-44a.809.809 0 10-.002-1.618.809.809 0 00.002 1.618zm0 33a.809.809 0 10-.002-1.618.809.809 0 00.002 1.619zm0-77a.802.802 0 00.746-.5.808.808 0 00-1.418-.76.817.817 0 00-.074.76.8.8 0 00.437.439c.098.04.203.062.309.061zm0 110.001a.807.807 0 00.57-1.382.807.807 0 00-1.316.882.802.802 0 00.746.5zm0-121a.808.808 0 10-.002-1.617.808.808 0 00.002 1.616zm0 33a.808.808 0 10-.002-1.617.808.808 0 00.002 1.616zm0 11a.802.802 0 00.746-.5.808.808 0 00-1.418-.76.817.817 0 00-.074.76.8.8 0 00.437.438c.098.04.203.062.309.062zm0-22a.808.808 0 10-.002-1.617.808.808 0 00.002 1.617zm-9.5 16.5a.807.807 0 00.791-.968.808.808 0 00-1.463-.292.809.809 0 00.672 1.26zm0-33a.807.807 0 00.791-.968.808.808 0 00-1.463-.292.809.809 0 00.672 1.26zm0 11a.807.807 0 00.791-.968.808.808 0 00-1.463-.292.809.809 0 00.672 1.26zm0 11a.807.807 0 00.791-.968.808.808 0 00-1.463-.292.809.809 0 00.672 1.26zm0 22a.806.806 0 00.791-.968.808.808 0 10-1.362.73.805.805 0 00.571.237zm9.5 82.499a.807.807 0 00.57-1.382.8.8 0 00-.879-.175.807.807 0 00-.437 1.058.813.813 0 00.437.438.781.781 0 00.309.061zm-9.5-71.5a.807.807 0 00.791-.967.808.808 0 00-1.463-.292.809.809 0 00.672 1.26zm9.5 93.5a.813.813 0 00.791-.967.813.813 0 00-.634-.636.807.807 0 00-.903 1.104.813.813 0 00.437.438.781.781 0 00.309.061zm0-10.999a.807.807 0 00.57-1.382.807.807 0 00-1.316.882.802.802 0 00.746.5zM209 6.31a.807.807 0 00.791-.968.808.808 0 00-1.463-.292.809.809 0 00.672 1.26zm9.5 181.5a.814.814 0 00.746-.5.806.806 0 00-.176-.882.808.808 0 00-.879-.176.806.806 0 00-.499.748.805.805 0 00.237.573.814.814 0 00.571.237zm0-11a.807.807 0 00.57-1.382.798.798 0 00-.879-.176.814.814 0 00-.499.748.805.805 0 00.237.573.814.814 0 00.571.237zm-9.5-82.5a.807.807 0 00.791-.968.808.808 0 00-1.463-.292.809.809 0 00.672 1.26zm-28.5 49.499a.807.807 0 00.571-1.381.802.802 0 00-.88-.176.81.81 0 00.309 1.557zm0-99a.803.803 0 00.746-.499.814.814 0 00-.175-.882.808.808 0 10-1.142 1.144.807.807 0 00.571.237zm0 77.001a.804.804 0 00.746-.5.815.815 0 00-.175-.882.802.802 0 00-.88-.176.81.81 0 00.309 1.558zm0 33a.804.804 0 00.746-.5.815.815 0 00-.175-.882.809.809 0 00-.88-.176.81.81 0 00.309 1.558zm0 10.999a.807.807 0 00.571-1.381.802.802 0 00-.88-.176.81.81 0 00.309 1.557zm0-55a.803.803 0 00.746-.499.815.815 0 00-.175-.882.8.8 0 00-.88-.176.812.812 0 00-.262 1.32.807.807 0 00.571.237zm0-11a.804.804 0 00.746-.499.814.814 0 00-.175-.882.809.809 0 00-.88-.176.812.812 0 00-.262 1.32.807.807 0 00.571.238zm0-33a.804.804 0 00.746-.5.814.814 0 00-.175-.881.808.808 0 00-.88-.176.81.81 0 00.309 1.558zm0-11a.803.803 0 00.746-.499.814.814 0 00-.175-.882.808.808 0 00-1.242.122.81.81 0 00.671 1.26zm0 33a.803.803 0 00.746-.499.814.814 0 00-.175-.882.808.808 0 00-1.242.122.809.809 0 00.671 1.26zm0 88.001a.804.804 0 00.746-.5.815.815 0 00-.175-.882.809.809 0 00-.88-.176.81.81 0 00.309 1.558zm0-99a.804.804 0 00.746-.5.814.814 0 00-.175-.882.808.808 0 10-1.142 1.144.807.807 0 00.571.238zm0 55a.804.804 0 00.746-.5.815.815 0 00-.175-.882.809.809 0 00-.88-.176.81.81 0 00.309 1.558zm0 55a.804.804 0 00.746-.5.811.811 0 00-.588-1.104.811.811 0 00-.829.344.81.81 0 00.671 1.26zM171 72.31a.806.806 0 00.746-.5.814.814 0 00-.175-.882.808.808 0 10-1.142 1.144.807.807 0 00.571.237zm0-11a.806.806 0 00.746-.5.814.814 0 00-.175-.883.808.808 0 10-1.142 1.145.807.807 0 00.571.237zm0 44a.806.806 0 00.746-.5.815.815 0 00-.175-.882.808.808 0 10-1.142 1.144.81.81 0 00.571.238zm0-11a.807.807 0 00.792-.968.809.809 0 00-1.463-.292.809.809 0 00.671 1.26zm0-11a.806.806 0 00.746-.5.814.814 0 00-.175-.882.808.808 0 10-1.142 1.144.807.807 0 00.571.238zm0-33a.807.807 0 00.792-.968.81.81 0 00-1.101-.59.809.809 0 00.309 1.558zm0-33a.807.807 0 00.792-.968.809.809 0 00-1.463-.292.809.809 0 00.671 1.26zm0-11a.806.806 0 00.746-.5.814.814 0 00-.175-.882.807.807 0 10-1.142 1.144.807.807 0 00.571.238zm0 33a.806.806 0 00.746-.5.814.814 0 00-.175-.882.808.808 0 00-1.242.122.809.809 0 00.671 1.26zm0-11a.807.807 0 00.792-.968.809.809 0 00-1.463-.292.809.809 0 00.671 1.26zm19 11a.815.815 0 00.746-.5.814.814 0 00-.175-.882.807.807 0 00-1.317.882.8.8 0 00.437.438c.098.04.203.062.309.062zm0 22a.808.808 0 10-.002-1.617.808.808 0 00.002 1.616zm0-11a.809.809 0 10-.002-1.618.809.809 0 00.002 1.618zm0 44a.808.808 0 10-.002-1.617.808.808 0 00.002 1.617zm0-11a.808.808 0 10-.002-1.617.808.808 0 00.002 1.617zm9.5 82.499a.814.814 0 00.792-.967.806.806 0 00-1.599.158.81.81 0 00.807.809zm-9.5-93.5a.809.809 0 10-.808-.81.804.804 0 00.237.574.807.807 0 00.571.237zm9.5 104.501a.806.806 0 00.746-.5.815.815 0 00-.175-.882.808.808 0 10-1.142 1.144.81.81 0 00.571.238zm0 11a.806.806 0 00.746-.5.811.811 0 00-.588-1.104.811.811 0 00-.829.344.81.81 0 00.671 1.26zM190 28.31a.809.809 0 10-.002-1.618.809.809 0 00.002 1.618zm0-11a.809.809 0 10-.002-1.618.809.809 0 00.002 1.618zm0-11a.809.809 0 10-.002-1.618A.809.809 0 00190 6.31zm0 165a.81.81 0 10-.309-1.558.807.807 0 00-.437 1.058.813.813 0 00.437.438.8.8 0 00.309.062zm-9.5-137.5a.803.803 0 00.746-.5.814.814 0 00-.175-.882.809.809 0 00-.88-.176.811.811 0 00.309 1.558zm9.5 159.499a.807.807 0 00.57-1.382.803.803 0 00-.879-.175.807.807 0 00-.437 1.058.813.813 0 00.437.438.781.781 0 00.309.061zm0-10.999a.807.807 0 00.57-1.382.798.798 0 00-.879-.176.814.814 0 00-.499.748.805.805 0 00.237.573.798.798 0 00.571.237zm-9.5-159.5a.803.803 0 00.746-.5.814.814 0 00-.175-.882.809.809 0 00-.88-.176.811.811 0 00.309 1.558zm0-11a.803.803 0 00.746-.5.814.814 0 00-.175-.883.808.808 0 10-1.142 1.145.808.808 0 00.571.237zm9.5 126.5a.814.814 0 00.746-.5.812.812 0 00-.589-1.104.808.808 0 00-.728 1.367.814.814 0 00.571.237zm0-11a.807.807 0 00.57-1.382.807.807 0 00-1.316.882.813.813 0 00.437.438.8.8 0 00.309.062zm0-11.001a.813.813 0 00.791-.967.813.813 0 00-.634-.636.807.807 0 00-.903 1.104.813.813 0 00.437.438.781.781 0 00.309.061zm0-10.999a.807.807 0 00.57-1.382.807.807 0 00-1.316.882.802.802 0 00.746.5zm0 44a.81.81 0 10-.309-1.558.807.807 0 00-.437 1.058.813.813 0 00.437.438.8.8 0 00.309.062zm0 10.999a.8.8 0 00.746-.5.81.81 0 00-1.056-1.057.81.81 0 00.31 1.557zm28.5-38.499a.81.81 0 10-.309-1.558.807.807 0 00-.437 1.058.813.813 0 00.437.438.8.8 0 00.309.062zm-171 33a.806.806 0 00.745-.5.813.813 0 00-.588-1.104.81.81 0 10-.157 1.604zm0 22a.806.806 0 00.745-.5.813.813 0 00-.588-1.104.81.81 0 10-.157 1.604zm0-11.001a.805.805 0 00.745-.499.813.813 0 00-.588-1.104.81.81 0 10-.157 1.603zm0 22.001a.806.806 0 00.745-.5.812.812 0 00-.588-1.104.81.81 0 10-.157 1.604zM38 6.31a.806.806 0 00.746-.5.812.812 0 00-.588-1.104.805.805 0 00-.965.794.811.811 0 00.807.81zm0 11a.805.805 0 00.746-.5.812.812 0 00-.588-1.104.806.806 0 00-.965.794.811.811 0 00.807.81zm9.5 126.499a.804.804 0 00.745-.499.813.813 0 00-.588-1.104.81.81 0 10-.157 1.603zm0-44a.805.805 0 00.745-.5.812.812 0 00-.588-1.103.805.805 0 00-.965.794.81.81 0 00.808.81zm0-11a.806.806 0 00.791-.967.81.81 0 00-.634-.636.804.804 0 00-.828.344.81.81 0 00.67 1.26zM38 28.31a.806.806 0 00.792-.967.81.81 0 00-1.1-.59.807.807 0 00-.5.748.811.811 0 00.808.81zm0 154.001a.806.806 0 00.746-.5.812.812 0 00-.588-1.104.81.81 0 10-.158 1.604zm9.5-49.5a.805.805 0 00.745-.5.813.813 0 00-.588-1.104.81.81 0 10-.157 1.604zm0-11a.813.813 0 00.745-.5.813.813 0 00-.588-1.104.809.809 0 10-.157 1.604zM38 72.31a.806.806 0 00.746-.5.812.812 0 00-.588-1.104.805.805 0 00-.83.344.812.812 0 00.672 1.26zm0 77a.806.806 0 00.746-.5.812.812 0 00-.588-1.104.81.81 0 10-.158 1.604zm0-11a.806.806 0 00.746-.5.809.809 0 00-1.417-.76.813.813 0 00.1 1.022.806.806 0 00.57.238zm0-11a.806.806 0 00.746-.5.812.812 0 00-.588-1.104.81.81 0 10-.158 1.604zm0 32.999a.805.805 0 00.792-.967.806.806 0 00-1.6.158.808.808 0 00.808.809zm0 11.001a.806.806 0 00.746-.5.812.812 0 00-.588-1.104.81.81 0 10-.158 1.604zm0-55.001a.809.809 0 10-.67-1.259.812.812 0 00.1 1.022.805.805 0 00.57.237zm0-66a.805.805 0 00.746-.499.812.812 0 00-.588-1.104.806.806 0 00-.965.794.811.811 0 00.807.81zm9.5 27.5a.806.806 0 00.745-.5.811.811 0 00-.588-1.103.805.805 0 00-.965.794.81.81 0 00.808.81zM38 105.31a.806.806 0 00.746-.5.813.813 0 00-.175-.882.807.807 0 10-1.142 1.144.81.81 0 00.57.238zm0-66a.806.806 0 00.746-.5.811.811 0 00-.588-1.104.806.806 0 00-.965.794.812.812 0 00.807.81zm0 22a.806.806 0 00.792-.968.81.81 0 00-1.101-.59.808.808 0 00-.498.748.81.81 0 00.807.81zm0 33a.806.806 0 00.792-.968.81.81 0 00-1.1-.59.807.807 0 00-.5.748.811.811 0 00.808.81zm0-11a.805.805 0 00.746-.5.812.812 0 00-.588-1.104.805.805 0 00-.83.344.811.811 0 00.672 1.26zm9.5 27.499a.805.805 0 00.791-.967.812.812 0 00-.634-.636.81.81 0 10-.157 1.603zm9.5-38.5a.806.806 0 00.792-.967.81.81 0 00-.635-.636.805.805 0 00-.964.794.811.811 0 00.807.81zm0-22a.805.805 0 00.746-.5.81.81 0 00-.589-1.103.805.805 0 00-.964.794.811.811 0 00.807.81zm0 33a.805.805 0 00.746-.5.812.812 0 00-.589-1.103.804.804 0 00-.828.344.81.81 0 00.671 1.26zm0-22a.806.806 0 00.746-.5.811.811 0 00-.589-1.103.805.805 0 00-.964.794.81.81 0 00.807.81zm0 44.001a.806.806 0 00.746-.5.813.813 0 00-.589-1.104.81.81 0 10-.157 1.604zm0 10.999a.805.805 0 00.746-.499.813.813 0 00-.589-1.104.81.81 0 10-.157 1.603zm0-22a.806.806 0 00.792-.967.81.81 0 00-.635-.636.805.805 0 00-.964.794.811.811 0 00.807.81zm9.5 93.501a.806.806 0 00.746-.5.809.809 0 00-1.417-.76.813.813 0 00.1 1.022.806.806 0 00.57.238zm0-11a.806.806 0 00.746-.5.812.812 0 00-.588-1.104.81.81 0 10-.158 1.604zM57 6.31a.806.806 0 00.746-.5.811.811 0 00-.589-1.104.805.805 0 00-.964.794.811.811 0 00.807.81zm0 22a.806.806 0 00.792-.968.81.81 0 00-.635-.636.805.805 0 00-.964.794.811.811 0 00.807.81zm0 11a.807.807 0 00.792-.968.811.811 0 00-.635-.636.804.804 0 00-.828.344.81.81 0 00.671 1.26zm-9.5 27.5a.805.805 0 00.745-.5.81.81 0 00-.588-1.104.805.805 0 00-.965.794.81.81 0 00.808.81zm9.5-49.5a.805.805 0 00.746-.5.811.811 0 00-.589-1.104.805.805 0 00-.964.794.811.811 0 00.807.81zm-9.5 5.5a.806.806 0 00.745-.5.811.811 0 00-.588-1.104.805.805 0 00-.965.794.812.812 0 00.808.81zm9.5 104.5a.806.806 0 00.746-.5.813.813 0 00-.589-1.104.81.81 0 10-.157 1.604zm-9.5-115.5a.806.806 0 00.791-.968.81.81 0 00-.634-.636.805.805 0 00-.965.794.81.81 0 00.808.81zm0 44a.805.805 0 00.745-.5.811.811 0 00-.588-1.104.806.806 0 00-.965.794.81.81 0 00.808.81zM57 193.309a.805.805 0 00.746-.499.813.813 0 00-.589-1.104.81.81 0 10-.157 1.603zm9.5-27.5a.808.808 0 00.571-1.381.8.8 0 00-.88-.176.807.807 0 00-.498.748.81.81 0 00.807.809zm-19-132a.805.805 0 00.745-.5.811.811 0 00-.588-1.103.804.804 0 00-.829.344.81.81 0 00.672 1.26zM57 149.31a.806.806 0 00.746-.5.813.813 0 00-.589-1.104.81.81 0 10-.157 1.604zm0-11a.806.806 0 00.746-.5.813.813 0 00-.589-1.104.81.81 0 10-.157 1.604zm0 33a.814.814 0 00.746-.5.813.813 0 00-.589-1.104.81.81 0 10-.157 1.604zm0-11.001a.805.805 0 00.746-.5.808.808 0 10-.746.5zm0 22.001a.806.806 0 00.746-.5.813.813 0 00-.589-1.104.81.81 0 10-.157 1.604zm-9.5-137.5a.806.806 0 00.745-.5.811.811 0 00-.588-1.104.806.806 0 00-.965.794.812.812 0 00.808.81zm-38-33a.806.806 0 00.746-.5.812.812 0 00-.589-1.104.805.805 0 00-.964.794.81.81 0 00.807.81zm0 11a.805.805 0 00.746-.5.812.812 0 00-.588-1.104.805.805 0 00-.83.344.81.81 0 00.672 1.26zM19 193.308a.805.805 0 00.745-.499.813.813 0 00-.588-1.104.81.81 0 10-.157 1.603zm-9.5-137.5a.805.805 0 00.746-.499.812.812 0 00-.588-1.104.805.805 0 00-.83.344.811.811 0 00.672 1.26zm0-11a.806.806 0 00.792-.967.81.81 0 00-1.1-.59.808.808 0 00-.5.748.81.81 0 00.808.81zM19 182.31a.806.806 0 00.745-.5.813.813 0 00-.588-1.104.81.81 0 10-.157 1.604zM9.5 33.81a.805.805 0 00.746-.5.812.812 0 00-.588-1.104.805.805 0 00-.965.794.81.81 0 00.807.81zm9.5 93.5a.805.805 0 00.745-.5.813.813 0 00-.588-1.104.81.81 0 10-.157 1.604zm0 44a.814.814 0 00.745-.5.813.813 0 00-.588-1.104.81.81 0 10-.157 1.604zm0-55.001a.804.804 0 00.745-.499.813.813 0 00-.588-1.104.809.809 0 10-.157 1.603zm0 22.001a.806.806 0 00.745-.5.812.812 0 00-.588-1.104.81.81 0 10-.157 1.604zm0 11a.805.805 0 00.745-.5.813.813 0 00-.588-1.104.81.81 0 10-.157 1.604zm0 10.999a.805.805 0 00.791-.967.81.81 0 00-.634-.636.81.81 0 10-.157 1.603zM9.5 176.81a.806.806 0 00.746-.5.812.812 0 00-.588-1.104.81.81 0 10-.158 1.604zm0-22a.806.806 0 00.746-.5.812.812 0 00-.588-1.104.81.81 0 10-.158 1.604zm0-22a.806.806 0 00.746-.5.812.812 0 00-.588-1.104.81.81 0 10-.158 1.604zm0 10.999a.808.808 0 00.571-1.381.8.8 0 00-.88-.176.807.807 0 00-.498.748.81.81 0 00.807.809zm0 22a.808.808 0 00.571-1.381.8.8 0 00-.88-.176.807.807 0 00-.498.748.81.81 0 00.807.809zM19 105.31a.805.805 0 00.745-.5.813.813 0 00-.588-1.104.809.809 0 10-.157 1.604zm-9.5-38.5a.806.806 0 00.792-.968.81.81 0 00-1.1-.59.808.808 0 00-.5.748.81.81 0 00.808.81zm0 121a.806.806 0 00.746-.5.809.809 0 00-1.417-.76.812.812 0 00.67 1.26zm0-99a.805.805 0 00.746-.5.811.811 0 00-.588-1.104.805.805 0 00-.965.794.811.811 0 00.807.81zm0 33a.806.806 0 00.746-.5.812.812 0 00-.588-1.104.81.81 0 10-.158 1.604zm0-44a.806.806 0 00.792-.968.81.81 0 00-1.1-.59.808.808 0 00-.5.748.81.81 0 00.808.81zm0 22a.806.806 0 00.792-.968.81.81 0 00-.634-.636.806.806 0 00-.965.794.81.81 0 00.807.81zm0 10.999a.805.805 0 00.792-.967.806.806 0 00-1.463-.292.811.811 0 00.67 1.259zm19 77.001a.806.806 0 00.746-.5.813.813 0 00-.589-1.104.81.81 0 10-.157 1.604zm0-77.001a.804.804 0 00.746-.5.809.809 0 00-1.418-.759.813.813 0 00.363 1.198.8.8 0 00.31.061zm0-11a.806.806 0 00.746-.5.812.812 0 00-.589-1.103.805.805 0 00-.964.794.809.809 0 00.807.81zm0-11a.806.806 0 00.792-.967.81.81 0 00-.635-.636.804.804 0 00-.828.344.81.81 0 00.671 1.26zm0 33.001a.813.813 0 00.746-.5.813.813 0 00-.589-1.104.81.81 0 10-.157 1.604zm0 11a.805.805 0 00.746-.5.813.813 0 00-.589-1.104.81.81 0 10-.157 1.604zm0-55a.806.806 0 00.746-.5.812.812 0 00-.589-1.104.805.805 0 00-.964.794.809.809 0 00.807.81zm0-22a.806.806 0 00.746-.5.812.812 0 00-.589-1.104.805.805 0 00-.828.344.81.81 0 00.671 1.26zm0-33a.806.806 0 00.746-.5.812.812 0 00-.589-1.104.805.805 0 00-.964.794.811.811 0 00.807.81zM19 94.31a.806.806 0 00.746-.5.812.812 0 00-.589-1.104.805.805 0 00-.965.794.812.812 0 00.808.81zm9.5-60.5a.805.805 0 00.746-.5.812.812 0 00-.589-1.104.805.805 0 00-.964.794.81.81 0 00.807.81zm0 11a.806.806 0 00.746-.5.812.812 0 00-.589-1.104.806.806 0 00-.964.794.81.81 0 00.807.81zm0 98.999a.805.805 0 00.746-.499.813.813 0 00-.589-1.104.81.81 0 10-.157 1.603zm0-77a.806.806 0 00.746-.5.812.812 0 00-.589-1.103.805.805 0 00-.964.794.809.809 0 00.807.81zm0-55a.805.805 0 00.746-.5.812.812 0 00-.589-1.103.805.805 0 00-.964.794.81.81 0 00.807.81zM19 28.31a.806.806 0 00.746-.5.812.812 0 00-.589-1.103.805.805 0 00-.965.794.81.81 0 00.808.81zm0 22a.806.806 0 00.746-.5.812.812 0 00-.589-1.103.805.805 0 00-.965.794.811.811 0 00.808.81zm0-11a.806.806 0 00.745-.5.811.811 0 00-.588-1.103.804.804 0 00-.829.344.811.811 0 00.672 1.26zm0 22a.805.805 0 00.746-.5.812.812 0 00-.59-1.103.805.805 0 00-.964.794.81.81 0 00.808.81zm0 11a.805.805 0 00.746-.5.812.812 0 00-.589-1.103.805.805 0 00-.965.794.811.811 0 00.808.81zm0 11a.805.805 0 00.746-.5.812.812 0 00-.589-1.103.805.805 0 00-.965.794.811.811 0 00.808.81zm9.5 82.5a.805.805 0 00.746-.499.813.813 0 00-.589-1.104.81.81 0 10-.157 1.603zM19 17.309a.805.805 0 00.745-.5.811.811 0 00-.588-1.103.805.805 0 00-.965.794.81.81 0 00.808.81zm9.5 137.501a.806.806 0 00.746-.5.813.813 0 00-.589-1.104.81.81 0 10-.157 1.604zm0 22a.806.806 0 00.746-.5.813.813 0 00-.589-1.104.81.81 0 10-.157 1.604zM19 6.31a.806.806 0 00.745-.5.811.811 0 00-.588-1.104.805.805 0 00-.965.794.811.811 0 00.808.81zm19 186.999a.808.808 0 00.571-1.381.8.8 0 00-.88-.176.807.807 0 00-.498.748.81.81 0 00.807.809zm57-132a.805.805 0 00.746-.5.812.812 0 00-.588-1.103.805.805 0 00-.965.794.81.81 0 00.807.81zm0-55a.805.805 0 00.746-.499.812.812 0 00-.588-1.104.805.805 0 00-.965.794.81.81 0 00.807.81zm0 11a.806.806 0 00.792-.967.811.811 0 00-.634-.636.806.806 0 00-.965.794.81.81 0 00.807.81zm9.5 170.501a.814.814 0 00.746-.5.806.806 0 00-.176-.882.808.808 0 00-.879-.176.81.81 0 00.309 1.558zm0-11a.814.814 0 00.746-.5.806.806 0 00-.176-.882.798.798 0 00-.879-.176.807.807 0 00-.437 1.058.813.813 0 00.437.438.8.8 0 00.309.062zM95 28.31a.806.806 0 00.792-.968.81.81 0 00-.634-.636.806.806 0 00-.965.794.81.81 0 00.807.81zm0 11a.805.805 0 00.746-.5.811.811 0 00-.588-1.104.806.806 0 00-.965.794.812.812 0 00.807.81zm9.5 93.5a.814.814 0 00.746-.5.806.806 0 00-.176-.882.798.798 0 00-.879-.176.814.814 0 00-.499.748.805.805 0 00.237.573.798.798 0 00.571.237zm0 32.999a.8.8 0 00.448-.136.806.806 0 00.343-.831.813.813 0 00-.634-.636.807.807 0 00-.903 1.104.813.813 0 00.437.438.781.781 0 00.309.061zm0-43.999a.81.81 0 10-.309-1.558.807.807 0 00-.437 1.058.813.813 0 00.437.438.8.8 0 00.309.062zm0-11.001a.8.8 0 00.746-.5.81.81 0 00-1.056-1.057.81.81 0 00.31 1.557zm-9.5-60.5a.805.805 0 00.746-.499.812.812 0 00-.588-1.104.806.806 0 00-.965.794.81.81 0 00.807.81zm9.5 49.5a.809.809 0 10-.002-1.618.809.809 0 00.002 1.618zm0 55.001a.814.814 0 00.746-.5.806.806 0 00-.176-.882.798.798 0 00-.879-.176.814.814 0 00-.499.748.805.805 0 00.237.573.814.814 0 00.571.237zm0-11.001a.814.814 0 00.746-.499.813.813 0 00-.589-1.104.807.807 0 00-.903 1.104.813.813 0 00.437.438.781.781 0 00.309.061zM95 149.31a.806.806 0 00.746-.5.813.813 0 00-.175-.882.8.8 0 00-.88-.176.807.807 0 00-.498.748.809.809 0 00.807.81zm0 10.999a.805.805 0 00.792-.967.806.806 0 00-1.6.158.809.809 0 00.808.809zm0-32.999a.806.806 0 00.746-.5.813.813 0 00-.175-.882.807.807 0 00-1.378.572.809.809 0 00.807.81zm0 11a.806.806 0 00.746-.5.809.809 0 00-1.417-.76.813.813 0 00.1 1.022.806.806 0 00.57.238zm0 44a.806.806 0 00.746-.5.813.813 0 00-.175-.882.807.807 0 00-1.378.572.809.809 0 00.807.81zm0-11a.806.806 0 00.746-.5.813.813 0 00-.175-.882.8.8 0 00-.88-.176.807.807 0 00-.498.748.81.81 0 00.807.81zm19-165a.807.807 0 00.792-.968.807.807 0 10-1.538.468.816.816 0 00.437.438c.098.04.203.062.309.062zm-19 77a.805.805 0 00.746-.5.812.812 0 00-.588-1.104.806.806 0 00-.965.794.811.811 0 00.807.81zm0 32.999a.809.809 0 10-.67-1.259.812.812 0 00.1 1.022.805.805 0 00.57.237zm0-44a.805.805 0 00.746-.499.812.812 0 00-.588-1.104.805.805 0 00-.965.794.811.811 0 00.807.81zm0 22a.806.806 0 00.792-.967.81.81 0 00-1.1-.59.807.807 0 00-.5.748.811.811 0 00.808.81zm0 11.001a.806.806 0 00.746-.5.813.813 0 00-.175-.882.807.807 0 00-1.378.572.809.809 0 00.807.81zm9.5-60.5a.808.808 0 10-.002-1.617.808.808 0 00.002 1.616zm9.5 60.5a.807.807 0 00.792-.968.814.814 0 00-.635-.636.808.808 0 00-.728 1.367.814.814 0 00.571.237zm0-11a.808.808 0 00.792-.968.807.807 0 10-1.538.468.815.815 0 00.437.438c.098.04.203.061.309.061zm0-11a.807.807 0 00.792-.968.807.807 0 10-1.538.468.816.816 0 00.437.438c.098.04.203.062.309.062zm0-11a.808.808 0 00.792-.968.807.807 0 10-1.538.468.816.816 0 00.437.438c.098.04.203.061.309.061zm0 43.999a.806.806 0 00.792-.967.806.806 0 00-1.599.158.804.804 0 00.807.809zm0 11.001a.807.807 0 00.792-.968.814.814 0 00-.635-.636.808.808 0 00-.728 1.367.814.814 0 00.571.237zm0-88a.808.808 0 00.792-.968.807.807 0 00-1.599.158.808.808 0 00.807.81zm0 22a.808.808 0 00.57-1.383.8.8 0 00-.879-.175.81.81 0 00.309 1.557zm0-33a.808.808 0 00.792-.968.807.807 0 10-1.538.468.815.815 0 00.437.438c.098.04.203.062.309.062zm0-11a.808.808 0 00.792-.968.807.807 0 10-1.538.468.816.816 0 00.437.438c.098.04.203.061.309.061zm0 33a.807.807 0 00.792-.968.815.815 0 00-.635-.636.804.804 0 00-.828.344.81.81 0 00.671 1.26zm0 88a.807.807 0 00.571-1.382.809.809 0 10-.571 1.382zm0 11a.815.815 0 00.746-.5.815.815 0 00-.175-.882.8.8 0 00-.88-.176.81.81 0 00.309 1.558zm-9.5-126.5a.802.802 0 00.746-.5.808.808 0 00-1.418-.76.817.817 0 00-.074.76.8.8 0 00.437.438c.098.04.203.062.309.061zm0 33a.802.802 0 00.746-.5.808.808 0 00-1.418-.76.817.817 0 00-.074.76.8.8 0 00.437.438c.098.04.203.062.309.062zm0 33a.803.803 0 00.746-.5.808.808 0 00-1.055-1.058.81.81 0 00.309 1.557zM95 193.309a.809.809 0 10-.67-1.259.812.812 0 00.1 1.022.805.805 0 00.57.237zm9.5-126.5a.808.808 0 10-.002-1.617.808.808 0 00.002 1.617zm0 11a.809.809 0 10-.002-1.618.809.809 0 00.002 1.619zm0-44a.809.809 0 10-.808-.81.804.804 0 00.237.574.807.807 0 00.571.237zm9.5 126.5a.806.806 0 00.792-.967.818.818 0 00-.222-.415.8.8 0 00-.879-.175.807.807 0 00-.437 1.058.814.814 0 00.746.499zm0 11.001a.815.815 0 00.746-.5.815.815 0 00-.175-.882.8.8 0 00-.88-.176.81.81 0 00.309 1.558zm0 11a.807.807 0 00.792-.968.821.821 0 00-.221-.414.8.8 0 00-.88-.176.806.806 0 00-.498.748.804.804 0 00.498.748.8.8 0 00.309.062zm0 10.999a.806.806 0 00.792-.967.806.806 0 00-1.599.158.804.804 0 00.807.809zm-9.5-181.5a.808.808 0 10-.002-1.617.808.808 0 00.002 1.617zm-19 33a.806.806 0 00.792-.967.81.81 0 00-.635-.636.806.806 0 00-.964.794.811.811 0 00.807.81zM76 160.31a.805.805 0 00.791-.967.812.812 0 00-.634-.636.81.81 0 10-.157 1.603zm0 11.001a.814.814 0 00.746-.5.813.813 0 00-.589-1.104.809.809 0 10-.157 1.604zm0-33a.805.805 0 00.746-.5.812.812 0 00-.589-1.104.81.81 0 10-.157 1.604zm0 11a.813.813 0 00.746-.5.813.813 0 00-.589-1.104.809.809 0 10-.157 1.604zm0 43.999a.805.805 0 00.746-.499.813.813 0 00-.589-1.104.809.809 0 10-.157 1.603zm0-10.999a.806.806 0 00.746-.5.813.813 0 00-.589-1.104.809.809 0 10-.157 1.604zm0-110a.806.806 0 00.746-.5.812.812 0 00-.589-1.104.805.805 0 00-.965.794.81.81 0 00.808.81zm0 11a.805.805 0 00.746-.5.812.812 0 00-.589-1.104.804.804 0 00-.829.344.81.81 0 00.672 1.26zm-9.5-71.5a.806.806 0 00.792-.968.81.81 0 00-1.101-.59.808.808 0 00-.498.748.81.81 0 00.807.81zm9.5 115.5a.805.805 0 00.746-.5.814.814 0 00-.176-.882.8.8 0 00-.88-.176.807.807 0 00-.436 1.058.814.814 0 00.746.5zm0-33a.806.806 0 00.746-.5.813.813 0 00-.589-1.104.805.805 0 00-.965.794.81.81 0 00.808.81zm0 21.999a.804.804 0 00.746-.499.814.814 0 00-.176-.883.806.806 0 00-1.378.573.81.81 0 00.808.809zm-9.5-16.5a.805.805 0 00.746-.499.812.812 0 00-.588-1.104.806.806 0 00-.965.794.811.811 0 00.807.81zm0 11a.805.805 0 00.792-.967.806.806 0 00-1.6.158.808.808 0 00.808.809zm9.5-49.5a.806.806 0 00.791-.967.81.81 0 00-.634-.636.805.805 0 00-.965.794.81.81 0 00.808.81zm-9.5 60.501a.806.806 0 00.746-.5.812.812 0 00-.588-1.104.81.81 0 10-.158 1.604zm0-99a.806.806 0 00.746-.5.812.812 0 00-.588-1.104.805.805 0 00-.965.794.811.811 0 00.807.81zm0 66a.806.806 0 00.792-.968.81.81 0 00-1.1-.59.808.808 0 00-.263 1.32.807.807 0 00.57.238zm0 54.999a.808.808 0 00.571-1.381.8.8 0 00-.88-.176.807.807 0 00-.498.748.81.81 0 00.807.809zm0-10.999a.806.806 0 00.746-.5.812.812 0 00-.588-1.104.81.81 0 10-.158 1.604zm0-88a.806.806 0 00.792-.968.81.81 0 00-1.1-.59.807.807 0 00-.5.748.81.81 0 00.808.81zm0-11a.805.805 0 00.746-.5.812.812 0 00-.588-1.104.805.805 0 00-.965.794.81.81 0 00.807.81zm0 33a.805.805 0 00.746-.5.812.812 0 00-.588-1.104.806.806 0 00-.965.794.811.811 0 00.807.81zm0-11a.806.806 0 00.746-.5.812.812 0 00-.588-1.104.805.805 0 00-.965.794.81.81 0 00.807.81zm0 22a.806.806 0 00.792-.968.81.81 0 00-1.1-.59.807.807 0 00-.5.748.811.811 0 00.808.81zm9.5 27.5a.805.805 0 00.746-.5.814.814 0 00-.176-.882.8.8 0 00-.88-.176.813.813 0 00-.436 1.058.814.814 0 00.746.5zm9.5 16.5a.814.814 0 00.746-.5.813.813 0 00-.589-1.104.81.81 0 10-.157 1.604zm0-66a.806.806 0 00.792-.968.81.81 0 00-.635-.636.806.806 0 00-.903 1.104.81.81 0 00.746.5zm0-22a.805.805 0 00.746-.5.81.81 0 00-.589-1.104.805.805 0 00-.964.794.811.811 0 00.807.81zm-19 121a.806.806 0 00.746-.5.812.812 0 00-.588-1.104.81.81 0 10-.158 1.604zm19-132a.806.806 0 00.792-.968.81.81 0 00-.635-.636.806.806 0 00-.964.794.811.811 0 00.807.81zm0 110a.806.806 0 00.746-.5.813.813 0 00-.589-1.104.81.81 0 10-.157 1.604zm0 10.999a.805.805 0 00.746-.499.813.813 0 00-.589-1.104.81.81 0 10-.157 1.603zm0-66a.806.806 0 00.792-.967.81.81 0 00-.635-.636.806.806 0 00-.964.794.811.811 0 00.807.81zm0 11a.807.807 0 00.792-.967.811.811 0 00-.635-.636.804.804 0 00-.828.344.81.81 0 00.671 1.26zm0 22a.804.804 0 00.746-.5.81.81 0 00-1.055-1.057.806.806 0 00-.498.748.812.812 0 00.498.748.8.8 0 00.31.061zm0-11a.805.805 0 00.746-.5.812.812 0 00-.589-1.103.805.805 0 00-.964.794.811.811 0 00.807.81zM76 50.31a.805.805 0 00.746-.5.812.812 0 00-.589-1.103.805.805 0 00-.965.794.811.811 0 00.808.81zm9.5 115.5a.805.805 0 00.746-.499.813.813 0 00-.589-1.104.81.81 0 10-.157 1.603zM76 17.309a.806.806 0 00.746-.5.812.812 0 00-.589-1.103.805.805 0 00-.965.794.81.81 0 00.808.81zm9.5-5.5a.806.806 0 00.746-.5.812.812 0 00-.589-1.103.805.805 0 00-.964.794.81.81 0 00.807.81zM76 6.31a.806.806 0 00.791-.967.81.81 0 00-.634-.636.805.805 0 00-.965.794.811.811 0 00.808.81zm0 33a.806.806 0 00.791-.967.81.81 0 00-1.1-.59.807.807 0 00-.437 1.058.81.81 0 00.746.5zm0-11a.806.806 0 00.746-.5.812.812 0 00-.589-1.103.805.805 0 00-.965.794.812.812 0 00.808.81zm9.5 159.501a.806.806 0 00.746-.5.813.813 0 00-.589-1.104.81.81 0 10-.157 1.604zm0-33a.806.806 0 00.746-.5.813.813 0 00-.589-1.104.81.81 0 10-.157 1.604zm0-88a.806.806 0 00.792-.968.81.81 0 00-.635-.636.806.806 0 00-.964.794.811.811 0 00.807.81zm0 110a.806.806 0 00.746-.5.813.813 0 00-.589-1.104.81.81 0 10-.157 1.604z" fill="#63D0FF"/></svg>
\ No newline at end of file
diff --git a/v1.9.4/website/public/img/integrations-text-split/integrations.png b/v1.9.4/website/public/img/integrations-text-split/integrations.png
new file mode 100644
index 0000000..4776022
--- /dev/null
+++ b/v1.9.4/website/public/img/integrations-text-split/integrations.png
Binary files differ
diff --git a/v1.9.4/website/public/img/integrations/aws.svg b/v1.9.4/website/public/img/integrations/aws.svg
new file mode 100644
index 0000000..31c0b4e
--- /dev/null
+++ b/v1.9.4/website/public/img/integrations/aws.svg
@@ -0,0 +1,17 @@
+<svg xmlns="http://www.w3.org/2000/svg" height="45" viewBox="0 0 50 30">
+ <defs>
+ <style>
+ .cls-1{fill:#252f3e;}.cls-2{fill:#f90;fill-rule:evenodd;}
+ </style>
+ </defs>
+ <title>
+ AWS_logo_RGB
+ </title>
+ <g id="Layer_2" data-name="Layer 2">
+ <g id="Layer_1-2" data-name="Layer 1">
+ <path d="M14.09,10.85a4.65,4.65,0,0,0,.19,1.49,6.73,6.73,0,0,0,.54,1.19.85.85,0,0,1,.11.38.61.61,0,0,1-.32.49l-1,.7a.86.86,0,0,1-.44.15.7.7,0,0,1-.5-.24,3.66,3.66,0,0,1-.59-.77,9.54,9.54,0,0,1-.51-1,6.16,6.16,0,0,1-4.89,2.3,4.54,4.54,0,0,1-3.32-1.2,4.27,4.27,0,0,1-1.22-3.2A4.32,4.32,0,0,1,3.61,7.75,6.08,6.08,0,0,1,7.69,6.46a12.07,12.07,0,0,1,1.76.13c.61.09,1.24.21,1.9.36V5.73a3.66,3.66,0,0,0-.78-2.66A3.85,3.85,0,0,0,7.86,2.3a7.49,7.49,0,0,0-1.79.22,12.78,12.78,0,0,0-1.79.56,4,4,0,0,1-.58.22,1.14,1.14,0,0,1-.26.05c-.23,0-.35-.18-.35-.53V2a1,1,0,0,1,.12-.58,1.06,1.06,0,0,1,.46-.35A10.58,10.58,0,0,1,5.77.32,10.32,10.32,0,0,1,8.36,0a6,6,0,0,1,4.35,1.35,5.5,5.5,0,0,1,1.38,4.09ZM7.34,13.38a5.52,5.52,0,0,0,1.72-.3A3.75,3.75,0,0,0,10.63,12,2.56,2.56,0,0,0,11.19,11a5.4,5.4,0,0,0,.16-1.44V8.82a13.68,13.68,0,0,0-1.52-.28,12.11,12.11,0,0,0-1.56-.1,3.79,3.79,0,0,0-2.47.67A2.31,2.31,0,0,0,5,11a2.39,2.39,0,0,0,.61,1.76A2.39,2.39,0,0,0,7.34,13.38Zm13.35,1.81a1.09,1.09,0,0,1-.64-.16,1.41,1.41,0,0,1-.35-.66L15.81,1.51a2.86,2.86,0,0,1-.15-.67.36.36,0,0,1,.41-.4H17.7a1,1,0,0,1,.65.16,1.32,1.32,0,0,1,.34.65l2.79,11,2.59-11A1.12,1.12,0,0,1,24.39.6a1.06,1.06,0,0,1,.67-.16H26.4a1.08,1.08,0,0,1,.67.16,1.18,1.18,0,0,1,.32.65L30,12.39,32.88,1.25A1.32,1.32,0,0,1,33.22.6a1,1,0,0,1,.65-.16h1.55a.35.35,0,0,1,.4.4,1.39,1.39,0,0,1,0,.27,2.07,2.07,0,0,1-.11.4l-4,12.86a1.26,1.26,0,0,1-.35.66,1.07,1.07,0,0,1-.64.16H29.25a1,1,0,0,1-.67-.18,1.23,1.23,0,0,1-.32-.67L25.67,3.64l-2.56,10.7a1.3,1.3,0,0,1-.32.67,1,1,0,0,1-.67.18Zm21.36.43a10.92,10.92,0,0,1-2.56-.29,7.13,7.13,0,0,1-1.92-.67,1.17,1.17,0,0,1-.51-.46,1.14,1.14,0,0,1-.1-.47v-.84c0-.35.12-.52.38-.52a1.11,1.11,0,0,1,.3.05l.42.18a9.42,9.42,0,0,0,1.84.58,9.5,9.5,0,0,0,2,.2,4.45,4.45,0,0,0,2.42-.55,1.75,1.75,0,0,0,.86-1.57,1.59,1.59,0,0,0-.45-1.16A4.41,4.41,0,0,0,43,9.22l-2.42-.75A5.14,5.14,0,0,1,38,6.78a4,4,0,0,1-.83-2.42,3.69,3.69,0,0,1,.45-1.84,4.37,4.37,0,0,1,1.2-1.37A5.29,5.29,0,0,1,40.51.29,7.54,7.54,0,0,1,42.6,0a8.53,8.53,0,0,1,1.12.07c.38,0,.74.11,1.08.19s.65.17,1,.26a5,5,0,0,1,.69.29,1.71,1.71,0,0,1,.5.41,1,1,0,0,1,.14.55v.79c0,.35-.12.52-.37.52a1.63,1.63,0,0,1-.64-.2,7.73,7.73,0,0,0-3.21-.64,4.37,4.37,0,0,0-2.21.47,1.59,1.59,0,0,0-.78,1.48,1.57,1.57,0,0,0,.49,1.18,4.91,4.91,0,0,0,1.84.91L44.55,7a5.14,5.14,0,0,1,2.58,1.6A3.79,3.79,0,0,1,47.9,11a4.22,4.22,0,0,1-1.65,3.4,5.32,5.32,0,0,1-1.84.93A8.07,8.07,0,0,1,42.05,15.62Z" class="cls-1"/>
+ <path d="M45.19,23.81C39.72,27.85,31.78,30,25,30A36.65,36.65,0,0,1,.22,20.57c-.51-.47,0-1.1.56-.74A49.75,49.75,0,0,0,25.53,26.4,49.13,49.13,0,0,0,44.4,22.53C45.32,22.14,46.1,23.14,45.19,23.81Z" class="cls-2"/>
+ <path d="M47.47,21.21c-.7-.89-4.63-.42-6.39-.21-.53.06-.62-.41-.14-.74,3.14-2.2,8.27-1.57,8.87-.83s-.16,5.89-3.1,8.35c-.45.37-.88.17-.68-.33C46.69,25.8,48.17,22.11,47.47,21.21Z" class="cls-2"/>
+ </g>
+ </g>
+</svg>
diff --git a/v1.9.4/website/public/img/integrations/azure.svg b/v1.9.4/website/public/img/integrations/azure.svg
new file mode 100644
index 0000000..85617d8
--- /dev/null
+++ b/v1.9.4/website/public/img/integrations/azure.svg
@@ -0,0 +1,30 @@
+<svg xmlns="http://www.w3.org/2000/svg" width="120" height="37" viewBox="0 0 273.33 82.67">
+ <defs>
+ <style>
+ .cls-1{fill:#737373;}.cls-2{fill:#f25022;}.cls-3{fill:#7fba00;}.cls-4{fill:#00a4ef;}.cls-5{fill:#ffb900;}
+ </style>
+ </defs>
+ <title>
+ azure-stacked-color
+ </title>
+ <g id="Azure_s" data-name="Azure s">
+ <path d="M113.13,47.24l11.42,30.32h-5.8L116.07,70H104.12l-2.58,7.53H95.79l11.42-30.32ZM110,52.87l-4.48,12.76h9.09l-4.46-12.76Z" class="cls-1"/>
+ <path d="M127.11,55.83h17.36v2.05L133.07,73.5h11.46v4.06H126.31V75.13l11.22-15.25H127.11Z" class="cls-1"/>
+ <path d="M166.3,55.83V77.56h-5.15V74.7h-.09A6.92,6.92,0,0,1,158.34,77a8.46,8.46,0,0,1-3.81.84,7.42,7.42,0,0,1-5.76-2.15q-2-2.14-2-6.67V55.83H152v12.6a6.57,6.57,0,0,0,1.09,4.13,3.92,3.92,0,0,0,3.29,1.38,4.34,4.34,0,0,0,3.48-1.53,5.93,5.93,0,0,0,1.32-4V55.83Z" class="cls-1"/>
+ <path d="M181.71,55.47a6.17,6.17,0,0,1,1.1.08,5.38,5.38,0,0,1,.82.21v5.18a4.41,4.41,0,0,0-1.17-.56,5.7,5.7,0,0,0-1.87-.26,4,4,0,0,0-3.18,1.58,7.62,7.62,0,0,0-1.3,4.89v11H171V55.83h5.12v3.42h.08a6,6,0,0,1,2.12-2.78A5.69,5.69,0,0,1,181.71,55.47Z" class="cls-1"/>
+ <path d="M202.05,72.08v4.21a11,11,0,0,1-3.32,1.3,18.65,18.65,0,0,1-4.38.5,10.07,10.07,0,0,1-7.72-2.94q-2.76-2.94-2.76-8.18a11.93,11.93,0,0,1,2.95-8.32,9.6,9.6,0,0,1,7.47-3.27,9,9,0,0,1,7,2.76q2.5,2.76,2.5,7.62v2.48H188.92c.23,2.18.93,3.71,2.1,4.57a7.49,7.49,0,0,0,4.56,1.3,10.76,10.76,0,0,0,3.51-.56A11.22,11.22,0,0,0,202.05,72.08Zm-3.28-7.59a5.7,5.7,0,0,0-1.17-3.87,4.21,4.21,0,0,0-3.31-1.33,4.78,4.78,0,0,0-3.3,1.32,6.76,6.76,0,0,0-1.94,3.88Z" class="cls-1"/>
+ </g>
+ <g id="MS-logotype">
+ <path d="M130.41,5.56V35.88h-5.27V12.11h-.08l-9.41,23.77h-3.49l-9.64-23.77h-.06V35.88H97.59V5.56h7.55L113.85,28H114l9.19-22.47Zm4.4,2.3a2.76,2.76,0,0,1,.92-2.12,3.25,3.25,0,0,1,4.43,0,2.86,2.86,0,0,1,.89,2.1,2.78,2.78,0,0,1-.91,2.1,3.16,3.16,0,0,1-2.22.84,3.07,3.07,0,0,1-2.21-.85A2.78,2.78,0,0,1,134.81,7.86Zm5.64,6.28V35.88h-5.11V14.14Zm15.52,18a7.17,7.17,0,0,0,2.52-.53,10.41,10.41,0,0,0,2.53-1.4V35a10.3,10.3,0,0,1-2.78,1.06,15.06,15.06,0,0,1-3.41.36A10.35,10.35,0,0,1,144,25.62,12.4,12.4,0,0,1,147.09,17q3.07-3.4,8.69-3.4a12.22,12.22,0,0,1,2.91.37,9.83,9.83,0,0,1,2.33.86v4.9a10.75,10.75,0,0,0-2.42-1.34,7.08,7.08,0,0,0-2.52-.47,6.42,6.42,0,0,0-4.89,2,7.41,7.41,0,0,0-1.86,5.31,7.08,7.08,0,0,0,1.79,5.14A6.47,6.47,0,0,0,156,32.16Zm19.62-18.38a6,6,0,0,1,1.1.09,3.85,3.85,0,0,1,.83.21v5.18a4.49,4.49,0,0,0-1.18-.56,5.7,5.7,0,0,0-1.87-.26A4,4,0,0,0,171.29,20,7.61,7.61,0,0,0,170,24.9v11h-5.12V14.14H170v3.43h.08a6,6,0,0,1,2.12-2.78A5.72,5.72,0,0,1,175.59,13.78Zm2.2,11.55a11.76,11.76,0,0,1,3.05-8.54q3-3.15,8.45-3.15a10.42,10.42,0,0,1,8,3,11.44,11.44,0,0,1,2.87,8.19,11.56,11.56,0,0,1-3.05,8.42,11,11,0,0,1-8.28,3.13,10.86,10.86,0,0,1-8-3A11,11,0,0,1,177.79,25.33Zm5.33-.17a7.76,7.76,0,0,0,1.54,5.2,5.52,5.52,0,0,0,4.42,1.8,5.15,5.15,0,0,0,4.25-1.8A8.32,8.32,0,0,0,194.79,25a8,8,0,0,0-1.51-5.29A5.23,5.23,0,0,0,189,18a5.37,5.37,0,0,0-4.37,1.87A8.19,8.19,0,0,0,183.12,25.16Zm24.61-5.31a2.17,2.17,0,0,0,.7,1.72,11.52,11.52,0,0,0,3.08,1.58,10.53,10.53,0,0,1,4.31,2.76,5.74,5.74,0,0,1,1.23,3.71,6,6,0,0,1-2.35,4.93,10,10,0,0,1-6.38,1.86,15.24,15.24,0,0,1-3-.33,13.34,13.34,0,0,1-2.78-.84v-5a12.52,12.52,0,0,0,3,1.54,8.62,8.62,0,0,0,2.92.58,5.24,5.24,0,0,0,2.56-.49,1.73,1.73,0,0,0,.82-1.63,2.28,2.28,0,0,0-.85-1.79,13.19,13.19,0,0,0-3.25-1.68,10,10,0,0,1-4-2.66,5.83,5.83,0,0,1-1.18-3.76,5.94,5.94,0,0,1,2.34-4.83,9.24,9.24,0,0,1,6.05-1.9,14.6,14.6,0,0,1,2.56.26,11.69,11.69,0,0,1,2.37.65v4.87a10.91,10.91,0,0,0-2.37-1.17,8,8,0,0,0-2.68-.48,3.94,3.94,0,0,0-2.28.57A1.81,1.81,0,0,0,207.73,19.85Zm11.52,5.48a11.76,11.76,0,0,1,3.05-8.54c2-2.1,4.84-3.15,8.45-3.15a10.42,10.42,0,0,1,8,3,11.44,11.44,0,0,1,2.87,8.19,11.56,11.56,0,0,1-3.05,8.42,11,11,0,0,1-8.28,3.13,10.86,10.86,0,0,1-8-3A11,11,0,0,1,219.25,25.33Zm5.33-.17a7.76,7.76,0,0,0,1.54,5.2,5.5,5.5,0,0,0,4.42,1.8,5.15,5.15,0,0,0,4.25-1.8A8.32,8.32,0,0,0,236.25,25a8,8,0,0,0-1.51-5.29A5.23,5.23,0,0,0,230.5,18a5.36,5.36,0,0,0-4.37,1.87A8.19,8.19,0,0,0,224.58,25.16Zm34-6.83h-7.62V35.88h-5.18V18.33h-3.63V14.14h3.63v-3A7.55,7.55,0,0,1,248,5.51a7.84,7.84,0,0,1,5.72-2.19,13.44,13.44,0,0,1,1.65.09,6.81,6.81,0,0,1,1.27.29V8.12a5.23,5.23,0,0,0-.89-.36,4.63,4.63,0,0,0-1.46-.21,3.08,3.08,0,0,0-2.47,1,4.42,4.42,0,0,0-.87,3v2.62h7.62V9.26l5.14-1.57v6.45h5.18v4.19h-5.18V28.5a4.26,4.26,0,0,0,.73,2.83,2.91,2.91,0,0,0,2.29.83,3.18,3.18,0,0,0,1.07-.22,4.78,4.78,0,0,0,1.09-.5v4.23a5.88,5.88,0,0,1-1.62.5,10.71,10.71,0,0,1-2.23.24,6.35,6.35,0,0,1-4.85-1.73,7.34,7.34,0,0,1-1.62-5.19Z" class="cls-1"/>
+ </g>
+ <g id="MS-symbol">
+ <rect width="34.22" height="34.22" x="3.99" y="5.56" class="cls-2"/>
+ <rect width="34.22" height="34.22" x="41.77" y="5.56" class="cls-3"/>
+ <rect width="34.22" height="34.22" x="3.99" y="43.34" class="cls-4"/>
+ <rect width="34.22" height="34.22" x="41.77" y="43.34" class="cls-5"/>
+ <rect width="34.22" height="34.22" x="3.99" y="5.56" class="cls-2"/>
+ <rect width="34.22" height="34.22" x="41.77" y="5.56" class="cls-3"/>
+ <rect width="34.22" height="34.22" x="3.99" y="43.34" class="cls-4"/>
+ <rect width="34.22" height="34.22" x="41.77" y="43.34" class="cls-5"/>
+ </g>
+</svg>
diff --git a/v1.9.4/website/public/img/integrations/digitalocean.svg b/v1.9.4/website/public/img/integrations/digitalocean.svg
new file mode 100644
index 0000000..4d92380
--- /dev/null
+++ b/v1.9.4/website/public/img/integrations/digitalocean.svg
@@ -0,0 +1,40 @@
+
+<svg width="110px" height="19px" viewBox="0 0 110 19" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
+ <desc>DigitalOcean Logo</desc>
+ <defs>
+ <polygon id="path-1" points="18.539185 0.160966667 0 0.160966667 0 18.7 18.539185 18.7"></polygon>
+ <polygon id="path-3" points="0 18.7223667 110 18.7223667 110 0.183333333 0 0.183333333"></polygon>
+ </defs>
+ <g id="Page-1" stroke="none" stroke-width="1" fill="none" fill-rule="evenodd">
+ <g>
+ <g id="Group-3" transform="translate(0.000000, 0.022367)">
+ <mask id="mask-2" fill="white">
+ <use xlink:href="#path-1"></use>
+ </mask>
+ <g id="Clip-2"></g>
+ <path d="M9.26960833,18.7000183 L9.26960833,15.109985 C13.0794583,15.109985 16.0252583,11.339185 14.570875,7.33390167 C14.0320583,5.85036833 12.8486417,4.66731833 11.364925,4.12886833 C7.36019167,2.675585 3.590675,5.62065167 3.590125,9.42976833 C3.590125,9.42976833 3.58975833,9.43050167 3.58920833,9.43050167 L-9.16666667e-05,9.43050167 C-9.16666667e-05,3.36106833 5.86364167,-1.36489833 12.2238417,0.620601667 C15.003175,1.48831833 17.2117917,3.696935 18.0795083,6.47626833 C20.0650083,12.8364683 15.339225,18.7000183 9.26960833,18.7000183" id="Fill-1" fill="#0080FF" mask="url(#mask-2)"></path>
+ </g>
+ <path d="M9.27784,15.1414817 L5.69844,15.1414817 L5.69844,11.5631817 C5.69844,11.5631817 5.69880667,11.5626317 5.69899,11.5626317 L9.27729,11.5626317 C9.27765667,11.5626317 9.27784,11.562815 9.27784,11.562815 L9.27784,15.1414817 Z" id="Fill-4" fill="#0080FF"></path>
+ <polygon id="Fill-6" fill="#0080FF" points="5.697835 17.891665 2.94856833 17.891665 2.947835 17.8909317 2.947835 15.1414817 5.698385 15.1414817 5.698385 17.8909317"></polygon>
+ <path d="M2.94979667,15.1414817 L0.645113333,15.1414817 C0.644196667,15.1414817 0.643463333,15.1407483 0.643463333,15.1407483 L0.643463333,12.837165 C0.643463333,12.837165 0.644196667,12.835515 0.645113333,12.835515 L2.94814667,12.835515 C2.94906333,12.835515 2.94979667,12.8362483 2.94979667,12.8362483 L2.94979667,15.1414817 Z" id="Fill-8" fill="#0080FF"></path>
+ <path d="M27.6794833,6.23566167 L28.7340167,6.23566167 C29.90735,6.23566167 30.8733333,6.466295 31.60575,6.922245 C32.41865,7.412295 32.83115,8.34527833 32.83115,9.69442833 C32.83115,11.084095 32.4177333,12.0590617 31.6028167,12.5923783 L31.6020833,12.5923783 C30.90065,13.056395 29.9407167,13.2916117 28.7486833,13.2916117 L27.6794833,13.2916117 L27.6794833,6.23566167 Z M33.0029333,5.543395 C31.9416167,4.806945 30.6205167,4.43367833 29.0770333,4.43367833 L25.7170833,4.43367833 L25.7170833,15.093595 L29.0770333,15.093595 C30.6166667,15.093595 31.9381333,14.6996117 33.0042167,13.9230117 C33.5842833,13.5116117 34.04005,12.9361283 34.35905,12.2136117 C34.6764,11.494945 34.8371833,10.6472117 34.8371833,9.69442833 C34.8371833,8.752645 34.6764,7.91591167 34.3588667,7.20732833 C34.0398667,6.495445 33.5837333,5.93572833 33.0029333,5.543395 L33.0029333,5.543395 Z" id="Fill-10" fill="#0080FF"></path>
+ <path d="M37.1762783,4.30233833 C36.853245,4.30233833 36.574945,4.41692167 36.3509117,4.64132167 C36.1241283,4.85728833 36.0091783,5.13118833 36.0091783,5.454955 C36.0091783,5.77798833 36.1235783,6.05592167 36.349445,6.28178833 C36.574945,6.507655 36.853245,6.62223833 37.1762783,6.62223833 C37.498945,6.62223833 37.7770617,6.507655 38.0031117,6.28178833 C38.2291617,6.055555 38.3435617,5.77762167 38.3435617,5.454955 C38.3435617,5.131555 38.2286117,4.857655 38.0031117,4.64278833 C37.7770617,4.41692167 37.498945,4.30233833 37.1762783,4.30233833" id="Fill-12" fill="#0080FF"></path>
+ <mask id="mask-4" fill="white">
+ <use xlink:href="#path-3"></use>
+ </mask>
+ <g id="Clip-15"></g>
+ <polygon id="Fill-14" fill="#0080FF" mask="url(#mask-4)" points="36.2134667 15.09365 38.1027167 15.09365 38.1027167 7.5856 36.2134667 7.5856"></polygon>
+ <path d="M44.46827,12.64714 C44.1380867,13.0220567 43.7140367,13.2039233 43.1721033,13.2039233 C42.6305367,13.2039233 42.20887,13.0220567 41.8836367,12.6475067 C41.5596867,12.2749733 41.3952367,11.78089 41.3952367,11.17919 C41.3952367,10.5677733 41.5596867,10.0674567 41.88382,9.69217333 C42.2048367,9.32074 42.6382367,9.13245667 43.1721033,9.13245667 C43.71367,9.13245667 44.13772,9.31542333 44.4680867,9.69290667 C44.7969867,10.06819 44.96382,10.56814 44.96382,11.17919 C44.96382,11.7805233 44.7969867,12.2746067 44.46827,12.64714 L44.46827,12.64714 Z M44.96382,8.21285667 C44.3942033,7.70612333 43.7578533,7.41059 43.07017,7.41059 C42.0271867,7.41059 41.1603867,7.77139 40.4941533,8.48217333 C39.81912,9.18727333 39.4766533,10.0947733 39.4766533,11.17919 C39.4766533,12.2388567 39.8138033,13.1434233 40.47967,13.8685067 C41.1508533,14.5701233 42.02242,14.92579 43.07017,14.92579 C43.79837,14.92579 44.4246367,14.7230233 44.93467,14.3226233 L44.93467,14.4953233 C44.93467,15.11829 44.7678367,15.60284 44.4389367,15.93559 C44.1104033,16.26834 43.65482,16.43664 43.0848367,16.43664 C42.21272,16.43664 41.6662033,16.09399 41.0007033,15.1945567 L39.7142533,16.43059 L39.7489033,16.4791733 C40.0266533,16.8693067 40.4523533,17.2508233 41.01427,17.6138233 C41.5761867,17.97499 42.28257,18.1585067 43.1139867,18.1585067 C44.2354367,18.1585067 45.1429367,17.81274 45.8110033,17.1311067 C46.48292,16.4456233 46.8237367,15.52804 46.8237367,14.4042067 L46.8237367,7.58567333 L44.96382,7.58567333 L44.96382,8.21285667 Z" id="Fill-16" fill="#0080FF" mask="url(#mask-4)"></path>
+ <polygon id="Fill-17" fill="#0080FF" mask="url(#mask-4)" points="48.4405167 15.09365 50.3297667 15.09365 50.3297667 7.5856 48.4405167 7.5856"></polygon>
+ <path d="M49.4034017,4.30233833 C49.0803683,4.30233833 48.8022517,4.41692167 48.578035,4.64132167 C48.3512517,4.85728833 48.2363017,5.13118833 48.2363017,5.454955 C48.2363017,5.77798833 48.3507017,6.05592167 48.5765683,6.28178833 C48.8022517,6.507655 49.0803683,6.62223833 49.4034017,6.62223833 C49.7260683,6.62223833 50.004185,6.507655 50.230235,6.28178833 C50.456285,6.055555 50.570685,5.77762167 50.570685,5.454955 C50.570685,5.131555 50.455735,4.857655 50.230235,4.64278833 C50.004185,4.41692167 49.7260683,4.30233833 49.4034017,4.30233833" id="Fill-18" fill="#0080FF" mask="url(#mask-4)"></path>
+ <path d="M54.47068,5.557035 L52.6107633,5.557035 L52.6107633,7.58561833 L51.5307467,7.58561833 L51.5307467,9.307485 L52.6107633,9.307485 L52.6107633,12.4261683 C52.6107633,13.402235 52.8056467,14.1003683 53.1904633,14.5015017 C53.57638,14.904285 54.26113,15.1085183 55.22638,15.1085183 C55.5330967,15.1085183 55.8420133,15.0982517 56.1439633,15.078635 L56.2292133,15.0729517 L56.2292133,13.352185 L55.5814967,13.386285 C55.1315967,13.386285 54.8312967,13.3072683 54.68848,13.1518017 C54.5440133,12.993585 54.47068,12.6593683 54.47068,12.1583183 L54.47068,9.307485 L56.2292133,9.307485 L56.2292133,7.58561833 L54.47068,7.58561833 L54.47068,5.557035 Z" id="Fill-19" fill="#0080FF" mask="url(#mask-4)"></path>
+ <polygon id="Fill-20" fill="#0080FF" mask="url(#mask-4)" points="65.0877333 15.09365 66.9771667 15.09365 66.9771667 4.43355 65.0877333 4.43355"></polygon>
+ <path d="M86.06389,12.40921 C85.7258233,12.7877933 85.38024,13.1161433 85.1138567,13.2868267 L85.1138567,13.2871933 C84.85279,13.45476 84.5231567,13.5398267 84.1343067,13.5398267 C83.5775233,13.5398267 83.1298233,13.3372433 82.7653567,12.9194267 C82.4027233,12.50436 82.2186567,11.97031 82.2186567,11.33231 C82.2186567,10.69431 82.40034,10.1611767 82.75839,9.74886 C83.11809,9.33397667 83.5634067,9.13231 84.11964,9.13231 C84.7281233,9.13231 85.3696067,9.51071 85.9196067,10.1606267 L87.1681067,8.96327667 C86.3539233,7.90361 85.3155233,7.41044333 84.0758233,7.41044333 C83.0385233,7.41044333 82.1394567,7.78847667 81.4035567,8.53317667 C80.6715067,9.27274333 80.3002567,10.2145267 80.3002567,11.33231 C80.3002567,12.4500933 80.67114,13.39426 81.4024567,14.1387767 C82.1343233,14.8838433 83.0341233,15.2616933 84.0758233,15.2616933 C85.4438567,15.2616933 86.54789,14.6711767 87.2922233,13.5893267 L86.06389,12.40921 Z" id="Fill-21" fill="#0080FF" mask="url(#mask-4)"></path>
+ <path d="M89.6888483,10.402205 C89.7795983,10.0432383 89.9451483,9.74403833 90.182015,9.511755 C90.4381317,9.259855 90.7712483,9.13243833 91.172565,9.13243833 C91.6305317,9.13243833 91.984915,9.26242167 92.2261817,9.520005 C92.4498483,9.75833833 92.5757983,10.0549717 92.6021983,10.402205 L89.6888483,10.402205 Z M93.8178817,8.634505 C93.550215,8.26123833 93.1851983,7.96093833 92.7330983,7.74112167 C92.282465,7.521855 91.757215,7.41057167 91.1721983,7.41057167 C90.1174817,7.41057167 89.2545317,7.79978833 88.6066317,8.56758833 C87.9777983,9.32988833 87.659165,10.2769883 87.659165,11.383405 C87.659165,12.521355 88.0087817,13.462955 88.6984817,14.1825383 C89.384515,14.898455 90.3028317,15.2616383 91.4273983,15.2616383 C92.701565,15.2616383 93.7469317,14.7464717 94.534715,13.7300717 L94.5772483,13.6754383 L93.344515,12.491105 C93.2302983,12.6287883 93.0687817,12.7851717 92.9208317,12.924505 C92.7341983,13.100505 92.5589317,13.2365383 92.371565,13.329855 C92.0892317,13.4704717 91.7724317,13.5397717 91.4182317,13.5397717 C90.8946317,13.5397717 90.4612317,13.3857717 90.129765,13.0821717 C89.8199317,12.798005 89.6387983,12.4150217 89.5905817,11.941655 L94.5959483,11.941655 L94.6126317,11.2521383 C94.6126317,10.7642883 94.5464483,10.2940383 94.4151817,9.854405 C94.2840983,9.41422167 94.083165,9.00373833 93.8178817,8.634505 L93.8178817,8.634505 Z" id="Fill-22" fill="#0080FF" mask="url(#mask-4)"></path>
+ <path d="M97.7189767,12.2246117 C97.9332933,12.0753783 98.2359767,11.999845 98.6191433,11.999845 C99.0739933,11.999845 99.55616,12.0909617 100.053177,12.271545 L100.053177,13.007995 C99.6426933,13.3895117 99.09416,13.583295 98.4224267,13.583295 C98.09536,13.583295 97.84126,13.5108783 97.6665433,13.3669617 C97.49476,13.226345 97.4115267,13.0472283 97.4115267,12.8208117 C97.4115267,12.5632283 97.5121767,12.3679783 97.7189767,12.2246117 M101.073427,8.14746167 L101.073243,8.14746167 C100.500693,7.658695 99.7092433,7.41046167 98.72126,7.41046167 C98.09261,7.41046167 97.5048433,7.548695 96.9729933,7.818195 C96.4809267,8.06771167 95.9978433,8.480945 95.6909433,9.021595 L95.71001,9.044695 L96.92001,10.2028117 C97.4181267,9.408245 97.9723433,9.13232833 98.70696,9.13232833 C99.1014933,9.13232833 99.4292933,9.238295 99.68101,9.44711167 C99.9314433,9.65427833 100.053177,9.91791167 100.053177,10.252495 L100.053177,10.6169617 C99.58476,10.4743283 99.1176267,10.4022783 98.66296,10.4022783 C97.7228267,10.4022783 96.9577767,10.6235617 96.3894433,11.0597117 C95.8137767,11.501545 95.5220933,12.1331283 95.5220933,12.9377783 C95.5220933,13.6430617 95.7681267,14.2161617 96.2552433,14.6422283 C96.7460267,15.052895 97.3598267,15.2615283 98.07941,15.2615283 C98.7986267,15.2615283 99.4716433,14.9716783 100.08251,14.475395 L100.08251,15.093595 L101.94261,15.093595 L101.94261,10.2671617 C101.94261,9.353245 101.650193,8.64026167 101.073427,8.14746167" id="Fill-23" fill="#0080FF" mask="url(#mask-4)"></path>
+ <path d="M109.210622,8.294495 C108.684455,7.708195 107.944888,7.41046167 107.012272,7.41046167 C106.262988,7.41046167 105.654322,7.62587833 105.198922,8.05047833 L105.198922,7.58572833 L103.346155,7.58572833 L103.346155,15.093595 L105.235405,15.093595 L105.235405,10.9528283 C105.235405,10.3841283 105.370888,9.932395 105.637822,9.610095 C105.904022,9.28852833 106.270138,9.13232833 106.756888,9.13232833 C107.184972,9.13232833 107.509472,9.27202833 107.748538,9.558945 C107.989072,9.847695 108.110805,10.2451617 108.110805,10.741445 L108.110805,15.093595 L110.000055,15.093595 L110.000055,10.741445 C110.000055,9.70157833 109.734405,8.878595 109.210622,8.294495" id="Fill-24" fill="#0080FF" mask="url(#mask-4)"></path>
+ <path d="M59.3589883,12.2246117 C59.573305,12.0753783 59.8759883,11.999845 60.2589717,11.999845 C60.714005,11.999845 61.1961717,12.0909617 61.6931883,12.271545 L61.6931883,13.007995 C61.2825217,13.3895117 60.7341717,13.583295 60.0624383,13.583295 C59.7353717,13.583295 59.4810883,13.5108783 59.3063717,13.3669617 C59.1347717,13.226345 59.051355,13.0472283 59.051355,12.8208117 C59.051355,12.5632283 59.152005,12.3679783 59.3589883,12.2246117 M62.7134383,8.14746167 L62.713255,8.14746167 C62.140705,7.658695 61.3490717,7.41046167 60.3612717,7.41046167 C59.7324383,7.41046167 59.1446717,7.548695 58.613005,7.818195 C58.1209383,8.06771167 57.637855,8.480945 57.330955,9.021595 L57.3500217,9.044695 L58.5598383,10.2028117 C59.057955,9.408245 59.6121717,9.13232833 60.3467883,9.13232833 C60.741505,9.13232833 61.069305,9.238295 61.3210217,9.44711167 C61.571455,9.65427833 61.6931883,9.91791167 61.6931883,10.252495 L61.6931883,10.6169617 C61.2247717,10.4743283 60.7576383,10.4022783 60.3027883,10.4022783 C59.3628383,10.4022783 58.5977883,10.6235617 58.029455,11.0597117 C57.4537883,11.501545 57.162105,12.1331283 57.162105,12.9377783 C57.162105,13.6430617 57.407955,14.2161617 57.895255,14.6422283 C58.3860383,15.052895 58.9998383,15.2615283 59.7192383,15.2615283 C60.4386383,15.2615283 61.1114717,14.9716783 61.7223383,14.475395 L61.7223383,15.093595 L63.5826217,15.093595 L63.5826217,10.2671617 C63.5826217,9.353245 63.290205,8.64026167 62.7134383,8.14746167" id="Fill-25" fill="#0080FF" mask="url(#mask-4)"></path>
+ <path d="M73.831945,6.20022333 C71.8697283,6.20022333 70.2732617,7.79650667 70.2732617,9.75890667 C70.2732617,11.7213067 71.8697283,13.31759 73.831945,13.31759 C75.7941617,13.31759 77.3906283,11.7213067 77.3906283,9.75890667 C77.3906283,7.79650667 75.7941617,6.20022333 73.831945,6.20022333 M73.831945,15.2543233 C70.8018117,15.2543233 68.3365283,12.78904 68.3365283,9.75890667 C68.3365283,6.72859 70.8018117,4.26349 73.831945,4.26349 C76.8620783,4.26349 79.3273617,6.72859 79.3273617,9.75890667 C79.3273617,12.78904 76.8620783,15.2543233 73.831945,15.2543233" id="Fill-26" fill="#0080FF" mask="url(#mask-4)"></path>
+ </g>
+ </g>
+</svg>
diff --git a/v1.9.4/website/public/img/integrations/docker.svg b/v1.9.4/website/public/img/integrations/docker.svg
new file mode 100644
index 0000000..3c12c93
--- /dev/null
+++ b/v1.9.4/website/public/img/integrations/docker.svg
@@ -0,0 +1,39 @@
+
+<svg width="69px" height="58px" viewBox="0 0 69 58" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
+ <desc>Docker Logo</desc>
+ <defs>
+ <polygon id="path-1" points="59.4988192 0.066917124 0.0504950991 0.066917124 0.0504950991 38.7311309 59.4988192 38.7311309 59.4988192 0.066917124"></polygon>
+ </defs>
+ <g id="Page-1" stroke="none" stroke-width="1" fill="none" fill-rule="evenodd">
+ <g transform="translate(0.500000, -0.016393)">
+ <g id="Group-3" transform="translate(0.000000, 40.764593)" fill="#394D54">
+ <path d="M10.2576862,5.82882835 L10.2576862,1.46019825 C10.2576862,0.886684181 10.6147573,0.425270593 11.2057029,0.425270593 L11.3695858,0.425270593 C11.9606736,0.425270593 12.3160377,0.886827166 12.3160377,1.46019825 L12.3160377,10.6571562 C12.3160377,12.8998808 11.2135272,14.6841944 9.29274059,15.8210706 C8.40191213,16.3476855 7.41776151,16.6180707 6.38524268,16.6180707 L5.97710042,16.6180707 C3.74547699,16.6180707 1.97221339,15.5090767 0.839401674,13.5796329 C0.313753138,12.683687 0.0467322176,11.6959445 0.0467322176,10.6571562 L0.0467322176,10.2470744 C0.0467322176,8.00377787 1.14981172,6.22032213 3.06917573,5.08144415 C3.96043096,4.5525415 4.94330126,4.28444405 5.97710042,4.28444405 L6.38524268,4.28444405 C7.89561088,4.28444405 9.17708368,4.87282859 10.2576862,5.82882835 L10.2576862,5.82882835 Z M2.1046569,10.4518293 C2.1046569,12.0718529 2.88608787,13.2898017 4.29829707,14.0663549 C4.86932636,14.3806366 5.48943515,14.5492163 6.14112552,14.5492163 C7.72319247,14.5492163 8.89654812,13.7991154 9.70586192,12.4516218 C10.0824226,11.8247742 10.2576862,11.1391597 10.2576862,10.4099346 C10.2576862,9.00553293 9.59617992,7.90969354 8.47033891,7.0955352 C7.78763598,6.6020929 7.01900837,6.35472832 6.18110042,6.35472832 C4.45677406,6.35472832 3.21584519,7.23022736 2.4709749,8.78576452 C2.21946025,9.31152149 2.1046569,9.87016509 2.1046569,10.4518293 L2.1046569,10.4518293 Z M19.4564644,4.28444405 L19.7418368,4.28444405 C22.1266736,4.28444405 23.9401967,5.44734355 25.0896527,7.53964756 C25.5491506,8.37654057 25.7951172,9.2900737 25.7951172,10.2470744 L25.7951172,10.6571562 C25.7951172,12.8995948 24.6947406,14.6866252 22.7709665,15.8213566 C21.8801381,16.3463986 20.896272,16.6180707 19.8640377,16.6180707 L19.4564644,16.6180707 C17.224841,16.6180707 15.4512929,15.5090767 14.3187657,13.5796329 C13.7931172,12.683687 13.5255272,11.6959445 13.5255272,10.6571562 L13.5255272,10.2470744 C13.5255272,8.0034919 14.6327322,6.22589855 16.5474017,5.08201609 C17.4376611,4.55039672 18.4220962,4.28444405 19.4564644,4.28444405 L19.4564644,4.28444405 Z M15.5835941,10.4518293 C15.5835941,12.0243817 16.3515105,13.1811329 17.6729582,13.9942903 C18.2933515,14.3763471 18.9766234,14.5492163 19.7018619,14.5492163 C21.247795,14.5492163 22.3902803,13.7615102 23.185795,12.450049 C23.5650586,11.8247742 23.7364812,11.1380158 23.7364812,10.4099346 C23.7364812,8.94776687 23.0357113,7.83062266 21.837887,7.02103985 C21.1813598,6.57692748 20.4505732,6.35472832 19.6601799,6.35472832 C17.9358536,6.35472832 16.6949247,7.23022736 15.9503389,8.78576452 C15.6982552,9.31152149 15.5835941,9.87016509 15.5835941,10.4518293 L15.5835941,10.4518293 Z M34.3517364,6.52001933 C34.0411841,6.37374536 33.4593431,6.32513036 33.1233264,6.31226168 C31.4038368,6.24720336 30.1594937,7.22036137 29.4297029,8.74515669 C29.1776192,9.27105665 29.0625314,9.82798442 29.0625314,10.4099346 C29.0625314,12.1819515 29.9880711,13.4223491 31.561887,14.1785984 C32.1367573,14.454846 32.8789247,14.5073216 33.5071423,14.5073216 C34.0596778,14.5073216 34.8405397,14.1668736 35.3309079,13.9329496 L35.4159791,13.8924848 L35.7962385,13.8924848 L35.838205,13.9010639 C36.3063808,13.9988658 36.6598954,14.2971332 36.6598954,14.8034442 L36.6598954,15.0080562 C36.6598954,16.2676137 34.3695188,16.5560151 33.4957615,16.6172128 C30.4118619,16.8319767 28.10541,15.1295937 27.2259623,12.1729435 C27.0731757,11.6596262 27.0046067,11.1497406 27.0046067,10.6146896 L27.0046067,10.2051797 C27.0046067,7.96188317 28.1120962,6.18486177 30.0264812,5.04183722 C30.9167406,4.51036083 31.9011757,4.24369323 32.9352594,4.24369323 L33.3431172,4.24369323 C34.4400795,4.24369323 35.4506904,4.55683106 36.3564561,5.17867416 L36.4308577,5.23029186 L36.4778033,5.30821885 C36.5756778,5.47136509 36.6598954,5.65953375 36.6598954,5.8537078 L36.6598954,6.05831977 C36.6598954,6.5865075 36.2666904,6.87047632 35.792113,6.96241587 L35.7529916,6.96942215 L35.6312176,6.96942215 C35.3239372,6.96942215 34.6260126,6.64956402 34.3517364,6.52001933 L34.3517364,6.52001933 Z M41.0279707,7.92084639 C41.8273264,7.11626806 42.6298117,6.31311959 43.4411172,5.52169591 C43.6673096,5.30106958 44.5232845,4.36651761 44.8602971,4.36651761 L45.2290335,4.36651761 L45.271,4.37523972 C45.7405983,4.47332764 46.0922636,4.77202395 46.0922636,5.27919283 L46.0922636,5.48394779 C46.0922636,5.82997224 45.6891004,6.23176095 45.4668912,6.46868761 C44.9940209,6.97242485 44.496113,7.45971877 44.0120042,7.95316107 L41.5255941,10.4904354 C42.5960962,11.5689735 43.665887,12.6485126 44.7278536,13.7354869 C45.021477,14.035899 45.3155272,14.3370261 45.6047406,14.6420138 C45.7068828,14.7501107 45.8578201,14.8846598 45.9437448,15.0346514 C46.0356444,15.174777 46.0922636,15.3332047 46.0922636,15.5020704 L46.0922636,15.7159764 L46.0803138,15.7651634 C45.9647992,16.2371579 45.6666234,16.6180707 45.1462385,16.6180707 L44.9826402,16.6180707 C44.6419289,16.6180707 44.2574017,16.2307235 44.023954,16.0095252 C43.5435439,15.554117 43.0793515,15.0751163 42.608046,14.6098421 L41.0279707,13.0507303 L41.0279707,15.5426782 C41.0279707,16.1164783 40.6703305,16.5778918 40.079954,16.5778918 L39.917636,16.5778918 C39.3266904,16.5778918 38.9696192,16.1164783 38.9696192,15.5426782 L38.9696192,1.50052011 C38.9696192,0.926291111 39.3269749,0.467165288 39.917636,0.467165288 L40.079954,0.467165288 C40.6703305,0.467165288 41.0279707,0.926291111 41.0279707,1.50052011 L41.0279707,7.92084639 Z M66.6813264,4.36651761 L66.8856109,4.36651761 C67.5028745,4.36651761 67.915,4.78460665 67.915,5.40158826 C67.915,6.25807025 67.1002803,6.47726672 66.3953849,6.47726672 C65.4709833,6.47726672 64.5885481,7.03977093 63.9515105,7.6706221 C63.1568494,8.45789921 62.8088828,9.4662316 62.8088828,10.5746537 L62.8088828,15.5831431 C62.8088828,16.1572291 62.4523808,16.6180707 61.8605816,16.6180707 L61.6984059,16.6180707 C61.106749,16.6180707 60.7503891,16.1572291 60.7503891,15.5831431 L60.7503891,10.2873962 C60.7503891,8.25371619 61.735251,6.59379975 63.3770669,5.42947039 C64.3579456,4.73384687 65.4807992,4.36651761 66.6813264,4.36651761 L66.6813264,4.36651761 Z M52.0519372,14.2918427 C52.8010753,14.5545068 53.6552008,14.5171876 54.4236862,14.3824954 C54.8166067,14.2146307 55.8218117,13.77395 56.1916862,13.8385793 L56.2494435,13.8483023 L56.3025063,13.8746116 C56.5281297,13.9845673 56.743795,14.1401353 56.8587406,14.3707706 C57.1283222,14.912256 56.9987238,15.4563151 56.4698033,15.7634475 L56.2935439,15.865682 C54.3411757,16.9984116 52.2644728,16.8415568 50.3185063,15.7836085 C49.3878452,15.2781554 48.6761213,14.5274825 48.1508996,13.6126625 L48.0281297,13.3986135 C46.774682,11.2170867 46.9439707,8.92202952 48.357318,6.8473127 C48.8455523,6.1300984 49.483159,5.57603033 50.2290251,5.14292783 L50.5109833,4.97935264 C52.3498285,3.91253926 54.3202636,3.98531878 56.2088996,4.92172956 C57.2240628,5.42532382 58.0468912,6.17599668 58.6136527,7.16288128 L58.7156527,7.34046903 C59.1273515,8.05768333 58.5938787,8.68267211 58.0431925,9.10962624 C57.4041632,9.6053563 56.7590167,10.201605 56.1463054,10.7330814 C54.7807573,11.9180007 53.4170586,13.1057796 52.0519372,14.2918427 L52.0519372,14.2918427 Z M50.2842218,13.04401 C51.8119456,11.7275442 53.3398117,10.4102206 54.8629833,9.08846441 C55.3833682,8.63720278 55.9543975,8.16878291 56.4709414,7.69435766 C56.0562552,7.16960158 55.3641632,6.79111948 54.7759205,6.56548866 C53.5890502,6.11093837 52.418113,6.26364668 51.3295439,6.89535576 C49.9041046,7.7222398 49.2973682,9.03956344 49.3507155,10.678604 C49.3714854,11.3240397 49.5443305,11.9458828 49.8853264,12.4952324 C50.005251,12.6888345 50.1395439,12.8705688 50.2842218,13.04401 L50.2842218,13.04401 Z" id="Fill-1"></path>
+ </g>
+ <g id="Group-6" transform="translate(8.251046, 0.076068)">
+ <mask id="mask-2" fill="white">
+ <use xlink:href="#path-1"></use>
+ </mask>
+ <g id="Clip-5"></g>
+ <path d="M30.9253046,12.2765612 L36.9990703,12.2765612 L36.9990703,18.517298 L40.0701665,18.517298 C41.4883506,18.517298 42.9470787,18.2632131 44.2901498,17.8058031 C44.9500912,17.5810302 45.690836,17.2678924 46.3418151,16.8742538 C45.4844176,15.7491024 45.0468276,14.3285434 44.9177983,12.9281453 C44.7428192,11.023295 45.1250703,8.54407276 46.4076812,7.05345093 L47.0461414,6.31107121 L47.8069448,6.92576505 C49.7224678,8.47258011 51.3334134,10.634089 51.6173632,13.0978688 C53.9238151,12.4161149 56.631723,12.5774023 58.6647523,13.7567451 L59.4988192,14.2403214 L59.059949,15.1016649 C57.3406017,18.4744024 53.7459908,19.519053 50.2317565,19.334173 C44.9731372,32.4986873 33.5245264,38.7311309 19.6431372,38.7311309 C12.4715556,38.7311309 5.89177322,36.0364298 2.14494477,29.6411259 L2.08363096,29.5367467 L1.53763933,28.4204604 C0.271246025,25.6055086 -0.149415063,22.5214585 0.135815063,19.4402681 L0.22145523,18.517298 L5.41534644,18.517298 L5.41534644,12.2765612 L11.4888276,12.2765612 L11.4888276,6.17180352 L23.6367858,6.17180352 L23.6367858,0.0669028255 L30.9253046,0.0669028255 L30.9253046,12.2765612 Z" id="Fill-4" fill="#394D54" mask="url(#mask-2)"></path>
+ </g>
+ <path d="M58.8545548,14.6613417 C59.2618435,11.4802046 56.8932243,8.98125034 55.4242536,7.79504423 C53.7315088,9.7620931 53.4684711,14.9174284 56.1241699,17.0879453 C54.6421113,18.4111314 51.5190904,19.6104921 48.321241,19.6104921 L9.39522427,19.6104921 C9.08438745,22.9656424 9.67035397,26.0552689 11.0087305,28.6999252 L11.4515841,29.5139405 C11.7319774,29.9922264 12.0382619,30.4537829 12.3692996,30.8981813 L12.3694418,30.8981813 C13.969718,31.0014167 15.4452326,31.037163 16.7951322,31.0071361 L16.7958435,31.0071361 C19.4485548,30.9480832 21.6130318,30.6335155 23.2535674,30.0621462 C23.4978268,29.976784 23.7639941,30.1069006 23.8484962,30.3522634 C23.9328561,30.5974832 23.8036845,30.8651517 23.5597096,30.9502279 C23.3416259,31.0261531 23.1141531,31.0972168 22.8792828,31.1647059 C22.8789983,31.1648489 22.8787138,31.1648489 22.8784293,31.1649919 C21.5867138,31.5356098 20.2016762,31.7851191 18.4144711,31.8959328 C18.5204544,31.8976486 18.3039356,31.9119471 18.3033665,31.9119471 C18.2426218,31.9158077 18.1660862,31.9243868 18.1050569,31.9279615 C17.4017264,31.9675684 16.6424879,31.9758615 15.8663205,31.9758615 C15.0176008,31.9758615 14.1814,31.9597042 13.2467556,31.9119471 L13.2228561,31.9279615 C16.4662285,35.59196 21.5376343,37.7895012 27.8942117,37.7895012 C41.3476845,37.7895012 52.7590234,31.7952711 57.8120778,18.3379229 C61.3971573,18.7076829 64.8425381,17.7888593 66.40981,14.7138173 C63.9134418,13.2658051 60.7030736,13.7275046 58.8545548,14.6613417" id="Fill-7" fill="#00AADA"></path>
+ <path d="M58.8545548,14.6613417 C59.2618435,11.4802046 56.8932243,8.98125034 55.4242536,7.79504423 C53.7315088,9.7620931 53.4684711,14.9174284 56.1241699,17.0879453 C54.6421113,18.4111314 51.5190904,19.6104921 48.321241,19.6104921 L11.7002536,19.6104921 C11.5413498,24.7488122 13.4385213,28.6491654 16.7951322,31.0071361 L16.7958435,31.0071361 C19.4485548,30.9480832 21.6130318,30.6335155 23.2535674,30.0621462 C23.4978268,29.976784 23.7639941,30.1069006 23.8484962,30.3522634 C23.9328561,30.5974832 23.8036845,30.8651517 23.5597096,30.9502279 C23.3416259,31.0261531 23.1141531,31.0972168 22.8792828,31.1647059 C22.8789983,31.1648489 22.8787138,31.1648489 22.8784293,31.1649919 C21.5867138,31.5356098 20.082605,31.8170049 18.2955423,31.9279615 C18.2949732,31.9279615 18.2521531,31.8863527 18.2515841,31.8864957 C22.8302033,34.2470402 29.4691657,34.238604 37.0804711,31.299827 C45.6153247,28.0044446 53.5568142,21.7259598 59.0982452,14.5449516 C59.0145967,14.5828428 58.9332243,14.6217348 58.8545548,14.6613417" id="Fill-9" fill="#24B8EC"></path>
+ <path d="M9.46803264,23.6870176 C9.7100159,25.4840569 10.2329615,27.166994 11.0087021,28.6999395 L11.4515556,29.5139548 C11.731949,29.9922407 12.0382335,30.4537972 12.3695556,30.8981956 C13.9699741,31.001431 15.4457732,31.0371773 16.7958151,31.0071504 C19.4485264,30.9480975 21.6130033,30.6335298 23.2535389,30.0621605 C23.4977983,29.9767983 23.7639657,30.1069149 23.8484678,30.3522777 C23.9329699,30.5974975 23.8036561,30.865166 23.5598234,30.9502422 C23.3415975,31.0261674 23.1141247,31.0972311 22.8792544,31.1647202 C22.8789699,31.1648632 22.8788276,31.1648632 22.8785431,31.1650062 C21.5868276,31.5356241 20.0905431,31.8011478 18.3033381,31.9119614 C18.2421665,31.915822 18.1350452,31.9165369 18.0731623,31.9199686 C17.3701163,31.9595755 16.6188444,31.98374 15.8425347,31.98374 C14.9938151,31.98374 14.1257481,31.9675827 13.191246,31.9199686 C16.4346184,35.5839671 21.5376059,37.7895155 27.8941833,37.7895155 C39.4116477,37.7895155 49.4321163,33.395434 55.2481079,23.6870176 L9.46803264,23.6870176 Z" id="Fill-11" fill="#008BB8"></path>
+ <path d="M12.0506527,23.6870176 C12.7391883,26.8425603 14.3938075,29.3199238 16.7957155,31.0071504 C19.448569,30.9480975 21.613046,30.6335298 23.2535816,30.0621605 C23.497841,29.9767983 23.7640084,30.1069149 23.8485105,30.3522777 C23.9328703,30.5974975 23.8036987,30.865166 23.5597238,30.9502422 C23.3416402,31.0261674 23.1141674,31.0972311 22.8792971,31.1647202 C22.8790126,31.1648632 22.878728,31.1648632 22.8784435,31.1650062 C21.586728,31.5356241 20.0588619,31.8011478 18.2716569,31.9119614 C22.8498494,34.2722199 29.4696067,34.2383324 37.0804854,31.2998413 C41.6848536,29.521819 46.1162343,26.874875 50.0919582,23.6870176 L12.0506527,23.6870176 Z" id="Fill-13" fill="#039BC6"></path>
+ <path d="M14.6786109,18.6610125 L19.9424937,18.6610125 L19.9424937,13.3699842 L14.6786109,13.3699842 L14.6786109,18.6610125 Z M15.1170544,18.2203318 L15.5324519,18.2203318 L15.5324519,13.8109509 L15.1170544,13.8109509 L15.1170544,18.2203318 Z M15.8980586,18.2203318 L16.3301004,18.2203318 L16.3301004,13.8109509 L15.8980586,13.8109509 L15.8980586,18.2203318 Z M16.6954226,18.2203318 L17.1274644,18.2203318 L17.1274644,13.8109509 L16.6954226,13.8109509 L16.6954226,18.2203318 Z M17.4932134,18.2203318 L17.9252552,18.2203318 L17.9252552,13.8109509 L17.4932134,13.8109509 L17.4932134,18.2203318 Z M18.2908619,18.2203318 L18.7229038,18.2203318 L18.7229038,13.8109509 L18.2908619,13.8109509 L18.2908619,18.2203318 Z M19.0883682,18.2203318 L19.5040502,18.2203318 L19.5040502,13.8109509 L19.0883682,13.8109509 L19.0883682,18.2203318 Z" id="Fill-15" fill="#00ACD3"></path>
+ <path d="M20.7520921,12.5561118 L26.0165439,12.5561118 L26.0165439,7.26522647 L20.7520921,7.26522647 L20.7520921,12.5561118 Z M21.1911046,12.1152881 L21.6062176,12.1152881 L21.6062176,7.70619316 L21.1911046,7.70619316 L21.1911046,12.1152881 Z M21.9721088,12.1152881 L22.4038661,12.1152881 L22.4038661,7.70619316 L21.9721088,7.70619316 L21.9721088,12.1152881 Z M22.7693305,12.1152881 L23.2013724,12.1152881 L23.2013724,7.70619316 L22.7693305,7.70619316 L22.7693305,12.1152881 Z M23.5669791,12.1152881 L23.9990209,12.1152881 L23.9990209,7.70619316 L23.5669791,7.70619316 L23.5669791,12.1152881 Z M24.3647699,12.1152881 L24.7968117,12.1152881 L24.7968117,7.70619316 L24.3647699,7.70619316 L24.3647699,12.1152881 Z M25.1621339,12.1152881 L25.5781004,12.1152881 L25.5781004,7.70619316 L25.1621339,7.70619316 L25.1621339,12.1152881 Z" id="Fill-17" fill="#00ACD3"></path>
+ <path d="M20.7520921,18.6610125 L26.0165439,18.6610125 L26.0165439,13.3699842 L20.7520921,13.3699842 L20.7520921,18.6610125 Z M21.1911046,18.2203318 L21.6062176,18.2203318 L21.6062176,13.8109509 L21.1911046,13.8109509 L21.1911046,18.2203318 Z M21.9721088,18.2203318 L22.4038661,18.2203318 L22.4038661,13.8109509 L21.9721088,13.8109509 L21.9721088,18.2203318 Z M22.7693305,18.2203318 L23.2013724,18.2203318 L23.2013724,13.8109509 L22.7693305,13.8109509 L22.7693305,18.2203318 Z M23.5669791,18.2203318 L23.9990209,18.2203318 L23.9990209,13.8109509 L23.5669791,13.8109509 L23.5669791,18.2203318 Z M24.3647699,18.2203318 L24.7968117,18.2203318 L24.7968117,13.8109509 L24.3647699,13.8109509 L24.3647699,18.2203318 Z M25.1621339,18.2203318 L25.5781004,18.2203318 L25.5781004,13.8109509 L25.1621339,13.8109509 L25.1621339,18.2203318 Z" id="Fill-18" fill="#1FC2EF"></path>
+ <path d="M26.8261423,18.6610125 L32.0903096,18.6610125 L32.0903096,13.3699842 L26.8261423,13.3699842 L26.8261423,18.6610125 Z M27.2648703,18.2203318 L27.6799833,18.2203318 L27.6799833,13.8109509 L27.2648703,13.8109509 L27.2648703,18.2203318 Z M28.0457322,18.2203318 L28.4777741,18.2203318 L28.4777741,13.8109509 L28.0457322,13.8109509 L28.0457322,18.2203318 Z M28.8433808,18.2203318 L29.2754226,18.2203318 L29.2754226,13.8109509 L28.8433808,13.8109509 L28.8433808,18.2203318 Z M29.6410293,18.2203318 L30.0730711,18.2203318 L30.0730711,13.8109509 L29.6410293,13.8109509 L29.6410293,18.2203318 Z M30.4385356,18.2203318 L30.8708619,18.2203318 L30.8708619,13.8109509 L30.4385356,13.8109509 L30.4385356,18.2203318 Z M31.2361841,18.2203318 L31.6515816,18.2203318 L31.6515816,13.8109509 L31.2361841,13.8109509 L31.2361841,18.2203318 Z" id="Fill-19" fill="#00ACD3"></path>
+ <path d="M26.8261423,12.5561118 L32.0903096,12.5561118 L32.0903096,7.26522647 L26.8261423,7.26522647 L26.8261423,12.5561118 Z M27.2648703,12.1152881 L27.6799833,12.1152881 L27.6799833,7.70619316 L27.2648703,7.70619316 L27.2648703,12.1152881 Z M28.0457322,12.1152881 L28.4777741,12.1152881 L28.4777741,7.70619316 L28.0457322,7.70619316 L28.0457322,12.1152881 Z M28.8433808,12.1152881 L29.2754226,12.1152881 L29.2754226,7.70619316 L28.8433808,7.70619316 L28.8433808,12.1152881 Z M29.6410293,12.1152881 L30.0730711,12.1152881 L30.0730711,7.70619316 L29.6410293,7.70619316 L29.6410293,12.1152881 Z M30.4385356,12.1152881 L30.8708619,12.1152881 L30.8708619,7.70619316 L30.4385356,7.70619316 L30.4385356,12.1152881 Z M31.2361841,12.1152881 L31.6515816,12.1152881 L31.6515816,7.70619316 L31.2361841,7.70619316 L31.2361841,12.1152881 Z" id="Fill-20" fill="#1FC2EF"></path>
+ <path d="M32.9000502,18.6610125 L38.1642176,18.6610125 L38.1642176,13.3699842 L32.9000502,13.3699842 L32.9000502,18.6610125 Z M33.3387782,18.2203318 L33.7541757,18.2203318 L33.7541757,13.8109509 L33.3387782,13.8109509 L33.3387782,18.2203318 Z M34.1197824,18.2203318 L34.5518243,18.2203318 L34.5518243,13.8109509 L34.1197824,13.8109509 L34.1197824,18.2203318 Z M34.9171464,18.2203318 L35.3491883,18.2203318 L35.3491883,13.8109509 L34.9171464,13.8109509 L34.9171464,18.2203318 Z M35.7149372,18.2203318 L36.1469791,18.2203318 L36.1469791,13.8109509 L35.7149372,13.8109509 L35.7149372,18.2203318 Z M36.5125858,18.2203318 L36.9446276,18.2203318 L36.9446276,13.8109509 L36.5125858,13.8109509 L36.5125858,18.2203318 Z M37.3100921,18.2203318 L37.7257741,18.2203318 L37.7257741,13.8109509 L37.3100921,13.8109509 L37.3100921,18.2203318 Z" id="Fill-21" fill="#1FC2EF"></path>
+ <path d="M32.9000502,12.5561118 L38.1642176,12.5561118 L38.1642176,7.26522647 L32.9000502,7.26522647 L32.9000502,12.5561118 Z M33.3387782,12.1152881 L33.7541757,12.1152881 L33.7541757,7.70619316 L33.3387782,7.70619316 L33.3387782,12.1152881 Z M34.1197824,12.1152881 L34.5518243,12.1152881 L34.5518243,7.70619316 L34.1197824,7.70619316 L34.1197824,12.1152881 Z M34.9171464,12.1152881 L35.3491883,12.1152881 L35.3491883,7.70619316 L34.9171464,7.70619316 L34.9171464,12.1152881 Z M35.7149372,12.1152881 L36.1469791,12.1152881 L36.1469791,7.70619316 L35.7149372,7.70619316 L35.7149372,12.1152881 Z M36.5125858,12.1152881 L36.9446276,12.1152881 L36.9446276,7.70619316 L36.5125858,7.70619316 L36.5125858,12.1152881 Z M37.3100921,12.1152881 L37.7257741,12.1152881 L37.7257741,7.70619316 L37.3100921,7.70619316 L37.3100921,12.1152881 Z" id="Fill-22" fill="#00ACD3"></path>
+ <path d="M32.9000502,6.45149708 L38.1642176,6.45149708 L38.1642176,1.16046876 L32.9000502,1.16046876 L32.9000502,6.45149708 Z M33.3387782,6.01053039 L33.7541757,6.01053039 L33.7541757,1.60114948 L33.3387782,1.60114948 L33.3387782,6.01053039 Z M34.1197824,6.01053039 L34.5518243,6.01053039 L34.5518243,1.60114948 L34.1197824,1.60114948 L34.1197824,6.01053039 Z M34.9171464,6.01053039 L35.3491883,6.01053039 L35.3491883,1.60114948 L34.9171464,1.60114948 L34.9171464,6.01053039 Z M35.7149372,6.01053039 L36.1469791,6.01053039 L36.1469791,1.60114948 L35.7149372,1.60114948 L35.7149372,6.01053039 Z M36.5125858,6.01053039 L36.9446276,6.01053039 L36.9446276,1.60114948 L36.5125858,1.60114948 L36.5125858,6.01053039 Z M37.3100921,6.01053039 L37.7257741,6.01053039 L37.7257741,1.60114948 L37.3100921,1.60114948 L37.3100921,6.01053039 Z" id="Fill-23" fill="#1FC2EF"></path>
+ <path d="M38.9738159,18.6610125 L44.2379833,18.6610125 L44.2379833,13.3699842 L38.9738159,13.3699842 L38.9738159,18.6610125 Z M39.4122594,18.2203318 L39.8279414,18.2203318 L39.8279414,13.8109509 L39.4122594,13.8109509 L39.4122594,18.2203318 Z M40.1932636,18.2203318 L40.6253054,18.2203318 L40.6253054,13.8109509 L40.1932636,13.8109509 L40.1932636,18.2203318 Z M40.9910544,18.2203318 L41.4230962,18.2203318 L41.4230962,13.8109509 L40.9910544,13.8109509 L40.9910544,18.2203318 Z M41.7884184,18.2203318 L42.2204603,18.2203318 L42.2204603,13.8109509 L41.7884184,13.8109509 L41.7884184,18.2203318 Z M42.5863515,18.2203318 L43.0181088,18.2203318 L43.0181088,13.8109509 L42.5863515,13.8109509 L42.5863515,18.2203318 Z M43.3838577,18.2203318 L43.7992552,18.2203318 L43.7992552,13.8109509 L43.3838577,13.8109509 L43.3838577,18.2203318 Z" id="Fill-24" fill="#00ACD3"></path>
+ <path d="M25.687,27.2393016 C26.4889163,27.2393016 27.1390418,27.8930305 27.1390418,28.6990387 C27.1390418,29.5050468 26.4889163,30.1584897 25.687,30.1584897 C24.8847992,30.1584897 24.2346736,29.5050468 24.2346736,28.6990387 C24.2346736,27.8930305 24.8847992,27.2393016 25.687,27.2393016" id="Fill-25" fill="#D4EDF1"></path>
+ <path d="M25.687,27.6534586 C25.8198703,27.6534586 25.9464812,27.678624 26.0634184,27.7240933 C25.9368075,27.7978738 25.8508828,27.9358546 25.8508828,28.0935674 C25.8508828,28.3293501 26.0409414,28.5200925 26.2755272,28.5200925 C26.4361381,28.5200925 26.5755523,28.4304408 26.6478201,28.2980364 C26.6986067,28.4214327 26.7270586,28.5568398 26.7270586,28.6989672 C26.7270586,29.2763418 26.2613013,29.7443327 25.687,29.7443327 C25.1126987,29.7443327 24.6467992,29.2763418 24.6467992,28.6989672 C24.6467992,28.1214495 25.1126987,27.6534586 25.687,27.6534586" id="Fill-26" fill="#394D54"></path>
+ <path d="M0,24.2145476 L31.8110544,24.2145476 L35.745523,24.2145476 L67.5557238,24.2145476 C66.0847615,23.8394971 62.9017071,23.3329001 63.4266444,21.3953062 C60.7520251,24.5060946 54.3016987,23.577834 52.6738243,22.0437446 C50.8610126,24.6865421 40.3077824,23.6819273 39.5717322,21.6232248 C37.2991381,24.3039134 30.2570126,24.3039134 27.9842762,21.6232248 C27.2479414,23.6819273 16.6948536,24.6865421 14.8818996,22.0437446 C13.2540251,23.577834 6.80426778,24.5060946 4.12936402,21.3953062 C4.65430126,23.3329001 1.47124686,23.8394971 0,24.2145476" id="Fill-27" fill="#394D54"></path>
+ <path d="M29.547451,37.7579443 C25.9509908,36.0425496 23.9768569,33.7106022 22.878472,31.1650348 C21.5425138,31.5482354 19.9365473,31.7931692 18.0708151,31.8985494 C17.3679113,31.9381563 16.6284469,31.9583172 15.8524218,31.9583172 C14.9580368,31.9583172 14.0152837,31.931865 13.0258695,31.8791034 C16.3240117,35.192073 20.3813925,37.7429309 27.8942544,37.7895441 C28.4487816,37.7895441 28.9994678,37.7786772 29.547451,37.7579443" id="Fill-28" fill="#BFDBE0"></path>
+ <path d="M24.2143874,33.5138973 C23.716764,32.8350031 23.2340778,31.9818097 22.8792828,31.1646487 C21.5431824,31.5481353 19.9369314,31.7932121 18.0707724,31.8984493 C19.3525297,32.5979334 21.1858268,33.2457999 24.2143874,33.5138973" id="Fill-29" fill="#D4EDF1"></path>
+ </g>
+ </g>
+</svg>
diff --git a/v1.9.4/website/public/img/integrations/google-cloud.svg b/v1.9.4/website/public/img/integrations/google-cloud.svg
new file mode 100644
index 0000000..2eaf125
--- /dev/null
+++ b/v1.9.4/website/public/img/integrations/google-cloud.svg
@@ -0,0 +1,223 @@
+<svg xmlns="http://www.w3.org/2000/svg" xmlns:cc="http://creativecommons.org/ns#" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#" xmlns:svg="http://www.w3.org/2000/svg" id="svg2" width="140" height="86" version="1.1" viewBox="0 0 2002.6667 1237.3333" xml:space="preserve">
+ <metadata id="metadata8">
+ <rdf:RDF>
+ <cc:Work rdf:about="">
+ <dc:format>
+ image/svg+xml
+ </dc:format>
+ <dc:type rdf:resource="http://purl.org/dc/dcmitype/StillImage"/>
+ </cc:Work>
+ </rdf:RDF>
+ </metadata>
+ <defs id="defs6">
+ <clipPath id="clipPath18" clipPathUnits="userSpaceOnUse">
+ <path id="path16" d="M 0,928 H 1502 V 0 H 0 Z"/>
+ </clipPath>
+ <clipPath id="clipPath46" clipPathUnits="userSpaceOnUse">
+ <path id="path44" d="M 530.797,799.473 H 943.992 V 653.641 H 530.797 Z"/>
+ </clipPath>
+ <clipPath id="clipPath62" clipPathUnits="userSpaceOnUse">
+ <path id="path60" d="M 585.703,706.566 H 943.992 V 559.715 H 585.703 Z"/>
+ </clipPath>
+ <clipPath id="clipPath78" clipPathUnits="userSpaceOnUse">
+ <path id="path76" d="M 481.614,655.137 H 834.062 V 412.859 H 481.614 Z"/>
+ </clipPath>
+ <clipPath id="clipPath94" clipPathUnits="userSpaceOnUse">
+ <path id="path92" d="M 481.614,561.215 H 780.625 V 319.953 H 481.614 Z"/>
+ </clipPath>
+ <clipPath id="clipPath110" clipPathUnits="userSpaceOnUse">
+ <path id="path108" d="M 778.891,703.57 H 1020.96 V 319.953 H 778.891 Z"/>
+ </clipPath>
+ <clipPath id="clipPath130" clipPathUnits="userSpaceOnUse">
+ <path id="path128" d="M 778.891,703.57 H 1020.96 V 319.953 H 778.891 Z"/>
+ </clipPath>
+ <clipPath id="clipPath150" clipPathUnits="userSpaceOnUse">
+ <path id="path148" d="m 634.402,799.473 c -12.886,0 -24.785,-6.891 -31.199,-18.071 v 0 L 486.32,577.606 c -6.355,-11.087 -6.355,-24.696 0,-35.785 v 0 L 603.203,338.024 c 6.414,-11.176 18.313,-18.071 31.199,-18.071 v 0 h 233.77 c 12.883,0 24.781,6.895 31.195,18.071 v 0 l 116.883,203.797 c 6.355,11.089 6.355,24.698 0,35.785 v 0 l -72.258,125.964 -44.625,77.832 c -6.414,11.18 -18.312,18.071 -31.195,18.071 v 0 z"/>
+ </clipPath>
+ <radialGradient id="radialGradient164" cx="0" cy="0" r="1" fx="0" fy="0" gradientTransform="matrix(553.65015,0,0,553.65015,559.08789,767.08496)" gradientUnits="userSpaceOnUse" spreadMethod="pad">
+ <stop id="stop160" offset="0" style="stop-opacity:0.09999237;stop-color:#ffffff"/>
+ <stop id="stop162" offset="1" style="stop-opacity:0;stop-color:#ffffff"/>
+ </radialGradient>
+ <mask id="mask166" width="1" height="1" x="0" y="0" maskUnits="userSpaceOnUse">
+ <g id="g176">
+ <g id="g174">
+ <g id="g172">
+ <g id="g170">
+ <path id="path168" d="M -32768,32767 H 32767 V -32768 H -32768 Z" style="fill:url(#radialGradient164);stroke:none"/>
+ </g>
+ </g>
+ </g>
+ </g>
+ </mask>
+ <radialGradient id="radialGradient186" cx="0" cy="0" r="1" fx="0" fy="0" gradientTransform="matrix(553.65015,0,0,553.65015,559.08789,767.08496)" gradientUnits="userSpaceOnUse" spreadMethod="pad">
+ <stop id="stop182" offset="0" style="stop-opacity:1;stop-color:#ffffff"/>
+ <stop id="stop184" offset="1" style="stop-opacity:1;stop-color:#ffffff"/>
+ </radialGradient>
+ <clipPath id="clipPath196" clipPathUnits="userSpaceOnUse">
+ <path id="path194" d="M 128,80 H 1374 V 272 H 128 Z"/>
+ </clipPath>
+ <clipPath id="clipPath254" clipPathUnits="userSpaceOnUse">
+ <path id="path252" d="M 0,136 H 416 V 0 H 0 Z"/>
+ </clipPath>
+ </defs>
+ <g id="g10" transform="matrix(1.3333333,0,0,-1.3333333,0,1237.3333)">
+ <g id="g12">
+ <g id="g14" clip-path="url(#clipPath18)">
+ <g id="g20" transform="translate(834.0625,415.8555)">
+ <path id="path22" d="M 0,0 -55.172,-95.902 H -199.66 c -12.887,0 -24.785,6.894 -31.199,18.07 l -116.883,203.797 c -6.356,11.09 -6.356,24.699 0,35.785 l 44.476,77.531 54.907,-95.422 L -165.586,0 Z" style="fill:#f8bb16;fill-opacity:1;fill-rule:nonzero;stroke:none"/>
+ </g>
+ <g id="g24" transform="translate(1016.25,541.8203)">
+ <path id="path26" d="m 0,0 -116.883,-203.797 c -6.414,-11.176 -18.312,-18.07 -31.195,-18.07 h -89.281 l 55.172,95.902 82.808,143.86 -82.808,143.855 H -72.258 L 0,35.785 C 6.355,24.699 6.355,11.09 0,0" style="fill:#ea4334;fill-opacity:1;fill-rule:nonzero;stroke:none"/>
+ </g>
+ <g id="g28" transform="translate(943.9922,703.5703)">
+ <path id="path30" d="m 0,0 h -275.516 l -82.773,-143.855 -54.906,95.421 72.406,126.266 c 6.414,11.18 18.312,18.07 31.199,18.07 h 233.77 c 12.882,0 24.781,-6.89 31.195,-18.07 z" style="fill:#0074bc;fill-opacity:1;fill-rule:nonzero;stroke:none"/>
+ </g>
+ <g id="g32" transform="translate(834.0625,703.5703)">
+ <path id="path34" d="M 0,0 82.781,-143.855 0,-287.715 h -165.555 l -82.804,143.86 L -165.586,0 Z" style="fill:#e2e3e4;fill-opacity:1;fill-rule:nonzero;stroke:none"/>
+ </g>
+ <g id="g36" transform="translate(751.2852,631.6445)">
+ <path id="path38" d="m 0,0 c 39.727,0 71.93,-32.207 71.93,-71.93 0,-39.726 -32.203,-71.929 -71.93,-71.929 -39.723,0 -71.926,32.203 -71.926,71.929 C -71.926,-32.207 -39.723,0 0,0" style="fill:#ffffff;fill-opacity:1;fill-rule:nonzero;stroke:none"/>
+ </g>
+ <g id="g40">
+ <g id="g42"/>
+ <g id="g54">
+ <g id="g52" clip-path="url(#clipPath46)" style="opacity:0.19999701">
+ <g id="g50" transform="translate(603.2031,778.4062)">
+ <path id="path48" d="m 0,0 c 6.414,11.18 18.312,18.074 31.199,18.074 h 233.77 c 12.883,0 24.781,-6.894 31.195,-18.074 l 42.918,-74.836 h 1.707 L 296.164,2.996 c -6.414,11.18 -18.312,18.07 -31.195,18.07 H 31.199 C 18.312,21.066 6.414,14.176 0,2.996 l -72.406,-126.266 0.867,-1.496 z" style="fill:#ffffff;fill-opacity:1;fill-rule:nonzero;stroke:none"/>
+ </g>
+ </g>
+ </g>
+ </g>
+ <g id="g56">
+ <g id="g58"/>
+ <g id="g70">
+ <g id="g68" clip-path="url(#clipPath62)" style="opacity:0.19999701">
+ <g id="g66" transform="translate(585.7031,559.7148)">
+ <path id="path64" d="m 0,0 82.773,143.855 h 275.516 l -1.707,2.997 H 82.773 L 0,2.996" style="fill:#2c3079;fill-opacity:1;fill-rule:nonzero;stroke:none"/>
+ </g>
+ </g>
+ </g>
+ </g>
+ <g id="g72">
+ <g id="g74"/>
+ <g id="g86">
+ <g id="g84" clip-path="url(#clipPath78)" style="opacity:0.19999701">
+ <g id="g82" transform="translate(486.3203,574.6094)">
+ <path id="path80" d="m 0,0 44.477,77.535 54.906,-95.43 82.773,-143.855 h 163.848 l 1.738,2.996 H 182.156 L 99.383,-14.895 44.477,80.527 0,2.996 C -3.445,-2.996 -4.945,-9.711 -4.676,-16.395 -4.437,-10.73 -2.906,-5.098 0,0" style="fill:#ffffff;fill-opacity:1;fill-rule:nonzero;stroke:none"/>
+ </g>
+ </g>
+ </g>
+ </g>
+ <g id="g88">
+ <g id="g90"/>
+ <g id="g102">
+ <g id="g100" clip-path="url(#clipPath94)" style="opacity:0.19999701">
+ <g id="g98" transform="translate(780.625,322.9492)">
+ <path id="path96" d="m 0,0 h -146.223 c -12.886,0 -24.785,6.891 -31.199,18.07 l -116.883,203.797 c -2.906,5.098 -4.437,10.731 -4.675,16.399 -0.27,-6.688 1.23,-13.399 4.675,-19.395 L -177.422,15.074 c 6.414,-11.176 18.313,-18.07 31.199,-18.07 H -1.734 Z" style="fill:#be3b26;fill-opacity:1;fill-rule:nonzero;stroke:none"/>
+ </g>
+ </g>
+ </g>
+ </g>
+ <g id="g104">
+ <g id="g106"/>
+ <g id="g122">
+ <g id="g120" clip-path="url(#clipPath110)" style="opacity:0.19999701">
+ <g id="g114" transform="translate(918.5508,559.7148)">
+ <path id="path112" d="m 0,0 -82.75,143.855 h -1.738 L -1.68,0 Z" style="fill:#3f2723;fill-opacity:1;fill-rule:nonzero;stroke:none"/>
+ </g>
+ <g id="g118" transform="translate(1016.25,544.8164)">
+ <path id="path116" d="m 0,0 -116.883,-203.797 c -6.414,-11.18 -18.312,-18.07 -31.195,-18.07 h -87.547 l -1.734,-2.996 h 89.281 c 12.883,0 24.781,6.894 31.195,18.07 L 0,-2.996 C 3.449,3 4.945,9.711 4.68,16.398 4.437,10.73 2.91,5.098 0,0" style="fill:#3f2723;fill-opacity:1;fill-rule:nonzero;stroke:none"/>
+ </g>
+ </g>
+ </g>
+ </g>
+ <g id="g124">
+ <g id="g126"/>
+ <g id="g142">
+ <g id="g140" clip-path="url(#clipPath130)" style="opacity:0.19999701">
+ <g id="g134" transform="translate(943.9922,700.5742)">
+ <path id="path132" d="m 0,0 72.258,-125.965 c 2.91,-5.097 4.437,-10.73 4.68,-16.394 0.265,6.683 -1.231,13.398 -4.68,19.39 L 0,2.996 H -109.93 L -108.191,0" style="fill:#ffffff;fill-opacity:1;fill-rule:nonzero;stroke:none"/>
+ </g>
+ <g id="g138" transform="translate(834.0625,412.8594)">
+ <path id="path136" d="M 0,0 84.488,146.855 H 82.809 L 0,2.996 -55.172,-92.906 h 1.734 z" style="fill:#ffffff;fill-opacity:1;fill-rule:nonzero;stroke:none"/>
+ </g>
+ </g>
+ </g>
+ </g>
+ </g>
+ </g>
+ <g id="g144">
+ <g id="g146" clip-path="url(#clipPath150)">
+ <g id="g152">
+ <g id="g154"/>
+ <g id="g178" mask="url(#mask166)">
+ <g id="g180">
+ <path id="path188" d="m 634.402,799.473 c -12.886,0 -24.785,-6.891 -31.199,-18.071 v 0 L 486.32,577.606 c -6.355,-11.087 -6.355,-24.696 0,-35.785 v 0 L 603.203,338.024 c 6.414,-11.176 18.313,-18.071 31.199,-18.071 v 0 h 233.77 c 12.883,0 24.781,6.895 31.195,18.071 v 0 l 116.883,203.797 c 6.355,11.089 6.355,24.698 0,35.785 v 0 l -72.258,125.964 -44.625,77.832 c -6.414,11.18 -18.312,18.071 -31.195,18.071 v 0 z" style="fill:url(#radialGradient186);stroke:none"/>
+ </g>
+ </g>
+ </g>
+ </g>
+ </g>
+ <g id="g190">
+ <g id="g192" clip-path="url(#clipPath196)">
+ <g id="g198" transform="translate(572.6328,173.8242)">
+ <path id="path200" d="m 0,0 c 0,27.266 20.609,47.875 47.617,47.875 13.824,0 25.473,-5.504 33.664,-14.977 L 73.09,24.961 C 66.691,32.898 58.113,36.609 47.617,36.609 28.289,36.609 12.031,22.531 12.031,0 c 0,-22.527 16.258,-36.609 35.586,-36.609 11.524,0 21.25,5.379 28.164,13.312 l 8.188,-8.191 C 75.906,-41.086 62.977,-47.871 47.617,-47.871 20.609,-47.871 0,-27.266 0,0" style="fill:#767576;fill-opacity:1;fill-rule:nonzero;stroke:none"/>
+ </g>
+ <path id="path202" d="m 665.816,219.652 h 11.777 V 128 h -11.777 z" style="fill:#767576;fill-opacity:1;fill-rule:nonzero;stroke:none"/>
+ <g id="g204" transform="translate(739.1602,159.3633)">
+ <path id="path206" d="m 0,0 c 0,14.336 -9.984,22.656 -20.48,22.656 -10.497,0 -20.481,-8.32 -20.481,-22.656 0,-14.34 9.984,-22.66 20.481,-22.66 C -9.984,-22.66 0,-14.34 0,0 m 11.777,0 c 0,-19.074 -13.441,-33.41 -32.257,-33.41 -18.817,0 -32.258,14.336 -32.258,33.41 0,19.07 13.441,33.406 32.258,33.406 C -1.664,33.406 11.777,19.07 11.777,0" style="fill:#767576;fill-opacity:1;fill-rule:nonzero;stroke:none"/>
+ </g>
+ <g id="g208" transform="translate(804.1836,128)">
+ <path id="path210" d="m 0,0 v 8.703 h -0.512 c -3.453,-5.762 -11.265,-10.75 -19.84,-10.75 -16.128,0 -23.937,10.879 -23.937,26.367 v 38.403 h 11.777 V 26.242 c 0,-13.058 6.528,-17.539 15.489,-17.539 10.238,0 16.511,9.856 16.511,19.457 V 62.723 H 11.266 V 0 Z" style="fill:#767576;fill-opacity:1;fill-rule:nonzero;stroke:none"/>
+ </g>
+ <g id="g212" transform="translate(876.6328,159.3633)">
+ <path id="path214" d="m 0,0 c 0,14.336 -9.473,22.656 -19.969,22.656 -10.5,0 -19.969,-8.578 -19.969,-22.656 0,-14.082 9.469,-22.66 19.969,-22.66 C -9.473,-22.66 0,-14.34 0,0 m -51.715,0 c 0,19.199 13.949,33.406 29.824,33.406 9.985,0 17.793,-4.992 21.375,-10.75 H 0 l -0.516,8.703 v 28.93 H 11.266 V -31.363 H 0 v 8.703 h -0.516 c -3.582,-5.762 -11.39,-10.75 -21.375,-10.75 -15.875,0 -29.824,14.207 -29.824,33.41" style="fill:#767576;fill-opacity:1;fill-rule:nonzero;stroke:none"/>
+ </g>
+ <g id="g216" transform="translate(951.5078,176.3867)">
+ <path id="path218" d="M 0,0 C 10.496,0 16.383,8.703 16.383,16 16.383,23.297 10.496,32 0,32 H -19.711 V 0 Z M -31.492,-48.387 V 43.266 H -0.258 C 14.977,43.266 28.418,32 28.418,16 28.418,0 14.977,-11.266 -0.258,-11.266 h -19.453 v -37.121 z" style="fill:#767576;fill-opacity:1;fill-rule:nonzero;stroke:none"/>
+ </g>
+ <path id="path220" d="m 988.242,219.652 h 11.773 V 128 h -11.773 z" style="fill:#767576;fill-opacity:1;fill-rule:nonzero;stroke:none"/>
+ <g id="g222" transform="translate(1054.6758,155.0078)">
+ <path id="path224" d="m 0,0 c 0,0 -4.992,4.098 -14.98,4.098 -12.415,0 -17.278,-6.657 -17.278,-12.414 0,-6.657 6.91,-9.989 13.055,-9.989 C -9.855,-18.305 0,-10.238 0,0 m -44.547,-8.063 c 0,14.208 12.801,21.887 27.52,21.887 8.449,0 14.593,-2.429 17.027,-3.84 v 1.793 c 0,9.473 -7.551,15.235 -16.387,15.235 -6.527,0 -12.8,-3.203 -14.976,-9.09 l -10.75,4.609 c 2.172,5.762 9.726,15.231 25.468,15.231 15.364,0 27.907,-9.215 27.907,-26.879 V -27.008 H 0 v 8.703 h -0.512 c -3.457,-5.246 -9.859,-10.75 -20.609,-10.75 -12.801,0 -23.426,7.934 -23.426,20.992" style="fill:#767576;fill-opacity:1;fill-rule:nonzero;stroke:none"/>
+ </g>
+ <g id="g226" transform="translate(1082.9609,147.0742)">
+ <path id="path228" d="m 0,0 v 32.898 h -11.008 v 10.75 H 0 V 62.852 H 11.777 V 43.648 h 15.36 V 32.898 H 11.777 V 0.895 c 0,-7.04 2.942,-10.239 8.45,-10.239 2.171,0 3.71,0.254 5.375,1.024 l 4.093,-10.114 c -2.687,-1.152 -5.5,-1.664 -9.468,-1.664 C 7.039,-20.098 0,-12.801 0,0" style="fill:#767576;fill-opacity:1;fill-rule:nonzero;stroke:none"/>
+ </g>
+ <g id="g230" transform="translate(1159.5039,218.5)">
+ <path id="path232" d="m 0,0 -4.098,-10.113 c -1.535,0.769 -3.199,1.023 -5.375,1.023 -5.886,0 -10.496,-3.453 -10.496,-10.75 v -7.937 h 16.387 v -10.75 H -19.969 V -90.5 h -11.777 v 51.973 H -43.52 v 10.75 h 11.774 v 8.32 c 0,12.801 9.09,21.121 22.273,21.121 C -5.504,1.664 -2.688,1.152 0,0" style="fill:#767576;fill-opacity:1;fill-rule:nonzero;stroke:none"/>
+ </g>
+ <g id="g234" transform="translate(1211.8555,159.3633)">
+ <path id="path236" d="m 0,0 c 0,14.336 -9.984,22.656 -20.48,22.656 -10.497,0 -20.481,-8.32 -20.481,-22.656 0,-14.34 9.984,-22.66 20.481,-22.66 C -9.984,-22.66 0,-14.34 0,0 m 11.777,0 c 0,-19.074 -13.441,-33.41 -32.257,-33.41 -18.817,0 -32.258,14.336 -32.258,33.41 0,19.07 13.441,33.406 32.258,33.406 C -1.664,33.406 11.777,19.07 11.777,0" style="fill:#767576;fill-opacity:1;fill-rule:nonzero;stroke:none"/>
+ </g>
+ <g id="g238" transform="translate(1233.1016,128)">
+ <path id="path240" d="M 0,0 V 62.723 H 11.266 V 52.48 h 0.511 c 2.559,7.172 11.649,11.778 18.176,11.778 3.84,0 6.399,-0.512 8.832,-1.535 l -4.48,-11.008 c -1.664,0.64 -3.711,0.894 -6.274,0.894 -8.062,0 -16.254,-6.785 -16.254,-18.304 L 11.777,0 Z" style="fill:#767576;fill-opacity:1;fill-rule:nonzero;stroke:none"/>
+ </g>
+ <g id="g242" transform="translate(1278.2852,190.7227)">
+ <path id="path244" d="m 0,0 h 11.262 v -8.703 h 0.515 c 3.582,6.015 11.903,10.75 19.328,10.75 10.11,0 16.641,-4.606 19.84,-12.031 4.481,7.039 12.16,12.031 21.891,12.031 15.359,0 22.402,-10.879 22.402,-26.367 V -62.723 H 83.457 v 36.61 c 0,13.058 -4.992,17.41 -13.949,17.41 -9.602,0 -16.004,-9.731 -16.004,-19.328 V -62.723 H 41.73 v 36.61 c 0,13.058 -4.992,17.41 -13.953,17.41 -9.601,0 -16,-9.731 -16,-19.328 V -62.723 H 0 Z" style="fill:#767576;fill-opacity:1;fill-rule:nonzero;stroke:none"/>
+ </g>
+ <g id="g246" transform="matrix(1,0,0,-1,128,231)">
+ <g id="g248">
+ <g id="g250" clip-path="url(#clipPath254)">
+ <g id="g256" transform="translate(0.7227,52.5654)">
+ <path id="path258" d="m 0,0 c 0,-28.929 24.321,-52.482 53.251,-52.482 16.001,0 27.394,6.272 35.97,14.464 L 79.108,-27.905 C 72.964,-33.665 64.644,-38.146 53.251,-38.146 32.13,-38.146 15.617,-21.12 15.617,0 c 0,21.121 16.513,38.145 37.634,38.145 13.696,0 21.505,-5.503 26.497,-10.496 4.097,-4.095 6.784,-9.984 7.809,-18.048 H 53.251 V -4.735 h 48.258 c 0.512,2.559 0.768,5.631 0.768,8.96 0,10.753 -2.944,24.065 -12.417,33.538 C 80.645,47.362 68.867,52.482 53.251,52.482 24.321,52.482 0,28.93 0,0" style="fill:#767576;fill-opacity:1;fill-rule:nonzero;stroke:none"/>
+ </g>
+ <g id="g260" transform="translate(142.0005,91.7354)">
+ <path id="path262" d="m 0,0 c -10.241,0 -19.073,-8.448 -19.073,-20.482 0,-12.16 8.832,-20.48 19.073,-20.48 10.24,0 19.072,8.32 19.072,20.48 C 19.072,-8.448 10.24,0 0,0 m 0,-54.275 c -18.689,0 -33.922,14.21 -33.922,33.793 0,19.457 15.233,33.794 33.922,33.794 18.689,0 33.921,-14.337 33.921,-33.794 0,-19.583 -15.232,-33.793 -33.921,-33.793" style="fill:#767576;fill-opacity:1;fill-rule:nonzero;stroke:none"/>
+ </g>
+ <g id="g264" transform="translate(216,91.7354)">
+ <path id="path266" d="m 0,0 c -10.24,0 -19.073,-8.448 -19.073,-20.482 0,-12.16 8.833,-20.48 19.073,-20.48 10.24,0 19.072,8.32 19.072,20.48 C 19.072,-8.448 10.24,0 0,0 m 0,-54.275 c -18.689,0 -33.922,14.21 -33.922,33.793 0,19.457 15.233,33.794 33.922,33.794 18.688,0 33.922,-14.337 33.922,-33.794 0,-19.583 -15.234,-33.793 -33.922,-33.793" style="fill:#767576;fill-opacity:1;fill-rule:nonzero;stroke:none"/>
+ </g>
+ <g id="g268" transform="translate(289.8057,91.7354)">
+ <path id="path270" d="m 0,0 c -10.24,0 -18.817,-8.576 -18.817,-20.353 0,-11.904 8.577,-20.609 18.817,-20.609 10.112,0 18.049,8.705 18.049,20.609 C 18.049,-8.576 10.112,0 0,0 m 17.024,-52.227 v 5.505 h -0.511 c -3.328,-3.968 -9.729,-7.553 -17.793,-7.553 -16.897,0 -32.386,14.849 -32.386,33.922 0,18.946 15.489,33.665 32.386,33.665 8.064,0 14.465,-3.584 17.793,-7.68 h 0.511 v 4.865 c 0,12.928 -6.912,19.84 -18.048,19.84 -9.088,0 -14.721,-6.527 -17.025,-12.031 l -12.929,5.375 c 3.712,8.961 13.569,19.969 29.954,19.969 17.409,0 32.129,-10.241 32.129,-35.202 v -60.675 z" style="fill:#767576;fill-opacity:1;fill-rule:nonzero;stroke:none"/>
+ </g>
+ <path id="path272" d="M 346,103 H 331.151 V 3.668 H 346 Z" style="fill:#767576;fill-opacity:1;fill-rule:nonzero;stroke:none"/>
+ <g id="g274" transform="translate(385.5537,50.5176)">
+ <path id="path276" d="M 0,0 C 5.889,0 10.881,2.944 12.545,7.168 L -17.664,19.713 C -18.049,6.656 -7.552,0 0,0 m 1.152,41.218 c -7.552,0 -12.928,-3.456 -16.384,-10.24 L 29.954,12.289 28.418,8.448 c -2.816,-7.551 -11.393,-21.505 -28.93,-21.505 -17.409,0 -31.873,13.698 -31.873,33.793 0,18.946 14.336,33.794 33.537,33.794 15.489,0 24.45,-9.471 28.162,-14.976 L 17.793,31.873 c -3.84,5.633 -9.088,9.345 -16.641,9.345" style="fill:#767576;fill-opacity:1;fill-rule:nonzero;stroke:none"/>
+ </g>
+ </g>
+ </g>
+ </g>
+ </g>
+ </g>
+ </g>
+</svg>
diff --git a/v1.9.4/website/public/img/integrations/vmware.svg b/v1.9.4/website/public/img/integrations/vmware.svg
new file mode 100644
index 0000000..bb1085b
--- /dev/null
+++ b/v1.9.4/website/public/img/integrations/vmware.svg
@@ -0,0 +1,26 @@
+
+<svg width="100px" height="17px" viewBox="0 0 100 17" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
+ <desc>VM Ware Logo</desc>
+ <defs>
+ <polygon id="path-1" points="7.20994469e-21 0.236160236 7.20994469e-21 16.0310345 37.4537057 16.0310345 37.4537057 0.236160236 0 0.236160236"></polygon>
+ </defs>
+ <g id="Page-1" stroke="none" stroke-width="1" fill="none" fill-rule="evenodd">
+ <g id="vmware">
+ <path d="M58.4103568,0.870619748 C57.8235607,0.870619748 57.5197888,1.27306509 57.3809368,1.73797792 L53.7026886,12.6902405 L50.0861525,1.76506559 C49.9196365,1.24653024 49.5578765,0.870619748 48.9721444,0.870619748 L48.8588284,0.870619748 C48.3050165,0.870619748 47.9703884,1.24653024 47.8044045,1.76506559 L44.1575443,12.6902405 L40.5362202,1.79491731 C40.3702361,1.24708304 40.0074121,0.871172558 39.4498761,0.871172558 C38.8114761,0.871172558 38.3661921,1.39136633 38.3661921,1.9397534 C38.3661921,2.14208169 38.4491841,2.37315608 38.5050441,2.5478439 L42.8743603,15.1917038 C43.0988643,15.8539696 43.5425523,16.201134 44.0697643,16.201134 L44.1282844,16.201134 C44.6836923,16.201134 45.1023763,15.8539696 45.2976204,15.1917038 L48.9173485,4.44729749 L52.5062206,15.1917038 C52.7025286,15.8539696 53.1212126,16.201134 53.6782166,16.201134 L53.7617407,16.201134 C54.2634167,16.201134 54.7071047,15.8539696 54.9316087,15.1917038 L59.3296528,2.518545 C59.3839168,2.34275156 59.4685049,2.11222999 59.4685049,1.9104545 C59.4685049,1.3598562 59.0221568,0.870619748 58.4103568,0.870619748" id="Fill-1" fill="#000000" fill-rule="nonzero"></path>
+ <path d="M81.837084,0.871448963 C80.280984,0.871448963 77.9327359,2.04727486 76.8740559,4.53934027 L76.8740559,1.97375119 C76.8740559,1.33470336 76.4016398,0.842150057 75.7855838,0.842150057 C75.2009158,0.842150057 74.7274357,1.36344946 74.7274357,1.97375119 L74.7284997,15.0515666 C74.7284997,15.6856391 75.2019797,16.1809565 75.8164397,16.1809565 C76.4293039,16.1809565 76.8751198,15.6602098 76.8751198,15.0515666 L76.8751198,9.97014122 C76.8751198,5.65159308 79.1589959,3.47684034 81.9488041,3.12967594 C82.5116601,3.04233204 82.8994881,2.61003497 82.8994881,2.00028605 C82.8994881,1.36344946 82.4813361,0.871448963 81.837084,0.871448963" id="Fill-3" fill="#000000" fill-rule="nonzero"></path>
+ <path d="M84.8721973,7.74569091 C85.1424533,4.84731048 87.0001973,2.69798697 89.4591015,2.69798697 C92.2744455,2.69798697 93.7502136,5.04742752 93.9704616,7.74569091 L84.8721973,7.74569091 Z M89.5160255,0.832254767 C85.6090173,0.832254767 82.7388773,4.27404698 82.7388773,8.54671194 L82.7388773,8.60586256 C82.7388773,13.1930761 85.9080014,16.3219782 89.7894735,16.3219782 C92.1925175,16.3219782 93.7789416,15.4291907 95.1163897,14.0830995 C95.3377016,13.8840881 95.4467617,13.6253732 95.4467617,13.3683168 C95.4467617,12.8497814 95.0355257,12.4196956 94.5178896,12.4196956 C94.2705096,12.4196956 94.0800536,12.5341271 93.9156656,12.6761993 C92.8756055,13.6795485 91.5956136,14.3970953 89.8458655,14.3970953 C87.3284414,14.3970953 85.1711813,12.5910666 84.8732613,9.38145434 L95.0892576,9.38145434 C95.6052977,9.38145434 96.0739897,8.94971009 96.0739897,8.34548927 C96.0739897,4.4144606 93.6948856,0.832254767 89.5160255,0.832254767 L89.5160255,0.832254767 Z" id="Fill-5" fill="#000000" fill-rule="nonzero"></path>
+ <path d="M70.1008444,10.5221216 C70.1008444,12.8886992 67.9302843,14.5648178 65.2905003,14.5648178 C63.3417842,14.5648178 61.6755602,13.466938 61.6755602,11.5895968 L61.6755602,11.5321046 C61.6755602,9.65642181 63.1789922,8.44134644 65.8725083,8.44134644 C67.6227883,8.44134644 69.0426964,8.75976473 70.1008444,9.07707741 L70.1008444,10.5221216 Z M66.0124242,0.873936606 C64.1786202,0.873936606 63.1108961,1.08621547 61.6952441,1.72471049 C61.3036921,1.9049264 61.1105761,2.19072894 61.1105761,2.65121929 C61.1105761,3.17030744 61.5569242,3.60481574 62.0580682,3.60481574 C62.1665961,3.60481574 62.3070442,3.57551684 62.4432361,3.51747184 C63.5024482,3.02712977 64.3446041,2.83585768 65.7905803,2.83585768 C68.4846284,2.83585768 70.0737124,4.22451524 70.0737124,6.90951119 L70.0737124,7.43191621 C68.7921244,7.05379449 67.4865963,6.793974 65.6501322,6.793974 C62.0091241,6.793974 59.5065961,8.47175096 59.5065961,11.6200013 L59.5065961,11.6780463 C59.5065961,14.7406111 62.2059641,16.3277273 64.8771363,16.3299386 C67.4020084,16.3299386 69.0714244,15.1181801 70.0742444,13.7582686 L70.0742444,15.1828588 C70.0742444,15.759992 70.4876084,16.2232463 71.0967485,16.2232463 C71.6840765,16.2232463 72.1288285,15.7594391 72.1288285,15.1253666 L72.1288285,6.88297634 C72.1288285,4.9752306 71.6276845,3.53129207 70.6530605,2.52020342 C69.5986364,1.42121805 68.0409403,0.873936606 66.0124242,0.873936606 L66.0124242,0.873936606 Z" id="Fill-7" fill="#000000" fill-rule="nonzero"></path>
+ <g id="Group-11" transform="translate(0.000000, 0.316484)">
+ <g id="Fill-9-Clipped">
+ <mask id="mask-2" fill="white">
+ <use xlink:href="#path-1"></use>
+ </mask>
+ <g id="path-1"></g>
+ <path d="M32.3151175,0.236160236 C29.5120094,0.236160236 27.7564094,2.25170383 27.7564094,2.25170383 C26.8238133,0.994614929 25.5374373,0.238924285 23.3610252,0.238924285 C21.0638491,0.238924285 19.0539531,2.25170383 19.0539531,2.25170383 C18.119761,0.994614929 16.530677,0.238924285 15.214509,0.238924285 C13.1790769,0.238924285 11.5623288,1.16874994 10.5765328,3.5126624 L7.66276866,10.648328 L3.92546854,1.49269633 C3.45464852,0.420245814 2.29116448,-0.0656737737 1.20428845,0.435724482 C0.116348404,0.938781165 -0.28371561,2.19200039 0.207320408,3.26500373 L4.77028456,13.5699264 C5.48795258,15.1846831 6.24392462,16.0310345 7.66276866,16.0310345 C9.17896871,16.0310345 9.84024474,15.109501 10.5568488,13.5699264 C10.5568488,13.5699264 14.5367409,4.56631739 14.5761088,4.47233977 C14.6165409,4.37670371 14.7447529,4.08592589 15.1496049,4.08868994 C15.4916809,4.09090117 15.7800249,4.37449247 15.7800249,4.75648386 L15.7800249,13.5610814 C15.7800249,14.9182288 16.504077,16.0310345 17.897917,16.0310345 C19.2906931,16.0310345 20.0434731,14.9182288 20.0434731,13.5610814 L20.0434731,6.35576187 C20.0434731,4.96655149 21.0016051,4.06436632 22.3076651,4.06436632 C23.6137252,4.06436632 24.4830132,4.99861445 24.4830132,6.35576187 L24.4830132,13.5610814 C24.4830132,14.9182288 25.2097253,16.0310345 26.6009053,16.0310345 C27.9931494,16.0310345 28.7501854,14.9182288 28.7501854,13.5610814 L28.7501854,6.35576187 C28.7501854,4.96655149 29.7045935,4.06436632 31.0111855,4.06436632 C32.3151175,4.06436632 33.1875976,4.99861445 33.1875976,6.35576187 L33.1875976,13.5610814 C33.1875976,14.9182288 33.9137776,16.0310345 35.3065536,16.0310345 C36.6982656,16.0310345 37.4537057,14.9182288 37.4537057,13.5610814 L37.4537057,5.3612575 C37.4537057,2.34733988 35.1214176,0.236160236 32.3151175,0.236160236" id="Fill-9" fill="#000000" fill-rule="nonzero" mask="url(#mask-2)"></path>
+ </g>
+ </g>
+ <path d="M99.4626702,2.68941843 C99.4626702,3.51586869 98.8365062,4.20632781 98.0246742,4.20632781 C97.2027341,4.20632781 96.5840181,3.52637207 96.5840181,2.69936899 L96.5840181,2.68941843 C96.5840181,1.86739063 97.2101821,1.17527309 98.0246742,1.17527309 C98.8466142,1.17527309 99.4626702,1.85522883 99.4626702,2.68444314 L99.4626702,2.68941843 Z M98.0246742,0.831978362 C97.0351541,0.831978362 96.247794,1.68109382 96.247794,2.68941843 L96.247794,2.70158024 C96.247794,3.71266889 97.0207901,4.55017534 98.0246742,4.55017534 C99.0195142,4.55017534 99.8047462,3.70105989 99.8047462,2.68941843 L99.8047462,2.68167909 C99.8047462,1.67224887 99.0280262,0.831978362 98.0246742,0.831978362 L98.0246742,0.831978362 Z" id="Fill-12" fill="#000000" fill-rule="nonzero"></path>
+ <path d="M98.3940417,2.37708103 C98.3940417,2.52965647 98.2929618,2.63026781 98.1078257,2.63026781 L98.1078257,2.62916219 L97.7226578,2.62916219 L97.7226578,2.1144965 L98.1009097,2.1144965 C98.2849818,2.1144965 98.3940417,2.20460446 98.3940417,2.37100013 L98.3940417,2.37708103 Z M98.1291058,1.76069839 L97.5359258,1.76069839 C97.4289938,1.76069839 97.3438737,1.8480423 97.3438737,1.95860421 L97.3449377,1.95860421 L97.3449377,3.36826855 C97.3449377,3.47772483 97.4295257,3.56506874 97.5364577,3.56506874 C97.6428577,3.56506874 97.7242537,3.47883045 97.7242537,3.36826855 L97.7242537,2.97909062 L98.0274937,2.97909062 L98.3961697,3.4639046 C98.4408578,3.52084397 98.4977818,3.56562155 98.5823697,3.56562155 C98.6728098,3.56562155 98.7616538,3.4937563 98.7616538,3.38430002 C98.7616538,3.32349097 98.7377138,3.28313588 98.7004738,3.23338301 L98.4387297,2.90169728 C98.6456777,2.81103653 98.7824017,2.63911276 98.7824017,2.3571799 L98.7824017,2.3516518 C98.7824017,2.18580893 98.7292018,2.04263126 98.6313138,1.94367835 C98.5243818,1.82648273 98.3525457,1.76069839 98.1291058,1.76069839 L98.1291058,1.76069839 Z" id="Fill-14" fill="#000000" fill-rule="nonzero"></path>
+ </g>
+ </g>
+</svg>
diff --git a/v1.9.4/website/public/img/logo-hashicorp.svg b/v1.9.4/website/public/img/logo-hashicorp.svg
new file mode 100644
index 0000000..597cd77
--- /dev/null
+++ b/v1.9.4/website/public/img/logo-hashicorp.svg
@@ -0,0 +1,6 @@
+<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 179.05 60.01">
+ <path class="text" fill="#000000" d="M61.23 7.86V4.63h-3v3.23h-1.46V.11h1.51v3.25h3V.11h1.51v7.75zm7 0h-1.2L67 7.48a3.28 3.28 0 0 1-1.78.52c-1.06 0-1.52-.7-1.52-1.66 0-1.14.51-1.57 1.7-1.57h1.4v-.62c0-.62-.18-.84-1.11-.84a8.46 8.46 0 0 0-1.61.17l-.18-1.07a7.89 7.89 0 0 1 2-.26c1.83 0 2.37.62 2.37 2zM66.8 5.75h-1.08c-.48 0-.61.13-.61.55s.13.56.59.56a2.37 2.37 0 0 0 1.1-.29zM71.31 8a7.12 7.12 0 0 1-2-.32l.2-1.07a6.77 6.77 0 0 0 1.73.24c.65 0 .74-.14.74-.56s-.07-.52-1-.73c-1.42-.33-1.59-.68-1.59-1.76s.51-1.62 2.18-1.62a8 8 0 0 1 1.75.2l-.14 1.11a10.66 10.66 0 0 0-1.6-.16c-.63 0-.74.14-.74.48s0 .48.82.68c1.63.41 1.78.62 1.78 1.77S73.07 8 71.31 8zM78 7.86V4c0-.3-.13-.45-.47-.45A4.14 4.14 0 0 0 76 4v3.86h-1.46V0L76 .22v2.47a5.31 5.31 0 0 1 2.13-.54c1 0 1.32.65 1.32 1.65v4.06zm2.68-6.38V.11h1.46v1.37zm0 6.38V2.27h1.46v5.59zm2.62-5.54c0-1.4.85-2.22 2.83-2.22a9.37 9.37 0 0 1 2.16.25l-.17 1.25a12.21 12.21 0 0 0-1.95-.2c-1 0-1.37.34-1.37 1.16V5.5c0 .81.33 1.16 1.37 1.16a12.21 12.21 0 0 0 1.95-.2l.17 1.25a9.37 9.37 0 0 1-2.16.29c-2 0-2.83-.81-2.83-2.22zM91.51 8C89.52 8 89 6.92 89 5.77V4.36c0-1.15.54-2.2 2.53-2.2S94 3.21 94 4.36v1.41C94 6.92 93.51 8 91.51 8zm0-4.63c-.78 0-1.08.33-1.08 1v1.5c0 .63.3 1 1.08 1s1.08-.33 1.08-1V4.31c0-.63-.3-.96-1.08-.96zm6.64.09a11.57 11.57 0 0 0-1.54.81v3.6h-1.46v-5.6h1.23l.1.62A6.63 6.63 0 0 1 98 2.15zM104 6a1.73 1.73 0 0 1-1.92 2 8.36 8.36 0 0 1-1.55-.16v2.26l-1.53.21v-8h1.16l.14.47a3.15 3.15 0 0 1 1.84-.59c1.17 0 1.79.67 1.79 1.94zm-3.48.63a6.72 6.72 0 0 0 1.29.15c.53 0 .73-.24.73-.75v-2c0-.46-.18-.71-.72-.71a2.11 2.11 0 0 0-1.3.51z"/>
+ <path class="p-front" fill="#02a8ef" d="M0 7.34l19.45 11.24v41.43L0 48.77V7.34z"/>
+ <path class="p-back" fill="#02a8ef" d="M29.07 12.19L7.94 0v8.47l14.37 8.3v25.36L29.07 46c4.19 2.42 7.61 1 7.61-3.22V24.19c0-4.19-3.42-9.59-7.61-12z"/>
+ <path class="text" fill="#000000" d="M56.77 14.1h12.48c7.4 0 10.13 3 10.13 8.65v4.37c0 5.57-3 8.6-10.42 8.6h-6.14v10.37h-6.05zm12.15 5.33h-6.1v11h6.1c3.41 0 4.42-1.25 4.42-3.89v-3.32c0-2.64-1.11-3.79-4.42-3.79zm30.93 26.66H95l-.43-1.58a12.79 12.79 0 0 1-7 2.07c-4.27 0-6.1-2.93-6.1-7 0-4.76 2.07-6.58 6.82-6.58H94v-2.43c0-2.59-.72-3.51-4.47-3.51a32.68 32.68 0 0 0-6.48.72l-.72-4.47a30.52 30.52 0 0 1 8-1.1c7.35 0 9.51 2.59 9.51 8.45zM94 37.25h-4.33c-1.92 0-2.45.53-2.45 2.31s.53 2.35 2.35 2.35a9.22 9.22 0 0 0 4.43-1.2zm9.35.34V31.2c0-6.29 2.74-9 10.09-9a20.15 20.15 0 0 1 5.72.86l-.72 4.8a21.31 21.31 0 0 0-4.85-.62c-3.36 0-4.37 1-4.37 3.89v6.48c0 2.88 1 3.89 4.37 3.89a19.79 19.79 0 0 0 4.85-.62l.72 4.8a19.29 19.29 0 0 1-5.72.86c-7.35.03-10.09-2.66-10.09-8.95zm19.5 8.5V13.14l5.86-.82v33.77zm19.89-23.39l-6.87 11.58L143 46.09h-6.44l-7.06-11.82 6.68-11.58zm12.2 19.06a24.51 24.51 0 0 0 7.16-1.1l.91 4.42a25.11 25.11 0 0 1-8.6 1.49c-7.35 0-9.89-3.41-9.89-9v-6.2c0-4.95 2.21-9.13 9.7-9.13s9.17 4.37 9.17 9.41v5h-13v1.2c-.02 2.81.99 3.91 4.55 3.91zm-4.56-9.85h7.44v-1.14c0-2.21-.67-3.75-3.55-3.75s-3.89 1.54-3.89 3.75zM179 27.6a45.86 45.86 0 0 0-6.2 3.41v15.08H167V22.7h4.95l.38 2.59a26.21 26.21 0 0 1 6.15-3.07z"/>
+</svg>
diff --git a/v1.9.4/website/public/img/logo-packer-padded.svg b/v1.9.4/website/public/img/logo-packer-padded.svg
new file mode 100644
index 0000000..4261cc7
--- /dev/null
+++ b/v1.9.4/website/public/img/logo-packer-padded.svg
@@ -0,0 +1,27 @@
+<svg width="225" height="84" viewBox="0 0 225 84" fill="none" xmlns="http://www.w3.org/2000/svg">
+<style>
+@media (prefers-color-scheme: dark) {
+ :root {
+ --text-color: #FFFFFF;
+ --background-color: #0d1117;
+ }
+}
+@media (prefers-color-scheme: light) {
+ :root {
+ --text-color: #000000;
+ --background-color: #FFFFFF;
+ }
+}
+.text {
+ fill: var(--text-color);
+}
+.background {
+ fill: var(--background-color);
+}
+</style>
+<rect class="background" width="225" height="84" fill="white"/>
+<path class="text" d="M84.23 19.86V16.63H81.23V19.86H79.77V12.11H81.28V15.36H84.28V12.11H85.79V19.86H84.23ZM91.23 19.86H90.03L90 19.48C89.469 19.8209 88.851 20.0015 88.22 20C87.16 20 86.7 19.3 86.7 18.34C86.7 17.2 87.21 16.77 88.4 16.77H89.8V16.15C89.8 15.53 89.62 15.31 88.69 15.31C88.1491 15.3151 87.61 15.372 87.08 15.48L86.9 14.41C87.5528 14.2381 88.225 14.1508 88.9 14.15C90.73 14.15 91.27 14.77 91.27 16.15L91.23 19.86ZM89.8 17.75H88.72C88.24 17.75 88.11 17.88 88.11 18.3C88.11 18.72 88.24 18.86 88.7 18.86C89.0848 18.8541 89.4623 18.7545 89.8 18.57V17.75ZM94.31 20C93.6315 19.9892 92.958 19.8814 92.31 19.68L92.51 18.61C93.0739 18.7644 93.6554 18.845 94.24 18.85C94.89 18.85 94.98 18.71 94.98 18.29C94.98 17.87 94.91 17.77 93.98 17.56C92.56 17.23 92.39 16.88 92.39 15.8C92.39 14.72 92.9 14.18 94.57 14.18C95.1589 14.1821 95.7458 14.2491 96.32 14.38L96.18 15.49C95.6515 15.3965 95.1166 15.343 94.58 15.33C93.95 15.33 93.84 15.47 93.84 15.81C93.84 16.15 93.84 16.29 94.66 16.49C96.29 16.9 96.44 17.11 96.44 18.26C96.44 19.41 96.07 20 94.31 20ZM101 19.86V16C101 15.7 100.87 15.55 100.53 15.55C99.9957 15.5994 99.476 15.7523 99 16V19.86H97.54V12L99 12.22V14.69C99.6646 14.3635 100.39 14.1795 101.13 14.15C102.13 14.15 102.45 14.8 102.45 15.8V19.86H101ZM103.68 13.48V12.11H105.14V13.48H103.68ZM103.68 19.86V14.27H105.14V19.86H103.68ZM106.3 14.32C106.3 12.92 107.15 12.1 109.13 12.1C109.857 12.0992 110.582 12.1831 111.29 12.35L111.12 13.6C110.476 13.4812 109.824 13.4143 109.17 13.4C108.17 13.4 107.8 13.74 107.8 14.56V17.5C107.8 18.31 108.13 18.66 109.17 18.66C109.824 18.6457 110.476 18.5788 111.12 18.46L111.29 19.71C110.584 19.8904 109.859 19.9877 109.13 20C107.13 20 106.3 19.19 106.3 17.78V14.32ZM114.51 20C112.52 20 112 18.92 112 17.77V16.36C112 15.21 112.54 14.16 114.53 14.16C116.52 14.16 117 15.21 117 16.36V17.77C117 18.92 116.51 20 114.51 20ZM114.51 15.37C113.73 15.37 113.43 15.7 113.43 16.37V17.87C113.43 18.5 113.73 18.87 114.51 18.87C115.29 18.87 115.59 18.54 115.59 17.87V16.31C115.59 15.68 115.29 15.35 114.51 15.35V15.37ZM121.15 15.46C120.617 15.691 120.102 15.9617 119.61 16.27V19.87H118.15V14.27H119.38L119.48 14.89C119.953 14.5795 120.464 14.3308 121 14.15L121.15 15.46ZM127 18C127.044 18.2656 127.026 18.5378 126.946 18.7949C126.866 19.0521 126.728 19.2871 126.541 19.4813C126.355 19.6755 126.126 19.8235 125.872 19.9135C125.618 20.0036 125.347 20.0332 125.08 20C124.559 19.995 124.041 19.9415 123.53 19.84V22.1L122 22.31V14.31H123.16L123.3 14.78C123.836 14.3954 124.48 14.189 125.14 14.19C126.31 14.19 126.93 14.86 126.93 16.13L127 18ZM123.52 18.63C123.944 18.7215 124.376 18.7718 124.81 18.78C125.34 18.78 125.54 18.54 125.54 18.03V16.03C125.54 15.57 125.36 15.32 124.82 15.32C124.341 15.3375 123.883 15.5174 123.52 15.83V18.63Z" fill="black"/>
+<path d="M23 19.34L42.45 30.58V72.01L23 60.77V19.34Z" fill="#02a8ef"/>
+<path d="M52.07 24.19L30.94 12V20.47L45.31 28.77V54.13L52.07 58C56.26 60.42 59.68 59 59.68 54.78V36.19C59.68 32 56.26 26.6 52.07 24.19Z" fill="#02a8ef"/>
+<path class="text" d="M79.77 26.1H92.25C99.65 26.1 102.38 29.1 102.38 34.75V39.12C102.38 44.69 99.38 47.72 91.96 47.72H85.82V58.09H79.77V26.1ZM91.92 31.43H85.82V42.43H91.92C95.33 42.43 96.34 41.18 96.34 38.54V35.22C96.34 32.58 95.23 31.43 91.92 31.43ZM122.85 58.09H118L117.57 56.51C115.487 57.8653 113.055 58.5846 110.57 58.58C106.3 58.58 104.47 55.65 104.47 51.58C104.47 46.82 106.54 45 111.29 45H117V42.57C117 39.98 116.28 39.06 112.53 39.06C110.351 39.0834 108.181 39.3246 106.05 39.78L105.33 35.31C107.936 34.5906 110.626 34.2207 113.33 34.21C120.68 34.21 122.84 36.8 122.84 42.66L122.85 58.09ZM117 49.25H112.67C110.75 49.25 110.22 49.78 110.22 51.56C110.22 53.34 110.75 53.91 112.57 53.91C114.124 53.8898 115.648 53.477 117 52.71V49.25ZM126.35 49.59V43.2C126.35 36.91 129.09 34.2 136.44 34.2C138.378 34.2101 140.305 34.4997 142.16 35.06L141.44 39.86C139.852 39.4679 138.225 39.2599 136.59 39.24C133.23 39.24 132.22 40.24 132.22 43.13V49.61C132.22 52.49 133.22 53.5 136.59 53.5C138.226 53.4946 139.855 53.2864 141.44 52.88L142.16 57.68C140.307 58.2525 138.379 58.5425 136.44 58.54C129.09 58.57 126.35 55.88 126.35 49.59ZM145.85 58.09V25.14L151.71 24.32V58.09H145.85ZM165.74 34.7L158.87 46.28L166 58.09H159.56L152.5 46.27L159.18 34.69L165.74 34.7ZM177.94 53.76C180.368 53.75 182.781 53.3793 185.1 52.66L186.01 57.08C183.252 58.0749 180.342 58.5792 177.41 58.57C170.06 58.57 167.52 55.16 167.52 49.57V43.37C167.52 38.42 169.73 34.24 177.22 34.24C184.71 34.24 186.39 38.61 186.39 43.65V48.65H173.39V49.85C173.37 52.66 174.38 53.76 177.94 53.76ZM173.38 43.91H180.82V42.77C180.82 40.56 180.15 39.02 177.27 39.02C174.39 39.02 173.38 40.56 173.38 42.77V43.91ZM202 39.6C199.849 40.5753 197.776 41.7154 195.8 43.01V58.09H190V34.7H194.95L195.33 37.29C197.236 36.0011 199.304 34.9689 201.48 34.22L202 39.6Z" fill="black"/>
+</svg>
diff --git a/v1.9.4/website/public/img/logo-text.svg b/v1.9.4/website/public/img/logo-text.svg
new file mode 100644
index 0000000..195e3d5
--- /dev/null
+++ b/v1.9.4/website/public/img/logo-text.svg
@@ -0,0 +1,5 @@
+<svg xmlns="http://www.w3.org/2000/svg" viewBox="423 368 142 54">
+ <path class="p-front" fill="#02a8ef" d="M423.046 374.78l17.42 9.96v36.717l-17.42-9.958"/>
+ <path class="p-back" fill="#02a8ef" d="M449.09 379.072l-18.935-10.79v7.493l12.876 7.356v22.485l6.06 3.443c3.75 2.14 6.82.858 6.82-2.85V389.71c0-3.71-3.07-8.497-6.82-10.638"/>
+ <path class="text" fill="#000000" d="M479.05 387.476h-4.55v8.194h4.55c2.542 0 3.294-.935 3.294-2.912v-2.443c0-1.977-.823-2.84-3.295-2.84zm-9.063-3.99h9.312c5.513 0 7.554 2.264 7.554 6.47v3.27c0 4.17-2.22 6.432-7.772 6.432H474.5v7.764h-4.513v-23.935zm28.12 17.324h-3.225c-1.433 0-1.827.394-1.827 1.725 0 1.22.394 1.76 1.755 1.76 1.29 0 2.472-.43 3.296-.898v-2.588zm4.37 6.612h-3.583l-.323-1.186c-1.572 1.042-3.433 1.546-5.19 1.546-3.19 0-4.55-2.193-4.55-5.212 0-3.557 1.54-4.923 5.088-4.923h4.19v-1.833c0-1.94-.537-2.624-3.33-2.624-1.576 0-3.295.216-4.835.54l-.536-3.343c1.647-.503 4.046-.827 5.98-.827 5.48 0 7.092 1.94 7.092 6.326v11.536zm3.15-6.362v-4.78c0-4.707 2.04-6.72 7.524-6.72 1.22 0 2.976.216 4.265.647l-.537 3.594c-1.182-.32-2.757-.463-3.618-.463-2.508 0-3.26.755-3.26 2.91v4.853c0 2.155.752 2.91 3.26 2.91 1.11 0 2.363-.144 3.617-.467l.537 3.595c-1.146.394-2.83.646-4.26.646-5.483 0-7.524-2.01-7.524-6.72m29.905-11.143l-5.12 8.66 5.335 8.845h-4.8l-5.264-8.842 4.98-8.66h4.87zm-14.827 17.505V382.77l4.37-.61v25.264h-4.37zm20.702-10.603h5.553v-.86c0-1.655-.5-2.805-2.65-2.805s-2.902 1.15-2.902 2.804v.86zm3.403 7.37c1.683 0 3.44-.254 5.337-.83l.68 3.308c-1.97.755-4.334 1.114-6.41 1.114-5.48 0-7.378-2.55-7.378-6.754v-4.636c0-3.703 1.647-6.83 7.235-6.83 5.586 0 6.84 3.27 6.84 7.044v3.738h-9.706v.9c0 2.118.756 2.946 3.406 2.946zm18.52-10.604c-1.684.755-3.045 1.546-4.62 2.552v11.285h-4.37V389.92h3.69l.284 1.94c.968-.646 3.045-1.868 4.585-2.3l.43 4.025z"/>
+</svg>
diff --git a/v1.9.4/website/public/img/og-image.png b/v1.9.4/website/public/img/og-image.png
new file mode 100644
index 0000000..70448ed
--- /dev/null
+++ b/v1.9.4/website/public/img/og-image.png
Binary files differ
diff --git a/v1.9.4/website/public/img/packer-signed-urls.png b/v1.9.4/website/public/img/packer-signed-urls.png
new file mode 100644
index 0000000..56dd1cc
--- /dev/null
+++ b/v1.9.4/website/public/img/packer-signed-urls.png
Binary files differ
diff --git a/v1.9.4/website/public/img/product-features-list/continuous-delivery.svg b/v1.9.4/website/public/img/product-features-list/continuous-delivery.svg
new file mode 100644
index 0000000..c58cfbb
--- /dev/null
+++ b/v1.9.4/website/public/img/product-features-list/continuous-delivery.svg
@@ -0,0 +1,4 @@
+<svg width="72" height="72" viewBox="0 0 72 72" fill="none" xmlns="http://www.w3.org/2000/svg">
+<rect width="72" height="72" fill="#F0FAFF"/>
+<path d="M41.0732 45.1918L47.9613 27.6476C48.0202 27.471 48.0202 27.2944 47.9025 27.1177L47.8436 27.0589C47.8436 27.0589 47.7847 27.0589 47.7847 27C47.7847 27 47.7847 27 47.7258 27C47.7258 27 47.7258 27 47.667 27C47.667 27 47.667 27 47.6081 27C47.6081 27 47.6081 27 47.5492 27C47.5492 27 47.5492 27 47.4903 27H47.4315L24.3532 33.0051C24.3532 33.0051 24.3532 33.0051 24.2944 33.0051C24.2944 33.0051 24.2355 33.0051 24.2355 33.0639L24.1766 33.1228C24 33.1817 24 33.3583 24 33.5349C24 33.5349 24 33.5349 24 33.5938C24 33.5938 24 33.5938 24 33.6527V33.7115C24 33.7115 24 33.7704 24.0589 33.7704L24.1177 33.8293L30.476 38.1859L31.418 44.3675C31.418 44.3675 31.418 44.3675 31.418 44.4264C31.418 44.4264 31.418 44.4264 31.418 44.4853C31.418 44.4853 31.418 44.4853 31.418 44.5442C31.418 44.5442 31.418 44.5442 31.418 44.603C31.418 44.603 31.418 44.603 31.418 44.6619C31.418 44.7208 31.418 44.6619 31.418 44.7208V44.7797C31.418 44.8385 31.4769 44.8385 31.4769 44.8974C31.5357 44.8974 31.5357 44.9563 31.5946 44.9563C31.6535 44.9563 31.6535 44.9563 31.7124 44.9563H31.7712C31.7712 44.9563 31.7712 44.9563 31.8301 44.9563H31.889C31.889 44.9563 31.889 44.9563 31.9479 44.9563C31.9479 44.9563 32.0067 44.9563 32.0067 44.8974L35.8924 42.2481L40.1312 45.545C40.1901 45.6039 40.249 45.6039 40.3078 45.6628C40.4845 45.7216 40.7199 45.6628 40.8377 45.4861C41.0143 45.3095 41.0143 45.2506 41.0732 45.1918C41.0732 45.2506 41.0732 45.2506 41.0732 45.1918ZM34.4205 39.6577L46.4895 29.0606L40.4845 44.3087L34.4205 39.6577ZM31.0059 37.3617L25.5307 33.5938L44.8999 28.5896L31.0059 37.3617ZM43.1337 30.8267L33.4197 39.3045C33.4197 39.3045 33.4197 39.3045 33.3608 39.3633C33.3608 39.4222 33.3019 39.4222 33.3019 39.4811L32.1834 42.5425L31.4769 38.127L43.1337 30.8267ZM32.8898 43.1901L33.9495 40.3642L35.3625 41.4828L32.8898 43.1901Z" fill="#63D0FF"/>
+</svg>
diff --git a/v1.9.4/website/public/img/product-features-list/demo-creation.svg b/v1.9.4/website/public/img/product-features-list/demo-creation.svg
new file mode 100644
index 0000000..c5da8c8
--- /dev/null
+++ b/v1.9.4/website/public/img/product-features-list/demo-creation.svg
@@ -0,0 +1,6 @@
+<svg width="72" height="72" viewBox="0 0 72 72" fill="none" xmlns="http://www.w3.org/2000/svg">
+<rect width="72" height="72" fill="#F0FAFF"/>
+<path fill-rule="evenodd" clip-rule="evenodd" d="M27 29C27 27.8954 27.8954 27 29 27L43 27C44.1046 27 45 27.8954 45 29V43C45 44.1046 44.1046 45 43 45H29C27.8954 45 27 44.1046 27 43L27 29Z" stroke="#63D0FF" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"/>
+<path d="M27 33H45" stroke="#63D0FF" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"/>
+<path d="M33 45V33" stroke="#63D0FF" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"/>
+</svg>
diff --git a/v1.9.4/website/public/img/product-features-list/deployment.svg b/v1.9.4/website/public/img/product-features-list/deployment.svg
new file mode 100644
index 0000000..079e245
--- /dev/null
+++ b/v1.9.4/website/public/img/product-features-list/deployment.svg
@@ -0,0 +1,4 @@
+<svg width="72" height="72" viewBox="0 0 72 72" fill="none" xmlns="http://www.w3.org/2000/svg">
+<rect width="72" height="72" fill="#F0FAFF"/>
+<path d="M29.6401 45.7152C29.4499 45.7152 29.2868 45.7967 29.151 45.9054L26.7324 48.324C26.5965 48.4599 26.5422 48.623 26.5422 48.8132C26.5422 49.0034 26.6237 49.1665 26.7324 49.3023C26.8683 49.4382 27.0313 49.4926 27.2215 49.4926C27.4118 49.4926 27.5748 49.411 27.7107 49.3023L30.1293 46.8838C30.2651 46.7479 30.3195 46.5848 30.3195 46.3946C30.3195 46.2044 30.238 46.0413 30.1293 45.9054C29.9934 45.7967 29.8303 45.7152 29.6401 45.7152ZM50.2932 21.6924C50.0758 21.475 49.7497 21.3391 49.4236 21.3391C49.3149 21.3391 49.2062 21.3663 49.0975 21.3935L46.8148 21.9913C42.8201 23.0511 38.934 25.1165 35.6458 27.9427C35.3741 28.1872 35.3197 28.6221 35.5643 28.8938C35.7002 29.0569 35.8904 29.1384 36.0806 29.1384C36.2437 29.1384 36.4067 29.084 36.5154 28.9753C39.6949 26.285 43.3636 24.3284 47.1953 23.2957L49.2606 22.7522L48.7171 24.8175C47.3311 30.0352 44.1788 34.9539 39.8852 38.6497L39.858 38.6769C39.8036 38.704 39.8036 38.704 39.7764 38.7312C39.7493 38.7584 39.7493 38.7584 39.7493 38.7856C39.7493 38.8127 39.7221 38.8127 39.7221 38.8399C39.7221 38.8671 39.6949 38.8671 39.6949 38.8943C39.6949 38.9214 39.6677 38.9486 39.6677 38.9486C39.6677 38.9758 39.6677 39.003 39.6406 39.003C39.6406 39.0301 39.6406 39.0573 39.6406 39.0573C39.6406 39.0845 39.6406 39.1117 39.6406 39.1388V39.166L39.8852 44.8456C39.9123 45.2532 39.6949 45.6609 39.3416 45.8783L34.6947 48.8132L34.2055 43.8401C34.1784 43.4869 33.8794 43.2151 33.5262 43.2151C33.499 43.2151 33.4718 43.2151 33.4718 43.2151C33.0914 43.2423 32.8196 43.5956 32.874 43.9488L33.4446 50.0361C33.4718 50.2806 33.6077 50.4709 33.8251 50.5796C33.9066 50.6339 34.0153 50.6611 34.124 50.6611C34.2599 50.6611 34.3686 50.6339 34.4773 50.5524L40.0482 47.0196C40.8091 46.5576 41.2711 45.6609 41.2167 44.7913L40.9993 39.4378L41.108 39.3562C45.4289 35.5245 48.6084 30.47 50.0487 25.1436L50.6465 22.8609C50.728 22.4805 50.6193 22.0185 50.2932 21.6924ZM27.0857 32.1548H27.1128L32.8196 32.4266C33.1729 32.4266 33.4718 32.1548 33.499 31.7744C33.499 31.5841 33.4446 31.4211 33.3359 31.2852C33.2001 31.1493 33.037 31.0678 32.874 31.0678L27.1944 30.7961C27.1672 30.7961 27.14 30.7961 27.1128 30.7961C26.2704 30.7961 25.428 31.258 24.966 31.9646L21.4332 37.5355C21.2973 37.7257 21.2973 37.9975 21.406 38.2149C21.5147 38.4323 21.7593 38.5682 22.0039 38.5682C22.2757 38.5682 24.504 38.7856 27.6563 39.1117C27.7379 39.1117 27.7922 39.1388 27.8466 39.1932L28.064 39.4106L22.955 44.5739C22.8192 44.7097 22.7648 44.8728 22.7648 45.063C22.7648 45.2532 22.8463 45.4163 22.955 45.5522C23.0909 45.688 23.254 45.7424 23.4442 45.7424C23.6344 45.7424 23.7975 45.6609 23.9333 45.5522L29.0694 40.4161L29.8847 41.2313C30.0206 41.3672 30.1836 41.4215 30.3738 41.4215C30.5641 41.4215 30.7271 41.34 30.863 41.2313C30.9989 41.0954 31.0532 40.9324 31.0532 40.7422C31.0532 40.5519 30.9717 40.3889 30.863 40.253L28.852 38.2421C28.5803 37.9703 28.227 37.8073 27.8466 37.7529C26.4335 37.617 24.8301 37.454 23.6616 37.3453L23.2268 37.2909L26.1617 32.6711C26.2976 32.3722 26.7052 32.1548 27.0857 32.1548Z" fill="#63D0FF"/>
+</svg>
diff --git a/v1.9.4/website/public/img/product-features-list/portability.svg b/v1.9.4/website/public/img/product-features-list/portability.svg
new file mode 100644
index 0000000..756c6e8
--- /dev/null
+++ b/v1.9.4/website/public/img/product-features-list/portability.svg
@@ -0,0 +1,15 @@
+<svg width="72" height="72" viewBox="0 0 72 72" fill="none" xmlns="http://www.w3.org/2000/svg">
+<rect width="72" height="72" fill="#F0FAFF"/>
+<g clip-path="url(#clip0)">
+<path fill-rule="evenodd" clip-rule="evenodd" d="M32.5 35.25C32.5 34.1454 33.3954 33.25 34.5 33.25H45.5C46.6046 33.25 47.5 34.1454 47.5 35.25V41.75C47.5 42.8546 46.6046 43.75 45.5 43.75H34.5C33.3954 43.75 32.5 42.8546 32.5 41.75V35.25Z" stroke="#63D0FF" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"/>
+<path d="M37 46.75H43" stroke="#63D0FF" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"/>
+<path d="M40 43.75V46.75" stroke="#63D0FF" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"/>
+<path d="M41 30L31 30C29.8954 30 29 30.8954 29 32V39" stroke="#63D0FF" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"/>
+<path d="M35 27H28C26.8954 27 26 27.8954 26 29V34" stroke="#63D0FF" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"/>
+</g>
+<defs>
+<clipPath id="clip0">
+<rect width="24" height="24" fill="white" transform="translate(24 24)"/>
+</clipPath>
+</defs>
+</svg>
diff --git a/v1.9.4/website/public/img/product-features-list/prod-parity.svg b/v1.9.4/website/public/img/product-features-list/prod-parity.svg
new file mode 100644
index 0000000..e864aed
--- /dev/null
+++ b/v1.9.4/website/public/img/product-features-list/prod-parity.svg
@@ -0,0 +1,6 @@
+<svg width="72" height="72" viewBox="0 0 72 72" fill="none" xmlns="http://www.w3.org/2000/svg">
+<rect width="72" height="72" fill="#F0FAFF"/>
+<path d="M36 36L26 31L36 26L46 31L36 36Z" stroke="#63D0FF" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"/>
+<path d="M26 41L36 46L46 41" stroke="#63D0FF" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"/>
+<path d="M26 36L36 41L46 36" stroke="#63D0FF" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"/>
+</svg>
diff --git a/v1.9.4/website/public/img/product-features-list/stability.svg b/v1.9.4/website/public/img/product-features-list/stability.svg
new file mode 100644
index 0000000..73e7ddd
--- /dev/null
+++ b/v1.9.4/website/public/img/product-features-list/stability.svg
@@ -0,0 +1,5 @@
+<svg width="72" height="72" viewBox="0 0 72 72" fill="none" xmlns="http://www.w3.org/2000/svg">
+<rect width="72" height="72" fill="#F0FAFF"/>
+<path fill-rule="evenodd" clip-rule="evenodd" d="M35.7425 24.0359C35.8702 23.988 36.011 23.988 36.1387 24.0359L37.0849 24.3908L37.0858 24.3911C39.4436 25.2535 41.9202 25.6005 44.4012 25.4862L45.1649 25.4274C45.3215 25.4154 45.4761 25.4692 45.5914 25.576C45.7067 25.6827 45.7722 25.8327 45.7722 25.9899V37.5743C45.7722 40.5309 44.1595 43.2591 41.1576 45.011L41.1569 45.0114L41.1562 45.0118L36.2893 47.9201C36.1111 48.0266 35.8889 48.0266 35.7107 47.9201L30.8444 45.0122L30.8433 45.0116L30.8424 45.011C27.8405 43.2591 26.2278 40.5309 26.2278 37.5743V25.9899C26.2278 25.8314 26.2945 25.6802 26.4115 25.5733C26.5285 25.4665 26.6851 25.4137 26.8429 25.4281L27.4839 25.4864C29.9667 25.6003 32.4988 25.2523 34.792 24.3924L35.7425 24.0359ZM35.9406 25.1665L35.1881 25.4487C32.7326 26.3695 30.0414 26.7347 27.4191 26.6127C27.4108 26.6123 27.4025 26.6118 27.3943 26.611L27.3559 26.6075V37.5743C27.3559 40.0826 28.7129 42.4628 31.4128 44.0377L31.418 44.0407L36 46.7788L40.5861 44.0383L40.5872 44.0377C43.2871 42.4628 44.6441 40.0826 44.6441 37.5743V26.599L44.4791 26.6117C44.4734 26.6121 44.4678 26.6125 44.4621 26.6127C41.8375 26.7348 39.2077 26.3687 36.6973 25.4502L36.6939 25.449L36.693 25.4487L35.9406 25.1665Z" fill="#63D0FF"/>
+<path fill-rule="evenodd" clip-rule="evenodd" d="M31.5693 36.5061C31.3396 36.273 31.3423 35.8978 31.5754 35.6681C31.8085 35.4383 32.1836 35.4411 32.4134 35.6742L34.5071 37.7985L37.8341 34.5194L40.7391 31.6562C40.9722 31.4265 41.3474 31.4292 41.5771 31.6623C41.8068 31.8954 41.8041 32.2706 41.571 32.5003L34.495 39.4745L31.5693 36.5061Z" fill="#63D0FF"/>
+</svg>
diff --git a/v1.9.4/website/public/robots.txt b/v1.9.4/website/public/robots.txt
new file mode 100644
index 0000000..b4835a1
--- /dev/null
+++ b/v1.9.4/website/public/robots.txt
@@ -0,0 +1,3 @@
+User-agent: *
+Disallow: /404
+Disallow: /500
diff --git a/v1.9.4/website/redirects.js b/v1.9.4/website/redirects.js
new file mode 100644
index 0000000..7d56c6e
--- /dev/null
+++ b/v1.9.4/website/redirects.js
@@ -0,0 +1,92 @@
+/**
+ * Define your custom redirects within this file.
+ *
+ * Vercel's redirect documentation:
+ * https://nextjs.org/docs/api-reference/next.config.js/redirects
+ *
+ * Relative paths with fragments (#) are not supported.
+ * For destinations with fragments, use an absolute URL.
+ *
+ * Playground for testing url pattern matching: https://npm.runkit.com/path-to-regexp
+ *
+ * Note that redirects defined in a product's redirects file are applied to
+ * the developer.hashicorp.com domain, which is where the documentation content
+ * is rendered. Redirect sources should be prefixed with the product slug
+ * to ensure they are scoped to the product's section. Any redirects that are
+ * not prefixed with a product slug will be ignored.
+ */
+module.exports = [
+ /*
+ Example redirect:
+ {
+ source: '/packer/docs/internal-docs/my-page',
+ destination: '/packer/docs/internals/my-page',
+ permanent: true,
+ },
+ */
+ /**
+ * BEGIN EMPTY PAGE REDIRECTS
+ * These redirects ensure some empty placeholder pages, dating back to when
+ * "Overview" pages were a requirement, cannot be visited.
+ *
+ * These redirects can likely be removed once we have content API "pruning"
+ * in place. That is, assuming the page at https://developer.hashicorp.com/packer/docs/templates/hcl_templates/functions/conversion
+ * is still empty, the content API response from the content URL for that page
+ * (https://content.hashicorp.com/api/content/packer/doc/latest/docs/templates/hcl_templates/functions/conversion)
+ * should be a 404. Asana task for this "don't return content for empty" work:
+ * https://app.asana.com/0/1100423001970639/1202110665886351/f
+ */
+ {
+ source: '/packer/docs/templates/hcl_templates/functions/collection',
+ destination: '/packer/docs/templates/hcl_templates/functions',
+ permanent: true,
+ },
+ {
+ source: '/packer/docs/templates/hcl_templates/functions/contextual',
+ destination: '/packer/docs/templates/hcl_templates/functions',
+ permanent: true,
+ },
+ {
+ source: '/packer/docs/templates/hcl_templates/functions/conversion',
+ destination: '/packer/docs/templates/hcl_templates/functions',
+ permanent: true,
+ },
+ {
+ source: '/packer/docs/templates/hcl_templates/functions/crypto',
+ destination: '/packer/docs/templates/hcl_templates/functions',
+ permanent: true,
+ },
+ {
+ source: '/packer/docs/templates/hcl_templates/functions/encoding',
+ destination: '/packer/docs/templates/hcl_templates/functions',
+ permanent: true,
+ },
+ {
+ source: '/packer/docs/templates/hcl_templates/functions/file',
+ destination: '/packer/docs/templates/hcl_templates/functions',
+ permanent: true,
+ },
+ {
+ source: '/packer/docs/templates/hcl_templates/functions/ipnet',
+ destination: '/packer/docs/templates/hcl_templates/functions',
+ permanent: true,
+ },
+ {
+ source: '/packer/docs/templates/hcl_templates/functions/numeric',
+ destination: '/packer/docs/templates/hcl_templates/functions',
+ permanent: true,
+ },
+ {
+ source: '/packer/docs/templates/hcl_templates/functions/string',
+ destination: '/packer/docs/templates/hcl_templates/functions',
+ permanent: true,
+ },
+ {
+ source: '/packer/docs/templates/hcl_templates/functions/uuid',
+ destination: '/packer/docs/templates/hcl_templates/functions',
+ permanent: true,
+ },
+ /**
+ * END EMPTY PAGE REDIRECTS
+ */
+]
diff --git a/v1.9.4/website/scripts/should-build.sh b/v1.9.4/website/scripts/should-build.sh
new file mode 100644
index 0000000..9760f47
--- /dev/null
+++ b/v1.9.4/website/scripts/should-build.sh
@@ -0,0 +1,18 @@
+#!/usr/bin/env bash
+
+######################################################
+# NOTE: This file is managed by the Digital Team's #
+# Terraform configuration @ hashicorp/mktg-terraform #
+######################################################
+
+# This is run during the website build step to determine if we should skip the build or not.
+# More information: https://vercel.com/docs/platform/projects#ignored-build-step
+
+if [[ "$VERCEL_GIT_COMMIT_REF" == "stable-website" ]] ; then
+ # Proceed with the build if the branch is stable-website
+ echo "✅ - Build can proceed"
+ exit 1;
+else
+ # Check for differences in the website directory
+ git diff --quiet HEAD^ HEAD ./
+fi
\ No newline at end of file
diff --git a/v1.9.4/website/scripts/tsconfig.json b/v1.9.4/website/scripts/tsconfig.json
new file mode 100644
index 0000000..50800aa
--- /dev/null
+++ b/v1.9.4/website/scripts/tsconfig.json
@@ -0,0 +1,6 @@
+{
+ "compilerOptions": {
+ "esModuleInterop": true,
+ "module": "CommonJS"
+ }
+}
diff --git a/v1.9.4/website/scripts/website-build.sh b/v1.9.4/website/scripts/website-build.sh
new file mode 100755
index 0000000..802cc8e
--- /dev/null
+++ b/v1.9.4/website/scripts/website-build.sh
@@ -0,0 +1,52 @@
+######################################################
+# NOTE: This file is managed by the Digital Team's #
+# Terraform configuration @ hashicorp/mktg-terraform #
+######################################################
+
+# Repo which we are cloning and executing npm run build:deploy-preview within
+REPO_TO_CLONE=dev-portal
+# Set the subdirectory name for the base project
+PREVIEW_DIR=website-preview
+# The directory we want to clone the project into
+CLONE_DIR=website-preview
+# The product for which we are building the deploy preview
+PRODUCT=packer
+# Preview mode, controls the UI rendered (either the product site or developer). Can be `io` or `developer`
+PREVIEW_MODE=developer
+
+# Get the git branch of the commit that triggered the deploy preview
+# This will power remote image assets in local and deploy previews
+CURRENT_GIT_BRANCH=$VERCEL_GIT_COMMIT_REF
+
+# This is where content files live, relative to the website-preview dir. If omitted, "../content" will be used
+LOCAL_CONTENT_DIR=
+
+from_cache=false
+
+if [ -d "$PREVIEW_DIR" ]; then
+ echo "$PREVIEW_DIR found"
+ CLONE_DIR="$PREVIEW_DIR-tmp"
+ from_cache=true
+fi
+
+# Clone the base project, if needed
+echo "⏳ Cloning the $REPO_TO_CLONE repo, this might take a while..."
+git clone --depth=1 "https://github.com/hashicorp/$REPO_TO_CLONE.git" "$CLONE_DIR"
+
+if [ "$from_cache" = true ]; then
+ echo "Setting up $PREVIEW_DIR"
+ cp -R "./$CLONE_DIR/." "./$PREVIEW_DIR"
+fi
+
+# cd into the preview directory project
+cd "$PREVIEW_DIR"
+
+# Run the build:deploy-preview start script
+PREVIEW_FROM_REPO=$PRODUCT \
+IS_CONTENT_PREVIEW=true \
+PREVIEW_MODE=$PREVIEW_MODE \
+REPO=$PRODUCT \
+HASHI_ENV=project-preview \
+LOCAL_CONTENT_DIR=$LOCAL_CONTENT_DIR \
+CURRENT_GIT_BRANCH=$CURRENT_GIT_BRANCH \
+npm run build:deploy-preview
\ No newline at end of file
diff --git a/v1.9.4/website/scripts/website-start.sh b/v1.9.4/website/scripts/website-start.sh
new file mode 100755
index 0000000..2e58c8b
--- /dev/null
+++ b/v1.9.4/website/scripts/website-start.sh
@@ -0,0 +1,44 @@
+######################################################
+# NOTE: This file is managed by the Digital Team's #
+# Terraform configuration @ hashicorp/mktg-terraform #
+######################################################
+
+# Repo which we are cloning and executing npm run build:deploy-preview within
+REPO_TO_CLONE=dev-portal
+# Set the subdirectory name for the dev-portal app
+PREVIEW_DIR=website-preview
+# The product for which we are building the deploy preview
+PRODUCT=packer
+# Preview mode, controls the UI rendered (either the product site or developer). Can be `io` or `developer`
+PREVIEW_MODE=developer
+
+# Get the git branch of the commit that triggered the deploy preview
+# This will power remote image assets in local and deploy previews
+CURRENT_GIT_BRANCH=$(git rev-parse --abbrev-ref HEAD)
+
+# This is where content files live, relative to the website-preview dir. If omitted, "../content" will be used
+LOCAL_CONTENT_DIR=
+
+should_pull=true
+
+# Clone the dev-portal project, if needed
+if [ ! -d "$PREVIEW_DIR" ]; then
+ echo "⏳ Cloning the $REPO_TO_CLONE repo, this might take a while..."
+ git clone --depth=1 https://github.com/hashicorp/$REPO_TO_CLONE.git "$PREVIEW_DIR"
+ should_pull=false
+fi
+
+cd "$PREVIEW_DIR"
+
+# If the directory already existed, pull to ensure the clone is fresh
+if [ "$should_pull" = true ]; then
+ git pull origin main
+fi
+
+# Run the dev-portal content-repo start script
+REPO=$PRODUCT \
+PREVIEW_FROM_REPO=$PRODUCT \
+LOCAL_CONTENT_DIR=$LOCAL_CONTENT_DIR \
+CURRENT_GIT_BRANCH=$CURRENT_GIT_BRANCH \
+PREVIEW_MODE=$PREVIEW_MODE \
+npm run start:local-preview
\ No newline at end of file
diff --git a/v1.9.4/website/vercel.json b/v1.9.4/website/vercel.json
new file mode 100644
index 0000000..0e6117e
--- /dev/null
+++ b/v1.9.4/website/vercel.json
@@ -0,0 +1,7 @@
+{
+ "version": 2,
+ "public": true,
+ "github": {
+ "silent": true
+ }
+}