etcd: move main logic to etcdmain subpackage
parent
38617f5c9b
commit
cf9dd31daa
|
@ -0,0 +1,19 @@
|
||||||
|
/*
|
||||||
|
Copyright 2014 CoreOS, Inc.
|
||||||
|
|
||||||
|
Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
you may not use this file except in compliance with the License.
|
||||||
|
You may obtain a copy of the License at
|
||||||
|
|
||||||
|
http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
|
||||||
|
Unless required by applicable law or agreed to in writing, software
|
||||||
|
distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
See the License for the specific language governing permissions and
|
||||||
|
limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/* Package etcd contains the main entry point for the etcd binary. */
|
||||||
|
|
||||||
|
package etcdmain
|
|
@ -0,0 +1,320 @@
|
||||||
|
/*
|
||||||
|
Copyright 2014 CoreOS, Inc.
|
||||||
|
|
||||||
|
Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
you may not use this file except in compliance with the License.
|
||||||
|
You may obtain a copy of the License at
|
||||||
|
|
||||||
|
http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
|
||||||
|
Unless required by applicable law or agreed to in writing, software
|
||||||
|
distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
See the License for the specific language governing permissions and
|
||||||
|
limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package etcdmain
|
||||||
|
|
||||||
|
import (
|
||||||
|
"flag"
|
||||||
|
"fmt"
|
||||||
|
"log"
|
||||||
|
"net/http"
|
||||||
|
"os"
|
||||||
|
"strings"
|
||||||
|
|
||||||
|
"github.com/coreos/etcd/etcdserver"
|
||||||
|
"github.com/coreos/etcd/etcdserver/etcdhttp"
|
||||||
|
"github.com/coreos/etcd/pkg/cors"
|
||||||
|
"github.com/coreos/etcd/pkg/fileutil"
|
||||||
|
"github.com/coreos/etcd/pkg/flags"
|
||||||
|
"github.com/coreos/etcd/pkg/transport"
|
||||||
|
"github.com/coreos/etcd/pkg/types"
|
||||||
|
"github.com/coreos/etcd/proxy"
|
||||||
|
"github.com/coreos/etcd/version"
|
||||||
|
)
|
||||||
|
|
||||||
|
const (
|
||||||
|
// the owner can make/remove files inside the directory
|
||||||
|
privateDirMode = 0700
|
||||||
|
)
|
||||||
|
|
||||||
|
var (
|
||||||
|
fs = flag.NewFlagSet("etcd", flag.ContinueOnError)
|
||||||
|
name = fs.String("name", "default", "Unique human-readable name for this node")
|
||||||
|
dir = fs.String("data-dir", "", "Path to the data directory")
|
||||||
|
durl = fs.String("discovery", "", "Discovery service used to bootstrap the cluster")
|
||||||
|
snapCount = fs.Uint64("snapshot-count", etcdserver.DefaultSnapCount, "Number of committed transactions to trigger a snapshot")
|
||||||
|
printVersion = fs.Bool("version", false, "Print the version and exit")
|
||||||
|
|
||||||
|
initialCluster = fs.String("initial-cluster", "default=http://localhost:2380,default=http://localhost:7001", "Initial cluster configuration for bootstrapping")
|
||||||
|
initialClusterName = fs.String("initial-cluster-name", "etcd", "Initial name for the etcd cluster during bootstrap")
|
||||||
|
clusterState = new(etcdserver.ClusterState)
|
||||||
|
|
||||||
|
corsInfo = &cors.CORSInfo{}
|
||||||
|
proxyFlag = new(flags.Proxy)
|
||||||
|
|
||||||
|
clientTLSInfo = transport.TLSInfo{}
|
||||||
|
peerTLSInfo = transport.TLSInfo{}
|
||||||
|
|
||||||
|
ignored = []string{
|
||||||
|
"cluster-active-size",
|
||||||
|
"cluster-remove-delay",
|
||||||
|
"cluster-sync-interval",
|
||||||
|
"config",
|
||||||
|
"force",
|
||||||
|
"max-result-buffer",
|
||||||
|
"max-retry-attempts",
|
||||||
|
"peer-heartbeat-interval",
|
||||||
|
"peer-election-timeout",
|
||||||
|
"retry-interval",
|
||||||
|
"snapshot",
|
||||||
|
"v",
|
||||||
|
"vv",
|
||||||
|
}
|
||||||
|
)
|
||||||
|
|
||||||
|
func init() {
|
||||||
|
fs.Var(clusterState, "initial-cluster-state", "Initial cluster configuration for bootstrapping")
|
||||||
|
if err := clusterState.Set(etcdserver.ClusterStateValueNew); err != nil {
|
||||||
|
// Should never happen.
|
||||||
|
log.Panicf("unexpected error setting up clusterState: %v", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
fs.Var(flags.NewURLsValue("http://localhost:2380,http://localhost:7001"), "initial-advertise-peer-urls", "List of this member's peer URLs to advertise to the rest of the cluster")
|
||||||
|
fs.Var(flags.NewURLsValue("http://localhost:2379,http://localhost:4001"), "advertise-client-urls", "List of this member's client URLs to advertise to the rest of the cluster")
|
||||||
|
fs.Var(flags.NewURLsValue("http://localhost:2380,http://localhost:7001"), "listen-peer-urls", "List of URLs to listen on for peer traffic")
|
||||||
|
fs.Var(flags.NewURLsValue("http://localhost:2379,http://localhost:4001"), "listen-client-urls", "List of URLs to listen on for client traffic")
|
||||||
|
|
||||||
|
fs.Var(corsInfo, "cors", "Comma-separated white list of origins for CORS (cross-origin resource sharing).")
|
||||||
|
|
||||||
|
fs.Var(proxyFlag, "proxy", fmt.Sprintf("Valid values include %s", strings.Join(flags.ProxyValues, ", ")))
|
||||||
|
if err := proxyFlag.Set(flags.ProxyValueOff); err != nil {
|
||||||
|
// Should never happen.
|
||||||
|
log.Panicf("unexpected error setting up proxyFlag: %v", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
fs.StringVar(&clientTLSInfo.CAFile, "ca-file", "", "Path to the client server TLS CA file.")
|
||||||
|
fs.StringVar(&clientTLSInfo.CertFile, "cert-file", "", "Path to the client server TLS cert file.")
|
||||||
|
fs.StringVar(&clientTLSInfo.KeyFile, "key-file", "", "Path to the client server TLS key file.")
|
||||||
|
|
||||||
|
fs.StringVar(&peerTLSInfo.CAFile, "peer-ca-file", "", "Path to the peer server TLS CA file.")
|
||||||
|
fs.StringVar(&peerTLSInfo.CertFile, "peer-cert-file", "", "Path to the peer server TLS cert file.")
|
||||||
|
fs.StringVar(&peerTLSInfo.KeyFile, "peer-key-file", "", "Path to the peer server TLS key file.")
|
||||||
|
|
||||||
|
// backwards-compatibility with v0.4.6
|
||||||
|
fs.Var(&flags.IPAddressPort{}, "addr", "DEPRECATED: Use -advertise-client-urls instead.")
|
||||||
|
fs.Var(&flags.IPAddressPort{}, "bind-addr", "DEPRECATED: Use -listen-client-urls instead.")
|
||||||
|
fs.Var(&flags.IPAddressPort{}, "peer-addr", "DEPRECATED: Use -initial-advertise-peer-urls instead.")
|
||||||
|
fs.Var(&flags.IPAddressPort{}, "peer-bind-addr", "DEPRECATED: Use -listen-peer-urls instead.")
|
||||||
|
|
||||||
|
for _, f := range ignored {
|
||||||
|
fs.Var(&flags.IgnoredFlag{Name: f}, f, "")
|
||||||
|
}
|
||||||
|
|
||||||
|
fs.Var(&flags.DeprecatedFlag{Name: "peers"}, "peers", "DEPRECATED: Use -initial-cluster instead")
|
||||||
|
fs.Var(&flags.DeprecatedFlag{Name: "peers-file"}, "peers-file", "DEPRECATED: Use -initial-cluster instead")
|
||||||
|
}
|
||||||
|
|
||||||
|
func Main() {
|
||||||
|
fs.Usage = flags.UsageWithIgnoredFlagsFunc(fs, ignored)
|
||||||
|
err := fs.Parse(os.Args[1:])
|
||||||
|
switch err {
|
||||||
|
case nil:
|
||||||
|
case flag.ErrHelp:
|
||||||
|
os.Exit(0)
|
||||||
|
default:
|
||||||
|
os.Exit(2)
|
||||||
|
}
|
||||||
|
|
||||||
|
if *printVersion {
|
||||||
|
fmt.Println("etcd version", version.Version)
|
||||||
|
os.Exit(0)
|
||||||
|
}
|
||||||
|
|
||||||
|
flags.SetFlagsFromEnv(fs)
|
||||||
|
|
||||||
|
if string(*proxyFlag) == flags.ProxyValueOff {
|
||||||
|
startEtcd()
|
||||||
|
} else {
|
||||||
|
startProxy()
|
||||||
|
}
|
||||||
|
|
||||||
|
// Block indefinitely
|
||||||
|
<-make(chan struct{})
|
||||||
|
}
|
||||||
|
|
||||||
|
// startEtcd launches the etcd server and HTTP handlers for client/server communication.
|
||||||
|
func startEtcd() {
|
||||||
|
cls, err := setupCluster()
|
||||||
|
if err != nil {
|
||||||
|
log.Fatalf("etcd: error setting up initial cluster: %v", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
if *dir == "" {
|
||||||
|
*dir = fmt.Sprintf("%v.etcd", *name)
|
||||||
|
log.Printf("etcd: no data-dir provided, using default data-dir ./%s", *dir)
|
||||||
|
}
|
||||||
|
if err := os.MkdirAll(*dir, privateDirMode); err != nil {
|
||||||
|
log.Fatalf("etcd: cannot create data directory: %v", err)
|
||||||
|
}
|
||||||
|
if err := fileutil.IsDirWriteable(*dir); err != nil {
|
||||||
|
log.Fatalf("etcd: cannot write to data directory: %v", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
pt, err := transport.NewTransport(peerTLSInfo)
|
||||||
|
if err != nil {
|
||||||
|
log.Fatal(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
acurls, err := flags.URLsFromFlags(fs, "advertise-client-urls", "addr", clientTLSInfo)
|
||||||
|
if err != nil {
|
||||||
|
log.Fatal(err.Error())
|
||||||
|
}
|
||||||
|
cfg := &etcdserver.ServerConfig{
|
||||||
|
Name: *name,
|
||||||
|
ClientURLs: acurls,
|
||||||
|
DataDir: *dir,
|
||||||
|
SnapCount: *snapCount,
|
||||||
|
Cluster: cls,
|
||||||
|
DiscoveryURL: *durl,
|
||||||
|
ClusterState: *clusterState,
|
||||||
|
Transport: pt,
|
||||||
|
}
|
||||||
|
s := etcdserver.NewServer(cfg)
|
||||||
|
s.Start()
|
||||||
|
|
||||||
|
ch := &cors.CORSHandler{
|
||||||
|
Handler: etcdhttp.NewClientHandler(s),
|
||||||
|
Info: corsInfo,
|
||||||
|
}
|
||||||
|
ph := etcdhttp.NewPeerHandler(s)
|
||||||
|
|
||||||
|
lpurls, err := flags.URLsFromFlags(fs, "listen-peer-urls", "peer-bind-addr", peerTLSInfo)
|
||||||
|
if err != nil {
|
||||||
|
log.Fatal(err.Error())
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, u := range lpurls {
|
||||||
|
l, err := transport.NewListener(u.Host, peerTLSInfo)
|
||||||
|
if err != nil {
|
||||||
|
log.Fatal(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Start the peer server in a goroutine
|
||||||
|
urlStr := u.String()
|
||||||
|
go func() {
|
||||||
|
log.Print("etcd: listening for peers on ", urlStr)
|
||||||
|
log.Fatal(http.Serve(l, ph))
|
||||||
|
}()
|
||||||
|
}
|
||||||
|
|
||||||
|
lcurls, err := flags.URLsFromFlags(fs, "listen-client-urls", "bind-addr", clientTLSInfo)
|
||||||
|
if err != nil {
|
||||||
|
log.Fatal(err.Error())
|
||||||
|
}
|
||||||
|
|
||||||
|
// Start a client server goroutine for each listen address
|
||||||
|
for _, u := range lcurls {
|
||||||
|
l, err := transport.NewListener(u.Host, clientTLSInfo)
|
||||||
|
if err != nil {
|
||||||
|
log.Fatal(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
urlStr := u.String()
|
||||||
|
go func() {
|
||||||
|
log.Print("etcd: listening for client requests on ", urlStr)
|
||||||
|
log.Fatal(http.Serve(l, ch))
|
||||||
|
}()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// startProxy launches an HTTP proxy for client communication which proxies to other etcd nodes.
|
||||||
|
func startProxy() {
|
||||||
|
cls, err := setupCluster()
|
||||||
|
if err != nil {
|
||||||
|
log.Fatalf("etcd: error setting up initial cluster: %v", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
pt, err := transport.NewTransport(clientTLSInfo)
|
||||||
|
if err != nil {
|
||||||
|
log.Fatal(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
// TODO(jonboulle): update peerURLs dynamically (i.e. when updating
|
||||||
|
// clientURLs) instead of just using the initial fixed list here
|
||||||
|
peerURLs := cls.PeerURLs()
|
||||||
|
uf := func() []string {
|
||||||
|
cls, err := etcdserver.GetClusterFromPeers(peerURLs)
|
||||||
|
if err != nil {
|
||||||
|
log.Printf("etcd: %v", err)
|
||||||
|
return []string{}
|
||||||
|
}
|
||||||
|
return cls.ClientURLs()
|
||||||
|
}
|
||||||
|
ph := proxy.NewHandler(pt, uf)
|
||||||
|
ph = &cors.CORSHandler{
|
||||||
|
Handler: ph,
|
||||||
|
Info: corsInfo,
|
||||||
|
}
|
||||||
|
|
||||||
|
if string(*proxyFlag) == flags.ProxyValueReadonly {
|
||||||
|
ph = proxy.NewReadonlyHandler(ph)
|
||||||
|
}
|
||||||
|
|
||||||
|
lcurls, err := flags.URLsFromFlags(fs, "listen-client-urls", "bind-addr", clientTLSInfo)
|
||||||
|
if err != nil {
|
||||||
|
log.Fatal(err.Error())
|
||||||
|
}
|
||||||
|
// Start a proxy server goroutine for each listen address
|
||||||
|
for _, u := range lcurls {
|
||||||
|
l, err := transport.NewListener(u.Host, clientTLSInfo)
|
||||||
|
if err != nil {
|
||||||
|
log.Fatal(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
host := u.Host
|
||||||
|
go func() {
|
||||||
|
log.Print("etcd: proxy listening for client requests on ", host)
|
||||||
|
log.Fatal(http.Serve(l, ph))
|
||||||
|
}()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// setupCluster sets up the cluster definition for bootstrap or discovery.
|
||||||
|
func setupCluster() (*etcdserver.Cluster, error) {
|
||||||
|
set := make(map[string]bool)
|
||||||
|
fs.Visit(func(f *flag.Flag) {
|
||||||
|
set[f.Name] = true
|
||||||
|
})
|
||||||
|
if set["discovery"] && set["initial-cluster"] {
|
||||||
|
return nil, fmt.Errorf("both discovery and bootstrap-config are set")
|
||||||
|
}
|
||||||
|
apurls, err := flags.URLsFromFlags(fs, "initial-advertise-peer-urls", "addr", peerTLSInfo)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
var cls *etcdserver.Cluster
|
||||||
|
switch {
|
||||||
|
case set["discovery"]:
|
||||||
|
clusterStr := genClusterString(*name, apurls)
|
||||||
|
cls, err = etcdserver.NewClusterFromString(*durl, clusterStr)
|
||||||
|
case set["initial-cluster"]:
|
||||||
|
fallthrough
|
||||||
|
default:
|
||||||
|
// We're statically configured, and cluster has appropriately been set.
|
||||||
|
// Try to configure by indexing the static cluster by name.
|
||||||
|
cls, err = etcdserver.NewClusterFromString(*initialClusterName, *initialCluster)
|
||||||
|
}
|
||||||
|
return cls, err
|
||||||
|
}
|
||||||
|
|
||||||
|
func genClusterString(name string, urls types.URLs) string {
|
||||||
|
addrs := make([]string, 0)
|
||||||
|
for _, u := range urls {
|
||||||
|
addrs = append(addrs, fmt.Sprintf("%v=%v", name, u.String()))
|
||||||
|
}
|
||||||
|
return strings.Join(addrs, ",")
|
||||||
|
}
|
|
@ -14,7 +14,7 @@
|
||||||
limitations under the License.
|
limitations under the License.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
package main
|
package etcdmain
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"testing"
|
"testing"
|
308
main.go
308
main.go
|
@ -14,307 +14,21 @@
|
||||||
limitations under the License.
|
limitations under the License.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
// Package main is a simple wrapper of the real etcd entrypoint package
|
||||||
|
// (located at github.com/coreos/etcd/etcdmain) to ensure that etcd is still
|
||||||
|
// "go getable"; e.g. `go get github.com/coreos/etcd` works as expected and
|
||||||
|
// builds a binary in $GOBIN/etcd
|
||||||
|
//
|
||||||
|
// This package should NOT be extended or modified in any way; to modify the
|
||||||
|
// etcd binary, work in the `github.com/coreos/etcd/etcdmain` package.
|
||||||
|
//
|
||||||
|
|
||||||
package main
|
package main
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"flag"
|
"github.com/coreos/etcd/etcdmain"
|
||||||
"fmt"
|
|
||||||
"log"
|
|
||||||
"net/http"
|
|
||||||
"os"
|
|
||||||
"strings"
|
|
||||||
|
|
||||||
"github.com/coreos/etcd/etcdserver"
|
|
||||||
"github.com/coreos/etcd/etcdserver/etcdhttp"
|
|
||||||
"github.com/coreos/etcd/pkg/cors"
|
|
||||||
"github.com/coreos/etcd/pkg/fileutil"
|
|
||||||
"github.com/coreos/etcd/pkg/flags"
|
|
||||||
"github.com/coreos/etcd/pkg/transport"
|
|
||||||
"github.com/coreos/etcd/pkg/types"
|
|
||||||
"github.com/coreos/etcd/proxy"
|
|
||||||
"github.com/coreos/etcd/version"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
const (
|
|
||||||
// the owner can make/remove files inside the directory
|
|
||||||
privateDirMode = 0700
|
|
||||||
)
|
|
||||||
|
|
||||||
var (
|
|
||||||
fs = flag.NewFlagSet("etcd", flag.ContinueOnError)
|
|
||||||
name = fs.String("name", "default", "Unique human-readable name for this node")
|
|
||||||
dir = fs.String("data-dir", "", "Path to the data directory")
|
|
||||||
durl = fs.String("discovery", "", "Discovery service used to bootstrap the cluster")
|
|
||||||
snapCount = fs.Uint64("snapshot-count", etcdserver.DefaultSnapCount, "Number of committed transactions to trigger a snapshot")
|
|
||||||
printVersion = fs.Bool("version", false, "Print the version and exit")
|
|
||||||
|
|
||||||
initialCluster = fs.String("initial-cluster", "default=http://localhost:2380,default=http://localhost:7001", "Initial cluster configuration for bootstrapping")
|
|
||||||
initialClusterName = fs.String("initial-cluster-name", "etcd", "Initial name for the etcd cluster during bootstrap")
|
|
||||||
clusterState = new(etcdserver.ClusterState)
|
|
||||||
|
|
||||||
corsInfo = &cors.CORSInfo{}
|
|
||||||
proxyFlag = new(flags.Proxy)
|
|
||||||
|
|
||||||
clientTLSInfo = transport.TLSInfo{}
|
|
||||||
peerTLSInfo = transport.TLSInfo{}
|
|
||||||
|
|
||||||
ignored = []string{
|
|
||||||
"cluster-active-size",
|
|
||||||
"cluster-remove-delay",
|
|
||||||
"cluster-sync-interval",
|
|
||||||
"config",
|
|
||||||
"force",
|
|
||||||
"max-result-buffer",
|
|
||||||
"max-retry-attempts",
|
|
||||||
"peer-heartbeat-interval",
|
|
||||||
"peer-election-timeout",
|
|
||||||
"retry-interval",
|
|
||||||
"snapshot",
|
|
||||||
"v",
|
|
||||||
"vv",
|
|
||||||
}
|
|
||||||
)
|
|
||||||
|
|
||||||
func init() {
|
|
||||||
fs.Var(clusterState, "initial-cluster-state", "Initial cluster configuration for bootstrapping")
|
|
||||||
if err := clusterState.Set(etcdserver.ClusterStateValueNew); err != nil {
|
|
||||||
// Should never happen.
|
|
||||||
log.Panicf("unexpected error setting up clusterState: %v", err)
|
|
||||||
}
|
|
||||||
|
|
||||||
fs.Var(flags.NewURLsValue("http://localhost:2380,http://localhost:7001"), "initial-advertise-peer-urls", "List of this member's peer URLs to advertise to the rest of the cluster")
|
|
||||||
fs.Var(flags.NewURLsValue("http://localhost:2379,http://localhost:4001"), "advertise-client-urls", "List of this member's client URLs to advertise to the rest of the cluster")
|
|
||||||
fs.Var(flags.NewURLsValue("http://localhost:2380,http://localhost:7001"), "listen-peer-urls", "List of URLs to listen on for peer traffic")
|
|
||||||
fs.Var(flags.NewURLsValue("http://localhost:2379,http://localhost:4001"), "listen-client-urls", "List of URLs to listen on for client traffic")
|
|
||||||
|
|
||||||
fs.Var(corsInfo, "cors", "Comma-separated white list of origins for CORS (cross-origin resource sharing).")
|
|
||||||
|
|
||||||
fs.Var(proxyFlag, "proxy", fmt.Sprintf("Valid values include %s", strings.Join(flags.ProxyValues, ", ")))
|
|
||||||
if err := proxyFlag.Set(flags.ProxyValueOff); err != nil {
|
|
||||||
// Should never happen.
|
|
||||||
log.Panicf("unexpected error setting up proxyFlag: %v", err)
|
|
||||||
}
|
|
||||||
|
|
||||||
fs.StringVar(&clientTLSInfo.CAFile, "ca-file", "", "Path to the client server TLS CA file.")
|
|
||||||
fs.StringVar(&clientTLSInfo.CertFile, "cert-file", "", "Path to the client server TLS cert file.")
|
|
||||||
fs.StringVar(&clientTLSInfo.KeyFile, "key-file", "", "Path to the client server TLS key file.")
|
|
||||||
|
|
||||||
fs.StringVar(&peerTLSInfo.CAFile, "peer-ca-file", "", "Path to the peer server TLS CA file.")
|
|
||||||
fs.StringVar(&peerTLSInfo.CertFile, "peer-cert-file", "", "Path to the peer server TLS cert file.")
|
|
||||||
fs.StringVar(&peerTLSInfo.KeyFile, "peer-key-file", "", "Path to the peer server TLS key file.")
|
|
||||||
|
|
||||||
// backwards-compatibility with v0.4.6
|
|
||||||
fs.Var(&flags.IPAddressPort{}, "addr", "DEPRECATED: Use -advertise-client-urls instead.")
|
|
||||||
fs.Var(&flags.IPAddressPort{}, "bind-addr", "DEPRECATED: Use -listen-client-urls instead.")
|
|
||||||
fs.Var(&flags.IPAddressPort{}, "peer-addr", "DEPRECATED: Use -initial-advertise-peer-urls instead.")
|
|
||||||
fs.Var(&flags.IPAddressPort{}, "peer-bind-addr", "DEPRECATED: Use -listen-peer-urls instead.")
|
|
||||||
|
|
||||||
for _, f := range ignored {
|
|
||||||
fs.Var(&flags.IgnoredFlag{Name: f}, f, "")
|
|
||||||
}
|
|
||||||
|
|
||||||
fs.Var(&flags.DeprecatedFlag{Name: "peers"}, "peers", "DEPRECATED: Use -initial-cluster instead")
|
|
||||||
fs.Var(&flags.DeprecatedFlag{Name: "peers-file"}, "peers-file", "DEPRECATED: Use -initial-cluster instead")
|
|
||||||
}
|
|
||||||
|
|
||||||
func main() {
|
func main() {
|
||||||
fs.Usage = flags.UsageWithIgnoredFlagsFunc(fs, ignored)
|
etcdmain.Main()
|
||||||
err := fs.Parse(os.Args[1:])
|
|
||||||
switch err {
|
|
||||||
case nil:
|
|
||||||
case flag.ErrHelp:
|
|
||||||
os.Exit(0)
|
|
||||||
default:
|
|
||||||
os.Exit(2)
|
|
||||||
}
|
|
||||||
|
|
||||||
if *printVersion {
|
|
||||||
fmt.Println("etcd version", version.Version)
|
|
||||||
os.Exit(0)
|
|
||||||
}
|
|
||||||
|
|
||||||
flags.SetFlagsFromEnv(fs)
|
|
||||||
|
|
||||||
if string(*proxyFlag) == flags.ProxyValueOff {
|
|
||||||
startEtcd()
|
|
||||||
} else {
|
|
||||||
startProxy()
|
|
||||||
}
|
|
||||||
|
|
||||||
// Block indefinitely
|
|
||||||
<-make(chan struct{})
|
|
||||||
}
|
|
||||||
|
|
||||||
// startEtcd launches the etcd server and HTTP handlers for client/server communication.
|
|
||||||
func startEtcd() {
|
|
||||||
cls, err := setupCluster()
|
|
||||||
if err != nil {
|
|
||||||
log.Fatalf("etcd: error setting up initial cluster: %v", err)
|
|
||||||
}
|
|
||||||
|
|
||||||
if *dir == "" {
|
|
||||||
*dir = fmt.Sprintf("%v.etcd", *name)
|
|
||||||
log.Printf("etcd: no data-dir provided, using default data-dir ./%s", *dir)
|
|
||||||
}
|
|
||||||
if err := os.MkdirAll(*dir, privateDirMode); err != nil {
|
|
||||||
log.Fatalf("etcd: cannot create data directory: %v", err)
|
|
||||||
}
|
|
||||||
if err := fileutil.IsDirWriteable(*dir); err != nil {
|
|
||||||
log.Fatalf("etcd: cannot write to data directory: %v", err)
|
|
||||||
}
|
|
||||||
|
|
||||||
pt, err := transport.NewTransport(peerTLSInfo)
|
|
||||||
if err != nil {
|
|
||||||
log.Fatal(err)
|
|
||||||
}
|
|
||||||
|
|
||||||
acurls, err := flags.URLsFromFlags(fs, "advertise-client-urls", "addr", clientTLSInfo)
|
|
||||||
if err != nil {
|
|
||||||
log.Fatal(err.Error())
|
|
||||||
}
|
|
||||||
cfg := &etcdserver.ServerConfig{
|
|
||||||
Name: *name,
|
|
||||||
ClientURLs: acurls,
|
|
||||||
DataDir: *dir,
|
|
||||||
SnapCount: *snapCount,
|
|
||||||
Cluster: cls,
|
|
||||||
DiscoveryURL: *durl,
|
|
||||||
ClusterState: *clusterState,
|
|
||||||
Transport: pt,
|
|
||||||
}
|
|
||||||
s := etcdserver.NewServer(cfg)
|
|
||||||
s.Start()
|
|
||||||
|
|
||||||
ch := &cors.CORSHandler{
|
|
||||||
Handler: etcdhttp.NewClientHandler(s),
|
|
||||||
Info: corsInfo,
|
|
||||||
}
|
|
||||||
ph := etcdhttp.NewPeerHandler(s)
|
|
||||||
|
|
||||||
lpurls, err := flags.URLsFromFlags(fs, "listen-peer-urls", "peer-bind-addr", peerTLSInfo)
|
|
||||||
if err != nil {
|
|
||||||
log.Fatal(err.Error())
|
|
||||||
}
|
|
||||||
|
|
||||||
for _, u := range lpurls {
|
|
||||||
l, err := transport.NewListener(u.Host, peerTLSInfo)
|
|
||||||
if err != nil {
|
|
||||||
log.Fatal(err)
|
|
||||||
}
|
|
||||||
|
|
||||||
// Start the peer server in a goroutine
|
|
||||||
urlStr := u.String()
|
|
||||||
go func() {
|
|
||||||
log.Print("etcd: listening for peers on ", urlStr)
|
|
||||||
log.Fatal(http.Serve(l, ph))
|
|
||||||
}()
|
|
||||||
}
|
|
||||||
|
|
||||||
lcurls, err := flags.URLsFromFlags(fs, "listen-client-urls", "bind-addr", clientTLSInfo)
|
|
||||||
if err != nil {
|
|
||||||
log.Fatal(err.Error())
|
|
||||||
}
|
|
||||||
|
|
||||||
// Start a client server goroutine for each listen address
|
|
||||||
for _, u := range lcurls {
|
|
||||||
l, err := transport.NewListener(u.Host, clientTLSInfo)
|
|
||||||
if err != nil {
|
|
||||||
log.Fatal(err)
|
|
||||||
}
|
|
||||||
|
|
||||||
urlStr := u.String()
|
|
||||||
go func() {
|
|
||||||
log.Print("etcd: listening for client requests on ", urlStr)
|
|
||||||
log.Fatal(http.Serve(l, ch))
|
|
||||||
}()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// startProxy launches an HTTP proxy for client communication which proxies to other etcd nodes.
|
|
||||||
func startProxy() {
|
|
||||||
cls, err := setupCluster()
|
|
||||||
if err != nil {
|
|
||||||
log.Fatalf("etcd: error setting up initial cluster: %v", err)
|
|
||||||
}
|
|
||||||
|
|
||||||
pt, err := transport.NewTransport(clientTLSInfo)
|
|
||||||
if err != nil {
|
|
||||||
log.Fatal(err)
|
|
||||||
}
|
|
||||||
|
|
||||||
// TODO(jonboulle): update peerURLs dynamically (i.e. when updating
|
|
||||||
// clientURLs) instead of just using the initial fixed list here
|
|
||||||
peerURLs := cls.PeerURLs()
|
|
||||||
uf := func() []string {
|
|
||||||
cls, err := etcdserver.GetClusterFromPeers(peerURLs)
|
|
||||||
if err != nil {
|
|
||||||
log.Printf("etcd: %v", err)
|
|
||||||
return []string{}
|
|
||||||
}
|
|
||||||
return cls.ClientURLs()
|
|
||||||
}
|
|
||||||
ph := proxy.NewHandler(pt, uf)
|
|
||||||
ph = &cors.CORSHandler{
|
|
||||||
Handler: ph,
|
|
||||||
Info: corsInfo,
|
|
||||||
}
|
|
||||||
|
|
||||||
if string(*proxyFlag) == flags.ProxyValueReadonly {
|
|
||||||
ph = proxy.NewReadonlyHandler(ph)
|
|
||||||
}
|
|
||||||
|
|
||||||
lcurls, err := flags.URLsFromFlags(fs, "listen-client-urls", "bind-addr", clientTLSInfo)
|
|
||||||
if err != nil {
|
|
||||||
log.Fatal(err.Error())
|
|
||||||
}
|
|
||||||
// Start a proxy server goroutine for each listen address
|
|
||||||
for _, u := range lcurls {
|
|
||||||
l, err := transport.NewListener(u.Host, clientTLSInfo)
|
|
||||||
if err != nil {
|
|
||||||
log.Fatal(err)
|
|
||||||
}
|
|
||||||
|
|
||||||
host := u.Host
|
|
||||||
go func() {
|
|
||||||
log.Print("etcd: proxy listening for client requests on ", host)
|
|
||||||
log.Fatal(http.Serve(l, ph))
|
|
||||||
}()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// setupCluster sets up the cluster definition for bootstrap or discovery.
|
|
||||||
func setupCluster() (*etcdserver.Cluster, error) {
|
|
||||||
set := make(map[string]bool)
|
|
||||||
fs.Visit(func(f *flag.Flag) {
|
|
||||||
set[f.Name] = true
|
|
||||||
})
|
|
||||||
if set["discovery"] && set["initial-cluster"] {
|
|
||||||
return nil, fmt.Errorf("both discovery and bootstrap-config are set")
|
|
||||||
}
|
|
||||||
apurls, err := flags.URLsFromFlags(fs, "initial-advertise-peer-urls", "addr", peerTLSInfo)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
|
|
||||||
var cls *etcdserver.Cluster
|
|
||||||
switch {
|
|
||||||
case set["discovery"]:
|
|
||||||
clusterStr := genClusterString(*name, apurls)
|
|
||||||
cls, err = etcdserver.NewClusterFromString(*durl, clusterStr)
|
|
||||||
case set["initial-cluster"]:
|
|
||||||
fallthrough
|
|
||||||
default:
|
|
||||||
// We're statically configured, and cluster has appropriately been set.
|
|
||||||
// Try to configure by indexing the static cluster by name.
|
|
||||||
cls, err = etcdserver.NewClusterFromString(*initialClusterName, *initialCluster)
|
|
||||||
}
|
|
||||||
return cls, err
|
|
||||||
}
|
|
||||||
|
|
||||||
func genClusterString(name string, urls types.URLs) string {
|
|
||||||
addrs := make([]string, 0)
|
|
||||||
for _, u := range urls {
|
|
||||||
addrs = append(addrs, fmt.Sprintf("%v=%v", name, u.String()))
|
|
||||||
}
|
|
||||||
return strings.Join(addrs, ",")
|
|
||||||
}
|
}
|
||||||
|
|
5
test
5
test
|
@ -15,13 +15,12 @@ COVER=${COVER:-"-cover"}
|
||||||
source ./build
|
source ./build
|
||||||
|
|
||||||
# Hack: gofmt ./ will recursively check the .git directory. So use *.go for gofmt.
|
# Hack: gofmt ./ will recursively check the .git directory. So use *.go for gofmt.
|
||||||
TESTABLE_AND_FORMATTABLE="client discovery etcdctl/command etcdserver etcdserver/etcdhttp etcdserver/etcdhttp/httptypes etcdserver/etcdserverpb integration pkg/flags pkg/strutil pkg/transport proxy raft snap store wait wal"
|
TESTABLE_AND_FORMATTABLE="client discovery etcdctl/command etcdmain etcdserver etcdserver/etcdhttp etcdserver/etcdhttp/httptypes etcdserver/etcdserverpb integration pkg/flags pkg/strutil pkg/transport proxy raft snap store wait wal"
|
||||||
TESTABLE="$TESTABLE_AND_FORMATTABLE ./"
|
|
||||||
FORMATTABLE="$TESTABLE_AND_FORMATTABLE *.go etcdctl/"
|
FORMATTABLE="$TESTABLE_AND_FORMATTABLE *.go etcdctl/"
|
||||||
|
|
||||||
# user has not provided PKG override
|
# user has not provided PKG override
|
||||||
if [ -z "$PKG" ]; then
|
if [ -z "$PKG" ]; then
|
||||||
TEST=$TESTABLE
|
TEST=$TESTABLE_AND_FORMATTABLE
|
||||||
FMT=$FORMATTABLE
|
FMT=$FORMATTABLE
|
||||||
|
|
||||||
# user has provided PKG override
|
# user has provided PKG override
|
||||||
|
|
Loading…
Reference in New Issue