From 67a8690bccc46e6bc990355a84e41ca156fcea4c Mon Sep 17 00:00:00 2001 From: irusoeqx Date: Wed, 4 Oct 2023 17:44:10 +0300 Subject: [PATCH 1/2] feat: VRF support --- cmd/cli.go | 2 ++ docs/metal.md | 1 + docs/metal_vrf.md | 36 +++++++++++++++++++ docs/metal_vrf_create.md | 52 +++++++++++++++++++++++++++ docs/metal_vrf_delete.md | 51 ++++++++++++++++++++++++++ docs/metal_vrf_get.md | 50 ++++++++++++++++++++++++++ go.sum | 4 +++ internal/vrf/create.go | 77 ++++++++++++++++++++++++++++++++++++++++ internal/vrf/delete.go | 67 ++++++++++++++++++++++++++++++++++ internal/vrf/retrieve.go | 75 ++++++++++++++++++++++++++++++++++++++ internal/vrf/vrf.go | 52 +++++++++++++++++++++++++++ 11 files changed, 467 insertions(+) create mode 100644 docs/metal_vrf.md create mode 100644 docs/metal_vrf_create.md create mode 100644 docs/metal_vrf_delete.md create mode 100644 docs/metal_vrf_get.md create mode 100644 internal/vrf/create.go create mode 100644 internal/vrf/delete.go create mode 100644 internal/vrf/retrieve.go create mode 100644 internal/vrf/vrf.go diff --git a/cmd/cli.go b/cmd/cli.go index a245d30e..b2e865d7 100644 --- a/cmd/cli.go +++ b/cmd/cli.go @@ -28,6 +28,7 @@ import ( "github.com/equinix/metal-cli/internal/twofa" "github.com/equinix/metal-cli/internal/users" "github.com/equinix/metal-cli/internal/vlan" + "github.com/equinix/metal-cli/internal/vrf" ) // Cli struct @@ -95,5 +96,6 @@ func (cli *Cli) RegisterCommands(client *root.Client) { gateway.NewClient(client, cli.Outputer).NewCommand(), ports.NewClient(client, cli.Outputer).NewCommand(), interconnections.NewClient(client, cli.Outputer).NewCommand(), + vrf.NewClient(client, cli.Outputer).NewCommand(), ) } diff --git a/docs/metal.md b/docs/metal.md index 11725572..ce9a4fd9 100644 --- a/docs/metal.md +++ b/docs/metal.md @@ -47,4 +47,5 @@ Command line interface for Equinix Metal * [metal ssh-key](metal_ssh-key.md) - SSH key operations: create, get, update, and delete. * [metal user](metal_user.md) - User operations: get and add. * [metal virtual-network](metal_virtual-network.md) - Virtual network (VLAN) operations : create, get, delete. +* [metal vrf](metal_vrf.md) - VRF operations : create, get, delete diff --git a/docs/metal_vrf.md b/docs/metal_vrf.md new file mode 100644 index 00000000..5ba8dbfa --- /dev/null +++ b/docs/metal_vrf.md @@ -0,0 +1,36 @@ +## metal vrf + +VRF operations : create, get, delete + +### Synopsis + +VRF operations : It defines a collection of customer-managed IP blocks that can be used in BGP peering on one or more virtual networks and basic operations + +### Options + +``` + -h, --help help for vrf +``` + +### Options inherited from parent commands + +``` + --config string Path to JSON or YAML configuration file + --exclude strings Comma separated Href references to collapse in results, may be dotted three levels deep + --filter stringArray Filter 'get' actions with name value pairs. Filter is not supported by all resources and is implemented as request query parameters. + --http-header strings Headers to add to requests (in format key=value) + --include strings Comma separated Href references to expand in results, may be dotted three levels deep + -o, --output string Output format (*table, json, yaml). env output formats are (*sh, terraform, capp). + --search string Search keyword for use in 'get' actions. Search is not supported by all resources. + --sort-by string Sort fields for use in 'get' actions. Sort is not supported by all resources. + --sort-dir string Sort field direction for use in 'get' actions. Sort is not supported by all resources. + --token string Metal API Token (METAL_AUTH_TOKEN) +``` + +### SEE ALSO + +* [metal](metal.md) - Command line interface for Equinix Metal +* [metal vrf create](metal_vrf_create.md) - Creates a Virtual Routing and Forwarding(VRF) for a specified project. +* [metal vrf delete](metal_vrf_delete.md) - Deletes a VRF. +* [metal vrf get](metal_vrf_get.md) - Lists VRFs. + diff --git a/docs/metal_vrf_create.md b/docs/metal_vrf_create.md new file mode 100644 index 00000000..6cf78788 --- /dev/null +++ b/docs/metal_vrf_create.md @@ -0,0 +1,52 @@ +## metal vrf create + +Creates a Virtual Routing and Forwarding(VRF) for a specified project. + +### Synopsis + +Creates a Creates a Virtual Routing and Forwarding(VRF) for a specified project. + +``` +metal vrf create [-p ] [-m ] [-n ] [-a ] [-r ] [-t ] [flags] +``` + +### Examples + +``` + # Creates an Creates a Virtual Routing and Forwarding(VRF) for a specified project. + + metal vrf create [-p ] [-m ] [-n ] [-a ] [-r ] [-t ] +``` + +### Options + +``` + -d, --description string Description of the Virtual Routing and Forwarding. + -h, --help help for create + -r, --ipranges 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. + -a, --local-asn int32 Local ASN for the VRF + -m, --metro string The UUID (or metro code) for the Metro in which to create this Virtual Routing and Forwarding + -n, --name string Name of the Virtual Routing and Forwarding + -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. + -t, --tags strings Adds or updates the tags for the connection --tags="tag1,tag2". +``` + +### Options inherited from parent commands + +``` + --config string Path to JSON or YAML configuration file + --exclude strings Comma separated Href references to collapse in results, may be dotted three levels deep + --filter stringArray Filter 'get' actions with name value pairs. Filter is not supported by all resources and is implemented as request query parameters. + --http-header strings Headers to add to requests (in format key=value) + --include strings Comma separated Href references to expand in results, may be dotted three levels deep + -o, --output string Output format (*table, json, yaml). env output formats are (*sh, terraform, capp). + --search string Search keyword for use in 'get' actions. Search is not supported by all resources. + --sort-by string Sort fields for use in 'get' actions. Sort is not supported by all resources. + --sort-dir string Sort field direction for use in 'get' actions. Sort is not supported by all resources. + --token string Metal API Token (METAL_AUTH_TOKEN) +``` + +### SEE ALSO + +* [metal vrf](metal_vrf.md) - VRF operations : create, get, delete + diff --git a/docs/metal_vrf_delete.md b/docs/metal_vrf_delete.md new file mode 100644 index 00000000..743eabe3 --- /dev/null +++ b/docs/metal_vrf_delete.md @@ -0,0 +1,51 @@ +## metal vrf delete + +Deletes a VRF. + +### Synopsis + +Deletes the specified VRF with a confirmation prompt. To skip the confirmation, use --force. + +``` +metal vrf delete vrf -i [-f] [flags] +``` + +### Examples + +``` +# Deletes a VRF, with confirmation. + metal delete vrf -i 77e6d57a-d7a4-4816-b451-cf9b043444e2 + > + ✔ Are you sure you want to delete device 7ec86e23-8dcf-48ed-bd9b-c25c20958277: y + + # Deletes a VRF, skipping confirmation. + metal delete vrf -f -i 77e6d57a-d7a4-4816-b451-cf9b043444e2 +``` + +### Options + +``` + -f, --force Skips confirmation for the removal of the VRF. + -h, --help help for delete + -i, --id string UUID of the VRF. +``` + +### Options inherited from parent commands + +``` + --config string Path to JSON or YAML configuration file + --exclude strings Comma separated Href references to collapse in results, may be dotted three levels deep + --filter stringArray Filter 'get' actions with name value pairs. Filter is not supported by all resources and is implemented as request query parameters. + --http-header strings Headers to add to requests (in format key=value) + --include strings Comma separated Href references to expand in results, may be dotted three levels deep + -o, --output string Output format (*table, json, yaml). env output formats are (*sh, terraform, capp). + --search string Search keyword for use in 'get' actions. Search is not supported by all resources. + --sort-by string Sort fields for use in 'get' actions. Sort is not supported by all resources. + --sort-dir string Sort field direction for use in 'get' actions. Sort is not supported by all resources. + --token string Metal API Token (METAL_AUTH_TOKEN) +``` + +### SEE ALSO + +* [metal vrf](metal_vrf.md) - VRF operations : create, get, delete + diff --git a/docs/metal_vrf_get.md b/docs/metal_vrf_get.md new file mode 100644 index 00000000..e5ddcc29 --- /dev/null +++ b/docs/metal_vrf_get.md @@ -0,0 +1,50 @@ +## metal vrf get + +Lists VRFs. + +### Synopsis + +Retrieves a list of all VRFs for the specified project or the details of the specified VRF ID. Either a project ID or a VRF ID is required. + +``` +metal vrf get -p [flags] +``` + +### Examples + +``` + # Gets the details of the specified device + metal vrf get -i 3b0795ba-ec9a-4a9e-83a7-043e7e11407c + + # Lists VRFs for project 3b0795ba-ec9a-4a9e-83a7-043e7e11407c: + metal vrf list -p 3b0795ba-ec9a-4a9e-83a7-043e7e11407c +``` + +### Options + +``` + -h, --help help for get + -m, --metro string Filter by Metro ID (uuid) or Metro Code + -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. + -v, --vrfID string VRF UUID +``` + +### Options inherited from parent commands + +``` + --config string Path to JSON or YAML configuration file + --exclude strings Comma separated Href references to collapse in results, may be dotted three levels deep + --filter stringArray Filter 'get' actions with name value pairs. Filter is not supported by all resources and is implemented as request query parameters. + --http-header strings Headers to add to requests (in format key=value) + --include strings Comma separated Href references to expand in results, may be dotted three levels deep + -o, --output string Output format (*table, json, yaml). env output formats are (*sh, terraform, capp). + --search string Search keyword for use in 'get' actions. Search is not supported by all resources. + --sort-by string Sort fields for use in 'get' actions. Sort is not supported by all resources. + --sort-dir string Sort field direction for use in 'get' actions. Sort is not supported by all resources. + --token string Metal API Token (METAL_AUTH_TOKEN) +``` + +### SEE ALSO + +* [metal vrf](metal_vrf.md) - VRF operations : create, get, delete + diff --git a/go.sum b/go.sum index ef749068..9d4da4c8 100644 --- a/go.sum +++ b/go.sum @@ -257,6 +257,8 @@ golang.org/x/mod v0.2.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= golang.org/x/mod v0.4.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= golang.org/x/mod v0.4.1/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= +golang.org/x/mod v0.12.0 h1:rmsUpXtvNzj340zd98LZ4KntptpfRHwpFOHG188oHXc= +golang.org/x/mod v0.12.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs= golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20180826012351-8a410e7b638d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= 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 golang.org/x/tools v0.0.0-20210105154028-b0ab187a4818/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= golang.org/x/tools v0.0.0-20210108195828-e2f9c7f1fc8e/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= golang.org/x/tools v0.1.0/go.mod h1:xkSsbof2nBLbhDlRMhhhyNLN/zl3eTqcnHD5viDpcZ0= +golang.org/x/tools v0.13.0 h1:Iey4qkscZuv0VvIt8E0neZjtPVQFSc870HQ448QgEmQ= +golang.org/x/tools v0.13.0/go.mod h1:HvlwmtVNQAhOuCjW7xxvovg8wbNq7LwfXh/k7wXUl58= golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= diff --git a/internal/vrf/create.go b/internal/vrf/create.go new file mode 100644 index 00000000..7ecd525c --- /dev/null +++ b/internal/vrf/create.go @@ -0,0 +1,77 @@ +package vrf + +import ( + "context" + "fmt" + "strconv" + "strings" + + metal "github.com/equinix-labs/metal-go/metal/v1" + "github.com/spf13/cobra" +) + +func (c *Client) Create() *cobra.Command { + var ( + projectID string + metro string + name string + description string + ipRanges []string + localASN int32 + tags []string + ) + + // createVRFCmd represents the creatVRF command + createVRFCmd := &cobra.Command{ + Use: "create [-p ] [-m ] [-n ] [-a ] [-r ] [-t ]", + Short: "Creates a Virtual Routing and Forwarding(VRF) for a specified project.", + Long: "Creates a Creates a Virtual Routing and Forwarding(VRF) for a specified project.", + Example: ` # Creates an Creates a Virtual Routing and Forwarding(VRF) for a specified project. + + metal vrf create [-p ] [-m ] [-n ] [-a ] [-r ] [-t ]`, + RunE: func(cmd *cobra.Command, args []string) error { + cmd.SilenceUsage = true + + req := metal.VrfCreateInput{ + Metro: metro, + Name: name, + IpRanges: ipRanges, + LocalAsn: &localASN, + Tags: tags, + Description: &description, + } + + inc := []string{} + exc := []string{} + vrfRequest, _, err := c.Service.CreateVrf(context.Background(), projectID).VrfCreateInput(req).Exclude(c.Servicer.Excludes(exc)).Include(c.Servicer.Includes(inc)).Execute() + if err != nil { + return fmt.Errorf("could not create VRF: %w", err) + } + + data := make([][]string, 1) + + // This output block below is probably incorrect but leaving it for now for testing later. + data[0] = []string{vrfRequest.GetName(), vrfRequest.GetDescription(), strconv.Itoa(int(vrfRequest.GetLocalAsn())), strings.Join(vrfRequest.GetIpRanges(), ","), vrfRequest.GetCreatedAt().String()} + header := []string{"ID", "Name", "Description", "LocalASN", "IPranges", "Created"} + + return c.Out.Output(vrfRequest, header, &data) + }, + } + + 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.") + createVRFCmd.Flags().StringSliceVarP(&tags, "tags", "t", []string{}, `Adds or updates the tags for the connection --tags="tag1,tag2".`) + createVRFCmd.Flags().StringVarP(&name, "name", "n", "", "Name of the Virtual Routing and Forwarding") + createVRFCmd.Flags().StringVarP(&description, "description", "d", "", "Description of the Virtual Routing and Forwarding.") + + createVRFCmd.Flags().StringVarP(&metro, "metro", "m", "", "The UUID (or metro code) for the Metro in which to create this Virtual Routing and Forwarding") + createVRFCmd.Flags().Int32VarP(&localASN, "local-asn", "a", 0, "Local ASN for the VRF") + createVRFCmd.Flags().StringSliceVarP(&ipRanges, "ipranges", "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.") + + // making them all required here + _ = createVRFCmd.MarkFlagRequired("name") + _ = createVRFCmd.MarkFlagRequired("metro") + _ = createVRFCmd.MarkFlagRequired("local-asn") + _ = createVRFCmd.MarkFlagRequired("ipranges") + + return createVRFCmd +} diff --git a/internal/vrf/delete.go b/internal/vrf/delete.go new file mode 100644 index 00000000..9a42f1b9 --- /dev/null +++ b/internal/vrf/delete.go @@ -0,0 +1,67 @@ +package vrf + +import ( + "context" + "fmt" + + "github.com/manifoldco/promptui" + "github.com/spf13/cobra" +) + +func (c *Client) Delete() *cobra.Command { + var ( + vrfID string + force bool + ) + + deleteVrf := func(id string) error { + _, err := c.Service.DeleteVrf(context.Background(), id).Execute() + if err != nil { + return err + } + fmt.Println("VRF", id, "successfully deleted.") + fmt.Println("Device deletion initiated. Please check 'metal vrf get -i", vrfID, "' for status") + return nil // No need to return 'err' here; it's always nil. + } + + deleteVrfCmd := &cobra.Command{ + Use: "delete vrf -i [-f]", + Short: "Deletes a VRF.", + Long: "Deletes the specified VRF with a confirmation prompt. To skip the confirmation, use --force.", + Example: `# Deletes a VRF, with confirmation. + metal delete vrf -i 77e6d57a-d7a4-4816-b451-cf9b043444e2 + > + ✔ Are you sure you want to delete device 7ec86e23-8dcf-48ed-bd9b-c25c20958277: y + + # Deletes a VRF, skipping confirmation. + metal delete vrf -f -i 77e6d57a-d7a4-4816-b451-cf9b043444e2`, + RunE: func(cmd *cobra.Command, args []string) error { + cmd.SilenceUsage = true + + if !force { + prompt := promptui.Prompt{ + Label: fmt.Sprintf("Are you sure you want to delete VRF %s: ", vrfID), + IsConfirm: true, + } + + result, err := prompt.Run() + if err != nil || result != "y" { + return nil + } + } + + if err := deleteVrf(vrfID); err != nil { + return fmt.Errorf("could not delete VRF: %w", err) + } + + return nil + }, + } + + deleteVrfCmd.Flags().StringVarP(&vrfID, "id", "i", "", "UUID of the VRF.") + deleteVrfCmd.Flags().BoolVarP(&force, "force", "f", false, "Skips confirmation for the removal of the VRF.") + + _ = deleteVrfCmd.MarkFlagRequired("id") + + return deleteVrfCmd +} diff --git a/internal/vrf/retrieve.go b/internal/vrf/retrieve.go new file mode 100644 index 00000000..c8dbd3c3 --- /dev/null +++ b/internal/vrf/retrieve.go @@ -0,0 +1,75 @@ +package vrf + +import ( + "context" + "fmt" + "strconv" + "strings" + + metal "github.com/equinix-labs/metal-go/metal/v1" + "github.com/spf13/cobra" +) + +func (c *Client) Retrieve() *cobra.Command { + var ( + projectID string + metro string + vrfID string + ) + + // retrieveVrfsCmd represents the retrieveMetalGateways command + retrieveVrfsCmd := &cobra.Command{ + Use: `get -p `, + Aliases: []string{"list"}, + Short: "Lists VRFs.", + Long: "Retrieves a list of all VRFs for the specified project or the details of the specified VRF ID. Either a project ID or a VRF ID is required.", + Example: ` # Gets the details of the specified device + metal vrf get -i 3b0795ba-ec9a-4a9e-83a7-043e7e11407c + + # Lists VRFs for project 3b0795ba-ec9a-4a9e-83a7-043e7e11407c: + metal vrf list -p 3b0795ba-ec9a-4a9e-83a7-043e7e11407c`, + + RunE: func(cmd *cobra.Command, args []string) error { + cmd.SilenceUsage = true + inc := []string{} + exc := []string{} + var ( + vrfsList *metal.VrfList + vrf *metal.Vrf + vrfs []metal.Vrf + err error + ) + vrfIdFlag, _ := cmd.Flags().GetString("vrfID") + if vrfIdFlag != "" { + vrf, _, err = c.Service.FindVrfById(context.Background(), vrfID).Include(c.Servicer.Includes(inc)).Exclude(c.Servicer.Excludes(exc)).Execute() + if err != nil { + return fmt.Errorf("error when calling `VRFsApi.FindVrfById``: %w", err) + } + vrfs[0] = *vrf + } else { + vrfsList, _, err = c.Service.FindVrfs(context.Background(), projectID).Metro(metro).Include(c.Servicer.Includes(inc)).Exclude(c.Servicer.Excludes(exc)).Execute() + if err != nil { + return fmt.Errorf("error when calling `VRFsApi.FindVrfs``: %w", err) + } + vrfs = vrfsList.GetVrfs() + } + + data := make([][]string, len(vrfs)) + + for i, vrf := range vrfs { + + data[i] = []string{vrf.GetId(), vrf.GetName(), vrf.GetDescription(), strings.Join(vrf.GetIpRanges(), ","), strconv.FormatInt(int64(vrf.GetLocalAsn()), 10), vrf.CreatedAt.String()} + } + header := []string{"ID", "Name", "Description", "IPRanges", "LocalASN", "Created"} + + return c.Out.Output(vrfs, header, &data) + }, + } + 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.") + retrieveVrfsCmd.Flags().StringVarP(&metro, "metro", "m", "", "Filter by Metro ID (uuid) or Metro Code") + retrieveVrfsCmd.Flags().StringVarP(&vrfID, "vrfID", "v", "", "VRF UUID") + + _ = retrieveVrfsCmd.MarkFlagRequired("project-id") + + return retrieveVrfsCmd +} diff --git a/internal/vrf/vrf.go b/internal/vrf/vrf.go new file mode 100644 index 00000000..0908ec67 --- /dev/null +++ b/internal/vrf/vrf.go @@ -0,0 +1,52 @@ +package vrf + +import ( + metal "github.com/equinix-labs/metal-go/metal/v1" + "github.com/equinix/metal-cli/internal/outputs" + "github.com/spf13/cobra" +) + +type Client struct { + Servicer Servicer + Service metal.VRFsApiService + Out outputs.Outputer +} + +func (c *Client) NewCommand() *cobra.Command { + cmd := &cobra.Command{ + Use: `vrf`, + Aliases: []string{"vrf"}, + Short: "VRF operations : create, get, delete", + Long: "VRF operations : It defines a collection of customer-managed IP blocks that can be used in BGP peering on one or more virtual networks and basic operations", + + PersistentPreRun: func(cmd *cobra.Command, args []string) { + if root := cmd.Root(); root != nil { + if root.PersistentPreRun != nil { + root.PersistentPreRun(cmd, args) + } + } + c.Service = *c.Servicer.MetalAPI(cmd).VRFsApi + }, + } + + cmd.AddCommand( + c.Create(), + c.Retrieve(), + c.Delete(), + ) + return cmd +} + +type Servicer interface { + MetalAPI(*cobra.Command) *metal.APIClient + Filters() map[string]string + Includes(defaultIncludes []string) (incl []string) + Excludes(defaultExcludes []string) (excl []string) +} + +func NewClient(s Servicer, out outputs.Outputer) *Client { + return &Client{ + Servicer: s, + Out: out, + } +} From 4c7779e33eea243a908baa0b30306a705b3cb049 Mon Sep 17 00:00:00 2001 From: Marques Johansson Date: Thu, 16 Nov 2023 12:23:51 -0500 Subject: [PATCH 2/2] Update internal/vrf/delete.go --- internal/vrf/delete.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/internal/vrf/delete.go b/internal/vrf/delete.go index 9a42f1b9..9d39eb45 100644 --- a/internal/vrf/delete.go +++ b/internal/vrf/delete.go @@ -20,7 +20,7 @@ func (c *Client) Delete() *cobra.Command { return err } fmt.Println("VRF", id, "successfully deleted.") - fmt.Println("Device deletion initiated. Please check 'metal vrf get -i", vrfID, "' for status") + fmt.Println("VRF deletion initiated. Please check 'metal vrf get -i", vrfID, "' for status") return nil // No need to return 'err' here; it's always nil. }