Compare commits

..

6 Commits

Author SHA1 Message Date
Megan Marsh e0e9b26457 moar fixed tests 2020-10-07 15:04:04 -07:00
Megan Marsh 155d6c2e32 more tests 2020-10-07 13:31:24 -07:00
Megan Marsh 105173a7c7 add moar tests 2020-10-07 11:50:28 -07:00
Megan Marsh b82704cc70 fix cd test 2020-10-07 11:32:00 -07:00
Megan Marsh c2b2bb2271 more tests 2020-10-06 16:55:54 -07:00
Megan Marsh 8445b6ff20 clean up test to get it working for old config 2020-10-06 16:05:52 -07:00
2282 changed files with 112541 additions and 225939 deletions
+4 -4
View File
@@ -7,7 +7,7 @@ version: 2.1
executors:
golang:
docker:
- image: docker.mirror.hashicorp.services/circleci/golang:1.15
- image: circleci/golang:1.15
resource_class: medium+
darwin:
macos:
@@ -153,7 +153,7 @@ jobs:
destination: /
build-website-docker-image:
docker:
- image: docker.mirror.hashicorp.services/circleci/buildpack-deps
- image: circleci/buildpack-deps
shell: /usr/bin/env bash -euo pipefail -c
steps:
- checkout
@@ -167,14 +167,14 @@ jobs:
echo "Dependencies have not changed, not building a new website docker image."
else
cd website/
docker login -u $WEBSITE_DOCKER_USER -p $WEBSITE_DOCKER_PASS
docker build -t hashicorp/packer-website:$IMAGE_TAG .
docker tag hashicorp/packer-website:$IMAGE_TAG hashicorp/packer-website:latest
docker login -u $WEBSITE_DOCKER_USER -p $WEBSITE_DOCKER_PASS
docker push hashicorp/packer-website
fi
algolia-index:
docker:
- image: docker.mirror.hashicorp.services/node:12
- image: node:12
steps:
- checkout
- run:
-1
View File
@@ -27,4 +27,3 @@ Thumbs.db
/packer.exe
.project
cache
/.vscode/
+3 -68
View File
@@ -1,46 +1,10 @@
## 1.6.6 (Upcoming)
### FEATURES:
* builder/azure-arm: Create keyvaults with SoftDelete enabled [GH-10210]
* builder/outscale: Add x509 certificate support [GH-10161]
* post-processor/yandex-export: Verify the access to a specific bucket [GH-10188]
## 1.6.5 (October 30, 2020)
### FEATURES:
* New Builder(s): Proxmox builder has been split into two new builders
`proxmox-iso` and `promox-clone`. See [Proxmox
Builder](https://packer.io/docs/builders/proxmox) for more information on
the builder. For users of the previous `proxmox` builder please use `packer
fix` to migrate your templates to the new `promox-iso` builder. [GH-9262]
## 1.6.5 (Upcoming)
### BUG FIXES:
* builder/amazon: SSM connection now recovers from reboots. [GH-10003]
* builder/azure-arm: Fix build failures due to the deletion of additional
managed disks defined in "disk_additional_size". [GH-10163]
* builder/azure-chroot: Fix typo in option `exlude_from_latest` to
`exclude_from_latest`. Old name will still be respected. [GH-10034]
* builder/googlecompute: Fix HCL image_encryption_key fields and use the same
casing in JSON and HCL2 [GH-10173]
* builder/openstack: Fix source image validation regression when using filters.
[GH-10065]
* builder/proxmox: Fix unhandled buildvar type for HCL2 enabled build
templates. [GH-10154]
* builder/qemu: Fix a regression where Packer would not wait properly in
step_shutdown when a null communicator was used. [GH-10178]
* builder/qemu: Fix crash in step_run of qemu when loading commhostport form
the statebag in a situation where the communicator is none. [GH-10145]
* builder/vsphere-clone: Packer was not respecting the "destroy" flag set in
the content library config, and always keeping the source vm. This has been
fixed. [GH-10165]
* builder/vsphere: Ensure builds are able to continue when no communicator has
been specified `"communicator": "none"`. [GH-9964]
* builder/vsphere: Fix CD uploads so that Packer does not try to delete a CD
that was not successfully uploaded. [GH-10155]
* core/hcl: Hide sensitive variables from output. [GH-10031]
* core/hcl: Packer HCL's "Coalesce" function now behaves same way as
* core/hcl2: Packer HCL's "Coalesce" function now behaves same way as
Terraform's. [GH-10016]
* core/HCL: Hide sensitive variables from output. [GH-10031]
* core: Fix artifact handling so that input artifacts are properly preserved in
postprocessors that don't modify artifacts. [GH-9996]
* core: Fix pathing in cd_files to copy proper directory tree when user
@@ -50,38 +14,9 @@
### IMPROVEMENTS:
* builder/amazon-ebssurrogate: Apply snapshot tags at snapshot creation time.
[GH-10150]
* builder/amazon: Add `io2` as a supported volume type. [GH-10102]
* builder/amazon: Add support for source instance tenancy [GH-10085]
* builder/google: Add service account impersonation. [GH-9968] [GH-10054]
* builder/googlecompute: Add `skip_create_image` option. [GH-10115]
* builder/googlecompute: Allow users to select the algorithm to use when
generating temporary SSH keypair [GH-10111]
* builder/linode: Add `state_timeout` attribute to Linode builder. [GH-10128]
* builder/oracle-oci: New option to specify image compartment separate from
build compartment. [GH-10040]
* builder/oracle-oci: New option to specify boot volume size. [GH-10017]
* builder/oracle: Add `base_image_filter` option as alternative to
`base_image_ocid` [GH-10116]
* builder/outscale: Migrate to new Outscale SDK. [GH-10056]
* builder/proxmox: split Proxmox into proxmox-iso and proxmox-clone. [GH-9626]
[GH-10166]
* builder/scaleway: Allow the user to use an image label (eg ubuntu_focal)
instead of a hardcoded UUID on the Scaleway builder. [GH-10061]
* builder/vsphere: Skip iso download if hashed file is already present on
remote datastore. [GH-10143]
* builder/yandex: Add support for IAM credentials in the token field and
YC_TOKEN environment variable. [GH-10158]
* core/hcl: Add ability to set version restrictions [GH-10149]
* core/hcl: Add build.name variable so users can access build name in addition
to source name. [GH-10114]
* core/hcl: Add consul_key function to HCL templates. [GH-10119]
* core/hcl: Add HCL2 aws_secretsmanager function [GH-10124]
* core/hcl: Add packer.version variable to hcl configs so users can access the
Packer release version. [GH-10117]
* core: Let user provide type of generated ssh key instead of always doing ssh-
rsa [GH-10101]
## 1.6.4 (September 30, 2020)
+1 -1
View File
@@ -1,4 +1,4 @@
FROM docker.mirror.hashicorp.services/ubuntu:16.04
FROM ubuntu:16.04
ENV DEBIAN_FRONTEND noninteractive
+4 -5
View File
@@ -1,5 +1,4 @@
TEST?=$(shell go list ./...)
COUNT?=1
VET?=$(shell go list ./...)
ACC_TEST_BUILDERS?=all
ACC_TEST_PROVISIONERS?=all
@@ -137,7 +136,7 @@ generate-check: generate ## Check go code generation is on par
fi
test: mode-check vet ## Run unit tests
@go test -count $(COUNT) $(TEST) $(TESTARGS) -timeout=3m
@go test $(TEST) $(TESTARGS) -timeout=3m
# acctest runs provisioners acceptance tests
provisioners-acctest: install-build-deps generate
@@ -146,14 +145,14 @@ provisioners-acctest: install-build-deps generate
# testacc runs acceptance tests
testacc: install-build-deps generate ## Run acceptance tests
@echo "WARN: Acceptance tests will take a long time to run and may cost money. Ctrl-C if you want to cancel."
PACKER_ACC=1 go test -count $(COUNT) -v $(TEST) $(TESTARGS) -timeout=120m
PACKER_ACC=1 go test -v $(TEST) $(TESTARGS) -timeout=45m
testrace: mode-check vet ## Test with race detection enabled
@GO111MODULE=off go test -count $(COUNT) -race $(TEST) $(TESTARGS) -timeout=3m -p=8
@GO111MODULE=off go test -race $(TEST) $(TESTARGS) -timeout=3m -p=8
# Runs code coverage and open a html page with report
cover:
go test -count $(COUNT) $(TEST) $(TESTARGS) -timeout=3m -coverprofile=coverage.out
go test $(TEST) $(TESTARGS) -timeout=3m -coverprofile=coverage.out
go tool cover -html=coverage.out
rm coverage.out
+3 -3
View File
@@ -11,8 +11,8 @@ import (
"time"
"github.com/aliyun/alibaba-cloud-sdk-go/services/ecs"
"github.com/hashicorp/packer/builder/alicloud/version"
"github.com/hashicorp/packer/packer-plugin-sdk/template/interpolate"
"github.com/hashicorp/packer/template/interpolate"
"github.com/hashicorp/packer/version"
"github.com/mitchellh/go-homedir"
)
@@ -78,7 +78,7 @@ func (c *AlicloudAccessConfig) Client() (*ClientWrapper, error) {
return nil, err
}
client.AppendUserAgent(Packer, version.AlicloudPluginVersion.FormattedVersion())
client.AppendUserAgent(Packer, version.FormattedVersion())
client.SetReadTimeout(DefaultRequestReadTimeout)
c.client = &ClientWrapper{client}
+6 -8
View File
@@ -9,13 +9,12 @@ import (
"fmt"
"github.com/hashicorp/hcl/v2/hcldec"
"github.com/hashicorp/packer/common"
"github.com/hashicorp/packer/helper/communicator"
"github.com/hashicorp/packer/helper/config"
"github.com/hashicorp/packer/helper/multistep"
"github.com/hashicorp/packer/packer"
"github.com/hashicorp/packer/packer-plugin-sdk/common"
"github.com/hashicorp/packer/packer-plugin-sdk/commonsteps"
"github.com/hashicorp/packer/packer-plugin-sdk/config"
"github.com/hashicorp/packer/packer-plugin-sdk/template/interpolate"
"github.com/hashicorp/packer/template/interpolate"
)
// The unique ID for this builder
@@ -47,7 +46,6 @@ func (b *Builder) ConfigSpec() hcldec.ObjectSpec { return b.config.FlatMapstruct
func (b *Builder) Prepare(raws ...interface{}) ([]string, []string, error) {
err := config.Decode(&b.config, &config.DecodeOpts{
PluginType: BuilderId,
Interpolate: true,
InterpolateContext: &b.config.ctx,
InterpolateFilter: &interpolate.RenderFilter{
@@ -165,8 +163,8 @@ func (b *Builder) Run(ctx context.Context, ui packer.Ui, hook packer.Hook) (pack
b.config.SSHPrivateIp),
SSHConfig: b.config.RunConfig.Comm.SSHConfigFunc(),
},
&commonsteps.StepProvision{},
&commonsteps.StepCleanupTempKeys{
&common.StepProvision{},
&common.StepCleanupTempKeys{
Comm: &b.config.RunConfig.Comm,
},
&stepStopAlicloudInstance{
@@ -207,7 +205,7 @@ func (b *Builder) Run(ctx context.Context, ui packer.Ui, hook packer.Hook) (pack
})
// Run!
b.runner = commonsteps.NewRunner(steps, b.config.PackerConfig, ui)
b.runner = common.NewRunner(steps, b.config.PackerConfig, ui)
b.runner.Run(ctx, state)
// If there was an error, return that
-6
View File
@@ -49,7 +49,6 @@ func (*FlatAlicloudDiskDevice) HCL2Spec() map[string]hcldec.Spec {
type FlatConfig struct {
PackerBuildName *string `mapstructure:"packer_build_name" cty:"packer_build_name" hcl:"packer_build_name"`
PackerBuilderType *string `mapstructure:"packer_builder_type" cty:"packer_builder_type" hcl:"packer_builder_type"`
PackerCoreVersion *string `mapstructure:"packer_core_version" cty:"packer_core_version" hcl:"packer_core_version"`
PackerDebug *bool `mapstructure:"packer_debug" cty:"packer_debug" hcl:"packer_debug"`
PackerForce *bool `mapstructure:"packer_force" cty:"packer_force" hcl:"packer_force"`
PackerOnError *string `mapstructure:"packer_on_error" cty:"packer_on_error" hcl:"packer_on_error"`
@@ -108,8 +107,6 @@ type FlatConfig struct {
SSHPassword *string `mapstructure:"ssh_password" cty:"ssh_password" hcl:"ssh_password"`
SSHKeyPairName *string `mapstructure:"ssh_keypair_name" undocumented:"true" cty:"ssh_keypair_name" hcl:"ssh_keypair_name"`
SSHTemporaryKeyPairName *string `mapstructure:"temporary_key_pair_name" undocumented:"true" cty:"temporary_key_pair_name" hcl:"temporary_key_pair_name"`
SSHTemporaryKeyPairType *string `mapstructure:"temporary_key_pair_type" cty:"temporary_key_pair_type" hcl:"temporary_key_pair_type"`
SSHTemporaryKeyPairBits *int `mapstructure:"temporary_key_pair_bits" cty:"temporary_key_pair_bits" hcl:"temporary_key_pair_bits"`
SSHCiphers []string `mapstructure:"ssh_ciphers" cty:"ssh_ciphers" hcl:"ssh_ciphers"`
SSHClearAuthorizedKeys *bool `mapstructure:"ssh_clear_authorized_keys" cty:"ssh_clear_authorized_keys" hcl:"ssh_clear_authorized_keys"`
SSHKEXAlgos []string `mapstructure:"ssh_key_exchange_algorithms" cty:"ssh_key_exchange_algorithms" hcl:"ssh_key_exchange_algorithms"`
@@ -166,7 +163,6 @@ func (*FlatConfig) HCL2Spec() map[string]hcldec.Spec {
s := map[string]hcldec.Spec{
"packer_build_name": &hcldec.AttrSpec{Name: "packer_build_name", Type: cty.String, Required: false},
"packer_builder_type": &hcldec.AttrSpec{Name: "packer_builder_type", Type: cty.String, Required: false},
"packer_core_version": &hcldec.AttrSpec{Name: "packer_core_version", Type: cty.String, Required: false},
"packer_debug": &hcldec.AttrSpec{Name: "packer_debug", Type: cty.Bool, Required: false},
"packer_force": &hcldec.AttrSpec{Name: "packer_force", Type: cty.Bool, Required: false},
"packer_on_error": &hcldec.AttrSpec{Name: "packer_on_error", Type: cty.String, Required: false},
@@ -225,8 +221,6 @@ func (*FlatConfig) HCL2Spec() map[string]hcldec.Spec {
"ssh_password": &hcldec.AttrSpec{Name: "ssh_password", Type: cty.String, Required: false},
"ssh_keypair_name": &hcldec.AttrSpec{Name: "ssh_keypair_name", Type: cty.String, Required: false},
"temporary_key_pair_name": &hcldec.AttrSpec{Name: "temporary_key_pair_name", Type: cty.String, Required: false},
"temporary_key_pair_type": &hcldec.AttrSpec{Name: "temporary_key_pair_type", Type: cty.String, Required: false},
"temporary_key_pair_bits": &hcldec.AttrSpec{Name: "temporary_key_pair_bits", Type: cty.Number, Required: false},
"ssh_ciphers": &hcldec.AttrSpec{Name: "ssh_ciphers", Type: cty.List(cty.String), Required: false},
"ssh_clear_authorized_keys": &hcldec.AttrSpec{Name: "ssh_clear_authorized_keys", Type: cty.Bool, Required: false},
"ssh_key_exchange_algorithms": &hcldec.AttrSpec{Name: "ssh_key_exchange_algorithms", Type: cty.List(cty.String), Required: false},
+1 -1
View File
@@ -4,8 +4,8 @@ import (
"reflect"
"testing"
helperconfig "github.com/hashicorp/packer/helper/config"
"github.com/hashicorp/packer/packer"
helperconfig "github.com/hashicorp/packer/packer-plugin-sdk/config"
)
func testBuilderConfig() map[string]interface{} {
+83 -43
View File
@@ -8,12 +8,10 @@ import (
"strings"
"github.com/hashicorp/packer/hcl2template"
"github.com/hashicorp/packer/packer-plugin-sdk/config"
"github.com/hashicorp/packer/packer-plugin-sdk/template/interpolate"
"github.com/hashicorp/packer/helper/config"
"github.com/hashicorp/packer/template/interpolate"
)
// The "AlicloudDiskDevice" object us used for the `ECSSystemDiskMapping` and
// `ECSImagesDiskMappings` options, and contains the following fields:
type AlicloudDiskDevice struct {
// The value of disk name is blank by default. [2,
// 128] English or Chinese characters, must begin with an
@@ -21,7 +19,8 @@ type AlicloudDiskDevice struct {
// ., _ and -. The disk name will appear on the console. It cannot
// begin with `http://` or `https://`.
DiskName string `mapstructure:"disk_name" required:"false"`
// Category of the system disk. Optional values are:
// Category of the system disk. Optional values
// are:
// - cloud - general cloud disk
// - cloud_efficiency - efficiency cloud disk
// - cloud_ssd - cloud SSD
@@ -33,8 +32,6 @@ type AlicloudDiskDevice struct {
// Snapshots are used to create the data
// disk After this parameter is specified, Size is ignored. The actual
// size of the created disk is the size of the specified snapshot.
// This field is only used in the ECSImagesDiskMappings option, not
// the ECSSystemDiskMapping option.
SnapshotId string `mapstructure:"disk_snapshot_id" required:"false"`
// The value of disk description is blank by
// default. [2, 256] characters. The disk description will appear on the
@@ -47,51 +44,94 @@ type AlicloudDiskDevice struct {
// such as /dev/xvdb It is null unless the Status is In_use.
Device string `mapstructure:"disk_device" required:"false"`
// Whether or not to encrypt the data disk.
// If this option is set to true, the data disk will be encryped and
// corresponding snapshot in the target image will also be encrypted. By
// If this option is set to true, the data disk will be encryped and corresponding snapshot in the target image will also be encrypted. By
// default, if this is an extra data disk, Packer will not encrypt the
// data disk. Otherwise, Packer will keep the encryption setting to what
// it was in the source image. Please refer to Introduction of ECS disk
// encryption for more details.
// it was in the source image. Please refer to Introduction of ECS disk encryption
// for more details.
Encrypted config.Trilean `mapstructure:"disk_encrypted" required:"false"`
}
// The "AlicloudDiskDevices" object is used to define disk mappings for your
// instance.
type AlicloudDiskDevices struct {
// Image disk mapping for the system disk.
// See the [disk device configuration](#disk-devices-configuration) section
// for more information on options.
// Usage example:
// Image disk mapping for system
// disk.
// - `disk_category` (string) - Category of the system disk. Optional values
// are:
// - `cloud` - general cloud disk
// - `cloud_efficiency` - efficiency cloud disk
// - `cloud_ssd` - cloud SSD
//
// For phased-out instance types and non-I/O optimized instances, the
// default value is cloud. Otherwise, the default value is
// cloud\_efficiency.
//
// - `disk_description` (string) - The value of disk description is blank by
// default. \[2, 256\] characters. The disk description will appear on the
// console. It cannot begin with `http://` or `https://`.
//
// - `disk_name` (string) - The value of disk name is blank by default. \[2,
// 128\] English or Chinese characters, must begin with an
// uppercase/lowercase letter or Chinese character. Can contain numbers,
// `.`, `_` and `-`. The disk name will appear on the console. It cannot
// begin with `http://` or `https://`.
//
// - `disk_size` (number) - Size of the system disk, measured in GiB. Value
// range: \[20, 500\]. The specified value must be equal to or greater
// than max{20, ImageSize}. Default value: max{40, ImageSize}.
//
// ```json
// "builders": [{
// "type":"alicloud-ecs",
// "system_disk_mapping": {
// "disk_size": 50,
// "disk_name": "mydisk"
// },
// ...
// }
// ```
ECSSystemDiskMapping AlicloudDiskDevice `mapstructure:"system_disk_mapping" required:"false"`
// Add one or more data disks to the image.
// See the [disk device configuration](#disk-devices-configuration) section
// for more information on options.
// Usage example:
// Add one or more data
// disks to the image.
//
// - `disk_category` (string) - Category of the data disk. Optional values
// are:
// - `cloud` - general cloud disk
// - `cloud_efficiency` - efficiency cloud disk
// - `cloud_ssd` - cloud SSD
//
// Default value: cloud.
//
// - `disk_delete_with_instance` (boolean) - Whether or not the disk is
// released along with the instance:
// - True indicates that when the instance is released, this disk will
// be released with it
// - False indicates that when the instance is released, this disk will
// be retained.
// - `disk_description` (string) - The value of disk description is blank by
// default. \[2, 256\] characters. The disk description will appear on the
// console. It cannot begin with `http://` or `https://`.
//
// - `disk_device` (string) - Device information of the related instance:
// such as `/dev/xvdb` It is null unless the Status is In\_use.
//
// - `disk_name` (string) - The value of disk name is blank by default. \[2,
// 128\] English or Chinese characters, must begin with an
// uppercase/lowercase letter or Chinese character. Can contain numbers,
// `.`, `_` and `-`. The disk name will appear on the console. It cannot
// begin with `http://` or `https://`.
//
// - `disk_size` (number) - Size of the data disk, in GB, values range:
// - `cloud` - 5 \~ 2000
// - `cloud_efficiency` - 20 \~ 2048
// - `cloud_ssd` - 20 \~ 2048
//
// The value should be equal to or greater than the size of the specific
// SnapshotId.
//
// - `disk_snapshot_id` (string) - Snapshots are used to create the data
// disk After this parameter is specified, Size is ignored. The actual
// size of the created disk is the size of the specified snapshot.
//
// Snapshots from on or before July 15, 2013 cannot be used to create a
// disk.
//
// - `disk_encrypted` (boolean) - Whether or not to encrypt the data disk.
// If this option is set to true, the data disk will be encryped and corresponding snapshot in the target image will also be encrypted. By
// default, if this is an extra data disk, Packer will not encrypt the
// data disk. Otherwise, Packer will keep the encryption setting to what
// it was in the source image. Please refer to Introduction of [ECS disk encryption](https://www.alibabacloud.com/help/doc-detail/59643.htm)
// for more details.
//
// ```json
// "builders": [{
// "type":"alicloud-ecs",
// "image_disk_mappings": [
// {
// "disk_snapshot_id": "someid",
// "disk_device": "dev/xvdb"
// }
// ],
// ...
// }
// ```
ECSImagesDiskMappings []AlicloudDiskDevice `mapstructure:"image_disk_mappings" required:"false"`
}
+3 -3
View File
@@ -8,10 +8,10 @@ import (
"os"
"strings"
"github.com/hashicorp/packer/common/uuid"
"github.com/hashicorp/packer/helper/communicator"
"github.com/hashicorp/packer/packer-plugin-sdk/config"
"github.com/hashicorp/packer/packer-plugin-sdk/template/interpolate"
"github.com/hashicorp/packer/packer-plugin-sdk/uuid"
"github.com/hashicorp/packer/helper/config"
"github.com/hashicorp/packer/template/interpolate"
)
type RunConfig struct {
+1 -1
View File
@@ -5,7 +5,7 @@ import (
"fmt"
"github.com/aliyun/alibaba-cloud-sdk-go/sdk/errors"
"github.com/hashicorp/packer/packer-plugin-sdk/uuid"
"github.com/hashicorp/packer/common/uuid"
"github.com/aliyun/alibaba-cloud-sdk-go/sdk/responses"
"github.com/aliyun/alibaba-cloud-sdk-go/services/ecs"
@@ -6,9 +6,9 @@ import (
"github.com/aliyun/alibaba-cloud-sdk-go/sdk/responses"
"github.com/aliyun/alibaba-cloud-sdk-go/services/ecs"
"github.com/hashicorp/packer/common/uuid"
"github.com/hashicorp/packer/helper/multistep"
"github.com/hashicorp/packer/packer"
"github.com/hashicorp/packer/packer-plugin-sdk/uuid"
)
type stepConfigAlicloudSecurityGroup struct {
+1 -1
View File
@@ -7,9 +7,9 @@ import (
"github.com/aliyun/alibaba-cloud-sdk-go/sdk/responses"
"github.com/aliyun/alibaba-cloud-sdk-go/services/ecs"
"github.com/hashicorp/packer/common/uuid"
"github.com/hashicorp/packer/helper/multistep"
"github.com/hashicorp/packer/packer"
"github.com/hashicorp/packer/packer-plugin-sdk/uuid"
)
type stepConfigAlicloudVPC struct {
+1 -1
View File
@@ -6,9 +6,9 @@ import (
"github.com/aliyun/alibaba-cloud-sdk-go/sdk/responses"
"github.com/aliyun/alibaba-cloud-sdk-go/services/ecs"
"github.com/hashicorp/packer/common/uuid"
"github.com/hashicorp/packer/helper/multistep"
"github.com/hashicorp/packer/packer"
"github.com/hashicorp/packer/packer-plugin-sdk/uuid"
)
type stepConfigAlicloudVSwitch struct {
+2 -2
View File
@@ -5,13 +5,13 @@ import (
"fmt"
"time"
"github.com/hashicorp/packer/packer-plugin-sdk/random"
"github.com/hashicorp/packer/common/random"
"github.com/aliyun/alibaba-cloud-sdk-go/sdk/responses"
"github.com/aliyun/alibaba-cloud-sdk-go/services/ecs"
"github.com/hashicorp/packer/common/uuid"
"github.com/hashicorp/packer/helper/multistep"
"github.com/hashicorp/packer/packer"
"github.com/hashicorp/packer/packer-plugin-sdk/uuid"
)
type stepCreateAlicloudImage struct {
+2 -2
View File
@@ -7,14 +7,14 @@ import (
"io/ioutil"
"strconv"
"github.com/hashicorp/packer/packer-plugin-sdk/uuid"
"github.com/hashicorp/packer/common/uuid"
"github.com/aliyun/alibaba-cloud-sdk-go/sdk/requests"
"github.com/aliyun/alibaba-cloud-sdk-go/sdk/responses"
"github.com/aliyun/alibaba-cloud-sdk-go/services/ecs"
confighelper "github.com/hashicorp/packer/helper/config"
"github.com/hashicorp/packer/helper/multistep"
"github.com/hashicorp/packer/packer"
confighelper "github.com/hashicorp/packer/packer-plugin-sdk/config"
)
type stepCreateAlicloudInstance struct {
@@ -7,9 +7,9 @@ import (
"github.com/aliyun/alibaba-cloud-sdk-go/sdk/requests"
"github.com/aliyun/alibaba-cloud-sdk-go/services/ecs"
confighelper "github.com/hashicorp/packer/helper/config"
"github.com/hashicorp/packer/helper/multistep"
"github.com/hashicorp/packer/packer"
confighelper "github.com/hashicorp/packer/packer-plugin-sdk/config"
)
type stepRegionCopyAlicloudImage struct {
-13
View File
@@ -1,13 +0,0 @@
package version
import (
"github.com/hashicorp/packer/helper/version"
packerVersion "github.com/hashicorp/packer/version"
)
var AlicloudPluginVersion *version.PluginVersion
func init() {
AlicloudPluginVersion = version.InitializePluginVersion(
packerVersion.Version, packerVersion.VersionPrerelease)
}
+7 -12
View File
@@ -14,16 +14,15 @@ import (
"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"
"github.com/hashicorp/packer/hcl2template"
"github.com/hashicorp/packer/helper/config"
"github.com/hashicorp/packer/helper/multistep"
"github.com/hashicorp/packer/packer"
"github.com/hashicorp/packer/packer-plugin-sdk/chroot"
"github.com/hashicorp/packer/packer-plugin-sdk/common"
"github.com/hashicorp/packer/packer-plugin-sdk/commonsteps"
"github.com/hashicorp/packer/packer-plugin-sdk/config"
"github.com/hashicorp/packer/packer-plugin-sdk/packerbuilderdata"
"github.com/hashicorp/packer/packer-plugin-sdk/template/interpolate"
"github.com/hashicorp/packer/template/interpolate"
)
// The unique ID for this builder
@@ -195,18 +194,14 @@ func (b *Builder) ConfigSpec() hcldec.ObjectSpec { return b.config.FlatMapstruct
func (b *Builder) Prepare(raws ...interface{}) ([]string, []string, error) {
b.config.ctx.Funcs = awscommon.TemplateFuncs
err := config.Decode(&b.config, &config.DecodeOpts{
PluginType: BuilderId,
Interpolate: true,
InterpolateContext: &b.config.ctx,
InterpolateFilter: &interpolate.RenderFilter{
Exclude: []string{
"ami_description",
"snapshot_tags",
"snapshot_tag",
"tags",
"tag",
"root_volume_tags",
"root_volume_tag",
"command_wrapper",
"post_mount_commands",
"pre_mount_commands",
@@ -373,7 +368,7 @@ func (b *Builder) Run(ctx context.Context, ui packer.Ui, hook packer.Hook) (pack
state.Put("hook", hook)
state.Put("ui", ui)
state.Put("wrappedCommand", common.CommandWrapper(wrappedCommand))
generatedData := &packerbuilderdata.GeneratedData{State: state}
generatedData := &builder.GeneratedData{State: state}
// Build the steps
steps := []multistep.Step{
@@ -479,7 +474,7 @@ func (b *Builder) Run(ctx context.Context, ui packer.Ui, hook packer.Hook) (pack
)
// Run!
b.runner = commonsteps.NewRunner(steps, b.config.PackerConfig, ui)
b.runner = common.NewRunner(steps, b.config.PackerConfig, ui)
b.runner.Run(ctx, state)
// If there was an error, return that
@@ -13,7 +13,6 @@ import (
type FlatConfig struct {
PackerBuildName *string `mapstructure:"packer_build_name" cty:"packer_build_name" hcl:"packer_build_name"`
PackerBuilderType *string `mapstructure:"packer_builder_type" cty:"packer_builder_type" hcl:"packer_builder_type"`
PackerCoreVersion *string `mapstructure:"packer_core_version" cty:"packer_core_version" hcl:"packer_core_version"`
PackerDebug *bool `mapstructure:"packer_debug" cty:"packer_debug" hcl:"packer_debug"`
PackerForce *bool `mapstructure:"packer_force" cty:"packer_force" hcl:"packer_force"`
PackerOnError *string `mapstructure:"packer_on_error" cty:"packer_on_error" hcl:"packer_on_error"`
@@ -93,7 +92,6 @@ func (*FlatConfig) HCL2Spec() map[string]hcldec.Spec {
s := map[string]hcldec.Spec{
"packer_build_name": &hcldec.AttrSpec{Name: "packer_build_name", Type: cty.String, Required: false},
"packer_builder_type": &hcldec.AttrSpec{Name: "packer_builder_type", Type: cty.String, Required: false},
"packer_core_version": &hcldec.AttrSpec{Name: "packer_core_version", Type: cty.String, Required: false},
"packer_debug": &hcldec.AttrSpec{Name: "packer_debug", Type: cty.Bool, Required: false},
"packer_force": &hcldec.AttrSpec{Name: "packer_force", Type: cty.Bool, Required: false},
"packer_on_error": &hcldec.AttrSpec{Name: "packer_on_error", Type: cty.String, Required: false},
+1 -1
View File
@@ -7,7 +7,7 @@ import (
"runtime"
"testing"
"github.com/hashicorp/packer/packer-plugin-sdk/common"
"github.com/hashicorp/packer/common"
)
func TestCopyFile(t *testing.T) {
@@ -3,7 +3,7 @@ package chroot
import (
"testing"
"github.com/hashicorp/packer/packer-plugin-sdk/chroot"
"github.com/hashicorp/packer/common/chroot"
)
func TestAttachVolumeCleanupFunc_ImplementsCleanupFunc(t *testing.T) {
+1 -1
View File
@@ -11,7 +11,7 @@ import (
awscommon "github.com/hashicorp/packer/builder/amazon/common"
"github.com/hashicorp/packer/helper/multistep"
"github.com/hashicorp/packer/packer"
"github.com/hashicorp/packer/packer-plugin-sdk/template/interpolate"
"github.com/hashicorp/packer/template/interpolate"
)
// StepCreateVolume creates a new volume from the snapshot of the root
+1 -1
View File
@@ -5,9 +5,9 @@ import (
"fmt"
"log"
"github.com/hashicorp/packer/common/chroot"
"github.com/hashicorp/packer/helper/multistep"
"github.com/hashicorp/packer/packer"
"github.com/hashicorp/packer/packer-plugin-sdk/chroot"
)
// StepEarlyUnflock unlocks the flock.
+1 -1
View File
@@ -3,7 +3,7 @@ package chroot
import (
"testing"
"github.com/hashicorp/packer/packer-plugin-sdk/chroot"
"github.com/hashicorp/packer/common/chroot"
)
func TestFlockCleanupFunc_ImplementsCleanupFunc(t *testing.T) {
+4 -4
View File
@@ -10,11 +10,11 @@ import (
"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"
"github.com/hashicorp/packer/packer-plugin-sdk/common"
"github.com/hashicorp/packer/packer-plugin-sdk/packerbuilderdata"
"github.com/hashicorp/packer/packer-plugin-sdk/template/interpolate"
"github.com/hashicorp/packer/template/interpolate"
)
type mountPathData struct {
@@ -31,7 +31,7 @@ type StepMountDevice struct {
MountPartition string
mountPath string
GeneratedData *packerbuilderdata.GeneratedData
GeneratedData *builder.GeneratedData
}
func (s *StepMountDevice) Run(ctx context.Context, state multistep.StateBag) multistep.StepAction {
@@ -3,7 +3,7 @@ package chroot
import (
"testing"
"github.com/hashicorp/packer/packer-plugin-sdk/chroot"
"github.com/hashicorp/packer/common/chroot"
)
func TestMountDeviceCleanupFunc_ImplementsCleanupFunc(t *testing.T) {
+2 -2
View File
@@ -6,14 +6,14 @@ import (
"log"
"os"
"github.com/hashicorp/packer/builder"
"github.com/hashicorp/packer/helper/multistep"
"github.com/hashicorp/packer/packer"
"github.com/hashicorp/packer/packer-plugin-sdk/packerbuilderdata"
)
// StepPrepareDevice finds an available device and sets it.
type StepPrepareDevice struct {
GeneratedData *packerbuilderdata.GeneratedData
GeneratedData *builder.GeneratedData
}
func (s *StepPrepareDevice) Run(ctx context.Context, state multistep.StateBag) multistep.StepAction {
+2 -2
View File
@@ -7,10 +7,10 @@ import (
"github.com/aws/aws-sdk-go/aws"
"github.com/aws/aws-sdk-go/service/ec2"
awscommon "github.com/hashicorp/packer/builder/amazon/common"
"github.com/hashicorp/packer/common/random"
confighelper "github.com/hashicorp/packer/helper/config"
"github.com/hashicorp/packer/helper/multistep"
"github.com/hashicorp/packer/packer"
confighelper "github.com/hashicorp/packer/packer-plugin-sdk/config"
"github.com/hashicorp/packer/packer-plugin-sdk/random"
)
// StepRegisterAMI creates the AMI.
@@ -4,7 +4,7 @@ import (
"testing"
amazon "github.com/hashicorp/packer/builder/amazon/common"
"github.com/hashicorp/packer/packer-plugin-sdk/common"
"github.com/hashicorp/packer/common"
"github.com/aws/aws-sdk-go/aws"
"github.com/aws/aws-sdk-go/service/ec2"
+2 -3
View File
@@ -17,8 +17,7 @@ import (
"github.com/aws/aws-sdk-go/service/ec2/ec2iface"
awsbase "github.com/hashicorp/aws-sdk-go-base"
cleanhttp "github.com/hashicorp/go-cleanhttp"
"github.com/hashicorp/packer/builder/amazon/common/awserrors"
"github.com/hashicorp/packer/packer-plugin-sdk/template/interpolate"
"github.com/hashicorp/packer/template/interpolate"
vaultapi "github.com/hashicorp/vault/api"
)
@@ -272,7 +271,7 @@ func (c *AccessConfig) Session() (*session.Session, error) {
cp, err := c.session.Config.Credentials.Get()
if awserrors.Matches(err, "NoCredentialProviders", "") {
if IsAWSErr(err, "NoCredentialProviders", "") {
return nil, c.NewNoValidCredentialSourcesError(err)
}
+2 -2
View File
@@ -8,8 +8,8 @@ import (
"regexp"
"github.com/hashicorp/packer/hcl2template"
"github.com/hashicorp/packer/packer-plugin-sdk/config"
"github.com/hashicorp/packer/packer-plugin-sdk/template/interpolate"
"github.com/hashicorp/packer/helper/config"
"github.com/hashicorp/packer/template/interpolate"
)
// AMIConfig is for common configuration related to creating AMIs.
+1 -1
View File
@@ -8,7 +8,7 @@ import (
"github.com/aws/aws-sdk-go/aws"
"github.com/aws/aws-sdk-go/service/ec2"
"github.com/aws/aws-sdk-go/service/ec2/ec2iface"
"github.com/hashicorp/packer/packer-plugin-sdk/config"
"github.com/hashicorp/packer/helper/config"
)
func testAMIConfig() *AMIConfig {
-18
View File
@@ -1,18 +0,0 @@
package awserrors
import (
"strings"
"github.com/aws/aws-sdk-go/aws/awserr"
)
// Returns true if the err matches all these conditions:
// * err is of type awserr.Error
// * Error.Code() matches code
// * Error.Message() contains message
func Matches(err error, code string, message string) bool {
if err, ok := err.(awserr.Error); ok {
return err.Code() == code && strings.Contains(err.Message(), message)
}
return false
}
+4 -4
View File
@@ -9,8 +9,8 @@ import (
"github.com/aws/aws-sdk-go/aws"
"github.com/aws/aws-sdk-go/service/ec2"
"github.com/hashicorp/packer/packer-plugin-sdk/config"
"github.com/hashicorp/packer/packer-plugin-sdk/template/interpolate"
"github.com/hashicorp/packer/helper/config"
"github.com/hashicorp/packer/template/interpolate"
)
// These will be attached when launching your instance. Your
@@ -134,8 +134,8 @@ func (blockDevice BlockDevice) BuildEC2BlockDeviceMapping() *ec2.BlockDeviceMapp
ebsBlockDevice.VolumeSize = aws.Int64(blockDevice.VolumeSize)
}
// IOPS is only valid for io1 and io2 types
if blockDevice.VolumeType == "io1" || blockDevice.VolumeType == "io2" {
// IOPS is only valid for io1 type
if blockDevice.VolumeType == "io1" {
ebsBlockDevice.Iops = aws.Int64(blockDevice.IOPS)
}
+1 -20
View File
@@ -6,7 +6,7 @@ import (
"github.com/aws/aws-sdk-go/aws"
"github.com/aws/aws-sdk-go/service/ec2"
"github.com/google/go-cmp/cmp"
"github.com/hashicorp/packer/packer-plugin-sdk/config"
"github.com/hashicorp/packer/helper/config"
)
func TestBlockDevice(t *testing.T) {
@@ -66,25 +66,6 @@ func TestBlockDevice(t *testing.T) {
},
},
},
{
Config: &BlockDevice{
DeviceName: "/dev/sdb",
VolumeType: "io2",
VolumeSize: 8,
DeleteOnTermination: true,
IOPS: 1000,
},
Result: &ec2.BlockDeviceMapping{
DeviceName: aws.String("/dev/sdb"),
Ebs: &ec2.EbsBlockDevice{
VolumeType: aws.String("io2"),
VolumeSize: aws.Int64(8),
DeleteOnTermination: aws.Bool(true),
Iops: aws.Int64(1000),
},
},
},
{
Config: &BlockDevice{
DeviceName: "/dev/sdb",
+16 -4
View File
@@ -4,12 +4,13 @@ import (
"context"
"fmt"
"log"
"strings"
"time"
"github.com/aws/aws-sdk-go/aws"
"github.com/aws/aws-sdk-go/aws/awserr"
"github.com/aws/aws-sdk-go/service/ec2"
"github.com/hashicorp/packer/builder/amazon/common/awserrors"
"github.com/hashicorp/packer/packer-plugin-sdk/retry"
"github.com/hashicorp/packer/common/retry"
)
// DestroyAMIs deregisters the AWS machine images in imageids from an active AWS account
@@ -30,7 +31,7 @@ func DestroyAMIs(imageids []*string, ec2conn *ec2.EC2) error {
err = retry.Config{
Tries: 11,
ShouldRetry: func(err error) bool {
return awserrors.Matches(err, "UnauthorizedOperation", "")
return IsAWSErr(err, "UnauthorizedOperation", "")
},
RetryDelay: (&retry.Backoff{InitialBackoff: 200 * time.Millisecond, MaxBackoff: 30 * time.Second, Multiplier: 2}).Linear,
}.Run(ctx, func(ctx context.Context) error {
@@ -53,7 +54,7 @@ func DestroyAMIs(imageids []*string, ec2conn *ec2.EC2) error {
err = retry.Config{
Tries: 11,
ShouldRetry: func(err error) bool {
return awserrors.Matches(err, "UnauthorizedOperation", "")
return IsAWSErr(err, "UnauthorizedOperation", "")
},
RetryDelay: (&retry.Backoff{InitialBackoff: 200 * time.Millisecond, MaxBackoff: 30 * time.Second, Multiplier: 2}).Linear,
}.Run(ctx, func(ctx context.Context) error {
@@ -73,3 +74,14 @@ func DestroyAMIs(imageids []*string, ec2conn *ec2.EC2) error {
}
return nil
}
// Returns true if the error matches all these conditions:
// * err is of type awserr.Error
// * Error.Code() matches code
// * Error.Message() contains message
func IsAWSErr(err error, code string, message string) bool {
if err, ok := err.(awserr.Error); ok {
return err.Code() == code && strings.Contains(err.Message(), message)
}
return false
}
@@ -3,8 +3,8 @@ package common
import (
"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"
"github.com/hashicorp/packer/packer-plugin-sdk/packerbuilderdata"
)
type BuildInfoTemplate struct {
@@ -17,7 +17,7 @@ type BuildInfoTemplate struct {
SourceAMITags map[string]string
}
func extractBuildInfo(region string, state multistep.StateBag, generatedData *packerbuilderdata.GeneratedData) *BuildInfoTemplate {
func extractBuildInfo(region string, state multistep.StateBag, generatedData *builder.GeneratedData) *BuildInfoTemplate {
rawSourceAMI, hasSourceAMI := state.GetOk("source_image")
if !hasSourceAMI {
return &BuildInfoTemplate{
@@ -6,8 +6,8 @@ import (
"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"
"github.com/hashicorp/packer/packer-plugin-sdk/packerbuilderdata"
)
func testImage() *ec2.Image {
@@ -17,7 +17,6 @@ func testImage() *ec2.Image {
Name: aws.String("ami_test_name"),
OwnerId: aws.String("ami_test_owner_id"),
ImageOwnerAlias: aws.String("ami_test_owner_alias"),
RootDeviceType: aws.String("ebs"),
Tags: []*ec2.Tag{
{
Key: aws.String("key-1"),
@@ -36,8 +35,8 @@ func testState() multistep.StateBag {
return state
}
func testGeneratedData(state multistep.StateBag) packerbuilderdata.GeneratedData {
generatedData := packerbuilderdata.GeneratedData{State: state}
func testGeneratedData(state multistep.StateBag) builder.GeneratedData {
generatedData := builder.GeneratedData{State: state}
return generatedData
}
+6 -15
View File
@@ -11,10 +11,10 @@ import (
"strings"
"time"
"github.com/hashicorp/packer/common/uuid"
"github.com/hashicorp/packer/hcl2template"
"github.com/hashicorp/packer/helper/communicator"
"github.com/hashicorp/packer/packer-plugin-sdk/template/interpolate"
"github.com/hashicorp/packer/packer-plugin-sdk/uuid"
"github.com/hashicorp/packer/template/interpolate"
)
var reShutdownBehavior = regexp.MustCompile("^(stop|terminate)$")
@@ -376,12 +376,6 @@ type RunConfig struct {
// subnet-12345def, where Packer will launch the EC2 instance. This field is
// required if you are using an non-default VPC.
SubnetId string `mapstructure:"subnet_id" required:"false"`
// [Tenancy](https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/dedicated-instance.html) used
// when Packer launches the EC2 instance, allowing it to be launched on dedicated hardware.
//
// The default is "default", meaning shared tenancy. Allowed values are "default",
// "dedicated" and "host".
Tenancy string `mapstructure:"tenancy" required:"false"`
// The name of the temporary key pair to
// generate. By default, Packer generates a name that looks like
// `packer_<UUID>`, where &lt;UUID&gt; is a 36 character unique identifier.
@@ -548,6 +542,10 @@ func (c *RunConfig) Prepare(ctx *interpolate.Context) []error {
msg := fmt.Errorf(`no iam_instance_profile defined; session_manager connectivity requires a valid instance profile with AmazonSSMManagedInstanceCore permissions. Alternatively a temporary_iam_instance_profile_policy_document can be used.`)
errs = append(errs, msg)
}
if c.PauseBeforeSSM == 0 {
c.PauseBeforeSSM = 10 * time.Second
}
}
if c.Comm.SSHKeyPairName != "" {
@@ -633,13 +631,6 @@ func (c *RunConfig) Prepare(ctx *interpolate.Context) []error {
}
}
if c.Tenancy != "" &&
c.Tenancy != "default" &&
c.Tenancy != "dedicated" &&
c.Tenancy != "host" {
errs = append(errs, fmt.Errorf("Error: Unknown tenancy type %s", c.Tenancy))
}
return errs
}
-20
View File
@@ -232,23 +232,3 @@ func TestRunConfigPrepare_TemporaryKeyPairName(t *testing.T) {
t.Fatal("keypair name does not match")
}
}
func TestRunConfigPrepare_TenancyBad(t *testing.T) {
c := testConfig()
c.Tenancy = "not_real"
if err := c.Prepare(nil); len(err) != 1 {
t.Fatal("Should error if tenancy is set to an invalid type")
}
}
func TestRunConfigPrepare_TenancyGood(t *testing.T) {
validTenancy := []string{"", "default", "dedicated", "host"}
for _, vt := range validTenancy {
c := testConfig()
c.Tenancy = vt
if err := c.Prepare(nil); len(err) != 0 {
t.Fatalf("Should not error if tenancy is set to %s", vt)
}
}
}
-117
View File
@@ -1,117 +0,0 @@
package ssm
import (
"context"
"encoding/json"
"fmt"
"log"
"os/exec"
"strconv"
"time"
"github.com/aws/aws-sdk-go/aws"
"github.com/aws/aws-sdk-go/service/ssm"
"github.com/aws/aws-sdk-go/service/ssm/ssmiface"
"github.com/hashicorp/packer/builder/amazon/common/awserrors"
"github.com/hashicorp/packer/packer"
"github.com/hashicorp/packer/packer-plugin-sdk/retry"
"github.com/hashicorp/packer/packer-plugin-sdk/shell-local/localexec"
)
type Session struct {
SvcClient ssmiface.SSMAPI
Region string
InstanceID string
LocalPort, RemotePort int
}
func (s Session) buildTunnelInput() *ssm.StartSessionInput {
portNumber, localPortNumber := strconv.Itoa(s.RemotePort), strconv.Itoa(s.LocalPort)
params := map[string][]*string{
"portNumber": []*string{aws.String(portNumber)},
"localPortNumber": []*string{aws.String(localPortNumber)},
}
return &ssm.StartSessionInput{
DocumentName: aws.String("AWS-StartPortForwardingSession"),
Parameters: params,
Target: aws.String(s.InstanceID),
}
}
// getCommand return a valid ordered set of arguments to pass to the driver command.
func (s Session) getCommand(ctx context.Context) ([]string, string, error) {
input := s.buildTunnelInput()
var session *ssm.StartSessionOutput
err := retry.Config{
ShouldRetry: func(err error) bool { return awserrors.Matches(err, "TargetNotConnected", "") },
RetryDelay: (&retry.Backoff{InitialBackoff: 200 * time.Millisecond, MaxBackoff: 60 * time.Second, Multiplier: 2}).Linear,
}.Run(ctx, func(ctx context.Context) (err error) {
session, err = s.SvcClient.StartSessionWithContext(ctx, input)
return err
})
if err != nil {
return nil, "", err
}
if session == nil {
return nil, "", fmt.Errorf("an active Amazon SSM Session is required before trying to open a session tunnel")
}
// AWS session-manager-plugin requires a valid session be passed in JSON.
sessionDetails, err := json.Marshal(session)
if err != nil {
return nil, *session.SessionId, fmt.Errorf("error encountered in reading session details %s", err)
}
// AWS session-manager-plugin requires the parameters used in the session to be passed in JSON as well.
sessionParameters, err := json.Marshal(input)
if err != nil {
return nil, "", fmt.Errorf("error encountered in reading session parameter details %s", err)
}
// Args must be in this order
args := []string{
string(sessionDetails),
s.Region,
"StartSession",
"", // ProfileName
string(sessionParameters),
*session.StreamUrl,
}
return args, *session.SessionId, nil
}
// Start an interactive Systems Manager session with a remote instance via the
// AWS session-manager-plugin. To terminate the session you must cancell the
// context. If you do not wish to terminate the session manually: calling
// StopSession on a instance of this driver will terminate the active session
// created from calling StartSession.
func (s Session) Start(ctx context.Context, ui packer.Ui) error {
for ctx.Err() == nil {
log.Printf("ssm: Starting PortForwarding session to instance %s", s.InstanceID)
args, sessionID, err := s.getCommand(ctx)
if sessionID != "" {
defer func() {
_, err := s.SvcClient.TerminateSession(&ssm.TerminateSessionInput{SessionId: aws.String(sessionID)})
if err != nil {
ui.Error(fmt.Sprintf("Error terminating SSM Session %q. Please terminate the session manually: %s", sessionID, err))
}
}()
}
if err != nil {
return err
}
cmd := exec.CommandContext(ctx, "session-manager-plugin", args...)
ui.Message(fmt.Sprintf("Starting portForwarding session %q.", sessionID))
err = localexec.RunAndStream(cmd, ui, nil)
if err != nil {
ui.Error(err.Error())
}
}
return nil
}
+197
View File
@@ -0,0 +1,197 @@
package common
import (
"context"
"encoding/json"
"fmt"
"log"
"os/exec"
"time"
"github.com/aws/aws-sdk-go/aws"
"github.com/aws/aws-sdk-go/service/ssm"
"github.com/aws/aws-sdk-go/service/ssm/ssmiface"
"github.com/hashicorp/packer/common/retry"
"github.com/mitchellh/iochan"
)
const (
sessionManagerPluginName string = "session-manager-plugin"
//sessionCommand is the AWS-SDK equivalent to the command you would specify to `aws ssm ...`
sessionCommand string = "StartSession"
)
type SSMDriverConfig struct {
SvcClient ssmiface.SSMAPI
Region string
ProfileName string
SvcEndpoint string
}
type SSMDriver struct {
SSMDriverConfig
session *ssm.StartSessionOutput
sessionParams ssm.StartSessionInput
pluginCmdFunc func(context.Context) error
}
func NewSSMDriver(config SSMDriverConfig) *SSMDriver {
d := SSMDriver{SSMDriverConfig: config}
return &d
}
// StartSession starts an interactive Systems Manager session with a remote instance via the AWS session-manager-plugin
// This ssm.StartSessionOutput returned by this function can be used for terminating the session manually. If you do
// not wish to manage the session manually calling StopSession on a instance of this driver will terminate the active session
// created from calling StartSession.
func (d *SSMDriver) StartSession(ctx context.Context, input ssm.StartSessionInput) (*ssm.StartSessionOutput, error) {
log.Printf("Starting PortForwarding session to instance %q", aws.StringValue(input.Target))
var output *ssm.StartSessionOutput
err := retry.Config{
ShouldRetry: func(err error) bool { return IsAWSErr(err, "TargetNotConnected", "") },
RetryDelay: (&retry.Backoff{InitialBackoff: 200 * time.Millisecond, MaxBackoff: 60 * time.Second, Multiplier: 2}).Linear,
}.Run(ctx, func(ctx context.Context) (err error) {
output, err = d.SvcClient.StartSessionWithContext(ctx, &input)
return err
})
if err != nil {
return nil, fmt.Errorf("error encountered in starting session for instance %q: %s", aws.StringValue(input.Target), err)
}
d.session = output
d.sessionParams = input
if d.pluginCmdFunc == nil {
d.pluginCmdFunc = d.openTunnelForSession
}
if err := d.pluginCmdFunc(ctx); err != nil {
return nil, fmt.Errorf("error encountered in starting session for instance %q: %s", aws.StringValue(input.Target), err)
}
return d.session, nil
}
func (d *SSMDriver) openTunnelForSession(ctx context.Context) error {
args, err := d.Args()
if err != nil {
return fmt.Errorf("error encountered validating session details: %s", err)
}
cmd := exec.CommandContext(ctx, sessionManagerPluginName, args...)
// Let's build up our logging
stdout, err := cmd.StdoutPipe()
if err != nil {
return err
}
stderr, err := cmd.StderrPipe()
if err != nil {
return err
}
// Create the channels we'll use for data
stdoutCh := iochan.DelimReader(stdout, '\n')
stderrCh := iochan.DelimReader(stderr, '\n')
/* Loop and get all our output
This particular logger will continue to run through an entire Packer run.
The decision to continue logging is due to the fact that session-manager-plugin
doesn't give a good way of knowing if the command failed or was successful other
than looking at the logs. Seeing as the plugin is updated frequently and that the
log information is a bit sparse this logger will indefinitely relying on other
steps to fail if the tunnel is unable to be created. If successful then the user
will get more information on the tunnel connection when running in a debug mode.
*/
go func(ctx context.Context, prefix string) {
for {
select {
case <-ctx.Done():
return
case output, ok := <-stderrCh:
if !ok {
stderrCh = nil
break
}
if output != "" {
log.Printf("[ERROR] %s: %s", prefix, output)
}
case output, ok := <-stdoutCh:
if !ok {
stdoutCh = nil
break
}
if output != "" {
log.Printf("[DEBUG] %s: %s", prefix, output)
}
}
if stdoutCh == nil && stderrCh == nil {
log.Printf("[DEBUG] %s: %s", prefix, "active session has been terminated; stopping all log polling processes.")
return
}
}
}(ctx, sessionManagerPluginName)
log.Printf("[DEBUG %s] opening session tunnel to instance %q for session %q", sessionManagerPluginName,
aws.StringValue(d.sessionParams.Target),
aws.StringValue(d.session.SessionId),
)
if err := cmd.Start(); err != nil {
err = fmt.Errorf("error encountered when calling %s: %s\n", sessionManagerPluginName, err)
return err
}
return nil
}
// StopSession terminates an active Session Manager session
func (d *SSMDriver) StopSession() error {
if d.session == nil || d.session.SessionId == nil {
return fmt.Errorf("Unable to find a valid session to instance %q; skipping the termination step",
aws.StringValue(d.sessionParams.Target))
}
_, err := d.SvcClient.TerminateSession(&ssm.TerminateSessionInput{SessionId: d.session.SessionId})
if err != nil {
err = fmt.Errorf("Error terminating SSM Session %q. Please terminate the session manually: %s", aws.StringValue(d.session.SessionId), err)
}
return err
}
// Args validates the driver inputs before returning an ordered set of arguments to pass to the driver command.
func (d *SSMDriver) Args() ([]string, error) {
if d.session == nil {
return nil, fmt.Errorf("an active Amazon SSM Session is required before trying to open a session tunnel")
}
// AWS session-manager-plugin requires a valid session be passed in JSON.
sessionDetails, err := json.Marshal(d.session)
if err != nil {
return nil, fmt.Errorf("error encountered in reading session details %s", err)
}
// AWS session-manager-plugin requires the parameters used in the session to be passed in JSON as well.
sessionParameters, err := json.Marshal(d.sessionParams)
if err != nil {
return nil, fmt.Errorf("error encountered in reading session parameter details %s", err)
}
// Args must be in this order
args := []string{
string(sessionDetails),
d.Region,
sessionCommand,
d.ProfileName,
string(sessionParameters),
d.SvcEndpoint,
}
return args, nil
}
+188
View File
@@ -0,0 +1,188 @@
package common
import (
"context"
"fmt"
"reflect"
"strings"
"testing"
)
func NewSSMDriverWithMockSvc(svc *MockSSMSvc) *SSMDriver {
config := SSMDriverConfig{
SvcClient: svc,
Region: "east",
ProfileName: "default",
SvcEndpoint: "example.com",
}
driver := SSMDriver{
SSMDriverConfig: config,
pluginCmdFunc: func(ctx context.Context) error { return nil },
}
return &driver
}
func TestSSMDriver_StartSession(t *testing.T) {
mockSvc := MockSSMSvc{}
driver := NewSSMDriverWithMockSvc(&mockSvc)
if driver.SvcClient == nil {
t.Fatalf("SvcClient for driver should not be nil")
}
session, err := driver.StartSession(context.TODO(), MockStartSessionInput("fakeinstance"))
if err != nil {
t.Fatalf("calling StartSession should not error but got %v", err)
}
if !mockSvc.StartSessionCalled {
t.Fatalf("expected test to call ssm mocks but didn't")
}
if session == nil {
t.Errorf("expected session to be set after a successful call to StartSession")
}
if !reflect.DeepEqual(session, MockStartSessionOutput()) {
t.Errorf("expected session to be %v but got %v", MockStartSessionOutput(), session)
}
}
func TestSSMDriver_StartSessionWithError(t *testing.T) {
mockSvc := MockSSMSvc{StartSessionError: fmt.Errorf("bogus error")}
driver := NewSSMDriverWithMockSvc(&mockSvc)
if driver.SvcClient == nil {
t.Fatalf("SvcClient for driver should not be nil")
}
session, err := driver.StartSession(context.TODO(), MockStartSessionInput("fakeinstance"))
if err == nil {
t.Fatalf("StartSession should have thrown an error but didn't")
}
if !mockSvc.StartSessionCalled {
t.Errorf("expected test to call StartSession mock but didn't")
}
if session != nil {
t.Errorf("expected session to be nil after a bad StartSession call, but got %v", session)
}
}
func TestSSMDriver_StopSession(t *testing.T) {
mockSvc := MockSSMSvc{}
driver := NewSSMDriverWithMockSvc(&mockSvc)
if driver.SvcClient == nil {
t.Fatalf("SvcClient for driver should not be nil")
}
// Calling StopSession before StartSession should fail
err := driver.StopSession()
if err == nil {
t.Fatalf("calling StopSession() on a driver that has no started session should fail")
}
if driver.session != nil {
t.Errorf("expected session to be default to nil")
}
if mockSvc.TerminateSessionCalled {
t.Fatalf("a call to TerminateSession should not occur when there is no valid SSM session")
}
// Lets try calling start session, then stopping to see what happens.
session, err := driver.StartSession(context.TODO(), MockStartSessionInput("fakeinstance"))
if err != nil {
t.Fatalf("calling StartSession should not error but got %v", err)
}
if !mockSvc.StartSessionCalled {
t.Fatalf("expected test to call StartSession mock but didn't")
}
if session == nil || driver.session != session {
t.Errorf("expected session to be set after a successful call to StartSession")
}
if !reflect.DeepEqual(session, MockStartSessionOutput()) {
t.Errorf("expected session to be %v but got %v", MockStartSessionOutput(), session)
}
err = driver.StopSession()
if err != nil {
t.Errorf("calling StopSession() on a driver on a started session should not fail")
}
if !mockSvc.TerminateSessionCalled {
t.Fatalf("expected test to call StopSession mock but didn't")
}
}
func TestSSMDriver_Args(t *testing.T) {
tt := []struct {
Name string
ProfileName string
SkipStartSession bool
ErrorExpected bool
}{
{
Name: "NilSession",
SkipStartSession: true,
ErrorExpected: true,
},
{
Name: "NonNilSession",
ErrorExpected: false,
},
{
Name: "SessionWithProfileName",
ProfileName: "default",
ErrorExpected: false,
},
}
for _, tc := range tt {
tc := tc
t.Run(tc.Name, func(t *testing.T) {
mockSvc := MockSSMSvc{}
driver := NewSSMDriverWithMockSvc(&mockSvc)
driver.ProfileName = tc.ProfileName
if driver.SvcClient == nil {
t.Fatalf("svcclient for driver should not be nil")
}
if !tc.SkipStartSession {
_, err := driver.StartSession(context.TODO(), MockStartSessionInput("fakeinstance"))
if err != nil {
t.Fatalf("got an error when calling StartSession %v", err)
}
}
args, err := driver.Args()
if tc.ErrorExpected && err == nil {
t.Fatalf("Driver.Args with a %q should have failed but instead no error was returned", tc.Name)
}
if tc.ErrorExpected {
return
}
if err != nil {
t.Fatalf("got an error when it should've worked %v", err)
}
// validate launch script
expectedArgString := fmt.Sprintf(`{"SessionId":"packerid","StreamUrl":"http://packer.io","TokenValue":"packer-token"} east StartSession %s {"DocumentName":"AWS-StartPortForwardingSession","Parameters":{"localPortNumber":["8001"],"portNumber":["22"]},"Target":"fakeinstance"} example.com`, tc.ProfileName)
argString := strings.Join(args, " ")
if argString != expectedArgString {
t.Errorf("Expected launch script to be %q but got %q", expectedArgString, argString)
}
})
}
}
+56
View File
@@ -0,0 +1,56 @@
package common
import (
"context"
"github.com/aws/aws-sdk-go/aws"
"github.com/aws/aws-sdk-go/aws/request"
"github.com/aws/aws-sdk-go/service/ssm"
"github.com/aws/aws-sdk-go/service/ssm/ssmiface"
)
type MockSSMSvc struct {
ssmiface.SSMAPI
StartSessionError error
TerminateSessionError error
StartSessionCalled bool
TerminateSessionCalled bool
}
func (svc *MockSSMSvc) StartSessionWithContext(ctx aws.Context, input *ssm.StartSessionInput, options ...request.Option) (*ssm.StartSessionOutput, error) {
svc.StartSessionCalled = true
return MockStartSessionOutput(), svc.StartSessionError
}
func (svc *MockSSMSvc) TerminateSession(input *ssm.TerminateSessionInput) (*ssm.TerminateSessionOutput, error) {
svc.TerminateSessionCalled = true
return new(ssm.TerminateSessionOutput), svc.TerminateSessionError
}
func MockPluginCmdFunc(ctx context.Context) error {
return nil
}
func MockStartSessionOutput() *ssm.StartSessionOutput {
id, url, token := "packerid", "http://packer.io", "packer-token"
output := ssm.StartSessionOutput{
SessionId: &id,
StreamUrl: &url,
TokenValue: &token,
}
return &output
}
func MockStartSessionInput(instance string) ssm.StartSessionInput {
params := map[string][]*string{
"portNumber": []*string{aws.String("22")},
"localPortNumber": []*string{aws.String("8001")},
}
input := ssm.StartSessionInput{
DocumentName: aws.String("AWS-StartPortForwardingSession"),
Parameters: params,
Target: aws.String(instance),
}
return input
}
@@ -8,9 +8,9 @@ import (
"github.com/aws/aws-sdk-go/aws"
"github.com/aws/aws-sdk-go/service/ec2"
"github.com/aws/aws-sdk-go/service/ec2/ec2iface"
"github.com/hashicorp/packer/helper/config"
"github.com/hashicorp/packer/helper/multistep"
"github.com/hashicorp/packer/packer"
"github.com/hashicorp/packer/packer-plugin-sdk/config"
)
type StepAMIRegionCopy struct {
@@ -11,9 +11,9 @@ import (
"github.com/aws/aws-sdk-go/aws/request"
"github.com/aws/aws-sdk-go/service/ec2"
"github.com/aws/aws-sdk-go/service/ec2/ec2iface"
"github.com/hashicorp/packer/helper/config"
"github.com/hashicorp/packer/helper/multistep"
"github.com/hashicorp/packer/packer"
"github.com/hashicorp/packer/packer-plugin-sdk/config"
)
// Define a mock struct to be used in unit tests for common aws steps.
+44 -23
View File
@@ -3,16 +3,16 @@ package common
import (
"context"
"fmt"
"strconv"
"time"
"github.com/aws/aws-sdk-go/aws"
"github.com/aws/aws-sdk-go/aws/session"
"github.com/aws/aws-sdk-go/service/ec2"
"github.com/aws/aws-sdk-go/service/ssm"
pssm "github.com/hashicorp/packer/builder/amazon/common/ssm"
"github.com/hashicorp/packer/common/net"
"github.com/hashicorp/packer/helper/multistep"
"github.com/hashicorp/packer/packer"
"github.com/hashicorp/packer/packer-plugin-sdk/net"
)
type StepCreateSSMTunnel struct {
@@ -21,8 +21,9 @@ type StepCreateSSMTunnel struct {
LocalPortNumber int
RemotePortNumber int
SSMAgentEnabled bool
instanceId string
PauseBeforeSSM time.Duration
stopSSMCommand func()
driver *SSMDriver
}
// Run executes the Packer build step that creates a session tunnel.
@@ -35,7 +36,7 @@ func (s *StepCreateSSMTunnel) Run(ctx context.Context, state multistep.StateBag)
// Wait for the remote port to become available
if s.PauseBeforeSSM > 0 {
ui.Say(fmt.Sprintf("Waiting %s before establishing the SSM session...", s.PauseBeforeSSM))
ui.Say(fmt.Sprintf("Waiting %s for establishing the SSM session...", s.PauseBeforeSSM))
select {
case <-time.After(s.PauseBeforeSSM):
break
@@ -60,38 +61,42 @@ func (s *StepCreateSSMTunnel) Run(ctx context.Context, state multistep.StateBag)
state.Put("error", err)
return multistep.ActionHalt
}
s.instanceId = aws.StringValue(instance.InstanceId)
state.Put("sessionPort", s.LocalPortNumber)
ssmCtx, ssmCancel := context.WithCancel(ctx)
s.stopSSMCommand = ssmCancel
go func() {
if s.driver == nil {
ssmconn := ssm.New(s.AWSSession)
err := pssm.Session{
SvcClient: ssmconn,
InstanceID: aws.StringValue(instance.InstanceId),
RemotePort: s.RemotePortNumber,
LocalPort: s.LocalPortNumber,
Region: s.Region,
}.Start(ssmCtx, ui)
if err != nil {
ui.Error(fmt.Sprintf("ssm error: %s", err))
cfg := SSMDriverConfig{
SvcClient: ssmconn,
Region: s.Region,
SvcEndpoint: ssmconn.Endpoint,
}
}()
driver := SSMDriver{SSMDriverConfig: cfg}
s.driver = &driver
}
input := s.BuildTunnelInputForInstance(s.instanceId)
_, err := s.driver.StartSession(ctx, input)
if err != nil {
err = fmt.Errorf("error encountered in establishing a tunnel %s", err)
ui.Error(err.Error())
state.Put("error", err)
return multistep.ActionHalt
}
ui.Message(fmt.Sprintf("PortForwarding session %q has been started", s.instanceId))
state.Put("sessionPort", s.LocalPortNumber)
return multistep.ActionContinue
}
// Cleanup terminates an active session on AWS, which in turn terminates the associated tunnel process running on the local machine.
func (s *StepCreateSSMTunnel) Cleanup(state multistep.StateBag) {
ui := state.Get("ui").(packer.Ui)
if !s.SSMAgentEnabled {
return
}
if s.stopSSMCommand != nil {
s.stopSSMCommand()
if err := s.driver.StopSession(); err != nil {
ui.Error(err.Error())
}
}
@@ -124,3 +129,19 @@ func (s *StepCreateSSMTunnel) ConfigureLocalHostPort(ctx context.Context) error
return nil
}
func (s *StepCreateSSMTunnel) BuildTunnelInputForInstance(instance string) ssm.StartSessionInput {
dst, src := strconv.Itoa(s.RemotePortNumber), strconv.Itoa(s.LocalPortNumber)
params := map[string][]*string{
"portNumber": []*string{aws.String(dst)},
"localPortNumber": []*string{aws.String(src)},
}
input := ssm.StartSessionInput{
DocumentName: aws.String("AWS-StartPortForwardingSession"),
Parameters: params,
Target: aws.String(instance),
}
return input
}
@@ -0,0 +1,139 @@
package common
import (
"context"
"reflect"
"testing"
"github.com/aws/aws-sdk-go/aws"
"github.com/aws/aws-sdk-go/service/ec2"
"github.com/hashicorp/packer/packer"
)
func TestStepCreateSSMTunnel_Run(t *testing.T) {
mockSvc := MockSSMSvc{}
config := SSMDriverConfig{
SvcClient: &mockSvc,
SvcEndpoint: "example.com",
}
mockDriver := NewSSMDriver(config)
mockDriver.pluginCmdFunc = MockPluginCmdFunc
state := testState()
state.Put("ui", &packer.NoopUi{})
state.Put("instance", &ec2.Instance{InstanceId: aws.String("i-something")})
step := StepCreateSSMTunnel{
driver: mockDriver,
}
step.Run(context.Background(), state)
err := state.Get("error")
if err != nil {
err = err.(error)
t.Fatalf("the call to Run failed with an error when it should've executed: %v", err)
}
if mockSvc.StartSessionCalled {
t.Errorf("StartSession should not be called when SSMAgentEnabled is false")
}
// Run when SSMAgentEnabled is true
step.SSMAgentEnabled = true
step.Run(context.Background(), state)
err = state.Get("error")
if err != nil {
err = err.(error)
t.Fatalf("the call to Run failed with an error when it should've executed: %v", err)
}
if !mockSvc.StartSessionCalled {
t.Errorf("calling run with the correct inputs should call StartSession")
}
step.Cleanup(state)
if !mockSvc.TerminateSessionCalled {
t.Errorf("calling cleanup on a successful run should call TerminateSession")
}
}
func TestStepCreateSSMTunnel_Cleanup(t *testing.T) {
mockSvc := MockSSMSvc{}
config := SSMDriverConfig{
SvcClient: &mockSvc,
SvcEndpoint: "example.com",
}
mockDriver := NewSSMDriver(config)
mockDriver.pluginCmdFunc = MockPluginCmdFunc
step := StepCreateSSMTunnel{
SSMAgentEnabled: true,
driver: mockDriver,
}
state := testState()
state.Put("ui", &packer.NoopUi{})
state.Put("instance", &ec2.Instance{InstanceId: aws.String("i-something")})
step.Cleanup(state)
if mockSvc.TerminateSessionCalled {
t.Fatalf("calling cleanup on a non started session should not call TerminateSession")
}
}
func TestStepCreateSSMTunnel_BuildTunnelInputForInstance(t *testing.T) {
step := StepCreateSSMTunnel{
Region: "region",
LocalPortNumber: 8001,
RemotePortNumber: 22,
SSMAgentEnabled: true,
}
input := step.BuildTunnelInputForInstance("i-something")
target := aws.StringValue(input.Target)
if target != "i-something" {
t.Errorf("input should contain instance id as target but it got %q", target)
}
params := map[string][]*string{
"portNumber": []*string{aws.String("22")},
"localPortNumber": []*string{aws.String("8001")},
}
if !reflect.DeepEqual(input.Parameters, params) {
t.Errorf("input should contain the expected port parameters but it got %v", input.Parameters)
}
}
func TestStepCreateSSMTunnel_ConfigureLocalHostPort(t *testing.T) {
tt := []struct {
Name string
Step StepCreateSSMTunnel
PortCheck func(int) bool
}{
{"WithLocalPortNumber", StepCreateSSMTunnel{LocalPortNumber: 9001}, func(port int) bool { return port == 9001 }},
{"WithNoLocalPortNumber", StepCreateSSMTunnel{}, func(port int) bool { return port >= 8000 && port <= 9000 }},
}
for _, tc := range tt {
tc := tc
t.Run(tc.Name, func(t *testing.T) {
step := tc.Step
if err := step.ConfigureLocalHostPort(context.TODO()); err != nil {
t.Errorf("failed to configure a port on localhost")
}
if !tc.PortCheck(step.LocalPortNumber) {
t.Errorf("failed to configure a port on localhost")
}
})
}
}
+3 -4
View File
@@ -8,11 +8,10 @@ import (
"github.com/aws/aws-sdk-go/aws"
"github.com/aws/aws-sdk-go/aws/session"
"github.com/aws/aws-sdk-go/service/ec2"
"github.com/hashicorp/packer/builder/amazon/common/awserrors"
"github.com/hashicorp/packer/common/retry"
"github.com/hashicorp/packer/helper/multistep"
"github.com/hashicorp/packer/packer"
"github.com/hashicorp/packer/packer-plugin-sdk/retry"
"github.com/hashicorp/packer/packer-plugin-sdk/template/interpolate"
"github.com/hashicorp/packer/template/interpolate"
)
type StepCreateTags struct {
@@ -92,7 +91,7 @@ func (s *StepCreateTags) Run(ctx context.Context, state multistep.StateBag) mult
// Retry creating tags for about 2.5 minutes
err = retry.Config{Tries: 11, ShouldRetry: func(error) bool {
if awserrors.Matches(err, "InvalidAMIID.NotFound", "") || awserrors.Matches(err, "InvalidSnapshot.NotFound", "") {
if IsAWSErr(err, "InvalidAMIID.NotFound", "") || IsAWSErr(err, "InvalidSnapshot.NotFound", "") {
return true
}
return false
+1 -1
View File
@@ -12,10 +12,10 @@ import (
"time"
"github.com/aws/aws-sdk-go/service/ec2"
"github.com/hashicorp/packer/common/retry"
"github.com/hashicorp/packer/helper/communicator"
"github.com/hashicorp/packer/helper/multistep"
"github.com/hashicorp/packer/packer"
"github.com/hashicorp/packer/packer-plugin-sdk/retry"
)
// StepGetPassword reads the password from a Windows server and sets it
@@ -8,9 +8,9 @@ import (
"github.com/aws/aws-sdk-go/aws"
"github.com/aws/aws-sdk-go/service/iam"
"github.com/hashicorp/packer/common/uuid"
"github.com/hashicorp/packer/helper/multistep"
"github.com/hashicorp/packer/packer"
"github.com/hashicorp/packer/packer-plugin-sdk/uuid"
)
type StepIamInstanceProfile struct {
+1 -1
View File
@@ -8,10 +8,10 @@ import (
"time"
"github.com/aws/aws-sdk-go/service/ec2"
"github.com/hashicorp/packer/common/retry"
"github.com/hashicorp/packer/helper/communicator"
"github.com/hashicorp/packer/helper/multistep"
"github.com/hashicorp/packer/packer"
"github.com/hashicorp/packer/packer-plugin-sdk/retry"
)
type StepKeyPair struct {
@@ -7,10 +7,10 @@ import (
"github.com/aws/aws-sdk-go/aws"
"github.com/aws/aws-sdk-go/aws/session"
"github.com/aws/aws-sdk-go/service/ec2"
"github.com/hashicorp/packer/builder"
"github.com/hashicorp/packer/helper/multistep"
"github.com/hashicorp/packer/packer"
"github.com/hashicorp/packer/packer-plugin-sdk/packerbuilderdata"
"github.com/hashicorp/packer/packer-plugin-sdk/template/interpolate"
"github.com/hashicorp/packer/template/interpolate"
)
type StepModifyAMIAttributes struct {
@@ -22,7 +22,7 @@ type StepModifyAMIAttributes struct {
Description string
Ctx interpolate.Context
GeneratedData *packerbuilderdata.GeneratedData
GeneratedData *builder.GeneratedData
}
func (s *StepModifyAMIAttributes) Run(ctx context.Context, state multistep.StateBag) multistep.StepAction {
@@ -7,9 +7,9 @@ import (
"github.com/aws/aws-sdk-go/service/ec2"
"github.com/aws/aws-sdk-go/service/ec2/ec2iface"
confighelper "github.com/hashicorp/packer/helper/config"
"github.com/hashicorp/packer/helper/multistep"
"github.com/hashicorp/packer/packer"
confighelper "github.com/hashicorp/packer/packer-plugin-sdk/config"
)
type StepModifyEBSBackedInstance struct {
+3 -4
View File
@@ -9,10 +9,9 @@ import (
"github.com/aws/aws-sdk-go/aws"
"github.com/aws/aws-sdk-go/service/ec2"
"github.com/aws/aws-sdk-go/service/ec2/ec2iface"
"github.com/hashicorp/packer/builder/amazon/common/awserrors"
"github.com/hashicorp/packer/common/retry"
"github.com/hashicorp/packer/helper/multistep"
"github.com/hashicorp/packer/packer"
"github.com/hashicorp/packer/packer-plugin-sdk/retry"
)
// StepPreValidate provides an opportunity to pre-validate any configuration for
@@ -40,7 +39,7 @@ func (s *StepPreValidate) Run(ctx context.Context, state multistep.StateBag) mul
err := retry.Config{
Tries: 11,
ShouldRetry: func(err error) bool {
if awserrors.Matches(err, "AuthFailure", "") {
if IsAWSErr(err, "AuthFailure", "") {
log.Printf("Waiting for Vault-generated AWS credentials" +
" to pass authentication... trying again.")
return true
@@ -132,7 +131,7 @@ func (s *StepPreValidate) checkVpc(conn ec2iface.EC2API) error {
}
res, err := conn.DescribeVpcs(&ec2.DescribeVpcsInput{VpcIds: []*string{aws.String(s.VpcId)}})
if awserrors.Matches(err, "InvalidVpcID.NotFound", "") || err != nil {
if IsAWSErr(err, "InvalidVpcID.NotFound", "") || err != nil {
return fmt.Errorf("Error retrieving VPC information for vpc_id %s: %s", s.VpcId, err)
}
@@ -11,12 +11,11 @@ import (
"github.com/aws/aws-sdk-go/aws"
"github.com/aws/aws-sdk-go/service/ec2"
"github.com/hashicorp/packer/builder/amazon/common/awserrors"
"github.com/hashicorp/packer/common/retry"
"github.com/hashicorp/packer/helper/communicator"
"github.com/hashicorp/packer/helper/multistep"
"github.com/hashicorp/packer/packer"
"github.com/hashicorp/packer/packer-plugin-sdk/retry"
"github.com/hashicorp/packer/packer-plugin-sdk/template/interpolate"
"github.com/hashicorp/packer/template/interpolate"
)
type StepRunSourceInstance struct {
@@ -34,7 +33,6 @@ type StepRunSourceInstance struct {
IsRestricted bool
SourceAMI string
Tags map[string]string
Tenancy string
UserData string
UserDataFile string
VolumeTags map[string]string
@@ -197,15 +195,11 @@ func (s *StepRunSourceInstance) Run(ctx context.Context, state multistep.StateBa
runOpts.InstanceInitiatedShutdownBehavior = &s.InstanceInitiatedShutdownBehavior
}
if s.Tenancy != "" {
runOpts.Placement.Tenancy = aws.String(s.Tenancy)
}
var runResp *ec2.Reservation
err = retry.Config{
Tries: 11,
ShouldRetry: func(err error) bool {
if awserrors.Matches(err, "InvalidParameterValue", "iamInstanceProfile") {
if IsAWSErr(err, "InvalidParameterValue", "iamInstanceProfile") {
return true
}
return false
@@ -216,7 +210,7 @@ func (s *StepRunSourceInstance) Run(ctx context.Context, state multistep.StateBa
return err
})
if awserrors.Matches(err, "VPCIdNotSpecified", "No default VPC for this user") && subnetId == "" {
if IsAWSErr(err, "VPCIdNotSpecified", "No default VPC for this user") && subnetId == "" {
err := fmt.Errorf("Error launching source instance: a valid Subnet Id was not specified")
state.Put("error", err)
ui.Error(err.Error())
@@ -254,7 +248,7 @@ func (s *StepRunSourceInstance) Run(ctx context.Context, state multistep.StateBa
var r *ec2.DescribeInstancesOutput
err = retry.Config{Tries: 11, ShouldRetry: func(err error) bool {
if awserrors.Matches(err, "InvalidInstanceID.NotFound", "") {
if IsAWSErr(err, "InvalidInstanceID.NotFound", "") {
return true
}
return false
@@ -299,7 +293,7 @@ func (s *StepRunSourceInstance) Run(ctx context.Context, state multistep.StateBa
ec2Tags.Report(ui)
// Retry creating tags for about 2.5 minutes
err = retry.Config{Tries: 11, ShouldRetry: func(error) bool {
if awserrors.Matches(err, "InvalidInstanceID.NotFound", "") {
if IsAWSErr(err, "InvalidInstanceID.NotFound", "") {
return true
}
return false
+15 -26
View File
@@ -11,14 +11,12 @@ import (
"github.com/aws/aws-sdk-go/aws"
"github.com/aws/aws-sdk-go/service/ec2"
"github.com/aws/aws-sdk-go/service/ec2/ec2iface"
"github.com/hashicorp/packer/builder/amazon/common/awserrors"
"github.com/hashicorp/packer/common/random"
"github.com/hashicorp/packer/common/retry"
"github.com/hashicorp/packer/helper/communicator"
"github.com/hashicorp/packer/helper/multistep"
"github.com/hashicorp/packer/packer"
"github.com/hashicorp/packer/packer-plugin-sdk/random"
"github.com/hashicorp/packer/packer-plugin-sdk/retry"
"github.com/hashicorp/packer/packer-plugin-sdk/template/interpolate"
"github.com/hashicorp/packer/template/interpolate"
)
type EC2BlockDeviceMappingsBuilder interface {
@@ -36,7 +34,6 @@ type StepRunSpotInstance struct {
ExpectedRootDevice string
InstanceInitiatedShutdownBehavior string
InstanceType string
Region string
SourceAMI string
SpotPrice string
SpotTags map[string]string
@@ -160,7 +157,7 @@ func (s *StepRunSpotInstance) LoadUserData() (string, error) {
}
func (s *StepRunSpotInstance) Run(ctx context.Context, state multistep.StateBag) multistep.StepAction {
ec2conn := state.Get("ec2").(ec2iface.EC2API)
ec2conn := state.Get("ec2").(*ec2.EC2)
ui := state.Get("ui").(packer.Ui)
ui.Say("Launching a spot AWS instance...")
@@ -199,7 +196,7 @@ func (s *StepRunSpotInstance) Run(ctx context.Context, state multistep.StateBag)
}
// Convert tags from the tag map provided by the user into *ec2.Tag s
ec2Tags, err := TagMap(s.Tags).EC2Tags(s.Ctx, s.Region, state)
ec2Tags, err := TagMap(s.Tags).EC2Tags(s.Ctx, *ec2conn.Config.Region, state)
if err != nil {
err := fmt.Errorf("Error generating tags for source instance: %s", err)
state.Put("error", err)
@@ -223,14 +220,6 @@ func (s *StepRunSpotInstance) Run(ctx context.Context, state multistep.StateBag)
}
marketOptions.SetMarketType(ec2.MarketTypeSpot)
spotTags, err := TagMap(s.SpotTags).EC2Tags(s.Ctx, s.Region, state)
if err != nil {
err := fmt.Errorf("Error generating tags for spot request: %s", err)
state.Put("error", err)
ui.Error(err.Error())
return multistep.ActionHalt
}
// Create a launch template for the instance
ui.Message("Loading User Data File...")
@@ -253,14 +242,6 @@ func (s *StepRunSpotInstance) Run(ctx context.Context, state multistep.StateBag)
LaunchTemplateName: aws.String(launchTemplateName),
VersionDescription: aws.String("template generated by packer for launching spot instances"),
}
if len(spotTags) > 0 {
launchTemplate.TagSpecifications = []*ec2.TagSpecification{
{
ResourceType: aws.String("launch-template"),
Tags: spotTags,
},
}
}
// Tell EC2 to create the template
_, err = ec2conn.CreateLaunchTemplate(launchTemplate)
@@ -379,6 +360,14 @@ func (s *StepRunSpotInstance) Run(ctx context.Context, state multistep.StateBag)
instance := describeOutput.Reservations[0].Instances[0]
// Tag the spot instance request (not the eventual spot instance)
spotTags, err := TagMap(s.SpotTags).EC2Tags(s.Ctx, *ec2conn.Config.Region, state)
if err != nil {
err := fmt.Errorf("Error generating tags for spot request: %s", err)
state.Put("error", err)
ui.Error(err.Error())
return multistep.ActionHalt
}
if len(spotTags) > 0 && len(s.SpotTags) > 0 {
spotTags.Report(ui)
// Use the instance ID to find out the SIR, so that we can tag the spot
@@ -407,7 +396,7 @@ func (s *StepRunSpotInstance) Run(ctx context.Context, state multistep.StateBag)
// Retry creating tags for about 2.5 minutes
err = retry.Config{Tries: 11, ShouldRetry: func(error) bool {
if awserrors.Matches(err, "InvalidInstanceID.NotFound", "") {
if IsAWSErr(err, "InvalidInstanceID.NotFound", "") {
return true
}
return false
@@ -438,7 +427,7 @@ func (s *StepRunSpotInstance) Run(ctx context.Context, state multistep.StateBag)
if len(volumeIds) > 0 && len(s.VolumeTags) > 0 {
ui.Say("Adding tags to source EBS Volumes")
volumeTags, err := TagMap(s.VolumeTags).EC2Tags(s.Ctx, s.Region, state)
volumeTags, err := TagMap(s.VolumeTags).EC2Tags(s.Ctx, *ec2conn.Config.Region, state)
if err != nil {
err := fmt.Errorf("Error tagging source EBS Volumes on %s: %s", *instance.InstanceId, err)
state.Put("error", err)
@@ -2,13 +2,11 @@ package common
import (
"bytes"
"context"
"fmt"
"testing"
"github.com/aws/aws-sdk-go/aws"
"github.com/aws/aws-sdk-go/service/ec2"
"github.com/aws/aws-sdk-go/service/ec2/ec2iface"
"github.com/hashicorp/packer/helper/communicator"
"github.com/hashicorp/packer/helper/multistep"
"github.com/hashicorp/packer/packer"
@@ -45,7 +43,6 @@ func getBasicStep() *StepRunSpotInstance {
ExpectedRootDevice: "ebs",
InstanceInitiatedShutdownBehavior: "stop",
InstanceType: "t2.micro",
Region: "us-east-1",
SourceAMI: "",
SpotPrice: "auto",
SpotTags: nil,
@@ -137,226 +134,3 @@ func TestCreateTemplateData_NoEphemeral(t *testing.T) {
// t.Fatalf("Should have created 26 mappings to keep ephemeral drives from appearing.")
// }
}
type runSpotEC2ConnMock struct {
ec2iface.EC2API
CreateLaunchTemplateParams []*ec2.CreateLaunchTemplateInput
CreateLaunchTemplateFn func(*ec2.CreateLaunchTemplateInput) (*ec2.CreateLaunchTemplateOutput, error)
CreateFleetParams []*ec2.CreateFleetInput
CreateFleetFn func(*ec2.CreateFleetInput) (*ec2.CreateFleetOutput, error)
CreateTagsParams []*ec2.CreateTagsInput
CreateTagsFn func(*ec2.CreateTagsInput) (*ec2.CreateTagsOutput, error)
DescribeInstancesParams []*ec2.DescribeInstancesInput
DescribeInstancesFn func(input *ec2.DescribeInstancesInput) (*ec2.DescribeInstancesOutput, error)
}
func (m *runSpotEC2ConnMock) CreateLaunchTemplate(req *ec2.CreateLaunchTemplateInput) (*ec2.CreateLaunchTemplateOutput, error) {
m.CreateLaunchTemplateParams = append(m.CreateLaunchTemplateParams, req)
resp, err := m.CreateLaunchTemplateFn(req)
return resp, err
}
func (m *runSpotEC2ConnMock) CreateFleet(req *ec2.CreateFleetInput) (*ec2.CreateFleetOutput, error) {
m.CreateFleetParams = append(m.CreateFleetParams, req)
if m.CreateFleetFn != nil {
resp, err := m.CreateFleetFn(req)
return resp, err
} else {
return nil, nil
}
}
func (m *runSpotEC2ConnMock) DescribeInstances(req *ec2.DescribeInstancesInput) (*ec2.DescribeInstancesOutput, error) {
m.DescribeInstancesParams = append(m.DescribeInstancesParams, req)
if m.DescribeInstancesFn != nil {
resp, err := m.DescribeInstancesFn(req)
return resp, err
} else {
return nil, nil
}
}
func (m *runSpotEC2ConnMock) CreateTags(req *ec2.CreateTagsInput) (*ec2.CreateTagsOutput, error) {
m.CreateTagsParams = append(m.CreateTagsParams, req)
if m.CreateTagsFn != nil {
resp, err := m.CreateTagsFn(req)
return resp, err
} else {
return nil, nil
}
}
func defaultEc2Mock(instanceId, spotRequestId, volumeId *string) *runSpotEC2ConnMock {
instance := &ec2.Instance{
InstanceId: instanceId,
SpotInstanceRequestId: spotRequestId,
BlockDeviceMappings: []*ec2.InstanceBlockDeviceMapping{
{
Ebs: &ec2.EbsInstanceBlockDevice{
VolumeId: volumeId,
},
},
},
}
return &runSpotEC2ConnMock{
CreateLaunchTemplateFn: func(in *ec2.CreateLaunchTemplateInput) (*ec2.CreateLaunchTemplateOutput, error) {
return &ec2.CreateLaunchTemplateOutput{
LaunchTemplate: nil,
Warning: nil,
}, nil
},
CreateFleetFn: func(*ec2.CreateFleetInput) (*ec2.CreateFleetOutput, error) {
return &ec2.CreateFleetOutput{
Errors: nil,
FleetId: nil,
Instances: []*ec2.CreateFleetInstance{
{
InstanceIds: []*string{instanceId},
},
},
}, nil
},
DescribeInstancesFn: func(input *ec2.DescribeInstancesInput) (*ec2.DescribeInstancesOutput, error) {
return &ec2.DescribeInstancesOutput{
NextToken: nil,
Reservations: []*ec2.Reservation{
{
Instances: []*ec2.Instance{instance},
},
},
}, nil
},
}
}
func TestRun(t *testing.T) {
instanceId := aws.String("test-instance-id")
spotRequestId := aws.String("spot-id")
volumeId := aws.String("volume-id")
ec2Mock := defaultEc2Mock(instanceId, spotRequestId, volumeId)
uiMock := packer.TestUi(t)
state := tStateSpot()
state.Put("ec2", ec2Mock)
state.Put("ui", uiMock)
state.Put("source_image", testImage())
stepRunSpotInstance := getBasicStep()
stepRunSpotInstance.Tags["Name"] = "Packer Builder"
stepRunSpotInstance.Tags["test-tag"] = "test-value"
stepRunSpotInstance.SpotTags = map[string]string{
"spot-tag": "spot-tag-value",
}
stepRunSpotInstance.VolumeTags = map[string]string{
"volume-tag": "volume-tag-value",
}
ctx := context.TODO()
action := stepRunSpotInstance.Run(ctx, state)
if err := state.Get("error"); err != nil {
t.Fatalf("should not error, but: %v", err)
}
if action != multistep.ActionContinue {
t.Fatalf("shoul continue, but: %v", action)
}
if len(ec2Mock.CreateLaunchTemplateParams) != 1 {
t.Fatalf("createLaunchTemplate should be invoked once, but invoked %v", len(ec2Mock.CreateLaunchTemplateParams))
}
launchTemplateName := ec2Mock.CreateLaunchTemplateParams[0].LaunchTemplateName
if len(ec2Mock.CreateLaunchTemplateParams[0].TagSpecifications) != 1 {
t.Fatalf("exactly one launch template tag specification expected")
}
if *ec2Mock.CreateLaunchTemplateParams[0].TagSpecifications[0].ResourceType != "launch-template" {
t.Fatalf("resource type 'launch-template' expected")
}
if len(ec2Mock.CreateLaunchTemplateParams[0].TagSpecifications[0].Tags) != 1 {
t.Fatalf("1 launch template tag expected")
}
nameTag := ec2Mock.CreateLaunchTemplateParams[0].TagSpecifications[0].Tags[0]
if *nameTag.Key != "spot-tag" || *nameTag.Value != "spot-tag-value" {
t.Fatalf("expected spot-tag: spot-tag-value")
}
if len(ec2Mock.CreateFleetParams) != 1 {
t.Fatalf("createFleet should be invoked once, but invoked %v", len(ec2Mock.CreateLaunchTemplateParams))
}
if *ec2Mock.CreateFleetParams[0].TargetCapacitySpecification.DefaultTargetCapacityType != "spot" {
t.Fatalf("capacity type should be spot")
}
if *ec2Mock.CreateFleetParams[0].TargetCapacitySpecification.TotalTargetCapacity != 1 {
t.Fatalf("target capacity should be 1")
}
if len(ec2Mock.CreateFleetParams[0].LaunchTemplateConfigs) != 1 {
t.Fatalf("exactly one launch config template expected")
}
if *ec2Mock.CreateFleetParams[0].LaunchTemplateConfigs[0].LaunchTemplateSpecification.LaunchTemplateName != *launchTemplateName {
t.Fatalf("launchTemplateName should match in createLaunchTemplate and createFleet requests")
}
if len(ec2Mock.DescribeInstancesParams) != 1 {
t.Fatalf("describeInstancesParams should be invoked once, but invoked %v", len(ec2Mock.DescribeInstancesParams))
}
if *ec2Mock.DescribeInstancesParams[0].InstanceIds[0] != *instanceId {
t.Fatalf("instanceId should match from createFleet response")
}
uiMock.Say(fmt.Sprintf("%v", ec2Mock.CreateTagsParams))
if len(ec2Mock.CreateTagsParams) != 3 {
t.Fatalf("createTags should be invoked 3 times")
}
if len(ec2Mock.CreateTagsParams[0].Resources) != 1 || *ec2Mock.CreateTagsParams[0].Resources[0] != *spotRequestId {
t.Fatalf("should create tags for spot request")
}
if len(ec2Mock.CreateTagsParams[1].Resources) != 1 || *ec2Mock.CreateTagsParams[1].Resources[0] != *instanceId {
t.Fatalf("should create tags for instance")
}
if len(ec2Mock.CreateTagsParams[2].Resources) != 1 || ec2Mock.CreateTagsParams[2].Resources[0] != volumeId {
t.Fatalf("should create tags for volume")
}
}
func TestRun_NoSpotTags(t *testing.T) {
instanceId := aws.String("test-instance-id")
spotRequestId := aws.String("spot-id")
volumeId := aws.String("volume-id")
ec2Mock := defaultEc2Mock(instanceId, spotRequestId, volumeId)
uiMock := packer.TestUi(t)
state := tStateSpot()
state.Put("ec2", ec2Mock)
state.Put("ui", uiMock)
state.Put("source_image", testImage())
stepRunSpotInstance := getBasicStep()
stepRunSpotInstance.Tags["Name"] = "Packer Builder"
stepRunSpotInstance.Tags["test-tag"] = "test-value"
stepRunSpotInstance.VolumeTags = map[string]string{
"volume-tag": "volume-tag-value",
}
ctx := context.TODO()
action := stepRunSpotInstance.Run(ctx, state)
if err := state.Get("error"); err != nil {
t.Fatalf("should not error, but: %v", err)
}
if action != multistep.ActionContinue {
t.Fatalf("shoul continue, but: %v", action)
}
if len(ec2Mock.CreateLaunchTemplateParams[0].TagSpecifications) != 0 {
t.Fatalf("0 launch template tags expected")
}
}
+1 -1
View File
@@ -10,10 +10,10 @@ import (
"github.com/aws/aws-sdk-go/aws"
"github.com/aws/aws-sdk-go/aws/request"
"github.com/aws/aws-sdk-go/service/ec2"
"github.com/hashicorp/packer/common/uuid"
"github.com/hashicorp/packer/helper/communicator"
"github.com/hashicorp/packer/helper/multistep"
"github.com/hashicorp/packer/packer"
"github.com/hashicorp/packer/packer-plugin-sdk/uuid"
)
type StepSecurityGroup struct {
@@ -4,8 +4,8 @@ import (
"context"
"github.com/aws/aws-sdk-go/service/ec2"
"github.com/hashicorp/packer/builder"
"github.com/hashicorp/packer/helper/multistep"
"github.com/hashicorp/packer/packer-plugin-sdk/packerbuilderdata"
)
// &awscommon.StepSetGeneratedData{
@@ -13,7 +13,7 @@ import (
// },
type StepSetGeneratedData struct {
GeneratedData *packerbuilderdata.GeneratedData
GeneratedData *builder.GeneratedData
}
func (s *StepSetGeneratedData) Run(ctx context.Context, state multistep.StateBag) multistep.StepAction {
@@ -8,9 +8,9 @@ import (
"time"
"github.com/aws/aws-sdk-go/service/ec2"
confighelper "github.com/hashicorp/packer/helper/config"
"github.com/hashicorp/packer/helper/multistep"
"github.com/hashicorp/packer/packer"
confighelper "github.com/hashicorp/packer/packer-plugin-sdk/config"
)
// StepSourceAMIInfo extracts critical information from the source AMI
@@ -6,10 +6,9 @@ import (
"time"
"github.com/aws/aws-sdk-go/service/ec2"
"github.com/hashicorp/packer/builder/amazon/common/awserrors"
"github.com/hashicorp/packer/common/retry"
"github.com/hashicorp/packer/helper/multistep"
"github.com/hashicorp/packer/packer"
"github.com/hashicorp/packer/packer-plugin-sdk/retry"
)
type StepStopEBSBackedInstance struct {
@@ -43,7 +42,7 @@ func (s *StepStopEBSBackedInstance) Run(ctx context.Context, state multistep.Sta
// Work around this by retrying a few times, up to about 5 minutes.
err := retry.Config{Tries: 6, ShouldRetry: func(error) bool {
if awserrors.Matches(err, "InvalidInstanceID.NotFound", "") {
if IsAWSErr(err, "InvalidInstanceID.NotFound", "") {
return true
}
return false
+3 -3
View File
@@ -5,10 +5,10 @@ import (
"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"
"github.com/hashicorp/packer/packer"
"github.com/hashicorp/packer/packer-plugin-sdk/packerbuilderdata"
"github.com/hashicorp/packer/packer-plugin-sdk/template/interpolate"
"github.com/hashicorp/packer/template/interpolate"
)
type TagMap map[string]string
@@ -23,7 +23,7 @@ func (t EC2Tags) Report(ui packer.Ui) {
func (t TagMap) EC2Tags(ictx interpolate.Context, region string, state multistep.StateBag) (EC2Tags, error) {
var ec2Tags []*ec2.Tag
generatedData := packerbuilderdata.GeneratedData{State: state}
generatedData := builder.GeneratedData{State: state}
ictx.Data = extractBuildInfo(region, state, &generatedData)
for key, value := range t {
+8 -17
View File
@@ -15,16 +15,15 @@ import (
"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/hcl2template"
"github.com/hashicorp/packer/helper/communicator"
"github.com/hashicorp/packer/helper/config"
"github.com/hashicorp/packer/helper/multistep"
"github.com/hashicorp/packer/packer"
"github.com/hashicorp/packer/packer-plugin-sdk/common"
"github.com/hashicorp/packer/packer-plugin-sdk/commonsteps"
"github.com/hashicorp/packer/packer-plugin-sdk/config"
"github.com/hashicorp/packer/packer-plugin-sdk/packerbuilderdata"
"github.com/hashicorp/packer/packer-plugin-sdk/template/interpolate"
"github.com/hashicorp/packer/template/interpolate"
)
// The unique ID for this builder
@@ -86,22 +85,16 @@ func (b *Builder) ConfigSpec() hcldec.ObjectSpec { return b.config.FlatMapstruct
func (b *Builder) Prepare(raws ...interface{}) ([]string, []string, error) {
b.config.ctx.Funcs = awscommon.TemplateFuncs
err := config.Decode(&b.config, &config.DecodeOpts{
PluginType: BuilderId,
Interpolate: true,
InterpolateContext: &b.config.ctx,
InterpolateFilter: &interpolate.RenderFilter{
Exclude: []string{
"ami_description",
"run_tags",
"run_tag",
"run_volume_tags",
"run_volume_tag",
"spot_tags",
"spot_tag",
"snapshot_tags",
"snapshot_tag",
"tags",
"tag",
},
},
}, raws...)
@@ -170,7 +163,7 @@ func (b *Builder) Run(ctx context.Context, ui packer.Ui, hook packer.Hook) (pack
state.Put("awsSession", session)
state.Put("hook", hook)
state.Put("ui", ui)
generatedData := &packerbuilderdata.GeneratedData{State: state}
generatedData := &builder.GeneratedData{State: state}
var instanceStep multistep.Step
@@ -187,7 +180,6 @@ func (b *Builder) Run(ctx context.Context, ui packer.Ui, hook packer.Hook) (pack
ExpectedRootDevice: "ebs",
InstanceInitiatedShutdownBehavior: b.config.InstanceInitiatedShutdownBehavior,
InstanceType: b.config.InstanceType,
Region: *ec2conn.Config.Region,
SourceAMI: b.config.SourceAmi,
SpotPrice: b.config.SpotPrice,
SpotTags: b.config.SpotTags,
@@ -214,7 +206,6 @@ func (b *Builder) Run(ctx context.Context, ui packer.Ui, hook packer.Hook) (pack
IsRestricted: b.config.IsChinaCloud() || b.config.IsGovCloud(),
SourceAMI: b.config.SourceAmi,
Tags: b.config.RunTags,
Tenancy: b.config.Tenancy,
UserData: b.config.UserData,
UserDataFile: b.config.UserDataFile,
VolumeTags: b.config.VolumeRunTags,
@@ -299,8 +290,8 @@ func (b *Builder) Run(ctx context.Context, ui packer.Ui, hook packer.Hook) (pack
&awscommon.StepSetGeneratedData{
GeneratedData: generatedData,
},
&commonsteps.StepProvision{},
&commonsteps.StepCleanupTempKeys{
&common.StepProvision{},
&common.StepCleanupTempKeys{
Comm: &b.config.RunConfig.Comm,
},
&awscommon.StepStopEBSBackedInstance{
@@ -351,7 +342,7 @@ func (b *Builder) Run(ctx context.Context, ui packer.Ui, hook packer.Hook) (pack
}
// Run!
b.runner = commonsteps.NewRunner(steps, b.config.PackerConfig, ui)
b.runner = common.NewRunner(steps, b.config.PackerConfig, ui)
b.runner.Run(ctx, state)
// If there was an error, return that
if rawErr, ok := state.GetOk("error"); ok {
-8
View File
@@ -13,7 +13,6 @@ import (
type FlatConfig struct {
PackerBuildName *string `mapstructure:"packer_build_name" cty:"packer_build_name" hcl:"packer_build_name"`
PackerBuilderType *string `mapstructure:"packer_builder_type" cty:"packer_builder_type" hcl:"packer_builder_type"`
PackerCoreVersion *string `mapstructure:"packer_core_version" cty:"packer_core_version" hcl:"packer_core_version"`
PackerDebug *bool `mapstructure:"packer_debug" cty:"packer_debug" hcl:"packer_debug"`
PackerForce *bool `mapstructure:"packer_force" cty:"packer_force" hcl:"packer_force"`
PackerOnError *string `mapstructure:"packer_on_error" cty:"packer_on_error" hcl:"packer_on_error"`
@@ -82,7 +81,6 @@ type FlatConfig struct {
SpotTag []hcl2template.FlatKeyValue `mapstructure:"spot_tag" required:"false" cty:"spot_tag" hcl:"spot_tag"`
SubnetFilter *common.FlatSubnetFilterOptions `mapstructure:"subnet_filter" required:"false" cty:"subnet_filter" hcl:"subnet_filter"`
SubnetId *string `mapstructure:"subnet_id" required:"false" cty:"subnet_id" hcl:"subnet_id"`
Tenancy *string `mapstructure:"tenancy" required:"false" cty:"tenancy" hcl:"tenancy"`
TemporaryKeyPairName *string `mapstructure:"temporary_key_pair_name" required:"false" cty:"temporary_key_pair_name" hcl:"temporary_key_pair_name"`
TemporarySGSourceCidrs []string `mapstructure:"temporary_security_group_source_cidrs" required:"false" cty:"temporary_security_group_source_cidrs" hcl:"temporary_security_group_source_cidrs"`
UserData *string `mapstructure:"user_data" required:"false" cty:"user_data" hcl:"user_data"`
@@ -97,8 +95,6 @@ type FlatConfig struct {
SSHUsername *string `mapstructure:"ssh_username" cty:"ssh_username" hcl:"ssh_username"`
SSHPassword *string `mapstructure:"ssh_password" cty:"ssh_password" hcl:"ssh_password"`
SSHKeyPairName *string `mapstructure:"ssh_keypair_name" undocumented:"true" cty:"ssh_keypair_name" hcl:"ssh_keypair_name"`
SSHTemporaryKeyPairType *string `mapstructure:"temporary_key_pair_type" cty:"temporary_key_pair_type" hcl:"temporary_key_pair_type"`
SSHTemporaryKeyPairBits *int `mapstructure:"temporary_key_pair_bits" cty:"temporary_key_pair_bits" hcl:"temporary_key_pair_bits"`
SSHCiphers []string `mapstructure:"ssh_ciphers" cty:"ssh_ciphers" hcl:"ssh_ciphers"`
SSHClearAuthorizedKeys *bool `mapstructure:"ssh_clear_authorized_keys" cty:"ssh_clear_authorized_keys" hcl:"ssh_clear_authorized_keys"`
SSHKEXAlgos []string `mapstructure:"ssh_key_exchange_algorithms" cty:"ssh_key_exchange_algorithms" hcl:"ssh_key_exchange_algorithms"`
@@ -162,7 +158,6 @@ func (*FlatConfig) HCL2Spec() map[string]hcldec.Spec {
s := map[string]hcldec.Spec{
"packer_build_name": &hcldec.AttrSpec{Name: "packer_build_name", Type: cty.String, Required: false},
"packer_builder_type": &hcldec.AttrSpec{Name: "packer_builder_type", Type: cty.String, Required: false},
"packer_core_version": &hcldec.AttrSpec{Name: "packer_core_version", Type: cty.String, Required: false},
"packer_debug": &hcldec.AttrSpec{Name: "packer_debug", Type: cty.Bool, Required: false},
"packer_force": &hcldec.AttrSpec{Name: "packer_force", Type: cty.Bool, Required: false},
"packer_on_error": &hcldec.AttrSpec{Name: "packer_on_error", Type: cty.String, Required: false},
@@ -231,7 +226,6 @@ func (*FlatConfig) HCL2Spec() map[string]hcldec.Spec {
"spot_tag": &hcldec.BlockListSpec{TypeName: "spot_tag", Nested: hcldec.ObjectSpec((*hcl2template.FlatKeyValue)(nil).HCL2Spec())},
"subnet_filter": &hcldec.BlockSpec{TypeName: "subnet_filter", Nested: hcldec.ObjectSpec((*common.FlatSubnetFilterOptions)(nil).HCL2Spec())},
"subnet_id": &hcldec.AttrSpec{Name: "subnet_id", Type: cty.String, Required: false},
"tenancy": &hcldec.AttrSpec{Name: "tenancy", Type: cty.String, Required: false},
"temporary_key_pair_name": &hcldec.AttrSpec{Name: "temporary_key_pair_name", Type: cty.String, Required: false},
"temporary_security_group_source_cidrs": &hcldec.AttrSpec{Name: "temporary_security_group_source_cidrs", Type: cty.List(cty.String), Required: false},
"user_data": &hcldec.AttrSpec{Name: "user_data", Type: cty.String, Required: false},
@@ -246,8 +240,6 @@ func (*FlatConfig) HCL2Spec() map[string]hcldec.Spec {
"ssh_username": &hcldec.AttrSpec{Name: "ssh_username", Type: cty.String, Required: false},
"ssh_password": &hcldec.AttrSpec{Name: "ssh_password", Type: cty.String, Required: false},
"ssh_keypair_name": &hcldec.AttrSpec{Name: "ssh_keypair_name", Type: cty.String, Required: false},
"temporary_key_pair_type": &hcldec.AttrSpec{Name: "temporary_key_pair_type", Type: cty.String, Required: false},
"temporary_key_pair_bits": &hcldec.AttrSpec{Name: "temporary_key_pair_bits", Type: cty.Number, Required: false},
"ssh_ciphers": &hcldec.AttrSpec{Name: "ssh_ciphers", Type: cty.List(cty.String), Required: false},
"ssh_clear_authorized_keys": &hcldec.AttrSpec{Name: "ssh_clear_authorized_keys", Type: cty.Bool, Required: false},
"ssh_key_exchange_algorithms": &hcldec.AttrSpec{Name: "ssh_key_exchange_algorithms", Type: cty.List(cty.String), Required: false},
-33
View File
@@ -246,14 +246,6 @@ func checkBootEncrypted() builderT.TestCheckFunc {
}
}
func TestBuilderAcc_SessionManagerInterface(t *testing.T) {
builderT.Test(t, builderT.TestCase{
PreCheck: func() { testAccPreCheck(t) },
Builder: &Builder{},
Template: testBuilderAccSessionManagerInterface,
})
}
func testAccPreCheck(t *testing.T) {
}
@@ -358,31 +350,6 @@ const testBuilderAccEncrypted = `
}
`
const testBuilderAccSessionManagerInterface = `
{
"builders": [{
"type": "test",
"region": "us-east-1",
"instance_type": "m3.medium",
"source_ami_filter": {
"filters": {
"virtualization-type": "hvm",
"name": "ubuntu/images/*ubuntu-xenial-16.04-amd64-server-*",
"root-device-type": "ebs"
},
"owners": [
"099720109477"
],
"most_recent": true
},
"ssh_username": "ubuntu",
"ssh_interface": "session_manager",
"iam_instance_profile": "SSMInstanceProfile",
"ami_name": "packer-ssm-test-{{timestamp}}"
}]
}
`
func buildForceDeregisterConfig(val, name string) string {
return fmt.Sprintf(testBuilderAccForceDeregister, val, name)
}
+3 -4
View File
@@ -9,11 +9,10 @@ import (
"github.com/aws/aws-sdk-go/aws"
"github.com/aws/aws-sdk-go/service/ec2"
awscommon "github.com/hashicorp/packer/builder/amazon/common"
"github.com/hashicorp/packer/builder/amazon/common/awserrors"
"github.com/hashicorp/packer/common/random"
"github.com/hashicorp/packer/common/retry"
"github.com/hashicorp/packer/helper/multistep"
"github.com/hashicorp/packer/packer"
"github.com/hashicorp/packer/packer-plugin-sdk/random"
"github.com/hashicorp/packer/packer-plugin-sdk/retry"
)
type stepCreateAMI struct {
@@ -62,7 +61,7 @@ func (s *stepCreateAMI) Run(ctx context.Context, state multistep.StateBag) multi
err = retry.Config{
Tries: 0,
ShouldRetry: func(err error) bool {
if awserrors.Matches(err, "InvalidParameterValue", "Instance is not in state") {
if awscommon.IsAWSErr(err, "InvalidParameterValue", "Instance is not in state") {
return true
}
return false
+1 -1
View File
@@ -5,7 +5,7 @@ package ebssurrogate
import (
"github.com/aws/aws-sdk-go/service/ec2"
awscommon "github.com/hashicorp/packer/builder/amazon/common"
"github.com/hashicorp/packer/packer-plugin-sdk/template/interpolate"
"github.com/hashicorp/packer/template/interpolate"
)
type BlockDevice struct {
+8 -19
View File
@@ -13,16 +13,15 @@ import (
"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/hcl2template"
"github.com/hashicorp/packer/helper/communicator"
"github.com/hashicorp/packer/helper/config"
"github.com/hashicorp/packer/helper/multistep"
"github.com/hashicorp/packer/packer"
"github.com/hashicorp/packer/packer-plugin-sdk/common"
"github.com/hashicorp/packer/packer-plugin-sdk/commonsteps"
"github.com/hashicorp/packer/packer-plugin-sdk/config"
"github.com/hashicorp/packer/packer-plugin-sdk/packerbuilderdata"
"github.com/hashicorp/packer/packer-plugin-sdk/template/interpolate"
"github.com/hashicorp/packer/template/interpolate"
)
const BuilderId = "mitchellh.amazon.ebssurrogate"
@@ -85,22 +84,16 @@ func (b *Builder) ConfigSpec() hcldec.ObjectSpec { return b.config.FlatMapstruct
func (b *Builder) Prepare(raws ...interface{}) ([]string, []string, error) {
b.config.ctx.Funcs = awscommon.TemplateFuncs
err := config.Decode(&b.config, &config.DecodeOpts{
PluginType: BuilderId,
Interpolate: true,
InterpolateContext: &b.config.ctx,
InterpolateFilter: &interpolate.RenderFilter{
Exclude: []string{
"ami_description",
"run_tags",
"run_tag",
"run_volume_tags",
"run_volume_tag",
"snapshot_tags",
"snapshot_tag",
"spot_tags",
"spot_tag",
"tags",
"tag",
},
},
}, raws...)
@@ -193,7 +186,7 @@ func (b *Builder) Run(ctx context.Context, ui packer.Ui, hook packer.Hook) (pack
state.Put("awsSession", session)
state.Put("hook", hook)
state.Put("ui", ui)
generatedData := &packerbuilderdata.GeneratedData{State: state}
generatedData := &builder.GeneratedData{State: state}
var instanceStep multistep.Step
@@ -210,7 +203,6 @@ func (b *Builder) Run(ctx context.Context, ui packer.Ui, hook packer.Hook) (pack
ExpectedRootDevice: "ebs",
InstanceInitiatedShutdownBehavior: b.config.InstanceInitiatedShutdownBehavior,
InstanceType: b.config.InstanceType,
Region: *ec2conn.Config.Region,
SourceAMI: b.config.SourceAmi,
SpotPrice: b.config.SpotPrice,
SpotInstanceTypes: b.config.SpotInstanceTypes,
@@ -236,7 +228,6 @@ func (b *Builder) Run(ctx context.Context, ui packer.Ui, hook packer.Hook) (pack
IsRestricted: b.config.IsChinaCloud() || b.config.IsGovCloud(),
SourceAMI: b.config.SourceAmi,
Tags: b.config.RunTags,
Tenancy: b.config.Tenancy,
UserData: b.config.UserData,
UserDataFile: b.config.UserDataFile,
VolumeTags: b.config.VolumeRunTags,
@@ -323,8 +314,8 @@ func (b *Builder) Run(ctx context.Context, ui packer.Ui, hook packer.Hook) (pack
&awscommon.StepSetGeneratedData{
GeneratedData: generatedData,
},
&commonsteps.StepProvision{},
&commonsteps.StepCleanupTempKeys{
&common.StepProvision{},
&common.StepCleanupTempKeys{
Comm: &b.config.RunConfig.Comm,
},
&awscommon.StepStopEBSBackedInstance{
@@ -341,8 +332,6 @@ func (b *Builder) Run(ctx context.Context, ui packer.Ui, hook packer.Hook) (pack
PollingConfig: b.config.PollingConfig,
LaunchDevices: launchDevices,
SnapshotOmitMap: b.config.LaunchMappings.GetOmissions(),
SnapshotTags: b.config.SnapshotTags,
Ctx: b.config.ctx,
},
&awscommon.StepDeregisterAMI{
AccessConfig: &b.config.AccessConfig,
@@ -390,7 +379,7 @@ func (b *Builder) Run(ctx context.Context, ui packer.Ui, hook packer.Hook) (pack
}
// Run!
b.runner = commonsteps.NewRunner(steps, b.config.PackerConfig, ui)
b.runner = common.NewRunner(steps, b.config.PackerConfig, ui)
b.runner.Run(ctx, state)
// If there was an error, return that
@@ -56,7 +56,6 @@ func (*FlatBlockDevice) HCL2Spec() map[string]hcldec.Spec {
type FlatConfig struct {
PackerBuildName *string `mapstructure:"packer_build_name" cty:"packer_build_name" hcl:"packer_build_name"`
PackerBuilderType *string `mapstructure:"packer_builder_type" cty:"packer_builder_type" hcl:"packer_builder_type"`
PackerCoreVersion *string `mapstructure:"packer_core_version" cty:"packer_core_version" hcl:"packer_core_version"`
PackerDebug *bool `mapstructure:"packer_debug" cty:"packer_debug" hcl:"packer_debug"`
PackerForce *bool `mapstructure:"packer_force" cty:"packer_force" hcl:"packer_force"`
PackerOnError *string `mapstructure:"packer_on_error" cty:"packer_on_error" hcl:"packer_on_error"`
@@ -104,7 +103,6 @@ type FlatConfig struct {
SpotTag []hcl2template.FlatKeyValue `mapstructure:"spot_tag" required:"false" cty:"spot_tag" hcl:"spot_tag"`
SubnetFilter *common.FlatSubnetFilterOptions `mapstructure:"subnet_filter" required:"false" cty:"subnet_filter" hcl:"subnet_filter"`
SubnetId *string `mapstructure:"subnet_id" required:"false" cty:"subnet_id" hcl:"subnet_id"`
Tenancy *string `mapstructure:"tenancy" required:"false" cty:"tenancy" hcl:"tenancy"`
TemporaryKeyPairName *string `mapstructure:"temporary_key_pair_name" required:"false" cty:"temporary_key_pair_name" hcl:"temporary_key_pair_name"`
TemporarySGSourceCidrs []string `mapstructure:"temporary_security_group_source_cidrs" required:"false" cty:"temporary_security_group_source_cidrs" hcl:"temporary_security_group_source_cidrs"`
UserData *string `mapstructure:"user_data" required:"false" cty:"user_data" hcl:"user_data"`
@@ -119,8 +117,6 @@ type FlatConfig struct {
SSHUsername *string `mapstructure:"ssh_username" cty:"ssh_username" hcl:"ssh_username"`
SSHPassword *string `mapstructure:"ssh_password" cty:"ssh_password" hcl:"ssh_password"`
SSHKeyPairName *string `mapstructure:"ssh_keypair_name" undocumented:"true" cty:"ssh_keypair_name" hcl:"ssh_keypair_name"`
SSHTemporaryKeyPairType *string `mapstructure:"temporary_key_pair_type" cty:"temporary_key_pair_type" hcl:"temporary_key_pair_type"`
SSHTemporaryKeyPairBits *int `mapstructure:"temporary_key_pair_bits" cty:"temporary_key_pair_bits" hcl:"temporary_key_pair_bits"`
SSHCiphers []string `mapstructure:"ssh_ciphers" cty:"ssh_ciphers" hcl:"ssh_ciphers"`
SSHClearAuthorizedKeys *bool `mapstructure:"ssh_clear_authorized_keys" cty:"ssh_clear_authorized_keys" hcl:"ssh_clear_authorized_keys"`
SSHKEXAlgos []string `mapstructure:"ssh_key_exchange_algorithms" cty:"ssh_key_exchange_algorithms" hcl:"ssh_key_exchange_algorithms"`
@@ -206,7 +202,6 @@ func (*FlatConfig) HCL2Spec() map[string]hcldec.Spec {
s := map[string]hcldec.Spec{
"packer_build_name": &hcldec.AttrSpec{Name: "packer_build_name", Type: cty.String, Required: false},
"packer_builder_type": &hcldec.AttrSpec{Name: "packer_builder_type", Type: cty.String, Required: false},
"packer_core_version": &hcldec.AttrSpec{Name: "packer_core_version", Type: cty.String, Required: false},
"packer_debug": &hcldec.AttrSpec{Name: "packer_debug", Type: cty.Bool, Required: false},
"packer_force": &hcldec.AttrSpec{Name: "packer_force", Type: cty.Bool, Required: false},
"packer_on_error": &hcldec.AttrSpec{Name: "packer_on_error", Type: cty.String, Required: false},
@@ -254,7 +249,6 @@ func (*FlatConfig) HCL2Spec() map[string]hcldec.Spec {
"spot_tag": &hcldec.BlockListSpec{TypeName: "spot_tag", Nested: hcldec.ObjectSpec((*hcl2template.FlatKeyValue)(nil).HCL2Spec())},
"subnet_filter": &hcldec.BlockSpec{TypeName: "subnet_filter", Nested: hcldec.ObjectSpec((*common.FlatSubnetFilterOptions)(nil).HCL2Spec())},
"subnet_id": &hcldec.AttrSpec{Name: "subnet_id", Type: cty.String, Required: false},
"tenancy": &hcldec.AttrSpec{Name: "tenancy", Type: cty.String, Required: false},
"temporary_key_pair_name": &hcldec.AttrSpec{Name: "temporary_key_pair_name", Type: cty.String, Required: false},
"temporary_security_group_source_cidrs": &hcldec.AttrSpec{Name: "temporary_security_group_source_cidrs", Type: cty.List(cty.String), Required: false},
"user_data": &hcldec.AttrSpec{Name: "user_data", Type: cty.String, Required: false},
@@ -269,8 +263,6 @@ func (*FlatConfig) HCL2Spec() map[string]hcldec.Spec {
"ssh_username": &hcldec.AttrSpec{Name: "ssh_username", Type: cty.String, Required: false},
"ssh_password": &hcldec.AttrSpec{Name: "ssh_password", Type: cty.String, Required: false},
"ssh_keypair_name": &hcldec.AttrSpec{Name: "ssh_keypair_name", Type: cty.String, Required: false},
"temporary_key_pair_type": &hcldec.AttrSpec{Name: "temporary_key_pair_type", Type: cty.String, Required: false},
"temporary_key_pair_bits": &hcldec.AttrSpec{Name: "temporary_key_pair_bits", Type: cty.Number, Required: false},
"ssh_ciphers": &hcldec.AttrSpec{Name: "ssh_ciphers", Type: cty.List(cty.String), Required: false},
"ssh_clear_authorized_keys": &hcldec.AttrSpec{Name: "ssh_clear_authorized_keys", Type: cty.Bool, Required: false},
"ssh_key_exchange_algorithms": &hcldec.AttrSpec{Name: "ssh_key_exchange_algorithms", Type: cty.List(cty.String), Required: false},
@@ -5,7 +5,7 @@ package ebssurrogate
import (
"errors"
"github.com/hashicorp/packer/packer-plugin-sdk/template/interpolate"
"github.com/hashicorp/packer/template/interpolate"
)
type RootBlockDevice struct {
@@ -7,10 +7,10 @@ import (
"github.com/aws/aws-sdk-go/aws"
"github.com/aws/aws-sdk-go/service/ec2"
awscommon "github.com/hashicorp/packer/builder/amazon/common"
"github.com/hashicorp/packer/common/random"
confighelper "github.com/hashicorp/packer/helper/config"
"github.com/hashicorp/packer/helper/multistep"
"github.com/hashicorp/packer/packer"
confighelper "github.com/hashicorp/packer/packer-plugin-sdk/config"
"github.com/hashicorp/packer/packer-plugin-sdk/random"
)
// StepRegisterAMI creates the AMI.
@@ -6,13 +6,11 @@ import (
"sync"
"time"
"github.com/aws/aws-sdk-go/aws"
"github.com/aws/aws-sdk-go/service/ec2"
multierror "github.com/hashicorp/go-multierror"
awscommon "github.com/hashicorp/packer/builder/amazon/common"
"github.com/hashicorp/packer/helper/multistep"
"github.com/hashicorp/packer/packer"
"github.com/hashicorp/packer/packer-plugin-sdk/template/interpolate"
)
// StepSnapshotVolumes creates snapshots of the created volumes.
@@ -25,8 +23,6 @@ type StepSnapshotVolumes struct {
snapshotIds map[string]string
snapshotMutex sync.Mutex
SnapshotOmitMap map[string]bool
SnapshotTags map[string]string
Ctx interpolate.Context
}
func (s *StepSnapshotVolumes) snapshotVolume(ctx context.Context, deviceName string, state multistep.StateBag) error {
@@ -44,34 +40,12 @@ func (s *StepSnapshotVolumes) snapshotVolume(ctx context.Context, deviceName str
return fmt.Errorf("Volume ID for device %s not found", deviceName)
}
ui.Say("Creating snapshot tags")
snapshotTags, err := awscommon.TagMap(s.SnapshotTags).EC2Tags(s.Ctx, *ec2conn.Config.Region, state)
if err != nil {
state.Put("error", err)
ui.Error(err.Error())
return err
}
snapshotTags.Report(ui)
ui.Say(fmt.Sprintf("Creating snapshot of EBS Volume %s...", volumeId))
description := fmt.Sprintf("Packer: %s", time.Now().String())
// Collect tags for tagging on resource creation
var tagSpecs []*ec2.TagSpecification
if len(snapshotTags) > 0 {
snapTags := &ec2.TagSpecification{
ResourceType: aws.String("snapshot"),
Tags: snapshotTags,
}
tagSpecs = append(tagSpecs, snapTags)
}
createSnapResp, err := ec2conn.CreateSnapshot(&ec2.CreateSnapshotInput{
VolumeId: &volumeId,
Description: &description,
TagSpecifications: tagSpecs,
VolumeId: &volumeId,
Description: &description,
})
if err != nil {
return err
+1 -1
View File
@@ -6,7 +6,7 @@ import (
"github.com/aws/aws-sdk-go/service/ec2"
awscommon "github.com/hashicorp/packer/builder/amazon/common"
"github.com/hashicorp/packer/hcl2template"
"github.com/hashicorp/packer/packer-plugin-sdk/template/interpolate"
"github.com/hashicorp/packer/template/interpolate"
)
type BlockDevice struct {
+8 -24
View File
@@ -12,16 +12,15 @@ import (
"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/hcl2template"
"github.com/hashicorp/packer/helper/communicator"
"github.com/hashicorp/packer/helper/config"
"github.com/hashicorp/packer/helper/multistep"
"github.com/hashicorp/packer/packer"
"github.com/hashicorp/packer/packer-plugin-sdk/common"
"github.com/hashicorp/packer/packer-plugin-sdk/commonsteps"
"github.com/hashicorp/packer/packer-plugin-sdk/config"
"github.com/hashicorp/packer/packer-plugin-sdk/packerbuilderdata"
"github.com/hashicorp/packer/packer-plugin-sdk/template/interpolate"
"github.com/hashicorp/packer/template/interpolate"
)
const BuilderId = "mitchellh.amazon.ebsvolume"
@@ -101,21 +100,8 @@ func (b *Builder) Prepare(raws ...interface{}) ([]string, []string, error) {
SourceAMI: `{{ .SourceAMI }} `,
}
err := config.Decode(&b.config, &config.DecodeOpts{
PluginType: BuilderId,
Interpolate: true,
InterpolateContext: &b.config.ctx,
InterpolateFilter: &interpolate.RenderFilter{
Exclude: []string{
"run_tags",
"run_tag",
"run_volume_tags",
"run_volume_tag",
"spot_tags",
"spot_tag",
"tags",
"tag",
},
},
}, raws...)
if err != nil {
return nil, nil, err
@@ -181,7 +167,7 @@ func (b *Builder) Run(ctx context.Context, ui packer.Ui, hook packer.Hook) (pack
state.Put("iam", iam)
state.Put("hook", hook)
state.Put("ui", ui)
generatedData := &packerbuilderdata.GeneratedData{State: state}
generatedData := &builder.GeneratedData{State: state}
var instanceStep multistep.Step
@@ -198,7 +184,6 @@ func (b *Builder) Run(ctx context.Context, ui packer.Ui, hook packer.Hook) (pack
ExpectedRootDevice: "ebs",
InstanceInitiatedShutdownBehavior: b.config.InstanceInitiatedShutdownBehavior,
InstanceType: b.config.InstanceType,
Region: *ec2conn.Config.Region,
SourceAMI: b.config.SourceAmi,
SpotInstanceTypes: b.config.SpotInstanceTypes,
SpotPrice: b.config.SpotPrice,
@@ -224,7 +209,6 @@ func (b *Builder) Run(ctx context.Context, ui packer.Ui, hook packer.Hook) (pack
IsRestricted: b.config.IsChinaCloud() || b.config.IsGovCloud(),
SourceAMI: b.config.SourceAmi,
Tags: b.config.RunTags,
Tenancy: b.config.Tenancy,
UserData: b.config.UserData,
UserDataFile: b.config.UserDataFile,
VolumeTags: b.config.VolumeRunTags,
@@ -300,8 +284,8 @@ func (b *Builder) Run(ctx context.Context, ui packer.Ui, hook packer.Hook) (pack
&awscommon.StepSetGeneratedData{
GeneratedData: generatedData,
},
&commonsteps.StepProvision{},
&commonsteps.StepCleanupTempKeys{
&common.StepProvision{},
&common.StepCleanupTempKeys{
Comm: &b.config.RunConfig.Comm,
},
&awscommon.StepStopEBSBackedInstance{
@@ -316,7 +300,7 @@ func (b *Builder) Run(ctx context.Context, ui packer.Ui, hook packer.Hook) (pack
}
// Run!
b.runner = commonsteps.NewRunner(steps, b.config.PackerConfig, ui)
b.runner = common.NewRunner(steps, b.config.PackerConfig, ui)
b.runner.Run(ctx, state)
// If there was an error, return that
@@ -58,7 +58,6 @@ func (*FlatBlockDevice) HCL2Spec() map[string]hcldec.Spec {
type FlatConfig struct {
PackerBuildName *string `mapstructure:"packer_build_name" cty:"packer_build_name" hcl:"packer_build_name"`
PackerBuilderType *string `mapstructure:"packer_builder_type" cty:"packer_builder_type" hcl:"packer_builder_type"`
PackerCoreVersion *string `mapstructure:"packer_core_version" cty:"packer_core_version" hcl:"packer_core_version"`
PackerDebug *bool `mapstructure:"packer_debug" cty:"packer_debug" hcl:"packer_debug"`
PackerForce *bool `mapstructure:"packer_force" cty:"packer_force" hcl:"packer_force"`
PackerOnError *string `mapstructure:"packer_on_error" cty:"packer_on_error" hcl:"packer_on_error"`
@@ -106,7 +105,6 @@ type FlatConfig struct {
SpotTag []hcl2template.FlatKeyValue `mapstructure:"spot_tag" required:"false" cty:"spot_tag" hcl:"spot_tag"`
SubnetFilter *common.FlatSubnetFilterOptions `mapstructure:"subnet_filter" required:"false" cty:"subnet_filter" hcl:"subnet_filter"`
SubnetId *string `mapstructure:"subnet_id" required:"false" cty:"subnet_id" hcl:"subnet_id"`
Tenancy *string `mapstructure:"tenancy" required:"false" cty:"tenancy" hcl:"tenancy"`
TemporaryKeyPairName *string `mapstructure:"temporary_key_pair_name" required:"false" cty:"temporary_key_pair_name" hcl:"temporary_key_pair_name"`
TemporarySGSourceCidrs []string `mapstructure:"temporary_security_group_source_cidrs" required:"false" cty:"temporary_security_group_source_cidrs" hcl:"temporary_security_group_source_cidrs"`
UserData *string `mapstructure:"user_data" required:"false" cty:"user_data" hcl:"user_data"`
@@ -121,8 +119,6 @@ type FlatConfig struct {
SSHUsername *string `mapstructure:"ssh_username" cty:"ssh_username" hcl:"ssh_username"`
SSHPassword *string `mapstructure:"ssh_password" cty:"ssh_password" hcl:"ssh_password"`
SSHKeyPairName *string `mapstructure:"ssh_keypair_name" undocumented:"true" cty:"ssh_keypair_name" hcl:"ssh_keypair_name"`
SSHTemporaryKeyPairType *string `mapstructure:"temporary_key_pair_type" cty:"temporary_key_pair_type" hcl:"temporary_key_pair_type"`
SSHTemporaryKeyPairBits *int `mapstructure:"temporary_key_pair_bits" cty:"temporary_key_pair_bits" hcl:"temporary_key_pair_bits"`
SSHCiphers []string `mapstructure:"ssh_ciphers" cty:"ssh_ciphers" hcl:"ssh_ciphers"`
SSHClearAuthorizedKeys *bool `mapstructure:"ssh_clear_authorized_keys" cty:"ssh_clear_authorized_keys" hcl:"ssh_clear_authorized_keys"`
SSHKEXAlgos []string `mapstructure:"ssh_key_exchange_algorithms" cty:"ssh_key_exchange_algorithms" hcl:"ssh_key_exchange_algorithms"`
@@ -186,7 +182,6 @@ func (*FlatConfig) HCL2Spec() map[string]hcldec.Spec {
s := map[string]hcldec.Spec{
"packer_build_name": &hcldec.AttrSpec{Name: "packer_build_name", Type: cty.String, Required: false},
"packer_builder_type": &hcldec.AttrSpec{Name: "packer_builder_type", Type: cty.String, Required: false},
"packer_core_version": &hcldec.AttrSpec{Name: "packer_core_version", Type: cty.String, Required: false},
"packer_debug": &hcldec.AttrSpec{Name: "packer_debug", Type: cty.Bool, Required: false},
"packer_force": &hcldec.AttrSpec{Name: "packer_force", Type: cty.Bool, Required: false},
"packer_on_error": &hcldec.AttrSpec{Name: "packer_on_error", Type: cty.String, Required: false},
@@ -234,7 +229,6 @@ func (*FlatConfig) HCL2Spec() map[string]hcldec.Spec {
"spot_tag": &hcldec.BlockListSpec{TypeName: "spot_tag", Nested: hcldec.ObjectSpec((*hcl2template.FlatKeyValue)(nil).HCL2Spec())},
"subnet_filter": &hcldec.BlockSpec{TypeName: "subnet_filter", Nested: hcldec.ObjectSpec((*common.FlatSubnetFilterOptions)(nil).HCL2Spec())},
"subnet_id": &hcldec.AttrSpec{Name: "subnet_id", Type: cty.String, Required: false},
"tenancy": &hcldec.AttrSpec{Name: "tenancy", Type: cty.String, Required: false},
"temporary_key_pair_name": &hcldec.AttrSpec{Name: "temporary_key_pair_name", Type: cty.String, Required: false},
"temporary_security_group_source_cidrs": &hcldec.AttrSpec{Name: "temporary_security_group_source_cidrs", Type: cty.List(cty.String), Required: false},
"user_data": &hcldec.AttrSpec{Name: "user_data", Type: cty.String, Required: false},
@@ -249,8 +243,6 @@ func (*FlatConfig) HCL2Spec() map[string]hcldec.Spec {
"ssh_username": &hcldec.AttrSpec{Name: "ssh_username", Type: cty.String, Required: false},
"ssh_password": &hcldec.AttrSpec{Name: "ssh_password", Type: cty.String, Required: false},
"ssh_keypair_name": &hcldec.AttrSpec{Name: "ssh_keypair_name", Type: cty.String, Required: false},
"temporary_key_pair_type": &hcldec.AttrSpec{Name: "temporary_key_pair_type", Type: cty.String, Required: false},
"temporary_key_pair_bits": &hcldec.AttrSpec{Name: "temporary_key_pair_bits", Type: cty.Number, Required: false},
"ssh_ciphers": &hcldec.AttrSpec{Name: "ssh_ciphers", Type: cty.List(cty.String), Required: false},
"ssh_clear_authorized_keys": &hcldec.AttrSpec{Name: "ssh_clear_authorized_keys", Type: cty.Bool, Required: false},
"ssh_key_exchange_algorithms": &hcldec.AttrSpec{Name: "ssh_key_exchange_algorithms", Type: cty.List(cty.String), Required: false},
@@ -10,7 +10,7 @@ import (
awscommon "github.com/hashicorp/packer/builder/amazon/common"
"github.com/hashicorp/packer/helper/multistep"
"github.com/hashicorp/packer/packer"
"github.com/hashicorp/packer/packer-plugin-sdk/template/interpolate"
"github.com/hashicorp/packer/template/interpolate"
)
type stepTagEBSVolumes struct {
+8 -12
View File
@@ -15,15 +15,14 @@ import (
"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"
"github.com/hashicorp/packer/helper/config"
"github.com/hashicorp/packer/helper/multistep"
"github.com/hashicorp/packer/packer"
"github.com/hashicorp/packer/packer-plugin-sdk/common"
"github.com/hashicorp/packer/packer-plugin-sdk/commonsteps"
"github.com/hashicorp/packer/packer-plugin-sdk/config"
"github.com/hashicorp/packer/packer-plugin-sdk/packerbuilderdata"
"github.com/hashicorp/packer/packer-plugin-sdk/template/interpolate"
"github.com/hashicorp/packer/template/interpolate"
)
// The unique ID for this builder
@@ -108,7 +107,6 @@ func (b *Builder) Prepare(raws ...interface{}) ([]string, []string, error) {
b.config.ctx.Funcs = awscommon.TemplateFuncs
err := config.Decode(&b.config, &config.DecodeOpts{
PluginType: BuilderId,
Interpolate: true,
InterpolateContext: &b.config.ctx,
InterpolateFilter: &interpolate.RenderFilter{
@@ -251,7 +249,7 @@ func (b *Builder) Run(ctx context.Context, ui packer.Ui, hook packer.Hook) (pack
state.Put("awsSession", session)
state.Put("hook", hook)
state.Put("ui", ui)
generatedData := &packerbuilderdata.GeneratedData{State: state}
generatedData := &builder.GeneratedData{State: state}
var instanceStep multistep.Step
@@ -266,7 +264,6 @@ func (b *Builder) Run(ctx context.Context, ui packer.Ui, hook packer.Hook) (pack
Debug: b.config.PackerDebug,
EbsOptimized: b.config.EbsOptimized,
InstanceType: b.config.InstanceType,
Region: *ec2conn.Config.Region,
SourceAMI: b.config.SourceAmi,
SpotPrice: b.config.SpotPrice,
SpotInstanceTypes: b.config.SpotInstanceTypes,
@@ -289,7 +286,6 @@ func (b *Builder) Run(ctx context.Context, ui packer.Ui, hook packer.Hook) (pack
IsRestricted: b.config.IsChinaCloud() || b.config.IsGovCloud(),
SourceAMI: b.config.SourceAmi,
Tags: b.config.RunTags,
Tenancy: b.config.Tenancy,
UserData: b.config.UserData,
UserDataFile: b.config.UserDataFile,
}
@@ -370,8 +366,8 @@ func (b *Builder) Run(ctx context.Context, ui packer.Ui, hook packer.Hook) (pack
&awscommon.StepSetGeneratedData{
GeneratedData: generatedData,
},
&commonsteps.StepProvision{},
&commonsteps.StepCleanupTempKeys{
&common.StepProvision{},
&common.StepCleanupTempKeys{
Comm: &b.config.RunConfig.Comm,
},
&StepUploadX509Cert{},
@@ -421,7 +417,7 @@ func (b *Builder) Run(ctx context.Context, ui packer.Ui, hook packer.Hook) (pack
}
// Run!
b.runner = commonsteps.NewRunner(steps, b.config.PackerConfig, ui)
b.runner = common.NewRunner(steps, b.config.PackerConfig, ui)
b.runner.Run(ctx, state)
// If there was an error, return that
@@ -13,7 +13,6 @@ import (
type FlatConfig struct {
PackerBuildName *string `mapstructure:"packer_build_name" cty:"packer_build_name" hcl:"packer_build_name"`
PackerBuilderType *string `mapstructure:"packer_builder_type" cty:"packer_builder_type" hcl:"packer_builder_type"`
PackerCoreVersion *string `mapstructure:"packer_core_version" cty:"packer_core_version" hcl:"packer_core_version"`
PackerDebug *bool `mapstructure:"packer_debug" cty:"packer_debug" hcl:"packer_debug"`
PackerForce *bool `mapstructure:"packer_force" cty:"packer_force" hcl:"packer_force"`
PackerOnError *string `mapstructure:"packer_on_error" cty:"packer_on_error" hcl:"packer_on_error"`
@@ -82,7 +81,6 @@ type FlatConfig struct {
SpotTag []hcl2template.FlatKeyValue `mapstructure:"spot_tag" required:"false" cty:"spot_tag" hcl:"spot_tag"`
SubnetFilter *common.FlatSubnetFilterOptions `mapstructure:"subnet_filter" required:"false" cty:"subnet_filter" hcl:"subnet_filter"`
SubnetId *string `mapstructure:"subnet_id" required:"false" cty:"subnet_id" hcl:"subnet_id"`
Tenancy *string `mapstructure:"tenancy" required:"false" cty:"tenancy" hcl:"tenancy"`
TemporaryKeyPairName *string `mapstructure:"temporary_key_pair_name" required:"false" cty:"temporary_key_pair_name" hcl:"temporary_key_pair_name"`
TemporarySGSourceCidrs []string `mapstructure:"temporary_security_group_source_cidrs" required:"false" cty:"temporary_security_group_source_cidrs" hcl:"temporary_security_group_source_cidrs"`
UserData *string `mapstructure:"user_data" required:"false" cty:"user_data" hcl:"user_data"`
@@ -97,8 +95,6 @@ type FlatConfig struct {
SSHUsername *string `mapstructure:"ssh_username" cty:"ssh_username" hcl:"ssh_username"`
SSHPassword *string `mapstructure:"ssh_password" cty:"ssh_password" hcl:"ssh_password"`
SSHKeyPairName *string `mapstructure:"ssh_keypair_name" undocumented:"true" cty:"ssh_keypair_name" hcl:"ssh_keypair_name"`
SSHTemporaryKeyPairType *string `mapstructure:"temporary_key_pair_type" cty:"temporary_key_pair_type" hcl:"temporary_key_pair_type"`
SSHTemporaryKeyPairBits *int `mapstructure:"temporary_key_pair_bits" cty:"temporary_key_pair_bits" hcl:"temporary_key_pair_bits"`
SSHCiphers []string `mapstructure:"ssh_ciphers" cty:"ssh_ciphers" hcl:"ssh_ciphers"`
SSHClearAuthorizedKeys *bool `mapstructure:"ssh_clear_authorized_keys" cty:"ssh_clear_authorized_keys" hcl:"ssh_clear_authorized_keys"`
SSHKEXAlgos []string `mapstructure:"ssh_key_exchange_algorithms" cty:"ssh_key_exchange_algorithms" hcl:"ssh_key_exchange_algorithms"`
@@ -168,7 +164,6 @@ func (*FlatConfig) HCL2Spec() map[string]hcldec.Spec {
s := map[string]hcldec.Spec{
"packer_build_name": &hcldec.AttrSpec{Name: "packer_build_name", Type: cty.String, Required: false},
"packer_builder_type": &hcldec.AttrSpec{Name: "packer_builder_type", Type: cty.String, Required: false},
"packer_core_version": &hcldec.AttrSpec{Name: "packer_core_version", Type: cty.String, Required: false},
"packer_debug": &hcldec.AttrSpec{Name: "packer_debug", Type: cty.Bool, Required: false},
"packer_force": &hcldec.AttrSpec{Name: "packer_force", Type: cty.Bool, Required: false},
"packer_on_error": &hcldec.AttrSpec{Name: "packer_on_error", Type: cty.String, Required: false},
@@ -237,7 +232,6 @@ func (*FlatConfig) HCL2Spec() map[string]hcldec.Spec {
"spot_tag": &hcldec.BlockListSpec{TypeName: "spot_tag", Nested: hcldec.ObjectSpec((*hcl2template.FlatKeyValue)(nil).HCL2Spec())},
"subnet_filter": &hcldec.BlockSpec{TypeName: "subnet_filter", Nested: hcldec.ObjectSpec((*common.FlatSubnetFilterOptions)(nil).HCL2Spec())},
"subnet_id": &hcldec.AttrSpec{Name: "subnet_id", Type: cty.String, Required: false},
"tenancy": &hcldec.AttrSpec{Name: "tenancy", Type: cty.String, Required: false},
"temporary_key_pair_name": &hcldec.AttrSpec{Name: "temporary_key_pair_name", Type: cty.String, Required: false},
"temporary_security_group_source_cidrs": &hcldec.AttrSpec{Name: "temporary_security_group_source_cidrs", Type: cty.List(cty.String), Required: false},
"user_data": &hcldec.AttrSpec{Name: "user_data", Type: cty.String, Required: false},
@@ -252,8 +246,6 @@ func (*FlatConfig) HCL2Spec() map[string]hcldec.Spec {
"ssh_username": &hcldec.AttrSpec{Name: "ssh_username", Type: cty.String, Required: false},
"ssh_password": &hcldec.AttrSpec{Name: "ssh_password", Type: cty.String, Required: false},
"ssh_keypair_name": &hcldec.AttrSpec{Name: "ssh_keypair_name", Type: cty.String, Required: false},
"temporary_key_pair_type": &hcldec.AttrSpec{Name: "temporary_key_pair_type", Type: cty.String, Required: false},
"temporary_key_pair_bits": &hcldec.AttrSpec{Name: "temporary_key_pair_bits", Type: cty.Number, Required: false},
"ssh_ciphers": &hcldec.AttrSpec{Name: "ssh_ciphers", Type: cty.List(cty.String), Required: false},
"ssh_clear_authorized_keys": &hcldec.AttrSpec{Name: "ssh_clear_authorized_keys", Type: cty.Bool, Required: false},
"ssh_key_exchange_algorithms": &hcldec.AttrSpec{Name: "ssh_key_exchange_algorithms", Type: cty.List(cty.String), Required: false},
@@ -7,7 +7,7 @@ import (
"github.com/aws/aws-sdk-go/service/ec2"
"github.com/hashicorp/packer/helper/multistep"
"github.com/hashicorp/packer/packer"
"github.com/hashicorp/packer/packer-plugin-sdk/template/interpolate"
"github.com/hashicorp/packer/template/interpolate"
)
type bundleCmdData struct {
+2 -2
View File
@@ -7,10 +7,10 @@ import (
"github.com/aws/aws-sdk-go/aws"
"github.com/aws/aws-sdk-go/service/ec2"
awscommon "github.com/hashicorp/packer/builder/amazon/common"
"github.com/hashicorp/packer/common/random"
confighelper "github.com/hashicorp/packer/helper/config"
"github.com/hashicorp/packer/helper/multistep"
"github.com/hashicorp/packer/packer"
confighelper "github.com/hashicorp/packer/packer-plugin-sdk/config"
"github.com/hashicorp/packer/packer-plugin-sdk/random"
)
type StepRegisterAMI struct {
@@ -6,7 +6,7 @@ import (
"github.com/hashicorp/packer/helper/multistep"
"github.com/hashicorp/packer/packer"
"github.com/hashicorp/packer/packer-plugin-sdk/template/interpolate"
"github.com/hashicorp/packer/template/interpolate"
)
type uploadCmdData struct {
-13
View File
@@ -1,13 +0,0 @@
package version
import (
"github.com/hashicorp/packer/helper/version"
packerVersion "github.com/hashicorp/packer/version"
)
var AWSPluginVersion *version.PluginVersion
func init() {
AWSPluginVersion = version.InitializePluginVersion(
packerVersion.Version, packerVersion.VersionPrerelease)
}
+17 -18
View File
@@ -22,7 +22,6 @@ import (
"github.com/Azure/go-autorest/autorest/adal"
"github.com/Azure/go-autorest/autorest/azure"
"github.com/hashicorp/packer/builder/azure/common"
"github.com/hashicorp/packer/builder/azure/version"
"github.com/hashicorp/packer/helper/useragent"
)
@@ -141,97 +140,97 @@ func NewAzureClient(subscriptionID, sigSubscriptionID, resourceGroupName, storag
azureClient.DeploymentsClient.Authorizer = autorest.NewBearerAuthorizer(servicePrincipalToken)
azureClient.DeploymentsClient.RequestInspector = withInspection(maxlen)
azureClient.DeploymentsClient.ResponseInspector = byConcatDecorators(byInspecting(maxlen), errorCapture(azureClient))
azureClient.DeploymentsClient.UserAgent = fmt.Sprintf("%s %s", useragent.String(version.AzurePluginVersion.FormattedVersion()), azureClient.DeploymentsClient.UserAgent)
azureClient.DeploymentsClient.UserAgent = fmt.Sprintf("%s %s", useragent.String(), azureClient.DeploymentsClient.UserAgent)
azureClient.DeploymentsClient.Client.PollingDuration = pollingDuration
azureClient.DeploymentOperationsClient = resources.NewDeploymentOperationsClientWithBaseURI(cloud.ResourceManagerEndpoint, subscriptionID)
azureClient.DeploymentOperationsClient.Authorizer = autorest.NewBearerAuthorizer(servicePrincipalToken)
azureClient.DeploymentOperationsClient.RequestInspector = withInspection(maxlen)
azureClient.DeploymentOperationsClient.ResponseInspector = byConcatDecorators(byInspecting(maxlen), errorCapture(azureClient))
azureClient.DeploymentOperationsClient.UserAgent = fmt.Sprintf("%s %s", useragent.String(version.AzurePluginVersion.FormattedVersion()), azureClient.DeploymentOperationsClient.UserAgent)
azureClient.DeploymentOperationsClient.UserAgent = fmt.Sprintf("%s %s", useragent.String(), azureClient.DeploymentOperationsClient.UserAgent)
azureClient.DeploymentOperationsClient.Client.PollingDuration = pollingDuration
azureClient.DisksClient = compute.NewDisksClientWithBaseURI(cloud.ResourceManagerEndpoint, subscriptionID)
azureClient.DisksClient.Authorizer = autorest.NewBearerAuthorizer(servicePrincipalToken)
azureClient.DisksClient.RequestInspector = withInspection(maxlen)
azureClient.DisksClient.ResponseInspector = byConcatDecorators(byInspecting(maxlen), errorCapture(azureClient))
azureClient.DisksClient.UserAgent = fmt.Sprintf("%s %s", useragent.String(version.AzurePluginVersion.FormattedVersion()), azureClient.DisksClient.UserAgent)
azureClient.DisksClient.UserAgent = fmt.Sprintf("%s %s", useragent.String(), azureClient.DisksClient.UserAgent)
azureClient.DisksClient.Client.PollingDuration = pollingDuration
azureClient.GroupsClient = resources.NewGroupsClientWithBaseURI(cloud.ResourceManagerEndpoint, subscriptionID)
azureClient.GroupsClient.Authorizer = autorest.NewBearerAuthorizer(servicePrincipalToken)
azureClient.GroupsClient.RequestInspector = withInspection(maxlen)
azureClient.GroupsClient.ResponseInspector = byConcatDecorators(byInspecting(maxlen), errorCapture(azureClient))
azureClient.GroupsClient.UserAgent = fmt.Sprintf("%s %s", useragent.String(version.AzurePluginVersion.FormattedVersion()), azureClient.GroupsClient.UserAgent)
azureClient.GroupsClient.UserAgent = fmt.Sprintf("%s %s", useragent.String(), azureClient.GroupsClient.UserAgent)
azureClient.GroupsClient.Client.PollingDuration = pollingDuration
azureClient.ImagesClient = compute.NewImagesClientWithBaseURI(cloud.ResourceManagerEndpoint, subscriptionID)
azureClient.ImagesClient.Authorizer = autorest.NewBearerAuthorizer(servicePrincipalToken)
azureClient.ImagesClient.RequestInspector = withInspection(maxlen)
azureClient.ImagesClient.ResponseInspector = byConcatDecorators(byInspecting(maxlen), errorCapture(azureClient))
azureClient.ImagesClient.UserAgent = fmt.Sprintf("%s %s", useragent.String(version.AzurePluginVersion.FormattedVersion()), azureClient.ImagesClient.UserAgent)
azureClient.ImagesClient.UserAgent = fmt.Sprintf("%s %s", useragent.String(), azureClient.ImagesClient.UserAgent)
azureClient.ImagesClient.Client.PollingDuration = pollingDuration
azureClient.InterfacesClient = network.NewInterfacesClientWithBaseURI(cloud.ResourceManagerEndpoint, subscriptionID)
azureClient.InterfacesClient.Authorizer = autorest.NewBearerAuthorizer(servicePrincipalToken)
azureClient.InterfacesClient.RequestInspector = withInspection(maxlen)
azureClient.InterfacesClient.ResponseInspector = byConcatDecorators(byInspecting(maxlen), errorCapture(azureClient))
azureClient.InterfacesClient.UserAgent = fmt.Sprintf("%s %s", useragent.String(version.AzurePluginVersion.FormattedVersion()), azureClient.InterfacesClient.UserAgent)
azureClient.InterfacesClient.UserAgent = fmt.Sprintf("%s %s", useragent.String(), azureClient.InterfacesClient.UserAgent)
azureClient.InterfacesClient.Client.PollingDuration = pollingDuration
azureClient.SubnetsClient = network.NewSubnetsClientWithBaseURI(cloud.ResourceManagerEndpoint, subscriptionID)
azureClient.SubnetsClient.Authorizer = autorest.NewBearerAuthorizer(servicePrincipalToken)
azureClient.SubnetsClient.RequestInspector = withInspection(maxlen)
azureClient.SubnetsClient.ResponseInspector = byConcatDecorators(byInspecting(maxlen), errorCapture(azureClient))
azureClient.SubnetsClient.UserAgent = fmt.Sprintf("%s %s", useragent.String(version.AzurePluginVersion.FormattedVersion()), azureClient.SubnetsClient.UserAgent)
azureClient.SubnetsClient.UserAgent = fmt.Sprintf("%s %s", useragent.String(), azureClient.SubnetsClient.UserAgent)
azureClient.SubnetsClient.Client.PollingDuration = pollingDuration
azureClient.VirtualNetworksClient = network.NewVirtualNetworksClientWithBaseURI(cloud.ResourceManagerEndpoint, subscriptionID)
azureClient.VirtualNetworksClient.Authorizer = autorest.NewBearerAuthorizer(servicePrincipalToken)
azureClient.VirtualNetworksClient.RequestInspector = withInspection(maxlen)
azureClient.VirtualNetworksClient.ResponseInspector = byConcatDecorators(byInspecting(maxlen), errorCapture(azureClient))
azureClient.VirtualNetworksClient.UserAgent = fmt.Sprintf("%s %s", useragent.String(version.AzurePluginVersion.FormattedVersion()), azureClient.VirtualNetworksClient.UserAgent)
azureClient.VirtualNetworksClient.UserAgent = fmt.Sprintf("%s %s", useragent.String(), azureClient.VirtualNetworksClient.UserAgent)
azureClient.VirtualNetworksClient.Client.PollingDuration = pollingDuration
azureClient.SecurityGroupsClient = network.NewSecurityGroupsClientWithBaseURI(cloud.ResourceManagerEndpoint, subscriptionID)
azureClient.SecurityGroupsClient.Authorizer = autorest.NewBearerAuthorizer(servicePrincipalToken)
azureClient.SecurityGroupsClient.RequestInspector = withInspection(maxlen)
azureClient.SecurityGroupsClient.ResponseInspector = byConcatDecorators(byInspecting(maxlen), errorCapture(azureClient))
azureClient.SecurityGroupsClient.UserAgent = fmt.Sprintf("%s %s", useragent.String(version.AzurePluginVersion.FormattedVersion()), azureClient.SecurityGroupsClient.UserAgent)
azureClient.SecurityGroupsClient.UserAgent = fmt.Sprintf("%s %s", useragent.String(), azureClient.SecurityGroupsClient.UserAgent)
azureClient.PublicIPAddressesClient = network.NewPublicIPAddressesClientWithBaseURI(cloud.ResourceManagerEndpoint, subscriptionID)
azureClient.PublicIPAddressesClient.Authorizer = autorest.NewBearerAuthorizer(servicePrincipalToken)
azureClient.PublicIPAddressesClient.RequestInspector = withInspection(maxlen)
azureClient.PublicIPAddressesClient.ResponseInspector = byConcatDecorators(byInspecting(maxlen), errorCapture(azureClient))
azureClient.PublicIPAddressesClient.UserAgent = fmt.Sprintf("%s %s", useragent.String(version.AzurePluginVersion.FormattedVersion()), azureClient.PublicIPAddressesClient.UserAgent)
azureClient.PublicIPAddressesClient.UserAgent = fmt.Sprintf("%s %s", useragent.String(), azureClient.PublicIPAddressesClient.UserAgent)
azureClient.PublicIPAddressesClient.Client.PollingDuration = pollingDuration
azureClient.VirtualMachinesClient = compute.NewVirtualMachinesClientWithBaseURI(cloud.ResourceManagerEndpoint, subscriptionID)
azureClient.VirtualMachinesClient.Authorizer = autorest.NewBearerAuthorizer(servicePrincipalToken)
azureClient.VirtualMachinesClient.RequestInspector = withInspection(maxlen)
azureClient.VirtualMachinesClient.ResponseInspector = byConcatDecorators(byInspecting(maxlen), templateCapture(azureClient), errorCapture(azureClient))
azureClient.VirtualMachinesClient.UserAgent = fmt.Sprintf("%s %s", useragent.String(version.AzurePluginVersion.FormattedVersion()), azureClient.VirtualMachinesClient.UserAgent)
azureClient.VirtualMachinesClient.UserAgent = fmt.Sprintf("%s %s", useragent.String(), azureClient.VirtualMachinesClient.UserAgent)
azureClient.VirtualMachinesClient.Client.PollingDuration = pollingDuration
azureClient.SnapshotsClient = compute.NewSnapshotsClientWithBaseURI(cloud.ResourceManagerEndpoint, subscriptionID)
azureClient.SnapshotsClient.Authorizer = autorest.NewBearerAuthorizer(servicePrincipalToken)
azureClient.SnapshotsClient.RequestInspector = withInspection(maxlen)
azureClient.SnapshotsClient.ResponseInspector = byConcatDecorators(byInspecting(maxlen), errorCapture(azureClient))
azureClient.SnapshotsClient.UserAgent = fmt.Sprintf("%s %s", useragent.String(version.AzurePluginVersion.FormattedVersion()), azureClient.SnapshotsClient.UserAgent)
azureClient.SnapshotsClient.UserAgent = fmt.Sprintf("%s %s", useragent.String(), azureClient.SnapshotsClient.UserAgent)
azureClient.SnapshotsClient.Client.PollingDuration = pollingDuration
azureClient.AccountsClient = armStorage.NewAccountsClientWithBaseURI(cloud.ResourceManagerEndpoint, subscriptionID)
azureClient.AccountsClient.Authorizer = autorest.NewBearerAuthorizer(servicePrincipalToken)
azureClient.AccountsClient.RequestInspector = withInspection(maxlen)
azureClient.AccountsClient.ResponseInspector = byConcatDecorators(byInspecting(maxlen), errorCapture(azureClient))
azureClient.AccountsClient.UserAgent = fmt.Sprintf("%s %s", useragent.String(version.AzurePluginVersion.FormattedVersion()), azureClient.AccountsClient.UserAgent)
azureClient.AccountsClient.UserAgent = fmt.Sprintf("%s %s", useragent.String(), azureClient.AccountsClient.UserAgent)
azureClient.AccountsClient.Client.PollingDuration = pollingDuration
azureClient.GalleryImageVersionsClient = newCompute.NewGalleryImageVersionsClientWithBaseURI(cloud.ResourceManagerEndpoint, subscriptionID)
azureClient.GalleryImageVersionsClient.Authorizer = autorest.NewBearerAuthorizer(servicePrincipalToken)
azureClient.GalleryImageVersionsClient.RequestInspector = withInspection(maxlen)
azureClient.GalleryImageVersionsClient.ResponseInspector = byConcatDecorators(byInspecting(maxlen), errorCapture(azureClient))
azureClient.GalleryImageVersionsClient.UserAgent = fmt.Sprintf("%s %s", useragent.String(version.AzurePluginVersion.FormattedVersion()), azureClient.GalleryImageVersionsClient.UserAgent)
azureClient.GalleryImageVersionsClient.UserAgent = fmt.Sprintf("%s %s", useragent.String(), azureClient.GalleryImageVersionsClient.UserAgent)
azureClient.GalleryImageVersionsClient.Client.PollingDuration = sharedGalleryTimeout
azureClient.GalleryImageVersionsClient.SubscriptionID = sigSubscriptionID
@@ -239,7 +238,7 @@ func NewAzureClient(subscriptionID, sigSubscriptionID, resourceGroupName, storag
azureClient.GalleryImagesClient.Authorizer = autorest.NewBearerAuthorizer(servicePrincipalToken)
azureClient.GalleryImagesClient.RequestInspector = withInspection(maxlen)
azureClient.GalleryImagesClient.ResponseInspector = byConcatDecorators(byInspecting(maxlen), errorCapture(azureClient))
azureClient.GalleryImagesClient.UserAgent = fmt.Sprintf("%s %s", useragent.String(version.AzurePluginVersion.FormattedVersion()), azureClient.GalleryImagesClient.UserAgent)
azureClient.GalleryImagesClient.UserAgent = fmt.Sprintf("%s %s", useragent.String(), azureClient.GalleryImagesClient.UserAgent)
azureClient.GalleryImagesClient.Client.PollingDuration = pollingDuration
azureClient.GalleryImagesClient.SubscriptionID = sigSubscriptionID
@@ -252,7 +251,7 @@ func NewAzureClient(subscriptionID, sigSubscriptionID, resourceGroupName, storag
azureClient.VaultClient.Authorizer = autorest.NewBearerAuthorizer(servicePrincipalTokenVault)
azureClient.VaultClient.RequestInspector = withInspection(maxlen)
azureClient.VaultClient.ResponseInspector = byConcatDecorators(byInspecting(maxlen), errorCapture(azureClient))
azureClient.VaultClient.UserAgent = fmt.Sprintf("%s %s", useragent.String(version.AzurePluginVersion.FormattedVersion()), azureClient.VaultClient.UserAgent)
azureClient.VaultClient.UserAgent = fmt.Sprintf("%s %s", useragent.String(), azureClient.VaultClient.UserAgent)
azureClient.VaultClient.Client.PollingDuration = pollingDuration
// This client is different than the above because it manages the vault
@@ -261,7 +260,7 @@ func NewAzureClient(subscriptionID, sigSubscriptionID, resourceGroupName, storag
azureClient.VaultClientDelete.Authorizer = autorest.NewBearerAuthorizer(servicePrincipalToken)
azureClient.VaultClientDelete.RequestInspector = withInspection(maxlen)
azureClient.VaultClientDelete.ResponseInspector = byConcatDecorators(byInspecting(maxlen), errorCapture(azureClient))
azureClient.VaultClientDelete.UserAgent = fmt.Sprintf("%s %s", useragent.String(version.AzurePluginVersion.FormattedVersion()), azureClient.VaultClientDelete.UserAgent)
azureClient.VaultClientDelete.UserAgent = fmt.Sprintf("%s %s", useragent.String(), azureClient.VaultClientDelete.UserAgent)
azureClient.VaultClientDelete.Client.PollingDuration = pollingDuration
// If this is a managed disk build, this should be ignored.
@@ -1,4 +1,4 @@
ERROR: -> DeploymentFailed : At least one resource deployment operation failed. Please list deployment operations for details. Please see https://aka.ms/arm-debug for usage details.
ERROR: -> BadRequest
ERROR: -> InvalidRequestFormat : Cannot parse the request.
ERROR: -> InvalidJson : Error converting value "playground" to type 'Microsoft.WindowsAzure.Networking.Nrp.Frontend.Contract.Csm.Public.IpAllocationMethod'. Path 'properties.publicIPAllocationMethod', line 1, position 130.
ERROR: -> DeploymentFailed : At least one resource deployment operation failed. Please list deployment operations for details. Please see https://aka.ms/arm-debug for usage details.
ERROR: -> BadRequest
ERROR: -> InvalidRequestFormat : Cannot parse the request.
ERROR: -> InvalidJson : Error converting value "playground" to type 'Microsoft.WindowsAzure.Networking.Nrp.Frontend.Contract.Csm.Public.IpAllocationMethod'. Path 'properties.publicIPAllocationMethod', line 1, position 130.
@@ -1 +1 @@
ERROR: -> ResourceNotFound : The Resource 'Microsoft.Compute/images/PackerUbuntuImage' under resource group 'packer-test00' was not found.
ERROR: -> ResourceNotFound : The Resource 'Microsoft.Compute/images/PackerUbuntuImage' under resource group 'packer-test00' was not found.
@@ -5,7 +5,7 @@ import (
"testing"
approvaltests "github.com/approvals/go-approval-tests"
"github.com/hashicorp/packer/packer-plugin-sdk/json"
"github.com/hashicorp/packer/common/json"
)
const AzureErrorSimple = `{"error":{"code":"ResourceNotFound","message":"The Resource 'Microsoft.Compute/images/PackerUbuntuImage' under resource group 'packer-test00' was not found."}}`
+7 -5
View File
@@ -18,10 +18,10 @@ import (
packerAzureCommon "github.com/hashicorp/packer/builder/azure/common"
"github.com/hashicorp/packer/builder/azure/common/constants"
"github.com/hashicorp/packer/builder/azure/common/lin"
packerCommon "github.com/hashicorp/packer/common"
"github.com/hashicorp/packer/helper/communicator"
"github.com/hashicorp/packer/helper/multistep"
"github.com/hashicorp/packer/packer"
"github.com/hashicorp/packer/packer-plugin-sdk/commonsteps"
)
type Builder struct {
@@ -211,8 +211,8 @@ func (b *Builder) Run(ctx context.Context, ui packer.Ui, hook packer.Hook) (pack
Host: lin.SSHHost,
SSHConfig: b.config.Comm.SSHConfigFunc(),
},
&commonsteps.StepProvision{},
&commonsteps.StepCleanupTempKeys{
&packerCommon.StepProvision{},
&packerCommon.StepCleanupTempKeys{
Comm: &b.config.Comm,
},
NewStepGetOSDisk(azureClient, ui),
@@ -222,6 +222,7 @@ func (b *Builder) Run(ctx context.Context, ui packer.Ui, hook packer.Hook) (pack
NewStepSnapshotDataDisks(azureClient, ui, &b.config),
NewStepCaptureImage(azureClient, ui),
NewStepPublishToSharedImageGallery(azureClient, ui, &b.config),
NewStepDeleteAdditionalDisks(azureClient, ui),
}
} else if b.config.OSType == constants.Target_Windows {
steps = []multistep.Step{
@@ -254,7 +255,7 @@ func (b *Builder) Run(ctx context.Context, ui packer.Ui, hook packer.Hook) (pack
}, nil
},
},
&commonsteps.StepProvision{},
&packerCommon.StepProvision{},
NewStepGetOSDisk(azureClient, ui),
NewStepGetAdditionalDisks(azureClient, ui),
NewStepPowerOffCompute(azureClient, ui),
@@ -262,6 +263,7 @@ func (b *Builder) Run(ctx context.Context, ui packer.Ui, hook packer.Hook) (pack
NewStepSnapshotDataDisks(azureClient, ui, &b.config),
NewStepCaptureImage(azureClient, ui),
NewStepPublishToSharedImageGallery(azureClient, ui, &b.config),
NewStepDeleteAdditionalDisks(azureClient, ui),
)
} else {
return nil, fmt.Errorf("Builder does not support the os_type '%s'", b.config.OSType)
@@ -279,7 +281,7 @@ func (b *Builder) Run(ctx context.Context, ui packer.Ui, hook packer.Hook) (pack
}
}
b.runner = commonsteps.NewRunner(steps, b.config.PackerConfig, ui)
b.runner = packerCommon.NewRunner(steps, b.config.PackerConfig, ui)
b.runner.Run(ctx, b.stateBag)
// Report any errors.
+4 -82
View File
@@ -6,6 +6,7 @@ package arm
// * ARM_CLIENT_ID
// * ARM_CLIENT_SECRET
// * ARM_SUBSCRIPTION_ID
// * ARM_OBJECT_ID
// * ARM_STORAGE_ACCOUNT
//
// The subscription in question should have a resource group
@@ -46,14 +47,6 @@ func TestBuilderAcc_ManagedDisk_Windows_Build_Resource_Group(t *testing.T) {
})
}
func TestBuilderAcc_ManagedDisk_Windows_Build_Resource_Group_Additional_Disk(t *testing.T) {
builderT.Test(t, builderT.TestCase{
PreCheck: func() { testAccPreCheck(t) },
Builder: &Builder{},
Template: testBuilderAccManagedDiskWindowsBuildResourceGroupAdditionalDisk,
})
}
func TestBuilderAcc_ManagedDisk_Windows_DeviceLogin(t *testing.T) {
if os.Getenv(DeviceLoginAcceptanceTest) == "" {
t.Skip(fmt.Sprintf(
@@ -90,19 +83,6 @@ func TestBuilderAcc_ManagedDisk_Linux_DeviceLogin(t *testing.T) {
})
}
func TestBuilderAcc_ManagedDisk_Linux_AzureCLI(t *testing.T) {
if os.Getenv("AZURE_CLI_AUTH") == "" {
t.Skip("Azure CLI Acceptance tests skipped unless env 'AZURE_CLI_AUTH' is set, and an active `az login` session has been established")
return
}
builderT.Test(t, builderT.TestCase{
PreCheck: func() { testAccPreCheck(t) },
Builder: &Builder{},
Template: testBuilderAccManagedDiskLinuxAzureCLI,
})
}
func TestBuilderAcc_Blob_Windows(t *testing.T) {
builderT.Test(t, builderT.TestCase{
PreCheck: func() { testAccPreCheck(t) },
@@ -171,7 +151,7 @@ const testBuilderAccManagedDiskWindowsBuildResourceGroup = `
"build_resource_group_name" : "packer-acceptance-test",
"managed_image_resource_group_name": "packer-acceptance-test",
"managed_image_name": "testBuilderAccManagedDiskWindowsBuildResourceGroup-{{timestamp}}",
"managed_image_name": "testBuilderAccManagedDiskWindows-{{timestamp}}",
"os_type": "Windows",
"image_publisher": "MicrosoftWindowsServer",
@@ -190,42 +170,6 @@ const testBuilderAccManagedDiskWindowsBuildResourceGroup = `
}
`
const testBuilderAccManagedDiskWindowsBuildResourceGroupAdditionalDisk = `
{
"variables": {
"client_id": "{{env ` + "`ARM_CLIENT_ID`" + `}}",
"client_secret": "{{env ` + "`ARM_CLIENT_SECRET`" + `}}",
"subscription_id": "{{env ` + "`ARM_SUBSCRIPTION_ID`" + `}}"
},
"builders": [{
"type": "test",
"client_id": "{{user ` + "`client_id`" + `}}",
"client_secret": "{{user ` + "`client_secret`" + `}}",
"subscription_id": "{{user ` + "`subscription_id`" + `}}",
"build_resource_group_name" : "packer-acceptance-test",
"managed_image_resource_group_name": "packer-acceptance-test",
"managed_image_name": "testBuilderAccManagedDiskWindowsBuildResourceGroupAdditionDisk-{{timestamp}}",
"os_type": "Windows",
"image_publisher": "MicrosoftWindowsServer",
"image_offer": "WindowsServer",
"image_sku": "2012-R2-Datacenter",
"communicator": "winrm",
"winrm_use_ssl": "true",
"winrm_insecure": "true",
"winrm_timeout": "3m",
"winrm_username": "packer",
"async_resourcegroup_delete": "true",
"vm_size": "Standard_DS2_v2",
"disk_additional_size": [10,15]
}]
}
`
const testBuilderAccManagedDiskWindowsDeviceLogin = `
{
"variables": {
@@ -318,6 +262,7 @@ const testBuilderAccBlobWindows = `
"client_id": "{{env ` + "`ARM_CLIENT_ID`" + `}}",
"client_secret": "{{env ` + "`ARM_CLIENT_SECRET`" + `}}",
"subscription_id": "{{env ` + "`ARM_SUBSCRIPTION_ID`" + `}}",
"object_id": "{{env ` + "`ARM_OBJECT_ID`" + `}}",
"storage_account": "{{env ` + "`ARM_STORAGE_ACCOUNT`" + `}}"
},
"builders": [{
@@ -326,6 +271,7 @@ const testBuilderAccBlobWindows = `
"client_id": "{{user ` + "`client_id`" + `}}",
"client_secret": "{{user ` + "`client_secret`" + `}}",
"subscription_id": "{{user ` + "`subscription_id`" + `}}",
"object_id": "{{user ` + "`object_id`" + `}}",
"storage_account": "{{user ` + "`storage_account`" + `}}",
"resource_group_name": "packer-acceptance-test",
@@ -379,27 +325,3 @@ const testBuilderAccBlobLinux = `
}]
}
`
const testBuilderAccManagedDiskLinuxAzureCLI = `
{
"builders": [{
"type": "test",
"use_azure_cli_auth": true,
"managed_image_resource_group_name": "packer-acceptance-test",
"managed_image_name": "testBuilderAccManagedDiskLinuxAzureCLI-{{timestamp}}",
"os_type": "Linux",
"image_publisher": "Canonical",
"image_offer": "UbuntuServer",
"image_sku": "16.04-LTS",
"location": "South Central US",
"vm_size": "Standard_DS2_v2",
"azure_tags": {
"env": "testing",
"builder": "packer"
}
}]
}
`
+4 -5
View File
@@ -18,7 +18,7 @@ import (
"strings"
"time"
"github.com/hashicorp/packer/packer-plugin-sdk/random"
"github.com/hashicorp/packer/common/random"
"github.com/Azure/azure-sdk-for-go/services/compute/mgmt/2018-04-01/compute"
"github.com/Azure/go-autorest/autorest/to"
@@ -28,12 +28,12 @@ import (
"github.com/hashicorp/packer/builder/azure/common/client"
"github.com/hashicorp/packer/builder/azure/common/constants"
"github.com/hashicorp/packer/builder/azure/pkcs12"
"github.com/hashicorp/packer/common"
"github.com/hashicorp/packer/hcl2template"
"github.com/hashicorp/packer/helper/communicator"
"github.com/hashicorp/packer/helper/config"
"github.com/hashicorp/packer/packer"
"github.com/hashicorp/packer/packer-plugin-sdk/common"
"github.com/hashicorp/packer/packer-plugin-sdk/config"
"github.com/hashicorp/packer/packer-plugin-sdk/template/interpolate"
"github.com/hashicorp/packer/template/interpolate"
"golang.org/x/crypto/ssh"
)
@@ -580,7 +580,6 @@ func (c *Config) createCertificate() (string, error) {
func (c *Config) Prepare(raws ...interface{}) ([]string, error) {
c.ctx.Funcs = azcommon.TemplateFuncs
err := config.Decode(c, &config.DecodeOpts{
PluginType: BuilderId,
Interpolate: true,
InterpolateContext: &c.ctx,
}, raws...)
-8
View File
@@ -12,7 +12,6 @@ import (
type FlatConfig struct {
PackerBuildName *string `mapstructure:"packer_build_name" cty:"packer_build_name" hcl:"packer_build_name"`
PackerBuilderType *string `mapstructure:"packer_builder_type" cty:"packer_builder_type" hcl:"packer_builder_type"`
PackerCoreVersion *string `mapstructure:"packer_core_version" cty:"packer_core_version" hcl:"packer_core_version"`
PackerDebug *bool `mapstructure:"packer_debug" cty:"packer_debug" hcl:"packer_debug"`
PackerForce *bool `mapstructure:"packer_force" cty:"packer_force" hcl:"packer_force"`
PackerOnError *string `mapstructure:"packer_on_error" cty:"packer_on_error" hcl:"packer_on_error"`
@@ -26,7 +25,6 @@ type FlatConfig struct {
ObjectID *string `mapstructure:"object_id" cty:"object_id" hcl:"object_id"`
TenantID *string `mapstructure:"tenant_id" required:"false" cty:"tenant_id" hcl:"tenant_id"`
SubscriptionID *string `mapstructure:"subscription_id" cty:"subscription_id" hcl:"subscription_id"`
UseAzureCLIAuth *bool `mapstructure:"use_azure_cli_auth" required:"false" cty:"use_azure_cli_auth" hcl:"use_azure_cli_auth"`
UserAssignedManagedIdentities []string `mapstructure:"user_assigned_managed_identities" required:"false" cty:"user_assigned_managed_identities" hcl:"user_assigned_managed_identities"`
CaptureNamePrefix *string `mapstructure:"capture_name_prefix" cty:"capture_name_prefix" hcl:"capture_name_prefix"`
CaptureContainerName *string `mapstructure:"capture_container_name" cty:"capture_container_name" hcl:"capture_container_name"`
@@ -82,8 +80,6 @@ type FlatConfig struct {
SSHPassword *string `mapstructure:"ssh_password" cty:"ssh_password" hcl:"ssh_password"`
SSHKeyPairName *string `mapstructure:"ssh_keypair_name" undocumented:"true" cty:"ssh_keypair_name" hcl:"ssh_keypair_name"`
SSHTemporaryKeyPairName *string `mapstructure:"temporary_key_pair_name" undocumented:"true" cty:"temporary_key_pair_name" hcl:"temporary_key_pair_name"`
SSHTemporaryKeyPairType *string `mapstructure:"temporary_key_pair_type" cty:"temporary_key_pair_type" hcl:"temporary_key_pair_type"`
SSHTemporaryKeyPairBits *int `mapstructure:"temporary_key_pair_bits" cty:"temporary_key_pair_bits" hcl:"temporary_key_pair_bits"`
SSHCiphers []string `mapstructure:"ssh_ciphers" cty:"ssh_ciphers" hcl:"ssh_ciphers"`
SSHClearAuthorizedKeys *bool `mapstructure:"ssh_clear_authorized_keys" cty:"ssh_clear_authorized_keys" hcl:"ssh_clear_authorized_keys"`
SSHKEXAlgos []string `mapstructure:"ssh_key_exchange_algorithms" cty:"ssh_key_exchange_algorithms" hcl:"ssh_key_exchange_algorithms"`
@@ -140,7 +136,6 @@ func (*FlatConfig) HCL2Spec() map[string]hcldec.Spec {
s := map[string]hcldec.Spec{
"packer_build_name": &hcldec.AttrSpec{Name: "packer_build_name", Type: cty.String, Required: false},
"packer_builder_type": &hcldec.AttrSpec{Name: "packer_builder_type", Type: cty.String, Required: false},
"packer_core_version": &hcldec.AttrSpec{Name: "packer_core_version", Type: cty.String, Required: false},
"packer_debug": &hcldec.AttrSpec{Name: "packer_debug", Type: cty.Bool, Required: false},
"packer_force": &hcldec.AttrSpec{Name: "packer_force", Type: cty.Bool, Required: false},
"packer_on_error": &hcldec.AttrSpec{Name: "packer_on_error", Type: cty.String, Required: false},
@@ -154,7 +149,6 @@ func (*FlatConfig) HCL2Spec() map[string]hcldec.Spec {
"object_id": &hcldec.AttrSpec{Name: "object_id", Type: cty.String, Required: false},
"tenant_id": &hcldec.AttrSpec{Name: "tenant_id", Type: cty.String, Required: false},
"subscription_id": &hcldec.AttrSpec{Name: "subscription_id", Type: cty.String, Required: false},
"use_azure_cli_auth": &hcldec.AttrSpec{Name: "use_azure_cli_auth", Type: cty.Bool, Required: false},
"user_assigned_managed_identities": &hcldec.AttrSpec{Name: "user_assigned_managed_identities", Type: cty.List(cty.String), Required: false},
"capture_name_prefix": &hcldec.AttrSpec{Name: "capture_name_prefix", Type: cty.String, Required: false},
"capture_container_name": &hcldec.AttrSpec{Name: "capture_container_name", Type: cty.String, Required: false},
@@ -210,8 +204,6 @@ func (*FlatConfig) HCL2Spec() map[string]hcldec.Spec {
"ssh_password": &hcldec.AttrSpec{Name: "ssh_password", Type: cty.String, Required: false},
"ssh_keypair_name": &hcldec.AttrSpec{Name: "ssh_keypair_name", Type: cty.String, Required: false},
"temporary_key_pair_name": &hcldec.AttrSpec{Name: "temporary_key_pair_name", Type: cty.String, Required: false},
"temporary_key_pair_type": &hcldec.AttrSpec{Name: "temporary_key_pair_type", Type: cty.String, Required: false},
"temporary_key_pair_bits": &hcldec.AttrSpec{Name: "temporary_key_pair_bits", Type: cty.Number, Required: false},
"ssh_ciphers": &hcldec.AttrSpec{Name: "ssh_ciphers", Type: cty.List(cty.String), Required: false},
"ssh_clear_authorized_keys": &hcldec.AttrSpec{Name: "ssh_clear_authorized_keys", Type: cty.Bool, Required: false},
"ssh_key_exchange_algorithms": &hcldec.AttrSpec{Name: "ssh_key_exchange_algorithms", Type: cty.List(cty.String), Required: false},
@@ -61,11 +61,7 @@ func (s *StepDeleteAdditionalDisk) deleteManagedDisk(ctx context.Context, resour
func (s *StepDeleteAdditionalDisk) Run(ctx context.Context, state multistep.StateBag) multistep.StepAction {
s.say("Deleting the temporary Additional disk ...")
var dataDisks []string
if disks := state.Get(constants.ArmAdditionalDiskVhds); disks != nil {
dataDisks = disks.([]string)
}
var dataDisks = state.Get(constants.ArmAdditionalDiskVhds).([]string)
var isManagedDisk = state.Get(constants.ArmIsManagedImage).(bool)
var isExistingResourceGroup = state.Get(constants.ArmIsExistingResourceGroup).(bool)
var resourceGroupName = state.Get(constants.ArmResourceGroupName).(string)
+81 -82
View File
@@ -6,18 +6,16 @@ import (
"fmt"
"net/url"
"strings"
"time"
"github.com/hashicorp/packer/builder/azure/common/constants"
"github.com/hashicorp/packer/helper/multistep"
"github.com/hashicorp/packer/packer"
"github.com/hashicorp/packer/packer-plugin-sdk/retry"
)
type StepDeployTemplate struct {
client *AzureClient
deploy func(ctx context.Context, resourceGroupName string, deploymentName string) error
delete func(ctx context.Context, deploymentName, resourceGroupName string) error
delete func(ctx context.Context, client *AzureClient, resourceType string, resourceName string, resourceGroupName string) error
disk func(ctx context.Context, resourceGroupName string, computeName string) (string, string, error)
deleteDisk func(ctx context.Context, imageType string, imageName string, resourceGroupName string) error
say func(message string)
@@ -38,7 +36,7 @@ func NewStepDeployTemplate(client *AzureClient, ui packer.Ui, config *Config, de
}
step.deploy = step.deployTemplate
step.delete = step.deleteDeploymentResources
step.delete = deleteResource
step.disk = step.getImageDetails
step.deleteDisk = step.deleteImage
return step
@@ -64,9 +62,8 @@ func (s *StepDeployTemplate) Cleanup(state multistep.StateBag) {
}
}()
// Only clean up if this is an existing resource group that has been verified to exist.
// ArmIsResourceGroupCreated is set in step_create_resource_group to true, when Packer has verified that the resource group exists.
// ArmIsExistingResourceGroup is set to true when build_resource_group is set in the Packer configuration.
//Only clean up if this was an existing resource group and the resource group
//is marked as created
existingResourceGroup := state.Get(constants.ArmIsExistingResourceGroup).(bool)
resourceGroupCreated := state.Get(constants.ArmIsResourceGroupCreated).(bool)
if !existingResourceGroup || !resourceGroupCreated {
@@ -78,12 +75,74 @@ func (s *StepDeployTemplate) Cleanup(state multistep.StateBag) {
deploymentName := s.name
resourceGroupName := state.Get(constants.ArmResourceGroupName).(string)
err := s.deleteDeploymentResources(context.TODO(), deploymentName, resourceGroupName)
if err != nil {
s.reportIfError(err, resourceGroupName)
// Get image disk details before deleting the image; otherwise we won't be able to
// delete the disk as the image request will return a 404
computeName := state.Get(constants.ArmComputeName).(string)
imageType, imageName, err := s.disk(context.TODO(), resourceGroupName, computeName)
if err != nil && !strings.Contains(err.Error(), "ResourceNotFound") {
ui.Error(fmt.Sprintf("Could not retrieve OS Image details: %s", err))
}
NewStepDeleteAdditionalDisks(s.client, ui).Run(context.TODO(), state)
ui.Say(" -> Deployment Resources within: " + deploymentName)
if deploymentName != "" {
maxResources := int32(50)
deploymentOperations, err := s.client.DeploymentOperationsClient.ListComplete(context.TODO(), resourceGroupName, deploymentName, &maxResources)
if err != nil {
ui.Error(fmt.Sprintf("Error deleting resources. Please delete them manually.\n\n"+
"Name: %s\n"+
"Error: %s", resourceGroupName, err))
}
for deploymentOperations.NotDone() {
deploymentOperation := deploymentOperations.Value()
// Sometimes an empty operation is added to the list by Azure
if deploymentOperation.Properties.TargetResource == nil {
if err := deploymentOperations.Next(); err != nil {
ui.Error(fmt.Sprintf("Error moving to to next deployment operation ...\n\n"+
"Name: %s\n"+
"Error: %s", resourceGroupName, err))
break
}
continue
}
ui.Say(fmt.Sprintf(" -> %s : '%s'",
*deploymentOperation.Properties.TargetResource.ResourceType,
*deploymentOperation.Properties.TargetResource.ResourceName))
err = s.delete(context.TODO(), s.client,
*deploymentOperation.Properties.TargetResource.ResourceType,
*deploymentOperation.Properties.TargetResource.ResourceName,
resourceGroupName)
if err != nil {
ui.Error(fmt.Sprintf("Error deleting resource. Please delete manually.\n\n"+
"Name: %s\n"+
"Error: %s", *deploymentOperation.Properties.TargetResource.ResourceName, err))
}
if err = deploymentOperations.Next(); err != nil {
ui.Error(fmt.Sprintf("Error deleting resources. Please delete them manually.\n\n"+
"Name: %s\n"+
"Error: %s", resourceGroupName, err))
break
}
}
// The disk is not defined as an operation in the template so it has to be deleted separately
if imageType == "" && imageName == "" {
return
}
ui.Say(fmt.Sprintf(" -> %s : '%s'", imageType, imageName))
err = s.deleteDisk(context.TODO(), imageType, imageName, resourceGroupName)
if err != nil {
ui.Error(fmt.Sprintf("Error deleting resource. Please delete manually.\n\n"+
"Name: %s\n"+
"Error: %s", imageName, err))
}
}
}
func (s *StepDeployTemplate) deployTemplate(ctx context.Context, resourceGroupName string, deploymentName string) error {
@@ -93,31 +152,27 @@ func (s *StepDeployTemplate) deployTemplate(ctx context.Context, resourceGroupNa
}
f, err := s.client.DeploymentsClient.CreateOrUpdate(ctx, resourceGroupName, deploymentName, *deployment)
if err == nil {
err = f.WaitForCompletionRef(ctx, s.client.DeploymentsClient.Client)
}
if err != nil {
s.say(s.client.LastError.Error())
return err
}
err = f.WaitForCompletionRef(ctx, s.client.DeploymentsClient.Client)
if err == nil {
s.say(s.client.LastError.Error())
}
return err
}
func (s *StepDeployTemplate) deleteTemplate(ctx context.Context, state multistep.StateBag) error {
deploymentName := s.name
resourceGroupName := state.Get(constants.ArmResourceGroupName).(string)
var resourceGroupName = state.Get(constants.ArmResourceGroupName).(string)
var deploymentName = s.name
ui := state.Get("ui").(packer.Ui)
ui.Say(fmt.Sprintf("Removing the created Deployment object: '%s'", deploymentName))
f, err := s.client.DeploymentsClient.Delete(ctx, resourceGroupName, deploymentName)
if err != nil {
return err
if err == nil {
err = f.WaitForCompletionRef(ctx, s.client.DeploymentsClient.Client)
}
return f.WaitForCompletionRef(ctx, s.client.DeploymentsClient.Client)
return err
}
func (s *StepDeployTemplate) getImageDetails(ctx context.Context, resourceGroupName string, computeName string) (string, string, error) {
@@ -131,12 +186,11 @@ func (s *StepDeployTemplate) getImageDetails(ctx context.Context, resourceGroupN
if vm.StorageProfile.OsDisk.Vhd != nil {
imageType = "image"
imageName = *vm.StorageProfile.OsDisk.Vhd.URI
return imageType, imageName, nil
} else {
imageType = "Microsoft.Compute/disks"
imageName = *vm.StorageProfile.OsDisk.ManagedDisk.ID
}
imageType = "Microsoft.Compute/disks"
imageName = *vm.StorageProfile.OsDisk.ManagedDisk.ID
return imageType, imageName, nil
}
@@ -213,58 +267,3 @@ func (s *StepDeployTemplate) deleteImage(ctx context.Context, imageType string,
return blob.Delete(nil)
}
func (s *StepDeployTemplate) deleteDeploymentResources(ctx context.Context, deploymentName, resourceGroupName string) error {
var maxResources int32 = 50
deploymentOperations, err := s.client.DeploymentOperationsClient.ListComplete(ctx, resourceGroupName, deploymentName, &maxResources)
if err != nil {
s.reportIfError(err, resourceGroupName)
return err
}
for deploymentOperations.NotDone() {
deploymentOperation := deploymentOperations.Value()
// Sometimes an empty operation is added to the list by Azure
if deploymentOperation.Properties.TargetResource == nil {
_ = deploymentOperations.Next()
continue
}
resourceName := *deploymentOperation.Properties.TargetResource.ResourceName
resourceType := *deploymentOperation.Properties.TargetResource.ResourceType
s.say(fmt.Sprintf(" -> %s : '%s'", resourceType, resourceName))
err = retry.Config{
Tries: 10,
RetryDelay: (&retry.Backoff{InitialBackoff: 10 * time.Second, MaxBackoff: 600 * time.Second, Multiplier: 2}).Linear,
}.Run(ctx, func(ctx context.Context) error {
err := deleteResource(ctx, s.client,
resourceType,
resourceName,
resourceGroupName)
if err != nil {
s.reportIfError(err, resourceName)
}
return nil
})
if err != nil {
s.reportIfError(err, resourceName)
}
if err = deploymentOperations.Next(); err != nil {
return err
}
}
return nil
}
func (s *StepDeployTemplate) reportIfError(err error, resourceName string) {
if err != nil {
s.say(fmt.Sprintf("Error deleting resource. Please delete manually.\n\n"+
"Name: %s\n"+
"Error: %s", resourceName, err.Error()))
s.error(err)
}
}
@@ -38,7 +38,6 @@
"tenantId": "[parameters('tenantId')]"
}
],
"enableSoftDelete": "true",
"enabledForDeployment": "true",
"enabledForTemplateDeployment": "true",
"sku": {
+1 -1
View File
@@ -4,7 +4,7 @@ import (
"fmt"
"strings"
"github.com/hashicorp/packer/packer-plugin-sdk/random"
"github.com/hashicorp/packer/common/random"
)
type TempName struct {
+1 -1
View File
@@ -4,7 +4,7 @@ import (
"strings"
"testing"
"github.com/hashicorp/packer/packer-plugin-sdk/random"
"github.com/hashicorp/packer/common/random"
)
func TestTempNameShouldCreatePrefixedRandomNames(t *testing.T) {
+5 -7
View File
@@ -18,13 +18,12 @@ import (
"github.com/hashicorp/hcl/v2/hcldec"
azcommon "github.com/hashicorp/packer/builder/azure/common"
"github.com/hashicorp/packer/builder/azure/common/client"
"github.com/hashicorp/packer/common"
"github.com/hashicorp/packer/common/chroot"
"github.com/hashicorp/packer/helper/config"
"github.com/hashicorp/packer/helper/multistep"
"github.com/hashicorp/packer/packer"
"github.com/hashicorp/packer/packer-plugin-sdk/chroot"
"github.com/hashicorp/packer/packer-plugin-sdk/common"
"github.com/hashicorp/packer/packer-plugin-sdk/commonsteps"
"github.com/hashicorp/packer/packer-plugin-sdk/config"
"github.com/hashicorp/packer/packer-plugin-sdk/template/interpolate"
"github.com/hashicorp/packer/template/interpolate"
"github.com/Azure/azure-sdk-for-go/services/compute/mgmt/2019-12-01/compute"
"github.com/Azure/go-autorest/autorest/azure"
@@ -154,7 +153,6 @@ func (b *Builder) Prepare(raws ...interface{}) ([]string, []string, error) {
b.config.ctx.Funcs["vm"] = CreateVMMetadataTemplateFunc()
md := &mapstructure.Metadata{}
err := config.Decode(&b.config, &config.DecodeOpts{
PluginType: BuilderID,
Interpolate: true,
InterpolateContext: &b.config.ctx,
InterpolateFilter: &interpolate.RenderFilter{
@@ -440,7 +438,7 @@ func (b *Builder) Run(ctx context.Context, ui packer.Ui, hook packer.Hook) (pack
steps := buildsteps(b.config, info)
// Run!
b.runner = commonsteps.NewRunner(steps, b.config.PackerConfig, ui)
b.runner = common.NewRunner(steps, b.config.PackerConfig, ui)
b.runner.Run(ctx, state)
// If there was an error, return that
-4
View File
@@ -11,7 +11,6 @@ import (
type FlatConfig struct {
PackerBuildName *string `mapstructure:"packer_build_name" cty:"packer_build_name" hcl:"packer_build_name"`
PackerBuilderType *string `mapstructure:"packer_builder_type" cty:"packer_builder_type" hcl:"packer_builder_type"`
PackerCoreVersion *string `mapstructure:"packer_core_version" cty:"packer_core_version" hcl:"packer_core_version"`
PackerDebug *bool `mapstructure:"packer_debug" cty:"packer_debug" hcl:"packer_debug"`
PackerForce *bool `mapstructure:"packer_force" cty:"packer_force" hcl:"packer_force"`
PackerOnError *string `mapstructure:"packer_on_error" cty:"packer_on_error" hcl:"packer_on_error"`
@@ -25,7 +24,6 @@ type FlatConfig struct {
ObjectID *string `mapstructure:"object_id" cty:"object_id" hcl:"object_id"`
TenantID *string `mapstructure:"tenant_id" required:"false" cty:"tenant_id" hcl:"tenant_id"`
SubscriptionID *string `mapstructure:"subscription_id" cty:"subscription_id" hcl:"subscription_id"`
UseAzureCLIAuth *bool `mapstructure:"use_azure_cli_auth" required:"false" cty:"use_azure_cli_auth" hcl:"use_azure_cli_auth"`
FromScratch *bool `mapstructure:"from_scratch" cty:"from_scratch" hcl:"from_scratch"`
Source *string `mapstructure:"source" required:"true" cty:"source" hcl:"source"`
CommandWrapper *string `mapstructure:"command_wrapper" cty:"command_wrapper" hcl:"command_wrapper"`
@@ -65,7 +63,6 @@ func (*FlatConfig) HCL2Spec() map[string]hcldec.Spec {
s := map[string]hcldec.Spec{
"packer_build_name": &hcldec.AttrSpec{Name: "packer_build_name", Type: cty.String, Required: false},
"packer_builder_type": &hcldec.AttrSpec{Name: "packer_builder_type", Type: cty.String, Required: false},
"packer_core_version": &hcldec.AttrSpec{Name: "packer_core_version", Type: cty.String, Required: false},
"packer_debug": &hcldec.AttrSpec{Name: "packer_debug", Type: cty.Bool, Required: false},
"packer_force": &hcldec.AttrSpec{Name: "packer_force", Type: cty.Bool, Required: false},
"packer_on_error": &hcldec.AttrSpec{Name: "packer_on_error", Type: cty.String, Required: false},
@@ -79,7 +76,6 @@ func (*FlatConfig) HCL2Spec() map[string]hcldec.Spec {
"object_id": &hcldec.AttrSpec{Name: "object_id", Type: cty.String, Required: false},
"tenant_id": &hcldec.AttrSpec{Name: "tenant_id", Type: cty.String, Required: false},
"subscription_id": &hcldec.AttrSpec{Name: "subscription_id", Type: cty.String, Required: false},
"use_azure_cli_auth": &hcldec.AttrSpec{Name: "use_azure_cli_auth", Type: cty.Bool, Required: false},
"from_scratch": &hcldec.AttrSpec{Name: "from_scratch", Type: cty.Bool, Required: false},
"source": &hcldec.AttrSpec{Name: "source", Type: cty.String, Required: false},
"command_wrapper": &hcldec.AttrSpec{Name: "command_wrapper", Type: cty.String, Required: false},

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