From 0f188017169ff6e6a761b696309c30409e9ae624 Mon Sep 17 00:00:00 2001 From: julianknodt Date: Tue, 22 Jun 2021 22:01:11 -0700 Subject: [PATCH] cmd/cloner: support maps with clone ptrs In order to clone DERPMaps, it was necessary to extend the cloner so that it supports nested pointers inside of maps which are also cloneable. This also adds cloning for DERPRegions and DERPNodes because they are on DERPMap's maps. Signed-off-by: julianknodt --- cmd/cloner/cloner.go | 4 +- tailcfg/tailcfg.go | 2 +- tailcfg/tailcfg_clone.go | 121 +++++++++++++++++++++++++++++++++++---- 3 files changed, 115 insertions(+), 12 deletions(-) diff --git a/cmd/cloner/cloner.go b/cmd/cloner/cloner.go index c5be5279e..6784f9dc4 100644 --- a/cmd/cloner/cloner.go +++ b/cmd/cloner/cloner.go @@ -246,7 +246,9 @@ func gen(buf *bytes.Buffer, imports map[string]struct{}, name string, typ *types writef("\t\tdst.%s[k] = append([]%s{}, src.%s[k]...)", fname, n, fname) writef("\t}") } else if containsPointers(ft.Elem()) { - writef("\t\t" + `panic("TODO map value pointers")`) + writef("\tfor k, v := range src.%s {", fname) + writef("\t\tdst.%s[k] = v.Clone()", fname) + writef("\t}") } else { writef("\tfor k, v := range src.%s {", fname) writef("\t\tdst.%s[k] = v", fname) diff --git a/tailcfg/tailcfg.go b/tailcfg/tailcfg.go index 1da0f643b..f4175cb59 100644 --- a/tailcfg/tailcfg.go +++ b/tailcfg/tailcfg.go @@ -4,7 +4,7 @@ package tailcfg -//go:generate go run tailscale.com/cmd/cloner --type=User,Node,Hostinfo,NetInfo,Login,DNSConfig,DNSResolver,RegisterResponse --clonefunc=true --output=tailcfg_clone.go +//go:generate go run tailscale.com/cmd/cloner --type=User,Node,Hostinfo,NetInfo,Login,DNSConfig,DNSResolver,RegisterResponse,DERPRegion,DERPMap,DERPNode --clonefunc=true --output=tailcfg_clone.go import ( "encoding/hex" diff --git a/tailcfg/tailcfg_clone.go b/tailcfg/tailcfg_clone.go index 706ac2981..c4701eaf2 100644 --- a/tailcfg/tailcfg_clone.go +++ b/tailcfg/tailcfg_clone.go @@ -2,7 +2,7 @@ // 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 User,Node,Hostinfo,NetInfo,Login,DNSConfig,DNSResolver,RegisterResponse; DO NOT EDIT. +// Code generated by tailscale.com/cmd/cloner -type User,Node,Hostinfo,NetInfo,Login,DNSConfig,DNSResolver,RegisterResponse,DERPRegion,DERPMap,DERPNode; DO NOT EDIT. package tailcfg @@ -26,7 +26,7 @@ func (src *User) Clone() *User { } // A compilation failure here means this code must be regenerated, with command: -// tailscale.com/cmd/cloner -type User,Node,Hostinfo,NetInfo,Login,DNSConfig,DNSResolver,RegisterResponse +// tailscale.com/cmd/cloner -type User,Node,Hostinfo,NetInfo,Login,DNSConfig,DNSResolver,RegisterResponse,DERPRegion,DERPMap,DERPNode var _UserNeedsRegeneration = User(struct { ID UserID LoginName string @@ -62,7 +62,7 @@ func (src *Node) Clone() *Node { } // A compilation failure here means this code must be regenerated, with command: -// tailscale.com/cmd/cloner -type User,Node,Hostinfo,NetInfo,Login,DNSConfig,DNSResolver,RegisterResponse +// tailscale.com/cmd/cloner -type User,Node,Hostinfo,NetInfo,Login,DNSConfig,DNSResolver,RegisterResponse,DERPRegion,DERPMap,DERPNode var _NodeNeedsRegeneration = Node(struct { ID NodeID StableID StableNodeID @@ -105,7 +105,7 @@ func (src *Hostinfo) Clone() *Hostinfo { } // A compilation failure here means this code must be regenerated, with command: -// tailscale.com/cmd/cloner -type User,Node,Hostinfo,NetInfo,Login,DNSConfig,DNSResolver,RegisterResponse +// tailscale.com/cmd/cloner -type User,Node,Hostinfo,NetInfo,Login,DNSConfig,DNSResolver,RegisterResponse,DERPRegion,DERPMap,DERPNode var _HostinfoNeedsRegeneration = Hostinfo(struct { IPNVersion string FrontendLogID string @@ -142,7 +142,7 @@ func (src *NetInfo) Clone() *NetInfo { } // A compilation failure here means this code must be regenerated, with command: -// tailscale.com/cmd/cloner -type User,Node,Hostinfo,NetInfo,Login,DNSConfig,DNSResolver,RegisterResponse +// tailscale.com/cmd/cloner -type User,Node,Hostinfo,NetInfo,Login,DNSConfig,DNSResolver,RegisterResponse,DERPRegion,DERPMap,DERPNode var _NetInfoNeedsRegeneration = NetInfo(struct { MappingVariesByDestIP opt.Bool HairPinning opt.Bool @@ -169,7 +169,7 @@ func (src *Login) Clone() *Login { } // A compilation failure here means this code must be regenerated, with command: -// tailscale.com/cmd/cloner -type User,Node,Hostinfo,NetInfo,Login,DNSConfig,DNSResolver,RegisterResponse +// tailscale.com/cmd/cloner -type User,Node,Hostinfo,NetInfo,Login,DNSConfig,DNSResolver,RegisterResponse,DERPRegion,DERPMap,DERPNode var _LoginNeedsRegeneration = Login(struct { _ structs.Incomparable ID LoginID @@ -210,7 +210,7 @@ func (src *DNSConfig) Clone() *DNSConfig { } // A compilation failure here means this code must be regenerated, with command: -// tailscale.com/cmd/cloner -type User,Node,Hostinfo,NetInfo,Login,DNSConfig,DNSResolver,RegisterResponse +// tailscale.com/cmd/cloner -type User,Node,Hostinfo,NetInfo,Login,DNSConfig,DNSResolver,RegisterResponse,DERPRegion,DERPMap,DERPNode var _DNSConfigNeedsRegeneration = DNSConfig(struct { Resolvers []DNSResolver Routes map[string][]DNSResolver @@ -236,7 +236,7 @@ func (src *DNSResolver) Clone() *DNSResolver { } // A compilation failure here means this code must be regenerated, with command: -// tailscale.com/cmd/cloner -type User,Node,Hostinfo,NetInfo,Login,DNSConfig,DNSResolver,RegisterResponse +// tailscale.com/cmd/cloner -type User,Node,Hostinfo,NetInfo,Login,DNSConfig,DNSResolver,RegisterResponse,DERPRegion,DERPMap,DERPNode var _DNSResolverNeedsRegeneration = DNSResolver(struct { Addr string BootstrapResolution []netaddr.IP @@ -255,7 +255,7 @@ func (src *RegisterResponse) Clone() *RegisterResponse { } // A compilation failure here means this code must be regenerated, with command: -// tailscale.com/cmd/cloner -type User,Node,Hostinfo,NetInfo,Login,DNSConfig,DNSResolver,RegisterResponse +// tailscale.com/cmd/cloner -type User,Node,Hostinfo,NetInfo,Login,DNSConfig,DNSResolver,RegisterResponse,DERPRegion,DERPMap,DERPNode var _RegisterResponseNeedsRegeneration = RegisterResponse(struct { User User Login Login @@ -264,9 +264,83 @@ func (src *RegisterResponse) Clone() *RegisterResponse { AuthURL string }{}) +// Clone makes a deep copy of DERPRegion. +// The result aliases no memory with the original. +func (src *DERPRegion) Clone() *DERPRegion { + if src == nil { + return nil + } + dst := new(DERPRegion) + *dst = *src + dst.Nodes = make([]*DERPNode, len(src.Nodes)) + for i := range dst.Nodes { + dst.Nodes[i] = src.Nodes[i].Clone() + } + return dst +} + +// A compilation failure here means this code must be regenerated, with command: +// tailscale.com/cmd/cloner -type User,Node,Hostinfo,NetInfo,Login,DNSConfig,DNSResolver,RegisterResponse,DERPRegion,DERPMap,DERPNode +var _DERPRegionNeedsRegeneration = DERPRegion(struct { + RegionID int + RegionCode string + RegionName string + Avoid bool + Nodes []*DERPNode +}{}) + +// Clone makes a deep copy of DERPMap. +// The result aliases no memory with the original. +func (src *DERPMap) Clone() *DERPMap { + if src == nil { + return nil + } + dst := new(DERPMap) + *dst = *src + if dst.Regions != nil { + dst.Regions = map[int]*DERPRegion{} + for k, v := range src.Regions { + dst.Regions[k] = v.Clone() + } + } + return dst +} + +// A compilation failure here means this code must be regenerated, with command: +// tailscale.com/cmd/cloner -type User,Node,Hostinfo,NetInfo,Login,DNSConfig,DNSResolver,RegisterResponse,DERPRegion,DERPMap,DERPNode +var _DERPMapNeedsRegeneration = DERPMap(struct { + Regions map[int]*DERPRegion +}{}) + +// Clone makes a deep copy of DERPNode. +// The result aliases no memory with the original. +func (src *DERPNode) Clone() *DERPNode { + if src == nil { + return nil + } + dst := new(DERPNode) + *dst = *src + return dst +} + +// A compilation failure here means this code must be regenerated, with command: +// tailscale.com/cmd/cloner -type User,Node,Hostinfo,NetInfo,Login,DNSConfig,DNSResolver,RegisterResponse,DERPRegion,DERPMap,DERPNode +var _DERPNodeNeedsRegeneration = DERPNode(struct { + Name string + RegionID int + HostName string + CertName string + IPv4 string + IPv6 string + STUNPort int + STUNOnly bool + DERPTestPort int + STUNTestIP string +}{}) + // Clone duplicates src into dst and reports whether it succeeded. // To succeed, must be of types <*T, *T> or <*T, **T>, -// where T is one of User,Node,Hostinfo,NetInfo,Login,DNSConfig,DNSResolver,RegisterResponse. +// where T is one of User,Node,Hostinfo,NetInfo,Login,DNSConfig,DNSResolver,RegisterResponse,DERPRegion,DERPMap,DERPNode. func Clone(dst, src interface{}) bool { switch src := src.(type) { case *User: @@ -341,6 +415,33 @@ func Clone(dst, src interface{}) bool { *dst = src.Clone() return true } + case *DERPRegion: + switch dst := dst.(type) { + case *DERPRegion: + *dst = *src.Clone() + return true + case **DERPRegion: + *dst = src.Clone() + return true + } + case *DERPMap: + switch dst := dst.(type) { + case *DERPMap: + *dst = *src.Clone() + return true + case **DERPMap: + *dst = src.Clone() + return true + } + case *DERPNode: + switch dst := dst.(type) { + case *DERPNode: + *dst = *src.Clone() + return true + case **DERPNode: + *dst = src.Clone() + return true + } } return false }