mirror of https://github.com/hashicorp/consul
354 lines
9.2 KiB
Go
354 lines
9.2 KiB
Go
// Copyright (c) HashiCorp, Inc.
|
|
// SPDX-License-Identifier: BUSL-1.1
|
|
|
|
//go:build integration
|
|
|
|
package sprawltest_test
|
|
|
|
import (
|
|
"strconv"
|
|
"testing"
|
|
|
|
"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)
|
|
|
|
cfg := &topology.Config{
|
|
Images: topology.Images{
|
|
// ConsulEnterprise: "consul-dev:latest",
|
|
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: "dc2"},
|
|
{Name: "wan", Type: "wan"},
|
|
},
|
|
Clusters: []*topology.Cluster{
|
|
{
|
|
Name: "dc1",
|
|
Nodes: topology.MergeSlices(serversDC1, []*topology.Node{
|
|
{
|
|
Kind: topology.NodeKindClient,
|
|
Name: "dc1-client1",
|
|
Workloads: []*topology.Workload{
|
|
{
|
|
ID: topology.ID{Name: "mesh-gateway"},
|
|
Port: 8443,
|
|
EnvoyAdminPort: 19000,
|
|
IsMeshGateway: true,
|
|
},
|
|
},
|
|
},
|
|
{
|
|
Kind: topology.NodeKindClient,
|
|
Name: "dc1-client2",
|
|
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,
|
|
Peer: "peer-dc2-default",
|
|
}},
|
|
},
|
|
},
|
|
},
|
|
}),
|
|
InitialConfigEntries: []api.ConfigEntry{
|
|
&api.ExportedServicesConfigEntry{
|
|
Name: "default",
|
|
Services: []api.ExportedService{{
|
|
Name: "ping",
|
|
Consumers: []api.ServiceConsumer{{
|
|
Peer: "peer-dc2-default",
|
|
}},
|
|
}},
|
|
},
|
|
},
|
|
},
|
|
{
|
|
Name: "dc2",
|
|
Nodes: topology.MergeSlices(serversDC2, []*topology.Node{
|
|
{
|
|
Kind: topology.NodeKindClient,
|
|
Name: "dc2-client1",
|
|
Workloads: []*topology.Workload{
|
|
{
|
|
ID: topology.ID{Name: "mesh-gateway"},
|
|
Port: 8443,
|
|
EnvoyAdminPort: 19000,
|
|
IsMeshGateway: true,
|
|
},
|
|
},
|
|
},
|
|
{
|
|
Kind: topology.NodeKindDataplane,
|
|
Name: "dc2-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,
|
|
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{{
|
|
ID: topology.ID{Name: "ping"},
|
|
LocalPort: 9090,
|
|
Peer: "peer-dc1-default",
|
|
}},
|
|
},
|
|
},
|
|
},
|
|
}),
|
|
InitialConfigEntries: []api.ConfigEntry{
|
|
&api.ExportedServicesConfigEntry{
|
|
Name: "default",
|
|
Services: []api.ExportedService{{
|
|
Name: "ping",
|
|
Consumers: []api.ServiceConsumer{{
|
|
Peer: "peer-dc2-default",
|
|
}},
|
|
}},
|
|
},
|
|
},
|
|
},
|
|
},
|
|
Peerings: []*topology.Peering{{
|
|
Dialing: topology.PeerCluster{
|
|
Name: "dc1",
|
|
},
|
|
Accepting: topology.PeerCluster{
|
|
Name: "dc2",
|
|
},
|
|
}},
|
|
}
|
|
|
|
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 newTopologyServerSet(
|
|
namePrefix string,
|
|
num int,
|
|
networks []string,
|
|
mutateFn func(i int, node *topology.Node),
|
|
) []*topology.Node {
|
|
var out []*topology.Node
|
|
for i := 1; i <= num; i++ {
|
|
name := namePrefix + strconv.Itoa(i)
|
|
|
|
node := &topology.Node{
|
|
Kind: topology.NodeKindServer,
|
|
Name: name,
|
|
}
|
|
for _, net := range networks {
|
|
node.Addresses = append(node.Addresses, &topology.Address{Network: net})
|
|
}
|
|
|
|
if mutateFn != nil {
|
|
mutateFn(i, node)
|
|
}
|
|
|
|
out = append(out, node)
|
|
}
|
|
return out
|
|
}
|