diff --git a/builder/tencentcloud/cvm/builder.hcl2spec.go b/builder/tencentcloud/cvm/builder.hcl2spec.go index 1ea698fcc..d04489d35 100644 --- a/builder/tencentcloud/cvm/builder.hcl2spec.go +++ b/builder/tencentcloud/cvm/builder.hcl2spec.go @@ -31,7 +31,8 @@ type FlatConfig struct { ImageCopyRegions []string `mapstructure:"image_copy_regions" required:"false" cty:"image_copy_regions" hcl:"image_copy_regions"` ImageShareAccounts []string `mapstructure:"image_share_accounts" required:"false" cty:"image_share_accounts" hcl:"image_share_accounts"` AssociatePublicIpAddress *bool `mapstructure:"associate_public_ip_address" required:"false" cty:"associate_public_ip_address" hcl:"associate_public_ip_address"` - SourceImageId *string `mapstructure:"source_image_id" required:"true" cty:"source_image_id" hcl:"source_image_id"` + SourceImageId *string `mapstructure:"source_image_id" required:"false" cty:"source_image_id" hcl:"source_image_id"` + SourceImageName *string `mapstructure:"source_image_name" required:"false" cty:"source_image_name" hcl:"source_image_name"` InstanceType *string `mapstructure:"instance_type" required:"true" cty:"instance_type" hcl:"instance_type"` InstanceName *string `mapstructure:"instance_name" required:"false" cty:"instance_name" hcl:"instance_name"` DiskType *string `mapstructure:"disk_type" required:"false" cty:"disk_type" hcl:"disk_type"` @@ -136,6 +137,7 @@ func (*FlatConfig) HCL2Spec() map[string]hcldec.Spec { "image_share_accounts": &hcldec.AttrSpec{Name: "image_share_accounts", Type: cty.List(cty.String), Required: false}, "associate_public_ip_address": &hcldec.AttrSpec{Name: "associate_public_ip_address", Type: cty.Bool, Required: false}, "source_image_id": &hcldec.AttrSpec{Name: "source_image_id", Type: cty.String, Required: false}, + "source_image_name": &hcldec.AttrSpec{Name: "source_image_name", Type: cty.String, Required: false}, "instance_type": &hcldec.AttrSpec{Name: "instance_type", Type: cty.String, Required: false}, "instance_name": &hcldec.AttrSpec{Name: "instance_name", Type: cty.String, Required: false}, "disk_type": &hcldec.AttrSpec{Name: "disk_type", Type: cty.String, Required: false}, diff --git a/builder/tencentcloud/cvm/run_config.go b/builder/tencentcloud/cvm/run_config.go index c92760650..08f0cfb6b 100644 --- a/builder/tencentcloud/cvm/run_config.go +++ b/builder/tencentcloud/cvm/run_config.go @@ -27,7 +27,10 @@ type TencentCloudRunConfig struct { AssociatePublicIpAddress bool `mapstructure:"associate_public_ip_address" required:"false"` // The base image id of Image you want to create // your customized image from. - SourceImageId string `mapstructure:"source_image_id" required:"true"` + SourceImageId string `mapstructure:"source_image_id" required:"false"` + // The base image name of Image you want to create your + // customized image from.Conflict with SourceImageId. + SourceImageName string `mapstructure:"source_image_name" required:"false"` // The instance type your cvm will be launched by. // You should reference Instace Type // for parameter taking. @@ -108,11 +111,11 @@ func (cf *TencentCloudRunConfig) Prepare(ctx *interpolate.Context) []error { } errs := cf.Comm.Prepare(ctx) - if cf.SourceImageId == "" { - errs = append(errs, errors.New("source_image_id must be specified")) + if cf.SourceImageId == "" && cf.SourceImageName == "" { + errs = append(errs, errors.New("source_image_id or source_image_name must be specified")) } - if !CheckResourceIdFormat("img", cf.SourceImageId) { + if cf.SourceImageId != "" && !CheckResourceIdFormat("img", cf.SourceImageId) { errs = append(errs, errors.New("source_image_id wrong format")) } diff --git a/builder/tencentcloud/cvm/step_check_source_image.go b/builder/tencentcloud/cvm/step_check_source_image.go index f9af0bf24..ea1e2bb5a 100644 --- a/builder/tencentcloud/cvm/step_check_source_image.go +++ b/builder/tencentcloud/cvm/step_check_source_image.go @@ -3,6 +3,7 @@ package cvm import ( "context" "fmt" + "regexp" "github.com/hashicorp/packer/helper/multistep" cvm "github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/cvm/v20170312" @@ -13,16 +14,36 @@ type stepCheckSourceImage struct { } func (s *stepCheckSourceImage) Run(ctx context.Context, state multistep.StateBag) multistep.StepAction { + var ( + imageNameRegex *regexp.Regexp + err error + ) config := state.Get("config").(*Config) client := state.Get("cvm_client").(*cvm.Client) Say(state, config.SourceImageId, "Trying to check source image") req := cvm.NewDescribeImagesRequest() - req.ImageIds = []*string{&config.SourceImageId} - req.InstanceType = &config.InstanceType + // req.InstanceType = &config.InstanceType + if config.SourceImageId != "" { + req.ImageIds = []*string{&config.SourceImageId} + } else { + imageNameRegex, err = regexp.Compile(config.SourceImageName) + if err != nil { + return Halt(state, fmt.Errorf("regex compilation error"), "Bad input") + } + private := "PRIVATE_IMAGE" + public := "PUBLIC_IMAGE" + shared := "SHARED_IMAGE" + filterType := "image-type" + filter := &cvm.Filter{ + Name: &filterType, + Values: []*string{&private, &public, &shared}, + } + req.Filters = []*cvm.Filter{filter} + } var resp *cvm.DescribeImagesResponse - err := Retry(ctx, func(ctx context.Context) error { + err = Retry(ctx, func(ctx context.Context) error { var err error resp, err = client.DescribeImages(req) return err @@ -32,9 +53,20 @@ func (s *stepCheckSourceImage) Run(ctx context.Context, state multistep.StateBag } if *resp.Response.TotalCount > 0 { - state.Put("source_image", resp.Response.ImageSet[0]) - Message(state, *resp.Response.ImageSet[0].ImageName, "Image found") - return multistep.ActionContinue + images := resp.Response.ImageSet + if imageNameRegex != nil { + for _, image := range images { + if imageNameRegex.MatchString(*image.ImageName) { + state.Put("source_image", image) + Message(state, *image.ImageName, "Image found") + return multistep.ActionContinue + } + } + } else { + state.Put("source_image", images[0]) + Message(state, *resp.Response.ImageSet[0].ImageName, "Image found") + return multistep.ActionContinue + } } return Halt(state, fmt.Errorf("No image found under current instance_type(%s) restriction", config.InstanceType), "")