Skip to content

Commit 4ac0ea4

Browse files
author
mikatong
committed
support snapshot tags
1 parent 70dcdf2 commit 4ac0ea4

File tree

14 files changed

+123
-15
lines changed

14 files changed

+123
-15
lines changed

.web-docs/components/builder/cvm/README.md

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -59,6 +59,9 @@ a [communicator](/packer/docs/templates/legacy_json_templates/communicator) can
5959
- `vpc_endpoint` (string) - The endpoint you want to reach the cloud endpoint,
6060
if tce cloud you should set a tce vpc endpoint.
6161

62+
- `tag_endpoint` (string) - The endpoint you want to reach the cloud endpoint,
63+
if tce cloud you should set a tce tag endpoint.
64+
6265
- `security_token` (string) - STS access token, can be set through template or by exporting
6366
as environment variable such as `export TENCENTCLOUD_SECURITY_TOKEN=value`.
6467

@@ -101,6 +104,8 @@ a [communicator](/packer/docs/templates/legacy_json_templates/communicator) can
101104

102105
- `image_tags` (map[string]string) - Key/value pair tags that will be applied to the resulting image.
103106

107+
- `snapshot_tags` (map[string]string) - Snapshot Tags
108+
104109
- `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.
105110

106111
<!-- End of code generated from the comments of the TencentCloudImageConfig struct in builder/tencentcloud/cvm/image_config.go; -->

builder/tencentcloud/cvm/access_config.go

Lines changed: 16 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@ import (
1313

1414
"github.com/hashicorp/packer-plugin-sdk/template/interpolate"
1515
cvm "github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/cvm/v20170312"
16+
tag "github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/tag/v20180813"
1617
vpc "github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/vpc/v20170312"
1718
)
1819

@@ -81,6 +82,9 @@ type TencentCloudAccessConfig struct {
8182
// The endpoint you want to reach the cloud endpoint,
8283
// if tce cloud you should set a tce vpc endpoint.
8384
VpcEndpoint string `mapstructure:"vpc_endpoint" required:"false"`
85+
// The endpoint you want to reach the cloud endpoint,
86+
// if tce cloud you should set a tce tag endpoint.
87+
TagEndpoint string `mapstructure:"tag_endpoint" required:"false"`
8488
// The region validation can be skipped if this value is true, the default
8589
// value is false.
8690
skipValidation bool
@@ -121,26 +125,31 @@ type TencentCloudAccessRole struct {
121125
SessionDuration int `mapstructure:"session_duration" required:"false"`
122126
}
123127

124-
func (cf *TencentCloudAccessConfig) Client() (*cvm.Client, *vpc.Client, error) {
128+
func (cf *TencentCloudAccessConfig) Client() (*cvm.Client, *vpc.Client, *tag.Client, error) {
125129
var (
126130
err error
127131
cvm_client *cvm.Client
128132
vpc_client *vpc.Client
133+
tag_client *tag.Client
129134
)
130135

131136
if err = cf.validateRegion(); err != nil {
132-
return nil, nil, err
137+
return nil, nil, nil, err
133138
}
134139

135140
if cvm_client, err = NewCvmClient(cf); err != nil {
136-
return nil, nil, err
141+
return nil, nil, nil, err
137142
}
138143

139144
if vpc_client, err = NewVpcClient(cf); err != nil {
140-
return nil, nil, err
145+
return nil, nil, nil, err
146+
}
147+
148+
if tag_client, err = NewTagClient(cf); err != nil {
149+
return nil, nil, nil, err
141150
}
142151

143-
return cvm_client, vpc_client, nil
152+
return cvm_client, vpc_client, tag_client, nil
144153
}
145154

146155
func (cf *TencentCloudAccessConfig) Prepare(ctx *interpolate.Context) []error {
@@ -150,9 +159,8 @@ func (cf *TencentCloudAccessConfig) Prepare(ctx *interpolate.Context) []error {
150159
errs = append(errs, err)
151160
}
152161

153-
if (cf.CvmEndpoint != "" && cf.VpcEndpoint == "") ||
154-
(cf.CvmEndpoint == "" && cf.VpcEndpoint != "") {
155-
errs = append(errs, fmt.Errorf("parameter cvm_endpoint and vpc_endpoint must be set simultaneously"))
162+
if cf.CvmEndpoint == "" || cf.VpcEndpoint == "" || cf.TagEndpoint == "" {
163+
errs = append(errs, fmt.Errorf("parameter cvm_endpoint, vpc_endpoint and tag_endpoint must be set simultaneously"))
156164
}
157165

158166
if cf.Region == "" {

builder/tencentcloud/cvm/builder.go

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -75,7 +75,7 @@ func (b *Builder) Prepare(raws ...interface{}) ([]string, []string, error) {
7575
}
7676

7777
func (b *Builder) Run(ctx context.Context, ui packersdk.Ui, hook packersdk.Hook) (packersdk.Artifact, error) {
78-
cvmClient, vpcClient, err := b.config.Client()
78+
cvmClient, vpcClient, tagClient, err := b.config.Client()
7979
if err != nil {
8080
return nil, err
8181
}
@@ -84,6 +84,7 @@ func (b *Builder) Run(ctx context.Context, ui packersdk.Ui, hook packersdk.Hook)
8484
state.Put("config", &b.config)
8585
state.Put("cvm_client", cvmClient)
8686
state.Put("vpc_client", vpcClient)
87+
state.Put("tag_client", tagClient)
8788
state.Put("hook", hook)
8889
state.Put("ui", ui)
8990

builder/tencentcloud/cvm/builder.hcl2spec.go

Lines changed: 4 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

builder/tencentcloud/cvm/client.go

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@ import (
88
"github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/common/profile"
99
cvm "github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/cvm/v20170312"
1010
sts "github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/sts/v20180813"
11+
tag "github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/tag/v20180813"
1112
vpc "github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/vpc/v20170312"
1213
)
1314

@@ -20,6 +21,7 @@ type TencentCloudClient struct {
2021
vpcConn *vpc.Client
2122
cvmConn *cvm.Client
2223
stsConn *sts.Client
24+
tagConn *tag.Client
2325
}
2426

2527
func (me *TencentCloudClient) UseVpcClient(cpf *profile.ClientProfile) *vpc.Client {
@@ -53,3 +55,13 @@ func (me *TencentCloudClient) UseStsClient() *sts.Client {
5355

5456
return me.stsConn
5557
}
58+
59+
func (me *TencentCloudClient) UseTagClient(cpf *profile.ClientProfile) *tag.Client {
60+
if me.tagConn != nil {
61+
return me.tagConn
62+
}
63+
64+
me.tagConn, _ = tag.NewClient(me.Credential, me.Region, cpf)
65+
66+
return me.tagConn
67+
}

builder/tencentcloud/cvm/common.go

Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@ import (
1919
"github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/common/profile"
2020
cvm "github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/cvm/v20170312"
2121
sts "github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/sts/v20180813"
22+
tag "github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/tag/v20180813"
2223
vpc "github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/vpc/v20170312"
2324
)
2425

@@ -78,6 +79,27 @@ func WaitForImageReady(ctx context.Context, client *cvm.Client, imageName string
7879
}
7980
}
8081

82+
func AddResourceTag(ctx context.Context, client *tag.Client, resourceName string, tags map[string]string) error {
83+
request := tag.NewModifyResourceTagsRequest()
84+
request.Resource = &resourceName
85+
request.ReplaceTags = make([]*tag.Tag, 0, len(tags))
86+
for k, v := range tags {
87+
key := k
88+
value := v
89+
replaceTag := &tag.Tag{
90+
TagKey: &key,
91+
TagValue: &value,
92+
}
93+
request.ReplaceTags = append(request.ReplaceTags, replaceTag)
94+
}
95+
96+
err := Retry(ctx, func(ctx context.Context) error {
97+
_, e := client.ModifyResourceTags(request)
98+
return e
99+
})
100+
return err
101+
}
102+
81103
// GetImageByName get image by image name
82104
func GetImageByName(ctx context.Context, client *cvm.Client, imageName string) (*cvm.Image, error) {
83105
req := cvm.NewDescribeImagesRequest()
@@ -143,6 +165,22 @@ func NewVpcClient(cf *TencentCloudAccessConfig) (client *vpc.Client, err error)
143165
return
144166
}
145167

168+
// UseTagClient returns a new tag client
169+
func NewTagClient(cf *TencentCloudAccessConfig) (client *tag.Client, err error) {
170+
apiV3Conn, err := packerConfigClient(cf)
171+
if err != nil {
172+
return nil, err
173+
}
174+
175+
tagClientProfile, err := newClientProfile(cf.TagEndpoint)
176+
if err != nil {
177+
return nil, err
178+
}
179+
client = apiV3Conn.UseTagClient(tagClientProfile)
180+
181+
return
182+
}
183+
146184
// CheckResourceIdFormat check resource id format
147185
func CheckResourceIdFormat(resource string, id string) bool {
148186
regex := regexp.MustCompile(fmt.Sprintf("%s-[0-9a-z]{8}$", resource))
@@ -322,3 +360,10 @@ func IntUint64(i int) *uint64 {
322360
u := uint64(i)
323361
return &u
324362
}
363+
364+
// BuildTagResourceName builds the Tencent Cloud specific name of a resource description.
365+
// The format is `qcs:project_id:service_type:region:account:resource`.
366+
// For more information, go to https://cloud.tencent.com/document/product/598/10606.
367+
func BuildTagResourceName(serviceType, resourceType, region, id string) string {
368+
return fmt.Sprintf("qcs::%s:%s:uin/:%s/%s", serviceType, region, resourceType, id)
369+
}

builder/tencentcloud/cvm/image_config.go

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,7 @@ type TencentCloudImageConfig struct {
3232
ImageShareAccounts []string `mapstructure:"image_share_accounts" required:"false"`
3333
// Key/value pair tags that will be applied to the resulting image.
3434
ImageTags map[string]string `mapstructure:"image_tags" required:"false"`
35+
SnapshotTags map[string]string `mapstructure:"snapshot_tags" required:"false"`
3536
skipValidation bool
3637
// 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.
3738
SkipCreateImage bool `mapstructure:"skip_create_image" required:"false"`
@@ -79,6 +80,9 @@ func (cf *TencentCloudImageConfig) Prepare(ctx *interpolate.Context) []error {
7980
if cf.ImageTags == nil {
8081
cf.ImageTags = make(map[string]string)
8182
}
83+
if cf.SnapshotTags == nil {
84+
cf.SnapshotTags = make(map[string]string)
85+
}
8286

8387
if len(errs) > 0 {
8488
return errs

builder/tencentcloud/cvm/step_create_image.go

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@ import (
99

1010
"github.com/hashicorp/packer-plugin-sdk/multistep"
1111
cvm "github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/cvm/v20170312"
12+
tag "github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/tag/v20180813"
1213
)
1314

1415
type stepCreateImage struct {
@@ -18,6 +19,7 @@ type stepCreateImage struct {
1819

1920
func (s *stepCreateImage) Run(ctx context.Context, state multistep.StateBag) multistep.StepAction {
2021
client := state.Get("cvm_client").(*cvm.Client)
22+
tagClient := state.Get("tag_client").(*tag.Client)
2123

2224
config := state.Get("config").(*Config)
2325
instance := state.Get("instance").(*cvm.Instance)
@@ -106,6 +108,15 @@ func (s *stepCreateImage) Run(ctx context.Context, state multistep.StateBag) mul
106108
state.Put("image", image)
107109
Message(state, s.imageId, "Image created")
108110

111+
snapshotTags := config.SnapshotTags
112+
if len(snapshotTags) > 0 {
113+
for _, snapshot := range image.SnapshotSet {
114+
resourceName := BuildTagResourceName("cvm", "snapshot", config.Region, *snapshot.SnapshotId)
115+
err := AddResourceTag(ctx, tagClient, resourceName, snapshotTags)
116+
return Halt(state, err, "Failed to set tag for snapshot")
117+
}
118+
}
119+
109120
tencentCloudImages := make(map[string]string)
110121
tencentCloudImages[config.Region] = s.imageId
111122
state.Put("tencentcloudimages", tencentCloudImages)

datasource/tencentcloud/image/data.go

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -105,7 +105,7 @@ func (d *Datasource) Execute() (cty.Value, error) {
105105
}
106106

107107
func (d *Datasource) ResolveImageByFilters() (*cvm.Image, error) {
108-
client, _, err := d.config.Client()
108+
client, _, _, err := d.config.Client()
109109
if err != nil {
110110
return nil, err
111111
}
@@ -150,7 +150,7 @@ func (d *Datasource) ResolveImageByFilters() (*cvm.Image, error) {
150150
}
151151

152152
func (d *Datasource) ResolveImageByImageFamily() (*cvm.Image, error) {
153-
client, _, err := d.config.Client()
153+
client, _, _, err := d.config.Client()
154154
if err != nil {
155155
return nil, err
156156
}

datasource/tencentcloud/image/data.hcl2spec.go

Lines changed: 2 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

docs-partials/builder/tencentcloud/cvm/TencentCloudAccessConfig-not-required.mdx

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,9 @@
66
- `vpc_endpoint` (string) - The endpoint you want to reach the cloud endpoint,
77
if tce cloud you should set a tce vpc endpoint.
88

9+
- `tag_endpoint` (string) - The endpoint you want to reach the cloud endpoint,
10+
if tce cloud you should set a tce tag endpoint.
11+
912
- `security_token` (string) - STS access token, can be set through template or by exporting
1013
as environment variable such as `export TENCENTCLOUD_SECURITY_TOKEN=value`.
1114

docs-partials/builder/tencentcloud/cvm/TencentCloudImageConfig-not-required.mdx

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,8 @@
1515

1616
- `image_tags` (map[string]string) - Key/value pair tags that will be applied to the resulting image.
1717

18+
- `snapshot_tags` (map[string]string) - Snapshot Tags
19+
1820
- `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.
1921

2022
<!-- End of code generated from the comments of the TencentCloudImageConfig struct in builder/tencentcloud/cvm/image_config.go; -->

go.mod

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,13 +6,19 @@ require (
66
github.com/hashicorp/hcl/v2 v2.19.1
77
github.com/hashicorp/packer-plugin-sdk v0.5.2
88
github.com/pkg/errors v0.9.1
9-
github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/common v1.0.1072
9+
github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/common v1.0.1175
1010
github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/cvm v1.0.1072
1111
github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/sts v1.0.797
12+
github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/tag v1.0.1175
1213
github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/vpc v1.0.1072
1314
github.com/zclconf/go-cty v1.13.3
1415
)
1516

17+
require (
18+
github.com/niemeyer/pretty v0.0.0-20200227124842-a10e7caefd8e // indirect
19+
gopkg.in/check.v1 v1.0.0-20200227125254-8fa46927fb4f // indirect
20+
)
21+
1622
require (
1723
cloud.google.com/go v0.105.0 // indirect
1824
cloud.google.com/go/compute v1.12.1 // indirect

0 commit comments

Comments
 (0)