diff --git a/cmd/cloudflared/tunnel/teamnet_subcommands.go b/cmd/cloudflared/tunnel/teamnet_subcommands.go index 6b795eb2..9a152317 100644 --- a/cmd/cloudflared/tunnel/teamnet_subcommands.go +++ b/cmd/cloudflared/tunnel/teamnet_subcommands.go @@ -41,7 +41,7 @@ func buildRouteIPSubcommand() *cli.Command { Usage: "Show the routing table", UsageText: "cloudflared tunnel [--config FILEPATH] route ip show [flags]", Description: `Shows your organization's private route table. You can use flags to filter the results.`, - Flags: teamnet.FilterFlags, + Flags: showRoutesFlags(), }, { Name: "delete", @@ -62,6 +62,13 @@ func buildRouteIPSubcommand() *cli.Command { } } +func showRoutesFlags() []cli.Flag { + flags := make([]cli.Flag, 0) + flags = append(flags, teamnet.FilterFlags...) + flags = append(flags, outputFormatFlag) + return flags +} + func showRoutesCommand(c *cli.Context) error { sc, err := newSubcommandContext(c) if err != nil { diff --git a/teamnet/api.go b/teamnet/api.go index 6a923984..4807a902 100644 --- a/teamnet/api.go +++ b/teamnet/api.go @@ -16,9 +16,9 @@ import ( // network, and says that eyeballs can reach that route using the corresponding // tunnel. type Route struct { - Network CIDR + Network CIDR `json:"network"` TunnelID uuid.UUID `json:"tunnel_id"` - Comment string + Comment string `json:"comment"` CreatedAt time.Time `json:"created_at"` DeletedAt time.Time `json:"deleted_at"` } @@ -26,11 +26,20 @@ type Route struct { // CIDR is just a newtype wrapper around net.IPNet. It adds JSON unmarshalling. type CIDR net.IPNet -func (c *CIDR) String() string { - n := net.IPNet(*c) +func (c CIDR) String() string { + n := net.IPNet(c) return n.String() } +func (c CIDR) MarshalJSON() ([]byte, error) { + str := c.String() + json, err := json.Marshal(str) + if err != nil { + return nil, errors.Wrap(err, "error serializing CIDR into JSON") + } + return json, nil +} + // UnmarshalJSON parses a JSON string into net.IPNet func (c *CIDR) UnmarshalJSON(data []byte) error { var s string @@ -68,9 +77,9 @@ func (r NewRoute) MarshalJSON() ([]byte, error) { // DetailedRoute is just a Route with some extra fields, e.g. TunnelName. type DetailedRoute struct { - Network CIDR + Network CIDR `json:"network"` TunnelID uuid.UUID `json:"tunnel_id"` - Comment string + Comment string `json:"comment"` CreatedAt time.Time `json:"created_at"` DeletedAt time.Time `json:"deleted_at"` TunnelName string `json:"tunnel_name"` diff --git a/teamnet/api_test.go b/teamnet/api_test.go index 222998f8..ad3133db 100644 --- a/teamnet/api_test.go +++ b/teamnet/api_test.go @@ -33,15 +33,15 @@ func TestUnmarshalRoute(t *testing.T) { require.Equal(t, "test", r.Comment) } -func TestUnmarshalDetailedRoute(t *testing.T) { +func TestDetailedRouteJsonRoundtrip(t *testing.T) { // Response from the teamnet route backend data := `{ "network":"10.1.2.40/29", "tunnel_id":"fba6ffea-807f-4e7a-a740-4184ee1b82c8", - "tunnel_name":"Mr. Tun", "comment":"test", "created_at":"2020-12-22T02:00:15.587008Z", - "deleted_at":null + "deleted_at":"2021-01-14T05:01:42.183002Z", + "tunnel_name":"Mr. Tun" }` var r DetailedRoute err := json.Unmarshal([]byte(data), &r) @@ -55,6 +55,13 @@ func TestUnmarshalDetailedRoute(t *testing.T) { require.Equal(t, CIDR(*cidr), r.Network) require.Equal(t, "test", r.Comment) require.Equal(t, "Mr. Tun", r.TunnelName) + + bytes, err := json.Marshal(r) + require.NoError(t, err) + obtainedJson := string(bytes) + data = strings.Replace(data, "\t", "", -1) + data = strings.Replace(data, "\n", "", -1) + require.Equal(t, data, obtainedJson) } func TestMarshalNewRoute(t *testing.T) {