mirror of
https://github.com/k3s-io/kubernetes.git
synced 2026-01-06 07:57:35 +00:00
ConfigMap resource and its REST implementation
This commit is contained in:
@@ -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 }
|
||||
|
||||
@@ -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"`
|
||||
}
|
||||
|
||||
@@ -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)
|
||||
}
|
||||
},
|
||||
)
|
||||
}
|
||||
|
||||
@@ -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 }
|
||||
|
||||
@@ -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"`
|
||||
}
|
||||
|
||||
@@ -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
|
||||
}
|
||||
|
||||
@@ -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)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user