From 7b5da2a2408de54f35335c5055709b2c64bcd7e2 Mon Sep 17 00:00:00 2001 From: Andy Lo-A-Foe Date: Tue, 11 Aug 2015 14:14:21 +0200 Subject: [PATCH 01/45] Add -http-port option to change the HTTP API port This is useful when pushing consul to PaaS like Cloud Foundry making the HTTP API easily routable. --- command/agent/command.go | 1 + command/agent/config.go | 8 ++++++++ 2 files changed, 9 insertions(+) diff --git a/command/agent/command.go b/command/agent/command.go index 008eed42d8..e3ce2787e2 100644 --- a/command/agent/command.go +++ b/command/agent/command.go @@ -80,6 +80,7 @@ func (c *Command) readConfig() *Config { cmdFlags.StringVar(&cmdConfig.ClientAddr, "client", "", "address to bind client listeners to (DNS, HTTP, HTTPS, RPC)") cmdFlags.StringVar(&cmdConfig.BindAddr, "bind", "", "address to bind server listeners to") + cmdFlags.IntVar(&cmdConfig.HttpPort, "http-port", 0, "http port to use") cmdFlags.StringVar(&cmdConfig.AdvertiseAddr, "advertise", "", "address to advertise instead of bind addr") cmdFlags.StringVar(&cmdConfig.AdvertiseAddrWan, "advertise-wan", "", "address to advertise on wan instead of bind or advertise addr") diff --git a/command/agent/config.go b/command/agent/config.go index 5b3357a34e..22331d0d63 100644 --- a/command/agent/config.go +++ b/command/agent/config.go @@ -141,6 +141,11 @@ type Config struct { // client services (DNS, HTTP, HTTPS, RPC) ClientAddr string `mapstructure:"client_addr"` + // HttpPort the HTTP port to listen on. + // This is useful e.g. when deploying to Cloud Foundry to make + // the HTTP API easily routable + HttpPort int `mapstructure:"http_port"` + // BindAddr is used to control the address we bind to. // If not specified, the first private IP we find is used. // This controls the address we use for cluster facing @@ -849,6 +854,9 @@ func MergeConfig(a, b *Config) *Config { if b.BindAddr != "" { result.BindAddr = b.BindAddr } + if b.HttpPort != 0 { + result.Ports.HTTP = b.HttpPort + } if b.AdvertiseAddr != "" { result.AdvertiseAddr = b.AdvertiseAddr } From 6b59226f0aec42d85780980939fa69160c79516c Mon Sep 17 00:00:00 2001 From: Mac Browning Date: Sat, 15 Aug 2015 17:32:38 -0400 Subject: [PATCH 02/45] consul: refactor GetPrivateIP for testability --- consul/server_test.go | 5 ++-- consul/util.go | 5 ++++ consul/util_test.go | 69 +++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 77 insertions(+), 2 deletions(-) diff --git a/consul/server_test.go b/consul/server_test.go index c86c83f355..380edc4733 100644 --- a/consul/server_test.go +++ b/consul/server_test.go @@ -120,9 +120,10 @@ func TestServer_StartStop(t *testing.T) { config := DefaultConfig() config.DataDir = dir - private, err := GetPrivateIP() + // Advertise on localhost. + private, _, err := net.ParseCIDR("127.0.0.1/32") if err != nil { - t.Fatalf("err: %v", err) + t.Fatalf("failed to parse 127.0.0.1 cidr: %v", err) } config.RPCAdvertise = &net.TCPAddr{ diff --git a/consul/util.go b/consul/util.go index 1be12edc77..a9544c0f21 100644 --- a/consul/util.go +++ b/consul/util.go @@ -169,6 +169,10 @@ func GetPrivateIP() (net.IP, error) { return nil, fmt.Errorf("Failed to get interface addresses: %v", err) } + return getPrivateIP(addresses) +} + +func getPrivateIP(addresses []net.Addr) (net.IP, error) { var candidates []net.IP // Find private IPv4 address @@ -200,6 +204,7 @@ func GetPrivateIP() (net.IP, error) { default: return nil, fmt.Errorf("Multiple private IPs found. Please configure one.") } + } // Converts bytes to an integer diff --git a/consul/util_test.go b/consul/util_test.go index 00b53fe76a..d2f08c397b 100644 --- a/consul/util_test.go +++ b/consul/util_test.go @@ -1,6 +1,7 @@ package consul import ( + "errors" "net" "regexp" "testing" @@ -28,6 +29,74 @@ func TestToLowerList(t *testing.T) { } } +func TestGetPrivateIP(t *testing.T) { + ip, _, err := net.ParseCIDR("10.1.2.3/32") + if err != nil { + t.Fatalf("failed to parse private cidr: %v", err) + } + + pubIP, _, err := net.ParseCIDR("8.8.8.8/32") + if err != nil { + t.Fatalf("failed to parse public cidr: %v", err) + } + + tests := []struct { + addrs []net.Addr + expected net.IP + err error + }{ + { + addrs: []net.Addr{ + &net.IPAddr{ + IP: ip, + }, + &net.IPAddr{ + IP: pubIP, + }, + }, + expected: ip, + }, + { + addrs: []net.Addr{ + &net.IPAddr{ + IP: pubIP, + }, + }, + err: errors.New("No private IP address found"), + }, + { + addrs: []net.Addr{ + &net.IPAddr{ + IP: ip, + }, + &net.IPAddr{ + IP: ip, + }, + &net.IPAddr{ + IP: pubIP, + }, + }, + err: errors.New("Multiple private IPs found. Please configure one."), + }, + } + + for _, test := range tests { + ip, err := getPrivateIP(test.addrs) + switch { + case test.err != nil && err != nil: + if err.Error() != test.err.Error() { + t.Fatalf("unexpected error: %v != %v", test.err, err) + } + case (test.err == nil && err != nil) || (test.err != nil && err == nil): + t.Fatalf("unexpected error: %v != %v", test.err, err) + default: + if !test.expected.Equal(ip) { + t.Fatalf("unexpected ip: %v != %v", ip, test.expected) + } + } + } +} + func TestIsPrivateIP(t *testing.T) { if !isPrivateIP("192.168.1.1") { t.Fatalf("bad") From 4e2c3373bcde4eb876af97a59bdbbb94afdd9b39 Mon Sep 17 00:00:00 2001 From: Andy Lo-A-Foe Date: Thu, 20 Aug 2015 20:19:35 +0200 Subject: [PATCH 03/45] Add documentation for http-port option --- command/agent/command.go | 1 + 1 file changed, 1 insertion(+) diff --git a/command/agent/command.go b/command/agent/command.go index e3ce2787e2..de474567d3 100644 --- a/command/agent/command.go +++ b/command/agent/command.go @@ -927,6 +927,7 @@ Options: -atlas-token=token Provides the Atlas API token -bootstrap Sets server to bootstrap mode -bind=0.0.0.0 Sets the bind address for cluster communication + -http-port=8500 Sets the HTTP API port to listen on -bootstrap-expect=0 Sets server to expect bootstrap mode. -client=127.0.0.1 Sets the address to bind for client access. This includes RPC, DNS, HTTP and HTTPS (if configured) From 3e046d3efcf756f5d694ceb1dc1c40254b697960 Mon Sep 17 00:00:00 2001 From: Andy Lo-A-Foe Date: Thu, 20 Aug 2015 20:27:20 +0200 Subject: [PATCH 04/45] Use Ports.HTTP directly --- command/agent/command.go | 2 +- command/agent/config.go | 9 ++------- 2 files changed, 3 insertions(+), 8 deletions(-) diff --git a/command/agent/command.go b/command/agent/command.go index de474567d3..2ea01171f8 100644 --- a/command/agent/command.go +++ b/command/agent/command.go @@ -80,7 +80,7 @@ func (c *Command) readConfig() *Config { cmdFlags.StringVar(&cmdConfig.ClientAddr, "client", "", "address to bind client listeners to (DNS, HTTP, HTTPS, RPC)") cmdFlags.StringVar(&cmdConfig.BindAddr, "bind", "", "address to bind server listeners to") - cmdFlags.IntVar(&cmdConfig.HttpPort, "http-port", 0, "http port to use") + cmdFlags.IntVar(&cmdConfig.Ports.HTTP, "http-port", 0, "http port to use") cmdFlags.StringVar(&cmdConfig.AdvertiseAddr, "advertise", "", "address to advertise instead of bind addr") cmdFlags.StringVar(&cmdConfig.AdvertiseAddrWan, "advertise-wan", "", "address to advertise on wan instead of bind or advertise addr") diff --git a/command/agent/config.go b/command/agent/config.go index 22331d0d63..716b6e8e11 100644 --- a/command/agent/config.go +++ b/command/agent/config.go @@ -141,11 +141,6 @@ type Config struct { // client services (DNS, HTTP, HTTPS, RPC) ClientAddr string `mapstructure:"client_addr"` - // HttpPort the HTTP port to listen on. - // This is useful e.g. when deploying to Cloud Foundry to make - // the HTTP API easily routable - HttpPort int `mapstructure:"http_port"` - // BindAddr is used to control the address we bind to. // If not specified, the first private IP we find is used. // This controls the address we use for cluster facing @@ -854,8 +849,8 @@ func MergeConfig(a, b *Config) *Config { if b.BindAddr != "" { result.BindAddr = b.BindAddr } - if b.HttpPort != 0 { - result.Ports.HTTP = b.HttpPort + if b.Ports.HTTP != 0 { + result.Ports.HTTP = b.Ports.HTTP } if b.AdvertiseAddr != "" { result.AdvertiseAddr = b.AdvertiseAddr From 85321301e1add610f95c5b6f5d0827ef54be9a0f Mon Sep 17 00:00:00 2001 From: Andy Lo-A-Foe Date: Thu, 20 Aug 2015 20:46:20 +0200 Subject: [PATCH 05/45] Remove duplicate code --- command/agent/config.go | 3 --- 1 file changed, 3 deletions(-) diff --git a/command/agent/config.go b/command/agent/config.go index 716b6e8e11..5b3357a34e 100644 --- a/command/agent/config.go +++ b/command/agent/config.go @@ -849,9 +849,6 @@ func MergeConfig(a, b *Config) *Config { if b.BindAddr != "" { result.BindAddr = b.BindAddr } - if b.Ports.HTTP != 0 { - result.Ports.HTTP = b.Ports.HTTP - } if b.AdvertiseAddr != "" { result.AdvertiseAddr = b.AdvertiseAddr } From f06ae16648f5e98d84234985136b5a2c7da641d6 Mon Sep 17 00:00:00 2001 From: Alvaro Miranda Date: Tue, 25 Aug 2015 13:38:25 +1200 Subject: [PATCH 06/45] update: add consul-cli to downloads_tools.html.erb update: add consul-cli to downloads_tools.html.erb --- website/source/downloads_tools.html.erb | 3 +++ 1 file changed, 3 insertions(+) diff --git a/website/source/downloads_tools.html.erb b/website/source/downloads_tools.html.erb index 8f127d1a83..f974826139 100644 --- a/website/source/downloads_tools.html.erb +++ b/website/source/downloads_tools.html.erb @@ -93,6 +93,9 @@ description: |-
  • confd - Manage local application configuration files using templates and data from etcd or Consul
  • +
  • + consul-cli - Command line interface to Consul HTTP API +
  • crypt - Store and retrieve encrypted configuration parameters from etcd or Consul
  • From 103fe83b4a6d6489982634924591d287c63d891f Mon Sep 17 00:00:00 2001 From: James Phillips Date: Tue, 25 Aug 2015 16:12:19 -0700 Subject: [PATCH 07/45] Clarifies services docs a bit. --- website/source/docs/agent/http/agent.html.markdown | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/website/source/docs/agent/http/agent.html.markdown b/website/source/docs/agent/http/agent.html.markdown index 4f3670b715..32ffa19f1f 100644 --- a/website/source/docs/agent/http/agent.html.markdown +++ b/website/source/docs/agent/http/agent.html.markdown @@ -330,7 +330,8 @@ The return code is 200 on success. The register endpoint is used to add a new service, with an optional health check, to the local agent. There is more documentation on services [here](/docs/agent/services.html). -The agent is responsible for managing the status of the service and keeping the Catalog in sync. +The agent is responsible for managing the status of its local services, and for sending updates +about its local services to the servers to keep the global Catalog in sync. The register endpoint expects a JSON request body to be PUT. The request body must look like: From 2e6ccded2c472812e3bf417f88cd2dcd4581d00a Mon Sep 17 00:00:00 2001 From: Ryan Uber Date: Tue, 25 Aug 2015 16:40:55 -0700 Subject: [PATCH 08/45] agent: scada client and HTTP server are tracked separately --- command/agent/command.go | 40 ++++++++++++++++++++++++++++++++----- command/agent/http.go | 41 +++++++++++++++++++------------------- command/agent/http_test.go | 4 ++-- command/util_test.go | 2 +- 4 files changed, 58 insertions(+), 29 deletions(-) diff --git a/command/agent/command.go b/command/agent/command.go index 008eed42d8..05f4c4374b 100644 --- a/command/agent/command.go +++ b/command/agent/command.go @@ -48,6 +48,7 @@ type Command struct { httpServers []*HTTPServer dnsServer *DNSServer scadaProvider *scada.Provider + scadaHttp *HTTPServer } // readConfig is responsible for setup of our configuration using @@ -357,8 +358,8 @@ func (c *Command) setupAgent(config *Config, logOutput io.Writer, logWriter *log scadaList = list } - if config.Ports.HTTP > 0 || config.Ports.HTTPS > 0 || scadaList != nil { - servers, err := NewHTTPServers(agent, config, scadaList, logOutput) + if config.Ports.HTTP > 0 || config.Ports.HTTPS > 0 { + servers, err := NewHTTPServers(agent, config, logOutput) if err != nil { agent.Shutdown() c.Ui.Error(fmt.Sprintf("Error starting http servers: %s", err)) @@ -367,6 +368,10 @@ func (c *Command) setupAgent(config *Config, logOutput io.Writer, logWriter *log c.httpServers = servers } + if scadaList != nil { + c.scadaHttp = newScadaHttp(agent, scadaList) + } + if config.Ports.DNS > 0 { dnsAddr, err := config.ClientListener(config.Addresses.DNS, config.Ports.DNS) if err != nil { @@ -684,9 +689,16 @@ AFTER_MIGRATE: for _, server := range c.httpServers { defer server.Shutdown() } - if c.scadaProvider != nil { - defer c.scadaProvider.Shutdown() - } + + // Check and shut down the SCADA listeners at the end + defer func() { + if c.scadaHttp != nil { + c.scadaHttp.Shutdown() + } + if c.scadaProvider != nil { + c.scadaProvider.Shutdown() + } + }() // Join startup nodes if specified if err := c.startupJoin(config); err != nil { @@ -904,6 +916,24 @@ func (c *Command) handleReload(config *Config) *Config { }(wp) } + // Reload the SCADA client + if c.scadaProvider != nil { + // Shut down the existing SCADA listeners + c.scadaProvider.Shutdown() + if c.scadaHttp != nil { + c.scadaHttp.Shutdown() + } + + // Create the new provider and listener + provider, list, err := NewProvider(newConf, c.logOutput) + if err != nil { + c.Ui.Error(fmt.Sprintf("Failed reloading SCADA client: %s", err)) + return nil + } + c.scadaProvider = provider + c.scadaHttp = newScadaHttp(c.agent, list) + } + return newConf } diff --git a/command/agent/http.go b/command/agent/http.go index 8e5ea7c24e..7b99286ea1 100644 --- a/command/agent/http.go +++ b/command/agent/http.go @@ -41,7 +41,7 @@ type HTTPServer struct { // NewHTTPServers starts new HTTP servers to provide an interface to // the agent. -func NewHTTPServers(agent *Agent, config *Config, scada net.Listener, logOutput io.Writer) ([]*HTTPServer, error) { +func NewHTTPServers(agent *Agent, config *Config, logOutput io.Writer) ([]*HTTPServer, error) { var servers []*HTTPServer if config.Ports.HTTPS > 0 { @@ -142,29 +142,28 @@ func NewHTTPServers(agent *Agent, config *Config, scada net.Listener, logOutput servers = append(servers, srv) } - if scada != nil { - // Create the mux - mux := http.NewServeMux() - - // Create the server - srv := &HTTPServer{ - agent: agent, - mux: mux, - listener: scada, - logger: log.New(logOutput, "", log.LstdFlags), - uiDir: config.UiDir, - addr: scadaHTTPAddr, - } - srv.registerHandlers(false) // Never allow debug for SCADA - - // Start the server - go http.Serve(scada, mux) - servers = append(servers, srv) - } - return servers, nil } +func newScadaHttp(agent *Agent, list net.Listener) *HTTPServer { + // Create the mux + mux := http.NewServeMux() + + // Create the server + srv := &HTTPServer{ + agent: agent, + mux: mux, + listener: list, + logger: agent.logger, + addr: scadaHTTPAddr, + } + srv.registerHandlers(false) // Never allow debug for SCADA + + // Start the server + go http.Serve(list, mux) + return srv +} + // tcpKeepAliveListener sets TCP keep-alive timeouts on accepted // connections. It's used by NewHttpServer so // dead TCP connections eventually go away. diff --git a/command/agent/http_test.go b/command/agent/http_test.go index 7adff75fb7..5923b24a87 100644 --- a/command/agent/http_test.go +++ b/command/agent/http_test.go @@ -38,7 +38,7 @@ func makeHTTPServerWithConfig(t *testing.T, cb func(c *Config)) (string, *HTTPSe t.Fatalf("err: %v", err) } conf.UiDir = uiDir - servers, err := NewHTTPServers(agent, conf, nil, agent.logOutput) + servers, err := NewHTTPServers(agent, conf, agent.logOutput) if err != nil { t.Fatalf("err: %v", err) } @@ -148,7 +148,7 @@ func TestHTTPServer_UnixSocket_FileExists(t *testing.T) { defer os.RemoveAll(dir) // Try to start the server with the same path anyways. - if _, err := NewHTTPServers(agent, conf, nil, agent.logOutput); err != nil { + if _, err := NewHTTPServers(agent, conf, agent.logOutput); err != nil { t.Fatalf("err: %s", err) } diff --git a/command/util_test.go b/command/util_test.go index 294d171ec3..a48f33cb0c 100644 --- a/command/util_test.go +++ b/command/util_test.go @@ -70,7 +70,7 @@ func testAgentWithConfig(t *testing.T, cb func(c *agent.Config)) *agentWrapper { conf.Addresses.HTTP = "127.0.0.1" httpAddr := fmt.Sprintf("127.0.0.1:%d", conf.Ports.HTTP) - http, err := agent.NewHTTPServers(a, conf, nil, os.Stderr) + http, err := agent.NewHTTPServers(a, conf, os.Stderr) if err != nil { os.RemoveAll(dir) t.Fatalf(fmt.Sprintf("err: %v", err)) From 87c1e4fcd3ddb1255a5b149268d0afb4db1c4a0b Mon Sep 17 00:00:00 2001 From: Ryan Uber Date: Tue, 25 Aug 2015 17:19:11 -0700 Subject: [PATCH 09/45] agent: document the scada http creation func --- command/agent/http.go | 2 ++ 1 file changed, 2 insertions(+) diff --git a/command/agent/http.go b/command/agent/http.go index 7b99286ea1..7a61a0498b 100644 --- a/command/agent/http.go +++ b/command/agent/http.go @@ -145,6 +145,8 @@ func NewHTTPServers(agent *Agent, config *Config, logOutput io.Writer) ([]*HTTPS return servers, nil } +// newScadaHttp creates a new HTTP server wrapping the SCADA +// listener such that HTTP calls can be sent from the brokers. func newScadaHttp(agent *Agent, list net.Listener) *HTTPServer { // Create the mux mux := http.NewServeMux() From 96e7b1869cf02b22f468cb60071e7f16c6ac5e82 Mon Sep 17 00:00:00 2001 From: Ryan Uber Date: Tue, 25 Aug 2015 17:21:29 -0700 Subject: [PATCH 10/45] website: add atlas token/infra to reloadable config --- website/source/docs/agent/options.html.markdown | 2 ++ 1 file changed, 2 insertions(+) diff --git a/website/source/docs/agent/options.html.markdown b/website/source/docs/agent/options.html.markdown index d84c2cc902..e014dea043 100644 --- a/website/source/docs/agent/options.html.markdown +++ b/website/source/docs/agent/options.html.markdown @@ -643,3 +643,5 @@ items which are reloaded include: * Services * Watches * HTTP Client Address +* Atlas Token +* Atlas Infrastructure From eb8974160fd606391289b0336e1c8a6789b317b5 Mon Sep 17 00:00:00 2001 From: Ryan Uber Date: Tue, 25 Aug 2015 18:27:07 -0700 Subject: [PATCH 11/45] agent: clean up scada connection manager --- command/agent/command.go | 64 +++++++++++++++++++++------------------- 1 file changed, 34 insertions(+), 30 deletions(-) diff --git a/command/agent/command.go b/command/agent/command.go index 05f4c4374b..f6d8ac6337 100644 --- a/command/agent/command.go +++ b/command/agent/command.go @@ -346,16 +346,10 @@ func (c *Command) setupAgent(config *Config, logOutput io.Writer, logWriter *log c.rpcServer = NewAgentRPC(agent, rpcListener, logOutput, logWriter) // Enable the SCADA integration - var scadaList net.Listener - if config.AtlasInfrastructure != "" { - provider, list, err := NewProvider(config, logOutput) - if err != nil { - agent.Shutdown() - c.Ui.Error(fmt.Sprintf("Error starting SCADA connection: %s", err)) - return err - } - c.scadaProvider = provider - scadaList = list + if err := c.setupScadaConn(config); err != nil { + agent.Shutdown() + c.Ui.Error(fmt.Sprintf("Error starting SCADA connection: %s", err)) + return err } if config.Ports.HTTP > 0 || config.Ports.HTTPS > 0 { @@ -368,10 +362,6 @@ func (c *Command) setupAgent(config *Config, logOutput io.Writer, logWriter *log c.httpServers = servers } - if scadaList != nil { - c.scadaHttp = newScadaHttp(agent, scadaList) - } - if config.Ports.DNS > 0 { dnsAddr, err := config.ClientListener(config.Addresses.DNS, config.Ports.DNS) if err != nil { @@ -916,27 +906,41 @@ func (c *Command) handleReload(config *Config) *Config { }(wp) } - // Reload the SCADA client - if c.scadaProvider != nil { - // Shut down the existing SCADA listeners - c.scadaProvider.Shutdown() - if c.scadaHttp != nil { - c.scadaHttp.Shutdown() - } - - // Create the new provider and listener - provider, list, err := NewProvider(newConf, c.logOutput) - if err != nil { - c.Ui.Error(fmt.Sprintf("Failed reloading SCADA client: %s", err)) - return nil - } - c.scadaProvider = provider - c.scadaHttp = newScadaHttp(c.agent, list) + // Reload SCADA client + if err := c.setupScadaConn(newConf); err != nil { + c.Ui.Error(fmt.Sprintf("Failed reloading SCADA client: %s", err)) + return nil } return newConf } +// startScadaClient is used to start a new SCADA provider and listener, +// replacing any existing listeners. +func (c *Command) setupScadaConn(config *Config) error { + // Shut down existing SCADA listeners + if c.scadaProvider != nil { + c.scadaProvider.Shutdown() + } + if c.scadaHttp != nil { + c.scadaHttp.Shutdown() + } + + // No-op if we don't have an infrastructure + if config.AtlasInfrastructure == "" { + return nil + } + + // Create the new provider and listener + provider, list, err := NewProvider(config, c.logOutput) + if err != nil { + return err + } + c.scadaProvider = provider + c.scadaHttp = newScadaHttp(c.agent, list) + return nil +} + func (c *Command) Synopsis() string { return "Runs a Consul agent" } From 52a7206ff3787b5286f5d84f4e7aad57c1fa1fa7 Mon Sep 17 00:00:00 2001 From: Ryan Uber Date: Tue, 25 Aug 2015 18:51:04 -0700 Subject: [PATCH 12/45] agent: test scada HTTP server creation --- command/agent/http_test.go | 33 +++++++++++++++++++++++++++++++++ 1 file changed, 33 insertions(+) diff --git a/command/agent/http_test.go b/command/agent/http_test.go index 5923b24a87..9869b258dd 100644 --- a/command/agent/http_test.go +++ b/command/agent/http_test.go @@ -516,6 +516,39 @@ func TestACLResolution(t *testing.T) { }) } +func TestScadaHTTP(t *testing.T) { + // Create the agent + dir, agent := makeAgent(t, nextConfig()) + defer os.RemoveAll(dir) + defer agent.Shutdown() + + // Create a generic listener + list, err := net.Listen("tcp", ":0") + if err != nil { + t.Fatalf("err: %s", err) + } + defer list.Close() + + // Create the SCADA HTTP server + scadaHttp := newScadaHttp(agent, list) + + // Returned server uses the listener and scada addr + if scadaHttp.listener != list { + t.Fatalf("bad listener: %#v", scadaHttp) + } + if scadaHttp.addr != scadaHTTPAddr { + t.Fatalf("expected %v, got: %v", scadaHttp.addr, scadaHTTPAddr) + } + + // Check that debug endpoints were not enabled. This will cause + // the serve mux to panic if the routes are already handled. + mockFn := func(w http.ResponseWriter, r *http.Request) {} + scadaHttp.mux.HandleFunc("/debug/pprof/", mockFn) + scadaHttp.mux.HandleFunc("/debug/pprof/cmdline", mockFn) + scadaHttp.mux.HandleFunc("/debug/pprof/profile", mockFn) + scadaHttp.mux.HandleFunc("/debug/pprof/symbol", mockFn) +} + // assertIndex tests that X-Consul-Index is set and non-zero func assertIndex(t *testing.T, resp *httptest.ResponseRecorder) { header := resp.Header().Get("X-Consul-Index") From ed70720d55c4b820ff8acd32589f10656b155f48 Mon Sep 17 00:00:00 2001 From: Ryan Uber Date: Tue, 25 Aug 2015 20:22:22 -0700 Subject: [PATCH 13/45] agent: testing scada client creation in command --- command/agent/agent_test.go | 2 ++ command/agent/command_test.go | 53 +++++++++++++++++++++++++++++++++++ 2 files changed, 55 insertions(+) diff --git a/command/agent/agent_test.go b/command/agent/agent_test.go index e08fcc51e2..e5fcfd09db 100644 --- a/command/agent/agent_test.go +++ b/command/agent/agent_test.go @@ -25,6 +25,8 @@ func nextConfig() *Config { idx := int(atomic.AddUint64(&offset, 1)) conf := DefaultConfig() + conf.Version = "a.b" + conf.VersionPrerelease = "c.d" conf.AdvertiseAddr = "127.0.0.1" conf.Bootstrap = true conf.Datacenter = "dc1" diff --git a/command/agent/command_test.go b/command/agent/command_test.go index b54bd45c5b..2b8a027f43 100644 --- a/command/agent/command_test.go +++ b/command/agent/command_test.go @@ -6,6 +6,7 @@ import ( "io/ioutil" "log" "os" + "strings" "testing" "github.com/hashicorp/consul/testutil" @@ -246,3 +247,55 @@ func TestSetupAgent_RPCUnixSocket_FileExists(t *testing.T) { t.Fatalf("bad permissions: %s", fi.Mode()) } } + +func TestSetupScadaConn(t *testing.T) { + // Create a config and assign an infra name + conf1 := nextConfig() + conf1.AtlasInfrastructure = "hashicorp/test1" + conf1.AtlasToken = "abc" + + dir, agent := makeAgent(t, conf1) + defer os.RemoveAll(dir) + defer agent.Shutdown() + + cmd := &Command{ + ShutdownCh: make(chan struct{}), + Ui: new(cli.MockUi), + agent: agent, + } + + // First start creates the scada conn + if err := cmd.setupScadaConn(conf1); err != nil { + t.Fatalf("err: %s", err) + } + list := cmd.scadaHttp.listener.(*scadaListener) + if list == nil || list.addr.infra != "hashicorp/test1" { + t.Fatalf("bad: %#v", list) + } + http1 := cmd.scadaHttp + provider1 := cmd.scadaProvider + + // Performing setup again tears down original and replaces + // with a new SCADA client. + conf2 := nextConfig() + conf2.AtlasInfrastructure = "hashicorp/test2" + conf2.AtlasToken = "123" + if err := cmd.setupScadaConn(conf2); err != nil { + t.Fatalf("err: %s", err) + } + if cmd.scadaHttp == http1 || cmd.scadaProvider == provider1 { + t.Fatalf("bad: %#v", cmd) + } + list = cmd.scadaHttp.listener.(*scadaListener) + if list == nil || list.addr.infra != "hashicorp/test2" { + t.Fatalf("bad: %#v", list) + } + + // Original provider and listener must be closed + if !provider1.IsShutdown() { + t.Fatalf("should be shutdown") + } + if _, err := http1.listener.Accept(); !strings.Contains(err.Error(), "closed") { + t.Fatalf("should be closed") + } +} From 4b715a7d2c7efa7cef614eb0d1869e6bf2690b29 Mon Sep 17 00:00:00 2001 From: Ryan Uber Date: Tue, 25 Aug 2015 20:43:57 -0700 Subject: [PATCH 14/45] agent: don't reload scada client if there is no config change --- command/agent/command.go | 11 +++++++---- command/agent/command_test.go | 2 +- 2 files changed, 8 insertions(+), 5 deletions(-) diff --git a/command/agent/command.go b/command/agent/command.go index f6d8ac6337..e7c5d2641f 100644 --- a/command/agent/command.go +++ b/command/agent/command.go @@ -906,10 +906,13 @@ func (c *Command) handleReload(config *Config) *Config { }(wp) } - // Reload SCADA client - if err := c.setupScadaConn(newConf); err != nil { - c.Ui.Error(fmt.Sprintf("Failed reloading SCADA client: %s", err)) - return nil + // Reload SCADA client if we have a change + if newConf.AtlasInfrastructure != config.AtlasInfrastructure || + newConf.AtlasToken != config.AtlasToken { + if err := c.setupScadaConn(newConf); err != nil { + c.Ui.Error(fmt.Sprintf("Failed reloading SCADA client: %s", err)) + return nil + } } return newConf diff --git a/command/agent/command_test.go b/command/agent/command_test.go index 2b8a027f43..9839446981 100644 --- a/command/agent/command_test.go +++ b/command/agent/command_test.go @@ -284,7 +284,7 @@ func TestSetupScadaConn(t *testing.T) { t.Fatalf("err: %s", err) } if cmd.scadaHttp == http1 || cmd.scadaProvider == provider1 { - t.Fatalf("bad: %#v", cmd) + t.Fatalf("should change: %#v %#v", cmd.scadaHttp, cmd.scadaProvider) } list = cmd.scadaHttp.listener.(*scadaListener) if list == nil || list.addr.infra != "hashicorp/test2" { From 5ad8bfbd41e9f5dbf0159fe22b1c57b41fa49622 Mon Sep 17 00:00:00 2001 From: Ryan Uber Date: Tue, 25 Aug 2015 21:03:16 -0700 Subject: [PATCH 15/45] agent: log a message when making a new scada connection --- command/agent/command.go | 1 + 1 file changed, 1 insertion(+) diff --git a/command/agent/command.go b/command/agent/command.go index e7c5d2641f..4805345895 100644 --- a/command/agent/command.go +++ b/command/agent/command.go @@ -935,6 +935,7 @@ func (c *Command) setupScadaConn(config *Config) error { } // Create the new provider and listener + c.Ui.Output("Connecting to Atlas: " + config.AtlasInfrastructure) provider, list, err := NewProvider(config, c.logOutput) if err != nil { return err From 33a6cde7dd48506b486af1cdfa2cf8a36144ef7d Mon Sep 17 00:00:00 2001 From: Ryota Arai Date: Wed, 26 Aug 2015 16:10:04 +0900 Subject: [PATCH 16/45] command/lock: Pass stdin to child process when -pass-stdin passed. --- command/lock.go | 16 +++++++++++++--- 1 file changed, 13 insertions(+), 3 deletions(-) diff --git a/command/lock.go b/command/lock.go index 2ea789120e..aa44abe0c6 100644 --- a/command/lock.go +++ b/command/lock.go @@ -65,6 +65,7 @@ Options: a semaphore is used. -name="" Optional name to associate with lock session. -token="" ACL token to use. Defaults to that of agent. + -pass-stdin Pass stdin to child process. -verbose Enables verbose output ` return strings.TrimSpace(helpText) @@ -74,11 +75,13 @@ func (c *LockCommand) Run(args []string) int { var childDone chan struct{} var name, token string var limit int + var passStdin bool cmdFlags := flag.NewFlagSet("watch", flag.ContinueOnError) cmdFlags.Usage = func() { c.Ui.Output(c.Help()) } cmdFlags.IntVar(&limit, "n", 1, "") cmdFlags.StringVar(&name, "name", "", "") cmdFlags.StringVar(&token, "token", "", "") + cmdFlags.BoolVar(&passStdin, "pass-stdin", false, "") cmdFlags.BoolVar(&c.verbose, "verbose", false, "") httpAddr := HTTPAddrFlag(cmdFlags) if err := cmdFlags.Parse(args); err != nil { @@ -160,7 +163,7 @@ func (c *LockCommand) Run(args []string) int { // Start the child process childDone = make(chan struct{}) go func() { - if err := c.startChild(script, childDone); err != nil { + if err := c.startChild(script, childDone, passStdin); err != nil { c.Ui.Error(fmt.Sprintf("%s", err)) } }() @@ -261,7 +264,7 @@ func (c *LockCommand) setupSemaphore(client *api.Client, limit int, prefix, name // startChild is a long running routine used to start and // wait for the child process to exit. -func (c *LockCommand) startChild(script string, doneCh chan struct{}) error { +func (c *LockCommand) startChild(script string, doneCh chan struct{}, passStdin bool) error { defer close(doneCh) if c.verbose { c.Ui.Info(fmt.Sprintf("Starting handler '%s'", script)) @@ -277,7 +280,14 @@ func (c *LockCommand) startChild(script string, doneCh chan struct{}) error { cmd.Env = append(os.Environ(), "CONSUL_LOCK_HELD=true", ) - cmd.Stdin = nil + if passStdin { + if c.verbose { + c.Ui.Info("Stdin passed to handler process") + } + cmd.Stdin = os.Stdin + } else { + cmd.Stdin = nil + } cmd.Stdout = os.Stdout cmd.Stderr = os.Stderr From 1cc2429364cdfd76b23695cd3f439e8e45cee983 Mon Sep 17 00:00:00 2001 From: Ryan Uber Date: Thu, 27 Aug 2015 11:08:01 -0700 Subject: [PATCH 17/45] agent: atlas_endpoint is configurable --- command/agent/config.go | 7 +++++++ command/agent/config_test.go | 11 ++++++++++- command/agent/scada.go | 1 + command/agent/scada_test.go | 2 ++ 4 files changed, 20 insertions(+), 1 deletion(-) diff --git a/command/agent/config.go b/command/agent/config.go index 5b3357a34e..f0aba4247f 100644 --- a/command/agent/config.go +++ b/command/agent/config.go @@ -363,6 +363,10 @@ type Config struct { // to it's cluster. Requires Atlas integration. AtlasJoin bool `mapstructure:"atlas_join"` + // AtlasEndpoint is the SCADA endpoint used for Atlas integration. If + // empty, the defaults from the provider are used. + AtlasEndpoint string `mapstructure:"atlas_endpoint"` + // AEInterval controls the anti-entropy interval. This is how often // the agent attempts to reconcile it's local state with the server' // representation of our state. Defaults to every 60s. @@ -1056,6 +1060,9 @@ func MergeConfig(a, b *Config) *Config { if b.AtlasJoin { result.AtlasJoin = true } + if b.AtlasEndpoint != "" { + result.AtlasEndpoint = b.AtlasEndpoint + } if b.SessionTTLMinRaw != "" { result.SessionTTLMin = b.SessionTTLMin result.SessionTTLMinRaw = b.SessionTTLMinRaw diff --git a/command/agent/config_test.go b/command/agent/config_test.go index ed2a2921e0..37e0cf27dd 100644 --- a/command/agent/config_test.go +++ b/command/agent/config_test.go @@ -706,7 +706,13 @@ func TestDecodeConfig(t *testing.T) { } // Atlas configs - input = `{"atlas_infrastructure": "hashicorp/prod", "atlas_token": "abcdefg", "atlas_acl_token": "123456789", "atlas_join": true}` + input = `{ + "atlas_infrastructure": "hashicorp/prod", + "atlas_token": "abcdefg", + "atlas_acl_token": "123456789", + "atlas_join": true, + "atlas_endpoint": "foo.bar:1111" +}` config, err = DecodeConfig(bytes.NewReader([]byte(input))) if err != nil { t.Fatalf("err: %s", err) @@ -724,6 +730,9 @@ func TestDecodeConfig(t *testing.T) { if !config.AtlasJoin { t.Fatalf("bad: %#v", config) } + if config.AtlasEndpoint != "foo.bar:1111" { + t.Fatalf("bad: %#v", config) + } // SessionTTLMin input = `{"session_ttl_min": "5s"}` diff --git a/command/agent/scada.go b/command/agent/scada.go index 2fd3d543d9..7cd69e0238 100644 --- a/command/agent/scada.go +++ b/command/agent/scada.go @@ -47,6 +47,7 @@ func ProviderConfig(c *Config) *client.ProviderConfig { Handlers: map[string]client.CapabilityProvider{ "http": nil, }, + Endpoint: c.AtlasEndpoint, ResourceGroup: c.AtlasInfrastructure, Token: c.AtlasToken, } diff --git a/command/agent/scada_test.go b/command/agent/scada_test.go index e142f54ae5..bdd52be6e2 100644 --- a/command/agent/scada_test.go +++ b/command/agent/scada_test.go @@ -43,6 +43,7 @@ func TestProviderConfig(t *testing.T) { conf.Server = true conf.AtlasInfrastructure = "armon/test" conf.AtlasToken = "foobarbaz" + conf.AtlasEndpoint = "foo.bar:1111" pc := ProviderConfig(conf) expect := &client.ProviderConfig{ @@ -62,6 +63,7 @@ func TestProviderConfig(t *testing.T) { Handlers: map[string]client.CapabilityProvider{ "http": nil, }, + Endpoint: "foo.bar:1111", ResourceGroup: "armon/test", Token: "foobarbaz", } From c468acf222a46b7d27c6a5a661ace4587fa593c0 Mon Sep 17 00:00:00 2001 From: Ryan Uber Date: Thu, 27 Aug 2015 11:11:05 -0700 Subject: [PATCH 18/45] command: atlas endpoint can be passed --- command/agent/command.go | 2 ++ 1 file changed, 2 insertions(+) diff --git a/command/agent/command.go b/command/agent/command.go index 4805345895..b656021935 100644 --- a/command/agent/command.go +++ b/command/agent/command.go @@ -87,6 +87,7 @@ func (c *Command) readConfig() *Config { cmdFlags.StringVar(&cmdConfig.AtlasInfrastructure, "atlas", "", "infrastructure name in Atlas") cmdFlags.StringVar(&cmdConfig.AtlasToken, "atlas-token", "", "authentication token for Atlas") cmdFlags.BoolVar(&cmdConfig.AtlasJoin, "atlas-join", false, "auto-join with Atlas") + cmdFlags.StringVar(&cmdConfig.AtlasEndpoint, "atlas-endpoint", "", "endpoint for Atlas integration") cmdFlags.IntVar(&cmdConfig.Protocol, "protocol", -1, "protocol version") @@ -962,6 +963,7 @@ Options: -atlas=org/name Sets the Atlas infrastructure name, enables SCADA. -atlas-join Enables auto-joining the Atlas cluster -atlas-token=token Provides the Atlas API token + -atlas-endpoint=1.2.3.4 The address of the endpoint for Atlas integration. -bootstrap Sets server to bootstrap mode -bind=0.0.0.0 Sets the bind address for cluster communication -bootstrap-expect=0 Sets server to expect bootstrap mode. From 692e9078cb5802f1b960e276fa558d6bf6653a4e Mon Sep 17 00:00:00 2001 From: Ryan Uber Date: Thu, 27 Aug 2015 11:29:42 -0700 Subject: [PATCH 19/45] website: rebundle --- website/Gemfile.lock | 64 ++++++++++++++++++++++++-------------------- 1 file changed, 35 insertions(+), 29 deletions(-) diff --git a/website/Gemfile.lock b/website/Gemfile.lock index 9477360f6c..c9d4cb9752 100644 --- a/website/Gemfile.lock +++ b/website/Gemfile.lock @@ -21,21 +21,25 @@ GIT GEM remote: https://rubygems.org/ specs: - activesupport (4.1.12) - i18n (~> 0.6, >= 0.6.9) + activesupport (4.2.4) + i18n (~> 0.7) json (~> 1.7, >= 1.7.7) minitest (~> 5.1) - thread_safe (~> 0.1) + thread_safe (~> 0.3, >= 0.3.4) tzinfo (~> 1.1) - autoprefixer-rails (5.2.1) + autoprefixer-rails (5.2.1.3) execjs json bootstrap-sass (3.3.5.1) autoprefixer-rails (>= 5.0.0.1) sass (>= 3.3.0) builder (3.2.2) - celluloid (0.16.0) - timers (~> 4.0.0) + capybara (2.4.4) + mime-types (>= 1.16) + nokogiri (>= 1.3.3) + rack (>= 1.0.0) + rack-test (>= 0.5.4) + xpath (~> 2.0) chunky_png (1.3.4) coffee-script (2.4.1) coffee-script-source @@ -59,16 +63,15 @@ GEM eventmachine (>= 0.12.9) http_parser.rb (~> 0.6.0) erubis (2.7.0) - eventmachine (1.0.7) - execjs (2.5.2) + eventmachine (1.0.8) + execjs (2.6.0) ffi (1.9.10) git-version-bump (0.15.1) - haml (4.0.6) + haml (4.0.7) tilt hike (1.2.3) - hitimes (1.2.2) - hooks (0.4.0) - uber (~> 0.0.4) + hooks (0.4.1) + uber (~> 0.0.14) htmlcompressor (0.2.0) http_parser.rb (0.6.0) i18n (0.7.0) @@ -77,34 +80,33 @@ GEM less (2.6.0) commonjs (~> 0.2.7) libv8 (3.16.14.11) - listen (2.10.1) - celluloid (~> 0.16.0) + listen (3.0.3) rb-fsevent (>= 0.9.3) rb-inotify (>= 0.9) - middleman (3.3.13) + middleman (3.4.0) coffee-script (~> 2.2) compass (>= 1.0.0, < 2.0.0) compass-import-once (= 1.0.5) execjs (~> 2.0) haml (>= 4.0.5) kramdown (~> 1.2) - middleman-core (= 3.3.13) + middleman-core (= 3.4.0) middleman-sprockets (>= 3.1.2) sass (>= 3.4.0, < 4.0) uglifier (~> 2.5) - middleman-core (3.3.13) - activesupport (~> 4.1.0) + middleman-core (3.4.0) + activesupport (~> 4.1) bundler (~> 1.1) + capybara (~> 2.4.4) erubis hooks (~> 0.3) i18n (~> 0.7.0) - listen (>= 2.7.9, < 3.0) + listen (~> 3.0.3) padrino-helpers (~> 0.12.3) rack (>= 1.4.5, < 2.0) - rack-test (~> 0.6.2) thor (>= 0.15.2, < 2.0) tilt (~> 1.4.1, < 2.0) - middleman-livereload (3.4.2) + middleman-livereload (3.4.3) em-websocket (~> 0.5.1) middleman-core (>= 3.3) rack-livereload (~> 0.3.15) @@ -119,8 +121,12 @@ GEM middleman-syntax (2.0.0) middleman-core (~> 3.2) rouge (~> 1.0) - minitest (5.7.0) + mime-types (2.6.1) + mini_portile (0.6.2) + minitest (5.8.0) multi_json (1.11.2) + nokogiri (1.6.6.2) + mini_portile (~> 0.6.0) padrino-helpers (0.12.5) i18n (~> 0.6, >= 0.6.7) padrino-support (= 0.12.5) @@ -128,7 +134,7 @@ GEM padrino-support (0.12.5) activesupport (>= 3.1) rack (1.6.4) - rack-contrib (1.3.0) + rack-contrib (1.4.0) git-version-bump (~> 0.15) rack (~> 1.4) rack-livereload (0.3.16) @@ -136,7 +142,7 @@ GEM rack-protection (1.5.3) rack rack-rewrite (1.5.1) - rack-ssl-enforcer (0.2.8) + rack-ssl-enforcer (0.2.9) rack-test (0.6.3) rack (>= 1.0) rb-fsevent (0.9.5) @@ -145,7 +151,7 @@ GEM redcarpet (3.3.2) ref (2.0.0) rouge (1.9.1) - sass (3.4.16) + sass (3.4.18) sprockets (2.12.4) hike (~> 1.2) multi_json (~> 1.0) @@ -166,14 +172,14 @@ GEM thor (0.19.1) thread_safe (0.3.5) tilt (1.4.1) - timers (4.0.1) - hitimes tzinfo (1.2.2) thread_safe (~> 0.1) - uber (0.0.13) - uglifier (2.7.1) + uber (0.0.14) + uglifier (2.7.2) execjs (>= 0.3.0) json (>= 1.8.0) + xpath (2.0.0) + nokogiri (~> 1.3) PLATFORMS ruby From b8e82eee1cb5c488362d866a797618bcca1aba93 Mon Sep 17 00:00:00 2001 From: Ryan Uber Date: Thu, 27 Aug 2015 11:31:29 -0700 Subject: [PATCH 20/45] website: document atlas endpoint config --- website/source/docs/agent/options.html.markdown | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/website/source/docs/agent/options.html.markdown b/website/source/docs/agent/options.html.markdown index e014dea043..ba9c526e10 100644 --- a/website/source/docs/agent/options.html.markdown +++ b/website/source/docs/agent/options.html.markdown @@ -63,6 +63,11 @@ The options below are all specified on the command-line. API authentication token. This can also be provided using the `ATLAS_TOKEN` environment variable. Required for use with Atlas. +* `-atlas-endpoint` - The endpoint + address used for Atlas integration. Used only if the `-atlas` and + `-atlas-token` options are specified. This is optional, and defaults to the + public Atlas endpoints. + * `-bootstrap` - This flag is used to control if a server is in "bootstrap" mode. It is important that no more than one server *per* datacenter be running in this mode. Technically, a server in bootstrap mode @@ -351,6 +356,9 @@ definitions support being updated during a reload. * `atlas_token` Equivalent to the [`-atlas-token` command-line flag](#_atlas_token). +* `atlas_endpoint` Equivalent to the + [`-atlas-endpoint` command-line flag](#_atlas_endpoint). + * `bootstrap` Equivalent to the [`-bootstrap` command-line flag](#_bootstrap). @@ -645,3 +653,4 @@ items which are reloaded include: * HTTP Client Address * Atlas Token * Atlas Infrastructure +* Atlas Endpoint From 11e4cfd72b5f43bfff6e834c3732b1bd65945ed0 Mon Sep 17 00:00:00 2001 From: Ryan Uber Date: Thu, 27 Aug 2015 13:29:07 -0700 Subject: [PATCH 21/45] agent: reload SCADA client if endpoint changes --- command/agent/command.go | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/command/agent/command.go b/command/agent/command.go index b656021935..a8bc10ee7f 100644 --- a/command/agent/command.go +++ b/command/agent/command.go @@ -909,7 +909,8 @@ func (c *Command) handleReload(config *Config) *Config { // Reload SCADA client if we have a change if newConf.AtlasInfrastructure != config.AtlasInfrastructure || - newConf.AtlasToken != config.AtlasToken { + newConf.AtlasToken != config.AtlasToken || + newConf.AtlasEndpoint != config.AtlasEndpoint { if err := c.setupScadaConn(newConf); err != nil { c.Ui.Error(fmt.Sprintf("Failed reloading SCADA client: %s", err)) return nil From 6ac89c28a811999c15545abda09153aeac443473 Mon Sep 17 00:00:00 2001 From: Ryan Uber Date: Thu, 27 Aug 2015 13:35:24 -0700 Subject: [PATCH 22/45] Update CHANGELOG.md --- CHANGELOG.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 8b7675b82c..dd93fe9a05 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -13,6 +13,8 @@ BUG FIXES: IMPROVEMENTS: * Advertised gossip/rpc addresses can now be configured [GH-1004] +* Atlas integration options are reload-able via SIGHUP [GH-1199] +* Atlas endpoint is a configurable option and CLI arg [GH-1201] MISC: From 4adc0b5c660919e3f21c9a60f567fd872b9e3d1e Mon Sep 17 00:00:00 2001 From: Ryan Uber Date: Thu, 27 Aug 2015 17:54:47 -0700 Subject: [PATCH 23/45] website: document precedence of Atlas endpoint inputs --- ui/static/base.css.map | 7 +++++++ website/source/docs/agent/options.html.markdown | 4 +++- 2 files changed, 10 insertions(+), 1 deletion(-) create mode 100644 ui/static/base.css.map diff --git a/ui/static/base.css.map b/ui/static/base.css.map new file mode 100644 index 0000000000..ccf07e284d --- /dev/null +++ b/ui/static/base.css.map @@ -0,0 +1,7 @@ +{ +"version": 3, +"mappings": "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", +"sources": ["../styles/_type.scss","../styles/_variables.scss","../styles/_mixins.scss","../styles/_panels.scss","../styles/_nav.scss","../styles/_buttons.scss","../styles/_lists.scss","../styles/_forms.scss","../styles/_notifications.scss","../styles/base.scss"], +"names": [], +"file": "base.css" +} diff --git a/website/source/docs/agent/options.html.markdown b/website/source/docs/agent/options.html.markdown index ba9c526e10..77b7261437 100644 --- a/website/source/docs/agent/options.html.markdown +++ b/website/source/docs/agent/options.html.markdown @@ -66,7 +66,9 @@ The options below are all specified on the command-line. * `-atlas-endpoint` - The endpoint address used for Atlas integration. Used only if the `-atlas` and `-atlas-token` options are specified. This is optional, and defaults to the - public Atlas endpoints. + public Atlas endpoints. This can also be specified using the `SCADA_ENDPOINT` + environment variable. The CLI option takes precedence, followed by the + configuration file directive, and lastly, the environment variable. * `-bootstrap` - This flag is used to control if a server is in "bootstrap" mode. It is important that From b71a51e27778ad7cde5e34026e9f77763b1992a8 Mon Sep 17 00:00:00 2001 From: Marc Tamsky Date: Fri, 28 Aug 2015 18:10:37 -0700 Subject: [PATCH 24/45] add dnsmasq example, add pointer to 'recursors' --- .../source/docs/guides/forwarding.html.markdown | 16 +++++++++++++++- 1 file changed, 15 insertions(+), 1 deletion(-) diff --git a/website/source/docs/guides/forwarding.html.markdown b/website/source/docs/guides/forwarding.html.markdown index 7a70ef9fa8..856fa59645 100644 --- a/website/source/docs/guides/forwarding.html.markdown +++ b/website/source/docs/guides/forwarding.html.markdown @@ -13,10 +13,15 @@ requires elevated privileges. Instead of running Consul with an administrative or root account, it is possible to instead forward appropriate queries to Consul, running on an unprivileged port, from another DNS server. -In this guide, we will demonstrate forwarding from [BIND](https://www.isc.org/downloads/bind/). +In this guide, we will demonstrate forwarding from [BIND](https://www.isc.org/downloads/bind/), +as well as [dnsmasq](http://www.thekelleys.org.uk/dnsmasq/doc.html). For the sake of simplicity, BIND and Consul are running on the same machine in this example, but this is not required. +Additionally, by default, consul will not attempt to resolve CNAME records outside the `.consul.` +zone, unless the [recursors](/docs/agent/options.html#recursors) configuration +option is set. + ### BIND Setup First, you have to disable DNSSEC so that Consul and BIND can communicate. @@ -60,6 +65,15 @@ zone "consul" IN { Here we assume Consul is running with default settings and is serving DNS on port 8600. +### Dnsmasq + +Add the following to your config. Typically `/etc/dnsmasq.d/` is enabled which should allow creation of a file `/etc/dnsmasq.d/10-consul`: +```text +server=/consul/127.0.0.1#8600 +``` +restart the dnsmasq process after making configuration changes. + + ### Testing First, perform a DNS query against Consul directly to be sure that the record exists: From 0db9346ecc649d2bef3bbff1cbb7881aa0637338 Mon Sep 17 00:00:00 2001 From: Marc Tamsky Date: Fri, 28 Aug 2015 18:27:26 -0700 Subject: [PATCH 25/45] Explain 'recursors' behavior with an example. --- website/source/docs/guides/forwarding.html.markdown | 12 +++++++++--- 1 file changed, 9 insertions(+), 3 deletions(-) diff --git a/website/source/docs/guides/forwarding.html.markdown b/website/source/docs/guides/forwarding.html.markdown index 856fa59645..809c4f68e9 100644 --- a/website/source/docs/guides/forwarding.html.markdown +++ b/website/source/docs/guides/forwarding.html.markdown @@ -18,9 +18,15 @@ as well as [dnsmasq](http://www.thekelleys.org.uk/dnsmasq/doc.html). For the sake of simplicity, BIND and Consul are running on the same machine in this example, but this is not required. -Additionally, by default, consul will not attempt to resolve CNAME records outside the `.consul.` -zone, unless the [recursors](/docs/agent/options.html#recursors) configuration -option is set. +It is worth mentioning that, by default, consul does not resolve DNS +records outside the `.consul.` zone, unless the +[recursors](/docs/agent/options.html#recursors) configuration option +has been set. An example of how this changes consul's behavior is: +When a consul DNS reply includes a CNAME record pointing outside +`.consul.` the DNS reply includes only CNAME records. +Contrastingly, when `recursors` is set and the upstream resolver is +functioning correctly, consul will try to resolve CNAMEs and include +any A/PTR records for them in its DNS reply. ### BIND Setup From 8e8526de8f4cefe7b6aed467e6e5dc4b81796a12 Mon Sep 17 00:00:00 2001 From: Ryan Breen Date: Sun, 30 Aug 2015 12:01:49 -0400 Subject: [PATCH 26/45] Cleanup for guides/forwarding.html --- .../docs/guides/forwarding.html.markdown | 25 ++++++++++--------- 1 file changed, 13 insertions(+), 12 deletions(-) diff --git a/website/source/docs/guides/forwarding.html.markdown b/website/source/docs/guides/forwarding.html.markdown index 809c4f68e9..dc0e18befc 100644 --- a/website/source/docs/guides/forwarding.html.markdown +++ b/website/source/docs/guides/forwarding.html.markdown @@ -13,20 +13,20 @@ requires elevated privileges. Instead of running Consul with an administrative or root account, it is possible to instead forward appropriate queries to Consul, running on an unprivileged port, from another DNS server. -In this guide, we will demonstrate forwarding from [BIND](https://www.isc.org/downloads/bind/), +In this guide, we will demonstrate forwarding from [BIND](https://www.isc.org/downloads/bind/) as well as [dnsmasq](http://www.thekelleys.org.uk/dnsmasq/doc.html). For the sake of simplicity, BIND and Consul are running on the same machine in this example, but this is not required. -It is worth mentioning that, by default, consul does not resolve DNS -records outside the `.consul.` zone, unless the +It is worth mentioning that, by default, Consul does not resolve DNS +records outside the `.consul.` zone unless the [recursors](/docs/agent/options.html#recursors) configuration option -has been set. An example of how this changes consul's behavior is: -When a consul DNS reply includes a CNAME record pointing outside -`.consul.` the DNS reply includes only CNAME records. -Contrastingly, when `recursors` is set and the upstream resolver is -functioning correctly, consul will try to resolve CNAMEs and include -any A/PTR records for them in its DNS reply. +has been set. As an example of how this changes Consul's behavior, +suppose a Consul DNS reply includes a CNAME record pointing outside +the `.consul` TLD. The DNS reply will only include CNAME records by +default. By contrast, when `recursors` is set and the upstream resolver is +functioning correctly, Consul will try to resolve CNAMEs and include +any records (e.g. A, AAAA, PTR) for them in its DNS reply. ### BIND Setup @@ -71,14 +71,15 @@ zone "consul" IN { Here we assume Consul is running with default settings and is serving DNS on port 8600. -### Dnsmasq +### Dnsmasq Setup + +Dnsmasq is typically configured via files in the `/etc/dnsmasq.d` directory. To configure Consul, create the file `/etc/dnsmasq.d/10-consul` with the following contents: -Add the following to your config. Typically `/etc/dnsmasq.d/` is enabled which should allow creation of a file `/etc/dnsmasq.d/10-consul`: ```text server=/consul/127.0.0.1#8600 ``` -restart the dnsmasq process after making configuration changes. +Once that configuration is created, restart the dnsmasq service. ### Testing From af7d2cb5964ac75a1e3c71ca62efba8b942a0a8e Mon Sep 17 00:00:00 2001 From: James Phillips Date: Mon, 31 Aug 2015 11:16:34 -0700 Subject: [PATCH 27/45] Bumps protocol version back down as we've made memberlist smarter. --- consul/config.go | 1 - consul/server.go | 2 +- 2 files changed, 1 insertion(+), 2 deletions(-) diff --git a/consul/config.go b/consul/config.go index 51b8a268d4..541c2bce02 100644 --- a/consul/config.go +++ b/consul/config.go @@ -32,7 +32,6 @@ func init() { protocolVersionMap = map[uint8]uint8{ 1: 4, 2: 4, - 3: 5, } } diff --git a/consul/server.go b/consul/server.go index ec6c8eccc9..b12a11e751 100644 --- a/consul/server.go +++ b/consul/server.go @@ -26,7 +26,7 @@ import ( // protocol versions. const ( ProtocolVersionMin uint8 = 1 - ProtocolVersionMax = 3 + ProtocolVersionMax = 2 ) const ( From b2755d026e25071f645c76a071069c242ab2a800 Mon Sep 17 00:00:00 2001 From: Ryota Arai Date: Tue, 1 Sep 2015 11:00:26 +0900 Subject: [PATCH 28/45] website: description of -pass-stdin option --- website/source/docs/commands/lock.html.markdown | 2 ++ 1 file changed, 2 insertions(+) diff --git a/website/source/docs/commands/lock.html.markdown b/website/source/docs/commands/lock.html.markdown index 06cac41926..5073ce22fd 100644 --- a/website/source/docs/commands/lock.html.markdown +++ b/website/source/docs/commands/lock.html.markdown @@ -60,5 +60,7 @@ The list of available flags are: * `-token` - ACL token to use. Defaults to that of agent. +* `-pass-stdin` - Pass stdin to child process. + * `-verbose` - Enables verbose output. From 4746c0f1e572346f5ce052deff6daed730e9b565 Mon Sep 17 00:00:00 2001 From: James Phillips Date: Mon, 31 Aug 2015 21:11:50 -0700 Subject: [PATCH 29/45] Removes incorrect protocol version in change log. --- CHANGELOG.md | 1 - 1 file changed, 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index dd93fe9a05..70af3f3bf5 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -18,7 +18,6 @@ IMPROVEMENTS: MISC: -* Protocol version bumped to 3 for serf protocol 5 [GH-996] * Vagrantfile fixed for VMware [GH-1042] ## 0.5.2 (May 18, 2015) From 13b9ff63305c82bd8e5a49532da3260793cbb9e6 Mon Sep 17 00:00:00 2001 From: Alvaro Miranda Date: Wed, 2 Sep 2015 00:52:20 +1200 Subject: [PATCH 30/45] add consul-do to community tools adding consul-do Do something based on leadership status https://github.com/zeroXten/consul-do From README.md Useful for running cronjobs in HA mode. Run something like this on two or more servers: * * * * * /usr/bin/consul-do JOB-1 $(/bin/hostname) && /path/to/job1 */10 * * * * /usr/bin/consul-do JOB-2 $(/bin/hostname) && /path/to/job2 Only one of the servers will be elected leader and will therefore run the job. Should the leader fail, a follower will take over. --- website/source/downloads_tools.html.erb | 3 +++ 1 file changed, 3 insertions(+) diff --git a/website/source/downloads_tools.html.erb b/website/source/downloads_tools.html.erb index f974826139..1c149f8831 100644 --- a/website/source/downloads_tools.html.erb +++ b/website/source/downloads_tools.html.erb @@ -96,6 +96,9 @@ description: |-
  • consul-cli - Command line interface to Consul HTTP API
  • +
  • + consul-do - Do something based on leadership status +
  • crypt - Store and retrieve encrypted configuration parameters from etcd or Consul
  • From 3e46d8a7fe93ebb17cbaa34eba03e6125ce4ca25 Mon Sep 17 00:00:00 2001 From: Andres Toomsalu Date: Tue, 1 Sep 2015 23:09:34 +0300 Subject: [PATCH 31/45] Adding NodeFabric reference to Community Tools --- website/source/downloads_tools.html.erb | 3 +++ 1 file changed, 3 insertions(+) diff --git a/website/source/downloads_tools.html.erb b/website/source/downloads_tools.html.erb index 974a03bdd2..90008a5fe5 100644 --- a/website/source/downloads_tools.html.erb +++ b/website/source/downloads_tools.html.erb @@ -57,6 +57,9 @@ description: |-
  • registrator -Service registry bridge for Docker
  • +
  • + NodeFabric - Turnkey CentOS 7 Atomic Host image with integrated Consul, Registrator and HAProxy - enabling rapid MariaDB-Galera and Ceph deployments +
  • From 369982270df0412027b70b9b3dc20c85e8b72728 Mon Sep 17 00:00:00 2001 From: Wim Date: Tue, 25 Aug 2015 22:37:33 +0200 Subject: [PATCH 32/45] Return SOA/not found when the answer is empty --- command/agent/dns.go | 8 ++++ command/agent/dns_test.go | 83 ++++++++++++++++++++++++++++++++++++++- 2 files changed, 90 insertions(+), 1 deletion(-) diff --git a/command/agent/dns.go b/command/agent/dns.go index e1e5a6e09e..3150683de5 100644 --- a/command/agent/dns.go +++ b/command/agent/dns.go @@ -528,6 +528,14 @@ RPC: if qType == dns.TypeSRV { d.serviceSRVRecords(datacenter, out.Nodes, req, resp, ttl) } + + // If the answer is empty, return not found + if len(resp.Answer) == 0 { + d.addSOA(d.domain, resp) + resp.SetRcode(req, dns.RcodeNameError) + return + } + } // filterServiceNodes is used to filter out nodes that are failing diff --git a/command/agent/dns_test.go b/command/agent/dns_test.go index ee656568fb..e4fb25643f 100644 --- a/command/agent/dns_test.go +++ b/command/agent/dns_test.go @@ -1933,5 +1933,86 @@ func TestDNS_NonExistingLookup(t *testing.T) { if soaRec.Hdr.Ttl != 0 { t.Fatalf("Bad: %#v", in.Ns[0]) } - +} + +func TestDNS_NonExistingLookupEmptyAorAAAA(t *testing.T) { + dir, srv := makeDNSServer(t) + defer os.RemoveAll(dir) + defer srv.agent.Shutdown() + + testutil.WaitForLeader(t, srv.agent.RPC, "dc1") + + // register v6 only service + args := &structs.RegisterRequest{ + Datacenter: "dc1", + Node: "foov6", + Address: "fe80::1", + Service: &structs.NodeService{ + Service: "webv6", + Port: 8000, + }, + } + + var out struct{} + if err := srv.agent.RPC("Catalog.Register", args, &out); err != nil { + t.Fatalf("err: %v", err) + } + + // register v4 only service + args = &structs.RegisterRequest{ + Datacenter: "dc1", + Node: "foov4", + Address: "127.0.0.1", + Service: &structs.NodeService{ + Service: "webv4", + Port: 8000, + }, + } + + if err := srv.agent.RPC("Catalog.Register", args, &out); err != nil { + t.Fatalf("err: %v", err) + } + + // check for ipv6 records on ipv4 only service + m := new(dns.Msg) + m.SetQuestion("webv4.service.consul.", dns.TypeAAAA) + + addr, _ := srv.agent.config.ClientListener("", srv.agent.config.Ports.DNS) + c := new(dns.Client) + in, _, err := c.Exchange(m, addr.String()) + if err != nil { + t.Fatalf("err: %v", err) + } + + if len(in.Ns) != 1 { + t.Fatalf("Bad: %#v", in) + } + + soaRec, ok := in.Ns[0].(*dns.SOA) + if !ok { + t.Fatalf("Bad: %#v", in.Ns[0]) + } + if soaRec.Hdr.Ttl != 0 { + t.Fatalf("Bad: %#v", in.Ns[0]) + } + + // check for ipv4 records on ipv6 only service + m.SetQuestion("webv6.service.consul.", dns.TypeA) + + in, _, err = c.Exchange(m, addr.String()) + if err != nil { + t.Fatalf("err: %v", err) + } + + if len(in.Ns) != 1 { + t.Fatalf("Bad: %#v", in) + } + + soaRec, ok = in.Ns[0].(*dns.SOA) + if !ok { + t.Fatalf("Bad: %#v", in.Ns[0]) + } + if soaRec.Hdr.Ttl != 0 { + t.Fatalf("Bad: %#v", in.Ns[0]) + } } From 54c9fd8403952ee3bd6e140fed2fc1b1ac5496d9 Mon Sep 17 00:00:00 2001 From: Alvaro Miranda Date: Wed, 2 Sep 2015 08:50:57 +1200 Subject: [PATCH 33/45] Update downloads_tools.html.erb --- website/source/downloads_tools.html.erb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/website/source/downloads_tools.html.erb b/website/source/downloads_tools.html.erb index 1c149f8831..cb9e175b70 100644 --- a/website/source/downloads_tools.html.erb +++ b/website/source/downloads_tools.html.erb @@ -97,7 +97,7 @@ description: |- consul-cli - Command line interface to Consul HTTP API

  • - consul-do - Do something based on leadership status + consul-do - Do something, such as run HA cronjobs, based on Consul leadership status
  • crypt - Store and retrieve encrypted configuration parameters from etcd or Consul From 4a1dc90cbaa564a8b2819444a9d46b60f4dbc5cf Mon Sep 17 00:00:00 2001 From: Wim Date: Tue, 25 Aug 2015 21:54:11 +0200 Subject: [PATCH 34/45] Limit the DNS responses after getting the NodeRecords --- command/agent/dns.go | 21 ++++++------- command/agent/dns_test.go | 66 +++++++++++++++++++++++++++++++++++++++ 2 files changed, 76 insertions(+), 11 deletions(-) diff --git a/command/agent/dns.go b/command/agent/dns.go index 3150683de5..2356866c41 100644 --- a/command/agent/dns.go +++ b/command/agent/dns.go @@ -511,16 +511,6 @@ RPC: // Perform a random shuffle shuffleServiceNodes(out.Nodes) - // If the network is not TCP, restrict the number of responses - if network != "tcp" && len(out.Nodes) > maxServiceResponses { - out.Nodes = out.Nodes[:maxServiceResponses] - - // Flag that there are more records to return in the UDP response - if d.config.EnableTruncate { - resp.Truncated = true - } - } - // Add various responses depending on the request qType := req.Question[0].Qtype d.serviceNodeRecords(out.Nodes, req, resp, ttl) @@ -529,13 +519,22 @@ RPC: d.serviceSRVRecords(datacenter, out.Nodes, req, resp, ttl) } + // If the network is not TCP, restrict the number of responses + if network != "tcp" && len(resp.Answer) > maxServiceResponses { + resp.Answer = resp.Answer[:maxServiceResponses] + + // Flag that there are more records to return in the UDP response + if d.config.EnableTruncate { + resp.Truncated = true + } + } + // If the answer is empty, return not found if len(resp.Answer) == 0 { d.addSOA(d.domain, resp) resp.SetRcode(req, dns.RcodeNameError) return } - } // filterServiceNodes is used to filter out nodes that are failing diff --git a/command/agent/dns_test.go b/command/agent/dns_test.go index e4fb25643f..cdd5c36097 100644 --- a/command/agent/dns_test.go +++ b/command/agent/dns_test.go @@ -1416,6 +1416,72 @@ func TestDNS_ServiceLookup_Truncate(t *testing.T) { } } +func TestDNS_ServiceLookup_MaxResponses(t *testing.T) { + dir, srv := makeDNSServer(t) + defer os.RemoveAll(dir) + defer srv.agent.Shutdown() + + testutil.WaitForLeader(t, srv.agent.RPC, "dc1") + + // Register nodes + for i := 0; i < 6*maxServiceResponses; i++ { + nodeAddress := fmt.Sprintf("127.0.0.%d", i+1) + if i > 3 { + nodeAddress = fmt.Sprintf("fe80::%d", i+1) + } + args := &structs.RegisterRequest{ + Datacenter: "dc1", + Node: fmt.Sprintf("foo%d", i), + Address: nodeAddress, + Service: &structs.NodeService{ + Service: "web", + Port: 8000, + }, + } + + var out struct{} + if err := srv.agent.RPC("Catalog.Register", args, &out); err != nil { + t.Fatalf("err: %v", err) + } + } + + // Ensure the response is randomized each time. + m := new(dns.Msg) + m.SetQuestion("web.service.consul.", dns.TypeANY) + + addr, _ := srv.agent.config.ClientListener("", srv.agent.config.Ports.DNS) + c := new(dns.Client) + in, _, err := c.Exchange(m, addr.String()) + if err != nil { + t.Fatalf("err: %v", err) + } + + if len(in.Answer) != 3 { + t.Fatalf("should receive 3 answers for ANY") + } + + m.SetQuestion("web.service.consul.", dns.TypeA) + in, _, err = c.Exchange(m, addr.String()) + if err != nil { + t.Fatalf("err: %v", err) + } + + if len(in.Answer) != 3 { + t.Fatalf("should receive 3 answers for A") + } + + m.SetQuestion("web.service.consul.", dns.TypeAAAA) + in, _, err = c.Exchange(m, addr.String()) + if err != nil { + t.Fatalf("err: %v", err) + } + + if len(in.Answer) != 3 { + t.Fatalf("should receive 3 answers for AAAA") + } + +} + func TestDNS_ServiceLookup_CNAME(t *testing.T) { recursor := makeRecursor(t, []dns.RR{ dnsCNAME("www.google.com", "google.com"), From 43ab372a189e1dacd902062b0b6faecda4d61364 Mon Sep 17 00:00:00 2001 From: "Michael S. Fischer" Date: Mon, 31 Aug 2015 16:33:09 -0700 Subject: [PATCH 35/45] lock.go: fix another race condition The previous fix to `consul lock` (commit 6875e8d) didn't completely eliminate the race that could occur if the lock was acquired around the same time SIGTERM was received: It was still possible for Run() to spawn the process via startChild() after killChild() had released the shared mutex. Now, when SIGTERM is received, we acquire a mutex that prevents spawning a new process and never release it. We've tested this fix pretty thoroughly and believe it completely resolves the issue. --- command/lock.go | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/command/lock.go b/command/lock.go index aa44abe0c6..f40fe2d764 100644 --- a/command/lock.go +++ b/command/lock.go @@ -185,7 +185,10 @@ func (c *LockCommand) Run(args []string) int { goto RELEASE } - // Kill the child + // Prevent starting a new child. The lock is never released + // after this point. + c.childLock.Lock() + // Kill any existing child if err := c.killChild(childDone); err != nil { c.Ui.Error(fmt.Sprintf("%s", err)) } @@ -318,9 +321,7 @@ func (c *LockCommand) startChild(script string, doneCh chan struct{}, passStdin // on the first attempt. func (c *LockCommand) killChild(childDone chan struct{}) error { // Get the child process - c.childLock.Lock() child := c.child - c.childLock.Unlock() // If there is no child process (failed to start), we can quit early if child == nil { From 52a8a95af9be16689a68724dcbb9870540eebba7 Mon Sep 17 00:00:00 2001 From: Armon Dadgar Date: Tue, 1 Sep 2015 18:28:32 -0700 Subject: [PATCH 36/45] agent: Always enable the UI endpoints --- command/agent/http.go | 11 ++++------- 1 file changed, 4 insertions(+), 7 deletions(-) diff --git a/command/agent/http.go b/command/agent/http.go index 7a61a0498b..ddb2d7cd31 100644 --- a/command/agent/http.go +++ b/command/agent/http.go @@ -270,13 +270,10 @@ func (s *HTTPServer) registerHandlers(enableDebug bool) { s.mux.Handle("/ui/", http.StripPrefix("/ui/", http.FileServer(http.Dir(s.uiDir)))) } - // Enable the special endpoints for UI or SCADA - if s.uiDir != "" || s.agent.config.AtlasInfrastructure != "" { - // API's are under /internal/ui/ to avoid conflict - s.mux.HandleFunc("/v1/internal/ui/nodes", s.wrap(s.UINodes)) - s.mux.HandleFunc("/v1/internal/ui/node/", s.wrap(s.UINodeInfo)) - s.mux.HandleFunc("/v1/internal/ui/services", s.wrap(s.UIServices)) - } + // API's are under /internal/ui/ to avoid conflict + s.mux.HandleFunc("/v1/internal/ui/nodes", s.wrap(s.UINodes)) + s.mux.HandleFunc("/v1/internal/ui/node/", s.wrap(s.UINodeInfo)) + s.mux.HandleFunc("/v1/internal/ui/services", s.wrap(s.UIServices)) } // wrap is used to wrap functions to make them more convenient From 00b906774bbd91de2cb3829f6d4a3202434fffc4 Mon Sep 17 00:00:00 2001 From: Andy Lo-A-Foe Date: Wed, 2 Sep 2015 05:36:09 +0200 Subject: [PATCH 37/45] Update agent options section on the website --- website/source/docs/agent/options.html.markdown | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/website/source/docs/agent/options.html.markdown b/website/source/docs/agent/options.html.markdown index d84c2cc902..c7790a2c0a 100644 --- a/website/source/docs/agent/options.html.markdown +++ b/website/source/docs/agent/options.html.markdown @@ -84,6 +84,11 @@ The options below are all specified on the command-line. IP address. Consul uses both TCP and UDP and the same port for both. If you have any firewalls, be sure to allow both protocols. +* `-http-port` - the HTTP API port to listen on. + This overrides the default port 8500. This option is very useful when deploying Consul + to an environment which communicates the HTTP port through the environment e.g. PaaS like CloudFoundry, allowing + you to set the port directly via a Procfile. + * `-client` - The address to which Consul will bind client interfaces, including the HTTP, DNS, and RPC servers. By default, this is "127.0.0.1", From bb5422af146bb7870dd7c085763ea1c14dcbe666 Mon Sep 17 00:00:00 2001 From: Andy Lo-A-Foe Date: Wed, 2 Sep 2015 06:28:55 +0200 Subject: [PATCH 38/45] Position it alphabetically --- website/source/docs/agent/options.html.markdown | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/website/source/docs/agent/options.html.markdown b/website/source/docs/agent/options.html.markdown index c7790a2c0a..c3fe188950 100644 --- a/website/source/docs/agent/options.html.markdown +++ b/website/source/docs/agent/options.html.markdown @@ -84,11 +84,6 @@ The options below are all specified on the command-line. IP address. Consul uses both TCP and UDP and the same port for both. If you have any firewalls, be sure to allow both protocols. -* `-http-port` - the HTTP API port to listen on. - This overrides the default port 8500. This option is very useful when deploying Consul - to an environment which communicates the HTTP port through the environment e.g. PaaS like CloudFoundry, allowing - you to set the port directly via a Procfile. - * `-client` - The address to which Consul will bind client interfaces, including the HTTP, DNS, and RPC servers. By default, this is "127.0.0.1", @@ -144,6 +139,11 @@ The options below are all specified on the command-line. initialized with an encryption key, then the provided key is ignored and a warning will be displayed. +* `-http-port` - the HTTP API port to listen on. + This overrides the default port 8500. This option is very useful when deploying Consul + to an environment which communicates the HTTP port through the environment e.g. PaaS like CloudFoundry, allowing + you to set the port directly via a Procfile. + * `-join` - Address of another agent to join upon starting up. This can be specified multiple times to specify multiple agents to join. If Consul is From 2701bb5cc20d919737169970115bee9482ff9be7 Mon Sep 17 00:00:00 2001 From: Wim Date: Wed, 2 Sep 2015 16:12:22 +0200 Subject: [PATCH 39/45] No NXDOMAIN when the answer is empty --- command/agent/dns.go | 1 - command/agent/dns_test.go | 9 +++++++++ 2 files changed, 9 insertions(+), 1 deletion(-) diff --git a/command/agent/dns.go b/command/agent/dns.go index 2356866c41..5c4a53adc5 100644 --- a/command/agent/dns.go +++ b/command/agent/dns.go @@ -532,7 +532,6 @@ RPC: // If the answer is empty, return not found if len(resp.Answer) == 0 { d.addSOA(d.domain, resp) - resp.SetRcode(req, dns.RcodeNameError) return } } diff --git a/command/agent/dns_test.go b/command/agent/dns_test.go index cdd5c36097..b4d7018a24 100644 --- a/command/agent/dns_test.go +++ b/command/agent/dns_test.go @@ -2062,6 +2062,10 @@ func TestDNS_NonExistingLookupEmptyAorAAAA(t *testing.T) { t.Fatalf("Bad: %#v", in.Ns[0]) } + if in.Rcode != dns.RcodeSuccess { + t.Fatalf("Bad: %#v", in) + } + // check for ipv4 records on ipv6 only service m.SetQuestion("webv6.service.consul.", dns.TypeA) @@ -2081,4 +2085,9 @@ func TestDNS_NonExistingLookupEmptyAorAAAA(t *testing.T) { if soaRec.Hdr.Ttl != 0 { t.Fatalf("Bad: %#v", in.Ns[0]) } + + if in.Rcode != dns.RcodeSuccess { + t.Fatalf("Bad: %#v", in) + } + } From 5da996067e7d401d1f6a8cb7377b926d7d3a9905 Mon Sep 17 00:00:00 2001 From: Seth Vargo Date: Wed, 2 Sep 2015 10:13:43 -0400 Subject: [PATCH 40/45] Update Middleman --- website/Gemfile.lock | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/website/Gemfile.lock b/website/Gemfile.lock index c9d4cb9752..29ad251b5e 100644 --- a/website/Gemfile.lock +++ b/website/Gemfile.lock @@ -1,12 +1,12 @@ GIT remote: git://github.com/hashicorp/middleman-hashicorp.git - revision: 76f0f284ad44cea0457484ea83467192f02daf87 + revision: 93983af15fd8d480bec266b50c9211a48e495815 specs: middleman-hashicorp (0.1.0) bootstrap-sass (~> 3.3) builder (~> 3.2) less (~> 2.6) - middleman (~> 3.3) + middleman (~> 3.4) middleman-livereload (~> 3.4) middleman-minify-html (~> 3.4) middleman-syntax (~> 2.0) @@ -145,7 +145,7 @@ GEM rack-ssl-enforcer (0.2.9) rack-test (0.6.3) rack (>= 1.0) - rb-fsevent (0.9.5) + rb-fsevent (0.9.6) rb-inotify (0.9.5) ffi (>= 0.5.0) redcarpet (3.3.2) @@ -174,7 +174,7 @@ GEM tilt (1.4.1) tzinfo (1.2.2) thread_safe (~> 0.1) - uber (0.0.14) + uber (0.0.15) uglifier (2.7.2) execjs (>= 0.3.0) json (>= 1.8.0) From 1387aba91b0320ecae387e0148fc51e0c9653d71 Mon Sep 17 00:00:00 2001 From: James Phillips Date: Wed, 2 Sep 2015 21:37:31 -0700 Subject: [PATCH 41/45] Fixes a typo in the telemetry docs. --- website/source/docs/agent/telemetry.html.markdown | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/website/source/docs/agent/telemetry.html.markdown b/website/source/docs/agent/telemetry.html.markdown index dfb635ae51..392edd59d0 100644 --- a/website/source/docs/agent/telemetry.html.markdown +++ b/website/source/docs/agent/telemetry.html.markdown @@ -22,7 +22,7 @@ getting a better view of what Consul is doing. Additionally, if the [`statsite_addr` configuration option](/docs/agent/options.html#statsite_addr) is provided, the telemetry information will be streamed to a [statsite](http://github.com/armon/statsite) server where it can be -aggregate and flushed to Graphite or any other metrics store. +aggregated and flushed to Graphite or any other metrics store. Below is sample output of a telemetry dump: From 0bc4d9322e4bce7e5802f6ec8f285ea8cccc537c Mon Sep 17 00:00:00 2001 From: Wim Date: Tue, 8 Sep 2015 15:54:13 +0200 Subject: [PATCH 42/45] Allow AAAA queries for nodeLookup --- command/agent/dns.go | 4 ++-- command/agent/dns_test.go | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/command/agent/dns.go b/command/agent/dns.go index 5c4a53adc5..35830648e3 100644 --- a/command/agent/dns.go +++ b/command/agent/dns.go @@ -352,9 +352,9 @@ INVALID: // nodeLookup is used to handle a node query func (d *DNSServer) nodeLookup(network, datacenter, node string, req, resp *dns.Msg) { - // Only handle ANY and A type requests + // Only handle ANY, A and AAAA type requests qType := req.Question[0].Qtype - if qType != dns.TypeANY && qType != dns.TypeA { + if qType != dns.TypeANY && qType != dns.TypeA && qType != dns.TypeAAAA { return } diff --git a/command/agent/dns_test.go b/command/agent/dns_test.go index b4d7018a24..aafc7c3902 100644 --- a/command/agent/dns_test.go +++ b/command/agent/dns_test.go @@ -293,7 +293,7 @@ func TestDNS_NodeLookup_AAAA(t *testing.T) { } m := new(dns.Msg) - m.SetQuestion("bar.node.consul.", dns.TypeANY) + m.SetQuestion("bar.node.consul.", dns.TypeAAAA) c := new(dns.Client) addr, _ := srv.agent.config.ClientListener("", srv.agent.config.Ports.DNS) From 125d7fd4eecd292178d806f058d51caf1df71b6f Mon Sep 17 00:00:00 2001 From: Ryan Uber Date: Thu, 10 Sep 2015 11:43:59 -0700 Subject: [PATCH 43/45] agent: thread tokens through for maintenance mode --- command/agent/agent.go | 8 ++++---- command/agent/agent_endpoint.go | 12 ++++++++++-- 2 files changed, 14 insertions(+), 6 deletions(-) diff --git a/command/agent/agent.go b/command/agent/agent.go index 397f616a43..6e11a535cf 100644 --- a/command/agent/agent.go +++ b/command/agent/agent.go @@ -1276,7 +1276,7 @@ func serviceMaintCheckID(serviceID string) string { // EnableServiceMaintenance will register a false health check against the given // service ID with critical status. This will exclude the service from queries. -func (a *Agent) EnableServiceMaintenance(serviceID, reason string) error { +func (a *Agent) EnableServiceMaintenance(serviceID, reason, token string) error { service, ok := a.state.Services()[serviceID] if !ok { return fmt.Errorf("No service registered with ID %q", serviceID) @@ -1303,7 +1303,7 @@ func (a *Agent) EnableServiceMaintenance(serviceID, reason string) error { ServiceName: service.Service, Status: structs.HealthCritical, } - a.AddCheck(check, nil, true, "") + a.AddCheck(check, nil, true, token) a.logger.Printf("[INFO] agent: Service %q entered maintenance mode", serviceID) return nil @@ -1330,7 +1330,7 @@ func (a *Agent) DisableServiceMaintenance(serviceID string) error { } // EnableNodeMaintenance places a node into maintenance mode. -func (a *Agent) EnableNodeMaintenance(reason string) { +func (a *Agent) EnableNodeMaintenance(reason, token string) { // Ensure node maintenance is not already enabled if _, ok := a.state.Checks()[nodeMaintCheckID]; ok { return @@ -1349,7 +1349,7 @@ func (a *Agent) EnableNodeMaintenance(reason string) { Notes: reason, Status: structs.HealthCritical, } - a.AddCheck(check, nil, true, "") + a.AddCheck(check, nil, true, token) a.logger.Printf("[INFO] agent: Node entered maintenance mode") } diff --git a/command/agent/agent_endpoint.go b/command/agent/agent_endpoint.go index a4b5f6ca94..a3baa4deb6 100644 --- a/command/agent/agent_endpoint.go +++ b/command/agent/agent_endpoint.go @@ -266,9 +266,13 @@ func (s *HTTPServer) AgentServiceMaintenance(resp http.ResponseWriter, req *http return nil, nil } + // Get the provided token, if any + var token string + s.parseToken(req, &token) + if enable { reason := params.Get("reason") - if err = s.agent.EnableServiceMaintenance(serviceID, reason); err != nil { + if err = s.agent.EnableServiceMaintenance(serviceID, reason, token); err != nil { resp.WriteHeader(404) resp.Write([]byte(err.Error())) return nil, nil @@ -307,8 +311,12 @@ func (s *HTTPServer) AgentNodeMaintenance(resp http.ResponseWriter, req *http.Re return nil, nil } + // Get the provided token, if any + var token string + s.parseToken(req, &token) + if enable { - s.agent.EnableNodeMaintenance(params.Get("reason")) + s.agent.EnableNodeMaintenance(params.Get("reason"), token) } else { s.agent.DisableNodeMaintenance() } From 039938a7e0803f77404f7011ed835dd8ae34a5c6 Mon Sep 17 00:00:00 2001 From: Ryan Uber Date: Thu, 10 Sep 2015 12:08:08 -0700 Subject: [PATCH 44/45] agent: testing node/service maintenance using tokens --- command/agent/agent_endpoint_test.go | 18 ++++++++++++++---- command/agent/agent_test.go | 18 ++++++++++++++---- 2 files changed, 28 insertions(+), 8 deletions(-) diff --git a/command/agent/agent_endpoint_test.go b/command/agent/agent_endpoint_test.go index b0f7a481c1..c899770497 100644 --- a/command/agent/agent_endpoint_test.go +++ b/command/agent/agent_endpoint_test.go @@ -655,7 +655,7 @@ func TestHTTPAgent_EnableServiceMaintenance(t *testing.T) { } // Force the service into maintenance mode - req, _ := http.NewRequest("PUT", "/v1/agent/service/maintenance/test?enable=true&reason=broken", nil) + req, _ := http.NewRequest("PUT", "/v1/agent/service/maintenance/test?enable=true&reason=broken&token=mytoken", nil) resp := httptest.NewRecorder() if _, err := srv.AgentServiceMaintenance(resp, req); err != nil { t.Fatalf("err: %s", err) @@ -671,6 +671,11 @@ func TestHTTPAgent_EnableServiceMaintenance(t *testing.T) { t.Fatalf("should have registered maintenance check") } + // Ensure the token was added + if token := srv.agent.state.CheckToken(checkID); token != "mytoken" { + t.Fatalf("expected 'mytoken', got '%s'", token) + } + // Ensure the reason was set in notes if check.Notes != "broken" { t.Fatalf("bad: %#v", check) @@ -693,7 +698,7 @@ func TestHTTPAgent_DisableServiceMaintenance(t *testing.T) { } // Force the service into maintenance mode - if err := srv.agent.EnableServiceMaintenance("test", ""); err != nil { + if err := srv.agent.EnableServiceMaintenance("test", "", ""); err != nil { t.Fatalf("err: %s", err) } @@ -749,7 +754,7 @@ func TestHTTPAgent_EnableNodeMaintenance(t *testing.T) { // Force the node into maintenance mode req, _ := http.NewRequest( - "PUT", "/v1/agent/self/maintenance?enable=true&reason=broken", nil) + "PUT", "/v1/agent/self/maintenance?enable=true&reason=broken&token=mytoken", nil) resp := httptest.NewRecorder() if _, err := srv.AgentNodeMaintenance(resp, req); err != nil { t.Fatalf("err: %s", err) @@ -764,6 +769,11 @@ func TestHTTPAgent_EnableNodeMaintenance(t *testing.T) { t.Fatalf("should have registered maintenance check") } + // Check that the token was used + if token := srv.agent.state.CheckToken(nodeMaintCheckID); token != "mytoken" { + t.Fatalf("expected 'mytoken', got '%s'", token) + } + // Ensure the reason was set in notes if check.Notes != "broken" { t.Fatalf("bad: %#v", check) @@ -777,7 +787,7 @@ func TestHTTPAgent_DisableNodeMaintenance(t *testing.T) { defer srv.agent.Shutdown() // Force the node into maintenance mode - srv.agent.EnableNodeMaintenance("") + srv.agent.EnableNodeMaintenance("", "") // Leave maintenance mode req, _ := http.NewRequest("PUT", "/v1/agent/self/maintenance?enable=false", nil) diff --git a/command/agent/agent_test.go b/command/agent/agent_test.go index e5fcfd09db..d735f60f30 100644 --- a/command/agent/agent_test.go +++ b/command/agent/agent_test.go @@ -1207,7 +1207,7 @@ func TestAgent_ServiceMaintenanceMode(t *testing.T) { } // Enter maintenance mode for the service - if err := agent.EnableServiceMaintenance("redis", "broken"); err != nil { + if err := agent.EnableServiceMaintenance("redis", "broken", "mytoken"); err != nil { t.Fatalf("err: %s", err) } @@ -1218,6 +1218,11 @@ func TestAgent_ServiceMaintenanceMode(t *testing.T) { t.Fatalf("should have registered critical maintenance check") } + // Check that the token was used to register the check + if token := agent.state.CheckToken(checkID); token != "mytoken" { + t.Fatalf("expected 'mytoken', got: '%s'", token) + } + // Ensure the reason was set in notes if check.Notes != "broken" { t.Fatalf("bad: %#v", check) @@ -1234,7 +1239,7 @@ func TestAgent_ServiceMaintenanceMode(t *testing.T) { } // Enter service maintenance mode without providing a reason - if err := agent.EnableServiceMaintenance("redis", ""); err != nil { + if err := agent.EnableServiceMaintenance("redis", "", ""); err != nil { t.Fatalf("err: %s", err) } @@ -1299,7 +1304,7 @@ func TestAgent_NodeMaintenanceMode(t *testing.T) { defer agent.Shutdown() // Enter maintenance mode for the node - agent.EnableNodeMaintenance("broken") + agent.EnableNodeMaintenance("broken", "mytoken") // Make sure the critical health check was added check, ok := agent.state.Checks()[nodeMaintCheckID] @@ -1307,6 +1312,11 @@ func TestAgent_NodeMaintenanceMode(t *testing.T) { t.Fatalf("should have registered critical node check") } + // Check that the token was used to register the check + if token := agent.state.CheckToken(nodeMaintCheckID); token != "mytoken" { + t.Fatalf("expected 'mytoken', got: '%s'", token) + } + // Ensure the reason was set in notes if check.Notes != "broken" { t.Fatalf("bad: %#v", check) @@ -1321,7 +1331,7 @@ func TestAgent_NodeMaintenanceMode(t *testing.T) { } // Enter maintenance mode without passing a reason - agent.EnableNodeMaintenance("") + agent.EnableNodeMaintenance("", "") // Make sure the check was registered with the default note check, ok = agent.state.Checks()[nodeMaintCheckID] From 897f8a3ed515a16041b39f1b4317516d8e58c5eb Mon Sep 17 00:00:00 2001 From: Ryan Uber Date: Thu, 10 Sep 2015 12:31:13 -0700 Subject: [PATCH 45/45] Update CHANGELOG.md --- CHANGELOG.md | 1 + 1 file changed, 1 insertion(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 70af3f3bf5..bc5ea3d2aa 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -9,6 +9,7 @@ BUG FIXES: * Allow services with `/` characters in the UI [GH-988] * Token hiding in HTTP logs bug fixed [GH-1020] * RFC6598 addresses are accepted as private IP's [GH-1050] +* Tokens passed from the CLI or API work for maint mode [GH-1230] IMPROVEMENTS: