github.com/proppy/fleet@v0.1.4/fleet.go (about)

     1  package main
     2  
     3  import (
     4  	"flag"
     5  	"fmt"
     6  	"os"
     7  	"os/signal"
     8  	"strings"
     9  	"syscall"
    10  
    11  	"github.com/coreos/fleet/third_party/github.com/coreos/go-etcd/etcd"
    12  	"github.com/coreos/fleet/third_party/github.com/golang/glog"
    13  	"github.com/coreos/fleet/third_party/github.com/rakyll/globalconf"
    14  
    15  	"github.com/coreos/fleet/agent"
    16  	"github.com/coreos/fleet/config"
    17  	"github.com/coreos/fleet/server"
    18  	"github.com/coreos/fleet/version"
    19  )
    20  
    21  func main() {
    22  	// We use a FlagSets since glog adds a bunch of flags we do not want to publish
    23  	userset := flag.NewFlagSet("fleet", flag.ExitOnError)
    24  	printVersion := userset.Bool("version", false, "Print the version and exit")
    25  	cfgPath := userset.String("config", "/etc/fleet/fleet.conf", "Path to config file")
    26  
    27  	err := userset.Parse(os.Args[1:])
    28  	if err == flag.ErrHelp {
    29  		userset.Usage()
    30  		syscall.Exit(1)
    31  	}
    32  
    33  	if *printVersion {
    34  		fmt.Println("fleet version", version.Version)
    35  		os.Exit(0)
    36  	}
    37  
    38  	cfgset := flag.NewFlagSet("fleet", flag.ExitOnError)
    39  	cfgset.Int("verbosity", 0, "Logging level")
    40  	cfgset.Var(&stringSlice{}, "etcd_servers", "List of etcd endpoints")
    41  	cfgset.String("boot_id", "", "Override default BootID of fleet machine")
    42  	cfgset.String("public_ip", "", "IP address that fleet machine should publish")
    43  	cfgset.String("metadata", "", "List of key-value metadata to assign to the fleet machine")
    44  	cfgset.String("unit_prefix", "", "Prefix that should be used for all systemd units")
    45  	cfgset.String("agent_ttl", agent.DefaultTTL, "TTL in seconds of fleet machine state in etcd")
    46  
    47  	globalconf.Register("", cfgset)
    48  	cfg, err := getConfig(cfgset, *cfgPath)
    49  	if err != nil {
    50  		glog.Error(err.Error())
    51  		syscall.Exit(1)
    52  	}
    53  
    54  	config.UpdateLoggingFlagsFromConfig(cfg)
    55  	etcd.SetLogger(etcdLogger{})
    56  
    57  	srv := server.New(*cfg)
    58  	srv.Run()
    59  
    60  	reconfigure := func() {
    61  		glog.Infof("Reloading configuration from %s", *cfgPath)
    62  
    63  		cfg, err := getConfig(cfgset, *cfgPath)
    64  		if err != nil {
    65  			glog.Errorf(err.Error())
    66  			syscall.Exit(1)
    67  		}
    68  
    69  		srv.Stop()
    70  
    71  		config.UpdateLoggingFlagsFromConfig(cfg)
    72  		srv = server.New(*cfg)
    73  
    74  		srv.Run()
    75  	}
    76  
    77  	shutdown := func() {
    78  		glog.Infof("Gracefully shutting down")
    79  		srv.Stop()
    80  		srv.Purge()
    81  		syscall.Exit(0)
    82  	}
    83  
    84  	signals := map[os.Signal]func(){
    85  		syscall.SIGHUP:  reconfigure,
    86  		syscall.SIGTERM: shutdown,
    87  		syscall.SIGINT:  shutdown,
    88  	}
    89  
    90  	listenForSignals(signals)
    91  }
    92  
    93  func getConfig(flagset *flag.FlagSet, file string) (*config.Config, error) {
    94  	if _, err := os.Stat(file); err != nil {
    95  		glog.Infof("Config file %s does not appear to exist - ignoring")
    96  		file = ""
    97  	}
    98  
    99  	opts := globalconf.Options{
   100  		EnvPrefix: "FLEET_",
   101  		ConfigFile: file,
   102  	}
   103  	gconf, err := globalconf.NewWithOptions(opts)
   104  	if err != nil {
   105  		return nil, err
   106  	}
   107  
   108  	gconf.ParseSet("", flagset)
   109  
   110  	cfg := config.NewConfig()
   111  	cfg.Verbosity = (*flagset.Lookup("verbosity")).Value.(flag.Getter).Get().(int)
   112  	cfg.EtcdServers = (*flagset.Lookup("etcd_servers")).Value.(flag.Getter).Get().(stringSlice)
   113  	cfg.BootId = (*flagset.Lookup("boot_id")).Value.(flag.Getter).Get().(string)
   114  	cfg.PublicIP = (*flagset.Lookup("public_ip")).Value.(flag.Getter).Get().(string)
   115  	cfg.RawMetadata = (*flagset.Lookup("metadata")).Value.(flag.Getter).Get().(string)
   116  	cfg.UnitPrefix = (*flagset.Lookup("unit_prefix")).Value.(flag.Getter).Get().(string)
   117  	cfg.AgentTTL = (*flagset.Lookup("agent_ttl")).Value.(flag.Getter).Get().(string)
   118  
   119  	return cfg, nil
   120  }
   121  
   122  func listenForSignals(sigmap map[os.Signal]func()) {
   123  	sigchan := make(chan os.Signal, 1)
   124  
   125  	for k, _ := range sigmap {
   126  		signal.Notify(sigchan, k)
   127  	}
   128  
   129  	for true {
   130  		sig := <-sigchan
   131  		handler, ok := sigmap[sig]
   132  		if ok {
   133  			handler()
   134  		}
   135  	}
   136  }
   137  
   138  type etcdLogger struct{}
   139  
   140  func (el etcdLogger) Debug(args ...interface{}) {
   141  	glog.V(3).Info(args...)
   142  }
   143  
   144  func (el etcdLogger) Debugf(fmt string, args ...interface{}) {
   145  	glog.V(3).Infof(fmt, args...)
   146  }
   147  
   148  func (el etcdLogger) Warning(args ...interface{}) {
   149  	glog.Warning(args...)
   150  }
   151  
   152  func (el etcdLogger) Warningf(fmt string, args ...interface{}) {
   153  	glog.Warningf(fmt, args...)
   154  }
   155  
   156  type stringSlice []string
   157  
   158  func (f *stringSlice) Set(value string) error {
   159  	for _, item := range strings.Split(value, ",") {
   160  		item = strings.TrimLeft(item, " [\"")
   161  		item = strings.TrimRight(item, " \"]")
   162  		*f = append(*f, item)
   163  	}
   164  
   165  	return nil
   166  }
   167  
   168  func (f *stringSlice) String() string {
   169  	return fmt.Sprintf("%v", *f)
   170  }
   171  
   172  func (f *stringSlice) Value() []string {
   173  	return *f
   174  }
   175  
   176  func (f *stringSlice) Get() interface{} {
   177  	return *f
   178  }