From 4e841fe6cc38c50f00137ca1699cf652c0de2ba8 Mon Sep 17 00:00:00 2001 From: Gianluca Arbezzano Date: Wed, 15 Mar 2017 21:36:48 +0000 Subject: [PATCH] Builded autotedection for swarm. --- cmd/daemon.go | 20 +++++++---- core/autodetect.go | 84 +++++++++++++++++++++++++++++++++++++++------- core/daemon.go | 11 +++--- 3 files changed, 90 insertions(+), 25 deletions(-) diff --git a/cmd/daemon.go b/cmd/daemon.go index 1577f85..afa83d3 100644 --- a/cmd/daemon.go +++ b/cmd/daemon.go @@ -11,6 +11,7 @@ import ( "github.com/Sirupsen/logrus" "github.com/gianarb/orbiter/api" + "github.com/gianarb/orbiter/autoscaler" "github.com/gianarb/orbiter/core" ) @@ -29,28 +30,35 @@ func (c *DaemonCmd) Run(args []string) int { cmdFlags.BoolVar(&debug, "debug", false, "debug") if err := cmdFlags.Parse(args); err != nil { logrus.WithField("error", err).Warn("Problem to parse arguments.") - return 1 + os.Exit(1) } if debug == true { logrus.SetLevel(logrus.DebugLevel) logrus.Debug("Daemon started in debug mode") } - var coreEngine core.Core + coreEngine := core.Core{ + Autoscalers: autoscaler.Autoscalers{}, + } + var err error if configPath != "" { config, err := readConfiguration(configPath) if err != nil { logrus.WithField("error", err).Warn("Configuration file malformed.") - return 1 + os.Exit(1) } logrus.Infof("Starting from configuration file located %s", configPath) - coreEngine, err = core.NewCoreByConfig(config.AutoscalersConf) + err = core.NewCoreByConfig(config.AutoscalersConf, &coreEngine) if err != nil { logrus.WithField("error", err).Warn(err) - return 1 + os.Exit(1) } } else { logrus.Info("Starting in auto-detection mode.") - coreEngine, err = core.Autodetect() + err = core.Autodetect(&coreEngine) + if err != nil { + logrus.WithField("error", err).Info(err) + os.Exit(0) + } } go func() { sigchan := make(chan os.Signal, 10) diff --git a/core/autodetect.go b/core/autodetect.go index d719629..dcd448e 100644 --- a/core/autodetect.go +++ b/core/autodetect.go @@ -1,21 +1,81 @@ package core -import "github.com/gianarb/orbiter/autoscaler" +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 error) { - scalers := autoscaler.Autoscalers{} - var core Core - autoDetectSwarmMode(&scalers) - return core, nil +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(a *autoscaler.Autoscalers) { - // Create Docker Client by EnvVar and check if it's working. - - // Get List of Services - - // Check which services has labels and register them to orbiter. +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 } diff --git a/core/daemon.go b/core/daemon.go index cf3b750..c1b9632 100644 --- a/core/daemon.go +++ b/core/daemon.go @@ -11,20 +11,17 @@ type Core struct { Autoscalers autoscaler.Autoscalers } -func NewCoreByConfig(c map[string]AutoscalerConf) (Core, error) { +func NewCoreByConfig(c map[string]AutoscalerConf, core *Core) error { scalers := autoscaler.Autoscalers{} - var core Core for scalerName, scaler := range c { p, err := provider.NewProvider(scaler.Provider, scaler.Parameters) if err != nil { - return core, err + return err } for serviceName, policy := range scaler.Policies { scalers[fmt.Sprintf("%s/%s", scalerName, serviceName)] = autoscaler.NewAutoscaler(p, serviceName, policy.Up, policy.Down) } } - core = Core{ - Autoscalers: scalers, - } - return core, nil + core.Autoscalers = scalers + return nil }