github.com/mhilton/juju-juju@v0.0.0-20150901100907-a94dd2c73455/apiserver/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/loggo" 9 "github.com/juju/names" 10 11 "github.com/juju/juju/apiserver/common" 12 "github.com/juju/juju/apiserver/params" 13 "github.com/juju/juju/state" 14 ) 15 16 var logger = loggo.GetLogger("juju.apiserver.spaces") 17 18 func init() { 19 common.RegisterStandardFacade("Spaces", 1, NewAPI) 20 } 21 22 // API defines the methods the Spaces API facade implements. 23 type API interface { 24 CreateSpaces(params.CreateSpacesParams) (params.ErrorResults, error) 25 ListSpaces() (params.ListSpacesResults, error) 26 } 27 28 // Backing defines the state methods this facede needs, so they can be 29 // mocked for testing. 30 type Backing interface { 31 // AddSpace creates a space 32 AddSpace(name string, subnetIds []string, public bool) error 33 34 // AllSpaces returns all known Juju network spaces. 35 AllSpaces() ([]common.BackingSpace, error) 36 } 37 38 // spacesAPI implements the API interface. 39 type spacesAPI struct { 40 backing Backing 41 resources *common.Resources 42 authorizer common.Authorizer 43 } 44 45 // NewAPI creates a new Space API server-side facade with a 46 // state.State backing. 47 func NewAPI(st *state.State, res *common.Resources, auth common.Authorizer) (API, error) { 48 return newAPIWithBacking(&stateShim{st: st}, res, auth) 49 } 50 51 // newAPIWithBacking creates a new server-side Spaces API facade with 52 // the given Backing. 53 func newAPIWithBacking(backing Backing, resources *common.Resources, authorizer common.Authorizer) (API, error) { 54 // Only clients can access the Spaces facade. 55 if !authorizer.AuthClient() { 56 return nil, common.ErrPerm 57 } 58 return &spacesAPI{ 59 backing: backing, 60 resources: resources, 61 authorizer: authorizer, 62 }, nil 63 } 64 65 // CreateSpaces creates a new Juju network space, associating the 66 // specified subnets with it (optional; can be empty). 67 func (api *spacesAPI) CreateSpaces(args params.CreateSpacesParams) (params.ErrorResults, error) { 68 results := params.ErrorResults{ 69 Results: make([]params.ErrorResult, len(args.Spaces)), 70 } 71 72 for i, space := range args.Spaces { 73 err := api.createOneSpace(space) 74 if err == nil { 75 continue 76 } 77 results.Results[i].Error = common.ServerError(errors.Trace(err)) 78 } 79 80 return results, nil 81 } 82 83 func (api *spacesAPI) createOneSpace(args params.CreateSpaceParams) error { 84 // Validate the args, assemble information for api.backing.AddSpaces 85 var subnets []string 86 87 spaceTag, err := names.ParseSpaceTag(args.SpaceTag) 88 if err != nil { 89 return errors.Trace(err) 90 } 91 92 for _, tag := range args.SubnetTags { 93 subnetTag, err := names.ParseSubnetTag(tag) 94 if err != nil { 95 return errors.Trace(err) 96 } 97 subnets = append(subnets, subnetTag.Id()) 98 } 99 100 // Add the validated space 101 err = api.backing.AddSpace(spaceTag.Id(), subnets, args.Public) 102 if err != nil { 103 return errors.Trace(err) 104 } 105 return nil 106 } 107 108 func backingSubnetToParamsSubnet(subnet common.BackingSubnet) params.Subnet { 109 cidr := subnet.CIDR() 110 vlantag := subnet.VLANTag() 111 providerid := subnet.ProviderId() 112 zones := subnet.AvailabilityZones() 113 status := subnet.Status() 114 var spaceTag names.SpaceTag 115 if subnet.SpaceName() != "" { 116 spaceTag = names.NewSpaceTag(subnet.SpaceName()) 117 } 118 119 return params.Subnet{ 120 CIDR: cidr, 121 VLANTag: vlantag, 122 ProviderId: providerid, 123 Zones: zones, 124 Status: status, 125 SpaceTag: spaceTag.String(), 126 Life: subnet.Life(), 127 } 128 } 129 130 // ListSpaces lists all the available spaces and their associated subnets. 131 func (api *spacesAPI) ListSpaces() (results params.ListSpacesResults, err error) { 132 spaces, err := api.backing.AllSpaces() 133 if err != nil { 134 return results, errors.Trace(err) 135 } 136 137 results.Results = make([]params.Space, len(spaces)) 138 for i, space := range spaces { 139 result := params.Space{} 140 result.Name = space.Name() 141 142 subnets, err := space.Subnets() 143 if err != nil { 144 err = errors.Annotatef(err, "fetching subnets") 145 result.Error = common.ServerError(err) 146 results.Results[i] = result 147 continue 148 } 149 150 result.Subnets = make([]params.Subnet, len(subnets)) 151 for i, subnet := range subnets { 152 result.Subnets[i] = backingSubnetToParamsSubnet(subnet) 153 } 154 results.Results[i] = result 155 } 156 return results, nil 157 }