// NewClientHandler generates a muxed http.Handler with the given parameters to serve etcd client requests. func NewClientHandler(server *etcdserver.EtcdServer) http.Handler { kh := &keysHandler{ server: server, clusterInfo: server.Cluster, timer: server, timeout: defaultServerTimeout, } sh := &statsHandler{ stats: server, } mh := &membersHandler{ server: server, clusterInfo: server.Cluster, clock: clockwork.NewRealClock(), } dmh := &deprecatedMachinesHandler{ clusterInfo: server.Cluster, } mux := http.NewServeMux() mux.HandleFunc("/", http.NotFound) mux.HandleFunc(versionPrefix, serveVersion) mux.Handle(keysPrefix, kh) mux.Handle(keysPrefix+"/", kh) mux.HandleFunc(statsPrefix+"/store", sh.serveStore) mux.HandleFunc(statsPrefix+"/self", sh.serveSelf) mux.HandleFunc(statsPrefix+"/leader", sh.serveLeader) mux.Handle(membersPrefix, mh) mux.Handle(membersPrefix+"/", mh) mux.Handle(deprecatedMachinesPrefix, dmh) return mux }
func newDiscovery(durl, dproxyurl string, id types.ID) (*discovery, error) { u, err := url.Parse(durl) if err != nil { return nil, err } token := u.Path u.Path = "" pf, err := newProxyFunc(dproxyurl) if err != nil { return nil, err } cfg := client.Config{ Transport: &http.Transport{Proxy: pf}, Endpoints: []string{u.String()}, } c, err := client.New(cfg) if err != nil { return nil, err } dc := client.NewKeysAPIWithPrefix(c, "") return &discovery{ cluster: token, c: dc, id: id, url: u, clock: clockwork.NewRealClock(), }, nil }
func NewPeriodic(h int, rg RevGetter, c Compactable) *Periodic { return &Periodic{ clock: clockwork.NewRealClock(), periodInHour: h, rg: rg, c: c, } }
func newSnapshotStore(dir string, kv dstorage.KV) *snapshotStore { return &snapshotStore{ dir: dir, kv: kv, reqsnapc: make(chan struct{}), raftsnapc: make(chan raftpb.Snapshot), clock: clockwork.NewRealClock(), } }
// NewClientHandler generates a muxed http.Handler with the given parameters to serve etcd client requests. func NewClientHandler(server *etcdserver.EtcdServer, timeout time.Duration) http.Handler { go capabilityLoop(server) sec := auth.NewStore(server, timeout) kh := &keysHandler{ sec: sec, server: server, cluster: server.Cluster(), timer: server, timeout: timeout, } sh := &statsHandler{ stats: server, } mh := &membersHandler{ sec: sec, server: server, cluster: server.Cluster(), timeout: timeout, clock: clockwork.NewRealClock(), } dmh := &deprecatedMachinesHandler{ cluster: server.Cluster(), } sech := &authHandler{ sec: sec, cluster: server.Cluster(), } mux := http.NewServeMux() mux.HandleFunc("/", http.NotFound) mux.Handle(healthPath, healthHandler(server)) mux.HandleFunc(versionPath, versionHandler(server.Cluster(), serveVersion)) mux.Handle(keysPrefix, kh) mux.Handle(keysPrefix+"/", kh) mux.HandleFunc(statsPrefix+"/store", sh.serveStore) mux.HandleFunc(statsPrefix+"/self", sh.serveSelf) mux.HandleFunc(statsPrefix+"/leader", sh.serveLeader) mux.HandleFunc(varsPath, serveVars) mux.HandleFunc(configPath+"/local/log", logHandleFunc) mux.Handle(metricsPath, prometheus.Handler()) mux.Handle(membersPrefix, mh) mux.Handle(membersPrefix+"/", mh) mux.Handle(deprecatedMachinesPrefix, dmh) handleAuth(mux, sech) return requestLogger(mux) }
func (h *keysHandler) ServeHTTP(w http.ResponseWriter, r *http.Request) { if !allowMethod(w, r.Method, "HEAD", "GET", "PUT", "POST", "DELETE") { return } w.Header().Set("X-Etcd-Cluster-ID", h.cluster.ID().String()) ctx, cancel := context.WithTimeout(context.Background(), h.timeout) defer cancel() clock := clockwork.NewRealClock() startTime := clock.Now() rr, err := parseKeyRequest(r, clock) if err != nil { writeKeyError(w, err) return } // The path must be valid at this point (we've parsed the request successfully). if !hasKeyPrefixAccess(h.sec, r, r.URL.Path[len(keysPrefix):], rr.Recursive) { writeKeyNoAuth(w) return } if !rr.Wait { reportRequestReceived(rr) } resp, err := h.server.Do(ctx, rr) if err != nil { err = trimErrorPrefix(err, etcdserver.StoreKeysPrefix) writeKeyError(w, err) reportRequestFailed(rr, err) return } switch { case resp.Event != nil: if err := writeKeyEvent(w, resp.Event, h.timer); err != nil { // Should never be reached plog.Errorf("error writing event (%v)", err) } reportRequestCompleted(rr, resp, startTime) case resp.Watcher != nil: ctx, cancel := context.WithTimeout(context.Background(), defaultWatchTimeout) defer cancel() handleKeyWatch(ctx, w, resp.Watcher, rr.Stream, h.timer) default: writeKeyError(w, errors.New("received response with no Event/Watcher!")) } }
func (h *keysHandler) ServeHTTP(w http.ResponseWriter, r *http.Request) { if !allowMethod(w, r.Method, "GET", "PUT", "POST", "DELETE") { return } cid := strconv.FormatUint(h.clusterInfo.ID(), 16) w.Header().Set("X-Etcd-Cluster-ID", cid) ctx, cancel := context.WithTimeout(context.Background(), h.timeout) defer cancel() rr, err := parseKeyRequest(r, etcdserver.GenID(), clockwork.NewRealClock()) if err != nil { writeError(w, err) return } resp, err := h.server.Do(ctx, rr) if err != nil { err = trimErrorPrefix(err, etcdserver.StoreKeysPrefix) writeError(w, err) return } switch { case resp.Event != nil: if err := writeKeyEvent(w, resp.Event, h.timer); err != nil { // Should never be reached log.Printf("error writing event: %v", err) } case resp.Watcher != nil: ctx, cancel := context.WithTimeout(context.Background(), defaultWatchTimeout) defer cancel() handleKeyWatch(ctx, w, resp.Watcher, rr.Stream, h.timer) default: writeError(w, errors.New("received response with no Event/Watcher!")) } }
func New(durl string, id uint64, config string) (Discoverer, error) { u, err := url.Parse(durl) if err != nil { return nil, err } token := u.Path u.Path = "" pf, err := proxyFuncFromEnv() if err != nil { return nil, err } c, err := client.NewDiscoveryKeysAPI(&http.Transport{Proxy: pf}, u.String(), client.DefaultRequestTimeout) if err != nil { return nil, err } return &discovery{ cluster: token, id: id, config: config, c: c, url: u, clock: clockwork.NewRealClock(), }, nil }
func newDiscovery(durl, dproxyurl string, id types.ID) (*discovery, error) { u, err := url.Parse(durl) if err != nil { return nil, err } token := u.Path u.Path = "" pf, err := newProxyFunc(dproxyurl) if err != nil { return nil, err } cfg := client.Config{ Transport: &http.Transport{ Proxy: pf, Dial: (&net.Dialer{ Timeout: 30 * time.Second, KeepAlive: 30 * time.Second, }).Dial, TLSHandshakeTimeout: 10 * time.Second, // TODO: add ResponseHeaderTimeout back when watch on discovery service writes header early }, Endpoints: []string{u.String()}, } c, err := client.New(cfg) if err != nil { return nil, err } dc := client.NewKeysAPIWithPrefix(c, "") return &discovery{ cluster: token, c: dc, id: id, url: u, clock: clockwork.NewRealClock(), }, nil }
func newDiscovery(durl, dproxyurl string, id types.ID) (*discovery, error) { u, err := url.Parse(durl) if err != nil { return nil, err } token := u.Path u.Path = "" pf, err := newProxyFunc(dproxyurl) if err != nil { return nil, err } c, err := client.NewHTTPClient(&http.Transport{Proxy: pf}, []string{u.String()}) if err != nil { return nil, err } dc := client.NewDiscoveryKeysAPI(c) return &discovery{ cluster: token, c: dc, id: id, url: u, clock: clockwork.NewRealClock(), }, nil }
// The given namespaces will be created as initial directories in the returned store. func New(namespaces ...string) Store { s := newStore(namespaces...) s.clock = clockwork.NewRealClock() return s }
// NewClientHandler generates a muxed http.Handler with the given parameters to serve etcd client requests. func NewClientHandler(server *etcdserver.EtcdServer, timeout time.Duration) http.Handler { go capabilityLoop(server) sec := auth.NewStore(server, timeout) kh := &keysHandler{ sec: sec, server: server, cluster: server.Cluster(), timer: server, timeout: timeout, } sh := &statsHandler{ stats: server, } mh := &membersHandler{ sec: sec, server: server, cluster: server.Cluster(), timeout: timeout, clock: clockwork.NewRealClock(), } dmh := &deprecatedMachinesHandler{ cluster: server.Cluster(), } sech := &authHandler{ sec: sec, cluster: server.Cluster(), } mux := http.NewServeMux() mux.HandleFunc("/", http.NotFound) mux.Handle(healthPath, healthHandler(server)) mux.HandleFunc(versionPath, versionHandler(server.Cluster(), serveVersion)) mux.Handle(keysPrefix, kh) mux.Handle(keysPrefix+"/", kh) mux.HandleFunc(statsPrefix+"/store", sh.serveStore) mux.HandleFunc(statsPrefix+"/self", sh.serveSelf) mux.HandleFunc(statsPrefix+"/leader", sh.serveLeader) mux.HandleFunc(varsPath, serveVars) mux.HandleFunc(configPath+"/local/log", logHandleFunc) mux.Handle(metricsPath, prometheus.Handler()) mux.Handle(membersPrefix, mh) mux.Handle(membersPrefix+"/", mh) mux.Handle(deprecatedMachinesPrefix, dmh) handleAuth(mux, sech) if server.IsPprofEnabled() { plog.Infof("pprof is enabled under %s", pprofPrefix) mux.HandleFunc(pprofPrefix, pprof.Index) mux.HandleFunc(pprofPrefix+"/profile", pprof.Profile) mux.HandleFunc(pprofPrefix+"/symbol", pprof.Symbol) mux.HandleFunc(pprofPrefix+"/cmdline", pprof.Cmdline) // TODO: currently, we don't create an entry for pprof.Trace, // because go 1.4 doesn't provide it. After support of go 1.4 is dropped, // we should add the entry. mux.Handle(pprofPrefix+"/heap", pprof.Handler("heap")) mux.Handle(pprofPrefix+"/goroutine", pprof.Handler("goroutine")) mux.Handle(pprofPrefix+"/threadcreate", pprof.Handler("threadcreate")) mux.Handle(pprofPrefix+"/block", pprof.Handler("block")) } return requestLogger(mux) }
func (h *keysHandler) ServeHTTP(w http.ResponseWriter, r *http.Request) { if !allowMethod(w, r.Method, "HEAD", "GET", "PUT", "POST", "DELETE") { return } w.Header().Set("X-Etcd-Cluster-ID", h.cluster.ID().String()) clock := clockwork.NewRealClock() startTime := clock.Now() rr, err := parseKeyRequest(r, clock) if err != nil { writeKeyError(w, err) return } if rr.Blocking { plog.Infof("Received request with blocking == true ##############################") } //TODO: return negative response if prev value exists and request is not blocking if rr.PrevValue != "" && !rr.Blocking { swapError := errors.New("Request with defined required previous value has to also be blocking") writeKeyError(w, swapError) reportRequestFailed(rr, swapError) return } var ctx context.Context var cancel context.CancelFunc if rr.Blocking { ctx, cancel = context.WithCancel(context.Background()) } else { ctx, cancel = context.WithTimeout(context.Background(), h.timeout) } defer cancel() // The path must be valid at this point (we've parsed the request successfully). if !hasKeyPrefixAccess(h.sec, r, r.URL.Path[len(keysPrefix):], rr.Recursive) { writeKeyNoAuth(w) return } if !rr.Wait { reportRequestReceived(rr) } resp, err := h.server.Do(ctx, rr) if err != nil { err = trimErrorPrefix(err, etcdserver.StoreKeysPrefix) writeKeyError(w, err) reportRequestFailed(rr, err) return } switch { case resp.Event != nil: if err := writeKeyEvent(w, resp.Event, h.timer); err != nil { // Should never be reached plog.Errorf("error writing event (%v)", err) } reportRequestCompleted(rr, resp, startTime) case resp.Watcher != nil: ctx, cancel := context.WithTimeout(context.Background(), defaultWatchTimeout) defer cancel() handleKeyWatch(ctx, w, resp.Watcher, rr.Stream, h.timer) default: writeKeyError(w, errors.New("received response with no Event/Watcher!")) } }
func New() Store { s := newStore() s.clock = clockwork.NewRealClock() return s }