Skip to content

Commit

Permalink
Added support for identifier in ibm_resource_instance (#5147)
Browse files Browse the repository at this point in the history
* Added support for identifier in ibm_resource_instance

* addressed review comment
  • Loading branch information
ujjwal-ibm authored Mar 7, 2024
1 parent c63eccd commit c3adf63
Show file tree
Hide file tree
Showing 3 changed files with 129 additions and 59 deletions.
133 changes: 75 additions & 58 deletions ibm/service/resourcecontroller/data_source_ibm_resource_instance.go
Original file line number Diff line number Diff line change
Expand Up @@ -25,9 +25,18 @@ func DataSourceIBMResourceInstance() *schema.Resource {

Schema: map[string]*schema.Schema{
"name": {
Description: "Resource instance name for example, myobjectstorage",
Type: schema.TypeString,
Required: true,
Description: "Resource instance name for example, myobjectstorage",
Type: schema.TypeString,
Optional: true,
Computed: true,
ExactlyOneOf: []string{"identifier", "name"},
},
"identifier": {
Description: "Resource instance guid",
Type: schema.TypeString,
Optional: true,
ExactlyOneOf: []string{"identifier", "name"},
ConflictsWith: []string{"resource_group_id", "name", "location", "service"},
},

"resource_group_id": {
Expand Down Expand Up @@ -162,83 +171,91 @@ func getInstancesNext(next *string) (string, error) {
}

func DataSourceIBMResourceInstanceRead(d *schema.ResourceData, meta interface{}) error {
name := d.Get("name").(string)
var instance rc.ResourceInstance
rsConClient, err := meta.(conns.ClientSession).ResourceControllerV2API()
if err != nil {
return err
}

resourceInstanceListOptions := rc.ListResourceInstancesOptions{
Name: &name,
}

if rsGrpID, ok := d.GetOk("resource_group_id"); ok {
rg := rsGrpID.(string)
resourceInstanceListOptions.ResourceGroupID = &rg
}

rsCatClient, err := meta.(conns.ClientSession).ResourceCatalogAPI()
if err != nil {
return err
}
rsCatRepo := rsCatClient.ResourceCatalog()

if service, ok := d.GetOk("service"); ok {

serviceOff, err := rsCatRepo.FindByName(service.(string), true)
if err != nil {
return fmt.Errorf("[ERROR] Error retrieving service offering: %s", err)
if _, ok := d.GetOk("name"); ok {
name := d.Get("name").(string)
resourceInstanceListOptions := rc.ListResourceInstancesOptions{
Name: &name,
}
resourceId := serviceOff[0].ID
resourceInstanceListOptions.ResourceID = &resourceId
}

next_url := ""
var instances []rc.ResourceInstance
for {
if next_url != "" {
resourceInstanceListOptions.Start = &next_url
}
listInstanceResponse, resp, err := rsConClient.ListResourceInstances(&resourceInstanceListOptions)
if err != nil {
return fmt.Errorf("[ERROR] Error retrieving resource instance: %s with resp code: %s", err, resp)
if rsGrpID, ok := d.GetOk("resource_group_id"); ok {
rg := rsGrpID.(string)
resourceInstanceListOptions.ResourceGroupID = &rg
}
next_url, err = getInstancesNext(listInstanceResponse.NextURL)
if err != nil {
return fmt.Errorf("[DEBUG] ListResourceInstances failed. Error occurred while parsing NextURL: %s", err)

if service, ok := d.GetOk("service"); ok {

serviceOff, err := rsCatRepo.FindByName(service.(string), true)
if err != nil {
return fmt.Errorf("[ERROR] Error retrieving service offering: %s", err)
}
resourceId := serviceOff[0].ID
resourceInstanceListOptions.ResourceID = &resourceId
}
instances = append(instances, listInstanceResponse.Resources...)
if next_url == "" {
break
}
}

var filteredInstances []rc.ResourceInstance
var location string
next_url := ""
var instances []rc.ResourceInstance
for {
if next_url != "" {
resourceInstanceListOptions.Start = &next_url
}
listInstanceResponse, resp, err := rsConClient.ListResourceInstances(&resourceInstanceListOptions)
if err != nil {
return fmt.Errorf("[ERROR] Error retrieving resource instance: %s with resp code: %s", err, resp)
}
next_url, err = getInstancesNext(listInstanceResponse.NextURL)
if err != nil {
return fmt.Errorf("[DEBUG] ListResourceInstances failed. Error occurred while parsing NextURL: %s", err)

if loc, ok := d.GetOk("location"); ok {
location = loc.(string)
for _, instance := range instances {
if flex.GetLocationV2(instance) == location {
filteredInstances = append(filteredInstances, instance)
}
instances = append(instances, listInstanceResponse.Resources...)
if next_url == "" {
break
}
}
} else {
filteredInstances = instances
}

if len(filteredInstances) == 0 {
return fmt.Errorf("[ERROR] No resource instance found with name [%s]\nIf not specified please specify more filters like resource_group_id if instance doesn't exists in default group, location or service", name)
}
var filteredInstances []rc.ResourceInstance
var location string

var instance rc.ResourceInstance
if loc, ok := d.GetOk("location"); ok {
location = loc.(string)
for _, instance := range instances {
if flex.GetLocationV2(instance) == location {
filteredInstances = append(filteredInstances, instance)
}
}
} else {
filteredInstances = instances
}

if len(filteredInstances) > 1 {
return fmt.Errorf("[ERROR] More than one resource instance found with name matching [%s]\nIf not specified please specify more filters like resource_group_id if instance doesn't exists in default group, location or service", name)
if len(filteredInstances) == 0 {
return fmt.Errorf("[ERROR] No resource instance found with name [%s]\nIf not specified please specify more filters like resource_group_id if instance doesn't exists in default group, location or service", name)
}
if len(filteredInstances) > 1 {
return fmt.Errorf("[ERROR] More than one resource instance found with name matching [%s]\nIf not specified please specify more filters like resource_group_id if instance doesn't exists in default group, location or service", name)
}
instance = filteredInstances[0]
} else if _, ok := d.GetOk("identifier"); ok {
instanceGUID := d.Get("identifier").(string)
getResourceInstanceOptions := &rc.GetResourceInstanceOptions{
ID: &instanceGUID,
}
instances, res, err := rsConClient.GetResourceInstance(getResourceInstanceOptions)
if err != nil {
return fmt.Errorf("[ERROR] No resource instance found with id [%s\n%v]", instanceGUID, res)
}
instance = *instances
d.Set("name", instance.Name)
}
instance = filteredInstances[0]

d.SetId(*instance.ID)
d.Set("status", instance.State)
d.Set("resource_group_id", instance.ResourceGroupID)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -62,6 +62,29 @@ func TestAccIBMResourceInstanceDataSource_basic(t *testing.T) {
},
})
}
func TestAccIBMResourceInstanceDataSource_identifier(t *testing.T) {
instanceName := fmt.Sprintf("terraform_%d", acctest.RandIntRange(10, 100))

resource.Test(t, resource.TestCase{
PreCheck: func() { acc.TestAccPreCheck(t) },
Providers: acc.TestAccProviders,
Steps: []resource.TestStep{
{
Config: testAccCheckIBMResourceInstanceDataSourceIdentifierConfig(instanceName),
Check: resource.ComposeTestCheckFunc(
resource.TestCheckResourceAttr("data.ibm_resource_instance.testacc_ds_resource_instance", "name", instanceName),
resource.TestCheckResourceAttr("data.ibm_resource_instance.testacc_ds_resource_instance", "service", "cloud-object-storage"),
resource.TestCheckResourceAttr("data.ibm_resource_instance.testacc_ds_resource_instance", "plan", "standard"),
resource.TestCheckResourceAttr("data.ibm_resource_instance.testacc_ds_resource_instance", "location", "global"),
resource.TestCheckResourceAttr("data.ibm_resource_instance.testacc_ds_resource_instance_identifier", "name", instanceName),
resource.TestCheckResourceAttr("data.ibm_resource_instance.testacc_ds_resource_instance_identifier", "service", "cloud-object-storage"),
resource.TestCheckResourceAttr("data.ibm_resource_instance.testacc_ds_resource_instance_identifier", "plan", "standard"),
resource.TestCheckResourceAttr("data.ibm_resource_instance.testacc_ds_resource_instance_identifier", "location", "global"),
),
},
},
})
}

func setupResourceInstanceConfig(instanceName string, instanceName2 string) string {
return fmt.Sprintf(`
Expand Down Expand Up @@ -118,6 +141,31 @@ data "ibm_resource_instance" "testacc_ds_resource_instance" {
}
`, instanceName, instanceName)

}
func testAccCheckIBMResourceInstanceDataSourceIdentifierConfig(instanceName string) string {
return fmt.Sprintf(`
data "ibm_resource_group" "group" {
is_default=true
}
resource "ibm_resource_instance" "instance" {
name = "%s"
service = "cloud-object-storage"
plan = "standard"
location = "global"
}
data "ibm_resource_instance" "testacc_ds_resource_instance" {
name = ibm_resource_instance.instance.name
location = "global"
resource_group_id = data.ibm_resource_group.group.id
}
data "ibm_resource_instance" "testacc_ds_resource_instance_identifier" {
identifier = ibm_resource_instance.instance.id
}
`, instanceName)

}

func testAccCheckIBMResourceInstanceDataSourceConfigWithService(instanceName string) string {
Expand Down
7 changes: 6 additions & 1 deletion website/docs/d/resource_instance.html.markdown
Original file line number Diff line number Diff line change
Expand Up @@ -23,14 +23,19 @@ data "ibm_resource_instance" "testacc_ds_resource_instance" {
resource_group_id = data.ibm_resource_group.group.id
service = "cloud-object-storage"
}
data "ibm_resource_instance" "testacc_ds_resource_instance_identifier" {
identifier = ibm_resource_instance.instance.id
}
```

## Argument reference

The following arguments are supported:

- `identifier` - The GUID of the resource instance. Conflicts with other arguments.

- `location` - (Optional, String) The location or the environment in which the instance exists.
- `name` - (Required, String) The name of the resource instance.
- `name` - (Optional, String) The name of the resource instance.
- `resource_group_id` - (Optional, String) The ID of the resource group where the resource instance exists. If not provided it takes the default resource group.
- `service` - (Optional, String) The service type of the instance. You can retrieve the value by executing the `ibmcloud catalog service-marketplace` or `ibmcloud catalog search` command in the [IBM Cloud CLI](https://cloud.ibm.com/docs/cli?topic=cloud-cli-getting-started).

Expand Down

0 comments on commit c3adf63

Please sign in to comment.