Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: added support for importing cloudfoundry_org_roles #226

Merged
merged 2 commits into from
Jan 16, 2025
Merged
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
4 changes: 4 additions & 0 deletions pkg/output/format.go
Original file line number Diff line number Diff line change
Expand Up @@ -17,3 +17,7 @@ func FormatSubscriptionResourceName(appName string, planName string) string {
func FormatServiceInstanceResourceName(serviceInstanceName string, planId string) string {
return serviceInstanceName + "_" + planId
}

func FormatOrgRoleResourceName(orgRoleType string, userId string) string {
return orgRoleType + "_" + userId
}
70 changes: 70 additions & 0 deletions pkg/tfimportprovider/cloudFoundryOrgRoleImportProvider.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,70 @@
package tfimportprovider

import (
"fmt"
"log"
"slices"
"strings"

"github.com/SAP/terraform-exporter-btp/pkg/output"
tfutils "github.com/SAP/terraform-exporter-btp/pkg/tfutils"
)

type cloudfoundryOrgRolesImportProvider struct {
TfImportProvider
}

func newCloudfoundryOrgRolesImportProvider() ITfImportProvider {
return &cloudfoundryOrgRolesImportProvider{
TfImportProvider: TfImportProvider{
resourceType: tfutils.CfOrgRoleType,
},
}
}

func (tf *cloudfoundryOrgRolesImportProvider) GetImportBlock(data map[string]interface{}, levelId string, filterValues []string) (string, int, error) {
count := 0
orgId := levelId
resourceDoc, err := tfutils.GetDocByResourceName(tfutils.ResourcesKind, tfutils.CfOrgRoleType, tfutils.OrganizationLevel)
if err != nil {
fmt.Print("\r\n")
log.Fatalf("read doc failed!")
return "", count, err
}
importBlock, count, err := createOrgRoleImportBlock(data, orgId, filterValues, resourceDoc)
if err != nil {
return "", count, err
}
return importBlock, count, nil
}
func createOrgRoleImportBlock(data map[string]interface{}, orgId string, filterValues []string, resourceDoc tfutils.EntityDocs) (importBlock string, count int, err error) {
count = 0
roles := data["roles"].([]interface{})
if len(filterValues) != 0 {
var cfAllOrgRoles []string
for x, value := range roles {
role := value.(map[string]interface{})
cfAllOrgRoles = append(cfAllOrgRoles, output.FormatOrgRoleResourceName(fmt.Sprintf("%v", role["type"]), fmt.Sprintf("%v", role["user"])))
if slices.Contains(filterValues, output.FormatOrgRoleResourceName(fmt.Sprintf("%v", role["type"]), fmt.Sprintf("%v", role["user"]))) {
importBlock += templateOrgRoleImport(x, role, resourceDoc)
count++
}
}
missingRole, subset := isSubset(cfAllOrgRoles, filterValues)
if !subset {
return "", 0, fmt.Errorf("cloud foudndry org role %s not found in the organization with ID %s. Please adjust it in the provided file", missingRole, orgId)
}
} else {
for x, value := range roles {
role := value.(map[string]interface{})
importBlock += templateOrgRoleImport(x, role, resourceDoc)
count++
}
}
return importBlock, count, nil
}
func templateOrgRoleImport(x int, role map[string]interface{}, resourceDoc tfutils.EntityDocs) string {
template := strings.Replace(resourceDoc.Import, "<resource_name>", "role_"+fmt.Sprintf("%v", role["type"])+"_"+fmt.Sprintf("%v", x), -1)
template = strings.Replace(template, "<role_guid>", fmt.Sprintf("%v", role["id"]), -1)
return template + "\n"
}
72 changes: 72 additions & 0 deletions pkg/tfimportprovider/cloudFoundryOrgRoleImportProvider_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,72 @@
package tfimportprovider

import (
"testing"

tfutils "github.com/SAP/terraform-exporter-btp/pkg/tfutils"
"github.com/stretchr/testify/assert"
)

func TestCreateCfOrgRoleImportBlock(t *testing.T) {
resourceDoc := tfutils.EntityDocs{
Import: "import {\n\t\t\t\tto = cloudfoundry_org_role.<resource_name>\n\t\t\t\tid = \"<role_guid>\"\"\n\t\t\t }\n",
}

jsonString := "{\"org\":\"12345\",\"roles\": [{\"created_at\":\"2024-10-22T19:52:23Z\",\"id\":\"34567\",\"org\":\"12345\",\"type\":\"organization_user\",\"updated_at\":\"2024-10-22T19:52:23Z\",\"user\":\"56789\"}],\"type\": null,\"user\": null}"
dataOrgRoles, _ := GetDataFromJsonString(jsonString)

jsonStringMultipleOrgRoles := "{\"org\":\"12345\",\"roles\": [{\"created_at\":\"2024-10-22T19:52:23Z\",\"id\":\"34567\",\"org\":\"12345\",\"type\":\"organization_user\",\"updated_at\":\"2024-10-22T19:52:23Z\",\"user\":\"56789\"}, {\"created_at\":\"2024-10-22T19:52:23Z\",\"id\":\"45678\",\"org\":\"12345\",\"type\":\"organization_manager\",\"updated_at\":\"2024-10-22T19:52:23Z\",\"user\":\"56789\"}],\"type\": null,\"user\": null}"
dataMultipleOrgRoles, _ := GetDataFromJsonString(jsonStringMultipleOrgRoles)

tests := []struct {
name string
data map[string]interface{}
orgId string
filterValues []string
expectedBlock string
expectedCount int
expectError bool
}{

{
name: "Valid data without filter",
data: dataOrgRoles,
orgId: "12345",
filterValues: []string{},
expectedBlock: "import {\n\t\t\t\tto = cloudfoundry_org_role.role_organization_user_0\n\t\t\t\tid = \"34567\"\"\n\t\t\t }\n\n",
expectedCount: 1,
expectError: false,
},
{
name: "Valid data with matching filter",
data: dataMultipleOrgRoles,
orgId: "12345",
filterValues: []string{"organization_user_56789"},
expectedBlock: "import {\n\t\t\t\tto = cloudfoundry_org_role.role_organization_user_0\n\t\t\t\tid = \"34567\"\"\n\t\t\t }\n\n",
expectedCount: 1,
expectError: false,
},
{
name: "Invalid filter value",
data: dataOrgRoles,
orgId: "12345",
filterValues: []string{"wrong-org-role"},
expectedBlock: "",
expectedCount: 0,
expectError: true,
},
}

for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
importBlock, count, err := createOrgRoleImportBlock(tt.data, tt.orgId, tt.filterValues, resourceDoc)
if tt.expectError {
assert.Error(t, err)
} else {
assert.NoError(t, err)
assert.Equal(t, tt.expectedBlock, importBlock)
assert.Equal(t, tt.expectedCount, count)
}
})
}
}
2 changes: 2 additions & 0 deletions pkg/tfimportprovider/tfImportProviderFactory.go
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,8 @@ func GetImportBlockProvider(cmdResourceName string, level string) (ITfImportProv
return newcloudfoundryUserImportProvider(), nil
case tfutils.CmdCfDomainParamater:
return newCloudfoundryDomainImportProvider(), nil
case tfutils.CmdCfOrgRoleParameter:
return newCloudfoundryOrgRolesImportProvider(), nil
case tfutils.CmdCfRouteParameter:
return newCloudfoundryRouteImportProvider(), nil
case tfutils.CmdCfSpaceQuotaParameter:
Expand Down
1 change: 1 addition & 0 deletions pkg/tfutils/tfConfig.go
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,7 @@ var AllowedResourcesOrganization = []string{
CmdCfSpaceParameter,
CmdCfUserParameter,
CmdCfDomainParamater,
CmdCfOrgRoleParameter,
CmdCfRouteParameter,
CmdCfSpaceQuotaParameter,
CmdCfServiceInstanceParameter,
Expand Down
14 changes: 14 additions & 0 deletions pkg/tfutils/tfImport.go
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,7 @@ const (
CmdCfSpaceParameter string = "spaces"
CmdCfUserParameter string = "users"
CmdCfDomainParamater string = "domains"
CmdCfOrgRoleParameter string = "org-roles"
CmdCfRouteParameter string = "routes"
CmdCfSpaceQuotaParameter string = "space-quotas"
CmdCfServiceInstanceParameter string = "cf-service-instances"
Expand Down Expand Up @@ -70,6 +71,7 @@ const (
const (
CfSpaceType string = "cloudfoundry_space"
CfUserType string = "cloudfoundry_user"
CfOrgRoleType string = "cloudfoundry_org_role"
CfDomainType string = "cloudfoundry_domain"
CfRouteType string = "cloudfoundry_route"
CfSpaceQuotaType string = "cloudfoundry_space_quota"
Expand Down Expand Up @@ -189,6 +191,8 @@ func TranslateResourceParamToTechnicalName(resource string, level string) string
return CfUserType
case CmdCfDomainParamater:
return CfDomainType
case CmdCfOrgRoleParameter:
return CfOrgRoleType
case CmdCfRouteParameter:
return CfRouteType
case CmdCfSpaceQuotaParameter:
Expand Down Expand Up @@ -385,6 +389,8 @@ func transformDataToStringArray(btpResource string, data map[string]interface{})
transformDataToStringArrayGeneric(data, &stringArr, "users", "username")
case CfDomainType:
transformDataToStringArrayGeneric(data, &stringArr, "domains", "name")
case CfOrgRoleType:
transformOrgRolesStringArray(data, &stringArr)
case CfRouteType:
transformDataToStringArrayGeneric(data, &stringArr, "routes", "url")
case CfSpaceQuotaType:
Expand Down Expand Up @@ -539,6 +545,14 @@ func transformSubscriptionsStringArray(data map[string]interface{}, stringArr *[
}
}

func transformOrgRolesStringArray(data map[string]interface{}, stringArr *[]string) {
roles := data["roles"].([]interface{})
for _, value := range roles {
role := value.(map[string]interface{})
*stringArr = append(*stringArr, output.FormatOrgRoleResourceName(fmt.Sprintf("%v", role["type"]), fmt.Sprintf("%v", role["user"])))
}
}

func transformCfServiceInstanceStringArray(data map[string]interface{}, stringArr *[]string) {
instances := data["service_instances"].([]interface{})
for _, value := range instances {
Expand Down
Loading