types/persist: split controlclient.Persist into a small leaf package

This one alone doesn't modify the global dependency map much
(depaware.txt if anything looks slightly worse), but it leave
controlclient as only containing NetworkMap:

bradfitz@tsdev:~/src/tailscale.com/ipn$ grep -F "controlclient." *.go
backend.go:     NetMap        *controlclient.NetworkMap // new netmap received
fake_test.go:   b.notify(Notify{NetMap: &controlclient.NetworkMap{}})
fake_test.go:   b.notify(Notify{NetMap: &controlclient.NetworkMap{}})
handle.go:      netmapCache       *controlclient.NetworkMap
handle.go:func (h *Handle) NetMap() *controlclient.NetworkMap {

Once that goes into a leaf package, then ipn doesn't depend on
controlclient at all, and then the client gets smaller.

Updates #1278
pull/1281/head
Brad Fitzpatrick 4 years ago
parent a046b48593
commit ddfcc4326c

@ -46,10 +46,11 @@ tailscale.com/cmd/tailscale dependencies: (generated by github.com/tailscale/dep
tailscale.com/types/key from tailscale.com/derp+ tailscale.com/types/key from tailscale.com/derp+
tailscale.com/types/logger from tailscale.com/cmd/tailscale/cli+ tailscale.com/types/logger from tailscale.com/cmd/tailscale/cli+
tailscale.com/types/opt from tailscale.com/control/controlclient+ tailscale.com/types/opt from tailscale.com/control/controlclient+
tailscale.com/types/persist from tailscale.com/control/controlclient+
tailscale.com/types/preftype from tailscale.com/cmd/tailscale/cli+ tailscale.com/types/preftype from tailscale.com/cmd/tailscale/cli+
tailscale.com/types/strbuilder from tailscale.com/net/packet tailscale.com/types/strbuilder from tailscale.com/net/packet
tailscale.com/types/structs from tailscale.com/control/controlclient+ tailscale.com/types/structs from tailscale.com/control/controlclient+
tailscale.com/types/wgkey from tailscale.com/control/controlclient tailscale.com/types/wgkey from tailscale.com/control/controlclient+
tailscale.com/util/dnsname from tailscale.com/cmd/tailscale/cli+ tailscale.com/util/dnsname from tailscale.com/cmd/tailscale/cli+
W tailscale.com/util/endian from tailscale.com/net/netns W tailscale.com/util/endian from tailscale.com/net/netns
tailscale.com/util/lineread from tailscale.com/control/controlclient+ tailscale.com/util/lineread from tailscale.com/control/controlclient+

@ -108,6 +108,7 @@ tailscale.com/cmd/tailscaled dependencies: (generated by github.com/tailscale/de
tailscale.com/types/logger from tailscale.com/cmd/tailscaled+ tailscale.com/types/logger from tailscale.com/cmd/tailscaled+
tailscale.com/types/nettype from tailscale.com/wgengine/magicsock tailscale.com/types/nettype from tailscale.com/wgengine/magicsock
tailscale.com/types/opt from tailscale.com/control/controlclient+ tailscale.com/types/opt from tailscale.com/control/controlclient+
tailscale.com/types/persist from tailscale.com/control/controlclient+
tailscale.com/types/preftype from tailscale.com/ipn+ tailscale.com/types/preftype from tailscale.com/ipn+
tailscale.com/types/strbuilder from tailscale.com/net/packet tailscale.com/types/strbuilder from tailscale.com/net/packet
tailscale.com/types/structs from tailscale.com/control/controlclient+ tailscale.com/types/structs from tailscale.com/control/controlclient+

@ -22,6 +22,7 @@ import (
"tailscale.com/tailcfg" "tailscale.com/tailcfg"
"tailscale.com/types/empty" "tailscale.com/types/empty"
"tailscale.com/types/logger" "tailscale.com/types/logger"
"tailscale.com/types/persist"
"tailscale.com/types/structs" "tailscale.com/types/structs"
"tailscale.com/types/wgkey" "tailscale.com/types/wgkey"
) )
@ -68,7 +69,7 @@ type Status struct {
LoginFinished *empty.Message LoginFinished *empty.Message
Err string Err string
URL string URL string
Persist *Persist // locally persisted configuration Persist *persist.Persist // locally persisted configuration
NetMap *NetworkMap // server-pushed configuration NetMap *NetworkMap // server-pushed configuration
Hostinfo *tailcfg.Hostinfo // current Hostinfo data Hostinfo *tailcfg.Hostinfo // current Hostinfo data
State State State State
@ -618,7 +619,7 @@ func (c *Client) sendStatus(who string, err error, url string, nm *NetworkMap) {
c.logf("[v1] sendStatus: %s: %v", who, state) c.logf("[v1] sendStatus: %s: %v", who, state)
var p *Persist var p *persist.Persist
var fin *empty.Message var fin *empty.Message
if state == StateAuthenticated { if state == StateAuthenticated {
fin = new(empty.Message) fin = new(empty.Message)

@ -4,8 +4,6 @@
package controlclient package controlclient
//go:generate go run tailscale.com/cmd/cloner -type=Persist -output=direct_clone.go
import ( import (
"bytes" "bytes"
"context" "context"
@ -42,69 +40,13 @@ import (
"tailscale.com/tailcfg" "tailscale.com/tailcfg"
"tailscale.com/types/logger" "tailscale.com/types/logger"
"tailscale.com/types/opt" "tailscale.com/types/opt"
"tailscale.com/types/structs" "tailscale.com/types/persist"
"tailscale.com/types/wgkey" "tailscale.com/types/wgkey"
"tailscale.com/util/systemd" "tailscale.com/util/systemd"
"tailscale.com/version" "tailscale.com/version"
"tailscale.com/wgengine/filter" "tailscale.com/wgengine/filter"
) )
type Persist struct {
_ structs.Incomparable
// LegacyFrontendPrivateMachineKey is here temporarily
// (starting 2020-09-28) during migration of Windows users'
// machine keys from frontend storage to the backend. On the
// first LocalBackend.Start call, the backend will initialize
// the real (backend-owned) machine key from the frontend's
// provided value (if non-zero), picking a new random one if
// needed. This field should be considered read-only from GUI
// frontends. The real value should not be written back in
// this field, lest the frontend persist it to disk.
LegacyFrontendPrivateMachineKey wgkey.Private `json:"PrivateMachineKey"`
PrivateNodeKey wgkey.Private
OldPrivateNodeKey wgkey.Private // needed to request key rotation
Provider string
LoginName string
}
func (p *Persist) Equals(p2 *Persist) bool {
if p == nil && p2 == nil {
return true
}
if p == nil || p2 == nil {
return false
}
return p.LegacyFrontendPrivateMachineKey.Equal(p2.LegacyFrontendPrivateMachineKey) &&
p.PrivateNodeKey.Equal(p2.PrivateNodeKey) &&
p.OldPrivateNodeKey.Equal(p2.OldPrivateNodeKey) &&
p.Provider == p2.Provider &&
p.LoginName == p2.LoginName
}
func (p *Persist) Pretty() string {
var mk, ok, nk wgkey.Key
if !p.LegacyFrontendPrivateMachineKey.IsZero() {
mk = p.LegacyFrontendPrivateMachineKey.Public()
}
if !p.OldPrivateNodeKey.IsZero() {
ok = p.OldPrivateNodeKey.Public()
}
if !p.PrivateNodeKey.IsZero() {
nk = p.PrivateNodeKey.Public()
}
ss := func(k wgkey.Key) string {
if k.IsZero() {
return ""
}
return k.ShortString()
}
return fmt.Sprintf("Persist{lm=%v, o=%v, n=%v u=%#v}",
ss(mk), ss(ok), ss(nk), p.LoginName)
}
// Direct is the client that connects to a tailcontrol server for a node. // Direct is the client that connects to a tailcontrol server for a node.
type Direct struct { type Direct struct {
httpc *http.Client // HTTP client used to talk to tailcontrol httpc *http.Client // HTTP client used to talk to tailcontrol
@ -121,7 +63,7 @@ type Direct struct {
mu sync.Mutex // mutex guards the following fields mu sync.Mutex // mutex guards the following fields
serverKey wgkey.Key serverKey wgkey.Key
persist Persist persist persist.Persist
authKey string authKey string
tryingNewKey wgkey.Private tryingNewKey wgkey.Private
expiry *time.Time expiry *time.Time
@ -133,7 +75,7 @@ type Direct struct {
} }
type Options struct { type Options struct {
Persist Persist // initial persistent data Persist persist.Persist // initial persistent data
MachinePrivateKey wgkey.Private // the machine key to use MachinePrivateKey wgkey.Private // the machine key to use
ServerURL string // URL of the tailcontrol server ServerURL string // URL of the tailcontrol server
AuthKey string // optional node auth key for auto registration AuthKey string // optional node auth key for auto registration
@ -271,7 +213,7 @@ func (c *Direct) SetNetInfo(ni *tailcfg.NetInfo) bool {
return true return true
} }
func (c *Direct) GetPersist() Persist { func (c *Direct) GetPersist() persist.Persist {
c.mu.Lock() c.mu.Lock()
defer c.mu.Unlock() defer c.mu.Unlock()
return c.persist return c.persist
@ -294,7 +236,7 @@ func (c *Direct) TryLogout(ctx context.Context) error {
// immediately invalidated. // immediately invalidated.
//if !c.persist.PrivateNodeKey.IsZero() { //if !c.persist.PrivateNodeKey.IsZero() {
//} //}
c.persist = Persist{} c.persist = persist.Persist{}
return nil return nil
} }

@ -1,20 +0,0 @@
// Copyright (c) 2020 Tailscale Inc & AUTHORS All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
// Code generated by tailscale.com/cmd/cloner -type Persist; DO NOT EDIT.
package controlclient
import ()
// Clone makes a deep copy of Persist.
// The result aliases no memory with the original.
func (src *Persist) Clone() *Persist {
if src == nil {
return nil
}
dst := new(Persist)
*dst = *src
return dst
}

@ -29,6 +29,7 @@ import (
"tailscale.com/types/empty" "tailscale.com/types/empty"
"tailscale.com/types/key" "tailscale.com/types/key"
"tailscale.com/types/logger" "tailscale.com/types/logger"
"tailscale.com/types/persist"
"tailscale.com/types/wgkey" "tailscale.com/types/wgkey"
"tailscale.com/util/systemd" "tailscale.com/util/systemd"
"tailscale.com/version" "tailscale.com/version"
@ -512,7 +513,7 @@ func (b *LocalBackend) Start(opts ipn.Options) error {
b.notify = opts.Notify b.notify = opts.Notify
b.setNetMapLocked(nil) b.setNetMapLocked(nil)
persist := b.prefs.Persist persistv := b.prefs.Persist
machinePrivKey := b.machinePrivKey machinePrivKey := b.machinePrivKey
b.mu.Unlock() b.mu.Unlock()
@ -545,14 +546,14 @@ func (b *LocalBackend) Start(opts ipn.Options) error {
} }
var err error var err error
if persist == nil { if persistv == nil {
// let controlclient initialize it // let controlclient initialize it
persist = &controlclient.Persist{} persistv = &persist.Persist{}
} }
cli, err := controlclient.New(controlclient.Options{ cli, err := controlclient.New(controlclient.Options{
MachinePrivateKey: machinePrivKey, MachinePrivateKey: machinePrivKey,
Logf: logger.WithPrefix(b.logf, "control: "), Logf: logger.WithPrefix(b.logf, "control: "),
Persist: *persist, Persist: *persistv,
ServerURL: b.serverURL, ServerURL: b.serverURL,
AuthKey: opts.AuthKey, AuthKey: opts.AuthKey,
Hostinfo: hostinfo, Hostinfo: hostinfo,

@ -9,13 +9,13 @@ import (
"testing" "testing"
"time" "time"
"tailscale.com/control/controlclient"
"tailscale.com/ipn" "tailscale.com/ipn"
"tailscale.com/ipn/ipnstate" "tailscale.com/ipn/ipnstate"
"tailscale.com/logtail" "tailscale.com/logtail"
"tailscale.com/tailcfg" "tailscale.com/tailcfg"
"tailscale.com/tstest" "tailscale.com/tstest"
"tailscale.com/types/key" "tailscale.com/types/key"
"tailscale.com/types/persist"
"tailscale.com/wgengine" "tailscale.com/wgengine"
) )
@ -67,7 +67,7 @@ func TestLocalLogLines(t *testing.T) {
} }
// log prefs line // log prefs line
persist := &controlclient.Persist{} persist := &persist.Persist{}
prefs := ipn.NewPrefs() prefs := ipn.NewPrefs()
prefs.Persist = persist prefs.Persist = persist
lb.SetPrefs(prefs) lb.SetPrefs(prefs)

@ -17,8 +17,8 @@ import (
"inet.af/netaddr" "inet.af/netaddr"
"tailscale.com/atomicfile" "tailscale.com/atomicfile"
"tailscale.com/control/controlclient"
"tailscale.com/tailcfg" "tailscale.com/tailcfg"
"tailscale.com/types/persist"
"tailscale.com/types/preftype" "tailscale.com/types/preftype"
) )
@ -144,7 +144,7 @@ type Prefs struct {
// TODO(apenwarr): We should move this out of here, it's not a pref. // TODO(apenwarr): We should move this out of here, it's not a pref.
// We can maybe do that once we're sure which module should persist // We can maybe do that once we're sure which module should persist
// it (backend or frontend?) // it (backend or frontend?)
Persist *controlclient.Persist `json:"Config"` Persist *persist.Persist `json:"Config"`
} }
// IsEmpty reports whether p is nil or pointing to a Prefs zero value. // IsEmpty reports whether p is nil or pointing to a Prefs zero value.
@ -275,7 +275,7 @@ func PrefsFromBytes(b []byte, enforceDefaults bool) (*Prefs, error) {
if len(b) == 0 { if len(b) == 0 {
return p, nil return p, nil
} }
persist := &controlclient.Persist{} persist := &persist.Persist{}
err := json.Unmarshal(b, persist) err := json.Unmarshal(b, persist)
if err == nil && (persist.Provider != "" || persist.LoginName != "") { if err == nil && (persist.Provider != "" || persist.LoginName != "") {
// old-style relaynode config; import it // old-style relaynode config; import it

@ -8,8 +8,8 @@ package ipn
import ( import (
"inet.af/netaddr" "inet.af/netaddr"
"tailscale.com/control/controlclient"
"tailscale.com/tailcfg" "tailscale.com/tailcfg"
"tailscale.com/types/persist"
"tailscale.com/types/preftype" "tailscale.com/types/preftype"
) )
@ -24,7 +24,7 @@ func (src *Prefs) Clone() *Prefs {
dst.AdvertiseTags = append(src.AdvertiseTags[:0:0], src.AdvertiseTags...) dst.AdvertiseTags = append(src.AdvertiseTags[:0:0], src.AdvertiseTags...)
dst.AdvertiseRoutes = append(src.AdvertiseRoutes[:0:0], src.AdvertiseRoutes...) dst.AdvertiseRoutes = append(src.AdvertiseRoutes[:0:0], src.AdvertiseRoutes...)
if dst.Persist != nil { if dst.Persist != nil {
dst.Persist = new(controlclient.Persist) dst.Persist = new(persist.Persist)
*dst.Persist = *src.Persist *dst.Persist = *src.Persist
} }
return dst return dst
@ -50,5 +50,5 @@ var _PrefsNeedsRegeneration = Prefs(struct {
AdvertiseRoutes []netaddr.IPPrefix AdvertiseRoutes []netaddr.IPPrefix
NoSNAT bool NoSNAT bool
NetfilterMode preftype.NetfilterMode NetfilterMode preftype.NetfilterMode
Persist *controlclient.Persist Persist *persist.Persist
}{}) }{})

@ -14,8 +14,8 @@ import (
"time" "time"
"inet.af/netaddr" "inet.af/netaddr"
"tailscale.com/control/controlclient"
"tailscale.com/tstest" "tailscale.com/tstest"
"tailscale.com/types/persist"
"tailscale.com/types/preftype" "tailscale.com/types/preftype"
"tailscale.com/types/wgkey" "tailscale.com/types/wgkey"
) )
@ -225,13 +225,13 @@ func TestPrefsEqual(t *testing.T) {
}, },
{ {
&Prefs{Persist: &controlclient.Persist{}}, &Prefs{Persist: &persist.Persist{}},
&Prefs{Persist: &controlclient.Persist{LoginName: "dave"}}, &Prefs{Persist: &persist.Persist{LoginName: "dave"}},
false, false,
}, },
{ {
&Prefs{Persist: &controlclient.Persist{LoginName: "dave"}}, &Prefs{Persist: &persist.Persist{LoginName: "dave"}},
&Prefs{Persist: &controlclient.Persist{LoginName: "dave"}}, &Prefs{Persist: &persist.Persist{LoginName: "dave"}},
true, true,
}, },
} }
@ -296,7 +296,7 @@ func TestBasicPrefs(t *testing.T) {
func TestPrefsPersist(t *testing.T) { func TestPrefsPersist(t *testing.T) {
tstest.PanicOnLog() tstest.PanicOnLog()
c := controlclient.Persist{ c := persist.Persist{
LoginName: "test@example.com", LoginName: "test@example.com",
} }
p := Prefs{ p := Prefs{
@ -362,14 +362,14 @@ func TestPrefsPretty(t *testing.T) {
}, },
{ {
Prefs{ Prefs{
Persist: &controlclient.Persist{}, Persist: &persist.Persist{},
}, },
"linux", "linux",
`Prefs{ra=false mesh=false dns=false want=false routes=[] nf=off Persist{lm=, o=, n= u=""}}`, `Prefs{ra=false mesh=false dns=false want=false routes=[] nf=off Persist{lm=, o=, n= u=""}}`,
}, },
{ {
Prefs{ Prefs{
Persist: &controlclient.Persist{ Persist: &persist.Persist{
PrivateNodeKey: wgkey.Private{1: 1}, PrivateNodeKey: wgkey.Private{1: 1},
}, },
}, },

@ -0,0 +1,73 @@
// Copyright (c) 2021 Tailscale Inc & AUTHORS All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
// Package persist contains the Persist type.
package persist
import (
"fmt"
"tailscale.com/types/structs"
"tailscale.com/types/wgkey"
)
//go:generate go run tailscale.com/cmd/cloner -type=Persist -output=persist_clone.go
// Persist is the JSON type stored on disk on nodes to remember their
// settings between runs.
type Persist struct {
_ structs.Incomparable
// LegacyFrontendPrivateMachineKey is here temporarily
// (starting 2020-09-28) during migration of Windows users'
// machine keys from frontend storage to the backend. On the
// first LocalBackend.Start call, the backend will initialize
// the real (backend-owned) machine key from the frontend's
// provided value (if non-zero), picking a new random one if
// needed. This field should be considered read-only from GUI
// frontends. The real value should not be written back in
// this field, lest the frontend persist it to disk.
LegacyFrontendPrivateMachineKey wgkey.Private `json:"PrivateMachineKey"`
PrivateNodeKey wgkey.Private
OldPrivateNodeKey wgkey.Private // needed to request key rotation
Provider string
LoginName string
}
func (p *Persist) Equals(p2 *Persist) bool {
if p == nil && p2 == nil {
return true
}
if p == nil || p2 == nil {
return false
}
return p.LegacyFrontendPrivateMachineKey.Equal(p2.LegacyFrontendPrivateMachineKey) &&
p.PrivateNodeKey.Equal(p2.PrivateNodeKey) &&
p.OldPrivateNodeKey.Equal(p2.OldPrivateNodeKey) &&
p.Provider == p2.Provider &&
p.LoginName == p2.LoginName
}
func (p *Persist) Pretty() string {
var mk, ok, nk wgkey.Key
if !p.LegacyFrontendPrivateMachineKey.IsZero() {
mk = p.LegacyFrontendPrivateMachineKey.Public()
}
if !p.OldPrivateNodeKey.IsZero() {
ok = p.OldPrivateNodeKey.Public()
}
if !p.PrivateNodeKey.IsZero() {
nk = p.PrivateNodeKey.Public()
}
ss := func(k wgkey.Key) string {
if k.IsZero() {
return ""
}
return k.ShortString()
}
return fmt.Sprintf("Persist{lm=%v, o=%v, n=%v u=%#v}",
ss(mk), ss(ok), ss(nk), p.LoginName)
}

@ -0,0 +1,34 @@
// Copyright (c) 2020 Tailscale Inc & AUTHORS All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
// Code generated by tailscale.com/cmd/cloner -type Persist; DO NOT EDIT.
package persist
import (
"tailscale.com/types/structs"
"tailscale.com/types/wgkey"
)
// Clone makes a deep copy of Persist.
// The result aliases no memory with the original.
func (src *Persist) Clone() *Persist {
if src == nil {
return nil
}
dst := new(Persist)
*dst = *src
return dst
}
// A compilation failure here means this code must be regenerated, with command:
// tailscale.com/cmd/cloner -type Persist
var _PersistNeedsRegeneration = Persist(struct {
_ structs.Incomparable
LegacyFrontendPrivateMachineKey wgkey.Private
PrivateNodeKey wgkey.Private
OldPrivateNodeKey wgkey.Private
Provider string
LoginName string
}{})

@ -2,7 +2,7 @@
// Use of this source code is governed by a BSD-style // Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file. // license that can be found in the LICENSE file.
package controlclient package persist
import ( import (
"reflect" "reflect"
@ -11,6 +11,15 @@ import (
"tailscale.com/types/wgkey" "tailscale.com/types/wgkey"
) )
func fieldsOf(t reflect.Type) (fields []string) {
for i := 0; i < t.NumField(); i++ {
if name := t.Field(i).Name; name != "_" {
fields = append(fields, name)
}
}
return
}
func TestPersistEqual(t *testing.T) { func TestPersistEqual(t *testing.T) {
persistHandles := []string{"LegacyFrontendPrivateMachineKey", "PrivateNodeKey", "OldPrivateNodeKey", "Provider", "LoginName"} persistHandles := []string{"LegacyFrontendPrivateMachineKey", "PrivateNodeKey", "OldPrivateNodeKey", "Provider", "LoginName"}
if have := fieldsOf(reflect.TypeOf(Persist{})); !reflect.DeepEqual(have, persistHandles) { if have := fieldsOf(reflect.TypeOf(Persist{})); !reflect.DeepEqual(have, persistHandles) {
Loading…
Cancel
Save