Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion .github/workflows/release.yml
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,7 @@ jobs:
passphrase: ${{ secrets.PASSPHRASE }}
-
name: Run GoReleaser
uses: goreleaser/goreleaser-action@v3
uses: goreleaser/goreleaser-action@v4
with:
version: latest
args: release --rm-dist
Expand Down
75 changes: 75 additions & 0 deletions ibm/flex/structures.go
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,7 @@ import (
"github.com/IBM-Cloud/bluemix-go/api/usermanagement/usermanagementv2"
"github.com/IBM/platform-services-go-sdk/iamaccessgroupsv2"
"github.com/IBM/platform-services-go-sdk/iamidentityv1"
rc "github.com/IBM/platform-services-go-sdk/resourcecontrollerv2"
)

const (
Expand Down Expand Up @@ -79,6 +80,14 @@ const (
isLBProfile = "profile"
isLBRouteMode = "route_mode"
isLBType = "type"
crnSeparator = ":"
scopeSeparator = "/"
crn = "crn"
)

var (
ErrMalformedCRN = errors.New("malformed CRN")
ErrMalformedScope = errors.New("malformed scope in CRN")
)

// HashInt ...
Expand Down Expand Up @@ -1948,6 +1957,72 @@ func GetLocation(instance models.ServiceInstanceV2) string {
}
}

type CRN struct {
Scheme string
Version string
CName string
CType string
ServiceName string
Region string
ScopeType string
Scope string
ServiceInstance string
ResourceType string
Resource string
}

func Parse(s string) (CRN, error) {
if s == "" {
return CRN{}, nil
}

segments := strings.Split(s, crnSeparator)
if len(segments) != 10 || segments[0] != crn {
return CRN{}, ErrMalformedCRN
}

crn := CRN{
Scheme: segments[0],
Version: segments[1],
CName: segments[2],
CType: segments[3],
ServiceName: segments[4],
Region: segments[5],
ServiceInstance: segments[7],
ResourceType: segments[8],
Resource: segments[9],
}

scopeSegments := segments[6]
if scopeSegments != "" {
if scopeSegments == "global" {
crn.Scope = "global"
} else {
scopeParts := strings.Split(scopeSegments, scopeSeparator)
if len(scopeParts) == 2 {
crn.ScopeType, crn.Scope = scopeParts[0], scopeParts[1]
} else {
return CRN{}, ErrMalformedScope
}
}
}

return crn, nil
}
func GetLocationV2(instance rc.ResourceInstance) string {
crn, err := Parse(*instance.CRN)
if err != nil {
log.Fatal(err)
}
region := crn.Region
cName := crn.CName
if cName == "bluemix" || cName == "staging" {
return region
} else {
return cName + "-" + region
}
}

func GetTags(d *schema.ResourceData, meta interface{}) error {
resourceID := d.Id()
gtClient, err := meta.(conns.ClientSession).GlobalTaggingAPI()
Expand Down
97 changes: 66 additions & 31 deletions ibm/service/resourcecontroller/data_source_ibm_resource_instance.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,11 +6,13 @@ package resourcecontroller
import (
"fmt"
"log"
"net/url"
"reflect"

rc "github.com/IBM/platform-services-go-sdk/resourcecontrollerv2"
rg "github.com/IBM/platform-services-go-sdk/resourcemanagerv2"
"github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema"

"github.com/IBM-Cloud/bluemix-go/api/resource/resourcev2/controllerv2"
"github.com/IBM-Cloud/bluemix-go/models"
"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"
Expand Down Expand Up @@ -140,27 +142,32 @@ func DataSourceIBMResourceInstanceValidator() *validate.ResourceValidator {
ibmIBMResourceInstanceValidator := validate.ResourceValidator{ResourceName: "ibm_resource_instance", Schema: validateSchema}
return &ibmIBMResourceInstanceValidator
}
func getInstancesNext(next *string) (string, error) {
if reflect.ValueOf(next).IsNil() {
return "", nil
}
u, err := url.Parse(*next)
if err != nil {
return "", err
}
q := u.Query()
return q.Get("next_url"), nil
}

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

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

if rsGrpID, ok := d.GetOk("resource_group_id"); ok {
rsInstQuery.ResourceGroupID = rsGrpID.(string)
} else {
defaultRg, err := flex.DefaultResourceGroup(meta)
if err != nil {
return err
}
rsInstQuery.ResourceGroupID = defaultRg
rg := rsGrpID.(string)
resourceInstanceListOptions.ResourceGroupID = &rg
}

rsCatClient, err := meta.(conns.ClientSession).ResourceCatalogAPI()
Expand All @@ -175,23 +182,38 @@ func DataSourceIBMResourceInstanceRead(d *schema.ResourceData, meta interface{})
if err != nil {
return fmt.Errorf("[ERROR] Error retrieving service offering: %s", err)
}

rsInstQuery.ServiceID = serviceOff[0].ID
resourceId := serviceOff[0].ID
resourceInstanceListOptions.ResourceID = &resourceId
}

var instances []models.ServiceInstanceV2
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)

instances, err = rsAPI.ListInstances(rsInstQuery)
if err != nil {
return err
}
instances = append(instances, listInstanceResponse.Resources...)
if next_url == "" {
break
}
}
var filteredInstances []models.ServiceInstanceV2

var filteredInstances []rc.ResourceInstance
var location string

if loc, ok := d.GetOk("location"); ok {
location = loc.(string)
for _, instance := range instances {
if flex.GetLocation(instance) == location {
if flex.GetLocationV2(instance) == location {
filteredInstances = append(filteredInstances, instance)
}
}
Expand All @@ -203,29 +225,42 @@ func DataSourceIBMResourceInstanceRead(d *schema.ResourceData, meta interface{})
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 instance models.ServiceInstanceV2
var instance rc.ResourceInstance

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]

d.SetId(instance.ID)
d.SetId(*instance.ID)
d.Set("status", instance.State)
d.Set("resource_group_id", instance.ResourceGroupID)
d.Set("location", instance.RegionID)
serviceOff, err := rsCatRepo.GetServiceName(instance.ServiceID)
serviceOff, err := rsCatRepo.GetServiceName(*instance.ResourceID)
if err != nil {
return fmt.Errorf("[ERROR] Error retrieving service offering: %s", err)
}

d.Set("service", serviceOff)

d.Set(flex.ResourceName, instance.Name)
d.Set(flex.ResourceCRN, instance.Crn.String())
d.Set(flex.ResourceCRN, instance.CRN)
d.Set(flex.ResourceStatus, instance.State)
d.Set(flex.ResourceGroupName, instance.ResourceGroupName)
d.Set("guid", instance.Guid)
rMgtClient, err := meta.(conns.ClientSession).ResourceManagerV2API()
if err != nil {
return err
}
GetResourceGroup := rg.GetResourceGroupOptions{
ID: instance.ResourceGroupID,
}
resourceGroup, resp, err := rMgtClient.GetResourceGroup(&GetResourceGroup)
if err != nil || resourceGroup == nil {
log.Printf("[ERROR] Error retrieving resource group: %s %s", err, resp)
}
if resourceGroup != nil && resourceGroup.Name != nil {
d.Set(flex.ResourceGroupName, resourceGroup.Name)
}
d.Set("guid", instance.GUID)
if len(instance.Extensions) == 0 {
d.Set("extensions", instance.Extensions)
} else {
Expand All @@ -238,13 +273,13 @@ func DataSourceIBMResourceInstanceRead(d *schema.ResourceData, meta interface{})
}
d.Set(flex.ResourceControllerURL, rcontroller+"/services/")

servicePlan, err := rsCatRepo.GetServicePlanName(instance.ResourcePlanID)
servicePlan, err := rsCatRepo.GetServicePlanName(*instance.ResourcePlanID)
if err != nil {
return fmt.Errorf("[ERROR] Error retrieving plan: %s", err)
}
d.Set("plan", servicePlan)
d.Set("crn", instance.Crn.String())
tags, err := flex.GetTagsUsingCRN(meta, instance.Crn.String())
d.Set("crn", instance.CRN)
tags, err := flex.GetTagsUsingCRN(meta, *instance.CRN)
if err != nil {
log.Printf(
"Error on get of resource instance tags (%s) tags: %s", d.Id(), err)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ import (

"github.com/IBM-Cloud/terraform-provider-ibm/ibm/conns"
"github.com/IBM-Cloud/terraform-provider-ibm/ibm/validate"
rc "github.com/IBM/platform-services-go-sdk/resourcecontrollerv2"
"github.com/IBM/secrets-manager-go-sdk/secretsmanagerv1"
"github.com/hashicorp/terraform-plugin-sdk/v2/diag"
"github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema"
Expand Down Expand Up @@ -253,24 +254,23 @@ func dataSourceIBMSecretsManagerSecretRead(context context.Context, d *schema.Re
if err != nil {
return diag.FromErr(err)
}
rContollerClient, err := meta.(conns.ClientSession).ResourceControllerAPIV2()
rsConClient, err := meta.(conns.ClientSession).ResourceControllerV2API()
if err != nil {
return diag.FromErr(err)
}

instanceID := d.Get("instance_id").(string)
endpointType := d.Get("endpoint_type").(string)
var smEndpointURL string

rContollerAPI := rContollerClient.ResourceServiceInstanceV2()

instanceData, err := rContollerAPI.GetInstance(instanceID)
resourceInstanceOptions := rc.GetResourceInstanceOptions{
ID: &instanceID,
}
instanceData, resp, err := rsConClient.GetResourceInstance(&resourceInstanceOptions)
if err != nil {
return diag.FromErr(err)
return diag.FromErr(fmt.Errorf("[ERROR] Error:%s Response: %s", err, resp))
}
instanceCRN := instanceData.Crn.String()
instanceCRN := instanceData.CRN

crnData := strings.Split(instanceCRN, ":")
crnData := strings.Split(*instanceCRN, ":")

if crnData[4] == "secrets-manager" {
if endpointType == "private" {
Expand Down