Skip to content

Commit

Permalink
Added support for resource access tag (#3321)
Browse files Browse the repository at this point in the history
* Added support for resource access tag

* updated license year

* Updated docs for ibm_resource_access_tag
  • Loading branch information
uibm authored Mar 22, 2024
1 parent 3289e78 commit dc2f51a
Show file tree
Hide file tree
Showing 7 changed files with 380 additions and 4 deletions.
4 changes: 3 additions & 1 deletion ibm/provider/provider.go
Original file line number Diff line number Diff line change
Expand Up @@ -1306,7 +1306,8 @@ func Provider() *schema.Provider {
"ibm_satellite_cluster_worker_pool_zone_attachment": satellite.ResourceIbmSatelliteClusterWorkerPoolZoneAttachment(),

// Added for Resource Tag
"ibm_resource_tag": globaltagging.ResourceIBMResourceTag(),
"ibm_resource_tag": globaltagging.ResourceIBMResourceTag(),
"ibm_resource_access_tag": globaltagging.ResourceIBMResourceAccessTag(),

// Atracker
"ibm_atracker_target": atracker.ResourceIBMAtrackerTarget(),
Expand Down Expand Up @@ -1600,6 +1601,7 @@ func Validator() validate.ValidatorDict {
"ibm_resource_key": resourcecontroller.ResourceIBMResourceKeyValidator(),
"ibm_is_virtual_endpoint_gateway": vpc.ResourceIBMISEndpointGatewayValidator(),
"ibm_resource_tag": globaltagging.ResourceIBMResourceTagValidator(),
"ibm_resource_access_tag": globaltagging.ResourceIBMResourceAccessTagValidator(),
"ibm_satellite_location": satellite.ResourceIBMSatelliteLocationValidator(),
"ibm_satellite_cluster": satellite.ResourceIBMSatelliteClusterValidator(),
"ibm_pi_volume": power.ResourceIBMPIVolumeValidator(),
Expand Down
165 changes: 165 additions & 0 deletions ibm/service/globaltagging/resource_ibm_resource_access_tag.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,165 @@
// Copyright IBM Corp. 2017, 2021 All Rights Reserved.
// Licensed under the Mozilla Public License v2.0

package globaltagging

import (
"encoding/json"
"fmt"
"log"

"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/IBM/platform-services-go-sdk/globaltaggingv1"
"github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema"
)

func ResourceIBMResourceAccessTag() *schema.Resource {
return &schema.Resource{
Create: resourceIBMResourceAccessTagCreate,
Read: resourceIBMResourceAccessTagRead,
Delete: resourceIBMResourceAccessTagDelete,
Importer: &schema.ResourceImporter{},

Schema: map[string]*schema.Schema{

"name": {
Type: schema.TypeString,
Required: true,
ForceNew: true,
ValidateFunc: validate.InvokeValidator("ibm_resource_access_tag", "name"),
Set: flex.ResourceIBMVPCHash,
Description: "Name of the access tag",
},
tagType: {
Type: schema.TypeString,
Computed: true,
Description: "Type of the tag(access)",
},
},
}
}

func ResourceIBMResourceAccessTagValidator() *validate.ResourceValidator {

validateSchema := make([]validate.ValidateSchema, 0)

validateSchema = append(validateSchema,
validate.ValidateSchema{
Identifier: "name",
ValidateFunctionIdentifier: validate.ValidateRegexpLen,
Type: validate.TypeString,
Required: true,
Regexp: `^([A-Za-z0-9_.-]|[A-Za-z0-9_.-][A-Za-z0-9_ .-]*[A-Za-z0-9_.-]):([A-Za-z0-9_.-]|[A-Za-z0-9_.-][A-Za-z0-9_ .-]*[A-Za-z0-9_.-])$`,
MinValueLength: 1,
MaxValueLength: 128})

ibmResourceAccessTagValidator := validate.ResourceValidator{ResourceName: "ibm_resource_access_tag", Schema: validateSchema}
return &ibmResourceAccessTagValidator
}

func resourceIBMResourceAccessTagCreate(d *schema.ResourceData, meta interface{}) error {

gtClient, err := meta.(conns.ClientSession).GlobalTaggingAPIv1()
if err != nil {
return fmt.Errorf("Error getting global tagging client settings: %s", err)
}

tagName := d.Get("name").(string)
add := make([]string, 0)
add = append(add, tagName)
accessTagType := "access"
createTagOptions := &globaltaggingv1.CreateTagOptions{
TagType: &accessTagType,
TagNames: add,
}
results, _, err := gtClient.CreateTag(createTagOptions)
if err != nil {
return err
}
if results != nil {
errMap := make([]globaltaggingv1.CreateTagResultsResultsItem, 0)
for _, res := range results.Results {
if res.IsError != nil && *res.IsError {
errMap = append(errMap, res)
}
}
if len(errMap) > 0 {
output, err := json.MarshalIndent(errMap, "", " ")
log.Printf("err is %s", err)
return fmt.Errorf("[ERROR] Error while creating access tag(%s) : %s", tagName, string(output))
}
}

d.SetId(tagName)
d.Set(tagType, accessTagType)

return nil
}

func resourceIBMResourceAccessTagRead(d *schema.ResourceData, meta interface{}) error {
tagName := d.Id()
gtClient, err := meta.(conns.ClientSession).GlobalTaggingAPIv1()
if err != nil {
return fmt.Errorf("Error getting global tagging client settings: %s", err)
}
accessTagType := "access"
listTagsOptions := &globaltaggingv1.ListTagsOptions{
TagType: &accessTagType,
}
taggingResult, _, err := gtClient.ListTags(listTagsOptions)
if err != nil {
return err
}

var taglist []string
for _, item := range taggingResult.Items {
taglist = append(taglist, *item.Name)
}
existingAccessTags := flex.NewStringSet(flex.ResourceIBMVPCHash, taglist)
if !existingAccessTags.Contains(tagName) {
d.SetId("")
return nil
}
d.Set("name", tagName)
d.Set(tagType, accessTagType)
return nil
}

func resourceIBMResourceAccessTagDelete(d *schema.ResourceData, meta interface{}) error {

gtClient, err := meta.(conns.ClientSession).GlobalTaggingAPIv1()
if err != nil {
return fmt.Errorf("[ERROR] Error getting global tagging client settings: %s", err)
}
tagName := d.Get("name").(string)
accessTagType := "access"

deleteTagOptions := &globaltaggingv1.DeleteTagOptions{
TagName: &tagName,
TagType: &accessTagType,
}

results, resp, err := gtClient.DeleteTag(deleteTagOptions)

if err != nil {
return fmt.Errorf("[ERROR] Error while deleting access tag(%s) : %v\n%v", tagName, err, resp)
}
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, err := json.MarshalIndent(errMap, "", " ")
log.Printf("err is %s", err)
return fmt.Errorf("[ERROR] Error while deleting access tag(%s) : %s", tagName, string(output))
}
}

d.SetId("")
return nil
}
143 changes: 143 additions & 0 deletions ibm/service/globaltagging/resource_ibm_resource_access_tag_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,143 @@
// Copyright IBM Corp. 2017, 2021 All Rights Reserved.
// Licensed under the Mozilla Public License v2.0

package globaltagging_test

import (
"fmt"
"regexp"
"strings"
"testing"

acc "github.com/IBM-Cloud/terraform-provider-ibm/ibm/acctest"
"github.com/IBM-Cloud/terraform-provider-ibm/ibm/conns"
"github.com/IBM-Cloud/terraform-provider-ibm/ibm/flex"
"github.com/IBM/platform-services-go-sdk/globaltaggingv1"
"github.com/hashicorp/terraform-plugin-sdk/v2/helper/acctest"
"github.com/hashicorp/terraform-plugin-sdk/v2/helper/resource"
"github.com/hashicorp/terraform-plugin-sdk/v2/terraform"
)

const (
accessTagRegex = "^([A-Za-z0-9_.-]|[A-Za-z0-9_.-][A-Za-z0-9_ .-]*[A-Za-z0-9_.-]):([A-Za-z0-9_.-]|[A-Za-z0-9_.-][A-Za-z0-9_ .-]*[A-Za-z0-9_.-])$"
)

func TestAccResourceAccessTag_Basic(t *testing.T) {
name := fmt.Sprintf("tf%d:access%d", acctest.RandIntRange(10, 100), acctest.RandIntRange(10, 100))

resource.Test(t, resource.TestCase{
PreCheck: func() { acc.TestAccPreCheck(t) },
Providers: acc.TestAccProviders,
Steps: []resource.TestStep{

resource.TestStep{
Config: testAccCheckResourceAccessTagCreate(name),
Check: resource.ComposeAggregateTestCheckFunc(
testAccCheckResourceAccessTagExists("ibm_resource_access_tag.tag"),
resource.TestCheckResourceAttr("ibm_resource_access_tag.tag", "id", name),
resource.TestCheckResourceAttr("ibm_resource_access_tag.tag", "name", name),
resource.TestCheckResourceAttr("ibm_resource_access_tag.tag", "tag_type", "access"),
),
},
},
})
}
func TestAccResourceAccessTag_Usage(t *testing.T) {
name := fmt.Sprintf("tf%d: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,
Steps: []resource.TestStep{

resource.TestStep{
Config: testAccCheckResourceAccessTagCreate(name),
Check: resource.ComposeAggregateTestCheckFunc(
testAccCheckResourceAccessTagExists("ibm_resource_access_tag.tag"),
resource.TestCheckResourceAttr("ibm_resource_access_tag.tag", "id", name),
resource.TestCheckResourceAttr("ibm_resource_access_tag.tag", "name", name),
resource.TestCheckResourceAttr("ibm_resource_access_tag.tag", "tag_type", "access"),
),
},
resource.TestStep{
Config: testAccCheckResourceAccessTagUsage(name, sshkeyname, publicKey),
Check: resource.ComposeAggregateTestCheckFunc(
testAccCheckResourceAccessTagExists("ibm_resource_access_tag.tag"),
resource.TestCheckResourceAttr("ibm_resource_access_tag.tag", "id", name),
resource.TestCheckResourceAttr("ibm_resource_access_tag.tag", "name", name),
resource.TestCheckResourceAttr("ibm_resource_access_tag.tag", "tag_type", "access"),
resource.TestCheckResourceAttr("ibm_is_ssh_key.key", "name", sshkeyname),
resource.TestCheckResourceAttrSet("ibm_is_ssh_key.key", "access_tags.#"),
resource.TestCheckResourceAttr("ibm_is_ssh_key.key", "access_tags.0", name),
),
},
},
})
}

func testAccCheckResourceAccessTagExists(n string) resource.TestCheckFunc {
return func(s *terraform.State) error {
var tagName string
rs, ok := s.RootModule().Resources[n]
if !ok {
return fmt.Errorf("Not found: %s", n)
}

accessTagRegex, err := regexp.Compile(accessTagRegex)
if err != nil {
return err
}

if accessTagRegex.MatchString(rs.Primary.ID) {
tagName = rs.Primary.ID
}

gtClient, err := acc.TestAccProvider.Meta().(conns.ClientSession).GlobalTaggingAPIv1()
if err != nil {
return fmt.Errorf("Error getting global tagging client settings: %s", err)
}
accessTagType := "access"
listTagsOptions := &globaltaggingv1.ListTagsOptions{
TagType: &accessTagType,
}
taggingResult, _, err := gtClient.ListTags(listTagsOptions)
if err != nil {
return err
}

var taglist []string
for _, item := range taggingResult.Items {
taglist = append(taglist, *item.Name)
}
existingAccessTags := flex.NewStringSet(flex.ResourceIBMVPCHash, taglist)
if !existingAccessTags.Contains(tagName) {
return fmt.Errorf(
"Error on get of resource tags (%s) : %s", tagName, err)
}
return nil
}
}

func testAccCheckResourceAccessTagCreate(name string) string {
return fmt.Sprintf(`
resource ibm_resource_access_tag tag {
name = "%s"
}
`, name)
}
func testAccCheckResourceAccessTagUsage(name, sshkeyname, publicKey string) string {
return fmt.Sprintf(`
resource ibm_resource_access_tag tag {
name = "%s"
}
resource "ibm_is_ssh_key" "key" {
name = "%s"
public_key = "%s"
access_tags = [ibm_resource_access_tag.tag.name]
}
`, name, sshkeyname, publicKey)
}
2 changes: 1 addition & 1 deletion ibm/service/globaltagging/resource_ibm_resource_tag.go
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
// Copyright IBM Corp. 2017, 2021 All Rights Reserved.
// Copyright IBM Corp. 2017, 2024 All Rights Reserved.
// Licensed under the Mozilla Public License v2.0

package globaltagging
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
// Copyright IBM Corp. 2017, 2021 All Rights Reserved.
// Copyright IBM Corp. 2017, 2024 All Rights Reserved.
// Licensed under the Mozilla Public License v2.0

package globaltagging_test
Expand Down
2 changes: 1 addition & 1 deletion ibm/service/vpc/resource_ibm_is_ssh_key.go
Original file line number Diff line number Diff line change
Expand Up @@ -143,7 +143,7 @@ func ResourceIBMISSSHKey() *schema.Resource {
Type: schema.TypeSet,
Optional: true,
Computed: true,
Elem: &schema.Schema{Type: schema.TypeString, ValidateFunc: validate.InvokeValidator("ibm_is_ssh_key", "accesstag")},
Elem: &schema.Schema{Type: schema.TypeString, ValidateFunc: validate.InvokeValidator("ibm_is_ssh_key", "access_tag")},
Set: flex.ResourceIBMVPCHash,
Description: "List of access management tags for SSH key",
},
Expand Down
Loading

0 comments on commit dc2f51a

Please sign in to comment.