Beispiel #1
0
// Run implements Command.Run.
func (c *ListCommand) Run(ctx *cmd.Context) error {
	return c.RunWithAPI(ctx, func(api SubnetAPI, ctx *cmd.Context) error {
		// Validate space and/or zone, if given to display a nicer error
		// message.
		// Get the list of subnets, filtering them as requested.
		subnets, err := api.ListSubnets(c.spaceTag, c.ZoneName)
		if err != nil {
			return errors.Annotate(err, "cannot list subnets")
		}

		// Display a nicer message in case no subnets were found.
		if len(subnets) == 0 {
			if c.SpaceName != "" || c.ZoneName != "" {
				ctx.Infof("no subnets found matching requested criteria")
			} else {
				ctx.Infof("no subnets to display")
			}
			return nil
		}

		// Construct the output list for displaying with the chosen
		// format.
		result := formattedList{
			Subnets: make(map[string]formattedSubnet),
		}
		for _, sub := range subnets {
			subResult := formattedSubnet{
				ProviderId: sub.ProviderId,
				Zones:      sub.Zones,
			}

			// Use the CIDR to determine the subnet type.
			if ip, _, err := net.ParseCIDR(sub.CIDR); err != nil {
				return errors.Errorf("subnet %q has invalid CIDR", sub.CIDR)
			} else if ip.To4() != nil {
				subResult.Type = typeIPv4
			} else if ip.To16() != nil {
				subResult.Type = typeIPv6
			}
			// Space must be valid, but verify anyway.
			spaceTag, err := names.ParseSpaceTag(sub.SpaceTag)
			if err != nil {
				return errors.Annotatef(err, "subnet %q has invalid space", sub.CIDR)
			}
			subResult.Space = spaceTag.Id()

			// Display correct status according to the life cycle value.
			switch sub.Life {
			case params.Alive:
				subResult.Status = statusInUse
			case params.Dying, params.Dead:
				subResult.Status = statusTerminating
			}

			result.Subnets[sub.CIDR] = subResult
		}

		return c.out.Write(ctx, result)
	})
}
Beispiel #2
0
func (s *spaceSuite) TestParseSpaceTag(c *gc.C) {
	for i, t := range parseSpaceTagTests {
		c.Logf("test %d: %s", i, t.tag)
		got, err := names.ParseSpaceTag(t.tag)
		if err != nil || t.err != nil {
			c.Check(err, gc.DeepEquals, t.err)
			continue
		}
		c.Check(got, gc.FitsTypeOf, t.expected)
		c.Check(got, gc.Equals, t.expected)
	}
}
Beispiel #3
0
// ListSubnets lists all the available subnets or only those matching
// all given optional filters.
func ListSubnets(api NetworkBacking, args params.SubnetsFilters) (results params.ListSubnetsResults, err error) {
	subnets, err := api.AllSubnets()
	if err != nil {
		return results, errors.Trace(err)
	}

	var spaceFilter string
	if args.SpaceTag != "" {
		tag, err := names.ParseSpaceTag(args.SpaceTag)
		if err != nil {
			return results, errors.Trace(err)
		}
		spaceFilter = tag.Id()
	}
	zoneFilter := args.Zone

	for _, subnet := range subnets {
		if spaceFilter != "" && subnet.SpaceName() != spaceFilter {
			logger.Tracef(
				"filtering subnet %q from space %q not matching filter %q",
				subnet.CIDR(), subnet.SpaceName(), spaceFilter,
			)
			continue
		}
		zoneSet := set.NewStrings(subnet.AvailabilityZones()...)
		if zoneFilter != "" && !zoneSet.IsEmpty() && !zoneSet.Contains(zoneFilter) {
			logger.Tracef(
				"filtering subnet %q with zones %v not matching filter %q",
				subnet.CIDR(), subnet.AvailabilityZones(), zoneFilter,
			)
			continue
		}
		result := params.Subnet{
			CIDR:       subnet.CIDR(),
			ProviderId: string(subnet.ProviderId()),
			VLANTag:    subnet.VLANTag(),
			Life:       subnet.Life(),
			SpaceTag:   names.NewSpaceTag(subnet.SpaceName()).String(),
			Zones:      subnet.AvailabilityZones(),
			Status:     subnet.Status(),
		}
		results.Results = append(results.Results, result)
	}
	return results, nil
}
Beispiel #4
0
// validateSpace parses the given spaceTag and verifies it exists by looking it
// up in the cache (or populates the cache if empty).
func (cache *addSubnetsCache) validateSpace(spaceTag string) (*names.SpaceTag, error) {
	if spaceTag == "" {
		return nil, errors.Errorf("SpaceTag is required")
	}
	tag, err := names.ParseSpaceTag(spaceTag)
	if err != nil {
		return nil, errors.Annotate(err, "given SpaceTag is invalid")
	}

	// Otherwise we need the cache to validate.
	if cache.allSpaces == nil {
		// Not yet cached.
		logger.Tracef("caching known spaces")

		allSpaces, err := cache.api.AllSpaces()
		if err != nil {
			return nil, errors.Annotate(err, "cannot validate given SpaceTag")
		}
		cache.allSpaces = set.NewStrings()
		for _, space := range allSpaces {
			if cache.allSpaces.Contains(space.Name()) {
				logger.Warningf("ignoring duplicated space %q", space.Name())
				continue
			}
			cache.allSpaces.Add(space.Name())
		}
	}
	if cache.allSpaces.IsEmpty() {
		return nil, errors.Errorf("no spaces defined")
	}
	logger.Tracef("using cached spaces: %v", cache.allSpaces.SortedValues())

	if !cache.allSpaces.Contains(tag.Id()) {
		return nil, errors.NotFoundf("space %q", tag.Id()) // " not found"
	}
	return &tag, nil
}
Beispiel #5
0
func (api *spacesAPI) createOneSpace(args params.CreateSpaceParams) error {
	// Validate the args, assemble information for api.backing.AddSpaces
	var subnets []string

	spaceTag, err := names.ParseSpaceTag(args.SpaceTag)
	if err != nil {
		return errors.Trace(err)
	}

	for _, tag := range args.SubnetTags {
		subnetTag, err := names.ParseSubnetTag(tag)
		if err != nil {
			return errors.Trace(err)
		}
		subnets = append(subnets, subnetTag.Id())
	}

	// Add the validated space
	err = api.backing.AddSpace(spaceTag.Id(), subnets, args.Public)
	if err != nil {
		return errors.Trace(err)
	}
	return nil
}