Compare commits
34 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 30aa6a0cb4 | |||
| a689fc79ef | |||
| c9b011145d | |||
| ac239d1188 | |||
| 9c171c1f13 | |||
| 909b9fcfc7 | |||
| cebdabe0f7 | |||
| c229607ee3 | |||
| f65198726d | |||
| 7f0de5fc8d | |||
| 9ec8b67392 | |||
| 2981fd627d | |||
| 7254b04129 | |||
| 1719633058 | |||
| 2bdca997ac | |||
| 19e7114301 | |||
| 2d0c796837 | |||
| 483c8ec7d0 | |||
| ff1af40c66 | |||
| 391cea13ed | |||
| 4f7670a1e6 | |||
| 23fa3107a3 | |||
| c2ad9481f6 | |||
| 675fe95882 | |||
| 78012dc56f | |||
| dc81720dc9 | |||
| d654898ebf | |||
| a6d90babbf | |||
| 90eee3829d | |||
| 1cb6f4e456 | |||
| 76680ac1c6 | |||
| 6b82bf5a93 | |||
| 9756a9858a | |||
| 4fa0f6baa3 |
@@ -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
|
||||
|
||||
@@ -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
@@ -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
|
||||
+11
-10
@@ -4,20 +4,21 @@ env:
|
||||
os:
|
||||
- osx
|
||||
|
||||
sudo: false
|
||||
|
||||
language: go
|
||||
|
||||
go:
|
||||
- 1.13.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
|
||||
|
||||
|
||||
@@ -1,3 +1,20 @@
|
||||
## 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
|
||||
|
||||
@@ -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 ./...
|
||||
|
||||
|
||||
@@ -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"
|
||||
|
||||
@@ -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"
|
||||
|
||||
@@ -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"
|
||||
)
|
||||
|
||||
@@ -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"
|
||||
)
|
||||
|
||||
|
||||
@@ -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"
|
||||
|
||||
@@ -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"
|
||||
|
||||
@@ -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"
|
||||
|
||||
@@ -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"
|
||||
)
|
||||
|
||||
|
||||
@@ -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"
|
||||
|
||||
@@ -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) {
|
||||
|
||||
@@ -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"
|
||||
)
|
||||
|
||||
@@ -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"
|
||||
)
|
||||
|
||||
@@ -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
|
||||
}
|
||||
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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"
|
||||
)
|
||||
|
||||
@@ -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.
|
||||
|
||||
@@ -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 {
|
||||
|
||||
@@ -2,6 +2,7 @@ package qemu
|
||||
|
||||
import (
|
||||
"context"
|
||||
|
||||
"github.com/hashicorp/packer/common"
|
||||
"github.com/hashicorp/packer/helper/multistep"
|
||||
)
|
||||
|
||||
@@ -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) {
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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) {
|
||||
|
||||
@@ -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"
|
||||
|
||||
@@ -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) {
|
||||
|
||||
@@ -1,8 +1,9 @@
|
||||
package clone
|
||||
|
||||
import (
|
||||
"github.com/hashicorp/packer/packer"
|
||||
"testing"
|
||||
|
||||
"github.com/hashicorp/packer/packer"
|
||||
)
|
||||
|
||||
func TestCloneBuilder_ImplementsBuilder(t *testing.T) {
|
||||
|
||||
@@ -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"
|
||||
|
||||
@@ -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"
|
||||
|
||||
@@ -6,6 +6,7 @@ package common
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
|
||||
"github.com/hashicorp/packer/builder/vsphere/driver"
|
||||
"github.com/hashicorp/packer/helper/multistep"
|
||||
)
|
||||
|
||||
@@ -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"
|
||||
|
||||
@@ -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 {
|
||||
|
||||
@@ -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 {
|
||||
|
||||
@@ -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"
|
||||
|
||||
@@ -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"
|
||||
|
||||
@@ -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 {
|
||||
|
||||
@@ -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 {
|
||||
|
||||
@@ -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"
|
||||
|
||||
@@ -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 {
|
||||
|
||||
@@ -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"
|
||||
|
||||
@@ -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"
|
||||
|
||||
@@ -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 {
|
||||
|
||||
@@ -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 {
|
||||
|
||||
@@ -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 {
|
||||
|
||||
@@ -2,6 +2,7 @@ package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
|
||||
"github.com/hashicorp/packer/builder/vsphere/driver"
|
||||
)
|
||||
|
||||
|
||||
@@ -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,
|
||||
},
|
||||
|
||||
@@ -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) {
|
||||
|
||||
@@ -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"`
|
||||
|
||||
@@ -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},
|
||||
|
||||
@@ -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"
|
||||
|
||||
@@ -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"
|
||||
|
||||
@@ -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 {
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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
|
||||
}
|
||||
|
||||
@@ -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 {
|
||||
|
||||
@@ -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
|
||||
}
|
||||
|
||||
|
||||
@@ -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
|
||||
}
|
||||
@@ -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"
|
||||
|
||||
@@ -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",
|
||||
}
|
||||
|
||||
@@ -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"
|
||||
|
||||
+31
-1
@@ -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) {
|
||||
|
||||
@@ -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"
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
@@ -5,7 +5,6 @@ package shell_local
|
||||
import (
|
||||
"errors"
|
||||
"fmt"
|
||||
// "log"
|
||||
"os"
|
||||
"path/filepath"
|
||||
"runtime"
|
||||
|
||||
@@ -1,8 +1,9 @@
|
||||
package fix
|
||||
|
||||
import (
|
||||
"github.com/mitchellh/mapstructure"
|
||||
"strings"
|
||||
|
||||
"github.com/mitchellh/mapstructure"
|
||||
)
|
||||
|
||||
type FixerAmazonTemporarySecurityCIDRs struct{}
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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)
|
||||
}
|
||||
|
||||
@@ -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",
|
||||
|
||||
@@ -1,8 +1,9 @@
|
||||
package ssh
|
||||
|
||||
import (
|
||||
"github.com/hashicorp/packer/communicator/ssh"
|
||||
"testing"
|
||||
|
||||
"github.com/hashicorp/packer/communicator/ssh"
|
||||
)
|
||||
|
||||
const (
|
||||
|
||||
@@ -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()
|
||||
|
||||
|
||||
@@ -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()
|
||||
|
||||
@@ -80,6 +80,13 @@ func BasicPlaceholderData() map[string]string {
|
||||
}
|
||||
|
||||
func CastDataToMap(data interface{}) map[string]interface{} {
|
||||
|
||||
if interMap, ok := data.(map[string]interface{}); ok {
|
||||
// null and file builder sometimes don't use a communicator and
|
||||
// therefore don't go through RPC
|
||||
return interMap
|
||||
}
|
||||
|
||||
// Provisioners expect a map[string]interface{} in their data field, but
|
||||
// it gets converted into a map[interface]interface on the way over the
|
||||
// RPC. Check that data can be cast into such a form, and cast it.
|
||||
|
||||
@@ -17,7 +17,7 @@ package main
|
||||
import (
|
||||
"github.com/hashicorp/packer/builder/amazon/chroot"
|
||||
"github.com/hashicorp/packer/packer/plugin"
|
||||
"github.com/hashicorp/packer/post-processor/docker-push"
|
||||
dockerpush "github.com/hashicorp/packer/post-processor/docker-push"
|
||||
"github.com/hashicorp/packer/provisioner/powershell"
|
||||
)
|
||||
|
||||
|
||||
@@ -5,7 +5,6 @@ import (
|
||||
"compress/flate"
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"github.com/hashicorp/packer/packer/tmp"
|
||||
"io"
|
||||
"log"
|
||||
"os"
|
||||
@@ -13,6 +12,7 @@ import (
|
||||
"runtime"
|
||||
|
||||
"github.com/hashicorp/packer/packer"
|
||||
"github.com/hashicorp/packer/packer/tmp"
|
||||
"github.com/klauspost/pgzip"
|
||||
)
|
||||
|
||||
|
||||
@@ -156,6 +156,9 @@ signed_checksum=$(
|
||||
| grep -i "x-checksum-sha256" | awk 'gsub("[\r\n]", "", $2) {print $2;}'
|
||||
)
|
||||
|
||||
echo "${signed_checksum} signed_${SN_ID}.zip" | SHASUM_PROG -c
|
||||
echo "${signed_checksum} signed_${SN_ID}.zip" | $SHASUM_PROG -c
|
||||
if [ $? -ne 0 ]; then
|
||||
exit 1
|
||||
fi
|
||||
|
||||
mv "signed_${SN_ID}.zip" "$TARGET_ZIP"
|
||||
|
||||
@@ -40,6 +40,9 @@ for PLATFORM in $(find ./pkg -mindepth 1 -maxdepth 1 -type d); do
|
||||
done
|
||||
|
||||
./scripts/sign.sh
|
||||
if [ $? -ne 0 ]; then
|
||||
exit 1
|
||||
fi
|
||||
|
||||
if [ -z $NOSIGN ]; then
|
||||
echo "==> Signing..."
|
||||
|
||||
@@ -5,14 +5,15 @@ DO_PR_CHECK=1
|
||||
|
||||
set -o pipefail
|
||||
|
||||
is_doc_pr(){
|
||||
is_doc_or_tech_debt_pr(){
|
||||
if ! (($+commands[jq])); then
|
||||
DO_PR_CHECK=0
|
||||
echo "jq not found"
|
||||
return 1
|
||||
fi
|
||||
PR_NUM=$1
|
||||
out=$(curl -fsS "https://api.github.com/repos/hashicorp/packer/issues/${PR_NUM}" | jq '[.labels[].name == "docs"] | any')
|
||||
out=$(curl -fsS "https://api.github.com/repos/hashicorp/packer/issues/${PR_NUM}" \
|
||||
| jq '[.labels[].name == "docs" or .labels[].name == "tech-debt"] | any')
|
||||
exy="$?"
|
||||
if [ $exy -ne 0 ]; then
|
||||
echo "bad response from github"
|
||||
@@ -28,9 +29,9 @@ if [ -z $LAST_RELEASE ]; then
|
||||
fi
|
||||
|
||||
get_prs(){
|
||||
# git log --merges v0.10.2...c3861d167533fb797b0fae0c380806625712e5f7 |
|
||||
git log --merges HEAD...${LAST_RELEASE} |
|
||||
grep -o "Merge pull request #\([0-9]\+\)" | awk -F\# '{print $2}' | while read line
|
||||
# git log v0.10.2...c3861d167533fb797b0fae0c380806625712e5f7 |
|
||||
git log HEAD...${LAST_RELEASE} |
|
||||
grep -o "#\([0-9]\+\)" | awk -F\# '{print $2}' | while read line
|
||||
do
|
||||
grep -q "GH-${line}" CHANGELOG.md
|
||||
if [ $? -ne 0 ]; then
|
||||
@@ -38,16 +39,16 @@ get_prs(){
|
||||
fi
|
||||
done | while read PR_NUM
|
||||
do
|
||||
if (($DO_PR_CHECK)) && is_doc_pr $PR_NUM; then
|
||||
if (($DO_PR_CHECK)) && is_doc_or_tech_debt_pr $PR_NUM; then
|
||||
continue
|
||||
fi
|
||||
echo "https://github.com/hashicorp/packer/pull/${PR_NUM}"
|
||||
done
|
||||
}
|
||||
|
||||
#is_doc_pr 52061111
|
||||
# is_doc_pr 5206 # non-doc pr
|
||||
#is_doc_pr 5434 # doc pr
|
||||
#is_doc_or_tech_debt_pr 52061111
|
||||
# is_doc_or_tech_debt_pr 5206 # non-doc pr
|
||||
#is_doc_or_tech_debt_pr 5434 # doc pr
|
||||
#echo $?
|
||||
#exit
|
||||
|
||||
|
||||
+11
-1
@@ -8,6 +8,13 @@
|
||||
# export PRODUCT_NAME="packer"
|
||||
# export ARTIFACTORY_TOKEN=$ARTIFACTORY_TOKEN
|
||||
|
||||
ARTIFACTORY_TOKEN="${ARTIFACTORY_TOKEN:-""}"
|
||||
|
||||
if [ -z "$ARTIFACTORY_TOKEN" ]; then
|
||||
echo "Missing required Artifactory credentials"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# Get the parent directory of where this script is.
|
||||
SOURCE="${BASH_SOURCE[0]}"
|
||||
while [ -h "$SOURCE" ] ; do SOURCE="$(readlink "$SOURCE")"; done
|
||||
@@ -26,6 +33,9 @@ for DARWIN_BIN in $(find ./pkg/dist/*darwin_*.zip); do
|
||||
|
||||
echo $TARGET_ZIP
|
||||
./scripts/codesign_example.sh
|
||||
if [ $? -ne 0 ]; then
|
||||
exit 1
|
||||
fi
|
||||
done
|
||||
|
||||
exit 0
|
||||
exit 0
|
||||
|
||||
@@ -2,10 +2,11 @@ package interpolate
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"github.com/google/uuid"
|
||||
"regexp"
|
||||
"strings"
|
||||
"text/template"
|
||||
|
||||
"github.com/google/uuid"
|
||||
)
|
||||
|
||||
// Context is the context that an interpolation is done in. This defines
|
||||
@@ -44,7 +45,12 @@ func NewContext() *Context {
|
||||
return &Context{}
|
||||
}
|
||||
|
||||
// Render is shorthand for constructing an I and calling Render.
|
||||
// RenderOnce is shorthand for constructing an I and calling Render one time.
|
||||
func RenderOnce(v string, ctx *Context) (string, error) {
|
||||
return (&I{Value: v}).Render(ctx)
|
||||
}
|
||||
|
||||
// Render is shorthand for constructing an I and calling Render until all variables are rendered.
|
||||
func Render(v string, ctx *Context) (rendered string, err error) {
|
||||
// Keep interpolating until all variables are done
|
||||
// Sometimes a variable can been inside another one
|
||||
|
||||
@@ -57,7 +57,7 @@ func RenderMap(v interface{}, ctx *Context, f *RenderFilter) (map[string]interfa
|
||||
// RenderInterface renders any value and returns the resulting value.
|
||||
func RenderInterface(v interface{}, ctx *Context) (interface{}, error) {
|
||||
f := func(v string) (string, error) {
|
||||
return Render(v, ctx)
|
||||
return RenderOnce(v, ctx)
|
||||
}
|
||||
|
||||
walker := &renderWalker{
|
||||
|
||||
+77
-9
@@ -327,17 +327,12 @@ func (r *rawTemplate) parsePostProcessor(
|
||||
|
||||
// Parse takes the given io.Reader and parses a Template object out of it.
|
||||
func Parse(r io.Reader) (*Template, error) {
|
||||
// Create a buffer to copy what we read
|
||||
var buf bytes.Buffer
|
||||
if _, err := buf.ReadFrom(r); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
// First, decode the object into an interface{}. We do this instead of
|
||||
// the rawTemplate directly because we'd rather use mapstructure to
|
||||
// First, decode the object into an interface{} and search for duplicate fields.
|
||||
// We do this instead of the rawTemplate directly because we'd rather use mapstructure to
|
||||
// decode since it has richer errors.
|
||||
var raw interface{}
|
||||
if err := json.Unmarshal(buf.Bytes(), &raw); err != nil {
|
||||
buf, err := jsonUnmarshal(r, &raw)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
@@ -394,6 +389,79 @@ func Parse(r io.Reader) (*Template, error) {
|
||||
return rawTpl.Template()
|
||||
}
|
||||
|
||||
func jsonUnmarshal(r io.Reader, raw *interface{}) (bytes.Buffer, error) {
|
||||
// Create a buffer to copy what we read
|
||||
var buf bytes.Buffer
|
||||
if _, err := buf.ReadFrom(r); err != nil {
|
||||
return buf, err
|
||||
}
|
||||
|
||||
// Decode the object into an interface{}
|
||||
if err := json.Unmarshal(buf.Bytes(), raw); err != nil {
|
||||
return buf, err
|
||||
}
|
||||
|
||||
// If Json is valid, check for duplicate fields to avoid silent unwanted override
|
||||
jsonDecoder := json.NewDecoder(strings.NewReader(buf.String()))
|
||||
if err := checkForDuplicateFields(jsonDecoder); err != nil {
|
||||
return buf, err
|
||||
}
|
||||
|
||||
return buf, nil
|
||||
}
|
||||
|
||||
func checkForDuplicateFields(d *json.Decoder) error {
|
||||
// Get next token from JSON
|
||||
t, err := d.Token()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
delim, ok := t.(json.Delim)
|
||||
// Do nothing if it's not a delimiter
|
||||
if !ok {
|
||||
return nil
|
||||
}
|
||||
|
||||
// Check for duplicates inside of a delimiter {} or []
|
||||
switch delim {
|
||||
case '{':
|
||||
keys := make(map[string]bool)
|
||||
for d.More() {
|
||||
// Get attribute key
|
||||
t, err := d.Token()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
key := t.(string)
|
||||
|
||||
// Check for duplicates
|
||||
if keys[key] {
|
||||
return fmt.Errorf("template has duplicate field: %s", key)
|
||||
}
|
||||
keys[key] = true
|
||||
|
||||
// Check value to find duplicates in nested blocks
|
||||
if err := checkForDuplicateFields(d); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
case '[':
|
||||
for d.More() {
|
||||
if err := checkForDuplicateFields(d); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// consume closing delimiter } or ]
|
||||
if _, err := d.Token(); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// ParseFile is the same as Parse but is a helper to automatically open
|
||||
// a file for parsing.
|
||||
func ParseFile(path string) (*Template, error) {
|
||||
|
||||
@@ -560,3 +560,22 @@ func TestParse_bad(t *testing.T) {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestParse_checkForDuplicateFields(t *testing.T) {
|
||||
cases := []struct {
|
||||
File string
|
||||
Expected string
|
||||
}{
|
||||
{"error-duplicate-variables.json", "template has duplicate field: variables"},
|
||||
{"error-duplicate-config.json", "template has duplicate field: foo"},
|
||||
}
|
||||
for _, tc := range cases {
|
||||
_, err := ParseFile(fixtureDir(tc.File))
|
||||
if err == nil {
|
||||
t.Fatalf("expected error")
|
||||
}
|
||||
if !strings.Contains(err.Error(), tc.Expected) {
|
||||
t.Fatalf("file: %s\nExpected: %s\n%s\n", tc.File, tc.Expected, err.Error())
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,11 @@
|
||||
{
|
||||
"variables": {
|
||||
"var": "value"
|
||||
},
|
||||
"builders": [
|
||||
{
|
||||
"foo": "something",
|
||||
"foo": "something"
|
||||
}
|
||||
]
|
||||
}
|
||||
@@ -0,0 +1,13 @@
|
||||
{
|
||||
"variables": {
|
||||
"var": "value"
|
||||
},
|
||||
"variables": {
|
||||
"var": "value"
|
||||
},
|
||||
"builders": [
|
||||
{
|
||||
"foo": "something"
|
||||
}
|
||||
]
|
||||
}
|
||||
+1
-1
@@ -9,7 +9,7 @@ import (
|
||||
var GitCommit string
|
||||
|
||||
// The main version number that is being run at the moment.
|
||||
const Version = "1.5.2"
|
||||
const Version = "1.5.4"
|
||||
|
||||
// A pre-release marker for the version. If this is "" (empty string)
|
||||
// then it means that it is a final release. Otherwise, this is a pre-release
|
||||
|
||||
+1
-1
@@ -2,7 +2,7 @@ set :base_url, "https://www.packer.io/"
|
||||
|
||||
activate :hashicorp do |h|
|
||||
h.name = "packer"
|
||||
h.version = "1.5.2"
|
||||
h.version = "1.5.4"
|
||||
h.github_slug = "hashicorp/packer"
|
||||
h.website_root = "website"
|
||||
end
|
||||
|
||||
@@ -321,7 +321,7 @@ Instead, you can just provide shell scripts, Chef recipes, Puppet manifests,
|
||||
etc. to provision your Docker container just like you would a regular
|
||||
virtualized or dedicated machine.
|
||||
|
||||
While Docker has many features, Packer views Docker simply as an container
|
||||
While Docker has many features, Packer views Docker simply as a container
|
||||
runner. To that end, Packer is able to repeatedly build these containers using
|
||||
portable provisioning scripts.
|
||||
|
||||
|
||||
@@ -67,6 +67,9 @@ necessary for this build to succeed and can be found further down the page.
|
||||
### Create Configuration
|
||||
<%= partial "partials/builder/vsphere/iso/CreateConfig-not-required" %>
|
||||
|
||||
### Network Adapter Configuration
|
||||
<%= partial "partials/builder/vsphere/iso/NIC-required" %>
|
||||
|
||||
### Floppy Configuration
|
||||
<%= partial "partials/builder/vsphere/iso/FloppyConfig-not-required" %>
|
||||
|
||||
@@ -79,6 +82,10 @@ necessary for this build to succeed and can be found further down the page.
|
||||
|
||||
<%= partial "partials/helper/communicator/Config-not-required" %>
|
||||
|
||||
#### Optional Network Adapter fields:
|
||||
|
||||
<%= partial "partials/builder/vsphere/iso/NIC-not-required" %>
|
||||
|
||||
#### Optional SSH fields:
|
||||
|
||||
<%= partial "partials/helper/communicator/SSH-not-required" %>
|
||||
|
||||
@@ -41,8 +41,8 @@ two have empty blocks `{}`. The third sets a default. If a default value is
|
||||
set, the variable is optional. Otherwise, the variable is required.
|
||||
This also defines two locals: `debian_ami_name` and `foo`.
|
||||
|
||||
-> **Note**: that it is *not* possible to use variables in a variable defintion
|
||||
but it *is* possible to use locals and variables in a local definintion.
|
||||
-> **Note**: that it is *not* possible to use variables in a variable definition
|
||||
but it *is* possible to use locals and variables in a local definition.
|
||||
|
||||
## Using Variables and locals in Configuration
|
||||
|
||||
|
||||
@@ -21,6 +21,8 @@
|
||||
|
||||
- `network_card` (string) - Set VM network card type. Example `vmxnet3`.
|
||||
|
||||
- `network_adapters` ([]NIC) - Network adapters
|
||||
|
||||
- `usb_controller` (bool) - Create USB controller for virtual machine. Defaults to `false`.
|
||||
|
||||
- `notes` (string) - VM notes.
|
||||
|
||||
@@ -0,0 +1,8 @@
|
||||
<!-- Code generated from the comments of the NIC struct in builder/vsphere/iso/step_create.go; DO NOT EDIT MANUALLY -->
|
||||
|
||||
- `network` (string) - Set network VM will be connected to.
|
||||
|
||||
- `mac_address` (string) - Set network card MAC address
|
||||
|
||||
- `passthrough` (\*bool) - Enable DirectPath I/O passthrough
|
||||
|
||||
@@ -0,0 +1,4 @@
|
||||
<!-- Code generated from the comments of the NIC struct in builder/vsphere/iso/step_create.go; DO NOT EDIT MANUALLY -->
|
||||
|
||||
- `network_card` (string) - Set VM network card type. Example `vmxnet3`.
|
||||
|
||||
@@ -0,0 +1,4 @@
|
||||
<!-- Code generated from the comments of the RemoveCDRomConfig struct in builder/vsphere/iso/step_remove_cdrom.go; DO NOT EDIT MANUALLY -->
|
||||
|
||||
- `remove_cdrom` (bool) - Remove CD-ROM devices from template. Defaults to `false`.
|
||||
|
||||
Reference in New Issue
Block a user