ClusterManager: Implements support of remote clusters.
After this change users will be able to:
* Create cluster and add/remove servers to it
* Install apps on remote cluster
* Move already installed apps between clusters
* Apps running on server being removed will auto-migrate
to another server from that same cluster
This is achieved by:
* Installing and running minimal version of dodo on remote cluster
* Ingress-nginx is installed automatically on new clusters
* Next to nginx we run VPN client in the same pod, so that
default cluster can establish secure communication with it
* Multiple reverse proxies are configured to get to the
remote cluster service from ingress installed on default cluster.
Next steps:
* Support remote clusters in dodo apps (prototype ready)
* Clean up old cluster when moving app to the new one. Currently
old cluster keeps running app pods even though no ingress can
reach it anymore.
Change-Id: Iffc908c93416d4126a8e1c2832eae7b659cb8044
diff --git a/core/headscale/client.go b/core/headscale/client.go
index 18c37df..159fffb 100644
--- a/core/headscale/client.go
+++ b/core/headscale/client.go
@@ -5,12 +5,14 @@
"encoding/json"
"errors"
"fmt"
+ "net"
"os/exec"
"strconv"
"strings"
)
var ErrorAlreadyExists = errors.New("already exists")
+var ErrorNotFound = errors.New("not found")
type client struct {
config string
@@ -89,8 +91,9 @@
}
type nodeInfo struct {
- Id int `json:"id"`
- Name string `json:"name"`
+ Id int `json:"id"`
+ Name string `json:"name"`
+ IPAddresses []net.IP `json:"ip_addresses"`
}
func (c *client) getNodeId(user, node string) (string, error) {
@@ -111,6 +114,24 @@
return "", fmt.Errorf("not found")
}
+func (c *client) getNodeAddresses(user, node string) ([]net.IP, error) {
+ cmd := exec.Command("headscale", c.config, "--user", user, "node", "list", "-o", "json")
+ out, err := cmd.Output()
+ if err != nil {
+ return nil, err
+ }
+ var nodes []nodeInfo
+ if err := json.NewDecoder(bytes.NewReader(out)).Decode(&nodes); err != nil {
+ return nil, err
+ }
+ for _, n := range nodes {
+ if n.Name == node {
+ return n.IPAddresses, nil
+ }
+ }
+ return nil, ErrorNotFound
+}
+
func extractLastLine(s string) (string, error) {
items := strings.Split(s, "\n")
for i := len(items) - 1; i >= 0; i-- {