diff --git a/command/agent/consul/client.go b/command/agent/consul/client.go index 636ecb7b19d5..a26befa31169 100644 --- a/command/agent/consul/client.go +++ b/command/agent/consul/client.go @@ -1023,20 +1023,7 @@ func makeAgentServiceID(role string, service *structs.Service) string { // // Example Service ID: _nomad-task-TNM333JKJPM5AK4FAS3VXQLXFDWOF4VH func makeTaskServiceID(allocID, taskName string, service *structs.Service) string { - h := sha1.New() - io.WriteString(h, allocID) - io.WriteString(h, taskName) - io.WriteString(h, service.Name) - io.WriteString(h, service.PortLabel) - io.WriteString(h, service.AddressMode) - for _, tag := range service.Tags { - io.WriteString(h, tag) - } - - // Base32 is used for encoding the hash as sha1 hashes can always be - // encoded without padding, only 4 bytes larger than base64, and saves - // 8 bytes vs hex. - return nomadTaskPrefix + base32.StdEncoding.EncodeToString(h.Sum(nil)) + return nomadTaskPrefix + service.Hash(allocID, taskName) } // makeCheckID creates a unique ID for a check. diff --git a/nomad/structs/structs.go b/nomad/structs/structs.go index 7884bbed067d..a2a8f4efda37 100644 --- a/nomad/structs/structs.go +++ b/nomad/structs/structs.go @@ -6,6 +6,7 @@ import ( "crypto/sha1" "crypto/sha256" "crypto/sha512" + "encoding/base32" "encoding/hex" "errors" "fmt" @@ -3140,6 +3141,26 @@ func (s *Service) ValidateName(name string) error { return nil } +// Hash returns a base32 encoded hash of a Service's contents excluding checks +// as they're hashed independently. +func (s *Service) Hash(allocID, taskName string) string { + h := sha1.New() + io.WriteString(h, allocID) + io.WriteString(h, taskName) + io.WriteString(h, s.Name) + io.WriteString(h, s.PortLabel) + io.WriteString(h, s.AddressMode) + for _, tag := range s.Tags { + io.WriteString(h, tag) + } + + // Base32 is used for encoding the hash as sha1 hashes can always be + // encoded without padding, only 4 bytes larger than base64, and saves + // 8 bytes vs hex. Since these hashes are used in Consul URLs it's nice + // to have a reasonably compact URL-safe representation. + return base32.StdEncoding.EncodeToString(h.Sum(nil)) +} + const ( // DefaultKillTimeout is the default timeout between signaling a task it // will be killed and killing it.