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 }