diff --git a/CHANGELOG.md b/CHANGELOG.md index 0ebdb7cd740..99dad9ad51d 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -19,6 +19,7 @@ FEATURES: * **New Data Source:** `huaweicloud_kms_key_v1` * **New Data Source:** `huaweicloud_kms_data_key_v1` * **New Data Source:** `huaweicloud_rds_flavors_v1` +* **New Data Source:** `huaweicloud_iam_role_v3` * **New Resource:** `huaweicloud_blockstorage_volume_v2` * **New Resource:** `huaweicloud_compute_instance_v2` * **New Resource:** `huaweicloud_compute_keypair_v2` @@ -58,3 +59,4 @@ FEATURES: * **New Resource:** `huaweicloud_rds_instance_v1` * **New Resource:** `huaweicloud_nat_gateway_v2` * **New Resource:** `huaweicloud_nat_snat_rule_v2` +* **New Resource:** `huaweicloud_iam_agency_v3` diff --git a/huaweicloud/data_source_huaweicloud_iam_role_v3.go b/huaweicloud/data_source_huaweicloud_iam_role_v3.go new file mode 100644 index 00000000000..b99bf45c14b --- /dev/null +++ b/huaweicloud/data_source_huaweicloud_iam_role_v3.go @@ -0,0 +1,138 @@ +package huaweicloud + +import ( + "fmt" + "log" + + "github.com/hashicorp/terraform/helper/schema" + "github.com/huaweicloud/golangsdk" + sdkroles "github.com/huaweicloud/golangsdk/openstack/identity/v3/roles" +) + +func dataSourceIAMRoleV3() *schema.Resource { + return &schema.Resource{ + Read: dataSourceIAMRoleV3Read, + + Schema: map[string]*schema.Schema{ + "projects": &schema.Schema{ + Type: schema.TypeMap, + Computed: true, + }, + "domains": &schema.Schema{ + Type: schema.TypeMap, + Computed: true, + }, + "project_domains": &schema.Schema{ + Type: schema.TypeMap, + Computed: true, + }, + "others": &schema.Schema{ + Type: schema.TypeMap, + Computed: true, + }, + }, + } +} + +func dataSourceIAMRoleV3Read(d *schema.ResourceData, meta interface{}) error { + config := meta.(*Config) + client, err := agencyClient(d, config) + if err != nil { + return fmt.Errorf("Error creating HuaweiCloud client: %s", err) + } + + domainID, err := getDomainID(config, client) + if err != nil { + return fmt.Errorf("Error getting the domain id, err=%s", err) + + } + + roles, err := dsAllRolesOfDomain(domainID, client) + if err != nil { + return err + } + if roles != nil { + d.Set("projects", roles["XA"]) + d.Set("domains", roles["AX"]) + d.Set("project_domains", roles["AA"]) + d.Set("others", roles["XX"]) + } + d.SetId("roles") + return nil +} + +func dsListRolesOfDomain(domainID string, client *golangsdk.ServiceClient) (map[string]map[string]string, error) { + old := client.Endpoint + defer func() { client.Endpoint = old }() + client.Endpoint = "https://iam.myhwclouds.com:443/v3/" + + opts := sdkroles.ListOpts{ + DomainID: domainID, + } + allPages, err := sdkroles.List(client, &opts).AllPages() + if err != nil { + return nil, fmt.Errorf("List roles failed, err=%s", err) + } + + all, err := sdkroles.ExtractRoles(allPages) + if err != nil { + return nil, fmt.Errorf("Extract roles failed, err=%s", err) + } + if len(all) == 0 { + return nil, nil + } + + r := map[string]map[string]string{ + "AX": make(map[string]string, 0), + "XA": make(map[string]string, 0), + "AA": make(map[string]string, 0), + "XX": make(map[string]string, 0), + } + for _, item := range all { + rtype, ok := item.Extra["type"].(string) + if !ok { + log.Printf("[DEBUG] Can not retrieve type of role:%#v", item) + continue + } + + dn, ok := item.Extra["display_name"].(string) + if !ok { + log.Printf("[DEBUG] Can not retrieve name ofrole:%#v", item) + continue + } + + desc, ok := item.Extra["description"].(string) + if !ok { + log.Printf("[DEBUG] Can not retrieve description of role:%#v", item) + continue + } + + r[rtype][dn] = desc + } + return r, nil +} + +func dsAllRolesOfDomain(domainID string, client *golangsdk.ServiceClient) (map[string]map[string]string, error) { + roles, err := dsListRolesOfDomain("", client) + if err != nil { + return nil, fmt.Errorf("Error listing global roles, err=%s", err) + } + + customRoles, err := dsListRolesOfDomain(domainID, client) + if err != nil { + return nil, fmt.Errorf("Error listing domain's custom roles, err=%s", err) + } + + if customRoles == nil { + return roles, nil + } + if roles == nil { + return customRoles, nil + } + for k, v := range customRoles { + for k1, v1 := range v { + roles[k][k1] = v1 + } + } + return roles, nil +} diff --git a/huaweicloud/data_source_huaweicloud_iam_role_v3_test.go b/huaweicloud/data_source_huaweicloud_iam_role_v3_test.go new file mode 100644 index 00000000000..be0a0be3d50 --- /dev/null +++ b/huaweicloud/data_source_huaweicloud_iam_role_v3_test.go @@ -0,0 +1,28 @@ +package huaweicloud + +import ( + "testing" + + "github.com/hashicorp/terraform/helper/resource" +) + +func TestAccIAMRoleV3DataSource_basic(t *testing.T) { + resource.Test(t, resource.TestCase{ + PreCheck: func() { testAccPreCheck(t) }, + Providers: testAccProviders, + Steps: []resource.TestStep{ + resource.TestStep{ + Config: testAccIAMRoleV3DataSource_basic, + Check: resource.ComposeTestCheckFunc( + resource.TestCheckResourceAttrSet( + "data.huaweicloud_iam_role_v3.roles", "id"), + ), + }, + }, + }) +} + +const testAccIAMRoleV3DataSource_basic = ` +data "huaweicloud_iam_role_v3" "roles" { +} +` diff --git a/huaweicloud/provider.go b/huaweicloud/provider.go index 08fdc654d85..31982220cdd 100644 --- a/huaweicloud/provider.go +++ b/huaweicloud/provider.go @@ -200,6 +200,7 @@ func Provider() terraform.ResourceProvider { "huaweicloud_sfs_file_system_v2": dataSourceSFSFileSystemV2(), "huaweicloud_rts_stack_v1": dataSourceRTSStackV1(), "huaweicloud_rts_stack_resource_v1": dataSourceRTSStackResourcesV1(), + "huaweicloud_iam_role_v3": dataSourceIAMRoleV3(), }, ResourcesMap: map[string]*schema.Resource{ diff --git a/huaweicloud/resource_huaweicloud_iam_agency_v3.go b/huaweicloud/resource_huaweicloud_iam_agency_v3.go index 8122676c518..063836fb35e 100644 --- a/huaweicloud/resource_huaweicloud_iam_agency_v3.go +++ b/huaweicloud/resource_huaweicloud_iam_agency_v3.go @@ -69,7 +69,7 @@ func resourceIAMAgencyV3() *schema.Resource { Optional: true, Elem: &schema.Resource{ Schema: map[string]*schema.Schema{ - "roles": { + "roles": &schema.Schema{ Type: schema.TypeSet, Required: true, MinItems: 1, @@ -77,7 +77,7 @@ func resourceIAMAgencyV3() *schema.Resource { Elem: &schema.Schema{Type: schema.TypeString}, Set: schema.HashString, }, - "project": { + "project": &schema.Schema{ Type: schema.TypeString, Required: true, }, @@ -186,20 +186,23 @@ func allRolesOfDomain(domainID string, client *golangsdk.ServiceClient) (map[str if err != nil { return nil, fmt.Errorf("Error listing global roles, err=%s", err) } - if roles == nil { - roles = map[string]string{} - } customRoles, err := listRolesOfDomain(domainID, client) if err != nil { return nil, fmt.Errorf("Error listing domain's custom roles, err=%s", err) } - if customRoles != nil { - for k, v := range customRoles { - roles[k] = v - } + + if roles == nil { + return customRoles, nil + } + + if customRoles == nil { + return roles, nil } + for k, v := range customRoles { + roles[k] = v + } return roles, nil } diff --git a/website/docs/d/iam_role_v3.html.markdown b/website/docs/d/iam_role_v3.html.markdown new file mode 100644 index 00000000000..555da1e9a27 --- /dev/null +++ b/website/docs/d/iam_role_v3.html.markdown @@ -0,0 +1,40 @@ +--- +layout: "huaweicloud" +page_title: "HuaweiCloud: huaweicloud_iam_role_v3" +sidebar_current: "docs-huaweicloud-datasource-iam-role-v3" +description: |- + Get all the IAM roles including global and a domain's custom ones. +--- + +# huaweicloud\_iam\_role_v3 + +Use this data source to get all the IAM roles a domain can use. + +## Example Usage + +```hcl + +data "huaweicloud_iam_role_v3" "roles" { +} + +``` + +**Note**: It can not set `tenant_name` in `provider "huaweicloud"` when + using this data source. + +## Argument Reference + + +## Attributes Reference + +* `projects` - The list of roles which can be granted only to a project. Each + role will include its name and description. + +* `domains` - The list of roles which can be granted only to a domain. Each + role will include its name and description. + +* `project_domains` - The list of roles which can be granted to a project or + domain. Each role will include its name and description. + +* `others` - The list of roles which can be granted to other service, like + object storage service. Each role will include its name and description. diff --git a/website/docs/r/iam_agency_v3.html.markdown b/website/docs/r/iam_agency_v3.html.markdown index 4b2317adbf9..1ddac350d19 100644 --- a/website/docs/r/iam_agency_v3.html.markdown +++ b/website/docs/r/iam_agency_v3.html.markdown @@ -31,6 +31,9 @@ resource "huaweicloud_iam_agency_v3" "agency" { } ``` +**Note**: It can not set `tenant_name` in `provider "huaweicloud"` when + using this resource. + ## Argument Reference The following arguments are supported: