mirror of
https://github.com/cloudflare/cloudflared.git
synced 2025-07-29 04:19:57 +00:00
TUN-3688: Subcommand for users to check which route an IP proxies through
This commit is contained in:
@@ -7,6 +7,7 @@ import (
|
||||
"time"
|
||||
|
||||
"github.com/google/uuid"
|
||||
"github.com/pkg/errors"
|
||||
)
|
||||
|
||||
// Route is a mapping from customer's IP space to a tunnel.
|
||||
@@ -15,56 +16,35 @@ import (
|
||||
// network, and says that eyeballs can reach that route using the corresponding
|
||||
// tunnel.
|
||||
type Route struct {
|
||||
Network net.IPNet
|
||||
TunnelID uuid.UUID
|
||||
Network CIDR
|
||||
TunnelID uuid.UUID `json:"tunnel_id"`
|
||||
Comment string
|
||||
CreatedAt time.Time
|
||||
DeletedAt time.Time
|
||||
CreatedAt time.Time `json:"created_at"`
|
||||
DeletedAt time.Time `json:"deleted_at"`
|
||||
}
|
||||
|
||||
// TableString outputs a table row summarizing the route, to be used
|
||||
// when showing the user their routing table.
|
||||
func (r Route) TableString() string {
|
||||
deletedColumn := "-"
|
||||
if !r.DeletedAt.IsZero() {
|
||||
deletedColumn = r.DeletedAt.Format(time.RFC3339)
|
||||
}
|
||||
return fmt.Sprintf(
|
||||
"%s\t%s\t%s\t%s\t%s\t",
|
||||
r.Network.String(),
|
||||
r.Comment,
|
||||
r.TunnelID,
|
||||
r.CreatedAt.Format(time.RFC3339),
|
||||
deletedColumn,
|
||||
)
|
||||
// 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)
|
||||
return n.String()
|
||||
}
|
||||
|
||||
// UnmarshalJSON handles fields with non-JSON types (e.g. net.IPNet).
|
||||
func (r *Route) UnmarshalJSON(data []byte) error {
|
||||
|
||||
// This is the raw JSON format that cloudflared receives from tunnelstore.
|
||||
// Note it does not understand types like IPNet.
|
||||
var resp struct {
|
||||
Network string `json:"network"`
|
||||
TunnelID uuid.UUID `json:"tunnel_id"`
|
||||
Comment string `json:"comment"`
|
||||
CreatedAt time.Time `json:"created_at"`
|
||||
DeletedAt time.Time `json:"deleted_at"`
|
||||
// UnmarshalJSON parses a JSON string into net.IPNet
|
||||
func (c *CIDR) UnmarshalJSON(data []byte) error {
|
||||
var s string
|
||||
if err := json.Unmarshal(data, &s); err != nil {
|
||||
return errors.Wrap(err, "error parsing cidr string")
|
||||
}
|
||||
if err := json.Unmarshal(data, &resp); err != nil {
|
||||
return err
|
||||
_, network, err := net.ParseCIDR(s)
|
||||
if err != nil {
|
||||
return errors.Wrap(err, "error parsing invalid network from backend")
|
||||
}
|
||||
|
||||
// Parse the raw JSON into a properly-typed response.
|
||||
_, network, err := net.ParseCIDR(resp.Network)
|
||||
if err != nil || network == nil {
|
||||
return fmt.Errorf("backend returned invalid network %s", resp.Network)
|
||||
if network == nil {
|
||||
return fmt.Errorf("backend returned invalid network %s", s)
|
||||
}
|
||||
r.Network = *network
|
||||
r.TunnelID = resp.TunnelID
|
||||
r.Comment = resp.Comment
|
||||
r.CreatedAt = resp.CreatedAt
|
||||
r.DeletedAt = resp.DeletedAt
|
||||
*c = CIDR(*network)
|
||||
return nil
|
||||
}
|
||||
|
||||
@@ -78,7 +58,6 @@ type NewRoute struct {
|
||||
// MarshalJSON handles fields with non-JSON types (e.g. net.IPNet).
|
||||
func (r NewRoute) MarshalJSON() ([]byte, error) {
|
||||
return json.Marshal(&struct {
|
||||
Network string `json:"network"`
|
||||
TunnelID uuid.UUID `json:"tunnel_id"`
|
||||
Comment string `json:"comment"`
|
||||
}{
|
||||
@@ -86,3 +65,36 @@ func (r NewRoute) MarshalJSON() ([]byte, error) {
|
||||
Comment: r.Comment,
|
||||
})
|
||||
}
|
||||
|
||||
// DetailedRoute is just a Route with some extra fields, e.g. TunnelName.
|
||||
type DetailedRoute struct {
|
||||
Network CIDR
|
||||
TunnelID uuid.UUID `json:"tunnel_id"`
|
||||
Comment string
|
||||
CreatedAt time.Time `json:"created_at"`
|
||||
DeletedAt time.Time `json:"deleted_at"`
|
||||
TunnelName string `json:"tunnel_name"`
|
||||
}
|
||||
|
||||
// IsZero checks if DetailedRoute is the zero value.
|
||||
func (r *DetailedRoute) IsZero() bool {
|
||||
return r.TunnelID == uuid.Nil
|
||||
}
|
||||
|
||||
// TableString outputs a table row summarizing the route, to be used
|
||||
// when showing the user their routing table.
|
||||
func (r DetailedRoute) TableString() string {
|
||||
deletedColumn := "-"
|
||||
if !r.DeletedAt.IsZero() {
|
||||
deletedColumn = r.DeletedAt.Format(time.RFC3339)
|
||||
}
|
||||
return fmt.Sprintf(
|
||||
"%s\t%s\t%s\t%s\t%s\t%s\t",
|
||||
r.Network.String(),
|
||||
r.Comment,
|
||||
r.TunnelID,
|
||||
r.TunnelName,
|
||||
r.CreatedAt.Format(time.RFC3339),
|
||||
deletedColumn,
|
||||
)
|
||||
}
|
||||
|
Reference in New Issue
Block a user