perf: remove expensive reflection from xDS hot path (#14934)

Replaces the reflection-based implementation of proxycfg's
ConfigSnapshot.Clone with code generated by deep-copy.

While load testing server-based xDS (for consul-dataplane) we discovered
this method is extremely expensive. The ConfigSnapshot struct, directly
or indirectly, contains a copy of many of the structs in the agent/structs
package, which creates a large graph for copystructure.Copy to traverse
at runtime, on every proxy reconfiguration.
pull/14960/head
Dan Upton 2 years ago committed by GitHub
parent 03734a1bac
commit e6b55d1d81
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23

@ -0,0 +1,3 @@
```release-note:enhancement
xds: Removed a bottleneck in Envoy config generation, enabling a higher number of dataplanes per server
```

@ -263,6 +263,26 @@ jobs:
name: "Protobuf Lint"
command: make proto-lint
check-generated-deep-copy:
docker:
- image: *GOLANG_IMAGE
environment:
<<: *ENVIRONMENT
# tput complains if this isn't set to something.
TERM: ansi
steps:
- checkout
- run:
name: Install deep-copy
command: make codegen-tools
- run:
command: make --always-make deep-copy
- run: |
if ! git diff --exit-code; then
echo "Generated code was not updated correctly"
exit 1
fi
go-test-arm64:
machine:
image: *UBUNTU_CI_IMAGE
@ -1036,6 +1056,7 @@ workflows:
- /^docs\/.*/
- /^ui\/.*/
- check-generated-protobuf: *filter-ignore-non-go-branches
- check-generated-deep-copy: *filter-ignore-non-go-branches
- lint-enums: *filter-ignore-non-go-branches
- lint-consul-retry: *filter-ignore-non-go-branches
- lint: *filter-ignore-non-go-branches

@ -13,6 +13,7 @@ BUF_VERSION='v1.4.0'
PROTOC_GEN_GO_GRPC_VERSION="v1.2.0"
MOG_VERSION='v0.3.0'
PROTOC_GO_INJECT_TAG_VERSION='v1.3.0'
DEEP_COPY_VERSION='bc3f5aa5735d8a54961580a3a24422c308c831c2'
MOCKED_PB_DIRS= pbdns
@ -321,6 +322,16 @@ lint-tools:
proto-tools:
@$(SHELL) $(CURDIR)/build-support/scripts/devtools.sh -protobuf
.PHONY: codegen-tools
codegen-tools:
@$(SHELL) $(CURDIR)/build-support/scripts/devtools.sh -codegen
.PHONY: deep-copy
deep-copy:
@$(SHELL) $(CURDIR)/agent/structs/deep-copy.sh
@$(SHELL) $(CURDIR)/proto/pbpeering/deep-copy.sh
@$(SHELL) $(CURDIR)/agent/proxycfg/deep-copy.sh
version:
@echo -n "Version: "
@$(SHELL) $(CURDIR)/build-support/scripts/version.sh

@ -0,0 +1,17 @@
#!/usr/bin/env bash
readonly PACKAGE_DIR="$(dirname "${BASH_SOURCE[0]}")"
cd $PACKAGE_DIR
# Uses: https://github.com/globusdigital/deep-copy
deep-copy -pointer-receiver \
-o ./proxycfg.deepcopy.go \
-type ConfigSnapshot \
-type ConfigSnapshotUpstreams \
-type PeerServersValue \
-type PeeringServiceValue \
-type configSnapshotConnectProxy \
-type configSnapshotIngressGateway \
-type configSnapshotMeshGateway \
-type configSnapshotTerminatingGateway \
./

@ -2,11 +2,18 @@ package watch
import "context"
// DeepCopyable describes a type that implements the DeepCopy
// method to get a copy of itself that is safe to pass around
// without worrying about receivers modifying the original.
type DeepCopyable[T any] interface {
DeepCopy() T
}
// Map safely stores and retrieves values by validating that
// there is a live watch for a key. InitWatch must be called
// to associate a key with its cancel function before any
// Set's are called.
type Map[K comparable, V any] struct {
type Map[K comparable, V DeepCopyable[V]] struct {
M map[K]watchedVal[V]
}
@ -20,10 +27,26 @@ type watchedVal[V any] struct {
cancel context.CancelFunc
}
func NewMap[K comparable, V any]() Map[K, V] {
func NewMap[K comparable, V DeepCopyable[V]]() Map[K, V] {
return Map[K, V]{M: make(map[K]watchedVal[V])}
}
// DeepCopy returns a copy of the Map that is safe to be passed
// around without worrying about receivers modifying the original
// or canceling its watches.
func (m Map[K, V]) DeepCopy() Map[K, V] {
dup := make(map[K]watchedVal[V], len(m.M))
for k, v := range m.M {
var val *V
if v.Val != nil {
dc := (*v.Val).DeepCopy()
val = &dc
}
dup[k] = watchedVal[V]{Val: val}
}
return Map[K, V]{M: dup}
}
// InitWatch associates a cancel function with a key,
// allowing Set to be called for the key. The cancel
// function is allowed to be nil.

@ -8,7 +8,7 @@ import (
)
func TestMap(t *testing.T) {
m := NewMap[string, string]()
m := NewMap[string, testVal]()
// Set without init is a no-op
{
@ -51,7 +51,7 @@ func TestMap(t *testing.T) {
{
got, ok := m.Get("hello")
require.True(t, ok)
require.Equal(t, "world", got)
require.Equal(t, "world", string(got))
}
// CancelWatch successful
@ -76,15 +76,11 @@ func TestMap(t *testing.T) {
}
func TestMap_ForEach(t *testing.T) {
type testType struct {
s string
}
m := NewMap[string, any]()
inputs := map[string]any{
"hello": 13,
"foo": struct{}{},
"bar": &testType{s: "wow"},
m := NewMap[string, testVal]()
inputs := map[string]testVal{
"hello": "world",
"foo": "bar",
"baz": "bat",
}
for k, v := range inputs {
m.InitWatch(k, nil)
@ -114,15 +110,11 @@ func TestMap_ForEach(t *testing.T) {
}
func TestMap_ForEachE(t *testing.T) {
type testType struct {
s string
}
m := NewMap[string, any]()
inputs := map[string]any{
"hello": 13,
"foo": struct{}{},
"bar": &testType{s: "wow"},
m := NewMap[string, testVal]()
inputs := map[string]testVal{
"hello": "world",
"foo": "bar",
"baz": "bat",
}
for k, v := range inputs {
m.InitWatch(k, nil)
@ -152,3 +144,27 @@ func TestMap_ForEachE(t *testing.T) {
require.Errorf(t, err, "boo")
}
}
func TestMap_DeepCopy(t *testing.T) {
orig := NewMap[string, testVal]()
inputs := map[string]testVal{
"hello": "world",
"foo": "bar",
"baz": "bat",
}
for k, v := range inputs {
orig.InitWatch(k, nil)
orig.Set(k, v)
}
require.Equal(t, 3, orig.Len())
clone := orig.DeepCopy()
require.Equal(t, 3, clone.Len())
orig.CancelWatch("hello")
require.NotEqual(t, orig.Len(), clone.Len())
}
type testVal string
func (tv testVal) DeepCopy() testVal { return tv }

@ -4,7 +4,6 @@ import (
"testing"
"time"
"github.com/mitchellh/copystructure"
"github.com/stretchr/testify/require"
"github.com/hashicorp/consul/acl"
@ -326,17 +325,14 @@ func TestManager_BasicLifecycle(t *testing.T) {
dataSources.ConfigEntry.Set(meshConfigReq, &structs.ConfigEntryResponse{Entry: nil})
tt.setup(t, dataSources)
expectSnapCopy, err := tt.expectSnap.Clone()
require.NoError(t, err)
webProxyCopy, err := copystructure.Copy(webProxy)
require.NoError(t, err)
expectSnapCopy := tt.expectSnap.Clone()
webProxyCopy := webProxy.DeepCopy()
testManager_BasicLifecycle(t,
dataSources,
rootsReq, leafReq,
roots,
webProxyCopy.(*structs.NodeService),
webProxyCopy,
expectSnapCopy,
)
})

@ -0,0 +1,607 @@
// generated by deep-copy -pointer-receiver -o ./proxycfg.deepcopy.go -type ConfigSnapshot -type ConfigSnapshotUpstreams -type PeerServersValue -type PeeringServiceValue -type configSnapshotConnectProxy -type configSnapshotIngressGateway -type configSnapshotMeshGateway -type configSnapshotTerminatingGateway ./; DO NOT EDIT.
package proxycfg
import (
"context"
"github.com/hashicorp/consul/agent/structs"
"github.com/hashicorp/consul/proto/pbpeering"
"github.com/hashicorp/consul/types"
)
// DeepCopy generates a deep copy of *ConfigSnapshot
func (o *ConfigSnapshot) DeepCopy() *ConfigSnapshot {
var cp ConfigSnapshot = *o
if o.ServiceMeta != nil {
cp.ServiceMeta = make(map[string]string, len(o.ServiceMeta))
for k2, v2 := range o.ServiceMeta {
cp.ServiceMeta[k2] = v2
}
}
if o.TaggedAddresses != nil {
cp.TaggedAddresses = make(map[string]structs.ServiceAddress, len(o.TaggedAddresses))
for k2, v2 := range o.TaggedAddresses {
cp.TaggedAddresses[k2] = v2
}
}
{
retV := o.Proxy.DeepCopy()
cp.Proxy = *retV
}
if o.Roots != nil {
cp.Roots = o.Roots.DeepCopy()
}
{
retV := o.ConnectProxy.DeepCopy()
cp.ConnectProxy = *retV
}
{
retV := o.TerminatingGateway.DeepCopy()
cp.TerminatingGateway = *retV
}
{
retV := o.MeshGateway.DeepCopy()
cp.MeshGateway = *retV
}
{
retV := o.IngressGateway.DeepCopy()
cp.IngressGateway = *retV
}
return &cp
}
// DeepCopy generates a deep copy of *ConfigSnapshotUpstreams
func (o *ConfigSnapshotUpstreams) DeepCopy() *ConfigSnapshotUpstreams {
var cp ConfigSnapshotUpstreams = *o
if o.Leaf != nil {
cp.Leaf = new(structs.IssuedCert)
*cp.Leaf = *o.Leaf
}
if o.MeshConfig != nil {
cp.MeshConfig = o.MeshConfig.DeepCopy()
}
if o.DiscoveryChain != nil {
cp.DiscoveryChain = make(map[UpstreamID]*structs.CompiledDiscoveryChain, len(o.DiscoveryChain))
for k2, v2 := range o.DiscoveryChain {
var cp_DiscoveryChain_v2 *structs.CompiledDiscoveryChain
if v2 != nil {
cp_DiscoveryChain_v2 = v2.DeepCopy()
}
cp.DiscoveryChain[k2] = cp_DiscoveryChain_v2
}
}
if o.WatchedDiscoveryChains != nil {
cp.WatchedDiscoveryChains = make(map[UpstreamID]context.CancelFunc, len(o.WatchedDiscoveryChains))
for k2, v2 := range o.WatchedDiscoveryChains {
cp.WatchedDiscoveryChains[k2] = v2
}
}
if o.WatchedUpstreams != nil {
cp.WatchedUpstreams = make(map[UpstreamID]map[string]context.CancelFunc, len(o.WatchedUpstreams))
for k2, v2 := range o.WatchedUpstreams {
var cp_WatchedUpstreams_v2 map[string]context.CancelFunc
if v2 != nil {
cp_WatchedUpstreams_v2 = make(map[string]context.CancelFunc, len(v2))
for k3, v3 := range v2 {
cp_WatchedUpstreams_v2[k3] = v3
}
}
cp.WatchedUpstreams[k2] = cp_WatchedUpstreams_v2
}
}
if o.WatchedUpstreamEndpoints != nil {
cp.WatchedUpstreamEndpoints = make(map[UpstreamID]map[string]structs.CheckServiceNodes, len(o.WatchedUpstreamEndpoints))
for k2, v2 := range o.WatchedUpstreamEndpoints {
var cp_WatchedUpstreamEndpoints_v2 map[string]structs.CheckServiceNodes
if v2 != nil {
cp_WatchedUpstreamEndpoints_v2 = make(map[string]structs.CheckServiceNodes, len(v2))
for k3, v3 := range v2 {
var cp_WatchedUpstreamEndpoints_v2_v3 structs.CheckServiceNodes
cp_WatchedUpstreamEndpoints_v2_v3 = v3.DeepCopy()
cp_WatchedUpstreamEndpoints_v2[k3] = cp_WatchedUpstreamEndpoints_v2_v3
}
}
cp.WatchedUpstreamEndpoints[k2] = cp_WatchedUpstreamEndpoints_v2
}
}
cp.UpstreamPeerTrustBundles = o.UpstreamPeerTrustBundles.DeepCopy()
if o.WatchedGateways != nil {
cp.WatchedGateways = make(map[UpstreamID]map[string]context.CancelFunc, len(o.WatchedGateways))
for k2, v2 := range o.WatchedGateways {
var cp_WatchedGateways_v2 map[string]context.CancelFunc
if v2 != nil {
cp_WatchedGateways_v2 = make(map[string]context.CancelFunc, len(v2))
for k3, v3 := range v2 {
cp_WatchedGateways_v2[k3] = v3
}
}
cp.WatchedGateways[k2] = cp_WatchedGateways_v2
}
}
if o.WatchedGatewayEndpoints != nil {
cp.WatchedGatewayEndpoints = make(map[UpstreamID]map[string]structs.CheckServiceNodes, len(o.WatchedGatewayEndpoints))
for k2, v2 := range o.WatchedGatewayEndpoints {
var cp_WatchedGatewayEndpoints_v2 map[string]structs.CheckServiceNodes
if v2 != nil {
cp_WatchedGatewayEndpoints_v2 = make(map[string]structs.CheckServiceNodes, len(v2))
for k3, v3 := range v2 {
var cp_WatchedGatewayEndpoints_v2_v3 structs.CheckServiceNodes
cp_WatchedGatewayEndpoints_v2_v3 = v3.DeepCopy()
cp_WatchedGatewayEndpoints_v2[k3] = cp_WatchedGatewayEndpoints_v2_v3
}
}
cp.WatchedGatewayEndpoints[k2] = cp_WatchedGatewayEndpoints_v2
}
}
cp.WatchedLocalGWEndpoints = o.WatchedLocalGWEndpoints.DeepCopy()
if o.UpstreamConfig != nil {
cp.UpstreamConfig = make(map[UpstreamID]*structs.Upstream, len(o.UpstreamConfig))
for k2, v2 := range o.UpstreamConfig {
var cp_UpstreamConfig_v2 *structs.Upstream
if v2 != nil {
cp_UpstreamConfig_v2 = v2.DeepCopy()
}
cp.UpstreamConfig[k2] = cp_UpstreamConfig_v2
}
}
if o.PassthroughUpstreams != nil {
cp.PassthroughUpstreams = make(map[UpstreamID]map[string]map[string]struct{}, len(o.PassthroughUpstreams))
for k2, v2 := range o.PassthroughUpstreams {
var cp_PassthroughUpstreams_v2 map[string]map[string]struct{}
if v2 != nil {
cp_PassthroughUpstreams_v2 = make(map[string]map[string]struct{}, len(v2))
for k3, v3 := range v2 {
var cp_PassthroughUpstreams_v2_v3 map[string]struct{}
if v3 != nil {
cp_PassthroughUpstreams_v2_v3 = make(map[string]struct{}, len(v3))
for k4, v4 := range v3 {
cp_PassthroughUpstreams_v2_v3[k4] = v4
}
}
cp_PassthroughUpstreams_v2[k3] = cp_PassthroughUpstreams_v2_v3
}
}
cp.PassthroughUpstreams[k2] = cp_PassthroughUpstreams_v2
}
}
if o.PassthroughIndices != nil {
cp.PassthroughIndices = make(map[string]indexedTarget, len(o.PassthroughIndices))
for k2, v2 := range o.PassthroughIndices {
cp.PassthroughIndices[k2] = v2
}
}
if o.IntentionUpstreams != nil {
cp.IntentionUpstreams = make(map[UpstreamID]struct{}, len(o.IntentionUpstreams))
for k2, v2 := range o.IntentionUpstreams {
cp.IntentionUpstreams[k2] = v2
}
}
if o.PeeredUpstreams != nil {
cp.PeeredUpstreams = make(map[UpstreamID]struct{}, len(o.PeeredUpstreams))
for k2, v2 := range o.PeeredUpstreams {
cp.PeeredUpstreams[k2] = v2
}
}
cp.PeerUpstreamEndpoints = o.PeerUpstreamEndpoints.DeepCopy()
if o.PeerUpstreamEndpointsUseHostnames != nil {
cp.PeerUpstreamEndpointsUseHostnames = make(map[UpstreamID]struct{}, len(o.PeerUpstreamEndpointsUseHostnames))
for k2, v2 := range o.PeerUpstreamEndpointsUseHostnames {
cp.PeerUpstreamEndpointsUseHostnames[k2] = v2
}
}
return &cp
}
// DeepCopy generates a deep copy of *PeerServersValue
func (o *PeerServersValue) DeepCopy() *PeerServersValue {
var cp PeerServersValue = *o
if o.Addresses != nil {
cp.Addresses = make([]structs.ServiceAddress, len(o.Addresses))
copy(cp.Addresses, o.Addresses)
}
return &cp
}
// DeepCopy generates a deep copy of *PeeringServiceValue
func (o *PeeringServiceValue) DeepCopy() *PeeringServiceValue {
var cp PeeringServiceValue = *o
cp.Nodes = o.Nodes.DeepCopy()
return &cp
}
// DeepCopy generates a deep copy of *configSnapshotConnectProxy
func (o *configSnapshotConnectProxy) DeepCopy() *configSnapshotConnectProxy {
var cp configSnapshotConnectProxy = *o
{
retV := o.ConfigSnapshotUpstreams.DeepCopy()
cp.ConfigSnapshotUpstreams = *retV
}
if o.InboundPeerTrustBundles != nil {
cp.InboundPeerTrustBundles = make([]*pbpeering.PeeringTrustBundle, len(o.InboundPeerTrustBundles))
copy(cp.InboundPeerTrustBundles, o.InboundPeerTrustBundles)
for i2 := range o.InboundPeerTrustBundles {
if o.InboundPeerTrustBundles[i2] != nil {
cp.InboundPeerTrustBundles[i2] = o.InboundPeerTrustBundles[i2].DeepCopy()
}
}
}
if o.WatchedServiceChecks != nil {
cp.WatchedServiceChecks = make(map[structs.ServiceID][]structs.CheckType, len(o.WatchedServiceChecks))
for k2, v2 := range o.WatchedServiceChecks {
var cp_WatchedServiceChecks_v2 []structs.CheckType
if v2 != nil {
cp_WatchedServiceChecks_v2 = make([]structs.CheckType, len(v2))
copy(cp_WatchedServiceChecks_v2, v2)
for i3 := range v2 {
{
retV := v2[i3].DeepCopy()
cp_WatchedServiceChecks_v2[i3] = *retV
}
}
}
cp.WatchedServiceChecks[k2] = cp_WatchedServiceChecks_v2
}
}
if o.PreparedQueryEndpoints != nil {
cp.PreparedQueryEndpoints = make(map[UpstreamID]structs.CheckServiceNodes, len(o.PreparedQueryEndpoints))
for k2, v2 := range o.PreparedQueryEndpoints {
var cp_PreparedQueryEndpoints_v2 structs.CheckServiceNodes
cp_PreparedQueryEndpoints_v2 = v2.DeepCopy()
cp.PreparedQueryEndpoints[k2] = cp_PreparedQueryEndpoints_v2
}
}
if o.Intentions != nil {
cp.Intentions = make([]*structs.Intention, len(o.Intentions))
copy(cp.Intentions, o.Intentions)
for i2 := range o.Intentions {
if o.Intentions[i2] != nil {
cp.Intentions[i2] = o.Intentions[i2].DeepCopy()
}
}
}
cp.DestinationsUpstream = o.DestinationsUpstream.DeepCopy()
cp.DestinationGateways = o.DestinationGateways.DeepCopy()
return &cp
}
// DeepCopy generates a deep copy of *configSnapshotIngressGateway
func (o *configSnapshotIngressGateway) DeepCopy() *configSnapshotIngressGateway {
var cp configSnapshotIngressGateway = *o
{
retV := o.ConfigSnapshotUpstreams.DeepCopy()
cp.ConfigSnapshotUpstreams = *retV
}
if o.TLSConfig.SDS != nil {
cp.TLSConfig.SDS = new(structs.GatewayTLSSDSConfig)
*cp.TLSConfig.SDS = *o.TLSConfig.SDS
}
if o.TLSConfig.CipherSuites != nil {
cp.TLSConfig.CipherSuites = make([]types.TLSCipherSuite, len(o.TLSConfig.CipherSuites))
copy(cp.TLSConfig.CipherSuites, o.TLSConfig.CipherSuites)
}
if o.Hosts != nil {
cp.Hosts = make([]string, len(o.Hosts))
copy(cp.Hosts, o.Hosts)
}
if o.Upstreams != nil {
cp.Upstreams = make(map[IngressListenerKey]structs.Upstreams, len(o.Upstreams))
for k2, v2 := range o.Upstreams {
var cp_Upstreams_v2 structs.Upstreams
if v2 != nil {
cp_Upstreams_v2 = make([]structs.Upstream, len(v2))
copy(cp_Upstreams_v2, v2)
for i3 := range v2 {
{
retV := v2[i3].DeepCopy()
cp_Upstreams_v2[i3] = *retV
}
}
}
cp.Upstreams[k2] = cp_Upstreams_v2
}
}
if o.UpstreamsSet != nil {
cp.UpstreamsSet = make(map[UpstreamID]struct{}, len(o.UpstreamsSet))
for k2, v2 := range o.UpstreamsSet {
cp.UpstreamsSet[k2] = v2
}
}
if o.Listeners != nil {
cp.Listeners = make(map[IngressListenerKey]structs.IngressListener, len(o.Listeners))
for k2, v2 := range o.Listeners {
var cp_Listeners_v2 structs.IngressListener
{
retV := v2.DeepCopy()
cp_Listeners_v2 = *retV
}
cp.Listeners[k2] = cp_Listeners_v2
}
}
return &cp
}
// DeepCopy generates a deep copy of *configSnapshotMeshGateway
func (o *configSnapshotMeshGateway) DeepCopy() *configSnapshotMeshGateway {
var cp configSnapshotMeshGateway = *o
if o.WatchedServices != nil {
cp.WatchedServices = make(map[structs.ServiceName]context.CancelFunc, len(o.WatchedServices))
for k2, v2 := range o.WatchedServices {
cp.WatchedServices[k2] = v2
}
}
if o.WatchedGateways != nil {
cp.WatchedGateways = make(map[string]context.CancelFunc, len(o.WatchedGateways))
for k2, v2 := range o.WatchedGateways {
cp.WatchedGateways[k2] = v2
}
}
if o.ServiceGroups != nil {
cp.ServiceGroups = make(map[structs.ServiceName]structs.CheckServiceNodes, len(o.ServiceGroups))
for k2, v2 := range o.ServiceGroups {
var cp_ServiceGroups_v2 structs.CheckServiceNodes
cp_ServiceGroups_v2 = v2.DeepCopy()
cp.ServiceGroups[k2] = cp_ServiceGroups_v2
}
}
if o.PeeringServices != nil {
cp.PeeringServices = make(map[string]map[structs.ServiceName]PeeringServiceValue, len(o.PeeringServices))
for k2, v2 := range o.PeeringServices {
var cp_PeeringServices_v2 map[structs.ServiceName]PeeringServiceValue
if v2 != nil {
cp_PeeringServices_v2 = make(map[structs.ServiceName]PeeringServiceValue, len(v2))
for k3, v3 := range v2 {
var cp_PeeringServices_v2_v3 PeeringServiceValue
{
retV := v3.DeepCopy()
cp_PeeringServices_v2_v3 = *retV
}
cp_PeeringServices_v2[k3] = cp_PeeringServices_v2_v3
}
}
cp.PeeringServices[k2] = cp_PeeringServices_v2
}
}
if o.WatchedPeeringServices != nil {
cp.WatchedPeeringServices = make(map[string]map[structs.ServiceName]context.CancelFunc, len(o.WatchedPeeringServices))
for k2, v2 := range o.WatchedPeeringServices {
var cp_WatchedPeeringServices_v2 map[structs.ServiceName]context.CancelFunc
if v2 != nil {
cp_WatchedPeeringServices_v2 = make(map[structs.ServiceName]context.CancelFunc, len(v2))
for k3, v3 := range v2 {
cp_WatchedPeeringServices_v2[k3] = v3
}
}
cp.WatchedPeeringServices[k2] = cp_WatchedPeeringServices_v2
}
}
if o.WatchedPeers != nil {
cp.WatchedPeers = make(map[string]context.CancelFunc, len(o.WatchedPeers))
for k2, v2 := range o.WatchedPeers {
cp.WatchedPeers[k2] = v2
}
}
if o.ServiceResolvers != nil {
cp.ServiceResolvers = make(map[structs.ServiceName]*structs.ServiceResolverConfigEntry, len(o.ServiceResolvers))
for k2, v2 := range o.ServiceResolvers {
var cp_ServiceResolvers_v2 *structs.ServiceResolverConfigEntry
if v2 != nil {
cp_ServiceResolvers_v2 = v2.DeepCopy()
}
cp.ServiceResolvers[k2] = cp_ServiceResolvers_v2
}
}
if o.GatewayGroups != nil {
cp.GatewayGroups = make(map[string]structs.CheckServiceNodes, len(o.GatewayGroups))
for k2, v2 := range o.GatewayGroups {
var cp_GatewayGroups_v2 structs.CheckServiceNodes
cp_GatewayGroups_v2 = v2.DeepCopy()
cp.GatewayGroups[k2] = cp_GatewayGroups_v2
}
}
if o.FedStateGateways != nil {
cp.FedStateGateways = make(map[string]structs.CheckServiceNodes, len(o.FedStateGateways))
for k2, v2 := range o.FedStateGateways {
var cp_FedStateGateways_v2 structs.CheckServiceNodes
cp_FedStateGateways_v2 = v2.DeepCopy()
cp.FedStateGateways[k2] = cp_FedStateGateways_v2
}
}
cp.WatchedLocalServers = o.WatchedLocalServers.DeepCopy()
if o.HostnameDatacenters != nil {
cp.HostnameDatacenters = make(map[string]structs.CheckServiceNodes, len(o.HostnameDatacenters))
for k2, v2 := range o.HostnameDatacenters {
var cp_HostnameDatacenters_v2 structs.CheckServiceNodes
cp_HostnameDatacenters_v2 = v2.DeepCopy()
cp.HostnameDatacenters[k2] = cp_HostnameDatacenters_v2
}
}
if o.ExportedServicesSlice != nil {
cp.ExportedServicesSlice = make([]structs.ServiceName, len(o.ExportedServicesSlice))
copy(cp.ExportedServicesSlice, o.ExportedServicesSlice)
}
if o.ExportedServicesWithPeers != nil {
cp.ExportedServicesWithPeers = make(map[structs.ServiceName][]string, len(o.ExportedServicesWithPeers))
for k2, v2 := range o.ExportedServicesWithPeers {
var cp_ExportedServicesWithPeers_v2 []string
if v2 != nil {
cp_ExportedServicesWithPeers_v2 = make([]string, len(v2))
copy(cp_ExportedServicesWithPeers_v2, v2)
}
cp.ExportedServicesWithPeers[k2] = cp_ExportedServicesWithPeers_v2
}
}
if o.DiscoveryChain != nil {
cp.DiscoveryChain = make(map[structs.ServiceName]*structs.CompiledDiscoveryChain, len(o.DiscoveryChain))
for k2, v2 := range o.DiscoveryChain {
var cp_DiscoveryChain_v2 *structs.CompiledDiscoveryChain
if v2 != nil {
cp_DiscoveryChain_v2 = v2.DeepCopy()
}
cp.DiscoveryChain[k2] = cp_DiscoveryChain_v2
}
}
if o.WatchedDiscoveryChains != nil {
cp.WatchedDiscoveryChains = make(map[structs.ServiceName]context.CancelFunc, len(o.WatchedDiscoveryChains))
for k2, v2 := range o.WatchedDiscoveryChains {
cp.WatchedDiscoveryChains[k2] = v2
}
}
if o.MeshConfig != nil {
cp.MeshConfig = o.MeshConfig.DeepCopy()
}
if o.Leaf != nil {
cp.Leaf = new(structs.IssuedCert)
*cp.Leaf = *o.Leaf
}
if o.PeerServers != nil {
cp.PeerServers = make(map[string]PeerServersValue, len(o.PeerServers))
for k2, v2 := range o.PeerServers {
var cp_PeerServers_v2 PeerServersValue
{
retV := v2.DeepCopy()
cp_PeerServers_v2 = *retV
}
cp.PeerServers[k2] = cp_PeerServers_v2
}
}
if o.PeeringTrustBundles != nil {
cp.PeeringTrustBundles = make([]*pbpeering.PeeringTrustBundle, len(o.PeeringTrustBundles))
copy(cp.PeeringTrustBundles, o.PeeringTrustBundles)
for i2 := range o.PeeringTrustBundles {
if o.PeeringTrustBundles[i2] != nil {
cp.PeeringTrustBundles[i2] = o.PeeringTrustBundles[i2].DeepCopy()
}
}
}
return &cp
}
// DeepCopy generates a deep copy of *configSnapshotTerminatingGateway
func (o *configSnapshotTerminatingGateway) DeepCopy() *configSnapshotTerminatingGateway {
var cp configSnapshotTerminatingGateway = *o
if o.MeshConfig != nil {
cp.MeshConfig = o.MeshConfig.DeepCopy()
}
if o.WatchedServices != nil {
cp.WatchedServices = make(map[structs.ServiceName]context.CancelFunc, len(o.WatchedServices))
for k2, v2 := range o.WatchedServices {
cp.WatchedServices[k2] = v2
}
}
if o.WatchedIntentions != nil {
cp.WatchedIntentions = make(map[structs.ServiceName]context.CancelFunc, len(o.WatchedIntentions))
for k2, v2 := range o.WatchedIntentions {
cp.WatchedIntentions[k2] = v2
}
}
if o.Intentions != nil {
cp.Intentions = make(map[structs.ServiceName]structs.Intentions, len(o.Intentions))
for k2, v2 := range o.Intentions {
var cp_Intentions_v2 structs.Intentions
if v2 != nil {
cp_Intentions_v2 = make([]*structs.Intention, len(v2))
copy(cp_Intentions_v2, v2)
for i3 := range v2 {
if v2[i3] != nil {
cp_Intentions_v2[i3] = v2[i3].DeepCopy()
}
}
}
cp.Intentions[k2] = cp_Intentions_v2
}
}
if o.WatchedLeaves != nil {
cp.WatchedLeaves = make(map[structs.ServiceName]context.CancelFunc, len(o.WatchedLeaves))
for k2, v2 := range o.WatchedLeaves {
cp.WatchedLeaves[k2] = v2
}
}
if o.ServiceLeaves != nil {
cp.ServiceLeaves = make(map[structs.ServiceName]*structs.IssuedCert, len(o.ServiceLeaves))
for k2, v2 := range o.ServiceLeaves {
var cp_ServiceLeaves_v2 *structs.IssuedCert
if v2 != nil {
cp_ServiceLeaves_v2 = new(structs.IssuedCert)
*cp_ServiceLeaves_v2 = *v2
}
cp.ServiceLeaves[k2] = cp_ServiceLeaves_v2
}
}
if o.WatchedConfigs != nil {
cp.WatchedConfigs = make(map[structs.ServiceName]context.CancelFunc, len(o.WatchedConfigs))
for k2, v2 := range o.WatchedConfigs {
cp.WatchedConfigs[k2] = v2
}
}
if o.ServiceConfigs != nil {
cp.ServiceConfigs = make(map[structs.ServiceName]*structs.ServiceConfigResponse, len(o.ServiceConfigs))
for k2, v2 := range o.ServiceConfigs {
var cp_ServiceConfigs_v2 *structs.ServiceConfigResponse
if v2 != nil {
cp_ServiceConfigs_v2 = v2.DeepCopy()
}
cp.ServiceConfigs[k2] = cp_ServiceConfigs_v2
}
}
if o.WatchedResolvers != nil {
cp.WatchedResolvers = make(map[structs.ServiceName]context.CancelFunc, len(o.WatchedResolvers))
for k2, v2 := range o.WatchedResolvers {
cp.WatchedResolvers[k2] = v2
}
}
if o.ServiceResolvers != nil {
cp.ServiceResolvers = make(map[structs.ServiceName]*structs.ServiceResolverConfigEntry, len(o.ServiceResolvers))
for k2, v2 := range o.ServiceResolvers {
var cp_ServiceResolvers_v2 *structs.ServiceResolverConfigEntry
if v2 != nil {
cp_ServiceResolvers_v2 = v2.DeepCopy()
}
cp.ServiceResolvers[k2] = cp_ServiceResolvers_v2
}
}
if o.ServiceResolversSet != nil {
cp.ServiceResolversSet = make(map[structs.ServiceName]bool, len(o.ServiceResolversSet))
for k2, v2 := range o.ServiceResolversSet {
cp.ServiceResolversSet[k2] = v2
}
}
if o.ServiceGroups != nil {
cp.ServiceGroups = make(map[structs.ServiceName]structs.CheckServiceNodes, len(o.ServiceGroups))
for k2, v2 := range o.ServiceGroups {
var cp_ServiceGroups_v2 structs.CheckServiceNodes
cp_ServiceGroups_v2 = v2.DeepCopy()
cp.ServiceGroups[k2] = cp_ServiceGroups_v2
}
}
if o.GatewayServices != nil {
cp.GatewayServices = make(map[structs.ServiceName]structs.GatewayService, len(o.GatewayServices))
for k2, v2 := range o.GatewayServices {
var cp_GatewayServices_v2 structs.GatewayService
{
retV := v2.DeepCopy()
cp_GatewayServices_v2 = *retV
}
cp.GatewayServices[k2] = cp_GatewayServices_v2
}
}
if o.DestinationServices != nil {
cp.DestinationServices = make(map[structs.ServiceName]structs.GatewayService, len(o.DestinationServices))
for k2, v2 := range o.DestinationServices {
var cp_DestinationServices_v2 structs.GatewayService
{
retV := v2.DeepCopy()
cp_DestinationServices_v2 = *retV
}
cp.DestinationServices[k2] = cp_DestinationServices_v2
}
}
if o.HostnameServices != nil {
cp.HostnameServices = make(map[structs.ServiceName]structs.CheckServiceNodes, len(o.HostnameServices))
for k2, v2 := range o.HostnameServices {
var cp_HostnameServices_v2 structs.CheckServiceNodes
cp_HostnameServices_v2 = v2.DeepCopy()
cp.HostnameServices[k2] = cp_HostnameServices_v2
}
}
return &cp
}

@ -50,4 +50,5 @@
// 7. It registers the service with the proxycfg manager.
// 7a. See: 2a.
// 8. xDS server receives snapshots of configuration data whenever it changes.
//
package proxycfg

@ -6,8 +6,6 @@ import (
"sort"
"strings"
"github.com/mitchellh/copystructure"
"github.com/hashicorp/consul/acl"
"github.com/hashicorp/consul/agent/proxycfg/internal/watch"
"github.com/hashicorp/consul/agent/structs"
@ -764,13 +762,8 @@ func (s *ConfigSnapshot) Valid() bool {
// Clone makes a deep copy of the snapshot we can send to other goroutines
// without worrying that they will racily read or mutate shared maps etc.
func (s *ConfigSnapshot) Clone() (*ConfigSnapshot, error) {
snapCopy, err := copystructure.Copy(s)
if err != nil {
return nil, err
}
snap := snapCopy.(*ConfigSnapshot)
func (s *ConfigSnapshot) Clone() *ConfigSnapshot {
snap := s.DeepCopy()
// nil these out as anything receiving one of these clones does not need them and should never "cancel" our watches
switch s.Kind {
@ -797,7 +790,7 @@ func (s *ConfigSnapshot) Clone() (*ConfigSnapshot, error) {
snap.IngressGateway.LeafCertWatchCancel = nil
}
return snap, nil
return snap
}
func (s *ConfigSnapshot) Leaf() *structs.IssuedCert {

@ -0,0 +1,52 @@
package proxycfg
import (
"context"
"regexp"
"testing"
"github.com/google/go-cmp/cmp"
"github.com/google/go-cmp/cmp/cmpopts"
fuzz "github.com/google/gofuzz"
"github.com/hashicorp/consul/proto/pbpeering"
)
func TestConfigSnapshot_Clone(t *testing.T) {
// ConfigSnapshot is a complex struct that (directly or indirectly) has a copy
// of most of the structs in the agent/structs package. It'd be easy to break
// the Clone method accidentally by changing one of those distant structs, so
// we test it by using a fuzzer to traverse the graph and fill every field and
// then compare the original to the copy.
f := fuzz.New()
f.NilChance(0)
f.NumElements(1, 3)
f.SkipFieldsWithPattern(regexp.MustCompile("^ServerSNIFn$"))
f.Funcs(
// Populate map[string]interface{} since gofuzz panics on these. We force them
// to be any rather than concrete types otherwise they won't compare equal when
// coming back out the other side.
func(m map[string]any, c fuzz.Continue) {
m[c.RandString()] = any(float64(c.RandUint64()))
m[c.RandString()] = any(c.RandString())
m[c.RandString()] = any([]any{c.RandString(), c.RandString()})
m[c.RandString()] = any(map[string]any{c.RandString(): c.RandString()})
},
func(*context.CancelFunc, fuzz.Continue) {},
)
snapshot := new(ConfigSnapshot)
f.Fuzz(snapshot)
clone := snapshot.Clone()
diff := cmp.Diff(snapshot, clone,
cmpopts.IgnoreUnexported(indexedTarget{}),
cmpopts.IgnoreUnexported(pbpeering.PeeringTrustBundle{}),
cmpopts.IgnoreTypes(context.CancelFunc(nil)),
)
if diff != "" {
t.Logf("Copied snaspshot is different to the original. You may need to re-run `make deep-copy`.\nDiff:\n%s", diff)
t.FailNow()
}
}

@ -10,7 +10,6 @@ import (
"time"
"github.com/hashicorp/go-hclog"
"github.com/mitchellh/copystructure"
cachetype "github.com/hashicorp/consul/agent/cache-types"
"github.com/hashicorp/consul/agent/structs"
@ -111,15 +110,8 @@ func copyProxyConfig(ns *structs.NodeService) (structs.ConnectProxyConfig, error
if ns == nil {
return structs.ConnectProxyConfig{}, nil
}
// Copy the config map
proxyCfgRaw, err := copystructure.Copy(ns.Proxy)
if err != nil {
return structs.ConnectProxyConfig{}, err
}
proxyCfg, ok := proxyCfgRaw.(structs.ConnectProxyConfig)
if !ok {
return structs.ConnectProxyConfig{}, errors.New("failed to copy proxy config")
}
proxyCfg := *(&ns.Proxy).DeepCopy()
// we can safely modify these since we just copied them
for idx := range proxyCfg.Upstreams {
@ -336,11 +328,7 @@ func (s *state) run(ctx context.Context, snap *ConfigSnapshot) {
coalesceTimer = nil
// Make a deep copy of snap so we don't mutate any of the embedded structs
// etc on future updates.
snapCopy, err := snap.Clone()
if err != nil {
s.logger.Error("Failed to copy config snapshot for proxy", "error", err)
continue
}
snapCopy := snap.Clone()
select {
// Try to send
@ -377,12 +365,7 @@ func (s *state) run(ctx context.Context, snap *ConfigSnapshot) {
}
// Make a deep copy of snap so we don't mutate any of the embedded structs
// etc on future updates.
snapCopy, err := snap.Clone()
if err != nil {
s.logger.Error("Failed to copy config snapshot for proxy", "error", err)
continue
}
replyCh <- snapCopy
replyCh <- snap.Clone()
// Skip rest of loop - there is nothing to send since nothing changed on
// this iteration

@ -0,0 +1,48 @@
#!/usr/bin/env bash
readonly PACKAGE_DIR="$(dirname "${BASH_SOURCE[0]}")"
cd $PACKAGE_DIR
# Uses: https://github.com/globusdigital/deep-copy
deep-copy \
-pointer-receiver \
-o ./structs.deepcopy.go \
-type CARoot \
-type CheckServiceNode \
-type CheckType \
-type CompiledDiscoveryChain \
-type ConnectProxyConfig \
-type DiscoveryFailover \
-type DiscoveryGraphNode \
-type DiscoveryResolver \
-type DiscoveryRoute \
-type DiscoverySplit \
-type ExposeConfig \
-type GatewayService \
-type GatewayServiceTLSConfig \
-type HTTPHeaderModifiers \
-type HashPolicy \
-type HealthCheck \
-type IndexedCARoots \
-type IngressListener \
-type Intention \
-type IntentionPermission \
-type LoadBalancer \
-type MeshConfigEntry \
-type MeshDirectionalTLSConfig \
-type MeshTLSConfig \
-type Node \
-type NodeService \
-type PeeringServiceMeta \
-type ServiceConfigEntry \
-type ServiceConfigResponse \
-type ServiceConnect \
-type ServiceDefinition \
-type ServiceResolverConfigEntry \
-type ServiceResolverFailover \
-type ServiceRoute \
-type ServiceRouteDestination \
-type ServiceRouteMatch \
-type Upstream \
-type UpstreamConfiguration \
./

@ -0,0 +1,838 @@
// generated by deep-copy -pointer-receiver -o ./structs.deepcopy.go -type CARoot -type CheckServiceNode -type CheckType -type CompiledDiscoveryChain -type ConnectProxyConfig -type DiscoveryFailover -type DiscoveryGraphNode -type DiscoveryResolver -type DiscoveryRoute -type DiscoverySplit -type ExposeConfig -type GatewayService -type GatewayServiceTLSConfig -type HTTPHeaderModifiers -type HashPolicy -type HealthCheck -type IndexedCARoots -type IngressListener -type Intention -type IntentionPermission -type LoadBalancer -type MeshConfigEntry -type MeshDirectionalTLSConfig -type MeshTLSConfig -type Node -type NodeService -type PeeringServiceMeta -type ServiceConfigEntry -type ServiceConfigResponse -type ServiceConnect -type ServiceDefinition -type ServiceResolverConfigEntry -type ServiceResolverFailover -type ServiceRoute -type ServiceRouteDestination -type ServiceRouteMatch -type Upstream -type UpstreamConfiguration ./; DO NOT EDIT.
package structs
import (
"github.com/hashicorp/consul/types"
)
// DeepCopy generates a deep copy of *CARoot
func (o *CARoot) DeepCopy() *CARoot {
var cp CARoot = *o
if o.IntermediateCerts != nil {
cp.IntermediateCerts = make([]string, len(o.IntermediateCerts))
copy(cp.IntermediateCerts, o.IntermediateCerts)
}
return &cp
}
// DeepCopy generates a deep copy of *CheckServiceNode
func (o *CheckServiceNode) DeepCopy() *CheckServiceNode {
var cp CheckServiceNode = *o
if o.Node != nil {
cp.Node = o.Node.DeepCopy()
}
if o.Service != nil {
cp.Service = o.Service.DeepCopy()
}
if o.Checks != nil {
cp.Checks = make([]*HealthCheck, len(o.Checks))
copy(cp.Checks, o.Checks)
for i2 := range o.Checks {
if o.Checks[i2] != nil {
cp.Checks[i2] = o.Checks[i2].DeepCopy()
}
}
}
return &cp
}
// DeepCopy generates a deep copy of *CheckType
func (o *CheckType) DeepCopy() *CheckType {
var cp CheckType = *o
if o.ScriptArgs != nil {
cp.ScriptArgs = make([]string, len(o.ScriptArgs))
copy(cp.ScriptArgs, o.ScriptArgs)
}
if o.Header != nil {
cp.Header = make(map[string][]string, len(o.Header))
for k2, v2 := range o.Header {
var cp_Header_v2 []string
if v2 != nil {
cp_Header_v2 = make([]string, len(v2))
copy(cp_Header_v2, v2)
}
cp.Header[k2] = cp_Header_v2
}
}
return &cp
}
// DeepCopy generates a deep copy of *CompiledDiscoveryChain
func (o *CompiledDiscoveryChain) DeepCopy() *CompiledDiscoveryChain {
var cp CompiledDiscoveryChain = *o
if o.ServiceMeta != nil {
cp.ServiceMeta = make(map[string]string, len(o.ServiceMeta))
for k2, v2 := range o.ServiceMeta {
cp.ServiceMeta[k2] = v2
}
}
if o.Nodes != nil {
cp.Nodes = make(map[string]*DiscoveryGraphNode, len(o.Nodes))
for k2, v2 := range o.Nodes {
var cp_Nodes_v2 *DiscoveryGraphNode
if v2 != nil {
cp_Nodes_v2 = v2.DeepCopy()
}
cp.Nodes[k2] = cp_Nodes_v2
}
}
if o.Targets != nil {
cp.Targets = make(map[string]*DiscoveryTarget, len(o.Targets))
for k2, v2 := range o.Targets {
var cp_Targets_v2 *DiscoveryTarget
if v2 != nil {
cp_Targets_v2 = new(DiscoveryTarget)
*cp_Targets_v2 = *v2
}
cp.Targets[k2] = cp_Targets_v2
}
}
return &cp
}
// DeepCopy generates a deep copy of *ConnectProxyConfig
func (o *ConnectProxyConfig) DeepCopy() *ConnectProxyConfig {
var cp ConnectProxyConfig = *o
if o.Config != nil {
cp.Config = make(map[string]interface{}, len(o.Config))
for k2, v2 := range o.Config {
cp.Config[k2] = v2
}
}
if o.Upstreams != nil {
cp.Upstreams = make([]Upstream, len(o.Upstreams))
copy(cp.Upstreams, o.Upstreams)
for i2 := range o.Upstreams {
{
retV := o.Upstreams[i2].DeepCopy()
cp.Upstreams[i2] = *retV
}
}
}
{
retV := o.Expose.DeepCopy()
cp.Expose = *retV
}
return &cp
}
// DeepCopy generates a deep copy of *DiscoveryFailover
func (o *DiscoveryFailover) DeepCopy() *DiscoveryFailover {
var cp DiscoveryFailover = *o
if o.Targets != nil {
cp.Targets = make([]string, len(o.Targets))
copy(cp.Targets, o.Targets)
}
return &cp
}
// DeepCopy generates a deep copy of *DiscoveryGraphNode
func (o *DiscoveryGraphNode) DeepCopy() *DiscoveryGraphNode {
var cp DiscoveryGraphNode = *o
if o.Routes != nil {
cp.Routes = make([]*DiscoveryRoute, len(o.Routes))
copy(cp.Routes, o.Routes)
for i2 := range o.Routes {
if o.Routes[i2] != nil {
cp.Routes[i2] = o.Routes[i2].DeepCopy()
}
}
}
if o.Splits != nil {
cp.Splits = make([]*DiscoverySplit, len(o.Splits))
copy(cp.Splits, o.Splits)
for i2 := range o.Splits {
if o.Splits[i2] != nil {
cp.Splits[i2] = o.Splits[i2].DeepCopy()
}
}
}
if o.Resolver != nil {
cp.Resolver = o.Resolver.DeepCopy()
}
if o.LoadBalancer != nil {
cp.LoadBalancer = o.LoadBalancer.DeepCopy()
}
return &cp
}
// DeepCopy generates a deep copy of *DiscoveryResolver
func (o *DiscoveryResolver) DeepCopy() *DiscoveryResolver {
var cp DiscoveryResolver = *o
if o.Failover != nil {
cp.Failover = o.Failover.DeepCopy()
}
return &cp
}
// DeepCopy generates a deep copy of *DiscoveryRoute
func (o *DiscoveryRoute) DeepCopy() *DiscoveryRoute {
var cp DiscoveryRoute = *o
if o.Definition != nil {
cp.Definition = o.Definition.DeepCopy()
}
return &cp
}
// DeepCopy generates a deep copy of *DiscoverySplit
func (o *DiscoverySplit) DeepCopy() *DiscoverySplit {
var cp DiscoverySplit = *o
if o.Definition != nil {
cp.Definition = new(ServiceSplit)
*cp.Definition = *o.Definition
if o.Definition.RequestHeaders != nil {
cp.Definition.RequestHeaders = o.Definition.RequestHeaders.DeepCopy()
}
if o.Definition.ResponseHeaders != nil {
cp.Definition.ResponseHeaders = o.Definition.ResponseHeaders.DeepCopy()
}
}
return &cp
}
// DeepCopy generates a deep copy of *ExposeConfig
func (o *ExposeConfig) DeepCopy() *ExposeConfig {
var cp ExposeConfig = *o
if o.Paths != nil {
cp.Paths = make([]ExposePath, len(o.Paths))
copy(cp.Paths, o.Paths)
}
return &cp
}
// DeepCopy generates a deep copy of *GatewayService
func (o *GatewayService) DeepCopy() *GatewayService {
var cp GatewayService = *o
if o.Hosts != nil {
cp.Hosts = make([]string, len(o.Hosts))
copy(cp.Hosts, o.Hosts)
}
return &cp
}
// DeepCopy generates a deep copy of *GatewayServiceTLSConfig
func (o *GatewayServiceTLSConfig) DeepCopy() *GatewayServiceTLSConfig {
var cp GatewayServiceTLSConfig = *o
if o.SDS != nil {
cp.SDS = new(GatewayTLSSDSConfig)
*cp.SDS = *o.SDS
}
return &cp
}
// DeepCopy generates a deep copy of *HTTPHeaderModifiers
func (o *HTTPHeaderModifiers) DeepCopy() *HTTPHeaderModifiers {
var cp HTTPHeaderModifiers = *o
if o.Add != nil {
cp.Add = make(map[string]string, len(o.Add))
for k2, v2 := range o.Add {
cp.Add[k2] = v2
}
}
if o.Set != nil {
cp.Set = make(map[string]string, len(o.Set))
for k2, v2 := range o.Set {
cp.Set[k2] = v2
}
}
if o.Remove != nil {
cp.Remove = make([]string, len(o.Remove))
copy(cp.Remove, o.Remove)
}
return &cp
}
// DeepCopy generates a deep copy of *HashPolicy
func (o *HashPolicy) DeepCopy() *HashPolicy {
var cp HashPolicy = *o
if o.CookieConfig != nil {
cp.CookieConfig = new(CookieConfig)
*cp.CookieConfig = *o.CookieConfig
}
return &cp
}
// DeepCopy generates a deep copy of *HealthCheck
func (o *HealthCheck) DeepCopy() *HealthCheck {
var cp HealthCheck = *o
if o.ServiceTags != nil {
cp.ServiceTags = make([]string, len(o.ServiceTags))
copy(cp.ServiceTags, o.ServiceTags)
}
if o.Definition.Header != nil {
cp.Definition.Header = make(map[string][]string, len(o.Definition.Header))
for k3, v3 := range o.Definition.Header {
var cp_Definition_Header_v3 []string
if v3 != nil {
cp_Definition_Header_v3 = make([]string, len(v3))
copy(cp_Definition_Header_v3, v3)
}
cp.Definition.Header[k3] = cp_Definition_Header_v3
}
}
if o.Definition.ScriptArgs != nil {
cp.Definition.ScriptArgs = make([]string, len(o.Definition.ScriptArgs))
copy(cp.Definition.ScriptArgs, o.Definition.ScriptArgs)
}
return &cp
}
// DeepCopy generates a deep copy of *IndexedCARoots
func (o *IndexedCARoots) DeepCopy() *IndexedCARoots {
var cp IndexedCARoots = *o
if o.Roots != nil {
cp.Roots = make([]*CARoot, len(o.Roots))
copy(cp.Roots, o.Roots)
for i2 := range o.Roots {
if o.Roots[i2] != nil {
cp.Roots[i2] = o.Roots[i2].DeepCopy()
}
}
}
return &cp
}
// DeepCopy generates a deep copy of *IngressListener
func (o *IngressListener) DeepCopy() *IngressListener {
var cp IngressListener = *o
if o.TLS != nil {
cp.TLS = new(GatewayTLSConfig)
*cp.TLS = *o.TLS
if o.TLS.SDS != nil {
cp.TLS.SDS = new(GatewayTLSSDSConfig)
*cp.TLS.SDS = *o.TLS.SDS
}
if o.TLS.CipherSuites != nil {
cp.TLS.CipherSuites = make([]types.TLSCipherSuite, len(o.TLS.CipherSuites))
copy(cp.TLS.CipherSuites, o.TLS.CipherSuites)
}
}
if o.Services != nil {
cp.Services = make([]IngressService, len(o.Services))
copy(cp.Services, o.Services)
for i2 := range o.Services {
if o.Services[i2].Hosts != nil {
cp.Services[i2].Hosts = make([]string, len(o.Services[i2].Hosts))
copy(cp.Services[i2].Hosts, o.Services[i2].Hosts)
}
if o.Services[i2].TLS != nil {
cp.Services[i2].TLS = o.Services[i2].TLS.DeepCopy()
}
if o.Services[i2].RequestHeaders != nil {
cp.Services[i2].RequestHeaders = o.Services[i2].RequestHeaders.DeepCopy()
}
if o.Services[i2].ResponseHeaders != nil {
cp.Services[i2].ResponseHeaders = o.Services[i2].ResponseHeaders.DeepCopy()
}
if o.Services[i2].Meta != nil {
cp.Services[i2].Meta = make(map[string]string, len(o.Services[i2].Meta))
for k4, v4 := range o.Services[i2].Meta {
cp.Services[i2].Meta[k4] = v4
}
}
}
}
return &cp
}
// DeepCopy generates a deep copy of *Intention
func (o *Intention) DeepCopy() *Intention {
var cp Intention = *o
if o.Permissions != nil {
cp.Permissions = make([]*IntentionPermission, len(o.Permissions))
copy(cp.Permissions, o.Permissions)
for i2 := range o.Permissions {
if o.Permissions[i2] != nil {
cp.Permissions[i2] = o.Permissions[i2].DeepCopy()
}
}
}
if o.Meta != nil {
cp.Meta = make(map[string]string, len(o.Meta))
for k2, v2 := range o.Meta {
cp.Meta[k2] = v2
}
}
if o.Hash != nil {
cp.Hash = make([]byte, len(o.Hash))
copy(cp.Hash, o.Hash)
}
return &cp
}
// DeepCopy generates a deep copy of *IntentionPermission
func (o *IntentionPermission) DeepCopy() *IntentionPermission {
var cp IntentionPermission = *o
if o.HTTP != nil {
cp.HTTP = new(IntentionHTTPPermission)
*cp.HTTP = *o.HTTP
if o.HTTP.Header != nil {
cp.HTTP.Header = make([]IntentionHTTPHeaderPermission, len(o.HTTP.Header))
copy(cp.HTTP.Header, o.HTTP.Header)
}
if o.HTTP.Methods != nil {
cp.HTTP.Methods = make([]string, len(o.HTTP.Methods))
copy(cp.HTTP.Methods, o.HTTP.Methods)
}
}
return &cp
}
// DeepCopy generates a deep copy of *LoadBalancer
func (o *LoadBalancer) DeepCopy() *LoadBalancer {
var cp LoadBalancer = *o
if o.RingHashConfig != nil {
cp.RingHashConfig = new(RingHashConfig)
*cp.RingHashConfig = *o.RingHashConfig
}
if o.LeastRequestConfig != nil {
cp.LeastRequestConfig = new(LeastRequestConfig)
*cp.LeastRequestConfig = *o.LeastRequestConfig
}
if o.HashPolicies != nil {
cp.HashPolicies = make([]HashPolicy, len(o.HashPolicies))
copy(cp.HashPolicies, o.HashPolicies)
for i2 := range o.HashPolicies {
{
retV := o.HashPolicies[i2].DeepCopy()
cp.HashPolicies[i2] = *retV
}
}
}
return &cp
}
// DeepCopy generates a deep copy of *MeshConfigEntry
func (o *MeshConfigEntry) DeepCopy() *MeshConfigEntry {
var cp MeshConfigEntry = *o
if o.TLS != nil {
cp.TLS = o.TLS.DeepCopy()
}
if o.HTTP != nil {
cp.HTTP = new(MeshHTTPConfig)
*cp.HTTP = *o.HTTP
}
if o.Peering != nil {
cp.Peering = new(PeeringMeshConfig)
*cp.Peering = *o.Peering
}
if o.Meta != nil {
cp.Meta = make(map[string]string, len(o.Meta))
for k2, v2 := range o.Meta {
cp.Meta[k2] = v2
}
}
return &cp
}
// DeepCopy generates a deep copy of *MeshDirectionalTLSConfig
func (o *MeshDirectionalTLSConfig) DeepCopy() *MeshDirectionalTLSConfig {
var cp MeshDirectionalTLSConfig = *o
if o.CipherSuites != nil {
cp.CipherSuites = make([]types.TLSCipherSuite, len(o.CipherSuites))
copy(cp.CipherSuites, o.CipherSuites)
}
return &cp
}
// DeepCopy generates a deep copy of *MeshTLSConfig
func (o *MeshTLSConfig) DeepCopy() *MeshTLSConfig {
var cp MeshTLSConfig = *o
if o.Incoming != nil {
cp.Incoming = o.Incoming.DeepCopy()
}
if o.Outgoing != nil {
cp.Outgoing = o.Outgoing.DeepCopy()
}
return &cp
}
// DeepCopy generates a deep copy of *Node
func (o *Node) DeepCopy() *Node {
var cp Node = *o
if o.TaggedAddresses != nil {
cp.TaggedAddresses = make(map[string]string, len(o.TaggedAddresses))
for k2, v2 := range o.TaggedAddresses {
cp.TaggedAddresses[k2] = v2
}
}
if o.Meta != nil {
cp.Meta = make(map[string]string, len(o.Meta))
for k2, v2 := range o.Meta {
cp.Meta[k2] = v2
}
}
return &cp
}
// DeepCopy generates a deep copy of *NodeService
func (o *NodeService) DeepCopy() *NodeService {
var cp NodeService = *o
if o.Tags != nil {
cp.Tags = make([]string, len(o.Tags))
copy(cp.Tags, o.Tags)
}
if o.TaggedAddresses != nil {
cp.TaggedAddresses = make(map[string]ServiceAddress, len(o.TaggedAddresses))
for k2, v2 := range o.TaggedAddresses {
cp.TaggedAddresses[k2] = v2
}
}
if o.Meta != nil {
cp.Meta = make(map[string]string, len(o.Meta))
for k2, v2 := range o.Meta {
cp.Meta[k2] = v2
}
}
if o.Weights != nil {
cp.Weights = new(Weights)
*cp.Weights = *o.Weights
}
{
retV := o.Proxy.DeepCopy()
cp.Proxy = *retV
}
{
retV := o.Connect.DeepCopy()
cp.Connect = *retV
}
return &cp
}
// DeepCopy generates a deep copy of *PeeringServiceMeta
func (o *PeeringServiceMeta) DeepCopy() *PeeringServiceMeta {
var cp PeeringServiceMeta = *o
if o.SNI != nil {
cp.SNI = make([]string, len(o.SNI))
copy(cp.SNI, o.SNI)
}
if o.SpiffeID != nil {
cp.SpiffeID = make([]string, len(o.SpiffeID))
copy(cp.SpiffeID, o.SpiffeID)
}
return &cp
}
// DeepCopy generates a deep copy of *ServiceConfigEntry
func (o *ServiceConfigEntry) DeepCopy() *ServiceConfigEntry {
var cp ServiceConfigEntry = *o
{
retV := o.Expose.DeepCopy()
cp.Expose = *retV
}
if o.UpstreamConfig != nil {
cp.UpstreamConfig = o.UpstreamConfig.DeepCopy()
}
if o.Destination != nil {
cp.Destination = new(DestinationConfig)
*cp.Destination = *o.Destination
if o.Destination.Addresses != nil {
cp.Destination.Addresses = make([]string, len(o.Destination.Addresses))
copy(cp.Destination.Addresses, o.Destination.Addresses)
}
}
if o.Meta != nil {
cp.Meta = make(map[string]string, len(o.Meta))
for k2, v2 := range o.Meta {
cp.Meta[k2] = v2
}
}
return &cp
}
// DeepCopy generates a deep copy of *ServiceConfigResponse
func (o *ServiceConfigResponse) DeepCopy() *ServiceConfigResponse {
var cp ServiceConfigResponse = *o
if o.ProxyConfig != nil {
cp.ProxyConfig = make(map[string]interface{}, len(o.ProxyConfig))
for k2, v2 := range o.ProxyConfig {
cp.ProxyConfig[k2] = v2
}
}
if o.UpstreamConfigs != nil {
cp.UpstreamConfigs = make(map[string]map[string]interface{}, len(o.UpstreamConfigs))
for k2, v2 := range o.UpstreamConfigs {
var cp_UpstreamConfigs_v2 map[string]interface{}
if v2 != nil {
cp_UpstreamConfigs_v2 = make(map[string]interface{}, len(v2))
for k3, v3 := range v2 {
cp_UpstreamConfigs_v2[k3] = v3
}
}
cp.UpstreamConfigs[k2] = cp_UpstreamConfigs_v2
}
}
if o.UpstreamIDConfigs != nil {
cp.UpstreamIDConfigs = make([]OpaqueUpstreamConfig, len(o.UpstreamIDConfigs))
copy(cp.UpstreamIDConfigs, o.UpstreamIDConfigs)
for i2 := range o.UpstreamIDConfigs {
if o.UpstreamIDConfigs[i2].Config != nil {
cp.UpstreamIDConfigs[i2].Config = make(map[string]interface{}, len(o.UpstreamIDConfigs[i2].Config))
for k4, v4 := range o.UpstreamIDConfigs[i2].Config {
cp.UpstreamIDConfigs[i2].Config[k4] = v4
}
}
}
}
{
retV := o.Expose.DeepCopy()
cp.Expose = *retV
}
if o.Destination.Addresses != nil {
cp.Destination.Addresses = make([]string, len(o.Destination.Addresses))
copy(cp.Destination.Addresses, o.Destination.Addresses)
}
if o.Meta != nil {
cp.Meta = make(map[string]string, len(o.Meta))
for k2, v2 := range o.Meta {
cp.Meta[k2] = v2
}
}
return &cp
}
// DeepCopy generates a deep copy of *ServiceConnect
func (o *ServiceConnect) DeepCopy() *ServiceConnect {
var cp ServiceConnect = *o
if o.SidecarService != nil {
cp.SidecarService = o.SidecarService.DeepCopy()
}
if o.PeerMeta != nil {
cp.PeerMeta = o.PeerMeta.DeepCopy()
}
return &cp
}
// DeepCopy generates a deep copy of *ServiceDefinition
func (o *ServiceDefinition) DeepCopy() *ServiceDefinition {
var cp ServiceDefinition = *o
if o.Tags != nil {
cp.Tags = make([]string, len(o.Tags))
copy(cp.Tags, o.Tags)
}
if o.TaggedAddresses != nil {
cp.TaggedAddresses = make(map[string]ServiceAddress, len(o.TaggedAddresses))
for k2, v2 := range o.TaggedAddresses {
cp.TaggedAddresses[k2] = v2
}
}
if o.Meta != nil {
cp.Meta = make(map[string]string, len(o.Meta))
for k2, v2 := range o.Meta {
cp.Meta[k2] = v2
}
}
{
retV := o.Check.DeepCopy()
cp.Check = *retV
}
if o.Checks != nil {
cp.Checks = make([]*CheckType, len(o.Checks))
copy(cp.Checks, o.Checks)
for i2 := range o.Checks {
if o.Checks[i2] != nil {
cp.Checks[i2] = o.Checks[i2].DeepCopy()
}
}
}
if o.Weights != nil {
cp.Weights = new(Weights)
*cp.Weights = *o.Weights
}
if o.Proxy != nil {
cp.Proxy = o.Proxy.DeepCopy()
}
if o.Connect != nil {
cp.Connect = o.Connect.DeepCopy()
}
return &cp
}
// DeepCopy generates a deep copy of *ServiceResolverConfigEntry
func (o *ServiceResolverConfigEntry) DeepCopy() *ServiceResolverConfigEntry {
var cp ServiceResolverConfigEntry = *o
if o.Subsets != nil {
cp.Subsets = make(map[string]ServiceResolverSubset, len(o.Subsets))
for k2, v2 := range o.Subsets {
cp.Subsets[k2] = v2
}
}
if o.Redirect != nil {
cp.Redirect = new(ServiceResolverRedirect)
*cp.Redirect = *o.Redirect
}
if o.Failover != nil {
cp.Failover = make(map[string]ServiceResolverFailover, len(o.Failover))
for k2, v2 := range o.Failover {
var cp_Failover_v2 ServiceResolverFailover
{
retV := v2.DeepCopy()
cp_Failover_v2 = *retV
}
cp.Failover[k2] = cp_Failover_v2
}
}
if o.LoadBalancer != nil {
cp.LoadBalancer = o.LoadBalancer.DeepCopy()
}
if o.Meta != nil {
cp.Meta = make(map[string]string, len(o.Meta))
for k2, v2 := range o.Meta {
cp.Meta[k2] = v2
}
}
return &cp
}
// DeepCopy generates a deep copy of *ServiceResolverFailover
func (o *ServiceResolverFailover) DeepCopy() *ServiceResolverFailover {
var cp ServiceResolverFailover = *o
if o.Datacenters != nil {
cp.Datacenters = make([]string, len(o.Datacenters))
copy(cp.Datacenters, o.Datacenters)
}
if o.Targets != nil {
cp.Targets = make([]ServiceResolverFailoverTarget, len(o.Targets))
copy(cp.Targets, o.Targets)
}
return &cp
}
// DeepCopy generates a deep copy of *ServiceRoute
func (o *ServiceRoute) DeepCopy() *ServiceRoute {
var cp ServiceRoute = *o
if o.Match != nil {
cp.Match = o.Match.DeepCopy()
}
if o.Destination != nil {
cp.Destination = o.Destination.DeepCopy()
}
return &cp
}
// DeepCopy generates a deep copy of *ServiceRouteDestination
func (o *ServiceRouteDestination) DeepCopy() *ServiceRouteDestination {
var cp ServiceRouteDestination = *o
if o.RetryOn != nil {
cp.RetryOn = make([]string, len(o.RetryOn))
copy(cp.RetryOn, o.RetryOn)
}
if o.RetryOnStatusCodes != nil {
cp.RetryOnStatusCodes = make([]uint32, len(o.RetryOnStatusCodes))
copy(cp.RetryOnStatusCodes, o.RetryOnStatusCodes)
}
if o.RequestHeaders != nil {
cp.RequestHeaders = o.RequestHeaders.DeepCopy()
}
if o.ResponseHeaders != nil {
cp.ResponseHeaders = o.ResponseHeaders.DeepCopy()
}
return &cp
}
// DeepCopy generates a deep copy of *ServiceRouteMatch
func (o *ServiceRouteMatch) DeepCopy() *ServiceRouteMatch {
var cp ServiceRouteMatch = *o
if o.HTTP != nil {
cp.HTTP = new(ServiceRouteHTTPMatch)
*cp.HTTP = *o.HTTP
if o.HTTP.Header != nil {
cp.HTTP.Header = make([]ServiceRouteHTTPMatchHeader, len(o.HTTP.Header))
copy(cp.HTTP.Header, o.HTTP.Header)
}
if o.HTTP.QueryParam != nil {
cp.HTTP.QueryParam = make([]ServiceRouteHTTPMatchQueryParam, len(o.HTTP.QueryParam))
copy(cp.HTTP.QueryParam, o.HTTP.QueryParam)
}
if o.HTTP.Methods != nil {
cp.HTTP.Methods = make([]string, len(o.HTTP.Methods))
copy(cp.HTTP.Methods, o.HTTP.Methods)
}
}
return &cp
}
// DeepCopy generates a deep copy of *Upstream
func (o *Upstream) DeepCopy() *Upstream {
var cp Upstream = *o
if o.Config != nil {
cp.Config = make(map[string]interface{}, len(o.Config))
for k2, v2 := range o.Config {
cp.Config[k2] = v2
}
}
if o.IngressHosts != nil {
cp.IngressHosts = make([]string, len(o.IngressHosts))
copy(cp.IngressHosts, o.IngressHosts)
}
return &cp
}
// DeepCopy generates a deep copy of *UpstreamConfiguration
func (o *UpstreamConfiguration) DeepCopy() *UpstreamConfiguration {
var cp UpstreamConfiguration = *o
if o.Overrides != nil {
cp.Overrides = make([]*UpstreamConfig, len(o.Overrides))
copy(cp.Overrides, o.Overrides)
for i2 := range o.Overrides {
if o.Overrides[i2] != nil {
cp.Overrides[i2] = new(UpstreamConfig)
*cp.Overrides[i2] = *o.Overrides[i2]
if o.Overrides[i2].Limits != nil {
cp.Overrides[i2].Limits = new(UpstreamLimits)
*cp.Overrides[i2].Limits = *o.Overrides[i2].Limits
if o.Overrides[i2].Limits.MaxConnections != nil {
cp.Overrides[i2].Limits.MaxConnections = new(int)
*cp.Overrides[i2].Limits.MaxConnections = *o.Overrides[i2].Limits.MaxConnections
}
if o.Overrides[i2].Limits.MaxPendingRequests != nil {
cp.Overrides[i2].Limits.MaxPendingRequests = new(int)
*cp.Overrides[i2].Limits.MaxPendingRequests = *o.Overrides[i2].Limits.MaxPendingRequests
}
if o.Overrides[i2].Limits.MaxConcurrentRequests != nil {
cp.Overrides[i2].Limits.MaxConcurrentRequests = new(int)
*cp.Overrides[i2].Limits.MaxConcurrentRequests = *o.Overrides[i2].Limits.MaxConcurrentRequests
}
}
if o.Overrides[i2].PassiveHealthCheck != nil {
cp.Overrides[i2].PassiveHealthCheck = new(PassiveHealthCheck)
*cp.Overrides[i2].PassiveHealthCheck = *o.Overrides[i2].PassiveHealthCheck
if o.Overrides[i2].PassiveHealthCheck.EnforcingConsecutive5xx != nil {
cp.Overrides[i2].PassiveHealthCheck.EnforcingConsecutive5xx = new(uint32)
*cp.Overrides[i2].PassiveHealthCheck.EnforcingConsecutive5xx = *o.Overrides[i2].PassiveHealthCheck.EnforcingConsecutive5xx
}
}
}
}
}
if o.Defaults != nil {
cp.Defaults = new(UpstreamConfig)
*cp.Defaults = *o.Defaults
if o.Defaults.Limits != nil {
cp.Defaults.Limits = new(UpstreamLimits)
*cp.Defaults.Limits = *o.Defaults.Limits
if o.Defaults.Limits.MaxConnections != nil {
cp.Defaults.Limits.MaxConnections = new(int)
*cp.Defaults.Limits.MaxConnections = *o.Defaults.Limits.MaxConnections
}
if o.Defaults.Limits.MaxPendingRequests != nil {
cp.Defaults.Limits.MaxPendingRequests = new(int)
*cp.Defaults.Limits.MaxPendingRequests = *o.Defaults.Limits.MaxPendingRequests
}
if o.Defaults.Limits.MaxConcurrentRequests != nil {
cp.Defaults.Limits.MaxConcurrentRequests = new(int)
*cp.Defaults.Limits.MaxConcurrentRequests = *o.Defaults.Limits.MaxConcurrentRequests
}
}
if o.Defaults.PassiveHealthCheck != nil {
cp.Defaults.PassiveHealthCheck = new(PassiveHealthCheck)
*cp.Defaults.PassiveHealthCheck = *o.Defaults.PassiveHealthCheck
if o.Defaults.PassiveHealthCheck.EnforcingConsecutive5xx != nil {
cp.Defaults.PassiveHealthCheck.EnforcingConsecutive5xx = new(uint32)
*cp.Defaults.PassiveHealthCheck.EnforcingConsecutive5xx = *o.Defaults.PassiveHealthCheck.EnforcingConsecutive5xx
}
}
}
return &cp
}

@ -2010,6 +2010,14 @@ func (csn *CheckServiceNode) CanRead(authz acl.Authorizer) acl.EnforcementDecisi
type CheckServiceNodes []CheckServiceNode
func (csns CheckServiceNodes) DeepCopy() CheckServiceNodes {
dup := make(CheckServiceNodes, len(csns))
for idx, v := range csns {
dup[idx] = *v.DeepCopy()
}
return dup
}
// Shuffle does an in-place random shuffle using the Fisher-Yates algorithm.
func (nodes CheckServiceNodes) Shuffle() {
for i := len(nodes) - 1; i > 0; i-- {

@ -21,6 +21,7 @@ Description:
Options:
-protobuf Just install tools for protobuf.
-lint Just install tools for linting.
-codegen Just install tools for codegen.
-h | --help Print this help text.
EOF
}
@ -43,6 +44,10 @@ function main {
lint_install
return 0
;;
-codegen )
codegen_install
return 0
;;
-h | --help )
usage
return 0
@ -135,10 +140,22 @@ function lint_install {
'github.com/golangci/golangci-lint/cmd/golangci-lint'
}
function codegen_install {
local deep_copy_version
deep_copy_version="$(make --no-print-directory print-DEEP_COPY_VERSION)"
install_versioned_tool \
'deep-copy' \
'github.com/globusdigital/deep-copy' \
"${deep_copy_version}" \
'github.com/globusdigital/deep-copy'
}
function tools_install {
lint_install
proto_tools_install
codegen_install
return 0
}

@ -0,0 +1,11 @@
#!/usr/bin/env bash
readonly PACKAGE_DIR="$(dirname "${BASH_SOURCE[0]}")"
cd $PACKAGE_DIR
# Uses: https://github.com/globusdigital/deep-copy
deep-copy -pointer-receiver \
-type PeeringTrustBundle \
-o ./peering.deepcopy.go \
./

@ -0,0 +1,17 @@
// generated by deep-copy -pointer-receiver -type PeeringTrustBundle -o ./peering.deepcopy.go ./; DO NOT EDIT.
package pbpeering
// DeepCopy generates a deep copy of *PeeringTrustBundle
func (o *PeeringTrustBundle) DeepCopy() *PeeringTrustBundle {
var cp PeeringTrustBundle = *o
if o.unknownFields != nil {
cp.unknownFields = make([]byte, len(o.unknownFields))
copy(cp.unknownFields, o.unknownFields)
}
if o.RootPEMs != nil {
cp.RootPEMs = make([]string, len(o.RootPEMs))
copy(cp.RootPEMs, o.RootPEMs)
}
return &cp
}
Loading…
Cancel
Save