Compare commits

..

150 Commits

Author SHA1 Message Date
Megan Marsh 0e564b4883 add source_ami_filter test to acceptance tests from packer-regressions 2020-03-11 16:21:16 -07:00
Wilken Rivera b9f1b3c8d4 Fix gosimple S1005 linting issue (#8870)
Results before change
```
⇶  golangci-lint run ./... --disable-all --enable=gosimple | grep 1005
fix/fixer_comm_config.go:48:4: S1005: should write `sshHostPortMinRaw := builders["ssh_host_port_min"]` instead of `sshHostPortMinRaw, _ := builders["ssh_host_port_min"]` (gosimple)
fix/fixer_comm_config.go:64:4: S1005: should write `sshHostPortMaxRaw := builders["ssh_host_port_max"]` instead of `sshHostPortMaxRaw, _ := builders["ssh_host_port_max"]` (gosimple)
fix/fixer_comm_config.go:81:4: S1005: should write `sshSkipNatMappingRaw := builders["ssh_skip_nat_mapping"]` instead of `sshSkipNatMappingRaw, _ := builders["ssh_skip_nat_mapping"]` (gosimple)
packer/artifact_mock.go:47:2: S1005: should write `value := a.StateValues[name]` instead of `value, _ := a.StateValues[name]` (gosimple)
packer/artifact_test.go:31:2: S1005: should write `value := a.state[name]` instead of `value, _ := a.state[name]` (gosimple)
```

Results after change
```
```
2020-03-11 10:30:08 +01:00
Wilken Rivera 66ad6f3483 builders: Fix gosimple S1007 linting issue (#8871)
Results before change
```
⇶  golangci-lint run ./... --disable-all --enable=gosimple | grep 1007
builder/alicloud/ecs/image_config.go:208:9: S1007: should use raw string
post-processor/vsphere-template/step_mark_as_template.go:130:8: S1007: shape twice (gosimple)
builder/azure/arm/config.go:58:27: S1007: should use raw string (`...`)
builder/azure/arm/config.go:59:27: S1007: should use raw string (`...`)
builder/qemu/driver.go:192:15: S1007: should use raw string (`...`)
```

Results after change
```
⇶  golangci-lint run ./... --disable-all --enable=gosimple | grep 1007
```
2020-03-11 10:29:22 +01:00
Megan Marsh 072a71b419 Merge pull request #8863 from hashicorp/update_go-cty_regex
import new replace and regex_replace funcs from go-cty + documentation
2020-03-10 13:09:09 -07:00
Megan Marsh e518a0a8b7 Merge branch 'master' into update_go-cty_regex 2020-03-10 10:52:42 -07:00
Megan Marsh 68e083603d Update website/source/docs/configuration/from-1.5/functions/string/replace.html.md
Co-Authored-By: Wilken Rivera <dev@wilkenrivera.com>
2020-03-10 10:51:25 -07:00
Megan Marsh 8a1caaa804 Merge pull request #8837 from hashicorp/fix_8730
Fix crash when an unset variable is used
2020-03-10 10:40:48 -07:00
Adrien Delorme 0c45bd8b4f import new replace and regex replace funcs from go-cty + documentation 2020-03-10 16:14:25 +01:00
Adrien Delorme d4d30127a3 Update variables.html.md 2020-03-10 14:53:48 +01:00
Adrien Delorme c4349f5a33 document variables behaviours with tables 2020-03-10 14:51:17 +01:00
Jaspal Chauhan b204687de9 Add VBoxManage config section to VirtualBox OVF builder docs (#8861) 2020-03-10 11:11:27 +01:00
Adrien Delorme 631f402d1e Merge branch 'master' into fix_8730 2020-03-09 17:49:33 +01:00
Megan Marsh 7873cabf63 Merge pull request #8858 from hashicorp/fix_8791
update spot price docs
2020-03-09 09:31:56 -07:00
Adrien Delorme 0ccff0d5b9 all variables must have a value.
A variable's default value can be set to null to force user to set it.
2020-03-09 17:25:56 +01:00
Sylvia Moss 76f13deaf4 Make template variables SSHPublicKey and SSHPrivateKey as strings (#8829) 2020-03-09 17:25:05 +01:00
Megan Marsh 4133acbdf3 update spot price docs 2020-03-09 08:46:30 -07:00
Sylvia Moss 4bdf30165a Fix example json format in ansible provisioner doc (#8856) 2020-03-09 16:40:56 +01:00
Adrien Delorme 6d8cce501e tweak validation & add tests 2020-03-09 16:16:59 +01:00
Lars Lehtonen 74a94d8547 helper/builder/testing: prune unused functions (#8852) 2020-03-09 10:46:32 +01:00
Adrien Delorme 9e6c94e141 circleci: VersionPrerelease: show tag or branch name and hash when building binary (#8850)
VersionPrerelease=${CIRCLE_TAG:=${CIRCLE_BRANCH}}-${CIRCLE_SHA1:0:9}"
2020-03-06 14:03:18 -05:00
jnsc 764b4cb50a updated link to GuestOsIdentifier (#8849)
Co-authored-by: Adrien Delorme <adrien.delorme@icloud.com>
2020-03-06 15:30:11 +01:00
Wilken Rivera 9403b48a52 hcl2template/types.variables: Update logic for parsing literal value variables (#8834)
* hcl2template/types.variables: Update logic for parsing literal value variables

In running tests via the CLI it was determined that when using the variable block with no explicit type assigned the type of the default
value was not being set within the map. This change updates the `decodeConfig` method so that a type is always set for any defined variable if not specified.

The second change is to properly handle the evaluation of basic variable types (e.g String, Number, Bool). Previously variables defined on the
CLI or via PKR_VAR required some additional quoting to for proper evaluation. This change fixes that issue so that it works like it does in Terraform :)

Build results before the change
```
⇶  PKR_VAR_example='["one","two"]' ~/bin/packer build -var 'foo=home' .
Error: Variables not allowed

  on <value for var.foo from arguments> line 1:
  (source code not available)

Variables may not be used here.

==> Builds finished but no artifacts were created.

```

Build results after the change
```
⇶  PKR_VAR_example='["one","two"]' ~/bin/packer build -var 'foo="home"' .
null: output will be in this color.

==> null: Running local shell script: /tmp/packer-shell885249462
    null: two
    null: home
Build 'null' finished.

==> Builds finished. The artifacts of successful builds are:
--> null: Did not export anything. This is the null builder

⇶  ~/bin/packer build -var 'foo=home' -var 'example=["one","another variable"]' .
null: output will be in this color.

==> null: Running local shell script: /tmp/packer-shell123467506
    null: another variable
    null: home
Build 'null' finished.

==> Builds finished. The artifacts of successful builds are:
--> null: Did not export anything. This is the null builder

```

* tests/hcl2template/types.variables: Update test to use Bool

Turns out a string value won't actually complain if it's given a non
string looking value. It will just covert the value to a string literal
so using a type Bool which should fail if given anything that is not
true or false.

* tests/hcl2template/types.variables: Update unit tests

During testing it was found that by default the variable stanza were defaulting to a cty.NilType, and not the Type of it's default value.
This change sets the default type of the defined variable to ensure variable evaluation behaviors correctly.

* Add a simple cty.Bool test case

* tests/hcl2template/types.variables:  Enable quoted_string test case

* Update hcl2template/types.variables.go

space

Co-authored-by: Adrien Delorme <azr@users.noreply.github.com>
2020-03-06 15:12:26 +01:00
Wilken Rivera 698924f246 vSphere ISO supports more common options (#8845)
The `convert_to_template` and `create_snapshot` are supported across
both builders, but currently only shown in the vSphere Clone docs, this adds
them to it.
2020-03-05 15:04:15 -05:00
Megan Marsh 7e382d0df7 Merge pull request #8828 from mvitaly/fix_8816
Remove all floppy controllers before adding a new one
2020-03-05 09:35:20 -08:00
Megan Marsh 8832b3e2ca Merge pull request #8787 from jhawk28/vsphere_iso_multiple_disks
(vsphere-iso) add ability to define multiple disks
2020-03-04 15:17:54 -08:00
Wilken Rivera e1a46ec293 Fix gosimple S1025 linting errors (#8838)
Remove unneeded use of fmt.Sprintf for variables that are already strings.
2020-03-04 15:31:30 -05:00
Sylvia Moss 717b9047db Fix boot command link in ssh communicator doc (#8839) 2020-03-04 16:28:39 +01:00
Joshua Foster 1dbe5abc14 update documentation based on feedback 2020-03-04 09:48:01 -05:00
Joshua Foster d7230827cd (vsphere-iso) add ability to define multiple disks
Closes #8749
2020-03-04 09:48:01 -05:00
Adrien Delorme e195c627fb vendor vendors 2020-03-04 13:50:15 +01:00
Adrien Delorme f013164298 bup modules 2020-03-04 13:49:38 +01:00
Adrien Delorme e9d3826219 variables: use Range instead of Block
because a variable can be defined in the Locals block
2020-03-04 13:19:07 +01:00
Adrien Delorme 9b649594c6 update tests 2020-03-04 13:01:18 +01:00
Adrien Delorme 8482c6c2e6 evaluateLocalVariable: also pass the variable name 2020-03-04 13:01:04 +01:00
Adrien Delorme bd3112fa7c parseLocalVariables: simplify loop 2020-03-04 13:00:51 +01:00
Adrien Delorme 23b940dbd5 fix this ! 2020-03-04 12:42:56 +01:00
Adrien Delorme e851050774 don't force to set unused variables too 2020-03-04 12:32:29 +01:00
Adrien Delorme 382f209b07 Update types.packer_config.go 2020-03-04 12:30:05 +01:00
Adrien Delorme 59cc246942 Merge remote-tracking branch 'origin/master' into fix_8730 2020-03-04 12:30:01 +01:00
Vitaly Polonetsky 25f59a1592 Add a simple test for the call to remove all floppy controllers 2020-03-03 20:58:09 -08:00
Noel Quiles 4ed896fc99 Update middleman-hashicorp to 0.3.44 (#8836) 2020-03-03 22:59:24 -05:00
Megan Marsh 5281740275 Merge pull request #8831 from rjhornsby/master
Clarify `expect_disconnect` behavior
2020-03-03 13:54:34 -08:00
rjhornsby b91c4d32cc Additional clarity
Co-Authored-By: Megan Marsh <megan@hashicorp.com>
2020-03-03 15:19:13 -06:00
Megan Marsh e35a872414 Merge pull request #8830 from hashicorp/d-var-file-hcl2-not-yet
document that the `-var-file` option still expects JSON files for now
2020-03-03 13:13:05 -08:00
Megan Marsh fc110e747f Merge pull request #8832 from alrs/post-processor-deprecated-session-new
post-processor/digitalocean-import/post-processor.go: Replace Deprecated session.New()
2020-03-03 13:11:54 -08:00
Lars Lehtonen db7a40d6ea post-processor/digitalocean-import/post-processor.go: replace deprecated session.New() with session.NewSession() 2020-03-03 11:53:40 -08:00
Rick Hornsby 0a2fb8c383 Clarify expect_disconnect behavior 2020-03-03 12:44:58 -06:00
Adrien Delorme d2964d59e9 document that the -var-file option still expects JSON files for now 2020-03-03 17:19:51 +01:00
Sylvia Moss ce674ff272 Add exclude mapstructure tag to exclude from hcl2spec struct (#8785) 2020-03-03 17:13:39 +01:00
Megan Marsh 6dbe86fcf4 only re-set path name if it needs to be unquoted; otherwise unquote r… (#8826) 2020-03-03 11:17:48 +01:00
Adrien Delorme 50896d4ddf WIP 2020-03-03 11:15:56 +01:00
Vitaly Polonetsky 67c9c2a59a Remove all floppy controllers before adding a new one 2020-03-02 21:56:20 -08:00
Megan Marsh 6540891ca2 Merge pull request #8825 from alrs/fix-powershell-err
common/powershell: Fix Dropped Error
2020-03-02 16:32:43 -08:00
Megan Marsh d422d81dec Merge pull request #8823 from hashicorp/d-provisioners-update-index
docs/provisioners/index: Add link to Template Provisioners section
2020-03-02 15:00:43 -08:00
Lars Lehtonen f808d1d968 common/powershell: fix dropped error 2020-03-02 14:45:22 -08:00
Wilken Rivera b8408c1c1a Merge pull request #8824 from hashicorp/d-hcl2-guides-issues-note
guides/hcl: Add link to HCL2 issues tracked on the Packer repo
2020-03-02 17:41:10 -05:00
Wilken Rivera 5dfeddc3a4 guides/hcl: Add link to HCL2 issues tracked on the Packer repo
This change adds a partial that contains a link to the HCL2 issues currently being tracked on GitHub. The partial has been added to the majority of the HCL2 guide documents as a way to help users learn about any open or recently resolved issues pertaining to the HCL2 support in Packer.
2020-03-02 17:13:35 -05:00
Megan Marsh 0f9c3e2cb4 Merge pull request #8784 from kirannhegde/bugfix-4295
Citrix XenServer packer plugin-#4295
2020-03-02 12:53:11 -08:00
Megan Marsh 9c9826ee4b Merge pull request #8714 from williamb1024/hyperv-gen1-boot-order
WIP: Add Hyper-V builder `first_boot_device` setting to allow the selection of the initial device or device class used for booting the VM.
2020-03-02 12:27:25 -08:00
Wilken Rivera 433c9e8276 docs/provisioners/index: Add link to Template Provisioners section 2020-03-02 15:05:00 -05:00
Megan Marsh 5eead20ae4 Merge pull request #8811 from benjamb/size-check
Fix Hyper-V compacted disk size comparison
2020-03-02 10:44:35 -08:00
Ben Brown 0936f8bc03 Fix Hyper-V compacted disk size comparison
Prior to this the code compares the length of the path, which of course
doesn't change.
2020-03-02 09:55:13 +00:00
Megan Marsh 0cfcbd66ca execute_command in powershell wasn't interpolating build vars properly (#8771) 2020-03-02 04:20:32 -05:00
Larry Eichenbaum b45ed4c4f1 Update build-image-in-cicd.html.md (#8813)
typo
2020-03-02 04:10:51 -05:00
Megan Marsh 60d952033e Merge pull request #8798 from EnMod/nq.add-x-frame-options-header
[Website] Set security-focused page headers
2020-02-28 11:42:24 -08:00
Megan Marsh 7d065d9030 Merge pull request #8793 from hashicorp/dependabot/bundler/website/nokogiri-1.10.8
Bump nokogiri from 1.10.4 to 1.10.8 in /website
2020-02-28 11:41:10 -08:00
Megan Marsh 66f01b6033 Merge pull request #8801 from andretorres-codurance/patch-1
Update ansible.html.md.erb
2020-02-28 11:20:13 -08:00
Megan Marsh 6d59cbd4b5 Merge pull request #8799 from carlpett/proxmox/validate-template-name
proxmox: template_name cannot contain spaces
2020-02-28 11:19:18 -08:00
Megan Marsh 36d574c9ec Merge pull request #8800 from carlpett/proxmox/bump-api-dep
Bump proxmox-api-go
2020-02-28 10:19:16 -08:00
Megan Marsh f25dc1cf74 Merge pull request #8815 from hashicorp/generate_boot_commanmd
regenerate boot command code
2020-02-28 10:15:26 -08:00
Megan Marsh 66a1cdb8d2 regenerate boot command code 2020-02-28 09:50:50 -08:00
andretorres-codurance 5d4e9af9cd Update ansible.html.md.erb 2020-02-26 10:38:40 +00:00
Calle Pettersson 81a65dac4f Bump proxmox-api-go 2020-02-26 08:47:44 +01:00
Calle Pettersson 17fa6a3e95 proxmox: template_name cannot contain spaces 2020-02-26 08:44:27 +01:00
Noel Quiles 806e799945 [Website] Set security-focused page headers
- Sets X-Frame-Options to SAMEORIGIN
- Sets Strict-Transport-Security to:
  max-age=31536000; includeSubDomains; preload
2020-02-25 19:11:47 -05:00
dependabot[bot] dbb884deb3 Bump nokogiri from 1.10.4 to 1.10.8 in /website
Bumps [nokogiri](https://github.com/sparklemotion/nokogiri) from 1.10.4 to 1.10.8.
- [Release notes](https://github.com/sparklemotion/nokogiri/releases)
- [Changelog](https://github.com/sparklemotion/nokogiri/blob/master/CHANGELOG.md)
- [Commits](https://github.com/sparklemotion/nokogiri/compare/v1.10.4...v1.10.8)

Signed-off-by: dependabot[bot] <support@github.com>
2020-02-25 08:03:20 +00:00
William Brooks 8e0ed66318 Fix raw string breaks escaping 2020-02-22 02:40:41 -06:00
William Brooks efa9d94d8e use raw string around regex to make go lint happy 2020-02-22 02:22:59 -06:00
William d246d0c82a More testing (#4)
Additional testing for SetFirstBootDevice and checking configuration in config.Prepare()
2020-02-22 02:03:42 -06:00
William b5b190b1f0 Bootdevice testing (#3)
Start step_first_boot_device_test and rejigger ParseBootDeviceIdentifier to avoid regex where reasonable.
2020-02-22 00:29:05 -06:00
William Brooks 7f38ce0686 test and correct gen2 SetFirstBootDeviceGen2 scripts 2020-02-21 11:09:49 -06:00
Kiran Hegde 31665dc8c3 Citrix XenServer packer plugin
Updating the GitHub reference to the packer plugins for the Citrix XenServer/Citrix Hypervisor to the official Github repository
2020-02-21 16:53:02 +05:30
Sylvia Moss 591b684f08 Fix HCL2 local variables decoding to allow local usage within another local in the same locals block (#8755) 2020-02-21 12:12:30 +01:00
William Brooks 723a9eba9a really, really, really fix driver_mock 2020-02-21 01:53:13 -06:00
William Brooks 11fae17308 again, really fix driver_mock 2020-02-21 01:44:49 -06:00
William Brooks 2de731453f really fix driver_mock this time 2020-02-21 01:43:03 -06:00
William Brooks 0a0fbfc33b fmt 2020-02-21 01:31:18 -06:00
William Brooks dd8f4370c6 initial support for gen2 and fix driver_mock 2020-02-21 01:30:59 -06:00
William Brooks 5e1e4ec701 fmt && generate 2020-02-21 01:07:58 -06:00
William Brooks d7300f4635 Remove legacy_boot and replace with first_boot_device (initial) 2020-02-21 01:01:09 -06:00
Megan Marsh dde74232f2 Clearly document all template-engine-enabled options (#8770) 2020-02-20 11:05:27 +01:00
Adrien Delorme a8fcb2d91a HCL2: add support for dynamic blocks, document for loops and splat expressions (#8720) 2020-02-20 10:51:34 +01:00
Megan Marsh 59fa6c036c update to v1.5.5-dev 2020-02-19 13:30:04 -08:00
Megan Marsh eb35617985 Merge pull request #8756 from aeber/feature_eagerly_scrub_disks
vsphere-iso: add support for eagerly zeroed / scrubbed disks
2020-02-19 09:47:49 -08:00
Megan Marsh 1a72eeb772 update changelog 2020-02-18 16:40:29 -08:00
Megan Marsh 5846c0cdd7 Merge pull request #8753 from jhawk28/bug_8743
fix #8743 by using interface instead of Network object
2020-02-18 10:12:34 -08:00
Joshua Foster 3f80414e6d fix #8743 by using interface instead of Network object 2020-02-18 10:05:18 -05:00
Adrien Delorme 52e5b7051e Update mock.go 2020-02-18 11:31:52 +01:00
Li Kexian f3231018ca showing tencentcloud image id after copy to desination region (#8763) 2020-02-18 11:17:19 +01:00
Jason A. Beranek 9cbb49bacb builder/vmware/iso: Expand guest_os_type docs (#8760) 2020-02-18 11:11:20 +01:00
Mark Lewis 70752e0488 Add prompt to use a specific directory for *.pkr.hcl (#8757)
This improves usability as many users will still expect
to use `packer build config.pkr.hcl` having run
`packer build config.json` in the past.
2020-02-18 10:55:30 +01:00
Adrien Delorme 3c213e6eaf continue and realise and unused undefaulted value triggers an error 2020-02-17 18:05:15 +01:00
Adrien Delorme cebfb1c735 give correct error when variable is unset 2020-02-17 17:15:52 +01:00
Anselm Eberhardt 94130b5def add autogenerated help for disk_eagerly_scrub 2020-02-17 17:01:00 +01:00
Adrien Delorme 79867ca26e add test for unset variable 2020-02-17 16:36:19 +01:00
Anselm Eberhardt 6c749eecf7 add support for eagerly zeroed / scrubbed disks 2020-02-17 16:26:07 +01:00
Adrien Delorme 00c812cfe8 insert "github.com/zclconf/go-cty/cty/json" encoding beforce hcl decoding things to make sure tests are working similarly as real life version 2020-02-17 15:53:05 +01:00
Adrien Delorme 1ec68cac23 refactor prepare into MockConfig 2020-02-17 15:47:31 +01:00
Wilken Rivera 5a87760702 makefile: Update code path for golangci-lint (#8751)
While `golangci-lint run` is the same as `golangci-lint run ./...` running it without a
path seems to throw warning messages related to its cache, which is confusing.
This change sets an explicit path for golangci-lint when calling `make lint` or `make ci-lint`.
2020-02-17 11:24:08 +01:00
William 807f39284d Merge pull request #2 from hashicorp/master
merge from hashicorp/packer
2020-02-15 23:13:38 -06:00
Megan Marsh 9a85fdd0a5 Cut version 1.5.4 2020-02-14 16:14:01 -08:00
Megan Marsh c9b011145d cut version 1.5.4 2020-02-14 14:55:03 -08:00
Megan Marsh ac239d1188 fix checking for codesign 2020-02-14 14:50:21 -08:00
Wilken Rivera 9c171c1f13 scripts: Update code signing scripts (#8746)
* scripts/codesign_example: Fix reference to SHASUM_PROG variable

* scripts/sign: Add check for required Artifactory token
2020-02-14 17:38:56 -05:00
Megan Marsh 909b9fcfc7 update to 1.5.4 dev on master branch 2020-02-14 11:16:07 -08:00
Megan Marsh cebdabe0f7 Cut version 1.5.3 2020-02-14 10:38:20 -08:00
Megan Marsh c229607ee3 update to v1.5.3 2020-02-14 10:30:18 -08:00
Megan Marsh f65198726d update changelog 2020-02-14 09:10:53 -08:00
jhawk28 7f0de5fc8d add ability to define multiple NICs for vsphere-iso (#8739) 2020-02-14 17:51:57 +01:00
Wilken Rivera 9ec8b67392 Add golangci-lint to project (#8686)
* Add golangci-lint as linting tool

* Disable failing staticchecks to start; GitHub issue to handle coming soon

* Run `goimports -w` to repair all source files that have improperly
formatted imports

* makefile: Add ci-lint target to run on travis

This change adds a new make target for running golangci-lint on newly
added Go files only. This target is expected to run during Packer ci builds.

* .github/contributing: Add code linting instructions

* travis: Update job configuration to run parallel builds
2020-02-14 11:42:29 -05:00
Sylvia Moss 2981fd627d Avoid calling CoreBuild.Prepare(...) for HCL2 templates (#8742) 2020-02-14 17:39:32 +01:00
Wilken Rivera 7254b04129 script/prepare_changelog: Update to show squashed merge commits (#8744)
* script/prepare_changelog: Update regex to include squashed PRs

* scripts/prepare_changelog: Update to show all commits not just merged commits
2020-02-14 11:33:33 -05:00
Wilken Rivera 1719633058 Merge pull request #8722 from hashicorp/td-prepare_changelog
scripts/prepare_changelog: Update jq filter to ignore tech-debt labelled pull-requests
2020-02-14 09:58:12 -05:00
Wilken Rivera 2bdca997ac Update function name 2020-02-14 09:44:45 -05:00
Wilken Rivera 19e7114301 scripts/prepare_changelog: Update jq filter to ignore tech-debt labelled pull-requests 2020-02-14 09:44:45 -05:00
Mark Lewis 2d0c796837 Fix typos in Input and Local Variables guide (#8741) 2020-02-14 15:30:25 +01:00
Adrien Delorme 4b10c5a87c try to reproduce #8730 in tests 2020-02-14 11:54:10 +01:00
Megan Marsh 483c8ec7d0 add go mod and go sum to gitattributes to fix line endings on windows (#8734) 2020-02-14 11:20:36 +01:00
jhawk28 ff1af40c66 struct-markdown should keep the same slash direction regardless of Windows or Linux (#8738) 2020-02-14 08:50:03 +01:00
Megan Marsh 391cea13ed Merge pull request #8725 from hashicorp/fix_8655
Check if JSON template doesn't have duplicate configuration
2020-02-13 12:04:26 -08:00
Megan Marsh 4f7670a1e6 Merge pull request #8690 from daxgames/vsphere_iso_remove_cdrom
vsphere iso remove cdroms
2020-02-13 11:00:47 -08:00
Sylvia Moss 23fa3107a3 Render variables one time on prepare method (#8727) 2020-02-13 17:35:23 +01:00
Aayush Sarva c2ad9481f6 Fix typo in Dockerfiles section (#8728)
`an container runner` => `a container runner`
2020-02-13 15:39:45 +01:00
Megan Marsh 675fe95882 move to 1.5.3-dev 2020-02-12 15:22:57 -08:00
Dax T. Games 78012dc56f add autogenerated help for vsphere iso remove cdrom 2020-02-12 11:31:46 -05:00
Moss dc81720dc9 Fix format 2020-02-12 14:44:28 +01:00
Moss d654898ebf Add tests for check of json duplicate fields 2020-02-12 14:34:20 +01:00
Moss a6d90babbf Add check for json duplicate fields 2020-02-12 11:56:18 +01:00
William Brooks 61f5f867eb make generate 2020-02-09 16:41:07 -06:00
William Brooks 9891e75f75 update hyper-v driver_mock.go 2020-02-09 15:39:35 -06:00
William Brooks 31622b50ac applied fmt 2020-02-09 15:22:36 -06:00
William Brooks 7152732597 changing SetBootDvdDrive messaging to be truthful 2020-02-09 14:26:46 -06:00
William Brooks 55ae803852 Add Hyper-V support for Gen-1 boot order with ISO 2020-02-09 13:08:22 -06:00
William e490b7651d Merge pull request #1 from hashicorp/master
Synchronize fork from upstream repository
2020-02-08 23:25:54 -06:00
Dax T. Games 90eee3829d add docs 2020-02-05 11:13:00 -05:00
Dax T. Games 1cb6f4e456 Merge branch 'vsphere_iso_remove_cdrom' of https://github.com/daxgames/packer into vsphere_iso_remove_cdrom
* 'vsphere_iso_remove_cdrom' of https://github.com/daxgames/packer:
  format
  Update builder.go
2020-02-05 11:11:43 -05:00
Dax T. Games 76680ac1c6 add docs 2020-02-05 11:10:50 -05:00
Dax T. Games 6b82bf5a93 format 2020-02-05 15:25:49 +00:00
Dax T Games 9756a9858a Update builder.go 2020-02-04 14:41:44 -05:00
Dax T. Games 4fa0f6baa3 recreate https://github.com/jetbrains-infra/packer-builder-vsphere/pull/238 2020-02-04 14:25:45 -05:00
279 changed files with 18156 additions and 953 deletions
+1 -1
View File
@@ -36,7 +36,7 @@ commands:
type: string
steps:
- checkout
- run: GOOS=<< parameters.GOOS >> go build -ldflags="-s -w" -o ./pkg/packer_<< parameters.GOOS >>_$(go env GOARCH) .
- run: GOOS=<< parameters.GOOS >> go build -ldflags="-s -w -X github.com/hashicorp/packer/version.GitCommit=${CIRCLE_SHA1}" -o ./pkg/packer_<< parameters.GOOS >>_$(go env GOARCH) .
- run: zip ./pkg/packer_<< parameters.GOOS >>_$(go env GOARCH).zip ./pkg/packer_<< parameters.GOOS >>_$(go env GOARCH)
- run: rm ./pkg/packer_<< parameters.GOOS >>_$(go env GOARCH)
- persist_to_workspace:
+2
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
+22
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
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
+11 -10
View File
@@ -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
+26
View File
@@ -1,3 +1,29 @@
## 1.5.5 (Upcoming)
### IMPROVEMENTS:
- builder/tencentcloud: Show tencentcloud image id after copy to desination
region. [GH-8763]
### Bug Fixes:
- builder/vsphere: Fix network object interface panic. [GH-8753]
## 1.5.4 (February 14, 2020)
no-change release to fix code-signing on OSX binaries. Since checksums for these
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
+21 -2
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 ./...
+1 -1
View File
@@ -205,7 +205,7 @@ func (c *AlicloudImageConfig) Prepare(ctx *interpolate.Context) []error {
strings.HasPrefix(c.AlicloudImageName, "https://") {
errs = append(errs, fmt.Errorf("image_name can't start with 'http://' or 'https://'"))
}
reg := regexp.MustCompile("\\s+")
reg := regexp.MustCompile(`\s+`)
if reg.FindString(c.AlicloudImageName) != "" {
errs = append(errs, fmt.Errorf("image_name can't include spaces"))
}
+1 -1
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"
+1 -1
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"
+1 -1
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"
)
+3 -3
View File
@@ -19,9 +19,9 @@ type AMIConfig struct {
// engine](../templates/engine.html) for more info).
AMIName string `mapstructure:"ami_name" required:"true"`
// The description to set for the resulting
// AMI(s). By default this description is empty. This is a template
// engine, see Build template
// data for more information.
// AMI(s). By default this description is empty. This is a
// [template engine](/docs/templates/engine.html), see [Build template
// data](#build-template-data) for more information.
AMIDescription string `mapstructure:"ami_description" required:"false"`
// The type of virtualization for the AMI
// you are building. This option is required to register HVM images. Can be
@@ -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"
)
+15 -7
View File
@@ -265,13 +265,21 @@ type RunConfig struct {
// because a particular availability zone does not have capacity for the
// specific instance_type requested in instance_type.
SpotInstanceTypes []string `mapstructure:"spot_instance_types" required:"false"`
// The maximum hourly price to pay for a spot instance
// to create the AMI. Spot instances are a type of instance that EC2 starts
// when the current spot price is less than the maximum price you specify.
// Spot price will be updated based on available spot instance capacity and
// current spot instance requests. It may save you some costs. You can set
// this to auto for Packer to automatically discover the best spot price or
// to "0" to use an on demand instance (default).
// With Spot Instances, you pay the Spot price that's in effect for the
// time period your instances are running. Spot Instance prices are set by
// Amazon EC2 and adjust gradually based on long-term trends in supply and
// demand for Spot Instance capacity.
//
// When this field is set, it represents the maximum hourly price you are
// willing to pay for a spot instance. If you do not set this value, it
// defaults to a maximum price equal to the on demand price of the
// instance. In the situation where the current Amazon-set spot price
// exceeds the value set in this field, Packer will not launch an instance
// and the build will error. In the situation where the Amazon-set spot
// price is less than the value set in this field, Packer will launch and
// you will pay the Amazon-set spot price, not this maximum value.
// For more information, see the Amazon docs on
// [spot pricing](https://aws.amazon.com/ec2/spot/pricing/).
SpotPrice string `mapstructure:"spot_price" required:"false"`
// Required if spot_price is set to
// auto. This tells Packer what sort of AMI you're launching to find the
@@ -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"
@@ -300,7 +300,7 @@ func (s *StepRunSpotInstance) Run(ctx context.Context, state multistep.StateBag)
if len(createOutput.Errors) > 0 {
errString := fmt.Sprintf("Error waiting for fleet request (%s) to become ready:", *createOutput.FleetId)
for _, outErr := range createOutput.Errors {
errString = errString + fmt.Sprintf("%s", *outErr.ErrorMessage)
errString = errString + aws.StringValue(outErr.ErrorMessage)
}
err = fmt.Errorf(errString)
state.Put("error", err)
+1
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"
+31
View File
@@ -87,6 +87,14 @@ func TestBuilderAcc_forceDeleteSnapshot(t *testing.T) {
})
}
func TestBuilderAcc_testSourceAmiFilter(t *testing.T) {
builderT.Test(t, builderT.TestCase{
PreCheck: func() { testAccPreCheck(t) },
Builder: &Builder{},
Template: testSourceAmiFilter,
})
}
func checkSnapshotsDeleted(snapshotIds []*string) builderT.TestCheckFunc {
return func(artifacts []packer.Artifact) error {
// Verify the snapshots are gone
@@ -344,6 +352,29 @@ const testBuilderAccEncrypted = `
}
`
const testSourceAmiFilter = `
{
"builders": [{
"type": "test",
"ami_name": "packer-filter-test-{{timestamp}}",
"region": "us-east-1",
"instance_type": "t2.micro",
"ssh_username": "ubuntu",
"source_ami_filter": {
"filters": {
"name": "*ubuntu-xenial-16.04-amd64-server-*",
"root-device-type": "ebs",
"virtualization-type": "hvm"
},
"most_recent": true,
"owners": [
"099720109477"
]
}
}]
}
`
func buildForceDeregisterConfig(val, name string) string {
return fmt.Sprintf(testBuilderAccForceDeregister, val, name)
}
+1
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"
+2 -1
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"
)
+1 -1
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"
+6 -6
View File
@@ -55,12 +55,12 @@ const (
)
var (
reCaptureContainerName = regexp.MustCompile("^[a-z0-9][a-z0-9\\-]{2,62}$")
reCaptureNamePrefix = regexp.MustCompile("^[A-Za-z0-9][A-Za-z0-9_\\-\\.]{0,23}$")
reCaptureContainerName = regexp.MustCompile(`^[a-z0-9][a-z0-9\-]{2,62}$`)
reCaptureNamePrefix = regexp.MustCompile(`^[A-Za-z0-9][A-Za-z0-9_\-\.]{0,23}$`)
reManagedDiskName = regexp.MustCompile(validManagedDiskName)
reResourceGroupName = regexp.MustCompile(validResourceGroupNameRe)
reSnapshotName = regexp.MustCompile("^[A-Za-z0-9_]{1,79}$")
reSnapshotPrefix = regexp.MustCompile("^[A-Za-z0-9_]{1,59}$")
reSnapshotName = regexp.MustCompile(`^[A-Za-z0-9_]{1,79}$`)
reSnapshotPrefix = regexp.MustCompile(`^[A-Za-z0-9_]{1,59}$`)
)
type PlanInformation struct {
@@ -371,8 +371,8 @@ type Config struct {
AllowedInboundIpAddresses []string `mapstructure:"allowed_inbound_ip_addresses"`
// Runtime Values
UserName string
Password string
UserName string `mapstructure-to-hcl2:",skip"`
Password string `mapstructure-to-hcl2:",skip"`
tmpAdminPassword string
tmpCertificatePassword string
tmpResourceGroupName string
-4
View File
@@ -66,8 +66,6 @@ type FlatConfig struct {
AdditionalDiskSize []int32 `mapstructure:"disk_additional_size" required:"false" cty:"disk_additional_size"`
DiskCachingType *string `mapstructure:"disk_caching_type" required:"false" cty:"disk_caching_type"`
AllowedInboundIpAddresses []string `mapstructure:"allowed_inbound_ip_addresses" cty:"allowed_inbound_ip_addresses"`
UserName *string `cty:"user_name"`
Password *string `cty:"password"`
Type *string `mapstructure:"communicator" cty:"communicator"`
PauseBeforeConnect *string `mapstructure:"pause_before_connecting" cty:"pause_before_connecting"`
SSHHost *string `mapstructure:"ssh_host" cty:"ssh_host"`
@@ -180,8 +178,6 @@ func (*FlatConfig) HCL2Spec() map[string]hcldec.Spec {
"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},
+1 -1
View File
@@ -120,7 +120,7 @@ type Config struct {
// provisioners should connect to the local IP address of the instance.
UseLocalIPAddress bool `mapstructure:"use_local_ip_address" required:"false"`
// User data to launch with the instance. This is a
// template engine see User Data bellow for
// template engine; see "User Data" bellow for
// more details. Packer will not automatically wait for a user script to
// finish before shutting down the instance this must be handled in a
// provisioner.
+1 -4
View File
@@ -186,12 +186,9 @@ func (c *Communicator) UploadDir(dst string, src string, exclude []string) error
*/
var dockerSource string
dockerSource := src
if src[len(src)-1] == '/' {
dockerSource = fmt.Sprintf("%s.", src)
} else {
dockerSource = fmt.Sprintf("%s", src)
}
// Make the directory, then copy into it
+2 -1
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) {
+22 -10
View File
@@ -91,17 +91,29 @@ type Config struct {
// Can be useful when using custom api_url. Defaults to public.
PublicNetAdpService string `mapstructure:"public_netadp_service" required:"false"`
ChrootDisk bool `mapstructure:"chroot_disk"`
ChrootDiskSize float32 `mapstructure:"chroot_disk_size"`
ChrootDiskType string `mapstructure:"chroot_disk_type"`
ChrootMountPath string `mapstructure:"chroot_mount_path"`
ChrootMounts [][]string `mapstructure:"chroot_mounts"`
ChrootCopyFiles []string `mapstructure:"chroot_copy_files"`
ChrootCommandWrapper string `mapstructure:"chroot_command_wrapper"`
ChrootDisk bool `mapstructure:"chroot_disk"`
ChrootDiskSize float32 `mapstructure:"chroot_disk_size"`
ChrootDiskType string `mapstructure:"chroot_disk_type"`
ChrootMountPath string `mapstructure:"chroot_mount_path"`
ChrootMounts [][]string `mapstructure:"chroot_mounts"`
ChrootCopyFiles []string `mapstructure:"chroot_copy_files"`
// How to run shell commands. This defaults to {{.Command}}. This may be
// useful to set if you want to set environmental variables or perhaps run
// it with sudo or so on. This is a configuration template where the
// .Command variable is replaced with the command to be run. Defaults to
// {{.Command}}.
ChrootCommandWrapper string `mapstructure:"chroot_command_wrapper"`
MountOptions []string `mapstructure:"mount_options"`
MountPartition string `mapstructure:"mount_partition"`
PreMountCommands []string `mapstructure:"pre_mount_commands"`
MountOptions []string `mapstructure:"mount_options"`
MountPartition string `mapstructure:"mount_partition"`
// A series of commands to execute after attaching the root volume and
// before mounting the chroot. This is not required unless using
// from_scratch. If so, this should include any partitioning and filesystem
// creation commands. The path to the device is provided by {{.Device}}.
PreMountCommands []string `mapstructure:"pre_mount_commands"`
// As pre_mount_commands, but the commands are executed after mounting the
// root device and before the extra mount and copy steps. The device and
// mount path are provided by {{.Device}} and {{.MountPath}}.
PostMountCommands []string `mapstructure:"post_mount_commands"`
// List of SSH keys by name or id to be added
// to the server on launch.
+22
View File
@@ -148,6 +148,21 @@ type CommonConfig struct {
// built. When this value is set to true, the machine will start without a
// console.
Headless bool `mapstructure:"headless" required:"false"`
// When configured, determines the device or device type that is given preferential
// treatment when choosing a boot device.
//
// For Generation 1:
// - `IDE`
// - `CD` *or* `DVD`
// - `Floppy`
// - `NET`
//
// For Generation 2:
// - `IDE:x:y`
// - `SCSI:x:y`
// - `CD` *or* `DVD`
// - `NET`
FirstBootDevice string `mapstructure:"first_boot_device" required:"false"`
}
func (c *CommonConfig) Prepare(ctx *interpolate.Context, pc *common.PackerConfig) ([]error, []string) {
@@ -268,6 +283,13 @@ func (c *CommonConfig) Prepare(ctx *interpolate.Context, pc *common.PackerConfig
}
}
if c.FirstBootDevice != "" {
_, _, _, err := ParseBootDeviceIdentifier(c.FirstBootDevice, c.Generation)
if err != nil {
errs = append(errs, fmt.Errorf("first_boot_device: %s", err))
}
}
if c.EnableVirtualizationExtensions {
if c.EnableDynamicMemory {
warning := fmt.Sprintf("For nested virtualization, when virtualization extension is enabled, " +
+2
View File
@@ -113,6 +113,8 @@ type Driver interface {
SetBootDvdDrive(string, uint, uint, uint) error
SetFirstBootDevice(string, string, uint, uint, uint) error
UnmountDvdDrive(string, uint, uint) error
DeleteDvdDrive(string, uint, uint) error
+19
View File
@@ -236,6 +236,14 @@ type DriverMock struct {
SetBootDvdDrive_Generation uint
SetBootDvdDrive_Err error
SetFirstBootDevice_Called bool
SetFirstBootDevice_VmName string
SetFirstBootDevice_ControllerType string
SetFirstBootDevice_ControllerNumber uint
SetFirstBootDevice_ControllerLocation uint
SetFirstBootDevice_Generation uint
SetFirstBootDevice_Err error
UnmountDvdDrive_Called bool
UnmountDvdDrive_VmName string
UnmountDvdDrive_ControllerNumber uint
@@ -575,6 +583,17 @@ func (d *DriverMock) SetBootDvdDrive(vmName string, controllerNumber uint, contr
return d.SetBootDvdDrive_Err
}
func (d *DriverMock) SetFirstBootDevice(vmName string, controllerType string, controllerNumber uint,
controllerLocation uint, generation uint) error {
d.SetFirstBootDevice_Called = true
d.SetFirstBootDevice_VmName = vmName
d.SetFirstBootDevice_ControllerType = controllerType
d.SetFirstBootDevice_ControllerNumber = controllerNumber
d.SetFirstBootDevice_ControllerLocation = controllerLocation
d.SetFirstBootDevice_Generation = generation
return d.SetFirstBootDevice_Err
}
func (d *DriverMock) UnmountDvdDrive(vmName string, controllerNumber uint, controllerLocation uint) error {
d.UnmountDvdDrive_Called = true
d.UnmountDvdDrive_VmName = vmName
+5
View File
@@ -267,6 +267,11 @@ func (d *HypervPS4Driver) SetBootDvdDrive(vmName string, controllerNumber uint,
return hyperv.SetBootDvdDrive(vmName, controllerNumber, controllerLocation, generation)
}
func (d *HypervPS4Driver) SetFirstBootDevice(vmName string, controllerType string, controllerNumber uint,
controllerLocation uint, generation uint) error {
return hyperv.SetFirstBootDevice(vmName, controllerType, controllerNumber, controllerLocation, generation)
}
func (d *HypervPS4Driver) UnmountDvdDrive(vmName string, controllerNumber uint, controllerLocation uint) error {
return hyperv.UnmountDvdDrive(vmName, controllerNumber, controllerLocation)
}
+20 -8
View File
@@ -12,7 +12,8 @@ import (
)
type StepMountDvdDrive struct {
Generation uint
Generation uint
FirstBootDevice string
}
func (s *StepMountDvdDrive) Run(ctx context.Context, state multistep.StateBag) multistep.StepAction {
@@ -57,13 +58,24 @@ func (s *StepMountDvdDrive) Run(ctx context.Context, state multistep.StateBag) m
state.Put("os.dvd.properties", dvdControllerProperties)
ui.Say(fmt.Sprintf("Setting boot drive to os dvd drive %s ...", isoPath))
err = driver.SetBootDvdDrive(vmName, controllerNumber, controllerLocation, s.Generation)
if err != nil {
err := fmt.Errorf(errorMsg, err)
state.Put("error", err)
ui.Error(err.Error())
return multistep.ActionHalt
// the "first_boot_device" setting has precedence over the legacy boot order
// configuration, but only if its been assigned a value.
if s.FirstBootDevice == "" {
if s.Generation > 1 {
// only print this message for Gen2, it's not a true statement for Gen1 VMs
ui.Say(fmt.Sprintf("Setting boot drive to os dvd drive %s ...", isoPath))
}
err = driver.SetBootDvdDrive(vmName, controllerNumber, controllerLocation, s.Generation)
if err != nil {
err := fmt.Errorf(errorMsg, err)
state.Put("error", err)
ui.Error(err.Error())
return multistep.ActionHalt
}
}
ui.Say(fmt.Sprintf("Mounting os dvd drive %s ...", isoPath))
@@ -0,0 +1,160 @@
package common
import (
"context"
"fmt"
"regexp"
"strconv"
"strings"
"github.com/hashicorp/packer/helper/multistep"
"github.com/hashicorp/packer/packer"
)
type StepSetFirstBootDevice struct {
Generation uint
FirstBootDevice string
}
func ParseBootDeviceIdentifier(deviceIdentifier string, generation uint) (string, uint, uint, error) {
// all input strings are forced to upperCase for comparison, I believe this is
// safe as all of our values are 7bit ASCII clean.
lookupDeviceIdentifier := strings.ToUpper(deviceIdentifier)
if generation == 1 {
// Gen1 values are a simple set of if/then/else values, which we coalesce into a map
// here for simplicity
lookupTable := map[string]string{
"FLOPPY": "FLOPPY",
"IDE": "IDE",
"NET": "NET",
"CD": "CD",
"DVD": "CD",
}
controllerType, isDefined := lookupTable[lookupDeviceIdentifier]
if !isDefined {
return "", 0, 0, fmt.Errorf("The value %q is not a properly formatted device group identifier.", deviceIdentifier)
}
// success
return controllerType, 0, 0, nil
}
// everything else is treated as generation 2... the first set of lookups covers
// the simple options..
lookupTable := map[string]string{
"CD": "CD",
"DVD": "CD",
"NET": "NET",
}
controllerType, isDefined := lookupTable[lookupDeviceIdentifier]
if isDefined {
// these types do not require controllerNumber or controllerLocation
return controllerType, 0, 0, nil
}
// not a simple option, check for a controllerType:controllerNumber:controllerLocation formatted
// device..
r, err := regexp.Compile(`^(IDE|SCSI):(\d+):(\d+)$`)
if err != nil {
return "", 0, 0, err
}
controllerMatch := r.FindStringSubmatch(lookupDeviceIdentifier)
if controllerMatch != nil {
var controllerLocation int64
var controllerNumber int64
// NOTE: controllerNumber and controllerLocation cannot be negative, the regex expression
// would not have matched if either number was signed
controllerNumber, err = strconv.ParseInt(controllerMatch[2], 10, 8)
if err == nil {
controllerLocation, err = strconv.ParseInt(controllerMatch[3], 10, 8)
if err == nil {
return controllerMatch[1], uint(controllerNumber), uint(controllerLocation), nil
}
}
return "", 0, 0, err
}
return "", 0, 0, fmt.Errorf("The value %q is not a properly formatted device identifier.", deviceIdentifier)
}
func (s *StepSetFirstBootDevice) Run(ctx context.Context, state multistep.StateBag) multistep.StepAction {
driver := state.Get("driver").(Driver)
ui := state.Get("ui").(packer.Ui)
vmName := state.Get("vmName").(string)
if s.FirstBootDevice != "" {
controllerType, controllerNumber, controllerLocation, err := ParseBootDeviceIdentifier(s.FirstBootDevice, s.Generation)
if err == nil {
switch {
case controllerType == "CD":
{
// the "DVD" controller is special, we only apply the setting if we actually mounted
// an ISO and only if that was mounted as the "IsoUrl" not a secondary ISO.
dvdControllerState := state.Get("os.dvd.properties")
if dvdControllerState == nil {
ui.Say("First Boot Device is DVD, but no primary ISO mounted. Ignoring.")
return multistep.ActionContinue
}
ui.Say(fmt.Sprintf("Setting boot device to %q", s.FirstBootDevice))
dvdController := dvdControllerState.(DvdControllerProperties)
err = driver.SetFirstBootDevice(vmName, controllerType, dvdController.ControllerNumber, dvdController.ControllerLocation, s.Generation)
}
default:
{
// anything else, we just pass as is..
ui.Say(fmt.Sprintf("Setting boot device to %q", s.FirstBootDevice))
err = driver.SetFirstBootDevice(vmName, controllerType, controllerNumber, controllerLocation, s.Generation)
}
}
}
if err != nil {
err := fmt.Errorf("Error setting first boot device: %s", err)
state.Put("error", err)
ui.Error(err.Error())
return multistep.ActionHalt
}
}
return multistep.ActionContinue
}
func (s *StepSetFirstBootDevice) Cleanup(state multistep.StateBag) {
// do nothing
}
@@ -0,0 +1,170 @@
package common
import (
"context"
"testing"
"github.com/hashicorp/packer/helper/multistep"
)
type parseBootDeviceIdentifierTest struct {
generation uint
deviceIdentifier string
controllerType string
controllerNumber uint
controllerLocation uint
failInParse bool // true if ParseBootDeviceIdentifier should return an error
haltStep bool // true if Step.Run should return Halt action
shouldCallSet bool // true if driver.SetFirstBootDevice should have been called
setDvdProps bool // true to set DvdDeviceProperties state
}
var parseIdentifierTests = [...]parseBootDeviceIdentifierTest{
{1, "IDE", "IDE", 0, 0, false, false, true, false},
{1, "idE", "IDE", 0, 0, false, false, true, false},
{1, "CD", "CD", 0, 0, false, false, false, false},
{1, "CD", "CD", 0, 0, false, false, true, true},
{1, "cD", "CD", 0, 0, false, false, false, false},
{1, "DVD", "CD", 0, 0, false, false, false, false},
{1, "DVD", "CD", 0, 0, false, false, true, true},
{1, "Dvd", "CD", 0, 0, false, false, false, false},
{1, "FLOPPY", "FLOPPY", 0, 0, false, false, true, false},
{1, "FloppY", "FLOPPY", 0, 0, false, false, true, false},
{1, "NET", "NET", 0, 0, false, false, true, false},
{1, "net", "NET", 0, 0, false, false, true, false},
{1, "", "", 0, 0, true, false, false, false},
{1, "bad", "", 0, 0, true, true, false, false},
{1, "IDE:0:0", "", 0, 0, true, true, true, false},
{1, "SCSI:0:0", "", 0, 0, true, true, true, false},
{2, "IDE", "", 0, 0, true, true, true, false},
{2, "idE", "", 0, 0, true, true, true, false},
{2, "CD", "CD", 0, 0, false, false, false, false},
{2, "CD", "CD", 0, 0, false, false, true, true},
{2, "cD", "CD", 0, 0, false, false, false, false},
{2, "DVD", "CD", 0, 0, false, false, false, false},
{2, "DVD", "CD", 0, 0, false, false, true, true},
{2, "Dvd", "CD", 0, 0, false, false, false, false},
{2, "FLOPPY", "", 0, 0, true, true, true, false},
{2, "FloppY", "", 0, 0, true, true, true, false},
{2, "NET", "NET", 0, 0, false, false, true, false},
{2, "net", "NET", 0, 0, false, false, true, false},
{2, "", "", 0, 0, true, false, false, false},
{2, "bad", "", 0, 0, true, true, false, false},
{2, "IDE:0:0", "IDE", 0, 0, false, false, true, false},
{2, "SCSI:0:0", "SCSI", 0, 0, false, false, true, false},
{2, "Ide:0:0", "IDE", 0, 0, false, false, true, false},
{2, "sCsI:0:0", "SCSI", 0, 0, false, false, true, false},
{2, "IDEscsi:0:0", "", 0, 0, true, true, false, false},
{2, "SCSIide:0:0", "", 0, 0, true, true, false, false},
{2, "IDE:0", "", 0, 0, true, true, false, false},
{2, "SCSI:0", "", 0, 0, true, true, false, false},
{2, "IDE:0:a", "", 0, 0, true, true, false, false},
{2, "SCSI:0:a", "", 0, 0, true, true, false, false},
{2, "IDE:0:653", "", 0, 0, true, true, false, false},
{2, "SCSI:-10:0", "", 0, 0, true, true, false, false},
}
func TestStepSetFirstBootDevice_impl(t *testing.T) {
var _ multistep.Step = new(StepSetFirstBootDevice)
}
func TestStepSetFirstBootDevice_ParseIdentifier(t *testing.T) {
for _, identifierTest := range parseIdentifierTests {
controllerType, controllerNumber, controllerLocation, err := ParseBootDeviceIdentifier(
identifierTest.deviceIdentifier,
identifierTest.generation)
if (err != nil) != identifierTest.failInParse {
t.Fatalf("Test %q (gen %v): failInParse: %v but err: %v", identifierTest.deviceIdentifier,
identifierTest.generation, identifierTest.failInParse, err)
}
switch {
case controllerType != identifierTest.controllerType:
t.Fatalf("Test %q (gen %v): controllerType: %q != %q", identifierTest.deviceIdentifier, identifierTest.generation,
identifierTest.controllerType, controllerType)
case controllerNumber != identifierTest.controllerNumber:
t.Fatalf("Test %q (gen %v): controllerNumber: %v != %v", identifierTest.deviceIdentifier, identifierTest.generation,
identifierTest.controllerNumber, controllerNumber)
case controllerLocation != identifierTest.controllerLocation:
t.Fatalf("Test %q (gen %v): controllerLocation: %v != %v", identifierTest.deviceIdentifier, identifierTest.generation,
identifierTest.controllerLocation, controllerLocation)
}
}
}
func TestStepSetFirstBootDevice(t *testing.T) {
step := new(StepSetFirstBootDevice)
for _, identifierTest := range parseIdentifierTests {
state := testState(t)
driver := state.Get("driver").(*DriverMock)
// requires the vmName state value
vmName := "foo"
state.Put("vmName", vmName)
// pretend that we mounted a DVD somewhere (CD:0:0)
if identifierTest.setDvdProps {
var dvdControllerProperties DvdControllerProperties
dvdControllerProperties.ControllerNumber = 0
dvdControllerProperties.ControllerLocation = 0
dvdControllerProperties.Existing = false
state.Put("os.dvd.properties", dvdControllerProperties)
}
step.Generation = identifierTest.generation
step.FirstBootDevice = identifierTest.deviceIdentifier
action := step.Run(context.Background(), state)
if (action != multistep.ActionContinue) != identifierTest.haltStep {
t.Fatalf("Test %q (gen %v): Bad action: %v", identifierTest.deviceIdentifier, identifierTest.generation, action)
}
if identifierTest.haltStep {
if _, ok := state.GetOk("error"); !ok {
t.Fatalf("Test %q (gen %v): Should have error", identifierTest.deviceIdentifier, identifierTest.generation)
}
// don't perform the remaining checks..
continue
} else {
if _, ok := state.GetOk("error"); ok {
t.Fatalf("Test %q (gen %v): Should NOT have error", identifierTest.deviceIdentifier, identifierTest.generation)
}
}
if driver.SetFirstBootDevice_Called != identifierTest.shouldCallSet {
if identifierTest.shouldCallSet {
t.Fatalf("Test %q (gen %v): Should have called SetFirstBootDevice", identifierTest.deviceIdentifier, identifierTest.generation)
}
t.Fatalf("Test %q (gen %v): Should NOT have called SetFirstBootDevice", identifierTest.deviceIdentifier, identifierTest.generation)
}
if (driver.SetFirstBootDevice_Called) &&
((driver.SetFirstBootDevice_VmName != vmName) ||
(driver.SetFirstBootDevice_ControllerType != identifierTest.controllerType) ||
(driver.SetFirstBootDevice_ControllerNumber != identifierTest.controllerNumber) ||
(driver.SetFirstBootDevice_ControllerLocation != identifierTest.controllerLocation) ||
(driver.SetFirstBootDevice_Generation != identifierTest.generation)) {
t.Fatalf("Test %q (gen %v): Called SetFirstBootDevice with unexpected arguments.", identifierTest.deviceIdentifier, identifierTest.generation)
}
}
}
+7 -1
View File
@@ -242,7 +242,8 @@ func (b *Builder) Run(ctx context.Context, ui packer.Ui, hook packer.Hook) (pack
&hypervcommon.StepEnableIntegrationService{},
&hypervcommon.StepMountDvdDrive{
Generation: b.config.Generation,
Generation: b.config.Generation,
FirstBootDevice: b.config.FirstBootDevice,
},
&hypervcommon.StepMountFloppydrive{
Generation: b.config.Generation,
@@ -264,6 +265,11 @@ func (b *Builder) Run(ctx context.Context, ui packer.Ui, hook packer.Hook) (pack
SwitchVlanId: b.config.SwitchVlanId,
},
&hypervcommon.StepSetFirstBootDevice{
Generation: b.config.Generation,
FirstBootDevice: b.config.FirstBootDevice,
},
&hypervcommon.StepRun{
Headless: b.config.Headless,
SwitchName: b.config.SwitchName,
+2
View File
@@ -97,6 +97,7 @@ type FlatConfig struct {
SkipCompaction *bool `mapstructure:"skip_compaction" required:"false" cty:"skip_compaction"`
SkipExport *bool `mapstructure:"skip_export" required:"false" cty:"skip_export"`
Headless *bool `mapstructure:"headless" required:"false" cty:"headless"`
FirstBootDevice *string `mapstructure:"first_boot_device" required:"false" cty:"first_boot_device"`
ShutdownCommand *string `mapstructure:"shutdown_command" required:"false" cty:"shutdown_command"`
ShutdownTimeout *string `mapstructure:"shutdown_timeout" required:"false" cty:"shutdown_timeout"`
DiskSize *uint `mapstructure:"disk_size" required:"false" cty:"disk_size"`
@@ -205,6 +206,7 @@ func (*FlatConfig) HCL2Spec() map[string]hcldec.Spec {
"skip_compaction": &hcldec.AttrSpec{Name: "skip_compaction", Type: cty.Bool, Required: false},
"skip_export": &hcldec.AttrSpec{Name: "skip_export", Type: cty.Bool, Required: false},
"headless": &hcldec.AttrSpec{Name: "headless", Type: cty.Bool, Required: false},
"first_boot_device": &hcldec.AttrSpec{Name: "first_boot_device", Type: cty.String, Required: false},
"shutdown_command": &hcldec.AttrSpec{Name: "shutdown_command", Type: cty.String, Required: false},
"shutdown_timeout": &hcldec.AttrSpec{Name: "shutdown_timeout", Type: cty.String, Required: false},
"disk_size": &hcldec.AttrSpec{Name: "disk_size", Type: cty.Number, Required: false},
+7 -1
View File
@@ -282,7 +282,8 @@ func (b *Builder) Run(ctx context.Context, ui packer.Ui, hook packer.Hook) (pack
&hypervcommon.StepEnableIntegrationService{},
&hypervcommon.StepMountDvdDrive{
Generation: b.config.Generation,
Generation: b.config.Generation,
FirstBootDevice: b.config.FirstBootDevice,
},
&hypervcommon.StepMountFloppydrive{
Generation: b.config.Generation,
@@ -304,6 +305,11 @@ func (b *Builder) Run(ctx context.Context, ui packer.Ui, hook packer.Hook) (pack
SwitchVlanId: b.config.SwitchVlanId,
},
&hypervcommon.StepSetFirstBootDevice{
Generation: b.config.Generation,
FirstBootDevice: b.config.FirstBootDevice,
},
&hypervcommon.StepRun{
Headless: b.config.Headless,
SwitchName: b.config.SwitchName,
+2
View File
@@ -97,6 +97,7 @@ type FlatConfig struct {
SkipCompaction *bool `mapstructure:"skip_compaction" required:"false" cty:"skip_compaction"`
SkipExport *bool `mapstructure:"skip_export" required:"false" cty:"skip_export"`
Headless *bool `mapstructure:"headless" required:"false" cty:"headless"`
FirstBootDevice *string `mapstructure:"first_boot_device" required:"false" cty:"first_boot_device"`
ShutdownCommand *string `mapstructure:"shutdown_command" required:"false" cty:"shutdown_command"`
ShutdownTimeout *string `mapstructure:"shutdown_timeout" required:"false" cty:"shutdown_timeout"`
CloneFromVMCXPath *string `mapstructure:"clone_from_vmcx_path" cty:"clone_from_vmcx_path"`
@@ -207,6 +208,7 @@ func (*FlatConfig) HCL2Spec() map[string]hcldec.Spec {
"skip_compaction": &hcldec.AttrSpec{Name: "skip_compaction", Type: cty.Bool, Required: false},
"skip_export": &hcldec.AttrSpec{Name: "skip_export", Type: cty.Bool, Required: false},
"headless": &hcldec.AttrSpec{Name: "headless", Type: cty.Bool, Required: false},
"first_boot_device": &hcldec.AttrSpec{Name: "first_boot_device", Type: cty.String, Required: false},
"shutdown_command": &hcldec.AttrSpec{Name: "shutdown_command", Type: cty.String, Required: false},
"shutdown_timeout": &hcldec.AttrSpec{Name: "shutdown_timeout", Type: cty.String, Required: false},
"clone_from_vmcx_path": &hcldec.AttrSpec{Name: "clone_from_vmcx_path", Type: cty.String, Required: false},
+1 -1
View File
@@ -28,7 +28,7 @@ type Config struct {
ContainerName string `mapstructure:"container_name" required:"false"`
// Allows you to specify a wrapper command, such
// as ssh so you can execute packer builds on a remote host. Defaults to
// Empty.
// `{{.Command}}`; i.e. no wrapper.
CommandWrapper string `mapstructure:"command_wrapper" required:"false"`
// The timeout in seconds to wait for the the
// container to start. Defaults to 20 seconds.
+1 -1
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"
)
+2 -1
View File
@@ -20,7 +20,8 @@ type Config struct {
OutputImage string `mapstructure:"output_image" required:"false"`
ContainerName string `mapstructure:"container_name"`
// Lets you prefix all builder commands, such as
// with ssh for a remote build host. Defaults to "".
// with ssh for a remote build host. Defaults to "{{.Command}}"; i.e. no
// wrapper.
CommandWrapper string `mapstructure:"command_wrapper" required:"false"`
// The source image to use when creating the build
// container. This can be a (local or remote) image (name or fingerprint).
+1 -1
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"
)
+5
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
}
+1
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)
+1 -1
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"
)
+2 -1
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.
+3 -2
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 {
+4
View File
@@ -8,6 +8,7 @@ import (
"log"
"net/url"
"os"
"strings"
"time"
"github.com/hashicorp/packer/common"
@@ -213,6 +214,9 @@ func (c *Config) Prepare(raws ...interface{}) ([]string, error) {
if c.Node == "" {
errs = packer.MultiErrorAppend(errs, errors.New("node must be specified"))
}
if strings.ContainsAny(c.TemplateName, " ") {
errs = packer.MultiErrorAppend(errs, errors.New("template_name must not contain spaces"))
}
for idx := range c.NICs {
if c.NICs[idx].Bridge == "" {
errs = packer.MultiErrorAppend(errs, errors.New(fmt.Sprintf("network_adapters[%d].bridge must be specified", idx)))
+4
View File
@@ -281,6 +281,10 @@ type Config struct {
// This will also work with WinRM, just change the port forward in
// `qemuargs` to map to WinRM's default port of `5985` or whatever value
// you have the service set to listen on.
//
// This is a template engine and allows access to the following variables:
// `{{ .HTTPIP }}`, `{{ .HTTPPort }}`, `{{ .HTTPDir }}`,
// `{{ .OutputDir }}`, `{{ .Name }}`, and `{{ .SSHHostPort }}`
QemuArgs [][]string `mapstructure:"qemuargs" required:"false"`
// The name of the Qemu binary to look for. This
// defaults to qemu-system-x86_64, but may need to be changed for
+1 -1
View File
@@ -189,7 +189,7 @@ func (d *QemuDriver) Version() (string, error) {
versionOutput := strings.TrimSpace(stdout.String())
log.Printf("Qemu --version output: %s", versionOutput)
versionRe := regexp.MustCompile("[\\.[0-9]+]*")
versionRe := regexp.MustCompile(`[\.[0-9]+]*`)
matches := versionRe.FindStringSubmatch(versionOutput)
if len(matches) == 0 {
return "", fmt.Errorf("No version found: %s", versionOutput)
+1 -1
View File
@@ -18,7 +18,7 @@ func (s *stepCopyDisk) Run(ctx context.Context, state multistep.StateBag) multis
driver := state.Get("driver").(Driver)
isoPath := state.Get("iso_path").(string)
ui := state.Get("ui").(packer.Ui)
path := filepath.Join(config.OutputDir, fmt.Sprintf("%s", config.VMName))
path := filepath.Join(config.OutputDir, config.VMName)
command := []string{
"convert",
+2 -2
View File
@@ -29,13 +29,13 @@ func (s *stepCreateDisk) Run(ctx context.Context, state multistep.StateBag) mult
ui.Say("Creating required virtual machine disks")
// The 'main' or 'default' disk
diskFullPaths = append(diskFullPaths, filepath.Join(config.OutputDir, name))
diskSizes = append(diskSizes, fmt.Sprintf("%s", config.DiskSize))
diskSizes = append(diskSizes, config.DiskSize)
// Additional disks
if len(config.AdditionalDiskSize) > 0 {
for i, diskSize := range config.AdditionalDiskSize {
path := filepath.Join(config.OutputDir, fmt.Sprintf("%s-%d", name, i+1))
diskFullPaths = append(diskFullPaths, path)
size := fmt.Sprintf("%s", diskSize)
size := diskSize
diskSizes = append(diskSizes, size)
}
}
+1
View File
@@ -2,6 +2,7 @@ package qemu
import (
"context"
"github.com/hashicorp/packer/common"
"github.com/hashicorp/packer/helper/multistep"
)
+2 -1
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) {
+1 -1
View File
@@ -23,7 +23,7 @@ func (s *stepResizeDisk) Run(ctx context.Context, state multistep.StateBag) mult
"resize",
"-f", config.Format,
path,
fmt.Sprintf("%s", config.DiskSize),
config.DiskSize,
}
if config.DiskImage == false {
return multistep.ActionContinue
+2 -10
View File
@@ -8,8 +8,6 @@ import (
"os"
"github.com/hashicorp/packer/template/interpolate"
"github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/common"
"github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/common/profile"
cvm "github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/cvm/v20170312"
vpc "github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/vpc/v20170312"
)
@@ -81,17 +79,11 @@ func (cf *TencentCloudAccessConfig) Client() (*cvm.Client, *vpc.Client, error) {
return nil, nil, fmt.Errorf("parameter zone must be set")
}
credential := common.NewCredential(cf.SecretId, cf.SecretKey)
cpf := profile.NewClientProfile()
cpf.HttpProfile.ReqMethod = "POST"
cpf.HttpProfile.ReqTimeout = 300
cpf.Language = "en-US"
if cvm_client, err = cvm.NewClient(credential, cf.Region, cpf); err != nil {
if cvm_client, err = NewCvmClient(cf.SecretId, cf.SecretKey, cf.Region); err != nil {
return nil, nil, err
}
if vpc_client, err = vpc.NewClient(credential, cf.Region, cpf); err != nil {
if vpc_client, err = NewVpcClient(cf.SecretId, cf.SecretKey, cf.Region); err != nil {
return nil, nil, err
}
+67 -33
View File
@@ -10,16 +10,18 @@ import (
"github.com/hashicorp/packer/common/retry"
"github.com/hashicorp/packer/helper/multistep"
"github.com/hashicorp/packer/packer"
"github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/common"
"github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/common/errors"
"github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/common/profile"
cvm "github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/cvm/v20170312"
vpc "github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/vpc/v20170312"
)
// DefaultWaitForInterval is sleep interval when wait statue
const DefaultWaitForInterval = 5
// WaitForInstance wait for instance reaches statue
func WaitForInstance(client *cvm.Client, instanceId string, status string, timeout int) error {
ctx := context.TODO()
func WaitForInstance(ctx context.Context, client *cvm.Client, instanceId string, status string, timeout int) error {
req := cvm.NewDescribeInstancesRequest()
req.InstanceIds = []*string{&instanceId}
@@ -50,54 +52,86 @@ func WaitForInstance(client *cvm.Client, instanceId string, status string, timeo
}
// WaitForImageReady wait for image reaches statue
func WaitForImageReady(client *cvm.Client, imageName string, status string, timeout int) error {
ctx := context.TODO()
req := cvm.NewDescribeImagesRequest()
FILTER_IMAGE_NAME := "image-name"
req.Filters = []*cvm.Filter{
{
Name: &FILTER_IMAGE_NAME,
Values: []*string{&imageName},
},
}
func WaitForImageReady(ctx context.Context, client *cvm.Client, imageName string, status string, timeout int) error {
for {
var resp *cvm.DescribeImagesResponse
err := Retry(ctx, func(ctx context.Context) error {
var e error
resp, e = client.DescribeImages(req)
return e
})
image, err := GetImageByName(ctx, client, imageName)
if err != nil {
return err
}
find := false
for _, image := range resp.Response.ImageSet {
if *image.ImageName == imageName && *image.ImageState == status {
find = true
break
}
}
if find {
break
if image != nil && *image.ImageState == status {
return nil
}
time.Sleep(DefaultWaitForInterval * time.Second)
timeout = timeout - DefaultWaitForInterval
if timeout <= 0 {
return fmt.Errorf("wait image(%s) status(%s) timeout", imageName, status)
}
}
}
return nil
// GetImageByName get image by image name
func GetImageByName(ctx context.Context, client *cvm.Client, imageName string) (*cvm.Image, error) {
req := cvm.NewDescribeImagesRequest()
req.Filters = []*cvm.Filter{
{
Name: common.StringPtr("image-name"),
Values: []*string{&imageName},
},
}
var resp *cvm.DescribeImagesResponse
err := Retry(ctx, func(ctx context.Context) error {
var e error
resp, e = client.DescribeImages(req)
return e
})
if err != nil {
return nil, err
}
if *resp.Response.TotalCount > 0 {
for _, image := range resp.Response.ImageSet {
if *image.ImageName == imageName {
return image, nil
}
}
}
return nil, nil
}
// NewCvmClient returns a new cvm client
func NewCvmClient(secretId, secretKey, region string) (client *cvm.Client, err error) {
cpf := profile.NewClientProfile()
cpf.HttpProfile.ReqMethod = "POST"
cpf.HttpProfile.ReqTimeout = 300
cpf.Language = "en-US"
credential := common.NewCredential(secretId, secretKey)
client, err = cvm.NewClient(credential, region, cpf)
return
}
// NewVpcClient returns a new vpc client
func NewVpcClient(secretId, secretKey, region string) (client *vpc.Client, err error) {
cpf := profile.NewClientProfile()
cpf.HttpProfile.ReqMethod = "POST"
cpf.HttpProfile.ReqTimeout = 300
cpf.Language = "en-US"
credential := common.NewCredential(secretId, secretKey)
client, err = vpc.NewClient(credential, region, cpf)
return
}
// CheckResourceIdFormat check resource id format
func CheckResourceIdFormat(resource string, id string) bool {
regex := regexp.MustCompile(fmt.Sprintf("%s-[0-9a-z]{8}$", resource))
if !regex.MatchString(id) {
return false
}
return true
return regex.MatchString(id)
}
// SSHHost returns a function that can be given to the SSH communicator
@@ -2,6 +2,7 @@ package cvm
import (
"context"
"fmt"
"strings"
"github.com/hashicorp/packer/helper/multistep"
@@ -19,6 +20,7 @@ func (s *stepCopyImage) Run(ctx context.Context, state multistep.StateBag) multi
return multistep.ActionContinue
}
config := state.Get("config").(*Config)
client := state.Get("cvm_client").(*cvm.Client)
imageId := state.Get("image").(*cvm.Image).ImageId
@@ -43,6 +45,34 @@ func (s *stepCopyImage) Run(ctx context.Context, state multistep.StateBag) multi
return Halt(state, err, "Failed to copy image")
}
Message(state, "Waiting for image ready", "")
tencentCloudImages := state.Get("tencentcloudimages").(map[string]string)
for _, region := range req.DestinationRegions {
rc, err := NewCvmClient(config.SecretId, config.SecretKey, *region)
if err != nil {
return Halt(state, err, "Failed to init client")
}
err = WaitForImageReady(ctx, rc, config.ImageName, "NORMAL", 1800)
if err != nil {
return Halt(state, err, "Failed to wait for image ready")
}
image, err := GetImageByName(ctx, rc, config.ImageName)
if err != nil {
return Halt(state, err, "Failed to get image")
}
if image == nil {
return Halt(state, err, "Failed to wait for image ready")
}
tencentCloudImages[*region] = *image.ImageId
Message(state, fmt.Sprintf("Copy image from %s(%s) to %s(%s)", s.SourceRegion, *imageId, *region, *image.ImageId), "")
}
state.Put("tencentcloudimages", tencentCloudImages)
Message(state, "Image copied", "")
return multistep.ActionContinue
+6 -20
View File
@@ -58,36 +58,22 @@ func (s *stepCreateImage) Run(ctx context.Context, state multistep.StateBag) mul
}
Message(state, "Waiting for image ready", "")
err = WaitForImageReady(client, config.ImageName, "NORMAL", 3600)
err = WaitForImageReady(ctx, client, config.ImageName, "NORMAL", 3600)
if err != nil {
return Halt(state, err, "Failed to wait for image ready")
}
describeReq := cvm.NewDescribeImagesRequest()
FILTER_IMAGE_NAME := "image-name"
describeReq.Filters = []*cvm.Filter{
{
Name: &FILTER_IMAGE_NAME,
Values: []*string{&config.ImageName},
},
}
var describeResp *cvm.DescribeImagesResponse
err = Retry(ctx, func(ctx context.Context) error {
var e error
describeResp, e = client.DescribeImages(describeReq)
return e
})
image, err := GetImageByName(ctx, client, config.ImageName)
if err != nil {
return Halt(state, err, "Failed to wait for image ready")
return Halt(state, err, "Failed to get image")
}
if *describeResp.Response.TotalCount == 0 {
if image == nil {
return Halt(state, fmt.Errorf("No image return"), "Failed to crate image")
}
s.imageId = *describeResp.Response.ImageSet[0].ImageId
state.Put("image", describeResp.Response.ImageSet[0])
s.imageId = *image.ImageId
state.Put("image", image)
Message(state, s.imageId, "Image created")
tencentCloudImages := make(map[string]string)
+2 -15
View File
@@ -5,7 +5,6 @@ import (
"fmt"
"github.com/hashicorp/packer/helper/multistep"
"github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/common"
cvm "github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/cvm/v20170312"
)
@@ -18,24 +17,12 @@ func (s *stepPreValidate) Run(ctx context.Context, state multistep.StateBag) mul
Say(state, config.ImageName, "Trying to check image name")
req := cvm.NewDescribeImagesRequest()
req.Filters = []*cvm.Filter{
{
Name: common.StringPtr("image-name"),
Values: []*string{&config.ImageName},
},
}
var resp *cvm.DescribeImagesResponse
err := Retry(ctx, func(ctx context.Context) error {
var err error
resp, err = client.DescribeImages(req)
return err
})
image, err := GetImageByName(ctx, client, config.ImageName)
if err != nil {
return Halt(state, err, "Failed to get images info")
}
if *resp.Response.TotalCount > 0 {
if image != nil {
return Halt(state, fmt.Errorf("Image name %s has exists", config.ImageName), "")
}
@@ -157,7 +157,7 @@ func (s *stepRunInstance) Run(ctx context.Context, state multistep.StateBag) mul
s.instanceId = *resp.Response.InstanceIdSet[0]
Message(state, "Waiting for instance ready", "")
err = WaitForInstance(client, s.instanceId, "RUNNING", 1800)
err = WaitForInstance(ctx, client, s.instanceId, "RUNNING", 1800)
if err != nil {
return Halt(state, err, "Failed to wait for instance ready")
}
+88
View File
@@ -0,0 +1,88 @@
package vagrant
// Create a mock driver so that we can test Vagrant builder steps
type MockVagrantDriver struct {
InitCalled bool
AddCalled bool
UpCalled bool
HaltCalled bool
SuspendCalled bool
SSHConfigCalled bool
DestroyCalled bool
PackageCalled bool
VerifyCalled bool
VersionCalled bool
ReturnError error
ReturnSSHConfig *VagrantSSHConfig
GlobalID string
}
func (d *MockVagrantDriver) Init([]string) error {
d.InitCalled = true
return d.ReturnError
}
func (d *MockVagrantDriver) Add([]string) error {
d.AddCalled = true
return d.ReturnError
}
func (d *MockVagrantDriver) Up([]string) (string, string, error) {
d.UpCalled = true
return "", "", nil
}
func (d *MockVagrantDriver) Halt(string) error {
d.HaltCalled = true
return d.ReturnError
}
func (d *MockVagrantDriver) Suspend(string) error {
d.SuspendCalled = true
return d.ReturnError
}
func (d *MockVagrantDriver) SSHConfig(gid string) (*VagrantSSHConfig, error) {
d.SSHConfigCalled = true
// track the input value
d.GlobalID = gid
if d.ReturnSSHConfig != nil {
return d.ReturnSSHConfig, nil
}
sshConfig := VagrantSSHConfig{
Hostname: "127.0.0.1",
User: "vagrant",
Port: "2222",
UserKnownHostsFile: "/dev/null",
StrictHostKeyChecking: false,
PasswordAuthentication: false,
IdentityFile: "\"/path with spaces/insecure_private_key\"",
IdentitiesOnly: true,
LogLevel: "FATAL"}
return &sshConfig, d.ReturnError
}
func (d *MockVagrantDriver) Destroy(string) error {
d.DestroyCalled = true
return d.ReturnError
}
func (d *MockVagrantDriver) Package([]string) error {
d.PackageCalled = true
return d.ReturnError
}
func (d *MockVagrantDriver) Verify() error {
d.VerifyCalled = true
return d.ReturnError
}
func (d *MockVagrantDriver) Version() (string, error) {
d.VersionCalled = true
return "", d.ReturnError
}
// End of mock definition
+3 -3
View File
@@ -56,9 +56,9 @@ func (s *StepSSHConfig) Run(ctx context.Context, state multistep.StateBag) multi
}
log.Printf("identity file is %s", sshConfig.IdentityFile)
log.Printf("Removing quotes from identity file")
sshConfig.IdentityFile, err = strconv.Unquote(sshConfig.IdentityFile)
if err != nil {
log.Printf("Error unquoting identity file: %s", err)
unquoted, err := strconv.Unquote(sshConfig.IdentityFile)
if err == nil {
sshConfig.IdentityFile = unquoted
}
config.Comm.SSHPrivateKeyFile = sshConfig.IdentityFile
config.Comm.SSHUsername = sshConfig.User
+98
View File
@@ -0,0 +1,98 @@
package vagrant
import (
"context"
"testing"
"github.com/hashicorp/packer/helper/multistep"
)
func TestStepSSHConfig_Impl(t *testing.T) {
var raw interface{}
raw = new(StepSSHConfig)
if _, ok := raw.(multistep.Step); !ok {
t.Fatalf("initialize should be a step")
}
}
func TestPrepStepSSHConfig_GlobalID(t *testing.T) {
driver := &MockVagrantDriver{}
config := &Config{}
state := new(multistep.BasicStateBag)
state.Put("driver", driver)
state.Put("config", config)
step := StepSSHConfig{
GlobalID: "adsfadf",
}
_ = step.Run(context.Background(), state)
if driver.GlobalID != "adsfadf" {
t.Fatalf("Should have called SSHConfig with GlobalID asdfasdf")
}
}
func TestPrepStepSSHConfig_NoGlobalID(t *testing.T) {
driver := &MockVagrantDriver{}
config := &Config{}
state := new(multistep.BasicStateBag)
state.Put("driver", driver)
state.Put("config", config)
step := StepSSHConfig{}
_ = step.Run(context.Background(), state)
if driver.GlobalID != "source" {
t.Fatalf("Should have called SSHConfig with GlobalID source")
}
}
func TestPrepStepSSHConfig_SpacesInPath(t *testing.T) {
driver := &MockVagrantDriver{}
driver.ReturnSSHConfig = &VagrantSSHConfig{
Hostname: "127.0.0.1",
User: "vagrant",
Port: "2222",
UserKnownHostsFile: "/dev/null",
StrictHostKeyChecking: false,
PasswordAuthentication: false,
IdentityFile: "\"/path with spaces/insecure_private_key\"",
IdentitiesOnly: true,
LogLevel: "FATAL"}
config := &Config{}
state := new(multistep.BasicStateBag)
state.Put("driver", driver)
state.Put("config", config)
step := StepSSHConfig{}
_ = step.Run(context.Background(), state)
expected := "/path with spaces/insecure_private_key"
if config.Comm.SSHPrivateKeyFile != expected {
t.Fatalf("Bad config private key. Recieved: %s; expected: %s.", config.Comm.SSHPrivateKeyFile, expected)
}
}
func TestPrepStepSSHConfig_NoSpacesInPath(t *testing.T) {
driver := &MockVagrantDriver{}
driver.ReturnSSHConfig = &VagrantSSHConfig{
Hostname: "127.0.0.1",
User: "vagrant",
Port: "2222",
UserKnownHostsFile: "/dev/null",
StrictHostKeyChecking: false,
PasswordAuthentication: false,
IdentityFile: "/path/without/spaces/insecure_private_key",
IdentitiesOnly: true,
LogLevel: "FATAL"}
config := &Config{}
state := new(multistep.BasicStateBag)
state.Put("driver", driver)
state.Put("config", config)
step := StepSSHConfig{}
_ = step.Run(context.Background(), state)
expected := "/path/without/spaces/insecure_private_key"
if config.Comm.SSHPrivateKeyFile != expected {
t.Fatalf("Bad config private key. Recieved: %s; expected: %s.", config.Comm.SSHPrivateKeyFile, expected)
}
}
+3
View File
@@ -25,6 +25,9 @@ type Driver interface {
// Create an NVME controller
CreateNVMeController(vm string, controller string, portcount int) error
// Delete all floppy controllers
RemoveFloppyControllers(vm string) error
// Delete a VM by name
Delete(string) error
+49
View File
@@ -75,6 +75,55 @@ func (d *VBox42Driver) CreateSCSIController(vmName string, name string) error {
return d.VBoxManage(command...)
}
func (d *VBox42Driver) RemoveFloppyControllers(vmName string) error {
var stdout bytes.Buffer
cmd := exec.Command(d.VBoxManagePath, "showvminfo", vmName, "--machinereadable")
cmd.Stdout = &stdout
if err := cmd.Run(); err != nil {
return err
}
StorageControllerTypeRe := regexp.MustCompile("^storagecontrollertype([0-9]+)=\"(.+)\"$")
StorageControllerNameRe := regexp.MustCompile("^storagecontrollername([0-9]+)=\"(.+)\"$")
storageControllerNames := make(map[string]string)
storageControllerIdx := ""
for _, line := range strings.Split(stdout.String(), "\n") {
// Need to trim off CR character when running in windows
// Trimming whitespaces at this point helps to filter out empty value
line = strings.TrimRight(line, " \r")
matches := StorageControllerTypeRe.FindStringSubmatch(line)
if matches != nil {
// Floppy controllers are of a type I82078
if matches[2] == "I82078" {
// VirtualBox supports only one floppy controller per VM
storageControllerIdx = matches[1]
}
continue
}
matches = StorageControllerNameRe.FindStringSubmatch(line)
if matches != nil {
storageControllerNames[matches[1]] = matches[2]
}
}
if storageControllerIdx == "" {
return nil
}
command := []string{
"storagectl", vmName,
"--name", storageControllerNames[storageControllerIdx],
"--remove",
}
return d.VBoxManage(command...)
}
func (d *VBox42Driver) Delete(name string) error {
return d.VBoxManage("unregistervm", name, "--delete")
}
+8
View File
@@ -17,6 +17,9 @@ type DriverMock struct {
CreateNVMeControllerController string
CreateNVMeControllerErr error
RemoveFloppyControllersVM string
RemoveFloppyControllersErr error
DeleteCalled bool
DeleteName string
DeleteErr error
@@ -81,6 +84,11 @@ func (d *DriverMock) CreateNVMeController(vm string, controller string, portcoun
return d.CreateNVMeControllerErr
}
func (d *DriverMock) RemoveFloppyControllers(vm string) error {
d.RemoveFloppyControllersVM = vm
return d.RemoveFloppyControllersErr
}
func (d *DriverMock) Delete(name string) error {
d.DeleteCalled = true
d.DeleteName = name
@@ -48,6 +48,12 @@ func (s *StepAttachFloppy) Run(ctx context.Context, state multistep.StateBag) mu
ui := state.Get("ui").(packer.Ui)
vmName := state.Get("vmName").(string)
ui.Say("Deleting any current floppy disk...")
if err := driver.RemoveFloppyControllers(vmName); err != nil {
state.Put("error", fmt.Errorf("Error deleting existing floppy controllers: %s", err))
return multistep.ActionHalt
}
ui.Say("Attaching floppy disk...")
// Create the floppy disk controller
@@ -38,6 +38,10 @@ func TestStepAttachFloppy(t *testing.T) {
t.Fatal("should NOT have error")
}
if driver.RemoveFloppyControllersVM == "" {
t.Fatal("RemoveFloppyControllers was not called")
}
if len(driver.VBoxManageCalls) != 2 {
t.Fatal("not enough calls to VBoxManage")
}
@@ -52,7 +52,7 @@ func (s *StepConfigureVRDP) Run(ctx context.Context, state multistep.StateBag) m
command := []string{
"modifyvm", vmName,
"--vrdeaddress", fmt.Sprintf("%s", s.VRDPBindAddress),
"--vrdeaddress", s.VRDPBindAddress,
"--vrdeauthtype", "null",
"--vrde", "on",
"--vrdeport",
+4 -3
View File
@@ -57,8 +57,8 @@ type Config struct {
// The path on the guest virtual machine where the VirtualBox guest
// additions ISO will be uploaded. By default this is
// VBoxGuestAdditions.iso which should upload into the login directory of
// the user. This is a configuration template where the Version variable is
// replaced with the VirtualBox version.
// the user. This is a configuration template where the `{{ .Version }}`
// variable is replaced with the VirtualBox version.
GuestAdditionsPath string `mapstructure:"guest_additions_path" required:"false"`
// The SHA256 checksum of the guest additions ISO that will be uploaded to
// the guest VM. By default the checksums will be downloaded from the
@@ -69,7 +69,8 @@ type Config struct {
// URL if the ISO is at a local path. By default, the VirtualBox builder
// will attempt to find the guest additions ISO on the local file system.
// If it is not available locally, the builder will download the proper
// guest additions ISO from the internet.
// guest additions ISO from the internet. This is a template engine, and you
// have access to the variable `{{ .Version }}`.
GuestAdditionsURL string `mapstructure:"guest_additions_url" required:"false"`
// The interface type to use to mount guest additions when
// guest_additions_mode is set to attach. Will default to the value set in
+1 -1
View File
@@ -102,7 +102,7 @@ func (s *StepExport) Run(ctx context.Context, state multistep.StateBag) multiste
return multistep.ActionHalt
}
ui.Message(fmt.Sprintf("%s", out.String()))
ui.Message(out.String())
return multistep.ActionContinue
}
@@ -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) {
+8 -3
View File
@@ -92,7 +92,9 @@ type Config struct {
// set in the VMware VMX. By default this is other. By specifying a more
// specific OS type, VMware may perform some optimizations or virtual hardware
// changes to better support the operating system running in the
// virtual machine.
// virtual machine. Valid values differ by platform and version numbers, and may
// not match other VMware API's representation of the guest OS names. Consult your
// platform for valid values.
GuestOSType string `mapstructure:"guest_os_type" required:"false"`
// The [vmx hardware
// version](http://kb.vmware.com/selfservice/microsites/search.do?language=en_US&cmd=displayKC&externalId=1003746)
@@ -106,8 +108,11 @@ type Config struct {
VMXDiskTemplatePath string `mapstructure:"vmx_disk_template_path"`
// Path to a [configuration template](/docs/templates/engine.html) that
// defines the contents of the virtual machine VMX file for VMware. This is
// for **advanced users only** as this can render the virtual machine
// defines the contents of the virtual machine VMX file for VMware. The
// engine has access to the template variables `{{ .DiskNumber }}` and
// `{{ .DiskName }}`.
//
// This is for **advanced users only** as this can render the virtual machine
// non-functional. See below for more information. For basic VMX
// modifications, try `vmx_data` first.
VMXTemplatePath string `mapstructure:"vmx_template_path" required:"false"`
+1
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"
+3 -2
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) {
+2 -1
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) {
+1
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"
@@ -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"
+1
View File
@@ -6,6 +6,7 @@ package common
import (
"context"
"fmt"
"github.com/hashicorp/packer/builder/vsphere/driver"
"github.com/hashicorp/packer/helper/multistep"
)
+1
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"
+2 -1
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 {
+3 -2
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 {
+1
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"
+1
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"
+3 -2
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 {
+4 -3
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 {
+1
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"
+3 -2
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 {
+1
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"
+11 -3
View File
@@ -1,6 +1,8 @@
package driver
import (
"fmt"
"github.com/vmware/govmomi/object"
"github.com/vmware/govmomi/vim25/mo"
"github.com/vmware/govmomi/vim25/types"
@@ -8,7 +10,7 @@ import (
type Network struct {
driver *Driver
network *object.Network
network object.NetworkReference
}
func (d *Driver) NewNetwork(ref *types.ManagedObjectReference) *Network {
@@ -24,7 +26,7 @@ func (d *Driver) FindNetwork(name string) (*Network, error) {
return nil, err
}
return &Network{
network: n.(*object.Network),
network: n,
driver: d,
}, nil
}
@@ -37,7 +39,13 @@ func (n *Network) Info(params ...string) (*mo.Network, error) {
p = params
}
var info mo.Network
err := n.network.Properties(n.driver.ctx, n.network.Reference(), p, &info)
network, ok := n.network.(*object.Network)
if !ok {
return nil, fmt.Errorf("unexpected %t network object type", n.network)
}
err := network.Properties(n.driver.ctx, network.Reference(), p, &info)
if err != nil {
return nil, err
}
+1
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"
+76 -43
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,10 +44,15 @@ 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"
DiskSize int64
DiskControllerType string // example: "scsi", "pvscsi"
Annotation string
Name string
@@ -56,11 +62,17 @@ 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
Storage []Disk
}
type Disk struct {
DiskSize int64
DiskEagerlyScrub bool
DiskThinProvisioned bool
}
func (d *Driver) NewVM(ref *types.ManagedObjectReference) *VirtualMachine {
@@ -480,6 +492,10 @@ func (vm *VirtualMachine) GetDir() (string, error) {
}
func addDisk(_ *Driver, devices object.VirtualDeviceList, config *CreateConfig) (object.VirtualDeviceList, error) {
if len(config.Storage) == 0 {
return nil, errors.New("no storage devices have been defined")
}
device, err := devices.CreateSCSIController(config.DiskControllerType)
if err != nil {
return nil, err
@@ -490,60 +506,77 @@ func addDisk(_ *Driver, devices object.VirtualDeviceList, config *CreateConfig)
return nil, err
}
disk := &types.VirtualDisk{
VirtualDevice: types.VirtualDevice{
Key: devices.NewKey(),
Backing: &types.VirtualDiskFlatVer2BackingInfo{
DiskMode: string(types.VirtualDiskModePersistent),
ThinProvisioned: types.NewBool(config.DiskThinProvisioned),
for _, dc := range config.Storage {
disk := &types.VirtualDisk{
VirtualDevice: types.VirtualDevice{
Key: devices.NewKey(),
Backing: &types.VirtualDiskFlatVer2BackingInfo{
DiskMode: string(types.VirtualDiskModePersistent),
ThinProvisioned: types.NewBool(dc.DiskThinProvisioned),
EagerlyScrub: types.NewBool(dc.DiskEagerlyScrub),
},
},
},
CapacityInKB: config.DiskSize * 1024,
}
CapacityInKB: dc.DiskSize * 1024,
}
devices.AssignController(disk, controller)
devices = append(devices, disk)
devices.AssignController(disk, controller)
devices = append(devices, disk)
}
return devices, nil
}
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 {
+18
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 {
+3 -2
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 {
+1
View File
@@ -2,6 +2,7 @@ package main
import (
"fmt"
"github.com/hashicorp/packer/builder/vsphere/driver"
)
+3 -1
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,
},
+4 -3
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) {
+6 -1
View File
@@ -1,3 +1,4 @@
//go:generate struct-markdown
//go:generate mapstructure-to-hcl2 -type Config
package iso
@@ -24,6 +25,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,7 +34,10 @@ type Config struct {
common.ShutdownConfig `mapstructure:",squash"`
CreateSnapshot bool `mapstructure:"create_snapshot"`
// Create a snapshot when set to `true`, so the VM can be used as a base
// for linked clones. Defaults to `false`.
CreateSnapshot bool `mapstructure:"create_snapshot"`
// Convert VM to a template. Defaults to `false`.
ConvertToTemplate bool `mapstructure:"convert_to_template"`
ctx interpolate.Context

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