@@ -2,48 +2,34 @@ package resource
22
33import (
44 "crypto/rand"
5- "encoding/base32"
65 "fmt"
7- "strings "
8- "time "
6+ "math/big "
7+ "sync "
98)
109
1110const UniqueIdPrefix = `terraform-`
1211
12+ // idCounter is a randomly seeded monotonic counter for generating ordered
13+ // unique ids. It uses a big.Int so we can easily increment a long numeric
14+ // string. The max possible hex value here with 12 random bytes is
15+ // "01000000000000000000000000", so there's no chance of rollover during
16+ // operation.
17+ var idMutex sync.Mutex
18+ var idCounter = big .NewInt (0 ).SetBytes (randomBytes (12 ))
19+
1320// Helper for a resource to generate a unique identifier w/ default prefix
1421func UniqueId () string {
1522 return PrefixedUniqueId (UniqueIdPrefix )
1623}
1724
1825// Helper for a resource to generate a unique identifier w/ given prefix
1926//
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.
27+ // After the prefix, the ID consists of an incrementing 26 digit value (to match
28+ // previous timestamp output).
2329func 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 ]
30+ idMutex .Lock ()
31+ defer idMutex .Unlock ()
32+ return fmt .Sprintf ("%s%026x" , prefix , idCounter .Add (idCounter , big .NewInt (1 )))
4733}
4834
4935func randomBytes (n int ) []byte {
0 commit comments