diff --git a/consul/util.go b/consul/util.go index 977d38a04f..f830086c04 100644 --- a/consul/util.go +++ b/consul/util.go @@ -1,6 +1,7 @@ package consul import ( + crand "crypto/rand" "encoding/binary" "fmt" "github.com/hashicorp/serf/serf" @@ -160,3 +161,18 @@ func runtimeStats() map[string]string { "cpu_count": strconv.FormatInt(int64(runtime.NumCPU()), 10), } } + +// generateUUID is used to generate a random UUID +func generateUUID() string { + buf := make([]byte, 16) + if _, err := crand.Read(buf); err != nil { + panic(fmt.Errorf("failed to read random bytes: %v", err)) + } + + return fmt.Sprintf("%08x-%04x-%04x-%04x-%12x", + buf[0:4], + buf[4:6], + buf[6:8], + buf[8:10], + buf[10:16]) +} diff --git a/consul/util_test.go b/consul/util_test.go index edd73fdf69..589404a341 100644 --- a/consul/util_test.go +++ b/consul/util_test.go @@ -2,6 +2,7 @@ package consul import ( "github.com/hashicorp/serf/serf" + "regexp" "testing" ) @@ -75,3 +76,19 @@ func TestByteConversion(t *testing.T) { t.Fatalf("no match") } } + +func TestGenerateUUID(t *testing.T) { + prev := generateUUID() + for i := 0; i < 100; i++ { + id := generateUUID() + if prev == id { + t.Fatalf("Should get a new ID!") + } + + matched, err := regexp.MatchString( + "[\\da-f]{8}-[\\da-f]{4}-[\\da-f]{4}-[\\da-f]{4}-[\\da-f]{12}", id) + if !matched || err != nil { + t.Fatalf("expected match %s %v %s", id, matched, err) + } + } +}