mirror of
https://github.com/k3s-io/kubernetes.git
synced 2025-08-14 14:23:37 +00:00
Merge pull request #3588 from vishh/api_resources
Adding a 'Typename' strongtype for representing all resource types
This commit is contained in:
commit
5d73fa40aa
@ -21,6 +21,7 @@ import (
|
|||||||
|
|
||||||
"github.com/GoogleCloudPlatform/kubernetes/pkg/api/resource"
|
"github.com/GoogleCloudPlatform/kubernetes/pkg/api/resource"
|
||||||
"github.com/GoogleCloudPlatform/kubernetes/pkg/conversion"
|
"github.com/GoogleCloudPlatform/kubernetes/pkg/conversion"
|
||||||
|
"github.com/GoogleCloudPlatform/kubernetes/pkg/util"
|
||||||
|
|
||||||
"github.com/davecgh/go-spew/spew"
|
"github.com/davecgh/go-spew/spew"
|
||||||
)
|
)
|
||||||
@ -60,3 +61,9 @@ var Semantic = conversion.EqualitiesOrDie(
|
|||||||
return a.Amount.Cmp(b.Amount) == 0
|
return a.Amount.Cmp(b.Amount) == 0
|
||||||
},
|
},
|
||||||
)
|
)
|
||||||
|
|
||||||
|
var standardResources = util.NewStringSet(string(ResourceMemory), string(ResourceCPU))
|
||||||
|
|
||||||
|
func IsStandardResourceName(str string) bool {
|
||||||
|
return standardResources.Has(str)
|
||||||
|
}
|
||||||
|
@ -67,3 +67,21 @@ func TestSemantic(t *testing.T) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestIsStandardResource(t *testing.T) {
|
||||||
|
testCases := []struct {
|
||||||
|
input string
|
||||||
|
output bool
|
||||||
|
}{
|
||||||
|
{"cpu", true},
|
||||||
|
{"memory", true},
|
||||||
|
{"disk", false},
|
||||||
|
{"blah", false},
|
||||||
|
{"x.y.z", false},
|
||||||
|
}
|
||||||
|
for i, tc := range testCases {
|
||||||
|
if IsStandardResourceName(tc.input) != tc.output {
|
||||||
|
t.Errorf("case[%d], expected: %t, got: %t", i, tc.output, !tc.output)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
@ -764,6 +764,8 @@ type NodeResources struct {
|
|||||||
type ResourceName string
|
type ResourceName string
|
||||||
|
|
||||||
const (
|
const (
|
||||||
|
// The default compute resource namespace for all standard resource types.
|
||||||
|
DefaultResourceNamespace = "kubernetes.io"
|
||||||
// CPU, in cores. (500m = .5 cores)
|
// CPU, in cores. (500m = .5 cores)
|
||||||
ResourceCPU ResourceName = "cpu"
|
ResourceCPU ResourceName = "cpu"
|
||||||
// Memory, in bytes. (500Gi = 500GiB = 500 * 1024 * 1024 * 1024)
|
// Memory, in bytes. (500Gi = 500GiB = 500 * 1024 * 1024 * 1024)
|
||||||
|
@ -785,6 +785,8 @@ type NodeCondition struct {
|
|||||||
type ResourceName string
|
type ResourceName string
|
||||||
|
|
||||||
const (
|
const (
|
||||||
|
// The default compute resource namespace for all standard resource types.
|
||||||
|
DefaultResourceNamespace = "kubernetes.io"
|
||||||
// CPU, in cores. (500m = .5 cores)
|
// CPU, in cores. (500m = .5 cores)
|
||||||
ResourceCPU ResourceName = "cpu"
|
ResourceCPU ResourceName = "cpu"
|
||||||
// Memory, in bytes. (500Gi = 500GiB = 500 * 1024 * 1024 * 1024)
|
// Memory, in bytes. (500Gi = 500GiB = 500 * 1024 * 1024 * 1024)
|
||||||
|
@ -622,3 +622,30 @@ func ValidateMinionUpdate(oldMinion *api.Node, minion *api.Node) errs.Validation
|
|||||||
}
|
}
|
||||||
return allErrs
|
return allErrs
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Typename is a generic representation for all compute resource typenames.
|
||||||
|
// Refer to docs/resources.md for more details.
|
||||||
|
func ValidateResourceName(str string) errs.ValidationErrorList {
|
||||||
|
if !util.IsQualifiedName(str) {
|
||||||
|
return errs.ValidationErrorList{fmt.Errorf("invalid compute resource typename format %q", str)}
|
||||||
|
}
|
||||||
|
|
||||||
|
parts := strings.Split(str, "/")
|
||||||
|
switch len(parts) {
|
||||||
|
case 1:
|
||||||
|
if !api.IsStandardResourceName(parts[0]) {
|
||||||
|
return errs.ValidationErrorList{fmt.Errorf("invalid compute resource typename. %q is neither a standard resource type nor is fully qualified", str)}
|
||||||
|
}
|
||||||
|
break
|
||||||
|
case 2:
|
||||||
|
if parts[0] == api.DefaultResourceNamespace {
|
||||||
|
if !api.IsStandardResourceName(parts[1]) {
|
||||||
|
return errs.ValidationErrorList{fmt.Errorf("invalid compute resource typename. %q contains a compute resource type not supported", str)}
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
break
|
||||||
|
}
|
||||||
|
|
||||||
|
return errs.ValidationErrorList{}
|
||||||
|
}
|
||||||
|
@ -1440,3 +1440,40 @@ func TestValidateMinionUpdate(t *testing.T) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestValidateResourceNames(t *testing.T) {
|
||||||
|
longString := "a"
|
||||||
|
for i := 0; i < 6; i++ {
|
||||||
|
longString += longString
|
||||||
|
}
|
||||||
|
table := []struct {
|
||||||
|
input string
|
||||||
|
success bool
|
||||||
|
}{
|
||||||
|
{"memory", true},
|
||||||
|
{"cpu", true},
|
||||||
|
{"network", false},
|
||||||
|
{"disk", false},
|
||||||
|
{"", false},
|
||||||
|
{".", false},
|
||||||
|
{"..", false},
|
||||||
|
{"kubernetes.io/cpu", true},
|
||||||
|
{"kubernetes.io/disk", false},
|
||||||
|
{"my.favorite.app.co/12345", true},
|
||||||
|
{"my.favorite.app.co/_12345", false},
|
||||||
|
{"my.favorite.app.co/12345_", false},
|
||||||
|
{"kubernetes.io/..", false},
|
||||||
|
{"kubernetes.io/" + longString, false},
|
||||||
|
{"kubernetes.io//", false},
|
||||||
|
{"kubernetes.io", false},
|
||||||
|
{"kubernetes.io/will/not/work/", false},
|
||||||
|
}
|
||||||
|
for _, item := range table {
|
||||||
|
err := ValidateResourceName(item.input)
|
||||||
|
if len(err) != 0 && item.success {
|
||||||
|
t.Errorf("expected no failure for input %q", item.input)
|
||||||
|
} else if len(err) == 0 && !item.success {
|
||||||
|
t.Errorf("expected failure for input %q", item.input)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
@ -20,10 +20,12 @@ import (
|
|||||||
"encoding/json"
|
"encoding/json"
|
||||||
"fmt"
|
"fmt"
|
||||||
"io/ioutil"
|
"io/ioutil"
|
||||||
|
"path"
|
||||||
"reflect"
|
"reflect"
|
||||||
"regexp"
|
"regexp"
|
||||||
"runtime"
|
"runtime"
|
||||||
"strconv"
|
"strconv"
|
||||||
|
"strings"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"github.com/golang/glog"
|
"github.com/golang/glog"
|
||||||
@ -183,3 +185,20 @@ func AllPtrFieldsNil(obj interface{}) bool {
|
|||||||
}
|
}
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Splits a fully qualified name and returns its namespace and name.
|
||||||
|
// Assumes that the input 'str' has been validated.
|
||||||
|
func SplitQualifiedName(str string) (string, string) {
|
||||||
|
parts := strings.Split(str, "/")
|
||||||
|
if len(parts) < 2 {
|
||||||
|
return "", str
|
||||||
|
}
|
||||||
|
|
||||||
|
return parts[0], parts[1]
|
||||||
|
}
|
||||||
|
|
||||||
|
// Joins 'namespace' and 'name' and returns a fully qualified name
|
||||||
|
// Assumes that the input is valid.
|
||||||
|
func JoinQualifiedName(namespace, name string) string {
|
||||||
|
return path.Join(namespace, name)
|
||||||
|
}
|
||||||
|
@ -263,3 +263,37 @@ func TestAllPtrFieldsNil(t *testing.T) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestSplitQualifiedName(t *testing.T) {
|
||||||
|
testCases := []struct {
|
||||||
|
input string
|
||||||
|
output []string
|
||||||
|
}{
|
||||||
|
{"kubernetes.io/blah", []string{"kubernetes.io", "blah"}},
|
||||||
|
{"blah", []string{"", "blah"}},
|
||||||
|
{"kubernetes.io/blah/blah", []string{"kubernetes.io", "blah"}},
|
||||||
|
}
|
||||||
|
for i, tc := range testCases {
|
||||||
|
namespace, name := SplitQualifiedName(tc.input)
|
||||||
|
if namespace != tc.output[0] || name != tc.output[1] {
|
||||||
|
t.Errorf("case[%d]: expected (%q, %q), got (%q, %q)", i, tc.output[0], tc.output[1], namespace, name)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestJoinQualifiedName(t *testing.T) {
|
||||||
|
testCases := []struct {
|
||||||
|
input []string
|
||||||
|
output string
|
||||||
|
}{
|
||||||
|
{[]string{"kubernetes.io", "blah"}, "kubernetes.io/blah"},
|
||||||
|
{[]string{"blah", ""}, "blah"},
|
||||||
|
{[]string{"kubernetes.io", "blah"}, "kubernetes.io/blah"},
|
||||||
|
}
|
||||||
|
for i, tc := range testCases {
|
||||||
|
res := JoinQualifiedName(tc.input[0], tc.input[1])
|
||||||
|
if res != tc.output {
|
||||||
|
t.Errorf("case[%d]: expected %q, got %q", i, tc.output, res)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user