github.com/emc-cmd/terraform@v0.7.8-0.20161101145618-f16309630e7c/helper/resource/id.go (about) 1 package resource 2 3 import ( 4 "crypto/rand" 5 "encoding/base32" 6 "fmt" 7 "strings" 8 "time" 9 ) 10 11 const UniqueIdPrefix = `terraform-` 12 13 // Helper for a resource to generate a unique identifier w/ default prefix 14 func UniqueId() string { 15 return PrefixedUniqueId(UniqueIdPrefix) 16 } 17 18 // Helper for a resource to generate a unique identifier w/ given prefix 19 // 20 // After the prefix, the ID consists of a timestamp and 12 random base32 21 // characters. The timestamp means that multiple IDs created with the same 22 // prefix will sort in the order of their creation. 23 func PrefixedUniqueId(prefix string) string { 24 // Be precise to the level nanoseconds, but remove the dot before the 25 // nanosecond. We assume that the randomCharacters call takes at least a 26 // nanosecond, so that multiple calls to this function from the same goroutine 27 // will have distinct ordered timestamps. 28 timestamp := strings.Replace( 29 time.Now().UTC().Format("20060102150405.000000000"), 30 ".", 31 "", 1) 32 // This uses 3 characters, so that the length of the unique ID is the same as 33 // it was before we added the timestamp prefix, which happened to be 23 34 // characters. 35 return fmt.Sprintf("%s%s%s", prefix, timestamp, randomCharacters(3)) 36 } 37 38 func randomCharacters(n int) string { 39 // Base32 has 5 bits of information per character. 40 b := randomBytes(n * 8 / 5) 41 chars := strings.ToLower( 42 strings.Replace( 43 base32.StdEncoding.EncodeToString(b), 44 "=", "", -1)) 45 // Trim extra characters. 46 return chars[:n] 47 } 48 49 func randomBytes(n int) []byte { 50 b := make([]byte, n) 51 rand.Read(b) 52 return b 53 }