1
// Copyright 2015 Canonical Ltd.
2
// Licensed under the AGPLv3, see LICENCE file for details.
10
"launchpad.net/gnuflag"
13
"github.com/juju/errors"
14
"github.com/juju/juju/apiserver/params"
15
"gopkg.in/juju/names.v2"
17
"github.com/juju/juju/cmd/modelcmd"
20
// NewListCommand returns a cammin used to list all subnets
22
func NewListCommand() cmd.Command {
23
return modelcmd.Wrap(&listCommand{})
26
// listCommand displays a list of all subnets known to Juju
27
type listCommand struct {
33
spaceTag *names.SpaceTag
38
const listCommandDoc = `
39
Displays a list of all subnets known to Juju. Results can be filtered
40
using the optional --space and/or --zone arguments to only display
41
subnets associated with a given network space and/or availability zone.
43
Like with other Juju commands, the output and its format can be changed
44
using the --format and --output (or -o) optional arguments. Supported
45
output formats include "yaml" (default) and "json". To redirect the
46
output to a file, use --output.
49
// Info is defined on the cmd.Command interface.
50
func (c *listCommand) Info() *cmd.Info {
53
Args: "[--space <name>] [--zone <name>] [--format yaml|json] [--output <path>]",
54
Purpose: "List subnets known to Juju.",
55
Doc: strings.TrimSpace(listCommandDoc),
56
Aliases: []string{"list-subnets"},
60
// SetFlags is defined on the cmd.Command interface.
61
func (c *listCommand) SetFlags(f *gnuflag.FlagSet) {
62
c.SubnetCommandBase.SetFlags(f)
63
c.Out.AddFlags(f, "yaml", map[string]cmd.Formatter{
64
"yaml": cmd.FormatYaml,
65
"json": cmd.FormatJson,
68
f.StringVar(&c.SpaceName, "space", "", "Filter results by space name")
69
f.StringVar(&c.ZoneName, "zone", "", "Filter results by zone name")
72
// Init is defined on the cmd.Command interface. It checks the
73
// arguments for sanity and sets up the command to run.
74
func (c *listCommand) Init(args []string) error {
75
// No arguments are accepted, just flags.
76
err := cmd.CheckEmpty(args)
81
// Validate space name, if given and store as tag.
83
if c.SpaceName != "" {
84
tag, err := c.ValidateSpace(c.SpaceName)
94
// Run implements Command.Run.
95
func (c *listCommand) Run(ctx *cmd.Context) error {
96
return c.RunWithAPI(ctx, func(api SubnetAPI, ctx *cmd.Context) error {
97
// Validate space and/or zone, if given to display a nicer error
99
// Get the list of subnets, filtering them as requested.
100
subnets, err := api.ListSubnets(c.spaceTag, c.ZoneName)
102
return errors.Annotate(err, "cannot list subnets")
105
// Display a nicer message in case no subnets were found.
106
if len(subnets) == 0 {
107
if c.SpaceName != "" || c.ZoneName != "" {
108
ctx.Infof("no subnets found matching requested criteria")
110
ctx.Infof("no subnets to display")
115
// Construct the output list for displaying with the chosen
117
result := formattedList{
118
Subnets: make(map[string]formattedSubnet),
120
for _, sub := range subnets {
121
subResult := formattedSubnet{
122
ProviderId: sub.ProviderId,
126
// Use the CIDR to determine the subnet type.
127
if ip, _, err := net.ParseCIDR(sub.CIDR); err != nil {
128
return errors.Errorf("subnet %q has invalid CIDR", sub.CIDR)
129
} else if ip.To4() != nil {
130
subResult.Type = typeIPv4
131
} else if ip.To16() != nil {
132
subResult.Type = typeIPv6
134
// Space must be valid, but verify anyway.
135
spaceTag, err := names.ParseSpaceTag(sub.SpaceTag)
137
return errors.Annotatef(err, "subnet %q has invalid space", sub.CIDR)
139
subResult.Space = spaceTag.Id()
141
// Display correct status according to the life cycle value.
144
subResult.Status = statusInUse
145
case params.Dying, params.Dead:
146
subResult.Status = statusTerminating
149
result.Subnets[sub.CIDR] = subResult
152
return c.Out.Write(ctx, result)
160
statusInUse = "in-use"
161
statusTerminating = "terminating"
164
type formattedList struct {
165
Subnets map[string]formattedSubnet `json:"subnets" yaml:"subnets"`
168
type formattedSubnet struct {
169
Type string `json:"type" yaml:"type"`
170
ProviderId string `json:"provider-id,omitempty" yaml:"provider-id,omitempty"`
171
Status string `json:"status,omitempty" yaml:"status,omitempty"`
172
Space string `json:"space" yaml:"space"`
173
Zones []string `json:"zones" yaml:"zones"`