mirror of
https://github.com/spaytac/orbiter.git
synced 2026-01-21 23:14:43 +00:00
Merge pull request #11 from gianarb/feature/autodetection
Bootstrap autodetection and swarm zero conf
This commit is contained in:
commit
2d31ddc26b
@ -11,6 +11,7 @@ import (
|
|||||||
|
|
||||||
"github.com/Sirupsen/logrus"
|
"github.com/Sirupsen/logrus"
|
||||||
"github.com/gianarb/orbiter/api"
|
"github.com/gianarb/orbiter/api"
|
||||||
|
"github.com/gianarb/orbiter/autoscaler"
|
||||||
"github.com/gianarb/orbiter/core"
|
"github.com/gianarb/orbiter/core"
|
||||||
)
|
)
|
||||||
|
|
||||||
@ -25,25 +26,39 @@ func (c *DaemonCmd) Run(args []string) int {
|
|||||||
var debug bool
|
var debug bool
|
||||||
cmdFlags := flag.NewFlagSet("event", flag.ExitOnError)
|
cmdFlags := flag.NewFlagSet("event", flag.ExitOnError)
|
||||||
cmdFlags.StringVar(&port, "port", ":8000", "port")
|
cmdFlags.StringVar(&port, "port", ":8000", "port")
|
||||||
cmdFlags.StringVar(&configPath, "config", "/etc/deamon.yml", "config")
|
cmdFlags.StringVar(&configPath, "config", "", "config")
|
||||||
cmdFlags.BoolVar(&debug, "debug", false, "debug")
|
cmdFlags.BoolVar(&debug, "debug", false, "debug")
|
||||||
if err := cmdFlags.Parse(args); err != nil {
|
if err := cmdFlags.Parse(args); err != nil {
|
||||||
logrus.WithField("error", err).Warn("Problem to parse arguments.")
|
logrus.WithField("error", err).Warn("Problem to parse arguments.")
|
||||||
return 1
|
os.Exit(1)
|
||||||
}
|
}
|
||||||
if debug == true {
|
if debug == true {
|
||||||
logrus.SetLevel(logrus.DebugLevel)
|
logrus.SetLevel(logrus.DebugLevel)
|
||||||
logrus.Debug("Daemon started in debug mode")
|
logrus.Debug("Daemon started in debug mode")
|
||||||
}
|
}
|
||||||
config, err := readConfiguration(configPath)
|
coreEngine := core.Core{
|
||||||
if err != nil {
|
Autoscalers: autoscaler.Autoscalers{},
|
||||||
logrus.WithField("error", err).Warn("Configuration file malformed.")
|
|
||||||
return 1
|
|
||||||
}
|
}
|
||||||
core, err := core.NewCore(config.AutoscalersConf)
|
var err error
|
||||||
if err != nil {
|
if configPath != "" {
|
||||||
logrus.WithField("error", err).Warn(err)
|
config, err := readConfiguration(configPath)
|
||||||
return 1
|
if err != nil {
|
||||||
|
logrus.WithField("error", err).Warn("Configuration file malformed.")
|
||||||
|
os.Exit(1)
|
||||||
|
}
|
||||||
|
logrus.Infof("Starting from configuration file located %s", configPath)
|
||||||
|
err = core.NewCoreByConfig(config.AutoscalersConf, &coreEngine)
|
||||||
|
if err != nil {
|
||||||
|
logrus.WithField("error", err).Warn(err)
|
||||||
|
os.Exit(1)
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
logrus.Info("Starting in auto-detection mode.")
|
||||||
|
err = core.Autodetect(&coreEngine)
|
||||||
|
if err != nil {
|
||||||
|
logrus.WithField("error", err).Info(err)
|
||||||
|
os.Exit(0)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
go func() {
|
go func() {
|
||||||
sigchan := make(chan os.Signal, 10)
|
sigchan := make(chan os.Signal, 10)
|
||||||
@ -52,7 +67,7 @@ func (c *DaemonCmd) Run(args []string) int {
|
|||||||
logrus.Info("Stopping and cleaning. Bye!")
|
logrus.Info("Stopping and cleaning. Bye!")
|
||||||
os.Exit(0)
|
os.Exit(0)
|
||||||
}()
|
}()
|
||||||
router := api.GetRouter(core, c.EventChannel)
|
router := api.GetRouter(coreEngine, c.EventChannel)
|
||||||
logrus.Infof("API Server run on port %s", port)
|
logrus.Infof("API Server run on port %s", port)
|
||||||
http.ListenAndServe(port, router)
|
http.ListenAndServe(port, router)
|
||||||
return 0
|
return 0
|
||||||
|
|||||||
81
core/autodetect.go
Normal file
81
core/autodetect.go
Normal file
@ -0,0 +1,81 @@
|
|||||||
|
package core
|
||||||
|
|
||||||
|
import (
|
||||||
|
"context"
|
||||||
|
"errors"
|
||||||
|
"fmt"
|
||||||
|
"strconv"
|
||||||
|
|
||||||
|
"github.com/Sirupsen/logrus"
|
||||||
|
"github.com/docker/docker/api/types"
|
||||||
|
"github.com/docker/docker/api/types/swarm"
|
||||||
|
"github.com/docker/docker/client"
|
||||||
|
"github.com/gianarb/orbiter/autoscaler"
|
||||||
|
"github.com/gianarb/orbiter/provider"
|
||||||
|
)
|
||||||
|
|
||||||
|
// This function use diferent strategies to get information from
|
||||||
|
// the system itself to configure the autoloader.
|
||||||
|
// They can be environment variables for example or other systems.
|
||||||
|
func Autodetect(core *Core) error {
|
||||||
|
autoDetectSwarmMode(core)
|
||||||
|
if len(core.Autoscalers) == 0 {
|
||||||
|
return errors.New("we didn't detect any autoscaling group")
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func autoDetectSwarmMode(c *Core) {
|
||||||
|
ctx := context.Background()
|
||||||
|
dockerClient, err := client.NewEnvClient()
|
||||||
|
if err != nil {
|
||||||
|
logrus.WithField("error", err).Debug("Problem communication with Docker")
|
||||||
|
return
|
||||||
|
}
|
||||||
|
info, err := dockerClient.Info(ctx)
|
||||||
|
if err != nil {
|
||||||
|
logrus.WithField("error", err).Debug("We didn't detect any Docker Swarm running")
|
||||||
|
return
|
||||||
|
}
|
||||||
|
if info.Swarm.NodeID == "" {
|
||||||
|
logrus.Debug("We didn't detect any Docker Swarm running")
|
||||||
|
return
|
||||||
|
}
|
||||||
|
services, err := dockerClient.ServiceList(ctx, types.ServiceListOptions{})
|
||||||
|
if err != nil {
|
||||||
|
logrus.WithField("error", err).Debug("Bad comunication with Docker.")
|
||||||
|
return
|
||||||
|
}
|
||||||
|
prov, _ := provider.NewSwarmProvider(map[string]string{})
|
||||||
|
for _, service := range services {
|
||||||
|
s, err := getAutoscalerByService(prov, service.Spec.Annotations)
|
||||||
|
if err != nil {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
logrus.Debugf("autodetect_swarm/%s added to orbiter.", service.Spec.Annotations.Name)
|
||||||
|
c.Autoscalers[fmt.Sprintf("autodetect_swarm/%s", service.Spec.Annotations.Name)] = s
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func getAutoscalerByService(p autoscaler.Provider, an swarm.Annotations) (autoscaler.Autoscaler, error) {
|
||||||
|
_, e := an.Labels["orbiter"]
|
||||||
|
if e == false {
|
||||||
|
return autoscaler.Autoscaler{}, errors.New("")
|
||||||
|
}
|
||||||
|
up := convertStringLabelToInt("orbiter.up", an.Labels)
|
||||||
|
down := convertStringLabelToInt("orbiter.down", an.Labels)
|
||||||
|
as := autoscaler.NewAutoscaler(p, an.Name, up, down)
|
||||||
|
return as, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func convertStringLabelToInt(labelName string, labels map[string]string) int {
|
||||||
|
row, e := labels[labelName]
|
||||||
|
if e == false {
|
||||||
|
i, err := strconv.ParseInt(row, 10, 64)
|
||||||
|
if err != nil {
|
||||||
|
return 1
|
||||||
|
}
|
||||||
|
return int(i)
|
||||||
|
}
|
||||||
|
return 1
|
||||||
|
}
|
||||||
@ -11,20 +11,17 @@ type Core struct {
|
|||||||
Autoscalers autoscaler.Autoscalers
|
Autoscalers autoscaler.Autoscalers
|
||||||
}
|
}
|
||||||
|
|
||||||
func NewCore(c map[string]AutoscalerConf) (Core, error) {
|
func NewCoreByConfig(c map[string]AutoscalerConf, core *Core) error {
|
||||||
scalers := autoscaler.Autoscalers{}
|
scalers := autoscaler.Autoscalers{}
|
||||||
var core Core
|
|
||||||
for scalerName, scaler := range c {
|
for scalerName, scaler := range c {
|
||||||
p, err := provider.NewProvider(scaler.Provider, scaler.Parameters)
|
p, err := provider.NewProvider(scaler.Provider, scaler.Parameters)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return core, err
|
return err
|
||||||
}
|
}
|
||||||
for serviceName, policy := range scaler.Policies {
|
for serviceName, policy := range scaler.Policies {
|
||||||
scalers[fmt.Sprintf("%s/%s", scalerName, serviceName)] = autoscaler.NewAutoscaler(p, serviceName, policy.Up, policy.Down)
|
scalers[fmt.Sprintf("%s/%s", scalerName, serviceName)] = autoscaler.NewAutoscaler(p, serviceName, policy.Up, policy.Down)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
core = Core{
|
core.Autoscalers = scalers
|
||||||
Autoscalers: scalers,
|
return nil
|
||||||
}
|
|
||||||
return core, nil
|
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,8 +1,15 @@
|
|||||||
package core
|
package core
|
||||||
|
|
||||||
import "testing"
|
import (
|
||||||
|
"testing"
|
||||||
|
|
||||||
|
"github.com/gianarb/orbiter/autoscaler"
|
||||||
|
)
|
||||||
|
|
||||||
func TestNewCore(t *testing.T) {
|
func TestNewCore(t *testing.T) {
|
||||||
|
core := Core{
|
||||||
|
Autoscalers: autoscaler.Autoscalers{},
|
||||||
|
}
|
||||||
conf := map[string]AutoscalerConf{
|
conf := map[string]AutoscalerConf{
|
||||||
"first-scaler": AutoscalerConf{
|
"first-scaler": AutoscalerConf{
|
||||||
Provider: "fake",
|
Provider: "fake",
|
||||||
@ -29,7 +36,7 @@ func TestNewCore(t *testing.T) {
|
|||||||
},
|
},
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
core, err := NewCore(conf)
|
err := NewCoreByConfig(conf, &core)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
}
|
}
|
||||||
@ -39,6 +46,9 @@ func TestNewCore(t *testing.T) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func TestGetSingleAutoscaler(t *testing.T) {
|
func TestGetSingleAutoscaler(t *testing.T) {
|
||||||
|
core := Core{
|
||||||
|
Autoscalers: autoscaler.Autoscalers{},
|
||||||
|
}
|
||||||
conf := map[string]AutoscalerConf{
|
conf := map[string]AutoscalerConf{
|
||||||
"second": AutoscalerConf{
|
"second": AutoscalerConf{
|
||||||
Provider: "fake",
|
Provider: "fake",
|
||||||
@ -55,7 +65,7 @@ func TestGetSingleAutoscaler(t *testing.T) {
|
|||||||
},
|
},
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
core, _ := NewCore(conf)
|
NewCoreByConfig(conf, &core)
|
||||||
_, ok := core.Autoscalers["second/micro"]
|
_, ok := core.Autoscalers["second/micro"]
|
||||||
if ok == false {
|
if ok == false {
|
||||||
t.Fatal("micro exist")
|
t.Fatal("micro exist")
|
||||||
@ -63,6 +73,9 @@ func TestGetSingleAutoscaler(t *testing.T) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func TestNewCoreWithUnsupportedProvider(t *testing.T) {
|
func TestNewCoreWithUnsupportedProvider(t *testing.T) {
|
||||||
|
core := Core{
|
||||||
|
Autoscalers: autoscaler.Autoscalers{},
|
||||||
|
}
|
||||||
conf := map[string]AutoscalerConf{
|
conf := map[string]AutoscalerConf{
|
||||||
"second-scaler": AutoscalerConf{
|
"second-scaler": AutoscalerConf{
|
||||||
Provider: "fake",
|
Provider: "fake",
|
||||||
@ -89,7 +102,7 @@ func TestNewCoreWithUnsupportedProvider(t *testing.T) {
|
|||||||
},
|
},
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
_, err := NewCore(conf)
|
err := NewCoreByConfig(conf, &core)
|
||||||
if err.Error() != "lalala not supported." {
|
if err.Error() != "lalala not supported." {
|
||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
}
|
}
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user