Support Naver Cloud Platform
This commit is contained in:
parent
60a136b20a
commit
5189d65467
|
@ -0,0 +1,46 @@
|
|||
package ncloud
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"fmt"
|
||||
|
||||
ncloud "github.com/NaverCloudPlatform/ncloud-sdk-go/sdk"
|
||||
)
|
||||
|
||||
const BuilderID = "ncloud.server.image"
|
||||
|
||||
type Artifact struct {
|
||||
ServerImage *ncloud.ServerImage
|
||||
}
|
||||
|
||||
func (*Artifact) BuilderId() string {
|
||||
return BuilderID
|
||||
}
|
||||
|
||||
func (a *Artifact) Files() []string {
|
||||
/* no file */
|
||||
return nil
|
||||
}
|
||||
|
||||
func (a *Artifact) Id() string {
|
||||
return a.ServerImage.MemberServerImageNo
|
||||
}
|
||||
|
||||
func (a *Artifact) String() string {
|
||||
var buf bytes.Buffer
|
||||
|
||||
// TODO : Logging artifact information
|
||||
buf.WriteString(fmt.Sprintf("%s:\n\n", a.BuilderId()))
|
||||
buf.WriteString(fmt.Sprintf("Member Server Image Name: %s\n", a.ServerImage.MemberServerImageName))
|
||||
buf.WriteString(fmt.Sprintf("Member Server Image No: %s\n", a.ServerImage.MemberServerImageNo))
|
||||
|
||||
return buf.String()
|
||||
}
|
||||
|
||||
func (a *Artifact) State(name string) interface{} {
|
||||
return a.ServerImage.MemberServerImageStatus
|
||||
}
|
||||
|
||||
func (a *Artifact) Destroy() error {
|
||||
return nil
|
||||
}
|
|
@ -0,0 +1,117 @@
|
|||
package ncloud
|
||||
|
||||
import (
|
||||
ncloud "github.com/NaverCloudPlatform/ncloud-sdk-go/sdk"
|
||||
"github.com/hashicorp/packer/common"
|
||||
"github.com/hashicorp/packer/helper/communicator"
|
||||
"github.com/hashicorp/packer/packer"
|
||||
"github.com/mitchellh/multistep"
|
||||
)
|
||||
|
||||
const version = "1.0.0"
|
||||
|
||||
// Builder assume this implements packer.Builder
|
||||
type Builder struct {
|
||||
config *Config
|
||||
stateBag multistep.StateBag
|
||||
runner multistep.Runner
|
||||
}
|
||||
|
||||
func (b *Builder) Prepare(raws ...interface{}) ([]string, error) {
|
||||
c, warnings, errs := NewConfig(raws...)
|
||||
if errs != nil {
|
||||
return warnings, errs
|
||||
}
|
||||
b.config = c
|
||||
|
||||
b.stateBag = new(multistep.BasicStateBag)
|
||||
|
||||
return warnings, nil
|
||||
}
|
||||
|
||||
func (b *Builder) Run(ui packer.Ui, hook packer.Hook, cache packer.Cache) (packer.Artifact, error) {
|
||||
ui.Say("Running builder for Naver Cloud Platform (version: " + version + ") ...")
|
||||
|
||||
ui.Message("Creating Naver Cloud Platform Connection ...")
|
||||
conn := ncloud.NewConnection(b.config.AccessKey, b.config.SecretKey)
|
||||
|
||||
b.stateBag.Put("hook", hook)
|
||||
b.stateBag.Put("ui", ui)
|
||||
|
||||
var steps []multistep.Step
|
||||
|
||||
steps = []multistep.Step{}
|
||||
|
||||
if b.config.OSType == "Linux" {
|
||||
steps = []multistep.Step{
|
||||
NewStepValidateTemplate(conn, ui, b.config),
|
||||
NewStepCreateLoginKey(conn, ui),
|
||||
NewStepCreateServerInstance(conn, ui, b.config),
|
||||
NewStepCreateBlockStorageInstance(conn, ui, b.config),
|
||||
NewStepGetRootPassword(conn, ui),
|
||||
NewStepCreatePublicIPInstance(conn, ui, b.config),
|
||||
&communicator.StepConnectSSH{
|
||||
Config: &b.config.Comm,
|
||||
Host: SSHHost,
|
||||
SSHConfig: SSHConfig(b.config.Comm.SSHUsername),
|
||||
},
|
||||
&common.StepProvision{},
|
||||
NewStepStopServerInstance(conn, ui),
|
||||
NewStepCreateServerImage(conn, ui, b.config),
|
||||
NewStepDeleteBlockStorageInstance(conn, ui, b.config),
|
||||
NewStepTerminateServerInstance(conn, ui),
|
||||
NewStepDeleteLoginKey(conn, ui),
|
||||
NewStepDeletePublicIPInstance(conn, ui),
|
||||
}
|
||||
} else if b.config.OSType == "Windows" {
|
||||
steps = []multistep.Step{
|
||||
NewStepValidateTemplate(conn, ui, b.config),
|
||||
NewStepCreateLoginKey(conn, ui),
|
||||
NewStepCreateServerInstance(conn, ui, b.config),
|
||||
NewStepCreateBlockStorageInstance(conn, ui, b.config),
|
||||
NewStepGetRootPassword(conn, ui),
|
||||
NewStepCreatePublicIPInstance(conn, ui, b.config),
|
||||
&communicator.StepConnectWinRM{
|
||||
Config: &b.config.Comm,
|
||||
Host: func(stateBag multistep.StateBag) (string, error) {
|
||||
return stateBag.Get("WinRMHost").(string), nil
|
||||
},
|
||||
WinRMConfig: func(state multistep.StateBag) (*communicator.WinRMConfig, error) {
|
||||
return &communicator.WinRMConfig{
|
||||
Username: b.config.Comm.WinRMUser,
|
||||
Password: state.Get("Password").(string),
|
||||
}, nil
|
||||
},
|
||||
},
|
||||
&common.StepProvision{},
|
||||
NewStepStopServerInstance(conn, ui),
|
||||
NewStepCreateServerImage(conn, ui, b.config),
|
||||
NewStepDeleteBlockStorageInstance(conn, ui, b.config),
|
||||
NewStepTerminateServerInstance(conn, ui),
|
||||
NewStepDeleteLoginKey(conn, ui),
|
||||
NewStepDeletePublicIPInstance(conn, ui),
|
||||
}
|
||||
}
|
||||
|
||||
// Run!
|
||||
b.runner = common.NewRunner(steps, b.config.PackerConfig, ui)
|
||||
b.runner.Run(b.stateBag)
|
||||
|
||||
// If there was an error, return that
|
||||
if rawErr, ok := b.stateBag.GetOk("Error"); ok {
|
||||
return nil, rawErr.(error)
|
||||
}
|
||||
|
||||
// Build the artifact and return it
|
||||
artifact := &Artifact{}
|
||||
|
||||
if serverImage, ok := b.stateBag.GetOk("memberServerImage"); ok {
|
||||
artifact.ServerImage = serverImage.(*ncloud.ServerImage)
|
||||
}
|
||||
|
||||
return artifact, nil
|
||||
}
|
||||
|
||||
func (b *Builder) Cancel() {
|
||||
b.runner.Cancel()
|
||||
}
|
|
@ -0,0 +1,114 @@
|
|||
package ncloud
|
||||
|
||||
import (
|
||||
"errors"
|
||||
|
||||
"github.com/hashicorp/packer/common"
|
||||
"github.com/hashicorp/packer/helper/communicator"
|
||||
"github.com/hashicorp/packer/helper/config"
|
||||
"github.com/hashicorp/packer/packer"
|
||||
"github.com/hashicorp/packer/template/interpolate"
|
||||
)
|
||||
|
||||
// Config is structure to use packer builder plugin for Naver Cloud Platform
|
||||
type Config struct {
|
||||
common.PackerConfig `mapstructure:",squash"`
|
||||
|
||||
AccessKey string `mapstructure:"access_key"`
|
||||
SecretKey string `mapstructure:"secret_key"`
|
||||
OSType string `mapstructure:"os_type"`
|
||||
ServerImageProductCode string `mapstructure:"server_image_product_code"`
|
||||
ServerProductCode string `mapstructure:"server_product_code"`
|
||||
MemberServerImageNo string `mapstructure:"member_server_image_no"`
|
||||
ServerImageName string `mapstructure:"server_image_name"`
|
||||
ServerImageDescription string `mapstructure:"server_image_description"`
|
||||
UserData string `mapstructure:"user_data"`
|
||||
BlockStorageSize int `mapstructure:"block_storage_size"`
|
||||
Region string `mapstructure:"region"`
|
||||
AccessControlGroupConfigurationNo string `mapstructure:"access_control_group_configuration_no"`
|
||||
FeeSystemTypeCode string `mapstructure:"-"`
|
||||
|
||||
Comm communicator.Config `mapstructure:",squash"`
|
||||
ctx *interpolate.Context
|
||||
}
|
||||
|
||||
// NewConfig checks parameters
|
||||
func NewConfig(raws ...interface{}) (*Config, []string, error) {
|
||||
c := new(Config)
|
||||
warnings := []string{}
|
||||
|
||||
err := config.Decode(c, &config.DecodeOpts{
|
||||
Interpolate: true,
|
||||
InterpolateFilter: &interpolate.RenderFilter{
|
||||
Exclude: []string{},
|
||||
},
|
||||
}, raws...)
|
||||
if err != nil {
|
||||
return nil, warnings, err
|
||||
}
|
||||
|
||||
var errs *packer.MultiError
|
||||
if es := c.Comm.Prepare(nil); len(es) > 0 {
|
||||
errs = packer.MultiErrorAppend(errs, es...)
|
||||
}
|
||||
|
||||
if c.AccessKey == "" {
|
||||
errs = packer.MultiErrorAppend(errs, errors.New("access_key is required"))
|
||||
}
|
||||
|
||||
if c.SecretKey == "" {
|
||||
errs = packer.MultiErrorAppend(errs, errors.New("secret_key is required"))
|
||||
}
|
||||
|
||||
if c.OSType != "Linux" && c.OSType != "Windows" {
|
||||
errs = packer.MultiErrorAppend(errs, errors.New("os_type is required. ('Linux' or 'Windows')"))
|
||||
}
|
||||
|
||||
if c.MemberServerImageNo == "" && c.ServerImageProductCode == "" {
|
||||
errs = packer.MultiErrorAppend(errs, errors.New("server_image_product_code or member_server_image_no is required"))
|
||||
}
|
||||
|
||||
if c.MemberServerImageNo != "" && c.ServerImageProductCode != "" {
|
||||
errs = packer.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 = packer.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 = packer.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 = packer.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 = packer.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 = packer.MultiErrorAppend(errs, errors.New("The size of BlockStorageSize is at least 10 GB and up to 2000GB"))
|
||||
} else if int(c.BlockStorageSize/10)*10 != c.BlockStorageSize {
|
||||
return nil, nil, errors.New("BlockStorageSize must be a multiple of 10 GB")
|
||||
}
|
||||
}
|
||||
|
||||
if c.UserData != "" && len(c.UserData) > 21847 {
|
||||
errs = packer.MultiErrorAppend(errs, errors.New("If user_data field is set, length of UserData should be max 21847"))
|
||||
}
|
||||
|
||||
if c.OSType == "Windows" && c.AccessControlGroupConfigurationNo == "" {
|
||||
errs = packer.MultiErrorAppend(errs, errors.New("If os_type is Windows, access_control_group_configuration_no is required"))
|
||||
}
|
||||
|
||||
c.FeeSystemTypeCode = "MTRAT"
|
||||
|
||||
if errs != nil && len(errs.Errors) > 0 {
|
||||
return nil, warnings, errs
|
||||
}
|
||||
|
||||
return c, warnings, nil
|
||||
}
|
|
@ -0,0 +1,149 @@
|
|||
package ncloud
|
||||
|
||||
import (
|
||||
"strings"
|
||||
"testing"
|
||||
)
|
||||
|
||||
func testConfig() map[string]interface{} {
|
||||
return map[string]interface{}{
|
||||
"access_key": "access_key",
|
||||
"secret_key": "secret_key",
|
||||
"os_type": "Windows",
|
||||
"server_image_product_code": "SPSW0WINNT000016",
|
||||
"server_product_code": "SPSVRSSD00000011",
|
||||
"server_image_name": "packer-test {{timestamp}}",
|
||||
"server_image_description": "server description",
|
||||
"block_storage_size": 100,
|
||||
"user_data": "#!/bin/sh\nyum install -y httpd\ntouch /var/www/html/index.html\nchkconfig --level 2345 httpd on",
|
||||
"region": "Korea",
|
||||
"access_control_group_configuration_no": "33",
|
||||
"communicator": "ssh",
|
||||
"ssh_username": "root",
|
||||
}
|
||||
}
|
||||
|
||||
func testConfigForMemberServerImage() map[string]interface{} {
|
||||
return map[string]interface{}{
|
||||
"access_key": "access_key",
|
||||
"secret_key": "secret_key",
|
||||
"os_type": "Windows",
|
||||
"server_product_code": "SPSVRSSD00000011",
|
||||
"member_server_image_no": "2440",
|
||||
"server_image_name": "packer-test {{timestamp}}",
|
||||
"server_image_description": "server description",
|
||||
"block_storage_size": 100,
|
||||
"user_data": "#!/bin/sh\nyum install -y httpd\ntouch /var/www/html/index.html\nchkconfig --level 2345 httpd on",
|
||||
"region": "Korea",
|
||||
"access_control_group_configuration_no": "33",
|
||||
"communicator": "ssh",
|
||||
"ssh_username": "root",
|
||||
}
|
||||
}
|
||||
|
||||
func TestConfigWithServerImageProductCode(t *testing.T) {
|
||||
raw := testConfig()
|
||||
|
||||
c, _, _ := NewConfig(raw)
|
||||
|
||||
if c.AccessKey != "access_key" {
|
||||
t.Errorf("Expected 'access_key' to be set to '%s', but got '%s'.", raw["access_key"], c.AccessKey)
|
||||
}
|
||||
|
||||
if c.SecretKey != "secret_key" {
|
||||
t.Errorf("Expected 'secret_key' to be set to '%s', but got '%s'.", raw["secret_key"], c.SecretKey)
|
||||
}
|
||||
|
||||
if c.ServerImageProductCode != "SPSW0WINNT000016" {
|
||||
t.Errorf("Expected 'server_image_product_code' to be set to '%s', but got '%s'.", raw["server_image_product_code"], c.ServerImageProductCode)
|
||||
}
|
||||
|
||||
if c.ServerProductCode != "SPSVRSSD00000011" {
|
||||
t.Errorf("Expected 'server_product_code' to be set to '%s', but got '%s'.", raw["server_product_code"], c.ServerProductCode)
|
||||
}
|
||||
|
||||
if c.BlockStorageSize != 100 {
|
||||
t.Errorf("Expected 'block_storage_size' to be set to '%d', but got '%d'.", raw["block_storage_size"], c.BlockStorageSize)
|
||||
}
|
||||
|
||||
if c.ServerImageDescription != "server description" {
|
||||
t.Errorf("Expected 'server_image_description_key' to be set to '%s', but got '%s'.", raw["server_image_description"], c.ServerImageDescription)
|
||||
}
|
||||
|
||||
if c.Region != "Korea" {
|
||||
t.Errorf("Expected 'region' to be set to '%s', but got '%s'.", raw["server_image_description"], c.Region)
|
||||
}
|
||||
}
|
||||
|
||||
func TestConfigWithMemberServerImageCode(t *testing.T) {
|
||||
raw := testConfigForMemberServerImage()
|
||||
|
||||
c, _, _ := NewConfig(raw)
|
||||
|
||||
if c.AccessKey != "access_key" {
|
||||
t.Errorf("Expected 'access_key' to be set to '%s', but got '%s'.", raw["access_key"], c.AccessKey)
|
||||
}
|
||||
|
||||
if c.SecretKey != "secret_key" {
|
||||
t.Errorf("Expected 'secret_key' to be set to '%s', but got '%s'.", raw["secret_key"], c.SecretKey)
|
||||
}
|
||||
|
||||
if c.MemberServerImageNo != "2440" {
|
||||
t.Errorf("Expected 'member_server_image_no' to be set to '%s', but got '%s'.", raw["member_server_image_no"], c.MemberServerImageNo)
|
||||
}
|
||||
|
||||
if c.ServerProductCode != "SPSVRSSD00000011" {
|
||||
t.Errorf("Expected 'server_product_code' to be set to '%s', but got '%s'.", raw["server_product_code"], c.ServerProductCode)
|
||||
}
|
||||
|
||||
if c.BlockStorageSize != 100 {
|
||||
t.Errorf("Expected 'block_storage_size' to be set to '%d', but got '%d'.", raw["block_storage_size"], c.BlockStorageSize)
|
||||
}
|
||||
|
||||
if c.ServerImageDescription != "server description" {
|
||||
t.Errorf("Expected 'server_image_description_key' to be set to '%s', but got '%s'.", raw["server_image_description"], c.ServerImageDescription)
|
||||
}
|
||||
|
||||
if c.Region != "Korea" {
|
||||
t.Errorf("Expected 'region' to be set to '%s', but got '%s'.", raw["server_image_description"], c.Region)
|
||||
}
|
||||
}
|
||||
|
||||
func TestEmptyConfig(t *testing.T) {
|
||||
raw := new(map[string]interface{})
|
||||
|
||||
_, _, err := NewConfig(raw)
|
||||
|
||||
if err == nil {
|
||||
t.Error("Expected Config to require 'access_key', 'secret_key' and some mendatory fields, but it did not")
|
||||
}
|
||||
|
||||
if !strings.Contains(err.Error(), "access_key is required") {
|
||||
t.Error("Expected Config to require 'access_key', but it did not")
|
||||
}
|
||||
|
||||
if !strings.Contains(err.Error(), "secret_key is required") {
|
||||
t.Error("Expected Config to require 'secret_key', but it did not")
|
||||
}
|
||||
|
||||
if !strings.Contains(err.Error(), "server_image_product_code or member_server_image_no is required") {
|
||||
t.Error("Expected Config to require 'server_image_product_code' or 'member_server_image_no', but it did not")
|
||||
}
|
||||
}
|
||||
|
||||
func TestExistsBothServerImageProductCodeAndMemberServerImageNoConfig(t *testing.T) {
|
||||
raw := map[string]interface{}{
|
||||
"access_key": "access_key",
|
||||
"secret_key": "secret_key",
|
||||
"os_type": "Windows",
|
||||
"server_image_product_code": "SPSW0WINNT000016",
|
||||
"server_product_code": "SPSVRSSD00000011",
|
||||
"member_server_image_no": "2440",
|
||||
}
|
||||
|
||||
_, _, err := NewConfig(raw)
|
||||
|
||||
if !strings.Contains(err.Error(), "Only one of server_image_product_code and member_server_image_no can be set") {
|
||||
t.Error("Expected Config to require Only one of 'server_image_product_code' and 'member_server_image_no' can be set, but it did not")
|
||||
}
|
||||
}
|
|
@ -0,0 +1,30 @@
|
|||
package ncloud
|
||||
|
||||
import (
|
||||
packerssh "github.com/hashicorp/packer/communicator/ssh"
|
||||
"github.com/mitchellh/multistep"
|
||||
"golang.org/x/crypto/ssh"
|
||||
)
|
||||
|
||||
func SSHHost(state multistep.StateBag) (string, error) {
|
||||
host := state.Get("SSHHost").(string)
|
||||
return host, nil
|
||||
}
|
||||
|
||||
// SSHConfig returns a function that can be used for the SSH communicator
|
||||
// config for connecting to the specified host via SSH
|
||||
func SSHConfig(username string) func(multistep.StateBag) (*ssh.ClientConfig, error) {
|
||||
return func(state multistep.StateBag) (*ssh.ClientConfig, error) {
|
||||
password := state.Get("Password").(string)
|
||||
|
||||
return &ssh.ClientConfig{
|
||||
User: username,
|
||||
Auth: []ssh.AuthMethod{
|
||||
ssh.Password(password),
|
||||
ssh.KeyboardInteractive(
|
||||
packerssh.PasswordKeyboardInteractive(password)),
|
||||
},
|
||||
HostKeyCallback: ssh.InsecureIgnoreHostKey(),
|
||||
}, nil
|
||||
}
|
||||
}
|
|
@ -0,0 +1,16 @@
|
|||
package ncloud
|
||||
|
||||
import (
|
||||
"github.com/mitchellh/multistep"
|
||||
)
|
||||
|
||||
func processStepResult(err error, sayError func(error), state multistep.StateBag) multistep.StepAction {
|
||||
if err != nil {
|
||||
state.Put("Error", err)
|
||||
sayError(err)
|
||||
|
||||
return multistep.ActionHalt
|
||||
}
|
||||
|
||||
return multistep.ActionContinue
|
||||
}
|
|
@ -0,0 +1,101 @@
|
|||
package ncloud
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"fmt"
|
||||
"log"
|
||||
"time"
|
||||
|
||||
ncloud "github.com/NaverCloudPlatform/ncloud-sdk-go/sdk"
|
||||
"github.com/hashicorp/packer/packer"
|
||||
"github.com/mitchellh/multistep"
|
||||
)
|
||||
|
||||
// StepCreateBlockStorageInstance struct is for making extra block storage
|
||||
type StepCreateBlockStorageInstance struct {
|
||||
Conn *ncloud.Conn
|
||||
CreateBlockStorageInstance func(serverInstanceNo string) (string, error)
|
||||
Say func(message string)
|
||||
Error func(e error)
|
||||
Config *Config
|
||||
}
|
||||
|
||||
// NewStepCreateBlockStorageInstance make StepCreateBlockStorage struct to make extra block storage
|
||||
func NewStepCreateBlockStorageInstance(conn *ncloud.Conn, ui packer.Ui, config *Config) *StepCreateBlockStorageInstance {
|
||||
var step = &StepCreateBlockStorageInstance{
|
||||
Conn: conn,
|
||||
Say: func(message string) { ui.Say(message) },
|
||||
Error: func(e error) { ui.Error(e.Error()) },
|
||||
Config: config,
|
||||
}
|
||||
|
||||
step.CreateBlockStorageInstance = step.createBlockStorageInstance
|
||||
|
||||
return step
|
||||
}
|
||||
|
||||
func (s *StepCreateBlockStorageInstance) createBlockStorageInstance(serverInstanceNo string) (string, error) {
|
||||
|
||||
reqParams := new(ncloud.RequestBlockStorageInstance)
|
||||
reqParams.BlockStorageSize = s.Config.BlockStorageSize
|
||||
reqParams.ServerInstanceNo = serverInstanceNo
|
||||
|
||||
blockStorageInstanceList, err := s.Conn.CreateBlockStorageInstance(reqParams)
|
||||
if err != nil {
|
||||
return "", fmt.Errorf("error code: %d, error message: %s", blockStorageInstanceList.ReturnCode, blockStorageInstanceList.ReturnMessage)
|
||||
}
|
||||
|
||||
log.Println("Block Storage Instance information : ", blockStorageInstanceList.BlockStorageInstance[0])
|
||||
|
||||
if err := waiterBlockStorageInstanceStatus(s.Conn, blockStorageInstanceList.BlockStorageInstance[0].BlockStorageInstanceNo, "ATTAC", 10*time.Minute); err != nil {
|
||||
return "", errors.New("TIMEOUT : Block Storage instance status is not attached")
|
||||
}
|
||||
|
||||
return blockStorageInstanceList.BlockStorageInstance[0].BlockStorageInstanceNo, nil
|
||||
}
|
||||
|
||||
func (s *StepCreateBlockStorageInstance) Run(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)
|
||||
|
||||
blockStorageInstanceNo, err := s.CreateBlockStorageInstance(serverInstanceNo)
|
||||
if err == nil {
|
||||
state.Put("BlockStorageInstanceNo", blockStorageInstanceNo)
|
||||
}
|
||||
|
||||
return processStepResult(err, s.Error, state)
|
||||
}
|
||||
|
||||
func (s *StepCreateBlockStorageInstance) Cleanup(state multistep.StateBag) {
|
||||
_, cancelled := state.GetOk(multistep.StateCancelled)
|
||||
_, halted := state.GetOk(multistep.StateHalted)
|
||||
|
||||
if !cancelled && !halted {
|
||||
return
|
||||
}
|
||||
|
||||
if s.Config.BlockStorageSize == 0 {
|
||||
return
|
||||
}
|
||||
|
||||
if blockStorageInstanceNo, ok := state.GetOk("BlockStorageInstanceNo"); ok {
|
||||
s.Say("Clean up Block Storage Instance")
|
||||
no := blockStorageInstanceNo.(string)
|
||||
blockStorageInstanceList, err := s.Conn.DeleteBlockStorageInstances([]string{no})
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
s.Say(fmt.Sprintf("Block Storage Instance is deleted. Block Storage InstanceNo is %s", no))
|
||||
log.Println("Block Storage Instance information : ", blockStorageInstanceList.BlockStorageInstance[0])
|
||||
|
||||
if err := waiterBlockStorageInstanceStatus(s.Conn, no, "DETAC", time.Minute); err != nil {
|
||||
s.Say("TIMEOUT : Block Storage instance status is not deattached")
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,62 @@
|
|||
package ncloud
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"github.com/mitchellh/multistep"
|
||||
"testing"
|
||||
)
|
||||
|
||||
func TestStepCreateBlockStorageInstanceShouldFailIfOperationCreateBlockStorageInstanceFails(t *testing.T) {
|
||||
|
||||
var testSubject = &StepCreateBlockStorageInstance{
|
||||
CreateBlockStorageInstance: func(serverInstanceNo string) (string, error) { return "", fmt.Errorf("!! Unit Test FAIL !!") },
|
||||
Say: func(message string) {},
|
||||
Error: func(e error) {},
|
||||
Config: new(Config),
|
||||
}
|
||||
|
||||
testSubject.Config.BlockStorageSize = 10
|
||||
|
||||
stateBag := createTestStateBagStepCreateBlockStorageInstance()
|
||||
|
||||
var result = testSubject.Run(stateBag)
|
||||
|
||||
if result != multistep.ActionHalt {
|
||||
t.Fatalf("Expected the step to return 'ActionHalt', but got '%d'.", result)
|
||||
}
|
||||
|
||||
if _, ok := stateBag.GetOk("Error"); ok == false {
|
||||
t.Fatal("Expected the step to set stateBag['Error'], but it was not.")
|
||||
}
|
||||
}
|
||||
|
||||
func TestStepCreateBlockStorageInstanceShouldPassIfOperationCreateBlockStorageInstancePasses(t *testing.T) {
|
||||
var testSubject = &StepCreateBlockStorageInstance{
|
||||
CreateBlockStorageInstance: func(serverInstanceNo string) (string, error) { return "a", nil },
|
||||
Say: func(message string) {},
|
||||
Error: func(e error) {},
|
||||
Config: new(Config),
|
||||
}
|
||||
|
||||
testSubject.Config.BlockStorageSize = 10
|
||||
|
||||
stateBag := createTestStateBagStepCreateBlockStorageInstance()
|
||||
|
||||
var result = testSubject.Run(stateBag)
|
||||
|
||||
if result != multistep.ActionContinue {
|
||||
t.Fatalf("Expected the step to return 'ActionContinue', but got '%d'.", result)
|
||||
}
|
||||
|
||||
if _, ok := stateBag.GetOk("Error"); ok == true {
|
||||
t.Fatalf("Expected the step to not set stateBag['Error'], but it was.")
|
||||
}
|
||||
}
|
||||
|
||||
func createTestStateBagStepCreateBlockStorageInstance() multistep.StateBag {
|
||||
stateBag := new(multistep.BasicStateBag)
|
||||
|
||||
stateBag.Put("InstanceNo", "a")
|
||||
|
||||
return stateBag
|
||||
}
|
|
@ -0,0 +1,71 @@
|
|||
package ncloud
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"time"
|
||||
|
||||
ncloud "github.com/NaverCloudPlatform/ncloud-sdk-go/sdk"
|
||||
"github.com/hashicorp/packer/packer"
|
||||
"github.com/mitchellh/multistep"
|
||||
)
|
||||
|
||||
type LoginKey struct {
|
||||
KeyName string
|
||||
PrivateKey string
|
||||
}
|
||||
|
||||
type StepCreateLoginKey struct {
|
||||
Conn *ncloud.Conn
|
||||
CreateLoginKey func() (*LoginKey, error)
|
||||
Say func(message string)
|
||||
Error func(e error)
|
||||
}
|
||||
|
||||
func NewStepCreateLoginKey(conn *ncloud.Conn, ui packer.Ui) *StepCreateLoginKey {
|
||||
var step = &StepCreateLoginKey{
|
||||
Conn: conn,
|
||||
Say: func(message string) { ui.Say(message) },
|
||||
Error: func(e error) { ui.Error(e.Error()) },
|
||||
}
|
||||
|
||||
step.CreateLoginKey = step.createLoginKey
|
||||
|
||||
return step
|
||||
}
|
||||
|
||||
func (s *StepCreateLoginKey) createLoginKey() (*LoginKey, error) {
|
||||
KeyName := fmt.Sprintf("packer-%d", time.Now().Unix())
|
||||
|
||||
privateKey, err := s.Conn.CreateLoginKey(KeyName)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("error code: %d , error message: %s", privateKey.ReturnCode, privateKey.ReturnMessage)
|
||||
}
|
||||
|
||||
return &LoginKey{KeyName, privateKey.PrivateKey}, nil
|
||||
}
|
||||
|
||||
func (s *StepCreateLoginKey) Run(state multistep.StateBag) multistep.StepAction {
|
||||
s.Say("Create Login Key")
|
||||
|
||||
loginKey, err := s.CreateLoginKey()
|
||||
if err == nil {
|
||||
state.Put("LoginKey", loginKey)
|
||||
s.Say(fmt.Sprintf("Login Key[%s] is created", loginKey.KeyName))
|
||||
}
|
||||
|
||||
return processStepResult(err, s.Error, state)
|
||||
}
|
||||
|
||||
func (s *StepCreateLoginKey) Cleanup(state multistep.StateBag) {
|
||||
_, cancelled := state.GetOk(multistep.StateCancelled)
|
||||
_, halted := state.GetOk(multistep.StateHalted)
|
||||
|
||||
if !cancelled && !halted {
|
||||
return
|
||||
}
|
||||
|
||||
if loginKey, ok := state.GetOk("LoginKey"); ok {
|
||||
s.Say("Clean up login key")
|
||||
s.Conn.DeleteLoginKey(loginKey.(*LoginKey).KeyName)
|
||||
}
|
||||
}
|
|
@ -0,0 +1,53 @@
|
|||
package ncloud
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"github.com/mitchellh/multistep"
|
||||
"testing"
|
||||
)
|
||||
|
||||
func TestStepCreateLoginKeyShouldFailIfOperationCreateLoginKeyFails(t *testing.T) {
|
||||
var testSubject = &StepCreateLoginKey{
|
||||
CreateLoginKey: func() (*LoginKey, error) { return nil, fmt.Errorf("!! Unit Test FAIL !!") },
|
||||
Say: func(message string) {},
|
||||
Error: func(e error) {},
|
||||
}
|
||||
|
||||
stateBag := createTestStateBagStepCreateLoginKey()
|
||||
|
||||
var result = testSubject.Run(stateBag)
|
||||
|
||||
if result != multistep.ActionHalt {
|
||||
t.Fatalf("Expected the step to return 'ActionHalt', but got '%d'.", result)
|
||||
}
|
||||
|
||||
if _, ok := stateBag.GetOk("Error"); ok == false {
|
||||
t.Fatal("Expected the step to set stateBag['Error'], but it was not.")
|
||||
}
|
||||
}
|
||||
|
||||
func TestStepCreateLoginKeyShouldPassIfOperationCreateLoginKeyPasses(t *testing.T) {
|
||||
var testSubject = &StepCreateLoginKey{
|
||||
CreateLoginKey: func() (*LoginKey, error) { return &LoginKey{"a", "b"}, nil },
|
||||
Say: func(message string) {},
|
||||
Error: func(e error) {},
|
||||
}
|
||||
|
||||
stateBag := createTestStateBagStepCreateLoginKey()
|
||||
|
||||
var result = testSubject.Run(stateBag)
|
||||
|
||||
if result != multistep.ActionContinue {
|
||||
t.Fatalf("Expected the step to return 'ActionContinue', but got '%d'.", result)
|
||||
}
|
||||
|
||||
if _, ok := stateBag.GetOk("Error"); ok == true {
|
||||
t.Fatalf("Expected the step to not set stateBag['Error'], but it was.")
|
||||
}
|
||||
}
|
||||
|
||||
func createTestStateBagStepCreateLoginKey() multistep.StateBag {
|
||||
stateBag := new(multistep.BasicStateBag)
|
||||
|
||||
return stateBag
|
||||
}
|
|
@ -0,0 +1,167 @@
|
|||
package ncloud
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"log"
|
||||
"time"
|
||||
|
||||
ncloud "github.com/NaverCloudPlatform/ncloud-sdk-go/sdk"
|
||||
"github.com/hashicorp/packer/packer"
|
||||
"github.com/mitchellh/multistep"
|
||||
)
|
||||
|
||||
type StepCreatePublicIPInstance struct {
|
||||
Conn *ncloud.Conn
|
||||
CreatePublicIPInstance func(serverInstanceNo string) (*ncloud.PublicIPInstance, error)
|
||||
WaiterAssociatePublicIPToServerInstance func(serverInstanceNo string, publicIP string) error
|
||||
Say func(message string)
|
||||
Error func(e error)
|
||||
Config *Config
|
||||
}
|
||||
|
||||
func NewStepCreatePublicIPInstance(conn *ncloud.Conn, ui packer.Ui, config *Config) *StepCreatePublicIPInstance {
|
||||
var step = &StepCreatePublicIPInstance{
|
||||
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
|
||||
|
||||
return step
|
||||
}
|
||||
|
||||
func (s *StepCreatePublicIPInstance) waiterAssociatePublicIPToServerInstance(serverInstanceNo string, publicIP string) error {
|
||||
reqParams := new(ncloud.RequestGetServerInstanceList)
|
||||
reqParams.ServerInstanceNoList = []string{serverInstanceNo}
|
||||
|
||||
c1 := make(chan error, 1)
|
||||
|
||||
go func() {
|
||||
for {
|
||||
serverInstanceList, err := s.Conn.GetServerInstanceList(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 *StepCreatePublicIPInstance) createPublicIPInstance(serverInstanceNo string) (*ncloud.PublicIPInstance, error) {
|
||||
reqParams := new(ncloud.RequestCreatePublicIPInstance)
|
||||
reqParams.ServerInstanceNo = serverInstanceNo
|
||||
|
||||
publicIPInstanceList, err := s.Conn.CreatePublicIPInstance(reqParams)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("error code: %d, error message: %s", publicIPInstanceList.ReturnCode, publicIPInstanceList.ReturnMessage)
|
||||
}
|
||||
|
||||
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)
|
||||
|
||||
return &publicIPInstance, nil
|
||||
}
|
||||
|
||||
func (s *StepCreatePublicIPInstance) Run(state multistep.StateBag) multistep.StepAction {
|
||||
s.Say("Create Public IP Instance")
|
||||
|
||||
serverInstanceNo := state.Get("InstanceNo").(string)
|
||||
|
||||
publicIPInstance, err := s.CreatePublicIPInstance(serverInstanceNo)
|
||||
if err == nil {
|
||||
switch s.Config.OSType {
|
||||
case "Linux":
|
||||
state.Put("SSHHost", publicIPInstance.PublicIP)
|
||||
case "Windows":
|
||||
state.Put("WinRMHost", publicIPInstance.PublicIP)
|
||||
}
|
||||
|
||||
state.Put("PublicIPInstance", publicIPInstance)
|
||||
}
|
||||
|
||||
return processStepResult(err, s.Error, state)
|
||||
}
|
||||
|
||||
func (s *StepCreatePublicIPInstance) Cleanup(state multistep.StateBag) {
|
||||
_, cancelled := state.GetOk(multistep.StateCancelled)
|
||||
_, halted := state.GetOk(multistep.StateHalted)
|
||||
|
||||
if !cancelled && !halted {
|
||||
return
|
||||
}
|
||||
|
||||
publicIPInstance, ok := state.GetOk("PublicIPInstance")
|
||||
if !ok {
|
||||
return
|
||||
}
|
||||
|
||||
s.Say("Clean up Public IP Instance")
|
||||
publicIPInstanceNo := publicIPInstance.(*ncloud.PublicIPInstance).PublicIPInstanceNo
|
||||
s.waitPublicIPInstanceStatus(publicIPInstanceNo, "USED")
|
||||
|
||||
log.Println("Disassociate Public IP Instance ", publicIPInstanceNo)
|
||||
s.Conn.DisassociatePublicIP(publicIPInstanceNo)
|
||||
|
||||
s.waitPublicIPInstanceStatus(publicIPInstanceNo, "CREAT")
|
||||
|
||||
reqParams := new(ncloud.RequestDeletePublicIPInstances)
|
||||
reqParams.PublicIPInstanceNoList = []string{publicIPInstanceNo}
|
||||
|
||||
log.Println("Delete Public IP Instance ", publicIPInstanceNo)
|
||||
s.Conn.DeletePublicIPInstances(reqParams)
|
||||
}
|
||||
|
||||
func (s *StepCreatePublicIPInstance) waitPublicIPInstanceStatus(publicIPInstanceNo string, status string) {
|
||||
c1 := make(chan error, 1)
|
||||
|
||||
go func() {
|
||||
reqParams := new(ncloud.RequestPublicIPInstanceList)
|
||||
reqParams.PublicIPInstanceNoList = []string{publicIPInstanceNo}
|
||||
|
||||
for {
|
||||
resp, err := s.Conn.GetPublicIPInstanceList(reqParams)
|
||||
if err != nil {
|
||||
log.Printf("error code: %d, error message: %s", resp.ReturnCode, resp.ReturnMessage)
|
||||
c1 <- err
|
||||
return
|
||||
}
|
||||
|
||||
instance := resp.PublicIPInstanceList[0]
|
||||
if instance.PublicIPInstanceStatus.Code == status && instance.PublicIPInstanceOperation.Code == "NULL" {
|
||||
c1 <- nil
|
||||
return
|
||||
}
|
||||
|
||||
time.Sleep(time.Second * 2)
|
||||
}
|
||||
}()
|
||||
|
||||
select {
|
||||
case <-c1:
|
||||
return
|
||||
case <-time.After(time.Second * 60):
|
||||
return
|
||||
}
|
||||
}
|
|
@ -0,0 +1,62 @@
|
|||
package ncloud
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
ncloud "github.com/NaverCloudPlatform/ncloud-sdk-go/sdk"
|
||||
"testing"
|
||||
|
||||
"github.com/mitchellh/multistep"
|
||||
)
|
||||
|
||||
func TestStepCreatePublicIPInstanceShouldFailIfOperationCreatePublicIPInstanceFails(t *testing.T) {
|
||||
var testSubject = &StepCreatePublicIPInstance{
|
||||
CreatePublicIPInstance: func(serverInstanceNo string) (*ncloud.PublicIPInstance, error) {
|
||||
return nil, fmt.Errorf("!! Unit Test FAIL !!")
|
||||
},
|
||||
Say: func(message string) {},
|
||||
Error: func(e error) {},
|
||||
}
|
||||
|
||||
stateBag := createTestStateBagStepCreateServerImage()
|
||||
|
||||
var result = testSubject.Run(stateBag)
|
||||
|
||||
if result != multistep.ActionHalt {
|
||||
t.Fatalf("Expected the step to return 'ActionHalt', but got '%d'.", result)
|
||||
}
|
||||
|
||||
if _, ok := stateBag.GetOk("Error"); ok == false {
|
||||
t.Fatal("Expected the step to set stateBag['Error'], but it was not.")
|
||||
}
|
||||
}
|
||||
|
||||
func TestStepCreatePublicIPInstanceShouldPassIfOperationCreatePublicIPInstancePasses(t *testing.T) {
|
||||
var testSubject = &StepCreatePublicIPInstance{
|
||||
CreatePublicIPInstance: func(serverInstanceNo string) (*ncloud.PublicIPInstance, error) {
|
||||
return &ncloud.PublicIPInstance{PublicIPInstanceNo: "a", PublicIP: "b"}, nil
|
||||
},
|
||||
Say: func(message string) {},
|
||||
Error: func(e error) {},
|
||||
Config: &Config{OSType: "Windows"},
|
||||
}
|
||||
|
||||
stateBag := createTestStateBagStepCreatePublicIPInstance()
|
||||
|
||||
var result = testSubject.Run(stateBag)
|
||||
|
||||
if result != multistep.ActionContinue {
|
||||
t.Fatalf("Expected the step to return 'ActionContinue', but got '%d'.", result)
|
||||
}
|
||||
|
||||
if _, ok := stateBag.GetOk("Error"); ok == true {
|
||||
t.Fatalf("Expected the step to not set stateBag['Error'], but it was.")
|
||||
}
|
||||
}
|
||||
|
||||
func createTestStateBagStepCreatePublicIPInstance() multistep.StateBag {
|
||||
stateBag := new(multistep.BasicStateBag)
|
||||
|
||||
stateBag.Put("InstanceNo", "a")
|
||||
|
||||
return stateBag
|
||||
}
|
|
@ -0,0 +1,77 @@
|
|||
package ncloud
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"fmt"
|
||||
"time"
|
||||
|
||||
ncloud "github.com/NaverCloudPlatform/ncloud-sdk-go/sdk"
|
||||
"github.com/hashicorp/packer/packer"
|
||||
"github.com/mitchellh/multistep"
|
||||
)
|
||||
|
||||
type StepCreateServerImage struct {
|
||||
Conn *ncloud.Conn
|
||||
CreateServerImage func(serverInstanceNo string) (*ncloud.ServerImage, error)
|
||||
Say func(message string)
|
||||
Error func(e error)
|
||||
Config *Config
|
||||
}
|
||||
|
||||
func NewStepCreateServerImage(conn *ncloud.Conn, ui packer.Ui, config *Config) *StepCreateServerImage {
|
||||
var step = &StepCreateServerImage{
|
||||
Conn: conn,
|
||||
Say: func(message string) { ui.Say(message) },
|
||||
Error: func(e error) { ui.Error(e.Error()) },
|
||||
Config: config,
|
||||
}
|
||||
|
||||
step.CreateServerImage = step.createServerImage
|
||||
|
||||
return step
|
||||
}
|
||||
|
||||
func (s *StepCreateServerImage) createServerImage(serverInstanceNo string) (*ncloud.ServerImage, error) {
|
||||
// 서버 인스턴스 상태가 정지 중일 경우에는 서버 이미지 생성할 수 없음.
|
||||
if err := waiterServerInstanceStatus(s.Conn, serverInstanceNo, "NSTOP", 1*time.Minute); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
reqParams := new(ncloud.RequestCreateServerImage)
|
||||
reqParams.MemberServerImageName = s.Config.ServerImageName
|
||||
reqParams.MemberServerImageDescription = s.Config.ServerImageDescription
|
||||
reqParams.ServerInstanceNo = serverInstanceNo
|
||||
|
||||
memberServerImageList, err := s.Conn.CreateMemberServerImage(reqParams)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("error code: %d , error message: %s", memberServerImageList.ReturnCode, memberServerImageList.ReturnMessage)
|
||||
}
|
||||
|
||||
serverImage := memberServerImageList.MemberServerImageList[0]
|
||||
|
||||
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 {
|
||||
return nil, errors.New("TIMEOUT : Server Image is not created")
|
||||
}
|
||||
|
||||
s.Say(fmt.Sprintf("Server Image[%s:%s] is created", serverImage.MemberServerImageName, serverImage.MemberServerImageNo))
|
||||
|
||||
return &serverImage, nil
|
||||
}
|
||||
|
||||
func (s *StepCreateServerImage) Run(state multistep.StateBag) multistep.StepAction {
|
||||
s.Say("Create Server Image")
|
||||
|
||||
serverInstanceNo := state.Get("InstanceNo").(string)
|
||||
|
||||
serverImage, err := s.CreateServerImage(serverInstanceNo)
|
||||
if err == nil {
|
||||
state.Put("memberServerImage", serverImage)
|
||||
}
|
||||
|
||||
return processStepResult(err, s.Error, state)
|
||||
}
|
||||
|
||||
func (*StepCreateServerImage) Cleanup(multistep.StateBag) {
|
||||
}
|
|
@ -0,0 +1,58 @@
|
|||
package ncloud
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
ncloud "github.com/NaverCloudPlatform/ncloud-sdk-go/sdk"
|
||||
"testing"
|
||||
|
||||
"github.com/mitchellh/multistep"
|
||||
)
|
||||
|
||||
func TestStepCreateServerImageShouldFailIfOperationCreateServerImageFails(t *testing.T) {
|
||||
var testSubject = &StepCreateServerImage{
|
||||
CreateServerImage: func(serverInstanceNo string) (*ncloud.ServerImage, error) {
|
||||
return nil, fmt.Errorf("!! Unit Test FAIL !!")
|
||||
},
|
||||
Say: func(message string) {},
|
||||
Error: func(e error) {},
|
||||
}
|
||||
|
||||
stateBag := createTestStateBagStepCreateServerImage()
|
||||
|
||||
var result = testSubject.Run(stateBag)
|
||||
|
||||
if result != multistep.ActionHalt {
|
||||
t.Fatalf("Expected the step to return 'ActionHalt', but got '%d'.", result)
|
||||
}
|
||||
|
||||
if _, ok := stateBag.GetOk("Error"); ok == false {
|
||||
t.Fatal("Expected the step to set stateBag['Error'], but it was not.")
|
||||
}
|
||||
}
|
||||
func TestStepCreateServerImageShouldPassIfOperationCreateServerImagePasses(t *testing.T) {
|
||||
var testSubject = &StepCreateServerImage{
|
||||
CreateServerImage: func(serverInstanceNo string) (*ncloud.ServerImage, error) { return nil, nil },
|
||||
Say: func(message string) {},
|
||||
Error: func(e error) {},
|
||||
}
|
||||
|
||||
stateBag := createTestStateBagStepCreateServerImage()
|
||||
|
||||
var result = testSubject.Run(stateBag)
|
||||
|
||||
if result != multistep.ActionContinue {
|
||||
t.Fatalf("Expected the step to return 'ActionContinue', but got '%d'.", result)
|
||||
}
|
||||
|
||||
if _, ok := stateBag.GetOk("Error"); ok == true {
|
||||
t.Fatalf("Expected the step to not set stateBag['Error'], but it was.")
|
||||
}
|
||||
}
|
||||
|
||||
func createTestStateBagStepCreateServerImage() multistep.StateBag {
|
||||
stateBag := new(multistep.BasicStateBag)
|
||||
|
||||
stateBag.Put("InstanceNo", "a")
|
||||
|
||||
return stateBag
|
||||
}
|
|
@ -0,0 +1,129 @@
|
|||
package ncloud
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"fmt"
|
||||
"log"
|
||||
"time"
|
||||
|
||||
ncloud "github.com/NaverCloudPlatform/ncloud-sdk-go/sdk"
|
||||
"github.com/hashicorp/packer/packer"
|
||||
"github.com/mitchellh/multistep"
|
||||
)
|
||||
|
||||
type StepCreateServerInstance struct {
|
||||
Conn *ncloud.Conn
|
||||
CreateServerInstance func(loginKeyName string, zoneNo string) (string, error)
|
||||
CheckServerInstanceStatusIsRunning func(serverInstanceNo string) error
|
||||
Say func(message string)
|
||||
Error func(e error)
|
||||
Config *Config
|
||||
serverInstanceNo string
|
||||
}
|
||||
|
||||
func NewStepCreateServerInstance(conn *ncloud.Conn, ui packer.Ui, config *Config) *StepCreateServerInstance {
|
||||
var step = &StepCreateServerInstance{
|
||||
Conn: conn,
|
||||
Say: func(message string) { ui.Say(message) },
|
||||
Error: func(e error) { ui.Error(e.Error()) },
|
||||
Config: config,
|
||||
}
|
||||
|
||||
step.CreateServerInstance = step.createServerInstance
|
||||
|
||||
return step
|
||||
}
|
||||
|
||||
func (s *StepCreateServerInstance) createServerInstance(loginKeyName string, zoneNo string) (string, error) {
|
||||
reqParams := new(ncloud.RequestCreateServerInstance)
|
||||
reqParams.ServerProductCode = s.Config.ServerProductCode
|
||||
reqParams.MemberServerImageNo = s.Config.MemberServerImageNo
|
||||
if s.Config.MemberServerImageNo == "" {
|
||||
reqParams.ServerImageProductCode = s.Config.ServerImageProductCode
|
||||
}
|
||||
reqParams.LoginKeyName = loginKeyName
|
||||
reqParams.ZoneNo = zoneNo
|
||||
reqParams.FeeSystemTypeCode = s.Config.FeeSystemTypeCode
|
||||
|
||||
if s.Config.UserData != "" {
|
||||
reqParams.UserData = s.Config.UserData
|
||||
}
|
||||
|
||||
if s.Config.AccessControlGroupConfigurationNo != "" {
|
||||
reqParams.AccessControlGroupConfigurationNoList = []string{s.Config.AccessControlGroupConfigurationNo}
|
||||
}
|
||||
|
||||
serverInstanceList, err := s.Conn.CreateServerInstances(reqParams)
|
||||
if err != nil {
|
||||
return "", fmt.Errorf("error code: %d, error message: %s", serverInstanceList.ReturnCode, serverInstanceList.ReturnMessage)
|
||||
}
|
||||
|
||||
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 := waiterServerInstanceStatus(s.Conn, s.serverInstanceNo, "RUN", 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) Run(state multistep.StateBag) multistep.StepAction {
|
||||
s.Say("Create Server Instance")
|
||||
|
||||
var loginKey = state.Get("LoginKey").(*LoginKey)
|
||||
var zoneNo = state.Get("ZoneNo").(string)
|
||||
|
||||
serverInstanceNo, err := s.CreateServerInstance(loginKey.KeyName, zoneNo)
|
||||
if err == nil {
|
||||
state.Put("InstanceNo", serverInstanceNo)
|
||||
}
|
||||
|
||||
return processStepResult(err, s.Error, state)
|
||||
}
|
||||
|
||||
func (s *StepCreateServerInstance) Cleanup(state multistep.StateBag) {
|
||||
_, cancelled := state.GetOk(multistep.StateCancelled)
|
||||
_, halted := state.GetOk(multistep.StateHalted)
|
||||
|
||||
if !cancelled && !halted {
|
||||
return
|
||||
}
|
||||
|
||||
if s.serverInstanceNo == "" {
|
||||
return
|
||||
}
|
||||
|
||||
reqParams := new(ncloud.RequestGetServerInstanceList)
|
||||
reqParams.ServerInstanceNoList = []string{s.serverInstanceNo}
|
||||
|
||||
serverInstanceList, err := s.Conn.GetServerInstanceList(reqParams)
|
||||
if err != nil || serverInstanceList.TotalRows == 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(ncloud.RequestStopServerInstances)
|
||||
reqParams.ServerInstanceNoList = []string{s.serverInstanceNo}
|
||||
|
||||
log.Println("Stop Server Instance")
|
||||
s.Conn.StopServerInstances(reqParams)
|
||||
waiterServerInstanceStatus(s.Conn, s.serverInstanceNo, "NSTOP", time.Minute)
|
||||
}
|
||||
|
||||
// terminate server instance
|
||||
if serverInstance.ServerInstanceStatus.Code != "TERMT" {
|
||||
reqParams := new(ncloud.RequestTerminateServerInstances)
|
||||
reqParams.ServerInstanceNoList = []string{s.serverInstanceNo}
|
||||
|
||||
log.Println("Terminate Server Instance")
|
||||
s.Conn.TerminateServerInstances(reqParams)
|
||||
}
|
||||
}
|
|
@ -0,0 +1,58 @@
|
|||
package ncloud
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"github.com/mitchellh/multistep"
|
||||
"testing"
|
||||
)
|
||||
|
||||
func TestStepCreateServerInstanceShouldFailIfOperationCreateFails(t *testing.T) {
|
||||
var testSubject = &StepCreateServerInstance{
|
||||
CreateServerInstance: func(loginKeyName string, zoneNo string) (string, error) {
|
||||
return "", fmt.Errorf("!! Unit Test FAIL !!")
|
||||
},
|
||||
Say: func(message string) {},
|
||||
Error: func(e error) {},
|
||||
}
|
||||
|
||||
stateBag := createTestStateBagStepCreateServerInstance()
|
||||
|
||||
var result = testSubject.Run(stateBag)
|
||||
|
||||
if result != multistep.ActionHalt {
|
||||
t.Fatalf("Expected the step to return 'ActionHalt', but got '%d'.", result)
|
||||
}
|
||||
|
||||
if _, ok := stateBag.GetOk("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) (string, error) { return "", nil },
|
||||
Say: func(message string) {},
|
||||
Error: func(e error) {},
|
||||
}
|
||||
|
||||
stateBag := createTestStateBagStepCreateServerInstance()
|
||||
|
||||
var result = testSubject.Run(stateBag)
|
||||
|
||||
if result != multistep.ActionContinue {
|
||||
t.Fatalf("Expected the step to return 'ActionContinue', but got '%d'.", result)
|
||||
}
|
||||
|
||||
if _, ok := stateBag.GetOk("Error"); ok == true {
|
||||
t.Fatalf("Expected the step to not set stateBag['Error'], but it was.")
|
||||
}
|
||||
}
|
||||
|
||||
func createTestStateBagStepCreateServerInstance() multistep.StateBag {
|
||||
stateBag := new(multistep.BasicStateBag)
|
||||
|
||||
stateBag.Put("LoginKey", &LoginKey{"a", "b"})
|
||||
stateBag.Put("ZoneNo", "1")
|
||||
|
||||
return stateBag
|
||||
}
|
|
@ -0,0 +1,95 @@
|
|||
package ncloud
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"fmt"
|
||||
"log"
|
||||
"time"
|
||||
|
||||
ncloud "github.com/NaverCloudPlatform/ncloud-sdk-go/sdk"
|
||||
"github.com/hashicorp/packer/packer"
|
||||
"github.com/mitchellh/multistep"
|
||||
)
|
||||
|
||||
type StepDeleteBlockStorageInstance struct {
|
||||
Conn *ncloud.Conn
|
||||
DeleteBlockStorageInstance func(blockStorageInstanceNo string) error
|
||||
Say func(message string)
|
||||
Error func(e error)
|
||||
Config *Config
|
||||
}
|
||||
|
||||
func NewStepDeleteBlockStorageInstance(conn *ncloud.Conn, ui packer.Ui, config *Config) *StepDeleteBlockStorageInstance {
|
||||
var step = &StepDeleteBlockStorageInstance{
|
||||
Conn: conn,
|
||||
Say: func(message string) { ui.Say(message) },
|
||||
Error: func(e error) { ui.Error(e.Error()) },
|
||||
Config: config,
|
||||
}
|
||||
|
||||
step.DeleteBlockStorageInstance = step.deleteBlockStorageInstance
|
||||
|
||||
return step
|
||||
}
|
||||
|
||||
func (s *StepDeleteBlockStorageInstance) getBlockInstanceList(serverInstanceNo string) []string {
|
||||
reqParams := new(ncloud.RequestBlockStorageInstanceList)
|
||||
reqParams.ServerInstanceNo = serverInstanceNo
|
||||
|
||||
blockStorageInstanceList, err := s.Conn.GetBlockStorageInstance(reqParams)
|
||||
if err != nil {
|
||||
return nil
|
||||
}
|
||||
|
||||
if blockStorageInstanceList.TotalRows == 1 {
|
||||
return nil
|
||||
}
|
||||
|
||||
var instanceList []string
|
||||
|
||||
for _, blockStorageInstance := range blockStorageInstanceList.BlockStorageInstance {
|
||||
log.Println(blockStorageInstance)
|
||||
if blockStorageInstance.BlockStorageType.Code != "BASIC" {
|
||||
instanceList = append(instanceList, blockStorageInstance.BlockStorageInstanceNo)
|
||||
}
|
||||
}
|
||||
|
||||
return instanceList
|
||||
}
|
||||
|
||||
func (s *StepDeleteBlockStorageInstance) deleteBlockStorageInstance(serverInstanceNo string) error {
|
||||
blockStorageInstanceList := s.getBlockInstanceList(serverInstanceNo)
|
||||
if blockStorageInstanceList == nil || len(blockStorageInstanceList) == 0 {
|
||||
return nil
|
||||
}
|
||||
|
||||
result, err := s.Conn.DeleteBlockStorageInstances(blockStorageInstanceList)
|
||||
if err != nil {
|
||||
return fmt.Errorf("error code: %d , error message: %s", result.ReturnCode, result.ReturnMessage)
|
||||
}
|
||||
|
||||
s.Say(fmt.Sprintf("Block Storage Instance is deleted. Block Storage InstanceNo is %s", blockStorageInstanceList))
|
||||
|
||||
if err := waiterDetachedBlockStorageInstance(s.Conn, serverInstanceNo, time.Minute); err != nil {
|
||||
return errors.New("TIMEOUT : Block Storage instance status is not deattached")
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (s *StepDeleteBlockStorageInstance) Run(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)
|
||||
|
||||
err := s.DeleteBlockStorageInstance(serverInstanceNo)
|
||||
|
||||
return processStepResult(err, s.Error, state)
|
||||
}
|
||||
|
||||
func (*StepDeleteBlockStorageInstance) Cleanup(multistep.StateBag) {
|
||||
}
|
|
@ -0,0 +1,57 @@
|
|||
package ncloud
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"github.com/mitchellh/multistep"
|
||||
"testing"
|
||||
)
|
||||
|
||||
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},
|
||||
}
|
||||
|
||||
stateBag := createTestStateBagStepDeleteBlockStorageInstance()
|
||||
|
||||
var result = testSubject.Run(stateBag)
|
||||
|
||||
if result != multistep.ActionHalt {
|
||||
t.Fatalf("Expected the step to return 'ActionHalt', but got '%d'.", result)
|
||||
}
|
||||
|
||||
if _, ok := stateBag.GetOk("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},
|
||||
}
|
||||
|
||||
stateBag := createTestStateBagStepDeleteBlockStorageInstance()
|
||||
|
||||
var result = testSubject.Run(stateBag)
|
||||
|
||||
if result != multistep.ActionContinue {
|
||||
t.Fatalf("Expected the step to return 'ActionContinue', but got '%d'.", result)
|
||||
}
|
||||
|
||||
if _, ok := stateBag.GetOk("Error"); ok == true {
|
||||
t.Fatalf("Expected the step to not set stateBag['Error'], but it was.")
|
||||
}
|
||||
}
|
||||
|
||||
func createTestStateBagStepDeleteBlockStorageInstance() multistep.StateBag {
|
||||
stateBag := new(multistep.BasicStateBag)
|
||||
|
||||
stateBag.Put("InstanceNo", "1")
|
||||
|
||||
return stateBag
|
||||
}
|
|
@ -0,0 +1,51 @@
|
|||
package ncloud
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
|
||||
ncloud "github.com/NaverCloudPlatform/ncloud-sdk-go/sdk"
|
||||
"github.com/hashicorp/packer/packer"
|
||||
"github.com/mitchellh/multistep"
|
||||
)
|
||||
|
||||
type StepDeleteLoginKey struct {
|
||||
Conn *ncloud.Conn
|
||||
DeleteLoginKey func(keyName string) error
|
||||
Say func(message string)
|
||||
Error func(e error)
|
||||
}
|
||||
|
||||
func NewStepDeleteLoginKey(conn *ncloud.Conn, ui packer.Ui) *StepDeleteLoginKey {
|
||||
var step = &StepDeleteLoginKey{
|
||||
Conn: conn,
|
||||
Say: func(message string) { ui.Say(message) },
|
||||
Error: func(e error) { ui.Error(e.Error()) },
|
||||
}
|
||||
|
||||
step.DeleteLoginKey = step.deleteLoginKey
|
||||
|
||||
return step
|
||||
}
|
||||
|
||||
func (s *StepDeleteLoginKey) deleteLoginKey(keyName string) error {
|
||||
resp, err := s.Conn.DeleteLoginKey(keyName)
|
||||
if err != nil {
|
||||
return fmt.Errorf("error code: %d , error message: %s", resp.ReturnCode, resp.ReturnMessage)
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (s *StepDeleteLoginKey) Run(state multistep.StateBag) multistep.StepAction {
|
||||
var loginKey = state.Get("LoginKey").(*LoginKey)
|
||||
|
||||
err := s.DeleteLoginKey(loginKey.KeyName)
|
||||
if err == nil {
|
||||
s.Say(fmt.Sprintf("Login Key[%s] is deleted", loginKey.KeyName))
|
||||
}
|
||||
|
||||
return processStepResult(err, s.Error, state)
|
||||
}
|
||||
|
||||
func (*StepDeleteLoginKey) Cleanup(multistep.StateBag) {
|
||||
}
|
|
@ -0,0 +1,55 @@
|
|||
package ncloud
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"github.com/mitchellh/multistep"
|
||||
"testing"
|
||||
)
|
||||
|
||||
func TestStepDeleteLoginKeyShouldFailIfOperationDeleteLoginKeyFails(t *testing.T) {
|
||||
var testSubject = &StepDeleteLoginKey{
|
||||
DeleteLoginKey: func(keyName string) error { return fmt.Errorf("!! Unit Test FAIL !!") },
|
||||
Say: func(message string) {},
|
||||
Error: func(e error) {},
|
||||
}
|
||||
|
||||
stateBag := DeleteTestStateBagStepDeleteLoginKey()
|
||||
|
||||
var result = testSubject.Run(stateBag)
|
||||
|
||||
if result != multistep.ActionHalt {
|
||||
t.Fatalf("Expected the step to return 'ActionHalt', but got '%d'.", result)
|
||||
}
|
||||
|
||||
if _, ok := stateBag.GetOk("Error"); ok == false {
|
||||
t.Fatal("Expected the step to set stateBag['Error'], but it was not.")
|
||||
}
|
||||
}
|
||||
|
||||
func TestStepDeleteLoginKeyShouldPassIfOperationDeleteLoginKeyPasses(t *testing.T) {
|
||||
var testSubject = &StepDeleteLoginKey{
|
||||
DeleteLoginKey: func(keyName string) error { return nil },
|
||||
Say: func(message string) {},
|
||||
Error: func(e error) {},
|
||||
}
|
||||
|
||||
stateBag := DeleteTestStateBagStepDeleteLoginKey()
|
||||
|
||||
var result = testSubject.Run(stateBag)
|
||||
|
||||
if result != multistep.ActionContinue {
|
||||
t.Fatalf("Expected the step to return 'ActionContinue', but got '%d'.", result)
|
||||
}
|
||||
|
||||
if _, ok := stateBag.GetOk("Error"); ok == true {
|
||||
t.Fatalf("Expected the step to not set stateBag['Error'], but it was.")
|
||||
}
|
||||
}
|
||||
|
||||
func DeleteTestStateBagStepDeleteLoginKey() multistep.StateBag {
|
||||
stateBag := new(multistep.BasicStateBag)
|
||||
|
||||
stateBag.Put("LoginKey", &LoginKey{"a", "b"})
|
||||
|
||||
return stateBag
|
||||
}
|
|
@ -0,0 +1,78 @@
|
|||
package ncloud
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"fmt"
|
||||
"log"
|
||||
"time"
|
||||
|
||||
ncloud "github.com/NaverCloudPlatform/ncloud-sdk-go/sdk"
|
||||
"github.com/hashicorp/packer/packer"
|
||||
"github.com/mitchellh/multistep"
|
||||
)
|
||||
|
||||
type StepDeletePublicIPInstance struct {
|
||||
Conn *ncloud.Conn
|
||||
DeletePublicIPInstance func(publicIPInstanceNo string) error
|
||||
Say func(message string)
|
||||
Error func(e error)
|
||||
}
|
||||
|
||||
func NewStepDeletePublicIPInstance(conn *ncloud.Conn, ui packer.Ui) *StepDeletePublicIPInstance {
|
||||
var step = &StepDeletePublicIPInstance{
|
||||
Conn: conn,
|
||||
Say: func(message string) { ui.Say(message) },
|
||||
Error: func(e error) { ui.Error(e.Error()) },
|
||||
}
|
||||
|
||||
step.DeletePublicIPInstance = step.deletePublicIPInstance
|
||||
|
||||
return step
|
||||
}
|
||||
|
||||
func (s *StepDeletePublicIPInstance) deletePublicIPInstance(publicIPInstanceNo string) error {
|
||||
reqParams := new(ncloud.RequestDeletePublicIPInstances)
|
||||
reqParams.PublicIPInstanceNoList = []string{publicIPInstanceNo}
|
||||
|
||||
c1 := make(chan error, 1)
|
||||
|
||||
go func() {
|
||||
for {
|
||||
resp, err := s.Conn.DeletePublicIPInstances(reqParams)
|
||||
if err != nil && (resp.ReturnCode == 24073 || resp.ReturnCode == 25032) {
|
||||
// error code : 24073 : Unable to destroy the server since a public IP is associated with the server. First, please disassociate a public IP from the server.
|
||||
// error code : 25032 : You may not delete sk since (other) user is changing the target official IP settings.
|
||||
log.Println(resp.ReturnCode, resp.ReturnMessage)
|
||||
} else if err != nil {
|
||||
c1 <- fmt.Errorf("error code: %d, error message: %s", resp.ReturnCode, resp.ReturnMessage)
|
||||
return
|
||||
} else if err == nil {
|
||||
s.Say(fmt.Sprintf("Public IP Instance [%s] is deleted.", publicIPInstanceNo))
|
||||
c1 <- nil
|
||||
return
|
||||
}
|
||||
|
||||
time.Sleep(time.Second * 5)
|
||||
}
|
||||
}()
|
||||
|
||||
select {
|
||||
case res := <-c1:
|
||||
return res
|
||||
case <-time.After(time.Second * 60):
|
||||
return errors.New("TIMEOUT : Can't delete server instance")
|
||||
}
|
||||
}
|
||||
|
||||
func (s *StepDeletePublicIPInstance) Run(state multistep.StateBag) multistep.StepAction {
|
||||
s.Say("Delete Public IP Instance")
|
||||
|
||||
publicIPInstance := state.Get("PublicIPInstance").(*ncloud.PublicIPInstance)
|
||||
|
||||
err := s.DeletePublicIPInstance(publicIPInstance.PublicIPInstanceNo)
|
||||
|
||||
return processStepResult(err, s.Error, state)
|
||||
}
|
||||
|
||||
func (*StepDeletePublicIPInstance) Cleanup(multistep.StateBag) {
|
||||
}
|
|
@ -0,0 +1,57 @@
|
|||
package ncloud
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
ncloud "github.com/NaverCloudPlatform/ncloud-sdk-go/sdk"
|
||||
"testing"
|
||||
|
||||
"github.com/mitchellh/multistep"
|
||||
)
|
||||
|
||||
func TestStepDeletePublicIPInstanceShouldFailIfOperationDeletePublicIPInstanceFails(t *testing.T) {
|
||||
var testSubject = &StepDeletePublicIPInstance{
|
||||
DeletePublicIPInstance: func(publicIPInstanceNo string) error { return fmt.Errorf("!! Unit Test FAIL !!") },
|
||||
Say: func(message string) {},
|
||||
Error: func(e error) {},
|
||||
}
|
||||
|
||||
stateBag := createTestStateBagStepDeletePublicIPInstance()
|
||||
|
||||
var result = testSubject.Run(stateBag)
|
||||
|
||||
if result != multistep.ActionHalt {
|
||||
t.Fatalf("Expected the step to return 'ActionHalt', but got '%d'.", result)
|
||||
}
|
||||
|
||||
if _, ok := stateBag.GetOk("Error"); ok == false {
|
||||
t.Fatal("Expected the step to set stateBag['Error'], but it was not.")
|
||||
}
|
||||
}
|
||||
|
||||
func TestStepDeletePublicIPInstanceShouldPassIfOperationDeletePublicIPInstancePasses(t *testing.T) {
|
||||
var testSubject = &StepDeletePublicIPInstance{
|
||||
DeletePublicIPInstance: func(publicIPInstanceNo string) error { return nil },
|
||||
Say: func(message string) {},
|
||||
Error: func(e error) {},
|
||||
}
|
||||
|
||||
stateBag := createTestStateBagStepDeletePublicIPInstance()
|
||||
|
||||
var result = testSubject.Run(stateBag)
|
||||
|
||||
if result != multistep.ActionContinue {
|
||||
t.Fatalf("Expected the step to return 'ActionContinue', but got '%d'.", result)
|
||||
}
|
||||
|
||||
if _, ok := stateBag.GetOk("Error"); ok == true {
|
||||
t.Fatalf("Expected the step to not set stateBag['Error'], but it was.")
|
||||
}
|
||||
}
|
||||
|
||||
func createTestStateBagStepDeletePublicIPInstance() multistep.StateBag {
|
||||
stateBag := new(multistep.BasicStateBag)
|
||||
|
||||
stateBag.Put("PublicIPInstance", &ncloud.PublicIPInstance{PublicIPInstanceNo: "22"})
|
||||
|
||||
return stateBag
|
||||
}
|
|
@ -0,0 +1,57 @@
|
|||
package ncloud
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
|
||||
ncloud "github.com/NaverCloudPlatform/ncloud-sdk-go/sdk"
|
||||
"github.com/hashicorp/packer/packer"
|
||||
"github.com/mitchellh/multistep"
|
||||
)
|
||||
|
||||
type StepGetRootPassword struct {
|
||||
Conn *ncloud.Conn
|
||||
GetRootPassword func(serverInstanceNo string, privateKey string) (string, error)
|
||||
Say func(message string)
|
||||
Error func(e error)
|
||||
}
|
||||
|
||||
func NewStepGetRootPassword(conn *ncloud.Conn, ui packer.Ui) *StepGetRootPassword {
|
||||
var step = &StepGetRootPassword{
|
||||
Conn: conn,
|
||||
Say: func(message string) { ui.Say(message) },
|
||||
Error: func(e error) { ui.Error(e.Error()) },
|
||||
}
|
||||
|
||||
step.GetRootPassword = step.getRootPassword
|
||||
|
||||
return step
|
||||
}
|
||||
|
||||
func (s *StepGetRootPassword) getRootPassword(serverInstanceNo string, privateKey string) (string, error) {
|
||||
reqParams := new(ncloud.RequestGetRootPassword)
|
||||
reqParams.ServerInstanceNo = serverInstanceNo
|
||||
reqParams.PrivateKey = privateKey
|
||||
|
||||
rootPassword, err := s.Conn.GetRootPassword(reqParams)
|
||||
if err != nil {
|
||||
return "", fmt.Errorf("error code: %d, error message: %s", rootPassword.ReturnCode, rootPassword.ReturnMessage)
|
||||
}
|
||||
|
||||
return rootPassword.RootPassword, nil
|
||||
}
|
||||
|
||||
func (s *StepGetRootPassword) Run(state multistep.StateBag) multistep.StepAction {
|
||||
s.Say("Get Root Password")
|
||||
|
||||
serverInstanceNo := state.Get("InstanceNo").(string)
|
||||
loginKey := state.Get("LoginKey").(*LoginKey)
|
||||
|
||||
rootPassword, err := s.GetRootPassword(serverInstanceNo, loginKey.PrivateKey)
|
||||
|
||||
state.Put("Password", rootPassword)
|
||||
|
||||
return processStepResult(err, s.Error, state)
|
||||
}
|
||||
|
||||
func (*StepGetRootPassword) Cleanup(multistep.StateBag) {
|
||||
}
|
|
@ -0,0 +1,56 @@
|
|||
package ncloud
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"github.com/mitchellh/multistep"
|
||||
"testing"
|
||||
)
|
||||
|
||||
func TestStepGetRootPasswordShouldFailIfOperationGetRootPasswordFails(t *testing.T) {
|
||||
var testSubject = &StepGetRootPassword{
|
||||
GetRootPassword: func(string, string) (string, error) { return "", fmt.Errorf("!! Unit Test FAIL !!") },
|
||||
Say: func(message string) {},
|
||||
Error: func(e error) {},
|
||||
}
|
||||
|
||||
stateBag := DeleteTestStateBagStepGetRootPassword()
|
||||
|
||||
var result = testSubject.Run(stateBag)
|
||||
|
||||
if result != multistep.ActionHalt {
|
||||
t.Fatalf("Expected the step to return 'ActionHalt', but got '%d'.", result)
|
||||
}
|
||||
|
||||
if _, ok := stateBag.GetOk("Error"); ok == false {
|
||||
t.Fatal("Expected the step to set stateBag['Error'], but it was not.")
|
||||
}
|
||||
}
|
||||
|
||||
func TestStepGetRootPasswordShouldPassIfOperationGetRootPasswordPasses(t *testing.T) {
|
||||
var testSubject = &StepGetRootPassword{
|
||||
GetRootPassword: func(string, string) (string, error) { return "a", nil },
|
||||
Say: func(message string) {},
|
||||
Error: func(e error) {},
|
||||
}
|
||||
|
||||
stateBag := DeleteTestStateBagStepGetRootPassword()
|
||||
|
||||
var result = testSubject.Run(stateBag)
|
||||
|
||||
if result != multistep.ActionContinue {
|
||||
t.Fatalf("Expected the step to return 'ActionContinue', but got '%d'.", result)
|
||||
}
|
||||
|
||||
if _, ok := stateBag.GetOk("Error"); ok == true {
|
||||
t.Fatalf("Expected the step to not set stateBag['Error'], but it was.")
|
||||
}
|
||||
}
|
||||
|
||||
func DeleteTestStateBagStepGetRootPassword() multistep.StateBag {
|
||||
stateBag := new(multistep.BasicStateBag)
|
||||
|
||||
stateBag.Put("LoginKey", &LoginKey{"a", "b"})
|
||||
stateBag.Put("InstanceNo", "a")
|
||||
|
||||
return stateBag
|
||||
}
|
|
@ -0,0 +1,64 @@
|
|||
package ncloud
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"log"
|
||||
"time"
|
||||
|
||||
ncloud "github.com/NaverCloudPlatform/ncloud-sdk-go/sdk"
|
||||
"github.com/hashicorp/packer/packer"
|
||||
"github.com/mitchellh/multistep"
|
||||
)
|
||||
|
||||
type StepStopServerInstance struct {
|
||||
Conn *ncloud.Conn
|
||||
StopServerInstance func(serverInstanceNo string) error
|
||||
Say func(message string)
|
||||
Error func(e error)
|
||||
}
|
||||
|
||||
func NewStepStopServerInstance(conn *ncloud.Conn, ui packer.Ui) *StepStopServerInstance {
|
||||
var step = &StepStopServerInstance{
|
||||
Conn: conn,
|
||||
Say: func(message string) { ui.Say(message) },
|
||||
Error: func(e error) { ui.Error(e.Error()) },
|
||||
}
|
||||
|
||||
step.StopServerInstance = step.stopServerInstance
|
||||
|
||||
return step
|
||||
}
|
||||
|
||||
func (s *StepStopServerInstance) stopServerInstance(serverInstanceNo string) error {
|
||||
reqParams := new(ncloud.RequestStopServerInstances)
|
||||
reqParams.ServerInstanceNoList = []string{serverInstanceNo}
|
||||
|
||||
serverInstanceList, err := s.Conn.StopServerInstances(reqParams)
|
||||
if err != nil {
|
||||
return fmt.Errorf("error code: %d , error message: %s", serverInstanceList.ReturnCode, serverInstanceList.ReturnMessage)
|
||||
}
|
||||
|
||||
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 {
|
||||
return err
|
||||
}
|
||||
|
||||
s.Say(fmt.Sprintf("Server Instance stopped. Server InstanceNo is %s", serverInstanceList.ServerInstanceList[0].ServerInstanceNo))
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (s *StepStopServerInstance) Run(state multistep.StateBag) multistep.StepAction {
|
||||
s.Say("Stop Server Instance")
|
||||
|
||||
var serverInstanceNo = state.Get("InstanceNo").(string)
|
||||
|
||||
err := s.StopServerInstance(serverInstanceNo)
|
||||
|
||||
return processStepResult(err, s.Error, state)
|
||||
}
|
||||
|
||||
func (*StepStopServerInstance) Cleanup(multistep.StateBag) {
|
||||
}
|
|
@ -0,0 +1,55 @@
|
|||
package ncloud
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"testing"
|
||||
|
||||
"github.com/mitchellh/multistep"
|
||||
)
|
||||
|
||||
func TestStepStopServerInstanceShouldFailIfOperationStopFails(t *testing.T) {
|
||||
var testSubject = &StepStopServerInstance{
|
||||
StopServerInstance: func(serverInstanceNo string) error { return fmt.Errorf("!! Unit Test FAIL !!") },
|
||||
Say: func(message string) {},
|
||||
Error: func(e error) {},
|
||||
}
|
||||
|
||||
stateBag := createTestStateBagStepStopServerInstance()
|
||||
|
||||
var result = testSubject.Run(stateBag)
|
||||
|
||||
if result != multistep.ActionHalt {
|
||||
t.Fatalf("Expected the step to return 'ActionHalt', but got '%d'.", result)
|
||||
}
|
||||
|
||||
if _, ok := stateBag.GetOk("Error"); ok == false {
|
||||
t.Fatal("Expected the step to set stateBag['Error'], but it was not.")
|
||||
}
|
||||
}
|
||||
|
||||
func TestStepStopServerInstanceShouldPassIfOperationStopPasses(t *testing.T) {
|
||||
var testSubject = &StepStopServerInstance{
|
||||
StopServerInstance: func(serverInstanceNo string) error { return nil },
|
||||
Say: func(message string) {},
|
||||
Error: func(e error) {},
|
||||
}
|
||||
|
||||
stateBag := createTestStateBagStepStopServerInstance()
|
||||
|
||||
var result = testSubject.Run(stateBag)
|
||||
|
||||
if result != multistep.ActionContinue {
|
||||
t.Fatalf("Expected the step to return 'ActionContinue', but got '%d'.", result)
|
||||
}
|
||||
|
||||
if _, ok := stateBag.GetOk("Error"); ok == true {
|
||||
t.Fatalf("Expected the step to not set stateBag['Error'], but it was.")
|
||||
}
|
||||
}
|
||||
|
||||
func createTestStateBagStepStopServerInstance() multistep.StateBag {
|
||||
stateBag := new(multistep.BasicStateBag)
|
||||
|
||||
stateBag.Put("InstanceNo", "a")
|
||||
return stateBag
|
||||
}
|
|
@ -0,0 +1,81 @@
|
|||
package ncloud
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"fmt"
|
||||
"time"
|
||||
|
||||
ncloud "github.com/NaverCloudPlatform/ncloud-sdk-go/sdk"
|
||||
"github.com/hashicorp/packer/packer"
|
||||
"github.com/mitchellh/multistep"
|
||||
)
|
||||
|
||||
type StepTerminateServerInstance struct {
|
||||
Conn *ncloud.Conn
|
||||
TerminateServerInstance func(serverInstanceNo string) error
|
||||
Say func(message string)
|
||||
Error func(e error)
|
||||
}
|
||||
|
||||
func NewStepTerminateServerInstance(conn *ncloud.Conn, ui packer.Ui) *StepTerminateServerInstance {
|
||||
var step = &StepTerminateServerInstance{
|
||||
Conn: conn,
|
||||
Say: func(message string) { ui.Say(message) },
|
||||
Error: func(e error) { ui.Error(e.Error()) },
|
||||
}
|
||||
|
||||
step.TerminateServerInstance = step.terminateServerInstance
|
||||
|
||||
return step
|
||||
}
|
||||
|
||||
func (s *StepTerminateServerInstance) terminateServerInstance(serverInstanceNo string) error {
|
||||
reqParams := new(ncloud.RequestTerminateServerInstances)
|
||||
reqParams.ServerInstanceNoList = []string{serverInstanceNo}
|
||||
|
||||
serverInstanceList, err := s.Conn.TerminateServerInstances(reqParams)
|
||||
if err != nil {
|
||||
return fmt.Errorf("error code: %d , error message: %s", serverInstanceList.ReturnCode, serverInstanceList.ReturnMessage)
|
||||
}
|
||||
|
||||
c1 := make(chan error, 1)
|
||||
|
||||
go func() {
|
||||
reqParams := new(ncloud.RequestGetServerInstanceList)
|
||||
reqParams.ServerInstanceNoList = []string{serverInstanceNo}
|
||||
|
||||
for {
|
||||
|
||||
serverInstanceList, err := s.Conn.GetServerInstanceList(reqParams)
|
||||
if err != nil {
|
||||
c1 <- fmt.Errorf("error code: %d , error message: %s", serverInstanceList.ReturnCode, serverInstanceList.ReturnMessage)
|
||||
return
|
||||
} else if serverInstanceList.TotalRows == 0 {
|
||||
c1 <- nil
|
||||
return
|
||||
}
|
||||
|
||||
time.Sleep(time.Second * 3)
|
||||
}
|
||||
}()
|
||||
|
||||
select {
|
||||
case res := <-c1:
|
||||
return res
|
||||
case <-time.After(time.Second * 60):
|
||||
return errors.New("TIMEOUT : Can't terminate server instance")
|
||||
}
|
||||
}
|
||||
|
||||
func (s *StepTerminateServerInstance) Run(state multistep.StateBag) multistep.StepAction {
|
||||
s.Say("Terminate Server Instance")
|
||||
|
||||
var serverInstanceNo = state.Get("InstanceNo").(string)
|
||||
|
||||
err := s.TerminateServerInstance(serverInstanceNo)
|
||||
|
||||
return processStepResult(err, s.Error, state)
|
||||
}
|
||||
|
||||
func (*StepTerminateServerInstance) Cleanup(multistep.StateBag) {
|
||||
}
|
|
@ -0,0 +1,54 @@
|
|||
package ncloud
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"github.com/mitchellh/multistep"
|
||||
"testing"
|
||||
)
|
||||
|
||||
func TestStepTerminateServerInstanceShouldFailIfOperationTerminationFails(t *testing.T) {
|
||||
var testSubject = &StepTerminateServerInstance{
|
||||
TerminateServerInstance: func(serverInstanceNo string) error { return fmt.Errorf("!! Unit Test FAIL !!") },
|
||||
Say: func(message string) {},
|
||||
Error: func(e error) {},
|
||||
}
|
||||
|
||||
stateBag := createTestStateBagStepTerminateServerInstance()
|
||||
|
||||
var result = testSubject.Run(stateBag)
|
||||
|
||||
if result != multistep.ActionHalt {
|
||||
t.Fatalf("Expected the step to return 'ActionHalt', but got '%d'.", result)
|
||||
}
|
||||
|
||||
if _, ok := stateBag.GetOk("Error"); ok == false {
|
||||
t.Fatal("Expected the step to set stateBag['Error'], but it was not.")
|
||||
}
|
||||
}
|
||||
|
||||
func TestStepTerminateServerInstanceShouldPassIfOperationTerminationPasses(t *testing.T) {
|
||||
var testSubject = &StepTerminateServerInstance{
|
||||
TerminateServerInstance: func(serverInstanceNo string) error { return nil },
|
||||
Say: func(message string) {},
|
||||
Error: func(e error) {},
|
||||
}
|
||||
|
||||
stateBag := createTestStateBagStepTerminateServerInstance()
|
||||
|
||||
var result = testSubject.Run(stateBag)
|
||||
|
||||
if result != multistep.ActionContinue {
|
||||
t.Fatalf("Expected the step to return 'ActionContinue', but got '%d'.", result)
|
||||
}
|
||||
|
||||
if _, ok := stateBag.GetOk("Error"); ok == true {
|
||||
t.Fatalf("Expected the step to not set stateBag['Error'], but it was.")
|
||||
}
|
||||
}
|
||||
|
||||
func createTestStateBagStepTerminateServerInstance() multistep.StateBag {
|
||||
stateBag := new(multistep.BasicStateBag)
|
||||
|
||||
stateBag.Put("InstanceNo", "a")
|
||||
return stateBag
|
||||
}
|
|
@ -0,0 +1,263 @@
|
|||
package ncloud
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"errors"
|
||||
"fmt"
|
||||
"strings"
|
||||
|
||||
ncloud "github.com/NaverCloudPlatform/ncloud-sdk-go/sdk"
|
||||
"github.com/hashicorp/packer/packer"
|
||||
"github.com/mitchellh/multistep"
|
||||
"github.com/olekukonko/tablewriter"
|
||||
)
|
||||
|
||||
//StepValidateTemplate : struct for Validation a tempalte
|
||||
type StepValidateTemplate struct {
|
||||
Conn *ncloud.Conn
|
||||
Validate func() error
|
||||
Say func(message string)
|
||||
Error func(e error)
|
||||
Config *Config
|
||||
zoneNo string
|
||||
regionNo string
|
||||
}
|
||||
|
||||
// NewStepValidateTemplate : funciton for Validation a tempalte
|
||||
func NewStepValidateTemplate(conn *ncloud.Conn, ui packer.Ui, config *Config) *StepValidateTemplate {
|
||||
var step = &StepValidateTemplate{
|
||||
Conn: conn,
|
||||
Say: func(message string) { ui.Say(message) },
|
||||
Error: func(e error) { ui.Error(e.Error()) },
|
||||
Config: config,
|
||||
}
|
||||
|
||||
step.Validate = step.validateTemplate
|
||||
|
||||
return step
|
||||
}
|
||||
|
||||
// getZoneNo : get zoneNo
|
||||
func (s *StepValidateTemplate) getZoneNo() error {
|
||||
if s.Config.Region == "" {
|
||||
return nil
|
||||
}
|
||||
|
||||
regionList, err := s.Conn.GetRegionList()
|
||||
if err != nil {
|
||||
return fmt.Errorf("error code: %d , error message: %s", regionList.ReturnCode, regionList.ReturnMessage)
|
||||
}
|
||||
|
||||
var regionNo string
|
||||
for _, region := range regionList.RegionList {
|
||||
if strings.EqualFold(region.RegionName, s.Config.Region) {
|
||||
regionNo = region.RegionNo
|
||||
}
|
||||
}
|
||||
|
||||
if regionNo == "" {
|
||||
return fmt.Errorf("region %s is invalid", s.Config.Region)
|
||||
}
|
||||
|
||||
s.regionNo = regionNo
|
||||
|
||||
// Get ZoneNo
|
||||
ZoneList, err := s.Conn.GetZoneList(regionNo)
|
||||
if err != nil {
|
||||
return fmt.Errorf("error code: %d , error message: %s", ZoneList.ReturnCode, ZoneList.ReturnMessage)
|
||||
}
|
||||
|
||||
if len(ZoneList.Zone) > 0 {
|
||||
s.zoneNo = ZoneList.Zone[0].ZoneNo
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (s *StepValidateTemplate) validateMemberServerImage() error {
|
||||
var serverImageName = s.Config.ServerImageName
|
||||
|
||||
reqParams := new(ncloud.RequestServerImageList)
|
||||
reqParams.RegionNo = s.regionNo
|
||||
|
||||
memberServerImageList, err := s.Conn.GetMemberServerImageList(reqParams)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
var isExistMemberServerImageNo = false
|
||||
for _, image := range memberServerImageList.MemberServerImageList {
|
||||
// Check duplicate server_image_name
|
||||
if image.MemberServerImageName == serverImageName {
|
||||
return fmt.Errorf("server_image_name %s is exists", serverImageName)
|
||||
}
|
||||
|
||||
if image.MemberServerImageNo == s.Config.MemberServerImageNo {
|
||||
isExistMemberServerImageNo = true
|
||||
if s.Config.ServerProductCode == "" {
|
||||
s.Config.ServerProductCode = image.OriginalServerProductCode
|
||||
s.Say("server_product_code for member server image '" + image.OriginalServerProductCode + "' is configured automatically")
|
||||
}
|
||||
s.Config.ServerImageProductCode = image.OriginalServerImageProductCode
|
||||
}
|
||||
}
|
||||
|
||||
if s.Config.MemberServerImageNo != "" && !isExistMemberServerImageNo {
|
||||
return fmt.Errorf("member_server_image_no %s does not exist", s.Config.MemberServerImageNo)
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (s *StepValidateTemplate) validateServerImageProduct() error {
|
||||
var serverImageProductCode = s.Config.ServerImageProductCode
|
||||
if serverImageProductCode == "" {
|
||||
return nil
|
||||
}
|
||||
|
||||
reqParams := new(ncloud.RequestGetServerImageProductList)
|
||||
reqParams.RegionNo = s.regionNo
|
||||
|
||||
serverImageProductList, err := s.Conn.GetServerImageProductList(reqParams)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
var isExistServerImage = false
|
||||
var buf bytes.Buffer
|
||||
var productName string
|
||||
table := tablewriter.NewWriter(&buf)
|
||||
table.SetHeader([]string{"Name", "Code"})
|
||||
|
||||
for _, product := range serverImageProductList.Product {
|
||||
// Check exist server image product code
|
||||
if product.ProductCode == serverImageProductCode {
|
||||
isExistServerImage = true
|
||||
productName = product.ProductName
|
||||
break
|
||||
}
|
||||
|
||||
table.Append([]string{product.ProductName, product.ProductCode})
|
||||
}
|
||||
|
||||
if !isExistServerImage {
|
||||
reqParams.BlockStorageSize = 100
|
||||
|
||||
serverImageProductList, err := s.Conn.GetServerImageProductList(reqParams)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
for _, product := range serverImageProductList.Product {
|
||||
// Check exist server image product code
|
||||
if product.ProductCode == serverImageProductCode {
|
||||
isExistServerImage = true
|
||||
productName = product.ProductName
|
||||
break
|
||||
}
|
||||
|
||||
table.Append([]string{product.ProductName, product.ProductCode})
|
||||
}
|
||||
}
|
||||
|
||||
if !isExistServerImage {
|
||||
table.Render()
|
||||
s.Say(buf.String())
|
||||
|
||||
return fmt.Errorf("server_image_product_code %s does not exist", serverImageProductCode)
|
||||
}
|
||||
|
||||
if strings.Contains(productName, "mssql") {
|
||||
s.Config.FeeSystemTypeCode = "FXSUM"
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (s *StepValidateTemplate) validateServerProductCode() error {
|
||||
var serverImageProductCode = s.Config.ServerImageProductCode
|
||||
var productCode = s.Config.ServerProductCode
|
||||
|
||||
reqParams := new(ncloud.RequestGetServerProductList)
|
||||
reqParams.ServerImageProductCode = serverImageProductCode
|
||||
reqParams.RegionNo = s.regionNo
|
||||
|
||||
productList, err := s.Conn.GetServerProductList(reqParams)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
var isExistProductCode = false
|
||||
for _, product := range productList.Product {
|
||||
// Check exist server image product code
|
||||
if product.ProductCode == productCode {
|
||||
isExistProductCode = true
|
||||
if strings.Contains(product.ProductName, "mssql") {
|
||||
s.Config.FeeSystemTypeCode = "FXSUM"
|
||||
}
|
||||
|
||||
if product.ProductType.Code == "VDS" {
|
||||
return errors.New("You cannot create my server image for VDS servers")
|
||||
}
|
||||
|
||||
break
|
||||
} else if productCode == "" && product.ProductType.Code == "STAND" {
|
||||
isExistProductCode = true
|
||||
s.Config.ServerProductCode = product.ProductCode
|
||||
s.Say("server_product_code '" + product.ProductCode + "' is configured automatically")
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
if !isExistProductCode {
|
||||
var buf bytes.Buffer
|
||||
table := tablewriter.NewWriter(&buf)
|
||||
table.SetHeader([]string{"Name", "Code"})
|
||||
for _, product := range productList.Product {
|
||||
table.Append([]string{product.ProductName, product.ProductCode})
|
||||
}
|
||||
table.Render()
|
||||
|
||||
s.Say(buf.String())
|
||||
|
||||
return fmt.Errorf("server_product_code %s does not exist", productCode)
|
||||
}
|
||||
|
||||
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 {
|
||||
return err
|
||||
}
|
||||
|
||||
// Validate member_server_image_no and member_server_image_no
|
||||
if err := s.validateMemberServerImage(); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// Validate server_image_product_code
|
||||
if err := s.validateServerImageProduct(); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// Validate server_product_code
|
||||
return s.validateServerProductCode()
|
||||
}
|
||||
|
||||
// Run : main funciton for validation a template
|
||||
func (s *StepValidateTemplate) Run(state multistep.StateBag) multistep.StepAction {
|
||||
s.Say("Validating deployment template ...")
|
||||
|
||||
err := s.Validate()
|
||||
|
||||
state.Put("ZoneNo", s.zoneNo)
|
||||
|
||||
return processStepResult(err, s.Error, state)
|
||||
}
|
||||
|
||||
// Cleanup : cleanup on error
|
||||
func (s *StepValidateTemplate) Cleanup(multistep.StateBag) {
|
||||
}
|
|
@ -0,0 +1,54 @@
|
|||
package ncloud
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"testing"
|
||||
|
||||
"github.com/mitchellh/multistep"
|
||||
)
|
||||
|
||||
func TestStepValidateTemplateShouldFailIfValidateFails(t *testing.T) {
|
||||
var testSubject = &StepValidateTemplate{
|
||||
Validate: func() error { return fmt.Errorf("!! Unit Test FAIL !!") },
|
||||
Say: func(message string) {},
|
||||
Error: func(e error) {},
|
||||
}
|
||||
|
||||
stateBag := createTestStateBagStepValidateTemplate()
|
||||
|
||||
var result = testSubject.Run(stateBag)
|
||||
|
||||
if result != multistep.ActionHalt {
|
||||
t.Fatalf("Expected the step to return 'ActionHalt', but got '%d'.", result)
|
||||
}
|
||||
|
||||
if _, ok := stateBag.GetOk("Error"); ok == false {
|
||||
t.Fatal("Expected the step to set stateBag['Error'], but it was not.")
|
||||
}
|
||||
}
|
||||
|
||||
func TestStepValidateTemplateShouldPassIfValidatePasses(t *testing.T) {
|
||||
var testSubject = &StepValidateTemplate{
|
||||
Validate: func() error { return nil },
|
||||
Say: func(message string) {},
|
||||
Error: func(e error) {},
|
||||
}
|
||||
|
||||
stateBag := createTestStateBagStepValidateTemplate()
|
||||
|
||||
var result = testSubject.Run(stateBag)
|
||||
|
||||
if result != multistep.ActionContinue {
|
||||
t.Fatalf("Expected the step to return 'ActionContinue', but got '%d'.", result)
|
||||
}
|
||||
|
||||
if _, ok := stateBag.GetOk("Error"); ok == true {
|
||||
t.Fatalf("Expected the step to not set stateBag['Error'], but it was.")
|
||||
}
|
||||
}
|
||||
|
||||
func createTestStateBagStepValidateTemplate() multistep.StateBag {
|
||||
stateBag := new(multistep.BasicStateBag)
|
||||
|
||||
return stateBag
|
||||
}
|
|
@ -0,0 +1,80 @@
|
|||
package ncloud
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"log"
|
||||
"time"
|
||||
|
||||
ncloud "github.com/NaverCloudPlatform/ncloud-sdk-go/sdk"
|
||||
)
|
||||
|
||||
func waiterBlockStorageInstanceStatus(conn *ncloud.Conn, blockStorageInstanceNo string, status string, timeout time.Duration) error {
|
||||
reqParams := new(ncloud.RequestBlockStorageInstanceList)
|
||||
reqParams.BlockStorageInstanceNoList = []string{blockStorageInstanceNo}
|
||||
|
||||
c1 := make(chan error, 1)
|
||||
|
||||
go func() {
|
||||
for {
|
||||
blockStorageInstanceList, err := conn.GetBlockStorageInstance(reqParams)
|
||||
if err != nil {
|
||||
c1 <- err
|
||||
return
|
||||
}
|
||||
|
||||
if status == "DETAC" && len(blockStorageInstanceList.BlockStorageInstance) == 0 {
|
||||
c1 <- nil
|
||||
return
|
||||
}
|
||||
|
||||
code := blockStorageInstanceList.BlockStorageInstance[0].BlockStorageInstanceStatus.Code
|
||||
operationCode := blockStorageInstanceList.BlockStorageInstance[0].BlockStorageInstanceOperation.Code
|
||||
|
||||
if code == status && operationCode == "NULL" {
|
||||
c1 <- nil
|
||||
return
|
||||
}
|
||||
|
||||
log.Println(blockStorageInstanceList.BlockStorageInstance[0])
|
||||
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 waiterDetachedBlockStorageInstance(conn *ncloud.Conn, serverInstanceNo string, timeout time.Duration) error {
|
||||
reqParams := new(ncloud.RequestBlockStorageInstanceList)
|
||||
reqParams.ServerInstanceNo = serverInstanceNo
|
||||
|
||||
c1 := make(chan error, 1)
|
||||
|
||||
go func() {
|
||||
for {
|
||||
blockStorageInstanceList, err := conn.GetBlockStorageInstance(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")
|
||||
}
|
||||
}
|
|
@ -0,0 +1,43 @@
|
|||
package ncloud
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"log"
|
||||
"time"
|
||||
|
||||
ncloud "github.com/NaverCloudPlatform/ncloud-sdk-go/sdk"
|
||||
)
|
||||
|
||||
func waiterMemberServerImageStatus(conn *ncloud.Conn, memberServerImageNo string, status string, timeout time.Duration) error {
|
||||
reqParams := new(ncloud.RequestServerImageList)
|
||||
reqParams.MemberServerImageNoList = []string{memberServerImageNo}
|
||||
|
||||
c1 := make(chan error, 1)
|
||||
|
||||
go func() {
|
||||
for {
|
||||
memberServerImageList, err := conn.GetMemberServerImageList(reqParams)
|
||||
if err != nil {
|
||||
c1 <- err
|
||||
return
|
||||
}
|
||||
|
||||
code := memberServerImageList.MemberServerImageList[0].MemberServerImageStatus.Code
|
||||
if code == status {
|
||||
c1 <- nil
|
||||
return
|
||||
}
|
||||
|
||||
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)
|
||||
}
|
||||
}
|
|
@ -0,0 +1,43 @@
|
|||
package ncloud
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"log"
|
||||
"time"
|
||||
|
||||
ncloud "github.com/NaverCloudPlatform/ncloud-sdk-go/sdk"
|
||||
)
|
||||
|
||||
func waiterServerInstanceStatus(conn *ncloud.Conn, serverInstanceNo string, status string, timeout time.Duration) error {
|
||||
reqParams := new(ncloud.RequestGetServerInstanceList)
|
||||
reqParams.ServerInstanceNoList = []string{serverInstanceNo}
|
||||
|
||||
c1 := make(chan error, 1)
|
||||
|
||||
go func() {
|
||||
for {
|
||||
serverInstanceList, err := conn.GetServerInstanceList(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)
|
||||
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)
|
||||
}
|
||||
}
|
|
@ -29,6 +29,7 @@ import (
|
|||
hypervvmcxbuilder "github.com/hashicorp/packer/builder/hyperv/vmcx"
|
||||
lxcbuilder "github.com/hashicorp/packer/builder/lxc"
|
||||
lxdbuilder "github.com/hashicorp/packer/builder/lxd"
|
||||
ncloudbuilder "github.com/hashicorp/packer/builder/ncloud"
|
||||
nullbuilder "github.com/hashicorp/packer/builder/null"
|
||||
oneandonebuilder "github.com/hashicorp/packer/builder/oneandone"
|
||||
openstackbuilder "github.com/hashicorp/packer/builder/openstack"
|
||||
|
@ -96,6 +97,7 @@ var Builders = map[string]packer.Builder{
|
|||
"hyperv-vmcx": new(hypervvmcxbuilder.Builder),
|
||||
"lxc": new(lxcbuilder.Builder),
|
||||
"lxd": new(lxdbuilder.Builder),
|
||||
"ncloud": new(ncloudbuilder.Builder),
|
||||
"null": new(nullbuilder.Builder),
|
||||
"oneandone": new(oneandonebuilder.Builder),
|
||||
"openstack": new(openstackbuilder.Builder),
|
||||
|
|
Loading…
Reference in New Issue