mirror of
https://github.com/hashicorp/packer.git
synced 2026-10-13 09:42:02 -04:00
Merge pull request #8261 from shawnmssu/feature/ucloud_import
Packer Post-Processor support UCloud import
This commit is contained in:
@@ -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
-1
@@ -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
|
||||
@@ -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
-1
@@ -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
-1
@@ -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"
|
||||
@@ -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 != "" {
|
||||
@@ -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,
|
||||
}
|
||||
|
||||
@@ -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},
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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",
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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 {
|
||||
|
||||
@@ -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...")
|
||||
|
||||
@@ -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)
|
||||
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
Reference in New Issue
Block a user