-
Notifications
You must be signed in to change notification settings - Fork 20
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Forklifted from incubator repo, contains validation for user-settable IDs and default implementation of system-generated IDs.
- Loading branch information
Showing
6 changed files
with
107 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,8 @@ | ||
package resourceid | ||
|
||
import "github.com/google/uuid" | ||
|
||
// NewSystemGenerated returns a new system-generated resource ID. | ||
func NewSystemGenerated() string { | ||
return uuid.New().String() | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,15 @@ | ||
package resourceid | ||
|
||
import ( | ||
"regexp" | ||
"testing" | ||
|
||
"gotest.tools/v3/assert" | ||
"gotest.tools/v3/assert/cmp" | ||
) | ||
|
||
func TestNewSystemGenerated(t *testing.T) { | ||
t.Parallel() | ||
const uuidV4Regexp = `^[0-9a-f]{8}-[0-9a-f]{4}-4[0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$` | ||
assert.Assert(t, cmp.Regexp(regexp.MustCompile(uuidV4Regexp), NewSystemGenerated())) | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,48 @@ | ||
package resourceid | ||
|
||
import ( | ||
"fmt" | ||
|
||
"github.com/google/uuid" | ||
) | ||
|
||
// ValidateUserSettable validates a user-settable resource ID. | ||
// | ||
// From https://google.aip.dev/122#resource-id-segments: | ||
// | ||
// User-settable resource IDs should conform to RFC-1034,which restricts to letters, numbers, and hyphen, with a 63 | ||
// character maximum. Additionally, user-settable resource IDs should restrict letters to lower-case. | ||
// | ||
// User-settable IDs should not be permitted to be a UUID (or any value that syntactically appears to be a UUID). | ||
// | ||
// See also: https://google.aip.dev/133#user-specified-ids | ||
func ValidateUserSettable(id string) error { | ||
if len(id) < 4 || 63 < len(id) { | ||
return fmt.Errorf("user-settable ID must be between 4 and 63 characters") | ||
} | ||
if id[0] == '-' { | ||
return fmt.Errorf("user-settable ID must not start with a hyphen") | ||
} | ||
if _, err := uuid.Parse(id); err == nil { | ||
return fmt.Errorf("user-settable ID must not be a valid UUIDv4") | ||
} | ||
for position, character := range id { | ||
switch character { | ||
case | ||
// numbers | ||
'0', '1', '2', '3', '4', '5', '6', '7', '8', '9', | ||
// hyphen | ||
'-', | ||
// lower-case | ||
'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', | ||
'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z': | ||
default: | ||
return fmt.Errorf( | ||
"user-settable ID must only contain lowercase, numbers and hyphens (got: '%c' in position %d)", | ||
character, | ||
position, | ||
) | ||
} | ||
} | ||
return nil | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,33 @@ | ||
package resourceid | ||
|
||
import ( | ||
"testing" | ||
|
||
"gotest.tools/v3/assert" | ||
) | ||
|
||
func TestValidateUserSettable(t *testing.T) { | ||
t.Parallel() | ||
for _, tt := range []struct { | ||
id string | ||
errorContains string | ||
}{ | ||
{id: "abcd"}, | ||
{id: "abcd-efgh-1234"}, | ||
{id: "abc", errorContains: "must be between 4 and 63 characters"}, | ||
{id: "-abc", errorContains: "must not start with a hyphen"}, | ||
{id: "daf1cb3e-f33b-43f1-81cc-e65fda51efa5", errorContains: "must not be a valid UUIDv4"}, | ||
{id: "abcd/efgh", errorContains: "must only contain lowercase, numbers and hyphens"}, | ||
} { | ||
tt := tt | ||
t.Run(tt.id, func(t *testing.T) { | ||
t.Parallel() | ||
err := ValidateUserSettable(tt.id) | ||
if tt.errorContains != "" { | ||
assert.ErrorContains(t, err, tt.errorContains) | ||
} else { | ||
assert.NilError(t, err) | ||
} | ||
}) | ||
} | ||
} |