mirror of
https://github.com/psviderski/uncloud.git
synced 2026-08-26 11:03:34 +00:00
ucind: init cluster with created machines
This commit is contained in:
@@ -7,7 +7,14 @@ import (
|
|||||||
"github.com/docker/docker/api/types/container"
|
"github.com/docker/docker/api/types/container"
|
||||||
"github.com/docker/docker/api/types/filters"
|
"github.com/docker/docker/api/types/filters"
|
||||||
"github.com/docker/docker/api/types/network"
|
"github.com/docker/docker/api/types/network"
|
||||||
"github.com/docker/docker/client"
|
dockerclient "github.com/docker/docker/client"
|
||||||
|
"google.golang.org/protobuf/types/known/emptypb"
|
||||||
|
"time"
|
||||||
|
"uncloud/internal/cli/client"
|
||||||
|
"uncloud/internal/cli/client/connector"
|
||||||
|
"uncloud/internal/machine"
|
||||||
|
"uncloud/internal/machine/api/pb"
|
||||||
|
"uncloud/internal/machine/cluster"
|
||||||
)
|
)
|
||||||
|
|
||||||
const (
|
const (
|
||||||
@@ -60,16 +67,96 @@ func (p *Provisioner) CreateCluster(ctx context.Context, name string, opts Creat
|
|||||||
c.Machines = append(c.Machines, m)
|
c.Machines = append(c.Machines, m)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if len(c.Machines) == 0 {
|
||||||
|
return c, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
if err = p.initCluster(ctx, c.Machines); err != nil {
|
||||||
|
return c, err
|
||||||
|
}
|
||||||
|
|
||||||
return c, nil
|
return c, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (p *Provisioner) initCluster(ctx context.Context, machines []Machine) error {
|
||||||
|
// TODO: properly wait for the API to respond.
|
||||||
|
time.Sleep(2 * time.Second) // Wait for the machines to be up and running.
|
||||||
|
|
||||||
|
// Init a new cluster on the first machine.
|
||||||
|
initMachine := machines[0]
|
||||||
|
initClient, err := client.New(ctx, connector.NewTCPConnector(initMachine.APIAddress))
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("create machine client over TCP '%s': %w", initMachine.APIAddress, err)
|
||||||
|
}
|
||||||
|
defer initClient.Close()
|
||||||
|
|
||||||
|
req := &pb.InitClusterRequest{
|
||||||
|
MachineName: initMachine.Name,
|
||||||
|
Network: pb.NewIPPrefix(cluster.DefaultNetwork),
|
||||||
|
}
|
||||||
|
initResp, err := initClient.InitCluster(ctx, req)
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("init cluster: %w", err)
|
||||||
|
}
|
||||||
|
fmt.Printf("Cluster %q initialised with machine %q\n", initMachine.ClusterName, initResp.Machine.Name)
|
||||||
|
|
||||||
|
// Join the rest of the machines to the cluster.
|
||||||
|
for _, m := range machines[1:] {
|
||||||
|
mcli, err := client.New(ctx, connector.NewTCPConnector(m.APIAddress))
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("create machine client over TCP '%s': %w", m.APIAddress, err)
|
||||||
|
}
|
||||||
|
//goland:noinspection GoDeferInLoop
|
||||||
|
defer mcli.Close()
|
||||||
|
|
||||||
|
tokenResp, err := mcli.Token(ctx, &emptypb.Empty{})
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("get machine token: %w", err)
|
||||||
|
}
|
||||||
|
token, err := machine.ParseToken(tokenResp.Token)
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("parse machine token: %w", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Register the machine in the cluster using its public key and endpoints from the token.
|
||||||
|
endpoints := make([]*pb.IPPort, len(token.Endpoints))
|
||||||
|
for i, addrPort := range token.Endpoints {
|
||||||
|
endpoints[i] = pb.NewIPPort(addrPort)
|
||||||
|
}
|
||||||
|
addReq := &pb.AddMachineRequest{
|
||||||
|
Name: m.Name,
|
||||||
|
Network: &pb.NetworkConfig{
|
||||||
|
Endpoints: endpoints,
|
||||||
|
PublicKey: token.PublicKey,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
addResp, err := initClient.AddMachine(ctx, addReq)
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("add machine to cluster: %w", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Configure the machine to join the cluster.
|
||||||
|
joinReq := &pb.JoinClusterRequest{
|
||||||
|
Machine: addResp.Machine,
|
||||||
|
OtherMachines: []*pb.MachineInfo{initResp.Machine},
|
||||||
|
}
|
||||||
|
if _, err = mcli.JoinCluster(ctx, joinReq); err != nil {
|
||||||
|
return fmt.Errorf("join cluster: %w", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
fmt.Printf("Machine %q added to cluster\n", addResp.Machine.Name)
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
func (p *Provisioner) InspectCluster(ctx context.Context, name string) (Cluster, error) {
|
func (p *Provisioner) InspectCluster(ctx context.Context, name string) (Cluster, error) {
|
||||||
var c Cluster
|
var c Cluster
|
||||||
|
|
||||||
// Docker network name is the same as the cluster name.
|
// Docker network name is the same as the cluster name.
|
||||||
net, err := p.client.NetworkInspect(ctx, name, network.InspectOptions{})
|
net, err := p.client.NetworkInspect(ctx, name, network.InspectOptions{})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
if client.IsErrNotFound(err) {
|
if dockerclient.IsErrNotFound(err) {
|
||||||
return c, ErrNotFound
|
return c, ErrNotFound
|
||||||
}
|
}
|
||||||
return c, fmt.Errorf("inspect Docker network '%s': %w", name, err)
|
return c, fmt.Errorf("inspect Docker network '%s': %w", name, err)
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
#!/bin/sh
|
#!/bin/sh
|
||||||
set -eu
|
set -eu
|
||||||
|
|
||||||
|
# TODO: cleanup /run/docker.pid on exit to support container restart.
|
||||||
dind dockerd &
|
dind dockerd &
|
||||||
echo "Waiting for Docker in Docker to be ready..."
|
echo "Waiting for Docker in Docker to be ready..."
|
||||||
timeout 5s sh -c "until docker info &> /dev/null; do sleep 0.1; done"
|
timeout 5s sh -c "until docker info &> /dev/null; do sleep 0.1; done"
|
||||||
|
|||||||
Reference in New Issue
Block a user