ipn: use cmd/cloner for Prefs.Clone

Also, make cmd/cloner's top-level "func Clone" generation opt-in.

Signed-off-by: Brad Fitzpatrick <bradfitz@tailscale.com>
reviewable/pr836/r1
Brad Fitzpatrick 4 years ago committed by Brad Fitzpatrick
parent 6cc6e251a9
commit 7c8ca28c74

@ -33,6 +33,7 @@ var (
flagTypes = flag.String("type", "", "comma-separated list of types; required") flagTypes = flag.String("type", "", "comma-separated list of types; required")
flagOutput = flag.String("output", "", "output file; required") flagOutput = flag.String("output", "", "output file; required")
flagBuildTags = flag.String("tags", "", "compiler build tags to apply") flagBuildTags = flag.String("tags", "", "compiler build tags to apply")
flagCloneFunc = flag.Bool("clonefunc", false, "add a top-level Clone func")
) )
func main() { func main() {
@ -98,25 +99,27 @@ func main() {
w := func(format string, args ...interface{}) { w := func(format string, args ...interface{}) {
fmt.Fprintf(buf, format+"\n", args...) fmt.Fprintf(buf, format+"\n", args...)
} }
w("// Clone duplicates src into dst and reports whether it succeeded.") if *flagCloneFunc {
w("// To succeed, <src, dst> must be of types <*T, *T> or <*T, **T>,") w("// Clone duplicates src into dst and reports whether it succeeded.")
w("// where T is one of %s.", *flagTypes) w("// To succeed, <src, dst> must be of types <*T, *T> or <*T, **T>,")
w("func Clone(dst, src interface{}) bool {") w("// where T is one of %s.", *flagTypes)
w(" switch src := src.(type) {") w("func Clone(dst, src interface{}) bool {")
for _, typeName := range typeNames { w(" switch src := src.(type) {")
w(" case *%s:", typeName) for _, typeName := range typeNames {
w(" switch dst := dst.(type) {") w(" case *%s:", typeName)
w(" case *%s:", typeName) w(" switch dst := dst.(type) {")
w(" *dst = *src.Clone()") w(" case *%s:", typeName)
w(" return true") w(" *dst = *src.Clone()")
w(" case **%s:", typeName) w(" return true")
w(" *dst = src.Clone()") w(" case **%s:", typeName)
w(" return true") w(" *dst = src.Clone()")
w(" }") w(" return true")
w(" }")
}
w(" }")
w(" return false")
w("}")
} }
w(" }")
w(" return false")
w("}")
contents := new(bytes.Buffer) contents := new(bytes.Buffer)
fmt.Fprintf(contents, header, *flagTypes, pkg.Name) fmt.Fprintf(contents, header, *flagTypes, pkg.Name)

@ -20,6 +20,8 @@ import (
"tailscale.com/wgengine/router" "tailscale.com/wgengine/router"
) )
//go:generate go run tailscale.com/cmd/cloner -type=Prefs -output=prefs_clone.go
// Prefs are the user modifiable settings of the Tailscale node agent. // Prefs are the user modifiable settings of the Tailscale node agent.
type Prefs struct { type Prefs struct {
// ControlURL is the URL of the control server to use. // ControlURL is the URL of the control server to use.
@ -261,16 +263,6 @@ func PrefsFromBytes(b []byte, enforceDefaults bool) (*Prefs, error) {
return p, err return p, err
} }
// Clone returns a deep copy of p.
func (p *Prefs) Clone() *Prefs {
// TODO: write a faster/non-Fatal-y Clone implementation?
p2, err := PrefsFromBytes(p.ToBytes(), false)
if err != nil {
log.Fatalf("Prefs was uncopyable: %v\n", err)
}
return p2
}
// LoadPrefs loads a legacy relaynode config file into Prefs // LoadPrefs loads a legacy relaynode config file into Prefs
// with sensible migration defaults set. // with sensible migration defaults set.
func LoadPrefs(filename string) (*Prefs, error) { func LoadPrefs(filename string) (*Prefs, error) {

@ -0,0 +1,51 @@
// 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 Prefs; DO NOT EDIT.
package ipn
import (
"github.com/tailscale/wireguard-go/wgcfg"
"tailscale.com/control/controlclient"
"tailscale.com/wgengine/router"
)
// Clone makes a deep copy of Prefs.
// The result aliases no memory with the original.
func (src *Prefs) Clone() *Prefs {
if src == nil {
return nil
}
dst := new(Prefs)
*dst = *src
dst.AdvertiseTags = append(src.AdvertiseTags[:0:0], src.AdvertiseTags...)
dst.AdvertiseRoutes = append(src.AdvertiseRoutes[:0:0], src.AdvertiseRoutes...)
if dst.Persist != nil {
dst.Persist = new(controlclient.Persist)
*dst.Persist = *src.Persist
}
return dst
}
// A compilation failure here means this code must be regenerated, with command:
// tailscale.com/cmd/cloner -type Prefs
var _PrefsNeedsRegeneration = Prefs(struct {
ControlURL string
RouteAll bool
AllowSingleHosts bool
CorpDNS bool
WantRunning bool
ShieldsUp bool
AdvertiseTags []string
Hostname string
OSVersion string
DeviceModel string
NotepadURLs bool
ForceDaemon bool
AdvertiseRoutes []wgcfg.CIDR
NoSNAT bool
NetfilterMode router.NetfilterMode
Persist *controlclient.Persist
}{})

@ -4,7 +4,7 @@
package tailcfg package tailcfg
//go:generate go run tailscale.com/cmd/cloner -type=User,Node,Hostinfo,NetInfo,Group,Role,Capability,Login,DNSConfig,RegisterResponse -output=tailcfg_clone.go //go:generate go run tailscale.com/cmd/cloner --type=User,Node,Hostinfo,NetInfo,Group,Role,Capability,Login,DNSConfig,RegisterResponse --clonefunc=true --output=tailcfg_clone.go
import ( import (
"bytes" "bytes"

Loading…
Cancel
Save