TUN-3689: Delete routes via cloudflared CLI
This commit is contained in:
parent
94c639d225
commit
32336859f8
|
@ -1,13 +1,18 @@
|
||||||
package tunnel
|
package tunnel
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"net"
|
||||||
|
|
||||||
"github.com/cloudflare/cloudflared/teamnet"
|
"github.com/cloudflare/cloudflared/teamnet"
|
||||||
|
"github.com/pkg/errors"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
const noClientMsg = "error while creating backend client"
|
||||||
|
|
||||||
func (sc *subcommandContext) listRoutes(filter *teamnet.Filter) ([]*teamnet.Route, error) {
|
func (sc *subcommandContext) listRoutes(filter *teamnet.Filter) ([]*teamnet.Route, error) {
|
||||||
client, err := sc.client()
|
client, err := sc.client()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, errors.Wrap(err, noClientMsg)
|
||||||
}
|
}
|
||||||
return client.ListRoutes(filter)
|
return client.ListRoutes(filter)
|
||||||
}
|
}
|
||||||
|
@ -15,7 +20,15 @@ func (sc *subcommandContext) listRoutes(filter *teamnet.Filter) ([]*teamnet.Rout
|
||||||
func (sc *subcommandContext) addRoute(newRoute teamnet.NewRoute) (teamnet.Route, error) {
|
func (sc *subcommandContext) addRoute(newRoute teamnet.NewRoute) (teamnet.Route, error) {
|
||||||
client, err := sc.client()
|
client, err := sc.client()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return teamnet.Route{}, err
|
return teamnet.Route{}, errors.Wrap(err, noClientMsg)
|
||||||
}
|
}
|
||||||
return client.AddRoute(newRoute)
|
return client.AddRoute(newRoute)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (sc *subcommandContext) deleteRoute(network net.IPNet) error {
|
||||||
|
client, err := sc.client()
|
||||||
|
if err != nil {
|
||||||
|
return errors.Wrap(err, noClientMsg)
|
||||||
|
}
|
||||||
|
return client.DeleteRoute(network)
|
||||||
|
}
|
||||||
|
|
|
@ -40,7 +40,14 @@ func buildRouteIPSubcommand() *cli.Command {
|
||||||
UsageText: "cloudflared tunnel [--config FILEPATH] route ip show [flags]",
|
UsageText: "cloudflared tunnel [--config FILEPATH] route ip show [flags]",
|
||||||
Description: `Shows all Cloudflare for Teams private routes. Using flags to specify filters means that
|
Description: `Shows all Cloudflare for Teams private routes. Using flags to specify filters means that
|
||||||
only routes which match that filter get shown.`,
|
only routes which match that filter get shown.`,
|
||||||
Flags: teamnet.Flags,
|
Flags: teamnet.FilterFlags,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
Name: "delete",
|
||||||
|
Action: cliutil.ErrorHandler(deleteRouteCommand),
|
||||||
|
Usage: "Delete a row of the routing table",
|
||||||
|
UsageText: "cloudflared tunnel [--config FILEPATH] route ip delete [CIDR]",
|
||||||
|
Description: `Deletes the Cloudflare for Teams private route for a given CIDR`,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
@ -80,7 +87,7 @@ func addRouteCommand(c *cli.Context) error {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
if c.NArg() < 2 {
|
if c.NArg() < 2 {
|
||||||
return fmt.Errorf("You must supply at least 2 arguments, first the network you wish to route (in CIDR form e.g. 1.2.3.4/32) and then the tunnel ID to proxy with")
|
return errors.New("You must supply at least 2 arguments, first the network you wish to route (in CIDR form e.g. 1.2.3.4/32) and then the tunnel ID to proxy with")
|
||||||
}
|
}
|
||||||
args := c.Args()
|
args := c.Args()
|
||||||
_, network, err := net.ParseCIDR(args.Get(0))
|
_, network, err := net.ParseCIDR(args.Get(0))
|
||||||
|
@ -111,6 +118,28 @@ func addRouteCommand(c *cli.Context) error {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func deleteRouteCommand(c *cli.Context) error {
|
||||||
|
sc, err := newSubcommandContext(c)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
if c.NArg() != 1 {
|
||||||
|
return errors.New("You must supply exactly one argument, the network whose route you want to delete (in CIDR form e.g. 1.2.3.4/32)")
|
||||||
|
}
|
||||||
|
_, network, err := net.ParseCIDR(c.Args().First())
|
||||||
|
if err != nil {
|
||||||
|
return errors.Wrap(err, "Invalid network CIDR")
|
||||||
|
}
|
||||||
|
if network == nil {
|
||||||
|
return errors.New("Invalid network CIDR")
|
||||||
|
}
|
||||||
|
if err := sc.deleteRoute(*network); err != nil {
|
||||||
|
return errors.Wrap(err, "API error")
|
||||||
|
}
|
||||||
|
fmt.Printf("Successfully deleted route for %s\n", network)
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
func formatAndPrintRouteList(routes []*teamnet.Route) {
|
func formatAndPrintRouteList(routes []*teamnet.Route) {
|
||||||
const (
|
const (
|
||||||
minWidth = 0
|
minWidth = 0
|
||||||
|
|
|
@ -35,7 +35,7 @@ var (
|
||||||
Usage: "Show only routes with this comment.",
|
Usage: "Show only routes with this comment.",
|
||||||
}
|
}
|
||||||
// Flags contains all filter flags.
|
// Flags contains all filter flags.
|
||||||
Flags = []cli.Flag{
|
FilterFlags = []cli.Flag{
|
||||||
&filterDeleted,
|
&filterDeleted,
|
||||||
&filterTunnelID,
|
&filterTunnelID,
|
||||||
&filterSubset,
|
&filterSubset,
|
||||||
|
|
|
@ -5,6 +5,7 @@ import (
|
||||||
"encoding/json"
|
"encoding/json"
|
||||||
"fmt"
|
"fmt"
|
||||||
"io"
|
"io"
|
||||||
|
"net"
|
||||||
"net/http"
|
"net/http"
|
||||||
"net/url"
|
"net/url"
|
||||||
"path"
|
"path"
|
||||||
|
@ -197,6 +198,7 @@ type Client interface {
|
||||||
// Teamnet endpoints
|
// Teamnet endpoints
|
||||||
ListRoutes(filter *teamnet.Filter) ([]*teamnet.Route, error)
|
ListRoutes(filter *teamnet.Filter) ([]*teamnet.Route, error)
|
||||||
AddRoute(newRoute teamnet.NewRoute) (teamnet.Route, error)
|
AddRoute(newRoute teamnet.NewRoute) (teamnet.Route, error)
|
||||||
|
DeleteRoute(network net.IPNet) error
|
||||||
}
|
}
|
||||||
|
|
||||||
type RESTClient struct {
|
type RESTClient struct {
|
||||||
|
|
|
@ -2,6 +2,7 @@ package tunnelstore
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"io"
|
"io"
|
||||||
|
"net"
|
||||||
"net/http"
|
"net/http"
|
||||||
"net/url"
|
"net/url"
|
||||||
"path"
|
"path"
|
||||||
|
@ -10,6 +11,7 @@ import (
|
||||||
"github.com/pkg/errors"
|
"github.com/pkg/errors"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
// ListRoutes calls the Tunnelstore GET endpoint for all routes under an account.
|
||||||
func (r *RESTClient) ListRoutes(filter *teamnet.Filter) ([]*teamnet.Route, error) {
|
func (r *RESTClient) ListRoutes(filter *teamnet.Filter) ([]*teamnet.Route, error) {
|
||||||
endpoint := r.baseEndpoints.accountRoutes
|
endpoint := r.baseEndpoints.accountRoutes
|
||||||
endpoint.RawQuery = filter.Encode()
|
endpoint.RawQuery = filter.Encode()
|
||||||
|
@ -26,6 +28,7 @@ func (r *RESTClient) ListRoutes(filter *teamnet.Filter) ([]*teamnet.Route, error
|
||||||
return nil, r.statusCodeToError("list routes", resp)
|
return nil, r.statusCodeToError("list routes", resp)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// AddRoute calls the Tunnelstore POST endpoint for a given route.
|
||||||
func (r *RESTClient) AddRoute(newRoute teamnet.NewRoute) (teamnet.Route, error) {
|
func (r *RESTClient) AddRoute(newRoute teamnet.NewRoute) (teamnet.Route, error) {
|
||||||
endpoint := r.baseEndpoints.accountRoutes
|
endpoint := r.baseEndpoints.accountRoutes
|
||||||
endpoint.Path = path.Join(endpoint.Path, url.PathEscape(newRoute.Network.String()))
|
endpoint.Path = path.Join(endpoint.Path, url.PathEscape(newRoute.Network.String()))
|
||||||
|
@ -42,6 +45,24 @@ func (r *RESTClient) AddRoute(newRoute teamnet.NewRoute) (teamnet.Route, error)
|
||||||
return teamnet.Route{}, r.statusCodeToError("add route", resp)
|
return teamnet.Route{}, r.statusCodeToError("add route", resp)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// DeleteRoute calls the Tunnelstore DELETE endpoint for a given route.
|
||||||
|
func (r *RESTClient) DeleteRoute(network net.IPNet) error {
|
||||||
|
endpoint := r.baseEndpoints.accountRoutes
|
||||||
|
endpoint.Path = path.Join(endpoint.Path, url.PathEscape(network.String()))
|
||||||
|
resp, err := r.sendRequest("DELETE", endpoint, nil)
|
||||||
|
if err != nil {
|
||||||
|
return errors.Wrap(err, "REST request failed")
|
||||||
|
}
|
||||||
|
defer resp.Body.Close()
|
||||||
|
|
||||||
|
if resp.StatusCode == http.StatusOK {
|
||||||
|
_, err := parseRoute(resp.Body)
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
return r.statusCodeToError("delete route", resp)
|
||||||
|
}
|
||||||
|
|
||||||
func parseListRoutes(body io.ReadCloser) ([]*teamnet.Route, error) {
|
func parseListRoutes(body io.ReadCloser) ([]*teamnet.Route, error) {
|
||||||
var routes []*teamnet.Route
|
var routes []*teamnet.Route
|
||||||
err := parseResponse(body, &routes)
|
err := parseResponse(body, &routes)
|
||||||
|
|
Loading…
Reference in New Issue