From 7804a52dd2f79b77b052aee3c0e8793f96f42799 Mon Sep 17 00:00:00 2001 From: "mingsheng.su" Date: Wed, 19 Jun 2019 21:32:33 +0800 Subject: [PATCH] ucloud packer review --- builder/ucloud/uhost/access_config.go | 3 - builder/ucloud/uhost/client.go | 7 -- builder/ucloud/uhost/consts.go | 14 ++-- builder/ucloud/uhost/image_config.go | 1 + builder/ucloud/uhost/run_config.go | 43 +++++++++- .../ucloud/uhost/step_check_source_image.go | 3 +- .../uhost/step_config_security_group.go | 11 +-- builder/ucloud/uhost/step_config_subnet.go | 2 +- builder/ucloud/uhost/step_config_vpc.go | 2 +- builder/ucloud/uhost/step_copy_image.go | 34 ++++---- builder/ucloud/uhost/step_create_image.go | 10 +-- builder/ucloud/uhost/step_create_instance.go | 80 +++++++------------ builder/ucloud/uhost/step_stop_instance.go | 6 +- builder/ucloud/uhost/utils.go | 7 +- examples/ucloud/ubuntu.json | 29 ------- .../source/docs/builders/ucloud-uhost.html.md | 2 +- 16 files changed, 123 insertions(+), 131 deletions(-) delete mode 100644 examples/ucloud/ubuntu.json diff --git a/builder/ucloud/uhost/access_config.go b/builder/ucloud/uhost/access_config.go index ae1f074cc..5450617f0 100644 --- a/builder/ucloud/uhost/access_config.go +++ b/builder/ucloud/uhost/access_config.go @@ -86,7 +86,6 @@ func (c *AccessConfig) Config() error { } func (c *AccessConfig) ValidateProjectId(projectId string) error { - supportedProjectIds, err := c.getSupportedProjectIds() if err != nil { return err @@ -102,7 +101,6 @@ func (c *AccessConfig) ValidateProjectId(projectId string) error { } func (c *AccessConfig) ValidateRegion(region string) error { - supportedRegions, err := c.getSupportedRegions() if err != nil { return err @@ -118,7 +116,6 @@ func (c *AccessConfig) ValidateRegion(region string) error { } func (c *AccessConfig) ValidateZone(region, zone string) error { - supportedZones, err := c.getSupportedZones(region) if err != nil { return err diff --git a/builder/ucloud/uhost/client.go b/builder/ucloud/uhost/client.go index c7cfd427b..120f2d33c 100644 --- a/builder/ucloud/uhost/client.go +++ b/builder/ucloud/uhost/client.go @@ -27,7 +27,6 @@ func (c *UCloudClient) describeFirewallById(sgId string) (*unet.FirewallDataSet, resp, err := conn.DescribeFirewall(req) - // [API-STYLE] Fire wall api has not found err code, but others don't have if err != nil { if uErr, ok := err.(uerr.Error); ok && uErr.Code() == 54002 { return nil, newNotFoundError("security group", sgId) @@ -93,9 +92,6 @@ func (c *UCloudClient) DescribeImageById(imageId string) (*uhost.UHostImageSet, resp, err := c.uhostconn.DescribeImage(req) if err != nil { - //if uErr, ok := err.(uerr.Error); ok && uErr.Code() == 8889 { - // return nil, newNotFoundError("image", imageId) - //} return nil, err } @@ -132,9 +128,6 @@ func (c *UCloudClient) describeImageByInfo(projectId, regionId, imageId string) resp, err := c.uhostconn.DescribeImage(req) if err != nil { - //if uErr, ok := err.(uerr.Error); ok && uErr.Code() == 8889 { - // return nil, newNotFoundError("image", imageId) - //} return nil, err } diff --git a/builder/ucloud/uhost/consts.go b/builder/ucloud/uhost/consts.go index c95ef1735..a275c4230 100644 --- a/builder/ucloud/uhost/consts.go +++ b/builder/ucloud/uhost/consts.go @@ -8,13 +8,13 @@ const ( ) const ( - osTypeWindows = "Windows" - securityGroupNonWeb = "recommend non web" - instanceStateRunning = "Running" - instanceStateStopped = "Stopped" - bootDiskStateInitializing = "Initializing" - bootDiskStateNormal = "Normal" - imageStateAvailable = "Available" + osTypeWindows = "Windows" + securityGroupNonWeb = "recommend non web" + instanceStateRunning = "Running" + instanceStateStopped = "Stopped" + bootDiskStateNormal = "Normal" + imageStateAvailable = "Available" + ipTypePrivate = "Private" ) var bootDiskTypeMap = map[string]string{ diff --git a/builder/ucloud/uhost/image_config.go b/builder/ucloud/uhost/image_config.go index d60406bd2..85fe43822 100644 --- a/builder/ucloud/uhost/image_config.go +++ b/builder/ucloud/uhost/image_config.go @@ -35,6 +35,7 @@ func (c *ImageConfig) Prepare(ctx *interpolate.Context) []error { if imageDestination.Name == "" { imageDestination.Name = imageName } + errs = append(errs, imageDestination.validate()...) } } diff --git a/builder/ucloud/uhost/run_config.go b/builder/ucloud/uhost/run_config.go index bf5a48681..cf8f1b0c3 100644 --- a/builder/ucloud/uhost/run_config.go +++ b/builder/ucloud/uhost/run_config.go @@ -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, - []string{"local_normal", "local_ssd", "cloud_normal", "cloud_ssd"}); err != nil { + []string{"local_normal", "local_ssd", "cloud_ssd"}); err != nil { errs = append(errs, err) } @@ -63,9 +63,50 @@ func (c *RunConfig) Prepare(ctx *interpolate.Context) []error { errs = append(errs, fmt.Errorf("%q must be set when use_ssh_private_ip is true", "vpc_id")) } + if c.Comm.SSHPassword != "" && len(validateInstancePassword(c.Comm.SSHPassword)) != 0 { + for _, v := range validateInstancePassword(c.Comm.SSHPassword) { + errs = append(errs, v) + } + } + if len(errs) > 0 { return errs } return nil } + +var instancePasswordUpperPattern = regexp.MustCompile(`[A-Z]`) +var instancePasswordLowerPattern = regexp.MustCompile(`[a-z]`) +var instancePasswordNumPattern = regexp.MustCompile(`[0-9]`) +var instancePasswordSpecialPattern = regexp.MustCompile(`[` + "`" + `()~!@#$%^&*-+=_|{}\[\]:;'<>,.?/]`) +var instancePasswordPattern = regexp.MustCompile(`^[A-Za-z0-9` + "`" + `()~!@#$%^&*-+=_|{}\[\]:;'<>,.?/]{8,30}$`) + +func validateInstancePassword(password string) (errors []error) { + if !instancePasswordPattern.MatchString(password) { + errors = append(errors, fmt.Errorf("%q is invalid, should have between 8-30 characters and any characters must be legal, got %q", "ssh_password", password)) + } + + categoryCount := 0 + if instancePasswordUpperPattern.MatchString(password) { + categoryCount++ + } + + if instancePasswordLowerPattern.MatchString(password) { + categoryCount++ + } + + if instancePasswordNumPattern.MatchString(password) { + categoryCount++ + } + + if instancePasswordSpecialPattern.MatchString(password) { + categoryCount++ + } + + if categoryCount < 2 { + errors = append(errors, fmt.Errorf("%q is invalid, should have least 2 items of capital letters, lower case letters, numbers and special characters, got %q", "ssh_password", password)) + } + + return +} diff --git a/builder/ucloud/uhost/step_check_source_image.go b/builder/ucloud/uhost/step_check_source_image.go index a8302a870..316a1f795 100644 --- a/builder/ucloud/uhost/step_check_source_image.go +++ b/builder/ucloud/uhost/step_check_source_image.go @@ -2,6 +2,7 @@ package uhost import ( "context" + "fmt" "github.com/hashicorp/packer/helper/multistep" "github.com/hashicorp/packer/packer" ) @@ -21,7 +22,7 @@ func (s *stepCheckSourceImageId) Run(ctx context.Context, state multistep.StateB if isNotFoundError(err) { return halt(state, err, "") } - return halt(state, err, "Error on querying source_image_id") + return halt(state, err, fmt.Sprintf("Error on querying specified source_image_id %q", s.SourceUHostImageId)) } if imageSet.OsType == osTypeWindows { diff --git a/builder/ucloud/uhost/step_config_security_group.go b/builder/ucloud/uhost/step_config_security_group.go index 713d4be11..8b7531666 100644 --- a/builder/ucloud/uhost/step_config_security_group.go +++ b/builder/ucloud/uhost/step_config_security_group.go @@ -25,7 +25,7 @@ func (s *stepConfigSecurityGroup) Run(ctx context.Context, state multistep.State err = fmt.Errorf("the specified security group %q not exist", s.SecurityGroupId) return halt(state, err, "") } - return halt(state, err, "Error on querying security group") + return halt(state, err, fmt.Sprintf("Error on querying specified security group %q", s.SecurityGroupId)) } state.Put("security_group_id", securityGroupSet.FWId) @@ -44,7 +44,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 security group") + return halt(state, err, "Error on querying default security group") } if resp == nil || len(resp.DataSet) < 1 { @@ -65,10 +65,11 @@ func (s *stepConfigSecurityGroup) Run(ctx context.Context, state multistep.State offset = offset + limit } - if securityGroupId != "" { - state.Put("security_group_id", securityGroupId) - return multistep.ActionContinue + if securityGroupId == "" { + return halt(state, fmt.Errorf("the default security group not exist"), "") } + + state.Put("security_group_id", securityGroupId) return multistep.ActionContinue } diff --git a/builder/ucloud/uhost/step_config_subnet.go b/builder/ucloud/uhost/step_config_subnet.go index 5eb30c4be..7042bea71 100644 --- a/builder/ucloud/uhost/step_config_subnet.go +++ b/builder/ucloud/uhost/step_config_subnet.go @@ -23,7 +23,7 @@ func (s *stepConfigSubnet) Run(ctx context.Context, state multistep.StateBag) mu err = fmt.Errorf("the specified subnet %q not exist", s.SubnetId) return halt(state, err, "") } - return halt(state, err, "Error on querying subnet") + return halt(state, err, fmt.Sprintf("Error on querying specified subnet %q", s.SubnetId)) } state.Put("subnet_id", subnetSet.SubnetId) diff --git a/builder/ucloud/uhost/step_config_vpc.go b/builder/ucloud/uhost/step_config_vpc.go index 001c6024c..0290775ad 100644 --- a/builder/ucloud/uhost/step_config_vpc.go +++ b/builder/ucloud/uhost/step_config_vpc.go @@ -25,7 +25,7 @@ func (s *stepConfigVPC) Run(ctx context.Context, state multistep.StateBag) multi err = fmt.Errorf("the specified vpc %q not exist", s.VPCId) return halt(state, err, "") } - return halt(state, err, "Error on querying vpc") + return halt(state, err, fmt.Sprintf("Error on querying specified vpc %q", s.VPCId)) } state.Put("vpc_id", vpcSet.VPCId) diff --git a/builder/ucloud/uhost/step_copy_image.go b/builder/ucloud/uhost/step_copy_image.go index 7bd818c3d..e9a6cee33 100644 --- a/builder/ucloud/uhost/step_copy_image.go +++ b/builder/ucloud/uhost/step_copy_image.go @@ -4,6 +4,7 @@ import ( "context" "fmt" "github.com/hashicorp/packer/common/retry" + "strings" "time" "github.com/hashicorp/packer/helper/multistep" @@ -29,34 +30,34 @@ func (s *stepCopyUCloudImage) Run(ctx context.Context, state multistep.StateBag) srcImageId := state.Get("image_id").(string) artifactImages := state.Get("ucloud_images").(*imageInfoSet) expectedImages := newImageInfoSet(nil) - ui.Say(fmt.Sprintf("Copying image with %q...", srcImageId)) - for _, imageDestination := range s.ImageDestinations { - if imageDestination.ProjectId == s.ProjectId && imageDestination.Region == s.RegionId { + for _, v := range s.ImageDestinations { + if v.ProjectId == s.ProjectId && v.Region == s.RegionId { continue } req := conn.NewCopyCustomImageRequest() - req.TargetProjectId = ucloud.String(imageDestination.ProjectId) - req.TargetRegion = ucloud.String(imageDestination.Region) + req.TargetProjectId = ucloud.String(v.ProjectId) + req.TargetRegion = ucloud.String(v.Region) req.SourceImageId = ucloud.String(srcImageId) - req.TargetImageName = ucloud.String(imageDestination.Name) + req.TargetImageName = ucloud.String(v.Name) + req.TargetImageDescription = ucloud.String(v.Description) resp, err := conn.CopyCustomImage(req) if err != nil { - return halt(state, err, "Error on copying images") + return halt(state, err, fmt.Sprintf("Error on copying image %q to %s:%s", srcImageId, v.ProjectId, v.Region)) } image := imageInfo{ - Region: imageDestination.Region, - ProjectId: imageDestination.ProjectId, + Region: v.Region, + ProjectId: v.ProjectId, ImageId: resp.TargetImageId, } expectedImages.Set(image) artifactImages.Set(image) ui.Message(fmt.Sprintf("Copying image from %s:%s:%s to %s:%s:%s)", - s.ProjectId, s.RegionId, srcImageId, imageDestination.ProjectId, imageDestination.Region, resp.TargetImageId)) + s.ProjectId, s.RegionId, srcImageId, v.ProjectId, v.Region, resp.TargetImageId)) } err := retry.Config{ @@ -67,7 +68,7 @@ func (s *stepCopyUCloudImage) Run(ctx context.Context, state multistep.StateBag) for _, v := range expectedImages.GetAll() { imageSet, err := client.describeImageByInfo(v.ProjectId, v.Region, v.ImageId) if err != nil { - return err + return fmt.Errorf("reading %s:%s:%s failed, %s", v.ProjectId, v.Region, v.ImageId, err) } if imageSet.State == imageStateAvailable { @@ -84,10 +85,15 @@ func (s *stepCopyUCloudImage) Run(ctx context.Context, state multistep.StateBag) }) if err != nil { - return halt(state, err, fmt.Sprintf("Error on waiting for copying image finished")) + var s []string + for _, v := range expectedImages.GetAll() { + 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 available", strings.Join(s, ","))) } - ui.Message(fmt.Sprintf("Copy image complete")) + ui.Message(fmt.Sprintf("Copying image complete")) return multistep.ActionContinue } @@ -128,5 +134,5 @@ func (s *stepCopyUCloudImage) Cleanup(state multistep.StateBag) { } } - ui.Message("Delete copied image complete") + ui.Message("Deleting copied image complete") } diff --git a/builder/ucloud/uhost/step_create_image.go b/builder/ucloud/uhost/step_create_image.go index 48268af2f..374a08e26 100644 --- a/builder/ucloud/uhost/step_create_image.go +++ b/builder/ucloud/uhost/step_create_image.go @@ -32,7 +32,7 @@ func (s *stepCreateImage) Run(ctx context.Context, state multistep.StateBag) mul resp, err := conn.CreateCustomImage(req) if err != nil { - return halt(state, err, "") + return halt(state, err, "Error on creating image") } err = retry.Config{ @@ -54,12 +54,12 @@ func (s *stepCreateImage) Run(ctx context.Context, state multistep.StateBag) mul }) if err != nil { - return halt(state, err, "Error on waiting for image to available") + return halt(state, err, fmt.Sprintf("Error on waiting for image %q available", resp.ImageId)) } imageSet, err := client.DescribeImageById(resp.ImageId) if err != nil { - return halt(state, err, "Error on reading image") + return halt(state, err, fmt.Sprintf("Error on reading image when creating %q", resp.ImageId)) } s.image = imageSet @@ -74,7 +74,7 @@ func (s *stepCreateImage) Run(ctx context.Context, state multistep.StateBag) mul } state.Put("ucloud_images", newImageInfoSet(images)) - ui.Message(fmt.Sprintf("Create image %q complete", imageSet.ImageId)) + ui.Message(fmt.Sprintf("Creating image %q complete", imageSet.ImageId)) return multistep.ActionContinue } @@ -99,5 +99,5 @@ func (s *stepCreateImage) Cleanup(state multistep.StateBag) { if err != nil { ui.Error(fmt.Sprintf("Error on deleting image %q", s.image.ImageId)) } - ui.Message(fmt.Sprintf("Delete image %q complete", s.image.ImageId)) + ui.Message(fmt.Sprintf("Deleting image %q complete", s.image.ImageId)) } diff --git a/builder/ucloud/uhost/step_create_instance.go b/builder/ucloud/uhost/step_create_instance.go index e797d5fea..b0b0652e7 100644 --- a/builder/ucloud/uhost/step_create_instance.go +++ b/builder/ucloud/uhost/step_create_instance.go @@ -31,12 +31,7 @@ func (s *stepCreateInstance) Run(ctx context.Context, state multistep.StateBag) ui := state.Get("ui").(packer.Ui) ui.Say("Creating Instance...") - req, err := s.buildCreateInstanceRequest(state) - if err != nil { - return halt(state, err, "") - } - - resp, err := conn.CreateUHostInstance(req) + resp, err := conn.CreateUHostInstance(s.buildCreateInstanceRequest(state)) if err != nil { return halt(state, err, "Error on creating instance") } @@ -53,6 +48,15 @@ func (s *stepCreateInstance) Run(ctx context.Context, state multistep.StateBag) if err != nil { return err } + + if inst.State == "ResizeFail" { + return fmt.Errorf("resizing instance failed") + } + + if inst.State == "Install Fail" { + return fmt.Errorf("install failed") + } + if inst == nil || inst.State != instanceStateRunning { return newExpectedStateError("instance", instanceId) } @@ -61,20 +65,23 @@ func (s *stepCreateInstance) Run(ctx context.Context, state multistep.StateBag) }) if err != nil { - return halt(state, err, "Error on waiting for instance to available") + return halt(state, err, fmt.Sprintf("Error on waiting for instance %q available", instanceId)) } - ui.Message(fmt.Sprintf("Create instance %q complete", instanceId)) + ui.Message(fmt.Sprintf("Creating instance %q complete", instanceId)) instance, err := client.describeUHostById(instanceId) if err != nil { - return halt(state, err, "") + return halt(state, err, fmt.Sprintf("Error on reading instance when creating %q", instanceId)) } s.instanceId = instanceId state.Put("instance", instance) - if instance.BootDiskState == bootDiskStateInitializing { - ui.Say(fmt.Sprintf("Waiting for boot disk of instance initialized when boot_disk_type is %q", s.BootDiskType)) + if instance.BootDiskState != 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)) + } err = retry.Config{ Tries: 200, @@ -95,10 +102,10 @@ func (s *stepCreateInstance) Run(ctx context.Context, state multistep.StateBag) }) if err != nil { - return halt(state, err, "Error on waiting for boot disk of instance initialized") + return halt(state, err, fmt.Sprintf("Error on waiting for boot disk of instance %q initialized", instanceId)) } - ui.Message(fmt.Sprintf("Waite for boot disk of instance %q initialized complete", instanceId)) + ui.Message(fmt.Sprintf("Waiting for boot disk of instance %q initialized complete", instanceId)) } return multistep.ActionContinue @@ -123,35 +130,21 @@ func (s *stepCreateInstance) Cleanup(state multistep.StateBag) { client := state.Get("client").(*UCloudClient) conn := client.uhostconn - stopReq := conn.NewPoweroffUHostInstanceRequest() - stopReq.UHostId = ucloud.String(s.instanceId) - instance, err := client.describeUHostById(s.instanceId) if err != nil { if isNotFoundError(err) { return } - ui.Error(fmt.Sprintf("Error on reading instance when delete %q, %s", + ui.Error(fmt.Sprintf("Error on reading instance when deleting %q, %s", s.instanceId, err.Error())) return } if instance.State != instanceStateStopped { - err = retry.Config{ - Tries: 5, - ShouldRetry: func(err error) bool { - return err != nil - }, - RetryDelay: (&retry.Backoff{InitialBackoff: 2 * time.Second, MaxBackoff: 6 * time.Second, Multiplier: 2}).Linear, - }.Run(ctx, func(ctx context.Context) error { - if _, err = conn.PoweroffUHostInstance(stopReq); err != nil { - return err - } - return nil - }) - - if err != nil { - ui.Error(fmt.Sprintf("Error on stopping instance when delete %q, %s", + stopReq := conn.NewPoweroffUHostInstanceRequest() + stopReq.UHostId = ucloud.String(s.instanceId) + if _, err = conn.PoweroffUHostInstance(stopReq); err != nil { + ui.Error(fmt.Sprintf("Error on stopping instance when deleting %q, %s", s.instanceId, err.Error())) return } @@ -176,7 +169,7 @@ func (s *stepCreateInstance) Cleanup(state multistep.StateBag) { }) if err != nil { - ui.Error(fmt.Sprintf("Error on waiting for instance %q to stopped, %s", + ui.Error(fmt.Sprintf("Error on waiting for stopping instance when deleting %q, %s", s.instanceId, err.Error())) return } @@ -187,20 +180,7 @@ func (s *stepCreateInstance) Cleanup(state multistep.StateBag) { deleteReq.ReleaseUDisk = ucloud.Bool(true) deleteReq.ReleaseEIP = ucloud.Bool(true) - err = retry.Config{ - Tries: 5, - ShouldRetry: func(err error) bool { - return err != nil - }, - RetryDelay: (&retry.Backoff{InitialBackoff: 2 * time.Second, MaxBackoff: 6 * time.Second, Multiplier: 2}).Linear, - }.Run(ctx, func(ctx context.Context) error { - if _, err = conn.TerminateUHostInstance(deleteReq); err != nil { - return err - } - return nil - }) - - if err != nil { + if _, err = conn.TerminateUHostInstance(deleteReq); err != nil { ui.Error(fmt.Sprintf("Error on deleting instance %q, %s", s.instanceId, err.Error())) return @@ -221,10 +201,10 @@ func (s *stepCreateInstance) Cleanup(state multistep.StateBag) { return } - ui.Message(fmt.Sprintf("Delete instance %q complete", s.instanceId)) + ui.Message(fmt.Sprintf("Deleting instance %q complete", s.instanceId)) } -func (s *stepCreateInstance) buildCreateInstanceRequest(state multistep.StateBag) (*uhost.CreateUHostInstanceRequest, error) { +func (s *stepCreateInstance) buildCreateInstanceRequest(state multistep.StateBag) *uhost.CreateUHostInstanceRequest { client := state.Get("client").(*UCloudClient) conn := client.uhostconn srcImage := state.Get("source_image").(*uhost.UHostImageSet) @@ -292,7 +272,7 @@ func (s *stepCreateInstance) buildCreateInstanceRequest(state multistep.StateBag req.NetworkInterface = append(req.NetworkInterface, networkInterface) } - return req, nil + return req } func (s *stepCreateInstance) randStringFromCharSet(strlen int, charSet string) string { diff --git a/builder/ucloud/uhost/step_stop_instance.go b/builder/ucloud/uhost/step_stop_instance.go index 621633b3c..4a87d4059 100644 --- a/builder/ucloud/uhost/step_stop_instance.go +++ b/builder/ucloud/uhost/step_stop_instance.go @@ -23,7 +23,7 @@ func (s *stepStopInstance) Run(ctx context.Context, state multistep.StateBag) mu instance, err := client.describeUHostById(instance.UHostId) if err != nil { - return halt(state, err, fmt.Sprintf("Error on reading instance when stop %q", instance.UHostId)) + return halt(state, err, fmt.Sprintf("Error on reading instance when stopping %q", instance.UHostId)) } if instance.State != instanceStateStopped { @@ -67,10 +67,10 @@ func (s *stepStopInstance) Run(ctx context.Context, state multistep.StateBag) mu }) if err != nil { - return halt(state, err, fmt.Sprintf("Error on waiting for instance %q to stopped", instance.UHostId)) + return halt(state, err, fmt.Sprintf("Error on waiting for stopping instance when stopping %q", instance.UHostId)) } - ui.Message(fmt.Sprintf("Stop instance %q complete", instance.UHostId)) + ui.Message(fmt.Sprintf("Stopping instance %q complete", instance.UHostId)) } return multistep.ActionContinue diff --git a/builder/ucloud/uhost/utils.go b/builder/ucloud/uhost/utils.go index 55f43a510..b05216bc3 100644 --- a/builder/ucloud/uhost/utils.go +++ b/builder/ucloud/uhost/utils.go @@ -46,17 +46,18 @@ func SSHHost(usePrivateIp bool) func(multistep.StateBag) (string, error) { var privateIp, publicIp string for _, v := range instance.IPSet { - if v.Type == "Private" { + if v.Type == ipTypePrivate { privateIp = v.IP } else { publicIp = v.IP } } + if usePrivateIp { return privateIp, nil - } else { - return publicIp, nil } + + return publicIp, nil } } diff --git a/examples/ucloud/ubuntu.json b/examples/ucloud/ubuntu.json deleted file mode 100644 index 930ecac32..000000000 --- a/examples/ucloud/ubuntu.json +++ /dev/null @@ -1,29 +0,0 @@ -{ - "variables": { - "ucloud_public_key": "{{env `UCLOUD_PUBLIC_KEY`}}", - "ucloud_private_key": "{{env `UCLOUD_PRIVATE_KEY`}}", - "ucloud_project_id": "{{env `UCLOUD_PROJECT_ID`}}" - }, - - "builders": [{ - "type": "ucloud-uhost", - "public_key":"{{user `ucloud_public_key`}}", - "private_key":"{{user `ucloud_private_key`}}", - "project_id": "{{user `ucloud_project_id`}}", - "region": "cn-bj2", - "availability_zone": "cn-bj2-02", - "instance_type": "n-basic-2", - "source_image_id":"uimage-irofn4", - "ssh_username":"ubuntu", - "image_name": "packer-test-ubuntu-bj" - }], - "provisioners": [{ - "type": "shell", - "inline": [ - "sudo visudo", - "ubuntu ALL = NOPASSWD: /usr/local/sbin/apt-get", - "sudo apt-get update", - "sudo apt-get install -y mysql" - ] - }] -} \ No newline at end of file diff --git a/website/source/docs/builders/ucloud-uhost.html.md b/website/source/docs/builders/ucloud-uhost.html.md index b7b10a6fa..b712819d1 100644 --- a/website/source/docs/builders/ucloud-uhost.html.md +++ b/website/source/docs/builders/ucloud-uhost.html.md @@ -26,7 +26,7 @@ In addition to the options listed here, a [communicator](../templates/communicator.html) can be configured for this builder. -\~> **Note:** This builder only support ssh authenticating with username and given password. +\~> **Note:** This builder not support build Windows image yet and only support ssh authenticating with `ssh_user_name` (Required) and `ssh_password` (Optional). There into, `ssh_user_name` can be set `root` for CentoOS image, `ubuntu` for Ubuntu image. `ssh_password` contains 8-30 characters, and at least 2 items of capital letters, lower case letters, numbers and special characters. The special characters include `()~!@#$%^&*-+=_|{}\[]:;'<>,.?/. ### Required: