Files
kairos-agent/internal/role/master.go
Ettore Di Giacinto 63cd28d1cb Split off cli into separate binaries (#37)
* 🎨 Split off cli into separate binaries

This commit splits off the cli into 3 binaries:
- agent
- cli
- provider

The provider now is a separate component that can be tested by itself
and have its own lifecycle. This paves the way to a ligher c3os variant,
HA support and other features that can be provided on runtime.

This is working, but still there are low hanging fruit to care about.

Fixes #14

* 🤖 Add provider bin to releases

* ⚙️ Handle signals

* ⚙️ Reduce buildsize footprint

* 🎨 Scan for providers also in /system/providers

* 🤖 Run goreleaser

* 🎨 Refactoring
2022-07-04 22:39:34 +02:00

135 lines
3.0 KiB
Go

package role
import (
"encoding/base64"
"errors"
"fmt"
"io/ioutil"
"strings"
"time"
"github.com/c3os-io/c3os/internal/machine"
"github.com/c3os-io/c3os/internal/utils"
"github.com/c3os-io/c3os/pkg/config"
service "github.com/mudler/edgevpn/api/client/service"
)
func propagateMasterData(ip string, c *service.RoleConfig) error {
defer func() {
// Avoid polluting the API.
// The ledger already retries in the background to update the blockchain, but it has
// a default timeout where it would stop trying afterwards.
// Each request here would have it's own background announce, so that can become expensive
// when network is having lot of changes on its way.
time.Sleep(30 * time.Second)
}()
// If we are configured as master, always signal our role
c.Client.Set("role", c.UUID, "master")
tokenB, err := ioutil.ReadFile("/var/lib/rancher/k3s/server/node-token")
if err != nil {
c.Logger.Error(err)
return err
}
nodeToken := string(tokenB)
nodeToken = strings.TrimRight(nodeToken, "\n")
if nodeToken != "" {
c.Client.Set("nodetoken", "token", nodeToken)
}
kubeB, err := ioutil.ReadFile("/etc/rancher/k3s/k3s.yaml")
if err != nil {
c.Logger.Error(err)
return err
}
kubeconfig := string(kubeB)
if kubeconfig != "" {
c.Client.Set("kubeconfig", "master", base64.RawURLEncoding.EncodeToString(kubeB))
}
c.Client.Set("master", "ip", ip)
return nil
}
func Master(cc *config.Config) Role {
return func(c *service.RoleConfig) error {
ip := utils.GetInterfaceIP("edgevpn0")
if ip == "" {
return errors.New("node doesn't have an ip yet")
}
if cc.C3OS.Role != "" {
// propagate role if we were forced by configuration
// This unblocks eventual auto instances to try to assign roles
c.Client.Set("role", c.UUID, cc.C3OS.Role)
}
if SentinelExist() {
c.Logger.Info("Node already configured, backing off")
return propagateMasterData(ip, c)
}
// Configure k3s service to start on edgevpn0
c.Logger.Info("Configuring k3s")
svc, err := machine.K3s()
if err != nil {
return err
}
k3sConfig := config.K3s{}
if cc.K3s.Enabled {
k3sConfig = cc.K3s
}
env := map[string]string{}
if !k3sConfig.ReplaceEnv {
// Override opts with user-supplied
for k, v := range k3sConfig.Env {
env[k] = v
}
} else {
env = k3sConfig.Env
}
if err := utils.WriteEnv(machine.K3sEnvUnit("k3s"),
env,
); err != nil {
return err
}
args := []string{"--flannel-iface=edgevpn0"}
if k3sConfig.ReplaceArgs {
args = k3sConfig.Args
} else {
args = append(args, k3sConfig.Args...)
}
if err := svc.OverrideCmd(fmt.Sprintf("/usr/bin/k3s server %s", strings.Join(args, " "))); err != nil {
return err
}
if err := svc.Start(); err != nil {
return err
}
if err := svc.Enable(); err != nil {
return err
}
propagateMasterData(ip, c)
CreateSentinel()
return nil
}
}
// TODO: https://rancher.com/docs/k3s/latest/en/installation/ha-embedded/
func HAMaster(c *service.RoleConfig) {
c.Logger.Info("HA Role not implemented yet")
}