2023-01-11 21:34:27 +00:00
|
|
|
package topology
|
|
|
|
|
|
|
|
import (
|
|
|
|
"context"
|
|
|
|
"fmt"
|
|
|
|
"testing"
|
|
|
|
|
|
|
|
"github.com/stretchr/testify/require"
|
|
|
|
|
2023-01-20 22:02:44 +00:00
|
|
|
"github.com/hashicorp/consul/api"
|
|
|
|
|
2023-01-11 21:34:27 +00:00
|
|
|
libassert "github.com/hashicorp/consul/test/integration/consul-container/libs/assert"
|
|
|
|
libcluster "github.com/hashicorp/consul/test/integration/consul-container/libs/cluster"
|
|
|
|
libservice "github.com/hashicorp/consul/test/integration/consul-container/libs/service"
|
|
|
|
"github.com/hashicorp/consul/test/integration/consul-container/libs/utils"
|
|
|
|
)
|
|
|
|
|
|
|
|
const (
|
|
|
|
AcceptingPeerName = "accepting-to-dialer"
|
|
|
|
DialingPeerName = "dialing-to-acceptor"
|
|
|
|
)
|
|
|
|
|
|
|
|
type BuiltCluster struct {
|
|
|
|
Cluster *libcluster.Cluster
|
|
|
|
Context *libcluster.BuildContext
|
|
|
|
Service libservice.Service
|
2023-02-13 19:09:12 +00:00
|
|
|
Container libservice.Service
|
2023-01-27 16:25:48 +00:00
|
|
|
Gateway libservice.Service
|
2023-01-11 21:34:27 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
// BasicPeeringTwoClustersSetup sets up a scenario for testing peering, which consists of
|
|
|
|
//
|
|
|
|
// - an accepting cluster with 3 servers and 1 client agent. The client should be used to
|
|
|
|
// host a service for export: staticServerSvc.
|
|
|
|
// - an dialing cluster with 1 server and 1 client. The client should be used to host a
|
|
|
|
// service connecting to staticServerSvc.
|
|
|
|
// - Create the peering, export the service from accepting cluster, and verify service
|
|
|
|
// connectivity.
|
|
|
|
//
|
|
|
|
// It returns objects of the accepting cluster, dialing cluster, staticServerSvc, and staticClientSvcSidecar
|
|
|
|
func BasicPeeringTwoClustersSetup(
|
|
|
|
t *testing.T,
|
|
|
|
consulVersion string,
|
2023-02-15 15:26:43 +00:00
|
|
|
peeringThroughMeshgateway bool,
|
2023-01-11 21:34:27 +00:00
|
|
|
) (*BuiltCluster, *BuiltCluster) {
|
2023-02-07 19:13:19 +00:00
|
|
|
// acceptingCluster, acceptingCtx, acceptingClient := NewPeeringCluster(t, "dc1", 3, consulVersion, true)
|
2023-03-01 20:45:27 +00:00
|
|
|
acceptingCluster, acceptingCtx, acceptingClient := NewPeeringCluster(t, 3, 1, &libcluster.BuildOptions{
|
2023-02-07 19:13:19 +00:00
|
|
|
Datacenter: "dc1",
|
|
|
|
ConsulVersion: consulVersion,
|
|
|
|
InjectAutoEncryption: true,
|
|
|
|
})
|
2023-03-01 20:45:27 +00:00
|
|
|
dialingCluster, dialingCtx, dialingClient := NewPeeringCluster(t, 1, 1, &libcluster.BuildOptions{
|
2023-02-07 19:13:19 +00:00
|
|
|
Datacenter: "dc2",
|
|
|
|
ConsulVersion: consulVersion,
|
|
|
|
InjectAutoEncryption: true,
|
|
|
|
})
|
2023-02-15 15:26:43 +00:00
|
|
|
|
|
|
|
// Create the mesh gateway for dataplane traffic and peering control plane traffic (if enabled)
|
|
|
|
acceptingClusterGateway, err := libservice.NewGatewayService(context.Background(), "mesh", "mesh", acceptingCluster.Clients()[0])
|
|
|
|
require.NoError(t, err)
|
|
|
|
dialingClusterGateway, err := libservice.NewGatewayService(context.Background(), "mesh", "mesh", dialingCluster.Clients()[0])
|
|
|
|
require.NoError(t, err)
|
|
|
|
|
|
|
|
// Enable peering control plane traffic through mesh gateway
|
|
|
|
if peeringThroughMeshgateway {
|
|
|
|
req := &api.MeshConfigEntry{
|
|
|
|
Peering: &api.PeeringMeshConfig{
|
|
|
|
PeerThroughMeshGateways: true,
|
|
|
|
},
|
|
|
|
}
|
|
|
|
configCluster := func(cli *api.Client) error {
|
|
|
|
libassert.CatalogServiceExists(t, cli, "mesh")
|
|
|
|
ok, _, err := cli.ConfigEntries().Set(req, &api.WriteOptions{})
|
|
|
|
if !ok {
|
|
|
|
return fmt.Errorf("config entry is not set")
|
|
|
|
}
|
|
|
|
|
|
|
|
if err != nil {
|
|
|
|
return fmt.Errorf("error writing config entry: %s", err)
|
|
|
|
}
|
|
|
|
return nil
|
|
|
|
}
|
|
|
|
err = configCluster(dialingClient)
|
|
|
|
require.NoError(t, err)
|
|
|
|
err = configCluster(acceptingClient)
|
|
|
|
require.NoError(t, err)
|
|
|
|
}
|
|
|
|
|
2023-01-11 21:34:27 +00:00
|
|
|
require.NoError(t, dialingCluster.PeerWithCluster(acceptingClient, AcceptingPeerName, DialingPeerName))
|
|
|
|
|
|
|
|
libassert.PeeringStatus(t, acceptingClient, AcceptingPeerName, api.PeeringStateActive)
|
|
|
|
// libassert.PeeringExports(t, acceptingClient, acceptingPeerName, 1)
|
|
|
|
|
|
|
|
// Register an static-server service in acceptingCluster and export to dialing cluster
|
2023-02-13 19:09:12 +00:00
|
|
|
var serverService, serverSidecarService libservice.Service
|
2023-01-11 21:34:27 +00:00
|
|
|
{
|
|
|
|
clientNode := acceptingCluster.Clients()[0]
|
|
|
|
|
|
|
|
// Create a service and proxy instance
|
|
|
|
var err error
|
2023-02-03 15:20:22 +00:00
|
|
|
// Create a service and proxy instance
|
|
|
|
serviceOpts := libservice.ServiceOpts{
|
2023-02-09 14:45:31 +00:00
|
|
|
Name: libservice.StaticServerServiceName,
|
|
|
|
ID: "static-server",
|
|
|
|
Meta: map[string]string{"version": ""},
|
|
|
|
HTTPPort: 8080,
|
|
|
|
GRPCPort: 8079,
|
2023-02-03 15:20:22 +00:00
|
|
|
}
|
2023-02-13 19:09:12 +00:00
|
|
|
serverService, serverSidecarService, err = libservice.CreateAndRegisterStaticServerAndSidecar(clientNode, &serviceOpts)
|
2023-01-11 21:34:27 +00:00
|
|
|
require.NoError(t, err)
|
|
|
|
|
2023-02-03 15:20:22 +00:00
|
|
|
libassert.CatalogServiceExists(t, acceptingClient, libservice.StaticServerServiceName)
|
2023-01-11 21:34:27 +00:00
|
|
|
libassert.CatalogServiceExists(t, acceptingClient, "static-server-sidecar-proxy")
|
|
|
|
|
2023-02-13 19:09:12 +00:00
|
|
|
require.NoError(t, serverService.Export("default", AcceptingPeerName, acceptingClient))
|
2023-01-11 21:34:27 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
// Register an static-client service in dialing cluster and set upstream to static-server service
|
|
|
|
var clientSidecarService *libservice.ConnectContainer
|
|
|
|
{
|
|
|
|
clientNode := dialingCluster.Clients()[0]
|
|
|
|
|
|
|
|
// Create a service and proxy instance
|
|
|
|
var err error
|
|
|
|
clientSidecarService, err = libservice.CreateAndRegisterStaticClientSidecar(clientNode, DialingPeerName, true)
|
|
|
|
require.NoError(t, err)
|
|
|
|
|
|
|
|
libassert.CatalogServiceExists(t, dialingClient, "static-client-sidecar-proxy")
|
2023-01-27 16:25:48 +00:00
|
|
|
|
2023-01-11 21:34:27 +00:00
|
|
|
}
|
|
|
|
|
2023-01-25 17:27:36 +00:00
|
|
|
_, adminPort := clientSidecarService.GetAdminAddr()
|
|
|
|
libassert.AssertUpstreamEndpointStatus(t, adminPort, fmt.Sprintf("static-server.default.%s.external", DialingPeerName), "HEALTHY", 1)
|
2023-01-11 21:34:27 +00:00
|
|
|
_, port := clientSidecarService.GetAddr()
|
2023-01-20 22:02:44 +00:00
|
|
|
libassert.HTTPServiceEchoes(t, "localhost", port, "")
|
2023-03-01 20:45:27 +00:00
|
|
|
libassert.AssertFortioName(t, fmt.Sprintf("http://localhost:%d", port), "static-server", "")
|
2023-01-11 21:34:27 +00:00
|
|
|
|
|
|
|
return &BuiltCluster{
|
|
|
|
Cluster: acceptingCluster,
|
|
|
|
Context: acceptingCtx,
|
|
|
|
Service: serverSidecarService,
|
2023-02-13 19:09:12 +00:00
|
|
|
Container: serverSidecarService,
|
2023-01-27 16:25:48 +00:00
|
|
|
Gateway: acceptingClusterGateway,
|
2023-01-11 21:34:27 +00:00
|
|
|
},
|
|
|
|
&BuiltCluster{
|
|
|
|
Cluster: dialingCluster,
|
|
|
|
Context: dialingCtx,
|
|
|
|
Service: nil,
|
|
|
|
Container: clientSidecarService,
|
2023-01-27 16:25:48 +00:00
|
|
|
Gateway: dialingClusterGateway,
|
2023-01-11 21:34:27 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// NewDialingCluster creates a cluster for peering with a single dev agent
|
|
|
|
// TODO: note: formerly called CreatingPeeringClusterAndSetup
|
|
|
|
//
|
|
|
|
// Deprecated: use NewPeeringCluster mostly
|
|
|
|
func NewDialingCluster(
|
|
|
|
t *testing.T,
|
|
|
|
version string,
|
|
|
|
dialingPeerName string,
|
|
|
|
) (*libcluster.Cluster, *api.Client, libservice.Service) {
|
|
|
|
t.Helper()
|
|
|
|
t.Logf("creating the dialing cluster")
|
|
|
|
|
|
|
|
opts := libcluster.BuildOptions{
|
|
|
|
Datacenter: "dc2",
|
|
|
|
InjectAutoEncryption: true,
|
|
|
|
InjectGossipEncryption: true,
|
|
|
|
AllowHTTPAnyway: true,
|
|
|
|
ConsulVersion: version,
|
|
|
|
}
|
|
|
|
ctx := libcluster.NewBuildContext(t, opts)
|
|
|
|
|
|
|
|
conf := libcluster.NewConfigBuilder(ctx).
|
|
|
|
Peering(true).
|
|
|
|
ToAgentConfig(t)
|
|
|
|
t.Logf("dc2 server config: \n%s", conf.JSON)
|
|
|
|
|
|
|
|
cluster, err := libcluster.NewN(t, *conf, 1)
|
|
|
|
require.NoError(t, err)
|
|
|
|
|
|
|
|
node := cluster.Agents[0]
|
|
|
|
client := node.GetClient()
|
|
|
|
libcluster.WaitForLeader(t, cluster, client)
|
|
|
|
libcluster.WaitForMembers(t, client, 1)
|
|
|
|
|
|
|
|
// Default Proxy Settings
|
|
|
|
ok, err := utils.ApplyDefaultProxySettings(client)
|
|
|
|
require.NoError(t, err)
|
|
|
|
require.True(t, ok)
|
|
|
|
|
|
|
|
// Create the mesh gateway for dataplane traffic
|
|
|
|
_, err = libservice.NewGatewayService(context.Background(), "mesh", "mesh", node)
|
|
|
|
require.NoError(t, err)
|
|
|
|
|
|
|
|
// Create a service and proxy instance
|
|
|
|
clientProxyService, err := libservice.CreateAndRegisterStaticClientSidecar(node, dialingPeerName, true)
|
|
|
|
require.NoError(t, err)
|
|
|
|
|
|
|
|
libassert.CatalogServiceExists(t, client, "static-client-sidecar-proxy")
|
|
|
|
|
|
|
|
return cluster, client, clientProxyService
|
|
|
|
}
|
|
|
|
|
|
|
|
// NewPeeringCluster creates a cluster with peering enabled. It also creates
|
|
|
|
// and registers a mesh-gateway at the client agent. The API client returned is
|
|
|
|
// pointed at the client agent.
|
2023-02-13 19:09:12 +00:00
|
|
|
// - proxy-defaults.protocol = tcp
|
2023-01-11 21:34:27 +00:00
|
|
|
func NewPeeringCluster(
|
|
|
|
t *testing.T,
|
|
|
|
numServers int,
|
2023-03-01 20:45:27 +00:00
|
|
|
numClients int,
|
2023-02-07 19:13:19 +00:00
|
|
|
buildOpts *libcluster.BuildOptions,
|
2023-01-11 21:34:27 +00:00
|
|
|
) (*libcluster.Cluster, *libcluster.BuildContext, *api.Client) {
|
2023-02-07 19:13:19 +00:00
|
|
|
require.NotEmpty(t, buildOpts.Datacenter)
|
2023-01-11 21:34:27 +00:00
|
|
|
require.True(t, numServers > 0)
|
|
|
|
|
|
|
|
opts := libcluster.BuildOptions{
|
2023-02-07 19:13:19 +00:00
|
|
|
Datacenter: buildOpts.Datacenter,
|
|
|
|
InjectAutoEncryption: buildOpts.InjectAutoEncryption,
|
2023-01-11 21:34:27 +00:00
|
|
|
InjectGossipEncryption: true,
|
|
|
|
AllowHTTPAnyway: true,
|
2023-02-07 19:13:19 +00:00
|
|
|
ConsulVersion: buildOpts.ConsulVersion,
|
|
|
|
ACLEnabled: buildOpts.ACLEnabled,
|
2023-01-11 21:34:27 +00:00
|
|
|
}
|
|
|
|
ctx := libcluster.NewBuildContext(t, opts)
|
|
|
|
|
|
|
|
serverConf := libcluster.NewConfigBuilder(ctx).
|
|
|
|
Bootstrap(numServers).
|
|
|
|
Peering(true).
|
|
|
|
ToAgentConfig(t)
|
2023-02-07 19:13:19 +00:00
|
|
|
t.Logf("%s server config: \n%s", opts.Datacenter, serverConf.JSON)
|
2023-01-11 21:34:27 +00:00
|
|
|
|
|
|
|
cluster, err := libcluster.NewN(t, *serverConf, numServers)
|
|
|
|
require.NoError(t, err)
|
|
|
|
|
|
|
|
var retryJoin []string
|
|
|
|
for i := 0; i < numServers; i++ {
|
|
|
|
retryJoin = append(retryJoin, fmt.Sprintf("agent-%d", i))
|
|
|
|
}
|
|
|
|
|
2023-03-01 20:45:27 +00:00
|
|
|
// Add numClients static clients to register the service
|
2023-02-07 19:13:19 +00:00
|
|
|
configbuiilder := libcluster.NewConfigBuilder(ctx).
|
2023-01-11 21:34:27 +00:00
|
|
|
Client().
|
|
|
|
Peering(true).
|
2023-02-07 19:13:19 +00:00
|
|
|
RetryJoin(retryJoin...)
|
|
|
|
clientConf := configbuiilder.ToAgentConfig(t)
|
|
|
|
t.Logf("%s client config: \n%s", opts.Datacenter, clientConf.JSON)
|
2023-01-11 21:34:27 +00:00
|
|
|
|
2023-03-01 20:45:27 +00:00
|
|
|
require.NoError(t, cluster.AddN(*clientConf, numClients, true))
|
2023-01-11 21:34:27 +00:00
|
|
|
|
|
|
|
// Use the client agent as the HTTP endpoint since we will not rotate it in many tests.
|
|
|
|
clientNode := cluster.Agents[numServers]
|
|
|
|
client := clientNode.GetClient()
|
|
|
|
libcluster.WaitForLeader(t, cluster, client)
|
2023-03-01 20:45:27 +00:00
|
|
|
libcluster.WaitForMembers(t, client, numServers+numClients)
|
2023-01-11 21:34:27 +00:00
|
|
|
|
|
|
|
// Default Proxy Settings
|
|
|
|
ok, err := utils.ApplyDefaultProxySettings(client)
|
|
|
|
require.NoError(t, err)
|
|
|
|
require.True(t, ok)
|
|
|
|
|
|
|
|
return cluster, ctx, client
|
|
|
|
}
|