implement vpc environment
This commit is contained in:
parent
af865b1591
commit
cd370aaaad
|
@ -32,7 +32,7 @@ func (b *Builder) Prepare(raws ...interface{}) ([]string, []string, error) {
|
|||
}
|
||||
|
||||
func (b *Builder) Run(ctx context.Context, ui packersdk.Ui, hook packersdk.Hook) (packersdk.Artifact, error) {
|
||||
ui.Message("Creating Naver Cloud Platform Connection ...")
|
||||
ui.Message("Creating NAVER CLOUD PLATFORM Connection ...")
|
||||
config := Config{
|
||||
AccessKey: b.config.AccessKey,
|
||||
SecretKey: b.config.SecretKey,
|
||||
|
@ -46,60 +46,41 @@ func (b *Builder) Run(ctx context.Context, ui packersdk.Ui, hook packersdk.Hook)
|
|||
b.stateBag.Put("hook", hook)
|
||||
b.stateBag.Put("ui", ui)
|
||||
|
||||
var steps []multistep.Step
|
||||
|
||||
steps = []multistep.Step{}
|
||||
|
||||
if b.config.Comm.Type == "ssh" {
|
||||
steps = []multistep.Step{
|
||||
NewStepValidateTemplate(conn, ui, &b.config),
|
||||
NewStepCreateLoginKey(conn, ui),
|
||||
NewStepCreateServerInstance(conn, ui, &b.config),
|
||||
NewStepCreateBlockStorageInstance(conn, ui, &b.config),
|
||||
NewStepGetRootPassword(conn, ui, &b.config),
|
||||
NewStepCreatePublicIPInstance(conn, ui, &b.config),
|
||||
&communicator.StepConnectSSH{
|
||||
Config: &b.config.Comm,
|
||||
Host: func(stateBag multistep.StateBag) (string, error) {
|
||||
return stateBag.Get("PublicIP").(string), nil
|
||||
},
|
||||
SSHConfig: b.config.Comm.SSHConfigFunc(),
|
||||
steps := []multistep.Step{
|
||||
NewStepValidateTemplate(conn, ui, &b.config),
|
||||
NewStepCreateLoginKey(conn, ui, &b.config),
|
||||
multistep.If(b.config.SupportVPC, NewStepCreateInitScript(conn, ui, &b.config)),
|
||||
NewStepCreateServerInstance(conn, ui, &b.config),
|
||||
NewStepCreateBlockStorage(conn, ui, &b.config),
|
||||
NewStepGetRootPassword(conn, ui, &b.config),
|
||||
NewStepCreatePublicIP(conn, ui, &b.config),
|
||||
multistep.If(b.config.Comm.Type == "ssh", &communicator.StepConnectSSH{
|
||||
Config: &b.config.Comm,
|
||||
Host: func(stateBag multistep.StateBag) (string, error) {
|
||||
return stateBag.Get("public_ip").(string), nil
|
||||
},
|
||||
&commonsteps.StepProvision{},
|
||||
&commonsteps.StepCleanupTempKeys{
|
||||
Comm: &b.config.Comm,
|
||||
SSHConfig: b.config.Comm.SSHConfigFunc(),
|
||||
}),
|
||||
multistep.If(b.config.Comm.Type == "winrm", &communicator.StepConnectWinRM{
|
||||
Config: &b.config.Comm,
|
||||
Host: func(stateBag multistep.StateBag) (string, error) {
|
||||
return stateBag.Get("public_ip").(string), nil
|
||||
},
|
||||
NewStepStopServerInstance(conn, ui),
|
||||
NewStepCreateServerImage(conn, ui, &b.config),
|
||||
NewStepDeleteBlockStorageInstance(conn, ui, &b.config),
|
||||
NewStepTerminateServerInstance(conn, ui),
|
||||
}
|
||||
} else if b.config.Comm.Type == "winrm" {
|
||||
steps = []multistep.Step{
|
||||
NewStepValidateTemplate(conn, ui, &b.config),
|
||||
NewStepCreateLoginKey(conn, ui),
|
||||
NewStepCreateServerInstance(conn, ui, &b.config),
|
||||
NewStepCreateBlockStorageInstance(conn, ui, &b.config),
|
||||
NewStepGetRootPassword(conn, ui, &b.config),
|
||||
NewStepCreatePublicIPInstance(conn, ui, &b.config),
|
||||
&communicator.StepConnectWinRM{
|
||||
Config: &b.config.Comm,
|
||||
Host: func(stateBag multistep.StateBag) (string, error) {
|
||||
return stateBag.Get("PublicIP").(string), nil
|
||||
},
|
||||
WinRMConfig: func(state multistep.StateBag) (*communicator.WinRMConfig, error) {
|
||||
return &communicator.WinRMConfig{
|
||||
Username: b.config.Comm.WinRMUser,
|
||||
Password: b.config.Comm.WinRMPassword,
|
||||
}, nil
|
||||
},
|
||||
WinRMConfig: func(state multistep.StateBag) (*communicator.WinRMConfig, error) {
|
||||
return &communicator.WinRMConfig{
|
||||
Username: b.config.Comm.WinRMUser,
|
||||
Password: b.config.Comm.WinRMPassword,
|
||||
}, nil
|
||||
},
|
||||
&commonsteps.StepProvision{},
|
||||
NewStepStopServerInstance(conn, ui),
|
||||
NewStepCreateServerImage(conn, ui, &b.config),
|
||||
NewStepDeleteBlockStorageInstance(conn, ui, &b.config),
|
||||
NewStepTerminateServerInstance(conn, ui),
|
||||
}
|
||||
}),
|
||||
&commonsteps.StepProvision{},
|
||||
multistep.If(b.config.Comm.Type == "ssh", &commonsteps.StepCleanupTempKeys{
|
||||
Comm: &b.config.Comm,
|
||||
}),
|
||||
NewStepStopServerInstance(conn, ui, &b.config),
|
||||
NewStepCreateServerImage(conn, ui, &b.config),
|
||||
NewStepDeleteBlockStorage(conn, ui, &b.config),
|
||||
NewStepTerminateServerInstance(conn, ui, &b.config),
|
||||
}
|
||||
|
||||
// Run!
|
||||
|
@ -107,7 +88,7 @@ func (b *Builder) Run(ctx context.Context, ui packersdk.Ui, hook packersdk.Hook)
|
|||
b.runner.Run(ctx, b.stateBag)
|
||||
|
||||
// If there was an error, return that
|
||||
if rawErr, ok := b.stateBag.GetOk("Error"); ok {
|
||||
if rawErr, ok := b.stateBag.GetOk("error"); ok {
|
||||
return nil, rawErr.(error)
|
||||
}
|
||||
|
||||
|
@ -116,7 +97,7 @@ func (b *Builder) Run(ctx context.Context, ui packersdk.Ui, hook packersdk.Hook)
|
|||
StateData: map[string]interface{}{"generated_data": b.stateBag.Get("generated_data")},
|
||||
}
|
||||
|
||||
if serverImage, ok := b.stateBag.GetOk("memberServerImage"); ok {
|
||||
if serverImage, ok := b.stateBag.GetOk("member_server_image"); ok {
|
||||
artifact.MemberServerImage = serverImage.(*server.MemberServerImage)
|
||||
}
|
||||
|
||||
|
|
|
@ -6,6 +6,8 @@ package ncloud
|
|||
import (
|
||||
"errors"
|
||||
"fmt"
|
||||
"github.com/NaverCloudPlatform/ncloud-sdk-go-v2/services/vpc"
|
||||
"github.com/NaverCloudPlatform/ncloud-sdk-go-v2/services/vserver"
|
||||
"os"
|
||||
|
||||
"github.com/NaverCloudPlatform/ncloud-sdk-go-v2/ncloud"
|
||||
|
@ -50,12 +52,19 @@ type Config struct {
|
|||
BlockStorageSize int `mapstructure:"block_storage_size" required:"false"`
|
||||
// Name of the region where you want to create an image.
|
||||
// (default: Korea)
|
||||
Region string `mapstructure:"region" required:"false"`
|
||||
Region string `mapstructure:"region" required:"false"`
|
||||
RegionCode string `mapstructure:"region_code" required:"false"`
|
||||
// This is used to allow
|
||||
// winrm access when you create a Windows server. An ACG that specifies an
|
||||
// access source (0.0.0.0/0) and allowed port (5985) must be created in
|
||||
// advance.
|
||||
AccessControlGroupConfigurationNo string `mapstructure:"access_control_group_configuration_no" required:"false"`
|
||||
// Whether to use VPC. By default, the value is false on "public" site. If you want to use VPC environment. Please set this value true.
|
||||
SupportVPC bool `mapstructure:"support_vpc" required:"false"`
|
||||
// The ID of the associated Subnet
|
||||
SubnetNo string `mapstructure:"subnet_no" required:"false"`
|
||||
// The ID of the VPC where you want to place the Server Instance
|
||||
VpcNo string `mapstructure:"vpc_no" required:"false"`
|
||||
|
||||
Comm communicator.Config `mapstructure:",squash"`
|
||||
ctx *interpolate.Context
|
||||
|
@ -63,7 +72,7 @@ type Config struct {
|
|||
|
||||
// NewConfig checks parameters
|
||||
func (c *Config) Prepare(raws ...interface{}) ([]string, error) {
|
||||
warnings := []string{}
|
||||
var warnings []string
|
||||
|
||||
err := config.Decode(c, &config.DecodeOpts{
|
||||
Interpolate: true,
|
||||
|
@ -81,59 +90,63 @@ func (c *Config) Prepare(raws ...interface{}) ([]string, error) {
|
|||
}
|
||||
|
||||
if c.AccessKey == "" {
|
||||
errs = packersdk.MultiErrorAppend(errs, errors.New("access_key is required"))
|
||||
errs = packersdk.MultiErrorAppend(errs, errors.New("`access_key` is required"))
|
||||
}
|
||||
|
||||
if c.SecretKey == "" {
|
||||
errs = packersdk.MultiErrorAppend(errs, errors.New("secret_key is required"))
|
||||
errs = packersdk.MultiErrorAppend(errs, errors.New("`secret_key` is required"))
|
||||
}
|
||||
|
||||
if c.MemberServerImageNo == "" && c.ServerImageProductCode == "" {
|
||||
errs = packersdk.MultiErrorAppend(errs, errors.New("server_image_product_code or member_server_image_no is required"))
|
||||
errs = packersdk.MultiErrorAppend(errs, errors.New("`server_image_product_code` or `member_server_image_no` is required"))
|
||||
}
|
||||
|
||||
if c.MemberServerImageNo != "" && c.ServerImageProductCode != "" {
|
||||
errs = packersdk.MultiErrorAppend(errs, errors.New("Only one of server_image_product_code and member_server_image_no can be set"))
|
||||
errs = packersdk.MultiErrorAppend(errs, errors.New("only one of `server_image_product_code` and `member_server_image_no` can be set"))
|
||||
}
|
||||
|
||||
if c.ServerImageProductCode != "" && len(c.ServerImageProductCode) > 20 {
|
||||
errs = packersdk.MultiErrorAppend(errs, errors.New("If server_image_product_code field is set, length of server_image_product_code should be max 20"))
|
||||
if c.ServerImageProductCode != "" && len(c.ServerImageProductCode) > 50 {
|
||||
errs = packersdk.MultiErrorAppend(errs, errors.New("if `server_image_product_code` field is set, length of `server_image_product_code` should be max 20"))
|
||||
}
|
||||
|
||||
if c.ServerProductCode != "" && len(c.ServerProductCode) > 20 {
|
||||
errs = packersdk.MultiErrorAppend(errs, errors.New("If server_product_code field is set, length of server_product_code should be max 20"))
|
||||
if c.ServerProductCode != "" && len(c.ServerProductCode) > 50 {
|
||||
errs = packersdk.MultiErrorAppend(errs, errors.New("if `server_product_code` field is set, length of `server_product_code` should be max 20"))
|
||||
}
|
||||
|
||||
if c.ServerImageName != "" && (len(c.ServerImageName) < 3 || len(c.ServerImageName) > 30) {
|
||||
errs = packersdk.MultiErrorAppend(errs, errors.New("If server_image_name field is set, length of server_image_name should be min 3 and max 20"))
|
||||
errs = packersdk.MultiErrorAppend(errs, errors.New("if `server_image_name` field is set, length of `server_image_name` should be min 3 and max 20"))
|
||||
}
|
||||
|
||||
if c.ServerImageDescription != "" && len(c.ServerImageDescription) > 1000 {
|
||||
errs = packersdk.MultiErrorAppend(errs, errors.New("If server_image_description field is set, length of server_image_description should be max 1000"))
|
||||
errs = packersdk.MultiErrorAppend(errs, errors.New("if `server_image_description` field is set, length of `server_image_description` should be max 1000"))
|
||||
}
|
||||
|
||||
if c.BlockStorageSize != 0 {
|
||||
if c.BlockStorageSize < 10 || c.BlockStorageSize > 2000 {
|
||||
errs = packersdk.MultiErrorAppend(errs, errors.New("The size of BlockStorageSize is at least 10 GB and up to 2000GB"))
|
||||
errs = packersdk.MultiErrorAppend(errs, errors.New("the size of `block_storage_size` is at least 10 GB and up to 2000GB"))
|
||||
} else if int(c.BlockStorageSize/10)*10 != c.BlockStorageSize {
|
||||
return nil, errors.New("BlockStorageSize must be a multiple of 10 GB")
|
||||
}
|
||||
}
|
||||
|
||||
if c.UserData != "" && c.UserDataFile != "" {
|
||||
errs = packersdk.MultiErrorAppend(errs, errors.New("Only one of user_data or user_data_file can be specified."))
|
||||
errs = packersdk.MultiErrorAppend(errs, errors.New("only one of user_data or `user_data`_file can be specified."))
|
||||
} else if c.UserDataFile != "" {
|
||||
if _, err := os.Stat(c.UserDataFile); err != nil {
|
||||
errs = packersdk.MultiErrorAppend(errs, fmt.Errorf("user_data_file not found: %s", c.UserDataFile))
|
||||
errs = packersdk.MultiErrorAppend(errs, fmt.Errorf("`user_data_file` not found: %s", c.UserDataFile))
|
||||
}
|
||||
}
|
||||
|
||||
if c.UserData != "" && len(c.UserData) > 21847 {
|
||||
errs = packersdk.MultiErrorAppend(errs, errors.New("If user_data field is set, length of UserData should be max 21847"))
|
||||
errs = packersdk.MultiErrorAppend(errs, errors.New("if `user_data` field is set, length of UserData should be max 21847"))
|
||||
}
|
||||
|
||||
if c.Comm.Type == "winrm" && c.AccessControlGroupConfigurationNo == "" {
|
||||
errs = packersdk.MultiErrorAppend(errs, errors.New("If Communicator is winrm, access_control_group_configuration_no is required"))
|
||||
errs = packersdk.MultiErrorAppend(errs, errors.New("if Communicator is winrm, `access_control_group_configuration_no` (allow 5986 port) is required"))
|
||||
}
|
||||
|
||||
if c.VpcNo != "" || c.SubnetNo != "" {
|
||||
c.SupportVPC = true
|
||||
}
|
||||
|
||||
if errs != nil && len(errs.Errors) > 0 {
|
||||
|
@ -144,7 +157,9 @@ func (c *Config) Prepare(raws ...interface{}) ([]string, error) {
|
|||
}
|
||||
|
||||
type NcloudAPIClient struct {
|
||||
server *server.APIClient
|
||||
server *server.APIClient
|
||||
vserver *vserver.APIClient
|
||||
vpc *vpc.APIClient
|
||||
}
|
||||
|
||||
func (c *Config) Client() (*NcloudAPIClient, error) {
|
||||
|
@ -153,6 +168,8 @@ func (c *Config) Client() (*NcloudAPIClient, error) {
|
|||
SecretKey: c.SecretKey,
|
||||
}
|
||||
return &NcloudAPIClient{
|
||||
server: server.NewAPIClient(server.NewConfiguration(apiKey)),
|
||||
server: server.NewAPIClient(server.NewConfiguration(apiKey)),
|
||||
vserver: vserver.NewAPIClient(vserver.NewConfiguration(apiKey)),
|
||||
vpc: vpc.NewAPIClient(vpc.NewConfiguration(apiKey)),
|
||||
}, nil
|
||||
}
|
||||
|
|
|
@ -29,7 +29,11 @@ type FlatConfig struct {
|
|||
UserDataFile *string `mapstructure:"user_data_file" required:"false" cty:"user_data_file" hcl:"user_data_file"`
|
||||
BlockStorageSize *int `mapstructure:"block_storage_size" required:"false" cty:"block_storage_size" hcl:"block_storage_size"`
|
||||
Region *string `mapstructure:"region" required:"false" cty:"region" hcl:"region"`
|
||||
RegionCode *string `mapstructure:"region_code" required:"false" cty:"region_code" hcl:"region_code"`
|
||||
AccessControlGroupConfigurationNo *string `mapstructure:"access_control_group_configuration_no" required:"false" cty:"access_control_group_configuration_no" hcl:"access_control_group_configuration_no"`
|
||||
SupportVPC *bool `mapstructure:"support_vpc" required:"false" cty:"support_vpc" hcl:"support_vpc"`
|
||||
SubnetNo *string `mapstructure:"subnet_no" required:"false" cty:"subnet_no" hcl:"subnet_no"`
|
||||
VpcNo *string `mapstructure:"vpc_no" required:"false" cty:"vpc_no" hcl:"vpc_no"`
|
||||
Type *string `mapstructure:"communicator" cty:"communicator" hcl:"communicator"`
|
||||
PauseBeforeConnect *string `mapstructure:"pause_before_connecting" cty:"pause_before_connecting" hcl:"pause_before_connecting"`
|
||||
SSHHost *string `mapstructure:"ssh_host" cty:"ssh_host" hcl:"ssh_host"`
|
||||
|
@ -112,7 +116,11 @@ func (*FlatConfig) HCL2Spec() map[string]hcldec.Spec {
|
|||
"user_data_file": &hcldec.AttrSpec{Name: "user_data_file", Type: cty.String, Required: false},
|
||||
"block_storage_size": &hcldec.AttrSpec{Name: "block_storage_size", Type: cty.Number, Required: false},
|
||||
"region": &hcldec.AttrSpec{Name: "region", Type: cty.String, Required: false},
|
||||
"region_code": &hcldec.AttrSpec{Name: "region_code", Type: cty.String, Required: false},
|
||||
"access_control_group_configuration_no": &hcldec.AttrSpec{Name: "access_control_group_configuration_no", Type: cty.String, Required: false},
|
||||
"support_vpc": &hcldec.AttrSpec{Name: "support_vpc", Type: cty.Bool, Required: false},
|
||||
"subnet_no": &hcldec.AttrSpec{Name: "subnet_no", Type: cty.String, Required: false},
|
||||
"vpc_no": &hcldec.AttrSpec{Name: "vpc_no", Type: cty.String, Required: false},
|
||||
"communicator": &hcldec.AttrSpec{Name: "communicator", Type: cty.String, Required: false},
|
||||
"pause_before_connecting": &hcldec.AttrSpec{Name: "pause_before_connecting", Type: cty.String, Required: false},
|
||||
"ssh_host": &hcldec.AttrSpec{Name: "ssh_host", Type: cty.String, Required: false},
|
||||
|
|
|
@ -6,7 +6,7 @@ import (
|
|||
|
||||
func processStepResult(err error, sayError func(error), state multistep.StateBag) multistep.StepAction {
|
||||
if err != nil {
|
||||
state.Put("Error", err)
|
||||
state.Put("error", err)
|
||||
sayError(err)
|
||||
|
||||
return multistep.ActionHalt
|
||||
|
|
|
@ -4,6 +4,7 @@ import (
|
|||
"context"
|
||||
"errors"
|
||||
"fmt"
|
||||
"github.com/NaverCloudPlatform/ncloud-sdk-go-v2/services/vserver"
|
||||
"log"
|
||||
"time"
|
||||
|
||||
|
@ -13,34 +14,49 @@ import (
|
|||
packersdk "github.com/hashicorp/packer-plugin-sdk/packer"
|
||||
)
|
||||
|
||||
const (
|
||||
BlockStorageStatusAttached = "ATTAC"
|
||||
BlockStorageStatusDetached = "DETAC"
|
||||
)
|
||||
|
||||
// StepCreateBlockStorageInstance struct is for making extra block storage
|
||||
type StepCreateBlockStorageInstance struct {
|
||||
Conn *NcloudAPIClient
|
||||
CreateBlockStorageInstance func(serverInstanceNo string) (*string, error)
|
||||
Say func(message string)
|
||||
Error func(e error)
|
||||
Config *Config
|
||||
type StepCreateBlockStorage struct {
|
||||
Conn *NcloudAPIClient
|
||||
CreateBlockStorage func(serverInstanceNo string) (*string, error)
|
||||
DeleteBlockStorage func(blockStorageInstanceNo string) error
|
||||
WaiterBlockStorageStatus func(conn *NcloudAPIClient, blockStorageInstanceNo *string, status string, timeout time.Duration) error
|
||||
Say func(message string)
|
||||
Error func(e error)
|
||||
Config *Config
|
||||
}
|
||||
|
||||
// NewStepCreateBlockStorageInstance make StepCreateBlockStorage struct to make extra block storage
|
||||
func NewStepCreateBlockStorageInstance(conn *NcloudAPIClient, ui packersdk.Ui, config *Config) *StepCreateBlockStorageInstance {
|
||||
var step = &StepCreateBlockStorageInstance{
|
||||
func NewStepCreateBlockStorage(conn *NcloudAPIClient, ui packersdk.Ui, config *Config) *StepCreateBlockStorage {
|
||||
var step = &StepCreateBlockStorage{
|
||||
Conn: conn,
|
||||
Say: func(message string) { ui.Say(message) },
|
||||
Error: func(e error) { ui.Error(e.Error()) },
|
||||
Config: config,
|
||||
}
|
||||
|
||||
step.CreateBlockStorageInstance = step.createBlockStorageInstance
|
||||
if config.SupportVPC {
|
||||
step.CreateBlockStorage = step.createVpcBlockStorage
|
||||
step.DeleteBlockStorage = step.deleteVpcBlockStorage
|
||||
step.WaiterBlockStorageStatus = waiterVpcBlockStorageStatus
|
||||
} else {
|
||||
step.CreateBlockStorage = step.createClassicBlockStorage
|
||||
step.DeleteBlockStorage = step.deleteClassicBlockStorage
|
||||
step.WaiterBlockStorageStatus = waiterClassicBlockStorageStatus
|
||||
}
|
||||
|
||||
return step
|
||||
}
|
||||
|
||||
func (s *StepCreateBlockStorageInstance) createBlockStorageInstance(serverInstanceNo string) (*string, error) {
|
||||
|
||||
reqParams := new(server.CreateBlockStorageInstanceRequest)
|
||||
reqParams.BlockStorageSize = ncloud.Int64(int64(s.Config.BlockStorageSize))
|
||||
reqParams.ServerInstanceNo = &serverInstanceNo
|
||||
func (s *StepCreateBlockStorage) createClassicBlockStorage(serverInstanceNo string) (*string, error) {
|
||||
reqParams := &server.CreateBlockStorageInstanceRequest{
|
||||
BlockStorageSize: ncloud.Int64(int64(s.Config.BlockStorageSize)),
|
||||
ServerInstanceNo: &serverInstanceNo,
|
||||
}
|
||||
|
||||
resp, err := s.Conn.server.V2Api.CreateBlockStorageInstance(reqParams)
|
||||
if err != nil {
|
||||
|
@ -50,31 +66,82 @@ func (s *StepCreateBlockStorageInstance) createBlockStorageInstance(serverInstan
|
|||
blockStorageInstance := resp.BlockStorageInstanceList[0]
|
||||
log.Println("Block Storage Instance information : ", blockStorageInstance.BlockStorageInstanceNo)
|
||||
|
||||
if err := waiterBlockStorageInstanceStatus(s.Conn, blockStorageInstance.BlockStorageInstanceNo, "ATTAC", 10*time.Minute); err != nil {
|
||||
if err := waiterClassicBlockStorageStatus(s.Conn, blockStorageInstance.BlockStorageInstanceNo, BlockStorageStatusAttached, 10*time.Minute); err != nil {
|
||||
return nil, errors.New("TIMEOUT : Block Storage instance status is not attached")
|
||||
}
|
||||
|
||||
return blockStorageInstance.BlockStorageInstanceNo, nil
|
||||
}
|
||||
|
||||
func (s *StepCreateBlockStorageInstance) Run(ctx context.Context, state multistep.StateBag) multistep.StepAction {
|
||||
func (s *StepCreateBlockStorage) createVpcBlockStorage(serverInstanceNo string) (*string, error) {
|
||||
reqParams := &vserver.CreateBlockStorageInstanceRequest{
|
||||
RegionCode: &s.Config.RegionCode,
|
||||
BlockStorageSize: ncloud.Int32(int32(s.Config.BlockStorageSize)),
|
||||
BlockStorageDescription: nil,
|
||||
ServerInstanceNo: &serverInstanceNo,
|
||||
BlockStorageSnapshotInstanceNo: nil,
|
||||
ZoneCode: nil,
|
||||
}
|
||||
|
||||
resp, err := s.Conn.vserver.V2Api.CreateBlockStorageInstance(reqParams)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
blockStorageInstance := resp.BlockStorageInstanceList[0]
|
||||
log.Println("Block Storage Instance information : ", blockStorageInstance.BlockStorageInstanceNo)
|
||||
|
||||
if err := s.WaiterBlockStorageStatus(s.Conn, blockStorageInstance.BlockStorageInstanceNo, BlockStorageStatusAttached, 10*time.Minute); err != nil {
|
||||
return nil, errors.New("TIMEOUT : Block Storage instance status is not attached")
|
||||
}
|
||||
|
||||
return blockStorageInstance.BlockStorageInstanceNo, nil
|
||||
}
|
||||
|
||||
func (s *StepCreateBlockStorage) deleteClassicBlockStorage(blockStorageInstanceNo string) error {
|
||||
reqParams := &server.DeleteBlockStorageInstancesRequest{
|
||||
BlockStorageInstanceNoList: []*string{&blockStorageInstanceNo},
|
||||
}
|
||||
|
||||
_, err := s.Conn.server.V2Api.DeleteBlockStorageInstances(reqParams)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (s *StepCreateBlockStorage) deleteVpcBlockStorage(blockStorageInstanceNo string) error {
|
||||
reqParams := &vserver.DeleteBlockStorageInstancesRequest{
|
||||
BlockStorageInstanceNoList: []*string{&blockStorageInstanceNo},
|
||||
}
|
||||
|
||||
_, err := s.Conn.vserver.V2Api.DeleteBlockStorageInstances(reqParams)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (s *StepCreateBlockStorage) Run(ctx context.Context, state multistep.StateBag) multistep.StepAction {
|
||||
if s.Config.BlockStorageSize == 0 {
|
||||
return processStepResult(nil, s.Error, state)
|
||||
}
|
||||
|
||||
s.Say("Create extra block storage instance")
|
||||
|
||||
serverInstanceNo := state.Get("InstanceNo").(string)
|
||||
serverInstanceNo := state.Get("instance_no").(string)
|
||||
|
||||
blockStorageInstanceNo, err := s.CreateBlockStorageInstance(serverInstanceNo)
|
||||
blockStorageInstanceNo, err := s.CreateBlockStorage(serverInstanceNo)
|
||||
if err == nil {
|
||||
state.Put("BlockStorageInstanceNo", *blockStorageInstanceNo)
|
||||
state.Put("block_storage_instance_no", *blockStorageInstanceNo)
|
||||
}
|
||||
|
||||
return processStepResult(err, s.Error, state)
|
||||
}
|
||||
|
||||
func (s *StepCreateBlockStorageInstance) Cleanup(state multistep.StateBag) {
|
||||
func (s *StepCreateBlockStorage) Cleanup(state multistep.StateBag) {
|
||||
_, cancelled := state.GetOk(multistep.StateCancelled)
|
||||
_, halted := state.GetOk(multistep.StateHalted)
|
||||
|
||||
|
@ -86,20 +153,17 @@ func (s *StepCreateBlockStorageInstance) Cleanup(state multistep.StateBag) {
|
|||
return
|
||||
}
|
||||
|
||||
if blockStorageInstanceNo, ok := state.GetOk("BlockStorageInstanceNo"); ok {
|
||||
if blockStorageInstanceNo, ok := state.GetOk("block_storage_instance_no"); ok {
|
||||
s.Say("Clean up Block Storage Instance")
|
||||
reqParams := server.DeleteBlockStorageInstancesRequest{
|
||||
BlockStorageInstanceNoList: []*string{blockStorageInstanceNo.(*string)},
|
||||
}
|
||||
blockStorageInstanceList, err := s.Conn.server.V2Api.DeleteBlockStorageInstances(&reqParams)
|
||||
err := s.DeleteBlockStorage(blockStorageInstanceNo.(string))
|
||||
if err != nil {
|
||||
s.Error(err)
|
||||
return
|
||||
}
|
||||
|
||||
s.Say(fmt.Sprintf("Block Storage Instance is deleted. Block Storage InstanceNo is %s", blockStorageInstanceNo.(string)))
|
||||
log.Println("Block Storage Instance information : ", blockStorageInstanceList.BlockStorageInstanceList[0])
|
||||
|
||||
if err := waiterBlockStorageInstanceStatus(s.Conn, blockStorageInstanceNo.(*string), "DETAC", time.Minute); err != nil {
|
||||
if err := s.WaiterBlockStorageStatus(s.Conn, blockStorageInstanceNo.(*string), BlockStorageStatusDetached, time.Minute); err != nil {
|
||||
s.Say("TIMEOUT : Block Storage instance status is not deattached")
|
||||
}
|
||||
}
|
||||
|
|
|
@ -10,11 +10,11 @@ import (
|
|||
|
||||
func TestStepCreateBlockStorageInstanceShouldFailIfOperationCreateBlockStorageInstanceFails(t *testing.T) {
|
||||
|
||||
var testSubject = &StepCreateBlockStorageInstance{
|
||||
CreateBlockStorageInstance: func(serverInstanceNo string) (*string, error) { return nil, fmt.Errorf("!! Unit Test FAIL !!") },
|
||||
Say: func(message string) {},
|
||||
Error: func(e error) {},
|
||||
Config: new(Config),
|
||||
var testSubject = &StepCreateBlockStorage{
|
||||
CreateBlockStorage: func(serverInstanceNo string) (*string, error) { return nil, fmt.Errorf("!! Unit Test FAIL !!") },
|
||||
Say: func(message string) {},
|
||||
Error: func(e error) {},
|
||||
Config: new(Config),
|
||||
}
|
||||
|
||||
testSubject.Config.BlockStorageSize = 10
|
||||
|
@ -27,18 +27,18 @@ func TestStepCreateBlockStorageInstanceShouldFailIfOperationCreateBlockStorageIn
|
|||
t.Fatalf("Expected the step to return 'ActionHalt', but got '%d'.", result)
|
||||
}
|
||||
|
||||
if _, ok := stateBag.GetOk("Error"); ok == false {
|
||||
if _, ok := stateBag.GetOk("error"); ok == false {
|
||||
t.Fatal("Expected the step to set stateBag['Error'], but it was not.")
|
||||
}
|
||||
}
|
||||
|
||||
func TestStepCreateBlockStorageInstanceShouldPassIfOperationCreateBlockStorageInstancePasses(t *testing.T) {
|
||||
var instanceNo = "a"
|
||||
var testSubject = &StepCreateBlockStorageInstance{
|
||||
CreateBlockStorageInstance: func(serverInstanceNo string) (*string, error) { return &instanceNo, nil },
|
||||
Say: func(message string) {},
|
||||
Error: func(e error) {},
|
||||
Config: new(Config),
|
||||
var testSubject = &StepCreateBlockStorage{
|
||||
CreateBlockStorage: func(serverInstanceNo string) (*string, error) { return &instanceNo, nil },
|
||||
Say: func(message string) {},
|
||||
Error: func(e error) {},
|
||||
Config: new(Config),
|
||||
}
|
||||
|
||||
testSubject.Config.BlockStorageSize = 10
|
||||
|
@ -51,7 +51,7 @@ func TestStepCreateBlockStorageInstanceShouldPassIfOperationCreateBlockStorageIn
|
|||
t.Fatalf("Expected the step to return 'ActionContinue', but got '%d'.", result)
|
||||
}
|
||||
|
||||
if _, ok := stateBag.GetOk("Error"); ok == true {
|
||||
if _, ok := stateBag.GetOk("error"); ok == true {
|
||||
t.Fatalf("Expected the step to not set stateBag['Error'], but it was.")
|
||||
}
|
||||
}
|
||||
|
@ -59,7 +59,7 @@ func TestStepCreateBlockStorageInstanceShouldPassIfOperationCreateBlockStorageIn
|
|||
func createTestStateBagStepCreateBlockStorageInstance() multistep.StateBag {
|
||||
stateBag := new(multistep.BasicStateBag)
|
||||
|
||||
stateBag.Put("InstanceNo", "a")
|
||||
stateBag.Put("instance_no", "a")
|
||||
|
||||
return stateBag
|
||||
}
|
||||
|
|
|
@ -0,0 +1,114 @@
|
|||
package ncloud
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"github.com/NaverCloudPlatform/ncloud-sdk-go-v2/ncloud"
|
||||
"io/ioutil"
|
||||
"time"
|
||||
|
||||
"github.com/NaverCloudPlatform/ncloud-sdk-go-v2/services/vserver"
|
||||
"github.com/hashicorp/packer-plugin-sdk/multistep"
|
||||
packersdk "github.com/hashicorp/packer-plugin-sdk/packer"
|
||||
)
|
||||
|
||||
type InitScript struct {
|
||||
KeyName string
|
||||
PrivateKey string
|
||||
}
|
||||
|
||||
type StepCreateInitScript struct {
|
||||
Conn *NcloudAPIClient
|
||||
CreateInitScript func() (string, error)
|
||||
DeleteInitScript func(initScriptNo string) error
|
||||
Say func(message string)
|
||||
Error func(e error)
|
||||
Config *Config
|
||||
}
|
||||
|
||||
func NewStepCreateInitScript(conn *NcloudAPIClient, ui packersdk.Ui, config *Config) *StepCreateInitScript {
|
||||
var step = &StepCreateInitScript{
|
||||
Conn: conn,
|
||||
Say: func(message string) { ui.Say(message) },
|
||||
Error: func(e error) { ui.Error(e.Error()) },
|
||||
Config: config,
|
||||
}
|
||||
|
||||
if config.SupportVPC {
|
||||
step.CreateInitScript = step.createVpcInitScript
|
||||
step.DeleteInitScript = step.deleteVpcInitScript
|
||||
}
|
||||
|
||||
return step
|
||||
}
|
||||
|
||||
func (s *StepCreateInitScript) createVpcInitScript() (string, error) {
|
||||
name := fmt.Sprintf("packer-%d", time.Now().Unix())
|
||||
reqParams := &vserver.CreateInitScriptRequest{
|
||||
RegionCode: &s.Config.RegionCode,
|
||||
InitScriptName: &name,
|
||||
}
|
||||
|
||||
if s.Config.Comm.Type == "winrm" {
|
||||
reqParams.OsTypeCode = ncloud.String("WND")
|
||||
}
|
||||
|
||||
if s.Config.UserData != "" {
|
||||
reqParams.InitScriptContent = &s.Config.UserData
|
||||
}
|
||||
if s.Config.UserDataFile != "" {
|
||||
contents, err := ioutil.ReadFile(s.Config.UserDataFile)
|
||||
if err != nil {
|
||||
return "", fmt.Errorf("Problem reading user data file: %s", err)
|
||||
}
|
||||
|
||||
reqParams.InitScriptContent = ncloud.String(string(contents))
|
||||
}
|
||||
|
||||
if reqParams.InitScriptContent == nil {
|
||||
return "", nil
|
||||
}
|
||||
|
||||
resp, err := s.Conn.vserver.V2Api.CreateInitScript(reqParams)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
|
||||
return *resp.InitScriptList[0].InitScriptNo, nil
|
||||
}
|
||||
|
||||
func (s *StepCreateInitScript) deleteVpcInitScript(initScriptNo string) error {
|
||||
reqParams := &vserver.DeleteInitScriptsRequest{
|
||||
RegionCode: &s.Config.RegionCode,
|
||||
InitScriptNoList: []*string{&initScriptNo},
|
||||
}
|
||||
_, err := s.Conn.vserver.V2Api.DeleteInitScripts(reqParams)
|
||||
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (s *StepCreateInitScript) Run(ctx context.Context, state multistep.StateBag) multistep.StepAction {
|
||||
s.Say("Create Init script")
|
||||
|
||||
initScriptNo, err := s.CreateInitScript()
|
||||
if err == nil && initScriptNo != "" {
|
||||
state.Put("init_script_no", initScriptNo)
|
||||
s.Say(fmt.Sprintf("Init script[%s] is created", initScriptNo))
|
||||
}
|
||||
|
||||
return processStepResult(err, s.Error, state)
|
||||
}
|
||||
|
||||
func (s *StepCreateInitScript) Cleanup(state multistep.StateBag) {
|
||||
if initScriptNo, ok := state.GetOk("init_script_no"); ok {
|
||||
s.Say("Cleanup Init script")
|
||||
if err := s.DeleteInitScript(initScriptNo.(string)); err != nil {
|
||||
s.Error(err)
|
||||
return
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,63 @@
|
|||
package ncloud
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"testing"
|
||||
|
||||
"github.com/hashicorp/packer-plugin-sdk/multistep"
|
||||
)
|
||||
|
||||
func TestStepCreateInitScriptShouldFailIfOperationCreateInitScriptFails(t *testing.T) {
|
||||
var testSubject = &StepCreateInitScript{
|
||||
CreateInitScript: func() (string, error) { return "", fmt.Errorf("!! Unit Test FAIL !!") },
|
||||
Say: func(message string) {},
|
||||
Error: func(e error) {},
|
||||
Config: &Config{
|
||||
Region: "KR",
|
||||
SupportVPC: true,
|
||||
},
|
||||
}
|
||||
|
||||
stateBag := createTestStateBagStepCreateInitScript()
|
||||
|
||||
var result = testSubject.Run(context.Background(), stateBag)
|
||||
|
||||
if result != multistep.ActionHalt {
|
||||
t.Fatalf("Expected the step to return 'ActionHalt', but got '%d'.", result)
|
||||
}
|
||||
|
||||
if _, ok := stateBag.GetOk("error"); ok == false {
|
||||
t.Fatal("Expected the step to set stateBag['Error'], but it was not.")
|
||||
}
|
||||
}
|
||||
|
||||
func TestStepCreateInitScriptShouldPassIfOperationCreateInitScriptPasses(t *testing.T) {
|
||||
var testSubject = &StepCreateInitScript{
|
||||
CreateInitScript: func() (string, error) { return "123", nil },
|
||||
Say: func(message string) {},
|
||||
Error: func(e error) {},
|
||||
Config: &Config{
|
||||
Region: "KR",
|
||||
SupportVPC: true,
|
||||
},
|
||||
}
|
||||
|
||||
stateBag := createTestStateBagStepCreateInitScript()
|
||||
|
||||
var result = testSubject.Run(context.Background(), stateBag)
|
||||
|
||||
if result != multistep.ActionContinue {
|
||||
t.Fatalf("Expected the step to return 'ActionContinue', but got '%d'.", result)
|
||||
}
|
||||
|
||||
if _, ok := stateBag.GetOk("error"); ok == true {
|
||||
t.Fatalf("Expected the step to not set stateBag['Error'], but it was.")
|
||||
}
|
||||
}
|
||||
|
||||
func createTestStateBagStepCreateInitScript() multistep.StateBag {
|
||||
stateBag := new(multistep.BasicStateBag)
|
||||
|
||||
return stateBag
|
||||
}
|
|
@ -6,6 +6,7 @@ import (
|
|||
"time"
|
||||
|
||||
"github.com/NaverCloudPlatform/ncloud-sdk-go-v2/services/server"
|
||||
"github.com/NaverCloudPlatform/ncloud-sdk-go-v2/services/vserver"
|
||||
"github.com/hashicorp/packer-plugin-sdk/multistep"
|
||||
packersdk "github.com/hashicorp/packer-plugin-sdk/packer"
|
||||
)
|
||||
|
@ -18,23 +19,32 @@ type LoginKey struct {
|
|||
type StepCreateLoginKey struct {
|
||||
Conn *NcloudAPIClient
|
||||
CreateLoginKey func() (*LoginKey, error)
|
||||
DeleteLoginKey func(loginKey string) error
|
||||
Say func(message string)
|
||||
Error func(e error)
|
||||
Config *Config
|
||||
}
|
||||
|
||||
func NewStepCreateLoginKey(conn *NcloudAPIClient, ui packersdk.Ui) *StepCreateLoginKey {
|
||||
func NewStepCreateLoginKey(conn *NcloudAPIClient, ui packersdk.Ui, config *Config) *StepCreateLoginKey {
|
||||
var step = &StepCreateLoginKey{
|
||||
Conn: conn,
|
||||
Say: func(message string) { ui.Say(message) },
|
||||
Error: func(e error) { ui.Error(e.Error()) },
|
||||
Conn: conn,
|
||||
Say: func(message string) { ui.Say(message) },
|
||||
Error: func(e error) { ui.Error(e.Error()) },
|
||||
Config: config,
|
||||
}
|
||||
|
||||
step.CreateLoginKey = step.createLoginKey
|
||||
if config.SupportVPC {
|
||||
step.CreateLoginKey = step.createVpcLoginKey
|
||||
step.DeleteLoginKey = step.deleteVpcLoginKey
|
||||
} else {
|
||||
step.CreateLoginKey = step.createClassicLoginKey
|
||||
step.DeleteLoginKey = step.deleteClassicLoginKey
|
||||
}
|
||||
|
||||
return step
|
||||
}
|
||||
|
||||
func (s *StepCreateLoginKey) createLoginKey() (*LoginKey, error) {
|
||||
func (s *StepCreateLoginKey) createClassicLoginKey() (*LoginKey, error) {
|
||||
keyName := fmt.Sprintf("packer-%d", time.Now().Unix())
|
||||
reqParams := &server.CreateLoginKeyRequest{KeyName: &keyName}
|
||||
|
||||
|
@ -46,12 +56,46 @@ func (s *StepCreateLoginKey) createLoginKey() (*LoginKey, error) {
|
|||
return &LoginKey{keyName, *privateKey.PrivateKey}, nil
|
||||
}
|
||||
|
||||
func (s *StepCreateLoginKey) createVpcLoginKey() (*LoginKey, error) {
|
||||
keyName := fmt.Sprintf("packer-%d", time.Now().Unix())
|
||||
reqParams := &vserver.CreateLoginKeyRequest{KeyName: &keyName}
|
||||
|
||||
privateKey, err := s.Conn.vserver.V2Api.CreateLoginKey(reqParams)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return &LoginKey{keyName, *privateKey.PrivateKey}, nil
|
||||
}
|
||||
|
||||
func (s *StepCreateLoginKey) deleteClassicLoginKey(keyName string) error {
|
||||
reqParams := &server.DeleteLoginKeyRequest{KeyName: &keyName}
|
||||
_, err := s.Conn.server.V2Api.DeleteLoginKey(reqParams)
|
||||
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (s *StepCreateLoginKey) deleteVpcLoginKey(keyName string) error {
|
||||
reqParams := &vserver.DeleteLoginKeysRequest{KeyNameList: []*string{&keyName}}
|
||||
_, err := s.Conn.vserver.V2Api.DeleteLoginKeys(reqParams)
|
||||
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (s *StepCreateLoginKey) Run(ctx context.Context, state multistep.StateBag) multistep.StepAction {
|
||||
s.Say("Create Login Key")
|
||||
|
||||
loginKey, err := s.CreateLoginKey()
|
||||
if err == nil {
|
||||
state.Put("LoginKey", loginKey)
|
||||
state.Put("login_key", loginKey)
|
||||
s.Say(fmt.Sprintf("Login Key[%s] is created", loginKey.KeyName))
|
||||
}
|
||||
|
||||
|
@ -59,9 +103,11 @@ func (s *StepCreateLoginKey) Run(ctx context.Context, state multistep.StateBag)
|
|||
}
|
||||
|
||||
func (s *StepCreateLoginKey) Cleanup(state multistep.StateBag) {
|
||||
if loginKey, ok := state.GetOk("LoginKey"); ok {
|
||||
if loginKey, ok := state.GetOk("login_key"); ok {
|
||||
s.Say("Clean up login key")
|
||||
reqParams := &server.DeleteLoginKeyRequest{KeyName: &loginKey.(*LoginKey).KeyName}
|
||||
s.Conn.server.V2Api.DeleteLoginKey(reqParams)
|
||||
if err := s.DeleteLoginKey(loginKey.(*LoginKey).KeyName); err != nil {
|
||||
s.Error(err)
|
||||
return
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -23,7 +23,7 @@ func TestStepCreateLoginKeyShouldFailIfOperationCreateLoginKeyFails(t *testing.T
|
|||
t.Fatalf("Expected the step to return 'ActionHalt', but got '%d'.", result)
|
||||
}
|
||||
|
||||
if _, ok := stateBag.GetOk("Error"); ok == false {
|
||||
if _, ok := stateBag.GetOk("error"); ok == false {
|
||||
t.Fatal("Expected the step to set stateBag['Error'], but it was not.")
|
||||
}
|
||||
}
|
||||
|
@ -43,7 +43,7 @@ func TestStepCreateLoginKeyShouldPassIfOperationCreateLoginKeyPasses(t *testing.
|
|||
t.Fatalf("Expected the step to return 'ActionContinue', but got '%d'.", result)
|
||||
}
|
||||
|
||||
if _, ok := stateBag.GetOk("Error"); ok == true {
|
||||
if _, ok := stateBag.GetOk("error"); ok == true {
|
||||
t.Fatalf("Expected the step to not set stateBag['Error'], but it was.")
|
||||
}
|
||||
}
|
||||
|
|
|
@ -3,6 +3,7 @@ package ncloud
|
|||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"github.com/NaverCloudPlatform/ncloud-sdk-go-v2/services/vserver"
|
||||
"log"
|
||||
"time"
|
||||
|
||||
|
@ -12,32 +13,103 @@ import (
|
|||
packersdk "github.com/hashicorp/packer-plugin-sdk/packer"
|
||||
)
|
||||
|
||||
type StepCreatePublicIPInstance struct {
|
||||
const (
|
||||
PublicIpStatusUsed = "USED"
|
||||
PublicIpStatusCreated = "CREAT"
|
||||
PublicIpStatusRunning = "RUN"
|
||||
)
|
||||
|
||||
type StepCreatePublicIP struct {
|
||||
Conn *NcloudAPIClient
|
||||
CreatePublicIPInstance func(serverInstanceNo string) (*server.PublicIpInstance, error)
|
||||
GetPublicIP func(publicIPNo string) (*server.PublicIpInstance, error)
|
||||
CreatePublicIP func(serverInstanceNo string) (*server.PublicIpInstance, error)
|
||||
DeletePublicIp func(publicIPNo string) error
|
||||
WaiterAssociatePublicIPToServerInstance func(serverInstanceNo string, publicIP string) error
|
||||
DisassociatePublicIpFromServerInstance func(publicIPNo string) error
|
||||
Say func(message string)
|
||||
Error func(e error)
|
||||
Config *Config
|
||||
}
|
||||
|
||||
func NewStepCreatePublicIPInstance(conn *NcloudAPIClient, ui packersdk.Ui, config *Config) *StepCreatePublicIPInstance {
|
||||
var step = &StepCreatePublicIPInstance{
|
||||
func NewStepCreatePublicIP(conn *NcloudAPIClient, ui packersdk.Ui, config *Config) *StepCreatePublicIP {
|
||||
var step = &StepCreatePublicIP{
|
||||
Conn: conn,
|
||||
Say: func(message string) { ui.Say(message) },
|
||||
Error: func(e error) { ui.Error(e.Error()) },
|
||||
Config: config,
|
||||
}
|
||||
|
||||
step.CreatePublicIPInstance = step.createPublicIPInstance
|
||||
step.WaiterAssociatePublicIPToServerInstance = step.waiterAssociatePublicIPToServerInstance
|
||||
if config.SupportVPC {
|
||||
step.GetPublicIP = step.getVpcPublicIP
|
||||
step.CreatePublicIP = step.createVpcPublicIP
|
||||
step.WaiterAssociatePublicIPToServerInstance = step.waiterAssociateVpcPublicIPToServerInstance
|
||||
step.DisassociatePublicIpFromServerInstance = step.disassociateVpcPublicIpFromServerInstance
|
||||
step.DeletePublicIp = step.deleteVpcPublicIp
|
||||
} else {
|
||||
step.GetPublicIP = step.getClassicPublicIP
|
||||
step.CreatePublicIP = step.createClassicPublicIP
|
||||
step.WaiterAssociatePublicIPToServerInstance = step.waiterAssociateClassicPublicIPToServerInstance
|
||||
step.DisassociatePublicIpFromServerInstance = step.disassociateClassicPublicIpFromServerInstance
|
||||
step.DeletePublicIp = step.deleteClassicPublicIp
|
||||
}
|
||||
|
||||
return step
|
||||
}
|
||||
|
||||
func (s *StepCreatePublicIPInstance) waiterAssociatePublicIPToServerInstance(serverInstanceNo string, publicIP string) error {
|
||||
reqParams := new(server.GetServerInstanceListRequest)
|
||||
reqParams.ServerInstanceNoList = []*string{&serverInstanceNo}
|
||||
func (s *StepCreatePublicIP) getClassicPublicIP(publicIPNo string) (*server.PublicIpInstance, error) {
|
||||
reqParams := &server.GetPublicIpInstanceListRequest{
|
||||
PublicIpInstanceNoList: []*string{&publicIPNo},
|
||||
}
|
||||
|
||||
resp, err := s.Conn.server.V2Api.GetPublicIpInstanceList(reqParams)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
if resp != nil && *resp.TotalRows > 0 {
|
||||
return resp.PublicIpInstanceList[0], nil
|
||||
}
|
||||
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
func (s *StepCreatePublicIP) getVpcPublicIP(publicIPNo string) (*server.PublicIpInstance, error) {
|
||||
reqParams := &vserver.GetPublicIpInstanceDetailRequest{
|
||||
RegionCode: &s.Config.RegionCode,
|
||||
PublicIpInstanceNo: &publicIPNo,
|
||||
}
|
||||
|
||||
resp, err := s.Conn.vserver.V2Api.GetPublicIpInstanceDetail(reqParams)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
if resp != nil && *resp.TotalRows > 0 {
|
||||
inst := resp.PublicIpInstanceList[0]
|
||||
return &server.PublicIpInstance{
|
||||
PublicIpInstanceNo: inst.PublicIpInstanceNo,
|
||||
PublicIp: inst.PublicIp,
|
||||
PublicIpInstanceStatus: &server.CommonCode{
|
||||
Code: inst.PublicIpInstanceStatus.Code,
|
||||
CodeName: inst.PublicIpInstanceStatus.CodeName,
|
||||
},
|
||||
PublicIpInstanceOperation: &server.CommonCode{
|
||||
Code: inst.PublicIpInstanceOperation.Code,
|
||||
CodeName: inst.PublicIpInstanceOperation.CodeName,
|
||||
},
|
||||
ServerInstanceAssociatedWithPublicIp: &server.ServerInstance{
|
||||
ServerInstanceNo: inst.ServerInstanceNo,
|
||||
},
|
||||
}, nil
|
||||
}
|
||||
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
func (s *StepCreatePublicIP) waiterAssociateClassicPublicIPToServerInstance(serverInstanceNo string, publicIP string) error {
|
||||
reqParams := &server.GetServerInstanceListRequest{
|
||||
ServerInstanceNoList: []*string{&serverInstanceNo},
|
||||
}
|
||||
|
||||
c1 := make(chan error, 1)
|
||||
|
||||
|
@ -68,9 +140,45 @@ func (s *StepCreatePublicIPInstance) waiterAssociatePublicIPToServerInstance(ser
|
|||
}
|
||||
}
|
||||
|
||||
func (s *StepCreatePublicIPInstance) createPublicIPInstance(serverInstanceNo string) (*server.PublicIpInstance, error) {
|
||||
reqParams := new(server.CreatePublicIpInstanceRequest)
|
||||
reqParams.ServerInstanceNo = &serverInstanceNo
|
||||
func (s *StepCreatePublicIP) waiterAssociateVpcPublicIPToServerInstance(serverInstanceNo string, publicIP string) error {
|
||||
reqParams := &vserver.GetServerInstanceDetailRequest{
|
||||
RegionCode: &s.Config.RegionCode,
|
||||
ServerInstanceNo: &serverInstanceNo,
|
||||
}
|
||||
|
||||
c1 := make(chan error, 1)
|
||||
|
||||
go func() {
|
||||
for {
|
||||
serverInstanceList, err := s.Conn.vserver.V2Api.GetServerInstanceDetail(reqParams)
|
||||
|
||||
if err != nil {
|
||||
c1 <- err
|
||||
return
|
||||
}
|
||||
|
||||
if publicIP == *serverInstanceList.ServerInstanceList[0].PublicIp {
|
||||
c1 <- nil
|
||||
return
|
||||
}
|
||||
|
||||
s.Say("Wait to associate public ip serverInstance")
|
||||
time.Sleep(time.Second * 3)
|
||||
}
|
||||
}()
|
||||
|
||||
select {
|
||||
case res := <-c1:
|
||||
return res
|
||||
case <-time.After(time.Second * 60):
|
||||
return fmt.Errorf("TIMEOUT : association public ip[%s] to server instance[%s] Failed", publicIP, serverInstanceNo)
|
||||
}
|
||||
}
|
||||
|
||||
func (s *StepCreatePublicIP) createClassicPublicIP(serverInstanceNo string) (*server.PublicIpInstance, error) {
|
||||
reqParams := &server.CreatePublicIpInstanceRequest{
|
||||
ServerInstanceNo: &serverInstanceNo,
|
||||
}
|
||||
|
||||
publicIPInstanceList, err := s.Conn.server.V2Api.CreatePublicIpInstance(reqParams)
|
||||
if err != nil {
|
||||
|
@ -81,7 +189,7 @@ func (s *StepCreatePublicIPInstance) createPublicIPInstance(serverInstanceNo str
|
|||
publicIP := publicIPInstance.PublicIp
|
||||
s.Say(fmt.Sprintf("Public IP Instance [%s:%s] is created", *publicIPInstance.PublicIpInstanceNo, *publicIP))
|
||||
|
||||
err = s.waiterAssociatePublicIPToServerInstance(serverInstanceNo, *publicIP)
|
||||
err = s.WaiterAssociatePublicIPToServerInstance(serverInstanceNo, *publicIP)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
@ -89,69 +197,49 @@ func (s *StepCreatePublicIPInstance) createPublicIPInstance(serverInstanceNo str
|
|||
return publicIPInstance, nil
|
||||
}
|
||||
|
||||
func (s *StepCreatePublicIPInstance) Run(ctx context.Context, state multistep.StateBag) multistep.StepAction {
|
||||
s.Say("Create Public IP Instance")
|
||||
|
||||
serverInstanceNo := state.Get("InstanceNo").(string)
|
||||
|
||||
publicIPInstance, err := s.CreatePublicIPInstance(serverInstanceNo)
|
||||
if err == nil {
|
||||
state.Put("PublicIP", *publicIPInstance.PublicIp)
|
||||
state.Put("PublicIPInstance", publicIPInstance)
|
||||
// instance_id is the generic term used so that users can have access to the
|
||||
// instance id inside of the provisioners, used in step_provision.
|
||||
state.Put("instance_id", *publicIPInstance)
|
||||
func (s *StepCreatePublicIP) createVpcPublicIP(serverInstanceNo string) (*server.PublicIpInstance, error) {
|
||||
reqParams := &vserver.CreatePublicIpInstanceRequest{
|
||||
RegionCode: &s.Config.RegionCode,
|
||||
ServerInstanceNo: &serverInstanceNo,
|
||||
}
|
||||
|
||||
return processStepResult(err, s.Error, state)
|
||||
publicIPInstanceList, err := s.Conn.vserver.V2Api.CreatePublicIpInstance(reqParams)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
publicIPInstance := publicIPInstanceList.PublicIpInstanceList[0]
|
||||
publicIP := publicIPInstance.PublicIp
|
||||
s.Say(fmt.Sprintf("Public IP Instance [%s:%s] is created", *publicIPInstance.PublicIpInstanceNo, *publicIP))
|
||||
|
||||
err = s.WaiterAssociatePublicIPToServerInstance(serverInstanceNo, *publicIP)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return &server.PublicIpInstance{
|
||||
PublicIpInstanceNo: publicIPInstance.PublicIpInstanceNo,
|
||||
PublicIp: publicIP,
|
||||
}, nil
|
||||
}
|
||||
|
||||
func (s *StepCreatePublicIPInstance) Cleanup(state multistep.StateBag) {
|
||||
publicIPInstance, ok := state.GetOk("PublicIPInstance")
|
||||
if !ok {
|
||||
return
|
||||
}
|
||||
|
||||
s.Say("Clean up Public IP Instance")
|
||||
publicIPInstanceNo := publicIPInstance.(*server.PublicIpInstance).PublicIpInstanceNo
|
||||
s.waitPublicIPInstanceStatus(publicIPInstanceNo, "USED")
|
||||
|
||||
log.Println("Disassociate Public IP Instance ", publicIPInstanceNo)
|
||||
reqParams := &server.DisassociatePublicIpFromServerInstanceRequest{PublicIpInstanceNo: publicIPInstanceNo}
|
||||
s.Conn.server.V2Api.DisassociatePublicIpFromServerInstance(reqParams)
|
||||
|
||||
s.waitPublicIPInstanceStatus(publicIPInstanceNo, "CREAT")
|
||||
|
||||
reqDeleteParams := &server.DeletePublicIpInstancesRequest{
|
||||
PublicIpInstanceNoList: ncloud.StringList([]string{*publicIPInstanceNo}),
|
||||
}
|
||||
|
||||
log.Println("Delete Public IP Instance ", publicIPInstanceNo)
|
||||
s.Conn.server.V2Api.DeletePublicIpInstances(reqDeleteParams)
|
||||
}
|
||||
|
||||
func (s *StepCreatePublicIPInstance) waitPublicIPInstanceStatus(publicIPInstanceNo *string, status string) {
|
||||
func (s *StepCreatePublicIP) waitPublicIPStatus(publicIPInstanceNo string, status string) error {
|
||||
c1 := make(chan error, 1)
|
||||
|
||||
go func() {
|
||||
reqParams := new(server.GetPublicIpInstanceListRequest)
|
||||
reqParams.PublicIpInstanceNoList = []*string{publicIPInstanceNo}
|
||||
|
||||
for {
|
||||
resp, err := s.Conn.server.V2Api.GetPublicIpInstanceList(reqParams)
|
||||
publicIp, err := s.GetPublicIP(publicIPInstanceNo)
|
||||
if err != nil {
|
||||
log.Printf(err.Error())
|
||||
c1 <- err
|
||||
return
|
||||
}
|
||||
|
||||
if *resp.TotalRows == 0 {
|
||||
if publicIp == nil {
|
||||
c1 <- nil
|
||||
return
|
||||
}
|
||||
|
||||
instance := resp.PublicIpInstanceList[0]
|
||||
if *instance.PublicIpInstanceStatus.Code == status && *instance.PublicIpInstanceOperation.Code == "NULL" {
|
||||
if *publicIp.PublicIpInstanceStatus.Code == status && *publicIp.PublicIpInstanceOperation.Code == "NULL" {
|
||||
c1 <- nil
|
||||
return
|
||||
}
|
||||
|
@ -162,8 +250,119 @@ func (s *StepCreatePublicIPInstance) waitPublicIPInstanceStatus(publicIPInstance
|
|||
|
||||
select {
|
||||
case <-c1:
|
||||
return
|
||||
return nil
|
||||
case <-time.After(time.Second * 60):
|
||||
return fmt.Errorf("TIMEOUT : wait for public ip[%s] to status[%s] Failed", publicIPInstanceNo, status)
|
||||
}
|
||||
}
|
||||
|
||||
func (s *StepCreatePublicIP) disassociateClassicPublicIpFromServerInstance(publicIPInstanceNo string) error {
|
||||
reqParams := &server.DisassociatePublicIpFromServerInstanceRequest{
|
||||
PublicIpInstanceNo: &publicIPInstanceNo,
|
||||
}
|
||||
|
||||
_, err := s.Conn.server.V2Api.DisassociatePublicIpFromServerInstance(reqParams)
|
||||
|
||||
return err
|
||||
}
|
||||
|
||||
func (s *StepCreatePublicIP) disassociateVpcPublicIpFromServerInstance(publicIPInstanceNo string) error {
|
||||
reqParams := &vserver.DisassociatePublicIpFromServerInstanceRequest{
|
||||
RegionCode: &s.Config.RegionCode,
|
||||
PublicIpInstanceNo: &publicIPInstanceNo,
|
||||
}
|
||||
|
||||
_, err := s.Conn.vserver.V2Api.DisassociatePublicIpFromServerInstance(reqParams)
|
||||
|
||||
return err
|
||||
}
|
||||
|
||||
func (s *StepCreatePublicIP) deleteClassicPublicIp(publicIPInstanceNo string) error {
|
||||
reqParams := &server.DeletePublicIpInstancesRequest{
|
||||
PublicIpInstanceNoList: ncloud.StringList([]string{publicIPInstanceNo}),
|
||||
}
|
||||
|
||||
_, err := s.Conn.server.V2Api.DeletePublicIpInstances(reqParams)
|
||||
|
||||
return err
|
||||
}
|
||||
|
||||
func (s *StepCreatePublicIP) deleteVpcPublicIp(publicIPInstanceNo string) error {
|
||||
reqParams := &vserver.DeletePublicIpInstanceRequest{
|
||||
RegionCode: &s.Config.RegionCode,
|
||||
PublicIpInstanceNo: &publicIPInstanceNo,
|
||||
}
|
||||
|
||||
_, err := s.Conn.vserver.V2Api.DeletePublicIpInstance(reqParams)
|
||||
|
||||
return err
|
||||
}
|
||||
|
||||
func (s *StepCreatePublicIP) Run(ctx context.Context, state multistep.StateBag) multistep.StepAction {
|
||||
s.Say("Create Public IP Instance")
|
||||
|
||||
serverInstanceNo := state.Get("instance_no").(string)
|
||||
|
||||
publicIPInstance, err := s.CreatePublicIP(serverInstanceNo)
|
||||
if err == nil {
|
||||
state.Put("public_ip", *publicIPInstance.PublicIp)
|
||||
state.Put("public_ip_instance", publicIPInstance)
|
||||
// instance_id is the generic term used so that users can have access to the
|
||||
// instance id inside of the provisioners, used in step_provision.
|
||||
state.Put("instance_id", *publicIPInstance)
|
||||
}
|
||||
|
||||
return processStepResult(err, s.Error, state)
|
||||
}
|
||||
|
||||
func (s *StepCreatePublicIP) Cleanup(state multistep.StateBag) {
|
||||
publicIPInstance, ok := state.GetOk("public_ip_instance")
|
||||
if !ok {
|
||||
return
|
||||
}
|
||||
|
||||
s.Say("Clean up Public IP Instance")
|
||||
publicIPInstanceNo := publicIPInstance.(*server.PublicIpInstance).PublicIpInstanceNo
|
||||
|
||||
publicIp, err := s.GetPublicIP(*publicIPInstanceNo)
|
||||
if err != nil {
|
||||
s.Error(err)
|
||||
}
|
||||
|
||||
if publicIp == nil {
|
||||
return
|
||||
}
|
||||
|
||||
publicIpUsedStatus := PublicIpStatusUsed
|
||||
publicIpCreatedStatus := PublicIpStatusCreated
|
||||
|
||||
if s.Config.SupportVPC {
|
||||
publicIpUsedStatus = PublicIpStatusRunning
|
||||
publicIpCreatedStatus = PublicIpStatusRunning
|
||||
}
|
||||
|
||||
if publicIp.ServerInstanceAssociatedWithPublicIp != nil &&
|
||||
publicIp.ServerInstanceAssociatedWithPublicIp.ServerInstanceNo != nil &&
|
||||
len(*publicIp.ServerInstanceAssociatedWithPublicIp.ServerInstanceNo) > 0 {
|
||||
if err := s.waitPublicIPStatus(*publicIPInstanceNo, publicIpUsedStatus); err != nil {
|
||||
s.Error(err)
|
||||
}
|
||||
|
||||
log.Println("Disassociate Public IP Instance ", publicIPInstanceNo)
|
||||
if err := s.DisassociatePublicIpFromServerInstance(*publicIPInstanceNo); err != nil {
|
||||
s.Error(err)
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
if err := s.waitPublicIPStatus(*publicIPInstanceNo, publicIpCreatedStatus); err != nil {
|
||||
s.Error(err)
|
||||
return
|
||||
}
|
||||
|
||||
log.Println("Delete Public IP Instance ", publicIPInstanceNo)
|
||||
if err := s.DeletePublicIp(*publicIPInstanceNo); err != nil {
|
||||
s.Error(err)
|
||||
return
|
||||
}
|
||||
}
|
||||
|
|
|
@ -12,8 +12,8 @@ import (
|
|||
)
|
||||
|
||||
func TestStepCreatePublicIPInstanceShouldFailIfOperationCreatePublicIPInstanceFails(t *testing.T) {
|
||||
var testSubject = &StepCreatePublicIPInstance{
|
||||
CreatePublicIPInstance: func(serverInstanceNo string) (*server.PublicIpInstance, error) {
|
||||
var testSubject = &StepCreatePublicIP{
|
||||
CreatePublicIP: func(serverInstanceNo string) (*server.PublicIpInstance, error) {
|
||||
return nil, fmt.Errorf("!! Unit Test FAIL !!")
|
||||
},
|
||||
Say: func(message string) {},
|
||||
|
@ -28,7 +28,7 @@ func TestStepCreatePublicIPInstanceShouldFailIfOperationCreatePublicIPInstanceFa
|
|||
t.Fatalf("Expected the step to return 'ActionHalt', but got '%d'.", result)
|
||||
}
|
||||
|
||||
if _, ok := stateBag.GetOk("Error"); ok == false {
|
||||
if _, ok := stateBag.GetOk("error"); ok == false {
|
||||
t.Fatal("Expected the step to set stateBag['Error'], but it was not.")
|
||||
}
|
||||
}
|
||||
|
@ -38,8 +38,8 @@ func TestStepCreatePublicIPInstanceShouldPassIfOperationCreatePublicIPInstancePa
|
|||
c.Comm.Prepare(nil)
|
||||
c.Comm.Type = "ssh"
|
||||
|
||||
var testSubject = &StepCreatePublicIPInstance{
|
||||
CreatePublicIPInstance: func(serverInstanceNo string) (*server.PublicIpInstance, error) {
|
||||
var testSubject = &StepCreatePublicIP{
|
||||
CreatePublicIP: func(serverInstanceNo string) (*server.PublicIpInstance, error) {
|
||||
return &server.PublicIpInstance{PublicIpInstanceNo: ncloud.String("a"), PublicIp: ncloud.String("b")}, nil
|
||||
},
|
||||
Say: func(message string) {},
|
||||
|
@ -55,7 +55,7 @@ func TestStepCreatePublicIPInstanceShouldPassIfOperationCreatePublicIPInstancePa
|
|||
t.Fatalf("Expected the step to return 'ActionContinue', but got '%d'.", result)
|
||||
}
|
||||
|
||||
if _, ok := stateBag.GetOk("Error"); ok == true {
|
||||
if _, ok := stateBag.GetOk("error"); ok == true {
|
||||
t.Fatalf("Expected the step to not set stateBag['Error'], but it was.")
|
||||
}
|
||||
}
|
||||
|
@ -63,7 +63,7 @@ func TestStepCreatePublicIPInstanceShouldPassIfOperationCreatePublicIPInstancePa
|
|||
func createTestStateBagStepCreatePublicIPInstance() multistep.StateBag {
|
||||
stateBag := new(multistep.BasicStateBag)
|
||||
|
||||
stateBag.Put("InstanceNo", "a")
|
||||
stateBag.Put("instance_no", "a")
|
||||
|
||||
return stateBag
|
||||
}
|
||||
|
|
|
@ -4,6 +4,7 @@ import (
|
|||
"context"
|
||||
"errors"
|
||||
"fmt"
|
||||
"github.com/NaverCloudPlatform/ncloud-sdk-go-v2/services/vserver"
|
||||
"time"
|
||||
|
||||
"github.com/NaverCloudPlatform/ncloud-sdk-go-v2/services/server"
|
||||
|
@ -11,6 +12,10 @@ import (
|
|||
packersdk "github.com/hashicorp/packer-plugin-sdk/packer"
|
||||
)
|
||||
|
||||
const (
|
||||
ServerImageStatusCreated = "CREAT"
|
||||
)
|
||||
|
||||
type StepCreateServerImage struct {
|
||||
Conn *NcloudAPIClient
|
||||
CreateServerImage func(serverInstanceNo string) (*server.MemberServerImage, error)
|
||||
|
@ -27,21 +32,26 @@ func NewStepCreateServerImage(conn *NcloudAPIClient, ui packersdk.Ui, config *Co
|
|||
Config: config,
|
||||
}
|
||||
|
||||
step.CreateServerImage = step.createServerImage
|
||||
if config.SupportVPC {
|
||||
step.CreateServerImage = step.createVpcServerImage
|
||||
} else {
|
||||
step.CreateServerImage = step.createClassicServerImage
|
||||
}
|
||||
|
||||
return step
|
||||
}
|
||||
|
||||
func (s *StepCreateServerImage) createServerImage(serverInstanceNo string) (*server.MemberServerImage, error) {
|
||||
func (s *StepCreateServerImage) createClassicServerImage(serverInstanceNo string) (*server.MemberServerImage, error) {
|
||||
// Can't create server image when status of server instance is stopping (not stopped)
|
||||
if err := waiterServerInstanceStatus(s.Conn, serverInstanceNo, "NSTOP", 1*time.Minute); err != nil {
|
||||
if err := waiterClassicServerInstanceStatus(s.Conn, serverInstanceNo, ServerInstanceStatusStopped, 1*time.Minute); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
reqParams := new(server.CreateMemberServerImageRequest)
|
||||
reqParams.MemberServerImageName = &s.Config.ServerImageName
|
||||
reqParams.MemberServerImageDescription = &s.Config.ServerImageDescription
|
||||
reqParams.ServerInstanceNo = &serverInstanceNo
|
||||
reqParams := &server.CreateMemberServerImageRequest{
|
||||
MemberServerImageName: &s.Config.ServerImageName,
|
||||
MemberServerImageDescription: &s.Config.ServerImageDescription,
|
||||
ServerInstanceNo: &serverInstanceNo,
|
||||
}
|
||||
|
||||
memberServerImageList, err := s.Conn.server.V2Api.CreateMemberServerImage(reqParams)
|
||||
if err != nil {
|
||||
|
@ -52,7 +62,7 @@ func (s *StepCreateServerImage) createServerImage(serverInstanceNo string) (*ser
|
|||
|
||||
s.Say(fmt.Sprintf("Server Image[%s:%s] is creating...", *serverImage.MemberServerImageName, *serverImage.MemberServerImageNo))
|
||||
|
||||
if err := waiterMemberServerImageStatus(s.Conn, *serverImage.MemberServerImageNo, "CREAT", 6*time.Hour); err != nil {
|
||||
if err := waiterClassicMemberServerImageStatus(s.Conn, *serverImage.MemberServerImageNo, ServerImageStatusCreated, 6*time.Hour); err != nil {
|
||||
return nil, errors.New("TIMEOUT : Server Image is not created")
|
||||
}
|
||||
|
||||
|
@ -61,14 +71,56 @@ func (s *StepCreateServerImage) createServerImage(serverInstanceNo string) (*ser
|
|||
return serverImage, nil
|
||||
}
|
||||
|
||||
func (s *StepCreateServerImage) createVpcServerImage(serverInstanceNo string) (*server.MemberServerImage, error) {
|
||||
// Can't create server image when status of server instance is stopping (not stopped)
|
||||
if err := waiterVpcServerInstanceStatus(s.Conn, serverInstanceNo, ServerInstanceStatusStopped, 1*time.Minute); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
reqParams := &vserver.CreateMemberServerImageInstanceRequest{
|
||||
MemberServerImageName: &s.Config.ServerImageName,
|
||||
MemberServerImageDescription: &s.Config.ServerImageDescription,
|
||||
ServerInstanceNo: &serverInstanceNo,
|
||||
}
|
||||
|
||||
memberServerImageList, err := s.Conn.vserver.V2Api.CreateMemberServerImageInstance(reqParams)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
serverImage := memberServerImageList.MemberServerImageInstanceList[0]
|
||||
|
||||
s.Say(fmt.Sprintf("Server Image[%s:%s] is creating...", *serverImage.MemberServerImageName, *serverImage.MemberServerImageInstanceNo))
|
||||
|
||||
if err := waiterVpcMemberServerImageStatus(s.Conn, *serverImage.MemberServerImageInstanceNo, ServerImageStatusCreated, 6*time.Hour); err != nil {
|
||||
return nil, errors.New("TIMEOUT : Server Image is not created")
|
||||
}
|
||||
|
||||
s.Say(fmt.Sprintf("Server Image[%s:%s] is created", *serverImage.MemberServerImageName, *serverImage.MemberServerImageInstanceNo))
|
||||
|
||||
result := &server.MemberServerImage{
|
||||
MemberServerImageNo: serverImage.MemberServerImageInstanceNo,
|
||||
MemberServerImageName: serverImage.MemberServerImageName,
|
||||
}
|
||||
|
||||
if serverImage.MemberServerImageInstanceStatus != nil {
|
||||
result.MemberServerImageStatus = &server.CommonCode{
|
||||
Code: serverImage.MemberServerImageInstanceStatus.Code,
|
||||
CodeName: serverImage.MemberServerImageInstanceStatus.CodeName,
|
||||
}
|
||||
}
|
||||
|
||||
return result, nil
|
||||
}
|
||||
|
||||
func (s *StepCreateServerImage) Run(ctx context.Context, state multistep.StateBag) multistep.StepAction {
|
||||
s.Say("Create Server Image")
|
||||
|
||||
serverInstanceNo := state.Get("InstanceNo").(string)
|
||||
serverInstanceNo := state.Get("instance_no").(string)
|
||||
|
||||
serverImage, err := s.CreateServerImage(serverInstanceNo)
|
||||
if err == nil {
|
||||
state.Put("memberServerImage", serverImage)
|
||||
state.Put("member_server_image", serverImage)
|
||||
}
|
||||
|
||||
return processStepResult(err, s.Error, state)
|
||||
|
|
|
@ -27,7 +27,7 @@ func TestStepCreateServerImageShouldFailIfOperationCreateServerImageFails(t *tes
|
|||
t.Fatalf("Expected the step to return 'ActionHalt', but got '%d'.", result)
|
||||
}
|
||||
|
||||
if _, ok := stateBag.GetOk("Error"); ok == false {
|
||||
if _, ok := stateBag.GetOk("error"); ok == false {
|
||||
t.Fatal("Expected the step to set stateBag['Error'], but it was not.")
|
||||
}
|
||||
}
|
||||
|
@ -46,7 +46,7 @@ func TestStepCreateServerImageShouldPassIfOperationCreateServerImagePasses(t *te
|
|||
t.Fatalf("Expected the step to return 'ActionContinue', but got '%d'.", result)
|
||||
}
|
||||
|
||||
if _, ok := stateBag.GetOk("Error"); ok == true {
|
||||
if _, ok := stateBag.GetOk("error"); ok == true {
|
||||
t.Fatalf("Expected the step to not set stateBag['Error'], but it was.")
|
||||
}
|
||||
}
|
||||
|
@ -54,7 +54,7 @@ func TestStepCreateServerImageShouldPassIfOperationCreateServerImagePasses(t *te
|
|||
func createTestStateBagStepCreateServerImage() multistep.StateBag {
|
||||
stateBag := new(multistep.BasicStateBag)
|
||||
|
||||
stateBag.Put("InstanceNo", "a")
|
||||
stateBag.Put("instance_no", "a")
|
||||
|
||||
return stateBag
|
||||
}
|
||||
|
|
|
@ -4,6 +4,7 @@ import (
|
|||
"context"
|
||||
"errors"
|
||||
"fmt"
|
||||
"github.com/NaverCloudPlatform/ncloud-sdk-go-v2/services/vserver"
|
||||
"io/ioutil"
|
||||
"log"
|
||||
"time"
|
||||
|
@ -14,14 +15,21 @@ import (
|
|||
packersdk "github.com/hashicorp/packer-plugin-sdk/packer"
|
||||
)
|
||||
|
||||
const (
|
||||
ServerInstanceStatusStopped = "NSTOP"
|
||||
ServerInstanceStatusTerminated = "TERMT"
|
||||
ServerInstanceStatusRunning = "RUN"
|
||||
)
|
||||
|
||||
type StepCreateServerInstance struct {
|
||||
Conn *NcloudAPIClient
|
||||
CreateServerInstance func(loginKeyName string, zoneNo string, feeSystemTypeCode string) (string, error)
|
||||
CheckServerInstanceStatusIsRunning func(serverInstanceNo string) error
|
||||
Say func(message string)
|
||||
Error func(e error)
|
||||
Config *Config
|
||||
serverInstanceNo string
|
||||
Conn *NcloudAPIClient
|
||||
CreateServerInstance func(loginKeyName string, feeSystemTypeCode string, state multistep.StateBag) (string, error)
|
||||
GetServerInstance func() (string, string, error)
|
||||
WaiterServerInstanceStatus func(conn *NcloudAPIClient, serverInstanceNo string, status string, timeout time.Duration) error
|
||||
Say func(message string)
|
||||
Error func(e error)
|
||||
Config *Config
|
||||
serverInstanceNo string
|
||||
}
|
||||
|
||||
func NewStepCreateServerInstance(conn *NcloudAPIClient, ui packersdk.Ui, config *Config) *StepCreateServerInstance {
|
||||
|
@ -32,21 +40,32 @@ func NewStepCreateServerInstance(conn *NcloudAPIClient, ui packersdk.Ui, config
|
|||
Config: config,
|
||||
}
|
||||
|
||||
step.CreateServerInstance = step.createServerInstance
|
||||
if config.SupportVPC {
|
||||
step.CreateServerInstance = step.createVpcServerInstance
|
||||
step.WaiterServerInstanceStatus = waiterVpcServerInstanceStatus
|
||||
step.GetServerInstance = step.getVpcServerInstance
|
||||
} else {
|
||||
step.CreateServerInstance = step.createClassicServerInstance
|
||||
step.WaiterServerInstanceStatus = waiterClassicServerInstanceStatus
|
||||
step.GetServerInstance = step.getClassicServerInstance
|
||||
}
|
||||
|
||||
return step
|
||||
}
|
||||
|
||||
func (s *StepCreateServerInstance) createServerInstance(loginKeyName string, zoneNo string, feeSystemTypeCode string) (string, error) {
|
||||
reqParams := new(server.CreateServerInstancesRequest)
|
||||
reqParams.ServerProductCode = &s.Config.ServerProductCode
|
||||
reqParams.MemberServerImageNo = &s.Config.MemberServerImageNo
|
||||
func (s *StepCreateServerInstance) createClassicServerInstance(loginKeyName string, feeSystemTypeCode string, state multistep.StateBag) (string, error) {
|
||||
var zoneNo = state.Get("zone_no").(string)
|
||||
|
||||
reqParams := &server.CreateServerInstancesRequest{
|
||||
ServerProductCode: &s.Config.ServerProductCode,
|
||||
MemberServerImageNo: &s.Config.MemberServerImageNo,
|
||||
LoginKeyName: &loginKeyName,
|
||||
ZoneNo: &zoneNo,
|
||||
FeeSystemTypeCode: &feeSystemTypeCode,
|
||||
}
|
||||
if s.Config.MemberServerImageNo == "" {
|
||||
reqParams.ServerImageProductCode = &s.Config.ServerImageProductCode
|
||||
}
|
||||
reqParams.LoginKeyName = &loginKeyName
|
||||
reqParams.ZoneNo = &zoneNo
|
||||
reqParams.FeeSystemTypeCode = &feeSystemTypeCode
|
||||
|
||||
if s.Config.UserData != "" {
|
||||
reqParams.UserData = &s.Config.UserData
|
||||
|
@ -74,7 +93,7 @@ func (s *StepCreateServerInstance) createServerInstance(loginKeyName string, zon
|
|||
s.Say(fmt.Sprintf("Server Instance is creating. Server InstanceNo is %s", s.serverInstanceNo))
|
||||
log.Println("Server Instance information : ", serverInstanceList.ServerInstanceList[0])
|
||||
|
||||
if err := waiterServerInstanceStatus(s.Conn, s.serverInstanceNo, "RUN", 30*time.Minute); err != nil {
|
||||
if err := s.WaiterServerInstanceStatus(s.Conn, s.serverInstanceNo, ServerInstanceStatusRunning, 30*time.Minute); err != nil {
|
||||
return "", errors.New("TIMEOUT : server instance status is not running")
|
||||
}
|
||||
|
||||
|
@ -83,20 +102,133 @@ func (s *StepCreateServerInstance) createServerInstance(loginKeyName string, zon
|
|||
return s.serverInstanceNo, nil
|
||||
}
|
||||
|
||||
func (s *StepCreateServerInstance) Run(ctx context.Context, state multistep.StateBag) multistep.StepAction {
|
||||
s.Say("Create Server Instance")
|
||||
func (s *StepCreateServerInstance) createVpcServerInstance(loginKeyName string, feeSystemTypeCode string, state multistep.StateBag) (string, error) {
|
||||
var initScriptNo string
|
||||
var acgNo string
|
||||
var err error
|
||||
|
||||
var loginKey = state.Get("LoginKey").(*LoginKey)
|
||||
var zoneNo = state.Get("ZoneNo").(string)
|
||||
|
||||
feeSystemTypeCode := "MTRAT"
|
||||
if _, ok := state.GetOk("FeeSystemTypeCode"); ok {
|
||||
feeSystemTypeCode = state.Get("FeeSystemTypeCode").(string)
|
||||
if v, ok := state.GetOk("init_script_no"); ok {
|
||||
initScriptNo = v.(string)
|
||||
}
|
||||
|
||||
serverInstanceNo, err := s.CreateServerInstance(loginKey.KeyName, zoneNo, feeSystemTypeCode)
|
||||
if s.Config.AccessControlGroupConfigurationNo != "" {
|
||||
acgNo = s.Config.AccessControlGroupConfigurationNo
|
||||
} else {
|
||||
acgNo, err = s.getDefaultAccessControlGroup(s.Config.VpcNo)
|
||||
}
|
||||
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
|
||||
reqParams := &vserver.CreateServerInstancesRequest{
|
||||
RegionCode: &s.Config.RegionCode,
|
||||
ServerProductCode: &s.Config.ServerProductCode,
|
||||
MemberServerImageInstanceNo: &s.Config.MemberServerImageNo,
|
||||
LoginKeyName: &loginKeyName,
|
||||
FeeSystemTypeCode: &feeSystemTypeCode,
|
||||
InitScriptNo: &initScriptNo,
|
||||
VpcNo: &s.Config.VpcNo,
|
||||
SubnetNo: &s.Config.SubnetNo,
|
||||
NetworkInterfaceList: []*vserver.NetworkInterfaceParameter{{
|
||||
NetworkInterfaceOrder: ncloud.Int32(0),
|
||||
AccessControlGroupNoList: []*string{ncloud.String(acgNo)}},
|
||||
},
|
||||
}
|
||||
|
||||
if s.Config.MemberServerImageNo == "" {
|
||||
reqParams.ServerImageProductCode = &s.Config.ServerImageProductCode
|
||||
}
|
||||
|
||||
serverInstanceList, err := s.Conn.vserver.V2Api.CreateServerInstances(reqParams)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
|
||||
s.serverInstanceNo = *serverInstanceList.ServerInstanceList[0].ServerInstanceNo
|
||||
s.Say(fmt.Sprintf("Server Instance is creating. Server InstanceNo is %s", s.serverInstanceNo))
|
||||
log.Println("Server Instance information : ", serverInstanceList.ServerInstanceList[0])
|
||||
|
||||
if err := s.WaiterServerInstanceStatus(s.Conn, s.serverInstanceNo, ServerInstanceStatusRunning, 30*time.Minute); err != nil {
|
||||
return "", errors.New("TIMEOUT : server instance status is not running")
|
||||
}
|
||||
|
||||
s.Say(fmt.Sprintf("Server Instance is created. Server InstanceNo is %s", s.serverInstanceNo))
|
||||
|
||||
return s.serverInstanceNo, nil
|
||||
}
|
||||
|
||||
func (s *StepCreateServerInstance) getDefaultAccessControlGroup(id string) (string, error) {
|
||||
reqParams := &vserver.GetAccessControlGroupListRequest{
|
||||
RegionCode: &s.Config.RegionCode,
|
||||
VpcNo: ncloud.String(id),
|
||||
}
|
||||
|
||||
resp, err := s.Conn.vserver.V2Api.GetAccessControlGroupList(reqParams)
|
||||
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
|
||||
if resp == nil || len(resp.AccessControlGroupList) == 0 {
|
||||
return "", fmt.Errorf("no matching Access Control Group found")
|
||||
}
|
||||
|
||||
for _, i := range resp.AccessControlGroupList {
|
||||
if *i.IsDefault {
|
||||
return *i.AccessControlGroupNo, nil
|
||||
}
|
||||
}
|
||||
|
||||
return "", fmt.Errorf("no matching default Access Control Group found")
|
||||
}
|
||||
|
||||
func (s *StepCreateServerInstance) getClassicServerInstance() (string, string, error) {
|
||||
reqParams := &server.GetServerInstanceListRequest{
|
||||
ServerInstanceNoList: []*string{&s.serverInstanceNo},
|
||||
}
|
||||
|
||||
resp, err := s.Conn.server.V2Api.GetServerInstanceList(reqParams)
|
||||
if err != nil {
|
||||
return "", "", err
|
||||
}
|
||||
|
||||
if *resp.TotalRows > 0 {
|
||||
return *resp.ServerInstanceList[0].ServerInstanceNo, *resp.ServerInstanceList[0].ServerInstanceStatus.Code, nil
|
||||
} else {
|
||||
return "", "", nil
|
||||
}
|
||||
}
|
||||
|
||||
func (s *StepCreateServerInstance) getVpcServerInstance() (string, string, error) {
|
||||
reqParams := &vserver.GetServerInstanceDetailRequest{
|
||||
ServerInstanceNo: &s.serverInstanceNo,
|
||||
}
|
||||
|
||||
resp, err := s.Conn.vserver.V2Api.GetServerInstanceDetail(reqParams)
|
||||
if err != nil {
|
||||
return "", "", err
|
||||
}
|
||||
|
||||
if *resp.TotalRows > 0 {
|
||||
return *resp.ServerInstanceList[0].ServerInstanceNo, *resp.ServerInstanceList[0].ServerInstanceStatus.Code, nil
|
||||
} else {
|
||||
return "", "", nil
|
||||
}
|
||||
}
|
||||
|
||||
func (s *StepCreateServerInstance) Run(ctx context.Context, state multistep.StateBag) multistep.StepAction {
|
||||
s.Say("Create Server Instance")
|
||||
var loginKey = state.Get("login_key").(*LoginKey)
|
||||
|
||||
feeSystemTypeCode := "MTRAT"
|
||||
if _, ok := state.GetOk("fee_system_type_code"); ok {
|
||||
feeSystemTypeCode = state.Get("fee_system_type_code").(string)
|
||||
}
|
||||
|
||||
serverInstanceNo, err := s.CreateServerInstance(loginKey.KeyName, feeSystemTypeCode, state)
|
||||
if err == nil {
|
||||
state.Put("InstanceNo", serverInstanceNo)
|
||||
state.Put("instance_no", serverInstanceNo)
|
||||
// instance_id is the generic term used so that users can have access to the
|
||||
// instance id inside of the provisioners, used in step_provision.
|
||||
state.Put("instance_id", serverInstanceNo)
|
||||
|
@ -108,6 +240,7 @@ func (s *StepCreateServerInstance) Run(ctx context.Context, state multistep.Stat
|
|||
func (s *StepCreateServerInstance) Cleanup(state multistep.StateBag) {
|
||||
_, cancelled := state.GetOk(multistep.StateCancelled)
|
||||
_, halted := state.GetOk(multistep.StateHalted)
|
||||
ui := state.Get("ui").(packersdk.Ui)
|
||||
|
||||
if !cancelled && !halted {
|
||||
return
|
||||
|
@ -117,33 +250,31 @@ func (s *StepCreateServerInstance) Cleanup(state multistep.StateBag) {
|
|||
return
|
||||
}
|
||||
|
||||
reqParams := new(server.GetServerInstanceListRequest)
|
||||
reqParams.ServerInstanceNoList = []*string{&s.serverInstanceNo}
|
||||
_, status, err := s.GetServerInstance()
|
||||
|
||||
serverInstanceList, err := s.Conn.server.V2Api.GetServerInstanceList(reqParams)
|
||||
if err != nil || *serverInstanceList.TotalRows == 0 {
|
||||
if err != nil || len(status) == 0 {
|
||||
return
|
||||
}
|
||||
|
||||
s.Say("Clean up Server Instance")
|
||||
|
||||
serverInstance := serverInstanceList.ServerInstanceList[0]
|
||||
// stop server instance
|
||||
if *serverInstance.ServerInstanceStatus.Code != "NSTOP" && *serverInstance.ServerInstanceStatus.Code != "TERMT" {
|
||||
reqParams := new(server.StopServerInstancesRequest)
|
||||
reqParams.ServerInstanceNoList = []*string{&s.serverInstanceNo}
|
||||
|
||||
log.Println("Stop Server Instance")
|
||||
s.Conn.server.V2Api.StopServerInstances(reqParams)
|
||||
waiterServerInstanceStatus(s.Conn, s.serverInstanceNo, "NSTOP", time.Minute)
|
||||
if status != ServerInstanceStatusStopped && status != ServerInstanceStatusTerminated {
|
||||
stepStopServerInstance := NewStepStopServerInstance(s.Conn, ui, s.Config)
|
||||
err := stepStopServerInstance.StopServerInstance(s.serverInstanceNo)
|
||||
if err != nil {
|
||||
s.Error(err)
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
// terminate server instance
|
||||
if *serverInstance.ServerInstanceStatus.Code != "TERMT" {
|
||||
reqParams := new(server.TerminateServerInstancesRequest)
|
||||
reqParams.ServerInstanceNoList = []*string{&s.serverInstanceNo}
|
||||
|
||||
log.Println("Terminate Server Instance")
|
||||
s.Conn.server.V2Api.TerminateServerInstances(reqParams)
|
||||
if status != ServerInstanceStatusTerminated {
|
||||
stepStopServerInstance := NewStepTerminateServerInstance(s.Conn, ui, s.Config)
|
||||
err := stepStopServerInstance.TerminateServerInstance(s.serverInstanceNo)
|
||||
if err != nil {
|
||||
s.Error(err)
|
||||
return
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -10,7 +10,7 @@ import (
|
|||
|
||||
func TestStepCreateServerInstanceShouldFailIfOperationCreateFails(t *testing.T) {
|
||||
var testSubject = &StepCreateServerInstance{
|
||||
CreateServerInstance: func(loginKeyName string, zoneNo string, feeSystemTypeCode string) (string, error) {
|
||||
CreateServerInstance: func(loginKeyName string, feeSystemTypeCode string, state multistep.StateBag) (string, error) {
|
||||
return "", fmt.Errorf("!! Unit Test FAIL !!")
|
||||
},
|
||||
Say: func(message string) {},
|
||||
|
@ -25,16 +25,18 @@ func TestStepCreateServerInstanceShouldFailIfOperationCreateFails(t *testing.T)
|
|||
t.Fatalf("Expected the step to return 'ActionHalt', but got '%d'.", result)
|
||||
}
|
||||
|
||||
if _, ok := stateBag.GetOk("Error"); ok == false {
|
||||
if _, ok := stateBag.GetOk("error"); ok == false {
|
||||
t.Fatal("Expected the step to set stateBag['Error'], but it was not.")
|
||||
}
|
||||
}
|
||||
|
||||
func TestStepCreateServerInstanceShouldPassIfOperationCreatePasses(t *testing.T) {
|
||||
var testSubject = &StepCreateServerInstance{
|
||||
CreateServerInstance: func(loginKeyName string, zoneNo string, feeSystemTypeCode string) (string, error) { return "", nil },
|
||||
Say: func(message string) {},
|
||||
Error: func(e error) {},
|
||||
CreateServerInstance: func(loginKeyName string, feeSystemTypeCode string, state multistep.StateBag) (string, error) {
|
||||
return "", nil
|
||||
},
|
||||
Say: func(message string) {},
|
||||
Error: func(e error) {},
|
||||
}
|
||||
|
||||
stateBag := createTestStateBagStepCreateServerInstance()
|
||||
|
@ -45,7 +47,7 @@ func TestStepCreateServerInstanceShouldPassIfOperationCreatePasses(t *testing.T)
|
|||
t.Fatalf("Expected the step to return 'ActionContinue', but got '%d'.", result)
|
||||
}
|
||||
|
||||
if _, ok := stateBag.GetOk("Error"); ok == true {
|
||||
if _, ok := stateBag.GetOk("error"); ok == true {
|
||||
t.Fatalf("Expected the step to not set stateBag['Error'], but it was.")
|
||||
}
|
||||
}
|
||||
|
@ -53,8 +55,8 @@ func TestStepCreateServerInstanceShouldPassIfOperationCreatePasses(t *testing.T)
|
|||
func createTestStateBagStepCreateServerInstance() multistep.StateBag {
|
||||
stateBag := new(multistep.BasicStateBag)
|
||||
|
||||
stateBag.Put("LoginKey", &LoginKey{"a", "b"})
|
||||
stateBag.Put("ZoneNo", "1")
|
||||
stateBag.Put("login_key", &LoginKey{"a", "b"})
|
||||
stateBag.Put("zone_no", "1")
|
||||
|
||||
return stateBag
|
||||
}
|
||||
|
|
|
@ -4,6 +4,7 @@ import (
|
|||
"context"
|
||||
"errors"
|
||||
"fmt"
|
||||
"github.com/NaverCloudPlatform/ncloud-sdk-go-v2/services/vserver"
|
||||
"log"
|
||||
"time"
|
||||
|
||||
|
@ -12,30 +13,35 @@ import (
|
|||
packersdk "github.com/hashicorp/packer-plugin-sdk/packer"
|
||||
)
|
||||
|
||||
type StepDeleteBlockStorageInstance struct {
|
||||
Conn *NcloudAPIClient
|
||||
DeleteBlockStorageInstance func(blockStorageInstanceNo string) error
|
||||
Say func(message string)
|
||||
Error func(e error)
|
||||
Config *Config
|
||||
type StepDeleteBlockStorage struct {
|
||||
Conn *NcloudAPIClient
|
||||
DeleteBlockStorage func(blockStorageNo string) error
|
||||
Say func(message string)
|
||||
Error func(e error)
|
||||
Config *Config
|
||||
}
|
||||
|
||||
func NewStepDeleteBlockStorageInstance(conn *NcloudAPIClient, ui packersdk.Ui, config *Config) *StepDeleteBlockStorageInstance {
|
||||
var step = &StepDeleteBlockStorageInstance{
|
||||
func NewStepDeleteBlockStorage(conn *NcloudAPIClient, ui packersdk.Ui, config *Config) *StepDeleteBlockStorage {
|
||||
var step = &StepDeleteBlockStorage{
|
||||
Conn: conn,
|
||||
Say: func(message string) { ui.Say(message) },
|
||||
Error: func(e error) { ui.Error(e.Error()) },
|
||||
Config: config,
|
||||
}
|
||||
|
||||
step.DeleteBlockStorageInstance = step.deleteBlockStorageInstance
|
||||
if config.SupportVPC {
|
||||
step.DeleteBlockStorage = step.deleteVpcBlockStorage
|
||||
} else {
|
||||
step.DeleteBlockStorage = step.deleteClassicBlockStorage
|
||||
}
|
||||
|
||||
return step
|
||||
}
|
||||
|
||||
func (s *StepDeleteBlockStorageInstance) getBlockInstanceList(serverInstanceNo string) []*string {
|
||||
reqParams := new(server.GetBlockStorageInstanceListRequest)
|
||||
reqParams.ServerInstanceNo = &serverInstanceNo
|
||||
func (s *StepDeleteBlockStorage) getClassicBlockList(serverInstanceNo string) []*string {
|
||||
reqParams := &server.GetBlockStorageInstanceListRequest{
|
||||
ServerInstanceNo: &serverInstanceNo,
|
||||
}
|
||||
|
||||
blockStorageInstanceList, err := s.Conn.server.V2Api.GetBlockStorageInstanceList(reqParams)
|
||||
if err != nil {
|
||||
|
@ -58,8 +64,34 @@ func (s *StepDeleteBlockStorageInstance) getBlockInstanceList(serverInstanceNo s
|
|||
return instanceList
|
||||
}
|
||||
|
||||
func (s *StepDeleteBlockStorageInstance) deleteBlockStorageInstance(serverInstanceNo string) error {
|
||||
blockStorageInstanceList := s.getBlockInstanceList(serverInstanceNo)
|
||||
func (s *StepDeleteBlockStorage) getVpcBlockList(serverInstanceNo string) []*string {
|
||||
reqParams := &vserver.GetBlockStorageInstanceListRequest{
|
||||
ServerInstanceNo: &serverInstanceNo,
|
||||
}
|
||||
|
||||
blockStorageInstanceList, err := s.Conn.vserver.V2Api.GetBlockStorageInstanceList(reqParams)
|
||||
if err != nil {
|
||||
return nil
|
||||
}
|
||||
|
||||
if *blockStorageInstanceList.TotalRows == 1 {
|
||||
return nil
|
||||
}
|
||||
|
||||
var instanceList []*string
|
||||
|
||||
for _, blockStorageInstance := range blockStorageInstanceList.BlockStorageInstanceList {
|
||||
log.Println(blockStorageInstance)
|
||||
if *blockStorageInstance.BlockStorageType.Code != "BASIC" {
|
||||
instanceList = append(instanceList, blockStorageInstance.BlockStorageInstanceNo)
|
||||
}
|
||||
}
|
||||
|
||||
return instanceList
|
||||
}
|
||||
|
||||
func (s *StepDeleteBlockStorage) deleteClassicBlockStorage(serverInstanceNo string) error {
|
||||
blockStorageInstanceList := s.getClassicBlockList(serverInstanceNo)
|
||||
if blockStorageInstanceList == nil || len(blockStorageInstanceList) == 0 {
|
||||
return nil
|
||||
}
|
||||
|
@ -73,26 +105,48 @@ func (s *StepDeleteBlockStorageInstance) deleteBlockStorageInstance(serverInstan
|
|||
|
||||
s.Say(fmt.Sprintf("Block Storage Instance is deleted. Block Storage Instance List is %v", blockStorageInstanceList))
|
||||
|
||||
if err := waiterDetachedBlockStorageInstance(s.Conn, serverInstanceNo, time.Minute); err != nil {
|
||||
if err := waiterClassicDetachedBlockStorage(s.Conn, serverInstanceNo, time.Minute); err != nil {
|
||||
return errors.New("TIMEOUT : Block Storage instance status is not deattached")
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (s *StepDeleteBlockStorageInstance) Run(ctx context.Context, state multistep.StateBag) multistep.StepAction {
|
||||
func (s *StepDeleteBlockStorage) deleteVpcBlockStorage(serverInstanceNo string) error {
|
||||
blockStorageInstanceList := s.getVpcBlockList(serverInstanceNo)
|
||||
if blockStorageInstanceList == nil || len(blockStorageInstanceList) == 0 {
|
||||
return nil
|
||||
}
|
||||
reqParams := vserver.DeleteBlockStorageInstancesRequest{
|
||||
BlockStorageInstanceNoList: blockStorageInstanceList,
|
||||
}
|
||||
_, err := s.Conn.vserver.V2Api.DeleteBlockStorageInstances(&reqParams)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
s.Say(fmt.Sprintf("Block Storage Instance is deleted. Block Storage Instance List is %v", blockStorageInstanceList))
|
||||
|
||||
if err := waiterVpcDetachedBlockStorage(s.Conn, serverInstanceNo, time.Minute); err != nil {
|
||||
return errors.New("TIMEOUT : Block Storage instance status is not deattached")
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (s *StepDeleteBlockStorage) Run(ctx context.Context, state multistep.StateBag) multistep.StepAction {
|
||||
if s.Config.BlockStorageSize == 0 {
|
||||
return processStepResult(nil, s.Error, state)
|
||||
}
|
||||
|
||||
s.Say("Delete Block Storage Instance")
|
||||
|
||||
var serverInstanceNo = state.Get("InstanceNo").(string)
|
||||
var serverInstanceNo = state.Get("instance_no").(string)
|
||||
|
||||
err := s.DeleteBlockStorageInstance(serverInstanceNo)
|
||||
err := s.DeleteBlockStorage(serverInstanceNo)
|
||||
|
||||
return processStepResult(err, s.Error, state)
|
||||
}
|
||||
|
||||
func (*StepDeleteBlockStorageInstance) Cleanup(multistep.StateBag) {
|
||||
func (*StepDeleteBlockStorage) Cleanup(multistep.StateBag) {
|
||||
}
|
||||
|
|
|
@ -9,11 +9,11 @@ import (
|
|||
)
|
||||
|
||||
func TestStepDeleteBlockStorageInstanceShouldFailIfOperationDeleteBlockStorageInstanceFails(t *testing.T) {
|
||||
var testSubject = &StepDeleteBlockStorageInstance{
|
||||
DeleteBlockStorageInstance: func(blockStorageInstanceNo string) error { return fmt.Errorf("!! Unit Test FAIL !!") },
|
||||
Say: func(message string) {},
|
||||
Error: func(e error) {},
|
||||
Config: &Config{BlockStorageSize: 10},
|
||||
var testSubject = &StepDeleteBlockStorage{
|
||||
DeleteBlockStorage: func(blockStorageNo string) error { return fmt.Errorf("!! Unit Test FAIL !!") },
|
||||
Say: func(message string) {},
|
||||
Error: func(e error) {},
|
||||
Config: &Config{BlockStorageSize: 10},
|
||||
}
|
||||
|
||||
stateBag := createTestStateBagStepDeleteBlockStorageInstance()
|
||||
|
@ -24,17 +24,17 @@ func TestStepDeleteBlockStorageInstanceShouldFailIfOperationDeleteBlockStorageIn
|
|||
t.Fatalf("Expected the step to return 'ActionHalt', but got '%d'.", result)
|
||||
}
|
||||
|
||||
if _, ok := stateBag.GetOk("Error"); ok == false {
|
||||
if _, ok := stateBag.GetOk("error"); ok == false {
|
||||
t.Fatal("Expected the step to set stateBag['Error'], but it was not.")
|
||||
}
|
||||
}
|
||||
|
||||
func TestStepDeleteBlockStorageInstanceShouldPassIfOperationDeleteBlockStorageInstancePasses(t *testing.T) {
|
||||
var testSubject = &StepDeleteBlockStorageInstance{
|
||||
DeleteBlockStorageInstance: func(blockStorageInstanceNo string) error { return nil },
|
||||
Say: func(message string) {},
|
||||
Error: func(e error) {},
|
||||
Config: &Config{BlockStorageSize: 10},
|
||||
var testSubject = &StepDeleteBlockStorage{
|
||||
DeleteBlockStorage: func(blockStorageNo string) error { return nil },
|
||||
Say: func(message string) {},
|
||||
Error: func(e error) {},
|
||||
Config: &Config{BlockStorageSize: 10},
|
||||
}
|
||||
|
||||
stateBag := createTestStateBagStepDeleteBlockStorageInstance()
|
||||
|
@ -45,7 +45,7 @@ func TestStepDeleteBlockStorageInstanceShouldPassIfOperationDeleteBlockStorageIn
|
|||
t.Fatalf("Expected the step to return 'ActionContinue', but got '%d'.", result)
|
||||
}
|
||||
|
||||
if _, ok := stateBag.GetOk("Error"); ok == true {
|
||||
if _, ok := stateBag.GetOk("error"); ok == true {
|
||||
t.Fatalf("Expected the step to not set stateBag['Error'], but it was.")
|
||||
}
|
||||
}
|
||||
|
@ -53,7 +53,7 @@ func TestStepDeleteBlockStorageInstanceShouldPassIfOperationDeleteBlockStorageIn
|
|||
func createTestStateBagStepDeleteBlockStorageInstance() multistep.StateBag {
|
||||
stateBag := new(multistep.BasicStateBag)
|
||||
|
||||
stateBag.Put("InstanceNo", "1")
|
||||
stateBag.Put("instance_no", "1")
|
||||
|
||||
return stateBag
|
||||
}
|
||||
|
|
|
@ -3,6 +3,7 @@ package ncloud
|
|||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"github.com/NaverCloudPlatform/ncloud-sdk-go-v2/services/vserver"
|
||||
|
||||
"github.com/NaverCloudPlatform/ncloud-sdk-go-v2/services/server"
|
||||
"github.com/hashicorp/packer-plugin-sdk/multistep"
|
||||
|
@ -25,15 +26,20 @@ func NewStepGetRootPassword(conn *NcloudAPIClient, ui packersdk.Ui, config *Conf
|
|||
Config: config,
|
||||
}
|
||||
|
||||
step.GetRootPassword = step.getRootPassword
|
||||
if config.SupportVPC {
|
||||
step.GetRootPassword = step.getVpcRootPassword
|
||||
} else {
|
||||
step.GetRootPassword = step.getClassicRootPassword
|
||||
}
|
||||
|
||||
return step
|
||||
}
|
||||
|
||||
func (s *StepGetRootPassword) getRootPassword(serverInstanceNo string, privateKey string) (string, error) {
|
||||
reqParams := new(server.GetRootPasswordRequest)
|
||||
reqParams.ServerInstanceNo = &serverInstanceNo
|
||||
reqParams.PrivateKey = &privateKey
|
||||
func (s *StepGetRootPassword) getClassicRootPassword(serverInstanceNo string, privateKey string) (string, error) {
|
||||
reqParams := &server.GetRootPasswordRequest{
|
||||
ServerInstanceNo: &serverInstanceNo,
|
||||
PrivateKey: &privateKey,
|
||||
}
|
||||
|
||||
rootPassword, err := s.Conn.server.V2Api.GetRootPassword(reqParams)
|
||||
if err != nil {
|
||||
|
@ -45,11 +51,28 @@ func (s *StepGetRootPassword) getRootPassword(serverInstanceNo string, privateKe
|
|||
return *rootPassword.RootPassword, nil
|
||||
}
|
||||
|
||||
func (s *StepGetRootPassword) getVpcRootPassword(serverInstanceNo string, privateKey string) (string, error) {
|
||||
reqParams := &vserver.GetRootPasswordRequest{
|
||||
RegionCode: &s.Config.RegionCode,
|
||||
ServerInstanceNo: &serverInstanceNo,
|
||||
PrivateKey: &privateKey,
|
||||
}
|
||||
|
||||
rootPassword, err := s.Conn.vserver.V2Api.GetRootPassword(reqParams)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
|
||||
s.Say(fmt.Sprintf("Root password is %s", *rootPassword.RootPassword))
|
||||
|
||||
return *rootPassword.RootPassword, nil
|
||||
}
|
||||
|
||||
func (s *StepGetRootPassword) Run(ctx context.Context, state multistep.StateBag) multistep.StepAction {
|
||||
s.Say("Get Root Password")
|
||||
|
||||
serverInstanceNo := state.Get("InstanceNo").(string)
|
||||
loginKey := state.Get("LoginKey").(*LoginKey)
|
||||
serverInstanceNo := state.Get("instance_no").(string)
|
||||
loginKey := state.Get("login_key").(*LoginKey)
|
||||
|
||||
rootPassword, err := s.GetRootPassword(serverInstanceNo, loginKey.PrivateKey)
|
||||
|
||||
|
|
|
@ -24,7 +24,7 @@ func TestStepGetRootPasswordShouldFailIfOperationGetRootPasswordFails(t *testing
|
|||
t.Fatalf("Expected the step to return 'ActionHalt', but got '%d'.", result)
|
||||
}
|
||||
|
||||
if _, ok := stateBag.GetOk("Error"); ok == false {
|
||||
if _, ok := stateBag.GetOk("error"); ok == false {
|
||||
t.Fatal("Expected the step to set stateBag['Error'], but it was not.")
|
||||
}
|
||||
}
|
||||
|
@ -45,7 +45,7 @@ func TestStepGetRootPasswordShouldPassIfOperationGetRootPasswordPasses(t *testin
|
|||
t.Fatalf("Expected the step to return 'ActionContinue', but got '%d'.", result)
|
||||
}
|
||||
|
||||
if _, ok := stateBag.GetOk("Error"); ok == true {
|
||||
if _, ok := stateBag.GetOk("error"); ok == true {
|
||||
t.Fatalf("Expected the step to not set stateBag['Error'], but it was.")
|
||||
}
|
||||
}
|
||||
|
@ -53,8 +53,8 @@ func TestStepGetRootPasswordShouldPassIfOperationGetRootPasswordPasses(t *testin
|
|||
func DeleteTestStateBagStepGetRootPassword() multistep.StateBag {
|
||||
stateBag := new(multistep.BasicStateBag)
|
||||
|
||||
stateBag.Put("LoginKey", &LoginKey{"a", "b"})
|
||||
stateBag.Put("InstanceNo", "a")
|
||||
stateBag.Put("login_key", &LoginKey{"a", "b"})
|
||||
stateBag.Put("instance_no", "a")
|
||||
|
||||
return stateBag
|
||||
}
|
||||
|
|
|
@ -3,7 +3,7 @@ package ncloud
|
|||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"log"
|
||||
"github.com/NaverCloudPlatform/ncloud-sdk-go-v2/services/vserver"
|
||||
"time"
|
||||
|
||||
"github.com/NaverCloudPlatform/ncloud-sdk-go-v2/services/server"
|
||||
|
@ -12,27 +12,37 @@ import (
|
|||
)
|
||||
|
||||
type StepStopServerInstance struct {
|
||||
Conn *NcloudAPIClient
|
||||
StopServerInstance func(serverInstanceNo string) error
|
||||
Say func(message string)
|
||||
Error func(e error)
|
||||
Conn *NcloudAPIClient
|
||||
StopServerInstance func(serverInstanceNo string) error
|
||||
WaiterServerInstanceStatus func(conn *NcloudAPIClient, serverInstanceNo string, status string, timeout time.Duration) error
|
||||
Say func(message string)
|
||||
Error func(e error)
|
||||
Config *Config
|
||||
}
|
||||
|
||||
func NewStepStopServerInstance(conn *NcloudAPIClient, ui packersdk.Ui) *StepStopServerInstance {
|
||||
func NewStepStopServerInstance(conn *NcloudAPIClient, ui packersdk.Ui, config *Config) *StepStopServerInstance {
|
||||
var step = &StepStopServerInstance{
|
||||
Conn: conn,
|
||||
Say: func(message string) { ui.Say(message) },
|
||||
Error: func(e error) { ui.Error(e.Error()) },
|
||||
Conn: conn,
|
||||
Say: func(message string) { ui.Say(message) },
|
||||
Error: func(e error) { ui.Error(e.Error()) },
|
||||
Config: config,
|
||||
}
|
||||
|
||||
step.StopServerInstance = step.stopServerInstance
|
||||
if config.SupportVPC {
|
||||
step.StopServerInstance = step.stopVpcServerInstance
|
||||
step.WaiterServerInstanceStatus = waiterVpcServerInstanceStatus
|
||||
} else {
|
||||
step.StopServerInstance = step.stopClassicServerInstance
|
||||
step.WaiterServerInstanceStatus = waiterClassicServerInstanceStatus
|
||||
}
|
||||
|
||||
return step
|
||||
}
|
||||
|
||||
func (s *StepStopServerInstance) stopServerInstance(serverInstanceNo string) error {
|
||||
reqParams := new(server.StopServerInstancesRequest)
|
||||
reqParams.ServerInstanceNoList = []*string{&serverInstanceNo}
|
||||
func (s *StepStopServerInstance) stopClassicServerInstance(serverInstanceNo string) error {
|
||||
reqParams := &server.StopServerInstancesRequest{
|
||||
ServerInstanceNoList: []*string{&serverInstanceNo},
|
||||
}
|
||||
|
||||
serverInstanceList, err := s.Conn.server.V2Api.StopServerInstances(reqParams)
|
||||
if err != nil {
|
||||
|
@ -40,9 +50,30 @@ func (s *StepStopServerInstance) stopServerInstance(serverInstanceNo string) err
|
|||
}
|
||||
|
||||
s.Say(fmt.Sprintf("Server Instance is stopping. Server InstanceNo is %s", *serverInstanceList.ServerInstanceList[0].ServerInstanceNo))
|
||||
log.Println("Server Instance information : ", serverInstanceList.ServerInstanceList[0])
|
||||
|
||||
if err := waiterServerInstanceStatus(s.Conn, serverInstanceNo, "NSTOP", 5*time.Minute); err != nil {
|
||||
if err := s.WaiterServerInstanceStatus(s.Conn, serverInstanceNo, ServerInstanceStatusStopped, 5*time.Minute); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
s.Say(fmt.Sprintf("Server Instance stopped. Server InstanceNo is %s", *serverInstanceList.ServerInstanceList[0].ServerInstanceNo))
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (s *StepStopServerInstance) stopVpcServerInstance(serverInstanceNo string) error {
|
||||
reqParams := &vserver.StopServerInstancesRequest{
|
||||
RegionCode: &s.Config.RegionCode,
|
||||
ServerInstanceNoList: []*string{&serverInstanceNo},
|
||||
}
|
||||
|
||||
serverInstanceList, err := s.Conn.vserver.V2Api.StopServerInstances(reqParams)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
s.Say(fmt.Sprintf("Server Instance is stopping. Server InstanceNo is %s", *serverInstanceList.ServerInstanceList[0].ServerInstanceNo))
|
||||
|
||||
if err := s.WaiterServerInstanceStatus(s.Conn, serverInstanceNo, ServerInstanceStatusStopped, 5*time.Minute); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
|
@ -54,7 +85,7 @@ func (s *StepStopServerInstance) stopServerInstance(serverInstanceNo string) err
|
|||
func (s *StepStopServerInstance) Run(ctx context.Context, state multistep.StateBag) multistep.StepAction {
|
||||
s.Say("Stop Server Instance")
|
||||
|
||||
var serverInstanceNo = state.Get("InstanceNo").(string)
|
||||
var serverInstanceNo = state.Get("instance_no").(string)
|
||||
|
||||
err := s.StopServerInstance(serverInstanceNo)
|
||||
|
||||
|
|
|
@ -23,7 +23,7 @@ func TestStepStopServerInstanceShouldFailIfOperationStopFails(t *testing.T) {
|
|||
t.Fatalf("Expected the step to return 'ActionHalt', but got '%d'.", result)
|
||||
}
|
||||
|
||||
if _, ok := stateBag.GetOk("Error"); ok == false {
|
||||
if _, ok := stateBag.GetOk("error"); ok == false {
|
||||
t.Fatal("Expected the step to set stateBag['Error'], but it was not.")
|
||||
}
|
||||
}
|
||||
|
@ -43,7 +43,7 @@ func TestStepStopServerInstanceShouldPassIfOperationStopPasses(t *testing.T) {
|
|||
t.Fatalf("Expected the step to return 'ActionContinue', but got '%d'.", result)
|
||||
}
|
||||
|
||||
if _, ok := stateBag.GetOk("Error"); ok == true {
|
||||
if _, ok := stateBag.GetOk("error"); ok == true {
|
||||
t.Fatalf("Expected the step to not set stateBag['Error'], but it was.")
|
||||
}
|
||||
}
|
||||
|
@ -51,6 +51,6 @@ func TestStepStopServerInstanceShouldPassIfOperationStopPasses(t *testing.T) {
|
|||
func createTestStateBagStepStopServerInstance() multistep.StateBag {
|
||||
stateBag := new(multistep.BasicStateBag)
|
||||
|
||||
stateBag.Put("InstanceNo", "a")
|
||||
stateBag.Put("instance_no", "a")
|
||||
return stateBag
|
||||
}
|
||||
|
|
|
@ -3,6 +3,9 @@ package ncloud
|
|||
import (
|
||||
"context"
|
||||
"errors"
|
||||
"fmt"
|
||||
"github.com/NaverCloudPlatform/ncloud-sdk-go-v2/services/vserver"
|
||||
"log"
|
||||
"time"
|
||||
|
||||
"github.com/NaverCloudPlatform/ncloud-sdk-go-v2/services/server"
|
||||
|
@ -15,37 +18,45 @@ type StepTerminateServerInstance struct {
|
|||
TerminateServerInstance func(serverInstanceNo string) error
|
||||
Say func(message string)
|
||||
Error func(e error)
|
||||
Config *Config
|
||||
}
|
||||
|
||||
func NewStepTerminateServerInstance(conn *NcloudAPIClient, ui packersdk.Ui) *StepTerminateServerInstance {
|
||||
func NewStepTerminateServerInstance(conn *NcloudAPIClient, ui packersdk.Ui, config *Config) *StepTerminateServerInstance {
|
||||
var step = &StepTerminateServerInstance{
|
||||
Conn: conn,
|
||||
Say: func(message string) { ui.Say(message) },
|
||||
Error: func(e error) { ui.Error(e.Error()) },
|
||||
Conn: conn,
|
||||
Say: func(message string) { ui.Say(message) },
|
||||
Error: func(e error) { ui.Error(e.Error()) },
|
||||
Config: config,
|
||||
}
|
||||
|
||||
step.TerminateServerInstance = step.terminateServerInstance
|
||||
if config.SupportVPC {
|
||||
step.TerminateServerInstance = step.terminateVpcServerInstance
|
||||
} else {
|
||||
step.TerminateServerInstance = step.terminateClassicServerInstance
|
||||
}
|
||||
|
||||
return step
|
||||
}
|
||||
|
||||
func (s *StepTerminateServerInstance) terminateServerInstance(serverInstanceNo string) error {
|
||||
reqParams := new(server.TerminateServerInstancesRequest)
|
||||
reqParams.ServerInstanceNoList = []*string{&serverInstanceNo}
|
||||
func (s *StepTerminateServerInstance) terminateClassicServerInstance(serverInstanceNo string) error {
|
||||
reqParams := &server.TerminateServerInstancesRequest{
|
||||
ServerInstanceNoList: []*string{&serverInstanceNo},
|
||||
}
|
||||
|
||||
_, err := s.Conn.server.V2Api.TerminateServerInstances(reqParams)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
s.Say(fmt.Sprintf("Server Instance is terminating. Server InstanceNo is %s", serverInstanceNo))
|
||||
|
||||
c1 := make(chan error, 1)
|
||||
|
||||
go func() {
|
||||
reqParams := new(server.GetServerInstanceListRequest)
|
||||
reqParams.ServerInstanceNoList = []*string{&serverInstanceNo}
|
||||
reqParams := &server.GetServerInstanceListRequest{
|
||||
ServerInstanceNoList: []*string{&serverInstanceNo},
|
||||
}
|
||||
|
||||
for {
|
||||
|
||||
serverInstanceList, err := s.Conn.server.V2Api.GetServerInstanceList(reqParams)
|
||||
if err != nil {
|
||||
c1 <- err
|
||||
|
@ -55,22 +66,67 @@ func (s *StepTerminateServerInstance) terminateServerInstance(serverInstanceNo s
|
|||
return
|
||||
}
|
||||
|
||||
log.Printf("Wating for terminating server instance [%s] is %s\n", serverInstanceNo, *serverInstanceList.ServerInstanceList[0].ServerInstanceStatus.Code)
|
||||
time.Sleep(time.Second * 3)
|
||||
}
|
||||
}()
|
||||
|
||||
select {
|
||||
case res := <-c1:
|
||||
s.Say(fmt.Sprintf("Server Instance terminated. Server InstanceNo is %s", serverInstanceNo))
|
||||
return res
|
||||
case <-time.After(time.Second * 60):
|
||||
return errors.New("TIMEOUT : Can't terminate server instance")
|
||||
}
|
||||
}
|
||||
|
||||
func (s *StepTerminateServerInstance) terminateVpcServerInstance(serverInstanceNo string) error {
|
||||
reqParams := &vserver.TerminateServerInstancesRequest{
|
||||
ServerInstanceNoList: []*string{&serverInstanceNo},
|
||||
}
|
||||
|
||||
_, err := s.Conn.vserver.V2Api.TerminateServerInstances(reqParams)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
s.Say(fmt.Sprintf("Server Instance is terminating. Server InstanceNo is %s", serverInstanceNo))
|
||||
|
||||
c1 := make(chan error, 1)
|
||||
|
||||
go func() {
|
||||
reqParams := &vserver.GetServerInstanceListRequest{
|
||||
RegionCode: &s.Config.RegionCode,
|
||||
ServerInstanceNoList: []*string{&serverInstanceNo},
|
||||
}
|
||||
|
||||
for {
|
||||
serverInstanceList, err := s.Conn.vserver.V2Api.GetServerInstanceList(reqParams)
|
||||
if err != nil {
|
||||
c1 <- err
|
||||
return
|
||||
} else if *serverInstanceList.TotalRows == 0 {
|
||||
c1 <- nil
|
||||
return
|
||||
}
|
||||
|
||||
log.Printf("Wating for terminating server instance [%s] is %s\n", serverInstanceNo, *serverInstanceList.ServerInstanceList[0].ServerInstanceStatus.Code)
|
||||
time.Sleep(time.Second * 3)
|
||||
}
|
||||
}()
|
||||
|
||||
select {
|
||||
case res := <-c1:
|
||||
s.Say(fmt.Sprintf("Server Instance terminated. Server InstanceNo is %s", serverInstanceNo))
|
||||
return res
|
||||
case <-time.After(time.Second * 120):
|
||||
return errors.New("TIMEOUT : Can't terminate server instance")
|
||||
}
|
||||
}
|
||||
|
||||
func (s *StepTerminateServerInstance) Run(ctx context.Context, state multistep.StateBag) multistep.StepAction {
|
||||
s.Say("Terminate Server Instance")
|
||||
|
||||
var serverInstanceNo = state.Get("InstanceNo").(string)
|
||||
var serverInstanceNo = state.Get("instance_no").(string)
|
||||
|
||||
err := s.TerminateServerInstance(serverInstanceNo)
|
||||
|
||||
|
|
|
@ -23,7 +23,7 @@ func TestStepTerminateServerInstanceShouldFailIfOperationTerminationFails(t *tes
|
|||
t.Fatalf("Expected the step to return 'ActionHalt', but got '%d'.", result)
|
||||
}
|
||||
|
||||
if _, ok := stateBag.GetOk("Error"); ok == false {
|
||||
if _, ok := stateBag.GetOk("error"); ok == false {
|
||||
t.Fatal("Expected the step to set stateBag['Error'], but it was not.")
|
||||
}
|
||||
}
|
||||
|
@ -43,7 +43,7 @@ func TestStepTerminateServerInstanceShouldPassIfOperationTerminationPasses(t *te
|
|||
t.Fatalf("Expected the step to return 'ActionContinue', but got '%d'.", result)
|
||||
}
|
||||
|
||||
if _, ok := stateBag.GetOk("Error"); ok == true {
|
||||
if _, ok := stateBag.GetOk("error"); ok == true {
|
||||
t.Fatalf("Expected the step to not set stateBag['Error'], but it was.")
|
||||
}
|
||||
}
|
||||
|
@ -51,6 +51,6 @@ func TestStepTerminateServerInstanceShouldPassIfOperationTerminationPasses(t *te
|
|||
func createTestStateBagStepTerminateServerInstance() multistep.StateBag {
|
||||
stateBag := new(multistep.BasicStateBag)
|
||||
|
||||
stateBag.Put("InstanceNo", "a")
|
||||
stateBag.Put("instance_no", "a")
|
||||
return stateBag
|
||||
}
|
||||
|
|
|
@ -5,6 +5,8 @@ import (
|
|||
"context"
|
||||
"errors"
|
||||
"fmt"
|
||||
"github.com/NaverCloudPlatform/ncloud-sdk-go-v2/services/vpc"
|
||||
"github.com/NaverCloudPlatform/ncloud-sdk-go-v2/services/vserver"
|
||||
"strings"
|
||||
|
||||
"github.com/NaverCloudPlatform/ncloud-sdk-go-v2/ncloud"
|
||||
|
@ -16,14 +18,20 @@ import (
|
|||
|
||||
//StepValidateTemplate : struct for Validation a template
|
||||
type StepValidateTemplate struct {
|
||||
Conn *NcloudAPIClient
|
||||
Validate func() error
|
||||
Say func(message string)
|
||||
Error func(e error)
|
||||
Config *Config
|
||||
zoneNo string
|
||||
regionNo string
|
||||
FeeSystemTypeCode string
|
||||
Conn *NcloudAPIClient
|
||||
Validate func() error
|
||||
getZone func() error
|
||||
getMemberServerImageList func() ([]*server.MemberServerImage, error)
|
||||
getServerImageProductList func(blockStorageSize *int32) ([]*server.Product, error)
|
||||
getServerProductList func(serverImageProductCode string) ([]*server.Product, error)
|
||||
Say func(message string)
|
||||
Error func(e error)
|
||||
Config *Config
|
||||
zoneNo string
|
||||
zoneCode string
|
||||
regionNo string
|
||||
regionCode string
|
||||
FeeSystemTypeCode string
|
||||
}
|
||||
|
||||
// NewStepValidateTemplate : function for Validation a template
|
||||
|
@ -35,6 +43,18 @@ func NewStepValidateTemplate(conn *NcloudAPIClient, ui packersdk.Ui, config *Con
|
|||
Config: config,
|
||||
}
|
||||
|
||||
if config.SupportVPC {
|
||||
step.getZone = step.getZoneCode
|
||||
step.getMemberServerImageList = step.getVpcMemberServerImageList
|
||||
step.getServerImageProductList = step.getVpcServerImageProductList
|
||||
step.getServerProductList = step.getVpcServerProductList
|
||||
} else {
|
||||
step.getZone = step.getZoneNo
|
||||
step.getMemberServerImageList = step.getClassicMemberServerImageList
|
||||
step.getServerImageProductList = step.getClassicServerImageProductList
|
||||
step.getServerProductList = step.getClassicServerProductList
|
||||
}
|
||||
|
||||
step.Validate = step.validateTemplate
|
||||
|
||||
return step
|
||||
|
@ -51,21 +71,19 @@ func (s *StepValidateTemplate) getZoneNo() error {
|
|||
return err
|
||||
}
|
||||
|
||||
var regionNo string
|
||||
for _, region := range regionList.RegionList {
|
||||
if strings.EqualFold(*region.RegionName, s.Config.Region) {
|
||||
regionNo = *region.RegionNo
|
||||
s.regionNo = *region.RegionNo
|
||||
s.regionCode = *region.RegionCode
|
||||
}
|
||||
}
|
||||
|
||||
if regionNo == "" {
|
||||
if s.regionNo == "" {
|
||||
return fmt.Errorf("region %s is invalid", s.Config.Region)
|
||||
}
|
||||
|
||||
s.regionNo = regionNo
|
||||
|
||||
// Get ZoneNo
|
||||
resp, err := s.Conn.server.V2Api.GetZoneList(&server.GetZoneListRequest{RegionNo: ®ionNo})
|
||||
resp, err := s.Conn.server.V2Api.GetZoneList(&server.GetZoneListRequest{RegionNo: &s.regionNo})
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
@ -77,19 +95,51 @@ func (s *StepValidateTemplate) getZoneNo() error {
|
|||
return nil
|
||||
}
|
||||
|
||||
func (s *StepValidateTemplate) validateMemberServerImage() error {
|
||||
// getZoneCode : get zoneCode
|
||||
func (s *StepValidateTemplate) getZoneCode() error {
|
||||
if s.Config.Region == "" {
|
||||
return nil
|
||||
}
|
||||
|
||||
regionList, err := s.Conn.vserver.V2Api.GetRegionList(&vserver.GetRegionListRequest{})
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
for _, region := range regionList.RegionList {
|
||||
if strings.EqualFold(*region.RegionName, s.Config.Region) {
|
||||
s.regionCode = *region.RegionCode
|
||||
s.Config.RegionCode = *region.RegionCode
|
||||
}
|
||||
}
|
||||
|
||||
if s.regionCode == "" {
|
||||
return fmt.Errorf("region %s is invalid", s.Config.Region)
|
||||
}
|
||||
|
||||
// Get ZoneNo
|
||||
resp, err := s.Conn.vserver.V2Api.GetZoneList(&vserver.GetZoneListRequest{RegionCode: &s.regionCode})
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if len(resp.ZoneList) > 0 {
|
||||
s.zoneCode = *resp.ZoneList[0].ZoneCode
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (s *StepValidateTemplate) validateMemberServerImage(fnGetServerImageList func() ([]*server.MemberServerImage, error)) error {
|
||||
var serverImageName = s.Config.ServerImageName
|
||||
|
||||
reqParams := new(server.GetMemberServerImageListRequest)
|
||||
reqParams.RegionNo = &s.regionNo
|
||||
|
||||
memberServerImageList, err := s.Conn.server.V2Api.GetMemberServerImageList(reqParams)
|
||||
memberServerImageList, err := fnGetServerImageList()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
var isExistMemberServerImageNo = false
|
||||
for _, image := range memberServerImageList.MemberServerImageList {
|
||||
for _, image := range memberServerImageList {
|
||||
// Check duplicate server_image_name
|
||||
if *image.MemberServerImageName == serverImageName {
|
||||
return fmt.Errorf("server_image_name %s is exists", serverImageName)
|
||||
|
@ -112,16 +162,86 @@ func (s *StepValidateTemplate) validateMemberServerImage() error {
|
|||
return nil
|
||||
}
|
||||
|
||||
func (s *StepValidateTemplate) getClassicMemberServerImageList() ([]*server.MemberServerImage, error) {
|
||||
reqParams := &server.GetMemberServerImageListRequest{
|
||||
RegionNo: &s.regionNo,
|
||||
}
|
||||
|
||||
resp, err := s.Conn.server.V2Api.GetMemberServerImageList(reqParams)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return resp.MemberServerImageList, nil
|
||||
}
|
||||
|
||||
func (s *StepValidateTemplate) getVpcMemberServerImageList() ([]*server.MemberServerImage, error) {
|
||||
reqParams := &vserver.GetMemberServerImageInstanceListRequest{
|
||||
RegionCode: &s.regionCode,
|
||||
}
|
||||
|
||||
memberServerImageList, err := s.Conn.vserver.V2Api.GetMemberServerImageInstanceList(reqParams)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
var results []*server.MemberServerImage
|
||||
for _, r := range memberServerImageList.MemberServerImageInstanceList {
|
||||
results = append(results, &server.MemberServerImage{
|
||||
MemberServerImageNo: r.MemberServerImageInstanceNo,
|
||||
MemberServerImageName: r.MemberServerImageName,
|
||||
MemberServerImageDescription: r.MemberServerImageDescription,
|
||||
OriginalServerInstanceNo: r.OriginalServerInstanceNo,
|
||||
OriginalServerProductCode: r.OriginalServerImageProductCode,
|
||||
})
|
||||
}
|
||||
|
||||
return results, nil
|
||||
}
|
||||
|
||||
func (s *StepValidateTemplate) getClassicServerImageProductList(blockStorageSize *int32) ([]*server.Product, error) {
|
||||
reqParams := &server.GetServerImageProductListRequest{
|
||||
RegionNo: &s.regionNo,
|
||||
BlockStorageSize: blockStorageSize,
|
||||
}
|
||||
|
||||
resp, err := s.Conn.server.V2Api.GetServerImageProductList(reqParams)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return resp.ProductList, nil
|
||||
}
|
||||
|
||||
func (s *StepValidateTemplate) getVpcServerImageProductList(blockStorageSize *int32) ([]*server.Product, error) {
|
||||
reqParams := &vserver.GetServerImageProductListRequest{
|
||||
RegionCode: &s.regionCode,
|
||||
BlockStorageSize: blockStorageSize,
|
||||
}
|
||||
|
||||
resp, err := s.Conn.vserver.V2Api.GetServerImageProductList(reqParams)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
var results []*server.Product
|
||||
for _, r := range resp.ProductList {
|
||||
results = append(results, &server.Product{
|
||||
ProductCode: r.ProductCode,
|
||||
ProductName: r.ProductName,
|
||||
})
|
||||
}
|
||||
|
||||
return results, nil
|
||||
}
|
||||
|
||||
func (s *StepValidateTemplate) validateServerImageProduct() error {
|
||||
var serverImageProductCode = s.Config.ServerImageProductCode
|
||||
if serverImageProductCode == "" {
|
||||
return nil
|
||||
}
|
||||
|
||||
reqParams := new(server.GetServerImageProductListRequest)
|
||||
reqParams.RegionNo = &s.regionNo
|
||||
|
||||
serverImageProductList, err := s.Conn.server.V2Api.GetServerImageProductList(reqParams)
|
||||
serverImageProductList, err := s.getServerImageProductList(nil)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
@ -132,7 +252,7 @@ func (s *StepValidateTemplate) validateServerImageProduct() error {
|
|||
table := tablewriter.NewWriter(&buf)
|
||||
table.SetHeader([]string{"Name", "Code"})
|
||||
|
||||
for _, product := range serverImageProductList.ProductList {
|
||||
for _, product := range serverImageProductList {
|
||||
// Check exist server image product code
|
||||
if *product.ProductCode == serverImageProductCode {
|
||||
isExistServerImage = true
|
||||
|
@ -144,14 +264,12 @@ func (s *StepValidateTemplate) validateServerImageProduct() error {
|
|||
}
|
||||
|
||||
if !isExistServerImage {
|
||||
reqParams.BlockStorageSize = ncloud.Int32(100)
|
||||
|
||||
serverImageProductList, err := s.Conn.server.V2Api.GetServerImageProductList(reqParams)
|
||||
serverImageProductList, err := s.getServerImageProductList(ncloud.Int32(100))
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
for _, product := range serverImageProductList.ProductList {
|
||||
for _, product := range serverImageProductList {
|
||||
// Check exist server image product code
|
||||
if *product.ProductCode == serverImageProductCode {
|
||||
isExistServerImage = true
|
||||
|
@ -177,21 +295,59 @@ func (s *StepValidateTemplate) validateServerImageProduct() error {
|
|||
return nil
|
||||
}
|
||||
|
||||
func (s *StepValidateTemplate) getClassicServerProductList(serverImageProductCode string) ([]*server.Product, error) {
|
||||
reqParams := &server.GetServerProductListRequest{
|
||||
ServerImageProductCode: &serverImageProductCode,
|
||||
RegionNo: &s.regionNo,
|
||||
}
|
||||
|
||||
resp, err := s.Conn.server.V2Api.GetServerProductList(reqParams)
|
||||
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return resp.ProductList, nil
|
||||
}
|
||||
|
||||
func (s *StepValidateTemplate) getVpcServerProductList(serverImageProductCode string) ([]*server.Product, error) {
|
||||
reqParams := &vserver.GetServerProductListRequest{
|
||||
ServerImageProductCode: &serverImageProductCode,
|
||||
RegionCode: &s.regionCode,
|
||||
}
|
||||
|
||||
resp, err := s.Conn.vserver.V2Api.GetServerProductList(reqParams)
|
||||
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
var results []*server.Product
|
||||
for _, r := range resp.ProductList {
|
||||
results = append(results, &server.Product{
|
||||
ProductCode: r.ProductCode,
|
||||
ProductName: r.ProductName,
|
||||
ProductType: &server.CommonCode{
|
||||
Code: r.ProductType.Code,
|
||||
CodeName: r.ProductType.CodeName,
|
||||
},
|
||||
})
|
||||
}
|
||||
|
||||
return results, nil
|
||||
}
|
||||
|
||||
func (s *StepValidateTemplate) validateServerProductCode() error {
|
||||
var serverImageProductCode = s.Config.ServerImageProductCode
|
||||
var productCode = s.Config.ServerProductCode
|
||||
|
||||
reqParams := new(server.GetServerProductListRequest)
|
||||
reqParams.ServerImageProductCode = &serverImageProductCode
|
||||
reqParams.RegionNo = &s.regionNo
|
||||
|
||||
resp, err := s.Conn.server.V2Api.GetServerProductList(reqParams)
|
||||
productList, err := s.getServerProductList(serverImageProductCode)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
var isExistProductCode = false
|
||||
for _, product := range resp.ProductList {
|
||||
for _, product := range productList {
|
||||
// Check exist server image product code
|
||||
if *product.ProductCode == productCode {
|
||||
isExistProductCode = true
|
||||
|
@ -216,7 +372,7 @@ func (s *StepValidateTemplate) validateServerProductCode() error {
|
|||
var buf bytes.Buffer
|
||||
table := tablewriter.NewWriter(&buf)
|
||||
table.SetHeader([]string{"Name", "Code"})
|
||||
for _, product := range resp.ProductList {
|
||||
for _, product := range productList {
|
||||
table.Append([]string{*product.ProductName, *product.ProductCode})
|
||||
}
|
||||
table.Render()
|
||||
|
@ -229,15 +385,80 @@ func (s *StepValidateTemplate) validateServerProductCode() error {
|
|||
return nil
|
||||
}
|
||||
|
||||
func (s *StepValidateTemplate) validateVpc() error {
|
||||
if !s.Config.SupportVPC {
|
||||
return nil
|
||||
}
|
||||
|
||||
if s.Config.VpcNo != "" {
|
||||
reqParam := &vpc.GetVpcDetailRequest{
|
||||
RegionCode: &s.Config.RegionCode,
|
||||
VpcNo: &s.Config.VpcNo,
|
||||
}
|
||||
|
||||
resp, err := s.Conn.vpc.V2Api.GetVpcDetail(reqParam)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if resp == nil || *resp.TotalRows == 0 {
|
||||
return fmt.Errorf("cloud not found VPC `vpc_no` [%s]", s.Config.VpcNo)
|
||||
}
|
||||
}
|
||||
|
||||
if s.Config.SubnetNo != "" {
|
||||
reqParam := &vpc.GetSubnetDetailRequest{
|
||||
RegionCode: &s.Config.RegionCode,
|
||||
SubnetNo: &s.Config.SubnetNo,
|
||||
}
|
||||
|
||||
resp, err := s.Conn.vpc.V2Api.GetSubnetDetail(reqParam)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if resp != nil && *resp.TotalRows > 0 && *resp.SubnetList[0].SubnetType.Code != "PUBLIC" {
|
||||
if s.Config.VpcNo == "" {
|
||||
s.Config.VpcNo = *resp.SubnetList[0].VpcNo
|
||||
s.Say("Set `vpc_no` is " + s.Config.VpcNo)
|
||||
}
|
||||
} else {
|
||||
return fmt.Errorf("cloud not found public subnet in `vpc_no` [%s]", s.Config.VpcNo)
|
||||
}
|
||||
}
|
||||
|
||||
if s.Config.VpcNo != "" && s.Config.SubnetNo == "" {
|
||||
reqParam := &vpc.GetSubnetListRequest{
|
||||
RegionCode: &s.Config.RegionCode,
|
||||
VpcNo: &s.Config.VpcNo,
|
||||
SubnetTypeCode: ncloud.String("PUBLIC"),
|
||||
}
|
||||
|
||||
resp, err := s.Conn.vpc.V2Api.GetSubnetList(reqParam)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if resp != nil && *resp.TotalRows > 0 {
|
||||
s.Config.SubnetNo = *resp.SubnetList[0].SubnetNo
|
||||
s.Say("Set `subnet_no` is " + s.Config.SubnetNo)
|
||||
} else {
|
||||
return fmt.Errorf("cloud not found public subnet in `vpc_no` [%s]", s.Config.VpcNo)
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// Check ImageName / Product Code / Server Image Product Code / Server Product Code...
|
||||
func (s *StepValidateTemplate) validateTemplate() error {
|
||||
// Get RegionNo, ZoneNo
|
||||
if err := s.getZoneNo(); err != nil {
|
||||
if err := s.getZone(); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// Validate member_server_image_no and member_server_image_no
|
||||
if err := s.validateMemberServerImage(); err != nil {
|
||||
if err := s.validateMemberServerImage(s.getMemberServerImageList); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
|
@ -246,6 +467,11 @@ func (s *StepValidateTemplate) validateTemplate() error {
|
|||
return err
|
||||
}
|
||||
|
||||
// Validate VPC
|
||||
if err := s.validateVpc(); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// Validate server_product_code
|
||||
return s.validateServerProductCode()
|
||||
}
|
||||
|
@ -256,10 +482,10 @@ func (s *StepValidateTemplate) Run(ctx context.Context, state multistep.StateBag
|
|||
|
||||
err := s.Validate()
|
||||
|
||||
state.Put("ZoneNo", s.zoneNo)
|
||||
state.Put("zone_no", s.zoneNo)
|
||||
|
||||
if s.FeeSystemTypeCode != "" {
|
||||
state.Put("FeeSystemTypeCode", s.FeeSystemTypeCode)
|
||||
state.Put("fee_system_type_code", s.FeeSystemTypeCode)
|
||||
}
|
||||
|
||||
return processStepResult(err, s.Error, state)
|
||||
|
|
|
@ -23,7 +23,7 @@ func TestStepValidateTemplateShouldFailIfValidateFails(t *testing.T) {
|
|||
t.Fatalf("Expected the step to return 'ActionHalt', but got '%d'.", result)
|
||||
}
|
||||
|
||||
if _, ok := stateBag.GetOk("Error"); ok == false {
|
||||
if _, ok := stateBag.GetOk("error"); ok == false {
|
||||
t.Fatal("Expected the step to set stateBag['Error'], but it was not.")
|
||||
}
|
||||
}
|
||||
|
@ -43,7 +43,7 @@ func TestStepValidateTemplateShouldPassIfValidatePasses(t *testing.T) {
|
|||
t.Fatalf("Expected the step to return 'ActionContinue', but got '%d'.", result)
|
||||
}
|
||||
|
||||
if _, ok := stateBag.GetOk("Error"); ok == true {
|
||||
if _, ok := stateBag.GetOk("error"); ok == true {
|
||||
t.Fatalf("Expected the step to not set stateBag['Error'], but it was.")
|
||||
}
|
||||
}
|
||||
|
|
|
@ -2,15 +2,17 @@ package ncloud
|
|||
|
||||
import (
|
||||
"fmt"
|
||||
"github.com/NaverCloudPlatform/ncloud-sdk-go-v2/services/vserver"
|
||||
"log"
|
||||
"time"
|
||||
|
||||
"github.com/NaverCloudPlatform/ncloud-sdk-go-v2/services/server"
|
||||
)
|
||||
|
||||
func waiterBlockStorageInstanceStatus(conn *NcloudAPIClient, blockStorageInstanceNo *string, status string, timeout time.Duration) error {
|
||||
reqParams := new(server.GetBlockStorageInstanceListRequest)
|
||||
reqParams.BlockStorageInstanceNoList = []*string{blockStorageInstanceNo}
|
||||
func waiterClassicBlockStorageStatus(conn *NcloudAPIClient, blockStorageInstanceNo *string, status string, timeout time.Duration) error {
|
||||
reqParams := &server.GetBlockStorageInstanceListRequest{
|
||||
BlockStorageInstanceNoList: []*string{blockStorageInstanceNo},
|
||||
}
|
||||
|
||||
c1 := make(chan error, 1)
|
||||
|
||||
|
@ -49,12 +51,54 @@ func waiterBlockStorageInstanceStatus(conn *NcloudAPIClient, blockStorageInstanc
|
|||
}
|
||||
}
|
||||
|
||||
func waiterDetachedBlockStorageInstance(conn *NcloudAPIClient, serverInstanceNo string, timeout time.Duration) error {
|
||||
reqParams := new(server.GetBlockStorageInstanceListRequest)
|
||||
reqParams.ServerInstanceNo = &serverInstanceNo
|
||||
func waiterVpcBlockStorageStatus(conn *NcloudAPIClient, blockStorageInstanceNo *string, status string, timeout time.Duration) error {
|
||||
reqParams := &vserver.GetBlockStorageInstanceListRequest{
|
||||
BlockStorageInstanceNoList: []*string{blockStorageInstanceNo},
|
||||
}
|
||||
|
||||
c1 := make(chan error, 1)
|
||||
|
||||
go func() {
|
||||
for {
|
||||
blockStorageInstanceList, err := conn.vserver.V2Api.GetBlockStorageInstanceList(reqParams)
|
||||
if err != nil {
|
||||
c1 <- err
|
||||
return
|
||||
}
|
||||
|
||||
if status == "DETAC" && len(blockStorageInstanceList.BlockStorageInstanceList) == 0 {
|
||||
c1 <- nil
|
||||
return
|
||||
}
|
||||
|
||||
blockStorageInstance := blockStorageInstanceList.BlockStorageInstanceList[0]
|
||||
code := blockStorageInstance.BlockStorageInstanceStatus.Code
|
||||
operationCode := blockStorageInstance.BlockStorageInstanceOperation.Code
|
||||
|
||||
if *code == status && *operationCode == "NULL" {
|
||||
c1 <- nil
|
||||
return
|
||||
}
|
||||
|
||||
log.Println(blockStorageInstance)
|
||||
time.Sleep(time.Second * 5)
|
||||
}
|
||||
}()
|
||||
|
||||
select {
|
||||
case res := <-c1:
|
||||
return res
|
||||
case <-time.After(timeout):
|
||||
return fmt.Errorf("TIMEOUT : block storage instance status is not changed into status %s", status)
|
||||
}
|
||||
}
|
||||
|
||||
func waiterClassicDetachedBlockStorage(conn *NcloudAPIClient, serverInstanceNo string, timeout time.Duration) error {
|
||||
reqParams := &server.GetBlockStorageInstanceListRequest{
|
||||
ServerInstanceNo: &serverInstanceNo,
|
||||
}
|
||||
c1 := make(chan error, 1)
|
||||
|
||||
go func() {
|
||||
for {
|
||||
blockStorageInstanceList, err := conn.server.V2Api.GetBlockStorageInstanceList(reqParams)
|
||||
|
@ -79,3 +123,34 @@ func waiterDetachedBlockStorageInstance(conn *NcloudAPIClient, serverInstanceNo
|
|||
return fmt.Errorf("TIMEOUT : attached block storage instance is not detached")
|
||||
}
|
||||
}
|
||||
|
||||
func waiterVpcDetachedBlockStorage(conn *NcloudAPIClient, serverInstanceNo string, timeout time.Duration) error {
|
||||
reqParams := &vserver.GetBlockStorageInstanceListRequest{
|
||||
ServerInstanceNo: &serverInstanceNo,
|
||||
}
|
||||
c1 := make(chan error, 1)
|
||||
|
||||
go func() {
|
||||
for {
|
||||
blockStorageInstanceList, err := conn.vserver.V2Api.GetBlockStorageInstanceList(reqParams)
|
||||
if err != nil {
|
||||
c1 <- err
|
||||
return
|
||||
}
|
||||
|
||||
if *blockStorageInstanceList.TotalRows == 1 {
|
||||
c1 <- nil
|
||||
return
|
||||
}
|
||||
|
||||
time.Sleep(time.Second * 5)
|
||||
}
|
||||
}()
|
||||
|
||||
select {
|
||||
case res := <-c1:
|
||||
return res
|
||||
case <-time.After(timeout):
|
||||
return fmt.Errorf("TIMEOUT : attached block storage instance is not detached")
|
||||
}
|
||||
}
|
||||
|
|
|
@ -2,15 +2,17 @@ package ncloud
|
|||
|
||||
import (
|
||||
"fmt"
|
||||
"github.com/NaverCloudPlatform/ncloud-sdk-go-v2/services/vserver"
|
||||
"log"
|
||||
"time"
|
||||
|
||||
"github.com/NaverCloudPlatform/ncloud-sdk-go-v2/services/server"
|
||||
)
|
||||
|
||||
func waiterMemberServerImageStatus(conn *NcloudAPIClient, memberServerImageNo string, status string, timeout time.Duration) error {
|
||||
reqParams := new(server.GetMemberServerImageListRequest)
|
||||
reqParams.MemberServerImageNoList = []*string{&memberServerImageNo}
|
||||
func waiterClassicMemberServerImageStatus(conn *NcloudAPIClient, memberServerImageNo string, status string, timeout time.Duration) error {
|
||||
reqParams := &server.GetMemberServerImageListRequest{
|
||||
MemberServerImageNoList: []*string{&memberServerImageNo},
|
||||
}
|
||||
|
||||
c1 := make(chan error, 1)
|
||||
|
||||
|
@ -29,7 +31,40 @@ func waiterMemberServerImageStatus(conn *NcloudAPIClient, memberServerImageNo st
|
|||
}
|
||||
|
||||
log.Printf("Status of member server image [%s] is %s\n", memberServerImageNo, *code)
|
||||
log.Println(memberServerImageList.MemberServerImageList[0])
|
||||
time.Sleep(time.Second * 5)
|
||||
}
|
||||
}()
|
||||
|
||||
select {
|
||||
case res := <-c1:
|
||||
return res
|
||||
case <-time.After(timeout):
|
||||
return fmt.Errorf("TIMEOUT : member server image status is not changed into status %s", status)
|
||||
}
|
||||
}
|
||||
|
||||
func waiterVpcMemberServerImageStatus(conn *NcloudAPIClient, memberServerImageNo string, status string, timeout time.Duration) error {
|
||||
reqParams := &vserver.GetMemberServerImageInstanceDetailRequest{
|
||||
MemberServerImageInstanceNo: &memberServerImageNo,
|
||||
}
|
||||
|
||||
c1 := make(chan error, 1)
|
||||
|
||||
go func() {
|
||||
for {
|
||||
memberServerImageList, err := conn.vserver.V2Api.GetMemberServerImageInstanceDetail(reqParams)
|
||||
if err != nil {
|
||||
c1 <- err
|
||||
return
|
||||
}
|
||||
|
||||
code := memberServerImageList.MemberServerImageInstanceList[0].MemberServerImageInstanceStatus.Code
|
||||
if *code == status {
|
||||
c1 <- nil
|
||||
return
|
||||
}
|
||||
|
||||
log.Printf("Status of member server image [%s] is %s\n", memberServerImageNo, *code)
|
||||
time.Sleep(time.Second * 5)
|
||||
}
|
||||
}()
|
||||
|
|
|
@ -2,13 +2,14 @@ package ncloud
|
|||
|
||||
import (
|
||||
"fmt"
|
||||
"github.com/NaverCloudPlatform/ncloud-sdk-go-v2/services/vserver"
|
||||
"log"
|
||||
"time"
|
||||
|
||||
"github.com/NaverCloudPlatform/ncloud-sdk-go-v2/services/server"
|
||||
)
|
||||
|
||||
func waiterServerInstanceStatus(conn *NcloudAPIClient, serverInstanceNo string, status string, timeout time.Duration) error {
|
||||
func waiterClassicServerInstanceStatus(conn *NcloudAPIClient, serverInstanceNo string, status string, timeout time.Duration) error {
|
||||
reqParams := new(server.GetServerInstanceListRequest)
|
||||
reqParams.ServerInstanceNoList = []*string{&serverInstanceNo}
|
||||
|
||||
|
@ -29,7 +30,40 @@ func waiterServerInstanceStatus(conn *NcloudAPIClient, serverInstanceNo string,
|
|||
}
|
||||
|
||||
log.Printf("Status of serverInstanceNo [%s] is %s\n", serverInstanceNo, *code)
|
||||
log.Println(serverInstanceList.ServerInstanceList[0])
|
||||
time.Sleep(time.Second * 5)
|
||||
}
|
||||
}()
|
||||
|
||||
select {
|
||||
case res := <-c1:
|
||||
return res
|
||||
case <-time.After(timeout):
|
||||
return fmt.Errorf("TIMEOUT : server instance status is not changed into status %s", status)
|
||||
}
|
||||
}
|
||||
|
||||
func waiterVpcServerInstanceStatus(conn *NcloudAPIClient, serverInstanceNo string, status string, timeout time.Duration) error {
|
||||
reqParams := &vserver.GetServerInstanceDetailRequest{
|
||||
ServerInstanceNo: &serverInstanceNo,
|
||||
}
|
||||
|
||||
c1 := make(chan error, 1)
|
||||
|
||||
go func() {
|
||||
for {
|
||||
serverInstanceList, err := conn.vserver.V2Api.GetServerInstanceDetail(reqParams)
|
||||
if err != nil {
|
||||
c1 <- err
|
||||
return
|
||||
}
|
||||
|
||||
code := serverInstanceList.ServerInstanceList[0].ServerInstanceStatus.Code
|
||||
if *code == status {
|
||||
c1 <- nil
|
||||
return
|
||||
}
|
||||
|
||||
log.Printf("Status of serverInstanceNo [%s] is %s\n", serverInstanceNo, *code)
|
||||
time.Sleep(time.Second * 5)
|
||||
}
|
||||
}()
|
||||
|
|
2
go.mod
2
go.mod
|
@ -11,7 +11,7 @@ require (
|
|||
github.com/Azure/go-autorest/autorest/date v0.2.0
|
||||
github.com/Azure/go-autorest/autorest/to v0.3.0
|
||||
github.com/ChrisTrenkamp/goxpath v0.0.0-20170922090931-c385f95c6022
|
||||
github.com/NaverCloudPlatform/ncloud-sdk-go-v2 v1.1.0
|
||||
github.com/NaverCloudPlatform/ncloud-sdk-go-v2 v1.1.7
|
||||
github.com/Telmate/proxmox-api-go v0.0.0-20200715182505-ec97c70ba887
|
||||
github.com/aliyun/alibaba-cloud-sdk-go v0.0.0-20190418113227-25233c783f4e
|
||||
github.com/aliyun/aliyun-oss-go-sdk v0.0.0-20170113022742-e6dbea820a9f
|
||||
|
|
2
go.sum
2
go.sum
|
@ -81,6 +81,8 @@ github.com/ChrisTrenkamp/goxpath v0.0.0-20170922090931-c385f95c6022/go.mod h1:nu
|
|||
github.com/DataDog/datadog-go v2.2.0+incompatible/go.mod h1:LButxg5PwREeZtORoXG3tL4fMGNddJ+vMq1mwgfaqoQ=
|
||||
github.com/NaverCloudPlatform/ncloud-sdk-go-v2 v1.1.0 h1:0nxjOH7NurPGUWNG5BCrASWjB0uuhGbgJAKLqj2ZDTo=
|
||||
github.com/NaverCloudPlatform/ncloud-sdk-go-v2 v1.1.0/go.mod h1:P+3VS0ETiQPyWOx3vB/oeC8J3qd7jnVZLYAFwWgGRt8=
|
||||
github.com/NaverCloudPlatform/ncloud-sdk-go-v2 v1.1.7 h1:Kpnbe19WkzVPpLLdAus4LkpNJ+pzLpfAViOUuvPcCqA=
|
||||
github.com/NaverCloudPlatform/ncloud-sdk-go-v2 v1.1.7/go.mod h1:P+3VS0ETiQPyWOx3vB/oeC8J3qd7jnVZLYAFwWgGRt8=
|
||||
github.com/StackExchange/wmi v0.0.0-20190523213315-cbe66965904d h1:G0m3OIz70MZUWq3EgK3CesDbo8upS2Vm9/P3FtgI+Jk=
|
||||
github.com/StackExchange/wmi v0.0.0-20190523213315-cbe66965904d/go.mod h1:3eOhrUMpNV+6aFIbp5/iudMxNCF27Vw2OZgy4xEx0Fg=
|
||||
github.com/Telmate/proxmox-api-go v0.0.0-20200715182505-ec97c70ba887 h1:Q65o4V0g/KR1sSUZIMf4m1rShb7f1tVHuEt30hfnh2A=
|
||||
|
|
|
@ -27,7 +27,15 @@
|
|||
- `region` (string) - Name of the region where you want to create an image.
|
||||
(default: Korea)
|
||||
|
||||
- `region_code` (string) - Region Code
|
||||
|
||||
- `access_control_group_configuration_no` (string) - This is used to allow
|
||||
winrm access when you create a Windows server. An ACG that specifies an
|
||||
access source (0.0.0.0/0) and allowed port (5985) must be created in
|
||||
advance.
|
||||
|
||||
- `support_vpc` (bool) - Whether to use VPC. By default, the value is false on "public" site. If you want to use VPC environment. Please set this value true.
|
||||
|
||||
- `subnet_no` (string) - The ID of the associated Subnet
|
||||
|
||||
- `vpc_no` (string) - The ID of the VPC where you want to place the Server Instance
|
||||
|
|
Loading…
Reference in New Issue