client/tailscale: remove some json.Unmarshal repetition, add helper

Change-Id: I73ece09895ad04c7d8c4a5673f9bd360be873b9f
Signed-off-by: Brad Fitzpatrick <bradfitz@tailscale.com>
pull/6281/head
Brad Fitzpatrick 2 years ago committed by Brad Fitzpatrick
parent f00a49667d
commit 329a0a8406

@ -231,20 +231,21 @@ func WhoIs(ctx context.Context, remoteAddr string) (*apitype.WhoIsResponse, erro
return defaultLocalClient.WhoIs(ctx, remoteAddr) return defaultLocalClient.WhoIs(ctx, remoteAddr)
} }
func decodeJSON[T any](b []byte) (ret T, err error) {
if err := json.Unmarshal(b, &ret); err != nil {
var zero T
return zero, fmt.Errorf("failed to unmarshal JSON into %T: %w", ret, err)
}
return ret, nil
}
// WhoIs returns the owner of the remoteAddr, which must be an IP or IP:port. // WhoIs returns the owner of the remoteAddr, which must be an IP or IP:port.
func (lc *LocalClient) WhoIs(ctx context.Context, remoteAddr string) (*apitype.WhoIsResponse, error) { func (lc *LocalClient) WhoIs(ctx context.Context, remoteAddr string) (*apitype.WhoIsResponse, error) {
body, err := lc.get200(ctx, "/localapi/v0/whois?addr="+url.QueryEscape(remoteAddr)) body, err := lc.get200(ctx, "/localapi/v0/whois?addr="+url.QueryEscape(remoteAddr))
if err != nil { if err != nil {
return nil, err return nil, err
} }
r := new(apitype.WhoIsResponse) return decodeJSON[*apitype.WhoIsResponse](body)
if err := json.Unmarshal(body, r); err != nil {
if max := 200; len(body) > max {
body = append(body[:max], "..."...)
}
return nil, fmt.Errorf("failed to parse JSON WhoIsResponse from %q", body)
}
return r, nil
} }
// Goroutines returns a dump of the Tailscale daemon's current goroutines. // Goroutines returns a dump of the Tailscale daemon's current goroutines.
@ -411,11 +412,7 @@ func (lc *LocalClient) status(ctx context.Context, queryString string) (*ipnstat
if err != nil { if err != nil {
return nil, err return nil, err
} }
st := new(ipnstate.Status) return decodeJSON[*ipnstate.Status](body)
if err := json.Unmarshal(body, st); err != nil {
return nil, err
}
return st, nil
} }
// IDToken is a request to get an OIDC ID token for an audience. // IDToken is a request to get an OIDC ID token for an audience.
@ -426,11 +423,7 @@ func (lc *LocalClient) IDToken(ctx context.Context, aud string) (*tailcfg.TokenR
if err != nil { if err != nil {
return nil, err return nil, err
} }
tr := new(tailcfg.TokenResponse) return decodeJSON[*tailcfg.TokenResponse](body)
if err := json.Unmarshal(body, tr); err != nil {
return nil, err
}
return tr, nil
} }
func (lc *LocalClient) WaitingFiles(ctx context.Context) ([]apitype.WaitingFile, error) { func (lc *LocalClient) WaitingFiles(ctx context.Context) ([]apitype.WaitingFile, error) {
@ -438,11 +431,7 @@ func (lc *LocalClient) WaitingFiles(ctx context.Context) ([]apitype.WaitingFile,
if err != nil { if err != nil {
return nil, err return nil, err
} }
var wfs []apitype.WaitingFile return decodeJSON[[]apitype.WaitingFile](body)
if err := json.Unmarshal(body, &wfs); err != nil {
return nil, err
}
return wfs, nil
} }
func (lc *LocalClient) DeleteWaitingFile(ctx context.Context, baseName string) error { func (lc *LocalClient) DeleteWaitingFile(ctx context.Context, baseName string) error {
@ -476,11 +465,7 @@ func (lc *LocalClient) FileTargets(ctx context.Context) ([]apitype.FileTarget, e
if err != nil { if err != nil {
return nil, err return nil, err
} }
var fts []apitype.FileTarget return decodeJSON[[]apitype.FileTarget](body)
if err := json.Unmarshal(body, &fts); err != nil {
return nil, fmt.Errorf("invalid JSON: %w", err)
}
return fts, nil
} }
// PushFile sends Taildrop file r to target. // PushFile sends Taildrop file r to target.
@ -555,11 +540,7 @@ func (lc *LocalClient) EditPrefs(ctx context.Context, mp *ipn.MaskedPrefs) (*ipn
if err != nil { if err != nil {
return nil, err return nil, err
} }
var p ipn.Prefs return decodeJSON[*ipn.Prefs](body)
if err := json.Unmarshal(body, &p); err != nil {
return nil, fmt.Errorf("invalid prefs JSON: %w", err)
}
return &p, nil
} }
func (lc *LocalClient) Logout(ctx context.Context) error { func (lc *LocalClient) Logout(ctx context.Context) error {
@ -765,11 +746,7 @@ func (lc *LocalClient) Ping(ctx context.Context, ip netip.Addr, pingtype tailcfg
if err != nil { if err != nil {
return nil, fmt.Errorf("error %w: %s", err, body) return nil, fmt.Errorf("error %w: %s", err, body)
} }
pr := new(ipnstate.PingResult) return decodeJSON[*ipnstate.PingResult](body)
if err := json.Unmarshal(body, pr); err != nil {
return nil, err
}
return pr, nil
} }
// NetworkLockStatus fetches information about the tailnet key authority, if one is configured. // NetworkLockStatus fetches information about the tailnet key authority, if one is configured.
@ -778,11 +755,7 @@ func (lc *LocalClient) NetworkLockStatus(ctx context.Context) (*ipnstate.Network
if err != nil { if err != nil {
return nil, fmt.Errorf("error: %w", err) return nil, fmt.Errorf("error: %w", err)
} }
pr := new(ipnstate.NetworkLockStatus) return decodeJSON[*ipnstate.NetworkLockStatus](body)
if err := json.Unmarshal(body, pr); err != nil {
return nil, err
}
return pr, nil
} }
// NetworkLockInit initializes the tailnet key authority. // NetworkLockInit initializes the tailnet key authority.
@ -803,12 +776,7 @@ func (lc *LocalClient) NetworkLockInit(ctx context.Context, keys []tka.Key, disa
if err != nil { if err != nil {
return nil, fmt.Errorf("error: %w", err) return nil, fmt.Errorf("error: %w", err)
} }
return decodeJSON[*ipnstate.NetworkLockStatus](body)
pr := new(ipnstate.NetworkLockStatus)
if err := json.Unmarshal(body, pr); err != nil {
return nil, err
}
return pr, nil
} }
// NetworkLockModify adds and/or removes key(s) to the tailnet key authority. // NetworkLockModify adds and/or removes key(s) to the tailnet key authority.
@ -827,12 +795,7 @@ func (lc *LocalClient) NetworkLockModify(ctx context.Context, addKeys, removeKey
if err != nil { if err != nil {
return nil, fmt.Errorf("error: %w", err) return nil, fmt.Errorf("error: %w", err)
} }
return decodeJSON[*ipnstate.NetworkLockStatus](body)
pr := new(ipnstate.NetworkLockStatus)
if err := json.Unmarshal(body, pr); err != nil {
return nil, err
}
return pr, nil
} }
// NetworkLockSign signs the specified node-key and transmits that signature to the control plane. // NetworkLockSign signs the specified node-key and transmits that signature to the control plane.

Loading…
Cancel
Save