From 9a2d3c144a4972b2a3822c5008fcd180832e7035 Mon Sep 17 00:00:00 2001 From: Armon Dadgar Date: Tue, 24 Dec 2013 16:48:07 -0800 Subject: [PATCH] Adding a bootstrap flag to allow single server raft --- command/agent/agent.go | 3 +++ command/agent/command.go | 3 ++- command/agent/config.go | 7 +++++++ consul/config.go | 8 ++++++++ consul/server.go | 5 +++++ 5 files changed, 25 insertions(+), 1 deletion(-) diff --git a/command/agent/agent.go b/command/agent/agent.go index 32133d9fc2..ae60fe9255 100644 --- a/command/agent/agent.go +++ b/command/agent/agent.go @@ -111,6 +111,9 @@ func (a *Agent) consulConfig() *consul.Config { if a.config.ServerAddr != "" { base.RPCAddr = a.config.ServerAddr } + if a.config.Bootstrap { + base.Bootstrap = true + } // Setup the loggers base.LogOutput = a.logOutput diff --git a/command/agent/command.go b/command/agent/command.go index 79cbb6e96a..cc195ce4a3 100644 --- a/command/agent/command.go +++ b/command/agent/command.go @@ -49,7 +49,8 @@ func (c *Command) readConfig() *Config { "address to bind RPC listener to") cmdFlags.StringVar(&cmdConfig.DataDir, "data", "", "path to the data directory") cmdFlags.StringVar(&cmdConfig.Datacenter, "dc", "", "node datacenter") - cmdFlags.BoolVar(&cmdConfig.Server, "server", false, "enable server mode") + cmdFlags.BoolVar(&cmdConfig.Server, "server", false, "run agent as server") + cmdFlags.BoolVar(&cmdConfig.Bootstrap, "bootstrap", false, "enable server bootstrap mode") if err := cmdFlags.Parse(c.args); err != nil { return nil } diff --git a/command/agent/config.go b/command/agent/config.go index 66701757d6..fb707218d7 100644 --- a/command/agent/config.go +++ b/command/agent/config.go @@ -16,6 +16,10 @@ import ( // Some of this is configurable as CLI flags, but most must // be set using a configuration file. type Config struct { + // Bootstrap is used to bring up the first Consul server, and + // permits that node to elect itself leader + Bootstrap bool + // Datacenter is the datacenter this node is in. Defaults to dc1 Datacenter string @@ -120,6 +124,9 @@ func MergeConfig(a, b *Config) *Config { var result Config = *a // Copy the strings if they're set + if b.Bootstrap { + result.Bootstrap = true + } if b.Datacenter != "" { result.Datacenter = b.Datacenter } diff --git a/consul/config.go b/consul/config.go index 554272d61c..05f9e855ae 100644 --- a/consul/config.go +++ b/consul/config.go @@ -18,6 +18,11 @@ const ( // Config is used to configure the server type Config struct { + // Bootstrap mode is used to bring up the first Consul server. + // It is required so that it can elect a leader without any + // other nodes being present + Bootstrap bool + // Datacenter is the datacenter this Consul server represents Datacenter string @@ -69,5 +74,8 @@ func DefaultConfig() *Config { conf.SerfLANConfig.MemberlistConfig.Port = DefaultLANSerfPort conf.SerfWANConfig.MemberlistConfig.Port = DefaultWANSerfPort + // Disable shutdown on removal + conf.RaftConfig.ShutdownOnRemove = false + return conf } diff --git a/consul/server.go b/consul/server.go index 1ea8b38939..1c45004ecd 100644 --- a/consul/server.go +++ b/consul/server.go @@ -158,6 +158,11 @@ func (s *Server) setupSerf(conf *serf.Config, ch chan serf.Event, path string) ( // setupRaft is used to setup and initialize Raft func (s *Server) setupRaft() error { + // If we are in bootstrap mode, enable a single node cluster + if s.config.Bootstrap { + s.config.RaftConfig.EnableSingleNode = true + } + // Create the base path path := filepath.Join(s.config.DataDir, raftState) if err := ensurePath(path, true); err != nil {