// CheckName checks whether name is a valid space name. func CheckName(name string) (string, error) { // Validate given name. if !names.IsValidSpace(name) { return "", errors.Errorf("%q is not a valid space name", name) } return name, nil }
func (v *Value) validateSpaces(spaces *[]string) error { if spaces == nil { return nil } for _, name := range *spaces { space := strings.TrimPrefix(name, "^") if !names.IsValidSpace(space) { return errors.Errorf("%q is not a valid space name", space) } } return nil }
func (s *spaceSuite) TestSpaceNames(c *gc.C) { for i, test := range spaceNameTests { c.Logf("test %d: %q", i, test.pattern) c.Check(names.IsValidSpace(test.pattern), gc.Equals, test.valid) if test.valid { expectTag := fmt.Sprintf("%s-%s", names.SpaceTagKind, test.pattern) c.Check(names.NewSpaceTag(test.pattern).String(), gc.Equals, expectTag) } else { expectErr := fmt.Sprintf("%q is not a valid space name", test.pattern) testTag := func() { names.NewSpaceTag(test.pattern) } c.Check(testTag, gc.PanicMatches, regexp.QuoteMeta(expectErr)) } } }
// AddSpace creates and returns a new space. func (st *State) AddSpace(name string, subnets []string, isPublic bool) (newSpace *Space, err error) { defer errors.DeferredAnnotatef(&err, "adding space %q", name) if !names.IsValidSpace(name) { return nil, errors.NewNotValid(nil, "invalid space name") } spaceID := st.docID(name) spaceDoc := spaceDoc{ DocID: spaceID, EnvUUID: st.EnvironUUID(), Life: Alive, Name: name, IsPublic: isPublic, } newSpace = &Space{doc: spaceDoc, st: st} ops := []txn.Op{{ C: spacesC, Id: spaceID, Assert: txn.DocMissing, Insert: spaceDoc, }} for _, subnetId := range subnets { // TODO:(mfoord) once we have refcounting for subnets we should // also assert that the refcount is zero as moving the space of a // subnet in use is not permitted. ops = append(ops, txn.Op{ C: subnetsC, Id: st.docID(subnetId), Assert: txn.DocExists, Update: bson.D{{"$set", bson.D{{"space-name", name}}}}, }) } if err := st.runTransaction(ops); err == txn.ErrAborted { if _, err := st.Space(name); err == nil { return nil, errors.AlreadyExistsf("space %q", name) } for _, subnetId := range subnets { if _, err := st.Subnet(subnetId); errors.IsNotFound(err) { return nil, err } } } else if err != nil { return nil, err } return newSpace, nil }
// Init is defined on the cmd.Command interface. It checks the // arguments for sanity and sets up the command to run. func (c *removeCommand) Init(args []string) (err error) { defer errors.DeferredAnnotatef(&err, "invalid arguments specified") // Validate given name. if len(args) == 0 { return errors.New("space name is required") } givenName := args[0] if !names.IsValidSpace(givenName) { return errors.Errorf("%q is not a valid space name", givenName) } c.name = givenName return cmd.CheckEmpty(args[1:]) }
// Init is defined on the cmd.Command interface. It checks the // arguments for sanity and sets up the command to run. func (c *renameCommand) Init(args []string) (err error) { defer errors.DeferredAnnotatef(&err, "invalid arguments specified") switch len(args) { case 0: return errors.New("old-name is required") case 1: return errors.New("new-name is required") } for _, name := range args { if !names.IsValidSpace(name) { return errors.Errorf("%q is not a valid space name", name) } } c.Name = args[0] c.NewName = args[1] if c.Name == c.NewName { return errors.New("old-name and new-name are the same") } return cmd.CheckEmpty(args[2:]) }
// parseBind parses the --bind option. Valid forms are: // * relation-name=space-name // * space-name // * The above in a space separated list to specify multiple bindings, // e.g. "rel1=space1 rel2=space2 space3" func (c *DeployCommand) parseBind() error { bindings := make(map[string]string) if c.BindToSpaces == "" { return nil } for _, s := range strings.Split(c.BindToSpaces, " ") { s = strings.TrimSpace(s) if s == "" { continue } v := strings.Split(s, "=") var endpoint, space string switch len(v) { case 1: endpoint = "" space = v[0] case 2: if v[0] == "" { return errors.New(parseBindErrorPrefix + "Found = without relation name. Use a lone space name to set the default.") } endpoint = v[0] space = v[1] default: return errors.New(parseBindErrorPrefix + "Found multiple = in binding. Did you forget to space-separate the binding list?") } if !names.IsValidSpace(space) { return errors.New(parseBindErrorPrefix + "Space name invalid.") } bindings[endpoint] = space } c.Bindings = bindings return nil }
func (dw *discoverspacesWorker) handleSubnets() error { environ, ok := environs.SupportsNetworking(dw.config.Environ) if !ok { logger.Debugf("not a networking environ") return nil } if supported, err := environ.SupportsSpaceDiscovery(); err != nil { return errors.Trace(err) } else if !supported { logger.Debugf("environ does not support space discovery") return nil } providerSpaces, err := environ.Spaces() if err != nil { return errors.Trace(err) } facade := dw.config.Facade listSpacesResult, err := facade.ListSpaces() if err != nil { return errors.Trace(err) } stateSubnets, err := facade.ListSubnets(params.SubnetsFilters{}) if err != nil { return errors.Trace(err) } stateSubnetIds := make(set.Strings) for _, subnet := range stateSubnets.Results { stateSubnetIds.Add(subnet.ProviderId) } stateSpaceMap := make(map[string]params.ProviderSpace) spaceNames := make(set.Strings) for _, space := range listSpacesResult.Results { stateSpaceMap[space.ProviderId] = space spaceNames.Add(space.Name) } // TODO(mfoord): we need to delete spaces and subnets that no longer // exist, so long as they're not in use. var createSpacesArgs params.CreateSpacesParams var addSubnetsArgs params.AddSubnetsParams for _, space := range providerSpaces { // Check if the space is already in state, in which case we know // its name. stateSpace, ok := stateSpaceMap[string(space.ProviderId)] var spaceTag names.SpaceTag if ok { spaceName := stateSpace.Name if !names.IsValidSpace(spaceName) { // Can only happen if an invalid name is stored // in state. logger.Errorf("space %q has an invalid name, ignoring", spaceName) continue } spaceTag = names.NewSpaceTag(spaceName) } else { // The space is new, we need to create a valid name for it // in state. spaceName := string(space.Name) // Convert the name into a valid name that isn't already in // use. spaceName = dw.config.NewName(spaceName, spaceNames) spaceNames.Add(spaceName) spaceTag = names.NewSpaceTag(spaceName) // We need to create the space. createSpacesArgs.Spaces = append(createSpacesArgs.Spaces, params.CreateSpaceParams{ Public: false, SpaceTag: spaceTag.String(), ProviderId: string(space.ProviderId), }) } // TODO(mfoord): currently no way of removing subnets, or // changing the space they're in, so we can only add ones we // don't already know about. for _, subnet := range space.Subnets { if stateSubnetIds.Contains(string(subnet.ProviderId)) { continue } zones := subnet.AvailabilityZones if len(zones) == 0 { logger.Tracef( "provider does not specify zones for subnet %q; using 'default' zone as fallback", subnet.CIDR, ) zones = []string{"default"} } addSubnetsArgs.Subnets = append(addSubnetsArgs.Subnets, params.AddSubnetParams{ SubnetProviderId: string(subnet.ProviderId), SpaceTag: spaceTag.String(), Zones: zones, }) } } if err := dw.createSpacesFromArgs(createSpacesArgs); err != nil { return errors.Trace(err) } if err := dw.addSubnetsFromArgs(addSubnetsArgs); err != nil { return errors.Trace(err) } return nil }
// ValidateSpace parses given and returns an error if it's not a valid // space name, otherwise returns the parsed tag and no error. func (s *SubnetCommandBase) ValidateSpace(given string) (names.SpaceTag, error) { if !names.IsValidSpace(given) { return names.SpaceTag{}, errors.Errorf("%q is not a valid space name", given) } return names.NewSpaceTag(given), nil }
func (dw *discoverspacesWorker) handleSubnets(env environs.NetworkingEnviron) error { ok, err := env.SupportsSpaceDiscovery() if err != nil { return errors.Trace(err) } if !ok { // Nothing to do. return nil } providerSpaces, err := env.Spaces() if err != nil { return errors.Trace(err) } listSpacesResult, err := dw.api.ListSpaces() if err != nil { return errors.Trace(err) } stateSubnets, err := dw.api.ListSubnets(params.SubnetsFilters{}) if err != nil { return errors.Trace(err) } stateSubnetIds := make(set.Strings) for _, subnet := range stateSubnets.Results { stateSubnetIds.Add(subnet.ProviderId) } stateSpaceMap := make(map[string]params.ProviderSpace) spaceNames := make(set.Strings) for _, space := range listSpacesResult.Results { stateSpaceMap[space.ProviderId] = space spaceNames.Add(space.Name) } // TODO(mfoord): we need to delete spaces and subnets that no longer // exist, so long as they're not in use. for _, space := range providerSpaces { // Check if the space is already in state, in which case we know // its name. stateSpace, ok := stateSpaceMap[string(space.ProviderId)] var spaceTag names.SpaceTag if ok { spaceName := stateSpace.Name if !names.IsValidSpace(spaceName) { // Can only happen if an invalid name is stored // in state. logger.Errorf("space %q has an invalid name, ignoring", spaceName) continue } spaceTag = names.NewSpaceTag(spaceName) } else { // The space is new, we need to create a valid name for it // in state. spaceName := string(space.ProviderId) // Convert the name into a valid name that isn't already in // use. spaceName = convertSpaceName(spaceName, spaceNames) spaceNames.Add(spaceName) spaceTag = names.NewSpaceTag(spaceName) // We need to create the space. args := params.CreateSpacesParams{ Spaces: []params.CreateSpaceParams{{ Public: false, SpaceTag: spaceTag.String(), ProviderId: string(space.ProviderId), }}} result, err := dw.api.CreateSpaces(args) if err != nil { logger.Errorf("error creating space %v", err) return errors.Trace(err) } if len(result.Results) != 1 { return errors.Errorf("unexpected number of results from CreateSpaces, should be 1: %v", result) } if result.Results[0].Error != nil { return errors.Errorf("error from CreateSpaces: %v", result.Results[0].Error) } } // TODO(mfoord): currently no way of removing subnets, or // changing the space they're in, so we can only add ones we // don't already know about. logger.Debugf("Created space %v with %v subnets", spaceTag.String(), len(space.Subnets)) for _, subnet := range space.Subnets { if stateSubnetIds.Contains(string(subnet.ProviderId)) { continue } zones := subnet.AvailabilityZones if len(zones) == 0 { zones = []string{"default"} } args := params.AddSubnetsParams{ Subnets: []params.AddSubnetParams{{ SubnetProviderId: string(subnet.ProviderId), SpaceTag: spaceTag.String(), Zones: zones, }}} logger.Tracef("Adding subnet %v", subnet.CIDR) result, err := dw.api.AddSubnets(args) if err != nil { logger.Errorf("invalid creating subnet %v", err) return errors.Trace(err) } if len(result.Results) != 1 { return errors.Errorf("unexpected number of results from AddSubnets, should be 1: %v", result) } if result.Results[0].Error != nil { logger.Errorf("error creating subnet %v", result.Results[0].Error) return errors.Errorf("error creating subnet %v", result.Results[0].Error) } } } return nil }
// AddSpace creates and returns a new space. func (st *State) AddSpace(name string, providerId network.Id, subnets []string, isPublic bool) (newSpace *Space, err error) { defer errors.DeferredAnnotatef(&err, "adding space %q", name) if !names.IsValidSpace(name) { return nil, errors.NewNotValid(nil, "invalid space name") } spaceID := st.docID(name) var modelLocalProviderID string if providerId != "" { modelLocalProviderID = st.docID(string(providerId)) } spaceDoc := spaceDoc{ DocID: spaceID, ModelUUID: st.ModelUUID(), Life: Alive, Name: name, IsPublic: isPublic, ProviderId: string(modelLocalProviderID), } newSpace = &Space{doc: spaceDoc, st: st} ops := []txn.Op{{ C: spacesC, Id: spaceID, Assert: txn.DocMissing, Insert: spaceDoc, }} for _, subnetId := range subnets { // TODO:(mfoord) once we have refcounting for subnets we should // also assert that the refcount is zero as moving the space of a // subnet in use is not permitted. ops = append(ops, txn.Op{ C: subnetsC, Id: st.docID(subnetId), Assert: txn.DocExists, Update: bson.D{{"$set", bson.D{{"space-name", name}}}}, }) } if err := st.runTransaction(ops); err == txn.ErrAborted { if _, err := st.Space(name); err == nil { return nil, errors.AlreadyExistsf("space %q", name) } for _, subnetId := range subnets { if _, err := st.Subnet(subnetId); errors.IsNotFound(err) { return nil, err } } } else if err != nil { return nil, err } // If the ProviderId was not unique adding the space can fail without an // error. Refreshing catches this by returning NotFoundError. err = newSpace.Refresh() if err != nil { if errors.IsNotFound(err) { return nil, errors.Errorf("ProviderId %q not unique", providerId) } return nil, errors.Trace(err) } return newSpace, nil }