consul/testing/deployer
cskh 3b806d41c0
test deployer: fix a bug when deploying cluster with various ent images (#19381)
2023-10-26 13:12:20 -04:00
..
sprawl chore: fix ce/ent drift in sdk and testing/deployer submodules (#19041) 2023-10-03 10:06:50 -05:00
topology test deployer: fix a bug when deploying cluster with various ent images (#19381) 2023-10-26 13:12:20 -04:00
util [COMPLIANCE] License changes (#18443) 2023-08-11 09:12:13 -04:00
.gitignore Add `testing/deployer` (neé `consul-topology`) [NET-4610] (#17823) 2023-07-17 15:15:22 -07:00
README.md Add `testing/deployer` (neé `consul-topology`) [NET-4610] (#17823) 2023-07-17 15:15:22 -07:00
TODO.md Add `testing/deployer` (neé `consul-topology`) [NET-4610] (#17823) 2023-07-17 15:15:22 -07:00
go.mod [NET-5944] security: Update Go version to 1.20.10 and `x/net` to 0.17.0 (#19225) 2023-10-16 17:49:04 -04:00
go.sum [NET-5944] security: Update Go version to 1.20.10 and `x/net` to 0.17.0 (#19225) 2023-10-16 17:49:04 -04:00

README.md

GoDoc

Summary

This is a Go library used to launch one or more Consul clusters that can be peered using the cluster peering feature. Under the covers terraform is used in conjunction with the kreuzwerker/docker provider to manage a fleet of local docker containers and networks.

Configuration

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 consul-dataplane instances are supported.

Here is an example configuration with two peered clusters:

cfg := &topology.Config{
    Networks: []*topology.Network{
        {Name: "dc1"},
        {Name: "dc2"},
        {Name: "wan", Type: "wan"},
    },
    Clusters: []*topology.Cluster{
        {
            Name: "dc1",
            Nodes: []*topology.Node{
                {
                    Kind: topology.NodeKindServer,
                    Name: "dc1-server1",
                    Addresses: []*topology.Address{
                        {Network: "dc1"},
                        {Network: "wan"},
                    },
                },
                {
                    Kind: topology.NodeKindClient,
                    Name: "dc1-client1",
                    Services: []*topology.Service{
                        {
                            ID:             topology.ServiceID{Name: "mesh-gateway"},
                            Port:           8443,
                            EnvoyAdminPort: 19000,
                            IsMeshGateway:  true,
                        },
                    },
                },
                {
                    Kind: topology.NodeKindClient,
                    Name: "dc1-client2",
                    Services: []*topology.Service{
                        {
                            ID:             topology.ServiceID{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",
                            },
                            Upstreams: []*topology.Upstream{{
                                ID:        topology.ServiceID{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.Node{
                {
                    Kind: topology.NodeKindServer,
                    Name: "dc2-server1",
                    Addresses: []*topology.Address{
                        {Network: "dc2"},
                        {Network: "wan"},
                    },
                },
                {
                    Kind: topology.NodeKindClient,
                    Name: "dc2-client1",
                    Services: []*topology.Service{
                        {
                            ID:             topology.ServiceID{Name: "mesh-gateway"},
                            Port:           8443,
                            EnvoyAdminPort: 19000,
                            IsMeshGateway:  true,
                        },
                    },
                },
                {
                    Kind: topology.NodeKindDataplane,
                    Name: "dc2-client2",
                    Services: []*topology.Service{
                        {
                            ID:             topology.ServiceID{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",
                            },
                            Upstreams: []*topology.Upstream{{
                                ID:        topology.ServiceID{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",
        },
    }},
}

Once you have a topology configuration, you simply call the appropriate Launch function to validate and boot the cluster.

You may also modify your original configuration (in some allowed ways) and call Relaunch on an existing topology which will differentially adjust the running infrastructure. This can be useful to do things like upgrade instances in place or subly reconfigure them.

For Testing

It is meant to be consumed primarily by unit tests desiring a complex reasonably realistic Consul setup. For that use case use the sprawl/sprawltest wrapper:

func TestSomething(t *testing.T) {
    cfg := &topology.Config{...}
    sp := sprawltest.Launch(t, cfg)
    // do stuff with 'sp'
}