From 7a868d3ae74c52a9e977f7654c58856da2ff57df Mon Sep 17 00:00:00 2001 From: "renzheng.wang" Date: Thu, 15 Jun 2023 21:58:46 +0800 Subject: [PATCH] support uk8s custom image and custom boot disk size --- builder/ucloud/common/access_config.go | 6 ++++- builder/ucloud/common/client.go | 23 +++++++++++++++++++ builder/ucloud/common/consts.go | 5 ++++ builder/ucloud/common/run_config.go | 3 +++ builder/ucloud/uhost/builder.go | 1 + builder/ucloud/uhost/builder.hcl2spec.go | 2 ++ .../ucloud/uhost/step_check_source_image.go | 17 ++++++++++++-- builder/ucloud/uhost/step_create_instance.go | 8 +++++++ .../ucloud/common/RunConfig-not-required.mdx | 3 +++ 9 files changed, 65 insertions(+), 3 deletions(-) diff --git a/builder/ucloud/common/access_config.go b/builder/ucloud/common/access_config.go index 75c9c8e..daa6f9b 100644 --- a/builder/ucloud/common/access_config.go +++ b/builder/ucloud/common/access_config.go @@ -17,6 +17,7 @@ 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/uk8s" "github.com/ucloud/ucloud-sdk-go/services/unet" "github.com/ucloud/ucloud-sdk-go/services/vpc" "github.com/ucloud/ucloud-sdk-go/ucloud" @@ -122,7 +123,7 @@ func (c *AccessConfig) Client() (*UCloudClient, error) { c.client.VPCConn = vpc.NewClient(&cfg, &cred) c.client.UAccountConn = uaccount.NewClient(&cfg, &cred) c.client.UFileConn = ufile.NewClient(&cfg, &cred) - + c.client.UK8sConn = uk8s.NewClient(&cfg, &cred) if cloudShellCredHandler != nil { if err := c.client.UHostConn.AddHttpRequestHandler(cloudShellCredHandler); err != nil { return nil, err @@ -139,6 +140,9 @@ func (c *AccessConfig) Client() (*UCloudClient, error) { if err := c.client.UFileConn.AddHttpRequestHandler(cloudShellCredHandler); err != nil { return nil, err } + if err := c.client.UK8sConn.AddHttpRequestHandler(cloudShellCredHandler); err != nil { + return nil, err + } } return c.client, nil diff --git a/builder/ucloud/common/client.go b/builder/ucloud/common/client.go index 58452ca..fe7bc4e 100644 --- a/builder/ucloud/common/client.go +++ b/builder/ucloud/common/client.go @@ -4,6 +4,7 @@ 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/uk8s" "github.com/ucloud/ucloud-sdk-go/services/unet" "github.com/ucloud/ucloud-sdk-go/services/vpc" "github.com/ucloud/ucloud-sdk-go/ucloud" @@ -12,6 +13,7 @@ import ( type UCloudClient struct { UHostConn *uhost.UHostClient + UK8sConn *uk8s.UK8SClient UNetConn *unet.UNetClient VPCConn *vpc.VPCClient UAccountConn *uaccount.UAccountClient @@ -140,3 +142,24 @@ func (c *UCloudClient) DescribeImageByInfo(projectId, regionId, imageId string) return &resp.ImageSet[0], nil } + +func (c *UCloudClient) DescribeUK8sNodeImageById(imageId string) (*uk8s.ImageInfo, error) { + if imageId == "" { + return nil, NewNotFoundError("image", imageId) + } + req := c.UK8sConn.NewDescribeUK8SImageRequest() + resp, err := c.UK8sConn.DescribeUK8SImage(req) + if err != nil { + return nil, err + } + + if len(resp.ImageSet) < 1 { + return nil, NewNotFoundError("image", imageId) + } + for _, image := range resp.ImageSet { + if image.ImageId == imageId { + return &image, nil + } + } + return nil, NewNotFoundError("image", imageId) +} diff --git a/builder/ucloud/common/consts.go b/builder/ucloud/common/consts.go index c0c64af..88952c1 100644 --- a/builder/ucloud/common/consts.go +++ b/builder/ucloud/common/consts.go @@ -24,6 +24,11 @@ const ( DefaultCreateImageTimeout = 3600 ) +const ( + UK8sImageSize = 40 + UK8sImageOsType = "Linux" +) + var BootDiskTypeMap = NewStringConverter(map[string]string{ "cloud_ssd": "CLOUD_SSD", "local_normal": "LOCAL_NORMAL", diff --git a/builder/ucloud/common/run_config.go b/builder/ucloud/common/run_config.go index f44bbe6..579f75a 100644 --- a/builder/ucloud/common/run_config.go +++ b/builder/ucloud/common/run_config.go @@ -30,6 +30,9 @@ type RunConfig struct { // //~> **Note:** It takes around 10 mins for boot disk initialization when `boot_disk_type` is `local_normal` or `local_ssd`. BootDiskType string `mapstructure:"boot_disk_type" required:"false"` + // The size of boot disk associated to UHost instance, which cannot be smaller than the size of source image. + // The unit is `GB`. Default value is the size of source image. + BootDiskSize int `mapstructure:"boot_disk_size" required:"false"` // The ID of VPC linked to the UHost instance. If not defined `vpc_id`, the instance will use the default VPC in the current region. VPCId string `mapstructure:"vpc_id" required:"false"` // The ID of subnet under the VPC. If `vpc_id` is defined, the `subnet_id` is mandatory required. diff --git a/builder/ucloud/uhost/builder.go b/builder/ucloud/uhost/builder.go index 0ff1817..62f651b 100644 --- a/builder/ucloud/uhost/builder.go +++ b/builder/ucloud/uhost/builder.go @@ -113,6 +113,7 @@ func (b *Builder) Run(ctx context.Context, ui packersdk.Ui, hook packersdk.Hook) SourceImageId: b.config.SourceImageId, InstanceName: b.config.InstanceName, BootDiskType: b.config.BootDiskType, + BootDiskSize: b.config.BootDiskSize, UsePrivateIp: b.config.UseSSHPrivateIp, EipBandwidth: b.config.EipBandwidth, EipChargeMode: b.config.EipChargeMode, diff --git a/builder/ucloud/uhost/builder.hcl2spec.go b/builder/ucloud/uhost/builder.hcl2spec.go index 2822bb3..8c44055 100644 --- a/builder/ucloud/uhost/builder.hcl2spec.go +++ b/builder/ucloud/uhost/builder.hcl2spec.go @@ -35,6 +35,7 @@ type FlatConfig struct { 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"` BootDiskType *string `mapstructure:"boot_disk_type" required:"false" cty:"boot_disk_type" hcl:"boot_disk_type"` + BootDiskSize *int `mapstructure:"boot_disk_size" required:"false" cty:"boot_disk_size" hcl:"boot_disk_size"` VPCId *string `mapstructure:"vpc_id" required:"false" cty:"vpc_id" hcl:"vpc_id"` SubnetId *string `mapstructure:"subnet_id" required:"false" cty:"subnet_id" hcl:"subnet_id"` SecurityGroupId *string `mapstructure:"security_group_id" required:"false" cty:"security_group_id" hcl:"security_group_id"` @@ -131,6 +132,7 @@ func (*FlatConfig) HCL2Spec() map[string]hcldec.Spec { "instance_type": &hcldec.AttrSpec{Name: "instance_type", Type: cty.String, Required: false}, "instance_name": &hcldec.AttrSpec{Name: "instance_name", Type: cty.String, Required: false}, "boot_disk_type": &hcldec.AttrSpec{Name: "boot_disk_type", Type: cty.String, Required: false}, + "boot_disk_size": &hcldec.AttrSpec{Name: "boot_disk_size", Type: cty.Number, Required: false}, "vpc_id": &hcldec.AttrSpec{Name: "vpc_id", Type: cty.String, Required: false}, "subnet_id": &hcldec.AttrSpec{Name: "subnet_id", Type: cty.String, Required: false}, "security_group_id": &hcldec.AttrSpec{Name: "security_group_id", Type: cty.String, Required: false}, diff --git a/builder/ucloud/uhost/step_check_source_image.go b/builder/ucloud/uhost/step_check_source_image.go index e5b26f9..09a419f 100644 --- a/builder/ucloud/uhost/step_check_source_image.go +++ b/builder/ucloud/uhost/step_check_source_image.go @@ -3,6 +3,7 @@ package uhost import ( "context" "fmt" + "github.com/ucloud/ucloud-sdk-go/services/uhost" "github.com/hashicorp/packer-plugin-sdk/multistep" packersdk "github.com/hashicorp/packer-plugin-sdk/packer" @@ -22,9 +23,21 @@ func (s *stepCheckSourceImageId) Run(ctx context.Context, state multistep.StateB imageSet, err := client.DescribeImageById(s.SourceUHostImageId) if err != nil { if ucloudcommon.IsNotFoundError(err) { - return ucloudcommon.Halt(state, err, "") + uk8sNodeImage, uk8sErr := client.DescribeUK8sNodeImageById(s.SourceUHostImageId) + if ucloudcommon.IsNotFoundError(uk8sErr) { + return ucloudcommon.Halt(state, fmt.Errorf("fail to find source_image_id %q", s.SourceUHostImageId), "") + } + if uk8sErr != nil { + return ucloudcommon.Halt(state, uk8sErr, fmt.Sprintf("Error on querying specified source_image_id %q", s.SourceUHostImageId)) + } + imageSet = &uhost.UHostImageSet{} + imageSet.ImageName = uk8sNodeImage.ImageName + imageSet.ImageSize = ucloudcommon.UK8sImageSize + imageSet.OsType = ucloudcommon.UK8sImageOsType + imageSet.Features = []string{"CloudInit"} + } else { + return ucloudcommon.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 == ucloudcommon.OsTypeWindows { diff --git a/builder/ucloud/uhost/step_create_instance.go b/builder/ucloud/uhost/step_create_instance.go index c0a01b4..3e56479 100644 --- a/builder/ucloud/uhost/step_create_instance.go +++ b/builder/ucloud/uhost/step_create_instance.go @@ -3,6 +3,7 @@ package uhost import ( "context" "encoding/base64" + "errors" "fmt" "io/ioutil" "math/rand" @@ -23,6 +24,7 @@ type stepCreateInstance struct { InstanceType string InstanceName string BootDiskType string + BootDiskSize int SourceImageId string UsePrivateIp bool @@ -281,6 +283,12 @@ func (s *stepCreateInstance) buildCreateInstanceRequest(state multistep.StateBag bootDisk := uhost.UHostDisk{} bootDisk.IsBoot = ucloud.String("true") bootDisk.Size = ucloud.Int(srcImage.ImageSize) + if s.BootDiskSize > 0 { + if s.BootDiskSize < srcImage.ImageSize { + return nil, errors.New("boot disk size should not be smaller than image size") + } + bootDisk.Size = ucloud.Int(s.BootDiskSize) + } bootDisk.Type = ucloud.String(ucloudcommon.BootDiskTypeMap.Convert(s.BootDiskType)) req.Disks = append(req.Disks, bootDisk) diff --git a/docs-partials/builder/ucloud/common/RunConfig-not-required.mdx b/docs-partials/builder/ucloud/common/RunConfig-not-required.mdx index e548718..b1bdc37 100644 --- a/docs-partials/builder/ucloud/common/RunConfig-not-required.mdx +++ b/docs-partials/builder/ucloud/common/RunConfig-not-required.mdx @@ -10,6 +10,9 @@ ~> **Note:** It takes around 10 mins for boot disk initialization when `boot_disk_type` is `local_normal` or `local_ssd`. +- `boot_disk_size` (int) - The size of boot disk associated to UHost instance, which cannot be smaller than the size of source image. + The unit is `GB`. Default value is the size of source image. + - `vpc_id` (string) - The ID of VPC linked to the UHost instance. If not defined `vpc_id`, the instance will use the default VPC in the current region. - `subnet_id` (string) - The ID of subnet under the VPC. If `vpc_id` is defined, the `subnet_id` is mandatory required.