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®ion=%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, ®ionOrgInfo) 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 }