mirror of
https://github.com/k3s-io/kubernetes.git
synced 2025-07-21 10:51:29 +00:00
explicit kubelet config key in Node.Spec.ConfigSource.ConfigMap
This makes the Kubelet config key in the ConfigMap an explicit part of the API, so we can stop using magic key names. As part of this change, we are retiring ConfigMapRef for ConfigMap.
This commit is contained in:
parent
dc7f074213
commit
c41cf55a2c
52
api/openapi-spec/swagger.json
generated
52
api/openapi-spec/swagger.json
generated
@ -75671,6 +75671,36 @@
|
|||||||
}
|
}
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
|
"io.k8s.api.core.v1.ConfigMapNodeConfigSource": {
|
||||||
|
"description": "ConfigMapNodeConfigSource contains the information to reference a ConfigMap as a config source for the Node.",
|
||||||
|
"required": [
|
||||||
|
"namespace",
|
||||||
|
"name",
|
||||||
|
"kubeletConfigKey"
|
||||||
|
],
|
||||||
|
"properties": {
|
||||||
|
"kubeletConfigKey": {
|
||||||
|
"description": "KubeletConfigKey declares which key of the referenced ConfigMap corresponds to the KubeletConfiguration structure This field is required in all cases.",
|
||||||
|
"type": "string"
|
||||||
|
},
|
||||||
|
"name": {
|
||||||
|
"description": "Name is the metadata.name of the referenced ConfigMap. This field is required in all cases.",
|
||||||
|
"type": "string"
|
||||||
|
},
|
||||||
|
"namespace": {
|
||||||
|
"description": "Namespace is the metadata.namespace of the referenced ConfigMap. This field is required in all cases.",
|
||||||
|
"type": "string"
|
||||||
|
},
|
||||||
|
"resourceVersion": {
|
||||||
|
"description": "ResourceVersion is the metadata.ResourceVersion of the referenced ConfigMap. This field is forbidden in Node.Spec.",
|
||||||
|
"type": "string"
|
||||||
|
},
|
||||||
|
"uid": {
|
||||||
|
"description": "UID is the metadata.UID of the referenced ConfigMap. This field is currently reqired in Node.Spec.",
|
||||||
|
"type": "string"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
"io.k8s.api.core.v1.ConfigMapProjection": {
|
"io.k8s.api.core.v1.ConfigMapProjection": {
|
||||||
"description": "Adapts a ConfigMap into a projected volume.\n\nThe contents of the target ConfigMap's Data field will be presented in a projected volume as files using the keys in the Data field as the file names, unless the items element is populated with specific mappings of keys to paths. Note that this is identical to a configmap volume source without the default mode.",
|
"description": "Adapts a ConfigMap into a projected volume.\n\nThe contents of the target ConfigMap's Data field will be presented in a projected volume as files using the keys in the Data field as the file names, unless the items element is populated with specific mappings of keys to paths. Note that this is identical to a configmap volume source without the default mode.",
|
||||||
"properties": {
|
"properties": {
|
||||||
@ -77242,25 +77272,11 @@
|
|||||||
"io.k8s.api.core.v1.NodeConfigSource": {
|
"io.k8s.api.core.v1.NodeConfigSource": {
|
||||||
"description": "NodeConfigSource specifies a source of node configuration. Exactly one subfield (excluding metadata) must be non-nil.",
|
"description": "NodeConfigSource specifies a source of node configuration. Exactly one subfield (excluding metadata) must be non-nil.",
|
||||||
"properties": {
|
"properties": {
|
||||||
"apiVersion": {
|
"configMap": {
|
||||||
"description": "APIVersion defines the versioned schema of this representation of an object. Servers should convert recognized schemas to the latest internal value, and may reject unrecognized values. More info: https://git.k8s.io/community/contributors/devel/api-conventions.md#resources",
|
"description": "ConfigMap is a reference to a Node's ConfigMap",
|
||||||
"type": "string"
|
"$ref": "#/definitions/io.k8s.api.core.v1.ConfigMapNodeConfigSource"
|
||||||
},
|
|
||||||
"configMapRef": {
|
|
||||||
"$ref": "#/definitions/io.k8s.api.core.v1.ObjectReference"
|
|
||||||
},
|
|
||||||
"kind": {
|
|
||||||
"description": "Kind is a string value representing the REST resource this object represents. Servers may infer this from the endpoint the client submits requests to. Cannot be updated. In CamelCase. More info: https://git.k8s.io/community/contributors/devel/api-conventions.md#types-kinds",
|
|
||||||
"type": "string"
|
|
||||||
}
|
}
|
||||||
},
|
}
|
||||||
"x-kubernetes-group-version-kind": [
|
|
||||||
{
|
|
||||||
"group": "",
|
|
||||||
"kind": "NodeConfigSource",
|
|
||||||
"version": "v1"
|
|
||||||
}
|
|
||||||
]
|
|
||||||
},
|
},
|
||||||
"io.k8s.api.core.v1.NodeDaemonEndpoints": {
|
"io.k8s.api.core.v1.NodeDaemonEndpoints": {
|
||||||
"description": "NodeDaemonEndpoints lists ports opened by daemons running on the Node.",
|
"description": "NodeDaemonEndpoints lists ports opened by daemons running on the Node.",
|
||||||
|
36
api/swagger-spec/v1.json
generated
36
api/swagger-spec/v1.json
generated
@ -18718,16 +18718,40 @@
|
|||||||
"id": "v1.NodeConfigSource",
|
"id": "v1.NodeConfigSource",
|
||||||
"description": "NodeConfigSource specifies a source of node configuration. Exactly one subfield (excluding metadata) must be non-nil.",
|
"description": "NodeConfigSource specifies a source of node configuration. Exactly one subfield (excluding metadata) must be non-nil.",
|
||||||
"properties": {
|
"properties": {
|
||||||
"kind": {
|
"configMap": {
|
||||||
|
"$ref": "v1.ConfigMapNodeConfigSource",
|
||||||
|
"description": "ConfigMap is a reference to a Node's ConfigMap"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"v1.ConfigMapNodeConfigSource": {
|
||||||
|
"id": "v1.ConfigMapNodeConfigSource",
|
||||||
|
"description": "ConfigMapNodeConfigSource contains the information to reference a ConfigMap as a config source for the Node.",
|
||||||
|
"required": [
|
||||||
|
"namespace",
|
||||||
|
"name",
|
||||||
|
"kubeletConfigKey"
|
||||||
|
],
|
||||||
|
"properties": {
|
||||||
|
"namespace": {
|
||||||
"type": "string",
|
"type": "string",
|
||||||
"description": "Kind is a string value representing the REST resource this object represents. Servers may infer this from the endpoint the client submits requests to. Cannot be updated. In CamelCase. More info: https://git.k8s.io/community/contributors/devel/api-conventions.md#types-kinds"
|
"description": "Namespace is the metadata.namespace of the referenced ConfigMap. This field is required in all cases."
|
||||||
},
|
},
|
||||||
"apiVersion": {
|
"name": {
|
||||||
"type": "string",
|
"type": "string",
|
||||||
"description": "APIVersion defines the versioned schema of this representation of an object. Servers should convert recognized schemas to the latest internal value, and may reject unrecognized values. More info: https://git.k8s.io/community/contributors/devel/api-conventions.md#resources"
|
"description": "Name is the metadata.name of the referenced ConfigMap. This field is required in all cases."
|
||||||
},
|
},
|
||||||
"configMapRef": {
|
"uid": {
|
||||||
"$ref": "v1.ObjectReference"
|
"type": "string",
|
||||||
|
"description": "UID is the metadata.UID of the referenced ConfigMap. This field is currently reqired in Node.Spec."
|
||||||
|
},
|
||||||
|
"resourceVersion": {
|
||||||
|
"type": "string",
|
||||||
|
"description": "ResourceVersion is the metadata.ResourceVersion of the referenced ConfigMap. This field is forbidden in Node.Spec."
|
||||||
|
},
|
||||||
|
"kubeletConfigKey": {
|
||||||
|
"type": "string",
|
||||||
|
"description": "KubeletConfigKey declares which key of the referenced ConfigMap corresponds to the KubeletConfiguration structure This field is required in all cases."
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
@ -116,10 +116,11 @@ func updateNodeWithConfigMap(client clientset.Interface, nodeName string) error
|
|||||||
}
|
}
|
||||||
|
|
||||||
node.Spec.ConfigSource = &v1.NodeConfigSource{
|
node.Spec.ConfigSource = &v1.NodeConfigSource{
|
||||||
ConfigMapRef: &v1.ObjectReference{
|
ConfigMap: &v1.ConfigMapNodeConfigSource{
|
||||||
Name: kubeadmconstants.KubeletBaseConfigurationConfigMap,
|
Name: kubeadmconstants.KubeletBaseConfigurationConfigMap,
|
||||||
Namespace: metav1.NamespaceSystem,
|
Namespace: metav1.NamespaceSystem,
|
||||||
UID: kubeletCfg.UID,
|
UID: kubeletCfg.UID,
|
||||||
|
KubeletConfigKey: kubeadmconstants.KubeletBaseConfigurationConfigMapKey,
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -50,7 +50,7 @@ func TestCreateBaseKubeletConfiguration(t *testing.T) {
|
|||||||
},
|
},
|
||||||
Spec: v1.NodeSpec{
|
Spec: v1.NodeSpec{
|
||||||
ConfigSource: &v1.NodeConfigSource{
|
ConfigSource: &v1.NodeConfigSource{
|
||||||
ConfigMapRef: &v1.ObjectReference{
|
ConfigMap: &v1.ConfigMapNodeConfigSource{
|
||||||
UID: "",
|
UID: "",
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
@ -94,7 +94,7 @@ func TestUpdateNodeWithConfigMap(t *testing.T) {
|
|||||||
},
|
},
|
||||||
Spec: v1.NodeSpec{
|
Spec: v1.NodeSpec{
|
||||||
ConfigSource: &v1.NodeConfigSource{
|
ConfigSource: &v1.NodeConfigSource{
|
||||||
ConfigMapRef: &v1.ObjectReference{
|
ConfigMap: &v1.ConfigMapNodeConfigSource{
|
||||||
UID: "",
|
UID: "",
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
85
docs/api-reference/v1/definitions.html
generated
85
docs/api-reference/v1/definitions.html
generated
@ -403,9 +403,6 @@ span.icon > [class^="icon-"], span.icon > [class*=" icon-"] { cursor: default; }
|
|||||||
<p><a href="#_v1_node">v1.Node</a></p>
|
<p><a href="#_v1_node">v1.Node</a></p>
|
||||||
</li>
|
</li>
|
||||||
<li>
|
<li>
|
||||||
<p><a href="#_v1_nodeconfigsource">v1.NodeConfigSource</a></p>
|
|
||||||
</li>
|
|
||||||
<li>
|
|
||||||
<p><a href="#_v1_nodelist">v1.NodeList</a></p>
|
<p><a href="#_v1_nodelist">v1.NodeList</a></p>
|
||||||
</li>
|
</li>
|
||||||
<li>
|
<li>
|
||||||
@ -3661,6 +3658,68 @@ Examples:<br>
|
|||||||
</tbody>
|
</tbody>
|
||||||
</table>
|
</table>
|
||||||
|
|
||||||
|
</div>
|
||||||
|
<div class="sect2">
|
||||||
|
<h3 id="_v1_configmapnodeconfigsource">v1.ConfigMapNodeConfigSource</h3>
|
||||||
|
<div class="paragraph">
|
||||||
|
<p>ConfigMapNodeConfigSource contains the information to reference a ConfigMap as a config source for the Node.</p>
|
||||||
|
</div>
|
||||||
|
<table class="tableblock frame-all grid-all" style="width:100%; ">
|
||||||
|
<colgroup>
|
||||||
|
<col style="width:20%;">
|
||||||
|
<col style="width:20%;">
|
||||||
|
<col style="width:20%;">
|
||||||
|
<col style="width:20%;">
|
||||||
|
<col style="width:20%;">
|
||||||
|
</colgroup>
|
||||||
|
<thead>
|
||||||
|
<tr>
|
||||||
|
<th class="tableblock halign-left valign-top">Name</th>
|
||||||
|
<th class="tableblock halign-left valign-top">Description</th>
|
||||||
|
<th class="tableblock halign-left valign-top">Required</th>
|
||||||
|
<th class="tableblock halign-left valign-top">Schema</th>
|
||||||
|
<th class="tableblock halign-left valign-top">Default</th>
|
||||||
|
</tr>
|
||||||
|
</thead>
|
||||||
|
<tbody>
|
||||||
|
<tr>
|
||||||
|
<td class="tableblock halign-left valign-top"><p class="tableblock">namespace</p></td>
|
||||||
|
<td class="tableblock halign-left valign-top"><p class="tableblock">Namespace is the metadata.namespace of the referenced ConfigMap. This field is required in all cases.</p></td>
|
||||||
|
<td class="tableblock halign-left valign-top"><p class="tableblock">true</p></td>
|
||||||
|
<td class="tableblock halign-left valign-top"><p class="tableblock">string</p></td>
|
||||||
|
<td class="tableblock halign-left valign-top"></td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td class="tableblock halign-left valign-top"><p class="tableblock">name</p></td>
|
||||||
|
<td class="tableblock halign-left valign-top"><p class="tableblock">Name is the metadata.name of the referenced ConfigMap. This field is required in all cases.</p></td>
|
||||||
|
<td class="tableblock halign-left valign-top"><p class="tableblock">true</p></td>
|
||||||
|
<td class="tableblock halign-left valign-top"><p class="tableblock">string</p></td>
|
||||||
|
<td class="tableblock halign-left valign-top"></td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td class="tableblock halign-left valign-top"><p class="tableblock">uid</p></td>
|
||||||
|
<td class="tableblock halign-left valign-top"><p class="tableblock">UID is the metadata.UID of the referenced ConfigMap. This field is currently reqired in Node.Spec.</p></td>
|
||||||
|
<td class="tableblock halign-left valign-top"><p class="tableblock">false</p></td>
|
||||||
|
<td class="tableblock halign-left valign-top"><p class="tableblock">string</p></td>
|
||||||
|
<td class="tableblock halign-left valign-top"></td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td class="tableblock halign-left valign-top"><p class="tableblock">resourceVersion</p></td>
|
||||||
|
<td class="tableblock halign-left valign-top"><p class="tableblock">ResourceVersion is the metadata.ResourceVersion of the referenced ConfigMap. This field is forbidden in Node.Spec.</p></td>
|
||||||
|
<td class="tableblock halign-left valign-top"><p class="tableblock">false</p></td>
|
||||||
|
<td class="tableblock halign-left valign-top"><p class="tableblock">string</p></td>
|
||||||
|
<td class="tableblock halign-left valign-top"></td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td class="tableblock halign-left valign-top"><p class="tableblock">kubeletConfigKey</p></td>
|
||||||
|
<td class="tableblock halign-left valign-top"><p class="tableblock">KubeletConfigKey declares which key of the referenced ConfigMap corresponds to the KubeletConfiguration structure This field is required in all cases.</p></td>
|
||||||
|
<td class="tableblock halign-left valign-top"><p class="tableblock">true</p></td>
|
||||||
|
<td class="tableblock halign-left valign-top"><p class="tableblock">string</p></td>
|
||||||
|
<td class="tableblock halign-left valign-top"></td>
|
||||||
|
</tr>
|
||||||
|
</tbody>
|
||||||
|
</table>
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
<div class="sect2">
|
<div class="sect2">
|
||||||
<h3 id="_v1_endpointport">v1.EndpointPort</h3>
|
<h3 id="_v1_endpointport">v1.EndpointPort</h3>
|
||||||
@ -5830,24 +5889,10 @@ Examples:<br>
|
|||||||
</thead>
|
</thead>
|
||||||
<tbody>
|
<tbody>
|
||||||
<tr>
|
<tr>
|
||||||
<td class="tableblock halign-left valign-top"><p class="tableblock">kind</p></td>
|
<td class="tableblock halign-left valign-top"><p class="tableblock">configMap</p></td>
|
||||||
<td class="tableblock halign-left valign-top"><p class="tableblock">Kind is a string value representing the REST resource this object represents. Servers may infer this from the endpoint the client submits requests to. Cannot be updated. In CamelCase. More info: <a href="https://git.k8s.io/community/contributors/devel/api-conventions.md#types-kinds">https://git.k8s.io/community/contributors/devel/api-conventions.md#types-kinds</a></p></td>
|
<td class="tableblock halign-left valign-top"><p class="tableblock">ConfigMap is a reference to a Node’s ConfigMap</p></td>
|
||||||
<td class="tableblock halign-left valign-top"><p class="tableblock">false</p></td>
|
<td class="tableblock halign-left valign-top"><p class="tableblock">false</p></td>
|
||||||
<td class="tableblock halign-left valign-top"><p class="tableblock">string</p></td>
|
<td class="tableblock halign-left valign-top"><p class="tableblock"><a href="#_v1_configmapnodeconfigsource">v1.ConfigMapNodeConfigSource</a></p></td>
|
||||||
<td class="tableblock halign-left valign-top"></td>
|
|
||||||
</tr>
|
|
||||||
<tr>
|
|
||||||
<td class="tableblock halign-left valign-top"><p class="tableblock">apiVersion</p></td>
|
|
||||||
<td class="tableblock halign-left valign-top"><p class="tableblock">APIVersion defines the versioned schema of this representation of an object. Servers should convert recognized schemas to the latest internal value, and may reject unrecognized values. More info: <a href="https://git.k8s.io/community/contributors/devel/api-conventions.md#resources">https://git.k8s.io/community/contributors/devel/api-conventions.md#resources</a></p></td>
|
|
||||||
<td class="tableblock halign-left valign-top"><p class="tableblock">false</p></td>
|
|
||||||
<td class="tableblock halign-left valign-top"><p class="tableblock">string</p></td>
|
|
||||||
<td class="tableblock halign-left valign-top"></td>
|
|
||||||
</tr>
|
|
||||||
<tr>
|
|
||||||
<td class="tableblock halign-left valign-top"><p class="tableblock">configMapRef</p></td>
|
|
||||||
<td class="tableblock halign-left valign-top"></td>
|
|
||||||
<td class="tableblock halign-left valign-top"><p class="tableblock">false</p></td>
|
|
||||||
<td class="tableblock halign-left valign-top"><p class="tableblock"><a href="#_v1_objectreference">v1.ObjectReference</a></p></td>
|
|
||||||
<td class="tableblock halign-left valign-top"></td>
|
<td class="tableblock halign-left valign-top"></td>
|
||||||
</tr>
|
</tr>
|
||||||
</tbody>
|
</tbody>
|
||||||
|
@ -60,7 +60,6 @@ func addKnownTypes(scheme *runtime.Scheme) error {
|
|||||||
&ServiceProxyOptions{},
|
&ServiceProxyOptions{},
|
||||||
&NodeList{},
|
&NodeList{},
|
||||||
&Node{},
|
&Node{},
|
||||||
&NodeConfigSource{},
|
|
||||||
&NodeProxyOptions{},
|
&NodeProxyOptions{},
|
||||||
&Endpoints{},
|
&Endpoints{},
|
||||||
&EndpointsList{},
|
&EndpointsList{},
|
||||||
|
@ -3257,12 +3257,48 @@ type NodeSpec struct {
|
|||||||
DoNotUse_ExternalID string
|
DoNotUse_ExternalID string
|
||||||
}
|
}
|
||||||
|
|
||||||
// +k8s:deepcopy-gen:interfaces=k8s.io/apimachinery/pkg/runtime.Object
|
|
||||||
|
|
||||||
// NodeConfigSource specifies a source of node configuration. Exactly one subfield must be non-nil.
|
// NodeConfigSource specifies a source of node configuration. Exactly one subfield must be non-nil.
|
||||||
type NodeConfigSource struct {
|
type NodeConfigSource struct {
|
||||||
metav1.TypeMeta
|
ConfigMap *ConfigMapNodeConfigSource
|
||||||
ConfigMapRef *ObjectReference
|
}
|
||||||
|
|
||||||
|
type ConfigMapNodeConfigSource struct {
|
||||||
|
// Namespace is the metadata.namespace of the referenced ConfigMap.
|
||||||
|
// This field is required in all cases.
|
||||||
|
Namespace string
|
||||||
|
|
||||||
|
// Name is the metadata.name of the referenced ConfigMap.
|
||||||
|
// This field is required in all cases.
|
||||||
|
Name string
|
||||||
|
|
||||||
|
// UID is the metadata.UID of the referenced ConfigMap.
|
||||||
|
// This field is currently reqired in Node.Spec.
|
||||||
|
// TODO(#61643): This field will be forbidden in Node.Spec when #61643 is resolved.
|
||||||
|
// #61643 changes the behavior of dynamic Kubelet config to respect
|
||||||
|
// ConfigMap updates, and thus removes the ability to pin the Spec to a given UID.
|
||||||
|
// TODO(#56896): This field will be required in Node.Status when #56896 is resolved.
|
||||||
|
// #63314 (the PR that resolves #56896) adds a structured status to the Node
|
||||||
|
// object for reporting information about the config. This status requires UID
|
||||||
|
// and ResourceVersion, so that it represents a fully-explicit description of
|
||||||
|
// the configuration in use, while (see previous TODO) the Spec will be
|
||||||
|
// restricted to namespace/name in #61643.
|
||||||
|
// +optional
|
||||||
|
UID types.UID
|
||||||
|
|
||||||
|
// ResourceVersion is the metadata.ResourceVersion of the referenced ConfigMap.
|
||||||
|
// This field is forbidden in Node.Spec.
|
||||||
|
// TODO(#56896): This field will be required in Node.Status when #56896 is resolved.
|
||||||
|
// #63314 (the PR that resolves #56896) adds a structured status to the Node
|
||||||
|
// object for reporting information about the config. This status requires UID
|
||||||
|
// and ResourceVersion, so that it represents a fully-explicit description of
|
||||||
|
// the configuration in use, while (see previous TODO) the Spec will be
|
||||||
|
// restricted to namespace/name in #61643.
|
||||||
|
// +optional
|
||||||
|
ResourceVersion string
|
||||||
|
|
||||||
|
// KubeletConfigKey declares which key of the referenced ConfigMap corresponds to the KubeletConfiguration structure
|
||||||
|
// This field is required in all cases.
|
||||||
|
KubeletConfigKey string
|
||||||
}
|
}
|
||||||
|
|
||||||
// DaemonEndpoint contains information about a single Daemon endpoint.
|
// DaemonEndpoint contains information about a single Daemon endpoint.
|
||||||
|
34
pkg/apis/core/v1/zz_generated.conversion.go
generated
34
pkg/apis/core/v1/zz_generated.conversion.go
generated
@ -82,6 +82,8 @@ func RegisterConversions(scheme *runtime.Scheme) error {
|
|||||||
Convert_core_ConfigMapKeySelector_To_v1_ConfigMapKeySelector,
|
Convert_core_ConfigMapKeySelector_To_v1_ConfigMapKeySelector,
|
||||||
Convert_v1_ConfigMapList_To_core_ConfigMapList,
|
Convert_v1_ConfigMapList_To_core_ConfigMapList,
|
||||||
Convert_core_ConfigMapList_To_v1_ConfigMapList,
|
Convert_core_ConfigMapList_To_v1_ConfigMapList,
|
||||||
|
Convert_v1_ConfigMapNodeConfigSource_To_core_ConfigMapNodeConfigSource,
|
||||||
|
Convert_core_ConfigMapNodeConfigSource_To_v1_ConfigMapNodeConfigSource,
|
||||||
Convert_v1_ConfigMapProjection_To_core_ConfigMapProjection,
|
Convert_v1_ConfigMapProjection_To_core_ConfigMapProjection,
|
||||||
Convert_core_ConfigMapProjection_To_v1_ConfigMapProjection,
|
Convert_core_ConfigMapProjection_To_v1_ConfigMapProjection,
|
||||||
Convert_v1_ConfigMapVolumeSource_To_core_ConfigMapVolumeSource,
|
Convert_v1_ConfigMapVolumeSource_To_core_ConfigMapVolumeSource,
|
||||||
@ -941,6 +943,34 @@ func Convert_core_ConfigMapList_To_v1_ConfigMapList(in *core.ConfigMapList, out
|
|||||||
return autoConvert_core_ConfigMapList_To_v1_ConfigMapList(in, out, s)
|
return autoConvert_core_ConfigMapList_To_v1_ConfigMapList(in, out, s)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func autoConvert_v1_ConfigMapNodeConfigSource_To_core_ConfigMapNodeConfigSource(in *v1.ConfigMapNodeConfigSource, out *core.ConfigMapNodeConfigSource, s conversion.Scope) error {
|
||||||
|
out.Namespace = in.Namespace
|
||||||
|
out.Name = in.Name
|
||||||
|
out.UID = types.UID(in.UID)
|
||||||
|
out.ResourceVersion = in.ResourceVersion
|
||||||
|
out.KubeletConfigKey = in.KubeletConfigKey
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// Convert_v1_ConfigMapNodeConfigSource_To_core_ConfigMapNodeConfigSource is an autogenerated conversion function.
|
||||||
|
func Convert_v1_ConfigMapNodeConfigSource_To_core_ConfigMapNodeConfigSource(in *v1.ConfigMapNodeConfigSource, out *core.ConfigMapNodeConfigSource, s conversion.Scope) error {
|
||||||
|
return autoConvert_v1_ConfigMapNodeConfigSource_To_core_ConfigMapNodeConfigSource(in, out, s)
|
||||||
|
}
|
||||||
|
|
||||||
|
func autoConvert_core_ConfigMapNodeConfigSource_To_v1_ConfigMapNodeConfigSource(in *core.ConfigMapNodeConfigSource, out *v1.ConfigMapNodeConfigSource, s conversion.Scope) error {
|
||||||
|
out.Namespace = in.Namespace
|
||||||
|
out.Name = in.Name
|
||||||
|
out.UID = types.UID(in.UID)
|
||||||
|
out.ResourceVersion = in.ResourceVersion
|
||||||
|
out.KubeletConfigKey = in.KubeletConfigKey
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// Convert_core_ConfigMapNodeConfigSource_To_v1_ConfigMapNodeConfigSource is an autogenerated conversion function.
|
||||||
|
func Convert_core_ConfigMapNodeConfigSource_To_v1_ConfigMapNodeConfigSource(in *core.ConfigMapNodeConfigSource, out *v1.ConfigMapNodeConfigSource, s conversion.Scope) error {
|
||||||
|
return autoConvert_core_ConfigMapNodeConfigSource_To_v1_ConfigMapNodeConfigSource(in, out, s)
|
||||||
|
}
|
||||||
|
|
||||||
func autoConvert_v1_ConfigMapProjection_To_core_ConfigMapProjection(in *v1.ConfigMapProjection, out *core.ConfigMapProjection, s conversion.Scope) error {
|
func autoConvert_v1_ConfigMapProjection_To_core_ConfigMapProjection(in *v1.ConfigMapProjection, out *core.ConfigMapProjection, s conversion.Scope) error {
|
||||||
if err := Convert_v1_LocalObjectReference_To_core_LocalObjectReference(&in.LocalObjectReference, &out.LocalObjectReference, s); err != nil {
|
if err := Convert_v1_LocalObjectReference_To_core_LocalObjectReference(&in.LocalObjectReference, &out.LocalObjectReference, s); err != nil {
|
||||||
return err
|
return err
|
||||||
@ -2586,7 +2616,7 @@ func Convert_core_NodeCondition_To_v1_NodeCondition(in *core.NodeCondition, out
|
|||||||
}
|
}
|
||||||
|
|
||||||
func autoConvert_v1_NodeConfigSource_To_core_NodeConfigSource(in *v1.NodeConfigSource, out *core.NodeConfigSource, s conversion.Scope) error {
|
func autoConvert_v1_NodeConfigSource_To_core_NodeConfigSource(in *v1.NodeConfigSource, out *core.NodeConfigSource, s conversion.Scope) error {
|
||||||
out.ConfigMapRef = (*core.ObjectReference)(unsafe.Pointer(in.ConfigMapRef))
|
out.ConfigMap = (*core.ConfigMapNodeConfigSource)(unsafe.Pointer(in.ConfigMap))
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -2596,7 +2626,7 @@ func Convert_v1_NodeConfigSource_To_core_NodeConfigSource(in *v1.NodeConfigSourc
|
|||||||
}
|
}
|
||||||
|
|
||||||
func autoConvert_core_NodeConfigSource_To_v1_NodeConfigSource(in *core.NodeConfigSource, out *v1.NodeConfigSource, s conversion.Scope) error {
|
func autoConvert_core_NodeConfigSource_To_v1_NodeConfigSource(in *core.NodeConfigSource, out *v1.NodeConfigSource, s conversion.Scope) error {
|
||||||
out.ConfigMapRef = (*v1.ObjectReference)(unsafe.Pointer(in.ConfigMapRef))
|
out.ConfigMap = (*v1.ConfigMapNodeConfigSource)(unsafe.Pointer(in.ConfigMap))
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -4120,7 +4120,7 @@ func ValidateNodeUpdate(node, oldNode *core.Node) field.ErrorList {
|
|||||||
// Allow updates to Node.Spec.ConfigSource if DynamicKubeletConfig feature gate is enabled
|
// Allow updates to Node.Spec.ConfigSource if DynamicKubeletConfig feature gate is enabled
|
||||||
if utilfeature.DefaultFeatureGate.Enabled(features.DynamicKubeletConfig) {
|
if utilfeature.DefaultFeatureGate.Enabled(features.DynamicKubeletConfig) {
|
||||||
if node.Spec.ConfigSource != nil {
|
if node.Spec.ConfigSource != nil {
|
||||||
allErrs = append(allErrs, validateNodeConfigSource(node.Spec.ConfigSource, field.NewPath("spec", "configSource"))...)
|
allErrs = append(allErrs, validateNodeConfigSourceSpec(node.Spec.ConfigSource, field.NewPath("spec", "configSource"))...)
|
||||||
}
|
}
|
||||||
oldNode.Spec.ConfigSource = node.Spec.ConfigSource
|
oldNode.Spec.ConfigSource = node.Spec.ConfigSource
|
||||||
}
|
}
|
||||||
@ -4135,15 +4135,13 @@ func ValidateNodeUpdate(node, oldNode *core.Node) field.ErrorList {
|
|||||||
return allErrs
|
return allErrs
|
||||||
}
|
}
|
||||||
|
|
||||||
func validateNodeConfigSource(source *core.NodeConfigSource, fldPath *field.Path) field.ErrorList {
|
// validation specific to Node.Spec.ConfigSource
|
||||||
|
func validateNodeConfigSourceSpec(source *core.NodeConfigSource, fldPath *field.Path) field.ErrorList {
|
||||||
allErrs := field.ErrorList{}
|
allErrs := field.ErrorList{}
|
||||||
count := int(0)
|
count := int(0)
|
||||||
if ref := source.ConfigMapRef; ref != nil {
|
if source.ConfigMap != nil {
|
||||||
count++
|
count++
|
||||||
// name, namespace, and UID must all be non-empty for ConfigMapRef
|
allErrs = append(allErrs, validateConfigMapNodeConfigSourceSpec(source.ConfigMap, fldPath.Child("configMap"))...)
|
||||||
if ref.Name == "" || ref.Namespace == "" || string(ref.UID) == "" {
|
|
||||||
allErrs = append(allErrs, field.Invalid(fldPath.Child("configMapRef"), ref, "name, namespace, and UID must all be non-empty"))
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
// add more subfields here in the future as they are added to NodeConfigSource
|
// add more subfields here in the future as they are added to NodeConfigSource
|
||||||
|
|
||||||
@ -4154,6 +4152,50 @@ func validateNodeConfigSource(source *core.NodeConfigSource, fldPath *field.Path
|
|||||||
return allErrs
|
return allErrs
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// validation specific to Node.Spec.ConfigSource.ConfigMap
|
||||||
|
func validateConfigMapNodeConfigSourceSpec(source *core.ConfigMapNodeConfigSource, fldPath *field.Path) field.ErrorList {
|
||||||
|
allErrs := field.ErrorList{}
|
||||||
|
// TODO(#61643): Prevent ref.UID from being set here when we switch from requiring UID to respecting all ConfigMap updates
|
||||||
|
if string(source.UID) == "" {
|
||||||
|
allErrs = append(allErrs, field.Required(fldPath.Child("uid"), "uid must be set in spec"))
|
||||||
|
}
|
||||||
|
// resourceVersion must not be set in spec
|
||||||
|
if source.ResourceVersion != "" {
|
||||||
|
allErrs = append(allErrs, field.Forbidden(fldPath.Child("resourceVersion"), "resourceVersion must not be set in spec"))
|
||||||
|
}
|
||||||
|
return append(allErrs, validateConfigMapNodeConfigSource(source, fldPath)...)
|
||||||
|
}
|
||||||
|
|
||||||
|
// common validation
|
||||||
|
func validateConfigMapNodeConfigSource(source *core.ConfigMapNodeConfigSource, fldPath *field.Path) field.ErrorList {
|
||||||
|
allErrs := field.ErrorList{}
|
||||||
|
// validate target configmap namespace
|
||||||
|
if source.Namespace == "" {
|
||||||
|
allErrs = append(allErrs, field.Required(fldPath.Child("namespace"), "namespace must be set in spec"))
|
||||||
|
} else {
|
||||||
|
for _, msg := range ValidateNameFunc(ValidateNamespaceName)(source.Namespace, false) {
|
||||||
|
allErrs = append(allErrs, field.Invalid(fldPath.Child("namespace"), source.Namespace, msg))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// validate target configmap name
|
||||||
|
if source.Name == "" {
|
||||||
|
allErrs = append(allErrs, field.Required(fldPath.Child("name"), "name must be set in spec"))
|
||||||
|
} else {
|
||||||
|
for _, msg := range ValidateNameFunc(ValidateConfigMapName)(source.Name, false) {
|
||||||
|
allErrs = append(allErrs, field.Invalid(fldPath.Child("name"), source.Name, msg))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// validate kubeletConfigKey against rules for configMap key names
|
||||||
|
if source.KubeletConfigKey == "" {
|
||||||
|
allErrs = append(allErrs, field.Required(fldPath.Child("kubeletConfigKey"), "kubeletConfigKey must be set in spec"))
|
||||||
|
} else {
|
||||||
|
for _, msg := range validation.IsConfigMapKey(source.KubeletConfigKey) {
|
||||||
|
allErrs = append(allErrs, field.Invalid(fldPath.Child("kubeletConfigKey"), source.KubeletConfigKey, msg))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return allErrs
|
||||||
|
}
|
||||||
|
|
||||||
// Validate compute resource typename.
|
// Validate compute resource typename.
|
||||||
// Refer to docs/design/resources.md for more details.
|
// Refer to docs/design/resources.md for more details.
|
||||||
func validateResourceName(value string, fldPath *field.Path) field.ErrorList {
|
func validateResourceName(value string, fldPath *field.Path) field.ErrorList {
|
||||||
|
31
pkg/apis/core/zz_generated.deepcopy.go
generated
31
pkg/apis/core/zz_generated.deepcopy.go
generated
@ -631,6 +631,22 @@ func (in *ConfigMapList) DeepCopyObject() runtime.Object {
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
|
||||||
|
func (in *ConfigMapNodeConfigSource) DeepCopyInto(out *ConfigMapNodeConfigSource) {
|
||||||
|
*out = *in
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ConfigMapNodeConfigSource.
|
||||||
|
func (in *ConfigMapNodeConfigSource) DeepCopy() *ConfigMapNodeConfigSource {
|
||||||
|
if in == nil {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
out := new(ConfigMapNodeConfigSource)
|
||||||
|
in.DeepCopyInto(out)
|
||||||
|
return out
|
||||||
|
}
|
||||||
|
|
||||||
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
|
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
|
||||||
func (in *ConfigMapProjection) DeepCopyInto(out *ConfigMapProjection) {
|
func (in *ConfigMapProjection) DeepCopyInto(out *ConfigMapProjection) {
|
||||||
*out = *in
|
*out = *in
|
||||||
@ -2364,13 +2380,12 @@ func (in *NodeCondition) DeepCopy() *NodeCondition {
|
|||||||
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
|
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
|
||||||
func (in *NodeConfigSource) DeepCopyInto(out *NodeConfigSource) {
|
func (in *NodeConfigSource) DeepCopyInto(out *NodeConfigSource) {
|
||||||
*out = *in
|
*out = *in
|
||||||
out.TypeMeta = in.TypeMeta
|
if in.ConfigMap != nil {
|
||||||
if in.ConfigMapRef != nil {
|
in, out := &in.ConfigMap, &out.ConfigMap
|
||||||
in, out := &in.ConfigMapRef, &out.ConfigMapRef
|
|
||||||
if *in == nil {
|
if *in == nil {
|
||||||
*out = nil
|
*out = nil
|
||||||
} else {
|
} else {
|
||||||
*out = new(ObjectReference)
|
*out = new(ConfigMapNodeConfigSource)
|
||||||
**out = **in
|
**out = **in
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -2387,14 +2402,6 @@ func (in *NodeConfigSource) DeepCopy() *NodeConfigSource {
|
|||||||
return out
|
return out
|
||||||
}
|
}
|
||||||
|
|
||||||
// DeepCopyObject is an autogenerated deepcopy function, copying the receiver, creating a new runtime.Object.
|
|
||||||
func (in *NodeConfigSource) DeepCopyObject() runtime.Object {
|
|
||||||
if c := in.DeepCopy(); c != nil {
|
|
||||||
return c
|
|
||||||
}
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
|
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
|
||||||
func (in *NodeDaemonEndpoints) DeepCopyInto(out *NodeDaemonEndpoints) {
|
func (in *NodeDaemonEndpoints) DeepCopyInto(out *NodeDaemonEndpoints) {
|
||||||
*out = *in
|
*out = *in
|
||||||
|
@ -17,6 +17,7 @@ go_library(
|
|||||||
],
|
],
|
||||||
importpath = "k8s.io/kubernetes/pkg/kubelet/apis/kubeletconfig",
|
importpath = "k8s.io/kubernetes/pkg/kubelet/apis/kubeletconfig",
|
||||||
deps = [
|
deps = [
|
||||||
|
"//vendor/k8s.io/api/core/v1:go_default_library",
|
||||||
"//vendor/k8s.io/apimachinery/pkg/apis/meta/v1:go_default_library",
|
"//vendor/k8s.io/apimachinery/pkg/apis/meta/v1:go_default_library",
|
||||||
"//vendor/k8s.io/apimachinery/pkg/runtime:go_default_library",
|
"//vendor/k8s.io/apimachinery/pkg/runtime:go_default_library",
|
||||||
"//vendor/k8s.io/apimachinery/pkg/runtime/schema:go_default_library",
|
"//vendor/k8s.io/apimachinery/pkg/runtime/schema:go_default_library",
|
||||||
|
@ -46,6 +46,7 @@ func addKnownTypes(scheme *runtime.Scheme) error {
|
|||||||
// TODO this will get cleaned up with the scheme types are fixed
|
// TODO this will get cleaned up with the scheme types are fixed
|
||||||
scheme.AddKnownTypes(SchemeGroupVersion,
|
scheme.AddKnownTypes(SchemeGroupVersion,
|
||||||
&KubeletConfiguration{},
|
&KubeletConfiguration{},
|
||||||
|
&SerializedNodeConfigSource{},
|
||||||
)
|
)
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
@ -17,6 +17,7 @@ limitations under the License.
|
|||||||
package kubeletconfig
|
package kubeletconfig
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"k8s.io/api/core/v1"
|
||||||
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||||
)
|
)
|
||||||
|
|
||||||
@ -333,3 +334,15 @@ type KubeletAnonymousAuthentication struct {
|
|||||||
// Anonymous requests have a username of system:anonymous, and a group name of system:unauthenticated.
|
// Anonymous requests have a username of system:anonymous, and a group name of system:unauthenticated.
|
||||||
Enabled bool
|
Enabled bool
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// +k8s:deepcopy-gen:interfaces=k8s.io/apimachinery/pkg/runtime.Object
|
||||||
|
|
||||||
|
// SerializedNodeConfigSource allows us to serialize NodeConfigSource
|
||||||
|
// This type is used internally by the Kubelet for tracking checkpointed dynamic configs.
|
||||||
|
// It exists in the kubeletconfig API group because it is classified as a versioned input to the Kubelet.
|
||||||
|
type SerializedNodeConfigSource struct {
|
||||||
|
metav1.TypeMeta
|
||||||
|
// Source is the source that we are serializing
|
||||||
|
// +optional
|
||||||
|
Source v1.NodeConfigSource
|
||||||
|
}
|
||||||
|
@ -23,6 +23,7 @@ go_library(
|
|||||||
"//pkg/kubelet/types:go_default_library",
|
"//pkg/kubelet/types:go_default_library",
|
||||||
"//pkg/master/ports:go_default_library",
|
"//pkg/master/ports:go_default_library",
|
||||||
"//pkg/util/pointer:go_default_library",
|
"//pkg/util/pointer:go_default_library",
|
||||||
|
"//vendor/k8s.io/api/core/v1:go_default_library",
|
||||||
"//vendor/k8s.io/apimachinery/pkg/apis/meta/v1:go_default_library",
|
"//vendor/k8s.io/apimachinery/pkg/apis/meta/v1:go_default_library",
|
||||||
"//vendor/k8s.io/apimachinery/pkg/conversion:go_default_library",
|
"//vendor/k8s.io/apimachinery/pkg/conversion:go_default_library",
|
||||||
"//vendor/k8s.io/apimachinery/pkg/runtime:go_default_library",
|
"//vendor/k8s.io/apimachinery/pkg/runtime:go_default_library",
|
||||||
|
@ -45,6 +45,7 @@ func init() {
|
|||||||
func addKnownTypes(scheme *runtime.Scheme) error {
|
func addKnownTypes(scheme *runtime.Scheme) error {
|
||||||
scheme.AddKnownTypes(SchemeGroupVersion,
|
scheme.AddKnownTypes(SchemeGroupVersion,
|
||||||
&KubeletConfiguration{},
|
&KubeletConfiguration{},
|
||||||
|
&SerializedNodeConfigSource{},
|
||||||
)
|
)
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
@ -17,6 +17,7 @@ limitations under the License.
|
|||||||
package v1beta1
|
package v1beta1
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"k8s.io/api/core/v1"
|
||||||
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||||
)
|
)
|
||||||
|
|
||||||
@ -512,3 +513,15 @@ type KubeletAnonymousAuthentication struct {
|
|||||||
// +optional
|
// +optional
|
||||||
Enabled *bool `json:"enabled,omitempty"`
|
Enabled *bool `json:"enabled,omitempty"`
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// +k8s:deepcopy-gen:interfaces=k8s.io/apimachinery/pkg/runtime.Object
|
||||||
|
|
||||||
|
// SerializedNodeConfigSource allows us to serialize v1.NodeConfigSource.
|
||||||
|
// This type is used internally by the Kubelet for tracking checkpointed dynamic configs.
|
||||||
|
// It exists in the kubeletconfig API group because it is classified as a versioned input to the Kubelet.
|
||||||
|
type SerializedNodeConfigSource struct {
|
||||||
|
metav1.TypeMeta `json:",inline"`
|
||||||
|
// Source is the source that we are serializing
|
||||||
|
// +optional
|
||||||
|
Source v1.NodeConfigSource `json:"source,omitempty" protobuf:"bytes,1,opt,name=source"`
|
||||||
|
}
|
||||||
|
@ -51,6 +51,8 @@ func RegisterConversions(scheme *runtime.Scheme) error {
|
|||||||
Convert_kubeletconfig_KubeletWebhookAuthorization_To_v1beta1_KubeletWebhookAuthorization,
|
Convert_kubeletconfig_KubeletWebhookAuthorization_To_v1beta1_KubeletWebhookAuthorization,
|
||||||
Convert_v1beta1_KubeletX509Authentication_To_kubeletconfig_KubeletX509Authentication,
|
Convert_v1beta1_KubeletX509Authentication_To_kubeletconfig_KubeletX509Authentication,
|
||||||
Convert_kubeletconfig_KubeletX509Authentication_To_v1beta1_KubeletX509Authentication,
|
Convert_kubeletconfig_KubeletX509Authentication_To_v1beta1_KubeletX509Authentication,
|
||||||
|
Convert_v1beta1_SerializedNodeConfigSource_To_kubeletconfig_SerializedNodeConfigSource,
|
||||||
|
Convert_kubeletconfig_SerializedNodeConfigSource_To_v1beta1_SerializedNodeConfigSource,
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -453,3 +455,23 @@ func autoConvert_kubeletconfig_KubeletX509Authentication_To_v1beta1_KubeletX509A
|
|||||||
func Convert_kubeletconfig_KubeletX509Authentication_To_v1beta1_KubeletX509Authentication(in *kubeletconfig.KubeletX509Authentication, out *KubeletX509Authentication, s conversion.Scope) error {
|
func Convert_kubeletconfig_KubeletX509Authentication_To_v1beta1_KubeletX509Authentication(in *kubeletconfig.KubeletX509Authentication, out *KubeletX509Authentication, s conversion.Scope) error {
|
||||||
return autoConvert_kubeletconfig_KubeletX509Authentication_To_v1beta1_KubeletX509Authentication(in, out, s)
|
return autoConvert_kubeletconfig_KubeletX509Authentication_To_v1beta1_KubeletX509Authentication(in, out, s)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func autoConvert_v1beta1_SerializedNodeConfigSource_To_kubeletconfig_SerializedNodeConfigSource(in *SerializedNodeConfigSource, out *kubeletconfig.SerializedNodeConfigSource, s conversion.Scope) error {
|
||||||
|
out.Source = in.Source
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// Convert_v1beta1_SerializedNodeConfigSource_To_kubeletconfig_SerializedNodeConfigSource is an autogenerated conversion function.
|
||||||
|
func Convert_v1beta1_SerializedNodeConfigSource_To_kubeletconfig_SerializedNodeConfigSource(in *SerializedNodeConfigSource, out *kubeletconfig.SerializedNodeConfigSource, s conversion.Scope) error {
|
||||||
|
return autoConvert_v1beta1_SerializedNodeConfigSource_To_kubeletconfig_SerializedNodeConfigSource(in, out, s)
|
||||||
|
}
|
||||||
|
|
||||||
|
func autoConvert_kubeletconfig_SerializedNodeConfigSource_To_v1beta1_SerializedNodeConfigSource(in *kubeletconfig.SerializedNodeConfigSource, out *SerializedNodeConfigSource, s conversion.Scope) error {
|
||||||
|
out.Source = in.Source
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// Convert_kubeletconfig_SerializedNodeConfigSource_To_v1beta1_SerializedNodeConfigSource is an autogenerated conversion function.
|
||||||
|
func Convert_kubeletconfig_SerializedNodeConfigSource_To_v1beta1_SerializedNodeConfigSource(in *kubeletconfig.SerializedNodeConfigSource, out *SerializedNodeConfigSource, s conversion.Scope) error {
|
||||||
|
return autoConvert_kubeletconfig_SerializedNodeConfigSource_To_v1beta1_SerializedNodeConfigSource(in, out, s)
|
||||||
|
}
|
||||||
|
@ -426,3 +426,29 @@ func (in *KubeletX509Authentication) DeepCopy() *KubeletX509Authentication {
|
|||||||
in.DeepCopyInto(out)
|
in.DeepCopyInto(out)
|
||||||
return out
|
return out
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
|
||||||
|
func (in *SerializedNodeConfigSource) DeepCopyInto(out *SerializedNodeConfigSource) {
|
||||||
|
*out = *in
|
||||||
|
out.TypeMeta = in.TypeMeta
|
||||||
|
in.Source.DeepCopyInto(&out.Source)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new SerializedNodeConfigSource.
|
||||||
|
func (in *SerializedNodeConfigSource) DeepCopy() *SerializedNodeConfigSource {
|
||||||
|
if in == nil {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
out := new(SerializedNodeConfigSource)
|
||||||
|
in.DeepCopyInto(out)
|
||||||
|
return out
|
||||||
|
}
|
||||||
|
|
||||||
|
// DeepCopyObject is an autogenerated deepcopy function, copying the receiver, creating a new runtime.Object.
|
||||||
|
func (in *SerializedNodeConfigSource) DeepCopyObject() runtime.Object {
|
||||||
|
if c := in.DeepCopy(); c != nil {
|
||||||
|
return c
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
@ -246,3 +246,29 @@ func (in *KubeletX509Authentication) DeepCopy() *KubeletX509Authentication {
|
|||||||
in.DeepCopyInto(out)
|
in.DeepCopyInto(out)
|
||||||
return out
|
return out
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
|
||||||
|
func (in *SerializedNodeConfigSource) DeepCopyInto(out *SerializedNodeConfigSource) {
|
||||||
|
*out = *in
|
||||||
|
out.TypeMeta = in.TypeMeta
|
||||||
|
in.Source.DeepCopyInto(&out.Source)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new SerializedNodeConfigSource.
|
||||||
|
func (in *SerializedNodeConfigSource) DeepCopy() *SerializedNodeConfigSource {
|
||||||
|
if in == nil {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
out := new(SerializedNodeConfigSource)
|
||||||
|
in.DeepCopyInto(out)
|
||||||
|
return out
|
||||||
|
}
|
||||||
|
|
||||||
|
// DeepCopyObject is an autogenerated deepcopy function, copying the receiver, creating a new runtime.Object.
|
||||||
|
func (in *SerializedNodeConfigSource) DeepCopyObject() runtime.Object {
|
||||||
|
if c := in.DeepCopy(); c != nil {
|
||||||
|
return c
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
@ -19,12 +19,12 @@ go_library(
|
|||||||
"//pkg/kubelet/kubeletconfig/checkpoint:go_default_library",
|
"//pkg/kubelet/kubeletconfig/checkpoint:go_default_library",
|
||||||
"//pkg/kubelet/kubeletconfig/checkpoint/store:go_default_library",
|
"//pkg/kubelet/kubeletconfig/checkpoint/store:go_default_library",
|
||||||
"//pkg/kubelet/kubeletconfig/status:go_default_library",
|
"//pkg/kubelet/kubeletconfig/status:go_default_library",
|
||||||
"//pkg/kubelet/kubeletconfig/util/equal:go_default_library",
|
|
||||||
"//pkg/kubelet/kubeletconfig/util/log:go_default_library",
|
"//pkg/kubelet/kubeletconfig/util/log:go_default_library",
|
||||||
"//pkg/kubelet/kubeletconfig/util/panic:go_default_library",
|
"//pkg/kubelet/kubeletconfig/util/panic:go_default_library",
|
||||||
"//pkg/util/filesystem:go_default_library",
|
"//pkg/util/filesystem:go_default_library",
|
||||||
"//vendor/github.com/golang/glog:go_default_library",
|
"//vendor/github.com/golang/glog:go_default_library",
|
||||||
"//vendor/k8s.io/api/core/v1:go_default_library",
|
"//vendor/k8s.io/api/core/v1:go_default_library",
|
||||||
|
"//vendor/k8s.io/apimachinery/pkg/api/equality:go_default_library",
|
||||||
"//vendor/k8s.io/apimachinery/pkg/apis/meta/v1:go_default_library",
|
"//vendor/k8s.io/apimachinery/pkg/apis/meta/v1:go_default_library",
|
||||||
"//vendor/k8s.io/apimachinery/pkg/fields:go_default_library",
|
"//vendor/k8s.io/apimachinery/pkg/fields:go_default_library",
|
||||||
"//vendor/k8s.io/apimachinery/pkg/runtime:go_default_library",
|
"//vendor/k8s.io/apimachinery/pkg/runtime:go_default_library",
|
||||||
|
@ -31,7 +31,9 @@ go_library(
|
|||||||
],
|
],
|
||||||
importpath = "k8s.io/kubernetes/pkg/kubelet/kubeletconfig/checkpoint",
|
importpath = "k8s.io/kubernetes/pkg/kubelet/kubeletconfig/checkpoint",
|
||||||
deps = [
|
deps = [
|
||||||
"//pkg/api/legacyscheme:go_default_library",
|
"//pkg/kubelet/apis/kubeletconfig:go_default_library",
|
||||||
|
"//pkg/kubelet/apis/kubeletconfig/scheme:go_default_library",
|
||||||
|
"//pkg/kubelet/apis/kubeletconfig/v1beta1:go_default_library",
|
||||||
"//pkg/kubelet/kubeletconfig/status:go_default_library",
|
"//pkg/kubelet/kubeletconfig/status:go_default_library",
|
||||||
"//pkg/kubelet/kubeletconfig/util/codec:go_default_library",
|
"//pkg/kubelet/kubeletconfig/util/codec:go_default_library",
|
||||||
"//pkg/kubelet/kubeletconfig/util/log:go_default_library",
|
"//pkg/kubelet/kubeletconfig/util/log:go_default_library",
|
||||||
|
@ -24,7 +24,9 @@ import (
|
|||||||
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||||
"k8s.io/apimachinery/pkg/runtime"
|
"k8s.io/apimachinery/pkg/runtime"
|
||||||
clientset "k8s.io/client-go/kubernetes"
|
clientset "k8s.io/client-go/kubernetes"
|
||||||
"k8s.io/kubernetes/pkg/api/legacyscheme"
|
kubeletconfiginternal "k8s.io/kubernetes/pkg/kubelet/apis/kubeletconfig"
|
||||||
|
"k8s.io/kubernetes/pkg/kubelet/apis/kubeletconfig/scheme"
|
||||||
|
kubeletconfigv1beta1 "k8s.io/kubernetes/pkg/kubelet/apis/kubeletconfig/v1beta1"
|
||||||
"k8s.io/kubernetes/pkg/kubelet/kubeletconfig/status"
|
"k8s.io/kubernetes/pkg/kubelet/kubeletconfig/status"
|
||||||
utilcodec "k8s.io/kubernetes/pkg/kubelet/kubeletconfig/util/codec"
|
utilcodec "k8s.io/kubernetes/pkg/kubelet/kubeletconfig/util/codec"
|
||||||
utillog "k8s.io/kubernetes/pkg/kubelet/kubeletconfig/util/log"
|
utillog "k8s.io/kubernetes/pkg/kubelet/kubeletconfig/util/log"
|
||||||
@ -46,6 +48,8 @@ type Payload interface {
|
|||||||
type RemoteConfigSource interface {
|
type RemoteConfigSource interface {
|
||||||
// UID returns a globally unique identifier of the source described by the remote config source object
|
// UID returns a globally unique identifier of the source described by the remote config source object
|
||||||
UID() string
|
UID() string
|
||||||
|
// KubeletFilename returns the name of the Kubelet config file as it should appear in the keys of Payload.Files()
|
||||||
|
KubeletFilename() string
|
||||||
// APIPath returns the API path to the remote resource, e.g. its SelfLink
|
// APIPath returns the API path to the remote resource, e.g. its SelfLink
|
||||||
APIPath() string
|
APIPath() string
|
||||||
// Download downloads the remote config source object returns a Payload backed by the object,
|
// Download downloads the remote config source object returns a Payload backed by the object,
|
||||||
@ -60,25 +64,18 @@ type RemoteConfigSource interface {
|
|||||||
object() interface{}
|
object() interface{}
|
||||||
}
|
}
|
||||||
|
|
||||||
// NewRemoteConfigSource constructs a RemoteConfigSource from a v1/NodeConfigSource object, or returns
|
// NewRemoteConfigSource constructs a RemoteConfigSource from a v1/NodeConfigSource object
|
||||||
// a sanitized failure reason and an error if the `source` is blatantly invalid.
|
|
||||||
// You should only call this with a non-nil config source.
|
// You should only call this with a non-nil config source.
|
||||||
|
// Note that the API server validates Node.Spec.ConfigSource.
|
||||||
func NewRemoteConfigSource(source *apiv1.NodeConfigSource) (RemoteConfigSource, string, error) {
|
func NewRemoteConfigSource(source *apiv1.NodeConfigSource) (RemoteConfigSource, string, error) {
|
||||||
// exactly one subfield of the config source must be non-nil, toady ConfigMapRef is the only reference
|
// NOTE: Even though the API server validates the config, we check whether all *known* fields are
|
||||||
if source.ConfigMapRef == nil {
|
// nil here, so that if a new API server allows a new config source type, old clients can send
|
||||||
|
// an error message rather than crashing due to a nil pointer dereference.
|
||||||
|
|
||||||
|
// exactly one reference subfield of the config source must be non-nil, today ConfigMap is the only reference subfield
|
||||||
|
if source.ConfigMap == nil {
|
||||||
return nil, status.FailSyncReasonAllNilSubfields, fmt.Errorf("%s, NodeConfigSource was: %#v", status.FailSyncReasonAllNilSubfields, source)
|
return nil, status.FailSyncReasonAllNilSubfields, fmt.Errorf("%s, NodeConfigSource was: %#v", status.FailSyncReasonAllNilSubfields, source)
|
||||||
}
|
}
|
||||||
|
|
||||||
// validate the NodeConfigSource:
|
|
||||||
|
|
||||||
// at this point we know we're using the ConfigMapRef subfield
|
|
||||||
ref := source.ConfigMapRef
|
|
||||||
|
|
||||||
// name, namespace, and UID must all be non-empty for ConfigMapRef
|
|
||||||
if ref.Name == "" || ref.Namespace == "" || string(ref.UID) == "" {
|
|
||||||
return nil, status.FailSyncReasonPartialObjectReference, fmt.Errorf("%s, ObjectReference was: %#v", status.FailSyncReasonPartialObjectReference, ref)
|
|
||||||
}
|
|
||||||
|
|
||||||
return &remoteConfigMap{source}, "", nil
|
return &remoteConfigMap{source}, "", nil
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -86,21 +83,25 @@ func NewRemoteConfigSource(source *apiv1.NodeConfigSource) (RemoteConfigSource,
|
|||||||
// e.g. the metadata stored by checkpoint/store/fsstore.go
|
// e.g. the metadata stored by checkpoint/store/fsstore.go
|
||||||
func DecodeRemoteConfigSource(data []byte) (RemoteConfigSource, error) {
|
func DecodeRemoteConfigSource(data []byte) (RemoteConfigSource, error) {
|
||||||
// decode the remote config source
|
// decode the remote config source
|
||||||
obj, err := runtime.Decode(legacyscheme.Codecs.UniversalDecoder(), data)
|
_, codecs, err := scheme.NewSchemeAndCodecs()
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
obj, err := runtime.Decode(codecs.UniversalDecoder(), data)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, fmt.Errorf("failed to decode, error: %v", err)
|
return nil, fmt.Errorf("failed to decode, error: %v", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
// for now we assume we are trying to load an apiv1.NodeConfigSource,
|
// for now we assume we are trying to load an kubeletconfigv1beta1.SerializedNodeConfigSource,
|
||||||
// this may need to be extended if e.g. a new version of the api is born
|
// this may need to be extended if e.g. a new version of the api is born
|
||||||
|
cs, ok := obj.(*kubeletconfiginternal.SerializedNodeConfigSource)
|
||||||
// convert it to the external NodeConfigSource type, so we're consistently working with the external type outside of the on-disk representation
|
if !ok {
|
||||||
cs := &apiv1.NodeConfigSource{}
|
return nil, fmt.Errorf("failed to cast decoded remote config source to *k8s.io/kubernetes/pkg/kubelet/apis/kubeletconfig.SerializedNodeConfigSource")
|
||||||
err = legacyscheme.Scheme.Convert(obj, cs, nil)
|
|
||||||
if err != nil {
|
|
||||||
return nil, fmt.Errorf("failed to convert decoded object into a v1 NodeConfigSource, error: %v", err)
|
|
||||||
}
|
}
|
||||||
source, _, err := NewRemoteConfigSource(cs)
|
|
||||||
|
// we use the v1.NodeConfigSource type on internal and external, so no need to convert to external here
|
||||||
|
source, _, err := NewRemoteConfigSource(&cs.Source)
|
||||||
return source, err
|
return source, err
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -121,32 +122,36 @@ type remoteConfigMap struct {
|
|||||||
var _ RemoteConfigSource = (*remoteConfigMap)(nil)
|
var _ RemoteConfigSource = (*remoteConfigMap)(nil)
|
||||||
|
|
||||||
func (r *remoteConfigMap) UID() string {
|
func (r *remoteConfigMap) UID() string {
|
||||||
return string(r.source.ConfigMapRef.UID)
|
return string(r.source.ConfigMap.UID)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (r *remoteConfigMap) KubeletFilename() string {
|
||||||
|
return r.source.ConfigMap.KubeletConfigKey
|
||||||
}
|
}
|
||||||
|
|
||||||
const configMapAPIPathFmt = "/api/v1/namespaces/%s/configmaps/%s"
|
const configMapAPIPathFmt = "/api/v1/namespaces/%s/configmaps/%s"
|
||||||
|
|
||||||
func (r *remoteConfigMap) APIPath() string {
|
func (r *remoteConfigMap) APIPath() string {
|
||||||
ref := r.source.ConfigMapRef
|
ref := r.source.ConfigMap
|
||||||
return fmt.Sprintf(configMapAPIPathFmt, ref.Namespace, ref.Name)
|
return fmt.Sprintf(configMapAPIPathFmt, ref.Namespace, ref.Name)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (r *remoteConfigMap) Download(client clientset.Interface) (Payload, string, error) {
|
func (r *remoteConfigMap) Download(client clientset.Interface) (Payload, string, error) {
|
||||||
var reason string
|
var reason string
|
||||||
uid := string(r.source.ConfigMapRef.UID)
|
uid := string(r.source.ConfigMap.UID)
|
||||||
|
|
||||||
utillog.Infof("attempting to download ConfigMap with UID %q", uid)
|
utillog.Infof("attempting to download ConfigMap with UID %q", uid)
|
||||||
|
|
||||||
// get the ConfigMap via namespace/name, there doesn't seem to be a way to get it by UID
|
// get the ConfigMap via namespace/name, there doesn't seem to be a way to get it by UID
|
||||||
cm, err := client.CoreV1().ConfigMaps(r.source.ConfigMapRef.Namespace).Get(r.source.ConfigMapRef.Name, metav1.GetOptions{})
|
cm, err := client.CoreV1().ConfigMaps(r.source.ConfigMap.Namespace).Get(r.source.ConfigMap.Name, metav1.GetOptions{})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
reason = fmt.Sprintf(status.FailSyncReasonDownloadFmt, r.APIPath())
|
reason = fmt.Sprintf(status.FailSyncReasonDownloadFmt, r.APIPath())
|
||||||
return nil, reason, fmt.Errorf("%s, error: %v", reason, err)
|
return nil, reason, fmt.Errorf("%s, error: %v", reason, err)
|
||||||
}
|
}
|
||||||
|
|
||||||
// ensure that UID matches the UID on the reference, the ObjectReference must be unambiguous
|
// ensure that UID matches the UID on the source
|
||||||
if r.source.ConfigMapRef.UID != cm.UID {
|
if r.source.ConfigMap.UID != cm.UID {
|
||||||
reason = fmt.Sprintf(status.FailSyncReasonUIDMismatchFmt, r.source.ConfigMapRef.UID, r.APIPath(), cm.UID)
|
reason = fmt.Sprintf(status.FailSyncReasonUIDMismatchFmt, r.source.ConfigMap.UID, r.APIPath(), cm.UID)
|
||||||
return nil, reason, fmt.Errorf(reason)
|
return nil, reason, fmt.Errorf(reason)
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -161,11 +166,12 @@ func (r *remoteConfigMap) Download(client clientset.Interface) (Payload, string,
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (r *remoteConfigMap) Encode() ([]byte, error) {
|
func (r *remoteConfigMap) Encode() ([]byte, error) {
|
||||||
encoder, err := utilcodec.NewYAMLEncoder(apiv1.GroupName)
|
encoder, err := utilcodec.NewKubeletconfigYAMLEncoder(kubeletconfigv1beta1.SchemeGroupVersion)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
data, err := runtime.Encode(encoder, r.source)
|
|
||||||
|
data, err := runtime.Encode(encoder, &kubeletconfigv1beta1.SerializedNodeConfigSource{Source: *r.source})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
@ -36,33 +36,30 @@ func TestNewRemoteConfigSource(t *testing.T) {
|
|||||||
expect RemoteConfigSource
|
expect RemoteConfigSource
|
||||||
err string
|
err string
|
||||||
}{
|
}{
|
||||||
// all NodeConfigSource subfields nil
|
{
|
||||||
{"all NodeConfigSource subfields nil",
|
desc: "all NodeConfigSource subfields nil",
|
||||||
&apiv1.NodeConfigSource{}, nil, "exactly one subfield must be non-nil"},
|
source: &apiv1.NodeConfigSource{},
|
||||||
{"ConfigMapRef: empty name, namespace, and UID",
|
expect: nil,
|
||||||
&apiv1.NodeConfigSource{ConfigMapRef: &apiv1.ObjectReference{}}, nil, "invalid ObjectReference"},
|
err: "exactly one subfield must be non-nil",
|
||||||
// ConfigMapRef: empty name and namespace
|
},
|
||||||
{"ConfigMapRef: empty name and namespace",
|
{
|
||||||
&apiv1.NodeConfigSource{ConfigMapRef: &apiv1.ObjectReference{UID: "uid"}}, nil, "invalid ObjectReference"},
|
desc: "ConfigMap: valid reference",
|
||||||
// ConfigMapRef: empty name and UID
|
source: &apiv1.NodeConfigSource{
|
||||||
{"ConfigMapRef: empty name and UID",
|
ConfigMap: &apiv1.ConfigMapNodeConfigSource{
|
||||||
&apiv1.NodeConfigSource{ConfigMapRef: &apiv1.ObjectReference{Namespace: "namespace"}}, nil, "invalid ObjectReference"},
|
Name: "name",
|
||||||
// ConfigMapRef: empty namespace and UID
|
Namespace: "namespace",
|
||||||
{"ConfigMapRef: empty namespace and UID",
|
UID: "uid",
|
||||||
&apiv1.NodeConfigSource{ConfigMapRef: &apiv1.ObjectReference{Name: "name"}}, nil, "invalid ObjectReference"},
|
KubeletConfigKey: "kubelet",
|
||||||
// ConfigMapRef: empty UID
|
}},
|
||||||
{"ConfigMapRef: empty namespace and UID",
|
expect: &remoteConfigMap{&apiv1.NodeConfigSource{
|
||||||
&apiv1.NodeConfigSource{ConfigMapRef: &apiv1.ObjectReference{Name: "name", Namespace: "namespace"}}, nil, "invalid ObjectReference"},
|
ConfigMap: &apiv1.ConfigMapNodeConfigSource{
|
||||||
// ConfigMapRef: empty namespace
|
Name: "name",
|
||||||
{"ConfigMapRef: empty namespace and UID",
|
Namespace: "namespace",
|
||||||
&apiv1.NodeConfigSource{ConfigMapRef: &apiv1.ObjectReference{Name: "name", UID: "uid"}}, nil, "invalid ObjectReference"},
|
UID: "uid",
|
||||||
// ConfigMapRef: empty name
|
KubeletConfigKey: "kubelet",
|
||||||
{"ConfigMapRef: empty namespace and UID",
|
}}},
|
||||||
&apiv1.NodeConfigSource{ConfigMapRef: &apiv1.ObjectReference{Namespace: "namespace", UID: "uid"}}, nil, "invalid ObjectReference"},
|
err: "",
|
||||||
// ConfigMapRef: valid reference
|
},
|
||||||
{"ConfigMapRef: valid reference",
|
|
||||||
&apiv1.NodeConfigSource{ConfigMapRef: &apiv1.ObjectReference{Name: "name", Namespace: "namespace", UID: "uid"}},
|
|
||||||
&remoteConfigMap{&apiv1.NodeConfigSource{ConfigMapRef: &apiv1.ObjectReference{Name: "name", Namespace: "namespace", UID: "uid"}}}, ""},
|
|
||||||
}
|
}
|
||||||
|
|
||||||
for _, c := range cases {
|
for _, c := range cases {
|
||||||
@ -82,7 +79,12 @@ func TestNewRemoteConfigSource(t *testing.T) {
|
|||||||
|
|
||||||
func TestRemoteConfigMapUID(t *testing.T) {
|
func TestRemoteConfigMapUID(t *testing.T) {
|
||||||
const expect = "uid"
|
const expect = "uid"
|
||||||
source, _, err := NewRemoteConfigSource(&apiv1.NodeConfigSource{ConfigMapRef: &apiv1.ObjectReference{Name: "name", Namespace: "namespace", UID: expect}})
|
source, _, err := NewRemoteConfigSource(&apiv1.NodeConfigSource{ConfigMap: &apiv1.ConfigMapNodeConfigSource{
|
||||||
|
Name: "name",
|
||||||
|
Namespace: "namespace",
|
||||||
|
UID: expect,
|
||||||
|
KubeletConfigKey: "kubelet",
|
||||||
|
}})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatalf("error constructing remote config source: %v", err)
|
t.Fatalf("error constructing remote config source: %v", err)
|
||||||
}
|
}
|
||||||
@ -93,14 +95,22 @@ func TestRemoteConfigMapUID(t *testing.T) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func TestRemoteConfigMapAPIPath(t *testing.T) {
|
func TestRemoteConfigMapAPIPath(t *testing.T) {
|
||||||
const namespace = "namespace"
|
const (
|
||||||
const name = "name"
|
name = "name"
|
||||||
source, _, err := NewRemoteConfigSource(&apiv1.NodeConfigSource{ConfigMapRef: &apiv1.ObjectReference{Name: name, Namespace: namespace, UID: "uid"}})
|
namespace = "namespace"
|
||||||
|
)
|
||||||
|
source, _, err := NewRemoteConfigSource(&apiv1.NodeConfigSource{ConfigMap: &apiv1.ConfigMapNodeConfigSource{
|
||||||
|
Name: name,
|
||||||
|
Namespace: namespace,
|
||||||
|
UID: "uid",
|
||||||
|
KubeletConfigKey: "kubelet",
|
||||||
|
}})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatalf("error constructing remote config source: %v", err)
|
t.Fatalf("error constructing remote config source: %v", err)
|
||||||
}
|
}
|
||||||
expect := fmt.Sprintf(configMapAPIPathFmt, namespace, name)
|
expect := fmt.Sprintf(configMapAPIPathFmt, namespace, name)
|
||||||
path := source.APIPath()
|
path := source.APIPath()
|
||||||
|
|
||||||
if expect != path {
|
if expect != path {
|
||||||
t.Errorf("expect %q, but got %q", expect, path)
|
t.Errorf("expect %q, but got %q", expect, path)
|
||||||
}
|
}
|
||||||
@ -133,18 +143,39 @@ func TestRemoteConfigMapDownload(t *testing.T) {
|
|||||||
expect Payload
|
expect Payload
|
||||||
err string
|
err string
|
||||||
}{
|
}{
|
||||||
// object doesn't exist
|
{
|
||||||
{"object doesn't exist",
|
desc: "object doesn't exist",
|
||||||
makeSource(&apiv1.NodeConfigSource{ConfigMapRef: &apiv1.ObjectReference{Name: "bogus", Namespace: "namespace", UID: "bogus"}}),
|
source: makeSource(&apiv1.NodeConfigSource{ConfigMap: &apiv1.ConfigMapNodeConfigSource{
|
||||||
nil, "not found"},
|
Name: "bogus",
|
||||||
// UID of downloaded object doesn't match UID of referent found via namespace/name
|
Namespace: "namespace",
|
||||||
{"UID is incorrect for namespace/name",
|
UID: "bogus",
|
||||||
makeSource(&apiv1.NodeConfigSource{ConfigMapRef: &apiv1.ObjectReference{Name: "name", Namespace: "namespace", UID: "bogus"}}),
|
KubeletConfigKey: "kubelet",
|
||||||
nil, "does not match"},
|
}}),
|
||||||
// successful download
|
expect: nil,
|
||||||
{"object exists and reference is correct",
|
err: "not found",
|
||||||
makeSource(&apiv1.NodeConfigSource{ConfigMapRef: &apiv1.ObjectReference{Name: "name", Namespace: "namespace", UID: "uid"}}),
|
},
|
||||||
payload, ""},
|
{
|
||||||
|
desc: "UID is incorrect for namespace/name",
|
||||||
|
source: makeSource(&apiv1.NodeConfigSource{ConfigMap: &apiv1.ConfigMapNodeConfigSource{
|
||||||
|
Name: "name",
|
||||||
|
Namespace: "namespace",
|
||||||
|
UID: "bogus",
|
||||||
|
KubeletConfigKey: "kubelet",
|
||||||
|
}}),
|
||||||
|
expect: nil,
|
||||||
|
err: "does not match",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
desc: "object exists and reference is correct",
|
||||||
|
source: makeSource(&apiv1.NodeConfigSource{ConfigMap: &apiv1.ConfigMapNodeConfigSource{
|
||||||
|
Name: "name",
|
||||||
|
Namespace: "namespace",
|
||||||
|
UID: "uid",
|
||||||
|
KubeletConfigKey: "kubelet",
|
||||||
|
}}),
|
||||||
|
expect: payload,
|
||||||
|
err: "",
|
||||||
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
for _, c := range cases {
|
for _, c := range cases {
|
||||||
@ -173,10 +204,12 @@ func TestEqualRemoteConfigSources(t *testing.T) {
|
|||||||
{"a nil", nil, &remoteConfigMap{}, false},
|
{"a nil", nil, &remoteConfigMap{}, false},
|
||||||
{"b nil", &remoteConfigMap{}, nil, false},
|
{"b nil", &remoteConfigMap{}, nil, false},
|
||||||
{"neither nil, equal", &remoteConfigMap{}, &remoteConfigMap{}, true},
|
{"neither nil, equal", &remoteConfigMap{}, &remoteConfigMap{}, true},
|
||||||
{"neither nil, not equal",
|
{
|
||||||
&remoteConfigMap{&apiv1.NodeConfigSource{ConfigMapRef: &apiv1.ObjectReference{Name: "a"}}},
|
desc: "neither nil, not equal",
|
||||||
&remoteConfigMap{},
|
a: &remoteConfigMap{&apiv1.NodeConfigSource{ConfigMap: &apiv1.ConfigMapNodeConfigSource{Name: "a"}}},
|
||||||
false},
|
b: &remoteConfigMap{&apiv1.NodeConfigSource{ConfigMap: &apiv1.ConfigMapNodeConfigSource{KubeletConfigKey: "kubelet"}}},
|
||||||
|
expect: false,
|
||||||
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
for _, c := range cases {
|
for _, c := range cases {
|
||||||
|
@ -35,7 +35,6 @@ const (
|
|||||||
lastKnownGoodFile = "last-known-good"
|
lastKnownGoodFile = "last-known-good"
|
||||||
|
|
||||||
checkpointsDir = "checkpoints"
|
checkpointsDir = "checkpoints"
|
||||||
kubeletKey = "kubelet" // TODO(mtaufen): eventually the API will have a way to parameterize the kubelet file name, and then we can remove this
|
|
||||||
)
|
)
|
||||||
|
|
||||||
// fsStore is for tracking checkpoints in the local filesystem, implements Store
|
// fsStore is for tracking checkpoints in the local filesystem, implements Store
|
||||||
@ -101,7 +100,7 @@ func (s *fsStore) Load(source checkpoint.RemoteConfigSource) (*kubeletconfig.Kub
|
|||||||
}
|
}
|
||||||
// load the kubelet config file
|
// load the kubelet config file
|
||||||
utillog.Infof("loading kubelet configuration checkpoint for source %s", sourceFmt)
|
utillog.Infof("loading kubelet configuration checkpoint for source %s", sourceFmt)
|
||||||
loader, err := configfiles.NewFsLoader(s.fs, filepath.Join(s.checkpointPath(source.UID()), kubeletKey))
|
loader, err := configfiles.NewFsLoader(s.fs, filepath.Join(s.checkpointPath(source.UID()), source.KubeletFilename()))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
@ -125,7 +125,12 @@ func TestFsStoreExists(t *testing.T) {
|
|||||||
for _, c := range cases {
|
for _, c := range cases {
|
||||||
t.Run(c.desc, func(t *testing.T) {
|
t.Run(c.desc, func(t *testing.T) {
|
||||||
source, _, err := checkpoint.NewRemoteConfigSource(&apiv1.NodeConfigSource{
|
source, _, err := checkpoint.NewRemoteConfigSource(&apiv1.NodeConfigSource{
|
||||||
ConfigMapRef: &apiv1.ObjectReference{Name: "name", Namespace: "namespace", UID: c.uid}})
|
ConfigMap: &apiv1.ConfigMapNodeConfigSource{
|
||||||
|
Name: "name",
|
||||||
|
Namespace: "namespace",
|
||||||
|
UID: c.uid,
|
||||||
|
KubeletConfigKey: "kubelet",
|
||||||
|
}})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatalf("error constructing remote config source: %v", err)
|
t.Fatalf("error constructing remote config source: %v", err)
|
||||||
}
|
}
|
||||||
@ -214,7 +219,10 @@ func TestFsStoreLoad(t *testing.T) {
|
|||||||
t.Fatalf("error encoding KubeletConfiguration: %v", err)
|
t.Fatalf("error encoding KubeletConfiguration: %v", err)
|
||||||
}
|
}
|
||||||
// construct a payload that contains the kubeletconfig
|
// construct a payload that contains the kubeletconfig
|
||||||
const uid = "uid"
|
const (
|
||||||
|
uid = "uid"
|
||||||
|
kubeletKey = "kubelet"
|
||||||
|
)
|
||||||
p, err := checkpoint.NewConfigMapPayload(&apiv1.ConfigMap{
|
p, err := checkpoint.NewConfigMapPayload(&apiv1.ConfigMap{
|
||||||
ObjectMeta: metav1.ObjectMeta{UID: types.UID(uid)},
|
ObjectMeta: metav1.ObjectMeta{UID: types.UID(uid)},
|
||||||
Data: map[string]string{
|
Data: map[string]string{
|
||||||
@ -241,7 +249,12 @@ func TestFsStoreLoad(t *testing.T) {
|
|||||||
for _, c := range cases {
|
for _, c := range cases {
|
||||||
t.Run(c.desc, func(t *testing.T) {
|
t.Run(c.desc, func(t *testing.T) {
|
||||||
source, _, err := checkpoint.NewRemoteConfigSource(&apiv1.NodeConfigSource{
|
source, _, err := checkpoint.NewRemoteConfigSource(&apiv1.NodeConfigSource{
|
||||||
ConfigMapRef: &apiv1.ObjectReference{Name: "name", Namespace: "namespace", UID: c.uid}})
|
ConfigMap: &apiv1.ConfigMapNodeConfigSource{
|
||||||
|
Name: "name",
|
||||||
|
Namespace: "namespace",
|
||||||
|
UID: c.uid,
|
||||||
|
KubeletConfigKey: kubeletKey,
|
||||||
|
}})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatalf("error constructing remote config source: %v", err)
|
t.Fatalf("error constructing remote config source: %v", err)
|
||||||
}
|
}
|
||||||
@ -291,7 +304,12 @@ func TestFsStoreCurrent(t *testing.T) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
source, _, err := checkpoint.NewRemoteConfigSource(&apiv1.NodeConfigSource{
|
source, _, err := checkpoint.NewRemoteConfigSource(&apiv1.NodeConfigSource{
|
||||||
ConfigMapRef: &apiv1.ObjectReference{Name: "name", Namespace: "namespace", UID: "uid"}})
|
ConfigMap: &apiv1.ConfigMapNodeConfigSource{
|
||||||
|
Name: "name",
|
||||||
|
Namespace: "namespace",
|
||||||
|
UID: "uid",
|
||||||
|
KubeletConfigKey: "kubelet",
|
||||||
|
}})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatalf("unexpected error: %v", err)
|
t.Fatalf("unexpected error: %v", err)
|
||||||
}
|
}
|
||||||
@ -329,7 +347,12 @@ func TestFsStoreLastKnownGood(t *testing.T) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
source, _, err := checkpoint.NewRemoteConfigSource(&apiv1.NodeConfigSource{
|
source, _, err := checkpoint.NewRemoteConfigSource(&apiv1.NodeConfigSource{
|
||||||
ConfigMapRef: &apiv1.ObjectReference{Name: "name", Namespace: "namespace", UID: "uid"}})
|
ConfigMap: &apiv1.ConfigMapNodeConfigSource{
|
||||||
|
Name: "name",
|
||||||
|
Namespace: "namespace",
|
||||||
|
UID: "uid",
|
||||||
|
KubeletConfigKey: "kubelet",
|
||||||
|
}})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatalf("unexpected error: %v", err)
|
t.Fatalf("unexpected error: %v", err)
|
||||||
}
|
}
|
||||||
@ -367,15 +390,21 @@ func TestFsStoreSetCurrent(t *testing.T) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
const uid = "uid"
|
const uid = "uid"
|
||||||
expect := fmt.Sprintf(`apiVersion: v1
|
expect := fmt.Sprintf(`apiVersion: kubelet.config.k8s.io/v1beta1
|
||||||
configMapRef:
|
kind: SerializedNodeConfigSource
|
||||||
name: name
|
source:
|
||||||
namespace: namespace
|
configMap:
|
||||||
uid: %s
|
kubeletConfigKey: kubelet
|
||||||
kind: NodeConfigSource
|
name: name
|
||||||
|
namespace: namespace
|
||||||
|
uid: %s
|
||||||
`, uid)
|
`, uid)
|
||||||
source, _, err := checkpoint.NewRemoteConfigSource(&apiv1.NodeConfigSource{ConfigMapRef: &apiv1.ObjectReference{
|
source, _, err := checkpoint.NewRemoteConfigSource(&apiv1.NodeConfigSource{ConfigMap: &apiv1.ConfigMapNodeConfigSource{
|
||||||
Name: "name", Namespace: "namespace", UID: types.UID(uid)}})
|
Name: "name",
|
||||||
|
Namespace: "namespace",
|
||||||
|
UID: types.UID(uid),
|
||||||
|
KubeletConfigKey: "kubelet",
|
||||||
|
}})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatalf("unexpected error: %v", err)
|
t.Fatalf("unexpected error: %v", err)
|
||||||
}
|
}
|
||||||
@ -399,15 +428,21 @@ func TestFsStoreSetLastKnownGood(t *testing.T) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
const uid = "uid"
|
const uid = "uid"
|
||||||
expect := fmt.Sprintf(`apiVersion: v1
|
expect := fmt.Sprintf(`apiVersion: kubelet.config.k8s.io/v1beta1
|
||||||
configMapRef:
|
kind: SerializedNodeConfigSource
|
||||||
name: name
|
source:
|
||||||
namespace: namespace
|
configMap:
|
||||||
uid: %s
|
kubeletConfigKey: kubelet
|
||||||
kind: NodeConfigSource
|
name: name
|
||||||
|
namespace: namespace
|
||||||
|
uid: %s
|
||||||
`, uid)
|
`, uid)
|
||||||
source, _, err := checkpoint.NewRemoteConfigSource(&apiv1.NodeConfigSource{ConfigMapRef: &apiv1.ObjectReference{
|
source, _, err := checkpoint.NewRemoteConfigSource(&apiv1.NodeConfigSource{ConfigMap: &apiv1.ConfigMapNodeConfigSource{
|
||||||
Name: "name", Namespace: "namespace", UID: types.UID(uid)}})
|
Name: "name",
|
||||||
|
Namespace: "namespace",
|
||||||
|
UID: types.UID(uid),
|
||||||
|
KubeletConfigKey: "kubelet",
|
||||||
|
}})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatalf("unexpected error: %v", err)
|
t.Fatalf("unexpected error: %v", err)
|
||||||
}
|
}
|
||||||
@ -430,11 +465,21 @@ func TestFsStoreReset(t *testing.T) {
|
|||||||
t.Fatalf("error constructing store: %v", err)
|
t.Fatalf("error constructing store: %v", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
source, _, err := checkpoint.NewRemoteConfigSource(&apiv1.NodeConfigSource{ConfigMapRef: &apiv1.ObjectReference{Name: "name", Namespace: "namespace", UID: "uid"}})
|
source, _, err := checkpoint.NewRemoteConfigSource(&apiv1.NodeConfigSource{ConfigMap: &apiv1.ConfigMapNodeConfigSource{
|
||||||
|
Name: "name",
|
||||||
|
Namespace: "namespace",
|
||||||
|
UID: "uid",
|
||||||
|
KubeletConfigKey: "kubelet",
|
||||||
|
}})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatalf("unexpected error: %v", err)
|
t.Fatalf("unexpected error: %v", err)
|
||||||
}
|
}
|
||||||
otherSource, _, err := checkpoint.NewRemoteConfigSource(&apiv1.NodeConfigSource{ConfigMapRef: &apiv1.ObjectReference{Name: "other-name", Namespace: "namespace", UID: "other-uid"}})
|
otherSource, _, err := checkpoint.NewRemoteConfigSource(&apiv1.NodeConfigSource{ConfigMap: &apiv1.ConfigMapNodeConfigSource{
|
||||||
|
Name: "other-name",
|
||||||
|
Namespace: "namespace",
|
||||||
|
UID: "other-uid",
|
||||||
|
KubeletConfigKey: "kubelet",
|
||||||
|
}})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatalf("unexpected error: %v", err)
|
t.Fatalf("unexpected error: %v", err)
|
||||||
}
|
}
|
||||||
@ -498,7 +543,12 @@ func TestFsStoreReadRemoteConfigSource(t *testing.T) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
source, _, err := checkpoint.NewRemoteConfigSource(&apiv1.NodeConfigSource{
|
source, _, err := checkpoint.NewRemoteConfigSource(&apiv1.NodeConfigSource{
|
||||||
ConfigMapRef: &apiv1.ObjectReference{Name: "name", Namespace: "namespace", UID: "uid"}})
|
ConfigMap: &apiv1.ConfigMapNodeConfigSource{
|
||||||
|
Name: "name",
|
||||||
|
Namespace: "namespace",
|
||||||
|
UID: "uid",
|
||||||
|
KubeletConfigKey: "kubelet",
|
||||||
|
}})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatalf("unexpected error: %v", err)
|
t.Fatalf("unexpected error: %v", err)
|
||||||
}
|
}
|
||||||
@ -534,7 +584,12 @@ func TestFsStoreWriteRemoteConfigSource(t *testing.T) {
|
|||||||
t.Fatalf("error constructing store: %v", err)
|
t.Fatalf("error constructing store: %v", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
source, _, err := checkpoint.NewRemoteConfigSource(&apiv1.NodeConfigSource{ConfigMapRef: &apiv1.ObjectReference{Name: "name", Namespace: "namespace", UID: "uid"}})
|
source, _, err := checkpoint.NewRemoteConfigSource(&apiv1.NodeConfigSource{ConfigMap: &apiv1.ConfigMapNodeConfigSource{
|
||||||
|
Name: "name",
|
||||||
|
Namespace: "namespace",
|
||||||
|
UID: "uid",
|
||||||
|
KubeletConfigKey: "kubelet",
|
||||||
|
}})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatalf("unexpected error: %v", err)
|
t.Fatalf("unexpected error: %v", err)
|
||||||
}
|
}
|
||||||
|
@ -26,11 +26,21 @@ import (
|
|||||||
)
|
)
|
||||||
|
|
||||||
func TestReset(t *testing.T) {
|
func TestReset(t *testing.T) {
|
||||||
source, _, err := checkpoint.NewRemoteConfigSource(&apiv1.NodeConfigSource{ConfigMapRef: &apiv1.ObjectReference{Name: "name", Namespace: "namespace", UID: "uid"}})
|
source, _, err := checkpoint.NewRemoteConfigSource(&apiv1.NodeConfigSource{ConfigMap: &apiv1.ConfigMapNodeConfigSource{
|
||||||
|
Name: "name",
|
||||||
|
Namespace: "namespace",
|
||||||
|
UID: "uid",
|
||||||
|
KubeletConfigKey: "kubelet",
|
||||||
|
}})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatalf("unexpected error: %v", err)
|
t.Fatalf("unexpected error: %v", err)
|
||||||
}
|
}
|
||||||
otherSource, _, err := checkpoint.NewRemoteConfigSource(&apiv1.NodeConfigSource{ConfigMapRef: &apiv1.ObjectReference{Name: "other-name", Namespace: "namespace", UID: "other-uid"}})
|
otherSource, _, err := checkpoint.NewRemoteConfigSource(&apiv1.NodeConfigSource{ConfigMap: &apiv1.ConfigMapNodeConfigSource{
|
||||||
|
Name: "other-name",
|
||||||
|
Namespace: "namespace",
|
||||||
|
UID: "other-uid",
|
||||||
|
KubeletConfigKey: "kubelet",
|
||||||
|
}})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatalf("unexpected error: %v", err)
|
t.Fatalf("unexpected error: %v", err)
|
||||||
}
|
}
|
||||||
|
@ -65,11 +65,11 @@ const (
|
|||||||
FailSyncReasonFmt = "failed to sync, reason: %s"
|
FailSyncReasonFmt = "failed to sync, reason: %s"
|
||||||
// FailSyncReasonAllNilSubfields is used when no subfields are set
|
// FailSyncReasonAllNilSubfields is used when no subfields are set
|
||||||
FailSyncReasonAllNilSubfields = "invalid NodeConfigSource, exactly one subfield must be non-nil, but all were nil"
|
FailSyncReasonAllNilSubfields = "invalid NodeConfigSource, exactly one subfield must be non-nil, but all were nil"
|
||||||
// FailSyncReasonPartialObjectReference is used when some required subfields remain unset
|
// FailSyncReasonPartialConfigMapSource is used when some required subfields remain unset
|
||||||
FailSyncReasonPartialObjectReference = "invalid ObjectReference, all of UID, Name, and Namespace must be specified"
|
FailSyncReasonPartialConfigMapSource = "invalid ConfigSource.ConfigMap, all of UID, Name, Namespace, and KubeletConfigKey must be specified"
|
||||||
// FailSyncReasonUIDMismatchFmt is used when there is a UID mismatch between the referenced and downloaded ConfigMaps,
|
// FailSyncReasonUIDMismatchFmt is used when there is a UID mismatch between the referenced and downloaded ConfigMaps,
|
||||||
// this can happen because objects must be downloaded by namespace/name, rather than by UID
|
// this can happen because objects must be downloaded by namespace/name, rather than by UID
|
||||||
FailSyncReasonUIDMismatchFmt = "invalid ConfigSource.ConfigMapRef.UID: %s does not match %s.UID: %s"
|
FailSyncReasonUIDMismatchFmt = "invalid ConfigSource.ConfigMap.UID: %s does not match %s.UID: %s"
|
||||||
// FailSyncReasonDownloadFmt is used when the download fails, e.g. due to network issues
|
// FailSyncReasonDownloadFmt is used when the download fails, e.g. due to network issues
|
||||||
FailSyncReasonDownloadFmt = "failed to download: %s"
|
FailSyncReasonDownloadFmt = "failed to download: %s"
|
||||||
// FailSyncReasonInformer is used when the informer fails to report the Node object
|
// FailSyncReasonInformer is used when the informer fails to report the Node object
|
||||||
|
@ -32,7 +32,7 @@ import (
|
|||||||
|
|
||||||
// EncodeKubeletConfig encodes an internal KubeletConfiguration to an external YAML representation
|
// EncodeKubeletConfig encodes an internal KubeletConfiguration to an external YAML representation
|
||||||
func EncodeKubeletConfig(internal *kubeletconfig.KubeletConfiguration, targetVersion schema.GroupVersion) ([]byte, error) {
|
func EncodeKubeletConfig(internal *kubeletconfig.KubeletConfiguration, targetVersion schema.GroupVersion) ([]byte, error) {
|
||||||
encoder, err := newKubeletConfigYAMLEncoder(targetVersion)
|
encoder, err := NewKubeletconfigYAMLEncoder(targetVersion)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
@ -44,8 +44,8 @@ func EncodeKubeletConfig(internal *kubeletconfig.KubeletConfiguration, targetVer
|
|||||||
return data, nil
|
return data, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// newKubeletConfigYAMLEncoder returns an encoder that can write a KubeletConfig to YAML
|
// NewKubeletconfigYAMLEncoder returns an encoder that can write objects in the kubeletconfig API group to YAML
|
||||||
func newKubeletConfigYAMLEncoder(targetVersion schema.GroupVersion) (runtime.Encoder, error) {
|
func NewKubeletconfigYAMLEncoder(targetVersion schema.GroupVersion) (runtime.Encoder, error) {
|
||||||
_, codecs, err := scheme.NewSchemeAndCodecs()
|
_, codecs, err := scheme.NewSchemeAndCodecs()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
|
@ -18,33 +18,6 @@ package equal
|
|||||||
|
|
||||||
import apiv1 "k8s.io/api/core/v1"
|
import apiv1 "k8s.io/api/core/v1"
|
||||||
|
|
||||||
// ConfigSourceEq returns true if the two config sources are semantically equivalent in the context of dynamic config
|
|
||||||
func ConfigSourceEq(a, b *apiv1.NodeConfigSource) bool {
|
|
||||||
if a == b {
|
|
||||||
return true
|
|
||||||
} else if a == nil || b == nil {
|
|
||||||
// not equal, and one is nil
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
// check equality of config source subifelds
|
|
||||||
if a.ConfigMapRef != b.ConfigMapRef {
|
|
||||||
return ObjectRefEq(a.ConfigMapRef, b.ConfigMapRef)
|
|
||||||
}
|
|
||||||
// all internal subfields of the config source are equal
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
|
|
||||||
// ObjectRefEq returns true if the two object references are semantically equivalent in the context of dynamic config
|
|
||||||
func ObjectRefEq(a, b *apiv1.ObjectReference) bool {
|
|
||||||
if a == b {
|
|
||||||
return true
|
|
||||||
} else if a == nil || b == nil {
|
|
||||||
// not equal, and one is nil
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
return a.UID == b.UID && a.Namespace == b.Namespace && a.Name == b.Name
|
|
||||||
}
|
|
||||||
|
|
||||||
// KubeletConfigOkEq returns true if the two conditions are semantically equivalent in the context of dynamic config
|
// KubeletConfigOkEq returns true if the two conditions are semantically equivalent in the context of dynamic config
|
||||||
func KubeletConfigOkEq(a, b *apiv1.NodeCondition) bool {
|
func KubeletConfigOkEq(a, b *apiv1.NodeCondition) bool {
|
||||||
return a.Message == b.Message && a.Reason == b.Reason && a.Status == b.Status
|
return a.Message == b.Message && a.Reason == b.Reason && a.Status == b.Status
|
||||||
|
@ -21,13 +21,13 @@ import (
|
|||||||
"time"
|
"time"
|
||||||
|
|
||||||
apiv1 "k8s.io/api/core/v1"
|
apiv1 "k8s.io/api/core/v1"
|
||||||
|
apiequality "k8s.io/apimachinery/pkg/api/equality"
|
||||||
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||||
"k8s.io/apimachinery/pkg/fields"
|
"k8s.io/apimachinery/pkg/fields"
|
||||||
kuberuntime "k8s.io/apimachinery/pkg/runtime"
|
kuberuntime "k8s.io/apimachinery/pkg/runtime"
|
||||||
"k8s.io/apimachinery/pkg/watch"
|
"k8s.io/apimachinery/pkg/watch"
|
||||||
clientset "k8s.io/client-go/kubernetes"
|
clientset "k8s.io/client-go/kubernetes"
|
||||||
"k8s.io/client-go/tools/cache"
|
"k8s.io/client-go/tools/cache"
|
||||||
utilequal "k8s.io/kubernetes/pkg/kubelet/kubeletconfig/util/equal"
|
|
||||||
utillog "k8s.io/kubernetes/pkg/kubelet/kubeletconfig/util/log"
|
utillog "k8s.io/kubernetes/pkg/kubelet/kubeletconfig/util/log"
|
||||||
)
|
)
|
||||||
|
|
||||||
@ -94,7 +94,7 @@ func (cc *Controller) onUpdateNodeEvent(oldObj interface{}, newObj interface{})
|
|||||||
utillog.Errorf("failed to cast old object to Node, couldn't handle event")
|
utillog.Errorf("failed to cast old object to Node, couldn't handle event")
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
if !utilequal.ConfigSourceEq(oldNode.Spec.ConfigSource, newNode.Spec.ConfigSource) {
|
if !apiequality.Semantic.DeepEqual(oldNode.Spec.ConfigSource, newNode.Spec.ConfigSource) {
|
||||||
cc.pokeConfigSourceWorker()
|
cc.pokeConfigSourceWorker()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -91,9 +91,19 @@ func Test_nodePlugin_Admit(t *testing.T) {
|
|||||||
mynodeObjMeta = metav1.ObjectMeta{Name: "mynode"}
|
mynodeObjMeta = metav1.ObjectMeta{Name: "mynode"}
|
||||||
mynodeObj = &api.Node{ObjectMeta: mynodeObjMeta}
|
mynodeObj = &api.Node{ObjectMeta: mynodeObjMeta}
|
||||||
mynodeObjConfigA = &api.Node{ObjectMeta: mynodeObjMeta, Spec: api.NodeSpec{ConfigSource: &api.NodeConfigSource{
|
mynodeObjConfigA = &api.Node{ObjectMeta: mynodeObjMeta, Spec: api.NodeSpec{ConfigSource: &api.NodeConfigSource{
|
||||||
ConfigMapRef: &api.ObjectReference{Name: "foo", Namespace: "bar", UID: "fooUID"}}}}
|
ConfigMap: &api.ConfigMapNodeConfigSource{
|
||||||
|
Name: "foo",
|
||||||
|
Namespace: "bar",
|
||||||
|
UID: "fooUID",
|
||||||
|
KubeletConfigKey: "kubelet",
|
||||||
|
}}}}
|
||||||
mynodeObjConfigB = &api.Node{ObjectMeta: mynodeObjMeta, Spec: api.NodeSpec{ConfigSource: &api.NodeConfigSource{
|
mynodeObjConfigB = &api.Node{ObjectMeta: mynodeObjMeta, Spec: api.NodeSpec{ConfigSource: &api.NodeConfigSource{
|
||||||
ConfigMapRef: &api.ObjectReference{Name: "qux", Namespace: "bar", UID: "quxUID"}}}}
|
ConfigMap: &api.ConfigMapNodeConfigSource{
|
||||||
|
Name: "qux",
|
||||||
|
Namespace: "bar",
|
||||||
|
UID: "quxUID",
|
||||||
|
KubeletConfigKey: "kubelet",
|
||||||
|
}}}}
|
||||||
othernodeObj = &api.Node{ObjectMeta: metav1.ObjectMeta{Name: "othernode"}}
|
othernodeObj = &api.Node{ObjectMeta: metav1.ObjectMeta{Name: "othernode"}}
|
||||||
|
|
||||||
mymirrorpod = makeTestPod("ns", "mymirrorpod", "mynode", true)
|
mymirrorpod = makeTestPod("ns", "mymirrorpod", "mynode", true)
|
||||||
|
@ -346,7 +346,7 @@ func (g *Graph) DeleteVolumeAttachment(name string) {
|
|||||||
g.deleteVertex_locked(vaVertexType, "", name)
|
g.deleteVertex_locked(vaVertexType, "", name)
|
||||||
}
|
}
|
||||||
|
|
||||||
// SetNodeConfigMap sets up edges for the Node.Spec.ConfigSource.ConfigMapRef relationship:
|
// SetNodeConfigMap sets up edges for the Node.Spec.ConfigSource.ConfigMap relationship:
|
||||||
//
|
//
|
||||||
// configmap -> node
|
// configmap -> node
|
||||||
func (g *Graph) SetNodeConfigMap(nodeName, configMapName, configMapNamespace string) {
|
func (g *Graph) SetNodeConfigMap(nodeName, configMapName, configMapNamespace string) {
|
||||||
|
@ -84,19 +84,19 @@ func (g *graphPopulator) updateNode(oldObj, obj interface{}) {
|
|||||||
oldNode = oldObj.(*api.Node)
|
oldNode = oldObj.(*api.Node)
|
||||||
}
|
}
|
||||||
|
|
||||||
// we only set up rules for ConfigMapRef today, because that is the only reference type
|
// we only set up rules for ConfigMap today, because that is the only reference type
|
||||||
|
|
||||||
var name, namespace string
|
var name, namespace string
|
||||||
if source := node.Spec.ConfigSource; source != nil && source.ConfigMapRef != nil {
|
if source := node.Spec.ConfigSource; source != nil && source.ConfigMap != nil {
|
||||||
name = source.ConfigMapRef.Name
|
name = source.ConfigMap.Name
|
||||||
namespace = source.ConfigMapRef.Namespace
|
namespace = source.ConfigMap.Namespace
|
||||||
}
|
}
|
||||||
|
|
||||||
var oldName, oldNamespace string
|
var oldName, oldNamespace string
|
||||||
if oldNode != nil {
|
if oldNode != nil {
|
||||||
if oldSource := oldNode.Spec.ConfigSource; oldSource != nil && oldSource.ConfigMapRef != nil {
|
if oldSource := oldNode.Spec.ConfigSource; oldSource != nil && oldSource.ConfigMap != nil {
|
||||||
oldName = oldSource.ConfigMapRef.Name
|
oldName = oldSource.ConfigMap.Name
|
||||||
oldNamespace = oldSource.ConfigMapRef.Namespace
|
oldNamespace = oldSource.ConfigMap.Namespace
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -693,10 +693,11 @@ func generate(opts sampleDataOpts) ([]*api.Node, []*api.Pod, []*api.PersistentVo
|
|||||||
ObjectMeta: metav1.ObjectMeta{Name: nodeName},
|
ObjectMeta: metav1.ObjectMeta{Name: nodeName},
|
||||||
Spec: api.NodeSpec{
|
Spec: api.NodeSpec{
|
||||||
ConfigSource: &api.NodeConfigSource{
|
ConfigSource: &api.NodeConfigSource{
|
||||||
ConfigMapRef: &api.ObjectReference{
|
ConfigMap: &api.ConfigMapNodeConfigSource{
|
||||||
Name: name,
|
Name: name,
|
||||||
Namespace: "ns0",
|
Namespace: "ns0",
|
||||||
UID: types.UID(fmt.Sprintf("ns0-%s", name)),
|
UID: types.UID(fmt.Sprintf("ns0-%s", name)),
|
||||||
|
KubeletConfigKey: "kubelet",
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
2156
staging/src/k8s.io/api/core/v1/generated.pb.go
generated
2156
staging/src/k8s.io/api/core/v1/generated.pb.go
generated
File diff suppressed because it is too large
Load Diff
@ -439,6 +439,34 @@ message ConfigMapList {
|
|||||||
repeated ConfigMap items = 2;
|
repeated ConfigMap items = 2;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// ConfigMapNodeConfigSource contains the information to reference a ConfigMap as a config source for the Node.
|
||||||
|
message ConfigMapNodeConfigSource {
|
||||||
|
// Namespace is the metadata.namespace of the referenced ConfigMap.
|
||||||
|
// This field is required in all cases.
|
||||||
|
optional string namespace = 1;
|
||||||
|
|
||||||
|
// Name is the metadata.name of the referenced ConfigMap.
|
||||||
|
// This field is required in all cases.
|
||||||
|
optional string name = 2;
|
||||||
|
|
||||||
|
// UID is the metadata.UID of the referenced ConfigMap.
|
||||||
|
// This field is currently reqired in Node.Spec.
|
||||||
|
// TODO(#61643): This field will be forbidden in Node.Spec when #61643 is resolved.
|
||||||
|
// TODO(#56896): This field will be required in Node.Status when #56896 is resolved.
|
||||||
|
// +optional
|
||||||
|
optional string uid = 3;
|
||||||
|
|
||||||
|
// ResourceVersion is the metadata.ResourceVersion of the referenced ConfigMap.
|
||||||
|
// This field is forbidden in Node.Spec.
|
||||||
|
// TODO(#56896): This field will be required in Node.Status when #56896 is resolved.
|
||||||
|
// +optional
|
||||||
|
optional string resourceVersion = 4;
|
||||||
|
|
||||||
|
// KubeletConfigKey declares which key of the referenced ConfigMap corresponds to the KubeletConfiguration structure
|
||||||
|
// This field is required in all cases.
|
||||||
|
optional string kubeletConfigKey = 5;
|
||||||
|
}
|
||||||
|
|
||||||
// Adapts a ConfigMap into a projected volume.
|
// Adapts a ConfigMap into a projected volume.
|
||||||
//
|
//
|
||||||
// The contents of the target ConfigMap's Data field will be presented in a
|
// The contents of the target ConfigMap's Data field will be presented in a
|
||||||
@ -1815,7 +1843,8 @@ message NodeCondition {
|
|||||||
|
|
||||||
// NodeConfigSource specifies a source of node configuration. Exactly one subfield (excluding metadata) must be non-nil.
|
// NodeConfigSource specifies a source of node configuration. Exactly one subfield (excluding metadata) must be non-nil.
|
||||||
message NodeConfigSource {
|
message NodeConfigSource {
|
||||||
optional ObjectReference configMapRef = 1;
|
// ConfigMap is a reference to a Node's ConfigMap
|
||||||
|
optional ConfigMapNodeConfigSource configMap = 2;
|
||||||
}
|
}
|
||||||
|
|
||||||
// NodeDaemonEndpoints lists ports opened by daemons running on the Node.
|
// NodeDaemonEndpoints lists ports opened by daemons running on the Node.
|
||||||
|
@ -57,7 +57,6 @@ func addKnownTypes(scheme *runtime.Scheme) error {
|
|||||||
&Endpoints{},
|
&Endpoints{},
|
||||||
&EndpointsList{},
|
&EndpointsList{},
|
||||||
&Node{},
|
&Node{},
|
||||||
&NodeConfigSource{},
|
|
||||||
&NodeList{},
|
&NodeList{},
|
||||||
&NodeProxyOptions{},
|
&NodeProxyOptions{},
|
||||||
&Binding{},
|
&Binding{},
|
||||||
|
@ -3640,12 +3640,49 @@ type NodeSpec struct {
|
|||||||
DoNotUse_ExternalID string `json:"externalID,omitempty" protobuf:"bytes,2,opt,name=externalID"`
|
DoNotUse_ExternalID string `json:"externalID,omitempty" protobuf:"bytes,2,opt,name=externalID"`
|
||||||
}
|
}
|
||||||
|
|
||||||
// +k8s:deepcopy-gen:interfaces=k8s.io/apimachinery/pkg/runtime.Object
|
|
||||||
|
|
||||||
// NodeConfigSource specifies a source of node configuration. Exactly one subfield (excluding metadata) must be non-nil.
|
// NodeConfigSource specifies a source of node configuration. Exactly one subfield (excluding metadata) must be non-nil.
|
||||||
type NodeConfigSource struct {
|
type NodeConfigSource struct {
|
||||||
metav1.TypeMeta `json:",inline"`
|
// For historical context, regarding the below kind, apiVersion, and configMapRef deprecation tags:
|
||||||
ConfigMapRef *ObjectReference `json:"configMapRef,omitempty" protobuf:"bytes,1,opt,name=configMapRef"`
|
// 1. kind/apiVersion were used by the kubelet to persist this struct to disk (they had no protobuf tags)
|
||||||
|
// 2. configMapRef and proto tag 1 were used by the API to refer to a configmap,
|
||||||
|
// but used a generic ObjectReference type that didn't really have the fields we needed
|
||||||
|
// All uses/persistence of the NodeConfigSource struct prior to 1.11 were gated by alpha feature flags,
|
||||||
|
// so there was no persisted data for these fields that needed to be migrated/handled.
|
||||||
|
|
||||||
|
// +k8s:deprecated=kind
|
||||||
|
// +k8s:deprecated=apiVersion
|
||||||
|
// +k8s:deprecated=configMapRef,protobuf=1
|
||||||
|
|
||||||
|
// ConfigMap is a reference to a Node's ConfigMap
|
||||||
|
ConfigMap *ConfigMapNodeConfigSource `json:"configMap,omitempty" protobuf:"bytes,2,opt,name=configMap"`
|
||||||
|
}
|
||||||
|
|
||||||
|
// ConfigMapNodeConfigSource contains the information to reference a ConfigMap as a config source for the Node.
|
||||||
|
type ConfigMapNodeConfigSource struct {
|
||||||
|
// Namespace is the metadata.namespace of the referenced ConfigMap.
|
||||||
|
// This field is required in all cases.
|
||||||
|
Namespace string `json:"namespace" protobuf:"bytes,1,opt,name=namespace"`
|
||||||
|
|
||||||
|
// Name is the metadata.name of the referenced ConfigMap.
|
||||||
|
// This field is required in all cases.
|
||||||
|
Name string `json:"name" protobuf:"bytes,2,opt,name=name"`
|
||||||
|
|
||||||
|
// UID is the metadata.UID of the referenced ConfigMap.
|
||||||
|
// This field is currently reqired in Node.Spec.
|
||||||
|
// TODO(#61643): This field will be forbidden in Node.Spec when #61643 is resolved.
|
||||||
|
// TODO(#56896): This field will be required in Node.Status when #56896 is resolved.
|
||||||
|
// +optional
|
||||||
|
UID types.UID `json:"uid,omitempty" protobuf:"bytes,3,opt,name=uid"`
|
||||||
|
|
||||||
|
// ResourceVersion is the metadata.ResourceVersion of the referenced ConfigMap.
|
||||||
|
// This field is forbidden in Node.Spec.
|
||||||
|
// TODO(#56896): This field will be required in Node.Status when #56896 is resolved.
|
||||||
|
// +optional
|
||||||
|
ResourceVersion string `json:"resourceVersion,omitempty" protobuf:"bytes,4,opt,name=resourceVersion"`
|
||||||
|
|
||||||
|
// KubeletConfigKey declares which key of the referenced ConfigMap corresponds to the KubeletConfiguration structure
|
||||||
|
// This field is required in all cases.
|
||||||
|
KubeletConfigKey string `json:"kubeletConfigKey" protobuf:"bytes,5,opt,name=kubeletConfigKey"`
|
||||||
}
|
}
|
||||||
|
|
||||||
// DaemonEndpoint contains information about a single Daemon endpoint.
|
// DaemonEndpoint contains information about a single Daemon endpoint.
|
||||||
|
@ -262,6 +262,19 @@ func (ConfigMapList) SwaggerDoc() map[string]string {
|
|||||||
return map_ConfigMapList
|
return map_ConfigMapList
|
||||||
}
|
}
|
||||||
|
|
||||||
|
var map_ConfigMapNodeConfigSource = map[string]string{
|
||||||
|
"": "ConfigMapNodeConfigSource contains the information to reference a ConfigMap as a config source for the Node.",
|
||||||
|
"namespace": "Namespace is the metadata.namespace of the referenced ConfigMap. This field is required in all cases.",
|
||||||
|
"name": "Name is the metadata.name of the referenced ConfigMap. This field is required in all cases.",
|
||||||
|
"uid": "UID is the metadata.UID of the referenced ConfigMap. This field is currently reqired in Node.Spec.",
|
||||||
|
"resourceVersion": "ResourceVersion is the metadata.ResourceVersion of the referenced ConfigMap. This field is forbidden in Node.Spec.",
|
||||||
|
"kubeletConfigKey": "KubeletConfigKey declares which key of the referenced ConfigMap corresponds to the KubeletConfiguration structure This field is required in all cases.",
|
||||||
|
}
|
||||||
|
|
||||||
|
func (ConfigMapNodeConfigSource) SwaggerDoc() map[string]string {
|
||||||
|
return map_ConfigMapNodeConfigSource
|
||||||
|
}
|
||||||
|
|
||||||
var map_ConfigMapProjection = map[string]string{
|
var map_ConfigMapProjection = map[string]string{
|
||||||
"": "Adapts a ConfigMap into a projected volume.\n\nThe contents of the target ConfigMap's Data field will be presented in a projected volume as files using the keys in the Data field as the file names, unless the items element is populated with specific mappings of keys to paths. Note that this is identical to a configmap volume source without the default mode.",
|
"": "Adapts a ConfigMap into a projected volume.\n\nThe contents of the target ConfigMap's Data field will be presented in a projected volume as files using the keys in the Data field as the file names, unless the items element is populated with specific mappings of keys to paths. Note that this is identical to a configmap volume source without the default mode.",
|
||||||
"items": "If unspecified, each key-value pair in the Data field of the referenced ConfigMap will be projected into the volume as a file whose name is the key and content is the value. If specified, the listed keys will be projected into the specified paths, and unlisted keys will not be present. If a key is specified which is not present in the ConfigMap, the volume setup will error unless it is marked optional. Paths must be relative and may not contain the '..' path or start with '..'.",
|
"items": "If unspecified, each key-value pair in the Data field of the referenced ConfigMap will be projected into the volume as a file whose name is the key and content is the value. If specified, the listed keys will be projected into the specified paths, and unlisted keys will not be present. If a key is specified which is not present in the ConfigMap, the volume setup will error unless it is marked optional. Paths must be relative and may not contain the '..' path or start with '..'.",
|
||||||
@ -969,7 +982,8 @@ func (NodeCondition) SwaggerDoc() map[string]string {
|
|||||||
}
|
}
|
||||||
|
|
||||||
var map_NodeConfigSource = map[string]string{
|
var map_NodeConfigSource = map[string]string{
|
||||||
"": "NodeConfigSource specifies a source of node configuration. Exactly one subfield (excluding metadata) must be non-nil.",
|
"": "NodeConfigSource specifies a source of node configuration. Exactly one subfield (excluding metadata) must be non-nil.",
|
||||||
|
"configMap": "ConfigMap is a reference to a Node's ConfigMap",
|
||||||
}
|
}
|
||||||
|
|
||||||
func (NodeConfigSource) SwaggerDoc() map[string]string {
|
func (NodeConfigSource) SwaggerDoc() map[string]string {
|
||||||
|
@ -631,6 +631,22 @@ func (in *ConfigMapList) DeepCopyObject() runtime.Object {
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
|
||||||
|
func (in *ConfigMapNodeConfigSource) DeepCopyInto(out *ConfigMapNodeConfigSource) {
|
||||||
|
*out = *in
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ConfigMapNodeConfigSource.
|
||||||
|
func (in *ConfigMapNodeConfigSource) DeepCopy() *ConfigMapNodeConfigSource {
|
||||||
|
if in == nil {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
out := new(ConfigMapNodeConfigSource)
|
||||||
|
in.DeepCopyInto(out)
|
||||||
|
return out
|
||||||
|
}
|
||||||
|
|
||||||
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
|
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
|
||||||
func (in *ConfigMapProjection) DeepCopyInto(out *ConfigMapProjection) {
|
func (in *ConfigMapProjection) DeepCopyInto(out *ConfigMapProjection) {
|
||||||
*out = *in
|
*out = *in
|
||||||
@ -2360,13 +2376,12 @@ func (in *NodeCondition) DeepCopy() *NodeCondition {
|
|||||||
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
|
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
|
||||||
func (in *NodeConfigSource) DeepCopyInto(out *NodeConfigSource) {
|
func (in *NodeConfigSource) DeepCopyInto(out *NodeConfigSource) {
|
||||||
*out = *in
|
*out = *in
|
||||||
out.TypeMeta = in.TypeMeta
|
if in.ConfigMap != nil {
|
||||||
if in.ConfigMapRef != nil {
|
in, out := &in.ConfigMap, &out.ConfigMap
|
||||||
in, out := &in.ConfigMapRef, &out.ConfigMapRef
|
|
||||||
if *in == nil {
|
if *in == nil {
|
||||||
*out = nil
|
*out = nil
|
||||||
} else {
|
} else {
|
||||||
*out = new(ObjectReference)
|
*out = new(ConfigMapNodeConfigSource)
|
||||||
**out = **in
|
**out = **in
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -2383,14 +2398,6 @@ func (in *NodeConfigSource) DeepCopy() *NodeConfigSource {
|
|||||||
return out
|
return out
|
||||||
}
|
}
|
||||||
|
|
||||||
// DeepCopyObject is an autogenerated deepcopy function, copying the receiver, creating a new runtime.Object.
|
|
||||||
func (in *NodeConfigSource) DeepCopyObject() runtime.Object {
|
|
||||||
if c := in.DeepCopy(); c != nil {
|
|
||||||
return c
|
|
||||||
}
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
|
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
|
||||||
func (in *NodeDaemonEndpoints) DeepCopyInto(out *NodeDaemonEndpoints) {
|
func (in *NodeDaemonEndpoints) DeepCopyInto(out *NodeDaemonEndpoints) {
|
||||||
*out = *in
|
*out = *in
|
||||||
|
@ -84,10 +84,12 @@ var _ = framework.KubeDescribe("DynamicKubeletConfiguration [Feature:DynamicKube
|
|||||||
// were initially set via the locally provisioned configuration.
|
// were initially set via the locally provisioned configuration.
|
||||||
// This is the same strategy several other e2e node tests use.
|
// This is the same strategy several other e2e node tests use.
|
||||||
setAndTestKubeletConfigState(f, &configState{desc: "reset to original values",
|
setAndTestKubeletConfigState(f, &configState{desc: "reset to original values",
|
||||||
configSource: &apiv1.NodeConfigSource{ConfigMapRef: &apiv1.ObjectReference{
|
configSource: &apiv1.NodeConfigSource{ConfigMap: &apiv1.ConfigMapNodeConfigSource{
|
||||||
UID: originalConfigMap.UID,
|
UID: originalConfigMap.UID,
|
||||||
Namespace: originalConfigMap.Namespace,
|
Namespace: originalConfigMap.Namespace,
|
||||||
Name: originalConfigMap.Name}},
|
Name: originalConfigMap.Name,
|
||||||
|
KubeletConfigKey: "kubelet",
|
||||||
|
}},
|
||||||
expectConfigOk: &apiv1.NodeCondition{Type: apiv1.NodeKubeletConfigOk, Status: apiv1.ConditionTrue,
|
expectConfigOk: &apiv1.NodeCondition{Type: apiv1.NodeKubeletConfigOk, Status: apiv1.ConditionTrue,
|
||||||
Message: fmt.Sprintf(status.CurRemoteMessageFmt, configMapAPIPath(originalConfigMap)),
|
Message: fmt.Sprintf(status.CurRemoteMessageFmt, configMapAPIPath(originalConfigMap)),
|
||||||
Reason: status.CurRemoteOkayReason},
|
Reason: status.CurRemoteOkayReason},
|
||||||
@ -123,8 +125,8 @@ var _ = framework.KubeDescribe("DynamicKubeletConfiguration [Feature:DynamicKube
|
|||||||
framework.ExpectNoError(err)
|
framework.ExpectNoError(err)
|
||||||
|
|
||||||
states := []configState{
|
states := []configState{
|
||||||
// Node.Spec.ConfigSource is nil
|
{
|
||||||
{desc: "Node.Spec.ConfigSource is nil",
|
desc: "Node.Spec.ConfigSource is nil",
|
||||||
configSource: nil,
|
configSource: nil,
|
||||||
expectConfigOk: &apiv1.NodeCondition{Type: apiv1.NodeKubeletConfigOk, Status: apiv1.ConditionTrue,
|
expectConfigOk: &apiv1.NodeCondition{Type: apiv1.NodeKubeletConfigOk, Status: apiv1.ConditionTrue,
|
||||||
Message: status.CurLocalMessage,
|
Message: status.CurLocalMessage,
|
||||||
@ -132,65 +134,107 @@ var _ = framework.KubeDescribe("DynamicKubeletConfiguration [Feature:DynamicKube
|
|||||||
expectConfig: nil,
|
expectConfig: nil,
|
||||||
event: true,
|
event: true,
|
||||||
},
|
},
|
||||||
|
|
||||||
// Node.Spec.ConfigSource has all nil subfields
|
// Node.Spec.ConfigSource has all nil subfields
|
||||||
{desc: "Node.Spec.ConfigSource has all nil subfields",
|
{desc: "Node.Spec.ConfigSource has all nil subfields",
|
||||||
configSource: &apiv1.NodeConfigSource{},
|
configSource: &apiv1.NodeConfigSource{},
|
||||||
apierr: "exactly one reference subfield must be non-nil",
|
apierr: "exactly one reference subfield must be non-nil",
|
||||||
},
|
},
|
||||||
|
// Node.Spec.ConfigSource.ConfigMap is partial
|
||||||
// Node.Spec.ConfigSource.ConfigMapRef is partial
|
{desc: "Node.Spec.ConfigSource.ConfigMap is partial",
|
||||||
{desc: "Node.Spec.ConfigSource.ConfigMapRef is partial",
|
configSource: &apiv1.NodeConfigSource{ConfigMap: &apiv1.ConfigMapNodeConfigSource{
|
||||||
configSource: &apiv1.NodeConfigSource{ConfigMapRef: &apiv1.ObjectReference{
|
UID: "foo",
|
||||||
UID: "foo",
|
Name: "bar",
|
||||||
Name: "bar"}}, // missing Namespace
|
KubeletConfigKey: "kubelet",
|
||||||
apierr: "name, namespace, and UID must all be non-empty",
|
}}, // missing Namespace
|
||||||
|
apierr: "spec.configSource.configMap.namespace: Required value: namespace must be set in spec",
|
||||||
},
|
},
|
||||||
|
{desc: "Node.Spec.ConfigSource.ConfigMap.ResourceVersion is illegally specified",
|
||||||
// Node.Spec.ConfigSource's UID does not align with namespace/name
|
configSource: &apiv1.NodeConfigSource{ConfigMap: &apiv1.ConfigMapNodeConfigSource{
|
||||||
{desc: "Node.Spec.ConfigSource.ConfigMapRef.UID does not align with Namespace/Name",
|
UID: "foo",
|
||||||
configSource: &apiv1.NodeConfigSource{ConfigMapRef: &apiv1.ObjectReference{UID: "foo",
|
Name: "bar",
|
||||||
Namespace: correctConfigMap.Namespace,
|
Namespace: "baz",
|
||||||
Name: correctConfigMap.Name}},
|
ResourceVersion: "1",
|
||||||
|
KubeletConfigKey: "kubelet",
|
||||||
|
}},
|
||||||
|
apierr: "spec.configSource.configMap.resourceVersion: Forbidden: resourceVersion must not be set in spec",
|
||||||
|
},
|
||||||
|
{desc: "Node.Spec.ConfigSource.ConfigMap has invalid namespace",
|
||||||
|
configSource: &apiv1.NodeConfigSource{ConfigMap: &apiv1.ConfigMapNodeConfigSource{
|
||||||
|
UID: "foo",
|
||||||
|
Name: "bar",
|
||||||
|
Namespace: "../baz",
|
||||||
|
KubeletConfigKey: "kubelet",
|
||||||
|
}},
|
||||||
|
apierr: "spec.configSource.configMap.namespace: Invalid value",
|
||||||
|
},
|
||||||
|
{desc: "Node.Spec.ConfigSource.ConfigMap has invalid name",
|
||||||
|
configSource: &apiv1.NodeConfigSource{ConfigMap: &apiv1.ConfigMapNodeConfigSource{
|
||||||
|
UID: "foo",
|
||||||
|
Name: "../bar",
|
||||||
|
Namespace: "baz",
|
||||||
|
KubeletConfigKey: "kubelet",
|
||||||
|
}},
|
||||||
|
apierr: "spec.configSource.configMap.name: Invalid value",
|
||||||
|
},
|
||||||
|
{desc: "Node.Spec.ConfigSource.ConfigMap has invalid kubeletConfigKey",
|
||||||
|
configSource: &apiv1.NodeConfigSource{ConfigMap: &apiv1.ConfigMapNodeConfigSource{
|
||||||
|
UID: "foo",
|
||||||
|
Name: "bar",
|
||||||
|
Namespace: "baz",
|
||||||
|
KubeletConfigKey: "../qux",
|
||||||
|
}},
|
||||||
|
apierr: "spec.configSource.configMap.kubeletConfigKey: Invalid value",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
desc: "Node.Spec.ConfigSource.ConfigMap.UID does not align with Namespace/Name",
|
||||||
|
configSource: &apiv1.NodeConfigSource{ConfigMap: &apiv1.ConfigMapNodeConfigSource{
|
||||||
|
UID: "foo",
|
||||||
|
Namespace: correctConfigMap.Namespace,
|
||||||
|
Name: correctConfigMap.Name,
|
||||||
|
KubeletConfigKey: "kubelet",
|
||||||
|
}},
|
||||||
expectConfigOk: &apiv1.NodeCondition{Type: apiv1.NodeKubeletConfigOk, Status: apiv1.ConditionFalse,
|
expectConfigOk: &apiv1.NodeCondition{Type: apiv1.NodeKubeletConfigOk, Status: apiv1.ConditionFalse,
|
||||||
Message: "",
|
Message: "",
|
||||||
Reason: fmt.Sprintf(status.FailSyncReasonFmt, fmt.Sprintf(status.FailSyncReasonUIDMismatchFmt, "foo", configMapAPIPath(correctConfigMap), correctConfigMap.UID))},
|
Reason: fmt.Sprintf(status.FailSyncReasonFmt, fmt.Sprintf(status.FailSyncReasonUIDMismatchFmt, "foo", configMapAPIPath(correctConfigMap), correctConfigMap.UID))},
|
||||||
expectConfig: nil,
|
expectConfig: nil,
|
||||||
event: false,
|
event: false,
|
||||||
},
|
},
|
||||||
|
{
|
||||||
// correct
|
desc: "correct",
|
||||||
{desc: "correct",
|
configSource: &apiv1.NodeConfigSource{ConfigMap: &apiv1.ConfigMapNodeConfigSource{
|
||||||
configSource: &apiv1.NodeConfigSource{ConfigMapRef: &apiv1.ObjectReference{
|
UID: correctConfigMap.UID,
|
||||||
UID: correctConfigMap.UID,
|
Namespace: correctConfigMap.Namespace,
|
||||||
Namespace: correctConfigMap.Namespace,
|
Name: correctConfigMap.Name,
|
||||||
Name: correctConfigMap.Name}},
|
KubeletConfigKey: "kubelet",
|
||||||
|
}},
|
||||||
expectConfigOk: &apiv1.NodeCondition{Type: apiv1.NodeKubeletConfigOk, Status: apiv1.ConditionTrue,
|
expectConfigOk: &apiv1.NodeCondition{Type: apiv1.NodeKubeletConfigOk, Status: apiv1.ConditionTrue,
|
||||||
Message: fmt.Sprintf(status.CurRemoteMessageFmt, configMapAPIPath(correctConfigMap)),
|
Message: fmt.Sprintf(status.CurRemoteMessageFmt, configMapAPIPath(correctConfigMap)),
|
||||||
Reason: status.CurRemoteOkayReason},
|
Reason: status.CurRemoteOkayReason},
|
||||||
expectConfig: correctKC,
|
expectConfig: correctKC,
|
||||||
event: true,
|
event: true,
|
||||||
},
|
},
|
||||||
|
{
|
||||||
// fail-parse
|
desc: "fail-parse",
|
||||||
{desc: "fail-parse",
|
configSource: &apiv1.NodeConfigSource{ConfigMap: &apiv1.ConfigMapNodeConfigSource{
|
||||||
configSource: &apiv1.NodeConfigSource{ConfigMapRef: &apiv1.ObjectReference{
|
UID: failParseConfigMap.UID,
|
||||||
UID: failParseConfigMap.UID,
|
Namespace: failParseConfigMap.Namespace,
|
||||||
Namespace: failParseConfigMap.Namespace,
|
Name: failParseConfigMap.Name,
|
||||||
Name: failParseConfigMap.Name}},
|
KubeletConfigKey: "kubelet",
|
||||||
|
}},
|
||||||
expectConfigOk: &apiv1.NodeCondition{Type: apiv1.NodeKubeletConfigOk, Status: apiv1.ConditionFalse,
|
expectConfigOk: &apiv1.NodeCondition{Type: apiv1.NodeKubeletConfigOk, Status: apiv1.ConditionFalse,
|
||||||
Message: status.LkgLocalMessage,
|
Message: status.LkgLocalMessage,
|
||||||
Reason: fmt.Sprintf(status.CurFailLoadReasonFmt, configMapAPIPath(failParseConfigMap))},
|
Reason: fmt.Sprintf(status.CurFailLoadReasonFmt, configMapAPIPath(failParseConfigMap))},
|
||||||
expectConfig: nil,
|
expectConfig: nil,
|
||||||
event: true,
|
event: true,
|
||||||
},
|
},
|
||||||
|
{
|
||||||
// fail-validate
|
desc: "fail-validate",
|
||||||
{desc: "fail-validate",
|
configSource: &apiv1.NodeConfigSource{ConfigMap: &apiv1.ConfigMapNodeConfigSource{
|
||||||
configSource: &apiv1.NodeConfigSource{ConfigMapRef: &apiv1.ObjectReference{
|
UID: failValidateConfigMap.UID,
|
||||||
UID: failValidateConfigMap.UID,
|
Namespace: failValidateConfigMap.Namespace,
|
||||||
Namespace: failValidateConfigMap.Namespace,
|
Name: failValidateConfigMap.Name,
|
||||||
Name: failValidateConfigMap.Name}},
|
KubeletConfigKey: "kubelet",
|
||||||
|
}},
|
||||||
expectConfigOk: &apiv1.NodeCondition{Type: apiv1.NodeKubeletConfigOk, Status: apiv1.ConditionFalse,
|
expectConfigOk: &apiv1.NodeCondition{Type: apiv1.NodeKubeletConfigOk, Status: apiv1.ConditionFalse,
|
||||||
Message: status.LkgLocalMessage,
|
Message: status.LkgLocalMessage,
|
||||||
Reason: fmt.Sprintf(status.CurFailValidateReasonFmt, configMapAPIPath(failValidateConfigMap))},
|
Reason: fmt.Sprintf(status.CurFailValidateReasonFmt, configMapAPIPath(failValidateConfigMap))},
|
||||||
@ -229,10 +273,12 @@ var _ = framework.KubeDescribe("DynamicKubeletConfiguration [Feature:DynamicKube
|
|||||||
states := []configState{
|
states := []configState{
|
||||||
// intended lkg
|
// intended lkg
|
||||||
{desc: "intended last-known-good",
|
{desc: "intended last-known-good",
|
||||||
configSource: &apiv1.NodeConfigSource{ConfigMapRef: &apiv1.ObjectReference{
|
configSource: &apiv1.NodeConfigSource{ConfigMap: &apiv1.ConfigMapNodeConfigSource{
|
||||||
UID: lkgConfigMap.UID,
|
UID: lkgConfigMap.UID,
|
||||||
Namespace: lkgConfigMap.Namespace,
|
Namespace: lkgConfigMap.Namespace,
|
||||||
Name: lkgConfigMap.Name}},
|
Name: lkgConfigMap.Name,
|
||||||
|
KubeletConfigKey: "kubelet",
|
||||||
|
}},
|
||||||
expectConfigOk: &apiv1.NodeCondition{Type: apiv1.NodeKubeletConfigOk, Status: apiv1.ConditionTrue,
|
expectConfigOk: &apiv1.NodeCondition{Type: apiv1.NodeKubeletConfigOk, Status: apiv1.ConditionTrue,
|
||||||
Message: fmt.Sprintf(status.CurRemoteMessageFmt, configMapAPIPath(lkgConfigMap)),
|
Message: fmt.Sprintf(status.CurRemoteMessageFmt, configMapAPIPath(lkgConfigMap)),
|
||||||
Reason: status.CurRemoteOkayReason},
|
Reason: status.CurRemoteOkayReason},
|
||||||
@ -242,10 +288,12 @@ var _ = framework.KubeDescribe("DynamicKubeletConfiguration [Feature:DynamicKube
|
|||||||
|
|
||||||
// bad config
|
// bad config
|
||||||
{desc: "bad config",
|
{desc: "bad config",
|
||||||
configSource: &apiv1.NodeConfigSource{ConfigMapRef: &apiv1.ObjectReference{
|
configSource: &apiv1.NodeConfigSource{ConfigMap: &apiv1.ConfigMapNodeConfigSource{
|
||||||
UID: badConfigMap.UID,
|
UID: badConfigMap.UID,
|
||||||
Namespace: badConfigMap.Namespace,
|
Namespace: badConfigMap.Namespace,
|
||||||
Name: badConfigMap.Name}},
|
Name: badConfigMap.Name,
|
||||||
|
KubeletConfigKey: "kubelet",
|
||||||
|
}},
|
||||||
expectConfigOk: &apiv1.NodeCondition{Type: apiv1.NodeKubeletConfigOk, Status: apiv1.ConditionFalse,
|
expectConfigOk: &apiv1.NodeCondition{Type: apiv1.NodeKubeletConfigOk, Status: apiv1.ConditionFalse,
|
||||||
Message: fmt.Sprintf(status.LkgRemoteMessageFmt, configMapAPIPath(lkgConfigMap)),
|
Message: fmt.Sprintf(status.LkgRemoteMessageFmt, configMapAPIPath(lkgConfigMap)),
|
||||||
Reason: fmt.Sprintf(status.CurFailLoadReasonFmt, configMapAPIPath(badConfigMap))},
|
Reason: fmt.Sprintf(status.CurFailLoadReasonFmt, configMapAPIPath(badConfigMap))},
|
||||||
@ -259,6 +307,55 @@ var _ = framework.KubeDescribe("DynamicKubeletConfiguration [Feature:DynamicKube
|
|||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
|
||||||
|
Context("When a remote config becomes the new last-known-good, and then Node.ConfigSource.ConfigMap.KubeletConfigKey is updated to use a new, bad config", func() {
|
||||||
|
It("the Kubelet should report a status and configz indicating that it rolled back to the new last-known-good", func() {
|
||||||
|
const badConfigKey = "bad"
|
||||||
|
var err error
|
||||||
|
// we base the "lkg" configmap off of the current configuration
|
||||||
|
lkgKC := originalKC.DeepCopy()
|
||||||
|
combinedConfigMap := newKubeletConfigMap("dynamic-kubelet-config-test-combined", lkgKC)
|
||||||
|
combinedConfigMap.Data[badConfigKey] = "{0xdeadbeef}"
|
||||||
|
combinedConfigMap, err = f.ClientSet.CoreV1().ConfigMaps("kube-system").Create(combinedConfigMap)
|
||||||
|
framework.ExpectNoError(err)
|
||||||
|
|
||||||
|
states := []configState{
|
||||||
|
// intended lkg
|
||||||
|
{desc: "intended last-known-good",
|
||||||
|
configSource: &apiv1.NodeConfigSource{ConfigMap: &apiv1.ConfigMapNodeConfigSource{
|
||||||
|
UID: combinedConfigMap.UID,
|
||||||
|
Namespace: combinedConfigMap.Namespace,
|
||||||
|
Name: combinedConfigMap.Name,
|
||||||
|
KubeletConfigKey: "kubelet",
|
||||||
|
}},
|
||||||
|
expectConfigOk: &apiv1.NodeCondition{Type: apiv1.NodeKubeletConfigOk, Status: apiv1.ConditionTrue,
|
||||||
|
Message: fmt.Sprintf(status.CurRemoteMessageFmt, configMapAPIPath(combinedConfigMap)),
|
||||||
|
Reason: status.CurRemoteOkayReason},
|
||||||
|
expectConfig: lkgKC,
|
||||||
|
event: true,
|
||||||
|
},
|
||||||
|
|
||||||
|
// bad config
|
||||||
|
{desc: "bad config",
|
||||||
|
configSource: &apiv1.NodeConfigSource{ConfigMap: &apiv1.ConfigMapNodeConfigSource{
|
||||||
|
UID: combinedConfigMap.UID,
|
||||||
|
Namespace: combinedConfigMap.Namespace,
|
||||||
|
Name: combinedConfigMap.Name,
|
||||||
|
KubeletConfigKey: badConfigKey,
|
||||||
|
}},
|
||||||
|
expectConfigOk: &apiv1.NodeCondition{Type: apiv1.NodeKubeletConfigOk, Status: apiv1.ConditionFalse,
|
||||||
|
// TODO(mtaufen): status should be more informative, and report the key being used
|
||||||
|
Message: fmt.Sprintf(status.LkgRemoteMessageFmt, configMapAPIPath(combinedConfigMap)),
|
||||||
|
Reason: fmt.Sprintf(status.CurFailLoadReasonFmt, configMapAPIPath(combinedConfigMap))},
|
||||||
|
expectConfig: lkgKC,
|
||||||
|
event: true,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
// wait 12 minutes after setting the first config to ensure it has time to pass the trial duration
|
||||||
|
testBothDirections(f, &states[0], states[1:], 12*time.Minute)
|
||||||
|
})
|
||||||
|
})
|
||||||
|
|
||||||
// This stress test will help turn up resource leaks across kubelet restarts that can, over time,
|
// This stress test will help turn up resource leaks across kubelet restarts that can, over time,
|
||||||
// break our ability to dynamically update kubelet config
|
// break our ability to dynamically update kubelet config
|
||||||
Context("When changing the configuration 100 times", func() {
|
Context("When changing the configuration 100 times", func() {
|
||||||
@ -280,10 +377,12 @@ var _ = framework.KubeDescribe("DynamicKubeletConfiguration [Feature:DynamicKube
|
|||||||
|
|
||||||
states := []configState{
|
states := []configState{
|
||||||
{desc: "cm1",
|
{desc: "cm1",
|
||||||
configSource: &apiv1.NodeConfigSource{ConfigMapRef: &apiv1.ObjectReference{
|
configSource: &apiv1.NodeConfigSource{ConfigMap: &apiv1.ConfigMapNodeConfigSource{
|
||||||
UID: cm1.UID,
|
UID: cm1.UID,
|
||||||
Namespace: cm1.Namespace,
|
Namespace: cm1.Namespace,
|
||||||
Name: cm1.Name}},
|
Name: cm1.Name,
|
||||||
|
KubeletConfigKey: "kubelet",
|
||||||
|
}},
|
||||||
expectConfigOk: &apiv1.NodeCondition{Type: apiv1.NodeKubeletConfigOk, Status: apiv1.ConditionTrue,
|
expectConfigOk: &apiv1.NodeCondition{Type: apiv1.NodeKubeletConfigOk, Status: apiv1.ConditionTrue,
|
||||||
Message: fmt.Sprintf(status.CurRemoteMessageFmt, configMapAPIPath(cm1)),
|
Message: fmt.Sprintf(status.CurRemoteMessageFmt, configMapAPIPath(cm1)),
|
||||||
Reason: status.CurRemoteOkayReason},
|
Reason: status.CurRemoteOkayReason},
|
||||||
@ -292,10 +391,12 @@ var _ = framework.KubeDescribe("DynamicKubeletConfiguration [Feature:DynamicKube
|
|||||||
},
|
},
|
||||||
|
|
||||||
{desc: "cm2",
|
{desc: "cm2",
|
||||||
configSource: &apiv1.NodeConfigSource{ConfigMapRef: &apiv1.ObjectReference{
|
configSource: &apiv1.NodeConfigSource{ConfigMap: &apiv1.ConfigMapNodeConfigSource{
|
||||||
UID: cm2.UID,
|
UID: cm2.UID,
|
||||||
Namespace: cm2.Namespace,
|
Namespace: cm2.Namespace,
|
||||||
Name: cm2.Name}},
|
Name: cm2.Name,
|
||||||
|
KubeletConfigKey: "kubelet",
|
||||||
|
}},
|
||||||
expectConfigOk: &apiv1.NodeCondition{Type: apiv1.NodeKubeletConfigOk, Status: apiv1.ConditionTrue,
|
expectConfigOk: &apiv1.NodeCondition{Type: apiv1.NodeKubeletConfigOk, Status: apiv1.ConditionTrue,
|
||||||
Message: fmt.Sprintf(status.CurRemoteMessageFmt, configMapAPIPath(cm2)),
|
Message: fmt.Sprintf(status.CurRemoteMessageFmt, configMapAPIPath(cm2)),
|
||||||
Reason: status.CurRemoteOkayReason},
|
Reason: status.CurRemoteOkayReason},
|
||||||
@ -335,7 +436,7 @@ func testBothDirections(f *framework.Framework, first *configState, states []con
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// setAndTestKubeletConfigState tests that after setting the config source, the ConfigOk condition
|
// setAndTestKubeletConfigState tests that after setting the config source, the KubeletConfigOk condition
|
||||||
// and (if appropriate) configuration exposed via conifgz are as expected.
|
// and (if appropriate) configuration exposed via conifgz are as expected.
|
||||||
// The configuration will be converted to the internal type prior to comparison.
|
// The configuration will be converted to the internal type prior to comparison.
|
||||||
func setAndTestKubeletConfigState(f *framework.Framework, state *configState, expectEvent bool) {
|
func setAndTestKubeletConfigState(f *framework.Framework, state *configState, expectEvent bool) {
|
||||||
@ -479,8 +580,8 @@ func checkEvent(f *framework.Framework, desc string, expect *apiv1.NodeConfigSou
|
|||||||
// ensure the message is what we expect (including the resource path)
|
// ensure the message is what we expect (including the resource path)
|
||||||
expectMessage := fmt.Sprintf(controller.EventMessageFmt, controller.LocalConfigMessage)
|
expectMessage := fmt.Sprintf(controller.EventMessageFmt, controller.LocalConfigMessage)
|
||||||
if expect != nil {
|
if expect != nil {
|
||||||
if expect.ConfigMapRef != nil {
|
if expect.ConfigMap != nil {
|
||||||
expectMessage = fmt.Sprintf(controller.EventMessageFmt, fmt.Sprintf("/api/v1/namespaces/%s/configmaps/%s", expect.ConfigMapRef.Namespace, expect.ConfigMapRef.Name))
|
expectMessage = fmt.Sprintf(controller.EventMessageFmt, fmt.Sprintf("/api/v1/namespaces/%s/configmaps/%s", expect.ConfigMap.Namespace, expect.ConfigMap.Name))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if expectMessage != recent.Message {
|
if expectMessage != recent.Message {
|
||||||
|
@ -57,8 +57,10 @@ var startServices = flag.Bool("start-services", true, "If true, start local node
|
|||||||
var stopServices = flag.Bool("stop-services", true, "If true, stop local node services after running tests")
|
var stopServices = flag.Bool("stop-services", true, "If true, stop local node services after running tests")
|
||||||
var busyboxImage = "busybox"
|
var busyboxImage = "busybox"
|
||||||
|
|
||||||
// Kubelet internal cgroup name for node allocatable cgroup.
|
const (
|
||||||
const defaultNodeAllocatableCgroup = "kubepods"
|
// Kubelet internal cgroup name for node allocatable cgroup.
|
||||||
|
defaultNodeAllocatableCgroup = "kubepods"
|
||||||
|
)
|
||||||
|
|
||||||
func getNodeSummary() (*stats.Summary, error) {
|
func getNodeSummary() (*stats.Summary, error) {
|
||||||
req, err := http.NewRequest("GET", *kubeletAddress+"/stats/summary", nil)
|
req, err := http.NewRequest("GET", *kubeletAddress+"/stats/summary", nil)
|
||||||
@ -167,10 +169,11 @@ func setKubeletConfiguration(f *framework.Framework, kubeCfg *kubeletconfig.Kube
|
|||||||
|
|
||||||
// create the reference and set Node.Spec.ConfigSource
|
// create the reference and set Node.Spec.ConfigSource
|
||||||
src := &apiv1.NodeConfigSource{
|
src := &apiv1.NodeConfigSource{
|
||||||
ConfigMapRef: &apiv1.ObjectReference{
|
ConfigMap: &apiv1.ConfigMapNodeConfigSource{
|
||||||
Namespace: "kube-system",
|
Namespace: "kube-system",
|
||||||
Name: cm.Name,
|
Name: cm.Name,
|
||||||
UID: cm.UID,
|
UID: cm.UID,
|
||||||
|
KubeletConfigKey: "kubelet",
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -50,7 +50,6 @@ var kindWhiteList = sets.NewString(
|
|||||||
"ExportOptions",
|
"ExportOptions",
|
||||||
"GetOptions",
|
"GetOptions",
|
||||||
"ListOptions",
|
"ListOptions",
|
||||||
"NodeConfigSource",
|
|
||||||
"NodeProxyOptions",
|
"NodeProxyOptions",
|
||||||
"PodAttachOptions",
|
"PodAttachOptions",
|
||||||
"PodExecOptions",
|
"PodExecOptions",
|
||||||
|
@ -286,12 +286,13 @@ func TestNodeAuthorizer(t *testing.T) {
|
|||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
node2.Spec.ConfigSource = &api.NodeConfigSource{
|
node2.Spec.ConfigSource = &api.NodeConfigSource{
|
||||||
ConfigMapRef: &api.ObjectReference{
|
ConfigMap: &api.ConfigMapNodeConfigSource{
|
||||||
Namespace: "ns",
|
Namespace: "ns",
|
||||||
Name: "myconfigmapconfigsource",
|
Name: "myconfigmapconfigsource",
|
||||||
// validation just requires UID to be non-empty and it isn't necessary for GET,
|
// validation just requires UID to be non-empty and it isn't necessary for GET,
|
||||||
// so we just use a bogus one for the test
|
// so we just use a bogus one for the test
|
||||||
UID: "uid",
|
UID: "uid",
|
||||||
|
KubeletConfigKey: "kubelet",
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
_, err = client.Core().Nodes().Update(node2)
|
_, err = client.Core().Nodes().Update(node2)
|
||||||
|
@ -437,7 +437,6 @@ var ephemeralWhiteList = createEphemeralWhiteList(
|
|||||||
gvk("", "v1", "RangeAllocation"), // stored in various places in etcd but cannot be directly created
|
gvk("", "v1", "RangeAllocation"), // stored in various places in etcd but cannot be directly created
|
||||||
gvk("", "v1", "ComponentStatus"), // status info not stored in etcd
|
gvk("", "v1", "ComponentStatus"), // status info not stored in etcd
|
||||||
gvk("", "v1", "SerializedReference"), // used for serilization, not stored in etcd
|
gvk("", "v1", "SerializedReference"), // used for serilization, not stored in etcd
|
||||||
gvk("", "v1", "NodeConfigSource"), // subfield of node.spec, but shouldn't be directly created
|
|
||||||
gvk("", "v1", "PodStatusResult"), // wrapper object not stored in etcd
|
gvk("", "v1", "PodStatusResult"), // wrapper object not stored in etcd
|
||||||
// --
|
// --
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user