Renamed configuration parameters.

This commit is contained in:
Ben Johnson 2013-11-14 22:58:47 -05:00
parent 3ce1132d5c
commit cba2611c68
35 changed files with 332 additions and 342 deletions

View File

@ -7,4 +7,4 @@ RUN apt-get install -y golang
ADD . /opt/etcd ADD . /opt/etcd
RUN cd /opt/etcd && ./build RUN cd /opt/etcd && ./build
EXPOSE 4001 7001 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"]

View File

@ -17,7 +17,7 @@ Error code corresponding strerror
EcodeKeyNotFound = 100 EcodeKeyNotFound = 100
EcodeTestFailed = 101 EcodeTestFailed = 101
EcodeNotFile = 102 EcodeNotFile = 102
EcodeNoMoreMachine = 103 EcodeNoMorePeer = 103
EcodeNotDir = 104 EcodeNotDir = 104
EcodeNodeExist = 105 EcodeNodeExist = 105
EcodeKeyIsPreserved = 106 EcodeKeyIsPreserved = 106
@ -38,7 +38,7 @@ Error code corresponding strerror
errors[100] = "Key Not Found" errors[100] = "Key Not Found"
errors[101] = "Test Failed" //test and set errors[101] = "Test Failed" //test and set
errors[102] = "Not A File" 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[104] = "Not A Directory"
errors[105] = "Already exists" // create errors[105] = "Already exists" // create
errors[106] = "The prefix of given key is a keyword in etcd" errors[106] = "The prefix of given key is a keyword in etcd"

View File

@ -14,34 +14,34 @@ configuration files.
### Required ### Required
* `-n` - The node name. Defaults to `default-name`. * `-name` - The node name. Defaults to the hostname.
### Optional ### Optional
* `-c` - The advertised public hostname:port for client communication. Defaults to `127.0.0.1:4001`. * `-addr` - 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. * `-bind-addr` - 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"`). * `-peers` - A comma separated list of peers 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. * `-peers-file` - The file path containing a comma separated list of peers in the cluster.
* `-clientCAFile` - The path of the client CAFile. Enables client cert authentication when present. * `-ca-file` - The path of the client CAFile. Enables client cert authentication when present.
* `-clientCert` - The cert file of the client. * `-cert-file` - The cert file of the client.
* `-clientKey` - The key file of the client. * `-key-file` - The key file of the client.
* `-configfile` - The path of the etcd config file. Defaults to `/etc/etcd/etcd.conf`. * `-config` - 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. * `-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. * `-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. * `-data-dir` - The directory to store log and snapshot. Defaults to the current working directory.
* `-m` - The max size of result buffer. Defaults to `1024`. * `-max-result-buffer` - The max size of result buffer. Defaults to `1024`.
* `-maxsize` - The max size of the cluster. Defaults to `9`. * `-max-cluster-size` - The max size of the cluster. Defaults to `9`.
* `-r` - The max retry attempts when trying to join a cluster. Defaults to `3`. * `-max-retry-attempts` - 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`. * `-peer-addr` - 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. * `-peer-bind-addr` - The listening hostname for server communication. Defaults to advertised ip.
* `-serverCAFile` - The path of the CAFile. Enables client/peer cert authentication when present. * `-peer-ca-file` - The path of the CAFile. Enables client/peer cert authentication when present.
* `-serverCert` - The cert file of the server. * `-peer-cert-file` - The cert file of the server.
* `-serverKey` - The key file of the server. * `-peer-key-file` - The key file of the server.
* `-snapshot` - Open or close snapshot. Defaults to `false`. * `-snapshot` - Open or close snapshot. Defaults to `false`.
* `-v` - Enable verbose logging. Defaults to `false`. * `-v` - Enable verbose logging. Defaults to `false`.
* `-vv` - Enable very verbose logging. Defaults to `false`. * `-vv` - Enable very verbose logging. Defaults to `false`.
* `-version` - Print the version and exit. * `-version` - Print the version and exit.
* `-w` - The hostname:port of web interface. * `-web-url` - The hostname:port of web interface.
## Configuration File ## 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. and read from `/etc/etcd/etcd.conf` by default.
```TOML ```TOML
advertised_url = "127.0.0.1:4001" addr = "127.0.0.1:4001"
bind_addr = "127.0.0.1:4001"
ca_file = "" ca_file = ""
cert_file = "" cert_file = ""
cors = [] cors_origins = []
cpu_profile_file = "" cpu_profile_file = ""
datadir = "." data_dir = "."
key_file = "" key_file = ""
listen_host = "127.0.0.1:4001" peers = []
machines = [] peers_file = ""
machines_file = ""
max_cluster_size = 9 max_cluster_size = 9
max_result_buffer = 1024 max_result_buffer = 1024
max_retry_attempts = 3 max_retry_attempts = 3
@ -69,36 +69,36 @@ very_verbose = false
web_url = "" web_url = ""
[peer] [peer]
advertised_url = "127.0.0.1:7001" addr = "127.0.0.1:7001"
bind_addr = "127.0.0.1:7001"
ca_file = "" ca_file = ""
cert_file = "" cert_file = ""
key_file = "" key_file = ""
listen_host = "127.0.0.1:7001"
``` ```
## Environment Variables ## Environment Variables
* `ETCD_ADVERTISED_URL` * `ETCD_ADDR`
* `ETCD_BIND_ADDR`
* `ETCD_CA_FILE` * `ETCD_CA_FILE`
* `ETCD_CERT_FILE` * `ETCD_CERT_FILE`
* `ETCD_CORS` * `ETCD_CORS_ORIGINS`
* `ETCD_CONFIG_FILE` * `ETCD_CONFIG`
* `ETCD_CPU_PROFILE_FILE` * `ETCD_CPU_PROFILE_FILE`
* `ETCD_DATADIR` * `ETCD_DATA_DIR`
* `ETCD_KEY_FILE` * `ETCD_KEY_FILE`
* `ETCD_LISTEN_HOST` * `ETCD_PEERS`
* `ETCD_MACHINES` * `ETCD_PEERS_FILE`
* `ETCD_MACHINES_FILE`
* `ETCD_MAX_RETRY_ATTEMPTS`
* `ETCD_MAX_CLUSTER_SIZE` * `ETCD_MAX_CLUSTER_SIZE`
* `ETCD_MAX_RESULT_BUFFER` * `ETCD_MAX_RESULT_BUFFER`
* `ETCD_MAX_RETRY_ATTEMPTS`
* `ETCD_NAME` * `ETCD_NAME`
* `ETCD_SNAPSHOT` * `ETCD_SNAPSHOT`
* `ETCD_VERBOSE` * `ETCD_VERBOSE`
* `ETCD_VERY_VERBOSE` * `ETCD_VERY_VERBOSE`
* `ETCD_WEB_URL` * `ETCD_WEB_URL`
* `ETCD_PEER_ADVERTISED_URL` * `ETCD_PEER_ADDR`
* `ETCD_PEER_BIND_ADDR`
* `ETCD_PEER_CA_FILE` * `ETCD_PEER_CA_FILE`
* `ETCD_PEER_CERT_FILE` * `ETCD_PEER_CERT_FILE`
* `ETCD_PEER_KEY_FILE` * `ETCD_PEER_KEY_FILE`
* `ETCD_PEER_LISTEN_HOST`

View File

@ -1,12 +1,12 @@
# Versioning # 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. 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. 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). 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. 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. 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
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.

View File

@ -62,12 +62,12 @@ These examples will use a single node cluster to show you the basics of the etcd
Let's start etcd: Let's start etcd:
```sh ```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. 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 `-data-dir 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 `-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: Let's configure etcd to use this keypair:
```sh ```sh
./etcd -n node0 -d node0 -clientCert=./fixtures/ca/server.crt -clientKey=./fixtures/ca/server.key.insecure -f ./etcd -name node0 -data-dir node0 -cert-file=./fixtures/ca/server.crt -key-file=./fixtures/ca/server.key.insecure -force-config
``` ```
There are a few new options we're using: 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!) * `-force-config` - 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: 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. 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 ```sh
./etcd -n node0 -d node0 -clientCAFile=./fixtures/ca/ca.crt -clientCert=./fixtures/ca/server.crt -clientKey=./fixtures/ca/server.key.insecure -f ./etcd -name node0 -data-dir node0 -ca-file=./fixtures/ca/ca.crt -cert-file=./fixtures/ca/server.crt -key-file=./fixtures/ca/server.key.insecure -force-config
``` ```
```-clientCAFile``` is the path to the CA cert. ```-ca-file``` is the path to the CA cert.
Try the same request to this server: 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. 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 ```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. **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 `-sl` is used to setup the listening address for the server port. 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 ```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 -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 -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: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: 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. 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. 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. 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? ### What size cluster should I use?
Every command the client sends to the master is broadcast to all of the followers. 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. 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 machine cluster can tolerate 3 machine failures and a 9 machine cluster can tolerate 4 nodes failures. 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 machines are responding the cluster will perform at the speed of the fastest 5 nodes. 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? ### Why SSLv3 alert handshake failure when using SSL client auth?

View File

@ -28,7 +28,7 @@ const (
EcodeKeyNotFound = 100 EcodeKeyNotFound = 100
EcodeTestFailed = 101 EcodeTestFailed = 101
EcodeNotFile = 102 EcodeNotFile = 102
EcodeNoMoreMachine = 103 EcodeNoMorePeer = 103
EcodeNotDir = 104 EcodeNotDir = 104
EcodeNodeExist = 105 EcodeNodeExist = 105
EcodeKeyIsPreserved = 106 EcodeKeyIsPreserved = 106
@ -53,7 +53,7 @@ func init() {
errors[EcodeKeyNotFound] = "Key Not Found" errors[EcodeKeyNotFound] = "Key Not Found"
errors[EcodeTestFailed] = "Test Failed" //test and set errors[EcodeTestFailed] = "Test Failed" //test and set
errors[EcodeNotFile] = "Not A File" 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[EcodeNotDir] = "Not A Directory"
errors[EcodeNodeExist] = "Already exists" // create errors[EcodeNodeExist] = "Already exists" // create
errors[EcodeKeyIsPreserved] = "The prefix of given key is a keyword in etcd" errors[EcodeKeyIsPreserved] = "The prefix of given key is a keyword in etcd"

12
etcd.go
View File

@ -55,13 +55,13 @@ func main() {
if info.Name == "" { if info.Name == "" {
host, err := os.Hostname() host, err := os.Hostname()
if err != nil || host == "" { 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 info.Name = host
} }
// Setup a default directory based on the machine name // Setup a default directory based on the node name
if config.DataDir == "" { if config.DataDir == "" {
config.DataDir = info.Name + ".etcd" config.DataDir = info.Name + ".etcd"
log.Warnf("Using the directory %s as the etcd configuration directory because a directory was not specified. ", config.DataDir) log.Warnf("Using the directory %s as the etcd configuration directory because a directory was not specified. ", config.DataDir)
@ -87,13 +87,13 @@ func main() {
registry := server.NewRegistry(store) registry := server.NewRegistry(store)
// Create peer server. // 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.MaxClusterSize = config.MaxClusterSize
ps.RetryTimes = config.MaxRetryAttempts ps.RetryTimes = config.MaxRetryAttempts
// Create client server. // Create client server.
s := server.New(info.Name, info.EtcdURL, info.EtcdListenHost, &tlsConfig, &info.EtcdTLS, ps, registry, store) 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) panic(err)
} }
@ -101,7 +101,7 @@ func main() {
// Run peer server in separate thread while the client server blocks. // Run peer server in separate thread while the client server blocks.
go func() { go func() {
log.Fatal(ps.ListenAndServe(config.Snapshot, config.Machines)) log.Fatal(ps.ListenAndServe(config.Snapshot, config.Peers))
}() }()
log.Fatal(s.ListenAndServe()) log.Fatal(s.ListenAndServe())
} }

View File

@ -24,9 +24,9 @@ angular.module('etcdStats', ['ngRoute', 'etcd'])
EtcdV2.getStat('leader').get().success(function(data) { EtcdV2.getStat('leader').get().success(function(data) {
$scope.leaderStats = data; $scope.leaderStats = data;
$scope.leaderName = data.leader; $scope.leaderName = data.leader;
$scope.machines = []; $scope.peers = [];
//hardcode leader stats //hardcode leader stats
$scope.machines.push({ $scope.peers.push({
latency: { latency: {
average: 0, average: 0,
current: 0, current: 0,
@ -38,10 +38,10 @@ angular.module('etcdStats', ['ngRoute', 'etcd'])
}); });
$.each(data.followers, function(index, value) { $.each(data.followers, function(index, value) {
value.name = index; value.name = index;
$scope.machines.push(value); $scope.peers.push(value);
}); });
//sort array so machines don't jump when output //sort array so peers don't jump when output
$scope.machines.sort(function(a, b){ $scope.peers.sort(function(a, b){
if(a.name < b.name) return -1; if(a.name < b.name) return -1;
if(a.name > b.name) return 1; if(a.name > b.name) return 1;
return 0; return 0;
@ -64,7 +64,7 @@ angular.module('etcdStats', ['ngRoute', 'etcd'])
chart({ chart({
el: $scope.graphContainer, el: $scope.graphContainer,
data: { data: {
'stats': $scope.machines 'stats': $scope.peers
} }
}).width(width).height(height).update(); }).width(width).height(height).update();
}); });

View File

@ -636,7 +636,7 @@ body {
background-color: #00DB24; background-color: #00DB24;
} }
.etcd-container.etcd-stats .etcd-list .etcd-machine-type { .etcd-container.etcd-stats .etcd-list .etcd-peer-type {
color: #999; color: #999;
padding-left: 3px; padding-left: 3px;
font-size: 13px; font-size: 13px;

View File

@ -20,26 +20,26 @@
</div> </div>
</div> </div>
<div class="etcd-graph"> <div class="etcd-graph">
<h2>Machine Latency</h2> <h2>Peer Latency</h2>
<div class="etcd-graph-container" id="latency"> <div class="etcd-graph-container" id="latency">
</div> </div>
</div> </div>
<div class="etcd-list"> <div class="etcd-list">
<h2>Machine List</h2> <h2>Peer List</h2>
<table cellpadding="0" cellspacing="0"> <table cellpadding="0" cellspacing="0">
<thead> <thead>
<td class="etcd-name-header">Machine Name</td> <td class="etcd-name-header">Peer Name</td>
<td class="etcd-latency">Latency</td> <td class="etcd-latency">Latency</td>
</thead> </thead>
<tbody> <tbody>
<tr ng-repeat="machine in machines"> <tr ng-repeat="peer in peers">
<td ng-switch on="{true:'leader', false: 'follower'}[leaderName == machine.name]"> <td ng-switch on="{true:'leader', false: 'follower'}[leaderName == peer.name]">
<div ng-switch-when="leader">{{machine.name}}<span class="etcd-machine-type">(leader)</span></div> <div ng-switch-when="leader">{{peer.name}}<span class="etcd-peer-type">(leader)</span></div>
<div ng-switch-default>{{machine.name}}</div> <div ng-switch-default>{{peer.name}}</div>
</td> </td>
<td> <td>
<div class="etcd-square ng-class: {'etcd-square-green': machine.latency.current < 25, 'etcd-square-orange': machine.latency.current < 60, 'etcd-square-red': machine.latency.current >= 60}"></div> <div class="etcd-square ng-class: {'etcd-square-green': peer.latency.current < 25, 'etcd-square-orange': peer.latency.current < 60, 'etcd-square-red': peer.latency.current >= 60}"></div>
<div class="etcd-latency-value">{{machine.latency.current | number:1 }} ms</div> <div class="etcd-latency-value">{{peer.latency.current | number:1 }} ms</div>
</td> </td>
</tr> </tr>
</tbody> </tbody>

View File

@ -1,2 +1,3 @@
package main package main
const releaseVersion = "v0.1.2-33-g1a2a9d6" const releaseVersion = "v0.1.2-33-g1a2a9d6"

View File

@ -4,15 +4,15 @@ SESSION=etcd-cluster
tmux new-session -d -s $SESSION tmux new-session -d -s $SESSION
# Setup a window for tailing log files # 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 split-window -h
tmux select-pane -t 0 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 for i in 2 3; do
tmux select-pane -t 0 tmux select-pane -t 0
tmux split-window -v 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 done
# Attach to session # Attach to session

View File

@ -23,31 +23,31 @@ const DefaultSystemConfigPath = "/etc/etcd/etcd.conf"
type Config struct { type Config struct {
SystemPath string 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"` CAFile string `toml:"ca_file" env:"ETCD_CA_FILE"`
CertFile string `toml:"cert_file" env:"ETCD_CERT_FILE"` CertFile string `toml:"cert_file" env:"ETCD_CERT_FILE"`
Cors []string `toml:"cors" env:"ETCD_CORS"` CorsOrigins []string `toml:"cors_origins" env:"ETCD_CORS_ORIGINS"`
DataDir string `toml:"datadir" env:"ETCD_DATADIR"` DataDir string `toml:"data_dir" env:"ETCD_DATA_DIR"`
KeyFile string `toml:"key_file" env:"ETCD_KEY_FILE"` KeyFile string `toml:"key_file" env:"ETCD_KEY_FILE"`
ListenHost string `toml:"listen_host" env:"ETCD_LISTEN_HOST"` Peers []string `toml:"peers" env:"ETCD_PEERS"`
Machines []string `toml:"machines" env:"ETCD_MACHINES"` PeersFile string `toml:"peers_file" env:"ETCD_PEERS_FILE"`
MachinesFile string `toml:"machines_file" env:"ETCD_MACHINES_FILE"`
MaxClusterSize int `toml:"max_cluster_size" env:"ETCD_MAX_CLUSTER_SIZE"` MaxClusterSize int `toml:"max_cluster_size" env:"ETCD_MAX_CLUSTER_SIZE"`
MaxResultBuffer int `toml:"max_result_buffer" env:"ETCD_MAX_RESULT_BUFFER"` MaxResultBuffer int `toml:"max_result_buffer" env:"ETCD_MAX_RESULT_BUFFER"`
MaxRetryAttempts int `toml:"max_retry_attempts" env:"ETCD_MAX_RETRY_ATTEMPTS"` MaxRetryAttempts int `toml:"max_retry_attempts" env:"ETCD_MAX_RETRY_ATTEMPTS"`
Name string `toml:"name" env:"ETCD_NAME"` Name string `toml:"name" env:"ETCD_NAME"`
Snapshot bool `toml:"snapshot" env:"ETCD_SNAPSHOT"` 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"` Verbose bool `toml:"verbose" env:"ETCD_VERBOSE"`
VeryVerbose bool `toml:"very_verbose" env:"ETCD_VERY_VERBOSE"` VeryVerbose bool `toml:"very_verbose" env:"ETCD_VERY_VERBOSE"`
WebURL string `toml:"web_url" env:"ETCD_WEB_URL"` WebURL string `toml:"web_url" env:"ETCD_WEB_URL"`
Peer struct { Peer struct {
AdvertisedUrl string `toml:"advertised_url" env:"ETCD_PEER_ADVERTISED_URL"` Addr string `toml:"addr" env:"ETCD_PEER_ADDR"`
CAFile string `toml:"ca_file" env:"ETCD_PEER_CA_FILE"` BindAddr string `toml:"bind_addr" env:"ETCD_PEER_BIND_ADDR"`
CertFile string `toml:"cert_file" env:"ETCD_PEER_CERT_FILE"` CAFile string `toml:"ca_file" env:"ETCD_PEER_CA_FILE"`
KeyFile string `toml:"key_file" env:"ETCD_PEER_KEY_FILE"` CertFile string `toml:"cert_file" env:"ETCD_PEER_CERT_FILE"`
ListenHost string `toml:"listen_host" env:"ETCD_PEER_LISTEN_HOST"` KeyFile string `toml:"key_file" env:"ETCD_PEER_KEY_FILE"`
} }
} }
@ -55,13 +55,12 @@ type Config struct {
func NewConfig() *Config { func NewConfig() *Config {
c := new(Config) c := new(Config)
c.SystemPath = DefaultSystemConfigPath c.SystemPath = DefaultSystemConfigPath
c.AdvertisedUrl = "127.0.0.1:4001" c.Addr = "127.0.0.1:4001"
c.AdvertisedUrl = "127.0.0.1:4001"
c.MaxClusterSize = 9 c.MaxClusterSize = 9
c.MaxResultBuffer = 1024 c.MaxResultBuffer = 1024
c.MaxRetryAttempts = 3 c.MaxRetryAttempts = 3
c.Peer.AdvertisedUrl = "127.0.0.1:7001" c.Peer.Addr = "127.0.0.1:7001"
c.SnapCount = 10000 c.SnapshotCount = 10000
return c return c
} }
@ -96,8 +95,8 @@ func (c *Config) Load(arguments []string) error {
return err return err
} }
// Loads machines if a machine file was specified. // Loads peers if a peer file was specified.
if err := c.LoadMachineFile(); err != nil { if err := c.LoadPeersFile(); err != nil {
return err return err
} }
@ -167,42 +166,42 @@ func (c *Config) loadEnv(target interface{}) error {
// Loads configuration from command line flags. // Loads configuration from command line flags.
func (c *Config) LoadFlags(arguments []string) error { func (c *Config) LoadFlags(arguments []string) error {
var machines, cors string var peers, cors string
var force bool var force bool
f := flag.NewFlagSet(os.Args[0], flag.ContinueOnError) f := flag.NewFlagSet(os.Args[0], flag.ContinueOnError)
f.BoolVar(&force, "f", false, "force new node configuration if existing is found (WARNING: data loss!)") f.BoolVar(&force, "force-config", false, "force new node configuration if existing is found (WARNING: data loss!)")
f.BoolVar(&c.Verbose, "v", c.Verbose, "verbose logging") f.BoolVar(&c.Verbose, "v", c.Verbose, "verbose logging")
f.BoolVar(&c.VeryVerbose, "vv", c.Verbose, "very 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(&peers, "peers", "", "the ip address and port of a existing peers 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.PeersFile, "peers-file", c.PeersFile, "the file contains a list of existing peers in the cluster, seperate by comma")
f.StringVar(&c.Name, "n", c.Name, "the node name (required)") f.StringVar(&c.Name, "name", 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.Addr, "addr", c.Addr, "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.BindAddr, "bind-addr", c.BindAddr, "the listening hostname for etcd client communication (defaults to advertised ip)")
f.StringVar(&c.ListenHost, "cl", c.ListenHost, "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.ListenHost, "sl", c.Peer.ListenHost, "the listening hostname for raft server communication (defaults to advertised ip)") 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.WebURL, "w", c.WebURL, "the hostname:port of web interface") f.StringVar(&c.WebURL, "web-url", c.WebURL, "the hostname:port of web interface")
f.StringVar(&c.Peer.CAFile, "serverCAFile", c.Peer.CAFile, "the path of the CAFile") f.StringVar(&c.Peer.CAFile, "peer-ca-file", c.Peer.CAFile, "the path of the CAFile")
f.StringVar(&c.Peer.CertFile, "serverCert", c.Peer.CertFile, "the cert file of the server") f.StringVar(&c.Peer.CertFile, "peer-cert-file", c.Peer.CertFile, "the cert file of the server")
f.StringVar(&c.Peer.KeyFile, "serverKey", c.Peer.KeyFile, "the key 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, "clientCAFile", c.CAFile, "the path of the client CAFile") f.StringVar(&c.CAFile, "ca-file", c.CAFile, "the path of the client CAFile")
f.StringVar(&c.CertFile, "clientCert", c.CertFile, "the cert file of the client") f.StringVar(&c.CertFile, "cert-file", c.CertFile, "the cert file of the client")
f.StringVar(&c.KeyFile, "clientKey", c.KeyFile, "the key file of the client") f.StringVar(&c.KeyFile, "key-file", c.KeyFile, "the key file of the client")
f.StringVar(&c.DataDir, "d", c.DataDir, "the directory to store log and snapshot") f.StringVar(&c.DataDir, "data-dir", c.DataDir, "the directory to store log and snapshot")
f.IntVar(&c.MaxResultBuffer, "m", c.MaxResultBuffer, "the max size of result buffer") f.IntVar(&c.MaxResultBuffer, "max-result-buffer", 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.MaxRetryAttempts, "max-retry-attempts", 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.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.StringVar(&cors, "cors-origins", "", "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.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. // These flags are ignored since they were already parsed.
var path string var path string
@ -211,11 +210,11 @@ func (c *Config) LoadFlags(arguments []string) error {
f.Parse(arguments) f.Parse(arguments)
// Convert some parameters to lists. // Convert some parameters to lists.
if machines != "" { if peers != "" {
c.Machines = trimsplit(machines, ",") c.Peers = trimsplit(peers, ",")
} }
if cors != "" { if cors != "" {
c.Cors = trimsplit(cors, ",") c.CorsOrigins = trimsplit(cors, ",")
} }
// Force remove server configuration if specified. // Force remove server configuration if specified.
@ -226,17 +225,17 @@ func (c *Config) LoadFlags(arguments []string) error {
return nil return nil
} }
// LoadMachineFile loads the machines listed in the machine file. // LoadPeersFile loads the peers listed in the peers file.
func (c *Config) LoadMachineFile() error { func (c *Config) LoadPeersFile() error {
if c.MachinesFile == "" { if c.PeersFile == "" {
return nil return nil
} }
b, err := ioutil.ReadFile(c.MachinesFile) b, err := ioutil.ReadFile(c.PeersFile)
if err != nil { 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 return nil
} }
@ -278,10 +277,10 @@ func (c *Config) Info() (*Info, error) {
// If the file doesn't exist then initialize it. // If the file doesn't exist then initialize it.
info.Name = strings.TrimSpace(c.Name) info.Name = strings.TrimSpace(c.Name)
info.EtcdURL = c.AdvertisedUrl info.EtcdURL = c.Addr
info.EtcdListenHost = c.ListenHost info.EtcdListenHost = c.BindAddr
info.RaftURL = c.Peer.AdvertisedUrl info.RaftURL = c.Peer.Addr
info.RaftListenHost = c.Peer.ListenHost info.RaftListenHost = c.Peer.BindAddr
info.WebURL = c.WebURL info.WebURL = c.WebURL
info.EtcdTLS = c.TLSInfo() info.EtcdTLS = c.TLSInfo()
info.RaftTLS = c.PeerTLSInfo() info.RaftTLS = c.PeerTLSInfo()
@ -313,19 +312,19 @@ func (c *Config) Sanitize() error {
} }
// Sanitize the URLs first. // 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) 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) return fmt.Errorf("Listen Host: %s", err)
} }
if c.WebURL, err = sanitizeURL(c.WebURL, "http"); err != nil { if c.WebURL, err = sanitizeURL(c.WebURL, "http"); err != nil {
return fmt.Errorf("Web URL: %s", err) 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) 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) return fmt.Errorf("Peer Listen Host: %s", err)
} }
@ -383,10 +382,10 @@ func sanitizeURL(host string, defaultScheme string) (string, error) {
return p.String(), nil 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. // if necessary based on the advertised port.
func sanitizeListenHost(listen string, advertised string) (string, error) { func sanitizeBindAddr(bindAddr string, addr string) (string, error) {
aurl, err := url.Parse(advertised) aurl, err := url.Parse(addr)
if err != nil { if err != nil {
return "", err return "", err
} }
@ -397,9 +396,9 @@ func sanitizeListenHost(listen string, advertised string) (string, error) {
} }
// If the listen host isn't set use the advertised host // If the listen host isn't set use the advertised host
if listen == "" { if bindAddr == "" {
listen = ahost bindAddr = ahost
} }
return net.JoinHostPort(listen, aport), nil return net.JoinHostPort(bindAddr, aport), nil
} }

View File

@ -9,20 +9,19 @@ import (
"github.com/stretchr/testify/assert" "github.com/stretchr/testify/assert"
) )
// Ensures that a configuration can be deserialized from TOML. // Ensures that a configuration can be deserialized from TOML.
func TestConfigTOML(t *testing.T) { func TestConfigTOML(t *testing.T) {
content := ` content := `
advertised_url = "127.0.0.1:4002" addr = "127.0.0.1:4002"
ca_file = "/tmp/file.ca" ca_file = "/tmp/file.ca"
cert_file = "/tmp/file.cert" cert_file = "/tmp/file.cert"
cors = ["*"] cors_origins = ["*"]
cpu_profile_file = "XXX" cpu_profile_file = "XXX"
datadir = "/tmp/data" data_dir = "/tmp/data"
key_file = "/tmp/file.key" key_file = "/tmp/file.key"
listen_host = "127.0.0.1:4003" bind_addr = "127.0.0.1:4003"
machines = ["coreos.com:4001", "coreos.com:4002"] peers = ["coreos.com:4001", "coreos.com:4002"]
machines_file = "/tmp/machines" peers_file = "/tmp/peers"
max_cluster_size = 10 max_cluster_size = 10
max_result_buffer = 512 max_result_buffer = 512
max_retry_attempts = 5 max_retry_attempts = 5
@ -33,24 +32,24 @@ func TestConfigTOML(t *testing.T) {
web_url = "/web" web_url = "/web"
[peer] [peer]
advertised_url = "127.0.0.1:7002" addr = "127.0.0.1:7002"
ca_file = "/tmp/peer/file.ca" ca_file = "/tmp/peer/file.ca"
cert_file = "/tmp/peer/file.cert" cert_file = "/tmp/peer/file.cert"
key_file = "/tmp/peer/file.key" key_file = "/tmp/peer/file.key"
listen_host = "127.0.0.1:7003" bind_addr = "127.0.0.1:7003"
` `
c := NewConfig() c := NewConfig()
_, err := toml.Decode(content, &c) _, err := toml.Decode(content, &c)
assert.Nil(t, err, "") 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.CAFile, "/tmp/file.ca", "")
assert.Equal(t, c.CertFile, "/tmp/file.cert", "") 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.DataDir, "/tmp/data", "")
assert.Equal(t, c.KeyFile, "/tmp/file.key", "") assert.Equal(t, c.KeyFile, "/tmp/file.key", "")
assert.Equal(t, c.ListenHost, "127.0.0.1:4003", "") assert.Equal(t, c.BindAddr, "127.0.0.1:4003", "")
assert.Equal(t, c.Machines, []string{"coreos.com:4001", "coreos.com:4002"}, "") assert.Equal(t, c.Peers, []string{"coreos.com:4001", "coreos.com:4002"}, "")
assert.Equal(t, c.MachinesFile, "/tmp/machines", "") assert.Equal(t, c.PeersFile, "/tmp/peers", "")
assert.Equal(t, c.MaxClusterSize, 10, "") assert.Equal(t, c.MaxClusterSize, 10, "")
assert.Equal(t, c.MaxResultBuffer, 512, "") assert.Equal(t, c.MaxResultBuffer, 512, "")
assert.Equal(t, c.MaxRetryAttempts, 5, "") assert.Equal(t, c.MaxRetryAttempts, 5, "")
@ -59,11 +58,11 @@ func TestConfigTOML(t *testing.T) {
assert.Equal(t, c.Verbose, true, "") assert.Equal(t, c.Verbose, true, "")
assert.Equal(t, c.VeryVerbose, true, "") assert.Equal(t, c.VeryVerbose, true, "")
assert.Equal(t, c.WebURL, "/web", "") 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.CAFile, "/tmp/peer/file.ca", "")
assert.Equal(t, c.Peer.CertFile, "/tmp/peer/file.cert", "") 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.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. // Ensures that a configuration can be retrieved from environment variables.
@ -71,12 +70,12 @@ func TestConfigEnv(t *testing.T) {
os.Setenv("ETCD_CA_FILE", "/tmp/file.ca") os.Setenv("ETCD_CA_FILE", "/tmp/file.ca")
os.Setenv("ETCD_CERT_FILE", "/tmp/file.cert") os.Setenv("ETCD_CERT_FILE", "/tmp/file.cert")
os.Setenv("ETCD_CPU_PROFILE_FILE", "XXX") os.Setenv("ETCD_CPU_PROFILE_FILE", "XXX")
os.Setenv("ETCD_CORS", "localhost:4001,localhost:4002") os.Setenv("ETCD_CORS_ORIGINS", "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_KEY_FILE", "/tmp/file.key")
os.Setenv("ETCD_LISTEN_HOST", "127.0.0.1:4003") os.Setenv("ETCD_BIND_ADDR", "127.0.0.1:4003")
os.Setenv("ETCD_MACHINES", "coreos.com:4001,coreos.com:4002") os.Setenv("ETCD_PEERS", "coreos.com:4001,coreos.com:4002")
os.Setenv("ETCD_MACHINES_FILE", "/tmp/machines") os.Setenv("ETCD_PEERS_FILE", "/tmp/peers")
os.Setenv("ETCD_MAX_CLUSTER_SIZE", "10") os.Setenv("ETCD_MAX_CLUSTER_SIZE", "10")
os.Setenv("ETCD_MAX_RESULT_BUFFER", "512") os.Setenv("ETCD_MAX_RESULT_BUFFER", "512")
os.Setenv("ETCD_MAX_RETRY_ATTEMPTS", "5") os.Setenv("ETCD_MAX_RETRY_ATTEMPTS", "5")
@ -85,22 +84,22 @@ func TestConfigEnv(t *testing.T) {
os.Setenv("ETCD_VERBOSE", "1") os.Setenv("ETCD_VERBOSE", "1")
os.Setenv("ETCD_VERY_VERBOSE", "yes") os.Setenv("ETCD_VERY_VERBOSE", "yes")
os.Setenv("ETCD_WEB_URL", "/web") 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_CA_FILE", "/tmp/peer/file.ca")
os.Setenv("ETCD_PEER_CERT_FILE", "/tmp/peer/file.cert") os.Setenv("ETCD_PEER_CERT_FILE", "/tmp/peer/file.cert")
os.Setenv("ETCD_PEER_KEY_FILE", "/tmp/peer/file.key") 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 := NewConfig()
c.LoadEnv() c.LoadEnv()
assert.Equal(t, c.CAFile, "/tmp/file.ca", "") assert.Equal(t, c.CAFile, "/tmp/file.ca", "")
assert.Equal(t, c.CertFile, "/tmp/file.cert", "") 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.DataDir, "/tmp/data", "")
assert.Equal(t, c.KeyFile, "/tmp/file.key", "") assert.Equal(t, c.KeyFile, "/tmp/file.key", "")
assert.Equal(t, c.ListenHost, "127.0.0.1:4003", "") assert.Equal(t, c.BindAddr, "127.0.0.1:4003", "")
assert.Equal(t, c.Machines, []string{"coreos.com:4001", "coreos.com:4002"}, "") assert.Equal(t, c.Peers, []string{"coreos.com:4001", "coreos.com:4002"}, "")
assert.Equal(t, c.MachinesFile, "/tmp/machines", "") assert.Equal(t, c.PeersFile, "/tmp/peers", "")
assert.Equal(t, c.MaxClusterSize, 10, "") assert.Equal(t, c.MaxClusterSize, 10, "")
assert.Equal(t, c.MaxResultBuffer, 512, "") assert.Equal(t, c.MaxResultBuffer, 512, "")
assert.Equal(t, c.MaxRetryAttempts, 5, "") assert.Equal(t, c.MaxRetryAttempts, 5, "")
@ -109,26 +108,26 @@ func TestConfigEnv(t *testing.T) {
assert.Equal(t, c.Verbose, true, "") assert.Equal(t, c.Verbose, true, "")
assert.Equal(t, c.VeryVerbose, true, "") assert.Equal(t, c.VeryVerbose, true, "")
assert.Equal(t, c.WebURL, "/web", "") 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.CAFile, "/tmp/peer/file.ca", "")
assert.Equal(t, c.Peer.CertFile, "/tmp/peer/file.cert", "") 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.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 the advertised url can be parsed from the environment. // Ensures that a the advertised url can be parsed from the environment.
func TestConfigAdvertisedUrlEnv(t *testing.T) { func TestConfigAddrEnv(t *testing.T) {
withEnv("ETCD_ADVERTISED_URL", "127.0.0.1:4002", func(c *Config) { withEnv("ETCD_ADDR", "127.0.0.1:4002", func(c *Config) {
assert.Nil(t, c.LoadEnv(), "") 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. // Ensures that a the advertised flag can be parsed.
func TestConfigAdvertisedUrlFlag(t *testing.T) { func TestConfigAddrFlag(t *testing.T) {
c := NewConfig() c := NewConfig()
assert.Nil(t, c.LoadFlags([]string{"-c", "127.0.0.1:4002"}), "") assert.Nil(t, c.LoadFlags([]string{"-addr", "127.0.0.1:4002"}), "")
assert.Equal(t, c.AdvertisedUrl, "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. // Ensures that a the CA file can be parsed from the environment.
@ -142,7 +141,7 @@ func TestConfigCAFileEnv(t *testing.T) {
// Ensures that a the CA file flag can be parsed. // Ensures that a the CA file flag can be parsed.
func TestConfigCAFileFlag(t *testing.T) { func TestConfigCAFileFlag(t *testing.T) {
c := NewConfig() 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", "") assert.Equal(t, c.CAFile, "/tmp/file.ca", "")
} }
@ -157,7 +156,7 @@ func TestConfigCertFileEnv(t *testing.T) {
// Ensures that a the Cert file flag can be parsed. // Ensures that a the Cert file flag can be parsed.
func TestConfigCertFileFlag(t *testing.T) { func TestConfigCertFileFlag(t *testing.T) {
c := NewConfig() 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", "") assert.Equal(t, c.CertFile, "/tmp/file.cert", "")
} }
@ -172,53 +171,53 @@ func TestConfigKeyFileEnv(t *testing.T) {
// Ensures that a the Key file flag can be parsed. // Ensures that a the Key file flag can be parsed.
func TestConfigKeyFileFlag(t *testing.T) { func TestConfigKeyFileFlag(t *testing.T) {
c := NewConfig() 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", "") assert.Equal(t, c.KeyFile, "/tmp/file.key", "")
} }
// Ensures that a the Listen Host can be parsed from the environment. // Ensures that a the Listen Host can be parsed from the environment.
func TestConfigListenHostEnv(t *testing.T) { func TestConfigBindAddrEnv(t *testing.T) {
withEnv("ETCD_LISTEN_HOST", "127.0.0.1:4003", func(c *Config) { withEnv("ETCD_BIND_ADDR", "127.0.0.1:4003", func(c *Config) {
assert.Nil(t, c.LoadEnv(), "") 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. // Ensures that a the Listen Host file flag can be parsed.
func TestConfigListenHostFlag(t *testing.T) { func TestConfigBindAddrFlag(t *testing.T) {
c := NewConfig() c := NewConfig()
assert.Nil(t, c.LoadFlags([]string{"-cl", "127.0.0.1:4003"}), "") assert.Nil(t, c.LoadFlags([]string{"-bind-addr", "127.0.0.1:4003"}), "")
assert.Equal(t, c.ListenHost, "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. // Ensures that the peers can be parsed from the environment.
func TestConfigMachinesEnv(t *testing.T) { func TestConfigPeersEnv(t *testing.T) {
withEnv("ETCD_MACHINES", "coreos.com:4001,coreos.com:4002", func(c *Config) { withEnv("ETCD_PEERS", "coreos.com:4001,coreos.com:4002", func(c *Config) {
assert.Nil(t, c.LoadEnv(), "") 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. // Ensures that a the Peers flag can be parsed.
func TestConfigMachinesFlag(t *testing.T) { func TestConfigPeersFlag(t *testing.T) {
c := NewConfig() c := NewConfig()
assert.Nil(t, c.LoadFlags([]string{"-C", "coreos.com:4001,coreos.com:4002"}), "") assert.Nil(t, c.LoadFlags([]string{"-peers", "coreos.com:4001,coreos.com:4002"}), "")
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 the Machines File can be parsed from the environment. // Ensures that the Peers File can be parsed from the environment.
func TestConfigMachinesFileEnv(t *testing.T) { func TestConfigPeersFileEnv(t *testing.T) {
withEnv("ETCD_MACHINES_FILE", "/tmp/machines", func(c *Config) { withEnv("ETCD_PEERS_FILE", "/tmp/peers", func(c *Config) {
assert.Nil(t, c.LoadEnv(), "") 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. // Ensures that a the Peers File flag can be parsed.
func TestConfigMachinesFileFlag(t *testing.T) { func TestConfigPeersFileFlag(t *testing.T) {
c := NewConfig() c := NewConfig()
assert.Nil(t, c.LoadFlags([]string{"-CF", "/tmp/machines"}), "") assert.Nil(t, c.LoadFlags([]string{"-peers-file", "/tmp/peers"}), "")
assert.Equal(t, c.MachinesFile, "/tmp/machines", "") assert.Equal(t, c.PeersFile, "/tmp/peers", "")
} }
// Ensures that the Max Cluster Size can be parsed from the environment. // Ensures that the Max Cluster Size can be parsed from the environment.
@ -232,7 +231,7 @@ func TestConfigMaxClusterSizeEnv(t *testing.T) {
// Ensures that a the Max Cluster Size flag can be parsed. // Ensures that a the Max Cluster Size flag can be parsed.
func TestConfigMaxClusterSizeFlag(t *testing.T) { func TestConfigMaxClusterSizeFlag(t *testing.T) {
c := NewConfig() 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, "") assert.Equal(t, c.MaxClusterSize, 5, "")
} }
@ -247,7 +246,7 @@ func TestConfigMaxResultBufferEnv(t *testing.T) {
// Ensures that a the Max Result Buffer flag can be parsed. // Ensures that a the Max Result Buffer flag can be parsed.
func TestConfigMaxResultBufferFlag(t *testing.T) { func TestConfigMaxResultBufferFlag(t *testing.T) {
c := NewConfig() 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, "") assert.Equal(t, c.MaxResultBuffer, 512, "")
} }
@ -262,7 +261,7 @@ func TestConfigMaxRetryAttemptsEnv(t *testing.T) {
// Ensures that a the Max Retry Attempts flag can be parsed. // Ensures that a the Max Retry Attempts flag can be parsed.
func TestConfigMaxRetryAttemptsFlag(t *testing.T) { func TestConfigMaxRetryAttemptsFlag(t *testing.T) {
c := NewConfig() 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, "") assert.Equal(t, c.MaxRetryAttempts, 10, "")
} }
@ -277,7 +276,7 @@ func TestConfigNameEnv(t *testing.T) {
// Ensures that a the Name flag can be parsed. // Ensures that a the Name flag can be parsed.
func TestConfigNameFlag(t *testing.T) { func TestConfigNameFlag(t *testing.T) {
c := NewConfig() 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", "") assert.Equal(t, c.Name, "test-name", "")
} }
@ -337,23 +336,23 @@ func TestConfigWebURLEnv(t *testing.T) {
// Ensures that a the Web URL flag can be parsed. // Ensures that a the Web URL flag can be parsed.
func TestConfigWebURLFlag(t *testing.T) { func TestConfigWebURLFlag(t *testing.T) {
c := NewConfig() c := NewConfig()
assert.Nil(t, c.LoadFlags([]string{"-w", "/web"}), "") assert.Nil(t, c.LoadFlags([]string{"-web-url", "/web"}), "")
assert.Equal(t, c.WebURL, "/web", "") assert.Equal(t, c.WebURL, "/web", "")
} }
// Ensures that the Peer Advertised URL can be parsed from the environment. // Ensures that the Peer Advertised URL can be parsed from the environment.
func TestConfigPeerAdvertisedUrlEnv(t *testing.T) { func TestConfigPeerAddrEnv(t *testing.T) {
withEnv("ETCD_PEER_ADVERTISED_URL", "localhost:7002", func(c *Config) { withEnv("ETCD_PEER_ADDR", "localhost:7002", func(c *Config) {
assert.Nil(t, c.LoadEnv(), "") 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. // Ensures that a the Peer Advertised URL flag can be parsed.
func TestConfigPeerAdvertisedUrlFlag(t *testing.T) { func TestConfigPeerAddrFlag(t *testing.T) {
c := NewConfig() c := NewConfig()
assert.Nil(t, c.LoadFlags([]string{"-s", "localhost:7002"}), "") assert.Nil(t, c.LoadFlags([]string{"-peer-addr", "localhost:7002"}), "")
assert.Equal(t, c.Peer.AdvertisedUrl, "localhost:7002", "") assert.Equal(t, c.Peer.Addr, "localhost:7002", "")
} }
// Ensures that the Peer CA File can be parsed from the environment. // Ensures that the Peer CA File can be parsed from the environment.
@ -367,7 +366,7 @@ func TestConfigPeerCAFileEnv(t *testing.T) {
// Ensures that a the Peer CA file flag can be parsed. // Ensures that a the Peer CA file flag can be parsed.
func TestConfigPeerCAFileFlag(t *testing.T) { func TestConfigPeerCAFileFlag(t *testing.T) {
c := NewConfig() 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", "") assert.Equal(t, c.Peer.CAFile, "/tmp/peer/file.ca", "")
} }
@ -382,7 +381,7 @@ func TestConfigPeerCertFileEnv(t *testing.T) {
// Ensures that a the Cert file flag can be parsed. // Ensures that a the Cert file flag can be parsed.
func TestConfigPeerCertFileFlag(t *testing.T) { func TestConfigPeerCertFileFlag(t *testing.T) {
c := NewConfig() 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", "") assert.Equal(t, c.Peer.CertFile, "/tmp/peer/file.cert", "")
} }
@ -397,66 +396,64 @@ func TestConfigPeerKeyFileEnv(t *testing.T) {
// Ensures that a the Peer Key file flag can be parsed. // Ensures that a the Peer Key file flag can be parsed.
func TestConfigPeerKeyFileFlag(t *testing.T) { func TestConfigPeerKeyFileFlag(t *testing.T) {
c := NewConfig() 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", "") assert.Equal(t, c.Peer.KeyFile, "/tmp/peer/file.key", "")
} }
// Ensures that the Peer Listen Host can be parsed from the environment. // Ensures that the Peer Listen Host can be parsed from the environment.
func TestConfigPeerListenHostEnv(t *testing.T) { func TestConfigPeerBindAddrEnv(t *testing.T) {
withEnv("ETCD_PEER_LISTEN_HOST", "localhost:7004", func(c *Config) { withEnv("ETCD_PEER_BIND_ADDR", "localhost:7004", func(c *Config) {
assert.Nil(t, c.LoadEnv(), "") 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. // Ensures that a the Peer Listen Host file flag can be parsed.
func TestConfigPeerListenHostFlag(t *testing.T) { func TestConfigPeerBindAddrFlag(t *testing.T) {
c := NewConfig() c := NewConfig()
assert.Nil(t, c.LoadFlags([]string{"-sl", "127.0.0.1:4003"}), "") assert.Nil(t, c.LoadFlags([]string{"-peer-bind-addr", "127.0.0.1:4003"}), "")
assert.Equal(t, c.Peer.ListenHost, "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. // Ensures that a system config field is overridden by a custom config field.
func TestConfigCustomConfigOverrideSystemConfig(t *testing.T) { func TestConfigCustomConfigOverrideSystemConfig(t *testing.T) {
system := `advertised_url = "127.0.0.1:5000"` system := `addr = "127.0.0.1:5000"`
custom := `advertised_url = "127.0.0.1:6000"` custom := `addr = "127.0.0.1:6000"`
withTempFile(system, func(p1 string) { withTempFile(system, func(p1 string) {
withTempFile(custom, func(p2 string) { withTempFile(custom, func(p2 string) {
c := NewConfig() c := NewConfig()
c.SystemPath = p1 c.SystemPath = p1
assert.Nil(t, c.Load([]string{"-config", p2}), "") 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. // Ensures that a custom config field is overridden by an environment variable.
func TestConfigEnvVarOverrideCustomConfig(t *testing.T) { func TestConfigEnvVarOverrideCustomConfig(t *testing.T) {
os.Setenv("ETCD_PEER_ADVERTISED_URL", "127.0.0.1:8000") os.Setenv("ETCD_PEER_ADDR", "127.0.0.1:8000")
defer os.Setenv("ETCD_PEER_ADVERTISED_URL", "") 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) { withTempFile(custom, func(path string) {
c := NewConfig() c := NewConfig()
c.SystemPath = "" c.SystemPath = ""
assert.Nil(t, c.Load([]string{"-config", path}), "") 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. // Ensures that an environment variable field is overridden by a command line argument.
func TestConfigCLIArgsOverrideEnvVar(t *testing.T) { func TestConfigCLIArgsOverrideEnvVar(t *testing.T) {
os.Setenv("ETCD_ADVERTISED_URL", "127.0.0.1:1000") os.Setenv("ETCD_ADDR", "127.0.0.1:1000")
defer os.Setenv("ETCD_ADVERTISED_URL", "") defer os.Setenv("ETCD_ADDR", "")
c := NewConfig() c := NewConfig()
c.SystemPath = "" c.SystemPath = ""
assert.Nil(t, c.Load([]string{"-c", "127.0.0.1:2000"}), "") assert.Nil(t, c.Load([]string{"-addr", "127.0.0.1:2000"}), "")
assert.Equal(t, c.AdvertisedUrl, "http://127.0.0.1:2000", "") assert.Equal(t, c.Addr, "http://127.0.0.1:2000", "")
} }
//-------------------------------------- //--------------------------------------
// Helpers // Helpers
//-------------------------------------- //--------------------------------------

View File

@ -16,4 +16,3 @@ type Info struct {
RaftTLS TLSInfo `json:"raftTLS"` RaftTLS TLSInfo `json:"raftTLS"`
EtcdTLS TLSInfo `json:"etcdTLS"` EtcdTLS TLSInfo `json:"etcdTLS"`
} }

View File

@ -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. // Make sure we're not getting a cached value from the registry.
ps.registry.Invalidate(c.Name) 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 { if _, ok := ps.registry.ClientURL(c.Name); ok {
return b, nil return b, nil
} }
// Check machine number in the cluster // Check peer number in the cluster
if ps.registry.Count() == ps.MaxClusterSize { if ps.registry.Count() == ps.MaxClusterSize {
log.Debug("Reject join request from ", c.Name) 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) ps.registry.Register(c.Name, c.RaftURL, c.EtcdURL)
// Add peer in raft // Add peer in raft

View File

@ -28,7 +28,7 @@ type PeerServer struct {
joinIndex uint64 joinIndex uint64
name string name string
url string url string
listenHost string bindAddr string
tlsConf *TLSConfig tlsConf *TLSConfig
tlsInfo *TLSInfo tlsInfo *TLSInfo
followersStats *raftFollowersStats followersStats *raftFollowersStats
@ -53,16 +53,16 @@ type snapshotConf struct {
writesThr uint64 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{ s := &PeerServer{
name: name, name: name,
url: url, url: url,
listenHost: listenHost, bindAddr: bindAddr,
tlsConf: tlsConf, tlsConf: tlsConf,
tlsInfo: tlsInfo, tlsInfo: tlsInfo,
registry: registry, registry: registry,
store: store, store: store,
snapConf: &snapshotConf{time.Second * 3, 0, uint64(snapCount)}, snapConf: &snapshotConf{time.Second * 3, 0, uint64(snapshotCount)},
followersStats: &raftFollowersStats{ followersStats: &raftFollowersStats{
Leader: name, Leader: name,
Followers: make(map[string]*raftFollowerStats), Followers: make(map[string]*raftFollowerStats),
@ -130,7 +130,7 @@ func (s *PeerServer) ListenAndServe(snapshot bool, cluster []string) error {
} }
ok := s.joinCluster(cluster) ok := s.joinCluster(cluster)
if !ok { 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) log.Debugf("%s restart as a follower", s.name)
@ -228,23 +228,23 @@ func (s *PeerServer) startAsFollower(cluster []string) {
if ok { if ok {
return 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) 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 // Start to listen and response raft command
func (s *PeerServer) startTransport(scheme string, tlsConf tls.Config) error { 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() router := mux.NewRouter()
s.httpServer = &http.Server{ s.httpServer = &http.Server{
Handler: router, Handler: router,
TLSConfig: &tlsConf, TLSConfig: &tlsConf,
Addr: s.listenHost, Addr: s.bindAddr,
} }
// internal commands // internal commands
@ -312,14 +312,14 @@ func (s *PeerServer) Upgradable() error {
} }
func (s *PeerServer) joinCluster(cluster []string) bool { func (s *PeerServer) joinCluster(cluster []string) bool {
for _, machine := range cluster { for _, peer := range cluster {
if len(machine) == 0 { if len(peer) == 0 {
continue continue
} }
err := s.joinByMachine(s.raftServer, machine, s.tlsConf.Scheme) err := s.joinByPeer(s.raftServer, peer, s.tlsConf.Scheme)
if err == nil { 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 return true
} else { } else {
@ -327,21 +327,21 @@ func (s *PeerServer) joinCluster(cluster []string) bool {
log.Fatal(err) 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 return false
} }
// Send join requests to machine. // Send join requests to peer.
func (s *PeerServer) joinByMachine(server raft.Server, machine string, scheme string) error { func (s *PeerServer) joinByPeer(server raft.Server, peer string, scheme string) error {
var b bytes.Buffer var b bytes.Buffer
// t must be ok // t must be ok
t, _ := server.Transporter().(*transporter) t, _ := server.Transporter().(*transporter)
// Our version must match the leaders version // 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) version, err := getVersion(t, versionURL)
if err != nil { if err != nil {
return fmt.Errorf("Error during join version check: %v", err) 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())) 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()) 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) resp, req, err = t.Post(address, &b)
} else if resp.StatusCode == http.StatusBadRequest { } 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) decoder := json.NewDecoder(resp.Body)
err := &etcdErr.Error{} err := &etcdErr.Error{}
decoder.Decode(err) decoder.Decode(err)

View File

@ -12,7 +12,7 @@ import (
"github.com/coreos/etcd/store" "github.com/coreos/etcd/store"
) )
// The location of the machine URL data. // The location of the peer URL data.
const RegistryKey = "/_etcd/machines" const RegistryKey = "/_etcd/machines"
// The Registry stores URL information for nodes. // The Registry stores URL information for nodes.
@ -168,7 +168,7 @@ func (r *Registry) load(name string) {
// Parse as a query string. // Parse as a query string.
m, err := url.ParseQuery(e.Value) m, err := url.ParseQuery(e.Value)
if err != nil { 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. // Create node.

View File

@ -36,12 +36,12 @@ type Server struct {
} }
// Creates a new Server. // 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{ s := &Server{
Server: http.Server{ Server: http.Server{
Handler: mux.NewRouter(), Handler: mux.NewRouter(),
TLSConfig: &tlsConf.Server, TLSConfig: &tlsConf.Server,
Addr: listenHost, Addr: bindAddr,
}, },
name: name, name: name,
store: store, store: store,
@ -102,7 +102,8 @@ func (s *Server) installV1() {
s.handleFuncV1("/v1/keys/{key:.*}", v1.DeleteKeyHandler).Methods("DELETE") s.handleFuncV1("/v1/keys/{key:.*}", v1.DeleteKeyHandler).Methods("DELETE")
s.handleFuncV1("/v1/watch/{key:.*}", v1.WatchKeyHandler).Methods("GET", "POST") s.handleFuncV1("/v1/watch/{key:.*}", v1.WatchKeyHandler).Methods("GET", "POST")
s.handleFunc("/v1/leader", s.GetLeaderHandler).Methods("GET") 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/self", s.GetStatsHandler).Methods("GET")
s.handleFunc("/v1/stats/leader", s.GetLeaderStatsHandler).Methods("GET") s.handleFunc("/v1/stats/leader", s.GetLeaderStatsHandler).Methods("GET")
s.handleFunc("/v1/stats/store", s.GetStoreStatsHandler).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.PutHandler).Methods("PUT")
s.handleFuncV2("/v2/keys/{key:.*}", v2.DeleteHandler).Methods("DELETE") s.handleFuncV2("/v2/keys/{key:.*}", v2.DeleteHandler).Methods("DELETE")
s.handleFunc("/v2/leader", s.GetLeaderHandler).Methods("GET") 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/self", s.GetStatsHandler).Methods("GET")
s.handleFunc("/v2/stats/leader", s.GetLeaderStatsHandler).Methods("GET") s.handleFunc("/v2/stats/leader", s.GetLeaderStatsHandler).Methods("GET")
s.handleFunc("/v2/stats/store", s.GetStoreStatsHandler).Methods("GET") s.handleFunc("/v2/stats/store", s.GetStoreStatsHandler).Methods("GET")
@ -339,11 +341,11 @@ func (s *Server) GetLeaderHandler(w http.ResponseWriter, req *http.Request) erro
return nil return nil
} }
// Handler to return all the known machines in the current cluster. // Handler to return all the known peers in the current cluster.
func (s *Server) GetMachinesHandler(w http.ResponseWriter, req *http.Request) error { func (s *Server) GetPeersHandler(w http.ResponseWriter, req *http.Request) error {
machines := s.registry.ClientURLs(s.peerServer.RaftServer().Leader(), s.name) peers := s.registry.ClientURLs(s.peerServer.RaftServer().Leader(), s.name)
w.WriteHeader(http.StatusOK) w.WriteHeader(http.StatusOK)
w.Write([]byte(strings.Join(machines, ", "))) w.Write([]byte(strings.Join(peers, ", ")))
return nil return nil
} }

View File

@ -32,7 +32,7 @@ func (info TLSInfo) Config() (TLSConfig, error) {
tlsCert, err := tls.LoadX509KeyPair(info.CertFile, info.KeyFile) tlsCert, err := tls.LoadX509KeyPair(info.CertFile, info.KeyFile)
if err != nil { if err != nil {
return t, err return t, err
} }
t.Scheme = "https" t.Scheme = "https"

View File

@ -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 // slice of the substrings between the separator with all leading and trailing
// white space removed, as defined by Unicode. // white space removed, as defined by Unicode.
func trimsplit(s, sep string) []string { func trimsplit(s, sep string) []string {
raw := strings.Split(s, ",") raw := strings.Split(s, ",")
trimmed := make([]string, 0) trimmed := make([]string, 0)
for _, r := range raw { for _, r := range raw {
trimmed = append(trimmed, strings.TrimSpace(r)) trimmed = append(trimmed, strings.TrimSpace(r))
} }
return trimmed return trimmed
} }

View File

@ -31,7 +31,7 @@ func TestInternalVersion(t *testing.T) {
procAttr := new(os.ProcAttr) procAttr := new(os.ProcAttr)
procAttr.Files = []*os.File{nil, os.Stdout, os.Stderr} 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", "-force-config", "-data-dir=/tmp/node1", "-peers=" + fakeURL.Host}
process, err := os.StartProcess(EtcdBinPath, args, procAttr) process, err := os.StartProcess(EtcdBinPath, args, procAttr)
if err != nil { if err != nil {
@ -53,4 +53,3 @@ func TestInternalVersion(t *testing.T) {
return return
} }
} }

View File

@ -55,9 +55,8 @@ func TestKillLeader(t *testing.T) {
totalTime += take totalTime += take
avgTime := totalTime / (time.Duration)(i+1) avgTime := totalTime / (time.Duration)(i+1)
fmt.Println("Total time:", totalTime, "; Avg time:", avgTime) fmt.Println("Total time:", totalTime, "; Avg time:", avgTime)
etcds[num], err = os.StartProcess(EtcdBinPath, argGroup[num], procAttr) etcds[num], err = os.StartProcess(EtcdBinPath, argGroup[num], procAttr)
} }
stop <- true stop <- true
} }

View File

@ -8,8 +8,8 @@ import (
"time" "time"
) )
// TestKillRandom kills random machines in the cluster and // TestKillRandom kills random peers in the cluster and
// restart them after all other machines agree on the same leader // restart them after all other peers agree on the same leader
func TestKillRandom(t *testing.T) { func TestKillRandom(t *testing.T) {
procAttr := new(os.ProcAttr) procAttr := new(os.ProcAttr)
procAttr.Files = []*os.File{nil, os.Stdout, os.Stderr} procAttr.Files = []*os.File{nil, os.Stdout, os.Stderr}
@ -73,4 +73,3 @@ func TestKillRandom(t *testing.T) {
stop <- true stop <- true
} }

View File

@ -55,4 +55,3 @@ func TestMultiNodeKillOne(t *testing.T) {
stop <- true stop <- true
<-stop <-stop
} }

View File

@ -42,7 +42,7 @@ func TestRemoveNode(t *testing.T) {
} }
if len(resp) != 2 { if len(resp) != 2 {
t.Fatal("cannot remove machine") t.Fatal("cannot remove peer")
} }
if i == 1 { if i == 1 {
@ -50,7 +50,7 @@ func TestRemoveNode(t *testing.T) {
etcds[2], err = os.StartProcess(EtcdBinPath, argGroup[2], procAttr) etcds[2], err = os.StartProcess(EtcdBinPath, argGroup[2], procAttr)
} else { } else {
// rejoin without log // rejoin without log
etcds[2], err = os.StartProcess(EtcdBinPath, append(argGroup[2], "-f"), procAttr) etcds[2], err = os.StartProcess(EtcdBinPath, append(argGroup[2], "-force-config"), procAttr)
} }
if err != nil { if err != nil {
@ -66,7 +66,7 @@ func TestRemoveNode(t *testing.T) {
} }
if len(resp) != 3 { 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 { if len(resp) != 2 {
t.Fatal("cannot remove machine") t.Fatal("cannot remove peer")
} }
if i == 1 { if i == 1 {
@ -93,7 +93,7 @@ func TestRemoveNode(t *testing.T) {
etcds[2], err = os.StartProcess(EtcdBinPath, append(argGroup[2]), procAttr) etcds[2], err = os.StartProcess(EtcdBinPath, append(argGroup[2]), procAttr)
} else { } else {
// rejoin without log // rejoin without log
etcds[2], err = os.StartProcess(EtcdBinPath, append(argGroup[2], "-f"), procAttr) etcds[2], err = os.StartProcess(EtcdBinPath, append(argGroup[2], "-force-config"), procAttr)
} }
if err != nil { if err != nil {
@ -109,7 +109,7 @@ func TestRemoveNode(t *testing.T) {
} }
if len(resp) != 3 { if len(resp) != 3 {
t.Fatalf("add machine fails #2 (%d != 3)", len(resp)) t.Fatalf("add peer fails #2 (%d != 3)", len(resp))
} }
} }
} }

View File

@ -14,9 +14,9 @@ import (
func TestSimpleSnapshot(t *testing.T) { func TestSimpleSnapshot(t *testing.T) {
procAttr := new(os.ProcAttr) procAttr := new(os.ProcAttr)
procAttr.Files = []*os.File{nil, os.Stdout, os.Stderr} 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) process, err := os.StartProcess(EtcdBinPath, append(args, "-force-config"), procAttr)
if err != nil { if err != nil {
t.Fatal("start process failed:" + err.Error()) t.Fatal("start process failed:" + err.Error())
} }

View File

@ -13,9 +13,9 @@ import (
func TestSingleNodeRecovery(t *testing.T) { func TestSingleNodeRecovery(t *testing.T) {
procAttr := new(os.ProcAttr) procAttr := new(os.ProcAttr)
procAttr.Files = []*os.File{nil, os.Stdout, os.Stderr} 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) process, err := os.StartProcess(EtcdBinPath, append(args, "-force-config"), procAttr)
if err != nil { if err != nil {
t.Fatal("start process failed:" + err.Error()) t.Fatal("start process failed:" + err.Error())
return return
@ -65,4 +65,3 @@ func TestSingleNodeRecovery(t *testing.T) {
t.Fatalf("Recovery Get failed with %s %s %v", result.Key, result.Value, result.TTL) t.Fatalf("Recovery Get failed with %s %s %v", result.Key, result.Value, result.TTL)
} }
} }

View File

@ -12,7 +12,7 @@ import (
func TestSingleNode(t *testing.T) { func TestSingleNode(t *testing.T) {
procAttr := new(os.ProcAttr) procAttr := new(os.ProcAttr)
procAttr.Files = []*os.File{nil, os.Stdout, os.Stderr} procAttr.Files = []*os.File{nil, os.Stdout, os.Stderr}
args := []string{"etcd", "-n=node1", "-f", "-d=/tmp/node1"} args := []string{"etcd", "-name=node1", "-force-config", "-data-dir=/tmp/node1"}
process, err := os.StartProcess(EtcdBinPath, args, procAttr) process, err := os.StartProcess(EtcdBinPath, args, procAttr)
if err != nil { 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") t.Fatalf("Set 5 expecting error when setting key with blank (incorrect) previous value")
} }
} }

View File

@ -73,25 +73,25 @@ func Set(stop chan bool) {
func CreateCluster(size int, procAttr *os.ProcAttr, ssl bool) ([][]string, []*os.Process, error) { func CreateCluster(size int, procAttr *os.ProcAttr, ssl bool) ([][]string, []*os.Process, error) {
argGroup := make([][]string, size) argGroup := make([][]string, size)
sslServer1 := []string{"-serverCAFile=../../fixtures/ca/ca.crt", sslServer1 := []string{"-peer-ca-file=../../fixtures/ca/ca.crt",
"-serverCert=../../fixtures/ca/server.crt", "-peer-cert-file=../../fixtures/ca/server.crt",
"-serverKey=../../fixtures/ca/server.key.insecure", "-peer-key-file=../../fixtures/ca/server.key.insecure",
} }
sslServer2 := []string{"-serverCAFile=../../fixtures/ca/ca.crt", sslServer2 := []string{"-peer-ca-file=../../fixtures/ca/ca.crt",
"-serverCert=../../fixtures/ca/server2.crt", "-peer-cert-file=../../fixtures/ca/server2.crt",
"-serverKey=../../fixtures/ca/server2.key.insecure", "-peer-cert-file=../../fixtures/ca/server2.key.insecure",
} }
for i := 0; i < size; i++ { for i := 0; i < size; i++ {
if i == 0 { if i == 0 {
argGroup[i] = []string{"etcd", "-d=/tmp/node1", "-n=node1"} argGroup[i] = []string{"etcd", "-data-dir=/tmp/node1", "-name=node1"}
if ssl { if ssl {
argGroup[i] = append(argGroup[i], sslServer1...) argGroup[i] = append(argGroup[i], sslServer1...)
} }
} else { } else {
strI := strconv.Itoa(i + 1) 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 { if ssl {
argGroup[i] = append(argGroup[i], sslServer2...) argGroup[i] = append(argGroup[i], sslServer2...)
} }
@ -102,7 +102,7 @@ func CreateCluster(size int, procAttr *os.ProcAttr, ssl bool) ([][]string, []*os
for i, _ := range etcds { for i, _ := range etcds {
var err error var err error
etcds[i], err = os.StartProcess(EtcdBinPath, append(argGroup[i], "-f"), procAttr) etcds[i], err = os.StartProcess(EtcdBinPath, append(argGroup[i], "-force-config"), procAttr)
if err != nil { if err != nil {
return nil, nil, err return nil, nil, err
} }

View File

@ -33,9 +33,9 @@ func TestV1SoloMigration(t *testing.T) {
procAttr := new(os.ProcAttr) procAttr := new(os.ProcAttr)
procAttr.Files = []*os.File{nil, os.Stdout, os.Stderr} procAttr.Files = []*os.File{nil, os.Stdout, os.Stderr}
args := []string{"etcd", fmt.Sprintf("-d=%s", nodepath)} args := []string{"etcd", fmt.Sprintf("-data-dir=%s", nodepath)}
args = append(args, "-c", "127.0.0.1:4001") args = append(args, "-addr", "127.0.0.1:4001")
args = append(args, "-s", "127.0.0.1:7001") args = append(args, "-peer-addr", "127.0.0.1:7001")
process, err := os.StartProcess(EtcdBinPath, args, procAttr) process, err := os.StartProcess(EtcdBinPath, args, procAttr)
if err != nil { if err != nil {
t.Fatal("start process failed:" + err.Error()) t.Fatal("start process failed:" + err.Error())
@ -75,9 +75,9 @@ func TestV1ClusterMigration(t *testing.T) {
procAttr := new(os.ProcAttr) procAttr := new(os.ProcAttr)
procAttr.Files = []*os.File{nil, os.Stdout, os.Stderr} procAttr.Files = []*os.File{nil, os.Stdout, os.Stderr}
args := []string{"etcd", fmt.Sprintf("-d=%s", nodepath)} args := []string{"etcd", fmt.Sprintf("-data-dir=%s", nodepath)}
args = append(args, "-c", fmt.Sprintf("127.0.0.1:%d", 4001 + i)) args = append(args, "-addr", fmt.Sprintf("127.0.0.1:%d", 4001+i))
args = append(args, "-s", fmt.Sprintf("127.0.0.1:%d", 7001 + i)) args = append(args, "-peer-addr", fmt.Sprintf("127.0.0.1:%d", 7001+i))
process, err := os.StartProcess(EtcdBinPath, args, procAttr) process, err := os.StartProcess(EtcdBinPath, args, procAttr)
if err != nil { if err != nil {
t.Fatal("start process failed:" + err.Error()) 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") resp, err := tests.Get("http://localhost:4001/v2/keys/message")
body := tests.ReadBody(resp) body := tests.ReadBody(resp)
assert.Nil(t, err, "") 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") assert.Equal(t, string(body), `{"errorCode":100,"message":"Key Not Found","cause":"/message","index":11}`+"\n")
// Ensure TTL'd message is removed. // Ensure TTL'd message is removed.

View File

@ -11,7 +11,7 @@ import (
func TestVersionCheck(t *testing.T) { func TestVersionCheck(t *testing.T) {
procAttr := new(os.ProcAttr) procAttr := new(os.ProcAttr)
procAttr.Files = []*os.File{nil, os.Stdout, os.Stderr} procAttr.Files = []*os.File{nil, os.Stdout, os.Stderr}
args := []string{"etcd", "-n=node1", "-f", "-d=/tmp/version_check"} args := []string{"etcd", "-name=node1", "-force-config", "-data-dir=/tmp/version_check"}
process, err := os.StartProcess(EtcdBinPath, args, procAttr) process, err := os.StartProcess(EtcdBinPath, args, procAttr)
if err != nil { if err != nil {
@ -43,4 +43,3 @@ func TestVersionCheck(t *testing.T) {
t.Fatal("Invalid version check: ", resp.StatusCode) t.Fatal("Invalid version check: ", resp.StatusCode)
} }
} }

View File

@ -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())) 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) { func send(method string, url string, bodyType string, body io.Reader) (*http.Response, error) {
c := NewHTTPClient() c := NewHTTPClient()
req, err := http.NewRequest(method, url, body) req, err := http.NewRequest(method, url, body)

View File

@ -2,7 +2,7 @@ package mock
import ( import (
"net/http" "net/http"
"github.com/coreos/etcd/store" "github.com/coreos/etcd/store"
"github.com/coreos/go-raft" "github.com/coreos/go-raft"
"github.com/stretchr/testify/mock" "github.com/stretchr/testify/mock"

View File

@ -10,10 +10,10 @@ import (
) )
const ( const (
testName = "ETCDTEST" testName = "ETCDTEST"
testClientURL = "localhost:4401" testClientURL = "localhost:4401"
testRaftURL = "localhost:7701" testRaftURL = "localhost:7701"
testSnapCount = 10000 testSnapshotCount = 10000
) )
// Starts a server in a temporary directory. // Starts a server in a temporary directory.
@ -23,7 +23,7 @@ func RunServer(f func(*server.Server)) {
store := store.New() store := store.New()
registry := server.NewRegistry(store) 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) s := server.New(testName, testClientURL, testClientURL, &server.TLSConfig{Scheme: "http"}, &server.TLSInfo{}, ps, registry, store)
ps.SetServer(s) ps.SetServer(s)