func setup(t etcdrunner.TestingT, ec EtcdClient, dc discoverdClient) (discoverdClient, EtcdClient, func()) { if *fake { if ec == nil { ec = newFakeEtcd() } if dc == nil { dc = newFakeDiscoverd() } return dc, ec, nil } var killEtcd, killDiscoverd func() if ec == nil { killEtcd = etcdrunner.RunEtcdServer(t) ec = etcd.NewClient(nil) } if dc == nil { dc, killDiscoverd = testutil.BootDiscoverd(t, "") } return dc, ec, func() { if killDiscoverd != nil { dc.Close() killDiscoverd() } if killEtcd != nil { killEtcd() } } }
func setup(t etcdrunner.TestingT, ec EtcdClient, dc discoverdClient) (discoverdClient, EtcdClient, func()) { if *fake { if ec == nil { ec = newFakeEtcd() } if dc == nil { dc = newFakeDiscoverd() } return dc, ec, nil } var killEtcd, killDiscoverd func() var etcdAddr string if ec == nil { etcdAddr, killEtcd = etcdrunner.RunEtcdServer(t) ec = etcd.NewClient([]string{etcdAddr}) } else if c, ok := ec.(*etcd.Client); ok { etcdAddr = c.GetCluster()[0] } if dc == nil { dc, killDiscoverd = testutil.BootDiscoverd(t, "", etcdAddr) } return dc, ec, func() { if killDiscoverd != nil { dc.Close() killDiscoverd() } if killEtcd != nil { killEtcd() } } }
func newEtcd(t etcdrunner.TestingT) (EtcdClient, func()) { if *fake { return newFakeEtcd(), func() {} } cleanup := etcdrunner.RunEtcdServer(t) return etcd.NewClient(nil), cleanup }
func newEtcd(t etcdrunner.TestingT) (EtcdClient, string, func()) { if *fake { return newFakeEtcd(), "", func() {} } addr, cleanup := etcdrunner.RunEtcdServer(t) return etcd.NewClient([]string{addr}), addr, cleanup }
func RunEtcdServer(t TestingT) func() { killCh := make(chan struct{}) doneCh := make(chan struct{}) name := "etcd-test." + strconv.Itoa(random.Math.Int()) dataDir, err := ioutil.TempDir("", "") if err != nil { t.Fatal("tempdir failed:", err) } go func() { cmd := exec.Command("etcd", "-name", name, "-data-dir", dataDir) var stderr, stdout io.Reader if os.Getenv("DEBUG") != "" { stderr, _ = cmd.StderrPipe() stdout, _ = cmd.StdoutPipe() } if err := cmd.Start(); err != nil { t.Fatal("etcd start failed:", err) return } cmdDone := make(chan error) go func() { if stdout != nil { LogOutput("etcd", stdout, stderr) } cmdDone <- cmd.Wait() }() defer close(doneCh) select { case <-killCh: if err := cmd.Process.Kill(); err != nil { t.Fatal("failed to kill etcd:", err) return } <-cmdDone case err := <-cmdDone: t.Log("etcd process exited:", err) return } if err := os.RemoveAll(dataDir); err != nil { t.Log("etcd data removal failed:", err) } }() // wait for etcd to come up client := etcd.NewClient(nil) err = Attempts.Run(func() (err error) { _, err = client.Get("/", false, false) return }) if err != nil { t.Fatalf("Failed to connect to etcd: %q", err) } return func() { close(killCh) <-doneCh } }
func main() { 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 { log.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") apiAddr := flag.String("apiaddr", ":"+apiPort, "api listen address") flag.Parse() // Will use DISCOVERD environment variable d, err := discoverd.NewClient() if err != nil { log.Fatal(err) } if err := d.Register("strowger-api", *apiAddr); err != nil { log.Fatal(err) } // Read etcd addresses from ETCD etcdAddrs := strings.Split(os.Getenv("ETCD"), ",") if len(etcdAddrs) == 1 && etcdAddrs[0] == "" { if externalIP := os.Getenv("EXTERNAL_IP"); externalIP != "" { etcdAddrs = []string{fmt.Sprintf("http://%s:4001", externalIP)} } else { etcdAddrs = nil } } etcdc := etcd.NewClient(etcdAddrs) var r Router r.TCP = NewTCPListener(*tcpIP, 0, 0, NewEtcdDataStore(etcdc, "/strowger/tcp/"), d) r.HTTP = NewHTTPListener(*httpAddr, *httpsAddr, cookieKey, NewEtcdDataStore(etcdc, "/strowger/http/"), d) go func() { log.Fatal(r.ListenAndServe(nil)) }() log.Fatal(http.ListenAndServe(*apiAddr, apiHandler(&r))) }
func main() { var config Config config.Backend.Type = "vxlan" flag.StringVar(&config.Network, "network", "100.100.0.0/16", "container network") flag.StringVar(&config.EtcdURLs, "etcd", "http://127.0.0.1:2379", "etcd URLs") flag.StringVar(&config.SubnetMin, "subnet-min", "", "container network min subnet") flag.StringVar(&config.SubnetMax, "subnet-max", "", "container network max subnet") flag.UintVar(&config.SubnetLen, "subnet-len", 0, "container network subnet length") flag.UintVar(&config.Backend.VNI, "vni", 0, "vxlan network identifier") flag.UintVar(&config.Backend.Port, "port", 0, "vxlan communication port (UDP)") etcdKey := flag.String("key", "/coreos.com/network/config", "flannel etcd configuration key") flag.Parse() bytes, err := json.Marshal(&config) if err != nil { log.Fatal(err) } data := string(bytes) client := etcd.NewClient(strings.Split(config.EtcdURLs, ",")) if err := networkConfigAttempts.Run(func() error { _, err = client.Create(*etcdKey, data, 0) if e, ok := err.(*etcd.EtcdError); ok && e.ErrorCode == 105 { // Skip if the key exists err = nil } return err }); err != nil { log.Fatal(err) } flanneld, err := exec.LookPath("flanneld") if err != nil { log.Fatal(err) } if err := syscall.Exec( flanneld, []string{ flanneld, "-etcd-endpoints=" + config.EtcdURLs, "-iface=" + os.Getenv("EXTERNAL_IP"), fmt.Sprintf("-notify-url=http://%s:1113/host/network", os.Getenv("EXTERNAL_IP")), }, os.Environ(), ); err != nil { log.Fatal(err) } }
// NewServer creates a new discoverd server listening at addr and backed by etcd. func NewServer(addr string, etcdAddrs []string) *Agent { client := etcd.NewClient(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 := Attempts.Run(func() (err error) { _, err = client.Get("/", false, false) return }) if err != nil { log.Fatalf("Failed to connect to etcd at %v: %q", etcdAddrs, err) } return &Agent{ Backend: &EtcdBackend{Client: client}, Address: addr, } }
func runEtcdServer(t *testing.T) (*etcd.Client, func()) { killCh := make(chan struct{}) doneCh := make(chan struct{}) r := rand.New(rand.NewSource(time.Now().UnixNano())) name := "etcd-test." + strconv.Itoa(r.Int()) dataDir := "/tmp/" + name go func() { cmd := exec.Command("etcd", "-name", name, "-data-dir", dataDir) if err := cmd.Start(); err != nil { panic(err) } cmdDone := make(chan error) go func() { cmdDone <- cmd.Wait() }() select { case <-killCh: if err := cmd.Process.Kill(); err != nil { panic(err) } <-cmdDone case err := <-cmdDone: panic(err) } if err := os.RemoveAll(dataDir); err != nil { panic(err) } doneCh <- struct{}{} }() client := etcd.NewClient(nil) err := Attempts.Run(func() (err error) { _, err = client.Get("/", false, false) return }) if err != nil { t.Fatalf("Failed to connect to etcd: %q", err) } return client, func() { close(killCh) <-doneCh } }
func newEtcdBackend(state *State) Backend { return NewEtcdBackend(etcd.NewClient([]string{etcdAddr}), fmt.Sprintf("/test/discoverd/%s", random.String(8)), state) }
func main() { 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 { log.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") apiAddr := flag.String("apiaddr", ":"+apiPort, "api listen address") flag.Parse() // Will use DISCOVERD environment variable d, err := discoverd.NewClient() if err != nil { log.Fatal(err) } services := map[string]string{ "router-api": *apiAddr, "router-http": *httpAddr, } for service, addr := range services { if err := d.Register(service, addr); err != nil { log.Fatal(err) } } shutdown.BeforeExit(func() { for service, addr := range services { discoverd.Unregister(service, addr) } }) // Read etcd addresses from ETCD etcdAddrs := strings.Split(os.Getenv("ETCD"), ",") if len(etcdAddrs) == 1 && etcdAddrs[0] == "" { if externalIP := os.Getenv("EXTERNAL_IP"); externalIP != "" { etcdAddrs = []string{fmt.Sprintf("http://%s:4001", externalIP)} } else { etcdAddrs = nil } } etcdc := etcd.NewClient(etcdAddrs) prefix := os.Getenv("ETCD_PREFIX") if prefix == "" { prefix = "/router" } var r Router r.TCP = NewTCPListener(*tcpIP, *tcpRangeStart, *tcpRangeEnd, NewEtcdDataStore(etcdc, path.Join(prefix, "tcp/")), d) r.HTTP = NewHTTPListener(*httpAddr, *httpsAddr, cookieKey, NewEtcdDataStore(etcdc, path.Join(prefix, "http/")), d) go func() { log.Fatal(r.ListenAndServe(nil)) }() log.Fatal(http.ListenAndServe(*apiAddr, apiHandler(&r))) }
func runEtcdServer(t *testing.T) (*etcd.Client, func()) { kill := etcdrunner.RunEtcdServer(t) return etcd.NewClient(nil), kill }
func runEtcdServer(t *testing.T) (*etcd.Client, func()) { addr, kill := etcdrunner.RunEtcdServer(t) return etcd.NewClient([]string{addr}), kill }
func RunEtcdServer(t TestingT) (string, func()) { killCh := make(chan struct{}) doneCh := make(chan struct{}) name := "etcd-test." + strconv.Itoa(random.Math.Int()) dataDir, err := ioutil.TempDir("", "") if err != nil { t.Fatal("tempdir failed: ", err) } port, err := RandomPort() if err != nil { t.Fatal("error getting random etcd port: ", err) } clusterPort, err := RandomPort() if err != nil { t.Fatal("error getting random cluster port: ", err) } go func() { cmd := exec.Command("etcd", "-name", name, "-data-dir", dataDir, "-addr", "127.0.0.1:"+port, "-bind-addr", "127.0.0.1:"+port, "-peer-addr", "127.0.0.1:"+clusterPort, "-peer-bind-addr", "127.0.0.1:"+clusterPort, ) var stderr, stdout io.Reader if os.Getenv("DEBUG") != "" { stderr, _ = cmd.StderrPipe() stdout, _ = cmd.StdoutPipe() } if err := cmd.Start(); err != nil { t.Fatal("etcd start failed: ", err) return } cmdDone := make(chan error) go func() { if stdout != nil { LogOutput("etcd", stdout, stderr) } cmdDone <- cmd.Wait() }() defer close(doneCh) select { case <-killCh: if err := cmd.Process.Kill(); err != nil { t.Fatal("failed to kill etcd: ", err) return } err := <-cmdDone t.Log("etcd process exited: ", err) case err := <-cmdDone: t.Log("etcd process exited unexpectedly: ", err) return } if err := os.RemoveAll(dataDir); err != nil { t.Log("etcd data removal failed: ", err) } }() addr := "http://127.0.0.1:" + port // wait for etcd to come up client := etcd.NewClient([]string{addr}) err = Attempts.Run(func() (err error) { _, err = client.Get("/", false, false) return }) if err != nil { t.Fatal("Failed to connect to etcd: ", err) } return addr, func() { close(killCh) <-doneCh } }
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() 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))) }