From 48b3e7f2abc1cf339fff318021cfbb30bfffa884 Mon Sep 17 00:00:00 2001 From: Ben Johnson Date: Mon, 21 Oct 2013 16:00:20 -0600 Subject: [PATCH] Add basic config. --- Documentation/external-documentation.md | 105 ++++++++++++++++++++++++ server/config.go | 45 ++++++++++ server/config_test.go | 66 +++++++++++++++ server/tls_config.go | 1 + server/tls_info.go | 1 + server/util.go | 13 +++ 6 files changed, 231 insertions(+) create mode 100644 Documentation/external-documentation.md create mode 100644 server/config.go create mode 100644 server/config_test.go diff --git a/Documentation/external-documentation.md b/Documentation/external-documentation.md new file mode 100644 index 000000000..1051e8674 --- /dev/null +++ b/Documentation/external-documentation.md @@ -0,0 +1,105 @@ +# 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 + +* `-n` - The node name. Defaults to `default-name`. + +### Optional + +* `-c` - The advertised public hostname:port for client communication. Defaults to `127.0.0.1:4001`. +* `-cl` - The listening hostname for client communication. Defaults to advertised ip. +* `-C` - A comma separated list of machines in the cluster (i.e `"203.0.113.101:7001,203.0.113.102:7001"`). +* `-CF` - The file path containing a comma separated list of machines in the cluster. +* `-clientCAFile` - The path of the client CAFile. Enables client cert authentication when present. +* `-clientCert` - The cert file of the client. +* `-clientKey` - The key file of the client. +* `-configfile` - The path of the etcd config file. Defaults to `/etc/etcd/etcd.toml`. +* `-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. +* `-d` - The directory to store log and snapshot. Defaults to the current working directory. +* `-m` - The max size of result buffer. Defaults to `1024`. +* `-maxsize` - The max size of the cluster. Defaults to `9`. +* `-r` - The max retry attempts when trying to join a cluster. Defaults to `3`. +* `-s` - The advertised public hostname:port for server communication. Defaults to `127.0.0.1:7001`. +* `-sl` - The listening hostname for server communication. Defaults to advertised ip. +* `-serverCAFile` - The path of the CAFile. Enables client/peer cert authentication when present. +* `-serverCert` - The cert file of the server. +* `-serverKey` - The key file of the server. +* `-snapshot` - Open or close snapshot. Defaults to `false`. +* `-v` - Enable verbose logging. Defaults to `false`. +* `-vv` - Enable very verbose logging. Defaults to `false`. +* `-version` - Print the version and exit. +* `-w` - The hostname:port of web interface. + +## Configuration File + +The etcd configuration file is written in [TOML](https://github.com/mojombo/toml) +and read from `/etc/etcd/etcd.toml` by default. + +```TOML +[etcd] + advertised_url = "127.0.0.1:4001" + ca_file = "" + cert_file = "" + cors = [] + cpu_profile_file = "" + datadir = "." + key_file = "" + listen_host = "127.0.0.1:4001" + machines = [] + machines_file = "" + max_cluster_size = 9 + max_result_buffer = 1024 + max_retry_attempts = 3 + name = "default-name" + snapshot = false + verbose = false + very_verbose = false + web_url = "" + +[raft] + advertised_url = "127.0.0.1:7001" + ca_file = "" + cert_file = "" + key_file = "" + listen_host = "127.0.0.1:7001" +``` + +## Environment Variables + + * `ETCD_ADVERTISED_URL` + * `ETCD_CA_FILE` + * `ETCD_CERT_FILE` + * `ETCD_CORS` + * `ETCD_CONFIG_FILE` + * `ETCD_CPU_PROFILE_FILE` + * `ETCD_DATADIR` + * `ETCD_KEY_FILE` + * `ETCD_LISTEN_HOST` + * `ETCD_MACHINES` + * `ETCD_MACHINES_FILE` + * `ETCD_MAX_RETRY_ATTEMPTS` + * `ETCD_MAX_CLUSTER_SIZE` + * `ETCD_MAX_RESULTS_BUFFER` + * `ETCD_NAME` + * `ETCD_SNAPSHOT` + * `ETCD_VERBOSE` + * `ETCD_VERY_VERBOSE` + * `ETCD_WEB_URL` + * `ETCD_RAFT_ADVERTISED_URL` + * `ETCD_RAFT_CA_FILE` + * `ETCD_RAFT_CERT_FILE` + * `ETCD_RAFT_KEY_FILE` + * `ETCD_RAFT_LISTEN_HOST` diff --git a/server/config.go b/server/config.go new file mode 100644 index 000000000..cf243dede --- /dev/null +++ b/server/config.go @@ -0,0 +1,45 @@ +package server + +// Config represents the server configuration. +type Config struct { + AdvertisedUrl string `toml:"advertised_url"` + CAFile string `toml:"ca_file"` + CertFile string `toml:"cert_file"` + CPUProfileFile string `toml:"cpu_profile_file"` + Cors []string `toml:"cors"` + CorsWhiteList map[string]bool + DataDir string `toml:"datadir"` + KeyFile string `toml:"key_file"` + ListenHost string `toml:"listen_host"` + Machines []string `toml:"machines"` + MachinesFile string `toml:"machines_file"` + MaxClusterSize int `toml:"max_cluster_size"` + MaxResultBuffer int `toml:"max_result_buffer"` + MaxRetryAttempts int `toml:"max_retry_attempts"` + Name string `toml:"name"` + Snapshot bool `toml:"snapshot"` + Verbose bool `toml:"verbose"` + VeryVerbose bool `toml:"very_verbose"` + WebURL string `toml:"web_url"` + + Peer struct { + AdvertisedUrl string `toml:"advertised_url"` + CAFile string `toml:"ca_file"` + CertFile string `toml:"cert_file"` + KeyFile string `toml:"key_file"` + ListenHost string `toml:"listen_host"` + } +} + +// NewConfig returns a Config initialized with default values. +func NewConfig() *Config { + c := new(Config) + c.AdvertisedUrl = "127.0.0.1:4001" + c.CorsWhiteList = make(map[string]bool) + c.DataDir = "." + c.MaxClusterSize = 9 + c.MaxResultBuffer = 1024 + c.MaxRetryAttempts = 3 + c.Peer.AdvertisedUrl = "127.0.0.1:7001" + return c +} diff --git a/server/config_test.go b/server/config_test.go new file mode 100644 index 000000000..550bffa7e --- /dev/null +++ b/server/config_test.go @@ -0,0 +1,66 @@ +package server + +import ( + "testing" + + "github.com/BurntSushi/toml" + "github.com/stretchr/testify/assert" +) + + +// Ensures that a configuration can be deserialized from TOML. +func TestConfigTOML(t *testing.T) { + content := ` + advertised_url = "127.0.0.1:4002" + ca_file = "/tmp/file.ca" + cert_file = "/tmp/file.cert" + cors = ["*"] + cpu_profile_file = "XXX" + datadir = "/tmp/data" + key_file = "/tmp/file.key" + listen_host = "127.0.0.1:4003" + machines = ["coreos.com:4001", "coreos.com:4002"] + machines_file = "/tmp/machines" + max_cluster_size = 10 + max_result_buffer = 512 + max_retry_attempts = 5 + name = "test-name" + snapshot = true + verbose = true + very_verbose = true + web_url = "/web" + + [peer] + advertised_url = "127.0.0.1:7002" + ca_file = "/tmp/peer/file.ca" + cert_file = "/tmp/peer/file.cert" + key_file = "/tmp/peer/file.key" + listen_host = "127.0.0.1:7003" + ` + c := NewConfig() + _, err := toml.Decode(content, &c) + assert.Nil(t, err, "") + assert.Equal(t, c.AdvertisedUrl, "127.0.0.1:4002", "") + assert.Equal(t, c.CAFile, "/tmp/file.ca", "") + assert.Equal(t, c.CertFile, "/tmp/file.cert", "") + assert.Equal(t, c.CPUProfileFile, "XXX", "") + assert.Equal(t, c.Cors, []string{"*"}, "") + assert.Equal(t, c.DataDir, "/tmp/data", "") + assert.Equal(t, c.KeyFile, "/tmp/file.key", "") + assert.Equal(t, c.ListenHost, "127.0.0.1:4003", "") + assert.Equal(t, c.Machines, []string{"coreos.com:4001", "coreos.com:4002"}, "") + assert.Equal(t, c.MachinesFile, "/tmp/machines", "") + assert.Equal(t, c.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.WebURL, "/web", "") + assert.Equal(t, c.Peer.AdvertisedUrl, "127.0.0.1:7002", "") + assert.Equal(t, c.Peer.CAFile, "/tmp/peer/file.ca", "") + assert.Equal(t, c.Peer.CertFile, "/tmp/peer/file.cert", "") + assert.Equal(t, c.Peer.KeyFile, "/tmp/peer/file.key", "") + assert.Equal(t, c.Peer.ListenHost, "127.0.0.1:7003", "") +} diff --git a/server/tls_config.go b/server/tls_config.go index 4b944626d..29b8fa5e4 100644 --- a/server/tls_config.go +++ b/server/tls_config.go @@ -4,6 +4,7 @@ import ( "crypto/tls" ) +// TLSConfig holds the TLS configuration. type TLSConfig struct { Scheme string Server tls.Config diff --git a/server/tls_info.go b/server/tls_info.go index 91936b090..89ed6f055 100644 --- a/server/tls_info.go +++ b/server/tls_info.go @@ -1,5 +1,6 @@ package server +// TLSInfo holds the SSL certificates paths. type TLSInfo struct { CertFile string `json:"CertFile"` KeyFile string `json:"KeyFile"` diff --git a/server/util.go b/server/util.go index 578c048cc..0fa36b69a 100644 --- a/server/util.go +++ b/server/util.go @@ -6,6 +6,7 @@ import ( "io" "net/http" "net/url" + "strings" "github.com/coreos/etcd/log" ) @@ -31,3 +32,15 @@ func redirect(hostname string, w http.ResponseWriter, req *http.Request) { log.Debugf("Redirect to %s", redirectURL.String()) http.Redirect(w, req, redirectURL.String(), http.StatusTemporaryRedirect) } + +// trimsplit slices s into all substrings separated by sep and returns a +// slice of the substrings between the separator with all leading and trailing +// white space removed, as defined by Unicode. +func trimsplit(s, sep string) []string { + raw := strings.Split(s, ",") + trimmed := make([]string, len(raw)) + for _, r := range raw { + trimmed = append(trimmed, strings.TrimSpace(r)) + } + return trimmed +}