refactor: change bsuvolume builder to new SDK
This commit is contained in:
parent
abdb4bcfbf
commit
d813c3647d
|
@ -2,13 +2,9 @@
|
|||
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) {
|
||||
|
@ -23,22 +19,6 @@ func TestBuilderAcc_basic(t *testing.T) {
|
|||
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": [
|
||||
|
|
|
@ -8,7 +8,6 @@ import (
|
|||
"os"
|
||||
|
||||
"github.com/hashicorp/packer/template/interpolate"
|
||||
"github.com/outscale/osc-go/oapi"
|
||||
"github.com/outscale/osc-sdk-go/osc"
|
||||
)
|
||||
|
||||
|
@ -24,49 +23,6 @@ type AccessConfig struct {
|
|||
SkipValidation bool `mapstructure:"skip_region_validation"`
|
||||
SkipMetadataApiCheck bool `mapstructure:"skip_metadata_api_check"`
|
||||
Token string `mapstructure:"token"`
|
||||
clientConfig *oapi.Config
|
||||
|
||||
getOAPIConnection func() oapi.OAPIClient
|
||||
}
|
||||
|
||||
// Config returns a valid oapi.Config object for access to Outscale services, or
|
||||
// an error if the authentication and region couldn't be resolved
|
||||
func (c *AccessConfig) Config() (*oapi.Config, error) {
|
||||
if c.clientConfig != nil {
|
||||
return c.clientConfig, nil
|
||||
}
|
||||
|
||||
//Check env variables if access configuration is not set.
|
||||
|
||||
if c.AccessKey == "" {
|
||||
c.AccessKey = os.Getenv("OUTSCALE_ACCESSKEYID")
|
||||
}
|
||||
|
||||
if c.SecretKey == "" {
|
||||
c.SecretKey = os.Getenv("OUTSCALE_SECRETKEYID")
|
||||
}
|
||||
|
||||
if c.RawRegion == "" {
|
||||
c.RawRegion = os.Getenv("OUTSCALE_REGION")
|
||||
}
|
||||
|
||||
if c.CustomEndpointOAPI == "" {
|
||||
c.CustomEndpointOAPI = os.Getenv("OUTSCALE_OAPI_URL")
|
||||
}
|
||||
|
||||
if c.CustomEndpointOAPI == "" {
|
||||
c.CustomEndpointOAPI = "outscale.com/oapi/latest"
|
||||
}
|
||||
|
||||
config := &oapi.Config{
|
||||
AccessKey: c.AccessKey,
|
||||
SecretKey: c.SecretKey,
|
||||
Region: c.RawRegion,
|
||||
URL: c.CustomEndpointOAPI,
|
||||
Service: "api",
|
||||
}
|
||||
|
||||
return config, nil
|
||||
}
|
||||
|
||||
// NewOSCClient retrieves the Outscale OSC-SDK client
|
||||
|
@ -115,29 +71,10 @@ func (c *AccessConfig) NewOSCClientByRegion(region string) *osc.APIClient {
|
|||
DefaultHeader: make(map[string]string),
|
||||
UserAgent: "packer-osc",
|
||||
HTTPClient: skipClient,
|
||||
Debug: true,
|
||||
})
|
||||
}
|
||||
|
||||
func (c *AccessConfig) NewOAPIConnection() (oapi.OAPIClient, error) {
|
||||
if c.getOAPIConnection != nil {
|
||||
return c.getOAPIConnection(), nil
|
||||
}
|
||||
oapicfg, err := c.Config()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
skipClient := &http.Client{
|
||||
Transport: &http.Transport{
|
||||
TLSClientConfig: &tls.Config{InsecureSkipVerify: c.InsecureSkipTLSVerify},
|
||||
},
|
||||
}
|
||||
|
||||
oapiClient := oapi.NewClient(oapicfg, skipClient)
|
||||
|
||||
return oapiClient, nil
|
||||
}
|
||||
|
||||
func (c *AccessConfig) Prepare(ctx *interpolate.Context) []error {
|
||||
var errs []error
|
||||
|
||||
|
|
|
@ -2,31 +2,10 @@ package common
|
|||
|
||||
import (
|
||||
"testing"
|
||||
|
||||
"github.com/outscale/osc-go/oapi"
|
||||
)
|
||||
|
||||
type mockOAPIClient struct {
|
||||
oapi.OAPIClient
|
||||
}
|
||||
|
||||
func testAccessConfig() *AccessConfig {
|
||||
return &AccessConfig{
|
||||
getOAPIConnection: func() oapi.OAPIClient {
|
||||
return &mockOAPIClient{}
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
func (m *mockOAPIClient) POST_ReadRegions(oapi.ReadRegionsRequest) (*oapi.POST_ReadRegionsResponses, error) {
|
||||
return &oapi.POST_ReadRegionsResponses{
|
||||
OK: &oapi.ReadRegionsResponse{
|
||||
Regions: []oapi.Region{
|
||||
{RegionEndpoint: "us-west1", RegionName: "us-west1"},
|
||||
{RegionEndpoint: "us-east-1", RegionName: "us-east-1"},
|
||||
},
|
||||
},
|
||||
}, nil
|
||||
return &AccessConfig{}
|
||||
}
|
||||
|
||||
func TestAccessConfigPrepare_Region(t *testing.T) {
|
||||
|
|
|
@ -1,15 +1,15 @@
|
|||
package common
|
||||
|
||||
import (
|
||||
"crypto/tls"
|
||||
"context"
|
||||
"fmt"
|
||||
"log"
|
||||
"net/http"
|
||||
"sort"
|
||||
"strings"
|
||||
|
||||
"github.com/antihax/optional"
|
||||
"github.com/hashicorp/packer/packer"
|
||||
"github.com/outscale/osc-go/oapi"
|
||||
"github.com/outscale/osc-sdk-go/osc"
|
||||
)
|
||||
|
||||
// Artifact is an artifact implementation that contains built OMIs.
|
||||
|
@ -20,9 +20,6 @@ type Artifact struct {
|
|||
// BuilderId is the unique ID for the builder that created this OMI
|
||||
BuilderIdValue string
|
||||
|
||||
// OAPI connection for performing API stuff.
|
||||
Config *oapi.Config
|
||||
|
||||
// StateData should store data such as GeneratedData
|
||||
// to be shared with post-processors
|
||||
StateData map[string]interface{}
|
||||
|
@ -74,47 +71,36 @@ func (a *Artifact) State(name string) interface{} {
|
|||
func (a *Artifact) Destroy() error {
|
||||
errors := make([]error, 0)
|
||||
|
||||
config := a.State("accessConfig").(*AccessConfig)
|
||||
|
||||
for region, imageId := range a.Omis {
|
||||
log.Printf("Deregistering image ID (%s) from region (%s)", imageId, region)
|
||||
|
||||
newConfig := &oapi.Config{
|
||||
UserAgent: a.Config.UserAgent,
|
||||
AccessKey: a.Config.AccessKey,
|
||||
SecretKey: a.Config.SecretKey,
|
||||
Service: a.Config.Service,
|
||||
Region: region, //New region
|
||||
URL: a.Config.URL,
|
||||
}
|
||||
|
||||
log.Printf("[DEBUG] New Client config %+v", newConfig)
|
||||
|
||||
skipClient := &http.Client{
|
||||
Transport: &http.Transport{
|
||||
TLSClientConfig: &tls.Config{InsecureSkipVerify: true},
|
||||
},
|
||||
}
|
||||
|
||||
regionConn := oapi.NewClient(newConfig, skipClient)
|
||||
regionConn := config.NewOSCClientByRegion(region)
|
||||
|
||||
// Get image metadata
|
||||
imageResp, err := regionConn.POST_ReadImages(oapi.ReadImagesRequest{
|
||||
Filters: oapi.FiltersImage{
|
||||
ImageIds: []string{imageId},
|
||||
},
|
||||
imageResp, _, err := regionConn.ImageApi.ReadImages(context.Background(), &osc.ReadImagesOpts{
|
||||
ReadImagesRequest: optional.NewInterface(osc.ReadImagesRequest{
|
||||
Filters: osc.FiltersImage{
|
||||
ImageIds: []string{imageId},
|
||||
},
|
||||
}),
|
||||
})
|
||||
if err != nil {
|
||||
errors = append(errors, err)
|
||||
}
|
||||
if len(imageResp.OK.Images) == 0 {
|
||||
if len(imageResp.Images) == 0 {
|
||||
err := fmt.Errorf("Error retrieving details for OMI (%s), no images found", imageId)
|
||||
errors = append(errors, err)
|
||||
}
|
||||
|
||||
// Deregister ami
|
||||
input := oapi.DeleteImageRequest{
|
||||
input := osc.DeleteImageRequest{
|
||||
ImageId: imageId,
|
||||
}
|
||||
if _, err := regionConn.POST_DeleteImage(input); err != nil {
|
||||
if _, _, err := regionConn.ImageApi.DeleteImage(context.Background(), &osc.DeleteImageOpts{
|
||||
DeleteImageRequest: optional.NewInterface(input),
|
||||
}); err != nil {
|
||||
errors = append(errors, err)
|
||||
}
|
||||
|
||||
|
|
|
@ -5,9 +5,7 @@ import (
|
|||
"log"
|
||||
"strings"
|
||||
|
||||
"github.com/aws/aws-sdk-go/aws"
|
||||
"github.com/hashicorp/packer/template/interpolate"
|
||||
"github.com/outscale/osc-go/oapi"
|
||||
"github.com/outscale/osc-sdk-go/osc"
|
||||
)
|
||||
|
||||
|
@ -36,48 +34,6 @@ type LaunchBlockDevices struct {
|
|||
LaunchMappings []BlockDevice `mapstructure:"launch_block_device_mappings"`
|
||||
}
|
||||
|
||||
func buildBlockDevicesImage(b []BlockDevice) []oapi.BlockDeviceMappingImage {
|
||||
var blockDevices []oapi.BlockDeviceMappingImage
|
||||
|
||||
for _, blockDevice := range b {
|
||||
mapping := oapi.BlockDeviceMappingImage{
|
||||
DeviceName: blockDevice.DeviceName,
|
||||
}
|
||||
|
||||
if blockDevice.VirtualName != "" {
|
||||
if strings.HasPrefix(blockDevice.VirtualName, "ephemeral") {
|
||||
mapping.VirtualDeviceName = blockDevice.VirtualName
|
||||
}
|
||||
} else {
|
||||
bsu := oapi.BsuToCreate{
|
||||
DeleteOnVmDeletion: aws.Bool(blockDevice.DeleteOnVmDeletion),
|
||||
}
|
||||
|
||||
if blockDevice.VolumeType != "" {
|
||||
bsu.VolumeType = blockDevice.VolumeType
|
||||
}
|
||||
|
||||
if blockDevice.VolumeSize > 0 {
|
||||
bsu.VolumeSize = blockDevice.VolumeSize
|
||||
}
|
||||
|
||||
// IOPS is only valid for io1 type
|
||||
if blockDevice.VolumeType == "io1" {
|
||||
bsu.Iops = blockDevice.IOPS
|
||||
}
|
||||
|
||||
if blockDevice.SnapshotId != "" {
|
||||
bsu.SnapshotId = blockDevice.SnapshotId
|
||||
}
|
||||
|
||||
mapping.Bsu = bsu
|
||||
}
|
||||
|
||||
blockDevices = append(blockDevices, mapping)
|
||||
}
|
||||
return blockDevices
|
||||
}
|
||||
|
||||
func buildOscBlockDevicesImage(b []BlockDevice) []osc.BlockDeviceMappingImage {
|
||||
var blockDevices []osc.BlockDeviceMappingImage
|
||||
|
||||
|
@ -120,52 +76,6 @@ func buildOscBlockDevicesImage(b []BlockDevice) []osc.BlockDeviceMappingImage {
|
|||
return blockDevices
|
||||
}
|
||||
|
||||
func buildBlockDevicesVmCreation(b []BlockDevice) []oapi.BlockDeviceMappingVmCreation {
|
||||
log.Printf("[DEBUG] Launch Block Device %#v", b)
|
||||
|
||||
var blockDevices []oapi.BlockDeviceMappingVmCreation
|
||||
|
||||
for _, blockDevice := range b {
|
||||
mapping := oapi.BlockDeviceMappingVmCreation{
|
||||
DeviceName: blockDevice.DeviceName,
|
||||
}
|
||||
|
||||
if blockDevice.NoDevice {
|
||||
mapping.NoDevice = ""
|
||||
} else if blockDevice.VirtualName != "" {
|
||||
if strings.HasPrefix(blockDevice.VirtualName, "ephemeral") {
|
||||
mapping.VirtualDeviceName = blockDevice.VirtualName
|
||||
}
|
||||
} else {
|
||||
bsu := oapi.BsuToCreate{
|
||||
DeleteOnVmDeletion: aws.Bool(blockDevice.DeleteOnVmDeletion),
|
||||
}
|
||||
|
||||
if blockDevice.VolumeType != "" {
|
||||
bsu.VolumeType = blockDevice.VolumeType
|
||||
}
|
||||
|
||||
if blockDevice.VolumeSize > 0 {
|
||||
bsu.VolumeSize = blockDevice.VolumeSize
|
||||
}
|
||||
|
||||
// IOPS is only valid for io1 type
|
||||
if blockDevice.VolumeType == "io1" {
|
||||
bsu.Iops = blockDevice.IOPS
|
||||
}
|
||||
|
||||
if blockDevice.SnapshotId != "" {
|
||||
bsu.SnapshotId = blockDevice.SnapshotId
|
||||
}
|
||||
|
||||
mapping.Bsu = bsu
|
||||
}
|
||||
|
||||
blockDevices = append(blockDevices, mapping)
|
||||
}
|
||||
return blockDevices
|
||||
}
|
||||
|
||||
func buildOscBlockDevicesVmCreation(b []BlockDevice) []osc.BlockDeviceMappingVmCreation {
|
||||
log.Printf("[DEBUG] Launch Block Device %#v", b)
|
||||
|
||||
|
@ -234,18 +144,10 @@ func (b *BlockDevices) Prepare(ctx *interpolate.Context) (errs []error) {
|
|||
return errs
|
||||
}
|
||||
|
||||
func (b *OMIBlockDevices) BuildOMIDevices() []oapi.BlockDeviceMappingImage {
|
||||
return buildBlockDevicesImage(b.OMIMappings)
|
||||
}
|
||||
|
||||
func (b *OMIBlockDevices) BuildOscOMIDevices() []osc.BlockDeviceMappingImage {
|
||||
return buildOscBlockDevicesImage(b.OMIMappings)
|
||||
}
|
||||
|
||||
func (b *LaunchBlockDevices) BuildLaunchDevices() []oapi.BlockDeviceMappingVmCreation {
|
||||
return buildBlockDevicesVmCreation(b.LaunchMappings)
|
||||
}
|
||||
|
||||
func (b *LaunchBlockDevices) BuildOSCLaunchDevices() []osc.BlockDeviceMappingVmCreation {
|
||||
return buildOscBlockDevicesVmCreation(b.LaunchMappings)
|
||||
}
|
||||
|
|
|
@ -4,19 +4,13 @@ import (
|
|||
"reflect"
|
||||
"testing"
|
||||
|
||||
"github.com/outscale/osc-go/oapi"
|
||||
"github.com/outscale/osc-sdk-go/osc"
|
||||
)
|
||||
|
||||
func TestBlockDevice_LaunchDevices(t *testing.T) {
|
||||
tr := new(bool)
|
||||
f := new(bool)
|
||||
|
||||
*tr = true
|
||||
*f = false
|
||||
|
||||
cases := []struct {
|
||||
Config *BlockDevice
|
||||
Result oapi.BlockDeviceMappingVmCreation
|
||||
Result osc.BlockDeviceMappingVmCreation
|
||||
}{
|
||||
{
|
||||
Config: &BlockDevice{
|
||||
|
@ -27,13 +21,13 @@ func TestBlockDevice_LaunchDevices(t *testing.T) {
|
|||
DeleteOnVmDeletion: true,
|
||||
},
|
||||
|
||||
Result: oapi.BlockDeviceMappingVmCreation{
|
||||
Result: osc.BlockDeviceMappingVmCreation{
|
||||
DeviceName: "/dev/sdb",
|
||||
Bsu: oapi.BsuToCreate{
|
||||
Bsu: osc.BsuToCreate{
|
||||
SnapshotId: "snap-1234",
|
||||
VolumeType: "standard",
|
||||
VolumeSize: 8,
|
||||
DeleteOnVmDeletion: tr,
|
||||
DeleteOnVmDeletion: true,
|
||||
},
|
||||
},
|
||||
},
|
||||
|
@ -43,11 +37,11 @@ func TestBlockDevice_LaunchDevices(t *testing.T) {
|
|||
VolumeSize: 8,
|
||||
},
|
||||
|
||||
Result: oapi.BlockDeviceMappingVmCreation{
|
||||
Result: osc.BlockDeviceMappingVmCreation{
|
||||
DeviceName: "/dev/sdb",
|
||||
Bsu: oapi.BsuToCreate{
|
||||
Bsu: osc.BsuToCreate{
|
||||
VolumeSize: 8,
|
||||
DeleteOnVmDeletion: f,
|
||||
DeleteOnVmDeletion: false,
|
||||
},
|
||||
},
|
||||
},
|
||||
|
@ -60,12 +54,12 @@ func TestBlockDevice_LaunchDevices(t *testing.T) {
|
|||
IOPS: 1000,
|
||||
},
|
||||
|
||||
Result: oapi.BlockDeviceMappingVmCreation{
|
||||
Result: osc.BlockDeviceMappingVmCreation{
|
||||
DeviceName: "/dev/sdb",
|
||||
Bsu: oapi.BsuToCreate{
|
||||
Bsu: osc.BsuToCreate{
|
||||
VolumeType: "io1",
|
||||
VolumeSize: 8,
|
||||
DeleteOnVmDeletion: tr,
|
||||
DeleteOnVmDeletion: true,
|
||||
Iops: 1000,
|
||||
},
|
||||
},
|
||||
|
@ -78,12 +72,12 @@ func TestBlockDevice_LaunchDevices(t *testing.T) {
|
|||
DeleteOnVmDeletion: true,
|
||||
},
|
||||
|
||||
Result: oapi.BlockDeviceMappingVmCreation{
|
||||
Result: osc.BlockDeviceMappingVmCreation{
|
||||
DeviceName: "/dev/sdb",
|
||||
Bsu: oapi.BsuToCreate{
|
||||
Bsu: osc.BsuToCreate{
|
||||
VolumeType: "gp2",
|
||||
VolumeSize: 8,
|
||||
DeleteOnVmDeletion: tr,
|
||||
DeleteOnVmDeletion: true,
|
||||
},
|
||||
},
|
||||
},
|
||||
|
@ -95,12 +89,12 @@ func TestBlockDevice_LaunchDevices(t *testing.T) {
|
|||
DeleteOnVmDeletion: true,
|
||||
},
|
||||
|
||||
Result: oapi.BlockDeviceMappingVmCreation{
|
||||
Result: osc.BlockDeviceMappingVmCreation{
|
||||
DeviceName: "/dev/sdb",
|
||||
Bsu: oapi.BsuToCreate{
|
||||
Bsu: osc.BsuToCreate{
|
||||
VolumeType: "gp2",
|
||||
VolumeSize: 8,
|
||||
DeleteOnVmDeletion: tr,
|
||||
DeleteOnVmDeletion: true,
|
||||
},
|
||||
},
|
||||
},
|
||||
|
@ -111,11 +105,11 @@ func TestBlockDevice_LaunchDevices(t *testing.T) {
|
|||
DeleteOnVmDeletion: true,
|
||||
},
|
||||
|
||||
Result: oapi.BlockDeviceMappingVmCreation{
|
||||
Result: osc.BlockDeviceMappingVmCreation{
|
||||
DeviceName: "/dev/sdb",
|
||||
Bsu: oapi.BsuToCreate{
|
||||
Bsu: osc.BsuToCreate{
|
||||
VolumeType: "standard",
|
||||
DeleteOnVmDeletion: tr,
|
||||
DeleteOnVmDeletion: true,
|
||||
},
|
||||
},
|
||||
},
|
||||
|
@ -125,7 +119,7 @@ func TestBlockDevice_LaunchDevices(t *testing.T) {
|
|||
VirtualName: "ephemeral0",
|
||||
},
|
||||
|
||||
Result: oapi.BlockDeviceMappingVmCreation{
|
||||
Result: osc.BlockDeviceMappingVmCreation{
|
||||
DeviceName: "/dev/sdb",
|
||||
VirtualDeviceName: "ephemeral0",
|
||||
},
|
||||
|
@ -136,7 +130,7 @@ func TestBlockDevice_LaunchDevices(t *testing.T) {
|
|||
NoDevice: true,
|
||||
},
|
||||
|
||||
Result: oapi.BlockDeviceMappingVmCreation{
|
||||
Result: osc.BlockDeviceMappingVmCreation{
|
||||
DeviceName: "/dev/sdb",
|
||||
NoDevice: "",
|
||||
},
|
||||
|
@ -149,9 +143,9 @@ func TestBlockDevice_LaunchDevices(t *testing.T) {
|
|||
LaunchMappings: []BlockDevice{*tc.Config},
|
||||
}
|
||||
|
||||
expected := []oapi.BlockDeviceMappingVmCreation{tc.Result}
|
||||
expected := []osc.BlockDeviceMappingVmCreation{tc.Result}
|
||||
|
||||
launchResults := launchBlockDevices.BuildLaunchDevices()
|
||||
launchResults := launchBlockDevices.BuildOSCLaunchDevices()
|
||||
if !reflect.DeepEqual(expected, launchResults) {
|
||||
t.Fatalf("Bad block device, \nexpected: %#v\n\ngot: %#v",
|
||||
expected, launchResults)
|
||||
|
@ -160,15 +154,9 @@ func TestBlockDevice_LaunchDevices(t *testing.T) {
|
|||
}
|
||||
|
||||
func TestBlockDevice_OMI(t *testing.T) {
|
||||
tr := new(bool)
|
||||
f := new(bool)
|
||||
|
||||
*tr = true
|
||||
*f = false
|
||||
|
||||
cases := []struct {
|
||||
Config *BlockDevice
|
||||
Result oapi.BlockDeviceMappingImage
|
||||
Result osc.BlockDeviceMappingImage
|
||||
}{
|
||||
{
|
||||
Config: &BlockDevice{
|
||||
|
@ -179,27 +167,28 @@ func TestBlockDevice_OMI(t *testing.T) {
|
|||
DeleteOnVmDeletion: true,
|
||||
},
|
||||
|
||||
Result: oapi.BlockDeviceMappingImage{
|
||||
Result: osc.BlockDeviceMappingImage{
|
||||
DeviceName: "/dev/sdb",
|
||||
Bsu: oapi.BsuToCreate{
|
||||
Bsu: osc.BsuToCreate{
|
||||
SnapshotId: "snap-1234",
|
||||
VolumeType: "standard",
|
||||
VolumeSize: 8,
|
||||
DeleteOnVmDeletion: tr,
|
||||
DeleteOnVmDeletion: true,
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
Config: &BlockDevice{
|
||||
DeviceName: "/dev/sdb",
|
||||
VolumeSize: 8,
|
||||
DeviceName: "/dev/sdb",
|
||||
VolumeSize: 8,
|
||||
DeleteOnVmDeletion: true,
|
||||
},
|
||||
|
||||
Result: oapi.BlockDeviceMappingImage{
|
||||
Result: osc.BlockDeviceMappingImage{
|
||||
DeviceName: "/dev/sdb",
|
||||
Bsu: oapi.BsuToCreate{
|
||||
Bsu: osc.BsuToCreate{
|
||||
VolumeSize: 8,
|
||||
DeleteOnVmDeletion: f,
|
||||
DeleteOnVmDeletion: true,
|
||||
},
|
||||
},
|
||||
},
|
||||
|
@ -212,12 +201,12 @@ func TestBlockDevice_OMI(t *testing.T) {
|
|||
IOPS: 1000,
|
||||
},
|
||||
|
||||
Result: oapi.BlockDeviceMappingImage{
|
||||
Result: osc.BlockDeviceMappingImage{
|
||||
DeviceName: "/dev/sdb",
|
||||
Bsu: oapi.BsuToCreate{
|
||||
Bsu: osc.BsuToCreate{
|
||||
VolumeType: "io1",
|
||||
VolumeSize: 8,
|
||||
DeleteOnVmDeletion: tr,
|
||||
DeleteOnVmDeletion: true,
|
||||
Iops: 1000,
|
||||
},
|
||||
},
|
||||
|
@ -230,12 +219,12 @@ func TestBlockDevice_OMI(t *testing.T) {
|
|||
DeleteOnVmDeletion: true,
|
||||
},
|
||||
|
||||
Result: oapi.BlockDeviceMappingImage{
|
||||
Result: osc.BlockDeviceMappingImage{
|
||||
DeviceName: "/dev/sdb",
|
||||
Bsu: oapi.BsuToCreate{
|
||||
Bsu: osc.BsuToCreate{
|
||||
VolumeType: "gp2",
|
||||
VolumeSize: 8,
|
||||
DeleteOnVmDeletion: tr,
|
||||
DeleteOnVmDeletion: true,
|
||||
},
|
||||
},
|
||||
},
|
||||
|
@ -247,12 +236,12 @@ func TestBlockDevice_OMI(t *testing.T) {
|
|||
DeleteOnVmDeletion: true,
|
||||
},
|
||||
|
||||
Result: oapi.BlockDeviceMappingImage{
|
||||
Result: osc.BlockDeviceMappingImage{
|
||||
DeviceName: "/dev/sdb",
|
||||
Bsu: oapi.BsuToCreate{
|
||||
Bsu: osc.BsuToCreate{
|
||||
VolumeType: "gp2",
|
||||
VolumeSize: 8,
|
||||
DeleteOnVmDeletion: tr,
|
||||
DeleteOnVmDeletion: true,
|
||||
},
|
||||
},
|
||||
},
|
||||
|
@ -263,11 +252,11 @@ func TestBlockDevice_OMI(t *testing.T) {
|
|||
DeleteOnVmDeletion: true,
|
||||
},
|
||||
|
||||
Result: oapi.BlockDeviceMappingImage{
|
||||
Result: osc.BlockDeviceMappingImage{
|
||||
DeviceName: "/dev/sdb",
|
||||
Bsu: oapi.BsuToCreate{
|
||||
Bsu: osc.BsuToCreate{
|
||||
VolumeType: "standard",
|
||||
DeleteOnVmDeletion: tr,
|
||||
DeleteOnVmDeletion: true,
|
||||
},
|
||||
},
|
||||
},
|
||||
|
@ -277,24 +266,24 @@ func TestBlockDevice_OMI(t *testing.T) {
|
|||
VirtualName: "ephemeral0",
|
||||
},
|
||||
|
||||
Result: oapi.BlockDeviceMappingImage{
|
||||
Result: osc.BlockDeviceMappingImage{
|
||||
DeviceName: "/dev/sdb",
|
||||
VirtualDeviceName: "ephemeral0",
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
for _, tc := range cases {
|
||||
for i, tc := range cases {
|
||||
omiBlockDevices := OMIBlockDevices{
|
||||
OMIMappings: []BlockDevice{*tc.Config},
|
||||
}
|
||||
|
||||
expected := []oapi.BlockDeviceMappingImage{tc.Result}
|
||||
expected := []osc.BlockDeviceMappingImage{tc.Result}
|
||||
|
||||
omiResults := omiBlockDevices.BuildOMIDevices()
|
||||
omiResults := omiBlockDevices.BuildOscOMIDevices()
|
||||
if !reflect.DeepEqual(expected, omiResults) {
|
||||
t.Fatalf("Bad block device, \nexpected: %+#v\n\ngot: %+#v",
|
||||
expected, omiResults)
|
||||
t.Fatalf("%d - Bad block device, \nexpected: %+#v\n\ngot: %+#v",
|
||||
i, expected, omiResults)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -4,36 +4,9 @@ import (
|
|||
"log"
|
||||
"strconv"
|
||||
|
||||
"github.com/outscale/osc-go/oapi"
|
||||
"github.com/outscale/osc-sdk-go/osc"
|
||||
)
|
||||
|
||||
func buildNetFilters(input map[string]string) oapi.FiltersNet {
|
||||
var filters oapi.FiltersNet
|
||||
for k, v := range input {
|
||||
filterValue := []string{v}
|
||||
switch name := k; name {
|
||||
case "ip-range":
|
||||
filters.IpRanges = filterValue
|
||||
case "dhcp-options-set-id":
|
||||
filters.DhcpOptionsSetIds = filterValue
|
||||
case "is-default":
|
||||
if isDefault, err := strconv.ParseBool(v); err == nil {
|
||||
filters.IsDefault = isDefault
|
||||
}
|
||||
case "state":
|
||||
filters.States = filterValue
|
||||
case "tag-key":
|
||||
filters.TagKeys = filterValue
|
||||
case "tag-value":
|
||||
filters.TagValues = filterValue
|
||||
default:
|
||||
log.Printf("[Debug] Unknown Filter Name: %s.", name)
|
||||
}
|
||||
}
|
||||
return filters
|
||||
}
|
||||
|
||||
func buildOscNetFilters(input map[string]string) osc.FiltersNet {
|
||||
var filters osc.FiltersNet
|
||||
for k, v := range input {
|
||||
|
@ -60,32 +33,6 @@ func buildOscNetFilters(input map[string]string) osc.FiltersNet {
|
|||
return filters
|
||||
}
|
||||
|
||||
func buildSubnetFilters(input map[string]string) oapi.FiltersSubnet {
|
||||
var filters oapi.FiltersSubnet
|
||||
for k, v := range input {
|
||||
filterValue := []string{v}
|
||||
switch name := k; name {
|
||||
case "available-ips-counts":
|
||||
if ipCount, err := strconv.Atoi(v); err == nil {
|
||||
filters.AvailableIpsCounts = []int64{int64(ipCount)}
|
||||
}
|
||||
case "ip-ranges":
|
||||
filters.IpRanges = filterValue
|
||||
case "net-ids":
|
||||
filters.NetIds = filterValue
|
||||
case "states":
|
||||
filters.States = filterValue
|
||||
case "subnet-ids":
|
||||
filters.SubnetIds = filterValue
|
||||
case "sub-region-names":
|
||||
filters.SubregionNames = filterValue
|
||||
default:
|
||||
log.Printf("[Debug] Unknown Filter Name: %s.", name)
|
||||
}
|
||||
}
|
||||
return filters
|
||||
}
|
||||
|
||||
func buildOscSubnetFilters(input map[string]string) osc.FiltersSubnet {
|
||||
var filters osc.FiltersSubnet
|
||||
for k, v := range input {
|
||||
|
@ -112,38 +59,6 @@ func buildOscSubnetFilters(input map[string]string) osc.FiltersSubnet {
|
|||
return filters
|
||||
}
|
||||
|
||||
func buildOMIFilters(input map[string]string) oapi.FiltersImage {
|
||||
var filters oapi.FiltersImage
|
||||
for k, v := range input {
|
||||
filterValue := []string{v}
|
||||
|
||||
switch name := k; name {
|
||||
case "account-alias":
|
||||
filters.AccountAliases = filterValue
|
||||
case "account-id":
|
||||
filters.AccountIds = filterValue
|
||||
case "architecture":
|
||||
filters.Architectures = filterValue
|
||||
case "image-id":
|
||||
filters.ImageIds = filterValue
|
||||
case "image-name":
|
||||
filters.ImageNames = filterValue
|
||||
case "image-type":
|
||||
filters.ImageTypes = filterValue
|
||||
case "virtualization-type":
|
||||
filters.VirtualizationTypes = filterValue
|
||||
case "root-device-type":
|
||||
filters.RootDeviceTypes = filterValue
|
||||
case "block-device-mapping-volume-type":
|
||||
filters.BlockDeviceMappingVolumeType = filterValue
|
||||
//Some params are missing.
|
||||
default:
|
||||
log.Printf("[WARN] Unknown Filter Name: %s.", name)
|
||||
}
|
||||
}
|
||||
return filters
|
||||
}
|
||||
|
||||
func buildOSCOMIFilters(input map[string]string) osc.FiltersImage {
|
||||
var filters osc.FiltersImage
|
||||
for k, v := range input {
|
||||
|
|
|
@ -5,14 +5,14 @@ import (
|
|||
"testing"
|
||||
|
||||
"github.com/hashicorp/packer/helper/multistep"
|
||||
"github.com/outscale/osc-go/oapi"
|
||||
"github.com/outscale/osc-sdk-go/osc"
|
||||
)
|
||||
|
||||
func testImage() oapi.Image {
|
||||
return oapi.Image{
|
||||
func testImage() osc.Image {
|
||||
return osc.Image{
|
||||
ImageId: "ami-abcd1234",
|
||||
ImageName: "ami_test_name",
|
||||
Tags: []oapi.ResourceTag{
|
||||
Tags: []osc.ResourceTag{
|
||||
{
|
||||
Key: "key-1",
|
||||
Value: "value-1",
|
||||
|
|
|
@ -36,17 +36,13 @@ func TestOMIConfigPrepare_regions(t *testing.T) {
|
|||
c.OMIRegions = nil
|
||||
|
||||
var errs []error
|
||||
var err error
|
||||
accessConf := testAccessConfig()
|
||||
mockConn := &mockOAPIClient{}
|
||||
if errs = c.prepareRegions(accessConf); len(errs) > 0 {
|
||||
t.Fatalf("shouldn't have err: %#v", errs)
|
||||
}
|
||||
|
||||
c.OMIRegions, err = listOAPIRegions(mockConn)
|
||||
if err != nil {
|
||||
t.Fatalf("shouldn't have err: %s", err.Error())
|
||||
}
|
||||
c.OMIRegions = []string{"us-east-1", "us-west-1"}
|
||||
|
||||
if errs = c.prepareRegions(accessConf); len(errs) > 0 {
|
||||
t.Fatalf("shouldn't have err: %#v", errs)
|
||||
}
|
||||
|
|
|
@ -1,19 +1,23 @@
|
|||
package common
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
|
||||
"github.com/outscale/osc-go/oapi"
|
||||
"github.com/antihax/optional"
|
||||
"github.com/outscale/osc-sdk-go/osc"
|
||||
)
|
||||
|
||||
func listOAPIRegions(oapiconn oapi.OAPIClient) ([]string, error) {
|
||||
func listOSCRegions(oscconn *osc.RegionApiService) ([]string, error) {
|
||||
var regions []string
|
||||
resp, err := oapiconn.POST_ReadRegions(oapi.ReadRegionsRequest{})
|
||||
if resp.OK == nil || err != nil {
|
||||
resp, _, err := oscconn.ReadRegions(context.Background(), &osc.ReadRegionsOpts{
|
||||
ReadRegionsRequest: optional.NewInterface(osc.ReadRegionsRequest{}),
|
||||
})
|
||||
if err != nil {
|
||||
return []string{}, err
|
||||
}
|
||||
|
||||
resultRegions := resp.OK
|
||||
resultRegions := resp
|
||||
|
||||
for _, region := range resultRegions.Regions {
|
||||
regions = append(regions, region.RegionName)
|
||||
|
@ -25,12 +29,9 @@ func listOAPIRegions(oapiconn oapi.OAPIClient) ([]string, error) {
|
|||
// ValidateRegion returns true if the supplied region is a valid Outscale
|
||||
// region and false if it's not.
|
||||
func (c *AccessConfig) ValidateRegion(regions ...string) error {
|
||||
oapiconn, err := c.NewOAPIConnection()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
oscconn := c.NewOSCClient()
|
||||
|
||||
validRegions, err := listOAPIRegions(oapiconn)
|
||||
validRegions, err := listOSCRegions(oscconn.RegionApi)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
|
|
@ -10,14 +10,9 @@ import (
|
|||
|
||||
"github.com/antihax/optional"
|
||||
"github.com/hashicorp/packer/helper/multistep"
|
||||
"github.com/outscale/osc-go/oapi"
|
||||
"github.com/outscale/osc-sdk-go/osc"
|
||||
)
|
||||
|
||||
type oapiDescriber interface {
|
||||
POST_ReadVms(oapi.ReadVmsRequest) (*oapi.POST_ReadVmsResponses, error)
|
||||
}
|
||||
|
||||
type oscDescriber interface {
|
||||
ReadVms(ctx context.Context, localVarOptionals *osc.ReadVmsOpts) (osc.ReadVmsResponse, *http.Response, error)
|
||||
}
|
||||
|
@ -29,7 +24,7 @@ var (
|
|||
|
||||
// SSHHost returns a function that can be given to the SSH communicator
|
||||
// for determining the SSH address based on the vm DNS name.
|
||||
func SSHHost(e oapiDescriber, sshInterface string) func(multistep.StateBag) (string, error) {
|
||||
func SSHHost(e oscDescriber, sshInterface string) func(multistep.StateBag) (string, error) {
|
||||
return func(state multistep.StateBag) (string, error) {
|
||||
const tries = 2
|
||||
// <= with current structure to check result of describing `tries` times
|
||||
|
@ -72,20 +67,22 @@ func SSHHost(e oapiDescriber, sshInterface string) func(multistep.StateBag) (str
|
|||
return host, nil
|
||||
}
|
||||
|
||||
r, err := e.POST_ReadVms(oapi.ReadVmsRequest{
|
||||
Filters: oapi.FiltersVm{
|
||||
VmIds: []string{i.VmId},
|
||||
},
|
||||
r, _, err := e.ReadVms(context.Background(), &osc.ReadVmsOpts{
|
||||
ReadVmsRequest: optional.NewInterface(osc.ReadVmsRequest{
|
||||
Filters: osc.FiltersVm{
|
||||
VmIds: []string{i.VmId},
|
||||
},
|
||||
}),
|
||||
})
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
|
||||
if len(r.OK.Vms) == 0 {
|
||||
if len(r.Vms) == 0 {
|
||||
return "", fmt.Errorf("vm not found: %s", i.VmId)
|
||||
}
|
||||
|
||||
state.Put("vm", r.OK.Vms[0])
|
||||
state.Put("vm", r.Vms[0])
|
||||
time.Sleep(sshHostSleepDuration)
|
||||
}
|
||||
|
||||
|
|
|
@ -7,26 +7,11 @@ import (
|
|||
|
||||
"github.com/antihax/optional"
|
||||
"github.com/hashicorp/packer/common"
|
||||
"github.com/outscale/osc-go/oapi"
|
||||
"github.com/outscale/osc-sdk-go/osc"
|
||||
)
|
||||
|
||||
type stateRefreshFunc func() (string, error)
|
||||
|
||||
func waitForSecurityGroup(conn *oapi.Client, securityGroupID string) error {
|
||||
errCh := make(chan error, 1)
|
||||
go waitForState(errCh, "exists", securityGroupWaitFunc(conn, securityGroupID))
|
||||
err := <-errCh
|
||||
return err
|
||||
}
|
||||
|
||||
func waitUntilForVmRunning(conn *oapi.Client, vmID string) error {
|
||||
errCh := make(chan error, 1)
|
||||
go waitForState(errCh, "running", waitUntilVmStateFunc(conn, vmID))
|
||||
err := <-errCh
|
||||
return err
|
||||
}
|
||||
|
||||
func waitUntilForOscVmRunning(conn *osc.APIClient, vmID string) error {
|
||||
errCh := make(chan error, 1)
|
||||
go waitForState(errCh, "running", waitUntilOscVmStateFunc(conn, vmID))
|
||||
|
@ -34,75 +19,51 @@ func waitUntilForOscVmRunning(conn *osc.APIClient, vmID string) error {
|
|||
return err
|
||||
}
|
||||
|
||||
func waitUntilVmDeleted(conn *oapi.Client, vmID string) error {
|
||||
errCh := make(chan error, 1)
|
||||
go waitForState(errCh, "terminated", waitUntilVmStateFunc(conn, vmID))
|
||||
return <-errCh
|
||||
}
|
||||
|
||||
func waitUntilOscVmDeleted(conn *osc.APIClient, vmID string) error {
|
||||
errCh := make(chan error, 1)
|
||||
go waitForState(errCh, "terminated", waitUntilOscVmStateFunc(conn, vmID))
|
||||
return <-errCh
|
||||
}
|
||||
|
||||
func waitUntilVmStopped(conn *oapi.Client, vmID string) error {
|
||||
errCh := make(chan error, 1)
|
||||
go waitForState(errCh, "stopped", waitUntilVmStateFunc(conn, vmID))
|
||||
return <-errCh
|
||||
}
|
||||
|
||||
func waitUntilOscVmStopped(conn *osc.APIClient, vmID string) error {
|
||||
errCh := make(chan error, 1)
|
||||
go waitForState(errCh, "stopped", waitUntilOscVmStateFunc(conn, vmID))
|
||||
return <-errCh
|
||||
}
|
||||
|
||||
func WaitUntilSnapshotCompleted(conn *oapi.Client, id string) error {
|
||||
errCh := make(chan error, 1)
|
||||
go waitForState(errCh, "completed", waitUntilSnapshotStateFunc(conn, id))
|
||||
return <-errCh
|
||||
}
|
||||
|
||||
func WaitUntilOscSnapshotCompleted(conn *osc.APIClient, id string) error {
|
||||
errCh := make(chan error, 1)
|
||||
go waitForState(errCh, "completed", waitUntilOscSnapshotStateFunc(conn, id))
|
||||
return <-errCh
|
||||
}
|
||||
|
||||
func WaitUntilImageAvailable(conn *oapi.Client, imageID string) error {
|
||||
errCh := make(chan error, 1)
|
||||
go waitForState(errCh, "available", waitUntilImageStateFunc(conn, imageID))
|
||||
return <-errCh
|
||||
}
|
||||
|
||||
func WaitUntilOscImageAvailable(conn *osc.APIClient, imageID string) error {
|
||||
errCh := make(chan error, 1)
|
||||
go waitForState(errCh, "available", waitUntilOscImageStateFunc(conn, imageID))
|
||||
return <-errCh
|
||||
}
|
||||
|
||||
func WaitUntilVolumeAvailable(conn *oapi.Client, volumeID string) error {
|
||||
func WaitUntilOscVolumeAvailable(conn *osc.APIClient, volumeID string) error {
|
||||
errCh := make(chan error, 1)
|
||||
go waitForState(errCh, "available", volumeWaitFunc(conn, volumeID))
|
||||
go waitForState(errCh, "available", volumeOscWaitFunc(conn, volumeID))
|
||||
return <-errCh
|
||||
}
|
||||
|
||||
func WaitUntilVolumeIsLinked(conn *oapi.Client, volumeID string) error {
|
||||
func WaitUntilOscVolumeIsLinked(conn *osc.APIClient, volumeID string) error {
|
||||
errCh := make(chan error, 1)
|
||||
go waitForState(errCh, "attached", waitUntilVolumeLinkedStateFunc(conn, volumeID))
|
||||
go waitForState(errCh, "attached", waitUntilOscVolumeLinkedStateFunc(conn, volumeID))
|
||||
return <-errCh
|
||||
}
|
||||
|
||||
func WaitUntilVolumeIsUnlinked(conn *oapi.Client, volumeID string) error {
|
||||
func WaitUntilOscVolumeIsUnlinked(conn *osc.APIClient, volumeID string) error {
|
||||
errCh := make(chan error, 1)
|
||||
go waitForState(errCh, "dettached", waitUntilVolumeUnLinkedStateFunc(conn, volumeID))
|
||||
go waitForState(errCh, "dettached", waitUntilOscVolumeUnLinkedStateFunc(conn, volumeID))
|
||||
return <-errCh
|
||||
}
|
||||
|
||||
func WaitUntilSnapshotDone(conn *oapi.Client, snapshotID string) error {
|
||||
func WaitUntilOscSnapshotDone(conn *osc.APIClient, snapshotID string) error {
|
||||
errCh := make(chan error, 1)
|
||||
go waitForState(errCh, "completed", waitUntilSnapshotDoneStateFunc(conn, snapshotID))
|
||||
go waitForState(errCh, "completed", waitUntilOscSnapshotDoneStateFunc(conn, snapshotID))
|
||||
return <-errCh
|
||||
}
|
||||
|
||||
|
@ -120,33 +81,6 @@ func waitForState(errCh chan<- error, target string, refresh stateRefreshFunc) e
|
|||
return err
|
||||
}
|
||||
|
||||
func waitUntilVmStateFunc(conn *oapi.Client, id string) stateRefreshFunc {
|
||||
return func() (string, error) {
|
||||
log.Printf("[Debug] Retrieving state for VM with id %s", id)
|
||||
resp, err := conn.POST_ReadVms(oapi.ReadVmsRequest{
|
||||
Filters: oapi.FiltersVm{
|
||||
VmIds: []string{id},
|
||||
},
|
||||
})
|
||||
|
||||
log.Printf("[Debug] Read Response %+v", resp.OK)
|
||||
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
|
||||
if resp.OK == nil {
|
||||
return "", fmt.Errorf("Vm with ID %s not Found", id)
|
||||
}
|
||||
|
||||
if len(resp.OK.Vms) == 0 {
|
||||
return "pending", nil
|
||||
}
|
||||
|
||||
return resp.OK.Vms[0].State, nil
|
||||
}
|
||||
}
|
||||
|
||||
func waitUntilOscVmStateFunc(conn *osc.APIClient, id string) stateRefreshFunc {
|
||||
return func() (string, error) {
|
||||
log.Printf("[Debug] Retrieving state for VM with id %s", id)
|
||||
|
@ -158,8 +92,6 @@ func waitUntilOscVmStateFunc(conn *osc.APIClient, id string) stateRefreshFunc {
|
|||
}),
|
||||
})
|
||||
|
||||
log.Printf("[Debug] Read Response %+v", resp)
|
||||
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
|
@ -177,61 +109,53 @@ func waitUntilOscVmStateFunc(conn *osc.APIClient, id string) stateRefreshFunc {
|
|||
}
|
||||
}
|
||||
|
||||
func waitUntilVolumeLinkedStateFunc(conn *oapi.Client, id string) stateRefreshFunc {
|
||||
func waitUntilOscVolumeLinkedStateFunc(conn *osc.APIClient, id string) stateRefreshFunc {
|
||||
return func() (string, error) {
|
||||
log.Printf("[Debug] Check if volume with id %s exists", id)
|
||||
resp, err := conn.POST_ReadVolumes(oapi.ReadVolumesRequest{
|
||||
Filters: oapi.FiltersVolume{
|
||||
VolumeIds: []string{id},
|
||||
},
|
||||
resp, _, err := conn.VolumeApi.ReadVolumes(context.Background(), &osc.ReadVolumesOpts{
|
||||
ReadVolumesRequest: optional.NewInterface(osc.ReadVolumesRequest{
|
||||
Filters: osc.FiltersVolume{
|
||||
VolumeIds: []string{id},
|
||||
},
|
||||
}),
|
||||
})
|
||||
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
|
||||
if resp.OK == nil {
|
||||
return "", fmt.Errorf("Vm with ID %s. Not Found", id)
|
||||
}
|
||||
|
||||
log.Printf("[Debug] Read Response %+v", resp.OK)
|
||||
|
||||
if len(resp.OK.Volumes) == 0 {
|
||||
if len(resp.Volumes) == 0 {
|
||||
return "pending", nil
|
||||
}
|
||||
|
||||
if len(resp.OK.Volumes[0].LinkedVolumes) == 0 {
|
||||
if len(resp.Volumes[0].LinkedVolumes) == 0 {
|
||||
return "pending", nil
|
||||
}
|
||||
|
||||
return resp.OK.Volumes[0].LinkedVolumes[0].State, nil
|
||||
return resp.Volumes[0].LinkedVolumes[0].State, nil
|
||||
}
|
||||
}
|
||||
|
||||
func waitUntilVolumeUnLinkedStateFunc(conn *oapi.Client, id string) stateRefreshFunc {
|
||||
func waitUntilOscVolumeUnLinkedStateFunc(conn *osc.APIClient, id string) stateRefreshFunc {
|
||||
return func() (string, error) {
|
||||
log.Printf("[Debug] Check if volume with id %s exists", id)
|
||||
resp, err := conn.POST_ReadVolumes(oapi.ReadVolumesRequest{
|
||||
Filters: oapi.FiltersVolume{
|
||||
VolumeIds: []string{id},
|
||||
},
|
||||
resp, _, err := conn.VolumeApi.ReadVolumes(context.Background(), &osc.ReadVolumesOpts{
|
||||
ReadVolumesRequest: optional.NewInterface(osc.ReadVolumesRequest{
|
||||
Filters: osc.FiltersVolume{
|
||||
VolumeIds: []string{id},
|
||||
},
|
||||
}),
|
||||
})
|
||||
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
|
||||
if resp.OK == nil {
|
||||
return "", fmt.Errorf("Vm with ID %s. Not Found", id)
|
||||
}
|
||||
|
||||
log.Printf("[Debug] Read Response %+v", resp.OK)
|
||||
|
||||
if len(resp.OK.Volumes) == 0 {
|
||||
if len(resp.Volumes) == 0 {
|
||||
return "pending", nil
|
||||
}
|
||||
|
||||
if len(resp.OK.Volumes[0].LinkedVolumes) == 0 {
|
||||
if len(resp.Volumes[0].LinkedVolumes) == 0 {
|
||||
return "dettached", nil
|
||||
}
|
||||
|
||||
|
@ -239,33 +163,6 @@ func waitUntilVolumeUnLinkedStateFunc(conn *oapi.Client, id string) stateRefresh
|
|||
}
|
||||
}
|
||||
|
||||
func waitUntilSnapshotStateFunc(conn *oapi.Client, id string) stateRefreshFunc {
|
||||
return func() (string, error) {
|
||||
log.Printf("[Debug] Check if Snapshot with id %s exists", id)
|
||||
resp, err := conn.POST_ReadSnapshots(oapi.ReadSnapshotsRequest{
|
||||
Filters: oapi.FiltersSnapshot{
|
||||
SnapshotIds: []string{id},
|
||||
},
|
||||
})
|
||||
|
||||
log.Printf("[Debug] Read Response %+v", resp.OK)
|
||||
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
|
||||
if resp.OK == nil {
|
||||
return "", fmt.Errorf("Vm with ID %s. Not Found", id)
|
||||
}
|
||||
|
||||
if len(resp.OK.Snapshots) == 0 {
|
||||
return "pending", nil
|
||||
}
|
||||
|
||||
return resp.OK.Snapshots[0].State, nil
|
||||
}
|
||||
}
|
||||
|
||||
func waitUntilOscSnapshotStateFunc(conn *osc.APIClient, id string) stateRefreshFunc {
|
||||
return func() (string, error) {
|
||||
log.Printf("[Debug] Check if Snapshot with id %s exists", id)
|
||||
|
@ -277,17 +174,10 @@ func waitUntilOscSnapshotStateFunc(conn *osc.APIClient, id string) stateRefreshF
|
|||
}),
|
||||
})
|
||||
|
||||
log.Printf("[Debug] Read Response %+v", resp)
|
||||
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
|
||||
//TODO: check if needed
|
||||
// if resp.OK == nil {
|
||||
// return "", fmt.Errorf("Vm with ID %s. Not Found", id)
|
||||
// }
|
||||
|
||||
if len(resp.Snapshots) == 0 {
|
||||
return "pending", nil
|
||||
}
|
||||
|
@ -296,37 +186,6 @@ func waitUntilOscSnapshotStateFunc(conn *osc.APIClient, id string) stateRefreshF
|
|||
}
|
||||
}
|
||||
|
||||
func waitUntilImageStateFunc(conn *oapi.Client, id string) stateRefreshFunc {
|
||||
return func() (string, error) {
|
||||
log.Printf("[Debug] Check if Image with id %s exists", id)
|
||||
resp, err := conn.POST_ReadImages(oapi.ReadImagesRequest{
|
||||
Filters: oapi.FiltersImage{
|
||||
ImageIds: []string{id},
|
||||
},
|
||||
})
|
||||
|
||||
log.Printf("[Debug] Read Response %+v", resp.OK)
|
||||
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
|
||||
if resp.OK == nil {
|
||||
return "", fmt.Errorf("Vm with ID %s. Not Found", id)
|
||||
}
|
||||
|
||||
if len(resp.OK.Images) == 0 {
|
||||
return "pending", nil
|
||||
}
|
||||
|
||||
if resp.OK.Images[0].State == "failed" {
|
||||
return resp.OK.Images[0].State, fmt.Errorf("Image (%s) creation is failed", id)
|
||||
}
|
||||
|
||||
return resp.OK.Images[0].State, nil
|
||||
}
|
||||
}
|
||||
|
||||
func waitUntilOscImageStateFunc(conn *osc.APIClient, id string) stateRefreshFunc {
|
||||
return func() (string, error) {
|
||||
log.Printf("[Debug] Check if Image with id %s exists", id)
|
||||
|
@ -338,17 +197,10 @@ func waitUntilOscImageStateFunc(conn *osc.APIClient, id string) stateRefreshFunc
|
|||
}),
|
||||
})
|
||||
|
||||
log.Printf("[Debug] Read Response %+v", resp)
|
||||
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
|
||||
//TODO: check if needed
|
||||
// if resp.OK == nil {
|
||||
// return "", fmt.Errorf("Vm with ID %s. Not Found", id)
|
||||
// }
|
||||
|
||||
if len(resp.Images) == 0 {
|
||||
return "pending", nil
|
||||
}
|
||||
|
@ -361,91 +213,56 @@ func waitUntilOscImageStateFunc(conn *osc.APIClient, id string) stateRefreshFunc
|
|||
}
|
||||
}
|
||||
|
||||
func securityGroupWaitFunc(conn *oapi.Client, id string) stateRefreshFunc {
|
||||
return func() (string, error) {
|
||||
log.Printf("[Debug] Check if SG with id %s exists", id)
|
||||
resp, err := conn.POST_ReadSecurityGroups(oapi.ReadSecurityGroupsRequest{
|
||||
Filters: oapi.FiltersSecurityGroup{
|
||||
SecurityGroupIds: []string{id},
|
||||
},
|
||||
})
|
||||
|
||||
log.Printf("[Debug] Read Response %+v", resp.OK)
|
||||
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
|
||||
if resp.OK == nil {
|
||||
return "", fmt.Errorf("Security Group with ID %s. Not Found", id)
|
||||
}
|
||||
|
||||
if len(resp.OK.SecurityGroups) == 0 {
|
||||
return "waiting", nil
|
||||
}
|
||||
|
||||
return "exists", nil
|
||||
}
|
||||
}
|
||||
|
||||
func waitUntilSnapshotDoneStateFunc(conn *oapi.Client, id string) stateRefreshFunc {
|
||||
func waitUntilOscSnapshotDoneStateFunc(conn *osc.APIClient, id string) stateRefreshFunc {
|
||||
return func() (string, error) {
|
||||
log.Printf("[Debug] Check if Snapshot with id %s exists", id)
|
||||
resp, err := conn.POST_ReadSnapshots(oapi.ReadSnapshotsRequest{
|
||||
Filters: oapi.FiltersSnapshot{
|
||||
SnapshotIds: []string{id},
|
||||
},
|
||||
resp, _, err := conn.SnapshotApi.ReadSnapshots(context.Background(), &osc.ReadSnapshotsOpts{
|
||||
ReadSnapshotsRequest: optional.NewInterface(osc.ReadSnapshotsRequest{
|
||||
Filters: osc.FiltersSnapshot{
|
||||
SnapshotIds: []string{id},
|
||||
},
|
||||
}),
|
||||
})
|
||||
|
||||
log.Printf("[Debug] Read Response %+v", resp.OK)
|
||||
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
|
||||
if resp.OK == nil {
|
||||
if len(resp.Snapshots) == 0 {
|
||||
return "", fmt.Errorf("Snapshot with ID %s. Not Found", id)
|
||||
}
|
||||
|
||||
if len(resp.OK.Snapshots) == 0 {
|
||||
return "", fmt.Errorf("Snapshot with ID %s. Not Found", id)
|
||||
if resp.Snapshots[0].State == "error" {
|
||||
return resp.Snapshots[0].State, fmt.Errorf("Snapshot (%s) creation is failed", id)
|
||||
}
|
||||
|
||||
if resp.OK.Snapshots[0].State == "error" {
|
||||
return resp.OK.Snapshots[0].State, fmt.Errorf("Snapshot (%s) creation is failed", id)
|
||||
}
|
||||
|
||||
return resp.OK.Snapshots[0].State, nil
|
||||
return resp.Snapshots[0].State, nil
|
||||
}
|
||||
}
|
||||
|
||||
func volumeWaitFunc(conn *oapi.Client, id string) stateRefreshFunc {
|
||||
func volumeOscWaitFunc(conn *osc.APIClient, id string) stateRefreshFunc {
|
||||
return func() (string, error) {
|
||||
log.Printf("[Debug] Check if SvolumeG with id %s exists", id)
|
||||
resp, err := conn.POST_ReadVolumes(oapi.ReadVolumesRequest{
|
||||
Filters: oapi.FiltersVolume{
|
||||
VolumeIds: []string{id},
|
||||
},
|
||||
resp, _, err := conn.VolumeApi.ReadVolumes(context.Background(), &osc.ReadVolumesOpts{
|
||||
ReadVolumesRequest: optional.NewInterface(osc.ReadVolumesRequest{
|
||||
Filters: osc.FiltersVolume{
|
||||
VolumeIds: []string{id},
|
||||
},
|
||||
}),
|
||||
})
|
||||
|
||||
log.Printf("[Debug] Read Response %+v", resp.OK)
|
||||
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
|
||||
if resp.OK == nil {
|
||||
return "", fmt.Errorf("Volume with ID %s. Not Found", id)
|
||||
}
|
||||
|
||||
if len(resp.OK.Volumes) == 0 {
|
||||
if len(resp.Volumes) == 0 {
|
||||
return "waiting", nil
|
||||
}
|
||||
|
||||
if resp.OK.Volumes[0].State == "error" {
|
||||
return resp.OK.Volumes[0].State, fmt.Errorf("Volume (%s) creation is failed", id)
|
||||
if resp.Volumes[0].State == "error" {
|
||||
return resp.Volumes[0].State, fmt.Errorf("Volume (%s) creation is failed", id)
|
||||
}
|
||||
|
||||
return resp.OK.Volumes[0].State, nil
|
||||
return resp.Volumes[0].State, nil
|
||||
}
|
||||
}
|
||||
|
|
|
@ -39,8 +39,8 @@ func (s *StepDeregisterOMI) Run(_ context.Context, state multistep.StateBag) mul
|
|||
resp, _, err := conn.ImageApi.ReadImages(context.Background(), &osc.ReadImagesOpts{
|
||||
ReadImagesRequest: optional.NewInterface(osc.ReadImagesRequest{
|
||||
Filters: osc.FiltersImage{
|
||||
ImageNames: []string{s.OMIName},
|
||||
AccountAliases: []string{"self"},
|
||||
ImageNames: []string{s.OMIName},
|
||||
//AccountAliases: []string{"self"},
|
||||
},
|
||||
}),
|
||||
})
|
||||
|
|
|
@ -11,10 +11,10 @@ import (
|
|||
"log"
|
||||
"time"
|
||||
|
||||
"github.com/antihax/optional"
|
||||
"github.com/hashicorp/packer/helper/communicator"
|
||||
"github.com/hashicorp/packer/helper/multistep"
|
||||
"github.com/hashicorp/packer/packer"
|
||||
"github.com/outscale/osc-go/oapi"
|
||||
"github.com/outscale/osc-sdk-go/osc"
|
||||
)
|
||||
|
||||
|
@ -103,7 +103,7 @@ WaitLoop:
|
|||
func (s *StepGetPassword) Cleanup(multistep.StateBag) {}
|
||||
|
||||
func (s *StepGetPassword) waitForPassword(state multistep.StateBag, cancel <-chan struct{}) (string, error) {
|
||||
oapiconn := state.Get("oapi").(*oapi.Client)
|
||||
oscconn := state.Get("osc").(*osc.APIClient)
|
||||
vm := state.Get("vm").(osc.Vm)
|
||||
privateKey := s.Comm.SSHPrivateKey
|
||||
|
||||
|
@ -115,17 +115,19 @@ func (s *StepGetPassword) waitForPassword(state multistep.StateBag, cancel <-cha
|
|||
case <-time.After(5 * time.Second):
|
||||
}
|
||||
|
||||
resp, err := oapiconn.POST_ReadAdminPassword(oapi.ReadAdminPasswordRequest{
|
||||
VmId: vm.VmId,
|
||||
resp, _, err := oscconn.VmApi.ReadAdminPassword(context.Background(), &osc.ReadAdminPasswordOpts{
|
||||
ReadAdminPasswordRequest: optional.NewInterface(osc.ReadAdminPasswordRequest{
|
||||
VmId: vm.VmId,
|
||||
}),
|
||||
})
|
||||
if err != nil {
|
||||
err := fmt.Errorf("Error retrieving auto-generated vm password: %s", err)
|
||||
return "", err
|
||||
}
|
||||
|
||||
if resp.OK.AdminPassword != "" {
|
||||
if resp.AdminPassword != "" {
|
||||
decryptedPassword, err := decryptPasswordDataWithPrivateKey(
|
||||
resp.OK.AdminPassword, []byte(privateKey))
|
||||
resp.AdminPassword, []byte(privateKey))
|
||||
if err != nil {
|
||||
err := fmt.Errorf("Error decrypting auto-generated vm password: %s", err)
|
||||
return "", err
|
||||
|
|
|
@ -10,7 +10,6 @@ import (
|
|||
"github.com/antihax/optional"
|
||||
"github.com/hashicorp/packer/helper/multistep"
|
||||
"github.com/hashicorp/packer/packer"
|
||||
"github.com/outscale/osc-go/oapi"
|
||||
"github.com/outscale/osc-sdk-go/osc"
|
||||
)
|
||||
|
||||
|
@ -31,14 +30,6 @@ type StepNetworkInfo struct {
|
|||
SecurityGroupFilter SecurityGroupFilterOptions
|
||||
}
|
||||
|
||||
type subnetsSort []oapi.Subnet
|
||||
|
||||
func (a subnetsSort) Len() int { return len(a) }
|
||||
func (a subnetsSort) Swap(i, j int) { a[i], a[j] = a[j], a[i] }
|
||||
func (a subnetsSort) Less(i, j int) bool {
|
||||
return a[i].AvailableIpsCount < a[j].AvailableIpsCount
|
||||
}
|
||||
|
||||
type subnetsOscSort []osc.Subnet
|
||||
|
||||
func (a subnetsOscSort) Len() int { return len(a) }
|
||||
|
@ -47,13 +38,6 @@ func (a subnetsOscSort) Less(i, j int) bool {
|
|||
return a[i].AvailableIpsCount < a[j].AvailableIpsCount
|
||||
}
|
||||
|
||||
// Returns the most recent OMI out of a slice of images.
|
||||
func mostFreeSubnet(subnets []oapi.Subnet) oapi.Subnet {
|
||||
sortedSubnets := subnets
|
||||
sort.Sort(subnetsSort(sortedSubnets))
|
||||
return sortedSubnets[len(sortedSubnets)-1]
|
||||
}
|
||||
|
||||
// Returns the most recent OMI out of a slice of images.
|
||||
func mostFreeOscSubnet(subnets []osc.Subnet) osc.Subnet {
|
||||
sortedSubnets := subnets
|
||||
|
|
|
@ -10,7 +10,6 @@ import (
|
|||
|
||||
"github.com/antihax/optional"
|
||||
"github.com/aws/aws-sdk-go/aws/awserr"
|
||||
"github.com/outscale/osc-go/oapi"
|
||||
"github.com/outscale/osc-sdk-go/osc"
|
||||
|
||||
retry "github.com/hashicorp/packer/common"
|
||||
|
@ -119,42 +118,8 @@ func (s *StepRunSourceVm) Run(ctx context.Context, state multistep.StateBag) mul
|
|||
Placement: osc.Placement{SubregionName: subregion},
|
||||
BsuOptimized: s.BsuOptimized,
|
||||
BlockDeviceMappings: s.BlockDevices.BuildOSCLaunchDevices(),
|
||||
//IamVmProfile: oapi.IamVmProfileSpecification{Name: &s.IamVmProfile},
|
||||
}
|
||||
|
||||
// if s.EnableT2Unlimited {
|
||||
// creditOption := "unlimited"
|
||||
// runOpts.CreditSpecification = &oapi.CreditSpecificationRequest{CpuCredits: &creditOption}
|
||||
// }
|
||||
|
||||
// Collect tags for tagging on resource creation
|
||||
// var tagSpecs []oapi.ResourceTag
|
||||
|
||||
// if len(oapiTags) > 0 {
|
||||
// runTags := &oapi.ResourceTag{
|
||||
// ResourceType: aws.String("vm"),
|
||||
// Tags: oapiTags,
|
||||
// }
|
||||
|
||||
// tagSpecs = append(tagSpecs, runTags)
|
||||
// }
|
||||
|
||||
// if len(volTags) > 0 {
|
||||
// runVolTags := &oapi.TagSpecification{
|
||||
// ResourceType: aws.String("volume"),
|
||||
// Tags: volTags,
|
||||
// }
|
||||
|
||||
// tagSpecs = append(tagSpecs, runVolTags)
|
||||
// }
|
||||
|
||||
// // If our region supports it, set tag specifications
|
||||
// if len(tagSpecs) > 0 && !s.IsRestricted {
|
||||
// runOpts.SetTagSpecifications(tagSpecs)
|
||||
// oapiTags.Report(ui)
|
||||
// volTags.Report(ui)
|
||||
// }
|
||||
|
||||
if s.Comm.SSHKeyPairName != "" {
|
||||
runOpts.KeypairName = s.Comm.SSHKeyPairName
|
||||
}
|
||||
|
@ -299,7 +264,7 @@ func (s *StepRunSourceVm) Run(ctx context.Context, state multistep.StateBag) mul
|
|||
|
||||
volumeIds := make([]string, 0)
|
||||
for _, v := range vm.BlockDeviceMappings {
|
||||
if bsu := v.Bsu; !reflect.DeepEqual(bsu, oapi.BsuCreated{}) {
|
||||
if bsu := v.Bsu; !reflect.DeepEqual(bsu, osc.BsuCreated{}) {
|
||||
volumeIds = append(volumeIds, bsu.VolumeId)
|
||||
}
|
||||
}
|
||||
|
|
|
@ -10,7 +10,6 @@ import (
|
|||
"github.com/antihax/optional"
|
||||
"github.com/hashicorp/packer/helper/multistep"
|
||||
"github.com/hashicorp/packer/packer"
|
||||
"github.com/outscale/osc-go/oapi"
|
||||
"github.com/outscale/osc-sdk-go/osc"
|
||||
)
|
||||
|
||||
|
@ -18,24 +17,15 @@ import (
|
|||
// that is used throughout the OMI creation process.
|
||||
//
|
||||
// Produces:
|
||||
// source_image *oapi.Image - the source OMI info
|
||||
// source_image *osc.Image - the source OMI info
|
||||
type StepSourceOMIInfo struct {
|
||||
SourceOmi string
|
||||
OMIVirtType string
|
||||
OmiFilters OmiFilterOptions
|
||||
}
|
||||
|
||||
type imageSort []oapi.Image
|
||||
type imageOscSort []osc.Image
|
||||
|
||||
func (a imageSort) Len() int { return len(a) }
|
||||
func (a imageSort) Swap(i, j int) { a[i], a[j] = a[j], a[i] }
|
||||
func (a imageSort) Less(i, j int) bool {
|
||||
itime, _ := time.Parse(time.RFC3339, a[i].CreationDate)
|
||||
jtime, _ := time.Parse(time.RFC3339, a[j].CreationDate)
|
||||
return itime.Unix() < jtime.Unix()
|
||||
}
|
||||
|
||||
func (a imageOscSort) Len() int { return len(a) }
|
||||
func (a imageOscSort) Swap(i, j int) { a[i], a[j] = a[j], a[i] }
|
||||
func (a imageOscSort) Less(i, j int) bool {
|
||||
|
@ -44,13 +34,6 @@ func (a imageOscSort) Less(i, j int) bool {
|
|||
return itime.Unix() < jtime.Unix()
|
||||
}
|
||||
|
||||
// Returns the most recent OMI out of a slice of images.
|
||||
func mostRecentOmi(images []oapi.Image) oapi.Image {
|
||||
sortedImages := images
|
||||
sort.Sort(imageSort(sortedImages))
|
||||
return sortedImages[len(sortedImages)-1]
|
||||
}
|
||||
|
||||
// Returns the most recent OMI out of a slice of images.
|
||||
func mostRecentOscOmi(images []osc.Image) osc.Image {
|
||||
sortedImages := images
|
||||
|
|
|
@ -8,21 +8,12 @@ import (
|
|||
"github.com/hashicorp/packer/helper/multistep"
|
||||
"github.com/hashicorp/packer/packer"
|
||||
"github.com/hashicorp/packer/template/interpolate"
|
||||
"github.com/outscale/osc-go/oapi"
|
||||
"github.com/outscale/osc-sdk-go/osc"
|
||||
)
|
||||
|
||||
type TagMap map[string]string
|
||||
type OAPITags []oapi.ResourceTag
|
||||
type OSCTags []osc.ResourceTag
|
||||
|
||||
func (t OAPITags) Report(ui packer.Ui) {
|
||||
for _, tag := range t {
|
||||
ui.Message(fmt.Sprintf("Adding tag: \"%s\": \"%s\"",
|
||||
tag.Key, tag.Value))
|
||||
}
|
||||
}
|
||||
|
||||
func (t OSCTags) Report(ui packer.Ui) {
|
||||
for _, tag := range t {
|
||||
ui.Message(fmt.Sprintf("Adding tag: \"%s\": \"%s\"",
|
||||
|
@ -34,27 +25,6 @@ func (t TagMap) IsSet() bool {
|
|||
return len(t) > 0
|
||||
}
|
||||
|
||||
func (t TagMap) OAPITags(ctx interpolate.Context, region string, state multistep.StateBag) (OAPITags, error) {
|
||||
var oapiTags []oapi.ResourceTag
|
||||
ctx.Data = extractBuildInfo(region, state)
|
||||
|
||||
for key, value := range t {
|
||||
interpolatedKey, err := interpolate.Render(key, &ctx)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("Error processing tag: %s:%s - %s", key, value, err)
|
||||
}
|
||||
interpolatedValue, err := interpolate.Render(value, &ctx)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("Error processing tag: %s:%s - %s", key, value, err)
|
||||
}
|
||||
oapiTags = append(oapiTags, oapi.ResourceTag{
|
||||
Key: interpolatedKey,
|
||||
Value: interpolatedValue,
|
||||
})
|
||||
}
|
||||
return oapiTags, nil
|
||||
}
|
||||
|
||||
func (t TagMap) OSCTags(ctx interpolate.Context, region string, state multistep.StateBag) (OSCTags, error) {
|
||||
var oscTags []osc.ResourceTag
|
||||
ctx.Data = extractBuildInfo(region, state)
|
||||
|
@ -76,17 +46,6 @@ func (t TagMap) OSCTags(ctx interpolate.Context, region string, state multistep.
|
|||
return oscTags, nil
|
||||
}
|
||||
|
||||
func CreateTags(conn *oapi.Client, resourceID string, ui packer.Ui, tags OAPITags) error {
|
||||
tags.Report(ui)
|
||||
|
||||
_, err := conn.POST_CreateTags(oapi.CreateTagsRequest{
|
||||
ResourceIds: []string{resourceID},
|
||||
Tags: tags,
|
||||
})
|
||||
|
||||
return err
|
||||
}
|
||||
|
||||
func CreateOSCTags(conn *osc.APIClient, resourceID string, ui packer.Ui, tags OSCTags) error {
|
||||
tags.Report(ui)
|
||||
|
||||
|
|
Loading…
Reference in New Issue