consul/agent/proxycfg/snapshot_test.go
Thomas Eckert e81a0c2855
API Gateway to Ingress Gateway Snapshot Translation and Routes to Virtual Routers and Splitters (#16127)
* Stub proxycfg handler for API gateway

* Add Service Kind constants/handling for API Gateway

* Begin stubbing for SDS

* Add new Secret type to xDS order of operations

* Continue stubbing of SDS

* Iterate on proxycfg handler for API gateway

* Handle BoundAPIGateway config entry subscription in proxycfg-glue

* Add API gateway to config snapshot validation

* Add API gateway to config snapshot clone, leaf, etc.

* Subscribe to bound route + cert config entries on bound-api-gateway

* Track routes + certs on API gateway config snapshot

* Generate DeepCopy() for types used in watch.Map

* Watch all active references on api-gateway, unwatch inactive

* Track loading of initial bound-api-gateway config entry

* Use proper proto package for SDS mapping

* Use ResourceReference instead of ServiceName, collect resources

* Fix typo, add + remove TODOs

* Watch discovery chains for TCPRoute

* Add TODO for updating gateway services for api-gateway

* make proto

* Regenerate deep-copy for proxycfg

* Set datacenter on upstream ID from query source

* Watch discovery chains for http-route service backends

* Add ServiceName getter to HTTP+TCP Service structs

* Clean up unwatched discovery chains on API Gateway

* Implement watch for ingress leaf certificate

* Collect upstreams on http-route + tcp-route updates

* Remove unused GatewayServices update handler

* Remove unnecessary gateway services logic for API Gateway

* Remove outdate TODO

* Use .ToIngress where appropriate, including TODO for cleaning up

* Cancel before returning error

* Remove GatewayServices subscription

* Add godoc for handlerAPIGateway functions

* Update terminology from Connect => Consul Service Mesh

Consistent with terminology changes in https://github.com/hashicorp/consul/pull/12690

* Add missing TODO

* Remove duplicate switch case

* Rerun deep-copy generator

* Use correct property on config snapshot

* Remove unnecessary leaf cert watch

* Clean up based on code review feedback

* Note handler properties that are initialized but set elsewhere

* Add TODO for moving helper func into structs pkg

* Update generated DeepCopy code

* gofmt

* Begin stubbing for SDS

* Start adding tests

* Remove second BoundAPIGateway case in glue

* TO BE PICKED: fix formatting of str

* WIP

* Fix merge conflict

* Implement HTTP Route to Discovery Chain config entries

* Stub out function to create discovery chain

* Add discovery chain merging code (#16131)

* Test adding TCP and HTTP routes

* Add some tests for the synthesizer

* Run go mod tidy

* Pairing with N8

* Run deep copy

* Clean up GatewayChainSynthesizer

* Fix missing assignment of BoundAPIGateway topic

* Separate out synthesizeChains and toIngressTLS

* Fix build errors

* Ensure synthesizer skips non-matching routes by protocol

* Rebase on N8s work

* Generate DeepCopy() for API gateway listener types

* Improve variable name

* Regenerate DeepCopy() code

* Fix linting issue

* fix protobuf import

* Fix more merge conflict errors

* Fix synthesize test

* Run deep copy

* Add URLRewrite to proto

* Update agent/consul/discoverychain/gateway_tcproute.go

Co-authored-by: Nathan Coleman <nathan.coleman@hashicorp.com>

* Remove APIGatewayConfigEntry that was extra

* Error out if route kind is unknown

* Fix formatting errors in proto

---------

Co-authored-by: Nathan Coleman <nathan.coleman@hashicorp.com>
Co-authored-by: Andrew Stucki <andrew.stucki@hashicorp.com>
2023-02-09 17:58:55 +00:00

89 lines
2.9 KiB
Go

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/agent/proxycfg/internal/watch"
"github.com/hashicorp/consul/agent/structs"
"github.com/hashicorp/consul/proto/pbpeering"
"github.com/stretchr/testify/require"
)
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()
}
}
func TestAPIGatewaySnapshotToIngressGatewaySnapshot(t *testing.T) {
cases := map[string]struct {
apiGatewaySnapshot *configSnapshotAPIGateway
expected configSnapshotIngressGateway
}{
"default": {
apiGatewaySnapshot: &configSnapshotAPIGateway{
Listeners: map[string]structs.APIGatewayListener{},
},
expected: configSnapshotIngressGateway{
GatewayConfigLoaded: true,
ConfigSnapshotUpstreams: ConfigSnapshotUpstreams{
PeerUpstreamEndpoints: watch.NewMap[UpstreamID, structs.CheckServiceNodes](),
WatchedLocalGWEndpoints: watch.NewMap[string, structs.CheckServiceNodes](),
UpstreamPeerTrustBundles: watch.NewMap[string, *pbpeering.PeeringTrustBundle](),
DiscoveryChain: map[UpstreamID]*structs.CompiledDiscoveryChain{},
},
Listeners: map[IngressListenerKey]structs.IngressListener{},
Defaults: structs.IngressServiceConfig{},
},
},
}
for name, tc := range cases {
t.Run(name, func(t *testing.T) {
actual, err := tc.apiGatewaySnapshot.ToIngress("dc1")
require.NoError(t, err)
require.Equal(t, tc.expected, actual)
})
}
}