github.com/juju/juju@v0.0.0-20240430160146-1752b71fcf00/api/client/spaces/spaces.go (about)

     1  // Copyright 2015 Canonical Ltd.
     2  // Licensed under the AGPLv3, see LICENCE file for details.
     3  
     4  package spaces
     5  
     6  import (
     7  	"github.com/juju/errors"
     8  	"github.com/juju/names/v5"
     9  
    10  	"github.com/juju/juju/api/base"
    11  	"github.com/juju/juju/rpc/params"
    12  )
    13  
    14  const spacesFacade = "Spaces"
    15  
    16  // API provides access to the Spaces API facade.
    17  type API struct {
    18  	base.ClientFacade
    19  	facade base.FacadeCaller
    20  }
    21  
    22  // NewAPI creates a new client-side Spaces facade.
    23  func NewAPI(caller base.APICallCloser) *API {
    24  	if caller == nil {
    25  		panic("caller is nil")
    26  	}
    27  	clientFacade, facadeCaller := base.NewClientFacade(caller, spacesFacade)
    28  	return &API{
    29  		ClientFacade: clientFacade,
    30  		facade:       facadeCaller,
    31  	}
    32  }
    33  
    34  func makeCreateSpacesParams(name string, cidrs []string, public bool) params.CreateSpacesParams {
    35  	return params.CreateSpacesParams{
    36  		Spaces: []params.CreateSpaceParams{
    37  			{
    38  				SpaceTag: names.NewSpaceTag(name).String(),
    39  				CIDRs:    cidrs,
    40  				Public:   public,
    41  			},
    42  		},
    43  	}
    44  }
    45  
    46  // CreateSpace creates a new Juju network space, associating the
    47  // specified subnets with it (optional; can be empty).
    48  func (api *API) CreateSpace(name string, cidrs []string, public bool) error {
    49  	var response params.ErrorResults
    50  	var args = makeCreateSpacesParams(name, cidrs, public)
    51  	err := api.facade.FacadeCall("CreateSpaces", args, &response)
    52  	if err != nil {
    53  		if params.IsCodeNotSupported(err) {
    54  			return errors.NewNotSupported(nil, err.Error())
    55  		}
    56  		return errors.Trace(err)
    57  	}
    58  	return response.OneError()
    59  }
    60  
    61  // ShowSpace shows details about a space.
    62  // Containing subnets, applications and machines count associated with it.
    63  func (api *API) ShowSpace(name string) (params.ShowSpaceResult, error) {
    64  	var response params.ShowSpaceResults
    65  	var args interface{}
    66  	args = params.Entities{
    67  		Entities: []params.Entity{{Tag: names.NewSpaceTag(name).String()}},
    68  	}
    69  	err := api.facade.FacadeCall("ShowSpace", args, &response)
    70  	if err != nil {
    71  		if params.IsCodeNotSupported(err) {
    72  			return params.ShowSpaceResult{}, errors.NewNotSupported(nil, err.Error())
    73  		}
    74  		return params.ShowSpaceResult{}, errors.Trace(err)
    75  	}
    76  	if len(response.Results) != 1 {
    77  		return params.ShowSpaceResult{}, errors.Errorf("expected 1 result, got %d", len(response.Results))
    78  	}
    79  
    80  	result := response.Results[0]
    81  	if err := result.Error; err != nil {
    82  		return params.ShowSpaceResult{}, errors.Trace(err)
    83  	}
    84  	return result, err
    85  }
    86  
    87  // ListSpaces lists all available spaces and their associated subnets.
    88  func (api *API) ListSpaces() ([]params.Space, error) {
    89  	var response params.ListSpacesResults
    90  	err := api.facade.FacadeCall("ListSpaces", nil, &response)
    91  	if params.IsCodeNotSupported(err) {
    92  		return response.Results, errors.NewNotSupported(nil, err.Error())
    93  	}
    94  	return response.Results, err
    95  }
    96  
    97  // ReloadSpaces reloads spaces from substrate.
    98  func (api *API) ReloadSpaces() error {
    99  	err := api.facade.FacadeCall("ReloadSpaces", nil, nil)
   100  	if params.IsCodeNotSupported(err) {
   101  		return errors.NewNotSupported(nil, err.Error())
   102  	}
   103  	return err
   104  }
   105  
   106  // RenameSpace attempts to rename a space from the old name to a new name.
   107  func (api *API) RenameSpace(oldName string, newName string) error {
   108  	var response params.ErrorResults
   109  	spaceRenameParams := make([]params.RenameSpaceParams, 1)
   110  	spaceRename := params.RenameSpaceParams{
   111  		FromSpaceTag: names.NewSpaceTag(oldName).String(),
   112  		ToSpaceTag:   names.NewSpaceTag(newName).String(),
   113  	}
   114  	spaceRenameParams[0] = spaceRename
   115  	args := params.RenameSpacesParams{Changes: spaceRenameParams}
   116  	err := api.facade.FacadeCall("RenameSpace", args, &response)
   117  	if err != nil {
   118  		if params.IsCodeNotSupported(err) {
   119  			return errors.NewNotSupported(nil, err.Error())
   120  		}
   121  		return errors.Trace(err)
   122  	}
   123  	if err := response.Combine(); err != nil {
   124  		return errors.Trace(err)
   125  	}
   126  	return nil
   127  }
   128  
   129  // RemoveSpace removes a space.
   130  func (api *API) RemoveSpace(name string, force bool, dryRun bool) (params.RemoveSpaceResult, error) {
   131  	var response params.RemoveSpaceResults
   132  	args := params.RemoveSpaceParams{
   133  		SpaceParams: []params.RemoveSpaceParam{{
   134  			Space:  params.Entity{Tag: names.NewSpaceTag(name).String()},
   135  			Force:  force,
   136  			DryRun: dryRun,
   137  		}},
   138  	}
   139  	err := api.facade.FacadeCall("RemoveSpace", args, &response)
   140  	if err != nil {
   141  		if params.IsCodeNotSupported(err) {
   142  			return params.RemoveSpaceResult{}, errors.NewNotSupported(nil, err.Error())
   143  		}
   144  		return params.RemoveSpaceResult{}, errors.Trace(err)
   145  	}
   146  	if len(response.Results) != 1 {
   147  		return params.RemoveSpaceResult{}, errors.Errorf("%d results, expected 1", len(response.Results))
   148  	}
   149  
   150  	result := response.Results[0]
   151  	if result.Error != nil {
   152  		return params.RemoveSpaceResult{}, result.Error
   153  	}
   154  	return result, nil
   155  }
   156  
   157  // MoveSubnets ensures that the input subnets are in the input space.
   158  func (api *API) MoveSubnets(space names.SpaceTag, subnets []names.SubnetTag, force bool) (params.MoveSubnetsResult, error) {
   159  	subnetTags := make([]string, len(subnets))
   160  	for k, subnet := range subnets {
   161  		subnetTags[k] = subnet.String()
   162  	}
   163  
   164  	args := params.MoveSubnetsParams{
   165  		Args: []params.MoveSubnetsParam{{
   166  			SubnetTags: subnetTags,
   167  			SpaceTag:   space.String(),
   168  			Force:      force,
   169  		}},
   170  	}
   171  
   172  	var results params.MoveSubnetsResults
   173  	if err := api.facade.FacadeCall("MoveSubnets", args, &results); err != nil {
   174  		if params.IsCodeNotSupported(err) {
   175  			return params.MoveSubnetsResult{}, errors.NewNotSupported(nil, err.Error())
   176  		}
   177  		return params.MoveSubnetsResult{}, errors.Trace(err)
   178  	}
   179  
   180  	if len(results.Results) != 1 {
   181  		return params.MoveSubnetsResult{}, errors.Errorf("expected 1 result, got %d", len(results.Results))
   182  	}
   183  
   184  	result := results.Results[0]
   185  	if result.Error != nil {
   186  		return result, errors.Trace(result.Error)
   187  	}
   188  
   189  	return result, nil
   190  }