summaryrefslogtreecommitdiff
path: root/vendor/github.com/mitchellh/packer/builder
diff options
context:
space:
mode:
Diffstat (limited to 'vendor/github.com/mitchellh/packer/builder')
-rw-r--r--vendor/github.com/mitchellh/packer/builder/alicloud/ecs/access_config.go2
-rw-r--r--vendor/github.com/mitchellh/packer/builder/alicloud/ecs/step_config_vswitch.go2
-rw-r--r--vendor/github.com/mitchellh/packer/builder/amazon/chroot/builder.go14
-rw-r--r--vendor/github.com/mitchellh/packer/builder/amazon/chroot/lockfile_unix.go7
-rw-r--r--vendor/github.com/mitchellh/packer/builder/amazon/chroot/step_register_ami.go9
-rw-r--r--vendor/github.com/mitchellh/packer/builder/amazon/common/ami_config.go3
-rw-r--r--vendor/github.com/mitchellh/packer/builder/amazon/common/artifact.go2
-rw-r--r--vendor/github.com/mitchellh/packer/builder/amazon/common/artifact_test.go4
-rw-r--r--vendor/github.com/mitchellh/packer/builder/amazon/common/step_deregister_ami.go81
-rw-r--r--vendor/github.com/mitchellh/packer/builder/amazon/common/step_encrypted_ami.go12
-rw-r--r--vendor/github.com/mitchellh/packer/builder/amazon/common/step_modify_ebs_instance.go17
-rw-r--r--vendor/github.com/mitchellh/packer/builder/amazon/common/step_run_source_instance.go84
-rw-r--r--vendor/github.com/mitchellh/packer/builder/amazon/common/step_security_group.go42
-rw-r--r--vendor/github.com/mitchellh/packer/builder/amazon/common/step_source_ami_info.go9
-rw-r--r--vendor/github.com/mitchellh/packer/builder/amazon/ebs/builder.go13
-rw-r--r--vendor/github.com/mitchellh/packer/builder/amazon/ebssurrogate/builder.go18
-rw-r--r--vendor/github.com/mitchellh/packer/builder/amazon/ebssurrogate/step_register_ami.go14
-rw-r--r--vendor/github.com/mitchellh/packer/builder/amazon/ebsvolume/builder.go15
-rw-r--r--vendor/github.com/mitchellh/packer/builder/amazon/instance/builder.go14
-rw-r--r--vendor/github.com/mitchellh/packer/builder/amazon/instance/step_register_ami.go12
-rw-r--r--vendor/github.com/mitchellh/packer/builder/azure/arm/artifact.go3
-rw-r--r--vendor/github.com/mitchellh/packer/builder/azure/arm/artifact_test.go3
-rw-r--r--vendor/github.com/mitchellh/packer/builder/azure/arm/authenticate.go3
-rw-r--r--vendor/github.com/mitchellh/packer/builder/azure/arm/azure_client.go3
-rw-r--r--vendor/github.com/mitchellh/packer/builder/azure/arm/builder.go11
-rw-r--r--vendor/github.com/mitchellh/packer/builder/azure/arm/builder_test.go3
-rw-r--r--vendor/github.com/mitchellh/packer/builder/azure/arm/capture_template.go3
-rw-r--r--vendor/github.com/mitchellh/packer/builder/azure/arm/capture_template_test.go3
-rw-r--r--vendor/github.com/mitchellh/packer/builder/azure/arm/config.go64
-rw-r--r--vendor/github.com/mitchellh/packer/builder/azure/arm/config_test.go89
-rw-r--r--vendor/github.com/mitchellh/packer/builder/azure/arm/openssh_key_pair.go3
-rw-r--r--vendor/github.com/mitchellh/packer/builder/azure/arm/openssh_key_pair_test.go3
-rw-r--r--vendor/github.com/mitchellh/packer/builder/azure/arm/step.go3
-rw-r--r--vendor/github.com/mitchellh/packer/builder/azure/arm/step_capture_image.go3
-rw-r--r--vendor/github.com/mitchellh/packer/builder/azure/arm/step_capture_image_test.go3
-rw-r--r--vendor/github.com/mitchellh/packer/builder/azure/arm/step_create_resource_group.go3
-rw-r--r--vendor/github.com/mitchellh/packer/builder/azure/arm/step_create_resource_group_test.go3
-rw-r--r--vendor/github.com/mitchellh/packer/builder/azure/arm/step_delete_os_disk.go3
-rw-r--r--vendor/github.com/mitchellh/packer/builder/azure/arm/step_delete_os_disk_test.go3
-rw-r--r--vendor/github.com/mitchellh/packer/builder/azure/arm/step_delete_resource_group.go3
-rw-r--r--vendor/github.com/mitchellh/packer/builder/azure/arm/step_delete_resource_group_test.go3
-rw-r--r--vendor/github.com/mitchellh/packer/builder/azure/arm/step_deploy_template.go3
-rw-r--r--vendor/github.com/mitchellh/packer/builder/azure/arm/step_deploy_template_test.go3
-rw-r--r--vendor/github.com/mitchellh/packer/builder/azure/arm/step_get_certificate.go3
-rw-r--r--vendor/github.com/mitchellh/packer/builder/azure/arm/step_get_certificate_test.go3
-rw-r--r--vendor/github.com/mitchellh/packer/builder/azure/arm/step_get_ip_address.go16
-rw-r--r--vendor/github.com/mitchellh/packer/builder/azure/arm/step_get_ip_address_test.go166
-rw-r--r--vendor/github.com/mitchellh/packer/builder/azure/arm/step_get_os_disk.go3
-rw-r--r--vendor/github.com/mitchellh/packer/builder/azure/arm/step_get_os_disk_test.go3
-rw-r--r--vendor/github.com/mitchellh/packer/builder/azure/arm/step_power_off_compute.go3
-rw-r--r--vendor/github.com/mitchellh/packer/builder/azure/arm/step_power_off_compute_test.go3
-rw-r--r--vendor/github.com/mitchellh/packer/builder/azure/arm/step_set_certificate.go3
-rw-r--r--vendor/github.com/mitchellh/packer/builder/azure/arm/step_set_certificate_test.go3
-rw-r--r--vendor/github.com/mitchellh/packer/builder/azure/arm/step_test.go3
-rw-r--r--vendor/github.com/mitchellh/packer/builder/azure/arm/step_validate_template.go3
-rw-r--r--vendor/github.com/mitchellh/packer/builder/azure/arm/step_validate_template_test.go3
-rw-r--r--vendor/github.com/mitchellh/packer/builder/azure/arm/template_factory.go11
-rw-r--r--vendor/github.com/mitchellh/packer/builder/azure/arm/template_factory_test.TestVirtualMachineDeployment08.approved.json3
-rw-r--r--vendor/github.com/mitchellh/packer/builder/azure/arm/template_factory_test.TestVirtualMachineDeployment09.approved.json3
-rw-r--r--vendor/github.com/mitchellh/packer/builder/azure/arm/template_factory_test.TestVirtualMachineDeployment10.approved.json144
-rw-r--r--vendor/github.com/mitchellh/packer/builder/azure/arm/template_factory_test.go37
-rw-r--r--vendor/github.com/mitchellh/packer/builder/azure/arm/tempname.go3
-rw-r--r--vendor/github.com/mitchellh/packer/builder/azure/arm/tempname_test.go3
-rw-r--r--vendor/github.com/mitchellh/packer/builder/azure/common/constants/stateBag.go3
-rw-r--r--vendor/github.com/mitchellh/packer/builder/azure/common/constants/targetplatforms.go3
-rw-r--r--vendor/github.com/mitchellh/packer/builder/azure/common/gluestrings.go3
-rw-r--r--vendor/github.com/mitchellh/packer/builder/azure/common/gluestrings_test.go3
-rw-r--r--vendor/github.com/mitchellh/packer/builder/azure/common/interruptible_task.go3
-rw-r--r--vendor/github.com/mitchellh/packer/builder/azure/common/interruptible_task_test.go3
-rw-r--r--vendor/github.com/mitchellh/packer/builder/azure/common/lin/ssh.go3
-rw-r--r--vendor/github.com/mitchellh/packer/builder/azure/common/lin/step_create_cert.go3
-rw-r--r--vendor/github.com/mitchellh/packer/builder/azure/common/lin/step_generalize_os.go3
-rw-r--r--vendor/github.com/mitchellh/packer/builder/azure/common/logutil/logfields.go3
-rw-r--r--vendor/github.com/mitchellh/packer/builder/azure/common/randomstring.go3
-rw-r--r--vendor/github.com/mitchellh/packer/builder/azure/common/randomstring_test.go3
-rw-r--r--vendor/github.com/mitchellh/packer/builder/azure/common/state_bag.go3
-rw-r--r--vendor/github.com/mitchellh/packer/builder/azure/common/template/template.go1
-rw-r--r--vendor/github.com/mitchellh/packer/builder/azure/common/template/template_builder.go28
-rw-r--r--vendor/github.com/mitchellh/packer/builder/azure/common/template/template_parameters.go3
-rw-r--r--vendor/github.com/mitchellh/packer/builder/azure/common/template/template_parameters_test.go3
-rw-r--r--vendor/github.com/mitchellh/packer/builder/azure/common/vault.go3
-rw-r--r--vendor/github.com/mitchellh/packer/builder/azure/pkcs12/LICENSE27
-rw-r--r--vendor/github.com/mitchellh/packer/builder/azure/pkcs12/README.md9
-rw-r--r--vendor/github.com/mitchellh/packer/builder/azure/pkcs12/bmp-string.go34
-rw-r--r--vendor/github.com/mitchellh/packer/builder/azure/pkcs12/bmp-string_test.go101
-rw-r--r--vendor/github.com/mitchellh/packer/builder/azure/pkcs12/crypto.go131
-rw-r--r--vendor/github.com/mitchellh/packer/builder/azure/pkcs12/crypto_test.go199
-rw-r--r--vendor/github.com/mitchellh/packer/builder/azure/pkcs12/errors.go6
-rw-r--r--vendor/github.com/mitchellh/packer/builder/azure/pkcs12/mac.go25
-rw-r--r--vendor/github.com/mitchellh/packer/builder/azure/pkcs12/mac_test.go18
-rw-r--r--vendor/github.com/mitchellh/packer/builder/azure/pkcs12/pbkdf.go109
-rw-r--r--vendor/github.com/mitchellh/packer/builder/azure/pkcs12/pbkdf_test.go24
-rw-r--r--vendor/github.com/mitchellh/packer/builder/azure/pkcs12/pkcs12.go308
-rw-r--r--vendor/github.com/mitchellh/packer/builder/azure/pkcs12/pkcs12_test.go138
-rw-r--r--vendor/github.com/mitchellh/packer/builder/azure/pkcs12/pkcs8.go5
-rw-r--r--vendor/github.com/mitchellh/packer/builder/azure/pkcs12/pkcs8_test.go2
-rw-r--r--vendor/github.com/mitchellh/packer/builder/azure/pkcs12/rc2/bench_test.go27
-rw-r--r--vendor/github.com/mitchellh/packer/builder/azure/pkcs12/rc2/rc2.go36
-rw-r--r--vendor/github.com/mitchellh/packer/builder/azure/pkcs12/rc2/rc2_test.go22
-rw-r--r--vendor/github.com/mitchellh/packer/builder/azure/pkcs12/safebags.go50
-rw-r--r--vendor/github.com/mitchellh/packer/builder/azure/pkcs12/safebags_test.go34
-rw-r--r--vendor/github.com/mitchellh/packer/builder/cloudstack/builder.go31
-rw-r--r--vendor/github.com/mitchellh/packer/builder/cloudstack/config.go55
-rw-r--r--vendor/github.com/mitchellh/packer/builder/cloudstack/ssh.go23
-rw-r--r--vendor/github.com/mitchellh/packer/builder/cloudstack/step_configure_networking.go12
-rw-r--r--vendor/github.com/mitchellh/packer/builder/cloudstack/step_create_instance.go21
-rw-r--r--vendor/github.com/mitchellh/packer/builder/cloudstack/step_create_security_group.go94
-rw-r--r--vendor/github.com/mitchellh/packer/builder/cloudstack/step_keypair.go133
-rw-r--r--vendor/github.com/mitchellh/packer/builder/cloudstack/step_prepare_config.go73
-rw-r--r--vendor/github.com/mitchellh/packer/builder/digitalocean/step_snapshot.go4
-rw-r--r--vendor/github.com/mitchellh/packer/builder/docker/communicator.go196
-rw-r--r--vendor/github.com/mitchellh/packer/builder/docker/config.go29
-rw-r--r--vendor/github.com/mitchellh/packer/builder/docker/step_connect_docker.go4
-rw-r--r--vendor/github.com/mitchellh/packer/builder/docker/step_run.go2
-rw-r--r--vendor/github.com/mitchellh/packer/builder/googlecompute/config.go11
-rw-r--r--vendor/github.com/mitchellh/packer/builder/googlecompute/config_test.go60
-rw-r--r--vendor/github.com/mitchellh/packer/builder/googlecompute/driver.go3
-rw-r--r--vendor/github.com/mitchellh/packer/builder/googlecompute/driver_gce.go13
-rw-r--r--vendor/github.com/mitchellh/packer/builder/googlecompute/startup.go2
-rw-r--r--vendor/github.com/mitchellh/packer/builder/googlecompute/step_create_instance.go3
-rw-r--r--vendor/github.com/mitchellh/packer/builder/googlecompute/step_create_instance_test.go4
-rw-r--r--vendor/github.com/mitchellh/packer/builder/hyperv/iso/builder.go15
-rw-r--r--vendor/github.com/mitchellh/packer/builder/lxc/artifact.go35
-rw-r--r--vendor/github.com/mitchellh/packer/builder/lxc/builder.go95
-rw-r--r--vendor/github.com/mitchellh/packer/builder/lxc/builder_test.go56
-rw-r--r--vendor/github.com/mitchellh/packer/builder/lxc/command.go15
-rw-r--r--vendor/github.com/mitchellh/packer/builder/lxc/communicator.go151
-rw-r--r--vendor/github.com/mitchellh/packer/builder/lxc/communicator_test.go14
-rw-r--r--vendor/github.com/mitchellh/packer/builder/lxc/config.go79
-rw-r--r--vendor/github.com/mitchellh/packer/builder/lxc/step_export.go98
-rw-r--r--vendor/github.com/mitchellh/packer/builder/lxc/step_lxc_create.go89
-rw-r--r--vendor/github.com/mitchellh/packer/builder/lxc/step_prepare_output_dir.go49
-rw-r--r--vendor/github.com/mitchellh/packer/builder/lxc/step_provision.go36
-rw-r--r--vendor/github.com/mitchellh/packer/builder/lxc/step_wait_init.go102
-rw-r--r--vendor/github.com/mitchellh/packer/builder/lxd/artifact.go34
-rw-r--r--vendor/github.com/mitchellh/packer/builder/lxd/builder.go74
-rw-r--r--vendor/github.com/mitchellh/packer/builder/lxd/builder_test.go77
-rw-r--r--vendor/github.com/mitchellh/packer/builder/lxd/command.go43
-rw-r--r--vendor/github.com/mitchellh/packer/builder/lxd/communicator.go142
-rw-r--r--vendor/github.com/mitchellh/packer/builder/lxd/communicator_test.go20
-rw-r--r--vendor/github.com/mitchellh/packer/builder/lxd/config.go60
-rw-r--r--vendor/github.com/mitchellh/packer/builder/lxd/step_lxd_launch.go50
-rw-r--r--vendor/github.com/mitchellh/packer/builder/lxd/step_provision.go34
-rw-r--r--vendor/github.com/mitchellh/packer/builder/lxd/step_publish.go54
-rw-r--r--vendor/github.com/mitchellh/packer/builder/oneandone/builder.go10
-rw-r--r--vendor/github.com/mitchellh/packer/builder/oracle/oci/LICENSE375
-rw-r--r--vendor/github.com/mitchellh/packer/builder/oracle/oci/artifact.go45
-rw-r--r--vendor/github.com/mitchellh/packer/builder/oracle/oci/artifact_test.go15
-rw-r--r--vendor/github.com/mitchellh/packer/builder/oracle/oci/builder.go96
-rw-r--r--vendor/github.com/mitchellh/packer/builder/oracle/oci/builder_test.go15
-rw-r--r--vendor/github.com/mitchellh/packer/builder/oracle/oci/client/base_client.go215
-rw-r--r--vendor/github.com/mitchellh/packer/builder/oracle/oci/client/client.go31
-rw-r--r--vendor/github.com/mitchellh/packer/builder/oracle/oci/client/client_test.go49
-rw-r--r--vendor/github.com/mitchellh/packer/builder/oracle/oci/client/compute.go21
-rw-r--r--vendor/github.com/mitchellh/packer/builder/oracle/oci/client/config.go240
-rw-r--r--vendor/github.com/mitchellh/packer/builder/oracle/oci/client/config_test.go283
-rw-r--r--vendor/github.com/mitchellh/packer/builder/oracle/oci/client/error.go27
-rw-r--r--vendor/github.com/mitchellh/packer/builder/oracle/oci/client/image.go122
-rw-r--r--vendor/github.com/mitchellh/packer/builder/oracle/oci/client/image_test.go115
-rw-r--r--vendor/github.com/mitchellh/packer/builder/oracle/oci/client/instance.go129
-rw-r--r--vendor/github.com/mitchellh/packer/builder/oracle/oci/client/instance_test.go96
-rw-r--r--vendor/github.com/mitchellh/packer/builder/oracle/oci/client/transport.go116
-rw-r--r--vendor/github.com/mitchellh/packer/builder/oracle/oci/client/transport_test.go156
-rw-r--r--vendor/github.com/mitchellh/packer/builder/oracle/oci/client/vnic.go47
-rw-r--r--vendor/github.com/mitchellh/packer/builder/oracle/oci/client/vnic_attachment.go52
-rw-r--r--vendor/github.com/mitchellh/packer/builder/oracle/oci/client/vnic_attachment_test.go31
-rw-r--r--vendor/github.com/mitchellh/packer/builder/oracle/oci/client/vnic_test.go29
-rw-r--r--vendor/github.com/mitchellh/packer/builder/oracle/oci/client/waiters.go59
-rw-r--r--vendor/github.com/mitchellh/packer/builder/oracle/oci/client/waiters_test.go80
-rw-r--r--vendor/github.com/mitchellh/packer/builder/oracle/oci/config.go215
-rw-r--r--vendor/github.com/mitchellh/packer/builder/oracle/oci/config_test.go181
-rw-r--r--vendor/github.com/mitchellh/packer/builder/oracle/oci/driver.go16
-rw-r--r--vendor/github.com/mitchellh/packer/builder/oracle/oci/driver_mock.go89
-rw-r--r--vendor/github.com/mitchellh/packer/builder/oracle/oci/driver_oci.go117
-rw-r--r--vendor/github.com/mitchellh/packer/builder/oracle/oci/ssh.go45
-rw-r--r--vendor/github.com/mitchellh/packer/builder/oracle/oci/step_create_instance.go75
-rw-r--r--vendor/github.com/mitchellh/packer/builder/oracle/oci/step_create_instance_test.go130
-rw-r--r--vendor/github.com/mitchellh/packer/builder/oracle/oci/step_image.go48
-rw-r--r--vendor/github.com/mitchellh/packer/builder/oracle/oci/step_image_test.go70
-rw-r--r--vendor/github.com/mitchellh/packer/builder/oracle/oci/step_instance_info.go36
-rw-r--r--vendor/github.com/mitchellh/packer/builder/oracle/oci/step_instance_info_test.go52
-rw-r--r--vendor/github.com/mitchellh/packer/builder/oracle/oci/step_ssh_key_pair.go116
-rw-r--r--vendor/github.com/mitchellh/packer/builder/oracle/oci/step_test.go62
-rw-r--r--vendor/github.com/mitchellh/packer/builder/parallels/common/driver_9.go17
-rw-r--r--vendor/github.com/mitchellh/packer/builder/parallels/common/driver_9_test.go26
-rw-r--r--vendor/github.com/mitchellh/packer/builder/profitbricks/builder.go10
-rw-r--r--vendor/github.com/mitchellh/packer/builder/profitbricks/config.go2
-rw-r--r--vendor/github.com/mitchellh/packer/builder/profitbricks/step_create_server.go88
-rw-r--r--vendor/github.com/mitchellh/packer/builder/profitbricks/step_take_snapshot.go2
-rw-r--r--vendor/github.com/mitchellh/packer/builder/vmware/common/artifact.go8
-rw-r--r--vendor/github.com/mitchellh/packer/builder/vmware/common/artifact_test.go5
-rw-r--r--vendor/github.com/mitchellh/packer/builder/vmware/iso/artifact.go5
-rw-r--r--vendor/github.com/mitchellh/packer/builder/vmware/iso/builder.go7
-rw-r--r--vendor/github.com/mitchellh/packer/builder/vmware/iso/step_export.go19
-rw-r--r--vendor/github.com/mitchellh/packer/builder/vmware/vmx/builder.go2
-rw-r--r--vendor/github.com/mitchellh/packer/builder/vmware/vmx/config.go3
196 files changed, 7428 insertions, 1066 deletions
diff --git a/vendor/github.com/mitchellh/packer/builder/alicloud/ecs/access_config.go b/vendor/github.com/mitchellh/packer/builder/alicloud/ecs/access_config.go
index 33d4ff52..bcc7ba76 100644
--- a/vendor/github.com/mitchellh/packer/builder/alicloud/ecs/access_config.go
+++ b/vendor/github.com/mitchellh/packer/builder/alicloud/ecs/access_config.go
@@ -22,7 +22,7 @@ func (c *AlicloudAccessConfig) Client() (*ecs.Client, error) {
if err := c.loadAndValidate(); err != nil {
return nil, err
}
- client := ecs.NewClient(c.AlicloudAccessKey, c.AlicloudSecretKey)
+ client := ecs.NewECSClient(c.AlicloudAccessKey, c.AlicloudSecretKey, common.Region(c.AlicloudRegion))
client.SetBusinessInfo("Packer")
if _, err := client.DescribeRegions(); err != nil {
return nil, err
diff --git a/vendor/github.com/mitchellh/packer/builder/alicloud/ecs/step_config_vswitch.go b/vendor/github.com/mitchellh/packer/builder/alicloud/ecs/step_config_vswitch.go
index 734647e0..dfa858d0 100644
--- a/vendor/github.com/mitchellh/packer/builder/alicloud/ecs/step_config_vswitch.go
+++ b/vendor/github.com/mitchellh/packer/builder/alicloud/ecs/step_config_vswitch.go
@@ -113,7 +113,7 @@ func (s *stepConfigAlicloudVSwitch) Run(state multistep.StateBag) multistep.Step
}
if err := client.WaitForVSwitchAvailable(vpcId, s.VSwitchId, ALICLOUD_DEFAULT_TIMEOUT); err != nil {
state.Put("error", err)
- ui.Error(fmt.Sprintf("Timeout waiting for vswitch to become avaiable: %v", err))
+ ui.Error(fmt.Sprintf("Timeout waiting for vswitch to become available: %v", err))
return multistep.ActionHalt
}
state.Put("vswitchid", vswitchId)
diff --git a/vendor/github.com/mitchellh/packer/builder/amazon/chroot/builder.go b/vendor/github.com/mitchellh/packer/builder/amazon/chroot/builder.go
index 65660cf4..a259960d 100644
--- a/vendor/github.com/mitchellh/packer/builder/amazon/chroot/builder.go
+++ b/vendor/github.com/mitchellh/packer/builder/amazon/chroot/builder.go
@@ -213,9 +213,10 @@ func (b *Builder) Run(ui packer.Ui, hook packer.Hook, cache packer.Cache) (packe
if !b.config.FromScratch {
steps = append(steps,
&awscommon.StepSourceAMIInfo{
- SourceAmi: b.config.SourceAmi,
- EnhancedNetworking: b.config.AMIEnhancedNetworking,
- AmiFilters: b.config.SourceAmiFilter,
+ SourceAmi: b.config.SourceAmi,
+ EnableAMISriovNetSupport: b.config.AMISriovNetSupport,
+ EnableAMIENASupport: b.config.AMIENASupport,
+ AmiFilters: b.config.SourceAmiFilter,
},
&StepCheckRootDevice{},
)
@@ -245,17 +246,22 @@ func (b *Builder) Run(ui packer.Ui, hook packer.Hook, cache packer.Cache) (packe
&StepEarlyCleanup{},
&StepSnapshot{},
&awscommon.StepDeregisterAMI{
+ AccessConfig: &b.config.AccessConfig,
ForceDeregister: b.config.AMIForceDeregister,
ForceDeleteSnapshot: b.config.AMIForceDeleteSnapshot,
AMIName: b.config.AMIName,
+ Regions: b.config.AMIRegions,
},
&StepRegisterAMI{
- RootVolumeSize: b.config.RootVolumeSize,
+ RootVolumeSize: b.config.RootVolumeSize,
+ EnableAMISriovNetSupport: b.config.AMISriovNetSupport,
+ EnableAMIENASupport: b.config.AMIENASupport,
},
&awscommon.StepCreateEncryptedAMICopy{
KeyID: b.config.AMIKmsKeyId,
EncryptBootVolume: b.config.AMIEncryptBootVolume,
Name: b.config.AMIName,
+ AMIMappings: b.config.AMIBlockDevices.AMIMappings,
},
&awscommon.StepAMIRegionCopy{
AccessConfig: &b.config.AccessConfig,
diff --git a/vendor/github.com/mitchellh/packer/builder/amazon/chroot/lockfile_unix.go b/vendor/github.com/mitchellh/packer/builder/amazon/chroot/lockfile_unix.go
index 43e92af2..0d0f8c8f 100644
--- a/vendor/github.com/mitchellh/packer/builder/amazon/chroot/lockfile_unix.go
+++ b/vendor/github.com/mitchellh/packer/builder/amazon/chroot/lockfile_unix.go
@@ -4,7 +4,8 @@ package chroot
import (
"os"
- "syscall"
+
+ "golang.org/x/sys/unix"
)
// See: http://linux.die.net/include/sys/file.h
@@ -13,7 +14,7 @@ const LOCK_NB = 4
const LOCK_UN = 8
func lockFile(f *os.File) error {
- err := syscall.Flock(int(f.Fd()), LOCK_EX)
+ err := unix.Flock(int(f.Fd()), LOCK_EX)
if err != nil {
return err
}
@@ -22,5 +23,5 @@ func lockFile(f *os.File) error {
}
func unlockFile(f *os.File) error {
- return syscall.Flock(int(f.Fd()), LOCK_UN)
+ return unix.Flock(int(f.Fd()), LOCK_UN)
}
diff --git a/vendor/github.com/mitchellh/packer/builder/amazon/chroot/step_register_ami.go b/vendor/github.com/mitchellh/packer/builder/amazon/chroot/step_register_ami.go
index d387eada..a19266f5 100644
--- a/vendor/github.com/mitchellh/packer/builder/amazon/chroot/step_register_ami.go
+++ b/vendor/github.com/mitchellh/packer/builder/amazon/chroot/step_register_ami.go
@@ -12,7 +12,9 @@ import (
// StepRegisterAMI creates the AMI.
type StepRegisterAMI struct {
- RootVolumeSize int64
+ RootVolumeSize int64
+ EnableAMIENASupport bool
+ EnableAMISriovNetSupport bool
}
func (s *StepRegisterAMI) Run(state multistep.StateBag) multistep.StepAction {
@@ -75,11 +77,12 @@ func (s *StepRegisterAMI) Run(state multistep.StateBag) multistep.StepAction {
registerOpts = buildRegisterOpts(config, image, newMappings)
}
- if config.AMIEnhancedNetworking {
+ if s.EnableAMISriovNetSupport {
// Set SriovNetSupport to "simple". See http://goo.gl/icuXh5
// As of February 2017, this applies to C3, C4, D2, I2, R3, and M4 (excluding m4.16xlarge)
registerOpts.SriovNetSupport = aws.String("simple")
-
+ }
+ if s.EnableAMIENASupport {
// Set EnaSupport to true
// As of February 2017, this applies to C5, I3, P2, R4, X1, and m4.16xlarge
registerOpts.EnaSupport = aws.Bool(true)
diff --git a/vendor/github.com/mitchellh/packer/builder/amazon/common/ami_config.go b/vendor/github.com/mitchellh/packer/builder/amazon/common/ami_config.go
index 72fd0704..f59cb1d6 100644
--- a/vendor/github.com/mitchellh/packer/builder/amazon/common/ami_config.go
+++ b/vendor/github.com/mitchellh/packer/builder/amazon/common/ami_config.go
@@ -17,7 +17,8 @@ type AMIConfig struct {
AMIRegions []string `mapstructure:"ami_regions"`
AMISkipRegionValidation bool `mapstructure:"skip_region_validation"`
AMITags map[string]string `mapstructure:"tags"`
- AMIEnhancedNetworking bool `mapstructure:"enhanced_networking"`
+ AMIENASupport bool `mapstructure:"ena_support"`
+ AMISriovNetSupport bool `mapstructure:"sriov_support"`
AMIForceDeregister bool `mapstructure:"force_deregister"`
AMIForceDeleteSnapshot bool `mapstructure:"force_delete_snapshot"`
AMIEncryptBootVolume bool `mapstructure:"encrypt_boot"`
diff --git a/vendor/github.com/mitchellh/packer/builder/amazon/common/artifact.go b/vendor/github.com/mitchellh/packer/builder/amazon/common/artifact.go
index c9f9a08b..dc50f772 100644
--- a/vendor/github.com/mitchellh/packer/builder/amazon/common/artifact.go
+++ b/vendor/github.com/mitchellh/packer/builder/amazon/common/artifact.go
@@ -51,7 +51,7 @@ func (a *Artifact) String() string {
}
sort.Strings(amiStrings)
- return fmt.Sprintf("AMIs were created:\n\n%s", strings.Join(amiStrings, "\n"))
+ return fmt.Sprintf("AMIs were created:\n%s\n", strings.Join(amiStrings, "\n"))
}
func (a *Artifact) State(name string) interface{} {
diff --git a/vendor/github.com/mitchellh/packer/builder/amazon/common/artifact_test.go b/vendor/github.com/mitchellh/packer/builder/amazon/common/artifact_test.go
index ccbf0a1e..d70754eb 100644
--- a/vendor/github.com/mitchellh/packer/builder/amazon/common/artifact_test.go
+++ b/vendor/github.com/mitchellh/packer/builder/amazon/common/artifact_test.go
@@ -48,9 +48,9 @@ func TestArtifactState_atlasMetadata(t *testing.T) {
func TestArtifactString(t *testing.T) {
expected := `AMIs were created:
-
east: foo
-west: bar`
+west: bar
+`
amis := make(map[string]string)
amis["east"] = "foo"
diff --git a/vendor/github.com/mitchellh/packer/builder/amazon/common/step_deregister_ami.go b/vendor/github.com/mitchellh/packer/builder/amazon/common/step_deregister_ami.go
index 7dc39e28..3ad8711a 100644
--- a/vendor/github.com/mitchellh/packer/builder/amazon/common/step_deregister_ami.go
+++ b/vendor/github.com/mitchellh/packer/builder/amazon/common/step_deregister_ami.go
@@ -10,59 +10,76 @@ import (
)
type StepDeregisterAMI struct {
+ AccessConfig *AccessConfig
ForceDeregister bool
ForceDeleteSnapshot bool
AMIName string
+ Regions []string
}
func (s *StepDeregisterAMI) Run(state multistep.StateBag) multistep.StepAction {
- ec2conn := state.Get("ec2").(*ec2.EC2)
ui := state.Get("ui").(packer.Ui)
+ regions := s.Regions
+ if len(regions) == 0 {
+ regions = append(regions, s.AccessConfig.RawRegion)
+ }
// Check for force deregister
if s.ForceDeregister {
- resp, err := ec2conn.DescribeImages(&ec2.DescribeImagesInput{
- Filters: []*ec2.Filter{{
- Name: aws.String("name"),
- Values: []*string{aws.String(s.AMIName)},
- }}})
+ for _, region := range regions {
+ // get new connection for each region in which we need to deregister vms
+ session, err := s.AccessConfig.Session()
+ if err != nil {
+ return multistep.ActionHalt
+ }
- if err != nil {
- err := fmt.Errorf("Error describing AMI: %s", err)
- state.Put("error", err)
- ui.Error(err.Error())
- return multistep.ActionHalt
- }
+ regionconn := ec2.New(session.Copy(&aws.Config{
+ Region: aws.String(region)},
+ ))
- // Deregister image(s) by name
- for _, i := range resp.Images {
- _, err := ec2conn.DeregisterImage(&ec2.DeregisterImageInput{
- ImageId: i.ImageId,
- })
+ resp, err := regionconn.DescribeImages(&ec2.DescribeImagesInput{
+ Filters: []*ec2.Filter{{
+ Name: aws.String("name"),
+ Values: []*string{aws.String(s.AMIName)},
+ }}})
if err != nil {
- err := fmt.Errorf("Error deregistering existing AMI: %s", err)
+ err := fmt.Errorf("Error describing AMI: %s", err)
state.Put("error", err)
ui.Error(err.Error())
return multistep.ActionHalt
}
- ui.Say(fmt.Sprintf("Deregistered AMI %s, id: %s", s.AMIName, *i.ImageId))
- // Delete snapshot(s) by image
- if s.ForceDeleteSnapshot {
- for _, b := range i.BlockDeviceMappings {
- if b.Ebs != nil && aws.StringValue(b.Ebs.SnapshotId) != "" {
- _, err := ec2conn.DeleteSnapshot(&ec2.DeleteSnapshotInput{
- SnapshotId: b.Ebs.SnapshotId,
- })
+ // Deregister image(s) by name
+ for _, i := range resp.Images {
+ _, err := regionconn.DeregisterImage(&ec2.DeregisterImageInput{
+ ImageId: i.ImageId,
+ })
+
+ if err != nil {
+ err := fmt.Errorf("Error deregistering existing AMI: %s", err)
+ state.Put("error", err)
+ ui.Error(err.Error())
+ return multistep.ActionHalt
+ }
+ ui.Say(fmt.Sprintf("Deregistered AMI %s, id: %s", s.AMIName, *i.ImageId))
+
+ // Delete snapshot(s) by image
+ if s.ForceDeleteSnapshot {
+ for _, b := range i.BlockDeviceMappings {
+ if b.Ebs != nil && aws.StringValue(b.Ebs.SnapshotId) != "" {
+ _, err := regionconn.DeleteSnapshot(&ec2.DeleteSnapshotInput{
+ SnapshotId: b.Ebs.SnapshotId,
+ })
- if err != nil {
- err := fmt.Errorf("Error deleting existing snapshot: %s", err)
- state.Put("error", err)
- ui.Error(err.Error())
- return multistep.ActionHalt
+ if err != nil {
+ err := fmt.Errorf("Error deleting existing snapshot: %s", err)
+ state.Put("error", err)
+ ui.Error(err.Error())
+ return multistep.ActionHalt
+ }
+ ui.Say(fmt.Sprintf("Deleted snapshot: %s", *b.Ebs.SnapshotId))
}
- ui.Say(fmt.Sprintf("Deleted snapshot: %s", *b.Ebs.SnapshotId))
}
}
}
diff --git a/vendor/github.com/mitchellh/packer/builder/amazon/common/step_encrypted_ami.go b/vendor/github.com/mitchellh/packer/builder/amazon/common/step_encrypted_ami.go
index fec882b6..16c4ce7a 100644
--- a/vendor/github.com/mitchellh/packer/builder/amazon/common/step_encrypted_ami.go
+++ b/vendor/github.com/mitchellh/packer/builder/amazon/common/step_encrypted_ami.go
@@ -15,6 +15,7 @@ type StepCreateEncryptedAMICopy struct {
KeyID string
EncryptBootVolume bool
Name string
+ AMIMappings []BlockDevice
}
func (s *StepCreateEncryptedAMICopy) Run(state multistep.StateBag) multistep.StepAction {
@@ -116,9 +117,18 @@ func (s *StepCreateEncryptedAMICopy) Run(state multistep.StateBag) multistep.Ste
ui.Say("Deleting unencrypted snapshots")
snapshots := state.Get("snapshots").(map[string][]string)
+OuterLoop:
for _, blockDevice := range unencImage.BlockDeviceMappings {
if blockDevice.Ebs != nil && blockDevice.Ebs.SnapshotId != nil {
- ui.Message(fmt.Sprintf("Snapshot ID: %s", *blockDevice.Ebs.SnapshotId))
+ // If this packer run didn't create it, then don't delete it
+ for _, origDevice := range s.AMIMappings {
+ if origDevice.SnapshotId == *blockDevice.Ebs.SnapshotId {
+ ui.Message(fmt.Sprintf("Keeping Snapshot ID: %s", *blockDevice.Ebs.SnapshotId))
+ continue OuterLoop
+ }
+ }
+
+ ui.Message(fmt.Sprintf("Deleting Snapshot ID: %s", *blockDevice.Ebs.SnapshotId))
deleteSnapOpts := &ec2.DeleteSnapshotInput{
SnapshotId: aws.String(*blockDevice.Ebs.SnapshotId),
}
diff --git a/vendor/github.com/mitchellh/packer/builder/amazon/common/step_modify_ebs_instance.go b/vendor/github.com/mitchellh/packer/builder/amazon/common/step_modify_ebs_instance.go
index 11fa629d..12c2367a 100644
--- a/vendor/github.com/mitchellh/packer/builder/amazon/common/step_modify_ebs_instance.go
+++ b/vendor/github.com/mitchellh/packer/builder/amazon/common/step_modify_ebs_instance.go
@@ -10,7 +10,8 @@ import (
)
type StepModifyEBSBackedInstance struct {
- EnableEnhancedNetworking bool
+ EnableAMIENASupport bool
+ EnableAMISriovNetSupport bool
}
func (s *StepModifyEBSBackedInstance) Run(state multistep.StateBag) multistep.StepAction {
@@ -18,9 +19,9 @@ func (s *StepModifyEBSBackedInstance) Run(state multistep.StateBag) multistep.St
instance := state.Get("instance").(*ec2.Instance)
ui := state.Get("ui").(packer.Ui)
- if s.EnableEnhancedNetworking {
- // Set SriovNetSupport to "simple". See http://goo.gl/icuXh5
- // As of February 2017, this applies to C3, C4, D2, I2, R3, and M4 (excluding m4.16xlarge)
+ // Set SriovNetSupport to "simple". See http://goo.gl/icuXh5
+ // As of February 2017, this applies to C3, C4, D2, I2, R3, and M4 (excluding m4.16xlarge)
+ if s.EnableAMISriovNetSupport {
ui.Say("Enabling Enhanced Networking (SR-IOV)...")
simple := "simple"
_, err := ec2conn.ModifyInstanceAttribute(&ec2.ModifyInstanceAttributeInput{
@@ -33,11 +34,13 @@ func (s *StepModifyEBSBackedInstance) Run(state multistep.StateBag) multistep.St
ui.Error(err.Error())
return multistep.ActionHalt
}
+ }
- // Set EnaSupport to true.
- // As of February 2017, this applies to C5, I3, P2, R4, X1, and m4.16xlarge
+ // Set EnaSupport to true.
+ // As of February 2017, this applies to C5, I3, P2, R4, X1, and m4.16xlarge
+ if s.EnableAMIENASupport {
ui.Say("Enabling Enhanced Networking (ENA)...")
- _, err = ec2conn.ModifyInstanceAttribute(&ec2.ModifyInstanceAttributeInput{
+ _, err := ec2conn.ModifyInstanceAttribute(&ec2.ModifyInstanceAttributeInput{
InstanceId: instance.InstanceId,
EnaSupport: &ec2.AttributeBooleanValue{Value: aws.Bool(true)},
})
diff --git a/vendor/github.com/mitchellh/packer/builder/amazon/common/step_run_source_instance.go b/vendor/github.com/mitchellh/packer/builder/amazon/common/step_run_source_instance.go
index 1aecd75f..5a864a5e 100644
--- a/vendor/github.com/mitchellh/packer/builder/amazon/common/step_run_source_instance.go
+++ b/vendor/github.com/mitchellh/packer/builder/amazon/common/step_run_source_instance.go
@@ -136,7 +136,23 @@ func (s *StepRunSourceInstance) Run(state multistep.StateBag) multistep.StepActi
var instanceId string
+ ui.Say("Adding tags to source instance")
+ if _, exists := s.Tags["Name"]; !exists {
+ s.Tags["Name"] = "Packer Builder"
+ }
+
+ createTagsAfterInstanceStarts := true
+ ec2Tags, err := ConvertToEC2Tags(s.Tags, *ec2conn.Config.Region, s.SourceAMI, s.Ctx)
+ if err != nil {
+ err := fmt.Errorf("Error tagging source instance: %s", err)
+ state.Put("error", err)
+ ui.Error(err.Error())
+ return multistep.ActionHalt
+ }
+ ReportTags(ui, ec2Tags)
+
if spotPrice == "" || spotPrice == "0" {
+
runOpts := &ec2.RunInstancesInput{
ImageId: &s.SourceAMI,
InstanceType: &s.InstanceType,
@@ -149,6 +165,16 @@ func (s *StepRunSourceInstance) Run(state multistep.StateBag) multistep.StepActi
EbsOptimized: &s.EbsOptimized,
}
+ if len(ec2Tags) > 0 {
+ runTags := &ec2.TagSpecification{
+ ResourceType: aws.String("instance"),
+ Tags: ec2Tags,
+ }
+
+ runOpts.SetTagSpecifications([]*ec2.TagSpecification{runTags})
+ createTagsAfterInstanceStarts = false
+ }
+
if keyName != "" {
runOpts.KeyName = &keyName
}
@@ -255,6 +281,7 @@ func (s *StepRunSourceInstance) Run(state multistep.StateBag) multistep.StepActi
return multistep.ActionHalt
}
instanceId = *spotResp.SpotInstanceRequests[0].InstanceId
+
}
// Set the instance ID so that the cleanup works properly
@@ -278,43 +305,30 @@ func (s *StepRunSourceInstance) Run(state multistep.StateBag) multistep.StepActi
instance := latestInstance.(*ec2.Instance)
- ui.Say("Adding tags to source instance")
- if _, exists := s.Tags["Name"]; !exists {
- s.Tags["Name"] = "Packer Builder"
- }
-
- ec2Tags, err := ConvertToEC2Tags(s.Tags, *ec2conn.Config.Region, s.SourceAMI, s.Ctx)
- if err != nil {
- err := fmt.Errorf("Error tagging source instance: %s", err)
- state.Put("error", err)
- ui.Error(err.Error())
- return multistep.ActionHalt
- }
-
- ReportTags(ui, ec2Tags)
-
- // Retry creating tags for about 2.5 minutes
- err = retry.Retry(0.2, 30, 11, func(_ uint) (bool, error) {
- _, err := ec2conn.CreateTags(&ec2.CreateTagsInput{
- Tags: ec2Tags,
- Resources: []*string{instance.InstanceId},
- })
- if err == nil {
- return true, nil
- }
- if awsErr, ok := err.(awserr.Error); ok {
- if awsErr.Code() == "InvalidInstanceID.NotFound" {
- return false, nil
+ if createTagsAfterInstanceStarts {
+ // Retry creating tags for about 2.5 minutes
+ err = retry.Retry(0.2, 30, 11, func(_ uint) (bool, error) {
+ _, err := ec2conn.CreateTags(&ec2.CreateTagsInput{
+ Tags: ec2Tags,
+ Resources: []*string{instance.InstanceId},
+ })
+ if err == nil {
+ return true, nil
}
- }
- return true, err
- })
+ if awsErr, ok := err.(awserr.Error); ok {
+ if awsErr.Code() == "InvalidInstanceID.NotFound" {
+ return false, nil
+ }
+ }
+ return true, err
+ })
- if err != nil {
- err := fmt.Errorf("Error tagging source instance: %s", err)
- state.Put("error", err)
- ui.Error(err.Error())
- return multistep.ActionHalt
+ if err != nil {
+ err := fmt.Errorf("Error tagging source instance: %s", err)
+ state.Put("error", err)
+ ui.Error(err.Error())
+ return multistep.ActionHalt
+ }
}
if s.Debug {
diff --git a/vendor/github.com/mitchellh/packer/builder/amazon/common/step_security_group.go b/vendor/github.com/mitchellh/packer/builder/amazon/common/step_security_group.go
index a5032772..e7bc294b 100644
--- a/vendor/github.com/mitchellh/packer/builder/amazon/common/step_security_group.go
+++ b/vendor/github.com/mitchellh/packer/builder/amazon/common/step_security_group.go
@@ -6,7 +6,7 @@ import (
"time"
"github.com/aws/aws-sdk-go/aws"
- "github.com/aws/aws-sdk-go/private/waiter"
+ "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"
@@ -153,36 +153,42 @@ func (s *StepSecurityGroup) Cleanup(state multistep.StateBag) {
}
func waitUntilSecurityGroupExists(c *ec2.EC2, input *ec2.DescribeSecurityGroupsInput) error {
- waiterCfg := waiter.Config{
- Operation: "DescribeSecurityGroups",
- Delay: 15,
+ ctx := aws.BackgroundContext()
+ w := request.Waiter{
+ Name: "DescribeSecurityGroups",
MaxAttempts: 40,
- Acceptors: []waiter.WaitAcceptor{
+ Acceptors: []request.WaiterAcceptor{
{
- State: "success",
- Matcher: "path",
+ State: request.SuccessWaiterState,
+ Matcher: request.PathWaiterMatch,
Argument: "length(SecurityGroups[]) > `0`",
Expected: true,
},
{
- State: "retry",
- Matcher: "error",
+ State: request.RetryWaiterState,
+ Matcher: request.ErrorWaiterMatch,
Argument: "",
Expected: "InvalidGroup.NotFound",
},
{
- State: "retry",
- Matcher: "error",
+ State: request.RetryWaiterState,
+ Matcher: request.ErrorWaiterMatch,
Argument: "",
Expected: "InvalidSecurityGroupID.NotFound",
},
},
+ Logger: c.Config.Logger,
+ NewRequest: func(opts []request.Option) (*request.Request, error) {
+ var inCpy *ec2.DescribeSecurityGroupsInput
+ if input != nil {
+ tmp := *input
+ inCpy = &tmp
+ }
+ req, _ := c.DescribeSecurityGroupsRequest(inCpy)
+ req.SetContext(ctx)
+ req.ApplyOptions(opts...)
+ return req, nil
+ },
}
-
- w := waiter.Waiter{
- Client: c,
- Input: input,
- Config: waiterCfg,
- }
- return w.Wait()
+ return w.WaitWithContext(ctx)
}
diff --git a/vendor/github.com/mitchellh/packer/builder/amazon/common/step_source_ami_info.go b/vendor/github.com/mitchellh/packer/builder/amazon/common/step_source_ami_info.go
index 386e8e8d..c7e9f733 100644
--- a/vendor/github.com/mitchellh/packer/builder/amazon/common/step_source_ami_info.go
+++ b/vendor/github.com/mitchellh/packer/builder/amazon/common/step_source_ami_info.go
@@ -17,9 +17,10 @@ import (
// Produces:
// source_image *ec2.Image - the source AMI info
type StepSourceAMIInfo struct {
- SourceAmi string
- EnhancedNetworking bool
- AmiFilters AmiFilterOptions
+ SourceAmi string
+ EnableAMISriovNetSupport bool
+ EnableAMIENASupport bool
+ AmiFilters AmiFilterOptions
}
// Build a slice of AMI filter options from the filters provided.
@@ -103,7 +104,7 @@ func (s *StepSourceAMIInfo) Run(state multistep.StateBag) multistep.StepAction {
// Enhanced Networking can only be enabled on HVM AMIs.
// See http://goo.gl/icuXh5
- if s.EnhancedNetworking && *image.VirtualizationType != "hvm" {
+ if (s.EnableAMIENASupport || s.EnableAMISriovNetSupport) && *image.VirtualizationType != "hvm" {
err := fmt.Errorf("Cannot enable enhanced networking, source AMI '%s' is not HVM", s.SourceAmi)
state.Put("error", err)
ui.Error(err.Error())
diff --git a/vendor/github.com/mitchellh/packer/builder/amazon/ebs/builder.go b/vendor/github.com/mitchellh/packer/builder/amazon/ebs/builder.go
index 79ef6e68..c31da73a 100644
--- a/vendor/github.com/mitchellh/packer/builder/amazon/ebs/builder.go
+++ b/vendor/github.com/mitchellh/packer/builder/amazon/ebs/builder.go
@@ -115,9 +115,10 @@ func (b *Builder) Run(ui packer.Ui, hook packer.Hook, cache packer.Cache) (packe
ForceDeregister: b.config.AMIForceDeregister,
},
&awscommon.StepSourceAMIInfo{
- SourceAmi: b.config.SourceAmi,
- EnhancedNetworking: b.config.AMIEnhancedNetworking,
- AmiFilters: b.config.SourceAmiFilter,
+ SourceAmi: b.config.SourceAmi,
+ EnableAMISriovNetSupport: b.config.AMISriovNetSupport,
+ EnableAMIENASupport: b.config.AMIENASupport,
+ AmiFilters: b.config.SourceAmiFilter,
},
&awscommon.StepKeyPair{
Debug: b.config.PackerDebug,
@@ -179,18 +180,22 @@ func (b *Builder) Run(ui packer.Ui, hook packer.Hook, cache packer.Cache) (packe
DisableStopInstance: b.config.DisableStopInstance,
},
&awscommon.StepModifyEBSBackedInstance{
- EnableEnhancedNetworking: b.config.AMIEnhancedNetworking,
+ EnableAMISriovNetSupport: b.config.AMISriovNetSupport,
+ EnableAMIENASupport: b.config.AMIENASupport,
},
&awscommon.StepDeregisterAMI{
+ AccessConfig: &b.config.AccessConfig,
ForceDeregister: b.config.AMIForceDeregister,
ForceDeleteSnapshot: b.config.AMIForceDeleteSnapshot,
AMIName: b.config.AMIName,
+ Regions: b.config.AMIRegions,
},
&stepCreateAMI{},
&awscommon.StepCreateEncryptedAMICopy{
KeyID: b.config.AMIKmsKeyId,
EncryptBootVolume: b.config.AMIEncryptBootVolume,
Name: b.config.AMIName,
+ AMIMappings: b.config.AMIBlockDevices.AMIMappings,
},
&awscommon.StepAMIRegionCopy{
AccessConfig: &b.config.AccessConfig,
diff --git a/vendor/github.com/mitchellh/packer/builder/amazon/ebssurrogate/builder.go b/vendor/github.com/mitchellh/packer/builder/amazon/ebssurrogate/builder.go
index 5508abde..20984fee 100644
--- a/vendor/github.com/mitchellh/packer/builder/amazon/ebssurrogate/builder.go
+++ b/vendor/github.com/mitchellh/packer/builder/amazon/ebssurrogate/builder.go
@@ -129,9 +129,10 @@ func (b *Builder) Run(ui packer.Ui, hook packer.Hook, cache packer.Cache) (packe
ForceDeregister: b.config.AMIForceDeregister,
},
&awscommon.StepSourceAMIInfo{
- SourceAmi: b.config.SourceAmi,
- EnhancedNetworking: b.config.AMIEnhancedNetworking,
- AmiFilters: b.config.SourceAmiFilter,
+ SourceAmi: b.config.SourceAmi,
+ EnableAMISriovNetSupport: b.config.AMISriovNetSupport,
+ EnableAMIENASupport: b.config.AMIENASupport,
+ AmiFilters: b.config.SourceAmiFilter,
},
&awscommon.StepKeyPair{
Debug: b.config.PackerDebug,
@@ -189,19 +190,24 @@ func (b *Builder) Run(ui packer.Ui, hook packer.Hook, cache packer.Cache) (packe
DisableStopInstance: b.config.DisableStopInstance,
},
&awscommon.StepModifyEBSBackedInstance{
- EnableEnhancedNetworking: b.config.AMIEnhancedNetworking,
+ EnableAMISriovNetSupport: b.config.AMISriovNetSupport,
+ EnableAMIENASupport: b.config.AMIENASupport,
},
&StepSnapshotNewRootVolume{
NewRootMountPoint: b.config.RootDevice.SourceDeviceName,
},
&awscommon.StepDeregisterAMI{
+ AccessConfig: &b.config.AccessConfig,
ForceDeregister: b.config.AMIForceDeregister,
ForceDeleteSnapshot: b.config.AMIForceDeleteSnapshot,
AMIName: b.config.AMIName,
+ Regions: b.config.AMIRegions,
},
&StepRegisterAMI{
- RootDevice: b.config.RootDevice,
- BlockDevices: b.config.BlockDevices.BuildAMIDevices(),
+ RootDevice: b.config.RootDevice,
+ BlockDevices: b.config.BlockDevices.BuildAMIDevices(),
+ EnableAMISriovNetSupport: b.config.AMISriovNetSupport,
+ EnableAMIENASupport: b.config.AMIENASupport,
},
&awscommon.StepCreateEncryptedAMICopy{
KeyID: b.config.AMIKmsKeyId,
diff --git a/vendor/github.com/mitchellh/packer/builder/amazon/ebssurrogate/step_register_ami.go b/vendor/github.com/mitchellh/packer/builder/amazon/ebssurrogate/step_register_ami.go
index d2f0f225..f0d145f3 100644
--- a/vendor/github.com/mitchellh/packer/builder/amazon/ebssurrogate/step_register_ami.go
+++ b/vendor/github.com/mitchellh/packer/builder/amazon/ebssurrogate/step_register_ami.go
@@ -12,9 +12,11 @@ import (
// StepRegisterAMI creates the AMI.
type StepRegisterAMI struct {
- RootDevice RootBlockDevice
- BlockDevices []*ec2.BlockDeviceMapping
- image *ec2.Image
+ RootDevice RootBlockDevice
+ BlockDevices []*ec2.BlockDeviceMapping
+ EnableAMIENASupport bool
+ EnableAMISriovNetSupport bool
+ image *ec2.Image
}
func (s *StepRegisterAMI) Run(state multistep.StateBag) multistep.StepAction {
@@ -35,16 +37,16 @@ func (s *StepRegisterAMI) Run(state multistep.StateBag) multistep.StepAction {
BlockDeviceMappings: blockDevicesExcludingRoot,
}
- if config.AMIEnhancedNetworking {
+ if s.EnableAMISriovNetSupport {
// Set SriovNetSupport to "simple". See http://goo.gl/icuXh5
// As of February 2017, this applies to C3, C4, D2, I2, R3, and M4 (excluding m4.16xlarge)
registerOpts.SriovNetSupport = aws.String("simple")
-
+ }
+ if s.EnableAMIENASupport {
// Set EnaSupport to true
// As of February 2017, this applies to C5, I3, P2, R4, X1, and m4.16xlarge
registerOpts.EnaSupport = aws.Bool(true)
}
-
registerResp, err := ec2conn.RegisterImage(registerOpts)
if err != nil {
state.Put("error", fmt.Errorf("Error registering AMI: %s", err))
diff --git a/vendor/github.com/mitchellh/packer/builder/amazon/ebsvolume/builder.go b/vendor/github.com/mitchellh/packer/builder/amazon/ebsvolume/builder.go
index 098cb4c9..1aad1819 100644
--- a/vendor/github.com/mitchellh/packer/builder/amazon/ebsvolume/builder.go
+++ b/vendor/github.com/mitchellh/packer/builder/amazon/ebsvolume/builder.go
@@ -23,8 +23,9 @@ type Config struct {
awscommon.AccessConfig `mapstructure:",squash"`
awscommon.RunConfig `mapstructure:",squash"`
- VolumeMappings []BlockDevice `mapstructure:"ebs_volumes"`
- AMIEnhancedNetworking bool `mapstructure:"enhanced_networking"`
+ VolumeMappings []BlockDevice `mapstructure:"ebs_volumes"`
+ AMIENASupport bool `mapstructure:"ena_support"`
+ AMISriovNetSupport bool `mapstructure:"sriov_support"`
launchBlockDevices awscommon.BlockDevices
ctx interpolate.Context
@@ -103,9 +104,10 @@ func (b *Builder) Run(ui packer.Ui, hook packer.Hook, cache packer.Cache) (packe
// Build the steps
steps := []multistep.Step{
&awscommon.StepSourceAMIInfo{
- SourceAmi: b.config.SourceAmi,
- EnhancedNetworking: b.config.AMIEnhancedNetworking,
- AmiFilters: b.config.SourceAmiFilter,
+ SourceAmi: b.config.SourceAmi,
+ EnableAMISriovNetSupport: b.config.AMISriovNetSupport,
+ EnableAMIENASupport: b.config.AMIENASupport,
+ AmiFilters: b.config.SourceAmiFilter,
},
&awscommon.StepKeyPair{
Debug: b.config.PackerDebug,
@@ -164,7 +166,8 @@ func (b *Builder) Run(ui packer.Ui, hook packer.Hook, cache packer.Cache) (packe
DisableStopInstance: b.config.DisableStopInstance,
},
&awscommon.StepModifyEBSBackedInstance{
- EnableEnhancedNetworking: b.config.AMIEnhancedNetworking,
+ EnableAMISriovNetSupport: b.config.AMISriovNetSupport,
+ EnableAMIENASupport: b.config.AMIENASupport,
},
}
diff --git a/vendor/github.com/mitchellh/packer/builder/amazon/instance/builder.go b/vendor/github.com/mitchellh/packer/builder/amazon/instance/builder.go
index d45dc64d..6329008f 100644
--- a/vendor/github.com/mitchellh/packer/builder/amazon/instance/builder.go
+++ b/vendor/github.com/mitchellh/packer/builder/amazon/instance/builder.go
@@ -200,9 +200,10 @@ func (b *Builder) Run(ui packer.Ui, hook packer.Hook, cache packer.Cache) (packe
ForceDeregister: b.config.AMIForceDeregister,
},
&awscommon.StepSourceAMIInfo{
- SourceAmi: b.config.SourceAmi,
- EnhancedNetworking: b.config.AMIEnhancedNetworking,
- AmiFilters: b.config.SourceAmiFilter,
+ SourceAmi: b.config.SourceAmi,
+ EnableAMISriovNetSupport: b.config.AMISriovNetSupport,
+ EnableAMIENASupport: b.config.AMIENASupport,
+ AmiFilters: b.config.SourceAmiFilter,
},
&awscommon.StepKeyPair{
Debug: b.config.PackerDebug,
@@ -258,11 +259,16 @@ func (b *Builder) Run(ui packer.Ui, hook packer.Hook, cache packer.Cache) (packe
Debug: b.config.PackerDebug,
},
&awscommon.StepDeregisterAMI{
+ AccessConfig: &b.config.AccessConfig,
ForceDeregister: b.config.AMIForceDeregister,
ForceDeleteSnapshot: b.config.AMIForceDeleteSnapshot,
AMIName: b.config.AMIName,
+ Regions: b.config.AMIRegions,
+ },
+ &StepRegisterAMI{
+ EnableAMISriovNetSupport: b.config.AMISriovNetSupport,
+ EnableAMIENASupport: b.config.AMIENASupport,
},
- &StepRegisterAMI{},
&awscommon.StepAMIRegionCopy{
AccessConfig: &b.config.AccessConfig,
Regions: b.config.AMIRegions,
diff --git a/vendor/github.com/mitchellh/packer/builder/amazon/instance/step_register_ami.go b/vendor/github.com/mitchellh/packer/builder/amazon/instance/step_register_ami.go
index 01ba46bd..d363bdfd 100644
--- a/vendor/github.com/mitchellh/packer/builder/amazon/instance/step_register_ami.go
+++ b/vendor/github.com/mitchellh/packer/builder/amazon/instance/step_register_ami.go
@@ -10,7 +10,10 @@ import (
"github.com/mitchellh/multistep"
)
-type StepRegisterAMI struct{}
+type StepRegisterAMI struct {
+ EnableAMIENASupport bool
+ EnableAMISriovNetSupport bool
+}
func (s *StepRegisterAMI) Run(state multistep.StateBag) multistep.StepAction {
config := state.Get("config").(*Config)
@@ -29,12 +32,13 @@ func (s *StepRegisterAMI) Run(state multistep.StateBag) multistep.StepAction {
registerOpts.VirtualizationType = aws.String(config.AMIVirtType)
}
- if config.AMIEnhancedNetworking {
+ if s.EnableAMISriovNetSupport {
// Set SriovNetSupport to "simple". See http://goo.gl/icuXh5
// As of February 2017, this applies to C3, C4, D2, I2, R3, and M4 (excluding m4.16xlarge)
registerOpts.SriovNetSupport = aws.String("simple")
-
- // Set EnaSupport to true.
+ }
+ if s.EnableAMIENASupport {
+ // Set EnaSupport to true
// As of February 2017, this applies to C5, I3, P2, R4, X1, and m4.16xlarge
registerOpts.EnaSupport = aws.Bool(true)
}
diff --git a/vendor/github.com/mitchellh/packer/builder/azure/arm/artifact.go b/vendor/github.com/mitchellh/packer/builder/azure/arm/artifact.go
index eade5017..e8a72091 100644
--- a/vendor/github.com/mitchellh/packer/builder/azure/arm/artifact.go
+++ b/vendor/github.com/mitchellh/packer/builder/azure/arm/artifact.go
@@ -1,6 +1,3 @@
-// Copyright (c) Microsoft Corporation. All rights reserved.
-// Licensed under the MIT License. See the LICENSE file in builder/azure for license information.
-
package arm
import (
diff --git a/vendor/github.com/mitchellh/packer/builder/azure/arm/artifact_test.go b/vendor/github.com/mitchellh/packer/builder/azure/arm/artifact_test.go
index 7202b652..1b9a472a 100644
--- a/vendor/github.com/mitchellh/packer/builder/azure/arm/artifact_test.go
+++ b/vendor/github.com/mitchellh/packer/builder/azure/arm/artifact_test.go
@@ -1,6 +1,3 @@
-// Copyright (c) Microsoft Corporation. All rights reserved.
-// Licensed under the MIT License. See the LICENSE file in builder/azure for license information.
-
package arm
import (
diff --git a/vendor/github.com/mitchellh/packer/builder/azure/arm/authenticate.go b/vendor/github.com/mitchellh/packer/builder/azure/arm/authenticate.go
index d89a1254..7f0b5bdc 100644
--- a/vendor/github.com/mitchellh/packer/builder/azure/arm/authenticate.go
+++ b/vendor/github.com/mitchellh/packer/builder/azure/arm/authenticate.go
@@ -1,6 +1,3 @@
-// Copyright (c) Microsoft Corporation. All rights reserved.
-// Licensed under the MIT License. See the LICENSE file in builder/azure for license information.
-
package arm
import (
diff --git a/vendor/github.com/mitchellh/packer/builder/azure/arm/azure_client.go b/vendor/github.com/mitchellh/packer/builder/azure/arm/azure_client.go
index 10c8d4bb..3fd58bc3 100644
--- a/vendor/github.com/mitchellh/packer/builder/azure/arm/azure_client.go
+++ b/vendor/github.com/mitchellh/packer/builder/azure/arm/azure_client.go
@@ -1,6 +1,3 @@
-// Copyright (c) Microsoft Corporation. All rights reserved.
-// Licensed under the MIT License. See the LICENSE file in builder/azure for license information.
-
package arm
import (
diff --git a/vendor/github.com/mitchellh/packer/builder/azure/arm/builder.go b/vendor/github.com/mitchellh/packer/builder/azure/arm/builder.go
index 5377b7bb..e6993cfb 100644
--- a/vendor/github.com/mitchellh/packer/builder/azure/arm/builder.go
+++ b/vendor/github.com/mitchellh/packer/builder/azure/arm/builder.go
@@ -1,6 +1,3 @@
-// Copyright (c) Microsoft Corporation. All rights reserved.
-// Licensed under the MIT License. See the LICENSE file in builder/azure for license information.
-
package arm
import (
@@ -119,7 +116,9 @@ func (b *Builder) Run(ui packer.Ui, hook packer.Hook, cache packer.Cache) (packe
}
endpointConnectType := PublicEndpoint
- if b.isPrivateNetworkCommunication() {
+ if b.isPublicPrivateNetworkCommunication() && b.isPrivateNetworkCommunication() {
+ endpointConnectType = PublicEndpointInPrivateNetwork
+ } else if b.isPrivateNetworkCommunication() {
endpointConnectType = PrivateEndpoint
}
@@ -245,6 +244,10 @@ func (b *Builder) writeSSHPrivateKey(ui packer.Ui, debugKeyPath string) {
}
}
+func (b *Builder) isPublicPrivateNetworkCommunication() bool {
+ return DefaultPrivateVirtualNetworkWithPublicIp != b.config.PrivateVirtualNetworkWithPublicIp
+}
+
func (b *Builder) isPrivateNetworkCommunication() bool {
return b.config.VirtualNetworkName != ""
}
diff --git a/vendor/github.com/mitchellh/packer/builder/azure/arm/builder_test.go b/vendor/github.com/mitchellh/packer/builder/azure/arm/builder_test.go
index 47f7a74b..a44d363d 100644
--- a/vendor/github.com/mitchellh/packer/builder/azure/arm/builder_test.go
+++ b/vendor/github.com/mitchellh/packer/builder/azure/arm/builder_test.go
@@ -1,6 +1,3 @@
-// Copyright (c) Microsoft Corporation. All rights reserved.
-// Licensed under the MIT License. See the LICENSE file in builder/azure for license information.
-
package arm
import (
diff --git a/vendor/github.com/mitchellh/packer/builder/azure/arm/capture_template.go b/vendor/github.com/mitchellh/packer/builder/azure/arm/capture_template.go
index 23e70199..0332a02f 100644
--- a/vendor/github.com/mitchellh/packer/builder/azure/arm/capture_template.go
+++ b/vendor/github.com/mitchellh/packer/builder/azure/arm/capture_template.go
@@ -1,6 +1,3 @@
-// Copyright (c) Microsoft Corporation. All rights reserved.
-// Licensed under the MIT License. See the LICENSE file in builder/azure for license information.
-
package arm
type CaptureTemplateParameter struct {
diff --git a/vendor/github.com/mitchellh/packer/builder/azure/arm/capture_template_test.go b/vendor/github.com/mitchellh/packer/builder/azure/arm/capture_template_test.go
index 6d2e53b1..8c7a7140 100644
--- a/vendor/github.com/mitchellh/packer/builder/azure/arm/capture_template_test.go
+++ b/vendor/github.com/mitchellh/packer/builder/azure/arm/capture_template_test.go
@@ -1,6 +1,3 @@
-// Copyright (c) Microsoft Corporation. All rights reserved.
-// Licensed under the MIT License. See the LICENSE file in builder/azure for license information.
-
package arm
import (
diff --git a/vendor/github.com/mitchellh/packer/builder/azure/arm/config.go b/vendor/github.com/mitchellh/packer/builder/azure/arm/config.go
index 1d0c98d1..3fc4f13b 100644
--- a/vendor/github.com/mitchellh/packer/builder/azure/arm/config.go
+++ b/vendor/github.com/mitchellh/packer/builder/azure/arm/config.go
@@ -1,6 +1,3 @@
-// Copyright (c) Microsoft Corporation. All rights reserved.
-// Licensed under the MIT License. See the LICENSE file in builder/azure for license information.
-
package arm
import (
@@ -34,10 +31,11 @@ import (
)
const (
- DefaultCloudEnvironmentName = "Public"
- DefaultImageVersion = "latest"
- DefaultUserName = "packer"
- DefaultVMSize = "Standard_A1"
+ DefaultCloudEnvironmentName = "Public"
+ DefaultImageVersion = "latest"
+ DefaultUserName = "packer"
+ DefaultPrivateVirtualNetworkWithPublicIp = false
+ DefaultVMSize = "Standard_A1"
)
var (
@@ -73,24 +71,27 @@ type Config struct {
Location string `mapstructure:"location"`
VMSize string `mapstructure:"vm_size"`
- ManagedImageResourceGroupName string `mapstructure:"managed_image_resource_group_name"`
- ManagedImageName string `mapstructure:"managed_image_name"`
- manageImageLocation string
+ ManagedImageResourceGroupName string `mapstructure:"managed_image_resource_group_name"`
+ ManagedImageName string `mapstructure:"managed_image_name"`
+ ManagedImageStorageAccountType string `mapstructure:"managed_image_storage_account_type"`
+ managedImageStorageAccountType compute.StorageAccountTypes
+ manageImageLocation string
// Deployment
- AzureTags map[string]*string `mapstructure:"azure_tags"`
- ResourceGroupName string `mapstructure:"resource_group_name"`
- StorageAccount string `mapstructure:"storage_account"`
- TempComputeName string `mapstructure:"temp_compute_name"`
- TempResourceGroupName string `mapstructure:"temp_resource_group_name"`
- storageAccountBlobEndpoint string
- CloudEnvironmentName string `mapstructure:"cloud_environment_name"`
- cloudEnvironment *azure.Environment
- VirtualNetworkName string `mapstructure:"virtual_network_name"`
- VirtualNetworkSubnetName string `mapstructure:"virtual_network_subnet_name"`
- VirtualNetworkResourceGroupName string `mapstructure:"virtual_network_resource_group_name"`
- CustomDataFile string `mapstructure:"custom_data_file"`
- customData string
+ AzureTags map[string]*string `mapstructure:"azure_tags"`
+ ResourceGroupName string `mapstructure:"resource_group_name"`
+ StorageAccount string `mapstructure:"storage_account"`
+ TempComputeName string `mapstructure:"temp_compute_name"`
+ TempResourceGroupName string `mapstructure:"temp_resource_group_name"`
+ storageAccountBlobEndpoint string
+ CloudEnvironmentName string `mapstructure:"cloud_environment_name"`
+ cloudEnvironment *azure.Environment
+ PrivateVirtualNetworkWithPublicIp bool `mapstructure:"private_virtual_network_with_public_ip"`
+ VirtualNetworkName string `mapstructure:"virtual_network_name"`
+ VirtualNetworkSubnetName string `mapstructure:"virtual_network_subnet_name"`
+ VirtualNetworkResourceGroupName string `mapstructure:"virtual_network_resource_group_name"`
+ CustomDataFile string `mapstructure:"custom_data_file"`
+ customData string
// OS
OSType string `mapstructure:"os_type"`
@@ -403,6 +404,10 @@ func provideDefaultValues(c *Config) {
c.VMSize = DefaultVMSize
}
+ if c.ManagedImageStorageAccountType == "" {
+ c.managedImageStorageAccountType = compute.StandardLRS
+ }
+
if c.ImagePublisher != "" && c.ImageVersion == "" {
c.ImageVersion = DefaultImageVersion
}
@@ -526,6 +531,10 @@ func assertRequiredParametersSet(c *Config, errs *packer.MultiError) {
errs = packer.MultiErrorAppend(errs, fmt.Errorf("Specify either a VHD (image_url), Image Reference (image_publisher, image_offer, image_sku) or a Managed Disk (custom_managed_disk_image_name, custom_managed_disk_resource_group_name"))
}
+ if isImageUrl && c.ManagedImageResourceGroupName != "" {
+ errs = packer.MultiErrorAppend(errs, fmt.Errorf("A managed image must be created from a managed image, it cannot be created from a VHD."))
+ }
+
if c.ImageUrl == "" && c.CustomManagedImageName == "" {
if c.ImagePublisher == "" {
errs = packer.MultiErrorAppend(errs, fmt.Errorf("An image_publisher must be specified"))
@@ -596,4 +605,13 @@ func assertRequiredParametersSet(c *Config, errs *packer.MultiError) {
} else {
errs = packer.MultiErrorAppend(errs, fmt.Errorf("The os_type %q is invalid", c.OSType))
}
+
+ switch c.ManagedImageStorageAccountType {
+ case "", string(compute.StandardLRS):
+ c.managedImageStorageAccountType = compute.StandardLRS
+ case string(compute.PremiumLRS):
+ c.managedImageStorageAccountType = compute.PremiumLRS
+ default:
+ errs = packer.MultiErrorAppend(errs, fmt.Errorf("The managed_image_storage_account_type %q is invalid", c.ManagedImageStorageAccountType))
+ }
}
diff --git a/vendor/github.com/mitchellh/packer/builder/azure/arm/config_test.go b/vendor/github.com/mitchellh/packer/builder/azure/arm/config_test.go
index 83545471..b7523f65 100644
--- a/vendor/github.com/mitchellh/packer/builder/azure/arm/config_test.go
+++ b/vendor/github.com/mitchellh/packer/builder/azure/arm/config_test.go
@@ -1,6 +1,3 @@
-// Copyright (c) Microsoft Corporation. All rights reserved.
-// Licensed under the MIT License. See the LICENSE file in builder/azure for license information.
-
package arm
import (
@@ -9,6 +6,7 @@ import (
"testing"
"time"
+ "github.com/Azure/azure-sdk-for-go/arm/compute"
"github.com/hashicorp/packer/builder/azure/common/constants"
"github.com/hashicorp/packer/packer"
)
@@ -48,6 +46,10 @@ func TestConfigShouldProvideReasonableDefaultValues(t *testing.T) {
if c.ObjectID != "" {
t.Errorf("Expected 'ObjectID' to be nil, but it was '%s'!", c.ObjectID)
}
+
+ if c.managedImageStorageAccountType == "" {
+ t.Errorf("Expected 'managedImageStorageAccountType' to be populated, but it was empty!")
+ }
}
func TestConfigShouldBeAbleToOverrideDefaultedValues(t *testing.T) {
@@ -56,6 +58,7 @@ func TestConfigShouldBeAbleToOverrideDefaultedValues(t *testing.T) {
builderValues["ssh_username"] = "override_username"
builderValues["vm_size"] = "override_vm_size"
builderValues["communicator"] = "ssh"
+ builderValues["managed_image_storage_account_type"] = "Premium_LRS"
c, _, err := newConfig(builderValues, getPackerConfiguration())
@@ -64,23 +67,27 @@ func TestConfigShouldBeAbleToOverrideDefaultedValues(t *testing.T) {
}
if c.Password != "override_password" {
- t.Errorf("Expected 'Password' to be set to 'override_password', but found '%s'!", c.Password)
+ t.Errorf("Expected 'Password' to be set to 'override_password', but found %q!", c.Password)
}
if c.Comm.SSHPassword != "override_password" {
- t.Errorf("Expected 'c.Comm.SSHPassword' to be set to 'override_password', but found '%s'!", c.Comm.SSHPassword)
+ t.Errorf("Expected 'c.Comm.SSHPassword' to be set to 'override_password', but found %q!", c.Comm.SSHPassword)
}
if c.UserName != "override_username" {
- t.Errorf("Expected 'UserName' to be set to 'override_username', but found '%s'!", c.UserName)
+ t.Errorf("Expected 'UserName' to be set to 'override_username', but found %q!", c.UserName)
}
if c.Comm.SSHUsername != "override_username" {
- t.Errorf("Expected 'c.Comm.SSHUsername' to be set to 'override_username', but found '%s'!", c.Comm.SSHUsername)
+ t.Errorf("Expected 'c.Comm.SSHUsername' to be set to 'override_username', but found %q!", c.Comm.SSHUsername)
}
if c.VMSize != "override_vm_size" {
- t.Errorf("Expected 'vm_size' to be set to 'override_vm_size', but found '%s'!", c.VMSize)
+ t.Errorf("Expected 'vm_size' to be set to 'override_vm_size', but found %q!", c.VMSize)
+ }
+
+ if c.managedImageStorageAccountType != compute.PremiumLRS {
+ t.Errorf("Expected 'managed_image_storage_account_type' to be set to 'Premium_LRS', but found %q!", c.managedImageStorageAccountType)
}
}
@@ -782,6 +789,26 @@ func TestConfigShouldRejectVhdAndManagedImageOutput(t *testing.T) {
}
}
+// If the user specified a build of a VHD, but started with a managed image it should be rejected.
+func TestConfigShouldRejectManagedImageSourceAndVhdOutput(t *testing.T) {
+ config := map[string]interface{}{
+ "image_url": "ignore",
+ "location": "ignore",
+ "subscription_id": "ignore",
+ "communicator": "none",
+ "managed_image_resource_group_name": "ignore",
+ "managed_image_name": "ignore",
+
+ // Does not matter for this test case, just pick one.
+ "os_type": constants.Target_Linux,
+ }
+
+ _, _, err := newConfig(config, getPackerConfiguration())
+ if err == nil {
+ t.Fatal("expected config to reject VHD and Managed Image build")
+ }
+}
+
func TestConfigShouldRejectCustomAndPlatformManagedImageBuild(t *testing.T) {
config := map[string]interface{}{
"custom_managed_image_resource_group_name": "ignore",
@@ -826,6 +853,52 @@ func TestConfigShouldRejectCustomAndImageUrlForManagedImageBuild(t *testing.T) {
}
}
+func TestConfigShouldRejectMalformedManageImageStorageAccountTypes(t *testing.T) {
+ config := map[string]interface{}{
+ "custom_managed_image_resource_group_name": "ignore",
+ "custom_managed_image_name": "ignore",
+ "location": "ignore",
+ "subscription_id": "ignore",
+ "communicator": "none",
+ "managed_image_resource_group_name": "ignore",
+ "managed_image_name": "ignore",
+ "managed_image_storage_account_type": "--invalid--",
+
+ // Does not matter for this test case, just pick one.
+ "os_type": constants.Target_Linux,
+ }
+
+ _, _, err := newConfig(config, getPackerConfiguration())
+ if err == nil {
+ t.Fatal("expected config to reject custom and platform input for a managed image build")
+ }
+}
+
+func TestConfigShouldAcceptManagedImageStorageAccountTypes(t *testing.T) {
+ config := map[string]interface{}{
+ "custom_managed_image_resource_group_name": "ignore",
+ "custom_managed_image_name": "ignore",
+ "location": "ignore",
+ "subscription_id": "ignore",
+ "communicator": "none",
+ "managed_image_resource_group_name": "ignore",
+ "managed_image_name": "ignore",
+
+ // Does not matter for this test case, just pick one.
+ "os_type": constants.Target_Linux,
+ }
+
+ storage_account_types := []string{"Premium_LRS", "Standard_LRS"}
+
+ for _, x := range storage_account_types {
+ config["managed_image_storage_account_type"] = x
+ _, _, err := newConfig(config, getPackerConfiguration())
+ if err != nil {
+ t.Fatalf("expected config to accept a managed_image_storage_account_type of %q", x)
+ }
+ }
+}
+
func getArmBuilderConfiguration() map[string]string {
m := make(map[string]string)
for _, v := range requiredConfigValues {
diff --git a/vendor/github.com/mitchellh/packer/builder/azure/arm/openssh_key_pair.go b/vendor/github.com/mitchellh/packer/builder/azure/arm/openssh_key_pair.go
index 4f8c8d22..e3b296f3 100644
--- a/vendor/github.com/mitchellh/packer/builder/azure/arm/openssh_key_pair.go
+++ b/vendor/github.com/mitchellh/packer/builder/azure/arm/openssh_key_pair.go
@@ -1,6 +1,3 @@
-// Copyright (c) Microsoft Corporation. All rights reserved.
-// Licensed under the MIT License. See the LICENSE file in builder/azure for license information.
-
package arm
import (
diff --git a/vendor/github.com/mitchellh/packer/builder/azure/arm/openssh_key_pair_test.go b/vendor/github.com/mitchellh/packer/builder/azure/arm/openssh_key_pair_test.go
index 7e2f6957..fae03105 100644
--- a/vendor/github.com/mitchellh/packer/builder/azure/arm/openssh_key_pair_test.go
+++ b/vendor/github.com/mitchellh/packer/builder/azure/arm/openssh_key_pair_test.go
@@ -1,6 +1,3 @@
-// Copyright (c) Microsoft Corporation. All rights reserved.
-// Licensed under the MIT License. See the LICENSE file in builder/azure for license information.
-
package arm
import (
diff --git a/vendor/github.com/mitchellh/packer/builder/azure/arm/step.go b/vendor/github.com/mitchellh/packer/builder/azure/arm/step.go
index 574527f8..707a1a07 100644
--- a/vendor/github.com/mitchellh/packer/builder/azure/arm/step.go
+++ b/vendor/github.com/mitchellh/packer/builder/azure/arm/step.go
@@ -1,6 +1,3 @@
-// Copyright (c) Microsoft Corporation. All rights reserved.
-// Licensed under the MIT License. See the LICENSE file in builder/azure for license information.
-
package arm
import (
diff --git a/vendor/github.com/mitchellh/packer/builder/azure/arm/step_capture_image.go b/vendor/github.com/mitchellh/packer/builder/azure/arm/step_capture_image.go
index eac4b5c6..10d29069 100644
--- a/vendor/github.com/mitchellh/packer/builder/azure/arm/step_capture_image.go
+++ b/vendor/github.com/mitchellh/packer/builder/azure/arm/step_capture_image.go
@@ -1,6 +1,3 @@
-// Copyright (c) Microsoft Corporation. All rights reserved.
-// Licensed under the MIT License. See the LICENSE file in builder/azure for license information.
-
package arm
import (
diff --git a/vendor/github.com/mitchellh/packer/builder/azure/arm/step_capture_image_test.go b/vendor/github.com/mitchellh/packer/builder/azure/arm/step_capture_image_test.go
index 24bba776..4527627a 100644
--- a/vendor/github.com/mitchellh/packer/builder/azure/arm/step_capture_image_test.go
+++ b/vendor/github.com/mitchellh/packer/builder/azure/arm/step_capture_image_test.go
@@ -1,6 +1,3 @@
-// Copyright (c) Microsoft Corporation. All rights reserved.
-// Licensed under the MIT License. See the LICENSE file in builder/azure for license information.
-
package arm
import (
diff --git a/vendor/github.com/mitchellh/packer/builder/azure/arm/step_create_resource_group.go b/vendor/github.com/mitchellh/packer/builder/azure/arm/step_create_resource_group.go
index b8e24149..079ad527 100644
--- a/vendor/github.com/mitchellh/packer/builder/azure/arm/step_create_resource_group.go
+++ b/vendor/github.com/mitchellh/packer/builder/azure/arm/step_create_resource_group.go
@@ -1,6 +1,3 @@
-// Copyright (c) Microsoft Corporation. All rights reserved.
-// Licensed under the MIT License. See the LICENSE file in builder/azure for license information.
-
package arm
import (
diff --git a/vendor/github.com/mitchellh/packer/builder/azure/arm/step_create_resource_group_test.go b/vendor/github.com/mitchellh/packer/builder/azure/arm/step_create_resource_group_test.go
index ca0c8f18..4e6b7592 100644
--- a/vendor/github.com/mitchellh/packer/builder/azure/arm/step_create_resource_group_test.go
+++ b/vendor/github.com/mitchellh/packer/builder/azure/arm/step_create_resource_group_test.go
@@ -1,6 +1,3 @@
-// Copyright (c) Microsoft Corporation. All rights reserved.
-// Licensed under the MIT License. See the LICENSE file in builder/azure for license information.
-
package arm
import (
diff --git a/vendor/github.com/mitchellh/packer/builder/azure/arm/step_delete_os_disk.go b/vendor/github.com/mitchellh/packer/builder/azure/arm/step_delete_os_disk.go
index 0041a8ec..1dd28ec8 100644
--- a/vendor/github.com/mitchellh/packer/builder/azure/arm/step_delete_os_disk.go
+++ b/vendor/github.com/mitchellh/packer/builder/azure/arm/step_delete_os_disk.go
@@ -1,6 +1,3 @@
-// Copyright (c) Microsoft Corporation. All rights reserved.
-// Licensed under the MIT License. See the LICENSE file in builder/azure for license information.
-
package arm
import (
diff --git a/vendor/github.com/mitchellh/packer/builder/azure/arm/step_delete_os_disk_test.go b/vendor/github.com/mitchellh/packer/builder/azure/arm/step_delete_os_disk_test.go
index 6e2e2d9a..2724ee61 100644
--- a/vendor/github.com/mitchellh/packer/builder/azure/arm/step_delete_os_disk_test.go
+++ b/vendor/github.com/mitchellh/packer/builder/azure/arm/step_delete_os_disk_test.go
@@ -1,6 +1,3 @@
-// Copyright (c) Microsoft Corporation. All rights reserved.
-// Licensed under the MIT License. See the LICENSE file in builder/azure for license information.
-
package arm
import (
diff --git a/vendor/github.com/mitchellh/packer/builder/azure/arm/step_delete_resource_group.go b/vendor/github.com/mitchellh/packer/builder/azure/arm/step_delete_resource_group.go
index 5a168328..2606b9fc 100644
--- a/vendor/github.com/mitchellh/packer/builder/azure/arm/step_delete_resource_group.go
+++ b/vendor/github.com/mitchellh/packer/builder/azure/arm/step_delete_resource_group.go
@@ -1,6 +1,3 @@
-// Copyright (c) Microsoft Corporation. All rights reserved.
-// Licensed under the MIT License. See the LICENSE file in builder/azure for license information.
-
package arm
import (
diff --git a/vendor/github.com/mitchellh/packer/builder/azure/arm/step_delete_resource_group_test.go b/vendor/github.com/mitchellh/packer/builder/azure/arm/step_delete_resource_group_test.go
index fb2882a4..25ab14e4 100644
--- a/vendor/github.com/mitchellh/packer/builder/azure/arm/step_delete_resource_group_test.go
+++ b/vendor/github.com/mitchellh/packer/builder/azure/arm/step_delete_resource_group_test.go
@@ -1,6 +1,3 @@
-// Copyright (c) Microsoft Corporation. All rights reserved.
-// Licensed under the MIT License. See the LICENSE file in builder/azure for license information.
-
package arm
import (
diff --git a/vendor/github.com/mitchellh/packer/builder/azure/arm/step_deploy_template.go b/vendor/github.com/mitchellh/packer/builder/azure/arm/step_deploy_template.go
index 96248684..8d73402b 100644
--- a/vendor/github.com/mitchellh/packer/builder/azure/arm/step_deploy_template.go
+++ b/vendor/github.com/mitchellh/packer/builder/azure/arm/step_deploy_template.go
@@ -1,6 +1,3 @@
-// Copyright (c) Microsoft Corporation. All rights reserved.
-// Licensed under the MIT License. See the LICENSE file in builder/azure for license information.
-
package arm
import (
diff --git a/vendor/github.com/mitchellh/packer/builder/azure/arm/step_deploy_template_test.go b/vendor/github.com/mitchellh/packer/builder/azure/arm/step_deploy_template_test.go
index 57bfce7d..3a1d0c0b 100644
--- a/vendor/github.com/mitchellh/packer/builder/azure/arm/step_deploy_template_test.go
+++ b/vendor/github.com/mitchellh/packer/builder/azure/arm/step_deploy_template_test.go
@@ -1,6 +1,3 @@
-// Copyright (c) Microsoft Corporation. All rights reserved.
-// Licensed under the MIT License. See the LICENSE file in builder/azure for license information.
-
package arm
import (
diff --git a/vendor/github.com/mitchellh/packer/builder/azure/arm/step_get_certificate.go b/vendor/github.com/mitchellh/packer/builder/azure/arm/step_get_certificate.go
index ffc27b14..b9126da3 100644
--- a/vendor/github.com/mitchellh/packer/builder/azure/arm/step_get_certificate.go
+++ b/vendor/github.com/mitchellh/packer/builder/azure/arm/step_get_certificate.go
@@ -1,6 +1,3 @@
-// Copyright (c) Microsoft Corporation. All rights reserved.
-// Licensed under the MIT License. See the LICENSE file in builder/azure for license information.
-
package arm
import (
diff --git a/vendor/github.com/mitchellh/packer/builder/azure/arm/step_get_certificate_test.go b/vendor/github.com/mitchellh/packer/builder/azure/arm/step_get_certificate_test.go
index 46c921a3..553806c5 100644
--- a/vendor/github.com/mitchellh/packer/builder/azure/arm/step_get_certificate_test.go
+++ b/vendor/github.com/mitchellh/packer/builder/azure/arm/step_get_certificate_test.go
@@ -1,6 +1,3 @@
-// Copyright (c) Microsoft Corporation. All rights reserved.
-// Licensed under the MIT License. See the LICENSE file in builder/azure for license information.
-
package arm
import (
diff --git a/vendor/github.com/mitchellh/packer/builder/azure/arm/step_get_ip_address.go b/vendor/github.com/mitchellh/packer/builder/azure/arm/step_get_ip_address.go
index fed78afb..2c8165b0 100644
--- a/vendor/github.com/mitchellh/packer/builder/azure/arm/step_get_ip_address.go
+++ b/vendor/github.com/mitchellh/packer/builder/azure/arm/step_get_ip_address.go
@@ -1,6 +1,3 @@
-// Copyright (c) Microsoft Corporation. All rights reserved.
-// Licensed under the MIT License. See the LICENSE file in builder/azure for license information.
-
package arm
import (
@@ -16,12 +13,14 @@ type EndpointType int
const (
PublicEndpoint EndpointType = iota
PrivateEndpoint
+ PublicEndpointInPrivateNetwork
)
var (
EndpointCommunicationText = map[EndpointType]string{
- PublicEndpoint: "PublicEndpoint",
- PrivateEndpoint: "PrivateEndpoint",
+ PublicEndpoint: "PublicEndpoint",
+ PrivateEndpoint: "PrivateEndpoint",
+ PublicEndpointInPrivateNetwork: "PublicEndpointInPrivateNetwork",
}
)
@@ -46,6 +45,8 @@ func NewStepGetIPAddress(client *AzureClient, ui packer.Ui, endpoint EndpointTyp
step.get = step.getPrivateIP
case PublicEndpoint:
step.get = step.getPublicIP
+ case PublicEndpointInPrivateNetwork:
+ step.get = step.getPublicIPInPrivateNetwork
}
return step
@@ -70,6 +71,11 @@ func (s *StepGetIPAddress) getPublicIP(resourceGroupName string, ipAddressName s
return *resp.IPAddress, nil
}
+func (s *StepGetIPAddress) getPublicIPInPrivateNetwork(resourceGroupName string, ipAddressName string, interfaceName string) (string, error) {
+ s.getPrivateIP(resourceGroupName, ipAddressName, interfaceName)
+ return s.getPublicIP(resourceGroupName, ipAddressName, interfaceName)
+}
+
func (s *StepGetIPAddress) Run(state multistep.StateBag) multistep.StepAction {
s.say("Getting the VM's IP address ...")
diff --git a/vendor/github.com/mitchellh/packer/builder/azure/arm/step_get_ip_address_test.go b/vendor/github.com/mitchellh/packer/builder/azure/arm/step_get_ip_address_test.go
index a0b854ed..1403e9a5 100644
--- a/vendor/github.com/mitchellh/packer/builder/azure/arm/step_get_ip_address_test.go
+++ b/vendor/github.com/mitchellh/packer/builder/azure/arm/step_get_ip_address_test.go
@@ -1,6 +1,3 @@
-// Copyright (c) Microsoft Corporation. All rights reserved.
-// Licensed under the MIT License. See the LICENSE file in builder/azure for license information.
-
package arm
import (
@@ -12,42 +9,50 @@ import (
)
func TestStepGetIPAddressShouldFailIfGetFails(t *testing.T) {
- var testSubject = &StepGetIPAddress{
- get: func(string, string, string) (string, error) { return "", fmt.Errorf("!! Unit Test FAIL !!") },
- endpoint: PublicEndpoint,
- say: func(message string) {},
- error: func(e error) {},
- }
-
- stateBag := createTestStateBagStepGetIPAddress()
-
- var result = testSubject.Run(stateBag)
- if result != multistep.ActionHalt {
- t.Fatalf("Expected the step to return 'ActionHalt', but got '%d'.", result)
- }
-
- if _, ok := stateBag.GetOk(constants.Error); ok == false {
- t.Fatalf("Expected the step to set stateBag['%s'], but it was not.", constants.Error)
+ endpoints := []EndpointType{PublicEndpoint, PublicEndpointInPrivateNetwork}
+
+ for _, endpoint := range endpoints {
+ var testSubject = &StepGetIPAddress{
+ get: func(string, string, string) (string, error) { return "", fmt.Errorf("!! Unit Test FAIL !!") },
+ endpoint: endpoint,
+ say: func(message string) {},
+ error: func(e error) {},
+ }
+
+ stateBag := createTestStateBagStepGetIPAddress()
+
+ var result = testSubject.Run(stateBag)
+ if result != multistep.ActionHalt {
+ t.Fatalf("Expected the step to return 'ActionHalt', but got '%d'.", result)
+ }
+
+ if _, ok := stateBag.GetOk(constants.Error); ok == false {
+ t.Fatalf("Expected the step to set stateBag['%s'], but it was not.", constants.Error)
+ }
}
}
func TestStepGetIPAddressShouldPassIfGetPasses(t *testing.T) {
- var testSubject = &StepGetIPAddress{
- get: func(string, string, string) (string, error) { return "", nil },
- endpoint: PublicEndpoint,
- say: func(message string) {},
- error: func(e error) {},
- }
-
- stateBag := createTestStateBagStepGetIPAddress()
-
- var result = testSubject.Run(stateBag)
- if result != multistep.ActionContinue {
- t.Fatalf("Expected the step to return 'ActionContinue', but got '%d'.", result)
- }
-
- if _, ok := stateBag.GetOk(constants.Error); ok == true {
- t.Fatalf("Expected the step to not set stateBag['%s'], but it was.", constants.Error)
+ endpoints := []EndpointType{PublicEndpoint, PublicEndpointInPrivateNetwork}
+
+ for _, endpoint := range endpoints {
+ var testSubject = &StepGetIPAddress{
+ get: func(string, string, string) (string, error) { return "", nil },
+ endpoint: endpoint,
+ say: func(message string) {},
+ error: func(e error) {},
+ }
+
+ stateBag := createTestStateBagStepGetIPAddress()
+
+ var result = testSubject.Run(stateBag)
+ if result != multistep.ActionContinue {
+ t.Fatalf("Expected the step to return 'ActionContinue', but got '%d'.", result)
+ }
+
+ if _, ok := stateBag.GetOk(constants.Error); ok == true {
+ t.Fatalf("Expected the step to not set stateBag['%s'], but it was.", constants.Error)
+ }
}
}
@@ -55,50 +60,53 @@ func TestStepGetIPAddressShouldTakeStepArgumentsFromStateBag(t *testing.T) {
var actualResourceGroupName string
var actualIPAddressName string
var actualNicName string
-
- var testSubject = &StepGetIPAddress{
- get: func(resourceGroupName string, ipAddressName string, nicName string) (string, error) {
- actualResourceGroupName = resourceGroupName
- actualIPAddressName = ipAddressName
- actualNicName = nicName
-
- return "127.0.0.1", nil
- },
- endpoint: PublicEndpoint,
- say: func(message string) {},
- error: func(e error) {},
- }
-
- stateBag := createTestStateBagStepGetIPAddress()
- var result = testSubject.Run(stateBag)
-
- if result != multistep.ActionContinue {
- t.Fatalf("Expected the step to return 'ActionContinue', but got '%d'.", result)
- }
-
- var expectedResourceGroupName = stateBag.Get(constants.ArmResourceGroupName).(string)
- var expectedIPAddressName = stateBag.Get(constants.ArmPublicIPAddressName).(string)
- var expectedNicName = stateBag.Get(constants.ArmNicName).(string)
-
- if actualIPAddressName != expectedIPAddressName {
- t.Fatal("Expected StepGetIPAddress to source 'constants.ArmIPAddressName' from the state bag, but it did not.")
- }
-
- if actualResourceGroupName != expectedResourceGroupName {
- t.Fatal("Expected StepGetIPAddress to source 'constants.ArmResourceGroupName' from the state bag, but it did not.")
- }
-
- if actualNicName != expectedNicName {
- t.Fatalf("Expected StepGetIPAddress to source 'constants.ArmNetworkInterfaceName' from the state bag, but it did not.")
- }
-
- expectedIPAddress, ok := stateBag.GetOk(constants.SSHHost)
- if !ok {
- t.Fatalf("Expected the state bag to have a value for '%s', but it did not.", constants.SSHHost)
- }
-
- if expectedIPAddress != "127.0.0.1" {
- t.Fatalf("Expected the value of stateBag[%s] to be '127.0.0.1', but got '%s'.", constants.SSHHost, expectedIPAddress)
+ endpoints := []EndpointType{PublicEndpoint, PublicEndpointInPrivateNetwork}
+
+ for _, endpoint := range endpoints {
+ var testSubject = &StepGetIPAddress{
+ get: func(resourceGroupName string, ipAddressName string, nicName string) (string, error) {
+ actualResourceGroupName = resourceGroupName
+ actualIPAddressName = ipAddressName
+ actualNicName = nicName
+
+ return "127.0.0.1", nil
+ },
+ endpoint: endpoint,
+ say: func(message string) {},
+ error: func(e error) {},
+ }
+
+ stateBag := createTestStateBagStepGetIPAddress()
+ var result = testSubject.Run(stateBag)
+
+ if result != multistep.ActionContinue {
+ t.Fatalf("Expected the step to return 'ActionContinue', but got '%d'.", result)
+ }
+
+ var expectedResourceGroupName = stateBag.Get(constants.ArmResourceGroupName).(string)
+ var expectedIPAddressName = stateBag.Get(constants.ArmPublicIPAddressName).(string)
+ var expectedNicName = stateBag.Get(constants.ArmNicName).(string)
+
+ if actualIPAddressName != expectedIPAddressName {
+ t.Fatal("Expected StepGetIPAddress to source 'constants.ArmIPAddressName' from the state bag, but it did not.")
+ }
+
+ if actualResourceGroupName != expectedResourceGroupName {
+ t.Fatal("Expected StepGetIPAddress to source 'constants.ArmResourceGroupName' from the state bag, but it did not.")
+ }
+
+ if actualNicName != expectedNicName {
+ t.Fatalf("Expected StepGetIPAddress to source 'constants.ArmNetworkInterfaceName' from the state bag, but it did not.")
+ }
+
+ expectedIPAddress, ok := stateBag.GetOk(constants.SSHHost)
+ if !ok {
+ t.Fatalf("Expected the state bag to have a value for '%s', but it did not.", constants.SSHHost)
+ }
+
+ if expectedIPAddress != "127.0.0.1" {
+ t.Fatalf("Expected the value of stateBag[%s] to be '127.0.0.1', but got '%s'.", constants.SSHHost, expectedIPAddress)
+ }
}
}
diff --git a/vendor/github.com/mitchellh/packer/builder/azure/arm/step_get_os_disk.go b/vendor/github.com/mitchellh/packer/builder/azure/arm/step_get_os_disk.go
index 6b21d57d..511ab5c5 100644
--- a/vendor/github.com/mitchellh/packer/builder/azure/arm/step_get_os_disk.go
+++ b/vendor/github.com/mitchellh/packer/builder/azure/arm/step_get_os_disk.go
@@ -1,6 +1,3 @@
-// Copyright (c) Microsoft Corporation. All rights reserved.
-// Licensed under the MIT License. See the LICENSE file in builder/azure for license information.
-
package arm
import (
diff --git a/vendor/github.com/mitchellh/packer/builder/azure/arm/step_get_os_disk_test.go b/vendor/github.com/mitchellh/packer/builder/azure/arm/step_get_os_disk_test.go
index 9b647492..2b3a4d5d 100644
--- a/vendor/github.com/mitchellh/packer/builder/azure/arm/step_get_os_disk_test.go
+++ b/vendor/github.com/mitchellh/packer/builder/azure/arm/step_get_os_disk_test.go
@@ -1,6 +1,3 @@
-// Copyright (c) Microsoft Corporation. All rights reserved.
-// Licensed under the MIT License. See the LICENSE file in builder/azure for license information.
-
package arm
import (
diff --git a/vendor/github.com/mitchellh/packer/builder/azure/arm/step_power_off_compute.go b/vendor/github.com/mitchellh/packer/builder/azure/arm/step_power_off_compute.go
index a1d38f34..931050e0 100644
--- a/vendor/github.com/mitchellh/packer/builder/azure/arm/step_power_off_compute.go
+++ b/vendor/github.com/mitchellh/packer/builder/azure/arm/step_power_off_compute.go
@@ -1,6 +1,3 @@
-// Copyright (c) Microsoft Corporation. All rights reserved.
-// Licensed under the MIT License. See the LICENSE file in builder/azure for license information.
-
package arm
import (
diff --git a/vendor/github.com/mitchellh/packer/builder/azure/arm/step_power_off_compute_test.go b/vendor/github.com/mitchellh/packer/builder/azure/arm/step_power_off_compute_test.go
index 71004256..2dcdac7f 100644
--- a/vendor/github.com/mitchellh/packer/builder/azure/arm/step_power_off_compute_test.go
+++ b/vendor/github.com/mitchellh/packer/builder/azure/arm/step_power_off_compute_test.go
@@ -1,6 +1,3 @@
-// Copyright (c) Microsoft Corporation. All rights reserved.
-// Licensed under the MIT License. See the LICENSE file in builder/azure for license information.
-
package arm
import (
diff --git a/vendor/github.com/mitchellh/packer/builder/azure/arm/step_set_certificate.go b/vendor/github.com/mitchellh/packer/builder/azure/arm/step_set_certificate.go
index a2263d12..5e865b88 100644
--- a/vendor/github.com/mitchellh/packer/builder/azure/arm/step_set_certificate.go
+++ b/vendor/github.com/mitchellh/packer/builder/azure/arm/step_set_certificate.go
@@ -1,6 +1,3 @@
-// Copyright (c) Microsoft Corporation. All rights reserved.
-// Licensed under the MIT License. See the LICENSE file in builder/azure for license information.
-
package arm
import (
diff --git a/vendor/github.com/mitchellh/packer/builder/azure/arm/step_set_certificate_test.go b/vendor/github.com/mitchellh/packer/builder/azure/arm/step_set_certificate_test.go
index 5bcb7dff..1ad9b7db 100644
--- a/vendor/github.com/mitchellh/packer/builder/azure/arm/step_set_certificate_test.go
+++ b/vendor/github.com/mitchellh/packer/builder/azure/arm/step_set_certificate_test.go
@@ -1,6 +1,3 @@
-// Copyright (c) Microsoft Corporation. All rights reserved.
-// Licensed under the MIT License. See the LICENSE file in builder/azure for license information.
-
package arm
import (
diff --git a/vendor/github.com/mitchellh/packer/builder/azure/arm/step_test.go b/vendor/github.com/mitchellh/packer/builder/azure/arm/step_test.go
index 060c1235..2b10c878 100644
--- a/vendor/github.com/mitchellh/packer/builder/azure/arm/step_test.go
+++ b/vendor/github.com/mitchellh/packer/builder/azure/arm/step_test.go
@@ -1,6 +1,3 @@
-// Copyright (c) Microsoft Corporation. All rights reserved.
-// Licensed under the MIT License. See the LICENSE file in builder/azure for license information.
-
package arm
import (
diff --git a/vendor/github.com/mitchellh/packer/builder/azure/arm/step_validate_template.go b/vendor/github.com/mitchellh/packer/builder/azure/arm/step_validate_template.go
index 5a041f91..d2b98638 100644
--- a/vendor/github.com/mitchellh/packer/builder/azure/arm/step_validate_template.go
+++ b/vendor/github.com/mitchellh/packer/builder/azure/arm/step_validate_template.go
@@ -1,6 +1,3 @@
-// Copyright (c) Microsoft Corporation. All rights reserved.
-// Licensed under the MIT License. See the LICENSE file in builder/azure for license information.
-
package arm
import (
diff --git a/vendor/github.com/mitchellh/packer/builder/azure/arm/step_validate_template_test.go b/vendor/github.com/mitchellh/packer/builder/azure/arm/step_validate_template_test.go
index 071d10d8..a5603078 100644
--- a/vendor/github.com/mitchellh/packer/builder/azure/arm/step_validate_template_test.go
+++ b/vendor/github.com/mitchellh/packer/builder/azure/arm/step_validate_template_test.go
@@ -1,6 +1,3 @@
-// Copyright (c) Microsoft Corporation. All rights reserved.
-// Licensed under the MIT License. See the LICENSE file in builder/azure for license information.
-
package arm
import (
diff --git a/vendor/github.com/mitchellh/packer/builder/azure/arm/template_factory.go b/vendor/github.com/mitchellh/packer/builder/azure/arm/template_factory.go
index 3cd00845..16fe7bf9 100644
--- a/vendor/github.com/mitchellh/packer/builder/azure/arm/template_factory.go
+++ b/vendor/github.com/mitchellh/packer/builder/azure/arm/template_factory.go
@@ -53,7 +53,7 @@ func GetVirtualMachineDeployment(config *Config) (*resources.Deployment, error)
if config.ImageUrl != "" {
builder.SetImageUrl(config.ImageUrl, osType)
} else if config.CustomManagedImageName != "" {
- builder.SetManagedDiskUrl(config.customManagedImageID)
+ builder.SetManagedDiskUrl(config.customManagedImageID, config.managedImageStorageAccountType)
} else if config.ManagedImageName != "" && config.ImagePublisher != "" {
imageID := fmt.Sprintf("/subscriptions/%s/providers/Microsoft.Compute/locations/%s/publishers/%s/ArtifactTypes/vmimage/offers/%s/skus/%s/versions/%s",
config.SubscriptionID,
@@ -63,7 +63,7 @@ func GetVirtualMachineDeployment(config *Config) (*resources.Deployment, error)
config.ImageSku,
config.ImageVersion)
- builder.SetManagedMarketplaceImage(config.Location, config.ImagePublisher, config.ImageOffer, config.ImageSku, config.ImageVersion, imageID)
+ builder.SetManagedMarketplaceImage(config.Location, config.ImagePublisher, config.ImageOffer, config.ImageSku, config.ImageVersion, imageID, config.managedImageStorageAccountType)
} else {
builder.SetMarketPlaceImage(config.ImagePublisher, config.ImageOffer, config.ImageSku, config.ImageVersion)
}
@@ -76,7 +76,12 @@ func GetVirtualMachineDeployment(config *Config) (*resources.Deployment, error)
builder.SetCustomData(config.customData)
}
- if config.VirtualNetworkName != "" {
+ if config.VirtualNetworkName != "" && DefaultPrivateVirtualNetworkWithPublicIp != config.PrivateVirtualNetworkWithPublicIp {
+ builder.SetPrivateVirtualNetworWithPublicIp(
+ config.VirtualNetworkResourceGroupName,
+ config.VirtualNetworkName,
+ config.VirtualNetworkSubnetName)
+ } else if config.VirtualNetworkName != "" {
builder.SetVirtualNetwork(
config.VirtualNetworkResourceGroupName,
config.VirtualNetworkName,
diff --git a/vendor/github.com/mitchellh/packer/builder/azure/arm/template_factory_test.TestVirtualMachineDeployment08.approved.json b/vendor/github.com/mitchellh/packer/builder/azure/arm/template_factory_test.TestVirtualMachineDeployment08.approved.json
index 7089ed59..c567b774 100644
--- a/vendor/github.com/mitchellh/packer/builder/azure/arm/template_factory_test.TestVirtualMachineDeployment08.approved.json
+++ b/vendor/github.com/mitchellh/packer/builder/azure/arm/template_factory_test.TestVirtualMachineDeployment08.approved.json
@@ -129,6 +129,9 @@
"osDisk": {
"caching": "ReadWrite",
"createOption": "fromImage",
+ "managedDisk": {
+ "storageAccountType": "Standard_LRS"
+ },
"name": "osdisk",
"osType": "Linux"
}
diff --git a/vendor/github.com/mitchellh/packer/builder/azure/arm/template_factory_test.TestVirtualMachineDeployment09.approved.json b/vendor/github.com/mitchellh/packer/builder/azure/arm/template_factory_test.TestVirtualMachineDeployment09.approved.json
index 03a00fa3..fbbb7384 100644
--- a/vendor/github.com/mitchellh/packer/builder/azure/arm/template_factory_test.TestVirtualMachineDeployment09.approved.json
+++ b/vendor/github.com/mitchellh/packer/builder/azure/arm/template_factory_test.TestVirtualMachineDeployment09.approved.json
@@ -132,6 +132,9 @@
"osDisk": {
"caching": "ReadWrite",
"createOption": "fromImage",
+ "managedDisk": {
+ "storageAccountType": "Standard_LRS"
+ },
"name": "osdisk",
"osType": "Linux"
}
diff --git a/vendor/github.com/mitchellh/packer/builder/azure/arm/template_factory_test.TestVirtualMachineDeployment10.approved.json b/vendor/github.com/mitchellh/packer/builder/azure/arm/template_factory_test.TestVirtualMachineDeployment10.approved.json
new file mode 100644
index 00000000..0eb13013
--- /dev/null
+++ b/vendor/github.com/mitchellh/packer/builder/azure/arm/template_factory_test.TestVirtualMachineDeployment10.approved.json
@@ -0,0 +1,144 @@
+{
+ "$schema": "http://schema.management.azure.com/schemas/2014-04-01-preview/deploymentTemplate.json",
+ "contentVersion": "1.0.0.0",
+ "parameters": {
+ "adminPassword": {
+ "type": "string"
+ },
+ "adminUsername": {
+ "type": "string"
+ },
+ "dnsNameForPublicIP": {
+ "type": "string"
+ },
+ "osDiskName": {
+ "type": "string"
+ },
+ "storageAccountBlobEndpoint": {
+ "type": "string"
+ },
+ "vmName": {
+ "type": "string"
+ },
+ "vmSize": {
+ "type": "string"
+ }
+ },
+ "resources": [
+ {
+ "apiVersion": "[variables('publicIPAddressApiVersion')]",
+ "location": "[variables('location')]",
+ "name": "[variables('publicIPAddressName')]",
+ "properties": {
+ "dnsSettings": {
+ "domainNameLabel": "[parameters('dnsNameForPublicIP')]"
+ },
+ "publicIPAllocationMethod": "[variables('publicIPAddressType')]"
+ },
+ "type": "Microsoft.Network/publicIPAddresses"
+ },
+ {
+ "apiVersion": "[variables('networkInterfacesApiVersion')]",
+ "dependsOn": [
+ "[concat('Microsoft.Network/publicIPAddresses/', variables('publicIPAddressName'))]"
+ ],
+ "location": "[variables('location')]",
+ "name": "[variables('nicName')]",
+ "properties": {
+ "ipConfigurations": [
+ {
+ "name": "ipconfig",
+ "properties": {
+ "privateIPAllocationMethod": "Dynamic",
+ "publicIPAddress": {
+ "id": "[resourceId('Microsoft.Network/publicIPAddresses', variables('publicIPAddressName'))]"
+ },
+ "subnet": {
+ "id": "[variables('subnetRef')]"
+ }
+ }
+ }
+ ]
+ },
+ "type": "Microsoft.Network/networkInterfaces"
+ },
+ {
+ "apiVersion": "[variables('apiVersion')]",
+ "dependsOn": [
+ "[concat('Microsoft.Network/networkInterfaces/', variables('nicName'))]"
+ ],
+ "location": "[variables('location')]",
+ "name": "[parameters('vmName')]",
+ "properties": {
+ "diagnosticsProfile": {
+ "bootDiagnostics": {
+ "enabled": false
+ }
+ },
+ "hardwareProfile": {
+ "vmSize": "[parameters('vmSize')]"
+ },
+ "networkProfile": {
+ "networkInterfaces": [
+ {
+ "id": "[resourceId('Microsoft.Network/networkInterfaces', variables('nicName'))]"
+ }
+ ]
+ },
+ "osProfile": {
+ "adminPassword": "[parameters('adminPassword')]",
+ "adminUsername": "[parameters('adminUsername')]",
+ "computerName": "[parameters('vmName')]",
+ "linuxConfiguration": {
+ "ssh": {
+ "publicKeys": [
+ {
+ "keyData": "",
+ "path": "[variables('sshKeyPath')]"
+ }
+ ]
+ }
+ }
+ },
+ "storageProfile": {
+ "imageReference": {
+ "offer": "--image-offer--",
+ "publisher": "--image-publisher--",
+ "sku": "--image-sku--",
+ "version": "--version--"
+ },
+ "osDisk": {
+ "caching": "ReadWrite",
+ "createOption": "fromImage",
+ "managedDisk": {
+ "storageAccountType": "Standard_LRS"
+ },
+ "name": "osdisk",
+ "osType": "Linux"
+ }
+ }
+ },
+ "type": "Microsoft.Compute/virtualMachines"
+ }
+ ],
+ "variables": {
+ "addressPrefix": "10.0.0.0/16",
+ "apiVersion": "2017-03-30",
+ "location": "[resourceGroup().location]",
+ "managedDiskApiVersion": "2017-03-30",
+ "networkInterfacesApiVersion": "2017-04-01",
+ "nicName": "packerNic",
+ "publicIPAddressApiVersion": "2017-04-01",
+ "publicIPAddressName": "packerPublicIP",
+ "publicIPAddressType": "Dynamic",
+ "sshKeyPath": "[concat('/home/',parameters('adminUsername'),'/.ssh/authorized_keys')]",
+ "subnetAddressPrefix": "10.0.0.0/24",
+ "subnetName": "--virtual_network_subnet_name--",
+ "subnetRef": "[concat(variables('vnetID'),'/subnets/',variables('subnetName'))]",
+ "virtualNetworkName": "--virtual_network_name--",
+ "virtualNetworkResourceGroup": "--virtual_network_resource_group_name--",
+ "virtualNetworksApiVersion": "2017-04-01",
+ "vmStorageAccountContainerName": "images",
+ "vnetID": "[resourceId(variables('virtualNetworkResourceGroup'), 'Microsoft.Network/virtualNetworks', variables('virtualNetworkName'))]"
+ }
+} \ No newline at end of file
diff --git a/vendor/github.com/mitchellh/packer/builder/azure/arm/template_factory_test.go b/vendor/github.com/mitchellh/packer/builder/azure/arm/template_factory_test.go
index 8a6e0c65..b571871e 100644
--- a/vendor/github.com/mitchellh/packer/builder/azure/arm/template_factory_test.go
+++ b/vendor/github.com/mitchellh/packer/builder/azure/arm/template_factory_test.go
@@ -318,6 +318,43 @@ func TestVirtualMachineDeployment09(t *testing.T) {
}
}
+// Ensure the VM template is correct when building with PublicIp and connect to Private Network
+func TestVirtualMachineDeployment10(t *testing.T) {
+ config := map[string]interface{}{
+ "location": "ignore",
+ "subscription_id": "ignore",
+ "os_type": constants.Target_Linux,
+ "communicator": "none",
+ "image_publisher": "--image-publisher--",
+ "image_offer": "--image-offer--",
+ "image_sku": "--image-sku--",
+ "image_version": "--version--",
+
+ "virtual_network_resource_group_name": "--virtual_network_resource_group_name--",
+ "virtual_network_name": "--virtual_network_name--",
+ "virtual_network_subnet_name": "--virtual_network_subnet_name--",
+ "private_virtual_network_with_public_ip": true,
+
+ "managed_image_name": "ManagedImageName",
+ "managed_image_resource_group_name": "ManagedImageResourceGroupName",
+ }
+
+ c, _, err := newConfig(config, getPackerConfiguration())
+ if err != nil {
+ t.Fatal(err)
+ }
+
+ deployment, err := GetVirtualMachineDeployment(c)
+ if err != nil {
+ t.Fatal(err)
+ }
+
+ err = approvaltests.VerifyJSONStruct(t, deployment.Properties.Template)
+ if err != nil {
+ t.Fatal(err)
+ }
+}
+
// Ensure the link values are not set, and the concrete values are set.
func TestKeyVaultDeployment00(t *testing.T) {
c, _, _ := newConfig(getArmBuilderConfiguration(), getPackerConfiguration())
diff --git a/vendor/github.com/mitchellh/packer/builder/azure/arm/tempname.go b/vendor/github.com/mitchellh/packer/builder/azure/arm/tempname.go
index 22e14097..734cd74a 100644
--- a/vendor/github.com/mitchellh/packer/builder/azure/arm/tempname.go
+++ b/vendor/github.com/mitchellh/packer/builder/azure/arm/tempname.go
@@ -1,6 +1,3 @@
-// Copyright (c) Microsoft Corporation. All rights reserved.
-// Licensed under the MIT License. See the LICENSE file in builder/azure for license information.
-
package arm
import (
diff --git a/vendor/github.com/mitchellh/packer/builder/azure/arm/tempname_test.go b/vendor/github.com/mitchellh/packer/builder/azure/arm/tempname_test.go
index c812e6c7..e9a49b42 100644
--- a/vendor/github.com/mitchellh/packer/builder/azure/arm/tempname_test.go
+++ b/vendor/github.com/mitchellh/packer/builder/azure/arm/tempname_test.go
@@ -1,6 +1,3 @@
-// Copyright (c) Microsoft Corporation. All rights reserved.
-// Licensed under the MIT License. See the LICENSE file in builder/azure for license information.
-
package arm
import (
diff --git a/vendor/github.com/mitchellh/packer/builder/azure/common/constants/stateBag.go b/vendor/github.com/mitchellh/packer/builder/azure/common/constants/stateBag.go
index b1289547..a6eef5bd 100644
--- a/vendor/github.com/mitchellh/packer/builder/azure/common/constants/stateBag.go
+++ b/vendor/github.com/mitchellh/packer/builder/azure/common/constants/stateBag.go
@@ -1,6 +1,3 @@
-// Copyright (c) Microsoft Corporation. All rights reserved.
-// Licensed under the MIT License. See the LICENSE file in builder/azure for license information.
-
package constants
// complete flags
diff --git a/vendor/github.com/mitchellh/packer/builder/azure/common/constants/targetplatforms.go b/vendor/github.com/mitchellh/packer/builder/azure/common/constants/targetplatforms.go
index 953f3d32..515eb746 100644
--- a/vendor/github.com/mitchellh/packer/builder/azure/common/constants/targetplatforms.go
+++ b/vendor/github.com/mitchellh/packer/builder/azure/common/constants/targetplatforms.go
@@ -1,6 +1,3 @@
-// Copyright (c) Microsoft Corporation. All rights reserved.
-// Licensed under the MIT License. See the LICENSE file in builder/azure for license information.
-
package constants
// Target types
diff --git a/vendor/github.com/mitchellh/packer/builder/azure/common/gluestrings.go b/vendor/github.com/mitchellh/packer/builder/azure/common/gluestrings.go
index b59b15fc..e3b6963d 100644
--- a/vendor/github.com/mitchellh/packer/builder/azure/common/gluestrings.go
+++ b/vendor/github.com/mitchellh/packer/builder/azure/common/gluestrings.go
@@ -1,6 +1,3 @@
-// Copyright (c) Microsoft Corporation. All rights reserved.
-// Licensed under the MIT License. See the LICENSE file in builder/azure for license information.
-
package common
// removes overlap between the end of a and the start of b and
diff --git a/vendor/github.com/mitchellh/packer/builder/azure/common/gluestrings_test.go b/vendor/github.com/mitchellh/packer/builder/azure/common/gluestrings_test.go
index 63379d47..0e7a633d 100644
--- a/vendor/github.com/mitchellh/packer/builder/azure/common/gluestrings_test.go
+++ b/vendor/github.com/mitchellh/packer/builder/azure/common/gluestrings_test.go
@@ -1,6 +1,3 @@
-// Copyright (c) Microsoft Corporation. All rights reserved.
-// Licensed under the MIT License. See the LICENSE file in builder/azure for license information.
-
package common
import (
diff --git a/vendor/github.com/mitchellh/packer/builder/azure/common/interruptible_task.go b/vendor/github.com/mitchellh/packer/builder/azure/common/interruptible_task.go
index 32acb099..94edc63c 100644
--- a/vendor/github.com/mitchellh/packer/builder/azure/common/interruptible_task.go
+++ b/vendor/github.com/mitchellh/packer/builder/azure/common/interruptible_task.go
@@ -1,6 +1,3 @@
-// Copyright (c) Microsoft Corporation. All rights reserved.
-// Licensed under the MIT License. See the LICENSE file in builder/azure for license information.
-
package common
import (
diff --git a/vendor/github.com/mitchellh/packer/builder/azure/common/interruptible_task_test.go b/vendor/github.com/mitchellh/packer/builder/azure/common/interruptible_task_test.go
index 44e849f6..d2090d87 100644
--- a/vendor/github.com/mitchellh/packer/builder/azure/common/interruptible_task_test.go
+++ b/vendor/github.com/mitchellh/packer/builder/azure/common/interruptible_task_test.go
@@ -1,6 +1,3 @@
-// Copyright (c) Microsoft Corporation. All rights reserved.
-// Licensed under the MIT License. See the LICENSE file in builder/azure for license information.
-
package common
import (
diff --git a/vendor/github.com/mitchellh/packer/builder/azure/common/lin/ssh.go b/vendor/github.com/mitchellh/packer/builder/azure/common/lin/ssh.go
index 7ee5a606..1600c2f4 100644
--- a/vendor/github.com/mitchellh/packer/builder/azure/common/lin/ssh.go
+++ b/vendor/github.com/mitchellh/packer/builder/azure/common/lin/ssh.go
@@ -1,6 +1,3 @@
-// Copyright (c) Microsoft Corporation. All rights reserved.
-// Licensed under the MIT License. See the LICENSE file in builder/azure for license information.
-
package lin
import (
diff --git a/vendor/github.com/mitchellh/packer/builder/azure/common/lin/step_create_cert.go b/vendor/github.com/mitchellh/packer/builder/azure/common/lin/step_create_cert.go
index 6ef4ff56..6f6a685d 100644
--- a/vendor/github.com/mitchellh/packer/builder/azure/common/lin/step_create_cert.go
+++ b/vendor/github.com/mitchellh/packer/builder/azure/common/lin/step_create_cert.go
@@ -1,6 +1,3 @@
-// Copyright (c) Microsoft Corporation. All rights reserved.
-// Licensed under the MIT License. See the LICENSE file in builder/azure for license information.
-
package lin
import (
diff --git a/vendor/github.com/mitchellh/packer/builder/azure/common/lin/step_generalize_os.go b/vendor/github.com/mitchellh/packer/builder/azure/common/lin/step_generalize_os.go
index 1c355c2c..c4dacc47 100644
--- a/vendor/github.com/mitchellh/packer/builder/azure/common/lin/step_generalize_os.go
+++ b/vendor/github.com/mitchellh/packer/builder/azure/common/lin/step_generalize_os.go
@@ -1,6 +1,3 @@
-// Copyright (c) Microsoft Corporation. All rights reserved.
-// Licensed under the MIT License. See the LICENSE file in builder/azure for license information.
-
package lin
import (
diff --git a/vendor/github.com/mitchellh/packer/builder/azure/common/logutil/logfields.go b/vendor/github.com/mitchellh/packer/builder/azure/common/logutil/logfields.go
index 4e63d521..b450594d 100644
--- a/vendor/github.com/mitchellh/packer/builder/azure/common/logutil/logfields.go
+++ b/vendor/github.com/mitchellh/packer/builder/azure/common/logutil/logfields.go
@@ -1,6 +1,3 @@
-// Copyright (c) Microsoft Corporation. All rights reserved.
-// Licensed under the MIT License. See the LICENSE file in builder/azure for license information.
-
package logutil
import "fmt"
diff --git a/vendor/github.com/mitchellh/packer/builder/azure/common/randomstring.go b/vendor/github.com/mitchellh/packer/builder/azure/common/randomstring.go
index 6d8d752d..a81f5b3c 100644
--- a/vendor/github.com/mitchellh/packer/builder/azure/common/randomstring.go
+++ b/vendor/github.com/mitchellh/packer/builder/azure/common/randomstring.go
@@ -1,6 +1,3 @@
-// Copyright (c) Microsoft Corporation. All rights reserved.
-// Licensed under the MIT License. See the LICENSE file in builder/azure for license information.
-
package common
import (
diff --git a/vendor/github.com/mitchellh/packer/builder/azure/common/randomstring_test.go b/vendor/github.com/mitchellh/packer/builder/azure/common/randomstring_test.go
index ce375e7b..c3e0fae5 100644
--- a/vendor/github.com/mitchellh/packer/builder/azure/common/randomstring_test.go
+++ b/vendor/github.com/mitchellh/packer/builder/azure/common/randomstring_test.go
@@ -1,6 +1,3 @@
-// Copyright (c) Microsoft Corporation. All rights reserved.
-// Licensed under the MIT License. See the LICENSE file in builder/azure for license information.
-
package common
import (
diff --git a/vendor/github.com/mitchellh/packer/builder/azure/common/state_bag.go b/vendor/github.com/mitchellh/packer/builder/azure/common/state_bag.go
index 128ee1e9..a402518a 100644
--- a/vendor/github.com/mitchellh/packer/builder/azure/common/state_bag.go
+++ b/vendor/github.com/mitchellh/packer/builder/azure/common/state_bag.go
@@ -1,6 +1,3 @@
-// Copyright (c) Microsoft Corporation. All rights reserved.
-// Licensed under the MIT License. See the LICENSE file in builder/azure for license information.
-
package common
import "github.com/mitchellh/multistep"
diff --git a/vendor/github.com/mitchellh/packer/builder/azure/common/template/template.go b/vendor/github.com/mitchellh/packer/builder/azure/common/template/template.go
index 0ce9d204..cdea487f 100644
--- a/vendor/github.com/mitchellh/packer/builder/azure/common/template/template.go
+++ b/vendor/github.com/mitchellh/packer/builder/azure/common/template/template.go
@@ -45,6 +45,7 @@ type OSDiskUnion struct {
Caching compute.CachingTypes `json:"caching,omitempty"`
CreateOption compute.DiskCreateOptionTypes `json:"createOption,omitempty"`
DiskSizeGB *int32 `json:"diskSizeGB,omitempty"`
+ ManagedDisk *compute.ManagedDiskParameters `json:"managedDisk,omitempty"`
}
// Union of the StorageProfile and ImageStorageProfile types.
diff --git a/vendor/github.com/mitchellh/packer/builder/azure/common/template/template_builder.go b/vendor/github.com/mitchellh/packer/builder/azure/common/template/template_builder.go
index 898bf77e..7311817c 100644
--- a/vendor/github.com/mitchellh/packer/builder/azure/common/template/template_builder.go
+++ b/vendor/github.com/mitchellh/packer/builder/azure/common/template/template_builder.go
@@ -101,7 +101,7 @@ func (s *TemplateBuilder) BuildWindows(keyVaultName, winRMCertificateUrl string)
return nil
}
-func (s *TemplateBuilder) SetManagedDiskUrl(managedImageId string) error {
+func (s *TemplateBuilder) SetManagedDiskUrl(managedImageId string, storageAccountType compute.StorageAccountTypes) error {
resource, err := s.getResourceByType(resourceVirtualMachine)
if err != nil {
return err
@@ -115,11 +115,14 @@ func (s *TemplateBuilder) SetManagedDiskUrl(managedImageId string) error {
profile.OsDisk.OsType = s.osType
profile.OsDisk.CreateOption = compute.FromImage
profile.OsDisk.Vhd = nil
+ profile.OsDisk.ManagedDisk = &compute.ManagedDiskParameters{
+ StorageAccountType: storageAccountType,
+ }
return nil
}
-func (s *TemplateBuilder) SetManagedMarketplaceImage(location, publisher, offer, sku, version, imageID string) error {
+func (s *TemplateBuilder) SetManagedMarketplaceImage(location, publisher, offer, sku, version, imageID string, storageAccountType compute.StorageAccountTypes) error {
resource, err := s.getResourceByType(resourceVirtualMachine)
if err != nil {
return err
@@ -137,6 +140,9 @@ func (s *TemplateBuilder) SetManagedMarketplaceImage(location, publisher, offer,
profile.OsDisk.OsType = s.osType
profile.OsDisk.CreateOption = compute.FromImage
profile.OsDisk.Vhd = nil
+ profile.OsDisk.ManagedDisk = &compute.ManagedDiskParameters{
+ StorageAccountType: storageAccountType,
+ }
return nil
}
@@ -219,6 +225,24 @@ func (s *TemplateBuilder) SetVirtualNetwork(virtualNetworkResourceGroup, virtual
return nil
}
+func (s *TemplateBuilder) SetPrivateVirtualNetworWithPublicIp(virtualNetworkResourceGroup, virtualNetworkName, subnetName string) error {
+ s.setVariable("virtualNetworkResourceGroup", virtualNetworkResourceGroup)
+ s.setVariable("virtualNetworkName", virtualNetworkName)
+ s.setVariable("subnetName", subnetName)
+
+ s.deleteResourceByType(resourceVirtualNetworks)
+ resource, err := s.getResourceByType(resourceNetworkInterfaces)
+ if err != nil {
+ return err
+ }
+
+ s.deleteResourceDependency(resource, func(s string) bool {
+ return strings.Contains(s, "Microsoft.Network/virtualNetworks")
+ })
+
+ return nil
+}
+
func (s *TemplateBuilder) SetTags(tags *map[string]*string) error {
if tags == nil || len(*tags) == 0 {
return nil
diff --git a/vendor/github.com/mitchellh/packer/builder/azure/common/template/template_parameters.go b/vendor/github.com/mitchellh/packer/builder/azure/common/template/template_parameters.go
index 50bc05cd..424a30c8 100644
--- a/vendor/github.com/mitchellh/packer/builder/azure/common/template/template_parameters.go
+++ b/vendor/github.com/mitchellh/packer/builder/azure/common/template/template_parameters.go
@@ -1,6 +1,3 @@
-// Copyright (c) Microsoft Corporation. All rights reserved.
-// Licensed under the MIT License. See the LICENSE file in builder/azure for license information.
-
package template
// The intent of these types to facilitate interchange with Azure in the
diff --git a/vendor/github.com/mitchellh/packer/builder/azure/common/template/template_parameters_test.go b/vendor/github.com/mitchellh/packer/builder/azure/common/template/template_parameters_test.go
index d9f12ad8..1c24e5bb 100644
--- a/vendor/github.com/mitchellh/packer/builder/azure/common/template/template_parameters_test.go
+++ b/vendor/github.com/mitchellh/packer/builder/azure/common/template/template_parameters_test.go
@@ -1,6 +1,3 @@
-// Copyright (c) Microsoft Corporation. All rights reserved.
-// Licensed under the MIT License. See the LICENSE file in builder/azure for license information.
-
package template
import (
diff --git a/vendor/github.com/mitchellh/packer/builder/azure/common/vault.go b/vendor/github.com/mitchellh/packer/builder/azure/common/vault.go
index c00eadbb..db5c6db0 100644
--- a/vendor/github.com/mitchellh/packer/builder/azure/common/vault.go
+++ b/vendor/github.com/mitchellh/packer/builder/azure/common/vault.go
@@ -1,6 +1,3 @@
-// Copyright (c) Microsoft Corporation. All rights reserved.
-// Licensed under the MIT License. See the LICENSE file in builder/azure for license information.
-
// NOTE: vault APIs do not yet exist in the SDK, but once they do this code
// should be removed.
diff --git a/vendor/github.com/mitchellh/packer/builder/azure/pkcs12/LICENSE b/vendor/github.com/mitchellh/packer/builder/azure/pkcs12/LICENSE
new file mode 100644
index 00000000..6a66aea5
--- /dev/null
+++ b/vendor/github.com/mitchellh/packer/builder/azure/pkcs12/LICENSE
@@ -0,0 +1,27 @@
+Copyright (c) 2009 The Go Authors. All rights reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are
+met:
+
+ * Redistributions of source code must retain the above copyright
+notice, this list of conditions and the following disclaimer.
+ * Redistributions in binary form must reproduce the above
+copyright notice, this list of conditions and the following disclaimer
+in the documentation and/or other materials provided with the
+distribution.
+ * Neither the name of Google Inc. nor the names of its
+contributors may be used to endorse or promote products derived from
+this software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
diff --git a/vendor/github.com/mitchellh/packer/builder/azure/pkcs12/README.md b/vendor/github.com/mitchellh/packer/builder/azure/pkcs12/README.md
deleted file mode 100644
index c8b4603e..00000000
--- a/vendor/github.com/mitchellh/packer/builder/azure/pkcs12/README.md
+++ /dev/null
@@ -1,9 +0,0 @@
-This is a fork of the from the original PKCS#12 parsing code
-published in the Azure repository [go-pkcs12](https://github.com/Azure/go-pkcs12).
-This fork adds serializing a x509 certificate and private key as PKCS#12 binary blob
-(aka .PFX file). Due to the specific nature of this code it was not accepted for
-inclusion in the official Go crypto repository.
-
-The methods used for decoding PKCS#12 have been moved to the test files to further
-discourage the use of this library for decoding. Please use the official
-[pkcs12](https://godoc.org/golang.org/x/crypto/pkcs12) library for decode support.
diff --git a/vendor/github.com/mitchellh/packer/builder/azure/pkcs12/bmp-string.go b/vendor/github.com/mitchellh/packer/builder/azure/pkcs12/bmp-string.go
index e98069b8..284d2a68 100644
--- a/vendor/github.com/mitchellh/packer/builder/azure/pkcs12/bmp-string.go
+++ b/vendor/github.com/mitchellh/packer/builder/azure/pkcs12/bmp-string.go
@@ -1,3 +1,7 @@
+// Copyright 2015 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
package pkcs12
import (
@@ -5,6 +9,7 @@ import (
"unicode/utf16"
)
+// bmpString returns s encoded in UCS-2 with a zero terminator.
func bmpString(s string) ([]byte, error) {
// References:
// https://tools.ietf.org/html/rfc7292#appendix-B.1
@@ -13,14 +18,33 @@ func bmpString(s string) ([]byte, error) {
// EncodeRune returns 0xfffd if the rune does not need special encoding
// - the above RFC provides the info that BMPStrings are NULL terminated.
- rv := make([]byte, 0, 2*len(s)+2)
+ ret := make([]byte, 0, 2*len(s)+2)
for _, r := range s {
if t, _ := utf16.EncodeRune(r); t != 0xfffd {
- return nil, errors.New("string contains characters that cannot be encoded in UCS-2")
+ return nil, errors.New("pkcs12: string contains characters that cannot be encoded in UCS-2")
}
- rv = append(rv, byte(r/256), byte(r%256))
+ ret = append(ret, byte(r/256), byte(r%256))
+ }
+
+ return append(ret, 0, 0), nil
+}
+
+func decodeBMPString(bmpString []byte) (string, error) {
+ if len(bmpString)%2 != 0 {
+ return "", errors.New("pkcs12: odd-length BMP string")
}
- rv = append(rv, 0, 0)
- return rv, nil
+
+ // strip terminator if present
+ if l := len(bmpString); l >= 2 && bmpString[l-1] == 0 && bmpString[l-2] == 0 {
+ bmpString = bmpString[:l-2]
+ }
+
+ s := make([]uint16, 0, len(bmpString)/2)
+ for len(bmpString) > 0 {
+ s = append(s, uint16(bmpString[0])<<8+uint16(bmpString[1]))
+ bmpString = bmpString[2:]
+ }
+
+ return string(utf16.Decode(s)), nil
}
diff --git a/vendor/github.com/mitchellh/packer/builder/azure/pkcs12/bmp-string_test.go b/vendor/github.com/mitchellh/packer/builder/azure/pkcs12/bmp-string_test.go
index 8d4599e9..711528b8 100644
--- a/vendor/github.com/mitchellh/packer/builder/azure/pkcs12/bmp-string_test.go
+++ b/vendor/github.com/mitchellh/packer/builder/azure/pkcs12/bmp-string_test.go
@@ -1,70 +1,69 @@
+// Copyright 2015 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
package pkcs12
import (
"bytes"
- "errors"
+ "encoding/hex"
"testing"
- "unicode/utf16"
)
-func decodeBMPString(bmpString []byte) (string, error) {
- if len(bmpString)%2 != 0 {
- return "", errors.New("expected BMP byte string to be an even length")
- }
-
- // strip terminator if present
- if terminator := bmpString[len(bmpString)-2:]; terminator[0] == terminator[1] && terminator[1] == 0 {
- bmpString = bmpString[:len(bmpString)-2]
- }
-
- s := make([]uint16, 0, len(bmpString)/2)
- for len(bmpString) > 0 {
- s = append(s, uint16(bmpString[0])*265+uint16(bmpString[1]))
- bmpString = bmpString[2:]
- }
-
- return string(utf16.Decode(s)), nil
+var bmpStringTests = []struct {
+ in string
+ expectedHex string
+ shouldFail bool
+}{
+ {"", "0000", false},
+ // Example from https://tools.ietf.org/html/rfc7292#appendix-B.
+ {"Beavis", "0042006500610076006900730000", false},
+ // Some characters from the "Letterlike Symbols Unicode block".
+ {"\u2115 - Double-struck N", "21150020002d00200044006f00750062006c0065002d00730074007200750063006b0020004e0000", false},
+ // any character outside the BMP should trigger an error.
+ {"\U0001f000 East wind (Mahjong)", "", true},
}
func TestBMPStringDecode(t *testing.T) {
- _, err := decodeBMPString([]byte("a"))
- if err == nil {
- t.Fatal("expected decode to fail, but it succeeded")
+ if _, err := decodeBMPString([]byte("a")); err == nil {
+ t.Fatalf("expected decode to fail, but it succeeded")
}
}
func TestBMPString(t *testing.T) {
- str, err := bmpString("")
- if !bytes.Equal(str, []byte{0, 0}) {
- t.Errorf("expected empty string to return double 0, but found: % x", str)
- }
- if err != nil {
- t.Errorf("err: %v", err)
- }
+ for i, test := range bmpStringTests {
+ expected, err := hex.DecodeString(test.expectedHex)
+ if err != nil {
+ t.Fatalf("#%d: failed to decode expectation", i)
+ }
- // Example from https://tools.ietf.org/html/rfc7292#appendix-B
- str, err = bmpString("Beavis")
- if !bytes.Equal(str, []byte{0x00, 0x42, 0x00, 0x65, 0x00, 0x61, 0x00, 0x0076, 0x00, 0x69, 0x00, 0x73, 0x00, 0x00}) {
- t.Errorf("expected 'Beavis' to return 0x00 0x42 0x00 0x65 0x00 0x61 0x00 0x76 0x00 0x69 0x00 0x73 0x00 0x00, but found: % x", str)
- }
- if err != nil {
- t.Errorf("err: %v", err)
- }
+ out, err := bmpString(test.in)
+ if err == nil && test.shouldFail {
+ t.Errorf("#%d: expected to fail, but produced %x", i, out)
+ continue
+ }
- // some characters from the "Letterlike Symbols Unicode block"
- tst := "\u2115 - Double-struck N"
- str, err = bmpString(tst)
- if !bytes.Equal(str, []byte{0x21, 0x15, 0x00, 0x20, 0x00, 0x2d, 0x00, 0x20, 0x00, 0x44, 0x00, 0x6f, 0x00, 0x75, 0x00, 0x62, 0x00, 0x6c, 0x00, 0x65, 0x00, 0x2d, 0x00, 0x73, 0x00, 0x74, 0x00, 0x72, 0x00, 0x75, 0x00, 0x63, 0x00, 0x6b, 0x00, 0x20, 0x00, 0x4e, 0x00, 0x00}) {
- t.Errorf("expected '%s' to return 0x21 0x15 0x00 0x20 0x00 0x2d 0x00 0x20 0x00 0x44 0x00 0x6f 0x00 0x75 0x00 0x62 0x00 0x6c 0x00 0x65 0x00 0x2d 0x00 0x73 0x00 0x74 0x00 0x72 0x00 0x75 0x00 0x63 0x00 0x6b 0x00 0x20 0x00 0x4e 0x00 0x00, but found: % x", tst, str)
- }
- if err != nil {
- t.Errorf("err: %v", err)
- }
+ if err != nil && !test.shouldFail {
+ t.Errorf("#%d: failed unexpectedly: %s", i, err)
+ continue
+ }
+
+ if !test.shouldFail {
+ if !bytes.Equal(out, expected) {
+ t.Errorf("#%d: expected %s, got %x", i, test.expectedHex, out)
+ continue
+ }
+
+ roundTrip, err := decodeBMPString(out)
+ if err != nil {
+ t.Errorf("#%d: decoding output gave an error: %s", i, err)
+ continue
+ }
- // some character outside the BMP should error
- tst = "\U0001f000 East wind (Mahjong)"
- str, err = bmpString(tst)
- if err == nil {
- t.Errorf("expected '%s' to throw error because the first character is not in the BMP", tst)
+ if roundTrip != test.in {
+ t.Errorf("#%d: decoding output resulted in %q, but it should have been %q", i, roundTrip, test.in)
+ continue
+ }
+ }
}
}
diff --git a/vendor/github.com/mitchellh/packer/builder/azure/pkcs12/crypto.go b/vendor/github.com/mitchellh/packer/builder/azure/pkcs12/crypto.go
index 5095a4f7..6c81eb77 100644
--- a/vendor/github.com/mitchellh/packer/builder/azure/pkcs12/crypto.go
+++ b/vendor/github.com/mitchellh/packer/builder/azure/pkcs12/crypto.go
@@ -1,4 +1,6 @@
-// implementation of https://tools.ietf.org/html/rfc2898#section-6.1.2
+// Copyright 2015 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
package pkcs12
@@ -16,30 +18,51 @@ import (
)
const (
- pbeWithSHAAnd3KeyTripleDESCBC = "pbeWithSHAAnd3-KeyTripleDES-CBC"
- pbewithSHAAnd40BitRC2CBC = "pbewithSHAAnd40BitRC2-CBC"
-)
-
-const (
pbeIterationCount = 2048
pbeSaltSizeBytes = 8
)
var (
- oidPbeWithSHAAnd3KeyTripleDESCBC = asn1.ObjectIdentifier{1, 2, 840, 113549, 1, 12, 1, 3}
- oidPbewithSHAAnd40BitRC2CBC = asn1.ObjectIdentifier{1, 2, 840, 113549, 1, 12, 1, 6}
+ oidPBEWithSHAAnd3KeyTripleDESCBC = asn1.ObjectIdentifier([]int{1, 2, 840, 113549, 1, 12, 1, 3})
+ oidPBEWithSHAAnd40BitRC2CBC = asn1.ObjectIdentifier([]int{1, 2, 840, 113549, 1, 12, 1, 6})
)
-var algByOID = map[string]string{
- oidPbeWithSHAAnd3KeyTripleDESCBC.String(): pbeWithSHAAnd3KeyTripleDESCBC,
- oidPbewithSHAAnd40BitRC2CBC.String(): pbewithSHAAnd40BitRC2CBC,
+// pbeCipher is an abstraction of a PKCS#12 cipher.
+type pbeCipher interface {
+ // create returns a cipher.Block given a key.
+ create(key []byte) (cipher.Block, error)
+ // deriveKey returns a key derived from the given password and salt.
+ deriveKey(salt, password []byte, iterations int) []byte
+ // deriveKey returns an IV derived from the given password and salt.
+ deriveIV(salt, password []byte, iterations int) []byte
+}
+
+type shaWithTripleDESCBC struct{}
+
+func (shaWithTripleDESCBC) create(key []byte) (cipher.Block, error) {
+ return des.NewTripleDESCipher(key)
+}
+
+func (shaWithTripleDESCBC) deriveKey(salt, password []byte, iterations int) []byte {
+ return pbkdf(sha1Sum, 20, 64, salt, password, iterations, 1, 24)
+}
+
+func (shaWithTripleDESCBC) deriveIV(salt, password []byte, iterations int) []byte {
+ return pbkdf(sha1Sum, 20, 64, salt, password, iterations, 2, 8)
}
-var blockcodeByAlg = map[string]func(key []byte) (cipher.Block, error){
- pbeWithSHAAnd3KeyTripleDESCBC: des.NewTripleDESCipher,
- pbewithSHAAnd40BitRC2CBC: func(key []byte) (cipher.Block, error) {
- return rc2.New(key, len(key)*8)
- },
+type shaWith40BitRC2CBC struct{}
+
+func (shaWith40BitRC2CBC) create(key []byte) (cipher.Block, error) {
+ return rc2.New(key, len(key)*8)
+}
+
+func (shaWith40BitRC2CBC) deriveKey(salt, password []byte, iterations int) []byte {
+ return pbkdf(sha1Sum, 20, 64, salt, password, iterations, 1, 5)
+}
+
+func (shaWith40BitRC2CBC) deriveIV(salt, password []byte, iterations int) []byte {
+ return pbkdf(sha1Sum, 20, 64, salt, password, iterations, 2, 8)
}
type pbeParams struct {
@@ -47,6 +70,67 @@ type pbeParams struct {
Iterations int
}
+func pbDecrypterFor(algorithm pkix.AlgorithmIdentifier, password []byte) (cipher.BlockMode, int, error) {
+ var cipherType pbeCipher
+
+ switch {
+ case algorithm.Algorithm.Equal(oidPBEWithSHAAnd3KeyTripleDESCBC):
+ cipherType = shaWithTripleDESCBC{}
+ case algorithm.Algorithm.Equal(oidPBEWithSHAAnd40BitRC2CBC):
+ cipherType = shaWith40BitRC2CBC{}
+ default:
+ return nil, 0, NotImplementedError("algorithm " + algorithm.Algorithm.String() + " is not supported")
+ }
+
+ var params pbeParams
+ if err := unmarshal(algorithm.Parameters.FullBytes, &params); err != nil {
+ return nil, 0, err
+ }
+
+ key := cipherType.deriveKey(params.Salt, password, params.Iterations)
+ iv := cipherType.deriveIV(params.Salt, password, params.Iterations)
+
+ block, err := cipherType.create(key)
+ if err != nil {
+ return nil, 0, err
+ }
+
+ return cipher.NewCBCDecrypter(block, iv), block.BlockSize(), nil
+}
+
+func pbDecrypt(info decryptable, password []byte) (decrypted []byte, err error) {
+ cbc, blockSize, err := pbDecrypterFor(info.Algorithm(), password)
+ if err != nil {
+ return nil, err
+ }
+
+ encrypted := info.Data()
+ if len(encrypted) == 0 {
+ return nil, errors.New("pkcs12: empty encrypted data")
+ }
+ if len(encrypted)%blockSize != 0 {
+ return nil, errors.New("pkcs12: input is not a multiple of the block size")
+ }
+ decrypted = make([]byte, len(encrypted))
+ cbc.CryptBlocks(decrypted, encrypted)
+
+ psLen := int(decrypted[len(decrypted)-1])
+ if psLen == 0 || psLen > blockSize {
+ return nil, ErrDecryption
+ }
+
+ if len(decrypted) < psLen {
+ return nil, ErrDecryption
+ }
+ ps := decrypted[len(decrypted)-psLen:]
+ decrypted = decrypted[:len(decrypted)-psLen]
+ if bytes.Compare(ps, bytes.Repeat([]byte{byte(psLen)}, psLen)) != 0 {
+ return nil, ErrDecryption
+ }
+
+ return
+}
+
func pad(src []byte, blockSize int) []byte {
paddingLength := blockSize - len(src)%blockSize
paddingText := bytes.Repeat([]byte{byte(paddingLength)}, paddingLength)
@@ -54,15 +138,15 @@ func pad(src []byte, blockSize int) []byte {
}
func pbEncrypt(plainText, salt, password []byte, iterations int) (cipherText []byte, err error) {
- _, err = io.ReadFull(rand.Reader, salt)
- if err != nil {
+ if _, err := io.ReadFull(rand.Reader, salt); err != nil {
return nil, errors.New("pkcs12: failed to create a random salt value: " + err.Error())
}
- key := deriveKeyByAlg[pbeWithSHAAnd3KeyTripleDESCBC](salt, password, iterations)
- iv := deriveIVByAlg[pbeWithSHAAnd3KeyTripleDESCBC](salt, password, iterations)
+ cipherType := shaWithTripleDESCBC{}
+ key := cipherType.deriveKey(salt, password, iterations)
+ iv := cipherType.deriveIV(salt, password, iterations)
- block, err := des.NewTripleDESCipher(key)
+ block, err := cipherType.create(key)
if err != nil {
return nil, errors.New("pkcs12: failed to create a block cipher: " + err.Error())
}
@@ -76,7 +160,8 @@ func pbEncrypt(plainText, salt, password []byte, iterations int) (cipherText []b
return cipherText, nil
}
+// decryptable abstracts a object that contains ciphertext.
type decryptable interface {
- GetAlgorithm() pkix.AlgorithmIdentifier
- GetData() []byte
+ Algorithm() pkix.AlgorithmIdentifier
+ Data() []byte
}
diff --git a/vendor/github.com/mitchellh/packer/builder/azure/pkcs12/crypto_test.go b/vendor/github.com/mitchellh/packer/builder/azure/pkcs12/crypto_test.go
index fb7f8484..efcd9082 100644
--- a/vendor/github.com/mitchellh/packer/builder/azure/pkcs12/crypto_test.go
+++ b/vendor/github.com/mitchellh/packer/builder/azure/pkcs12/crypto_test.go
@@ -1,62 +1,19 @@
+// Copyright 2015 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
package pkcs12
import (
"bytes"
- "crypto/cipher"
+ "crypto/rand"
"crypto/x509/pkix"
"encoding/asn1"
+ "io"
"testing"
)
-func pbDecrypterFor(algorithm pkix.AlgorithmIdentifier, password []byte) (cipher.BlockMode, error) {
- algorithmName, supported := algByOID[algorithm.Algorithm.String()]
- if !supported {
- return nil, NotImplementedError("algorithm " + algorithm.Algorithm.String() + " is not supported")
- }
-
- var params pbeParams
- if _, err := asn1.Unmarshal(algorithm.Parameters.FullBytes, &params); err != nil {
- return nil, err
- }
-
- k := deriveKeyByAlg[algorithmName](params.Salt, password, params.Iterations)
- iv := deriveIVByAlg[algorithmName](params.Salt, password, params.Iterations)
- password = nil
-
- code, err := blockcodeByAlg[algorithmName](k)
- if err != nil {
- return nil, err
- }
-
- cbc := cipher.NewCBCDecrypter(code, iv)
- return cbc, nil
-}
-
-func pbDecrypt(info decryptable, password []byte) (decrypted []byte, err error) {
- cbc, err := pbDecrypterFor(info.GetAlgorithm(), password)
- password = nil
- if err != nil {
- return nil, err
- }
-
- encrypted := info.GetData()
-
- decrypted = make([]byte, len(encrypted))
- cbc.CryptBlocks(decrypted, encrypted)
-
- if psLen := int(decrypted[len(decrypted)-1]); psLen > 0 && psLen <= cbc.BlockSize() {
- m := decrypted[:len(decrypted)-psLen]
- ps := decrypted[len(decrypted)-psLen:]
- if !bytes.Equal(ps, bytes.Repeat([]byte{byte(psLen)}, psLen)) {
- return nil, ErrDecryption
- }
- decrypted = m
- } else {
- return nil, ErrDecryption
- }
-
- return
-}
+var sha1WithTripleDES = asn1.ObjectIdentifier([]int{1, 2, 840, 113549, 1, 12, 1, 3})
func TestPbDecrypterFor(t *testing.T) {
params, _ := asn1.Marshal(pbeParams{
@@ -72,70 +29,122 @@ func TestPbDecrypterFor(t *testing.T) {
pass, _ := bmpString("Sesame open")
- _, err := pbDecrypterFor(alg, pass)
+ _, _, err := pbDecrypterFor(alg, pass)
if _, ok := err.(NotImplementedError); !ok {
t.Errorf("expected not implemented error, got: %T %s", err, err)
}
- alg.Algorithm = asn1.ObjectIdentifier([]int{1, 2, 840, 113549, 1, 12, 1, 3})
- cbc, err := pbDecrypterFor(alg, pass)
+ alg.Algorithm = sha1WithTripleDES
+ cbc, blockSize, err := pbDecrypterFor(alg, pass)
if err != nil {
- t.Errorf("err: %v", err)
+ t.Errorf("unexpected error from pbDecrypterFor %v", err)
+ }
+ if blockSize != 8 {
+ t.Errorf("unexpected block size %d, wanted 8", blockSize)
}
- M := []byte{1, 2, 3, 4, 5, 6, 7, 8}
- expectedM := []byte{185, 73, 135, 249, 137, 1, 122, 247}
- cbc.CryptBlocks(M, M)
+ plaintext := []byte{1, 2, 3, 4, 5, 6, 7, 8}
+ expectedCiphertext := []byte{185, 73, 135, 249, 137, 1, 122, 247}
+ ciphertext := make([]byte, len(plaintext))
+ cbc.CryptBlocks(ciphertext, plaintext)
- if !bytes.Equal(M, expectedM) {
- t.Errorf("expected M to be '%d', but found '%d", expectedM, M)
+ if bytes.Compare(ciphertext, expectedCiphertext) != 0 {
+ t.Errorf("bad ciphertext, got %x but wanted %x", ciphertext, expectedCiphertext)
}
}
-func TestPbDecrypt(t *testing.T) {
-
- tests := [][]byte{
+var pbDecryptTests = []struct {
+ in []byte
+ expected []byte
+ expectedError error
+}{
+ {
[]byte("\x33\x73\xf3\x9f\xda\x49\xae\xfc\xa0\x9a\xdf\x5a\x58\xa0\xea\x46"), // 7 padding bytes
- []byte("\x33\x73\xf3\x9f\xda\x49\xae\xfc\x96\x24\x2f\x71\x7e\x32\x3f\xe7"), // 8 padding bytes
- []byte("\x35\x0c\xc0\x8d\xab\xa9\x5d\x30\x7f\x9a\xec\x6a\xd8\x9b\x9c\xd9"), // 9 padding bytes, incorrect
- []byte("\xb2\xf9\x6e\x06\x60\xae\x20\xcf\x08\xa0\x7b\xd9\x6b\x20\xef\x41"), // incorrect padding bytes: [ ... 0x04 0x02 ]
- }
- expected := []interface{}{
[]byte("A secret!"),
+ nil,
+ },
+ {
+ []byte("\x33\x73\xf3\x9f\xda\x49\xae\xfc\x96\x24\x2f\x71\x7e\x32\x3f\xe7"), // 8 padding bytes
[]byte("A secret"),
+ nil,
+ },
+ {
+ []byte("\x35\x0c\xc0\x8d\xab\xa9\x5d\x30\x7f\x9a\xec\x6a\xd8\x9b\x9c\xd9"), // 9 padding bytes, incorrect
+ nil,
ErrDecryption,
+ },
+ {
+ []byte("\xb2\xf9\x6e\x06\x60\xae\x20\xcf\x08\xa0\x7b\xd9\x6b\x20\xef\x41"), // incorrect padding bytes: [ ... 0x04 0x02 ]
+ nil,
ErrDecryption,
+ },
+}
+
+func TestPbDecrypt(t *testing.T) {
+ salt := []byte("\xf1\xf2\xf3\xf4\xf5\xf6\xf7\xf8")
+
+ for i, test := range pbDecryptTests {
+ decryptable := makeTestDecryptable(test.in, salt)
+ password, _ := bmpString("sesame")
+
+ plaintext, err := pbDecrypt(decryptable, password)
+ if err != test.expectedError {
+ t.Errorf("#%d: got error %q, but wanted %q", i, err, test.expectedError)
+ continue
+ }
+
+ if !bytes.Equal(plaintext, test.expected) {
+ t.Errorf("#%d: got %x, but wanted %x", i, plaintext, test.expected)
+ }
}
+}
- for i, c := range tests {
- td := testDecryptable{
- data: c,
- algorithm: pkix.AlgorithmIdentifier{
- Algorithm: asn1.ObjectIdentifier([]int{1, 2, 840, 113549, 1, 12, 1, 3}), // SHA1/3TDES
- Parameters: pbeParams{
- Salt: []byte("\xf1\xf2\xf3\xf4\xf5\xf6\xf7\xf8"),
- Iterations: 4096,
- }.RawASN1(),
- },
+func TestRoundTripPkc12EncryptDecrypt(t *testing.T) {
+ salt := []byte{0xfe, 0xee, 0xfa, 0xce}
+ password := salt
+
+ // Sweep the possible padding lengths
+ for i := 0; i < 9; i++ {
+ bs := make([]byte, i)
+ _, err := io.ReadFull(rand.Reader, bs)
+ if err != nil {
+ t.Fatalf("failed to read: %s", err)
+ }
+
+ cipherText, err := pbEncrypt(bs, salt, password, 4096)
+ if err != nil {
+ t.Fatalf("failed to encrypt: %s\n", err)
}
- p, _ := bmpString("sesame")
-
- m, err := pbDecrypt(td, p)
-
- switch e := expected[i].(type) {
- case []byte:
- if err != nil {
- t.Errorf("error decrypting C=%x: %v", c, err)
- }
- if !bytes.Equal(m, e) {
- t.Errorf("expected C=%x to be decoded to M=%x, but found %x", c, e, m)
- }
- case error:
- if err == nil || err.Error() != e.Error() {
- t.Errorf("expecting error '%v' during decryption of c=%x, but found err='%v'", e, c, err)
- }
+
+ if len(cipherText)%8 != 0 {
+ t.Fatalf("plain text was not padded as expected")
}
+
+ decryptable := makeTestDecryptable(cipherText, salt)
+ plainText, err := pbDecrypt(decryptable, password)
+ if err != nil {
+ t.Fatalf("failed to decrypt: %s\n", err)
+ }
+
+ if !bytes.Equal(bs, plainText) {
+ t.Fatalf("got %x, but wanted %x", bs, plainText)
+ }
+ }
+}
+
+func makeTestDecryptable(bytes, salt []byte) testDecryptable {
+ decryptable := testDecryptable{
+ data: bytes,
+ algorithm: pkix.AlgorithmIdentifier{
+ Algorithm: sha1WithTripleDES,
+ Parameters: pbeParams{
+ Salt: salt,
+ Iterations: 4096,
+ }.RawASN1(),
+ },
}
+
+ return decryptable
}
type testDecryptable struct {
@@ -143,8 +152,8 @@ type testDecryptable struct {
algorithm pkix.AlgorithmIdentifier
}
-func (d testDecryptable) GetAlgorithm() pkix.AlgorithmIdentifier { return d.algorithm }
-func (d testDecryptable) GetData() []byte { return d.data }
+func (d testDecryptable) Algorithm() pkix.AlgorithmIdentifier { return d.algorithm }
+func (d testDecryptable) Data() []byte { return d.data }
func (params pbeParams) RawASN1() (raw asn1.RawValue) {
asn1Bytes, err := asn1.Marshal(params)
diff --git a/vendor/github.com/mitchellh/packer/builder/azure/pkcs12/errors.go b/vendor/github.com/mitchellh/packer/builder/azure/pkcs12/errors.go
index 64a9433e..36ad6e95 100644
--- a/vendor/github.com/mitchellh/packer/builder/azure/pkcs12/errors.go
+++ b/vendor/github.com/mitchellh/packer/builder/azure/pkcs12/errors.go
@@ -1,3 +1,7 @@
+// Copyright 2015 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
package pkcs12
import "errors"
@@ -16,7 +20,7 @@ type NotImplementedError string
type EncodeError string
func (e NotImplementedError) Error() string {
- return string(e)
+ return "pkcs12: " + string(e)
}
func (e EncodeError) Error() string {
diff --git a/vendor/github.com/mitchellh/packer/builder/azure/pkcs12/mac.go b/vendor/github.com/mitchellh/packer/builder/azure/pkcs12/mac.go
index c7e42811..76ad0cdc 100644
--- a/vendor/github.com/mitchellh/packer/builder/azure/pkcs12/mac.go
+++ b/vendor/github.com/mitchellh/packer/builder/azure/pkcs12/mac.go
@@ -1,3 +1,7 @@
+// Copyright 2015 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
package pkcs12
import (
@@ -7,10 +11,6 @@ import (
"encoding/asn1"
)
-var (
- oidSha1Algorithm = asn1.ObjectIdentifier{1, 3, 14, 3, 2, 26}
-)
-
type macData struct {
Mac digestInfo
MacSalt []byte
@@ -23,6 +23,23 @@ type digestInfo struct {
Digest []byte
}
+var (
+ oidSHA1 = asn1.ObjectIdentifier([]int{1, 3, 14, 3, 2, 26})
+)
+
+func verifyMac(macData *macData, message, password []byte) error {
+ if !macData.Mac.Algorithm.Algorithm.Equal(oidSHA1) {
+ return NotImplementedError("unknown digest algorithm: " + macData.Mac.Algorithm.Algorithm.String())
+ }
+
+ expectedMAC := computeMac(message, macData.Iterations, macData.MacSalt, password)
+
+ if !hmac.Equal(macData.Mac.Digest, expectedMAC) {
+ return ErrIncorrectPassword
+ }
+ return nil
+}
+
func computeMac(message []byte, iterations int, salt, password []byte) []byte {
key := pbkdf(sha1Sum, 20, 64, salt, password, iterations, 3, 20)
diff --git a/vendor/github.com/mitchellh/packer/builder/azure/pkcs12/mac_test.go b/vendor/github.com/mitchellh/packer/builder/azure/pkcs12/mac_test.go
index 0ccea710..1ed4ff21 100644
--- a/vendor/github.com/mitchellh/packer/builder/azure/pkcs12/mac_test.go
+++ b/vendor/github.com/mitchellh/packer/builder/azure/pkcs12/mac_test.go
@@ -1,24 +1,14 @@
+// Copyright 2015 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
package pkcs12
import (
- "crypto/hmac"
"encoding/asn1"
"testing"
)
-func verifyMac(macData *macData, message, password []byte) error {
- if !macData.Mac.Algorithm.Algorithm.Equal(oidSha1Algorithm) {
- return NotImplementedError("unknown digest algorithm: " + macData.Mac.Algorithm.Algorithm.String())
- }
-
- expectedMAC := computeMac(message, macData.Iterations, macData.MacSalt, password)
-
- if !hmac.Equal(macData.Mac.Digest, expectedMAC) {
- return ErrIncorrectPassword
- }
- return nil
-}
-
func TestVerifyMac(t *testing.T) {
td := macData{
Mac: digestInfo{
diff --git a/vendor/github.com/mitchellh/packer/builder/azure/pkcs12/pbkdf.go b/vendor/github.com/mitchellh/packer/builder/azure/pkcs12/pbkdf.go
index 29685723..5c419d41 100644
--- a/vendor/github.com/mitchellh/packer/builder/azure/pkcs12/pbkdf.go
+++ b/vendor/github.com/mitchellh/packer/builder/azure/pkcs12/pbkdf.go
@@ -1,34 +1,35 @@
+// Copyright 2015 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
package pkcs12
import (
+ "bytes"
"crypto/sha1"
"math/big"
)
var (
- deriveKeyByAlg = map[string]func(salt, password []byte, iterations int) []byte{
- pbeWithSHAAnd3KeyTripleDESCBC: func(salt, password []byte, iterations int) []byte {
- return pbkdf(sha1Sum, 20, 64, salt, password, iterations, 1, 24)
- },
- pbewithSHAAnd40BitRC2CBC: func(salt, password []byte, iterations int) []byte {
- return pbkdf(sha1Sum, 20, 64, salt, password, iterations, 1, 5)
- },
- }
- deriveIVByAlg = map[string]func(salt, password []byte, iterations int) []byte{
- pbeWithSHAAnd3KeyTripleDESCBC: func(salt, password []byte, iterations int) []byte {
- return pbkdf(sha1Sum, 20, 64, salt, password, iterations, 2, 8)
- },
- pbewithSHAAnd40BitRC2CBC: func(salt, password []byte, iterations int) []byte {
- return pbkdf(sha1Sum, 20, 64, salt, password, iterations, 2, 8)
- },
- }
+ one = big.NewInt(1)
)
+// sha1Sum returns the SHA-1 hash of in.
func sha1Sum(in []byte) []byte {
sum := sha1.Sum(in)
return sum[:]
}
+// fillWithRepeats returns v*ceiling(len(pattern) / v) bytes consisting of
+// repeats of pattern.
+func fillWithRepeats(pattern []byte, v int) []byte {
+ if len(pattern) == 0 {
+ return nil
+ }
+ outputLen := v * ((len(pattern) + v - 1) / v)
+ return bytes.Repeat(pattern, (outputLen+len(pattern)-1)/len(pattern))[:outputLen]
+}
+
func pbkdf(hash func([]byte) []byte, u, v int, salt, password []byte, r int, ID byte, size int) (key []byte) {
// implementation of https://tools.ietf.org/html/rfc7292#appendix-B.2 , RFC text verbatim in comments
@@ -75,7 +76,7 @@ func pbkdf(hash func([]byte) []byte, u, v int, salt, password []byte, r int, ID
// 1. Construct a string, D (the "diversifier"), by concatenating v/8
// copies of ID.
- D := []byte{}
+ var D []byte
for i := 0; i < v; i++ {
D = append(D, ID)
}
@@ -85,87 +86,71 @@ func pbkdf(hash func([]byte) []byte, u, v int, salt, password []byte, r int, ID
// truncated to create S). Note that if the salt is the empty
// string, then so is S.
- S := []byte{}
- {
- s := len(salt)
- times := s / v
- if s%v > 0 {
- times++
- }
- for len(S) < times*v {
- S = append(S, salt...)
- }
- S = S[:times*v]
- }
+ S := fillWithRepeats(salt, v)
// 3. Concatenate copies of the password together to create a string P
// of length v(ceiling(p/v)) bits (the final copy of the password
// may be truncated to create P). Note that if the password is the
// empty string, then so is P.
- P := []byte{}
- {
- s := len(password)
- times := s / v
- if s%v > 0 {
- times++
- }
- for len(P) < times*v {
- P = append(P, password...)
- }
- password = nil
- P = P[:times*v]
- }
+ P := fillWithRepeats(password, v)
// 4. Set I=S||P to be the concatenation of S and P.
I := append(S, P...)
// 5. Set c=ceiling(n/u).
- c := size / u
- if size%u > 0 {
- c++
- }
+ c := (size + u - 1) / u
// 6. For i=1, 2, ..., c, do the following:
A := make([]byte, c*20)
+ var IjBuf []byte
for i := 0; i < c; i++ {
-
// A. Set A2=H^r(D||I). (i.e., the r-th hash of D||1,
// H(H(H(... H(D||I))))
Ai := hash(append(D, I...))
for j := 1; j < r; j++ {
- Ai = hash(Ai[:])
+ Ai = hash(Ai)
}
copy(A[i*20:], Ai[:])
if i < c-1 { // skip on last iteration
-
- // B. Concatenate copies of Ai to create a string B of length v
- // bits (the final copy of Ai may be truncated to create B).
- B := []byte{}
+ // B. Concatenate copies of Ai to create a string B of length v
+ // bits (the final copy of Ai may be truncated to create B).
+ var B []byte
for len(B) < v {
B = append(B, Ai[:]...)
}
B = B[:v]
- // C. Treating I as a concatenation I_0, I_1, ..., I_(k-1) of v-bit
- // blocks, where k=ceiling(s/v)+ceiling(p/v), modify I by
- // setting I_j=(I_j+B+1) mod 2^v for each j.
+ // C. Treating I as a concatenation I_0, I_1, ..., I_(k-1) of v-bit
+ // blocks, where k=ceiling(s/v)+ceiling(p/v), modify I by
+ // setting I_j=(I_j+B+1) mod 2^v for each j.
{
- Bbi := new(big.Int)
- Bbi.SetBytes(B)
-
- one := big.NewInt(1)
+ Bbi := new(big.Int).SetBytes(B)
+ Ij := new(big.Int)
for j := 0; j < len(I)/v; j++ {
- Ij := new(big.Int)
Ij.SetBytes(I[j*v : (j+1)*v])
Ij.Add(Ij, Bbi)
Ij.Add(Ij, one)
Ijb := Ij.Bytes()
+ // We expect Ijb to be exactly v bytes,
+ // if it is longer or shorter we must
+ // adjust it accordingly.
if len(Ijb) > v {
Ijb = Ijb[len(Ijb)-v:]
}
+ if len(Ijb) < v {
+ if IjBuf == nil {
+ IjBuf = make([]byte, v)
+ }
+ bytesShort := v - len(Ijb)
+ for i := 0; i < bytesShort; i++ {
+ IjBuf[i] = 0
+ }
+ copy(IjBuf[bytesShort:], Ijb)
+ Ijb = IjBuf
+ }
copy(I[j*v:(j+1)*v], Ijb)
}
}
@@ -175,9 +160,7 @@ func pbkdf(hash func([]byte) []byte, u, v int, salt, password []byte, r int, ID
// bit string, A.
// 8. Use the first n bits of A as the output of this entire process.
- A = A[:size]
-
- return A
+ return A[:size]
// If the above process is being used to generate a DES key, the process
// should be used to create 64 random bits, and the key's parity bits
diff --git a/vendor/github.com/mitchellh/packer/builder/azure/pkcs12/pbkdf_test.go b/vendor/github.com/mitchellh/packer/builder/azure/pkcs12/pbkdf_test.go
index cd66e059..262037d7 100644
--- a/vendor/github.com/mitchellh/packer/builder/azure/pkcs12/pbkdf_test.go
+++ b/vendor/github.com/mitchellh/packer/builder/azure/pkcs12/pbkdf_test.go
@@ -1,3 +1,7 @@
+// Copyright 2015 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
package pkcs12
import (
@@ -6,13 +10,25 @@ import (
)
func TestThatPBKDFWorksCorrectlyForLongKeys(t *testing.T) {
- pbkdf := deriveKeyByAlg[pbeWithSHAAnd3KeyTripleDESCBC]
+ cipherInfo := shaWithTripleDESCBC{}
salt := []byte("\xff\xff\xff\xff\xff\xff\xff\xff")
password, _ := bmpString("sesame")
- key := pbkdf(salt, password, 2048)
+ key := cipherInfo.deriveKey(salt, password, 2048)
+
+ if expected := []byte("\x7c\xd9\xfd\x3e\x2b\x3b\xe7\x69\x1a\x44\xe3\xbe\xf0\xf9\xea\x0f\xb9\xb8\x97\xd4\xe3\x25\xd9\xd1"); bytes.Compare(key, expected) != 0 {
+ t.Fatalf("expected key '%x', but found '%x'", expected, key)
+ }
+}
- if expected := []byte("\x7c\xd9\xfd\x3e\x2b\x3b\xe7\x69\x1a\x44\xe3\xbe\xf0\xf9\xea\x0f\xb9\xb8\x97\xd4\xe3\x25\xd9\xd1"); !bytes.Equal(key, expected) {
- t.Fatalf("expected key '% x', but found '% x'", key, expected)
+func TestThatPBKDFHandlesLeadingZeros(t *testing.T) {
+ // This test triggers a case where I_j (in step 6C) ends up with leading zero
+ // byte, meaning that len(Ijb) < v (leading zeros get stripped by big.Int).
+ // This was previously causing bug whereby certain inputs would break the
+ // derivation and produce the wrong output.
+ key := pbkdf(sha1Sum, 20, 64, []byte("\xf3\x7e\x05\xb5\x18\x32\x4b\x4b"), []byte("\x00\x00"), 2048, 1, 24)
+ expected := []byte("\x00\xf7\x59\xff\x47\xd1\x4d\xd0\x36\x65\xd5\x94\x3c\xb3\xc4\xa3\x9a\x25\x55\xc0\x2a\xed\x66\xe1")
+ if bytes.Compare(key, expected) != 0 {
+ t.Fatalf("expected key '%x', but found '%x'", expected, key)
}
}
diff --git a/vendor/github.com/mitchellh/packer/builder/azure/pkcs12/pkcs12.go b/vendor/github.com/mitchellh/packer/builder/azure/pkcs12/pkcs12.go
index 7db1a2e0..8279cb57 100644
--- a/vendor/github.com/mitchellh/packer/builder/azure/pkcs12/pkcs12.go
+++ b/vendor/github.com/mitchellh/packer/builder/azure/pkcs12/pkcs12.go
@@ -1,20 +1,34 @@
-// Package pkcs12 provides some implementations of PKCS#12.
+// Copyright 2015 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// Package pkcs12 implements some of PKCS#12.
//
-// This implementation is distilled from https://tools.ietf.org/html/rfc7292 and referenced documents.
-// It is intended for decoding P12/PFX-stored certificate+key for use with the crypto/tls package.
+// This implementation is distilled from https://tools.ietf.org/html/rfc7292
+// and referenced documents. It is intended for decoding P12/PFX-stored
+// certificates and keys for use with the crypto/tls package.
package pkcs12
import (
+ "crypto/ecdsa"
"crypto/rand"
+ "crypto/rsa"
+ "crypto/x509"
"crypto/x509/pkix"
"encoding/asn1"
+ "encoding/hex"
+ "encoding/pem"
"errors"
"io"
)
var (
- oidLocalKeyID = asn1.ObjectIdentifier{1, 2, 840, 113549, 1, 9, 21}
- oidDataContentType = asn1.ObjectIdentifier{1, 2, 840, 113549, 1, 7, 1}
+ oidDataContentType = asn1.ObjectIdentifier([]int{1, 2, 840, 113549, 1, 7, 1})
+ oidEncryptedDataContentType = asn1.ObjectIdentifier([]int{1, 2, 840, 113549, 1, 7, 6})
+
+ oidFriendlyName = asn1.ObjectIdentifier([]int{1, 2, 840, 113549, 1, 9, 20})
+ oidLocalKeyID = asn1.ObjectIdentifier([]int{1, 2, 840, 113549, 1, 9, 21})
+ oidMicrosoftCSPName = asn1.ObjectIdentifier([]int{1, 3, 6, 1, 4, 1, 311, 17, 1})
localKeyId = []byte{0x01, 0x00, 0x00, 0x00}
)
@@ -30,6 +44,23 @@ type contentInfo struct {
Content asn1.RawValue `asn1:"tag:0,explicit,optional"`
}
+type encryptedData struct {
+ Version int
+ EncryptedContentInfo encryptedContentInfo
+}
+
+type encryptedContentInfo struct {
+ ContentType asn1.ObjectIdentifier
+ ContentEncryptionAlgorithm pkix.AlgorithmIdentifier
+ EncryptedContent []byte `asn1:"tag:0,optional"`
+}
+
+func (i encryptedContentInfo) Algorithm() pkix.AlgorithmIdentifier {
+ return i.ContentEncryptionAlgorithm
+}
+
+func (i encryptedContentInfo) Data() []byte { return i.EncryptedContent }
+
type safeBag struct {
Id asn1.ObjectIdentifier
Value asn1.RawValue `asn1:"tag:0,explicit"`
@@ -38,7 +69,7 @@ type safeBag struct {
type pkcs12Attribute struct {
Id asn1.ObjectIdentifier
- Value asn1.RawValue `ans1:"set"`
+ Value asn1.RawValue `asn1:"set"`
}
type encryptedPrivateKeyInfo struct {
@@ -46,8 +77,19 @@ type encryptedPrivateKeyInfo struct {
EncryptedData []byte
}
-func (i encryptedPrivateKeyInfo) GetAlgorithm() pkix.AlgorithmIdentifier { return i.AlgorithmIdentifier }
-func (i encryptedPrivateKeyInfo) GetData() []byte { return i.EncryptedData }
+func (i encryptedPrivateKeyInfo) Algorithm() pkix.AlgorithmIdentifier {
+ return i.AlgorithmIdentifier
+}
+
+func (i encryptedPrivateKeyInfo) Data() []byte {
+ return i.EncryptedData
+}
+
+// PEM block types
+const (
+ certificateType = "CERTIFICATE"
+ privateKeyType = "PRIVATE KEY"
+)
// unmarshal calls asn1.Unmarshal, but also returns an error if there is any
// trailing data after unmarshaling.
@@ -62,6 +104,168 @@ func unmarshal(in []byte, out interface{}) error {
return nil
}
+// ConvertToPEM converts all "safe bags" contained in pfxData to PEM blocks.
+func ToPEM(pfxData []byte, password string) ([]*pem.Block, error) {
+ encodedPassword, err := bmpString(password)
+ if err != nil {
+ return nil, ErrIncorrectPassword
+ }
+
+ bags, encodedPassword, err := getSafeContents(pfxData, encodedPassword)
+
+ blocks := make([]*pem.Block, 0, len(bags))
+ for _, bag := range bags {
+ block, err := convertBag(&bag, encodedPassword)
+ if err != nil {
+ return nil, err
+ }
+ blocks = append(blocks, block)
+ }
+
+ return blocks, nil
+}
+
+func convertBag(bag *safeBag, password []byte) (*pem.Block, error) {
+ block := &pem.Block{
+ Headers: make(map[string]string),
+ }
+
+ for _, attribute := range bag.Attributes {
+ k, v, err := convertAttribute(&attribute)
+ if err != nil {
+ return nil, err
+ }
+ block.Headers[k] = v
+ }
+
+ switch {
+ case bag.Id.Equal(oidCertBag):
+ block.Type = certificateType
+ certsData, err := decodeCertBag(bag.Value.Bytes)
+ if err != nil {
+ return nil, err
+ }
+ block.Bytes = certsData
+ case bag.Id.Equal(oidPKCS8ShroudedKeyBag):
+ block.Type = privateKeyType
+
+ key, err := decodePkcs8ShroudedKeyBag(bag.Value.Bytes, password)
+ if err != nil {
+ return nil, err
+ }
+
+ switch key := key.(type) {
+ case *rsa.PrivateKey:
+ block.Bytes = x509.MarshalPKCS1PrivateKey(key)
+ case *ecdsa.PrivateKey:
+ block.Bytes, err = x509.MarshalECPrivateKey(key)
+ if err != nil {
+ return nil, err
+ }
+ default:
+ return nil, errors.New("found unknown private key type in PKCS#8 wrapping")
+ }
+ default:
+ return nil, errors.New("don't know how to convert a safe bag of type " + bag.Id.String())
+ }
+ return block, nil
+}
+
+func convertAttribute(attribute *pkcs12Attribute) (key, value string, err error) {
+ isString := false
+
+ switch {
+ case attribute.Id.Equal(oidFriendlyName):
+ key = "friendlyName"
+ isString = true
+ case attribute.Id.Equal(oidLocalKeyID):
+ key = "localKeyId"
+ case attribute.Id.Equal(oidMicrosoftCSPName):
+ // This key is chosen to match OpenSSL.
+ key = "Microsoft CSP Name"
+ isString = true
+ default:
+ return "", "", errors.New("pkcs12: unknown attribute with OID " + attribute.Id.String())
+ }
+
+ if isString {
+ if err := unmarshal(attribute.Value.Bytes, &attribute.Value); err != nil {
+ return "", "", err
+ }
+ if value, err = decodeBMPString(attribute.Value.Bytes); err != nil {
+ return "", "", err
+ }
+ } else {
+ var id []byte
+ if err := unmarshal(attribute.Value.Bytes, &id); err != nil {
+ return "", "", err
+ }
+ value = hex.EncodeToString(id)
+ }
+
+ return key, value, nil
+}
+
+// Decode extracts a certificate and private key from pfxData. This function
+// assumes that there is only one certificate and only one private key in the
+// pfxData.
+func Decode(pfxData []byte, password string) (privateKey interface{}, certificate *x509.Certificate, err error) {
+ encodedPassword, err := bmpString(password)
+ if err != nil {
+ return nil, nil, err
+ }
+
+ bags, encodedPassword, err := getSafeContents(pfxData, encodedPassword)
+ if err != nil {
+ return nil, nil, err
+ }
+
+ if len(bags) != 2 {
+ err = errors.New("pkcs12: expected exactly two safe bags in the PFX PDU")
+ return
+ }
+
+ for _, bag := range bags {
+ switch {
+ case bag.Id.Equal(oidCertBag):
+ if certificate != nil {
+ err = errors.New("pkcs12: expected exactly one certificate bag")
+ }
+
+ certsData, err := decodeCertBag(bag.Value.Bytes)
+ if err != nil {
+ return nil, nil, err
+ }
+ certs, err := x509.ParseCertificates(certsData)
+ if err != nil {
+ return nil, nil, err
+ }
+ if len(certs) != 1 {
+ err = errors.New("pkcs12: expected exactly one certificate in the certBag")
+ return nil, nil, err
+ }
+ certificate = certs[0]
+
+ case bag.Id.Equal(oidPKCS8ShroudedKeyBag):
+ if privateKey != nil {
+ err = errors.New("pkcs12: expected exactly one key bag")
+ }
+ if privateKey, err = decodePkcs8ShroudedKeyBag(bag.Value.Bytes, encodedPassword); err != nil {
+ return nil, nil, err
+ }
+ }
+ }
+
+ if certificate == nil {
+ return nil, nil, errors.New("pkcs12: certificate missing")
+ }
+ if privateKey == nil {
+ return nil, nil, errors.New("pkcs12: private key missing")
+ }
+
+ return
+}
+
func getLocalKeyId(id []byte) (attribute pkcs12Attribute, err error) {
octetString := asn1.RawValue{Tag: 4, Class: 0, IsCompound: false, Bytes: id}
bytes, err := asn1.Marshal(octetString)
@@ -115,7 +319,7 @@ func makeCertBagContentInfo(derBytes []byte) (*contentInfo, error) {
return nil, EncodeError("encoding cert bag: " + err.Error())
}
- certSafeBags, err := makeSafeBags(oidCertBagType, bytes)
+ certSafeBags, err := makeSafeBags(oidCertBag, bytes)
if err != nil {
return nil, EncodeError("safe bags: " + err.Error())
}
@@ -129,7 +333,7 @@ func makeShroudedKeyBagContentInfo(privateKey interface{}, password []byte) (*co
return nil, EncodeError("encode PKCS#8 shrouded key bag: " + err.Error())
}
- safeBags, err := makeSafeBags(oidPkcs8ShroudedKeyBagType, shroudedKeyBagBytes)
+ safeBags, err := makeSafeBags(oidPKCS8ShroudedKeyBag, shroudedKeyBagBytes)
if err != nil {
return nil, EncodeError("safe bags: " + err.Error())
}
@@ -183,7 +387,7 @@ func makeSalt(saltByteCount int) ([]byte, error) {
//
// derBytes is a DER encoded certificate.
// privateKey is an RSA
-func Encode(derBytes []byte, privateKey interface{}, password string) ([]byte, error) {
+func Encode(derBytes []byte, privateKey interface{}, password string) (pfxBytes []byte, err error) {
secret, err := bmpString(password)
if err != nil {
return nil, ErrIncorrectPassword
@@ -230,7 +434,7 @@ func Encode(derBytes []byte, privateKey interface{}, password string) ([]byte, e
MacSalt: salt,
Mac: digestInfo{
Algorithm: pkix.AlgorithmIdentifier{
- Algorithm: oidSha1Algorithm,
+ Algorithm: oidSHA1,
},
Digest: digest,
},
@@ -244,3 +448,83 @@ func Encode(derBytes []byte, privateKey interface{}, password string) ([]byte, e
return bytes, err
}
+
+func getSafeContents(p12Data, password []byte) (bags []safeBag, updatedPassword []byte, err error) {
+ pfx := new(pfxPdu)
+
+ if err := unmarshal(p12Data, pfx); err != nil {
+ return nil, nil, errors.New("pkcs12: error reading P12 data: " + err.Error())
+ }
+
+ if pfx.Version != 3 {
+ return nil, nil, NotImplementedError("can only decode v3 PFX PDU's")
+ }
+
+ if !pfx.AuthSafe.ContentType.Equal(oidDataContentType) {
+ return nil, nil, NotImplementedError("only password-protected PFX is implemented")
+ }
+
+ // unmarshal the explicit bytes in the content for type 'data'
+ if err := unmarshal(pfx.AuthSafe.Content.Bytes, &pfx.AuthSafe.Content); err != nil {
+ return nil, nil, err
+ }
+
+ if len(pfx.MacData.Mac.Algorithm.Algorithm) == 0 {
+ return nil, nil, errors.New("pkcs12: no MAC in data")
+ }
+
+ if err := verifyMac(&pfx.MacData, pfx.AuthSafe.Content.Bytes, password); err != nil {
+ if err == ErrIncorrectPassword && len(password) == 2 && password[0] == 0 && password[1] == 0 {
+ // some implementations use an empty byte array
+ // for the empty string password try one more
+ // time with empty-empty password
+ password = nil
+ err = verifyMac(&pfx.MacData, pfx.AuthSafe.Content.Bytes, password)
+ }
+ if err != nil {
+ return nil, nil, err
+ }
+ }
+
+ var authenticatedSafe []contentInfo
+ if err := unmarshal(pfx.AuthSafe.Content.Bytes, &authenticatedSafe); err != nil {
+ return nil, nil, err
+ }
+
+ if len(authenticatedSafe) != 2 {
+ return nil, nil, NotImplementedError("expected exactly two items in the authenticated safe")
+ }
+
+ for _, ci := range authenticatedSafe {
+ var data []byte
+
+ switch {
+ case ci.ContentType.Equal(oidDataContentType):
+ if err := unmarshal(ci.Content.Bytes, &data); err != nil {
+ return nil, nil, err
+ }
+ case ci.ContentType.Equal(oidEncryptedDataContentType):
+ var encryptedData encryptedData
+ if err := unmarshal(ci.Content.Bytes, &encryptedData); err != nil {
+ return nil, nil, err
+ }
+ if encryptedData.Version != 0 {
+ return nil, nil, NotImplementedError("only version 0 of EncryptedData is supported")
+ }
+ if data, err = pbDecrypt(encryptedData.EncryptedContentInfo, password); err != nil {
+ return nil, nil, err
+ }
+ default:
+ return nil, nil, NotImplementedError("only data and encryptedData content types are supported in authenticated safe")
+ }
+
+ var safeContents []safeBag
+ if err := unmarshal(data, &safeContents); err != nil {
+ return nil, nil, err
+ }
+
+ bags = append(bags, safeContents...)
+ }
+
+ return bags, password, nil
+}
diff --git a/vendor/github.com/mitchellh/packer/builder/azure/pkcs12/pkcs12_test.go b/vendor/github.com/mitchellh/packer/builder/azure/pkcs12/pkcs12_test.go
index 2cfbc44d..2ac382a0 100644
--- a/vendor/github.com/mitchellh/packer/builder/azure/pkcs12/pkcs12_test.go
+++ b/vendor/github.com/mitchellh/packer/builder/azure/pkcs12/pkcs12_test.go
@@ -1,3 +1,7 @@
+// Copyright 2015 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
package pkcs12
import (
@@ -5,16 +9,36 @@ import (
"crypto/elliptic"
"crypto/rand"
"crypto/rsa"
+ "crypto/tls"
"crypto/x509"
"crypto/x509/pkix"
+ "encoding/base64"
+ "encoding/pem"
"fmt"
"math/big"
"testing"
"time"
-
- gopkcs12 "golang.org/x/crypto/pkcs12"
)
+func TestPfx(t *testing.T) {
+ for commonName, base64P12 := range testdata {
+ p12, _ := base64.StdEncoding.DecodeString(base64P12)
+
+ priv, cert, err := Decode(p12, "")
+ if err != nil {
+ t.Fatal(err)
+ }
+
+ if err := priv.(*rsa.PrivateKey).Validate(); err != nil {
+ t.Errorf("error while validating private key: %v", err)
+ }
+
+ if cert.Subject.CommonName != commonName {
+ t.Errorf("expected common name to be %q, but found %q", commonName, cert.Subject.CommonName)
+ }
+ }
+}
+
func TestPfxRoundTriRsa(t *testing.T) {
privateKey, err := rsa.GenerateKey(rand.Reader, 512)
if err != nil {
@@ -25,7 +49,7 @@ func TestPfxRoundTriRsa(t *testing.T) {
actualPrivateKey, ok := key.(*rsa.PrivateKey)
if !ok {
- t.Fatal("failed to decode private key")
+ t.Fatalf("failed to decode private key")
}
if privateKey.D.Cmp(actualPrivateKey.D) != 0 {
@@ -62,7 +86,7 @@ func testPfxRoundTrip(t *testing.T, privateKey interface{}) interface{} {
t.Fatal(err.Error())
}
- key, _, err := gopkcs12.Decode(bytes, "sesame")
+ key, _, err := Decode(bytes, "sesame")
if err != nil {
t.Fatalf(err.Error())
}
@@ -70,6 +94,61 @@ func testPfxRoundTrip(t *testing.T, privateKey interface{}) interface{} {
return key
}
+func TestPEM(t *testing.T) {
+ for commonName, base64P12 := range testdata {
+ p12, _ := base64.StdEncoding.DecodeString(base64P12)
+
+ blocks, err := ToPEM(p12, "")
+ if err != nil {
+ t.Fatalf("error while converting to PEM: %s", err)
+ }
+
+ var pemData []byte
+ for _, b := range blocks {
+ pemData = append(pemData, pem.EncodeToMemory(b)...)
+ }
+
+ cert, err := tls.X509KeyPair(pemData, pemData)
+ if err != nil {
+ t.Errorf("err while converting to key pair: %v", err)
+ }
+ config := tls.Config{
+ Certificates: []tls.Certificate{cert},
+ }
+ config.BuildNameToCertificate()
+
+ if _, exists := config.NameToCertificate[commonName]; !exists {
+ t.Errorf("did not find our cert in PEM?: %v", config.NameToCertificate)
+ }
+ }
+}
+
+func ExampleToPEM() {
+ p12, _ := base64.StdEncoding.DecodeString(`MIIJzgIBAzCCCZQGCS ... CA+gwggPk==`)
+
+ blocks, err := ToPEM(p12, "password")
+ if err != nil {
+ panic(err)
+ }
+
+ var pemData []byte
+ for _, b := range blocks {
+ pemData = append(pemData, pem.EncodeToMemory(b)...)
+ }
+
+ // then use PEM data for tls to construct tls certificate:
+ cert, err := tls.X509KeyPair(pemData, pemData)
+ if err != nil {
+ panic(err)
+ }
+
+ config := &tls.Config{
+ Certificates: []tls.Certificate{cert},
+ }
+
+ _ = config
+}
+
func newCertificate(hostname string, privateKey interface{}) ([]byte, error) {
t, _ := time.Parse("2006-01-02", "2016-01-01")
notBefore := t
@@ -115,3 +194,54 @@ func newCertificate(hostname string, privateKey interface{}) ([]byte, error) {
return derBytes, nil
}
+
+var testdata = map[string]string{
+ // 'null' password test case
+ "Windows Azure Tools": `MIIKDAIBAzCCCcwGCSqGSIb3DQEHAaCCCb0Eggm5MIIJtTCCBe4GCSqGSIb3DQEHAaCCBd8EggXbMIIF1zCCBdMGCyqGSIb3DQEMCgECoIIE7jCCBOowHAYKKoZIhvcNAQwBAzAOBAhStUNnlTGV+gICB9AEggTIJ81JIossF6boFWpPtkiQRPtI6DW6e9QD4/WvHAVrM2bKdpMzSMsCML5NyuddANTKHBVq00Jc9keqGNAqJPKkjhSUebzQFyhe0E1oI9T4zY5UKr/I8JclOeccH4QQnsySzYUG2SnniXnQ+JrG3juetli7EKth9h6jLc6xbubPadY5HMB3wL/eG/kJymiXwU2KQ9Mgd4X6jbcV+NNCE/8jbZHvSTCPeYTJIjxfeX61Sj5kFKUCzERbsnpyevhY3X0eYtEDezZQarvGmXtMMdzf8HJHkWRdk9VLDLgjk8uiJif/+X4FohZ37ig0CpgC2+dP4DGugaZZ51hb8tN9GeCKIsrmWogMXDIVd0OACBp/EjJVmFB6y0kUCXxUE0TZt0XA1tjAGJcjDUpBvTntZjPsnH/4ZySy+s2d9OOhJ6pzRQBRm360TzkFdSwk9DLiLdGfv4pwMMu/vNGBlqjP/1sQtj+jprJiD1sDbCl4AdQZVoMBQHadF2uSD4/o17XG/Ci0r2h6Htc2yvZMAbEY4zMjjIn2a+vqIxD6onexaek1R3zbkS9j19D6EN9EWn8xgz80YRCyW65znZk8xaIhhvlU/mg7sTxeyuqroBZNcq6uDaQTehDpyH7bY2l4zWRpoj10a6JfH2q5shYz8Y6UZC/kOTfuGqbZDNZWro/9pYquvNNW0M847E5t9bsf9VkAAMHRGBbWoVoU9VpI0UnoXSfvpOo+aXa2DSq5sHHUTVY7A9eov3z5IqT+pligx11xcs+YhDWcU8di3BTJisohKvv5Y8WSkm/rloiZd4ig269k0jTRk1olP/vCksPli4wKG2wdsd5o42nX1yL7mFfXocOANZbB+5qMkiwdyoQSk+Vq+C8nAZx2bbKhUq2MbrORGMzOe0Hh0x2a0PeObycN1Bpyv7Mp3ZI9h5hBnONKCnqMhtyQHUj/nNvbJUnDVYNfoOEqDiEqqEwB7YqWzAKz8KW0OIqdlM8uiQ4JqZZlFllnWJUfaiDrdFM3lYSnFQBkzeVlts6GpDOOBjCYd7dcCNS6kq6pZC6p6HN60Twu0JnurZD6RT7rrPkIGE8vAenFt4iGe/yF52fahCSY8Ws4K0UTwN7bAS+4xRHVCWvE8sMRZsRCHizb5laYsVrPZJhE6+hux6OBb6w8kwPYXc+ud5v6UxawUWgt6uPwl8mlAtU9Z7Miw4Nn/wtBkiLL/ke1UI1gqJtcQXgHxx6mzsjh41+nAgTvdbsSEyU6vfOmxGj3Rwc1eOrIhJUqn5YjOWfzzsz/D5DzWKmwXIwdspt1p+u+kol1N3f2wT9fKPnd/RGCb4g/1hc3Aju4DQYgGY782l89CEEdalpQ/35bQczMFk6Fje12HykakWEXd/bGm9Unh82gH84USiRpeOfQvBDYoqEyrY3zkFZzBjhDqa+jEcAj41tcGx47oSfDq3iVYCdL7HSIjtnyEktVXd7mISZLoMt20JACFcMw+mrbjlug+eU7o2GR7T+LwtOp/p4LZqyLa7oQJDwde1BNZtm3TCK2P1mW94QDL0nDUps5KLtr1DaZXEkRbjSJub2ZE9WqDHyU3KA8G84Tq/rN1IoNu/if45jacyPje1Npj9IftUZSP22nV7HMwZtwQ4P4MYHRMBMGCSqGSIb3DQEJFTEGBAQBAAAAMFsGCSqGSIb3DQEJFDFOHkwAewBCADQAQQA0AEYARQBCADAALQBBADEAOABBAC0ANAA0AEIAQgAtAEIANQBGADIALQA0ADkAMQBFAEYAMQA1ADIAQgBBADEANgB9MF0GCSsGAQQBgjcRATFQHk4ATQBpAGMAcgBvAHMAbwBmAHQAIABTAG8AZgB0AHcAYQByAGUAIABLAGUAeQAgAFMAdABvAHIAYQBnAGUAIABQAHIAbwB2AGkAZABlAHIwggO/BgkqhkiG9w0BBwagggOwMIIDrAIBADCCA6UGCSqGSIb3DQEHATAcBgoqhkiG9w0BDAEGMA4ECEBk5ZAYpu0WAgIH0ICCA3hik4mQFGpw9Ha8TQPtk+j2jwWdxfF0+sTk6S8PTsEfIhB7wPltjiCK92Uv2tCBQnodBUmatIfkpnRDEySmgmdglmOCzj204lWAMRs94PoALGn3JVBXbO1vIDCbAPOZ7Z0Hd0/1t2hmk8v3//QJGUg+qr59/4y/MuVfIg4qfkPcC2QSvYWcK3oTf6SFi5rv9B1IOWFgN5D0+C+x/9Lb/myPYX+rbOHrwtJ4W1fWKoz9g7wwmGFA9IJ2DYGuH8ifVFbDFT1Vcgsvs8arSX7oBsJVW0qrP7XkuDRe3EqCmKW7rBEwYrFznhxZcRDEpMwbFoSvgSIZ4XhFY9VKYglT+JpNH5iDceYEBOQL4vBLpxNUk3l5jKaBNxVa14AIBxq18bVHJ+STInhLhad4u10v/Xbx7wIL3f9DX1yLAkPrpBYbNHS2/ew6H/ySDJnoIDxkw2zZ4qJ+qUJZ1S0lbZVG+VT0OP5uF6tyOSpbMlcGkdl3z254n6MlCrTifcwkzscysDsgKXaYQw06rzrPW6RDub+t+hXzGny799fS9jhQMLDmOggaQ7+LA4oEZsfT89HLMWxJYDqjo3gIfjciV2mV54R684qLDS+AO09U49e6yEbwGlq8lpmO/pbXCbpGbB1b3EomcQbxdWxW2WEkkEd/VBn81K4M3obmywwXJkw+tPXDXfBmzzaqqCR+onMQ5ME1nMkY8ybnfoCc1bDIupjVWsEL2Wvq752RgI6KqzVNr1ew1IdqV5AWN2fOfek+0vi3Jd9FHF3hx8JMwjJL9dZsETV5kHtYJtE7wJ23J68BnCt2eI0GEuwXcCf5EdSKN/xXCTlIokc4Qk/gzRdIZsvcEJ6B1lGovKG54X4IohikqTjiepjbsMWj38yxDmK3mtENZ9ci8FPfbbvIEcOCZIinuY3qFUlRSbx7VUerEoV1IP3clUwexVQo4lHFee2jd7ocWsdSqSapW7OWUupBtDzRkqVhE7tGria+i1W2d6YLlJ21QTjyapWJehAMO637OdbJCCzDs1cXbodRRE7bsP492ocJy8OX66rKdhYbg8srSFNKdb3pF3UDNbN9jhI/t8iagRhNBhlQtTr1me2E/c86Q18qcRXl4bcXTt6acgCeffK6Y26LcVlrgjlD33AEYRRUeyC+rpxbT0aMjdFderlndKRIyG23mSp0HaUwNzAfMAcGBSsOAwIaBBRlviCbIyRrhIysg2dc/KbLFTc2vQQUg4rfwHMM4IKYRD/fsd1x6dda+wQ=`,
+ // empty string password test case
+ "testing@example.com": `MIIJzgIBAzCCCZQGCSqGSIb3DQEHAaCCCYUEggmBMIIJfTCCA/cGCSqGSIb3DQEHBqCCA+gwggPk
+AgEAMIID3QYJKoZIhvcNAQcBMBwGCiqGSIb3DQEMAQYwDgQIIszfRGqcmPcCAggAgIIDsOZ9Eg1L
+s5Wx8JhYoV3HAL4aRnkAWvTYB5NISZOgSgIQTssmt/3A7134dibTmaT/93LikkL3cTKLnQzJ4wDf
+YZ1bprpVJvUqz+HFT79m27bP9zYXFrvxWBJbxjYKTSjQMgz+h8LAEpXXGajCmxMJ1oCOtdXkhhzc
+LdZN6SAYgtmtyFnCdMEDskSggGuLb3fw84QEJ/Sj6FAULXunW/CPaS7Ce0TMsKmNU/jfFWj3yXXw
+ro0kwjKiVLpVFlnBlHo2OoVU7hmkm59YpGhLgS7nxLD3n7nBroQ0ID1+8R01NnV9XLGoGzxMm1te
+6UyTCkr5mj+kEQ8EP1Ys7g/TC411uhVWySMt/rcpkx7Vz1r9kYEAzJpONAfr6cuEVkPKrxpq4Fh0
+2fzlKBky0i/hrfIEUmngh+ERHUb/Mtv/fkv1j5w9suESbhsMLLiCXAlsP1UWMX+3bNizi3WVMEts
+FM2k9byn+p8IUD/A8ULlE4kEaWeoc+2idkCNQkLGuIdGUXUFVm58se0auUkVRoRJx8x4CkMesT8j
+b1H831W66YRWoEwwDQp2kK1lA2vQXxdVHWlFevMNxJeromLzj3ayiaFrfByeUXhR2S+Hpm+c0yNR
+4UVU9WED2kacsZcpRm9nlEa5sr28mri5JdBrNa/K02OOhvKCxr5ZGmbOVzUQKla2z4w+Ku9k8POm
+dfDNU/fGx1b5hcFWtghXe3msWVsSJrQihnN6q1ughzNiYZlJUGcHdZDRtiWwCFI0bR8h/Dmg9uO9
+4rawQQrjIRT7B8yF3UbkZyAqs8Ppb1TsMeNPHh1rxEfGVQknh/48ouJYsmtbnzugTUt3mJCXXiL+
+XcPMV6bBVAUu4aaVKSmg9+yJtY4/VKv10iw88ktv29fViIdBe3t6l/oPuvQgbQ8dqf4T8w0l/uKZ
+9lS1Na9jfT1vCoS7F5TRi+tmyj1vL5kr/amEIW6xKEP6oeAMvCMtbPAzVEj38zdJ1R22FfuIBxkh
+f0Zl7pdVbmzRxl/SBx9iIBJSqAvcXItiT0FIj8HxQ+0iZKqMQMiBuNWJf5pYOLWGrIyntCWwHuaQ
+wrx0sTGuEL9YXLEAsBDrsvzLkx/56E4INGZFrH8G7HBdW6iGqb22IMI4GHltYSyBRKbB0gadYTyv
+abPEoqww8o7/85aPSzOTJ/53ozD438Q+d0u9SyDuOb60SzCD/zPuCEd78YgtXJwBYTuUNRT27FaM
+3LGMX8Hz+6yPNRnmnA2XKPn7dx/IlaqAjIs8MIIFfgYJKoZIhvcNAQcBoIIFbwSCBWswggVnMIIF
+YwYLKoZIhvcNAQwKAQKgggTuMIIE6jAcBgoqhkiG9w0BDAEDMA4ECJr0cClYqOlcAgIIAASCBMhe
+OQSiP2s0/46ONXcNeVAkz2ksW3u/+qorhSiskGZ0b3dFa1hhgBU2Q7JVIkc4Hf7OXaT1eVQ8oqND
+uhqsNz83/kqYo70+LS8Hocj49jFgWAKrf/yQkdyP1daHa2yzlEw4mkpqOfnIORQHvYCa8nEApspZ
+wVu8y6WVuLHKU67mel7db2xwstQp7PRuSAYqGjTfAylElog8ASdaqqYbYIrCXucF8iF9oVgmb/Qo
+xrXshJ9aSLO4MuXlTPELmWgj07AXKSb90FKNihE+y0bWb9LPVFY1Sly3AX9PfrtkSXIZwqW3phpv
+MxGxQl/R6mr1z+hlTfY9Wdpb5vlKXPKA0L0Rt8d2pOesylFi6esJoS01QgP1kJILjbrV731kvDc0
+Jsd+Oxv4BMwA7ClG8w1EAOInc/GrV1MWFGw/HeEqj3CZ/l/0jv9bwkbVeVCiIhoL6P6lVx9pXq4t
+KZ0uKg/tk5TVJmG2vLcMLvezD0Yk3G2ZOMrywtmskrwoF7oAUpO9e87szoH6fEvUZlkDkPVW1NV4
+cZk3DBSQiuA3VOOg8qbo/tx/EE3H59P0axZWno2GSB0wFPWd1aj+b//tJEJHaaNR6qPRj4IWj9ru
+Qbc8eRAcVWleHg8uAehSvUXlFpyMQREyrnpvMGddpiTC8N4UMrrBRhV7+UbCOWhxPCbItnInBqgl
+1JpSZIP7iUtsIMdu3fEC2cdbXMTRul+4rdzUR7F9OaezV3jjvcAbDvgbK1CpyC+MJ1Mxm/iTgk9V
+iUArydhlR8OniN84GyGYoYCW9O/KUwb6ASmeFOu/msx8x6kAsSQHIkKqMKv0TUR3kZnkxUvdpBGP
+KTl4YCTvNGX4dYALBqrAETRDhua2KVBD/kEttDHwBNVbN2xi81+Mc7ml461aADfk0c66R/m2sjHB
+2tN9+wG12OIWFQjL6wF/UfJMYamxx2zOOExiId29Opt57uYiNVLOO4ourPewHPeH0u8Gz35aero7
+lkt7cZAe1Q0038JUuE/QGlnK4lESK9UkSIQAjSaAlTsrcfwtQxB2EjoOoLhwH5mvxUEmcNGNnXUc
+9xj3M5BD3zBz3Ft7G3YMMDwB1+zC2l+0UG0MGVjMVaeoy32VVNvxgX7jk22OXG1iaOB+PY9kdk+O
+X+52BGSf/rD6X0EnqY7XuRPkMGgjtpZeAYxRQnFtCZgDY4wYheuxqSSpdF49yNczSPLkgB3CeCfS
++9NTKN7aC6hBbmW/8yYh6OvSiCEwY0lFS/T+7iaVxr1loE4zI1y/FFp4Pe1qfLlLttVlkygga2UU
+SCunTQ8UB/M5IXWKkhMOO11dP4niWwb39Y7pCWpau7mwbXOKfRPX96cgHnQJK5uG+BesDD1oYnX0
+6frN7FOnTSHKruRIwuI8KnOQ/I+owmyz71wiv5LMQt+yM47UrEjB/EZa5X8dpEwOZvkdqL7utcyo
+l0XH5kWMXdW856LL/FYftAqJIDAmtX1TXF/rbP6mPyN/IlDC0gjP84Uzd/a2UyTIWr+wk49Ek3vQ
+/uDamq6QrwAxVmNh5Tset5Vhpc1e1kb7mRMZIzxSP8JcTuYd45oFKi98I8YjvueHVZce1g7OudQP
+SbFQoJvdT46iBg1TTatlltpOiH2mFaxWVS0xYjAjBgkqhkiG9w0BCRUxFgQUdA9eVqvETX4an/c8
+p8SsTugkit8wOwYJKoZIhvcNAQkUMS4eLABGAHIAaQBlAG4AZABsAHkAIABuAGEAbQBlACAAZgBv
+AHIAIABjAGUAcgB0MDEwITAJBgUrDgMCGgUABBRFsNz3Zd1O1GI8GTuFwCWuDOjEEwQIuBEfIcAy
+HQ8CAggA`,
+}
diff --git a/vendor/github.com/mitchellh/packer/builder/azure/pkcs12/pkcs8.go b/vendor/github.com/mitchellh/packer/builder/azure/pkcs12/pkcs8.go
index 5203d394..22ab14d2 100644
--- a/vendor/github.com/mitchellh/packer/builder/azure/pkcs12/pkcs8.go
+++ b/vendor/github.com/mitchellh/packer/builder/azure/pkcs12/pkcs8.go
@@ -1,3 +1,6 @@
+// Copyright 2016 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
package pkcs12
import (
@@ -28,7 +31,7 @@ var (
// marshalPKCS8PrivateKey converts a private key to PKCS#8 encoded form.
// See http://www.rsa.com/rsalabs/node.asp?id=2130 and RFC5208.
-func marshalPKCS8PrivateKey(key interface{}) ([]byte, error) {
+func marshalPKCS8PrivateKey(key interface{}) (der []byte, err error) {
pkcs := pkcs8{
Version: 0,
}
diff --git a/vendor/github.com/mitchellh/packer/builder/azure/pkcs12/pkcs8_test.go b/vendor/github.com/mitchellh/packer/builder/azure/pkcs12/pkcs8_test.go
index 1f891ef8..7d12119f 100644
--- a/vendor/github.com/mitchellh/packer/builder/azure/pkcs12/pkcs8_test.go
+++ b/vendor/github.com/mitchellh/packer/builder/azure/pkcs12/pkcs8_test.go
@@ -35,7 +35,7 @@ func TestRoundTripPkcs8Rsa(t *testing.T) {
}
if actualPrivateKey.Validate() != nil {
- t.Fatal("private key did not validate")
+ t.Fatalf("private key did not validate")
}
if actualPrivateKey.N.Cmp(privateKey.N) != 0 {
diff --git a/vendor/github.com/mitchellh/packer/builder/azure/pkcs12/rc2/bench_test.go b/vendor/github.com/mitchellh/packer/builder/azure/pkcs12/rc2/bench_test.go
new file mode 100644
index 00000000..3347f338
--- /dev/null
+++ b/vendor/github.com/mitchellh/packer/builder/azure/pkcs12/rc2/bench_test.go
@@ -0,0 +1,27 @@
+// Copyright 2015 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package rc2
+
+import (
+ "testing"
+)
+
+func BenchmarkEncrypt(b *testing.B) {
+ r, _ := New([]byte{0, 0, 0, 0, 0, 0, 0, 0}, 64)
+ b.ResetTimer()
+ var src [8]byte
+ for i := 0; i < b.N; i++ {
+ r.Encrypt(src[:], src[:])
+ }
+}
+
+func BenchmarkDecrypt(b *testing.B) {
+ r, _ := New([]byte{0, 0, 0, 0, 0, 0, 0, 0}, 64)
+ b.ResetTimer()
+ var src [8]byte
+ for i := 0; i < b.N; i++ {
+ r.Decrypt(src[:], src[:])
+ }
+}
diff --git a/vendor/github.com/mitchellh/packer/builder/azure/pkcs12/rc2/rc2.go b/vendor/github.com/mitchellh/packer/builder/azure/pkcs12/rc2/rc2.go
index aa194e50..8c709025 100644
--- a/vendor/github.com/mitchellh/packer/builder/azure/pkcs12/rc2/rc2.go
+++ b/vendor/github.com/mitchellh/packer/builder/azure/pkcs12/rc2/rc2.go
@@ -1,3 +1,7 @@
+// Copyright 2015 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
// Package rc2 implements the RC2 cipher
/*
https://www.ietf.org/rfc/rfc2268.txt
@@ -10,7 +14,6 @@ package rc2
import (
"crypto/cipher"
"encoding/binary"
- "strconv"
)
// The rc2 block size in bytes
@@ -20,34 +23,15 @@ type rc2Cipher struct {
k [64]uint16
}
-// KeySizeError indicates the supplied key was invalid
-type KeySizeError int
-
-func (k KeySizeError) Error() string { return "rc2: invalid key size " + strconv.Itoa(int(k)) }
-
-// EffectiveKeySizeError indicates the supplied effective key length was invalid
-type EffectiveKeySizeError int
-
-func (k EffectiveKeySizeError) Error() string {
- return "rc2: invalid effective key size " + strconv.Itoa(int(k))
-}
-
// New returns a new rc2 cipher with the given key and effective key length t1
func New(key []byte, t1 int) (cipher.Block, error) {
- if l := len(key); l == 0 || l > 128 {
- return nil, KeySizeError(l)
- }
-
- if t1 < 8 || t1 > 1024 {
- return nil, EffectiveKeySizeError(t1)
- }
-
+ // TODO(dgryski): error checking for key length
return &rc2Cipher{
k: expandKey(key, t1),
}, nil
}
-func (c *rc2Cipher) BlockSize() int { return BlockSize }
+func (*rc2Cipher) BlockSize() int { return BlockSize }
var piTable = [256]byte{
0xd9, 0x78, 0xf9, 0xc4, 0x19, 0xdd, 0xb5, 0xed, 0x28, 0xe9, 0xfd, 0x79, 0x4a, 0xa0, 0xd8, 0x9d,
@@ -109,7 +93,6 @@ func (c *rc2Cipher) Encrypt(dst, src []byte) {
var j int
- // These three mix blocks have not been extracted to a common function for to performance reasons.
for j <= 16 {
// mix r0
r0 = r0 + c.k[j] + (r3 & r2) + ((^r3) & r1)
@@ -130,6 +113,7 @@ func (c *rc2Cipher) Encrypt(dst, src []byte) {
r3 = r3 + c.k[j] + (r2 & r1) + ((^r2) & r0)
r3 = rotl16(r3, 5)
j++
+
}
r0 = r0 + c.k[r3&63]
@@ -138,6 +122,7 @@ func (c *rc2Cipher) Encrypt(dst, src []byte) {
r3 = r3 + c.k[r2&63]
for j <= 40 {
+
// mix r0
r0 = r0 + c.k[j] + (r3 & r2) + ((^r3) & r1)
r0 = rotl16(r0, 1)
@@ -157,6 +142,7 @@ func (c *rc2Cipher) Encrypt(dst, src []byte) {
r3 = r3 + c.k[j] + (r2 & r1) + ((^r2) & r0)
r3 = rotl16(r3, 5)
j++
+
}
r0 = r0 + c.k[r3&63]
@@ -165,6 +151,7 @@ func (c *rc2Cipher) Encrypt(dst, src []byte) {
r3 = r3 + c.k[r2&63]
for j <= 60 {
+
// mix r0
r0 = r0 + c.k[j] + (r3 & r2) + ((^r3) & r1)
r0 = rotl16(r0, 1)
@@ -248,6 +235,7 @@ func (c *rc2Cipher) Decrypt(dst, src []byte) {
r0 = rotl16(r0, 16-1)
r0 = r0 - c.k[j] - (r3 & r2) - ((^r3) & r1)
j--
+
}
r3 = r3 - c.k[r2&63]
@@ -256,6 +244,7 @@ func (c *rc2Cipher) Decrypt(dst, src []byte) {
r0 = r0 - c.k[r3&63]
for j >= 0 {
+
// unmix r3
r3 = rotl16(r3, 16-5)
r3 = r3 - c.k[j] - (r2 & r1) - ((^r2) & r0)
@@ -275,6 +264,7 @@ func (c *rc2Cipher) Decrypt(dst, src []byte) {
r0 = rotl16(r0, 16-1)
r0 = r0 - c.k[j] - (r3 & r2) - ((^r3) & r1)
j--
+
}
binary.LittleEndian.PutUint16(dst[0:], r0)
diff --git a/vendor/github.com/mitchellh/packer/builder/azure/pkcs12/rc2/rc2_test.go b/vendor/github.com/mitchellh/packer/builder/azure/pkcs12/rc2/rc2_test.go
index adb73c59..8a49dfaf 100644
--- a/vendor/github.com/mitchellh/packer/builder/azure/pkcs12/rc2/rc2_test.go
+++ b/vendor/github.com/mitchellh/packer/builder/azure/pkcs12/rc2/rc2_test.go
@@ -1,3 +1,7 @@
+// Copyright 2015 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
package rc2
import (
@@ -8,6 +12,7 @@ import (
func TestEncryptDecrypt(t *testing.T) {
+ // TODO(dgryski): add the rest of the test vectors from the RFC
var tests = []struct {
key string
plain string
@@ -86,20 +91,3 @@ func TestEncryptDecrypt(t *testing.T) {
}
}
}
-
-func BenchmarkEncrypt(b *testing.B) {
- r, _ := New([]byte{0, 0, 0, 0, 0, 0, 0, 0}, 64)
- b.ResetTimer()
- var src [8]byte
- for i := 0; i < b.N; i++ {
- r.Encrypt(src[:], src[:])
- }
-}
-func BenchmarkDecrypt(b *testing.B) {
- r, _ := New([]byte{0, 0, 0, 0, 0, 0, 0, 0}, 64)
- b.ResetTimer()
- var src [8]byte
- for i := 0; i < b.N; i++ {
- r.Decrypt(src[:], src[:])
- }
-}
diff --git a/vendor/github.com/mitchellh/packer/builder/azure/pkcs12/safebags.go b/vendor/github.com/mitchellh/packer/builder/azure/pkcs12/safebags.go
index 5d4793b3..bbd1526b 100644
--- a/vendor/github.com/mitchellh/packer/builder/azure/pkcs12/safebags.go
+++ b/vendor/github.com/mitchellh/packer/builder/azure/pkcs12/safebags.go
@@ -1,17 +1,21 @@
+// Copyright 2015 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
package pkcs12
import (
+ "crypto/x509"
"crypto/x509/pkix"
"encoding/asn1"
"errors"
)
-//see https://tools.ietf.org/html/rfc7292#appendix-D
var (
- oidPkcs8ShroudedKeyBagType = asn1.ObjectIdentifier{1, 2, 840, 113549, 1, 12, 10, 1, 2}
- oidCertBagType = asn1.ObjectIdentifier{1, 2, 840, 113549, 1, 12, 10, 1, 3}
-
- oidCertTypeX509Certificate = asn1.ObjectIdentifier{1, 2, 840, 113549, 1, 9, 22, 1}
+ // see https://tools.ietf.org/html/rfc7292#appendix-D
+ oidCertTypeX509Certificate = asn1.ObjectIdentifier([]int{1, 2, 840, 113549, 1, 9, 22, 1})
+ oidPKCS8ShroudedKeyBag = asn1.ObjectIdentifier([]int{1, 2, 840, 113549, 1, 12, 10, 1, 2})
+ oidCertBag = asn1.ObjectIdentifier([]int{1, 2, 840, 113549, 1, 12, 10, 1, 3})
)
type certBag struct {
@@ -52,7 +56,7 @@ func encodePkcs8ShroudedKeyBag(privateKey interface{}, password []byte) (bytes [
pkinfo := encryptedPrivateKeyInfo{
AlgorithmIdentifier: pkix.AlgorithmIdentifier{
- Algorithm: oidPbeWithSHAAnd3KeyTripleDESCBC,
+ Algorithm: oidPBEWithSHAAnd3KeyTripleDESCBC,
Parameters: params,
},
EncryptedData: pkData,
@@ -65,3 +69,37 @@ func encodePkcs8ShroudedKeyBag(privateKey interface{}, password []byte) (bytes [
return bytes, err
}
+
+func decodePkcs8ShroudedKeyBag(asn1Data, password []byte) (privateKey interface{}, err error) {
+ pkinfo := new(encryptedPrivateKeyInfo)
+ if err = unmarshal(asn1Data, pkinfo); err != nil {
+ return nil, errors.New("pkcs12: error decoding PKCS#8 shrouded key bag: " + err.Error())
+ }
+
+ pkData, err := pbDecrypt(pkinfo, password)
+ if err != nil {
+ return nil, errors.New("pkcs12: error decrypting PKCS#8 shrouded key bag: " + err.Error())
+ }
+
+ ret := new(asn1.RawValue)
+ if err = unmarshal(pkData, ret); err != nil {
+ return nil, errors.New("pkcs12: error unmarshaling decrypted private key: " + err.Error())
+ }
+
+ if privateKey, err = x509.ParsePKCS8PrivateKey(pkData); err != nil {
+ return nil, errors.New("pkcs12: error parsing PKCS#8 private key: " + err.Error())
+ }
+
+ return privateKey, nil
+}
+
+func decodeCertBag(asn1Data []byte) (x509Certificates []byte, err error) {
+ bag := new(certBag)
+ if err := unmarshal(asn1Data, bag); err != nil {
+ return nil, errors.New("pkcs12: error decoding cert bag: " + err.Error())
+ }
+ if !bag.Id.Equal(oidCertTypeX509Certificate) {
+ return nil, NotImplementedError("only X509 certificates are supported")
+ }
+ return bag.Data, nil
+}
diff --git a/vendor/github.com/mitchellh/packer/builder/azure/pkcs12/safebags_test.go b/vendor/github.com/mitchellh/packer/builder/azure/pkcs12/safebags_test.go
index 384dd5ce..f21a83c6 100644
--- a/vendor/github.com/mitchellh/packer/builder/azure/pkcs12/safebags_test.go
+++ b/vendor/github.com/mitchellh/packer/builder/azure/pkcs12/safebags_test.go
@@ -1,39 +1,15 @@
+// Copyright 2016 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
package pkcs12
import (
"crypto/rand"
"crypto/rsa"
- "crypto/x509"
"encoding/asn1"
- "fmt"
"testing"
)
-func decodePkcs8ShroudedKeyBag(asn1Data, password []byte) (privateKey interface{}, err error) {
- pkinfo := new(encryptedPrivateKeyInfo)
- if _, err = asn1.Unmarshal(asn1Data, pkinfo); err != nil {
- err = fmt.Errorf("error decoding PKCS8 shrouded key bag: %v", err)
- return nil, err
- }
-
- pkData, err := pbDecrypt(pkinfo, password)
- if err != nil {
- err = fmt.Errorf("error decrypting PKCS8 shrouded key bag: %v", err)
- return
- }
-
- rv := new(asn1.RawValue)
- if _, err = asn1.Unmarshal(pkData, rv); err != nil {
- err = fmt.Errorf("could not decode decrypted private key data")
- }
-
- if privateKey, err = x509.ParsePKCS8PrivateKey(pkData); err != nil {
- err = fmt.Errorf("error parsing PKCS8 private key: %v", err)
- return nil, err
- }
- return
-}
-
// Assert the default algorithm parameters are in the correct order,
// and default to the correct value. Defaults are based on OpenSSL.
// 1. IterationCount, defaults to 2,048 long.
@@ -61,7 +37,7 @@ func TestDefaultAlgorithmParametersPkcs8ShroudedKeyBag(t *testing.T) {
}
var params pbeParams
- rest, err = asn1.Unmarshal(pkinfo.GetAlgorithm().Parameters.FullBytes, &params)
+ rest, err = asn1.Unmarshal(pkinfo.Algorithm().Parameters.FullBytes, &params)
if err != nil {
t.Fatalf("failed to unmarshal encryptedPrivateKeyInfo %s", err)
}
@@ -97,6 +73,6 @@ func TestRoundTripPkcs8ShroudedKeyBag(t *testing.T) {
actualPrivateKey := key.(*rsa.PrivateKey)
if actualPrivateKey.D.Cmp(privateKey.D) != 0 {
- t.Fatal("failed to round-trip rsa.PrivateKey.D")
+ t.Fatalf("failed to round-trip rsa.PrivateKey.D")
}
}
diff --git a/vendor/github.com/mitchellh/packer/builder/cloudstack/builder.go b/vendor/github.com/mitchellh/packer/builder/cloudstack/builder.go
index 369fe0cc..5c82e318 100644
--- a/vendor/github.com/mitchellh/packer/builder/cloudstack/builder.go
+++ b/vendor/github.com/mitchellh/packer/builder/cloudstack/builder.go
@@ -1,6 +1,8 @@
package cloudstack
import (
+ "fmt"
+
"github.com/hashicorp/packer/common"
"github.com/hashicorp/packer/helper/communicator"
"github.com/hashicorp/packer/packer"
@@ -61,34 +63,37 @@ func (b *Builder) Run(ui packer.Ui, hook packer.Hook, cache packer.Cache) (packe
HTTPPortMin: b.config.HTTPPortMin,
HTTPPortMax: b.config.HTTPPortMax,
},
+ &stepKeypair{
+ Debug: b.config.PackerDebug,
+ DebugKeyPath: fmt.Sprintf("cs_%s.pem", b.config.PackerBuildName),
+ KeyPair: b.config.Keypair,
+ PrivateKeyFile: b.config.Comm.SSHPrivateKey,
+ SSHAgentAuth: b.config.Comm.SSHAgentAuth,
+ TemporaryKeyPairName: b.config.TemporaryKeypairName,
+ },
+ &stepCreateSecurityGroup{},
&stepCreateInstance{
- Ctx: b.config.ctx,
+ Ctx: b.config.ctx,
+ Debug: b.config.PackerDebug,
},
&stepSetupNetworking{},
&communicator.StepConnect{
Config: &b.config.Comm,
Host: commHost,
- SSHConfig: SSHConfig(
+ SSHConfig: sshConfig(
b.config.Comm.SSHAgentAuth,
b.config.Comm.SSHUsername,
b.config.Comm.SSHPassword),
+ SSHPort: commPort,
+ WinRMPort: commPort,
},
&common.StepProvision{},
&stepShutdownInstance{},
&stepCreateTemplate{},
}
- // Configure the runner.
- if b.config.PackerDebug {
- b.runner = &multistep.DebugRunner{
- Steps: steps,
- PauseFn: common.MultistepDebugFn(ui),
- }
- } else {
- b.runner = &multistep.BasicRunner{Steps: steps}
- }
-
- // Run the steps.
+ // Configure the runner and run the steps.
+ b.runner = common.NewRunner(steps, b.config.PackerConfig, ui)
b.runner.Run(state)
// If there was an error, return that
diff --git a/vendor/github.com/mitchellh/packer/builder/cloudstack/config.go b/vendor/github.com/mitchellh/packer/builder/cloudstack/config.go
index 5d6e9da0..7a617c6c 100644
--- a/vendor/github.com/mitchellh/packer/builder/cloudstack/config.go
+++ b/vendor/github.com/mitchellh/packer/builder/cloudstack/config.go
@@ -27,23 +27,26 @@ type Config struct {
HTTPGetOnly bool `mapstructure:"http_get_only"`
SSLNoVerify bool `mapstructure:"ssl_no_verify"`
- CIDRList []string `mapstructure:"cidr_list"`
- DiskOffering string `mapstructure:"disk_offering"`
- DiskSize int64 `mapstructure:"disk_size"`
- Expunge bool `mapstructure:"expunge"`
- Hypervisor string `mapstructure:"hypervisor"`
- InstanceName string `mapstructure:"instance_name"`
- Keypair string `mapstructure:"keypair"`
- Network string `mapstructure:"network"`
- Project string `mapstructure:"project"`
- PublicIPAddress string `mapstructure:"public_ip_address"`
- ServiceOffering string `mapstructure:"service_offering"`
- SourceTemplate string `mapstructure:"source_template"`
- SourceISO string `mapstructure:"source_iso"`
- UserData string `mapstructure:"user_data"`
- UserDataFile string `mapstructure:"user_data_file"`
- UseLocalIPAddress bool `mapstructure:"use_local_ip_address"`
- Zone string `mapstructure:"zone"`
+ CIDRList []string `mapstructure:"cidr_list"`
+ CreateSecurityGroup bool `mapstructure:"create_security_group"`
+ DiskOffering string `mapstructure:"disk_offering"`
+ DiskSize int64 `mapstructure:"disk_size"`
+ Expunge bool `mapstructure:"expunge"`
+ Hypervisor string `mapstructure:"hypervisor"`
+ InstanceName string `mapstructure:"instance_name"`
+ Keypair string `mapstructure:"keypair"`
+ Network string `mapstructure:"network"`
+ Project string `mapstructure:"project"`
+ PublicIPAddress string `mapstructure:"public_ip_address"`
+ SecurityGroups []string `mapstructure:"security_groups"`
+ ServiceOffering string `mapstructure:"service_offering"`
+ SourceISO string `mapstructure:"source_iso"`
+ SourceTemplate string `mapstructure:"source_template"`
+ TemporaryKeypairName string `mapstructure:"temporary_keypair_name"`
+ UseLocalIPAddress bool `mapstructure:"use_local_ip_address"`
+ UserData string `mapstructure:"user_data"`
+ UserDataFile string `mapstructure:"user_data_file"`
+ Zone string `mapstructure:"zone"`
TemplateName string `mapstructure:"template_name"`
TemplateDisplayText string `mapstructure:"template_display_text"`
@@ -55,9 +58,7 @@ type Config struct {
TemplateScalable bool `mapstructure:"template_scalable"`
TemplateTag string `mapstructure:"template_tag"`
- ctx interpolate.Context
- hostAddress string // The host address used by the communicators.
- instanceSource string // This can be either a template ID or an ISO ID.
+ ctx interpolate.Context
}
// NewConfig parses and validates the given config.
@@ -98,7 +99,7 @@ func NewConfig(raws ...interface{}) (*Config, error) {
c.AsyncTimeout = 30 * time.Minute
}
- if len(c.CIDRList) == 0 && !c.UseLocalIPAddress {
+ if len(c.CIDRList) == 0 {
c.CIDRList = []string{"0.0.0.0/0"}
}
@@ -120,6 +121,14 @@ func NewConfig(raws ...interface{}) (*Config, error) {
c.TemplateDisplayText = c.TemplateName
}
+ // If we are not given an explicit keypair, ssh_password or ssh_private_key_file,
+ // then create a temporary one, but only if the temporary_keypair_name has not
+ // been provided.
+ if c.Keypair == "" && c.TemporaryKeypairName == "" &&
+ c.Comm.SSHPrivateKey == "" && c.Comm.SSHPassword == "" {
+ c.TemporaryKeypairName = fmt.Sprintf("packer_%s", uuid.TimeOrderedUUID())
+ }
+
// Process required parameters.
if c.APIURL == "" {
errs = packer.MultiErrorAppend(errs, errors.New("a api_url must be specified"))
@@ -137,6 +146,10 @@ func NewConfig(raws ...interface{}) (*Config, error) {
errs = packer.MultiErrorAppend(errs, errors.New("a network must be specified"))
}
+ if c.CreateSecurityGroup && !c.Expunge {
+ errs = packer.MultiErrorAppend(errs, errors.New("auto creating a temporary security group requires expunge"))
+ }
+
if c.ServiceOffering == "" {
errs = packer.MultiErrorAppend(errs, errors.New("a service_offering must be specified"))
}
diff --git a/vendor/github.com/mitchellh/packer/builder/cloudstack/ssh.go b/vendor/github.com/mitchellh/packer/builder/cloudstack/ssh.go
index ab350d05..7a4c2fcb 100644
--- a/vendor/github.com/mitchellh/packer/builder/cloudstack/ssh.go
+++ b/vendor/github.com/mitchellh/packer/builder/cloudstack/ssh.go
@@ -7,28 +7,29 @@ import (
packerssh "github.com/hashicorp/packer/communicator/ssh"
"github.com/mitchellh/multistep"
- "github.com/xanzy/go-cloudstack/cloudstack"
"golang.org/x/crypto/ssh"
"golang.org/x/crypto/ssh/agent"
)
func commHost(state multistep.StateBag) (string, error) {
- client := state.Get("client").(*cloudstack.CloudStackClient)
- config := state.Get("config").(*Config)
+ ip, hasIP := state.Get("ipaddress").(string)
+ if !hasIP {
+ return "", fmt.Errorf("Failed to retrieve IP address")
+ }
- if config.hostAddress == "" {
- ipAddr, _, err := client.Address.GetPublicIpAddressByID(config.PublicIPAddress)
- if err != nil {
- return "", fmt.Errorf("Failed to retrieve IP address: %s", err)
- }
+ return ip, nil
+}
- config.hostAddress = ipAddr.Ipaddress
+func commPort(state multistep.StateBag) (int, error) {
+ commPort, hasPort := state.Get("commPort").(int)
+ if !hasPort {
+ return 0, fmt.Errorf("Failed to retrieve communication port")
}
- return config.hostAddress, nil
+ return commPort, nil
}
-func SSHConfig(useAgent bool, username, password string) func(state multistep.StateBag) (*ssh.ClientConfig, error) {
+func sshConfig(useAgent bool, username, password string) func(state multistep.StateBag) (*ssh.ClientConfig, error) {
return func(state multistep.StateBag) (*ssh.ClientConfig, error) {
if useAgent {
authSock := os.Getenv("SSH_AUTH_SOCK")
diff --git a/vendor/github.com/mitchellh/packer/builder/cloudstack/step_configure_networking.go b/vendor/github.com/mitchellh/packer/builder/cloudstack/step_configure_networking.go
index 48a3742a..d9a6a365 100644
--- a/vendor/github.com/mitchellh/packer/builder/cloudstack/step_configure_networking.go
+++ b/vendor/github.com/mitchellh/packer/builder/cloudstack/step_configure_networking.go
@@ -25,6 +25,7 @@ func (s *stepSetupNetworking) Run(state multistep.StateBag) multistep.StepAction
if config.UseLocalIPAddress {
ui.Message("Using the local IP address...")
+ state.Put("commPort", config.Comm.Port())
ui.Message("Networking has been setup!")
return multistep.ActionContinue
}
@@ -32,18 +33,11 @@ func (s *stepSetupNetworking) Run(state multistep.StateBag) multistep.StepAction
// Generate a random public port used to configure our port forward.
rand.Seed(time.Now().UnixNano())
s.publicPort = 50000 + rand.Intn(10000)
+ state.Put("commPort", s.publicPort)
// Set the currently configured port to be the private port.
s.privatePort = config.Comm.Port()
- // Set the SSH or WinRM port to be the randomly generated public port.
- switch config.Comm.Type {
- case "ssh":
- config.Comm.SSHPort = s.publicPort
- case "winrm":
- config.Comm.WinRMPort = s.publicPort
- }
-
// Retrieve the instance ID from the previously saved state.
instanceID, ok := state.Get("instance_id").(string)
if !ok || instanceID == "" {
@@ -91,7 +85,7 @@ func (s *stepSetupNetworking) Run(state multistep.StateBag) multistep.StepAction
// Set the IP address and it's ID.
config.PublicIPAddress = ipAddr.Id
- config.hostAddress = ipAddr.Ipaddress
+ state.Put("ipaddress", ipAddr.Ipaddress)
// Store the IP address ID.
state.Put("ip_address_id", ipAddr.Id)
diff --git a/vendor/github.com/mitchellh/packer/builder/cloudstack/step_create_instance.go b/vendor/github.com/mitchellh/packer/builder/cloudstack/step_create_instance.go
index 3b624de3..3e37fad1 100644
--- a/vendor/github.com/mitchellh/packer/builder/cloudstack/step_create_instance.go
+++ b/vendor/github.com/mitchellh/packer/builder/cloudstack/step_create_instance.go
@@ -22,7 +22,8 @@ type userDataTemplateData struct {
// stepCreateInstance represents a Packer build step that creates CloudStack instances.
type stepCreateInstance struct {
- Ctx interpolate.Context
+ Debug bool
+ Ctx interpolate.Context
}
// Run executes the Packer build step that creates a CloudStack instance.
@@ -36,7 +37,7 @@ func (s *stepCreateInstance) Run(state multistep.StateBag) multistep.StepAction
// Create a new parameter struct.
p := client.VirtualMachine.NewDeployVirtualMachineParams(
config.ServiceOffering,
- config.instanceSource,
+ state.Get("source").(string),
config.Zone,
)
@@ -44,8 +45,12 @@ func (s *stepCreateInstance) Run(state multistep.StateBag) multistep.StepAction
p.SetName(config.InstanceName)
p.SetDisplayname("Created by Packer")
- if config.Keypair != "" {
- p.SetKeypair(config.Keypair)
+ if keypair, ok := state.GetOk("keypair"); ok {
+ p.SetKeypair(keypair.(string))
+ }
+
+ if securitygroups, ok := state.GetOk("security_groups"); ok {
+ p.SetSecuritygroupids(securitygroups.([]string))
}
// If we use an ISO, configure the disk offering.
@@ -115,6 +120,12 @@ func (s *stepCreateInstance) Run(state multistep.StateBag) multistep.StepAction
ui.Message("Instance has been created!")
+ // In debug-mode, we output the password
+ if s.Debug {
+ ui.Message(fmt.Sprintf(
+ "Password (since debug is enabled) \"%s\"", instance.Password))
+ }
+
// Set the auto generated password if a password was not explicitly configured.
switch config.Comm.Type {
case "ssh":
@@ -129,7 +140,7 @@ func (s *stepCreateInstance) Run(state multistep.StateBag) multistep.StepAction
// Set the host address when using the local IP address to connect.
if config.UseLocalIPAddress {
- config.hostAddress = instance.Nic[0].Ipaddress
+ state.Put("ipaddress", instance.Nic[0].Ipaddress)
}
// Store the instance ID so we can remove it later.
diff --git a/vendor/github.com/mitchellh/packer/builder/cloudstack/step_create_security_group.go b/vendor/github.com/mitchellh/packer/builder/cloudstack/step_create_security_group.go
new file mode 100644
index 00000000..1bf23100
--- /dev/null
+++ b/vendor/github.com/mitchellh/packer/builder/cloudstack/step_create_security_group.go
@@ -0,0 +1,94 @@
+package cloudstack
+
+import (
+ "fmt"
+
+ "github.com/hashicorp/packer/common/uuid"
+ "github.com/hashicorp/packer/packer"
+ "github.com/mitchellh/multistep"
+ "github.com/xanzy/go-cloudstack/cloudstack"
+)
+
+type stepCreateSecurityGroup struct {
+ tempSG string
+}
+
+func (s *stepCreateSecurityGroup) Run(state multistep.StateBag) multistep.StepAction {
+ client := state.Get("client").(*cloudstack.CloudStackClient)
+ config := state.Get("config").(*Config)
+ ui := state.Get("ui").(packer.Ui)
+
+ if len(config.SecurityGroups) > 0 {
+ state.Put("security_groups", config.SecurityGroups)
+ return multistep.ActionContinue
+ }
+
+ if !config.CreateSecurityGroup {
+ return multistep.ActionContinue
+ }
+
+ ui.Say("Creating temporary Security Group...")
+
+ p := client.SecurityGroup.NewCreateSecurityGroupParams(
+ fmt.Sprintf("packer-%s", uuid.TimeOrderedUUID()),
+ )
+ p.SetDescription("Temporary SG created by Packer")
+ if config.Project != "" {
+ p.SetProjectid(config.Project)
+ }
+
+ sg, err := client.SecurityGroup.CreateSecurityGroup(p)
+ if err != nil {
+ err := fmt.Errorf("Failed to create security group: %s", err)
+ state.Put("error", err)
+ ui.Error(err.Error())
+ return multistep.ActionHalt
+ }
+
+ s.tempSG = sg.Id
+ state.Put("security_groups", []string{sg.Id})
+
+ // Create Ingress rule
+ i := client.SecurityGroup.NewAuthorizeSecurityGroupIngressParams()
+ i.SetCidrlist(config.CIDRList)
+ i.SetProtocol("TCP")
+ i.SetSecuritygroupid(sg.Id)
+ i.SetStartport(config.Comm.Port())
+ i.SetEndport(config.Comm.Port())
+ if config.Project != "" {
+ i.SetProjectid(config.Project)
+ }
+
+ _, err = client.SecurityGroup.AuthorizeSecurityGroupIngress(i)
+ if err != nil {
+ err := fmt.Errorf("Failed to authorize security group ingress rule: %s", err)
+ state.Put("error", err)
+ ui.Error(err.Error())
+ return multistep.ActionHalt
+ }
+
+ return multistep.ActionContinue
+}
+
+// Cleanup any resources that may have been created during the Run phase.
+func (s *stepCreateSecurityGroup) Cleanup(state multistep.StateBag) {
+ client := state.Get("client").(*cloudstack.CloudStackClient)
+ config := state.Get("config").(*Config)
+ ui := state.Get("ui").(packer.Ui)
+
+ if s.tempSG == "" {
+ return
+ }
+
+ ui.Say(fmt.Sprintf("Cleanup temporary security group: %s ...", s.tempSG))
+ p := client.SecurityGroup.NewDeleteSecurityGroupParams()
+ p.SetId(s.tempSG)
+ if config.Project != "" {
+ p.SetProjectid(config.Project)
+ }
+
+ if _, err := client.SecurityGroup.DeleteSecurityGroup(p); err != nil {
+ ui.Error(err.Error())
+ ui.Error(fmt.Sprintf("Error deleting security group: %s. Please destroy it manually.\n", s.tempSG))
+ }
+}
diff --git a/vendor/github.com/mitchellh/packer/builder/cloudstack/step_keypair.go b/vendor/github.com/mitchellh/packer/builder/cloudstack/step_keypair.go
new file mode 100644
index 00000000..675994fc
--- /dev/null
+++ b/vendor/github.com/mitchellh/packer/builder/cloudstack/step_keypair.go
@@ -0,0 +1,133 @@
+package cloudstack
+
+import (
+ "fmt"
+ "io/ioutil"
+ "os"
+ "runtime"
+
+ "github.com/hashicorp/packer/packer"
+ "github.com/mitchellh/multistep"
+ "github.com/xanzy/go-cloudstack/cloudstack"
+)
+
+type stepKeypair struct {
+ Debug bool
+ DebugKeyPath string
+ KeyPair string
+ PrivateKeyFile string
+ SSHAgentAuth bool
+ TemporaryKeyPairName string
+}
+
+func (s *stepKeypair) Run(state multistep.StateBag) multistep.StepAction {
+ ui := state.Get("ui").(packer.Ui)
+
+ if s.PrivateKeyFile != "" {
+ privateKeyBytes, err := ioutil.ReadFile(s.PrivateKeyFile)
+ if err != nil {
+ state.Put("error", fmt.Errorf(
+ "Error loading configured private key file: %s", err))
+ return multistep.ActionHalt
+ }
+
+ state.Put("keypair", s.KeyPair)
+ state.Put("privateKey", string(privateKeyBytes))
+
+ return multistep.ActionContinue
+ }
+
+ if s.SSHAgentAuth && s.KeyPair == "" {
+ ui.Say("Using SSH Agent with keypair in Source image")
+ return multistep.ActionContinue
+ }
+
+ if s.SSHAgentAuth && s.KeyPair != "" {
+ ui.Say(fmt.Sprintf("Using SSH Agent for existing keypair %s", s.KeyPair))
+ state.Put("keypair", s.KeyPair)
+ return multistep.ActionContinue
+ }
+
+ if s.TemporaryKeyPairName == "" {
+ ui.Say("Not using a keypair")
+ state.Put("keypair", "")
+ return multistep.ActionContinue
+ }
+
+ client := state.Get("client").(*cloudstack.CloudStackClient)
+
+ ui.Say(fmt.Sprintf("Creating temporary keypair: %s ...", s.TemporaryKeyPairName))
+
+ p := client.SSH.NewCreateSSHKeyPairParams(s.TemporaryKeyPairName)
+ keypair, err := client.SSH.CreateSSHKeyPair(p)
+ if err != nil {
+ err := fmt.Errorf("Error creating temporary keypair: %s", err)
+ state.Put("error", err)
+ ui.Error(err.Error())
+ return multistep.ActionHalt
+ }
+
+ if keypair.Privatekey == "" {
+ err := fmt.Errorf("The temporary keypair returned was blank")
+ state.Put("error", err)
+ ui.Error(err.Error())
+ return multistep.ActionHalt
+ }
+
+ ui.Say(fmt.Sprintf("Created temporary keypair: %s", s.TemporaryKeyPairName))
+
+ // If we're in debug mode, output the private key to the working directory.
+ if s.Debug {
+ ui.Message(fmt.Sprintf("Saving key for debug purposes: %s", s.DebugKeyPath))
+ f, err := os.Create(s.DebugKeyPath)
+ if err != nil {
+ state.Put("error", fmt.Errorf("Error saving debug key: %s", err))
+ return multistep.ActionHalt
+ }
+ defer f.Close()
+
+ // Write the key out
+ if _, err := f.Write([]byte(keypair.Privatekey)); err != nil {
+ err := fmt.Errorf("Error saving debug key: %s", err)
+ state.Put("error", err)
+ ui.Error(err.Error())
+ return multistep.ActionHalt
+ }
+
+ // Chmod it so that it is SSH ready
+ if runtime.GOOS != "windows" {
+ if err := f.Chmod(0600); err != nil {
+ err := fmt.Errorf("Error setting permissions of debug key: %s", err)
+ state.Put("error", err)
+ ui.Error(err.Error())
+ return multistep.ActionHalt
+ }
+ }
+ }
+
+ // Set some state data for use in future steps
+ state.Put("keypair", s.TemporaryKeyPairName)
+ state.Put("privateKey", keypair.Privatekey)
+
+ return multistep.ActionContinue
+}
+
+func (s *stepKeypair) Cleanup(state multistep.StateBag) {
+ if s.TemporaryKeyPairName == "" {
+ return
+ }
+
+ ui := state.Get("ui").(packer.Ui)
+ client := state.Get("client").(*cloudstack.CloudStackClient)
+
+ ui.Say(fmt.Sprintf("Deleting temporary keypair: %s ...", s.TemporaryKeyPairName))
+
+ _, err := client.SSH.DeleteSSHKeyPair(client.SSH.NewDeleteSSHKeyPairParams(
+ s.TemporaryKeyPairName,
+ ))
+ if err != nil {
+ ui.Error(err.Error())
+ ui.Error(fmt.Sprintf(
+ "Error cleaning up keypair. Please delete the key manually: %s", s.TemporaryKeyPairName))
+ }
+}
diff --git a/vendor/github.com/mitchellh/packer/builder/cloudstack/step_prepare_config.go b/vendor/github.com/mitchellh/packer/builder/cloudstack/step_prepare_config.go
index de397308..4d6353c6 100644
--- a/vendor/github.com/mitchellh/packer/builder/cloudstack/step_prepare_config.go
+++ b/vendor/github.com/mitchellh/packer/builder/cloudstack/step_prepare_config.go
@@ -22,15 +22,6 @@ func (s *stepPrepareConfig) Run(state multistep.StateBag) multistep.StepAction {
var err error
var errs *packer.MultiError
- if config.Comm.SSHPrivateKey != "" {
- privateKey, err := ioutil.ReadFile(config.Comm.SSHPrivateKey)
- if err != nil {
- errs = packer.MultiErrorAppend(errs, fmt.Errorf("Error loading configured private key file: %s", err))
- }
-
- state.Put("privateKey", privateKey)
- }
-
// First get the project and zone UUID's so we can use them in other calls when needed.
if config.Project != "" && !isUUID(config.Project) {
config.Project, _, err = client.Project.GetProjectID(config.Project)
@@ -62,26 +53,34 @@ func (s *stepPrepareConfig) Run(state multistep.StateBag) multistep.StepAction {
}
}
- if config.PublicIPAddress != "" && !isUUID(config.PublicIPAddress) {
- // Save the public IP address before replacing it with it's UUID.
- config.hostAddress = config.PublicIPAddress
+ if config.PublicIPAddress != "" {
+ if isUUID(config.PublicIPAddress) {
+ ip, _, err := client.Address.GetPublicIpAddressByID(config.PublicIPAddress)
+ if err != nil {
+ errs = packer.MultiErrorAppend(errs, fmt.Errorf("Failed to retrieve IP address: %s", err))
+ }
+ state.Put("ipaddress", ip.Ipaddress)
+ } else {
+ // Save the public IP address before replacing it with it's UUID.
+ state.Put("ipaddress", config.PublicIPAddress)
- p := client.Address.NewListPublicIpAddressesParams()
- p.SetIpaddress(config.PublicIPAddress)
+ p := client.Address.NewListPublicIpAddressesParams()
+ p.SetIpaddress(config.PublicIPAddress)
- if config.Project != "" {
- p.SetProjectid(config.Project)
- }
+ if config.Project != "" {
+ p.SetProjectid(config.Project)
+ }
- ipAddrs, err := client.Address.ListPublicIpAddresses(p)
- if err != nil {
- errs = packer.MultiErrorAppend(errs, &retrieveErr{"IP address", config.PublicIPAddress, err})
- }
- if err == nil && ipAddrs.Count != 1 {
- errs = packer.MultiErrorAppend(errs, &retrieveErr{"IP address", config.PublicIPAddress, ipAddrs})
- }
- if err == nil && ipAddrs.Count == 1 {
- config.PublicIPAddress = ipAddrs.PublicIpAddresses[0].Id
+ ipAddrs, err := client.Address.ListPublicIpAddresses(p)
+ if err != nil {
+ errs = packer.MultiErrorAppend(errs, &retrieveErr{"IP address", config.PublicIPAddress, err})
+ }
+ if err == nil && ipAddrs.Count != 1 {
+ errs = packer.MultiErrorAppend(errs, &retrieveErr{"IP address", config.PublicIPAddress, ipAddrs})
+ }
+ if err == nil && ipAddrs.Count == 1 {
+ config.PublicIPAddress = ipAddrs.PublicIpAddresses[0].Id
+ }
}
}
@@ -92,6 +91,18 @@ func (s *stepPrepareConfig) Run(state multistep.StateBag) multistep.StepAction {
}
}
+ // Then try to get the SG's UUID's.
+ if len(config.SecurityGroups) > 0 {
+ for i := range config.SecurityGroups {
+ if !isUUID(config.SecurityGroups[i]) {
+ config.SecurityGroups[i], _, err = client.SecurityGroup.GetSecurityGroupID(config.SecurityGroups[i], cloudstack.WithProject(config.Project))
+ if err != nil {
+ errs = packer.MultiErrorAppend(errs, &retrieveErr{"network", config.SecurityGroups[i], err})
+ }
+ }
+ }
+ }
+
if !isUUID(config.ServiceOffering) {
config.ServiceOffering, _, err = client.ServiceOffering.GetServiceOfferingID(config.ServiceOffering)
if err != nil {
@@ -101,23 +112,25 @@ func (s *stepPrepareConfig) Run(state multistep.StateBag) multistep.StepAction {
if config.SourceISO != "" {
if isUUID(config.SourceISO) {
- config.instanceSource = config.SourceISO
+ state.Put("source", config.SourceISO)
} else {
- config.instanceSource, _, err = client.ISO.GetIsoID(config.SourceISO, "executable", config.Zone)
+ isoID, _, err := client.ISO.GetIsoID(config.SourceISO, "executable", config.Zone)
if err != nil {
errs = packer.MultiErrorAppend(errs, &retrieveErr{"ISO", config.SourceISO, err})
}
+ state.Put("source", isoID)
}
}
if config.SourceTemplate != "" {
if isUUID(config.SourceTemplate) {
- config.instanceSource = config.SourceTemplate
+ state.Put("source", config.SourceTemplate)
} else {
- config.instanceSource, _, err = client.Template.GetTemplateID(config.SourceTemplate, "executable", config.Zone)
+ templateID, _, err := client.Template.GetTemplateID(config.SourceTemplate, "executable", config.Zone)
if err != nil {
errs = packer.MultiErrorAppend(errs, &retrieveErr{"template", config.SourceTemplate, err})
}
+ state.Put("source", templateID)
}
}
diff --git a/vendor/github.com/mitchellh/packer/builder/digitalocean/step_snapshot.go b/vendor/github.com/mitchellh/packer/builder/digitalocean/step_snapshot.go
index bd529813..eb91fdea 100644
--- a/vendor/github.com/mitchellh/packer/builder/digitalocean/step_snapshot.go
+++ b/vendor/github.com/mitchellh/packer/builder/digitalocean/step_snapshot.go
@@ -85,12 +85,12 @@ func (s *stepSnapshot) Run(state multistep.StateBag) multistep.StepAction {
}
imageTransfer, _, err := client.ImageActions.Transfer(context.TODO(), images[0].ID, transferRequest)
if err != nil {
- err := fmt.Errorf("Error transfering snapshot: %s", err)
+ err := fmt.Errorf("Error transferring snapshot: %s", err)
state.Put("error", err)
ui.Error(err.Error())
return multistep.ActionHalt
}
- ui.Say(fmt.Sprintf("Transfering Snapshot ID: %d", imageTransfer.ID))
+ ui.Say(fmt.Sprintf("transferring Snapshot ID: %d", imageTransfer.ID))
if err := waitForImageState(godo.ActionCompleted, imageTransfer.ID, action.ID,
client, 20*time.Minute); err != nil {
// If we get an error the first time, actually report it
diff --git a/vendor/github.com/mitchellh/packer/builder/docker/communicator.go b/vendor/github.com/mitchellh/packer/builder/docker/communicator.go
index d33f79e9..8a1546ba 100644
--- a/vendor/github.com/mitchellh/packer/builder/docker/communicator.go
+++ b/vendor/github.com/mitchellh/packer/builder/docker/communicator.go
@@ -18,7 +18,7 @@ import (
)
type Communicator struct {
- ContainerId string
+ ContainerID string
HostDir string
ContainerDir string
Version *version.Version
@@ -29,9 +29,9 @@ type Communicator struct {
func (c *Communicator) Start(remote *packer.RemoteCmd) error {
var cmd *exec.Cmd
if c.Config.Pty {
- cmd = exec.Command("docker", "exec", "-i", "-t", c.ContainerId, "/bin/sh", "-c", fmt.Sprintf("(%s)", remote.Command))
+ cmd = exec.Command("docker", "exec", "-i", "-t", c.ContainerID, "/bin/sh", "-c", fmt.Sprintf("(%s)", remote.Command))
} else {
- cmd = exec.Command("docker", "exec", "-i", c.ContainerId, "/bin/sh", "-c", fmt.Sprintf("(%s)", remote.Command))
+ cmd = exec.Command("docker", "exec", "-i", c.ContainerID, "/bin/sh", "-c", fmt.Sprintf("(%s)", remote.Command))
}
var (
@@ -60,130 +60,138 @@ func (c *Communicator) Start(remote *packer.RemoteCmd) error {
return nil
}
+// Upload uploads a file to the docker container
func (c *Communicator) Upload(dst string, src io.Reader, fi *os.FileInfo) error {
+ if fi == nil {
+ return c.uploadReader(dst, src)
+ }
+ return c.uploadFile(dst, src, fi)
+}
+
+// uploadReader writes an io.Reader to a temporary file before uploading
+func (c *Communicator) uploadReader(dst string, src io.Reader) error {
// Create a temporary file to store the upload
tempfile, err := ioutil.TempFile(c.HostDir, "upload")
if err != nil {
- return err
+ return fmt.Errorf("Failed to open temp file for writing: %s", err)
}
defer os.Remove(tempfile.Name())
+ defer tempfile.Close()
- // Copy the contents to the temporary file
- _, err = io.Copy(tempfile, src)
+ if _, err := io.Copy(tempfile, src); err != nil {
+ return fmt.Errorf("Failed to copy upload file to tempfile: %s", err)
+ }
+ tempfile.Seek(0, 0)
+ fi, err := tempfile.Stat()
if err != nil {
- return err
+ return fmt.Errorf("Error getting tempfile info: %s", err)
}
+ return c.uploadFile(dst, tempfile, &fi)
+}
- if fi != nil {
- tempfile.Chmod((*fi).Mode())
+// uploadFile uses docker cp to copy the file from the host to the container
+func (c *Communicator) uploadFile(dst string, src io.Reader, fi *os.FileInfo) error {
+
+ // command format: docker cp /path/to/infile containerid:/path/to/outfile
+ log.Printf("Copying to %s on container %s.", dst, c.ContainerID)
+
+ localCmd := exec.Command("docker", "cp", "-",
+ fmt.Sprintf("%s:%s", c.ContainerID, filepath.Dir(dst)))
+
+ stderrP, err := localCmd.StderrPipe()
+ if err != nil {
+ return fmt.Errorf("Failed to open pipe: %s", err)
}
- tempfile.Close()
- // Copy the file into place by copying the temporary file we put
- // into the shared folder into the proper location in the container
- cmd := &packer.RemoteCmd{
- Command: fmt.Sprintf("command cp %s/%s %s", c.ContainerDir,
- filepath.Base(tempfile.Name()), dst),
+ stdin, err := localCmd.StdinPipe()
+ if err != nil {
+ return fmt.Errorf("Failed to open pipe: %s", err)
}
- if err := c.Start(cmd); err != nil {
+ if err := localCmd.Start(); err != nil {
return err
}
- // Wait for the copy to complete
- cmd.Wait()
- if cmd.ExitStatus != 0 {
- return fmt.Errorf("Upload failed with non-zero exit status: %d", cmd.ExitStatus)
+ archive := tar.NewWriter(stdin)
+ header, err := tar.FileInfoHeader(*fi, "")
+ if err != nil {
+ return err
}
+ header.Name = filepath.Base(dst)
+ archive.WriteHeader(header)
+ numBytes, err := io.Copy(archive, src)
+ if err != nil {
+ return fmt.Errorf("Failed to pipe upload: %s", err)
+ }
+ log.Printf("Copied %d bytes for %s", numBytes, dst)
- return nil
-}
+ if err := archive.Close(); err != nil {
+ return fmt.Errorf("Failed to close archive: %s", err)
+ }
+ if err := stdin.Close(); err != nil {
+ return fmt.Errorf("Failed to close stdin: %s", err)
+ }
-func (c *Communicator) UploadDir(dst string, src string, exclude []string) error {
- // Create the temporary directory that will store the contents of "src"
- // for copying into the container.
- td, err := ioutil.TempDir(c.HostDir, "dirupload")
+ stderrOut, err := ioutil.ReadAll(stderrP)
if err != nil {
return err
}
- defer os.RemoveAll(td)
- walkFn := func(path string, info os.FileInfo, err error) error {
- if err != nil {
- return err
- }
-
- relpath, err := filepath.Rel(src, path)
- if err != nil {
- return err
- }
- hostpath := filepath.Join(td, relpath)
-
- // If it is a directory, just create it
- if info.IsDir() {
- return os.MkdirAll(hostpath, info.Mode())
- }
-
- if info.Mode()&os.ModeSymlink == os.ModeSymlink {
- dest, err := os.Readlink(path)
-
- if err != nil {
- return err
- }
-
- return os.Symlink(dest, hostpath)
- }
-
- // It is a file, copy it over, including mode.
- src, err := os.Open(path)
- if err != nil {
- return err
- }
- defer src.Close()
-
- dst, err := os.Create(hostpath)
- if err != nil {
- return err
- }
- defer dst.Close()
-
- if _, err := io.Copy(dst, src); err != nil {
- return err
- }
-
- si, err := src.Stat()
- if err != nil {
- return err
- }
-
- return dst.Chmod(si.Mode())
+ if err := localCmd.Wait(); err != nil {
+ return fmt.Errorf("Failed to upload to '%s' in container: %s. %s.", dst, stderrOut, err)
}
- // Copy the entire directory tree to the temporary directory
- if err := filepath.Walk(src, walkFn); err != nil {
- return err
- }
+ return nil
+}
- // Determine the destination directory
- containerSrc := filepath.Join(c.ContainerDir, filepath.Base(td))
- containerDst := dst
- if src[len(src)-1] != '/' {
- containerDst = filepath.Join(dst, filepath.Base(src))
+func (c *Communicator) UploadDir(dst string, src string, exclude []string) error {
+ /*
+ from https://docs.docker.com/engine/reference/commandline/cp/#extended-description
+ SRC_PATH specifies a directory
+ DEST_PATH does not exist
+ DEST_PATH is created as a directory and the contents of the source directory are copied into this directory
+ DEST_PATH exists and is a file
+ Error condition: cannot copy a directory to a file
+ DEST_PATH exists and is a directory
+ SRC_PATH does not end with /. (that is: slash followed by dot)
+ the source directory is copied into this directory
+ SRC_PATH does end with /. (that is: slash followed by dot)
+ the content of the source directory is copied into this directory
+
+ translating that in to our semantics:
+
+ if source ends in /
+ docker cp src. dest
+ otherwise, cp source dest
+
+ */
+
+ var dockerSource string
+
+ if src[len(src)-1] == '/' {
+ dockerSource = fmt.Sprintf("%s.", src)
+ } else {
+ dockerSource = fmt.Sprintf("%s", src)
}
// Make the directory, then copy into it
- cmd := &packer.RemoteCmd{
- Command: fmt.Sprintf("set -e; mkdir -p %s; cd %s; command cp -R `ls -A .` %s",
- containerDst, containerSrc, containerDst),
+ localCmd := exec.Command("docker", "cp", dockerSource, fmt.Sprintf("%s:%s", c.ContainerID, dst))
+
+ stderrP, err := localCmd.StderrPipe()
+ if err != nil {
+ return fmt.Errorf("Failed to open pipe: %s", err)
+ }
+ if err := localCmd.Start(); err != nil {
+ return fmt.Errorf("Failed to copy: %s", err)
}
- if err := c.Start(cmd); err != nil {
+ stderrOut, err := ioutil.ReadAll(stderrP)
+ if err != nil {
return err
}
// Wait for the copy to complete
- cmd.Wait()
- if cmd.ExitStatus != 0 {
- return fmt.Errorf("Upload failed with non-zero exit status: %d", cmd.ExitStatus)
+ if err := localCmd.Wait(); err != nil {
+ return fmt.Errorf("Failed to upload to '%s' in container: %s. %s.", dst, stderrOut, err)
}
return nil
@@ -193,8 +201,8 @@ func (c *Communicator) UploadDir(dst string, src string, exclude []string) error
// path and want to write to an io.Writer, not a file. We use - to make docker
// cp to write to stdout, and then copy the stream to our destination io.Writer.
func (c *Communicator) Download(src string, dst io.Writer) error {
- log.Printf("Downloading file from container: %s:%s", c.ContainerId, src)
- localCmd := exec.Command("docker", "cp", fmt.Sprintf("%s:%s", c.ContainerId, src), "-")
+ log.Printf("Downloading file from container: %s:%s", c.ContainerID, src)
+ localCmd := exec.Command("docker", "cp", fmt.Sprintf("%s:%s", c.ContainerID, src), "-")
pipe, err := localCmd.StdoutPipe()
if err != nil {
diff --git a/vendor/github.com/mitchellh/packer/builder/docker/config.go b/vendor/github.com/mitchellh/packer/builder/docker/config.go
index 7ba1f458..3f8f4d42 100644
--- a/vendor/github.com/mitchellh/packer/builder/docker/config.go
+++ b/vendor/github.com/mitchellh/packer/builder/docker/config.go
@@ -23,18 +23,19 @@ type Config struct {
common.PackerConfig `mapstructure:",squash"`
Comm communicator.Config `mapstructure:",squash"`
- Commit bool
- Discard bool
- ExportPath string `mapstructure:"export_path"`
- Image string
- Pty bool
- Pull bool
- RunCommand []string `mapstructure:"run_command"`
- Volumes map[string]string
- Privileged bool `mapstructure:"privileged"`
- Author string
- Changes []string
- Message string
+ Commit bool
+ Discard bool
+ ExportPath string `mapstructure:"export_path"`
+ Image string
+ Pty bool
+ Pull bool
+ RunCommand []string `mapstructure:"run_command"`
+ Volumes map[string]string
+ Privileged bool `mapstructure:"privileged"`
+ Author string
+ Changes []string
+ Message string
+ ContainerDir string `mapstructure:"container_dir"`
// This is used to login to dockerhub to pull a private base container. For
// pushing to dockerhub, see the docker post-processors
@@ -112,6 +113,10 @@ func NewConfig(raws ...interface{}) (*Config, []string, error) {
}
}
+ if c.ContainerDir == "" {
+ c.ContainerDir = "/packer-files"
+ }
+
if c.EcrLogin && c.LoginServer == "" {
errs = packer.MultiErrorAppend(errs, fmt.Errorf("ECR login requires login server to be provided."))
}
diff --git a/vendor/github.com/mitchellh/packer/builder/docker/step_connect_docker.go b/vendor/github.com/mitchellh/packer/builder/docker/step_connect_docker.go
index f84d369c..7a947d50 100644
--- a/vendor/github.com/mitchellh/packer/builder/docker/step_connect_docker.go
+++ b/vendor/github.com/mitchellh/packer/builder/docker/step_connect_docker.go
@@ -22,9 +22,9 @@ func (s *StepConnectDocker) Run(state multistep.StateBag) multistep.StepAction {
// Create the communicator that talks to Docker via various
// os/exec tricks.
comm := &Communicator{
- ContainerId: containerId,
+ ContainerID: containerId,
HostDir: tempDir,
- ContainerDir: "/packer-files",
+ ContainerDir: config.ContainerDir,
Version: version,
Config: config,
}
diff --git a/vendor/github.com/mitchellh/packer/builder/docker/step_run.go b/vendor/github.com/mitchellh/packer/builder/docker/step_run.go
index 92803f93..5a56d8d7 100644
--- a/vendor/github.com/mitchellh/packer/builder/docker/step_run.go
+++ b/vendor/github.com/mitchellh/packer/builder/docker/step_run.go
@@ -26,7 +26,7 @@ func (s *StepRun) Run(state multistep.StateBag) multistep.StepAction {
for host, container := range config.Volumes {
runConfig.Volumes[host] = container
}
- runConfig.Volumes[tempDir] = "/packer-files"
+ runConfig.Volumes[tempDir] = config.ContainerDir
ui.Say("Starting docker container...")
containerId, err := driver.StartContainer(&runConfig)
diff --git a/vendor/github.com/mitchellh/packer/builder/googlecompute/config.go b/vendor/github.com/mitchellh/packer/builder/googlecompute/config.go
index 4250f182..c4aa79d2 100644
--- a/vendor/github.com/mitchellh/packer/builder/googlecompute/config.go
+++ b/vendor/github.com/mitchellh/packer/builder/googlecompute/config.go
@@ -26,6 +26,8 @@ type Config struct {
AccountFile string `mapstructure:"account_file"`
ProjectId string `mapstructure:"project_id"`
+ AcceleratorType string `mapstructure:"accelerator_type"`
+ AcceleratorCount int64 `mapstructure:"accelerator_count"`
Address string `mapstructure:"address"`
DiskName string `mapstructure:"disk_name"`
DiskSizeGb int64 `mapstructure:"disk_size"`
@@ -34,6 +36,7 @@ type Config struct {
ImageDescription string `mapstructure:"image_description"`
ImageFamily string `mapstructure:"image_family"`
InstanceName string `mapstructure:"instance_name"`
+ Labels map[string]string `mapstructure:"labels"`
MachineType string `mapstructure:"machine_type"`
Metadata map[string]string `mapstructure:"metadata"`
Network string `mapstructure:"network"`
@@ -205,6 +208,14 @@ func NewConfig(raws ...interface{}) (*Config, []string, error) {
errs = packer.MultiErrorAppend(fmt.Errorf("'use_internal_ip' must be true if 'omit_external_ip' is true"))
}
+ if c.AcceleratorCount > 0 && len(c.AcceleratorType) == 0 {
+ errs = packer.MultiErrorAppend(fmt.Errorf("'accelerator_type' must be set when 'accelerator_count' is more than 0"))
+ }
+
+ if c.AcceleratorCount > 0 && c.OnHostMaintenance != "TERMINATE" {
+ errs = packer.MultiErrorAppend(fmt.Errorf("'on_host_maintenance' must be set to 'TERMINATE' when 'accelerator_count' is more than 0"))
+ }
+
// Check for any errors.
if errs != nil && len(errs.Errors) > 0 {
return nil, nil, errs
diff --git a/vendor/github.com/mitchellh/packer/builder/googlecompute/config_test.go b/vendor/github.com/mitchellh/packer/builder/googlecompute/config_test.go
index e65da279..7255add3 100644
--- a/vendor/github.com/mitchellh/packer/builder/googlecompute/config_test.go
+++ b/vendor/github.com/mitchellh/packer/builder/googlecompute/config_test.go
@@ -1,6 +1,7 @@
package googlecompute
import (
+ "fmt"
"io/ioutil"
"strings"
"testing"
@@ -190,6 +191,65 @@ func TestConfigPrepare(t *testing.T) {
}
}
+func TestConfigPrepareAccelerator(t *testing.T) {
+ cases := []struct {
+ Keys []string
+ Values []interface{}
+ Err bool
+ }{
+ {
+ []string{"accelerator_count", "on_host_maintenance", "accelerator_type"},
+ []interface{}{1, "MIGRATE", "something_valid"},
+ true,
+ },
+ {
+ []string{"accelerator_count", "on_host_maintenance", "accelerator_type"},
+ []interface{}{1, "TERMINATE", "something_valid"},
+ false,
+ },
+ {
+ []string{"accelerator_count", "on_host_maintenance", "accelerator_type"},
+ []interface{}{1, "TERMINATE", nil},
+ true,
+ },
+ {
+ []string{"accelerator_count", "on_host_maintenance", "accelerator_type"},
+ []interface{}{1, "TERMINATE", ""},
+ true,
+ },
+ {
+ []string{"accelerator_count", "on_host_maintenance", "accelerator_type"},
+ []interface{}{1, "TERMINATE", "something_valid"},
+ false,
+ },
+ }
+
+ for _, tc := range cases {
+ raw := testConfig(t)
+
+ errStr := ""
+ for k := range tc.Keys {
+
+ // Create the string for error reporting
+ // convert value to string if it can be converted
+ errStr += fmt.Sprintf("%s:%v, ", tc.Keys[k], tc.Values[k])
+ if tc.Values[k] == nil {
+ delete(raw, tc.Keys[k])
+ } else {
+ raw[tc.Keys[k]] = tc.Values[k]
+ }
+ }
+
+ _, warns, errs := NewConfig(raw)
+
+ if tc.Err {
+ testConfigErr(t, warns, errs, strings.TrimRight(errStr, ", "))
+ } else {
+ testConfigOk(t, warns, errs)
+ }
+ }
+}
+
func TestConfigDefaults(t *testing.T) {
cases := []struct {
Read func(c *Config) interface{}
diff --git a/vendor/github.com/mitchellh/packer/builder/googlecompute/driver.go b/vendor/github.com/mitchellh/packer/builder/googlecompute/driver.go
index b07c9d77..60707ac8 100644
--- a/vendor/github.com/mitchellh/packer/builder/googlecompute/driver.go
+++ b/vendor/github.com/mitchellh/packer/builder/googlecompute/driver.go
@@ -58,11 +58,14 @@ type Driver interface {
}
type InstanceConfig struct {
+ AcceleratorType string
+ AcceleratorCount int64
Address string
Description string
DiskSizeGb int64
DiskType string
Image *Image
+ Labels map[string]string
MachineType string
Metadata map[string]string
Name string
diff --git a/vendor/github.com/mitchellh/packer/builder/googlecompute/driver_gce.go b/vendor/github.com/mitchellh/packer/builder/googlecompute/driver_gce.go
index fe3987a1..0df21eba 100644
--- a/vendor/github.com/mitchellh/packer/builder/googlecompute/driver_gce.go
+++ b/vendor/github.com/mitchellh/packer/builder/googlecompute/driver_gce.go
@@ -380,6 +380,15 @@ func (d *driverGCE) RunInstance(c *InstanceConfig) (<-chan error, error) {
})
}
+ var guestAccelerators []*compute.AcceleratorConfig
+ if c.AcceleratorCount > 0 {
+ ac := &compute.AcceleratorConfig{
+ AcceleratorCount: c.AcceleratorCount,
+ AcceleratorType: c.AcceleratorType,
+ }
+ guestAccelerators = append(guestAccelerators, ac)
+ }
+
// Create the instance information
instance := compute.Instance{
Description: c.Description,
@@ -397,7 +406,9 @@ func (d *driverGCE) RunInstance(c *InstanceConfig) (<-chan error, error) {
},
},
},
- MachineType: machineType.SelfLink,
+ GuestAccelerators: guestAccelerators,
+ Labels: c.Labels,
+ MachineType: machineType.SelfLink,
Metadata: &compute.Metadata{
Items: metadata,
},
diff --git a/vendor/github.com/mitchellh/packer/builder/googlecompute/startup.go b/vendor/github.com/mitchellh/packer/builder/googlecompute/startup.go
index a94c9114..687afec9 100644
--- a/vendor/github.com/mitchellh/packer/builder/googlecompute/startup.go
+++ b/vendor/github.com/mitchellh/packer/builder/googlecompute/startup.go
@@ -21,7 +21,7 @@ GetMetadata () {
echo "$(curl -f -H "Metadata-Flavor: Google" ${BASEMETADATAURL}/${1} 2> /dev/null)"
}
-ZONE=$(GetMetadata zone | grep -oP "[^/]*$")
+ZONE=$(basename $(GetMetadata zone))
SetMetadata () {
gcloud compute instances add-metadata ${HOSTNAME} --metadata ${1}=${2} --zone ${ZONE}
diff --git a/vendor/github.com/mitchellh/packer/builder/googlecompute/step_create_instance.go b/vendor/github.com/mitchellh/packer/builder/googlecompute/step_create_instance.go
index adb08e7b..a4509354 100644
--- a/vendor/github.com/mitchellh/packer/builder/googlecompute/step_create_instance.go
+++ b/vendor/github.com/mitchellh/packer/builder/googlecompute/step_create_instance.go
@@ -99,11 +99,14 @@ func (s *StepCreateInstance) Run(state multistep.StateBag) multistep.StepAction
var metadata map[string]string
metadata, err = c.createInstanceMetadata(sourceImage, sshPublicKey)
errCh, err = d.RunInstance(&InstanceConfig{
+ AcceleratorType: c.AcceleratorType,
+ AcceleratorCount: c.AcceleratorCount,
Address: c.Address,
Description: "New instance created by Packer",
DiskSizeGb: c.DiskSizeGb,
DiskType: c.DiskType,
Image: sourceImage,
+ Labels: c.Labels,
MachineType: c.MachineType,
Metadata: metadata,
Name: name,
diff --git a/vendor/github.com/mitchellh/packer/builder/googlecompute/step_create_instance_test.go b/vendor/github.com/mitchellh/packer/builder/googlecompute/step_create_instance_test.go
index 00e84296..a9a91d69 100644
--- a/vendor/github.com/mitchellh/packer/builder/googlecompute/step_create_instance_test.go
+++ b/vendor/github.com/mitchellh/packer/builder/googlecompute/step_create_instance_test.go
@@ -229,10 +229,6 @@ func TestStepCreateInstance_errorTimeout(t *testing.T) {
state.Put("ssh_public_key", "key")
errCh := make(chan error, 1)
- go func() {
- <-time.After(10 * time.Millisecond)
- errCh <- nil
- }()
config := state.Get("config").(*Config)
config.stateTimeout = 1 * time.Microsecond
diff --git a/vendor/github.com/mitchellh/packer/builder/hyperv/iso/builder.go b/vendor/github.com/mitchellh/packer/builder/hyperv/iso/builder.go
index e6c8d4d6..9b4065d8 100644
--- a/vendor/github.com/mitchellh/packer/builder/hyperv/iso/builder.go
+++ b/vendor/github.com/mitchellh/packer/builder/hyperv/iso/builder.go
@@ -92,7 +92,8 @@ type Config struct {
// Prepare processes the build configuration parameters.
func (b *Builder) Prepare(raws ...interface{}) ([]string, error) {
err := config.Decode(&b.config, &config.DecodeOpts{
- Interpolate: true,
+ Interpolate: true,
+ InterpolateContext: &b.config.ctx,
InterpolateFilter: &interpolate.RenderFilter{
Exclude: []string{
"boot_command",
@@ -404,17 +405,7 @@ func (b *Builder) Run(ui packer.Ui, hook packer.Hook, cache packer.Cache) (packe
}
// Run the steps.
- if b.config.PackerDebug {
- pauseFn := common.MultistepDebugFn(ui)
- state.Put("pauseFn", pauseFn)
- b.runner = &multistep.DebugRunner{
- Steps: steps,
- PauseFn: pauseFn,
- }
- } else {
- b.runner = &multistep.BasicRunner{Steps: steps}
- }
-
+ b.runner = common.NewRunner(steps, b.config.PackerConfig, ui)
b.runner.Run(state)
// Report any errors.
diff --git a/vendor/github.com/mitchellh/packer/builder/lxc/artifact.go b/vendor/github.com/mitchellh/packer/builder/lxc/artifact.go
new file mode 100644
index 00000000..0a53f70e
--- /dev/null
+++ b/vendor/github.com/mitchellh/packer/builder/lxc/artifact.go
@@ -0,0 +1,35 @@
+package lxc
+
+import (
+ "fmt"
+ "os"
+)
+
+type Artifact struct {
+ dir string
+ f []string
+}
+
+func (*Artifact) BuilderId() string {
+ return BuilderId
+}
+
+func (a *Artifact) Files() []string {
+ return a.f
+}
+
+func (*Artifact) Id() string {
+ return "VM"
+}
+
+func (a *Artifact) String() string {
+ return fmt.Sprintf("VM files in directory: %s", a.dir)
+}
+
+func (a *Artifact) State(name string) interface{} {
+ return nil
+}
+
+func (a *Artifact) Destroy() error {
+ return os.RemoveAll(a.dir)
+}
diff --git a/vendor/github.com/mitchellh/packer/builder/lxc/builder.go b/vendor/github.com/mitchellh/packer/builder/lxc/builder.go
new file mode 100644
index 00000000..31770b740
--- /dev/null
+++ b/vendor/github.com/mitchellh/packer/builder/lxc/builder.go
@@ -0,0 +1,95 @@
+package lxc
+
+import (
+ "github.com/hashicorp/packer/common"
+ "github.com/hashicorp/packer/packer"
+ "github.com/hashicorp/packer/template/interpolate"
+ "github.com/mitchellh/multistep"
+ "log"
+ "os"
+ "path/filepath"
+)
+
+// The unique ID for this builder
+const BuilderId = "ustream.lxc"
+
+type wrappedCommandTemplate struct {
+ Command string
+}
+
+type Builder struct {
+ config *Config
+ runner multistep.Runner
+}
+
+func (b *Builder) Prepare(raws ...interface{}) ([]string, error) {
+ c, errs := NewConfig(raws...)
+ if errs != nil {
+ return nil, errs
+ }
+ b.config = c
+
+ return nil, nil
+}
+
+func (b *Builder) Run(ui packer.Ui, hook packer.Hook, cache packer.Cache) (packer.Artifact, error) {
+ wrappedCommand := func(command string) (string, error) {
+ b.config.ctx.Data = &wrappedCommandTemplate{Command: command}
+ return interpolate.Render(b.config.CommandWrapper, &b.config.ctx)
+ }
+
+ steps := []multistep.Step{
+ new(stepPrepareOutputDir),
+ new(stepLxcCreate),
+ &StepWaitInit{
+ WaitTimeout: b.config.InitTimeout,
+ },
+ new(StepProvision),
+ new(stepExport),
+ }
+
+ // Setup the state bag
+ state := new(multistep.BasicStateBag)
+ state.Put("config", b.config)
+ state.Put("cache", cache)
+ state.Put("hook", hook)
+ state.Put("ui", ui)
+ state.Put("wrappedCommand", CommandWrapper(wrappedCommand))
+
+ // Run
+ b.runner = common.NewRunnerWithPauseFn(steps, b.config.PackerConfig, ui, state)
+ b.runner.Run(state)
+
+ // If there was an error, return that
+ if rawErr, ok := state.GetOk("error"); ok {
+ return nil, rawErr.(error)
+ }
+
+ // Compile the artifact list
+ files := make([]string, 0, 5)
+ visit := func(path string, info os.FileInfo, err error) error {
+ if !info.IsDir() {
+ files = append(files, path)
+ }
+
+ return err
+ }
+
+ if err := filepath.Walk(b.config.OutputDir, visit); err != nil {
+ return nil, err
+ }
+
+ artifact := &Artifact{
+ dir: b.config.OutputDir,
+ f: files,
+ }
+
+ return artifact, nil
+}
+
+func (b *Builder) Cancel() {
+ if b.runner != nil {
+ log.Println("Cancelling the step runner...")
+ b.runner.Cancel()
+ }
+}
diff --git a/vendor/github.com/mitchellh/packer/builder/lxc/builder_test.go b/vendor/github.com/mitchellh/packer/builder/lxc/builder_test.go
new file mode 100644
index 00000000..4eeb2759
--- /dev/null
+++ b/vendor/github.com/mitchellh/packer/builder/lxc/builder_test.go
@@ -0,0 +1,56 @@
+package lxc
+
+import (
+ "os"
+ "testing"
+
+ "github.com/hashicorp/packer/packer"
+)
+
+func testConfig() map[string]interface{} {
+ return map[string]interface{}{
+ "config_file": "builder_test.go",
+ "template_name": "debian",
+ "template_environment_vars": "SUITE=jessie",
+ }
+}
+
+func TestBuilder_Foo(t *testing.T) {
+ if os.Getenv("PACKER_ACC") == "" {
+ t.Skip("This test is only run with PACKER_ACC=1")
+ }
+}
+
+func TestBuilderPrepare_ConfigFile(t *testing.T) {
+ var b Builder
+ // Good
+ config := testConfig()
+ warnings, err := b.Prepare(config)
+ if len(warnings) > 0 {
+ t.Fatalf("bad: %#v", warnings)
+ }
+ if err != nil {
+ t.Fatalf("should not have error: %s", err)
+ }
+
+ // Bad, missing config file
+ config = testConfig()
+ delete(config, "config_file")
+ b = Builder{}
+ warnings, err = b.Prepare(config)
+ if len(warnings) > 0 {
+ t.Fatalf("bad: %#v", warnings)
+ }
+ if err == nil {
+ t.Fatalf("should have error")
+ }
+
+}
+
+func TestBuilder_ImplementsBuilder(t *testing.T) {
+ var raw interface{}
+ raw = &Builder{}
+ if _, ok := raw.(packer.Builder); !ok {
+ t.Fatalf("Builder should be a builder")
+ }
+}
diff --git a/vendor/github.com/mitchellh/packer/builder/lxc/command.go b/vendor/github.com/mitchellh/packer/builder/lxc/command.go
new file mode 100644
index 00000000..af81cff8
--- /dev/null
+++ b/vendor/github.com/mitchellh/packer/builder/lxc/command.go
@@ -0,0 +1,15 @@
+package lxc
+
+import (
+ "os/exec"
+)
+
+// CommandWrapper is a type that given a command, will possibly modify that
+// command in-flight. This might return an error.
+type CommandWrapper func(string) (string, error)
+
+// ShellCommand takes a command string and returns an *exec.Cmd to execute
+// it within the context of a shell (/bin/sh).
+func ShellCommand(command string) *exec.Cmd {
+ return exec.Command("/bin/sh", "-c", command)
+}
diff --git a/vendor/github.com/mitchellh/packer/builder/lxc/communicator.go b/vendor/github.com/mitchellh/packer/builder/lxc/communicator.go
new file mode 100644
index 00000000..8d976597
--- /dev/null
+++ b/vendor/github.com/mitchellh/packer/builder/lxc/communicator.go
@@ -0,0 +1,151 @@
+package lxc
+
+import (
+ "fmt"
+ "github.com/hashicorp/packer/packer"
+ "io"
+ "io/ioutil"
+ "log"
+ "os"
+ "os/exec"
+ "path/filepath"
+ "strings"
+ "syscall"
+)
+
+type LxcAttachCommunicator struct {
+ RootFs string
+ ContainerName string
+ CmdWrapper CommandWrapper
+}
+
+func (c *LxcAttachCommunicator) Start(cmd *packer.RemoteCmd) error {
+ localCmd, err := c.Execute(cmd.Command)
+
+ if err != nil {
+ return err
+ }
+
+ localCmd.Stdin = cmd.Stdin
+ localCmd.Stdout = cmd.Stdout
+ localCmd.Stderr = cmd.Stderr
+ if err := localCmd.Start(); err != nil {
+ return err
+ }
+
+ go func() {
+ exitStatus := 0
+ if err := localCmd.Wait(); err != nil {
+ if exitErr, ok := err.(*exec.ExitError); ok {
+ exitStatus = 1
+
+ // There is no process-independent way to get the REAL
+ // exit status so we just try to go deeper.
+ if status, ok := exitErr.Sys().(syscall.WaitStatus); ok {
+ exitStatus = status.ExitStatus()
+ }
+ }
+ }
+
+ log.Printf(
+ "lxc-attach execution exited with '%d': '%s'",
+ exitStatus, cmd.Command)
+ cmd.SetExited(exitStatus)
+ }()
+
+ return nil
+}
+
+func (c *LxcAttachCommunicator) Upload(dst string, r io.Reader, fi *os.FileInfo) error {
+ dst = filepath.Join(c.RootFs, dst)
+ log.Printf("Uploading to rootfs: %s", dst)
+ tf, err := ioutil.TempFile("", "packer-lxc-attach")
+ if err != nil {
+ return fmt.Errorf("Error uploading file to rootfs: %s", err)
+ }
+ defer os.Remove(tf.Name())
+ io.Copy(tf, r)
+
+ cpCmd, err := c.CmdWrapper(fmt.Sprintf("sudo cp %s %s", tf.Name(), dst))
+ if err != nil {
+ return err
+ }
+
+ log.Printf("Running copy command: %s", dst)
+
+ return ShellCommand(cpCmd).Run()
+}
+
+func (c *LxcAttachCommunicator) UploadDir(dst string, src string, exclude []string) error {
+ // TODO: remove any file copied if it appears in `exclude`
+ dest := filepath.Join(c.RootFs, dst)
+ log.Printf("Uploading directory '%s' to rootfs '%s'", src, dest)
+ cpCmd, err := c.CmdWrapper(fmt.Sprintf("sudo cp -R %s/. %s", src, dest))
+ if err != nil {
+ return err
+ }
+
+ return ShellCommand(cpCmd).Run()
+}
+
+func (c *LxcAttachCommunicator) Download(src string, w io.Writer) error {
+ src = filepath.Join(c.RootFs, src)
+ log.Printf("Downloading from rootfs dir: %s", src)
+ f, err := os.Open(src)
+ if err != nil {
+ return err
+ }
+ defer f.Close()
+
+ if _, err := io.Copy(w, f); err != nil {
+ return err
+ }
+
+ return nil
+}
+
+func (c *LxcAttachCommunicator) DownloadDir(src string, dst string, exclude []string) error {
+ return fmt.Errorf("DownloadDir is not implemented for lxc")
+}
+
+func (c *LxcAttachCommunicator) Execute(commandString string) (*exec.Cmd, error) {
+ log.Printf("Executing with lxc-attach in container: %s %s %s", c.ContainerName, c.RootFs, commandString)
+ command, err := c.CmdWrapper(
+ fmt.Sprintf("sudo lxc-attach --name %s -- /bin/sh -c \"%s\"", c.ContainerName, commandString))
+ if err != nil {
+ return nil, err
+ }
+
+ localCmd := ShellCommand(command)
+ log.Printf("Executing lxc-attach: %s %#v", localCmd.Path, localCmd.Args)
+
+ return localCmd, nil
+}
+
+func (c *LxcAttachCommunicator) CheckInit() (string, error) {
+ log.Printf("Debug runlevel exec")
+ localCmd, err := c.Execute("/sbin/runlevel")
+
+ if err != nil {
+ return "", err
+ }
+
+ pr, _ := localCmd.StdoutPipe()
+ if err = localCmd.Start(); err != nil {
+ return "", err
+ }
+
+ output, err := ioutil.ReadAll(pr)
+
+ if err != nil {
+ return "", err
+ }
+
+ err = localCmd.Wait()
+
+ if err != nil {
+ return "", err
+ }
+
+ return strings.TrimSpace(string(output)), nil
+}
diff --git a/vendor/github.com/mitchellh/packer/builder/lxc/communicator_test.go b/vendor/github.com/mitchellh/packer/builder/lxc/communicator_test.go
new file mode 100644
index 00000000..854ba668
--- /dev/null
+++ b/vendor/github.com/mitchellh/packer/builder/lxc/communicator_test.go
@@ -0,0 +1,14 @@
+package lxc
+
+import (
+ "github.com/hashicorp/packer/packer"
+ "testing"
+)
+
+func TestCommunicator_ImplementsCommunicator(t *testing.T) {
+ var raw interface{}
+ raw = &LxcAttachCommunicator{}
+ if _, ok := raw.(packer.Communicator); !ok {
+ t.Fatalf("Communicator should be a communicator")
+ }
+}
diff --git a/vendor/github.com/mitchellh/packer/builder/lxc/config.go b/vendor/github.com/mitchellh/packer/builder/lxc/config.go
new file mode 100644
index 00000000..c3c28d4f
--- /dev/null
+++ b/vendor/github.com/mitchellh/packer/builder/lxc/config.go
@@ -0,0 +1,79 @@
+package lxc
+
+import (
+ "fmt"
+ "github.com/hashicorp/packer/common"
+ "github.com/hashicorp/packer/helper/config"
+ "github.com/hashicorp/packer/packer"
+ "github.com/hashicorp/packer/template/interpolate"
+ "github.com/mitchellh/mapstructure"
+ "os"
+ "time"
+)
+
+type Config struct {
+ common.PackerConfig `mapstructure:",squash"`
+ ConfigFile string `mapstructure:"config_file"`
+ OutputDir string `mapstructure:"output_directory"`
+ ContainerName string `mapstructure:"container_name"`
+ CommandWrapper string `mapstructure:"command_wrapper"`
+ RawInitTimeout string `mapstructure:"init_timeout"`
+ Name string `mapstructure:"template_name"`
+ Parameters []string `mapstructure:"template_parameters"`
+ EnvVars []string `mapstructure:"template_environment_vars"`
+ TargetRunlevel int `mapstructure:"target_runlevel"`
+ InitTimeout time.Duration
+
+ ctx interpolate.Context
+}
+
+func NewConfig(raws ...interface{}) (*Config, error) {
+ var c Config
+
+ var md mapstructure.Metadata
+ err := config.Decode(&c, &config.DecodeOpts{
+ Metadata: &md,
+ Interpolate: true,
+ }, raws...)
+ if err != nil {
+ return nil, err
+ }
+
+ // Accumulate any errors
+ var errs *packer.MultiError
+
+ if c.OutputDir == "" {
+ c.OutputDir = fmt.Sprintf("output-%s", c.PackerBuildName)
+ }
+
+ if c.ContainerName == "" {
+ c.ContainerName = fmt.Sprintf("packer-%s", c.PackerBuildName)
+ }
+
+ if c.TargetRunlevel == 0 {
+ c.TargetRunlevel = 3
+ }
+
+ if c.CommandWrapper == "" {
+ c.CommandWrapper = "{{.Command}}"
+ }
+
+ if c.RawInitTimeout == "" {
+ c.RawInitTimeout = "20s"
+ }
+
+ c.InitTimeout, err = time.ParseDuration(c.RawInitTimeout)
+ if err != nil {
+ errs = packer.MultiErrorAppend(errs, fmt.Errorf("Failed parsing init_timeout: %s", err))
+ }
+
+ if _, err := os.Stat(c.ConfigFile); os.IsNotExist(err) {
+ errs = packer.MultiErrorAppend(errs, fmt.Errorf("LXC Config file appears to be missing: %s", c.ConfigFile))
+ }
+
+ if errs != nil && len(errs.Errors) > 0 {
+ return nil, errs
+ }
+
+ return &c, nil
+}
diff --git a/vendor/github.com/mitchellh/packer/builder/lxc/step_export.go b/vendor/github.com/mitchellh/packer/builder/lxc/step_export.go
new file mode 100644
index 00000000..59e4b79e
--- /dev/null
+++ b/vendor/github.com/mitchellh/packer/builder/lxc/step_export.go
@@ -0,0 +1,98 @@
+package lxc
+
+import (
+ "bytes"
+ "fmt"
+ "github.com/hashicorp/packer/packer"
+ "github.com/mitchellh/multistep"
+ "io"
+ "log"
+ "os"
+ "os/exec"
+ "path/filepath"
+ "strings"
+)
+
+type stepExport struct{}
+
+func (s *stepExport) Run(state multistep.StateBag) multistep.StepAction {
+ config := state.Get("config").(*Config)
+ ui := state.Get("ui").(packer.Ui)
+
+ name := config.ContainerName
+
+ containerDir := fmt.Sprintf("/var/lib/lxc/%s", name)
+ outputPath := filepath.Join(config.OutputDir, "rootfs.tar.gz")
+ configFilePath := filepath.Join(config.OutputDir, "lxc-config")
+
+ configFile, err := os.Create(configFilePath)
+
+ if err != nil {
+ err := fmt.Errorf("Error creating config file: %s", err)
+ state.Put("error", err)
+ ui.Error(err.Error())
+ return multistep.ActionHalt
+ }
+
+ originalConfigFile, err := os.Open(config.ConfigFile)
+
+ if err != nil {
+ err := fmt.Errorf("Error opening config file: %s", err)
+ state.Put("error", err)
+ ui.Error(err.Error())
+ return multistep.ActionHalt
+ }
+
+ _, err = io.Copy(configFile, originalConfigFile)
+
+ commands := make([][]string, 4)
+ commands[0] = []string{
+ "lxc-stop", "--name", name,
+ }
+ commands[1] = []string{
+ "tar", "-C", containerDir, "--numeric-owner", "--anchored", "--exclude=./rootfs/dev/log", "-czf", outputPath, "./rootfs",
+ }
+ commands[2] = []string{
+ "chmod", "+x", configFilePath,
+ }
+ commands[3] = []string{
+ "sh", "-c", "chown $USER:`id -gn` " + filepath.Join(config.OutputDir, "*"),
+ }
+
+ ui.Say("Exporting container...")
+ for _, command := range commands {
+ err := s.SudoCommand(command...)
+ if err != nil {
+ err := fmt.Errorf("Error exporting container: %s", err)
+ state.Put("error", err)
+ ui.Error(err.Error())
+ return multistep.ActionHalt
+ }
+ }
+
+ return multistep.ActionContinue
+}
+
+func (s *stepExport) Cleanup(state multistep.StateBag) {}
+
+func (s *stepExport) SudoCommand(args ...string) error {
+ var stdout, stderr bytes.Buffer
+
+ log.Printf("Executing sudo command: %#v", args)
+ cmd := exec.Command("sudo", args...)
+ cmd.Stdout = &stdout
+ cmd.Stderr = &stderr
+ err := cmd.Run()
+
+ stdoutString := strings.TrimSpace(stdout.String())
+ stderrString := strings.TrimSpace(stderr.String())
+
+ if _, ok := err.(*exec.ExitError); ok {
+ err = fmt.Errorf("Sudo command error: %s", stderrString)
+ }
+
+ log.Printf("stdout: %s", stdoutString)
+ log.Printf("stderr: %s", stderrString)
+
+ return err
+}
diff --git a/vendor/github.com/mitchellh/packer/builder/lxc/step_lxc_create.go b/vendor/github.com/mitchellh/packer/builder/lxc/step_lxc_create.go
new file mode 100644
index 00000000..a98926ff
--- /dev/null
+++ b/vendor/github.com/mitchellh/packer/builder/lxc/step_lxc_create.go
@@ -0,0 +1,89 @@
+package lxc
+
+import (
+ "bytes"
+ "fmt"
+ "github.com/hashicorp/packer/packer"
+ "github.com/mitchellh/multistep"
+ "log"
+ "os/exec"
+ "path/filepath"
+ "strings"
+)
+
+type stepLxcCreate struct{}
+
+func (s *stepLxcCreate) Run(state multistep.StateBag) multistep.StepAction {
+ config := state.Get("config").(*Config)
+ ui := state.Get("ui").(packer.Ui)
+
+ name := config.ContainerName
+
+ // TODO: read from env
+ lxc_dir := "/var/lib/lxc"
+ rootfs := filepath.Join(lxc_dir, name, "rootfs")
+
+ if config.PackerForce {
+ s.Cleanup(state)
+ }
+
+ commands := make([][]string, 3)
+ commands[0] = append(config.EnvVars, []string{"lxc-create", "-n", name, "-t", config.Name, "--"}...)
+ commands[0] = append(commands[0], config.Parameters...)
+ // prevent tmp from being cleaned on boot, we put provisioning scripts there
+ // todo: wait for init to finish before moving on to provisioning instead of this
+ commands[1] = []string{"touch", filepath.Join(rootfs, "tmp", ".tmpfs")}
+ commands[2] = []string{"lxc-start", "-d", "--name", name}
+
+ ui.Say("Creating container...")
+ for _, command := range commands {
+ log.Printf("Executing sudo command: %#v", command)
+ err := s.SudoCommand(command...)
+ if err != nil {
+ err := fmt.Errorf("Error creating container: %s", err)
+ state.Put("error", err)
+ ui.Error(err.Error())
+ return multistep.ActionHalt
+ }
+ }
+
+ state.Put("mount_path", rootfs)
+
+ return multistep.ActionContinue
+}
+
+func (s *stepLxcCreate) Cleanup(state multistep.StateBag) {
+ config := state.Get("config").(*Config)
+ ui := state.Get("ui").(packer.Ui)
+
+ command := []string{
+ "lxc-destroy", "-f", "-n", config.ContainerName,
+ }
+
+ ui.Say("Unregistering and deleting virtual machine...")
+ if err := s.SudoCommand(command...); err != nil {
+ ui.Error(fmt.Sprintf("Error deleting virtual machine: %s", err))
+ }
+}
+
+func (s *stepLxcCreate) SudoCommand(args ...string) error {
+ var stdout, stderr bytes.Buffer
+
+ log.Printf("Executing sudo command: %#v", args)
+ cmd := exec.Command("sudo", args...)
+ cmd.Stdout = &stdout
+ cmd.Stderr = &stderr
+ err := cmd.Run()
+
+ stdoutString := strings.TrimSpace(stdout.String())
+ stderrString := strings.TrimSpace(stderr.String())
+
+ if _, ok := err.(*exec.ExitError); ok {
+ err = fmt.Errorf("Sudo command error: %s", stderrString)
+ }
+
+ log.Printf("stdout: %s", stdoutString)
+ log.Printf("stderr: %s", stderrString)
+
+ return err
+}
diff --git a/vendor/github.com/mitchellh/packer/builder/lxc/step_prepare_output_dir.go b/vendor/github.com/mitchellh/packer/builder/lxc/step_prepare_output_dir.go
new file mode 100644
index 00000000..07c6f08b
--- /dev/null
+++ b/vendor/github.com/mitchellh/packer/builder/lxc/step_prepare_output_dir.go
@@ -0,0 +1,49 @@
+package lxc
+
+import (
+ "github.com/hashicorp/packer/packer"
+ "github.com/mitchellh/multistep"
+ "log"
+ "os"
+ "time"
+)
+
+type stepPrepareOutputDir struct{}
+
+func (stepPrepareOutputDir) Run(state multistep.StateBag) multistep.StepAction {
+ config := state.Get("config").(*Config)
+ ui := state.Get("ui").(packer.Ui)
+
+ if _, err := os.Stat(config.OutputDir); err == nil && config.PackerForce {
+ ui.Say("Deleting previous output directory...")
+ os.RemoveAll(config.OutputDir)
+ }
+
+ if err := os.MkdirAll(config.OutputDir, 0755); err != nil {
+ state.Put("error", err)
+ return multistep.ActionHalt
+ }
+
+ return multistep.ActionContinue
+}
+
+func (stepPrepareOutputDir) Cleanup(state multistep.StateBag) {
+ _, cancelled := state.GetOk(multistep.StateCancelled)
+ _, halted := state.GetOk(multistep.StateHalted)
+
+ if cancelled || halted {
+ config := state.Get("config").(*Config)
+ ui := state.Get("ui").(packer.Ui)
+
+ ui.Say("Deleting output directory...")
+ for i := 0; i < 5; i++ {
+ err := os.RemoveAll(config.OutputDir)
+ if err == nil {
+ break
+ }
+
+ log.Printf("Error removing output dir: %s", err)
+ time.Sleep(2 * time.Second)
+ }
+ }
+}
diff --git a/vendor/github.com/mitchellh/packer/builder/lxc/step_provision.go b/vendor/github.com/mitchellh/packer/builder/lxc/step_provision.go
new file mode 100644
index 00000000..f91eb56c
--- /dev/null
+++ b/vendor/github.com/mitchellh/packer/builder/lxc/step_provision.go
@@ -0,0 +1,36 @@
+package lxc
+
+import (
+ "github.com/hashicorp/packer/packer"
+ "github.com/mitchellh/multistep"
+ "log"
+)
+
+// StepProvision provisions the instance within a chroot.
+type StepProvision struct{}
+
+func (s *StepProvision) Run(state multistep.StateBag) multistep.StepAction {
+ hook := state.Get("hook").(packer.Hook)
+ config := state.Get("config").(*Config)
+ mountPath := state.Get("mount_path").(string)
+ ui := state.Get("ui").(packer.Ui)
+ wrappedCommand := state.Get("wrappedCommand").(CommandWrapper)
+
+ // Create our communicator
+ comm := &LxcAttachCommunicator{
+ ContainerName: config.ContainerName,
+ RootFs: mountPath,
+ CmdWrapper: wrappedCommand,
+ }
+
+ // Provision
+ log.Println("Running the provision hook")
+ if err := hook.Run(packer.HookProvision, ui, comm, nil); err != nil {
+ state.Put("error", err)
+ return multistep.ActionHalt
+ }
+
+ return multistep.ActionContinue
+}
+
+func (s *StepProvision) Cleanup(state multistep.StateBag) {}
diff --git a/vendor/github.com/mitchellh/packer/builder/lxc/step_wait_init.go b/vendor/github.com/mitchellh/packer/builder/lxc/step_wait_init.go
new file mode 100644
index 00000000..e5d37531
--- /dev/null
+++ b/vendor/github.com/mitchellh/packer/builder/lxc/step_wait_init.go
@@ -0,0 +1,102 @@
+package lxc
+
+import (
+ "errors"
+ "fmt"
+ "github.com/hashicorp/packer/packer"
+ "github.com/mitchellh/multistep"
+ "log"
+ "strings"
+ "time"
+)
+
+type StepWaitInit struct {
+ WaitTimeout time.Duration
+}
+
+func (s *StepWaitInit) Run(state multistep.StateBag) multistep.StepAction {
+ ui := state.Get("ui").(packer.Ui)
+
+ var err error
+
+ cancel := make(chan struct{})
+ waitDone := make(chan bool, 1)
+ go func() {
+ ui.Say("Waiting for container to finish init...")
+ err = s.waitForInit(state, cancel)
+ waitDone <- true
+ }()
+
+ log.Printf("Waiting for container to finish init, up to timeout: %s", s.WaitTimeout)
+ timeout := time.After(s.WaitTimeout)
+WaitLoop:
+ for {
+ select {
+ case <-waitDone:
+ if err != nil {
+ ui.Error(fmt.Sprintf("Error waiting for container to finish init: %s", err))
+ return multistep.ActionHalt
+ }
+
+ ui.Say("Container finished init!")
+ break WaitLoop
+ case <-timeout:
+ err := fmt.Errorf("Timeout waiting for container to finish init.")
+ state.Put("error", err)
+ ui.Error(err.Error())
+ close(cancel)
+ return multistep.ActionHalt
+ case <-time.After(1 * time.Second):
+ if _, ok := state.GetOk(multistep.StateCancelled); ok {
+ close(cancel)
+ log.Println("Interrupt detected, quitting waiting for container to finish init.")
+ return multistep.ActionHalt
+ }
+ }
+ }
+
+ return multistep.ActionContinue
+}
+
+func (s *StepWaitInit) Cleanup(multistep.StateBag) {
+}
+
+func (s *StepWaitInit) waitForInit(state multistep.StateBag, cancel <-chan struct{}) error {
+ config := state.Get("config").(*Config)
+ mountPath := state.Get("mount_path").(string)
+ wrappedCommand := state.Get("wrappedCommand").(CommandWrapper)
+
+ for {
+ select {
+ case <-cancel:
+ log.Println("Cancelled. Exiting loop.")
+ return errors.New("Wait cancelled")
+ case <-time.After(1 * time.Second):
+ }
+
+ comm := &LxcAttachCommunicator{
+ ContainerName: config.ContainerName,
+ RootFs: mountPath,
+ CmdWrapper: wrappedCommand,
+ }
+
+ runlevel, _ := comm.CheckInit()
+ currentRunlevel := "unknown"
+ if arr := strings.Split(runlevel, " "); len(arr) >= 2 {
+ currentRunlevel = arr[1]
+ }
+
+ log.Printf("Current runlevel in container: '%s'", runlevel)
+
+ targetRunlevel := fmt.Sprintf("%d", config.TargetRunlevel)
+ if currentRunlevel == targetRunlevel {
+ log.Printf("Container finished init.")
+ break
+ } else if currentRunlevel > targetRunlevel {
+ log.Printf("Expected Runlevel %s, Got Runlevel %s, continuing", targetRunlevel, currentRunlevel)
+ break
+ }
+ }
+
+ return nil
+}
diff --git a/vendor/github.com/mitchellh/packer/builder/lxd/artifact.go b/vendor/github.com/mitchellh/packer/builder/lxd/artifact.go
new file mode 100644
index 00000000..481f0758
--- /dev/null
+++ b/vendor/github.com/mitchellh/packer/builder/lxd/artifact.go
@@ -0,0 +1,34 @@
+package lxd
+
+import (
+ "fmt"
+)
+
+type Artifact struct {
+ id string
+}
+
+func (*Artifact) BuilderId() string {
+ return BuilderId
+}
+
+func (a *Artifact) Files() []string {
+ return nil
+}
+
+func (a *Artifact) Id() string {
+ return a.id
+}
+
+func (a *Artifact) String() string {
+ return fmt.Sprintf("image: %s", a.id)
+}
+
+func (a *Artifact) State(name string) interface{} {
+ return nil
+}
+
+func (a *Artifact) Destroy() error {
+ _, err := LXDCommand("image", "delete", a.id)
+ return err
+}
diff --git a/vendor/github.com/mitchellh/packer/builder/lxd/builder.go b/vendor/github.com/mitchellh/packer/builder/lxd/builder.go
new file mode 100644
index 00000000..d59cf5bc
--- /dev/null
+++ b/vendor/github.com/mitchellh/packer/builder/lxd/builder.go
@@ -0,0 +1,74 @@
+package lxd
+
+import (
+ "github.com/hashicorp/packer/common"
+ "github.com/hashicorp/packer/packer"
+ "github.com/hashicorp/packer/template/interpolate"
+ "github.com/mitchellh/multistep"
+ "log"
+)
+
+// The unique ID for this builder
+const BuilderId = "lxd"
+
+type wrappedCommandTemplate struct {
+ Command string
+}
+
+type Builder struct {
+ config *Config
+ runner multistep.Runner
+}
+
+func (b *Builder) Prepare(raws ...interface{}) ([]string, error) {
+ c, errs := NewConfig(raws...)
+ if errs != nil {
+ return nil, errs
+ }
+ b.config = c
+
+ return nil, nil
+}
+
+func (b *Builder) Run(ui packer.Ui, hook packer.Hook, cache packer.Cache) (packer.Artifact, error) {
+ wrappedCommand := func(command string) (string, error) {
+ b.config.ctx.Data = &wrappedCommandTemplate{Command: command}
+ return interpolate.Render(b.config.CommandWrapper, &b.config.ctx)
+ }
+
+ steps := []multistep.Step{
+ &stepLxdLaunch{},
+ &StepProvision{},
+ &stepPublish{},
+ }
+
+ // Setup the state bag
+ state := new(multistep.BasicStateBag)
+ state.Put("config", b.config)
+ state.Put("cache", cache)
+ state.Put("hook", hook)
+ state.Put("ui", ui)
+ state.Put("wrappedCommand", CommandWrapper(wrappedCommand))
+
+ // Run
+ b.runner = common.NewRunnerWithPauseFn(steps, b.config.PackerConfig, ui, state)
+ b.runner.Run(state)
+
+ // If there was an error, return that
+ if rawErr, ok := state.GetOk("error"); ok {
+ return nil, rawErr.(error)
+ }
+
+ artifact := &Artifact{
+ id: state.Get("imageFingerprint").(string),
+ }
+
+ return artifact, nil
+}
+
+func (b *Builder) Cancel() {
+ if b.runner != nil {
+ log.Println("Cancelling the step runner...")
+ b.runner.Cancel()
+ }
+}
diff --git a/vendor/github.com/mitchellh/packer/builder/lxd/builder_test.go b/vendor/github.com/mitchellh/packer/builder/lxd/builder_test.go
new file mode 100644
index 00000000..b2ea70e5
--- /dev/null
+++ b/vendor/github.com/mitchellh/packer/builder/lxd/builder_test.go
@@ -0,0 +1,77 @@
+package lxd
+
+import (
+ "os"
+ "testing"
+
+ "github.com/hashicorp/packer/packer"
+)
+
+func testConfig() map[string]interface{} {
+ return map[string]interface{}{
+ "output_image": "foo",
+ "image": "bar",
+ }
+}
+
+func TestBuilder_Foo(t *testing.T) {
+ if os.Getenv("PACKER_ACC") == "" {
+ t.Skip("This test is only run with PACKER_ACC=1")
+ }
+}
+
+func TestBuilderPrepare_ConfigFile(t *testing.T) {
+ var b Builder
+ // Good
+ config := testConfig()
+ warnings, err := b.Prepare(config)
+ if len(warnings) > 0 {
+ t.Fatalf("bad: %#v", warnings)
+ }
+ if err != nil {
+ t.Fatalf("should not have error: %s", err)
+ }
+
+ // Good, remote image
+ config = testConfig()
+ config["image"] = "remote:bar"
+ warnings, err = b.Prepare(config)
+ if len(warnings) > 0 {
+ t.Fatalf("bad: %#v", warnings)
+ }
+ if err != nil {
+ t.Fatalf("should not have error: %s", err)
+ }
+
+ // Good, remote output image
+ config = testConfig()
+ config["output_image"] = "remote:foo"
+ warnings, err = b.Prepare(config)
+ if len(warnings) > 0 {
+ t.Fatalf("bad: %#v", warnings)
+ }
+ if err != nil {
+ t.Fatalf("should not have error: %s", err)
+ }
+
+ // Bad, missing image name
+ config = testConfig()
+ delete(config, "image")
+ b = Builder{}
+ warnings, err = b.Prepare(config)
+ if len(warnings) > 0 {
+ t.Fatalf("bad: %#v", warnings)
+ }
+ if err == nil {
+ t.Fatalf("should have error")
+ }
+
+}
+
+func TestBuilder_ImplementsBuilder(t *testing.T) {
+ var raw interface{}
+ raw = &Builder{}
+ if _, ok := raw.(packer.Builder); !ok {
+ t.Fatalf("Builder should be a builder")
+ }
+}
diff --git a/vendor/github.com/mitchellh/packer/builder/lxd/command.go b/vendor/github.com/mitchellh/packer/builder/lxd/command.go
new file mode 100644
index 00000000..c9a39279
--- /dev/null
+++ b/vendor/github.com/mitchellh/packer/builder/lxd/command.go
@@ -0,0 +1,43 @@
+package lxd
+
+import (
+ "bytes"
+ "fmt"
+ "log"
+ "os/exec"
+ "strings"
+)
+
+// CommandWrapper is a type that given a command, will possibly modify that
+// command in-flight. This might return an error.
+type CommandWrapper func(string) (string, error)
+
+// ShellCommand takes a command string and returns an *exec.Cmd to execute
+// it within the context of a shell (/bin/sh).
+func ShellCommand(command string) *exec.Cmd {
+ return exec.Command("/bin/sh", "-c", command)
+}
+
+// Yeah...LXD calls `lxc` because the command line is different between the
+// packages. This should also avoid a naming collision between the LXC builder.
+func LXDCommand(args ...string) (string, error) {
+ var stdout, stderr bytes.Buffer
+
+ log.Printf("Executing lxc command: %#v", args)
+ cmd := exec.Command("lxc", args...)
+ cmd.Stdout = &stdout
+ cmd.Stderr = &stderr
+ err := cmd.Run()
+
+ stdoutString := strings.TrimSpace(stdout.String())
+ stderrString := strings.TrimSpace(stderr.String())
+
+ if _, ok := err.(*exec.ExitError); ok {
+ err = fmt.Errorf("LXD command error: %s", stderrString)
+ }
+
+ log.Printf("stdout: %s", stdoutString)
+ log.Printf("stderr: %s", stderrString)
+
+ return stdoutString, err
+}
diff --git a/vendor/github.com/mitchellh/packer/builder/lxd/communicator.go b/vendor/github.com/mitchellh/packer/builder/lxd/communicator.go
new file mode 100644
index 00000000..8eaa47a5
--- /dev/null
+++ b/vendor/github.com/mitchellh/packer/builder/lxd/communicator.go
@@ -0,0 +1,142 @@
+package lxd
+
+import (
+ "fmt"
+ "github.com/hashicorp/packer/packer"
+ "io"
+ "log"
+ "os"
+ "os/exec"
+ "path/filepath"
+ "syscall"
+)
+
+type Communicator struct {
+ ContainerName string
+ CmdWrapper CommandWrapper
+}
+
+func (c *Communicator) Start(cmd *packer.RemoteCmd) error {
+ localCmd, err := c.Execute(cmd.Command)
+
+ if err != nil {
+ return err
+ }
+
+ localCmd.Stdin = cmd.Stdin
+ localCmd.Stdout = cmd.Stdout
+ localCmd.Stderr = cmd.Stderr
+ if err := localCmd.Start(); err != nil {
+ return err
+ }
+
+ go func() {
+ exitStatus := 0
+ if err := localCmd.Wait(); err != nil {
+ if exitErr, ok := err.(*exec.ExitError); ok {
+ exitStatus = 1
+
+ // There is no process-independent way to get the REAL
+ // exit status so we just try to go deeper.
+ if status, ok := exitErr.Sys().(syscall.WaitStatus); ok {
+ exitStatus = status.ExitStatus()
+ }
+ }
+ }
+
+ log.Printf(
+ "lxc exec execution exited with '%d': '%s'",
+ exitStatus, cmd.Command)
+ cmd.SetExited(exitStatus)
+ }()
+
+ return nil
+}
+
+func (c *Communicator) Upload(dst string, r io.Reader, fi *os.FileInfo) error {
+ cpCmd, err := c.CmdWrapper(fmt.Sprintf("lxc file push - %s", filepath.Join(c.ContainerName, dst)))
+ if err != nil {
+ return err
+ }
+
+ log.Printf("Running copy command: %s", cpCmd)
+ command := ShellCommand(cpCmd)
+ command.Stdin = r
+
+ return command.Run()
+}
+
+func (c *Communicator) UploadDir(dst string, src string, exclude []string) error {
+ // NOTE:lxc file push doesn't yet support directory uploads.
+ // As a work around, we tar up the folder, upload it as a file, then extract it
+
+ // Don't use 'z' flag as compressing may take longer and the transfer is likely local.
+ // If this isn't the case, it is possible for the user to compress in another step then transfer.
+ // It wouldn't be possibe to disable compression, without exposing this option.
+ tar, err := c.CmdWrapper(fmt.Sprintf("tar -cf - -C %s .", src))
+ if err != nil {
+ return err
+ }
+
+ cp, err := c.CmdWrapper(fmt.Sprintf("lxc exec %s -- tar -xf - -C %s", c.ContainerName, dst))
+ if err != nil {
+ return err
+ }
+
+ tarCmd := ShellCommand(tar)
+ cpCmd := ShellCommand(cp)
+
+ cpCmd.Stdin, _ = tarCmd.StdoutPipe()
+ log.Printf("Starting tar command: %s", tar)
+ err = tarCmd.Start()
+ if err != nil {
+ return err
+ }
+
+ log.Printf("Running cp command: %s", cp)
+ err = cpCmd.Run()
+ if err != nil {
+ log.Printf("Error running cp command: %s", err)
+ return err
+ }
+
+ err = tarCmd.Wait()
+ if err != nil {
+ log.Printf("Error running tar command: %s", err)
+ return err
+ }
+
+ return nil
+}
+
+func (c *Communicator) Download(src string, w io.Writer) error {
+ cpCmd, err := c.CmdWrapper(fmt.Sprintf("lxc file pull %s -", filepath.Join(c.ContainerName, src)))
+ if err != nil {
+ return err
+ }
+
+ log.Printf("Running copy command: %s", cpCmd)
+ command := ShellCommand(cpCmd)
+ command.Stdout = w
+
+ return command.Run()
+}
+
+func (c *Communicator) DownloadDir(src string, dst string, exclude []string) error {
+ // TODO This could probably be "lxc exec <container> -- cd <src> && tar -czf - | tar -xzf - -C <dst>"
+ return fmt.Errorf("DownloadDir is not implemented for lxc")
+}
+
+func (c *Communicator) Execute(commandString string) (*exec.Cmd, error) {
+ log.Printf("Executing with lxc exec in container: %s %s", c.ContainerName, commandString)
+ command, err := c.CmdWrapper(
+ fmt.Sprintf("lxc exec %s -- /bin/sh -c \"%s\"", c.ContainerName, commandString))
+ if err != nil {
+ return nil, err
+ }
+
+ localCmd := ShellCommand(command)
+ log.Printf("Executing lxc exec: %s %#v", localCmd.Path, localCmd.Args)
+
+ return localCmd, nil
+}
diff --git a/vendor/github.com/mitchellh/packer/builder/lxd/communicator_test.go b/vendor/github.com/mitchellh/packer/builder/lxd/communicator_test.go
new file mode 100644
index 00000000..4a70160b
--- /dev/null
+++ b/vendor/github.com/mitchellh/packer/builder/lxd/communicator_test.go
@@ -0,0 +1,20 @@
+package lxd
+
+import (
+ "github.com/hashicorp/packer/packer"
+ "testing"
+)
+
+func TestCommunicator_ImplementsCommunicator(t *testing.T) {
+ var raw interface{}
+ raw = &Communicator{}
+ if _, ok := raw.(packer.Communicator); !ok {
+ t.Fatalf("Communicator should be a communicator")
+ }
+}
+
+// Acceptance tests
+// TODO Execute a command
+// TODO Upload a file
+// TODO Download a file
+// TODO Upload a Directory
diff --git a/vendor/github.com/mitchellh/packer/builder/lxd/config.go b/vendor/github.com/mitchellh/packer/builder/lxd/config.go
new file mode 100644
index 00000000..73de7212
--- /dev/null
+++ b/vendor/github.com/mitchellh/packer/builder/lxd/config.go
@@ -0,0 +1,60 @@
+package lxd
+
+import (
+ "fmt"
+ "github.com/hashicorp/packer/common"
+ "github.com/hashicorp/packer/helper/config"
+ "github.com/hashicorp/packer/packer"
+ "github.com/hashicorp/packer/template/interpolate"
+ "github.com/mitchellh/mapstructure"
+ "time"
+)
+
+type Config struct {
+ common.PackerConfig `mapstructure:",squash"`
+ OutputImage string `mapstructure:"output_image"`
+ ContainerName string `mapstructure:"container_name"`
+ CommandWrapper string `mapstructure:"command_wrapper"`
+ Image string `mapstructure:"image"`
+ InitTimeout time.Duration
+
+ ctx interpolate.Context
+}
+
+func NewConfig(raws ...interface{}) (*Config, error) {
+ var c Config
+
+ var md mapstructure.Metadata
+ err := config.Decode(&c, &config.DecodeOpts{
+ Metadata: &md,
+ Interpolate: true,
+ }, raws...)
+ if err != nil {
+ return nil, err
+ }
+
+ // Accumulate any errors
+ var errs *packer.MultiError
+
+ if c.ContainerName == "" {
+ c.ContainerName = fmt.Sprintf("packer-%s", c.PackerBuildName)
+ }
+
+ if c.OutputImage == "" {
+ c.OutputImage = c.ContainerName
+ }
+
+ if c.CommandWrapper == "" {
+ c.CommandWrapper = "{{.Command}}"
+ }
+
+ if c.Image == "" {
+ errs = packer.MultiErrorAppend(errs, fmt.Errorf("`image` is a required parameter for LXD. Please specify an image by alias or fingerprint. e.g. `ubuntu-daily:x`"))
+ }
+
+ if errs != nil && len(errs.Errors) > 0 {
+ return nil, errs
+ }
+
+ return &c, nil
+}
diff --git a/vendor/github.com/mitchellh/packer/builder/lxd/step_lxd_launch.go b/vendor/github.com/mitchellh/packer/builder/lxd/step_lxd_launch.go
new file mode 100644
index 00000000..1ec573b1
--- /dev/null
+++ b/vendor/github.com/mitchellh/packer/builder/lxd/step_lxd_launch.go
@@ -0,0 +1,50 @@
+package lxd
+
+import (
+ "fmt"
+ "github.com/hashicorp/packer/packer"
+ "github.com/mitchellh/multistep"
+ "time"
+)
+
+type stepLxdLaunch struct{}
+
+func (s *stepLxdLaunch) Run(state multistep.StateBag) multistep.StepAction {
+ config := state.Get("config").(*Config)
+ ui := state.Get("ui").(packer.Ui)
+
+ name := config.ContainerName
+ image := config.Image
+
+ args := []string{
+ "launch", "--ephemeral=false", image, name,
+ }
+
+ ui.Say("Creating container...")
+ _, err := LXDCommand(args...)
+ if err != nil {
+ err := fmt.Errorf("Error creating container: %s", err)
+ state.Put("error", err)
+ ui.Error(err.Error())
+ return multistep.ActionHalt
+ }
+ // TODO: Should we check `lxc info <container>` for "Running"?
+ // We have to do this so /tmp doens't get cleared and lose our provisioner scripts.
+ time.Sleep(1 * time.Second)
+
+ return multistep.ActionContinue
+}
+
+func (s *stepLxdLaunch) Cleanup(state multistep.StateBag) {
+ config := state.Get("config").(*Config)
+ ui := state.Get("ui").(packer.Ui)
+
+ args := []string{
+ "delete", "--force", config.ContainerName,
+ }
+
+ ui.Say("Unregistering and deleting deleting container...")
+ if _, err := LXDCommand(args...); err != nil {
+ ui.Error(fmt.Sprintf("Error deleting container: %s", err))
+ }
+}
diff --git a/vendor/github.com/mitchellh/packer/builder/lxd/step_provision.go b/vendor/github.com/mitchellh/packer/builder/lxd/step_provision.go
new file mode 100644
index 00000000..c46b900e
--- /dev/null
+++ b/vendor/github.com/mitchellh/packer/builder/lxd/step_provision.go
@@ -0,0 +1,34 @@
+package lxd
+
+import (
+ "github.com/hashicorp/packer/packer"
+ "github.com/mitchellh/multistep"
+ "log"
+)
+
+// StepProvision provisions the container
+type StepProvision struct{}
+
+func (s *StepProvision) Run(state multistep.StateBag) multistep.StepAction {
+ hook := state.Get("hook").(packer.Hook)
+ config := state.Get("config").(*Config)
+ ui := state.Get("ui").(packer.Ui)
+ wrappedCommand := state.Get("wrappedCommand").(CommandWrapper)
+
+ // Create our communicator
+ comm := &Communicator{
+ ContainerName: config.ContainerName,
+ CmdWrapper: wrappedCommand,
+ }
+
+ // Provision
+ log.Println("Running the provision hook")
+ if err := hook.Run(packer.HookProvision, ui, comm, nil); err != nil {
+ state.Put("error", err)
+ return multistep.ActionHalt
+ }
+
+ return multistep.ActionContinue
+}
+
+func (s *StepProvision) Cleanup(state multistep.StateBag) {}
diff --git a/vendor/github.com/mitchellh/packer/builder/lxd/step_publish.go b/vendor/github.com/mitchellh/packer/builder/lxd/step_publish.go
new file mode 100644
index 00000000..0c0aabd3
--- /dev/null
+++ b/vendor/github.com/mitchellh/packer/builder/lxd/step_publish.go
@@ -0,0 +1,54 @@
+package lxd
+
+import (
+ "fmt"
+ "github.com/hashicorp/packer/packer"
+ "github.com/mitchellh/multistep"
+ "regexp"
+)
+
+type stepPublish struct{}
+
+func (s *stepPublish) Run(state multistep.StateBag) multistep.StepAction {
+ config := state.Get("config").(*Config)
+ ui := state.Get("ui").(packer.Ui)
+
+ name := config.ContainerName
+ stop_args := []string{
+ // We created the container with "--ephemeral=false" so we know it is safe to stop.
+ "stop", name,
+ }
+
+ ui.Say("Stopping container...")
+ _, err := LXDCommand(stop_args...)
+ if err != nil {
+ err := fmt.Errorf("Error stopping container: %s", err)
+ state.Put("error", err)
+ ui.Error(err.Error())
+ return multistep.ActionHalt
+ }
+
+ publish_args := []string{
+ "publish", name, "--alias", config.OutputImage,
+ }
+
+ ui.Say("Publishing container...")
+ stdoutString, err := LXDCommand(publish_args...)
+ if err != nil {
+ err := fmt.Errorf("Error publishing container: %s", err)
+ state.Put("error", err)
+ ui.Error(err.Error())
+ return multistep.ActionHalt
+ }
+
+ r := regexp.MustCompile("([0-9a-fA-F]+)$")
+ fingerprint := r.FindAllStringSubmatch(stdoutString, -1)[0][0]
+
+ ui.Say(fmt.Sprintf("Created image: %s", fingerprint))
+
+ state.Put("imageFingerprint", fingerprint)
+
+ return multistep.ActionContinue
+}
+
+func (s *stepPublish) Cleanup(state multistep.StateBag) {}
diff --git a/vendor/github.com/mitchellh/packer/builder/oneandone/builder.go b/vendor/github.com/mitchellh/packer/builder/oneandone/builder.go
index f4f8e1dc..ad470c15 100644
--- a/vendor/github.com/mitchellh/packer/builder/oneandone/builder.go
+++ b/vendor/github.com/mitchellh/packer/builder/oneandone/builder.go
@@ -50,15 +50,7 @@ func (b *Builder) Run(ui packer.Ui, hook packer.Hook, cache packer.Cache) (packe
new(stepTakeSnapshot),
}
- if b.config.PackerDebug {
- b.runner = &multistep.DebugRunner{
- Steps: steps,
- PauseFn: common.MultistepDebugFn(ui),
- }
- } else {
- b.runner = &multistep.BasicRunner{Steps: steps}
- }
-
+ b.runner = common.NewRunner(steps, b.config.PackerConfig, ui)
b.runner.Run(state)
if rawErr, ok := state.GetOk("error"); ok {
diff --git a/vendor/github.com/mitchellh/packer/builder/oracle/oci/LICENSE b/vendor/github.com/mitchellh/packer/builder/oracle/oci/LICENSE
new file mode 100644
index 00000000..0ddc33c2
--- /dev/null
+++ b/vendor/github.com/mitchellh/packer/builder/oracle/oci/LICENSE
@@ -0,0 +1,375 @@
+Copyright (c) 2017 Oracle and/or its affiliates. All rights reserved.
+
+Mozilla Public License Version 2.0
+==================================
+
+1. Definitions
+--------------
+
+1.1. "Contributor"
+ means each individual or legal entity that creates, contributes to
+ the creation of, or owns Covered Software.
+
+1.2. "Contributor Version"
+ means the combination of the Contributions of others (if any) used
+ by a Contributor and that particular Contributor's Contribution.
+
+1.3. "Contribution"
+ means Covered Software of a particular Contributor.
+
+1.4. "Covered Software"
+ means Source Code Form to which the initial Contributor has attached
+ the notice in Exhibit A, the Executable Form of such Source Code
+ Form, and Modifications of such Source Code Form, in each case
+ including portions thereof.
+
+1.5. "Incompatible With Secondary Licenses"
+ means
+
+ (a) that the initial Contributor has attached the notice described
+ in Exhibit B to the Covered Software; or
+
+ (b) that the Covered Software was made available under the terms of
+ version 1.1 or earlier of the License, but not also under the
+ terms of a Secondary License.
+
+1.6. "Executable Form"
+ means any form of the work other than Source Code Form.
+
+1.7. "Larger Work"
+ means a work that combines Covered Software with other material, in
+ a separate file or files, that is not Covered Software.
+
+1.8. "License"
+ means this document.
+
+1.9. "Licensable"
+ means having the right to grant, to the maximum extent possible,
+ whether at the time of the initial grant or subsequently, any and
+ all of the rights conveyed by this License.
+
+1.10. "Modifications"
+ means any of the following:
+
+ (a) any file in Source Code Form that results from an addition to,
+ deletion from, or modification of the contents of Covered
+ Software; or
+
+ (b) any new file in Source Code Form that contains any Covered
+ Software.
+
+1.11. "Patent Claims" of a Contributor
+ means any patent claim(s), including without limitation, method,
+ process, and apparatus claims, in any patent Licensable by such
+ Contributor that would be infringed, but for the grant of the
+ License, by the making, using, selling, offering for sale, having
+ made, import, or transfer of either its Contributions or its
+ Contributor Version.
+
+1.12. "Secondary License"
+ means either the GNU General Public License, Version 2.0, the GNU
+ Lesser General Public License, Version 2.1, the GNU Affero General
+ Public License, Version 3.0, or any later versions of those
+ licenses.
+
+1.13. "Source Code Form"
+ means the form of the work preferred for making modifications.
+
+1.14. "You" (or "Your")
+ means an individual or a legal entity exercising rights under this
+ License. For legal entities, "You" includes any entity that
+ controls, is controlled by, or is under common control with You. For
+ purposes of this definition, "control" means (a) the power, direct
+ or indirect, to cause the direction or management of such entity,
+ whether by contract or otherwise, or (b) ownership of more than
+ fifty percent (50%) of the outstanding shares or beneficial
+ ownership of such entity.
+
+2. License Grants and Conditions
+--------------------------------
+
+2.1. Grants
+
+Each Contributor hereby grants You a world-wide, royalty-free,
+non-exclusive license:
+
+(a) under intellectual property rights (other than patent or trademark)
+ Licensable by such Contributor to use, reproduce, make available,
+ modify, display, perform, distribute, and otherwise exploit its
+ Contributions, either on an unmodified basis, with Modifications, or
+ as part of a Larger Work; and
+
+(b) under Patent Claims of such Contributor to make, use, sell, offer
+ for sale, have made, import, and otherwise transfer either its
+ Contributions or its Contributor Version.
+
+2.2. Effective Date
+
+The licenses granted in Section 2.1 with respect to any Contribution
+become effective for each Contribution on the date the Contributor first
+distributes such Contribution.
+
+2.3. Limitations on Grant Scope
+
+The licenses granted in this Section 2 are the only rights granted under
+this License. No additional rights or licenses will be implied from the
+distribution or licensing of Covered Software under this License.
+Notwithstanding Section 2.1(b) above, no patent license is granted by a
+Contributor:
+
+(a) for any code that a Contributor has removed from Covered Software;
+ or
+
+(b) for infringements caused by: (i) Your and any other third party's
+ modifications of Covered Software, or (ii) the combination of its
+ Contributions with other software (except as part of its Contributor
+ Version); or
+
+(c) under Patent Claims infringed by Covered Software in the absence of
+ its Contributions.
+
+This License does not grant any rights in the trademarks, service marks,
+or logos of any Contributor (except as may be necessary to comply with
+the notice requirements in Section 3.4).
+
+2.4. Subsequent Licenses
+
+No Contributor makes additional grants as a result of Your choice to
+distribute the Covered Software under a subsequent version of this
+License (see Section 10.2) or under the terms of a Secondary License (if
+permitted under the terms of Section 3.3).
+
+2.5. Representation
+
+Each Contributor represents that the Contributor believes its
+Contributions are its original creation(s) or it has sufficient rights
+to grant the rights to its Contributions conveyed by this License.
+
+2.6. Fair Use
+
+This License is not intended to limit any rights You have under
+applicable copyright doctrines of fair use, fair dealing, or other
+equivalents.
+
+2.7. Conditions
+
+Sections 3.1, 3.2, 3.3, and 3.4 are conditions of the licenses granted
+in Section 2.1.
+
+3. Responsibilities
+-------------------
+
+3.1. Distribution of Source Form
+
+All distribution of Covered Software in Source Code Form, including any
+Modifications that You create or to which You contribute, must be under
+the terms of this License. You must inform recipients that the Source
+Code Form of the Covered Software is governed by the terms of this
+License, and how they can obtain a copy of this License. You may not
+attempt to alter or restrict the recipients' rights in the Source Code
+Form.
+
+3.2. Distribution of Executable Form
+
+If You distribute Covered Software in Executable Form then:
+
+(a) such Covered Software must also be made available in Source Code
+ Form, as described in Section 3.1, and You must inform recipients of
+ the Executable Form how they can obtain a copy of such Source Code
+ Form by reasonable means in a timely manner, at a charge no more
+ than the cost of distribution to the recipient; and
+
+(b) You may distribute such Executable Form under the terms of this
+ License, or sublicense it under different terms, provided that the
+ license for the Executable Form does not attempt to limit or alter
+ the recipients' rights in the Source Code Form under this License.
+
+3.3. Distribution of a Larger Work
+
+You may create and distribute a Larger Work under terms of Your choice,
+provided that You also comply with the requirements of this License for
+the Covered Software. If the Larger Work is a combination of Covered
+Software with a work governed by one or more Secondary Licenses, and the
+Covered Software is not Incompatible With Secondary Licenses, this
+License permits You to additionally distribute such Covered Software
+under the terms of such Secondary License(s), so that the recipient of
+the Larger Work may, at their option, further distribute the Covered
+Software under the terms of either this License or such Secondary
+License(s).
+
+3.4. Notices
+
+You may not remove or alter the substance of any license notices
+(including copyright notices, patent notices, disclaimers of warranty,
+or limitations of liability) contained within the Source Code Form of
+the Covered Software, except that You may alter any license notices to
+the extent required to remedy known factual inaccuracies.
+
+3.5. Application of Additional Terms
+
+You may choose to offer, and to charge a fee for, warranty, support,
+indemnity or liability obligations to one or more recipients of Covered
+Software. However, You may do so only on Your own behalf, and not on
+behalf of any Contributor. You must make it absolutely clear that any
+such warranty, support, indemnity, or liability obligation is offered by
+You alone, and You hereby agree to indemnify every Contributor for any
+liability incurred by such Contributor as a result of warranty, support,
+indemnity or liability terms You offer. You may include additional
+disclaimers of warranty and limitations of liability specific to any
+jurisdiction.
+
+4. Inability to Comply Due to Statute or Regulation
+---------------------------------------------------
+
+If it is impossible for You to comply with any of the terms of this
+License with respect to some or all of the Covered Software due to
+statute, judicial order, or regulation then You must: (a) comply with
+the terms of this License to the maximum extent possible; and (b)
+describe the limitations and the code they affect. Such description must
+be placed in a text file included with all distributions of the Covered
+Software under this License. Except to the extent prohibited by statute
+or regulation, such description must be sufficiently detailed for a
+recipient of ordinary skill to be able to understand it.
+
+5. Termination
+--------------
+
+5.1. The rights granted under this License will terminate automatically
+if You fail to comply with any of its terms. However, if You become
+compliant, then the rights granted under this License from a particular
+Contributor are reinstated (a) provisionally, unless and until such
+Contributor explicitly and finally terminates Your grants, and (b) on an
+ongoing basis, if such Contributor fails to notify You of the
+non-compliance by some reasonable means prior to 60 days after You have
+come back into compliance. Moreover, Your grants from a particular
+Contributor are reinstated on an ongoing basis if such Contributor
+notifies You of the non-compliance by some reasonable means, this is the
+first time You have received notice of non-compliance with this License
+from such Contributor, and You become compliant prior to 30 days after
+Your receipt of the notice.
+
+5.2. If You initiate litigation against any entity by asserting a patent
+infringement claim (excluding declaratory judgment actions,
+counter-claims, and cross-claims) alleging that a Contributor Version
+directly or indirectly infringes any patent, then the rights granted to
+You by any and all Contributors for the Covered Software under Section
+2.1 of this License shall terminate.
+
+5.3. In the event of termination under Sections 5.1 or 5.2 above, all
+end user license agreements (excluding distributors and resellers) which
+have been validly granted by You or Your distributors under this License
+prior to termination shall survive termination.
+
+************************************************************************
+* *
+* 6. Disclaimer of Warranty *
+* ------------------------- *
+* *
+* Covered Software is provided under this License on an "as is" *
+* basis, without warranty of any kind, either expressed, implied, or *
+* statutory, including, without limitation, warranties that the *
+* Covered Software is free of defects, merchantable, fit for a *
+* particular purpose or non-infringing. The entire risk as to the *
+* quality and performance of the Covered Software is with You. *
+* Should any Covered Software prove defective in any respect, You *
+* (not any Contributor) assume the cost of any necessary servicing, *
+* repair, or correction. This disclaimer of warranty constitutes an *
+* essential part of this License. No use of any Covered Software is *
+* authorized under this License except under this disclaimer. *
+* *
+************************************************************************
+
+************************************************************************
+* *
+* 7. Limitation of Liability *
+* -------------------------- *
+* *
+* Under no circumstances and under no legal theory, whether tort *
+* (including negligence), contract, or otherwise, shall any *
+* Contributor, or anyone who distributes Covered Software as *
+* permitted above, be liable to You for any direct, indirect, *
+* special, incidental, or consequential damages of any character *
+* including, without limitation, damages for lost profits, loss of *
+* goodwill, work stoppage, computer failure or malfunction, or any *
+* and all other commercial damages or losses, even if such party *
+* shall have been informed of the possibility of such damages. This *
+* limitation of liability shall not apply to liability for death or *
+* personal injury resulting from such party's negligence to the *
+* extent applicable law prohibits such limitation. Some *
+* jurisdictions do not allow the exclusion or limitation of *
+* incidental or consequential damages, so this exclusion and *
+* limitation may not apply to You. *
+* *
+************************************************************************
+
+8. Litigation
+-------------
+
+Any litigation relating to this License may be brought only in the
+courts of a jurisdiction where the defendant maintains its principal
+place of business and such litigation shall be governed by laws of that
+jurisdiction, without reference to its conflict-of-law provisions.
+Nothing in this Section shall prevent a party's ability to bring
+cross-claims or counter-claims.
+
+9. Miscellaneous
+----------------
+
+This License represents the complete agreement concerning the subject
+matter hereof. If any provision of this License is held to be
+unenforceable, such provision shall be reformed only to the extent
+necessary to make it enforceable. Any law or regulation which provides
+that the language of a contract shall be construed against the drafter
+shall not be used to construe this License against a Contributor.
+
+10. Versions of the License
+---------------------------
+
+10.1. New Versions
+
+Mozilla Foundation is the license steward. Except as provided in Section
+10.3, no one other than the license steward has the right to modify or
+publish new versions of this License. Each version will be given a
+distinguishing version number.
+
+10.2. Effect of New Versions
+
+You may distribute the Covered Software under the terms of the version
+of the License under which You originally received the Covered Software,
+or under the terms of any subsequent version published by the license
+steward.
+
+10.3. Modified Versions
+
+If you create software not governed by this License, and you want to
+create a new license for such software, you may create and use a
+modified version of this License if you rename the license and remove
+any references to the name of the license steward (except to note that
+such modified license differs from this License).
+
+10.4. Distributing Source Code Form that is Incompatible With Secondary
+Licenses
+
+If You choose to distribute Source Code Form that is Incompatible With
+Secondary Licenses under the terms of this version of the License, the
+notice described in Exhibit B of this License must be attached.
+
+Exhibit A - Source Code Form License Notice
+-------------------------------------------
+
+ This Source Code Form is subject to the terms of the Mozilla Public
+ License, v. 2.0. If a copy of the MPL was not distributed with this
+ file, You can obtain one at http://mozilla.org/MPL/2.0/.
+
+If it is not possible or desirable to put the notice in a particular
+file, then You may include the notice in a location (such as a LICENSE
+file in a relevant directory) where a recipient would be likely to look
+for such a notice.
+
+You may add additional accurate notices of copyright ownership.
+
+Exhibit B - "Incompatible With Secondary Licenses" Notice
+---------------------------------------------------------
+
+ This Source Code Form is "Incompatible With Secondary Licenses", as
+ defined by the Mozilla Public License, v. 2.0.
diff --git a/vendor/github.com/mitchellh/packer/builder/oracle/oci/artifact.go b/vendor/github.com/mitchellh/packer/builder/oracle/oci/artifact.go
new file mode 100644
index 00000000..6684468f
--- /dev/null
+++ b/vendor/github.com/mitchellh/packer/builder/oracle/oci/artifact.go
@@ -0,0 +1,45 @@
+package oci
+
+import (
+ "fmt"
+ client "github.com/hashicorp/packer/builder/oracle/oci/client"
+)
+
+// Artifact is an artifact implementation that contains a built Custom Image.
+type Artifact struct {
+ Image client.Image
+ Region string
+ driver Driver
+}
+
+// BuilderId uniquely identifies the builder.
+func (a *Artifact) BuilderId() string {
+ return BuilderId
+}
+
+// Files lists the files associated with an artifact. We don't have any files
+// as the custom image is stored server side.
+func (a *Artifact) Files() []string {
+ return nil
+}
+
+// Id returns the OCID of the associated Image.
+func (a *Artifact) Id() string {
+ return a.Image.ID
+}
+
+func (a *Artifact) String() string {
+ return fmt.Sprintf(
+ "An image was created: '%v' (OCID: %v) in region '%v'",
+ a.Image.DisplayName, a.Image.ID, a.Region,
+ )
+}
+
+func (a *Artifact) State(name string) interface{} {
+ return nil
+}
+
+// Destroy deletes the custom image associated with the artifact.
+func (a *Artifact) Destroy() error {
+ return a.driver.DeleteImage(a.Image.ID)
+}
diff --git a/vendor/github.com/mitchellh/packer/builder/oracle/oci/artifact_test.go b/vendor/github.com/mitchellh/packer/builder/oracle/oci/artifact_test.go
new file mode 100644
index 00000000..5cfbc1cb
--- /dev/null
+++ b/vendor/github.com/mitchellh/packer/builder/oracle/oci/artifact_test.go
@@ -0,0 +1,15 @@
+package oci
+
+import (
+ "testing"
+
+ "github.com/hashicorp/packer/packer"
+)
+
+func TestArtifactImpl(t *testing.T) {
+ var raw interface{}
+ raw = &Artifact{}
+ if _, ok := raw.(packer.Artifact); !ok {
+ t.Fatalf("Artifact should be artifact")
+ }
+}
diff --git a/vendor/github.com/mitchellh/packer/builder/oracle/oci/builder.go b/vendor/github.com/mitchellh/packer/builder/oracle/oci/builder.go
new file mode 100644
index 00000000..5eedaa0b
--- /dev/null
+++ b/vendor/github.com/mitchellh/packer/builder/oracle/oci/builder.go
@@ -0,0 +1,96 @@
+// Package oci contains a packer.Builder implementation that builds Oracle
+// Bare Metal Cloud Services (OCI) images.
+package oci
+
+import (
+ "fmt"
+ "log"
+
+ client "github.com/hashicorp/packer/builder/oracle/oci/client"
+ "github.com/hashicorp/packer/common"
+ "github.com/hashicorp/packer/helper/communicator"
+ "github.com/hashicorp/packer/packer"
+ "github.com/mitchellh/multistep"
+)
+
+// BuilderId uniquely identifies the builder
+const BuilderId = "packer.oracle.oci"
+
+// OCI API version
+const ociAPIVersion = "20160918"
+
+// Builder is a builder implementation that creates Oracle OCI custom images.
+type Builder struct {
+ config *Config
+ runner multistep.Runner
+}
+
+func (b *Builder) Prepare(rawConfig ...interface{}) ([]string, error) {
+ config, err := NewConfig(rawConfig...)
+ if err != nil {
+ return nil, err
+ }
+ b.config = config
+
+ return nil, nil
+}
+
+func (b *Builder) Run(ui packer.Ui, hook packer.Hook, cache packer.Cache) (packer.Artifact, error) {
+ driver, err := NewDriverOCI(b.config)
+ if err != nil {
+ return nil, err
+ }
+
+ // Populate the state bag
+ state := new(multistep.BasicStateBag)
+ state.Put("config", b.config)
+ state.Put("driver", driver)
+ state.Put("hook", hook)
+ state.Put("ui", ui)
+
+ // Build the steps
+ steps := []multistep.Step{
+ &stepKeyPair{
+ Debug: b.config.PackerDebug,
+ DebugKeyPath: fmt.Sprintf("oci_%s.pem", b.config.PackerBuildName),
+ PrivateKeyFile: b.config.Comm.SSHPrivateKey,
+ },
+ &stepCreateInstance{},
+ &stepInstanceInfo{},
+ &communicator.StepConnect{
+ Config: &b.config.Comm,
+ Host: commHost,
+ SSHConfig: SSHConfig(
+ b.config.Comm.SSHUsername,
+ b.config.Comm.SSHPassword),
+ },
+ &common.StepProvision{},
+ &stepImage{},
+ }
+
+ // Run the steps
+ b.runner = common.NewRunnerWithPauseFn(steps, b.config.PackerConfig, ui, state)
+ b.runner.Run(state)
+
+ // If there was an error, return that
+ if rawErr, ok := state.GetOk("error"); ok {
+ return nil, rawErr.(error)
+ }
+
+ // Build the artifact and return it
+ artifact := &Artifact{
+ Image: state.Get("image").(client.Image),
+ Region: b.config.AccessCfg.Region,
+ driver: driver,
+ }
+
+ return artifact, nil
+}
+
+// Cancel terminates a running build.
+func (b *Builder) Cancel() {
+ if b.runner != nil {
+ log.Println("Cancelling the step runner...")
+ b.runner.Cancel()
+ }
+}
diff --git a/vendor/github.com/mitchellh/packer/builder/oracle/oci/builder_test.go b/vendor/github.com/mitchellh/packer/builder/oracle/oci/builder_test.go
new file mode 100644
index 00000000..80500ef5
--- /dev/null
+++ b/vendor/github.com/mitchellh/packer/builder/oracle/oci/builder_test.go
@@ -0,0 +1,15 @@
+package oci
+
+import (
+ "testing"
+
+ "github.com/hashicorp/packer/packer"
+)
+
+func TestBuilder_ImplementsBuilder(t *testing.T) {
+ var raw interface{}
+ raw = &Builder{}
+ if _, ok := raw.(packer.Builder); !ok {
+ t.Fatalf("Builder should be a builder")
+ }
+}
diff --git a/vendor/github.com/mitchellh/packer/builder/oracle/oci/client/base_client.go b/vendor/github.com/mitchellh/packer/builder/oracle/oci/client/base_client.go
new file mode 100644
index 00000000..7270687e
--- /dev/null
+++ b/vendor/github.com/mitchellh/packer/builder/oracle/oci/client/base_client.go
@@ -0,0 +1,215 @@
+package oci
+
+import (
+ "bytes"
+ "encoding/json"
+ "github.com/google/go-querystring/query"
+ "net/http"
+ "net/url"
+)
+
+const (
+ contentType = "Content-Type"
+ jsonContentType = "application/json"
+)
+
+// baseClient provides a basic (AND INTENTIONALLY INCOMPLETE) JSON REST client
+// that abstracts away some of the repetitive code required in the OCI Client.
+type baseClient struct {
+ httpClient *http.Client
+ method string
+ url string
+ queryStruct interface{}
+ header http.Header
+ body interface{}
+}
+
+// newBaseClient constructs a default baseClient.
+func newBaseClient() *baseClient {
+ return &baseClient{
+ httpClient: http.DefaultClient,
+ method: "GET",
+ header: make(http.Header),
+ }
+}
+
+// New creates a copy of an existing baseClient.
+func (c *baseClient) New() *baseClient {
+ // Copy headers
+ header := make(http.Header)
+ for k, v := range c.header {
+ header[k] = v
+ }
+
+ return &baseClient{
+ httpClient: c.httpClient,
+ method: c.method,
+ url: c.url,
+ header: header,
+ }
+}
+
+// Client sets the http Client used to perform requests.
+func (c *baseClient) Client(httpClient *http.Client) *baseClient {
+ if httpClient == nil {
+ c.httpClient = http.DefaultClient
+ } else {
+ c.httpClient = httpClient
+ }
+ return c
+}
+
+// Base sets the base client url.
+func (c *baseClient) Base(path string) *baseClient {
+ c.url = path
+ return c
+}
+
+// Path extends the client url.
+func (c *baseClient) Path(path string) *baseClient {
+ baseURL, baseErr := url.Parse(c.url)
+ pathURL, pathErr := url.Parse(path)
+ // Bail on parsing error leaving the client's url unmodified
+ if baseErr != nil || pathErr != nil {
+ return c
+ }
+
+ c.url = baseURL.ResolveReference(pathURL).String()
+ return c
+}
+
+// QueryStruct sets the struct from which the request querystring is built.
+func (c *baseClient) QueryStruct(params interface{}) *baseClient {
+ c.queryStruct = params
+ return c
+}
+
+// SetBody wraps a given struct for serialisation and sets the client body.
+func (c *baseClient) SetBody(params interface{}) *baseClient {
+ c.body = params
+ return c
+}
+
+// Header
+
+// AddHeader adds a HTTP header to the client. Existing keys will be extended.
+func (c *baseClient) AddHeader(key, value string) *baseClient {
+ c.header.Add(key, value)
+ return c
+}
+
+// SetHeader sets a HTTP header on the client. Existing keys will be
+// overwritten.
+func (c *baseClient) SetHeader(key, value string) *baseClient {
+ c.header.Add(key, value)
+ return c
+}
+
+// HTTP methods (subset)
+
+// Get sets the client's HTTP method to GET.
+func (c *baseClient) Get(path string) *baseClient {
+ c.method = "GET"
+ return c.Path(path)
+}
+
+// Post sets the client's HTTP method to POST.
+func (c *baseClient) Post(path string) *baseClient {
+ c.method = "POST"
+ return c.Path(path)
+}
+
+// Delete sets the client's HTTP method to DELETE.
+func (c *baseClient) Delete(path string) *baseClient {
+ c.method = "DELETE"
+ return c.Path(path)
+}
+
+// Do executes a HTTP request and returns the response encoded as either error
+// or success values.
+func (c *baseClient) Do(req *http.Request, successV, failureV interface{}) (*http.Response, error) {
+ resp, err := c.httpClient.Do(req)
+ if err != nil {
+ return nil, err
+ }
+ defer resp.Body.Close()
+
+ if resp.StatusCode >= 200 && resp.StatusCode < 300 {
+ if successV != nil {
+ err = json.NewDecoder(resp.Body).Decode(successV)
+ }
+ } else {
+ if failureV != nil {
+ err = json.NewDecoder(resp.Body).Decode(failureV)
+ }
+ }
+
+ return resp, err
+}
+
+// Request builds a http.Request from the baseClient instance.
+func (c *baseClient) Request() (*http.Request, error) {
+ reqURL, err := url.Parse(c.url)
+ if err != nil {
+ return nil, err
+ }
+
+ if c.queryStruct != nil {
+ err = addQueryStruct(reqURL, c.queryStruct)
+ if err != nil {
+ return nil, err
+ }
+ }
+
+ body := &bytes.Buffer{}
+ if c.body != nil {
+ if err := json.NewEncoder(body).Encode(c.body); err != nil {
+ return nil, err
+ }
+ }
+
+ req, err := http.NewRequest(c.method, reqURL.String(), body)
+ if err != nil {
+ return nil, err
+ }
+
+ // Add headers to request
+ for k, vs := range c.header {
+ for _, v := range vs {
+ req.Header.Add(k, v)
+ }
+ }
+
+ return req, nil
+}
+
+// Recieve creates a http request from the client and executes it returning the
+// response.
+func (c *baseClient) Receive(successV, failureV interface{}) (*http.Response, error) {
+ req, err := c.Request()
+ if err != nil {
+ return nil, err
+ }
+ return c.Do(req, successV, failureV)
+}
+
+// addQueryStruct converts a struct to a querystring and merges any values
+// provided in the URL itself.
+func addQueryStruct(reqURL *url.URL, queryStruct interface{}) error {
+ urlValues, err := url.ParseQuery(reqURL.RawQuery)
+ if err != nil {
+ return err
+ }
+ queryValues, err := query.Values(queryStruct)
+ if err != nil {
+ return err
+ }
+
+ for k, vs := range queryValues {
+ for _, v := range vs {
+ urlValues.Add(k, v)
+ }
+ }
+ reqURL.RawQuery = urlValues.Encode()
+ return nil
+}
diff --git a/vendor/github.com/mitchellh/packer/builder/oracle/oci/client/client.go b/vendor/github.com/mitchellh/packer/builder/oracle/oci/client/client.go
new file mode 100644
index 00000000..8e6c1762
--- /dev/null
+++ b/vendor/github.com/mitchellh/packer/builder/oracle/oci/client/client.go
@@ -0,0 +1,31 @@
+package oci
+
+import (
+ "net/http"
+)
+
+const (
+ apiVersion = "20160918"
+ userAgent = "go-oci/" + apiVersion
+ baseURLPattern = "https://%s.%s.oraclecloud.com/%s/"
+)
+
+// Client is the main interface through which consumers interact with the OCI
+// API.
+type Client struct {
+ UserAgent string
+ Compute *ComputeClient
+ Config *Config
+}
+
+// NewClient creates a new Client for communicating with the OCI API.
+func NewClient(config *Config) (*Client, error) {
+ transport := NewTransport(http.DefaultTransport, config)
+ base := newBaseClient().Client(&http.Client{Transport: transport})
+
+ return &Client{
+ UserAgent: userAgent,
+ Compute: NewComputeClient(base.New().Base(config.getBaseURL("iaas"))),
+ Config: config,
+ }, nil
+}
diff --git a/vendor/github.com/mitchellh/packer/builder/oracle/oci/client/client_test.go b/vendor/github.com/mitchellh/packer/builder/oracle/oci/client/client_test.go
new file mode 100644
index 00000000..f2ebd8f8
--- /dev/null
+++ b/vendor/github.com/mitchellh/packer/builder/oracle/oci/client/client_test.go
@@ -0,0 +1,49 @@
+package oci
+
+import (
+ "net/http"
+ "net/http/httptest"
+ "net/url"
+ "os"
+
+ "github.com/go-ini/ini"
+)
+
+var (
+ mux *http.ServeMux
+ client *Client
+ server *httptest.Server
+ keyFile *os.File
+)
+
+// setup sets up a test HTTP server along with a oci.Client that is
+// configured to talk to that test server. Tests should register handlers on
+// mux which provide mock responses for the API method being tested.
+func setup() {
+ mux = http.NewServeMux()
+ server = httptest.NewServer(mux)
+ parsedURL, _ := url.Parse(server.URL)
+
+ config := &Config{}
+ config.baseURL = parsedURL.String()
+
+ var cfg *ini.File
+ var err error
+ cfg, keyFile, err = BaseTestConfig()
+
+ config, err = loadConfigSection(cfg, "DEFAULT", config)
+ if err != nil {
+ panic(err)
+ }
+
+ client, err = NewClient(config)
+ if err != nil {
+ panic("Failed to instantiate test client")
+ }
+}
+
+// teardown closes the test HTTP server
+func teardown() {
+ server.Close()
+ os.Remove(keyFile.Name())
+}
diff --git a/vendor/github.com/mitchellh/packer/builder/oracle/oci/client/compute.go b/vendor/github.com/mitchellh/packer/builder/oracle/oci/client/compute.go
new file mode 100644
index 00000000..183a3794
--- /dev/null
+++ b/vendor/github.com/mitchellh/packer/builder/oracle/oci/client/compute.go
@@ -0,0 +1,21 @@
+package oci
+
+// ComputeClient is a client for the OCI Compute API.
+type ComputeClient struct {
+ BaseURL string
+ Instances *InstanceService
+ Images *ImageService
+ VNICAttachments *VNICAttachmentService
+ VNICs *VNICService
+}
+
+// NewComputeClient creates a new client for communicating with the OCI
+// Compute API.
+func NewComputeClient(s *baseClient) *ComputeClient {
+ return &ComputeClient{
+ Instances: NewInstanceService(s),
+ Images: NewImageService(s),
+ VNICAttachments: NewVNICAttachmentService(s),
+ VNICs: NewVNICService(s),
+ }
+}
diff --git a/vendor/github.com/mitchellh/packer/builder/oracle/oci/client/config.go b/vendor/github.com/mitchellh/packer/builder/oracle/oci/client/config.go
new file mode 100644
index 00000000..580cd9f7
--- /dev/null
+++ b/vendor/github.com/mitchellh/packer/builder/oracle/oci/client/config.go
@@ -0,0 +1,240 @@
+package oci
+
+import (
+ "crypto/rand"
+ "crypto/rsa"
+ "crypto/x509"
+ "encoding/pem"
+ "errors"
+ "fmt"
+ "io/ioutil"
+ "os"
+
+ "github.com/go-ini/ini"
+ "github.com/mitchellh/go-homedir"
+)
+
+// Config API authentication and target configuration
+type Config struct {
+ // User OCID e.g. ocid1.user.oc1..aaaaaaaadcshyehbkvxl7arse3lv7z5oknexjgfhnhwidtugsxhlm4247
+ User string `ini:"user"`
+
+ // User's Tenancy OCID e.g. ocid1.tenancy.oc1..aaaaaaaagtgvshv6opxzjyzkupkt64ymd32n6kbomadanpcg43d
+ Tenancy string `ini:"tenancy"`
+
+ // Bare metal region identifier (e.g. us-phoenix-1)
+ Region string `ini:"region"`
+
+ // Hex key fingerprint (e.g. b5:a0:62:57:28:0d:fd:c9:59:16:eb:d4:51:9f:70:e4)
+ Fingerprint string `ini:"fingerprint"`
+
+ // Path to OCI config file (e.g. ~/.oci/config)
+ KeyFile string `ini:"key_file"`
+
+ // Passphrase used for the key, if it is encrypted.
+ PassPhrase string `ini:"pass_phrase"`
+
+ // Private key (loaded via LoadPrivateKey or ParsePrivateKey)
+ Key *rsa.PrivateKey
+
+ // Used to override base API URL.
+ baseURL string
+}
+
+// getBaseURL returns either the specified base URL or builds the appropriate
+// URL based on service, region, and API version.
+func (c *Config) getBaseURL(service string) string {
+ if c.baseURL != "" {
+ return c.baseURL
+ }
+ return fmt.Sprintf(baseURLPattern, service, c.Region, apiVersion)
+}
+
+// LoadConfigsFromFile loads all oracle oci configurations from a file
+// (generally ~/.oci/config).
+func LoadConfigsFromFile(path string) (map[string]*Config, error) {
+ if _, err := os.Stat(path); err != nil {
+ return nil, fmt.Errorf("Oracle OCI config file is missing: %s", path)
+ }
+
+ cfgFile, err := ini.Load(path)
+ if err != nil {
+ err := fmt.Errorf("Failed to parse config file %s: %s", path, err.Error())
+ return nil, err
+ }
+
+ configs := make(map[string]*Config)
+
+ // Load DEFAULT section to populate defaults for all other configs
+ config, err := loadConfigSection(cfgFile, "DEFAULT", nil)
+ if err != nil {
+ return nil, err
+ }
+ configs["DEFAULT"] = config
+
+ // Load other sections.
+ for _, sectionName := range cfgFile.SectionStrings() {
+ if sectionName == "DEFAULT" {
+ continue
+ }
+
+ // Map to Config struct with defaults from DEFAULT section.
+ config, err := loadConfigSection(cfgFile, sectionName, configs["DEFAULT"])
+ if err != nil {
+ return nil, err
+ }
+ configs[sectionName] = config
+ }
+
+ return configs, nil
+}
+
+// Loads an individual Config object from a ini.Section in the Oracle OCI config
+// file.
+func loadConfigSection(f *ini.File, sectionName string, config *Config) (*Config, error) {
+ if config == nil {
+ config = &Config{}
+ }
+
+ section, err := f.GetSection(sectionName)
+ if err != nil {
+ return nil, fmt.Errorf("Config file does not contain a %s section", sectionName)
+ }
+
+ if err := section.MapTo(config); err != nil {
+ return nil, err
+ }
+
+ config.Key, err = LoadPrivateKey(config)
+ if err != nil {
+ return nil, err
+ }
+
+ return config, err
+}
+
+// LoadPrivateKey loads private key from disk and parses it.
+func LoadPrivateKey(config *Config) (*rsa.PrivateKey, error) {
+ // Expand '~' to $HOME
+ path, err := homedir.Expand(config.KeyFile)
+ if err != nil {
+ return nil, err
+ }
+
+ // Read and parse API signing key
+ keyContent, err := ioutil.ReadFile(path)
+ if err != nil {
+ return nil, err
+ }
+ key, err := ParsePrivateKey(keyContent, []byte(config.PassPhrase))
+
+ return key, err
+}
+
+// ParsePrivateKey parses a PEM encoded array of bytes into an rsa.PrivateKey.
+// Attempts to decrypt the PEM encoded array of bytes with the given password
+// if the PEM encoded byte array is encrypted.
+func ParsePrivateKey(content, password []byte) (*rsa.PrivateKey, error) {
+ keyBlock, _ := pem.Decode(content)
+
+ if keyBlock == nil {
+ return nil, errors.New("could not decode PEM private key")
+ }
+
+ var der []byte
+ var err error
+ if x509.IsEncryptedPEMBlock(keyBlock) {
+ if len(password) < 1 {
+ return nil, errors.New("encrypted private key but no pass phrase provided")
+ }
+ der, err = x509.DecryptPEMBlock(keyBlock, password)
+ if err != nil {
+ return nil, err
+ }
+ } else {
+ der = keyBlock.Bytes
+ }
+
+ if key, err := x509.ParsePKCS1PrivateKey(der); err == nil {
+ return key, nil
+ }
+
+ key, err := x509.ParsePKCS8PrivateKey(der)
+ if err == nil {
+ switch key := key.(type) {
+ case *rsa.PrivateKey:
+ return key, nil
+ default:
+ return nil, errors.New("Private key is not an RSA private key")
+ }
+ }
+ return nil, fmt.Errorf("Failed to parse private key :%s", err)
+}
+
+// BaseTestConfig creates the base (DEFAULT) config including a temporary key
+// file.
+// NOTE: Caller is responsible for removing temporary key file.
+func BaseTestConfig() (*ini.File, *os.File, error) {
+ keyFile, err := generateRSAKeyFile()
+ if err != nil {
+ return nil, keyFile, err
+ }
+ // Build ini
+ cfg := ini.Empty()
+ section, _ := cfg.NewSection("DEFAULT")
+ section.NewKey("region", "us-phoenix-1")
+ section.NewKey("tenancy", "ocid1.tenancy.oc1..aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa")
+ section.NewKey("user", "ocid1.user.oc1..aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa")
+ section.NewKey("fingerprint", "3c:b6:44:d7:49:1a:ac:bf:de:7d:76:22:a7:f5:df:55")
+ section.NewKey("key_file", keyFile.Name())
+
+ return cfg, keyFile, nil
+}
+
+// WriteTestConfig writes a ini.File to a temporary file for use in unit tests.
+// NOTE: Caller is responsible for removing temporary file.
+func WriteTestConfig(cfg *ini.File) (*os.File, error) {
+ confFile, err := ioutil.TempFile("", "config_file")
+ if err != nil {
+ return nil, err
+ }
+
+ _, err = cfg.WriteTo(confFile)
+ if err != nil {
+ os.Remove(confFile.Name())
+ return nil, err
+ }
+
+ return confFile, nil
+}
+
+// generateRSAKeyFile generates an RSA key file for use in unit tests.
+// NOTE: The caller is responsible for deleting the temporary file.
+func generateRSAKeyFile() (*os.File, error) {
+ // Create temporary file for the key
+ f, err := ioutil.TempFile("", "key")
+ if err != nil {
+ return nil, err
+ }
+
+ // Generate key
+ priv, err := rsa.GenerateKey(rand.Reader, 2014)
+ if err != nil {
+ return nil, err
+ }
+
+ // ASN.1 DER encoded form
+ privDer := x509.MarshalPKCS1PrivateKey(priv)
+ privBlk := pem.Block{
+ Type: "RSA PRIVATE KEY",
+ Headers: nil,
+ Bytes: privDer,
+ }
+
+ // Write the key out
+ if _, err := f.Write(pem.EncodeToMemory(&privBlk)); err != nil {
+ return nil, err
+ }
+
+ return f, nil
+}
diff --git a/vendor/github.com/mitchellh/packer/builder/oracle/oci/client/config_test.go b/vendor/github.com/mitchellh/packer/builder/oracle/oci/client/config_test.go
new file mode 100644
index 00000000..08f0b806
--- /dev/null
+++ b/vendor/github.com/mitchellh/packer/builder/oracle/oci/client/config_test.go
@@ -0,0 +1,283 @@
+package oci
+
+import (
+ "crypto/rand"
+ "crypto/rsa"
+ "crypto/x509"
+ "encoding/asn1"
+ "encoding/pem"
+ "os"
+ "reflect"
+ "strings"
+ "testing"
+)
+
+func TestNewConfigMissingFile(t *testing.T) {
+ // WHEN
+ _, err := LoadConfigsFromFile("some/invalid/path")
+
+ // THEN
+
+ if err == nil {
+ t.Error("Expected missing file error")
+ }
+}
+
+func TestNewConfigDefaultOnly(t *testing.T) {
+ // GIVEN
+
+ // Get DEFAULT config
+ cfg, keyFile, err := BaseTestConfig()
+ defer os.Remove(keyFile.Name())
+
+ // Write test config to file
+ f, err := WriteTestConfig(cfg)
+ if err != nil {
+ t.Fatal(err)
+ }
+ defer os.Remove(f.Name()) // clean up
+
+ // WHEN
+
+ // Load configs
+ cfgs, err := LoadConfigsFromFile(f.Name())
+ if err != nil {
+ t.Fatal(err)
+ }
+
+ // THEN
+
+ if _, ok := cfgs["DEFAULT"]; !ok {
+ t.Fatal("Expected DEFAULT config to exist in map")
+ }
+}
+
+func TestNewConfigDefaultsPopulated(t *testing.T) {
+ // GIVEN
+
+ // Get DEFAULT config
+ cfg, keyFile, err := BaseTestConfig()
+ defer os.Remove(keyFile.Name())
+
+ admin := cfg.Section("ADMIN")
+ admin.NewKey("user", "ocid1.user.oc1..bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb")
+ admin.NewKey("fingerprint", "11:11:11:11:11:11:11:11:11:11:11:11:11:11:11:11")
+
+ // Write test config to file
+ f, err := WriteTestConfig(cfg)
+ if err != nil {
+ t.Fatal(err)
+ }
+ defer os.Remove(f.Name()) // clean up
+
+ // WHEN
+
+ cfgs, err := LoadConfigsFromFile(f.Name())
+ adminConfig, ok := cfgs["ADMIN"]
+
+ // THEN
+
+ if !ok {
+ t.Fatal("Expected ADMIN config to exist in map")
+ }
+
+ if adminConfig.Region != "us-phoenix-1" {
+ t.Errorf("Expected 'us-phoenix-1', got '%s'", adminConfig.Region)
+ }
+}
+
+func TestNewConfigDefaultsOverridden(t *testing.T) {
+ // GIVEN
+
+ // Get DEFAULT config
+ cfg, keyFile, err := BaseTestConfig()
+ defer os.Remove(keyFile.Name())
+
+ admin := cfg.Section("ADMIN")
+ admin.NewKey("user", "ocid1.user.oc1..bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb")
+ admin.NewKey("fingerprint", "11:11:11:11:11:11:11:11:11:11:11:11:11:11:11:11")
+
+ // Write test config to file
+ f, err := WriteTestConfig(cfg)
+ if err != nil {
+ t.Fatal(err)
+ }
+ defer os.Remove(f.Name()) // clean up
+
+ // WHEN
+
+ cfgs, err := LoadConfigsFromFile(f.Name())
+ adminConfig, ok := cfgs["ADMIN"]
+
+ // THEN
+
+ if !ok {
+ t.Fatal("Expected ADMIN config to exist in map")
+ }
+
+ if adminConfig.Fingerprint != "11:11:11:11:11:11:11:11:11:11:11:11:11:11:11:11" {
+ t.Errorf("Expected fingerprint '11:11:11:11:11:11:11:11:11:11:11:11:11:11:11:11', got '%s'",
+ adminConfig.Fingerprint)
+ }
+}
+
+func TestParseEncryptedPrivateKeyValidPassword(t *testing.T) {
+ // Generate private key
+ priv, err := rsa.GenerateKey(rand.Reader, 2014)
+ if err != nil {
+ t.Fatalf("Unexpected generating RSA key: %+v", err)
+ }
+ publicKey := priv.PublicKey
+
+ // ASN.1 DER encoded form
+ privDer := x509.MarshalPKCS1PrivateKey(priv)
+
+ blockType := "RSA PRIVATE KEY"
+ password := []byte("password")
+ cipherType := x509.PEMCipherAES256
+
+ // Encrypt priv with password
+ encryptedPEMBlock, err := x509.EncryptPEMBlock(
+ rand.Reader,
+ blockType,
+ privDer,
+ password,
+ cipherType)
+ if err != nil {
+ t.Fatalf("Unexpected error encryting PEM block: %+v", err)
+ }
+
+ // Parse private key
+ key, err := ParsePrivateKey(pem.EncodeToMemory(encryptedPEMBlock), password)
+ if err != nil {
+ t.Fatalf("unexpected error: %+v", err)
+ }
+
+ // Check we get the same key back
+ if !reflect.DeepEqual(publicKey, key.PublicKey) {
+ t.Errorf("expected public key of encrypted and decrypted key to match")
+ }
+}
+
+func TestParseEncryptedPrivateKeyPKCS8(t *testing.T) {
+ // Generate private key
+ priv, err := rsa.GenerateKey(rand.Reader, 2014)
+ if err != nil {
+ t.Fatalf("Unexpected generating RSA key: %+v", err)
+ }
+ publicKey := priv.PublicKey
+
+ // Implements x509.MarshalPKCS8PrivateKey which is not included in the
+ // standard library.
+ pkey := struct {
+ Version int
+ PrivateKeyAlgorithm []asn1.ObjectIdentifier
+ PrivateKey []byte
+ }{
+ Version: 0,
+ PrivateKeyAlgorithm: []asn1.ObjectIdentifier{{1, 2, 840, 113549, 1, 1, 1}},
+ PrivateKey: x509.MarshalPKCS1PrivateKey(priv),
+ }
+ privDer, err := asn1.Marshal(pkey)
+ if err != nil {
+ t.Fatalf("Unexpected marshaling RSA key: %+v", err)
+ }
+
+ blockType := "RSA PRIVATE KEY"
+ password := []byte("password")
+ cipherType := x509.PEMCipherAES256
+
+ // Encrypt priv with password
+ encryptedPEMBlock, err := x509.EncryptPEMBlock(
+ rand.Reader,
+ blockType,
+ privDer,
+ password,
+ cipherType)
+ if err != nil {
+ t.Fatalf("Unexpected error encryting PEM block: %+v", err)
+ }
+
+ // Parse private key
+ key, err := ParsePrivateKey(pem.EncodeToMemory(encryptedPEMBlock), password)
+ if err != nil {
+ t.Fatalf("unexpected error: %+v", err)
+ }
+
+ // Check we get the same key back
+ if !reflect.DeepEqual(publicKey, key.PublicKey) {
+ t.Errorf("expected public key of encrypted and decrypted key to match")
+ }
+}
+
+func TestParseEncryptedPrivateKeyInvalidPassword(t *testing.T) {
+ // Generate private key
+ priv, err := rsa.GenerateKey(rand.Reader, 2014)
+ if err != nil {
+ t.Fatalf("Unexpected generating RSA key: %+v", err)
+ }
+
+ // ASN.1 DER encoded form
+ privDer := x509.MarshalPKCS1PrivateKey(priv)
+
+ blockType := "RSA PRIVATE KEY"
+ password := []byte("password")
+ cipherType := x509.PEMCipherAES256
+
+ // Encrypt priv with password
+ encryptedPEMBlock, err := x509.EncryptPEMBlock(
+ rand.Reader,
+ blockType,
+ privDer,
+ password,
+ cipherType)
+ if err != nil {
+ t.Fatalf("Unexpected error encrypting PEM block: %+v", err)
+ }
+
+ // Parse private key (with wrong password)
+ _, err = ParsePrivateKey(pem.EncodeToMemory(encryptedPEMBlock), []byte("foo"))
+ if err == nil {
+ t.Fatalf("Expected error, got nil")
+ }
+
+ if !strings.Contains(err.Error(), "decryption password incorrect") {
+ t.Errorf("Expected error to contain 'decryption password incorrect', got %+v", err)
+ }
+}
+
+func TestParseEncryptedPrivateKeyInvalidNoPassword(t *testing.T) {
+ // Generate private key
+ priv, err := rsa.GenerateKey(rand.Reader, 2014)
+ if err != nil {
+ t.Fatalf("Unexpected generating RSA key: %+v", err)
+ }
+
+ // ASN.1 DER encoded form
+ privDer := x509.MarshalPKCS1PrivateKey(priv)
+
+ blockType := "RSA PRIVATE KEY"
+ password := []byte("password")
+ cipherType := x509.PEMCipherAES256
+
+ // Encrypt priv with password
+ encryptedPEMBlock, err := x509.EncryptPEMBlock(
+ rand.Reader,
+ blockType,
+ privDer,
+ password,
+ cipherType)
+ if err != nil {
+ t.Fatalf("Unexpected error encrypting PEM block: %+v", err)
+ }
+
+ // Parse private key (with wrong password)
+ _, err = ParsePrivateKey(pem.EncodeToMemory(encryptedPEMBlock), []byte{})
+ if err == nil {
+ t.Fatalf("Expected error, got nil")
+ }
+
+ if !strings.Contains(err.Error(), "no pass phrase provided") {
+ t.Errorf("Expected error to contain 'no pass phrase provided', got %+v", err)
+ }
+}
diff --git a/vendor/github.com/mitchellh/packer/builder/oracle/oci/client/error.go b/vendor/github.com/mitchellh/packer/builder/oracle/oci/client/error.go
new file mode 100644
index 00000000..a97112f8
--- /dev/null
+++ b/vendor/github.com/mitchellh/packer/builder/oracle/oci/client/error.go
@@ -0,0 +1,27 @@
+package oci
+
+import "fmt"
+
+// APIError encapsulates an error returned from the API
+type APIError struct {
+ Code string `json:"code"`
+ Message string `json:"message"`
+}
+
+func (e APIError) Error() string {
+ return fmt.Sprintf("OCI: [%s] '%s'", e.Code, e.Message)
+}
+
+// firstError is a helper function to work out which error to return from calls
+// to the API.
+func firstError(err error, apiError *APIError) error {
+ if err != nil {
+ return err
+ }
+
+ if apiError != nil && len(apiError.Code) > 0 {
+ return apiError
+ }
+
+ return nil
+}
diff --git a/vendor/github.com/mitchellh/packer/builder/oracle/oci/client/image.go b/vendor/github.com/mitchellh/packer/builder/oracle/oci/client/image.go
new file mode 100644
index 00000000..802b4650
--- /dev/null
+++ b/vendor/github.com/mitchellh/packer/builder/oracle/oci/client/image.go
@@ -0,0 +1,122 @@
+package oci
+
+import (
+ "time"
+)
+
+// ImageService enables communicating with the OCI compute API's instance
+// related endpoints.
+type ImageService struct {
+ client *baseClient
+}
+
+// NewImageService creates a new ImageService for communicating with the
+// OCI compute API's instance related endpoints.
+func NewImageService(s *baseClient) *ImageService {
+ return &ImageService{
+ client: s.New().Path("images/"),
+ }
+}
+
+// Image details a OCI boot disk image.
+type Image struct {
+ // The OCID of the image originally used to launch the instance.
+ BaseImageID string `json:"baseImageId,omitempty"`
+
+ // The OCID of the compartment containing the instance you want to use
+ // as the basis for the image.
+ CompartmentID string `json:"compartmentId"`
+
+ // Whether instances launched with this image can be used to create new
+ // images.
+ CreateImageAllowed bool `json:"createImageAllowed"`
+
+ // A user-friendly name for the image. It does not have to be unique,
+ // and it's changeable. You cannot use an Oracle-provided image name
+ // as a custom image name.
+ DisplayName string `json:"displayName,omitempty"`
+
+ // The OCID of the image.
+ ID string `json:"id"`
+
+ // Current state of the image. Allowed values are:
+ // - PROVISIONING
+ // - AVAILABLE
+ // - DISABLED
+ // - DELETED
+ LifecycleState string `json:"lifecycleState"`
+
+ // The image's operating system (e.g. Oracle Linux).
+ OperatingSystem string `json:"operatingSystem"`
+
+ // The image's operating system version (e.g. 7.2).
+ OperatingSystemVersion string `json:"operatingSystemVersion"`
+
+ // The date and time the image was created.
+ TimeCreated time.Time `json:"timeCreated"`
+}
+
+// GetImageParams are the paramaters available when communicating with the
+// GetImage API endpoint.
+type GetImageParams struct {
+ ID string `url:"imageId"`
+}
+
+// Get returns a single Image
+func (s *ImageService) Get(params *GetImageParams) (Image, error) {
+ image := Image{}
+ e := &APIError{}
+
+ _, err := s.client.New().Get(params.ID).Receive(&image, e)
+ err = firstError(err, e)
+
+ return image, err
+}
+
+// CreateImageParams are the parameters available when communicating with
+// the CreateImage API endpoint.
+type CreateImageParams struct {
+ CompartmentID string `json:"compartmentId"`
+ DisplayName string `json:"displayName,omitempty"`
+ InstanceID string `json:"instanceId"`
+}
+
+// Create creates a new custom image based on a running compute instance. It
+// does *not* wait for the imaging process to finish.
+func (s *ImageService) Create(params *CreateImageParams) (Image, error) {
+ image := Image{}
+ e := &APIError{}
+
+ _, err := s.client.New().Post("").SetBody(params).Receive(&image, &e)
+ err = firstError(err, e)
+
+ return image, err
+}
+
+// GetResourceState GETs the LifecycleState of the given image id.
+func (s *ImageService) GetResourceState(id string) (string, error) {
+ image, err := s.Get(&GetImageParams{ID: id})
+ if err != nil {
+ return "", err
+ }
+ return image.LifecycleState, nil
+
+}
+
+// DeleteImageParams are the parameters available when communicating with
+// the DeleteImage API endpoint.
+type DeleteImageParams struct {
+ ID string `url:"imageId"`
+}
+
+// Delete deletes an existing custom image.
+// NOTE: Deleting an image results in the API endpoint returning 404 on
+// subsequent calls. As such deletion can't be waited on with a Waiter.
+func (s *ImageService) Delete(params *DeleteImageParams) error {
+ e := &APIError{}
+
+ _, err := s.client.New().Delete(params.ID).SetBody(params).Receive(nil, e)
+ err = firstError(err, e)
+
+ return err
+}
diff --git a/vendor/github.com/mitchellh/packer/builder/oracle/oci/client/image_test.go b/vendor/github.com/mitchellh/packer/builder/oracle/oci/client/image_test.go
new file mode 100644
index 00000000..ef55cc55
--- /dev/null
+++ b/vendor/github.com/mitchellh/packer/builder/oracle/oci/client/image_test.go
@@ -0,0 +1,115 @@
+package oci
+
+import (
+ "fmt"
+ "net/http"
+ "reflect"
+ "testing"
+)
+
+func TestGetImage(t *testing.T) {
+ setup()
+ defer teardown()
+
+ id := "ocid1.image.oc1.phx.a"
+ path := fmt.Sprintf("/images/%s", id)
+ mux.HandleFunc(path, func(w http.ResponseWriter, r *http.Request) {
+ fmt.Fprintf(w, `{"id":"%s"}`, id)
+ })
+
+ image, err := client.Compute.Images.Get(&GetImageParams{ID: id})
+ if err != nil {
+ t.Errorf("Client.Compute.Images.Get() returned error: %v", err)
+ }
+
+ want := Image{ID: id}
+
+ if !reflect.DeepEqual(image, want) {
+ t.Errorf("Client.Compute.Images.Get() returned %+v, want %+v", image, want)
+ }
+}
+
+func TestCreateImage(t *testing.T) {
+ setup()
+ defer teardown()
+
+ mux.HandleFunc("/images/", func(w http.ResponseWriter, r *http.Request) {
+ fmt.Fprint(w, `{"displayName": "go-oci test"}`)
+ })
+
+ params := &CreateImageParams{
+ CompartmentID: "ocid1.compartment.oc1..a",
+ DisplayName: "go-oci test image",
+ InstanceID: "ocid1.image.oc1.phx.a",
+ }
+
+ image, err := client.Compute.Images.Create(params)
+ if err != nil {
+ t.Errorf("Client.Compute.Images.Create() returned error: %v", err)
+ }
+
+ want := Image{DisplayName: "go-oci test"}
+
+ if !reflect.DeepEqual(image, want) {
+ t.Errorf("Client.Compute.Images.Create() returned %+v, want %+v", image, want)
+ }
+}
+
+func TestImageGetResourceState(t *testing.T) {
+ setup()
+ defer teardown()
+
+ id := "ocid1.image.oc1.phx.a"
+ path := fmt.Sprintf("/images/%s", id)
+ mux.HandleFunc(path, func(w http.ResponseWriter, r *http.Request) {
+ fmt.Fprint(w, `{"LifecycleState": "AVAILABLE"}`)
+ })
+
+ state, err := client.Compute.Images.GetResourceState(id)
+ if err != nil {
+ t.Errorf("Client.Compute.Images.GetResourceState() returned error: %v", err)
+ }
+
+ want := "AVAILABLE"
+ if state != want {
+ t.Errorf("Client.Compute.Images.GetResourceState() returned %+v, want %+v", state, want)
+ }
+}
+
+func TestImageGetResourceStateInvalidID(t *testing.T) {
+ setup()
+ defer teardown()
+
+ id := "ocid1.image.oc1.phx.a"
+ path := fmt.Sprintf("/images/%s", id)
+ mux.HandleFunc(path, func(w http.ResponseWriter, r *http.Request) {
+ w.WriteHeader(http.StatusNotFound)
+ fmt.Fprint(w, `{"code": "NotAuthorizedOrNotFound"}`)
+ })
+
+ state, err := client.Compute.Images.GetResourceState(id)
+ if err == nil {
+ t.Errorf("Client.Compute.Images.GetResourceState() expected error, got %v", state)
+ }
+
+ want := &APIError{Code: "NotAuthorizedOrNotFound"}
+ if !reflect.DeepEqual(err, want) {
+ t.Errorf("Client.Compute.Images.GetResourceState() errored with %+v, want %+v", err, want)
+ }
+}
+
+func TestDeleteInstance(t *testing.T) {
+ setup()
+ defer teardown()
+
+ id := "ocid1.image.oc1.phx.a"
+ path := fmt.Sprintf("/images/%s", id)
+ mux.HandleFunc(path, func(w http.ResponseWriter, r *http.Request) {
+ w.WriteHeader(http.StatusNoContent)
+ })
+
+ err := client.Compute.Images.Delete(&DeleteImageParams{ID: id})
+ if err != nil {
+ t.Errorf("Client.Compute.Images.Delete() returned error: %v", err)
+ }
+}
diff --git a/vendor/github.com/mitchellh/packer/builder/oracle/oci/client/instance.go b/vendor/github.com/mitchellh/packer/builder/oracle/oci/client/instance.go
new file mode 100644
index 00000000..30cdbd50
--- /dev/null
+++ b/vendor/github.com/mitchellh/packer/builder/oracle/oci/client/instance.go
@@ -0,0 +1,129 @@
+package oci
+
+import (
+ "time"
+)
+
+// InstanceService enables communicating with the OCI compute API's instance
+// related endpoints.
+type InstanceService struct {
+ client *baseClient
+}
+
+// NewInstanceService creates a new InstanceService for communicating with the
+// OCI compute API's instance related endpoints.
+func NewInstanceService(s *baseClient) *InstanceService {
+ return &InstanceService{
+ client: s.New().Path("instances/"),
+ }
+}
+
+// Instance details a OCI compute instance.
+type Instance struct {
+ // The Availability Domain the instance is running in.
+ AvailabilityDomain string `json:"availabilityDomain"`
+
+ // The OCID of the compartment that contains the instance.
+ CompartmentID string `json:"compartmentId"`
+
+ // A user-friendly name. Does not have to be unique, and it's changeable.
+ DisplayName string `json:"displayName,omitempty"`
+
+ // The OCID of the instance.
+ ID string `json:"id"`
+
+ // The image used to boot the instance.
+ ImageID string `json:"imageId,omitempty"`
+
+ // The current state of the instance. Allowed values:
+ // - PROVISIONING
+ // - RUNNING
+ // - STARTING
+ // - STOPPING
+ // - STOPPED
+ // - CREATING_IMAGE
+ // - TERMINATING
+ // - TERMINATED
+ LifecycleState string `json:"lifecycleState"`
+
+ // Custom metadata that you provide.
+ Metadata map[string]string `json:"metadata,omitempty"`
+
+ // The region that contains the Availability Domain the instance is running in.
+ Region string `json:"region"`
+
+ // The shape of the instance. The shape determines the number of CPUs
+ // and the amount of memory allocated to the instance.
+ Shape string `json:"shape"`
+
+ // The date and time the instance was created.
+ TimeCreated time.Time `json:"timeCreated"`
+}
+
+// GetInstanceParams are the paramaters available when communicating with the
+// GetInstance API endpoint.
+type GetInstanceParams struct {
+ ID string `url:"instanceId,omitempty"`
+}
+
+// Get returns a single Instance
+func (s *InstanceService) Get(params *GetInstanceParams) (Instance, error) {
+ instance := Instance{}
+ e := &APIError{}
+
+ _, err := s.client.New().Get(params.ID).Receive(&instance, e)
+ err = firstError(err, e)
+
+ return instance, err
+}
+
+// LaunchInstanceParams are the parameters available when communicating with
+// the LunchInstance API endpoint.
+type LaunchInstanceParams struct {
+ AvailabilityDomain string `json:"availabilityDomain,omitempty"`
+ CompartmentID string `json:"compartmentId,omitempty"`
+ DisplayName string `json:"displayName,omitempty"`
+ ImageID string `json:"imageId,omitempty"`
+ Metadata map[string]string `json:"metadata,omitempty"`
+ OPCiPXEScript string `json:"opcIpxeScript,omitempty"`
+ Shape string `json:"shape,omitempty"`
+ SubnetID string `json:"subnetId,omitempty"`
+}
+
+// Launch creates a new OCI compute instance. It does *not* wait for the
+// instance to boot.
+func (s *InstanceService) Launch(params *LaunchInstanceParams) (Instance, error) {
+ instance := &Instance{}
+ e := &APIError{}
+
+ _, err := s.client.New().Post("").SetBody(params).Receive(instance, e)
+ err = firstError(err, e)
+
+ return *instance, err
+}
+
+// TerminateInstanceParams are the parameters available when communicating with
+// the TerminateInstance API endpoint.
+type TerminateInstanceParams struct {
+ ID string `url:"instanceId,omitempty"`
+}
+
+// Terminate terminates a running OCI compute instance.
+// instance to boot.
+func (s *InstanceService) Terminate(params *TerminateInstanceParams) error {
+ e := &APIError{}
+
+ _, err := s.client.New().Delete(params.ID).SetBody(params).Receive(nil, e)
+ err = firstError(err, e)
+
+ return err
+}
+
+// GetResourceState GETs the LifecycleState of the given instance id.
+func (s *InstanceService) GetResourceState(id string) (string, error) {
+ instance, err := s.Get(&GetInstanceParams{ID: id})
+ if err != nil {
+ return "", err
+ }
+ return instance.LifecycleState, nil
+}
diff --git a/vendor/github.com/mitchellh/packer/builder/oracle/oci/client/instance_test.go b/vendor/github.com/mitchellh/packer/builder/oracle/oci/client/instance_test.go
new file mode 100644
index 00000000..e45b707a
--- /dev/null
+++ b/vendor/github.com/mitchellh/packer/builder/oracle/oci/client/instance_test.go
@@ -0,0 +1,96 @@
+package oci
+
+import (
+ "fmt"
+ "net/http"
+ "reflect"
+ "testing"
+)
+
+func TestGetInstance(t *testing.T) {
+ setup()
+ defer teardown()
+
+ id := "ocid1.instance.oc1.phx.a"
+ path := fmt.Sprintf("/instances/%s", id)
+ mux.HandleFunc(path, func(w http.ResponseWriter, r *http.Request) {
+ fmt.Fprintf(w, `{"id":"%s"}`, id)
+ })
+
+ instance, err := client.Compute.Instances.Get(&GetInstanceParams{ID: id})
+ if err != nil {
+ t.Errorf("Client.Compute.Instances.Get() returned error: %v", err)
+ }
+
+ want := Instance{ID: id}
+
+ if !reflect.DeepEqual(instance, want) {
+ t.Errorf("Client.Compute.Instances.Get() returned %+v, want %+v", instance, want)
+ }
+}
+
+func TestLaunchInstance(t *testing.T) {
+ setup()
+ defer teardown()
+
+ mux.HandleFunc("/instances/", func(w http.ResponseWriter, r *http.Request) {
+ fmt.Fprint(w, `{"displayName": "go-oci test"}`)
+ })
+
+ params := &LaunchInstanceParams{
+ AvailabilityDomain: "aaaa:PHX-AD-1",
+ CompartmentID: "ocid1.compartment.oc1..a",
+ DisplayName: "go-oci test",
+ ImageID: "ocid1.image.oc1.phx.a",
+ Shape: "VM.Standard1.1",
+ SubnetID: "ocid1.subnet.oc1.phx.a",
+ }
+
+ instance, err := client.Compute.Instances.Launch(params)
+ if err != nil {
+ t.Errorf("Client.Compute.Instances.Launch() returned error: %v", err)
+ }
+
+ want := Instance{DisplayName: "go-oci test"}
+
+ if !reflect.DeepEqual(instance, want) {
+ t.Errorf("Client.Compute.Instances.Launch() returned %+v, want %+v", instance, want)
+ }
+}
+
+func TestTerminateInstance(t *testing.T) {
+ setup()
+ defer teardown()
+
+ id := "ocid1.instance.oc1.phx.a"
+ path := fmt.Sprintf("/instances/%s", id)
+ mux.HandleFunc(path, func(w http.ResponseWriter, r *http.Request) {
+ w.WriteHeader(http.StatusNoContent)
+ })
+
+ err := client.Compute.Instances.Terminate(&TerminateInstanceParams{ID: id})
+ if err != nil {
+ t.Errorf("Client.Compute.Instances.Terminate() returned error: %v", err)
+ }
+}
+
+func TestInstanceGetResourceState(t *testing.T) {
+ setup()
+ defer teardown()
+
+ id := "ocid1.instance.oc1.phx.a"
+ path := fmt.Sprintf("/instances/%s", id)
+ mux.HandleFunc(path, func(w http.ResponseWriter, r *http.Request) {
+ fmt.Fprint(w, `{"LifecycleState": "RUNNING"}`)
+ })
+
+ state, err := client.Compute.Instances.GetResourceState(id)
+ if err != nil {
+ t.Errorf("Client.Compute.Instances.GetResourceState() returned error: %v", err)
+ }
+
+ want := "RUNNING"
+ if state != want {
+ t.Errorf("Client.Compute.Instances.GetResourceState() returned %+v, want %+v", state, want)
+ }
+}
diff --git a/vendor/github.com/mitchellh/packer/builder/oracle/oci/client/transport.go b/vendor/github.com/mitchellh/packer/builder/oracle/oci/client/transport.go
new file mode 100644
index 00000000..79da2050
--- /dev/null
+++ b/vendor/github.com/mitchellh/packer/builder/oracle/oci/client/transport.go
@@ -0,0 +1,116 @@
+package oci
+
+import (
+ "bytes"
+ "crypto"
+ "crypto/rand"
+ "crypto/rsa"
+ "crypto/sha256"
+ "encoding/base64"
+ "fmt"
+ "io"
+ "net/http"
+ "strconv"
+ "strings"
+ "time"
+)
+
+type nopCloser struct {
+ io.Reader
+}
+
+func (nopCloser) Close() error {
+ return nil
+}
+
+// Transport adds OCI signature authentication to each outgoing request.
+type Transport struct {
+ transport http.RoundTripper
+ config *Config
+}
+
+// NewTransport creates a new Transport to add OCI signature authentication
+// to each outgoing request.
+func NewTransport(transport http.RoundTripper, config *Config) *Transport {
+ return &Transport{
+ transport: transport,
+ config: config,
+ }
+}
+
+func (t *Transport) RoundTrip(req *http.Request) (*http.Response, error) {
+ var buf *bytes.Buffer
+
+ if req.Body != nil {
+ buf = new(bytes.Buffer)
+ buf.ReadFrom(req.Body)
+ req.Body = nopCloser{buf}
+ }
+ if req.Header.Get("date") == "" {
+ req.Header.Set("date", time.Now().UTC().Format(http.TimeFormat))
+ }
+ if req.Header.Get("content-type") == "" {
+ req.Header.Set("content-type", "application/json")
+ }
+ if req.Header.Get("accept") == "" {
+ req.Header.Set("accept", "application/json")
+ }
+ if req.Header.Get("host") == "" {
+ req.Header.Set("host", req.URL.Host)
+ }
+
+ var signheaders []string
+ if (req.Method == "PUT" || req.Method == "POST") && buf != nil {
+ signheaders = []string{"(request-target)", "host", "date",
+ "content-length", "content-type", "x-content-sha256"}
+
+ if req.Header.Get("content-length") == "" {
+ req.Header.Set("content-length", strconv.Itoa(buf.Len()))
+ }
+
+ hasher := sha256.New()
+ hasher.Write(buf.Bytes())
+ hash := hasher.Sum(nil)
+ req.Header.Set("x-content-sha256", base64.StdEncoding.EncodeToString(hash))
+ } else {
+ signheaders = []string{"date", "host", "(request-target)"}
+ }
+
+ var signbuffer bytes.Buffer
+ for idx, header := range signheaders {
+ signbuffer.WriteString(header)
+ signbuffer.WriteString(": ")
+
+ if header == "(request-target)" {
+ signbuffer.WriteString(strings.ToLower(req.Method))
+ signbuffer.WriteString(" ")
+ signbuffer.WriteString(req.URL.RequestURI())
+ } else {
+ signbuffer.WriteString(req.Header.Get(header))
+ }
+
+ if idx < len(signheaders)-1 {
+ signbuffer.WriteString("\n")
+ }
+ }
+
+ h := sha256.New()
+ h.Write(signbuffer.Bytes())
+ digest := h.Sum(nil)
+ signature, err := rsa.SignPKCS1v15(rand.Reader, t.config.Key, crypto.SHA256, digest)
+ if err != nil {
+ return nil, err
+ }
+
+ authHeader := fmt.Sprintf("Signature headers=\"%s\","+
+ "keyId=\"%s/%s/%s\","+
+ "algorithm=\"rsa-sha256\","+
+ "signature=\"%s\","+
+ "version=\"1\"",
+ strings.Join(signheaders, " "),
+ t.config.Tenancy, t.config.User, t.config.Fingerprint,
+ base64.StdEncoding.EncodeToString(signature))
+ req.Header.Add("Authorization", authHeader)
+
+ return t.transport.RoundTrip(req)
+}
diff --git a/vendor/github.com/mitchellh/packer/builder/oracle/oci/client/transport_test.go b/vendor/github.com/mitchellh/packer/builder/oracle/oci/client/transport_test.go
new file mode 100644
index 00000000..2299f3a0
--- /dev/null
+++ b/vendor/github.com/mitchellh/packer/builder/oracle/oci/client/transport_test.go
@@ -0,0 +1,156 @@
+package oci
+
+import (
+ "net/http"
+ "strings"
+ "testing"
+)
+
+const testKey = `-----BEGIN RSA PRIVATE KEY-----
+MIIEpQIBAAKCAQEAyLnyzmYj0dZuDo2nclIdEyLZrFZLtw5xFldWpCUl5W3SxKDL
+iIgwxpSO75Yf++Rzqc5j6S5bpIrdca6AwVXCNmjjxMPO7vLLm4l4IUOZMv5FqKaC
+I2plFz9uBkzGscnYnMbsDA430082E07lYpNv1xy8JwpbrIsqIMh4XCKci/Od5sLR
+kEicmOpQK42FGRTQjjmQoWtv+9XED+vYTRL0AxQEC/6i/E7yssFXZ+fpHSKWeKTQ
+K/1Fc4pZ1zNzJcDXGuweISx/QMLz78TAPH5OBq/EQzHKSpKvfnWFRyBHne8pwuN8
+8wzbbD+/7OFjz28jNSERVJvfYe3X1k69IWMNGwIDAQABAoIBAQCZhcdU38AzxSrG
+DMfuYymDslsEObiNWQlbig9lWlhCwx26cDVbxrZvm747NvpdgVyJmqbF+UP0dJVs
+Voh51qrFTLIwk4bZMXBTFPCBmJ865knG9RuCFOUew8/WF7C82GHJf0eY7OL7xpDY
+cbZ2D8gxofOydHSrYoElM88CwSI00xPCbBKEMrBO94oXC8yfp2bmV6bNhVXwFDEM
+qda7M6jVAsBrTOzxUF5VdUUU/MLsu2cCk/ap1zer2Bml9Afk1bMeGJ3XDQgol0pS
+CLxaGczpSNVMF9+pjA5sFHR5rmcl0b/kC9HsgOJGhLOimtS94O64dSdWifgsjf6+
+fhT2SMiRAoGBAOUDwkdzNqQfvS+qrP2ULpB4vt7MZ70rDGmyMDLZ1VWgcm2cDIad
+b7MkFG6GCa48mKkFXK9mOPyq8ELoTjZo2p+relEqf49BpaNxr+cp11pX7g0AkzCa
+a8LwdOOUW/poqYl2xLuw9Rz6ky6ybzatMvCwpQCwnbAdABIVxz4oQKHpAoGBAOBg
+3uYC/ynGdF9gJTfdS5XPYoLcKKRRspBZrvvDHaWyBnanm5KYwDAZPzLQMqcpyPeo
+5xgwMmtNlc6lKKyGkhSLNCV+eO3yAx1h/cq7ityvMS7u6o5sq+/bvtEnbUPYbEtk
+AhVD7/w5Yyzzi4beiQxDKe0q1mvUAH56aGqJivBjAoGBALmUMTPbDhUzTwg4Y1Rd
+ZtpVrj43H31wS+++oEYktTZc/T0LLi9Llr9w5kmlvmR94CtfF/ted6FwF5/wRajb
+kQXAXC83pAR/au0mbCeDhWpFRLculxfUmqxuVBozF9G0TGYDY2rA+++OsgQuPebt
+tRDL4/nKJQ4Ygf0lvr4EulM5AoGBALoIdyabu3WmfhwJujH8P8wA+ztmUCgVOIio
+YwWIe49C8Er2om1ESqxWcmit6CFi6qY0Gw6Z/2OqGxgPJY8NsBZqaBziJF+cdWqq
+MWMiZXqdopi4LC9T+KZROn9tQhGrYfaL/5IkFti3t/uwHbH/1f8dvKhQCSGzz4kN
+8n7KdTDjAoGAKh8XdIOQlThFK108VT2yp4BGZXEOvWrR19DLbuUzHVrEX+Bd+uFo
+Ruk9iKEH7PSnlRnIvWc1y9qN7fUi5OR3LvQNGlXHyUl6CtmH3/b064bBKudC+XTn
+VBelcIoGpH7Dn9I6pKUFauJz1TSbQCIjYGNqrjyzLtG+lH/gy5q4xs8=
+-----END RSA PRIVATE KEY-----`
+
+type testTarget struct {
+ CapturedReq *http.Request
+ Response *http.Response
+}
+
+func (target *testTarget) RoundTrip(req *http.Request) (*http.Response, error) {
+ target.CapturedReq = req
+ return target.Response, nil
+}
+
+func testReq(method string, url string, body string, headers map[string]string) *http.Request {
+ req, err := http.NewRequest(method, url, strings.NewReader(body))
+ if err != nil {
+ panic(err.Error())
+ }
+
+ for k, v := range headers {
+ req.Header.Add(k, v)
+ }
+ return req
+}
+
+var KnownGoodCases = []struct {
+ name string
+ inputRequest func() *http.Request
+ expectedHeaders map[string]string
+}{
+ {
+ name: "Simple GET",
+ inputRequest: func() *http.Request {
+ return testReq("GET", "https://example.com/", "", map[string]string{
+ "date": "Mon, 26 Sep 2016 11:04:22 GMT"})
+ },
+ expectedHeaders: map[string]string{
+ "date": "Mon, 26 Sep 2016 11:04:22 GMT",
+ "content-type": "application/json",
+ "host": "example.com",
+ "accept": "application/json",
+ "Authorization": "Signature headers=\"date host (request-target)\",keyId=\"tenant/testuser/3c:b6:44:d7:49:1a:ac:bf:de:7d:76:22:a7:f5:df:55\",algorithm=\"rsa-sha256\",signature=\"UMw/FImQYZ5JBpfYcR9YN72lhupGl5yS+522NS9glLodU9f4oKRqaocpGdSUSRhhSDKxIx01rV547/HemJ6QqEPaJJuDQPXsGthokWMU2DBGyaMAqhLClgCJiRQMwpg4rdL2tETzkM3wy6UN+I52RYoNSdsnat2ZArCkfl8dIl9ydcwD8/+BqB8d2wyaAIS4iagdPKLAC/Mu9OzyUPOXQhYGYsoEdOowOUkHOlob65PFrlHmKJDdjEF3MDcygEpApItf4iUEloP5bjixAbZEVpj3HLQ5uaPx9m+RsLzYMeO0adE0wOv2YNmwZrExGhXh1BpTU33m5amHeUBxSaG+2A==\",version=\"1\"",
+ },
+ },
+ {
+ name: "Simple PUT request",
+ inputRequest: func() *http.Request {
+ return testReq("PUT", "https://example.com/", "Some Content", map[string]string{
+ "date": "Mon, 26 Sep 2016 11:04:22 GMT"})
+ },
+ expectedHeaders: map[string]string{
+ "date": "Mon, 26 Sep 2016 11:04:22 GMT",
+ "content-type": "application/json",
+ "content-length": "12",
+ "x-content-sha256": "lQ8fsURxamLtHxnwTYqd3MNYadJ4ZB/U9yQBKzu/fXA=",
+ "accept": "application/json",
+ "Authorization": "Signature headers=\"(request-target) host date content-length content-type x-content-sha256\",keyId=\"tenant/testuser/3c:b6:44:d7:49:1a:ac:bf:de:7d:76:22:a7:f5:df:55\",algorithm=\"rsa-sha256\",signature=\"FHyPt4PE2HGH+iftzcViB76pCJ2R9+DdTCo1Ss4mH4KHQJdyQtPsCpe6Dc19zie6cRr6dsenk21yYnncic8OwZhII8DULj2//qLFGmgFi84s7LJqMQ/COiP7O9KtCN+U8MMt4PV7ZDsiGFn3/8EUJ1wxYscxSIB19S1NpuEL062JgGfkqxTkTPd7V3Xh1NlmUUtQrAMR3l56k1iV0zXY9Uw0CjWYjueMP0JUmkO7zycYAVBrx7Q8wkmejlyD7yFrAnObyEsMm9cIL9IcruWFHeCHFxRLslw7AoLxibAm2Dc9EROuvCK2UkUp8AFkE+QyYDMrrSm1NLBMWdnYqdickA==\",version=\"1\"",
+ },
+ },
+ {
+ name: "Simple POST request",
+ inputRequest: func() *http.Request {
+ return testReq("POST", "https://example.com/", "Some Content", map[string]string{
+ "date": "Mon, 26 Sep 2016 11:04:22 GMT"})
+ },
+ expectedHeaders: map[string]string{
+ "date": "Mon, 26 Sep 2016 11:04:22 GMT",
+ "content-type": "application/json",
+ "content-length": "12",
+ "x-content-sha256": "lQ8fsURxamLtHxnwTYqd3MNYadJ4ZB/U9yQBKzu/fXA=",
+ "accept": "application/json",
+ "Authorization": "Signature headers=\"(request-target) host date content-length content-type x-content-sha256\",keyId=\"tenant/testuser/3c:b6:44:d7:49:1a:ac:bf:de:7d:76:22:a7:f5:df:55\",algorithm=\"rsa-sha256\",signature=\"WzGIoySkjqydwabMTxjVs05UBu0hThAEBzVs7HbYO45o2XpaoqGiNX67mNzs1PeYrGHpJp8+Ysoz66PChWV/1trxuTU92dQ/FgwvcwBRy5dQvdLkjWCZihNunSk4gt9652w6zZg/ybLon0CFbLRnlanDJDX9BgR3ttuTxf30t5qr2A4fnjFF4VjaU/CzE13cNfaWftjSd+xNcla2sbArF3R0+CEEb0xZEPzTyjjjkyvXdaPZwEprVn8IDmdJvLmRP4EniAPxE1EZIhd712M5ondQkR4/WckM44/hlKDeXGFb4y+QnU02i4IWgOWs3dh2tuzS1hp1zfq7qgPbZ4hp0A==\",version=\"1\"",
+ },
+ },
+
+ {
+ name: "Simple DELETE",
+ inputRequest: func() *http.Request {
+ return testReq("DELETE", "https://example.com/", "Some Content", map[string]string{
+ "date": "Mon, 26 Sep 2016 11:04:22 GMT"})
+ },
+ expectedHeaders: map[string]string{
+ "date": "Mon, 26 Sep 2016 11:04:22 GMT",
+ "content-type": "application/json",
+ "accept": "application/json",
+ "Authorization": "Signature headers=\"date host (request-target)\",keyId=\"tenant/testuser/3c:b6:44:d7:49:1a:ac:bf:de:7d:76:22:a7:f5:df:55\",algorithm=\"rsa-sha256\",signature=\"Kj4YSpONZG1cibLbNgxIp4VoS5+80fsB2Fh2Ue28+QyXq4wwrJpMP+8jEupz1yTk1SNPYuxsk7lNOgtI6G1Hq0YJJVum74j46sUwRWe+f08tMJ3c9J+rrzLfpIrakQ8PaudLhHU0eK5kuTZme1dCwRWXvZq3r5IqkGot/OGMabKpBygRv9t0i5ry+bTslSjMqafTWLosY9hgIiGrXD+meB5tpyn+gPVYc//Hc/C7uNNgLJIMk5DKVa4U0YnoY3ojafZTXZQQNGRn2NDMcZUX3f3nJlUIfiZRiOCTkbPwx/fWb4MZtYaEsY5OPficbJRvfOBxSG1wjX+8rgO7ijhMAA==\",version=\"1\"",
+ },
+ },
+}
+
+func TestKnownGoodRequests(t *testing.T) {
+ pKey, err := ParsePrivateKey([]byte(testKey), []byte{})
+ if err != nil {
+ t.Fatalf("Failed to parse test key: %s", err.Error())
+ }
+
+ config := &Config{
+ Key: pKey,
+ User: "testuser",
+ Tenancy: "tenant",
+ Fingerprint: "3c:b6:44:d7:49:1a:ac:bf:de:7d:76:22:a7:f5:df:55",
+ }
+
+ expectedResponse := &http.Response{}
+ for _, tt := range KnownGoodCases {
+ targetBackend := &testTarget{Response: expectedResponse}
+ target := NewTransport(targetBackend, config)
+
+ _, err = target.RoundTrip(tt.inputRequest())
+ if err != nil {
+ t.Fatalf("%s: Failed to handle request %s", tt.name, err.Error())
+ }
+
+ sentReq := targetBackend.CapturedReq
+
+ for header, val := range tt.expectedHeaders {
+ if sentReq.Header.Get(header) != val {
+ t.Fatalf("%s: Header mismatch in responnse,\n\t expecting \"%s\"\n\t got \"%s\"", tt.name, val, sentReq.Header.Get(header))
+ }
+ }
+ }
+
+}
diff --git a/vendor/github.com/mitchellh/packer/builder/oracle/oci/client/vnic.go b/vendor/github.com/mitchellh/packer/builder/oracle/oci/client/vnic.go
new file mode 100644
index 00000000..31b37ec3
--- /dev/null
+++ b/vendor/github.com/mitchellh/packer/builder/oracle/oci/client/vnic.go
@@ -0,0 +1,47 @@
+package oci
+
+import (
+ "time"
+)
+
+// VNICService enables communicating with the OCI compute API's VNICs
+// endpoint.
+type VNICService struct {
+ client *baseClient
+}
+
+// NewVNICService creates a new VNICService for communicating with the
+// OCI compute API's instance related endpoints.
+func NewVNICService(s *baseClient) *VNICService {
+ return &VNICService{client: s.New().Path("vnics/")}
+}
+
+// VNIC - a virtual network interface card.
+type VNIC struct {
+ AvailabilityDomain string `json:"availabilityDomain"`
+ CompartmentID string `json:"compartmentId"`
+ DisplayName string `json:"displayName,omitempty"`
+ ID string `json:"id"`
+ LifecycleState string `json:"lifecycleState"`
+ PrivateIP string `json:"privateIp"`
+ PublicIP string `json:"publicIp"`
+ SubnetID string `json:"subnetId"`
+ TimeCreated time.Time `json:"timeCreated"`
+}
+
+// GetVNICParams are the paramaters available when communicating with the
+// ListVNICs API endpoint.
+type GetVNICParams struct {
+ ID string `url:"vnicId"`
+}
+
+// Get returns an individual VNIC.
+func (s *VNICService) Get(params *GetVNICParams) (VNIC, error) {
+ VNIC := &VNIC{}
+ e := &APIError{}
+
+ _, err := s.client.New().Get(params.ID).Receive(VNIC, e)
+ err = firstError(err, e)
+
+ return *VNIC, err
+}
diff --git a/vendor/github.com/mitchellh/packer/builder/oracle/oci/client/vnic_attachment.go b/vendor/github.com/mitchellh/packer/builder/oracle/oci/client/vnic_attachment.go
new file mode 100644
index 00000000..3458f7da
--- /dev/null
+++ b/vendor/github.com/mitchellh/packer/builder/oracle/oci/client/vnic_attachment.go
@@ -0,0 +1,52 @@
+package oci
+
+import (
+ "time"
+)
+
+// VNICAttachmentService enables communicating with the OCI compute API's VNIC
+// attachment endpoint.
+type VNICAttachmentService struct {
+ client *baseClient
+}
+
+// NewVNICAttachmentService creates a new VNICAttachmentService for communicating with the
+// OCI compute API's instance related endpoints.
+func NewVNICAttachmentService(s *baseClient) *VNICAttachmentService {
+ return &VNICAttachmentService{
+ client: s.New().Path("vnicAttachments/"),
+ }
+}
+
+// VNICAttachment details the attachment of a VNIC to a OCI instance.
+type VNICAttachment struct {
+ AvailabilityDomain string `json:"availabilityDomain"`
+ CompartmentID string `json:"compartmentId"`
+ DisplayName string `json:"displayName,omitempty"`
+ ID string `json:"id"`
+ InstanceID string `json:"instanceId"`
+ LifecycleState string `json:"lifecycleState"`
+ SubnetID string `json:"subnetId"`
+ TimeCreated time.Time `json:"timeCreated"`
+ VNICID string `json:"vnicId"`
+}
+
+// ListVnicAttachmentsParams are the paramaters available when communicating
+// with the ListVnicAttachments API endpoint.
+type ListVnicAttachmentsParams struct {
+ AvailabilityDomain string `url:"availabilityDomain,omitempty"`
+ CompartmentID string `url:"compartmentId"`
+ InstanceID string `url:"instanceId,omitempty"`
+ VNICID string `url:"vnicId,omitempty"`
+}
+
+// List returns an array of VNICAttachments.
+func (s *VNICAttachmentService) List(params *ListVnicAttachmentsParams) ([]VNICAttachment, error) {
+ vnicAttachments := new([]VNICAttachment)
+ e := new(APIError)
+
+ _, err := s.client.New().Get("").QueryStruct(params).Receive(vnicAttachments, e)
+ err = firstError(err, e)
+
+ return *vnicAttachments, err
+}
diff --git a/vendor/github.com/mitchellh/packer/builder/oracle/oci/client/vnic_attachment_test.go b/vendor/github.com/mitchellh/packer/builder/oracle/oci/client/vnic_attachment_test.go
new file mode 100644
index 00000000..704423fb
--- /dev/null
+++ b/vendor/github.com/mitchellh/packer/builder/oracle/oci/client/vnic_attachment_test.go
@@ -0,0 +1,31 @@
+package oci
+
+import (
+ "fmt"
+ "net/http"
+ "reflect"
+ "testing"
+)
+
+func TestListVNICAttachments(t *testing.T) {
+ setup()
+ defer teardown()
+
+ id := "ocid1.image.oc1.phx.a"
+ mux.HandleFunc("/vnicAttachments/", func(w http.ResponseWriter, r *http.Request) {
+ fmt.Fprintf(w, `[{"id":"%s"}]`, id)
+ })
+
+ params := &ListVnicAttachmentsParams{InstanceID: id}
+
+ vnicAttachment, err := client.Compute.VNICAttachments.List(params)
+ if err != nil {
+ t.Errorf("Client.Compute.VNICAttachments.List() returned error: %v", err)
+ }
+
+ want := []VNICAttachment{{ID: id}}
+
+ if !reflect.DeepEqual(vnicAttachment, want) {
+ t.Errorf("Client.Compute.VNICAttachments.List() returned %+v, want %+v", vnicAttachment, want)
+ }
+}
diff --git a/vendor/github.com/mitchellh/packer/builder/oracle/oci/client/vnic_test.go b/vendor/github.com/mitchellh/packer/builder/oracle/oci/client/vnic_test.go
new file mode 100644
index 00000000..c208db5c
--- /dev/null
+++ b/vendor/github.com/mitchellh/packer/builder/oracle/oci/client/vnic_test.go
@@ -0,0 +1,29 @@
+package oci
+
+import (
+ "fmt"
+ "net/http"
+ "reflect"
+ "testing"
+)
+
+func TestGetVNIC(t *testing.T) {
+ setup()
+ defer teardown()
+
+ id := "ocid1.vnic.oc1.phx.a"
+ path := fmt.Sprintf("/vnics/%s", id)
+ mux.HandleFunc(path, func(w http.ResponseWriter, r *http.Request) {
+ fmt.Fprintf(w, `{"id": "%s"}`, id)
+ })
+
+ vnic, err := client.Compute.VNICs.Get(&GetVNICParams{ID: id})
+ if err != nil {
+ t.Errorf("Client.Compute.VNICs.Get() returned error: %v", err)
+ }
+
+ want := &VNIC{ID: id}
+ if reflect.DeepEqual(vnic, want) {
+ t.Errorf("Client.Compute.VNICs.Get() returned %+v, want %+v", vnic, want)
+ }
+}
diff --git a/vendor/github.com/mitchellh/packer/builder/oracle/oci/client/waiters.go b/vendor/github.com/mitchellh/packer/builder/oracle/oci/client/waiters.go
new file mode 100644
index 00000000..bb9ca1c1
--- /dev/null
+++ b/vendor/github.com/mitchellh/packer/builder/oracle/oci/client/waiters.go
@@ -0,0 +1,59 @@
+package oci
+
+import (
+ "fmt"
+ "time"
+)
+
+const (
+ defaultWaitDurationMS = 5000
+ defaultMaxRetries = 0
+)
+
+type Waiter struct {
+ WaitDurationMS int
+ MaxRetries int
+}
+
+type WaitableService interface {
+ GetResourceState(id string) (string, error)
+}
+
+func stringSliceContains(slice []string, value string) bool {
+ for _, elem := range slice {
+ if elem == value {
+ return true
+ }
+ }
+ return false
+}
+
+// NewWaiter creates a waiter with default wait duration and unlimited retry
+// operations.
+func NewWaiter() *Waiter {
+ return &Waiter{WaitDurationMS: defaultWaitDurationMS, MaxRetries: defaultMaxRetries}
+}
+
+// WaitForResourceToReachState polls a resource that implements WaitableService
+// repeatedly until it reaches a known state or fails if it reaches an
+// unexpected state. The duration of the interval and number of polls is
+// determined by the Waiter configuration.
+func (w *Waiter) WaitForResourceToReachState(svc WaitableService, id string, waitStates []string, terminalState string) error {
+ for i := 0; w.MaxRetries == 0 || i < w.MaxRetries; i++ {
+ state, err := svc.GetResourceState(id)
+ if err != nil {
+ return err
+ }
+
+ if stringSliceContains(waitStates, state) {
+ time.Sleep(time.Duration(w.WaitDurationMS) * time.Millisecond)
+ continue
+ } else if state == terminalState {
+ return nil
+ }
+
+ return fmt.Errorf("Unexpected resource state %s, expecting a waiting state %s or terminal state %s ", state, waitStates, terminalState)
+ }
+
+ return fmt.Errorf("Maximum number of retries (%d) exceeded; resource did not reach state %s", w.MaxRetries, terminalState)
+}
diff --git a/vendor/github.com/mitchellh/packer/builder/oracle/oci/client/waiters_test.go b/vendor/github.com/mitchellh/packer/builder/oracle/oci/client/waiters_test.go
new file mode 100644
index 00000000..ce52b792
--- /dev/null
+++ b/vendor/github.com/mitchellh/packer/builder/oracle/oci/client/waiters_test.go
@@ -0,0 +1,80 @@
+package oci
+
+import (
+ "errors"
+ "fmt"
+ "testing"
+)
+
+const (
+ ValidID = "ID"
+)
+
+type testWaitSvc struct {
+ states []string
+ idx int
+ err error
+}
+
+func (tw *testWaitSvc) GetResourceState(id string) (string, error) {
+ if id != ValidID {
+ return "", fmt.Errorf("Invalid id %s", id)
+ }
+ if tw.err != nil {
+ return "", tw.err
+ }
+
+ if tw.idx >= len(tw.states) {
+ panic("Invalid test state")
+ }
+ state := tw.states[tw.idx]
+ tw.idx++
+ return state, nil
+}
+
+func TestReturnsWhenWaitStateIsReachedImmediately(t *testing.T) {
+ ws := &testWaitSvc{states: []string{"OK"}}
+ w := NewWaiter()
+ err := w.WaitForResourceToReachState(ws, ValidID, []string{}, "OK")
+ if err != nil {
+ t.Errorf("Failed to reach expected state, got %s", err)
+ }
+}
+
+func TestReturnsWhenResourceWaitsInValidWaitingState(t *testing.T) {
+ w := &Waiter{WaitDurationMS: 1, MaxRetries: defaultMaxRetries}
+ ws := &testWaitSvc{states: []string{"WAITING", "OK"}}
+ err := w.WaitForResourceToReachState(ws, ValidID, []string{"WAITING"}, "OK")
+ if err != nil {
+ t.Errorf("Failed to reach expected state, got %s", err)
+ }
+}
+
+func TestPropagatesErrorFromGetter(t *testing.T) {
+ w := NewWaiter()
+ ws := &testWaitSvc{states: []string{}, err: errors.New("ERROR")}
+ err := w.WaitForResourceToReachState(ws, ValidID, []string{"WAITING"}, "OK")
+ if err != ws.err {
+ t.Errorf("Expected error from getter got %s", err)
+ }
+}
+
+func TestReportsInvalidTransitionStateAsError(t *testing.T) {
+ w := NewWaiter()
+ tw := &testWaitSvc{states: []string{"UNKNOWN_STATE"}, err: errors.New("ERROR")}
+ err := w.WaitForResourceToReachState(tw, ValidID, []string{"WAITING"}, "OK")
+ if err == nil {
+ t.Fatal("Expected error from getter")
+ }
+}
+
+func TestErrorsWhenMaxWaitTriesExceeded(t *testing.T) {
+ w := Waiter{WaitDurationMS: 1, MaxRetries: 1}
+
+ ws := &testWaitSvc{states: []string{"WAITING", "OK"}}
+
+ err := w.WaitForResourceToReachState(ws, ValidID, []string{"WAITING"}, "OK")
+ if err == nil {
+ t.Fatal("Expecting error but wait terminated")
+ }
+}
diff --git a/vendor/github.com/mitchellh/packer/builder/oracle/oci/config.go b/vendor/github.com/mitchellh/packer/builder/oracle/oci/config.go
new file mode 100644
index 00000000..883c61cb
--- /dev/null
+++ b/vendor/github.com/mitchellh/packer/builder/oracle/oci/config.go
@@ -0,0 +1,215 @@
+package oci
+
+import (
+ "errors"
+ "fmt"
+ "os"
+ "path/filepath"
+
+ client "github.com/hashicorp/packer/builder/oracle/oci/client"
+ "github.com/hashicorp/packer/common"
+ "github.com/hashicorp/packer/helper/communicator"
+ "github.com/hashicorp/packer/helper/config"
+ "github.com/hashicorp/packer/packer"
+ "github.com/hashicorp/packer/template/interpolate"
+
+ "github.com/mitchellh/go-homedir"
+)
+
+type Config struct {
+ common.PackerConfig `mapstructure:",squash"`
+ Comm communicator.Config `mapstructure:",squash"`
+
+ AccessCfg *client.Config
+
+ AccessCfgFile string `mapstructure:"access_cfg_file"`
+ AccessCfgFileAccount string `mapstructure:"access_cfg_file_account"`
+
+ // Access config overrides
+ UserID string `mapstructure:"user_ocid"`
+ TenancyID string `mapstructure:"tenancy_ocid"`
+ Region string `mapstructure:"region"`
+ Fingerprint string `mapstructure:"fingerprint"`
+ KeyFile string `mapstructure:"key_file"`
+ PassPhrase string `mapstructure:"pass_phrase"`
+
+ AvailabilityDomain string `mapstructure:"availability_domain"`
+ CompartmentID string `mapstructure:"compartment_ocid"`
+
+ // Image
+ BaseImageID string `mapstructure:"base_image_ocid"`
+ Shape string `mapstructure:"shape"`
+ ImageName string `mapstructure:"image_name"`
+
+ // Networking
+ SubnetID string `mapstructure:"subnet_ocid"`
+
+ ctx interpolate.Context
+}
+
+func NewConfig(raws ...interface{}) (*Config, error) {
+ c := &Config{}
+
+ // Decode from template
+ err := config.Decode(c, &config.DecodeOpts{
+ Interpolate: true,
+ InterpolateContext: &c.ctx,
+ }, raws...)
+ if err != nil {
+ return nil, fmt.Errorf("Failed to mapstructure Config: %+v", err)
+ }
+
+ // Determine where the SDK config is located
+ var accessCfgFile string
+ if c.AccessCfgFile != "" {
+ accessCfgFile = c.AccessCfgFile
+ } else {
+ accessCfgFile, err = getDefaultOCISettingsPath()
+ if err != nil {
+ accessCfgFile = "" // Access cfg might be in template
+ }
+ }
+
+ accessCfg := &client.Config{}
+
+ if accessCfgFile != "" {
+ loadedAccessCfgs, err := client.LoadConfigsFromFile(accessCfgFile)
+ if err != nil {
+ return nil, fmt.Errorf("Invalid config file %s: %s", accessCfgFile, err)
+ }
+ cfgAccount := "DEFAULT"
+ if c.AccessCfgFileAccount != "" {
+ cfgAccount = c.AccessCfgFileAccount
+ }
+
+ var ok bool
+ accessCfg, ok = loadedAccessCfgs[cfgAccount]
+ if !ok {
+ return nil, fmt.Errorf("No account section '%s' found in config file %s", cfgAccount, accessCfgFile)
+ }
+ }
+
+ // Override SDK client config with any non-empty template properties
+
+ if c.UserID != "" {
+ accessCfg.User = c.UserID
+ }
+
+ if c.TenancyID != "" {
+ accessCfg.Tenancy = c.TenancyID
+ }
+
+ if c.Region != "" {
+ accessCfg.Region = c.Region
+ } else {
+ accessCfg.Region = "us-phoenix-1"
+ }
+
+ if c.Fingerprint != "" {
+ accessCfg.Fingerprint = c.Fingerprint
+ }
+
+ if c.PassPhrase != "" {
+ accessCfg.PassPhrase = c.PassPhrase
+ }
+
+ if c.KeyFile != "" {
+ accessCfg.KeyFile = c.KeyFile
+ accessCfg.Key, err = client.LoadPrivateKey(accessCfg)
+ if err != nil {
+ return nil, fmt.Errorf("Failed to load private key %s : %s", accessCfg.KeyFile, err)
+ }
+ }
+
+ var errs *packer.MultiError
+ if es := c.Comm.Prepare(&c.ctx); len(es) > 0 {
+ errs = packer.MultiErrorAppend(errs, es...)
+ }
+
+ // Required AccessCfg configuration options
+
+ if accessCfg.User == "" {
+ errs = packer.MultiErrorAppend(
+ errs, errors.New("'user_ocid' must be specified"))
+ }
+
+ if accessCfg.Tenancy == "" {
+ errs = packer.MultiErrorAppend(
+ errs, errors.New("'tenancy_ocid' must be specified"))
+ }
+
+ if accessCfg.Region == "" {
+ errs = packer.MultiErrorAppend(
+ errs, errors.New("'region' must be specified"))
+ }
+
+ if accessCfg.Fingerprint == "" {
+ errs = packer.MultiErrorAppend(
+ errs, errors.New("'fingerprint' must be specified"))
+ }
+
+ if accessCfg.Key == nil {
+ errs = packer.MultiErrorAppend(
+ errs, errors.New("'key_file' must be specified"))
+ }
+
+ c.AccessCfg = accessCfg
+
+ // Required non AccessCfg configuration options
+
+ if c.AvailabilityDomain == "" {
+ errs = packer.MultiErrorAppend(
+ errs, errors.New("'availability_domain' must be specified"))
+ }
+
+ if c.CompartmentID == "" {
+ c.CompartmentID = accessCfg.Tenancy
+ }
+
+ if c.Shape == "" {
+ errs = packer.MultiErrorAppend(
+ errs, errors.New("'shape' must be specified"))
+ }
+
+ if c.SubnetID == "" {
+ errs = packer.MultiErrorAppend(
+ errs, errors.New("'subnet_ocid' must be specified"))
+ }
+
+ if c.BaseImageID == "" {
+ errs = packer.MultiErrorAppend(
+ errs, errors.New("'base_image_ocid' must be specified"))
+ }
+
+ if c.ImageName == "" {
+ name, err := interpolate.Render("packer-{{timestamp}}", nil)
+ if err != nil {
+ errs = packer.MultiErrorAppend(errs,
+ fmt.Errorf("unable to parse image name: %s", err))
+ } else {
+ c.ImageName = name
+ }
+ }
+
+ if errs != nil && len(errs.Errors) > 0 {
+ return nil, errs
+ }
+
+ return c, nil
+}
+
+// getDefaultOCISettingsPath uses mitchellh/go-homedir to compute the default
+// config file location ($HOME/.oci/config).
+func getDefaultOCISettingsPath() (string, error) {
+ home, err := homedir.Dir()
+ if err != nil {
+ return "", err
+ }
+
+ path := filepath.Join(home, ".oci", "config")
+ if _, err := os.Stat(path); err != nil {
+ return "", err
+ }
+
+ return path, nil
+}
diff --git a/vendor/github.com/mitchellh/packer/builder/oracle/oci/config_test.go b/vendor/github.com/mitchellh/packer/builder/oracle/oci/config_test.go
new file mode 100644
index 00000000..bc6039a5
--- /dev/null
+++ b/vendor/github.com/mitchellh/packer/builder/oracle/oci/config_test.go
@@ -0,0 +1,181 @@
+package oci
+
+import (
+ "io/ioutil"
+ "os"
+ "reflect"
+ "strings"
+ "testing"
+
+ client "github.com/hashicorp/packer/builder/oracle/oci/client"
+)
+
+func testConfig(accessConfFile *os.File) map[string]interface{} {
+ return map[string]interface{}{
+ "availability_domain": "aaaa:PHX-AD-3",
+ "access_cfg_file": accessConfFile.Name(),
+
+ // Image
+ "base_image_ocid": "ocd1...",
+ "shape": "VM.Standard1.1",
+ "image_name": "HelloWorld",
+
+ // Networking
+ "subnet_ocid": "ocd1...",
+
+ // Comm
+ "ssh_username": "opc",
+ }
+}
+
+func getField(c *client.Config, field string) string {
+ r := reflect.ValueOf(c)
+ f := reflect.Indirect(r).FieldByName(field)
+ return string(f.String())
+}
+
+func TestConfig(t *testing.T) {
+ // Shared set-up and defered deletion
+
+ cfg, keyFile, err := client.BaseTestConfig()
+ if err != nil {
+ t.Fatal(err)
+ }
+ defer os.Remove(keyFile.Name())
+
+ cfgFile, err := client.WriteTestConfig(cfg)
+ if err != nil {
+ t.Fatal(err)
+ }
+ defer os.Remove(cfgFile.Name())
+
+ // Temporarily set $HOME to temp directory to bypass default
+ // access config loading.
+
+ tmpHome, err := ioutil.TempDir("", "packer_config_test")
+ if err != nil {
+ t.Fatalf("err: %+v", err)
+ }
+ defer os.Remove(tmpHome)
+
+ home := os.Getenv("HOME")
+ os.Setenv("HOME", tmpHome)
+ defer os.Setenv("HOME", home)
+
+ // Config tests
+
+ t.Run("BaseConfig", func(t *testing.T) {
+ raw := testConfig(cfgFile)
+ _, errs := NewConfig(raw)
+
+ if errs != nil {
+ t.Fatalf("err: %+v", errs)
+ }
+
+ })
+
+ t.Run("NoAccessConfig", func(t *testing.T) {
+ raw := testConfig(cfgFile)
+ delete(raw, "access_cfg_file")
+
+ _, errs := NewConfig(raw)
+
+ s := errs.Error()
+ expectedErrors := []string{
+ "'user_ocid'", "'tenancy_ocid'", "'fingerprint'",
+ "'key_file'",
+ }
+ for _, expected := range expectedErrors {
+ if !strings.Contains(s, expected) {
+ t.Errorf("Expected %s to contain '%s'", s, expected)
+ }
+ }
+ })
+
+ t.Run("AccessConfigTemplateOnly", func(t *testing.T) {
+ raw := testConfig(cfgFile)
+ delete(raw, "access_cfg_file")
+ raw["user_ocid"] = "ocid1..."
+ raw["tenancy_ocid"] = "ocid1..."
+ raw["fingerprint"] = "00:00..."
+ raw["key_file"] = keyFile.Name()
+
+ _, errs := NewConfig(raw)
+
+ if errs != nil {
+ t.Fatalf("err: %+v", errs)
+ }
+
+ })
+
+ t.Run("TenancyReadFromAccessCfgFile", func(t *testing.T) {
+ raw := testConfig(cfgFile)
+ c, errs := NewConfig(raw)
+ if errs != nil {
+ t.Fatalf("err: %+v", errs)
+ }
+
+ expected := "ocid1.tenancy.oc1..aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
+ if c.AccessCfg.Tenancy != expected {
+ t.Errorf("Expected tenancy: %s, got %s.", expected, c.AccessCfg.Tenancy)
+ }
+
+ })
+
+ // Test the correct errors are produced when required template keys are
+ // omitted.
+ requiredKeys := []string{"availability_domain", "base_image_ocid", "shape", "subnet_ocid"}
+ for _, k := range requiredKeys {
+ t.Run(k+"_required", func(t *testing.T) {
+ raw := testConfig(cfgFile)
+ delete(raw, k)
+
+ _, errs := NewConfig(raw)
+
+ if !strings.Contains(errs.Error(), k) {
+ t.Errorf("Expected '%s' to contain '%s'", errs.Error(), k)
+ }
+ })
+ }
+
+ t.Run("ImageNameDefaultedIfEmpty", func(t *testing.T) {
+ raw := testConfig(cfgFile)
+ delete(raw, "image_name")
+
+ c, errs := NewConfig(raw)
+ if errs != nil {
+ t.Errorf("Unexpected error(s): %s", errs)
+ }
+
+ if !strings.Contains(c.ImageName, "packer-") {
+ t.Errorf("got default ImageName %q, want image name 'packer-{{timestamp}}'", c.ImageName)
+ }
+ })
+
+ // Test that AccessCfgFile properties are overridden by their
+ // corosponding template keys.
+ accessOverrides := map[string]string{
+ "user_ocid": "User",
+ "tenancy_ocid": "Tenancy",
+ "region": "Region",
+ "fingerprint": "Fingerprint",
+ }
+ for k, v := range accessOverrides {
+ t.Run("AccessCfg."+v+"Overridden", func(t *testing.T) {
+ expected := "override"
+
+ raw := testConfig(cfgFile)
+ raw[k] = expected
+
+ c, errs := NewConfig(raw)
+ if errs != nil {
+ t.Fatalf("err: %+v", errs)
+ }
+
+ accessVal := getField(c.AccessCfg, v)
+ if accessVal != expected {
+ t.Errorf("Expected AccessCfg.%s: %s, got %s", v, expected, accessVal)
+ }
+ })
+ }
+}
diff --git a/vendor/github.com/mitchellh/packer/builder/oracle/oci/driver.go b/vendor/github.com/mitchellh/packer/builder/oracle/oci/driver.go
new file mode 100644
index 00000000..51f6c364
--- /dev/null
+++ b/vendor/github.com/mitchellh/packer/builder/oracle/oci/driver.go
@@ -0,0 +1,16 @@
+package oci
+
+import (
+ client "github.com/hashicorp/packer/builder/oracle/oci/client"
+)
+
+// Driver interfaces between the builder steps and the OCI SDK.
+type Driver interface {
+ CreateInstance(publicKey string) (string, error)
+ CreateImage(id string) (client.Image, error)
+ DeleteImage(id string) error
+ GetInstanceIP(id string) (string, error)
+ TerminateInstance(id string) error
+ WaitForImageCreation(id string) error
+ WaitForInstanceState(id string, waitStates []string, terminalState string) error
+}
diff --git a/vendor/github.com/mitchellh/packer/builder/oracle/oci/driver_mock.go b/vendor/github.com/mitchellh/packer/builder/oracle/oci/driver_mock.go
new file mode 100644
index 00000000..6173760f
--- /dev/null
+++ b/vendor/github.com/mitchellh/packer/builder/oracle/oci/driver_mock.go
@@ -0,0 +1,89 @@
+package oci
+
+import (
+ client "github.com/hashicorp/packer/builder/oracle/oci/client"
+)
+
+// driverMock implements the Driver interface and communicates with Oracle
+// OCI.
+type driverMock struct {
+ CreateInstanceID string
+ CreateInstanceErr error
+
+ CreateImageID string
+ CreateImageErr error
+
+ DeleteImageID string
+ DeleteImageErr error
+
+ GetInstanceIPErr error
+
+ TerminateInstanceID string
+ TerminateInstanceErr error
+
+ WaitForImageCreationErr error
+
+ WaitForInstanceStateErr error
+}
+
+// CreateInstance creates a new compute instance.
+func (d *driverMock) CreateInstance(publicKey string) (string, error) {
+ if d.CreateInstanceErr != nil {
+ return "", d.CreateInstanceErr
+ }
+
+ d.CreateInstanceID = "ocid1..."
+
+ return d.CreateInstanceID, nil
+}
+
+// CreateImage creates a new custom image.
+func (d *driverMock) CreateImage(id string) (client.Image, error) {
+ if d.CreateImageErr != nil {
+ return client.Image{}, d.CreateImageErr
+ }
+ d.CreateImageID = id
+ return client.Image{ID: id}, nil
+}
+
+// DeleteImage mocks deleting a custom image.
+func (d *driverMock) DeleteImage(id string) error {
+ if d.DeleteImageErr != nil {
+ return d.DeleteImageErr
+ }
+
+ d.DeleteImageID = id
+
+ return nil
+}
+
+// GetInstanceIP returns the public IP corresponding to the given instance id.
+func (d *driverMock) GetInstanceIP(id string) (string, error) {
+ if d.GetInstanceIPErr != nil {
+ return "", d.GetInstanceIPErr
+ }
+ return "ip", nil
+}
+
+// TerminateInstance terminates a compute instance.
+func (d *driverMock) TerminateInstance(id string) error {
+ if d.TerminateInstanceErr != nil {
+ return d.TerminateInstanceErr
+ }
+
+ d.TerminateInstanceID = id
+
+ return nil
+}
+
+// WaitForImageCreation waits for a provisioning custom image to reach the
+// "AVAILABLE" state.
+func (d *driverMock) WaitForImageCreation(id string) error {
+ return d.WaitForImageCreationErr
+}
+
+// WaitForInstanceState waits for an instance to reach the a given terminal
+// state.
+func (d *driverMock) WaitForInstanceState(id string, waitStates []string, terminalState string) error {
+ return d.WaitForInstanceStateErr
+}
diff --git a/vendor/github.com/mitchellh/packer/builder/oracle/oci/driver_oci.go b/vendor/github.com/mitchellh/packer/builder/oracle/oci/driver_oci.go
new file mode 100644
index 00000000..1d6f943c
--- /dev/null
+++ b/vendor/github.com/mitchellh/packer/builder/oracle/oci/driver_oci.go
@@ -0,0 +1,117 @@
+package oci
+
+import (
+ "errors"
+ "fmt"
+
+ client "github.com/hashicorp/packer/builder/oracle/oci/client"
+)
+
+// driverOCI implements the Driver interface and communicates with Oracle
+// OCI.
+type driverOCI struct {
+ client *client.Client
+ cfg *Config
+}
+
+// NewDriverOCI Creates a new driverOCI with a connected client.
+func NewDriverOCI(cfg *Config) (Driver, error) {
+ client, err := client.NewClient(cfg.AccessCfg)
+ if err != nil {
+ return nil, err
+ }
+ return &driverOCI{client: client, cfg: cfg}, nil
+}
+
+// CreateInstance creates a new compute instance.
+func (d *driverOCI) CreateInstance(publicKey string) (string, error) {
+ params := &client.LaunchInstanceParams{
+ AvailabilityDomain: d.cfg.AvailabilityDomain,
+ CompartmentID: d.cfg.CompartmentID,
+ ImageID: d.cfg.BaseImageID,
+ Shape: d.cfg.Shape,
+ SubnetID: d.cfg.SubnetID,
+ Metadata: map[string]string{
+ "ssh_authorized_keys": publicKey,
+ },
+ }
+ instance, err := d.client.Compute.Instances.Launch(params)
+ if err != nil {
+ return "", err
+ }
+
+ return instance.ID, nil
+}
+
+// CreateImage creates a new custom image.
+func (d *driverOCI) CreateImage(id string) (client.Image, error) {
+ params := &client.CreateImageParams{
+ CompartmentID: d.cfg.CompartmentID,
+ InstanceID: id,
+ DisplayName: d.cfg.ImageName,
+ }
+ image, err := d.client.Compute.Images.Create(params)
+ if err != nil {
+ return client.Image{}, err
+ }
+
+ return image, nil
+}
+
+// DeleteImage deletes a custom image.
+func (d *driverOCI) DeleteImage(id string) error {
+ return d.client.Compute.Images.Delete(&client.DeleteImageParams{ID: id})
+}
+
+// GetInstanceIP returns the public IP corresponding to the given instance id.
+func (d *driverOCI) GetInstanceIP(id string) (string, error) {
+ // get nvic and cross ref to find pub ip address
+ vnics, err := d.client.Compute.VNICAttachments.List(
+ &client.ListVnicAttachmentsParams{
+ InstanceID: id,
+ CompartmentID: d.cfg.CompartmentID,
+ },
+ )
+ if err != nil {
+ return "", err
+ }
+
+ if len(vnics) < 1 {
+ return "", errors.New("instance has zero VNICs")
+ }
+
+ vnic, err := d.client.Compute.VNICs.Get(&client.GetVNICParams{ID: vnics[0].VNICID})
+ if err != nil {
+ return "", fmt.Errorf("Error getting VNIC details: %s", err)
+ }
+
+ return vnic.PublicIP, nil
+}
+
+// TerminateInstance terminates a compute instance.
+func (d *driverOCI) TerminateInstance(id string) error {
+ params := &client.TerminateInstanceParams{ID: id}
+ return d.client.Compute.Instances.Terminate(params)
+}
+
+// WaitForImageCreation waits for a provisioning custom image to reach the
+// "AVAILABLE" state.
+func (d *driverOCI) WaitForImageCreation(id string) error {
+ return client.NewWaiter().WaitForResourceToReachState(
+ d.client.Compute.Images,
+ id,
+ []string{"PROVISIONING"},
+ "AVAILABLE",
+ )
+}
+
+// WaitForInstanceState waits for an instance to reach the a given terminal
+// state.
+func (d *driverOCI) WaitForInstanceState(id string, waitStates []string, terminalState string) error {
+ return client.NewWaiter().WaitForResourceToReachState(
+ d.client.Compute.Instances,
+ id,
+ waitStates,
+ terminalState,
+ )
+}
diff --git a/vendor/github.com/mitchellh/packer/builder/oracle/oci/ssh.go b/vendor/github.com/mitchellh/packer/builder/oracle/oci/ssh.go
new file mode 100644
index 00000000..a9d62f4a
--- /dev/null
+++ b/vendor/github.com/mitchellh/packer/builder/oracle/oci/ssh.go
@@ -0,0 +1,45 @@
+package oci
+
+import (
+ "fmt"
+
+ packerssh "github.com/hashicorp/packer/communicator/ssh"
+ "github.com/mitchellh/multistep"
+ "golang.org/x/crypto/ssh"
+)
+
+func commHost(state multistep.StateBag) (string, error) {
+ ipAddress := state.Get("instance_ip").(string)
+ return ipAddress, nil
+}
+
+// SSHConfig returns a function that can be used for the SSH communicator
+// config for connecting to the instance created over SSH using the private key
+// or password.
+func SSHConfig(username, password string) func(state multistep.StateBag) (*ssh.ClientConfig, error) {
+ return func(state multistep.StateBag) (*ssh.ClientConfig, error) {
+ privateKey, hasKey := state.GetOk("privateKey")
+ if hasKey {
+
+ signer, err := ssh.ParsePrivateKey([]byte(privateKey.(string)))
+ if err != nil {
+ return nil, fmt.Errorf("Error setting up SSH config: %s", err)
+ }
+ return &ssh.ClientConfig{
+ User: username,
+ Auth: []ssh.AuthMethod{ssh.PublicKeys(signer)},
+ HostKeyCallback: ssh.InsecureIgnoreHostKey(),
+ }, nil
+
+ }
+
+ return &ssh.ClientConfig{
+ User: username,
+ HostKeyCallback: ssh.InsecureIgnoreHostKey(),
+ Auth: []ssh.AuthMethod{
+ ssh.Password(password),
+ ssh.KeyboardInteractive(packerssh.PasswordKeyboardInteractive(password)),
+ },
+ }, nil
+ }
+}
diff --git a/vendor/github.com/mitchellh/packer/builder/oracle/oci/step_create_instance.go b/vendor/github.com/mitchellh/packer/builder/oracle/oci/step_create_instance.go
new file mode 100644
index 00000000..8650f731
--- /dev/null
+++ b/vendor/github.com/mitchellh/packer/builder/oracle/oci/step_create_instance.go
@@ -0,0 +1,75 @@
+package oci
+
+import (
+ "fmt"
+
+ "github.com/hashicorp/packer/packer"
+ "github.com/mitchellh/multistep"
+)
+
+type stepCreateInstance struct{}
+
+func (s *stepCreateInstance) Run(state multistep.StateBag) multistep.StepAction {
+ var (
+ driver = state.Get("driver").(Driver)
+ ui = state.Get("ui").(packer.Ui)
+ publicKey = state.Get("publicKey").(string)
+ )
+
+ ui.Say("Creating instance...")
+
+ instanceID, err := driver.CreateInstance(publicKey)
+ if err != nil {
+ err = fmt.Errorf("Problem creating instance: %s", err)
+ ui.Error(err.Error())
+ state.Put("error", err)
+ return multistep.ActionHalt
+ }
+
+ state.Put("instance_id", instanceID)
+
+ ui.Say(fmt.Sprintf("Created instance (%s).", instanceID))
+
+ ui.Say("Waiting for instance to enter 'RUNNING' state...")
+
+ if err = driver.WaitForInstanceState(instanceID, []string{"STARTING", "PROVISIONING"}, "RUNNING"); err != nil {
+ err = fmt.Errorf("Error waiting for instance to start: %s", err)
+ ui.Error(err.Error())
+ state.Put("error", err)
+ return multistep.ActionHalt
+ }
+
+ ui.Say("Instance 'RUNNING'.")
+
+ return multistep.ActionContinue
+}
+
+func (s *stepCreateInstance) Cleanup(state multistep.StateBag) {
+ driver := state.Get("driver").(Driver)
+ ui := state.Get("ui").(packer.Ui)
+
+ idRaw, ok := state.GetOk("instance_id")
+ if !ok {
+ return
+ }
+ id := idRaw.(string)
+
+ ui.Say(fmt.Sprintf("Terminating instance (%s)...", id))
+
+ if err := driver.TerminateInstance(id); err != nil {
+ err = fmt.Errorf("Error terminating instance. Please terminate manually: %s", err)
+ ui.Error(err.Error())
+ state.Put("error", err)
+ return
+ }
+
+ err := driver.WaitForInstanceState(id, []string{"TERMINATING"}, "TERMINATED")
+ if err != nil {
+ err = fmt.Errorf("Error terminating instance. Please terminate manually: %s", err)
+ ui.Error(err.Error())
+ state.Put("error", err)
+ return
+ }
+
+ ui.Say("Terminated instance.")
+}
diff --git a/vendor/github.com/mitchellh/packer/builder/oracle/oci/step_create_instance_test.go b/vendor/github.com/mitchellh/packer/builder/oracle/oci/step_create_instance_test.go
new file mode 100644
index 00000000..558a17cb
--- /dev/null
+++ b/vendor/github.com/mitchellh/packer/builder/oracle/oci/step_create_instance_test.go
@@ -0,0 +1,130 @@
+package oci
+
+import (
+ "errors"
+ "testing"
+
+ "github.com/mitchellh/multistep"
+)
+
+func TestStepCreateInstance(t *testing.T) {
+ state := testState()
+ state.Put("publicKey", "key")
+
+ step := new(stepCreateInstance)
+ defer step.Cleanup(state)
+
+ driver := state.Get("driver").(*driverMock)
+
+ if action := step.Run(state); action != multistep.ActionContinue {
+ t.Fatalf("bad action: %#v", action)
+ }
+
+ instanceIDRaw, ok := state.GetOk("instance_id")
+ if !ok {
+ t.Fatalf("should have machine")
+ }
+
+ step.Cleanup(state)
+
+ if driver.TerminateInstanceID != instanceIDRaw.(string) {
+ t.Fatalf(
+ "should've deleted instance (%s != %s)",
+ driver.TerminateInstanceID, instanceIDRaw.(string))
+ }
+}
+
+func TestStepCreateInstance_CreateInstanceErr(t *testing.T) {
+ state := testState()
+ state.Put("publicKey", "key")
+
+ step := new(stepCreateInstance)
+ defer step.Cleanup(state)
+
+ driver := state.Get("driver").(*driverMock)
+ driver.CreateInstanceErr = errors.New("error")
+
+ if action := step.Run(state); action != multistep.ActionHalt {
+ t.Fatalf("bad action: %#v", action)
+ }
+
+ if _, ok := state.GetOk("error"); !ok {
+ t.Fatalf("should have error")
+ }
+
+ if _, ok := state.GetOk("instance_id"); ok {
+ t.Fatalf("should NOT have instance_id")
+ }
+
+ step.Cleanup(state)
+
+ if driver.TerminateInstanceID != "" {
+ t.Fatalf("Should not have tried to terminate an instance")
+ }
+}
+
+func TestStepCreateInstance_WaitForInstanceStateErr(t *testing.T) {
+ state := testState()
+ state.Put("publicKey", "key")
+
+ step := new(stepCreateInstance)
+ defer step.Cleanup(state)
+
+ driver := state.Get("driver").(*driverMock)
+ driver.WaitForInstanceStateErr = errors.New("error")
+
+ if action := step.Run(state); action != multistep.ActionHalt {
+ t.Fatalf("bad action: %#v", action)
+ }
+
+ if _, ok := state.GetOk("error"); !ok {
+ t.Fatalf("should have error")
+ }
+}
+
+func TestStepCreateInstance_TerminateInstanceErr(t *testing.T) {
+ state := testState()
+ state.Put("publicKey", "key")
+
+ step := new(stepCreateInstance)
+ defer step.Cleanup(state)
+
+ driver := state.Get("driver").(*driverMock)
+
+ if action := step.Run(state); action != multistep.ActionContinue {
+ t.Fatalf("bad action: %#v", action)
+ }
+
+ _, ok := state.GetOk("instance_id")
+ if !ok {
+ t.Fatalf("should have machine")
+ }
+
+ driver.TerminateInstanceErr = errors.New("error")
+ step.Cleanup(state)
+
+ if _, ok := state.GetOk("error"); !ok {
+ t.Fatalf("should have error")
+ }
+}
+
+func TestStepCreateInstanceCleanup_WaitForInstanceStateErr(t *testing.T) {
+ state := testState()
+ state.Put("publicKey", "key")
+
+ step := new(stepCreateInstance)
+ defer step.Cleanup(state)
+
+ driver := state.Get("driver").(*driverMock)
+
+ if action := step.Run(state); action != multistep.ActionContinue {
+ t.Fatalf("bad action: %#v", action)
+ }
+
+ driver.WaitForInstanceStateErr = errors.New("error")
+ step.Cleanup(state)
+
+ if _, ok := state.GetOk("error"); !ok {
+ t.Fatalf("should have error")
+ }
+}
diff --git a/vendor/github.com/mitchellh/packer/builder/oracle/oci/step_image.go b/vendor/github.com/mitchellh/packer/builder/oracle/oci/step_image.go
new file mode 100644
index 00000000..07c9ddb4
--- /dev/null
+++ b/vendor/github.com/mitchellh/packer/builder/oracle/oci/step_image.go
@@ -0,0 +1,48 @@
+package oci
+
+import (
+ "fmt"
+
+ "github.com/hashicorp/packer/packer"
+ "github.com/mitchellh/multistep"
+)
+
+type stepImage struct{}
+
+func (s *stepImage) Run(state multistep.StateBag) multistep.StepAction {
+ var (
+ driver = state.Get("driver").(Driver)
+ ui = state.Get("ui").(packer.Ui)
+ instanceID = state.Get("instance_id").(string)
+ )
+
+ ui.Say("Creating image from instance...")
+
+ image, err := driver.CreateImage(instanceID)
+ if err != nil {
+ err = fmt.Errorf("Error creating image from instance: %s", err)
+ ui.Error(err.Error())
+ state.Put("error", err)
+ return multistep.ActionHalt
+ }
+
+ err = driver.WaitForImageCreation(image.ID)
+ if err != nil {
+ err = fmt.Errorf("Error waiting for image creation to finish: %s", err)
+ ui.Error(err.Error())
+ state.Put("error", err)
+ return multistep.ActionHalt
+ }
+
+ // TODO(apryde): This is stale as .LifecycleState has changed to
+ // AVAILABLE at this point. Does it matter?
+ state.Put("image", image)
+
+ ui.Say("Image created.")
+
+ return multistep.ActionContinue
+}
+
+func (s *stepImage) Cleanup(state multistep.StateBag) {
+ // Nothing to do
+}
diff --git a/vendor/github.com/mitchellh/packer/builder/oracle/oci/step_image_test.go b/vendor/github.com/mitchellh/packer/builder/oracle/oci/step_image_test.go
new file mode 100644
index 00000000..72399278
--- /dev/null
+++ b/vendor/github.com/mitchellh/packer/builder/oracle/oci/step_image_test.go
@@ -0,0 +1,70 @@
+package oci
+
+import (
+ "errors"
+ "testing"
+
+ "github.com/mitchellh/multistep"
+)
+
+func TestStepImage(t *testing.T) {
+ state := testState()
+ state.Put("instance_id", "ocid1...")
+
+ step := new(stepImage)
+ defer step.Cleanup(state)
+
+ if action := step.Run(state); action != multistep.ActionContinue {
+ t.Fatalf("bad action: %#v", action)
+ }
+
+ if _, ok := state.GetOk("image"); !ok {
+ t.Fatalf("should have image")
+ }
+}
+
+func TestStepImage_CreateImageErr(t *testing.T) {
+ state := testState()
+ state.Put("instance_id", "ocid1...")
+
+ step := new(stepImage)
+ defer step.Cleanup(state)
+
+ driver := state.Get("driver").(*driverMock)
+ driver.CreateImageErr = errors.New("error")
+
+ if action := step.Run(state); action != multistep.ActionHalt {
+ t.Fatalf("bad action: %#v", action)
+ }
+
+ if _, ok := state.GetOk("error"); !ok {
+ t.Fatalf("should have error")
+ }
+
+ if _, ok := state.GetOk("image"); ok {
+ t.Fatalf("should NOT have image")
+ }
+}
+
+func TestStepImage_WaitForImageCreationErr(t *testing.T) {
+ state := testState()
+ state.Put("instance_id", "ocid1...")
+
+ step := new(stepImage)
+ defer step.Cleanup(state)
+
+ driver := state.Get("driver").(*driverMock)
+ driver.WaitForImageCreationErr = errors.New("error")
+
+ if action := step.Run(state); action != multistep.ActionHalt {
+ t.Fatalf("bad action: %#v", action)
+ }
+
+ if _, ok := state.GetOk("error"); !ok {
+ t.Fatalf("should have error")
+ }
+
+ if _, ok := state.GetOk("image"); ok {
+ t.Fatalf("should not have image")
+ }
+}
diff --git a/vendor/github.com/mitchellh/packer/builder/oracle/oci/step_instance_info.go b/vendor/github.com/mitchellh/packer/builder/oracle/oci/step_instance_info.go
new file mode 100644
index 00000000..310d8699
--- /dev/null
+++ b/vendor/github.com/mitchellh/packer/builder/oracle/oci/step_instance_info.go
@@ -0,0 +1,36 @@
+package oci
+
+import (
+ "fmt"
+
+ "github.com/hashicorp/packer/packer"
+ "github.com/mitchellh/multistep"
+)
+
+type stepInstanceInfo struct{}
+
+func (s *stepInstanceInfo) Run(state multistep.StateBag) multistep.StepAction {
+ var (
+ driver = state.Get("driver").(Driver)
+ ui = state.Get("ui").(packer.Ui)
+ id = state.Get("instance_id").(string)
+ )
+
+ ip, err := driver.GetInstanceIP(id)
+ if err != nil {
+ err = fmt.Errorf("Error getting instance's public IP: %s", err)
+ ui.Error(err.Error())
+ state.Put("error", err)
+ return multistep.ActionHalt
+ }
+
+ state.Put("instance_ip", ip)
+
+ ui.Say(fmt.Sprintf("Instance has public IP: %s.", ip))
+
+ return multistep.ActionContinue
+}
+
+func (s *stepInstanceInfo) Cleanup(state multistep.StateBag) {
+ // no cleanup
+}
diff --git a/vendor/github.com/mitchellh/packer/builder/oracle/oci/step_instance_info_test.go b/vendor/github.com/mitchellh/packer/builder/oracle/oci/step_instance_info_test.go
new file mode 100644
index 00000000..fdae8a0e
--- /dev/null
+++ b/vendor/github.com/mitchellh/packer/builder/oracle/oci/step_instance_info_test.go
@@ -0,0 +1,52 @@
+package oci
+
+import (
+ "errors"
+ "testing"
+
+ "github.com/mitchellh/multistep"
+)
+
+func TestInstanceInfo(t *testing.T) {
+ state := testState()
+ state.Put("instance_id", "ocid1...")
+
+ step := new(stepInstanceInfo)
+ defer step.Cleanup(state)
+
+ if action := step.Run(state); action != multistep.ActionContinue {
+ t.Fatalf("bad action: %#v", action)
+ }
+
+ instanceIPRaw, ok := state.GetOk("instance_ip")
+ if !ok {
+ t.Fatalf("should have instance_ip")
+ }
+
+ if instanceIPRaw.(string) != "ip" {
+ t.Fatalf("should've got ip ('%s' != 'ip')", instanceIPRaw.(string))
+ }
+}
+
+func TestInstanceInfo_GetInstanceIPErr(t *testing.T) {
+ state := testState()
+ state.Put("instance_id", "ocid1...")
+
+ step := new(stepInstanceInfo)
+ defer step.Cleanup(state)
+
+ driver := state.Get("driver").(*driverMock)
+ driver.GetInstanceIPErr = errors.New("error")
+
+ if action := step.Run(state); action != multistep.ActionHalt {
+ t.Fatalf("bad action: %#v", action)
+ }
+
+ if _, ok := state.GetOk("error"); !ok {
+ t.Fatalf("should have error")
+ }
+
+ if _, ok := state.GetOk("instance_ip"); ok {
+ t.Fatalf("should NOT have instance_ip")
+ }
+}
diff --git a/vendor/github.com/mitchellh/packer/builder/oracle/oci/step_ssh_key_pair.go b/vendor/github.com/mitchellh/packer/builder/oracle/oci/step_ssh_key_pair.go
new file mode 100644
index 00000000..cc9d0358
--- /dev/null
+++ b/vendor/github.com/mitchellh/packer/builder/oracle/oci/step_ssh_key_pair.go
@@ -0,0 +1,116 @@
+package oci
+
+import (
+ "crypto/rand"
+ "crypto/rsa"
+ "crypto/x509"
+ "encoding/pem"
+ "fmt"
+ "io/ioutil"
+ "os"
+ "runtime"
+
+ "github.com/hashicorp/packer/packer"
+ "github.com/mitchellh/multistep"
+ "golang.org/x/crypto/ssh"
+)
+
+type stepKeyPair struct {
+ Debug bool
+ DebugKeyPath string
+ PrivateKeyFile string
+}
+
+func (s *stepKeyPair) Run(state multistep.StateBag) multistep.StepAction {
+ ui := state.Get("ui").(packer.Ui)
+
+ if s.PrivateKeyFile != "" {
+ privateKeyBytes, err := ioutil.ReadFile(s.PrivateKeyFile)
+ if err != nil {
+ err = fmt.Errorf("Error loading configured private key file: %s", err)
+ ui.Error(err.Error())
+ state.Put("error", err)
+ return multistep.ActionHalt
+ }
+
+ key, err := ssh.ParsePrivateKey(privateKeyBytes)
+ if err != nil {
+ err = fmt.Errorf("Error parsing 'ssh_private_key_file': %s", err)
+ ui.Error(err.Error())
+ state.Put("error", err)
+ return multistep.ActionHalt
+ }
+
+ state.Put("publicKey", string(ssh.MarshalAuthorizedKey(key.PublicKey())))
+ state.Put("privateKey", string(privateKeyBytes))
+
+ return multistep.ActionContinue
+ }
+
+ ui.Say("Creating temporary ssh key for instance...")
+
+ priv, err := rsa.GenerateKey(rand.Reader, 2048)
+ if err != nil {
+ err = fmt.Errorf("Error creating temporary SSH key: %s", err)
+ ui.Error(err.Error())
+ state.Put("error", err)
+ return multistep.ActionHalt
+ }
+
+ // ASN.1 DER encoded form
+ privDer := x509.MarshalPKCS1PrivateKey(priv)
+ privBlk := pem.Block{Type: "RSA PRIVATE KEY", Headers: nil, Bytes: privDer}
+
+ // Set the private key in the statebag for later
+ state.Put("privateKey", string(pem.EncodeToMemory(&privBlk)))
+
+ // Marshal the public key into SSH compatible format
+ pub, err := ssh.NewPublicKey(&priv.PublicKey)
+ if err != nil {
+ err = fmt.Errorf("Error marshaling temporary SSH public key: %s", err)
+ ui.Error(err.Error())
+ state.Put("error", err)
+ return multistep.ActionHalt
+ }
+
+ pubSSHFormat := string(ssh.MarshalAuthorizedKey(pub))
+ state.Put("publicKey", pubSSHFormat)
+
+ // If we're in debug mode, output the private key to the working
+ // directory.
+ if s.Debug {
+ ui.Message(fmt.Sprintf("Saving key for debug purposes: %s", s.DebugKeyPath))
+ f, err := os.Create(s.DebugKeyPath)
+ if err != nil {
+ err = fmt.Errorf("Error saving debug key: %s", err)
+ ui.Error(err.Error())
+ state.Put("error", err)
+ return multistep.ActionHalt
+ }
+ defer f.Close()
+
+ // Write the key out
+ if _, err := f.Write(pem.EncodeToMemory(&privBlk)); err != nil {
+ err = fmt.Errorf("Error saving debug key: %s", err)
+ ui.Error(err.Error())
+ state.Put("error", err)
+ return multistep.ActionHalt
+ }
+
+ // Chmod it so that it is SSH ready
+ if runtime.GOOS != "windows" {
+ if err := f.Chmod(0600); err != nil {
+ err = fmt.Errorf("Error setting permissions of debug key: %s", err)
+ ui.Error(err.Error())
+ state.Put("error", err)
+ return multistep.ActionHalt
+ }
+ }
+ }
+
+ return multistep.ActionContinue
+}
+
+func (s *stepKeyPair) Cleanup(state multistep.StateBag) {
+ // Nothing to do
+}
diff --git a/vendor/github.com/mitchellh/packer/builder/oracle/oci/step_test.go b/vendor/github.com/mitchellh/packer/builder/oracle/oci/step_test.go
new file mode 100644
index 00000000..d4436e30
--- /dev/null
+++ b/vendor/github.com/mitchellh/packer/builder/oracle/oci/step_test.go
@@ -0,0 +1,62 @@
+package oci
+
+import (
+ "bytes"
+ "os"
+
+ "github.com/hashicorp/packer/packer"
+ "github.com/mitchellh/multistep"
+
+ client "github.com/hashicorp/packer/builder/oracle/oci/client"
+)
+
+// TODO(apryde): It would be good not to have to write a key file to disk to
+// load the config.
+func baseTestConfig() *Config {
+ _, keyFile, err := client.BaseTestConfig()
+ if err != nil {
+ panic(err)
+ }
+
+ cfg, err := NewConfig(map[string]interface{}{
+ "availability_domain": "aaaa:PHX-AD-3",
+
+ // Image
+ "base_image_ocid": "ocd1...",
+ "shape": "VM.Standard1.1",
+ "image_name": "HelloWorld",
+
+ // Networking
+ "subnet_ocid": "ocd1...",
+
+ // AccessConfig
+ "user_ocid": "ocid1...",
+ "tenancy_ocid": "ocid1...",
+ "fingerprint": "00:00...",
+ "key_file": keyFile.Name(),
+
+ // Comm
+ "ssh_username": "opc",
+ })
+
+ // Once we have a config object they key file isn't re-read so we can
+ // remove it now.
+ os.Remove(keyFile.Name())
+
+ if err != nil {
+ panic(err)
+ }
+ return cfg
+}
+
+func testState() multistep.StateBag {
+ state := new(multistep.BasicStateBag)
+ state.Put("config", baseTestConfig())
+ state.Put("driver", &driverMock{})
+ state.Put("hook", &packer.MockHook{})
+ state.Put("ui", &packer.BasicUi{
+ Reader: new(bytes.Buffer),
+ Writer: new(bytes.Buffer),
+ })
+ return state
+}
diff --git a/vendor/github.com/mitchellh/packer/builder/parallels/common/driver_9.go b/vendor/github.com/mitchellh/packer/builder/parallels/common/driver_9.go
index e0e82fb6..b6757d89 100644
--- a/vendor/github.com/mitchellh/packer/builder/parallels/common/driver_9.go
+++ b/vendor/github.com/mitchellh/packer/builder/parallels/common/driver_9.go
@@ -13,7 +13,8 @@ import (
"strings"
"time"
- "gopkg.in/xmlpath.v2"
+ "github.com/ChrisTrenkamp/goxpath"
+ "github.com/ChrisTrenkamp/goxpath/tree/xmltree"
)
// Parallels9Driver is a base type for Parallels builders.
@@ -78,13 +79,19 @@ func getConfigValueFromXpath(path, xpath string) (string, error) {
if err != nil {
return "", err
}
- xpathComp := xmlpath.MustCompile(xpath)
- root, err := xmlpath.Parse(file)
+
+ doc, err := xmltree.ParseXML(file)
+ if err != nil {
+ return "", err
+ }
+
+ xpExec := goxpath.MustParse(xpath)
+ node, err := xpExec.Exec(doc)
if err != nil {
return "", err
}
- value, _ := xpathComp.String(root)
- return value, nil
+
+ return node.String(), nil
}
// Finds an application bundle by identifier (for "darwin" platform only)
diff --git a/vendor/github.com/mitchellh/packer/builder/parallels/common/driver_9_test.go b/vendor/github.com/mitchellh/packer/builder/parallels/common/driver_9_test.go
index f57ef663..32d7c666 100644
--- a/vendor/github.com/mitchellh/packer/builder/parallels/common/driver_9_test.go
+++ b/vendor/github.com/mitchellh/packer/builder/parallels/common/driver_9_test.go
@@ -58,3 +58,29 @@ func TestIPAddress(t *testing.T) {
t.Fatalf("Should have found 10.211.55.124, not %s!\n", ip)
}
}
+
+func TestXMLParseConfig(t *testing.T) {
+ td, err := ioutil.TempDir("", "configpvs")
+ if err != nil {
+ t.Fatalf("Error creating temp file: %s", err)
+ }
+ defer os.Remove(td)
+
+ config := []byte(`
+<ExampleParallelsConfig>
+ <SystemConfig>
+ <DiskSize>20</DiskSize>
+ </SystemConfig>
+</ExampleParallelsConfig>
+`)
+ ioutil.WriteFile(td+"/config.pvs", config, 0666)
+
+ result, err := getConfigValueFromXpath(td, "//DiskSize")
+ if err != nil {
+ t.Fatalf("Error parsing XML: %s", err)
+ }
+
+ if result != "20" {
+ t.Fatalf("Expected %q, got %q", "20", result)
+ }
+}
diff --git a/vendor/github.com/mitchellh/packer/builder/profitbricks/builder.go b/vendor/github.com/mitchellh/packer/builder/profitbricks/builder.go
index 95a2b1b2..750b843c 100644
--- a/vendor/github.com/mitchellh/packer/builder/profitbricks/builder.go
+++ b/vendor/github.com/mitchellh/packer/builder/profitbricks/builder.go
@@ -49,15 +49,7 @@ func (b *Builder) Run(ui packer.Ui, hook packer.Hook, cache packer.Cache) (packe
config := state.Get("config").(*Config)
- if b.config.PackerDebug {
- b.runner = &multistep.DebugRunner{
- Steps: steps,
- PauseFn: common.MultistepDebugFn(ui),
- }
- } else {
- b.runner = &multistep.BasicRunner{Steps: steps}
- }
-
+ b.runner = common.NewRunner(steps, b.config.PackerConfig, ui)
b.runner.Run(state)
if rawErr, ok := state.GetOk("error"); ok {
diff --git a/vendor/github.com/mitchellh/packer/builder/profitbricks/config.go b/vendor/github.com/mitchellh/packer/builder/profitbricks/config.go
index 62ffc18c..bb4e8d37 100644
--- a/vendor/github.com/mitchellh/packer/builder/profitbricks/config.go
+++ b/vendor/github.com/mitchellh/packer/builder/profitbricks/config.go
@@ -76,7 +76,7 @@ func NewConfig(raws ...interface{}) (*Config, []string, error) {
}
if c.PBUrl == "" {
- c.PBUrl = "https://api.profitbricks.com/rest/v2"
+ c.PBUrl = "https://api.profitbricks.com/cloudapi/v4"
}
if c.Cores == 0 {
diff --git a/vendor/github.com/mitchellh/packer/builder/profitbricks/step_create_server.go b/vendor/github.com/mitchellh/packer/builder/profitbricks/step_create_server.go
index 70c9148d..a4de3cb1 100644
--- a/vendor/github.com/mitchellh/packer/builder/profitbricks/step_create_server.go
+++ b/vendor/github.com/mitchellh/packer/builder/profitbricks/step_create_server.go
@@ -26,34 +26,33 @@ func (s *stepCreateServer) Run(state multistep.StateBag) multistep.StepAction {
}
ui.Say("Creating Virtual Data Center...")
img := s.getImageId(c.Image, c)
+ alias := ""
+ if img == "" {
+ alias = s.getImageAlias(c.Image, c.Region, ui)
+ }
datacenter := profitbricks.Datacenter{
Properties: profitbricks.DatacenterProperties{
Name: c.SnapshotName,
Location: c.Region,
},
- Entities: profitbricks.DatacenterEntities{
- Servers: &profitbricks.Servers{
- Items: []profitbricks.Server{
+ }
+ server := profitbricks.Server{
+ Properties: profitbricks.ServerProperties{
+ Name: c.SnapshotName,
+ Ram: c.Ram,
+ Cores: c.Cores,
+ },
+ Entities: &profitbricks.ServerEntities{
+ Volumes: &profitbricks.Volumes{
+ Items: []profitbricks.Volume{
{
- Properties: profitbricks.ServerProperties{
- Name: c.SnapshotName,
- Ram: c.Ram,
- Cores: c.Cores,
- },
- Entities: &profitbricks.ServerEntities{
- Volumes: &profitbricks.Volumes{
- Items: []profitbricks.Volume{
- {
- Properties: profitbricks.VolumeProperties{
- Type: c.DiskType,
- Size: c.DiskSize,
- Name: c.SnapshotName,
- Image: img,
- },
- },
- },
- },
+ Properties: profitbricks.VolumeProperties{
+ Type: c.DiskType,
+ Size: c.DiskSize,
+ Name: c.SnapshotName,
+ ImageAlias: alias,
+ Image: img,
},
},
},
@@ -61,11 +60,11 @@ func (s *stepCreateServer) Run(state multistep.StateBag) multistep.StepAction {
},
}
if c.SSHKey != "" {
- datacenter.Entities.Servers.Items[0].Entities.Volumes.Items[0].Properties.SshKeys = []string{c.SSHKey}
+ server.Entities.Volumes.Items[0].Properties.SshKeys = []string{c.SSHKey}
}
if c.Comm.SSHPassword != "" {
- datacenter.Entities.Servers.Items[0].Entities.Volumes.Items[0].Properties.ImagePassword = c.Comm.SSHPassword
+ server.Entities.Volumes.Items[0].Properties.ImagePassword = c.Comm.SSHPassword
}
datacenter = profitbricks.CompositeCreateDatacenter(datacenter)
@@ -94,8 +93,20 @@ func (s *stepCreateServer) Run(state multistep.StateBag) multistep.StepAction {
state.Put("datacenter_id", datacenter.Id)
- lan := profitbricks.CreateLan(datacenter.Id, profitbricks.Lan{
- Properties: profitbricks.LanProperties{
+ server = profitbricks.CreateServer(datacenter.Id, server)
+ if server.StatusCode > 299 {
+ ui.Error(fmt.Sprintf("Error occurred %s", parseErrorMessage(server.Response)))
+ return multistep.ActionHalt
+ }
+
+ err = s.waitTillProvisioned(server.Headers.Get("Location"), *c)
+ if err != nil {
+ ui.Error(fmt.Sprintf("Error occurred while creating a server %s", err.Error()))
+ return multistep.ActionHalt
+ }
+
+ lan := profitbricks.CreateLan(datacenter.Id, profitbricks.CreateLanRequest{
+ Properties: profitbricks.CreateLanProperties{
Public: true,
Name: c.SnapshotName,
},
@@ -113,8 +124,8 @@ func (s *stepCreateServer) Run(state multistep.StateBag) multistep.StepAction {
}
lanId, _ := strconv.Atoi(lan.Id)
- nic := profitbricks.CreateNic(datacenter.Id, datacenter.Entities.Servers.Items[0].Id, profitbricks.Nic{
- Properties: profitbricks.NicProperties{
+ nic := profitbricks.CreateNic(datacenter.Id, server.Id, profitbricks.Nic{
+ Properties: &profitbricks.NicProperties{
Name: c.SnapshotName,
Lan: lanId,
Dhcp: true,
@@ -132,9 +143,9 @@ func (s *stepCreateServer) Run(state multistep.StateBag) multistep.StepAction {
return multistep.ActionHalt
}
- state.Put("volume_id", datacenter.Entities.Servers.Items[0].Entities.Volumes.Items[0].Id)
+ state.Put("volume_id", server.Entities.Volumes.Items[0].Id)
- server := profitbricks.GetServer(datacenter.Id, datacenter.Entities.Servers.Items[0].Id)
+ server = profitbricks.GetServer(datacenter.Id, server.Id)
state.Put("server_ip", server.Entities.Nics.Items[0].Properties.Ips[0])
@@ -225,6 +236,25 @@ func (d *stepCreateServer) getImageId(imageName string, c *Config) string {
return ""
}
+func (d *stepCreateServer) getImageAlias(imageAlias string, location string, ui packer.Ui) string {
+ if imageAlias == "" {
+ return ""
+ }
+ locations := profitbricks.GetLocation(location)
+ if len(locations.Properties.ImageAliases) > 0 {
+ for _, i := range locations.Properties.ImageAliases {
+ alias := ""
+ if i != "" {
+ alias = i
+ }
+ if alias != "" && strings.ToLower(alias) == strings.ToLower(imageAlias) {
+ return alias
+ }
+ }
+ }
+ return ""
+}
+
func parseErrorMessage(raw string) (toreturn string) {
var tmp map[string]interface{}
json.Unmarshal([]byte(raw), &tmp)
diff --git a/vendor/github.com/mitchellh/packer/builder/profitbricks/step_take_snapshot.go b/vendor/github.com/mitchellh/packer/builder/profitbricks/step_take_snapshot.go
index db63df73..822ea869 100644
--- a/vendor/github.com/mitchellh/packer/builder/profitbricks/step_take_snapshot.go
+++ b/vendor/github.com/mitchellh/packer/builder/profitbricks/step_take_snapshot.go
@@ -22,7 +22,7 @@ func (s *stepTakeSnapshot) Run(state multistep.StateBag) multistep.StepAction {
dcId := state.Get("datacenter_id").(string)
volumeId := state.Get("volume_id").(string)
- snapshot := profitbricks.CreateSnapshot(dcId, volumeId, c.SnapshotName)
+ snapshot := profitbricks.CreateSnapshot(dcId, volumeId, c.SnapshotName, "")
state.Put("snapshotname", c.SnapshotName)
diff --git a/vendor/github.com/mitchellh/packer/builder/vmware/common/artifact.go b/vendor/github.com/mitchellh/packer/builder/vmware/common/artifact.go
index 48fcb813..e0b3e875 100644
--- a/vendor/github.com/mitchellh/packer/builder/vmware/common/artifact.go
+++ b/vendor/github.com/mitchellh/packer/builder/vmware/common/artifact.go
@@ -14,13 +14,14 @@ const BuilderId = "mitchellh.vmware"
// Artifact is the result of running the VMware builder, namely a set
// of files associated with the resulting machine.
type localArtifact struct {
+ id string
dir string
f []string
}
// NewLocalArtifact returns a VMware artifact containing the files
// in the given directory.
-func NewLocalArtifact(dir string) (packer.Artifact, error) {
+func NewLocalArtifact(id string, dir string) (packer.Artifact, error) {
files := make([]string, 0, 5)
visit := func(path string, info os.FileInfo, err error) error {
if err != nil {
@@ -37,6 +38,7 @@ func NewLocalArtifact(dir string) (packer.Artifact, error) {
}
return &localArtifact{
+ id: id,
dir: dir,
f: files,
}, nil
@@ -50,8 +52,8 @@ func (a *localArtifact) Files() []string {
return a.f
}
-func (*localArtifact) Id() string {
- return "VM"
+func (a *localArtifact) Id() string {
+ return a.id
}
func (a *localArtifact) String() string {
diff --git a/vendor/github.com/mitchellh/packer/builder/vmware/common/artifact_test.go b/vendor/github.com/mitchellh/packer/builder/vmware/common/artifact_test.go
index e081cc35..53b8364f 100644
--- a/vendor/github.com/mitchellh/packer/builder/vmware/common/artifact_test.go
+++ b/vendor/github.com/mitchellh/packer/builder/vmware/common/artifact_test.go
@@ -29,7 +29,7 @@ func TestNewLocalArtifact(t *testing.T) {
t.Fatalf("err: %s", err)
}
- a, err := NewLocalArtifact(td)
+ a, err := NewLocalArtifact("vm1", td)
if err != nil {
t.Fatalf("err: %s", err)
}
@@ -37,6 +37,9 @@ func TestNewLocalArtifact(t *testing.T) {
if a.BuilderId() != BuilderId {
t.Fatalf("bad: %#v", a.BuilderId())
}
+ if a.Id() != "vm1" {
+ t.Fatalf("bad: %#v", a.Id())
+ }
if len(a.Files()) != 1 {
t.Fatalf("should length 1: %d", len(a.Files()))
}
diff --git a/vendor/github.com/mitchellh/packer/builder/vmware/iso/artifact.go b/vendor/github.com/mitchellh/packer/builder/vmware/iso/artifact.go
index d0e1a6d8..a0c3ceac 100644
--- a/vendor/github.com/mitchellh/packer/builder/vmware/iso/artifact.go
+++ b/vendor/github.com/mitchellh/packer/builder/vmware/iso/artifact.go
@@ -8,6 +8,7 @@ import (
// of files associated with the resulting machine.
type Artifact struct {
builderId string
+ id string
dir OutputDir
f []string
}
@@ -20,8 +21,8 @@ func (a *Artifact) Files() []string {
return a.f
}
-func (*Artifact) Id() string {
- return "VM"
+func (a *Artifact) Id() string {
+ return a.id
}
func (a *Artifact) String() string {
diff --git a/vendor/github.com/mitchellh/packer/builder/vmware/iso/builder.go b/vendor/github.com/mitchellh/packer/builder/vmware/iso/builder.go
index 42038b96..688f52d7 100644
--- a/vendor/github.com/mitchellh/packer/builder/vmware/iso/builder.go
+++ b/vendor/github.com/mitchellh/packer/builder/vmware/iso/builder.go
@@ -200,6 +200,9 @@ func (b *Builder) Run(ui packer.Ui, hook packer.Hook, cache packer.Cache) (packe
default:
dir = new(vmwcommon.LocalOutputDir)
}
+
+ exportOutputPath := b.config.OutputDir
+
if b.config.RemoteType != "" && b.config.Format != "" {
b.config.OutputDir = b.config.VMName
}
@@ -307,6 +310,7 @@ func (b *Builder) Run(ui packer.Ui, hook packer.Hook, cache packer.Cache) (packe
&StepExport{
Format: b.config.Format,
SkipExport: b.config.SkipExport,
+ OutputDir: exportOutputPath,
},
}
@@ -332,7 +336,7 @@ func (b *Builder) Run(ui packer.Ui, hook packer.Hook, cache packer.Cache) (packe
var files []string
if b.config.RemoteType != "" && b.config.Format != "" {
dir = new(vmwcommon.LocalOutputDir)
- dir.SetOutputDir(b.config.OutputDir)
+ dir.SetOutputDir(exportOutputPath)
files, err = dir.ListFiles()
} else {
files, err = state.Get("dir").(OutputDir).ListFiles()
@@ -349,6 +353,7 @@ func (b *Builder) Run(ui packer.Ui, hook packer.Hook, cache packer.Cache) (packe
return &Artifact{
builderId: builderId,
+ id: b.config.VMName,
dir: dir,
f: files,
}, nil
diff --git a/vendor/github.com/mitchellh/packer/builder/vmware/iso/step_export.go b/vendor/github.com/mitchellh/packer/builder/vmware/iso/step_export.go
index 3d055ddb..91a2ce48 100644
--- a/vendor/github.com/mitchellh/packer/builder/vmware/iso/step_export.go
+++ b/vendor/github.com/mitchellh/packer/builder/vmware/iso/step_export.go
@@ -6,7 +6,6 @@ import (
"net/url"
"os"
"os/exec"
- "path/filepath"
"runtime"
"strings"
@@ -17,9 +16,10 @@ import (
type StepExport struct {
Format string
SkipExport bool
+ OutputDir string
}
-func (s *StepExport) generateArgs(c *Config, outputPath string, hidePassword bool) []string {
+func (s *StepExport) generateArgs(c *Config, hidePassword bool) []string {
password := url.QueryEscape(c.RemotePassword)
if hidePassword {
password = "****"
@@ -29,7 +29,7 @@ func (s *StepExport) generateArgs(c *Config, outputPath string, hidePassword boo
"--skipManifestCheck",
"-tt=" + s.Format,
"vi://" + c.RemoteUser + ":" + password + "@" + c.RemoteHost + "/" + c.VMName,
- outputPath,
+ s.OutputDir,
}
return append(c.OVFToolOptions, args...)
}
@@ -45,6 +45,7 @@ func (s *StepExport) Run(state multistep.StateBag) multistep.StepAction {
}
if c.RemoteType != "esx5" || s.Format == "" {
+ ui.Say("Skipping export of virtual machine (export is allowed only for ESXi and the format needs to be specified)...")
return multistep.ActionContinue
}
@@ -61,16 +62,18 @@ func (s *StepExport) Run(state multistep.StateBag) multistep.StepAction {
}
// Export the VM
- outputPath := filepath.Join(c.VMName, c.VMName+"."+s.Format)
+ if s.OutputDir == "" {
+ s.OutputDir = c.VMName + "." + s.Format
+ }
if s.Format == "ova" {
- os.MkdirAll(outputPath, 0755)
+ os.MkdirAll(s.OutputDir, 0755)
}
ui.Say("Exporting virtual machine...")
- ui.Message(fmt.Sprintf("Executing: %s %s", ovftool, strings.Join(s.generateArgs(c, outputPath, true), " ")))
+ ui.Message(fmt.Sprintf("Executing: %s %s", ovftool, strings.Join(s.generateArgs(c, true), " ")))
var out bytes.Buffer
- cmd := exec.Command(ovftool, s.generateArgs(c, outputPath, false)...)
+ cmd := exec.Command(ovftool, s.generateArgs(c, false)...)
cmd.Stdout = &out
if err := cmd.Run(); err != nil {
err := fmt.Errorf("Error exporting virtual machine: %s\n%s\n", err, out.String())
@@ -81,8 +84,6 @@ func (s *StepExport) Run(state multistep.StateBag) multistep.StepAction {
ui.Message(fmt.Sprintf("%s", out.String()))
- state.Put("exportPath", outputPath)
-
return multistep.ActionContinue
}
diff --git a/vendor/github.com/mitchellh/packer/builder/vmware/vmx/builder.go b/vendor/github.com/mitchellh/packer/builder/vmware/vmx/builder.go
index c5c1f10b..894c3488 100644
--- a/vendor/github.com/mitchellh/packer/builder/vmware/vmx/builder.go
+++ b/vendor/github.com/mitchellh/packer/builder/vmware/vmx/builder.go
@@ -142,7 +142,7 @@ func (b *Builder) Run(ui packer.Ui, hook packer.Hook, cache packer.Cache) (packe
return nil, errors.New("Build was halted.")
}
- return vmwcommon.NewLocalArtifact(b.config.OutputDir)
+ return vmwcommon.NewLocalArtifact(b.config.VMName, b.config.OutputDir)
}
// Cancel.
diff --git a/vendor/github.com/mitchellh/packer/builder/vmware/vmx/config.go b/vendor/github.com/mitchellh/packer/builder/vmware/vmx/config.go
index 93e8347c..145705fd 100644
--- a/vendor/github.com/mitchellh/packer/builder/vmware/vmx/config.go
+++ b/vendor/github.com/mitchellh/packer/builder/vmware/vmx/config.go
@@ -51,7 +51,8 @@ func NewConfig(raws ...interface{}) (*Config, []string, error) {
// Defaults
if c.VMName == "" {
- c.VMName = fmt.Sprintf("packer-%s-{{timestamp}}", c.PackerBuildName)
+ c.VMName = fmt.Sprintf(
+ "packer-%s-%d", c.PackerBuildName, interpolate.InitTime.Unix())
}
// Prepare the errors