ConfigMap resource and its REST implementation

This commit is contained in:
Tamer Tas
2015-04-01 00:36:25 +03:00
committed by Paul Morie
parent 7242cf96fa
commit c798a6ef01
17 changed files with 917 additions and 0 deletions

View File

@@ -65,6 +65,8 @@ func addKnownTypes() {
&Ingress{},
&IngressList{},
&api.ListOptions{},
&ConfigMap{},
&ConfigMapList{},
)
}
@@ -86,3 +88,5 @@ func (obj *ThirdPartyResourceData) GetObjectKind() unversioned.ObjectKind {
func (obj *ThirdPartyResourceDataList) GetObjectKind() unversioned.ObjectKind { return &obj.TypeMeta }
func (obj *Ingress) GetObjectKind() unversioned.ObjectKind { return &obj.TypeMeta }
func (obj *IngressList) GetObjectKind() unversioned.ObjectKind { return &obj.TypeMeta }
func (obj *ConfigMap) GetObjectKind() unversioned.ObjectKind { return &obj.TypeMeta }
func (obj *ConfigMapList) GetObjectKind() unversioned.ObjectKind { return &obj.TypeMeta }

View File

@@ -691,3 +691,26 @@ const (
LabelSelectorOpExists LabelSelectorOperator = "Exists"
LabelSelectorOpDoesNotExist LabelSelectorOperator = "DoesNotExist"
)
// ConfigMap holds configuration data for components or applications to consume.
type ConfigMap struct {
unversioned.TypeMeta `json:",inline"`
// Standard object metadata; More info: http://releases.k8s.io/HEAD/docs/devel/api-conventions.md#metadata.
api.ObjectMeta `json:"metadata,omitempty"`
// Data contains the configuration data.
// Each key must be a valid DNS_SUBDOMAIN with an optional leading dot.
Data map[string]string `json:"data,omitempty"`
}
// ConfigMapList is a resource containing a list of ConfigMap objects.
type ConfigMapList struct {
unversioned.TypeMeta `json:",inline"`
// More info: http://releases.k8s.io/HEAD/docs/devel/api-conventions.md#metadata
unversioned.ListMeta `json:"metadata,omitempty"`
// Items is the list of ConfigMaps.
Items []ConfigMap `json:"items,omitempty"`
}

View File

@@ -118,5 +118,10 @@ func addDefaultingFuncs() {
obj.Spec.CPUUtilization = &CPUTargetUtilization{TargetPercentage: 80}
}
},
func(obj *ConfigMap) {
if obj.Data == nil {
obj.Data = make(map[string]string)
}
},
)
}

View File

@@ -58,6 +58,8 @@ func addKnownTypes() {
&Ingress{},
&IngressList{},
&ListOptions{},
&ConfigMap{},
&ConfigMapList{},
)
}
@@ -80,3 +82,5 @@ func (obj *ThirdPartyResourceDataList) GetObjectKind() unversioned.ObjectKind {
func (obj *Ingress) GetObjectKind() unversioned.ObjectKind { return &obj.TypeMeta }
func (obj *IngressList) GetObjectKind() unversioned.ObjectKind { return &obj.TypeMeta }
func (obj *ListOptions) GetObjectKind() unversioned.ObjectKind { return &obj.TypeMeta }
func (obj *ConfigMap) GetObjectKind() unversioned.ObjectKind { return &obj.TypeMeta }
func (obj *ConfigMapList) GetObjectKind() unversioned.ObjectKind { return &obj.TypeMeta }

View File

@@ -719,3 +719,26 @@ const (
LabelSelectorOpExists LabelSelectorOperator = "Exists"
LabelSelectorOpDoesNotExist LabelSelectorOperator = "DoesNotExist"
)
// ConfigMap holds configuration data for pods to consume.
type ConfigMap struct {
unversioned.TypeMeta `json:",inline"`
// Standard object metadata; More info: http://releases.k8s.io/HEAD/docs/devel/api-conventions.md#metadata.
v1.ObjectMeta `json:"metadata,omitempty"`
// Data contains the configuration data.
// Each key must be a valid DNS_SUBDOMAIN with an optional leading dot.
Data map[string]string `json:"data,omitempty"`
}
// ConfigMapList is a resource containing a list of ConfigMap objects.
type ConfigMapList struct {
unversioned.TypeMeta `json:",inline"`
// More info: http://releases.k8s.io/HEAD/docs/devel/api-conventions.md#metadata
unversioned.ListMeta `json:"metadata,omitempty"`
// Items is the list of ConfigMaps.
Items []ConfigMap `json:"items,omitempty"`
}

View File

@@ -17,6 +17,7 @@ limitations under the License.
package validation
import (
"fmt"
"net"
"regexp"
"strconv"
@@ -593,3 +594,33 @@ func ValidateScale(scale *extensions.Scale) field.ErrorList {
return allErrs
}
// ValidateConfigMapName can be used to check whether the given ConfigMap name is valid.
// Prefix indicates this name will be used as part of generation, in which case
// trailing dashes are allowed.
func ValidateConfigMapName(name string, prefix bool) (bool, string) {
return apivalidation.NameIsDNSSubdomain(name, prefix)
}
// ValidateConfigMap tests whether required fields in the ConfigMap are set.
func ValidateConfigMap(cfg *extensions.ConfigMap) field.ErrorList {
allErrs := field.ErrorList{}
allErrs = append(allErrs, apivalidation.ValidateObjectMeta(&cfg.ObjectMeta, true, ValidateConfigMapName, field.NewPath("metadata"))...)
for key := range cfg.Data {
if !apivalidation.IsSecretKey(key) {
allErrs = append(allErrs, field.Invalid(field.NewPath("data").Key(key), key, fmt.Sprintf("must have at most %d characters and match regex %s", validation.DNS1123SubdomainMaxLength, apivalidation.SecretKeyFmt)))
}
}
return allErrs
}
// ValidateConfigMapUpdate tests if required fields in the ConfigMap are set.
func ValidateConfigMapUpdate(newCfg, oldCfg *extensions.ConfigMap) field.ErrorList {
allErrs := field.ErrorList{}
allErrs = append(allErrs, apivalidation.ValidateObjectMetaUpdate(&newCfg.ObjectMeta, &oldCfg.ObjectMeta, field.NewPath("metadata"))...)
allErrs = append(allErrs, ValidateConfigMap(newCfg)...)
return allErrs
}

View File

@@ -1300,3 +1300,105 @@ func newInt(val int) *int {
*p = val
return p
}
func TestValidateConfigMap(t *testing.T) {
newConfigMap := func(name, namespace string, data map[string]string) extensions.ConfigMap {
return extensions.ConfigMap{
ObjectMeta: api.ObjectMeta{
Name: name,
Namespace: namespace,
},
Data: data,
}
}
var (
validConfigMap = newConfigMap("validname", "validns", map[string]string{"key": "value"})
maxKeyLength = newConfigMap("validname", "validns", map[string]string{strings.Repeat("a", 253): "value"})
emptyName = newConfigMap("", "validns", nil)
invalidName = newConfigMap("NoUppercaseOrSpecialCharsLike=Equals", "validns", nil)
emptyNs = newConfigMap("validname", "", nil)
invalidNs = newConfigMap("validname", "NoUppercaseOrSpecialCharsLike=Equals", nil)
invalidKey = newConfigMap("validname", "validns", map[string]string{"a..b": "value"})
leadingDotKey = newConfigMap("validname", "validns", map[string]string{".ab": "value"})
dotKey = newConfigMap("validname", "validns", map[string]string{".": "value"})
doubleDotKey = newConfigMap("validname", "validns", map[string]string{"..": "value"})
overMaxKeyLength = newConfigMap("validname", "validns", map[string]string{strings.Repeat("a", 254): "value"})
)
tests := map[string]struct {
cfg extensions.ConfigMap
isValid bool
}{
"valid": {validConfigMap, true},
"max key length": {maxKeyLength, true},
"leading dot key": {leadingDotKey, true},
"empty name": {emptyName, false},
"invalid name": {invalidName, false},
"invalid key": {invalidKey, false},
"empty namespace": {emptyNs, false},
"invalid namespace": {invalidNs, false},
"dot key": {dotKey, false},
"double dot key": {doubleDotKey, false},
"over max key length": {overMaxKeyLength, false},
}
for name, tc := range tests {
errs := ValidateConfigMap(&tc.cfg)
if tc.isValid && len(errs) > 0 {
t.Errorf("%v: unexpected error: %v", name, errs)
}
if !tc.isValid && len(errs) == 0 {
t.Errorf("%v: unexpected non-error", name)
}
}
}
func TestValidateConfigMapUpdate(t *testing.T) {
newConfigMap := func(version, name, namespace string, data map[string]string) extensions.ConfigMap {
return extensions.ConfigMap{
ObjectMeta: api.ObjectMeta{
Name: name,
Namespace: namespace,
ResourceVersion: version,
},
Data: data,
}
}
var (
validConfigMap = newConfigMap("1", "validname", "validns", map[string]string{"key": "value"})
noVersion = newConfigMap("", "validname", "validns", map[string]string{"key": "value"})
)
cases := []struct {
name string
newCfg extensions.ConfigMap
oldCfg extensions.ConfigMap
isValid bool
}{
{
name: "valid",
newCfg: validConfigMap,
oldCfg: validConfigMap,
isValid: true,
},
{
name: "invalid",
newCfg: noVersion,
oldCfg: validConfigMap,
isValid: false,
},
}
for _, tc := range cases {
errs := ValidateConfigMapUpdate(&tc.newCfg, &tc.oldCfg)
if tc.isValid && len(errs) > 0 {
t.Errorf("%v: unexpected error: %v", tc.name, errs)
}
if !tc.isValid && len(errs) == 0 {
t.Errorf("%v: unexpected non-error", tc.name)
}
}
}