github.com/IBM-Cloud/bluemix-go@v0.0.0-20240423071914-9e96525baef4/api/mccp/mccpv2/organizations.go (about)

     1  package mccpv2
     2  
     3  import (
     4  	"fmt"
     5  	"strings"
     6  
     7  	"github.com/IBM-Cloud/bluemix-go/bmxerror"
     8  	"github.com/IBM-Cloud/bluemix-go/client"
     9  	"github.com/IBM-Cloud/bluemix-go/rest"
    10  )
    11  
    12  //ErrCodeOrgDoesnotExist ...
    13  var ErrCodeOrgDoesnotExist = "OrgDoesnotExist"
    14  
    15  //Metadata ...
    16  type Metadata struct {
    17  	GUID string `json:"guid"`
    18  	URL  string `json:"url"`
    19  }
    20  
    21  //Resource ...
    22  type Resource struct {
    23  	Metadata Metadata
    24  }
    25  
    26  //OrgResource ...
    27  type OrgResource struct {
    28  	Resource
    29  	Entity OrgEntity
    30  }
    31  
    32  //OrgEntity ...
    33  type OrgEntity struct {
    34  	Name                   string `json:"name"`
    35  	Region                 string `json:"region"`
    36  	BillingEnabled         bool   `json:"billing_enabled"`
    37  	Status                 string `json:"status"`
    38  	OrgQuotaDefinitionGUID string `json:"quota_definition_guid"`
    39  }
    40  
    41  //ToFields ..
    42  func (resource OrgResource) ToFields() Organization {
    43  	entity := resource.Entity
    44  
    45  	return Organization{
    46  		GUID:                   resource.Metadata.GUID,
    47  		Name:                   entity.Name,
    48  		Region:                 entity.Region,
    49  		BillingEnabled:         entity.BillingEnabled,
    50  		Status:                 entity.Status,
    51  		OrgQuotaDefinitionGUID: entity.OrgQuotaDefinitionGUID,
    52  	}
    53  }
    54  
    55  //OrgCreateRequest ...
    56  type OrgCreateRequest struct {
    57  	Name                   string `json:"name"`
    58  	OrgQuotaDefinitionGUID string `json:"quota_definition_guid,omitempty"`
    59  	Status                 string `json:"status,omitempty"`
    60  }
    61  
    62  //OrgUpdateRequest ...
    63  type OrgUpdateRequest struct {
    64  	Name                   *string `json:"name,omitempty"`
    65  	OrgQuotaDefinitionGUID string  `json:"quota_definition_guid,omitempty"`
    66  }
    67  
    68  //Organization model
    69  type Organization struct {
    70  	GUID                   string
    71  	Name                   string
    72  	Region                 string
    73  	BillingEnabled         bool
    74  	Status                 string
    75  	OrgQuotaDefinitionGUID string
    76  }
    77  
    78  //OrganizationFields ...
    79  type OrganizationFields struct {
    80  	Metadata Metadata
    81  	Entity   OrgEntity
    82  }
    83  
    84  //OrgRole ...
    85  type OrgRole struct {
    86  	UserGUID string
    87  	Admin    bool
    88  	UserName string
    89  }
    90  
    91  //OrgRoleResource ...
    92  type OrgRoleResource struct {
    93  	Resource
    94  	Entity OrgRoleEntity
    95  }
    96  
    97  //OrgRoleEntity ...
    98  type OrgRoleEntity struct {
    99  	UserGUID string `json:"guid"`
   100  	Admin    bool   `json:"bool"`
   101  	UserName string `json:"username"`
   102  }
   103  
   104  //ToFields ...
   105  func (resource *OrgRoleResource) ToFields() OrgRole {
   106  	entity := resource.Entity
   107  
   108  	return OrgRole{
   109  		UserGUID: resource.Metadata.GUID,
   110  		Admin:    entity.Admin,
   111  		UserName: entity.UserName,
   112  	}
   113  }
   114  
   115  // OrgRegionInformation is the region information associated with an org
   116  type OrgRegionInformation struct {
   117  	ID          string `json:"id"`
   118  	Domain      string `json:"domain"`
   119  	Name        string `json:"name"`
   120  	Region      string `json:"region"`
   121  	DisplayName string `json:"display_name"`
   122  	Customer    struct {
   123  		Name        string `json:"name"`
   124  		DisplayName string `json:"display_name"`
   125  	} `json:"customer"`
   126  	Deployment struct {
   127  		Name        string `json:"name"`
   128  		DisplayName string `json:"display_name"`
   129  	} `json:"deployment"`
   130  	Geo struct {
   131  		Name        string `json:"name"`
   132  		DisplayName string `json:"display_name"`
   133  	} `json:"geo"`
   134  	Account struct {
   135  		GUID       string   `json:"guid"`
   136  		OwnerGUIDs []string `json:"owner_guids"`
   137  	} `json:"account"`
   138  	PublicRegionsByProximity []string `json:"public_regions_by_proximity"`
   139  	ConsoleURL               string   `json:"console_url"`
   140  	CFAPI                    string   `json:"cf_api"`
   141  	MCCPAPI                  string   `json:"mccp_api"`
   142  	Type                     string   `json:"type"`
   143  	Home                     bool     `json:"home"`
   144  	Stealth                  string   `json:"stealth"`
   145  	Aliases                  []string `json:"aliases"`
   146  	Settings                 struct {
   147  		Devops struct {
   148  			Enabled bool `json:"enabled"`
   149  		} `json:"devops"`
   150  		EnhancedAutoFix bool `json:"enhancedAutofix"`
   151  	} `json:"settings"`
   152  	OrgName string `json:"org_name"`
   153  	OrgGUID string `json:"org_guid"`
   154  }
   155  
   156  //Organizations ...
   157  type Organizations interface {
   158  	Create(req OrgCreateRequest, opts ...bool) (*OrganizationFields, error)
   159  	Get(orgGUID string) (*OrganizationFields, error)
   160  	List(region string) ([]Organization, error)
   161  	FindByName(orgName, region string) (*Organization, error)
   162  	DeleteByRegion(guid string, region string, opts ...bool) error
   163  	Delete(guid string, opts ...bool) error
   164  	Update(guid string, req OrgUpdateRequest, opts ...bool) (*OrganizationFields, error)
   165  	GetRegionInformation(orgGUID string) ([]OrgRegionInformation, error)
   166  
   167  	AssociateBillingManager(orgGUID string, userMail string) (*OrganizationFields, error)
   168  	AssociateAuditor(orgGUID string, userMail string) (*OrganizationFields, error)
   169  	AssociateManager(orgGUID string, userMail string) (*OrganizationFields, error)
   170  	AssociateUser(orgGUID string, userMail string) (*OrganizationFields, error)
   171  
   172  	ListBillingManager(orgGUID string, filters ...string) ([]OrgRole, error)
   173  	ListAuditors(orgGUID string, filters ...string) ([]OrgRole, error)
   174  	ListManager(orgGUID string, filters ...string) ([]OrgRole, error)
   175  	ListUsers(orgGUID string, filters ...string) ([]OrgRole, error)
   176  
   177  	DisassociateBillingManager(orgGUID string, userMail string) error
   178  	DisassociateManager(orgGUID string, userMail string) error
   179  	DisassociateAuditor(orgGUID string, userMail string) error
   180  	DisassociateUser(orgGUID string, userMail string) error
   181  }
   182  
   183  type organization struct {
   184  	client *client.Client
   185  }
   186  
   187  func newOrganizationAPI(c *client.Client) Organizations {
   188  	return &organization{
   189  		client: c,
   190  	}
   191  }
   192  
   193  // opts is list of boolean parametes
   194  // opts[0] - async - Will run the create request in a background job. Recommended: 'true'. Default to 'true'.
   195  
   196  func (o *organization) Create(req OrgCreateRequest, opts ...bool) (*OrganizationFields, error) {
   197  	async := true
   198  	orgFields := OrganizationFields{}
   199  	if len(opts) > 0 {
   200  		async = opts[0]
   201  	}
   202  	rawURL := fmt.Sprintf("/v2/organizations?async=%t", async)
   203  	_, err := o.client.Post(rawURL, req, &orgFields)
   204  	if err != nil {
   205  		return nil, err
   206  	}
   207  	return &orgFields, err
   208  }
   209  
   210  func (o *organization) Get(orgGUID string) (*OrganizationFields, error) {
   211  	rawURL := fmt.Sprintf("/v2/organizations/%s", orgGUID)
   212  	orgFields := OrganizationFields{}
   213  	_, err := o.client.Get(rawURL, &orgFields)
   214  	if err != nil {
   215  		return nil, err
   216  	}
   217  	return &orgFields, err
   218  }
   219  
   220  // opts is list of boolean parametes
   221  // opts[0] - async - Will run the update request in a background job. Recommended: 'true'. Default to 'true'.
   222  
   223  func (o *organization) Update(guid string, req OrgUpdateRequest, opts ...bool) (*OrganizationFields, error) {
   224  	async := true
   225  	if len(opts) > 0 {
   226  		async = opts[0]
   227  	}
   228  	orgFields := OrganizationFields{}
   229  	rawURL := fmt.Sprintf("/v2/organizations/%s?async=%t", guid, async)
   230  
   231  	_, err := o.client.Put(rawURL, req, &orgFields)
   232  	return &orgFields, err
   233  }
   234  
   235  // opts is list of boolean parametes
   236  // opts[0] - async - Will run the delete request in a background job. Recommended: 'true'. Default to 'true'.
   237  // opts[1] - recursive - Will delete all spaces, apps, services, routes, and private domains associated with the org. Default to 'false'.
   238  // Deprecated: Use DeleteByRegion instead.
   239  func (o *organization) Delete(guid string, opts ...bool) error {
   240  	async := true
   241  	recursive := false
   242  	if len(opts) > 0 {
   243  		async = opts[0]
   244  	}
   245  	if len(opts) > 1 {
   246  		recursive = opts[1]
   247  	}
   248  	rawURL := fmt.Sprintf("/v2/organizations/%s?async=%t&recursive=%t", guid, async, recursive)
   249  	_, err := o.client.Delete(rawURL)
   250  	return err
   251  }
   252  
   253  // opts is list of boolean parametes
   254  // opts[0] - async - Will run the delete request in a background job. Recommended: 'true'. Default to 'true'.
   255  // opts[1] - recursive - Will delete all spaces, apps, services, routes, and private domains associated with the org. Default to 'false'.
   256  // region - specify the region where the org to be deleted. If org to be deleted in all region's pass the region as 'all'.
   257  func (o *organization) DeleteByRegion(guid string, region string, opts ...bool) error {
   258  	async := true
   259  	recursive := false
   260  	if len(opts) > 0 {
   261  		async = opts[0]
   262  	}
   263  	if len(opts) > 1 {
   264  		recursive = opts[1]
   265  	}
   266  
   267  	rawURL := fmt.Sprintf("/v2/organizations/%s?async=%t&recursive=%t&region=%s", guid, async, recursive, region)
   268  	_, err := o.client.Delete(rawURL)
   269  	return err
   270  }
   271  
   272  func (o *organization) List(region string) ([]Organization, error) {
   273  	req := rest.GetRequest("/v2/organizations")
   274  	if region != "" {
   275  		req.Query("region", region)
   276  	}
   277  	path, err := o.url(req)
   278  	if err != nil {
   279  		return []Organization{}, err
   280  	}
   281  
   282  	var orgs []Organization
   283  	err = o.listOrgResourcesWithPath(path, func(orgResource OrgResource) bool {
   284  		orgs = append(orgs, orgResource.ToFields())
   285  		return true
   286  	})
   287  	return orgs, err
   288  }
   289  
   290  //FindByName ...
   291  func (o *organization) FindByName(name string, region string) (*Organization, error) {
   292  	path, err := o.urlOfOrgWithName(name, region, false)
   293  	if err != nil {
   294  		return nil, err
   295  	}
   296  
   297  	var org Organization
   298  	var found bool
   299  	err = o.listOrgResourcesWithPath(path, func(orgResource OrgResource) bool {
   300  		org = orgResource.ToFields()
   301  		found = true
   302  		return false
   303  	})
   304  
   305  	if err != nil {
   306  		return nil, err
   307  	}
   308  
   309  	if found {
   310  		return &org, err
   311  	}
   312  
   313  	//May not be found and no error
   314  	return nil, bmxerror.New(ErrCodeOrgDoesnotExist,
   315  		fmt.Sprintf("Given org %q doesn't exist in the given region %q", name, region))
   316  
   317  }
   318  
   319  // GetRegionInformation get the region information associated with this org.
   320  func (o *organization) GetRegionInformation(orgGUID string) ([]OrgRegionInformation, error) {
   321  	rawURL := fmt.Sprintf("/v2/organizations/%s/regions", orgGUID)
   322  	var regionOrgInfo []OrgRegionInformation
   323  	_, err := o.client.Get(rawURL, &regionOrgInfo)
   324  	if err != nil {
   325  		return nil, err
   326  	}
   327  	return regionOrgInfo, nil
   328  }
   329  
   330  func (o *organization) listOrgResourcesWithPath(path string, cb func(OrgResource) bool) error {
   331  	_, err := o.client.GetPaginated(path, NewCCPaginatedResources(OrgResource{}), func(resource interface{}) bool {
   332  		if orgResource, ok := resource.(OrgResource); ok {
   333  			return cb(orgResource)
   334  		}
   335  		return false
   336  	})
   337  	return err
   338  }
   339  
   340  func (o *organization) urlOfOrgWithName(name string, region string, inline bool) (string, error) {
   341  	req := rest.GetRequest("/v2/organizations").Query("q", fmt.Sprintf("name:%s", name))
   342  	if region != "" {
   343  		req.Query("region", region)
   344  	}
   345  	if inline {
   346  		req.Query("inline-relations-depth", "1")
   347  	}
   348  	return o.url(req)
   349  }
   350  
   351  func (o *organization) url(req *rest.Request) (string, error) {
   352  	httpReq, err := req.Build()
   353  	if err != nil {
   354  		return "", err
   355  	}
   356  	return httpReq.URL.String(), nil
   357  }
   358  
   359  func (o *organization) associateOrgRole(url, userMail string) (*OrganizationFields, error) {
   360  	orgFields := OrganizationFields{}
   361  	_, err := o.client.Put(url, map[string]string{"username": userMail}, &orgFields)
   362  	if err != nil {
   363  		return nil, err
   364  	}
   365  	return &orgFields, nil
   366  }
   367  
   368  func (o *organization) removeOrgRole(url, userMail string) error {
   369  	orgFields := OrganizationFields{}
   370  	_, err := o.client.DeleteWithBody(url, map[string]string{"username": userMail}, &orgFields)
   371  	return err
   372  }
   373  func (o *organization) AssociateBillingManager(orgGUID string, userMail string) (*OrganizationFields, error) {
   374  	rawURL := fmt.Sprintf("/v2/organizations/%s/billing_managers", orgGUID)
   375  	return o.associateOrgRole(rawURL, userMail)
   376  
   377  }
   378  func (o *organization) AssociateAuditor(orgGUID string, userMail string) (*OrganizationFields, error) {
   379  	rawURL := fmt.Sprintf("/v2/organizations/%s/auditors", orgGUID)
   380  	return o.associateOrgRole(rawURL, userMail)
   381  }
   382  func (o *organization) AssociateManager(orgGUID string, userMail string) (*OrganizationFields, error) {
   383  	rawURL := fmt.Sprintf("/v2/organizations/%s/managers", orgGUID)
   384  	return o.associateOrgRole(rawURL, userMail)
   385  }
   386  
   387  func (o *organization) AssociateUser(orgGUID string, userMail string) (*OrganizationFields, error) {
   388  	rawURL := fmt.Sprintf("/v2/organizations/%s/users", orgGUID)
   389  	return o.associateOrgRole(rawURL, userMail)
   390  }
   391  
   392  func (o *organization) DisassociateBillingManager(orgGUID string, userMail string) error {
   393  	rawURL := fmt.Sprintf("/v2/organizations/%s/billing_managers", orgGUID)
   394  	return o.removeOrgRole(rawURL, userMail)
   395  
   396  }
   397  func (o *organization) DisassociateAuditor(orgGUID string, userMail string) error {
   398  	rawURL := fmt.Sprintf("/v2/organizations/%s/auditors", orgGUID)
   399  	return o.removeOrgRole(rawURL, userMail)
   400  }
   401  func (o *organization) DisassociateManager(orgGUID string, userMail string) error {
   402  	rawURL := fmt.Sprintf("/v2/organizations/%s/managers", orgGUID)
   403  	return o.removeOrgRole(rawURL, userMail)
   404  }
   405  
   406  func (o *organization) DisassociateUser(orgGUID string, userMail string) error {
   407  	rawURL := fmt.Sprintf("/v2/organizations/%s/users", orgGUID)
   408  	return o.removeOrgRole(rawURL, userMail)
   409  }
   410  
   411  func (o *organization) listOrgRolesWithPath(path string) ([]OrgRole, error) {
   412  	var orgRoles []OrgRole
   413  	_, err := o.client.GetPaginated(path, NewCCPaginatedResources(OrgRoleResource{}), func(resource interface{}) bool {
   414  		if orgRoleResource, ok := resource.(OrgRoleResource); ok {
   415  			orgRoles = append(orgRoles, orgRoleResource.ToFields())
   416  			return true
   417  		}
   418  		return false
   419  	})
   420  	return orgRoles, err
   421  }
   422  func (o *organization) listOrgRoles(rawURL string, filters ...string) ([]OrgRole, error) {
   423  	req := rest.GetRequest(rawURL)
   424  	if len(filters) > 0 {
   425  		req.Query("q", strings.Join(filters, ""))
   426  	}
   427  	httpReq, err := req.Build()
   428  	if err != nil {
   429  		return nil, err
   430  	}
   431  	path := httpReq.URL.String()
   432  	return o.listOrgRolesWithPath(path)
   433  }
   434  
   435  func (o *organization) ListBillingManager(orgGUID string, filters ...string) ([]OrgRole, error) {
   436  	rawURL := fmt.Sprintf("/v2/organizations/%s/billing_managers", orgGUID)
   437  	return o.listOrgRoles(rawURL, filters...)
   438  }
   439  
   440  func (o *organization) ListManager(orgGUID string, filters ...string) ([]OrgRole, error) {
   441  	rawURL := fmt.Sprintf("/v2/organizations/%s/managers", orgGUID)
   442  	return o.listOrgRoles(rawURL, filters...)
   443  }
   444  
   445  func (o *organization) ListAuditors(orgGUID string, filters ...string) ([]OrgRole, error) {
   446  	rawURL := fmt.Sprintf("/v2/organizations/%s/auditors", orgGUID)
   447  	return o.listOrgRoles(rawURL, filters...)
   448  }
   449  
   450  func (o *organization) ListUsers(orgGUID string, filters ...string) ([]OrgRole, error) {
   451  	rawURL := fmt.Sprintf("/v2/organizations/%s/users", orgGUID)
   452  	return o.listOrgRoles(rawURL, filters...)
   453  }