1
0
Fork 0

Remove old etcd.

This commit is contained in:
Willi Goesgens 2015-02-09 17:25:15 +01:00
parent f7a8264956
commit b85ee2956a
492 changed files with 0 additions and 87585 deletions

20
3rdParty/etcd/.header vendored
View File

@ -1,20 +0,0 @@
/*
Copyright 2013 CoreOS Inc.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
package x
import (
)

View File

@ -1,44 +0,0 @@
v0.3.0
* Add Compare-and-Delete support.
* Added prevNode to response objects.
* Added Discovery API.
* Add tracing and debug endpoints (Documentation/debugging.md).
* Improved logging of cluster events.
* go get github.com/coreos/etcd works.
* info file is no longer used.
* Snapshots are on by default.
* Statistics APIs documented.
v0.2.0
* Support directory creation and removal.
* Add Compare-and-Swap (CAS) support.
* Support recursive GETs.
* Support fully consistent GETs.
* Allow clients to watch specific paths.
* Allow clients to watch for key expiration.
* Unique key generation.
* Support hidden paths.
* Refactor low-level data store.
* Modularize store, server and API code.
* Integrate Gorilla Web Toolkit.
* Add tiered configuration (command line args, env variables, config file).
* Add peer protocol versioning.
* Add rolling upgrade support for future versions.
* Sync key expiration across cluster.
* Significantly improve test coverage.
* Improve migration testing.
* Configurable snapshot count.
* Reduce TCP connection count.
* Fix TCP connection leak.
* Bug Fixes: https://github.com/coreos/etcd/issues?milestone=1&state=closed
Contributors:
* Xiang Li (@xiangli-cmu)
* Ben Johnson (@benbjohnson)
* Brandon Philips (@philips)
* Yifan (@yifan-gu)
* Rob Szumski
* Hongchao Deng (@fengjingchao)
* Kelsey Hightower (@kelseyhightower)
* Adrián (@adrianlzt)
* Antonio Terreno (@aterreno)

View File

@ -1,75 +0,0 @@
# How to contribute
etcd is open source, Apache 2.0 licensed and accepts contributions via Github pull requests.
This document outlines some of the conventions on commit message formatting, contact points for developers and other resources to make getting your contribution into etcd easier.
# Email and chat
For simplicity etcd discussions happen on coreos-dev and in #coreos-dev.
As the community grows we will move to a dedicated mailing list and IRC channel.
- Email: [coreos-dev](https://groups.google.com/forum/#!forum/coreos-dev)
- IRC: #[coreos](irc://irc.freenode.org:6667/#coreos) IRC channel on freenode.org
## Getting Started
- Fork the repository on GitHub
- Read the README.md for build instructions
## Contribution flow
This is a rough outline of what a contributor's workflow looks like:
- Create a topic branch from where you want to base your work. This is usually master.
- Make commits of logical units.
- Make sure your commit messages are in the proper format, see below
- Push your changes to a topic branch in your fork of the repository.
- Submit a pull request to coreos/etcd
Thanks for you contributions!
### Format of the commit message
etcd follow a rough convention for commit messages borrowed from Angularjs.
This is an example of a commit:
```
feat(scripts/test-cluster): add a cluster test command
this uses tmux to setup a test cluster that you can easily kill and
start for debugging.
```
To make it more formal it looks something like this:
```
<type>(<scope>): <subject>
<BLANK LINE>
<body>
<BLANK LINE>
<footer>
```
The first line is the subject and should not be longer than 70 characters, the second line is always blank and other lines should be wrapped at 80 characters.
This allows the message to be easier to read on github as well as in various git tools.
### Subject line
The subject line contains succinct description of the change.
### Allowed <type>
- feat (feature)
- fix (bug fix)
- docs (documentation)
- style (formatting, missing semi colons, …)
- refactor
- test (when adding missing tests)
- chore (maintain)
### Allowed <scope>
Scopes could be anything specifying place of the commit change. For example store, api, etc.
### More details on commits
For more details see the [angularjs commit style guide](https://docs.google.com/a/coreos.com/document/d/1QrDFcIiPjSLDn3EL15IJygNPiHORgU1_OOAqWjiDU5Y/edit#).

View File

@ -1,12 +0,0 @@
FROM ubuntu:12.04
# Let's install go just like Docker (from source).
RUN apt-get update -q
RUN apt-get install -qy build-essential curl git
RUN curl -s https://go.googlecode.com/files/go1.2.src.tar.gz | tar -v -C /usr/local -xz
RUN cd /usr/local/go/src && ./make.bash --no-clean 2>&1
ENV PATH /usr/local/go/bin:$PATH
ADD . /opt/etcd
RUN cd /opt/etcd && ./build
EXPOSE 4001 7001
ENTRYPOINT ["/opt/etcd/bin/etcd"]

File diff suppressed because it is too large Load Diff

View File

@ -1,46 +0,0 @@
# Client libraries support matrix for etcd
As etcd features support is really uneven between client libraries, a compatibility matrix can be important.
We will consider in detail only the features of clients supporting the v2 API. Clients still supporting the v1 API *only* are listed below.
## v1-only clients
Clients supporting only the API version 1
- [justinsb/jetcd](https://github.com/justinsb/jetcd) Java
- [transitorykris/etcd-py](https://github.com/transitorykris/etcd-py) Python
- [russellhaering/txetcd](https://github.com/russellhaering/txetcd) Python
- [iconara/etcd-rb](https://github.com/iconara/etcd-rb) Ruby
- [jpfuentes2/etcd-ruby](https://github.com/jpfuentes2/etcd-ruby) Ruby
- [aterreno/etcd-clojure](https://github.com/aterreno/etcd-clojure) Clojure
- [marshall-lee/etcd.erl](https://github.com/marshall-lee/etcd.erl) Erlang
## v2 clients
The v2 API has a lot of features, we will categorize them in a few categories:
- **HTTPS Auth**: Support for SSL-certificate based authentication
- **Reconnect**: If the client is able to reconnect automatically to another server if one fails.
- **Mod/Lock**: Support for the locking module
- **Mod/Leader**: Support for the leader election module
- **GET,PUT,POST,DEL Features**: Support for all the modifiers when calling the etcd server with said HTTP method.
### Supported features matrix
| Client| [go-etcd](https://github.com/coreos/go-etcd) | [jetcd](https://github.com/diwakergupta/jetcd) | [python-etcd](https://github.com/jplana/python-etcd) | [python-etcd-client](https://github.com/dsoprea/PythonEtcdClient) | [node-etcd](https://github.com/stianeikeland/node-etcd) | [nodejs-etcd](https://github.com/lavagetto/nodejs-etcd) | [etcd-ruby](https://github.com/ranjib/etcd-ruby) | [etcd-api](https://github.com/jdarcy/etcd-api) | [cetcd](https://github.com/dwwoelfel/cetcd) | [clj-etcd](https://github.com/rthomas/clj-etcd) | [etcetera](https://github.com/drusellers/etcetera)|
| --- | :---: | :---: | :---: | :---: | :---: | :---: | :---: | :---: | :---: | :---: | :---: |
| **HTTPS Auth** | Y | Y | Y | Y | Y | Y | - | - | - | - | - |
| **Reconnect** | Y | - | Y | Y | - | - | - | Y | - | - | - |
| **Mod/Lock** | Y | - | Y | Y | - | - | - | - | - | - | - |
| **Mod/Leader** | Y | - | - | Y | - | - | - | - | - | - | - |
| **GET Features** | F | B | F | F | F | F | F | B | F | G | F |
| **PUT Features** | F | B | F | F | F | F | F | G | F | G | F |
| **POST Features** | F | - | F | F | - | F | F | - | - | - | F |
| **DEL Features** | F | B | F | F | F | F | F | B | G | B | F |
**Legend**
**F**: Full support **G**: Good support **B**: Basic support
**Y**: Feature supported **-**: Feature not supported

View File

@ -1,45 +0,0 @@
# Cluster Discovery
## Overview
Starting an etcd cluster can be painful since each node needs to know of another node in the cluster to get started. If you are trying to bring up a cluster all at once, say using a cloud formation, you also need to coordinate who will be the initial cluster leader. The discovery protocol helps you by providing an automated way to discover other existing peers in a cluster.
## Using discovery.etcd.io
### Create a Token
To use the discovery API, you must first create a token for your etcd cluster. Visit [https://discovery.etcd.io/new](https://discovery.etcd.io/new) to create a new token.
You can inspect the list of peers by viewing `https://discovery.etcd.io/<token>`.
### Start etcd With the Discovery Flag
Specify the `-discovery` flag when you start each etcd instance. The list of existing peers in the cluster will be downloaded and configured. If the instance is the first peer, it will start as the leader of the cluster.
Here's a full example:
```
TOKEN=$(curl https://discovery.etcd.io/new)
./etcd -name instance1 -peer-addr 10.1.2.3:7001 -addr 10.1.2.3:4001 -discovery https://discovery.etcd.io/$TOKEN
./etcd -name instance2 -peer-addr 10.1.2.4:7002 -addr 10.1.2.4:4002 -discovery https://discovery.etcd.io/$TOKEN
```
## Running Your Own Discovery Endpoint
The discovery API communicates with a separate etcd cluster to store and retrieve the list of peers. CoreOS provides [https://discovery.etcd.io](https://discovery.etcd.io) as a free service, but you can easily run your own etcd cluster for this purpose. Here's an example using an etcd cluster located at `10.10.10.10:4001`:
```
TOKEN="testcluster"
./etcd -name instance1 -peer-addr 10.1.2.3:7001 -addr 10.1.2.3:4001 -discovery http://10.10.10.10:4001/v2/keys/$TOKEN
./etcd -name instance2 -peer-addr 10.1.2.4:7002 -addr 10.1.2.4:4002 -discovery http://10.10.10.10:4001/v2/keys/$TOKEN
```
If you're interested in how to discovery API works behind the scenes, read about the [Discovery Protocol](https://github.com/coreos/etcd/blob/master/Documentation/discovery-protocol.md).
## Setting Peer Addresses Correctly
The Discovery API submits the `-peer-addr` of each etcd instance to the configured Discovery endpoint. It's important to select an address that *all* peers in the cluster can communicate with. For example, if you're located in two regions of a cloud provider, configuring a private `10.x` address will not work between the two regions, and communication will not be possible between all peers.
## Stale Peers
The discovery API will automatically clean up the address of a stale peer that is no longer part of the cluster. The TTL for this process is a week, which should be long enough to handle any extremely long outage you may encounter. There is no harm in having stale peers in the list until they are cleaned up, since an etcd instance only needs to connect to one valid peer in the cluster to join.

View File

@ -1,174 +0,0 @@
## Clustering
### Example cluster of three machines
Let's explore the use of etcd clustering.
We use Raft as the underlying distributed protocol which provides consistency and persistence of the data across all of the etcd instances.
Let start by creating 3 new etcd instances.
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 machine in the cluster:
```sh
./etcd -peer-addr 127.0.0.1:7001 -addr 127.0.0.1:4001 -data-dir machines/machine1 -name machine1
```
**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 machines to this cluster using the `-peers` argument. A single connection to any peer will allow a new machine to join, but multiple can be specified for greater resiliency.
```sh
./etcd -peer-addr 127.0.0.1:7002 -addr 127.0.0.1:4002 -peers 127.0.0.1:7001,127.0.0.1:7003 -data-dir machines/machine2 -name machine2
./etcd -peer-addr 127.0.0.1:7003 -addr 127.0.0.1:4003 -peers 127.0.0.1:7001,127.0.0.1:7002 -data-dir machines/machine3 -name machine3
```
We can retrieve a list of machines in the cluster using the HTTP API:
```sh
curl -L http://127.0.0.1:4001/v2/machines
```
We should see there are three machines in the cluster
```
http://127.0.0.1:4001, http://127.0.0.1:4002, http://127.0.0.1:4003
```
The machine list is also available via the main key API:
```sh
curl -L http://127.0.0.1:4001/v2/keys/_etcd/machines
```
```json
{
"action": "get",
"node": {
"createdIndex": 1,
"dir": true,
"key": "/_etcd/machines",
"modifiedIndex": 1,
"nodes": [
{
"createdIndex": 1,
"key": "/_etcd/machines/machine1",
"modifiedIndex": 1,
"value": "raft=http://127.0.0.1:7001&etcd=http://127.0.0.1:4001"
},
{
"createdIndex": 2,
"key": "/_etcd/machines/machine2",
"modifiedIndex": 2,
"value": "raft=http://127.0.0.1:7002&etcd=http://127.0.0.1:4002"
},
{
"createdIndex": 3,
"key": "/_etcd/machines/machine3",
"modifiedIndex": 3,
"value": "raft=http://127.0.0.1:7003&etcd=http://127.0.0.1:4003"
}
]
}
}
```
We can also get the current leader in the cluster:
```
curl -L http://127.0.0.1:4001/v2/leader
```
The first server we set up should still be the leader unless it has died during these commands.
```
http://127.0.0.1:7001
```
Now we can do normal SET and GET operations on keys as we explored earlier.
```sh
curl -L http://127.0.0.1:4001/v2/keys/foo -XPUT -d value=bar
```
```json
{
"action": "set",
"node": {
"createdIndex": 4,
"key": "/foo",
"modifiedIndex": 4,
"value": "bar"
}
}
```
### Killing Nodes in the Cluster
Now if we kill the leader of the cluster, we can get the value from one of the other two machines:
```sh
curl -L http://127.0.0.1:4002/v2/keys/foo
```
We can also see that a new leader has been elected:
```
curl -L http://127.0.0.1:4002/v2/leader
```
```
http://127.0.0.1:7002
```
or
```
http://127.0.0.1:7003
```
### Testing Persistence
Next we'll kill all the machines to test persistence.
Type `CTRL-C` on each terminal and then rerun the same command you used to start each machine.
Your request for the `foo` key will return the correct value:
```sh
curl -L http://127.0.0.1:4002/v2/keys/foo
```
```json
{
"action": "get",
"node": {
"createdIndex": 4,
"key": "/foo",
"modifiedIndex": 4,
"value": "bar"
}
}
```
### Using HTTPS between servers
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 `-*-file` flags to `-peer-*-file`.
If you are using SSL for server-to-server communication, you must use it on all instances of etcd.
### 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 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 peers.
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 machine failures.
And in the best case when all 9 peers are responding the cluster will perform at the speed of the fastest 5 machines.

View File

@ -1,102 +0,0 @@
# Etcd Configuration
Configuration options can be set in three places:
1. Command line flags
2. Environment variables
3. Configuration file
Options set on the command line take precedence over all other sources.
Options set in environment variables take precedence over options set in
configuration files.
## Command Line Flags
### Required
* `-name` - The node name. Defaults to the hostname.
### Optional
* `-addr` - The advertised public hostname:port for client communication. Defaults to `127.0.0.1:4001`.
* `-discovery` - A URL to use for discovering the peer list. (i.e `"https://discovery.etcd.io/your-unique-key"`).
* `-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` - 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.
* `-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=false` - Disable log snapshots. Defaults to `true`.
* `-v` - Enable verbose logging. Defaults to `false`.
* `-vv` - Enable very verbose logging. Defaults to `false`.
* `-version` - Print the version and exit.
## Configuration File
The etcd configuration file is written in [TOML](https://github.com/mojombo/toml)
and read from `/etc/etcd/etcd.conf` by default.
```TOML
addr = "127.0.0.1:4001"
bind_addr = "127.0.0.1:4001"
ca_file = ""
cert_file = ""
cors = []
cpu_profile_file = ""
data_dir = "."
key_file = ""
peers = []
peers_file = ""
max_cluster_size = 9
max_result_buffer = 1024
max_retry_attempts = 3
name = "default-name"
snapshot = false
verbose = false
very_verbose = false
[peer]
addr = "127.0.0.1:7001"
bind_addr = "127.0.0.1:7001"
ca_file = ""
cert_file = ""
key_file = ""
```
## Environment Variables
* `ETCD_ADDR`
* `ETCD_BIND_ADDR`
* `ETCD_CA_FILE`
* `ETCD_CERT_FILE`
* `ETCD_CORS_ORIGINS`
* `ETCD_CONFIG`
* `ETCD_CPU_PROFILE_FILE`
* `ETCD_DATA_DIR`
* `ETCD_KEY_FILE`
* `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_PEER_ADDR`
* `ETCD_PEER_BIND_ADDR`
* `ETCD_PEER_CA_FILE`
* `ETCD_PEER_CERT_FILE`
* `ETCD_PEER_KEY_FILE`

View File

@ -1,69 +0,0 @@
# Debugging etcd
Diagnosing issues in a distributed application is hard.
etcd will help as much as it can - just enable these debug features using the CLI flag `-trace=*` or the config option `trace=*`.
## Logging
Log verbosity can be increased to the max using either the `-vvv` CLI flag or the `very_very_verbose=true` config option.
The only supported logging mode is to stdout.
## Metrics
etcd itself can generate a set of metrics.
These metrics represent many different internal data points that can be helpful when debugging etcd servers.
#### Metrics reference
Each individual metric name is prefixed with `etcd.<NAME>`, where \<NAME\> is the configured name of the etcd server.
* `timer.appendentries.handle`: amount of time a peer takes to process an AppendEntriesRequest from the POV of the peer itself
* `timer.peer.<PEER>.heartbeat`: amount of time a peer heartbeat operation takes from the POV of the leader that initiated that operation for peer \<PEER\>
* `timer.command.<COMMAND>`: amount of time a given command took to be processed through the local server's raft state machine. This does not include time waiting on locks.
#### Fetching metrics over HTTP
Once tracing has been enabled on a given etcd server, all metric data is available at the server's `/debug/metrics` HTTP endpoint (i.e. `http://127.0.0.1:4001/debug/metrics`).
Executing a GET HTTP command against the metrics endpoint will yield the current state of all metrics in the etcd server.
#### Sending metrics to Graphite
etcd supports [Graphite's Carbon plaintext protocol](https://graphite.readthedocs.org/en/latest/feeding-carbon.html#the-plaintext-protocol) - a TCP wire protocol designed for shipping metric data to an aggregator.
To send metrics to a Graphite endpoint using this protocol, use of the `-graphite-host` CLI flag or the `graphite_host` config option (i.e. `graphite_host=172.17.0.19:2003`).
See an [example graphite deploy script](https://github.com/coreos/etcd/contrib/graphite).
#### Generating additional metrics with Collectd
[Collectd](http://collectd.org/documentation.shtml) gathers metrics from the host running etcd.
While these aren't metrics generated by etcd itself, it can be invaluable to compare etcd's view of the world to that of a separate process running next to etcd.
See an [example collectd deploy script](https://github.com/coreos/etcd/contrib/collectd).
## Profiling
etcd exposes profiling information from the Go pprof package over HTTP.
The basic browseable interface is served by etcd at the `/debug/pprof` HTTP endpoint (i.e. `http://127.0.0.1:4001/debug/pprof`).
For more information on using profiling tools, see http://blog.golang.org/profiling-go-programs.
**NOTE**: In the following examples you need to ensure that the `./bin/etcd` is identical to the `./bin/etcd` that you are targetting (same git hash, arch, platform, etc).
#### Heap memory profile
```
go tool pprof ./bin/etcd http://127.0.0.1:4001/debug/pprof/heap
```
#### CPU profile
```
go tool pprof ./bin/etcd http://127.0.0.1:4001/debug/pprof/profile
```
#### Blocked goroutine profile
```
go tool pprof ./bin/etcd http://127.0.0.1:4001/debug/pprof/block
```

View File

@ -1,87 +0,0 @@
# Discovery Protocol
Starting a new etcd cluster can be painful since each machine needs to know of at least one live machine in the cluster. If you are trying to bring up a new cluster all at once, say using an AWS cloud formation, you also need to coordinate who will be the initial cluster leader. The discovery protocol uses an existing running etcd cluster to start a second etcd cluster.
To use this feature you add the command line flag `-discovery` to your etcd args. In this example we will use `http://example.com/v2/keys/_etcd/registry` as the URL prefix.
## The Protocol
By convention the etcd discovery protocol uses the key prefix `_etcd/registry`. A full URL to the keyspace will be `http://example.com/v2/keys/_etcd/registry`.
### Creating a New Cluster
Generate a unique token that will identify the new cluster. This will be used as a key prefix in the following steps. An easy way to do this is to use uuidgen:
```
UUID=$(uuidgen)
```
### Bringing up Machines
Now that you have your cluster ID you can start bringing up machines. Every machine will follow this protocol internally in etcd if given a `-discovery`.
### Registering your Machine
The first thing etcd must do is register your machine. This is done by using the machine name (from the `-name` arg) and posting it with a long TTL to the given key.
```
curl -X PUT "http://example.com/v2/keys/_etcd/registry/${UUID}/${etcd_machine_name}?ttl=604800" -d value=${peer_addr}
```
### Discovering Peers
Now that this etcd machine is registered it must discover its peers.
But, the tricky bit of starting a new cluster is that one machine needs to assume the initial role of leader and will have no peers. To figure out if another machine has already started the cluster etcd needs to create the `_state` key and set its value to "started":
```
curl -X PUT "http://example.com/v2/keys/_etcd/registry/${UUID}/_state?prevExist=false" -d value=started
```
If this returns a `200 OK` response then this machine is the initial leader and should start with no peers configured. If, however, this returns a `412 Precondition Failed` then you need to find all of the registered peers:
```
curl -X GET "http://example.com/v2/keys/_etcd/registry/${UUID}?recursive=true"
```
```
{
"action": "get",
"node": {
"createdIndex": 11,
"dir": true,
"key": "/_etcd/registry/9D4258A5-A1D3-4074-8837-31C1E091131D",
"modifiedIndex": 11,
"nodes": [
{
"createdIndex": 16,
"expiration": "2014-02-03T13:19:57.631253589-08:00",
"key": "/_etcd/registry/9D4258A5-A1D3-4074-8837-31C1E091131D/peer1",
"modifiedIndex": 16,
"ttl": 604765,
"value": "127.0.0.1:7001"
},
{
"createdIndex": 17,
"expiration": "2014-02-03T13:19:57.631253589-08:00",
"key": "/_etcd/registry/9D4258A5-A1D3-4074-8837-31C1E091131D/peer2",
"modifiedIndex": 17,
"ttl": 604765,
"value": "127.0.0.1:7002"
}
]
}
}
```
Using this information you can connect to the rest of the peers in the cluster.
### Heartbeating
At this point etcd will start heart beating to your registration URL. The
protocol uses a heartbeat so permanently deleted nodes get slowly removed from
the discovery information cluster.
The heartbeat interval is about once per day and the TTL is one week. This
should give a sufficiently wide window to protect against a discovery service
taking a temporary outage yet provide adequate cleanup.

View File

@ -1,58 +0,0 @@
Error Code
======
This document describes the error code in **Etcd** project.
It's categorized into four groups:
- Command Related Error
- Post Form Related Error
- Raft Related Error
- Etcd Related Error
Error code corresponding strerror
------
const (
EcodeKeyNotFound = 100
EcodeTestFailed = 101
EcodeNotFile = 102
EcodeNoMorePeer = 103
EcodeNotDir = 104
EcodeNodeExist = 105
EcodeKeyIsPreserved = 106
EcodeValueRequired = 200
EcodePrevValueRequired = 201
EcodeTTLNaN = 202
EcodeIndexNaN = 203
EcodeRaftInternal = 300
EcodeLeaderElect = 301
EcodeWatcherCleared = 400
EcodeEventIndexCleared = 401
)
// command related errors
errors[100] = "Key Not Found"
errors[101] = "Test Failed" //test and set
errors[102] = "Not A File"
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"
// Post form related errors
errors[200] = "Value is Required in POST form"
errors[201] = "PrevValue is Required in POST form"
errors[202] = "The given TTL in POST form is not a number"
errors[203] = "The given index in POST form is not a number"
// raft related errors
errors[300] = "Raft Internal Error"
errors[301] = "During Leader Election"
// etcd related errors
errors[400] = "watcher is cleared due to etcd recovery"
errors[401] = "The event in requested index is outdated and cleared"

View File

@ -1,101 +0,0 @@
#Etcd File System
## Structure
[TODO]
![alt text](./img/etcd_fs_structure.jpg "etcd file system structure")
## Node
In **etcd**, the **node** is the base from which the filesystem is constructed.
**etcd**'s file system is Unix-like with two kinds of nodes: file and directories.
- A **file node** has data associated with it.
- A **directory node** has child nodes associated with it.
All nodes, regardless of type, have the following attributes and operations:
### Attributes:
- **Expiration Time** [optional]
The node will be deleted when it expires.
- **ACL**
The path to the node's access control list.
### Operation:
- **Get** (path, recursive, sorted)
Get the content of the node
- If the node is a file, the data of the file will be returned.
- If the node is a directory, the child nodes of the directory will be returned.
- If recursive is true, it will recursively get the nodes of the directory.
- If sorted is true, the result will be sorted based on the path.
- **Create** (path, value[optional], ttl [optional])
Create a file. Create operation will help to create intermediate directories with no expiration time.
- If the file already exists, create will fail.
- If the value is given, set will create a file.
- If the value is not given, set will crate a directory.
- If ttl is given, the node will be deleted when it expires.
- **Update** (path, value[optional], ttl [optional])
Update the content of the node.
- If the value is given, the value of the key will be updated.
- If ttl is given, the expiration time of the node will be updated.
- **Delete** (path, recursive)
Delete the node of given path.
- If the node is a directory:
- If recursive is true, the operation will delete all nodes under the directory.
- If recursive is false, error will be returned.
- **TestAndSet** (path, prevValue [prevIndex], value, ttl)
Atomic *test and set* value to a file. If test succeeds, this operation will change the previous value of the file to the given value.
- If the prevValue is given, it will test against previous value of
the node.
- If the prevValue is empty, it will test if the node is not existing.
- If the prevValue is not empty, it will test if the prevValue is equal to the current value of the file.
- If the prevIndex is given, it will test if the create/last modified index of the node is equal to prevIndex.
- **Renew** (path, ttl)
Set the node's expiration time to (current time + ttl)
## ACL
### Theory
Etcd exports a Unix-like file system interface consisting of files and directories, collectively called nodes.
Each node has various meta-data, including three names of the access control lists used to control reading, writing and changing (change ACL names for the node).
We are storing the ACL names for nodes under a special *ACL* directory.
Each node has ACL name corresponding to one file within *ACL* dir.
Unless overridden, a node naturally inherits the ACL names of its parent directory on creation.
For each ACL name, it has three children: *R (Reading)*, *W (Writing)*, *C (Changing)*
Each permission is also a node. Under the node it contains the users who have this permission for the file refering to this ACL name.
### Example
[TODO]
### Diagram
[TODO]
### Interface
Testing permissions:
- (node *Node) get_perm()
- (node *Node) has_perm(perm string, user string)
Setting/Changing permissions:
- (node *Node) set_perm(perm string)
- (node *Node) change_ACLname(aclname string)
## User Group
[TODO]

Binary file not shown.

Before

Width:  |  Height:  |  Size: 26 KiB

View File

@ -1,61 +0,0 @@
# Versioning
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 rolling upgrade process (e.g. the CoreOS developer alpha).
Longer term need: Having a mixed version cluster where all peers are not 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.
## Join Control
We will add a version field to the join command.
But, who decides whether a newly upgraded follower should be able to join a cluster?
### Leader Controlled
If the leader controls the version of followers joining the cluster then it compares its version to the version number presented by the follower in the JoinCommand and rejects the join if the number is less than the leader's version number.
Advantages
- Leader controls all cluster decisions still
Disadvantages
- Follower knows better what versions of the interal protocol it can talk than the leader
### Follower Controlled
A newly upgraded follower should be able to figure out the leaders internal version from a defined internal backwards compatible API endpoint and figure out if it can join the cluster.
If it cannot join the cluster then it simply exits.
Advantages
- The follower is running newer code and knows better if it can talk older protocols
Disadvantages
- This cluster decision isn't made by the leader
## Recommendation
To solve the immediate need and to plan for the future lets do the following:
- Add Version field to JoinCommand
- Have a joining follower read the Version field of the leader and if its own version doesn't match the leader then sleep for some random interval and retry later to see if the leader has upgraded.
# Research
## Zookeeper versioning
Zookeeper very recently added versioning into the protocol and it doesn't seem to have seen any use yet.
https://issues.apache.org/jira/browse/ZOOKEEPER-1633
## doozerd
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

@ -1,79 +0,0 @@
## Libraries and Tools
**Tools**
- [etcdctl](https://github.com/coreos/etcdctl) - A command line client for etcd
- [etcd-dump](https://npmjs.org/package/etcd-dump) - Command line utility for dumping/restoring etcd.
**Go libraries**
- [go-etcd](https://github.com/coreos/go-etcd) - Supports v2
**Java libraries**
- [justinsb/jetcd](https://github.com/justinsb/jetcd)
- [diwakergupta/jetcd](https://github.com/diwakergupta/jetcd) - Supports v2
**Python libraries**
- [transitorykris/etcd-py](https://github.com/transitorykris/etcd-py)
- [jplana/python-etcd](https://github.com/jplana/python-etcd) - Supports v2
- [russellhaering/txetcd](https://github.com/russellhaering/txetcd) - a Twisted Python library
**Node libraries**
- [stianeikeland/node-etcd](https://github.com/stianeikeland/node-etcd) - Supports v2 (w Coffeescript)
- [lavagetto/nodejs-etcd](https://github.com/lavagetto/nodejs-etcd) - Supports v2
**Ruby libraries**
- [iconara/etcd-rb](https://github.com/iconara/etcd-rb)
- [jpfuentes2/etcd-ruby](https://github.com/jpfuentes2/etcd-ruby)
- [ranjib/etcd-ruby](https://github.com/ranjib/etcd-ruby) - Supports v2
**C libraries**
- [jdarcy/etcd-api](https://github.com/jdarcy/etcd-api) - Supports v2
**Clojure libraries**
- [aterreno/etcd-clojure](https://github.com/aterreno/etcd-clojure)
- [dwwoelfel/cetcd](https://github.com/dwwoelfel/cetcd) - Supports v2
- [rthomas/clj-etcd](https://github.com/rthomas/clj-etcd) - Supports v2
**Erlang libraries**
- [marshall-lee/etcd.erl](https://github.com/marshall-lee/etcd.erl)
**.Net Libraries**
-[drusellers/etcetera](https://github.com/drusellers/etcetera)
A detailed recap of client functionalities can be found in the [clients compatibility matrix][clients-matrix.md].
[clients-matrix.md]: https://github.com/coreos/etcd/blob/master/Documentation/clients-matrix.md
**Chef Integration**
- [coderanger/etcd-chef](https://github.com/coderanger/etcd-chef)
**Chef Cookbook**
- [spheromak/etcd-cookbook](https://github.com/spheromak/etcd-cookbook)
**BOSH Releases**
- [cloudfoundry-community/etcd-boshrelease](https://github.com/cloudfoundry-community/etcd-boshrelease)
- [cloudfoundry/cf-release](https://github.com/cloudfoundry/cf-release/tree/master/jobs/etcd)
**Projects using etcd**
- [binocarlos/yoda](https://github.com/binocarlos/yoda) - etcd + ZeroMQ
- [calavera/active-proxy](https://github.com/calavera/active-proxy) - HTTP Proxy configured with etcd
- [derekchiang/etcdplus](https://github.com/derekchiang/etcdplus) - A set of distributed synchronization primitives built upon etcd
- [go-discover](https://github.com/flynn/go-discover) - service discovery in Go
- [gleicon/goreman](https://github.com/gleicon/goreman/tree/etcd) - Branch of the Go Foreman clone with etcd support
- [garethr/hiera-etcd](https://github.com/garethr/hiera-etcd) - Puppet hiera backend using etcd
- [mattn/etcd-vim](https://github.com/mattn/etcd-vim) - SET and GET keys from inside vim
- [mattn/etcdenv](https://github.com/mattn/etcdenv) - "env" shebang with etcd integration
- [kelseyhightower/confd](https://github.com/kelseyhightower/confd) - Manage local app config files using templates and data from etcd
- [configdb](https://git.autistici.org/ai/configdb/tree/master) - A REST relational abstraction on top of arbitrary database backends, aimed at storing configs and inventories.

View File

@ -1,105 +0,0 @@
## Modules
etcd has a number of modules that are built on top of the core etcd API.
These modules provide things like dashboards, locks and leader election.
### Dashboard
An HTML dashboard can be found at `http://127.0.0.1:4001/mod/dashboard/`.
This dashboard is compiled into the etcd binary and uses the same API as regular etcd clients.
Use the `-cors='*'` flag to allow your browser to request information from the current master as it changes.
### Lock
The Lock module implements a fair lock that can be used when lots of clients want access to a single resource.
A lock can be associated with a value.
The value is unique so if a lock tries to request a value that is already queued for a lock then it will find it and watch until that value obtains the lock.
If you lock the same value on a key from two separate curl sessions they'll both return at the same time.
Here's the API:
**Acquire a lock (with no value) for "customer1"**
```sh
curl -X POST http://127.0.0.1:4001/mod/v2/lock/customer1?ttl=60
```
**Acquire a lock for "customer1" that is associated with the value "bar"**
```sh
curl -X POST http://127.0.0.1:4001/mod/v2/lock/customer1?ttl=60 -d value=bar
```
**Renew the TTL on the "customer1" lock for index 2**
```sh
curl -X PUT http://127.0.0.1:4001/mod/v2/lock/customer1?ttl=60 -d index=2
```
**Renew the TTL on the "customer1" lock for value "customer1"**
```sh
curl -X PUT http://127.0.0.1:4001/mod/v2/lock/customer1?ttl=60 -d value=bar
```
**Retrieve the current value for the "customer1" lock.**
```sh
curl http://127.0.0.1:4001/mod/v2/lock/customer1
```
**Retrieve the current index for the "customer1" lock**
```sh
curl http://127.0.0.1:4001/mod/v2/lock/customer1?field=index
```
**Delete the "customer1" lock with the index 2**
```sh
curl -X DELETE http://127.0.0.1:4001/mod/v2/lock/customer1?index=2
```
**Delete the "customer1" lock with the value "bar"**
```sh
curl -X DELETE http://127.0.0.1:4001/mod/v2/lock/customer1?value=bar
```
### Leader Election
The Leader Election module wraps the Lock module to allow clients to come to consensus on a single value.
This is useful when you want one server to process at a time but allow other servers to fail over.
The API is similar to the Lock module but is limited to simple strings values.
Here's the API:
**Attempt to set a value for the "order_processing" leader key:**
```sh
curl -X PUT http://127.0.0.1:4001/mod/v2/leader/order_processing?ttl=60 -d name=myserver1.foo.com
```
**Retrieve the current value for the "order_processing" leader key:**
```sh
curl http://127.0.0.1:4001/mod/v2/leader/order_processing
myserver1.foo.com
```
**Remove a value from the "order_processing" leader key:**
```sh
curl -X DELETE http://127.0.0.1:4001/mod/v2/leader/order_processing?name=myserver1.foo.com
```
If multiple clients attempt to set the value for a key then only one will succeed.
The other clients will hang until the current value is removed because of TTL or because of a `DELETE` operation.
Multiple clients can submit the same value and will all be notified when that value succeeds.
To update the TTL of a value simply reissue the same `PUT` command that you used to set the value.

View File

@ -1,30 +0,0 @@
# Optimal etcd Cluster Size
etcd's Raft consensus algorithm is most efficient in small clusters between 3 and 9 peers. Let's briefly explore how etcd works internally to understand why.
## Writing to etcd
Writes to an etcd peer are always redirected to the leader of the cluster and distributed to all of the peers immediately. A write is only considered successful when a majority of the peers acknowledge the write.
For example, in a 5 node cluster, a write operation is only as fast as the 3rd fastest machine. This is the main reason for keeping your etcd cluster below 9 nodes. In practice, you only need to worry about write performance in high latency environments such as a cluster spanning multiple data centers.
## Leader Election
The leader election process is similar to writing a key &mdash; a majority of the cluster must acknowledge the new leader before cluster operations can continue. The longer each node takes to elect a new leader means you have to wait longer before you can write to the cluster again. In low latency environments this process takes milliseconds.
## Odd Cluster Size
The other important cluster optimization is to always have an odd cluster size. Adding an odd node to the cluster doesn't change the size of the majority and therefore doesn't increase the total latency of the majority as described above. But you do gain a higher tolerance for peer failure by adding the extra machine. You can see this in practice when comparing two even and odd sized clusters:
| Cluster Size | Majority | Failure Tolerance |
|--------------|------------|-------------------|
| 8 machines | 5 machines | 3 machines |
| 9 machines | 5 machines | **4 machines** |
As you can see, adding another node to bring the cluster up to an odd size is always worth it. During a network partition, an odd cluster size also guarantees that there will almost always be a majority of the cluster that can continue to operate and be the source of truth when the partition ends.
## Cluster Management
Currently, each CoreOS machine is an etcd peer &mdash; if you have 30 CoreOS machines, you have 30 etcd peers and end up with a cluster size that is way too large. If desired, you may manually stop some of these etcd instances to increase cluster performance.
Functionality is being developed to expose two different types of followers: active and benched followers. Active followers will influence operations within the cluster. Benched followers will not participate, but will transparently proxy etcd traffic to an active follower. This allows every CoreOS machine to expose etcd on port 4001 for ease of use. Benched followers will have the ability to transition into an active follower if needed.

View File

@ -1,62 +0,0 @@
# FreeBSD
Starting with version 0.1.2 both etcd and etcdctl have been ported to FreeBSD and can
be installed either via packages or ports system. Their versions have been recently
updated to 0.2.0 so now you can enjoy using etcd and etcdctl on FreeBSD 10.0 (RC4 as
of now) and 9.x where they have been tested. They might also work when installed from
ports on earlier versions of FreeBSD, but your mileage may vary.
## Installation
### Using pkgng package system
1. If you do not have pkg­ng installed, install it with command `pkg` and answering 'Y'
when asked
2. Update your repository data with `pkg update`
3. Install etcd with `pkg install coreos­etcd coreos­etcdctl`
4. Verify successful installation with `pkg info | grep etcd` and you should get:
```
r@fbsd­10:/ # pkg info | grep etcd
coreos­etcd­0.2.0              Highly­available key value store and service discovery
coreos­etcdctl­0.2.0           Simple commandline client for etcd
r@fbsd­10:/ #
```
5. Youre ready to use etcd and etcdctl! For more information about using pkgng, plese
see: http://www.freebsd.org/doc/handbook/pkgng­intro.html
 
### Using ports system
1. If you do not have ports installed, install with with `portsnap fetch extract` (it
may take some time depending on your hardware and network connection)
2. Build etcd with `cd /usr/ports/devel/etcd && make install clean`, you
will get an option to build and install documentation and etcdctl with it.
3. If you havent install it with etcdctl, and you would like to install it later, you can build it
with `cd /usr/ports/devel/etcdctl && make install clean`
4. Verify successful installation with `pkg info | grep etcd` and you should get:
 
```
r@fbsd­10:/ # pkg info | grep etcd
coreos­etcd­0.2.0              Highly­available key value store and service discovery
coreos­etcdctl­0.2.0           Simple commandline client for etcd
r@fbsd­10:/ #
```
5. Youre ready to use etcd and etcdctl! For more information about using ports system,
please see: https://www.freebsd.org/doc/handbook/ports­using.html
## Issues
If you find any issues with the build/install procedure or youve found a problem that
youve verified is local to FreeBSD version only (for example, by not being able to
reproduce it on any other platform, like OSX or Linux), please sent a
problem report using this page for more
information: http://www.freebsd.org/send­pr.html

View File

@ -1,130 +0,0 @@
# Reading and Writing over HTTPS
## Transport Security with HTTPS
Etcd supports SSL/TLS and client cert authentication for clients to server, as well as server to server communication.
First, you need to have a CA cert `clientCA.crt` and signed key pair `client.crt`, `client.key`.
This site has a good reference for how to generate self-signed key pairs:
http://www.g-loaded.eu/2005/11/10/be-your-own-ca/
For testing you can use the certificates in the `fixtures/ca` directory.
Let's configure etcd to use this keypair:
```sh
./etcd -f -name machine0 -data-dir machine0 -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 machine configuration, even if an existing configuration is found. (WARNING: data loss!)
* `-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:
```sh
curl --cacert ./fixtures/ca/server-chain.pem https://127.0.0.1:4001/v2/keys/foo -XPUT -d value=bar -v
```
You should be able to see the handshake succeed.
**OSX 10.9+ Users**: curl 7.30.0 on OSX 10.9+ doesn't understand certificates passed in on the command line.
Instead you must import the dummy ca.crt directly into the keychain or add the `-k` flag to curl to ignore errors.
If you want to test without the `-k` flag run `open ./fixtures/ca/ca.crt` and follow the prompts.
Please remove this certificate after you are done testing!
If you know of a workaround let us know.
```
...
SSLv3, TLS handshake, Finished (20):
...
```
And also the response from the etcd server:
```json
{
"action": "set",
"key": "/foo",
"modifiedIndex": 3,
"value": "bar"
}
```
## Authentication with HTTPS Client Certificates
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 -f -name machine0 -data-dir machine0 -ca-file=./fixtures/ca/ca.crt -cert-file=./fixtures/ca/server.crt -key-file=./fixtures/ca/server.key.insecure
```
```-ca-file``` is the path to the CA cert.
Try the same request to this server:
```sh
curl --cacert ./fixtures/ca/server-chain.pem https://127.0.0.1:4001/v2/keys/foo -XPUT -d value=bar -v
```
The request should be rejected by the server.
```
...
routines:SSL3_READ_BYTES:sslv3 alert bad certificate
...
```
We need to give the CA signed cert to the server.
```sh
curl --key ./fixtures/ca/server2.key.insecure --cert ./fixtures/ca/server2.crt --cacert ./fixtures/ca/server-chain.pem -L https://127.0.0.1:4001/v2/keys/foo -XPUT -d value=bar -v
```
You should able to see:
```
...
SSLv3, TLS handshake, CERT verify (15):
...
TLS handshake, Finished (20)
```
And also the response from the server:
```json
{
"action": "set",
"node": {
"createdIndex": 12,
"key": "/foo",
"modifiedIndex": 12,
"value": "bar"
}
}
```
### Why SSLv3 alert handshake failure when using SSL client auth?
The `crypto/tls` package of `golang` checks the key usage of the certificate public key before using it.
To use the certificate public key to do client auth, we need to add `clientAuth` to `Extended Key Usage` when creating the certificate public key.
Here is how to do it:
Add the following section to your openssl.cnf:
```
[ ssl_client ]
...
extendedKeyUsage = clientAuth
...
```
When creating the cert be sure to reference it in the `-extensions` flag:
```
openssl ca -config openssl.cnf -policy policy_anything -extensions ssl_client -out certs/machine.crt -infiles machine.csr
```

View File

@ -1,93 +0,0 @@
## Tuning
The default settings in etcd should work well for installations on a local network where the average network latency is low.
However, when using etcd across multiple data centers or over networks with high latency you may need to tweak the heartbeat and election timeout settings.
### Timeouts
The underlying distributed consensus protocol relies on two separate timeouts to ensure that nodes can handoff leadership if one stalls or goes offline.
The first timeout is called the *Heartbeat Timeout*.
This is the frequency with which the leader will notify followers that it is still the leader.
etcd batches commands together for higher throughput so this heartbeat timeout is also a delay for how long it takes for commands to be committed.
By default, etcd uses a `50ms` heartbeat timeout.
The second timeout is the *Election Timeout*.
This timeout is how long a follower node will go without hearing a heartbeat before attempting to become leader itself.
By default, etcd uses a `200ms` election timeout.
Adjusting these values is a trade off.
Lowering the heartbeat timeout will cause individual commands to be committed faster but it will lower the overall throughput of etcd.
If your etcd instances have low utilization then lowering the heartbeat timeout can improve your command response time.
The election timeout should be set based on the heartbeat timeout and your network ping time between nodes.
Election timeouts should be at least 10 times your ping time so it can account for variance in your network.
For example, if the ping time between your nodes is 10ms then you should have at least a 100ms election timeout.
You should also set your election timeout to at least 4 to 5 times your heartbeat timeout to account for variance in leader replication.
For a heartbeat timeout of 50ms you should set your election timeout to at least 200ms - 250ms.
You can override the default values on the command line:
```sh
# Command line arguments:
$ etcd -peer-heartbeat-timeout=100 -peer-election-timeout=500
# Environment variables:
$ ETCD_PEER_HEARTBEAT_TIMEOUT=100 ETCD_PEER_ELECTION_TIMEOUT=500 etcd
```
Or you can set the values within the configuration file:
```toml
[peer]
heartbeat_timeout = 100
election_timeout = 100
```
The values are specified in milliseconds.
### Snapshots
etcd appends all key changes to a log file.
This log grows forever and is a complete linear history of every change made to the keys.
A complete history works well for lightly used clusters but clusters that are heavily used would carry around a large log.
To avoid having a huge log etcd makes periodic snapshots.
These snapshots provide a way for etcd to compact the log by saving the current state of the system and removing old logs.
### Snapshot Tuning
Creating snapshots can be expensive so they're only created after a given number of changes to etcd.
By default, snapshots will be made after every 10,000 changes.
If etcd's memory usage and disk usage are too high, you can lower the snapshot threshold by setting the following on the command line:
```sh
# Command line arguments:
$ etcd -snapshot-count=5000
# Environment variables:
$ ETCD_SNAPSHOT_COUNT=5000 etcd
```
Or you can change the setting in the configuration file:
```toml
snapshot_count = 5000
```
You can also disable snapshotting by adding the following to your command line:
```sh
# Command line arguments:
$ etcd -snapshot false
# Environment variables:
$ ETCD_SNAPSHOT=false etcd
```
You can also enable snapshotting within the configuration file:
```toml
snapshot = false
```

202
3rdParty/etcd/LICENSE vendored
View File

@ -1,202 +0,0 @@
Apache License
Version 2.0, January 2004
http://www.apache.org/licenses/
TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
1. Definitions.
"License" shall mean the terms and conditions for use, reproduction,
and distribution as defined by Sections 1 through 9 of this document.
"Licensor" shall mean the copyright owner or entity authorized by
the copyright owner that is granting the License.
"Legal Entity" shall mean the union of the acting entity and all
other entities that control, are controlled by, or are under common
control with that entity. For the purposes of this definition,
"control" means (i) the power, direct or indirect, to cause the
direction or management of such entity, whether by contract or
otherwise, or (ii) ownership of fifty percent (50%) or more of the
outstanding shares, or (iii) beneficial ownership of such entity.
"You" (or "Your") shall mean an individual or Legal Entity
exercising permissions granted by this License.
"Source" form shall mean the preferred form for making modifications,
including but not limited to software source code, documentation
source, and configuration files.
"Object" form shall mean any form resulting from mechanical
transformation or translation of a Source form, including but
not limited to compiled object code, generated documentation,
and conversions to other media types.
"Work" shall mean the work of authorship, whether in Source or
Object form, made available under the License, as indicated by a
copyright notice that is included in or attached to the work
(an example is provided in the Appendix below).
"Derivative Works" shall mean any work, whether in Source or Object
form, that is based on (or derived from) the Work and for which the
editorial revisions, annotations, elaborations, or other modifications
represent, as a whole, an original work of authorship. For the purposes
of this License, Derivative Works shall not include works that remain
separable from, or merely link (or bind by name) to the interfaces of,
the Work and Derivative Works thereof.
"Contribution" shall mean any work of authorship, including
the original version of the Work and any modifications or additions
to that Work or Derivative Works thereof, that is intentionally
submitted to Licensor for inclusion in the Work by the copyright owner
or by an individual or Legal Entity authorized to submit on behalf of
the copyright owner. For the purposes of this definition, "submitted"
means any form of electronic, verbal, or written communication sent
to the Licensor or its representatives, including but not limited to
communication on electronic mailing lists, source code control systems,
and issue tracking systems that are managed by, or on behalf of, the
Licensor for the purpose of discussing and improving the Work, but
excluding communication that is conspicuously marked or otherwise
designated in writing by the copyright owner as "Not a Contribution."
"Contributor" shall mean Licensor and any individual or Legal Entity
on behalf of whom a Contribution has been received by Licensor and
subsequently incorporated within the Work.
2. Grant of Copyright License. Subject to the terms and conditions of
this License, each Contributor hereby grants to You a perpetual,
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
copyright license to reproduce, prepare Derivative Works of,
publicly display, publicly perform, sublicense, and distribute the
Work and such Derivative Works in Source or Object form.
3. Grant of Patent License. Subject to the terms and conditions of
this License, each Contributor hereby grants to You a perpetual,
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
(except as stated in this section) patent license to make, have made,
use, offer to sell, sell, import, and otherwise transfer the Work,
where such license applies only to those patent claims licensable
by such Contributor that are necessarily infringed by their
Contribution(s) alone or by combination of their Contribution(s)
with the Work to which such Contribution(s) was submitted. If You
institute patent litigation against any entity (including a
cross-claim or counterclaim in a lawsuit) alleging that the Work
or a Contribution incorporated within the Work constitutes direct
or contributory patent infringement, then any patent licenses
granted to You under this License for that Work shall terminate
as of the date such litigation is filed.
4. Redistribution. You may reproduce and distribute copies of the
Work or Derivative Works thereof in any medium, with or without
modifications, and in Source or Object form, provided that You
meet the following conditions:
(a) You must give any other recipients of the Work or
Derivative Works a copy of this License; and
(b) You must cause any modified files to carry prominent notices
stating that You changed the files; and
(c) You must retain, in the Source form of any Derivative Works
that You distribute, all copyright, patent, trademark, and
attribution notices from the Source form of the Work,
excluding those notices that do not pertain to any part of
the Derivative Works; and
(d) If the Work includes a "NOTICE" text file as part of its
distribution, then any Derivative Works that You distribute must
include a readable copy of the attribution notices contained
within such NOTICE file, excluding those notices that do not
pertain to any part of the Derivative Works, in at least one
of the following places: within a NOTICE text file distributed
as part of the Derivative Works; within the Source form or
documentation, if provided along with the Derivative Works; or,
within a display generated by the Derivative Works, if and
wherever such third-party notices normally appear. The contents
of the NOTICE file are for informational purposes only and
do not modify the License. You may add Your own attribution
notices within Derivative Works that You distribute, alongside
or as an addendum to the NOTICE text from the Work, provided
that such additional attribution notices cannot be construed
as modifying the License.
You may add Your own copyright statement to Your modifications and
may provide additional or different license terms and conditions
for use, reproduction, or distribution of Your modifications, or
for any such Derivative Works as a whole, provided Your use,
reproduction, and distribution of the Work otherwise complies with
the conditions stated in this License.
5. Submission of Contributions. Unless You explicitly state otherwise,
any Contribution intentionally submitted for inclusion in the Work
by You to the Licensor shall be under the terms and conditions of
this License, without any additional terms or conditions.
Notwithstanding the above, nothing herein shall supersede or modify
the terms of any separate license agreement you may have executed
with Licensor regarding such Contributions.
6. Trademarks. This License does not grant permission to use the trade
names, trademarks, service marks, or product names of the Licensor,
except as required for reasonable and customary use in describing the
origin of the Work and reproducing the content of the NOTICE file.
7. Disclaimer of Warranty. Unless required by applicable law or
agreed to in writing, Licensor provides the Work (and each
Contributor provides its Contributions) on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
implied, including, without limitation, any warranties or conditions
of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
PARTICULAR PURPOSE. You are solely responsible for determining the
appropriateness of using or redistributing the Work and assume any
risks associated with Your exercise of permissions under this License.
8. Limitation of Liability. In no event and under no legal theory,
whether in tort (including negligence), contract, or otherwise,
unless required by applicable law (such as deliberate and grossly
negligent acts) or agreed to in writing, shall any Contributor be
liable to You for damages, including any direct, indirect, special,
incidental, or consequential damages of any character arising as a
result of this License or out of the use or inability to use the
Work (including but not limited to damages for loss of goodwill,
work stoppage, computer failure or malfunction, or any and all
other commercial damages or losses), even if such Contributor
has been advised of the possibility of such damages.
9. Accepting Warranty or Additional Liability. While redistributing
the Work or Derivative Works thereof, You may choose to offer,
and charge a fee for, acceptance of support, warranty, indemnity,
or other liability obligations and/or rights consistent with this
License. However, in accepting such obligations, You may act only
on Your own behalf and on Your sole responsibility, not on behalf
of any other Contributor, and only if You agree to indemnify,
defend, and hold each Contributor harmless for any liability
incurred by, or claims asserted against, such Contributor by reason
of your accepting any such warranty or additional liability.
END OF TERMS AND CONDITIONS
APPENDIX: How to apply the Apache License to your work.
To apply the Apache License to your work, attach the following
boilerplate notice, with the fields enclosed by brackets "[]"
replaced with your own identifying information. (Don't include
the brackets!) The text should be enclosed in the appropriate
comment syntax for the file format. We also recommend that a
file or class name and description of purpose be included on the
same "printed page" as the copyright notice for easier
identification within third-party archives.
Copyright [yyyy] [name of copyright owner]
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.

View File

@ -1,128 +0,0 @@
# etcd
README version 0.2.0
[![Build Status](https://drone.io/github.com/coreos/etcd/status.png)](https://drone.io/github.com/coreos/etcd/latest)
A highly-available key value store for shared configuration and service discovery.
etcd is inspired by zookeeper and doozer, with a focus on:
* Simple: curl'able user facing API (HTTP+JSON)
* Secure: optional SSL client cert authentication
* Fast: benchmarked 1000s of writes/s per instance
* Reliable: Properly distributed using Raft
Etcd is written in Go and uses the [Raft][raft] consensus algorithm to manage a highly-available replicated log.
See [etcdctl][etcdctl] for a simple command line client.
Or feel free to just use curl, as in the examples below.
[raft]: https://github.com/coreos/go-raft
[etcdctl]: http://github.com/coreos/etcdctl/
## Contact
- Mailing list: http://coreos.com/lists/etcd-dev/
- IRC: #coreos on irc.freenode.net
- Planning/Roadmap: https://trello.com/b/OiEbU547/etcd
- Bugs: https://github.com/coreos/etcd/issues
## Getting Started
### Getting etcd
The latest release and setup instructions are available at [Github][github-release].
[github-release]: https://github.com/coreos/etcd/releases/
### Building
You can build etcd from source:
```sh
git clone https://github.com/coreos/etcd
cd etcd
./build
```
This will generate a binary called `./bin/etcd`.
_NOTE_: you need go 1.2+. Please check your installation with
```
go version
```
### Running
First start a single machine cluster of etcd:
```sh
./bin/etcd
```
This will bring up etcd listening on port 4001 for client communication and on port 7001 for server-to-server communication.
Next lets set a single key and then retrieve it:
```
curl -L http://127.0.0.1:4001/v2/keys/mykey -XPUT -d value="this is awesome"
curl -L http://127.0.0.1:4001/v2/keys/mykey
```
You have successfully started an etcd on a single machine and written a key to the store. Now it time to dig into the full etcd API and other guides.
### Next Steps
- Explore the full [API][api.md].
- Setup a [multi-machine cluster][clustering.md].
- Learn the [config format, env variables and flags][configuration.md].
- Find [language bindings and tools][libraries-and-tools.md].
- Learn about the dashboard, lock and leader election [modules][modules.md].
- Use TLS to [secure an etcd cluster][security.md].
- [Tune etcd][tuning.md].
[api.md]: https://github.com/coreos/etcd/blob/master/Documentation/api.md
[clustering.md]: https://github.com/coreos/etcd/blob/master/Documentation/clustering.md
[configuration.md]: https://github.com/coreos/etcd/blob/master/Documentation/configuration.md
[libraries-and-tools.md]: https://github.com/coreos/etcd/blob/master/Documentation/libraries-and-tools.md
[modules.md]: https://github.com/coreos/etcd/blob/master/Documentation/modules.md
[security.md]: https://github.com/coreos/etcd/blob/master/Documentation/security.md
[tuning.md]: https://github.com/coreos/etcd/blob/master/Documentation/tuning.md
## Contributing
See [CONTRIBUTING](https://github.com/coreos/etcd/blob/master/CONTRIBUTING.md) for details on submitting patches and contacting developers via IRC and mailing lists.
## Project Details
### Versioning
#### Service Versioning
etcd uses [semantic versioning][semver].
New minor versions may add additional features to the API.
You can get the version of etcd by issuing a request to /version:
```sh
curl -L http://127.0.0.1:4001/version
```
[semver]: http://semver.org/
#### API Versioning
Clients are encouraged to use the `v2` API. The `v1` API will not change.
The `v2` API responses should not change after the 0.2.0 release but new features will be added over time.
During the pre-v1.0.0 series of releases we may break the API as we fix bugs and get feedback.
### License
etcd is under the Apache 2.0 license. See the [LICENSE][license] file for details.
[license]: https://github.com/coreos/etcd/blob/master/LICENSE

View File

@ -1,63 +0,0 @@
package main
import (
"flag"
"log"
"strconv"
"github.com/coreos/etcd/third_party/github.com/coreos/go-etcd/etcd"
)
func write(endpoint string, requests int, end chan int) {
client := etcd.NewClient([]string{endpoint})
for i := 0; i < requests; i++ {
key := strconv.Itoa(i)
_, err := client.Set(key, key, 0)
if err != nil {
println(err.Error())
}
}
end <- 1
}
func watch(endpoint string, key string) {
client := etcd.NewClient([]string{endpoint})
receiver := make(chan *etcd.Response)
go client.Watch(key, 0, true, receiver, nil)
log.Printf("watching: %s", key)
received := 0
for {
<-receiver
received++
}
}
func main() {
endpoint := flag.String("endpoint", "http://127.0.0.1:4001", "etcd HTTP endpoint")
rWrites := flag.Int("write-requests", 50000, "number of writes")
cWrites := flag.Int("concurrent-writes", 500, "number of concurrent writes")
watches := flag.Int("watches", 500, "number of writes")
flag.Parse()
for i := 0; i < *watches; i++ {
key := strconv.Itoa(i)
go watch(*endpoint, key)
}
wChan := make(chan int, *cWrites)
for i := 0; i < *cWrites; i++ {
go write(*endpoint, (*rWrites / *cWrites), wChan)
}
for i := 0; i < *cWrites; i++ {
<-wChan
log.Printf("Completed %d writes", (*rWrites / *cWrites))
}
}

12
3rdParty/etcd/build vendored
View File

@ -1,12 +0,0 @@
#!/bin/sh -e
if [ ! -h src/github.com/coreos/etcd ]; then
mkdir -p src/github.com/coreos/
ln -s ../../.. src/github.com/coreos/etcd
fi
export GOBIN=${PWD}/bin
export GOPATH=${PWD}
go install github.com/coreos/etcd
go install github.com/coreos/etcd/bench

14
3rdParty/etcd/clean vendored
View File

@ -1,14 +0,0 @@
#!/bin/sh -e
if [ ! -h src/github.com/coreos/etcd ]; then
mkdir -p src/github.com/coreos/
ln -s ../../.. src/github.com/coreos/etcd
fi
export GOBIN=${PWD}/bin
export GOPATH=${PWD}
go clean -i -x github.com/coreos/etcd
go clean -i -x github.com/coreos/etcd/bench
rm -rf src

View File

@ -1,507 +0,0 @@
package config
import (
"flag"
"fmt"
"io/ioutil"
"net"
"net/url"
"os"
"path/filepath"
"reflect"
"strconv"
"strings"
"github.com/coreos/etcd/third_party/github.com/BurntSushi/toml"
"github.com/coreos/etcd/discovery"
"github.com/coreos/etcd/log"
ustrings "github.com/coreos/etcd/pkg/strings"
"github.com/coreos/etcd/server"
)
// 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
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"`
CPUProfileFile string
CorsOrigins []string `toml:"cors" env:"ETCD_CORS"`
DataDir string `toml:"data_dir" env:"ETCD_DATA_DIR"`
Discovery string `toml:"discovery" env:"ETCD_DISCOVERY"`
Force bool
KeyFile string `toml:"key_file" env:"ETCD_KEY_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"`
RetryInterval float64 `toml:"retry_interval" env:"ETCD_RETRY_INTERVAL"`
Name string `toml:"name" env:"ETCD_NAME"`
Snapshot bool `toml:"snapshot" env:"ETCD_SNAPSHOT"`
SnapshotCount int `toml:"snapshot_count" env:"ETCD_SNAPSHOTCOUNT"`
ShowHelp bool
ShowVersion bool
Verbose bool `toml:"verbose" env:"ETCD_VERBOSE"`
VeryVerbose bool `toml:"very_verbose" env:"ETCD_VERY_VERBOSE"`
VeryVeryVerbose bool `toml:"very_very_verbose" env:"ETCD_VERY_VERY_VERBOSE"`
Peer struct {
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"`
HeartbeatTimeout int `toml:"heartbeat_timeout" env:"ETCD_PEER_HEARTBEAT_TIMEOUT"`
ElectionTimeout int `toml:"election_timeout" env:"ETCD_PEER_ELECTION_TIMEOUT"`
}
strTrace string `toml:"trace" env:"ETCD_TRACE"`
GraphiteHost string `toml:"graphite_host" env:"ETCD_GRAPHITE_HOST"`
}
// New returns a Config initialized with default values.
func New() *Config {
c := new(Config)
c.SystemPath = DefaultSystemConfigPath
c.Addr = "127.0.0.1:4001"
c.MaxClusterSize = 9
c.MaxResultBuffer = 1024
c.MaxRetryAttempts = 3
c.RetryInterval = 10.0
c.Snapshot = true
c.SnapshotCount = 10000
c.Peer.Addr = "127.0.0.1:7001"
c.Peer.HeartbeatTimeout = defaultHeartbeatTimeout
c.Peer.ElectionTimeout = defaultElectionTimeout
return c
}
// Loads the configuration from the system config, command line config,
// environment variables, and finally command line arguments.
func (c *Config) Load(arguments []string) error {
var path string
f := flag.NewFlagSet("etcd", -1)
f.SetOutput(ioutil.Discard)
f.StringVar(&path, "config", "", "path to config file")
f.Parse(arguments)
// Load from system file.
if err := c.LoadSystemFile(); err != nil {
return err
}
// Load from config file specified in arguments.
if path != "" {
if err := c.LoadFile(path); err != nil {
return err
}
}
// Load from the environment variables next.
if err := c.LoadEnv(); err != nil {
return err
}
// Load from command line flags.
if err := c.LoadFlags(arguments); err != nil {
return err
}
// Loads peers if a peer file was specified.
if err := c.LoadPeersFile(); err != nil {
return err
}
// Sanitize all the input fields.
if err := c.Sanitize(); err != nil {
return fmt.Errorf("sanitize: %v", err)
}
// Attempt cluster discovery
if c.Discovery != "" {
if err := c.handleDiscovery(); err != nil {
return err
}
}
// Force remove server configuration if specified.
if c.Force {
c.Reset()
}
return nil
}
// Loads from the system etcd configuration file if it exists.
func (c *Config) LoadSystemFile() error {
if _, err := os.Stat(c.SystemPath); os.IsNotExist(err) {
return nil
}
return c.LoadFile(c.SystemPath)
}
// Loads configuration from a file.
func (c *Config) LoadFile(path string) error {
_, err := toml.DecodeFile(path, &c)
return err
}
// LoadEnv loads the configuration via environment variables.
func (c *Config) LoadEnv() error {
if err := c.loadEnv(c); err != nil {
return err
}
if err := c.loadEnv(&c.Peer); err != nil {
return err
}
return nil
}
func (c *Config) loadEnv(target interface{}) error {
value := reflect.Indirect(reflect.ValueOf(target))
typ := value.Type()
for i := 0; i < typ.NumField(); i++ {
field := typ.Field(i)
// Retrieve environment variable.
v := strings.TrimSpace(os.Getenv(field.Tag.Get("env")))
if v == "" {
continue
}
// Set the appropriate type.
switch field.Type.Kind() {
case reflect.Bool:
value.Field(i).SetBool(v != "0" && v != "false")
case reflect.Int:
newValue, err := strconv.ParseInt(v, 10, 0)
if err != nil {
return fmt.Errorf("Parse error: %s: %s", field.Tag.Get("env"), err)
}
value.Field(i).SetInt(newValue)
case reflect.String:
value.Field(i).SetString(v)
case reflect.Slice:
value.Field(i).Set(reflect.ValueOf(ustrings.TrimSplit(v, ",")))
}
}
return nil
}
func (c *Config) handleDiscovery() error {
p, err := discovery.Do(c.Discovery, c.Name, c.Peer.Addr)
// This is fatal, discovery encountered an unexpected error
// and we have no peer list.
if err != nil && len(c.Peers) == 0 {
log.Fatalf("Discovery failed and a backup peer list wasn't provided: %v", err)
return err
}
// Warn about errors coming from discovery, this isn't fatal
// since the user might have provided a peer list elsewhere.
if err != nil {
log.Warnf("Discovery encountered an error but a backup peer list (%v) was provided: %v", c.Peers, err)
}
for i := range p {
// Strip the scheme off of the peer if it has one
// TODO(bp): clean this up!
purl, err := url.Parse(p[i])
if err == nil {
p[i] = purl.Host
}
}
c.Peers = p
return nil
}
// Loads configuration from command line flags.
func (c *Config) LoadFlags(arguments []string) error {
var peers, cors, path string
f := flag.NewFlagSet(os.Args[0], flag.ContinueOnError)
f.SetOutput(ioutil.Discard)
f.BoolVar(&c.ShowHelp, "h", false, "")
f.BoolVar(&c.ShowHelp, "help", false, "")
f.BoolVar(&c.ShowVersion, "version", false, "")
f.BoolVar(&c.Force, "f", false, "")
f.BoolVar(&c.Force, "force", false, "")
f.BoolVar(&c.Verbose, "v", c.Verbose, "")
f.BoolVar(&c.VeryVerbose, "vv", c.VeryVerbose, "")
f.BoolVar(&c.VeryVeryVerbose, "vvv", c.VeryVeryVerbose, "")
f.StringVar(&peers, "peers", "", "")
f.StringVar(&c.PeersFile, "peers-file", c.PeersFile, "")
f.StringVar(&c.Name, "name", c.Name, "")
f.StringVar(&c.Addr, "addr", c.Addr, "")
f.StringVar(&c.Discovery, "discovery", c.Discovery, "")
f.StringVar(&c.BindAddr, "bind-addr", c.BindAddr, "")
f.StringVar(&c.Peer.Addr, "peer-addr", c.Peer.Addr, "")
f.StringVar(&c.Peer.BindAddr, "peer-bind-addr", c.Peer.BindAddr, "")
f.StringVar(&c.CAFile, "ca-file", c.CAFile, "")
f.StringVar(&c.CertFile, "cert-file", c.CertFile, "")
f.StringVar(&c.KeyFile, "key-file", c.KeyFile, "")
f.StringVar(&c.Peer.CAFile, "peer-ca-file", c.Peer.CAFile, "")
f.StringVar(&c.Peer.CertFile, "peer-cert-file", c.Peer.CertFile, "")
f.StringVar(&c.Peer.KeyFile, "peer-key-file", c.Peer.KeyFile, "")
f.StringVar(&c.DataDir, "data-dir", c.DataDir, "")
f.IntVar(&c.MaxResultBuffer, "max-result-buffer", c.MaxResultBuffer, "")
f.IntVar(&c.MaxRetryAttempts, "max-retry-attempts", c.MaxRetryAttempts, "")
f.Float64Var(&c.RetryInterval, "retry-interval", c.RetryInterval, "")
f.IntVar(&c.MaxClusterSize, "max-cluster-size", c.MaxClusterSize, "")
f.IntVar(&c.Peer.HeartbeatTimeout, "peer-heartbeat-timeout", c.Peer.HeartbeatTimeout, "")
f.IntVar(&c.Peer.ElectionTimeout, "peer-election-timeout", c.Peer.ElectionTimeout, "")
f.StringVar(&cors, "cors", "", "")
f.BoolVar(&c.Snapshot, "snapshot", c.Snapshot, "")
f.IntVar(&c.SnapshotCount, "snapshot-count", c.SnapshotCount, "")
f.StringVar(&c.CPUProfileFile, "cpuprofile", "", "")
f.StringVar(&c.strTrace, "trace", "", "")
f.StringVar(&c.GraphiteHost, "graphite-host", "", "")
// BEGIN IGNORED FLAGS
f.StringVar(&path, "config", "", "")
// BEGIN IGNORED FLAGS
// BEGIN DEPRECATED FLAGS
f.StringVar(&peers, "C", "", "(deprecated)")
f.StringVar(&c.PeersFile, "CF", c.PeersFile, "(deprecated)")
f.StringVar(&c.Name, "n", c.Name, "(deprecated)")
f.StringVar(&c.Addr, "c", c.Addr, "(deprecated)")
f.StringVar(&c.BindAddr, "cl", c.BindAddr, "(deprecated)")
f.StringVar(&c.Peer.Addr, "s", c.Peer.Addr, "(deprecated)")
f.StringVar(&c.Peer.BindAddr, "sl", c.Peer.BindAddr, "(deprecated)")
f.StringVar(&c.Peer.CAFile, "serverCAFile", c.Peer.CAFile, "(deprecated)")
f.StringVar(&c.Peer.CertFile, "serverCert", c.Peer.CertFile, "(deprecated)")
f.StringVar(&c.Peer.KeyFile, "serverKey", c.Peer.KeyFile, "(deprecated)")
f.StringVar(&c.CAFile, "clientCAFile", c.CAFile, "(deprecated)")
f.StringVar(&c.CertFile, "clientCert", c.CertFile, "(deprecated)")
f.StringVar(&c.KeyFile, "clientKey", c.KeyFile, "(deprecated)")
f.StringVar(&c.DataDir, "d", c.DataDir, "(deprecated)")
f.IntVar(&c.MaxResultBuffer, "m", c.MaxResultBuffer, "(deprecated)")
f.IntVar(&c.MaxRetryAttempts, "r", c.MaxRetryAttempts, "(deprecated)")
f.IntVar(&c.MaxClusterSize, "maxsize", c.MaxClusterSize, "(deprecated)")
f.IntVar(&c.SnapshotCount, "snapshotCount", c.SnapshotCount, "(deprecated)")
// END DEPRECATED FLAGS
if err := f.Parse(arguments); err != nil {
return err
}
// Print deprecation warnings on STDERR.
f.Visit(func(f *flag.Flag) {
if len(newFlagNameLookup[f.Name]) > 0 {
fmt.Fprintf(os.Stderr, "[deprecated] use -%s, not -%s\n", newFlagNameLookup[f.Name], f.Name)
}
})
// Convert some parameters to lists.
if peers != "" {
c.Peers = ustrings.TrimSplit(peers, ",")
}
if cors != "" {
c.CorsOrigins = ustrings.TrimSplit(cors, ",")
}
return nil
}
// LoadPeersFile loads the peers listed in the peers file.
func (c *Config) LoadPeersFile() error {
if c.PeersFile == "" {
return nil
}
b, err := ioutil.ReadFile(c.PeersFile)
if err != nil {
return fmt.Errorf("Peers file error: %s", err)
}
c.Peers = ustrings.TrimSplit(string(b), ",")
return nil
}
// DataDirFromName sets the data dir from a machine name and issue a warning
// that etcd is guessing.
func (c *Config) DataDirFromName() {
c.DataDir = c.Name + ".etcd"
log.Warnf("Using the directory %s as the etcd curation directory because a directory was not specified. ", c.DataDir)
return
}
// NameFromHostname sets the machine name from the hostname. This is to help
// people get started without thinking up a name.
func (c *Config) NameFromHostname() {
host, err := os.Hostname()
if err != nil && host == "" {
log.Fatal("Node name required and hostname not set. e.g. '-name=name'")
}
c.Name = host
}
// Reset removes all server configuration files.
func (c *Config) Reset() error {
if err := os.RemoveAll(filepath.Join(c.DataDir, "log")); err != nil {
return err
}
if err := os.RemoveAll(filepath.Join(c.DataDir, "conf")); err != nil {
return err
}
if err := os.RemoveAll(filepath.Join(c.DataDir, "snapshot")); err != nil {
return err
}
return nil
}
// Sanitize cleans the input fields.
func (c *Config) Sanitize() error {
var err error
// Sanitize the URLs first.
if c.Addr, err = sanitizeURL(c.Addr, c.EtcdTLSInfo().Scheme()); err != nil {
return fmt.Errorf("Advertised URL: %s", err)
}
if c.BindAddr, err = sanitizeBindAddr(c.BindAddr, c.Addr); err != nil {
return fmt.Errorf("Listen Host: %s", err)
}
if c.Peer.Addr, err = sanitizeURL(c.Peer.Addr, c.PeerTLSInfo().Scheme()); err != nil {
return fmt.Errorf("Peer Advertised URL: %s", err)
}
if c.Peer.BindAddr, err = sanitizeBindAddr(c.Peer.BindAddr, c.Peer.Addr); err != nil {
return fmt.Errorf("Peer Listen Host: %s", err)
}
// Only guess the machine name if there is no data dir specified
// because the info file should have our name
if c.Name == "" && c.DataDir == "" {
c.NameFromHostname()
}
if c.DataDir == "" && c.Name != "" && !c.ShowVersion && !c.ShowHelp {
c.DataDirFromName()
}
return nil
}
// EtcdTLSInfo retrieves a TLSInfo object for the etcd server
func (c *Config) EtcdTLSInfo() server.TLSInfo {
return server.TLSInfo{
CAFile: c.CAFile,
CertFile: c.CertFile,
KeyFile: c.KeyFile,
}
}
// PeerRaftInfo retrieves a TLSInfo object for the peer server.
func (c *Config) PeerTLSInfo() server.TLSInfo {
return server.TLSInfo{
CAFile: c.Peer.CAFile,
CertFile: c.Peer.CertFile,
KeyFile: c.Peer.KeyFile,
}
}
// MetricsBucketName generates the name that should be used for a
// corresponding MetricsBucket object
func (c *Config) MetricsBucketName() string {
return fmt.Sprintf("etcd.%s", c.Name)
}
// Trace determines if any trace-level information should be emitted
func (c *Config) Trace() bool {
return c.strTrace == "*"
}
// sanitizeURL will cleanup a host string in the format hostname[:port] and
// attach a schema.
func sanitizeURL(host string, defaultScheme string) (string, error) {
// Blank URLs are fine input, just return it
if len(host) == 0 {
return host, nil
}
p, err := url.Parse(host)
if err != nil {
return "", err
}
// Make sure the host is in Host:Port format
_, _, err = net.SplitHostPort(host)
if err != nil {
return "", err
}
p = &url.URL{Host: host, Scheme: defaultScheme}
return p.String(), nil
}
// sanitizeBindAddr cleans up the BindAddr parameter and appends a port
// if necessary based on the advertised port.
func sanitizeBindAddr(bindAddr string, addr string) (string, error) {
aurl, err := url.Parse(addr)
if err != nil {
return "", err
}
// If it is a valid host:port simply return with no further checks.
bhost, bport, err := net.SplitHostPort(bindAddr)
if err == nil && bhost != "" {
return bindAddr, nil
}
// SplitHostPort makes the host optional, but we don't want that.
if bhost == "" && bport != "" {
return "", fmt.Errorf("IP required can't use a port only")
}
// bindAddr doesn't have a port if we reach here so take the port from the
// advertised URL.
_, aport, err := net.SplitHostPort(aurl.Host)
if err != nil {
return "", err
}
return net.JoinHostPort(bindAddr, aport), nil
}

View File

@ -1,736 +0,0 @@
package config
import (
"io/ioutil"
"os"
"testing"
"github.com/coreos/etcd/third_party/github.com/BurntSushi/toml"
"github.com/coreos/etcd/third_party/github.com/stretchr/testify/assert"
)
// Ensures that a configuration can be deserialized from TOML.
func TestConfigTOML(t *testing.T) {
content := `
addr = "127.0.0.1:4002"
ca_file = "/tmp/file.ca"
cert_file = "/tmp/file.cert"
cors = ["*"]
cpu_profile_file = "XXX"
data_dir = "/tmp/data"
discovery = "http://example.com/foobar"
key_file = "/tmp/file.key"
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
name = "test-name"
snapshot = true
verbose = true
very_verbose = true
[peer]
addr = "127.0.0.1:7002"
ca_file = "/tmp/peer/file.ca"
cert_file = "/tmp/peer/file.cert"
key_file = "/tmp/peer/file.key"
bind_addr = "127.0.0.1:7003"
`
c := New()
_, err := toml.Decode(content, &c)
assert.Nil(t, err, "")
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.CorsOrigins, []string{"*"}, "")
assert.Equal(t, c.DataDir, "/tmp/data", "")
assert.Equal(t, c.Discovery, "http://example.com/foobar", "")
assert.Equal(t, c.KeyFile, "/tmp/file.key", "")
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, "")
assert.Equal(t, c.Name, "test-name", "")
assert.Equal(t, c.Snapshot, true, "")
assert.Equal(t, c.Verbose, true, "")
assert.Equal(t, c.VeryVerbose, true, "")
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.BindAddr, "127.0.0.1:7003", "")
}
// Ensures that a configuration can be retrieved from environment variables.
func TestConfigEnv(t *testing.T) {
os.Setenv("ETCD_CA_FILE", "/tmp/file.ca")
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_DATA_DIR", "/tmp/data")
os.Setenv("ETCD_DISCOVERY", "http://example.com/foobar")
os.Setenv("ETCD_KEY_FILE", "/tmp/file.key")
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")
os.Setenv("ETCD_NAME", "test-name")
os.Setenv("ETCD_SNAPSHOT", "true")
os.Setenv("ETCD_VERBOSE", "1")
os.Setenv("ETCD_VERY_VERBOSE", "yes")
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_BIND_ADDR", "127.0.0.1:7003")
c := New()
c.LoadEnv()
assert.Equal(t, c.CAFile, "/tmp/file.ca", "")
assert.Equal(t, c.CertFile, "/tmp/file.cert", "")
assert.Equal(t, c.CorsOrigins, []string{"localhost:4001", "localhost:4002"}, "")
assert.Equal(t, c.DataDir, "/tmp/data", "")
assert.Equal(t, c.Discovery, "http://example.com/foobar", "")
assert.Equal(t, c.KeyFile, "/tmp/file.key", "")
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, "")
assert.Equal(t, c.Name, "test-name", "")
assert.Equal(t, c.Snapshot, true, "")
assert.Equal(t, c.Verbose, true, "")
assert.Equal(t, c.VeryVerbose, true, "")
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.BindAddr, "127.0.0.1:7003", "")
// Clear this as it will mess up other tests
os.Setenv("ETCD_DISCOVERY", "")
}
// Ensures that the "help" flag can be parsed.
func TestConfigHelpFlag(t *testing.T) {
c := New()
assert.Nil(t, c.LoadFlags([]string{"-help"}), "")
assert.True(t, c.ShowHelp)
}
// Ensures that the abbreviated "help" flag can be parsed.
func TestConfigAbbreviatedHelpFlag(t *testing.T) {
c := New()
assert.Nil(t, c.LoadFlags([]string{"-h"}), "")
assert.True(t, c.ShowHelp)
}
// Ensures that the "version" flag can be parsed.
func TestConfigVersionFlag(t *testing.T) {
c := New()
assert.Nil(t, c.LoadFlags([]string{"-version"}), "")
assert.True(t, c.ShowVersion)
}
// Ensures that the "force config" flag can be parsed.
func TestConfigForceFlag(t *testing.T) {
c := New()
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 := New()
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 TestConfigAddrEnv(t *testing.T) {
withEnv("ETCD_ADDR", "127.0.0.1:4002", func(c *Config) {
assert.Nil(t, c.LoadEnv(), "")
assert.Equal(t, c.Addr, "127.0.0.1:4002", "")
})
}
// Ensures that a the advertised flag can be parsed.
func TestConfigAddrFlag(t *testing.T) {
c := New()
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.
func TestConfigCAFileEnv(t *testing.T) {
withEnv("ETCD_CA_FILE", "/tmp/file.ca", func(c *Config) {
assert.Nil(t, c.LoadEnv(), "")
assert.Equal(t, c.CAFile, "/tmp/file.ca", "")
})
}
// Ensures that a the CA file flag can be parsed.
func TestConfigCAFileFlag(t *testing.T) {
c := New()
assert.Nil(t, c.LoadFlags([]string{"-ca-file", "/tmp/file.ca"}), "")
assert.Equal(t, c.CAFile, "/tmp/file.ca", "")
}
// Ensures that a the CA file can be parsed from the environment.
func TestConfigCertFileEnv(t *testing.T) {
withEnv("ETCD_CERT_FILE", "/tmp/file.cert", func(c *Config) {
assert.Nil(t, c.LoadEnv(), "")
assert.Equal(t, c.CertFile, "/tmp/file.cert", "")
})
}
// Ensures that a the Cert file flag can be parsed.
func TestConfigCertFileFlag(t *testing.T) {
c := New()
assert.Nil(t, c.LoadFlags([]string{"-cert-file", "/tmp/file.cert"}), "")
assert.Equal(t, c.CertFile, "/tmp/file.cert", "")
}
// Ensures that a the Key file can be parsed from the environment.
func TestConfigKeyFileEnv(t *testing.T) {
withEnv("ETCD_KEY_FILE", "/tmp/file.key", func(c *Config) {
assert.Nil(t, c.LoadEnv(), "")
assert.Equal(t, c.KeyFile, "/tmp/file.key", "")
})
}
// Ensures that a the Key file flag can be parsed.
func TestConfigKeyFileFlag(t *testing.T) {
c := New()
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 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.BindAddr, "127.0.0.1:4003", "")
})
}
// Ensures that a the Listen Host file flag can be parsed.
func TestConfigBindAddrFlag(t *testing.T) {
c := New()
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 a the Listen Host port overrides the advertised port
func TestConfigBindAddrOverride(t *testing.T) {
c := New()
assert.Nil(t, c.LoadFlags([]string{"-addr", "127.0.0.1:4009", "-bind-addr", "127.0.0.1:4010"}), "")
assert.Nil(t, c.Sanitize())
assert.Equal(t, c.BindAddr, "127.0.0.1:4010", "")
}
// Ensures that a the Listen Host inherits its port from the advertised addr
func TestConfigBindAddrInheritPort(t *testing.T) {
c := New()
assert.Nil(t, c.LoadFlags([]string{"-addr", "127.0.0.1:4009", "-bind-addr", "127.0.0.1"}), "")
assert.Nil(t, c.Sanitize())
assert.Equal(t, c.BindAddr, "127.0.0.1:4009", "")
}
// Ensures that a port only argument errors out
func TestConfigBindAddrErrorOnNoHost(t *testing.T) {
c := New()
assert.Nil(t, c.LoadFlags([]string{"-addr", "127.0.0.1:4009", "-bind-addr", ":4010"}), "")
assert.Error(t, c.Sanitize())
}
// 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.Peers, []string{"coreos.com:4001", "coreos.com:4002"}, "")
})
}
// Ensures that a the Peers flag can be parsed.
func TestConfigPeersFlag(t *testing.T) {
c := New()
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 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.PeersFile, "/tmp/peers", "")
})
}
// Ensures that a the Peers File flag can be parsed.
func TestConfigPeersFileFlag(t *testing.T) {
c := New()
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.
func TestConfigMaxClusterSizeEnv(t *testing.T) {
withEnv("ETCD_MAX_CLUSTER_SIZE", "5", func(c *Config) {
assert.Nil(t, c.LoadEnv(), "")
assert.Equal(t, c.MaxClusterSize, 5, "")
})
}
// Ensures that a the Max Cluster Size flag can be parsed.
func TestConfigMaxClusterSizeFlag(t *testing.T) {
c := New()
assert.Nil(t, c.LoadFlags([]string{"-max-cluster-size", "5"}), "")
assert.Equal(t, c.MaxClusterSize, 5, "")
}
// Ensures that the Max Result Buffer can be parsed from the environment.
func TestConfigMaxResultBufferEnv(t *testing.T) {
withEnv("ETCD_MAX_RESULT_BUFFER", "512", func(c *Config) {
assert.Nil(t, c.LoadEnv(), "")
assert.Equal(t, c.MaxResultBuffer, 512, "")
})
}
// Ensures that a the Max Result Buffer flag can be parsed.
func TestConfigMaxResultBufferFlag(t *testing.T) {
c := New()
assert.Nil(t, c.LoadFlags([]string{"-max-result-buffer", "512"}), "")
assert.Equal(t, c.MaxResultBuffer, 512, "")
}
// Ensures that the Max Retry Attempts can be parsed from the environment.
func TestConfigMaxRetryAttemptsEnv(t *testing.T) {
withEnv("ETCD_MAX_RETRY_ATTEMPTS", "10", func(c *Config) {
assert.Nil(t, c.LoadEnv(), "")
assert.Equal(t, c.MaxRetryAttempts, 10, "")
})
}
// Ensures that a the Max Retry Attempts flag can be parsed.
func TestConfigMaxRetryAttemptsFlag(t *testing.T) {
c := New()
assert.Nil(t, c.LoadFlags([]string{"-max-retry-attempts", "10"}), "")
assert.Equal(t, c.MaxRetryAttempts, 10, "")
}
// Ensures that the Name can be parsed from the environment.
func TestConfigNameEnv(t *testing.T) {
withEnv("ETCD_NAME", "test-name", func(c *Config) {
assert.Nil(t, c.LoadEnv(), "")
assert.Equal(t, c.Name, "test-name", "")
})
}
// Ensures that a the Name flag can be parsed.
func TestConfigNameFlag(t *testing.T) {
c := New()
assert.Nil(t, c.LoadFlags([]string{"-name", "test-name"}), "")
assert.Equal(t, c.Name, "test-name", "")
}
// Ensures that a Name gets guessed if not specified
func TestConfigNameGuess(t *testing.T) {
c := New()
assert.Nil(t, c.LoadFlags([]string{}), "")
assert.Nil(t, c.Sanitize())
name, _ := os.Hostname()
assert.Equal(t, c.Name, name, "")
}
// Ensures that a DataDir gets guessed if not specified
func TestConfigDataDirGuess(t *testing.T) {
c := New()
assert.Nil(t, c.LoadFlags([]string{}), "")
assert.Nil(t, c.Sanitize())
name, _ := os.Hostname()
assert.Equal(t, c.DataDir, name+".etcd", "")
}
// Ensures that Snapshot can be parsed from the environment.
func TestConfigSnapshotEnv(t *testing.T) {
withEnv("ETCD_SNAPSHOT", "1", func(c *Config) {
assert.Nil(t, c.LoadEnv(), "")
assert.Equal(t, c.Snapshot, true, "")
})
}
// Ensures that a the Snapshot flag can be parsed.
func TestConfigSnapshotFlag(t *testing.T) {
c := New()
assert.Nil(t, c.LoadFlags([]string{"-snapshot"}), "")
assert.Equal(t, c.Snapshot, true, "")
}
// Ensures that Verbose can be parsed from the environment.
func TestConfigVerboseEnv(t *testing.T) {
withEnv("ETCD_VERBOSE", "true", func(c *Config) {
assert.Nil(t, c.LoadEnv(), "")
assert.Equal(t, c.Verbose, true, "")
})
}
// Ensures that a the Verbose flag can be parsed.
func TestConfigVerboseFlag(t *testing.T) {
c := New()
assert.Nil(t, c.LoadFlags([]string{"-v"}), "")
assert.Equal(t, c.Verbose, true, "")
}
// Ensures that Very Verbose can be parsed from the environment.
func TestConfigVeryVerboseEnv(t *testing.T) {
withEnv("ETCD_VERY_VERBOSE", "true", func(c *Config) {
assert.Nil(t, c.LoadEnv(), "")
assert.Equal(t, c.VeryVerbose, true, "")
})
}
// Ensures that a the Very Verbose flag can be parsed.
func TestConfigVeryVerboseFlag(t *testing.T) {
c := New()
assert.Nil(t, c.LoadFlags([]string{"-vv"}), "")
assert.Equal(t, c.VeryVerbose, true, "")
}
// Ensures that the Peer Advertised URL can be parsed from the environment.
func TestConfigPeerAddrEnv(t *testing.T) {
withEnv("ETCD_PEER_ADDR", "localhost:7002", func(c *Config) {
assert.Nil(t, c.LoadEnv(), "")
assert.Equal(t, c.Peer.Addr, "localhost:7002", "")
})
}
// Ensures that a the Peer Advertised URL flag can be parsed.
func TestConfigPeerAddrFlag(t *testing.T) {
c := New()
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.
func TestConfigPeerCAFileEnv(t *testing.T) {
withEnv("ETCD_PEER_CA_FILE", "/tmp/peer/file.ca", func(c *Config) {
assert.Nil(t, c.LoadEnv(), "")
assert.Equal(t, c.Peer.CAFile, "/tmp/peer/file.ca", "")
})
}
// Ensures that a the Peer CA file flag can be parsed.
func TestConfigPeerCAFileFlag(t *testing.T) {
c := New()
assert.Nil(t, c.LoadFlags([]string{"-peer-ca-file", "/tmp/peer/file.ca"}), "")
assert.Equal(t, c.Peer.CAFile, "/tmp/peer/file.ca", "")
}
// Ensures that the Peer Cert File can be parsed from the environment.
func TestConfigPeerCertFileEnv(t *testing.T) {
withEnv("ETCD_PEER_CERT_FILE", "/tmp/peer/file.cert", func(c *Config) {
assert.Nil(t, c.LoadEnv(), "")
assert.Equal(t, c.Peer.CertFile, "/tmp/peer/file.cert", "")
})
}
// Ensures that a the Cert file flag can be parsed.
func TestConfigPeerCertFileFlag(t *testing.T) {
c := New()
assert.Nil(t, c.LoadFlags([]string{"-peer-cert-file", "/tmp/peer/file.cert"}), "")
assert.Equal(t, c.Peer.CertFile, "/tmp/peer/file.cert", "")
}
// Ensures that the Peer Key File can be parsed from the environment.
func TestConfigPeerKeyFileEnv(t *testing.T) {
withEnv("ETCD_PEER_KEY_FILE", "/tmp/peer/file.key", func(c *Config) {
assert.Nil(t, c.LoadEnv(), "")
assert.Equal(t, c.Peer.KeyFile, "/tmp/peer/file.key", "")
})
}
// Ensures that a the Peer Key file flag can be parsed.
func TestConfigPeerKeyFileFlag(t *testing.T) {
c := New()
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 TestConfigPeerBindAddrEnv(t *testing.T) {
withEnv("ETCD_PEER_BIND_ADDR", "localhost:7004", func(c *Config) {
assert.Nil(t, c.LoadEnv(), "")
assert.Equal(t, c.Peer.BindAddr, "localhost:7004", "")
})
}
// Ensures that a bad flag returns an error.
func TestConfigBadFlag(t *testing.T) {
c := New()
err := c.LoadFlags([]string{"-no-such-flag"})
assert.Error(t, err)
assert.Equal(t, err.Error(), `flag provided but not defined: -no-such-flag`)
}
// Ensures that a the Peer Listen Host file flag can be parsed.
func TestConfigPeerBindAddrFlag(t *testing.T) {
c := New()
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 := `addr = "127.0.0.1:5000"`
custom := `addr = "127.0.0.1:6000"`
withTempFile(system, func(p1 string) {
withTempFile(custom, func(p2 string) {
c := New()
c.SystemPath = p1
assert.Nil(t, c.Load([]string{"-config", p2}), "")
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_ADDR", "127.0.0.1:8000")
defer os.Setenv("ETCD_PEER_ADDR", "")
custom := `[peer]` + "\n" + `advertised_url = "127.0.0.1:9000"`
withTempFile(custom, func(path string) {
c := New()
c.SystemPath = ""
assert.Nil(t, c.Load([]string{"-config", path}), "")
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_ADDR", "127.0.0.1:1000")
defer os.Setenv("ETCD_ADDR", "")
c := New()
c.SystemPath = ""
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) {
_, stderr := capture(func() {
c := New()
err := c.LoadFlags([]string{"-c", "127.0.0.1:4002"})
assert.NoError(t, err)
assert.Equal(t, c.Addr, "127.0.0.1:4002")
})
assert.Equal(t, stderr, "[deprecated] use -addr, not -c\n")
}
func TestConfigDeprecatedBindAddrFlag(t *testing.T) {
_, stderr := capture(func() {
c := New()
err := c.LoadFlags([]string{"-cl", "127.0.0.1:4003"})
assert.NoError(t, err)
assert.Equal(t, c.BindAddr, "127.0.0.1:4003", "")
})
assert.Equal(t, stderr, "[deprecated] use -bind-addr, not -cl\n", "")
}
func TestConfigDeprecatedCAFileFlag(t *testing.T) {
_, stderr := capture(func() {
c := New()
err := c.LoadFlags([]string{"-clientCAFile", "/tmp/file.ca"})
assert.NoError(t, err)
assert.Equal(t, c.CAFile, "/tmp/file.ca", "")
})
assert.Equal(t, stderr, "[deprecated] use -ca-file, not -clientCAFile\n", "")
}
func TestConfigDeprecatedCertFileFlag(t *testing.T) {
_, stderr := capture(func() {
c := New()
err := c.LoadFlags([]string{"-clientCert", "/tmp/file.cert"})
assert.NoError(t, err)
assert.Equal(t, c.CertFile, "/tmp/file.cert", "")
})
assert.Equal(t, stderr, "[deprecated] use -cert-file, not -clientCert\n", "")
}
func TestConfigDeprecatedKeyFileFlag(t *testing.T) {
_, stderr := capture(func() {
c := New()
err := c.LoadFlags([]string{"-clientKey", "/tmp/file.key"})
assert.NoError(t, err)
assert.Equal(t, c.KeyFile, "/tmp/file.key", "")
})
assert.Equal(t, stderr, "[deprecated] use -key-file, not -clientKey\n", "")
}
func TestConfigDeprecatedPeersFlag(t *testing.T) {
_, stderr := capture(func() {
c := New()
err := c.LoadFlags([]string{"-C", "coreos.com:4001,coreos.com:4002"})
assert.NoError(t, err)
assert.Equal(t, c.Peers, []string{"coreos.com:4001", "coreos.com:4002"}, "")
})
assert.Equal(t, stderr, "[deprecated] use -peers, not -C\n", "")
}
func TestConfigDeprecatedPeersFileFlag(t *testing.T) {
_, stderr := capture(func() {
c := New()
err := c.LoadFlags([]string{"-CF", "/tmp/machines"})
assert.NoError(t, err)
assert.Equal(t, c.PeersFile, "/tmp/machines", "")
})
assert.Equal(t, stderr, "[deprecated] use -peers-file, not -CF\n", "")
}
func TestConfigDeprecatedMaxClusterSizeFlag(t *testing.T) {
_, stderr := capture(func() {
c := New()
err := c.LoadFlags([]string{"-maxsize", "5"})
assert.NoError(t, err)
assert.Equal(t, c.MaxClusterSize, 5, "")
})
assert.Equal(t, stderr, "[deprecated] use -max-cluster-size, not -maxsize\n", "")
}
func TestConfigDeprecatedMaxResultBufferFlag(t *testing.T) {
_, stderr := capture(func() {
c := New()
err := c.LoadFlags([]string{"-m", "512"})
assert.NoError(t, err)
assert.Equal(t, c.MaxResultBuffer, 512, "")
})
assert.Equal(t, stderr, "[deprecated] use -max-result-buffer, not -m\n", "")
}
func TestConfigDeprecatedMaxRetryAttemptsFlag(t *testing.T) {
_, stderr := capture(func() {
c := New()
err := c.LoadFlags([]string{"-r", "10"})
assert.NoError(t, err)
assert.Equal(t, c.MaxRetryAttempts, 10, "")
})
assert.Equal(t, stderr, "[deprecated] use -max-retry-attempts, not -r\n", "")
}
func TestConfigDeprecatedNameFlag(t *testing.T) {
_, stderr := capture(func() {
c := New()
err := c.LoadFlags([]string{"-n", "test-name"})
assert.NoError(t, err)
assert.Equal(t, c.Name, "test-name", "")
})
assert.Equal(t, stderr, "[deprecated] use -name, not -n\n", "")
}
func TestConfigDeprecatedPeerAddrFlag(t *testing.T) {
_, stderr := capture(func() {
c := New()
err := c.LoadFlags([]string{"-s", "localhost:7002"})
assert.NoError(t, err)
assert.Equal(t, c.Peer.Addr, "localhost:7002", "")
})
assert.Equal(t, stderr, "[deprecated] use -peer-addr, not -s\n", "")
}
func TestConfigDeprecatedPeerBindAddrFlag(t *testing.T) {
_, stderr := capture(func() {
c := New()
err := c.LoadFlags([]string{"-sl", "127.0.0.1:4003"})
assert.NoError(t, err)
assert.Equal(t, c.Peer.BindAddr, "127.0.0.1:4003", "")
})
assert.Equal(t, stderr, "[deprecated] use -peer-bind-addr, not -sl\n", "")
}
func TestConfigDeprecatedPeerCAFileFlag(t *testing.T) {
_, stderr := capture(func() {
c := New()
err := c.LoadFlags([]string{"-serverCAFile", "/tmp/peer/file.ca"})
assert.NoError(t, err)
assert.Equal(t, c.Peer.CAFile, "/tmp/peer/file.ca", "")
})
assert.Equal(t, stderr, "[deprecated] use -peer-ca-file, not -serverCAFile\n", "")
}
func TestConfigDeprecatedPeerCertFileFlag(t *testing.T) {
_, stderr := capture(func() {
c := New()
err := c.LoadFlags([]string{"-serverCert", "/tmp/peer/file.cert"})
assert.NoError(t, err)
assert.Equal(t, c.Peer.CertFile, "/tmp/peer/file.cert", "")
})
assert.Equal(t, stderr, "[deprecated] use -peer-cert-file, not -serverCert\n", "")
}
func TestConfigDeprecatedPeerKeyFileFlag(t *testing.T) {
_, stderr := capture(func() {
c := New()
err := c.LoadFlags([]string{"-serverKey", "/tmp/peer/file.key"})
assert.NoError(t, err)
assert.Equal(t, c.Peer.KeyFile, "/tmp/peer/file.key", "")
})
assert.Equal(t, stderr, "[deprecated] use -peer-key-file, not -serverKey\n", "")
}
//--------------------------------------
// Helpers
//--------------------------------------
// Sets up the environment with a given environment variable set.
func withEnv(key, value string, f func(c *Config)) {
os.Setenv(key, value)
defer os.Setenv(key, "")
c := New()
f(c)
}
// Creates a temp file and calls a function with the context.
func withTempFile(content string, fn func(string)) {
f, _ := ioutil.TempFile("", "")
f.WriteString(content)
f.Close()
defer os.Remove(f.Name())
fn(f.Name())
}
// Captures STDOUT & STDERR and returns the output as strings.
func capture(fn func()) (string, string) {
// Create temp files.
tmpout, _ := ioutil.TempFile("", "")
defer os.Remove(tmpout.Name())
tmperr, _ := ioutil.TempFile("", "")
defer os.Remove(tmperr.Name())
stdout, stderr := os.Stdout, os.Stderr
os.Stdout, os.Stderr = tmpout, tmperr
// Execute function argument and then reassign stdout/stderr.
fn()
os.Stdout, os.Stderr = stdout, stderr
// Close temp files and read them.
tmpout.Close()
bout, _ := ioutil.ReadFile(tmpout.Name())
tmperr.Close()
berr, _ := ioutil.ReadFile(tmperr.Name())
return string(bout), string(berr)
}

View File

@ -1,9 +0,0 @@
package config
const (
// The amount of time (in ms) to elapse without a heartbeat before becoming a candidate
defaultElectionTimeout = 200
// The frequency (in ms) by which heartbeats are sent to followers.
defaultHeartbeatTimeout = 50
)

View File

@ -1,9 +0,0 @@
FROM stackbrew/ubuntu:raring
RUN apt-get update && apt-get install -y collectd
RUN adduser --system --group --no-create-home collectd
ADD collectd.conf /etc/collectd/collectd.conf.tmpl
ADD collectd-wrapper /bin/collectd-wrapper
RUN chown -R collectd:collectd /etc/collectd
CMD ["collectd-wrapper"]

View File

@ -1,20 +0,0 @@
We're going to use Docker to build a chroot env that can be run with systemd-nspawn since I cannot figure out how to run
a container using docker in the global network namespace.
1. Build the collectd image using docker
docker build -t collectd .
2. Run the container (since we have to run it to export it...)
COLLECTD_CONTAINER=`docker run -name collectd-tmp -d collectd`
3. Export then kill the container
docker export collectd-tmp > /tmp/collectd.tar
4. Kill the temporary container
docker kill $COLLECTD_CONTAINER
5. Unpack the tar archive
mkdir -p /tmp/collectd && tar -xvf /tmp/collectd.tar -C /tmp/collectd/
6. Run collectd with systemd-nspawn - replace the COLLECTD_* env vars with your parameters!
sudo systemd-run --unit collectd systemd-nspawn -D /tmp/collectd /bin/bash -c "COLLECTD_GRAPHITE_HOSTNAME=172.31.13.241 COLLECTD_LOCAL_HOSTNAME=node1 /bin/collectd-wrapper"

View File

@ -1,16 +0,0 @@
#!/bin/bash
cat /etc/collectd/collectd.conf.tmpl > /etc/collectd/collectd.conf
cat << EOF >> /etc/collectd/collectd.conf
Hostname "${COLLECTD_LOCAL_HOSTNAME}"
<Plugin write_graphite>
<Carbon>
Host "${COLLECTD_GRAPHITE_HOSTNAME}"
Port "2003"
</Carbon>
</Plugin>
EOF
collectd -C /etc/collectd/collectd.conf -f

View File

@ -1,898 +0,0 @@
# Config file for collectd(1).
#
# Some plugins need additional configuration and are disabled by default.
# Please read collectd.conf(5) for details.
#
# You should also read /usr/share/doc/collectd-core/README.Debian.plugins
# before enabling any more plugins.
#Hostname "localhost"
#FQDNLookup true
#BaseDir "/var/lib/collectd"
#PluginDir "/usr/lib/collectd"
#TypesDB "/usr/share/collectd/types.db" "/etc/collectd/my_types.db"
#Interval 10
#Timeout 2
#ReadThreads 5
LoadPlugin logfile
#LoadPlugin syslog
<Plugin logfile>
LogLevel "info"
File STDOUT
Timestamp true
PrintSeverity false
</Plugin>
#<Plugin syslog>
# LogLevel info
#</Plugin>
#LoadPlugin amqp
#LoadPlugin apache
#LoadPlugin apcups
#LoadPlugin ascent
#LoadPlugin battery
#LoadPlugin bind
#LoadPlugin conntrack
#LoadPlugin contextswitch
LoadPlugin cpu
#LoadPlugin cpufreq
#LoadPlugin csv
#LoadPlugin curl
#LoadPlugin curl_json
#LoadPlugin curl_xml
#LoadPlugin dbi
LoadPlugin df
#LoadPlugin disk
#LoadPlugin dns
#LoadPlugin email
#LoadPlugin entropy
#LoadPlugin ethstat
#LoadPlugin exec
#LoadPlugin filecount
#LoadPlugin fscache
#LoadPlugin gmond
#LoadPlugin hddtemp
#LoadPlugin interface
#LoadPlugin ipmi
#LoadPlugin iptables
#LoadPlugin ipvs
#LoadPlugin irq
#LoadPlugin java
#LoadPlugin libvirt
#LoadPlugin load
#LoadPlugin madwifi
#LoadPlugin mbmon
#LoadPlugin md
#LoadPlugin memcachec
#LoadPlugin memcached
LoadPlugin memory
#LoadPlugin multimeter
#LoadPlugin mysql
#LoadPlugin netlink
#LoadPlugin network
#LoadPlugin nfs
#LoadPlugin nginx
#LoadPlugin notify_desktop
#LoadPlugin notify_email
#LoadPlugin ntpd
#LoadPlugin numa
#LoadPlugin nut
#LoadPlugin olsrd
#LoadPlugin openvpn
#<LoadPlugin perl>
# Globals true
#</LoadPlugin>
#LoadPlugin pinba
#LoadPlugin ping
#LoadPlugin postgresql
#LoadPlugin powerdns
#LoadPlugin processes
#LoadPlugin protocols
#<LoadPlugin python>
# Globals true
#</LoadPlugin>
#LoadPlugin rrdcached
#LoadPlugin rrdtool
#LoadPlugin sensors
#LoadPlugin serial
#LoadPlugin snmp
#LoadPlugin swap
#LoadPlugin table
#LoadPlugin tail
LoadPlugin tcpconns
#LoadPlugin teamspeak2
#LoadPlugin ted
#LoadPlugin thermal
#LoadPlugin tokyotyrant
#LoadPlugin unixsock
#LoadPlugin uptime
#LoadPlugin users
#LoadPlugin uuid
#LoadPlugin varnish
#LoadPlugin vmem
#LoadPlugin vserver
#LoadPlugin wireless
LoadPlugin write_graphite
#LoadPlugin write_http
#LoadPlugin write_mongodb
#<Plugin amqp>
# <Publish "name">
# Host "localhost"
# Port "5672"
# VHost "/"
# User "guest"
# Password "guest"
# Exchange "amq.fanout"
# RoutingKey "collectd"
# Persistent false
# StoreRates false
# </Publish>
#</Plugin>
#<Plugin apache>
# <Instance "foo">
# URL "http://localhost/server-status?auto"
# User "www-user"
# Password "secret"
# VerifyPeer false
# VerifyHost false
# CACert "/etc/ssl/ca.crt"
# Server "apache"
# </Instance>
#
# <Instance "bar">
# URL "http://some.domain.tld/status?auto"
# Host "some.domain.tld"
# Server "lighttpd"
# </Instance>
#</Plugin>
#<Plugin apcups>
# Host "localhost"
# Port "3551"
#</Plugin>
#<Plugin ascent>
# URL "http://localhost/ascent/status/"
# User "www-user"
# Password "secret"
# VerifyPeer false
# VerifyHost false
# CACert "/etc/ssl/ca.crt"
#</Plugin>
#<Plugin "bind">
# URL "http://localhost:8053/"
#
# ParseTime false
#
# OpCodes true
# QTypes true
# ServerStats true
# ZoneMaintStats true
# ResolverStats false
# MemoryStats true
#
# <View "_default">
# QTypes true
# ResolverStats true
# CacheRRSets true
#
# Zone "127.in-addr.arpa/IN"
# </View>
#</Plugin>
#<Plugin csv>
# DataDir "/var/lib/collectd/csv"
# StoreRates false
#</Plugin>
#<Plugin curl>
# <Page "stock_quotes">
# URL "http://finance.google.com/finance?q=NYSE%3AAMD"
# User "foo"
# Password "bar"
# VerifyPeer false
# VerifyHost false
# CACert "/etc/ssl/ca.crt"
# MeasureResponseTime false
# <Match>
# Regex "<span +class=\"pr\"[^>]*> *([0-9]*\\.[0-9]+) *</span>"
# DSType "GaugeAverage"
# Type "stock_value"
# Instance "AMD"
# </Match>
# </Page>
#</Plugin>
#<Plugin curl_json>
## See: http://wiki.apache.org/couchdb/Runtime_Statistics
# <URL "http://localhost:5984/_stats">
# Instance "httpd"
# <Key "httpd/requests/count">
# Type "http_requests"
# </Key>
#
# <Key "httpd_request_methods/*/count">
# Type "http_request_methods"
# </Key>
#
# <Key "httpd_status_codes/*/count">
# Type "http_response_codes"
# </Key>
# </URL>
## Database status metrics:
# <URL "http://localhost:5984/_all_dbs">
# Instance "dbs"
# <Key "*/doc_count">
# Type "gauge"
# </Key>
# <Key "*/doc_del_count">
# Type "counter"
# </Key>
# <Key "*/disk_size">
# Type "bytes"
# </Key>
# </URL>
#</Plugin>
#<Plugin "curl_xml">
# <URL "http://localhost/stats.xml">
# Host "my_host"
# Instance "some_instance"
# User "collectd"
# Password "thaiNg0I"
# VerifyPeer true
# VerifyHost true
# CACert "/path/to/ca.crt"
#
# <XPath "table[@id=\"magic_level\"]/tr">
# Type "magic_level"
# InstancePrefix "prefix-"
# InstanceFrom "td[1]"
# ValuesFrom "td[2]/span[@class=\"level\"]"
# </XPath>
# </URL>
#</Plugin>
#<Plugin dbi>
# <Query "num_of_customers">
# Statement "SELECT 'customers' AS c_key, COUNT(*) AS c_value \
# FROM customers_tbl"
# MinVersion 40102
# MaxVersion 50042
# <Result>
# Type "gauge"
# InstancePrefix "customer"
# InstancesFrom "c_key"
# ValuesFrom "c_value"
# </Result>
# </Query>
#
# <Database "customers_db">
# Driver "mysql"
# DriverOption "host" "localhost"
# DriverOption "username" "collectd"
# DriverOption "password" "secret"
# DriverOption "dbname" "custdb0"
# SelectDB "custdb0"
# Query "num_of_customers"
# Query "..."
# </Database>
#</Plugin>
#<Plugin df>
# Device "/dev/sda1"
# Device "192.168.0.2:/mnt/nfs"
# MountPoint "/home"
# FSType "ext3"
# IgnoreSelected false
# ReportByDevice false
# ReportReserved false
# ReportInodes false
#</Plugin>
#<Plugin disk>
# Disk "hda"
# Disk "/sda[23]/"
# IgnoreSelected false
#</Plugin>
#<Plugin dns>
# Interface "eth0"
# IgnoreSource "192.168.0.1"
# SelectNumericQueryTypes false
#</Plugin>
#<Plugin email>
# SocketFile "/var/run/collectd-email"
# SocketGroup "collectd"
# SocketPerms "0770"
# MaxConns 5
#</Plugin>
#<Plugin ethstat>
# Interface "eth0"
# Map "rx_csum_offload_errors" "if_rx_errors" "checksum_offload"
# Map "multicast" "if_multicast"
# MappedOnly false
#</Plugin>
#<Plugin exec>
# Exec user "/path/to/exec"
# Exec "user:group" "/path/to/exec"
# NotificationExec user "/path/to/exec"
#</Plugin>
#<Plugin filecount>
# <Directory "/path/to/dir">
# Instance "foodir"
# Name "*.conf"
# MTime "-5m"
# Size "+10k"
# Recursive true
# IncludeHidden false
# </Directory>
#</Plugin>
#<Plugin gmond>
# MCReceiveFrom "239.2.11.71" "8649"
#
# <Metric "swap_total">
# Type "swap"
# TypeInstance "total"
# DataSource "value"
# </Metric>
#
# <Metric "swap_free">
# Type "swap"
# TypeInstance "free"
# DataSource "value"
# </Metric>
#</Plugin>
#<Plugin hddtemp>
# Host "127.0.0.1"
# Port 7634
#</Plugin>
#<Plugin interface>
# Interface "eth0"
# IgnoreSelected false
#</Plugin>
#<Plugin ipmi>
# Sensor "some_sensor"
# Sensor "another_one"
# IgnoreSelected false
# NotifySensorAdd false
# NotifySensorRemove true
# NotifySensorNotPresent false
#</Plugin>
#<Plugin iptables>
# Chain "table" "chain"
#</Plugin>
#<Plugin irq>
# Irq 7
# Irq 8
# Irq 9
# IgnoreSelected true
#</Plugin>
#<Plugin java>
# JVMArg "-verbose:jni"
# JVMArg "-Djava.class.path=/usr/share/collectd/java/collectd-api.jar"
#
# LoadPlugin "org.collectd.java.GenericJMX"
# <Plugin "GenericJMX">
# # See /usr/share/doc/collectd/examples/GenericJMX.conf
# # for an example config.
# </Plugin>
#</Plugin>
#<Plugin libvirt>
# Connection "xen:///"
# RefreshInterval 60
# Domain "name"
# BlockDevice "name:device"
# InterfaceDevice "name:device"
# IgnoreSelected false
# HostnameFormat name
# InterfaceFormat name
#</Plugin>
#<Plugin madwifi>
# Interface "wlan0"
# IgnoreSelected false
# Source "SysFS"
# WatchSet "None"
# WatchAdd "node_octets"
# WatchAdd "node_rssi"
# WatchAdd "is_rx_acl"
# WatchAdd "is_scan_active"
#</Plugin>
#<Plugin mbmon>
# Host "127.0.0.1"
# Port 411
#</Plugin>
#<Plugin md>
# Device "/dev/md0"
# IgnoreSelected false
#</Plugin>
#<Plugin memcachec>
# <Page "plugin_instance">
# Server "localhost"
# Key "page_key"
# <Match>
# Regex "(\\d+) bytes sent"
# ExcludeRegex "<lines to be excluded>"
# DSType CounterAdd
# Type "ipt_octets"
# Instance "type_instance"
# </Match>
# </Page>
#</Plugin>
#<Plugin memcached>
# Socket "/var/run/memcached.sock"
# or:
# Host "127.0.0.1"
# Port "11211"
#</Plugin>
#<Plugin mysql>
# <Database db_name>
# Host "database.serv.er"
# Port "3306"
# User "db_user"
# Password "secret"
# Database "db_name"
# MasterStats true
# </Database>
#
# <Database db_name2>
# Host "localhost"
# Socket "/var/run/mysql/mysqld.sock"
# SlaveStats true
# SlaveNotifications true
# </Database>
#</Plugin>
#<Plugin netlink>
# Interface "All"
# VerboseInterface "All"
# QDisc "eth0" "pfifo_fast-1:0"
# Class "ppp0" "htb-1:10"
# Filter "ppp0" "u32-1:0"
# IgnoreSelected false
#</Plugin>
#<Plugin network>
# # client setup:
# Server "ff18::efc0:4a42" "25826"
# <Server "239.192.74.66" "25826">
# SecurityLevel Encrypt
# Username "user"
# Password "secret"
# Interface "eth0"
# </Server>
# TimeToLive "128"
#
# # server setup:
# Listen "0.0.0.0" "25826"
# <Listen "239.192.74.66" "25826">
# SecurityLevel Sign
# AuthFile "/etc/collectd/passwd"
# Interface "eth0"
# </Listen>
# MaxPacketSize 1024
#
# # proxy setup (client and server as above):
# Forward true
#
# # statistics about the network plugin itself
# ReportStats false
#
# # "garbage collection"
# CacheFlush 1800
#</Plugin>
#<Plugin nginx>
# URL "http://localhost/status?auto"
# User "www-user"
# Password "secret"
# VerifyPeer false
# VerifyHost false
# CACert "/etc/ssl/ca.crt"
#</Plugin>
#<Plugin notify_desktop>
# OkayTimeout 1000
# WarningTimeout 5000
# FailureTimeout 0
#</Plugin>
#<Plugin notify_email>
# SMTPServer "localhost"
# SMTPPort 25
# SMTPUser "my-username"
# SMTPPassword "my-password"
# From "collectd@main0server.com"
# # <WARNING/FAILURE/OK> on <hostname>.
# # Beware! Do not use not more than two placeholders (%)!
# Subject "[collectd] %s on %s!"
# Recipient "email1@domain1.net"
# Recipient "email2@domain2.com"
#</Plugin>
#<Plugin ntpd>
# Host "localhost"
# Port 123
# ReverseLookups false
#</Plugin>
#<Plugin nut>
# UPS "upsname@hostname:port"
#</Plugin>
#<Plugin olsrd>
# Host "127.0.0.1"
# Port "2006"
# CollectLinks "Summary"
# CollectRoutes "Summary"
# CollectTopology "Summary"
#</Plugin>
#<Plugin openvpn>
# StatusFile "/etc/openvpn/openvpn-status.log"
# ImprovedNamingSchema false
# CollectCompression true
# CollectIndividualUsers true
# CollectUserCount false
#</Plugin>
#<Plugin perl>
# IncludeDir "/my/include/path"
# BaseName "Collectd::Plugins"
# EnableDebugger ""
# LoadPlugin Monitorus
# LoadPlugin OpenVZ
#
# <Plugin foo>
# Foo "Bar"
# Qux "Baz"
# </Plugin>
#</Plugin>
#<Plugin pinba>
# Address "::0"
# Port "30002"
# <View "name">
# Host "host name"
# Server "server name"
# Script "script name"
# <View>
#</Plugin>
#<Plugin ping>
# Host "host.foo.bar"
# Host "host.baz.qux"
# Interval 1.0
# Timeout 0.9
# TTL 255
# SourceAddress "1.2.3.4"
# Device "eth0"
# MaxMissed -1
#</Plugin>
#<Plugin postgresql>
# <Query magic>
# Statement "SELECT magic FROM wizard WHERE host = $1;"
# Param hostname
#
# <Result>
# Type gauge
# InstancePrefix "magic"
# ValuesFrom "magic"
# </Result>
# </Query>
#
# <Query rt36_tickets>
# Statement "SELECT COUNT(type) AS count, type \
# FROM (SELECT CASE \
# WHEN resolved = 'epoch' THEN 'open' \
# ELSE 'resolved' END AS type \
# FROM tickets) type \
# GROUP BY type;"
#
# <Result>
# Type counter
# InstancePrefix "rt36_tickets"
# InstancesFrom "type"
# ValuesFrom "count"
# </Result>
# </Query>
#
# <Database foo>
# Host "hostname"
# Port 5432
# User "username"
# Password "secret"
#
# SSLMode "prefer"
# KRBSrvName "kerberos_service_name"
#
# Query magic
# </Database>
#
# <Database bar>
# Interval 60
# Service "service_name"
#
# Query backend # predefined
# Query rt36_tickets
# </Database>
#</Plugin>
#<Plugin powerdns>
# <Server "server_name">
# Collect "latency"
# Collect "udp-answers" "udp-queries"
# Socket "/var/run/pdns.controlsocket"
# </Server>
# <Recursor "recursor_name">
# Collect "questions"
# Collect "cache-hits" "cache-misses"
# Socket "/var/run/pdns_recursor.controlsocket"
# </Recursor>
# LocalSocket "/opt/collectd/var/run/collectd-powerdns"
#</Plugin>
#<Plugin processes>
# Process "name"
# ProcessMatch "foobar" "/usr/bin/perl foobar\\.pl.*"
#</Plugin>
#<Plugin protocols>
# Value "/^Tcp:/"
# IgnoreSelected false
#</Plugin>
#<Plugin python>
# ModulePath "/path/to/your/python/modules"
# LogTraces true
# Interactive true
# Import "spam"
#
# <Module spam>
# spam "wonderful" "lovely"
# </Module>
#</Plugin>
#<Plugin rrdcached>
# DaemonAddress "unix:/var/run/rrdcached.sock"
# DataDir "/var/lib/rrdcached/db/collectd"
# CreateFiles true
# CollectStatistics true
#</Plugin>
<Plugin rrdtool>
DataDir "/var/lib/collectd/rrd"
# CacheTimeout 120
# CacheFlush 900
# WritesPerSecond 30
# RandomTimeout 0
#
# The following settings are rather advanced
# and should usually not be touched:
# StepSize 10
# HeartBeat 20
# RRARows 1200
# RRATimespan 158112000
# XFF 0.1
</Plugin>
#<Plugin sensors>
# SensorConfigFile "/etc/sensors3.conf"
# Sensor "it8712-isa-0290/temperature-temp1"
# Sensor "it8712-isa-0290/fanspeed-fan3"
# Sensor "it8712-isa-0290/voltage-in8"
# IgnoreSelected false
#</Plugin>
# See /usr/share/doc/collectd/examples/snmp-data.conf.gz for a
# comprehensive sample configuration.
#<Plugin snmp>
# <Data "powerplus_voltge_input">
# Type "voltage"
# Table false
# Instance "input_line1"
# Scale 0.1
# Values "SNMPv2-SMI::enterprises.6050.5.4.1.1.2.1"
# </Data>
# <Data "hr_users">
# Type "users"
# Table false
# Instance ""
# Shift -1
# Values "HOST-RESOURCES-MIB::hrSystemNumUsers.0"
# </Data>
# <Data "std_traffic">
# Type "if_octets"
# Table true
# InstancePrefix "traffic"
# Instance "IF-MIB::ifDescr"
# Values "IF-MIB::ifInOctets" "IF-MIB::ifOutOctets"
# </Data>
#
# <Host "some.switch.mydomain.org">
# Address "192.168.0.2"
# Version 1
# Community "community_string"
# Collect "std_traffic"
# Inverval 120
# </Host>
# <Host "some.server.mydomain.org">
# Address "192.168.0.42"
# Version 2
# Community "another_string"
# Collect "std_traffic" "hr_users"
# </Host>
# <Host "some.ups.mydomain.org">
# Address "192.168.0.3"
# Version 1
# Community "more_communities"
# Collect "powerplus_voltge_input"
# Interval 300
# </Host>
#</Plugin>
#<Plugin swap>
# ReportByDevice false
#</Plugin>
#<Plugin table>
# <Table "/proc/slabinfo">
# Instance "slabinfo"
# Separator " "
# <Result>
# Type gauge
# InstancePrefix "active_objs"
# InstancesFrom 0
# ValuesFrom 1
# </Result>
# <Result>
# Type gauge
# InstancePrefix "objperslab"
# InstancesFrom 0
# ValuesFrom 4
# </Result>
# </Table>
#</Plugin>
#<Plugin "tail">
# <File "/var/log/exim4/mainlog">
# Instance "exim"
# <Match>
# Regex "S=([1-9][0-9]*)"
# DSType "CounterAdd"
# Type "ipt_bytes"
# Instance "total"
# </Match>
# <Match>
# Regex "\\<R=local_user\\>"
# ExcludeRegex "\\<R=local_user\\>.*mail_spool defer"
# DSType "CounterInc"
# Type "counter"
# Instance "local_user"
# </Match>
# </File>
#</Plugin>
<Plugin tcpconns>
LocalPort "4001"
LocalPort "7001"
</Plugin>
#<Plugin teamspeak2>
# Host "127.0.0.1"
# Port "51234"
# Server "8767"
#</Plugin>
#<Plugin ted>
# Device "/dev/ttyUSB0"
# Retries 0
#</Plugin>
#<Plugin thermal>
# ForceUseProcfs false
# Device "THRM"
# IgnoreSelected false
#</Plugin>
#<Plugin tokyotyrant>
# Host "localhost"
# Port "1978"
#</Plugin>
#<Plugin unixsock>
# SocketFile "/var/run/collectd-unixsock"
# SocketGroup "collectd"
# SocketPerms "0660"
# DeleteSocket false
#</Plugin>
#<Plugin uuid>
# UUIDFile "/etc/uuid"
#</Plugin>
#<Plugin varnish>
# <Instance>
# CollectCache true
# CollectBackend true
# CollectConnections true
# CollectSHM true
# CollectESI false
# CollectFetch false
# CollectHCB false
# CollectSMA false
# CollectSMS false
# CollectSM false
# CollectTotals false
# CollectWorkers false
# </Instance>
#
# <Instance "myinstance">
# CollectCache true
# </Instance>
#</Plugin>
#<Plugin vmem>
# Verbose false
#</Plugin>
#<Plugin write_graphite>
# <Carbon>
# Host "127.0.01"
# Port "2003"
# Prefix "collectd"
# Postfix "collectd"
# StoreRates false
# AlwaysAppendDS false
# EscapeCharacter "_"
# </Carbon>
#</Plugin>
#<Plugin write_http>
# <URL "http://example.com/collectd-post">
# User "collectd"
# Password "secret"
# VerifyPeer true
# VerifyHost true
# CACert "/etc/ssl/ca.crt"
# Format "Command"
# StoreRates false
# </URL>
#</Plugin>
#<Plugin write_mongodb>
# <Node "example">
# Host "localhost"
# Port "27017"
# Timeout 1000
# StoreRates false
# <Node>
#</Plugin>
Include "/etc/collectd/filters.conf"
Include "/etc/collectd/thresholds.conf"

View File

@ -1,31 +0,0 @@
from stackbrew/ubuntu:precise
run echo 'deb http://us.archive.ubuntu.com/ubuntu/ precise universe' >> /etc/apt/sources.list
run apt-get -y update
# Install required packages
run apt-get -y install python-cairo python-django python-twisted python-django-tagging python-simplejson python-pysqlite2 python-support python-pip gunicorn supervisor nginx-light
run pip install whisper
run pip install --install-option="--prefix=/var/lib/graphite" --install-option="--install-lib=/var/lib/graphite/lib" carbon
run pip install --install-option="--prefix=/var/lib/graphite" --install-option="--install-lib=/var/lib/graphite/webapp" graphite-web
# Add system service config
add ./nginx.conf /etc/nginx/nginx.conf
add ./supervisord.conf /etc/supervisor/conf.d/supervisord.conf
# Add graphite config
add ./initial_data.json /var/lib/graphite/webapp/graphite/initial_data.json
add ./local_settings.py /var/lib/graphite/webapp/graphite/local_settings.py
add ./carbon.conf /var/lib/graphite/conf/carbon.conf
add ./storage-schemas.conf /var/lib/graphite/conf/storage-schemas.conf
run mkdir -p /var/lib/graphite/storage/whisper
run touch /var/lib/graphite/storage/graphite.db /var/lib/graphite/storage/index
run chown -R www-data /var/lib/graphite/storage
run chmod 0775 /var/lib/graphite/storage /var/lib/graphite/storage/whisper
run chmod 0664 /var/lib/graphite/storage/graphite.db
run cd /var/lib/graphite/webapp/graphite && python manage.py syncdb --noinput
expose :80
expose :2003
cmd ["/usr/bin/supervisord"]

View File

@ -1,7 +0,0 @@
Running graphite under Docker is straightforward:
1. Build the graphite image using Docker
docker build -t graphite .
2. Run a graphite container. Be sure to replace the $IP field with the IP address at which you wish to expose your graphite web service.
docker run -p $IP:8080:80 -p $IP:2003:2003 -d graphite

View File

@ -1,62 +0,0 @@
[cache]
LOCAL_DATA_DIR = /var/lib/graphite/storage/whisper/
# Specify the user to drop privileges to
# If this is blank carbon runs as the user that invokes it
# This user must have write access to the local data directory
USER =
# Limit the size of the cache to avoid swapping or becoming CPU bound.
# Sorts and serving cache queries gets more expensive as the cache grows.
# Use the value "inf" (infinity) for an unlimited cache size.
MAX_CACHE_SIZE = inf
# Limits the number of whisper update_many() calls per second, which effectively
# means the number of write requests sent to the disk. This is intended to
# prevent over-utilizing the disk and thus starving the rest of the system.
# When the rate of required updates exceeds this, then carbon's caching will
# take effect and increase the overall throughput accordingly.
MAX_UPDATES_PER_SECOND = 1000
# Softly limits the number of whisper files that get created each minute.
# Setting this value low (like at 50) is a good way to ensure your graphite
# system will not be adversely impacted when a bunch of new metrics are
# sent to it. The trade off is that it will take much longer for those metrics'
# database files to all get created and thus longer until the data becomes usable.
# Setting this value high (like "inf" for infinity) will cause graphite to create
# the files quickly but at the risk of slowing I/O down considerably for a while.
MAX_CREATES_PER_MINUTE = inf
LINE_RECEIVER_INTERFACE = 0.0.0.0
LINE_RECEIVER_PORT = 2003
#PICKLE_RECEIVER_INTERFACE = 0.0.0.0
#PICKLE_RECEIVER_PORT = 2004
#CACHE_QUERY_INTERFACE = 0.0.0.0
#CACHE_QUERY_PORT = 7002
LOG_UPDATES = False
# Enable AMQP if you want to receve metrics using an amqp broker
# ENABLE_AMQP = False
# Verbose means a line will be logged for every metric received
# useful for testing
# AMQP_VERBOSE = False
# AMQP_HOST = localhost
# AMQP_PORT = 5672
# AMQP_VHOST = /
# AMQP_USER = guest
# AMQP_PASSWORD = guest
# AMQP_EXCHANGE = graphite
# Patterns for all of the metrics this machine will store. Read more at
# http://en.wikipedia.org/wiki/Advanced_Message_Queuing_Protocol#Bindings
#
# Example: store all sales, linux servers, and utilization metrics
# BIND_PATTERNS = sales.#, servers.linux.#, #.utilization
#
# Example: store everything
# BIND_PATTERNS = #

View File

@ -1,20 +0,0 @@
[
{
"pk": 1,
"model": "auth.user",
"fields": {
"username": "admin",
"first_name": "",
"last_name": "",
"is_active": true,
"is_superuser": true,
"is_staff": true,
"last_login": "2011-09-20 17:02:14",
"groups": [],
"user_permissions": [],
"password": "sha1$1b11b$edeb0a67a9622f1f2cfeabf9188a711f5ac7d236",
"email": "root@example.com",
"date_joined": "2011-09-20 17:02:14"
}
}
]

View File

@ -1 +0,0 @@
TIME_ZONE = 'UTC'

View File

@ -1,69 +0,0 @@
daemon off;
user www-data;
worker_processes 1;
pid /var/run/nginx.pid;
events {
worker_connections 1024;
}
http {
sendfile on;
tcp_nopush on;
tcp_nodelay on;
keepalive_timeout 65;
types_hash_max_size 2048;
server_tokens off;
server_names_hash_bucket_size 32;
include /etc/nginx/mime.types;
default_type application/octet-stream;
access_log /var/log/nginx/access.log;
error_log /var/log/nginx/error.log;
gzip on;
gzip_disable "msie6";
server {
listen 80 default_server;
server_name _;
open_log_file_cache max=1000 inactive=20s min_uses=2 valid=1m;
location / {
proxy_pass http://127.0.0.1:8000;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
proxy_set_header X-Forwarded-Server $host;
proxy_set_header X-Forwarded-Host $host;
proxy_set_header Host $host;
client_max_body_size 10m;
client_body_buffer_size 128k;
proxy_connect_timeout 90;
proxy_send_timeout 90;
proxy_read_timeout 90;
proxy_buffer_size 4k;
proxy_buffers 4 32k;
proxy_busy_buffers_size 64k;
proxy_temp_file_write_size 64k;
}
add_header Access-Control-Allow-Origin "*";
add_header Access-Control-Allow-Methods "GET, OPTIONS";
add_header Access-Control-Allow-Headers "origin, authorization, accept";
location /content {
alias /var/lib/graphite/webapp/content;
}
location /media {
alias /usr/share/pyshared/django/contrib/admin/media;
}
}
}

View File

@ -1,7 +0,0 @@
[carbon]
pattern = ^carbon\..*
retentions = 1m:31d,10m:1y,1h:5y
[default]
pattern = .*
retentions = 10s:8d,1m:31d,10m:1y,1h:5y

View File

@ -1,25 +0,0 @@
[supervisord]
nodaemon = true
environment = GRAPHITE_STORAGE_DIR='/var/lib/graphite/storage',GRAPHITE_CONF_DIR='/var/lib/graphite/conf'
[program:nginx]
command = /usr/sbin/nginx
stdout_logfile = /var/log/supervisor/%(program_name)s.log
stderr_logfile = /var/log/supervisor/%(program_name)s.log
autorestart = true
[program:carbon-cache]
user = www-data
command = /var/lib/graphite/bin/carbon-cache.py --debug start
stdout_logfile = /var/log/supervisor/%(program_name)s.log
stderr_logfile = /var/log/supervisor/%(program_name)s.log
autorestart = true
[program:graphite-webapp]
user = www-data
directory = /var/lib/graphite/webapp
environment = PYTHONPATH='/var/lib/graphite/webapp'
command = /usr/bin/gunicorn_django -b127.0.0.1:8000 -w2 graphite/settings.py
stdout_logfile = /var/log/supervisor/%(program_name)s.log
stderr_logfile = /var/log/supervisor/%(program_name)s.log
autorestart = true

View File

@ -1,145 +0,0 @@
package discovery
import (
"errors"
"fmt"
"net/url"
"path"
"strings"
"time"
etcdErr "github.com/coreos/etcd/error"
"github.com/coreos/etcd/log"
"github.com/coreos/etcd/third_party/github.com/coreos/go-etcd/etcd"
)
const (
stateKey = "_state"
startedState = "started"
defaultTTL = 604800 // One week TTL
)
type Discoverer struct {
client *etcd.Client
name string
peer string
prefix string
discoveryURL string
}
var defaultDiscoverer *Discoverer
func init() {
defaultDiscoverer = &Discoverer{}
}
func (d *Discoverer) Do(discoveryURL string, name string, peer string) (peers []string, err error) {
d.name = name
d.peer = peer
d.discoveryURL = discoveryURL
u, err := url.Parse(discoveryURL)
if err != nil {
return
}
// prefix is prepended to all keys for this discovery
d.prefix = strings.TrimPrefix(u.Path, "/v2/keys/")
// keep the old path in case we need to set the KeyPrefix below
oldPath := u.Path
u.Path = ""
// Connect to a scheme://host not a full URL with path
log.Infof("Discovery via %s using prefix %s.", u.String(), d.prefix)
d.client = etcd.NewClient([]string{u.String()})
if !strings.HasPrefix(oldPath, "/v2/keys") {
d.client.SetKeyPrefix("")
}
// Register this machine first and announce that we are a member of
// this cluster
err = d.heartbeat()
if err != nil {
return
}
// Start the very slow heartbeat to the cluster now in anticipation
// that everything is going to go alright now
go d.startHeartbeat()
// Attempt to take the leadership role, if there is no error we are it!
resp, err := d.client.Create(path.Join(d.prefix, stateKey), startedState, 0)
// Bail out on unexpected errors
if err != nil {
if clientErr, ok := err.(*etcd.EtcdError); !ok || clientErr.ErrorCode != etcdErr.EcodeNodeExist {
return nil, err
}
}
// If we got a response then the CAS was successful, we are leader
if resp != nil && resp.Node.Value == startedState {
// We are the leader, we have no peers
log.Infof("Discovery _state was empty, so this machine is the initial leader.")
return nil, nil
}
// Fall through to finding the other discovery peers
return d.findPeers()
}
func (d *Discoverer) findPeers() (peers []string, err error) {
resp, err := d.client.Get(path.Join(d.prefix), false, true)
if err != nil {
return nil, err
}
node := resp.Node
if node == nil {
return nil, fmt.Errorf("%s key doesn't exist.", d.prefix)
}
for _, n := range node.Nodes {
// Skip our own entry in the list, there is no point
if strings.HasSuffix(n.Key, "/"+d.name) {
continue
}
peers = append(peers, n.Value)
}
if len(peers) == 0 {
return nil, errors.New("Discovery found an initialized cluster but no peers are registered.")
}
log.Infof("Discovery found peers %v", peers)
return
}
func (d *Discoverer) startHeartbeat() {
// In case of errors we should attempt to heartbeat fairly frequently
heartbeatInterval := defaultTTL / 8
ticker := time.Tick(time.Second * time.Duration(heartbeatInterval))
for {
select {
case <-ticker:
err := d.heartbeat()
if err != nil {
log.Warnf("Discovery heartbeat failed: %v", err)
}
}
}
}
func (d *Discoverer) heartbeat() error {
_, err := d.client.Set(path.Join(d.prefix, d.name), d.peer, defaultTTL)
return err
}
func Do(discoveryURL string, name string, peer string) ([]string, error) {
return defaultDiscoverer.Do(discoveryURL, name, peer)
}

View File

@ -1,139 +0,0 @@
/*
Copyright 2013 CoreOS Inc.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
package error
import (
"encoding/json"
"fmt"
"net/http"
)
var errors map[int]string
const (
EcodeKeyNotFound = 100
EcodeTestFailed = 101
EcodeNotFile = 102
EcodeNoMorePeer = 103
EcodeNotDir = 104
EcodeNodeExist = 105
EcodeKeyIsPreserved = 106
EcodeRootROnly = 107
EcodeDirNotEmpty = 108
EcodeValueRequired = 200
EcodePrevValueRequired = 201
EcodeTTLNaN = 202
EcodeIndexNaN = 203
EcodeValueOrTTLRequired = 204
EcodeTimeoutNaN = 205
EcodeNameRequired = 206
EcodeIndexOrValueRequired = 207
EcodeIndexValueMutex = 208
EcodeInvalidField = 209
EcodeRaftInternal = 300
EcodeLeaderElect = 301
EcodeWatcherCleared = 400
EcodeEventIndexCleared = 401
)
func init() {
errors = make(map[int]string)
// command related errors
errors[EcodeKeyNotFound] = "Key not found"
errors[EcodeTestFailed] = "Compare failed" //test and set
errors[EcodeNotFile] = "Not a file"
errors[EcodeNoMorePeer] = "Reached the max number of peers in the cluster"
errors[EcodeNotDir] = "Not a directory"
errors[EcodeNodeExist] = "Key already exists" // create
errors[EcodeRootROnly] = "Root is read only"
errors[EcodeKeyIsPreserved] = "The prefix of given key is a keyword in etcd"
errors[EcodeDirNotEmpty] = "Directory not empty"
// Post form related errors
errors[EcodeValueRequired] = "Value is Required in POST form"
errors[EcodePrevValueRequired] = "PrevValue is Required in POST form"
errors[EcodeTTLNaN] = "The given TTL in POST form is not a number"
errors[EcodeIndexNaN] = "The given index in POST form is not a number"
errors[EcodeValueOrTTLRequired] = "Value or TTL is required in POST form"
errors[EcodeTimeoutNaN] = "The given timeout in POST form is not a number"
errors[EcodeNameRequired] = "Name is required in POST form"
errors[EcodeIndexOrValueRequired] = "Index or value is required"
errors[EcodeIndexValueMutex] = "Index and value cannot both be specified"
errors[EcodeInvalidField] = "Invalid field"
// raft related errors
errors[EcodeRaftInternal] = "Raft Internal Error"
errors[EcodeLeaderElect] = "During Leader Election"
// etcd related errors
errors[EcodeWatcherCleared] = "watcher is cleared due to etcd recovery"
errors[EcodeEventIndexCleared] = "The event in requested index is outdated and cleared"
}
type Error struct {
ErrorCode int `json:"errorCode"`
Message string `json:"message"`
Cause string `json:"cause,omitempty"`
Index uint64 `json:"index"`
}
func NewError(errorCode int, cause string, index uint64) *Error {
return &Error{
ErrorCode: errorCode,
Message: errors[errorCode],
Cause: cause,
Index: index,
}
}
func Message(code int) string {
return errors[code]
}
// Only for error interface
func (e Error) Error() string {
return e.Message
}
func (e Error) toJsonString() string {
b, _ := json.Marshal(e)
return string(b)
}
func (e Error) Write(w http.ResponseWriter) {
w.Header().Add("X-Etcd-Index", fmt.Sprint(e.Index))
// 3xx is raft internal error
status := http.StatusBadRequest
switch e.ErrorCode {
case EcodeKeyNotFound:
status = http.StatusNotFound
case EcodeNotFile, EcodeDirNotEmpty:
status = http.StatusForbidden
case EcodeTestFailed, EcodeNodeExist:
status = http.StatusPreconditionFailed
default:
if e.ErrorCode/100 == 3 {
status = http.StatusInternalServerError
}
}
http.Error(w, e.toJsonString(), status)
}

201
3rdParty/etcd/etcd.go vendored
View File

@ -1,201 +0,0 @@
/*
Copyright 2013 CoreOS Inc.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
package main
import (
"fmt"
"net"
"net/http"
"os"
"path/filepath"
"runtime"
"time"
"github.com/coreos/etcd/third_party/github.com/coreos/raft"
"github.com/coreos/etcd/config"
ehttp "github.com/coreos/etcd/http"
"github.com/coreos/etcd/log"
"github.com/coreos/etcd/metrics"
"github.com/coreos/etcd/server"
"github.com/coreos/etcd/store"
)
func main() {
// Load configuration.
var config = config.New()
if err := config.Load(os.Args[1:]); err != nil {
fmt.Println(server.Usage() + "\n")
fmt.Println(err.Error() + "\n")
os.Exit(1)
} else if config.ShowVersion {
fmt.Println(server.ReleaseVersion)
os.Exit(0)
} else if config.ShowHelp {
fmt.Println(server.Usage() + "\n")
os.Exit(0)
}
// Enable options.
if config.VeryVeryVerbose {
log.Verbose = true
raft.SetLogLevel(raft.Trace)
} else if config.VeryVerbose {
log.Verbose = true
raft.SetLogLevel(raft.Debug)
} else if config.Verbose {
log.Verbose = true
}
if config.CPUProfileFile != "" {
profile(config.CPUProfileFile)
}
if config.DataDir == "" {
log.Fatal("The data dir was not set and could not be guessed from machine name")
}
// 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)
}
// Warn people if they have an info file
info := filepath.Join(config.DataDir, "info")
if _, err := os.Stat(info); err == nil {
log.Warnf("All cached configuration is now ignored. The file %s can be removed.", info)
}
var mbName string
if config.Trace() {
mbName = config.MetricsBucketName()
runtime.SetBlockProfileRate(1)
}
mb := metrics.NewBucket(mbName)
if config.GraphiteHost != "" {
err := mb.Publish(config.GraphiteHost)
if err != nil {
panic(err)
}
}
// Retrieve CORS configuration
corsInfo, err := ehttp.NewCORSInfo(config.CorsOrigins)
if err != nil {
log.Fatal("CORS:", err)
}
// Create etcd key-value store and registry.
store := store.New()
registry := server.NewRegistry(store)
// Create stats objects
followersStats := server.NewRaftFollowersStats(config.Name)
serverStats := server.NewRaftServerStats(config.Name)
// Calculate all of our timeouts
heartbeatTimeout := time.Duration(config.Peer.HeartbeatTimeout) * time.Millisecond
electionTimeout := time.Duration(config.Peer.ElectionTimeout) * time.Millisecond
dialTimeout := (3 * heartbeatTimeout) + electionTimeout
responseHeaderTimeout := (3 * heartbeatTimeout) + electionTimeout
// Create peer server
psConfig := server.PeerServerConfig{
Name: config.Name,
Scheme: config.PeerTLSInfo().Scheme(),
URL: config.Peer.Addr,
SnapshotCount: config.SnapshotCount,
MaxClusterSize: config.MaxClusterSize,
RetryTimes: config.MaxRetryAttempts,
RetryInterval: config.RetryInterval,
}
ps := server.NewPeerServer(psConfig, registry, store, &mb, followersStats, serverStats)
var psListener net.Listener
if psConfig.Scheme == "https" {
peerServerTLSConfig, err := config.PeerTLSInfo().ServerConfig()
if err != nil {
log.Fatal("peer server TLS error: ", err)
}
psListener, err = server.NewTLSListener(config.Peer.BindAddr, peerServerTLSConfig)
if err != nil {
log.Fatal("Failed to create peer listener: ", err)
}
} else {
psListener, err = server.NewListener(config.Peer.BindAddr)
if err != nil {
log.Fatal("Failed to create peer listener: ", err)
}
}
// Create raft transporter and server
raftTransporter := server.NewTransporter(followersStats, serverStats, registry, heartbeatTimeout, dialTimeout, responseHeaderTimeout)
if psConfig.Scheme == "https" {
raftClientTLSConfig, err := config.PeerTLSInfo().ClientConfig()
if err != nil {
log.Fatal("raft client TLS error: ", err)
}
raftTransporter.SetTLSConfig(*raftClientTLSConfig)
}
raftServer, err := raft.NewServer(config.Name, config.DataDir, raftTransporter, store, ps, "")
if err != nil {
log.Fatal(err)
}
raftServer.SetElectionTimeout(electionTimeout)
raftServer.SetHeartbeatInterval(heartbeatTimeout)
ps.SetRaftServer(raftServer)
// Create etcd server
s := server.New(config.Name, config.Addr, ps, registry, store, &mb)
if config.Trace() {
s.EnableTracing()
}
var sListener net.Listener
if config.EtcdTLSInfo().Scheme() == "https" {
etcdServerTLSConfig, err := config.EtcdTLSInfo().ServerConfig()
if err != nil {
log.Fatal("etcd TLS error: ", err)
}
sListener, err = server.NewTLSListener(config.BindAddr, etcdServerTLSConfig)
if err != nil {
log.Fatal("Failed to create TLS etcd listener: ", err)
}
} else {
sListener, err = server.NewListener(config.BindAddr)
if err != nil {
log.Fatal("Failed to create etcd listener: ", err)
}
}
ps.SetServer(s)
ps.Start(config.Snapshot, config.Peers)
go func() {
log.Infof("peer server [name %s, listen on %s, advertised url %s]", ps.Config.Name, psListener.Addr(), ps.Config.URL)
sHTTP := &ehttp.CORSHandler{ps.HTTPHandler(), corsInfo}
log.Fatal(http.Serve(psListener, sHTTP))
}()
log.Infof("etcd server [name %s, listen on %s, advertised url %s]", s.Name, sListener.Addr(), s.URL())
sHTTP := &ehttp.CORSHandler{s.HTTPHandler(), corsInfo}
log.Fatal(http.Serve(sListener, sHTTP))
}

View File

@ -1 +0,0 @@
* -text

View File

@ -1,21 +0,0 @@
Testing x509 certs for etcd
The passphrases for the keys are `asdf`.
# Make the CA cert
openssl genrsa -des3 -out ca.key 4096
openssl req -new -x509 -days 365 -key ca.key -out ca.crt -config openssl.cnf -extensions v3_ca
# Make server cert and signing request
openssl genrsa -des3 -out server.key 4096
openssl req -new -key server.key -out server.csr -config openssl.cnf
# Sign the server csr and generate a crt
openssl x509 -req -days 365 -in server.csr -CA ca.crt -CAkey ca.key -set_serial 01 -out server.crt -extfile openssl.cnf -extensions v3_req
# Output unencrypted server key
openssl rsa -in server.key -out server.key.insecure
# Output "raw" public key from server crt
openssl x509 -pubkey -noout -in server.crt > server.pub

View File

@ -1,21 +0,0 @@
## Testing x509 certs for luvit
# Make the CA cert
openssl genrsa -out ca.key 4096
openssl req -new -x509 -days 365 -key ca.key -out ca.crt
# Make server cert and signing request
openssl genrsa -out server.key 4096
openssl req -new -key server.key -out server.csr
# Sign the server csr and generate a crt
openssl x509 -req -days 365 -in server.csr -CA ca.crt -CAkey ca.key -set_serial 01 -out server.crt
# Output unencrypted server key
openssl rsa -in server.key -out server.key.insecure
# Output "raw" public key from server crt
openssl x509 -pubkey -noout -in server.crt > server.pub
# Sign the public key with the key (just for testing signatures)
openssl dgst -sign server.key.insecure -sha256 server.pub > server.pub.sig

View File

@ -1,33 +0,0 @@
-----BEGIN CERTIFICATE-----
MIIFtTCCA52gAwIBAgIJANfWYo0ePBBqMA0GCSqGSIb3DQEBBQUAMEUxCzAJBgNV
BAYTAkFVMRMwEQYDVQQIEwpTb21lLVN0YXRlMSEwHwYDVQQKExhJbnRlcm5ldCBX
aWRnaXRzIFB0eSBMdGQwHhcNMTIwMzE1MjMxMzMwWhcNMTMwMzE1MjMxMzMwWjBF
MQswCQYDVQQGEwJBVTETMBEGA1UECBMKU29tZS1TdGF0ZTEhMB8GA1UEChMYSW50
ZXJuZXQgV2lkZ2l0cyBQdHkgTHRkMIICIjANBgkqhkiG9w0BAQEFAAOCAg8AMIIC
CgKCAgEAyzBV/DH0PWmPxdnr3BTogxPYKVJQ4OQjiiALRRtYPjvQYKPWWsbt4Zlw
kfYsc6ihIKUL1tGEnjD6YDTtTwWH7DXeq0mWebFr3kQg/ssoTM5oHN9VglwPMRnx
7qqbBG0/LO/K2Go/UMFGmWHiRYRWcOYegq6DXJpj1sRJz8o3uk4Fxz/xr1sjng1l
EfAfE4segFLRhmXy1e6Ooy2U5WcpDeKGrD1O01DKsYdR+RavcgkmFYfZ5rdtaKrE
wpYLylJNmOAkss7w5tOyEEDLoZHtkRFX5Ss38wuU2h9Li8P9vhyL4Ylzcuy/pBXW
MA89D8bBXjR3G4Hk7qX7gqlI9GdRXtPqnRpgEy/vw/+6aJVfNJtLIRdabSr3vStL
rhF1y4ocr8OJdNjHGp8tssc9I0LhhItT7bWgjQLHTRezVXV5kzpggAlDCQc48bdc
aYjBoLuu8jH9mgGCnPtrJMyV+T96rV5V4XJieA9k4IQ3nWJk1Nslqm5S/FSQbM32
+ineL0ZlT/x8qXNnL3FHQFDOKCng3Ww6wC7M9BDf9+Di04lNtd37pri/i5dcvsn1
WaYzvHpSGom234Bl4NQSoupKlEhfgTc5w/uuhbGSWcsH+wB4Yi7dg5U7voNkwtVo
loEaZ58ldd4Dkz16lZSSg4wzwDbMQWpGCPRAfVDAVk/AxpfOiOsCAwEAAaOBpzCB
pDAdBgNVHQ4EFgQUpahFGYUWGD8RygULRRlo6TlAkxowdQYDVR0jBG4wbIAUpahF
GYUWGD8RygULRRlo6TlAkxqhSaRHMEUxCzAJBgNVBAYTAkFVMRMwEQYDVQQIEwpT
b21lLVN0YXRlMSEwHwYDVQQKExhJbnRlcm5ldCBXaWRnaXRzIFB0eSBMdGSCCQDX
1mKNHjwQajAMBgNVHRMEBTADAQH/MA0GCSqGSIb3DQEBBQUAA4ICAQAvdXT3GIjK
diHYGurJKSGhja8nVcZ9vm0SICyMQU3nOaMhNdrFXUP21dqO1xP+uqgc7vHGOyPg
MNLvamCY7JtmcLEgByG5Z+aeNESdwGjP4Rl4YRB83JUyOHke0cONiJXYTjGwF7FL
vCXjJm/3t5rTj+gPPMkcN3FtYpiVUn2Ra5LURCiRucsqnStEKiLeIM3WluKOFssZ
AHGkUEGXpYyuobdBvejCqdc02+ywyqGuV05mOHB7dDAt0eS0tUqaEyoKlWgIuVlN
770LJGjQkQqa0oYwrbsgKuPjH4zu7MDjzooZsYkEpgPCaK64HQ03mdWYWiqW3KY5
JxT4TdOwSXQfvmeLbT/By1Qo0m9R2Sqb4Q0t3VDILyJmvTr4dLCRjAMfDaADxiPI
58cXUeT5kLbF2kHQ8GZIFXpWQRhX5Go0sETlv35HtL9szNK/p2ngob6XkbxJf8rC
ygP96Xa09J94CPrJF34slRM3hsdf/t92ytG8HTOf+42QjT60zgApibVVXwEYwx2S
M/1FZbt9xR2nfvrKBZG4luyPuIVbAI3VbtgfP2ywIxQI7OkBQec52Ck2e4AvZk9q
PUgxRqZbzpQSdEr3U3bhEtKf/Yq3Lgx/4Luo11BlZkWRKViBpK1yTUe1C4UkFo5Z
gZO0oCwwO5YWxTCA1xCJDJeSuz16snOXpw==
-----END CERTIFICATE-----

View File

@ -1,51 +0,0 @@
-----BEGIN RSA PRIVATE KEY-----
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
-----END RSA PRIVATE KEY-----

View File

@ -1,29 +0,0 @@
-----BEGIN CERTIFICATE-----
MIIE/jCCAuYCAQEwDQYJKoZIhvcNAQEFBQAwRTELMAkGA1UEBhMCQVUxEzARBgNV
BAgTClNvbWUtU3RhdGUxITAfBgNVBAoTGEludGVybmV0IFdpZGdpdHMgUHR5IEx0
ZDAeFw0xMjAzMTUyMzEzNDZaFw0xMzAzMTUyMzEzNDZaMEUxCzAJBgNVBAYTAkFV
MRMwEQYDVQQIEwpTb21lLVN0YXRlMSEwHwYDVQQKExhJbnRlcm5ldCBXaWRnaXRz
IFB0eSBMdGQwggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQDOwQ+StykH
YPBXIQPgD+ZqU4RBgbwpT94p9Fvf5/OZIenI2Ujv9wCEeRbwdtbKj+RlvcM8BX2I
27MNp0dd5G9+dLizKbDgigjDRJXVNk4d9RPd7r/51jBT3WIkkI+4qkbTMjqfhkJn
iBQZisAajucaO02F6FGxdqlFcU/l92CG12MRbvmNqmJ9odWniylKHwAfV1jSbnQS
ckvtsxAc9bCNm3mDrjAwZlZCaHWEy0sq3VoBA7y1IWxOSg7aXR5t6NHEMs61ARfQ
/bdGR4ww4haGVdflS68oSZtOa9TJytv0BaMnIFLkFDvEpq39KXjP0yrSGqJQC5cA
3yh3uJQxUcZ9A2rPRR7LoS6ZVEk+4OWRP0kPW6FILDRiHMOlj0jeMmfLzLGLW/NW
WBPBAG6pwNJaO1Y4LLHZRUJE3dM70v/lNMmB/T1S3kJ7TX+pluTgdCKo2qjxvnQI
A0CnQeeQSV7TiefuIixXwAGGdg7dZO0MSkX8NASPiS/B3KWP4pSDDEzsRmz4UqRG
0tnkFRfCKHtkBPJ7OWdHapgXnlUBImQWO2MStPenmZBzuVcCkv52QwuFC8g/EKlr
tvzRl11Ajgg9LZApI0BaOtXE/LGkBpPpXNh0Pi10ETniPhvfZhX/RYb4g6WeVGsx
oD6V9vHrD1Psp4u+QKZRldsD0d1aRvXvzwIDAQABMA0GCSqGSIb3DQEBBQUAA4IC
AQCAzJrMHAIZVPupdJiiooCHvLc3M/4wn02Wws/NgvkIO3mNs+9uZvJ/IsLSOS/0
x9gIVIXscoT0y/RRCg9IUwCGmCp9XkfL0MzBNPfhOXZ2/SXLGv2ubBTv7nyXAeF9
Oh719bbir+vmEKoMXej0LBQ3qGT6zS8Zs2iKGj1bXZjZXiTt67YkYZgr65uZTYW4
XtywTnJ+vUg9Mp6fReXgOWDlM8BiJ6JKnRn9f5Y66INSePV4NvtcIrqNNvrBEDqX
LOWuh1Vs32gOySF8A1jM/GdSCdV1Wsng5HxGMMuGAKnw35YguW598Fk8LLfE8w5V
x9Gth2RdxvimMu+qsNMq0mc78C1yPDSfRXC51t8J8d5+hke/apb6KfB/47gooQeH
TCRMorOzO8tWhK6NDPp9iKoNSYznmtWq+0Lc4Upa+cc3ktIOCiTWh9OBaFsFd8jB
Dlhw3sqwhMtqxJEoEJIZMGSE0W9p9y+D1XeNqfHmJ04NaTvuqfkt2z6ROd+pPdqb
A+b6aFZfBdh+ynOq2g6Epwq8rNe338E23gVGgNfcw4pdFq9NmpdVKREIQKObQWCQ
oElaQwIgyPI9rkpkT3QsHHJnEb9mRn05tlEplOi6S05/NIb+yz07Jb09UdAjxHDR
4MiUfXVXZwUAvuWKBnKK4ZjjgEZe21aoliLDl3yekewVqA==
-----END CERTIFICATE-----

View File

@ -1,27 +0,0 @@
-----BEGIN CERTIFICATE REQUEST-----
MIIEijCCAnICAQAwRTELMAkGA1UEBhMCQVUxEzARBgNVBAgTClNvbWUtU3RhdGUx
ITAfBgNVBAoTGEludGVybmV0IFdpZGdpdHMgUHR5IEx0ZDCCAiIwDQYJKoZIhvcN
AQEBBQADggIPADCCAgoCggIBAM7BD5K3KQdg8FchA+AP5mpThEGBvClP3in0W9/n
85kh6cjZSO/3AIR5FvB21sqP5GW9wzwFfYjbsw2nR13kb350uLMpsOCKCMNEldU2
Th31E93uv/nWMFPdYiSQj7iqRtMyOp+GQmeIFBmKwBqO5xo7TYXoUbF2qUVxT+X3
YIbXYxFu+Y2qYn2h1aeLKUofAB9XWNJudBJyS+2zEBz1sI2beYOuMDBmVkJodYTL
SyrdWgEDvLUhbE5KDtpdHm3o0cQyzrUBF9D9t0ZHjDDiFoZV1+VLryhJm05r1MnK
2/QFoycgUuQUO8Smrf0peM/TKtIaolALlwDfKHe4lDFRxn0Das9FHsuhLplUST7g
5ZE/SQ9boUgsNGIcw6WPSN4yZ8vMsYtb81ZYE8EAbqnA0lo7VjgssdlFQkTd0zvS
/+U0yYH9PVLeQntNf6mW5OB0IqjaqPG+dAgDQKdB55BJXtOJ5+4iLFfAAYZ2Dt1k
7QxKRfw0BI+JL8HcpY/ilIMMTOxGbPhSpEbS2eQVF8Ioe2QE8ns5Z0dqmBeeVQEi
ZBY7YxK096eZkHO5VwKS/nZDC4ULyD8QqWu2/NGXXUCOCD0tkCkjQFo61cT8saQG
k+lc2HQ+LXQROeI+G99mFf9FhviDpZ5UazGgPpX28esPU+yni75AplGV2wPR3VpG
9e/PAgMBAAGgADANBgkqhkiG9w0BAQUFAAOCAgEAyqppt9mxmlqAUkYCbNxPnc+M
1d5OQZ1Fqy0a4eF9/WxK+PqjRTKbD+rvGEulYdeCGiz8wP5HxVCdT2xzdVZdhMUX
opZGG3x5H1xXy0YLzBsxB9rkYjz+NeVtl8lKXvWDfgZ1vjjRHOIc261Eq6CPoXjT
5ENHnTyT0xbDmdkyjGNT0qowl50rlZotx6Vb2VPquAtau1m2nrvx5t0wkbJPocPA
XTndphgdH0aecJXZOgN8MWh9LYObNM5UqIFPaiNHHAetJIOLoDDIpEl5ZVj4PwtU
uiiaWpNjz3ODx2j5tmEz1SUF+6vS0OfvKx/pInQzFFRLfudgphzGYLf9rwOswBI7
8d0sEfrUNEladzvIz/IvJpuRrWJ/uLfpE4LXYTNbGWP50d1YRGxv7Zl8Bio0CU34
q+Du1CXpWce5bcOJ25KYZd7Lrf0YVzQjneuyNbBCPrp2gbweeydQWd6LGdtUab0l
gjQ3lj4E8Y1vIpTOL2K3bvkqJxJYoaYdzzGEzuv6/FS7ATYVn5sBYxJrsUqgYdjp
SMx6RS6ImNbHVy56nb6MiaztwAE4uo59vkrdKdvIETvP5duD4qDBsZL3WzJwhMxl
d9An+z3VAqEABzNtM7/Cdq7pZmgdPAHgGFasB3eihdmHsONWqExRPhcmW4H1hpVQ
pkguJFDOpRqebdLHZPI=
-----END CERTIFICATE REQUEST-----

View File

@ -1,51 +0,0 @@
-----BEGIN RSA PRIVATE KEY-----
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
-----END RSA PRIVATE KEY-----

View File

@ -1,51 +0,0 @@
-----BEGIN RSA PRIVATE KEY-----
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
-----END RSA PRIVATE KEY-----

View File

@ -1,14 +0,0 @@
-----BEGIN PUBLIC KEY-----
MIICIjANBgkqhkiG9w0BAQEFAAOCAg8AMIICCgKCAgEAzsEPkrcpB2DwVyED4A/m
alOEQYG8KU/eKfRb3+fzmSHpyNlI7/cAhHkW8HbWyo/kZb3DPAV9iNuzDadHXeRv
fnS4symw4IoIw0SV1TZOHfUT3e6/+dYwU91iJJCPuKpG0zI6n4ZCZ4gUGYrAGo7n
GjtNhehRsXapRXFP5fdghtdjEW75japifaHVp4spSh8AH1dY0m50EnJL7bMQHPWw
jZt5g64wMGZWQmh1hMtLKt1aAQO8tSFsTkoO2l0ebejRxDLOtQEX0P23RkeMMOIW
hlXX5UuvKEmbTmvUycrb9AWjJyBS5BQ7xKat/Sl4z9Mq0hqiUAuXAN8od7iUMVHG
fQNqz0Uey6EumVRJPuDlkT9JD1uhSCw0YhzDpY9I3jJny8yxi1vzVlgTwQBuqcDS
WjtWOCyx2UVCRN3TO9L/5TTJgf09Ut5Ce01/qZbk4HQiqNqo8b50CANAp0HnkEle
04nn7iIsV8ABhnYO3WTtDEpF/DQEj4kvwdylj+KUgwxM7EZs+FKkRtLZ5BUXwih7
ZATyezlnR2qYF55VASJkFjtjErT3p5mQc7lXApL+dkMLhQvIPxCpa7b80ZddQI4I
PS2QKSNAWjrVxPyxpAaT6VzYdD4tdBE54j4b32YV/0WG+IOlnlRrMaA+lfbx6w9T
7KeLvkCmUZXbA9HdWkb1788CAwEAAQ==
-----END PUBLIC KEY-----

Binary file not shown.

View File

@ -1,31 +0,0 @@
-----BEGIN CERTIFICATE-----
MIIFajCCA1KgAwIBAgIJAKMtnrbM5eQaMA0GCSqGSIb3DQEBBQUAMEUxCzAJBgNV
BAYTAkFVMRMwEQYDVQQIDApTb21lLVN0YXRlMSEwHwYDVQQKDBhJbnRlcm5ldCBX
aWRnaXRzIFB0eSBMdGQwHhcNMTMxMTEzMTkwNzMwWhcNMTQxMTEzMTkwNzMwWjBF
MQswCQYDVQQGEwJBVTETMBEGA1UECAwKU29tZS1TdGF0ZTEhMB8GA1UECgwYSW50
ZXJuZXQgV2lkZ2l0cyBQdHkgTHRkMIICIjANBgkqhkiG9w0BAQEFAAOCAg8AMIIC
CgKCAgEAs3+PRcgMLMquxhHB/1aN7lytduBGlXTsDNky3IQyQCpqFUdYYc5cS3nL
Y0wtwB4v+yNJ2qNOsYOlSUSSPS1nUxDsHWiMMPC6NxsE34wuf1jYI1UQbQiAEf73
wB+LMTuv30ZDG9EMfwiHf1VbOGKUwkSeZcMl8EX/DfmJCB9PONFHvlS1yQHnJwqv
SvIw55UgL/7fRvmblqrMsl0g/cveSanT2bGTV6eNYlDcAfw6SsszYbKA+i5zjt9F
puZA+JbqZ2mQ4RNi228ib9qGiS1S1YgyWqiJqGD8I15nvrWV9fA93z+kYekdc+nM
HXtWnd296vfcGQfuRgKAigp0Q2Xr/r6IfT0etMwNWOT/ikAE7l5hA3xUdEba0xdZ
2PYLmrb+5mtPB8uZ8K0JSrZJU70p1hlk644Nw1S6Je5/XfUZFzwLq8OotGnRzD7Y
dyvY/DEDodiQisLtLTCI9z4F7cjadTKwSSq5Yzr8Pdq1PkahBQth1Eq8KvodOXOR
WTVxP+YBYmbbk7EEOSZ8ZI7ppqngS6/pjcjCHobZfzJdfx8YuTrBWUHucYDqeV6r
xYtvlDiOaxyij8vhaAJ7zLfUuVGHKPfLgHZDAH47a+1qnIq5tM2Zv8p9g7wg56UV
aplu4GwBqNrL+5R10P2YuBgrUOZOjIOv0u5pvBjLZpTeal8KI7sCAwEAAaNdMFsw
HQYDVR0OBBYEFOkUWSDlAWoxFoSsbnbEH9GIN8bfMB8GA1UdIwQYMBaAFOkUWSDl
AWoxFoSsbnbEH9GIN8bfMAwGA1UdEwQFMAMBAf8wCwYDVR0PBAQDAgEGMA0GCSqG
SIb3DQEBBQUAA4ICAQBi30INj8fsPRsX9p1vVtljln2dh/iOJ0shL3gz9NmUM0jV
/UchKo5iykVrrCKVlI7DD/QFXXty20x6PnbSUwfhZpJj+AwT9G8pVD/8DBU60+z0
1zFSUxQ2GN9RDWgoiyz1QZ48n5zl7JVzzvBAf6N3jmdvgmIoKaDpqNLmQxqNsuCW
USMKqvqKwWfqvj8JQNYVmKdDVsoax36glVaj4qHZojul9eWS6SdDOo6a5t/xf0kP
Upxi87dqS4H7qfa6HTVFQhqRL8JuPqTs4csojA6XJt+yYzTfs8Gf3MAyQznuwiWh
E7kIv9lYH5APLW5LXNLizTaZtBS826f05TgBsYuYj3mGeSsr/llP4zb8u7qxL+B3
0Q6OLK3JtPbwtaHCBxs70HOQzjWjiEF6PE3f1MhvXFjMQmQEgGzCuK69EEUWK2s0
cIjoTLJxmQ+voWPms39gjstNLeykAygsyaYryGks/YjgchRrTtrOxUCows8knkmB
lve7RC9xW7yQwmWacPq0ndJUL0smdsWODx+L3J0R/YmbjYIO5N8i9YFqSwFLIC2v
ghirHq7EqZbYAaDxS6KvpeVh+f0pC8AC63FLbsp9+SOayoEQJ/gB8f+s3cxV+rNQ
/Z6077QuDgb1gpjCWCHHjMMELtjvy+HNUmgiRfv6a+mtWOS8g5Ii3OUYFVr2kQ==
-----END CERTIFICATE-----

View File

@ -1,54 +0,0 @@
-----BEGIN RSA PRIVATE KEY-----
Proc-Type: 4,ENCRYPTED
DEK-Info: DES-EDE3-CBC,5AD5C95753A0AE70
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
-----END RSA PRIVATE KEY-----

View File

@ -1,337 +0,0 @@
[ new_oids ]
# We can add new OIDs in here for use by 'ca', 'req' and 'ts'.
# Add a simple OID like this:
# testoid1=1.2.3.4
# Or use config file substitution like this:
# testoid2=${testoid1}.5.6
# Policies used by the TSA examples.
tsa_policy1 = 1.2.3.4.1
tsa_policy2 = 1.2.3.4.5.6
tsa_policy3 = 1.2.3.4.5.7
####################################################################
[ ca ]
default_ca = CA_default # The default ca section
####################################################################
[ CA_default ]
dir = ./demoCA # Where everything is kept
certs = $dir/certs # Where the issued certs are kept
crl_dir = $dir/crl # Where the issued crl are kept
database = $dir/index.txt # database index file.
#unique_subject = no # Set to 'no' to allow creation of
# several ctificates with same subject.
new_certs_dir = $dir/newcerts # default place for new certs.
certificate = $dir/cacert.pem # The CA certificate
serial = $dir/serial # The current serial number
crlnumber = $dir/crlnumber # the current crl number
# must be commented out to leave a V1 CRL
crl = $dir/crl.pem # The current CRL
private_key = $dir/private/cakey.pem# The private key
RANDFILE = $dir/private/.rand # private random number file
x509_extensions = usr_cert # The extentions to add to the cert
# Comment out the following two lines for the "traditional"
# (and highly broken) format.
name_opt = ca_default # Subject Name options
cert_opt = ca_default # Certificate field options
# Extension copying option: use with caution.
# copy_extensions = copy
# Extensions to add to a CRL. Note: Netscape communicator chokes on V2 CRLs
# so this is commented out by default to leave a V1 CRL.
# crlnumber must also be commented out to leave a V1 CRL.
# crl_extensions = crl_ext
default_days = 365 # how long to certify for
default_crl_days= 30 # how long before next CRL
default_md = default # use public key default MD
preserve = no # keep passed DN ordering
# A few difference way of specifying how similar the request should look
# For type CA, the listed attributes must be the same, and the optional
# and supplied fields are just that :-)
policy = policy_match
# For the CA policy
[ policy_match ]
countryName = match
stateOrProvinceName = match
organizationName = match
organizationalUnitName = optional
commonName = supplied
emailAddress = optional
# For the 'anything' policy
# At this point in time, you must list all acceptable 'object'
# types.
[ policy_anything ]
countryName = optional
stateOrProvinceName = optional
localityName = optional
organizationName = optional
organizationalUnitName = optional
commonName = supplied
emailAddress = optional
####################################################################
[ req ]
default_bits = 1024
default_keyfile = privkey.pem
distinguished_name = req_distinguished_name
attributes = req_attributes
x509_extensions = v3_ca # The extentions to add to the self signed cert
# Passwords for private keys if not present they will be prompted for
# input_password = secret
# output_password = secret
# This sets a mask for permitted string types. There are several options.
# default: PrintableString, T61String, BMPString.
# pkix : PrintableString, BMPString (PKIX recommendation before 2004)
# utf8only: only UTF8Strings (PKIX recommendation after 2004).
# nombstr : PrintableString, T61String (no BMPStrings or UTF8Strings).
# MASK:XXXX a literal mask value.
# WARNING: ancient versions of Netscape crash on BMPStrings or UTF8Strings.
string_mask = utf8only
req_extensions = v3_req # The extensions to add to a certificate request
[ req_distinguished_name ]
countryName = Country Name (2 letter code)
countryName_default = AU
countryName_min = 2
countryName_max = 2
stateOrProvinceName = State or Province Name (full name)
stateOrProvinceName_default = Some-State
localityName = Locality Name (eg, city)
0.organizationName = Organization Name (eg, company)
0.organizationName_default = Internet Widgits Pty Ltd
# we can do this but it is not needed normally :-)
#1.organizationName = Second Organization Name (eg, company)
#1.organizationName_default = World Wide Web Pty Ltd
organizationalUnitName = Organizational Unit Name (eg, section)
#organizationalUnitName_default =
commonName = Common Name (e.g. server FQDN or YOUR name)
commonName_max = 64
emailAddress = Email Address
emailAddress_max = 64
# SET-ex3 = SET extension number 3
[ req_attributes ]
challengePassword = A challenge password
challengePassword_min = 4
challengePassword_max = 20
unstructuredName = An optional company name
[ usr_cert ]
# This is required for TSA certificates.
# This is required for client Auth and server Auth
extendedKeyUsage = critical,timeStamping,serverAuth,clientAuth
# These extensions are added when 'ca' signs a request.
# This goes against PKIX guidelines but some CAs do it and some software
# requires this to avoid interpreting an end user certificate as a CA.
basicConstraints=CA:FALSE
# Here are some examples of the usage of nsCertType. If it is omitted
# the certificate can be used for anything *except* object signing.
# This is OK for an SSL server.
# nsCertType = server
# For an object signing certificate this would be used.
# nsCertType = objsign
# For normal client use this is typical
# nsCertType = client, email
# and for everything including object signing:
# nsCertType = client, email, objsign
# This is typical in keyUsage for a client certificate.
# keyUsage = nonRepudiation, digitalSignature, keyEncipherment
# This will be displayed in Netscape's comment listbox.
nsComment = "OpenSSL Generated Certificate"
# PKIX recommendations harmless if included in all certificates.
subjectKeyIdentifier=hash
authorityKeyIdentifier=keyid,issuer
# This stuff is for subjectAltName and issuerAltname.
# Import the email address.
# subjectAltName=email:copy
# An alternative to produce certificates that aren't
# deprecated according to PKIX.
# subjectAltName=email:move
# Copy subject details
# issuerAltName=issuer:copy
#nsCaRevocationUrl = http://www.domain.dom/ca-crl.pem
#nsBaseUrl
#nsRevocationUrl
#nsRenewalUrl
#nsCaPolicyUrl
#nsSslServerName
[ v3_req ]
# Extensions to add to a certificate request
basicConstraints = CA:FALSE
keyUsage = nonRepudiation, digitalSignature, keyEncipherment
extendedKeyUsage = critical,timeStamping,serverAuth,clientAuth
subjectAltName = @alt_names
[ v3_ca ]
# Extensions for a typical CA
# PKIX recommendation.
subjectKeyIdentifier=hash
authorityKeyIdentifier=keyid:always,issuer
# This is what PKIX recommends but some broken software chokes on critical
# extensions.
#basicConstraints = critical,CA:true
# So we do this instead.
basicConstraints = CA:true
keyUsage = keyCertSign, cRLSign
# Key usage: this is typical for a CA certificate. However since it will
# prevent it being used as an test self-signed certificate it is best
# left out by default.
# keyUsage = cRLSign, keyCertSign
# Some might want this also
# nsCertType = sslCA, emailCA
# Include email address in subject alt name: another PKIX recommendation
# subjectAltName=email:copy
# Copy issuer details
# issuerAltName=issuer:copy
# DER hex encoding of an extension: beware experts only!
# obj=DER:02:03
# Where 'obj' is a standard or added object
# You can even override a supported extension:
# basicConstraints= critical, DER:30:03:01:01:FF
[ crl_ext ]
# CRL extensions.
# Only issuerAltName and authorityKeyIdentifier make any sense in a CRL.
# issuerAltName=issuer:copy
authorityKeyIdentifier=keyid:always
[ proxy_cert_ext ]
# These extensions should be added when creating a proxy certificate
# This goes against PKIX guidelines but some CAs do it and some software
# requires this to avoid interpreting an end user certificate as a CA.
basicConstraints=CA:FALSE
# Here are some examples of the usage of nsCertType. If it is omitted
# the certificate can be used for anything *except* object signing.
# This is OK for an SSL server.
# nsCertType = server
# For an object signing certificate this would be used.
# nsCertType = objsign
# For normal client use this is typical
# nsCertType = client, email
# and for everything including object signing:
# nsCertType = client, email, objsign
# This is typical in keyUsage for a client certificate.
# keyUsage = nonRepudiation, digitalSignature, keyEncipherment
# This will be displayed in Netscape's comment listbox.
nsComment = "OpenSSL Generated Certificate"
# PKIX recommendations harmless if included in all certificates.
subjectKeyIdentifier=hash
authorityKeyIdentifier=keyid,issuer
# This stuff is for subjectAltName and issuerAltname.
# Import the email address.
# subjectAltName=email:copy
# An alternative to produce certificates that aren't
# deprecated according to PKIX.
# subjectAltName=email:move
# Copy subject details
# issuerAltName=issuer:copy
#nsCaRevocationUrl = http://www.domain.dom/ca-crl.pem
#nsBaseUrl
#nsRevocationUrl
#nsRenewalUrl
#nsCaPolicyUrl
#nsSslServerName
# This really needs to be in place for it to be a proxy certificate.
proxyCertInfo=critical,language:id-ppl-anyLanguage,pathlen:3,policy:foo
####################################################################
[ tsa ]
default_tsa = tsa_config1 # the default TSA section
[ tsa_config1 ]
# These are used by the TSA reply generation only.
dir = ./demoCA # TSA root directory
serial = $dir/tsaserial # The current serial number (mandatory)
crypto_device = builtin # OpenSSL engine to use for signing
signer_cert = $dir/tsacert.pem # The TSA signing certificate
# (optional)
certs = $dir/cacert.pem # Certificate chain to include in reply
# (optional)
signer_key = $dir/private/tsakey.pem # The TSA private key (optional)
default_policy = tsa_policy1 # Policy if request did not specify it
# (optional)
other_policies = tsa_policy2, tsa_policy3 # acceptable policies (optional)
digests = md5, sha1 # Acceptable message digests (mandatory)
accuracy = secs:1, millisecs:500, microsecs:100 # (optional)
clock_precision_digits = 0 # number of digits after dot. (optional)
ordering = yes # Is ordering defined for timestamps?
# (optional, default: no)
tsa_name = yes # Must the TSA name be included in the reply?
# (optional, default: no)
ess_cert_id_chain = no # Must the ESS cert id chain be included?
# (optional, default: no)
[alt_names]
IP.1 = 127.0.0.1

View File

@ -1,63 +0,0 @@
-----BEGIN CERTIFICATE-----
MIIFajCCA1KgAwIBAgIJAKMtnrbM5eQaMA0GCSqGSIb3DQEBBQUAMEUxCzAJBgNV
BAYTAkFVMRMwEQYDVQQIDApTb21lLVN0YXRlMSEwHwYDVQQKDBhJbnRlcm5ldCBX
aWRnaXRzIFB0eSBMdGQwHhcNMTMxMTEzMTkwNzMwWhcNMTQxMTEzMTkwNzMwWjBF
MQswCQYDVQQGEwJBVTETMBEGA1UECAwKU29tZS1TdGF0ZTEhMB8GA1UECgwYSW50
ZXJuZXQgV2lkZ2l0cyBQdHkgTHRkMIICIjANBgkqhkiG9w0BAQEFAAOCAg8AMIIC
CgKCAgEAs3+PRcgMLMquxhHB/1aN7lytduBGlXTsDNky3IQyQCpqFUdYYc5cS3nL
Y0wtwB4v+yNJ2qNOsYOlSUSSPS1nUxDsHWiMMPC6NxsE34wuf1jYI1UQbQiAEf73
wB+LMTuv30ZDG9EMfwiHf1VbOGKUwkSeZcMl8EX/DfmJCB9PONFHvlS1yQHnJwqv
SvIw55UgL/7fRvmblqrMsl0g/cveSanT2bGTV6eNYlDcAfw6SsszYbKA+i5zjt9F
puZA+JbqZ2mQ4RNi228ib9qGiS1S1YgyWqiJqGD8I15nvrWV9fA93z+kYekdc+nM
HXtWnd296vfcGQfuRgKAigp0Q2Xr/r6IfT0etMwNWOT/ikAE7l5hA3xUdEba0xdZ
2PYLmrb+5mtPB8uZ8K0JSrZJU70p1hlk644Nw1S6Je5/XfUZFzwLq8OotGnRzD7Y
dyvY/DEDodiQisLtLTCI9z4F7cjadTKwSSq5Yzr8Pdq1PkahBQth1Eq8KvodOXOR
WTVxP+YBYmbbk7EEOSZ8ZI7ppqngS6/pjcjCHobZfzJdfx8YuTrBWUHucYDqeV6r
xYtvlDiOaxyij8vhaAJ7zLfUuVGHKPfLgHZDAH47a+1qnIq5tM2Zv8p9g7wg56UV
aplu4GwBqNrL+5R10P2YuBgrUOZOjIOv0u5pvBjLZpTeal8KI7sCAwEAAaNdMFsw
HQYDVR0OBBYEFOkUWSDlAWoxFoSsbnbEH9GIN8bfMB8GA1UdIwQYMBaAFOkUWSDl
AWoxFoSsbnbEH9GIN8bfMAwGA1UdEwQFMAMBAf8wCwYDVR0PBAQDAgEGMA0GCSqG
SIb3DQEBBQUAA4ICAQBi30INj8fsPRsX9p1vVtljln2dh/iOJ0shL3gz9NmUM0jV
/UchKo5iykVrrCKVlI7DD/QFXXty20x6PnbSUwfhZpJj+AwT9G8pVD/8DBU60+z0
1zFSUxQ2GN9RDWgoiyz1QZ48n5zl7JVzzvBAf6N3jmdvgmIoKaDpqNLmQxqNsuCW
USMKqvqKwWfqvj8JQNYVmKdDVsoax36glVaj4qHZojul9eWS6SdDOo6a5t/xf0kP
Upxi87dqS4H7qfa6HTVFQhqRL8JuPqTs4csojA6XJt+yYzTfs8Gf3MAyQznuwiWh
E7kIv9lYH5APLW5LXNLizTaZtBS826f05TgBsYuYj3mGeSsr/llP4zb8u7qxL+B3
0Q6OLK3JtPbwtaHCBxs70HOQzjWjiEF6PE3f1MhvXFjMQmQEgGzCuK69EEUWK2s0
cIjoTLJxmQ+voWPms39gjstNLeykAygsyaYryGks/YjgchRrTtrOxUCows8knkmB
lve7RC9xW7yQwmWacPq0ndJUL0smdsWODx+L3J0R/YmbjYIO5N8i9YFqSwFLIC2v
ghirHq7EqZbYAaDxS6KvpeVh+f0pC8AC63FLbsp9+SOayoEQJ/gB8f+s3cxV+rNQ
/Z6077QuDgb1gpjCWCHHjMMELtjvy+HNUmgiRfv6a+mtWOS8g5Ii3OUYFVr2kQ==
-----END CERTIFICATE-----
-----BEGIN CERTIFICATE-----
MIIFfDCCA2SgAwIBAgIBATANBgkqhkiG9w0BAQUFADBFMQswCQYDVQQGEwJBVTET
MBEGA1UECAwKU29tZS1TdGF0ZTEhMB8GA1UECgwYSW50ZXJuZXQgV2lkZ2l0cyBQ
dHkgTHRkMB4XDTEzMTExMzE5MDgxMloXDTE0MTExMzE5MDgxMlowZTELMAkGA1UE
BhMCQVUxEzARBgNVBAgMClNvbWUtU3RhdGUxITAfBgNVBAoMGEludGVybmV0IFdp
ZGdpdHMgUHR5IEx0ZDEeMBwGA1UEAwwVaHR0cDovLzEyNy4wLjAuMTo0MDAxMIIC
IjANBgkqhkiG9w0BAQEFAAOCAg8AMIICCgKCAgEA1XBtjDav5Sl3H+/fUcGiQO36
oqtZG+YuC9D0z0u89Shq+XNs3tRtonGGCyEIrDtI6R7PItMJa6rQ1VuFoMWPrjmF
f5tFemSOZtQx/DF78H+5tWaIBVDA+Kw1zxdqj1n3/AQjAGsSuqhgcaIQQFqTNNtA
tW40048fDh17jWIDB9baF65az2uArq97uS4deDujG3CHV9svO7hoqpzYt039VDKK
4N+dDMUZFqhEmY2MqjyQySY2bd/gsYBjcGWSIuonALactiYDc4zIusAfNptnXycw
K/aQAqDwhwMcQA9L5YKQ5hoUukDTQFbvoNLJ3vNQDI/o8sjCh94EkMuopSp90tJ/
syTPKRlh/MaGMXvwu8Vab5iPeVop48jTKl3Z+G8NErGM8KKCyd1mQoGisVuIMQPK
uJUi7jOu6wgXlA8ZgUGfSQQDA4v2Q0tV/GlJmvsP5JshA3v7C/sSBY/3AnPHeWTl
ozXlNgXitxps1EwgR2jo+YW2gxrfM//xtgMCjMXjO9g2TsCnWR6j93oXWn88UP/C
eAcyjeTdJjW+piuLdvYOctY6+Yql5gm9Vx0u+w9jTmpzOCoh+9cNtjqmPiOhecFc
Vf71vMf4krMp6lmY/Nq1/km9u0ViNP5CJHk18YXG42vnj7sUgT7WgpLh8g/iPc2p
etH9lMd9te+Jyak/zA8CAwEAAaNXMFUwCQYDVR0TBAIwADALBgNVHQ8EBAMCBeAw
KgYDVR0lAQH/BCAwHgYIKwYBBQUHAwgGCCsGAQUFBwMBBggrBgEFBQcDAjAPBgNV
HREECDAGhwR/AAABMA0GCSqGSIb3DQEBBQUAA4ICAQCmF13fF7kAcgCzRKBCpggz
ObVNSK9btGKUU+xyOZsRgEDWdfeBvG3VzXflLMDv3P45O90CHkcGfckbj1ISctIY
0OSnCn4vmIwnhwUWyYlCagtNB68GVcPH8XLxn/wsnT2MbiA/ohUStKXQtBmBxIUH
rI+7r28qcHW7AnT47G5BbSYzW0xYzlkUwyl8rBxRLDKVTHBJ5GmlREJKdAzKS7CS
6jhcsxa544Rsa7CDvjLKpJO0iploL0/GY+5oj3VdhgdEJgwqwvu3skfd1N8wkxH4
NQuRmyvXxcMSxKv4vbOOUm4PfOqOwwXiVZLoc29ePUv9zCU2AVdS21DD9zAZeKDb
B87VWnQKO6JUvL5vX7xsMnsSbnLHGA2kPv4IDZ6jKuZdVneM+whDZlBWpHRL2RKX
K0JZICf7+EbmrUW3Rwl+dIaIJ55Ni1rfDSZWeIYKFx04Mod6Wbch7ahb/XVvIDe9
SFjLfeNj7L/Iz0i+1lTarAMxIRC521IwcobhAxqxYCv3oNf6f+tz8DyCCvsTCc9W
/OLKX7sukh1ohle+0EFrSYpX5PzkHwZRVZjx55KwkIV/KtwBadJv+z6iwW3qOn/A
/1yC8Mbc2TdCaRPwFO80LAg9cz+XfT5vZoQUvOnOxIrhFnasQ/xiovy0zKCr2Fjg
ePQ4BNEN9wt3SsPp8ig39g==
-----END CERTIFICATE-----

View File

@ -1,32 +0,0 @@
-----BEGIN CERTIFICATE-----
MIIFfDCCA2SgAwIBAgIBATANBgkqhkiG9w0BAQUFADBFMQswCQYDVQQGEwJBVTET
MBEGA1UECAwKU29tZS1TdGF0ZTEhMB8GA1UECgwYSW50ZXJuZXQgV2lkZ2l0cyBQ
dHkgTHRkMB4XDTEzMTExMzE5MDgxMloXDTE0MTExMzE5MDgxMlowZTELMAkGA1UE
BhMCQVUxEzARBgNVBAgMClNvbWUtU3RhdGUxITAfBgNVBAoMGEludGVybmV0IFdp
ZGdpdHMgUHR5IEx0ZDEeMBwGA1UEAwwVaHR0cDovLzEyNy4wLjAuMTo0MDAxMIIC
IjANBgkqhkiG9w0BAQEFAAOCAg8AMIICCgKCAgEA1XBtjDav5Sl3H+/fUcGiQO36
oqtZG+YuC9D0z0u89Shq+XNs3tRtonGGCyEIrDtI6R7PItMJa6rQ1VuFoMWPrjmF
f5tFemSOZtQx/DF78H+5tWaIBVDA+Kw1zxdqj1n3/AQjAGsSuqhgcaIQQFqTNNtA
tW40048fDh17jWIDB9baF65az2uArq97uS4deDujG3CHV9svO7hoqpzYt039VDKK
4N+dDMUZFqhEmY2MqjyQySY2bd/gsYBjcGWSIuonALactiYDc4zIusAfNptnXycw
K/aQAqDwhwMcQA9L5YKQ5hoUukDTQFbvoNLJ3vNQDI/o8sjCh94EkMuopSp90tJ/
syTPKRlh/MaGMXvwu8Vab5iPeVop48jTKl3Z+G8NErGM8KKCyd1mQoGisVuIMQPK
uJUi7jOu6wgXlA8ZgUGfSQQDA4v2Q0tV/GlJmvsP5JshA3v7C/sSBY/3AnPHeWTl
ozXlNgXitxps1EwgR2jo+YW2gxrfM//xtgMCjMXjO9g2TsCnWR6j93oXWn88UP/C
eAcyjeTdJjW+piuLdvYOctY6+Yql5gm9Vx0u+w9jTmpzOCoh+9cNtjqmPiOhecFc
Vf71vMf4krMp6lmY/Nq1/km9u0ViNP5CJHk18YXG42vnj7sUgT7WgpLh8g/iPc2p
etH9lMd9te+Jyak/zA8CAwEAAaNXMFUwCQYDVR0TBAIwADALBgNVHQ8EBAMCBeAw
KgYDVR0lAQH/BCAwHgYIKwYBBQUHAwgGCCsGAQUFBwMBBggrBgEFBQcDAjAPBgNV
HREECDAGhwR/AAABMA0GCSqGSIb3DQEBBQUAA4ICAQCmF13fF7kAcgCzRKBCpggz
ObVNSK9btGKUU+xyOZsRgEDWdfeBvG3VzXflLMDv3P45O90CHkcGfckbj1ISctIY
0OSnCn4vmIwnhwUWyYlCagtNB68GVcPH8XLxn/wsnT2MbiA/ohUStKXQtBmBxIUH
rI+7r28qcHW7AnT47G5BbSYzW0xYzlkUwyl8rBxRLDKVTHBJ5GmlREJKdAzKS7CS
6jhcsxa544Rsa7CDvjLKpJO0iploL0/GY+5oj3VdhgdEJgwqwvu3skfd1N8wkxH4
NQuRmyvXxcMSxKv4vbOOUm4PfOqOwwXiVZLoc29ePUv9zCU2AVdS21DD9zAZeKDb
B87VWnQKO6JUvL5vX7xsMnsSbnLHGA2kPv4IDZ6jKuZdVneM+whDZlBWpHRL2RKX
K0JZICf7+EbmrUW3Rwl+dIaIJ55Ni1rfDSZWeIYKFx04Mod6Wbch7ahb/XVvIDe9
SFjLfeNj7L/Iz0i+1lTarAMxIRC521IwcobhAxqxYCv3oNf6f+tz8DyCCvsTCc9W
/OLKX7sukh1ohle+0EFrSYpX5PzkHwZRVZjx55KwkIV/KtwBadJv+z6iwW3qOn/A
/1yC8Mbc2TdCaRPwFO80LAg9cz+XfT5vZoQUvOnOxIrhFnasQ/xiovy0zKCr2Fjg
ePQ4BNEN9wt3SsPp8ig39g==
-----END CERTIFICATE-----

View File

@ -1,30 +0,0 @@
-----BEGIN CERTIFICATE REQUEST-----
MIIFEDCCAvgCAQAwZTELMAkGA1UEBhMCQVUxEzARBgNVBAgMClNvbWUtU3RhdGUx
ITAfBgNVBAoMGEludGVybmV0IFdpZGdpdHMgUHR5IEx0ZDEeMBwGA1UEAwwVaHR0
cDovLzEyNy4wLjAuMTo0MDAxMIICIjANBgkqhkiG9w0BAQEFAAOCAg8AMIICCgKC
AgEA1XBtjDav5Sl3H+/fUcGiQO36oqtZG+YuC9D0z0u89Shq+XNs3tRtonGGCyEI
rDtI6R7PItMJa6rQ1VuFoMWPrjmFf5tFemSOZtQx/DF78H+5tWaIBVDA+Kw1zxdq
j1n3/AQjAGsSuqhgcaIQQFqTNNtAtW40048fDh17jWIDB9baF65az2uArq97uS4d
eDujG3CHV9svO7hoqpzYt039VDKK4N+dDMUZFqhEmY2MqjyQySY2bd/gsYBjcGWS
IuonALactiYDc4zIusAfNptnXycwK/aQAqDwhwMcQA9L5YKQ5hoUukDTQFbvoNLJ
3vNQDI/o8sjCh94EkMuopSp90tJ/syTPKRlh/MaGMXvwu8Vab5iPeVop48jTKl3Z
+G8NErGM8KKCyd1mQoGisVuIMQPKuJUi7jOu6wgXlA8ZgUGfSQQDA4v2Q0tV/GlJ
mvsP5JshA3v7C/sSBY/3AnPHeWTlozXlNgXitxps1EwgR2jo+YW2gxrfM//xtgMC
jMXjO9g2TsCnWR6j93oXWn88UP/CeAcyjeTdJjW+piuLdvYOctY6+Yql5gm9Vx0u
+w9jTmpzOCoh+9cNtjqmPiOhecFcVf71vMf4krMp6lmY/Nq1/km9u0ViNP5CJHk1
8YXG42vnj7sUgT7WgpLh8g/iPc2petH9lMd9te+Jyak/zA8CAwEAAaBmMGQGCSqG
SIb3DQEJDjFXMFUwCQYDVR0TBAIwADALBgNVHQ8EBAMCBeAwKgYDVR0lAQH/BCAw
HgYIKwYBBQUHAwgGCCsGAQUFBwMBBggrBgEFBQcDAjAPBgNVHREECDAGhwR/AAAB
MA0GCSqGSIb3DQEBBQUAA4ICAQCeVkI4JwSyax5kJJ1iljkngfK+BdsrqBJWPITj
mrl9DH7/2ev0GdzHEG3oQrti6vMvsowS6vHtpgc1tsbS9UwDY/N0ZgFWgnb5O5k2
4zZfGkma3GHCvG9WXsA9+Gs7KedggsXxfnJTLe4B/sZqtRO0dMD/JZTJQ6reuayh
bYvVBVSmittAjsfer+9xuXkHYYAPNYmW52aUN1AhnIsS3TVp1vHcxgNoFOQglN21
lHwmeh5QbTx/paHFnWLLqLVydbiB/Qzz6x4zsEKESATd02WbN9XKUfGM0G+bG+57
ErtrU7yzsLjPYYPcP9nYg8dzfdwVgfdjg+yw2hdmkqjDQD3YAmxRcat7uK8htVa0
z4dfjdNRO3HhSLALKS/Tl9qpLKpEi8/0ByYErJz6i+Xyf4pkdPQcBQKybkFja136
9xkonhE7DLTo1zQobfAJlnfTMxuJc0mOGvT+DqGSCFmNEl3WgIAgu9m77mp81Bqo
0qwrB3pYSAzL9xHuluwZMn37sdmVFFReEkEaRllRgDTZL9vSQh2yOqtV920083/y
sHPUijSsKysSKz0RuzMBCc3RD07Kcs1TFg/NdZiYKf8V9NDDOgk5LC2Sqoin7v6F
yB4wpnm6RqQ7iSRpp/VBs3PAnK2uJEkoOU5p5jZdQ0IDtesHVzM7bCUIrQIX2pAr
owvMhQ==
-----END CERTIFICATE REQUEST-----

View File

@ -1,54 +0,0 @@
-----BEGIN RSA PRIVATE KEY-----
Proc-Type: 4,ENCRYPTED
DEK-Info: DES-EDE3-CBC,E445BB698AB9CDC4
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
-----END RSA PRIVATE KEY-----

View File

@ -1,51 +0,0 @@
-----BEGIN RSA PRIVATE KEY-----
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
-----END RSA PRIVATE KEY-----

View File

@ -1,31 +0,0 @@
-----BEGIN CERTIFICATE-----
MIIFXDCCA0SgAwIBAgIBAjANBgkqhkiG9w0BAQUFADBFMQswCQYDVQQGEwJBVTET
MBEGA1UECAwKU29tZS1TdGF0ZTEhMB8GA1UECgwYSW50ZXJuZXQgV2lkZ2l0cyBQ
dHkgTHRkMB4XDTEzMTExMzE5MTg1MFoXDTE0MTExMzE5MTg1MFowRTELMAkGA1UE
BhMCQVUxEzARBgNVBAgMClNvbWUtU3RhdGUxITAfBgNVBAoMGEludGVybmV0IFdp
ZGdpdHMgUHR5IEx0ZDCCAiIwDQYJKoZIhvcNAQEBBQADggIPADCCAgoCggIBALY5
FfOgbclrkfZS/XpzPJgWZrs/W+zakuoBDtkeTeIdVMk2lNZ//oA4g+eYVPnf0DSJ
oEPvJIOuwjF8b2M3iYR+fwV4iI2NKVEiV5469qtjkSm7OlvNRMAeWztGm8uXI9wg
9MEqVU4SPlpTV7kUE2c/d3jU6ZAjvgBn6sWnRWG39lBGXecqay6PzbAYhlrGH/Ou
PZaL4mc6nE1D7/mdBOo3J+6dNQUzB9FhU/BY55M5c0tSrDGlM9pPE9/p3JXu1dcp
95YtZbUCib/NPVnHGEK5s8LfG6RE8kxxUj6bPjPmyEF+jsgwJb2vdHjOXbwbtsji
WprZ6TrAFfLQWmD9qbsVxvyMlnuzrfPyaREWhgijBADDGBmcL8k/OFH3LqhmwOET
LpGepCV5BbRqD3+tDIQcjjlt1fdJTDu1RuPs921EdHXaQNzTTPbO9DoNpFY0l6Ul
Hjlz8VlnwuEoehd3NDZc7a/b8X6Ry0JwuaymouUJE9GQrGJRJ3imZkwrhhqxiWIt
p6HJKgePD38V1tFbifqjiF/LfhqaZ/oaFU5f3wLbs41BuMOQtEoNsmRCNd2L6BJ+
+fskqnJfbuw6YRoB7gvoFjyqn5CZuox8ArmOs/oYk2nior2jBEQI+S0JwVquBDvb
vyUnYT+E/mSURUA6kPtHax0kaDZnQijXGc4KwASpAgMBAAGjVzBVMAkGA1UdEwQC
MAAwCwYDVR0PBAQDAgXgMCoGA1UdJQEB/wQgMB4GCCsGAQUFBwMIBggrBgEFBQcD
AQYIKwYBBQUHAwIwDwYDVR0RBAgwBocEfwAAATANBgkqhkiG9w0BAQUFAAOCAgEA
qZuN6qS3vIXPCOcRAC/3mxLtccfZOg57NKb6NQ1lzkPXdMDp6Bd3TfWyrkj0lm1w
Ya9fb/G0yVGAI11WW4ifML3SF3sKwd5PwiqCZa2kTTxL2Wes7t01jueZ0J7vDecf
n++PNkCZjQ4BoSbnCABNyuHoW3GMdZAnlaVdkZHetRN7gwsNvfiCWFHU/slhjN8K
KgvQi08BWhiIFqUmBhqpDJDSgd8lJi2gBjq4idkYkW1xcpO4Iz+dZRloPB/ZICnl
dt+Err9MAec6XpKdniJFLil2FALMmATEZXnGZMuXezXJEZKYhx9ZHuZZDuNBhD6Y
VbOTrpq9F7oWdzqhUCa4y3HKKPt0ZuvP/0nHnGBe/eOPrJANQYpCHw02AXom67eJ
9PW0PS2YC7O4cy+Y/DOI9FkzRpa+Z6OMSqKu9hkBCLGVad1cb8cLyl0MJpUu2UAV
55ovFT6owhR/ZSIDEX4VeNwX0PsHIXIUDFE5Xp58tB9QbRp9ZA4c4OAQ2eGQ8Grz
v2IxJJgmjBIuAZqdW6KDKy2vc1SQZw3uaFOYUEk3f5uAoTiARIVF2qrVGPDQjGbC
fumWNsjU0ale1EstgS5KdQc2Ox3wHsc84up6QaMfPqKmvSDOd+RgGzRqh5G07bni
BWHaIF0K+tJNnPYiTX7nbP9dP3SAfvsPylUFVj9fiSI=
-----END CERTIFICATE-----

View File

@ -1,29 +0,0 @@
-----BEGIN CERTIFICATE REQUEST-----
MIIE8DCCAtgCAQAwRTELMAkGA1UEBhMCQVUxEzARBgNVBAgMClNvbWUtU3RhdGUx
ITAfBgNVBAoMGEludGVybmV0IFdpZGdpdHMgUHR5IEx0ZDCCAiIwDQYJKoZIhvcN
AQEBBQADggIPADCCAgoCggIBALY5FfOgbclrkfZS/XpzPJgWZrs/W+zakuoBDtke
TeIdVMk2lNZ//oA4g+eYVPnf0DSJoEPvJIOuwjF8b2M3iYR+fwV4iI2NKVEiV546
9qtjkSm7OlvNRMAeWztGm8uXI9wg9MEqVU4SPlpTV7kUE2c/d3jU6ZAjvgBn6sWn
RWG39lBGXecqay6PzbAYhlrGH/OuPZaL4mc6nE1D7/mdBOo3J+6dNQUzB9FhU/BY
55M5c0tSrDGlM9pPE9/p3JXu1dcp95YtZbUCib/NPVnHGEK5s8LfG6RE8kxxUj6b
PjPmyEF+jsgwJb2vdHjOXbwbtsjiWprZ6TrAFfLQWmD9qbsVxvyMlnuzrfPyaREW
hgijBADDGBmcL8k/OFH3LqhmwOETLpGepCV5BbRqD3+tDIQcjjlt1fdJTDu1RuPs
921EdHXaQNzTTPbO9DoNpFY0l6UlHjlz8VlnwuEoehd3NDZc7a/b8X6Ry0Jwuaym
ouUJE9GQrGJRJ3imZkwrhhqxiWItp6HJKgePD38V1tFbifqjiF/LfhqaZ/oaFU5f
3wLbs41BuMOQtEoNsmRCNd2L6BJ++fskqnJfbuw6YRoB7gvoFjyqn5CZuox8ArmO
s/oYk2nior2jBEQI+S0JwVquBDvbvyUnYT+E/mSURUA6kPtHax0kaDZnQijXGc4K
wASpAgMBAAGgZjBkBgkqhkiG9w0BCQ4xVzBVMAkGA1UdEwQCMAAwCwYDVR0PBAQD
AgXgMCoGA1UdJQEB/wQgMB4GCCsGAQUFBwMIBggrBgEFBQcDAQYIKwYBBQUHAwIw
DwYDVR0RBAgwBocEfwAAATANBgkqhkiG9w0BAQUFAAOCAgEAsjhQOckysiSTZaz/
Ck5APYE13ckBQOxvHqrCvDQSRMqq/yb/eWtItQhCs9u3fKGFGKCefPYwtVdUj6v2
g4SpXzBblcXNP8SXEtbcNuG4lPNsTc2YbDxuLWmgvLX8on2nq0f+TcGmtvvmCaLz
tEdLPlQfkzQUlwfaK4kMJ4qzR8eeHxBrhKJyDyzSreZSa/ZXMcKpjJLhXl6oM+ud
cfi0BO/xOKt/MmGHAxTMNrTFV5HcEWzws+r51sCcIV4BwuELA5rZuG0leaj3CDDy
3dPkpLp3HObbX3KV6yyCCfEAN4pyoZQNut8i87FITsYbJJy4ld7/PWTvg/JMk96X
ZACpeI1ERL/Sr3uzFpmlLszwSQ7t/hv5ykFA6d1QLv0u+EX1mL1O/PZ5Lb3moC4t
7ma3CffPqJpEjvvdXtweol62MI4Rr/1sXyZGR+lvkjcoSY5vzv0j7V4w6/e1In3D
nHY4vmpuy65w5gGm/s2y2cXRfCc8P4we0+A+QbNAgt3eicdJmWZGcWwlMQI10Nmq
6Qnp8cpwvFM/iCIajfIAz0fD7G0UEL5ExSFoh6WhFFDOYbTl5MeXUjMaYmemICE2
r3GVfZxHLvDQzftkq/oSXXiZgLkoYveN0R7VJuUfCgyLOlJL5O8WX2lX8odUKINc
DcZ/FpV+R/u7WGm2j0tvRA4y9Qc=
-----END CERTIFICATE REQUEST-----

View File

@ -1,54 +0,0 @@
-----BEGIN RSA PRIVATE KEY-----
Proc-Type: 4,ENCRYPTED
DEK-Info: DES-EDE3-CBC,F332544C4A2552FC
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
-----END RSA PRIVATE KEY-----

View File

@ -1,51 +0,0 @@
-----BEGIN RSA PRIVATE KEY-----
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
-----END RSA PRIVATE KEY-----

View File

@ -1,3 +0,0 @@
// +build !go1.2
"etcd requires go 1.2 or greater to build"

View File

@ -1,75 +0,0 @@
/*
Copyright 2013 CoreOS Inc.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
package http
import (
"fmt"
"net/http"
"net/url"
)
type CORSInfo map[string]bool
func NewCORSInfo(origins []string) (*CORSInfo, error) {
// Construct a lookup of all origins.
m := make(map[string]bool)
for _, v := range origins {
if v != "*" {
if _, err := url.Parse(v); err != nil {
return nil, fmt.Errorf("Invalid CORS origin: %s", err)
}
}
m[v] = true
}
info := CORSInfo(m)
return &info, nil
}
// OriginAllowed determines whether the server will allow a given CORS origin.
func (c CORSInfo) OriginAllowed(origin string) bool {
return c["*"] || c[origin]
}
type CORSHandler struct {
Handler http.Handler
Info *CORSInfo
}
// addHeader adds the correct cors headers given an origin
func (h *CORSHandler) addHeader(w http.ResponseWriter, origin string) {
w.Header().Add("Access-Control-Allow-Methods", "POST, GET, OPTIONS, PUT, DELETE")
w.Header().Add("Access-Control-Allow-Origin", origin)
}
// ServeHTTP adds the correct CORS headers based on the origin and returns immediatly
// with a 200 OK if the method is OPTIONS.
func (h *CORSHandler) ServeHTTP(w http.ResponseWriter, req *http.Request) {
// Write CORS header.
if h.Info.OriginAllowed("*") {
h.addHeader(w, "*")
} else if origin := req.Header.Get("Origin"); h.Info.OriginAllowed(origin) {
h.addHeader(w, origin)
}
if req.Method == "OPTIONS" {
w.WriteHeader(http.StatusOK)
return
}
h.Handler.ServeHTTP(w, req)
}

View File

@ -1,36 +0,0 @@
package http
import (
"net/http"
"strings"
)
func NewLowerQueryParamsHandler(hdlr http.Handler) *LowerQueryParamsHandler {
return &LowerQueryParamsHandler{hdlr}
}
type LowerQueryParamsHandler struct {
Handler http.Handler
}
func (h *LowerQueryParamsHandler) ServeHTTP(w http.ResponseWriter, req *http.Request) {
err := req.ParseForm()
if err == nil {
lowerBoolQueryParams(req)
}
h.Handler.ServeHTTP(w, req)
}
func lowerBoolQueryParams(req *http.Request) {
form := req.Form
for key, vals := range form {
for i, val := range vals {
lowered := strings.ToLower(val)
if lowered == "true" || lowered == "false" {
req.Form[key][i] = lowered
} else {
req.Form[key][i] = val
}
}
}
}

View File

@ -1,46 +0,0 @@
package http
import (
"net/http"
"testing"
)
type NilResponseWriter struct{}
func (w NilResponseWriter) Header() http.Header {
return http.Header{}
}
func (w NilResponseWriter) Write(data []byte) (int, error) {
return 0, nil
}
func (w NilResponseWriter) WriteHeader(code int) {
return
}
type FunctionHandler struct {
f func(*http.Request)
}
func (h FunctionHandler) ServeHTTP(w http.ResponseWriter, r *http.Request) {
h.f(r)
}
func TestQueryParamsLowered(t *testing.T) {
assertFunc := func(req *http.Request) {
if len(req.Form["One"]) != 1 || req.Form["One"][0] != "true" {
t.Errorf("Unexpected value for One: %s", req.Form["One"])
} else if len(req.Form["TWO"]) != 1 || req.Form["TWO"][0] != "false" {
t.Errorf("Unexpected value for TWO")
} else if len(req.Form["three"]) != 2 || req.Form["three"][0] != "true" || req.Form["three"][1] != "false" {
t.Errorf("Unexpected value for three")
}
}
assertHdlr := FunctionHandler{assertFunc}
hdlr := NewLowerQueryParamsHandler(assertHdlr)
respWriter := NilResponseWriter{}
req, _ := http.NewRequest("GET", "http://example.com?One=TRUE&TWO=False&three=true&three=FALSE", nil)
hdlr.ServeHTTP(respWriter, req)
}

View File

@ -1,44 +0,0 @@
package log
import (
golog "github.com/coreos/etcd/third_party/github.com/coreos/go-log/log"
"os"
)
// The Verbose flag turns on verbose logging.
var Verbose bool = false
var logger *golog.Logger = golog.New("etcd", false,
golog.CombinedSink(os.Stdout, "[%s] %s %-9s | %s\n", []string{"prefix", "time", "priority", "message"}))
func Infof(format string, v ...interface{}) {
logger.Infof(format, v...)
}
func Debugf(format string, v ...interface{}) {
if Verbose {
logger.Debugf(format, v...)
}
}
func Debug(v ...interface{}) {
if Verbose {
logger.Debug(v...)
}
}
func Warnf(format string, v ...interface{}) {
logger.Warningf(format, v...)
}
func Warn(v ...interface{}) {
logger.Warning(v...)
}
func Fatalf(format string, v ...interface{}) {
logger.Fatalf(format, v...)
}
func Fatal(v ...interface{}) {
logger.Fatalln(v...)
}

View File

@ -1,42 +0,0 @@
// Package metrics provides both a means of generating metrics and the ability
// to send metric data to a graphite endpoint.
// The usage of this package without providing a graphite_addr when calling
// NewBucket results in NOP metric objects. No data will be collected.
package metrics
import (
"io"
gometrics "github.com/coreos/etcd/third_party/github.com/rcrowley/go-metrics"
)
type Timer gometrics.Timer
type Gauge gometrics.Gauge
type Bucket interface {
// If a timer exists in this Bucket, return it. Otherwise, create
// a new timer with the given name and store it in this Bucket.
// The returned object will fulfull the Timer interface.
Timer(name string) Timer
// This acts similarly to Timer, but with objects that fufill the
// Gauge interface.
Gauge(name string) Gauge
// Write the current state of all Metrics in a human-readable format
// to the provide io.Writer.
Dump(io.Writer)
// Instruct the Bucket to periodically push all metric data to the
// provided graphite endpoint.
Publish(string) error
}
// Create a new Bucket object that periodically
func NewBucket(name string) Bucket {
if name == "" {
return nilBucket{}
}
return newStandardBucket(name)
}

View File

@ -1,25 +0,0 @@
package metrics
import (
"io"
gometrics "github.com/coreos/etcd/third_party/github.com/rcrowley/go-metrics"
)
type nilBucket struct{}
func (nmb nilBucket) Dump(w io.Writer) {
return
}
func (nmb nilBucket) Timer(name string) Timer {
return gometrics.NilTimer{}
}
func (nmf nilBucket) Gauge(name string) Gauge {
return gometrics.NilGauge{}
}
func (nmf nilBucket) Publish(string) error {
return nil
}

View File

@ -1,86 +0,0 @@
package metrics
import (
"io"
"net"
"sync"
"time"
gometrics "github.com/coreos/etcd/third_party/github.com/rcrowley/go-metrics"
)
const (
// RuntimeMemStatsSampleInterval is the interval in seconds at which the
// Go runtime's memory statistics will be gathered.
RuntimeMemStatsSampleInterval = time.Duration(2) * time.Second
// GraphitePublishInterval is the interval in seconds at which all
// gathered statistics will be published to a Graphite endpoint.
GraphitePublishInterval = time.Duration(2) * time.Second
)
type standardBucket struct {
sync.Mutex
name string
registry gometrics.Registry
timers map[string]Timer
gauges map[string]Gauge
}
func newStandardBucket(name string) standardBucket {
registry := gometrics.NewRegistry()
gometrics.RegisterRuntimeMemStats(registry)
go gometrics.CaptureRuntimeMemStats(registry, RuntimeMemStatsSampleInterval)
return standardBucket{
name: name,
registry: registry,
timers: make(map[string]Timer),
gauges: make(map[string]Gauge),
}
}
func (smb standardBucket) Dump(w io.Writer) {
gometrics.WriteOnce(smb.registry, w)
return
}
func (smb standardBucket) Timer(name string) Timer {
smb.Lock()
defer smb.Unlock()
timer, ok := smb.timers[name]
if !ok {
timer = gometrics.NewTimer()
smb.timers[name] = timer
smb.registry.Register(name, timer)
}
return timer
}
func (smb standardBucket) Gauge(name string) Gauge {
smb.Lock()
defer smb.Unlock()
gauge, ok := smb.gauges[name]
if !ok {
gauge = gometrics.NewGauge()
smb.gauges[name] = gauge
smb.registry.Register(name, gauge)
}
return gauge
}
func (smb standardBucket) Publish(graphite_addr string) error {
addr, err := net.ResolveTCPAddr("tcp", graphite_addr)
if err != nil {
return err
}
go gometrics.Graphite(smb.registry, GraphitePublishInterval, smb.name, addr)
return nil
}

View File

@ -1,10 +0,0 @@
## Etcd modules
etcd modules (mods) are higher order pieces of functionality that only
speak to the client etcd API and are presented in the `/mod` HTTP path
of the etcd service.
The basic idea is that etcd can ship things like dashboards, master
election APIs and other helpful services that would normally have to
stand up and talk to an etcd cluster directly in the binary. It is a
convienence and hopefully eases complexity in deployments.

View File

@ -1,3 +0,0 @@
{
"directory": "app/bower_components"
}

View File

@ -1,21 +0,0 @@
# EditorConfig helps developers define and maintain consistent
# coding styles between different editors and IDEs
# editorconfig.org
root = true
[*]
# Change these settings to your own preference
indent_style = space
indent_size = 2
# We recommend you to keep these unchanged
end_of_line = lf
charset = utf-8
trim_trailing_whitespace = true
insert_final_newline = true
[*.md]
trim_trailing_whitespace = false

View File

@ -1 +0,0 @@
* text=auto

View File

@ -1,6 +0,0 @@
node_modules
dist
.tmp
.sass-cache
app/bower_components
/go-bindata

View File

@ -1,3 +0,0 @@
app/scripts/vega.js
app/scripts/moment.min.js
app/scripts/ng-time-relative.min.js

View File

@ -1,27 +0,0 @@
{
"node": true,
"browser": true,
"esnext": true,
"bitwise": true,
"camelcase": true,
"curly": true,
"eqeqeq": true,
"immed": true,
"indent": 2,
"latedef": true,
"newcap": true,
"noarg": true,
"quotmark": "single",
"regexp": true,
"undef": true,
"unused": false,
"strict": true,
"trailing": true,
"smarttabs": true,
"globals": {
"angular": false,
"$": false,
"vg": false,
"moment": false
}
}

View File

@ -1,7 +0,0 @@
language: node_js
node_js:
- '0.8'
- '0.10'
before_script:
- 'npm install -g bower grunt-cli'
- 'bower install'

View File

@ -1,355 +0,0 @@
// Generated on 2013-10-07 using generator-webapp 0.4.3
'use strict';
// # Globbing
// for performance reasons we're only matching one level down:
// 'test/spec/{,*/}*.js'
// use this if you want to recursively match all subfolders:
// 'test/spec/**/*.js'
module.exports = function (grunt) {
// show elapsed time at the end
require('time-grunt')(grunt);
// load all grunt tasks
require('load-grunt-tasks')(grunt);
grunt.initConfig({
// configurable paths
uglify: {
options: {
mangle: false
},
},
yeoman: {
app: 'app',
dist: 'dist'
},
watch: {
compass: {
files: ['<%= yeoman.app %>/styles/{,*/}*.{scss,sass}'],
tasks: ['compass:server', 'autoprefixer']
},
styles: {
files: ['<%= yeoman.app %>/styles/{,*/}*.css'],
tasks: ['copy:styles', 'autoprefixer']
},
livereload: {
options: {
livereload: '<%= connect.options.livereload %>'
},
files: [
'<%= yeoman.app %>/*.html',
'.tmp/styles/{,*/}*.css',
'{.tmp,<%= yeoman.app %>}/scripts/{,*/}*.js',
'<%= yeoman.app %>/images/{,*/}*.{png,jpg,jpeg,gif,webp,svg}'
]
}
},
connect: {
options: {
port: 9000,
livereload: 35729,
// change this to '0.0.0.0' to access the server from outside
hostname: 'localhost'
},
livereload: {
options: {
open: true,
base: [
'.tmp',
'<%= yeoman.app %>'
]
}
},
test: {
options: {
base: [
'.tmp',
'test',
'<%= yeoman.app %>'
]
}
},
dist: {
options: {
open: true,
base: '<%= yeoman.dist %>'
}
}
},
clean: {
dist: {
files: [{
dot: true,
src: [
'.tmp',
'<%= yeoman.dist %>/*',
'!<%= yeoman.dist %>/.git*'
]
}]
},
server: '.tmp'
},
jshint: {
options: {
jshintrc: '.jshintrc'
},
all: [
'<%= yeoman.app %>/scripts/{,*/}*.js',
'!<%= yeoman.app %>/scripts/vendor/*',
]
},
mocha: {
all: {
options: {
run: true,
urls: ['http://<%= connect.test.options.hostname %>:<%= connect.test.options.port %>/index.html']
}
}
},
compass: {
options: {
sassDir: '<%= yeoman.app %>/styles',
cssDir: '.tmp/styles',
generatedImagesDir: '.tmp/images/generated',
imagesDir: '<%= yeoman.app %>/images',
javascriptsDir: '<%= yeoman.app %>/scripts',
fontsDir: '<%= yeoman.app %>/styles/fonts',
importPath: '<%= yeoman.app %>/bower_components',
httpImagesPath: '/images',
httpGeneratedImagesPath: '/images/generated',
httpFontsPath: '/styles/fonts',
relativeAssets: false,
assetCacheBuster: false
},
dist: {
options: {
generatedImagesDir: '<%= yeoman.dist %>/images/generated'
}
},
server: {
options: {
debugInfo: true
}
}
},
autoprefixer: {
options: {
browsers: ['last 1 version']
},
dist: {
files: [{
expand: true,
cwd: '.tmp/styles/',
src: '{,*/}*.css',
dest: '.tmp/styles/'
}]
}
},
// not used since Uglify task does concat,
// but still available if needed
/*concat: {
dist: {}
},*/
requirejs: {
dist: {
// Options: https://github.com/jrburke/r.js/blob/master/build/example.build.js
options: {
// `name` and `out` is set by grunt-usemin
baseUrl: '<%= yeoman.app %>/scripts',
optimize: 'none',
// TODO: Figure out how to make sourcemaps work with grunt-usemin
// https://github.com/yeoman/grunt-usemin/issues/30
//generateSourceMaps: true,
// required to support SourceMaps
// http://requirejs.org/docs/errors.html#sourcemapcomments
preserveLicenseComments: false,
useStrict: true,
wrap: true
//uglify2: {} // https://github.com/mishoo/UglifyJS2
}
}
},
useminPrepare: {
options: {
dest: '<%= yeoman.dist %>'
},
html: ['<%= yeoman.app %>/index.html']
},
usemin: {
options: {
dirs: ['<%= yeoman.dist %>']
},
html: ['<%= yeoman.dist %>/{,*/}*.html'],
css: ['<%= yeoman.dist %>/styles/{,*/}*.css']
},
imagemin: {
dist: {
files: [{
expand: true,
cwd: '<%= yeoman.app %>/images',
src: '{,*/}*.{png,jpg,jpeg}',
dest: '<%= yeoman.dist %>/images'
}]
}
},
svgmin: {
dist: {
files: [{
expand: true,
cwd: '<%= yeoman.app %>/images',
src: '{,*/}*.svg',
dest: '<%= yeoman.dist %>/images'
}]
}
},
cssmin: {
// This task is pre-configured if you do not wish to use Usemin
// blocks for your CSS. By default, the Usemin block from your
// `index.html` will take care of minification, e.g.
//
// <!-- build:css({.tmp,app}) styles/main.css -->
//
// dist: {
// files: {
// '<%= yeoman.dist %>/styles/main.css': [
// '.tmp/styles/{,*/}*.css',
// '<%= yeoman.app %>/styles/{,*/}*.css'
// ]
// }
// }
},
htmlmin: {
dist: {
options: {
/*removeCommentsFromCDATA: true,
// https://github.com/yeoman/grunt-usemin/issues/44
//collapseWhitespace: true,
collapseBooleanAttributes: true,
removeAttributeQuotes: true,
removeRedundantAttributes: true,
useShortDoctype: true,
removeEmptyAttributes: true,
removeOptionalTags: true*/
},
files: [{
expand: true,
cwd: '<%= yeoman.app %>',
src: '*.html',
dest: '<%= yeoman.dist %>'
}]
}
},
ngmin: {
dist: {
src: '.tmp/concat/scripts/app.js',
dest: '.tmp/concat/scripts/app.js'
}
},
// Put files not handled in other tasks here
copy: {
dist: {
files: [{
expand: true,
dot: true,
cwd: '<%= yeoman.app %>',
dest: '<%= yeoman.dist %>',
src: [
'*.{ico,png,txt}',
'.htaccess',
'images/{,*/}*.{webp,gif,svg}',
'styles/fonts/{,*/}*.*',
'views/*.*',
//'index.html',
'bower_components/sass-bootstrap/fonts/*.*'
]
}]
},
styles: {
expand: true,
dot: true,
cwd: '<%= yeoman.app %>/styles',
dest: '.tmp/styles/',
src: '{,*/}*.css'
}
},
modernizr: {
devFile: '<%= yeoman.app %>/bower_components/modernizr/modernizr.js',
outputFile: '<%= yeoman.dist %>/bower_components/modernizr/modernizr.js',
files: [
'<%= yeoman.dist %>/scripts/{,*/}*.js',
'<%= yeoman.dist %>/styles/{,*/}*.css',
'!<%= yeoman.dist %>/scripts/vendor/*'
],
uglify: true
},
concurrent: {
server: [
'compass',
'copy:styles'
],
test: [
'copy:styles'
],
dist: [
//'compass',
'copy:styles',
'imagemin',
'svgmin',
'htmlmin'
]
},
bower: {
options: {
exclude: ['modernizr']
},
all: {
rjsConfig: '<%= yeoman.app %>/scripts/main.js'
}
}
});
grunt.registerTask('server', function (target) {
if (target === 'dist') {
return grunt.task.run(['build', 'connect:dist:keepalive']);
}
grunt.task.run([
'clean:server',
'concurrent:server',
'autoprefixer',
'connect:livereload',
'watch'
]);
});
grunt.registerTask('test', [
'clean:server',
'concurrent:test',
'autoprefixer',
'connect:test',
'mocha'
]);
grunt.registerTask('build', [
'clean:dist',
'jshint',
'useminPrepare',
'concurrent:dist',
'autoprefixer',
'concat',
'cssmin',
'ngmin',
'usemin',
'uglify',
'copy:dist'
]);
grunt.registerTask('default', [
'jshint',
'test',
'build'
]);
};

View File

@ -1,202 +0,0 @@
Apache License
Version 2.0, January 2004
http://www.apache.org/licenses/
TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
1. Definitions.
"License" shall mean the terms and conditions for use, reproduction,
and distribution as defined by Sections 1 through 9 of this document.
"Licensor" shall mean the copyright owner or entity authorized by
the copyright owner that is granting the License.
"Legal Entity" shall mean the union of the acting entity and all
other entities that control, are controlled by, or are under common
control with that entity. For the purposes of this definition,
"control" means (i) the power, direct or indirect, to cause the
direction or management of such entity, whether by contract or
otherwise, or (ii) ownership of fifty percent (50%) or more of the
outstanding shares, or (iii) beneficial ownership of such entity.
"You" (or "Your") shall mean an individual or Legal Entity
exercising permissions granted by this License.
"Source" form shall mean the preferred form for making modifications,
including but not limited to software source code, documentation
source, and configuration files.
"Object" form shall mean any form resulting from mechanical
transformation or translation of a Source form, including but
not limited to compiled object code, generated documentation,
and conversions to other media types.
"Work" shall mean the work of authorship, whether in Source or
Object form, made available under the License, as indicated by a
copyright notice that is included in or attached to the work
(an example is provided in the Appendix below).
"Derivative Works" shall mean any work, whether in Source or Object
form, that is based on (or derived from) the Work and for which the
editorial revisions, annotations, elaborations, or other modifications
represent, as a whole, an original work of authorship. For the purposes
of this License, Derivative Works shall not include works that remain
separable from, or merely link (or bind by name) to the interfaces of,
the Work and Derivative Works thereof.
"Contribution" shall mean any work of authorship, including
the original version of the Work and any modifications or additions
to that Work or Derivative Works thereof, that is intentionally
submitted to Licensor for inclusion in the Work by the copyright owner
or by an individual or Legal Entity authorized to submit on behalf of
the copyright owner. For the purposes of this definition, "submitted"
means any form of electronic, verbal, or written communication sent
to the Licensor or its representatives, including but not limited to
communication on electronic mailing lists, source code control systems,
and issue tracking systems that are managed by, or on behalf of, the
Licensor for the purpose of discussing and improving the Work, but
excluding communication that is conspicuously marked or otherwise
designated in writing by the copyright owner as "Not a Contribution."
"Contributor" shall mean Licensor and any individual or Legal Entity
on behalf of whom a Contribution has been received by Licensor and
subsequently incorporated within the Work.
2. Grant of Copyright License. Subject to the terms and conditions of
this License, each Contributor hereby grants to You a perpetual,
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
copyright license to reproduce, prepare Derivative Works of,
publicly display, publicly perform, sublicense, and distribute the
Work and such Derivative Works in Source or Object form.
3. Grant of Patent License. Subject to the terms and conditions of
this License, each Contributor hereby grants to You a perpetual,
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
(except as stated in this section) patent license to make, have made,
use, offer to sell, sell, import, and otherwise transfer the Work,
where such license applies only to those patent claims licensable
by such Contributor that are necessarily infringed by their
Contribution(s) alone or by combination of their Contribution(s)
with the Work to which such Contribution(s) was submitted. If You
institute patent litigation against any entity (including a
cross-claim or counterclaim in a lawsuit) alleging that the Work
or a Contribution incorporated within the Work constitutes direct
or contributory patent infringement, then any patent licenses
granted to You under this License for that Work shall terminate
as of the date such litigation is filed.
4. Redistribution. You may reproduce and distribute copies of the
Work or Derivative Works thereof in any medium, with or without
modifications, and in Source or Object form, provided that You
meet the following conditions:
(a) You must give any other recipients of the Work or
Derivative Works a copy of this License; and
(b) You must cause any modified files to carry prominent notices
stating that You changed the files; and
(c) You must retain, in the Source form of any Derivative Works
that You distribute, all copyright, patent, trademark, and
attribution notices from the Source form of the Work,
excluding those notices that do not pertain to any part of
the Derivative Works; and
(d) If the Work includes a "NOTICE" text file as part of its
distribution, then any Derivative Works that You distribute must
include a readable copy of the attribution notices contained
within such NOTICE file, excluding those notices that do not
pertain to any part of the Derivative Works, in at least one
of the following places: within a NOTICE text file distributed
as part of the Derivative Works; within the Source form or
documentation, if provided along with the Derivative Works; or,
within a display generated by the Derivative Works, if and
wherever such third-party notices normally appear. The contents
of the NOTICE file are for informational purposes only and
do not modify the License. You may add Your own attribution
notices within Derivative Works that You distribute, alongside
or as an addendum to the NOTICE text from the Work, provided
that such additional attribution notices cannot be construed
as modifying the License.
You may add Your own copyright statement to Your modifications and
may provide additional or different license terms and conditions
for use, reproduction, or distribution of Your modifications, or
for any such Derivative Works as a whole, provided Your use,
reproduction, and distribution of the Work otherwise complies with
the conditions stated in this License.
5. Submission of Contributions. Unless You explicitly state otherwise,
any Contribution intentionally submitted for inclusion in the Work
by You to the Licensor shall be under the terms and conditions of
this License, without any additional terms or conditions.
Notwithstanding the above, nothing herein shall supersede or modify
the terms of any separate license agreement you may have executed
with Licensor regarding such Contributions.
6. Trademarks. This License does not grant permission to use the trade
names, trademarks, service marks, or product names of the Licensor,
except as required for reasonable and customary use in describing the
origin of the Work and reproducing the content of the NOTICE file.
7. Disclaimer of Warranty. Unless required by applicable law or
agreed to in writing, Licensor provides the Work (and each
Contributor provides its Contributions) on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
implied, including, without limitation, any warranties or conditions
of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
PARTICULAR PURPOSE. You are solely responsible for determining the
appropriateness of using or redistributing the Work and assume any
risks associated with Your exercise of permissions under this License.
8. Limitation of Liability. In no event and under no legal theory,
whether in tort (including negligence), contract, or otherwise,
unless required by applicable law (such as deliberate and grossly
negligent acts) or agreed to in writing, shall any Contributor be
liable to You for damages, including any direct, indirect, special,
incidental, or consequential damages of any character arising as a
result of this License or out of the use or inability to use the
Work (including but not limited to damages for loss of goodwill,
work stoppage, computer failure or malfunction, or any and all
other commercial damages or losses), even if such Contributor
has been advised of the possibility of such damages.
9. Accepting Warranty or Additional Liability. While redistributing
the Work or Derivative Works thereof, You may choose to offer,
and charge a fee for, acceptance of support, warranty, indemnity,
or other liability obligations and/or rights consistent with this
License. However, in accepting such obligations, You may act only
on Your own behalf and on Your sole responsibility, not on behalf
of any other Contributor, and only if You agree to indemnify,
defend, and hold each Contributor harmless for any liability
incurred by, or claims asserted against, such Contributor by reason
of your accepting any such warranty or additional liability.
END OF TERMS AND CONDITIONS
APPENDIX: How to apply the Apache License to your work.
To apply the Apache License to your work, attach the following
boilerplate notice, with the fields enclosed by brackets "[]"
replaced with your own identifying information. (Don't include
the brackets!) The text should be enclosed in the appropriate
comment syntax for the file format. We also recommend that a
file or class name and description of purpose be included on the
same "printed page" as the copyright notice for easier
identification within third-party archives.
Copyright [yyyy] [name of copyright owner]
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.

View File

@ -1,29 +0,0 @@
# etcd Dashboard
## Developing
If you'd like to contribute to the etcd dashboard mod, follow these instructions. For contributing to the rest of etcd, see the contributing document in the root of the repository.
### Install yeoman
http://yeoman.io/
### Install NPM locally
```
npm install
```
### Install Bower Components
```
bower install
```
### View in Browser
run `export ETCD_DASHBOARD_DIR=/absolute/path/to/coreos/etcd/mod/dashboard/app`
Run etcd like you normally would and afterward browse to:
http://localhost:4001/mod/dashboard/

View File

@ -1,7 +0,0 @@
<svg version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
preserveAspectRatio="xMinYMin" viewBox="0 0 72.556 61" enable-background="new 0 0 72.556 61" xml:space="preserve">
<path d="M34.521,8v11.088v23v10.737c0,2.209,1.791,4,4,4c2.209,0,4-1.791,4-4V42.067V19.109V8c0-2.209-1.791-4-4-4
C36.312,4,34.521,5.791,34.521,8z"/>
<path d="M16.109,34.412h11.088h23h10.737c2.209,0,4-1.791,4-4c0-2.209-1.791-4-4-4H50.175H27.217H16.109c-2.209,0-4,1.791-4,4
C12.109,32.621,13.9,34.412,16.109,34.412z"/>
</svg>

Before

Width:  |  Height:  |  Size: 561 B

View File

@ -1,6 +0,0 @@
<svg version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
preserveAspectRatio="xMinYMin" viewBox="0 0 73.356 61" enable-background="new 0 0 73.356 61" xml:space="preserve">
<path d="M5.27,33.226l22.428,22.428c1.562,1.562,4.095,1.562,5.657,0c1.562-1.562,1.562-4.095,0-5.657L17.77,34.413h48.514
c2.209,0,4-1.791,4-4s-1.791-4-4-4H17.749l15.604-15.582c1.563-1.561,1.565-4.094,0.004-5.657C32.576,4.391,31.552,4,30.527,4
c-1.023,0-2.046,0.39-2.827,1.169L5.272,27.567c-0.751,0.75-1.173,1.768-1.173,2.829C4.098,31.458,4.52,32.476,5.27,33.226z"/>
</svg>

Before

Width:  |  Height:  |  Size: 608 B

View File

@ -1,7 +0,0 @@
<svg version="1.1" fill="#f00" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink"
x="0px" y="0px" preserveAspectRatio="xMinYMin" viewBox="0 0 76.143 61" enable-background="new 0 0 76.143 61" xml:space="preserve">
<path d="M49.41,13.505l-6.035,6.035L27.112,35.803l-6.035,6.035c-1.562,1.562-1.562,4.095,0,5.657c1.562,1.562,4.095,1.562,5.657,0
l6.05-6.05l16.234-16.234l6.05-6.05c1.562-1.562,1.562-4.095,0-5.657C53.505,11.943,50.972,11.943,49.41,13.505z"/>
<path d="M21.077,19.162l6.035,6.035L43.375,41.46l6.035,6.035c1.562,1.562,4.095,1.562,5.657,0c1.562-1.562,1.562-4.095,0-5.657
l-6.05-6.05L32.783,19.555l-6.05-6.05c-1.562-1.562-4.095-1.562-5.657,0C19.515,15.067,19.515,17.6,21.077,19.162z"/>
</svg>

Before

Width:  |  Height:  |  Size: 749 B

View File

@ -1,46 +0,0 @@
<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
preserveAspectRatio="xMinYMin" viewBox="0 0 792 306" enable-background="new 0 0 792 306" xml:space="preserve">
<g>
<g>
<path fill="#53A3DA" d="M136.168,45.527C76.898,45.527,28.689,93.739,28.689,153c0,59.265,48.209,107.474,107.479,107.474
c59.252,0,107.465-48.209,107.465-107.474C243.633,93.739,195.42,45.527,136.168,45.527z"/>
<path fill="#F1606D" d="M136.168,55.389c-17.283,0-31.941,27.645-37.235,66.069c-0.169,1.236-0.333,2.487-0.478,3.746
c-0.723,6.047-1.213,12.335-1.458,18.808c-0.117,2.962-0.175,5.956-0.175,8.988c0,3.029,0.058,6.029,0.175,8.985
c0.245,6.472,0.735,12.764,1.458,18.811c8.104,1.049,16.769,1.761,25.807,2.099c3.907,0.146,7.872,0.233,11.907,0.233
c4.023,0,8-0.088,11.895-0.233c9.049-0.338,17.708-1.05,25.819-2.099c0.892-0.114,1.77-0.239,2.659-0.368
c33.754-4.74,57.235-15.232,57.235-27.428C233.776,99.088,190.071,55.389,136.168,55.389z"/>
<path fill="#FFFFFF" d="M176.541,125.569c-0.979-1.428-2.029-2.796-3.148-4.11c-8.956-10.557-22.297-17.265-37.224-17.265
c-4.839,0-9.148,7.407-11.907,18.909c-1.096,4.586-1.947,9.819-2.495,15.498c-0.432,4.551-0.665,9.391-0.665,14.399
s0.233,9.849,0.665,14.396c4.554,0.432,9.387,0.664,14.402,0.664c5.009,0,9.842-0.232,14.396-0.664
c10.011-0.95,18.653-2.875,24.775-5.411c6.046-2.501,9.624-5.615,9.624-8.985C184.963,142.832,181.858,133.388,176.541,125.569z"
/>
</g>
<g>
<path fill="#231F20" d="M344.891,100.053c12.585,0,22.816,6.138,29.262,13.062l-10.064,11.326
c-5.353-5.192-11.175-8.495-19.041-8.495c-16.839,0-28.953,14.16-28.953,37.291c0,23.448,11.169,37.608,28.32,37.608
c9.128,0,15.895-3.775,21.717-10.228l10.067,11.169c-8.335,9.598-19.038,14.95-32.099,14.95c-26.119,0-46.731-18.88-46.731-53.025
C297.37,120.036,318.454,100.053,344.891,100.053z"/>
<path fill="#231F20" d="M416.961,125.701c19.352,0,36.822,14.793,36.822,40.597c0,25.647-17.471,40.439-36.822,40.439
c-19.197,0-36.66-14.792-36.66-40.439C380.301,140.494,397.764,125.701,416.961,125.701z M416.961,191.945
c11.33,0,18.25-10.228,18.25-25.647c0-15.577-6.92-25.804-18.25-25.804s-18.094,10.227-18.094,25.804
C398.867,181.717,405.631,191.945,416.961,191.945z"/>
<path fill="#231F20" d="M459.771,127.589h14.943l1.26,13.688h0.629c5.506-10.07,13.691-15.577,21.871-15.577
c3.938,0,6.455,0.472,8.811,1.574l-3.148,15.734c-2.67-0.784-4.717-1.257-8.018-1.257c-6.139,0-13.539,4.245-18.256,15.893v47.203
h-18.092V127.589z"/>
<path fill="#231F20" d="M541.121,125.701c20.928,0,31.941,15.107,31.941,36.667c0,3.458-0.314,6.604-0.787,8.495h-49.09
c1.57,14.003,10.379,21.869,22.811,21.869c6.613,0,12.273-2.041,17.941-5.662l6.135,11.326
c-7.395,4.878-16.676,8.341-26.432,8.341c-21.404,0-38.08-14.95-38.08-40.439C505.561,141.12,523.023,125.701,541.121,125.701z
M557.326,159.376c0-12.277-5.189-19.671-15.732-19.671c-9.125,0-16.996,6.768-18.57,19.671H557.326z"/>
<path fill="#F1606D" d="M600.602,152.607c0-32.729,17.785-53.344,42.799-53.344c24.863,0,42.641,20.615,42.641,53.344
c0,32.889-17.777,54.13-42.641,54.13C618.387,206.737,600.602,185.496,600.602,152.607z M678.49,152.607
c0-28.639-14.158-46.731-35.09-46.731c-21.084,0-35.248,18.093-35.248,46.731c0,28.796,14.164,47.521,35.248,47.521
C664.332,200.128,678.49,181.403,678.49,152.607z"/>
<path fill="#53A4D9" d="M699.738,186.125c7.557,8.495,18.412,14.003,30.529,14.003c15.732,0,25.807-8.499,25.807-20.767
c0-12.904-8.494-17.154-18.723-21.717l-15.736-7.082c-8.969-3.936-20.934-10.385-20.934-25.808
c0-14.947,12.904-25.492,30.059-25.492c12.588,0,22.658,5.665,28.949,12.435l-4.244,4.878c-5.982-6.452-14.32-10.7-24.705-10.7
c-13.691,0-22.816,7.239-22.816,18.565c0,11.962,10.385,16.521,17.936,19.985l15.738,6.921
c11.486,5.195,21.713,11.647,21.713,27.539s-13.061,27.851-33.201,27.851c-15.107,0-26.75-6.451-34.932-15.576L699.738,186.125z"
/>
</g>
</g>
</svg>

Before

Width:  |  Height:  |  Size: 4.1 KiB

View File

@ -1,64 +0,0 @@
<!DOCTYPE html>
<html class="no-js" ng-app="etcdControlPanel" ng-controller="RootCtrl">
<head>
<meta charset="utf-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<title>etcd dashboard</title>
<meta name="description" content="">
<meta name="viewport" content="width=device-width">
<link href="http://fonts.googleapis.com/css?family=Source+Sans+Pro:200,300,400,400italic,600,700,900" rel="stylesheet" type="text/css">
<link href="http://fonts.googleapis.com/css?family=Source+Code+Pro:400,500,600,700" rel="stylesheet" type="text/css">
<!-- build:css styles/styles.css -->
<link rel="stylesheet" href="styles/bootstrap.css">
<link rel="stylesheet" href="styles/main.css">
<link rel="stylesheet" href="styles/browser.css">
<link rel="stylesheet" href="styles/stats.css">
<link rel="stylesheet" href="styles/etcd-widgets.css">
<!-- endbuild -->
</head>
<body>
<h1>etcd Dashboard</h1>
<div id="view-container" ng-view></div>
<div id="footer">
<div id="powered-by" class="text-center">Powered by <a href="https://github.com/coreos/etcd" tabindex="-1">etcd</a></div>
<div id="coreos-logo">
<a href="http://coreos.com" tabindex="-1"><img src="images/logo.svg"/></a>
</div>
</div>
<!-- build:js scripts/modules.js -->
<script src="bower_components/jquery/jquery.js"></script>
<script src="bower_components/angular/angular.js"></script>
<script src="bower_components/angular-resource/angular-resource.js"></script>
<script src="bower_components/angular-route/angular-route.js"></script>
<script src="bower_components/angular-cookies/angular-cookies.js"></script>
<script src="bower_components/angular-sanitize/angular-sanitize.js"></script>
<script src="bower_components/d3/d3.js"></script>
<script src="bower_components/underscore/underscore.js"></script>
<script src="bower_components/underscore.string/lib/underscore.string.js"></script>
<script src="bower_components/moment/moment.js"></script>
<script src="scripts/vega.js"></script>
<script src="scripts/ng-time-relative.min.js"></script>
<!-- endbuild -->
<!-- build:js scripts/app.js -->
<script src="scripts/app.js"></script>
<script src="scripts/controllers/root.js"></script>
<script src="scripts/directives.js"></script>
<script src="scripts/shims.js"></script>
<script src="scripts/controllers/home.js"></script>
<script src="scripts/controllers/browser.js"></script>
<script src="scripts/common/services/etcd.js"></script>
<script src="scripts/common/services/prefix-url.js"></script>
<script src="scripts/common/directives/highlight.js"></script>
<script src="scripts/common/directives/enter.js"></script>
<script src="scripts/common/services/etcd.js"></script>
<script src="scripts/controllers/stats.js"></script>
<!-- endbuild -->
</body>
</html>

View File

@ -1,43 +0,0 @@
'use strict';
var app = angular.module('etcdControlPanel', [
'ngRoute',
'ngResource',
'etcd',
'etcdDirectives',
'timeRelative',
'underscore',
'jquery',
'moment',
'vg'
]);
app.constant('urlPrefix', '/mod/dashboard');
app.constant('keyPrefix', '/v2/keys/');
app.config(function($routeProvider, $locationProvider, urlPrefix) {
function prefixUrl(url) {
return urlPrefix + url;
}
$locationProvider.html5Mode(true);
$routeProvider
.when(prefixUrl('/'), {
controller: 'HomeCtrl',
templateUrl: prefixUrl('/views/home.html')
})
.when(prefixUrl('/stats'), {
controller: 'StatsCtrl',
templateUrl: prefixUrl('/views/stats.html')
})
.when(prefixUrl('/browser'), {
controller: 'BrowserCtrl',
templateUrl: prefixUrl('/views/browser.html')
})
.otherwise({
templateUrl: prefixUrl('/404.html')
});
});

View File

@ -1,16 +0,0 @@
'use strict';
angular.module('etcdControlPanel')
.directive('ngEnter', function() {
return function(scope, element, attrs) {
element.bind('keydown keypress', function(event) {
if(event.which === 13) {
scope.$apply(function(){
scope.$eval(attrs.ngEnter);
});
event.preventDefault();
}
});
};
});

View File

@ -1,19 +0,0 @@
'use strict';
angular.module('etcdControlPanel')
.directive('highlight', function(keyPrefix) {
return {
restrict: 'E',
scope: {
highlightBase: '=',
highlightCurrent: '='
},
link: function(scope, element, attrs) {
var base = _.str.strRight(scope.highlightBase, keyPrefix),
current = _.str.trim(scope.highlightCurrent, '/');
if (base === current) {
element.parent().parent().addClass('etcd-selected');
}
}
};
});

View File

@ -1,103 +0,0 @@
'use strict';
angular.module('etcd', [])
.factory('EtcdV2', ['$http', '$q', function($http, $q) {
var keyPrefix = '/v2/keys/'
var statsPrefix = '/v2/stats/'
var baseURL = '/v2/'
var leaderURL = ''
delete $http.defaults.headers.common['X-Requested-With'];
function cleanupPath(path) {
var parts = path.split('/');
if (parts.length === 0) {
return '';
}
parts = parts.filter(function(v){return v!=='';});
parts = parts.join('/');
return parts
}
function newKey(keyName) {
var self = {};
self.name = cleanupPath(keyName);
self.getParent = function() {
var parts = self.name.split('/');
if (parts.length === 0) {
return newKey('');
}
parts.pop();
return newKey(parts.join('/'));
};
self.path = function() {
var path = '/' + cleanupPath(keyPrefix + self.name);
if (path === keyPrefix.substring(0, keyPrefix.length - 1)) {
return keyPrefix
}
return path
};
self.get = function() {
return $http.get(self.path());
};
self.set = function(keyValue) {
return getLeader().then(function(leader) {
return $http({
url: leader + self.path(),
data: $.param({value: keyValue}),
method: 'PUT',
headers: {'Content-Type': 'application/x-www-form-urlencoded'}
});
});
};
self.deleteKey = function(keyValue) {
return getLeader().then(function(leader) {
return $http({
url: leader + self.path(),
method: 'DELETE',
headers: {'Content-Type': 'application/x-www-form-urlencoded'}
});
});
};
return self;
}
function newStat(statName) {
var self = {};
self.name = cleanupPath(statName);
self.path = function() {
return '/' + cleanupPath(statsPrefix + self.name);
};
self.get = function() {
return $http.get(self.path());
};
return self
}
function getLeader() {
return newStat('leader').get().then(function(response) {
return newKey('/_etcd/machines/' + response.data.leader).get().then(function(response) {
// TODO: do something better here p.s. I hate javascript
var data = decodeURIComponent(response.data.node.value);
data = data.replace(/&/g, "\",\"").replace(/=/g,"\":\"");
data = JSON.parse('{"' + data + '"}');
return data.etcd;
});
});
}
return {
getStat: newStat,
getKey: newKey,
}
}]);

View File

@ -1,10 +0,0 @@
'use strict';
angular.module('etcdControlPanel')
.factory('prefixUrl', function(urlPrefix) {
return function(url) {
return urlPrefix + url;
}
});

View File

@ -1,156 +0,0 @@
'use strict';
angular.module('etcdControlPanel')
.controller('BrowserCtrl', function ($scope, $window, EtcdV2, keyPrefix, $, _, moment) {
$scope.save = 'etcd-save-hide';
$scope.preview = 'etcd-preview-hide';
$scope.enableBack = true;
$scope.writingNew = false;
$scope.key = null;
$scope.list = [];
// etcdPath is the path to the key that is currenly being looked at.
$scope.etcdPath = keyPrefix;
$scope.inputPath = keyPrefix;
$scope.resetInputPath = function() {
$scope.inputPath = $scope.etcdPath;
};
$scope.setActiveKey = function(key) {
$scope.etcdPath = keyPrefix + _.str.trim(key, '/');
$scope.resetInputPath();
};
$scope.stripPrefix = function(path) {
return _.str.strRight(path, keyPrefix);
};
$scope.onEnter = function() {
var path = $scope.stripPrefix($scope.inputPath);
if (path !== '') {
$scope.setActiveKey(path);
}
};
$scope.updateCurrentKey = function() {
function etcdPathKey() {
return pathKey($scope.etcdPath);
}
function pathKey(path) {
var parts = path.split(keyPrefix);
if (parts.length === 1) {
return '';
}
return parts[1];
}
// Notify everyone of the update
localStorage.setItem('etcdPath', $scope.etcdPath);
$scope.enableBack = true;
//disable back button if at root (/v2/keys/)
if ($scope.etcdPath === keyPrefix) {
$scope.enableBack = false;
}
$scope.key = EtcdV2.getKey(etcdPathKey($scope.etcdPath));
};
$scope.$watch('etcdPath', $scope.updateCurrentKey);
$scope.$watch('key', function() {
if ($scope.writingNew === true) {
return;
}
$scope.key.get().success(function (data, status, headers, config) {
//hide any errors
$('#etcd-browse-error').hide();
// Looking at a directory if we got an array
if (data.dir === true) {
$scope.list = data.node.nodes;
$scope.preview = 'etcd-preview-hide';
} else {
$scope.singleValue = data.node.value;
$scope.preview = 'etcd-preview-reveal';
$scope.key.getParent().get().success(function(data) {
$scope.list = data.node.nodes;
});
}
$scope.previewMessage = 'No key selected.';
}).error(function (data, status, headers, config) {
$scope.previewMessage = 'Key does not exist.';
$scope.showBrowseError(data.message);
});
});
//back button click
$scope.back = function() {
$scope.etcdPath = $scope.key.getParent().path();
$scope.resetInputPath();
$scope.preview = 'etcd-preview-hide';
$scope.writingNew = false;
};
$scope.showSave = function() {
$scope.save = 'etcd-save-reveal';
};
$scope.saveData = function() {
$scope.setActiveKey($scope.stripPrefix($scope.inputPath));
$scope.updateCurrentKey();
// TODO: fixup etcd to allow for empty values
$scope.key.set($scope.singleValue || ' ').then(function(response) {
$scope.save = 'etcd-save-hide';
$scope.preview = 'etcd-preview-hide';
$scope.back();
$scope.writingNew = false;
}, function (response) {
$scope.showSaveError(response.message);
});
};
$scope.deleteKey = function(key) {
$scope.setActiveKey(key);
$scope.updateCurrentKey();
$scope.key.deleteKey().then(function(response) {
//TODO: remove loader
$scope.save = 'etcd-save-hide';
$scope.preview = 'etcd-preview-hide';
$scope.back();
}, function (response) {
//TODO: remove loader
//show errors
$scope.showBrowseError('Could not delete the key');
});
};
$scope.add = function() {
$scope.save = 'etcd-save-reveal';
$scope.preview = 'etcd-preview-reveal';
$scope.singleValue = '';
$('.etcd-browser-path').find('input').focus();
$scope.writingNew = true;
};
$scope.showBrowseError = function(message) {
$('#etcd-browse-error').find('.etcd-popover-content').text('Error: ' + message);
$('#etcd-browse-error').addClass('etcd-popover-right').show();
};
$scope.showSaveError = function(message) {
$('#etcd-save-error').find('.etcd-popover-content').text('Error: ' + message);
$('#etcd-save-error').addClass('etcd-popover-left').show();
};
$scope.getHeight = function() {
return $($window).height();
};
//$scope.$watch($scope.getHeight, function() {
////$('.etcd-container.etcd-browser etcd-body').css('height', $scope.getHeight()-45);
//});
$window.onresize = function(){
$scope.$apply();
};
});

View File

@ -1,3 +0,0 @@
angular.module('etcdControlPanel')
.controller('HomeCtrl', function($scope) {
});

View File

@ -1,9 +0,0 @@
'use strict';
angular.module('etcdControlPanel')
.controller('RootCtrl', function($rootScope, prefixUrl) {
// Expose prefixUrl() function to all.
$rootScope.prefixUrl = prefixUrl;
});

View File

@ -1,210 +0,0 @@
'use strict';
angular.module('etcdControlPanel')
.controller('StatsCtrl', function ($scope, $rootScope, $interval, EtcdV2, statsVega, vg) {
$scope.graphContainer = '#latency';
$scope.graphVisibility = 'etcd-graph-show';
$scope.tableVisibility = 'etcd-table-hide';
//make requests
function readStats() {
EtcdV2.getStat('leader').get().success(function(data) {
$scope.leaderStats = data;
$scope.leaderName = data.leader;
$scope.peers = [];
//hardcode leader stats
$scope.peers.push({
latency: {
average: 0,
current: 0,
minimum: 0,
maximum: 0,
standardDeviation: 0
},
name: data.leader
});
$.each(data.followers, function(index, value) {
value.name = index;
$scope.peers.push(value);
});
//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;
});
drawGraph();
});
}
function drawGraph () {
//hardcoded padding from chart json
var vertPadding = 30;
var horzPadding = 15;
//fetch width and height of graph area
var width = $($scope.graphContainer).width() - horzPadding;
var height = $($scope.graphContainer).height() - vertPadding;
// parse a spec and create a visualization view
function parse(spec) {
vg.parse.spec(spec, function(chart) {
chart({
el: $scope.graphContainer,
data: {
'stats': $scope.peers
}
}).width(width).height(height).update();
});
}
parse(statsVega);
}
$scope.showTable = function() {
$scope.tableVisibility = 'etcd-table-reveal';
};
$scope.showGraph = function() {
$scope.tableVisibility = 'etcd-table-hide';
};
$scope.getHeight = function() {
return $(window).height();
};
$scope.getWidth = function() {
return $(window).width();
};
//$scope.$watch($scope.getHeight, function() {
////$('.etcd-container.etcd-stats .etcd-body').css('height', $scope.getHeight()-5);
//readStats();
//});
$scope.$watch($scope.getWidth, function() {
readStats();
});
window.onresize = function(){
$scope.$apply();
};
$scope.pollPromise = null;
$scope.startPolling = function() {
// Update the graphs live
if ($scope.pollPromise) {
return;
}
$scope.pollPromise = $interval(function() {
readStats();
}, 500);
};
$scope.stopPolling = function() {
$interval.cancel($scope.pollPromise);
$scope.pollPromise = null;
};
// Stop polling when navigating away from a view with this controller.
$rootScope.$on('$routeChangeStart', function () {
$scope.stopPolling();
});
$scope.startPolling();
})
/* statsVega returns the vega configuration for the stats dashboard */
.factory('statsVega', function () {
return {
'padding': {'top': 10, 'left': 5, 'bottom': 40, 'right': 10},
'data': [
{
'name': 'stats'
},
{
'name': 'thresholds',
'values': [50, 100]
}
],
'scales': [
{
'name': 'y',
'type': 'ordinal',
'range': 'height',
'domain': {'data': 'stats', 'field': 'index'}
},
{
'name': 'x',
'range': 'width',
'domainMin': 0,
'domainMax': 100,
'nice': true,
'zero': true,
'domain': {'data': 'stats', 'field': 'data.latency.current'}
},
{
'name': 'color',
'type': 'linear',
'domain': [10, 50, 100, 1000000000],
'range': ['#00DB24', '#FFC000', '#c40022', '#c40022']
}
],
'axes': [
{
'type': 'x',
'scale': 'x',
'ticks': 6,
'name': 'Latency (ms)'
},
{
'type': 'y',
'scale': 'y',
'properties': {
'ticks': {
'stroke': {'value': 'transparent'}
},
'majorTicks': {
'stroke': {'value': 'transparent'}
},
'labels': {
'fill': {'value': 'transparent'}
},
'axis': {
'stroke': {'value': '#333'},
'strokeWidth': {'value': 1}
}
}
}
],
'marks': [
{
'type': 'rect',
'from': {'data': 'stats'},
'properties': {
'enter': {
'x': {'scale': 'x', 'value': 0},
'x2': {'scale': 'x', 'field': 'data.latency.current'},
'y': {'scale': 'y', 'field': 'index', 'offset': -1},
'height': {'value': 3},
'fill': {'scale':'color', 'field':'data.latency.current'}
}
}
},
{
'type': 'symbol',
'from': {'data': 'stats'},
'properties': {
'enter': {
'x': {'scale': 'x', 'field': 'data.latency.current'},
'y': {'scale': 'y', 'field': 'index'},
'size': {'value': 50},
'fill': {'value': '#000'}
}
}
}
]
};
});

Some files were not shown because too many files have changed in this diff Show More