|
|
|
@ -6,48 +6,66 @@ import (
|
|
|
|
|
"encoding/json"
|
|
|
|
|
"fmt"
|
|
|
|
|
"log"
|
|
|
|
|
"net"
|
|
|
|
|
"os"
|
|
|
|
|
"path"
|
|
|
|
|
"strconv"
|
|
|
|
|
"time"
|
|
|
|
|
)
|
|
|
|
|
|
|
|
|
|
type Worker struct {
|
|
|
|
|
ID int
|
|
|
|
|
const retryDelay = time.Second * 2
|
|
|
|
|
|
|
|
|
|
IP string
|
|
|
|
|
type WorkerConfig struct {
|
|
|
|
|
// Path to festoons.
|
|
|
|
|
FestoonsDir string
|
|
|
|
|
|
|
|
|
|
FestoonsDir string
|
|
|
|
|
// Path to deployments.
|
|
|
|
|
DeploymentsDir string
|
|
|
|
|
|
|
|
|
|
// Address to connect to queen bee.
|
|
|
|
|
Queen string
|
|
|
|
|
|
|
|
|
|
// Worker IP address.
|
|
|
|
|
IP string
|
|
|
|
|
|
|
|
|
|
// Unique ID.
|
|
|
|
|
ID int
|
|
|
|
|
|
|
|
|
|
// Password.
|
|
|
|
|
Password string
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
type Worker struct {
|
|
|
|
|
WorkerConfig
|
|
|
|
|
|
|
|
|
|
Deployments []*Deployment
|
|
|
|
|
|
|
|
|
|
TaskQueue chan *TaskMessage
|
|
|
|
|
|
|
|
|
|
requestPortsFunc func(d *Deployment) []int
|
|
|
|
|
|
|
|
|
|
reconnect chan struct{}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
func NewWorker(id int, ip string, festoonsDir string, deploymentsDir string) *Worker {
|
|
|
|
|
func NewWorker(config *WorkerConfig) *Worker {
|
|
|
|
|
w := &Worker{
|
|
|
|
|
ID: id,
|
|
|
|
|
IP: ip,
|
|
|
|
|
FestoonsDir: festoonsDir,
|
|
|
|
|
DeploymentsDir: deploymentsDir,
|
|
|
|
|
TaskQueue: make(chan *TaskMessage),
|
|
|
|
|
WorkerConfig: *config,
|
|
|
|
|
TaskQueue: make(chan *TaskMessage),
|
|
|
|
|
reconnect: make(chan struct{}),
|
|
|
|
|
}
|
|
|
|
|
go w.handleTaskQueue()
|
|
|
|
|
|
|
|
|
|
log.Println("Loading deployments...")
|
|
|
|
|
// TODO list directories in deployments dir, no db needed
|
|
|
|
|
|
|
|
|
|
dirEntries, err := os.ReadDir(deploymentsDir)
|
|
|
|
|
dirEntries, err := os.ReadDir(config.DeploymentsDir)
|
|
|
|
|
if err != nil {
|
|
|
|
|
log.Fatal(err)
|
|
|
|
|
}
|
|
|
|
|
for _, dirEntry := range dirEntries {
|
|
|
|
|
if dirEntry.IsDir() {
|
|
|
|
|
log.Println(dirEntry.Name())
|
|
|
|
|
d, err := LoadDeployment(path.Join(deploymentsDir, dirEntry.Name()))
|
|
|
|
|
d, err := LoadDeployment(path.Join(config.DeploymentsDir, dirEntry.Name()))
|
|
|
|
|
if err != nil {
|
|
|
|
|
log.Fatalf("failed to load deployment %s: %s", dirEntry.Name(), err)
|
|
|
|
|
}
|
|
|
|
@ -57,12 +75,41 @@ func NewWorker(id int, ip string, festoonsDir string, deploymentsDir string) *Wo
|
|
|
|
|
w.Deployments = append(w.Deployments, d)
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
log.Println("Finished loading deployments")
|
|
|
|
|
|
|
|
|
|
go w.handleConnect()
|
|
|
|
|
|
|
|
|
|
return w
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
func (w *Worker) handleConnect() {
|
|
|
|
|
log.Printf("Connecting to queen bee at %s...", w.Queen)
|
|
|
|
|
for {
|
|
|
|
|
var conn net.Conn
|
|
|
|
|
var err error
|
|
|
|
|
for {
|
|
|
|
|
conn, err = net.Dial("tcp", w.Queen)
|
|
|
|
|
if err != nil {
|
|
|
|
|
log.Printf("Failed to connect to queen: %s", err)
|
|
|
|
|
log.Println("Retrying in 2 seconds...")
|
|
|
|
|
time.Sleep(retryDelay)
|
|
|
|
|
continue
|
|
|
|
|
}
|
|
|
|
|
break
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
log.Println("Connected")
|
|
|
|
|
|
|
|
|
|
client := NewClient(conn)
|
|
|
|
|
client.Authenticate(w.ID, w.Password)
|
|
|
|
|
go w.HandleRead(client)
|
|
|
|
|
|
|
|
|
|
<-w.reconnect
|
|
|
|
|
|
|
|
|
|
log.Println("Reconnecting...")
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
func (w *Worker) handleTaskQueue() {
|
|
|
|
|
for t := range w.TaskQueue {
|
|
|
|
|
w.ExecuteTask(t)
|
|
|
|
@ -189,4 +236,8 @@ func (w *Worker) HandleRead(c *Client) {
|
|
|
|
|
log.Fatalf("unknown task type %d", task.Type)
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
log.Println("Connection lost")
|
|
|
|
|
|
|
|
|
|
w.reconnect <- struct{}{}
|
|
|
|
|
}
|
|
|
|
|