From 993121da00badff48283b2a7036a68e25f7166b1 Mon Sep 17 00:00:00 2001 From: zengchen1024 Date: Wed, 11 Jul 2018 18:07:27 +0800 Subject: [PATCH] resource iam agency --- huaweicloud/config.go | 4 + huaweicloud/provider.go | 1 + .../resource_huaweicloud_iam_agency_v3.go | 585 ++++++++++++++++++ .../openstack/identity/v3/agency/requests.go | 96 +++ .../openstack/identity/v3/agency/results.go | 58 ++ .../openstack/identity/v3/agency/urls.go | 24 + vendor/vendor.json | 18 +- website/docs/r/iam_agency_v3.html.markdown | 75 +++ website/huaweicloud.erb | 9 + 9 files changed, 864 insertions(+), 6 deletions(-) create mode 100644 huaweicloud/resource_huaweicloud_iam_agency_v3.go create mode 100644 vendor/github.com/huaweicloud/golangsdk/openstack/identity/v3/agency/requests.go create mode 100644 vendor/github.com/huaweicloud/golangsdk/openstack/identity/v3/agency/results.go create mode 100644 vendor/github.com/huaweicloud/golangsdk/openstack/identity/v3/agency/urls.go create mode 100644 website/docs/r/iam_agency_v3.html.markdown diff --git a/huaweicloud/config.go b/huaweicloud/config.go index 5c8055c4ce..e7d5cb2ce4 100644 --- a/huaweicloud/config.go +++ b/huaweicloud/config.go @@ -481,6 +481,10 @@ func (c *Config) loadCESClient(region string) (*golangsdk.ServiceClient, error) }) } +func (c *Config) loadIAMV3Client(region string) (*golangsdk.ServiceClient, error) { + return huaweisdk.NewIdentityV3(c.HwClient, golangsdk.EndpointOpts{}) +} + func (c *Config) getEndpointType() gophercloud.Availability { if c.EndpointType == "internal" || c.EndpointType == "internalURL" { return gophercloud.AvailabilityInternal diff --git a/huaweicloud/provider.go b/huaweicloud/provider.go index 64622f26c1..08fdc654d8 100644 --- a/huaweicloud/provider.go +++ b/huaweicloud/provider.go @@ -246,6 +246,7 @@ func Provider() terraform.ResourceProvider { "huaweicloud_vpc_eip_v1": resourceVpcEIPV1(), "huaweicloud_sfs_file_system_v2": resourceSFSFileSystemV2(), "huaweicloud_rts_stack_v1": resourceRTSStackV1(), + "huaweicloud_iam_agency_v3": resourceIAMAgencyV3(), }, ConfigureFunc: configureProvider, diff --git a/huaweicloud/resource_huaweicloud_iam_agency_v3.go b/huaweicloud/resource_huaweicloud_iam_agency_v3.go new file mode 100644 index 0000000000..8122676c51 --- /dev/null +++ b/huaweicloud/resource_huaweicloud_iam_agency_v3.go @@ -0,0 +1,585 @@ +package huaweicloud + +import ( + "bytes" + "fmt" + "log" + "strings" + "time" + + "github.com/hashicorp/terraform/helper/hashcode" + "github.com/hashicorp/terraform/helper/resource" + "github.com/hashicorp/terraform/helper/schema" + "github.com/huaweicloud/golangsdk" + "github.com/huaweicloud/golangsdk/openstack/identity/v3/agency" + "github.com/huaweicloud/golangsdk/openstack/identity/v3/domains" + sdkprojects "github.com/huaweicloud/golangsdk/openstack/identity/v3/projects" + sdkroles "github.com/huaweicloud/golangsdk/openstack/identity/v3/roles" +) + +func resourceIAMAgencyV3() *schema.Resource { + return &schema.Resource{ + Create: resourceIAMAgencyV3Create, + Read: resourceIAMAgencyV3Read, + Update: resourceIAMAgencyV3Update, + Delete: resourceIAMAgencyV3Delete, + Importer: &schema.ResourceImporter{ + State: schema.ImportStatePassthrough, + }, + + Timeouts: &schema.ResourceTimeout{ + Create: schema.DefaultTimeout(10 * time.Minute), + Update: schema.DefaultTimeout(10 * time.Minute), + Delete: schema.DefaultTimeout(5 * time.Minute), + }, + + Schema: map[string]*schema.Schema{ + "region": &schema.Schema{ + Type: schema.TypeString, + Optional: true, + Computed: true, + }, + "name": &schema.Schema{ + Type: schema.TypeString, + Required: true, + }, + "delegated_domain_name": &schema.Schema{ + Type: schema.TypeString, + Required: true, + }, + "description": &schema.Schema{ + Type: schema.TypeString, + Optional: true, + Computed: true, + }, + "duration": &schema.Schema{ + Type: schema.TypeString, + Computed: true, + }, + "expire_time": &schema.Schema{ + Type: schema.TypeString, + Computed: true, + }, + "create_time": &schema.Schema{ + Type: schema.TypeString, + Computed: true, + }, + "project_role": &schema.Schema{ + Type: schema.TypeSet, + Optional: true, + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "roles": { + Type: schema.TypeSet, + Required: true, + MinItems: 1, + MaxItems: 25, + Elem: &schema.Schema{Type: schema.TypeString}, + Set: schema.HashString, + }, + "project": { + Type: schema.TypeString, + Required: true, + }, + }, + }, + Set: resourceIAMAgencyProRoleHash, + }, + "domain_roles": &schema.Schema{ + Type: schema.TypeSet, + Optional: true, + MinItems: 1, + MaxItems: 25, + Elem: &schema.Schema{Type: schema.TypeString}, + Set: schema.HashString, + }, + }, + } +} + +func resourceIAMAgencyProRoleHash(v interface{}) int { + var buf bytes.Buffer + m := v.(map[string]interface{}) + buf.WriteString(fmt.Sprintf("%s-", m["project"].(string))) + + r := m["roles"].(*schema.Set).List() + s := make([]string, len(r)) + for i, item := range r { + s[i] = item.(string) + } + buf.WriteString(strings.Join(s, "-")) + + return hashcode.String(buf.String()) +} + +func agencyClient(d *schema.ResourceData, config *Config) (*golangsdk.ServiceClient, error) { + c, err := config.loadIAMV3Client(GetRegion(d, config)) + if err != nil { + return nil, err + } + c.Endpoint = "https://iam.myhwclouds.com:443/v3.0/" + return c, nil +} + +func listProjectsOfDomain(domainID string, client *golangsdk.ServiceClient) (map[string]string, error) { + old := client.Endpoint + defer func() { client.Endpoint = old }() + client.Endpoint = "https://iam.myhwclouds.com:443/v3/" + + opts := sdkprojects.ListOpts{ + DomainID: domainID, + } + allPages, err := sdkprojects.List(client, &opts).AllPages() + if err != nil { + return nil, fmt.Errorf("List projects failed, err=%s", err) + } + + all, err := sdkprojects.ExtractProjects(allPages) + if err != nil { + return nil, fmt.Errorf("Extract projects failed, err=%s", err) + } + + r := make(map[string]string, len(all)) + for _, item := range all { + r[item.Name] = item.ID + } + log.Printf("[TRACE] projects = %#v\n", r) + return r, nil +} + +func listRolesOfDomain(domainID string, client *golangsdk.ServiceClient) (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 := make(map[string]string, len(all)) + for _, item := range all { + dn, ok := item.Extra["display_name"].(string) + if ok { + r[dn] = item.ID + } else { + log.Printf("[DEBUG] Can not retrieve role:%#v", item) + } + } + log.Printf("[TRACE] list roles = %#v, len=%d\n", r, len(r)) + return r, nil +} + +func allRolesOfDomain(domainID string, client *golangsdk.ServiceClient) (map[string]string, error) { + roles, err := listRolesOfDomain("", client) + 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 + } + } + + return roles, nil +} + +func getDomainID(config *Config, client *golangsdk.ServiceClient) (string, error) { + if config.DomainID != "" { + return config.DomainID, nil + } + + name := config.DomainName + if name == "" { + return "", fmt.Errorf("The required domain name was missed") + } + + old := client.Endpoint + defer func() { client.Endpoint = old }() + client.Endpoint = "https://iam.myhwclouds.com:443/v3/auth/" + + opts := domains.ListOpts{ + Name: name, + } + allPages, err := domains.List(client, &opts).AllPages() + if err != nil { + return "", fmt.Errorf("List domains failed, err=%s", err) + } + + all, err := domains.ExtractDomains(allPages) + if err != nil { + return "", fmt.Errorf("Extract domains failed, err=%s", err) + } + + count := len(all) + switch count { + case 0: + err := &golangsdk.ErrResourceNotFound{} + err.ResourceType = "iam" + err.Name = name + return "", err + case 1: + return all[0].ID, nil + default: + err := &golangsdk.ErrMultipleResourcesFound{} + err.ResourceType = "iam" + err.Name = name + err.Count = count + return "", err + } +} + +func changeToPRPair(prs *schema.Set) (r map[string]bool) { + r = make(map[string]bool) + for _, v := range prs.List() { + pr := v.(map[string]interface{}) + + pn := pr["project"].(string) + rs := pr["roles"].(*schema.Set) + for _, role := range rs.List() { + r[pn+"|"+role.(string)] = true + } + } + return +} + +func diffChangeOfProjectRole(old, newv *schema.Set) (delete, add []string) { + delete = make([]string, 0) + add = make([]string, 0) + + oldprs := changeToPRPair(old) + newprs := changeToPRPair(newv) + + for k := range oldprs { + if _, ok := newprs[k]; !ok { + delete = append(delete, k) + } + } + + for k := range newprs { + if _, ok := oldprs[k]; !ok { + add = append(add, k) + } + } + return +} + +func resourceIAMAgencyV3Create(d *schema.ResourceData, meta interface{}) error { + prs := d.Get("project_role").(*schema.Set) + drs := d.Get("domain_roles").(*schema.Set) + if prs.Len() == 0 && drs.Len() == 0 { + return fmt.Errorf("One or both of project_role and domain_roles must be input") + } + + 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) + } + + opts := agency.CreateOpts{ + Name: d.Get("name").(string), + DomainID: domainID, + DelegatedDomain: d.Get("delegated_domain_name").(string), + Description: d.Get("description").(string), + } + log.Printf("[DEBUG] Create IAM-Agency Options: %#v", opts) + a, err := agency.Create(client, opts).Extract() + if err != nil { + return fmt.Errorf("Error creating IAM-Agency: %s", err) + } + + d.SetId(a.ID) + + projects, err := listProjectsOfDomain(domainID, client) + if err != nil { + return fmt.Errorf("Error querying the projects, err=%s", err) + } + + roles, err := allRolesOfDomain(domainID, client) + if err != nil { + return fmt.Errorf("Error querying the roles, err=%s", err) + } + + agencyID := a.ID + for _, v := range prs.List() { + pr := v.(map[string]interface{}) + pn := pr["project"].(string) + pid, ok := projects[pn] + if !ok { + return fmt.Errorf("The project(%s) is not exist", pn) + } + + rs := pr["roles"].(*schema.Set) + for _, role := range rs.List() { + r := role.(string) + rid, ok := roles[r] + if !ok { + return fmt.Errorf("The role(%s) is not exist", r) + } + + err = agency.AttachRoleByProject(client, agencyID, pid, rid).ExtractErr() + if err != nil { + return fmt.Errorf("Error attaching role(%s) by project{%s} to agency(%s), err=%s", + rid, pid, agencyID, err) + } + } + } + + for _, role := range drs.List() { + r := role.(string) + rid, ok := roles[r] + if !ok { + return fmt.Errorf("The role(%s) is not exist", r) + } + + err = agency.AttachRoleByDomain(client, agencyID, domainID, rid).ExtractErr() + if err != nil { + return fmt.Errorf("Error attaching role(%s) by domain{%s} to agency(%s), err=%s", + rid, domainID, agencyID, err) + } + } + + return resourceIAMAgencyV3Read(d, meta) +} + +func resourceIAMAgencyV3Read(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) + } + + a, err := agency.Get(client, d.Id()).Extract() + if err != nil { + return CheckDeleted(d, err, "IAM-Agency") + } + log.Printf("[DEBUG] Retrieved IAM-Agency %s: %#v", d.Id(), a) + + d.Set("region", GetRegion(d, config)) + d.Set("name", a.Name) + d.Set("delegated_domain_name", a.DelegatedDomainName) + d.Set("description", a.Description) + d.Set("duration", a.Duration) + d.Set("expire_time", a.ExpireTime) + d.Set("create_time", a.CreateTime) + + projects, err := listProjectsOfDomain(a.DomainID, client) + if err != nil { + return fmt.Errorf("Error querying the projects, err=%s", err) + } + agencyID := d.Id() + prs := schema.Set{F: resourceIAMAgencyProRoleHash} + for pn, pid := range projects { + roles, err := agency.ListRolesAttachedOnProject(client, agencyID, pid).ExtractRoles() + if err != nil && !isResourceNotFound(err) { + return fmt.Errorf("Error querying the roles attached on project(%s), err=%s", pn, err) + } + if len(roles) == 0 { + continue + } + v := schema.Set{F: schema.HashString} + for _, role := range roles { + v.Add(role.Extra["display_name"]) + } + prs.Add(map[string]interface{}{ + "project": pn, + "roles": &v, + }) + } + err = d.Set("project_role", &prs) + if err != nil { + log.Printf("[ERROR]Set project_role failed, err=%s", err) + } + + roles, err := agency.ListRolesAttachedOnDomain(client, agencyID, a.DomainID).ExtractRoles() + if err != nil && !isResourceNotFound(err) { + return fmt.Errorf("Error querying the roles attached on domain, err=%s", err) + } + if len(roles) != 0 { + v := schema.Set{F: schema.HashString} + for _, role := range roles { + v.Add(role.Extra["display_name"]) + } + err = d.Set("domain_roles", &v) + if err != nil { + log.Printf("[ERROR]Set domain_roles failed, err=%s", err) + } + } + + return nil +} + +func resourceIAMAgencyV3Update(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) + } + + aID := d.Id() + + if d.HasChange("delegated_domain_name") || d.HasChange("description") { + updateOpts := agency.UpdateOpts{ + DelegatedDomain: d.Get("delegated_domain_name").(string), + Description: d.Get("description").(string), + } + log.Printf("[DEBUG] Updating IAM-Agency %s with options: %#v", aID, updateOpts) + timeout := d.Timeout(schema.TimeoutUpdate) + err = resource.Retry(timeout, func() *resource.RetryError { + _, err := agency.Update(client, aID, updateOpts).Extract() + if err != nil { + return checkForRetryableError(err) + } + return nil + }) + if err != nil { + return fmt.Errorf("Error updating IAM-Agency %s: %s", aID, err) + } + } + + domainID := "" + var roles map[string]string + if d.HasChange("project_role") || d.HasChange("domain_roles") { + domainID, err = getDomainID(config, client) + if err != nil { + return fmt.Errorf("Error getting the domain id, err=%s", err) + } + + roles, err = allRolesOfDomain(domainID, client) + if err != nil { + return fmt.Errorf("Error querying the roles, err=%s", err) + } + } + + if d.HasChange("project_role") { + projects, err := listProjectsOfDomain(domainID, client) + if err != nil { + return fmt.Errorf("Error querying the projects, err=%s", err) + } + + o, n := d.GetChange("project_role") + deleteprs, addprs := diffChangeOfProjectRole(o.(*schema.Set), n.(*schema.Set)) + for _, v := range deleteprs { + pr := strings.Split(v, "|") + pid, ok := projects[pr[0]] + if !ok { + return fmt.Errorf("The project(%s) is not exist", pr[0]) + } + rid, ok := roles[pr[1]] + if !ok { + return fmt.Errorf("The role(%s) is not exist", pr[1]) + } + + err = agency.DetachRoleByProject(client, aID, pid, rid).ExtractErr() + if err != nil && !isResourceNotFound(err) { + return fmt.Errorf("Error detaching role(%s) by project{%s} from agency(%s), err=%s", + rid, pid, aID, err) + } + } + + for _, v := range addprs { + pr := strings.Split(v, "|") + pid, ok := projects[pr[0]] + if !ok { + return fmt.Errorf("The project(%s) is not exist", pr[0]) + } + rid, ok := roles[pr[1]] + if !ok { + return fmt.Errorf("The role(%s) is not exist", pr[1]) + } + + err = agency.AttachRoleByProject(client, aID, pid, rid).ExtractErr() + if err != nil { + return fmt.Errorf("Error attaching role(%s) by project{%s} to agency(%s), err=%s", + rid, pid, aID, err) + } + } + } + + if d.HasChange("domain_roles") { + o, n := d.GetChange("domain_roles") + oldr := o.(*schema.Set) + newr := n.(*schema.Set) + + for _, r := range oldr.Difference(newr).List() { + rid, ok := roles[r.(string)] + if !ok { + return fmt.Errorf("The role(%s) is not exist", r.(string)) + } + + err = agency.DetachRoleByDomain(client, aID, domainID, rid).ExtractErr() + if err != nil && !isResourceNotFound(err) { + return fmt.Errorf("Error detaching role(%s) by domain{%s} from agency(%s), err=%s", + rid, domainID, aID, err) + } + } + + for _, r := range newr.Difference(oldr).List() { + rid, ok := roles[r.(string)] + if !ok { + return fmt.Errorf("The role(%s) is not exist", r.(string)) + } + + err = agency.AttachRoleByDomain(client, aID, domainID, rid).ExtractErr() + if err != nil { + return fmt.Errorf("Error attaching role(%s) by domain{%s} to agency(%s), err=%s", + rid, domainID, aID, err) + } + } + } + return resourceIAMAgencyV3Read(d, meta) +} + +func resourceIAMAgencyV3Delete(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) + } + + rID := d.Id() + log.Printf("[DEBUG] Deleting IAM-Agency %s", rID) + + timeout := d.Timeout(schema.TimeoutDelete) + err = resource.Retry(timeout, func() *resource.RetryError { + err := agency.Delete(client, rID).ExtractErr() + if err != nil { + return checkForRetryableError(err) + } + return nil + }) + if err != nil { + if isResourceNotFound(err) { + log.Printf("[INFO] deleting an unavailable IAM-Agency: %s", rID) + return nil + } + return fmt.Errorf("Error deleting IAM-Agency %s: %s", rID, err) + } + + return nil +} diff --git a/vendor/github.com/huaweicloud/golangsdk/openstack/identity/v3/agency/requests.go b/vendor/github.com/huaweicloud/golangsdk/openstack/identity/v3/agency/requests.go new file mode 100644 index 0000000000..4e2b341daf --- /dev/null +++ b/vendor/github.com/huaweicloud/golangsdk/openstack/identity/v3/agency/requests.go @@ -0,0 +1,96 @@ +package agency + +import "github.com/huaweicloud/golangsdk" + +type CreateOpts struct { + Name string `json:"name" required:"true"` + DomainID string `json:"domain_id" required:"true"` + DelegatedDomain string `json:"trust_domain_name" required:"true"` + Description string `json:"description,omitempty"` +} + +type CreateOptsBuilder interface { + ToAgencyCreateMap() (map[string]interface{}, error) +} + +func (opts CreateOpts) ToAgencyCreateMap() (map[string]interface{}, error) { + return golangsdk.BuildRequestBody(opts, "agency") +} + +func Create(c *golangsdk.ServiceClient, opts CreateOptsBuilder) (r CreateResult) { + b, err := opts.ToAgencyCreateMap() + if err != nil { + r.Err = err + return + } + _, r.Err = c.Post(rootURL(c), b, &r.Body, nil) + return +} + +type UpdateOpts struct { + DelegatedDomain string `json:"trust_domain_name,omitempty"` + Description string `json:"description,omitempty"` +} + +type UpdateOptsBuilder interface { + ToAgencyUpdateMap() (map[string]interface{}, error) +} + +func (opts UpdateOpts) ToAgencyUpdateMap() (map[string]interface{}, error) { + return golangsdk.BuildRequestBody(opts, "agency") +} + +func Update(c *golangsdk.ServiceClient, id string, opts UpdateOptsBuilder) (r UpdateResult) { + b, err := opts.ToAgencyUpdateMap() + if err != nil { + r.Err = err + return + } + reqOpt := &golangsdk.RequestOpts{OkCodes: []int{200}} + _, r.Err = c.Put(resourceURL(c, id), b, &r.Body, reqOpt) + return +} + +func Get(c *golangsdk.ServiceClient, id string) (r GetResult) { + _, r.Err = c.Get(resourceURL(c, id), &r.Body, nil) + return +} + +func Delete(c *golangsdk.ServiceClient, id string) (r ErrResult) { + _, r.Err = c.Delete(resourceURL(c, id), nil) + return +} + +func AttachRoleByProject(c *golangsdk.ServiceClient, agencyID, projectID, roleID string) (r ErrResult) { + reqOpt := &golangsdk.RequestOpts{OkCodes: []int{204}} + _, r.Err = c.Put(roleURL(c, "projects", projectID, agencyID, roleID), nil, nil, reqOpt) + return +} + +func AttachRoleByDomain(c *golangsdk.ServiceClient, agencyID, domainID, roleID string) (r ErrResult) { + reqOpt := &golangsdk.RequestOpts{OkCodes: []int{204}} + _, r.Err = c.Put(roleURL(c, "domains", domainID, agencyID, roleID), nil, nil, reqOpt) + return +} + +func DetachRoleByProject(c *golangsdk.ServiceClient, agencyID, projectID, roleID string) (r ErrResult) { + reqOpt := &golangsdk.RequestOpts{OkCodes: []int{204}} + _, r.Err = c.Delete(roleURL(c, "projects", projectID, agencyID, roleID), reqOpt) + return +} + +func DetachRoleByDomain(c *golangsdk.ServiceClient, agencyID, domainID, roleID string) (r ErrResult) { + reqOpt := &golangsdk.RequestOpts{OkCodes: []int{204}} + _, r.Err = c.Delete(roleURL(c, "domains", domainID, agencyID, roleID), reqOpt) + return +} + +func ListRolesAttachedOnProject(c *golangsdk.ServiceClient, agencyID, projectID string) (r ListRolesResult) { + _, r.Err = c.Get(listRolesURL(c, "projects", projectID, agencyID), &r.Body, nil) + return +} + +func ListRolesAttachedOnDomain(c *golangsdk.ServiceClient, agencyID, domainID string) (r ListRolesResult) { + _, r.Err = c.Get(listRolesURL(c, "domains", domainID, agencyID), &r.Body, nil) + return +} diff --git a/vendor/github.com/huaweicloud/golangsdk/openstack/identity/v3/agency/results.go b/vendor/github.com/huaweicloud/golangsdk/openstack/identity/v3/agency/results.go new file mode 100644 index 0000000000..953e98aa55 --- /dev/null +++ b/vendor/github.com/huaweicloud/golangsdk/openstack/identity/v3/agency/results.go @@ -0,0 +1,58 @@ +package agency + +import ( + "github.com/huaweicloud/golangsdk" + "github.com/huaweicloud/golangsdk/openstack/identity/v3/roles" +) + +type Agency struct { + ID string `json:"id"` + Name string `json:"name"` + DomainID string `json:"domain_id"` + DelegatedDomainID string `json:"trust_domain_id"` + DelegatedDomainName string `json:"trust_domain_name"` + Description string `json:"description"` + Duration string `json:"duration"` + ExpireTime string `json:"expire_time"` + CreateTime string `json:"create_time"` +} + +type commonResult struct { + golangsdk.Result +} + +func (r commonResult) Extract() (*Agency, error) { + var s struct { + Agency *Agency `json:"agency"` + } + err := r.ExtractInto(&s) + return s.Agency, err +} + +type GetResult struct { + commonResult +} + +type CreateResult struct { + commonResult +} + +type UpdateResult struct { + commonResult +} + +type ErrResult struct { + golangsdk.ErrResult +} + +type ListRolesResult struct { + golangsdk.Result +} + +func (r ListRolesResult) ExtractRoles() ([]roles.Role, error) { + var s struct { + Roles []roles.Role `json:"roles"` + } + err := r.ExtractInto(&s) + return s.Roles, err +} diff --git a/vendor/github.com/huaweicloud/golangsdk/openstack/identity/v3/agency/urls.go b/vendor/github.com/huaweicloud/golangsdk/openstack/identity/v3/agency/urls.go new file mode 100644 index 0000000000..cb92be2ca0 --- /dev/null +++ b/vendor/github.com/huaweicloud/golangsdk/openstack/identity/v3/agency/urls.go @@ -0,0 +1,24 @@ +package agency + +import "github.com/huaweicloud/golangsdk" + +const ( + rootPath = "OS-AGENCY" + resourcePath = "agencies" +) + +func rootURL(c *golangsdk.ServiceClient) string { + return c.ServiceURL(rootPath, resourcePath) +} + +func resourceURL(c *golangsdk.ServiceClient, id string) string { + return c.ServiceURL(rootPath, resourcePath, id) +} + +func roleURL(c *golangsdk.ServiceClient, resource, resourceID, agencyID, roleID string) string { + return c.ServiceURL(rootPath, resource, resourceID, resourcePath, agencyID, "roles", roleID) +} + +func listRolesURL(c *golangsdk.ServiceClient, resource, resourceID, agencyID string) string { + return c.ServiceURL(rootPath, resource, resourceID, resourcePath, agencyID, "roles") +} diff --git a/vendor/vendor.json b/vendor/vendor.json index 5e970d21eb..ecc1e1d70c 100644 --- a/vendor/vendor.json +++ b/vendor/vendor.json @@ -785,14 +785,14 @@ "checksumSHA1": "XOIIgkGo+ASyGm2ggTUkbV5FUXg=", "checksumSHA1": "cZlMp+J4uHxr97+lBhMMQavprwk=", "path": "github.com/huaweicloud/golangsdk", - "revision": "ffc7e20dd56d293082449363b897dac040bed9e4", - "revisionTime": "2018-07-17T08:08:51Z" + "revision": "aef01041fa9cf1fa8844a490cac4ded3fceec9a7", + "revisionTime": "2018-07-17T08:53:40Z" }, { "checksumSHA1": "NBnvn7QO72h76Gt99INBda0pm/k=", "path": "github.com/huaweicloud/golangsdk/openstack", - "revision": "ffc7e20dd56d293082449363b897dac040bed9e4", - "revisionTime": "2018-07-17T08:08:51Z" + "revision": "aef01041fa9cf1fa8844a490cac4ded3fceec9a7", + "revisionTime": "2018-07-17T08:53:40Z" }, { "checksumSHA1": "lpp6hBnX9xBhrnxXc0i/5fHHoWY=", @@ -824,11 +824,17 @@ "revision": "888f77744ab7c65bb4d448d5b5313edba29e76c7", "revisionTime": "2018-02-24T07:23:49Z" }, + { + "checksumSHA1": "01rgTDEc7ZtwU5rhtTu0dEAnfyA=", + "path": "github.com/huaweicloud/golangsdk/openstack/identity/v3/agency", + "revision": "aef01041fa9cf1fa8844a490cac4ded3fceec9a7", + "revisionTime": "2018-07-17T08:53:40Z" + }, { "checksumSHA1": "2WCVVbTVr7UGO0l1ZjmdJJc1tXk=", "path": "github.com/huaweicloud/golangsdk/openstack/identity/v3/tokens", - "revision": "ffc7e20dd56d293082449363b897dac040bed9e4", - "revisionTime": "2018-07-17T08:08:51Z" + "revision": "aef01041fa9cf1fa8844a490cac4ded3fceec9a7", + "revisionTime": "2018-07-17T08:53:40Z" }, { "checksumSHA1": "JRRYtYkrco9209oThCcF5MEPIII=", diff --git a/website/docs/r/iam_agency_v3.html.markdown b/website/docs/r/iam_agency_v3.html.markdown new file mode 100644 index 0000000000..4b2317adbf --- /dev/null +++ b/website/docs/r/iam_agency_v3.html.markdown @@ -0,0 +1,75 @@ +--- +layout: "huaweicloud" +page_title: "HuaweiCloud: huaweicloud_iam_agency_v3" +sidebar_current: "docs-huaweicloud-resource-iam-agency-v3" +description: |- + Manages an agency resource within huawei cloud. +--- + +# huaweicloud\_iam\_agency\_v3 + +Manages an agency resource within huawei cloud. + +## Example Usage + +```hcl +resource "huaweicloud_iam_agency_v3" "agency" { + name = "test_agency" + description = "test agency" + delegated_domain_name = "***" + project_role = [ + { + project = "cn-north-1" + roles = [ + "Tenant Administrator", + ] + } + ] + domain_roles = [ + "Anti-DDoS Administrator", + ] +} +``` + +## Argument Reference + +The following arguments are supported: + +* `name` - (Required) The name of agency. The name is a string of 1 to 64 + characters. + +* `description` - (Optional) Provides supplementary information about the + agency. The value is a string of 0 to 255 characters. + +* `delegated_domain_name` - (Required) The name of delegated domain. + +* `project_role` - (Optional) An array of roles and projects which are used to + grant permissions to agency on project. The structure is documented below. + +* `domain_roles` - (optional) An array of role names which stand for the + permissionis to be granted to agency on domain. + +The `project_role` block supports: + +* `project` - (Required) The name of project + +* `roles` - (Required) An array of role names + +**note**: + one or both of `project_role` and `domain_roles` must be input when +creating an agency. + +## Attributes Reference + +The following attributes are exported: + +* `name` - See Argument Reference above. +* `description` - See Argument Reference above. +* `delegated_domain_name` - See Argument Reference above. +* `project_role` - See Argument Reference above. +* `domain_roles` - See Argument Reference above. +* `duration` - Validity period of an agency. The default value is null, + indicating that the agency is permanently valid. +* `expire_time` - The expiration time of agency +* `create_time` - The time when the agency was created. +* `id` - The agency ID. diff --git a/website/huaweicloud.erb b/website/huaweicloud.erb index 81a1f1d05e..d430c55d89 100644 --- a/website/huaweicloud.erb +++ b/website/huaweicloud.erb @@ -265,6 +265,15 @@ + > + IAM Resources + + + <% end %>