Skip to content

Commit 7f50e1c

Browse files
authored
Merge pull request #777 from viola/vpc-support
Add support for vpcs command
2 parents d87958a + 7748a95 commit 7f50e1c

15 files changed

+1194
-0
lines changed

args.go

+7
Original file line numberDiff line numberDiff line change
@@ -285,4 +285,11 @@ const (
285285
ArgObjectName = "name"
286286
// ArgObjectNamespace is the Kubernetes object namespace
287287
ArgObjectNamespace = "namespace"
288+
289+
// ArgVPCName is a name of the VPC.
290+
ArgVPCName = "name"
291+
// ArgVPCDescription is a VPC description.
292+
ArgVPCDescription = "description"
293+
// ArgVPCIPRange is a VPC range of IP addresses in CIDR notation.
294+
ArgVPCIPRange = "ip-range"
288295
)

commands/command_config.go

+2
Original file line numberDiff line numberDiff line change
@@ -62,6 +62,7 @@ type CmdConfig struct {
6262
Kubernetes func() do.KubernetesService
6363
Databases func() do.DatabasesService
6464
Registry func() do.RegistryService
65+
VPCs func() do.VPCsService
6566
}
6667

6768
// NewCmdConfig creates an instance of a CmdConfig.
@@ -107,6 +108,7 @@ func NewCmdConfig(ns string, dc doctl.Config, out io.Writer, args []string, init
107108
c.Kubernetes = func() do.KubernetesService { return do.NewKubernetesService(godoClient) }
108109
c.Databases = func() do.DatabasesService { return do.NewDatabasesService(godoClient) }
109110
c.Registry = func() do.RegistryService { return do.NewRegistryService(godoClient) }
111+
c.VPCs = func() do.VPCsService { return do.NewVPCsService(godoClient) }
110112

111113
return nil
112114
},

commands/commands_test.go

+3
Original file line numberDiff line numberDiff line change
@@ -174,6 +174,7 @@ type tcMocks struct {
174174
kubernetes *domocks.MockKubernetesService
175175
registry *domocks.MockRegistryService
176176
sshRunner *domocks.MockRunner
177+
vpcs *domocks.MockVPCsService
177178
}
178179

179180
func withTestClient(t *testing.T, tFn testFn) {
@@ -209,6 +210,7 @@ func withTestClient(t *testing.T, tFn testFn) {
209210
databases: domocks.NewMockDatabasesService(ctrl),
210211
registry: domocks.NewMockRegistryService(ctrl),
211212
sshRunner: domocks.NewMockRunner(ctrl),
213+
vpcs: domocks.NewMockVPCsService(ctrl),
212214
}
213215

214216
config := &CmdConfig{
@@ -252,6 +254,7 @@ func withTestClient(t *testing.T, tFn testFn) {
252254
Kubernetes: func() do.KubernetesService { return tm.kubernetes },
253255
Databases: func() do.DatabasesService { return tm.databases },
254256
Registry: func() do.RegistryService { return tm.registry },
257+
VPCs: func() do.VPCsService { return tm.vpcs },
255258
}
256259

257260
tFn(config, tm)

commands/displayers/vpc.go

+76
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,76 @@
1+
/*
2+
Copyright 2018 The Doctl Authors All rights reserved.
3+
Licensed under the Apache License, Version 2.0 (the "License");
4+
you may not use this file except in compliance with the License.
5+
You may obtain a copy of the License at
6+
http://www.apache.org/licenses/LICENSE-2.0
7+
Unless required by applicable law or agreed to in writing, software
8+
distributed under the License is distributed on an "AS IS" BASIS,
9+
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
10+
See the License for the specific language governing permissions and
11+
limitations under the License.
12+
*/
13+
14+
package displayers
15+
16+
import (
17+
"io"
18+
19+
"github.com/digitalocean/doctl/do"
20+
)
21+
22+
type VPC struct {
23+
VPCs do.VPCs
24+
}
25+
26+
var _ Displayable = &VPC{}
27+
28+
func (v *VPC) JSON(out io.Writer) error {
29+
return writeJSON(v.VPCs, out)
30+
}
31+
32+
func (v *VPC) Cols() []string {
33+
return []string{
34+
"ID",
35+
"URN",
36+
"Name",
37+
"Description",
38+
"IPRange",
39+
"Region",
40+
"Created",
41+
"Default",
42+
}
43+
}
44+
45+
func (v *VPC) ColMap() map[string]string {
46+
return map[string]string{
47+
"ID": "ID",
48+
"URN": "URN",
49+
"Name": "Name",
50+
"Description": "Description",
51+
"IPRange": "IP Range",
52+
"Region": "Region",
53+
"Created": "Created At",
54+
"Default": "Default",
55+
}
56+
}
57+
58+
func (v *VPC) KV() []map[string]interface{} {
59+
out := []map[string]interface{}{}
60+
61+
for _, v := range v.VPCs {
62+
o := map[string]interface{}{
63+
"ID": v.ID,
64+
"URN": v.URN,
65+
"Name": v.Name,
66+
"Description": v.Description,
67+
"IPRange": v.IPRange,
68+
"Created": v.CreatedAt,
69+
"Region": v.RegionSlug,
70+
"Default": v.Default,
71+
}
72+
out = append(out, o)
73+
}
74+
75+
return out
76+
}

commands/doit.go

+1
Original file line numberDiff line numberDiff line change
@@ -138,6 +138,7 @@ func addCommands() {
138138
DoitCmd.AddCommand(Projects())
139139
DoitCmd.AddCommand(Version())
140140
DoitCmd.AddCommand(Registry())
141+
DoitCmd.AddCommand(VPCs())
141142
}
142143

143144
func computeCmd() *Command {

commands/vpcs.go

+197
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,197 @@
1+
/*
2+
Copyright 2018 The Doctl Authors All rights reserved.
3+
Licensed under the Apache License, Version 2.0 (the "License");
4+
you may not use this file except in compliance with the License.
5+
You may obtain a copy of the License at
6+
http://www.apache.org/licenses/LICENSE-2.0
7+
Unless required by applicable law or agreed to in writing, software
8+
distributed under the License is distributed on an "AS IS" BASIS,
9+
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
10+
See the License for the specific language governing permissions and
11+
limitations under the License.
12+
*/
13+
14+
package commands
15+
16+
import (
17+
"fmt"
18+
"github.com/digitalocean/doctl"
19+
"github.com/digitalocean/doctl/commands/displayers"
20+
"github.com/digitalocean/doctl/do"
21+
"github.com/digitalocean/godo"
22+
"github.com/spf13/cobra"
23+
)
24+
25+
// VPCs creates the vpcs command.
26+
func VPCs() *Command {
27+
28+
cmd := &Command{
29+
Command: &cobra.Command{
30+
Use: "vpcs",
31+
Short: "Display commands that manage VPCs",
32+
Long: `The commands under ` + "`" + `doctl vpcs` + "`" + ` are for managing your VPCs.
33+
34+
With the vpcs command, you can list, create, or delete VPCs, and manage their configuration details.`,
35+
},
36+
}
37+
38+
vpcDetail := `
39+
- The VPC's ID
40+
- The uniform resource name (URN) for the VPC
41+
- The VPC's name
42+
- The VPC's description
43+
- The range of IP addresses in the VPC in CIDR notation
44+
- The datacenter region slug the VPC is located in
45+
- The VPC's default boolean value indicating whether or not the VPC is the default one for the region
46+
- The VPC's creation date, in ISO8601 combined date and time format
47+
`
48+
49+
CmdBuilder(cmd, RunVPCGet, "get <id>", "Retrieve a VPC", "Use this command to retrieve information about a VPC, including:"+vpcDetail, Writer,
50+
aliasOpt("g"), displayerType(&displayers.VPC{}))
51+
52+
cmdRecordCreate := CmdBuilder(cmd, RunVPCCreate, "create",
53+
"Create a new VPC", "Use this command to create a new VPC on your account.", Writer, aliasOpt("c"))
54+
AddStringFlag(cmdRecordCreate, doctl.ArgVPCName, "", "",
55+
"The VPC's name", requiredOpt())
56+
AddStringFlag(cmdRecordCreate, doctl.ArgVPCDescription, "", "", "The VPC's name")
57+
AddStringFlag(cmdRecordCreate, doctl.ArgVPCIPRange, "", "",
58+
"The range of IP addresses in the VPC in CIDR notation, e.g.: `10.116.0.0/20`")
59+
AddStringFlag(cmdRecordCreate, doctl.ArgRegionSlug, "", "", "The VPC's region slug, e.g.: `nyc1`", requiredOpt())
60+
61+
cmdRecordUpdate := CmdBuilder(cmd, RunVPCUpdate, "update <id>",
62+
"Update a VPC's configuration", `Use this command to update the configuration of a specified VPC.`, Writer, aliasOpt("u"))
63+
AddStringFlag(cmdRecordUpdate, doctl.ArgVPCName, "", "",
64+
"The VPC's name", requiredOpt())
65+
AddStringFlag(cmdRecordUpdate, doctl.ArgVPCDescription, "", "",
66+
"The VPC's description")
67+
68+
CmdBuilder(cmd, RunVPCList, "list", "List VPCs", "Use this command to get a list of the VPCs on your account, including the following information for each:"+vpcDetail, Writer,
69+
aliasOpt("ls"), displayerType(&displayers.VPC{}))
70+
71+
cmdRunRecordDelete := CmdBuilder(cmd, RunVPCDelete, "delete <id>",
72+
"Permanently delete a VPC", `Use this command to permanently delete the specified VPC. This is irreversible.`, Writer, aliasOpt("d", "rm"))
73+
AddBoolFlag(cmdRunRecordDelete, doctl.ArgForce, doctl.ArgShortForce, false,
74+
"Delete the VPC without a confirmation prompt")
75+
76+
return cmd
77+
}
78+
79+
// RunVPCGet retrieves an existing VPC by its identifier.
80+
func RunVPCGet(c *CmdConfig) error {
81+
if len(c.Args) != 1 {
82+
return doctl.NewMissingArgsErr(c.NS)
83+
}
84+
vpcUUID := c.Args[0]
85+
86+
vpcs := c.VPCs()
87+
vpc, err := vpcs.Get(vpcUUID)
88+
if err != nil {
89+
return err
90+
}
91+
92+
item := &displayers.VPC{VPCs: do.VPCs{*vpc}}
93+
return c.Display(item)
94+
}
95+
96+
// RunVPCList lists VPCs.
97+
func RunVPCList(c *CmdConfig) error {
98+
vpcs := c.VPCs()
99+
list, err := vpcs.List()
100+
if err != nil {
101+
return err
102+
}
103+
104+
item := &displayers.VPC{VPCs: list}
105+
return c.Display(item)
106+
}
107+
108+
// RunVPCCreate creates a new VPC with a given configuration.
109+
func RunVPCCreate(c *CmdConfig) error {
110+
r := new(godo.VPCCreateRequest)
111+
name, err := c.Doit.GetString(c.NS, doctl.ArgVPCName)
112+
if err != nil {
113+
return err
114+
}
115+
r.Name = name
116+
117+
desc, err := c.Doit.GetString(c.NS, doctl.ArgVPCDescription)
118+
if err != nil {
119+
return err
120+
}
121+
r.Description = desc
122+
123+
ipRange, err := c.Doit.GetString(c.NS, doctl.ArgVPCIPRange)
124+
if err != nil {
125+
return err
126+
}
127+
r.IPRange = ipRange
128+
129+
rSlug, err := c.Doit.GetString(c.NS, doctl.ArgRegionSlug)
130+
if err != nil {
131+
return err
132+
}
133+
r.RegionSlug = rSlug
134+
135+
vpcs := c.VPCs()
136+
vpc, err := vpcs.Create(r)
137+
if err != nil {
138+
return err
139+
}
140+
141+
item := &displayers.VPC{VPCs: do.VPCs{*vpc}}
142+
return c.Display(item)
143+
}
144+
145+
// RunVPCUpdate updates an existing VPC with new configuration.
146+
func RunVPCUpdate(c *CmdConfig) error {
147+
if len(c.Args) == 0 {
148+
return doctl.NewMissingArgsErr(c.NS)
149+
}
150+
vpcUUID := c.Args[0]
151+
152+
r := new(godo.VPCUpdateRequest)
153+
name, err := c.Doit.GetString(c.NS, doctl.ArgVPCName)
154+
if err != nil {
155+
return err
156+
}
157+
r.Name = name
158+
159+
desc, err := c.Doit.GetString(c.NS, doctl.ArgVPCDescription)
160+
if err != nil {
161+
return err
162+
}
163+
r.Description = desc
164+
165+
vpcs := c.VPCs()
166+
vpc, err := vpcs.Update(vpcUUID, r)
167+
if err != nil {
168+
return err
169+
}
170+
171+
item := &displayers.VPC{VPCs: do.VPCs{*vpc}}
172+
return c.Display(item)
173+
}
174+
175+
// RunVPCDelete deletes a VPC by its identifier.
176+
func RunVPCDelete(c *CmdConfig) error {
177+
if len(c.Args) != 1 {
178+
return doctl.NewMissingArgsErr(c.NS)
179+
}
180+
vpcUUID := c.Args[0]
181+
182+
force, err := c.Doit.GetBool(c.NS, doctl.ArgForce)
183+
if err != nil {
184+
return err
185+
}
186+
187+
if force || AskForConfirm("Delete this VPC?") == nil {
188+
vpcs := c.VPCs()
189+
if err := vpcs.Delete(vpcUUID); err != nil {
190+
return err
191+
}
192+
} else {
193+
return fmt.Errorf("operation aborted")
194+
}
195+
196+
return nil
197+
}

0 commit comments

Comments
 (0)