From bd056e065d4e872358ed784c1f370f379a0d117c Mon Sep 17 00:00:00 2001 From: arunma Date: Mon, 21 Jul 2025 11:23:19 +0800 Subject: [PATCH 1/2] feat: Support organization account and other accounts sharing --- .web-docs/components/builder/cvm/README.md | 11 +++ builder/tencentcloud/cvm/access_config.go | 43 +++++--- builder/tencentcloud/cvm/builder.go | 18 +++- builder/tencentcloud/cvm/builder.hcl2spec.go | 6 ++ builder/tencentcloud/cvm/client.go | 25 +++++ builder/tencentcloud/cvm/common.go | 31 ++++++ builder/tencentcloud/cvm/image_config.go | 8 ++ builder/tencentcloud/cvm/step_create_image.go | 1 + builder/tencentcloud/cvm/step_share_image.go | 98 ++++++++++++++++++- .../tencentcloud/image/data.hcl2spec.go | 2 + .../TencentCloudAccessConfig-not-required.mdx | 3 + .../TencentCloudImageConfig-not-required.mdx | 8 ++ go.mod | 4 +- go.sum | 6 ++ 14 files changed, 239 insertions(+), 25 deletions(-) diff --git a/.web-docs/components/builder/cvm/README.md b/.web-docs/components/builder/cvm/README.md index c7f60fdd..e0a7ff14 100644 --- a/.web-docs/components/builder/cvm/README.md +++ b/.web-docs/components/builder/cvm/README.md @@ -62,6 +62,9 @@ a [communicator](/packer/docs/templates/legacy_json_templates/communicator) can - `tag_endpoint` (string) - The endpoint you want to reach the cloud endpoint, if tce cloud you should set a tce tag endpoint. +- `org_endpoint` (string) - The endpoint you want to reach the cloud endpoint, + if tce cloud you should set a tce organization endpoint. + - `security_token` (string) - STS access token, can be set through template or by exporting as environment variable such as `export TENCENTCLOUD_SECURITY_TOKEN=value`. @@ -108,6 +111,14 @@ a [communicator](/packer/docs/templates/legacy_json_templates/communicator) can - `skip_create_image` (bool) - Skip creating an image. When set to true, you don't need to enter target image information, share, copy, etc. The default value is false. +- `is_share_org_members` (bool) - After creating the image, + whether to share it with other accounts in the organization + where the current account is located. + The image can be copied to a maximum of 50 accounts, + with ImageShareAccounts being the priority. + +- `image_family` (string) - Image family. Example value: business-daily-update. + diff --git a/builder/tencentcloud/cvm/access_config.go b/builder/tencentcloud/cvm/access_config.go index cecf8595..f5992696 100644 --- a/builder/tencentcloud/cvm/access_config.go +++ b/builder/tencentcloud/cvm/access_config.go @@ -12,9 +12,6 @@ import ( "strconv" "github.com/hashicorp/packer-plugin-sdk/template/interpolate" - cvm "github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/cvm/v20170312" - tag "github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/tag/v20180813" - vpc "github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/vpc/v20170312" ) const ( @@ -85,6 +82,9 @@ type TencentCloudAccessConfig struct { // The endpoint you want to reach the cloud endpoint, // if tce cloud you should set a tce tag endpoint. TagEndpoint string `mapstructure:"tag_endpoint" required:"false"` + // The endpoint you want to reach the cloud endpoint, + // if tce cloud you should set a tce organization endpoint. + OrgEndpoint string `mapstructure:"org_endpoint" required:"false"` // The region validation can be skipped if this value is true, the default // value is false. skipValidation bool @@ -125,31 +125,42 @@ type TencentCloudAccessRole struct { SessionDuration int `mapstructure:"session_duration" required:"false"` } -func (cf *TencentCloudAccessConfig) Client() (*cvm.Client, *vpc.Client, *tag.Client, error) { +func (cf *TencentCloudAccessConfig) Client() (map[string]interface{}, error) { var ( - err error - cvm_client *cvm.Client - vpc_client *vpc.Client - tag_client *tag.Client + err error + // cvm_client *cvm.Client + // vpc_client *vpc.Client + // tag_client *tag.Client + // org_client *org.Client + // cam_client *cam.Client ) if err = cf.validateRegion(); err != nil { - return nil, nil, nil, err + return nil, err + } + + clientMap := map[string]interface{}{} + if clientMap["cvm_client"], err = NewCvmClient(cf); err != nil { + return nil, err + } + + if clientMap["vpc_client"], err = NewVpcClient(cf); err != nil { + return nil, err } - if cvm_client, err = NewCvmClient(cf); err != nil { - return nil, nil, nil, err + if clientMap["tag_client"], err = NewTagClient(cf); err != nil { + return nil, err } - if vpc_client, err = NewVpcClient(cf); err != nil { - return nil, nil, nil, err + if clientMap["org_client"], err = NewOrgClient(cf); err != nil { + return nil, err } - if tag_client, err = NewTagClient(cf); err != nil { - return nil, nil, nil, err + if clientMap["cam_client"], err = NewCamClient(cf); err != nil { + return nil, err } - return cvm_client, vpc_client, tag_client, nil + return clientMap, nil } func (cf *TencentCloudAccessConfig) Prepare(ctx *interpolate.Context) []error { diff --git a/builder/tencentcloud/cvm/builder.go b/builder/tencentcloud/cvm/builder.go index 6718d3ee..d814e8fb 100644 --- a/builder/tencentcloud/cvm/builder.go +++ b/builder/tencentcloud/cvm/builder.go @@ -17,6 +17,11 @@ import ( packersdk "github.com/hashicorp/packer-plugin-sdk/packer" "github.com/hashicorp/packer-plugin-sdk/template/config" "github.com/hashicorp/packer-plugin-sdk/template/interpolate" + cam "github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/cam/v20190116" + vm "github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/cvm/v20170312" + org "github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/organization/v20210331" + tag "github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/tag/v20180813" + vpc "github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/vpc/v20170312" ) const BuilderId = "tencent.cloud" @@ -75,16 +80,18 @@ func (b *Builder) Prepare(raws ...interface{}) ([]string, []string, error) { } func (b *Builder) Run(ctx context.Context, ui packersdk.Ui, hook packersdk.Hook) (packersdk.Artifact, error) { - cvmClient, vpcClient, tagClient, err := b.config.Client() + clientMap, err := b.config.Client() if err != nil { return nil, err } state := new(multistep.BasicStateBag) state.Put("config", &b.config) - state.Put("cvm_client", cvmClient) - state.Put("vpc_client", vpcClient) - state.Put("tag_client", tagClient) + state.Put("cvm_client", clientMap["cvm_client"].(*vm.Client)) + state.Put("vpc_client", clientMap["vpc_client"].(*vpc.Client)) + state.Put("tag_client", clientMap["tag_client"].(*tag.Client)) + state.Put("org_client", clientMap["org_client"].(*org.Client)) + state.Put("cam_client", clientMap["cam_client"].(*cam.Client)) state.Put("hook", hook) state.Put("ui", ui) @@ -155,6 +162,7 @@ func (b *Builder) Run(ctx context.Context, ui packersdk.Ui, hook packersdk.Hook) }, &stepShareImage{ b.config.ImageShareAccounts, + b.config.IsShareOrgMembers, }, &stepCopyImage{ DestinationRegions: b.config.ImageCopyRegions, @@ -177,7 +185,7 @@ func (b *Builder) Run(ctx context.Context, ui packersdk.Ui, hook packersdk.Hook) artifact := &Artifact{ TencentCloudImages: state.Get("tencentcloudimages").(map[string]string), BuilderIdValue: BuilderId, - Client: cvmClient, + Client: clientMap["cvm_client"].(*vm.Client), StateData: map[string]interface{}{"generated_data": state.Get("generated_data")}, } diff --git a/builder/tencentcloud/cvm/builder.hcl2spec.go b/builder/tencentcloud/cvm/builder.hcl2spec.go index 976a1d62..ba1cd00c 100644 --- a/builder/tencentcloud/cvm/builder.hcl2spec.go +++ b/builder/tencentcloud/cvm/builder.hcl2spec.go @@ -25,6 +25,7 @@ type FlatConfig struct { CvmEndpoint *string `mapstructure:"cvm_endpoint" required:"false" cty:"cvm_endpoint" hcl:"cvm_endpoint"` VpcEndpoint *string `mapstructure:"vpc_endpoint" required:"false" cty:"vpc_endpoint" hcl:"vpc_endpoint"` TagEndpoint *string `mapstructure:"tag_endpoint" required:"false" cty:"tag_endpoint" hcl:"tag_endpoint"` + OrgEndpoint *string `mapstructure:"org_endpoint" required:"false" cty:"org_endpoint" hcl:"org_endpoint"` SecurityToken *string `mapstructure:"security_token" required:"false" cty:"security_token" hcl:"security_token"` AssumeRole *FlatTencentCloudAccessRole `mapstructure:"assume_role" required:"false" cty:"assume_role" hcl:"assume_role"` Profile *string `mapstructure:"profile" required:"false" cty:"profile" hcl:"profile"` @@ -38,6 +39,8 @@ type FlatConfig struct { ImageTags map[string]string `mapstructure:"image_tags" required:"false" cty:"image_tags" hcl:"image_tags"` SnapshotTags map[string]string `mapstructure:"snapshot_tags" required:"false" cty:"snapshot_tags" hcl:"snapshot_tags"` SkipCreateImage *bool `mapstructure:"skip_create_image" required:"false" cty:"skip_create_image" hcl:"skip_create_image"` + IsShareOrgMembers *bool `mapstructure:"is_share_org_members" required:"false" cty:"is_share_org_members" hcl:"is_share_org_members"` + ImageFamily *string `mapstructure:"image_family" required:"false" cty:"image_family" hcl:"image_family"` 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:"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"` @@ -145,6 +148,7 @@ func (*FlatConfig) HCL2Spec() map[string]hcldec.Spec { "cvm_endpoint": &hcldec.AttrSpec{Name: "cvm_endpoint", Type: cty.String, Required: false}, "vpc_endpoint": &hcldec.AttrSpec{Name: "vpc_endpoint", Type: cty.String, Required: false}, "tag_endpoint": &hcldec.AttrSpec{Name: "tag_endpoint", Type: cty.String, Required: false}, + "org_endpoint": &hcldec.AttrSpec{Name: "org_endpoint", Type: cty.String, Required: false}, "security_token": &hcldec.AttrSpec{Name: "security_token", Type: cty.String, Required: false}, "assume_role": &hcldec.BlockSpec{TypeName: "assume_role", Nested: hcldec.ObjectSpec((*FlatTencentCloudAccessRole)(nil).HCL2Spec())}, "profile": &hcldec.AttrSpec{Name: "profile", Type: cty.String, Required: false}, @@ -158,6 +162,8 @@ func (*FlatConfig) HCL2Spec() map[string]hcldec.Spec { "image_tags": &hcldec.AttrSpec{Name: "image_tags", Type: cty.Map(cty.String), Required: false}, "snapshot_tags": &hcldec.AttrSpec{Name: "snapshot_tags", Type: cty.Map(cty.String), Required: false}, "skip_create_image": &hcldec.AttrSpec{Name: "skip_create_image", Type: cty.Bool, Required: false}, + "is_share_org_members": &hcldec.AttrSpec{Name: "is_share_org_members", Type: cty.Bool, Required: false}, + "image_family": &hcldec.AttrSpec{Name: "image_family", Type: 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}, diff --git a/builder/tencentcloud/cvm/client.go b/builder/tencentcloud/cvm/client.go index 1d83edcc..f738cf29 100644 --- a/builder/tencentcloud/cvm/client.go +++ b/builder/tencentcloud/cvm/client.go @@ -4,9 +4,11 @@ package cvm import ( + cam "github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/cam/v20190116" "github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/common" "github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/common/profile" cvm "github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/cvm/v20170312" + org "github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/organization/v20210331" sts "github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/sts/v20180813" tag "github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/tag/v20180813" vpc "github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/vpc/v20170312" @@ -22,6 +24,8 @@ type TencentCloudClient struct { cvmConn *cvm.Client stsConn *sts.Client tagConn *tag.Client + orgConn *org.Client + camConn *cam.Client } func (me *TencentCloudClient) UseVpcClient(cpf *profile.ClientProfile) *vpc.Client { @@ -65,3 +69,24 @@ func (me *TencentCloudClient) UseTagClient(cpf *profile.ClientProfile) *tag.Clie return me.tagConn } + +func (me *TencentCloudClient) UseOrgClient(cpf *profile.ClientProfile) *org.Client { + if me.orgConn != nil { + return me.orgConn + } + + me.orgConn, _ = org.NewClient(me.Credential, me.Region, cpf) + + return me.orgConn +} + +func (me *TencentCloudClient) UseCamClient() *cam.Client { + if me.camConn != nil { + return me.camConn + } + + cpf := me.ClientProfile + me.camConn, _ = cam.NewClient(me.Credential, me.Region, cpf) + + return me.camConn +} diff --git a/builder/tencentcloud/cvm/common.go b/builder/tencentcloud/cvm/common.go index ff514abf..adda19c1 100644 --- a/builder/tencentcloud/cvm/common.go +++ b/builder/tencentcloud/cvm/common.go @@ -14,10 +14,12 @@ import ( "github.com/hashicorp/packer-plugin-sdk/multistep" packersdk "github.com/hashicorp/packer-plugin-sdk/packer" "github.com/hashicorp/packer-plugin-sdk/retry" + cam "github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/cam/v20190116" "github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/common" "github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/common/errors" "github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/common/profile" cvm "github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/cvm/v20170312" + org "github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/organization/v20210331" sts "github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/sts/v20180813" tag "github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/tag/v20180813" vpc "github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/vpc/v20170312" @@ -181,6 +183,35 @@ func NewTagClient(cf *TencentCloudAccessConfig) (client *tag.Client, err error) return } +// NewVpcClient returns a new organization client +func NewOrgClient(cf *TencentCloudAccessConfig) (client *org.Client, err error) { + apiV3Conn, err := packerConfigClient(cf) + if err != nil { + return nil, err + } + + orgClientProfile, err := newClientProfile(cf.OrgEndpoint) + if err != nil { + return nil, err + } + + client = apiV3Conn.UseOrgClient(orgClientProfile) + + return +} + +// NewCamClient returns a new cam client +func NewCamClient(cf *TencentCloudAccessConfig) (client *cam.Client, err error) { + apiV3Conn, err := packerConfigClient(cf) + if err != nil { + return nil, err + } + + client = apiV3Conn.UseCamClient() + + return +} + // CheckResourceIdFormat check resource id format func CheckResourceIdFormat(resource string, id string) bool { regex := regexp.MustCompile(fmt.Sprintf("%s-[0-9a-z]{8}$", resource)) diff --git a/builder/tencentcloud/cvm/image_config.go b/builder/tencentcloud/cvm/image_config.go index 75a948d9..63a9b148 100644 --- a/builder/tencentcloud/cvm/image_config.go +++ b/builder/tencentcloud/cvm/image_config.go @@ -37,6 +37,14 @@ type TencentCloudImageConfig struct { skipValidation bool // Skip creating an image. When set to true, you don't need to enter target image information, share, copy, etc. The default value is false. SkipCreateImage bool `mapstructure:"skip_create_image" required:"false"` + // After creating the image, + // whether to share it with other accounts in the organization + // where the current account is located. + // The image can be copied to a maximum of 50 accounts, + // with ImageShareAccounts being the priority. + IsShareOrgMembers bool `mapstructure:"is_share_org_members" required:"false"` + // Image family. Example value: business-daily-update. + ImageFamily string `mapstructure:"image_family" required:"false"` } func (cf *TencentCloudImageConfig) Prepare(ctx *interpolate.Context) []error { diff --git a/builder/tencentcloud/cvm/step_create_image.go b/builder/tencentcloud/cvm/step_create_image.go index 3fd164aa..bb823404 100644 --- a/builder/tencentcloud/cvm/step_create_image.go +++ b/builder/tencentcloud/cvm/step_create_image.go @@ -35,6 +35,7 @@ func (s *stepCreateImage) Run(ctx context.Context, state multistep.StateBag) mul req := cvm.NewCreateImageRequest() req.ImageName = &config.ImageName req.ImageDescription = &config.ImageDescription + req.ImageFamily = &config.ImageFamily req.InstanceId = instance.InstanceId // TODO: We should allow user to specify which data disk should be diff --git a/builder/tencentcloud/cvm/step_share_image.go b/builder/tencentcloud/cvm/step_share_image.go index 821555bf..e4f8350e 100644 --- a/builder/tencentcloud/cvm/step_share_image.go +++ b/builder/tencentcloud/cvm/step_share_image.go @@ -6,19 +6,23 @@ package cvm import ( "context" "fmt" + "strconv" "strings" "github.com/hashicorp/packer-plugin-sdk/multistep" + cam "github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/cam/v20190116" "github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/common" cvm "github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/cvm/v20170312" + organization "github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/organization/v20210331" ) type stepShareImage struct { - ShareAccounts []string + ShareAccounts []string + IsShareOrgMembers bool } func (s *stepShareImage) Run(ctx context.Context, state multistep.StateBag) multistep.StepAction { - if len(s.ShareAccounts) == 0 { + if len(s.ShareAccounts) == 0 && !s.IsShareOrgMembers { return multistep.ActionContinue } @@ -30,10 +34,23 @@ func (s *stepShareImage) Run(ctx context.Context, state multistep.StateBag) mult req := cvm.NewModifyImageSharePermissionRequest() req.ImageId = imageId req.Permission = common.StringPtr("SHARE") - accounts := make([]*string, 0, len(s.ShareAccounts)) + accounts := []*string{} for _, account := range s.ShareAccounts { accounts = append(accounts, common.StringPtr(account)) } + + if s.IsShareOrgMembers { + accountList, err := s.getOrgAccounts(ctx, state) + if err != nil { + return Halt(state, err, "Failed to get org accounts") + } + accounts = append(accounts, accountList...) + } + + if len(accounts) == 0 { + return multistep.ActionContinue + } + req.AccountIds = accounts err := Retry(ctx, func(ctx context.Context) error { _, e := client.ModifyImageSharePermission(req) @@ -48,6 +65,81 @@ func (s *stepShareImage) Run(ctx context.Context, state multistep.StateBag) mult return multistep.ActionContinue } +func (s *stepShareImage) getOrgAccounts(ctx context.Context, state multistep.StateBag) ([]*string, error) { + + currentAccount, err := s.getUserId(ctx, state) + if err != nil { + return nil, err + } + + req := organization.NewDescribeOrganizationMembersRequest() + resp := organization.NewDescribeOrganizationMembersResponse() + + var limit uint64 = 50 + var offset uint64 = 0 + + req.Limit = &limit + req.Offset = &offset + + accounts := []*string{} + for { + client := state.Get("org_client").(*organization.Client) + err := Retry(ctx, func(ctx context.Context) error { + var e error + resp, e = client.DescribeOrganizationMembers(req) + return e + }) + if err != nil { + return nil, nil + } + if resp.Response == nil { + return nil, nil + } + items := resp.Response.Items + for _, v := range items { + if v.MemberUin != nil { + if strconv.FormatInt(*v.MemberUin, 10) == currentAccount { + continue + } + accounts = append(accounts, common.StringPtr(strconv.Itoa(int(*v.MemberUin)))) + } + } + + if len(items) < int(limit) { + break + } + + offset += limit + } + + return accounts, nil +} + +func (s *stepShareImage) getUserId(ctx context.Context, state multistep.StateBag) (string, error) { + req := cam.NewGetUserAppIdRequest() + resp := cam.NewGetUserAppIdResponse() + + client := state.Get("cam_client").(*cam.Client) + err := Retry(ctx, func(ctx context.Context) error { + var e error + resp, e = client.GetUserAppId(req) + return e + }) + if err != nil { + return "", err + } + + if resp.Response == nil { + return "", nil + } + + if resp.Response.Uin != nil { + return *resp.Response.Uin, nil + } + + return "", nil +} + func (s *stepShareImage) Cleanup(state multistep.StateBag) { _, cancelled := state.GetOk(multistep.StateCancelled) _, halted := state.GetOk(multistep.StateHalted) diff --git a/datasource/tencentcloud/image/data.hcl2spec.go b/datasource/tencentcloud/image/data.hcl2spec.go index 7327099a..f870f0de 100644 --- a/datasource/tencentcloud/image/data.hcl2spec.go +++ b/datasource/tencentcloud/image/data.hcl2spec.go @@ -25,6 +25,7 @@ type FlatConfig struct { CvmEndpoint *string `mapstructure:"cvm_endpoint" required:"false" cty:"cvm_endpoint" hcl:"cvm_endpoint"` VpcEndpoint *string `mapstructure:"vpc_endpoint" required:"false" cty:"vpc_endpoint" hcl:"vpc_endpoint"` TagEndpoint *string `mapstructure:"tag_endpoint" required:"false" cty:"tag_endpoint" hcl:"tag_endpoint"` + OrgEndpoint *string `mapstructure:"org_endpoint" required:"false" cty:"org_endpoint" hcl:"org_endpoint"` SecurityToken *string `mapstructure:"security_token" required:"false" cty:"security_token" hcl:"security_token"` AssumeRole *cvm.FlatTencentCloudAccessRole `mapstructure:"assume_role" required:"false" cty:"assume_role" hcl:"assume_role"` Profile *string `mapstructure:"profile" required:"false" cty:"profile" hcl:"profile"` @@ -60,6 +61,7 @@ func (*FlatConfig) HCL2Spec() map[string]hcldec.Spec { "cvm_endpoint": &hcldec.AttrSpec{Name: "cvm_endpoint", Type: cty.String, Required: false}, "vpc_endpoint": &hcldec.AttrSpec{Name: "vpc_endpoint", Type: cty.String, Required: false}, "tag_endpoint": &hcldec.AttrSpec{Name: "tag_endpoint", Type: cty.String, Required: false}, + "org_endpoint": &hcldec.AttrSpec{Name: "org_endpoint", Type: cty.String, Required: false}, "security_token": &hcldec.AttrSpec{Name: "security_token", Type: cty.String, Required: false}, "assume_role": &hcldec.BlockSpec{TypeName: "assume_role", Nested: hcldec.ObjectSpec((*cvm.FlatTencentCloudAccessRole)(nil).HCL2Spec())}, "profile": &hcldec.AttrSpec{Name: "profile", Type: cty.String, Required: false}, diff --git a/docs-partials/builder/tencentcloud/cvm/TencentCloudAccessConfig-not-required.mdx b/docs-partials/builder/tencentcloud/cvm/TencentCloudAccessConfig-not-required.mdx index 7bb930b5..8c15fe1d 100644 --- a/docs-partials/builder/tencentcloud/cvm/TencentCloudAccessConfig-not-required.mdx +++ b/docs-partials/builder/tencentcloud/cvm/TencentCloudAccessConfig-not-required.mdx @@ -9,6 +9,9 @@ - `tag_endpoint` (string) - The endpoint you want to reach the cloud endpoint, if tce cloud you should set a tce tag endpoint. +- `org_endpoint` (string) - The endpoint you want to reach the cloud endpoint, + if tce cloud you should set a tce organization endpoint. + - `security_token` (string) - STS access token, can be set through template or by exporting as environment variable such as `export TENCENTCLOUD_SECURITY_TOKEN=value`. diff --git a/docs-partials/builder/tencentcloud/cvm/TencentCloudImageConfig-not-required.mdx b/docs-partials/builder/tencentcloud/cvm/TencentCloudImageConfig-not-required.mdx index 21a382cf..8859424a 100644 --- a/docs-partials/builder/tencentcloud/cvm/TencentCloudImageConfig-not-required.mdx +++ b/docs-partials/builder/tencentcloud/cvm/TencentCloudImageConfig-not-required.mdx @@ -19,4 +19,12 @@ - `skip_create_image` (bool) - Skip creating an image. When set to true, you don't need to enter target image information, share, copy, etc. The default value is false. +- `is_share_org_members` (bool) - After creating the image, + whether to share it with other accounts in the organization + where the current account is located. + The image can be copied to a maximum of 50 accounts, + with ImageShareAccounts being the priority. + +- `image_family` (string) - Image family. Example value: business-daily-update. + diff --git a/go.mod b/go.mod index 6c5fad98..ca56c5d5 100644 --- a/go.mod +++ b/go.mod @@ -6,7 +6,7 @@ require ( github.com/hashicorp/hcl/v2 v2.19.1 github.com/hashicorp/packer-plugin-sdk v0.5.2 github.com/pkg/errors v0.9.1 - github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/common v1.0.1175 + github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/common v1.0.1200 github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/cvm v1.0.1072 github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/sts v1.0.797 github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/tag v1.0.1175 @@ -16,6 +16,8 @@ require ( require ( github.com/niemeyer/pretty v0.0.0-20200227124842-a10e7caefd8e // indirect + github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/cam v1.0.1200 // indirect + github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/organization v1.0.1200 // indirect gopkg.in/check.v1 v1.0.0-20200227125254-8fa46927fb4f // indirect ) diff --git a/go.sum b/go.sum index 104dac73..f9e0ff20 100644 --- a/go.sum +++ b/go.sum @@ -306,12 +306,18 @@ github.com/stretchr/testify v1.6.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/ github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= github.com/stretchr/testify v1.7.2/go.mod h1:R6va5+xMeoiuVRoj+gSkQ7d3FALtqAAGI1FQKckRals= github.com/stretchr/testify v1.8.3 h1:RP3t2pwF7cMEbC1dqtB6poj3niw/9gnV4Cjg5oW5gtY= +github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/cam v1.0.1200 h1:vONBPPPZR83iIJGnrIBjIrFj1Lba8p3tBmwmveabLlo= +github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/cam v1.0.1200/go.mod h1:g1HW2Y5P+yi9XH2dL136gEMKogKcNRLoZ4hq9767D48= github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/common v1.0.797/go.mod h1:r5r4xbfxSaeR04b166HGsBa/R4U3SueirEUpXGuw+Q0= github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/common v1.0.1072/go.mod h1:r5r4xbfxSaeR04b166HGsBa/R4U3SueirEUpXGuw+Q0= github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/common v1.0.1175 h1:w0z4dtrinCY3R4aHnw9vcq80XWEIEKXv6c3p779ueRo= github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/common v1.0.1175/go.mod h1:r5r4xbfxSaeR04b166HGsBa/R4U3SueirEUpXGuw+Q0= +github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/common v1.0.1200 h1:n6elge0PuoOtHt67BhlQka5Y7ChPbCtp23zYDFw56V0= +github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/common v1.0.1200/go.mod h1:r5r4xbfxSaeR04b166HGsBa/R4U3SueirEUpXGuw+Q0= github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/cvm v1.0.1072 h1:BO6eEqw2CxeP73AnOfkq99mJAPccP+w3exmVuBDMvAc= github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/cvm v1.0.1072/go.mod h1:Ot4h9BuqIbyOPotq8cIT3vCCMDdn6LXkc37jU2teHnQ= +github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/organization v1.0.1200 h1:hYOvCfgPKpH2OS6+6ZOT+h21CfduIbGfz7RE+Ey1H14= +github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/organization v1.0.1200/go.mod h1:qYzdOsPWtOJ18uQ/4QupBTF98ariELEH4dx93GiBeuY= github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/sts v1.0.797 h1:Z9rTZBoR4arEXA9gYLu8AQnMInG1scb+WnlIWczLH2A= github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/sts v1.0.797/go.mod h1:IugQh1ZI86ZeEUBYf+u/REwTeKZcneP449FPU8BbLxA= github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/tag v1.0.1175 h1:Yw7azOzlQqh6/Zyk5JCLH69LJ7nE2jkilGXU+3vIqUM= From c916d99e108cd1fcc0a53a8f6d5267c88dcede99 Mon Sep 17 00:00:00 2001 From: arunma Date: Mon, 21 Jul 2025 11:26:53 +0800 Subject: [PATCH 2/2] fix: modify get client --- datasource/tencentcloud/image/data.go | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/datasource/tencentcloud/image/data.go b/datasource/tencentcloud/image/data.go index d096cc2e..bdec647c 100644 --- a/datasource/tencentcloud/image/data.go +++ b/datasource/tencentcloud/image/data.go @@ -105,11 +105,13 @@ func (d *Datasource) Execute() (cty.Value, error) { } func (d *Datasource) ResolveImageByFilters() (*cvm.Image, error) { - client, _, _, err := d.config.Client() + clientMap, err := d.config.Client() if err != nil { return nil, err } + cvmClient := clientMap["cvm_client"].(*cvm.Client) + req := cvm.NewDescribeImagesRequest() var filters []*cvm.Filter @@ -127,7 +129,7 @@ func (d *Datasource) ResolveImageByFilters() (*cvm.Image, error) { var resp *cvm.DescribeImagesResponse err = buildCvm.Retry(ctx, func(ctx context.Context) error { var e error - resp, e = client.DescribeImages(req) + resp, e = cvmClient.DescribeImages(req) return e }) if err != nil { @@ -150,11 +152,13 @@ func (d *Datasource) ResolveImageByFilters() (*cvm.Image, error) { } func (d *Datasource) ResolveImageByImageFamily() (*cvm.Image, error) { - client, _, _, err := d.config.Client() + clientMap, err := d.config.Client() if err != nil { return nil, err } + cvmClient := clientMap["cvm_client"].(*cvm.Client) + var resp *cvm.DescribeImageFromFamilyResponse req := cvm.NewDescribeImageFromFamilyRequest() req.ImageFamily = &d.config.ImageFamily @@ -162,7 +166,7 @@ func (d *Datasource) ResolveImageByImageFamily() (*cvm.Image, error) { ctx := context.TODO() err = buildCvm.Retry(ctx, func(ctx context.Context) error { var e error - resp, e = client.DescribeImageFromFamily(req) + resp, e = cvmClient.DescribeImageFromFamily(req) return e }) pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy