diff --git a/ibm/flex/structures.go b/ibm/flex/structures.go index da354497e6..147a0d6bba 100644 --- a/ibm/flex/structures.go +++ b/ibm/flex/structures.go @@ -2401,34 +2401,46 @@ func GetTags(d *schema.ResourceData, meta interface{}) error { // } func GetGlobalTagsUsingCRN(meta interface{}, resourceID, resourceType, tagType string) (*schema.Set, error) { + taggingResult, err := GetGlobalTagsUsingSearchAPI(meta, resourceID, resourceType, tagType) + if err != nil { + return nil, err + } + return taggingResult, nil +} + +func GetTagsUsingResourceCRNFromTaggingApi(meta interface{}, resourceID, resourceType, tagType string) (*schema.Set, error) { + gtClient, err := meta.(conns.ClientSession).GlobalTaggingAPIv1() + if err != nil { + return nil, fmt.Errorf("[ERROR] Error getting global tagging client settings: %s", err) + } userDetails, err := meta.(conns.ClientSession).BluemixUserDetails() if err != nil { return nil, err } accountID := userDetails.UserAccount ListTagsOptions := &globaltaggingv1.ListTagsOptions{} - if resourceID != "" { - ListTagsOptions.AttachedTo = &resourceID - } + ListTagsOptions.AttachedTo = &resourceID if strings.HasPrefix(resourceType, "Softlayer_") { ListTagsOptions.Providers = []string{"ims"} } if len(tagType) > 0 { ListTagsOptions.TagType = PtrToString(tagType) - if tagType == "service" { ListTagsOptions.AccountID = PtrToString(accountID) } } - taggingResult, err := GetGlobalTagsUsingSearchAPI(meta, resourceID, resourceType, tagType) + taggingResult, _, err := gtClient.ListTags(ListTagsOptions) if err != nil { return nil, err } - return taggingResult, nil + var taglist []string + for _, item := range taggingResult.Items { + taglist = append(taglist, *item.Name) + } + return NewStringSet(ResourceIBMVPCHash, taglist), nil } func GetGlobalTagsUsingSearchAPI(meta interface{}, resourceID, resourceType, tagType string) (*schema.Set, error) { - gsClient, err := meta.(conns.ClientSession).GlobalSearchAPIV2() if err != nil { return nil, fmt.Errorf("[ERROR] Error getting global search client settings: %s", err) @@ -2531,18 +2543,20 @@ func UpdateGlobalTagsUsingCRN(oldList, newList interface{}, meta interface{}, re detachTagOptions.AccountID = PtrToString(acctID) } } - - _, resp, err := gtClient.DetachTag(detachTagOptions) + results, fullResponse, err := gtClient.DetachTag(detachTagOptions) if err != nil { - return fmt.Errorf("[ERROR] Error detaching database tags %v: %s\n%s", remove, err, resp) + return fmt.Errorf("[ERROR] Error detaching tags calling api %v: %s\n%s", remove, err, fullResponse) } - for _, v := range remove { - delTagOptions := &globaltaggingv1.DeleteTagOptions{ - TagName: PtrToString(v), + if results != nil { + errMap := make([]globaltaggingv1.TagResultsItem, 0) + for _, res := range results.Results { + if res.IsError != nil && *res.IsError { + errMap = append(errMap, res) + } } - _, resp, err := gtClient.DeleteTag(delTagOptions) - if err != nil { - return fmt.Errorf("[ERROR] Error deleting database tag %v: %s\n%s", v, err, resp) + if len(errMap) > 0 { + output, _ := json.MarshalIndent(errMap, "", " ") + return fmt.Errorf("[ERROR] Error detaching tag in results %v: %s\n%s", remove, string(output), fullResponse) } } } @@ -2624,7 +2638,7 @@ func GetTagsUsingCRN(meta interface{}, resourceCRN string) (*schema.Set, error) } func UpdateTagsUsingCRN(oldList, newList interface{}, meta interface{}, resourceCRN string) error { - gtClient, err := meta.(conns.ClientSession).GlobalTaggingAPI() + gtClient, err := meta.(conns.ClientSession).GlobalTaggingAPIv1() if err != nil { return fmt.Errorf("[ERROR] Error getting global tagging client settings: %s", err) } @@ -2654,23 +2668,74 @@ func UpdateTagsUsingCRN(oldList, newList interface{}, meta interface{}, resource add = append(add, envTags...) } + resources := []globaltaggingv1.Resource{} + r := globaltaggingv1.Resource{ResourceID: &resourceCRN} + resources = append(resources, r) + if len(remove) > 0 { - _, err := gtClient.Tags().DetachTags(resourceCRN, remove) + detachTagOptions := &globaltaggingv1.DetachTagOptions{} + detachTagOptions.Resources = resources + detachTagOptions.TagNames = remove + + results, fullResponse, err := gtClient.DetachTag(detachTagOptions) if err != nil { - return fmt.Errorf("[ERROR] Error detaching database tags %v: %s", remove, err) + return fmt.Errorf("[ERROR] Error detaching tags %v: %s", remove, err) + } + if results != nil { + errMap := make([]globaltaggingv1.TagResultsItem, 0) + for _, res := range results.Results { + if res.IsError != nil && *res.IsError { + errMap = append(errMap, res) + } + } + if len(errMap) > 0 { + output, _ := json.MarshalIndent(errMap, "", " ") + return fmt.Errorf("[ERROR] Error detaching tag %v: %s\n%s", remove, string(output), fullResponse) + } } for _, v := range remove { - _, err := gtClient.Tags().DeleteTag(v) + delTagOptions := &globaltaggingv1.DeleteTagOptions{ + TagName: PtrToString(v), + } + results, fullResponse, err := gtClient.DeleteTag(delTagOptions) if err != nil { - return fmt.Errorf("[ERROR] Error deleting database tag %v: %s", v, err) + return fmt.Errorf("[ERROR] Error deleting tag %v: %s\n%s", v, err, fullResponse) + } + + if results != nil { + errMap := make([]globaltaggingv1.DeleteTagResultsItem, 0) + for _, res := range results.Results { + if res.IsError != nil && *res.IsError { + errMap = append(errMap, res) + } + } + if len(errMap) > 0 { + output, _ := json.MarshalIndent(errMap, "", " ") + return fmt.Errorf("[ERROR] Error deleting tag %s: %s\n%s", v, string(output), fullResponse) + } } } } if len(add) > 0 { - _, err := gtClient.Tags().AttachTags(resourceCRN, add) + AttachTagOptions := &globaltaggingv1.AttachTagOptions{} + AttachTagOptions.Resources = resources + AttachTagOptions.TagNames = add + results, fullResponse, err := gtClient.AttachTag(AttachTagOptions) if err != nil { - return fmt.Errorf("[ERROR] Error updating database tags %v : %s", add, err) + return fmt.Errorf("[ERROR] Error updating tags %v : %s", add, err) + } + if results != nil { + errMap := make([]globaltaggingv1.TagResultsItem, 0) + for _, res := range results.Results { + if res.IsError != nil && *res.IsError { + errMap = append(errMap, res) + } + } + if len(errMap) > 0 { + output, _ := json.MarshalIndent(errMap, "", " ") + return fmt.Errorf("Error while updating tag: %s - Full response: %s", string(output), fullResponse) + } } } diff --git a/ibm/service/globaltagging/resource_ibm_iam_access_tag.go b/ibm/service/globaltagging/resource_ibm_iam_access_tag.go index fa7874bef7..a1844c8fc3 100644 --- a/ibm/service/globaltagging/resource_ibm_iam_access_tag.go +++ b/ibm/service/globaltagging/resource_ibm_iam_access_tag.go @@ -153,7 +153,7 @@ func resourceIBMIamAccessTagDelete(context context.Context, d *schema.ResourceDa results, resp, err := gtClient.DeleteTagWithContext(context, deleteTagOptions) if err != nil { - return diag.FromErr(fmt.Errorf("Error while deleting access tag(%s) : %v\n%v", tagName, err, resp)) + return diag.FromErr(fmt.Errorf("Error while deleting access tag calling api (%s) : %v\n%v", tagName, err, resp)) } if results != nil { errMap := make([]globaltaggingv1.DeleteTagResultsItem, 0) @@ -164,7 +164,7 @@ func resourceIBMIamAccessTagDelete(context context.Context, d *schema.ResourceDa } if len(errMap) > 0 { output, _ := json.MarshalIndent(errMap, "", " ") - return diag.FromErr(fmt.Errorf("Error while deleting access tag(%s) : %s", tagName, string(output))) + return diag.FromErr(fmt.Errorf("Error while deleting access tag in results (%s) : %s", tagName, string(output))) } } diff --git a/ibm/service/globaltagging/resource_ibm_iam_access_tag_test.go b/ibm/service/globaltagging/resource_ibm_iam_access_tag_test.go index a6d973def4..e4a4f2362c 100644 --- a/ibm/service/globaltagging/resource_ibm_iam_access_tag_test.go +++ b/ibm/service/globaltagging/resource_ibm_iam_access_tag_test.go @@ -6,7 +6,6 @@ package globaltagging_test import ( "fmt" "regexp" - "strings" "testing" acc "github.com/IBM-Cloud/terraform-provider-ibm/ibm/acctest" @@ -44,10 +43,6 @@ func TestAccIamAccessTag_Basic(t *testing.T) { } func TestAccIamAccessTag_Usage(t *testing.T) { name := fmt.Sprintf("tf%d:iam-access%d", acctest.RandIntRange(10, 100), acctest.RandIntRange(10, 100)) - publicKey := strings.TrimSpace(` -ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQCKVmnMOlHKcZK8tpt3MP1lqOLAcqcJzhsvJcjscgVERRN7/9484SOBJ3HSKxxNG5JN8owAjy5f9yYwcUg+JaUVuytn5Pv3aeYROHGGg+5G346xaq3DAwX6Y5ykr2fvjObgncQBnuU5KHWCECO/4h8uWuwh/kfniXPVjFToc+gnkqA+3RKpAecZhFXwfalQ9mMuYGFxn+fwn8cYEApsJbsEmb0iJwPiZ5hjFC8wREuiTlhPHDgkBLOiycd20op2nXzDbHfCHInquEe/gYxEitALONxm0swBOwJZwlTDOB7C6y2dzlrtxr1L59m7pCkWI4EtTRLvleehBoj3u7jB4usR -`) - sshkeyname := fmt.Sprintf("tfssh-createname-%d", acctest.RandIntRange(10, 100)) resource.Test(t, resource.TestCase{ PreCheck: func() { acc.TestAccPreCheck(t) }, Providers: acc.TestAccProviders, @@ -63,7 +58,7 @@ ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQCKVmnMOlHKcZK8tpt3MP1lqOLAcqcJzhsvJcjscgVE ), }, resource.TestStep{ - Config: testAccCheckIamAccessTagUsage(name, sshkeyname, publicKey), + Config: testAccCheckIamAccessTagUsage(name), Check: resource.ComposeAggregateTestCheckFunc( testAccCheckIamAccessTagExists("ibm_iam_access_tag.tag"), resource.TestCheckResourceAttr("ibm_iam_access_tag.tag", "id", name), @@ -129,19 +124,24 @@ func testAccCheckIamAccessTagCreate(name string) string { } `, name) } -func testAccCheckIamAccessTagUsage(name, sshkeyname, publicKey string) string { +func testAccCheckIamAccessTagUsage(name string) string { + resource_group_name := fmt.Sprintf("tf%d-iam-access%d", acctest.RandIntRange(10, 100), acctest.RandIntRange(10, 100)) return fmt.Sprintf(` + data "ibm_resource_group" "group" { + name = "Default" + } resource "ibm_iam_access_tag" "tag" { name = "%s" } - resource "ibm_is_ssh_key" "key" { - name = "%s" - public_key = "%s" + resource "ibm_cd_toolchain" "cd_toolchain_instance" { + description = "Terraform test" + name = "%s-toolchain" + resource_group_id = data.ibm_resource_group.group.id } resource "ibm_resource_tag" "tag" { - resource_id = ibm_is_ssh_key.key.crn + resource_id = ibm_cd_toolchain.cd_toolchain_instance.crn tags = [ibm_iam_access_tag.tag.name] tag_type = "access" } -`, name, sshkeyname, publicKey) +`, name, resource_group_name) } diff --git a/ibm/service/globaltagging/resource_ibm_resource_tag.go b/ibm/service/globaltagging/resource_ibm_resource_tag.go index 34df86fc29..aa23bd1f73 100644 --- a/ibm/service/globaltagging/resource_ibm_resource_tag.go +++ b/ibm/service/globaltagging/resource_ibm_resource_tag.go @@ -5,6 +5,7 @@ package globaltagging import ( "context" + "encoding/json" "fmt" "log" "os" @@ -18,6 +19,7 @@ import ( "github.com/IBM-Cloud/terraform-provider-ibm/ibm/conns" "github.com/IBM-Cloud/terraform-provider-ibm/ibm/flex" "github.com/IBM-Cloud/terraform-provider-ibm/ibm/validate" + "github.com/hashicorp/terraform-plugin-sdk/v2/diag" ) const ( @@ -32,11 +34,11 @@ const ( func ResourceIBMResourceTag() *schema.Resource { return &schema.Resource{ - Create: resourceIBMResourceTagCreate, - Read: resourceIBMResourceTagRead, - Update: resourceIBMResourceTagUpdate, - Delete: resourceIBMResourceTagDelete, - Importer: &schema.ResourceImporter{}, + CreateContext: resourceIBMResourceTagCreate, + ReadContext: resourceIBMResourceTagRead, + UpdateContext: resourceIBMResourceTagUpdate, + DeleteContext: resourceIBMResourceTagDelete, + Importer: &schema.ResourceImporter{}, CustomizeDiff: customdiff.Sequence( func(_ context.Context, diff *schema.ResourceDiff, v interface{}) error { @@ -125,19 +127,23 @@ func ResourceIBMResourceTagValidator() *validate.ResourceValidator { return &ibmResourceTagValidator } -func resourceIBMResourceTagCreate(d *schema.ResourceData, meta interface{}) error { +func resourceIBMResourceTagCreate(context context.Context, d *schema.ResourceData, meta interface{}) diag.Diagnostics { var rType, tType string resources := []globaltaggingv1.Resource{} userDetails, err := meta.(conns.ClientSession).BluemixUserDetails() if err != nil { - return err + tfErr := flex.TerraformErrorf(err, err.Error(), "ibm_resource_tag", "create") + log.Printf("[DEBUG]\n%s", tfErr.GetDebugMessage()) + return tfErr.GetDiag() } accountID := userDetails.UserAccount gtClient, err := meta.(conns.ClientSession).GlobalTaggingAPIv1() if err != nil { - return fmt.Errorf("[ERROR] Error getting global tagging client settings: %s", err) + tfErr := flex.TerraformErrorf(err, err.Error(), "ibm_resource_tag", "create") + log.Printf("[DEBUG]\n%s", tfErr.GetDebugMessage()) + return tfErr.GetDiag() } resourceID := d.Get(resourceID).(string) @@ -187,9 +193,24 @@ func resourceIBMResourceTagCreate(d *schema.ResourceData, meta interface{}) erro } if len(add) > 0 { - _, resp, err := gtClient.AttachTag(AttachTagOptions) + results, fullResponse, err := gtClient.AttachTagWithContext(context, AttachTagOptions) if err != nil { - return fmt.Errorf("[ERROR] Error attaching resource tags : %v\n%s", resp, err) + tfErr := flex.TerraformErrorf(err, err.Error(), "ibm_resource_tag", "create") + return tfErr.GetDiag() + } + + // Check if there are errors on the attach internal response + if results != nil { + errMap := make([]globaltaggingv1.TagResultsItem, 0) + for _, res := range results.Results { + if res.IsError != nil && *res.IsError { + errMap = append(errMap, res) + } + } + if len(errMap) > 0 { + output, _ := json.MarshalIndent(errMap, "", " ") + return diag.FromErr(fmt.Errorf("Error while creating tag: %s - Full response: %s", string(output), fullResponse)) + } } response, errored := flex.WaitForTagsAvailable(meta, resourceID, resourceType, tagType, news, d.Timeout(schema.TimeoutCreate)) if errored != nil { @@ -204,15 +225,17 @@ func resourceIBMResourceTagCreate(d *schema.ResourceData, meta interface{}) erro d.SetId(fmt.Sprintf("%s/%s", resourceID, rType)) } - return resourceIBMResourceTagRead(d, meta) + return resourceIBMResourceTagRead(context, d, meta) } -func resourceIBMResourceTagRead(d *schema.ResourceData, meta interface{}) error { +func resourceIBMResourceTagRead(context context.Context, d *schema.ResourceData, meta interface{}) diag.Diagnostics { var rID, rType, tType string userDetails, err := meta.(conns.ClientSession).BluemixUserDetails() if err != nil { - return err + tfErr := flex.TerraformErrorf(err, err.Error(), "ibm_resource_tag", "read") + log.Printf("[DEBUG]\n%s", tfErr.GetDebugMessage()) + return tfErr.GetDiag() } acctID := userDetails.UserAccount @@ -221,10 +244,12 @@ func resourceIBMResourceTagRead(d *schema.ResourceData, meta interface{}) error } else { parts, err := flex.VmIdParts(d.Id()) if err != nil { - return err + tfErr := flex.TerraformErrorf(err, err.Error(), "ibm_resource_tag", "read") + log.Printf("[DEBUG]\n%s", tfErr.GetDebugMessage()) + return tfErr.GetDiag() } if len(parts) < 2 { - return fmt.Errorf("[ERROR] Incorrect ID %s: Id should be a combination of resourceID/resourceType", d.Id()) + return diag.FromErr(fmt.Errorf("Incorrect ID %s: Id should be a combination of resourceID/resourceType", d.Id())) } rID = parts[0] rType = parts[1] @@ -240,7 +265,7 @@ func resourceIBMResourceTagRead(d *schema.ResourceData, meta interface{}) error tagList, err := flex.GetGlobalTagsUsingSearchAPI(meta, rID, rType, tType) if err != nil { - return fmt.Errorf("[ERROR] Error getting resource tags for: %s with error : %s", rID, err) + return diag.FromErr(fmt.Errorf("Error getting resource tags for: %s with error : %s", rID, err)) } d.Set(resourceID, rID) @@ -250,7 +275,7 @@ func resourceIBMResourceTagRead(d *schema.ResourceData, meta interface{}) error return nil } -func resourceIBMResourceTagUpdate(d *schema.ResourceData, meta interface{}) error { +func resourceIBMResourceTagUpdate(context context.Context, d *schema.ResourceData, meta interface{}) diag.Diagnostics { var rID, rType, tType string if strings.HasPrefix(d.Id(), "crn:") { @@ -258,7 +283,9 @@ func resourceIBMResourceTagUpdate(d *schema.ResourceData, meta interface{}) erro } else { parts, err := flex.VmIdParts(d.Id()) if err != nil { - return err + tfErr := flex.TerraformErrorf(err, err.Error(), "ibm_resource_tag", "update") + log.Printf("[DEBUG]\n%s", tfErr.GetDebugMessage()) + return tfErr.GetDiag() } rID = parts[0] rType = parts[1] @@ -272,68 +299,38 @@ func resourceIBMResourceTagUpdate(d *schema.ResourceData, meta interface{}) erro oldList, newList := d.GetChange(tags) err := flex.UpdateGlobalTagsUsingCRN(oldList, newList, meta, rID, rType, tType) if err != nil { - return fmt.Errorf("[ERROR] Error on create of resource tags: %s", err) + return diag.FromErr(fmt.Errorf("Error on create of resource tags: %s", err)) } } - return resourceIBMResourceTagRead(d, meta) + return resourceIBMResourceTagRead(context, d, meta) } -func resourceIBMResourceTagDelete(d *schema.ResourceData, meta interface{}) error { +func resourceIBMResourceTagDelete(context context.Context, d *schema.ResourceData, meta interface{}) diag.Diagnostics { var rID, rType string - if strings.HasPrefix(d.Id(), "crn:") { rID = d.Id() } else { parts, err := flex.VmIdParts(d.Id()) if err != nil { - return err + tfErr := flex.TerraformErrorf(err, err.Error(), "ibm_resource_tag", "delete") + log.Printf("[ERROR] Error in deleting.\n%s", tfErr.GetDebugMessage()) + return tfErr.GetDiag() } rID = parts[0] rType = parts[1] } - - gtClient, err := meta.(conns.ClientSession).GlobalTaggingAPIv1() - if err != nil { - return fmt.Errorf("[ERROR] Error getting global tagging client settings: %s", err) - } - - var remove []string removeTags := d.Get(tags).(*schema.Set) - remove = make([]string, len(removeTags.List())) - for i, v := range removeTags.List() { - remove[i] = fmt.Sprint(v) - } var tType string if v, ok := d.GetOk(tagType); ok && v != nil { tType = v.(string) } else { tType = "user" } - - if len(remove) > 0 { - resources := []globaltaggingv1.Resource{} - r := globaltaggingv1.Resource{ResourceID: flex.PtrToString(rID), ResourceType: flex.PtrToString(rType)} - resources = append(resources, r) - - detachTagOptions := &globaltaggingv1.DetachTagOptions{ - Resources: resources, - TagNames: remove, - TagType: &tType, - } - - _, resp, err := gtClient.DetachTag(detachTagOptions) + if len(removeTags.List()) > 0 { + err := flex.UpdateGlobalTagsUsingCRN(removeTags, nil, meta, rID, rType, tType) if err != nil { - return fmt.Errorf("[ERROR] Error detaching resource tags %v: %s\n%s", remove, err, resp) - } - for _, v := range remove { - delTagOptions := &globaltaggingv1.DeleteTagOptions{ - TagName: flex.PtrToString(v), - } - _, resp, err := gtClient.DeleteTag(delTagOptions) - if err != nil { - return fmt.Errorf("[ERROR] Error deleting resource tag %v: %s\n%s", v, err, resp) - } + return diag.FromErr(fmt.Errorf("Error on deleting tags: %s", err)) } } return nil diff --git a/ibm/service/globaltagging/resource_ibm_resource_tag_test.go b/ibm/service/globaltagging/resource_ibm_resource_tag_test.go index b7dca8d395..414a1a2d4b 100644 --- a/ibm/service/globaltagging/resource_ibm_resource_tag_test.go +++ b/ibm/service/globaltagging/resource_ibm_resource_tag_test.go @@ -7,6 +7,7 @@ import ( "fmt" "log" "regexp" + "strings" "testing" acc "github.com/IBM-Cloud/terraform-provider-ibm/ibm/acctest" @@ -18,14 +19,17 @@ import ( func TestAccResourceTag_Basic(t *testing.T) { name := fmt.Sprintf("tf-cos-%d", acctest.RandIntRange(10, 100)) + var tags []string + tags = append(tags, "env:dev") + tags = append(tags, "cpu:4") resource.Test(t, resource.TestCase{ - PreCheck: func() { acc.TestAccPreCheck(t) }, - Providers: acc.TestAccProviders, + PreCheck: func() { acc.TestAccPreCheck(t) }, + Providers: acc.TestAccProviders, + CheckDestroy: testAccCheckTagDestroy("ibm_resource_tag.tag", "user", tags), Steps: []resource.TestStep{ - { - Config: testAccCheckResourceTagCreate(name), + Config: testAccCheckResourceTagCreate(name, tags), Check: resource.ComposeAggregateTestCheckFunc( testAccCheckResourceTagExists("ibm_resource_tag.tag"), resource.TestCheckResourceAttr("ibm_resource_tag.tag", "tags.#", "2"), @@ -41,26 +45,45 @@ func TestAccResourceTag_Basic(t *testing.T) { }, }) } -func TestAccResourceTag_Wait(t *testing.T) { - name := fmt.Sprintf("tf-cos-%d", acctest.RandIntRange(10, 100)) +func TestAccResourceTag_FakeCrnExpectingError(t *testing.T) { + var tags []string + tags = append(tags, "env:dev") + tags = append(tags, "cpu:4") resource.Test(t, resource.TestCase{ PreCheck: func() { acc.TestAccPreCheck(t) }, Providers: acc.TestAccProviders, Steps: []resource.TestStep{ + { + Config: testAccCheckResourceTagCreateFakeCrnExpectingError(tags), + ExpectError: regexp.MustCompile("\"is_error\": true"), + }, + }, + }) +} +func TestAccResourceTag_AttachOnExistingResource(t *testing.T) { + crn := "crn:v1:bluemix:public:toolchain:eu-gb:a/970f5cb4bbc04119ab0a0f399e4b776c:8784b8c3-1c7f-476a-ac30-50ae07e3cce3::" + var tags []string + tags = append(tags, "env:dev") + tags = append(tags, "cpu:4") + resource.Test(t, resource.TestCase{ + PreCheck: func() { acc.TestAccPreCheck(t) }, + Providers: acc.TestAccProviders, + CheckDestroy: testAccCheckTagOnExistingResourceDestroy(crn, "ibm_resource_tag.tag", "user", tags), + Steps: []resource.TestStep{ { - Config: testAccCheckResourceTagWaitCreate(name), + Config: testAccCheckResourceAttachOnExistingResource(crn, tags), Check: resource.ComposeAggregateTestCheckFunc( testAccCheckResourceTagExists("ibm_resource_tag.tag"), - resource.TestCheckResourceAttr("ibm_resource_tag.tag", "tags.#", "3"), + resource.TestCheckResourceAttr("ibm_resource_tag.tag", "tags.#", "2"), ), }, }, }) } -func testAccCheckResourceTagExists(n string) resource.TestCheckFunc { +func testAccCheckTagDestroy(n, tagType string, tagNames []string) resource.TestCheckFunc { return func(s *terraform.State) error { var resourceID string rs, ok := s.RootModule().Resources[n] @@ -72,7 +95,80 @@ func testAccCheckResourceTagExists(n string) resource.TestCheckFunc { if err != nil { return err } + if crn.MatchString(rs.Primary.ID) { + resourceID = rs.Primary.ID + } else { + parts, err := flex.VmIdParts(rs.Primary.ID) + if err != nil { + return err + } + resourceID = parts[0] + } + results, errorGet := flex.GetTagsUsingResourceCRNFromTaggingApi(acc.TestAccProvider.Meta(), resourceID, "", tagType) + if errorGet != nil { + return fmt.Errorf("Error on get of resource tags (%s) : %s", resourceID, errorGet) + } + var taglist []string + for _, v := range results.List() { + taglist = append(taglist, fmt.Sprint(v)) + } + existingAccessTags := flex.NewStringSet(flex.ResourceIBMVPCHash, taglist) + for _, tagName := range tagNames { + if existingAccessTags.Contains(tagName) { + return fmt.Errorf("Tag still exists") + } + } + return nil + } +} +func testAccCheckTagOnExistingResourceDestroy(resourceCrn, n, tagType string, tagNames []string) resource.TestCheckFunc { + return func(s *terraform.State) error { + var resourceID string + _, ok := s.RootModule().Resources[n] + if !ok { + return fmt.Errorf("Not found: %s", n) + } + crnRegex := "^crn:v1(:[a-zA-Z0-9 \\-\\._~\\*\\+,;=!$&'\\(\\)\\/\\?#\\[\\]@]*){8}$|^[0-9]+$" + crn, err := regexp.Compile(crnRegex) + if err != nil { + return err + } + if crn.MatchString(resourceCrn) { + resourceID = resourceCrn + } else { + return fmt.Errorf("CRN not correct: %s", resourceCrn) + } + results, errorGet := flex.GetTagsUsingResourceCRNFromTaggingApi(acc.TestAccProvider.Meta(), resourceID, "", tagType) + if errorGet != nil { + return fmt.Errorf("Error on get of resource tags (%s) : %s", resourceID, errorGet) + } + var taglist []string + for _, v := range results.List() { + taglist = append(taglist, fmt.Sprint(v)) + } + existingAccessTags := flex.NewStringSet(flex.ResourceIBMVPCHash, taglist) + for _, tagName := range tagNames { + if existingAccessTags.Contains(tagName) { + return fmt.Errorf("Tag still exists") + } + } + return nil + } +} + +func testAccCheckResourceTagExists(n string) resource.TestCheckFunc { + return func(s *terraform.State) error { + var resourceID string + rs, ok := s.RootModule().Resources[n] + if !ok { + return fmt.Errorf("Not found: %s", n) + } + crnRegex := "^crn:v1(:[a-zA-Z0-9 \\-\\._~\\*\\+,;=!$&'\\(\\)\\/\\?#\\[\\]@]*){8}$|^[0-9]+$" + crn, err := regexp.Compile(crnRegex) + if err != nil { + return err + } if crn.MatchString(rs.Primary.ID) { resourceID = rs.Primary.ID } else { @@ -91,7 +187,7 @@ func testAccCheckResourceTagExists(n string) resource.TestCheckFunc { } } -func testAccCheckResourceTagWaitCreate(name string) string { +func testAccCheckResourceTagCreate(name string, tagNames []string) string { return fmt.Sprintf(` resource "ibm_resource_instance" "resource_1" { name = "%s" @@ -102,24 +198,27 @@ func testAccCheckResourceTagWaitCreate(name string) string { resource "ibm_resource_tag" "tag" { resource_id = ibm_resource_instance.resource_1.crn - tags = ["env:dev", "cpu:4", "user:8"] + tags = ["%s"] } -`, name) +`, name, strings.Join(tagNames[:], "\",\"")) } -func testAccCheckResourceTagCreate(name string) string { + +func testAccCheckResourceTagCreateFakeCrnExpectingError(tagNames []string) string { return fmt.Sprintf(` - resource "ibm_resource_instance" "resource_1" { - name = "%s" - service = "cloud-object-storage" - plan = "lite" - location = "global" + resource "ibm_resource_tag" "tag" { + resource_id = "crn:v1:staging:public:cloud-object-storage:global:a/d99e99999dfe99ee999999f99bddd099:ab99d9be-9e9c-99dd-ad99-9bced9999999::" + tags = ["%s"] } +`, strings.Join(tagNames[:], "\",\"")) +} +func testAccCheckResourceAttachOnExistingResource(crn string, tagNames []string) string { + return fmt.Sprintf(` resource "ibm_resource_tag" "tag" { - resource_id = ibm_resource_instance.resource_1.crn - tags = ["env:dev", "cpu:4"] + resource_id = "%s" + tags = ["%s"] } -`, name) +`, crn, strings.Join(tagNames[:], "\",\"")) } func TestAccResourceTag_replace_Basic(t *testing.T) {