From 9b206ee9f43dd46622582d121f6ab7715595de2b Mon Sep 17 00:00:00 2001 From: Kyle Havlovitz Date: Tue, 21 Nov 2017 16:29:11 -0800 Subject: [PATCH 01/13] Added support for v2 raft APIs and -raft-protocol option --- api/operator.go | 3 + command/agent/agent.go | 4 + command/agent/command.go | 5 + command/agent/config.go | 6 + command/agent/config_test.go | 1 + command/operator_raft_list.go | 6 +- nomad/config.go | 9 +- nomad/leader.go | 108 ++++++++++++++---- nomad/leader_test.go | 91 +++++++++++++++ nomad/operator_endpoint.go | 3 + nomad/operator_endpoint_test.go | 22 ++-- nomad/serf.go | 13 ++- nomad/server.go | 7 +- nomad/structs/operator.go | 3 + nomad/util.go | 44 +++++++ nomad/util_test.go | 100 ++++++++++++++++ .../docs/agent/configuration/server.html.md | 5 + 17 files changed, 391 insertions(+), 39 deletions(-) diff --git a/api/operator.go b/api/operator.go index a83d54cb3..d1761569c 100644 --- a/api/operator.go +++ b/api/operator.go @@ -32,6 +32,9 @@ type RaftServer struct { // it's a non-voting server, which will be added in a future release of // Nomad. Voter bool + + // RaftProtocol is the version of the Raft protocol spoken by this server. + RaftProtocol string } // RaftConfigration is returned when querying for the current Raft configuration. diff --git a/command/agent/agent.go b/command/agent/agent.go index c66bdaeb2..de05400fa 100644 --- a/command/agent/agent.go +++ b/command/agent/agent.go @@ -22,6 +22,7 @@ import ( "github.com/hashicorp/nomad/nomad" "github.com/hashicorp/nomad/nomad/structs" "github.com/hashicorp/nomad/nomad/structs/config" + "github.com/hashicorp/raft" ) const ( @@ -141,6 +142,9 @@ func convertServerConfig(agentConfig *Config, logOutput io.Writer) (*nomad.Confi if agentConfig.Server.ProtocolVersion != 0 { conf.ProtocolVersion = uint8(agentConfig.Server.ProtocolVersion) } + if agentConfig.Server.RaftProtocol != 0 { + conf.RaftConfig.ProtocolVersion = raft.ProtocolVersion(agentConfig.Server.RaftProtocol) + } if agentConfig.Server.NumSchedulers != 0 { conf.NumSchedulers = agentConfig.Server.NumSchedulers } diff --git a/command/agent/command.go b/command/agent/command.go index 9966b278c..c8a715b39 100644 --- a/command/agent/command.go +++ b/command/agent/command.go @@ -83,6 +83,7 @@ func (c *Command) readConfig() *Config { flags.IntVar(&cmdConfig.Server.RetryMaxAttempts, "retry-max", 0, "") flags.StringVar(&cmdConfig.Server.RetryInterval, "retry-interval", "", "") flags.StringVar(&cmdConfig.Server.EncryptKey, "encrypt", "", "gossip encryption key") + flags.IntVar(&cmdConfig.Server.RaftProtocol, "raft-protocol", 0, "") // Client-only options flags.StringVar(&cmdConfig.Client.StateDir, "state-dir", "", "") @@ -870,6 +871,10 @@ Server Options: Address of an agent to join at start time. Can be specified multiple times. + -raft-protocol= + The Raft protocol version to use. Used for enabling certain Autopilot + features. Defaults to 2. + -retry-join=
Address of an agent to join at start time with retries enabled. Can be specified multiple times. diff --git a/command/agent/config.go b/command/agent/config.go index 08e8d2b78..8802c19ff 100644 --- a/command/agent/config.go +++ b/command/agent/config.go @@ -256,6 +256,9 @@ type ServerConfig struct { // ProtocolVersionMin and ProtocolVersionMax. ProtocolVersion int `mapstructure:"protocol_version"` + // RaftProtocol is the Raft protocol version to speak. This must be from [1-3]. + RaftProtocol int `mapstructure:"raft_protocol"` + // NumSchedulers is the number of scheduler thread that are run. // This can be as many as one per core, or zero to disable this server // from doing any scheduling work. @@ -976,6 +979,9 @@ func (a *ServerConfig) Merge(b *ServerConfig) *ServerConfig { if b.ProtocolVersion != 0 { result.ProtocolVersion = b.ProtocolVersion } + if b.RaftProtocol != 0 { + result.RaftProtocol = b.RaftProtocol + } if b.NumSchedulers != 0 { result.NumSchedulers = b.NumSchedulers } diff --git a/command/agent/config_test.go b/command/agent/config_test.go index 0324be6fd..67d75d480 100644 --- a/command/agent/config_test.go +++ b/command/agent/config_test.go @@ -234,6 +234,7 @@ func TestConfig_Merge(t *testing.T) { BootstrapExpect: 2, DataDir: "/tmp/data2", ProtocolVersion: 2, + RaftProtocol: 2, NumSchedulers: 2, EnabledSchedulers: []string{structs.JobTypeBatch}, NodeGCThreshold: "12h", diff --git a/command/operator_raft_list.go b/command/operator_raft_list.go index 508bbb783..6295dae48 100644 --- a/command/operator_raft_list.go +++ b/command/operator_raft_list.go @@ -79,14 +79,14 @@ func (c *OperatorRaftListCommand) Run(args []string) int { } // Format it as a nice table. - result := []string{"Node|ID|Address|State|Voter"} + result := []string{"Node|ID|Address|State|Voter|RaftProtocol"} for _, s := range reply.Servers { state := "follower" if s.Leader { state = "leader" } - result = append(result, fmt.Sprintf("%s|%s|%s|%s|%v", - s.Node, s.ID, s.Address, state, s.Voter)) + result = append(result, fmt.Sprintf("%s|%s|%s|%s|%v|%s", + s.Node, s.ID, s.Address, state, s.Voter, s.RaftProtocol)) } c.Ui.Output(columnize.SimpleFormat(result)) diff --git a/nomad/config.go b/nomad/config.go index bc7f715c9..4a918f393 100644 --- a/nomad/config.go +++ b/nomad/config.go @@ -10,6 +10,7 @@ import ( "github.com/hashicorp/memberlist" "github.com/hashicorp/nomad/helper/tlsutil" + "github.com/hashicorp/nomad/helper/uuid" "github.com/hashicorp/nomad/nomad/structs" "github.com/hashicorp/nomad/nomad/structs/config" "github.com/hashicorp/nomad/scheduler" @@ -98,6 +99,9 @@ type Config struct { // Node name is the name we use to advertise. Defaults to hostname. NodeName string + // NodeID is the uuid of this server. + NodeID string + // Region is the region this Nomad server belongs to. Region string @@ -283,6 +287,7 @@ func DefaultConfig() *Config { AuthoritativeRegion: DefaultRegion, Datacenter: DefaultDC, NodeName: hostname, + NodeID: uuid.Generate(), ProtocolVersion: ProtocolVersionMax, RaftConfig: raft.DefaultConfig(), RaftTimeout: 10 * time.Second, @@ -339,9 +344,9 @@ func DefaultConfig() *Config { // Disable shutdown on removal c.RaftConfig.ShutdownOnRemove = false - // Enable interoperability with unversioned Raft library, and don't + // Enable interoperability with raft protocol version 1, and don't // start using new ID-based features yet. - c.RaftConfig.ProtocolVersion = 1 + c.RaftConfig.ProtocolVersion = 2 return c } diff --git a/nomad/leader.go b/nomad/leader.go index 01787f30e..3a622f6eb 100644 --- a/nomad/leader.go +++ b/nomad/leader.go @@ -744,8 +744,8 @@ func (s *Server) addRaftPeer(m serf.Member, parts *serverParts) error { } // Check for possibility of multiple bootstrap nodes + members := s.serf.Members() if parts.Bootstrap { - members := s.serf.Members() for _, member := range members { valid, p := isNomadServer(member) if valid && member.Name != m.Name && p.Bootstrap { @@ -755,12 +755,10 @@ func (s *Server) addRaftPeer(m serf.Member, parts *serverParts) error { } } - // TODO (alexdadgar) - This will need to be changed once we support node IDs. - addr := (&net.TCPAddr{IP: m.Addr, Port: parts.Port}).String() - // See if it's already in the configuration. It's harmless to re-add it // but we want to avoid doing that if possible to prevent useless Raft // log entries. + addr := (&net.TCPAddr{IP: m.Addr, Port: parts.Port}).String() configFuture := s.raft.GetConfiguration() if err := configFuture.Error(); err != nil { s.logger.Printf("[ERR] nomad: failed to get raft configuration: %v", err) @@ -772,14 +770,64 @@ func (s *Server) addRaftPeer(m serf.Member, parts *serverParts) error { } } - // Attempt to add as a peer - addFuture := s.raft.AddPeer(raft.ServerAddress(addr)) - if err := addFuture.Error(); err != nil { - s.logger.Printf("[ERR] nomad: failed to add raft peer: %v", err) + // See if it's already in the configuration. It's harmless to re-add it + // but we want to avoid doing that if possible to prevent useless Raft + // log entries. If the address is the same but the ID changed, remove the + // old server before adding the new one. + minRaftProtocol, err := MinRaftProtocol(s.config.Datacenter, members) + if err != nil { return err - } else if err == nil { - s.logger.Printf("[INFO] nomad: added raft peer: %v", parts) } + for _, server := range configFuture.Configuration().Servers { + // No-op if the raft version is too low + if server.Address == raft.ServerAddress(addr) && (minRaftProtocol < 2 || parts.RaftVersion < 3) { + return nil + } + + // If the address or ID matches an existing server, see if we need to remove the old one first + if server.Address == raft.ServerAddress(addr) || server.ID == raft.ServerID(parts.ID) { + // Exit with no-op if this is being called on an existing server + if server.Address == raft.ServerAddress(addr) && server.ID == raft.ServerID(parts.ID) { + return nil + } + future := s.raft.RemoveServer(server.ID, 0, 0) + if server.Address == raft.ServerAddress(addr) { + if err := future.Error(); err != nil { + return fmt.Errorf("error removing server with duplicate address %q: %s", server.Address, err) + } + s.logger.Printf("[INFO] nomad: removed server with duplicate address: %s", server.Address) + } else { + if err := future.Error(); err != nil { + return fmt.Errorf("error removing server with duplicate ID %q: %s", server.ID, err) + } + s.logger.Printf("[INFO] nomad: removed server with duplicate ID: %s", server.ID) + } + } + } + + // Attempt to add as a peer + switch { + case minRaftProtocol >= 3: + // todo(kyhavlov): change this to AddNonVoter when adding autopilot + addFuture := s.raft.AddVoter(raft.ServerID(parts.ID), raft.ServerAddress(addr), 0, 0) + if err := addFuture.Error(); err != nil { + s.logger.Printf("[ERR] nomad: failed to add raft peer: %v", err) + return err + } + case minRaftProtocol == 2 && parts.RaftVersion >= 3: + addFuture := s.raft.AddVoter(raft.ServerID(parts.ID), raft.ServerAddress(addr), 0, 0) + if err := addFuture.Error(); err != nil { + s.logger.Printf("[ERR] nomad: failed to add raft peer: %v", err) + return err + } + default: + addFuture := s.raft.AddPeer(raft.ServerAddress(addr)) + if err := addFuture.Error(); err != nil { + s.logger.Printf("[ERR] nomad: failed to add raft peer: %v", err) + return err + } + } + return nil } @@ -797,21 +845,37 @@ func (s *Server) removeRaftPeer(m serf.Member, parts *serverParts) error { s.logger.Printf("[ERR] nomad: failed to get raft configuration: %v", err) return err } - for _, server := range configFuture.Configuration().Servers { - if server.Address == raft.ServerAddress(addr) { - goto REMOVE - } - } - return nil -REMOVE: - // Attempt to remove as a peer. - future := s.raft.RemovePeer(raft.ServerAddress(addr)) - if err := future.Error(); err != nil { - s.logger.Printf("[ERR] nomad: failed to remove raft peer '%v': %v", - parts, err) + minRaftProtocol, err := MinRaftProtocol(s.config.Datacenter, s.serf.Members()) + if err != nil { return err } + + // Pick which remove API to use based on how the server was added. + for _, server := range configFuture.Configuration().Servers { + // If we understand the new add/remove APIs and the server was added by ID, use the new remove API + if minRaftProtocol >= 2 && server.ID == raft.ServerID(parts.ID) { + s.logger.Printf("[INFO] nomad: removing server by ID: %q", server.ID) + future := s.raft.RemoveServer(raft.ServerID(parts.ID), 0, 0) + if err := future.Error(); err != nil { + s.logger.Printf("[ERR] nomad: failed to remove raft peer '%v': %v", + server.ID, err) + return err + } + break + } else if server.Address == raft.ServerAddress(addr) { + // If not, use the old remove API + s.logger.Printf("[INFO] nomad: removing server by address: %q", server.Address) + future := s.raft.RemovePeer(raft.ServerAddress(addr)) + if err := future.Error(); err != nil { + s.logger.Printf("[ERR] nomad: failed to remove raft peer '%v': %v", + addr, err) + return err + } + break + } + } + return nil } diff --git a/nomad/leader_test.go b/nomad/leader_test.go index 814e29d1f..05d534ad2 100644 --- a/nomad/leader_test.go +++ b/nomad/leader_test.go @@ -811,3 +811,94 @@ func TestLeader_DiffACLTokens(t *testing.T) { // P2 is un-modified - ignore. P3 modified, P4 new. assert.Equal(t, []string{p3.AccessorID, p4.AccessorID}, update) } + +func TestLeader_UpgradeRaftVersion(t *testing.T) { + t.Parallel() + s1 := testServer(t, func(c *Config) { + c.Datacenter = "dc1" + c.RaftConfig.ProtocolVersion = 2 + }) + defer s1.Shutdown() + + s2 := testServer(t, func(c *Config) { + c.DevDisableBootstrap = true + c.Datacenter = "dc1" + c.RaftConfig.ProtocolVersion = 1 + }) + defer s2.Shutdown() + + s3 := testServer(t, func(c *Config) { + c.DevDisableBootstrap = true + c.Datacenter = "dc1" + c.RaftConfig.ProtocolVersion = 2 + }) + defer s3.Shutdown() + + servers := []*Server{s1, s2, s3} + + // Try to join + testJoin(t, s1, s2, s3) + + for _, s := range servers { + testutil.WaitForResult(func() (bool, error) { + peers, _ := s.numPeers() + return peers == 3, nil + }, func(err error) { + t.Fatalf("should have 3 peers") + }) + } + + // Kill the v1 server + if err := s2.Leave(); err != nil { + t.Fatal(err) + } + + for _, s := range []*Server{s1, s3} { + minVer, err := MinRaftProtocol("dc1", s.Members()) + if err != nil { + t.Fatal(err) + } + if got, want := minVer, 2; got != want { + t.Fatalf("got min raft version %d want %d", got, want) + } + } + + // Replace the dead server with one running raft protocol v3 + s4 := testServer(t, func(c *Config) { + c.DevDisableBootstrap = true + c.Datacenter = "dc1" + c.RaftConfig.ProtocolVersion = 3 + }) + defer s4.Shutdown() + testJoin(t, s1, s4) + servers[1] = s4 + + // Make sure we're back to 3 total peers with the new one added via ID + for _, s := range servers { + testutil.WaitForResult(func() (bool, error) { + addrs := 0 + ids := 0 + future := s.raft.GetConfiguration() + if err := future.Error(); err != nil { + return false, err + } + for _, server := range future.Configuration().Servers { + if string(server.ID) == string(server.Address) { + addrs++ + } else { + ids++ + } + } + if got, want := addrs, 2; got != want { + return false, fmt.Errorf("got %d server addresses want %d", got, want) + } + if got, want := ids, 1; got != want { + return false, fmt.Errorf("got %d server ids want %d", got, want) + } + + return true, nil + }, func(err error) { + t.Fatal(err) + }) + } +} diff --git a/nomad/operator_endpoint.go b/nomad/operator_endpoint.go index 69bc81294..10c84f536 100644 --- a/nomad/operator_endpoint.go +++ b/nomad/operator_endpoint.go @@ -51,8 +51,10 @@ func (op *Operator) RaftGetConfiguration(args *structs.GenericRequest, reply *st reply.Index = future.Index() for _, server := range future.Configuration().Servers { node := "(unknown)" + raftProtocolVersion := "unknown" if member, ok := serverMap[server.Address]; ok { node = member.Name + raftProtocolVersion = member.Tags["raft_vsn"] } entry := &structs.RaftServer{ @@ -61,6 +63,7 @@ func (op *Operator) RaftGetConfiguration(args *structs.GenericRequest, reply *st Address: server.Address, Leader: server.Address == leader, Voter: server.Suffrage == raft.Voter, + RaftProtocol: raftProtocolVersion, } reply.Servers = append(reply.Servers, entry) } diff --git a/nomad/operator_endpoint_test.go b/nomad/operator_endpoint_test.go index 82d830f1c..9c211fb0e 100644 --- a/nomad/operator_endpoint_test.go +++ b/nomad/operator_endpoint_test.go @@ -44,11 +44,12 @@ func TestOperator_RaftGetConfiguration(t *testing.T) { expected := structs.RaftConfigurationResponse{ Servers: []*structs.RaftServer{ { - ID: me.ID, - Node: fmt.Sprintf("%v.%v", s1.config.NodeName, s1.config.Region), - Address: me.Address, - Leader: true, - Voter: true, + ID: me.ID, + Node: fmt.Sprintf("%v.%v", s1.config.NodeName, s1.config.Region), + Address: me.Address, + Leader: true, + Voter: true, + RaftProtocol: fmt.Sprintf("%d", s1.config.RaftConfig.ProtocolVersion), }, }, Index: future.Index(), @@ -107,11 +108,12 @@ func TestOperator_RaftGetConfiguration_ACL(t *testing.T) { expected := structs.RaftConfigurationResponse{ Servers: []*structs.RaftServer{ { - ID: me.ID, - Node: fmt.Sprintf("%v.%v", s1.config.NodeName, s1.config.Region), - Address: me.Address, - Leader: true, - Voter: true, + ID: me.ID, + Node: fmt.Sprintf("%v.%v", s1.config.NodeName, s1.config.Region), + Address: me.Address, + Leader: true, + Voter: true, + RaftProtocol: fmt.Sprintf("%d", s1.config.RaftConfig.ProtocolVersion), }, }, Index: future.Index(), diff --git a/nomad/serf.go b/nomad/serf.go index ad6c58d0c..4d8aa90bd 100644 --- a/nomad/serf.go +++ b/nomad/serf.go @@ -184,11 +184,22 @@ func (s *Server) maybeBootstrap() { // Attempt a live bootstrap! var configuration raft.Configuration var addrs []string + minRaftVersion, err := MinRaftProtocol(s.config.Datacenter, members) + if err != nil { + s.logger.Printf("[ERR] consul: Failed to read server raft versions: %v", err) + } + for _, server := range servers { addr := server.Addr.String() addrs = append(addrs, addr) + var id raft.ServerID + if minRaftVersion >= 3 { + id = raft.ServerID(server.ID) + } else { + id = raft.ServerID(addr) + } peer := raft.Server{ - ID: raft.ServerID(addr), + ID: id, Address: raft.ServerAddress(addr), } configuration.Servers = append(configuration.Servers, peer) diff --git a/nomad/server.go b/nomad/server.go index 018958473..1bd77e3bb 100644 --- a/nomad/server.go +++ b/nomad/server.go @@ -835,6 +835,9 @@ func (s *Server) setupRaft() error { // Our version of Raft protocol requires the LocalID to match the network // address of the transport. s.config.RaftConfig.LocalID = raft.ServerID(trans.LocalAddr()) + if s.config.RaftConfig.ProtocolVersion >= 3 { + s.config.RaftConfig.LocalID = raft.ServerID(s.config.NodeID) + } // Build an all in-memory setup for dev mode, otherwise prepare a full // disk-based setup. @@ -937,7 +940,7 @@ func (s *Server) setupRaft() error { configuration := raft.Configuration{ Servers: []raft.Server{ { - ID: raft.ServerID(trans.LocalAddr()), + ID: s.config.RaftConfig.LocalID, Address: trans.LocalAddr(), }, }, @@ -972,6 +975,8 @@ func (s *Server) setupSerf(conf *serf.Config, ch chan serf.Event, path string) ( conf.Tags["vsn"] = fmt.Sprintf("%d", structs.ApiMajorVersion) conf.Tags["mvn"] = fmt.Sprintf("%d", structs.ApiMinorVersion) conf.Tags["build"] = s.config.Build + conf.Tags["raft_vsn"] = fmt.Sprintf("%d", s.config.RaftConfig.ProtocolVersion) + conf.Tags["id"] = s.config.NodeID conf.Tags["port"] = fmt.Sprintf("%d", s.rpcAdvertise.(*net.TCPAddr).Port) if s.config.Bootstrap || (s.config.DevMode && !s.config.DevDisableBootstrap) { conf.Tags["bootstrap"] = "1" diff --git a/nomad/structs/operator.go b/nomad/structs/operator.go index 93b99f6fb..22e37ae79 100644 --- a/nomad/structs/operator.go +++ b/nomad/structs/operator.go @@ -26,6 +26,9 @@ type RaftServer struct { // it's a non-voting server, which will be added in a future release of // Nomad. Voter bool + + // RaftProtocol is the version of the Raft protocol spoken by this server. + RaftProtocol string } // RaftConfigrationResponse is returned when querying for the current Raft diff --git a/nomad/util.go b/nomad/util.go index b19129aac..b7a723bee 100644 --- a/nomad/util.go +++ b/nomad/util.go @@ -36,6 +36,7 @@ func RuntimeStats() map[string]string { // serverParts is used to return the parts of a server role type serverParts struct { Name string + ID string Region string Datacenter string Port int @@ -44,6 +45,7 @@ type serverParts struct { MajorVersion int MinorVersion int Build version.Version + RaftVersion int Addr net.Addr Status serf.MemberStatus } @@ -60,6 +62,7 @@ func isNomadServer(m serf.Member) (bool, *serverParts) { return false, nil } + id := m.Tags["id"] region := m.Tags["region"] datacenter := m.Tags["dc"] _, bootstrap := m.Tags["bootstrap"] @@ -100,9 +103,19 @@ func isNomadServer(m serf.Member) (bool, *serverParts) { minorVersion = 0 } + raft_vsn := 0 + raft_vsn_str, ok := m.Tags["raft_vsn"] + if ok { + raft_vsn, err = strconv.Atoi(raft_vsn_str) + if err != nil { + return false, nil + } + } + addr := &net.TCPAddr{IP: m.Addr, Port: port} parts := &serverParts{ Name: m.Name, + ID: id, Region: region, Datacenter: datacenter, Port: port, @@ -112,6 +125,7 @@ func isNomadServer(m serf.Member) (bool, *serverParts) { MajorVersion: majorVersion, MinorVersion: minorVersion, Build: *build_version, + RaftVersion: raft_vsn, Status: m.Status, } return true, parts @@ -131,6 +145,36 @@ func ServersMeetMinimumVersion(members []serf.Member, minVersion *version.Versio return true } +// MinRaftProtocol returns the lowest supported Raft protocol among alive servers +// in the given datacenter. +func MinRaftProtocol(datacenter string, members []serf.Member) (int, error) { + minVersion := -1 + for _, m := range members { + if m.Tags["role"] != "nomad" || m.Tags["dc"] != datacenter || m.Status != serf.StatusAlive { + continue + } + + vsn, ok := m.Tags["raft_vsn"] + if !ok { + vsn = "1" + } + raftVsn, err := strconv.Atoi(vsn) + if err != nil { + return -1, err + } + + if minVersion == -1 || raftVsn < minVersion { + minVersion = raftVsn + } + } + + if minVersion == -1 { + return minVersion, fmt.Errorf("no servers found") + } + + return minVersion, nil +} + // shuffleStrings randomly shuffles the list of strings func shuffleStrings(list []string) { for i := range list { diff --git a/nomad/util_test.go b/nomad/util_test.go index 2ad50248f..cf28a2b22 100644 --- a/nomad/util_test.go +++ b/nomad/util_test.go @@ -1,6 +1,7 @@ package nomad import ( + "errors" "net" "reflect" "testing" @@ -151,6 +152,105 @@ func TestServersMeetMinimumVersion(t *testing.T) { } } +func TestMinRaftProtocol(t *testing.T) { + t.Parallel() + makeMember := func(version, datacenter string) serf.Member { + return serf.Member{ + Name: "foo", + Addr: net.IP([]byte{127, 0, 0, 1}), + Tags: map[string]string{ + "role": "nomad", + "region": "aws", + "dc": datacenter, + "port": "10000", + "vsn": "1", + "raft_vsn": version, + }, + Status: serf.StatusAlive, + } + } + + cases := []struct { + members []serf.Member + datacenter string + expected int + err error + }{ + // No servers, error + { + members: []serf.Member{}, + expected: -1, + err: errors.New("no servers found"), + }, + // One server + { + members: []serf.Member{ + makeMember("1", "dc1"), + }, + datacenter: "dc1", + expected: 1, + }, + // One server, bad version formatting + { + members: []serf.Member{ + makeMember("asdf", "dc1"), + }, + datacenter: "dc1", + expected: -1, + err: errors.New(`strconv.Atoi: parsing "asdf": invalid syntax`), + }, + // One server, wrong datacenter + { + members: []serf.Member{ + makeMember("1", "dc1"), + }, + datacenter: "dc2", + expected: -1, + err: errors.New("no servers found"), + }, + // Multiple servers, different versions + { + members: []serf.Member{ + makeMember("1", "dc1"), + makeMember("2", "dc1"), + }, + datacenter: "dc1", + expected: 1, + }, + // Multiple servers, same version + { + members: []serf.Member{ + makeMember("2", "dc1"), + makeMember("2", "dc1"), + }, + datacenter: "dc1", + expected: 2, + }, + // Multiple servers, multiple datacenters + { + members: []serf.Member{ + makeMember("3", "dc1"), + makeMember("2", "dc1"), + makeMember("1", "dc2"), + }, + datacenter: "dc1", + expected: 2, + }, + } + + for _, tc := range cases { + result, err := MinRaftProtocol(tc.datacenter, tc.members) + if result != tc.expected { + t.Fatalf("bad: %v, %v, %v", result, tc.expected, tc) + } + if tc.err != nil { + if err == nil || tc.err.Error() != err.Error() { + t.Fatalf("bad: %v, %v, %v", err, tc.err, tc) + } + } + } +} + func TestShuffleStrings(t *testing.T) { t.Parallel() // Generate input diff --git a/website/source/docs/agent/configuration/server.html.md b/website/source/docs/agent/configuration/server.html.md index 265db668d..53f30b6a3 100644 --- a/website/source/docs/agent/configuration/server.html.md +++ b/website/source/docs/agent/configuration/server.html.md @@ -112,6 +112,11 @@ server { required as the agent internally knows the latest version, but may be useful in some upgrade scenarios. +- `raft_protocol` `(int: 2)` - Specifies the Raft protocol version to use when + communicating with other Nomad servers. This affects available Autopilot + features and is typically not required as the agent internally knows the + latest version, but may be useful in some upgrade scenarios. + - `rejoin_after_leave` `(bool: false)` - Specifies if Nomad will ignore a previous leave and attempt to rejoin the cluster when starting. By default, Nomad treats leave as a permanent intent and does not attempt to join the From f67b0d0ebe893eb41ead2c4b05295b9a2e7da48c Mon Sep 17 00:00:00 2001 From: Kyle Havlovitz Date: Mon, 27 Nov 2017 14:46:37 -0800 Subject: [PATCH 02/13] Add missing exist checks and doc line --- nomad/operator_endpoint.go | 14 ++++++++------ nomad/util.go | 5 ++++- website/source/api/operator.html.md | 1 + 3 files changed, 13 insertions(+), 7 deletions(-) diff --git a/nomad/operator_endpoint.go b/nomad/operator_endpoint.go index 10c84f536..0edfc4b71 100644 --- a/nomad/operator_endpoint.go +++ b/nomad/operator_endpoint.go @@ -54,15 +54,17 @@ func (op *Operator) RaftGetConfiguration(args *structs.GenericRequest, reply *st raftProtocolVersion := "unknown" if member, ok := serverMap[server.Address]; ok { node = member.Name - raftProtocolVersion = member.Tags["raft_vsn"] + if raftVsn, ok := member.Tags["raft_vsn"]; ok { + raftProtocolVersion = raftVsn + } } entry := &structs.RaftServer{ - ID: server.ID, - Node: node, - Address: server.Address, - Leader: server.Address == leader, - Voter: server.Suffrage == raft.Voter, + ID: server.ID, + Node: node, + Address: server.Address, + Leader: server.Address == leader, + Voter: server.Suffrage == raft.Voter, RaftProtocol: raftProtocolVersion, } reply.Servers = append(reply.Servers, entry) diff --git a/nomad/util.go b/nomad/util.go index b7a723bee..5cae76309 100644 --- a/nomad/util.go +++ b/nomad/util.go @@ -62,7 +62,10 @@ func isNomadServer(m serf.Member) (bool, *serverParts) { return false, nil } - id := m.Tags["id"] + id := "unknown" + if v, ok := m.Tags["id"]; ok { + id = v + } region := m.Tags["region"] datacenter := m.Tags["dc"] _, bootstrap := m.Tags["bootstrap"] diff --git a/website/source/api/operator.html.md b/website/source/api/operator.html.md index 22aed2584..5d71d3e1e 100644 --- a/website/source/api/operator.html.md +++ b/website/source/api/operator.html.md @@ -59,6 +59,7 @@ $ curl \ "ID": "127.0.0.1:4647", "Leader": true, "Node": "bacon-mac.global", + "RaftProtocol": 2, "Voter": true } ] From 88a339cc0a354c83128f6abacf5de692b51d511f Mon Sep 17 00:00:00 2001 From: Kyle Havlovitz Date: Mon, 4 Dec 2017 12:35:41 -0800 Subject: [PATCH 03/13] Use region instead of datacenter for version checking --- nomad/leader.go | 4 +-- nomad/leader_test.go | 2 +- nomad/serf.go | 4 +-- nomad/util.go | 6 ++--- nomad/util_test.go | 64 ++++++++++++++++++++++---------------------- 5 files changed, 40 insertions(+), 40 deletions(-) diff --git a/nomad/leader.go b/nomad/leader.go index 3a622f6eb..304e87617 100644 --- a/nomad/leader.go +++ b/nomad/leader.go @@ -774,7 +774,7 @@ func (s *Server) addRaftPeer(m serf.Member, parts *serverParts) error { // but we want to avoid doing that if possible to prevent useless Raft // log entries. If the address is the same but the ID changed, remove the // old server before adding the new one. - minRaftProtocol, err := MinRaftProtocol(s.config.Datacenter, members) + minRaftProtocol, err := MinRaftProtocol(s.config.Region, members) if err != nil { return err } @@ -846,7 +846,7 @@ func (s *Server) removeRaftPeer(m serf.Member, parts *serverParts) error { return err } - minRaftProtocol, err := MinRaftProtocol(s.config.Datacenter, s.serf.Members()) + minRaftProtocol, err := MinRaftProtocol(s.config.Region, s.serf.Members()) if err != nil { return err } diff --git a/nomad/leader_test.go b/nomad/leader_test.go index 05d534ad2..765f2638f 100644 --- a/nomad/leader_test.go +++ b/nomad/leader_test.go @@ -854,7 +854,7 @@ func TestLeader_UpgradeRaftVersion(t *testing.T) { } for _, s := range []*Server{s1, s3} { - minVer, err := MinRaftProtocol("dc1", s.Members()) + minVer, err := MinRaftProtocol(s1.config.Region, s.Members()) if err != nil { t.Fatal(err) } diff --git a/nomad/serf.go b/nomad/serf.go index 4d8aa90bd..011d7b358 100644 --- a/nomad/serf.go +++ b/nomad/serf.go @@ -184,9 +184,9 @@ func (s *Server) maybeBootstrap() { // Attempt a live bootstrap! var configuration raft.Configuration var addrs []string - minRaftVersion, err := MinRaftProtocol(s.config.Datacenter, members) + minRaftVersion, err := MinRaftProtocol(s.config.Region, members) if err != nil { - s.logger.Printf("[ERR] consul: Failed to read server raft versions: %v", err) + s.logger.Printf("[ERR] nomad: Failed to read server raft versions: %v", err) } for _, server := range servers { diff --git a/nomad/util.go b/nomad/util.go index 5cae76309..8f789a969 100644 --- a/nomad/util.go +++ b/nomad/util.go @@ -149,11 +149,11 @@ func ServersMeetMinimumVersion(members []serf.Member, minVersion *version.Versio } // MinRaftProtocol returns the lowest supported Raft protocol among alive servers -// in the given datacenter. -func MinRaftProtocol(datacenter string, members []serf.Member) (int, error) { +// in the given region. +func MinRaftProtocol(region string, members []serf.Member) (int, error) { minVersion := -1 for _, m := range members { - if m.Tags["role"] != "nomad" || m.Tags["dc"] != datacenter || m.Status != serf.StatusAlive { + if m.Tags["role"] != "nomad" || m.Tags["region"] != region || m.Status != serf.StatusAlive { continue } diff --git a/nomad/util_test.go b/nomad/util_test.go index cf28a2b22..82e939491 100644 --- a/nomad/util_test.go +++ b/nomad/util_test.go @@ -154,14 +154,14 @@ func TestServersMeetMinimumVersion(t *testing.T) { func TestMinRaftProtocol(t *testing.T) { t.Parallel() - makeMember := func(version, datacenter string) serf.Member { + makeMember := func(version, region string) serf.Member { return serf.Member{ Name: "foo", Addr: net.IP([]byte{127, 0, 0, 1}), Tags: map[string]string{ "role": "nomad", - "region": "aws", - "dc": datacenter, + "region": region, + "dc": "dc1", "port": "10000", "vsn": "1", "raft_vsn": version, @@ -171,10 +171,10 @@ func TestMinRaftProtocol(t *testing.T) { } cases := []struct { - members []serf.Member - datacenter string - expected int - err error + members []serf.Member + region string + expected int + err error }{ // No servers, error { @@ -185,61 +185,61 @@ func TestMinRaftProtocol(t *testing.T) { // One server { members: []serf.Member{ - makeMember("1", "dc1"), + makeMember("1", "global"), }, - datacenter: "dc1", - expected: 1, + region: "global", + expected: 1, }, // One server, bad version formatting { members: []serf.Member{ - makeMember("asdf", "dc1"), + makeMember("asdf", "global"), }, - datacenter: "dc1", - expected: -1, - err: errors.New(`strconv.Atoi: parsing "asdf": invalid syntax`), + region: "global", + expected: -1, + err: errors.New(`strconv.Atoi: parsing "asdf": invalid syntax`), }, // One server, wrong datacenter { members: []serf.Member{ - makeMember("1", "dc1"), + makeMember("1", "global"), }, - datacenter: "dc2", - expected: -1, - err: errors.New("no servers found"), + region: "nope", + expected: -1, + err: errors.New("no servers found"), }, // Multiple servers, different versions { members: []serf.Member{ - makeMember("1", "dc1"), - makeMember("2", "dc1"), + makeMember("1", "global"), + makeMember("2", "global"), }, - datacenter: "dc1", - expected: 1, + region: "global", + expected: 1, }, // Multiple servers, same version { members: []serf.Member{ - makeMember("2", "dc1"), - makeMember("2", "dc1"), + makeMember("2", "global"), + makeMember("2", "global"), }, - datacenter: "dc1", - expected: 2, + region: "global", + expected: 2, }, // Multiple servers, multiple datacenters { members: []serf.Member{ - makeMember("3", "dc1"), - makeMember("2", "dc1"), - makeMember("1", "dc2"), + makeMember("3", "r1"), + makeMember("2", "r1"), + makeMember("1", "r2"), }, - datacenter: "dc1", - expected: 2, + region: "r1", + expected: 2, }, } for _, tc := range cases { - result, err := MinRaftProtocol(tc.datacenter, tc.members) + result, err := MinRaftProtocol(tc.region, tc.members) if result != tc.expected { t.Fatalf("bad: %v, %v, %v", result, tc.expected, tc) } From 805ade7d34cf67001b5a6d38bc1d7bbca01ca20a Mon Sep 17 00:00:00 2001 From: Preetha Appan Date: Wed, 6 Dec 2017 13:30:31 -0600 Subject: [PATCH 04/13] Makes tests on travis not run in verbose mode. --- GNUmakefile | 24 +++++++++++++++--------- scripts/test_check.sh | 10 ++++++++++ 2 files changed, 25 insertions(+), 9 deletions(-) create mode 100755 scripts/test_check.sh diff --git a/GNUmakefile b/GNUmakefile index bcdb9ffeb..a4e304b6d 100644 --- a/GNUmakefile +++ b/GNUmakefile @@ -1,3 +1,4 @@ + SHELL = bash PROJECT_ROOT := $(patsubst %/,%,$(dir $(abspath $(lastword $(MAKEFILE_LIST))))) THIS_OS := $(shell uname) @@ -22,6 +23,15 @@ ifeq (0,$(shell pkg-config --exists lxc; echo $$?)) HAS_LXC="true" endif +ifeq ($(TRAVIS),true) +$(info Running in Travis, verbose mode is disabled) +else +VERBOSE="true" +endif + +print-% : ; @echo $* = $($*) + + ALL_TARGETS += linux_386 \ linux_amd64 \ linux_arm \ @@ -227,17 +237,13 @@ test: ## Run the Nomad test suite and/or the Nomad UI test suite test-nomad: dev ## Run Nomad test suites @echo "==> Running Nomad test suites:" @NOMAD_TEST_RKT=1 \ - go test \ - -v \ + go test $(if $(VERBOSE),-v) \ -cover \ -timeout=900s \ - -tags="nomad_test $(if $(HAS_LXC),lxc)" ./... >test.log ; echo $$? > exit-code - @echo "Exit code: $$(cat exit-code)" >> test.log - @grep -A1 -- '--- FAIL:' test.log || true - @grep '^FAIL' test.log || true - @grep -A10 'panic' test.log || true - @test "$$TRAVIS" == "true" && cat test.log || true - @if [ "$$(cat exit-code)" == "0" ] ; then echo "PASS" ; exit 0 ; else exit 1 ; fi + -tags="nomad_test $(if $(HAS_LXC),lxc)" ./... $(if $(VERBOSE), >test.log ; echo $$? > exit-code) + @if [ $(VERBOSE) ] ; then \ + bash -C "$(PROJECT_ROOT)/scripts/test_check.sh" ; \ + fi .PHONY: clean clean: GOPATH=$(shell go env GOPATH) diff --git a/scripts/test_check.sh b/scripts/test_check.sh new file mode 100755 index 000000000..4110f5c89 --- /dev/null +++ b/scripts/test_check.sh @@ -0,0 +1,10 @@ +#!/usr/bin/env bash +echo "Exit code: $(cat exit-code)" >> test.log; +grep -A10 'panic: test timed out' test.log || true; +grep -A1 -- '--- SKIP:' test.log || true; +grep -A1 -- '--- FAIL:' test.log || true; +grep '^FAIL' test.log || true; +exit_code=`cat exit-code` +echo $exit_code +if [ ${exit_code} == "0" ]; then echo "PASS" ; exit 0 ; else echo "TESTS FAILED"; exit 1 ; fi + From c8b5b204abb4378fecb4c545ba60603aa00f3e65 Mon Sep 17 00:00:00 2001 From: Preetha Appan Date: Wed, 6 Dec 2017 13:36:46 -0600 Subject: [PATCH 05/13] Remove newline --- GNUmakefile | 1 - 1 file changed, 1 deletion(-) diff --git a/GNUmakefile b/GNUmakefile index a4e304b6d..034b060b0 100644 --- a/GNUmakefile +++ b/GNUmakefile @@ -1,4 +1,3 @@ - SHELL = bash PROJECT_ROOT := $(patsubst %/,%,$(dir $(abspath $(lastword $(MAKEFILE_LIST))))) THIS_OS := $(shell uname) From 7f6c7bee1ae0706710b8c454474a7dd11bfddba5 Mon Sep 17 00:00:00 2001 From: Preetha Appan Date: Wed, 6 Dec 2017 18:29:25 -0600 Subject: [PATCH 06/13] Removes variable value printer --- GNUmakefile | 2 -- 1 file changed, 2 deletions(-) diff --git a/GNUmakefile b/GNUmakefile index 034b060b0..9608add4c 100644 --- a/GNUmakefile +++ b/GNUmakefile @@ -28,8 +28,6 @@ else VERBOSE="true" endif -print-% : ; @echo $* = $($*) - ALL_TARGETS += linux_386 \ linux_amd64 \ From de90db139a37ca19c53e8b45edd36953561eea48 Mon Sep 17 00:00:00 2001 From: Kyle Havlovitz Date: Tue, 21 Nov 2017 16:29:11 -0800 Subject: [PATCH 07/13] Added support for v2 raft APIs and -raft-protocol option --- api/operator.go | 3 + command/agent/agent.go | 4 + command/agent/command.go | 5 + command/agent/config.go | 6 + command/agent/config_test.go | 1 + command/operator_raft_list.go | 6 +- nomad/config.go | 9 +- nomad/leader.go | 108 ++++++++++++++---- nomad/leader_test.go | 91 +++++++++++++++ nomad/operator_endpoint.go | 3 + nomad/operator_endpoint_test.go | 22 ++-- nomad/serf.go | 13 ++- nomad/server.go | 7 +- nomad/structs/operator.go | 3 + nomad/util.go | 44 +++++++ nomad/util_test.go | 100 ++++++++++++++++ .../docs/agent/configuration/server.html.md | 5 + 17 files changed, 391 insertions(+), 39 deletions(-) diff --git a/api/operator.go b/api/operator.go index a83d54cb3..d1761569c 100644 --- a/api/operator.go +++ b/api/operator.go @@ -32,6 +32,9 @@ type RaftServer struct { // it's a non-voting server, which will be added in a future release of // Nomad. Voter bool + + // RaftProtocol is the version of the Raft protocol spoken by this server. + RaftProtocol string } // RaftConfigration is returned when querying for the current Raft configuration. diff --git a/command/agent/agent.go b/command/agent/agent.go index c66bdaeb2..de05400fa 100644 --- a/command/agent/agent.go +++ b/command/agent/agent.go @@ -22,6 +22,7 @@ import ( "github.com/hashicorp/nomad/nomad" "github.com/hashicorp/nomad/nomad/structs" "github.com/hashicorp/nomad/nomad/structs/config" + "github.com/hashicorp/raft" ) const ( @@ -141,6 +142,9 @@ func convertServerConfig(agentConfig *Config, logOutput io.Writer) (*nomad.Confi if agentConfig.Server.ProtocolVersion != 0 { conf.ProtocolVersion = uint8(agentConfig.Server.ProtocolVersion) } + if agentConfig.Server.RaftProtocol != 0 { + conf.RaftConfig.ProtocolVersion = raft.ProtocolVersion(agentConfig.Server.RaftProtocol) + } if agentConfig.Server.NumSchedulers != 0 { conf.NumSchedulers = agentConfig.Server.NumSchedulers } diff --git a/command/agent/command.go b/command/agent/command.go index 65af1f85d..c1be2286e 100644 --- a/command/agent/command.go +++ b/command/agent/command.go @@ -83,6 +83,7 @@ func (c *Command) readConfig() *Config { flags.IntVar(&cmdConfig.Server.RetryMaxAttempts, "retry-max", 0, "") flags.StringVar(&cmdConfig.Server.RetryInterval, "retry-interval", "", "") flags.StringVar(&cmdConfig.Server.EncryptKey, "encrypt", "", "gossip encryption key") + flags.IntVar(&cmdConfig.Server.RaftProtocol, "raft-protocol", 0, "") // Client-only options flags.StringVar(&cmdConfig.Client.StateDir, "state-dir", "", "") @@ -876,6 +877,10 @@ Server Options: Address of an agent to join at start time. Can be specified multiple times. + -raft-protocol= + The Raft protocol version to use. Used for enabling certain Autopilot + features. Defaults to 2. + -retry-join=
Address of an agent to join at start time with retries enabled. Can be specified multiple times. diff --git a/command/agent/config.go b/command/agent/config.go index 08e8d2b78..8802c19ff 100644 --- a/command/agent/config.go +++ b/command/agent/config.go @@ -256,6 +256,9 @@ type ServerConfig struct { // ProtocolVersionMin and ProtocolVersionMax. ProtocolVersion int `mapstructure:"protocol_version"` + // RaftProtocol is the Raft protocol version to speak. This must be from [1-3]. + RaftProtocol int `mapstructure:"raft_protocol"` + // NumSchedulers is the number of scheduler thread that are run. // This can be as many as one per core, or zero to disable this server // from doing any scheduling work. @@ -976,6 +979,9 @@ func (a *ServerConfig) Merge(b *ServerConfig) *ServerConfig { if b.ProtocolVersion != 0 { result.ProtocolVersion = b.ProtocolVersion } + if b.RaftProtocol != 0 { + result.RaftProtocol = b.RaftProtocol + } if b.NumSchedulers != 0 { result.NumSchedulers = b.NumSchedulers } diff --git a/command/agent/config_test.go b/command/agent/config_test.go index 0324be6fd..67d75d480 100644 --- a/command/agent/config_test.go +++ b/command/agent/config_test.go @@ -234,6 +234,7 @@ func TestConfig_Merge(t *testing.T) { BootstrapExpect: 2, DataDir: "/tmp/data2", ProtocolVersion: 2, + RaftProtocol: 2, NumSchedulers: 2, EnabledSchedulers: []string{structs.JobTypeBatch}, NodeGCThreshold: "12h", diff --git a/command/operator_raft_list.go b/command/operator_raft_list.go index 508bbb783..6295dae48 100644 --- a/command/operator_raft_list.go +++ b/command/operator_raft_list.go @@ -79,14 +79,14 @@ func (c *OperatorRaftListCommand) Run(args []string) int { } // Format it as a nice table. - result := []string{"Node|ID|Address|State|Voter"} + result := []string{"Node|ID|Address|State|Voter|RaftProtocol"} for _, s := range reply.Servers { state := "follower" if s.Leader { state = "leader" } - result = append(result, fmt.Sprintf("%s|%s|%s|%s|%v", - s.Node, s.ID, s.Address, state, s.Voter)) + result = append(result, fmt.Sprintf("%s|%s|%s|%s|%v|%s", + s.Node, s.ID, s.Address, state, s.Voter, s.RaftProtocol)) } c.Ui.Output(columnize.SimpleFormat(result)) diff --git a/nomad/config.go b/nomad/config.go index bc7f715c9..4a918f393 100644 --- a/nomad/config.go +++ b/nomad/config.go @@ -10,6 +10,7 @@ import ( "github.com/hashicorp/memberlist" "github.com/hashicorp/nomad/helper/tlsutil" + "github.com/hashicorp/nomad/helper/uuid" "github.com/hashicorp/nomad/nomad/structs" "github.com/hashicorp/nomad/nomad/structs/config" "github.com/hashicorp/nomad/scheduler" @@ -98,6 +99,9 @@ type Config struct { // Node name is the name we use to advertise. Defaults to hostname. NodeName string + // NodeID is the uuid of this server. + NodeID string + // Region is the region this Nomad server belongs to. Region string @@ -283,6 +287,7 @@ func DefaultConfig() *Config { AuthoritativeRegion: DefaultRegion, Datacenter: DefaultDC, NodeName: hostname, + NodeID: uuid.Generate(), ProtocolVersion: ProtocolVersionMax, RaftConfig: raft.DefaultConfig(), RaftTimeout: 10 * time.Second, @@ -339,9 +344,9 @@ func DefaultConfig() *Config { // Disable shutdown on removal c.RaftConfig.ShutdownOnRemove = false - // Enable interoperability with unversioned Raft library, and don't + // Enable interoperability with raft protocol version 1, and don't // start using new ID-based features yet. - c.RaftConfig.ProtocolVersion = 1 + c.RaftConfig.ProtocolVersion = 2 return c } diff --git a/nomad/leader.go b/nomad/leader.go index 1b13bf86d..3910f5f58 100644 --- a/nomad/leader.go +++ b/nomad/leader.go @@ -746,8 +746,8 @@ func (s *Server) addRaftPeer(m serf.Member, parts *serverParts) error { } // Check for possibility of multiple bootstrap nodes + members := s.serf.Members() if parts.Bootstrap { - members := s.serf.Members() for _, member := range members { valid, p := isNomadServer(member) if valid && member.Name != m.Name && p.Bootstrap { @@ -757,12 +757,10 @@ func (s *Server) addRaftPeer(m serf.Member, parts *serverParts) error { } } - // TODO (alexdadgar) - This will need to be changed once we support node IDs. - addr := (&net.TCPAddr{IP: m.Addr, Port: parts.Port}).String() - // See if it's already in the configuration. It's harmless to re-add it // but we want to avoid doing that if possible to prevent useless Raft // log entries. + addr := (&net.TCPAddr{IP: m.Addr, Port: parts.Port}).String() configFuture := s.raft.GetConfiguration() if err := configFuture.Error(); err != nil { s.logger.Printf("[ERR] nomad: failed to get raft configuration: %v", err) @@ -774,14 +772,64 @@ func (s *Server) addRaftPeer(m serf.Member, parts *serverParts) error { } } - // Attempt to add as a peer - addFuture := s.raft.AddPeer(raft.ServerAddress(addr)) - if err := addFuture.Error(); err != nil { - s.logger.Printf("[ERR] nomad: failed to add raft peer: %v", err) + // See if it's already in the configuration. It's harmless to re-add it + // but we want to avoid doing that if possible to prevent useless Raft + // log entries. If the address is the same but the ID changed, remove the + // old server before adding the new one. + minRaftProtocol, err := MinRaftProtocol(s.config.Datacenter, members) + if err != nil { return err - } else if err == nil { - s.logger.Printf("[INFO] nomad: added raft peer: %v", parts) } + for _, server := range configFuture.Configuration().Servers { + // No-op if the raft version is too low + if server.Address == raft.ServerAddress(addr) && (minRaftProtocol < 2 || parts.RaftVersion < 3) { + return nil + } + + // If the address or ID matches an existing server, see if we need to remove the old one first + if server.Address == raft.ServerAddress(addr) || server.ID == raft.ServerID(parts.ID) { + // Exit with no-op if this is being called on an existing server + if server.Address == raft.ServerAddress(addr) && server.ID == raft.ServerID(parts.ID) { + return nil + } + future := s.raft.RemoveServer(server.ID, 0, 0) + if server.Address == raft.ServerAddress(addr) { + if err := future.Error(); err != nil { + return fmt.Errorf("error removing server with duplicate address %q: %s", server.Address, err) + } + s.logger.Printf("[INFO] nomad: removed server with duplicate address: %s", server.Address) + } else { + if err := future.Error(); err != nil { + return fmt.Errorf("error removing server with duplicate ID %q: %s", server.ID, err) + } + s.logger.Printf("[INFO] nomad: removed server with duplicate ID: %s", server.ID) + } + } + } + + // Attempt to add as a peer + switch { + case minRaftProtocol >= 3: + // todo(kyhavlov): change this to AddNonVoter when adding autopilot + addFuture := s.raft.AddVoter(raft.ServerID(parts.ID), raft.ServerAddress(addr), 0, 0) + if err := addFuture.Error(); err != nil { + s.logger.Printf("[ERR] nomad: failed to add raft peer: %v", err) + return err + } + case minRaftProtocol == 2 && parts.RaftVersion >= 3: + addFuture := s.raft.AddVoter(raft.ServerID(parts.ID), raft.ServerAddress(addr), 0, 0) + if err := addFuture.Error(); err != nil { + s.logger.Printf("[ERR] nomad: failed to add raft peer: %v", err) + return err + } + default: + addFuture := s.raft.AddPeer(raft.ServerAddress(addr)) + if err := addFuture.Error(); err != nil { + s.logger.Printf("[ERR] nomad: failed to add raft peer: %v", err) + return err + } + } + return nil } @@ -799,21 +847,37 @@ func (s *Server) removeRaftPeer(m serf.Member, parts *serverParts) error { s.logger.Printf("[ERR] nomad: failed to get raft configuration: %v", err) return err } - for _, server := range configFuture.Configuration().Servers { - if server.Address == raft.ServerAddress(addr) { - goto REMOVE - } - } - return nil -REMOVE: - // Attempt to remove as a peer. - future := s.raft.RemovePeer(raft.ServerAddress(addr)) - if err := future.Error(); err != nil { - s.logger.Printf("[ERR] nomad: failed to remove raft peer '%v': %v", - parts, err) + minRaftProtocol, err := MinRaftProtocol(s.config.Datacenter, s.serf.Members()) + if err != nil { return err } + + // Pick which remove API to use based on how the server was added. + for _, server := range configFuture.Configuration().Servers { + // If we understand the new add/remove APIs and the server was added by ID, use the new remove API + if minRaftProtocol >= 2 && server.ID == raft.ServerID(parts.ID) { + s.logger.Printf("[INFO] nomad: removing server by ID: %q", server.ID) + future := s.raft.RemoveServer(raft.ServerID(parts.ID), 0, 0) + if err := future.Error(); err != nil { + s.logger.Printf("[ERR] nomad: failed to remove raft peer '%v': %v", + server.ID, err) + return err + } + break + } else if server.Address == raft.ServerAddress(addr) { + // If not, use the old remove API + s.logger.Printf("[INFO] nomad: removing server by address: %q", server.Address) + future := s.raft.RemovePeer(raft.ServerAddress(addr)) + if err := future.Error(); err != nil { + s.logger.Printf("[ERR] nomad: failed to remove raft peer '%v': %v", + addr, err) + return err + } + break + } + } + return nil } diff --git a/nomad/leader_test.go b/nomad/leader_test.go index 814e29d1f..05d534ad2 100644 --- a/nomad/leader_test.go +++ b/nomad/leader_test.go @@ -811,3 +811,94 @@ func TestLeader_DiffACLTokens(t *testing.T) { // P2 is un-modified - ignore. P3 modified, P4 new. assert.Equal(t, []string{p3.AccessorID, p4.AccessorID}, update) } + +func TestLeader_UpgradeRaftVersion(t *testing.T) { + t.Parallel() + s1 := testServer(t, func(c *Config) { + c.Datacenter = "dc1" + c.RaftConfig.ProtocolVersion = 2 + }) + defer s1.Shutdown() + + s2 := testServer(t, func(c *Config) { + c.DevDisableBootstrap = true + c.Datacenter = "dc1" + c.RaftConfig.ProtocolVersion = 1 + }) + defer s2.Shutdown() + + s3 := testServer(t, func(c *Config) { + c.DevDisableBootstrap = true + c.Datacenter = "dc1" + c.RaftConfig.ProtocolVersion = 2 + }) + defer s3.Shutdown() + + servers := []*Server{s1, s2, s3} + + // Try to join + testJoin(t, s1, s2, s3) + + for _, s := range servers { + testutil.WaitForResult(func() (bool, error) { + peers, _ := s.numPeers() + return peers == 3, nil + }, func(err error) { + t.Fatalf("should have 3 peers") + }) + } + + // Kill the v1 server + if err := s2.Leave(); err != nil { + t.Fatal(err) + } + + for _, s := range []*Server{s1, s3} { + minVer, err := MinRaftProtocol("dc1", s.Members()) + if err != nil { + t.Fatal(err) + } + if got, want := minVer, 2; got != want { + t.Fatalf("got min raft version %d want %d", got, want) + } + } + + // Replace the dead server with one running raft protocol v3 + s4 := testServer(t, func(c *Config) { + c.DevDisableBootstrap = true + c.Datacenter = "dc1" + c.RaftConfig.ProtocolVersion = 3 + }) + defer s4.Shutdown() + testJoin(t, s1, s4) + servers[1] = s4 + + // Make sure we're back to 3 total peers with the new one added via ID + for _, s := range servers { + testutil.WaitForResult(func() (bool, error) { + addrs := 0 + ids := 0 + future := s.raft.GetConfiguration() + if err := future.Error(); err != nil { + return false, err + } + for _, server := range future.Configuration().Servers { + if string(server.ID) == string(server.Address) { + addrs++ + } else { + ids++ + } + } + if got, want := addrs, 2; got != want { + return false, fmt.Errorf("got %d server addresses want %d", got, want) + } + if got, want := ids, 1; got != want { + return false, fmt.Errorf("got %d server ids want %d", got, want) + } + + return true, nil + }, func(err error) { + t.Fatal(err) + }) + } +} diff --git a/nomad/operator_endpoint.go b/nomad/operator_endpoint.go index 69bc81294..10c84f536 100644 --- a/nomad/operator_endpoint.go +++ b/nomad/operator_endpoint.go @@ -51,8 +51,10 @@ func (op *Operator) RaftGetConfiguration(args *structs.GenericRequest, reply *st reply.Index = future.Index() for _, server := range future.Configuration().Servers { node := "(unknown)" + raftProtocolVersion := "unknown" if member, ok := serverMap[server.Address]; ok { node = member.Name + raftProtocolVersion = member.Tags["raft_vsn"] } entry := &structs.RaftServer{ @@ -61,6 +63,7 @@ func (op *Operator) RaftGetConfiguration(args *structs.GenericRequest, reply *st Address: server.Address, Leader: server.Address == leader, Voter: server.Suffrage == raft.Voter, + RaftProtocol: raftProtocolVersion, } reply.Servers = append(reply.Servers, entry) } diff --git a/nomad/operator_endpoint_test.go b/nomad/operator_endpoint_test.go index 82d830f1c..9c211fb0e 100644 --- a/nomad/operator_endpoint_test.go +++ b/nomad/operator_endpoint_test.go @@ -44,11 +44,12 @@ func TestOperator_RaftGetConfiguration(t *testing.T) { expected := structs.RaftConfigurationResponse{ Servers: []*structs.RaftServer{ { - ID: me.ID, - Node: fmt.Sprintf("%v.%v", s1.config.NodeName, s1.config.Region), - Address: me.Address, - Leader: true, - Voter: true, + ID: me.ID, + Node: fmt.Sprintf("%v.%v", s1.config.NodeName, s1.config.Region), + Address: me.Address, + Leader: true, + Voter: true, + RaftProtocol: fmt.Sprintf("%d", s1.config.RaftConfig.ProtocolVersion), }, }, Index: future.Index(), @@ -107,11 +108,12 @@ func TestOperator_RaftGetConfiguration_ACL(t *testing.T) { expected := structs.RaftConfigurationResponse{ Servers: []*structs.RaftServer{ { - ID: me.ID, - Node: fmt.Sprintf("%v.%v", s1.config.NodeName, s1.config.Region), - Address: me.Address, - Leader: true, - Voter: true, + ID: me.ID, + Node: fmt.Sprintf("%v.%v", s1.config.NodeName, s1.config.Region), + Address: me.Address, + Leader: true, + Voter: true, + RaftProtocol: fmt.Sprintf("%d", s1.config.RaftConfig.ProtocolVersion), }, }, Index: future.Index(), diff --git a/nomad/serf.go b/nomad/serf.go index ad6c58d0c..4d8aa90bd 100644 --- a/nomad/serf.go +++ b/nomad/serf.go @@ -184,11 +184,22 @@ func (s *Server) maybeBootstrap() { // Attempt a live bootstrap! var configuration raft.Configuration var addrs []string + minRaftVersion, err := MinRaftProtocol(s.config.Datacenter, members) + if err != nil { + s.logger.Printf("[ERR] consul: Failed to read server raft versions: %v", err) + } + for _, server := range servers { addr := server.Addr.String() addrs = append(addrs, addr) + var id raft.ServerID + if minRaftVersion >= 3 { + id = raft.ServerID(server.ID) + } else { + id = raft.ServerID(addr) + } peer := raft.Server{ - ID: raft.ServerID(addr), + ID: id, Address: raft.ServerAddress(addr), } configuration.Servers = append(configuration.Servers, peer) diff --git a/nomad/server.go b/nomad/server.go index 018958473..1bd77e3bb 100644 --- a/nomad/server.go +++ b/nomad/server.go @@ -835,6 +835,9 @@ func (s *Server) setupRaft() error { // Our version of Raft protocol requires the LocalID to match the network // address of the transport. s.config.RaftConfig.LocalID = raft.ServerID(trans.LocalAddr()) + if s.config.RaftConfig.ProtocolVersion >= 3 { + s.config.RaftConfig.LocalID = raft.ServerID(s.config.NodeID) + } // Build an all in-memory setup for dev mode, otherwise prepare a full // disk-based setup. @@ -937,7 +940,7 @@ func (s *Server) setupRaft() error { configuration := raft.Configuration{ Servers: []raft.Server{ { - ID: raft.ServerID(trans.LocalAddr()), + ID: s.config.RaftConfig.LocalID, Address: trans.LocalAddr(), }, }, @@ -972,6 +975,8 @@ func (s *Server) setupSerf(conf *serf.Config, ch chan serf.Event, path string) ( conf.Tags["vsn"] = fmt.Sprintf("%d", structs.ApiMajorVersion) conf.Tags["mvn"] = fmt.Sprintf("%d", structs.ApiMinorVersion) conf.Tags["build"] = s.config.Build + conf.Tags["raft_vsn"] = fmt.Sprintf("%d", s.config.RaftConfig.ProtocolVersion) + conf.Tags["id"] = s.config.NodeID conf.Tags["port"] = fmt.Sprintf("%d", s.rpcAdvertise.(*net.TCPAddr).Port) if s.config.Bootstrap || (s.config.DevMode && !s.config.DevDisableBootstrap) { conf.Tags["bootstrap"] = "1" diff --git a/nomad/structs/operator.go b/nomad/structs/operator.go index 93b99f6fb..22e37ae79 100644 --- a/nomad/structs/operator.go +++ b/nomad/structs/operator.go @@ -26,6 +26,9 @@ type RaftServer struct { // it's a non-voting server, which will be added in a future release of // Nomad. Voter bool + + // RaftProtocol is the version of the Raft protocol spoken by this server. + RaftProtocol string } // RaftConfigrationResponse is returned when querying for the current Raft diff --git a/nomad/util.go b/nomad/util.go index b19129aac..b7a723bee 100644 --- a/nomad/util.go +++ b/nomad/util.go @@ -36,6 +36,7 @@ func RuntimeStats() map[string]string { // serverParts is used to return the parts of a server role type serverParts struct { Name string + ID string Region string Datacenter string Port int @@ -44,6 +45,7 @@ type serverParts struct { MajorVersion int MinorVersion int Build version.Version + RaftVersion int Addr net.Addr Status serf.MemberStatus } @@ -60,6 +62,7 @@ func isNomadServer(m serf.Member) (bool, *serverParts) { return false, nil } + id := m.Tags["id"] region := m.Tags["region"] datacenter := m.Tags["dc"] _, bootstrap := m.Tags["bootstrap"] @@ -100,9 +103,19 @@ func isNomadServer(m serf.Member) (bool, *serverParts) { minorVersion = 0 } + raft_vsn := 0 + raft_vsn_str, ok := m.Tags["raft_vsn"] + if ok { + raft_vsn, err = strconv.Atoi(raft_vsn_str) + if err != nil { + return false, nil + } + } + addr := &net.TCPAddr{IP: m.Addr, Port: port} parts := &serverParts{ Name: m.Name, + ID: id, Region: region, Datacenter: datacenter, Port: port, @@ -112,6 +125,7 @@ func isNomadServer(m serf.Member) (bool, *serverParts) { MajorVersion: majorVersion, MinorVersion: minorVersion, Build: *build_version, + RaftVersion: raft_vsn, Status: m.Status, } return true, parts @@ -131,6 +145,36 @@ func ServersMeetMinimumVersion(members []serf.Member, minVersion *version.Versio return true } +// MinRaftProtocol returns the lowest supported Raft protocol among alive servers +// in the given datacenter. +func MinRaftProtocol(datacenter string, members []serf.Member) (int, error) { + minVersion := -1 + for _, m := range members { + if m.Tags["role"] != "nomad" || m.Tags["dc"] != datacenter || m.Status != serf.StatusAlive { + continue + } + + vsn, ok := m.Tags["raft_vsn"] + if !ok { + vsn = "1" + } + raftVsn, err := strconv.Atoi(vsn) + if err != nil { + return -1, err + } + + if minVersion == -1 || raftVsn < minVersion { + minVersion = raftVsn + } + } + + if minVersion == -1 { + return minVersion, fmt.Errorf("no servers found") + } + + return minVersion, nil +} + // shuffleStrings randomly shuffles the list of strings func shuffleStrings(list []string) { for i := range list { diff --git a/nomad/util_test.go b/nomad/util_test.go index 2ad50248f..cf28a2b22 100644 --- a/nomad/util_test.go +++ b/nomad/util_test.go @@ -1,6 +1,7 @@ package nomad import ( + "errors" "net" "reflect" "testing" @@ -151,6 +152,105 @@ func TestServersMeetMinimumVersion(t *testing.T) { } } +func TestMinRaftProtocol(t *testing.T) { + t.Parallel() + makeMember := func(version, datacenter string) serf.Member { + return serf.Member{ + Name: "foo", + Addr: net.IP([]byte{127, 0, 0, 1}), + Tags: map[string]string{ + "role": "nomad", + "region": "aws", + "dc": datacenter, + "port": "10000", + "vsn": "1", + "raft_vsn": version, + }, + Status: serf.StatusAlive, + } + } + + cases := []struct { + members []serf.Member + datacenter string + expected int + err error + }{ + // No servers, error + { + members: []serf.Member{}, + expected: -1, + err: errors.New("no servers found"), + }, + // One server + { + members: []serf.Member{ + makeMember("1", "dc1"), + }, + datacenter: "dc1", + expected: 1, + }, + // One server, bad version formatting + { + members: []serf.Member{ + makeMember("asdf", "dc1"), + }, + datacenter: "dc1", + expected: -1, + err: errors.New(`strconv.Atoi: parsing "asdf": invalid syntax`), + }, + // One server, wrong datacenter + { + members: []serf.Member{ + makeMember("1", "dc1"), + }, + datacenter: "dc2", + expected: -1, + err: errors.New("no servers found"), + }, + // Multiple servers, different versions + { + members: []serf.Member{ + makeMember("1", "dc1"), + makeMember("2", "dc1"), + }, + datacenter: "dc1", + expected: 1, + }, + // Multiple servers, same version + { + members: []serf.Member{ + makeMember("2", "dc1"), + makeMember("2", "dc1"), + }, + datacenter: "dc1", + expected: 2, + }, + // Multiple servers, multiple datacenters + { + members: []serf.Member{ + makeMember("3", "dc1"), + makeMember("2", "dc1"), + makeMember("1", "dc2"), + }, + datacenter: "dc1", + expected: 2, + }, + } + + for _, tc := range cases { + result, err := MinRaftProtocol(tc.datacenter, tc.members) + if result != tc.expected { + t.Fatalf("bad: %v, %v, %v", result, tc.expected, tc) + } + if tc.err != nil { + if err == nil || tc.err.Error() != err.Error() { + t.Fatalf("bad: %v, %v, %v", err, tc.err, tc) + } + } + } +} + func TestShuffleStrings(t *testing.T) { t.Parallel() // Generate input diff --git a/website/source/docs/agent/configuration/server.html.md b/website/source/docs/agent/configuration/server.html.md index 265db668d..53f30b6a3 100644 --- a/website/source/docs/agent/configuration/server.html.md +++ b/website/source/docs/agent/configuration/server.html.md @@ -112,6 +112,11 @@ server { required as the agent internally knows the latest version, but may be useful in some upgrade scenarios. +- `raft_protocol` `(int: 2)` - Specifies the Raft protocol version to use when + communicating with other Nomad servers. This affects available Autopilot + features and is typically not required as the agent internally knows the + latest version, but may be useful in some upgrade scenarios. + - `rejoin_after_leave` `(bool: false)` - Specifies if Nomad will ignore a previous leave and attempt to rejoin the cluster when starting. By default, Nomad treats leave as a permanent intent and does not attempt to join the From 57492977314d6e00bc2e5543cc13c9357d482344 Mon Sep 17 00:00:00 2001 From: Kyle Havlovitz Date: Mon, 27 Nov 2017 14:46:37 -0800 Subject: [PATCH 08/13] Add missing exist checks and doc line --- nomad/operator_endpoint.go | 14 ++++++++------ nomad/util.go | 5 ++++- website/source/api/operator.html.md | 1 + 3 files changed, 13 insertions(+), 7 deletions(-) diff --git a/nomad/operator_endpoint.go b/nomad/operator_endpoint.go index 10c84f536..0edfc4b71 100644 --- a/nomad/operator_endpoint.go +++ b/nomad/operator_endpoint.go @@ -54,15 +54,17 @@ func (op *Operator) RaftGetConfiguration(args *structs.GenericRequest, reply *st raftProtocolVersion := "unknown" if member, ok := serverMap[server.Address]; ok { node = member.Name - raftProtocolVersion = member.Tags["raft_vsn"] + if raftVsn, ok := member.Tags["raft_vsn"]; ok { + raftProtocolVersion = raftVsn + } } entry := &structs.RaftServer{ - ID: server.ID, - Node: node, - Address: server.Address, - Leader: server.Address == leader, - Voter: server.Suffrage == raft.Voter, + ID: server.ID, + Node: node, + Address: server.Address, + Leader: server.Address == leader, + Voter: server.Suffrage == raft.Voter, RaftProtocol: raftProtocolVersion, } reply.Servers = append(reply.Servers, entry) diff --git a/nomad/util.go b/nomad/util.go index b7a723bee..5cae76309 100644 --- a/nomad/util.go +++ b/nomad/util.go @@ -62,7 +62,10 @@ func isNomadServer(m serf.Member) (bool, *serverParts) { return false, nil } - id := m.Tags["id"] + id := "unknown" + if v, ok := m.Tags["id"]; ok { + id = v + } region := m.Tags["region"] datacenter := m.Tags["dc"] _, bootstrap := m.Tags["bootstrap"] diff --git a/website/source/api/operator.html.md b/website/source/api/operator.html.md index 22aed2584..5d71d3e1e 100644 --- a/website/source/api/operator.html.md +++ b/website/source/api/operator.html.md @@ -59,6 +59,7 @@ $ curl \ "ID": "127.0.0.1:4647", "Leader": true, "Node": "bacon-mac.global", + "RaftProtocol": 2, "Voter": true } ] From 933cad25433784698af5073aee8ae2d455ab6d79 Mon Sep 17 00:00:00 2001 From: Kyle Havlovitz Date: Mon, 4 Dec 2017 12:35:41 -0800 Subject: [PATCH 09/13] Use region instead of datacenter for version checking --- nomad/leader.go | 4 +-- nomad/leader_test.go | 2 +- nomad/serf.go | 4 +-- nomad/util.go | 6 ++--- nomad/util_test.go | 64 ++++++++++++++++++++++---------------------- 5 files changed, 40 insertions(+), 40 deletions(-) diff --git a/nomad/leader.go b/nomad/leader.go index 3910f5f58..b7be18c06 100644 --- a/nomad/leader.go +++ b/nomad/leader.go @@ -776,7 +776,7 @@ func (s *Server) addRaftPeer(m serf.Member, parts *serverParts) error { // but we want to avoid doing that if possible to prevent useless Raft // log entries. If the address is the same but the ID changed, remove the // old server before adding the new one. - minRaftProtocol, err := MinRaftProtocol(s.config.Datacenter, members) + minRaftProtocol, err := MinRaftProtocol(s.config.Region, members) if err != nil { return err } @@ -848,7 +848,7 @@ func (s *Server) removeRaftPeer(m serf.Member, parts *serverParts) error { return err } - minRaftProtocol, err := MinRaftProtocol(s.config.Datacenter, s.serf.Members()) + minRaftProtocol, err := MinRaftProtocol(s.config.Region, s.serf.Members()) if err != nil { return err } diff --git a/nomad/leader_test.go b/nomad/leader_test.go index 05d534ad2..765f2638f 100644 --- a/nomad/leader_test.go +++ b/nomad/leader_test.go @@ -854,7 +854,7 @@ func TestLeader_UpgradeRaftVersion(t *testing.T) { } for _, s := range []*Server{s1, s3} { - minVer, err := MinRaftProtocol("dc1", s.Members()) + minVer, err := MinRaftProtocol(s1.config.Region, s.Members()) if err != nil { t.Fatal(err) } diff --git a/nomad/serf.go b/nomad/serf.go index 4d8aa90bd..011d7b358 100644 --- a/nomad/serf.go +++ b/nomad/serf.go @@ -184,9 +184,9 @@ func (s *Server) maybeBootstrap() { // Attempt a live bootstrap! var configuration raft.Configuration var addrs []string - minRaftVersion, err := MinRaftProtocol(s.config.Datacenter, members) + minRaftVersion, err := MinRaftProtocol(s.config.Region, members) if err != nil { - s.logger.Printf("[ERR] consul: Failed to read server raft versions: %v", err) + s.logger.Printf("[ERR] nomad: Failed to read server raft versions: %v", err) } for _, server := range servers { diff --git a/nomad/util.go b/nomad/util.go index 5cae76309..8f789a969 100644 --- a/nomad/util.go +++ b/nomad/util.go @@ -149,11 +149,11 @@ func ServersMeetMinimumVersion(members []serf.Member, minVersion *version.Versio } // MinRaftProtocol returns the lowest supported Raft protocol among alive servers -// in the given datacenter. -func MinRaftProtocol(datacenter string, members []serf.Member) (int, error) { +// in the given region. +func MinRaftProtocol(region string, members []serf.Member) (int, error) { minVersion := -1 for _, m := range members { - if m.Tags["role"] != "nomad" || m.Tags["dc"] != datacenter || m.Status != serf.StatusAlive { + if m.Tags["role"] != "nomad" || m.Tags["region"] != region || m.Status != serf.StatusAlive { continue } diff --git a/nomad/util_test.go b/nomad/util_test.go index cf28a2b22..82e939491 100644 --- a/nomad/util_test.go +++ b/nomad/util_test.go @@ -154,14 +154,14 @@ func TestServersMeetMinimumVersion(t *testing.T) { func TestMinRaftProtocol(t *testing.T) { t.Parallel() - makeMember := func(version, datacenter string) serf.Member { + makeMember := func(version, region string) serf.Member { return serf.Member{ Name: "foo", Addr: net.IP([]byte{127, 0, 0, 1}), Tags: map[string]string{ "role": "nomad", - "region": "aws", - "dc": datacenter, + "region": region, + "dc": "dc1", "port": "10000", "vsn": "1", "raft_vsn": version, @@ -171,10 +171,10 @@ func TestMinRaftProtocol(t *testing.T) { } cases := []struct { - members []serf.Member - datacenter string - expected int - err error + members []serf.Member + region string + expected int + err error }{ // No servers, error { @@ -185,61 +185,61 @@ func TestMinRaftProtocol(t *testing.T) { // One server { members: []serf.Member{ - makeMember("1", "dc1"), + makeMember("1", "global"), }, - datacenter: "dc1", - expected: 1, + region: "global", + expected: 1, }, // One server, bad version formatting { members: []serf.Member{ - makeMember("asdf", "dc1"), + makeMember("asdf", "global"), }, - datacenter: "dc1", - expected: -1, - err: errors.New(`strconv.Atoi: parsing "asdf": invalid syntax`), + region: "global", + expected: -1, + err: errors.New(`strconv.Atoi: parsing "asdf": invalid syntax`), }, // One server, wrong datacenter { members: []serf.Member{ - makeMember("1", "dc1"), + makeMember("1", "global"), }, - datacenter: "dc2", - expected: -1, - err: errors.New("no servers found"), + region: "nope", + expected: -1, + err: errors.New("no servers found"), }, // Multiple servers, different versions { members: []serf.Member{ - makeMember("1", "dc1"), - makeMember("2", "dc1"), + makeMember("1", "global"), + makeMember("2", "global"), }, - datacenter: "dc1", - expected: 1, + region: "global", + expected: 1, }, // Multiple servers, same version { members: []serf.Member{ - makeMember("2", "dc1"), - makeMember("2", "dc1"), + makeMember("2", "global"), + makeMember("2", "global"), }, - datacenter: "dc1", - expected: 2, + region: "global", + expected: 2, }, // Multiple servers, multiple datacenters { members: []serf.Member{ - makeMember("3", "dc1"), - makeMember("2", "dc1"), - makeMember("1", "dc2"), + makeMember("3", "r1"), + makeMember("2", "r1"), + makeMember("1", "r2"), }, - datacenter: "dc1", - expected: 2, + region: "r1", + expected: 2, }, } for _, tc := range cases { - result, err := MinRaftProtocol(tc.datacenter, tc.members) + result, err := MinRaftProtocol(tc.region, tc.members) if result != tc.expected { t.Fatalf("bad: %v, %v, %v", result, tc.expected, tc) } From 120f13bd78b34455a185c2646f0f4b6d4c8da5a2 Mon Sep 17 00:00:00 2001 From: Preetha Appan Date: Tue, 12 Dec 2017 10:30:36 -0600 Subject: [PATCH 10/13] Changes vendor.json to one dependency per line --- GNUmakefile | 8 +- vendor/vendor.json | 1901 +++++++------------------------------------- 2 files changed, 285 insertions(+), 1624 deletions(-) diff --git a/GNUmakefile b/GNUmakefile index 9608add4c..a4ada95cc 100644 --- a/GNUmakefile +++ b/GNUmakefile @@ -151,6 +151,7 @@ deps: ## Install build and development dependencies go get -u github.com/jteeuwen/go-bindata/... go get -u github.com/elazarl/go-bindata-assetfs/... go get -u github.com/a8m/tree/cmd/tree + go get -u github.com/magiconair/vendorfmt/cmd/vendorfmt .PHONY: lint-deps lint-deps: ## Install linter dependencies @@ -193,12 +194,17 @@ generate: LOCAL_PACKAGES = $(shell go list ./... | grep -v '/vendor/') generate: ## Update generated code @go generate $(LOCAL_PACKAGES) +vendorfmt: + @echo "--> Formatting vendor/vendor.json" + test -x $(GOPATH)/bin/vendorfmt || go get -u github.com/magiconair/vendorfmt/cmd/vendorfmt + vendorfmt + .PHONY: dev dev: GOOS=$(shell go env GOOS) dev: GOARCH=$(shell go env GOARCH) dev: GOPATH=$(shell go env GOPATH) dev: DEV_TARGET=pkg/$(GOOS)_$(GOARCH)$(if $(HAS_LXC),-lxc)/nomad -dev: ## Build for the current development platform +dev: vendorfmt ## Build for the current development platform @echo "==> Removing old development build..." @rm -f $(PROJECT_ROOT)/$(DEV_TARGET) @rm -f $(PROJECT_ROOT)/bin/nomad diff --git a/vendor/vendor.json b/vendor/vendor.json index 20d362f57..eec26146c 100644 --- a/vendor/vendor.json +++ b/vendor/vendor.json @@ -2,1629 +2,284 @@ "comment": "", "ignore": "test appengine", "package": [ - { - "path": "context", - "revision": "" - }, - { - "checksumSHA1": "23FJUX+AInYeEM2hoUMvYZtXZd4=", - "path": "github.com/Azure/go-ansiterm", - "revision": "fa152c58bc15761d0200cb75fe958b89a9d4888e", - "revisionTime": "2016-06-22T17:32:16Z" - }, - { - "checksumSHA1": "jBimnggjIiFUjaImNoJhSVLtdzw=", - "path": "github.com/Azure/go-ansiterm/winterm", - "revision": "fa152c58bc15761d0200cb75fe958b89a9d4888e", - "revisionTime": "2016-06-22T17:32:16Z" - }, - { - "checksumSHA1": "WvApwvvSe3i/3KO8300dyeFmkbI=", - "path": "github.com/DataDog/datadog-go/statsd", - "revision": "b10af4b12965a1ad08d164f57d14195b4140d8de", - "revisionTime": "2017-08-09T10:47:06Z" - }, - { - "checksumSHA1": "AzjRkOQtVBTwIw4RJLTygFhJs3s=", - "path": "github.com/Microsoft/go-winio", - "revision": "f533f7a102197536779ea3a8cb881d639e21ec5a", - "revisionTime": "2017-05-24T00:36:31Z" - }, - { - "checksumSHA1": "jktW57+vJsziNVPeXMCoujTzdW4=", - "path": "github.com/NYTimes/gziphandler", - "revision": "97ae7fbaf81620fe97840685304a78a306a39c64", - "revisionTime": "2017-09-16T00:36:49Z" - }, - { - "checksumSHA1": "Aqy8/FoAIidY/DeQ5oTYSZ4YFVc=", - "path": "github.com/Nvveen/Gotty", - "revision": "cd527374f1e5bff4938207604a14f2e38a9cf512", - "revisionTime": "2012-06-04T00:48:16Z" - }, - { - "checksumSHA1": "OTN4c1F0p+mEG2CpkU1Kuavupf0=", - "path": "github.com/RackSec/srslog", - "revision": "259aed10dfa74ea2961eddd1d9847619f6e98837", - "revisionTime": "2016-01-20T22:33:50Z" - }, - { - "comment": "v0.8.7-87-g4b6ea73", - "path": "github.com/Sirupsen/logrus", - "revision": "4b6ea7319e214d98c938f12692336f7ca9348d6b" - }, - { - "checksumSHA1": "qtjd74+bErubh+qyv3s+lWmn9wc=", - "path": "github.com/StackExchange/wmi", - "revision": "ea383cf3ba6ec950874b8486cd72356d007c768f", - "revisionTime": "2017-04-10T19:29:09Z" - }, - { - "checksumSHA1": "uWJDTv0R/NJVYv51LVy6vKP1CZw=", - "path": "github.com/appc/spec/schema", - "revision": "cbe99b7160b1397bf89f9c8bb1418f69c9424049", - "revisionTime": "2017-09-19T09:55:19Z" - }, - { - "checksumSHA1": "Q47G6996hbfQaNp/8CFkGWTVQpw=", - "path": "github.com/appc/spec/schema/common", - "revision": "cbe99b7160b1397bf89f9c8bb1418f69c9424049", - "revisionTime": "2017-09-19T09:55:19Z" - }, - { - "checksumSHA1": "kYXCle7Ikc8WqiMs7NXz99bUWqo=", - "path": "github.com/appc/spec/schema/types", - "revision": "cbe99b7160b1397bf89f9c8bb1418f69c9424049", - "revisionTime": "2017-09-19T09:55:19Z" - }, - { - "checksumSHA1": "VgPsPj5PH7LKXMa3ZLe5/+Avydo=", - "path": "github.com/appc/spec/schema/types/resource", - "revision": "cbe99b7160b1397bf89f9c8bb1418f69c9424049", - "revisionTime": "2017-09-19T09:55:19Z" - }, - { - "path": "github.com/armon/circbuf", - "revision": "bbbad097214e2918d8543d5201d12bfd7bca254d" - }, - { - "checksumSHA1": "xp/2s4XclLL17DThGBI7jXZ4Crs=", - "path": "github.com/armon/go-metrics", - "revision": "6c3acc97c61d04290a8ba2e54640151f54c1546a", - "revisionTime": "2017-11-16T18:41:20Z" - }, - { - "checksumSHA1": "xCsGGM9TKBogZDfSN536KtQdLko=", - "path": "github.com/armon/go-metrics/circonus", - "revision": "6c3acc97c61d04290a8ba2e54640151f54c1546a", - "revisionTime": "2017-11-16T18:41:20Z" - }, - { - "checksumSHA1": "Dt0n1sSivvvdZQdzc4Hu/yOG+T0=", - "path": "github.com/armon/go-metrics/datadog", - "revision": "6c3acc97c61d04290a8ba2e54640151f54c1546a", - "revisionTime": "2017-11-16T18:41:20Z" - }, - { - "checksumSHA1": "XfPPXw55zKziOWnZbkEGEJ96O9c=", - "path": "github.com/armon/go-metrics/prometheus", - "revision": "6c3acc97c61d04290a8ba2e54640151f54c1546a", - "revisionTime": "2017-11-16T18:41:20Z" - }, - { - "checksumSHA1": "gNO0JNpLzYOdInGeq7HqMZUzx9M=", - "path": "github.com/armon/go-radix", - "revision": "4239b77079c7b5d1243b7b4736304ce8ddb6f0f2", - "revisionTime": "2016-01-15T23:47:25Z" - }, - { - "comment": "v1.0.6-2-g80dd495", - "path": "github.com/aws/aws-sdk-go/aws", - "revision": "80dd4951fdb3f711d31843b8d87871130ef2df67" - }, - { - "comment": "v1.0.6-2-g80dd495", - "path": "github.com/aws/aws-sdk-go/aws/awserr", - "revision": "80dd4951fdb3f711d31843b8d87871130ef2df67" - }, - { - "comment": "v1.0.6-2-g80dd495", - "path": "github.com/aws/aws-sdk-go/aws/awsutil", - "revision": "80dd4951fdb3f711d31843b8d87871130ef2df67" - }, - { - "comment": "v1.0.6-2-g80dd495", - "path": "github.com/aws/aws-sdk-go/aws/client", - "revision": "80dd4951fdb3f711d31843b8d87871130ef2df67" - }, - { - "comment": "v1.0.6-2-g80dd495", - "path": "github.com/aws/aws-sdk-go/aws/client/metadata", - "revision": "80dd4951fdb3f711d31843b8d87871130ef2df67" - }, - { - "comment": "v1.0.6-2-g80dd495", - "path": "github.com/aws/aws-sdk-go/aws/corehandlers", - "revision": "80dd4951fdb3f711d31843b8d87871130ef2df67" - }, - { - "comment": "v1.0.6-2-g80dd495", - "path": "github.com/aws/aws-sdk-go/aws/credentials", - "revision": "80dd4951fdb3f711d31843b8d87871130ef2df67" - }, - { - "comment": "v1.0.6-2-g80dd495", - "path": "github.com/aws/aws-sdk-go/aws/credentials/ec2rolecreds", - "revision": "80dd4951fdb3f711d31843b8d87871130ef2df67" - }, - { - "comment": "v1.0.6-2-g80dd495", - "path": "github.com/aws/aws-sdk-go/aws/defaults", - "revision": "80dd4951fdb3f711d31843b8d87871130ef2df67" - }, - { - "comment": "v1.0.6-2-g80dd495", - "path": "github.com/aws/aws-sdk-go/aws/ec2metadata", - "revision": "80dd4951fdb3f711d31843b8d87871130ef2df67" - }, - { - "comment": "v1.0.6-2-g80dd495", - "path": "github.com/aws/aws-sdk-go/aws/request", - "revision": "80dd4951fdb3f711d31843b8d87871130ef2df67" - }, - { - "comment": "v1.0.6-2-g80dd495", - "path": "github.com/aws/aws-sdk-go/aws/session", - "revision": "80dd4951fdb3f711d31843b8d87871130ef2df67" - }, - { - "comment": "v1.0.6-2-g80dd495", - "path": "github.com/aws/aws-sdk-go/private/endpoints", - "revision": "80dd4951fdb3f711d31843b8d87871130ef2df67" - }, - { - "comment": "v1.0.6-2-g80dd495", - "path": "github.com/aws/aws-sdk-go/private/protocol/query", - "revision": "80dd4951fdb3f711d31843b8d87871130ef2df67" - }, - { - "comment": "v1.0.6-2-g80dd495", - "path": "github.com/aws/aws-sdk-go/private/protocol/query/queryutil", - "revision": "80dd4951fdb3f711d31843b8d87871130ef2df67" - }, - { - "comment": "v1.0.6-2-g80dd495", - "path": "github.com/aws/aws-sdk-go/private/protocol/rest", - "revision": "80dd4951fdb3f711d31843b8d87871130ef2df67" - }, - { - "comment": "v1.0.6-2-g80dd495", - "path": "github.com/aws/aws-sdk-go/private/protocol/restxml", - "revision": "80dd4951fdb3f711d31843b8d87871130ef2df67" - }, - { - "comment": "v1.0.6-2-g80dd495", - "path": "github.com/aws/aws-sdk-go/private/protocol/xml/xmlutil", - "revision": "80dd4951fdb3f711d31843b8d87871130ef2df67" - }, - { - "comment": "v1.0.6-2-g80dd495", - "path": "github.com/aws/aws-sdk-go/private/signer/v4", - "revision": "80dd4951fdb3f711d31843b8d87871130ef2df67" - }, - { - "comment": "v1.0.6-2-g80dd495", - "path": "github.com/aws/aws-sdk-go/private/waiter", - "revision": "80dd4951fdb3f711d31843b8d87871130ef2df67" - }, - { - "comment": "v1.0.6-2-g80dd495", - "path": "github.com/aws/aws-sdk-go/service/s3", - "revision": "80dd4951fdb3f711d31843b8d87871130ef2df67" - }, - { - "checksumSHA1": "spyv5/YFBjYyZLZa1U2LBfDR8PM=", - "path": "github.com/beorn7/perks/quantile", - "revision": "4c0e84591b9aa9e6dcfdf3e020114cd81f89d5f9", - "revisionTime": "2016-08-04T10:47:26Z" - }, - { - "checksumSHA1": "nqw2Qn5xUklssHTubS5HDvEL9L4=", - "path": "github.com/bgentry/go-netrc/netrc", - "revision": "9fd32a8b3d3d3f9d43c341bfe098430e07609480", - "revisionTime": "2014-04-22T17:41:19Z" - }, - { - "path": "github.com/bgentry/speakeasy", - "revision": "36e9cfdd690967f4f690c6edcc9ffacd006014a0" - }, - { - "path": "github.com/bgentry/speakeasy/example", - "revision": "36e9cfdd690967f4f690c6edcc9ffacd006014a0" - }, - { - "checksumSHA1": "R1Q34Pfnt197F/nCOO9kG8c+Z90=", - "comment": "v1.2.0", - "path": "github.com/boltdb/bolt", - "revision": "2f1ce7a837dcb8da3ec595b1dac9d0632f0f99e8", - "revisionTime": "2017-07-17T17:11:48Z", - "version": "v1.3.1", - "versionExact": "v1.3.1" - }, - { - "checksumSHA1": "InIrfOI7Ys1QqZpCgTB4yW1G32M=", - "path": "github.com/burntsushi/toml", - "revision": "99064174e013895bbd9b025c31100bd1d9b590ca", - "revisionTime": "2016-07-17T15:07:09Z" - }, - { - "checksumSHA1": "vhCArnFcQRM84iZcfMXka+2OzrE=", - "path": "github.com/circonus-labs/circonus-gometrics", - "revision": "a2c28f079ec3d4fdc17ed577cca75bee88a2da25", - "revisionTime": "2017-01-31T13:03:52Z" - }, - { - "checksumSHA1": "sInms3AjZrjG/WCRcmS/NSzLUT4=", - "path": "github.com/circonus-labs/circonus-gometrics/api", - "revision": "a2c28f079ec3d4fdc17ed577cca75bee88a2da25", - "revisionTime": "2017-01-31T13:03:52Z" - }, - { - "checksumSHA1": "bQhz/fcyZPmuHSH2qwC4ZtATy5c=", - "path": "github.com/circonus-labs/circonus-gometrics/api/config", - "revision": "a2c28f079ec3d4fdc17ed577cca75bee88a2da25", - "revisionTime": "2017-01-31T13:03:52Z" - }, - { - "checksumSHA1": "6hvd+YFb1eWFkc3pVcnOPPa2OVw=", - "path": "github.com/circonus-labs/circonus-gometrics/checkmgr", - "revision": "a2c28f079ec3d4fdc17ed577cca75bee88a2da25", - "revisionTime": "2017-01-31T13:03:52Z" - }, - { - "checksumSHA1": "VbfeVqeOM+dTNxCmpvmYS0LwQn0=", - "path": "github.com/circonus-labs/circonusllhist", - "revision": "7d649b46cdc2cd2ed102d350688a75a4fd7778c6", - "revisionTime": "2016-11-21T13:51:53Z" - }, - { - "checksumSHA1": "NeAp/3+Hedu9tnMai+LihERPj84=", - "path": "github.com/containernetworking/cni/pkg/types", - "revision": "5c3c17164270150467498a32c71436c7cd5501be", - "revisionTime": "2016-06-02T16:00:07Z" - }, - { - "checksumSHA1": "97BsbXOiZ8+Kr+LIuZkQFtSj7H4=", - "path": "github.com/coreos/go-semver/semver", - "revision": "1817cd4bea52af76542157eeabd74b057d1a199e", - "revisionTime": "2017-06-13T09:22:38Z" - }, - { - "checksumSHA1": "mrz/kicZiUaHxkyfvC/DyQcr8Do=", - "path": "github.com/davecgh/go-spew/spew", - "revision": "ecdeabc65495df2dec95d7c4a4c3e021903035e5", - "revisionTime": "2017-10-02T20:02:53Z" - }, - { - "checksumSHA1": "Gj+xR1VgFKKmFXYOJMnAczC3Znk=", - "path": "github.com/docker/distribution/digestset", - "revision": "69c7f303d511a5777e79505b23340d37d532d7ac", - "revisionTime": "2017-01-11T18:37:34Z" - }, - { - "checksumSHA1": "FqADPtHUqEtmfC7Zf+0pI++Kb6g=", - "path": "github.com/docker/distribution/reference", - "revision": "69c7f303d511a5777e79505b23340d37d532d7ac", - "revisionTime": "2017-01-11T18:37:34Z" - }, - { - "checksumSHA1": "HoN/78ovv3/DC+kDKF7IENEc40g=", - "path": "github.com/docker/docker/api/types", - "revision": "e4d0fe84f9ea88b0e0cfd847412c9f29442cc62d", - "revisionTime": "2017-11-14T19:25:14Z" - }, - { - "checksumSHA1": "jVJDbe0IcyjoKc2xbohwzQr+FF0=", - "path": "github.com/docker/docker/api/types/blkiodev", - "revision": "3dc87714d1bfcaf0620fabec3bfea89620b59337", - "revisionTime": "2017-02-14T23:27:04Z" - }, - { - "checksumSHA1": "Vso/6NenP1G74lQjvyvzOdfIZ28=", - "path": "github.com/docker/docker/api/types/container", - "revision": "3dc87714d1bfcaf0620fabec3bfea89620b59337", - "revisionTime": "2017-02-14T23:27:04Z" - }, - { - "checksumSHA1": "J2OKngfI3vgswudr9PZVUFcRRu0=", - "path": "github.com/docker/docker/api/types/filters", - "revision": "fe9ab0588606a5566d065bc68ae68f3926ddaa72", - "revisionTime": "2017-02-28T18:28:19Z" - }, - { - "checksumSHA1": "OXsrx4ynzLV+6/6vUeyru0Fprx8=", - "path": "github.com/docker/docker/api/types/mount", - "revision": "3dc87714d1bfcaf0620fabec3bfea89620b59337", - "revisionTime": "2017-02-14T23:27:04Z" - }, - { - "checksumSHA1": "Gskp+nvbVe8Gk1xPLHylZvNmqTg=", - "path": "github.com/docker/docker/api/types/network", - "revision": "e4d0fe84f9ea88b0e0cfd847412c9f29442cc62d", - "revisionTime": "2017-11-14T19:25:14Z" - }, - { - "checksumSHA1": "r2vWq7Uc3ExKzMqYgH0b4AKjLKY=", - "path": "github.com/docker/docker/api/types/registry", - "revision": "e4d0fe84f9ea88b0e0cfd847412c9f29442cc62d", - "revisionTime": "2017-11-14T19:25:14Z" - }, - { - "checksumSHA1": "VTxWyFud/RedrpllGdQonVtGM/A=", - "path": "github.com/docker/docker/api/types/strslice", - "revision": "3dc87714d1bfcaf0620fabec3bfea89620b59337", - "revisionTime": "2017-02-14T23:27:04Z" - }, - { - "checksumSHA1": "Q0U3queMsCw+rPPztXnRHwAxQEc=", - "path": "github.com/docker/docker/api/types/swarm", - "revision": "e4d0fe84f9ea88b0e0cfd847412c9f29442cc62d", - "revisionTime": "2017-11-14T19:25:14Z" - }, - { - "checksumSHA1": "mi8EDCDjtrZEONRXPG7VHJosDwY=", - "path": "github.com/docker/docker/api/types/swarm/runtime", - "revision": "e4d0fe84f9ea88b0e0cfd847412c9f29442cc62d", - "revisionTime": "2017-11-14T19:25:14Z" - }, - { - "checksumSHA1": "uDPQ3nHsrvGQc9tg/J9OSC4N5dQ=", - "path": "github.com/docker/docker/api/types/versions", - "revision": "fe9ab0588606a5566d065bc68ae68f3926ddaa72", - "revisionTime": "2017-02-28T18:28:19Z" - }, - { - "checksumSHA1": "l8Re54Tp3x8kYWPoD2jXBOWloSY=", - "path": "github.com/docker/docker/cli/config/configfile", - "revision": "518945b6bd30dc535addf2aac9d5eeefbfc5e523", - "revisionTime": "2017-01-10T19:35:11Z" - }, - { - "checksumSHA1": "mswe275heIklTKj7mPTnVzAFoMk=", - "path": "github.com/docker/docker/opts", - "revision": "da39e9a4f920a15683dd0f23923c302d4db6eed5", - "revisionTime": "2016-05-28T08:11:04Z" - }, - { - "checksumSHA1": "OShlvanyvyee8I0/kdmLuOEOF5w=", - "path": "github.com/docker/docker/pkg/archive", - "revision": "da39e9a4f920a15683dd0f23923c302d4db6eed5", - "revisionTime": "2016-05-28T08:11:04Z" - }, - { - "checksumSHA1": "EONnM7E8xCzJCAbX1rhayK6knwM=", - "path": "github.com/docker/docker/pkg/fileutils", - "revision": "da39e9a4f920a15683dd0f23923c302d4db6eed5", - "revisionTime": "2016-05-28T08:11:04Z" - }, - { - "checksumSHA1": "p6Ud4Yf1ywWy20YxXF1RU4yhTio=", - "path": "github.com/docker/docker/pkg/homedir", - "revision": "da39e9a4f920a15683dd0f23923c302d4db6eed5", - "revisionTime": "2016-05-28T08:11:04Z" - }, - { - "checksumSHA1": "iP5slJJPRZUm0rfdII8OiATAACA=", - "path": "github.com/docker/docker/pkg/idtools", - "revision": "02caa73df411debed164f520a6a1304778f8b88c", - "revisionTime": "2016-05-28T10:48:36Z" - }, - { - "checksumSHA1": "iP5slJJPRZUm0rfdII8OiATAACA=", - "path": "github.com/docker/docker/pkg/idtools", - "revision": "52debcd58ac91bf68503ce60561536911b74ff05", - "revisionTime": "2016-05-20T15:17:10Z" - }, - { - "checksumSHA1": "tdhmIGUaoOMEDymMC23qTS7bt0g=", - "path": "github.com/docker/docker/pkg/ioutils", - "revision": "da39e9a4f920a15683dd0f23923c302d4db6eed5", - "revisionTime": "2016-05-28T08:11:04Z" - }, - { - "checksumSHA1": "tdhmIGUaoOMEDymMC23qTS7bt0g=", - "path": "github.com/docker/docker/pkg/ioutils", - "revision": "52debcd58ac91bf68503ce60561536911b74ff05", - "revisionTime": "2016-05-20T15:17:10Z" - }, - { - "checksumSHA1": "BlFSSK7zUjPzPuxkLmM/0wpvku8=", - "path": "github.com/docker/docker/pkg/jsonlog", - "revision": "3dc87714d1bfcaf0620fabec3bfea89620b59337", - "revisionTime": "2017-02-14T23:27:04Z" - }, - { - "checksumSHA1": "IpcW+FAHu0DmbvbhqXuP42f4FCo=", - "path": "github.com/docker/docker/pkg/jsonmessage", - "revision": "3dc87714d1bfcaf0620fabec3bfea89620b59337", - "revisionTime": "2017-02-14T23:27:04Z" - }, - { - "checksumSHA1": "ndnAFCfsGC3upNQ6jAEwzxcurww=", - "path": "github.com/docker/docker/pkg/longpath", - "revision": "da39e9a4f920a15683dd0f23923c302d4db6eed5", - "revisionTime": "2016-05-28T08:11:04Z" - }, - { - "checksumSHA1": "rArZ5mYIe9I1L5PRQOJu8BwafFw=", - "path": "github.com/docker/docker/pkg/pools", - "revision": "da39e9a4f920a15683dd0f23923c302d4db6eed5", - "revisionTime": "2016-05-28T08:11:04Z" - }, - { - "checksumSHA1": "rArZ5mYIe9I1L5PRQOJu8BwafFw=", - "path": "github.com/docker/docker/pkg/pools", - "revision": "52debcd58ac91bf68503ce60561536911b74ff05", - "revisionTime": "2016-05-20T15:17:10Z" - }, - { - "checksumSHA1": "txf3EORYff4hO6PEvwBm2lyh1MU=", - "path": "github.com/docker/docker/pkg/promise", - "revision": "52debcd58ac91bf68503ce60561536911b74ff05", - "revisionTime": "2016-05-20T15:17:10Z" - }, - { - "checksumSHA1": "txf3EORYff4hO6PEvwBm2lyh1MU=", - "path": "github.com/docker/docker/pkg/promise", - "revision": "da39e9a4f920a15683dd0f23923c302d4db6eed5", - "revisionTime": "2016-05-28T08:11:04Z" - }, - { - "checksumSHA1": "lThih54jzz9A4zHKEFb9SIV3Ed0=", - "path": "github.com/docker/docker/pkg/random", - "revision": "518945b6bd30dc535addf2aac9d5eeefbfc5e523", - "revisionTime": "2017-01-10T19:35:11Z" - }, - { - "checksumSHA1": "YDYbS5U2mDwfcOUJ6M09cP6Bubg=", - "path": "github.com/docker/docker/pkg/stdcopy", - "revision": "da39e9a4f920a15683dd0f23923c302d4db6eed5", - "revisionTime": "2016-05-28T08:11:04Z" - }, - { - "checksumSHA1": "YGZBluVbky9i5i+BgM+RTc0NEtc=", - "path": "github.com/docker/docker/pkg/stringid", - "revision": "518945b6bd30dc535addf2aac9d5eeefbfc5e523", - "revisionTime": "2017-01-10T19:35:11Z" - }, - { - "checksumSHA1": "NGqzajRG0Vri8ConQuHY3cCs1RA=", - "path": "github.com/docker/docker/pkg/system", - "revision": "fe9ab0588606a5566d065bc68ae68f3926ddaa72", - "revisionTime": "2017-02-28T18:28:19Z" - }, - { - "checksumSHA1": "jtruj9m4YJtPaXqUZ5PXdgFQjRA=", - "path": "github.com/docker/docker/pkg/system", - "revision": "47cd4bf526723100bdbbd5a6bb983cdd668882e9", - "revisionTime": "2017-03-13T17:42:22Z" - }, - { - "checksumSHA1": "Nfp/0W+HK8ZEgklbSWmjJGXTJew=", - "path": "github.com/docker/docker/pkg/term", - "revision": "3dc87714d1bfcaf0620fabec3bfea89620b59337", - "revisionTime": "2017-02-14T23:27:04Z" - }, - { - "checksumSHA1": "EMjTiUTHNxqSsmdMB1V29hRvJbQ=", - "path": "github.com/docker/docker/pkg/term/windows", - "revision": "3dc87714d1bfcaf0620fabec3bfea89620b59337", - "revisionTime": "2017-02-14T23:27:04Z" - }, - { - "checksumSHA1": "bASLGmo2Ae+10Pc2zVCpXbBcPag=", - "path": "github.com/docker/docker/reference", - "revision": "518945b6bd30dc535addf2aac9d5eeefbfc5e523", - "revisionTime": "2017-01-10T19:35:11Z" - }, - { - "checksumSHA1": "AlBQLsNEpPJIe7OxsqN1P3BKi/M=", - "path": "github.com/docker/docker/registry", - "revision": "518945b6bd30dc535addf2aac9d5eeefbfc5e523", - "revisionTime": "2017-01-10T19:35:11Z" - }, - { - "checksumSHA1": "JbiWTzH699Sqz25XmDlsARpMN9w=", - "path": "github.com/docker/go-connections/nat", - "revision": "7da10c8c50cad14494ec818dcdfb6506265c0086", - "revisionTime": "2017-02-03T23:56:24Z" - }, - { - "comment": "v0.1.0-23-g5d2041e", - "path": "github.com/docker/go-units", - "revision": "5d2041e26a699eaca682e2ea41c8f891e1060444" - }, - { - "path": "github.com/dustin/go-humanize", - "revision": "8929fe90cee4b2cb9deb468b51fb34eba64d1bf0" - }, - { - "checksumSHA1": "7DxViusFRJ7UPH0jZqYatwDrOkY=", - "path": "github.com/elazarl/go-bindata-assetfs", - "revision": "30f82fa23fd844bd5bb1e5f216db87fd77b5eb43", - "revisionTime": "2017-02-27T21:27:28Z" - }, - { - "checksumSHA1": "QBkOnLnM6zZ158NJSVLqoE4V6fI=", - "path": "github.com/fatih/structs", - "revision": "14f46232cd7bc732dc67313a9e4d3d210e082587", - "revisionTime": "2016-07-19T20:45:16Z" - }, - { - "checksumSHA1": "E+wmSQrc/BXzgITrbNAbUzljoiM=", - "path": "github.com/fsouza/go-dockerclient", - "revision": "5ffdfff51ec0eba739b1039e65ba3625ef25f7c0", - "revisionTime": "2017-11-23T03:37:03Z" - }, - { - "comment": "v1.8.5-2-g6ec4abd", - "path": "github.com/go-ini/ini", - "revision": "6ec4abd8f8d587536da56f730858f0e27aeb4126" - }, - { - "checksumSHA1": "IvHj/4iR2nYa/S3cB2GXoyDG/xQ=", - "comment": "v1.2.0-4-g5005588", - "path": "github.com/go-ole/go-ole", - "revision": "085abb85892dc1949567b726dff00fa226c60c45", - "revisionTime": "2017-07-12T17:44:59Z" - }, - { - "comment": "v1.2.0-4-g5005588", - "path": "github.com/go-ole/go-ole/oleutil", - "revision": "50055884d646dd9434f16bbb5c9801749b9bafe4" - }, - { - "checksumSHA1": "I460dM/HmGE9DWimQvd1hJkYosU=", - "path": "github.com/gogo/protobuf/proto", - "revision": "616a82ed12d78d24d4839363e8f3c5d3f20627cf", - "revisionTime": "2017-11-09T18:15:19Z" - }, - { - "checksumSHA1": "dUAIotNrGq6Tvz/z6ktSxSHW7Rc=", - "path": "github.com/golang/protobuf/proto", - "revision": "0a4f71a498b7c4812f64969510bcb4eca251e33a", - "revisionTime": "2017-07-12T04:22:13Z" - }, - { - "checksumSHA1": "Z4RIWIXH05QItZqVbmbONO9mWig=", - "path": "github.com/golang/protobuf/ptypes/any", - "revision": "0a4f71a498b7c4812f64969510bcb4eca251e33a", - "revisionTime": "2017-07-12T04:22:13Z" - }, - { - "checksumSHA1": "W+E/2xXcE1GmJ0Qb784ald0Fn6I=", - "path": "github.com/golang/snappy", - "revision": "d9eb7a3d35ec988b8585d4a0068e462c27d28380", - "revisionTime": "2016-05-29T05:00:41Z" - }, - { - "checksumSHA1": "+suAHHPBmbdZf/HusugaL4/H+NE=", - "path": "github.com/google/go-cmp/cmp", - "revision": "d5735f74713c51f7450a43d0a98d41ce2c1db3cb", - "revisionTime": "2017-09-01T21:42:48Z" - }, - { - "checksumSHA1": "VmBLfV9TChrjNu8Z96wZkYie1aI=", - "path": "github.com/google/go-cmp/cmp/cmpopts", - "revision": "d5735f74713c51f7450a43d0a98d41ce2c1db3cb", - "revisionTime": "2017-09-01T21:42:48Z" - }, - { - "checksumSHA1": "eTwchtMX+RMJUvle2wt295P2h10=", - "path": "github.com/google/go-cmp/cmp/internal/diff", - "revision": "d5735f74713c51f7450a43d0a98d41ce2c1db3cb", - "revisionTime": "2017-09-01T21:42:48Z" - }, - { - "checksumSHA1": "kYtvRhMjM0X4bvEjR3pqEHLw1qo=", - "path": "github.com/google/go-cmp/cmp/internal/function", - "revision": "d5735f74713c51f7450a43d0a98d41ce2c1db3cb", - "revisionTime": "2017-09-01T21:42:48Z" - }, - { - "checksumSHA1": "f+mgZLvc4VITtMmBv0bmew4rL2Y=", - "path": "github.com/google/go-cmp/cmp/internal/value", - "revision": "d5735f74713c51f7450a43d0a98d41ce2c1db3cb", - "revisionTime": "2017-09-01T21:42:48Z" - }, - { - "checksumSHA1": "m8B3L3qJ3tFfP6BI9pIFr9oal3w=", - "comment": "1.0.0", - "origin": "github.com/dadgar/cronexpr", - "path": "github.com/gorhill/cronexpr", - "revision": "675cac9b2d182dccb5ba8d5f8a0d5988df8a4394", - "revisionTime": "2017-09-15T18:30:32Z" - }, - { - "comment": "1.0.0", - "path": "github.com/gorhill/cronexpr/cronexpr", - "revision": "a557574d6c024ed6e36acc8b610f5f211c91568a" - }, - { - "checksumSHA1": "Nu2j1GusM7ZH0uYrGzqr1K7yH7I=", - "path": "github.com/hashicorp/consul-template/child", - "revision": "26d029ad37335b3827a9fde5569b2c5e10dcac8f", - "revisionTime": "2017-10-31T14:25:17Z" - }, - { - "checksumSHA1": "qKAxyhYnUpKzZ5KpA6aOiIHHqqg=", - "path": "github.com/hashicorp/consul-template/config", - "revision": "26d029ad37335b3827a9fde5569b2c5e10dcac8f", - "revisionTime": "2017-10-31T14:25:17Z" - }, - { - "checksumSHA1": "gZUb/+jEn+2hdO/lmQSKcYuOB/o=", - "path": "github.com/hashicorp/consul-template/dependency", - "revision": "26d029ad37335b3827a9fde5569b2c5e10dcac8f", - "revisionTime": "2017-10-31T14:25:17Z" - }, - { - "checksumSHA1": "JVwx9FW1/nxRvg1lEeydBhaf3No=", - "path": "github.com/hashicorp/consul-template/manager", - "revision": "26d029ad37335b3827a9fde5569b2c5e10dcac8f", - "revisionTime": "2017-10-31T14:25:17Z" - }, - { - "checksumSHA1": "YSEUV/9/k85XciRKu0cngxdjZLE=", - "path": "github.com/hashicorp/consul-template/signals", - "revision": "26d029ad37335b3827a9fde5569b2c5e10dcac8f", - "revisionTime": "2017-10-31T14:25:17Z" - }, - { - "checksumSHA1": "N9qobVzScLbTEnGE7MgFnnTbGBw=", - "path": "github.com/hashicorp/consul-template/template", - "revision": "26d029ad37335b3827a9fde5569b2c5e10dcac8f", - "revisionTime": "2017-10-31T14:25:17Z" - }, - { - "checksumSHA1": "NB5+D4AuCNV9Bsqh3YFdPi4AJ6U=", - "path": "github.com/hashicorp/consul-template/version", - "revision": "26d029ad37335b3827a9fde5569b2c5e10dcac8f", - "revisionTime": "2017-10-31T14:25:17Z" - }, - { - "checksumSHA1": "b4+Y+02pY2Y5620F9ALzKg8Zmdw=", - "path": "github.com/hashicorp/consul-template/watch", - "revision": "26d029ad37335b3827a9fde5569b2c5e10dcac8f", - "revisionTime": "2017-10-31T14:25:17Z" - }, - { - "checksumSHA1": "XLfcIX2qpRr0o26aFMjCOzvw6jo=", - "path": "github.com/hashicorp/consul/api", - "revision": "51ea240df8476e02215d53fbfad5838bf0d44d21", - "revisionTime": "2017-10-16T16:22:40Z" - }, - { - "checksumSHA1": "HGljdtVaqi/e3DgIHymLRLfPYhw=", - "path": "github.com/hashicorp/consul/lib", - "revision": "bcafded4e60982d0b71e730f0b8564d73cb1d715", - "revisionTime": "2017-10-31T16:39:15Z" - }, - { - "checksumSHA1": "hDJiPli3EEGJE4vAezMi05oOC7o=", - "path": "github.com/hashicorp/consul/lib/freeport", - "revision": "bcafded4e60982d0b71e730f0b8564d73cb1d715", - "revisionTime": "2017-10-31T16:39:15Z" - }, - { - "checksumSHA1": "5XjgqE4UIfwXvkq5VssGNc7uPhQ=", - "path": "github.com/hashicorp/consul/test/porter", - "revision": "ad9425ca6353b8afcfebd19130a8cf768f7eac30", - "revisionTime": "2017-10-21T00:05:25Z" - }, - { - "checksumSHA1": "+go9ycmyfF4b0W174gc7ej5mnE8=", - "path": "github.com/hashicorp/consul/testutil", - "revision": "350932161d6745836c1b2f39849bddb0f9fb52fd", - "revisionTime": "2017-10-20T23:49:17Z" - }, - { - "checksumSHA1": "J8TTDc84MvAyXE/FrfgS+xc/b6s=", - "path": "github.com/hashicorp/consul/testutil/retry", - "revision": "350932161d6745836c1b2f39849bddb0f9fb52fd", - "revisionTime": "2017-10-20T23:49:17Z" - }, - { - "path": "github.com/hashicorp/errwrap", - "revision": "7554cd9344cec97297fa6649b055a8c98c2a1e55" - }, - { - "checksumSHA1": "D267IUMW2rcb+vNe3QU+xhfSrgY=", - "path": "github.com/hashicorp/go-checkpoint", - "revision": "1545e56e46dec3bba264e41fde2c1e2aa65b5dd4", - "revisionTime": "2017-10-09T17:35:28Z" - }, - { - "checksumSHA1": "6ihdHMkDfFx/rJ1A36com2F6bQk=", - "path": "github.com/hashicorp/go-cleanhttp", - "revision": "a45970658e51fea2c41445ff0f7e07106d007617", - "revisionTime": "2017-02-11T00:33:01Z" - }, - { - "checksumSHA1": "mB5JzxaVCPIvbwADY0acdnkhmT8=", - "path": "github.com/hashicorp/go-envparse", - "revision": "7953113a2936d8e5f7e2a0a3dd8089565c39ef21", - "revisionTime": "2017-06-02T22:43:19Z" - }, - { - "checksumSHA1": "wCKbbnwvVEoKAE5TWunloLhErm4=", - "path": "github.com/hashicorp/go-getter", - "revision": "994f50a6f071b07cfbea9eca9618c9674091ca51", - "revisionTime": "2017-12-04T19:28:26Z" - }, - { - "checksumSHA1": "9J+kDr29yDrwsdu2ULzewmqGjpA=", - "path": "github.com/hashicorp/go-getter/helper/url", - "revision": "994f50a6f071b07cfbea9eca9618c9674091ca51", - "revisionTime": "2017-12-04T19:28:26Z" - }, - { - "checksumSHA1": "miVF4/7JP0lRwZvFJGKwZWk7aAQ=", - "path": "github.com/hashicorp/go-hclog", - "revision": "b4e5765d1e5f00a0550911084f45f8214b5b83b9", - "revisionTime": "2017-07-16T17:45:23Z" - }, - { - "checksumSHA1": "Cas2nprG6pWzf05A2F/OlnjUu2Y=", - "path": "github.com/hashicorp/go-immutable-radix", - "revision": "8aac2701530899b64bdea735a1de8da899815220", - "revisionTime": "2017-07-25T22:12:15Z" - }, - { - "checksumSHA1": "FMAvwDar2bQyYAW4XMFhAt0J5xA=", - "path": "github.com/hashicorp/go-memdb", - "revision": "20ff6434c1cc49b80963d45bf5c6aa89c78d8d57", - "revisionTime": "2017-08-31T20:15:40Z" - }, - { - "path": "github.com/hashicorp/go-msgpack/codec", - "revision": "fa3f63826f7c23912c15263591e65d54d080b458" - }, - { - "path": "github.com/hashicorp/go-multierror", - "revision": "d30f09973e19c1dfcd120b2d9c4f168e68d6b5d5" - }, - { - "checksumSHA1": "R6me0jVmcT/OPo80Fe0qo5fRwHc=", - "path": "github.com/hashicorp/go-plugin", - "revision": "3e6d191694b5a3a2b99755f31b47fa209e4bcd09", - "revisionTime": "2017-08-28T02:45:49Z" - }, - { - "checksumSHA1": "ErJHGU6AVPZM9yoY/xV11TwSjQs=", - "path": "github.com/hashicorp/go-retryablehttp", - "revision": "6e85be8fee1dcaa02c0eaaac2df5a8fbecf94145", - "revisionTime": "2016-09-30T03:51:02Z" - }, - { - "checksumSHA1": "A1PcINvF3UiwHRKn8UcgARgvGRs=", - "path": "github.com/hashicorp/go-rootcerts", - "revision": "6bb64b370b90e7ef1fa532be9e591a81c3493e00", - "revisionTime": "2016-05-03T14:34:40Z" - }, - { - "checksumSHA1": "X2tSlVe532du67MEIU1KHoCT68k=", - "path": "github.com/hashicorp/go-sockaddr", - "revision": "e12d9401a74f025fe672cd1a84b2081c773990d3", - "revisionTime": "2017-06-22T20:44:38Z" - }, - { - "checksumSHA1": "mIUCMmRHslN2bxQZ0uObMnXxk9E=", - "path": "github.com/hashicorp/go-sockaddr/template", - "revision": "e12d9401a74f025fe672cd1a84b2081c773990d3", - "revisionTime": "2017-06-22T20:44:38Z" - }, - { - "path": "github.com/hashicorp/go-syslog", - "revision": "42a2b573b664dbf281bd48c3cc12c086b17a39ba" - }, - { - "checksumSHA1": "mAkPa/RLuIwN53GbwIEMATexams=", - "path": "github.com/hashicorp/go-uuid", - "revision": "64130c7a86d732268a38cb04cfbaf0cc987fda98", - "revisionTime": "2016-07-17T02:21:40Z" - }, - { - "checksumSHA1": "tUGxc7rfX0cmhOOUDhMuAZ9rWsA=", - "path": "github.com/hashicorp/go-version", - "revision": "03c5bf6be031b6dd45afec16b1cf94fc8938bc77", - "revisionTime": "2017-02-02T08:07:59Z" - }, - { - "checksumSHA1": "d9PxF1XQGLMJZRct2R8qVM/eYlE=", - "path": "github.com/hashicorp/golang-lru", - "revision": "a0d98a5f288019575c6d1f4bb1573fef2d1fcdc4", - "revisionTime": "2016-02-07T21:47:19Z" - }, - { - "path": "github.com/hashicorp/golang-lru/simplelru", - "revision": "a0d98a5f288019575c6d1f4bb1573fef2d1fcdc4" - }, - { - "checksumSHA1": "8OPDk+bKyRGJoKcS4QNw9F7dpE8=", - "path": "github.com/hashicorp/hcl", - "revision": "6e968a3fcdcbab092f5307fd0d85479d5af1e4dc", - "revisionTime": "2016-11-01T18:00:25Z" - }, - { - "checksumSHA1": "XQmjDva9JCGGkIecOgwtBEMCJhU=", - "path": "github.com/hashicorp/hcl/hcl/ast", - "revision": "6e968a3fcdcbab092f5307fd0d85479d5af1e4dc", - "revisionTime": "2016-11-01T18:00:25Z" - }, - { - "checksumSHA1": "croNloscHsjX87X+4/cKOURf1EY=", - "path": "github.com/hashicorp/hcl/hcl/parser", - "revision": "6e968a3fcdcbab092f5307fd0d85479d5af1e4dc", - "revisionTime": "2016-11-01T18:00:25Z" - }, - { - "checksumSHA1": "lgR7PSAZ0RtvAc9OCtCnNsF/x8g=", - "path": "github.com/hashicorp/hcl/hcl/scanner", - "revision": "6e968a3fcdcbab092f5307fd0d85479d5af1e4dc", - "revisionTime": "2016-11-01T18:00:25Z" - }, - { - "checksumSHA1": "JlZmnzqdmFFyb1+2afLyR3BOE/8=", - "path": "github.com/hashicorp/hcl/hcl/strconv", - "revision": "6e968a3fcdcbab092f5307fd0d85479d5af1e4dc", - "revisionTime": "2016-11-01T18:00:25Z" - }, - { - "checksumSHA1": "c6yprzj06ASwCo18TtbbNNBHljA=", - "path": "github.com/hashicorp/hcl/hcl/token", - "revision": "6e968a3fcdcbab092f5307fd0d85479d5af1e4dc", - "revisionTime": "2016-11-01T18:00:25Z" - }, - { - "checksumSHA1": "138aCV5n8n7tkGYMsMVQQnnLq+0=", - "path": "github.com/hashicorp/hcl/json/parser", - "revision": "6e968a3fcdcbab092f5307fd0d85479d5af1e4dc", - "revisionTime": "2016-11-01T18:00:25Z" - }, - { - "checksumSHA1": "YdvFsNOMSWMLnY6fcliWQa0O5Fw=", - "path": "github.com/hashicorp/hcl/json/scanner", - "revision": "6e968a3fcdcbab092f5307fd0d85479d5af1e4dc", - "revisionTime": "2016-11-01T18:00:25Z" - }, - { - "checksumSHA1": "fNlXQCQEnb+B3k5UDL/r15xtSJY=", - "path": "github.com/hashicorp/hcl/json/token", - "revision": "6e968a3fcdcbab092f5307fd0d85479d5af1e4dc", - "revisionTime": "2016-11-01T18:00:25Z" - }, - { - "path": "github.com/hashicorp/logutils", - "revision": "0dc08b1671f34c4250ce212759ebd880f743d883" - }, - { - "checksumSHA1": "1zk7IeGClUqBo+Phsx89p7fQ/rQ=", - "path": "github.com/hashicorp/memberlist", - "revision": "23ad4b7d7b38496cd64c241dfd4c60b7794c254a", - "revisionTime": "2017-02-08T21:15:06Z" - }, - { - "path": "github.com/hashicorp/net-rpc-msgpackrpc", - "revision": "a14192a58a694c123d8fe5481d4a4727d6ae82f3" - }, - { - "checksumSHA1": "ecpaHOImbL/NaivWrUDUUe5461E=", - "path": "github.com/hashicorp/raft", - "revision": "3a6f3bdfe4fc69e300c6d122b1a92051af6f0b95", - "revisionTime": "2017-08-07T22:22:24Z" - }, - { - "checksumSHA1": "QAxukkv54/iIvLfsUP6IK4R0m/A=", - "path": "github.com/hashicorp/raft-boltdb", - "revision": "d1e82c1ec3f15ee991f7cc7ffd5b67ff6f5bbaee", - "revisionTime": "2015-02-01T20:08:39Z" - }, - { - "checksumSHA1": "/oss17GO4hXGM7QnUdI3VzcAHzA=", - "path": "github.com/hashicorp/serf/coordinate", - "revision": "bbeddf0b3ab3072a60525afbd6b6f47d33839eee", - "revisionTime": "2017-07-14T18:26:01Z" - }, - { - "checksumSHA1": "pvLOzocYsZtxuJ9pREHRTxYnoa4=", - "path": "github.com/hashicorp/serf/serf", - "revision": "bbeddf0b3ab3072a60525afbd6b6f47d33839eee", - "revisionTime": "2017-07-14T18:26:01Z" - }, - { - "checksumSHA1": "eGzvBRMFD6ZB3A6uO750np7Om/E=", - "path": "github.com/hashicorp/vault", - "revision": "182ba68a9589d4cef95234134aaa498a686e3de3", - "revisionTime": "2016-08-21T23:40:57Z" - }, - { - "checksumSHA1": "hLIXn9iQhPcjY+/G64j3mIlLlK8=", - "path": "github.com/hashicorp/vault/api", - "revision": "0c3e14f047aede0a70256e1e8b321610910b246e", - "revisionTime": "2017-08-01T15:50:41Z" - }, - { - "checksumSHA1": "au+CDkddC4sVFV15UaPiI7FvSw0=", - "path": "github.com/hashicorp/vault/helper/compressutil", - "revision": "1fd46cbcb10569bd205c3f662e7a4f16f1e69056", - "revisionTime": "2017-08-11T01:28:18Z" - }, - { - "checksumSHA1": "yUiSTPf0QUuL2r/81sjuytqBoeQ=", - "path": "github.com/hashicorp/vault/helper/jsonutil", - "revision": "0c3e14f047aede0a70256e1e8b321610910b246e", - "revisionTime": "2017-08-01T15:50:41Z" - }, - { - "checksumSHA1": "GGveKvOwScWGZAAnupzpyw+0Jko=", - "path": "github.com/hashicorp/vault/helper/parseutil", - "revision": "1fd46cbcb10569bd205c3f662e7a4f16f1e69056", - "revisionTime": "2017-08-11T01:28:18Z" - }, - { - "checksumSHA1": "VMaF3Q7RIrRzvbnPbqxuSLryOvc=", - "path": "github.com/hashicorp/yamux", - "revision": "badf81fca035b8ebac61b5ab83330b72541056f4", - "revisionTime": "2016-06-09T13:59:02Z" - }, - { - "checksumSHA1": "0xM336Lb25URO/1W1/CtGoRygVU=", - "path": "github.com/hpcloud/tail/util", - "revision": "37f4271387456dd1bf82ab1ad9229f060cc45386", - "revisionTime": "2017-08-14T16:06:53Z" - }, - { - "checksumSHA1": "TP4OAv5JMtzj2TB6OQBKqauaKDc=", - "path": "github.com/hpcloud/tail/watch", - "revision": "37f4271387456dd1bf82ab1ad9229f060cc45386", - "revisionTime": "2017-08-14T16:06:53Z" - }, - { - "comment": "0.2.2-2-gc01cf91", - "path": "github.com/jmespath/go-jmespath", - "revision": "c01cf91b011868172fdcd9f41838e80c9d716264" - }, - { - "path": "github.com/kardianos/osext", - "revision": "29ae4ffbc9a6fe9fb2bc5029050ce6996ea1d3bc" - }, - { - "checksumSHA1": "eOXF2PEvYLMeD8DSzLZJWbjYzco=", - "path": "github.com/kr/pretty", - "revision": "cfb55aafdaf3ec08f0db22699ab822c50091b1c4", - "revisionTime": "2016-08-23T17:07:15Z" - }, - { - "checksumSHA1": "uulQHQ7IsRKqDudBC8Go9J0gtAc=", - "path": "github.com/kr/text", - "revision": "7cafcd837844e784b526369c9bce262804aebc60", - "revisionTime": "2016-05-04T02:26:26Z" - }, - { - "checksumSHA1": "trzmsZQDCc13zk/6qANox7Z/KCg=", - "path": "github.com/mattn/go-isatty", - "revision": "fc9e8d8ef48496124e79ae0df75490096eccf6fe", - "revisionTime": "2017-03-22T23:44:13Z" - }, - { - "checksumSHA1": "ajImwVZHzsI+aNwsgzCSFSbmJqs=", - "path": "github.com/mattn/go-shellwords", - "revision": "f4e566c536cf69158e808ec28ef4182a37fdc981", - "revisionTime": "2015-03-21T17:42:21Z" - }, - { - "checksumSHA1": "bKMZjd2wPw13VwoE7mBeSv5djFA=", - "path": "github.com/matttproud/golang_protobuf_extensions/pbutil", - "revision": "c12348ce28de40eed0136aa2b644d0ee0650e56c", - "revisionTime": "2016-04-24T11:30:07Z" - }, - { - "path": "github.com/miekg/dns", - "revision": "7e024ce8ce18b21b475ac6baf8fa3c42536bf2fa" - }, - { - "checksumSHA1": "UIqCj7qI0hhIMpAhS9YYqs2jD48=", - "path": "github.com/mitchellh/cli", - "revision": "65fcae5817c8600da98ada9d7edf26dd1a84837b", - "revisionTime": "2017-09-08T18:10:43Z" - }, - { - "checksumSHA1": "ttEN1Aupb7xpPMkQLqb3tzLFdXs=", - "path": "github.com/mitchellh/colorstring", - "revision": "8631ce90f28644f54aeedcb3e389a85174e067d1", - "revisionTime": "2015-09-17T21:48:07Z" - }, - { - "checksumSHA1": "+p4JY4wmFQAppCdlrJ8Kxybmht8=", - "path": "github.com/mitchellh/copystructure", - "revision": "d23ffcb85de31694d6ccaa23ccb4a03e55c1303f", - "revisionTime": "2017-05-25T01:39:02Z" - }, - { - "checksumSHA1": "AXacfEchaUqT5RGmPmMXsOWRhv8=", - "path": "github.com/mitchellh/go-homedir", - "revision": "756f7b183b7ab78acdbbee5c7f392838ed459dda", - "revisionTime": "2016-06-21T17:42:43Z" - }, - { - "checksumSHA1": "DcYIZnMiq/Tj22/ge9os3NwOhs4=", - "path": "github.com/mitchellh/go-ps", - "revision": "4fdf99ab29366514c69ccccddab5dc58b8d84062", - "revisionTime": "2017-03-09T13:30:38Z" - }, - { - "checksumSHA1": "bDdhmDk8q6utWrccBhEOa6IoGkE=", - "path": "github.com/mitchellh/go-testing-interface", - "revision": "a61a99592b77c9ba629d254a693acffaeb4b7e28", - "revisionTime": "2017-10-04T22:19:16Z" - }, - { - "path": "github.com/mitchellh/hashstructure", - "revision": "1ef5c71b025aef149d12346356ac5973992860bc" - }, - { - "path": "github.com/mitchellh/mapstructure", - "revision": "281073eb9eb092240d33ef253c404f1cca550309" - }, - { - "checksumSHA1": "KqsMqI+Y+3EFYPhyzafpIneaVCM=", - "path": "github.com/mitchellh/reflectwalk", - "revision": "8d802ff4ae93611b807597f639c19f76074df5c6", - "revisionTime": "2017-05-08T17:38:06Z" - }, - { - "checksumSHA1": "NTperEHVh1uBqfTy9+oKceN4tKI=", - "path": "github.com/opencontainers/go-digest", - "revision": "21dfd564fd89c944783d00d069f33e3e7123c448", - "revisionTime": "2017-01-11T18:16:59Z" - }, - { - "checksumSHA1": "ZGlIwSRjdLYCUII7JLE++N4w7Xc=", - "path": "github.com/opencontainers/image-spec/specs-go", - "revision": "89b51c794e9113108a2914e38e66c826a649f2b5", - "revisionTime": "2017-11-03T11:36:04Z" - }, - { - "checksumSHA1": "jdbXRRzeu0njLE9/nCEZG+Yg/Jk=", - "path": "github.com/opencontainers/image-spec/specs-go/v1", - "revision": "89b51c794e9113108a2914e38e66c826a649f2b5", - "revisionTime": "2017-11-03T11:36:04Z" - }, - { - "checksumSHA1": "UPfYFznGeLEloCkGG8KKgsKjtPU=", - "comment": "v0.0.9-108-g89ab7f2", - "path": "github.com/opencontainers/runc/libcontainer/cgroups", - "revision": "89ab7f2ccc1e45ddf6485eaa802c35dcf321dfc8", - "revisionTime": "2016-03-31T09:02:02Z" - }, - { - "checksumSHA1": "xIrNApwB9+yQBhu2p6bt7blV+x4=", - "comment": "v0.0.9-108-g89ab7f2", - "path": "github.com/opencontainers/runc/libcontainer/cgroups/fs", - "revision": "89ab7f2ccc1e45ddf6485eaa802c35dcf321dfc8", - "revisionTime": "2016-03-31T09:02:02Z" - }, - { - "checksumSHA1": "CdhRZZmDeY+t3PN4Qpi1ojy50pE=", - "comment": "v0.0.9-108-g89ab7f2", - "path": "github.com/opencontainers/runc/libcontainer/configs", - "revision": "89ab7f2ccc1e45ddf6485eaa802c35dcf321dfc8", - "revisionTime": "2016-03-31T09:02:02Z" - }, - { - "checksumSHA1": "xo2LfoL27cGF6cChWvew2KfhpNI=", - "comment": "v0.0.9-108-g89ab7f2", - "path": "github.com/opencontainers/runc/libcontainer/system", - "revision": "89ab7f2ccc1e45ddf6485eaa802c35dcf321dfc8", - "revisionTime": "2016-03-31T09:02:02Z" - }, - { - "checksumSHA1": "3AoPMXlmVq2+iWMpsdJZkcUKHB8=", - "path": "github.com/opencontainers/runc/libcontainer/user", - "revision": "89ab7f2ccc1e45ddf6485eaa802c35dcf321dfc8", - "revisionTime": "2016-03-31T09:02:02Z" - }, - { - "checksumSHA1": "PCfoPliJrUhzLP4arNs2KjEb2Bc=", - "comment": "v0.0.9-108-g89ab7f2", - "path": "github.com/opencontainers/runc/libcontainer/utils", - "revision": "89ab7f2ccc1e45ddf6485eaa802c35dcf321dfc8", - "revisionTime": "2016-03-31T09:02:02Z" - }, - { - "checksumSHA1": "ynJSWoF6v+3zMnh9R0QmmG6iGV8=", - "path": "github.com/pkg/errors", - "revision": "248dadf4e9068a0b3e79f02ed0a610d935de5302", - "revisionTime": "2016-10-29T09:36:37Z" - }, - { - "checksumSHA1": "LuFv4/jlrmFNnDb/5SCSEPAM9vU=", - "path": "github.com/pmezard/go-difflib/difflib", - "revision": "792786c7400a136282c1664665ae0a8db921c6c2", - "revisionTime": "2016-01-10T10:55:54Z" - }, - { - "checksumSHA1": "rTNABfFJ9wtLQRH8uYNkEZGQOrY=", - "path": "github.com/posener/complete", - "revision": "9f41f7636a724791a3b8b1d35e84caa1124f0d3c", - "revisionTime": "2017-08-29T17:11:12Z" - }, - { - "checksumSHA1": "NB7uVS0/BJDmNu68vPAlbrq4TME=", - "path": "github.com/posener/complete/cmd", - "revision": "9f41f7636a724791a3b8b1d35e84caa1124f0d3c", - "revisionTime": "2017-08-29T17:11:12Z" - }, - { - "checksumSHA1": "gSX86Xl0w9hvtntdT8h23DZtSag=", - "path": "github.com/posener/complete/cmd/install", - "revision": "9f41f7636a724791a3b8b1d35e84caa1124f0d3c", - "revisionTime": "2017-08-29T17:11:12Z" - }, - { - "checksumSHA1": "DMo94FwJAm9ZCYCiYdJU2+bh4no=", - "path": "github.com/posener/complete/match", - "revision": "9f41f7636a724791a3b8b1d35e84caa1124f0d3c", - "revisionTime": "2017-08-29T17:11:12Z" - }, - { - "checksumSHA1": "+5YXakGoZBEMrHp6h64TC5GSFfg=", - "path": "github.com/prometheus/client_golang/prometheus", - "revision": "671c87b04728565380d95c621edc687bfa00664c", - "revisionTime": "2017-09-07T15:06:25Z" - }, - { - "checksumSHA1": "wsAkYlRRUNx+OAuUOIqdjO7dICM=", - "path": "github.com/prometheus/client_golang/prometheus/promhttp", - "revision": "671c87b04728565380d95c621edc687bfa00664c", - "revisionTime": "2017-09-07T15:06:25Z" - }, - { - "checksumSHA1": "DvwvOlPNAgRntBzt3b3OSRMS2N4=", - "path": "github.com/prometheus/client_model/go", - "revision": "6f3806018612930941127f2a7c6c453ba2c527d2", - "revisionTime": "2017-02-16T18:52:47Z" - }, - { - "checksumSHA1": "xfnn0THnqNwjwimeTClsxahYrIo=", - "path": "github.com/prometheus/common/expfmt", - "revision": "2f17f4a9d485bf34b4bfaccc273805040e4f86c8", - "revisionTime": "2017-09-08T16:18:22Z" - }, - { - "checksumSHA1": "GWlM3d2vPYyNATtTFgftS10/A9w=", - "path": "github.com/prometheus/common/internal/bitbucket.org/ww/goautoneg", - "revision": "2f17f4a9d485bf34b4bfaccc273805040e4f86c8", - "revisionTime": "2017-09-08T16:18:22Z" - }, - { - "checksumSHA1": "3VoqH7TFfzA6Ds0zFzIbKCUvBmw=", - "path": "github.com/prometheus/common/model", - "revision": "2f17f4a9d485bf34b4bfaccc273805040e4f86c8", - "revisionTime": "2017-09-08T16:18:22Z" - }, - { - "checksumSHA1": "ihxJIjxtbEYdQKwA0D0nRipj95I=", - "path": "github.com/prometheus/procfs", - "revision": "e645f4e5aaa8506fc71d6edbc5c4ff02c04c46f2", - "revisionTime": "2017-07-03T10:12:42Z" - }, - { - "checksumSHA1": "xCiFAAwVTrjsfZT1BIJQ3DgeNCY=", - "path": "github.com/prometheus/procfs/xfs", - "revision": "e645f4e5aaa8506fc71d6edbc5c4ff02c04c46f2", - "revisionTime": "2017-07-03T10:12:42Z" - }, - { - "checksumSHA1": "ge4Z0w3QJJYTBqJaK3S+a6MCxzQ=", - "path": "github.com/rkt/rkt/api/v1", - "revision": "3abde24bc284b7ded5784c56b4e8184c28999641", - "revisionTime": "2017-08-01T12:18:56Z", - "version": "v1.28.1", - "versionExact": "v1.28.1" - }, - { - "checksumSHA1": "4QqLbh9MmajcN6gCx8Er1voiQys=", - "path": "github.com/rkt/rkt/networking/netinfo", - "revision": "5e83d91aafef5f7a38fef62c045e8b57eeeb8bce", - "revisionTime": "2017-09-20T12:17:54Z" - }, - { - "checksumSHA1": "I778b2sbNN/yjwKSdb3y7hz2yUQ=", - "path": "github.com/rs/cors", - "revision": "eabcc6af4bbe5ad3a949d36450326a2b0b9894b8", - "revisionTime": "2017-08-01T07:32:01Z" - }, - { - "checksumSHA1": "M57Rrfc8Z966p+IBtQ91QOcUtcg=", - "comment": "v2.0.1-8-g983d3a5", - "path": "github.com/ryanuber/columnize", - "revision": "abc90934186a77966e2beeac62ed966aac0561d5", - "revisionTime": "2017-07-03T20:58:27Z" - }, - { - "checksumSHA1": "tnMZLo/kR9Kqx6GtmWwowtTLlA8=", - "path": "github.com/sean-/seed", - "revision": "e2103e2c35297fb7e17febb81e49b312087a2372", - "revisionTime": "2017-03-13T16:33:22Z" - }, - { - "checksumSHA1": "8Lm8nsMCFz4+gr9EvQLqK8+w+Ks=", - "path": "github.com/sethgrid/pester", - "revision": "8053687f99650573b28fb75cddf3f295082704d7", - "revisionTime": "2016-04-29T17:20:22Z" - }, - { - "checksumSHA1": "T2ThCk35wXAZGh37nrgA07199dA=", - "path": "github.com/shirou/gopsutil/cpu", - "revision": "1c211f0807a3436707409fa313599dd8c7a48664", - "revisionTime": "2017-08-17T03:45:37Z" - }, - { - "checksumSHA1": "T4uyVXPqCS5rj4vYLgv04as0Avw=", - "path": "github.com/shirou/gopsutil/disk", - "revision": "1c211f0807a3436707409fa313599dd8c7a48664", - "revisionTime": "2017-08-17T03:45:37Z" - }, - { - "checksumSHA1": "YBXpUckp1TtJf2mfMLx/bpnm22Q=", - "path": "github.com/shirou/gopsutil/host", - "revision": "1c211f0807a3436707409fa313599dd8c7a48664", - "revisionTime": "2017-08-17T03:45:37Z" - }, - { - "checksumSHA1": "jUWM0P4G1bHpO9CPS8gcr4rt1t0=", - "path": "github.com/shirou/gopsutil/internal/common", - "revision": "1c211f0807a3436707409fa313599dd8c7a48664", - "revisionTime": "2017-08-17T03:45:37Z" - }, - { - "checksumSHA1": "xIAuacHA0LNq1yM5Wd1q4lnbzxU=", - "path": "github.com/shirou/gopsutil/mem", - "revision": "1c211f0807a3436707409fa313599dd8c7a48664", - "revisionTime": "2017-08-17T03:45:37Z" - }, - { - "checksumSHA1": "moxD+mq0dMHnbTeFyeEHK0Iq7i8=", - "path": "github.com/shirou/gopsutil/net", - "revision": "1c211f0807a3436707409fa313599dd8c7a48664", - "revisionTime": "2017-08-17T03:45:37Z" - }, - { - "checksumSHA1": "C6ybAAUmWz+PQKqJ8byV7Nj5JXQ=", - "path": "github.com/shirou/gopsutil/process", - "revision": "1c211f0807a3436707409fa313599dd8c7a48664", - "revisionTime": "2017-08-17T03:45:37Z" - }, - { - "checksumSHA1": "Nve7SpDmjsv6+rhkXAkfg/UQx94=", - "path": "github.com/shirou/w32", - "revision": "bb4de0191aa41b5507caa14b0650cdbddcd9280b", - "revisionTime": "2016-09-30T03:27:40Z" - }, - { - "checksumSHA1": "h/HMhokbQHTdLUbruoBBTee+NYw=", - "path": "github.com/skratchdot/open-golang/open", - "revision": "75fb7ed4208cf72d323d7d02fd1a5964a7a9073c", - "revisionTime": "2016-03-02T14:40:31Z" - }, - { - "checksumSHA1": "Q52Y7t0lEtk/wcDn5q7tS7B+jqs=", - "path": "github.com/spf13/pflag", - "revision": "7aff26db30c1be810f9de5038ec5ef96ac41fd7c", - "revisionTime": "2017-08-24T17:57:12Z" - }, - { - "checksumSHA1": "K0crHygPTP42i1nLKWphSlvOQJw=", - "path": "github.com/stretchr/objx", - "revision": "1a9d0bb9f541897e62256577b352fdbc1fb4fd94", - "revisionTime": "2015-09-28T12:21:52Z" - }, - { - "checksumSHA1": "o+jsS/rxceTym4M3reSPfrPxaio=", - "path": "github.com/stretchr/testify/mock", - "revision": "f6abca593680b2315d2075e0f5e2a9751e3f431a", - "revisionTime": "2017-06-01T20:57:54Z" - }, - { - "checksumSHA1": "8G1zvpE4gTtWQRuP/x2HPVDmflo=", - "path": "github.com/ugorji/go/codec", - "revision": "0053ebfd9d0ee06ccefbfe17072021e1d4acebee", - "revisionTime": "2017-06-20T06:01:02Z" - }, - { - "checksumSHA1": "OgParimNuU2CJqr3pcTympeQZUc=", - "path": "github.com/ugorji/go/codec/codecgen", - "revision": "5efa3251c7f7d05e5d9704a69a984ec9f1386a40", - "revisionTime": "2017-06-20T10:48:52Z" - }, - { - "checksumSHA1": "z2kAtVle4NFV2OExI85fZoTcsI4=", - "path": "github.com/ulikunitz/xz", - "revision": "0c6b41e72360850ca4f98dc341fd999726ea007f", - "revisionTime": "2017-06-05T21:53:11Z" - }, - { - "checksumSHA1": "vjnTkzNrMs5Xj6so/fq0mQ6dT1c=", - "path": "github.com/ulikunitz/xz/internal/hash", - "revision": "0c6b41e72360850ca4f98dc341fd999726ea007f", - "revisionTime": "2017-06-05T21:53:11Z" - }, - { - "checksumSHA1": "m0pm57ASBK/CTdmC0ppRHO17mBs=", - "path": "github.com/ulikunitz/xz/internal/xlog", - "revision": "0c6b41e72360850ca4f98dc341fd999726ea007f", - "revisionTime": "2017-06-05T21:53:11Z" - }, - { - "checksumSHA1": "2vZw6zc8xuNlyVz2QKvdlNSZQ1U=", - "path": "github.com/ulikunitz/xz/lzma", - "revision": "0c6b41e72360850ca4f98dc341fd999726ea007f", - "revisionTime": "2017-06-05T21:53:11Z" - }, - { - "checksumSHA1": "PMr/a5kcnC4toJtVwWhlU5E4tJY=", - "path": "go4.org/errorutil", - "revision": "034d17a462f7b2dcd1a4a73553ec5357ff6e6c6e", - "revisionTime": "2017-05-24T23:16:39Z" - }, - { - "checksumSHA1": "5TlXhxVMqfHQKpCKucmXNeE6/kc=", - "path": "golang.org/x/crypto/blake2b", - "revision": "74b34b9dd60829a9fcaf56a59e81c3877a8ecd2c", - "revisionTime": "2017-09-02T17:19:23Z" - }, - { - "checksumSHA1": "nqWNlnMmVpt628zzvyo6Yv2CX5Q=", - "path": "golang.org/x/crypto/ssh/terminal", - "revision": "eb71ad9bd329b5ac0fd0148dd99bd62e8be8e035", - "revisionTime": "2017-08-07T10:11:13Z" - }, - { - "checksumSHA1": "9jjO5GjLa0XF/nfWihF02RoH4qc=", - "path": "golang.org/x/net/context", - "revision": "30db96677b74e24b967e23f911eb3364fc61a011", - "revisionTime": "2016-05-25T13:11:03Z" - }, - { - "checksumSHA1": "WHc3uByvGaMcnSoI21fhzYgbOgg=", - "path": "golang.org/x/net/context/ctxhttp", - "revision": "f09c4662a0bd6bd8943ac7b4931e185df9471da4", - "revisionTime": "2016-09-24T00:10:04Z" - }, - { - "checksumSHA1": "kKuxyoDujo5CopTxAvvZ1rrLdd0=", - "path": "golang.org/x/net/http2", - "revision": "ab5485076ff3407ad2d02db054635913f017b0ed", - "revisionTime": "2017-07-19T21:11:51Z" - }, - { - "checksumSHA1": "ezWhc7n/FtqkLDQKeU2JbW+80tE=", - "path": "golang.org/x/net/http2/hpack", - "revision": "ab5485076ff3407ad2d02db054635913f017b0ed", - "revisionTime": "2017-07-19T21:11:51Z" - }, - { - "checksumSHA1": "g/Z/Ka0VgJESgQK7/SJCjm/aX0I=", - "path": "golang.org/x/net/idna", - "revision": "ab5485076ff3407ad2d02db054635913f017b0ed", - "revisionTime": "2017-07-19T21:11:51Z" - }, - { - "checksumSHA1": "UxahDzW2v4mf/+aFxruuupaoIwo=", - "path": "golang.org/x/net/internal/timeseries", - "revision": "ab5485076ff3407ad2d02db054635913f017b0ed", - "revisionTime": "2017-07-19T21:11:51Z" - }, - { - "checksumSHA1": "3xyuaSNmClqG4YWC7g0isQIbUTc=", - "path": "golang.org/x/net/lex/httplex", - "revision": "ab5485076ff3407ad2d02db054635913f017b0ed", - "revisionTime": "2017-07-19T21:11:51Z" - }, - { - "checksumSHA1": "u/r66lwYfgg682u5hZG7/E7+VCY=", - "path": "golang.org/x/net/trace", - "revision": "ab5485076ff3407ad2d02db054635913f017b0ed", - "revisionTime": "2017-07-19T21:11:51Z" - }, - { - "checksumSHA1": "S0DP7Pn7sZUmXc55IzZnNvERu6s=", - "path": "golang.org/x/sync/errgroup", - "revision": "316e794f7b5e3df4e95175a45a5fb8b12f85cb4f", - "revisionTime": "2016-07-15T18:54:39Z" - }, - { - "checksumSHA1": "SIhhNXud9FKua0s3WlGPRRkDKRg=", - "path": "golang.org/x/sys/unix", - "revision": "8b4580aae2a0dd0c231a45d3ccb8434ff533b840", - "revisionTime": "2017-11-30T16:26:51Z" - }, - { - "checksumSHA1": "riTVymIu2BFphV6UlA73Fn9tmmU=", - "path": "golang.org/x/sys/windows", - "revision": "8b4580aae2a0dd0c231a45d3ccb8434ff533b840", - "revisionTime": "2017-11-30T16:26:51Z" - }, - { - "checksumSHA1": "tltivJ/uj/lqLk05IqGfCv2F/E8=", - "path": "golang.org/x/text/secure/bidirule", - "revision": "88f656faf3f37f690df1a32515b479415e1a6769", - "revisionTime": "2017-10-26T07:52:28Z" - }, - { - "checksumSHA1": "ziMb9+ANGRJSSIuxYdRbA+cDRBQ=", - "path": "golang.org/x/text/transform", - "revision": "88f656faf3f37f690df1a32515b479415e1a6769", - "revisionTime": "2017-10-26T07:52:28Z" - }, - { - "checksumSHA1": "iB6/RoQIzBaZxVi+t7tzbkwZTlo=", - "path": "golang.org/x/text/unicode/bidi", - "revision": "88f656faf3f37f690df1a32515b479415e1a6769", - "revisionTime": "2017-10-26T07:52:28Z" - }, - { - "checksumSHA1": "km/8bLtOpIP7sua4MnEmiSDYTAE=", - "path": "golang.org/x/text/unicode/norm", - "revision": "88f656faf3f37f690df1a32515b479415e1a6769", - "revisionTime": "2017-10-26T07:52:28Z" - }, - { - "checksumSHA1": "h/06ikMECfJoTkWj2e1nJ30aDDg=", - "path": "golang.org/x/time/rate", - "revision": "a4bde12657593d5e90d0533a3e4fd95e635124cb", - "revisionTime": "2016-02-02T18:34:45Z" - }, - { - "checksumSHA1": "AvVpgwhxhJgjoSledwDtYrEKVE4=", - "path": "google.golang.org/genproto/googleapis/rpc/status", - "revision": "b0a3dcfcd1a9bd48e63634bd8802960804cf8315", - "revisionTime": "2017-07-11T23:52:30Z" - }, - { - "checksumSHA1": "2HA7jxFtX4Dp7Lt3wafAUXa9IZc=", - "path": "google.golang.org/grpc", - "revision": "0c41876308d45bc82e587965971e28be659a1aca", - "revisionTime": "2017-07-21T17:58:12Z" - }, - { - "checksumSHA1": "/eTpFgjvMq5Bc9hYnw5fzKG4B6I=", - "path": "google.golang.org/grpc/codes", - "revision": "0c41876308d45bc82e587965971e28be659a1aca", - "revisionTime": "2017-07-21T17:58:12Z" - }, - { - "checksumSHA1": "5ylThBvJnIcyWhL17AC9+Sdbw2E=", - "path": "google.golang.org/grpc/credentials", - "revision": "0c41876308d45bc82e587965971e28be659a1aca", - "revisionTime": "2017-07-21T17:58:12Z" - }, - { - "checksumSHA1": "2NbY9kmMweE4VUsruRsvmViVnNg=", - "path": "google.golang.org/grpc/grpclb/grpc_lb_v1", - "revision": "0c41876308d45bc82e587965971e28be659a1aca", - "revisionTime": "2017-07-21T17:58:12Z" - }, - { - "checksumSHA1": "MCQmohiDJwkgLWu/wpnekweQh8s=", - "path": "google.golang.org/grpc/grpclog", - "revision": "0c41876308d45bc82e587965971e28be659a1aca", - "revisionTime": "2017-07-21T17:58:12Z" - }, - { - "checksumSHA1": "pc9cweMiKQ5hVMuO9UoMGdbizaY=", - "path": "google.golang.org/grpc/health", - "revision": "0c41876308d45bc82e587965971e28be659a1aca", - "revisionTime": "2017-07-21T17:58:12Z" - }, - { - "checksumSHA1": "W5KfI1NIGJt7JaVnLzefDZr3+4s=", - "path": "google.golang.org/grpc/health/grpc_health_v1", - "revision": "0c41876308d45bc82e587965971e28be659a1aca", - "revisionTime": "2017-07-21T17:58:12Z" - }, - { - "checksumSHA1": "U9vDe05/tQrvFBojOQX8Xk12W9I=", - "path": "google.golang.org/grpc/internal", - "revision": "0c41876308d45bc82e587965971e28be659a1aca", - "revisionTime": "2017-07-21T17:58:12Z" - }, - { - "checksumSHA1": "hcuHgKp8W0wIzoCnNfKI8NUss5o=", - "path": "google.golang.org/grpc/keepalive", - "revision": "0c41876308d45bc82e587965971e28be659a1aca", - "revisionTime": "2017-07-21T17:58:12Z" - }, - { - "checksumSHA1": "N++Ur11m6Dq3j14/Hc2Kqmxroag=", - "path": "google.golang.org/grpc/metadata", - "revision": "0c41876308d45bc82e587965971e28be659a1aca", - "revisionTime": "2017-07-21T17:58:12Z" - }, - { - "checksumSHA1": "Zzb7Xsc3tbTJzrcZbSPyye+yxmw=", - "path": "google.golang.org/grpc/naming", - "revision": "0c41876308d45bc82e587965971e28be659a1aca", - "revisionTime": "2017-07-21T17:58:12Z" - }, - { - "checksumSHA1": "n5EgDdBqFMa2KQFhtl+FF/4gIFo=", - "path": "google.golang.org/grpc/peer", - "revision": "0c41876308d45bc82e587965971e28be659a1aca", - "revisionTime": "2017-07-21T17:58:12Z" - }, - { - "checksumSHA1": "ZY8Tq61fGK1stTuvwK5WoqcU8j8=", - "path": "google.golang.org/grpc/stats", - "revision": "0c41876308d45bc82e587965971e28be659a1aca", - "revisionTime": "2017-07-21T17:58:12Z" - }, - { - "checksumSHA1": "DIv9qbApAoh2cF2G3Br24lVPqUI=", - "path": "google.golang.org/grpc/status", - "revision": "0c41876308d45bc82e587965971e28be659a1aca", - "revisionTime": "2017-07-21T17:58:12Z" - }, - { - "checksumSHA1": "aixGx/Kd0cj9ZlZHacpHe3XgMQ4=", - "path": "google.golang.org/grpc/tap", - "revision": "0c41876308d45bc82e587965971e28be659a1aca", - "revisionTime": "2017-07-21T17:58:12Z" - }, - { - "checksumSHA1": "oFGr0JoquaPGVnV86fVL8MVTc3A=", - "path": "google.golang.org/grpc/transport", - "revision": "0c41876308d45bc82e587965971e28be659a1aca", - "revisionTime": "2017-07-21T17:58:12Z" - }, - { - "checksumSHA1": "eIhF+hmL/XZhzTiAwhLD0M65vlY=", - "path": "gopkg.in/fsnotify.v1", - "revision": "629574ca2a5df945712d3079857300b5e4da0236", - "revisionTime": "2016-10-11T02:33:12Z" - }, - { - "checksumSHA1": "6f8MEU31llHM1sLM/GGH4/Qxu0A=", - "path": "gopkg.in/inf.v0", - "revision": "3887ee99ecf07df5b447e9b00d9c0b2adaa9f3e4", - "revisionTime": "2015-09-11T12:57:57Z" - }, - { - "checksumSHA1": "i97goLq3AIfUNB8l1hxGGMSW0+s=", - "path": "gopkg.in/lxc/go-lxc.v2", - "revision": "f8a6938e600c634232eeef79dc04a1226f73a88b", - "revisionTime": "2016-08-03T16:52:18Z" - }, - { - "checksumSHA1": "TO8baX+t1Qs7EmOYth80MkbKzFo=", - "path": "gopkg.in/tomb.v1", - "revision": "dd632973f1e7218eb1089048e0798ec9ae7dceb8", - "revisionTime": "2014-10-24T13:56:13Z" - }, - { - "checksumSHA1": "WiyCOMvfzRdymImAJ3ME6aoYUdM=", - "path": "gopkg.in/tomb.v2", - "revision": "14b3d72120e8d10ea6e6b7f87f7175734b1faab8", - "revisionTime": "2014-06-26T14:46:23Z" - }, - { - "checksumSHA1": "12GqsW8PiRPnezDDy0v4brZrndM=", - "path": "gopkg.in/yaml.v2", - "revision": "a5b47d31c556af34a302ce5d659e6fea44d90de0", - "revisionTime": "2016-09-28T15:37:09Z" - } + {"path":"context","revision":""}, + {"path":"github.com/Azure/go-ansiterm","checksumSHA1":"23FJUX+AInYeEM2hoUMvYZtXZd4=","revision":"fa152c58bc15761d0200cb75fe958b89a9d4888e","revisionTime":"2016-06-22T17:32:16Z"}, + {"path":"github.com/Azure/go-ansiterm/winterm","checksumSHA1":"jBimnggjIiFUjaImNoJhSVLtdzw=","revision":"fa152c58bc15761d0200cb75fe958b89a9d4888e","revisionTime":"2016-06-22T17:32:16Z"}, + {"path":"github.com/DataDog/datadog-go/statsd","checksumSHA1":"WvApwvvSe3i/3KO8300dyeFmkbI=","revision":"b10af4b12965a1ad08d164f57d14195b4140d8de","revisionTime":"2017-08-09T10:47:06Z"}, + {"path":"github.com/Microsoft/go-winio","checksumSHA1":"AzjRkOQtVBTwIw4RJLTygFhJs3s=","revision":"f533f7a102197536779ea3a8cb881d639e21ec5a","revisionTime":"2017-05-24T00:36:31Z"}, + {"path":"github.com/NYTimes/gziphandler","checksumSHA1":"jktW57+vJsziNVPeXMCoujTzdW4=","revision":"97ae7fbaf81620fe97840685304a78a306a39c64","revisionTime":"2017-09-16T00:36:49Z"}, + {"path":"github.com/Nvveen/Gotty","checksumSHA1":"Aqy8/FoAIidY/DeQ5oTYSZ4YFVc=","revision":"cd527374f1e5bff4938207604a14f2e38a9cf512","revisionTime":"2012-06-04T00:48:16Z"}, + {"path":"github.com/RackSec/srslog","checksumSHA1":"OTN4c1F0p+mEG2CpkU1Kuavupf0=","revision":"259aed10dfa74ea2961eddd1d9847619f6e98837","revisionTime":"2016-01-20T22:33:50Z"}, + {"path":"github.com/Sirupsen/logrus","comment":"v0.8.7-87-g4b6ea73","revision":"4b6ea7319e214d98c938f12692336f7ca9348d6b"}, + {"path":"github.com/StackExchange/wmi","checksumSHA1":"qtjd74+bErubh+qyv3s+lWmn9wc=","revision":"ea383cf3ba6ec950874b8486cd72356d007c768f","revisionTime":"2017-04-10T19:29:09Z"}, + {"path":"github.com/appc/spec/schema","checksumSHA1":"uWJDTv0R/NJVYv51LVy6vKP1CZw=","revision":"cbe99b7160b1397bf89f9c8bb1418f69c9424049","revisionTime":"2017-09-19T09:55:19Z"}, + {"path":"github.com/appc/spec/schema/common","checksumSHA1":"Q47G6996hbfQaNp/8CFkGWTVQpw=","revision":"cbe99b7160b1397bf89f9c8bb1418f69c9424049","revisionTime":"2017-09-19T09:55:19Z"}, + {"path":"github.com/appc/spec/schema/types","checksumSHA1":"kYXCle7Ikc8WqiMs7NXz99bUWqo=","revision":"cbe99b7160b1397bf89f9c8bb1418f69c9424049","revisionTime":"2017-09-19T09:55:19Z"}, + {"path":"github.com/appc/spec/schema/types/resource","checksumSHA1":"VgPsPj5PH7LKXMa3ZLe5/+Avydo=","revision":"cbe99b7160b1397bf89f9c8bb1418f69c9424049","revisionTime":"2017-09-19T09:55:19Z"}, + {"path":"github.com/armon/circbuf","revision":"bbbad097214e2918d8543d5201d12bfd7bca254d"}, + {"path":"github.com/armon/go-metrics","checksumSHA1":"xp/2s4XclLL17DThGBI7jXZ4Crs=","revision":"6c3acc97c61d04290a8ba2e54640151f54c1546a","revisionTime":"2017-11-16T18:41:20Z"}, + {"path":"github.com/armon/go-metrics/circonus","checksumSHA1":"xCsGGM9TKBogZDfSN536KtQdLko=","revision":"6c3acc97c61d04290a8ba2e54640151f54c1546a","revisionTime":"2017-11-16T18:41:20Z"}, + {"path":"github.com/armon/go-metrics/datadog","checksumSHA1":"Dt0n1sSivvvdZQdzc4Hu/yOG+T0=","revision":"6c3acc97c61d04290a8ba2e54640151f54c1546a","revisionTime":"2017-11-16T18:41:20Z"}, + {"path":"github.com/armon/go-metrics/prometheus","checksumSHA1":"XfPPXw55zKziOWnZbkEGEJ96O9c=","revision":"6c3acc97c61d04290a8ba2e54640151f54c1546a","revisionTime":"2017-11-16T18:41:20Z"}, + {"path":"github.com/armon/go-radix","checksumSHA1":"gNO0JNpLzYOdInGeq7HqMZUzx9M=","revision":"4239b77079c7b5d1243b7b4736304ce8ddb6f0f2","revisionTime":"2016-01-15T23:47:25Z"}, + {"path":"github.com/aws/aws-sdk-go/aws","comment":"v1.0.6-2-g80dd495","revision":"80dd4951fdb3f711d31843b8d87871130ef2df67"}, + {"path":"github.com/aws/aws-sdk-go/aws/awserr","comment":"v1.0.6-2-g80dd495","revision":"80dd4951fdb3f711d31843b8d87871130ef2df67"}, + {"path":"github.com/aws/aws-sdk-go/aws/awsutil","comment":"v1.0.6-2-g80dd495","revision":"80dd4951fdb3f711d31843b8d87871130ef2df67"}, + {"path":"github.com/aws/aws-sdk-go/aws/client","comment":"v1.0.6-2-g80dd495","revision":"80dd4951fdb3f711d31843b8d87871130ef2df67"}, + {"path":"github.com/aws/aws-sdk-go/aws/client/metadata","comment":"v1.0.6-2-g80dd495","revision":"80dd4951fdb3f711d31843b8d87871130ef2df67"}, + {"path":"github.com/aws/aws-sdk-go/aws/corehandlers","comment":"v1.0.6-2-g80dd495","revision":"80dd4951fdb3f711d31843b8d87871130ef2df67"}, + {"path":"github.com/aws/aws-sdk-go/aws/credentials","comment":"v1.0.6-2-g80dd495","revision":"80dd4951fdb3f711d31843b8d87871130ef2df67"}, + {"path":"github.com/aws/aws-sdk-go/aws/credentials/ec2rolecreds","comment":"v1.0.6-2-g80dd495","revision":"80dd4951fdb3f711d31843b8d87871130ef2df67"}, + {"path":"github.com/aws/aws-sdk-go/aws/defaults","comment":"v1.0.6-2-g80dd495","revision":"80dd4951fdb3f711d31843b8d87871130ef2df67"}, + {"path":"github.com/aws/aws-sdk-go/aws/ec2metadata","comment":"v1.0.6-2-g80dd495","revision":"80dd4951fdb3f711d31843b8d87871130ef2df67"}, + {"path":"github.com/aws/aws-sdk-go/aws/request","comment":"v1.0.6-2-g80dd495","revision":"80dd4951fdb3f711d31843b8d87871130ef2df67"}, + {"path":"github.com/aws/aws-sdk-go/aws/session","comment":"v1.0.6-2-g80dd495","revision":"80dd4951fdb3f711d31843b8d87871130ef2df67"}, + {"path":"github.com/aws/aws-sdk-go/private/endpoints","comment":"v1.0.6-2-g80dd495","revision":"80dd4951fdb3f711d31843b8d87871130ef2df67"}, + {"path":"github.com/aws/aws-sdk-go/private/protocol/query","comment":"v1.0.6-2-g80dd495","revision":"80dd4951fdb3f711d31843b8d87871130ef2df67"}, + {"path":"github.com/aws/aws-sdk-go/private/protocol/query/queryutil","comment":"v1.0.6-2-g80dd495","revision":"80dd4951fdb3f711d31843b8d87871130ef2df67"}, + {"path":"github.com/aws/aws-sdk-go/private/protocol/rest","comment":"v1.0.6-2-g80dd495","revision":"80dd4951fdb3f711d31843b8d87871130ef2df67"}, + {"path":"github.com/aws/aws-sdk-go/private/protocol/restxml","comment":"v1.0.6-2-g80dd495","revision":"80dd4951fdb3f711d31843b8d87871130ef2df67"}, + {"path":"github.com/aws/aws-sdk-go/private/protocol/xml/xmlutil","comment":"v1.0.6-2-g80dd495","revision":"80dd4951fdb3f711d31843b8d87871130ef2df67"}, + {"path":"github.com/aws/aws-sdk-go/private/signer/v4","comment":"v1.0.6-2-g80dd495","revision":"80dd4951fdb3f711d31843b8d87871130ef2df67"}, + {"path":"github.com/aws/aws-sdk-go/private/waiter","comment":"v1.0.6-2-g80dd495","revision":"80dd4951fdb3f711d31843b8d87871130ef2df67"}, + {"path":"github.com/aws/aws-sdk-go/service/s3","comment":"v1.0.6-2-g80dd495","revision":"80dd4951fdb3f711d31843b8d87871130ef2df67"}, + {"path":"github.com/beorn7/perks/quantile","checksumSHA1":"spyv5/YFBjYyZLZa1U2LBfDR8PM=","revision":"4c0e84591b9aa9e6dcfdf3e020114cd81f89d5f9","revisionTime":"2016-08-04T10:47:26Z"}, + {"path":"github.com/bgentry/go-netrc/netrc","checksumSHA1":"nqw2Qn5xUklssHTubS5HDvEL9L4=","revision":"9fd32a8b3d3d3f9d43c341bfe098430e07609480","revisionTime":"2014-04-22T17:41:19Z"}, + {"path":"github.com/bgentry/speakeasy","revision":"36e9cfdd690967f4f690c6edcc9ffacd006014a0"}, + {"path":"github.com/bgentry/speakeasy/example","revision":"36e9cfdd690967f4f690c6edcc9ffacd006014a0"}, + {"path":"github.com/boltdb/bolt","checksumSHA1":"R1Q34Pfnt197F/nCOO9kG8c+Z90=","comment":"v1.2.0","revision":"2f1ce7a837dcb8da3ec595b1dac9d0632f0f99e8","revisionTime":"2017-07-17T17:11:48Z","version":"v1.3.1","versionExact":"v1.3.1"}, + {"path":"github.com/burntsushi/toml","checksumSHA1":"InIrfOI7Ys1QqZpCgTB4yW1G32M=","revision":"99064174e013895bbd9b025c31100bd1d9b590ca","revisionTime":"2016-07-17T15:07:09Z"}, + {"path":"github.com/circonus-labs/circonus-gometrics","checksumSHA1":"vhCArnFcQRM84iZcfMXka+2OzrE=","revision":"a2c28f079ec3d4fdc17ed577cca75bee88a2da25","revisionTime":"2017-01-31T13:03:52Z"}, + {"path":"github.com/circonus-labs/circonus-gometrics/api","checksumSHA1":"sInms3AjZrjG/WCRcmS/NSzLUT4=","revision":"a2c28f079ec3d4fdc17ed577cca75bee88a2da25","revisionTime":"2017-01-31T13:03:52Z"}, + {"path":"github.com/circonus-labs/circonus-gometrics/api/config","checksumSHA1":"bQhz/fcyZPmuHSH2qwC4ZtATy5c=","revision":"a2c28f079ec3d4fdc17ed577cca75bee88a2da25","revisionTime":"2017-01-31T13:03:52Z"}, + {"path":"github.com/circonus-labs/circonus-gometrics/checkmgr","checksumSHA1":"6hvd+YFb1eWFkc3pVcnOPPa2OVw=","revision":"a2c28f079ec3d4fdc17ed577cca75bee88a2da25","revisionTime":"2017-01-31T13:03:52Z"}, + {"path":"github.com/circonus-labs/circonusllhist","checksumSHA1":"VbfeVqeOM+dTNxCmpvmYS0LwQn0=","revision":"7d649b46cdc2cd2ed102d350688a75a4fd7778c6","revisionTime":"2016-11-21T13:51:53Z"}, + {"path":"github.com/containernetworking/cni/pkg/types","checksumSHA1":"NeAp/3+Hedu9tnMai+LihERPj84=","revision":"5c3c17164270150467498a32c71436c7cd5501be","revisionTime":"2016-06-02T16:00:07Z"}, + {"path":"github.com/coreos/go-semver/semver","checksumSHA1":"97BsbXOiZ8+Kr+LIuZkQFtSj7H4=","revision":"1817cd4bea52af76542157eeabd74b057d1a199e","revisionTime":"2017-06-13T09:22:38Z"}, + {"path":"github.com/davecgh/go-spew/spew","checksumSHA1":"mrz/kicZiUaHxkyfvC/DyQcr8Do=","revision":"ecdeabc65495df2dec95d7c4a4c3e021903035e5","revisionTime":"2017-10-02T20:02:53Z"}, + {"path":"github.com/docker/distribution/digestset","checksumSHA1":"Gj+xR1VgFKKmFXYOJMnAczC3Znk=","revision":"69c7f303d511a5777e79505b23340d37d532d7ac","revisionTime":"2017-01-11T18:37:34Z"}, + {"path":"github.com/docker/distribution/reference","checksumSHA1":"FqADPtHUqEtmfC7Zf+0pI++Kb6g=","revision":"69c7f303d511a5777e79505b23340d37d532d7ac","revisionTime":"2017-01-11T18:37:34Z"}, + {"path":"github.com/docker/docker/api/types","checksumSHA1":"HoN/78ovv3/DC+kDKF7IENEc40g=","revision":"e4d0fe84f9ea88b0e0cfd847412c9f29442cc62d","revisionTime":"2017-11-14T19:25:14Z"}, + {"path":"github.com/docker/docker/api/types/blkiodev","checksumSHA1":"jVJDbe0IcyjoKc2xbohwzQr+FF0=","revision":"3dc87714d1bfcaf0620fabec3bfea89620b59337","revisionTime":"2017-02-14T23:27:04Z"}, + {"path":"github.com/docker/docker/api/types/container","checksumSHA1":"Vso/6NenP1G74lQjvyvzOdfIZ28=","revision":"3dc87714d1bfcaf0620fabec3bfea89620b59337","revisionTime":"2017-02-14T23:27:04Z"}, + {"path":"github.com/docker/docker/api/types/filters","checksumSHA1":"J2OKngfI3vgswudr9PZVUFcRRu0=","revision":"fe9ab0588606a5566d065bc68ae68f3926ddaa72","revisionTime":"2017-02-28T18:28:19Z"}, + {"path":"github.com/docker/docker/api/types/mount","checksumSHA1":"OXsrx4ynzLV+6/6vUeyru0Fprx8=","revision":"3dc87714d1bfcaf0620fabec3bfea89620b59337","revisionTime":"2017-02-14T23:27:04Z"}, + {"path":"github.com/docker/docker/api/types/network","checksumSHA1":"Gskp+nvbVe8Gk1xPLHylZvNmqTg=","revision":"e4d0fe84f9ea88b0e0cfd847412c9f29442cc62d","revisionTime":"2017-11-14T19:25:14Z"}, + {"path":"github.com/docker/docker/api/types/registry","checksumSHA1":"r2vWq7Uc3ExKzMqYgH0b4AKjLKY=","revision":"e4d0fe84f9ea88b0e0cfd847412c9f29442cc62d","revisionTime":"2017-11-14T19:25:14Z"}, + {"path":"github.com/docker/docker/api/types/strslice","checksumSHA1":"VTxWyFud/RedrpllGdQonVtGM/A=","revision":"3dc87714d1bfcaf0620fabec3bfea89620b59337","revisionTime":"2017-02-14T23:27:04Z"}, + {"path":"github.com/docker/docker/api/types/swarm","checksumSHA1":"Q0U3queMsCw+rPPztXnRHwAxQEc=","revision":"e4d0fe84f9ea88b0e0cfd847412c9f29442cc62d","revisionTime":"2017-11-14T19:25:14Z"}, + {"path":"github.com/docker/docker/api/types/swarm/runtime","checksumSHA1":"mi8EDCDjtrZEONRXPG7VHJosDwY=","revision":"e4d0fe84f9ea88b0e0cfd847412c9f29442cc62d","revisionTime":"2017-11-14T19:25:14Z"}, + {"path":"github.com/docker/docker/api/types/versions","checksumSHA1":"uDPQ3nHsrvGQc9tg/J9OSC4N5dQ=","revision":"fe9ab0588606a5566d065bc68ae68f3926ddaa72","revisionTime":"2017-02-28T18:28:19Z"}, + {"path":"github.com/docker/docker/cli/config/configfile","checksumSHA1":"l8Re54Tp3x8kYWPoD2jXBOWloSY=","revision":"518945b6bd30dc535addf2aac9d5eeefbfc5e523","revisionTime":"2017-01-10T19:35:11Z"}, + {"path":"github.com/docker/docker/opts","checksumSHA1":"mswe275heIklTKj7mPTnVzAFoMk=","revision":"da39e9a4f920a15683dd0f23923c302d4db6eed5","revisionTime":"2016-05-28T08:11:04Z"}, + {"path":"github.com/docker/docker/pkg/archive","checksumSHA1":"OShlvanyvyee8I0/kdmLuOEOF5w=","revision":"da39e9a4f920a15683dd0f23923c302d4db6eed5","revisionTime":"2016-05-28T08:11:04Z"}, + {"path":"github.com/docker/docker/pkg/fileutils","checksumSHA1":"EONnM7E8xCzJCAbX1rhayK6knwM=","revision":"da39e9a4f920a15683dd0f23923c302d4db6eed5","revisionTime":"2016-05-28T08:11:04Z"}, + {"path":"github.com/docker/docker/pkg/homedir","checksumSHA1":"p6Ud4Yf1ywWy20YxXF1RU4yhTio=","revision":"da39e9a4f920a15683dd0f23923c302d4db6eed5","revisionTime":"2016-05-28T08:11:04Z"}, + {"path":"github.com/docker/docker/pkg/idtools","checksumSHA1":"iP5slJJPRZUm0rfdII8OiATAACA=","revision":"02caa73df411debed164f520a6a1304778f8b88c","revisionTime":"2016-05-28T10:48:36Z"}, + {"path":"github.com/docker/docker/pkg/idtools","checksumSHA1":"iP5slJJPRZUm0rfdII8OiATAACA=","revision":"52debcd58ac91bf68503ce60561536911b74ff05","revisionTime":"2016-05-20T15:17:10Z"}, + {"path":"github.com/docker/docker/pkg/ioutils","checksumSHA1":"tdhmIGUaoOMEDymMC23qTS7bt0g=","revision":"52debcd58ac91bf68503ce60561536911b74ff05","revisionTime":"2016-05-20T15:17:10Z"}, + {"path":"github.com/docker/docker/pkg/ioutils","checksumSHA1":"tdhmIGUaoOMEDymMC23qTS7bt0g=","revision":"da39e9a4f920a15683dd0f23923c302d4db6eed5","revisionTime":"2016-05-28T08:11:04Z"}, + {"path":"github.com/docker/docker/pkg/jsonlog","checksumSHA1":"BlFSSK7zUjPzPuxkLmM/0wpvku8=","revision":"3dc87714d1bfcaf0620fabec3bfea89620b59337","revisionTime":"2017-02-14T23:27:04Z"}, + {"path":"github.com/docker/docker/pkg/jsonmessage","checksumSHA1":"IpcW+FAHu0DmbvbhqXuP42f4FCo=","revision":"3dc87714d1bfcaf0620fabec3bfea89620b59337","revisionTime":"2017-02-14T23:27:04Z"}, + {"path":"github.com/docker/docker/pkg/longpath","checksumSHA1":"ndnAFCfsGC3upNQ6jAEwzxcurww=","revision":"da39e9a4f920a15683dd0f23923c302d4db6eed5","revisionTime":"2016-05-28T08:11:04Z"}, + {"path":"github.com/docker/docker/pkg/pools","checksumSHA1":"rArZ5mYIe9I1L5PRQOJu8BwafFw=","revision":"52debcd58ac91bf68503ce60561536911b74ff05","revisionTime":"2016-05-20T15:17:10Z"}, + {"path":"github.com/docker/docker/pkg/pools","checksumSHA1":"rArZ5mYIe9I1L5PRQOJu8BwafFw=","revision":"da39e9a4f920a15683dd0f23923c302d4db6eed5","revisionTime":"2016-05-28T08:11:04Z"}, + {"path":"github.com/docker/docker/pkg/promise","checksumSHA1":"txf3EORYff4hO6PEvwBm2lyh1MU=","revision":"52debcd58ac91bf68503ce60561536911b74ff05","revisionTime":"2016-05-20T15:17:10Z"}, + {"path":"github.com/docker/docker/pkg/promise","checksumSHA1":"txf3EORYff4hO6PEvwBm2lyh1MU=","revision":"da39e9a4f920a15683dd0f23923c302d4db6eed5","revisionTime":"2016-05-28T08:11:04Z"}, + {"path":"github.com/docker/docker/pkg/random","checksumSHA1":"lThih54jzz9A4zHKEFb9SIV3Ed0=","revision":"518945b6bd30dc535addf2aac9d5eeefbfc5e523","revisionTime":"2017-01-10T19:35:11Z"}, + {"path":"github.com/docker/docker/pkg/stdcopy","checksumSHA1":"YDYbS5U2mDwfcOUJ6M09cP6Bubg=","revision":"da39e9a4f920a15683dd0f23923c302d4db6eed5","revisionTime":"2016-05-28T08:11:04Z"}, + {"path":"github.com/docker/docker/pkg/stringid","checksumSHA1":"YGZBluVbky9i5i+BgM+RTc0NEtc=","revision":"518945b6bd30dc535addf2aac9d5eeefbfc5e523","revisionTime":"2017-01-10T19:35:11Z"}, + {"path":"github.com/docker/docker/pkg/system","checksumSHA1":"NGqzajRG0Vri8ConQuHY3cCs1RA=","revision":"fe9ab0588606a5566d065bc68ae68f3926ddaa72","revisionTime":"2017-02-28T18:28:19Z"}, + {"path":"github.com/docker/docker/pkg/system","checksumSHA1":"jtruj9m4YJtPaXqUZ5PXdgFQjRA=","revision":"47cd4bf526723100bdbbd5a6bb983cdd668882e9","revisionTime":"2017-03-13T17:42:22Z"}, + {"path":"github.com/docker/docker/pkg/term","checksumSHA1":"Nfp/0W+HK8ZEgklbSWmjJGXTJew=","revision":"3dc87714d1bfcaf0620fabec3bfea89620b59337","revisionTime":"2017-02-14T23:27:04Z"}, + {"path":"github.com/docker/docker/pkg/term/windows","checksumSHA1":"EMjTiUTHNxqSsmdMB1V29hRvJbQ=","revision":"3dc87714d1bfcaf0620fabec3bfea89620b59337","revisionTime":"2017-02-14T23:27:04Z"}, + {"path":"github.com/docker/docker/reference","checksumSHA1":"bASLGmo2Ae+10Pc2zVCpXbBcPag=","revision":"518945b6bd30dc535addf2aac9d5eeefbfc5e523","revisionTime":"2017-01-10T19:35:11Z"}, + {"path":"github.com/docker/docker/registry","checksumSHA1":"AlBQLsNEpPJIe7OxsqN1P3BKi/M=","revision":"518945b6bd30dc535addf2aac9d5eeefbfc5e523","revisionTime":"2017-01-10T19:35:11Z"}, + {"path":"github.com/docker/go-connections/nat","checksumSHA1":"JbiWTzH699Sqz25XmDlsARpMN9w=","revision":"7da10c8c50cad14494ec818dcdfb6506265c0086","revisionTime":"2017-02-03T23:56:24Z"}, + {"path":"github.com/docker/go-units","comment":"v0.1.0-23-g5d2041e","revision":"5d2041e26a699eaca682e2ea41c8f891e1060444"}, + {"path":"github.com/dustin/go-humanize","revision":"8929fe90cee4b2cb9deb468b51fb34eba64d1bf0"}, + {"path":"github.com/elazarl/go-bindata-assetfs","checksumSHA1":"7DxViusFRJ7UPH0jZqYatwDrOkY=","revision":"30f82fa23fd844bd5bb1e5f216db87fd77b5eb43","revisionTime":"2017-02-27T21:27:28Z"}, + {"path":"github.com/fatih/structs","checksumSHA1":"QBkOnLnM6zZ158NJSVLqoE4V6fI=","revision":"14f46232cd7bc732dc67313a9e4d3d210e082587","revisionTime":"2016-07-19T20:45:16Z"}, + {"path":"github.com/fsouza/go-dockerclient","checksumSHA1":"E+wmSQrc/BXzgITrbNAbUzljoiM=","revision":"5ffdfff51ec0eba739b1039e65ba3625ef25f7c0","revisionTime":"2017-11-23T03:37:03Z"}, + {"path":"github.com/go-ini/ini","comment":"v1.8.5-2-g6ec4abd","revision":"6ec4abd8f8d587536da56f730858f0e27aeb4126"}, + {"path":"github.com/go-ole/go-ole","checksumSHA1":"IvHj/4iR2nYa/S3cB2GXoyDG/xQ=","comment":"v1.2.0-4-g5005588","revision":"085abb85892dc1949567b726dff00fa226c60c45","revisionTime":"2017-07-12T17:44:59Z"}, + {"path":"github.com/go-ole/go-ole/oleutil","comment":"v1.2.0-4-g5005588","revision":"50055884d646dd9434f16bbb5c9801749b9bafe4"}, + {"path":"github.com/gogo/protobuf/proto","checksumSHA1":"I460dM/HmGE9DWimQvd1hJkYosU=","revision":"616a82ed12d78d24d4839363e8f3c5d3f20627cf","revisionTime":"2017-11-09T18:15:19Z"}, + {"path":"github.com/golang/protobuf/proto","checksumSHA1":"dUAIotNrGq6Tvz/z6ktSxSHW7Rc=","revision":"0a4f71a498b7c4812f64969510bcb4eca251e33a","revisionTime":"2017-07-12T04:22:13Z"}, + {"path":"github.com/golang/protobuf/ptypes/any","checksumSHA1":"Z4RIWIXH05QItZqVbmbONO9mWig=","revision":"0a4f71a498b7c4812f64969510bcb4eca251e33a","revisionTime":"2017-07-12T04:22:13Z"}, + {"path":"github.com/golang/snappy","checksumSHA1":"W+E/2xXcE1GmJ0Qb784ald0Fn6I=","revision":"d9eb7a3d35ec988b8585d4a0068e462c27d28380","revisionTime":"2016-05-29T05:00:41Z"}, + {"path":"github.com/google/go-cmp/cmp","checksumSHA1":"+suAHHPBmbdZf/HusugaL4/H+NE=","revision":"d5735f74713c51f7450a43d0a98d41ce2c1db3cb","revisionTime":"2017-09-01T21:42:48Z"}, + {"path":"github.com/google/go-cmp/cmp/cmpopts","checksumSHA1":"VmBLfV9TChrjNu8Z96wZkYie1aI=","revision":"d5735f74713c51f7450a43d0a98d41ce2c1db3cb","revisionTime":"2017-09-01T21:42:48Z"}, + {"path":"github.com/google/go-cmp/cmp/internal/diff","checksumSHA1":"eTwchtMX+RMJUvle2wt295P2h10=","revision":"d5735f74713c51f7450a43d0a98d41ce2c1db3cb","revisionTime":"2017-09-01T21:42:48Z"}, + {"path":"github.com/google/go-cmp/cmp/internal/function","checksumSHA1":"kYtvRhMjM0X4bvEjR3pqEHLw1qo=","revision":"d5735f74713c51f7450a43d0a98d41ce2c1db3cb","revisionTime":"2017-09-01T21:42:48Z"}, + {"path":"github.com/google/go-cmp/cmp/internal/value","checksumSHA1":"f+mgZLvc4VITtMmBv0bmew4rL2Y=","revision":"d5735f74713c51f7450a43d0a98d41ce2c1db3cb","revisionTime":"2017-09-01T21:42:48Z"}, + {"path":"github.com/gorhill/cronexpr","checksumSHA1":"m8B3L3qJ3tFfP6BI9pIFr9oal3w=","comment":"1.0.0","origin":"github.com/dadgar/cronexpr","revision":"675cac9b2d182dccb5ba8d5f8a0d5988df8a4394","revisionTime":"2017-09-15T18:30:32Z"}, + {"path":"github.com/gorhill/cronexpr/cronexpr","comment":"1.0.0","revision":"a557574d6c024ed6e36acc8b610f5f211c91568a"}, + {"path":"github.com/hashicorp/consul-template/child","checksumSHA1":"Nu2j1GusM7ZH0uYrGzqr1K7yH7I=","revision":"26d029ad37335b3827a9fde5569b2c5e10dcac8f","revisionTime":"2017-10-31T14:25:17Z"}, + {"path":"github.com/hashicorp/consul-template/config","checksumSHA1":"qKAxyhYnUpKzZ5KpA6aOiIHHqqg=","revision":"26d029ad37335b3827a9fde5569b2c5e10dcac8f","revisionTime":"2017-10-31T14:25:17Z"}, + {"path":"github.com/hashicorp/consul-template/dependency","checksumSHA1":"gZUb/+jEn+2hdO/lmQSKcYuOB/o=","revision":"26d029ad37335b3827a9fde5569b2c5e10dcac8f","revisionTime":"2017-10-31T14:25:17Z"}, + {"path":"github.com/hashicorp/consul-template/manager","checksumSHA1":"JVwx9FW1/nxRvg1lEeydBhaf3No=","revision":"26d029ad37335b3827a9fde5569b2c5e10dcac8f","revisionTime":"2017-10-31T14:25:17Z"}, + {"path":"github.com/hashicorp/consul-template/signals","checksumSHA1":"YSEUV/9/k85XciRKu0cngxdjZLE=","revision":"26d029ad37335b3827a9fde5569b2c5e10dcac8f","revisionTime":"2017-10-31T14:25:17Z"}, + {"path":"github.com/hashicorp/consul-template/template","checksumSHA1":"N9qobVzScLbTEnGE7MgFnnTbGBw=","revision":"26d029ad37335b3827a9fde5569b2c5e10dcac8f","revisionTime":"2017-10-31T14:25:17Z"}, + {"path":"github.com/hashicorp/consul-template/version","checksumSHA1":"NB5+D4AuCNV9Bsqh3YFdPi4AJ6U=","revision":"26d029ad37335b3827a9fde5569b2c5e10dcac8f","revisionTime":"2017-10-31T14:25:17Z"}, + {"path":"github.com/hashicorp/consul-template/watch","checksumSHA1":"b4+Y+02pY2Y5620F9ALzKg8Zmdw=","revision":"26d029ad37335b3827a9fde5569b2c5e10dcac8f","revisionTime":"2017-10-31T14:25:17Z"}, + {"path":"github.com/hashicorp/consul/api","checksumSHA1":"XLfcIX2qpRr0o26aFMjCOzvw6jo=","revision":"51ea240df8476e02215d53fbfad5838bf0d44d21","revisionTime":"2017-10-16T16:22:40Z"}, + {"path":"github.com/hashicorp/consul/lib","checksumSHA1":"HGljdtVaqi/e3DgIHymLRLfPYhw=","revision":"bcafded4e60982d0b71e730f0b8564d73cb1d715","revisionTime":"2017-10-31T16:39:15Z"}, + {"path":"github.com/hashicorp/consul/lib/freeport","checksumSHA1":"hDJiPli3EEGJE4vAezMi05oOC7o=","revision":"bcafded4e60982d0b71e730f0b8564d73cb1d715","revisionTime":"2017-10-31T16:39:15Z"}, + {"path":"github.com/hashicorp/consul/test/porter","checksumSHA1":"5XjgqE4UIfwXvkq5VssGNc7uPhQ=","revision":"ad9425ca6353b8afcfebd19130a8cf768f7eac30","revisionTime":"2017-10-21T00:05:25Z"}, + {"path":"github.com/hashicorp/consul/testutil","checksumSHA1":"+go9ycmyfF4b0W174gc7ej5mnE8=","revision":"350932161d6745836c1b2f39849bddb0f9fb52fd","revisionTime":"2017-10-20T23:49:17Z"}, + {"path":"github.com/hashicorp/consul/testutil/retry","checksumSHA1":"J8TTDc84MvAyXE/FrfgS+xc/b6s=","revision":"350932161d6745836c1b2f39849bddb0f9fb52fd","revisionTime":"2017-10-20T23:49:17Z"}, + {"path":"github.com/hashicorp/errwrap","revision":"7554cd9344cec97297fa6649b055a8c98c2a1e55"}, + {"path":"github.com/hashicorp/go-checkpoint","checksumSHA1":"D267IUMW2rcb+vNe3QU+xhfSrgY=","revision":"1545e56e46dec3bba264e41fde2c1e2aa65b5dd4","revisionTime":"2017-10-09T17:35:28Z"}, + {"path":"github.com/hashicorp/go-cleanhttp","checksumSHA1":"6ihdHMkDfFx/rJ1A36com2F6bQk=","revision":"a45970658e51fea2c41445ff0f7e07106d007617","revisionTime":"2017-02-11T00:33:01Z"}, + {"path":"github.com/hashicorp/go-envparse","checksumSHA1":"mB5JzxaVCPIvbwADY0acdnkhmT8=","revision":"7953113a2936d8e5f7e2a0a3dd8089565c39ef21","revisionTime":"2017-06-02T22:43:19Z"}, + {"path":"github.com/hashicorp/go-getter","checksumSHA1":"wCKbbnwvVEoKAE5TWunloLhErm4=","revision":"994f50a6f071b07cfbea9eca9618c9674091ca51","revisionTime":"2017-12-04T19:28:26Z"}, + {"path":"github.com/hashicorp/go-getter/helper/url","checksumSHA1":"9J+kDr29yDrwsdu2ULzewmqGjpA=","revision":"994f50a6f071b07cfbea9eca9618c9674091ca51","revisionTime":"2017-12-04T19:28:26Z"}, + {"path":"github.com/hashicorp/go-hclog","checksumSHA1":"miVF4/7JP0lRwZvFJGKwZWk7aAQ=","revision":"b4e5765d1e5f00a0550911084f45f8214b5b83b9","revisionTime":"2017-07-16T17:45:23Z"}, + {"path":"github.com/hashicorp/go-immutable-radix","checksumSHA1":"Cas2nprG6pWzf05A2F/OlnjUu2Y=","revision":"8aac2701530899b64bdea735a1de8da899815220","revisionTime":"2017-07-25T22:12:15Z"}, + {"path":"github.com/hashicorp/go-memdb","checksumSHA1":"FMAvwDar2bQyYAW4XMFhAt0J5xA=","revision":"20ff6434c1cc49b80963d45bf5c6aa89c78d8d57","revisionTime":"2017-08-31T20:15:40Z"}, + {"path":"github.com/hashicorp/go-msgpack/codec","revision":"fa3f63826f7c23912c15263591e65d54d080b458"}, + {"path":"github.com/hashicorp/go-multierror","revision":"d30f09973e19c1dfcd120b2d9c4f168e68d6b5d5"}, + {"path":"github.com/hashicorp/go-plugin","checksumSHA1":"R6me0jVmcT/OPo80Fe0qo5fRwHc=","revision":"3e6d191694b5a3a2b99755f31b47fa209e4bcd09","revisionTime":"2017-08-28T02:45:49Z"}, + {"path":"github.com/hashicorp/go-retryablehttp","checksumSHA1":"ErJHGU6AVPZM9yoY/xV11TwSjQs=","revision":"6e85be8fee1dcaa02c0eaaac2df5a8fbecf94145","revisionTime":"2016-09-30T03:51:02Z"}, + {"path":"github.com/hashicorp/go-rootcerts","checksumSHA1":"A1PcINvF3UiwHRKn8UcgARgvGRs=","revision":"6bb64b370b90e7ef1fa532be9e591a81c3493e00","revisionTime":"2016-05-03T14:34:40Z"}, + {"path":"github.com/hashicorp/go-sockaddr","checksumSHA1":"X2tSlVe532du67MEIU1KHoCT68k=","revision":"e12d9401a74f025fe672cd1a84b2081c773990d3","revisionTime":"2017-06-22T20:44:38Z"}, + {"path":"github.com/hashicorp/go-sockaddr/template","checksumSHA1":"mIUCMmRHslN2bxQZ0uObMnXxk9E=","revision":"e12d9401a74f025fe672cd1a84b2081c773990d3","revisionTime":"2017-06-22T20:44:38Z"}, + {"path":"github.com/hashicorp/go-syslog","revision":"42a2b573b664dbf281bd48c3cc12c086b17a39ba"}, + {"path":"github.com/hashicorp/go-uuid","checksumSHA1":"mAkPa/RLuIwN53GbwIEMATexams=","revision":"64130c7a86d732268a38cb04cfbaf0cc987fda98","revisionTime":"2016-07-17T02:21:40Z"}, + {"path":"github.com/hashicorp/go-version","checksumSHA1":"tUGxc7rfX0cmhOOUDhMuAZ9rWsA=","revision":"03c5bf6be031b6dd45afec16b1cf94fc8938bc77","revisionTime":"2017-02-02T08:07:59Z"}, + {"path":"github.com/hashicorp/golang-lru","checksumSHA1":"d9PxF1XQGLMJZRct2R8qVM/eYlE=","revision":"a0d98a5f288019575c6d1f4bb1573fef2d1fcdc4","revisionTime":"2016-02-07T21:47:19Z"}, + {"path":"github.com/hashicorp/golang-lru/simplelru","revision":"a0d98a5f288019575c6d1f4bb1573fef2d1fcdc4"}, + {"path":"github.com/hashicorp/hcl","checksumSHA1":"8OPDk+bKyRGJoKcS4QNw9F7dpE8=","revision":"6e968a3fcdcbab092f5307fd0d85479d5af1e4dc","revisionTime":"2016-11-01T18:00:25Z"}, + {"path":"github.com/hashicorp/hcl/hcl/ast","checksumSHA1":"XQmjDva9JCGGkIecOgwtBEMCJhU=","revision":"6e968a3fcdcbab092f5307fd0d85479d5af1e4dc","revisionTime":"2016-11-01T18:00:25Z"}, + {"path":"github.com/hashicorp/hcl/hcl/parser","checksumSHA1":"croNloscHsjX87X+4/cKOURf1EY=","revision":"6e968a3fcdcbab092f5307fd0d85479d5af1e4dc","revisionTime":"2016-11-01T18:00:25Z"}, + {"path":"github.com/hashicorp/hcl/hcl/scanner","checksumSHA1":"lgR7PSAZ0RtvAc9OCtCnNsF/x8g=","revision":"6e968a3fcdcbab092f5307fd0d85479d5af1e4dc","revisionTime":"2016-11-01T18:00:25Z"}, + {"path":"github.com/hashicorp/hcl/hcl/strconv","checksumSHA1":"JlZmnzqdmFFyb1+2afLyR3BOE/8=","revision":"6e968a3fcdcbab092f5307fd0d85479d5af1e4dc","revisionTime":"2016-11-01T18:00:25Z"}, + {"path":"github.com/hashicorp/hcl/hcl/token","checksumSHA1":"c6yprzj06ASwCo18TtbbNNBHljA=","revision":"6e968a3fcdcbab092f5307fd0d85479d5af1e4dc","revisionTime":"2016-11-01T18:00:25Z"}, + {"path":"github.com/hashicorp/hcl/json/parser","checksumSHA1":"138aCV5n8n7tkGYMsMVQQnnLq+0=","revision":"6e968a3fcdcbab092f5307fd0d85479d5af1e4dc","revisionTime":"2016-11-01T18:00:25Z"}, + {"path":"github.com/hashicorp/hcl/json/scanner","checksumSHA1":"YdvFsNOMSWMLnY6fcliWQa0O5Fw=","revision":"6e968a3fcdcbab092f5307fd0d85479d5af1e4dc","revisionTime":"2016-11-01T18:00:25Z"}, + {"path":"github.com/hashicorp/hcl/json/token","checksumSHA1":"fNlXQCQEnb+B3k5UDL/r15xtSJY=","revision":"6e968a3fcdcbab092f5307fd0d85479d5af1e4dc","revisionTime":"2016-11-01T18:00:25Z"}, + {"path":"github.com/hashicorp/logutils","revision":"0dc08b1671f34c4250ce212759ebd880f743d883"}, + {"path":"github.com/hashicorp/memberlist","checksumSHA1":"1zk7IeGClUqBo+Phsx89p7fQ/rQ=","revision":"23ad4b7d7b38496cd64c241dfd4c60b7794c254a","revisionTime":"2017-02-08T21:15:06Z"}, + {"path":"github.com/hashicorp/net-rpc-msgpackrpc","revision":"a14192a58a694c123d8fe5481d4a4727d6ae82f3"}, + {"path":"github.com/hashicorp/raft","checksumSHA1":"ecpaHOImbL/NaivWrUDUUe5461E=","revision":"3a6f3bdfe4fc69e300c6d122b1a92051af6f0b95","revisionTime":"2017-08-07T22:22:24Z"}, + {"path":"github.com/hashicorp/raft-boltdb","checksumSHA1":"QAxukkv54/iIvLfsUP6IK4R0m/A=","revision":"d1e82c1ec3f15ee991f7cc7ffd5b67ff6f5bbaee","revisionTime":"2015-02-01T20:08:39Z"}, + {"path":"github.com/hashicorp/serf/coordinate","checksumSHA1":"/oss17GO4hXGM7QnUdI3VzcAHzA=","revision":"bbeddf0b3ab3072a60525afbd6b6f47d33839eee","revisionTime":"2017-07-14T18:26:01Z"}, + {"path":"github.com/hashicorp/serf/serf","checksumSHA1":"pvLOzocYsZtxuJ9pREHRTxYnoa4=","revision":"bbeddf0b3ab3072a60525afbd6b6f47d33839eee","revisionTime":"2017-07-14T18:26:01Z"}, + {"path":"github.com/hashicorp/vault","checksumSHA1":"eGzvBRMFD6ZB3A6uO750np7Om/E=","revision":"182ba68a9589d4cef95234134aaa498a686e3de3","revisionTime":"2016-08-21T23:40:57Z"}, + {"path":"github.com/hashicorp/vault/api","checksumSHA1":"hLIXn9iQhPcjY+/G64j3mIlLlK8=","revision":"0c3e14f047aede0a70256e1e8b321610910b246e","revisionTime":"2017-08-01T15:50:41Z"}, + {"path":"github.com/hashicorp/vault/helper/compressutil","checksumSHA1":"au+CDkddC4sVFV15UaPiI7FvSw0=","revision":"1fd46cbcb10569bd205c3f662e7a4f16f1e69056","revisionTime":"2017-08-11T01:28:18Z"}, + {"path":"github.com/hashicorp/vault/helper/jsonutil","checksumSHA1":"yUiSTPf0QUuL2r/81sjuytqBoeQ=","revision":"0c3e14f047aede0a70256e1e8b321610910b246e","revisionTime":"2017-08-01T15:50:41Z"}, + {"path":"github.com/hashicorp/vault/helper/parseutil","checksumSHA1":"GGveKvOwScWGZAAnupzpyw+0Jko=","revision":"1fd46cbcb10569bd205c3f662e7a4f16f1e69056","revisionTime":"2017-08-11T01:28:18Z"}, + {"path":"github.com/hashicorp/yamux","checksumSHA1":"VMaF3Q7RIrRzvbnPbqxuSLryOvc=","revision":"badf81fca035b8ebac61b5ab83330b72541056f4","revisionTime":"2016-06-09T13:59:02Z"}, + {"path":"github.com/hpcloud/tail/util","checksumSHA1":"0xM336Lb25URO/1W1/CtGoRygVU=","revision":"37f4271387456dd1bf82ab1ad9229f060cc45386","revisionTime":"2017-08-14T16:06:53Z"}, + {"path":"github.com/hpcloud/tail/watch","checksumSHA1":"TP4OAv5JMtzj2TB6OQBKqauaKDc=","revision":"37f4271387456dd1bf82ab1ad9229f060cc45386","revisionTime":"2017-08-14T16:06:53Z"}, + {"path":"github.com/jmespath/go-jmespath","comment":"0.2.2-2-gc01cf91","revision":"c01cf91b011868172fdcd9f41838e80c9d716264"}, + {"path":"github.com/kardianos/osext","revision":"29ae4ffbc9a6fe9fb2bc5029050ce6996ea1d3bc"}, + {"path":"github.com/kr/pretty","checksumSHA1":"eOXF2PEvYLMeD8DSzLZJWbjYzco=","revision":"cfb55aafdaf3ec08f0db22699ab822c50091b1c4","revisionTime":"2016-08-23T17:07:15Z"}, + {"path":"github.com/kr/text","checksumSHA1":"uulQHQ7IsRKqDudBC8Go9J0gtAc=","revision":"7cafcd837844e784b526369c9bce262804aebc60","revisionTime":"2016-05-04T02:26:26Z"}, + {"path":"github.com/mattn/go-isatty","checksumSHA1":"trzmsZQDCc13zk/6qANox7Z/KCg=","revision":"fc9e8d8ef48496124e79ae0df75490096eccf6fe","revisionTime":"2017-03-22T23:44:13Z"}, + {"path":"github.com/mattn/go-shellwords","checksumSHA1":"ajImwVZHzsI+aNwsgzCSFSbmJqs=","revision":"f4e566c536cf69158e808ec28ef4182a37fdc981","revisionTime":"2015-03-21T17:42:21Z"}, + {"path":"github.com/matttproud/golang_protobuf_extensions/pbutil","checksumSHA1":"bKMZjd2wPw13VwoE7mBeSv5djFA=","revision":"c12348ce28de40eed0136aa2b644d0ee0650e56c","revisionTime":"2016-04-24T11:30:07Z"}, + {"path":"github.com/miekg/dns","revision":"7e024ce8ce18b21b475ac6baf8fa3c42536bf2fa"}, + {"path":"github.com/mitchellh/cli","checksumSHA1":"UIqCj7qI0hhIMpAhS9YYqs2jD48=","revision":"65fcae5817c8600da98ada9d7edf26dd1a84837b","revisionTime":"2017-09-08T18:10:43Z"}, + {"path":"github.com/mitchellh/colorstring","checksumSHA1":"ttEN1Aupb7xpPMkQLqb3tzLFdXs=","revision":"8631ce90f28644f54aeedcb3e389a85174e067d1","revisionTime":"2015-09-17T21:48:07Z"}, + {"path":"github.com/mitchellh/copystructure","checksumSHA1":"+p4JY4wmFQAppCdlrJ8Kxybmht8=","revision":"d23ffcb85de31694d6ccaa23ccb4a03e55c1303f","revisionTime":"2017-05-25T01:39:02Z"}, + {"path":"github.com/mitchellh/go-homedir","checksumSHA1":"AXacfEchaUqT5RGmPmMXsOWRhv8=","revision":"756f7b183b7ab78acdbbee5c7f392838ed459dda","revisionTime":"2016-06-21T17:42:43Z"}, + {"path":"github.com/mitchellh/go-ps","checksumSHA1":"DcYIZnMiq/Tj22/ge9os3NwOhs4=","revision":"4fdf99ab29366514c69ccccddab5dc58b8d84062","revisionTime":"2017-03-09T13:30:38Z"}, + {"path":"github.com/mitchellh/go-testing-interface","checksumSHA1":"bDdhmDk8q6utWrccBhEOa6IoGkE=","revision":"a61a99592b77c9ba629d254a693acffaeb4b7e28","revisionTime":"2017-10-04T22:19:16Z"}, + {"path":"github.com/mitchellh/hashstructure","revision":"1ef5c71b025aef149d12346356ac5973992860bc"}, + {"path":"github.com/mitchellh/mapstructure","revision":"281073eb9eb092240d33ef253c404f1cca550309"}, + {"path":"github.com/mitchellh/reflectwalk","checksumSHA1":"KqsMqI+Y+3EFYPhyzafpIneaVCM=","revision":"8d802ff4ae93611b807597f639c19f76074df5c6","revisionTime":"2017-05-08T17:38:06Z"}, + {"path":"github.com/opencontainers/go-digest","checksumSHA1":"NTperEHVh1uBqfTy9+oKceN4tKI=","revision":"21dfd564fd89c944783d00d069f33e3e7123c448","revisionTime":"2017-01-11T18:16:59Z"}, + {"path":"github.com/opencontainers/image-spec/specs-go","checksumSHA1":"ZGlIwSRjdLYCUII7JLE++N4w7Xc=","revision":"89b51c794e9113108a2914e38e66c826a649f2b5","revisionTime":"2017-11-03T11:36:04Z"}, + {"path":"github.com/opencontainers/image-spec/specs-go/v1","checksumSHA1":"jdbXRRzeu0njLE9/nCEZG+Yg/Jk=","revision":"89b51c794e9113108a2914e38e66c826a649f2b5","revisionTime":"2017-11-03T11:36:04Z"}, + {"path":"github.com/opencontainers/runc/libcontainer/cgroups","checksumSHA1":"UPfYFznGeLEloCkGG8KKgsKjtPU=","comment":"v0.0.9-108-g89ab7f2","revision":"89ab7f2ccc1e45ddf6485eaa802c35dcf321dfc8","revisionTime":"2016-03-31T09:02:02Z"}, + {"path":"github.com/opencontainers/runc/libcontainer/cgroups/fs","checksumSHA1":"xIrNApwB9+yQBhu2p6bt7blV+x4=","comment":"v0.0.9-108-g89ab7f2","revision":"89ab7f2ccc1e45ddf6485eaa802c35dcf321dfc8","revisionTime":"2016-03-31T09:02:02Z"}, + {"path":"github.com/opencontainers/runc/libcontainer/configs","checksumSHA1":"CdhRZZmDeY+t3PN4Qpi1ojy50pE=","comment":"v0.0.9-108-g89ab7f2","revision":"89ab7f2ccc1e45ddf6485eaa802c35dcf321dfc8","revisionTime":"2016-03-31T09:02:02Z"}, + {"path":"github.com/opencontainers/runc/libcontainer/system","checksumSHA1":"xo2LfoL27cGF6cChWvew2KfhpNI=","comment":"v0.0.9-108-g89ab7f2","revision":"89ab7f2ccc1e45ddf6485eaa802c35dcf321dfc8","revisionTime":"2016-03-31T09:02:02Z"}, + {"path":"github.com/opencontainers/runc/libcontainer/user","checksumSHA1":"3AoPMXlmVq2+iWMpsdJZkcUKHB8=","revision":"89ab7f2ccc1e45ddf6485eaa802c35dcf321dfc8","revisionTime":"2016-03-31T09:02:02Z"}, + {"path":"github.com/opencontainers/runc/libcontainer/utils","checksumSHA1":"PCfoPliJrUhzLP4arNs2KjEb2Bc=","comment":"v0.0.9-108-g89ab7f2","revision":"89ab7f2ccc1e45ddf6485eaa802c35dcf321dfc8","revisionTime":"2016-03-31T09:02:02Z"}, + {"path":"github.com/pkg/errors","checksumSHA1":"ynJSWoF6v+3zMnh9R0QmmG6iGV8=","revision":"248dadf4e9068a0b3e79f02ed0a610d935de5302","revisionTime":"2016-10-29T09:36:37Z"}, + {"path":"github.com/pmezard/go-difflib/difflib","checksumSHA1":"LuFv4/jlrmFNnDb/5SCSEPAM9vU=","revision":"792786c7400a136282c1664665ae0a8db921c6c2","revisionTime":"2016-01-10T10:55:54Z"}, + {"path":"github.com/posener/complete","checksumSHA1":"rTNABfFJ9wtLQRH8uYNkEZGQOrY=","revision":"9f41f7636a724791a3b8b1d35e84caa1124f0d3c","revisionTime":"2017-08-29T17:11:12Z"}, + {"path":"github.com/posener/complete/cmd","checksumSHA1":"NB7uVS0/BJDmNu68vPAlbrq4TME=","revision":"9f41f7636a724791a3b8b1d35e84caa1124f0d3c","revisionTime":"2017-08-29T17:11:12Z"}, + {"path":"github.com/posener/complete/cmd/install","checksumSHA1":"gSX86Xl0w9hvtntdT8h23DZtSag=","revision":"9f41f7636a724791a3b8b1d35e84caa1124f0d3c","revisionTime":"2017-08-29T17:11:12Z"}, + {"path":"github.com/posener/complete/match","checksumSHA1":"DMo94FwJAm9ZCYCiYdJU2+bh4no=","revision":"9f41f7636a724791a3b8b1d35e84caa1124f0d3c","revisionTime":"2017-08-29T17:11:12Z"}, + {"path":"github.com/prometheus/client_golang/prometheus","checksumSHA1":"+5YXakGoZBEMrHp6h64TC5GSFfg=","revision":"671c87b04728565380d95c621edc687bfa00664c","revisionTime":"2017-09-07T15:06:25Z"}, + {"path":"github.com/prometheus/client_golang/prometheus/promhttp","checksumSHA1":"wsAkYlRRUNx+OAuUOIqdjO7dICM=","revision":"671c87b04728565380d95c621edc687bfa00664c","revisionTime":"2017-09-07T15:06:25Z"}, + {"path":"github.com/prometheus/client_model/go","checksumSHA1":"DvwvOlPNAgRntBzt3b3OSRMS2N4=","revision":"6f3806018612930941127f2a7c6c453ba2c527d2","revisionTime":"2017-02-16T18:52:47Z"}, + {"path":"github.com/prometheus/common/expfmt","checksumSHA1":"xfnn0THnqNwjwimeTClsxahYrIo=","revision":"2f17f4a9d485bf34b4bfaccc273805040e4f86c8","revisionTime":"2017-09-08T16:18:22Z"}, + {"path":"github.com/prometheus/common/internal/bitbucket.org/ww/goautoneg","checksumSHA1":"GWlM3d2vPYyNATtTFgftS10/A9w=","revision":"2f17f4a9d485bf34b4bfaccc273805040e4f86c8","revisionTime":"2017-09-08T16:18:22Z"}, + {"path":"github.com/prometheus/common/model","checksumSHA1":"3VoqH7TFfzA6Ds0zFzIbKCUvBmw=","revision":"2f17f4a9d485bf34b4bfaccc273805040e4f86c8","revisionTime":"2017-09-08T16:18:22Z"}, + {"path":"github.com/prometheus/procfs","checksumSHA1":"ihxJIjxtbEYdQKwA0D0nRipj95I=","revision":"e645f4e5aaa8506fc71d6edbc5c4ff02c04c46f2","revisionTime":"2017-07-03T10:12:42Z"}, + {"path":"github.com/prometheus/procfs/xfs","checksumSHA1":"xCiFAAwVTrjsfZT1BIJQ3DgeNCY=","revision":"e645f4e5aaa8506fc71d6edbc5c4ff02c04c46f2","revisionTime":"2017-07-03T10:12:42Z"}, + {"path":"github.com/rkt/rkt/api/v1","checksumSHA1":"ge4Z0w3QJJYTBqJaK3S+a6MCxzQ=","revision":"3abde24bc284b7ded5784c56b4e8184c28999641","revisionTime":"2017-08-01T12:18:56Z","version":"v1.28.1","versionExact":"v1.28.1"}, + {"path":"github.com/rkt/rkt/networking/netinfo","checksumSHA1":"4QqLbh9MmajcN6gCx8Er1voiQys=","revision":"5e83d91aafef5f7a38fef62c045e8b57eeeb8bce","revisionTime":"2017-09-20T12:17:54Z"}, + {"path":"github.com/rs/cors","checksumSHA1":"I778b2sbNN/yjwKSdb3y7hz2yUQ=","revision":"eabcc6af4bbe5ad3a949d36450326a2b0b9894b8","revisionTime":"2017-08-01T07:32:01Z"}, + {"path":"github.com/ryanuber/columnize","checksumSHA1":"M57Rrfc8Z966p+IBtQ91QOcUtcg=","comment":"v2.0.1-8-g983d3a5","revision":"abc90934186a77966e2beeac62ed966aac0561d5","revisionTime":"2017-07-03T20:58:27Z"}, + {"path":"github.com/sean-/seed","checksumSHA1":"tnMZLo/kR9Kqx6GtmWwowtTLlA8=","revision":"e2103e2c35297fb7e17febb81e49b312087a2372","revisionTime":"2017-03-13T16:33:22Z"}, + {"path":"github.com/sethgrid/pester","checksumSHA1":"8Lm8nsMCFz4+gr9EvQLqK8+w+Ks=","revision":"8053687f99650573b28fb75cddf3f295082704d7","revisionTime":"2016-04-29T17:20:22Z"}, + {"path":"github.com/shirou/gopsutil/cpu","checksumSHA1":"T2ThCk35wXAZGh37nrgA07199dA=","revision":"1c211f0807a3436707409fa313599dd8c7a48664","revisionTime":"2017-08-17T03:45:37Z"}, + {"path":"github.com/shirou/gopsutil/disk","checksumSHA1":"T4uyVXPqCS5rj4vYLgv04as0Avw=","revision":"1c211f0807a3436707409fa313599dd8c7a48664","revisionTime":"2017-08-17T03:45:37Z"}, + {"path":"github.com/shirou/gopsutil/host","checksumSHA1":"YBXpUckp1TtJf2mfMLx/bpnm22Q=","revision":"1c211f0807a3436707409fa313599dd8c7a48664","revisionTime":"2017-08-17T03:45:37Z"}, + {"path":"github.com/shirou/gopsutil/internal/common","checksumSHA1":"jUWM0P4G1bHpO9CPS8gcr4rt1t0=","revision":"1c211f0807a3436707409fa313599dd8c7a48664","revisionTime":"2017-08-17T03:45:37Z"}, + {"path":"github.com/shirou/gopsutil/mem","checksumSHA1":"xIAuacHA0LNq1yM5Wd1q4lnbzxU=","revision":"1c211f0807a3436707409fa313599dd8c7a48664","revisionTime":"2017-08-17T03:45:37Z"}, + {"path":"github.com/shirou/gopsutil/net","checksumSHA1":"moxD+mq0dMHnbTeFyeEHK0Iq7i8=","revision":"1c211f0807a3436707409fa313599dd8c7a48664","revisionTime":"2017-08-17T03:45:37Z"}, + {"path":"github.com/shirou/gopsutil/process","checksumSHA1":"C6ybAAUmWz+PQKqJ8byV7Nj5JXQ=","revision":"1c211f0807a3436707409fa313599dd8c7a48664","revisionTime":"2017-08-17T03:45:37Z"}, + {"path":"github.com/shirou/w32","checksumSHA1":"Nve7SpDmjsv6+rhkXAkfg/UQx94=","revision":"bb4de0191aa41b5507caa14b0650cdbddcd9280b","revisionTime":"2016-09-30T03:27:40Z"}, + {"path":"github.com/skratchdot/open-golang/open","checksumSHA1":"h/HMhokbQHTdLUbruoBBTee+NYw=","revision":"75fb7ed4208cf72d323d7d02fd1a5964a7a9073c","revisionTime":"2016-03-02T14:40:31Z"}, + {"path":"github.com/spf13/pflag","checksumSHA1":"Q52Y7t0lEtk/wcDn5q7tS7B+jqs=","revision":"7aff26db30c1be810f9de5038ec5ef96ac41fd7c","revisionTime":"2017-08-24T17:57:12Z"}, + {"path":"github.com/stretchr/objx","checksumSHA1":"K0crHygPTP42i1nLKWphSlvOQJw=","revision":"1a9d0bb9f541897e62256577b352fdbc1fb4fd94","revisionTime":"2015-09-28T12:21:52Z"}, + {"path":"github.com/stretchr/testify/mock","checksumSHA1":"o+jsS/rxceTym4M3reSPfrPxaio=","revision":"f6abca593680b2315d2075e0f5e2a9751e3f431a","revisionTime":"2017-06-01T20:57:54Z"}, + {"path":"github.com/ugorji/go/codec","checksumSHA1":"8G1zvpE4gTtWQRuP/x2HPVDmflo=","revision":"0053ebfd9d0ee06ccefbfe17072021e1d4acebee","revisionTime":"2017-06-20T06:01:02Z"}, + {"path":"github.com/ugorji/go/codec/codecgen","checksumSHA1":"OgParimNuU2CJqr3pcTympeQZUc=","revision":"5efa3251c7f7d05e5d9704a69a984ec9f1386a40","revisionTime":"2017-06-20T10:48:52Z"}, + {"path":"github.com/ulikunitz/xz","checksumSHA1":"z2kAtVle4NFV2OExI85fZoTcsI4=","revision":"0c6b41e72360850ca4f98dc341fd999726ea007f","revisionTime":"2017-06-05T21:53:11Z"}, + {"path":"github.com/ulikunitz/xz/internal/hash","checksumSHA1":"vjnTkzNrMs5Xj6so/fq0mQ6dT1c=","revision":"0c6b41e72360850ca4f98dc341fd999726ea007f","revisionTime":"2017-06-05T21:53:11Z"}, + {"path":"github.com/ulikunitz/xz/internal/xlog","checksumSHA1":"m0pm57ASBK/CTdmC0ppRHO17mBs=","revision":"0c6b41e72360850ca4f98dc341fd999726ea007f","revisionTime":"2017-06-05T21:53:11Z"}, + {"path":"github.com/ulikunitz/xz/lzma","checksumSHA1":"2vZw6zc8xuNlyVz2QKvdlNSZQ1U=","revision":"0c6b41e72360850ca4f98dc341fd999726ea007f","revisionTime":"2017-06-05T21:53:11Z"}, + {"path":"go4.org/errorutil","checksumSHA1":"PMr/a5kcnC4toJtVwWhlU5E4tJY=","revision":"034d17a462f7b2dcd1a4a73553ec5357ff6e6c6e","revisionTime":"2017-05-24T23:16:39Z"}, + {"path":"golang.org/x/crypto/blake2b","checksumSHA1":"5TlXhxVMqfHQKpCKucmXNeE6/kc=","revision":"74b34b9dd60829a9fcaf56a59e81c3877a8ecd2c","revisionTime":"2017-09-02T17:19:23Z"}, + {"path":"golang.org/x/crypto/ssh/terminal","checksumSHA1":"nqWNlnMmVpt628zzvyo6Yv2CX5Q=","revision":"eb71ad9bd329b5ac0fd0148dd99bd62e8be8e035","revisionTime":"2017-08-07T10:11:13Z"}, + {"path":"golang.org/x/net/context","checksumSHA1":"9jjO5GjLa0XF/nfWihF02RoH4qc=","revision":"30db96677b74e24b967e23f911eb3364fc61a011","revisionTime":"2016-05-25T13:11:03Z"}, + {"path":"golang.org/x/net/context/ctxhttp","checksumSHA1":"WHc3uByvGaMcnSoI21fhzYgbOgg=","revision":"f09c4662a0bd6bd8943ac7b4931e185df9471da4","revisionTime":"2016-09-24T00:10:04Z"}, + {"path":"golang.org/x/net/http2","checksumSHA1":"kKuxyoDujo5CopTxAvvZ1rrLdd0=","revision":"ab5485076ff3407ad2d02db054635913f017b0ed","revisionTime":"2017-07-19T21:11:51Z"}, + {"path":"golang.org/x/net/http2/hpack","checksumSHA1":"ezWhc7n/FtqkLDQKeU2JbW+80tE=","revision":"ab5485076ff3407ad2d02db054635913f017b0ed","revisionTime":"2017-07-19T21:11:51Z"}, + {"path":"golang.org/x/net/idna","checksumSHA1":"g/Z/Ka0VgJESgQK7/SJCjm/aX0I=","revision":"ab5485076ff3407ad2d02db054635913f017b0ed","revisionTime":"2017-07-19T21:11:51Z"}, + {"path":"golang.org/x/net/internal/timeseries","checksumSHA1":"UxahDzW2v4mf/+aFxruuupaoIwo=","revision":"ab5485076ff3407ad2d02db054635913f017b0ed","revisionTime":"2017-07-19T21:11:51Z"}, + {"path":"golang.org/x/net/lex/httplex","checksumSHA1":"3xyuaSNmClqG4YWC7g0isQIbUTc=","revision":"ab5485076ff3407ad2d02db054635913f017b0ed","revisionTime":"2017-07-19T21:11:51Z"}, + {"path":"golang.org/x/net/trace","checksumSHA1":"u/r66lwYfgg682u5hZG7/E7+VCY=","revision":"ab5485076ff3407ad2d02db054635913f017b0ed","revisionTime":"2017-07-19T21:11:51Z"}, + {"path":"golang.org/x/sync/errgroup","checksumSHA1":"S0DP7Pn7sZUmXc55IzZnNvERu6s=","revision":"316e794f7b5e3df4e95175a45a5fb8b12f85cb4f","revisionTime":"2016-07-15T18:54:39Z"}, + {"path":"golang.org/x/sys/unix","checksumSHA1":"SIhhNXud9FKua0s3WlGPRRkDKRg=","revision":"8b4580aae2a0dd0c231a45d3ccb8434ff533b840","revisionTime":"2017-11-30T16:26:51Z"}, + {"path":"golang.org/x/sys/windows","checksumSHA1":"riTVymIu2BFphV6UlA73Fn9tmmU=","revision":"8b4580aae2a0dd0c231a45d3ccb8434ff533b840","revisionTime":"2017-11-30T16:26:51Z"}, + {"path":"golang.org/x/text/secure/bidirule","checksumSHA1":"tltivJ/uj/lqLk05IqGfCv2F/E8=","revision":"88f656faf3f37f690df1a32515b479415e1a6769","revisionTime":"2017-10-26T07:52:28Z"}, + {"path":"golang.org/x/text/transform","checksumSHA1":"ziMb9+ANGRJSSIuxYdRbA+cDRBQ=","revision":"88f656faf3f37f690df1a32515b479415e1a6769","revisionTime":"2017-10-26T07:52:28Z"}, + {"path":"golang.org/x/text/unicode/bidi","checksumSHA1":"iB6/RoQIzBaZxVi+t7tzbkwZTlo=","revision":"88f656faf3f37f690df1a32515b479415e1a6769","revisionTime":"2017-10-26T07:52:28Z"}, + {"path":"golang.org/x/text/unicode/norm","checksumSHA1":"km/8bLtOpIP7sua4MnEmiSDYTAE=","revision":"88f656faf3f37f690df1a32515b479415e1a6769","revisionTime":"2017-10-26T07:52:28Z"}, + {"path":"golang.org/x/time/rate","checksumSHA1":"h/06ikMECfJoTkWj2e1nJ30aDDg=","revision":"a4bde12657593d5e90d0533a3e4fd95e635124cb","revisionTime":"2016-02-02T18:34:45Z"}, + {"path":"google.golang.org/genproto/googleapis/rpc/status","checksumSHA1":"AvVpgwhxhJgjoSledwDtYrEKVE4=","revision":"b0a3dcfcd1a9bd48e63634bd8802960804cf8315","revisionTime":"2017-07-11T23:52:30Z"}, + {"path":"google.golang.org/grpc","checksumSHA1":"2HA7jxFtX4Dp7Lt3wafAUXa9IZc=","revision":"0c41876308d45bc82e587965971e28be659a1aca","revisionTime":"2017-07-21T17:58:12Z"}, + {"path":"google.golang.org/grpc/codes","checksumSHA1":"/eTpFgjvMq5Bc9hYnw5fzKG4B6I=","revision":"0c41876308d45bc82e587965971e28be659a1aca","revisionTime":"2017-07-21T17:58:12Z"}, + {"path":"google.golang.org/grpc/credentials","checksumSHA1":"5ylThBvJnIcyWhL17AC9+Sdbw2E=","revision":"0c41876308d45bc82e587965971e28be659a1aca","revisionTime":"2017-07-21T17:58:12Z"}, + {"path":"google.golang.org/grpc/grpclb/grpc_lb_v1","checksumSHA1":"2NbY9kmMweE4VUsruRsvmViVnNg=","revision":"0c41876308d45bc82e587965971e28be659a1aca","revisionTime":"2017-07-21T17:58:12Z"}, + {"path":"google.golang.org/grpc/grpclog","checksumSHA1":"MCQmohiDJwkgLWu/wpnekweQh8s=","revision":"0c41876308d45bc82e587965971e28be659a1aca","revisionTime":"2017-07-21T17:58:12Z"}, + {"path":"google.golang.org/grpc/health","checksumSHA1":"pc9cweMiKQ5hVMuO9UoMGdbizaY=","revision":"0c41876308d45bc82e587965971e28be659a1aca","revisionTime":"2017-07-21T17:58:12Z"}, + {"path":"google.golang.org/grpc/health/grpc_health_v1","checksumSHA1":"W5KfI1NIGJt7JaVnLzefDZr3+4s=","revision":"0c41876308d45bc82e587965971e28be659a1aca","revisionTime":"2017-07-21T17:58:12Z"}, + {"path":"google.golang.org/grpc/internal","checksumSHA1":"U9vDe05/tQrvFBojOQX8Xk12W9I=","revision":"0c41876308d45bc82e587965971e28be659a1aca","revisionTime":"2017-07-21T17:58:12Z"}, + {"path":"google.golang.org/grpc/keepalive","checksumSHA1":"hcuHgKp8W0wIzoCnNfKI8NUss5o=","revision":"0c41876308d45bc82e587965971e28be659a1aca","revisionTime":"2017-07-21T17:58:12Z"}, + {"path":"google.golang.org/grpc/metadata","checksumSHA1":"N++Ur11m6Dq3j14/Hc2Kqmxroag=","revision":"0c41876308d45bc82e587965971e28be659a1aca","revisionTime":"2017-07-21T17:58:12Z"}, + {"path":"google.golang.org/grpc/naming","checksumSHA1":"Zzb7Xsc3tbTJzrcZbSPyye+yxmw=","revision":"0c41876308d45bc82e587965971e28be659a1aca","revisionTime":"2017-07-21T17:58:12Z"}, + {"path":"google.golang.org/grpc/peer","checksumSHA1":"n5EgDdBqFMa2KQFhtl+FF/4gIFo=","revision":"0c41876308d45bc82e587965971e28be659a1aca","revisionTime":"2017-07-21T17:58:12Z"}, + {"path":"google.golang.org/grpc/stats","checksumSHA1":"ZY8Tq61fGK1stTuvwK5WoqcU8j8=","revision":"0c41876308d45bc82e587965971e28be659a1aca","revisionTime":"2017-07-21T17:58:12Z"}, + {"path":"google.golang.org/grpc/status","checksumSHA1":"DIv9qbApAoh2cF2G3Br24lVPqUI=","revision":"0c41876308d45bc82e587965971e28be659a1aca","revisionTime":"2017-07-21T17:58:12Z"}, + {"path":"google.golang.org/grpc/tap","checksumSHA1":"aixGx/Kd0cj9ZlZHacpHe3XgMQ4=","revision":"0c41876308d45bc82e587965971e28be659a1aca","revisionTime":"2017-07-21T17:58:12Z"}, + {"path":"google.golang.org/grpc/transport","checksumSHA1":"oFGr0JoquaPGVnV86fVL8MVTc3A=","revision":"0c41876308d45bc82e587965971e28be659a1aca","revisionTime":"2017-07-21T17:58:12Z"}, + {"path":"gopkg.in/fsnotify.v1","checksumSHA1":"eIhF+hmL/XZhzTiAwhLD0M65vlY=","revision":"629574ca2a5df945712d3079857300b5e4da0236","revisionTime":"2016-10-11T02:33:12Z"}, + {"path":"gopkg.in/inf.v0","checksumSHA1":"6f8MEU31llHM1sLM/GGH4/Qxu0A=","revision":"3887ee99ecf07df5b447e9b00d9c0b2adaa9f3e4","revisionTime":"2015-09-11T12:57:57Z"}, + {"path":"gopkg.in/lxc/go-lxc.v2","checksumSHA1":"i97goLq3AIfUNB8l1hxGGMSW0+s=","revision":"f8a6938e600c634232eeef79dc04a1226f73a88b","revisionTime":"2016-08-03T16:52:18Z"}, + {"path":"gopkg.in/tomb.v1","checksumSHA1":"TO8baX+t1Qs7EmOYth80MkbKzFo=","revision":"dd632973f1e7218eb1089048e0798ec9ae7dceb8","revisionTime":"2014-10-24T13:56:13Z"}, + {"path":"gopkg.in/tomb.v2","checksumSHA1":"WiyCOMvfzRdymImAJ3ME6aoYUdM=","revision":"14b3d72120e8d10ea6e6b7f87f7175734b1faab8","revisionTime":"2014-06-26T14:46:23Z"}, + {"path":"gopkg.in/yaml.v2","checksumSHA1":"12GqsW8PiRPnezDDy0v4brZrndM=","revision":"a5b47d31c556af34a302ce5d659e6fea44d90de0","revisionTime":"2016-09-28T15:37:09Z"} ], "rootPath": "github.com/hashicorp/nomad" } From 99e896da2d26a30e781f5785ba540723ecc37e49 Mon Sep 17 00:00:00 2001 From: Preetha Appan Date: Tue, 12 Dec 2017 15:52:58 -0600 Subject: [PATCH 11/13] Linkify changelog issues --- GNUmakefile | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/GNUmakefile b/GNUmakefile index a4ada95cc..c2527210b 100644 --- a/GNUmakefile +++ b/GNUmakefile @@ -198,6 +198,10 @@ vendorfmt: @echo "--> Formatting vendor/vendor.json" test -x $(GOPATH)/bin/vendorfmt || go get -u github.com/magiconair/vendorfmt/cmd/vendorfmt vendorfmt +changelogfmt: + @echo "--> Making [GH-xxxx] references clickable..." + @sed -E 's|([^\[])\[GH-([0-9]+)\]|\1[[GH-\2](https://github.com/hashicorp/nomad/issues/\2)]|g' CHANGELOG.md > changelog.tmp && mv changelog.tmp CHANGELOG.md + .PHONY: dev dev: GOOS=$(shell go env GOOS) From d7fcea53c37419c9a503433c695b07993b77c23f Mon Sep 17 00:00:00 2001 From: Preetha Appan Date: Tue, 12 Dec 2017 15:54:16 -0600 Subject: [PATCH 12/13] Initial run of make changelogfmt that linkifies all issues in CHANGELOG --- CHANGELOG.md | 1162 +++++++++++++++++++++++++------------------------- 1 file changed, 581 insertions(+), 581 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 593d7e4d5..f746f5cc5 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -3,7 +3,7 @@ __BACKWARDS INCOMPATIBILITIES:__ * client: The format of service IDs in Consul has changed. If you rely upon Nomad's service IDs (*not* service names; those are stable), you will need - to update your code. [GH-3632] + to update your code. [[GH-3632](https://github.com/hashicorp/nomad/issues/3632)] * config: Nomad no longer parses Atlas configuration stanzas. Atlas has been deprecated since earlier this year. If you have an Atlas stanza in your config file it will have to be removed. @@ -13,78 +13,78 @@ __BACKWARDS INCOMPATIBILITIES:__ IMPROVEMENTS: * core: Allow operators to reload TLS certificate and key files via SIGHUP - [GH-3479] + [[GH-3479](https://github.com/hashicorp/nomad/issues/3479)] * core: Allow configurable stop signals for a task, when drivers support - sending stop signals [GH-1755] + sending stop signals [[GH-1755](https://github.com/hashicorp/nomad/issues/1755)] * core: Allow agents to be run in `rpc_upgrade_mode` when migrating a cluster to TLS rather than changing `heartbeat_grace` * api: Allocations now track and return modify time in addition to create time - [GH-3446] + [[GH-3446](https://github.com/hashicorp/nomad/issues/3446)] * api: Introduced new fields to track details and display message for task - events, and deprecated redundant existing fields [GH-3399] - * api: Environment variables are ignored during service name validation [GH-3532] + events, and deprecated redundant existing fields [[GH-3399](https://github.com/hashicorp/nomad/issues/3399)] + * api: Environment variables are ignored during service name validation [[GH-3532](https://github.com/hashicorp/nomad/issues/3532)] * cli: Allocation create and modify times are displayed in a human readable - relative format like `6 h ago` [GH-3449] - * client: Support `address_mode` on checks [GH-3619] - * client: Sticky volume migrations are now atomic. [GH-3563] - * client: Added metrics to track state transitions of allocations [GH-3061] + relative format like `6 h ago` [[GH-3449](https://github.com/hashicorp/nomad/issues/3449)] + * client: Support `address_mode` on checks [[GH-3619](https://github.com/hashicorp/nomad/issues/3619)] + * client: Sticky volume migrations are now atomic. [[GH-3563](https://github.com/hashicorp/nomad/issues/3563)] + * client: Added metrics to track state transitions of allocations [[GH-3061](https://github.com/hashicorp/nomad/issues/3061)] * client: When `network_interface` is unspecified use interface attached to - default route [GH-3546] + default route [[GH-3546](https://github.com/hashicorp/nomad/issues/3546)] * client: Support numeric ports on services and checks when - `address_mode="driver"` [GH-3619] - * driver/docker: Detect OOM kill event [GH-3459] + `address_mode="driver"` [[GH-3619](https://github.com/hashicorp/nomad/issues/3619)] + * driver/docker: Detect OOM kill event [[GH-3459](https://github.com/hashicorp/nomad/issues/3459)] * driver/docker: Adds support for adding host device to container via - `--device` [GH-2938] - * driver/docker: Adds support for `ulimit` and `sysctl` options [GH-3568] + `--device` [[GH-2938](https://github.com/hashicorp/nomad/issues/2938)] + * driver/docker: Adds support for `ulimit` and `sysctl` options [[GH-3568](https://github.com/hashicorp/nomad/issues/3568)] * driver/docker: Adds support for StopTimeout (set to the same value as - kill_timeout [GH-3601] - * driver/rkt: Add support for passing through user [GH-3612] - * driver/qemu: Support graceful shutdowns on unix platforms [GH-3411] - * template: Updated to consul template 0.19.4 [GH-3543] + kill_timeout [[GH-3601](https://github.com/hashicorp/nomad/issues/3601)] + * driver/rkt: Add support for passing through user [[GH-3612](https://github.com/hashicorp/nomad/issues/3612)] + * driver/qemu: Support graceful shutdowns on unix platforms [[GH-3411](https://github.com/hashicorp/nomad/issues/3411)] + * template: Updated to consul template 0.19.4 [[GH-3543](https://github.com/hashicorp/nomad/issues/3543)] * core/enterprise: Return 501 status code in Nomad Pro for Premium end points - * ui: Added log streaming for tasks [GH-3564] - * ui: Show the modify time for allocations [GH-3607] - * ui: Added a dedicated Task page under allocations [GH-3472] - * ui: Added placement failures to the Job Detail page [GH-3603] - * ui: Warn uncaught exceptions to the developer console [GH-3623] + * ui: Added log streaming for tasks [[GH-3564](https://github.com/hashicorp/nomad/issues/3564)] + * ui: Show the modify time for allocations [[GH-3607](https://github.com/hashicorp/nomad/issues/3607)] + * ui: Added a dedicated Task page under allocations [[GH-3472](https://github.com/hashicorp/nomad/issues/3472)] + * ui: Added placement failures to the Job Detail page [[GH-3603](https://github.com/hashicorp/nomad/issues/3603)] + * ui: Warn uncaught exceptions to the developer console [[GH-3623](https://github.com/hashicorp/nomad/issues/3623)] BUG FIXES: * core: Fix issue in which restoring periodic jobs could fail when a leader - election occurs [GH-3646] + election occurs [[GH-3646](https://github.com/hashicorp/nomad/issues/3646)] * core: Fixed an issue where the leader server could get into a state where it was no longer performing the periodic leader loop duties after a barrier - timeout error [GH-3402] + timeout error [[GH-3402](https://github.com/hashicorp/nomad/issues/3402)] * core: Fixes an issue with jobs that have `auto_revert` set to true, where reverting to a previously stable job that fails to start up causes an - infinite cycle of reverts [GH-3496] + infinite cycle of reverts [[GH-3496](https://github.com/hashicorp/nomad/issues/3496)] * api: Apply correct memory default when task's do not specify memory - explicitly [GH-3520] - * cli: Fix passing Consul address via flags [GH-3504] - * cli: Fix panic when running `keyring` commands [GH-3509] + explicitly [[GH-3520](https://github.com/hashicorp/nomad/issues/3520)] + * cli: Fix passing Consul address via flags [[GH-3504](https://github.com/hashicorp/nomad/issues/3504)] + * cli: Fix panic when running `keyring` commands [[GH-3509](https://github.com/hashicorp/nomad/issues/3509)] * client: Fix advertising services with tags that require URL escaping - [GH-3632] + [[GH-3632](https://github.com/hashicorp/nomad/issues/3632)] * client: Fix a panic when restoring an allocation with a dead leader task - [GH-3502] - * client: Fix crash when following logs from a Windows node [GH-3608] + [[GH-3502](https://github.com/hashicorp/nomad/issues/3502)] + * client: Fix crash when following logs from a Windows node [[GH-3608](https://github.com/hashicorp/nomad/issues/3608)] * client: Fix service/check updating when just interpolated variables change - [GH-3619] + [[GH-3619](https://github.com/hashicorp/nomad/issues/3619)] * client: Fix allocation accounting in GC and trigger GCs on allocation - updates [GH-3445] - * driver/docker: Fix container name conflict handling [GH-3551] - * driver/rkt: Remove pods on shutdown [GH-3562] - * driver/rkt: Don't require port maps when using host networking [GH-3615] + updates [[GH-3445](https://github.com/hashicorp/nomad/issues/3445)] + * driver/docker: Fix container name conflict handling [[GH-3551](https://github.com/hashicorp/nomad/issues/3551)] + * driver/rkt: Remove pods on shutdown [[GH-3562](https://github.com/hashicorp/nomad/issues/3562)] + * driver/rkt: Don't require port maps when using host networking [[GH-3615](https://github.com/hashicorp/nomad/issues/3615)] * template: Fix issue where multiple environment variable templates would be parsed incorrectly when contents of one have changed after the initial - rendering [GH-3529] + rendering [[GH-3529](https://github.com/hashicorp/nomad/issues/3529)] * sentinel: (Nomad Enterprise) Fix an issue that could cause an import error when multiple Sentinel policies are applied - * telemetry: Do not emit metrics for non-running tasks [GH-3559] - * telemetry: Emit hostname as a tag rather than within the key name [GH-3616] - * ui: Remove timezone text from timestamps [GH-3621] - * ui: Allow cross-origin requests from the UI [GH-3530] - * ui: Consistently use Clients instead of Nodes in copy [GH-3466] - * ui: Fully expand the job definition on the Job Definition page [GH-3631] + * telemetry: Do not emit metrics for non-running tasks [[GH-3559](https://github.com/hashicorp/nomad/issues/3559)] + * telemetry: Emit hostname as a tag rather than within the key name [[GH-3616](https://github.com/hashicorp/nomad/issues/3616)] + * ui: Remove timezone text from timestamps [[GH-3621](https://github.com/hashicorp/nomad/issues/3621)] + * ui: Allow cross-origin requests from the UI [[GH-3530](https://github.com/hashicorp/nomad/issues/3530)] + * ui: Consistently use Clients instead of Nodes in copy [[GH-3466](https://github.com/hashicorp/nomad/issues/3466)] + * ui: Fully expand the job definition on the Job Definition page [[GH-3631](https://github.com/hashicorp/nomad/issues/3631)] ## 0.7.0 (November 1, 2017) @@ -99,81 +99,81 @@ IMPROVEMENTS: * core/enterprise: Sentinel integration for fine grain policy enforcement. * core/enterprise: Namespace support allowing jobs and their associated objects to be isolated from each other and other users of the cluster. - * api: Allow force deregistration of a node [GH-3447] + * api: Allow force deregistration of a node [[GH-3447](https://github.com/hashicorp/nomad/issues/3447)] * api: New `/v1/agent/health` endpoint for health checks. - * api: Metrics endpoint exposes Prometheus formatted metrics [GH-3171] - * cli: Consul config option flags for nomad agent command [GH-3327] - * discovery: Allow restarting unhealthy tasks with `check_restart` [GH-3105] - * driver/rkt: Enable rkt driver to use address_mode = 'driver' [GH-3256] - * telemetry: Add support for tagged metrics for Nomad clients [GH-3147] - * telemetry: Add basic Prometheus configuration for a Nomad cluster [GH-3186] + * api: Metrics endpoint exposes Prometheus formatted metrics [[GH-3171](https://github.com/hashicorp/nomad/issues/3171)] + * cli: Consul config option flags for nomad agent command [[GH-3327](https://github.com/hashicorp/nomad/issues/3327)] + * discovery: Allow restarting unhealthy tasks with `check_restart` [[GH-3105](https://github.com/hashicorp/nomad/issues/3105)] + * driver/rkt: Enable rkt driver to use address_mode = 'driver' [[GH-3256](https://github.com/hashicorp/nomad/issues/3256)] + * telemetry: Add support for tagged metrics for Nomad clients [[GH-3147](https://github.com/hashicorp/nomad/issues/3147)] + * telemetry: Add basic Prometheus configuration for a Nomad cluster [[GH-3186](https://github.com/hashicorp/nomad/issues/3186)] BUG FIXES: - * core: Fix restoration of stopped periodic jobs [GH-3201] - * core: Run deployment garbage collector on an interval [GH-3267] + * core: Fix restoration of stopped periodic jobs [[GH-3201](https://github.com/hashicorp/nomad/issues/3201)] + * core: Run deployment garbage collector on an interval [[GH-3267](https://github.com/hashicorp/nomad/issues/3267)] * core: Fix paramterized jobs occasionally showing status dead incorrectly - [GH-3460] + [[GH-3460](https://github.com/hashicorp/nomad/issues/3460)] * core: Fix issue in which job versions above a threshold potentially wouldn't - be stored [GH-3372] + be stored [[GH-3372](https://github.com/hashicorp/nomad/issues/3372)] * core: Fix issue where node-drain with complete batch allocation would create - replacement [GH-3217] + replacement [[GH-3217](https://github.com/hashicorp/nomad/issues/3217)] * core: Allow batch jobs that have been purged to be rerun without a job - specification change [GH-3375] + specification change [[GH-3375](https://github.com/hashicorp/nomad/issues/3375)] * core: Fix issue in which batch allocations from previous job versions may not - have been stopped properly. [GH-3217] + have been stopped properly. [[GH-3217](https://github.com/hashicorp/nomad/issues/3217)] * core: Fix issue in which allocations with the same name during a scale - down/stop event wouldn't be properly stopped [GH-3217] + down/stop event wouldn't be properly stopped [[GH-3217](https://github.com/hashicorp/nomad/issues/3217)] * core: Fix a race condition in which scheduling results from one invocation of - the scheduler wouldn't be considered by the next for the same job [GH-3206] + the scheduler wouldn't be considered by the next for the same job [[GH-3206](https://github.com/hashicorp/nomad/issues/3206)] * api: Sort /v1/agent/servers output so that output of Consul checks does not - change [GH-3214] + change [[GH-3214](https://github.com/hashicorp/nomad/issues/3214)] * api: Fix search handling of jobs with more than four hyphens and case were - length could cause lookup error [GH-3203] + length could cause lookup error [[GH-3203](https://github.com/hashicorp/nomad/issues/3203)] * client: Improve the speed at which clients detect garbage collection events [GH_-3452] * client: Fix lock contention that could cause a node to miss a heartbeat and - be marked as down [GH-3195] + be marked as down [[GH-3195](https://github.com/hashicorp/nomad/issues/3195)] * client: Fix data race that could lead to concurrent map read/writes during - hearbeating and fingerprinting [GH-3461] - * driver/docker: Fix docker user specified syslogging [GH-3184] + hearbeating and fingerprinting [[GH-3461](https://github.com/hashicorp/nomad/issues/3461)] + * driver/docker: Fix docker user specified syslogging [[GH-3184](https://github.com/hashicorp/nomad/issues/3184)] * driver/docker: Fix issue where CPU usage statistics were artificially high - [GH-3229] + [[GH-3229](https://github.com/hashicorp/nomad/issues/3229)] * client/template: Fix issue in which secrets would be renewed too aggressively - [GH-3360] + [[GH-3360](https://github.com/hashicorp/nomad/issues/3360)] ## 0.6.3 (September 11, 2017) BUG FIXES: - * api: Search handles prefix longer than allowed UUIDs [GH-3138] - * api: Search endpoint handles even UUID prefixes with hyphens [GH-3120] - * api: Don't merge empty update stanza from job into task groups [GH-3139] - * cli: Sort task groups when displaying a deployment [GH-3137] - * cli: Handle reading files that are in a symlinked directory [GH-3164] - * cli: All status commands handle even UUID prefixes with hyphens [GH-3122] - * cli: Fix autocompletion of paths that include directories on zsh [GH-3129] + * api: Search handles prefix longer than allowed UUIDs [[GH-3138](https://github.com/hashicorp/nomad/issues/3138)] + * api: Search endpoint handles even UUID prefixes with hyphens [[GH-3120](https://github.com/hashicorp/nomad/issues/3120)] + * api: Don't merge empty update stanza from job into task groups [[GH-3139](https://github.com/hashicorp/nomad/issues/3139)] + * cli: Sort task groups when displaying a deployment [[GH-3137](https://github.com/hashicorp/nomad/issues/3137)] + * cli: Handle reading files that are in a symlinked directory [[GH-3164](https://github.com/hashicorp/nomad/issues/3164)] + * cli: All status commands handle even UUID prefixes with hyphens [[GH-3122](https://github.com/hashicorp/nomad/issues/3122)] + * cli: Fix autocompletion of paths that include directories on zsh [[GH-3129](https://github.com/hashicorp/nomad/issues/3129)] * cli: Fix job deployment -latest handling of jobs without deployments - [GH-3166] + [[GH-3166](https://github.com/hashicorp/nomad/issues/3166)] * cli: Hide CLI commands not expected to be run by user from autocomplete - suggestions [GH-3177] + suggestions [[GH-3177](https://github.com/hashicorp/nomad/issues/3177)] * cli: Status command honors exact job match even when it is the prefix of - another job [GH-3120] + another job [[GH-3120](https://github.com/hashicorp/nomad/issues/3120)] * cli: Fix setting of TLSServerName for node API Client. This fixes an issue of - contacting nodes that are using TLS [GH-3127] + contacting nodes that are using TLS [[GH-3127](https://github.com/hashicorp/nomad/issues/3127)] * client/template: Fix issue in which the template block could cause high load - on Vault when secret lease duration was less than the Vault grace [GH-3153] - * driver/docker: Always purge stopped containers [GH-3148] - * driver/docker: Fix MemorySwappiness on Windows [GH-3187] - * driver/docker: Fix issue in which mounts could parse incorrectly [GH-3163] + on Vault when secret lease duration was less than the Vault grace [[GH-3153](https://github.com/hashicorp/nomad/issues/3153)] + * driver/docker: Always purge stopped containers [[GH-3148](https://github.com/hashicorp/nomad/issues/3148)] + * driver/docker: Fix MemorySwappiness on Windows [[GH-3187](https://github.com/hashicorp/nomad/issues/3187)] + * driver/docker: Fix issue in which mounts could parse incorrectly [[GH-3163](https://github.com/hashicorp/nomad/issues/3163)] * driver/docker: Fix issue where potentially incorrect syslog server address is - used [GH-3135] + used [[GH-3135](https://github.com/hashicorp/nomad/issues/3135)] * driver/docker: Fix server url passed to credential helpers and properly - capture error output [GH-3165] - * jobspec: Allow distinct_host constraint to have L/RTarget set [GH-3136] + capture error output [[GH-3165](https://github.com/hashicorp/nomad/issues/3165)] + * jobspec: Allow distinct_host constraint to have L/RTarget set [[GH-3136](https://github.com/hashicorp/nomad/issues/3136)] ## 0.6.2 (August 28, 2017) BUG FIXES: - * api/cli: Fix logs and fs api and command [GH-3116] + * api/cli: Fix logs and fs api and command [[GH-3116](https://github.com/hashicorp/nomad/issues/3116)] ## 0.6.1 (August 28, 2017) @@ -183,52 +183,52 @@ __BACKWARDS INCOMPATIBILITIES:__ remove the stanza as a zero parallelism update is not valid. IMPROVEMENTS: - * core: Lost allocations replaced even if part of failed deployment [GH-2961] + * core: Lost allocations replaced even if part of failed deployment [[GH-2961](https://github.com/hashicorp/nomad/issues/2961)] * core: Add autocomplete functionality for resources: allocations, evaluations, - jobs, deployments and nodes [GH-2964] + jobs, deployments and nodes [[GH-2964](https://github.com/hashicorp/nomad/issues/2964)] * core: `distinct_property` constraint can set the number of allocations that - are allowed to share a property value [GH-2942] + are allowed to share a property value [[GH-2942](https://github.com/hashicorp/nomad/issues/2942)] * core: Placing allocation counts towards placement limit fixing issue where - rolling update could remove an unnecessary amount of allocations [GH-3070] - * api: Redact Vault.Token from AgentSelf response [GH-2988] - * cli: node-status displays node version [GH-3002] - * cli: Disable color output when STDOUT is not a TTY [GH-3057] + rolling update could remove an unnecessary amount of allocations [[GH-3070](https://github.com/hashicorp/nomad/issues/3070)] + * api: Redact Vault.Token from AgentSelf response [[GH-2988](https://github.com/hashicorp/nomad/issues/2988)] + * cli: node-status displays node version [[GH-3002](https://github.com/hashicorp/nomad/issues/3002)] + * cli: Disable color output when STDOUT is not a TTY [[GH-3057](https://github.com/hashicorp/nomad/issues/3057)] * cli: Add autocomplete functionality for flags for all CLI command [GH 3087] * cli: Add status command which takes any identifier and routes to the appropriate status command. - * client: Unmount task directories when alloc is terminal [GH-3006] - * client/template: Allow template to set Vault grace [GH-2947] - * client/template: Template emits events explaining why it is blocked [GH-3001] - * deployment: Disallow max_parallel of zero [GH-3081] - * deployment: Emit task events explaining unhealthy allocations [GH-3025] + * client: Unmount task directories when alloc is terminal [[GH-3006](https://github.com/hashicorp/nomad/issues/3006)] + * client/template: Allow template to set Vault grace [[GH-2947](https://github.com/hashicorp/nomad/issues/2947)] + * client/template: Template emits events explaining why it is blocked [[GH-3001](https://github.com/hashicorp/nomad/issues/3001)] + * deployment: Disallow max_parallel of zero [[GH-3081](https://github.com/hashicorp/nomad/issues/3081)] + * deployment: Emit task events explaining unhealthy allocations [[GH-3025](https://github.com/hashicorp/nomad/issues/3025)] * deployment: Better description when a deployment should auto-revert but there - is no target [GH-3024] - * discovery: Add HTTP header and method support to checks [GH-3031] - * driver/docker: Added DNS options [GH-2992] - * driver/docker: Add mount options for volumes [GH-3021] + is no target [[GH-3024](https://github.com/hashicorp/nomad/issues/3024)] + * discovery: Add HTTP header and method support to checks [[GH-3031](https://github.com/hashicorp/nomad/issues/3031)] + * driver/docker: Added DNS options [[GH-2992](https://github.com/hashicorp/nomad/issues/2992)] + * driver/docker: Add mount options for volumes [[GH-3021](https://github.com/hashicorp/nomad/issues/3021)] * driver/docker: Allow retry of 500 API errors to be handled by restart - policies when starting a container [GH-3073] - * driver/rkt: support read-only volume mounts [GH-2883] + policies when starting a container [[GH-3073](https://github.com/hashicorp/nomad/issues/3073)] + * driver/rkt: support read-only volume mounts [[GH-2883](https://github.com/hashicorp/nomad/issues/2883)] * jobspec: Add `shutdown_delay` so tasks can delay shutdown after deregistering - from Consul [GH-3043] + from Consul [[GH-3043](https://github.com/hashicorp/nomad/issues/3043)] BUG FIXES: - * core: Fix purging of job versions [GH-3056] - * core: Fix race creating EvalFuture [GH-3051] - * core: Fix panic occuring from improper bitmap size [GH-3023] - * core: Fix restoration of parameterized, periodic jobs [GH-2959] + * core: Fix purging of job versions [[GH-3056](https://github.com/hashicorp/nomad/issues/3056)] + * core: Fix race creating EvalFuture [[GH-3051](https://github.com/hashicorp/nomad/issues/3051)] + * core: Fix panic occuring from improper bitmap size [[GH-3023](https://github.com/hashicorp/nomad/issues/3023)] + * core: Fix restoration of parameterized, periodic jobs [[GH-2959](https://github.com/hashicorp/nomad/issues/2959)] * core: Fix incorrect destructive update with `distinct_property` constraint - [GH-2939] - * cli: Fix autocmpleting global flags [GH-2928] - * cli: Fix panic when using 0.6.0 cli with an older cluster [GH-2929] - * cli: Fix TLS handling for alloc stats API calls [GH-3108] - * client: Fix `LC_ALL=C` being set on subprocesses [GH-3041] + [[GH-2939](https://github.com/hashicorp/nomad/issues/2939)] + * cli: Fix autocmpleting global flags [[GH-2928](https://github.com/hashicorp/nomad/issues/2928)] + * cli: Fix panic when using 0.6.0 cli with an older cluster [[GH-2929](https://github.com/hashicorp/nomad/issues/2929)] + * cli: Fix TLS handling for alloc stats API calls [[GH-3108](https://github.com/hashicorp/nomad/issues/3108)] + * client: Fix `LC_ALL=C` being set on subprocesses [[GH-3041](https://github.com/hashicorp/nomad/issues/3041)] * client/networking: Handle interfaces that only have link-local addresses - while prefering globally routable addresses [GH-3089] + while prefering globally routable addresses [[GH-3089](https://github.com/hashicorp/nomad/issues/3089)] * deployment: Fix alloc health with services/checks using interpolation - [GH-2984] - * discovery: Fix timeout validation for script checks [GH-3022] - * driver/docker: Fix leaking plugin file used by syslog server [GH-2937] + [[GH-2984](https://github.com/hashicorp/nomad/issues/2984)] + * discovery: Fix timeout validation for script checks [[GH-3022](https://github.com/hashicorp/nomad/issues/3022)] + * driver/docker: Fix leaking plugin file used by syslog server [[GH-2937](https://github.com/hashicorp/nomad/issues/2937)] ## 0.6.0 (July 26, 2017) @@ -239,100 +239,100 @@ __BACKWARDS INCOMPATIBILITIES:__ IMPROVEMENTS: * core: Rolling updates based on allocation health [GH-2621, GH-2634, GH-2799] * core: New deployment object to track job updates [GH-2621, GH-2634, GH-2799] - * core: Default advertise to private IP address if bind is 0.0.0.0 [GH-2399] - * core: Track multiple job versions and add a stopped state for jobs [GH-2566] + * core: Default advertise to private IP address if bind is 0.0.0.0 [[GH-2399](https://github.com/hashicorp/nomad/issues/2399)] + * core: Track multiple job versions and add a stopped state for jobs [[GH-2566](https://github.com/hashicorp/nomad/issues/2566)] * core: Job updates can create canaries before beginning rolling update [GH-2621, GH-2634, GH-2799] * core: Back-pressure when evaluations are nacked and ensure scheduling - progress on evaluation failures [GH-2555] + progress on evaluation failures [[GH-2555](https://github.com/hashicorp/nomad/issues/2555)] * agent/config: Late binding to IP addresses using go-sockaddr/template syntax - [GH-2399] + [[GH-2399](https://github.com/hashicorp/nomad/issues/2399)] * api: Add `verify_https_client` to require certificates from HTTP clients - [GH-2587] - * api/job: Ability to revert job to older versions [GH-2575] - * cli: Autocomplete for CLI commands [GH-2848] - * client: Use a random host UUID by default [GH-2735] - * client: Add `NOMAD_GROUP_NAME` environment variable [GH-2877] - * client: Environment variables for client DC and Region [GH-2507] - * client: Hash host ID so its stable and well distributed [GH-2541] - * client: GC dead allocs if total allocs > `gc_max_allocs` tunable [GH-2636] + [[GH-2587](https://github.com/hashicorp/nomad/issues/2587)] + * api/job: Ability to revert job to older versions [[GH-2575](https://github.com/hashicorp/nomad/issues/2575)] + * cli: Autocomplete for CLI commands [[GH-2848](https://github.com/hashicorp/nomad/issues/2848)] + * client: Use a random host UUID by default [[GH-2735](https://github.com/hashicorp/nomad/issues/2735)] + * client: Add `NOMAD_GROUP_NAME` environment variable [[GH-2877](https://github.com/hashicorp/nomad/issues/2877)] + * client: Environment variables for client DC and Region [[GH-2507](https://github.com/hashicorp/nomad/issues/2507)] + * client: Hash host ID so its stable and well distributed [[GH-2541](https://github.com/hashicorp/nomad/issues/2541)] + * client: GC dead allocs if total allocs > `gc_max_allocs` tunable [[GH-2636](https://github.com/hashicorp/nomad/issues/2636)] * client: Persist state using bolt-db and more efficient write patterns - [GH-2610] + [[GH-2610](https://github.com/hashicorp/nomad/issues/2610)] * client: Fingerprint all routable addresses on an interface including IPv6 - addresses [GH-2536] - * client/artifact: Support .xz archives [GH-2836] - * client/artifact: Allow specifying a go-getter mode [GH-2781] - * client/artifact: Support non-Amazon S3-compatible sources [GH-2781] - * client/template: Support reading env vars from templates [GH-2654] - * config: Support Unix socket addresses for Consul [GH-2622] - * discovery: Advertise driver-specified IP address and port [GH-2709] - * discovery: Support `tls_skip_verify` for Consul HTTPS checks [GH-2467] - * driver/docker: Allow specifying extra hosts [GH-2547] - * driver/docker: Allow setting seccomp profiles [GH-2658] - * driver/docker: Support Docker credential helpers [GH-2651] - * driver/docker: Auth failures can optionally be ignored [GH-2786] - * driver/docker: Add `driver.docker.bridge_ip` node attribute [GH-2797] + addresses [[GH-2536](https://github.com/hashicorp/nomad/issues/2536)] + * client/artifact: Support .xz archives [[GH-2836](https://github.com/hashicorp/nomad/issues/2836)] + * client/artifact: Allow specifying a go-getter mode [[GH-2781](https://github.com/hashicorp/nomad/issues/2781)] + * client/artifact: Support non-Amazon S3-compatible sources [[GH-2781](https://github.com/hashicorp/nomad/issues/2781)] + * client/template: Support reading env vars from templates [[GH-2654](https://github.com/hashicorp/nomad/issues/2654)] + * config: Support Unix socket addresses for Consul [[GH-2622](https://github.com/hashicorp/nomad/issues/2622)] + * discovery: Advertise driver-specified IP address and port [[GH-2709](https://github.com/hashicorp/nomad/issues/2709)] + * discovery: Support `tls_skip_verify` for Consul HTTPS checks [[GH-2467](https://github.com/hashicorp/nomad/issues/2467)] + * driver/docker: Allow specifying extra hosts [[GH-2547](https://github.com/hashicorp/nomad/issues/2547)] + * driver/docker: Allow setting seccomp profiles [[GH-2658](https://github.com/hashicorp/nomad/issues/2658)] + * driver/docker: Support Docker credential helpers [[GH-2651](https://github.com/hashicorp/nomad/issues/2651)] + * driver/docker: Auth failures can optionally be ignored [[GH-2786](https://github.com/hashicorp/nomad/issues/2786)] + * driver/docker: Add `driver.docker.bridge_ip` node attribute [[GH-2797](https://github.com/hashicorp/nomad/issues/2797)] * driver/docker: Allow setting container IP with user defined networks - [GH-2535] - * driver/rkt: Support `no_overlay` [GH-2702] - * driver/rkt: Support `insecure_options` list [GH-2695] - * server: Allow tuning of node heartbeat TTLs [GH-2859] + [[GH-2535](https://github.com/hashicorp/nomad/issues/2535)] + * driver/rkt: Support `no_overlay` [[GH-2702](https://github.com/hashicorp/nomad/issues/2702)] + * driver/rkt: Support `insecure_options` list [[GH-2695](https://github.com/hashicorp/nomad/issues/2695)] + * server: Allow tuning of node heartbeat TTLs [[GH-2859](https://github.com/hashicorp/nomad/issues/2859)] * server/networking: Shrink dynamic port range to not overlap with majority of - operating system's ephemeral port ranges to avoid port conflicts [GH-2856] + operating system's ephemeral port ranges to avoid port conflicts [[GH-2856](https://github.com/hashicorp/nomad/issues/2856)] BUG FIXES: - * core: Protect against nil job in new allocation, avoiding panic [GH-2592] - * core: System jobs should be running until explicitly stopped [GH-2750] - * core: Prevent invalid job updates (eg service -> batch) [GH-2746] - * client: Lookup `ip` utility on `$PATH` [GH-2729] - * client: Add sticky bit to temp directory [GH-2519] - * client: Shutdown task group leader before other tasks [GH-2753] - * client: Include symlinks in snapshots when migrating disks [GH-2687] + * core: Protect against nil job in new allocation, avoiding panic [[GH-2592](https://github.com/hashicorp/nomad/issues/2592)] + * core: System jobs should be running until explicitly stopped [[GH-2750](https://github.com/hashicorp/nomad/issues/2750)] + * core: Prevent invalid job updates (eg service -> batch) [[GH-2746](https://github.com/hashicorp/nomad/issues/2746)] + * client: Lookup `ip` utility on `$PATH` [[GH-2729](https://github.com/hashicorp/nomad/issues/2729)] + * client: Add sticky bit to temp directory [[GH-2519](https://github.com/hashicorp/nomad/issues/2519)] + * client: Shutdown task group leader before other tasks [[GH-2753](https://github.com/hashicorp/nomad/issues/2753)] + * client: Include symlinks in snapshots when migrating disks [[GH-2687](https://github.com/hashicorp/nomad/issues/2687)] * client: Regression for allocation directory unix perms introduced in v0.5.6 - fixed [GH-2675] + fixed [[GH-2675](https://github.com/hashicorp/nomad/issues/2675)] * client: Client syncs allocation state with server before waiting for allocation destroy fixing a corner case in which an allocation may be blocked - till destroy [GH-2563] - * client: Improved state file handling and reduced write volume [GH-2878] - * client/artifact: Honor netrc [GH-2524] + till destroy [[GH-2563](https://github.com/hashicorp/nomad/issues/2563)] + * client: Improved state file handling and reduced write volume [[GH-2878](https://github.com/hashicorp/nomad/issues/2878)] + * client/artifact: Honor netrc [[GH-2524](https://github.com/hashicorp/nomad/issues/2524)] * client/artifact: Handle tars where file in directory is listed before - directory [GH-2524] - * client/config: Use `cpu_total_compute` whenever it is set [GH-2745] + directory [[GH-2524](https://github.com/hashicorp/nomad/issues/2524)] + * client/config: Use `cpu_total_compute` whenever it is set [[GH-2745](https://github.com/hashicorp/nomad/issues/2745)] * client/config: Respect `vault.tls_server_name` setting in consul-template - [GH-2793] - * driver/exec: Properly set file/dir ownership in chroots [GH-2552] - * driver/docker: Fix panic in Docker driver on Windows [GH-2614] - * driver/rkt: Fix env var interpolation [GH-2777] - * jobspec/validation: Prevent static port conflicts [GH-2807] - * server: Reject non-TLS clients when TLS enabled [GH-2525] + [[GH-2793](https://github.com/hashicorp/nomad/issues/2793)] + * driver/exec: Properly set file/dir ownership in chroots [[GH-2552](https://github.com/hashicorp/nomad/issues/2552)] + * driver/docker: Fix panic in Docker driver on Windows [[GH-2614](https://github.com/hashicorp/nomad/issues/2614)] + * driver/rkt: Fix env var interpolation [[GH-2777](https://github.com/hashicorp/nomad/issues/2777)] + * jobspec/validation: Prevent static port conflicts [[GH-2807](https://github.com/hashicorp/nomad/issues/2807)] + * server: Reject non-TLS clients when TLS enabled [[GH-2525](https://github.com/hashicorp/nomad/issues/2525)] * server: Fix a panic in plan evaluation with partial failures and all_at_once - set [GH-2544] + set [[GH-2544](https://github.com/hashicorp/nomad/issues/2544)] * server/periodic: Restoring periodic jobs takes launch time zone into - consideration [GH-2808] - * server/vault: Fix Vault Client panic when given nonexistant role [GH-2648] - * telemetry: Fix merging of use node name [GH-2762] + consideration [[GH-2808](https://github.com/hashicorp/nomad/issues/2808)] + * server/vault: Fix Vault Client panic when given nonexistant role [[GH-2648](https://github.com/hashicorp/nomad/issues/2648)] + * telemetry: Fix merging of use node name [[GH-2762](https://github.com/hashicorp/nomad/issues/2762)] ## 0.5.6 (March 31, 2017) IMPROVEMENTS: * api: Improve log API error when task doesn't exist or hasn't started - [GH-2512] - * client: Improve error message when artifact downloading fails [GH-2289] - * client: Track task start/finish time [GH-2512] - * client/template: Access Node meta and attributes in template [GH-2488] + [[GH-2512](https://github.com/hashicorp/nomad/issues/2512)] + * client: Improve error message when artifact downloading fails [[GH-2289](https://github.com/hashicorp/nomad/issues/2289)] + * client: Track task start/finish time [[GH-2512](https://github.com/hashicorp/nomad/issues/2512)] + * client/template: Access Node meta and attributes in template [[GH-2488](https://github.com/hashicorp/nomad/issues/2488)] BUG FIXES: - * core: Fix periodic job state switching to dead incorrectly [GH-2486] + * core: Fix periodic job state switching to dead incorrectly [[GH-2486](https://github.com/hashicorp/nomad/issues/2486)] * core: Fix dispatch of periodic job launching allocations immediately - [GH-2489] - * api: Fix TLS in logs and fs commands/APIs [GH-2290] - * cli/plan: Fix diff alignment and remove no change DC output [GH-2465] - * client: Fix panic when restarting non-running tasks [GH-2480] - * client: Fix env vars when multiple tasks and ports present [GH-2491] + [[GH-2489](https://github.com/hashicorp/nomad/issues/2489)] + * api: Fix TLS in logs and fs commands/APIs [[GH-2290](https://github.com/hashicorp/nomad/issues/2290)] + * cli/plan: Fix diff alignment and remove no change DC output [[GH-2465](https://github.com/hashicorp/nomad/issues/2465)] + * client: Fix panic when restarting non-running tasks [[GH-2480](https://github.com/hashicorp/nomad/issues/2480)] + * client: Fix env vars when multiple tasks and ports present [[GH-2491](https://github.com/hashicorp/nomad/issues/2491)] * client: Fix `user` attribute disregarding membership of non-main group - [GH-2461] - * client/vault: Stop Vault token renewal on task exit [GH-2495] - * driver/docker: Proper reference counting through task restarts [GH-2484] + [[GH-2461](https://github.com/hashicorp/nomad/issues/2461)] + * client/vault: Stop Vault token renewal on task exit [[GH-2495](https://github.com/hashicorp/nomad/issues/2495)] + * driver/docker: Proper reference counting through task restarts [[GH-2484](https://github.com/hashicorp/nomad/issues/2484)] ## 0.5.5 (March 14, 2017) @@ -342,149 +342,149 @@ __BACKWARDS INCOMPATIBILITIES:__ * driver/docker: The `load` configuration took an array of paths to images prior to this release. A single image is expected by the driver so this behavior has been changed to take a single path as a string. Jobs using the - `load` command should update the syntax to a single string. [GH-2361] + `load` command should update the syntax to a single string. [[GH-2361](https://github.com/hashicorp/nomad/issues/2361)] IMPROVEMENTS: - * core: Handle Serf Reap event [GH-2310] - * core: Update Serf and Memberlist for more reliable gossip [GH-2255] - * api: API defaults missing values [GH-2300] - * api: Validate the restart policy interval [GH-2311] - * api: New task event for task environment setup [GH-2302] + * core: Handle Serf Reap event [[GH-2310](https://github.com/hashicorp/nomad/issues/2310)] + * core: Update Serf and Memberlist for more reliable gossip [[GH-2255](https://github.com/hashicorp/nomad/issues/2255)] + * api: API defaults missing values [[GH-2300](https://github.com/hashicorp/nomad/issues/2300)] + * api: Validate the restart policy interval [[GH-2311](https://github.com/hashicorp/nomad/issues/2311)] + * api: New task event for task environment setup [[GH-2302](https://github.com/hashicorp/nomad/issues/2302)] * api/cli: Add nomad operator command and API for interacting with Raft - configuration [GH-2305] - * cli: node-status displays enabled drivers on the node [GH-2349] - * client: Apply GC related configurations properly [GH-2273] - * client: Don't force uppercase meta keys in env vars [GH-2338] - * client: Limit parallelism during garbage collection [GH-2427] - * client: Don't exec `uname -r` for node attribute kernel.version [GH-2380] - * client: Artifact support for git and hg as well as netrc support [GH-2386] - * client: Add metrics to show number of allocations on in each state [GH-2425] - * client: Add `NOMAD_{IP,PORT}__