Skip to content

Commit 615aac1

Browse files
irusoeqxcodinja1188
authored andcommitted
feat: VRF support
1 parent a64058f commit 615aac1

10 files changed

+326
-0
lines changed

.DS_Store

6 KB
Binary file not shown.

cmd/cli.go

+2
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,7 @@ import (
2727
"github.com/equinix/metal-cli/internal/twofa"
2828
"github.com/equinix/metal-cli/internal/users"
2929
"github.com/equinix/metal-cli/internal/vlan"
30+
"github.com/equinix/metal-cli/internal/vrf"
3031
)
3132

3233
// Cli struct
@@ -93,5 +94,6 @@ func (cli *Cli) RegisterCommands(client *root.Client) {
9394
twofa.NewClient(client, cli.Outputer).NewCommand(),
9495
gateway.NewClient(client, cli.Outputer).NewCommand(),
9596
ports.NewClient(client, cli.Outputer).NewCommand(),
97+
vrf.NewClient(client, cli.Outputer).NewCommand(),
9698
)
9799
}

docs/metal.md

+1
Original file line numberDiff line numberDiff line change
@@ -46,4 +46,5 @@ Command line interface for Equinix Metal
4646
* [metal ssh-key](metal_ssh-key.md) - SSH key operations: create, get, update, and delete.
4747
* [metal user](metal_user.md) - User operations: get and add.
4848
* [metal virtual-network](metal_virtual-network.md) - Virtual network (VLAN) operations : create, get, delete.
49+
* [metal vrf](metal_vrf.md) - VRF operations : create, TODO: make other commands.
4950

docs/metal_vrf.md

+34
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
## metal vrf
2+
3+
VRF operations : create, TODO: make other commands.
4+
5+
### Synopsis
6+
7+
Experimental VRF function
8+
9+
### Options
10+
11+
```
12+
-h, --help help for vrf
13+
```
14+
15+
### Options inherited from parent commands
16+
17+
```
18+
--config string Path to JSON or YAML configuration file
19+
--exclude strings Comma separated Href references to collapse in results, may be dotted three levels deep
20+
--filter stringArray Filter 'get' actions with name value pairs. Filter is not supported by all resources and is implemented as request query parameters.
21+
--http-header strings Headers to add to requests (in format key=value)
22+
--include strings Comma separated Href references to expand in results, may be dotted three levels deep
23+
-o, --output string Output format (*table, json, yaml). env output formats are (*sh, terraform, capp).
24+
--search string Search keyword for use in 'get' actions. Search is not supported by all resources.
25+
--sort-by string Sort fields for use in 'get' actions. Sort is not supported by all resources.
26+
--sort-dir string Sort field direction for use in 'get' actions. Sort is not supported by all resources.
27+
--token string Metal API Token (METAL_AUTH_TOKEN)
28+
```
29+
30+
### SEE ALSO
31+
32+
* [metal](metal.md) - Command line interface for Equinix Metal
33+
* [metal vrf create](metal_vrf_create.md) - Creates a Virtual Routing and Forwarding(VRF) for a specified project.
34+

docs/metal_vrf_create.md

+52
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,52 @@
1+
## metal vrf create
2+
3+
Creates a Virtual Routing and Forwarding(VRF) for a specified project.
4+
5+
### Synopsis
6+
7+
Creates a Creates a Virtual Routing and Forwarding(VRF) for a specified project.
8+
9+
```
10+
metal vrf create vrf <my_vrf> [-m <metro_code>] [-AS int] [-I str] [-d <description>] [flags]
11+
```
12+
13+
### Examples
14+
15+
```
16+
# Creates an Creates a Virtual Routing and Forwarding(VRF) for a specified project.
17+
18+
metal vrf create [-p <project_id] [-d <description>] [-m <metro>] [-n <name>] [-a <localASN>] [-r <IPranges>] [-t <tags> ]
19+
```
20+
21+
### Options
22+
23+
```
24+
-d, --description string Description of the VRF.
25+
-h, --help help for create
26+
-r, --ip-ranges strings A list of CIDR network addresses. Like [10.0.0.0/16, 2001:d78::/56]. IPv4 blocks must be between /8 and /29 in size. IPv6 blocks must be between /56 and /64.
27+
-a, --local-asn int32 Local ASN for the VRF
28+
-m, --metro string The UUID (or metro code) for the Metro in which to create this VRF.
29+
-n, --name string Name of the VRF
30+
-p, --project-id string The project's UUID. This flag is required, unless specified in the config created by metal init or set as METAL_PROJECT_ID environment variable.
31+
-t, --tags strings Adds or updates the tags for the connection --tags="tag1,tag2".
32+
```
33+
34+
### Options inherited from parent commands
35+
36+
```
37+
--config string Path to JSON or YAML configuration file
38+
--exclude strings Comma separated Href references to collapse in results, may be dotted three levels deep
39+
--filter stringArray Filter 'get' actions with name value pairs. Filter is not supported by all resources and is implemented as request query parameters.
40+
--http-header strings Headers to add to requests (in format key=value)
41+
--include strings Comma separated Href references to expand in results, may be dotted three levels deep
42+
-o, --output string Output format (*table, json, yaml). env output formats are (*sh, terraform, capp).
43+
--search string Search keyword for use in 'get' actions. Search is not supported by all resources.
44+
--sort-by string Sort fields for use in 'get' actions. Sort is not supported by all resources.
45+
--sort-dir string Sort field direction for use in 'get' actions. Sort is not supported by all resources.
46+
--token string Metal API Token (METAL_AUTH_TOKEN)
47+
```
48+
49+
### SEE ALSO
50+
51+
* [metal vrf](metal_vrf.md) - VRF operations : create, TODO: make other commands.
52+

go.sum

+4
Original file line numberDiff line numberDiff line change
@@ -257,6 +257,8 @@ golang.org/x/mod v0.2.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
257257
golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
258258
golang.org/x/mod v0.4.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
259259
golang.org/x/mod v0.4.1/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
260+
golang.org/x/mod v0.12.0 h1:rmsUpXtvNzj340zd98LZ4KntptpfRHwpFOHG188oHXc=
261+
golang.org/x/mod v0.12.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs=
260262
golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
261263
golang.org/x/net v0.0.0-20180826012351-8a410e7b638d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
262264
golang.org/x/net v0.0.0-20190108225652-1e06a53dbb7e/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
@@ -410,6 +412,8 @@ golang.org/x/tools v0.0.0-20201208233053-a543418bbed2/go.mod h1:emZCQorbCU4vsT4f
410412
golang.org/x/tools v0.0.0-20210105154028-b0ab187a4818/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA=
411413
golang.org/x/tools v0.0.0-20210108195828-e2f9c7f1fc8e/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA=
412414
golang.org/x/tools v0.1.0/go.mod h1:xkSsbof2nBLbhDlRMhhhyNLN/zl3eTqcnHD5viDpcZ0=
415+
golang.org/x/tools v0.13.0 h1:Iey4qkscZuv0VvIt8E0neZjtPVQFSc870HQ448QgEmQ=
416+
golang.org/x/tools v0.13.0/go.mod h1:HvlwmtVNQAhOuCjW7xxvovg8wbNq7LwfXh/k7wXUl58=
413417
golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
414418
golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
415419
golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=

internal/vrf/create.go

+77
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,77 @@
1+
package vrf
2+
3+
import (
4+
"context"
5+
"fmt"
6+
"strconv"
7+
"strings"
8+
9+
metal "github.com/equinix-labs/metal-go/metal/v1"
10+
"github.com/spf13/cobra"
11+
)
12+
13+
func (c *Client) Create() *cobra.Command {
14+
var (
15+
projectID string
16+
metro string
17+
name string
18+
description string
19+
ipRanges []string
20+
localASN int32
21+
tags []string
22+
)
23+
24+
// createVRFCmd represents the creatVRF command
25+
createVRFCmd := &cobra.Command{
26+
Use: "create vrf <my_vrf> [-m <metro_code>] [-AS int] [-I str] [-d <description>]",
27+
Short: "Creates a Virtual Routing and Forwarding(VRF) for a specified project.",
28+
Long: "Creates a Creates a Virtual Routing and Forwarding(VRF) for a specified project.",
29+
Example: ` # Creates an Creates a Virtual Routing and Forwarding(VRF) for a specified project.
30+
31+
metal vrf create [-p <project_id] [-d <description>] [-m <metro>] [-n <name>] [-a <localASN>] [-r <IPranges>] [-t <tags> ]`,
32+
RunE: func(cmd *cobra.Command, args []string) error {
33+
cmd.SilenceUsage = true
34+
35+
req := metal.VrfCreateInput{
36+
Metro: metro,
37+
Name: name,
38+
IpRanges: ipRanges,
39+
LocalAsn: &localASN,
40+
Tags: tags,
41+
Description: &description,
42+
}
43+
44+
inc := []string{}
45+
exc := []string{}
46+
vrfRequest, _, err := c.Service.CreateVrf(context.Background(), projectID).VrfCreateInput(req).Exclude(c.Servicer.Excludes(exc)).Include(c.Servicer.Includes(inc)).Execute()
47+
if err != nil {
48+
return fmt.Errorf("Could not create VRF: %w", err)
49+
}
50+
51+
data := make([][]string, 1)
52+
53+
// This output block below is probably incorrect but leaving it for now for testing later.
54+
data[0] = []string{vrfRequest.GetName(), vrfRequest.Metro.GetCode(), vrfRequest.GetDescription(), strconv.Itoa(int(vrfRequest.GetLocalAsn())), strings.Join(vrfRequest.GetIpRanges(), ","), vrfRequest.GetCreatedAt().String()}
55+
header := []string{"Name", "Metro", "Description", "LocalASN", "IPrange", "Created"}
56+
57+
return c.Out.Output(vrfRequest, header, &data)
58+
},
59+
}
60+
61+
createVRFCmd.Flags().StringVarP(&projectID, "project-id", "p", "", "The project's UUID. This flag is required, unless specified in the config created by metal init or set as METAL_PROJECT_ID environment variable.")
62+
createVRFCmd.Flags().StringSliceVarP(&tags, "tags", "t", []string{}, `Adds or updates the tags for the connection --tags="tag1,tag2".`)
63+
createVRFCmd.Flags().StringVarP(&name, "name", "n", "", "Name of the VRF")
64+
createVRFCmd.Flags().StringVarP(&description, "description", "d", "", "Description of the VRF.")
65+
66+
createVRFCmd.Flags().StringVarP(&metro, "metro", "m", "", "The UUID (or metro code) for the Metro in which to create this VRF.")
67+
createVRFCmd.Flags().Int32VarP(&localASN, "local-asn", "a", 0, "Local ASN for the VRF")
68+
createVRFCmd.Flags().StringSliceVarP(&ipRanges, "ip-ranges", "r", []string{}, "A list of CIDR network addresses. Like [10.0.0.0/16, 2001:d78::/56]. IPv4 blocks must be between /8 and /29 in size. IPv6 blocks must be between /56 and /64.")
69+
70+
// making them all required here
71+
_ = createVRFCmd.MarkFlagRequired("name")
72+
_ = createVRFCmd.MarkFlagRequired("metro")
73+
_ = createVRFCmd.MarkFlagRequired("local-asn")
74+
_ = createVRFCmd.MarkFlagRequired("IPrange")
75+
76+
return createVRFCmd
77+
}

internal/vrf/delete.go

+63
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,63 @@
1+
package vrf
2+
3+
// import (
4+
// "fmt"
5+
6+
// "github.com/manifoldco/promptui"
7+
// "github.com/spf13/cobra"
8+
// )
9+
10+
// func (c *Client) Delete() *cobra.Command {
11+
// var (
12+
// vrfID string
13+
// force bool
14+
// )
15+
16+
// deleteVrf := func(id string) error {
17+
// _, err := c.Service.Delete(id)
18+
// if err != nil {
19+
// return err
20+
// }
21+
// fmt.Println("VRF", id, "successfully deleted.")
22+
// return nil // No need to return 'err' here; it's always nil.
23+
// }
24+
25+
// deleteMetalVrfCmd := &cobra.Command{
26+
// Use: "delete vrf -i <metal_vrf_UUID> [-f]",
27+
// Short: "Deletes a VRF.",
28+
// Long: "Deletes the specified VRF with a confirmation prompt. To skip the confirmation, use --force.",
29+
// Example: `# Deletes a VRF, with confirmation.
30+
// metal delete vrf -i 77e6d57a-d7a4-4816-b451-cf9b043444e2
31+
32+
// # Deletes a VRF, skipping confirmation.
33+
// metal delete vrf -f -i 77e6d57a-d7a4-4816-b451-cf9b043444e2`,
34+
// RunE: func(cmd *cobra.Command, args []string) error {
35+
// cmd.SilenceUsage = true
36+
37+
// if !force {
38+
// prompt := promptui.Prompt{
39+
// Label: fmt.Sprintf("Are you sure you want to delete VRF %s: ", vrfID),
40+
// IsConfirm: true,
41+
// }
42+
43+
// result, err := prompt.Run()
44+
// if err != nil || result != "y" {
45+
// fmt.Println("VRF deletion aborted.")
46+
// return nil
47+
// }
48+
// }
49+
50+
// if err := deleteVrf(vrfID); err != nil {
51+
// return fmt.Errorf("Could not delete VRF: %w", err)
52+
// }
53+
54+
// return nil
55+
// },
56+
// }
57+
58+
// deleteMetalVrfCmd.Flags().StringVarP(&vrfID, "id", "i", "", "UUID of the VRF.")
59+
// _ = deleteMetalVrfCmd.MarkFlagRequired("id")
60+
// deleteMetalVrfCmd.Flags().BoolVarP(&force, "force", "f", false, "Skips confirmation for the removal of the VRF.")
61+
62+
// return deleteMetalVrfCmd
63+
// }

internal/vrf/retrieve.go

+43
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,43 @@
1+
package vrf
2+
3+
// import (
4+
// "fmt"
5+
6+
// "github.com/spf13/cobra"
7+
// )
8+
9+
// func (c *Client) Retrieve() *cobra.Command {
10+
// var projectID string
11+
12+
// // retrieveVrfsCmd represents the retrieveMetalGateways command
13+
// retrieveVrfsCmd := &cobra.Command{
14+
// Use: `get -p <project_UUID>`,
15+
// Aliases: []string{"list"},
16+
// Short: "Lists VRFs.",
17+
// Long: "Retrieves a list of all VRFs for the specified project.",
18+
// Example: `
19+
// # Lists VRFs for project 3b0795ba-ec9a-4a9e-83a7-043e7e11407c:
20+
// metal vrf list -p 3b0795ba-ec9a-4a9e-83a7-043e7e11407c`,
21+
22+
// RunE: func(cmd *cobra.Command, args []string) error {
23+
// cmd.SilenceUsage = true
24+
// vrfs, _, err := c.Service.Get(ProjectID, c.Servicer.GetOptions(nil, nil)) // <- Not sure about the correct service to call Im assuming its this? https://github.com/packethost/packngo/blob/master/vrf.go
25+
// if err != nil {
26+
// return fmt.Errorf("Could not list VRFs: %w", err)
27+
// }
28+
29+
// data := make([][]string, len(vrfs.VirtualRoutingFunctions))
30+
31+
// for i, n := range vnets.VirtualRoutingFunctions {
32+
// data[i] = []string{n.ID, n.Description, n.IPranges, n.LocalASN, n.Metro, n.CreatedAt} //Data should contain all info about VRF not sure where the formatting comes from, going with this.
33+
// }
34+
// header := []string{"ID", "Description", "VXLAN", "Facility", "Created"}
35+
36+
// return c.Out.Output(vrfs, header, &data)
37+
// },
38+
// }
39+
// retrieveVrfsCmd.Flags().StringVarP(&projectID, "project-id", "p", "", "The project's UUID. This flag is required, unless specified in the config created by metal init or set as METAL_PROJECT_ID environment variable.")
40+
// _ = retrieveVrfsCmd.MarkFlagRequired("project-id")
41+
42+
// return retrieveVrfsCmd
43+
// }

internal/vrf/vrf.go

+50
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,50 @@
1+
package vrf
2+
3+
import (
4+
metal "github.com/equinix-labs/metal-go/metal/v1"
5+
"github.com/equinix/metal-cli/internal/outputs"
6+
"github.com/spf13/cobra"
7+
)
8+
9+
type Client struct {
10+
Servicer Servicer
11+
Service metal.VRFsApiService
12+
Out outputs.Outputer
13+
}
14+
15+
func (c *Client) NewCommand() *cobra.Command {
16+
cmd := &cobra.Command{
17+
Use: `vrf`,
18+
Aliases: []string{"vrf"},
19+
Short: "VRF operations : create, TODO: make other commands.",
20+
Long: "Experimental VRF function",
21+
22+
PersistentPreRun: func(cmd *cobra.Command, args []string) {
23+
if root := cmd.Root(); root != nil {
24+
if root.PersistentPreRun != nil {
25+
root.PersistentPreRun(cmd, args)
26+
}
27+
}
28+
c.Service = *c.Servicer.MetalAPI(cmd).VRFsApi
29+
},
30+
}
31+
32+
cmd.AddCommand(
33+
c.Create(),
34+
)
35+
return cmd
36+
}
37+
38+
type Servicer interface {
39+
MetalAPI(*cobra.Command) *metal.APIClient
40+
Filters() map[string]string
41+
Includes(defaultIncludes []string) (incl []string)
42+
Excludes(defaultExcludes []string) (excl []string)
43+
}
44+
45+
func NewClient(s Servicer, out outputs.Outputer) *Client {
46+
return &Client{
47+
Servicer: s,
48+
Out: out,
49+
}
50+
}

0 commit comments

Comments
 (0)