diff --git a/Dockerfile b/Dockerfile index 7f554fd9f..e025979db 100644 --- a/Dockerfile +++ b/Dockerfile @@ -7,4 +7,4 @@ RUN apt-get install -y golang ADD . /opt/etcd RUN cd /opt/etcd && ./build EXPOSE 4001 7001 -ENTRYPOINT ["/opt/etcd/etcd", "-c", "0.0.0.0:4001", "-s", "0.0.0.0:7001"] +ENTRYPOINT ["/opt/etcd/etcd", "-addr", "0.0.0.0:4001", "-bind-addr", "0.0.0.0:7001"] diff --git a/Documentation/errorcode.md b/Documentation/errorcode.md index 3a0443f8b..d9dea44ad 100644 --- a/Documentation/errorcode.md +++ b/Documentation/errorcode.md @@ -17,7 +17,7 @@ Error code corresponding strerror EcodeKeyNotFound = 100 EcodeTestFailed = 101 EcodeNotFile = 102 - EcodeNoMoreMachine = 103 + EcodeNoMorePeer = 103 EcodeNotDir = 104 EcodeNodeExist = 105 EcodeKeyIsPreserved = 106 @@ -38,7 +38,7 @@ Error code corresponding strerror errors[100] = "Key Not Found" errors[101] = "Test Failed" //test and set errors[102] = "Not A File" - errors[103] = "Reached the max number of machines in the cluster" + errors[103] = "Reached the max number of peers in the cluster" errors[104] = "Not A Directory" errors[105] = "Already exists" // create errors[106] = "The prefix of given key is a keyword in etcd" diff --git a/Documentation/external-documentation.md b/Documentation/external-documentation.md index a7d957aef..e48140ce8 100644 --- a/Documentation/external-documentation.md +++ b/Documentation/external-documentation.md @@ -14,34 +14,34 @@ configuration files. ### Required -* `-n` - The node name. Defaults to `default-name`. +* `-name` - The node name. Defaults to the hostname. ### Optional -* `-c` - The advertised public hostname:port for client communication. Defaults to `127.0.0.1:4001`. -* `-cl` - The listening hostname for client communication. Defaults to advertised ip. -* `-C` - A comma separated list of machines in the cluster (i.e `"203.0.113.101:7001,203.0.113.102:7001"`). -* `-CF` - The file path containing a comma separated list of machines in the cluster. -* `-clientCAFile` - The path of the client CAFile. Enables client cert authentication when present. -* `-clientCert` - The cert file of the client. -* `-clientKey` - The key file of the client. -* `-configfile` - The path of the etcd config file. Defaults to `/etc/etcd/etcd.conf`. -* `-cors` - A comma separated white list of origins for cross-origin resource sharing. +* `-addr` - The advertised public hostname:port for client communication. Defaults to `127.0.0.1:4001`. +* `-bind-addr` - The listening hostname for client communication. Defaults to advertised ip. +* `-peers` - A comma separated list of peers in the cluster (i.e `"203.0.113.101:7001,203.0.113.102:7001"`). +* `-peers-file` - The file path containing a comma separated list of peers in the cluster. +* `-ca-file` - The path of the client CAFile. Enables client cert authentication when present. +* `-cert-file` - The cert file of the client. +* `-key-file` - The key file of the client. +* `-config` - The path of the etcd config file. Defaults to `/etc/etcd/etcd.conf`. +* `-cors-origins` - A comma separated white list of origins for cross-origin resource sharing. * `-cpuprofile` - The path to a file to output cpu profile data. Enables cpu profiling when present. -* `-d` - The directory to store log and snapshot. Defaults to the current working directory. -* `-m` - The max size of result buffer. Defaults to `1024`. -* `-maxsize` - The max size of the cluster. Defaults to `9`. -* `-r` - The max retry attempts when trying to join a cluster. Defaults to `3`. -* `-s` - The advertised public hostname:port for server communication. Defaults to `127.0.0.1:7001`. -* `-sl` - The listening hostname for server communication. Defaults to advertised ip. -* `-serverCAFile` - The path of the CAFile. Enables client/peer cert authentication when present. -* `-serverCert` - The cert file of the server. -* `-serverKey` - The key file of the server. +* `-data-dir` - The directory to store log and snapshot. Defaults to the current working directory. +* `-max-result-buffer` - The max size of result buffer. Defaults to `1024`. +* `-max-cluster-size` - The max size of the cluster. Defaults to `9`. +* `-max-retry-attempts` - The max retry attempts when trying to join a cluster. Defaults to `3`. +* `-peer-addr` - The advertised public hostname:port for server communication. Defaults to `127.0.0.1:7001`. +* `-peer-bind-addr` - The listening hostname for server communication. Defaults to advertised ip. +* `-peer-ca-file` - The path of the CAFile. Enables client/peer cert authentication when present. +* `-peer-cert-file` - The cert file of the server. +* `-peer-key-file` - The key file of the server. * `-snapshot` - Open or close snapshot. Defaults to `false`. * `-v` - Enable verbose logging. Defaults to `false`. * `-vv` - Enable very verbose logging. Defaults to `false`. * `-version` - Print the version and exit. -* `-w` - The hostname:port of web interface. +* `-web-url` - The hostname:port of web interface. ## Configuration File @@ -49,16 +49,16 @@ The etcd configuration file is written in [TOML](https://github.com/mojombo/toml and read from `/etc/etcd/etcd.conf` by default. ```TOML -advertised_url = "127.0.0.1:4001" +addr = "127.0.0.1:4001" +bind_addr = "127.0.0.1:4001" ca_file = "" cert_file = "" -cors = [] +cors_origins = [] cpu_profile_file = "" -datadir = "." +data_dir = "." key_file = "" -listen_host = "127.0.0.1:4001" -machines = [] -machines_file = "" +peers = [] +peers_file = "" max_cluster_size = 9 max_result_buffer = 1024 max_retry_attempts = 3 @@ -69,36 +69,36 @@ very_verbose = false web_url = "" [peer] -advertised_url = "127.0.0.1:7001" +addr = "127.0.0.1:7001" +bind_addr = "127.0.0.1:7001" ca_file = "" cert_file = "" key_file = "" -listen_host = "127.0.0.1:7001" ``` ## Environment Variables - * `ETCD_ADVERTISED_URL` + * `ETCD_ADDR` + * `ETCD_BIND_ADDR` * `ETCD_CA_FILE` * `ETCD_CERT_FILE` - * `ETCD_CORS` - * `ETCD_CONFIG_FILE` + * `ETCD_CORS_ORIGINS` + * `ETCD_CONFIG` * `ETCD_CPU_PROFILE_FILE` - * `ETCD_DATADIR` + * `ETCD_DATA_DIR` * `ETCD_KEY_FILE` - * `ETCD_LISTEN_HOST` - * `ETCD_MACHINES` - * `ETCD_MACHINES_FILE` - * `ETCD_MAX_RETRY_ATTEMPTS` + * `ETCD_PEERS` + * `ETCD_PEERS_FILE` * `ETCD_MAX_CLUSTER_SIZE` * `ETCD_MAX_RESULT_BUFFER` + * `ETCD_MAX_RETRY_ATTEMPTS` * `ETCD_NAME` * `ETCD_SNAPSHOT` * `ETCD_VERBOSE` * `ETCD_VERY_VERBOSE` * `ETCD_WEB_URL` - * `ETCD_PEER_ADVERTISED_URL` + * `ETCD_PEER_ADDR` + * `ETCD_PEER_BIND_ADDR` * `ETCD_PEER_CA_FILE` * `ETCD_PEER_CERT_FILE` * `ETCD_PEER_KEY_FILE` - * `ETCD_PEER_LISTEN_HOST` diff --git a/Documentation/internal-protocol-versioning.md b/Documentation/internal-protocol-versioning.md index 503a3029b..4602f91b6 100644 --- a/Documentation/internal-protocol-versioning.md +++ b/Documentation/internal-protocol-versioning.md @@ -1,12 +1,12 @@ # Versioning -Goal: We want to be able to upgrade an individual machine in an etcd cluster to a newer version of etcd. +Goal: We want to be able to upgrade an individual peer in an etcd cluster to a newer version of etcd. The process will take the form of individual followers upgrading to the latest version until the entire cluster is on the new version. Immediate need: etcd is moving too fast to version the internal API right now. But, we need to keep mixed version clusters from being started by a rollowing upgrade process (e.g. the CoreOS developer alpha). -Longer term need: Having a mixed version cluster where all machines are not be running the exact same version of etcd itself but are able to speak one version of the internal protocol. +Longer term need: Having a mixed version cluster where all peers are not be running the exact same version of etcd itself but are able to speak one version of the internal protocol. Solution: The internal protocol needs to be versioned just as the client protocol is. Initially during the 0.\*.\* series of etcd releases we won't allow mixed versions at all. @@ -58,4 +58,4 @@ https://issues.apache.org/jira/browse/ZOOKEEPER-1633 ## doozerd -doozerd stores the version number of the machine in the datastore for other clients to check, no decisions are made off of this number currently. +doozerd stores the version number of the peers in the datastore for other clients to check, no decisions are made off of this number currently. diff --git a/README.md b/README.md index e51674488..13f111dbf 100644 --- a/README.md +++ b/README.md @@ -62,12 +62,12 @@ These examples will use a single node cluster to show you the basics of the etcd Let's start etcd: ```sh -./etcd -d node0 -n node0 +./etcd -data-dir node0 -name node0 ``` This will bring up an etcd node listening on port 4001 for client communication and on port 7001 for server-to-server communication. -The `-d node0` argument tells etcd to write node configuration, logs and snapshots to the `./node0/` directory. -The `-n node0` tells the rest of the cluster that this node is named node0. +The `-data-dir node0` argument tells etcd to write node configuration, logs and snapshots to the `./node0/` directory. +The `-name node0` tells the rest of the cluster that this node is named node0. @@ -378,13 +378,13 @@ For testing you can use the certificates in the `fixtures/ca` directory. Let's configure etcd to use this keypair: ```sh -./etcd -n node0 -d node0 -clientCert=./fixtures/ca/server.crt -clientKey=./fixtures/ca/server.key.insecure -f +./etcd -f -name node0 -data-dir node0 -cert-file=./fixtures/ca/server.crt -key-file=./fixtures/ca/server.key.insecure ``` There are a few new options we're using: * `-f` - forces a new node configuration, even if an existing configuration is found. (WARNING: data loss!) -* `-clientCert` and `-clientKey` specify the location of the cert and key files to be used for for transport layer security between the client and server. +* `-cert-file` and `-key-file` specify the location of the cert and key files to be used for for transport layer security between the client and server. You can now test the configuration using HTTPS: @@ -413,10 +413,10 @@ We can also do authentication using CA certs. The clients will provide their cert to the server and the server will check whether the cert is signed by the CA and decide whether to serve the request. ```sh -./etcd -n node0 -d node0 -clientCAFile=./fixtures/ca/ca.crt -clientCert=./fixtures/ca/server.crt -clientKey=./fixtures/ca/server.key.insecure -f +./etcd -f -name node0 -data-dir node0 -ca-file=./fixtures/ca/ca.crt -cert-file=./fixtures/ca/server.crt -key-file=./fixtures/ca/server.key.insecure ``` -```-clientCAFile``` is the path to the CA cert. +```-ca-file``` is the path to the CA cert. Try the same request to this server: @@ -463,20 +463,20 @@ We use Raft as the underlying distributed protocol which provides consistency an Let start by creating 3 new etcd instances. -We use -s to specify server port and -c to specify client port and -d to specify the directory to store the log and info of the node in the cluster +We use `-peer-addr` to specify server port and `-addr` to specify client port and `-data-dir` to specify the directory to store the log and info of the node in the cluster: ```sh -./etcd -s 127.0.0.1:7001 -c 127.0.0.1:4001 -d nodes/node1 -n node1 +./etcd -peer-addr 127.0.0.1:7001 -addr 127.0.0.1:4001 -data-dir nodes/node1 -name node1 ``` -**Note:** If you want to run etcd on an external IP address and still have access locally, you'll need to add `-cl 0.0.0.0` so that it will listen on both external and localhost addresses. -A similar argument `-sl` is used to setup the listening address for the server port. +**Note:** If you want to run etcd on an external IP address and still have access locally, you'll need to add `-bind-addr 0.0.0.0` so that it will listen on both external and localhost addresses. +A similar argument `-peer-bind-addr` is used to setup the listening address for the server port. -Let's join two more nodes to this cluster using the `-C` argument: +Let's join two more nodes to this cluster using the `-peers` argument: ```sh -./etcd -s 127.0.0.1:7002 -c 127.0.0.1:4002 -C 127.0.0.1:7001 -d nodes/node2 -n node2 -./etcd -s 127.0.0.1:7003 -c 127.0.0.1:4003 -C 127.0.0.1:7001 -d nodes/node3 -n node3 +./etcd -peer-addr 127.0.0.1:7002 -addr 127.0.0.1:4002 -peers 127.0.0.1:7001 -data-dir nodes/node2 -name node2 +./etcd -peer-addr 127.0.0.1:7003 -addr 127.0.0.1:4003 -peers 127.0.0.1:7001 -data-dir nodes/node3 -name node3 ``` We can retrieve a list of machines in the cluster using the HTTP API: @@ -569,7 +569,7 @@ curl -L http://127.0.0.1:4002/v1/keys/foo In the previous example we showed how to use SSL client certs for client-to-server communication. Etcd can also do internal server-to-server communication using SSL client certs. -To do this just change the `-client*` flags to `-server*`. +To do this just change the `-*-file` flags to `-peer-*-file`. If you are using SSL for server-to-server communication, you must use it on all instances of etcd. @@ -648,13 +648,13 @@ See [CONTRIBUTING](https://github.com/coreos/etcd/blob/master/CONTRIBUTING.md) f ### What size cluster should I use? Every command the client sends to the master is broadcast to all of the followers. -The command is not committed until the majority of the cluster machines receive that command. +The command is not committed until the majority of the cluster peers receive that command. -Because of this majority voting property, the ideal cluster should be kept small to keep speed up and be made up of an odd number of machines. +Because of this majority voting property, the ideal cluster should be kept small to keep speed up and be made up of an odd number of peers. -Odd numbers are good because if you have 8 machines the majority will be 5 and if you have 9 machines the majority will still be 5. -The result is that an 8 machine cluster can tolerate 3 machine failures and a 9 machine cluster can tolerate 4 nodes failures. -And in the best case when all 9 machines are responding the cluster will perform at the speed of the fastest 5 nodes. +Odd numbers are good because if you have 8 peers the majority will be 5 and if you have 9 peers the majority will still be 5. +The result is that an 8 peer cluster can tolerate 3 peer failures and a 9 peer cluster can tolerate 4 nodes failures. +And in the best case when all 9 peers are responding the cluster will perform at the speed of the fastest 5 nodes. ### Why SSLv3 alert handshake failure when using SSL client auth? diff --git a/error/error.go b/error/error.go index 3eef90c65..dddad19b4 100644 --- a/error/error.go +++ b/error/error.go @@ -28,7 +28,7 @@ const ( EcodeKeyNotFound = 100 EcodeTestFailed = 101 EcodeNotFile = 102 - EcodeNoMoreMachine = 103 + EcodeNoMorePeer = 103 EcodeNotDir = 104 EcodeNodeExist = 105 EcodeKeyIsPreserved = 106 @@ -53,7 +53,7 @@ func init() { errors[EcodeKeyNotFound] = "Key Not Found" errors[EcodeTestFailed] = "Test Failed" //test and set errors[EcodeNotFile] = "Not A File" - errors[EcodeNoMoreMachine] = "Reached the max number of machines in the cluster" + errors[EcodeNoMorePeer] = "Reached the max number of peers in the cluster" errors[EcodeNotDir] = "Not A Directory" errors[EcodeNodeExist] = "Already exists" // create errors[EcodeKeyIsPreserved] = "The prefix of given key is a keyword in etcd" diff --git a/etcd.go b/etcd.go index 3bcb400f9..bfad9b5e4 100644 --- a/etcd.go +++ b/etcd.go @@ -66,12 +66,23 @@ func main() { if info.Name == "" { host, err := os.Hostname() if err != nil || host == "" { - log.Fatal("Machine name required and hostname not set. e.g. '-n=machine_name'") + log.Fatal("Node name required and hostname not set. e.g. '-name=name'") } - log.Warnf("Using hostname %s as the machine name. You must ensure this name is unique among etcd machines.", host) + log.Warnf("Using hostname %s as the node name. You must ensure this name is unique among etcd nodes.", host) info.Name = host } + // Setup a default directory based on the node name + if config.DataDir == "" { + config.DataDir = info.Name + ".etcd" + log.Warnf("Using the directory %s as the etcd configuration directory because a directory was not specified. ", config.DataDir) + } + + // Create data directory if it doesn't already exist. + if err := os.MkdirAll(config.DataDir, 0744); err != nil { + log.Fatalf("Unable to create path: %s", err) + } + // Retrieve TLS configuration. tlsConfig, err := info.EtcdTLS.Config() if err != nil { @@ -87,13 +98,13 @@ func main() { registry := server.NewRegistry(store) // Create peer server. - ps := server.NewPeerServer(info.Name, config.DataDir, info.RaftURL, info.RaftListenHost, &peerTLSConfig, &info.RaftTLS, registry, store, config.SnapCount) + ps := server.NewPeerServer(info.Name, config.DataDir, info.RaftURL, info.RaftListenHost, &peerTLSConfig, &info.RaftTLS, registry, store, config.SnapshotCount) ps.MaxClusterSize = config.MaxClusterSize ps.RetryTimes = config.MaxRetryAttempts // Create client server. s := server.New(info.Name, info.EtcdURL, info.EtcdListenHost, &tlsConfig, &info.EtcdTLS, ps, registry, store) - if err := s.AllowOrigins(config.Cors); err != nil { + if err := s.AllowOrigins(config.CorsOrigins); err != nil { panic(err) } @@ -101,7 +112,7 @@ func main() { // Run peer server in separate thread while the client server blocks. go func() { - log.Fatal(ps.ListenAndServe(config.Snapshot, config.Machines)) + log.Fatal(ps.ListenAndServe(config.Snapshot, config.Peers)) }() log.Fatal(s.ListenAndServe()) } diff --git a/mod/dashboard/app/scripts/controllers/stats.js b/mod/dashboard/app/scripts/controllers/stats.js index 5e1216ace..614cfd78c 100644 --- a/mod/dashboard/app/scripts/controllers/stats.js +++ b/mod/dashboard/app/scripts/controllers/stats.js @@ -24,9 +24,9 @@ angular.module('etcdStats', ['ngRoute', 'etcd']) EtcdV2.getStat('leader').get().success(function(data) { $scope.leaderStats = data; $scope.leaderName = data.leader; - $scope.machines = []; + $scope.peers = []; //hardcode leader stats - $scope.machines.push({ + $scope.peers.push({ latency: { average: 0, current: 0, @@ -38,10 +38,10 @@ angular.module('etcdStats', ['ngRoute', 'etcd']) }); $.each(data.followers, function(index, value) { value.name = index; - $scope.machines.push(value); + $scope.peers.push(value); }); - //sort array so machines don't jump when output - $scope.machines.sort(function(a, b){ + //sort array so peers don't jump when output + $scope.peers.sort(function(a, b){ if(a.name < b.name) return -1; if(a.name > b.name) return 1; return 0; @@ -64,7 +64,7 @@ angular.module('etcdStats', ['ngRoute', 'etcd']) chart({ el: $scope.graphContainer, data: { - 'stats': $scope.machines + 'stats': $scope.peers } }).width(width).height(height).update(); }); diff --git a/mod/dashboard/app/styles/etcd-widgets.css b/mod/dashboard/app/styles/etcd-widgets.css index 5abfdc25f..0ed4deb51 100644 --- a/mod/dashboard/app/styles/etcd-widgets.css +++ b/mod/dashboard/app/styles/etcd-widgets.css @@ -636,7 +636,7 @@ body { background-color: #00DB24; } - .etcd-container.etcd-stats .etcd-list .etcd-machine-type { + .etcd-container.etcd-stats .etcd-list .etcd-peer-type { color: #999; padding-left: 3px; font-size: 13px; diff --git a/mod/dashboard/app/views/stats.html b/mod/dashboard/app/views/stats.html index e8a85ceac..8243d3617 100644 --- a/mod/dashboard/app/views/stats.html +++ b/mod/dashboard/app/views/stats.html @@ -20,26 +20,26 @@
-

Machine Latency

+

Peer Latency

-

Machine List

+

Peer List

- + - - + diff --git a/release_version.go b/release_version.go index 5285c9763..23d8bce95 100644 --- a/release_version.go +++ b/release_version.go @@ -1,2 +1,3 @@ package main + const releaseVersion = "v0.1.2-33-g1a2a9d6" diff --git a/scripts/test-cluster b/scripts/test-cluster index ccdedd1b7..486e3d636 100755 --- a/scripts/test-cluster +++ b/scripts/test-cluster @@ -4,15 +4,15 @@ SESSION=etcd-cluster tmux new-session -d -s $SESSION # Setup a window for tailing log files -tmux new-window -t $SESSION:1 -n 'machines' +tmux new-window -t $SESSION:1 -n 'peers' tmux split-window -h tmux select-pane -t 0 -tmux send-keys "./etcd -s 127.0.0.1:7001 -c 127.0.0.1:4001 -d machine1 -n machine1" C-m +tmux send-keys "./etcd -s 127.0.0.1:7001 -c 127.0.0.1:4001 -d peer1 -n peer1" C-m for i in 2 3; do tmux select-pane -t 0 tmux split-window -v - tmux send-keys "./etcd -cors='*' -s 127.0.0.1:700${i} -c 127.0.0.1:400${i} -C 127.0.0.1:7001 -d machine${i} -n machine${i}" C-m + tmux send-keys "./etcd -cors='*' -s 127.0.0.1:700${i} -c 127.0.0.1:400${i} -C 127.0.0.1:7001 -d peer${i} -n peer${i}" C-m done # Attach to session diff --git a/server/config.go b/server/config.go index 8d8adcf82..67a36f733 100644 --- a/server/config.go +++ b/server/config.go @@ -19,35 +19,57 @@ import ( // The default location for the etcd configuration file. const DefaultSystemConfigPath = "/etc/etcd/etcd.conf" +// A lookup of deprecated flags to their new flag name. +var newFlagNameLookup = map[string]string{ + "C": "peers", + "CF": "peers-file", + "n": "name", + "c": "addr", + "cl": "bind-addr", + "s": "peer-addr", + "sl": "peer-bind-addr", + "d": "data-dir", + "m": "max-result-buffer", + "r": "max-retry-attempts", + "maxsize": "max-cluster-size", + "clientCAFile": "ca-file", + "clientCert": "cert-file", + "clientKey": "key-file", + "serverCAFile": "peer-ca-file", + "serverCert": "peer-cert-file", + "serverKey": "peer-key-file", + "snapshotCount": "snapshot-count", +} + // Config represents the server configuration. type Config struct { SystemPath string - AdvertisedUrl string `toml:"advertised_url" env:"ETCD_ADVERTISED_URL"` + Addr string `toml:"addr" env:"ETCD_ADDR"` + BindAddr string `toml:"bind_addr" env:"ETCD_BIND_ADDR"` CAFile string `toml:"ca_file" env:"ETCD_CA_FILE"` CertFile string `toml:"cert_file" env:"ETCD_CERT_FILE"` - Cors []string `toml:"cors" env:"ETCD_CORS"` - DataDir string `toml:"datadir" env:"ETCD_DATADIR"` + CorsOrigins []string `toml:"cors" env:"ETCD_CORS"` + DataDir string `toml:"data_dir" env:"ETCD_DATA_DIR"` + Force bool KeyFile string `toml:"key_file" env:"ETCD_KEY_FILE"` - ListenHost string `toml:"listen_host" env:"ETCD_LISTEN_HOST"` - Machines []string `toml:"machines" env:"ETCD_MACHINES"` - MachinesFile string `toml:"machines_file" env:"ETCD_MACHINES_FILE"` + Peers []string `toml:"peers" env:"ETCD_PEERS"` + PeersFile string `toml:"peers_file" env:"ETCD_PEERS_FILE"` MaxClusterSize int `toml:"max_cluster_size" env:"ETCD_MAX_CLUSTER_SIZE"` MaxResultBuffer int `toml:"max_result_buffer" env:"ETCD_MAX_RESULT_BUFFER"` MaxRetryAttempts int `toml:"max_retry_attempts" env:"ETCD_MAX_RETRY_ATTEMPTS"` Name string `toml:"name" env:"ETCD_NAME"` Snapshot bool `toml:"snapshot" env:"ETCD_SNAPSHOT"` - SnapCount int `toml:"snapshot_count" env:"ETCD_SNAPSHOTCOUNT"` + SnapshotCount int `toml:"snapshot_count" env:"ETCD_SNAPSHOTCOUNT"` Verbose bool `toml:"verbose" env:"ETCD_VERBOSE"` VeryVerbose bool `toml:"very_verbose" env:"ETCD_VERY_VERBOSE"` - WebURL string `toml:"web_url" env:"ETCD_WEB_URL"` Peer struct { - AdvertisedUrl string `toml:"advertised_url" env:"ETCD_PEER_ADVERTISED_URL"` - CAFile string `toml:"ca_file" env:"ETCD_PEER_CA_FILE"` - CertFile string `toml:"cert_file" env:"ETCD_PEER_CERT_FILE"` - KeyFile string `toml:"key_file" env:"ETCD_PEER_KEY_FILE"` - ListenHost string `toml:"listen_host" env:"ETCD_PEER_LISTEN_HOST"` + Addr string `toml:"addr" env:"ETCD_PEER_ADDR"` + BindAddr string `toml:"bind_addr" env:"ETCD_PEER_BIND_ADDR"` + CAFile string `toml:"ca_file" env:"ETCD_PEER_CA_FILE"` + CertFile string `toml:"cert_file" env:"ETCD_PEER_CERT_FILE"` + KeyFile string `toml:"key_file" env:"ETCD_PEER_KEY_FILE"` } } @@ -55,13 +77,12 @@ type Config struct { func NewConfig() *Config { c := new(Config) c.SystemPath = DefaultSystemConfigPath - c.AdvertisedUrl = "127.0.0.1:4001" - c.AdvertisedUrl = "127.0.0.1:4001" + c.Addr = "127.0.0.1:4001" c.MaxClusterSize = 9 c.MaxResultBuffer = 1024 c.MaxRetryAttempts = 3 - c.Peer.AdvertisedUrl = "127.0.0.1:7001" - c.SnapCount = 10000 + c.Peer.Addr = "127.0.0.1:7001" + c.SnapshotCount = 10000 return c } @@ -96,8 +117,17 @@ func (c *Config) Load(arguments []string) error { return err } - // Loads machines if a machine file was specified. - if err := c.LoadMachineFile(); err != nil { + // Load from command line flags (deprecated). + if err := c.LoadDeprecatedFlags(arguments); err != nil { + if err, ok := err.(*DeprecationError); ok { + fmt.Fprintln(os.Stderr, err.Error()) + } else { + return err + } + } + + // Loads peers if a peer file was specified. + if err := c.LoadPeersFile(); err != nil { return err } @@ -165,27 +195,21 @@ func (c *Config) loadEnv(target interface{}) error { return nil } -// Loads configuration from command line flags. -func (c *Config) LoadFlags(arguments []string) error { - var machines, cors string - var force bool +// Loads deprecated configuration settings from the command line. +func (c *Config) LoadDeprecatedFlags(arguments []string) error { + var peers string f := flag.NewFlagSet(os.Args[0], flag.ContinueOnError) + f.SetOutput(ioutil.Discard) - f.BoolVar(&force, "f", false, "force new node configuration if existing is found (WARNING: data loss!)") + f.StringVar(&peers, "C", "", "(deprecated)") + f.StringVar(&c.PeersFile, "CF", c.PeersFile, "(deprecated)") - f.BoolVar(&c.Verbose, "v", c.Verbose, "verbose logging") - f.BoolVar(&c.VeryVerbose, "vv", c.Verbose, "very verbose logging") - - f.StringVar(&machines, "C", "", "the ip address and port of a existing machines in the cluster, sepearate by comma") - f.StringVar(&c.MachinesFile, "CF", c.MachinesFile, "the file contains a list of existing machines in the cluster, seperate by comma") - - f.StringVar(&c.Name, "n", c.Name, "the node name (required)") - f.StringVar(&c.AdvertisedUrl, "c", c.AdvertisedUrl, "the advertised public hostname:port for etcd client communication") - f.StringVar(&c.Peer.AdvertisedUrl, "s", c.Peer.AdvertisedUrl, "the advertised public hostname:port for raft server communication") - f.StringVar(&c.ListenHost, "cl", c.ListenHost, "the listening hostname for etcd client communication (defaults to advertised ip)") - f.StringVar(&c.Peer.ListenHost, "sl", c.Peer.ListenHost, "the listening hostname for raft server communication (defaults to advertised ip)") - f.StringVar(&c.WebURL, "w", c.WebURL, "the hostname:port of web interface") + f.StringVar(&c.Name, "n", c.Name, "(deprecated)") + f.StringVar(&c.Addr, "c", c.Addr, "(deprecated)") + f.StringVar(&c.BindAddr, "cl", c.BindAddr, "the listening hostname for etcd client communication (defaults to advertised ip)") + f.StringVar(&c.Peer.Addr, "s", c.Peer.Addr, "the advertised public hostname:port for raft server communication") + f.StringVar(&c.Peer.BindAddr, "sl", c.Peer.BindAddr, "the listening hostname for raft server communication (defaults to advertised ip)") f.StringVar(&c.Peer.CAFile, "serverCAFile", c.Peer.CAFile, "the path of the CAFile") f.StringVar(&c.Peer.CertFile, "serverCert", c.Peer.CertFile, "the cert file of the server") @@ -199,10 +223,66 @@ func (c *Config) LoadFlags(arguments []string) error { f.IntVar(&c.MaxResultBuffer, "m", c.MaxResultBuffer, "the max size of result buffer") f.IntVar(&c.MaxRetryAttempts, "r", c.MaxRetryAttempts, "the max retry attempts when trying to join a cluster") f.IntVar(&c.MaxClusterSize, "maxsize", c.MaxClusterSize, "the max size of the cluster") + + f.IntVar(&c.SnapshotCount, "snapshotCount", c.SnapshotCount, "save the in-memory logs and states to a snapshot file a given number of transactions") + + f.Parse(arguments) + + // Convert some parameters to lists. + if peers != "" { + c.Peers = trimsplit(peers, ",") + } + + // Generate deprecation warning. + warnings := make([]string, 0) + f.Visit(func(f *flag.Flag) { + warnings = append(warnings, fmt.Sprintf("[deprecated] use -%s, not -%s", newFlagNameLookup[f.Name], f.Name)) + }) + if len(warnings) > 0 { + return &DeprecationError{strings.Join(warnings, "\n")} + } + + return nil +} + +// Loads configuration from command line flags. +func (c *Config) LoadFlags(arguments []string) error { + var peers, cors string + + f := flag.NewFlagSet(os.Args[0], flag.ContinueOnError) + f.SetOutput(ioutil.Discard) + + f.BoolVar(&c.Force, "f", false, "force new node configuration if existing is found (WARNING: data loss!)") + f.BoolVar(&c.Force, "force", false, "force new node configuration if existing is found (WARNING: data loss!)") + + f.BoolVar(&c.Verbose, "v", c.Verbose, "verbose logging") + f.BoolVar(&c.VeryVerbose, "vv", c.Verbose, "very verbose logging") + + f.StringVar(&peers, "peers", "", "the ip address and port of a existing peers in the cluster, sepearate by comma") + f.StringVar(&c.PeersFile, "peers-file", c.PeersFile, "the file contains a list of existing peers in the cluster, seperate by comma") + + f.StringVar(&c.Name, "name", c.Name, "the node name (required)") + f.StringVar(&c.Addr, "addr", c.Addr, "the advertised public hostname:port for etcd client communication") + f.StringVar(&c.BindAddr, "bind-addr", c.BindAddr, "the listening hostname for etcd client communication (defaults to advertised ip)") + f.StringVar(&c.Peer.Addr, "peer-addr", c.Peer.Addr, "the advertised public hostname:port for raft server communication") + f.StringVar(&c.Peer.BindAddr, "peer-bind-addr", c.Peer.BindAddr, "the listening hostname for raft server communication (defaults to advertised ip)") + + f.StringVar(&c.Peer.CAFile, "peer-ca-file", c.Peer.CAFile, "the path of the CAFile") + f.StringVar(&c.Peer.CertFile, "peer-cert-file", c.Peer.CertFile, "the cert file of the server") + f.StringVar(&c.Peer.KeyFile, "peer-key-file", c.Peer.KeyFile, "the key file of the server") + + f.StringVar(&c.CAFile, "ca-file", c.CAFile, "the path of the client CAFile") + f.StringVar(&c.CertFile, "cert-file", c.CertFile, "the cert file of the client") + f.StringVar(&c.KeyFile, "key-file", c.KeyFile, "the key file of the client") + + f.StringVar(&c.DataDir, "data-dir", c.DataDir, "the directory to store log and snapshot") + f.IntVar(&c.MaxResultBuffer, "max-result-buffer", c.MaxResultBuffer, "the max size of result buffer") + f.IntVar(&c.MaxRetryAttempts, "max-retry-attempts", c.MaxRetryAttempts, "the max retry attempts when trying to join a cluster") + f.IntVar(&c.MaxClusterSize, "max-cluster-size", c.MaxClusterSize, "the max size of the cluster") f.StringVar(&cors, "cors", "", "whitelist origins for cross-origin resource sharing (e.g. '*' or 'http://localhost:8001,etc')") f.BoolVar(&c.Snapshot, "snapshot", c.Snapshot, "open or close snapshot") - f.IntVar(&c.SnapCount, "snapshotCount", c.SnapCount, "save the in memory logs and states to a snapshot file after snapCount transactions") + f.IntVar(&c.SnapshotCount, "snapshot-count", c.SnapshotCount, "save the in-memory logs and states to a snapshot file a given number of transactions") // These flags are ignored since they were already parsed. var path string @@ -211,32 +291,32 @@ func (c *Config) LoadFlags(arguments []string) error { f.Parse(arguments) // Convert some parameters to lists. - if machines != "" { - c.Machines = trimsplit(machines, ",") + if peers != "" { + c.Peers = trimsplit(peers, ",") } if cors != "" { - c.Cors = trimsplit(cors, ",") + c.CorsOrigins = trimsplit(cors, ",") } // Force remove server configuration if specified. - if force { + if c.Force { c.Reset() } return nil } -// LoadMachineFile loads the machines listed in the machine file. -func (c *Config) LoadMachineFile() error { - if c.MachinesFile == "" { +// LoadPeersFile loads the peers listed in the peers file. +func (c *Config) LoadPeersFile() error { + if c.PeersFile == "" { return nil } - b, err := ioutil.ReadFile(c.MachinesFile) + b, err := ioutil.ReadFile(c.PeersFile) if err != nil { - return fmt.Errorf("Machines file error: %s", err) + return fmt.Errorf("Peers file error: %s", err) } - c.Machines = trimsplit(string(b), ",") + c.Peers = trimsplit(string(b), ",") return nil } @@ -278,11 +358,10 @@ func (c *Config) Info() (*Info, error) { // If the file doesn't exist then initialize it. info.Name = strings.TrimSpace(c.Name) - info.EtcdURL = c.AdvertisedUrl - info.EtcdListenHost = c.ListenHost - info.RaftURL = c.Peer.AdvertisedUrl - info.RaftListenHost = c.Peer.ListenHost - info.WebURL = c.WebURL + info.EtcdURL = c.Addr + info.EtcdListenHost = c.BindAddr + info.RaftURL = c.Peer.Addr + info.RaftListenHost = c.Peer.BindAddr info.EtcdTLS = c.TLSInfo() info.RaftTLS = c.PeerTLSInfo() @@ -313,19 +392,16 @@ func (c *Config) Sanitize() error { } // Sanitize the URLs first. - if c.AdvertisedUrl, err = sanitizeURL(c.AdvertisedUrl, tlsConfig.Scheme); err != nil { + if c.Addr, err = sanitizeURL(c.Addr, tlsConfig.Scheme); err != nil { return fmt.Errorf("Advertised URL: %s", err) } - if c.ListenHost, err = sanitizeListenHost(c.ListenHost, c.AdvertisedUrl); err != nil { + if c.BindAddr, err = sanitizeBindAddr(c.BindAddr, c.Addr); err != nil { return fmt.Errorf("Listen Host: %s", err) } - if c.WebURL, err = sanitizeURL(c.WebURL, "http"); err != nil { - return fmt.Errorf("Web URL: %s", err) - } - if c.Peer.AdvertisedUrl, err = sanitizeURL(c.Peer.AdvertisedUrl, peerTlsConfig.Scheme); err != nil { + if c.Peer.Addr, err = sanitizeURL(c.Peer.Addr, peerTlsConfig.Scheme); err != nil { return fmt.Errorf("Peer Advertised URL: %s", err) } - if c.Peer.ListenHost, err = sanitizeListenHost(c.Peer.ListenHost, c.Peer.AdvertisedUrl); err != nil { + if c.Peer.BindAddr, err = sanitizeBindAddr(c.Peer.BindAddr, c.Peer.Addr); err != nil { return fmt.Errorf("Peer Listen Host: %s", err) } @@ -383,10 +459,10 @@ func sanitizeURL(host string, defaultScheme string) (string, error) { return p.String(), nil } -// sanitizeListenHost cleans up the ListenHost parameter and appends a port +// sanitizeBindAddr cleans up the BindAddr parameter and appends a port // if necessary based on the advertised port. -func sanitizeListenHost(listen string, advertised string) (string, error) { - aurl, err := url.Parse(advertised) +func sanitizeBindAddr(bindAddr string, addr string) (string, error) { + aurl, err := url.Parse(addr) if err != nil { return "", err } @@ -397,9 +473,21 @@ func sanitizeListenHost(listen string, advertised string) (string, error) { } // If the listen host isn't set use the advertised host - if listen == "" { - listen = ahost + if bindAddr == "" { + bindAddr = ahost } - return net.JoinHostPort(listen, aport), nil + return net.JoinHostPort(bindAddr, aport), nil } + + +// DeprecationError is a warning for CLI users that one or more arguments will +// not be supported in future released. +type DeprecationError struct { + s string +} + +func (e *DeprecationError) Error() string { + return e.s +} + diff --git a/server/config_test.go b/server/config_test.go index 720534888..9ebe70548 100644 --- a/server/config_test.go +++ b/server/config_test.go @@ -9,20 +9,19 @@ import ( "github.com/stretchr/testify/assert" ) - // Ensures that a configuration can be deserialized from TOML. func TestConfigTOML(t *testing.T) { content := ` - advertised_url = "127.0.0.1:4002" + addr = "127.0.0.1:4002" ca_file = "/tmp/file.ca" cert_file = "/tmp/file.cert" cors = ["*"] cpu_profile_file = "XXX" - datadir = "/tmp/data" + data_dir = "/tmp/data" key_file = "/tmp/file.key" - listen_host = "127.0.0.1:4003" - machines = ["coreos.com:4001", "coreos.com:4002"] - machines_file = "/tmp/machines" + bind_addr = "127.0.0.1:4003" + peers = ["coreos.com:4001", "coreos.com:4002"] + peers_file = "/tmp/peers" max_cluster_size = 10 max_result_buffer = 512 max_retry_attempts = 5 @@ -33,24 +32,24 @@ func TestConfigTOML(t *testing.T) { web_url = "/web" [peer] - advertised_url = "127.0.0.1:7002" + addr = "127.0.0.1:7002" ca_file = "/tmp/peer/file.ca" cert_file = "/tmp/peer/file.cert" key_file = "/tmp/peer/file.key" - listen_host = "127.0.0.1:7003" + bind_addr = "127.0.0.1:7003" ` c := NewConfig() _, err := toml.Decode(content, &c) assert.Nil(t, err, "") - assert.Equal(t, c.AdvertisedUrl, "127.0.0.1:4002", "") + assert.Equal(t, c.Addr, "127.0.0.1:4002", "") assert.Equal(t, c.CAFile, "/tmp/file.ca", "") assert.Equal(t, c.CertFile, "/tmp/file.cert", "") - assert.Equal(t, c.Cors, []string{"*"}, "") + assert.Equal(t, c.CorsOrigins, []string{"*"}, "") assert.Equal(t, c.DataDir, "/tmp/data", "") assert.Equal(t, c.KeyFile, "/tmp/file.key", "") - assert.Equal(t, c.ListenHost, "127.0.0.1:4003", "") - assert.Equal(t, c.Machines, []string{"coreos.com:4001", "coreos.com:4002"}, "") - assert.Equal(t, c.MachinesFile, "/tmp/machines", "") + assert.Equal(t, c.BindAddr, "127.0.0.1:4003", "") + assert.Equal(t, c.Peers, []string{"coreos.com:4001", "coreos.com:4002"}, "") + assert.Equal(t, c.PeersFile, "/tmp/peers", "") assert.Equal(t, c.MaxClusterSize, 10, "") assert.Equal(t, c.MaxResultBuffer, 512, "") assert.Equal(t, c.MaxRetryAttempts, 5, "") @@ -58,12 +57,11 @@ func TestConfigTOML(t *testing.T) { assert.Equal(t, c.Snapshot, true, "") assert.Equal(t, c.Verbose, true, "") assert.Equal(t, c.VeryVerbose, true, "") - assert.Equal(t, c.WebURL, "/web", "") - assert.Equal(t, c.Peer.AdvertisedUrl, "127.0.0.1:7002", "") + assert.Equal(t, c.Peer.Addr, "127.0.0.1:7002", "") assert.Equal(t, c.Peer.CAFile, "/tmp/peer/file.ca", "") assert.Equal(t, c.Peer.CertFile, "/tmp/peer/file.cert", "") assert.Equal(t, c.Peer.KeyFile, "/tmp/peer/file.key", "") - assert.Equal(t, c.Peer.ListenHost, "127.0.0.1:7003", "") + assert.Equal(t, c.Peer.BindAddr, "127.0.0.1:7003", "") } // Ensures that a configuration can be retrieved from environment variables. @@ -72,11 +70,11 @@ func TestConfigEnv(t *testing.T) { os.Setenv("ETCD_CERT_FILE", "/tmp/file.cert") os.Setenv("ETCD_CPU_PROFILE_FILE", "XXX") os.Setenv("ETCD_CORS", "localhost:4001,localhost:4002") - os.Setenv("ETCD_DATADIR", "/tmp/data") + os.Setenv("ETCD_DATA_DIR", "/tmp/data") os.Setenv("ETCD_KEY_FILE", "/tmp/file.key") - os.Setenv("ETCD_LISTEN_HOST", "127.0.0.1:4003") - os.Setenv("ETCD_MACHINES", "coreos.com:4001,coreos.com:4002") - os.Setenv("ETCD_MACHINES_FILE", "/tmp/machines") + os.Setenv("ETCD_BIND_ADDR", "127.0.0.1:4003") + os.Setenv("ETCD_PEERS", "coreos.com:4001,coreos.com:4002") + os.Setenv("ETCD_PEERS_FILE", "/tmp/peers") os.Setenv("ETCD_MAX_CLUSTER_SIZE", "10") os.Setenv("ETCD_MAX_RESULT_BUFFER", "512") os.Setenv("ETCD_MAX_RETRY_ATTEMPTS", "5") @@ -85,22 +83,22 @@ func TestConfigEnv(t *testing.T) { os.Setenv("ETCD_VERBOSE", "1") os.Setenv("ETCD_VERY_VERBOSE", "yes") os.Setenv("ETCD_WEB_URL", "/web") - os.Setenv("ETCD_PEER_ADVERTISED_URL", "127.0.0.1:7002") + os.Setenv("ETCD_PEER_ADDR", "127.0.0.1:7002") os.Setenv("ETCD_PEER_CA_FILE", "/tmp/peer/file.ca") os.Setenv("ETCD_PEER_CERT_FILE", "/tmp/peer/file.cert") os.Setenv("ETCD_PEER_KEY_FILE", "/tmp/peer/file.key") - os.Setenv("ETCD_PEER_LISTEN_HOST", "127.0.0.1:7003") - + os.Setenv("ETCD_PEER_BIND_ADDR", "127.0.0.1:7003") + c := NewConfig() c.LoadEnv() assert.Equal(t, c.CAFile, "/tmp/file.ca", "") assert.Equal(t, c.CertFile, "/tmp/file.cert", "") - assert.Equal(t, c.Cors, []string{"localhost:4001", "localhost:4002"}, "") + assert.Equal(t, c.CorsOrigins, []string{"localhost:4001", "localhost:4002"}, "") assert.Equal(t, c.DataDir, "/tmp/data", "") assert.Equal(t, c.KeyFile, "/tmp/file.key", "") - assert.Equal(t, c.ListenHost, "127.0.0.1:4003", "") - assert.Equal(t, c.Machines, []string{"coreos.com:4001", "coreos.com:4002"}, "") - assert.Equal(t, c.MachinesFile, "/tmp/machines", "") + assert.Equal(t, c.BindAddr, "127.0.0.1:4003", "") + assert.Equal(t, c.Peers, []string{"coreos.com:4001", "coreos.com:4002"}, "") + assert.Equal(t, c.PeersFile, "/tmp/peers", "") assert.Equal(t, c.MaxClusterSize, 10, "") assert.Equal(t, c.MaxResultBuffer, 512, "") assert.Equal(t, c.MaxRetryAttempts, 5, "") @@ -108,27 +106,40 @@ func TestConfigEnv(t *testing.T) { assert.Equal(t, c.Snapshot, true, "") assert.Equal(t, c.Verbose, true, "") assert.Equal(t, c.VeryVerbose, true, "") - assert.Equal(t, c.WebURL, "/web", "") - assert.Equal(t, c.Peer.AdvertisedUrl, "127.0.0.1:7002", "") + assert.Equal(t, c.Peer.Addr, "127.0.0.1:7002", "") assert.Equal(t, c.Peer.CAFile, "/tmp/peer/file.ca", "") assert.Equal(t, c.Peer.CertFile, "/tmp/peer/file.cert", "") assert.Equal(t, c.Peer.KeyFile, "/tmp/peer/file.key", "") - assert.Equal(t, c.Peer.ListenHost, "127.0.0.1:7003", "") + assert.Equal(t, c.Peer.BindAddr, "127.0.0.1:7003", "") +} + +// Ensures that the "force config" flag can be parsed. +func TestConfigForceFlag(t *testing.T) { + c := NewConfig() + assert.Nil(t, c.LoadFlags([]string{"-force"}), "") + assert.True(t, c.Force) +} + +// Ensures that the abbreviated "force config" flag can be parsed. +func TestConfigAbbreviatedForceFlag(t *testing.T) { + c := NewConfig() + assert.Nil(t, c.LoadFlags([]string{"-f"}), "") + assert.True(t, c.Force) } // Ensures that a the advertised url can be parsed from the environment. -func TestConfigAdvertisedUrlEnv(t *testing.T) { - withEnv("ETCD_ADVERTISED_URL", "127.0.0.1:4002", func(c *Config) { +func TestConfigAddrEnv(t *testing.T) { + withEnv("ETCD_ADDR", "127.0.0.1:4002", func(c *Config) { assert.Nil(t, c.LoadEnv(), "") - assert.Equal(t, c.AdvertisedUrl, "127.0.0.1:4002", "") + assert.Equal(t, c.Addr, "127.0.0.1:4002", "") }) } // Ensures that a the advertised flag can be parsed. -func TestConfigAdvertisedUrlFlag(t *testing.T) { +func TestConfigAddrFlag(t *testing.T) { c := NewConfig() - assert.Nil(t, c.LoadFlags([]string{"-c", "127.0.0.1:4002"}), "") - assert.Equal(t, c.AdvertisedUrl, "127.0.0.1:4002", "") + assert.Nil(t, c.LoadFlags([]string{"-addr", "127.0.0.1:4002"}), "") + assert.Equal(t, c.Addr, "127.0.0.1:4002", "") } // Ensures that a the CA file can be parsed from the environment. @@ -142,7 +153,7 @@ func TestConfigCAFileEnv(t *testing.T) { // Ensures that a the CA file flag can be parsed. func TestConfigCAFileFlag(t *testing.T) { c := NewConfig() - assert.Nil(t, c.LoadFlags([]string{"-clientCAFile", "/tmp/file.ca"}), "") + assert.Nil(t, c.LoadFlags([]string{"-ca-file", "/tmp/file.ca"}), "") assert.Equal(t, c.CAFile, "/tmp/file.ca", "") } @@ -157,7 +168,7 @@ func TestConfigCertFileEnv(t *testing.T) { // Ensures that a the Cert file flag can be parsed. func TestConfigCertFileFlag(t *testing.T) { c := NewConfig() - assert.Nil(t, c.LoadFlags([]string{"-clientCert", "/tmp/file.cert"}), "") + assert.Nil(t, c.LoadFlags([]string{"-cert-file", "/tmp/file.cert"}), "") assert.Equal(t, c.CertFile, "/tmp/file.cert", "") } @@ -172,53 +183,53 @@ func TestConfigKeyFileEnv(t *testing.T) { // Ensures that a the Key file flag can be parsed. func TestConfigKeyFileFlag(t *testing.T) { c := NewConfig() - assert.Nil(t, c.LoadFlags([]string{"-clientKey", "/tmp/file.key"}), "") + assert.Nil(t, c.LoadFlags([]string{"-key-file", "/tmp/file.key"}), "") assert.Equal(t, c.KeyFile, "/tmp/file.key", "") } // Ensures that a the Listen Host can be parsed from the environment. -func TestConfigListenHostEnv(t *testing.T) { - withEnv("ETCD_LISTEN_HOST", "127.0.0.1:4003", func(c *Config) { +func TestConfigBindAddrEnv(t *testing.T) { + withEnv("ETCD_BIND_ADDR", "127.0.0.1:4003", func(c *Config) { assert.Nil(t, c.LoadEnv(), "") - assert.Equal(t, c.ListenHost, "127.0.0.1:4003", "") + assert.Equal(t, c.BindAddr, "127.0.0.1:4003", "") }) } // Ensures that a the Listen Host file flag can be parsed. -func TestConfigListenHostFlag(t *testing.T) { +func TestConfigBindAddrFlag(t *testing.T) { c := NewConfig() - assert.Nil(t, c.LoadFlags([]string{"-cl", "127.0.0.1:4003"}), "") - assert.Equal(t, c.ListenHost, "127.0.0.1:4003", "") + assert.Nil(t, c.LoadFlags([]string{"-bind-addr", "127.0.0.1:4003"}), "") + assert.Equal(t, c.BindAddr, "127.0.0.1:4003", "") } -// Ensures that the Machines can be parsed from the environment. -func TestConfigMachinesEnv(t *testing.T) { - withEnv("ETCD_MACHINES", "coreos.com:4001,coreos.com:4002", func(c *Config) { +// Ensures that the peers can be parsed from the environment. +func TestConfigPeersEnv(t *testing.T) { + withEnv("ETCD_PEERS", "coreos.com:4001,coreos.com:4002", func(c *Config) { assert.Nil(t, c.LoadEnv(), "") - assert.Equal(t, c.Machines, []string{"coreos.com:4001", "coreos.com:4002"}, "") + assert.Equal(t, c.Peers, []string{"coreos.com:4001", "coreos.com:4002"}, "") }) } -// Ensures that a the Machines flag can be parsed. -func TestConfigMachinesFlag(t *testing.T) { +// Ensures that a the Peers flag can be parsed. +func TestConfigPeersFlag(t *testing.T) { c := NewConfig() - assert.Nil(t, c.LoadFlags([]string{"-C", "coreos.com:4001,coreos.com:4002"}), "") - assert.Equal(t, c.Machines, []string{"coreos.com:4001", "coreos.com:4002"}, "") + assert.Nil(t, c.LoadFlags([]string{"-peers", "coreos.com:4001,coreos.com:4002"}), "") + assert.Equal(t, c.Peers, []string{"coreos.com:4001", "coreos.com:4002"}, "") } -// Ensures that the Machines File can be parsed from the environment. -func TestConfigMachinesFileEnv(t *testing.T) { - withEnv("ETCD_MACHINES_FILE", "/tmp/machines", func(c *Config) { +// Ensures that the Peers File can be parsed from the environment. +func TestConfigPeersFileEnv(t *testing.T) { + withEnv("ETCD_PEERS_FILE", "/tmp/peers", func(c *Config) { assert.Nil(t, c.LoadEnv(), "") - assert.Equal(t, c.MachinesFile, "/tmp/machines", "") + assert.Equal(t, c.PeersFile, "/tmp/peers", "") }) } -// Ensures that a the Machines File flag can be parsed. -func TestConfigMachinesFileFlag(t *testing.T) { +// Ensures that a the Peers File flag can be parsed. +func TestConfigPeersFileFlag(t *testing.T) { c := NewConfig() - assert.Nil(t, c.LoadFlags([]string{"-CF", "/tmp/machines"}), "") - assert.Equal(t, c.MachinesFile, "/tmp/machines", "") + assert.Nil(t, c.LoadFlags([]string{"-peers-file", "/tmp/peers"}), "") + assert.Equal(t, c.PeersFile, "/tmp/peers", "") } // Ensures that the Max Cluster Size can be parsed from the environment. @@ -232,7 +243,7 @@ func TestConfigMaxClusterSizeEnv(t *testing.T) { // Ensures that a the Max Cluster Size flag can be parsed. func TestConfigMaxClusterSizeFlag(t *testing.T) { c := NewConfig() - assert.Nil(t, c.LoadFlags([]string{"-maxsize", "5"}), "") + assert.Nil(t, c.LoadFlags([]string{"-max-cluster-size", "5"}), "") assert.Equal(t, c.MaxClusterSize, 5, "") } @@ -247,7 +258,7 @@ func TestConfigMaxResultBufferEnv(t *testing.T) { // Ensures that a the Max Result Buffer flag can be parsed. func TestConfigMaxResultBufferFlag(t *testing.T) { c := NewConfig() - assert.Nil(t, c.LoadFlags([]string{"-m", "512"}), "") + assert.Nil(t, c.LoadFlags([]string{"-max-result-buffer", "512"}), "") assert.Equal(t, c.MaxResultBuffer, 512, "") } @@ -262,7 +273,7 @@ func TestConfigMaxRetryAttemptsEnv(t *testing.T) { // Ensures that a the Max Retry Attempts flag can be parsed. func TestConfigMaxRetryAttemptsFlag(t *testing.T) { c := NewConfig() - assert.Nil(t, c.LoadFlags([]string{"-r", "10"}), "") + assert.Nil(t, c.LoadFlags([]string{"-max-retry-attempts", "10"}), "") assert.Equal(t, c.MaxRetryAttempts, 10, "") } @@ -277,7 +288,7 @@ func TestConfigNameEnv(t *testing.T) { // Ensures that a the Name flag can be parsed. func TestConfigNameFlag(t *testing.T) { c := NewConfig() - assert.Nil(t, c.LoadFlags([]string{"-n", "test-name"}), "") + assert.Nil(t, c.LoadFlags([]string{"-name", "test-name"}), "") assert.Equal(t, c.Name, "test-name", "") } @@ -326,34 +337,19 @@ func TestConfigVeryVerboseFlag(t *testing.T) { assert.Equal(t, c.VeryVerbose, true, "") } -// Ensures that Web URL can be parsed from the environment. -func TestConfigWebURLEnv(t *testing.T) { - withEnv("ETCD_WEB_URL", "/web", func(c *Config) { - assert.Nil(t, c.LoadEnv(), "") - assert.Equal(t, c.WebURL, "/web", "") - }) -} - -// Ensures that a the Web URL flag can be parsed. -func TestConfigWebURLFlag(t *testing.T) { - c := NewConfig() - assert.Nil(t, c.LoadFlags([]string{"-w", "/web"}), "") - assert.Equal(t, c.WebURL, "/web", "") -} - // Ensures that the Peer Advertised URL can be parsed from the environment. -func TestConfigPeerAdvertisedUrlEnv(t *testing.T) { - withEnv("ETCD_PEER_ADVERTISED_URL", "localhost:7002", func(c *Config) { +func TestConfigPeerAddrEnv(t *testing.T) { + withEnv("ETCD_PEER_ADDR", "localhost:7002", func(c *Config) { assert.Nil(t, c.LoadEnv(), "") - assert.Equal(t, c.Peer.AdvertisedUrl, "localhost:7002", "") + assert.Equal(t, c.Peer.Addr, "localhost:7002", "") }) } // Ensures that a the Peer Advertised URL flag can be parsed. -func TestConfigPeerAdvertisedUrlFlag(t *testing.T) { +func TestConfigPeerAddrFlag(t *testing.T) { c := NewConfig() - assert.Nil(t, c.LoadFlags([]string{"-s", "localhost:7002"}), "") - assert.Equal(t, c.Peer.AdvertisedUrl, "localhost:7002", "") + assert.Nil(t, c.LoadFlags([]string{"-peer-addr", "localhost:7002"}), "") + assert.Equal(t, c.Peer.Addr, "localhost:7002", "") } // Ensures that the Peer CA File can be parsed from the environment. @@ -367,7 +363,7 @@ func TestConfigPeerCAFileEnv(t *testing.T) { // Ensures that a the Peer CA file flag can be parsed. func TestConfigPeerCAFileFlag(t *testing.T) { c := NewConfig() - assert.Nil(t, c.LoadFlags([]string{"-serverCAFile", "/tmp/peer/file.ca"}), "") + assert.Nil(t, c.LoadFlags([]string{"-peer-ca-file", "/tmp/peer/file.ca"}), "") assert.Equal(t, c.Peer.CAFile, "/tmp/peer/file.ca", "") } @@ -382,7 +378,7 @@ func TestConfigPeerCertFileEnv(t *testing.T) { // Ensures that a the Cert file flag can be parsed. func TestConfigPeerCertFileFlag(t *testing.T) { c := NewConfig() - assert.Nil(t, c.LoadFlags([]string{"-serverCert", "/tmp/peer/file.cert"}), "") + assert.Nil(t, c.LoadFlags([]string{"-peer-cert-file", "/tmp/peer/file.cert"}), "") assert.Equal(t, c.Peer.CertFile, "/tmp/peer/file.cert", "") } @@ -397,63 +393,178 @@ func TestConfigPeerKeyFileEnv(t *testing.T) { // Ensures that a the Peer Key file flag can be parsed. func TestConfigPeerKeyFileFlag(t *testing.T) { c := NewConfig() - assert.Nil(t, c.LoadFlags([]string{"-serverKey", "/tmp/peer/file.key"}), "") + assert.Nil(t, c.LoadFlags([]string{"-peer-key-file", "/tmp/peer/file.key"}), "") assert.Equal(t, c.Peer.KeyFile, "/tmp/peer/file.key", "") } // Ensures that the Peer Listen Host can be parsed from the environment. -func TestConfigPeerListenHostEnv(t *testing.T) { - withEnv("ETCD_PEER_LISTEN_HOST", "localhost:7004", func(c *Config) { +func TestConfigPeerBindAddrEnv(t *testing.T) { + withEnv("ETCD_PEER_BIND_ADDR", "localhost:7004", func(c *Config) { assert.Nil(t, c.LoadEnv(), "") - assert.Equal(t, c.Peer.ListenHost, "localhost:7004", "") + assert.Equal(t, c.Peer.BindAddr, "localhost:7004", "") }) } // Ensures that a the Peer Listen Host file flag can be parsed. -func TestConfigPeerListenHostFlag(t *testing.T) { +func TestConfigPeerBindAddrFlag(t *testing.T) { c := NewConfig() - assert.Nil(t, c.LoadFlags([]string{"-sl", "127.0.0.1:4003"}), "") - assert.Equal(t, c.Peer.ListenHost, "127.0.0.1:4003", "") + assert.Nil(t, c.LoadFlags([]string{"-peer-bind-addr", "127.0.0.1:4003"}), "") + assert.Equal(t, c.Peer.BindAddr, "127.0.0.1:4003", "") } - // Ensures that a system config field is overridden by a custom config field. func TestConfigCustomConfigOverrideSystemConfig(t *testing.T) { - system := `advertised_url = "127.0.0.1:5000"` - custom := `advertised_url = "127.0.0.1:6000"` + system := `addr = "127.0.0.1:5000"` + custom := `addr = "127.0.0.1:6000"` withTempFile(system, func(p1 string) { withTempFile(custom, func(p2 string) { c := NewConfig() c.SystemPath = p1 assert.Nil(t, c.Load([]string{"-config", p2}), "") - assert.Equal(t, c.AdvertisedUrl, "http://127.0.0.1:6000", "") + assert.Equal(t, c.Addr, "http://127.0.0.1:6000", "") }) }) } // Ensures that a custom config field is overridden by an environment variable. func TestConfigEnvVarOverrideCustomConfig(t *testing.T) { - os.Setenv("ETCD_PEER_ADVERTISED_URL", "127.0.0.1:8000") - defer os.Setenv("ETCD_PEER_ADVERTISED_URL", "") + os.Setenv("ETCD_PEER_ADDR", "127.0.0.1:8000") + defer os.Setenv("ETCD_PEER_ADDR", "") - custom := `[peer]`+"\n"+`advertised_url = "127.0.0.1:9000"` + custom := `[peer]` + "\n" + `advertised_url = "127.0.0.1:9000"` withTempFile(custom, func(path string) { c := NewConfig() c.SystemPath = "" assert.Nil(t, c.Load([]string{"-config", path}), "") - assert.Equal(t, c.Peer.AdvertisedUrl, "http://127.0.0.1:8000", "") + assert.Equal(t, c.Peer.Addr, "http://127.0.0.1:8000", "") }) } // Ensures that an environment variable field is overridden by a command line argument. func TestConfigCLIArgsOverrideEnvVar(t *testing.T) { - os.Setenv("ETCD_ADVERTISED_URL", "127.0.0.1:1000") - defer os.Setenv("ETCD_ADVERTISED_URL", "") + os.Setenv("ETCD_ADDR", "127.0.0.1:1000") + defer os.Setenv("ETCD_ADDR", "") c := NewConfig() c.SystemPath = "" - assert.Nil(t, c.Load([]string{"-c", "127.0.0.1:2000"}), "") - assert.Equal(t, c.AdvertisedUrl, "http://127.0.0.1:2000", "") + assert.Nil(t, c.Load([]string{"-addr", "127.0.0.1:2000"}), "") + assert.Equal(t, c.Addr, "http://127.0.0.1:2000", "") +} + +//-------------------------------------- +// DEPRECATED (v1) +//-------------------------------------- + +func TestConfigDeprecatedAddrFlag(t *testing.T) { + c := NewConfig() + err := c.LoadDeprecatedFlags([]string{"-c", "127.0.0.1:4002"}) + assert.Equal(t, err.Error(), "[deprecated] use -addr, not -c", "") + assert.Equal(t, c.Addr, "127.0.0.1:4002", "") +} + +func TestConfigDeprecatedBindAddrFlag(t *testing.T) { + c := NewConfig() + err := c.LoadDeprecatedFlags([]string{"-cl", "127.0.0.1:4003"}) + assert.Equal(t, err.Error(), "[deprecated] use -bind-addr, not -cl", "") + assert.Equal(t, c.BindAddr, "127.0.0.1:4003", "") +} + +func TestConfigDeprecatedCAFileFlag(t *testing.T) { + c := NewConfig() + err := c.LoadDeprecatedFlags([]string{"-clientCAFile", "/tmp/file.ca"}) + assert.Equal(t, err.Error(), "[deprecated] use -ca-file, not -clientCAFile", "") + assert.Equal(t, c.CAFile, "/tmp/file.ca", "") +} + +func TestConfigDeprecatedCertFileFlag(t *testing.T) { + c := NewConfig() + err := c.LoadDeprecatedFlags([]string{"-clientCert", "/tmp/file.cert"}) + assert.Equal(t, err.Error(), "[deprecated] use -cert-file, not -clientCert", "") + assert.Equal(t, c.CertFile, "/tmp/file.cert", "") +} + +func TestConfigDeprecatedKeyFileFlag(t *testing.T) { + c := NewConfig() + err := c.LoadDeprecatedFlags([]string{"-clientKey", "/tmp/file.key"}) + assert.Equal(t, err.Error(), "[deprecated] use -key-file, not -clientKey", "") + assert.Equal(t, c.KeyFile, "/tmp/file.key", "") +} + +func TestConfigDeprecatedPeersFlag(t *testing.T) { + c := NewConfig() + err := c.LoadDeprecatedFlags([]string{"-C", "coreos.com:4001,coreos.com:4002"}) + assert.Equal(t, err.Error(), "[deprecated] use -peers, not -C", "") + assert.Equal(t, c.Peers, []string{"coreos.com:4001", "coreos.com:4002"}, "") +} + +func TestConfigDeprecatedPeersFileFlag(t *testing.T) { + c := NewConfig() + err := c.LoadDeprecatedFlags([]string{"-CF", "/tmp/machines"}) + assert.Equal(t, err.Error(), "[deprecated] use -peers-file, not -CF", "") + assert.Equal(t, c.PeersFile, "/tmp/machines", "") +} + +func TestConfigDeprecatedMaxClusterSizeFlag(t *testing.T) { + c := NewConfig() + err := c.LoadDeprecatedFlags([]string{"-maxsize", "5"}) + assert.Equal(t, err.Error(), "[deprecated] use -max-cluster-size, not -maxsize", "") + assert.Equal(t, c.MaxClusterSize, 5, "") +} + +func TestConfigDeprecatedMaxResultBufferFlag(t *testing.T) { + c := NewConfig() + err := c.LoadDeprecatedFlags([]string{"-m", "512"}) + assert.Equal(t, err.Error(), "[deprecated] use -max-result-buffer, not -m", "") + assert.Equal(t, c.MaxResultBuffer, 512, "") +} + +func TestConfigDeprecatedMaxRetryAttemptsFlag(t *testing.T) { + c := NewConfig() + err := c.LoadDeprecatedFlags([]string{"-r", "10"}) + assert.Equal(t, err.Error(), "[deprecated] use -max-retry-attempts, not -r", "") + assert.Equal(t, c.MaxRetryAttempts, 10, "") +} + +func TestConfigDeprecatedNameFlag(t *testing.T) { + c := NewConfig() + err := c.LoadDeprecatedFlags([]string{"-n", "test-name"}) + assert.Equal(t, err.Error(), "[deprecated] use -name, not -n", "") + assert.Equal(t, c.Name, "test-name", "") +} + +func TestConfigDeprecatedPeerAddrFlag(t *testing.T) { + c := NewConfig() + err := c.LoadDeprecatedFlags([]string{"-s", "localhost:7002"}) + assert.Equal(t, err.Error(), "[deprecated] use -peer-addr, not -s", "") + assert.Equal(t, c.Peer.Addr, "localhost:7002", "") +} + +func TestConfigDeprecatedPeerBindAddrFlag(t *testing.T) { + c := NewConfig() + err := c.LoadDeprecatedFlags([]string{"-sl", "127.0.0.1:4003"}) + assert.Equal(t, err.Error(), "[deprecated] use -peer-bind-addr, not -sl", "") + assert.Equal(t, c.Peer.BindAddr, "127.0.0.1:4003", "") +} + +func TestConfigDeprecatedPeerCAFileFlag(t *testing.T) { + c := NewConfig() + err := c.LoadDeprecatedFlags([]string{"-serverCAFile", "/tmp/peer/file.ca"}) + assert.Equal(t, err.Error(), "[deprecated] use -peer-ca-file, not -serverCAFile", "") + assert.Equal(t, c.Peer.CAFile, "/tmp/peer/file.ca", "") +} + +func TestConfigDeprecatedPeerCertFileFlag(t *testing.T) { + c := NewConfig() + err := c.LoadDeprecatedFlags([]string{"-serverCert", "/tmp/peer/file.cert"}) + assert.Equal(t, err.Error(), "[deprecated] use -peer-cert-file, not -serverCert", "") + assert.Equal(t, c.Peer.CertFile, "/tmp/peer/file.cert", "") +} + +func TestConfigDeprecatedPeerKeyFileFlag(t *testing.T) { + c := NewConfig() + err := c.LoadDeprecatedFlags([]string{"-serverKey", "/tmp/peer/file.key"}) + assert.Equal(t, err.Error(), "[deprecated] use -peer-key-file, not -serverKey", "") + assert.Equal(t, c.Peer.KeyFile, "/tmp/peer/file.key", "") } diff --git a/server/info.go b/server/info.go index 434f24a03..7e05debe4 100644 --- a/server/info.go +++ b/server/info.go @@ -8,7 +8,6 @@ type Info struct { RaftURL string `json:"raftURL"` EtcdURL string `json:"etcdURL"` - WebURL string `json:"webURL"` RaftListenHost string `json:"raftListenHost"` EtcdListenHost string `json:"etcdListenHost"` @@ -16,4 +15,3 @@ type Info struct { RaftTLS TLSInfo `json:"raftTLS"` EtcdTLS TLSInfo `json:"etcdTLS"` } - diff --git a/server/join_command.go b/server/join_command.go index 6e7f7471b..e1b181e6b 100644 --- a/server/join_command.go +++ b/server/join_command.go @@ -46,18 +46,18 @@ func (c *JoinCommand) Apply(server raft.Server) (interface{}, error) { // Make sure we're not getting a cached value from the registry. ps.registry.Invalidate(c.Name) - // Check if the join command is from a previous machine, who lost all its previous log. + // Check if the join command is from a previous peer, who lost all its previous log. if _, ok := ps.registry.ClientURL(c.Name); ok { return b, nil } - // Check machine number in the cluster + // Check peer number in the cluster if ps.registry.Count() == ps.MaxClusterSize { log.Debug("Reject join request from ", c.Name) - return []byte{0}, etcdErr.NewError(etcdErr.EcodeNoMoreMachine, "", server.CommitIndex()) + return []byte{0}, etcdErr.NewError(etcdErr.EcodeNoMorePeer, "", server.CommitIndex()) } - // Add to shared machine registry. + // Add to shared peer registry. ps.registry.Register(c.Name, c.RaftURL, c.EtcdURL) // Add peer in raft diff --git a/server/peer_server.go b/server/peer_server.go index 018c48110..20e9051f3 100644 --- a/server/peer_server.go +++ b/server/peer_server.go @@ -28,7 +28,7 @@ type PeerServer struct { joinIndex uint64 name string url string - listenHost string + bindAddr string tlsConf *TLSConfig tlsInfo *TLSInfo followersStats *raftFollowersStats @@ -53,16 +53,16 @@ type snapshotConf struct { writesThr uint64 } -func NewPeerServer(name string, path string, url string, listenHost string, tlsConf *TLSConfig, tlsInfo *TLSInfo, registry *Registry, store store.Store, snapCount int) *PeerServer { +func NewPeerServer(name string, path string, url string, bindAddr string, tlsConf *TLSConfig, tlsInfo *TLSInfo, registry *Registry, store store.Store, snapshotCount int) *PeerServer { s := &PeerServer{ - name: name, - url: url, - listenHost: listenHost, - tlsConf: tlsConf, - tlsInfo: tlsInfo, - registry: registry, - store: store, - snapConf: &snapshotConf{time.Second * 3, 0, uint64(snapCount)}, + name: name, + url: url, + bindAddr: bindAddr, + tlsConf: tlsConf, + tlsInfo: tlsInfo, + registry: registry, + store: store, + snapConf: &snapshotConf{time.Second * 3, 0, uint64(snapshotCount)}, followersStats: &raftFollowersStats{ Leader: name, Followers: make(map[string]*raftFollowerStats), @@ -130,7 +130,7 @@ func (s *PeerServer) ListenAndServe(snapshot bool, cluster []string) error { } ok := s.joinCluster(cluster) if !ok { - log.Warn("the entire cluster is down! this machine will restart the cluster.") + log.Warn("the entire cluster is down! this peer will restart the cluster.") } log.Debugf("%s restart as a follower", s.name) @@ -228,23 +228,23 @@ func (s *PeerServer) startAsFollower(cluster []string) { if ok { return } - log.Warnf("cannot join to cluster via given machines, retry in %d seconds", RetryInterval) + log.Warnf("cannot join to cluster via given peers, retry in %d seconds", RetryInterval) time.Sleep(time.Second * RetryInterval) } - log.Fatalf("Cannot join the cluster via given machines after %x retries", s.RetryTimes) + log.Fatalf("Cannot join the cluster via given peers after %x retries", s.RetryTimes) } // Start to listen and response raft command func (s *PeerServer) startTransport(scheme string, tlsConf tls.Config) error { - log.Infof("raft server [name %s, listen on %s, advertised url %s]", s.name, s.listenHost, s.url) + log.Infof("raft server [name %s, listen on %s, advertised url %s]", s.name, s.bindAddr, s.url) router := mux.NewRouter() s.httpServer = &http.Server{ Handler: router, TLSConfig: &tlsConf, - Addr: s.listenHost, + Addr: s.bindAddr, } // internal commands @@ -312,14 +312,14 @@ func (s *PeerServer) Upgradable() error { } func (s *PeerServer) joinCluster(cluster []string) bool { - for _, machine := range cluster { - if len(machine) == 0 { + for _, peer := range cluster { + if len(peer) == 0 { continue } - err := s.joinByMachine(s.raftServer, machine, s.tlsConf.Scheme) + err := s.joinByPeer(s.raftServer, peer, s.tlsConf.Scheme) if err == nil { - log.Debugf("%s success join to the cluster via machine %s", s.name, machine) + log.Debugf("%s success join to the cluster via peer %s", s.name, peer) return true } else { @@ -327,21 +327,21 @@ func (s *PeerServer) joinCluster(cluster []string) bool { log.Fatal(err) } - log.Debugf("cannot join to cluster via machine %s %s", machine, err) + log.Debugf("cannot join to cluster via peer %s %s", peer, err) } } return false } -// Send join requests to machine. -func (s *PeerServer) joinByMachine(server raft.Server, machine string, scheme string) error { +// Send join requests to peer. +func (s *PeerServer) joinByPeer(server raft.Server, peer string, scheme string) error { var b bytes.Buffer // t must be ok t, _ := server.Transporter().(*transporter) // Our version must match the leaders version - versionURL := url.URL{Host: machine, Scheme: scheme, Path: "/version"} + versionURL := url.URL{Host: peer, Scheme: scheme, Path: "/version"} version, err := getVersion(t, versionURL) if err != nil { return fmt.Errorf("Error during join version check: %v", err) @@ -352,7 +352,7 @@ func (s *PeerServer) joinByMachine(server raft.Server, machine string, scheme st json.NewEncoder(&b).Encode(NewJoinCommand(store.MinVersion(), store.MaxVersion(), server.Name(), s.url, s.server.URL())) - joinURL := url.URL{Host: machine, Scheme: scheme, Path: "/join"} + joinURL := url.URL{Host: peer, Scheme: scheme, Path: "/join"} log.Debugf("Send Join Request to %s", joinURL.String()) @@ -379,7 +379,7 @@ func (s *PeerServer) joinByMachine(server raft.Server, machine string, scheme st resp, req, err = t.Post(address, &b) } else if resp.StatusCode == http.StatusBadRequest { - log.Debug("Reach max number machines in the cluster") + log.Debug("Reach max number peers in the cluster") decoder := json.NewDecoder(resp.Body) err := &etcdErr.Error{} decoder.Decode(err) diff --git a/server/registry.go b/server/registry.go index b7d238099..d1d98d9ed 100644 --- a/server/registry.go +++ b/server/registry.go @@ -12,7 +12,7 @@ import ( "github.com/coreos/etcd/store" ) -// The location of the machine URL data. +// The location of the peer URL data. const RegistryKey = "/_etcd/machines" // The Registry stores URL information for nodes. @@ -168,7 +168,7 @@ func (r *Registry) load(name string) { // Parse as a query string. m, err := url.ParseQuery(e.Value) if err != nil { - panic(fmt.Sprintf("Failed to parse machines entry: %s", name)) + panic(fmt.Sprintf("Failed to parse peers entry: %s", name)) } // Create node. diff --git a/server/server.go b/server/server.go index c31aa3c0f..28ac842d8 100644 --- a/server/server.go +++ b/server/server.go @@ -36,12 +36,12 @@ type Server struct { } // Creates a new Server. -func New(name string, urlStr string, listenHost string, tlsConf *TLSConfig, tlsInfo *TLSInfo, peerServer *PeerServer, registry *Registry, store store.Store) *Server { +func New(name string, urlStr string, bindAddr string, tlsConf *TLSConfig, tlsInfo *TLSInfo, peerServer *PeerServer, registry *Registry, store store.Store) *Server { s := &Server{ Server: http.Server{ Handler: mux.NewRouter(), TLSConfig: &tlsConf.Server, - Addr: listenHost, + Addr: bindAddr, }, name: name, store: store, @@ -102,7 +102,8 @@ func (s *Server) installV1() { s.handleFuncV1("/v1/keys/{key:.*}", v1.DeleteKeyHandler).Methods("DELETE") s.handleFuncV1("/v1/watch/{key:.*}", v1.WatchKeyHandler).Methods("GET", "POST") s.handleFunc("/v1/leader", s.GetLeaderHandler).Methods("GET") - s.handleFunc("/v1/machines", s.GetMachinesHandler).Methods("GET") + s.handleFunc("/v1/machines", s.GetPeersHandler).Methods("GET") + s.handleFunc("/v1/peers", s.GetPeersHandler).Methods("GET") s.handleFunc("/v1/stats/self", s.GetStatsHandler).Methods("GET") s.handleFunc("/v1/stats/leader", s.GetLeaderStatsHandler).Methods("GET") s.handleFunc("/v1/stats/store", s.GetStoreStatsHandler).Methods("GET") @@ -114,7 +115,8 @@ func (s *Server) installV2() { s.handleFuncV2("/v2/keys/{key:.*}", v2.PutHandler).Methods("PUT") s.handleFuncV2("/v2/keys/{key:.*}", v2.DeleteHandler).Methods("DELETE") s.handleFunc("/v2/leader", s.GetLeaderHandler).Methods("GET") - s.handleFunc("/v2/machines", s.GetMachinesHandler).Methods("GET") + s.handleFunc("/v2/machines", s.GetPeersHandler).Methods("GET") + s.handleFunc("/v2/peers", s.GetPeersHandler).Methods("GET") s.handleFunc("/v2/stats/self", s.GetStatsHandler).Methods("GET") s.handleFunc("/v2/stats/leader", s.GetLeaderStatsHandler).Methods("GET") s.handleFunc("/v2/stats/store", s.GetStoreStatsHandler).Methods("GET") @@ -341,11 +343,11 @@ func (s *Server) GetLeaderHandler(w http.ResponseWriter, req *http.Request) erro return nil } -// Handler to return all the known machines in the current cluster. -func (s *Server) GetMachinesHandler(w http.ResponseWriter, req *http.Request) error { - machines := s.registry.ClientURLs(s.peerServer.RaftServer().Leader(), s.name) +// Handler to return all the known peers in the current cluster. +func (s *Server) GetPeersHandler(w http.ResponseWriter, req *http.Request) error { + peers := s.registry.ClientURLs(s.peerServer.RaftServer().Leader(), s.name) w.WriteHeader(http.StatusOK) - w.Write([]byte(strings.Join(machines, ", "))) + w.Write([]byte(strings.Join(peers, ", "))) return nil } diff --git a/server/tls_info.go b/server/tls_info.go index 1867ef44f..1048f21e7 100644 --- a/server/tls_info.go +++ b/server/tls_info.go @@ -32,7 +32,7 @@ func (info TLSInfo) Config() (TLSConfig, error) { tlsCert, err := tls.LoadX509KeyPair(info.CertFile, info.KeyFile) if err != nil { - return t, err + return t, err } t.Scheme = "https" diff --git a/server/util.go b/server/util.go index bae2eaa72..d124a1fc0 100644 --- a/server/util.go +++ b/server/util.go @@ -37,10 +37,10 @@ func redirect(hostname string, w http.ResponseWriter, req *http.Request) { // slice of the substrings between the separator with all leading and trailing // white space removed, as defined by Unicode. func trimsplit(s, sep string) []string { - raw := strings.Split(s, ",") - trimmed := make([]string, 0) - for _, r := range raw { - trimmed = append(trimmed, strings.TrimSpace(r)) - } - return trimmed + raw := strings.Split(s, ",") + trimmed := make([]string, 0) + for _, r := range raw { + trimmed = append(trimmed, strings.TrimSpace(r)) + } + return trimmed } diff --git a/tests/functional/internal_version_test.go b/tests/functional/internal_version_test.go index 37ac0d532..edc8fc098 100644 --- a/tests/functional/internal_version_test.go +++ b/tests/functional/internal_version_test.go @@ -31,7 +31,7 @@ func TestInternalVersion(t *testing.T) { procAttr := new(os.ProcAttr) procAttr.Files = []*os.File{nil, os.Stdout, os.Stderr} - args := []string{"etcd", "-n=node1", "-f", "-d=/tmp/node1", "-C=" + fakeURL.Host} + args := []string{"etcd", "-name=node1", "-f", "-data-dir=/tmp/node1", "-peers=" + fakeURL.Host} process, err := os.StartProcess(EtcdBinPath, args, procAttr) if err != nil { @@ -53,4 +53,3 @@ func TestInternalVersion(t *testing.T) { return } } - diff --git a/tests/functional/kill_leader_test.go b/tests/functional/kill_leader_test.go index ad9113695..df23cdfa7 100644 --- a/tests/functional/kill_leader_test.go +++ b/tests/functional/kill_leader_test.go @@ -55,9 +55,8 @@ func TestKillLeader(t *testing.T) { totalTime += take avgTime := totalTime / (time.Duration)(i+1) fmt.Println("Total time:", totalTime, "; Avg time:", avgTime) - + etcds[num], err = os.StartProcess(EtcdBinPath, argGroup[num], procAttr) } stop <- true } - diff --git a/tests/functional/kill_random_test.go b/tests/functional/kill_random_test.go index 4fc3c1171..d5f8efc0a 100644 --- a/tests/functional/kill_random_test.go +++ b/tests/functional/kill_random_test.go @@ -8,8 +8,8 @@ import ( "time" ) -// TestKillRandom kills random machines in the cluster and -// restart them after all other machines agree on the same leader +// TestKillRandom kills random peers in the cluster and +// restart them after all other peers agree on the same leader func TestKillRandom(t *testing.T) { procAttr := new(os.ProcAttr) procAttr.Files = []*os.File{nil, os.Stdout, os.Stderr} @@ -73,4 +73,3 @@ func TestKillRandom(t *testing.T) { stop <- true } - diff --git a/tests/functional/multi_node_kill_one_test.go b/tests/functional/multi_node_kill_one_test.go index 725d54b6c..96537ba39 100644 --- a/tests/functional/multi_node_kill_one_test.go +++ b/tests/functional/multi_node_kill_one_test.go @@ -55,4 +55,3 @@ func TestMultiNodeKillOne(t *testing.T) { stop <- true <-stop } - diff --git a/tests/functional/node1.etcd/conf b/tests/functional/node1.etcd/conf new file mode 100644 index 000000000..d6da4d992 --- /dev/null +++ b/tests/functional/node1.etcd/conf @@ -0,0 +1 @@ +{"commitIndex":43,"peers":[{"name":"node2","connectionString":""},{"name":"node3","connectionString":""},{"name":"node4","connectionString":""},{"name":"node5","connectionString":""},{"name":"node6","connectionString":""},{"name":"node7","connectionString":""},{"name":"node9","connectionString":""},{"name":"node8","connectionString":""}]} \ No newline at end of file diff --git a/tests/functional/node1.etcd/info b/tests/functional/node1.etcd/info new file mode 100644 index 000000000..5d6ce814a --- /dev/null +++ b/tests/functional/node1.etcd/info @@ -0,0 +1 @@ +{"name":"node1","raftURL":"http://127.0.0.1:7001","etcdURL":"http://127.0.0.1:4001","raftListenHost":"127.0.0.1:7001","etcdListenHost":"127.0.0.1:4001","raftTLS":{"CertFile":"","KeyFile":"","CAFile":""},"etcdTLS":{"CertFile":"","KeyFile":"","CAFile":""}} diff --git a/tests/functional/node1.etcd/log b/tests/functional/node1.etcd/log new file mode 100644 index 000000000..8d992569c Binary files /dev/null and b/tests/functional/node1.etcd/log differ diff --git a/tests/functional/remove_node_test.go b/tests/functional/remove_node_test.go index a9490cdcc..55149cc36 100644 --- a/tests/functional/remove_node_test.go +++ b/tests/functional/remove_node_test.go @@ -42,7 +42,7 @@ func TestRemoveNode(t *testing.T) { } if len(resp) != 2 { - t.Fatal("cannot remove machine") + t.Fatal("cannot remove peer") } if i == 1 { @@ -66,7 +66,7 @@ func TestRemoveNode(t *testing.T) { } if len(resp) != 3 { - t.Fatalf("add machine fails #1 (%d != 3)", len(resp)) + t.Fatalf("add peer fails #1 (%d != 3)", len(resp)) } } @@ -85,7 +85,7 @@ func TestRemoveNode(t *testing.T) { } if len(resp) != 2 { - t.Fatal("cannot remove machine") + t.Fatal("cannot remove peer") } if i == 1 { @@ -109,7 +109,7 @@ func TestRemoveNode(t *testing.T) { } if len(resp) != 3 { - t.Fatalf("add machine fails #2 (%d != 3)", len(resp)) + t.Fatalf("add peer fails #2 (%d != 3)", len(resp)) } } } diff --git a/tests/functional/simple_snapshot_test.go b/tests/functional/simple_snapshot_test.go index c5121a6a7..2ca14cdfe 100644 --- a/tests/functional/simple_snapshot_test.go +++ b/tests/functional/simple_snapshot_test.go @@ -14,7 +14,7 @@ import ( func TestSimpleSnapshot(t *testing.T) { procAttr := new(os.ProcAttr) procAttr.Files = []*os.File{nil, os.Stdout, os.Stderr} - args := []string{"etcd", "-n=node1", "-d=/tmp/node1", "-snapshot=true", "-snapshotCount=500"} + args := []string{"etcd", "-name=node1", "-data-dir=/tmp/node1", "-snapshot=true", "-snapshot-count=500"} process, err := os.StartProcess(EtcdBinPath, append(args, "-f"), procAttr) if err != nil { diff --git a/tests/functional/single_node_recovery_test.go b/tests/functional/single_node_recovery_test.go index 1b0d7f878..8acf77e2f 100644 --- a/tests/functional/single_node_recovery_test.go +++ b/tests/functional/single_node_recovery_test.go @@ -13,7 +13,7 @@ import ( func TestSingleNodeRecovery(t *testing.T) { procAttr := new(os.ProcAttr) procAttr.Files = []*os.File{nil, os.Stdout, os.Stderr} - args := []string{"etcd", "-n=node1", "-d=/tmp/node1"} + args := []string{"etcd", "-name=node1", "-data-dir=/tmp/node1"} process, err := os.StartProcess(EtcdBinPath, append(args, "-f"), procAttr) if err != nil { @@ -65,4 +65,3 @@ func TestSingleNodeRecovery(t *testing.T) { t.Fatalf("Recovery Get failed with %s %s %v", result.Key, result.Value, result.TTL) } } - diff --git a/tests/functional/single_node_test.go b/tests/functional/single_node_test.go index 04362e328..eee852d94 100644 --- a/tests/functional/single_node_test.go +++ b/tests/functional/single_node_test.go @@ -12,7 +12,7 @@ import ( func TestSingleNode(t *testing.T) { procAttr := new(os.ProcAttr) procAttr.Files = []*os.File{nil, os.Stdout, os.Stderr} - args := []string{"etcd", "-n=node1", "-f", "-d=/tmp/node1"} + args := []string{"etcd", "-name=node1", "-f", "-data-dir=/tmp/node1"} process, err := os.StartProcess(EtcdBinPath, args, procAttr) if err != nil { @@ -74,4 +74,3 @@ func TestSingleNode(t *testing.T) { t.Fatalf("Set 5 expecting error when setting key with blank (incorrect) previous value") } } - diff --git a/tests/functional/util.go b/tests/functional/util.go index fd2f3c8fe..791f5045c 100644 --- a/tests/functional/util.go +++ b/tests/functional/util.go @@ -73,25 +73,25 @@ func Set(stop chan bool) { func CreateCluster(size int, procAttr *os.ProcAttr, ssl bool) ([][]string, []*os.Process, error) { argGroup := make([][]string, size) - sslServer1 := []string{"-serverCAFile=../../fixtures/ca/ca.crt", - "-serverCert=../../fixtures/ca/server.crt", - "-serverKey=../../fixtures/ca/server.key.insecure", + sslServer1 := []string{"-peer-ca-file=../../fixtures/ca/ca.crt", + "-peer-cert-file=../../fixtures/ca/server.crt", + "-peer-key-file=../../fixtures/ca/server.key.insecure", } - sslServer2 := []string{"-serverCAFile=../../fixtures/ca/ca.crt", - "-serverCert=../../fixtures/ca/server2.crt", - "-serverKey=../../fixtures/ca/server2.key.insecure", + sslServer2 := []string{"-peer-ca-file=../../fixtures/ca/ca.crt", + "-peer-cert-file=../../fixtures/ca/server2.crt", + "-peer-cert-file=../../fixtures/ca/server2.key.insecure", } for i := 0; i < size; i++ { if i == 0 { - argGroup[i] = []string{"etcd", "-d=/tmp/node1", "-n=node1"} + argGroup[i] = []string{"etcd", "-data-dir=/tmp/node1", "-name=node1"} if ssl { argGroup[i] = append(argGroup[i], sslServer1...) } } else { strI := strconv.Itoa(i + 1) - argGroup[i] = []string{"etcd", "-n=node" + strI, "-c=127.0.0.1:400" + strI, "-s=127.0.0.1:700" + strI, "-d=/tmp/node" + strI, "-C=127.0.0.1:7001"} + argGroup[i] = []string{"etcd", "-name=node" + strI, "-addr=127.0.0.1:400" + strI, "-peer-addr=127.0.0.1:700" + strI, "-data-dir=/tmp/node" + strI, "-peers=127.0.0.1:7001"} if ssl { argGroup[i] = append(argGroup[i], sslServer2...) } diff --git a/tests/functional/v1_migration_test.go b/tests/functional/v1_migration_test.go index 415ff6ded..506f48cc7 100644 --- a/tests/functional/v1_migration_test.go +++ b/tests/functional/v1_migration_test.go @@ -33,9 +33,9 @@ func TestV1SoloMigration(t *testing.T) { procAttr := new(os.ProcAttr) procAttr.Files = []*os.File{nil, os.Stdout, os.Stderr} - args := []string{"etcd", fmt.Sprintf("-d=%s", nodepath)} - args = append(args, "-c", "127.0.0.1:4001") - args = append(args, "-s", "127.0.0.1:7001") + args := []string{"etcd", fmt.Sprintf("-data-dir=%s", nodepath)} + args = append(args, "-addr", "127.0.0.1:4001") + args = append(args, "-peer-addr", "127.0.0.1:7001") process, err := os.StartProcess(EtcdBinPath, args, procAttr) if err != nil { t.Fatal("start process failed:" + err.Error()) @@ -75,9 +75,9 @@ func TestV1ClusterMigration(t *testing.T) { procAttr := new(os.ProcAttr) procAttr.Files = []*os.File{nil, os.Stdout, os.Stderr} - args := []string{"etcd", fmt.Sprintf("-d=%s", nodepath)} - args = append(args, "-c", fmt.Sprintf("127.0.0.1:%d", 4001 + i)) - args = append(args, "-s", fmt.Sprintf("127.0.0.1:%d", 7001 + i)) + args := []string{"etcd", fmt.Sprintf("-data-dir=%s", nodepath)} + args = append(args, "-addr", fmt.Sprintf("127.0.0.1:%d", 4001+i)) + args = append(args, "-peer-addr", fmt.Sprintf("127.0.0.1:%d", 7001+i)) process, err := os.StartProcess(EtcdBinPath, args, procAttr) if err != nil { t.Fatal("start process failed:" + err.Error()) @@ -91,7 +91,7 @@ func TestV1ClusterMigration(t *testing.T) { resp, err := tests.Get("http://localhost:4001/v2/keys/message") body := tests.ReadBody(resp) assert.Nil(t, err, "") - assert.Equal(t, resp.StatusCode, 400, ) + assert.Equal(t, resp.StatusCode, 400) assert.Equal(t, string(body), `{"errorCode":100,"message":"Key Not Found","cause":"/message","index":11}`+"\n") // Ensure TTL'd message is removed. diff --git a/tests/functional/version_check_test.go b/tests/functional/version_check_test.go index 98a155390..84c5cefbf 100644 --- a/tests/functional/version_check_test.go +++ b/tests/functional/version_check_test.go @@ -11,7 +11,7 @@ import ( func TestVersionCheck(t *testing.T) { procAttr := new(os.ProcAttr) procAttr.Files = []*os.File{nil, os.Stdout, os.Stderr} - args := []string{"etcd", "-n=node1", "-f", "-d=/tmp/version_check"} + args := []string{"etcd", "-name=node1", "-f", "-data-dir=/tmp/version_check"} process, err := os.StartProcess(EtcdBinPath, args, procAttr) if err != nil { @@ -43,4 +43,3 @@ func TestVersionCheck(t *testing.T) { t.Fatal("Invalid version check: ", resp.StatusCode) } } - diff --git a/tests/http_utils.go b/tests/http_utils.go index ebe6f5273..b0ae029d8 100644 --- a/tests/http_utils.go +++ b/tests/http_utils.go @@ -63,7 +63,6 @@ func DeleteForm(url string, data url.Values) (*http.Response, error) { return Delete(url, "application/x-www-form-urlencoded", strings.NewReader(data.Encode())) } - func send(method string, url string, bodyType string, body io.Reader) (*http.Response, error) { c := NewHTTPClient() req, err := http.NewRequest(method, url, body) diff --git a/tests/mock/server_v2.go b/tests/mock/server_v2.go index 2aa28185b..d48d5c0ef 100644 --- a/tests/mock/server_v2.go +++ b/tests/mock/server_v2.go @@ -2,7 +2,7 @@ package mock import ( "net/http" - + "github.com/coreos/etcd/store" "github.com/coreos/go-raft" "github.com/stretchr/testify/mock" diff --git a/tests/server_utils.go b/tests/server_utils.go index e7ed347a3..e3e7d5323 100644 --- a/tests/server_utils.go +++ b/tests/server_utils.go @@ -10,10 +10,10 @@ import ( ) const ( - testName = "ETCDTEST" - testClientURL = "localhost:4401" - testRaftURL = "localhost:7701" - testSnapCount = 10000 + testName = "ETCDTEST" + testClientURL = "localhost:4401" + testRaftURL = "localhost:7701" + testSnapshotCount = 10000 ) // Starts a server in a temporary directory. @@ -23,7 +23,7 @@ func RunServer(f func(*server.Server)) { store := store.New() registry := server.NewRegistry(store) - ps := server.NewPeerServer(testName, path, testRaftURL, testRaftURL, &server.TLSConfig{Scheme: "http"}, &server.TLSInfo{}, registry, store, testSnapCount) + ps := server.NewPeerServer(testName, path, testRaftURL, testRaftURL, &server.TLSConfig{Scheme: "http"}, &server.TLSInfo{}, registry, store, testSnapshotCount) s := server.New(testName, testClientURL, testClientURL, &server.TLSConfig{Scheme: "http"}, &server.TLSInfo{}, ps, registry, store) ps.SetServer(s)
Machine NamePeer Name Latency
-
{{machine.name}}(leader)
-
{{machine.name}}
+
+
{{peer.name}}(leader)
+
{{peer.name}}
-
-
{{machine.latency.current | number:1 }} ms
+
+
{{peer.latency.current | number:1 }} ms