Merge pull request #8261 from shawnmssu/feature/ucloud_import

Packer Post-Processor support UCloud import
This commit is contained in:
Megan Marsh
2019-10-30 13:11:55 -07:00
committed by GitHub
114 changed files with 5261 additions and 503 deletions
@@ -1,12 +1,14 @@
package uhost
package common
import (
"fmt"
"net/url"
"os"
"github.com/hashicorp/packer/template/interpolate"
"github.com/hashicorp/packer/version"
"github.com/ucloud/ucloud-sdk-go/services/uaccount"
"github.com/ucloud/ucloud-sdk-go/services/ufile"
"github.com/ucloud/ucloud-sdk-go/services/uhost"
"github.com/ucloud/ucloud-sdk-go/services/unet"
"github.com/ucloud/ucloud-sdk-go/services/vpc"
@@ -36,16 +38,19 @@ func (c *AccessConfig) Client() (*UCloudClient, error) {
cfg.BaseUrl = c.BaseUrl
}
cfg.UserAgent = fmt.Sprintf("Packer-UCloud/%s", version.FormattedVersion())
// set default max retry count
cfg.MaxRetries = 3
cred := auth.NewCredential()
cred.PublicKey = c.PublicKey
cred.PrivateKey = c.PrivateKey
c.client = &UCloudClient{}
c.client.uhostconn = uhost.NewClient(&cfg, &cred)
c.client.unetconn = unet.NewClient(&cfg, &cred)
c.client.vpcconn = vpc.NewClient(&cfg, &cred)
c.client.uaccountconn = uaccount.NewClient(&cfg, &cred)
c.client.UHostConn = uhost.NewClient(&cfg, &cred)
c.client.UNetConn = unet.NewClient(&cfg, &cred)
c.client.VPCConn = vpc.NewClient(&cfg, &cred)
c.client.UAccountConn = uaccount.NewClient(&cfg, &cred)
c.client.UFileConn = ufile.NewClient(&cfg, &cred)
return c.client, nil
}
@@ -64,6 +69,12 @@ func (c *AccessConfig) Prepare(ctx *interpolate.Context) []error {
errs = append(errs, fmt.Errorf("%q must be set", "region"))
}
if c.BaseUrl != "" {
if _, err := url.Parse(c.BaseUrl); err != nil {
errs = append(errs, fmt.Errorf("%q is invalid, should be an valid ucloud base_url, got %q, parse error: %s", "base_url", c.BaseUrl, err))
}
}
if len(errs) > 0 {
return errs
}
@@ -137,7 +148,7 @@ func (c *AccessConfig) ValidateZone(region, zone string) error {
func (c *AccessConfig) getSupportedProjectIds() ([]string, error) {
client, err := c.Client()
conn := client.uaccountconn
conn := client.UAccountConn
if err != nil {
return nil, err
}
@@ -150,7 +161,7 @@ func (c *AccessConfig) getSupportedProjectIds() ([]string, error) {
validProjectIds := make([]string, len(resp.ProjectSet))
for _, val := range resp.ProjectSet {
if !isStringIn(val.ProjectId, validProjectIds) {
if !IsStringIn(val.ProjectId, validProjectIds) {
validProjectIds = append(validProjectIds, val.ProjectId)
}
}
@@ -160,7 +171,7 @@ func (c *AccessConfig) getSupportedProjectIds() ([]string, error) {
func (c *AccessConfig) getSupportedRegions() ([]string, error) {
client, err := c.Client()
conn := client.uaccountconn
conn := client.UAccountConn
if err != nil {
return nil, err
}
@@ -173,7 +184,7 @@ func (c *AccessConfig) getSupportedRegions() ([]string, error) {
validRegions := make([]string, len(resp.Regions))
for _, val := range resp.Regions {
if !isStringIn(val.Region, validRegions) {
if !IsStringIn(val.Region, validRegions) {
validRegions = append(validRegions, val.Region)
}
}
@@ -183,7 +194,7 @@ func (c *AccessConfig) getSupportedRegions() ([]string, error) {
func (c *AccessConfig) getSupportedZones(region string) ([]string, error) {
client, err := c.Client()
conn := client.uaccountconn
conn := client.UAccountConn
if err != nil {
return nil, err
}
@@ -196,7 +207,7 @@ func (c *AccessConfig) getSupportedZones(region string) ([]string, error) {
validZones := make([]string, len(resp.Regions))
for _, val := range resp.Regions {
if val.Region == region && !isStringIn(val.Zone, validZones) {
if val.Region == region && !IsStringIn(val.Zone, validZones) {
validZones = append(validZones, val.Zone)
}
@@ -1,4 +1,4 @@
package uhost
package common
import (
"os"
@@ -1,4 +1,4 @@
package uhost
package common
import (
"fmt"
@@ -10,7 +10,7 @@ import (
)
type Artifact struct {
UCloudImages *imageInfoSet
UCloudImages *ImageInfoSet
BuilderIdValue string
@@ -56,7 +56,7 @@ func (a *Artifact) State(name string) interface{} {
}
func (a *Artifact) Destroy() error {
conn := a.Client.uhostconn
conn := a.Client.UHostConn
errors := make([]error, 0)
for _, v := range a.UCloudImages.GetAll() {
@@ -1,4 +1,4 @@
package uhost
package common
import (
"github.com/hashicorp/packer/packer"
@@ -13,14 +13,14 @@ func TestArtifact_Impl(t *testing.T) {
func TestArtifactId(t *testing.T) {
expected := `project1:region1:foo,project2:region2:bar`
images := newImageInfoSet(nil)
images.Set(imageInfo{
images := NewImageInfoSet(nil)
images.Set(ImageInfo{
Region: "region1",
ProjectId: "project1",
ImageId: "foo",
})
images.Set(imageInfo{
images.Set(ImageInfo{
Region: "region2",
ProjectId: "project2",
ImageId: "bar",
@@ -37,14 +37,14 @@ func TestArtifactId(t *testing.T) {
}
func TestArtifactState_atlasMetadata(t *testing.T) {
images := newImageInfoSet(nil)
images.Set(imageInfo{
images := NewImageInfoSet(nil)
images.Set(ImageInfo{
Region: "region1",
ProjectId: "project1",
ImageId: "foo",
})
images.Set(imageInfo{
images.Set(ImageInfo{
Region: "region2",
ProjectId: "project2",
ImageId: "bar",
@@ -1,7 +1,8 @@
package uhost
package common
import (
"github.com/ucloud/ucloud-sdk-go/services/uaccount"
"github.com/ucloud/ucloud-sdk-go/services/ufile"
"github.com/ucloud/ucloud-sdk-go/services/uhost"
"github.com/ucloud/ucloud-sdk-go/services/unet"
"github.com/ucloud/ucloud-sdk-go/services/vpc"
@@ -10,17 +11,18 @@ import (
)
type UCloudClient struct {
uhostconn *uhost.UHostClient
unetconn *unet.UNetClient
vpcconn *vpc.VPCClient
uaccountconn *uaccount.UAccountClient
UHostConn *uhost.UHostClient
UNetConn *unet.UNetClient
VPCConn *vpc.VPCClient
UAccountConn *uaccount.UAccountClient
UFileConn *ufile.UFileClient
}
func (c *UCloudClient) describeFirewallById(sgId string) (*unet.FirewallDataSet, error) {
func (c *UCloudClient) DescribeFirewallById(sgId string) (*unet.FirewallDataSet, error) {
if sgId == "" {
return nil, newNotFoundError("security group", sgId)
return nil, NewNotFoundError("security group", sgId)
}
conn := c.unetconn
conn := c.UNetConn
req := conn.NewDescribeFirewallRequest()
req.FWId = ucloud.String(sgId)
@@ -29,23 +31,23 @@ func (c *UCloudClient) describeFirewallById(sgId string) (*unet.FirewallDataSet,
if err != nil {
if uErr, ok := err.(uerr.Error); ok && uErr.Code() == 54002 {
return nil, newNotFoundError("security group", sgId)
return nil, NewNotFoundError("security group", sgId)
}
return nil, err
}
if len(resp.DataSet) < 1 {
return nil, newNotFoundError("security group", sgId)
return nil, NewNotFoundError("security group", sgId)
}
return &resp.DataSet[0], nil
}
func (c *UCloudClient) describeSubnetById(subnetId string) (*vpc.VPCSubnetInfoSet, error) {
func (c *UCloudClient) DescribeSubnetById(subnetId string) (*vpc.VPCSubnetInfoSet, error) {
if subnetId == "" {
return nil, newNotFoundError("Subnet", subnetId)
return nil, NewNotFoundError("Subnet", subnetId)
}
conn := c.vpcconn
conn := c.VPCConn
req := conn.NewDescribeSubnetRequest()
req.SubnetIds = []string{subnetId}
@@ -56,17 +58,17 @@ func (c *UCloudClient) describeSubnetById(subnetId string) (*vpc.VPCSubnetInfoSe
}
if resp == nil || len(resp.DataSet) < 1 {
return nil, newNotFoundError("Subnet", subnetId)
return nil, NewNotFoundError("Subnet", subnetId)
}
return &resp.DataSet[0], nil
}
func (c *UCloudClient) describeVPCById(vpcId string) (*vpc.VPCInfo, error) {
func (c *UCloudClient) DescribeVPCById(vpcId string) (*vpc.VPCInfo, error) {
if vpcId == "" {
return nil, newNotFoundError("VPC", vpcId)
return nil, NewNotFoundError("VPC", vpcId)
}
conn := c.vpcconn
conn := c.VPCConn
req := conn.NewDescribeVPCRequest()
req.VPCIds = []string{vpcId}
@@ -77,7 +79,7 @@ func (c *UCloudClient) describeVPCById(vpcId string) (*vpc.VPCInfo, error) {
}
if resp == nil || len(resp.DataSet) < 1 {
return nil, newNotFoundError("VPC", vpcId)
return nil, NewNotFoundError("VPC", vpcId)
}
return &resp.DataSet[0], nil
@@ -85,31 +87,31 @@ func (c *UCloudClient) describeVPCById(vpcId string) (*vpc.VPCInfo, error) {
func (c *UCloudClient) DescribeImageById(imageId string) (*uhost.UHostImageSet, error) {
if imageId == "" {
return nil, newNotFoundError("image", imageId)
return nil, NewNotFoundError("image", imageId)
}
req := c.uhostconn.NewDescribeImageRequest()
req := c.UHostConn.NewDescribeImageRequest()
req.ImageId = ucloud.String(imageId)
resp, err := c.uhostconn.DescribeImage(req)
resp, err := c.UHostConn.DescribeImage(req)
if err != nil {
return nil, err
}
if len(resp.ImageSet) < 1 {
return nil, newNotFoundError("image", imageId)
return nil, NewNotFoundError("image", imageId)
}
return &resp.ImageSet[0], nil
}
func (c *UCloudClient) describeUHostById(uhostId string) (*uhost.UHostInstanceSet, error) {
func (c *UCloudClient) DescribeUHostById(uhostId string) (*uhost.UHostInstanceSet, error) {
if uhostId == "" {
return nil, newNotFoundError("instance", uhostId)
return nil, NewNotFoundError("instance", uhostId)
}
req := c.uhostconn.NewDescribeUHostInstanceRequest()
req := c.UHostConn.NewDescribeUHostInstanceRequest()
req.UHostIds = []string{uhostId}
resp, err := c.uhostconn.DescribeUHostInstance(req)
resp, err := c.UHostConn.DescribeUHostInstance(req)
if err != nil {
return nil, err
}
@@ -120,19 +122,19 @@ func (c *UCloudClient) describeUHostById(uhostId string) (*uhost.UHostInstanceSe
return &resp.UHostSet[0], nil
}
func (c *UCloudClient) describeImageByInfo(projectId, regionId, imageId string) (*uhost.UHostImageSet, error) {
req := c.uhostconn.NewDescribeImageRequest()
func (c *UCloudClient) DescribeImageByInfo(projectId, regionId, imageId string) (*uhost.UHostImageSet, error) {
req := c.UHostConn.NewDescribeImageRequest()
req.ProjectId = ucloud.String(projectId)
req.ImageId = ucloud.String(imageId)
req.Region = ucloud.String(regionId)
resp, err := c.uhostconn.DescribeImage(req)
resp, err := c.UHostConn.DescribeImage(req)
if err != nil {
return nil, err
}
if len(resp.ImageSet) < 1 {
return nil, newNotFoundError("image", imageId)
return nil, NewNotFoundError("image", imageId)
}
return &resp.ImageSet[0], nil
+31
View File
@@ -0,0 +1,31 @@
package common
const (
// DefaultPasswordStr, DefaultPasswordNum and DefaultPasswordSpe are used to general default value of root password of UHost instance
DefaultPasswordNum = "012346789"
DefaultPasswordStr = "abcdefghijklmnopqrstuvwxyz"
DefaultPasswordSpe = "-_"
)
const (
InstanceStateRunning = "Running"
InstanceStateStopped = "Stopped"
ImageStateAvailable = "Available"
ImageStateUnavailable = "Unavailable"
BootDiskStateNormal = "Normal"
OsTypeWindows = "Windows"
SecurityGroupNonWeb = "recommend non web"
IpTypePrivate = "Private"
)
const (
DefaultCreateImageTimeout = 3600
)
var BootDiskTypeMap = NewStringConverter(map[string]string{
"cloud_ssd": "CLOUD_SSD",
"local_normal": "LOCAL_NORMAL",
"local_ssd": "LOCAL_SSD",
})
@@ -1,4 +1,4 @@
package uhost
package common
import (
"fmt"
@@ -12,7 +12,7 @@ type ExpectedStateError struct {
message string
}
type NotCompleteError struct {
type NotCompletedError struct {
message string
}
@@ -24,38 +24,38 @@ func (e *NotFoundError) Error() string {
return e.message
}
func (e *NotCompleteError) Error() string {
func (e *NotCompletedError) Error() string {
return e.message
}
func newNotFoundError(product, id string) error {
func NewNotFoundError(product, id string) error {
return &NotFoundError{fmt.Sprintf("the %s %s is not found", product, id)}
}
func newExpectedStateError(product, id string) error {
func NewExpectedStateError(product, id string) error {
return &ExpectedStateError{fmt.Sprintf("the %s %s not be expected state", product, id)}
}
func newNotCompleteError(product string) error {
return &NotCompleteError{fmt.Sprintf("%s is not completed", product)}
func NewNotCompletedError(product string) error {
return &NotCompletedError{fmt.Sprintf("%s is not completed", product)}
}
func isNotFoundError(err error) bool {
func IsNotFoundError(err error) bool {
if _, ok := err.(*NotFoundError); ok {
return true
}
return false
}
func isExpectedStateError(err error) bool {
func IsExpectedStateError(err error) bool {
if _, ok := err.(*ExpectedStateError); ok {
return true
}
return false
}
func isNotCompleteError(err error) bool {
if _, ok := err.(*NotCompleteError); ok {
func IsNotCompleteError(err error) bool {
if _, ok := err.(*NotCompletedError); ok {
return true
}
return false
@@ -1,6 +1,6 @@
//go:generate mapstructure-to-hcl2 -type ImageDestination
package uhost
package common
import (
"fmt"
@@ -17,19 +17,20 @@ type ImageDestination struct {
}
type ImageConfig struct {
ImageName string `mapstructure:"image_name"`
ImageDescription string `mapstructure:"image_description"`
ImageDestinations []ImageDestination `mapstructure:"image_copy_to_mappings"`
ImageName string `mapstructure:"image_name"`
ImageDescription string `mapstructure:"image_description"`
ImageDestinations []ImageDestination `mapstructure:"image_copy_to_mappings"`
WaitImageReadyTimeout int `mapstructure:"wait_image_ready_timeout"`
}
var imageNamePattern = regexp.MustCompile(`^[A-Za-z0-9\p{Han}-_\[\]:,.]{1,63}$`)
var ImageNamePattern = regexp.MustCompile(`^[A-Za-z0-9\p{Han}-_\[\]:,.]{1,63}$`)
func (c *ImageConfig) Prepare(ctx *interpolate.Context) []error {
var errs []error
imageName := c.ImageName
if imageName == "" {
errs = append(errs, fmt.Errorf("%q must be set", "image_name"))
} else if !imageNamePattern.MatchString(imageName) {
} else if !ImageNamePattern.MatchString(imageName) {
errs = append(errs, fmt.Errorf("expected %q to be 1-63 characters and only support chinese, english, numbers, '-_,.:[]', got %q", "image_name", imageName))
}
@@ -43,6 +44,10 @@ func (c *ImageConfig) Prepare(ctx *interpolate.Context) []error {
}
}
if c.WaitImageReadyTimeout <= 0 {
c.WaitImageReadyTimeout = DefaultCreateImageTimeout
}
if len(errs) > 0 {
return errs
}
@@ -61,7 +66,7 @@ func (imageDestination *ImageDestination) validate() []error {
errs = append(errs, fmt.Errorf("%q must be set", "image_copy_project"))
}
if imageDestination.Name != "" && !imageNamePattern.MatchString(imageDestination.Name) {
if imageDestination.Name != "" && !ImageNamePattern.MatchString(imageDestination.Name) {
errs = append(errs, fmt.Errorf("expected %q to be 1-63 characters and only support chinese, english, numbers, '-_,.:[]', got %q", "image_copy_name", imageDestination.Name))
}
@@ -1,5 +1,5 @@
// Code generated by "mapstructure-to-hcl2 -type ImageDestination"; DO NOT EDIT.
package uhost
package common
import (
"github.com/hashicorp/hcl/v2/hcldec"
@@ -1,4 +1,4 @@
package uhost
package common
import (
"testing"
@@ -1,4 +1,4 @@
package uhost
package common
import (
"fmt"
@@ -39,7 +39,7 @@ func (c *RunConfig) Prepare(ctx *interpolate.Context) []error {
if c.InstanceType == "" {
errs = append(errs, fmt.Errorf("%q must be set", "instance_type"))
} else if _, err := parseInstanceType(c.InstanceType); err != nil {
} else if _, err := ParseInstanceType(c.InstanceType); err != nil {
errs = append(errs, err)
}
@@ -49,7 +49,7 @@ func (c *RunConfig) Prepare(ctx *interpolate.Context) []error {
if c.BootDiskType == "" {
c.BootDiskType = "cloud_ssd"
} else if err := checkStringIn(c.BootDiskType,
} else if err := CheckStringIn(c.BootDiskType,
[]string{"local_normal", "local_ssd", "cloud_ssd"}); err != nil {
errs = append(errs, err)
}
@@ -1,4 +1,4 @@
package uhost
package common
import (
"testing"
+31
View File
@@ -0,0 +1,31 @@
package common
type stringConverter struct {
c map[string]string
r map[string]string
}
func NewStringConverter(input map[string]string) stringConverter {
reversed := make(map[string]string)
for k, v := range input {
reversed[v] = k
}
return stringConverter{
c: input,
r: reversed,
}
}
func (c stringConverter) Convert(src string) string {
if dst, ok := c.c[src]; ok {
return dst
}
return src
}
func (c stringConverter) UnConvert(dst string) string {
if src, ok := c.r[dst]; ok {
return src
}
return dst
}
@@ -1,4 +1,4 @@
package uhost
package common
import (
"fmt"
@@ -7,14 +7,14 @@ import (
"sync"
)
type instanceType struct {
type InstanceType struct {
CPU int
Memory int
HostType string
HostScaleType string
}
func parseInstanceType(s string) (*instanceType, error) {
func ParseInstanceType(s string) (*InstanceType, error) {
split := strings.Split(s, "-")
if len(split) < 3 {
return nil, fmt.Errorf("instance type is invalid, got %q", s)
@@ -26,7 +26,7 @@ func parseInstanceType(s string) (*instanceType, error) {
return parseInstanceTypeByNormal(split...)
}
func (i *instanceType) String() string {
func (i *InstanceType) String() string {
if i.Iscustomized() {
return fmt.Sprintf("%s-%s-%v-%v", i.HostType, i.HostScaleType, i.CPU, i.Memory)
} else {
@@ -34,7 +34,7 @@ func (i *instanceType) String() string {
}
}
func (i *instanceType) Iscustomized() bool {
func (i *InstanceType) Iscustomized() bool {
return i.HostScaleType == "customized"
}
@@ -47,13 +47,13 @@ var instanceTypeScaleMap = map[string]int{
var availableHostTypes = []string{"n"}
func parseInstanceTypeByCustomize(splited ...string) (*instanceType, error) {
func parseInstanceTypeByCustomize(splited ...string) (*InstanceType, error) {
if len(splited) != 4 {
return nil, fmt.Errorf("instance type is invalid, expected like n-customize-1-2")
}
hostType := splited[0]
err := checkStringIn(hostType, availableHostTypes)
err := CheckStringIn(hostType, availableHostTypes)
if err != nil {
return nil, err
}
@@ -95,7 +95,7 @@ func parseInstanceTypeByCustomize(splited ...string) (*instanceType, error) {
return nil, fmt.Errorf("expected the number of memory must be divisible by 2 without a remainder (except single memory), got %d", memory)
}
t := &instanceType{}
t := &InstanceType{}
t.HostType = hostType
t.HostScaleType = hostScaleType
t.CPU = cpu
@@ -105,13 +105,13 @@ func parseInstanceTypeByCustomize(splited ...string) (*instanceType, error) {
var availableOutstandingCpu = []int{4, 8, 16, 32, 64}
func parseInstanceTypeByNormal(split ...string) (*instanceType, error) {
func parseInstanceTypeByNormal(split ...string) (*InstanceType, error) {
if len(split) != 3 {
return nil, fmt.Errorf("instance type is invalid, expected like n-standard-1")
}
hostType := split[0]
err := checkStringIn(hostType, []string{"n", "o"})
err := CheckStringIn(hostType, []string{"n", "o"})
if err != nil {
return nil, err
}
@@ -131,7 +131,7 @@ func parseInstanceTypeByNormal(split ...string) (*instanceType, error) {
}
if hostType == "o" {
if err := checkIntIn(cpu, availableOutstandingCpu); err != nil {
if err := CheckIntIn(cpu, availableOutstandingCpu); err != nil {
return nil, fmt.Errorf("expected cpu of outstanding instancetype %q", err)
}
@@ -150,7 +150,7 @@ func parseInstanceTypeByNormal(split ...string) (*instanceType, error) {
memory := cpu * scale
t := &instanceType{}
t := &InstanceType{}
t.HostType = hostType
t.HostScaleType = hostScaleType
t.CPU = cpu
@@ -159,46 +159,46 @@ func parseInstanceTypeByNormal(split ...string) (*instanceType, error) {
}
}
type imageInfo struct {
type ImageInfo struct {
ImageId string
ProjectId string
Region string
}
func (i *imageInfo) Id() string {
func (i *ImageInfo) Id() string {
return fmt.Sprintf("%s:%s", i.ProjectId, i.Region)
}
type imageInfoSet struct {
m map[string]imageInfo
type ImageInfoSet struct {
m map[string]ImageInfo
once sync.Once
}
func newImageInfoSet(vL []imageInfo) *imageInfoSet {
s := imageInfoSet{}
func NewImageInfoSet(vL []ImageInfo) *ImageInfoSet {
s := ImageInfoSet{}
for _, v := range vL {
s.Set(v)
}
return &s
}
func (i *imageInfoSet) init() {
i.m = make(map[string]imageInfo)
func (i *ImageInfoSet) init() {
i.m = make(map[string]ImageInfo)
}
func (i *imageInfoSet) Set(img imageInfo) {
func (i *ImageInfoSet) Set(img ImageInfo) {
i.once.Do(i.init)
i.m[img.Id()] = img
}
func (i *imageInfoSet) Remove(id string) {
func (i *ImageInfoSet) Remove(id string) {
i.once.Do(i.init)
delete(i.m, id)
}
func (i *imageInfoSet) Get(projectId, region string) *imageInfo {
func (i *ImageInfoSet) Get(projectId, region string) *ImageInfo {
k := fmt.Sprintf("%s:%s", projectId, region)
if v, ok := i.m[k]; ok {
return &v
@@ -206,8 +206,8 @@ func (i *imageInfoSet) Get(projectId, region string) *imageInfo {
return nil
}
func (i *imageInfoSet) GetAll() []imageInfo {
var vL []imageInfo
func (i *ImageInfoSet) GetAll() []ImageInfo {
var vL []ImageInfo
for _, img := range i.m {
vL = append(vL, img)
}
@@ -1,4 +1,4 @@
package uhost
package common
import (
"testing"
@@ -12,14 +12,14 @@ func Test_parseInstanceType(t *testing.T) {
tests := []struct {
name string
args args
want *instanceType
want *InstanceType
wantErr bool
}{
{"ok_highcpu", args{"n-highcpu-1"}, &instanceType{1, 1024, "n", "highcpu"}, false},
{"ok_basic", args{"n-basic-1"}, &instanceType{1, 2048, "n", "basic"}, false},
{"ok_standard", args{"n-standard-1"}, &instanceType{1, 4096, "n", "standard"}, false},
{"ok_highmem", args{"n-highmem-1"}, &instanceType{1, 8192, "n", "highmem"}, false},
{"ok_customized", args{"n-customized-1-12"}, &instanceType{1, 12288, "n", "customized"}, false},
{"ok_highcpu", args{"n-highcpu-1"}, &InstanceType{1, 1024, "n", "highcpu"}, false},
{"ok_basic", args{"n-basic-1"}, &InstanceType{1, 2048, "n", "basic"}, false},
{"ok_standard", args{"n-standard-1"}, &InstanceType{1, 4096, "n", "standard"}, false},
{"ok_highmem", args{"n-highmem-1"}, &InstanceType{1, 8192, "n", "highmem"}, false},
{"ok_customized", args{"n-customized-1-12"}, &InstanceType{1, 12288, "n", "customized"}, false},
{"err_customized", args{"n-customized-1-5"}, nil, true},
{"err_type", args{"nx-highcpu-1"}, nil, true},
@@ -33,9 +33,9 @@ func Test_parseInstanceType(t *testing.T) {
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
got, err := parseInstanceType(tt.args.s)
got, err := ParseInstanceType(tt.args.s)
if (err != nil) != tt.wantErr {
t.Errorf("parseInstanceType() arg %s got %#v error = %v, wantErr %v", tt.args.s, got, err, tt.wantErr)
t.Errorf("ParseInstanceType() arg %s got %#v error = %v, wantErr %v", tt.args.s, got, err, tt.wantErr)
return
}
@@ -47,7 +47,7 @@ func Test_parseInstanceType(t *testing.T) {
!(tt.want.Memory == got.Memory) ||
!(tt.want.HostType == got.HostType) ||
!(tt.want.HostScaleType == got.HostScaleType) {
t.Errorf("parseInstanceType() = %v, want %v", got, tt.want)
t.Errorf("ParseInstanceType() = %v, want %v", got, tt.want)
}
})
}
@@ -1,4 +1,4 @@
package uhost
package common
import (
"fmt"
@@ -8,7 +8,7 @@ import (
"strings"
)
func checkStringIn(val string, available []string) error {
func CheckStringIn(val string, available []string) error {
for _, choice := range available {
if val == choice {
return nil
@@ -18,7 +18,7 @@ func checkStringIn(val string, available []string) error {
return fmt.Errorf("should be one of %q, got %q", strings.Join(available, ","), val)
}
func checkIntIn(val int, available []int) error {
func CheckIntIn(val int, available []int) error {
for _, choice := range available {
if val == choice {
return nil
@@ -28,7 +28,7 @@ func checkIntIn(val int, available []int) error {
return fmt.Errorf("should be one of %v, got %d", available, val)
}
func isStringIn(val string, available []string) bool {
func IsStringIn(val string, available []string) bool {
for _, choice := range available {
if val == choice {
return true
@@ -46,7 +46,7 @@ func SSHHost(usePrivateIp bool) func(multistep.StateBag) (string, error) {
var privateIp, publicIp string
for _, v := range instance.IPSet {
if v.Type == ipTypePrivate {
if v.Type == IpTypePrivate {
privateIp = v.IP
} else {
publicIp = v.IP
@@ -61,7 +61,7 @@ func SSHHost(usePrivateIp bool) func(multistep.StateBag) (string, error) {
}
}
func halt(state multistep.StateBag, err error, prefix string) multistep.StepAction {
func Halt(state multistep.StateBag, err error, prefix string) multistep.StepAction {
ui := state.Get("ui").(packer.Ui)
if prefix != "" {
+12 -10
View File
@@ -7,6 +7,7 @@ package uhost
import (
"context"
ucloudcommon "github.com/hashicorp/packer/builder/ucloud/common"
"github.com/hashicorp/packer/common"
"github.com/hashicorp/packer/helper/communicator"
"github.com/hashicorp/packer/helper/config"
@@ -19,10 +20,10 @@ import (
const BuilderId = "ucloud.uhost"
type Config struct {
common.PackerConfig `mapstructure:",squash"`
AccessConfig `mapstructure:",squash"`
ImageConfig `mapstructure:",squash"`
RunConfig `mapstructure:",squash"`
common.PackerConfig `mapstructure:",squash"`
ucloudcommon.AccessConfig `mapstructure:",squash"`
ucloudcommon.ImageConfig `mapstructure:",squash"`
ucloudcommon.RunConfig `mapstructure:",squash"`
ctx interpolate.Context
}
@@ -111,7 +112,7 @@ func (b *Builder) Run(ctx context.Context, ui packer.Ui, hook packer.Hook) (pack
},
&communicator.StepConnect{
Config: &b.config.RunConfig.Comm,
Host: SSHHost(
Host: ucloudcommon.SSHHost(
b.config.UseSSHPrivateIp),
SSHConfig: b.config.RunConfig.Comm.SSHConfigFunc(),
},
@@ -119,9 +120,10 @@ func (b *Builder) Run(ctx context.Context, ui packer.Ui, hook packer.Hook) (pack
&stepStopInstance{},
&stepCreateImage{},
&stepCopyUCloudImage{
ImageDestinations: b.config.ImageDestinations,
RegionId: b.config.Region,
ProjectId: b.config.ProjectId,
ImageDestinations: b.config.ImageDestinations,
RegionId: b.config.Region,
ProjectId: b.config.ProjectId,
WaitImageReadyTimeout: b.config.WaitImageReadyTimeout,
},
}
@@ -140,8 +142,8 @@ func (b *Builder) Run(ctx context.Context, ui packer.Ui, hook packer.Hook) (pack
}
// Build the artifact and return it
artifact := &Artifact{
UCloudImages: state.Get("ucloud_images").(*imageInfoSet),
artifact := &ucloudcommon.Artifact{
UCloudImages: state.Get("ucloud_images").(*ucloudcommon.ImageInfoSet),
BuilderIdValue: BuilderId,
Client: client,
}
+68 -65
View File
@@ -3,76 +3,78 @@ package uhost
import (
"github.com/hashicorp/hcl/v2/hcldec"
"github.com/hashicorp/packer/builder/ucloud/common"
"github.com/zclconf/go-cty/cty"
)
// FlatConfig is an auto-generated flat version of Config.
// Where the contents of a field with a `mapstructure:,squash` tag are bubbled up.
type FlatConfig struct {
PackerBuildName *string `mapstructure:"packer_build_name" cty:"packer_build_name"`
PackerBuilderType *string `mapstructure:"packer_builder_type" cty:"packer_builder_type"`
PackerDebug *bool `mapstructure:"packer_debug" cty:"packer_debug"`
PackerForce *bool `mapstructure:"packer_force" cty:"packer_force"`
PackerOnError *string `mapstructure:"packer_on_error" cty:"packer_on_error"`
PackerUserVars map[string]string `mapstructure:"packer_user_variables" cty:"packer_user_variables"`
PackerSensitiveVars []string `mapstructure:"packer_sensitive_variables" cty:"packer_sensitive_variables"`
PublicKey *string `mapstructure:"public_key" cty:"public_key"`
PrivateKey *string `mapstructure:"private_key" cty:"private_key"`
Region *string `mapstructure:"region" cty:"region"`
ProjectId *string `mapstructure:"project_id" cty:"project_id"`
BaseUrl *string `mapstructure:"base_url" cty:"base_url"`
ImageName *string `mapstructure:"image_name" cty:"image_name"`
ImageDescription *string `mapstructure:"image_description" cty:"image_description"`
ImageDestinations []FlatImageDestination `mapstructure:"image_copy_to_mappings" cty:"image_copy_to_mappings"`
Zone *string `mapstructure:"availability_zone" cty:"availability_zone"`
SourceImageId *string `mapstructure:"source_image_id" cty:"source_image_id"`
InstanceType *string `mapstructure:"instance_type" cty:"instance_type"`
InstanceName *string `mapstructure:"instance_name" cty:"instance_name"`
BootDiskType *string `mapstructure:"boot_disk_type" cty:"boot_disk_type"`
VPCId *string `mapstructure:"vpc_id" cty:"vpc_id"`
SubnetId *string `mapstructure:"subnet_id" cty:"subnet_id"`
SecurityGroupId *string `mapstructure:"security_group_id" cty:"security_group_id"`
Type *string `mapstructure:"communicator" cty:"communicator"`
PauseBeforeConnect *string `mapstructure:"pause_before_connecting" cty:"pause_before_connecting"`
SSHHost *string `mapstructure:"ssh_host" cty:"ssh_host"`
SSHPort *int `mapstructure:"ssh_port" cty:"ssh_port"`
SSHUsername *string `mapstructure:"ssh_username" cty:"ssh_username"`
SSHPassword *string `mapstructure:"ssh_password" cty:"ssh_password"`
SSHKeyPairName *string `mapstructure:"ssh_keypair_name" cty:"ssh_keypair_name"`
SSHTemporaryKeyPairName *string `mapstructure:"temporary_key_pair_name" cty:"temporary_key_pair_name"`
SSHClearAuthorizedKeys *bool `mapstructure:"ssh_clear_authorized_keys" cty:"ssh_clear_authorized_keys"`
SSHPrivateKeyFile *string `mapstructure:"ssh_private_key_file" cty:"ssh_private_key_file"`
SSHPty *bool `mapstructure:"ssh_pty" cty:"ssh_pty"`
SSHTimeout *string `mapstructure:"ssh_timeout" cty:"ssh_timeout"`
SSHAgentAuth *bool `mapstructure:"ssh_agent_auth" cty:"ssh_agent_auth"`
SSHDisableAgentForwarding *bool `mapstructure:"ssh_disable_agent_forwarding" cty:"ssh_disable_agent_forwarding"`
SSHHandshakeAttempts *int `mapstructure:"ssh_handshake_attempts" cty:"ssh_handshake_attempts"`
SSHBastionHost *string `mapstructure:"ssh_bastion_host" cty:"ssh_bastion_host"`
SSHBastionPort *int `mapstructure:"ssh_bastion_port" cty:"ssh_bastion_port"`
SSHBastionAgentAuth *bool `mapstructure:"ssh_bastion_agent_auth" cty:"ssh_bastion_agent_auth"`
SSHBastionUsername *string `mapstructure:"ssh_bastion_username" cty:"ssh_bastion_username"`
SSHBastionPassword *string `mapstructure:"ssh_bastion_password" cty:"ssh_bastion_password"`
SSHBastionPrivateKeyFile *string `mapstructure:"ssh_bastion_private_key_file" cty:"ssh_bastion_private_key_file"`
SSHFileTransferMethod *string `mapstructure:"ssh_file_transfer_method" cty:"ssh_file_transfer_method"`
SSHProxyHost *string `mapstructure:"ssh_proxy_host" cty:"ssh_proxy_host"`
SSHProxyPort *int `mapstructure:"ssh_proxy_port" cty:"ssh_proxy_port"`
SSHProxyUsername *string `mapstructure:"ssh_proxy_username" cty:"ssh_proxy_username"`
SSHProxyPassword *string `mapstructure:"ssh_proxy_password" cty:"ssh_proxy_password"`
SSHKeepAliveInterval *string `mapstructure:"ssh_keep_alive_interval" cty:"ssh_keep_alive_interval"`
SSHReadWriteTimeout *string `mapstructure:"ssh_read_write_timeout" cty:"ssh_read_write_timeout"`
SSHRemoteTunnels []string `mapstructure:"ssh_remote_tunnels" cty:"ssh_remote_tunnels"`
SSHLocalTunnels []string `mapstructure:"ssh_local_tunnels" cty:"ssh_local_tunnels"`
SSHPublicKey []byte `cty:"ssh_public_key"`
SSHPrivateKey []byte `cty:"ssh_private_key"`
WinRMUser *string `mapstructure:"winrm_username" cty:"winrm_username"`
WinRMPassword *string `mapstructure:"winrm_password" cty:"winrm_password"`
WinRMHost *string `mapstructure:"winrm_host" cty:"winrm_host"`
WinRMPort *int `mapstructure:"winrm_port" cty:"winrm_port"`
WinRMTimeout *string `mapstructure:"winrm_timeout" cty:"winrm_timeout"`
WinRMUseSSL *bool `mapstructure:"winrm_use_ssl" cty:"winrm_use_ssl"`
WinRMInsecure *bool `mapstructure:"winrm_insecure" cty:"winrm_insecure"`
WinRMUseNTLM *bool `mapstructure:"winrm_use_ntlm" cty:"winrm_use_ntlm"`
UseSSHPrivateIp *bool `mapstructure:"use_ssh_private_ip" cty:"use_ssh_private_ip"`
PackerBuildName *string `mapstructure:"packer_build_name" cty:"packer_build_name"`
PackerBuilderType *string `mapstructure:"packer_builder_type" cty:"packer_builder_type"`
PackerDebug *bool `mapstructure:"packer_debug" cty:"packer_debug"`
PackerForce *bool `mapstructure:"packer_force" cty:"packer_force"`
PackerOnError *string `mapstructure:"packer_on_error" cty:"packer_on_error"`
PackerUserVars map[string]string `mapstructure:"packer_user_variables" cty:"packer_user_variables"`
PackerSensitiveVars []string `mapstructure:"packer_sensitive_variables" cty:"packer_sensitive_variables"`
PublicKey *string `mapstructure:"public_key" cty:"public_key"`
PrivateKey *string `mapstructure:"private_key" cty:"private_key"`
Region *string `mapstructure:"region" cty:"region"`
ProjectId *string `mapstructure:"project_id" cty:"project_id"`
BaseUrl *string `mapstructure:"base_url" cty:"base_url"`
ImageName *string `mapstructure:"image_name" cty:"image_name"`
ImageDescription *string `mapstructure:"image_description" cty:"image_description"`
ImageDestinations []common.FlatImageDestination `mapstructure:"image_copy_to_mappings" cty:"image_copy_to_mappings"`
WaitImageReadyTimeout *int `mapstructure:"wait_image_ready_timeout" cty:"wait_image_ready_timeout"`
Zone *string `mapstructure:"availability_zone" cty:"availability_zone"`
SourceImageId *string `mapstructure:"source_image_id" cty:"source_image_id"`
InstanceType *string `mapstructure:"instance_type" cty:"instance_type"`
InstanceName *string `mapstructure:"instance_name" cty:"instance_name"`
BootDiskType *string `mapstructure:"boot_disk_type" cty:"boot_disk_type"`
VPCId *string `mapstructure:"vpc_id" cty:"vpc_id"`
SubnetId *string `mapstructure:"subnet_id" cty:"subnet_id"`
SecurityGroupId *string `mapstructure:"security_group_id" cty:"security_group_id"`
Type *string `mapstructure:"communicator" cty:"communicator"`
PauseBeforeConnect *string `mapstructure:"pause_before_connecting" cty:"pause_before_connecting"`
SSHHost *string `mapstructure:"ssh_host" cty:"ssh_host"`
SSHPort *int `mapstructure:"ssh_port" cty:"ssh_port"`
SSHUsername *string `mapstructure:"ssh_username" cty:"ssh_username"`
SSHPassword *string `mapstructure:"ssh_password" cty:"ssh_password"`
SSHKeyPairName *string `mapstructure:"ssh_keypair_name" cty:"ssh_keypair_name"`
SSHTemporaryKeyPairName *string `mapstructure:"temporary_key_pair_name" cty:"temporary_key_pair_name"`
SSHClearAuthorizedKeys *bool `mapstructure:"ssh_clear_authorized_keys" cty:"ssh_clear_authorized_keys"`
SSHPrivateKeyFile *string `mapstructure:"ssh_private_key_file" cty:"ssh_private_key_file"`
SSHPty *bool `mapstructure:"ssh_pty" cty:"ssh_pty"`
SSHTimeout *string `mapstructure:"ssh_timeout" cty:"ssh_timeout"`
SSHAgentAuth *bool `mapstructure:"ssh_agent_auth" cty:"ssh_agent_auth"`
SSHDisableAgentForwarding *bool `mapstructure:"ssh_disable_agent_forwarding" cty:"ssh_disable_agent_forwarding"`
SSHHandshakeAttempts *int `mapstructure:"ssh_handshake_attempts" cty:"ssh_handshake_attempts"`
SSHBastionHost *string `mapstructure:"ssh_bastion_host" cty:"ssh_bastion_host"`
SSHBastionPort *int `mapstructure:"ssh_bastion_port" cty:"ssh_bastion_port"`
SSHBastionAgentAuth *bool `mapstructure:"ssh_bastion_agent_auth" cty:"ssh_bastion_agent_auth"`
SSHBastionUsername *string `mapstructure:"ssh_bastion_username" cty:"ssh_bastion_username"`
SSHBastionPassword *string `mapstructure:"ssh_bastion_password" cty:"ssh_bastion_password"`
SSHBastionPrivateKeyFile *string `mapstructure:"ssh_bastion_private_key_file" cty:"ssh_bastion_private_key_file"`
SSHFileTransferMethod *string `mapstructure:"ssh_file_transfer_method" cty:"ssh_file_transfer_method"`
SSHProxyHost *string `mapstructure:"ssh_proxy_host" cty:"ssh_proxy_host"`
SSHProxyPort *int `mapstructure:"ssh_proxy_port" cty:"ssh_proxy_port"`
SSHProxyUsername *string `mapstructure:"ssh_proxy_username" cty:"ssh_proxy_username"`
SSHProxyPassword *string `mapstructure:"ssh_proxy_password" cty:"ssh_proxy_password"`
SSHKeepAliveInterval *string `mapstructure:"ssh_keep_alive_interval" cty:"ssh_keep_alive_interval"`
SSHReadWriteTimeout *string `mapstructure:"ssh_read_write_timeout" cty:"ssh_read_write_timeout"`
SSHRemoteTunnels []string `mapstructure:"ssh_remote_tunnels" cty:"ssh_remote_tunnels"`
SSHLocalTunnels []string `mapstructure:"ssh_local_tunnels" cty:"ssh_local_tunnels"`
SSHPublicKey []byte `cty:"ssh_public_key"`
SSHPrivateKey []byte `cty:"ssh_private_key"`
WinRMUser *string `mapstructure:"winrm_username" cty:"winrm_username"`
WinRMPassword *string `mapstructure:"winrm_password" cty:"winrm_password"`
WinRMHost *string `mapstructure:"winrm_host" cty:"winrm_host"`
WinRMPort *int `mapstructure:"winrm_port" cty:"winrm_port"`
WinRMTimeout *string `mapstructure:"winrm_timeout" cty:"winrm_timeout"`
WinRMUseSSL *bool `mapstructure:"winrm_use_ssl" cty:"winrm_use_ssl"`
WinRMInsecure *bool `mapstructure:"winrm_insecure" cty:"winrm_insecure"`
WinRMUseNTLM *bool `mapstructure:"winrm_use_ntlm" cty:"winrm_use_ntlm"`
UseSSHPrivateIp *bool `mapstructure:"use_ssh_private_ip" cty:"use_ssh_private_ip"`
}
// FlatMapstructure returns a new FlatConfig.
@@ -98,7 +100,8 @@ func (*FlatConfig) HCL2Spec() map[string]hcldec.Spec {
"base_url": &hcldec.AttrSpec{Name: "base_url", Type: cty.String, Required: false},
"image_name": &hcldec.AttrSpec{Name: "image_name", Type: cty.String, Required: false},
"image_description": &hcldec.AttrSpec{Name: "image_description", Type: cty.String, Required: false},
"image_copy_to_mappings": &hcldec.BlockListSpec{TypeName: "image_copy_to_mappings", Nested: &hcldec.BlockSpec{TypeName: "image_copy_to_mappings", Nested: hcldec.ObjectSpec((*FlatImageDestination)(nil).HCL2Spec())}},
"image_copy_to_mappings": &hcldec.BlockListSpec{TypeName: "image_copy_to_mappings", Nested: &hcldec.BlockSpec{TypeName: "image_copy_to_mappings", Nested: hcldec.ObjectSpec((*common.FlatImageDestination)(nil).HCL2Spec())}},
"wait_image_ready_timeout": &hcldec.AttrSpec{Name: "wait_image_ready_timeout", Type: cty.Number, Required: false},
"availability_zone": &hcldec.AttrSpec{Name: "availability_zone", Type: cty.String, Required: false},
"source_image_id": &hcldec.AttrSpec{Name: "source_image_id", Type: cty.String, Required: false},
"instance_type": &hcldec.AttrSpec{Name: "instance_type", Type: cty.String, Required: false},
+17 -16
View File
@@ -2,6 +2,7 @@ package uhost
import (
"fmt"
ucloudcommon "github.com/hashicorp/packer/builder/ucloud/common"
"github.com/hashicorp/packer/packer"
"github.com/stretchr/testify/assert"
"os"
@@ -20,7 +21,7 @@ func TestBuilderAcc_validateRegion(t *testing.T) {
testAccPreCheck(t)
access := &AccessConfig{Region: "cn-bj2"}
access := &ucloudcommon.AccessConfig{Region: "cn-bj2"}
err := access.Config()
if err != nil {
t.Fatalf("Error on initing UCloud AccessConfig, %s", err)
@@ -94,8 +95,8 @@ func TestBuilderAcc_regionCopy(t *testing.T) {
Template: testBuilderAccRegionCopy(projectId),
Check: checkRegionCopy(
projectId,
[]ImageDestination{
{projectId, "cn-sh2", "packer-test-regionCopy-sh", "test"},
[]ucloudcommon.ImageDestination{
{ProjectId: projectId, Region: "cn-sh2", Name: "packer-test-regionCopy-sh", Description: "test"},
}),
})
}
@@ -121,21 +122,21 @@ func testBuilderAccRegionCopy(projectId string) string {
}`, projectId)
}
func checkRegionCopy(projectId string, imageDst []ImageDestination) builderT.TestCheckFunc {
func checkRegionCopy(projectId string, imageDst []ucloudcommon.ImageDestination) builderT.TestCheckFunc {
return func(artifacts []packer.Artifact) error {
if len(artifacts) > 1 {
return fmt.Errorf("more than 1 artifact")
}
artifactSet := artifacts[0]
artifact, ok := artifactSet.(*Artifact)
artifact, ok := artifactSet.(*ucloudcommon.Artifact)
if !ok {
return fmt.Errorf("unknown artifact: %#v", artifactSet)
}
destSet := newImageInfoSet(nil)
destSet := ucloudcommon.NewImageInfoSet(nil)
for _, dest := range imageDst {
destSet.Set(imageInfo{
destSet.Set(ucloudcommon.ImageInfo{
Region: dest.Region,
ProjectId: dest.ProjectId,
})
@@ -163,9 +164,9 @@ func checkRegionCopy(projectId string, imageDst []ImageDestination) builderT.Tes
if r.ProjectId == projectId && r.Region == "cn-bj2" {
continue
}
imageSet, err := client.describeImageByInfo(r.ProjectId, r.Region, r.ImageId)
imageSet, err := client.DescribeImageByInfo(r.ProjectId, r.Region, r.ImageId)
if err != nil {
if isNotFoundError(err) {
if ucloudcommon.IsNotFoundError(err) {
return fmt.Errorf("image %s in artifacts can not be found", r.ImageId)
}
return err
@@ -196,17 +197,17 @@ func testAccPreCheck(t *testing.T) {
func TestUCloudClientBaseUrlConfigurable(t *testing.T) {
const url = "baseUrl"
access := &AccessConfig{BaseUrl: url}
access := &ucloudcommon.AccessConfig{BaseUrl: url}
client, err := access.Client()
assert.Nil(t, err)
assert.Equal(t, url, client.uaccountconn.Client.GetConfig().BaseUrl, "account conn's base url not configurable")
assert.Equal(t, url, client.uhostconn.Client.GetConfig().BaseUrl, "host conn's base url not configurable")
assert.Equal(t, url, client.unetconn.Client.GetConfig().BaseUrl, "net conn's base url not configurable")
assert.Equal(t, url, client.vpcconn.Client.GetConfig().BaseUrl, "vpc conn's base url not configurable")
assert.Equal(t, url, client.UAccountConn.Client.GetConfig().BaseUrl, "account conn's base url not configurable")
assert.Equal(t, url, client.UHostConn.Client.GetConfig().BaseUrl, "host conn's base url not configurable")
assert.Equal(t, url, client.UNetConn.Client.GetConfig().BaseUrl, "net conn's base url not configurable")
assert.Equal(t, url, client.VPCConn.Client.GetConfig().BaseUrl, "vpc conn's base url not configurable")
}
func testUCloudClient() (*UCloudClient, error) {
access := &AccessConfig{Region: "cn-bj2"}
func testUCloudClient() (*ucloudcommon.UCloudClient, error) {
access := &ucloudcommon.AccessConfig{Region: "cn-bj2"}
err := access.Config()
if err != nil {
return nil, err
+2 -1
View File
@@ -1,6 +1,7 @@
package uhost
import (
ucloudcommon "github.com/hashicorp/packer/builder/ucloud/common"
"github.com/hashicorp/packer/packer"
"reflect"
"testing"
@@ -120,7 +121,7 @@ func TestBuilderPrepare_ImageDestinations(t *testing.T) {
t.Fatalf("should not have error: %s", err)
}
if !reflect.DeepEqual(b.config.ImageDestinations, []ImageDestination{
if !reflect.DeepEqual(b.config.ImageDestinations, []ucloudcommon.ImageDestination{
{
ProjectId: "project1",
Region: "region1",
-24
View File
@@ -1,24 +0,0 @@
package uhost
const (
// defaultPasswordStr, defaultPasswordNum and defaultPasswordSpe are used to general default value of root password of UHost instance
defaultPasswordNum = "012346789"
defaultPasswordStr = "abcdefghijklmnopqrstuvwxyz"
defaultPasswordSpe = "-_"
)
const (
osTypeWindows = "Windows"
securityGroupNonWeb = "recommend non web"
instanceStateRunning = "Running"
instanceStateStopped = "Stopped"
bootDiskStateNormal = "Normal"
imageStateAvailable = "Available"
ipTypePrivate = "Private"
)
var bootDiskTypeMap = map[string]string{
"cloud_ssd": "CLOUD_SSD",
"local_normal": "LOCAL_NORMAL",
"local_ssd": "LOCAL_SSD",
}
@@ -3,6 +3,7 @@ package uhost
import (
"context"
"fmt"
ucloudcommon "github.com/hashicorp/packer/builder/ucloud/common"
"github.com/hashicorp/packer/helper/multistep"
"github.com/hashicorp/packer/packer"
)
@@ -13,20 +14,20 @@ type stepCheckSourceImageId struct {
func (s *stepCheckSourceImageId) Run(ctx context.Context, state multistep.StateBag) multistep.StepAction {
ui := state.Get("ui").(packer.Ui)
client := state.Get("client").(*UCloudClient)
client := state.Get("client").(*ucloudcommon.UCloudClient)
ui.Say("Querying source image id...")
imageSet, err := client.DescribeImageById(s.SourceUHostImageId)
if err != nil {
if isNotFoundError(err) {
return halt(state, err, "")
if ucloudcommon.IsNotFoundError(err) {
return ucloudcommon.Halt(state, err, "")
}
return halt(state, err, fmt.Sprintf("Error on querying specified source_image_id %q", s.SourceUHostImageId))
return ucloudcommon.Halt(state, err, fmt.Sprintf("Error on querying specified source_image_id %q", s.SourceUHostImageId))
}
if imageSet.OsType == osTypeWindows {
return halt(state, err, "The ucloud-uhost builder does not support Windows images yet")
if imageSet.OsType == ucloudcommon.OsTypeWindows {
return ucloudcommon.Halt(state, err, "The ucloud-uhost builder does not support Windows images yet")
}
state.Put("source_image", imageSet)
@@ -3,6 +3,7 @@ package uhost
import (
"context"
"fmt"
ucloudcommon "github.com/hashicorp/packer/builder/ucloud/common"
"github.com/hashicorp/packer/helper/multistep"
"github.com/hashicorp/packer/packer"
"github.com/ucloud/ucloud-sdk-go/ucloud"
@@ -13,19 +14,19 @@ type stepConfigSecurityGroup struct {
}
func (s *stepConfigSecurityGroup) Run(ctx context.Context, state multistep.StateBag) multistep.StepAction {
client := state.Get("client").(*UCloudClient)
conn := client.unetconn
client := state.Get("client").(*ucloudcommon.UCloudClient)
conn := client.UNetConn
ui := state.Get("ui").(packer.Ui)
if len(s.SecurityGroupId) != 0 {
ui.Say(fmt.Sprintf("Trying to use specified security group %q...", s.SecurityGroupId))
securityGroupSet, err := client.describeFirewallById(s.SecurityGroupId)
securityGroupSet, err := client.DescribeFirewallById(s.SecurityGroupId)
if err != nil {
if isNotFoundError(err) {
if ucloudcommon.IsNotFoundError(err) {
err = fmt.Errorf("the specified security group %q does not exist", s.SecurityGroupId)
return halt(state, err, "")
return ucloudcommon.Halt(state, err, "")
}
return halt(state, err, fmt.Sprintf("Error on querying specified security group %q", s.SecurityGroupId))
return ucloudcommon.Halt(state, err, fmt.Sprintf("Error on querying specified security group %q", s.SecurityGroupId))
}
state.Put("security_group_id", securityGroupSet.FWId)
@@ -44,7 +45,7 @@ func (s *stepConfigSecurityGroup) Run(ctx context.Context, state multistep.State
resp, err := conn.DescribeFirewall(req)
if err != nil {
return halt(state, err, "Error on querying default security group")
return ucloudcommon.Halt(state, err, "Error on querying default security group")
}
if resp == nil || len(resp.DataSet) < 1 {
@@ -52,7 +53,7 @@ func (s *stepConfigSecurityGroup) Run(ctx context.Context, state multistep.State
}
for _, item := range resp.DataSet {
if item.Type == securityGroupNonWeb {
if item.Type == ucloudcommon.SecurityGroupNonWeb {
securityGroupId = item.FWId
break
}
@@ -66,7 +67,7 @@ func (s *stepConfigSecurityGroup) Run(ctx context.Context, state multistep.State
}
if securityGroupId == "" {
return halt(state, fmt.Errorf("the default security group does not exist"), "")
return ucloudcommon.Halt(state, fmt.Errorf("the default security group does not exist"), "")
}
state.Put("security_group_id", securityGroupId)
+6 -5
View File
@@ -3,6 +3,7 @@ package uhost
import (
"context"
"fmt"
ucloudcommon "github.com/hashicorp/packer/builder/ucloud/common"
"github.com/hashicorp/packer/helper/multistep"
"github.com/hashicorp/packer/packer"
)
@@ -12,18 +13,18 @@ type stepConfigSubnet struct {
}
func (s *stepConfigSubnet) Run(ctx context.Context, state multistep.StateBag) multistep.StepAction {
client := state.Get("client").(*UCloudClient)
client := state.Get("client").(*ucloudcommon.UCloudClient)
ui := state.Get("ui").(packer.Ui)
if len(s.SubnetId) != 0 {
ui.Say(fmt.Sprintf("Trying to use specified subnet %q...", s.SubnetId))
subnetSet, err := client.describeSubnetById(s.SubnetId)
subnetSet, err := client.DescribeSubnetById(s.SubnetId)
if err != nil {
if isNotFoundError(err) {
if ucloudcommon.IsNotFoundError(err) {
err = fmt.Errorf("the specified subnet %q does not exist", s.SubnetId)
return halt(state, err, "")
return ucloudcommon.Halt(state, err, "")
}
return halt(state, err, fmt.Sprintf("Error on querying specified subnet %q", s.SubnetId))
return ucloudcommon.Halt(state, err, fmt.Sprintf("Error on querying specified subnet %q", s.SubnetId))
}
state.Put("subnet_id", subnetSet.SubnetId)
+6 -5
View File
@@ -3,6 +3,7 @@ package uhost
import (
"context"
"fmt"
ucloudcommon "github.com/hashicorp/packer/builder/ucloud/common"
"github.com/hashicorp/packer/helper/multistep"
"github.com/hashicorp/packer/packer"
@@ -13,19 +14,19 @@ type stepConfigVPC struct {
}
func (s *stepConfigVPC) Run(ctx context.Context, state multistep.StateBag) multistep.StepAction {
client := state.Get("client").(*UCloudClient)
client := state.Get("client").(*ucloudcommon.UCloudClient)
ui := state.Get("ui").(packer.Ui)
if len(s.VPCId) != 0 {
ui.Say(fmt.Sprintf("Trying to use specified vpc %q...", s.VPCId))
vpcSet, err := client.describeVPCById(s.VPCId)
vpcSet, err := client.DescribeVPCById(s.VPCId)
if err != nil {
if isNotFoundError(err) {
if ucloudcommon.IsNotFoundError(err) {
err = fmt.Errorf("the specified vpc %q does not exist", s.VPCId)
return halt(state, err, "")
return ucloudcommon.Halt(state, err, "")
}
return halt(state, err, fmt.Sprintf("Error on querying specified vpc %q", s.VPCId))
return ucloudcommon.Halt(state, err, fmt.Sprintf("Error on querying specified vpc %q", s.VPCId))
}
state.Put("vpc_id", vpcSet.VPCId)
+23 -19
View File
@@ -3,6 +3,7 @@ package uhost
import (
"context"
"fmt"
ucloudcommon "github.com/hashicorp/packer/builder/ucloud/common"
"github.com/hashicorp/packer/common/retry"
"strings"
"time"
@@ -13,9 +14,10 @@ import (
)
type stepCopyUCloudImage struct {
ImageDestinations []ImageDestination
RegionId string
ProjectId string
ImageDestinations []ucloudcommon.ImageDestination
RegionId string
ProjectId string
WaitImageReadyTimeout int
}
func (s *stepCopyUCloudImage) Run(ctx context.Context, state multistep.StateBag) multistep.StepAction {
@@ -23,13 +25,13 @@ func (s *stepCopyUCloudImage) Run(ctx context.Context, state multistep.StateBag)
return multistep.ActionContinue
}
client := state.Get("client").(*UCloudClient)
conn := client.uhostconn
client := state.Get("client").(*ucloudcommon.UCloudClient)
conn := client.UHostConn
ui := state.Get("ui").(packer.Ui)
srcImageId := state.Get("image_id").(string)
artifactImages := state.Get("ucloud_images").(*imageInfoSet)
expectedImages := newImageInfoSet(nil)
artifactImages := state.Get("ucloud_images").(*ucloudcommon.ImageInfoSet)
expectedImages := ucloudcommon.NewImageInfoSet(nil)
ui.Say(fmt.Sprintf("Copying images from %q...", srcImageId))
for _, v := range s.ImageDestinations {
if v.ProjectId == s.ProjectId && v.Region == s.RegionId {
@@ -45,10 +47,10 @@ func (s *stepCopyUCloudImage) Run(ctx context.Context, state multistep.StateBag)
resp, err := conn.CopyCustomImage(req)
if err != nil {
return halt(state, err, fmt.Sprintf("Error on copying image %q to %s:%s", srcImageId, v.ProjectId, v.Region))
return ucloudcommon.Halt(state, err, fmt.Sprintf("Error on copying image %q to %s:%s", srcImageId, v.ProjectId, v.Region))
}
image := imageInfo{
image := ucloudcommon.ImageInfo{
Region: v.Region,
ProjectId: v.ProjectId,
ImageId: resp.TargetImageId,
@@ -62,24 +64,26 @@ func (s *stepCopyUCloudImage) Run(ctx context.Context, state multistep.StateBag)
ui.Message("Waiting for the copied images to become available...")
err := retry.Config{
Tries: 200,
ShouldRetry: func(err error) bool { return isNotCompleteError(err) },
RetryDelay: (&retry.Backoff{InitialBackoff: 2 * time.Second, MaxBackoff: 12 * time.Second, Multiplier: 2}).Linear,
StartTimeout: time.Duration(s.WaitImageReadyTimeout) * time.Second,
ShouldRetry: func(err error) bool {
return ucloudcommon.IsNotCompleteError(err)
},
RetryDelay: (&retry.Backoff{InitialBackoff: 2 * time.Second, MaxBackoff: 12 * time.Second, Multiplier: 2}).Linear,
}.Run(ctx, func(ctx context.Context) error {
for _, v := range expectedImages.GetAll() {
imageSet, err := client.describeImageByInfo(v.ProjectId, v.Region, v.ImageId)
imageSet, err := client.DescribeImageByInfo(v.ProjectId, v.Region, v.ImageId)
if err != nil {
return fmt.Errorf("reading %s:%s:%s failed, %s", v.ProjectId, v.Region, v.ImageId, err)
}
if imageSet.State == imageStateAvailable {
if imageSet.State == ucloudcommon.ImageStateAvailable {
expectedImages.Remove(v.Id())
continue
}
}
if len(expectedImages.GetAll()) != 0 {
return newNotCompleteError("copying image")
return ucloudcommon.NewNotCompletedError("copying image")
}
return nil
@@ -91,7 +95,7 @@ func (s *stepCopyUCloudImage) Run(ctx context.Context, state multistep.StateBag)
s = append(s, fmt.Sprintf("%s:%s:%s", v.ProjectId, v.Region, v.ImageId))
}
return halt(state, err, fmt.Sprintf("Error on waiting for copying images %q to become available", strings.Join(s, ",")))
return ucloudcommon.Halt(state, err, fmt.Sprintf("Error on waiting for copying images %q to become available", strings.Join(s, ",")))
}
ui.Message(fmt.Sprintf("Copying image complete"))
@@ -107,7 +111,7 @@ func (s *stepCopyUCloudImage) Cleanup(state multistep.StateBag) {
}
srcImageId := state.Get("image_id").(string)
ucloudImages := state.Get("ucloud_images").(*imageInfoSet)
ucloudImages := state.Get("ucloud_images").(*ucloudcommon.ImageInfoSet)
imageInfos := ucloudImages.GetAll()
if len(imageInfos) == 0 {
return
@@ -116,8 +120,8 @@ func (s *stepCopyUCloudImage) Cleanup(state multistep.StateBag) {
}
ui := state.Get("ui").(packer.Ui)
client := state.Get("client").(*UCloudClient)
conn := client.uhostconn
client := state.Get("client").(*ucloudcommon.UCloudClient)
conn := client.UHostConn
ui.Say(fmt.Sprintf("Deleting copied image because of cancellation or error..."))
for _, v := range imageInfos {
+14 -13
View File
@@ -3,6 +3,7 @@ package uhost
import (
"context"
"fmt"
ucloudcommon "github.com/hashicorp/packer/builder/ucloud/common"
"github.com/hashicorp/packer/common/retry"
"time"
@@ -17,8 +18,8 @@ type stepCreateImage struct {
}
func (s *stepCreateImage) Run(ctx context.Context, state multistep.StateBag) multistep.StepAction {
client := state.Get("client").(*UCloudClient)
conn := client.uhostconn
client := state.Get("client").(*ucloudcommon.UCloudClient)
conn := client.UHostConn
instance := state.Get("instance").(*uhost.UHostInstanceSet)
ui := state.Get("ui").(packer.Ui)
config := state.Get("config").(*Config)
@@ -32,14 +33,14 @@ func (s *stepCreateImage) Run(ctx context.Context, state multistep.StateBag) mul
resp, err := conn.CreateCustomImage(req)
if err != nil {
return halt(state, err, "Error on creating image")
return ucloudcommon.Halt(state, err, "Error on creating image")
}
ui.Message(fmt.Sprintf("Waiting for the created image %q to become available...", resp.ImageId))
err = retry.Config{
Tries: 200,
StartTimeout: time.Duration(config.WaitImageReadyTimeout) * time.Second,
ShouldRetry: func(err error) bool {
return isExpectedStateError(err)
return ucloudcommon.IsExpectedStateError(err)
},
RetryDelay: (&retry.Backoff{InitialBackoff: 2 * time.Second, MaxBackoff: 12 * time.Second, Multiplier: 2}).Linear,
}.Run(ctx, func(ctx context.Context) error {
@@ -47,26 +48,26 @@ func (s *stepCreateImage) Run(ctx context.Context, state multistep.StateBag) mul
if err != nil {
return err
}
if inst == nil || inst.State != imageStateAvailable {
return newExpectedStateError("image", resp.ImageId)
if inst == nil || inst.State != ucloudcommon.ImageStateAvailable {
return ucloudcommon.NewExpectedStateError("image", resp.ImageId)
}
return nil
})
if err != nil {
return halt(state, err, fmt.Sprintf("Error on waiting for image %q to become available", resp.ImageId))
return ucloudcommon.Halt(state, err, fmt.Sprintf("Error on waiting for image %q to become available", resp.ImageId))
}
imageSet, err := client.DescribeImageById(resp.ImageId)
if err != nil {
return halt(state, err, fmt.Sprintf("Error on reading image when creating %q", resp.ImageId))
return ucloudcommon.Halt(state, err, fmt.Sprintf("Error on reading image when creating %q", resp.ImageId))
}
s.image = imageSet
state.Put("image_id", imageSet.ImageId)
images := []imageInfo{
images := []ucloudcommon.ImageInfo{
{
ImageId: imageSet.ImageId,
ProjectId: config.ProjectId,
@@ -74,7 +75,7 @@ func (s *stepCreateImage) Run(ctx context.Context, state multistep.StateBag) mul
},
}
state.Put("ucloud_images", newImageInfoSet(images))
state.Put("ucloud_images", ucloudcommon.NewImageInfoSet(images))
ui.Message(fmt.Sprintf("Creating image %q complete", imageSet.ImageId))
return multistep.ActionContinue
}
@@ -89,8 +90,8 @@ func (s *stepCreateImage) Cleanup(state multistep.StateBag) {
return
}
client := state.Get("client").(*UCloudClient)
conn := client.uhostconn
client := state.Get("client").(*ucloudcommon.UCloudClient)
conn := client.UHostConn
ui := state.Get("ui").(packer.Ui)
ui.Say("Deleting image because of cancellation or error...")
+41 -34
View File
@@ -3,6 +3,7 @@ package uhost
import (
"context"
"fmt"
ucloudcommon "github.com/hashicorp/packer/builder/ucloud/common"
"github.com/hashicorp/packer/common/retry"
"github.com/hashicorp/packer/helper/multistep"
"github.com/hashicorp/packer/packer"
@@ -26,25 +27,25 @@ type stepCreateInstance struct {
}
func (s *stepCreateInstance) Run(ctx context.Context, state multistep.StateBag) multistep.StepAction {
client := state.Get("client").(*UCloudClient)
conn := client.uhostconn
client := state.Get("client").(*ucloudcommon.UCloudClient)
conn := client.UHostConn
ui := state.Get("ui").(packer.Ui)
ui.Say("Creating Instance...")
resp, err := conn.CreateUHostInstance(s.buildCreateInstanceRequest(state))
if err != nil {
return halt(state, err, "Error on creating instance")
return ucloudcommon.Halt(state, err, "Error on creating instance")
}
instanceId := resp.UHostIds[0]
err = retry.Config{
Tries: 20,
ShouldRetry: func(err error) bool {
return isExpectedStateError(err)
return ucloudcommon.IsExpectedStateError(err)
},
RetryDelay: (&retry.Backoff{InitialBackoff: 2 * time.Second, MaxBackoff: 6 * time.Second, Multiplier: 2}).Linear,
}.Run(ctx, func(ctx context.Context) error {
inst, err := client.describeUHostById(instanceId)
inst, err := client.DescribeUHostById(instanceId)
if err != nil {
return err
}
@@ -57,27 +58,27 @@ func (s *stepCreateInstance) Run(ctx context.Context, state multistep.StateBag)
return fmt.Errorf("install failed")
}
if inst == nil || inst.State != instanceStateRunning {
return newExpectedStateError("instance", instanceId)
if inst == nil || inst.State != ucloudcommon.InstanceStateRunning {
return ucloudcommon.NewExpectedStateError("instance", instanceId)
}
return nil
})
if err != nil {
return halt(state, err, fmt.Sprintf("Error on waiting for instance %q to become available", instanceId))
return ucloudcommon.Halt(state, err, fmt.Sprintf("Error on waiting for instance %q to become available", instanceId))
}
ui.Message(fmt.Sprintf("Creating instance %q complete", instanceId))
instance, err := client.describeUHostById(instanceId)
instance, err := client.DescribeUHostById(instanceId)
if err != nil {
return halt(state, err, fmt.Sprintf("Error on reading instance when creating %q", instanceId))
return ucloudcommon.Halt(state, err, fmt.Sprintf("Error on reading instance when creating %q", instanceId))
}
s.instanceId = instanceId
state.Put("instance", instance)
if instance.BootDiskState != bootDiskStateNormal {
if instance.BootDiskState != ucloudcommon.BootDiskStateNormal {
ui.Say("Waiting for boot disk of instance initialized")
if s.BootDiskType == "local_normal" || s.BootDiskType == "local_ssd" {
ui.Message(fmt.Sprintf("Warning: It takes around 10 mins for boot disk initialization when `boot_disk_type` is %q", s.BootDiskType))
@@ -86,23 +87,23 @@ func (s *stepCreateInstance) Run(ctx context.Context, state multistep.StateBag)
err = retry.Config{
Tries: 200,
ShouldRetry: func(err error) bool {
return isExpectedStateError(err)
return ucloudcommon.IsExpectedStateError(err)
},
RetryDelay: (&retry.Backoff{InitialBackoff: 2 * time.Second, MaxBackoff: 12 * time.Second, Multiplier: 2}).Linear,
}.Run(ctx, func(ctx context.Context) error {
inst, err := client.describeUHostById(instanceId)
inst, err := client.DescribeUHostById(instanceId)
if err != nil {
return err
}
if inst.BootDiskState != bootDiskStateNormal {
return newExpectedStateError("boot_disk of instance", instanceId)
if inst.BootDiskState != ucloudcommon.BootDiskStateNormal {
return ucloudcommon.NewExpectedStateError("boot_disk of instance", instanceId)
}
return nil
})
if err != nil {
return halt(state, err, fmt.Sprintf("Error on waiting for boot disk of instance %q initialized", instanceId))
return ucloudcommon.Halt(state, err, fmt.Sprintf("Error on waiting for boot disk of instance %q initialized", instanceId))
}
ui.Message(fmt.Sprintf("Waiting for boot disk of instance %q initialized complete", instanceId))
@@ -127,12 +128,12 @@ func (s *stepCreateInstance) Cleanup(state multistep.StateBag) {
ui.Say("Deleting instance...")
}
client := state.Get("client").(*UCloudClient)
conn := client.uhostconn
client := state.Get("client").(*ucloudcommon.UCloudClient)
conn := client.UHostConn
instance, err := client.describeUHostById(s.instanceId)
instance, err := client.DescribeUHostById(s.instanceId)
if err != nil {
if isNotFoundError(err) {
if ucloudcommon.IsNotFoundError(err) {
return
}
ui.Error(fmt.Sprintf("Error on reading instance when deleting %q, %s",
@@ -140,7 +141,7 @@ func (s *stepCreateInstance) Cleanup(state multistep.StateBag) {
return
}
if instance.State != instanceStateStopped {
if instance.State != ucloudcommon.InstanceStateStopped {
stopReq := conn.NewStopUHostInstanceRequest()
stopReq.UHostId = ucloud.String(s.instanceId)
if _, err = conn.StopUHostInstance(stopReq); err != nil {
@@ -152,17 +153,17 @@ func (s *stepCreateInstance) Cleanup(state multistep.StateBag) {
err = retry.Config{
Tries: 30,
ShouldRetry: func(err error) bool {
return isExpectedStateError(err)
return ucloudcommon.IsExpectedStateError(err)
},
RetryDelay: (&retry.Backoff{InitialBackoff: 2 * time.Second, MaxBackoff: 6 * time.Second, Multiplier: 2}).Linear,
}.Run(ctx, func(ctx context.Context) error {
instance, err := client.describeUHostById(s.instanceId)
instance, err := client.DescribeUHostById(s.instanceId)
if err != nil {
return err
}
if instance.State != instanceStateStopped {
return newExpectedStateError("instance", s.instanceId)
if instance.State != ucloudcommon.InstanceStateStopped {
return ucloudcommon.NewExpectedStateError("instance", s.instanceId)
}
return nil
@@ -188,10 +189,10 @@ func (s *stepCreateInstance) Cleanup(state multistep.StateBag) {
err = retry.Config{
Tries: 30,
ShouldRetry: func(err error) bool { return !isNotFoundError(err) },
ShouldRetry: func(err error) bool { return !ucloudcommon.IsNotFoundError(err) },
RetryDelay: (&retry.Backoff{InitialBackoff: 2 * time.Second, MaxBackoff: 6 * time.Second, Multiplier: 2}).Linear,
}.Run(ctx, func(ctx context.Context) error {
_, err := client.describeUHostById(s.instanceId)
_, err := client.DescribeUHostById(s.instanceId)
return err
})
@@ -205,8 +206,8 @@ func (s *stepCreateInstance) Cleanup(state multistep.StateBag) {
}
func (s *stepCreateInstance) buildCreateInstanceRequest(state multistep.StateBag) *uhost.CreateUHostInstanceRequest {
client := state.Get("client").(*UCloudClient)
conn := client.uhostconn
client := state.Get("client").(*ucloudcommon.UCloudClient)
conn := client.UHostConn
srcImage := state.Get("source_image").(*uhost.UHostImageSet)
config := state.Get("config").(*Config)
connectConfig := &config.RunConfig.Comm
@@ -218,16 +219,16 @@ func (s *stepCreateInstance) buildCreateInstanceRequest(state multistep.StateBag
if password == "" {
password = fmt.Sprintf("%s%s%s",
s.randStringFromCharSet(5, defaultPasswordStr),
s.randStringFromCharSet(1, defaultPasswordSpe),
s.randStringFromCharSet(5, defaultPasswordNum))
s.randStringFromCharSet(5, ucloudcommon.DefaultPasswordStr),
s.randStringFromCharSet(1, ucloudcommon.DefaultPasswordSpe),
s.randStringFromCharSet(5, ucloudcommon.DefaultPasswordNum))
if srcImage.OsType == "Linux" {
connectConfig.SSHPassword = password
}
}
req := conn.NewCreateUHostInstanceRequest()
t, _ := parseInstanceType(s.InstanceType)
t, _ := ucloudcommon.ParseInstanceType(s.InstanceType)
req.CPU = ucloud.Int(t.CPU)
req.Memory = ucloud.Int(t.Memory)
@@ -238,6 +239,12 @@ func (s *stepCreateInstance) buildCreateInstanceRequest(state multistep.StateBag
req.ChargeType = ucloud.String("Dynamic")
req.Password = ucloud.String(password)
req.MachineType = ucloud.String("N")
req.MinimalCpuPlatform = ucloud.String("Intel/Auto")
if t.HostType == "o" {
req.MachineType = ucloud.String("O")
}
if v, ok := state.GetOk("security_group_id"); ok {
req.SecurityGroupId = ucloud.String(v.(string))
}
@@ -253,7 +260,7 @@ func (s *stepCreateInstance) buildCreateInstanceRequest(state multistep.StateBag
bootDisk := uhost.UHostDisk{}
bootDisk.IsBoot = ucloud.String("true")
bootDisk.Size = ucloud.Int(srcImage.ImageSize)
bootDisk.Type = ucloud.String(bootDiskTypeMap[s.BootDiskType])
bootDisk.Type = ucloud.String(ucloudcommon.BootDiskTypeMap.Convert(s.BootDiskType))
req.Disks = append(req.Disks, bootDisk)
+5 -4
View File
@@ -2,6 +2,7 @@ package uhost
import (
"context"
ucloudcommon "github.com/hashicorp/packer/builder/ucloud/common"
"github.com/hashicorp/packer/helper/multistep"
"github.com/hashicorp/packer/packer"
)
@@ -10,20 +11,20 @@ type stepPreValidate struct {
ProjectId string
Region string
Zone string
ImageDestinations []ImageDestination
ImageDestinations []ucloudcommon.ImageDestination
}
func (s *stepPreValidate) Run(ctx context.Context, state multistep.StateBag) multistep.StepAction {
if err := s.validateProjectIds(state); err != nil {
return halt(state, err, "")
return ucloudcommon.Halt(state, err, "")
}
if err := s.validateRegions(state); err != nil {
return halt(state, err, "")
return ucloudcommon.Halt(state, err, "")
}
if err := s.validateZones(state); err != nil {
return halt(state, err, "")
return ucloudcommon.Halt(state, err, "")
}
return multistep.ActionContinue
+12 -11
View File
@@ -3,6 +3,7 @@ package uhost
import (
"context"
"fmt"
ucloudcommon "github.com/hashicorp/packer/builder/ucloud/common"
"github.com/hashicorp/packer/common/retry"
"time"
@@ -16,17 +17,17 @@ type stepStopInstance struct {
}
func (s *stepStopInstance) Run(ctx context.Context, state multistep.StateBag) multistep.StepAction {
client := state.Get("client").(*UCloudClient)
conn := client.uhostconn
client := state.Get("client").(*ucloudcommon.UCloudClient)
conn := client.UHostConn
instance := state.Get("instance").(*uhost.UHostInstanceSet)
ui := state.Get("ui").(packer.Ui)
instance, err := client.describeUHostById(instance.UHostId)
instance, err := client.DescribeUHostById(instance.UHostId)
if err != nil {
return halt(state, err, fmt.Sprintf("Error on reading instance when stopping %q", instance.UHostId))
return ucloudcommon.Halt(state, err, fmt.Sprintf("Error on reading instance when stopping %q", instance.UHostId))
}
if instance.State != instanceStateStopped {
if instance.State != ucloudcommon.InstanceStateStopped {
stopReq := conn.NewStopUHostInstanceRequest()
stopReq.UHostId = ucloud.String(instance.UHostId)
ui.Say(fmt.Sprintf("Stopping instance %q", instance.UHostId))
@@ -44,30 +45,30 @@ func (s *stepStopInstance) Run(ctx context.Context, state multistep.StateBag) mu
})
if err != nil {
return halt(state, err, fmt.Sprintf("Error on stopping instance %q", instance.UHostId))
return ucloudcommon.Halt(state, err, fmt.Sprintf("Error on stopping instance %q", instance.UHostId))
}
err = retry.Config{
Tries: 20,
ShouldRetry: func(err error) bool {
return isExpectedStateError(err)
return ucloudcommon.IsExpectedStateError(err)
},
RetryDelay: (&retry.Backoff{InitialBackoff: 2 * time.Second, MaxBackoff: 6 * time.Second, Multiplier: 2}).Linear,
}.Run(ctx, func(ctx context.Context) error {
instance, err := client.describeUHostById(instance.UHostId)
instance, err := client.DescribeUHostById(instance.UHostId)
if err != nil {
return err
}
if instance.State != instanceStateStopped {
return newExpectedStateError("instance", instance.UHostId)
if instance.State != ucloudcommon.InstanceStateStopped {
return ucloudcommon.NewExpectedStateError("instance", instance.UHostId)
}
return nil
})
if err != nil {
return halt(state, err, fmt.Sprintf("Error on waiting for stopping instance when stopping %q", instance.UHostId))
return ucloudcommon.Halt(state, err, fmt.Sprintf("Error on waiting for stopping instance when stopping %q", instance.UHostId))
}
ui.Message(fmt.Sprintf("Stopping instance %q complete", instance.UHostId))

Some files were not shown because too many files have changed in this diff Show More