From 50b26aa56a0f77acfb59690692bb66ab6c679a36 Mon Sep 17 00:00:00 2001 From: "R.B. Boyer" <4903+rboyer@users.noreply.github.com> Date: Tue, 21 May 2024 14:52:19 -0500 Subject: [PATCH] deployer: remove catalog/mesh v2 support (#21194) - Low level plumbing for resources is still retained for now. - Retain "Workload" terminology over "Service". - Revert "Destination" terminology back to "Upstream". - Remove TPROXY support as it only worked for v2. --- test-integ/README.md | 51 +- test-integ/connect/snapshot_test.go | 8 +- .../peering_commontopo/ac1_basic_test.go | 10 +- .../ac2_disco_chain_test.go | 15 +- .../ac3_service_defaults_upstream_test.go | 18 +- .../ac4_proxy_defaults_test.go | 20 +- .../peering_commontopo/ac6_failovers_test.go | 11 +- .../ac7_1_rotate_gw_test.go | 9 +- .../ac7_2_rotate_leader_test.go | 13 +- test-integ/peering_commontopo/commontopo.go | 10 +- test-integ/topoutil/asserter.go | 85 +- test-integ/topoutil/asserter_blankspace.go | 58 +- test-integ/topoutil/fixtures.go | 8 - test-integ/topoutil/naming_shim.go | 19 +- test-integ/upgrade/basic/common.go | 6 +- .../upgrade/l7_traffic_management/common.go | 13 +- .../l7_traffic_management/resolver_test.go | 8 +- testing/deployer/README.md | 24 +- testing/deployer/sprawl/acl_rules.go | 8 - testing/deployer/sprawl/boot.go | 17 +- testing/deployer/sprawl/catalog.go | 380 +----- testing/deployer/sprawl/details.go | 23 +- .../deployer/sprawl/internal/build/docker.go | 2 +- .../deployer/sprawl/internal/tfgen/agent.go | 13 +- testing/deployer/sprawl/internal/tfgen/dns.go | 33 - testing/deployer/sprawl/internal/tfgen/gen.go | 3 - .../deployer/sprawl/internal/tfgen/nodes.go | 8 +- .../templates/container-app-dataplane.tf.tmpl | 19 - .../deployer/sprawl/sprawltest/test_test.go | 166 +-- testing/deployer/topology/compile.go | 314 +---- testing/deployer/topology/compile_test.go | 1140 ++--------------- testing/deployer/topology/naming_shim.go | 4 +- testing/deployer/topology/relationships.go | 50 +- testing/deployer/topology/topology.go | 286 +---- 34 files changed, 398 insertions(+), 2454 deletions(-) diff --git a/test-integ/README.md b/test-integ/README.md index 8955d0556d..048e377aeb 100644 --- a/test-integ/README.md +++ b/test-integ/README.md @@ -25,7 +25,7 @@ You can run the entire set of deployer integration tests using: You can also run them one by one if you like: - go test ./catalogv2 -run TestBasicL4ExplicitDestinations -v + go test ./connect/ -run Test_Snapshot_Restore_Agentless -v You can have the logs stream unbuffered directly to your terminal which can help diagnose stuck tests that would otherwise need to fully timeout before the @@ -65,26 +65,18 @@ These are comprised of 4 main parts: - **Nodes**: A "box with ip address(es)". This should feel a bit like a VM or a Kubernetes Pod as an enclosing entity. - - **Workloads**: The list of service instances (v1) or workloads - (v2) that will execute on the given node. v2 Services will - be implied by similarly named workloads here unless opted - out. This helps define a v1-compatible topology and - repurpose it for v2 without reworking it. + - **Workloads**: The list of service instances that will execute on the given node. - - **Services** (v2): v2 Service definitions to define explicitly, in addition - to the inferred ones. + - **InitialConfigEntries**: Config entries that should be created as + part of the fixture and that make sense to + include as part of the test definition, rather + than something created during the test assertion + phase. - - **InitialConfigEntries** (v1): Config entries that should be created as - part of the fixture and that make sense to - include as part of the test definition, - rather than something created during the - test assertion phase. - - - **InitialResources** (v2): v2 Resources that should be created as part of - the fixture and that make sense to include as - part of the test definition, rather than - something created during the test assertion - phase. + - **InitialResources**: Resources that should be created as part of + the fixture and that make sense to include as part of + the test definition, rather than something created + during the test assertion phase. - **Peerings**: The peering relationships between Clusters to establish. @@ -102,15 +94,13 @@ a variety of axes: - agentful (clients) vs agentless (dataplane) - tenancies (partitions, namespaces) - locally or across a peering -- catalog v1 or v2 object model Since the topology is just a declarative struct, a test author could rewrite -any one of these attributes with a single field (such as `Node.Kind` or -`Node.Version`) and cause the identical test to run against the other -configuration. With the addition of a few `if enterprise {}` blocks and `for` -loops, a test author could easily write one test of a behavior and execute it -to cover agentless, agentful, non-default tenancy, and v1/v2 in a few extra -lines of code. +any one of these attributes with a single field (such as `Node.Kind`) and cause +the identical test to run against the other configuration. With the addition of +a few `if enterprise {}` blocks and `for` loops, a test author could easily +write one test of a behavior and execute it to cover agentless, agentful, and +non-default tenancy in a few extra lines of code. #### Non-optional security settings @@ -197,12 +187,3 @@ and Envoy that you can create in your test: asserter := topoutil.NewAsserter(sp) asserter.UpstreamEndpointStatus(t, svc, clusterPrefix+".", "HEALTHY", 1) - -## Examples - -- `catalogv2` - - [Explicit L4 destinations](./catalogv2/explicit_destinations_test.go) - - [Implicit L4 destinations](./catalogv2/implicit_destinations_test.go) - - [Explicit L7 destinations with traffic splits](./catalogv2/explicit_destinations_l7_test.go) -- [`peering_commontopo`](./peering_commontopo) - - A variety of extensive v1 Peering tests. diff --git a/test-integ/connect/snapshot_test.go b/test-integ/connect/snapshot_test.go index 5a7a4a342c..423fa25340 100644 --- a/test-integ/connect/snapshot_test.go +++ b/test-integ/connect/snapshot_test.go @@ -27,7 +27,7 @@ import ( // 1. The test spins up a one-server cluster with static-server and static-client. // 2. A snapshot is taken and the cluster is restored from the snapshot // 3. A new static-server replaces the old one -// 4. At the end, we assert the static-client's destination is updated with the +// 4. At the end, we assert the static-client's upstream is updated with the // new static-server func Test_Snapshot_Restore_Agentless(t *testing.T) { t.Parallel() @@ -89,7 +89,7 @@ func Test_Snapshot_Restore_Agentless(t *testing.T) { "-http-port", "8080", "-redirect-port", "-disabled", }, - Destinations: []*topology.Destination{ + Upstreams: []*topology.Upstream{ { ID: staticServerSID, LocalPort: 5000, @@ -153,7 +153,7 @@ func Test_Snapshot_Restore_Agentless(t *testing.T) { topology.NewNodeID("dc1-client2", "default"), staticClientSID, ) - asserter.FortioFetch2HeaderEcho(t, staticClient, &topology.Destination{ + asserter.FortioFetch2HeaderEcho(t, staticClient, &topology.Upstream{ ID: staticServerSID, LocalPort: 5000, }) @@ -182,7 +182,7 @@ func Test_Snapshot_Restore_Agentless(t *testing.T) { require.NoError(t, sp.Relaunch(cfg)) // Ensure the static-client connected to the new static-server - asserter.FortioFetch2HeaderEcho(t, staticClient, &topology.Destination{ + asserter.FortioFetch2HeaderEcho(t, staticClient, &topology.Upstream{ ID: staticServerSID, LocalPort: 5000, }) diff --git a/test-integ/peering_commontopo/ac1_basic_test.go b/test-integ/peering_commontopo/ac1_basic_test.go index e104288c1f..c09bd3d537 100644 --- a/test-integ/peering_commontopo/ac1_basic_test.go +++ b/test-integ/peering_commontopo/ac1_basic_test.go @@ -30,8 +30,8 @@ type ac1BasicSuite struct { sidClientHTTP topology.ID nodeClientHTTP topology.NodeID - upstreamHTTP *topology.Destination - upstreamTCP *topology.Destination + upstreamHTTP *topology.Upstream + upstreamTCP *topology.Upstream } var ac1BasicSuites []sharedTopoSuite = []sharedTopoSuite{ @@ -65,7 +65,7 @@ func (s *ac1BasicSuite) setup(t *testing.T, ct *commonTopo) { Name: prefix + "server-http", Partition: partition, } - upstreamHTTP := &topology.Destination{ + upstreamHTTP := &topology.Upstream{ ID: topology.ID{ Name: httpServerSID.Name, Partition: partition, @@ -73,7 +73,7 @@ func (s *ac1BasicSuite) setup(t *testing.T, ct *commonTopo) { LocalPort: 5001, Peer: peer, } - upstreamTCP := &topology.Destination{ + upstreamTCP := &topology.Upstream{ ID: topology.ID{ Name: tcpServerSID.Name, Partition: partition, @@ -93,7 +93,7 @@ func (s *ac1BasicSuite) setup(t *testing.T, ct *commonTopo) { clu.Datacenter, sid, func(s *topology.Workload) { - s.Destinations = []*topology.Destination{ + s.Upstreams = []*topology.Upstream{ upstreamTCP, upstreamHTTP, } diff --git a/test-integ/peering_commontopo/ac2_disco_chain_test.go b/test-integ/peering_commontopo/ac2_disco_chain_test.go index ab85b7ffdb..0c0f05ae45 100644 --- a/test-integ/peering_commontopo/ac2_disco_chain_test.go +++ b/test-integ/peering_commontopo/ac2_disco_chain_test.go @@ -7,9 +7,10 @@ import ( "fmt" "testing" + "github.com/stretchr/testify/require" + "github.com/hashicorp/consul/api" "github.com/hashicorp/consul/testing/deployer/topology" - "github.com/stretchr/testify/require" ) type ac2DiscoChainSuite struct { @@ -84,7 +85,7 @@ func (s *ac2DiscoChainSuite) setup(t *testing.T, ct *commonTopo) { ct.AddServiceNode(clu, serviceExt{Workload: server}) // Define server as upstream for client - upstream := &topology.Destination{ + upstream := &topology.Upstream{ ID: topology.ID{ Name: server.ID.Name, Partition: partition, // TODO: iterate over all possible partitions @@ -105,7 +106,7 @@ func (s *ac2DiscoChainSuite) setup(t *testing.T, ct *commonTopo) { clu.Datacenter, clientSID, func(s *topology.Workload) { - s.Destinations = []*topology.Destination{ + s.Upstreams = []*topology.Upstream{ upstream, } }, @@ -164,8 +165,8 @@ func (s *ac2DiscoChainSuite) test(t *testing.T, ct *commonTopo) { require.Len(t, svcs, 1, "expected exactly one client in datacenter") client := svcs[0] - require.Len(t, client.Destinations, 1, "expected exactly one upstream for client") - u := client.Destinations[0] + require.Len(t, client.Upstreams, 1, "expected exactly one upstream for client") + u := client.Upstreams[0] t.Run("peered upstream exists in catalog", func(t *testing.T) { t.Parallel() @@ -176,7 +177,7 @@ func (s *ac2DiscoChainSuite) test(t *testing.T, ct *commonTopo) { t.Run("peered upstream endpoint status is healthy", func(t *testing.T) { t.Parallel() - ct.Assert.DestinationEndpointStatus(t, client, peerClusterPrefix(u), "HEALTHY", 1) + ct.Assert.UpstreamEndpointStatus(t, client, peerClusterPrefix(u), "HEALTHY", 1) }) t.Run("response contains header injected by splitter", func(t *testing.T) { @@ -196,7 +197,7 @@ func (s *ac2DiscoChainSuite) test(t *testing.T, ct *commonTopo) { // func (s *ResourceGenerator) getTargetClusterName // // and connect/sni.go -func peerClusterPrefix(u *topology.Destination) string { +func peerClusterPrefix(u *topology.Upstream) string { if u.Peer == "" { panic("upstream is not from a peer") } diff --git a/test-integ/peering_commontopo/ac3_service_defaults_upstream_test.go b/test-integ/peering_commontopo/ac3_service_defaults_upstream_test.go index caf801b09e..30b4b19480 100644 --- a/test-integ/peering_commontopo/ac3_service_defaults_upstream_test.go +++ b/test-integ/peering_commontopo/ac3_service_defaults_upstream_test.go @@ -11,13 +11,15 @@ import ( "testing" "time" + "github.com/itchyny/gojq" + "github.com/stretchr/testify/require" + + "github.com/hashicorp/go-cleanhttp" + "github.com/hashicorp/consul/api" "github.com/hashicorp/consul/sdk/testutil/retry" libassert "github.com/hashicorp/consul/test/integration/consul-container/libs/assert" "github.com/hashicorp/consul/testing/deployer/topology" - "github.com/hashicorp/go-cleanhttp" - "github.com/itchyny/gojq" - "github.com/stretchr/testify/require" ) var ac3SvcDefaultsSuites []sharedTopoSuite = []sharedTopoSuite{ @@ -40,7 +42,7 @@ type ac3SvcDefaultsSuite struct { sidClient topology.ID nodeClient topology.NodeID - upstream *topology.Destination + upstream *topology.Upstream } func (s *ac3SvcDefaultsSuite) testName() string { @@ -60,7 +62,7 @@ func (s *ac3SvcDefaultsSuite) setup(t *testing.T, ct *commonTopo) { Name: "ac3-server", Partition: partition, } - upstream := &topology.Destination{ + upstream := &topology.Upstream{ ID: topology.ID{ Name: serverSID.Name, Partition: partition, @@ -78,7 +80,7 @@ func (s *ac3SvcDefaultsSuite) setup(t *testing.T, ct *commonTopo) { clu.Datacenter, sid, func(s *topology.Workload) { - s.Destinations = []*topology.Destination{ + s.Upstreams = []*topology.Upstream{ upstream, } }, @@ -183,7 +185,7 @@ func (s *ac3SvcDefaultsSuite) test(t *testing.T, ct *commonTopo) { // TODO: what is default? namespace? partition? clusterName := fmt.Sprintf("%s.default.%s.external", s.upstream.ID.Name, s.upstream.Peer) nonceStatus := http.StatusInsufficientStorage - url507 := fmt.Sprintf("http://localhost:%d/fortio/fetch2?url=%s", svcClient.ExposedPort(""), + url507 := fmt.Sprintf("http://localhost:%d/fortio/fetch2?url=%s", svcClient.ExposedPort(), url.QueryEscape(fmt.Sprintf("http://localhost:%d/?status=%d", s.upstream.LocalPort, nonceStatus)), ) @@ -219,7 +221,7 @@ func (s *ac3SvcDefaultsSuite) test(t *testing.T, ct *commonTopo) { require.True(r, resultAsBool) }) - url200 := fmt.Sprintf("http://localhost:%d/fortio/fetch2?url=%s", svcClient.ExposedPort(""), + url200 := fmt.Sprintf("http://localhost:%d/fortio/fetch2?url=%s", svcClient.ExposedPort(), url.QueryEscape(fmt.Sprintf("http://localhost:%d/", s.upstream.LocalPort)), ) retry.RunWith(&retry.Timer{Timeout: time.Minute * 1, Wait: time.Millisecond * 500}, t, func(r *retry.R) { diff --git a/test-integ/peering_commontopo/ac4_proxy_defaults_test.go b/test-integ/peering_commontopo/ac4_proxy_defaults_test.go index c6bbc9506b..c27057a07a 100644 --- a/test-integ/peering_commontopo/ac4_proxy_defaults_test.go +++ b/test-integ/peering_commontopo/ac4_proxy_defaults_test.go @@ -9,10 +9,12 @@ import ( "net/url" "testing" + "github.com/stretchr/testify/require" + + "github.com/hashicorp/go-cleanhttp" + "github.com/hashicorp/consul/api" "github.com/hashicorp/consul/testing/deployer/topology" - "github.com/hashicorp/go-cleanhttp" - "github.com/stretchr/testify/require" ) type ac4ProxyDefaultsSuite struct { @@ -24,7 +26,7 @@ type ac4ProxyDefaultsSuite struct { serverSID topology.ID clientSID topology.ID - upstream *topology.Destination + upstream *topology.Upstream } var ac4ProxyDefaultsSuites []sharedTopoSuite = []sharedTopoSuite{ @@ -54,7 +56,7 @@ func (s *ac4ProxyDefaultsSuite) setup(t *testing.T, ct *commonTopo) { Partition: partition, } // Define server as upstream for client - upstream := &topology.Destination{ + upstream := &topology.Upstream{ ID: serverSID, LocalPort: 5000, Peer: peer, @@ -70,7 +72,7 @@ func (s *ac4ProxyDefaultsSuite) setup(t *testing.T, ct *commonTopo) { clu.Datacenter, clientSID, func(s *topology.Workload) { - s.Destinations = []*topology.Destination{ + s.Upstreams = []*topology.Upstream{ upstream, } }, @@ -165,11 +167,11 @@ func (s *ac4ProxyDefaultsSuite) test(t *testing.T, ct *commonTopo) { dcSvcs := dc.WorkloadsByID(s.clientSID) require.Len(t, dcSvcs, 1, "expected exactly one client") client = dcSvcs[0] - require.Len(t, client.Destinations, 1, "expected exactly one upstream for client") + require.Len(t, client.Upstreams, 1, "expected exactly one upstream for client") server := dc.WorkloadsByID(s.serverSID) require.Len(t, server, 1, "expected exactly one server") - require.Len(t, server[0].Destinations, 0, "expected no upstream for server") + require.Len(t, server[0].Upstreams, 0, "expected no upstream for server") }) t.Run("peered upstream exists in catalog", func(t *testing.T) { @@ -179,11 +181,11 @@ func (s *ac4ProxyDefaultsSuite) test(t *testing.T, ct *commonTopo) { }) t.Run("HTTP service fails due to connection timeout", func(t *testing.T) { - url504 := fmt.Sprintf("http://localhost:%d/fortio/fetch2?url=%s", client.ExposedPort(""), + url504 := fmt.Sprintf("http://localhost:%d/fortio/fetch2?url=%s", client.ExposedPort(), url.QueryEscape(fmt.Sprintf("http://localhost:%d/?delay=1000ms", s.upstream.LocalPort)), ) - url200 := fmt.Sprintf("http://localhost:%d/fortio/fetch2?url=%s", client.ExposedPort(""), + url200 := fmt.Sprintf("http://localhost:%d/fortio/fetch2?url=%s", client.ExposedPort(), url.QueryEscape(fmt.Sprintf("http://localhost:%d/", s.upstream.LocalPort)), ) diff --git a/test-integ/peering_commontopo/ac6_failovers_test.go b/test-integ/peering_commontopo/ac6_failovers_test.go index ad71cf477b..4b37d10955 100644 --- a/test-integ/peering_commontopo/ac6_failovers_test.go +++ b/test-integ/peering_commontopo/ac6_failovers_test.go @@ -7,11 +7,12 @@ import ( "fmt" "testing" + "github.com/stretchr/testify/require" + "github.com/hashicorp/consul/api" "github.com/hashicorp/consul/test/integration/consul-container/libs/utils" "github.com/hashicorp/consul/testing/deployer/sprawl" "github.com/hashicorp/consul/testing/deployer/topology" - "github.com/stretchr/testify/require" ) type ac6FailoversSuite struct { @@ -347,8 +348,8 @@ func (s *ac6FailoversSuite) setup(t *testing.T, ct *commonTopo) { nearClu.Datacenter, clientSID, func(s *topology.Workload) { - // Destination per partition - s.Destinations = []*topology.Destination{ + // Upstream per partition + s.Upstreams = []*topology.Upstream{ { ID: topology.ID{ Name: nearServerSID.Name, @@ -437,8 +438,8 @@ func (s *ac6FailoversSuite) test(t *testing.T, ct *commonTopo) { require.Len(t, svcs, 1, "expected exactly one client in datacenter") client := svcs[0] - require.Len(t, client.Destinations, 1, "expected one upstream for client") - upstream := client.Destinations[0] + require.Len(t, client.Upstreams, 1, "expected one upstream for client") + upstream := client.Upstreams[0] fmt.Println("### preconditions") diff --git a/test-integ/peering_commontopo/ac7_1_rotate_gw_test.go b/test-integ/peering_commontopo/ac7_1_rotate_gw_test.go index 6c5749f37c..e901c7c305 100644 --- a/test-integ/peering_commontopo/ac7_1_rotate_gw_test.go +++ b/test-integ/peering_commontopo/ac7_1_rotate_gw_test.go @@ -8,9 +8,10 @@ import ( "strings" "testing" + "github.com/stretchr/testify/require" + "github.com/hashicorp/consul/api" "github.com/hashicorp/consul/testing/deployer/topology" - "github.com/stretchr/testify/require" ) // TestRotateGW ensures that peered services continue to be able to talk to their @@ -27,7 +28,7 @@ type suiteRotateGW struct { sidClient topology.ID nodeClient topology.NodeID - upstream *topology.Destination + upstream *topology.Upstream newMGWNodeName string } @@ -70,7 +71,7 @@ func (s *suiteRotateGW) setup(t *testing.T, ct *commonTopo) { ) // Make clients which have server upstreams - upstream := &topology.Destination{ + upstream := &topology.Upstream{ ID: topology.ID{ Name: server.ID.Name, Partition: partition, @@ -88,7 +89,7 @@ func (s *suiteRotateGW) setup(t *testing.T, ct *commonTopo) { Partition: partition, }, func(s *topology.Workload) { - s.Destinations = []*topology.Destination{ + s.Upstreams = []*topology.Upstream{ upstream, } }, diff --git a/test-integ/peering_commontopo/ac7_2_rotate_leader_test.go b/test-integ/peering_commontopo/ac7_2_rotate_leader_test.go index 2cf9920278..0f6fe439e2 100644 --- a/test-integ/peering_commontopo/ac7_2_rotate_leader_test.go +++ b/test-integ/peering_commontopo/ac7_2_rotate_leader_test.go @@ -8,13 +8,14 @@ import ( "testing" "time" + "github.com/mitchellh/copystructure" + "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" + "github.com/hashicorp/consul/api" "github.com/hashicorp/consul/sdk/testutil/retry" "github.com/hashicorp/consul/test/integration/consul-container/libs/utils" "github.com/hashicorp/consul/testing/deployer/topology" - "github.com/mitchellh/copystructure" - "github.com/stretchr/testify/assert" - "github.com/stretchr/testify/require" ) // TestAC7_2RotateLeader ensures that after a leader rotation, information continues to replicate to peers @@ -29,7 +30,7 @@ type ac7_2RotateLeaderSuite struct { sidClient topology.ID nodeClient topology.NodeID - upstream *topology.Destination + upstream *topology.Upstream } func TestAC7_2RotateLeader(t *testing.T) { @@ -71,7 +72,7 @@ func (s *ac7_2RotateLeaderSuite) setup(t *testing.T, ct *commonTopo) { ) // Make clients which have server upstreams - upstream := &topology.Destination{ + upstream := &topology.Upstream{ ID: topology.ID{ Name: server.ID.Name, Partition: partition, @@ -87,7 +88,7 @@ func (s *ac7_2RotateLeaderSuite) setup(t *testing.T, ct *commonTopo) { Partition: partition, }, func(s *topology.Workload) { - s.Destinations = []*topology.Destination{ + s.Upstreams = []*topology.Upstream{ upstream, } }, diff --git a/test-integ/peering_commontopo/commontopo.go b/test-integ/peering_commontopo/commontopo.go index 8d931d86bb..c436093255 100644 --- a/test-integ/peering_commontopo/commontopo.go +++ b/test-integ/peering_commontopo/commontopo.go @@ -9,16 +9,16 @@ import ( "testing" "time" + "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" + "github.com/hashicorp/consul/api" "github.com/hashicorp/consul/sdk/testutil/retry" + "github.com/hashicorp/consul/test-integ/topoutil" "github.com/hashicorp/consul/test/integration/consul-container/libs/utils" "github.com/hashicorp/consul/testing/deployer/sprawl" "github.com/hashicorp/consul/testing/deployer/sprawl/sprawltest" "github.com/hashicorp/consul/testing/deployer/topology" - "github.com/stretchr/testify/assert" - "github.com/stretchr/testify/require" - - "github.com/hashicorp/consul/test-integ/topoutil" ) // commonTopo helps create a shareable topology configured to represent @@ -509,7 +509,7 @@ func NewFortioServiceWithDefaults( sid topology.ID, mut func(s *topology.Workload), ) *topology.Workload { - return topoutil.NewFortioServiceWithDefaults(cluster, sid, topology.NodeVersionV1, mut) + return topoutil.NewFortioServiceWithDefaults(cluster, sid, mut) } func newTopologyMeshGatewaySet( diff --git a/test-integ/topoutil/asserter.go b/test-integ/topoutil/asserter.go index 361adf1769..0ba842ad07 100644 --- a/test-integ/topoutil/asserter.go +++ b/test-integ/topoutil/asserter.go @@ -6,16 +6,6 @@ package topoutil import ( "encoding/json" "fmt" - "github.com/google/go-cmp/cmp" - "github.com/hashicorp/consul/api" - "github.com/hashicorp/consul/proto-public/pbresource" - "github.com/hashicorp/consul/sdk/testutil" - "github.com/hashicorp/consul/sdk/testutil/retry" - libassert "github.com/hashicorp/consul/test/integration/consul-container/libs/assert" - "github.com/hashicorp/consul/test/integration/consul-container/libs/utils" - "github.com/hashicorp/consul/testing/deployer/topology" - "github.com/stretchr/testify/assert" - "github.com/stretchr/testify/require" "io" "net/http" "net/url" @@ -24,6 +14,18 @@ import ( "strings" "testing" "time" + + "github.com/google/go-cmp/cmp" + "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" + + "github.com/hashicorp/consul/api" + "github.com/hashicorp/consul/proto-public/pbresource" + "github.com/hashicorp/consul/sdk/testutil" + "github.com/hashicorp/consul/sdk/testutil/retry" + libassert "github.com/hashicorp/consul/test/integration/consul-container/libs/assert" + "github.com/hashicorp/consul/test/integration/consul-container/libs/utils" + "github.com/hashicorp/consul/testing/deployer/topology" ) // Asserter is a utility to help in reducing boilerplate in invoking test @@ -33,7 +35,7 @@ import ( // ip/ports if there is only one port that makes sense for the assertion (such // as use of the envoy admin port 19000). // -// If it's up to the test (like picking a destination) leave port as an argument +// If it's up to the test (like picking an upstream) leave port as an argument // but still take the service and use that to grab the local ip from the // topology.Node. type Asserter struct { @@ -82,12 +84,12 @@ func (a *Asserter) httpClientFor(cluster string) (*http.Client, error) { return client, nil } -// DestinationEndpointStatus validates that proxy was configured with provided clusterName in the healthStatus +// UpstreamEndpointStatus validates that proxy was configured with provided clusterName in the healthStatus // // Exposes libassert.UpstreamEndpointStatus for use against a Sprawl. // // NOTE: this doesn't take a port b/c you always want to use the envoy admin port. -func (a *Asserter) DestinationEndpointStatus( +func (a *Asserter) UpstreamEndpointStatus( t *testing.T, workload *topology.Workload, clusterName string, @@ -169,7 +171,7 @@ func (a *Asserter) AssertEnvoyHTTPrbacFiltersContainIntentions(t *testing.T, wor // // Exposes libassert.HTTPServiceEchoes for use against a Sprawl. // -// NOTE: this takes a port b/c you may want to reach this via your choice of destination. +// NOTE: this takes a port b/c you may want to reach this via your choice of upstream. func (a *Asserter) HTTPServiceEchoes( t *testing.T, workload *topology.Workload, @@ -193,7 +195,7 @@ func (a *Asserter) HTTPServiceEchoes( // // Exposes libassert.HTTPServiceEchoes for use against a Sprawl. // -// NOTE: this takes a port b/c you may want to reach this via your choice of destination. +// NOTE: this takes a port b/c you may want to reach this via your choice of upstream. func (a *Asserter) HTTPServiceEchoesResHeader( t *testing.T, workload *topology.Workload, @@ -266,27 +268,27 @@ type testingT interface { Helper() } -// does a fortio /fetch2 to the given fortio service, targetting the given destination. Returns +// does a fortio /fetch2 to the given fortio service, targetting the given upstream. Returns // the body, and response with response.Body already Closed. // // We treat 400, 503, and 504s as retryable errors -func (a *Asserter) fortioFetch2Destination( +func (a *Asserter) fortioFetch2Upstream( t testutil.TestingTB, client *http.Client, addr string, - dest *topology.Destination, + us *topology.Upstream, path string, ) (body []byte, res *http.Response) { t.Helper() - err, res := getFortioFetch2DestinationResponse(t, client, addr, dest, path, nil) + err, res := getFortioFetch2UpstreamResponse(t, client, addr, us, path, nil) require.NoError(t, err) defer res.Body.Close() // not sure when these happen, suspect it's when the mesh gateway in the peer is not yet ready require.NotEqual(t, http.StatusServiceUnavailable, res.StatusCode) require.NotEqual(t, http.StatusGatewayTimeout, res.StatusCode) - // not sure when this happens, suspect it's when envoy hasn't configured the local destination yet + // not sure when this happens, suspect it's when envoy hasn't configured the local upstream yet require.NotEqual(t, http.StatusBadRequest, res.StatusCode) body, err = io.ReadAll(res.Body) require.NoError(t, err) @@ -294,19 +296,8 @@ func (a *Asserter) fortioFetch2Destination( return body, res } -func getFortioFetch2DestinationResponse(t testutil.TestingTB, client *http.Client, addr string, dest *topology.Destination, path string, headers map[string]string) (error, *http.Response) { - var actualURL string - if dest.Implied { - actualURL = fmt.Sprintf("http://%s--%s--%s.virtual.consul:%d/%s", - dest.ID.Name, - dest.ID.Namespace, - dest.ID.Partition, - dest.VirtualPort, - path, - ) - } else { - actualURL = fmt.Sprintf("http://localhost:%d/%s", dest.LocalPort, path) - } +func getFortioFetch2UpstreamResponse(t testutil.TestingTB, client *http.Client, addr string, us *topology.Upstream, path string, headers map[string]string) (error, *http.Response) { + actualURL := fmt.Sprintf("http://localhost:%d/%s", us.LocalPort, path) url := fmt.Sprintf("http://%s/fortio/fetch2?url=%s", addr, url.QueryEscape(actualURL), @@ -324,20 +315,20 @@ func getFortioFetch2DestinationResponse(t testutil.TestingTB, client *http.Clien } // uses the /fortio/fetch2 endpoint to do a header echo check against an -// destination fortio -func (a *Asserter) FortioFetch2HeaderEcho(t *testing.T, fortioWrk *topology.Workload, dest *topology.Destination) { +// upstream fortio +func (a *Asserter) FortioFetch2HeaderEcho(t *testing.T, fortioWrk *topology.Workload, us *topology.Upstream) { const kPassphrase = "x-passphrase" const passphrase = "hello" path := (fmt.Sprintf("/?header=%s:%s", kPassphrase, passphrase)) var ( node = fortioWrk.Node - addr = fmt.Sprintf("%s:%d", node.LocalAddress(), fortioWrk.PortOrDefault(dest.PortName)) + addr = fmt.Sprintf("%s:%d", node.LocalAddress(), fortioWrk.Port) client = a.mustGetHTTPClient(t, node.Cluster) ) retry.RunWith(&retry.Timer{Timeout: 60 * time.Second, Wait: time.Millisecond * 500}, t, func(r *retry.R) { - _, res := a.fortioFetch2Destination(r, client, addr, dest, path) + _, res := a.fortioFetch2Upstream(r, client, addr, us, path) require.Equal(r, http.StatusOK, res.StatusCode) v := res.Header.Get(kPassphrase) require.Equal(r, passphrase, v) @@ -345,12 +336,12 @@ func (a *Asserter) FortioFetch2HeaderEcho(t *testing.T, fortioWrk *topology.Work } // similar to libassert.AssertFortioName, -// uses the /fortio/fetch2 endpoint to hit the debug endpoint on the destination, +// uses the /fortio/fetch2 endpoint to hit the debug endpoint on the upstream, // and assert that the FORTIO_NAME == name func (a *Asserter) FortioFetch2FortioName( t *testing.T, fortioWrk *topology.Workload, - dest *topology.Destination, + us *topology.Upstream, clusterName string, sid topology.ID, ) { @@ -358,7 +349,7 @@ func (a *Asserter) FortioFetch2FortioName( var ( node = fortioWrk.Node - addr = fmt.Sprintf("%s:%d", node.LocalAddress(), fortioWrk.PortOrDefault(dest.PortName)) + addr = fmt.Sprintf("%s:%d", node.LocalAddress(), fortioWrk.Port) client = a.mustGetHTTPClient(t, node.Cluster) ) @@ -366,7 +357,7 @@ func (a *Asserter) FortioFetch2FortioName( path := "/debug?env=dump" retry.RunWith(&retry.Timer{Timeout: 60 * time.Second, Wait: time.Millisecond * 500}, t, func(r *retry.R) { - body, res := a.fortioFetch2Destination(r, client, addr, dest, path) + body, res := a.fortioFetch2Upstream(r, client, addr, us, path) require.Equal(r, http.StatusOK, res.StatusCode) @@ -378,24 +369,24 @@ func (a *Asserter) FortioFetch2FortioName( }) } -func (a *Asserter) FortioFetch2ServiceUnavailable(t *testing.T, fortioWrk *topology.Workload, dest *topology.Destination) { +func (a *Asserter) FortioFetch2ServiceUnavailable(t *testing.T, fortioWrk *topology.Workload, us *topology.Upstream) { const kPassphrase = "x-passphrase" const passphrase = "hello" path := (fmt.Sprintf("/?header=%s:%s", kPassphrase, passphrase)) - a.FortioFetch2ServiceStatusCodes(t, fortioWrk, dest, path, nil, []int{http.StatusServiceUnavailable}) + a.FortioFetch2ServiceStatusCodes(t, fortioWrk, us, path, nil, []int{http.StatusServiceUnavailable}) } -// FortioFetch2ServiceStatusCodes uses the /fortio/fetch2 endpoint to do a header echo check against a destination +// FortioFetch2ServiceStatusCodes uses the /fortio/fetch2 endpoint to do a header echo check against a upstream // fortio and asserts that the returned status code matches the desired one(s) -func (a *Asserter) FortioFetch2ServiceStatusCodes(t *testing.T, fortioWrk *topology.Workload, dest *topology.Destination, path string, headers map[string]string, statuses []int) { +func (a *Asserter) FortioFetch2ServiceStatusCodes(t *testing.T, fortioWrk *topology.Workload, us *topology.Upstream, path string, headers map[string]string, statuses []int) { var ( node = fortioWrk.Node - addr = fmt.Sprintf("%s:%d", node.LocalAddress(), fortioWrk.PortOrDefault(dest.PortName)) + addr = fmt.Sprintf("%s:%d", node.LocalAddress(), fortioWrk.Port) client = a.mustGetHTTPClient(t, node.Cluster) ) retry.RunWith(&retry.Timer{Timeout: 60 * time.Second, Wait: time.Millisecond * 500}, t, func(r *retry.R) { - _, res := getFortioFetch2DestinationResponse(r, client, addr, dest, path, headers) + _, res := getFortioFetch2UpstreamResponse(r, client, addr, us, path, headers) defer res.Body.Close() require.Contains(r, statuses, res.StatusCode) }) diff --git a/test-integ/topoutil/asserter_blankspace.go b/test-integ/topoutil/asserter_blankspace.go index ca41e2f32d..ed6d76b9b3 100644 --- a/test-integ/topoutil/asserter_blankspace.go +++ b/test-integ/topoutil/asserter_blankspace.go @@ -9,9 +9,10 @@ import ( "testing" "time" + "github.com/stretchr/testify/require" + "github.com/hashicorp/consul/sdk/testutil/retry" "github.com/hashicorp/consul/testing/deployer/topology" - "github.com/stretchr/testify/require" ) // CheckBlankspaceNameViaHTTP calls a copy of blankspace and asserts it arrived @@ -19,7 +20,7 @@ import ( func (a *Asserter) CheckBlankspaceNameViaHTTP( t *testing.T, workload *topology.Workload, - dest *topology.Destination, + us *topology.Upstream, useHTTP2 bool, path string, clusterName string, @@ -27,7 +28,7 @@ func (a *Asserter) CheckBlankspaceNameViaHTTP( ) { t.Helper() - a.checkBlankspaceNameViaHTTPWithCallback(t, workload, dest, useHTTP2, path, 1, func(_ *retry.R) {}, func(r *retry.R, remoteName string) { + a.checkBlankspaceNameViaHTTPWithCallback(t, workload, us, useHTTP2, path, 1, func(_ *retry.R) {}, func(r *retry.R, remoteName string) { require.Equal(r, fmt.Sprintf("%s::%s", clusterName, sid.String()), remoteName) }, func(r *retry.R) {}) } @@ -37,7 +38,7 @@ func (a *Asserter) CheckBlankspaceNameViaHTTP( func (a *Asserter) CheckBlankspaceNameTrafficSplitViaHTTP( t *testing.T, workload *topology.Workload, - dest *topology.Destination, + us *topology.Upstream, useHTTP2 bool, path string, expect map[string]int, @@ -45,7 +46,7 @@ func (a *Asserter) CheckBlankspaceNameTrafficSplitViaHTTP( t.Helper() got := make(map[string]int) - a.checkBlankspaceNameViaHTTPWithCallback(t, workload, dest, useHTTP2, path, 100, func(_ *retry.R) { + a.checkBlankspaceNameViaHTTPWithCallback(t, workload, us, useHTTP2, path, 100, func(_ *retry.R) { got = make(map[string]int) }, func(_ *retry.R, name string) { got[name]++ @@ -57,7 +58,7 @@ func (a *Asserter) CheckBlankspaceNameTrafficSplitViaHTTP( func (a *Asserter) checkBlankspaceNameViaHTTPWithCallback( t *testing.T, workload *topology.Workload, - dest *topology.Destination, + us *topology.Upstream, useHTTP2 bool, path string, count int, @@ -69,7 +70,7 @@ func (a *Asserter) checkBlankspaceNameViaHTTPWithCallback( var ( node = workload.Node - internalPort = workload.PortOrDefault(dest.PortName) + internalPort = workload.Port addr = fmt.Sprintf("%s:%d", node.LocalAddress(), internalPort) client = a.mustGetHTTPClient(t, node.Cluster) ) @@ -85,18 +86,7 @@ func (a *Asserter) checkBlankspaceNameViaHTTPWithCallback( client = EnableHTTP2(client) } - var actualURL string - if dest.Implied { - actualURL = fmt.Sprintf("http://%s--%s--%s.virtual.consul:%d/%s", - dest.ID.Name, - dest.ID.Namespace, - dest.ID.Partition, - dest.VirtualPort, - path, - ) - } else { - actualURL = fmt.Sprintf("http://localhost:%d/%s", dest.LocalPort, path) - } + actualURL := fmt.Sprintf("http://localhost:%d/%s", us.LocalPort, path) multiassert(t, count, resetFn, func(r *retry.R) { name, err := GetBlankspaceNameViaHTTP(context.Background(), client, addr, actualURL) @@ -112,13 +102,13 @@ func (a *Asserter) checkBlankspaceNameViaHTTPWithCallback( func (a *Asserter) CheckBlankspaceNameViaTCP( t *testing.T, workload *topology.Workload, - dest *topology.Destination, + us *topology.Upstream, clusterName string, sid topology.ID, ) { t.Helper() - a.checkBlankspaceNameViaTCPWithCallback(t, workload, dest, 1, func(_ *retry.R) {}, func(r *retry.R, remoteName string) { + a.checkBlankspaceNameViaTCPWithCallback(t, workload, us, 1, func(_ *retry.R) {}, func(r *retry.R, remoteName string) { require.Equal(r, fmt.Sprintf("%s::%s", clusterName, sid.String()), remoteName) }, func(r *retry.R) {}) } @@ -128,13 +118,13 @@ func (a *Asserter) CheckBlankspaceNameViaTCP( func (a *Asserter) CheckBlankspaceNameTrafficSplitViaTCP( t *testing.T, workload *topology.Workload, - dest *topology.Destination, + us *topology.Upstream, expect map[string]int, ) { t.Helper() got := make(map[string]int) - a.checkBlankspaceNameViaTCPWithCallback(t, workload, dest, 100, func(_ *retry.R) { + a.checkBlankspaceNameViaTCPWithCallback(t, workload, us, 100, func(_ *retry.R) { got = make(map[string]int) }, func(_ *retry.R, name string) { got[name]++ @@ -146,7 +136,7 @@ func (a *Asserter) CheckBlankspaceNameTrafficSplitViaTCP( func (a *Asserter) checkBlankspaceNameViaTCPWithCallback( t *testing.T, workload *topology.Workload, - dest *topology.Destination, + us *topology.Upstream, count int, resetFn func(r *retry.R), attemptFn func(r *retry.R, remoteName string), @@ -154,8 +144,7 @@ func (a *Asserter) checkBlankspaceNameViaTCPWithCallback( ) { t.Helper() - require.False(t, dest.Implied, "helper does not support tproxy yet") - port := dest.LocalPort + port := us.LocalPort require.True(t, port > 0) node := workload.Node @@ -180,13 +169,13 @@ func (a *Asserter) checkBlankspaceNameViaTCPWithCallback( func (a *Asserter) CheckBlankspaceNameViaGRPC( t *testing.T, workload *topology.Workload, - dest *topology.Destination, + us *topology.Upstream, clusterName string, sid topology.ID, ) { t.Helper() - a.checkBlankspaceNameViaGRPCWithCallback(t, workload, dest, 1, func(_ *retry.R) {}, func(r *retry.R, remoteName string) { + a.checkBlankspaceNameViaGRPCWithCallback(t, workload, us, 1, func(_ *retry.R) {}, func(r *retry.R, remoteName string) { require.Equal(r, fmt.Sprintf("%s::%s", clusterName, sid.String()), remoteName) }, func(_ *retry.R) {}) } @@ -196,13 +185,13 @@ func (a *Asserter) CheckBlankspaceNameViaGRPC( func (a *Asserter) CheckBlankspaceNameTrafficSplitViaGRPC( t *testing.T, workload *topology.Workload, - dest *topology.Destination, + us *topology.Upstream, expect map[string]int, ) { t.Helper() got := make(map[string]int) - a.checkBlankspaceNameViaGRPCWithCallback(t, workload, dest, 100, func(_ *retry.R) { + a.checkBlankspaceNameViaGRPCWithCallback(t, workload, us, 100, func(_ *retry.R) { got = make(map[string]int) }, func(_ *retry.R, name string) { got[name]++ @@ -214,7 +203,7 @@ func (a *Asserter) CheckBlankspaceNameTrafficSplitViaGRPC( func (a *Asserter) checkBlankspaceNameViaGRPCWithCallback( t *testing.T, workload *topology.Workload, - dest *topology.Destination, + us *topology.Upstream, count int, resetFn func(r *retry.R), attemptFn func(r *retry.R, remoteName string), @@ -222,8 +211,7 @@ func (a *Asserter) checkBlankspaceNameViaGRPCWithCallback( ) { t.Helper() - require.False(t, dest.Implied, "helper does not support tproxy yet") - port := dest.LocalPort + port := us.LocalPort require.True(t, port > 0) node := workload.Node @@ -244,7 +232,7 @@ func (a *Asserter) checkBlankspaceNameViaGRPCWithCallback( } // assertTrafficSplitFor100Requests compares the counts of 100 requests that -// did reach an observed set of destinations (nameCounts) against the expected +// did reach an observed set of upstreams (nameCounts) against the expected // counts of those same services is the same within a fixed difference of 2. func assertTrafficSplitFor100Requests(t require.TestingT, nameCounts map[string]int, expect map[string]int) { const ( @@ -265,7 +253,7 @@ func sumMapValues(m map[string]int) int { } // assertTrafficSplit compares the counts of requests that did reach an -// observed set of destinations (nameCounts) against the expected counts of +// observed set of upstreams (nameCounts) against the expected counts of // those same services is the same within the provided allowedDelta value. // // When doing random traffic splits it'll never be perfect so we need the diff --git a/test-integ/topoutil/fixtures.go b/test-integ/topoutil/fixtures.go index aeb82a0bc9..49daac947c 100644 --- a/test-integ/topoutil/fixtures.go +++ b/test-integ/topoutil/fixtures.go @@ -15,12 +15,8 @@ const HashicorpDockerProxy = "docker.mirror.hashicorp.services" func NewFortioWorkloadWithDefaults( cluster string, sid topology.ID, - nodeVersion topology.NodeVersion, mut func(*topology.Workload), ) *topology.Workload { - if nodeVersion == topology.NodeVersionV2 { - panic("v2 nodes are not supported") - } const ( httpPort = 8080 grpcPort = 8079 @@ -56,12 +52,8 @@ func NewFortioWorkloadWithDefaults( func NewBlankspaceWorkloadWithDefaults( cluster string, sid topology.ID, - nodeVersion topology.NodeVersion, mut func(*topology.Workload), ) *topology.Workload { - if nodeVersion == topology.NodeVersionV2 { - panic("v2 nodes are not supported") - } const ( httpPort = 8080 grpcPort = 8079 diff --git a/test-integ/topoutil/naming_shim.go b/test-integ/topoutil/naming_shim.go index 40355992a3..8a4edc8f9e 100644 --- a/test-integ/topoutil/naming_shim.go +++ b/test-integ/topoutil/naming_shim.go @@ -4,38 +4,23 @@ package topoutil import ( - "testing" - "github.com/hashicorp/consul/testing/deployer/topology" ) -// Deprecated: DestinationEndpointStatus -func (a *Asserter) UpstreamEndpointStatus( - t *testing.T, - workload *topology.Workload, - clusterName string, - healthStatus string, - count int, -) { - a.DestinationEndpointStatus(t, workload, clusterName, healthStatus, count) -} - // Deprecated: NewFortioWorkloadWithDefaults func NewFortioServiceWithDefaults( cluster string, sid topology.ID, - nodeVersion topology.NodeVersion, mut func(*topology.Workload), ) *topology.Workload { - return NewFortioWorkloadWithDefaults(cluster, sid, nodeVersion, mut) + return NewFortioWorkloadWithDefaults(cluster, sid, mut) } // Deprecated: NewBlankspaceWorkloadWithDefaults func NewBlankspaceServiceWithDefaults( cluster string, sid topology.ID, - nodeVersion topology.NodeVersion, mut func(*topology.Workload), ) *topology.Workload { - return NewBlankspaceWorkloadWithDefaults(cluster, sid, nodeVersion, mut) + return NewBlankspaceWorkloadWithDefaults(cluster, sid, mut) } diff --git a/test-integ/upgrade/basic/common.go b/test-integ/upgrade/basic/common.go index c79fc82799..0b4bff8bf1 100644 --- a/test-integ/upgrade/basic/common.go +++ b/test-integ/upgrade/basic/common.go @@ -130,7 +130,7 @@ func newCommonTopo(t *testing.T) *commonTopo { "-http-port", "8080", "-redirect-port", "-disabled", }, - Upstreams: []*topology.Destination{ + Upstreams: []*topology.Upstream{ { ID: staticServerSID, LocalPort: 5000, @@ -218,7 +218,7 @@ func (ct *commonTopo) PostUpgradeValidation(t *testing.T) { cluster.Nodes[ct.StaticServerInstTwo].Disabled = false // client 3 -- new static-server require.NoError(t, ct.Sprawl.RelaunchWithPhase(cfg, sprawl.LaunchPhaseRegular)) // Ensure the static-client connected to the new static-server - ct.Assert.FortioFetch2HeaderEcho(t, ct.StaticClientWorkload, &topology.Destination{ + ct.Assert.FortioFetch2HeaderEcho(t, ct.StaticClientWorkload, &topology.Upstream{ ID: ct.StaticServerSID, LocalPort: 5000, }) @@ -244,7 +244,7 @@ func (ct *commonTopo) Launch(t *testing.T) { topology.NewNodeID("dc1-client2", "default"), ct.StaticClientSID, ) - ct.Assert.FortioFetch2HeaderEcho(t, staticClientWorkload, &topology.Destination{ + ct.Assert.FortioFetch2HeaderEcho(t, staticClientWorkload, &topology.Upstream{ ID: ct.StaticServerSID, LocalPort: 5000, }) diff --git a/test-integ/upgrade/l7_traffic_management/common.go b/test-integ/upgrade/l7_traffic_management/common.go index ca24a75c05..f60e995b71 100644 --- a/test-integ/upgrade/l7_traffic_management/common.go +++ b/test-integ/upgrade/l7_traffic_management/common.go @@ -8,12 +8,11 @@ import ( "testing" "github.com/hashicorp/consul/api" + "github.com/hashicorp/consul/test-integ/topoutil" "github.com/hashicorp/consul/test/integration/consul-container/libs/utils" "github.com/hashicorp/consul/testing/deployer/sprawl" "github.com/hashicorp/consul/testing/deployer/sprawl/sprawltest" "github.com/hashicorp/consul/testing/deployer/topology" - - "github.com/hashicorp/consul/test-integ/topoutil" ) type commonTopo struct { @@ -51,11 +50,11 @@ func NewCommonTopo(t *testing.T) *commonTopo { // // dataplane // - workload(fortio) static-server on node dc1-client1 -// - workload(fortio) static-client on node dc1-client2 with destination to static-server +// - workload(fortio) static-client on node dc1-client2 with upstream to static-server // - static-client, static-server are registered at 2 agentless nodes. // // Intentions -// - static-client has destination to static-server +// - static-client has upstream to static-server func newCommonTopo(t *testing.T) *commonTopo { t.Helper() @@ -107,7 +106,7 @@ func newCommonTopo(t *testing.T) *commonTopo { }, }, }, - // static-client on dc1-client2 with destination to static-server + // static-client on dc1-client2 with upstream to static-server { Kind: topology.NodeKindDataplane, Name: "dc1-client2", @@ -123,7 +122,7 @@ func newCommonTopo(t *testing.T) *commonTopo { "-http-port", "8080", "-redirect-port", "-disabled", }, - Destinations: []*topology.Destination{ + Upstreams: []*topology.Upstream{ { ID: staticServerSID, // static-server LocalPort: 5000, @@ -208,7 +207,7 @@ func (ct *commonTopo) ValidateWorkloads(t *testing.T) { // check the service exists in catalog svcs := cluster.WorkloadsByID(ct.StaticClientSID) client := svcs[0] - upstream := client.Destinations[0] + upstream := client.Upstreams[0] ct.Assert.CatalogServiceExists(t, cluster.Name, upstream.ID.Name, utils.CompatQueryOpts(&api.QueryOptions{ Partition: upstream.ID.Partition, Namespace: upstream.ID.Namespace, diff --git a/test-integ/upgrade/l7_traffic_management/resolver_test.go b/test-integ/upgrade/l7_traffic_management/resolver_test.go index a3bc553c04..17c4eefaf0 100644 --- a/test-integ/upgrade/l7_traffic_management/resolver_test.go +++ b/test-integ/upgrade/l7_traffic_management/resolver_test.go @@ -38,15 +38,15 @@ func TestTrafficManagement_ResolverDefaultSubset_Agentless(t *testing.T) { topology.NewNodeID("dc1-client2", defaultPartition), ct.StaticClientSID, ) - ct.Assert.FortioFetch2HeaderEcho(t, staticClientWorkload, &topology.Destination{ + ct.Assert.FortioFetch2HeaderEcho(t, staticClientWorkload, &topology.Upstream{ ID: ct.StaticServerSID, LocalPort: 5000, }) - ct.Assert.FortioFetch2FortioName(t, staticClientWorkload, &topology.Destination{ + ct.Assert.FortioFetch2FortioName(t, staticClientWorkload, &topology.Upstream{ ID: ct.StaticServerSID, LocalPort: 5000, }, dc1, staticServerSID) - ct.Assert.DestinationEndpointStatus(t, staticClientWorkload, "v2.static-server.default", "HEALTHY", 1) + ct.Assert.UpstreamEndpointStatus(t, staticClientWorkload, "v2.static-server.default", "HEALTHY", 1) } resolverV2AssertFn() @@ -82,7 +82,7 @@ func TestTrafficManagement_ResolverDefaultSubset_Agentless(t *testing.T) { topology.NewNodeID("dc1-client2", defaultPartition), ct.StaticClientSID, ) - ct.Assert.FortioFetch2ServiceUnavailable(t, staticClientWorkload, &topology.Destination{ + ct.Assert.FortioFetch2ServiceUnavailable(t, staticClientWorkload, &topology.Upstream{ ID: ct.StaticServerSID, LocalPort: 5000, }) diff --git a/testing/deployer/README.md b/testing/deployer/README.md index 604bbdb087..513c6c6245 100644 --- a/testing/deployer/README.md +++ b/testing/deployer/README.md @@ -12,7 +12,7 @@ provider to manage a fleet of local docker containers and networks. The complete topology of Consul clusters is defined using a topology.Config which allows you to define a set of networks and reference those networks when -assigning nodes and services to clusters. Both Consul clients and +assigning nodes and workloads to clusters. Both Consul clients and `consul-dataplane` instances are supported. Here is an example configuration with two peered clusters: @@ -39,9 +39,9 @@ cfg := &topology.Config{ { Kind: topology.NodeKindClient, Name: "dc1-client1", - Services: []*topology.Service{ + Workloads: []*topology.Workload{ { - ID: topology.ServiceID{Name: "mesh-gateway"}, + ID: topology.ID{Name: "mesh-gateway"}, Port: 8443, EnvoyAdminPort: 19000, IsMeshGateway: true, @@ -51,9 +51,9 @@ cfg := &topology.Config{ { Kind: topology.NodeKindClient, Name: "dc1-client2", - Services: []*topology.Service{ + Workloads: []*topology.Workload{ { - ID: topology.ServiceID{Name: "ping"}, + ID: topology.ID{Name: "ping"}, Image: "rboyer/pingpong:latest", Port: 8080, EnvoyAdminPort: 19000, @@ -65,7 +65,7 @@ cfg := &topology.Config{ "-name", "ping", }, Upstreams: []*topology.Upstream{{ - ID: topology.ServiceID{Name: "pong"}, + ID: topology.ID{Name: "pong"}, LocalPort: 9090, Peer: "peer-dc2-default", }}, @@ -99,9 +99,9 @@ cfg := &topology.Config{ { Kind: topology.NodeKindClient, Name: "dc2-client1", - Services: []*topology.Service{ + Workloads: []*topology.Workload{ { - ID: topology.ServiceID{Name: "mesh-gateway"}, + ID: topology.ID{Name: "mesh-gateway"}, Port: 8443, EnvoyAdminPort: 19000, IsMeshGateway: true, @@ -111,9 +111,9 @@ cfg := &topology.Config{ { Kind: topology.NodeKindDataplane, Name: "dc2-client2", - Services: []*topology.Service{ + Workloads: []*topology.Workload{ { - ID: topology.ServiceID{Name: "pong"}, + ID: topology.ID{Name: "pong"}, Image: "rboyer/pingpong:latest", Port: 8080, EnvoyAdminPort: 19000, @@ -125,7 +125,7 @@ cfg := &topology.Config{ "-name", "pong", }, Upstreams: []*topology.Upstream{{ - ID: topology.ServiceID{Name: "ping"}, + ID: topology.ID{Name: "ping"}, LocalPort: 9090, Peer: "peer-dc1-default", }}, @@ -176,4 +176,4 @@ func TestSomething(t *testing.T) { sp := sprawltest.Launch(t, cfg) // do stuff with 'sp' } -``` \ No newline at end of file +``` diff --git a/testing/deployer/sprawl/acl_rules.go b/testing/deployer/sprawl/acl_rules.go index 554b418cd0..fd0033f246 100644 --- a/testing/deployer/sprawl/acl_rules.go +++ b/testing/deployer/sprawl/acl_rules.go @@ -7,7 +7,6 @@ import ( "fmt" "github.com/hashicorp/consul/api" - "github.com/hashicorp/consul/testing/deployer/topology" ) @@ -98,13 +97,6 @@ func tokenForWorkload(wrk *topology.Workload, overridePolicy *api.ACLPolicy, ent } if overridePolicy != nil { token.Policies = []*api.ACLTokenPolicyLink{{ID: overridePolicy.ID}} - } else if wrk.IsV2() { - token.TemplatedPolicies = []*api.ACLTemplatedPolicy{{ - TemplateName: api.ACLTemplatedPolicyWorkloadIdentityName, - TemplateVariables: &api.ACLTemplatedPolicyVariables{ - Name: wrk.WorkloadIdentity, - }, - }} } else { token.ServiceIdentities = []*api.ACLServiceIdentity{{ ServiceName: wrk.ID.Name, diff --git a/testing/deployer/sprawl/boot.go b/testing/deployer/sprawl/boot.go index 908916a113..2840eaf760 100644 --- a/testing/deployer/sprawl/boot.go +++ b/testing/deployer/sprawl/boot.go @@ -13,9 +13,10 @@ import ( "time" retry "github.com/avast/retry-go" - "github.com/hashicorp/consul/api" + "github.com/hashicorp/go-multierror" + "github.com/hashicorp/consul/api" "github.com/hashicorp/consul/testing/deployer/sprawl/internal/build" "github.com/hashicorp/consul/testing/deployer/sprawl/internal/secrets" "github.com/hashicorp/consul/testing/deployer/sprawl/internal/tfgen" @@ -258,8 +259,8 @@ func (s *Sprawl) initConsulServers() error { return fmt.Errorf("error creating final client for cluster=%s: %v", cluster.Name, err) } - // Connect to gRPC as well. - if cluster.EnableV2 { + // Connect to gRPC as well for the resource service. + { s.grpcConns[cluster.Name], s.grpcConnCancel[cluster.Name], err = s.dialServerGRPC(cluster, node, mgmtToken) if err != nil { return fmt.Errorf("error creating gRPC client conn for cluster=%s: %w", cluster.Name, err) @@ -281,11 +282,8 @@ func (s *Sprawl) initConsulServers() error { return fmt.Errorf("populateInitialConfigEntries[%s]: %w", cluster.Name, err) } - if cluster.EnableV2 { - // Resources are available only in V2 - if err := s.populateInitialResources(cluster); err != nil { - return fmt.Errorf("populateInitialResources[%s]: %w", cluster.Name, err) - } + if err := s.populateInitialResources(cluster); err != nil { + return fmt.Errorf("populateInitialResources[%s]: %w", cluster.Name, err) } if err := s.createAnonymousToken(cluster); err != nil { @@ -535,9 +533,6 @@ func (s *Sprawl) waitForLocalWrites(cluster *topology.Cluster, token string) { } func (s *Sprawl) waitForClientAntiEntropyOnce(cluster *topology.Cluster) error { - if cluster.EnableV2 { - return nil // v1 catalog is disabled when v2 catalog is enabled - } var ( client = s.clients[cluster.Name] logger = s.logger.With("cluster", cluster.Name) diff --git a/testing/deployer/sprawl/catalog.go b/testing/deployer/sprawl/catalog.go index bde3c9a266..e8ec68b03d 100644 --- a/testing/deployer/sprawl/catalog.go +++ b/testing/deployer/sprawl/catalog.go @@ -9,14 +9,11 @@ import ( "net/http" "time" - "github.com/hashicorp/consul/api" - pbauth "github.com/hashicorp/consul/proto-public/pbauth/v2beta1" - pbcatalog "github.com/hashicorp/consul/proto-public/pbcatalog/v2beta1" - pbmesh "github.com/hashicorp/consul/proto-public/pbmesh/v2beta1" - "github.com/hashicorp/consul/proto-public/pbresource" "google.golang.org/protobuf/proto" "google.golang.org/protobuf/types/known/anypb" + "github.com/hashicorp/consul/api" + "github.com/hashicorp/consul/proto-public/pbresource" "github.com/hashicorp/consul/testing/deployer/topology" "github.com/hashicorp/consul/testing/deployer/util" ) @@ -49,9 +46,6 @@ func (s *Sprawl) registerServicesToAgents(cluster *topology.Cluster) error { if !node.IsAgent() { continue } - if node.IsV2() { - panic("don't call this") - } agentClient, err := util.ProxyAPIClient( node.LocalProxyPort(), @@ -82,9 +76,6 @@ func (s *Sprawl) registerAgentService( if !node.IsAgent() { panic("called wrong method type") } - if node.IsV2() { - panic("don't call this") - } if wrk.IsMeshGateway { return nil // handled at startup time for agent-ful, but won't be for agent-less @@ -107,19 +98,19 @@ func (s *Sprawl) registerAgentService( if !wrk.DisableServiceMesh { var upstreams []api.Upstream - for _, dest := range wrk.Destinations { + for _, us := range wrk.Upstreams { uAPI := api.Upstream{ - DestinationPeer: dest.Peer, - DestinationName: dest.ID.Name, - LocalBindAddress: dest.LocalAddress, - LocalBindPort: dest.LocalPort, + DestinationPeer: us.Peer, + DestinationName: us.ID.Name, + LocalBindAddress: us.LocalAddress, + LocalBindPort: us.LocalPort, // Config map[string]interface{} `json:",omitempty" bexpr:"-"` // MeshGateway MeshGatewayConfig `json:",omitempty"` } if cluster.Enterprise { - uAPI.DestinationNamespace = dest.ID.Namespace - if dest.Peer == "" { - uAPI.DestinationPartition = dest.ID.Partition + uAPI.DestinationNamespace = us.ID.Namespace + if us.Peer == "" { + uAPI.DestinationPartition = us.ID.Partition } } upstreams = append(upstreams, uAPI) @@ -179,65 +170,14 @@ RETRY: // syncWorkloadsForDataplaneInstances register/deregister services in the given cluster func (s *Sprawl) syncWorkloadsForDataplaneInstances(cluster *topology.Cluster) error { - identityInfo := make(map[topology.ID]*Resource[*pbauth.WorkloadIdentity]) - // registerWorkloadToNode is called when node is not disabled registerWorkloadToNode := func(node *topology.Node, wrk *topology.Workload) error { - if node.IsV2() { - pending := workloadInstanceToResources(node, wrk) - - workloadID := topology.NewID(wrk.WorkloadIdentity, wrk.ID.Namespace, wrk.ID.Partition) - if _, ok := identityInfo[workloadID]; !ok { - identityInfo[workloadID] = pending.WorkloadIdentity - } - - // Write workload - res, err := pending.Workload.Build() - if err != nil { - return fmt.Errorf("error serializing resource %s: %w", util.IDToString(pending.Workload.Resource.Id), err) - } - workload, err := s.writeResource(cluster, res) - if err != nil { - return err - } - // Write check linked to workload - for _, check := range pending.HealthStatuses { - check.Resource.Owner = workload.Id - res, err := check.Build() - if err != nil { - return fmt.Errorf("error serializing resource %s: %w", util.IDToString(check.Resource.Id), err) - } - if _, err := s.writeResource(cluster, res); err != nil { - return err - } - } - // maybe write destinations - if pending.Destinations != nil { - res, err := pending.Destinations.Build() - if err != nil { - return fmt.Errorf("error serializing resource %s: %w", util.IDToString(pending.Destinations.Resource.Id), err) - } - if _, err := s.writeResource(cluster, res); err != nil { - return err - } - } - if pending.ProxyConfiguration != nil { - res, err := pending.ProxyConfiguration.Build() - if err != nil { - return fmt.Errorf("error serializing resource %s: %w", util.IDToString(pending.ProxyConfiguration.Resource.Id), err) - } - if _, err := s.writeResource(cluster, res); err != nil { - return err - } - } - } else { - if err := s.registerCatalogServiceV1(cluster, node, wrk); err != nil { - return fmt.Errorf("error registering service: %w", err) - } - if !wrk.DisableServiceMesh { - if err := s.registerCatalogSidecarServiceV1(cluster, node, wrk); err != nil { - return fmt.Errorf("error registering sidecar service: %w", err) - } + if err := s.registerCatalogServiceV1(cluster, node, wrk); err != nil { + return fmt.Errorf("error registering service: %w", err) + } + if !wrk.DisableServiceMesh { + if err := s.registerCatalogSidecarServiceV1(cluster, node, wrk); err != nil { + return fmt.Errorf("error registering sidecar service: %w", err) } } return nil @@ -245,17 +185,12 @@ func (s *Sprawl) syncWorkloadsForDataplaneInstances(cluster *topology.Cluster) e // deregisterWorkloadFromNode is called when node is disabled deregisterWorkloadFromNode := func(node *topology.Node, wrk *topology.Workload) error { - if node.IsV2() { - // TODO: implement deregister workload for v2 - panic("deregister workload is not implemented for V2") - } else { - if err := s.deregisterCatalogServiceV1(cluster, node, wrk); err != nil { - return fmt.Errorf("error deregistering service: %w", err) - } - if !wrk.DisableServiceMesh { - if err := s.deregisterCatalogSidecarServiceV1(cluster, node, wrk); err != nil { - return fmt.Errorf("error deregistering sidecar service: %w", err) - } + if err := s.deregisterCatalogServiceV1(cluster, node, wrk); err != nil { + return fmt.Errorf("error deregistering service: %w", err) + } + if !wrk.DisableServiceMesh { + if err := s.deregisterCatalogSidecarServiceV1(cluster, node, wrk); err != nil { + return fmt.Errorf("error deregistering sidecar service: %w", err) } } return nil @@ -299,42 +234,6 @@ func (s *Sprawl) syncWorkloadsForDataplaneInstances(cluster *topology.Cluster) e } } - if cluster.EnableV2 { - for _, identity := range identityInfo { - res, err := identity.Build() - if err != nil { - return fmt.Errorf("error serializing resource %s: %w", util.IDToString(identity.Resource.Id), err) - } - if _, err := s.writeResource(cluster, res); err != nil { - return err - } - } - - for id, svcData := range cluster.Services { - svcInfo := &Resource[*pbcatalog.Service]{ - Resource: &pbresource.Resource{ - Id: &pbresource.ID{ - Type: pbcatalog.ServiceType, - Name: id.Name, - Tenancy: &pbresource.Tenancy{ - Partition: id.Partition, - Namespace: id.Namespace, - }, - }, - }, - Data: svcData, - } - - res, err := svcInfo.Build() - if err != nil { - return fmt.Errorf("error serializing resource %s: %w", util.IDToString(svcInfo.Resource.Id), err) - } - if _, err := s.writeResource(cluster, res); err != nil { - return err - } - } - } - return nil } @@ -342,9 +241,6 @@ func (s *Sprawl) registerCatalogNode( cluster *topology.Cluster, node *topology.Node, ) error { - if node.IsV2() { - return s.registerCatalogNodeV2(cluster, node) - } return s.registerCatalogNodeV1(cluster, node) } @@ -352,49 +248,9 @@ func (s *Sprawl) deregisterCatalogNode( cluster *topology.Cluster, node *topology.Node, ) error { - if node.IsV2() { - panic("deregister V2 node is not implemented") - } return s.deregisterCatalogNodeV1(cluster, node) } -func (s *Sprawl) registerCatalogNodeV2( - cluster *topology.Cluster, - node *topology.Node, -) error { - if !node.IsDataplane() { - panic("called wrong method type") - } - - nodeRes := &Resource[*pbcatalog.Node]{ - Resource: &pbresource.Resource{ - Id: &pbresource.ID{ - Type: pbcatalog.NodeType, - Name: node.PodName(), - Tenancy: &pbresource.Tenancy{ - Partition: node.Partition, - }, - }, - Metadata: map[string]string{ - "dataplane-faux": "1", - }, - }, - Data: &pbcatalog.Node{ - Addresses: []*pbcatalog.NodeAddress{ - {Host: node.LocalAddress()}, - }, - }, - } - - res, err := nodeRes.Build() - if err != nil { - return err - } - - _, err = s.writeResource(cluster, res) - return err -} - func (s *Sprawl) writeResource(cluster *topology.Cluster, res *pbresource.Resource) (*pbresource.Resource, error) { var ( client = s.getResourceClient(cluster.Name) @@ -505,9 +361,6 @@ func (s *Sprawl) deregisterCatalogServiceV1( if !node.IsDataplane() { panic("called wrong method type") } - if node.IsV2() { - panic("don't call this") - } var ( client = s.clients[cluster.Name] @@ -543,9 +396,6 @@ func (s *Sprawl) registerCatalogServiceV1( if !node.IsDataplane() { panic("called wrong method type") } - if node.IsV2() { - panic("don't call this") - } var ( client = s.clients[cluster.Name] @@ -582,9 +432,6 @@ func (s *Sprawl) deregisterCatalogSidecarServiceV1( if wrk.DisableServiceMesh { panic("not valid") } - if node.IsV2() { - panic("don't call this") - } var ( client = s.clients[cluster.Name] @@ -626,9 +473,6 @@ func (s *Sprawl) registerCatalogSidecarServiceV1( if wrk.DisableServiceMesh { panic("not valid") } - if node.IsV2() { - panic("don't call this") - } var ( client = s.clients[cluster.Name] @@ -667,172 +511,11 @@ func (r *Resource[V]) Build() (*pbresource.Resource, error) { return r.Resource, nil } -type ServiceResources struct { - Workload *Resource[*pbcatalog.Workload] - HealthStatuses []*Resource[*pbcatalog.HealthStatus] - Destinations *Resource[*pbmesh.Destinations] - WorkloadIdentity *Resource[*pbauth.WorkloadIdentity] - ProxyConfiguration *Resource[*pbmesh.ProxyConfiguration] -} - -func workloadInstanceToResources( - node *topology.Node, - wrk *topology.Workload, -) *ServiceResources { - if wrk.IsMeshGateway { - panic("v2 does not yet support mesh gateways") - } - - tenancy := &pbresource.Tenancy{ - Partition: wrk.ID.Partition, - Namespace: wrk.ID.Namespace, - } - - var ( - wlPorts = map[string]*pbcatalog.WorkloadPort{} - ) - for name, port := range wrk.Ports { - wlPorts[name] = &pbcatalog.WorkloadPort{ - Port: uint32(port.Number), - Protocol: port.ActualProtocol, - } - } - - var ( - selector = &pbcatalog.WorkloadSelector{ - Names: []string{wrk.Workload}, - } - - workloadRes = &Resource[*pbcatalog.Workload]{ - Resource: &pbresource.Resource{ - Id: &pbresource.ID{ - Type: pbcatalog.WorkloadType, - Name: wrk.Workload, - Tenancy: tenancy, - }, - Metadata: wrk.Meta, - }, - Data: &pbcatalog.Workload{ - NodeName: node.PodName(), - Identity: wrk.WorkloadIdentity, - Ports: wlPorts, - Addresses: []*pbcatalog.WorkloadAddress{ - {Host: node.LocalAddress()}, - }, - }, - } - workloadIdentityRes = &Resource[*pbauth.WorkloadIdentity]{ - Resource: &pbresource.Resource{ - Id: &pbresource.ID{ - Type: pbauth.WorkloadIdentityType, - Name: wrk.WorkloadIdentity, - Tenancy: tenancy, - }, - }, - Data: &pbauth.WorkloadIdentity{}, - } - - healthResList []*Resource[*pbcatalog.HealthStatus] - destinationsRes *Resource[*pbmesh.Destinations] - proxyConfigRes *Resource[*pbmesh.ProxyConfiguration] - ) - - if wrk.HasCheck() { - // TODO: needs ownerId - checkRes := &Resource[*pbcatalog.HealthStatus]{ - Resource: &pbresource.Resource{ - Id: &pbresource.ID{ - Type: pbcatalog.HealthStatusType, - Name: wrk.Workload + "-check-0", - Tenancy: tenancy, - }, - }, - Data: &pbcatalog.HealthStatus{ - Type: "external-sync", - Status: pbcatalog.Health_HEALTH_PASSING, - }, - } - - healthResList = []*Resource[*pbcatalog.HealthStatus]{checkRes} - } - - if node.HasPublicAddress() { - workloadRes.Data.Addresses = append(workloadRes.Data.Addresses, - &pbcatalog.WorkloadAddress{Host: node.PublicAddress(), External: true}, - ) - } - - if !wrk.DisableServiceMesh { - destinationsRes = &Resource[*pbmesh.Destinations]{ - Resource: &pbresource.Resource{ - Id: &pbresource.ID{ - Type: pbmesh.DestinationsType, - Name: wrk.Workload, - Tenancy: tenancy, - }, - }, - Data: &pbmesh.Destinations{ - Workloads: selector, - }, - } - - for _, dest := range wrk.Destinations { - meshDest := &pbmesh.Destination{ - DestinationRef: &pbresource.Reference{ - Type: pbcatalog.ServiceType, - Name: dest.ID.Name, - Tenancy: &pbresource.Tenancy{ - Partition: dest.ID.Partition, - Namespace: dest.ID.Namespace, - }, - }, - DestinationPort: dest.PortName, - ListenAddr: &pbmesh.Destination_IpPort{ - IpPort: &pbmesh.IPPortAddress{ - Ip: dest.LocalAddress, - Port: uint32(dest.LocalPort), - }, - }, - } - destinationsRes.Data.Destinations = append(destinationsRes.Data.Destinations, meshDest) - } - - if wrk.EnableTransparentProxy { - proxyConfigRes = &Resource[*pbmesh.ProxyConfiguration]{ - Resource: &pbresource.Resource{ - Id: &pbresource.ID{ - Type: pbmesh.ProxyConfigurationType, - Name: wrk.Workload, - Tenancy: tenancy, - }, - }, - Data: &pbmesh.ProxyConfiguration{ - Workloads: selector, - DynamicConfig: &pbmesh.DynamicConfig{ - Mode: pbmesh.ProxyMode_PROXY_MODE_TRANSPARENT, - }, - }, - } - } - } - - return &ServiceResources{ - Workload: workloadRes, - HealthStatuses: healthResList, - Destinations: destinationsRes, - WorkloadIdentity: workloadIdentityRes, - ProxyConfiguration: proxyConfigRes, - } -} - func workloadToCatalogRegistration( cluster *topology.Cluster, node *topology.Node, wrk *topology.Workload, ) *api.CatalogRegistration { - if node.IsV2() { - panic("don't call this") - } reg := &api.CatalogRegistration{ Node: node.PodName(), SkipNodeUpdate: true, @@ -921,9 +604,6 @@ func workloadToSidecarCatalogRegistration( node *topology.Node, wrk *topology.Workload, ) (topology.ID, *api.CatalogRegistration) { - if node.IsV2() { - panic("don't call this") - } pid := wrk.ID pid.Name += "-sidecar-proxy" reg := &api.CatalogRegistration{ @@ -970,17 +650,17 @@ func workloadToSidecarCatalogRegistration( reg.Checks[0].Partition = pid.Partition } - for _, dest := range wrk.Destinations { + for _, us := range wrk.Upstreams { pu := api.Upstream{ - DestinationName: dest.ID.Name, - DestinationPeer: dest.Peer, - LocalBindAddress: dest.LocalAddress, - LocalBindPort: dest.LocalPort, + DestinationName: us.ID.Name, + DestinationPeer: us.Peer, + LocalBindAddress: us.LocalAddress, + LocalBindPort: us.LocalPort, } if cluster.Enterprise { - pu.DestinationNamespace = dest.ID.Namespace - if dest.Peer == "" { - pu.DestinationPartition = dest.ID.Partition + pu.DestinationNamespace = us.ID.Namespace + if us.Peer == "" { + pu.DestinationPartition = us.ID.Partition } } reg.Service.Proxy.Upstreams = append(reg.Service.Proxy.Upstreams, pu) diff --git a/testing/deployer/sprawl/details.go b/testing/deployer/sprawl/details.go index 4fde28bed2..f4f91f8d74 100644 --- a/testing/deployer/sprawl/details.go +++ b/testing/deployer/sprawl/details.go @@ -13,6 +13,7 @@ import ( "time" retry "github.com/avast/retry-go" + "github.com/hashicorp/consul/api" ) @@ -86,15 +87,10 @@ func (s *Sprawl) PrintDetails() error { Service: wrk.ID.String(), }) } else { - ports := make(map[string]int) - for name, port := range wrk.Ports { - ports[name] = node.ExposedPort(port.Number) - } cd.Apps = append(cd.Apps, appDetail{ Type: "app", Container: node.DockerName(), ExposedPort: node.ExposedPort(wrk.Port), - ExposedPorts: ports, ExposedEnvoyAdminPort: node.ExposedPort(wrk.EnvoyAdminPort), Addresses: addrs, Service: wrk.ID.String(), @@ -142,17 +138,7 @@ func (s *Sprawl) PrintDetails() error { if d.Type == "server" && d.Container == cluster.Leader { d.Type = "leader" } - var portStr string - if len(d.ExposedPorts) > 0 { - var out []string - for name, exposed := range d.ExposedPorts { - out = append(out, fmt.Sprintf("app:%s=%d", name, exposed)) - } - sort.Strings(out) - portStr = strings.Join(out, " ") - } else { - portStr = "app=" + strconv.Itoa(d.ExposedPort) - } + portStr := "app=" + strconv.Itoa(d.ExposedPort) if d.ExposedEnvoyAdminPort > 0 { portStr += " envoy=" + strconv.Itoa(d.ExposedEnvoyAdminPort) } @@ -191,9 +177,8 @@ type appDetail struct { Type string // server|mesh-gateway|app Container string Addresses []string - ExposedPort int `json:",omitempty"` - ExposedPorts map[string]int `json:",omitempty"` - ExposedEnvoyAdminPort int `json:",omitempty"` + ExposedPort int `json:",omitempty"` + ExposedEnvoyAdminPort int `json:",omitempty"` // just services Service string `json:",omitempty"` } diff --git a/testing/deployer/sprawl/internal/build/docker.go b/testing/deployer/sprawl/internal/build/docker.go index 53baa07ae7..bb24047154 100644 --- a/testing/deployer/sprawl/internal/build/docker.go +++ b/testing/deployer/sprawl/internal/build/docker.go @@ -102,7 +102,7 @@ func DockerImages( built := make(map[string]struct{}) for _, c := range t.Clusters { for _, n := range c.Nodes { - needsTproxy := n.NeedsTransparentProxy() + const needsTproxy = false // TODO: see if we can bring this back for v1 CDP joint := n.Images.EnvoyConsulImage() if _, ok := built[joint]; joint != "" && !ok { diff --git a/testing/deployer/sprawl/internal/tfgen/agent.go b/testing/deployer/sprawl/internal/tfgen/agent.go index 58bd564e64..efd8589525 100644 --- a/testing/deployer/sprawl/internal/tfgen/agent.go +++ b/testing/deployer/sprawl/internal/tfgen/agent.go @@ -13,7 +13,7 @@ import ( "github.com/hashicorp/consul/testing/deployer/topology" ) -func (g *Generator) generateAgentHCL(node *topology.Node, enableV2, enableV2Tenancy bool) string { +func (g *Generator) generateAgentHCL(node *topology.Node) string { if !node.IsAgent() { panic("generateAgentHCL only applies to agents") } @@ -41,17 +41,6 @@ func (g *Generator) generateAgentHCL(node *topology.Node, enableV2, enableV2Tena b.add("enable_debug", true) b.add("use_streaming_backend", true) - var experiments []string - if enableV2 { - experiments = append(experiments, "resource-apis") - } - if enableV2Tenancy { - experiments = append(experiments, "v2tenancy") - } - if len(experiments) > 0 { - b.addSlice("experiments", experiments) - } - // speed up leaves b.addBlock("performance", func() { b.add("leave_drain_time", "50ms") diff --git a/testing/deployer/sprawl/internal/tfgen/dns.go b/testing/deployer/sprawl/internal/tfgen/dns.go index 9b03693c83..73ea5f388d 100644 --- a/testing/deployer/sprawl/internal/tfgen/dns.go +++ b/testing/deployer/sprawl/internal/tfgen/dns.go @@ -8,11 +8,8 @@ import ( "fmt" "os" "path/filepath" - "sort" "strings" - "golang.org/x/exp/maps" - "github.com/hashicorp/consul/testing/deployer/topology" "github.com/hashicorp/consul/testing/deployer/util" ) @@ -66,22 +63,6 @@ func (g *Generator) writeCoreDNSFiles(net *topology.Network, dnsIPAddress string } } - // Until Consul DNS understands v2, simulate it. - // - // NOTE: this DNS is not quite what consul normally does. It's simpler - // to simulate this format here. - virtualNames := make(map[string][]string) - for id, svcData := range cluster.Services { - if len(svcData.VirtualIps) == 0 { - continue - } - vips := svcData.VirtualIps - - // ----.virtual. - name := fmt.Sprintf("%s--%s--%s", id.Name, id.Namespace, id.Partition) - virtualNames[name] = vips - } - var ( clusterDNSName = cluster.Name + "-consulcluster.lan" virtualDNSName = "virtual.consul" @@ -132,7 +113,6 @@ func (g *Generator) writeCoreDNSFiles(net *topology.Network, dnsIPAddress string generateCoreDNSVirtualZoneFile( dnsIPAddress, virtualDNSName, - virtualNames, ), virtualZonefilePath, 0644, @@ -230,7 +210,6 @@ server IN A %s ; Consul server func generateCoreDNSVirtualZoneFile( dnsIPAddress string, virtualDNSName string, - nameToAddr map[string][]string, ) []byte { var buf bytes.Buffer buf.WriteString(fmt.Sprintf(` @@ -247,17 +226,5 @@ $ORIGIN %[1]s. ns IN A %[2]s ; self `, virtualDNSName, dnsIPAddress)) - names := maps.Keys(nameToAddr) - sort.Strings(names) - - for _, name := range names { - vips := nameToAddr[name] - for _, vip := range vips { - buf.WriteString(fmt.Sprintf(` -%s IN A %s ; Consul server -`, name, vip)) - } - } - return buf.Bytes() } diff --git a/testing/deployer/sprawl/internal/tfgen/gen.go b/testing/deployer/sprawl/internal/tfgen/gen.go index 7985cff774..0f5f74df28 100644 --- a/testing/deployer/sprawl/internal/tfgen/gen.go +++ b/testing/deployer/sprawl/internal/tfgen/gen.go @@ -262,9 +262,6 @@ func (g *Generator) Generate(step Step) error { addImage("", node.Images.Consul) addImage("", node.Images.EnvoyConsulImage()) addImage("", node.Images.LocalDataplaneImage()) - if node.NeedsTransparentProxy() { - addImage("", node.Images.LocalDataplaneTProxyImage()) - } if node.IsAgent() { addVolume(node.DockerName()) diff --git a/testing/deployer/sprawl/internal/tfgen/nodes.go b/testing/deployer/sprawl/internal/tfgen/nodes.go index 8ef8f10199..06f37453a4 100644 --- a/testing/deployer/sprawl/internal/tfgen/nodes.go +++ b/testing/deployer/sprawl/internal/tfgen/nodes.go @@ -67,7 +67,7 @@ func (g *Generator) generateNodeContainers( }{ terraformPod: pod, ImageResource: DockerImageResourceName(node.Images.Consul), - HCL: g.generateAgentHCL(node, cluster.EnableV2 && node.IsServer(), cluster.EnableV2Tenancy && node.IsServer()), + HCL: g.generateAgentHCL(node), EnterpriseLicense: g.license, })) } @@ -125,11 +125,7 @@ func (g *Generator) generateNodeContainers( var img string if node.IsDataplane() { tmpl = tfAppDataplaneT - if wrk.EnableTransparentProxy { - img = DockerImageResourceName(node.Images.LocalDataplaneTProxyImage()) - } else { - img = DockerImageResourceName(node.Images.LocalDataplaneImage()) - } + img = DockerImageResourceName(node.Images.LocalDataplaneImage()) } else { img = DockerImageResourceName(node.Images.EnvoyConsulImage()) } diff --git a/testing/deployer/sprawl/internal/tfgen/templates/container-app-dataplane.tf.tmpl b/testing/deployer/sprawl/internal/tfgen/templates/container-app-dataplane.tf.tmpl index a72bd21bbf..9a65c3426a 100644 --- a/testing/deployer/sprawl/internal/tfgen/templates/container-app-dataplane.tf.tmpl +++ b/testing/deployer/sprawl/internal/tfgen/templates/container-app-dataplane.tf.tmpl @@ -17,39 +17,20 @@ resource "docker_container" "{{.Node.DockerName}}-{{.Workload.ID.TFString}}-side read_only = true } -{{ if .Workload.EnableTransparentProxy }} - capabilities { - add = ["NET_ADMIN"] - } - entrypoint = [ "/bin/tproxy-startup.sh" ] -{{ end }} - env = [ "DP_CONSUL_ADDRESSES=server.{{.Node.Cluster}}-consulcluster.lan", -{{ if .Node.IsV2 }} - "DP_PROXY_ID={{.Workload.Workload}}", -{{ if .Enterprise }} - "DP_PROXY_NAMESPACE={{.Workload.ID.Namespace}}", - "DP_PROXY_PARTITION={{.Workload.ID.Partition}}", -{{ end }} -{{ else }} "DP_SERVICE_NODE_NAME={{.Node.PodName}}", "DP_PROXY_SERVICE_ID={{.Workload.ID.Name}}-sidecar-proxy", {{ if .Enterprise }} "DP_SERVICE_NAMESPACE={{.Workload.ID.Namespace}}", "DP_SERVICE_PARTITION={{.Workload.ID.Partition}}", {{ end }} -{{ end }} {{ if .Token }} "DP_CREDENTIAL_TYPE=static", "DP_CREDENTIAL_STATIC_TOKEN={{.Token}}", {{ end }} -{{ if .Workload.EnableTransparentProxy }} - "REDIRECT_TRAFFIC_ARGS=-exclude-inbound-port=19000", -{{ end }} - // for demo purposes "DP_ENVOY_ADMIN_BIND_ADDRESS=0.0.0.0", "DP_ENVOY_ADMIN_BIND_PORT=19000", diff --git a/testing/deployer/sprawl/sprawltest/test_test.go b/testing/deployer/sprawl/sprawltest/test_test.go index 30ebfc181f..84fc5ecbfd 100644 --- a/testing/deployer/sprawl/sprawltest/test_test.go +++ b/testing/deployer/sprawl/sprawltest/test_test.go @@ -12,147 +12,10 @@ import ( "github.com/stretchr/testify/require" "github.com/hashicorp/consul/api" - pbauth "github.com/hashicorp/consul/proto-public/pbauth/v2beta1" - pbcatalog "github.com/hashicorp/consul/proto-public/pbcatalog/v2beta1" - pbmesh "github.com/hashicorp/consul/proto-public/pbmesh/v2beta1" - "github.com/hashicorp/consul/proto-public/pbresource" "github.com/hashicorp/consul/testing/deployer/sprawl/sprawltest" "github.com/hashicorp/consul/testing/deployer/topology" ) -func TestSprawl_CatalogV2(t *testing.T) { - serversDC1 := newTopologyServerSet("dc1-server", 3, []string{"dc1", "wan"}, nil) - - cfg := &topology.Config{ - Images: topology.Images{ - ConsulCE: "hashicorppreview/consul:1.17-dev", - ConsulEnterprise: "hashicorppreview/consul-enterprise:1.17-dev", - Dataplane: "hashicorppreview/consul-dataplane:1.3-dev", - }, - Networks: []*topology.Network{ - {Name: "dc1"}, - {Name: "wan", Type: "wan"}, - }, - Clusters: []*topology.Cluster{ - { - Enterprise: true, - Name: "dc1", - Nodes: topology.MergeSlices(serversDC1, []*topology.Node{ - { - Kind: topology.NodeKindDataplane, - Version: topology.NodeVersionV2, - Name: "dc1-client1", - Workloads: []*topology.Workload{ - { - ID: topology.ID{Name: "ping"}, - Image: "rboyer/pingpong:latest", - Port: 8080, - EnvoyAdminPort: 19000, - Command: []string{ - "-bind", "0.0.0.0:8080", - "-dial", "127.0.0.1:9090", - "-pong-chaos", - "-dialfreq", "250ms", - "-name", "ping", - }, - Destinations: []*topology.Destination{{ - ID: topology.ID{Name: "pong"}, - LocalPort: 9090, - }}, - }, - }, - }, - { - Kind: topology.NodeKindDataplane, - Version: topology.NodeVersionV2, - Name: "dc1-client2", - Workloads: []*topology.Workload{ - { - ID: topology.ID{Name: "pong"}, - Image: "rboyer/pingpong:latest", - Port: 8080, - EnvoyAdminPort: 19000, - Command: []string{ - "-bind", "0.0.0.0:8080", - "-dial", "127.0.0.1:9090", - "-pong-chaos", - "-dialfreq", "250ms", - "-name", "pong", - }, - Destinations: []*topology.Destination{{ - ID: topology.ID{Name: "ping"}, - LocalPort: 9090, - }}, - }, - }, - }, - }), - InitialResources: []*pbresource.Resource{ - sprawltest.MustSetResourceData(t, &pbresource.Resource{ - Id: &pbresource.ID{ - Type: pbmesh.HTTPRouteType, - Name: "test-http-route", - }, - }, &pbmesh.HTTPRoute{ - ParentRefs: []*pbmesh.ParentReference{{ - Ref: &pbresource.Reference{ - Type: pbcatalog.ServiceType, - Name: "test", - }, - }}, - }), - sprawltest.MustSetResourceData(t, &pbresource.Resource{ - Id: &pbresource.ID{ - Type: pbauth.TrafficPermissionsType, - Name: "ping-perms", - }, - }, &pbauth.TrafficPermissions{ - Destination: &pbauth.Destination{ - IdentityName: "ping", - }, - Action: pbauth.Action_ACTION_ALLOW, - Permissions: []*pbauth.Permission{{ - Sources: []*pbauth.Source{{ - IdentityName: "pong", - }}, - }}, - }), - sprawltest.MustSetResourceData(t, &pbresource.Resource{ - Id: &pbresource.ID{ - Type: pbauth.TrafficPermissionsType, - Name: "pong-perms", - }, - }, &pbauth.TrafficPermissions{ - Destination: &pbauth.Destination{ - IdentityName: "pong", - }, - Action: pbauth.Action_ACTION_ALLOW, - Permissions: []*pbauth.Permission{{ - Sources: []*pbauth.Source{{ - IdentityName: "ping", - }}, - }}, - }), - }, - }, - }, - } - - sp := sprawltest.Launch(t, cfg) - - for _, cluster := range sp.Topology().Clusters { - leader, err := sp.Leader(cluster.Name) - require.NoError(t, err) - t.Logf("%s: leader = %s", cluster.Name, leader.ID()) - - followers, err := sp.Followers(cluster.Name) - require.NoError(t, err) - for _, f := range followers { - t.Logf("%s: follower = %s", cluster.Name, f.ID()) - } - } -} - func TestSprawl(t *testing.T) { serversDC1 := newTopologyServerSet("dc1-server", 3, []string{"dc1", "wan"}, nil) serversDC2 := newTopologyServerSet("dc2-server", 3, []string{"dc2", "wan"}, nil) @@ -201,7 +64,7 @@ func TestSprawl(t *testing.T) { "-dialfreq", "250ms", "-name", "ping", }, - Destinations: []*topology.Destination{{ + Upstreams: []*topology.Upstream{{ ID: topology.ID{Name: "pong"}, LocalPort: 9090, Peer: "peer-dc2-default", @@ -253,32 +116,7 @@ func TestSprawl(t *testing.T) { "-dialfreq", "250ms", "-name", "pong", }, - Destinations: []*topology.Destination{{ - ID: topology.ID{Name: "ping"}, - LocalPort: 9090, - Peer: "peer-dc1-default", - }}, - }, - }, - }, - { - Kind: topology.NodeKindDataplane, - Version: topology.NodeVersionV2, - Name: "dc2-client3", - Workloads: []*topology.Workload{ - { - ID: topology.ID{Name: "pong"}, - Image: "rboyer/pingpong:latest", - Port: 8080, - EnvoyAdminPort: 19000, - Command: []string{ - "-bind", "0.0.0.0:8080", - "-dial", "127.0.0.1:9090", - "-pong-chaos", - "-dialfreq", "250ms", - "-name", "pong", - }, - Destinations: []*topology.Destination{{ + Upstreams: []*topology.Upstream{{ ID: topology.ID{Name: "ping"}, LocalPort: 9090, Peer: "peer-dc1-default", diff --git a/testing/deployer/topology/compile.go b/testing/deployer/topology/compile.go index 130284f37d..ffed56aaf3 100644 --- a/testing/deployer/topology/compile.go +++ b/testing/deployer/topology/compile.go @@ -17,9 +17,6 @@ import ( "github.com/hashicorp/go-hclog" - pbauth "github.com/hashicorp/consul/proto-public/pbauth/v2beta1" - pbcatalog "github.com/hashicorp/consul/proto-public/pbcatalog/v2beta1" - pbmesh "github.com/hashicorp/consul/proto-public/pbmesh/v2beta1" "github.com/hashicorp/consul/proto-public/pbresource" "github.com/hashicorp/consul/testing/deployer/util" ) @@ -133,22 +130,6 @@ func compile(logger hclog.Logger, raw *Config, prev *Topology, testingID string) return nil, fmt.Errorf("cluster %q has no nodes", c.Name) } - if len(c.Services) == 0 { // always initialize this regardless of v2-ness, because we might late-enable it below - c.Services = make(map[ID]*pbcatalog.Service) - } - - var implicitV2Services bool - if len(c.Services) > 0 { - c.EnableV2 = true - for name, svc := range c.Services { - if svc.Workloads != nil { - return nil, fmt.Errorf("the workloads field for v2 service %q is not user settable", name) - } - } - } else { - implicitV2Services = true - } - if c.TLSVolumeName != "" { return nil, fmt.Errorf("user cannot specify the TLSVolumeName field") } @@ -177,31 +158,17 @@ func compile(logger hclog.Logger, raw *Config, prev *Topology, testingID string) addTenancy(ce.GetPartition(), ce.GetNamespace()) } - if len(c.InitialResources) > 0 { - c.EnableV2 = true - } for _, res := range c.InitialResources { if res.Id.Tenancy == nil { res.Id.Tenancy = &pbresource.Tenancy{} } - // TODO(peering/v2) prevent non-local peer resources res.Id.Tenancy.Partition = PartitionOrDefault(res.Id.Tenancy.Partition) if !util.IsTypePartitionScoped(res.Id.Type) { res.Id.Tenancy.Namespace = NamespaceOrDefault(res.Id.Tenancy.Namespace) } - switch { - case util.EqualType(pbauth.ComputedTrafficPermissionsType, res.Id.GetType()), - util.EqualType(pbauth.WorkloadIdentityType, res.Id.GetType()): - fallthrough - case util.EqualType(pbmesh.ComputedRoutesType, res.Id.GetType()), - util.EqualType(pbmesh.ProxyStateTemplateType, res.Id.GetType()): - fallthrough - case util.EqualType(pbcatalog.HealthChecksType, res.Id.GetType()), - util.EqualType(pbcatalog.HealthStatusType, res.Id.GetType()), - util.EqualType(pbcatalog.NodeType, res.Id.GetType()), - util.EqualType(pbcatalog.ServiceEndpointsType, res.Id.GetType()), - util.EqualType(pbcatalog.WorkloadType, res.Id.GetType()): + // TODO: if we reintroduce new resources for v1, allow them here + if true { return nil, fmt.Errorf("you should not create a resource of type %q this way", util.TypeToString(res.Id.Type)) } @@ -222,20 +189,6 @@ func compile(logger hclog.Logger, raw *Config, prev *Topology, testingID string) return nil, fmt.Errorf("cluster %q node %q has invalid kind: %s", c.Name, n.Name, n.Kind) } - if n.Version == NodeVersionUnknown { - n.Version = NodeVersionV1 - } - switch n.Version { - case NodeVersionV1: - case NodeVersionV2: - if n.Kind == NodeKindClient { - return nil, fmt.Errorf("v2 does not support client agents at this time") - } - c.EnableV2 = true - default: - return nil, fmt.Errorf("cluster %q node %q has invalid version: %s", c.Name, n.Name, n.Version) - } - n.Partition = PartitionOrDefault(n.Partition) if !IsValidLabel(n.Partition) { return nil, fmt.Errorf("node partition is not valid: %s", n.Partition) @@ -318,12 +271,6 @@ func compile(logger hclog.Logger, raw *Config, prev *Topology, testingID string) return nil, fmt.Errorf("cluster %q node %q has more than one public address", c.Name, n.Name) } - if len(n.Services) > 0 { - logger.Warn("please use Node.Workloads instead of Node.Services") - n.Workloads = append(n.Workloads, n.Services...) - n.Services = nil - } - if n.IsDataplane() && len(n.Workloads) > 1 { // Our use of consul-dataplane here is supposed to mimic that // of consul-k8s, which ultimately has one IP per Service, so @@ -344,10 +291,6 @@ func compile(logger hclog.Logger, raw *Config, prev *Topology, testingID string) // Denormalize wrk.Node = n - wrk.NodeVersion = n.Version - if n.IsV2() { - wrk.Workload = wrk.ID.Name + "-" + n.Name - } if !IsValidLabel(wrk.ID.Partition) { return nil, fmt.Errorf("service partition is not valid: %s", wrk.ID.Partition) @@ -404,136 +347,42 @@ func compile(logger hclog.Logger, raw *Config, prev *Topology, testingID string) // return nil, fmt.Errorf("service has invalid protocol: %s", wrk.Protocol) // } - defaultDestination := func(dest *Destination) error { + defaultUpstream := func(us *Upstream) error { // Default to that of the enclosing service. - if dest.Peer == "" { - if dest.ID.Partition == "" { - dest.ID.Partition = wrk.ID.Partition + if us.Peer == "" { + if us.ID.Partition == "" { + us.ID.Partition = wrk.ID.Partition } - if dest.ID.Namespace == "" { - dest.ID.Namespace = wrk.ID.Namespace + if us.ID.Namespace == "" { + us.ID.Namespace = wrk.ID.Namespace } } else { - if dest.ID.Partition != "" { - dest.ID.Partition = "" // irrelevant here; we'll set it to the value of the OTHER side for plumbing purposes in tests + if us.ID.Partition != "" { + us.ID.Partition = "" // irrelevant here; we'll set it to the value of the OTHER side for plumbing purposes in tests } - dest.ID.Namespace = NamespaceOrDefault(dest.ID.Namespace) - foundPeerNames[dest.Peer] = struct{}{} + us.ID.Namespace = NamespaceOrDefault(us.ID.Namespace) + foundPeerNames[us.Peer] = struct{}{} } - addTenancy(dest.ID.Partition, dest.ID.Namespace) + addTenancy(us.ID.Partition, us.ID.Namespace) - if dest.Implied { - if dest.PortName == "" { - return fmt.Errorf("implicit destinations must use port names in v2") - } - } else { - if dest.LocalAddress == "" { - // v1 defaults to 127.0.0.1 but v2 does not. Safe to do this generally though. - dest.LocalAddress = "127.0.0.1" - } - if dest.PortName != "" && n.IsV1() { - return fmt.Errorf("explicit destinations cannot use port names in v1") - } - if dest.PortName == "" && n.IsV2() { - // Assume this is a v1->v2 conversion and name it. - dest.PortName = V1DefaultPortName - } + if us.LocalAddress == "" { + // v1 consul code defaults this to 127.0.0.1, but safer to not rely upon that. + us.LocalAddress = "127.0.0.1" } return nil } - for _, dest := range wrk.Destinations { - if err := defaultDestination(dest); err != nil { + for _, us := range wrk.Upstreams { + if err := defaultUpstream(us); err != nil { return nil, err } } - if n.IsV2() { - for _, dest := range wrk.ImpliedDestinations { - dest.Implied = true - if err := defaultDestination(dest); err != nil { - return nil, err - } - } - } else { - if len(wrk.ImpliedDestinations) > 0 { - return nil, fmt.Errorf("v1 does not support implied destinations yet") - } - } - if err := wrk.Validate(); err != nil { return nil, fmt.Errorf("cluster %q node %q service %q is not valid: %w", c.Name, n.Name, wrk.ID.String(), err) } - - if wrk.EnableTransparentProxy && !n.IsDataplane() { - return nil, fmt.Errorf("cannot enable tproxy on a non-dataplane node") - } - - if n.IsV2() { - if implicitV2Services { - wrk.V2Services = []string{wrk.ID.Name} - - var svcPorts []*pbcatalog.ServicePort - for name, cfg := range wrk.Ports { - svcPorts = append(svcPorts, &pbcatalog.ServicePort{ - TargetPort: name, - Protocol: cfg.ActualProtocol, - }) - } - sort.Slice(svcPorts, func(i, j int) bool { - a, b := svcPorts[i], svcPorts[j] - if a.TargetPort < b.TargetPort { - return true - } else if a.TargetPort > b.TargetPort { - return false - } - return a.Protocol < b.Protocol - }) - - v2svc := &pbcatalog.Service{ - Workloads: &pbcatalog.WorkloadSelector{}, - Ports: svcPorts, - } - - prev, ok := c.Services[wrk.ID] - if !ok { - c.Services[wrk.ID] = v2svc - prev = v2svc - } - if prev.Workloads == nil { - prev.Workloads = &pbcatalog.WorkloadSelector{} - } - prev.Workloads.Names = append(prev.Workloads.Names, wrk.Workload) - - } else { - for _, name := range wrk.V2Services { - v2ID := NewServiceID(name, wrk.ID.Namespace, wrk.ID.Partition) - - v2svc, ok := c.Services[v2ID] - if !ok { - return nil, fmt.Errorf("cluster %q node %q service %q has a v2 service reference that does not exist %q", - c.Name, n.Name, wrk.ID.String(), name) - } - if v2svc.Workloads == nil { - v2svc.Workloads = &pbcatalog.WorkloadSelector{} - } - v2svc.Workloads.Names = append(v2svc.Workloads.Names, wrk.Workload) - } - } - - if wrk.WorkloadIdentity == "" { - wrk.WorkloadIdentity = wrk.ID.Name - } - } else { - if len(wrk.V2Services) > 0 { - return nil, fmt.Errorf("cannot specify v2 services for v1") - } - if wrk.WorkloadIdentity != "" { - return nil, fmt.Errorf("cannot specify workload identities for v1") - } - } } return foundPeerNames, nil } @@ -553,53 +402,6 @@ func compile(logger hclog.Logger, raw *Config, prev *Topology, testingID string) maps.Copy(foundPeerNames, peerNames) } - // Default anything in the toplevel services map. - for _, svc := range c.Services { - for _, port := range svc.Ports { - if port.Protocol == pbcatalog.Protocol_PROTOCOL_UNSPECIFIED { - port.Protocol = pbcatalog.Protocol_PROTOCOL_TCP - } - } - } - - if err := assignVirtualIPs(c); err != nil { - return nil, err - } - - if c.EnableV2 { - // Populate the VirtualPort field on all destinations. - for _, n := range c.Nodes { - for _, wrk := range n.Workloads { - for _, dest := range wrk.ImpliedDestinations { - res, ok := c.Services[dest.ID] - if ok { - for _, sp := range res.Ports { - if sp.Protocol == pbcatalog.Protocol_PROTOCOL_MESH { - continue - } - if sp.MatchesPortId(dest.PortName) { - dest.VirtualPort = sp.VirtualPort - } - } - } - } - for _, dest := range wrk.Destinations { - res, ok := c.Services[dest.ID] - if ok { - for _, sp := range res.Ports { - if sp.Protocol == pbcatalog.Protocol_PROTOCOL_MESH { - continue - } - if sp.MatchesPortId(dest.PortName) { - dest.VirtualPort = sp.VirtualPort - } - } - } - } - } - } - } - // Explode this into the explicit list based on stray references made. c.Partitions = nil for ap, nsMap := range tenancies { @@ -723,40 +525,25 @@ func compile(logger hclog.Logger, raw *Config, prev *Topology, testingID string) } } - // after we decoded the peering stuff, we can fill in some computed data in the destinations + // after we decoded the peering stuff, we can fill in some computed data in the upstreams for _, c := range clusters { c.Peerings = clusteredPeerings[c.Name] for _, n := range c.Nodes { for _, wrk := range n.Workloads { - for _, dest := range wrk.Destinations { - if dest.Peer == "" { - dest.Cluster = c.Name - dest.Peering = nil + for _, us := range wrk.Upstreams { + if us.Peer == "" { + us.Cluster = c.Name + us.Peering = nil continue } - remotePeer, ok := c.Peerings[dest.Peer] + remotePeer, ok := c.Peerings[us.Peer] if !ok { return nil, fmt.Errorf("not possible") } - dest.Cluster = remotePeer.Link.Name - dest.Peering = remotePeer.Link + us.Cluster = remotePeer.Link.Name + us.Peering = remotePeer.Link // this helps in generating fortio assertions; otherwise field is ignored - dest.ID.Partition = remotePeer.Link.Partition - } - for _, dest := range wrk.ImpliedDestinations { - if dest.Peer == "" { - dest.Cluster = c.Name - dest.Peering = nil - continue - } - remotePeer, ok := c.Peerings[dest.Peer] - if !ok { - return nil, fmt.Errorf("not possible") - } - dest.Cluster = remotePeer.Link.Name - dest.Peering = remotePeer.Link - // this helps in generating fortio assertions; otherwise field is ignored - dest.ID.Partition = remotePeer.Link.Partition + us.ID.Partition = remotePeer.Link.Partition } } } @@ -825,51 +612,6 @@ func compile(logger hclog.Logger, raw *Config, prev *Topology, testingID string) return t, nil } -func assignVirtualIPs(c *Cluster) error { - lastVIPIndex := 1 - for _, svcData := range c.Services { - lastVIPIndex++ - if lastVIPIndex > 250 { - return fmt.Errorf("too many ips using this approach to VIPs") - } - svcData.VirtualIps = []string{ - fmt.Sprintf("10.244.0.%d", lastVIPIndex), - } - - // populate virtual ports where we forgot them - var ( - usedPorts = make(map[uint32]struct{}) - next = uint32(8080) - ) - for _, sp := range svcData.Ports { - if sp.Protocol == pbcatalog.Protocol_PROTOCOL_MESH { - continue - } - if sp.VirtualPort > 0 { - usedPorts[sp.VirtualPort] = struct{}{} - } - } - for _, sp := range svcData.Ports { - if sp.Protocol == pbcatalog.Protocol_PROTOCOL_MESH { - continue - } - if sp.VirtualPort > 0 { - continue - } - RETRY: - attempt := next - next++ - _, used := usedPorts[attempt] - if used { - goto RETRY - } - usedPorts[attempt] = struct{}{} - sp.VirtualPort = attempt - } - } - return nil -} - const permutedWarning = "use the disabled node kind if you want to ignore a node" func inheritAndValidateNodes( @@ -893,7 +635,6 @@ func inheritAndValidateNodes( } if currNode.Node.Kind != node.Kind || - currNode.Node.Version != node.Version || currNode.Node.Partition != node.Partition || currNode.Node.Name != node.Name || currNode.Node.Index != node.Index || @@ -930,7 +671,6 @@ func inheritAndValidateNodes( if currWrk.ID != wrk.ID || currWrk.Port != wrk.Port || - !maps.Equal(currWrk.Ports, wrk.Ports) || currWrk.EnvoyAdminPort != wrk.EnvoyAdminPort || currWrk.EnvoyPublicListenerPort != wrk.EnvoyPublicListenerPort || isSame(currWrk.Command, wrk.Command) != nil || diff --git a/testing/deployer/topology/compile_test.go b/testing/deployer/topology/compile_test.go index d7da18599f..564906ae96 100644 --- a/testing/deployer/topology/compile_test.go +++ b/testing/deployer/topology/compile_test.go @@ -13,7 +13,6 @@ import ( "github.com/hashicorp/go-hclog" - pbcatalog "github.com/hashicorp/consul/proto-public/pbcatalog/v2beta1" "github.com/hashicorp/consul/sdk/testutil" ) @@ -143,7 +142,6 @@ func TestCompile_CE(t *testing.T) { Images: DefaultImages().ChooseConsul(false), Nodes: []*Node{{ Kind: NodeKindServer, - Version: NodeVersionV1, Partition: "default", Name: "node1", Images: DefaultImages().ChooseConsul(false).ChooseNode(NodeKindServer), @@ -154,7 +152,6 @@ func TestCompile_CE(t *testing.T) { Cluster: "foo2", Datacenter: "foo2", }}, - Services: map[ID]*pbcatalog.Service{}, Partitions: []*Partition{{ Name: "default", Namespaces: []string{"default"}, @@ -285,7 +282,7 @@ func TestCompile_CE(t *testing.T) { Image: "busybox", Port: 8877, EnvoyAdminPort: 19001, - Destinations: []*Destination{{ + Upstreams: []*Upstream{{ ID: NewID("gaz", "ns3", "ap3"), LocalAddress: "127.0.0.1", LocalPort: 5000, @@ -293,27 +290,6 @@ func TestCompile_CE(t *testing.T) { }, }, }, - { - Kind: NodeKindDataplane, - Version: NodeVersionV2, - Name: "mesh2", - Partition: "ap2", - Addresses: []*Address{ - {Network: "foo"}, - }, - Workloads: []*Workload{ - { - ID: NewID("gir", "ns4", "ap2"), - Image: "busybox", - Port: 8877, - EnvoyAdminPort: 19001, - ImpliedDestinations: []*Destination{{ - ID: NewID("gaz", "", "ap4"), - PortName: "www", - }}, - }, - }, - }, }, }}, }, @@ -329,24 +305,10 @@ func TestCompile_CE(t *testing.T) { NetworkName: "foo", Datacenter: "foo", Enterprise: true, - EnableV2: true, Images: DefaultImages().ChooseConsul(true), - Services: map[ID]*pbcatalog.Service{ - NewID("gir", "ns4", "ap2"): { - Workloads: &pbcatalog.WorkloadSelector{ - Names: []string{"gir-mesh2"}, - }, - Ports: []*pbcatalog.ServicePort{ - {TargetPort: "legacy", VirtualPort: 8080, Protocol: pbcatalog.Protocol_PROTOCOL_TCP}, - {TargetPort: "mesh", Protocol: pbcatalog.Protocol_PROTOCOL_MESH}, - }, - VirtualIps: []string{"10.244.0.2"}, - }, - }, Nodes: []*Node{ { Kind: NodeKindServer, - Version: NodeVersionV1, Name: "server1", Partition: "default", Images: DefaultImages().ChooseConsul(true).ChooseNode(NodeKindServer), @@ -358,7 +320,6 @@ func TestCompile_CE(t *testing.T) { }, { Kind: NodeKindClient, - Version: NodeVersionV1, Name: "mesh1", Partition: "ap1", Images: DefaultImages().ChooseConsul(true).ChooseNode(NodeKindClient), @@ -374,15 +335,13 @@ func TestCompile_CE(t *testing.T) { Image: "busybox", Port: 8888, EnvoyAdminPort: 19000, - NodeVersion: NodeVersionV1, }, { ID: NewID("gir", "ns2", "ap1"), Image: "busybox", Port: 8877, EnvoyAdminPort: 19001, - NodeVersion: NodeVersionV1, - Destinations: []*Destination{{ + Upstreams: []*Upstream{{ ID: NewID("gaz", "ns3", "ap3"), Cluster: "foo", LocalAddress: "127.0.0.1", @@ -391,59 +350,16 @@ func TestCompile_CE(t *testing.T) { }, }, }, - { - Kind: NodeKindDataplane, - Version: NodeVersionV2, - Name: "mesh2", - Partition: "ap2", - Images: DefaultImages().ChooseConsul(true).ChooseNode(NodeKindDataplane), - Addresses: []*Address{ - {Network: "foo", Type: "lan", DockerNetworkName: "cslc-foo-" + clusterID}, - }, - Cluster: "foo", - Datacenter: "foo", - Index: 2, - Workloads: []*Workload{ - { - ID: NewID("gir", "ns4", "ap2"), - Image: "busybox", - Ports: map[string]*Port{ - "legacy": {Number: 8877, Protocol: "tcp", ActualProtocol: pbcatalog.Protocol_PROTOCOL_TCP}, - "mesh": {Number: 20000, Protocol: "mesh", ActualProtocol: pbcatalog.Protocol_PROTOCOL_MESH}, - }, - EnvoyAdminPort: 19001, - EnvoyPublicListenerPort: 20000, - NodeVersion: NodeVersionV2, - V2Services: []string{"gir"}, - WorkloadIdentity: "gir", - Workload: "gir-mesh2", - ImpliedDestinations: []*Destination{{ - ID: NewID("gaz", "default", "ap4"), - Cluster: "foo", // TODO: why is this only sometimes populated? - PortName: "www", - Implied: true, - }}, - }, - }, - }, }, Partitions: []*Partition{ { Name: "ap1", Namespaces: []string{"default", "ns1", "ns2"}, }, - { - Name: "ap2", - Namespaces: []string{"default", "ns4"}, - }, { Name: "ap3", Namespaces: []string{"default", "ns3"}, }, - { - Name: "ap4", - Namespaces: []string{"default"}, - }, { Name: "default", Namespaces: []string{"default"}, @@ -453,93 +369,6 @@ func TestCompile_CE(t *testing.T) { }, }, }, - "explicit v2 services": { - in: &Config{ - Networks: []*Network{ - {Name: "foo"}, - }, - Clusters: []*Cluster{{ - Name: "foo", - Nodes: []*Node{{ - Kind: NodeKindServer, - Name: "node1", - }}, - Services: map[ID]*pbcatalog.Service{ - NewID("zim", "default", "default"): { - Ports: []*pbcatalog.ServicePort{ - {TargetPort: "http"}, - {TargetPort: "mesh", Protocol: pbcatalog.Protocol_PROTOCOL_MESH}, - }, - }, - }, - }}, - }, - expect: &Topology{ - ID: clusterID, - Images: DefaultImages(), - Networks: map[string]*Network{ - "foo": {Name: "foo", Type: "lan", DockerName: "cslc-foo-" + clusterID}, - }, - Clusters: map[string]*Cluster{ - "foo": { - Name: "foo", - NetworkName: "foo", - Datacenter: "foo", - Images: DefaultImages().ChooseConsul(false), - Nodes: []*Node{{ - Kind: NodeKindServer, - Version: NodeVersionV1, - Partition: "default", - Name: "node1", - Images: DefaultImages().ChooseConsul(false).ChooseNode(NodeKindServer), - Addresses: []*Address{ - {Network: "foo", Type: "lan", DockerNetworkName: "cslc-foo-" + clusterID}, - }, - Cluster: "foo", - Datacenter: "foo", - }}, - EnableV2: true, - Services: map[ID]*pbcatalog.Service{ - NewID("zim", "default", "default"): { - Ports: []*pbcatalog.ServicePort{ - {TargetPort: "http", VirtualPort: 8080, Protocol: pbcatalog.Protocol_PROTOCOL_TCP}, - {TargetPort: "mesh", Protocol: pbcatalog.Protocol_PROTOCOL_MESH}, - }, - VirtualIps: []string{"10.244.0.2"}, - }, - }, - Partitions: []*Partition{{ - Name: "default", - Namespaces: []string{"default"}, - }}, - }, - }, - }, - }, - "explicit v2 services/bad workload selector": { - in: &Config{ - Networks: []*Network{ - {Name: "foo"}, - }, - Clusters: []*Cluster{{ - Name: "foo", - Nodes: []*Node{{ - Kind: NodeKindServer, - Name: "node1", - }}, - Services: map[ID]*pbcatalog.Service{ - NewID("zim", "default", "default"): { - Workloads: &pbcatalog.WorkloadSelector{Names: []string{"zzz"}}, - Ports: []*pbcatalog.ServicePort{ - {TargetPort: "http"}, - {TargetPort: "mesh"}, - }, - }, - }, - }}, - }, - expectErr: `error building cluster "foo": the workloads field for v2 service "default/default/zim" is not user settable`, - }, "tls volume errantly set": { in: &Config{ Networks: []*Network{ @@ -599,38 +428,6 @@ func TestCompile_CE(t *testing.T) { }, expectErr: `error building cluster "foo": error compiling node "zim": cluster "foo" node "zim" has invalid kind`, }, - "node/bad version": { - in: &Config{ - Networks: []*Network{ - {Name: "foo"}, - }, - Clusters: []*Cluster{{ - Name: "foo", - Nodes: []*Node{{ - Kind: NodeKindServer, - Version: "v3", - Name: "zim", - }}, - }}, - }, - expectErr: `error building cluster "foo": error compiling node "zim": cluster "foo" node "zim" has invalid version: v3`, - }, - "node/bad version for client": { - in: &Config{ - Networks: []*Network{ - {Name: "foo"}, - }, - Clusters: []*Cluster{{ - Name: "foo", - Nodes: []*Node{{ - Kind: NodeKindClient, - Version: NodeVersionV2, - Name: "zim", - }}, - }}, - }, - expectErr: `error building cluster "foo": error compiling node "zim": v2 does not support client agents at this time`, - }, "node/invalid partition": { in: &Config{ Networks: []*Network{ @@ -977,7 +774,7 @@ func TestCompile_CE(t *testing.T) { }, expectErr: `error building cluster "foo": error compiling node "mesh1": cannot have two services on the same node "default/mesh1" in the same cluster "foo" with the same name "default/default/zim"`, }, - "workload/v1 and implied dest": { + "workload/default-upstream/expl dest local address defaulting": { in: &Config{ Networks: []*Network{ {Name: "foo"}, @@ -993,7 +790,7 @@ func TestCompile_CE(t *testing.T) { }, }, { - Kind: NodeKindClient, + Kind: NodeKindDataplane, Name: "mesh1", Addresses: []*Address{{Network: "foo"}}, Workloads: []*Workload{{ @@ -1001,17 +798,105 @@ func TestCompile_CE(t *testing.T) { Image: "busybox", Port: 8080, EnvoyAdminPort: 19000, - ImpliedDestinations: []*Destination{{ - ID: NewID("gir", "", ""), + Upstreams: []*Upstream{{ + ID: NewID("gir", "", ""), + LocalPort: 5000, + }}, + }}, + }, + }, + }}, + }, + expect: &Topology{ + ID: clusterID, + Images: DefaultImages(), + Networks: map[string]*Network{ + "foo": {Name: "foo", Type: "lan", DockerName: "cslc-foo-" + clusterID}, + }, + Clusters: map[string]*Cluster{ + "foo": { + Name: "foo", + NetworkName: "foo", + Datacenter: "foo", + Images: DefaultImages().ChooseConsul(false), + Nodes: []*Node{ + { + Kind: NodeKindServer, + Partition: "default", + Name: "server1", + Images: DefaultImages().ChooseConsul(false).ChooseNode(NodeKindServer), + Addresses: []*Address{ + {Network: "foo", Type: "lan", DockerNetworkName: "cslc-foo-" + clusterID}, + }, + Cluster: "foo", + Datacenter: "foo", + }, + { + Kind: NodeKindDataplane, + Partition: "default", + Name: "mesh1", + Images: DefaultImages().ChooseConsul(false).ChooseNode(NodeKindDataplane), + Addresses: []*Address{ + {Network: "foo", Type: "lan", DockerNetworkName: "cslc-foo-" + clusterID}, + }, + Cluster: "foo", + Datacenter: "foo", + Index: 1, + Workloads: []*Workload{{ + ID: NewID("zim", "", ""), + Image: "busybox", + Port: 8080, + EnvoyAdminPort: 19000, + EnvoyPublicListenerPort: 20000, + Upstreams: []*Upstream{{ + ID: NewID("gir", "", ""), + LocalAddress: "127.0.0.1", // <--- this + LocalPort: 5000, + Cluster: "foo", + }}, }}, + }, + }, + Partitions: []*Partition{{ + Name: "default", + Namespaces: []string{"default"}, + }}, + }, + }, + }, + }, + "workload/validate/no name": { + in: &Config{ + Networks: []*Network{ + {Name: "foo"}, + }, + Clusters: []*Cluster{{ + Name: "foo", + Nodes: []*Node{ + { + Kind: NodeKindServer, + Name: "server1", + Addresses: []*Address{ + {Network: "foo"}, + }, + }, + { + Kind: NodeKindClient, + Name: "mesh1", + Addresses: []*Address{{Network: "foo"}}, + Workloads: []*Workload{{ + ID: NewID("", "", ""), + Image: "busybox", + Port: 8080, + EnvoyAdminPort: 19000, }}, }, }, }}, }, - expectErr: `error building cluster "foo": error compiling node "mesh1": v1 does not support implied destinations yet`, + expectErr: `error building cluster "foo": error compiling node "mesh1": service name is not valid`, }, - "workload/default-destination/impl dest need port names in v2": { + "workload/validate/no image": { in: &Config{ Networks: []*Network{ {Name: "foo"}, @@ -1027,26 +912,21 @@ func TestCompile_CE(t *testing.T) { }, }, { - Kind: NodeKindDataplane, - Version: NodeVersionV2, + Kind: NodeKindClient, Name: "mesh1", Addresses: []*Address{{Network: "foo"}}, Workloads: []*Workload{{ ID: NewID("zim", "", ""), - Image: "busybox", Port: 8080, EnvoyAdminPort: 19000, - ImpliedDestinations: []*Destination{{ - ID: NewID("gir", "", ""), - }}, }}, }, }, }}, }, - expectErr: `error building cluster "foo": error compiling node "mesh1": implicit destinations must use port names in v2`, + expectErr: `error building cluster "foo": error compiling node "mesh1": cluster "foo" node "mesh1" service "default/default/zim" is not valid: service image is required`, }, - "workload/default-destination/expl dest port name legacy defaulting": { + "workload/validate/no image mesh gateway": { in: &Config{ Networks: []*Network{ {Name: "foo"}, @@ -1062,20 +942,14 @@ func TestCompile_CE(t *testing.T) { }, }, { - Kind: NodeKindDataplane, - Version: NodeVersionV2, + Kind: NodeKindClient, Name: "mesh1", Addresses: []*Address{{Network: "foo"}}, Workloads: []*Workload{{ ID: NewID("zim", "", ""), - Image: "busybox", - Port: 8888, + Port: 8080, EnvoyAdminPort: 19000, - Destinations: []*Destination{{ - ID: NewID("gir", "", ""), - LocalAddress: "127.0.0.1", - LocalPort: 5000, - }}, + IsMeshGateway: true, }}, }, }, @@ -1093,23 +967,9 @@ func TestCompile_CE(t *testing.T) { NetworkName: "foo", Datacenter: "foo", Images: DefaultImages().ChooseConsul(false), - EnableV2: true, - Services: map[ID]*pbcatalog.Service{ - NewID("zim", "default", "default"): { - Workloads: &pbcatalog.WorkloadSelector{ - Names: []string{"zim-mesh1"}, - }, - Ports: []*pbcatalog.ServicePort{ - {TargetPort: "legacy", VirtualPort: 8080, Protocol: pbcatalog.Protocol_PROTOCOL_TCP}, - {TargetPort: "mesh", Protocol: pbcatalog.Protocol_PROTOCOL_MESH}, - }, - VirtualIps: []string{"10.244.0.2"}, - }, - }, Nodes: []*Node{ { Kind: NodeKindServer, - Version: NodeVersionV1, Partition: "default", Name: "server1", Images: DefaultImages().ChooseConsul(false).ChooseNode(NodeKindServer), @@ -1120,11 +980,10 @@ func TestCompile_CE(t *testing.T) { Datacenter: "foo", }, { - Kind: NodeKindDataplane, - Version: NodeVersionV2, + Kind: NodeKindClient, Partition: "default", Name: "mesh1", - Images: DefaultImages().ChooseConsul(false).ChooseNode(NodeKindDataplane), + Images: DefaultImages().ChooseConsul(false).ChooseNode(NodeKindClient), Addresses: []*Address{ {Network: "foo", Type: "lan", DockerNetworkName: "cslc-foo-" + clusterID}, }, @@ -1132,25 +991,10 @@ func TestCompile_CE(t *testing.T) { Datacenter: "foo", Index: 1, Workloads: []*Workload{{ - ID: NewID("zim", "", ""), - Image: "busybox", - Ports: map[string]*Port{ - "legacy": {Number: 8888, Protocol: "tcp", ActualProtocol: pbcatalog.Protocol_PROTOCOL_TCP}, - "mesh": {Number: 20000, Protocol: "mesh", ActualProtocol: pbcatalog.Protocol_PROTOCOL_MESH}, - }, - EnvoyAdminPort: 19000, - EnvoyPublicListenerPort: 20000, - NodeVersion: NodeVersionV2, - V2Services: []string{"zim"}, - WorkloadIdentity: "zim", - Workload: "zim-mesh1", - Destinations: []*Destination{{ - ID: NewID("gir", "", ""), - LocalAddress: "127.0.0.1", - LocalPort: 5000, - Cluster: "foo", - PortName: "legacy", // <--- this - }}, + ID: NewID("zim", "", ""), + Port: 8080, + EnvoyAdminPort: 19000, + IsMeshGateway: true, }}, }, }, @@ -1162,7 +1006,7 @@ func TestCompile_CE(t *testing.T) { }, }, }, - "workload/default-destination/expl dest local address defaulting": { + "workload/validate/singleport invalid port": { in: &Config{ Networks: []*Network{ {Name: "foo"}, @@ -1179,476 +1023,13 @@ func TestCompile_CE(t *testing.T) { }, { Kind: NodeKindDataplane, - Version: NodeVersionV1, Name: "mesh1", Addresses: []*Address{{Network: "foo"}}, Workloads: []*Workload{{ ID: NewID("zim", "", ""), Image: "busybox", - Port: 8080, EnvoyAdminPort: 19000, - Destinations: []*Destination{{ - ID: NewID("gir", "", ""), - LocalPort: 5000, - }}, - }}, - }, - }, - }}, - }, - expect: &Topology{ - ID: clusterID, - Images: DefaultImages(), - Networks: map[string]*Network{ - "foo": {Name: "foo", Type: "lan", DockerName: "cslc-foo-" + clusterID}, - }, - Clusters: map[string]*Cluster{ - "foo": { - Name: "foo", - NetworkName: "foo", - Datacenter: "foo", - Images: DefaultImages().ChooseConsul(false), - Services: map[ID]*pbcatalog.Service{ - // - }, - Nodes: []*Node{ - { - Kind: NodeKindServer, - Version: NodeVersionV1, - Partition: "default", - Name: "server1", - Images: DefaultImages().ChooseConsul(false).ChooseNode(NodeKindServer), - Addresses: []*Address{ - {Network: "foo", Type: "lan", DockerNetworkName: "cslc-foo-" + clusterID}, - }, - Cluster: "foo", - Datacenter: "foo", - }, - { - Kind: NodeKindDataplane, - Version: NodeVersionV1, - Partition: "default", - Name: "mesh1", - Images: DefaultImages().ChooseConsul(false).ChooseNode(NodeKindDataplane), - Addresses: []*Address{ - {Network: "foo", Type: "lan", DockerNetworkName: "cslc-foo-" + clusterID}, - }, - Cluster: "foo", - Datacenter: "foo", - Index: 1, - Workloads: []*Workload{{ - ID: NewID("zim", "", ""), - Image: "busybox", - Port: 8080, - EnvoyAdminPort: 19000, - EnvoyPublicListenerPort: 20000, - NodeVersion: NodeVersionV1, - Destinations: []*Destination{{ - ID: NewID("gir", "", ""), - LocalAddress: "127.0.0.1", // <--- this - LocalPort: 5000, - Cluster: "foo", - }}, - }}, - }, - }, - Partitions: []*Partition{{ - Name: "default", - Namespaces: []string{"default"}, - }}, - }, - }, - }, - }, - "workload/default-destination/expl dest cannot use port names in v1": { - in: &Config{ - Networks: []*Network{ - {Name: "foo"}, - }, - Clusters: []*Cluster{{ - Name: "foo", - Nodes: []*Node{ - { - Kind: NodeKindServer, - Name: "server1", - Addresses: []*Address{ - {Network: "foo"}, - }, - }, - { - Kind: NodeKindDataplane, - Version: NodeVersionV1, - Name: "mesh1", - Addresses: []*Address{{Network: "foo"}}, - Workloads: []*Workload{{ - ID: NewID("zim", "", ""), - Image: "busybox", - Port: 8080, - EnvoyAdminPort: 19000, - Destinations: []*Destination{{ - ID: NewID("gir", "", ""), - PortName: "http", - }}, - }}, - }, - }, - }}, - }, - expectErr: `error building cluster "foo": error compiling node "mesh1": explicit destinations cannot use port names in v1`, - }, - "workload/validate/no name": { - in: &Config{ - Networks: []*Network{ - {Name: "foo"}, - }, - Clusters: []*Cluster{{ - Name: "foo", - Nodes: []*Node{ - { - Kind: NodeKindServer, - Name: "server1", - Addresses: []*Address{ - {Network: "foo"}, - }, - }, - { - Kind: NodeKindClient, - Name: "mesh1", - Addresses: []*Address{{Network: "foo"}}, - Workloads: []*Workload{{ - ID: NewID("", "", ""), - Image: "busybox", - Port: 8080, - EnvoyAdminPort: 19000, - }}, - }, - }, - }}, - }, - expectErr: `error building cluster "foo": error compiling node "mesh1": service name is not valid`, - }, - "workload/validate/no image": { - in: &Config{ - Networks: []*Network{ - {Name: "foo"}, - }, - Clusters: []*Cluster{{ - Name: "foo", - Nodes: []*Node{ - { - Kind: NodeKindServer, - Name: "server1", - Addresses: []*Address{ - {Network: "foo"}, - }, - }, - { - Kind: NodeKindClient, - Name: "mesh1", - Addresses: []*Address{{Network: "foo"}}, - Workloads: []*Workload{{ - ID: NewID("zim", "", ""), - Port: 8080, - EnvoyAdminPort: 19000, - }}, - }, - }, - }}, - }, - expectErr: `error building cluster "foo": error compiling node "mesh1": cluster "foo" node "mesh1" service "default/default/zim" is not valid: service image is required`, - }, - "workload/validate/no image mesh gateway": { - in: &Config{ - Networks: []*Network{ - {Name: "foo"}, - }, - Clusters: []*Cluster{{ - Name: "foo", - Nodes: []*Node{ - { - Kind: NodeKindServer, - Name: "server1", - Addresses: []*Address{ - {Network: "foo"}, - }, - }, - { - Kind: NodeKindClient, - Name: "mesh1", - Addresses: []*Address{{Network: "foo"}}, - Workloads: []*Workload{{ - ID: NewID("zim", "", ""), - Port: 8080, - EnvoyAdminPort: 19000, - IsMeshGateway: true, - }}, - }, - }, - }}, - }, - expect: &Topology{ - ID: clusterID, - Images: DefaultImages(), - Networks: map[string]*Network{ - "foo": {Name: "foo", Type: "lan", DockerName: "cslc-foo-" + clusterID}, - }, - Clusters: map[string]*Cluster{ - "foo": { - Name: "foo", - NetworkName: "foo", - Datacenter: "foo", - Images: DefaultImages().ChooseConsul(false), - Services: map[ID]*pbcatalog.Service{ - // - }, - Nodes: []*Node{ - { - Kind: NodeKindServer, - Version: NodeVersionV1, - Partition: "default", - Name: "server1", - Images: DefaultImages().ChooseConsul(false).ChooseNode(NodeKindServer), - Addresses: []*Address{ - {Network: "foo", Type: "lan", DockerNetworkName: "cslc-foo-" + clusterID}, - }, - Cluster: "foo", - Datacenter: "foo", - }, - { - Kind: NodeKindClient, - Version: NodeVersionV1, - Partition: "default", - Name: "mesh1", - Images: DefaultImages().ChooseConsul(false).ChooseNode(NodeKindClient), - Addresses: []*Address{ - {Network: "foo", Type: "lan", DockerNetworkName: "cslc-foo-" + clusterID}, - }, - Cluster: "foo", - Datacenter: "foo", - Index: 1, - Workloads: []*Workload{{ - ID: NewID("zim", "", ""), - Port: 8080, - EnvoyAdminPort: 19000, - IsMeshGateway: true, - NodeVersion: NodeVersionV1, - }}, - }, - }, - Partitions: []*Partition{{ - Name: "default", - Namespaces: []string{"default"}, - }}, - }, - }, - }, - }, - "workload/validate/single and multiport v2": { - in: &Config{ - Networks: []*Network{ - {Name: "foo"}, - }, - Clusters: []*Cluster{{ - Name: "foo", - Nodes: []*Node{ - { - Kind: NodeKindServer, - Name: "server1", - Addresses: []*Address{ - {Network: "foo"}, - }, - }, - { - Kind: NodeKindDataplane, - Name: "mesh1", - Version: NodeVersionV2, - Addresses: []*Address{{Network: "foo"}}, - Workloads: []*Workload{{ - ID: NewID("zim", "", ""), - Image: "busybox", - Port: 8080, - EnvoyAdminPort: 19000, - Ports: map[string]*Port{ - "blah": { - Number: 8181, - Protocol: "tcp", - }, - }, - }}, - }, - }, - }}, - }, - expectErr: `error building cluster "foo": error compiling node "mesh1": cluster "foo" node "mesh1" service "default/default/zim" is not valid: cannot specify both singleport and multiport on service in v2`, - }, - "workload/validate/multiport nil port": { - in: &Config{ - Networks: []*Network{ - {Name: "foo"}, - }, - Clusters: []*Cluster{{ - Name: "foo", - Nodes: []*Node{ - { - Kind: NodeKindServer, - Name: "server1", - Addresses: []*Address{ - {Network: "foo"}, - }, - }, - { - Kind: NodeKindDataplane, - Name: "mesh1", - Version: NodeVersionV2, - Addresses: []*Address{{Network: "foo"}}, - Workloads: []*Workload{{ - ID: NewID("zim", "", ""), - Image: "busybox", - EnvoyAdminPort: 19000, - Ports: map[string]*Port{ - "blah": nil, - }, - }}, - }, - }, - }}, - }, - expectErr: `error building cluster "foo": error compiling node "mesh1": cluster "foo" node "mesh1" service "default/default/zim" is not valid: cannot be nil`, - }, - "workload/validate/multiport negative port": { - in: &Config{ - Networks: []*Network{ - {Name: "foo"}, - }, - Clusters: []*Cluster{{ - Name: "foo", - Nodes: []*Node{ - { - Kind: NodeKindServer, - Name: "server1", - Addresses: []*Address{ - {Network: "foo"}, - }, - }, - { - Kind: NodeKindDataplane, - Name: "mesh1", - Version: NodeVersionV2, - Addresses: []*Address{{Network: "foo"}}, - Workloads: []*Workload{{ - ID: NewID("zim", "", ""), - Image: "busybox", - EnvoyAdminPort: 19000, - Ports: map[string]*Port{ - "blah": { - Number: -5, - }, - }, - }}, - }, - }, - }}, - }, - expectErr: `error building cluster "foo": error compiling node "mesh1": cluster "foo" node "mesh1" service "default/default/zim" is not valid: service has invalid port number`, - }, - "workload/validate/multiport set actualprotocol": { - in: &Config{ - Networks: []*Network{ - {Name: "foo"}, - }, - Clusters: []*Cluster{{ - Name: "foo", - Nodes: []*Node{ - { - Kind: NodeKindServer, - Name: "server1", - Addresses: []*Address{ - {Network: "foo"}, - }, - }, - { - Kind: NodeKindDataplane, - Name: "mesh1", - Version: NodeVersionV2, - Addresses: []*Address{{Network: "foo"}}, - Workloads: []*Workload{{ - ID: NewID("zim", "", ""), - Image: "busybox", - EnvoyAdminPort: 19000, - Ports: map[string]*Port{ - "blah": { - Number: 8888, - ActualProtocol: pbcatalog.Protocol_PROTOCOL_GRPC, - }, - }, - }}, - }, - }, - }}, - }, - expectErr: `error building cluster "foo": error compiling node "mesh1": cluster "foo" node "mesh1" service "default/default/zim" is not valid: user cannot specify ActualProtocol field`, - }, - "workload/validate/multiport invalid port protocol": { - in: &Config{ - Networks: []*Network{ - {Name: "foo"}, - }, - Clusters: []*Cluster{{ - Name: "foo", - Nodes: []*Node{ - { - Kind: NodeKindServer, - Name: "server1", - Addresses: []*Address{ - {Network: "foo"}, - }, - }, - { - Kind: NodeKindDataplane, - Name: "mesh1", - Version: NodeVersionV2, - Addresses: []*Address{{Network: "foo"}}, - Workloads: []*Workload{{ - ID: NewID("zim", "", ""), - Image: "busybox", - EnvoyAdminPort: 19000, - Ports: map[string]*Port{ - "blah": { - Number: 8888, - Protocol: "zzzz", - }, - }, - }}, - }, - }, - }}, - }, - expectErr: `error building cluster "foo": error compiling node "mesh1": cluster "foo" node "mesh1" service "default/default/zim" is not valid: service has invalid port protocol "zzzz"`, - }, - "workload/validate/singleport invalid port": { - in: &Config{ - Networks: []*Network{ - {Name: "foo"}, - }, - Clusters: []*Cluster{{ - Name: "foo", - Nodes: []*Node{ - { - Kind: NodeKindServer, - Name: "server1", - Addresses: []*Address{ - {Network: "foo"}, - }, - }, - { - Kind: NodeKindDataplane, - Name: "mesh1", - Addresses: []*Address{{Network: "foo"}}, - Workloads: []*Workload{{ - ID: NewID("zim", "", ""), - Image: "busybox", - EnvoyAdminPort: 19000, - Port: -999, + Port: -999, }}, }, }, @@ -1656,38 +1037,6 @@ func TestCompile_CE(t *testing.T) { }, expectErr: `error building cluster "foo": error compiling node "mesh1": cluster "foo" node "mesh1" service "default/default/zim" is not valid: service has invalid port`, }, - "workload/validate/singleport tproxy": { - in: &Config{ - Networks: []*Network{ - {Name: "foo"}, - }, - Clusters: []*Cluster{{ - Name: "foo", - Nodes: []*Node{ - { - Kind: NodeKindServer, - Name: "server1", - Addresses: []*Address{ - {Network: "foo"}, - }, - }, - { - Kind: NodeKindDataplane, - Name: "mesh1", - Addresses: []*Address{{Network: "foo"}}, - Workloads: []*Workload{{ - ID: NewID("zim", "", ""), - Image: "busybox", - EnvoyAdminPort: 19000, - Port: 999, - EnableTransparentProxy: true, - }}, - }, - }, - }}, - }, - expectErr: `error building cluster "foo": error compiling node "mesh1": cluster "foo" node "mesh1" service "default/default/zim" is not valid: tproxy does not work with v1 yet`, - }, "workload/validate/mesh with no admin port": { in: &Config{ Networks: []*Network{ @@ -1774,7 +1123,7 @@ func TestCompile_CE(t *testing.T) { EnvoyAdminPort: 19000, Image: "busybox", Port: 999, - Destinations: []*Destination{{ + Upstreams: []*Upstream{{ ID: NewID("", "", ""), }}, }}, @@ -1782,7 +1131,7 @@ func TestCompile_CE(t *testing.T) { }, }}, }, - expectErr: `error building cluster "foo": error compiling node "mesh1": cluster "foo" node "mesh1" service "default/default/zim" is not valid: destination service name is required`, + expectErr: `error building cluster "foo": error compiling node "mesh1": cluster "foo" node "mesh1" service "default/default/zim" is not valid: upstream service name is required`, }, "workload/validate/expl dest with no local port": { in: &Config{ @@ -1808,7 +1157,7 @@ func TestCompile_CE(t *testing.T) { EnvoyAdminPort: 19000, Image: "busybox", Port: 999, - Destinations: []*Destination{{ + Upstreams: []*Upstream{{ ID: NewID("dib", "", ""), }}, }}, @@ -1816,7 +1165,7 @@ func TestCompile_CE(t *testing.T) { }, }}, }, - expectErr: `error building cluster "foo": error compiling node "mesh1": cluster "foo" node "mesh1" service "default/default/zim" is not valid: destination local port is required`, + expectErr: `error building cluster "foo": error compiling node "mesh1": cluster "foo" node "mesh1" service "default/default/zim" is not valid: upstream local port is required`, }, "workload/validate/expl dest bad local address": { in: &Config{ @@ -1842,7 +1191,7 @@ func TestCompile_CE(t *testing.T) { EnvoyAdminPort: 19000, Image: "busybox", Port: 999, - Destinations: []*Destination{{ + Upstreams: []*Upstream{{ ID: NewID("dib", "", ""), LocalPort: 5000, LocalAddress: "clown@address", @@ -1852,186 +1201,7 @@ func TestCompile_CE(t *testing.T) { }, }}, }, - expectErr: `error building cluster "foo": error compiling node "mesh1": cluster "foo" node "mesh1" service "default/default/zim" is not valid: destination local address is invalid: clown@address`, - }, - "workload/validate/expl dest with implied": { - in: &Config{ - Networks: []*Network{ - {Name: "foo"}, - }, - Clusters: []*Cluster{{ - Name: "foo", - Nodes: []*Node{ - { - Kind: NodeKindServer, - Name: "server1", - Addresses: []*Address{ - {Network: "foo"}, - }, - }, - { - Kind: NodeKindDataplane, - Version: NodeVersionV2, - Name: "mesh1", - Addresses: []*Address{{Network: "foo"}}, - Workloads: []*Workload{{ - ID: NewID("zim", "", ""), - EnvoyAdminPort: 19000, - Image: "busybox", - Port: 999, - Destinations: []*Destination{{ - ID: NewID("dib", "", ""), - LocalPort: 5000, - PortName: "http", - Implied: true, - }}, - }}, - }, - }, - }}, - }, - expectErr: `error building cluster "foo": error compiling node "mesh1": cluster "foo" node "mesh1" service "default/default/zim" is not valid: implied field cannot be set`, - }, - "workload/validate/impl dest with no name": { - in: &Config{ - Networks: []*Network{ - {Name: "foo"}, - }, - Clusters: []*Cluster{{ - Name: "foo", - Nodes: []*Node{ - { - Kind: NodeKindServer, - Name: "server1", - Addresses: []*Address{ - {Network: "foo"}, - }, - }, - { - Kind: NodeKindDataplane, - Version: NodeVersionV2, - Name: "mesh1", - Addresses: []*Address{{Network: "foo"}}, - Workloads: []*Workload{{ - ID: NewID("zim", "", ""), - EnvoyAdminPort: 19000, - Image: "busybox", - Port: 999, - ImpliedDestinations: []*Destination{{ - ID: NewID("", "", ""), - PortName: "http", - }}, - }}, - }, - }, - }}, - }, - expectErr: `error building cluster "foo": error compiling node "mesh1": cluster "foo" node "mesh1" service "default/default/zim" is not valid: implied destination service name is required`, - }, - "workload/validate/impl dest with local port": { - in: &Config{ - Networks: []*Network{ - {Name: "foo"}, - }, - Clusters: []*Cluster{{ - Name: "foo", - Nodes: []*Node{ - { - Kind: NodeKindServer, - Name: "server1", - Addresses: []*Address{ - {Network: "foo"}, - }, - }, - { - Kind: NodeKindDataplane, - Version: NodeVersionV2, - Name: "mesh1", - Addresses: []*Address{{Network: "foo"}}, - Workloads: []*Workload{{ - ID: NewID("zim", "", ""), - EnvoyAdminPort: 19000, - Image: "busybox", - Port: 999, - ImpliedDestinations: []*Destination{{ - ID: NewID("dib", "", ""), - PortName: "http", - LocalPort: 5000, - }}, - }}, - }, - }, - }}, - }, - expectErr: `error building cluster "foo": error compiling node "mesh1": cluster "foo" node "mesh1" service "default/default/zim" is not valid: implied destination local port cannot be set`, - }, - "workload/validate/impl dest with local address": { - in: &Config{ - Networks: []*Network{ - {Name: "foo"}, - }, - Clusters: []*Cluster{{ - Name: "foo", - Nodes: []*Node{ - { - Kind: NodeKindServer, - Name: "server1", - Addresses: []*Address{ - {Network: "foo"}, - }, - }, - { - Kind: NodeKindDataplane, - Version: NodeVersionV2, - Name: "mesh1", - Addresses: []*Address{{Network: "foo"}}, - Workloads: []*Workload{{ - ID: NewID("zim", "", ""), - EnvoyAdminPort: 19000, - Image: "busybox", - Port: 999, - ImpliedDestinations: []*Destination{{ - ID: NewID("dib", "", ""), - PortName: "http", - LocalAddress: "127.0.0.1", - }}, - }}, - }, - }, - }}, - }, - expectErr: `error building cluster "foo": error compiling node "mesh1": cluster "foo" node "mesh1" service "default/default/zim" is not valid: implied destination local address cannot be set`, - }, - "workload/validate/v1 cannot use multiport": { - in: &Config{ - Networks: []*Network{ - {Name: "foo"}, - }, - Clusters: []*Cluster{{ - Name: "foo", - Nodes: []*Node{ - { - Kind: NodeKindServer, - Name: "server1", - Addresses: []*Address{ - {Network: "foo"}, - }, - }, - { - Kind: NodeKindDataplane, - Name: "mesh1", - Addresses: []*Address{{Network: "foo"}}, - Workloads: []*Workload{{ - ID: NewID("zim", "", ""), - Image: "busybox", - EnvoyAdminPort: 19000, - Ports: map[string]*Port{"web": {Number: 8080}}, - }}, - }, - }, - }}, - }, - expectErr: `error building cluster "foo": error compiling node "mesh1": cluster "foo" node "mesh1" service "default/default/zim" is not valid: cannot specify multiport on service in v1`, + expectErr: `error building cluster "foo": error compiling node "mesh1": cluster "foo" node "mesh1" service "default/default/zim" is not valid: upstream local address is invalid: clown@address`, }, "workload/validate/disable-mesh/mgw": { in: &Config{ @@ -2083,7 +1253,6 @@ func TestCompile_CE(t *testing.T) { }, { Kind: NodeKindDataplane, - Version: NodeVersionV2, Name: "mesh1", Addresses: []*Address{{Network: "foo"}}, Workloads: []*Workload{{ @@ -2092,7 +1261,7 @@ func TestCompile_CE(t *testing.T) { EnvoyAdminPort: 19000, Port: 8443, DisableServiceMesh: true, - Destinations: []*Destination{{ + Upstreams: []*Upstream{{ ID: NewID("gir", "", ""), }}, }}, @@ -2100,78 +1269,7 @@ func TestCompile_CE(t *testing.T) { }, }}, }, - expectErr: `error building cluster "foo": error compiling node "mesh1": cluster "foo" node "mesh1" service "default/default/zim" is not valid: cannot disable service mesh and configure destinations`, - }, - "workload/validate/disable-mesh/impl dest": { - in: &Config{ - Networks: []*Network{ - {Name: "foo"}, - }, - Clusters: []*Cluster{{ - Name: "foo", - Nodes: []*Node{ - { - Kind: NodeKindServer, - Name: "server1", - Addresses: []*Address{ - {Network: "foo"}, - }, - }, - { - Kind: NodeKindDataplane, - Version: NodeVersionV2, - Name: "mesh1", - Addresses: []*Address{{Network: "foo"}}, - Workloads: []*Workload{{ - ID: NewID("zim", "", ""), - Image: "busybox", - EnvoyAdminPort: 19000, - Port: 8443, - DisableServiceMesh: true, - ImpliedDestinations: []*Destination{{ - ID: NewID("gir", "", ""), - PortName: "web", - }}, - }}, - }, - }, - }}, - }, - expectErr: `error building cluster "foo": error compiling node "mesh1": cluster "foo" node "mesh1" service "default/default/zim" is not valid: cannot disable service mesh and configure implied destinations`, - }, - "workload/validate/disable-mesh/tproxy": { - in: &Config{ - Networks: []*Network{ - {Name: "foo"}, - }, - Clusters: []*Cluster{{ - Name: "foo", - Nodes: []*Node{ - { - Kind: NodeKindServer, - Name: "server1", - Addresses: []*Address{ - {Network: "foo"}, - }, - }, - { - Kind: NodeKindDataplane, - Version: NodeVersionV2, - Name: "mesh1", - Addresses: []*Address{{Network: "foo"}}, - Workloads: []*Workload{{ - ID: NewID("zim", "", ""), - Image: "busybox", - EnvoyAdminPort: 19000, - Port: 8443, - DisableServiceMesh: true, - EnableTransparentProxy: true, - }}, - }, - }, - }}, - }, - expectErr: `error building cluster "foo": error compiling node "mesh1": cluster "foo" node "mesh1" service "default/default/zim" is not valid: cannot disable service mesh and activate tproxy`, + expectErr: `error building cluster "foo": error compiling node "mesh1": cluster "foo" node "mesh1" service "default/default/zim" is not valid: cannot disable service mesh and configure upstreams`, }, "workload/validate/disable-mesh/set admin port": { in: &Config{ @@ -2190,7 +1288,6 @@ func TestCompile_CE(t *testing.T) { }, { Kind: NodeKindDataplane, - Version: NodeVersionV2, Name: "mesh1", Addresses: []*Address{{Network: "foo"}}, Workloads: []*Workload{{ @@ -2223,7 +1320,6 @@ func TestCompile_CE(t *testing.T) { }, { Kind: NodeKindDataplane, - Version: NodeVersionV2, Name: "mesh1", Addresses: []*Address{{Network: "foo"}}, Workloads: []*Workload{{ diff --git a/testing/deployer/topology/naming_shim.go b/testing/deployer/topology/naming_shim.go index 7cc51c19d8..e307b3b6e2 100644 --- a/testing/deployer/topology/naming_shim.go +++ b/testing/deployer/topology/naming_shim.go @@ -39,5 +39,5 @@ func NewServiceID(name, namespace, partition string) ID { return NewID(name, namespace, partition) } -// Deprecated: Destination -type Upstream = Destination +// Deprecated: +type Destination = Upstream diff --git a/testing/deployer/topology/relationships.go b/testing/deployer/topology/relationships.go index 212841de3c..b5fdc0b1f6 100644 --- a/testing/deployer/topology/relationships.go +++ b/testing/deployer/topology/relationships.go @@ -10,24 +10,16 @@ import ( ) // ComputeRelationships will analyze a full topology and generate all of the -// caller/destination information for all of them. +// caller/upstream information for all of them. func (t *Topology) ComputeRelationships() []Relationship { var out []Relationship for _, cluster := range t.Clusters { for _, n := range cluster.Nodes { for _, w := range n.Workloads { - for _, dest := range w.Destinations { + for _, us := range w.Upstreams { out = append(out, Relationship{ - Caller: w, - Destination: dest, - Upstream: dest, - }) - } - for _, dest := range w.ImpliedDestinations { - out = append(out, Relationship{ - Caller: w, - Destination: dest, - Upstream: dest, + Caller: w, + Upstream: us, }) } } @@ -43,18 +35,14 @@ func RenderRelationships(ships []Relationship) string { w := tabwriter.NewWriter(&buf, 0, 0, 3, ' ', tabwriter.Debug) fmt.Fprintf(w, "CALLER\tnode\tservice\tport\tDEST\tservice\t\n") for _, r := range ships { - suffix := "" - if r.Destination.Implied { - suffix = " (implied)" - } fmt.Fprintf(w, "%s\t%s\t%s\t%d\t%s\t%s\t\n", r.callingCluster(), r.Caller.Node.ID().String(), r.Caller.ID.String(), - r.Destination.LocalPort, - r.destinationCluster(), - r.Destination.ID.String()+suffix, + r.Upstream.LocalPort, + r.upstreamCluster(), + r.Upstream.ID.String(), ) } fmt.Fprintf(w, "\t\t\t\t\t\t\n") @@ -64,27 +52,19 @@ func RenderRelationships(ships []Relationship) string { } type Relationship struct { - Caller *Workload - Destination *Destination - - // Deprecated: Destination - Upstream *Destination + Caller *Workload + Upstream *Upstream } func (r Relationship) String() string { - suffix := "" - if r.Destination.PortName != "" { - suffix = " port " + r.Destination.PortName - } return fmt.Sprintf( - "%s on %s in %s via :%d => %s in %s%s", + "%s on %s in %s via :%d => %s in %s", r.Caller.ID.String(), r.Caller.Node.ID().String(), r.callingCluster(), - r.Destination.LocalPort, - r.Destination.ID.String(), - r.destinationCluster(), - suffix, + r.Upstream.LocalPort, + r.Upstream.ID.String(), + r.upstreamCluster(), ) } @@ -92,6 +72,6 @@ func (r Relationship) callingCluster() string { return r.Caller.Node.Cluster } -func (r Relationship) destinationCluster() string { - return r.Destination.Cluster +func (r Relationship) upstreamCluster() string { + return r.Upstream.Cluster } diff --git a/testing/deployer/topology/topology.go b/testing/deployer/topology/topology.go index a45b27678d..a2feefca4b 100644 --- a/testing/deployer/topology/topology.go +++ b/testing/deployer/topology/topology.go @@ -10,17 +10,11 @@ import ( "net/netip" "reflect" "sort" - "strings" "github.com/hashicorp/consul/api" - pbcatalog "github.com/hashicorp/consul/proto-public/pbcatalog/v2beta1" "github.com/hashicorp/consul/proto-public/pbresource" ) -const ( - V1DefaultPortName = "legacy" -) - type Topology struct { ID string @@ -252,14 +246,6 @@ type Cluster struct { // components. Enterprise bool `json:",omitempty"` - // Services is a forward declaration of V2 services. This goes in hand with - // the V2Services field on the Service (instance) struct. - // - // Use of this is optional. If you elect not to use it, then v2 Services - // definitions are inferred from the list of service instances defined on - // the nodes in this cluster. - Services map[ID]*pbcatalog.Service `json:"omitempty"` - // Nodes is the definition of the nodes (agent-less and agent-ful). Nodes []*Node @@ -295,14 +281,6 @@ type Cluster struct { // Denormalized during compile. Peerings map[string]*PeerCluster `json:",omitempty"` - // EnableV2 activates V2 on the servers. If any node in the cluster needs - // V2 this will be turned on automatically. - EnableV2 bool `json:",omitempty"` - - // EnableV2Tenancy activates V2 tenancy on the servers. If not enabled, - // V2 resources are bridged to V1 tenancy counterparts. - EnableV2Tenancy bool `json:",omitempty"` - // Segments is a map of network segment name and the ports Segments map[string]int @@ -505,14 +483,6 @@ const ( NodeKindDataplane NodeKind = "dataplane" ) -type NodeVersion string - -const ( - NodeVersionUnknown NodeVersion = "" - NodeVersionV1 NodeVersion = "v1" - NodeVersionV2 NodeVersion = "v2" -) - type NetworkSegment struct { Name string Port int @@ -521,7 +491,6 @@ type NetworkSegment struct { // TODO: rename pod type Node struct { Kind NodeKind - Version NodeVersion Partition string // will be not empty Name string // logical name @@ -534,8 +503,6 @@ type Node struct { Addresses []*Address Workloads []*Workload - // Deprecated: use Workloads - Services []*Workload // denormalized at topology compile Cluster string @@ -685,14 +652,6 @@ func (n *Node) PublicProxyPort() int { panic("node has no public network") } -func (n *Node) IsV2() bool { - return n.Version == NodeVersionV2 -} - -func (n *Node) IsV1() bool { - return !n.IsV2() -} - func (n *Node) IsServer() bool { return n.Kind == NodeKindServer } @@ -725,15 +684,6 @@ func (n *Node) SortedWorkloads() []*Workload { return out } -func (n *Node) NeedsTransparentProxy() bool { - for _, svc := range n.Workloads { - if svc.EnableTransparentProxy { - return true - } - } - return false -} - // DigestExposedPorts returns true if it was changed. func (n *Node) DigestExposedPorts(ports map[int]int) bool { if reflect.DeepEqual(n.usedPorts, ports) { @@ -768,63 +718,12 @@ func (n *Node) WorkloadByID(id ID) *Workload { panic("workload not found: " + id.String()) } -// Protocol is a convenience function to use when authoring topology configs. -func Protocol(s string) (pbcatalog.Protocol, bool) { - switch strings.ToLower(s) { - case "tcp": - return pbcatalog.Protocol_PROTOCOL_TCP, true - case "http": - return pbcatalog.Protocol_PROTOCOL_HTTP, true - case "http2": - return pbcatalog.Protocol_PROTOCOL_HTTP2, true - case "grpc": - return pbcatalog.Protocol_PROTOCOL_GRPC, true - case "mesh": - return pbcatalog.Protocol_PROTOCOL_MESH, true - default: - return pbcatalog.Protocol_PROTOCOL_UNSPECIFIED, false - } -} - -type Port struct { - Number int - Protocol string `json:",omitempty"` - - // denormalized at topology compile - ActualProtocol pbcatalog.Protocol `json:",omitempty"` -} - type Workload struct { ID ID Image string - // Port is the v1 single-port of this service. Port int `json:",omitempty"` - // Ports is the v2 multi-port list for this service. - // - // This only applies for multi-port (v2). - Ports map[string]*Port `json:",omitempty"` - - // V2Services contains service names (which are merged with the tenancy - // info from ID) to resolve services in the Services slice in the Cluster - // definition. - // - // If omitted it is inferred that the ID.Name field is the singular service - // for this workload. - // - // This only applies for multi-port (v2). - V2Services []string `json:",omitempty"` - - // WorkloadIdentity contains named WorkloadIdentity to assign to this - // workload. - // - // If omitted it is inferred that the ID.Name field is the singular - // identity for this workload. - // - // This only applies for multi-port (v2). - WorkloadIdentity string `json:",omitempty"` - Disabled bool `json:",omitempty"` // TODO // TODO: expose extra port here? @@ -842,55 +741,19 @@ type Workload struct { Command []string `json:",omitempty"` // optional Env []string `json:",omitempty"` // optional - EnableTransparentProxy bool `json:",omitempty"` - DisableServiceMesh bool `json:",omitempty"` - IsMeshGateway bool `json:",omitempty"` - Destinations []*Destination `json:",omitempty"` - ImpliedDestinations []*Destination `json:",omitempty"` - - // Deprecated: Destinations - Upstreams []*Destination `json:",omitempty"` - // Deprecated: ImpliedDestinations - ImpliedUpstreams []*Destination `json:",omitempty"` + DisableServiceMesh bool `json:",omitempty"` + IsMeshGateway bool `json:",omitempty"` + Upstreams []*Upstream `json:",omitempty"` // denormalized at topology compile - Node *Node `json:"-"` - NodeVersion NodeVersion `json:"-"` - Workload string `json:"-"` + Node *Node `json:"-"` } -func (w *Workload) ExposedPort(name string) int { +func (w *Workload) ExposedPort() int { if w.Node == nil { panic("ExposedPort cannot be called until after Compile") } - - var internalPort int - if name == "" { - internalPort = w.Port - } else { - port, ok := w.Ports[name] - if !ok { - panic("port with name " + name + " not present on service") - } - internalPort = port.Number - } - - return w.Node.ExposedPort(internalPort) -} - -func (w *Workload) PortOrDefault(name string) int { - if len(w.Ports) > 0 { - return w.Ports[name].Number - } - return w.Port -} - -func (w *Workload) IsV2() bool { - return w.NodeVersion == NodeVersionV2 -} - -func (w *Workload) IsV1() bool { - return !w.IsV2() + return w.Node.ExposedPort(w.Port) } func (w *Workload) inheritFromExisting(existing *Workload) { @@ -899,19 +762,7 @@ func (w *Workload) inheritFromExisting(existing *Workload) { func (w *Workload) ports() []int { var out []int - if len(w.Ports) > 0 { - seen := make(map[int]struct{}) - for _, port := range w.Ports { - if port == nil { - continue - } - if _, ok := seen[port.Number]; !ok { - // It's totally fine to expose the same port twice in a workload. - seen[port.Number] = struct{}{} - out = append(out, port.Number) - } - } - } else if w.Port > 0 { + if w.Port > 0 { out = append(out, w.Port) } if w.EnvoyAdminPort > 0 { @@ -920,9 +771,9 @@ func (w *Workload) ports() []int { if w.EnvoyPublicListenerPort > 0 { out = append(out, w.EnvoyPublicListenerPort) } - for _, dest := range w.Destinations { - if dest.LocalPort > 0 { - out = append(out, dest.LocalPort) + for _, us := range w.Upstreams { + if us.LocalPort > 0 { + out = append(out, us.LocalPort) } } return out @@ -950,78 +801,14 @@ func (w *Workload) Validate() error { return fmt.Errorf("service image is required") } - if len(w.Upstreams) > 0 { - w.Destinations = append(w.Destinations, w.Upstreams...) - w.Upstreams = nil - } - if len(w.ImpliedUpstreams) > 0 { - w.ImpliedDestinations = append(w.ImpliedDestinations, w.ImpliedUpstreams...) - w.ImpliedUpstreams = nil - } - - if w.IsV2() { - if len(w.Ports) > 0 && w.Port > 0 { - return fmt.Errorf("cannot specify both singleport and multiport on service in v2") - } - if w.Port > 0 { - w.Ports = map[string]*Port{ - V1DefaultPortName: { - Number: w.Port, - Protocol: "tcp", - }, - } - w.Port = 0 - } - if w.Ports == nil { - w.Ports = make(map[string]*Port) - } - - if !w.DisableServiceMesh && w.EnvoyPublicListenerPort > 0 { - w.Ports["mesh"] = &Port{ - Number: w.EnvoyPublicListenerPort, - Protocol: "mesh", - } - } - - for name, port := range w.Ports { - if port == nil { - return fmt.Errorf("cannot be nil") - } - if port.Number <= 0 { - return fmt.Errorf("service has invalid port number %q", name) - } - if port.ActualProtocol != pbcatalog.Protocol_PROTOCOL_UNSPECIFIED { - return fmt.Errorf("user cannot specify ActualProtocol field") - } - - proto, valid := Protocol(port.Protocol) - if !valid { - return fmt.Errorf("service has invalid port protocol %q", port.Protocol) - } - port.ActualProtocol = proto - } - } else { - if len(w.Ports) > 0 { - return fmt.Errorf("cannot specify multiport on service in v1") - } - if w.Port <= 0 { - return fmt.Errorf("service has invalid port") - } - if w.EnableTransparentProxy { - return fmt.Errorf("tproxy does not work with v1 yet") - } + if w.Port <= 0 { + return fmt.Errorf("service has invalid port") } if w.DisableServiceMesh && w.IsMeshGateway { return fmt.Errorf("cannot disable service mesh and still run a mesh gateway") } - if w.DisableServiceMesh && len(w.Destinations) > 0 { - return fmt.Errorf("cannot disable service mesh and configure destinations") - } - if w.DisableServiceMesh && len(w.ImpliedDestinations) > 0 { - return fmt.Errorf("cannot disable service mesh and configure implied destinations") - } - if w.DisableServiceMesh && w.EnableTransparentProxy { - return fmt.Errorf("cannot disable service mesh and activate tproxy") + if w.DisableServiceMesh && len(w.Upstreams) > 0 { + return fmt.Errorf("cannot disable service mesh and configure upstreams") } if w.DisableServiceMesh { @@ -1034,59 +821,36 @@ func (w *Workload) Validate() error { } } - for _, dest := range w.Destinations { - if dest.ID.Name == "" { - return fmt.Errorf("destination service name is required") + for _, us := range w.Upstreams { + if us.ID.Name == "" { + return fmt.Errorf("upstream service name is required") } - if dest.LocalPort <= 0 { - return fmt.Errorf("destination local port is required") + if us.LocalPort <= 0 { + return fmt.Errorf("upstream local port is required") } - if dest.LocalAddress != "" { - ip := net.ParseIP(dest.LocalAddress) + if us.LocalAddress != "" { + ip := net.ParseIP(us.LocalAddress) if ip == nil { - return fmt.Errorf("destination local address is invalid: %s", dest.LocalAddress) + return fmt.Errorf("upstream local address is invalid: %s", us.LocalAddress) } } - if dest.Implied { - return fmt.Errorf("implied field cannot be set") - } - } - for _, dest := range w.ImpliedDestinations { - if dest.ID.Name == "" { - return fmt.Errorf("implied destination service name is required") - } - if dest.LocalPort > 0 { - return fmt.Errorf("implied destination local port cannot be set") - } - if dest.LocalAddress != "" { - return fmt.Errorf("implied destination local address cannot be set") - } } return nil } -type Destination struct { +type Upstream struct { ID ID LocalAddress string `json:",omitempty"` // defaults to 127.0.0.1 LocalPort int Peer string `json:",omitempty"` - // PortName is the port of this Destination to route traffic to. - // - // For more details on potential values of this field, see documentation - // for Service.ServicePort. - // - // This only applies for multi-port (v2). - PortName string `json:",omitempty"` // TODO: what about mesh gateway mode overrides? // computed at topology compile - Cluster string `json:",omitempty"` - Peering *PeerCluster `json:",omitempty"` // this will have Link!=nil - Implied bool `json:",omitempty"` - VirtualPort uint32 `json:",omitempty"` + Cluster string `json:",omitempty"` + Peering *PeerCluster `json:",omitempty"` // this will have Link!=nil } type Peering struct {