From ff37fde01b84cd62f62a4b35e10cdfdbb4920069 Mon Sep 17 00:00:00 2001 From: longkai Date: Thu, 2 Jul 2020 19:55:06 +0800 Subject: [PATCH 1/3] fix cvm creation while its tags not sync issue When cvm created success, its tags may not attached at once, since it's async. We use a dedicated [tag](https://cloud.tencent.com/document/api/651/35326) api to attach and makes its behavior like a sync one. --- tencentcloud/resource_tc_instance.go | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/tencentcloud/resource_tc_instance.go b/tencentcloud/resource_tc_instance.go index 9bc768ab5d..423447011f 100644 --- a/tencentcloud/resource_tc_instance.go +++ b/tencentcloud/resource_tc_instance.go @@ -598,6 +598,20 @@ func resourceTencentCloudInstanceCreate(d *schema.ResourceData, meta interface{} return err } + // Wait for the tags attached to the vm since tags attachment it's async while vm creation. + if tags := helper.GetTags(d, "tags"); len(tags) > 0 { + tcClient := meta.(*TencentCloudClient).apiV3Conn + tagService := &TagService{client: tcClient} + resourceName := BuildTagResourceName("cvm", "instance", tcClient.Region, instanceId) + err := tagService.ModifyTags(ctx, resourceName, tags, nil) + if err != nil { + // Since we have included the tags params in the creating cvm request, + // when the call returns success, we assume it's successful, regardless of this `ModifyTags` call failed. + // The next time user run terraform, the missing tags(if any) would be synced. + log.Printf("[WARN] sync cvm %s tags failed: %+v, ignore", instanceId, err) + } + } + if !(d.Get("running_flag").(bool)) { err = cvmService.StopInstance(ctx, instanceId) if err != nil { From 62221282568fa501d6820fd2cc50a73140bc9a3f Mon Sep 17 00:00:00 2001 From: longkai Date: Fri, 3 Jul 2020 10:43:24 +0800 Subject: [PATCH 2/3] refactor cvm tags related stuff - use `helper.GetTags` to do with tags uniformly - use `BuildTagResourceName` to build resource name uniformly --- tencentcloud/common.go | 3 +++ tencentcloud/resource_tc_instance.go | 10 +++++----- 2 files changed, 8 insertions(+), 5 deletions(-) diff --git a/tencentcloud/common.go b/tencentcloud/common.go index db21aea52c..9c5179c9cd 100644 --- a/tencentcloud/common.go +++ b/tencentcloud/common.go @@ -191,6 +191,9 @@ func CheckNil(object interface{}, fields map[string]string) (nilFields []string) return } +// BuildTagResourceName builds the Tencent Clould specific name of a resource description. +// The format is `qcs:project_id:service_type:region:account:resource`. +// For more information, go to https://cloud.tencent.com/document/product/598/10606. func BuildTagResourceName(serviceType, resourceType, region, id string) string { switch serviceType { case "cos": diff --git a/tencentcloud/resource_tc_instance.go b/tencentcloud/resource_tc_instance.go index 423447011f..14ab9a981e 100644 --- a/tencentcloud/resource_tc_instance.go +++ b/tencentcloud/resource_tc_instance.go @@ -542,12 +542,12 @@ func resourceTencentCloudInstanceCreate(d *schema.ResourceData, meta interface{} } // tags - if v, ok := d.GetOk("tags"); ok { + if tmpTags := helper.GetTags(d, "tags"); len(tmpTags) > 0 { tags := make([]*cvm.Tag, 0) - for key, value := range v.(map[string]interface{}) { + for k, v := range tmpTags { tag := &cvm.Tag{ - Key: helper.String(key), - Value: helper.String(value.(string)), + Key: helper.String(k), + Value: helper.String(v), } tags = append(tags, tag) } @@ -974,7 +974,7 @@ func resourceTencentCloudInstanceUpdate(d *schema.ResourceData, meta interface{} client: meta.(*TencentCloudClient).apiV3Conn, } region := meta.(*TencentCloudClient).apiV3Conn.Region - resourceName := fmt.Sprintf("qcs::cvm:%s:uin/:instance/%s", region, instanceId) + resourceName := BuildTagResourceName("cvm", "instance", region, instanceId) err := tagService.ModifyTags(ctx, resourceName, replaceTags, deleteTags) if err != nil { return err From 1ec3141a0e3dc189c60e6352308e6eadd5713e1d Mon Sep 17 00:00:00 2001 From: longkai Date: Fri, 3 Jul 2020 12:08:40 +0800 Subject: [PATCH 3/3] remove old tag attachement code If new tag api call failed, the user will be notified and tack actions with terraform --- tencentcloud/resource_tc_instance.go | 26 +++----------------------- 1 file changed, 3 insertions(+), 23 deletions(-) diff --git a/tencentcloud/resource_tc_instance.go b/tencentcloud/resource_tc_instance.go index 14ab9a981e..d70c0156b3 100644 --- a/tencentcloud/resource_tc_instance.go +++ b/tencentcloud/resource_tc_instance.go @@ -541,23 +541,6 @@ func resourceTencentCloudInstanceCreate(d *schema.ResourceData, meta interface{} request.UserData = &userData } - // tags - if tmpTags := helper.GetTags(d, "tags"); len(tmpTags) > 0 { - tags := make([]*cvm.Tag, 0) - for k, v := range tmpTags { - tag := &cvm.Tag{ - Key: helper.String(k), - Value: helper.String(v), - } - tags = append(tags, tag) - } - tagSpecification := &cvm.TagSpecification{ - ResourceType: helper.String("instance"), - Tags: tags, - } - request.TagSpecification = []*cvm.TagSpecification{tagSpecification} - } - instanceId := "" err := resource.Retry(writeRetryTimeout, func() *resource.RetryError { ratelimit.Check("create") @@ -603,12 +586,9 @@ func resourceTencentCloudInstanceCreate(d *schema.ResourceData, meta interface{} tcClient := meta.(*TencentCloudClient).apiV3Conn tagService := &TagService{client: tcClient} resourceName := BuildTagResourceName("cvm", "instance", tcClient.Region, instanceId) - err := tagService.ModifyTags(ctx, resourceName, tags, nil) - if err != nil { - // Since we have included the tags params in the creating cvm request, - // when the call returns success, we assume it's successful, regardless of this `ModifyTags` call failed. - // The next time user run terraform, the missing tags(if any) would be synced. - log.Printf("[WARN] sync cvm %s tags failed: %+v, ignore", instanceId, err) + if err := tagService.ModifyTags(ctx, resourceName, tags, nil); err != nil { + // If tags attachment failed, the user will be notified, then plan/apply/update with terraform. + return err } }