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  }