Skip to content

Commit f0edf46

Browse files
authored
Merge pull request #15 from tencentcloudstack/feat/datasource-image
feat: add datasource image
2 parents d605d92 + 4c03d82 commit f0edf46

25 files changed

+667
-104
lines changed

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

Lines changed: 9 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -24,10 +24,6 @@ a [communicator](/packer/docs/templates/legacy_json_templates/communicator) can
2424
reference [Region and Zone](https://intl.cloud.tencent.com/document/product/213/6091)
2525
for parameter taking.
2626

27-
- `zone` (string) - The zone where your cvm will be launch. You should
28-
reference [Region and Zone](https://intl.cloud.tencent.com/document/product/213/6091)
29-
for parameter taking.
30-
3127
<!-- End of code generated from the comments of the TencentCloudAccessConfig struct in builder/tencentcloud/cvm/access_config.go; -->
3228

3329

@@ -37,6 +33,10 @@ a [communicator](/packer/docs/templates/legacy_json_templates/communicator) can
3733
You should reference [Instance Type](https://intl.cloud.tencent.com/document/product/213/11518)
3834
for parameter taking.
3935

36+
- `zone` (string) - The zone where your cvm will be launch. You should
37+
reference [Region and Zone](https://intl.cloud.tencent.com/document/product/213/6091)
38+
for parameter taking.
39+
4040
<!-- End of code generated from the comments of the TencentCloudRunConfig struct in builder/tencentcloud/cvm/run_config.go; -->
4141

4242

@@ -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) - Key/value pair tags that will be applied to snapshot.
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: 15 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -7,13 +7,13 @@
77
package cvm
88

99
import (
10-
"context"
1110
"fmt"
1211
"os"
1312
"strconv"
1413

1514
"github.com/hashicorp/packer-plugin-sdk/template/interpolate"
1615
cvm "github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/cvm/v20170312"
16+
tag "github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/tag/v20180813"
1717
vpc "github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/vpc/v20170312"
1818
)
1919

@@ -76,16 +76,15 @@ type TencentCloudAccessConfig struct {
7676
// reference [Region and Zone](https://intl.cloud.tencent.com/document/product/213/6091)
7777
// for parameter taking.
7878
Region string `mapstructure:"region" required:"true"`
79-
// The zone where your cvm will be launch. You should
80-
// reference [Region and Zone](https://intl.cloud.tencent.com/document/product/213/6091)
81-
// for parameter taking.
82-
Zone string `mapstructure:"zone" required:"true"`
8379
// The endpoint you want to reach the cloud endpoint,
8480
// if tce cloud you should set a tce cvm endpoint.
8581
CvmEndpoint string `mapstructure:"cvm_endpoint" required:"false"`
8682
// The endpoint you want to reach the cloud endpoint,
8783
// if tce cloud you should set a tce vpc endpoint.
8884
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"`
8988
// The region validation can be skipped if this value is true, the default
9089
// value is false.
9190
skipValidation bool
@@ -126,47 +125,31 @@ type TencentCloudAccessRole struct {
126125
SessionDuration int `mapstructure:"session_duration" required:"false"`
127126
}
128127

129-
func (cf *TencentCloudAccessConfig) Client() (*cvm.Client, *vpc.Client, error) {
128+
func (cf *TencentCloudAccessConfig) Client() (*cvm.Client, *vpc.Client, *tag.Client, error) {
130129
var (
131130
err error
132131
cvm_client *cvm.Client
133132
vpc_client *vpc.Client
134-
resp *cvm.DescribeZonesResponse
133+
tag_client *tag.Client
135134
)
136135

137136
if err = cf.validateRegion(); err != nil {
138-
return nil, nil, err
139-
}
140-
141-
if cf.Zone == "" {
142-
return nil, nil, fmt.Errorf("parameter zone must be set")
137+
return nil, nil, nil, err
143138
}
144139

145140
if cvm_client, err = NewCvmClient(cf); err != nil {
146-
return nil, nil, err
141+
return nil, nil, nil, err
147142
}
148143

149144
if vpc_client, err = NewVpcClient(cf); err != nil {
150-
return nil, nil, err
145+
return nil, nil, nil, err
151146
}
152147

153-
ctx := context.TODO()
154-
err = Retry(ctx, func(ctx context.Context) error {
155-
var e error
156-
resp, e = cvm_client.DescribeZones(nil)
157-
return e
158-
})
159-
if err != nil {
160-
return nil, nil, err
161-
}
162-
163-
for _, zone := range resp.Response.ZoneSet {
164-
if cf.Zone == *zone.Zone {
165-
return cvm_client, vpc_client, nil
166-
}
148+
if tag_client, err = NewTagClient(cf); err != nil {
149+
return nil, nil, nil, err
167150
}
168151

169-
return nil, nil, fmt.Errorf("unknown zone: %s", cf.Zone)
152+
return cvm_client, vpc_client, tag_client, nil
170153
}
171154

172155
func (cf *TencentCloudAccessConfig) Prepare(ctx *interpolate.Context) []error {
@@ -176,9 +159,9 @@ func (cf *TencentCloudAccessConfig) Prepare(ctx *interpolate.Context) []error {
176159
errs = append(errs, err)
177160
}
178161

179-
if (cf.CvmEndpoint != "" && cf.VpcEndpoint == "") ||
180-
(cf.CvmEndpoint == "" && cf.VpcEndpoint != "") {
181-
errs = append(errs, fmt.Errorf("parameter cvm_endpoint and vpc_endpoint must be set simultaneously"))
162+
if !((cf.CvmEndpoint == "" && cf.VpcEndpoint == "" && cf.TagEndpoint == "") ||
163+
(cf.CvmEndpoint != "" && cf.VpcEndpoint != "" && cf.TagEndpoint != "")) {
164+
errs = append(errs, fmt.Errorf("parameter cvm_endpoint, vpc_endpoint and tag_endpoint must be set simultaneously"))
182165
}
183166

184167
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: 6 additions & 2 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: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,9 @@ type TencentCloudImageConfig struct {
3131
// after your image created.
3232
ImageShareAccounts []string `mapstructure:"image_share_accounts" required:"false"`
3333
// Key/value pair tags that will be applied to the resulting image.
34-
ImageTags map[string]string `mapstructure:"image_tags" required:"false"`
34+
ImageTags map[string]string `mapstructure:"image_tags" required:"false"`
35+
// Key/value pair tags that will be applied to snapshot.
36+
SnapshotTags map[string]string `mapstructure:"snapshot_tags" required:"false"`
3537
skipValidation bool
3638
// 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.
3739
SkipCreateImage bool `mapstructure:"skip_create_image" required:"false"`
@@ -79,6 +81,9 @@ func (cf *TencentCloudImageConfig) Prepare(ctx *interpolate.Context) []error {
7981
if cf.ImageTags == nil {
8082
cf.ImageTags = make(map[string]string)
8183
}
84+
if cf.SnapshotTags == nil {
85+
cf.SnapshotTags = make(map[string]string)
86+
}
8287

8388
if len(errs) > 0 {
8489
return errs

builder/tencentcloud/cvm/run_config.go

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -109,6 +109,10 @@ type TencentCloudRunConfig struct {
109109
// Communicator settings
110110
Comm communicator.Config `mapstructure:",squash"`
111111
SSHPrivateIp bool `mapstructure:"ssh_private_ip"`
112+
// The zone where your cvm will be launch. You should
113+
// reference [Region and Zone](https://intl.cloud.tencent.com/document/product/213/6091)
114+
// for parameter taking.
115+
Zone string `mapstructure:"zone" required:"true"`
112116
}
113117

114118
var ValidCBSType = []string{
@@ -125,6 +129,10 @@ func (cf *TencentCloudRunConfig) Prepare(ctx *interpolate.Context) []error {
125129
}
126130

127131
errs := cf.Comm.Prepare(ctx)
132+
if cf.Zone == "" {
133+
errs = append(errs, errors.New("zone must be specified"))
134+
}
135+
128136
if cf.SourceImageId == "" && cf.SourceImageName == "" {
129137
errs = append(errs, errors.New("source_image_id or source_image_name must be specified"))
130138
}

builder/tencentcloud/cvm/run_config_test.go

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@ import (
1313

1414
func testConfig() *TencentCloudRunConfig {
1515
return &TencentCloudRunConfig{
16+
Zone: "ap-guangzhou",
1617
SourceImageId: "img-qwer1234",
1718
InstanceType: "S3.SMALL2",
1819
Comm: communicator.Config{

builder/tencentcloud/cvm/step_copy_image.go

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -58,7 +58,6 @@ func (s *stepCopyImage) Run(ctx context.Context, state multistep.StateBag) multi
5858
cf := &TencentCloudAccessConfig{
5959
SecretId: config.SecretId,
6060
SecretKey: config.SecretKey,
61-
Zone: config.Zone,
6261
CvmEndpoint: config.CvmEndpoint,
6362
SecurityToken: config.SecurityToken,
6463
AssumeRole: TencentCloudAccessRole{

0 commit comments

Comments
 (0)