Beispiel #1
0
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()
		}
	}
}
Beispiel #2
0
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()
		}
	}
}
Beispiel #3
0
func newEtcd(t etcdrunner.TestingT) (EtcdClient, func()) {
	if *fake {
		return newFakeEtcd(), func() {}
	}
	cleanup := etcdrunner.RunEtcdServer(t)
	return etcd.NewClient(nil), cleanup
}
Beispiel #4
0
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
}
Beispiel #5
0
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
	}
}
Beispiel #6
0
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)))
}
Beispiel #7
0
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)
	}
}
Beispiel #8
0
// 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
	}
}
Beispiel #10
0
func newEtcdBackend(state *State) Backend {
	return NewEtcdBackend(etcd.NewClient([]string{etcdAddr}), fmt.Sprintf("/test/discoverd/%s", random.String(8)), state)
}
Beispiel #11
0
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)))
}
Beispiel #12
0
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
}
Beispiel #14
0
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
	}
}
Beispiel #15
0
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)))
}
Beispiel #16
0
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)))
}