github.com/IBM-Cloud/bluemix-go@v0.0.0-20240423071914-9e96525baef4/api/mccp/mccpv2/spaces.go (about) 1 package mccpv2 2 3 import ( 4 "fmt" 5 "strconv" 6 "strings" 7 8 "github.com/IBM-Cloud/bluemix-go/bmxerror" 9 "github.com/IBM-Cloud/bluemix-go/client" 10 "github.com/IBM-Cloud/bluemix-go/rest" 11 ) 12 13 //SpaceCreateRequest ... 14 type SpaceCreateRequest struct { 15 Name string `json:"name"` 16 OrgGUID string `json:"organization_guid"` 17 SpaceQuotaGUID string `json:"space_quota_definition_guid,omitempty"` 18 } 19 20 //SpaceUpdateRequest ... 21 type SpaceUpdateRequest struct { 22 Name *string `json:"name,omitempty"` 23 } 24 25 //Space ... 26 type Space struct { 27 GUID string 28 Name string 29 OrgGUID string 30 SpaceQuotaGUID string 31 AllowSSH bool 32 } 33 34 //SpaceRole ... 35 type SpaceRole struct { 36 UserGUID string 37 Admin bool 38 UserName string 39 } 40 41 //SpaceFields ... 42 type SpaceFields struct { 43 Metadata SpaceMetadata 44 Entity SpaceEntity 45 } 46 47 //SpaceMetadata ... 48 type SpaceMetadata struct { 49 GUID string `json:"guid"` 50 URL string `json:"url"` 51 } 52 53 //ErrCodeSpaceDoesnotExist ... 54 const ErrCodeSpaceDoesnotExist = "SpaceDoesnotExist" 55 56 //SpaceResource ... 57 type SpaceResource struct { 58 Resource 59 Entity SpaceEntity 60 } 61 62 //SpaceRoleResource ... 63 type SpaceRoleResource struct { 64 Resource 65 Entity SpaceRoleEntity 66 } 67 68 //SpaceRoleEntity ... 69 type SpaceRoleEntity struct { 70 UserGUID string `json:"guid"` 71 Admin bool `json:"bool"` 72 UserName string `json:"username"` 73 } 74 75 //SpaceEntity ... 76 type SpaceEntity struct { 77 Name string `json:"name"` 78 OrgGUID string `json:"organization_guid"` 79 SpaceQuotaGUID string `json:"space_quota_definition_guid"` 80 AllowSSH bool `json:"allow_ssh"` 81 } 82 83 //ToFields ... 84 func (resource *SpaceResource) ToFields() Space { 85 entity := resource.Entity 86 87 return Space{ 88 GUID: resource.Metadata.GUID, 89 Name: entity.Name, 90 OrgGUID: entity.OrgGUID, 91 SpaceQuotaGUID: entity.SpaceQuotaGUID, 92 AllowSSH: entity.AllowSSH, 93 } 94 } 95 96 //ToFields ... 97 func (resource *SpaceRoleResource) ToFields() SpaceRole { 98 entity := resource.Entity 99 100 return SpaceRole{ 101 UserGUID: resource.Metadata.GUID, 102 Admin: entity.Admin, 103 UserName: entity.UserName, 104 } 105 } 106 107 //RouteFilter ... 108 type RouteFilter struct { 109 DomainGUID string 110 Host *string 111 Path *string 112 Port *int 113 } 114 115 //Spaces ... 116 type Spaces interface { 117 ListSpacesInOrg(orgGUID, region string) ([]Space, error) 118 FindByNameInOrg(orgGUID, name, region string) (*Space, error) 119 Create(req SpaceCreateRequest, opts ...bool) (*SpaceFields, error) 120 Update(spaceGUID string, req SpaceUpdateRequest, opts ...bool) (*SpaceFields, error) 121 Delete(spaceGUID string, opts ...bool) error 122 Get(spaceGUID string) (*SpaceFields, error) 123 ListRoutes(spaceGUID string, req RouteFilter) ([]Route, error) 124 AssociateAuditor(spaceGUID, userMail string) (*SpaceFields, error) 125 AssociateDeveloper(spaceGUID, userMail string) (*SpaceFields, error) 126 AssociateManager(spaceGUID, userMail string) (*SpaceFields, error) 127 128 DisassociateAuditor(spaceGUID, userMail string) error 129 DisassociateDeveloper(spaceGUID, userMail string) error 130 DisassociateManager(spaceGUID, userMail string) error 131 132 ListAuditors(spaceGUID string, filters ...string) ([]SpaceRole, error) 133 ListDevelopers(spaceGUID string, filters ...string) ([]SpaceRole, error) 134 ListManagers(spaceGUID string, filters ...string) ([]SpaceRole, error) 135 } 136 137 type spaces struct { 138 client *client.Client 139 } 140 141 func newSpacesAPI(c *client.Client) Spaces { 142 return &spaces{ 143 client: c, 144 } 145 } 146 147 func (r *spaces) FindByNameInOrg(orgGUID string, name string, region string) (*Space, error) { 148 rawURL := fmt.Sprintf("/v2/organizations/%s/spaces", orgGUID) 149 req := rest.GetRequest(rawURL).Query("q", "name:"+name) 150 if region != "" { 151 req.Query("region", region) 152 } 153 httpReq, err := req.Build() 154 if err != nil { 155 return nil, err 156 } 157 path := httpReq.URL.String() 158 159 spaces, err := r.listSpacesWithPath(path) 160 161 if err != nil { 162 return nil, err 163 } 164 if len(spaces) == 0 { 165 return nil, bmxerror.New(ErrCodeSpaceDoesnotExist, 166 fmt.Sprintf("Given space: %q doesn't exist in given org: %q in the given region %q", name, orgGUID, region)) 167 168 } 169 return &spaces[0], nil 170 } 171 172 func (r *spaces) ListSpacesInOrg(orgGUID string, region string) ([]Space, error) { 173 rawURL := fmt.Sprintf("v2/organizations/%s/spaces", orgGUID) 174 req := rest.GetRequest(rawURL) 175 if region != "" { 176 req.Query("region", region) 177 } 178 httpReq, err := req.Build() 179 if err != nil { 180 return nil, err 181 } 182 path := httpReq.URL.String() 183 184 return r.listSpacesWithPath(path) 185 } 186 187 func (r *spaces) listSpacesWithPath(path string) ([]Space, error) { 188 var spaces []Space 189 _, err := r.client.GetPaginated(path, NewCCPaginatedResources(SpaceResource{}), func(resource interface{}) bool { 190 if spaceResource, ok := resource.(SpaceResource); ok { 191 spaces = append(spaces, spaceResource.ToFields()) 192 return true 193 } 194 return false 195 }) 196 return spaces, err 197 } 198 199 func (r *spaces) listSpaceRolesWithPath(path string) ([]SpaceRole, error) { 200 var spaceRoles []SpaceRole 201 _, err := r.client.GetPaginated(path, NewCCPaginatedResources(SpaceRoleResource{}), func(resource interface{}) bool { 202 if spaceRoleResource, ok := resource.(SpaceRoleResource); ok { 203 spaceRoles = append(spaceRoles, spaceRoleResource.ToFields()) 204 return true 205 } 206 return false 207 }) 208 return spaceRoles, err 209 } 210 211 // opts is list of boolean parametes 212 // opts[0] - async - Will run the create request in a background job. Recommended: 'true'. Default to 'true'. 213 214 func (r *spaces) Create(req SpaceCreateRequest, opts ...bool) (*SpaceFields, error) { 215 async := true 216 if len(opts) > 0 { 217 async = opts[0] 218 } 219 rawURL := fmt.Sprintf("/v2/spaces?async=%t", async) 220 spaceFields := SpaceFields{} 221 _, err := r.client.Post(rawURL, req, &spaceFields) 222 if err != nil { 223 return nil, err 224 } 225 return &spaceFields, nil 226 } 227 228 func (r *spaces) Get(spaceGUID string) (*SpaceFields, error) { 229 rawURL := fmt.Sprintf("/v2/spaces/%s", spaceGUID) 230 spaceFields := SpaceFields{} 231 _, err := r.client.Get(rawURL, &spaceFields) 232 if err != nil { 233 return nil, err 234 } 235 236 return &spaceFields, err 237 } 238 239 // opts is list of boolean parametes 240 // opts[0] - async - Will run the update request in a background job. Recommended: 'true'. Default to 'true'. 241 242 func (r *spaces) Update(spaceGUID string, req SpaceUpdateRequest, opts ...bool) (*SpaceFields, error) { 243 async := true 244 if len(opts) > 0 { 245 async = opts[0] 246 } 247 rawURL := fmt.Sprintf("/v2/spaces/%s?async=%t", spaceGUID, async) 248 spaceFields := SpaceFields{} 249 _, err := r.client.Put(rawURL, req, &spaceFields) 250 if err != nil { 251 return nil, err 252 } 253 return &spaceFields, nil 254 } 255 256 // opts is list of boolean parametes 257 // opts[0] - async - Will run the delete request in a background job. Recommended: 'true'. Default to 'true'. 258 // opts[1] - recursive - Will delete all apps, services, routes, and service brokers associated with the space. Default to 'false'. 259 260 func (r *spaces) Delete(spaceGUID string, opts ...bool) error { 261 async := true 262 recursive := false 263 if len(opts) > 0 { 264 async = opts[0] 265 } 266 if len(opts) > 1 { 267 recursive = opts[1] 268 } 269 rawURL := fmt.Sprintf("/v2/spaces/%s?async=%t&recursive=%t", spaceGUID, async, recursive) 270 _, err := r.client.Delete(rawURL) 271 return err 272 } 273 274 func (r *spaces) associateRole(url, userMail string) (*SpaceFields, error) { 275 spaceFields := SpaceFields{} 276 _, err := r.client.Put(url, map[string]string{"username": userMail}, &spaceFields) 277 if err != nil { 278 return nil, err 279 } 280 return &spaceFields, nil 281 } 282 283 func (r *spaces) removeRole(url, userMail string) error { 284 spaceFields := SpaceFields{} 285 _, err := r.client.DeleteWithBody(url, map[string]string{"username": userMail}, &spaceFields) 286 return err 287 } 288 289 func (r *spaces) AssociateManager(spaceGUID string, userMail string) (*SpaceFields, error) { 290 rawURL := fmt.Sprintf("/v2/spaces/%s/managers", spaceGUID) 291 return r.associateRole(rawURL, userMail) 292 } 293 func (r *spaces) AssociateDeveloper(spaceGUID string, userMail string) (*SpaceFields, error) { 294 rawURL := fmt.Sprintf("/v2/spaces/%s/developers", spaceGUID) 295 return r.associateRole(rawURL, userMail) 296 } 297 func (r *spaces) AssociateAuditor(spaceGUID string, userMail string) (*SpaceFields, error) { 298 rawURL := fmt.Sprintf("/v2/spaces/%s/auditors", spaceGUID) 299 return r.associateRole(rawURL, userMail) 300 } 301 302 func (r *spaces) DisassociateManager(spaceGUID string, userMail string) error { 303 rawURL := fmt.Sprintf("/v2/spaces/%s/managers", spaceGUID) 304 return r.removeRole(rawURL, userMail) 305 } 306 307 func (r *spaces) DisassociateDeveloper(spaceGUID string, userMail string) error { 308 rawURL := fmt.Sprintf("/v2/spaces/%s/developers", spaceGUID) 309 return r.removeRole(rawURL, userMail) 310 } 311 func (r *spaces) DisassociateAuditor(spaceGUID string, userMail string) error { 312 rawURL := fmt.Sprintf("/v2/spaces/%s/auditors", spaceGUID) 313 return r.removeRole(rawURL, userMail) 314 } 315 316 func (r *spaces) listSpaceRoles(rawURL string, filters ...string) ([]SpaceRole, error) { 317 req := rest.GetRequest(rawURL) 318 if len(filters) > 0 { 319 req.Query("q", strings.Join(filters, "")) 320 } 321 httpReq, err := req.Build() 322 if err != nil { 323 return nil, err 324 } 325 path := httpReq.URL.String() 326 return r.listSpaceRolesWithPath(path) 327 } 328 329 func (r *spaces) ListAuditors(spaceGUID string, filters ...string) ([]SpaceRole, error) { 330 rawURL := fmt.Sprintf("/v2/spaces/%s/auditors", spaceGUID) 331 return r.listSpaceRoles(rawURL, filters...) 332 } 333 334 func (r *spaces) ListManagers(spaceGUID string, filters ...string) ([]SpaceRole, error) { 335 rawURL := fmt.Sprintf("/v2/spaces/%s/managers", spaceGUID) 336 return r.listSpaceRoles(rawURL, filters...) 337 } 338 func (r *spaces) ListDevelopers(spaceGUID string, filters ...string) ([]SpaceRole, error) { 339 rawURL := fmt.Sprintf("/v2/spaces/%s/developers", spaceGUID) 340 return r.listSpaceRoles(rawURL, filters...) 341 } 342 343 func (r *spaces) ListRoutes(spaceGUID string, routeFilter RouteFilter) ([]Route, error) { 344 rawURL := fmt.Sprintf("/v2/spaces/%s/routes", spaceGUID) 345 req := rest.GetRequest(rawURL) 346 var query string 347 if routeFilter.DomainGUID != "" { 348 query = "domain_guid:" + routeFilter.DomainGUID + ";" 349 } 350 if routeFilter.Host != nil { 351 query += "host:" + *routeFilter.Host + ";" 352 } 353 if routeFilter.Path != nil { 354 query += "path:" + *routeFilter.Path + ";" 355 } 356 if routeFilter.Port != nil { 357 query += "port:" + strconv.Itoa(*routeFilter.Port) + ";" 358 } 359 360 if len(query) > 0 { 361 req.Query("q", query) 362 } 363 364 httpReq, err := req.Build() 365 if err != nil { 366 return nil, err 367 } 368 path := httpReq.URL.String() 369 route, err := listRouteWithPath(r.client, path) 370 if err != nil { 371 return nil, err 372 } 373 return route, nil 374 }