github.com/niedbalski/juju@v0.0.0-20190215020005-8ff100488e47/apiserver/facades/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 9 "github.com/juju/juju/apiserver/common" 10 "github.com/juju/juju/apiserver/common/networkingcommon" 11 "github.com/juju/juju/apiserver/facade" 12 "github.com/juju/juju/apiserver/params" 13 "github.com/juju/juju/environs" 14 "github.com/juju/juju/environs/context" 15 "github.com/juju/juju/permission" 16 "github.com/juju/juju/state" 17 ) 18 19 // API defines the methods the Spaces API facade implements. 20 type API interface { 21 CreateSpaces(params.CreateSpacesParams) (params.ErrorResults, error) 22 ListSpaces() (params.ListSpacesResults, error) 23 ReloadSpaces() error 24 } 25 26 // APIV2 is missing ReloadSpaces method 27 type APIV2 interface { 28 CreateSpaces(params.CreateSpacesParams) (params.ErrorResults, error) 29 ListSpaces() (params.ListSpacesResults, error) 30 } 31 32 // spacesAPI implements the API interface. 33 type spacesAPI struct { 34 backing networkingcommon.NetworkBacking 35 resources facade.Resources 36 authorizer facade.Authorizer 37 context context.ProviderCallContext 38 } 39 40 // NewAPI creates a new Space API server-side facade with a 41 // state.State backing. 42 func NewAPI(st *state.State, res facade.Resources, auth facade.Authorizer) (API, error) { 43 stateShim, err := networkingcommon.NewStateShim(st) 44 if err != nil { 45 return nil, errors.Trace(err) 46 } 47 return newAPIWithBacking(stateShim, state.CallContext(st), res, auth) 48 } 49 50 // newAPIWithBacking creates a new server-side Spaces API facade with 51 // the given Backing. 52 func newAPIWithBacking(backing networkingcommon.NetworkBacking, ctx context.ProviderCallContext, resources facade.Resources, authorizer facade.Authorizer) (API, error) { 53 // Only clients can access the Spaces facade. 54 if !authorizer.AuthClient() { 55 return nil, common.ErrPerm 56 } 57 return &spacesAPI{ 58 backing: backing, 59 resources: resources, 60 authorizer: authorizer, 61 context: ctx, 62 }, nil 63 } 64 65 // NewAPIV2 is a wrapper that creates a V2 spaces API. 66 func NewAPIV2(st *state.State, res facade.Resources, auth facade.Authorizer) (APIV2, error) { 67 return NewAPI(st, res, auth) 68 } 69 70 // CreateSpaces creates a new Juju network space, associating the 71 // specified subnets with it (optional; can be empty). 72 func (api *spacesAPI) CreateSpaces(args params.CreateSpacesParams) (results params.ErrorResults, err error) { 73 isAdmin, err := api.authorizer.HasPermission(permission.AdminAccess, api.backing.ModelTag()) 74 if err != nil && !errors.IsNotFound(err) { 75 return results, errors.Trace(err) 76 } 77 if !isAdmin { 78 return results, common.ServerError(common.ErrPerm) 79 } 80 81 return networkingcommon.CreateSpaces(api.backing, api.context, args) 82 } 83 84 // ListSpaces lists all the available spaces and their associated subnets. 85 func (api *spacesAPI) ListSpaces() (results params.ListSpacesResults, err error) { 86 canRead, err := api.authorizer.HasPermission(permission.ReadAccess, api.backing.ModelTag()) 87 if err != nil && !errors.IsNotFound(err) { 88 return results, errors.Trace(err) 89 } 90 if !canRead { 91 return results, common.ServerError(common.ErrPerm) 92 } 93 94 err = networkingcommon.SupportsSpaces(api.backing, api.context) 95 if err != nil { 96 return results, common.ServerError(errors.Trace(err)) 97 } 98 99 spaces, err := api.backing.AllSpaces() 100 if err != nil { 101 return results, errors.Trace(err) 102 } 103 104 results.Results = make([]params.Space, len(spaces)) 105 for i, space := range spaces { 106 result := params.Space{} 107 result.Name = space.Name() 108 109 subnets, err := space.Subnets() 110 if err != nil { 111 err = errors.Annotatef(err, "fetching subnets") 112 result.Error = common.ServerError(err) 113 results.Results[i] = result 114 continue 115 } 116 117 result.Subnets = make([]params.Subnet, len(subnets)) 118 for i, subnet := range subnets { 119 result.Subnets[i] = networkingcommon.BackingSubnetToParamsSubnet(subnet) 120 } 121 results.Results[i] = result 122 } 123 return results, nil 124 } 125 126 // RefreshSpaces refreshes spaces from substrate 127 func (api *spacesAPI) ReloadSpaces() error { 128 canWrite, err := api.authorizer.HasPermission(permission.WriteAccess, api.backing.ModelTag()) 129 if err != nil && !errors.IsNotFound(err) { 130 return errors.Trace(err) 131 } 132 if !canWrite { 133 return common.ServerError(common.ErrPerm) 134 } 135 env, err := environs.GetEnviron(api.backing, environs.New) 136 if err != nil { 137 return errors.Trace(err) 138 } 139 return errors.Trace(api.backing.ReloadSpaces(env)) 140 }