Merge pull request #2 from hashicorp/master

merge from hashicorp/packer
This commit is contained in:
William 2020-02-15 23:13:38 -06:00 committed by GitHub
commit 807f39284d
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
216 changed files with 3322 additions and 2903 deletions

2
.gitattributes vendored
View File

@ -5,4 +5,6 @@
*.md text eol=lf
*.ps1 text eol=lf
*.hcl text eol=lf
go.mod text eol=lf
go.sum text eol=lf
common/test-fixtures/root/* eol=lf

View File

@ -259,6 +259,28 @@ 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=origin/master` flag to only lint new files added within a branch or pull-request. To run this check locally you can use the `ci-lint` make target. See [golangci-lint in CI](https://github.com/golangci/golangci-lint#faq) for more information.
```
make ci-lint
```
#### Running Unit Tests
You can run tests for individual packages using commands like this:

124
.golangci.yml Normal file
View File

@ -0,0 +1,124 @@
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: vendor
# 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

View File

@ -4,20 +4,21 @@ env:
os:
- osx
sudo: false
language: go
go:
- 1.12.x
script:
- df -h
- travis_wait make ci
branches:
only:
- master
matrix:
jobs:
fast_finish: true
include:
- go: "1.13.x"
name: "go test"
script:
- df -h
- travis_wait make ci
- go: "1.13.x"
name: "go lint"
script: travis_wait make ci-lint

View File

@ -1,19 +1,56 @@
## 1.5.2 (Upcoming)
** New Builder ** The vsphere-iso builder, previously maintained by JetBrains,
## 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]
@ -26,6 +63,9 @@ Packer team at HashiCorp moving forward. [GH-8480]
* 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]
@ -33,6 +73,7 @@ Packer team at HashiCorp moving forward. [GH-8480]
* 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]

View File

@ -18,7 +18,8 @@ GOLDFLAGS=-X $(GIT_IMPORT).GitCommit=$(GIT_COMMIT)$(GIT_DIRTY)
export GOLDFLAGS
.PHONY: bin checkversion ci default install-build-deps install-gen-deps fmt fmt-docs fmt-examples generate releasebin test testacc testrace
.PHONY: bin checkversion ci ci-lint default install-build-deps install-gen-deps fmt fmt-docs fmt-examples generate install-lint-deps lint \
releasebin test testacc testrace
default: install-build-deps install-gen-deps generate testrace dev releasebin package dev fmt fmt-check mode-check fmt-docs fmt-examples
@ -49,12 +50,16 @@ install-gen-deps: ## Install dependencies for code generation
# dir. `go get` will change our deps and the following deps are not part of
# out code dependencies; so a go mod tidy will remove them again. `go
# install` seems to install the last tagged version and we want to install
# master.
# master.
@(cd $(TEMPDIR) && GO111MODULE=on go get github.com/mna/pigeon@master)
@(cd $(TEMPDIR) && GO111MODULE=on go get github.com/alvaroloes/enumer@master)
@go install ./cmd/struct-markdown
@go install ./cmd/mapstructure-to-hcl2
install-lint-deps: ## Install linter dependencies
@echo "==> Updating linter dependencies..."
@curl -sSfL -q https://raw.githubusercontent.com/golangci/golangci-lint/master/install.sh | sh -s -- -b $(GOPATH)/bin v1.23.1
dev: ## Build and install a development build
@grep 'const VersionPrerelease = ""' version/version.go > /dev/null ; if [ $$? -eq 0 ]; then \
echo "ERROR: You must add prerelease tags to version/version.go prior to making a dev build."; \
@ -66,6 +71,20 @@ dev: ## Build and install a development build
@cp $(GOPATH)/bin/packer bin/packer
@cp $(GOPATH)/bin/packer pkg/$(GOOS)_$(GOARCH)
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=origin/master
fmt: ## Format Go code
@go fmt ./...

View File

@ -10,11 +10,11 @@ package chroot
import (
"context"
"errors"
"github.com/hashicorp/packer/builder"
"runtime"
"github.com/aws/aws-sdk-go/service/ec2"
"github.com/hashicorp/hcl/v2/hcldec"
"github.com/hashicorp/packer/builder"
awscommon "github.com/hashicorp/packer/builder/amazon/common"
"github.com/hashicorp/packer/common"
"github.com/hashicorp/packer/common/chroot"

View File

@ -41,6 +41,7 @@ type FlatConfig struct {
CustomEndpointEc2 *string `mapstructure:"custom_endpoint_ec2" required:"false" cty:"custom_endpoint_ec2"`
DecodeAuthZMessages *bool `mapstructure:"decode_authorization_messages" required:"false" cty:"decode_authorization_messages"`
InsecureSkipTLSVerify *bool `mapstructure:"insecure_skip_tls_verify" required:"false" cty:"insecure_skip_tls_verify"`
MaxRetries *int `mapstructure:"max_retries" required:"false" cty:"max_retries"`
MFACode *string `mapstructure:"mfa_code" required:"false" cty:"mfa_code"`
ProfileName *string `mapstructure:"profile" required:"false" cty:"profile"`
RawRegion *string `mapstructure:"region" required:"true" cty:"region"`
@ -112,6 +113,7 @@ func (*FlatConfig) HCL2Spec() map[string]hcldec.Spec {
"custom_endpoint_ec2": &hcldec.AttrSpec{Name: "custom_endpoint_ec2", Type: cty.String, Required: false},
"decode_authorization_messages": &hcldec.AttrSpec{Name: "decode_authorization_messages", Type: cty.Bool, Required: false},
"insecure_skip_tls_verify": &hcldec.AttrSpec{Name: "insecure_skip_tls_verify", Type: cty.Bool, Required: false},
"max_retries": &hcldec.AttrSpec{Name: "max_retries", Type: cty.Number, Required: false},
"mfa_code": &hcldec.AttrSpec{Name: "mfa_code", Type: cty.String, Required: false},
"profile": &hcldec.AttrSpec{Name: "profile", Type: cty.String, Required: false},
"region": &hcldec.AttrSpec{Name: "region", Type: cty.String, Required: false},

View File

@ -4,13 +4,13 @@ import (
"bytes"
"context"
"fmt"
"github.com/hashicorp/packer/builder"
"log"
"os"
"path/filepath"
"strings"
"github.com/aws/aws-sdk-go/service/ec2"
"github.com/hashicorp/packer/builder"
"github.com/hashicorp/packer/common"
"github.com/hashicorp/packer/helper/multistep"
"github.com/hashicorp/packer/packer"

View File

@ -3,10 +3,10 @@ package chroot
import (
"context"
"fmt"
"github.com/hashicorp/packer/builder"
"log"
"os"
"github.com/hashicorp/packer/builder"
"github.com/hashicorp/packer/helper/multistep"
"github.com/hashicorp/packer/packer"
)

View File

@ -60,6 +60,10 @@ type AccessConfig struct {
// This allows skipping TLS
// verification of the AWS EC2 endpoint. The default is false.
InsecureSkipTLSVerify bool `mapstructure:"insecure_skip_tls_verify" required:"false"`
// This is the maximum number of times an API call is retried, in the case
// where requests are being throttled or experiencing transient failures.
// The delay between the subsequent API calls increases exponentially.
MaxRetries int `mapstructure:"max_retries" required:"false"`
// The MFA
// [TOTP](https://en.wikipedia.org/wiki/Time-based_One-time_Password_Algorithm)
// code. This should probably be a user variable since it changes all the
@ -134,6 +138,9 @@ func (c *AccessConfig) Session() (*session.Session, error) {
}
config := aws.NewConfig().WithCredentialsChainVerboseErrors(true)
if c.MaxRetries > 0 {
config = config.WithMaxRetries(c.MaxRetries)
}
staticCreds := credentials.NewStaticCredentials(c.AccessKey, c.SecretKey, c.Token)
if _, err := staticCreds.Get(); err != credentials.ErrStaticCredentialsEmpty {

View File

@ -1,12 +1,12 @@
package common
import (
"github.com/hashicorp/packer/builder"
"reflect"
"testing"
"github.com/aws/aws-sdk-go/aws"
"github.com/aws/aws-sdk-go/service/ec2"
"github.com/hashicorp/packer/builder"
"github.com/hashicorp/packer/helper/multistep"
)

View File

@ -3,6 +3,7 @@ package common
import (
"context"
"fmt"
"github.com/aws/aws-sdk-go/aws"
"github.com/aws/aws-sdk-go/aws/session"
"github.com/aws/aws-sdk-go/service/ec2"

View File

@ -11,6 +11,7 @@ package ebs
import (
"context"
"fmt"
"github.com/aws/aws-sdk-go/service/ec2"
"github.com/aws/aws-sdk-go/service/iam"
"github.com/hashicorp/hcl/v2/hcldec"

View File

@ -21,6 +21,7 @@ type FlatConfig struct {
CustomEndpointEc2 *string `mapstructure:"custom_endpoint_ec2" required:"false" cty:"custom_endpoint_ec2"`
DecodeAuthZMessages *bool `mapstructure:"decode_authorization_messages" required:"false" cty:"decode_authorization_messages"`
InsecureSkipTLSVerify *bool `mapstructure:"insecure_skip_tls_verify" required:"false" cty:"insecure_skip_tls_verify"`
MaxRetries *int `mapstructure:"max_retries" required:"false" cty:"max_retries"`
MFACode *string `mapstructure:"mfa_code" required:"false" cty:"mfa_code"`
ProfileName *string `mapstructure:"profile" required:"false" cty:"profile"`
RawRegion *string `mapstructure:"region" required:"true" cty:"region"`
@ -147,6 +148,7 @@ func (*FlatConfig) HCL2Spec() map[string]hcldec.Spec {
"custom_endpoint_ec2": &hcldec.AttrSpec{Name: "custom_endpoint_ec2", Type: cty.String, Required: false},
"decode_authorization_messages": &hcldec.AttrSpec{Name: "decode_authorization_messages", Type: cty.Bool, Required: false},
"insecure_skip_tls_verify": &hcldec.AttrSpec{Name: "insecure_skip_tls_verify", Type: cty.Bool, Required: false},
"max_retries": &hcldec.AttrSpec{Name: "max_retries", Type: cty.Number, Required: false},
"mfa_code": &hcldec.AttrSpec{Name: "mfa_code", Type: cty.String, Required: false},
"profile": &hcldec.AttrSpec{Name: "profile", Type: cty.String, Required: false},
"region": &hcldec.AttrSpec{Name: "region", Type: cty.String, Required: false},

View File

@ -9,6 +9,7 @@ import (
"context"
"errors"
"fmt"
"github.com/aws/aws-sdk-go/service/ec2"
"github.com/aws/aws-sdk-go/service/iam"
"github.com/hashicorp/hcl/v2/hcldec"

View File

@ -64,6 +64,7 @@ type FlatConfig struct {
CustomEndpointEc2 *string `mapstructure:"custom_endpoint_ec2" required:"false" cty:"custom_endpoint_ec2"`
DecodeAuthZMessages *bool `mapstructure:"decode_authorization_messages" required:"false" cty:"decode_authorization_messages"`
InsecureSkipTLSVerify *bool `mapstructure:"insecure_skip_tls_verify" required:"false" cty:"insecure_skip_tls_verify"`
MaxRetries *int `mapstructure:"max_retries" required:"false" cty:"max_retries"`
MFACode *string `mapstructure:"mfa_code" required:"false" cty:"mfa_code"`
ProfileName *string `mapstructure:"profile" required:"false" cty:"profile"`
RawRegion *string `mapstructure:"region" required:"true" cty:"region"`
@ -191,6 +192,7 @@ func (*FlatConfig) HCL2Spec() map[string]hcldec.Spec {
"custom_endpoint_ec2": &hcldec.AttrSpec{Name: "custom_endpoint_ec2", Type: cty.String, Required: false},
"decode_authorization_messages": &hcldec.AttrSpec{Name: "decode_authorization_messages", Type: cty.Bool, Required: false},
"insecure_skip_tls_verify": &hcldec.AttrSpec{Name: "insecure_skip_tls_verify", Type: cty.Bool, Required: false},
"max_retries": &hcldec.AttrSpec{Name: "max_retries", Type: cty.Number, Required: false},
"mfa_code": &hcldec.AttrSpec{Name: "mfa_code", Type: cty.String, Required: false},
"profile": &hcldec.AttrSpec{Name: "profile", Type: cty.String, Required: false},
"region": &hcldec.AttrSpec{Name: "region", Type: cty.String, Required: false},

View File

@ -1,9 +1,10 @@
package ebssurrogate
import (
"github.com/hashicorp/packer/builder/amazon/common"
"testing"
"github.com/hashicorp/packer/builder/amazon/common"
"github.com/hashicorp/packer/packer"
)

View File

@ -64,6 +64,7 @@ type FlatConfig struct {
CustomEndpointEc2 *string `mapstructure:"custom_endpoint_ec2" required:"false" cty:"custom_endpoint_ec2"`
DecodeAuthZMessages *bool `mapstructure:"decode_authorization_messages" required:"false" cty:"decode_authorization_messages"`
InsecureSkipTLSVerify *bool `mapstructure:"insecure_skip_tls_verify" required:"false" cty:"insecure_skip_tls_verify"`
MaxRetries *int `mapstructure:"max_retries" required:"false" cty:"max_retries"`
MFACode *string `mapstructure:"mfa_code" required:"false" cty:"mfa_code"`
ProfileName *string `mapstructure:"profile" required:"false" cty:"profile"`
RawRegion *string `mapstructure:"region" required:"true" cty:"region"`
@ -171,6 +172,7 @@ func (*FlatConfig) HCL2Spec() map[string]hcldec.Spec {
"custom_endpoint_ec2": &hcldec.AttrSpec{Name: "custom_endpoint_ec2", Type: cty.String, Required: false},
"decode_authorization_messages": &hcldec.AttrSpec{Name: "decode_authorization_messages", Type: cty.Bool, Required: false},
"insecure_skip_tls_verify": &hcldec.AttrSpec{Name: "insecure_skip_tls_verify", Type: cty.Bool, Required: false},
"max_retries": &hcldec.AttrSpec{Name: "max_retries", Type: cty.Number, Required: false},
"mfa_code": &hcldec.AttrSpec{Name: "mfa_code", Type: cty.String, Required: false},
"profile": &hcldec.AttrSpec{Name: "profile", Type: cty.String, Required: false},
"region": &hcldec.AttrSpec{Name: "region", Type: cty.String, Required: false},

View File

@ -9,13 +9,13 @@ import (
"context"
"errors"
"fmt"
"github.com/hashicorp/packer/builder"
"os"
"strings"
"github.com/aws/aws-sdk-go/service/ec2"
"github.com/aws/aws-sdk-go/service/iam"
"github.com/hashicorp/hcl/v2/hcldec"
"github.com/hashicorp/packer/builder"
awscommon "github.com/hashicorp/packer/builder/amazon/common"
"github.com/hashicorp/packer/common"
"github.com/hashicorp/packer/helper/communicator"

View File

@ -21,6 +21,7 @@ type FlatConfig struct {
CustomEndpointEc2 *string `mapstructure:"custom_endpoint_ec2" required:"false" cty:"custom_endpoint_ec2"`
DecodeAuthZMessages *bool `mapstructure:"decode_authorization_messages" required:"false" cty:"decode_authorization_messages"`
InsecureSkipTLSVerify *bool `mapstructure:"insecure_skip_tls_verify" required:"false" cty:"insecure_skip_tls_verify"`
MaxRetries *int `mapstructure:"max_retries" required:"false" cty:"max_retries"`
MFACode *string `mapstructure:"mfa_code" required:"false" cty:"mfa_code"`
ProfileName *string `mapstructure:"profile" required:"false" cty:"profile"`
RawRegion *string `mapstructure:"region" required:"true" cty:"region"`
@ -154,6 +155,7 @@ func (*FlatConfig) HCL2Spec() map[string]hcldec.Spec {
"custom_endpoint_ec2": &hcldec.AttrSpec{Name: "custom_endpoint_ec2", Type: cty.String, Required: false},
"decode_authorization_messages": &hcldec.AttrSpec{Name: "decode_authorization_messages", Type: cty.Bool, Required: false},
"insecure_skip_tls_verify": &hcldec.AttrSpec{Name: "insecure_skip_tls_verify", Type: cty.Bool, Required: false},
"max_retries": &hcldec.AttrSpec{Name: "max_retries", Type: cty.Number, Required: false},
"mfa_code": &hcldec.AttrSpec{Name: "mfa_code", Type: cty.String, Required: false},
"profile": &hcldec.AttrSpec{Name: "profile", Type: cty.String, Required: false},
"region": &hcldec.AttrSpec{Name: "region", Type: cty.String, Required: false},

View File

@ -231,8 +231,16 @@ func (b *Builder) Run(ctx context.Context, ui packer.Ui, hook packer.Hook) (pack
keyVaultDeploymentName := b.stateBag.Get(constants.ArmKeyVaultDeploymentName).(string)
steps = []multistep.Step{
NewStepCreateResourceGroup(azureClient, ui),
NewStepValidateTemplate(azureClient, ui, &b.config, GetKeyVaultDeployment),
NewStepDeployTemplate(azureClient, ui, &b.config, keyVaultDeploymentName, GetKeyVaultDeployment),
}
if b.config.BuildKeyVaultName == "" {
steps = append(steps,
NewStepValidateTemplate(azureClient, ui, &b.config, GetKeyVaultDeployment),
NewStepDeployTemplate(azureClient, ui, &b.config, keyVaultDeploymentName, GetKeyVaultDeployment),
)
} else {
steps = append(steps, NewStepCertificateInKeyVault(&azureClient.VaultClient, ui, &b.config))
}
steps = append(steps,
NewStepGetCertificate(azureClient, ui),
NewStepSetCertificate(&b.config, ui),
NewStepValidateTemplate(azureClient, ui, &b.config, GetVirtualMachineDeployment),
@ -261,7 +269,7 @@ func (b *Builder) Run(ctx context.Context, ui packer.Ui, hook packer.Hook) (pack
NewStepDeleteResourceGroup(azureClient, ui),
NewStepDeleteOSDisk(azureClient, ui),
NewStepDeleteAdditionalDisks(azureClient, ui),
}
)
} else {
return nil, fmt.Errorf("Builder does not support the os_type '%s'", b.config.OSType)
}
@ -396,6 +404,13 @@ func (b *Builder) configureStateBag(stateBag multistep.StateBag) {
}
stateBag.Put(constants.ArmKeyVaultName, b.config.tmpKeyVaultName)
stateBag.Put(constants.ArmIsExistingKeyVault, false)
if b.config.BuildKeyVaultName != "" {
stateBag.Put(constants.ArmKeyVaultName, b.config.BuildKeyVaultName)
b.config.tmpKeyVaultName = b.config.BuildKeyVaultName
stateBag.Put(constants.ArmIsExistingKeyVault, true)
}
stateBag.Put(constants.ArmNicName, b.config.tmpNicName)
stateBag.Put(constants.ArmPublicIPAddressName, b.config.tmpPublicIPAddressName)
stateBag.Put(constants.ArmResourceGroupName, b.config.BuildResourceGroupName)

View File

@ -147,20 +147,20 @@ type Config struct {
// If set to true, Virtual Machines deployed from the latest version of the
// Image Definition won't use this Image Version.
SharedGalleryImageVersionExcludeFromLatest bool `mapstructure:"shared_gallery_image_version_exclude_from_latest" required:"false"`
// PublisherName for your base image. See
// Name of the publisher to use for your base image (Azure Marketplace Images only). See
// [documentation](https://azure.microsoft.com/en-us/documentation/articles/resource-groups-vm-searching/)
// for details.
//
// CLI example `az vm image list-publishers --location westus`
ImagePublisher string `mapstructure:"image_publisher" required:"true"`
// Offer for your base image. See
// Name of the publisher's offer to use for your base image (Azure Marketplace Images only). See
// [documentation](https://azure.microsoft.com/en-us/documentation/articles/resource-groups-vm-searching/)
// for details.
//
// CLI example
// `az vm image list-offers --location westus --publisher Canonical`
ImageOffer string `mapstructure:"image_offer" required:"true"`
// SKU for your base image. See
// SKU of the image offer to use for your base image (Azure Marketplace Images only). See
// [documentation](https://azure.microsoft.com/en-us/documentation/articles/resource-groups-vm-searching/)
// for details.
//
@ -176,24 +176,24 @@ type Config struct {
// CLI example
// `az vm image list --location westus --publisher Canonical --offer UbuntuServer --sku 16.04.0-LTS --all`
ImageVersion string `mapstructure:"image_version" required:"false"`
// Specify a custom VHD to use. If this value is set, do
// URL to a custom VHD to use for your base image. If this value is set, do
// not set image_publisher, image_offer, image_sku, or image_version.
ImageUrl string `mapstructure:"image_url" required:"true"`
// Name of a custom managed image to use for your base image. If this value is set, do
// not set image_publisher, image_offer, image_sku, or image_version.
ImageUrl string `mapstructure:"image_url" required:"false"`
// Specify the source managed image's resource group used to use. If this
// value is set, do not set image\_publisher, image\_offer, image\_sku, or
// image\_version. If this value is set, the value
// `custom_managed_image_name` must also be set. See
// [documentation](https://docs.microsoft.com/en-us/azure/storage/storage-managed-disks-overview#images)
// to learn more about managed images.
CustomManagedImageResourceGroupName string `mapstructure:"custom_managed_image_resource_group_name" required:"false"`
// Specify the source managed image's name to use. If this value is set, do
// not set image\_publisher, image\_offer, image\_sku, or image\_version.
// If this value is set, the value
// `custom_managed_image_resource_group_name` must also be set. See
// [documentation](https://docs.microsoft.com/en-us/azure/storage/storage-managed-disks-overview#images)
// to learn more about managed images.
CustomManagedImageName string `mapstructure:"custom_managed_image_name" required:"false"`
customManagedImageID string
CustomManagedImageName string `mapstructure:"custom_managed_image_name" required:"true"`
// Name of a custom managed image's resource group to use for your base image. If this
// value is set, image_publisher, image_offer, image_sku, or image_version.
// `custom_managed_image_name` must also be set. See
// [documentation](https://docs.microsoft.com/en-us/azure/storage/storage-managed-disks-overview#images)
// to learn more about managed images.
CustomManagedImageResourceGroupName string `mapstructure:"custom_managed_image_resource_group_name" required:"true"`
customManagedImageID string
Location string `mapstructure:"location"`
// Size of the VM used for building. This can be changed when you deploy a
@ -253,7 +253,10 @@ type Config struct {
// group is deleted at the end of the build.
TempResourceGroupName string `mapstructure:"temp_resource_group_name"`
// Specify an existing resource group to run the build in.
BuildResourceGroupName string `mapstructure:"build_resource_group_name"`
BuildResourceGroupName string `mapstructure:"build_resource_group_name"`
// Specify an existing key vault to use for uploading certificates to the
// instance to connect.
BuildKeyVaultName string `mapstructure:"build_key_vault_name"`
storageAccountBlobEndpoint string
// This value allows you to
// set a virtual_network_name and obtain a public IP. If this value is not

View File

@ -36,9 +36,9 @@ type FlatConfig struct {
ImageOffer *string `mapstructure:"image_offer" required:"true" cty:"image_offer"`
ImageSku *string `mapstructure:"image_sku" required:"true" cty:"image_sku"`
ImageVersion *string `mapstructure:"image_version" required:"false" cty:"image_version"`
ImageUrl *string `mapstructure:"image_url" required:"false" cty:"image_url"`
CustomManagedImageResourceGroupName *string `mapstructure:"custom_managed_image_resource_group_name" required:"false" cty:"custom_managed_image_resource_group_name"`
CustomManagedImageName *string `mapstructure:"custom_managed_image_name" required:"false" cty:"custom_managed_image_name"`
ImageUrl *string `mapstructure:"image_url" required:"true" cty:"image_url"`
CustomManagedImageName *string `mapstructure:"custom_managed_image_name" required:"true" cty:"custom_managed_image_name"`
CustomManagedImageResourceGroupName *string `mapstructure:"custom_managed_image_resource_group_name" required:"true" cty:"custom_managed_image_resource_group_name"`
Location *string `mapstructure:"location" cty:"location"`
VMSize *string `mapstructure:"vm_size" required:"false" cty:"vm_size"`
ManagedImageResourceGroupName *string `mapstructure:"managed_image_resource_group_name" cty:"managed_image_resource_group_name"`
@ -53,6 +53,7 @@ type FlatConfig struct {
TempComputeName *string `mapstructure:"temp_compute_name" required:"false" cty:"temp_compute_name"`
TempResourceGroupName *string `mapstructure:"temp_resource_group_name" cty:"temp_resource_group_name"`
BuildResourceGroupName *string `mapstructure:"build_resource_group_name" cty:"build_resource_group_name"`
BuildKeyVaultName *string `mapstructure:"build_key_vault_name" cty:"build_key_vault_name"`
PrivateVirtualNetworkWithPublicIp *bool `mapstructure:"private_virtual_network_with_public_ip" required:"false" cty:"private_virtual_network_with_public_ip"`
VirtualNetworkName *string `mapstructure:"virtual_network_name" required:"false" cty:"virtual_network_name"`
VirtualNetworkSubnetName *string `mapstructure:"virtual_network_subnet_name" required:"false" cty:"virtual_network_subnet_name"`
@ -145,82 +146,83 @@ func (*FlatConfig) HCL2Spec() map[string]hcldec.Spec {
"shared_gallery_image_version_end_of_life_date": &hcldec.AttrSpec{Name: "shared_gallery_image_version_end_of_life_date", Type: cty.String, Required: false},
"shared_image_gallery_replica_count": &hcldec.AttrSpec{Name: "shared_image_gallery_replica_count", Type: cty.Number, Required: false},
"shared_gallery_image_version_exclude_from_latest": &hcldec.AttrSpec{Name: "shared_gallery_image_version_exclude_from_latest", Type: cty.Bool, Required: false},
"image_publisher": &hcldec.AttrSpec{Name: "image_publisher", Type: cty.String, Required: false},
"image_offer": &hcldec.AttrSpec{Name: "image_offer", Type: cty.String, Required: false},
"image_sku": &hcldec.AttrSpec{Name: "image_sku", Type: cty.String, Required: false},
"image_version": &hcldec.AttrSpec{Name: "image_version", Type: cty.String, Required: false},
"image_url": &hcldec.AttrSpec{Name: "image_url", Type: cty.String, Required: false},
"image_publisher": &hcldec.AttrSpec{Name: "image_publisher", Type: cty.String, Required: false},
"image_offer": &hcldec.AttrSpec{Name: "image_offer", Type: cty.String, Required: false},
"image_sku": &hcldec.AttrSpec{Name: "image_sku", Type: cty.String, Required: false},
"image_version": &hcldec.AttrSpec{Name: "image_version", Type: cty.String, Required: false},
"image_url": &hcldec.AttrSpec{Name: "image_url", Type: cty.String, Required: false},
"custom_managed_image_name": &hcldec.AttrSpec{Name: "custom_managed_image_name", Type: cty.String, Required: false},
"custom_managed_image_resource_group_name": &hcldec.AttrSpec{Name: "custom_managed_image_resource_group_name", Type: cty.String, Required: false},
"custom_managed_image_name": &hcldec.AttrSpec{Name: "custom_managed_image_name", Type: cty.String, Required: false},
"location": &hcldec.AttrSpec{Name: "location", Type: cty.String, Required: false},
"vm_size": &hcldec.AttrSpec{Name: "vm_size", Type: cty.String, Required: false},
"managed_image_resource_group_name": &hcldec.AttrSpec{Name: "managed_image_resource_group_name", Type: cty.String, Required: false},
"managed_image_name": &hcldec.AttrSpec{Name: "managed_image_name", Type: cty.String, Required: false},
"managed_image_storage_account_type": &hcldec.AttrSpec{Name: "managed_image_storage_account_type", Type: cty.String, Required: false},
"managed_image_os_disk_snapshot_name": &hcldec.AttrSpec{Name: "managed_image_os_disk_snapshot_name", Type: cty.String, Required: false},
"managed_image_data_disk_snapshot_prefix": &hcldec.AttrSpec{Name: "managed_image_data_disk_snapshot_prefix", Type: cty.String, Required: false},
"managed_image_zone_resilient": &hcldec.AttrSpec{Name: "managed_image_zone_resilient", Type: cty.Bool, Required: false},
"azure_tags": &hcldec.BlockAttrsSpec{TypeName: "azure_tags", ElementType: cty.String, Required: false},
"resource_group_name": &hcldec.AttrSpec{Name: "resource_group_name", Type: cty.String, Required: false},
"storage_account": &hcldec.AttrSpec{Name: "storage_account", Type: cty.String, Required: false},
"temp_compute_name": &hcldec.AttrSpec{Name: "temp_compute_name", Type: cty.String, Required: false},
"temp_resource_group_name": &hcldec.AttrSpec{Name: "temp_resource_group_name", Type: cty.String, Required: false},
"build_resource_group_name": &hcldec.AttrSpec{Name: "build_resource_group_name", Type: cty.String, Required: false},
"private_virtual_network_with_public_ip": &hcldec.AttrSpec{Name: "private_virtual_network_with_public_ip", Type: cty.Bool, Required: false},
"virtual_network_name": &hcldec.AttrSpec{Name: "virtual_network_name", Type: cty.String, Required: false},
"virtual_network_subnet_name": &hcldec.AttrSpec{Name: "virtual_network_subnet_name", Type: cty.String, Required: false},
"virtual_network_resource_group_name": &hcldec.AttrSpec{Name: "virtual_network_resource_group_name", Type: cty.String, Required: false},
"custom_data_file": &hcldec.AttrSpec{Name: "custom_data_file", Type: cty.String, Required: false},
"plan_info": &hcldec.BlockSpec{TypeName: "plan_info", Nested: hcldec.ObjectSpec((*FlatPlanInformation)(nil).HCL2Spec())},
"polling_duration_timeout": &hcldec.AttrSpec{Name: "polling_duration_timeout", Type: cty.String, Required: false},
"os_type": &hcldec.AttrSpec{Name: "os_type", Type: cty.String, Required: false},
"os_disk_size_gb": &hcldec.AttrSpec{Name: "os_disk_size_gb", Type: cty.Number, Required: false},
"disk_additional_size": &hcldec.AttrSpec{Name: "disk_additional_size", Type: cty.List(cty.Number), Required: false},
"disk_caching_type": &hcldec.AttrSpec{Name: "disk_caching_type", Type: cty.String, Required: false},
"allowed_inbound_ip_addresses": &hcldec.AttrSpec{Name: "allowed_inbound_ip_addresses", Type: cty.List(cty.String), Required: false},
"user_name": &hcldec.AttrSpec{Name: "user_name", Type: cty.String, Required: false},
"password": &hcldec.AttrSpec{Name: "password", Type: cty.String, Required: false},
"communicator": &hcldec.AttrSpec{Name: "communicator", Type: cty.String, Required: false},
"pause_before_connecting": &hcldec.AttrSpec{Name: "pause_before_connecting", Type: cty.String, Required: false},
"ssh_host": &hcldec.AttrSpec{Name: "ssh_host", Type: cty.String, Required: false},
"ssh_port": &hcldec.AttrSpec{Name: "ssh_port", Type: cty.Number, Required: false},
"ssh_username": &hcldec.AttrSpec{Name: "ssh_username", Type: cty.String, Required: false},
"ssh_password": &hcldec.AttrSpec{Name: "ssh_password", Type: cty.String, Required: false},
"ssh_keypair_name": &hcldec.AttrSpec{Name: "ssh_keypair_name", Type: cty.String, Required: false},
"temporary_key_pair_name": &hcldec.AttrSpec{Name: "temporary_key_pair_name", Type: cty.String, Required: false},
"ssh_clear_authorized_keys": &hcldec.AttrSpec{Name: "ssh_clear_authorized_keys", Type: cty.Bool, Required: false},
"ssh_private_key_file": &hcldec.AttrSpec{Name: "ssh_private_key_file", Type: cty.String, Required: false},
"ssh_pty": &hcldec.AttrSpec{Name: "ssh_pty", Type: cty.Bool, Required: false},
"ssh_timeout": &hcldec.AttrSpec{Name: "ssh_timeout", Type: cty.String, Required: false},
"ssh_agent_auth": &hcldec.AttrSpec{Name: "ssh_agent_auth", Type: cty.Bool, Required: false},
"ssh_disable_agent_forwarding": &hcldec.AttrSpec{Name: "ssh_disable_agent_forwarding", Type: cty.Bool, Required: false},
"ssh_handshake_attempts": &hcldec.AttrSpec{Name: "ssh_handshake_attempts", Type: cty.Number, Required: false},
"ssh_bastion_host": &hcldec.AttrSpec{Name: "ssh_bastion_host", Type: cty.String, Required: false},
"ssh_bastion_port": &hcldec.AttrSpec{Name: "ssh_bastion_port", Type: cty.Number, Required: false},
"ssh_bastion_agent_auth": &hcldec.AttrSpec{Name: "ssh_bastion_agent_auth", Type: cty.Bool, Required: false},
"ssh_bastion_username": &hcldec.AttrSpec{Name: "ssh_bastion_username", Type: cty.String, Required: false},
"ssh_bastion_password": &hcldec.AttrSpec{Name: "ssh_bastion_password", Type: cty.String, Required: false},
"ssh_bastion_private_key_file": &hcldec.AttrSpec{Name: "ssh_bastion_private_key_file", Type: cty.String, Required: false},
"ssh_file_transfer_method": &hcldec.AttrSpec{Name: "ssh_file_transfer_method", Type: cty.String, Required: false},
"ssh_proxy_host": &hcldec.AttrSpec{Name: "ssh_proxy_host", Type: cty.String, Required: false},
"ssh_proxy_port": &hcldec.AttrSpec{Name: "ssh_proxy_port", Type: cty.Number, Required: false},
"ssh_proxy_username": &hcldec.AttrSpec{Name: "ssh_proxy_username", Type: cty.String, Required: false},
"ssh_proxy_password": &hcldec.AttrSpec{Name: "ssh_proxy_password", Type: cty.String, Required: false},
"ssh_keep_alive_interval": &hcldec.AttrSpec{Name: "ssh_keep_alive_interval", Type: cty.String, Required: false},
"ssh_read_write_timeout": &hcldec.AttrSpec{Name: "ssh_read_write_timeout", Type: cty.String, Required: false},
"ssh_remote_tunnels": &hcldec.AttrSpec{Name: "ssh_remote_tunnels", Type: cty.List(cty.String), Required: false},
"ssh_local_tunnels": &hcldec.AttrSpec{Name: "ssh_local_tunnels", Type: cty.List(cty.String), Required: false},
"ssh_public_key": &hcldec.AttrSpec{Name: "ssh_public_key", Type: cty.List(cty.Number), Required: false},
"ssh_private_key": &hcldec.AttrSpec{Name: "ssh_private_key", Type: cty.List(cty.Number), Required: false},
"winrm_username": &hcldec.AttrSpec{Name: "winrm_username", Type: cty.String, Required: false},
"winrm_password": &hcldec.AttrSpec{Name: "winrm_password", Type: cty.String, Required: false},
"winrm_host": &hcldec.AttrSpec{Name: "winrm_host", Type: cty.String, Required: false},
"winrm_port": &hcldec.AttrSpec{Name: "winrm_port", Type: cty.Number, Required: false},
"winrm_timeout": &hcldec.AttrSpec{Name: "winrm_timeout", Type: cty.String, Required: false},
"winrm_use_ssl": &hcldec.AttrSpec{Name: "winrm_use_ssl", Type: cty.Bool, Required: false},
"winrm_insecure": &hcldec.AttrSpec{Name: "winrm_insecure", Type: cty.Bool, Required: false},
"winrm_use_ntlm": &hcldec.AttrSpec{Name: "winrm_use_ntlm", Type: cty.Bool, Required: false},
"async_resourcegroup_delete": &hcldec.AttrSpec{Name: "async_resourcegroup_delete", Type: cty.Bool, Required: false},
"location": &hcldec.AttrSpec{Name: "location", Type: cty.String, Required: false},
"vm_size": &hcldec.AttrSpec{Name: "vm_size", Type: cty.String, Required: false},
"managed_image_resource_group_name": &hcldec.AttrSpec{Name: "managed_image_resource_group_name", Type: cty.String, Required: false},
"managed_image_name": &hcldec.AttrSpec{Name: "managed_image_name", Type: cty.String, Required: false},
"managed_image_storage_account_type": &hcldec.AttrSpec{Name: "managed_image_storage_account_type", Type: cty.String, Required: false},
"managed_image_os_disk_snapshot_name": &hcldec.AttrSpec{Name: "managed_image_os_disk_snapshot_name", Type: cty.String, Required: false},
"managed_image_data_disk_snapshot_prefix": &hcldec.AttrSpec{Name: "managed_image_data_disk_snapshot_prefix", Type: cty.String, Required: false},
"managed_image_zone_resilient": &hcldec.AttrSpec{Name: "managed_image_zone_resilient", Type: cty.Bool, Required: false},
"azure_tags": &hcldec.BlockAttrsSpec{TypeName: "azure_tags", ElementType: cty.String, Required: false},
"resource_group_name": &hcldec.AttrSpec{Name: "resource_group_name", Type: cty.String, Required: false},
"storage_account": &hcldec.AttrSpec{Name: "storage_account", Type: cty.String, Required: false},
"temp_compute_name": &hcldec.AttrSpec{Name: "temp_compute_name", Type: cty.String, Required: false},
"temp_resource_group_name": &hcldec.AttrSpec{Name: "temp_resource_group_name", Type: cty.String, Required: false},
"build_resource_group_name": &hcldec.AttrSpec{Name: "build_resource_group_name", Type: cty.String, Required: false},
"build_key_vault_name": &hcldec.AttrSpec{Name: "build_key_vault_name", Type: cty.String, Required: false},
"private_virtual_network_with_public_ip": &hcldec.AttrSpec{Name: "private_virtual_network_with_public_ip", Type: cty.Bool, Required: false},
"virtual_network_name": &hcldec.AttrSpec{Name: "virtual_network_name", Type: cty.String, Required: false},
"virtual_network_subnet_name": &hcldec.AttrSpec{Name: "virtual_network_subnet_name", Type: cty.String, Required: false},
"virtual_network_resource_group_name": &hcldec.AttrSpec{Name: "virtual_network_resource_group_name", Type: cty.String, Required: false},
"custom_data_file": &hcldec.AttrSpec{Name: "custom_data_file", Type: cty.String, Required: false},
"plan_info": &hcldec.BlockSpec{TypeName: "plan_info", Nested: hcldec.ObjectSpec((*FlatPlanInformation)(nil).HCL2Spec())},
"polling_duration_timeout": &hcldec.AttrSpec{Name: "polling_duration_timeout", Type: cty.String, Required: false},
"os_type": &hcldec.AttrSpec{Name: "os_type", Type: cty.String, Required: false},
"os_disk_size_gb": &hcldec.AttrSpec{Name: "os_disk_size_gb", Type: cty.Number, Required: false},
"disk_additional_size": &hcldec.AttrSpec{Name: "disk_additional_size", Type: cty.List(cty.Number), Required: false},
"disk_caching_type": &hcldec.AttrSpec{Name: "disk_caching_type", Type: cty.String, Required: false},
"allowed_inbound_ip_addresses": &hcldec.AttrSpec{Name: "allowed_inbound_ip_addresses", Type: cty.List(cty.String), Required: false},
"user_name": &hcldec.AttrSpec{Name: "user_name", Type: cty.String, Required: false},
"password": &hcldec.AttrSpec{Name: "password", Type: cty.String, Required: false},
"communicator": &hcldec.AttrSpec{Name: "communicator", Type: cty.String, Required: false},
"pause_before_connecting": &hcldec.AttrSpec{Name: "pause_before_connecting", Type: cty.String, Required: false},
"ssh_host": &hcldec.AttrSpec{Name: "ssh_host", Type: cty.String, Required: false},
"ssh_port": &hcldec.AttrSpec{Name: "ssh_port", Type: cty.Number, Required: false},
"ssh_username": &hcldec.AttrSpec{Name: "ssh_username", Type: cty.String, Required: false},
"ssh_password": &hcldec.AttrSpec{Name: "ssh_password", Type: cty.String, Required: false},
"ssh_keypair_name": &hcldec.AttrSpec{Name: "ssh_keypair_name", Type: cty.String, Required: false},
"temporary_key_pair_name": &hcldec.AttrSpec{Name: "temporary_key_pair_name", Type: cty.String, Required: false},
"ssh_clear_authorized_keys": &hcldec.AttrSpec{Name: "ssh_clear_authorized_keys", Type: cty.Bool, Required: false},
"ssh_private_key_file": &hcldec.AttrSpec{Name: "ssh_private_key_file", Type: cty.String, Required: false},
"ssh_pty": &hcldec.AttrSpec{Name: "ssh_pty", Type: cty.Bool, Required: false},
"ssh_timeout": &hcldec.AttrSpec{Name: "ssh_timeout", Type: cty.String, Required: false},
"ssh_agent_auth": &hcldec.AttrSpec{Name: "ssh_agent_auth", Type: cty.Bool, Required: false},
"ssh_disable_agent_forwarding": &hcldec.AttrSpec{Name: "ssh_disable_agent_forwarding", Type: cty.Bool, Required: false},
"ssh_handshake_attempts": &hcldec.AttrSpec{Name: "ssh_handshake_attempts", Type: cty.Number, Required: false},
"ssh_bastion_host": &hcldec.AttrSpec{Name: "ssh_bastion_host", Type: cty.String, Required: false},
"ssh_bastion_port": &hcldec.AttrSpec{Name: "ssh_bastion_port", Type: cty.Number, Required: false},
"ssh_bastion_agent_auth": &hcldec.AttrSpec{Name: "ssh_bastion_agent_auth", Type: cty.Bool, Required: false},
"ssh_bastion_username": &hcldec.AttrSpec{Name: "ssh_bastion_username", Type: cty.String, Required: false},
"ssh_bastion_password": &hcldec.AttrSpec{Name: "ssh_bastion_password", Type: cty.String, Required: false},
"ssh_bastion_private_key_file": &hcldec.AttrSpec{Name: "ssh_bastion_private_key_file", Type: cty.String, Required: false},
"ssh_file_transfer_method": &hcldec.AttrSpec{Name: "ssh_file_transfer_method", Type: cty.String, Required: false},
"ssh_proxy_host": &hcldec.AttrSpec{Name: "ssh_proxy_host", Type: cty.String, Required: false},
"ssh_proxy_port": &hcldec.AttrSpec{Name: "ssh_proxy_port", Type: cty.Number, Required: false},
"ssh_proxy_username": &hcldec.AttrSpec{Name: "ssh_proxy_username", Type: cty.String, Required: false},
"ssh_proxy_password": &hcldec.AttrSpec{Name: "ssh_proxy_password", Type: cty.String, Required: false},
"ssh_keep_alive_interval": &hcldec.AttrSpec{Name: "ssh_keep_alive_interval", Type: cty.String, Required: false},
"ssh_read_write_timeout": &hcldec.AttrSpec{Name: "ssh_read_write_timeout", Type: cty.String, Required: false},
"ssh_remote_tunnels": &hcldec.AttrSpec{Name: "ssh_remote_tunnels", Type: cty.List(cty.String), Required: false},
"ssh_local_tunnels": &hcldec.AttrSpec{Name: "ssh_local_tunnels", Type: cty.List(cty.String), Required: false},
"ssh_public_key": &hcldec.AttrSpec{Name: "ssh_public_key", Type: cty.List(cty.Number), Required: false},
"ssh_private_key": &hcldec.AttrSpec{Name: "ssh_private_key", Type: cty.List(cty.Number), Required: false},
"winrm_username": &hcldec.AttrSpec{Name: "winrm_username", Type: cty.String, Required: false},
"winrm_password": &hcldec.AttrSpec{Name: "winrm_password", Type: cty.String, Required: false},
"winrm_host": &hcldec.AttrSpec{Name: "winrm_host", Type: cty.String, Required: false},
"winrm_port": &hcldec.AttrSpec{Name: "winrm_port", Type: cty.Number, Required: false},
"winrm_timeout": &hcldec.AttrSpec{Name: "winrm_timeout", Type: cty.String, Required: false},
"winrm_use_ssl": &hcldec.AttrSpec{Name: "winrm_use_ssl", Type: cty.Bool, Required: false},
"winrm_insecure": &hcldec.AttrSpec{Name: "winrm_insecure", Type: cty.Bool, Required: false},
"winrm_use_ntlm": &hcldec.AttrSpec{Name: "winrm_use_ntlm", Type: cty.Bool, Required: false},
"async_resourcegroup_delete": &hcldec.AttrSpec{Name: "async_resourcegroup_delete", Type: cty.Bool, Required: false},
}
return s
}

View File

@ -0,0 +1,45 @@
package arm
import (
"context"
"fmt"
"github.com/hashicorp/packer/builder/azure/common"
"github.com/hashicorp/packer/builder/azure/common/constants"
"github.com/hashicorp/packer/helper/multistep"
"github.com/hashicorp/packer/packer"
)
type StepCertificateInKeyVault struct {
config *Config
client common.AZVaultClientIface
say func(message string)
error func(e error)
}
func NewStepCertificateInKeyVault(cli common.AZVaultClientIface, ui packer.Ui, config *Config) *StepCertificateInKeyVault {
var step = &StepCertificateInKeyVault{
client: cli,
config: config,
say: func(message string) { ui.Say(message) },
error: func(e error) { ui.Error(e.Error()) },
}
return step
}
func (s *StepCertificateInKeyVault) Run(ctx context.Context, state multistep.StateBag) multistep.StepAction {
s.say("Setting the certificate in the KeyVault...")
var keyVaultName = state.Get(constants.ArmKeyVaultName).(string)
err := s.client.SetSecret(keyVaultName, DefaultSecretName, s.config.winrmCertificate)
if err != nil {
s.error(fmt.Errorf("Error setting winrm cert in custom keyvault: %s", err))
return multistep.ActionHalt
}
return multistep.ActionContinue
}
func (*StepCertificateInKeyVault) Cleanup(multistep.StateBag) {
}

View File

@ -0,0 +1,66 @@
package arm
import (
"bytes"
"context"
"testing"
azcommon "github.com/hashicorp/packer/builder/azure/common"
"github.com/hashicorp/packer/builder/azure/common/constants"
"github.com/hashicorp/packer/helper/multistep"
"github.com/hashicorp/packer/packer"
)
func TestNewStepCertificateInKeyVault(t *testing.T) {
cli := azcommon.MockAZVaultClient{}
ui := &packer.BasicUi{
Reader: new(bytes.Buffer),
Writer: new(bytes.Buffer),
}
state := new(multistep.BasicStateBag)
state.Put(constants.ArmKeyVaultName, "testKeyVaultName")
config := &Config{
winrmCertificate: "testCertificateString",
}
certKVStep := NewStepCertificateInKeyVault(&cli, ui, config)
stepAction := certKVStep.Run(context.TODO(), state)
if stepAction == multistep.ActionHalt {
t.Fatalf("step should have succeeded.")
}
if !cli.SetSecretCalled {
t.Fatalf("Step should have called SetSecret on Azure client.")
}
if cli.SetSecretCert != "testCertificateString" {
t.Fatalf("Step should have read cert from winRMCertificate field on config.")
}
if cli.SetSecretVaultName != "testKeyVaultName" {
t.Fatalf("step should have read keyvault name from state.")
}
}
func TestNewStepCertificateInKeyVault_error(t *testing.T) {
// Tell mock to return an error
cli := azcommon.MockAZVaultClient{}
cli.IsError = true
ui := &packer.BasicUi{
Reader: new(bytes.Buffer),
Writer: new(bytes.Buffer),
}
state := new(multistep.BasicStateBag)
state.Put(constants.ArmKeyVaultName, "testKeyVaultName")
config := &Config{
winrmCertificate: "testCertificateString",
}
certKVStep := NewStepCertificateInKeyVault(&cli, ui, config)
stepAction := certKVStep.Run(context.TODO(), state)
if stepAction != multistep.ActionHalt {
t.Fatalf("step should have failed.")
}
}

View File

@ -44,9 +44,12 @@ func (s *StepDeleteResourceGroup) deleteResourceGroup(ctx context.Context, state
}
if keyVaultDeploymentName, ok := state.GetOk(constants.ArmKeyVaultDeploymentName); ok {
err = s.deleteDeploymentResources(ctx, keyVaultDeploymentName.(string), resourceGroupName)
if err != nil {
return err
// Only delete if custom keyvault was not provided.
if exists := state.Get(constants.ArmIsExistingKeyVault).(bool); exists {
err = s.deleteDeploymentResources(ctx, keyVaultDeploymentName.(string), resourceGroupName)
if err != nil {
return err
}
}
}

View File

@ -36,6 +36,7 @@ const (
ArmTags string = "arm.Tags"
ArmVirtualMachineCaptureParameters string = "arm.VirtualMachineCaptureParameters"
ArmIsExistingResourceGroup string = "arm.IsExistingResourceGroup"
ArmIsExistingKeyVault string = "arm.IsExistingKeyVault"
ArmIsManagedImage string = "arm.IsManagedImage"
ArmManagedImageResourceGroupName string = "arm.ManagedImageResourceGroupName"

View File

@ -16,6 +16,15 @@ const (
AzureVaultApiVersion = "2016-10-01"
)
// Enables us to test steps that access this cli
type AZVaultClientIface interface {
GetSecret(string, string) (*Secret, error)
SetSecret(string, string, string) error
DeletePreparer(string, string) (*http.Request, error)
DeleteResponder(*http.Response) (autorest.Response, error)
DeleteSender(*http.Request) (*http.Response, error)
}
type VaultClient struct {
autorest.Client
keyVaultEndpoint url.URL
@ -54,7 +63,8 @@ func (client *VaultClient) GetSecret(vaultName, secretName string) (*Secret, err
autorest.AsGet(),
autorest.WithBaseURL(client.getVaultUrl(vaultName)),
autorest.WithPathParameters("/secrets/{secret-name}", p),
autorest.WithQueryParameters(q))
autorest.WithQueryParameters(q),
)
if err != nil {
return nil, err
@ -86,6 +96,47 @@ func (client *VaultClient) GetSecret(vaultName, secretName string) (*Secret, err
return &secret, nil
}
func (client *VaultClient) SetSecret(vaultName, secretName string, secretValue string) error {
p := map[string]interface{}{
"secret-name": autorest.Encode("path", secretName),
}
q := map[string]interface{}{
"api-version": AzureVaultApiVersion,
}
jsonBody := fmt.Sprintf(`{"value": "%s"}`, secretValue)
req, err := autorest.Prepare(
&http.Request{},
autorest.AsPut(),
autorest.AsContentType("application/json; charset=utf-8"),
autorest.WithBaseURL(client.getVaultUrl(vaultName)),
autorest.WithPathParameters("/secrets/{secret-name}", p),
autorest.WithQueryParameters(q),
autorest.WithString(jsonBody),
)
if err != nil {
return err
}
resp, err := autorest.SendWithSender(client, req)
if err != nil {
return err
}
if resp.StatusCode != 200 {
return fmt.Errorf(
"Failed to set secret to %s/%s, HTTP status code=%d (%s)",
vaultName,
secretName,
resp.StatusCode,
http.StatusText(resp.StatusCode))
}
return nil
}
// Delete deletes the specified Azure key vault.
//
// resourceGroupName is the name of the Resource Group to which the vault belongs. vaultName is the name of the vault

View File

@ -0,0 +1,56 @@
package common
import (
"fmt"
"net/http"
"github.com/Azure/go-autorest/autorest"
)
type MockAZVaultClient struct {
GetSecretCalled bool
SetSecretCalled bool
SetSecretVaultName string
SetSecretSecretName string
SetSecretCert string
DeleteResponderCalled bool
DeletePreparerCalled bool
DeleteSenderCalled bool
IsError bool
}
func (m *MockAZVaultClient) GetSecret(vaultName, secretName string) (*Secret, error) {
m.GetSecretCalled = true
var secret Secret
return &secret, nil
}
func (m *MockAZVaultClient) SetSecret(vaultName, secretName string, secretValue string) error {
m.SetSecretCalled = true
m.SetSecretVaultName = vaultName
m.SetSecretSecretName = secretName
m.SetSecretCert = secretValue
if m.IsError {
return fmt.Errorf("generic error!!")
}
return nil
}
func (m *MockAZVaultClient) DeletePreparer(resourceGroupName string, vaultName string) (*http.Request, error) {
m.DeletePreparerCalled = true
return nil, nil
}
func (m *MockAZVaultClient) DeleteResponder(resp *http.Response) (autorest.Response, error) {
m.DeleteResponderCalled = true
var result autorest.Response
return result, nil
}
func (m *MockAZVaultClient) DeleteSender(req *http.Request) (*http.Response, error) {
m.DeleteSenderCalled = true
return nil, nil
}

View File

@ -1,8 +1,9 @@
package builder
import (
"github.com/hashicorp/packer/helper/multistep"
"testing"
"github.com/hashicorp/packer/helper/multistep"
)
func TestGeneratedData_Put(t *testing.T) {

View File

@ -2,9 +2,9 @@ package lxc
import (
"context"
"github.com/hashicorp/packer/common"
"log"
"github.com/hashicorp/packer/common"
"github.com/hashicorp/packer/helper/multistep"
"github.com/hashicorp/packer/packer"
)

View File

@ -2,9 +2,9 @@ package lxd
import (
"context"
"github.com/hashicorp/packer/common"
"log"
"github.com/hashicorp/packer/common"
"github.com/hashicorp/packer/helper/multistep"
"github.com/hashicorp/packer/packer"
)

View File

@ -25,6 +25,11 @@ func (a *NullArtifact) String() string {
}
func (a *NullArtifact) State(name string) interface{} {
if name == "generated_data" {
return map[interface{}]interface{}{
"ID": "Null",
}
}
return nil
}

View File

@ -47,6 +47,7 @@ func (b *Builder) Run(ctx context.Context, ui packer.Ui, hook packer.Hook) (pack
state := new(multistep.BasicStateBag)
state.Put("hook", hook)
state.Put("ui", ui)
state.Put("instance_id", "Null")
// Run!
b.runner = common.NewRunner(steps, b.config.PackerConfig, ui)

View File

@ -2,9 +2,9 @@ package chroot
import (
"context"
"github.com/hashicorp/packer/common"
"log"
"github.com/hashicorp/packer/common"
"github.com/hashicorp/packer/helper/multistep"
"github.com/hashicorp/packer/packer"
)

View File

@ -1,9 +1,10 @@
package common
import (
"time"
"github.com/hashicorp/packer/helper/communicator"
"github.com/hashicorp/packer/template/interpolate"
"time"
)
// SSHConfig contains the configuration for SSH communicator.

View File

@ -1,12 +1,13 @@
package common
import (
"github.com/hashicorp/packer/helper/communicator"
"github.com/hashicorp/packer/template/interpolate"
"io/ioutil"
"os"
"testing"
"time"
"github.com/hashicorp/packer/helper/communicator"
"github.com/hashicorp/packer/template/interpolate"
)
func testSSHConfig() *SSHConfig {

View File

@ -2,6 +2,7 @@ package qemu
import (
"context"
"github.com/hashicorp/packer/common"
"github.com/hashicorp/packer/helper/multistep"
)

View File

@ -2,9 +2,10 @@ package qemu
import (
"context"
"testing"
"github.com/hashicorp/packer/common"
"github.com/hashicorp/packer/helper/multistep"
"testing"
)
func TestStepHTTPIPDiscover_Run(t *testing.T) {

View File

@ -3,10 +3,11 @@ package common
import (
"context"
"fmt"
"log"
"github.com/hashicorp/packer/common"
"github.com/hashicorp/packer/helper/multistep"
"github.com/hashicorp/packer/packer"
"log"
)
// Step to discover the http ip

View File

@ -3,9 +3,10 @@ package common
import (
"context"
"errors"
"testing"
"github.com/hashicorp/packer/common"
"github.com/hashicorp/packer/helper/multistep"
"testing"
)
func TestStepHTTPIPDiscover_Run(t *testing.T) {

View File

@ -2,6 +2,7 @@ package clone
import (
"context"
"github.com/hashicorp/hcl/v2/hcldec"
"github.com/hashicorp/packer/builder/vsphere/common"
"github.com/hashicorp/packer/builder/vsphere/driver"

View File

@ -1,13 +1,14 @@
package clone
import (
"os"
"testing"
"github.com/hashicorp/packer/builder/vsphere/common"
commonT "github.com/hashicorp/packer/builder/vsphere/common/testing"
builderT "github.com/hashicorp/packer/helper/builder/testing"
"github.com/hashicorp/packer/packer"
"github.com/vmware/govmomi/vim25/types"
"os"
"testing"
)
func TestCloneBuilderAcc_default(t *testing.T) {

View File

@ -1,8 +1,9 @@
package clone
import (
"github.com/hashicorp/packer/packer"
"testing"
"github.com/hashicorp/packer/packer"
)
func TestCloneBuilder_ImplementsBuilder(t *testing.T) {

View File

@ -6,6 +6,7 @@ package clone
import (
"context"
"fmt"
"github.com/hashicorp/packer/builder/vsphere/common"
"github.com/hashicorp/packer/builder/vsphere/driver"
"github.com/hashicorp/packer/helper/multistep"

View File

@ -6,6 +6,7 @@ package common
import (
"context"
"fmt"
"github.com/hashicorp/packer/builder/vsphere/driver"
"github.com/hashicorp/packer/helper/multistep"
"github.com/hashicorp/packer/packer"

View File

@ -6,6 +6,7 @@ package common
import (
"context"
"fmt"
"github.com/hashicorp/packer/builder/vsphere/driver"
"github.com/hashicorp/packer/helper/multistep"
)

View File

@ -6,6 +6,7 @@ package common
import (
"context"
"fmt"
"github.com/hashicorp/packer/builder/vsphere/driver"
"github.com/hashicorp/packer/helper/multistep"
"github.com/hashicorp/packer/packer"

View File

@ -5,10 +5,11 @@ package common
import (
"context"
"strings"
"github.com/hashicorp/packer/builder/vsphere/driver"
"github.com/hashicorp/packer/helper/multistep"
"github.com/hashicorp/packer/packer"
"strings"
)
type RunConfig struct {

View File

@ -7,11 +7,12 @@ import (
"bytes"
"context"
"fmt"
"log"
"time"
"github.com/hashicorp/packer/builder/vsphere/driver"
"github.com/hashicorp/packer/helper/multistep"
"github.com/hashicorp/packer/packer"
"log"
"time"
)
type ShutdownConfig struct {

View File

@ -2,6 +2,7 @@ package common
import (
"context"
"github.com/hashicorp/packer/builder/vsphere/driver"
"github.com/hashicorp/packer/helper/multistep"
"github.com/hashicorp/packer/packer"

View File

@ -2,6 +2,7 @@ package common
import (
"context"
"github.com/hashicorp/packer/builder/vsphere/driver"
"github.com/hashicorp/packer/helper/multistep"
"github.com/hashicorp/packer/packer"

View File

@ -6,11 +6,12 @@ package common
import (
"context"
"fmt"
"log"
"time"
"github.com/hashicorp/packer/builder/vsphere/driver"
"github.com/hashicorp/packer/helper/multistep"
"github.com/hashicorp/packer/packer"
"log"
"time"
)
type WaitIpConfig struct {

View File

@ -3,13 +3,14 @@ package testing
import (
"encoding/json"
"fmt"
"github.com/hashicorp/packer/builder/vsphere/common"
"github.com/hashicorp/packer/builder/vsphere/driver"
"github.com/hashicorp/packer/packer"
"math/rand"
"os"
"testing"
"time"
"github.com/hashicorp/packer/builder/vsphere/common"
"github.com/hashicorp/packer/builder/vsphere/driver"
"github.com/hashicorp/packer/packer"
)
func NewVMName() string {

View File

@ -2,6 +2,7 @@ package driver
import (
"fmt"
"github.com/vmware/govmomi/object"
"github.com/vmware/govmomi/vim25/mo"
"github.com/vmware/govmomi/vim25/soap"

View File

@ -3,14 +3,15 @@ package driver
import (
"context"
"fmt"
"net/url"
"time"
"github.com/vmware/govmomi"
"github.com/vmware/govmomi/find"
"github.com/vmware/govmomi/object"
"github.com/vmware/govmomi/session"
"github.com/vmware/govmomi/vim25"
"github.com/vmware/govmomi/vim25/soap"
"net/url"
"time"
)
type Driver struct {

View File

@ -2,6 +2,7 @@ package driver
import (
"fmt"
"github.com/vmware/govmomi/object"
"github.com/vmware/govmomi/vim25/mo"
"github.com/vmware/govmomi/vim25/types"

View File

@ -2,6 +2,7 @@ package driver
import (
"fmt"
"github.com/vmware/govmomi/object"
"github.com/vmware/govmomi/vim25/mo"
"github.com/vmware/govmomi/vim25/types"

View File

@ -4,12 +4,13 @@ import (
"context"
"errors"
"fmt"
"github.com/vmware/govmomi/object"
"github.com/vmware/govmomi/vim25/mo"
"github.com/vmware/govmomi/vim25/types"
"log"
"strings"
"time"
"github.com/vmware/govmomi/object"
"github.com/vmware/govmomi/vim25/mo"
"github.com/vmware/govmomi/vim25/types"
)
type VirtualMachine struct {
@ -43,6 +44,13 @@ type HardwareConfig struct {
VideoRAM int64
}
type NIC struct {
Network string // "" for default network
NetworkCard string // example: vmxnet3
MacAddress string // set mac if want specific address
Passthrough *bool // direct path i/o
}
type CreateConfig struct {
DiskThinProvisioned bool
DiskControllerType string // example: "scsi", "pvscsi"
@ -56,8 +64,7 @@ type CreateConfig struct {
ResourcePool string
Datastore string
GuestOS string // example: otherGuest
Network string // "" for default network
NetworkCard string // example: vmxnet3
NICs []NIC
USBController bool
Version uint // example: 10
Firmware string // efi or bios
@ -508,42 +515,56 @@ func addDisk(_ *Driver, devices object.VirtualDeviceList, config *CreateConfig)
}
func addNetwork(d *Driver, devices object.VirtualDeviceList, config *CreateConfig) (object.VirtualDeviceList, error) {
if len(config.NICs) == 0 {
return nil, errors.New("no network adapters have been defined")
}
var network object.NetworkReference
if config.Network == "" {
h, err := d.FindHost(config.Host)
for _, nic := range config.NICs {
if nic.Network == "" {
h, err := d.FindHost(config.Host)
if err != nil {
return nil, err
}
i, err := h.Info("network")
if err != nil {
return nil, err
}
if len(i.Network) > 1 {
return nil, fmt.Errorf("Host has multiple networks. Specify it explicitly")
}
network = object.NewNetwork(d.client.Client, i.Network[0])
} else {
var err error
network, err = d.finder.Network(d.ctx, nic.Network)
if err != nil {
return nil, err
}
}
backing, err := network.EthernetCardBackingInfo(d.ctx)
if err != nil {
return nil, err
}
i, err := h.Info("network")
device, err := object.EthernetCardTypes().CreateEthernetCard(nic.NetworkCard, backing)
if err != nil {
return nil, err
}
if len(i.Network) > 1 {
return nil, fmt.Errorf("Host has multiple networks. Specify it explicitly")
card := device.(types.BaseVirtualEthernetCard).GetVirtualEthernetCard()
if nic.MacAddress != "" {
card.AddressType = string(types.VirtualEthernetCardMacTypeManual)
card.MacAddress = nic.MacAddress
}
card.UptCompatibilityEnabled = nic.Passthrough
network = object.NewNetwork(d.client.Client, i.Network[0])
} else {
var err error
network, err = d.finder.Network(d.ctx, config.Network)
if err != nil {
return nil, err
}
devices = append(devices, device)
}
backing, err := network.EthernetCardBackingInfo(d.ctx)
if err != nil {
return nil, err
}
device, err := object.EthernetCardTypes().CreateEthernetCard(config.NetworkCard, backing)
if err != nil {
return nil, err
}
return append(devices, device), nil
return devices, nil
}
func (vm *VirtualMachine) AddCdrom(controllerType string, isoPath string) error {

View File

@ -2,6 +2,7 @@ package driver
import (
"errors"
"github.com/vmware/govmomi/vim25/types"
)
@ -51,6 +52,23 @@ func (vm *VirtualMachine) CreateCdrom(c *types.VirtualController) (*types.Virtua
return device, nil
}
func (vm *VirtualMachine) RemoveCdroms() error {
devices, err := vm.Devices()
if err != nil {
return err
}
cdroms := devices.SelectByType((*types.VirtualCdrom)(nil))
if err = vm.RemoveDevice(true, cdroms...); err != nil {
return err
}
sata := devices.SelectByType((*types.VirtualAHCIController)(nil))
if err = vm.RemoveDevice(true, sata...); err != nil {
return err
}
return nil
}
func (vm *VirtualMachine) EjectCdroms() error {
devices, err := vm.Devices()
if err != nil {

View File

@ -1,11 +1,12 @@
package driver
import (
"strings"
"unicode"
"github.com/vmware/govmomi/vim25/methods"
"github.com/vmware/govmomi/vim25/types"
"golang.org/x/mobile/event/key"
"strings"
"unicode"
)
type KeyInput struct {

View File

@ -2,6 +2,7 @@ package main
import (
"fmt"
"github.com/hashicorp/packer/builder/vsphere/driver"
)

View File

@ -121,7 +121,9 @@ func (b *Builder) Run(ctx context.Context, ui packer.Ui, hook packer.Hook) (pack
}
steps = append(steps,
&StepRemoveCDRom{},
&StepRemoveCDRom{
Config: &b.config.RemoveCDRomConfig,
},
&common.StepCreateSnapshot{
CreateSnapshot: b.config.CreateSnapshot,
},

View File

@ -2,13 +2,14 @@ package iso
import (
"fmt"
"io/ioutil"
"os"
"testing"
commonT "github.com/hashicorp/packer/builder/vsphere/common/testing"
builderT "github.com/hashicorp/packer/helper/builder/testing"
"github.com/hashicorp/packer/packer"
"github.com/vmware/govmomi/vim25/types"
"io/ioutil"
"os"
"testing"
)
func TestISOBuilderAcc_default(t *testing.T) {

View File

@ -24,6 +24,7 @@ type Config struct {
packerCommon.ISOConfig `mapstructure:",squash"`
CDRomConfig `mapstructure:",squash"`
RemoveCDRomConfig `mapstructure:",squash"`
FloppyConfig `mapstructure:",squash"`
common.RunConfig `mapstructure:",squash"`
BootConfig `mapstructure:",squash"`

View File

@ -32,6 +32,7 @@ type FlatConfig struct {
DiskThinProvisioned *bool `mapstructure:"disk_thin_provisioned" cty:"disk_thin_provisioned"`
Network *string `mapstructure:"network" cty:"network"`
NetworkCard *string `mapstructure:"network_card" cty:"network_card"`
NICs []FlatNIC `mapstructure:"network_adapters" cty:"network_adapters"`
USBController *bool `mapstructure:"usb_controller" cty:"usb_controller"`
Notes *string `mapstructure:"notes" cty:"notes"`
VMName *string `mapstructure:"vm_name" cty:"vm_name"`
@ -61,6 +62,7 @@ type FlatConfig struct {
TargetExtension *string `mapstructure:"iso_target_extension" cty:"iso_target_extension"`
CdromType *string `mapstructure:"cdrom_type" cty:"cdrom_type"`
ISOPaths []string `mapstructure:"iso_paths" cty:"iso_paths"`
RemoveCdrom *bool `mapstructure:"remove_cdrom" cty:"remove_cdrom"`
FloppyIMGPath *string `mapstructure:"floppy_img_path" cty:"floppy_img_path"`
FloppyFiles []string `mapstructure:"floppy_files" cty:"floppy_files"`
FloppyDirectories []string `mapstructure:"floppy_dirs" cty:"floppy_dirs"`
@ -151,6 +153,7 @@ func (*FlatConfig) HCL2Spec() map[string]hcldec.Spec {
"disk_thin_provisioned": &hcldec.AttrSpec{Name: "disk_thin_provisioned", Type: cty.Bool, Required: false},
"network": &hcldec.AttrSpec{Name: "network", Type: cty.String, Required: false},
"network_card": &hcldec.AttrSpec{Name: "network_card", Type: cty.String, Required: false},
"network_adapters": &hcldec.BlockListSpec{TypeName: "network_adapters", Nested: hcldec.ObjectSpec((*FlatNIC)(nil).HCL2Spec())},
"usb_controller": &hcldec.AttrSpec{Name: "usb_controller", Type: cty.Bool, Required: false},
"notes": &hcldec.AttrSpec{Name: "notes", Type: cty.String, Required: false},
"vm_name": &hcldec.AttrSpec{Name: "vm_name", Type: cty.String, Required: false},
@ -180,6 +183,7 @@ func (*FlatConfig) HCL2Spec() map[string]hcldec.Spec {
"iso_target_extension": &hcldec.AttrSpec{Name: "iso_target_extension", Type: cty.String, Required: false},
"cdrom_type": &hcldec.AttrSpec{Name: "cdrom_type", Type: cty.String, Required: false},
"iso_paths": &hcldec.AttrSpec{Name: "iso_paths", Type: cty.List(cty.String), Required: false},
"remove_cdrom": &hcldec.AttrSpec{Name: "remove_cdrom", Type: cty.Bool, Required: false},
"floppy_img_path": &hcldec.AttrSpec{Name: "floppy_img_path", Type: cty.String, Required: false},
"floppy_files": &hcldec.AttrSpec{Name: "floppy_files", Type: cty.List(cty.String), Required: false},
"floppy_dirs": &hcldec.AttrSpec{Name: "floppy_dirs", Type: cty.List(cty.String), Required: false},

View File

@ -6,6 +6,7 @@ package iso
import (
"context"
"fmt"
"github.com/hashicorp/packer/builder/vsphere/driver"
"github.com/hashicorp/packer/helper/multistep"
"github.com/hashicorp/packer/packer"

View File

@ -6,6 +6,7 @@ package iso
import (
"context"
"fmt"
"github.com/hashicorp/packer/builder/vsphere/driver"
"github.com/hashicorp/packer/helper/multistep"
"github.com/hashicorp/packer/packer"

View File

@ -3,18 +3,19 @@ package iso
import (
"context"
"fmt"
"github.com/hashicorp/packer/builder/vsphere/driver"
packerCommon "github.com/hashicorp/packer/common"
"github.com/hashicorp/packer/helper/multistep"
"github.com/hashicorp/packer/packer"
"github.com/hashicorp/packer/template/interpolate"
"golang.org/x/mobile/event/key"
"log"
"net"
"os"
"strings"
"time"
"unicode/utf8"
"github.com/hashicorp/packer/builder/vsphere/driver"
packerCommon "github.com/hashicorp/packer/common"
"github.com/hashicorp/packer/helper/multistep"
"github.com/hashicorp/packer/packer"
"github.com/hashicorp/packer/template/interpolate"
"golang.org/x/mobile/event/key"
)
type BootConfig struct {

View File

@ -1,5 +1,5 @@
//go:generate struct-markdown
//go:generate mapstructure-to-hcl2 -type CreateConfig
//go:generate mapstructure-to-hcl2 -type NIC,CreateConfig
package iso
@ -13,6 +13,17 @@ import (
"github.com/hashicorp/packer/packer"
)
type NIC struct {
// Set network VM will be connected to.
Network string `mapstructure:"network"`
// Set VM network card type. Example `vmxnet3`.
NetworkCard string `mapstructure:"network_card" required:"true"`
// Set network card MAC address
MacAddress string `mapstructure:"mac_address"`
// Enable DirectPath I/O passthrough
Passthrough *bool `mapstructure:"passthrough"`
}
type CreateConfig struct {
// Set VM hardware version. Defaults to the most current VM hardware
// version supported by vCenter. See
@ -35,6 +46,8 @@ type CreateConfig struct {
Network string `mapstructure:"network"`
// Set VM network card type. Example `vmxnet3`.
NetworkCard string `mapstructure:"network_card"`
// Network adapters
NICs []NIC `mapstructure:"network_adapters"`
// Create USB controller for virtual machine. Defaults to `false`.
USBController bool `mapstructure:"usb_controller"`
// VM notes.
@ -83,6 +96,23 @@ func (s *StepCreateVM) Run(_ context.Context, state multistep.StateBag) multiste
}
ui.Say("Creating VM...")
// add network/network card an the first nic for backwards compatibility in the type is defined
var networkCards []driver.NIC
if s.Config.NetworkCard != "" {
networkCards = append(networkCards, driver.NIC{
NetworkCard: s.Config.NetworkCard,
Network: s.Config.Network})
}
for _, nic := range s.Config.NICs {
networkCards = append(networkCards, driver.NIC{
Network: nic.Network,
NetworkCard: nic.NetworkCard,
MacAddress: nic.MacAddress,
Passthrough: nic.Passthrough,
})
}
vm, err = d.CreateVM(&driver.CreateConfig{
DiskThinProvisioned: s.Config.DiskThinProvisioned,
DiskControllerType: s.Config.DiskControllerType,
@ -94,8 +124,7 @@ func (s *StepCreateVM) Run(_ context.Context, state multistep.StateBag) multiste
ResourcePool: s.Location.ResourcePool,
Datastore: s.Location.Datastore,
GuestOS: s.Config.GuestOSType,
Network: s.Config.Network,
NetworkCard: s.Config.NetworkCard,
NICs: networkCards,
USBController: s.Config.USBController,
Version: s.Config.Version,
Firmware: s.Config.Firmware,

View File

@ -1,4 +1,4 @@
// Code generated by "mapstructure-to-hcl2 -type CreateConfig"; DO NOT EDIT.
// Code generated by "mapstructure-to-hcl2 -type NIC,CreateConfig"; DO NOT EDIT.
package iso
import (
@ -9,16 +9,17 @@ import (
// FlatCreateConfig is an auto-generated flat version of CreateConfig.
// Where the contents of a field with a `mapstructure:,squash` tag are bubbled up.
type FlatCreateConfig struct {
Version *uint `mapstructure:"vm_version" cty:"vm_version"`
GuestOSType *string `mapstructure:"guest_os_type" cty:"guest_os_type"`
Firmware *string `mapstructure:"firmware" cty:"firmware"`
DiskControllerType *string `mapstructure:"disk_controller_type" cty:"disk_controller_type"`
DiskSize *int64 `mapstructure:"disk_size" cty:"disk_size"`
DiskThinProvisioned *bool `mapstructure:"disk_thin_provisioned" cty:"disk_thin_provisioned"`
Network *string `mapstructure:"network" cty:"network"`
NetworkCard *string `mapstructure:"network_card" cty:"network_card"`
USBController *bool `mapstructure:"usb_controller" cty:"usb_controller"`
Notes *string `mapstructure:"notes" cty:"notes"`
Version *uint `mapstructure:"vm_version" cty:"vm_version"`
GuestOSType *string `mapstructure:"guest_os_type" cty:"guest_os_type"`
Firmware *string `mapstructure:"firmware" cty:"firmware"`
DiskControllerType *string `mapstructure:"disk_controller_type" cty:"disk_controller_type"`
DiskSize *int64 `mapstructure:"disk_size" cty:"disk_size"`
DiskThinProvisioned *bool `mapstructure:"disk_thin_provisioned" cty:"disk_thin_provisioned"`
Network *string `mapstructure:"network" cty:"network"`
NetworkCard *string `mapstructure:"network_card" cty:"network_card"`
NICs []FlatNIC `mapstructure:"network_adapters" cty:"network_adapters"`
USBController *bool `mapstructure:"usb_controller" cty:"usb_controller"`
Notes *string `mapstructure:"notes" cty:"notes"`
}
// FlatMapstructure returns a new FlatCreateConfig.
@ -41,8 +42,36 @@ func (*FlatCreateConfig) HCL2Spec() map[string]hcldec.Spec {
"disk_thin_provisioned": &hcldec.AttrSpec{Name: "disk_thin_provisioned", Type: cty.Bool, Required: false},
"network": &hcldec.AttrSpec{Name: "network", Type: cty.String, Required: false},
"network_card": &hcldec.AttrSpec{Name: "network_card", Type: cty.String, Required: false},
"network_adapters": &hcldec.BlockListSpec{TypeName: "network_adapters", Nested: hcldec.ObjectSpec((*FlatNIC)(nil).HCL2Spec())},
"usb_controller": &hcldec.AttrSpec{Name: "usb_controller", Type: cty.Bool, Required: false},
"notes": &hcldec.AttrSpec{Name: "notes", Type: cty.String, Required: false},
}
return s
}
// FlatNIC is an auto-generated flat version of NIC.
// Where the contents of a field with a `mapstructure:,squash` tag are bubbled up.
type FlatNIC struct {
Network *string `mapstructure:"network" cty:"network"`
NetworkCard *string `mapstructure:"network_card" required:"true" cty:"network_card"`
MacAddress *string `mapstructure:"mac_address" cty:"mac_address"`
Passthrough *bool `mapstructure:"passthrough" cty:"passthrough"`
}
// FlatMapstructure returns a new FlatNIC.
// FlatNIC is an auto-generated flat version of NIC.
// Where the contents a fields with a `mapstructure:,squash` tag are bubbled up.
func (*NIC) FlatMapstructure() interface{ HCL2Spec() map[string]hcldec.Spec } { return new(FlatNIC) }
// HCL2Spec returns the hcl spec of a NIC.
// This spec is used by HCL to read the fields of NIC.
// The decoded values from this spec will then be applied to a FlatNIC.
func (*FlatNIC) HCL2Spec() map[string]hcldec.Spec {
s := map[string]hcldec.Spec{
"network": &hcldec.AttrSpec{Name: "network", Type: cty.String, Required: false},
"network_card": &hcldec.AttrSpec{Name: "network_card", Type: cty.String, Required: false},
"mac_address": &hcldec.AttrSpec{Name: "mac_address", Type: cty.String, Required: false},
"passthrough": &hcldec.AttrSpec{Name: "passthrough", Type: cty.Bool, Required: false},
}
return s
}

View File

@ -3,10 +3,11 @@ package iso
import (
"context"
"fmt"
"path/filepath"
"github.com/hashicorp/packer/builder/vsphere/driver"
"github.com/hashicorp/packer/helper/multistep"
"github.com/hashicorp/packer/packer"
"path/filepath"
)
type StepRemoteUpload struct {

View File

@ -1,13 +1,24 @@
//go:generate struct-markdown
//go:generate mapstructure-to-hcl2 -type RemoveCDRomConfig
package iso
import (
"context"
"github.com/hashicorp/packer/builder/vsphere/driver"
"github.com/hashicorp/packer/helper/multistep"
"github.com/hashicorp/packer/packer"
)
type StepRemoveCDRom struct{}
type RemoveCDRomConfig struct {
// Remove CD-ROM devices from template. Defaults to `false`.
RemoveCdrom bool `mapstructure:"remove_cdrom"`
}
type StepRemoveCDRom struct {
Config *RemoveCDRomConfig
}
func (s *StepRemoveCDRom) Run(_ context.Context, state multistep.StateBag) multistep.StepAction {
ui := state.Get("ui").(packer.Ui)
@ -20,6 +31,15 @@ func (s *StepRemoveCDRom) Run(_ context.Context, state multistep.StateBag) multi
return multistep.ActionHalt
}
if s.Config.RemoveCdrom == true {
ui.Say("Deleting CD-ROM drives...")
err := vm.RemoveCdroms()
if err != nil {
state.Put("error", err)
return multistep.ActionHalt
}
}
return multistep.ActionContinue
}

View File

@ -0,0 +1,30 @@
// Code generated by "mapstructure-to-hcl2 -type RemoveCDRomConfig"; DO NOT EDIT.
package iso
import (
"github.com/hashicorp/hcl/v2/hcldec"
"github.com/zclconf/go-cty/cty"
)
// FlatRemoveCDRomConfig is an auto-generated flat version of RemoveCDRomConfig.
// Where the contents of a field with a `mapstructure:,squash` tag are bubbled up.
type FlatRemoveCDRomConfig struct {
RemoveCdrom *bool `mapstructure:"remove_cdrom" cty:"remove_cdrom"`
}
// FlatMapstructure returns a new FlatRemoveCDRomConfig.
// FlatRemoveCDRomConfig is an auto-generated flat version of RemoveCDRomConfig.
// Where the contents a fields with a `mapstructure:,squash` tag are bubbled up.
func (*RemoveCDRomConfig) FlatMapstructure() interface{ HCL2Spec() map[string]hcldec.Spec } {
return new(FlatRemoveCDRomConfig)
}
// HCL2Spec returns the hcl spec of a RemoveCDRomConfig.
// This spec is used by HCL to read the fields of RemoveCDRomConfig.
// The decoded values from this spec will then be applied to a FlatRemoveCDRomConfig.
func (*FlatRemoveCDRomConfig) HCL2Spec() map[string]hcldec.Spec {
s := map[string]hcldec.Spec{
"remove_cdrom": &hcldec.AttrSpec{Name: "remove_cdrom", Type: cty.Bool, Required: false},
}
return s
}

View File

@ -2,6 +2,7 @@ package iso
import (
"context"
"github.com/hashicorp/packer/builder/vsphere/driver"
"github.com/hashicorp/packer/helper/multistep"
"github.com/hashicorp/packer/packer"

View File

@ -41,6 +41,8 @@ type Config struct {
// is an alternative method to authenticate to Yandex.Cloud. Alternatively you may set environment variable
// YC_SERVICE_ACCOUNT_KEY_FILE.
ServiceAccountKeyFile string `mapstructure:"service_account_key_file" required:"false"`
// Service account identifier to assign to instance
ServiceAccountID string `mapstructure:"service_account_id" required:"false"`
// OAuth token to use to authenticate to Yandex.Cloud. Alternatively you may set
// value by environment variable YC_TOKEN.
Token string `mapstructure:"token" required:"true"`

View File

@ -59,6 +59,7 @@ type FlatConfig struct {
Endpoint *string `mapstructure:"endpoint" required:"false" cty:"endpoint"`
FolderID *string `mapstructure:"folder_id" required:"true" cty:"folder_id"`
ServiceAccountKeyFile *string `mapstructure:"service_account_key_file" required:"false" cty:"service_account_key_file"`
ServiceAccountID *string `mapstructure:"service_account_id" required:"false" cty:"service_account_id"`
Token *string `mapstructure:"token" required:"true" cty:"token"`
DiskName *string `mapstructure:"disk_name" required:"false" cty:"disk_name"`
DiskSizeGb *int `mapstructure:"disk_size_gb" required:"false" cty:"disk_size_gb"`
@ -153,6 +154,7 @@ func (*FlatConfig) HCL2Spec() map[string]hcldec.Spec {
"endpoint": &hcldec.AttrSpec{Name: "endpoint", Type: cty.String, Required: false},
"folder_id": &hcldec.AttrSpec{Name: "folder_id", Type: cty.String, Required: false},
"service_account_key_file": &hcldec.AttrSpec{Name: "service_account_key_file", Type: cty.String, Required: false},
"service_account_id": &hcldec.AttrSpec{Name: "service_account_id", Type: cty.String, Required: false},
"token": &hcldec.AttrSpec{Name: "token", Type: cty.String, Required: false},
"disk_name": &hcldec.AttrSpec{Name: "disk_name", Type: cty.String, Required: false},
"disk_size_gb": &hcldec.AttrSpec{Name: "disk_size_gb", Type: cty.Number, Required: false},

View File

@ -205,6 +205,10 @@ runcmd:
},
}
if config.ServiceAccountID != "" {
req.ServiceAccountId = config.ServiceAccountID
}
if config.UseIPv6 {
req.NetworkInterfaceSpecs[0].PrimaryV6AddressSpec = &compute.PrimaryAddressSpec{}
}

View File

@ -25,7 +25,6 @@ import (
"bytes"
"flag"
"fmt"
"go/format"
"go/types"
"io"
"log"
@ -39,6 +38,7 @@ import (
"github.com/zclconf/go-cty/cty"
"golang.org/x/tools/go/packages"
"golang.org/x/tools/imports"
)
var (
@ -189,7 +189,7 @@ func main() {
log.Fatalf("os.Create: %v", err)
}
_, err = outputFile.Write(goFmt(out.Bytes()))
_, err = outputFile.Write(goFmt(outputFile.Name(), out.Bytes()))
if err != nil {
log.Fatalf("failed to write file: %v", err)
}
@ -575,8 +575,8 @@ func ToSnakeCase(str string) string {
return strings.ToLower(snake)
}
func goFmt(b []byte) []byte {
fb, err := format.Source(b)
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

View File

@ -60,19 +60,20 @@ func main() {
}
fields := structDecl.Fields.List
sourcePath := filepath.ToSlash(paths[1])
header := Struct{
SourcePath: paths[1],
SourcePath: sourcePath,
Name: typeSpec.Name.Name,
Filename: "_" + typeSpec.Name.Name + ".html.md",
Header: typeDecl.Doc.Text(),
}
required := Struct{
SourcePath: paths[1],
SourcePath: sourcePath,
Name: typeSpec.Name.Name,
Filename: "_" + typeSpec.Name.Name + "-required.html.md",
}
notRequired := Struct{
SourcePath: paths[1],
SourcePath: sourcePath,
Name: typeSpec.Name.Name,
Filename: "_" + typeSpec.Name.Name + "-not-required.html.md",
}

View File

@ -4,11 +4,12 @@ import (
"bytes"
"context"
"fmt"
"github.com/hashicorp/hcl/v2/hcldec"
"path/filepath"
"sync"
"testing"
"github.com/hashicorp/hcl/v2/hcldec"
"golang.org/x/sync/errgroup"
"github.com/hashicorp/packer/builder/file"

View File

@ -111,6 +111,33 @@ func TestBuildOnlyFileMultipleFlags(t *testing.T) {
}
}
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),
@ -231,7 +258,7 @@ func testMetaFile(t *testing.T) Meta {
}
}
func cleanup() {
func cleanup(moreFiles ...string) {
os.RemoveAll("chocolate.txt")
os.RemoveAll("vanilla.txt")
os.RemoveAll("cherry.txt")
@ -245,6 +272,9 @@ func cleanup() {
os.RemoveAll("lilas.txt")
os.RemoveAll("campanules.txt")
os.RemoveAll("ducky.txt")
for _, file := range moreFiles {
os.RemoveAll(file)
}
}
func TestBuildCommand_ParseArgs(t *testing.T) {

View File

@ -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"
]
}
]
}

View File

@ -3,15 +3,12 @@
package common
import (
"context"
"encoding/hex"
"errors"
"fmt"
"log"
"net/url"
"os"
"strings"
getter "github.com/hashicorp/go-getter"
"github.com/hashicorp/packer/template/interpolate"
)
@ -106,7 +103,7 @@ type ISOConfig struct {
TargetExtension string `mapstructure:"iso_target_extension"`
}
func (c *ISOConfig) Prepare(ctx *interpolate.Context) (warnings []string, errs []error) {
func (c *ISOConfig) Prepare(*interpolate.Context) (warnings []string, errs []error) {
if len(c.ISOUrls) != 0 && c.RawSingleISOUrl != "" {
errs = append(
errs, errors.New("Only one of iso_url or iso_urls must be specified"))
@ -159,27 +156,13 @@ func (c *ISOConfig) Prepare(ctx *interpolate.Context) (warnings []string, errs [
errs = append(errs, fmt.Errorf("A checksum must be specified"))
}
if c.ISOChecksumType == "file" {
u, err := url.Parse(c.ISOUrls[0])
url := c.ISOChecksum
if c.ISOChecksumURL != "" {
url = c.ISOChecksumURL
}
cksum, err := defaultGetterClient.ChecksumFromFile(context.TODO(), url, c.ISOUrls[0])
if err != nil {
errs = append(errs, fmt.Errorf("error parsing URL <%s>: %s",
c.ISOUrls[0], err))
}
wd, err := os.Getwd()
if err != nil {
log.Printf("get working directory: %v", err)
// here we ignore the error in case the
// working directory is not needed.
}
gc := getter.Client{
Dst: "no-op",
Src: u.String(),
Pwd: wd,
Dir: false,
Getters: getter.Getters,
}
cksum, err := gc.ChecksumFromFile(c.ISOChecksumURL, u)
if cksum == nil || err != nil {
errs = append(errs, fmt.Errorf("Couldn't extract checksum from checksum file"))
errs = append(errs, fmt.Errorf("Couldn't extract checksum from checksum file: %v", err))
} else {
c.ISOChecksumType = cksum.Type
c.ISOChecksum = hex.EncodeToString(cksum.Value)

View File

@ -5,7 +5,6 @@ package shell_local
import (
"errors"
"fmt"
// "log"
"os"
"path/filepath"
"runtime"

View File

@ -11,8 +11,8 @@ import (
"runtime"
"strings"
getter "github.com/hashicorp/go-getter"
urlhelper "github.com/hashicorp/go-getter/helper/url"
getter "github.com/hashicorp/go-getter/v2"
urlhelper "github.com/hashicorp/go-getter/v2/helper/url"
"github.com/hashicorp/packer/common/filelock"
"github.com/hashicorp/packer/helper/multistep"
"github.com/hashicorp/packer/packer"
@ -52,6 +52,8 @@ type StepDownload struct {
Extension string
}
var defaultGetterClient = getter.Client{}
func (s *StepDownload) Run(ctx context.Context, state multistep.StateBag) multistep.StepAction {
if len(s.Url) == 0 {
log.Printf("No URLs were provided to Step Download. Continuing...")
@ -96,24 +98,6 @@ func (s *StepDownload) Run(ctx context.Context, state multistep.StateBag) multis
return multistep.ActionHalt
}
var (
getters = getter.Getters
)
func init() {
if runtime.GOOS == "windows" {
getters["file"] = &getter.FileGetter{
// always copy local files instead of symlinking to fix GH-7534. The
// longer term fix for this would be to change the go-getter so that it
// can leave the source file where it is & tell us where it is.
Copy: true,
}
getters["smb"] = &getter.FileGetter{
Copy: true,
}
}
}
func (s *StepDownload) download(ctx context.Context, ui packer.Ui, source string) (string, error) {
if runtime.GOOS == "windows" {
// Check that the user specified a UNC path, and promote it to an smb:// uri.
@ -208,20 +192,19 @@ func (s *StepDownload) download(ctx context.Context, ui packer.Ui, source string
}
ui.Say(fmt.Sprintf("Trying %s", u.String()))
gc := getter.Client{
Ctx: ctx,
req := &getter.Request{
Dst: targetPath,
Src: src,
ProgressListener: ui,
Pwd: wd,
Dir: false,
Getters: getters,
Mode: getter.ModeFile,
Inplace: true,
}
switch err := gc.Get(); err.(type) {
switch op, err := defaultGetterClient.Get(ctx, req); err.(type) {
case nil: // success !
ui.Say(fmt.Sprintf("%s => %s", u.String(), targetPath))
return targetPath, nil
ui.Say(fmt.Sprintf("%s => %s", u.String(), op.Dst))
return op.Dst, nil
case *getter.ChecksumError:
ui.Say(fmt.Sprintf("Checksum did not match, removing %s", targetPath))
if err := os.Remove(targetPath); err != nil {

View File

@ -5,7 +5,6 @@ import (
"context"
"crypto/sha1"
"encoding/hex"
"github.com/hashicorp/packer/packer"
"io/ioutil"
"log"
"net/http"
@ -16,8 +15,9 @@ import (
"testing"
"github.com/google/go-cmp/cmp"
urlhelper "github.com/hashicorp/go-getter/helper/url"
urlhelper "github.com/hashicorp/go-getter/v2/helper/url"
"github.com/hashicorp/packer/helper/multistep"
"github.com/hashicorp/packer/packer"
"github.com/hashicorp/packer/packer/tmp"
)
@ -74,7 +74,6 @@ func TestStepDownload_Run(t *testing.T) {
fields{Url: []string{abs(t, "./test-fixtures/root/another.txt")}},
multistep.ActionContinue,
[]string{
toSha1(abs(t, "./test-fixtures/root/another.txt")),
toSha1(abs(t, "./test-fixtures/root/another.txt")) + ".lock",
},
},
@ -82,7 +81,6 @@ func TestStepDownload_Run(t *testing.T) {
fields{Url: []string{abs(t, "./test-fixtures/root//another.txt")}},
multistep.ActionContinue,
[]string{
toSha1(abs(t, "./test-fixtures/root//another.txt")),
toSha1(abs(t, "./test-fixtures/root//another.txt")) + ".lock",
},
},
@ -90,7 +88,6 @@ func TestStepDownload_Run(t *testing.T) {
fields{Url: []string{abs(t, "./test-fixtures/root/another.txt")}, ChecksumType: "none"},
multistep.ActionContinue,
[]string{
toSha1(abs(t, "./test-fixtures/root/another.txt")),
toSha1(abs(t, "./test-fixtures/root/another.txt")) + ".lock",
},
},
@ -159,7 +156,6 @@ func TestStepDownload_Run(t *testing.T) {
fields{Extension: "txt", Url: []string{"./test-fixtures/root/another.txt?checksum=" + cs["/root/another.txt"]}},
multistep.ActionContinue,
[]string{
toSha1(cs["/root/another.txt"]) + ".txt",
toSha1(cs["/root/another.txt"]) + ".txt.lock",
},
},
@ -167,7 +163,6 @@ func TestStepDownload_Run(t *testing.T) {
fields{Extension: "txt", Url: []string{"./test-fixtures/root/another.txt?"}, Checksum: cs["/root/another.txt"]},
multistep.ActionContinue,
[]string{
toSha1(cs["/root/another.txt"]) + ".txt",
toSha1(cs["/root/another.txt"]) + ".txt.lock",
},
},
@ -175,7 +170,6 @@ func TestStepDownload_Run(t *testing.T) {
fields{Extension: "txt", Url: []string{"./test-fixtures/root/another.txt?"}, ChecksumType: "sha1", Checksum: cs["/root/another.txt"]},
multistep.ActionContinue,
[]string{
toSha1(cs["/root/another.txt"]) + ".txt",
toSha1(cs["/root/another.txt"]) + ".txt.lock",
},
},
@ -183,7 +177,6 @@ func TestStepDownload_Run(t *testing.T) {
fields{Extension: "txt", Url: []string{abs(t, "./test-fixtures/root/another.txt") + "?checksum=" + cs["/root/another.txt"]}},
multistep.ActionContinue,
[]string{
toSha1(cs["/root/another.txt"]) + ".txt",
toSha1(cs["/root/another.txt"]) + ".txt.lock",
},
},
@ -191,7 +184,6 @@ func TestStepDownload_Run(t *testing.T) {
fields{Extension: "txt", Url: []string{abs(t, "./test-fixtures/root/another.txt") + "?"}, Checksum: cs["/root/another.txt"]},
multistep.ActionContinue,
[]string{
toSha1(cs["/root/another.txt"]) + ".txt",
toSha1(cs["/root/another.txt"]) + ".txt.lock",
},
},
@ -199,7 +191,6 @@ func TestStepDownload_Run(t *testing.T) {
fields{Extension: "txt", Url: []string{abs(t, "./test-fixtures/root/another.txt") + "?"}, ChecksumType: "sha1", Checksum: cs["/root/another.txt"]},
multistep.ActionContinue,
[]string{
toSha1(cs["/root/another.txt"]) + ".txt",
toSha1(cs["/root/another.txt"]) + ".txt.lock",
},
},
@ -214,7 +205,6 @@ func TestStepDownload_Run(t *testing.T) {
},
multistep.ActionContinue,
[]string{
toSha1(cs["/root/basic.txt"]),
toSha1(cs["/root/basic.txt"]) + ".lock",
},
},
@ -268,36 +258,33 @@ func TestStepDownload_download(t *testing.T) {
// Abs path with extension provided
step.TargetPath = "./packer"
step.Extension = "ova"
path, err := step.download(context.TODO(), ui, "./test-fixtures/root/basic.txt")
_, err := step.download(context.TODO(), ui, "./test-fixtures/root/basic.txt")
if err != nil {
t.Fatalf("Bad: non expected error %s", err.Error())
}
if filepath.Ext(path) != "."+step.Extension {
t.Fatalf("bad: path should contain extension %s but it was %s", step.Extension, filepath.Ext(path))
}
// because of the inplace option; the result file will not be renamed
// sha.ova.
os.RemoveAll(step.TargetPath)
// Abs path with no extension provided
step.TargetPath = "./packer"
step.Extension = ""
path, err = step.download(context.TODO(), ui, "./test-fixtures/root/basic.txt")
_, err = step.download(context.TODO(), ui, "./test-fixtures/root/basic.txt")
if err != nil {
t.Fatalf("Bad: non expected error %s", err.Error())
}
if filepath.Ext(path) != ".iso" {
t.Fatalf("bad: path should contain extension %s but it was .iso", step.Extension)
}
// because of the inplace option; the result file will not be renamed
// sha.ova.
os.RemoveAll(step.TargetPath)
// Path with file
step.TargetPath = "./packer/file.iso"
path, err = step.download(context.TODO(), ui, "./test-fixtures/root/basic.txt")
_, err = step.download(context.TODO(), ui, "./test-fixtures/root/basic.txt")
if err != nil {
t.Fatalf("Bad: non expected error %s", err.Error())
}
if path != "./packer/file.iso" {
t.Fatalf("bad: path should be ./packer/file.iso but it was %s", path)
}
// because of the inplace option; the result file will not be renamed
// sha.ova.
os.RemoveAll(step.TargetPath)
}

View File

@ -2,10 +2,10 @@ package common
import (
"fmt"
"github.com/hashicorp/packer/helper/communicator"
"os"
"testing"
"github.com/hashicorp/packer/helper/communicator"
"github.com/hashicorp/packer/helper/multistep"
)

View File

@ -4,8 +4,9 @@ package common
// Imports for determining terminal information across platforms
import (
"golang.org/x/sys/unix"
"os"
"golang.org/x/sys/unix"
)
// posix api

View File

@ -1,8 +1,9 @@
package fix
import (
"github.com/mitchellh/mapstructure"
"strings"
"github.com/mitchellh/mapstructure"
)
type FixerAmazonTemporarySecurityCIDRs struct{}

6
go.mod
View File

@ -72,7 +72,8 @@ require (
github.com/hashicorp/go-cty-funcs/encoding v0.0.0-20200203151509-c92509f48b18
github.com/hashicorp/go-cty-funcs/filesystem v0.0.0-20200203151509-c92509f48b18
github.com/hashicorp/go-cty-funcs/uuid v0.0.0-20200203151509-c92509f48b18
github.com/hashicorp/go-getter v1.3.1-0.20190906090232-a0f878cb75da
github.com/hashicorp/go-getter v1.3.1-0.20190906090232-a0f878cb75da // indirect
github.com/hashicorp/go-getter/v2 v2.0.0-20200206160058-e2a28063d6e7
github.com/hashicorp/go-multierror v1.0.0
github.com/hashicorp/go-oracle-terraform v0.0.0-20181016190316-007121241b79
github.com/hashicorp/go-retryablehttp v0.5.2 // indirect
@ -111,6 +112,7 @@ require (
github.com/mitchellh/go-fs v0.0.0-20180402234041-7b48fa161ea7
github.com/mitchellh/go-homedir v1.1.0
github.com/mitchellh/go-vnc v0.0.0-20150629162542-723ed9867aed
github.com/mitchellh/gox v1.0.1 // indirect
github.com/mitchellh/iochan v1.0.0
github.com/mitchellh/mapstructure v0.0.0-20180111000720-b4575eea38cc
github.com/mitchellh/panicwrap v0.0.0-20170106182340-fce601fe5557
@ -163,7 +165,7 @@ require (
golang.org/x/sync v0.0.0-20190911185100-cd5d95a43a6e
golang.org/x/sys v0.0.0-20191128015809-6d18c012aee9
golang.org/x/time v0.0.0-20191024005414-555d28b269f0 // indirect
golang.org/x/tools v0.0.0-20191203051722-db047d72ee39
golang.org/x/tools v0.0.0-20200207183749-b753a1ba74fa
google.golang.org/api v0.14.0
google.golang.org/appengine v1.6.5 // indirect
google.golang.org/genproto v0.0.0-20191115221424-83cc0476cb11 // indirect

14
go.sum
View File

@ -239,6 +239,8 @@ github.com/hashicorp/go-cty-funcs/uuid v0.0.0-20200203151509-c92509f48b18 h1:CxY
github.com/hashicorp/go-cty-funcs/uuid v0.0.0-20200203151509-c92509f48b18/go.mod h1:QFbv9KeSic7KIgfOYbUW02G4LxOf3Fh9Ylm4n174LUQ=
github.com/hashicorp/go-getter v1.3.1-0.20190906090232-a0f878cb75da h1:HAasZmyRrb7/paYuww5RfVwY3wkFpsbMNYwBxOSZquY=
github.com/hashicorp/go-getter v1.3.1-0.20190906090232-a0f878cb75da/go.mod h1:7qxyCd8rBfcShwsvxgIguu4KbS3l8bUCwg2Umn7RjeY=
github.com/hashicorp/go-getter/v2 v2.0.0-20200206160058-e2a28063d6e7 h1:ODZKizgWGz4diUEZwCgf8qgIn/D+qVW/JOdVVV/z7k8=
github.com/hashicorp/go-getter/v2 v2.0.0-20200206160058-e2a28063d6e7/go.mod h1:jlmxRRjTpY0KdWrV1Uq38GUVskrjIZUrjOAybo0OArw=
github.com/hashicorp/go-immutable-radix v1.0.0 h1:AKDB1HM5PWEA7i4nhcpwOrO2byshxBjXVn/J/3+z5/0=
github.com/hashicorp/go-immutable-radix v1.0.0/go.mod h1:0y9vanUI8NX6FsYoO3zeMjhV/C5i9g4Q3DwcSNZ4P60=
github.com/hashicorp/go-msgpack v0.5.3 h1:zKjpN5BK/P5lMYrLmBHdBULWbJ0XpYR+7NGzqkZzoD4=
@ -261,6 +263,7 @@ github.com/hashicorp/go-uuid v1.0.1 h1:fv1ep09latC32wFoVwnqcnKJGnMSdBanPczbHAYm1
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.0.0/go.mod h1:fltr4n8CU8Ke44wwGCBoEymUuxUHl09ZGVZPK5anwXA=
github.com/hashicorp/go-version v1.1.0 h1:bPIoEKD27tNdebFGGxxYwcL4nepeY4j1QP23PFRGzg0=
github.com/hashicorp/go-version v1.1.0/go.mod h1:fltr4n8CU8Ke44wwGCBoEymUuxUHl09ZGVZPK5anwXA=
github.com/hashicorp/go-version v1.2.0 h1:3vNe/fWF5CBgRIguda1meWhsZHy3m8gCJ5wx+dIzX/E=
@ -368,6 +371,8 @@ github.com/mitchellh/go-vnc v0.0.0-20150629162542-723ed9867aed/go.mod h1:3rdaFaC
github.com/mitchellh/go-wordwrap v0.0.0-20150314170334-ad45545899c7 h1:DpOJ2HYzCv8LZP15IdmG+YdwD2luVPHITV96TkirNBM=
github.com/mitchellh/go-wordwrap v0.0.0-20150314170334-ad45545899c7/go.mod h1:ZXFpozHsX6DPmq2I0TCekCxypsnAUbP2oI0UX1GXzOo=
github.com/mitchellh/gox v0.4.0/go.mod h1:Sd9lOJ0+aimLBi73mGofS1ycjY8lL3uZM3JPS42BGNg=
github.com/mitchellh/gox v1.0.1 h1:x0jD3dcHk9a9xPSDN6YEL4xL6Qz0dvNYm8yZqui5chI=
github.com/mitchellh/gox v1.0.1/go.mod h1:ED6BioOGXMswlXa2zxfh/xdd5QhwYliBFn9V18Ap4z4=
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=
@ -500,6 +505,7 @@ golang.org/x/crypto v0.0.0-20190426145343-a29dc8fdc734/go.mod h1:yigFU9vqHzYiE8U
golang.org/x/crypto v0.0.0-20190510104115-cbcb75029529/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
golang.org/x/crypto v0.0.0-20190605123033-f99c8df09eb5 h1:58fnuSXlxZmFdJyvtTFVmVhcMLU6v5fEb/ok4wyqtNU=
golang.org/x/crypto v0.0.0-20190605123033-f99c8df09eb5/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
golang.org/x/crypto v0.0.0-20200117160349-530e935923ad h1:Jh8cai0fqIK+f6nG0UgPW5wFk8wmiMhM3AyciDBdtQg=
golang.org/x/crypto v0.0.0-20200117160349-530e935923ad/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA=
@ -527,6 +533,8 @@ golang.org/x/mobile v0.0.0-20191130191448-5c0e7e404af8 h1:9w7mvrikkrG9zFfEJfuFe0
golang.org/x/mobile v0.0.0-20191130191448-5c0e7e404af8/go.mod h1:p895TfNkDgPEmEQrNiOtIl3j98d/tGU95djDj7NfyjQ=
golang.org/x/mod v0.0.0-20190513183733-4bf6d317e70e/go.mod h1:mXi4GBBbnImb6dmsKGUJ2LatrhH/nqhxcFungHvyanc=
golang.org/x/mod v0.1.0/go.mod h1:0QHyrYULN0/3qlju5TqG8bIK38QM8yzMo5ekMj3DlcY=
golang.org/x/mod v0.1.1-0.20191105210325-c90efee705ee h1:WG0RUwxtNT4qqaXX3DPA8zHFNm/D9xaBpxzHt1WcA/E=
golang.org/x/mod v0.1.1-0.20191105210325-c90efee705ee/go.mod h1:QqPTAvyqsEbceGzBzNggFXnrqF1CaUcvgkdR5Ot7KZg=
golang.org/x/net v0.0.0-20180218175443-cbe0f9307d01/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
golang.org/x/net v0.0.0-20180826012351-8a410e7b638d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
@ -620,9 +628,11 @@ golang.org/x/tools v0.0.0-20191012152004-8de300cfc20a/go.mod h1:b+2E5dAYhXwXZwtn
golang.org/x/tools v0.0.0-20191113191852-77e3bb0ad9e7/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
golang.org/x/tools v0.0.0-20191115202509-3a792d9c32b2/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
golang.org/x/tools v0.0.0-20191125144606-a911d9008d1f/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
golang.org/x/tools v0.0.0-20191203051722-db047d72ee39 h1:zARK4PTmTfx1BC6iKP21qIRjz0nFzFj4ZAlbUy6Q6pM=
golang.org/x/tools v0.0.0-20191203051722-db047d72ee39/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
golang.org/x/tools v0.0.0-20200207183749-b753a1ba74fa h1:5E4dL8+NgFOgjwbTKz+OOEGGhP+ectTmF842l6KjupQ=
golang.org/x/tools v0.0.0-20200207183749-b753a1ba74fa/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28=
golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898 h1:/atklqdjdhuosWIl6AIbOeHJjicWYPqR9bpxqxYG2pA=
golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
google.golang.org/api v0.4.0 h1:KKgc1aqhV8wDPbDzlDtpvyjZFY3vjz85FP7p4wcQUyI=
google.golang.org/api v0.4.0/go.mod h1:8k5glujaEP+g9n7WNsDg8QP6cUVNI86fCNMcbazEtwE=
google.golang.org/api v0.7.0/go.mod h1:WtwebWUNSVBH/HAw79HIFXZNqEvBhG+Ra+ax0hx3E3M=

View File

@ -49,7 +49,7 @@ func (p *Parser) decodePostProcessor(block *hcl.Block) (*PostProcessorBlock, hcl
return postProcessor, diags
}
func (p *Parser) startPostProcessor(pp *PostProcessorBlock, ectx *hcl.EvalContext) (packer.PostProcessor, hcl.Diagnostics) {
func (p *Parser) startPostProcessor(pp *PostProcessorBlock, ectx *hcl.EvalContext, generatedVars map[string]string) (packer.PostProcessor, hcl.Diagnostics) {
// ProvisionerBlock represents a detected but unparsed provisioner
var diags hcl.Diagnostics
@ -64,7 +64,7 @@ func (p *Parser) startPostProcessor(pp *PostProcessorBlock, ectx *hcl.EvalContex
}
flatProvisinerCfg, moreDiags := decodeHCL2Spec(pp.Rest, ectx, postProcessor)
diags = append(diags, moreDiags...)
err = postProcessor.Configure(flatProvisinerCfg)
err = postProcessor.Configure(flatProvisinerCfg, generatedVars)
if err != nil {
diags = append(diags, &hcl.Diagnostic{
Severity: hcl.DiagError,

View File

@ -5,7 +5,6 @@ import (
"github.com/hashicorp/hcl/v2"
"github.com/hashicorp/hcl/v2/gohcl"
"github.com/hashicorp/packer/helper/common"
"github.com/hashicorp/packer/packer"
)
@ -47,7 +46,7 @@ func (p *Parser) decodeProvisioner(block *hcl.Block) (*ProvisionerBlock, hcl.Dia
return provisioner, diags
}
func (p *Parser) startProvisioner(pb *ProvisionerBlock, ectx *hcl.EvalContext, generatedVars []string) (packer.Provisioner, hcl.Diagnostics) {
func (p *Parser) startProvisioner(pb *ProvisionerBlock, ectx *hcl.EvalContext, generatedVars map[string]string) (packer.Provisioner, hcl.Diagnostics) {
var diags hcl.Diagnostics
provisioner, err := p.ProvisionersSchemas.Start(pb.PType)
@ -67,22 +66,10 @@ func (p *Parser) startProvisioner(pb *ProvisionerBlock, ectx *hcl.EvalContext, g
// manipulate generatedVars from builder to add to the interfaces being
// passed to the provisioner Prepare()
// 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.
generatedPlaceholderMap := packer.BasicPlaceholderData()
if generatedVars != nil {
for _, k := range generatedVars {
generatedPlaceholderMap[k] = fmt.Sprintf("Generated_%s. "+
common.PlaceholderMsg, k)
}
}
// configs := make([]interface{}, 2)
// configs = append(, flatProvisionerCfg)
// configs = append(configs, generatedPlaceholderMap)
err = provisioner.Prepare(flatProvisionerCfg, generatedPlaceholderMap)
// configs = append(configs, generatedVars)
err = provisioner.Prepare(flatProvisionerCfg, generatedVars)
if err != nil {
diags = append(diags, &hcl.Diagnostic{
Severity: hcl.DiagError,

View File

@ -1,7 +1,9 @@
package hcl2template
import (
"fmt"
"github.com/hashicorp/hcl/v2"
"github.com/hashicorp/packer/helper/common"
"github.com/hashicorp/packer/packer"
"github.com/zclconf/go-cty/cty"
)
@ -42,7 +44,7 @@ func (cfg *PackerConfig) EvalContext() *hcl.EvalContext {
// getCoreBuildProvisioners takes a list of provisioner block, starts according
// provisioners and sends parsed HCL2 over to it.
func (p *Parser) getCoreBuildProvisioners(blocks []*ProvisionerBlock, ectx *hcl.EvalContext, generatedVars []string) ([]packer.CoreBuildProvisioner, hcl.Diagnostics) {
func (p *Parser) getCoreBuildProvisioners(blocks []*ProvisionerBlock, ectx *hcl.EvalContext, generatedVars map[string]string) ([]packer.CoreBuildProvisioner, hcl.Diagnostics) {
var diags hcl.Diagnostics
res := []packer.CoreBuildProvisioner{}
for _, pb := range blocks {
@ -62,11 +64,11 @@ func (p *Parser) getCoreBuildProvisioners(blocks []*ProvisionerBlock, ectx *hcl.
// getCoreBuildProvisioners takes a list of post processor block, starts
// according provisioners and sends parsed HCL2 over to it.
func (p *Parser) getCoreBuildPostProcessors(blocks []*PostProcessorBlock, ectx *hcl.EvalContext) ([]packer.CoreBuildPostProcessor, hcl.Diagnostics) {
func (p *Parser) getCoreBuildPostProcessors(blocks []*PostProcessorBlock, ectx *hcl.EvalContext, generatedVars map[string]string) ([]packer.CoreBuildPostProcessor, hcl.Diagnostics) {
var diags hcl.Diagnostics
res := []packer.CoreBuildPostProcessor{}
for _, ppb := range blocks {
postProcessor, moreDiags := p.startPostProcessor(ppb, ectx)
postProcessor, moreDiags := p.startPostProcessor(ppb, ectx, generatedVars)
diags = append(diags, moreDiags...)
if moreDiags.HasErrors() {
continue
@ -104,12 +106,26 @@ func (p *Parser) getBuilds(cfg *PackerConfig) ([]packer.Build, hcl.Diagnostics)
if moreDiags.HasErrors() {
continue
}
provisioners, moreDiags := p.getCoreBuildProvisioners(build.ProvisionerBlocks, cfg.EvalContext(), generatedVars)
// 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.
generatedPlaceholderMap := packer.BasicPlaceholderData()
if generatedVars != nil {
for _, k := range generatedVars {
generatedPlaceholderMap[k] = fmt.Sprintf("Build_%s. "+
common.PlaceholderMsg, k)
}
}
provisioners, moreDiags := p.getCoreBuildProvisioners(build.ProvisionerBlocks, cfg.EvalContext(), generatedPlaceholderMap)
diags = append(diags, moreDiags...)
if moreDiags.HasErrors() {
continue
}
postProcessors, moreDiags := p.getCoreBuildPostProcessors(build.PostProcessors, cfg.EvalContext())
postProcessors, moreDiags := p.getCoreBuildPostProcessors(build.PostProcessors, cfg.EvalContext(), generatedPlaceholderMap)
pps := [][]packer.CoreBuildPostProcessor{}
if len(postProcessors) > 0 {
pps = [][]packer.CoreBuildPostProcessor{postProcessors}
@ -124,6 +140,7 @@ func (p *Parser) getBuilds(cfg *PackerConfig) ([]packer.Build, hcl.Diagnostics)
Builder: builder,
Provisioners: provisioners,
PostProcessors: pps,
Prepared: true,
}
res = append(res, pcb)
}

View File

@ -57,8 +57,9 @@ func TestParser_complete(t *testing.T) {
false, false,
[]packer.Build{
&packer.CoreBuild{
Type: "virtualbox-iso",
Builder: basicMockBuilder,
Type: "virtualbox-iso",
Prepared: true,
Builder: basicMockBuilder,
Provisioners: []packer.CoreBuildProvisioner{
{
PType: "shell",

View File

@ -1,8 +1,9 @@
package ssh
import (
"github.com/hashicorp/packer/communicator/ssh"
"testing"
"github.com/hashicorp/packer/communicator/ssh"
)
const (

View File

@ -97,6 +97,9 @@ type CoreBuild struct {
TemplatePath string
Variables map[string]string
// Indicates whether the build is already initialized before calling Prepare(..)
Prepared bool
debug bool
force bool
onError string
@ -132,6 +135,13 @@ func (b *CoreBuild) Name() string {
// 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()

View File

@ -88,6 +88,17 @@ func TestBuild_Prepare(t *testing.T) {
}
}
func TestBuild_Prepare_SkipWhenBuilderAlreadyInitialized(t *testing.T) {
build := testBuild()
builder := build.Builder.(*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()

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