func runVolumeDestroy(args *docopt.Args) error { if os.Getuid() != 0 { fmt.Println("this command requires root!\ntry again with `sudo flynn-host destroy-volumes`.") shutdown.ExitWithCode(1) } volPath := args.String["--volpath"] includeData := args.Bool["--include-data"] keepSystemImages := args.Bool["--keep-system-images"] volumeDBPath := filepath.Join(volPath, "volumes.bolt") // if there is no state db, nothing to do if _, err := os.Stat(volumeDBPath); err != nil && os.IsNotExist(err) { fmt.Printf("no volume state db exists at %q; already clean.\n", volumeDBPath) shutdown.Exit() } // open state db. we're maybe using it; and regardless want to flock before removing it vman, vmanErr := loadVolumeState(volumeDBPath) // if '--include-data' specified and vman loaded, destroy volumes allVolumesDestroyed := true if vmanErr != nil { fmt.Printf("%s\n", vmanErr) } else if includeData == false { fmt.Println("'--include-data' not specified; leaving backend data storage intact.") } else { if err := destroyVolumes(vman, keepSystemImages); err != nil { fmt.Printf("%s\n", err) allVolumesDestroyed = false } } if !keepSystemImages { // remove db file if err := os.Remove(volumeDBPath); err != nil { fmt.Printf("could not remove volume state db file %q: %s.\n", volumeDBPath, err) shutdown.ExitWithCode(5) } fmt.Printf("state db file %q removed.\n", volumeDBPath) } // exit code depends on if all volumes were destroyed successfully or not if includeData && !allVolumesDestroyed { shutdown.ExitWithCode(6) } shutdown.Exit() return nil }
func main() { defer shutdown.Exit() db := postgres.Wait(&postgres.Conf{ Service: serviceName, User: "******", Password: os.Getenv("PGPASSWORD"), Database: "postgres", }, nil) api := &pgAPI{db} router := httprouter.New() router.POST("/databases", httphelper.WrapHandler(api.createDatabase)) router.DELETE("/databases", httphelper.WrapHandler(api.dropDatabase)) router.GET("/ping", httphelper.WrapHandler(api.ping)) port := os.Getenv("PORT") if port == "" { port = "3000" } addr := ":" + port hb, err := discoverd.AddServiceAndRegister(serviceName+"-api", addr) if err != nil { shutdown.Fatal(err) } shutdown.BeforeExit(func() { hb.Close() }) handler := httphelper.ContextInjector(serviceName+"-api", httphelper.NewRequestLogger(router)) shutdown.Fatal(http.ListenAndServe(addr, handler)) }
func main() { defer shutdown.Exit() apiPort := os.Getenv("PORT") if apiPort == "" { apiPort = "5000" } logAddr := flag.String("logaddr", ":3000", "syslog input listen address") apiAddr := flag.String("apiaddr", ":"+apiPort, "api listen address") flag.Parse() a := NewAggregator(*logAddr) if err := a.Start(); err != nil { shutdown.Fatal(err) } shutdown.BeforeExit(a.Shutdown) listener, err := reuseport.NewReusablePortListener("tcp4", *apiAddr) if err != nil { shutdown.Fatal(err) } hb, err := discoverd.AddServiceAndRegister("flynn-logaggregator", *logAddr) if err != nil { shutdown.Fatal(err) } shutdown.BeforeExit(func() { hb.Close() }) shutdown.Fatal(http.Serve(listener, apiHandler(a))) }
func main() { defer shutdown.Exit() dsn := &mariadb.DSN{ Host: serviceHost + ":3306", User: "******", Password: os.Getenv("MYSQL_PWD"), Database: "mysql", } db, err := sql.Open("mysql", dsn.String()) api := &API{db} router := httprouter.New() router.POST("/databases", httphelper.WrapHandler(api.createDatabase)) router.DELETE("/databases", httphelper.WrapHandler(api.dropDatabase)) router.GET("/ping", httphelper.WrapHandler(api.ping)) port := os.Getenv("PORT") if port == "" { port = "3000" } addr := ":" + port hb, err := discoverd.AddServiceAndRegister(serviceName+"-api", addr) if err != nil { shutdown.Fatal(err) } shutdown.BeforeExit(func() { hb.Close() }) handler := httphelper.ContextInjector(serviceName+"-api", httphelper.NewRequestLogger(router)) shutdown.Fatal(http.ListenAndServe(addr, handler)) }
func main() { defer shutdown.Exit() usage := ` usage: flynn-blobstore <command> [<args>...] Commands: help show usage for a specific command cleanup delete file blobs from default backend migrate move file blobs from default backend to a different backend server run blobstore HTTP server See 'flynn-blobstore help <command>' for more information on a specific command. `[1:] args, _ := docopt.Parse(usage, nil, true, version.String(), true) cmd := args.String["<command>"] cmdArgs := args.All["<args>"].([]string) if cmd == "help" { if len(cmdArgs) == 0 { // `flynn-blobstore help` fmt.Println(usage) return } else { // `flynn-blobstore help <command>` cmd = cmdArgs[0] cmdArgs = []string{"--help"} } } if err := runCommand(cmd, cmdArgs); err != nil { log.Println(err) shutdown.ExitWithCode(1) } }
func main() { defer shutdown.Exit() api := &API{} router := httprouter.New() router.POST("/databases", api.createDatabase) router.DELETE("/databases", api.dropDatabase) router.GET("/ping", api.ping) port := os.Getenv("PORT") if port == "" { port = "3000" } addr := ":" + port hb, err := discoverd.AddServiceAndRegister(serviceName+"-api", addr) if err != nil { shutdown.Fatal(err) } shutdown.BeforeExit(func() { hb.Close() }) handler := httphelper.ContextInjector(serviceName+"-api", httphelper.NewRequestLogger(router)) shutdown.Fatal(http.ListenAndServe(addr, handler)) }
/* ish: the Inexusable/Insecure/Internet SHell. */ func main() { defer shutdown.Exit() name := os.Getenv("NAME") port := os.Getenv("PORT") addr := ":" + port if name == "" { name = "ish-service" } l, err := net.Listen("tcp", addr) if err != nil { shutdown.Fatal(err) } defer l.Close() hb, err := discoverd.AddServiceAndRegister(name, addr) if err != nil { shutdown.Fatal(err) } shutdown.BeforeExit(func() { hb.Close() }) http.HandleFunc("/ish", ish) if err := http.Serve(l, nil); err != nil { shutdown.Fatal(err) } }
func main() { logger := log15.New("component", "scheduler") logger.SetHandler(log15.LvlFilterHandler(log15.LvlInfo, log15.StdoutHandler)) log := logger.New("fn", "main") log.Info("creating cluster and controller clients") hc := &http.Client{Timeout: 5 * time.Second} clusterClient := utils.ClusterClientWrapper(cluster.NewClientWithHTTP(nil, hc)) controllerClient, err := controller.NewClient("", os.Getenv("AUTH_KEY")) if err != nil { log.Error("error creating controller client", "err", err) shutdown.Fatal(err) } log.Info("waiting for controller API to come up") if _, err := discoverd.GetInstances("controller", 5*time.Minute); err != nil { log.Error("error waiting for controller API", "err", err) shutdown.Fatal(err) } s := NewScheduler(clusterClient, controllerClient, newDiscoverdWrapper(logger), logger) log.Info("started scheduler", "backoffPeriod", s.backoffPeriod) go s.startHTTPServer(os.Getenv("PORT")) if err := s.Run(); err != nil { shutdown.Fatal(err) } shutdown.Exit() }
func main() { defer shutdown.Exit() port := os.Getenv("PORT") addr := ":" + port http.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) { w.Write([]byte("OK")) }) http.ListenAndServe(addr, nil) }
func main() { defer shutdown.Exit() grohl.AddContext("app", "controller-scheduler") grohl.Log(grohl.Data{"at": "start"}) go startHTTPServer() if period := os.Getenv("BACKOFF_PERIOD"); period != "" { var err error backoffPeriod, err = time.ParseDuration(period) if err != nil { shutdown.Fatal(err) } grohl.Log(grohl.Data{"at": "backoff_period", "period": backoffPeriod.String()}) } cc, err := controller.NewClient("", os.Getenv("AUTH_KEY")) if err != nil { shutdown.Fatal(err) } c := newContext(cc, cluster.NewClient()) c.watchHosts() grohl.Log(grohl.Data{"at": "leaderwait"}) hb, err := discoverd.AddServiceAndRegister("controller-scheduler", ":"+os.Getenv("PORT")) if err != nil { shutdown.Fatal(err) } shutdown.BeforeExit(func() { hb.Close() }) leaders := make(chan *discoverd.Instance) stream, err := discoverd.NewService("controller-scheduler").Leaders(leaders) if err != nil { shutdown.Fatal(err) } for leader := range leaders { if leader.Addr == hb.Addr() { break } } if err := stream.Err(); err != nil { // TODO: handle discoverd errors shutdown.Fatal(err) } stream.Close() // TODO: handle demotion grohl.Log(grohl.Data{"at": "leader"}) // TODO: periodic full cluster sync for anti-entropy c.watchFormations() }
func main() { defer shutdown.Exit() // Initialize main program and execute. m := NewMain() if err := m.Run(os.Args[1:]...); err != nil { fmt.Fprintln(m.Stderr, err.Error()) os.Exit(1) } // Wait indefinitely. <-(chan struct{})(nil) }
func main() { defer shutdown.Exit() runner := &Runner{ bc: args.BootConfig, events: make(chan Event), networks: make(map[string]struct{}), buildCh: make(chan struct{}, maxConcurrentBuilds), clusters: make(map[string]*cluster.Cluster), ircMsgs: make(chan string), } if err := runner.start(); err != nil { shutdown.Fatal(err) } }
func main() { defer shutdown.Exit() apiPort := os.Getenv("PORT") if apiPort == "" { apiPort = "5000" } logAddr := flag.String("logaddr", ":3000", "syslog input listen address") apiAddr := flag.String("apiaddr", ":"+apiPort, "api listen address") flag.Parse() conf := ServerConfig{ SyslogAddr: *logAddr, ApiAddr: *apiAddr, Discoverd: discoverd.DefaultClient, ServiceName: "logaggregator", } srv := NewServer(conf) shutdown.BeforeExit(srv.Shutdown) // get leader for snapshot (if any) leader, err := conf.Discoverd.Service(conf.ServiceName).Leader() if err == nil { host, _, _ := net.SplitHostPort(leader.Addr) log15.Info("loading snapshot from leader", "leader", host) c, _ := client.New("http://" + host) snapshot, err := c.GetSnapshot() if err == nil { if err := srv.LoadSnapshot(snapshot); err != nil { log15.Error("error receiving snapshot from leader", "error", err) } snapshot.Close() } else { log15.Error("error getting snapshot from leader", "error", err) } } else { log15.Info("error finding leader for snapshot", "error", err) } if err := srv.Start(); err != nil { shutdown.Fatal(err) } <-make(chan struct{}) }
func main() { defer shutdown.Exit() apiPort := os.Getenv("PORT") if apiPort == "" { apiPort = "5000" } logAddr := flag.String("logaddr", ":3000", "syslog input listen address") apiAddr := flag.String("apiaddr", ":"+apiPort, "api listen address") snapshotPath := flag.String("snapshot", "", "snapshot path") flag.Parse() a := NewAggregator(*logAddr) if *snapshotPath != "" { if err := a.ReplaySnapshot(*snapshotPath); err != nil { shutdown.Fatal(err) } shutdown.BeforeExit(func() { if err := a.TakeSnapshot(*snapshotPath); err != nil { log15.Error("snapshot error", "err", err) } }) } if err := a.Start(); err != nil { shutdown.Fatal(err) } shutdown.BeforeExit(a.Shutdown) listener, err := net.Listen("tcp4", *apiAddr) if err != nil { shutdown.Fatal(err) } hb, err := discoverd.AddServiceAndRegister("flynn-logaggregator", *logAddr) if err != nil { shutdown.Fatal(err) } shutdown.BeforeExit(func() { hb.Close() }) shutdown.Fatal(http.Serve(listener, apiHandler(a))) }
func main() { defer shutdown.Exit() flag.Parse() addr := os.Getenv("PORT") if addr == "" { addr = *listenPort } addr = ":" + addr var fs Filesystem var storageDesc string if *storageDir != "" { fs = NewOSFilesystem(*storageDir) storageDesc = *storageDir } else { var err error db := postgres.Wait(nil, nil) fs, err = NewPostgresFilesystem(db) if err != nil { shutdown.Fatal(err) } storageDesc = "Postgres" } if *serviceDiscovery { hb, err := discoverd.AddServiceAndRegister("blobstore", addr) if err != nil { shutdown.Fatal(err) } shutdown.BeforeExit(func() { hb.Close() }) } log.Println("Blobstore serving files on " + addr + " from " + storageDesc) mux := http.NewServeMux() mux.Handle("/", handler(fs)) mux.Handle(status.Path, status.Handler(fs.Status)) h := httphelper.ContextInjector("blobstore", httphelper.NewRequestLogger(mux)) shutdown.Fatal(http.ListenAndServe(addr, h)) }
func main() { defer shutdown.Exit() flag.Parse() addr := os.Getenv("PORT") if addr == "" { addr = *listenPort } addr = ":" + addr var fs Filesystem var storageDesc string if *storageDir != "" { fs = NewOSFilesystem(*storageDir) storageDesc = *storageDir } else { db, err := postgres.Open("", "") if err != nil { shutdown.Fatal(err) } fs, err = NewPostgresFilesystem(db.DB) if err != nil { shutdown.Fatal(err) } storageDesc = "Postgres" } if *serviceDiscovery { hb, err := discoverd.AddServiceAndRegister("blobstore", addr) if err != nil { shutdown.Fatal(err) } shutdown.BeforeExit(func() { hb.Close() }) } log.Println("Blobstore serving files on " + addr + " from " + storageDesc) http.Handle("/", handler(fs)) status.AddHandler(fs.Status) shutdown.Fatal(http.ListenAndServe(addr, nil)) }
func main() { log := logger.New("fn", "main") log.Info("creating cluster and controller clients") hc := &http.Client{Timeout: 5 * time.Second} clusterClient := utils.ClusterClientWrapper(cluster.NewClientWithHTTP(nil, hc)) controllerClient, err := controller.NewClient("", os.Getenv("AUTH_KEY")) if err != nil { log.Error("error creating controller client", "err", err) shutdown.Fatal(err) } s := NewScheduler(clusterClient, controllerClient, newDiscoverdWrapper()) log.Info("started scheduler", "backoffPeriod", s.backoffPeriod) go s.startHTTPServer(os.Getenv("PORT")) if err := s.Run(); err != nil { shutdown.Fatal(err) } shutdown.Exit() }
func main() { defer shutdown.Exit() port := os.Getenv("PORT") addr := ":" + port l, err := net.Listen("tcp", addr) if err != nil { shutdown.Fatal(err) } defer l.Close() log.Println("Listening on", addr) for { conn, err := l.Accept() if err != nil { shutdown.Fatal(err) } go handle(conn) } }
func main() { defer shutdown.Exit() addr := ":" + os.Getenv("PORT") db := postgres.Wait(nil, nil) if err := dbMigrations.Migrate(db); err != nil { shutdown.Fatalf("error running DB migrations: %s", err) } mux := http.NewServeMux() repo, err := data.NewFileRepoFromEnv(db) if err != nil { shutdown.Fatal(err) } hb, err := discoverd.AddServiceAndRegister("blobstore", addr) if err != nil { shutdown.Fatal(err) } shutdown.BeforeExit(func() { hb.Close() }) log.Println("Blobstore serving files on " + addr) mux.Handle("/", handler(repo)) mux.Handle(status.Path, status.Handler(func() status.Status { if err := db.Exec("SELECT 1"); err != nil { return status.Unhealthy } return status.Healthy })) h := httphelper.ContextInjector("blobstore", httphelper.NewRequestLogger(mux)) shutdown.Fatal(http.ListenAndServe(addr, h)) }
func main() { // when starting a container with libcontainer, we first exec the // current binary with libcontainer-init as the first argument, // which triggers the following code to initialise the container // environment (namespaces, network etc.) then exec containerinit if len(os.Args) > 1 && os.Args[1] == "libcontainer-init" { runtime.GOMAXPROCS(1) runtime.LockOSThread() factory, _ := libcontainer.New("") if err := factory.StartInitialization(); err != nil { log.Fatal(err) } } defer shutdown.Exit() usage := `usage: flynn-host [-h|--help] [--version] <command> [<args>...] Options: -h, --help Show this message --version Show current version Commands: help Show usage for a specific command init Create cluster configuration for daemon daemon Start the daemon update Update Flynn components download Download container images bootstrap Bootstrap layer 1 inspect Get low-level information about a job log Get the logs of a job ps List jobs stop Stop running jobs signal Signal a job destroy-volumes Destroys the local volume database collect-debug-info Collect debug information into an anonymous gist or tarball list Lists ID and IP of each host version Show current version fix Fix a broken cluster tags Manage flynn-host daemon tags discover Return low-level information about a service See 'flynn-host help <command>' for more information on a specific command. ` args, _ := docopt.Parse(usage, nil, true, version.String(), true) cmd := args.String["<command>"] cmdArgs := args.All["<args>"].([]string) if cmd == "help" { if len(cmdArgs) == 0 { // `flynn help` fmt.Println(usage) return } else { // `flynn help <command>` cmd = cmdArgs[0] cmdArgs = []string{"--help"} } } if cmd == "daemon" { // merge in args and env from config file, if available var c *config.Config if n := os.Getenv("FLYNN_HOST_CONFIG"); n != "" { var err error c, err = config.Open(n) if err != nil { shutdown.Fatalf("error opening config file %s: %s", n, err) } } else { var err error c, err = config.Open(configFile) if err != nil && !os.IsNotExist(err) { shutdown.Fatalf("error opening config file %s: %s", configFile, err) } if c == nil { c = &config.Config{} } } cmdArgs = append(cmdArgs, c.Args...) for k, v := range c.Env { os.Setenv(k, v) } } if err := cli.Run(cmd, cmdArgs); err != nil { if err == cli.ErrInvalidCommand { fmt.Printf("ERROR: %q is not a valid command\n\n", cmd) fmt.Println(usage) shutdown.ExitWithCode(1) } else if _, ok := err.(cli.ErrAlreadyLogged); ok { shutdown.ExitWithCode(1) } shutdown.Fatal(err) } }
func main() { defer shutdown.Exit() var cookieKey *[32]byte if key := os.Getenv("COOKIE_KEY"); key != "" { res, err := base64.StdEncoding.DecodeString(key) if err != nil { shutdown.Fatalf("error decoding COOKIE_KEY: %s", err) } if len(res) != 32 { shutdown.Fatalf("decoded %d bytes from COOKIE_KEY, expected 32", len(res)) } var k [32]byte copy(k[:], res) cookieKey = &k } if cookieKey == nil { shutdown.Fatal("Missing random 32 byte base64-encoded COOKIE_KEY") } httpPort := flag.String("http-port", "8080", "http listen port") httpsPort := flag.String("https-port", "4433", "https listen port") tcpIP := flag.String("tcp-ip", os.Getenv("LISTEN_IP"), "tcp router listen ip") tcpRangeStart := flag.Int("tcp-range-start", 3000, "tcp port range start") tcpRangeEnd := flag.Int("tcp-range-end", 3500, "tcp port range end") certFile := flag.String("tls-cert", "", "TLS (SSL) cert file in pem format") keyFile := flag.String("tls-key", "", "TLS (SSL) key file in pem format") apiPort := flag.String("api-port", "", "api listen port") flag.Parse() if *apiPort == "" { *apiPort = os.Getenv("PORT") if *apiPort == "" { *apiPort = "5000" } } keypair := tls.Certificate{} var err error if *certFile != "" { if keypair, err = tls.LoadX509KeyPair(*certFile, *keyFile); err != nil { shutdown.Fatal(err) } } else if tlsCert := os.Getenv("TLSCERT"); tlsCert != "" { if tlsKey := os.Getenv("TLSKEY"); tlsKey != "" { os.Setenv("TLSKEY", fmt.Sprintf("md5^(%s)", md5sum(tlsKey))) if keypair, err = tls.X509KeyPair([]byte(tlsCert), []byte(tlsKey)); err != nil { shutdown.Fatal(err) } } } log := logger.New("fn", "main") log.Info("connecting to postgres") db, err := postgres.Open("", "") if err != nil { log.Error("error connecting to postgres", "err", err) shutdown.Fatal(err) } log.Info("running DB migrations") if err := migrateDB(db.DB); err != nil { log.Error("error running DB migrations", "err", err) shutdown.Fatal(err) } var pgport int if port := os.Getenv("PGPORT"); port != "" { var err error if pgport, err = strconv.Atoi(port); err != nil { shutdown.Fatal(err) } } log.Info("creating postgres connection pool") pgxpool, err := pgx.NewConnPool(pgx.ConnPoolConfig{ ConnConfig: pgx.ConnConfig{ Host: os.Getenv("PGHOST"), Port: uint16(pgport), Database: os.Getenv("PGDATABASE"), User: os.Getenv("PGUSER"), Password: os.Getenv("PGPASSWORD"), }, }) if err != nil { log.Error("error creating postgres connection pool", "err", err) shutdown.Fatal(err) } shutdown.BeforeExit(func() { pgxpool.Close() }) httpAddr := net.JoinHostPort(os.Getenv("LISTEN_IP"), *httpPort) httpsAddr := net.JoinHostPort(os.Getenv("LISTEN_IP"), *httpsPort) r := Router{ TCP: &TCPListener{ IP: *tcpIP, startPort: *tcpRangeStart, endPort: *tcpRangeEnd, ds: NewPostgresDataStore("tcp", pgxpool), discoverd: discoverd.DefaultClient, }, HTTP: &HTTPListener{ Addr: httpAddr, TLSAddr: httpsAddr, cookieKey: cookieKey, keypair: keypair, ds: NewPostgresDataStore("http", pgxpool), discoverd: discoverd.DefaultClient, }, } if err := r.Start(); err != nil { shutdown.Fatal(err) } shutdown.BeforeExit(r.Close) apiAddr := net.JoinHostPort(os.Getenv("LISTEN_IP"), *apiPort) log.Info("starting API listener") listener, err := listenFunc("tcp4", apiAddr) if err != nil { log.Error("error starting API listener", "err", err) shutdown.Fatal(listenErr{apiAddr, err}) } services := map[string]string{ "router-api": apiAddr, "router-http": httpAddr, } for service, addr := range services { log.Info("registering service", "name", service, "addr", addr) hb, err := discoverd.AddServiceAndRegister(service, addr) if err != nil { log.Error("error registering service", "name", service, "addr", addr, "err", err) shutdown.Fatal(err) } shutdown.BeforeExit(func() { hb.Close() }) } log.Info("serving API requests") shutdown.Fatal(http.Serve(listener, apiHandler(&r))) }
func main() { defer shutdown.Exit() usage := `usage: flynn-host [-h|--help] [--version] <command> [<args>...] Options: -h, --help Show this message --version Show current version Commands: help Show usage for a specific command init Create cluster configuration for daemon daemon Start the daemon update Update Flynn components download Download container images bootstrap Bootstrap layer 1 inspect Get low-level information about a job log Get the logs of a job ps List jobs stop Stop running jobs destroy-volumes Destroys the local volume database collect-debug-info Collect debug information into an anonymous gist or tarball version Show current version See 'flynn-host help <command>' for more information on a specific command. ` args, _ := docopt.Parse(usage, nil, true, version.String(), true) cmd := args.String["<command>"] cmdArgs := args.All["<args>"].([]string) if cmd == "help" { if len(cmdArgs) == 0 { // `flynn help` fmt.Println(usage) return } else { // `flynn help <command>` cmd = cmdArgs[0] cmdArgs = []string{"--help"} } } if cmd == "daemon" { // merge in args and env from config file, if available var c *config.Config if n := os.Getenv("FLYNN_HOST_CONFIG"); n != "" { var err error c, err = config.Open(n) if err != nil { log.Fatalf("error opening config file %s: %s", n, err) } } else { var err error c, err = config.Open(configFile) if err != nil && !os.IsNotExist(err) { log.Fatalf("error opening config file %s: %s", configFile, err) } if c == nil { c = &config.Config{} } } cmdArgs = append(cmdArgs, c.Args...) for k, v := range c.Env { os.Setenv(k, v) } } if err := cli.Run(cmd, cmdArgs); err != nil { if err == cli.ErrInvalidCommand { fmt.Printf("ERROR: %q is not a valid command\n\n", cmd) fmt.Println(usage) shutdown.ExitWithCode(1) } shutdown.Fatal(err) } }
func main() { defer shutdown.Exit() port := os.Getenv("PORT") if port == "" { port = "3000" } addr := ":" + port if seed := os.Getenv("NAME_SEED"); seed != "" { s, err := hex.DecodeString(seed) if err != nil { log.Fatalln("error decoding NAME_SEED:", err) } name.SetSeed(s) } db := postgres.Wait("", "") if err := migrateDB(db.DB); err != nil { shutdown.Fatal(err) } pgxcfg, err := pgx.ParseURI(fmt.Sprintf("http://%s:%s@%s/%s", os.Getenv("PGUSER"), os.Getenv("PGPASSWORD"), db.Addr(), os.Getenv("PGDATABASE"))) if err != nil { log.Fatal(err) } pgxcfg.Dial = dialer.Retry.Dial pgxpool, err := pgx.NewConnPool(pgx.ConnPoolConfig{ ConnConfig: pgxcfg, AfterConnect: que.PrepareStatements, }) if err != nil { log.Fatal(err) } shutdown.BeforeExit(func() { pgxpool.Close() }) lc, err := logaggc.New("") if err != nil { shutdown.Fatal(err) } rc := routerc.New() hb, err := discoverd.DefaultClient.AddServiceAndRegisterInstance("flynn-controller", &discoverd.Instance{ Addr: addr, Proto: "http", Meta: map[string]string{ "AUTH_KEY": os.Getenv("AUTH_KEY"), }, }) if err != nil { shutdown.Fatal(err) } shutdown.BeforeExit(func() { hb.Close() }) handler := appHandler(handlerConfig{ db: db, cc: clusterClientWrapper{cluster.NewClient()}, lc: lc, rc: rc, pgxpool: pgxpool, keys: strings.Split(os.Getenv("AUTH_KEY"), ","), }) shutdown.Fatal(http.ListenAndServe(addr, handler)) }
func main() { defer shutdown.Exit() httpAddr := flag.String("http-addr", ":1111", "address to serve HTTP API from") dnsAddr := flag.String("dns-addr", "", "address to service DNS from") resolvers := flag.String("recursors", "8.8.8.8,8.8.4.4", "upstream recursive DNS servers") etcdAddrs := flag.String("etcd", "http://127.0.0.1:2379", "etcd servers (comma separated)") notify := flag.String("notify", "", "url to send webhook to after starting listener") waitNetDNS := flag.Bool("wait-net-dns", false, "start DNS server after host network is configured") flag.Parse() etcdClient := etcd.NewClient(strings.Split(*etcdAddrs, ",")) // Check to make sure that etcd is online and accepting connections // etcd takes a while to come online, so we attempt a GET multiple times err := attempt.Strategy{ Min: 5, Total: 10 * time.Minute, Delay: 200 * time.Millisecond, }.Run(func() (err error) { _, err = etcdClient.Get("/", false, false) if e, ok := err.(*etcd.EtcdError); ok && e.ErrorCode == 100 { // Valid 404 from etcd (> v2.0) err = nil } return }) if err != nil { log.Fatalf("Failed to connect to etcd at %v: %q", etcdAddrs, err) } state := server.NewState() backend := server.NewEtcdBackend(etcdClient, "/discoverd", state) if err := backend.StartSync(); err != nil { log.Fatalf("Failed to perform initial etcd sync: %s", err) } // if we have a DNS address, start a DNS server right away, otherwise // wait for the host network to come up and then start a DNS server. if *dnsAddr != "" { var recursors []string if *resolvers != "" { recursors = strings.Split(*resolvers, ",") } if err := startDNSServer(state, *dnsAddr, recursors); err != nil { log.Fatalf("Failed to start DNS server: %s", err) } log.Printf("discoverd listening for DNS on %s", *dnsAddr) } else if *waitNetDNS { go func() { status, err := waitForHostNetwork() if err != nil { log.Fatal(err) } ip, _, err := net.ParseCIDR(status.Network.Subnet) if err != nil { log.Fatal(err) } addr := net.JoinHostPort(ip.String(), "53") if err := startDNSServer(state, addr, status.Network.Resolvers); err != nil { log.Fatalf("Failed to start DNS server: %s", err) } log.Printf("discoverd listening for DNS on %s", addr) if *notify != "" { notifyWebhook(*notify, "", addr) } }() } l, err := net.Listen("tcp4", *httpAddr) if err != nil { log.Fatalf("Failed to start HTTP listener: %s", err) } log.Printf("discoverd listening for HTTP on %s", *httpAddr) if *notify != "" { addr := l.Addr().String() host, port, _ := net.SplitHostPort(addr) if host == "0.0.0.0" { addr = net.JoinHostPort(os.Getenv("EXTERNAL_IP"), port) } notifyWebhook(*notify, fmt.Sprintf("http://%s", addr), *dnsAddr) } http.Serve(l, server.NewHTTPHandler(server.NewBasicDatastore(state, backend))) }
func main() { defer shutdown.Exit() apiPort := os.Getenv("PORT") if apiPort == "" { apiPort = "5000" } var cookieKey *[32]byte if key := os.Getenv("COOKIE_KEY"); key != "" { res, err := base64.StdEncoding.DecodeString(key) if err != nil { shutdown.Fatal("error decoding COOKIE_KEY:", err) } var k [32]byte copy(k[:], res) cookieKey = &k } httpAddr := flag.String("httpaddr", ":8080", "http listen address") httpsAddr := flag.String("httpsaddr", ":4433", "https listen address") tcpIP := flag.String("tcpip", "", "tcp router listen ip") tcpRangeStart := flag.Int("tcp-range-start", 3000, "tcp port range start") tcpRangeEnd := flag.Int("tcp-range-end", 3500, "tcp port range end") certFile := flag.String("tlscert", "", "TLS (SSL) cert file in pem format") keyFile := flag.String("tlskey", "", "TLS (SSL) key file in pem format") apiAddr := flag.String("apiaddr", ":"+apiPort, "api listen address") flag.Parse() keypair := tls.Certificate{} var err error if *certFile != "" { if keypair, err = tls.LoadX509KeyPair(*certFile, *keyFile); err != nil { shutdown.Fatal(err) } } else if tlsCert := os.Getenv("TLSCERT"); tlsCert != "" { if tlsKey := os.Getenv("TLSKEY"); tlsKey != "" { os.Setenv("TLSKEY", fmt.Sprintf("md5^(%s)", md5sum(tlsKey))) if keypair, err = tls.X509KeyPair([]byte(tlsCert), []byte(tlsKey)); err != nil { shutdown.Fatal(err) } } } db, err := postgres.Open("", "") if err != nil { shutdown.Fatal(err) } if err := migrateDB(db.DB); err != nil { shutdown.Fatal(err) } var pgport int if port := os.Getenv("PGPORT"); port != "" { var err error if pgport, err = strconv.Atoi(port); err != nil { shutdown.Fatal(err) } } pgxpool, err := pgx.NewConnPool(pgx.ConnPoolConfig{ ConnConfig: pgx.ConnConfig{ Host: os.Getenv("PGHOST"), Port: uint16(pgport), Database: os.Getenv("PGDATABASE"), User: os.Getenv("PGUSER"), Password: os.Getenv("PGPASSWORD"), }, }) if err != nil { shutdown.Fatal(err) } shutdown.BeforeExit(func() { pgxpool.Close() }) r := Router{ TCP: &TCPListener{ IP: *tcpIP, startPort: *tcpRangeStart, endPort: *tcpRangeEnd, ds: NewPostgresDataStore("tcp", pgxpool), discoverd: discoverd.DefaultClient, }, HTTP: &HTTPListener{ Addr: *httpAddr, TLSAddr: *httpsAddr, cookieKey: cookieKey, keypair: keypair, ds: NewPostgresDataStore("http", pgxpool), discoverd: discoverd.DefaultClient, }, } if err := r.Start(); err != nil { shutdown.Fatal(err) } listener, err := listenFunc("tcp4", *apiAddr) if err != nil { shutdown.Fatal(listenErr{*apiAddr, err}) } services := map[string]string{ "router-api": *apiAddr, "router-http": *httpAddr, } for service, addr := range services { hb, err := discoverd.AddServiceAndRegister(service, addr) if err != nil { shutdown.Fatal(err) } shutdown.BeforeExit(func() { hb.Close() }) } shutdown.Fatal(http.Serve(listener, apiHandler(&r))) }
func main() { defer shutdown.Exit() var err error if err = lookupImageURIs(); err != nil { log.Fatalf("could not determine image ID: %s", err) } var res *check.Result // defer exiting here so it runs after all other defers defer func() { if err != nil || res != nil && !res.Passed() { os.Exit(1) } }() flynnrc = args.Flynnrc routerIP = args.RouterIP if flynnrc == "" { c := cluster.New(args.BootConfig, os.Stdout) var rootFS string rootFS, err = c.BuildFlynn(args.RootFS, "origin/master", false, false) if err != nil { if args.Kill { c.Shutdown() } log.Println("could not build flynn: ", err) if rootFS != "" { os.RemoveAll(rootFS) } return } if args.BuildRootFS { c.Shutdown() fmt.Println("Built Flynn in rootfs:", rootFS) return } else { defer os.RemoveAll(rootFS) } if _, err = c.Boot(cluster.ClusterTypeDefault, 3, nil, args.Kill); err != nil { log.Println("could not boot cluster: ", err) return } if args.Kill { defer c.Shutdown() } if err = createFlynnrc(c); err != nil { log.Println(err) return } defer os.RemoveAll(flynnrc) routerIP = c.RouterIP } if args.ClusterAPI != "" { testCluster, err = testcluster.NewClient(args.ClusterAPI) if err != nil { log.Println(err) return } } res = check.RunAll(&check.RunConf{ Filter: args.Run, Stream: args.Stream, Verbose: args.Debug, KeepWorkDir: args.Debug, ConcurrencyLevel: args.Concurrency, }) fmt.Println(res) }
func main() { defer shutdown.Exit() log.SetFlags(0) usage := ` usage: flynn [-a <app>] [-c <cluster>] <command> [<args>...] Options: -a <app> -c <cluster> -h, --help Commands: help show usage for a specific command install install flynn cluster manage clusters create create an app delete delete an app apps list apps ps list jobs kill kill a job log get app log scale change formation run run a job env manage env variables meta manage app metadata route manage routes pg manage postgres database provider manage resource providers resource provision a new resource key manage SSH public keys release add a docker image release export export app data import create app from exported data version show flynn version See 'flynn help <command>' for more information on a specific command. `[1:] args, _ := docopt.Parse(usage, nil, true, version.String(), true) cmd := args.String["<command>"] cmdArgs := args.All["<args>"].([]string) if cmd == "help" { if len(cmdArgs) == 0 { // `flynn help` fmt.Println(usage) return } else if cmdArgs[0] == "--json" { cmds := make(map[string]string) for name, cmd := range commands { cmds[name] = cmd.usage } out, err := json.MarshalIndent(cmds, "", "\t") if err != nil { shutdown.Fatal(err) } fmt.Println(string(out)) return } else { // `flynn help <command>` cmd = cmdArgs[0] cmdArgs = make([]string, 1) cmdArgs[0] = "--help" } } // Run the update command as early as possible to avoid the possibility of // installations being stranded without updates due to errors in other code if cmd == "update" { if err := runUpdate(); err != nil { shutdown.Fatal(err) } return } else { defer updater.backgroundRun() // doesn't run if os.Exit is called } // Set the cluster config name if args.String["-c"] != "" { flagCluster = args.String["-c"] } flagApp = args.String["-a"] if flagApp != "" { if err := readConfig(); err != nil { shutdown.Fatal(err) } if ra, err := appFromGitRemote(flagApp); err == nil { clusterConf = ra.Cluster flagApp = ra.Name } } if err := runCommand(cmd, cmdArgs); err != nil { log.Println(err) shutdown.ExitWithCode(1) return } }
func main() { defer shutdown.Exit() httpAddr := flag.String("http-addr", ":1111", "address to serve HTTP API from") dnsAddr := flag.String("dns-addr", ":53", "address to service DNS from") resolvers := flag.String("recursors", "8.8.8.8,8.8.4.4", "upstream recursive DNS servers") etcdAddrs := flag.String("etcd", "http://127.0.0.1:2379", "etcd servers (comma separated)") notify := flag.String("notify", "", "url to send webhook to after starting listener") flag.Parse() etcdClient := etcd.NewClient(strings.Split(*etcdAddrs, ",")) // Check to make sure that etcd is online and accepting connections // etcd takes a while to come online, so we attempt a GET multiple times err := attempt.Strategy{ Min: 5, Total: 10 * time.Minute, Delay: 200 * time.Millisecond, }.Run(func() (err error) { _, err = etcdClient.Get("/", false, false) if e, ok := err.(*etcd.EtcdError); ok && e.ErrorCode == 100 { // Valid 404 from etcd (> v2.0) err = nil } return }) if err != nil { log.Fatalf("Failed to connect to etcd at %v: %q", etcdAddrs, err) } state := server.NewState() backend := server.NewEtcdBackend(etcdClient, "/discoverd", state) if err := backend.StartSync(); err != nil { log.Fatalf("Failed to perform initial etcd sync: %s", err) } dns := server.DNSServer{ UDPAddr: *dnsAddr, TCPAddr: *dnsAddr, Store: state, } if *resolvers != "" { dns.Recursors = strings.Split(*resolvers, ",") } if err := dns.ListenAndServe(); err != nil { log.Fatalf("Failed to start DNS server: %s", err) } l, err := net.Listen("tcp4", *httpAddr) if err != nil { log.Fatalf("Failed to start HTTP listener: %s", err) } log.Printf("discoverd listening for HTTP on %s and DNS on %s", *httpAddr, *dnsAddr) if *notify != "" { addr := l.Addr().String() host, port, _ := net.SplitHostPort(addr) if host == "0.0.0.0" { // try to get real address from dns addr if dnsHost, _, _ := net.SplitHostPort(*dnsAddr); dnsHost != "" { addr = net.JoinHostPort(dnsHost, port) } } data := struct { URL string `json:"url"` }{fmt.Sprintf("http://%s", addr)} payload, _ := json.Marshal(data) res, err := http.Post(*notify, "application/json", bytes.NewReader(payload)) if err != nil { log.Printf("failed to notify: %s", err) } else { res.Body.Close() } } http.Serve(l, server.NewHTTPHandler(server.NewBasicDatastore(state, backend))) }