feature: add bsuvolume builder and acceptance test
This commit is contained in:
parent
c9b8bc6b54
commit
80dadaf3f1
|
@ -0,0 +1,87 @@
|
|||
package bsuvolume
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"log"
|
||||
"sort"
|
||||
"strings"
|
||||
|
||||
"github.com/hashicorp/packer/packer"
|
||||
"github.com/outscale/osc-go/oapi"
|
||||
)
|
||||
|
||||
// map of region to list of volume IDs
|
||||
type BsuVolumes map[string][]string
|
||||
|
||||
// Artifact is an artifact implementation that contains built AMIs.
|
||||
type Artifact struct {
|
||||
// A map of regions to EBS Volume IDs.
|
||||
Volumes BsuVolumes
|
||||
|
||||
// BuilderId is the unique ID for the builder that created this AMI
|
||||
BuilderIdValue string
|
||||
|
||||
// Client connection for performing API stuff.
|
||||
Conn *oapi.Client
|
||||
}
|
||||
|
||||
func (a *Artifact) BuilderId() string {
|
||||
return a.BuilderIdValue
|
||||
}
|
||||
|
||||
func (*Artifact) Files() []string {
|
||||
// We have no files
|
||||
return nil
|
||||
}
|
||||
|
||||
// returns a sorted list of region:ID pairs
|
||||
func (a *Artifact) idList() []string {
|
||||
parts := make([]string, 0, len(a.Volumes))
|
||||
for region, volumeIDs := range a.Volumes {
|
||||
for _, volumeID := range volumeIDs {
|
||||
parts = append(parts, fmt.Sprintf("%s:%s", region, volumeID))
|
||||
}
|
||||
}
|
||||
|
||||
sort.Strings(parts)
|
||||
return parts
|
||||
}
|
||||
|
||||
func (a *Artifact) Id() string {
|
||||
return strings.Join(a.idList(), ",")
|
||||
}
|
||||
|
||||
func (a *Artifact) String() string {
|
||||
return fmt.Sprintf("EBS Volumes were created:\n\n%s", strings.Join(a.idList(), "\n"))
|
||||
}
|
||||
|
||||
func (a *Artifact) State(name string) interface{} {
|
||||
return nil
|
||||
}
|
||||
|
||||
func (a *Artifact) Destroy() error {
|
||||
errors := make([]error, 0)
|
||||
|
||||
for region, volumeIDs := range a.Volumes {
|
||||
for _, volumeID := range volumeIDs {
|
||||
log.Printf("Deregistering Volume ID (%s) from region (%s)", volumeID, region)
|
||||
|
||||
input := oapi.DeleteVolumeRequest{
|
||||
VolumeId: volumeID,
|
||||
}
|
||||
if _, err := a.Conn.POST_DeleteVolume(input); err != nil {
|
||||
errors = append(errors, err)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if len(errors) > 0 {
|
||||
if len(errors) == 1 {
|
||||
return errors[0]
|
||||
} else {
|
||||
return &packer.MultiError{Errors: errors}
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
|
@ -0,0 +1,29 @@
|
|||
package bsuvolume
|
||||
|
||||
import (
|
||||
osccommon "github.com/hashicorp/packer/builder/osc/common"
|
||||
"github.com/hashicorp/packer/template/interpolate"
|
||||
)
|
||||
|
||||
type BlockDevice struct {
|
||||
osccommon.BlockDevice `mapstructure:"-,squash"`
|
||||
Tags osccommon.TagMap `mapstructure:"tags"`
|
||||
}
|
||||
|
||||
func commonBlockDevices(mappings []BlockDevice, ctx *interpolate.Context) (osccommon.BlockDevices, error) {
|
||||
result := make([]osccommon.BlockDevice, len(mappings))
|
||||
|
||||
for i, mapping := range mappings {
|
||||
interpolateBlockDev, err := interpolate.RenderInterface(&mapping.BlockDevice, ctx)
|
||||
if err != nil {
|
||||
return osccommon.BlockDevices{}, err
|
||||
}
|
||||
result[i] = *interpolateBlockDev.(*osccommon.BlockDevice)
|
||||
}
|
||||
|
||||
return osccommon.BlockDevices{
|
||||
LaunchBlockDevices: osccommon.LaunchBlockDevices{
|
||||
LaunchMappings: result,
|
||||
},
|
||||
}, nil
|
||||
}
|
|
@ -0,0 +1,204 @@
|
|||
// The ebsvolume package contains a packer.Builder implementation that
|
||||
// builds EBS volumes for Outscale using an ephemeral instance,
|
||||
package bsuvolume
|
||||
|
||||
import (
|
||||
"crypto/tls"
|
||||
"fmt"
|
||||
"log"
|
||||
"net/http"
|
||||
|
||||
osccommon "github.com/hashicorp/packer/builder/osc/common"
|
||||
"github.com/hashicorp/packer/common"
|
||||
"github.com/hashicorp/packer/helper/communicator"
|
||||
"github.com/hashicorp/packer/helper/config"
|
||||
"github.com/hashicorp/packer/helper/multistep"
|
||||
"github.com/hashicorp/packer/packer"
|
||||
"github.com/hashicorp/packer/template/interpolate"
|
||||
"github.com/outscale/osc-go/oapi"
|
||||
)
|
||||
|
||||
const BuilderId = "oapi.outscale.bsuvolume"
|
||||
|
||||
type Config struct {
|
||||
common.PackerConfig `mapstructure:",squash"`
|
||||
osccommon.AccessConfig `mapstructure:",squash"`
|
||||
osccommon.RunConfig `mapstructure:",squash"`
|
||||
|
||||
VolumeMappings []BlockDevice `mapstructure:"ebs_volumes"`
|
||||
|
||||
launchBlockDevices osccommon.BlockDevices
|
||||
ctx interpolate.Context
|
||||
}
|
||||
|
||||
type Builder struct {
|
||||
config Config
|
||||
runner multistep.Runner
|
||||
}
|
||||
|
||||
type EngineVarsTemplate struct {
|
||||
BuildRegion string
|
||||
SourceOMI string
|
||||
}
|
||||
|
||||
func (b *Builder) Prepare(raws ...interface{}) ([]string, error) {
|
||||
b.config.ctx.Funcs = osccommon.TemplateFuncs
|
||||
// Create passthrough for {{ .BuildRegion }} and {{ .SourceOMI }} variables
|
||||
// so we can fill them in later
|
||||
b.config.ctx.Data = &EngineVarsTemplate{
|
||||
BuildRegion: `{{ .BuildRegion }}`,
|
||||
SourceOMI: `{{ .SourceOMI }} `,
|
||||
}
|
||||
err := config.Decode(&b.config, &config.DecodeOpts{
|
||||
Interpolate: true,
|
||||
InterpolateContext: &b.config.ctx,
|
||||
}, raws...)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
// Accumulate any errors
|
||||
var errs *packer.MultiError
|
||||
errs = packer.MultiErrorAppend(errs, b.config.AccessConfig.Prepare(&b.config.ctx)...)
|
||||
errs = packer.MultiErrorAppend(errs, b.config.RunConfig.Prepare(&b.config.ctx)...)
|
||||
errs = packer.MultiErrorAppend(errs, b.config.launchBlockDevices.Prepare(&b.config.ctx)...)
|
||||
|
||||
for _, d := range b.config.VolumeMappings {
|
||||
if err := d.Prepare(&b.config.ctx); err != nil {
|
||||
errs = packer.MultiErrorAppend(errs, fmt.Errorf("OMIMapping: %s", err.Error()))
|
||||
}
|
||||
}
|
||||
|
||||
b.config.launchBlockDevices, err = commonBlockDevices(b.config.VolumeMappings, &b.config.ctx)
|
||||
if err != nil {
|
||||
errs = packer.MultiErrorAppend(errs, err)
|
||||
}
|
||||
|
||||
if errs != nil && len(errs.Errors) > 0 {
|
||||
return nil, errs
|
||||
}
|
||||
|
||||
packer.LogSecretFilter.Set(b.config.AccessKey, b.config.SecretKey, b.config.Token)
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
func (b *Builder) Run(ui packer.Ui, hook packer.Hook, cache packer.Cache) (packer.Artifact, error) {
|
||||
clientConfig, err := b.config.Config()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
skipClient := &http.Client{
|
||||
Transport: &http.Transport{
|
||||
TLSClientConfig: &tls.Config{InsecureSkipVerify: true},
|
||||
},
|
||||
}
|
||||
|
||||
oapiconn := oapi.NewClient(clientConfig, skipClient)
|
||||
|
||||
// Setup the state bag and initial state for the steps
|
||||
state := new(multistep.BasicStateBag)
|
||||
state.Put("config", &b.config)
|
||||
state.Put("oapi", oapiconn)
|
||||
state.Put("hook", hook)
|
||||
state.Put("ui", ui)
|
||||
|
||||
log.Printf("[DEBUG] launch block devices %#v", b.config.launchBlockDevices)
|
||||
|
||||
instanceStep := &osccommon.StepRunSourceVm{
|
||||
AssociatePublicIpAddress: b.config.AssociatePublicIpAddress,
|
||||
BlockDevices: b.config.launchBlockDevices,
|
||||
Comm: &b.config.RunConfig.Comm,
|
||||
Ctx: b.config.ctx,
|
||||
Debug: b.config.PackerDebug,
|
||||
BsuOptimized: b.config.BsuOptimized,
|
||||
EnableT2Unlimited: b.config.EnableT2Unlimited,
|
||||
ExpectedRootDevice: "ebs",
|
||||
IamVmProfile: b.config.IamVmProfile,
|
||||
VmInitiatedShutdownBehavior: b.config.VmInitiatedShutdownBehavior,
|
||||
VmType: b.config.VmType,
|
||||
SourceOMI: b.config.SourceOmi,
|
||||
Tags: b.config.RunTags,
|
||||
UserData: b.config.UserData,
|
||||
UserDataFile: b.config.UserDataFile,
|
||||
}
|
||||
|
||||
// Build the steps
|
||||
steps := []multistep.Step{
|
||||
&osccommon.StepSourceOMIInfo{
|
||||
SourceOmi: b.config.SourceOmi,
|
||||
OmiFilters: b.config.SourceOmiFilter,
|
||||
},
|
||||
&osccommon.StepNetworkInfo{
|
||||
NetId: b.config.NetId,
|
||||
NetFilter: b.config.NetFilter,
|
||||
SecurityGroupIds: b.config.SecurityGroupIds,
|
||||
SecurityGroupFilter: b.config.SecurityGroupFilter,
|
||||
SubnetId: b.config.SubnetId,
|
||||
SubnetFilter: b.config.SubnetFilter,
|
||||
SubregionName: b.config.Subregion,
|
||||
},
|
||||
&osccommon.StepKeyPair{
|
||||
Debug: b.config.PackerDebug,
|
||||
Comm: &b.config.RunConfig.Comm,
|
||||
DebugKeyPath: fmt.Sprintf("oapi_%s.pem", b.config.PackerBuildName),
|
||||
},
|
||||
&osccommon.StepSecurityGroup{
|
||||
SecurityGroupFilter: b.config.SecurityGroupFilter,
|
||||
SecurityGroupIds: b.config.SecurityGroupIds,
|
||||
CommConfig: &b.config.RunConfig.Comm,
|
||||
TemporarySGSourceCidr: b.config.TemporarySGSourceCidr,
|
||||
},
|
||||
instanceStep,
|
||||
&stepTagBSUVolumes{
|
||||
VolumeMapping: b.config.VolumeMappings,
|
||||
Ctx: b.config.ctx,
|
||||
},
|
||||
&osccommon.StepGetPassword{
|
||||
Debug: b.config.PackerDebug,
|
||||
Comm: &b.config.RunConfig.Comm,
|
||||
Timeout: b.config.WindowsPasswordTimeout,
|
||||
BuildName: b.config.PackerBuildName,
|
||||
},
|
||||
&communicator.StepConnect{
|
||||
Config: &b.config.RunConfig.Comm,
|
||||
Host: osccommon.SSHHost(
|
||||
oapiconn,
|
||||
b.config.Comm.SSHInterface),
|
||||
SSHConfig: b.config.RunConfig.Comm.SSHConfigFunc(),
|
||||
},
|
||||
&common.StepProvision{},
|
||||
&common.StepCleanupTempKeys{
|
||||
Comm: &b.config.RunConfig.Comm,
|
||||
},
|
||||
&osccommon.StepStopBSUBackedVm{
|
||||
Skip: b.config.IsSpotVm(),
|
||||
DisableStopVm: b.config.DisableStopVm,
|
||||
},
|
||||
}
|
||||
|
||||
// Run!
|
||||
b.runner = common.NewRunner(steps, b.config.PackerConfig, ui)
|
||||
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{
|
||||
Volumes: state.Get("bsuvolumes").(BsuVolumes),
|
||||
BuilderIdValue: BuilderId,
|
||||
Conn: oapiconn,
|
||||
}
|
||||
ui.Say(fmt.Sprintf("Created Volumes: %s", artifact))
|
||||
return artifact, nil
|
||||
}
|
||||
|
||||
func (b *Builder) Cancel() {
|
||||
if b.runner != nil {
|
||||
log.Println("Cancelling the step runner...")
|
||||
b.runner.Cancel()
|
||||
}
|
||||
}
|
|
@ -0,0 +1,86 @@
|
|||
//TODO: explain how to delete the image.
|
||||
package bsuvolume
|
||||
|
||||
import (
|
||||
"crypto/tls"
|
||||
"net/http"
|
||||
"testing"
|
||||
|
||||
"github.com/hashicorp/packer/builder/osc/common"
|
||||
builderT "github.com/hashicorp/packer/helper/builder/testing"
|
||||
"github.com/outscale/osc-go/oapi"
|
||||
)
|
||||
|
||||
func TestBuilderAcc_basic(t *testing.T) {
|
||||
builderT.Test(t, builderT.TestCase{
|
||||
PreCheck: func() { testAccPreCheck(t) },
|
||||
Builder: &Builder{},
|
||||
Template: testBuilderAccBasic,
|
||||
SkipArtifactTeardown: true,
|
||||
})
|
||||
}
|
||||
|
||||
func testAccPreCheck(t *testing.T) {
|
||||
}
|
||||
|
||||
func testOAPIConn() (*oapi.Client, error) {
|
||||
access := &common.AccessConfig{RawRegion: "us-east-1"}
|
||||
clientConfig, err := access.Config()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
skipClient := &http.Client{
|
||||
Transport: &http.Transport{
|
||||
TLSClientConfig: &tls.Config{InsecureSkipVerify: true},
|
||||
},
|
||||
}
|
||||
|
||||
return oapi.NewClient(clientConfig, skipClient), nil
|
||||
}
|
||||
|
||||
const testBuilderAccBasic = `
|
||||
{
|
||||
"builders": [
|
||||
{
|
||||
"type": "test",
|
||||
"region": "eu-west-2",
|
||||
"vm_type": "t2.micro",
|
||||
"source_omi": "ami-65efcc11",
|
||||
"ssh_username": "outscale",
|
||||
"ebs_volumes": [
|
||||
{
|
||||
"volume_type": "gp2",
|
||||
"device_name": "/dev/xvdf",
|
||||
"delete_on_vm_deletion": false,
|
||||
"tags": {
|
||||
"zpool": "data",
|
||||
"Name": "Data1"
|
||||
},
|
||||
"volume_size": 10
|
||||
},
|
||||
{
|
||||
"volume_type": "gp2",
|
||||
"device_name": "/dev/xvdg",
|
||||
"tags": {
|
||||
"zpool": "data",
|
||||
"Name": "Data2"
|
||||
},
|
||||
"delete_on_vm_deletion": false,
|
||||
"volume_size": 10
|
||||
},
|
||||
{
|
||||
"volume_size": 10,
|
||||
"tags": {
|
||||
"Name": "Data3",
|
||||
"zpool": "data"
|
||||
},
|
||||
"delete_on_vm_deletion": false,
|
||||
"device_name": "/dev/xvdh",
|
||||
"volume_type": "gp2"
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
`
|
|
@ -0,0 +1,92 @@
|
|||
package bsuvolume
|
||||
|
||||
import (
|
||||
"testing"
|
||||
|
||||
"github.com/hashicorp/packer/packer"
|
||||
)
|
||||
|
||||
func testConfig() map[string]interface{} {
|
||||
return map[string]interface{}{
|
||||
"access_key": "foo",
|
||||
"secret_key": "bar",
|
||||
"source_omi": "foo",
|
||||
"vm_type": "foo",
|
||||
"region": "us-east-1",
|
||||
"ssh_username": "root",
|
||||
}
|
||||
}
|
||||
|
||||
func TestBuilder_ImplementsBuilder(t *testing.T) {
|
||||
var raw interface{}
|
||||
raw = &Builder{}
|
||||
if _, ok := raw.(packer.Builder); !ok {
|
||||
t.Fatalf("Builder should be a builder")
|
||||
}
|
||||
}
|
||||
|
||||
func TestBuilder_Prepare_BadType(t *testing.T) {
|
||||
b := &Builder{}
|
||||
c := map[string]interface{}{
|
||||
"access_key": []string{},
|
||||
}
|
||||
|
||||
warnings, err := b.Prepare(c)
|
||||
if len(warnings) > 0 {
|
||||
t.Fatalf("bad: %#v", warnings)
|
||||
}
|
||||
if err == nil {
|
||||
t.Fatalf("prepare should fail")
|
||||
}
|
||||
}
|
||||
|
||||
func TestBuilderPrepare_InvalidKey(t *testing.T) {
|
||||
var b Builder
|
||||
config := testConfig()
|
||||
|
||||
// Add a random key
|
||||
config["i_should_not_be_valid"] = true
|
||||
warnings, err := b.Prepare(config)
|
||||
if len(warnings) > 0 {
|
||||
t.Fatalf("bad: %#v", warnings)
|
||||
}
|
||||
if err == nil {
|
||||
t.Fatal("should have error")
|
||||
}
|
||||
}
|
||||
|
||||
func TestBuilderPrepare_InvalidShutdownBehavior(t *testing.T) {
|
||||
var b Builder
|
||||
config := testConfig()
|
||||
|
||||
// Test good
|
||||
config["shutdown_behavior"] = "terminate"
|
||||
config["skip_region_validation"] = true
|
||||
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)
|
||||
}
|
||||
|
||||
// Test good
|
||||
config["shutdown_behavior"] = "stop"
|
||||
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)
|
||||
}
|
||||
|
||||
// Test bad
|
||||
config["shutdown_behavior"] = "foobar"
|
||||
warnings, err = b.Prepare(config)
|
||||
if len(warnings) > 0 {
|
||||
t.Fatalf("bad: %#v", warnings)
|
||||
}
|
||||
if err == nil {
|
||||
t.Fatal("should have error")
|
||||
}
|
||||
}
|
|
@ -0,0 +1,81 @@
|
|||
package bsuvolume
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
|
||||
"github.com/hashicorp/packer/helper/multistep"
|
||||
"github.com/hashicorp/packer/packer"
|
||||
"github.com/hashicorp/packer/template/interpolate"
|
||||
"github.com/outscale/osc-go/oapi"
|
||||
)
|
||||
|
||||
type stepTagBSUVolumes struct {
|
||||
VolumeMapping []BlockDevice
|
||||
Ctx interpolate.Context
|
||||
}
|
||||
|
||||
func (s *stepTagBSUVolumes) Run(_ context.Context, state multistep.StateBag) multistep.StepAction {
|
||||
oapiconn := state.Get("oapi").(*oapi.Client)
|
||||
vm := state.Get("vm").(oapi.Vm)
|
||||
ui := state.Get("ui").(packer.Ui)
|
||||
|
||||
volumes := make(BsuVolumes)
|
||||
for _, instanceBlockDevices := range vm.BlockDeviceMappings {
|
||||
for _, configVolumeMapping := range s.VolumeMapping {
|
||||
if configVolumeMapping.DeviceName == instanceBlockDevices.DeviceName {
|
||||
volumes[oapiconn.GetConfig().Region] = append(
|
||||
volumes[oapiconn.GetConfig().Region],
|
||||
instanceBlockDevices.Bsu.VolumeId)
|
||||
}
|
||||
}
|
||||
}
|
||||
state.Put("bsuvolumes", volumes)
|
||||
|
||||
if len(s.VolumeMapping) > 0 {
|
||||
ui.Say("Tagging BSU volumes...")
|
||||
|
||||
toTag := map[string][]oapi.ResourceTag{}
|
||||
for _, mapping := range s.VolumeMapping {
|
||||
if len(mapping.Tags) == 0 {
|
||||
ui.Say(fmt.Sprintf("No tags specified for volume on %s...", mapping.DeviceName))
|
||||
continue
|
||||
}
|
||||
|
||||
tags, err := mapping.Tags.OAPITags(s.Ctx, oapiconn.GetConfig().Region, state)
|
||||
if err != nil {
|
||||
err := fmt.Errorf("Error tagging device %s with %s", mapping.DeviceName, err)
|
||||
state.Put("error", err)
|
||||
ui.Error(err.Error())
|
||||
return multistep.ActionHalt
|
||||
}
|
||||
tags.Report(ui)
|
||||
|
||||
for _, v := range vm.BlockDeviceMappings {
|
||||
if v.DeviceName == mapping.DeviceName {
|
||||
toTag[v.Bsu.VolumeId] = tags
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
for volumeId, tags := range toTag {
|
||||
_, err := oapiconn.POST_CreateTags(oapi.CreateTagsRequest{
|
||||
ResourceIds: []string{volumeId},
|
||||
Tags: tags,
|
||||
})
|
||||
if err != nil {
|
||||
err := fmt.Errorf("Error tagging BSU Volume %s on %s: %s", volumeId, vm.VmId, err)
|
||||
state.Put("error", err)
|
||||
ui.Error(err.Error())
|
||||
return multistep.ActionHalt
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
return multistep.ActionContinue
|
||||
}
|
||||
|
||||
func (s *stepTagBSUVolumes) Cleanup(state multistep.StateBag) {
|
||||
// No cleanup...
|
||||
}
|
|
@ -2,6 +2,7 @@ package common
|
|||
|
||||
import (
|
||||
"fmt"
|
||||
"log"
|
||||
"strings"
|
||||
|
||||
"github.com/hashicorp/packer/template/interpolate"
|
||||
|
@ -50,9 +51,8 @@ func buildBlockDevices(b []BlockDevice) []*oapi.BlockDeviceMapping {
|
|||
mapping.VirtualDeviceName = blockDevice.VirtualName
|
||||
}
|
||||
} else {
|
||||
bsu := oapi.Bsu{
|
||||
DeleteOnVmDeletion: blockDevice.DeleteOnVmDeletion,
|
||||
}
|
||||
bsu := oapi.Bsu{}
|
||||
bsu.DeleteOnVmDeletion = &blockDevice.DeleteOnVmDeletion
|
||||
|
||||
if blockDevice.VolumeType != "" {
|
||||
bsu.VolumeType = blockDevice.VolumeType
|
||||
|
@ -97,7 +97,7 @@ func buildBlockDevicesImage(b []BlockDevice) []oapi.BlockDeviceMappingImage {
|
|||
}
|
||||
} else {
|
||||
bsu := oapi.BsuToCreate{
|
||||
DeleteOnVmDeletion: blockDevice.DeleteOnVmDeletion,
|
||||
DeleteOnVmDeletion: &blockDevice.DeleteOnVmDeletion,
|
||||
}
|
||||
|
||||
if blockDevice.VolumeType != "" {
|
||||
|
@ -126,6 +126,8 @@ func buildBlockDevicesImage(b []BlockDevice) []oapi.BlockDeviceMappingImage {
|
|||
}
|
||||
|
||||
func buildBlockDevicesVmCreation(b []BlockDevice) []oapi.BlockDeviceMappingVmCreation {
|
||||
log.Printf("[DEBUG] Launch Block Device %#v", b)
|
||||
|
||||
var blockDevices []oapi.BlockDeviceMappingVmCreation
|
||||
|
||||
for _, blockDevice := range b {
|
||||
|
@ -141,7 +143,7 @@ func buildBlockDevicesVmCreation(b []BlockDevice) []oapi.BlockDeviceMappingVmCre
|
|||
}
|
||||
} else {
|
||||
bsu := oapi.BsuToCreate{
|
||||
DeleteOnVmDeletion: blockDevice.DeleteOnVmDeletion,
|
||||
DeleteOnVmDeletion: &blockDevice.DeleteOnVmDeletion,
|
||||
}
|
||||
|
||||
if blockDevice.VolumeType != "" {
|
||||
|
|
|
@ -40,6 +40,7 @@ import (
|
|||
oracleocibuilder "github.com/hashicorp/packer/builder/oracle/oci"
|
||||
oscbsubuilder "github.com/hashicorp/packer/builder/osc/bsu"
|
||||
oscbsusurrogatebuilder "github.com/hashicorp/packer/builder/osc/bsusurrogate"
|
||||
oscbsuvolumebuilder "github.com/hashicorp/packer/builder/osc/bsuvolume"
|
||||
oscchrootbuilder "github.com/hashicorp/packer/builder/osc/chroot"
|
||||
parallelsisobuilder "github.com/hashicorp/packer/builder/parallels/iso"
|
||||
parallelspvmbuilder "github.com/hashicorp/packer/builder/parallels/pvm"
|
||||
|
@ -126,6 +127,7 @@ var Builders = map[string]packer.Builder{
|
|||
"oracle-oci": new(oracleocibuilder.Builder),
|
||||
"osc-bsu": new(oscbsubuilder.Builder),
|
||||
"osc-bsusurrogate": new(oscbsusurrogatebuilder.Builder),
|
||||
"osc-bsuvolume": new(oscbsuvolumebuilder.Builder),
|
||||
"osc-chroot": new(oscchrootbuilder.Builder),
|
||||
"parallels-iso": new(parallelsisobuilder.Builder),
|
||||
"parallels-pvm": new(parallelspvmbuilder.Builder),
|
||||
|
|
Loading…
Reference in New Issue