1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153
|
package main
import (
"fmt"
"net"
"testing"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
incus "github.com/lxc/incus/v6/client"
"github.com/lxc/incus/v6/shared/api"
)
// allocatePort asks the kernel for a free open port that is ready to use.
func allocatePort() (int, error) {
addr, err := net.ResolveTCPAddr("tcp", "localhost:0")
if err != nil {
return -1, err
}
l, err := net.ListenTCP("tcp", addr)
if err != nil {
return -1, err
}
return l.Addr().(*net.TCPAddr).Port, l.Close()
}
// A node which is already configured for networking can be converted to a
// single-node cluster.
func TestCluster_Bootstrap(t *testing.T) {
daemon, cleanup := newTestDaemon(t)
defer cleanup()
// Simulate what happens when running "init", where a PUT /1.0
// request is issued to set both core.https_address and
// cluster.https_address to the same value.
f := clusterFixture{t: t}
f.EnableNetworkingWithClusterAddress(daemon)
client := f.ClientUnix(daemon)
cluster := api.ClusterPut{}
cluster.ServerName = "buzz"
cluster.Enabled = true
op, err := client.UpdateCluster(cluster, "")
require.NoError(t, err)
require.NoError(t, op.Wait())
server, _, err := client.GetServer()
require.NoError(t, err)
assert.True(t, client.IsClustered())
assert.Equal(t, "buzz", server.Environment.ServerName)
}
// Check the cluster API on a non-clustered server.
func TestCluster_Get(t *testing.T) {
daemon, cleanup := newTestDaemon(t)
defer cleanup()
c, err := incus.ConnectIncusUnix(daemon.os.GetUnixSocket(), nil)
require.NoError(t, err)
cluster, _, err := c.GetCluster()
require.NoError(t, err)
assert.Equal(t, "", cluster.ServerName)
assert.False(t, cluster.Enabled)
}
// A node can be renamed.
func TestCluster_RenameNode(t *testing.T) {
daemon, cleanup := newTestDaemon(t)
defer cleanup()
f := clusterFixture{t: t}
f.EnableNetworking(daemon)
client := f.ClientUnix(daemon)
cluster := api.ClusterPut{}
cluster.ServerName = "buzz"
cluster.Enabled = true
op, err := client.UpdateCluster(cluster, "")
require.NoError(t, err)
require.NoError(t, op.Wait())
node := api.ClusterMemberPost{ServerName: "rusp"}
err = client.RenameClusterMember("buzz", node)
require.NoError(t, err)
_, _, err = client.GetClusterMember("rusp")
require.NoError(t, err)
}
// Test helper for cluster-related APIs.
type clusterFixture struct {
t *testing.T
clients map[*Daemon]incus.InstanceServer
}
// Enable networking in the given daemon. The password is optional and can be
// an empty string.
func (f *clusterFixture) EnableNetworking(daemon *Daemon) {
port, err := allocatePort()
require.NoError(f.t, err)
address := fmt.Sprintf("127.0.0.1:%d", port)
client := f.ClientUnix(daemon)
server, _, err := client.GetServer()
require.NoError(f.t, err)
serverPut := server.Writable()
serverPut.Config["core.https_address"] = address
require.NoError(f.t, client.UpdateServer(serverPut, ""))
}
// Enable networking in the given daemon, and set cluster.https_address to the
// same value as core.https address. The password is optional and can be an
// empty string.
func (f *clusterFixture) EnableNetworkingWithClusterAddress(daemon *Daemon) {
port, err := allocatePort()
require.NoError(f.t, err)
address := fmt.Sprintf("127.0.0.1:%d", port)
client := f.ClientUnix(daemon)
server, _, err := client.GetServer()
require.NoError(f.t, err)
serverPut := server.Writable()
serverPut.Config["core.https_address"] = address
serverPut.Config["cluster.https_address"] = address
require.NoError(f.t, client.UpdateServer(serverPut, ""))
}
// Get a client for the given daemon connected via UNIX socket, creating one if
// needed.
func (f *clusterFixture) ClientUnix(daemon *Daemon) incus.InstanceServer {
if f.clients == nil {
f.clients = make(map[*Daemon]incus.InstanceServer)
}
client, ok := f.clients[daemon]
if !ok {
var err error
client, err = incus.ConnectIncusUnix(daemon.os.GetUnixSocket(), nil)
require.NoError(f.t, err)
}
return client
}
|