From 1bb3d9be7398ba6089c488a2d16e2407bfa7c709 Mon Sep 17 00:00:00 2001 From: Martin Date: Wed, 20 Jul 2016 11:48:39 +0200 Subject: [PATCH] add command storeconfig add test integration command storeconfig update doc --- docs/basics.md | 25 ++++++++++++++++++++++- docs/user-guide/kv-config.md | 34 ++++++++++++++++++++++--------- glide.lock | 18 +++++++++-------- glide.yaml | 11 ++++++---- integration/consul_test.go | 35 ++++++++++++++++++++++++++++++++ integration/etcd_test.go | 35 ++++++++++++++++++++++++++++++++ traefik.go | 39 ++++++++++++++++++++++++++++++++---- 7 files changed, 170 insertions(+), 27 deletions(-) diff --git a/docs/basics.md b/docs/basics.md index dcce736e5..013990465 100644 --- a/docs/basics.md +++ b/docs/basics.md @@ -293,7 +293,7 @@ Please refer to the [global configuration](/toml/#global-configuration) section ### Arguments -Each argument is described in the help section: +Each argument (and command) is described in the help section: ```bash $ traefik --help @@ -326,3 +326,26 @@ We only need to enable `watch` option to make Træfɪk watch configuration backe Routes to services will be created and updated instantly at any changes. Please refer to the [configuration backends](/toml/#configuration-backends) section to get documentation on it. + +# Commands + +Usage: `traefik [command] [--flag=flag_argument]` + +List of Træfɪk available commands with description :                                                              + +- `version` : Print version  +- `storeconfig` : Store the static traefik configuration into a Key-value stores. Please refer to the [Store Træfɪk configuration](/user-guide/kv-config/#store-trfk-configuration) section to get documentation on it. + +Each command may have related flags. +All those related flags will be displayed with : + +```bash +$ traefik [command] --help +``` + +Note that each command is described at the begining of the help section: + +```bash +$ traefik --help +``` + diff --git a/docs/user-guide/kv-config.md b/docs/user-guide/kv-config.md index 264722e1d..9361cc524 100644 --- a/docs/user-guide/kv-config.md +++ b/docs/user-guide/kv-config.md @@ -55,9 +55,12 @@ whoami4: ## Upload the configuration in the Key-value store We should now fill the store with the Træfɪk global configuration, as we do with a [TOML file configuration](/toml). -To do that, we can send the Key-value pairs via [curl commands](https://www.consul.io/intro/getting-started/kv.html) or via the [Web UI](https://www.consul.io/intro/getting-started/ui.html) +To do that, we can send the Key-value pairs via [curl commands](https://www.consul.io/intro/getting-started/kv.html) or via the [Web UI](https://www.consul.io/intro/getting-started/ui.html). -Here the toml configuration we would like to store in the Key-value Store : +Hopefully, Træfɪk allows automation of this process using the `storeconfig` subcommand. +Please refer to the [store Træfɪk configuration](/user-guide/kv-config/#store-configuration-in-key-value-store) section to get documentation on it. + +Here is the toml configuration we would like to store in the Key-value Store : ```toml logLevel = "DEBUG" @@ -109,9 +112,9 @@ And there, the same global configuration in the Key-value Store (using `prefix = | `/traefik/consul/prefix` | `traefik` | | `/traefik/web/address` | `:8081` | -Remember to specify the indexes (`0`,`1`, `2`, ... ) under prefixes `/traefik/defaultentrypoints/` and `/traefik/entrypoints/https/tls/certificates/` in order to match the global configuration structure. - -Be careful to give the correct IP address and port on the key `/traefik/consul/endpoint`. +In case you are setting key values manually,: + - Remember to specify the indexes (`0`,`1`, `2`, ... ) under prefixes `/traefik/defaultentrypoints/` and `/traefik/entrypoints/https/tls/certificates/` in order to match the global configuration structure. + - Be careful to give the correct IP address and port on the key `/traefik/consul/endpoint`. Note that we can either give path to certificate file or directly the file content itself. @@ -121,7 +124,7 @@ We will now launch Træfɪk in a container. We use CLI flags to setup the connection between Træfɪk and Consul. All the rest of the global configuration is stored in Consul. -Here the [docker-compose file](https://docs.docker.com/compose/compose-file/) : +Here is the [docker-compose file](https://docs.docker.com/compose/compose-file/) : ```yml traefik: @@ -130,8 +133,6 @@ traefik: ports: - "80:80" - "8080:8080" - volumes: - - /var/run/docker.sock:/var/run/docker.sock ``` NB : Be careful to give the correct IP address and port in the flag `--consul.endpoint`. @@ -166,7 +167,7 @@ Note that this section is independent of the way Træfɪk got its static configu It means that the static configuration can either come from the same Key-value store or from any other sources. ## Key-value storage structure -Here the toml configuration we would like to store in the store : +Here is the toml configuration we would like to store in the store : ```toml [file] @@ -295,4 +296,17 @@ Once the `/traefik/alias` key is updated, the new `/traefik_configurations/2` co | `/traefik_configurations/2/backends/backend1/servers/server2/weight` | `5` | Note that Træfɪk *will not watch for key changes in the `/traefik_configurations` prefix*. It will only watch for changes in the `/traefik/alias`. -Further, if the `/traefik/alias` key is set, all other configuration with `/traefik/backends` or `/traefik/frontends` prefix are ignored. \ No newline at end of file +Further, if the `/traefik/alias` key is set, all other configuration with `/traefik/backends` or `/traefik/frontends` prefix are ignored. + +# Store configuration in Key-value store + +The static Træfɪk configuration in a key-value store can be automatically created and updated, using the [`storeconfig` subcommand](/basics/#commands). + +```bash +$ traefik storeconfig [flags] ... +``` +This command is here only to automate the [process which upload the configuration into the Key-value store](/user-guide/kv-config/#upload-the-configuration-in-the-key-value-store). +Træfɪk will not start but the [static configuration](/basics/#static-trfk-configuration) will be uploaded into the Key-value store. + +Don't forget to [setup the connection between Træfɪk and Key-value store](/user-guide/kv-config/#launch-trfk). + diff --git a/glide.lock b/glide.lock index e4cc5734d..c0e265256 100644 --- a/glide.lock +++ b/glide.lock @@ -1,6 +1,8 @@ -hash: d46d9eb54571fad41c44e85508bc5e71a94801f4dfa9227686683bdd8f724544 -updated: 2016-07-21T15:55:22.90786751+02:00 +hash: 745d05424943c3345ff5fca5b121c6af3930f62fc13195d87d9fcce6686620ea +updated: 2016-07-22T15:14:53.608798979+02:00 imports: +- name: github.com/abbot/go-http-auth + version: cb4372376e1e00e9f6ab9ec142e029302c9e7140 - name: github.com/boltdb/bolt version: 5cc10bbbc5c141029940133bb33c9e969512a698 - name: github.com/BurntSushi/toml @@ -18,11 +20,11 @@ imports: - name: github.com/codegangsta/negroni version: dc6b9d037e8dab60cbfc09c61d6932537829be8b - name: github.com/containous/flaeg - version: b98687da5c323650f4513fda6b6203fcbdec9313 + version: da9515902135a2c9071c7464a1ae660b8b24d994 - name: github.com/containous/mux version: a819b77bba13f0c0cbe36e437bc2e948411b3996 - name: github.com/containous/staert - version: 436a2f21e5e28c7c761130720befe05381db0765 + version: 8a848df89b01313ad890142bcd613a932f629a41 - name: github.com/coreos/etcd version: 1c9e0a0e33051fed6c05c141e6fcbfe5c7f2a899 subpackages: @@ -34,7 +36,7 @@ imports: subpackages: - spew - name: github.com/docker/distribution - version: 857d0f15c0a4d8037175642e0ca3660829551cb5 + version: 2b72dd3927b2958160a2336f16145c0c421aa6a4 subpackages: - reference - digest @@ -155,7 +157,7 @@ imports: - name: github.com/go-check/check version: 4f90aeace3a26ad7021961c297b22c42160c7b25 - name: github.com/gogo/protobuf - version: e57a569e1882958f6b188cb42231d6db87701f2a + version: 6abcf94fd4c97dcb423fdafd42fe9f96ca7e421b subpackages: - proto - name: github.com/golang/glog @@ -224,7 +226,7 @@ imports: - name: github.com/ogier/pflag version: 45c278ab3607870051a2ea9040bb85fcb8557481 - name: github.com/opencontainers/runc - version: ff88baa42fa5b2a1568a3a14665142fb4bdb3a2a + version: fb221651e5120cd287a76c7c1b6c877520fbd034 subpackages: - libcontainer/user - name: github.com/parnurzeal/gorequest @@ -329,7 +331,7 @@ testImports: - name: github.com/gorilla/mux version: 9fa818a44c2bf1396a17f9d5a3c0f6dd39d2ff8e - name: github.com/libkermit/docker-check - version: cbe0ef03b3d23070eac4d00ba8828f2cc7f7e5a3 + version: bb75a86b169c6c5d22c0ee98278124036f272d7b - name: github.com/spf13/pflag version: 5644820622454e71517561946e3d94b9f9db6842 - name: github.com/vbatts/tar-split diff --git a/glide.yaml b/glide.yaml index 640d3b2ce..70314fdaf 100644 --- a/glide.yaml +++ b/glide.yaml @@ -8,7 +8,7 @@ import: - package: github.com/cenkalti/backoff - package: github.com/codegangsta/negroni - package: github.com/containous/flaeg - version: b98687da5c323650f4513fda6b6203fcbdec9313 + version: da9515902135a2c9071c7464a1ae660b8b24d994 - package: github.com/vulcand/oxy version: 8d476862d38b9be356eaa83b5712cad561be08a1 repo: https://github.com/containous/oxy.git @@ -21,7 +21,7 @@ import: - stream - utils - package: github.com/containous/staert - version: 436a2f21e5e28c7c761130720befe05381db0765 + version: 8a848df89b01313ad890142bcd613a932f629a41 - package: github.com/docker/engine-api version: 62043eb79d581a32ea849645277023c550732e52 subpackages: @@ -93,7 +93,10 @@ import: - detector - package: github.com/jarcoal/httpmock - package: github.com/mesosphere/mesos-dns - vcs: git - repo: https://github.com/containous/mesos-dns.git version: b47dc4c19f215e98da687b15b4c64e70f629bea5 + repo: https://github.com/containous/mesos-dns.git + vcs: git - package: github.com/tv42/zbase32 +- package: github.com/abbot/go-http-auth +- package: github.com/miekg/dns + version: 5d001d020961ae1c184f9f8152fdc73810481677 diff --git a/integration/consul_test.go b/integration/consul_test.go index 9352bedb1..e51479047 100644 --- a/integration/consul_test.go +++ b/integration/consul_test.go @@ -392,3 +392,38 @@ func (s *ConsulSuite) skipTestGlobalConfigurationWithClientTLS(c *check.C) { c.Assert(err, checker.IsNil) } +func (s *ConsulSuite) TestCommandStoreConfig(c *check.C) { + s.setupConsul(c) + consulHost := s.composeProject.Container(c, "consul").NetworkSettings.IPAddress + + cmd := exec.Command(traefikBinary, "storeconfig", "--configFile=fixtures/simple_web.toml", "--consul.endpoint="+consulHost+":8500") + err := cmd.Start() + c.Assert(err, checker.IsNil) + + // wait for traefik finish without error + cmd.Wait() + + //CHECK + checkmap := map[string]string{ + "/traefik/loglevel": "DEBUG", + "/traefik/defaultentrypoints/0": "http", + "/traefik/entrypoints/http/address": ":8000", + "/traefik/web/address": ":8080", + "/traefik/consul/endpoint": (consulHost + ":8500"), + } + + for key, value := range checkmap { + var p *store.KVPair + err = utils.Try(60*time.Second, func() error { + p, err = s.kv.Get(key) + if err != nil { + return err + } + return nil + }) + c.Assert(err, checker.IsNil) + + c.Assert(string(p.Value), checker.Equals, value) + + } +} diff --git a/integration/etcd_test.go b/integration/etcd_test.go index 0b6b2d077..6191b05fb 100644 --- a/integration/etcd_test.go +++ b/integration/etcd_test.go @@ -431,3 +431,38 @@ func (s *EtcdSuite) TestCertificatesContentstWithSNIConfigHandshake(c *check.C) err = cs.PeerCertificates[0].VerifyHostname("snitest.com") c.Assert(err, checker.IsNil, check.Commentf("certificate did not match SNI servername")) } + +func (s *EtcdSuite) TestCommandStoreConfig(c *check.C) { + etcdHost := s.composeProject.Container(c, "etcd").NetworkSettings.IPAddress + + cmd := exec.Command(traefikBinary, "storeconfig", "--configFile=fixtures/simple_web.toml", "--etcd.endpoint="+etcdHost+":4001") + err := cmd.Start() + c.Assert(err, checker.IsNil) + + // wait for traefik finish without error + cmd.Wait() + + //CHECK + checkmap := map[string]string{ + "/traefik/loglevel": "DEBUG", + "/traefik/defaultentrypoints/0": "http", + "/traefik/entrypoints/http/address": ":8000", + "/traefik/web/address": ":8080", + "/traefik/etcd/endpoint": (etcdHost + ":4001"), + } + + for key, value := range checkmap { + var p *store.KVPair + err = utils.Try(60*time.Second, func() error { + p, err = s.kv.Get(key) + if err != nil { + return err + } + return nil + }) + c.Assert(err, checker.IsNil) + + c.Assert(string(p.Value), checker.Equals, value) + + } +} diff --git a/traefik.go b/traefik.go index c6bd21b9b..8bc01e7bc 100644 --- a/traefik.go +++ b/traefik.go @@ -84,6 +84,28 @@ Complete documentation is available at https://traefik.io`, }, } + //storeconfig Command init + var kv *staert.KvSource + var err error + + storeconfigCmd := &flaeg.Command{ + Name: "storeconfig", + Description: `Store the static traefik configuration into a Key-value stores. Traefik will not start.`, + Config: traefikConfiguration, + DefaultPointersConfig: traefikPointersConfiguration, + Run: func() error { + if kv == nil { + return fmt.Errorf("Error using command storeconfig, no Key-value store defined") + } + jsonConf, _ := json.Marshal(traefikConfiguration.GlobalConfiguration) + fmtlog.Printf("Storing configuration: %s\n", jsonConf) + return kv.StoreConfig(traefikConfiguration.GlobalConfiguration) + }, + Metadata: map[string]string{ + "parseAllSources": "true", + }, + } + //init flaeg source f := flaeg.New(traefikCmd, os.Args[1:]) //add custom parsers @@ -93,8 +115,9 @@ Complete documentation is available at https://traefik.io`, f.AddParser(reflect.TypeOf(provider.Namespaces{}), &provider.Namespaces{}) f.AddParser(reflect.TypeOf([]acme.Domain{}), &acme.Domains{}) - //add version command + //add commands f.AddCommand(versionCmd) + f.AddCommand(storeconfigCmd) if _, err := f.Parse(traefikCmd); err != nil { fmtlog.Println(err) os.Exit(-1) @@ -110,20 +133,28 @@ Complete documentation is available at https://traefik.io`, s.AddSource(f) if _, err := s.LoadConfig(); err != nil { fmtlog.Println(fmt.Errorf("Error reading TOML config file %s : %s", toml.ConfigFileUsed(), err)) + os.Exit(-1) } traefikConfiguration.ConfigFile = toml.ConfigFileUsed() - kv, err := CreateKvSource(traefikConfiguration) + kv, err = CreateKvSource(traefikConfiguration) if err != nil { fmtlog.Println(err) os.Exit(-1) } - if kv != nil { + usedCmd, err := f.GetCommand() + if err != nil { + fmtlog.Println(err) + os.Exit(-1) + } + // IF a KV Store is enable and no sub-command called in args + if kv != nil && usedCmd == traefikCmd { s.AddSource(kv) if _, err := s.LoadConfig(); err != nil { fmtlog.Println(err) + os.Exit(-1) } } @@ -173,7 +204,7 @@ func run(traefikConfiguration *TraefikConfiguration) { fi, err := os.OpenFile(globalConfiguration.TraefikLogsFile, os.O_RDWR|os.O_CREATE|os.O_APPEND, 0666) defer func() { if err := fi.Close(); err != nil { - log.Error("Error closinf file", err) + log.Error("Error closing file", err) } }() if err != nil {