github.com/cloudfoundry-community/cloudfoundry-cli@v6.44.1-0.20240130060226-cda5ed8e89a5+incompatible/api/cloudcontroller/ccv2/space.go (about) 1 package ccv2 2 3 import ( 4 "bytes" 5 "code.cloudfoundry.org/cli/api/cloudcontroller/ccv2/constant" 6 "encoding/json" 7 "fmt" 8 "net/url" 9 10 "code.cloudfoundry.org/cli/api/cloudcontroller" 11 "code.cloudfoundry.org/cli/api/cloudcontroller/ccerror" 12 "code.cloudfoundry.org/cli/api/cloudcontroller/ccv2/internal" 13 ) 14 15 // Space represents a Cloud Controller Space. 16 type Space struct { 17 // AllowSSH specifies whether SSH is enabled for this space. 18 AllowSSH bool 19 20 // GUID is the unique space identifier. 21 GUID string 22 23 // Name is the name given to the space. 24 Name string 25 26 // OrganizationGUID is the unique identifier of the organization this space 27 // belongs to. 28 OrganizationGUID string 29 30 // SpaceQuotaDefinitionGUID is the unique identifier of the space quota 31 // defined for this space. 32 SpaceQuotaDefinitionGUID string 33 } 34 35 // UnmarshalJSON helps unmarshal a Cloud Controller Space response. 36 func (space *Space) UnmarshalJSON(data []byte) error { 37 var ccSpace struct { 38 Metadata internal.Metadata `json:"metadata"` 39 Entity struct { 40 Name string `json:"name"` 41 AllowSSH bool `json:"allow_ssh"` 42 SpaceQuotaDefinitionGUID string `json:"space_quota_definition_guid"` 43 OrganizationGUID string `json:"organization_guid"` 44 } `json:"entity"` 45 } 46 err := cloudcontroller.DecodeJSON(data, &ccSpace) 47 if err != nil { 48 return err 49 } 50 51 space.GUID = ccSpace.Metadata.GUID 52 space.Name = ccSpace.Entity.Name 53 space.AllowSSH = ccSpace.Entity.AllowSSH 54 space.SpaceQuotaDefinitionGUID = ccSpace.Entity.SpaceQuotaDefinitionGUID 55 space.OrganizationGUID = ccSpace.Entity.OrganizationGUID 56 return nil 57 } 58 59 // UnmarshalJSON helps unmarshal a Cloud Controller Space response. 60 func (space Space) MarshalJSON() ([]byte, error) { 61 ccObj := struct { 62 Name string `json:"name,omitempty"` 63 OrganizationGUID string `json:"organization_guid,omitempty"` 64 AllowSSH bool `json:"allow_ssh"` 65 SpaceQuotaDefinitionGUID string `json:"space_quota_definition_guid,omitempty"` 66 }{ 67 Name: space.Name, 68 OrganizationGUID: space.OrganizationGUID, 69 AllowSSH: space.AllowSSH, 70 SpaceQuotaDefinitionGUID: space.SpaceQuotaDefinitionGUID, 71 } 72 73 return json.Marshal(ccObj) 74 } 75 76 type createSpaceRequestBody struct { 77 Name string `json:"name"` 78 OrganizationGUID string `json:"organization_guid"` 79 } 80 81 // CreateSpace creates a new space with the provided spaceName in the org with 82 // the provided orgGUID. 83 func (client *Client) CreateSpace(spaceName string, orgGUID string) (Space, Warnings, error) { 84 requestBody := createSpaceRequestBody{ 85 Name: spaceName, 86 OrganizationGUID: orgGUID, 87 } 88 89 bodyBytes, _ := json.Marshal(requestBody) 90 91 request, err := client.newHTTPRequest(requestOptions{ 92 RequestName: internal.PostSpaceRequest, 93 Body: bytes.NewReader(bodyBytes), 94 }) 95 96 if err != nil { 97 return Space{}, nil, err 98 } 99 100 var space Space 101 response := cloudcontroller.Response{ 102 DecodeJSONResponseInto: &space, 103 } 104 105 err = client.connection.Make(request, &response) 106 107 return space, response.Warnings, err 108 } 109 110 // CreateSpace creates a new space with the provided spaceName in the org with 111 // the provided orgGUID. 112 func (client *Client) CreateSpaceFromObject(space Space) (Space, Warnings, error) { 113 bodyBytes, _ := json.Marshal(space) 114 115 request, err := client.newHTTPRequest(requestOptions{ 116 RequestName: internal.PostSpaceRequest, 117 Body: bytes.NewReader(bodyBytes), 118 }) 119 120 if err != nil { 121 return Space{}, nil, err 122 } 123 124 var updateSpace Space 125 response := cloudcontroller.Response{ 126 DecodeJSONResponseInto: &updateSpace, 127 } 128 129 err = client.connection.Make(request, &response) 130 131 return updateSpace, response.Warnings, err 132 } 133 134 // DeleteSpace deletes the Space associated with the provided 135 // GUID. It will return the Cloud Controller job that is assigned to the 136 // Space deletion. 137 func (client *Client) DeleteSpace(guid string) (Job, Warnings, error) { 138 request, err := client.newHTTPRequest(requestOptions{ 139 RequestName: internal.DeleteSpaceRequest, 140 URIParams: Params{"space_guid": guid}, 141 Query: url.Values{ 142 "recursive": {"true"}, 143 "async": {"true"}, 144 }, 145 }) 146 if err != nil { 147 return Job{}, nil, err 148 } 149 150 var job Job 151 response := cloudcontroller.Response{ 152 DecodeJSONResponseInto: &job, 153 } 154 155 err = client.connection.Make(request, &response) 156 return job, response.Warnings, err 157 } 158 159 // GetSecurityGroupSpaces returns a list of Spaces based on the provided 160 // SecurityGroup GUID. 161 func (client *Client) GetSecurityGroupSpaces(securityGroupGUID string) ([]Space, Warnings, error) { 162 request, err := client.newHTTPRequest(requestOptions{ 163 RequestName: internal.GetSecurityGroupSpacesRequest, 164 URIParams: map[string]string{"security_group_guid": securityGroupGUID}, 165 }) 166 if err != nil { 167 return nil, nil, err 168 } 169 170 var fullSpacesList []Space 171 warnings, err := client.paginate(request, Space{}, func(item interface{}) error { 172 if space, ok := item.(Space); ok { 173 fullSpacesList = append(fullSpacesList, space) 174 } else { 175 return ccerror.UnknownObjectInListError{ 176 Expected: Space{}, 177 Unexpected: item, 178 } 179 } 180 return nil 181 }) 182 183 return fullSpacesList, warnings, err 184 } 185 186 // GetSecurityGroupStagingSpaces returns a list of Spaces based on the provided 187 // SecurityGroup GUID. 188 func (client *Client) GetSecurityGroupStagingSpaces(securityGroupGUID string) ([]Space, Warnings, error) { 189 request, err := client.newHTTPRequest(requestOptions{ 190 RequestName: internal.GetSecurityGroupStagingSpacesRequest, 191 URIParams: map[string]string{"security_group_guid": securityGroupGUID}, 192 }) 193 if err != nil { 194 return nil, nil, err 195 } 196 197 var fullSpacesList []Space 198 warnings, err := client.paginate(request, Space{}, func(item interface{}) error { 199 if space, ok := item.(Space); ok { 200 fullSpacesList = append(fullSpacesList, space) 201 } else { 202 return ccerror.UnknownObjectInListError{ 203 Expected: Space{}, 204 Unexpected: item, 205 } 206 } 207 return nil 208 }) 209 210 return fullSpacesList, warnings, err 211 } 212 213 // GetSpaces returns a list of Spaces based off of the provided filters. 214 func (client *Client) GetSpaces(filters ...Filter) ([]Space, Warnings, error) { 215 params := ConvertFilterParameters(filters) 216 params.Add("order-by", "name") 217 request, err := client.newHTTPRequest(requestOptions{ 218 RequestName: internal.GetSpacesRequest, 219 Query: params, 220 }) 221 if err != nil { 222 return nil, nil, err 223 } 224 225 var fullSpacesList []Space 226 warnings, err := client.paginate(request, Space{}, func(item interface{}) error { 227 if space, ok := item.(Space); ok { 228 fullSpacesList = append(fullSpacesList, space) 229 } else { 230 return ccerror.UnknownObjectInListError{ 231 Expected: Space{}, 232 Unexpected: item, 233 } 234 } 235 return nil 236 }) 237 238 return fullSpacesList, warnings, err 239 } 240 241 // UpdateSpaceDeveloper grants the space developer role to the user or client 242 // associated with the given UAA ID. 243 func (client *Client) UpdateSpaceDeveloper(spaceGUID string, uaaID string) (Warnings, error) { 244 request, err := client.newHTTPRequest(requestOptions{ 245 RequestName: internal.PutSpaceDeveloperRequest, 246 URIParams: map[string]string{ 247 "space_guid": spaceGUID, 248 "developer_guid": uaaID, 249 }, 250 }) 251 if err != nil { 252 return Warnings{}, err 253 } 254 255 response := cloudcontroller.Response{} 256 err = client.connection.Make(request, &response) 257 return response.Warnings, err 258 } 259 260 type updateRoleRequestBody struct { 261 Username string `json:"username"` 262 } 263 264 // UpdateSpaceDeveloperByUsername grants the given username the space developer role. 265 func (client *Client) UpdateSpaceDeveloperByUsername(spaceGUID string, username string) (Warnings, error) { 266 requestBody := updateRoleRequestBody{ 267 Username: username, 268 } 269 270 bodyBytes, err := json.Marshal(requestBody) 271 if err != nil { 272 return Warnings{}, err 273 } 274 275 request, err := client.newHTTPRequest(requestOptions{ 276 RequestName: internal.PutSpaceDeveloperByUsernameRequest, 277 URIParams: map[string]string{"space_guid": spaceGUID}, 278 Body: bytes.NewReader(bodyBytes), 279 }) 280 if err != nil { 281 return Warnings{}, err 282 } 283 284 response := cloudcontroller.Response{} 285 err = client.connection.Make(request, &response) 286 287 return Warnings(response.Warnings), err 288 } 289 290 // UpdateSpaceAuditorByUsername grants the given username the space developer role. 291 func (client *Client) UpdateSpaceAuditorByUsername(spaceGUID string, username string) (Warnings, error) { 292 requestBody := updateRoleRequestBody{ 293 Username: username, 294 } 295 296 bodyBytes, err := json.Marshal(requestBody) 297 if err != nil { 298 return Warnings{}, err 299 } 300 301 request, err := client.newHTTPRequest(requestOptions{ 302 RequestName: internal.PutSpaceAuditorByUsernameRequest, 303 URIParams: map[string]string{"space_guid": spaceGUID}, 304 Body: bytes.NewReader(bodyBytes), 305 }) 306 if err != nil { 307 return Warnings{}, err 308 } 309 310 response := cloudcontroller.Response{} 311 err = client.connection.Make(request, &response) 312 313 return Warnings(response.Warnings), err 314 } 315 316 // UpdateSpaceManager grants the space manager role to the user or client 317 // associated with the given UAA ID. 318 func (client *Client) UpdateSpaceManager(spaceGUID string, uaaID string) (Warnings, error) { 319 request, err := client.newHTTPRequest(requestOptions{ 320 RequestName: internal.PutSpaceManagerRequest, 321 URIParams: map[string]string{ 322 "space_guid": spaceGUID, 323 "manager_guid": uaaID, 324 }, 325 }) 326 if err != nil { 327 return Warnings{}, err 328 } 329 330 response := cloudcontroller.Response{} 331 err = client.connection.Make(request, &response) 332 return response.Warnings, err 333 } 334 335 // UpdateSpaceManagerByUsername grants the given username the space manager role. 336 func (client *Client) UpdateSpaceManagerByUsername(spaceGUID string, username string) (Warnings, error) { 337 requestBody := updateRoleRequestBody{ 338 Username: username, 339 } 340 341 bodyBytes, err := json.Marshal(requestBody) 342 if err != nil { 343 return Warnings{}, err 344 } 345 request, err := client.newHTTPRequest(requestOptions{ 346 RequestName: internal.PutSpaceManagerByUsernameRequest, 347 URIParams: map[string]string{"space_guid": spaceGUID}, 348 Body: bytes.NewReader(bodyBytes), 349 }) 350 351 if err != nil { 352 return nil, err 353 } 354 355 response := cloudcontroller.Response{} 356 357 err = client.connection.Make(request, &response) 358 359 return response.Warnings, err 360 } 361 362 // GetSpace returns back a space. 363 func (client *Client) GetSpace(guid string) (Space, Warnings, error) { 364 request, err := client.newHTTPRequest(requestOptions{ 365 RequestName: internal.GetSpaceRequest, 366 URIParams: Params{ 367 "space_guid": guid, 368 }, 369 }) 370 if err != nil { 371 return Space{}, nil, err 372 } 373 374 var obj Space 375 response := cloudcontroller.Response{ 376 DecodeJSONResponseInto: &obj, 377 } 378 379 err = client.connection.Make(request, &response) 380 return obj, response.Warnings, err 381 } 382 383 // UpdateSpace updates the space with the given GUID. 384 func (client *Client) UpdateSpace(space Space) (Space, Warnings, error) { 385 body, err := json.Marshal(space) 386 if err != nil { 387 return Space{}, nil, err 388 } 389 390 request, err := client.newHTTPRequest(requestOptions{ 391 RequestName: internal.PutSpaceRequest, 392 URIParams: Params{"space_guid": space.GUID}, 393 Body: bytes.NewReader(body), 394 }) 395 if err != nil { 396 return Space{}, nil, err 397 } 398 399 var updatedObj Space 400 response := cloudcontroller.Response{ 401 DecodeJSONResponseInto: &updatedObj, 402 } 403 404 err = client.connection.Make(request, &response) 405 return updatedObj, response.Warnings, err 406 } 407 408 // UpdateSpaceUserByRole makes the user or client with the given UAA ID a 409 // member of this role in the space . (Only available: SpaceManager, SpaceDeveloper and SpaceAuditor) 410 func (client *Client) UpdateSpaceUserByRole(role constant.UserRole, guid string, uaaID string) (Warnings, error) { 411 paramUserKey := "" 412 requestName := "" 413 switch role { 414 case constant.SpaceManager: 415 paramUserKey = "manager_guid" 416 requestName = internal.PutSpaceManagerRequest 417 case constant.SpaceDeveloper: 418 paramUserKey = "developer_guid" 419 requestName = internal.PutSpaceDeveloperRequest 420 case constant.SpaceAuditor: 421 paramUserKey = "auditor_guid" 422 requestName = internal.PutSpaceAuditorRequest 423 default: 424 return Warnings{}, fmt.Errorf("Not a valid role, it must be one of SpaceManager, SpaceDeveloper and SpaceAuditor") 425 } 426 request, err := client.newHTTPRequest(requestOptions{ 427 RequestName: requestName, 428 URIParams: Params{"space_guid": guid, paramUserKey: uaaID}, 429 }) 430 if err != nil { 431 return nil, err 432 } 433 434 response := cloudcontroller.Response{} 435 err = client.connection.Make(request, &response) 436 437 return response.Warnings, err 438 } 439 440 // UpdateSpaceUserByRole makes the user or client with the given UAA ID a 441 // member of this role in the space . (Only available: SpaceManager, SpaceDeveloper and SpaceAuditor) 442 func (client *Client) DeleteSpaceUserByRole(role constant.UserRole, guid string, uaaID string) (Warnings, error) { 443 paramUserKey := "" 444 requestName := "" 445 switch role { 446 case constant.SpaceManager: 447 paramUserKey = "manager_guid" 448 requestName = internal.DeleteSpaceManagerRequest 449 case constant.SpaceDeveloper: 450 paramUserKey = "developer_guid" 451 requestName = internal.DeleteSpaceDeveloperRequest 452 case constant.SpaceAuditor: 453 paramUserKey = "auditor_guid" 454 requestName = internal.DeleteSpaceAuditorRequest 455 default: 456 return Warnings{}, fmt.Errorf("Not a valid role, it must be one of SpaceManager, SpaceDeveloper and SpaceAuditor") 457 } 458 request, err := client.newHTTPRequest(requestOptions{ 459 RequestName: requestName, 460 URIParams: Params{"space_guid": guid, paramUserKey: uaaID}, 461 }) 462 if err != nil { 463 return nil, err 464 } 465 466 response := cloudcontroller.Response{} 467 err = client.connection.Make(request, &response) 468 469 return response.Warnings, err 470 } 471 472 // GetSpaceUsersByRole find all users for a space by role . 473 // (Only available: SpaceManager, SpaceDeveloper and SpaceAuditor) 474 func (client *Client) GetSpaceUsersByRole(role constant.UserRole, guid string) ([]User, Warnings, error) { 475 requestName := "" 476 switch role { 477 case constant.SpaceManager: 478 requestName = internal.GetSpaceManagersRequest 479 case constant.SpaceDeveloper: 480 requestName = internal.GetSpaceDevelopersRequest 481 case constant.SpaceAuditor: 482 requestName = internal.GetSpaceAuditorsRequest 483 default: 484 return []User{}, Warnings{}, fmt.Errorf("Not a valid role, it must be one of SpaceManager, SpaceDeveloper and SpaceAuditor") 485 } 486 request, err := client.newHTTPRequest(requestOptions{ 487 RequestName: requestName, 488 URIParams: Params{"space_guid": guid}, 489 }) 490 if err != nil { 491 return []User{}, nil, err 492 } 493 494 var fullUsersList []User 495 warnings, err := client.paginate(request, User{}, func(item interface{}) error { 496 if user, ok := item.(User); ok { 497 fullUsersList = append(fullUsersList, user) 498 } else { 499 return ccerror.UnknownObjectInListError{ 500 Expected: User{}, 501 Unexpected: item, 502 } 503 } 504 return nil 505 }) 506 507 return fullUsersList, warnings, err 508 } 509 510 // DeleteSpaceManagerByUsername revoke the given username the space manager role. 511 func (client *Client) DeleteSpaceManagerByUsername(spaceGUID string, username string) (Warnings, error) { 512 requestBody := updateRoleRequestBody{ 513 Username: username, 514 } 515 516 bodyBytes, err := json.Marshal(requestBody) 517 if err != nil { 518 return Warnings{}, err 519 } 520 request, err := client.newHTTPRequest(requestOptions{ 521 RequestName: internal.DeleteSpaceManagerByUsernameRequest, 522 URIParams: map[string]string{"space_guid": spaceGUID}, 523 Body: bytes.NewReader(bodyBytes), 524 }) 525 526 if err != nil { 527 return nil, err 528 } 529 530 response := cloudcontroller.Response{} 531 532 err = client.connection.Make(request, &response) 533 534 return response.Warnings, err 535 } 536 537 // DeleteSpaceAuditorByUsername revoke the given username the space manager role. 538 func (client *Client) DeleteSpaceAuditorByUsername(spaceGUID string, username string) (Warnings, error) { 539 requestBody := updateRoleRequestBody{ 540 Username: username, 541 } 542 543 bodyBytes, err := json.Marshal(requestBody) 544 if err != nil { 545 return Warnings{}, err 546 } 547 request, err := client.newHTTPRequest(requestOptions{ 548 RequestName: internal.DeleteSpaceAuditorByUsernameRequest, 549 URIParams: map[string]string{"space_guid": spaceGUID}, 550 Body: bytes.NewReader(bodyBytes), 551 }) 552 553 if err != nil { 554 return nil, err 555 } 556 557 response := cloudcontroller.Response{} 558 559 err = client.connection.Make(request, &response) 560 561 return response.Warnings, err 562 } 563 564 // DeleteSpaceDeveloperByUsername revoke the given username the space manager role. 565 func (client *Client) DeleteSpaceDeveloperByUsername(spaceGUID string, username string) (Warnings, error) { 566 requestBody := updateRoleRequestBody{ 567 Username: username, 568 } 569 570 bodyBytes, err := json.Marshal(requestBody) 571 if err != nil { 572 return Warnings{}, err 573 } 574 request, err := client.newHTTPRequest(requestOptions{ 575 RequestName: internal.DeleteSpaceDeveloperByUsernameRequest, 576 URIParams: map[string]string{"space_guid": spaceGUID}, 577 Body: bytes.NewReader(bodyBytes), 578 }) 579 580 if err != nil { 581 return nil, err 582 } 583 584 response := cloudcontroller.Response{} 585 586 err = client.connection.Make(request, &response) 587 588 return response.Warnings, err 589 }