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  }