-
Notifications
You must be signed in to change notification settings - Fork 23
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
feat: scheduler (9/): add uniquename utility for preparing binding na…
…mes (#404)
- Loading branch information
1 parent
4104a44
commit b9a39e9
Showing
2 changed files
with
136 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
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,57 @@ | ||
/* | ||
Copyright (c) Microsoft Corporation. | ||
Licensed under the MIT license. | ||
*/ | ||
|
||
// package uniquename features some utilities that are used to generate unique names in use | ||
// by the scheduler. | ||
package uniquename | ||
|
||
import ( | ||
"fmt" | ||
|
||
"k8s.io/apimachinery/pkg/util/uuid" | ||
"k8s.io/apimachinery/pkg/util/validation" | ||
) | ||
|
||
const ( | ||
uuidLength = 6 | ||
) | ||
|
||
// minInt returns the smaller one of two integers. | ||
func minInt(a, b int) int { | ||
if a < b { | ||
return a | ||
} | ||
return b | ||
} | ||
|
||
// NewClusterResourceBindingName returns a unique name for a cluster resource binding in the | ||
// format of DNS subdomain names (RFC 1123). | ||
// | ||
// The name is generated using the following format: | ||
// * [CRP-NAME] - [TARGET-CLUSTER-NAME] - [RANDOM-SUFFIX] | ||
// | ||
// Segments will be truncated if necessary. | ||
// | ||
// Note that the name generation is, in essence, a best-effort process, though the chances | ||
// of name collisions are extremely low. | ||
// | ||
// In addition, note that this function assumes that both the CRP name and the cluster name | ||
// are valid DNS subdomain names (RFC 1123). | ||
func NewClusterResourceBindingName(CRPName string, clusterName string) (string, error) { | ||
reservedSlots := 2 + uuidLength // 2 dashs + 6 character UUID string | ||
|
||
slotsPerSeg := (validation.DNS1123SubdomainMaxLength - reservedSlots) / 2 | ||
uniqueName := fmt.Sprintf("%s-%s-%s", | ||
CRPName[:minInt(slotsPerSeg, len(CRPName))], | ||
clusterName[:minInt(slotsPerSeg, len(clusterName))], | ||
uuid.NewUUID()[:uuidLength], | ||
) | ||
|
||
if errs := validation.IsDNS1123Subdomain(uniqueName); len(errs) != 0 { | ||
// Do a sanity check here; normally this would not occur. | ||
return "", fmt.Errorf("failed to format a unique RFC 1123 DNS subdomain name with namespace %s, name %s: %v", CRPName, clusterName, errs) | ||
} | ||
return uniqueName, 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,79 @@ | ||
/* | ||
Copyright (c) Microsoft Corporation. | ||
Licensed under the MIT license. | ||
*/ | ||
|
||
package uniquename | ||
|
||
import ( | ||
"fmt" | ||
"strings" | ||
"testing" | ||
) | ||
|
||
const ( | ||
crpName = "app" | ||
clusterName = "bravelion" | ||
|
||
longName = "c7t2c6oppjnryqcihwweexeobs7tlmf08ha4qb5htc4cifzpalhb5ec2lbh3" + | ||
"j73reciaz2f0jfd2rl5qba6rzuuwgyw6d9e6la19bo89k41lphln4s4dy1gr" + | ||
"h1dvua17iu4ro61dxo91ayovns8cgnmshlsflmi68e3najm7dw5dqe17pih7" + | ||
"up0dtyvrqxyp90sxedbf" | ||
) | ||
|
||
// TO-DO (chenyu1): Expand the test cases as development proceeds. | ||
|
||
// TestClusterResourceBindingUniqueName tests the ClusterResourceBindingUniqueName function. | ||
func TestClusterResourceBindingUniqueName(t *testing.T) { | ||
testCases := []struct { | ||
name string | ||
crpName string | ||
clusterName string | ||
wantPrefix string | ||
wantLength int | ||
expectedToFail bool | ||
}{ | ||
{ | ||
name: "valid name", | ||
crpName: crpName, | ||
clusterName: clusterName, | ||
wantPrefix: fmt.Sprintf("%s-%s", crpName, clusterName), | ||
wantLength: len(crpName) + len(clusterName) + 2 + uuidLength, | ||
}, | ||
{ | ||
name: "valid name (truncated)", | ||
crpName: longName, | ||
clusterName: longName, | ||
wantPrefix: fmt.Sprintf("%s-%s", longName[:122], longName[:122]), | ||
wantLength: 252, | ||
}, | ||
{ | ||
name: "invalid name", | ||
crpName: crpName, | ||
clusterName: clusterName + "!", | ||
expectedToFail: true, | ||
}, | ||
} | ||
|
||
for _, tc := range testCases { | ||
t.Run(tc.name, func(t *testing.T) { | ||
name, err := NewClusterResourceBindingName(tc.crpName, tc.clusterName) | ||
|
||
if tc.expectedToFail { | ||
if err == nil { | ||
t.Errorf("ClusterResourceBindingUniqueName(%s, %s) = %v, %v, want error", tc.crpName, tc.clusterName, name, err) | ||
} | ||
return | ||
} | ||
if err != nil { | ||
t.Errorf("ClusterResourceBindingUniqueName(%s, %s) = %v, %v, want no error", tc.crpName, tc.clusterName, name, err) | ||
} | ||
if !strings.HasPrefix(name, tc.wantPrefix) { | ||
t.Errorf("ClusterResourceBindingUniqueName(%s, %s) = %s, want to have prefix %s", tc.crpName, tc.clusterName, name, tc.wantPrefix) | ||
} | ||
if len(name) != tc.wantLength { | ||
t.Errorf("ClusterResourceBindingUniqueName(%s, %s) = %s, want to have length %d", tc.crpName, tc.clusterName, name, tc.wantLength) | ||
} | ||
}) | ||
} | ||
} |