mirror of
				https://github.com/optim-enterprises-bv/kubernetes.git
				synced 2025-11-03 19:58:17 +00:00 
			
		
		
		
	Merge pull request #112643 from SergeyKanzhelev/removeDynamicKubeletConfig
remove DynamicKubeletConfig feature gate from the code
This commit is contained in:
		
							
								
								
									
										2
									
								
								api/openapi-spec/swagger.json
									
									
									
										generated
									
									
									
								
							
							
						
						
									
										2
									
								
								api/openapi-spec/swagger.json
									
									
									
										generated
									
									
									
								
							@@ -6322,7 +6322,7 @@
 | 
				
			|||||||
      "properties": {
 | 
					      "properties": {
 | 
				
			||||||
        "configSource": {
 | 
					        "configSource": {
 | 
				
			||||||
          "$ref": "#/definitions/io.k8s.api.core.v1.NodeConfigSource",
 | 
					          "$ref": "#/definitions/io.k8s.api.core.v1.NodeConfigSource",
 | 
				
			||||||
          "description": "Deprecated: Previously used to specify the source of the node's configuration for the DynamicKubeletConfig feature. This feature is removed from Kubelets as of 1.24 and will be fully removed in 1.26."
 | 
					          "description": "Deprecated: Previously used to specify the source of the node's configuration for the DynamicKubeletConfig feature. This feature is removed."
 | 
				
			||||||
        },
 | 
					        },
 | 
				
			||||||
        "externalID": {
 | 
					        "externalID": {
 | 
				
			||||||
          "description": "Deprecated. Not all kubelets will set this field. Remove field after 1.13. see: https://issues.k8s.io/61966",
 | 
					          "description": "Deprecated. Not all kubelets will set this field. Remove field after 1.13. see: https://issues.k8s.io/61966",
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -3594,7 +3594,7 @@
 | 
				
			|||||||
                "$ref": "#/components/schemas/io.k8s.api.core.v1.NodeConfigSource"
 | 
					                "$ref": "#/components/schemas/io.k8s.api.core.v1.NodeConfigSource"
 | 
				
			||||||
              }
 | 
					              }
 | 
				
			||||||
            ],
 | 
					            ],
 | 
				
			||||||
            "description": "Deprecated: Previously used to specify the source of the node's configuration for the DynamicKubeletConfig feature. This feature is removed from Kubelets as of 1.24 and will be fully removed in 1.26."
 | 
					            "description": "Deprecated: Previously used to specify the source of the node's configuration for the DynamicKubeletConfig feature. This feature is removed."
 | 
				
			||||||
          },
 | 
					          },
 | 
				
			||||||
          "externalID": {
 | 
					          "externalID": {
 | 
				
			||||||
            "description": "Deprecated. Not all kubelets will set this field. Remove field after 1.13. see: https://issues.k8s.io/61966",
 | 
					            "description": "Deprecated. Not all kubelets will set this field. Remove field after 1.13. see: https://issues.k8s.io/61966",
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -235,13 +235,6 @@ HTTP server: The kubelet can also listen for HTTP and respond to a simple API
 | 
				
			|||||||
				klog.InfoS("unsupported configuration:KubeletCgroups is not within KubeReservedCgroup")
 | 
									klog.InfoS("unsupported configuration:KubeletCgroups is not within KubeReservedCgroup")
 | 
				
			||||||
			}
 | 
								}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
			// The features.DynamicKubeletConfig is locked to false,
 | 
					 | 
				
			||||||
			// feature gate is not locked using the LockedToDefault flag
 | 
					 | 
				
			||||||
			// to make sure node authorizer can keep working with the older nodes
 | 
					 | 
				
			||||||
			if utilfeature.DefaultFeatureGate.Enabled(features.DynamicKubeletConfig) {
 | 
					 | 
				
			||||||
				return fmt.Errorf("cannot set feature gate %v to %v, feature is locked to %v", features.DynamicKubeletConfig, true, false)
 | 
					 | 
				
			||||||
			}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
			// construct a KubeletServer from kubeletFlags and kubeletConfig
 | 
								// construct a KubeletServer from kubeletFlags and kubeletConfig
 | 
				
			||||||
			kubeletServer := &options.KubeletServer{
 | 
								kubeletServer := &options.KubeletServer{
 | 
				
			||||||
				KubeletFlags:         *kubeletFlags,
 | 
									KubeletFlags:         *kubeletFlags,
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -4160,7 +4160,7 @@ type NodeSpec struct {
 | 
				
			|||||||
	// +optional
 | 
						// +optional
 | 
				
			||||||
	Taints []Taint
 | 
						Taints []Taint
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	// Deprecated: Previously used to specify the source of the node's configuration for the DynamicKubeletConfig feature. This feature is removed from Kubelets as of 1.24 and will be fully removed in 1.26.
 | 
						// Deprecated: Previously used to specify the source of the node's configuration for the DynamicKubeletConfig feature. This feature is removed.
 | 
				
			||||||
	// +optional
 | 
						// +optional
 | 
				
			||||||
	ConfigSource *NodeConfigSource
 | 
						ConfigSource *NodeConfigSource
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -5259,6 +5259,8 @@ func ValidateNodeUpdate(node, oldNode *core.Node) field.ErrorList {
 | 
				
			|||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// validation specific to Node.Spec.ConfigSource
 | 
					// validation specific to Node.Spec.ConfigSource
 | 
				
			||||||
 | 
					// The field ConfigSource is deprecated and will not be used. The validation is kept in place
 | 
				
			||||||
 | 
					// for the backward compatibility
 | 
				
			||||||
func validateNodeConfigSourceSpec(source *core.NodeConfigSource, fldPath *field.Path) field.ErrorList {
 | 
					func validateNodeConfigSourceSpec(source *core.NodeConfigSource, fldPath *field.Path) field.ErrorList {
 | 
				
			||||||
	allErrs := field.ErrorList{}
 | 
						allErrs := field.ErrorList{}
 | 
				
			||||||
	count := int(0)
 | 
						count := int(0)
 | 
				
			||||||
@@ -5276,6 +5278,8 @@ func validateNodeConfigSourceSpec(source *core.NodeConfigSource, fldPath *field.
 | 
				
			|||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// validation specific to Node.Spec.ConfigSource.ConfigMap
 | 
					// validation specific to Node.Spec.ConfigSource.ConfigMap
 | 
				
			||||||
 | 
					// The field ConfigSource is deprecated and will not be used. The validation is kept in place
 | 
				
			||||||
 | 
					// for the backward compatibility
 | 
				
			||||||
func validateConfigMapNodeConfigSourceSpec(source *core.ConfigMapNodeConfigSource, fldPath *field.Path) field.ErrorList {
 | 
					func validateConfigMapNodeConfigSourceSpec(source *core.ConfigMapNodeConfigSource, fldPath *field.Path) field.ErrorList {
 | 
				
			||||||
	allErrs := field.ErrorList{}
 | 
						allErrs := field.ErrorList{}
 | 
				
			||||||
	// uid and resourceVersion must not be set in spec
 | 
						// uid and resourceVersion must not be set in spec
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -256,12 +256,6 @@ const (
 | 
				
			|||||||
	// Enables usage of hugepages-<size> in downward API.
 | 
						// Enables usage of hugepages-<size> in downward API.
 | 
				
			||||||
	DownwardAPIHugePages featuregate.Feature = "DownwardAPIHugePages"
 | 
						DownwardAPIHugePages featuregate.Feature = "DownwardAPIHugePages"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	// owner: @mtaufen
 | 
					 | 
				
			||||||
	// alpha: v1.4
 | 
					 | 
				
			||||||
	// beta: v1.11
 | 
					 | 
				
			||||||
	// deprecated: 1.22
 | 
					 | 
				
			||||||
	DynamicKubeletConfig featuregate.Feature = "DynamicKubeletConfig"
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	// owner: @andrewsykim
 | 
						// owner: @andrewsykim
 | 
				
			||||||
	// kep: https://kep.k8s.io/1672
 | 
						// kep: https://kep.k8s.io/1672
 | 
				
			||||||
	// alpha: v1.20
 | 
						// alpha: v1.20
 | 
				
			||||||
@@ -863,8 +857,6 @@ var defaultKubernetesFeatureGates = map[featuregate.Feature]featuregate.FeatureS
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
	DownwardAPIHugePages: {Default: true, PreRelease: featuregate.Beta}, // on by default in 1.22
 | 
						DownwardAPIHugePages: {Default: true, PreRelease: featuregate.Beta}, // on by default in 1.22
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	DynamicKubeletConfig: {Default: false, PreRelease: featuregate.Deprecated}, // feature gate is deprecated in 1.22, kubelet logic is removed in 1.24, api server logic can be removed in 1.26
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	EndpointSliceTerminatingCondition: {Default: true, PreRelease: featuregate.Beta},
 | 
						EndpointSliceTerminatingCondition: {Default: true, PreRelease: featuregate.Beta},
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	EphemeralContainers: {Default: true, PreRelease: featuregate.GA, LockToDefault: true}, // remove in 1.27
 | 
						EphemeralContainers: {Default: true, PreRelease: featuregate.GA, LockToDefault: true}, // remove in 1.27
 | 
				
			||||||
 
 | 
				
			|||||||
							
								
								
									
										2
									
								
								pkg/generated/openapi/zz_generated.openapi.go
									
									
									
										generated
									
									
									
								
							
							
						
						
									
										2
									
								
								pkg/generated/openapi/zz_generated.openapi.go
									
									
									
										generated
									
									
									
								
							@@ -19913,7 +19913,7 @@ func schema_k8sio_api_core_v1_NodeSpec(ref common.ReferenceCallback) common.Open
 | 
				
			|||||||
					},
 | 
										},
 | 
				
			||||||
					"configSource": {
 | 
										"configSource": {
 | 
				
			||||||
						SchemaProps: spec.SchemaProps{
 | 
											SchemaProps: spec.SchemaProps{
 | 
				
			||||||
							Description: "Deprecated: Previously used to specify the source of the node's configuration for the DynamicKubeletConfig feature. This feature is removed from Kubelets as of 1.24 and will be fully removed in 1.26.",
 | 
												Description: "Deprecated: Previously used to specify the source of the node's configuration for the DynamicKubeletConfig feature. This feature is removed.",
 | 
				
			||||||
							Ref:         ref("k8s.io/api/core/v1.NodeConfigSource"),
 | 
												Ref:         ref("k8s.io/api/core/v1.NodeConfigSource"),
 | 
				
			||||||
						},
 | 
											},
 | 
				
			||||||
					},
 | 
										},
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -34,11 +34,9 @@ import (
 | 
				
			|||||||
	"k8s.io/apiserver/pkg/registry/generic"
 | 
						"k8s.io/apiserver/pkg/registry/generic"
 | 
				
			||||||
	pkgstorage "k8s.io/apiserver/pkg/storage"
 | 
						pkgstorage "k8s.io/apiserver/pkg/storage"
 | 
				
			||||||
	"k8s.io/apiserver/pkg/storage/names"
 | 
						"k8s.io/apiserver/pkg/storage/names"
 | 
				
			||||||
	utilfeature "k8s.io/apiserver/pkg/util/feature"
 | 
					 | 
				
			||||||
	"k8s.io/kubernetes/pkg/api/legacyscheme"
 | 
						"k8s.io/kubernetes/pkg/api/legacyscheme"
 | 
				
			||||||
	api "k8s.io/kubernetes/pkg/apis/core"
 | 
						api "k8s.io/kubernetes/pkg/apis/core"
 | 
				
			||||||
	"k8s.io/kubernetes/pkg/apis/core/validation"
 | 
						"k8s.io/kubernetes/pkg/apis/core/validation"
 | 
				
			||||||
	"k8s.io/kubernetes/pkg/features"
 | 
					 | 
				
			||||||
	"k8s.io/kubernetes/pkg/kubelet/client"
 | 
						"k8s.io/kubernetes/pkg/kubelet/client"
 | 
				
			||||||
	proxyutil "k8s.io/kubernetes/pkg/proxy/util"
 | 
						proxyutil "k8s.io/kubernetes/pkg/proxy/util"
 | 
				
			||||||
	"sigs.k8s.io/structured-merge-diff/v4/fieldpath"
 | 
						"sigs.k8s.io/structured-merge-diff/v4/fieldpath"
 | 
				
			||||||
@@ -94,13 +92,13 @@ func (nodeStrategy) PrepareForUpdate(ctx context.Context, obj, old runtime.Objec
 | 
				
			|||||||
func dropDisabledFields(node *api.Node, oldNode *api.Node) {
 | 
					func dropDisabledFields(node *api.Node, oldNode *api.Node) {
 | 
				
			||||||
	// Nodes allow *all* fields, including status, to be set on create.
 | 
						// Nodes allow *all* fields, including status, to be set on create.
 | 
				
			||||||
	// for create
 | 
						// for create
 | 
				
			||||||
	if !utilfeature.DefaultFeatureGate.Enabled(features.DynamicKubeletConfig) && oldNode == nil {
 | 
						if oldNode == nil {
 | 
				
			||||||
		node.Spec.ConfigSource = nil
 | 
							node.Spec.ConfigSource = nil
 | 
				
			||||||
		node.Status.Config = nil
 | 
							node.Status.Config = nil
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	// for update
 | 
						// for update
 | 
				
			||||||
	if !utilfeature.DefaultFeatureGate.Enabled(features.DynamicKubeletConfig) && !nodeConfigSourceInUse(oldNode) && oldNode != nil {
 | 
						if !nodeConfigSourceInUse(oldNode) && oldNode != nil {
 | 
				
			||||||
		node.Spec.ConfigSource = nil
 | 
							node.Spec.ConfigSource = nil
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -170,7 +168,7 @@ func (nodeStatusStrategy) PrepareForUpdate(ctx context.Context, obj, old runtime
 | 
				
			|||||||
	oldNode := old.(*api.Node)
 | 
						oldNode := old.(*api.Node)
 | 
				
			||||||
	newNode.Spec = oldNode.Spec
 | 
						newNode.Spec = oldNode.Spec
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if !utilfeature.DefaultFeatureGate.Enabled(features.DynamicKubeletConfig) && !nodeStatusConfigInUse(oldNode) {
 | 
						if !nodeStatusConfigInUse(oldNode) {
 | 
				
			||||||
		newNode.Status.Config = nil
 | 
							newNode.Status.Config = nil
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
@@ -274,7 +272,7 @@ func dynamicKubeletConfigIsDeprecatedWarning(obj runtime.Object) []string {
 | 
				
			|||||||
	if newNode.Spec.ConfigSource != nil {
 | 
						if newNode.Spec.ConfigSource != nil {
 | 
				
			||||||
		var warnings []string
 | 
							var warnings []string
 | 
				
			||||||
		// KEP https://github.com/kubernetes/enhancements/issues/281
 | 
							// KEP https://github.com/kubernetes/enhancements/issues/281
 | 
				
			||||||
		warnings = append(warnings, "spec.configSource: deprecated in v1.22, support removal is planned in v1.23")
 | 
							warnings = append(warnings, "spec.configSource: the feature is removed")
 | 
				
			||||||
		return warnings
 | 
							return warnings
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	return nil
 | 
						return nil
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -27,11 +27,8 @@ import (
 | 
				
			|||||||
	"k8s.io/apimachinery/pkg/fields"
 | 
						"k8s.io/apimachinery/pkg/fields"
 | 
				
			||||||
	"k8s.io/apimachinery/pkg/labels"
 | 
						"k8s.io/apimachinery/pkg/labels"
 | 
				
			||||||
	"k8s.io/apimachinery/pkg/util/diff"
 | 
						"k8s.io/apimachinery/pkg/util/diff"
 | 
				
			||||||
	utilfeature "k8s.io/apiserver/pkg/util/feature"
 | 
					 | 
				
			||||||
	featuregatetesting "k8s.io/component-base/featuregate/testing"
 | 
					 | 
				
			||||||
	apitesting "k8s.io/kubernetes/pkg/api/testing"
 | 
						apitesting "k8s.io/kubernetes/pkg/api/testing"
 | 
				
			||||||
	api "k8s.io/kubernetes/pkg/apis/core"
 | 
						api "k8s.io/kubernetes/pkg/apis/core"
 | 
				
			||||||
	"k8s.io/kubernetes/pkg/features"
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
	// ensure types are installed
 | 
						// ensure types are installed
 | 
				
			||||||
	_ "k8s.io/kubernetes/pkg/apis/core/install"
 | 
						_ "k8s.io/kubernetes/pkg/apis/core/install"
 | 
				
			||||||
@@ -92,7 +89,6 @@ func TestDropFields(t *testing.T) {
 | 
				
			|||||||
		node        *api.Node
 | 
							node        *api.Node
 | 
				
			||||||
		oldNode     *api.Node
 | 
							oldNode     *api.Node
 | 
				
			||||||
		compareNode *api.Node
 | 
							compareNode *api.Node
 | 
				
			||||||
		enableNodeDynamicConfig bool
 | 
					 | 
				
			||||||
	}{
 | 
						}{
 | 
				
			||||||
		{
 | 
							{
 | 
				
			||||||
			name:        "nil pod cidrs",
 | 
								name:        "nil pod cidrs",
 | 
				
			||||||
@@ -127,60 +123,45 @@ func TestDropFields(t *testing.T) {
 | 
				
			|||||||
			compareNode: makeNode([]string{"2000::/10", "10.0.0.0/8"}, false, false),
 | 
								compareNode: makeNode([]string{"2000::/10", "10.0.0.0/8"}, false, false),
 | 
				
			||||||
		},
 | 
							},
 | 
				
			||||||
		{
 | 
							{
 | 
				
			||||||
			name:                    "new with no Spec.ConfigSource and no Status.Config , enableNodeDynamicConfig disabled",
 | 
								name:        "new with no Spec.ConfigSource and no Status.Config",
 | 
				
			||||||
			enableNodeDynamicConfig: false,
 | 
					 | 
				
			||||||
			node:        makeNode(nil, false, false),
 | 
								node:        makeNode(nil, false, false),
 | 
				
			||||||
			oldNode:     nil,
 | 
								oldNode:     nil,
 | 
				
			||||||
			compareNode: makeNode(nil, false, false),
 | 
								compareNode: makeNode(nil, false, false),
 | 
				
			||||||
		},
 | 
							},
 | 
				
			||||||
		{
 | 
							{
 | 
				
			||||||
			name:                    "new with Spec.ConfigSource and no Status.Config, enableNodeDynamicConfig disabled",
 | 
								name:        "new with Spec.ConfigSource and no Status.Config",
 | 
				
			||||||
			enableNodeDynamicConfig: false,
 | 
					 | 
				
			||||||
			node:        makeNode(nil, true, false),
 | 
								node:        makeNode(nil, true, false),
 | 
				
			||||||
			oldNode:     nil,
 | 
								oldNode:     nil,
 | 
				
			||||||
			compareNode: makeNode(nil, false, false),
 | 
								compareNode: makeNode(nil, false, false),
 | 
				
			||||||
		},
 | 
							},
 | 
				
			||||||
		{
 | 
							{
 | 
				
			||||||
			name:                    "new with Spec.ConfigSource and Status.Config, enableNodeDynamicConfig disabled",
 | 
								name:        "new with Spec.ConfigSource and Status.Config",
 | 
				
			||||||
			enableNodeDynamicConfig: false,
 | 
					 | 
				
			||||||
			node:        makeNode(nil, true, true),
 | 
								node:        makeNode(nil, true, true),
 | 
				
			||||||
			oldNode:     nil,
 | 
								oldNode:     nil,
 | 
				
			||||||
			compareNode: makeNode(nil, false, false),
 | 
								compareNode: makeNode(nil, false, false),
 | 
				
			||||||
		},
 | 
							},
 | 
				
			||||||
		{
 | 
							{
 | 
				
			||||||
			name:                    "update with Spec.ConfigSource and Status.Config (old has none), enableNodeDynamicConfig disabled",
 | 
								name:        "update with Spec.ConfigSource and Status.Config (old has none)",
 | 
				
			||||||
			enableNodeDynamicConfig: false,
 | 
					 | 
				
			||||||
			node:        makeNode(nil, true, true),
 | 
								node:        makeNode(nil, true, true),
 | 
				
			||||||
			oldNode:     makeNode(nil, false, false),
 | 
								oldNode:     makeNode(nil, false, false),
 | 
				
			||||||
			compareNode: makeNode(nil, false, true),
 | 
								compareNode: makeNode(nil, false, true),
 | 
				
			||||||
		},
 | 
							},
 | 
				
			||||||
		{
 | 
							{
 | 
				
			||||||
			name:                    "update with Spec.ConfigSource and Status.Config (old has them), enableNodeDynamicConfig disabled",
 | 
								name:        "update with Spec.ConfigSource and Status.Config (old has them)",
 | 
				
			||||||
			enableNodeDynamicConfig: false,
 | 
					 | 
				
			||||||
			node:        makeNode(nil, true, true),
 | 
								node:        makeNode(nil, true, true),
 | 
				
			||||||
			oldNode:     makeNode(nil, true, true),
 | 
								oldNode:     makeNode(nil, true, true),
 | 
				
			||||||
			compareNode: makeNode(nil, true, true),
 | 
								compareNode: makeNode(nil, true, true),
 | 
				
			||||||
		},
 | 
							},
 | 
				
			||||||
		{
 | 
							{
 | 
				
			||||||
			name:                    "update with Spec.ConfigSource and Status.Config (old has Status.Config), enableNodeDynamicConfig disabled",
 | 
								name:        "update with Spec.ConfigSource and Status.Config (old has Status.Config)",
 | 
				
			||||||
			enableNodeDynamicConfig: false,
 | 
					 | 
				
			||||||
			node:        makeNode(nil, true, true),
 | 
								node:        makeNode(nil, true, true),
 | 
				
			||||||
			oldNode:     makeNode(nil, false, true),
 | 
								oldNode:     makeNode(nil, false, true),
 | 
				
			||||||
			compareNode: makeNode(nil, false, true),
 | 
								compareNode: makeNode(nil, false, true),
 | 
				
			||||||
		},
 | 
							},
 | 
				
			||||||
		{
 | 
					 | 
				
			||||||
			name:                    "new with Spec.ConfigSource and Status.Config, enableNodeDynamicConfig enabled",
 | 
					 | 
				
			||||||
			enableNodeDynamicConfig: true,
 | 
					 | 
				
			||||||
			node:                    makeNode(nil, true, true),
 | 
					 | 
				
			||||||
			oldNode:                 nil,
 | 
					 | 
				
			||||||
			compareNode:             makeNode(nil, true, true),
 | 
					 | 
				
			||||||
		},
 | 
					 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	for _, tc := range testCases {
 | 
						for _, tc := range testCases {
 | 
				
			||||||
		func() {
 | 
							func() {
 | 
				
			||||||
			defer featuregatetesting.SetFeatureGateDuringTest(t, utilfeature.DefaultFeatureGate, features.DynamicKubeletConfig, tc.enableNodeDynamicConfig)()
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
			dropDisabledFields(tc.node, tc.oldNode)
 | 
								dropDisabledFields(tc.node, tc.oldNode)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
			old := tc.oldNode.DeepCopy()
 | 
								old := tc.oldNode.DeepCopy()
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -476,31 +476,3 @@ func (g *Graph) DeleteVolumeAttachment(name string) {
 | 
				
			|||||||
	defer g.lock.Unlock()
 | 
						defer g.lock.Unlock()
 | 
				
			||||||
	g.deleteVertex_locked(vaVertexType, "", name)
 | 
						g.deleteVertex_locked(vaVertexType, "", name)
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					 | 
				
			||||||
// SetNodeConfigMap sets up edges for the Node.Spec.ConfigSource.ConfigMap relationship:
 | 
					 | 
				
			||||||
//
 | 
					 | 
				
			||||||
// configmap -> node
 | 
					 | 
				
			||||||
func (g *Graph) SetNodeConfigMap(nodeName, configMapName, configMapNamespace string) {
 | 
					 | 
				
			||||||
	start := time.Now()
 | 
					 | 
				
			||||||
	defer func() {
 | 
					 | 
				
			||||||
		graphActionsDuration.WithLabelValues("SetNodeConfigMap").Observe(time.Since(start).Seconds())
 | 
					 | 
				
			||||||
	}()
 | 
					 | 
				
			||||||
	g.lock.Lock()
 | 
					 | 
				
			||||||
	defer g.lock.Unlock()
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	// TODO(mtaufen): ensure len(nodeName) > 0 in all cases (would sure be nice to have a dependently-typed language here...)
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	// clear edges configmaps -> node where the destination is the current node *only*
 | 
					 | 
				
			||||||
	// at present, a node can only have one *direct* configmap reference at a time
 | 
					 | 
				
			||||||
	g.deleteEdges_locked(configMapVertexType, nodeVertexType, "", nodeName)
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	// establish new edges if we have a real ConfigMap to reference
 | 
					 | 
				
			||||||
	if len(configMapName) > 0 && len(configMapNamespace) > 0 {
 | 
					 | 
				
			||||||
		configmapVertex := g.getOrCreateVertex_locked(configMapVertexType, configMapNamespace, configMapName)
 | 
					 | 
				
			||||||
		nodeVertex := g.getOrCreateVertex_locked(nodeVertexType, "", nodeName)
 | 
					 | 
				
			||||||
		e := newDestinationEdge(configmapVertex, nodeVertex, nodeVertex)
 | 
					 | 
				
			||||||
		g.graph.SetEdge(e)
 | 
					 | 
				
			||||||
		g.addEdgeToDestinationIndex_locked(e)
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 
 | 
				
			|||||||
@@ -17,7 +17,6 @@ limitations under the License.
 | 
				
			|||||||
package node
 | 
					package node
 | 
				
			||||||
 | 
					
 | 
				
			||||||
import (
 | 
					import (
 | 
				
			||||||
	"fmt"
 | 
					 | 
				
			||||||
	"time"
 | 
						"time"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	"k8s.io/klog/v2"
 | 
						"k8s.io/klog/v2"
 | 
				
			||||||
@@ -25,11 +24,9 @@ import (
 | 
				
			|||||||
	corev1 "k8s.io/api/core/v1"
 | 
						corev1 "k8s.io/api/core/v1"
 | 
				
			||||||
	storagev1 "k8s.io/api/storage/v1"
 | 
						storagev1 "k8s.io/api/storage/v1"
 | 
				
			||||||
	"k8s.io/apimachinery/pkg/util/wait"
 | 
						"k8s.io/apimachinery/pkg/util/wait"
 | 
				
			||||||
	utilfeature "k8s.io/apiserver/pkg/util/feature"
 | 
					 | 
				
			||||||
	corev1informers "k8s.io/client-go/informers/core/v1"
 | 
						corev1informers "k8s.io/client-go/informers/core/v1"
 | 
				
			||||||
	storageinformers "k8s.io/client-go/informers/storage/v1"
 | 
						storageinformers "k8s.io/client-go/informers/storage/v1"
 | 
				
			||||||
	"k8s.io/client-go/tools/cache"
 | 
						"k8s.io/client-go/tools/cache"
 | 
				
			||||||
	"k8s.io/kubernetes/pkg/features"
 | 
					 | 
				
			||||||
)
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
type graphPopulator struct {
 | 
					type graphPopulator struct {
 | 
				
			||||||
@@ -49,15 +46,6 @@ func AddGraphEventHandlers(
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
	var hasSynced []cache.InformerSynced
 | 
						var hasSynced []cache.InformerSynced
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if utilfeature.DefaultFeatureGate.Enabled(features.DynamicKubeletConfig) {
 | 
					 | 
				
			||||||
		nodes.Informer().AddEventHandler(cache.ResourceEventHandlerFuncs{
 | 
					 | 
				
			||||||
			AddFunc:    g.addNode,
 | 
					 | 
				
			||||||
			UpdateFunc: g.updateNode,
 | 
					 | 
				
			||||||
			DeleteFunc: g.deleteNode,
 | 
					 | 
				
			||||||
		})
 | 
					 | 
				
			||||||
		hasSynced = append(hasSynced, nodes.Informer().HasSynced)
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	pods.Informer().AddEventHandler(cache.ResourceEventHandlerFuncs{
 | 
						pods.Informer().AddEventHandler(cache.ResourceEventHandlerFuncs{
 | 
				
			||||||
		AddFunc:    g.addPod,
 | 
							AddFunc:    g.addPod,
 | 
				
			||||||
		UpdateFunc: g.updatePod,
 | 
							UpdateFunc: g.updatePod,
 | 
				
			||||||
@@ -82,62 +70,6 @@ func AddGraphEventHandlers(
 | 
				
			|||||||
	go cache.WaitForNamedCacheSync("node_authorizer", wait.NeverStop, hasSynced...)
 | 
						go cache.WaitForNamedCacheSync("node_authorizer", wait.NeverStop, hasSynced...)
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
func (g *graphPopulator) addNode(obj interface{}) {
 | 
					 | 
				
			||||||
	g.updateNode(nil, obj)
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
func (g *graphPopulator) updateNode(oldObj, obj interface{}) {
 | 
					 | 
				
			||||||
	node := obj.(*corev1.Node)
 | 
					 | 
				
			||||||
	var oldNode *corev1.Node
 | 
					 | 
				
			||||||
	if oldObj != nil {
 | 
					 | 
				
			||||||
		oldNode = oldObj.(*corev1.Node)
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	// we only set up rules for ConfigMap today, because that is the only reference type
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	var name, namespace string
 | 
					 | 
				
			||||||
	if source := node.Spec.ConfigSource; source != nil && source.ConfigMap != nil {
 | 
					 | 
				
			||||||
		name = source.ConfigMap.Name
 | 
					 | 
				
			||||||
		namespace = source.ConfigMap.Namespace
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	var oldName, oldNamespace string
 | 
					 | 
				
			||||||
	if oldNode != nil {
 | 
					 | 
				
			||||||
		if oldSource := oldNode.Spec.ConfigSource; oldSource != nil && oldSource.ConfigMap != nil {
 | 
					 | 
				
			||||||
			oldName = oldSource.ConfigMap.Name
 | 
					 | 
				
			||||||
			oldNamespace = oldSource.ConfigMap.Namespace
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	// if Node.Spec.ConfigSource wasn't updated, nothing for us to do
 | 
					 | 
				
			||||||
	if name == oldName && namespace == oldNamespace {
 | 
					 | 
				
			||||||
		return
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	path := "nil"
 | 
					 | 
				
			||||||
	if node.Spec.ConfigSource != nil {
 | 
					 | 
				
			||||||
		path = fmt.Sprintf("%s/%s", namespace, name)
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
	klog.V(4).Infof("updateNode configSource reference to %s for node %s", path, node.Name)
 | 
					 | 
				
			||||||
	g.graph.SetNodeConfigMap(node.Name, name, namespace)
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
func (g *graphPopulator) deleteNode(obj interface{}) {
 | 
					 | 
				
			||||||
	if tombstone, ok := obj.(cache.DeletedFinalStateUnknown); ok {
 | 
					 | 
				
			||||||
		obj = tombstone.Obj
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
	node, ok := obj.(*corev1.Node)
 | 
					 | 
				
			||||||
	if !ok {
 | 
					 | 
				
			||||||
		klog.Infof("unexpected type %T", obj)
 | 
					 | 
				
			||||||
		return
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	// NOTE: We don't remove the node, because if the node is re-created not all pod -> node
 | 
					 | 
				
			||||||
	// links are re-established (we don't get relevant events because the no mutations need
 | 
					 | 
				
			||||||
	// to happen in the API; the state is already there).
 | 
					 | 
				
			||||||
	g.graph.SetNodeConfigMap(node.Name, "", "")
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
func (g *graphPopulator) addPod(obj interface{}) {
 | 
					func (g *graphPopulator) addPod(obj interface{}) {
 | 
				
			||||||
	g.updatePod(nil, obj)
 | 
						g.updatePod(nil, obj)
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -343,74 +343,4 @@ func TestIndex(t *testing.T) {
 | 
				
			|||||||
		"configmap:ns/cm3":      {"node:node1=1", "node:node2=1", "node:node3=1"},
 | 
							"configmap:ns/cm3":      {"node:node1=1", "node:node2=1", "node:node3=1"},
 | 
				
			||||||
		"serviceAccount:ns/sa1": {"node:node1=1", "node:node2=1", "node:node3=1"},
 | 
							"serviceAccount:ns/sa1": {"node:node1=1", "node:node2=1", "node:node3=1"},
 | 
				
			||||||
	})
 | 
						})
 | 
				
			||||||
 | 
					 | 
				
			||||||
	// Set node->configmap references
 | 
					 | 
				
			||||||
	g.SetNodeConfigMap("node1", "cm1", "ns")
 | 
					 | 
				
			||||||
	g.SetNodeConfigMap("node2", "cm1", "ns")
 | 
					 | 
				
			||||||
	g.SetNodeConfigMap("node3", "cm1", "ns")
 | 
					 | 
				
			||||||
	g.SetNodeConfigMap("node4", "cm1", "ns")
 | 
					 | 
				
			||||||
	expectGraph(map[string][]string{
 | 
					 | 
				
			||||||
		"node:node1":            {},
 | 
					 | 
				
			||||||
		"node:node2":            {},
 | 
					 | 
				
			||||||
		"node:node3":            {},
 | 
					 | 
				
			||||||
		"node:node4":            {},
 | 
					 | 
				
			||||||
		"pod:ns/pod2":           {"node:node2"},
 | 
					 | 
				
			||||||
		"pod:ns/pod3":           {"node:node3"},
 | 
					 | 
				
			||||||
		"pod:ns/pod4":           {"node:node1"},
 | 
					 | 
				
			||||||
		"configmap:ns/cm1":      {"node:node1", "node:node2", "node:node3", "node:node4", "pod:ns/pod2", "pod:ns/pod3", "pod:ns/pod4"},
 | 
					 | 
				
			||||||
		"configmap:ns/cm2":      {"pod:ns/pod2", "pod:ns/pod3", "pod:ns/pod4"},
 | 
					 | 
				
			||||||
		"configmap:ns/cm3":      {"pod:ns/pod2", "pod:ns/pod3", "pod:ns/pod4"},
 | 
					 | 
				
			||||||
		"serviceAccount:ns/sa1": {"pod:ns/pod2", "pod:ns/pod3", "pod:ns/pod4"},
 | 
					 | 
				
			||||||
	})
 | 
					 | 
				
			||||||
	expectIndex(map[string][]string{
 | 
					 | 
				
			||||||
		"configmap:ns/cm1":      {"node:node1=2", "node:node2=2", "node:node3=2", "node:node4=1"},
 | 
					 | 
				
			||||||
		"configmap:ns/cm2":      {"node:node1=1", "node:node2=1", "node:node3=1"},
 | 
					 | 
				
			||||||
		"configmap:ns/cm3":      {"node:node1=1", "node:node2=1", "node:node3=1"},
 | 
					 | 
				
			||||||
		"serviceAccount:ns/sa1": {"node:node1=1", "node:node2=1", "node:node3=1"},
 | 
					 | 
				
			||||||
	})
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	// Update node->configmap reference
 | 
					 | 
				
			||||||
	g.SetNodeConfigMap("node1", "cm2", "ns")
 | 
					 | 
				
			||||||
	expectGraph(map[string][]string{
 | 
					 | 
				
			||||||
		"node:node1":            {},
 | 
					 | 
				
			||||||
		"node:node2":            {},
 | 
					 | 
				
			||||||
		"node:node3":            {},
 | 
					 | 
				
			||||||
		"node:node4":            {},
 | 
					 | 
				
			||||||
		"pod:ns/pod2":           {"node:node2"},
 | 
					 | 
				
			||||||
		"pod:ns/pod3":           {"node:node3"},
 | 
					 | 
				
			||||||
		"pod:ns/pod4":           {"node:node1"},
 | 
					 | 
				
			||||||
		"configmap:ns/cm1":      {"node:node2", "node:node3", "node:node4", "pod:ns/pod2", "pod:ns/pod3", "pod:ns/pod4"},
 | 
					 | 
				
			||||||
		"configmap:ns/cm2":      {"node:node1", "pod:ns/pod2", "pod:ns/pod3", "pod:ns/pod4"},
 | 
					 | 
				
			||||||
		"configmap:ns/cm3":      {"pod:ns/pod2", "pod:ns/pod3", "pod:ns/pod4"},
 | 
					 | 
				
			||||||
		"serviceAccount:ns/sa1": {"pod:ns/pod2", "pod:ns/pod3", "pod:ns/pod4"},
 | 
					 | 
				
			||||||
	})
 | 
					 | 
				
			||||||
	expectIndex(map[string][]string{
 | 
					 | 
				
			||||||
		"configmap:ns/cm1":      {"node:node1=1", "node:node2=2", "node:node3=2", "node:node4=1"},
 | 
					 | 
				
			||||||
		"configmap:ns/cm2":      {"node:node1=2", "node:node2=1", "node:node3=1"},
 | 
					 | 
				
			||||||
		"configmap:ns/cm3":      {"node:node1=1", "node:node2=1", "node:node3=1"},
 | 
					 | 
				
			||||||
		"serviceAccount:ns/sa1": {"node:node1=1", "node:node2=1", "node:node3=1"},
 | 
					 | 
				
			||||||
	})
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	// Remove node->configmap reference
 | 
					 | 
				
			||||||
	g.SetNodeConfigMap("node1", "", "")
 | 
					 | 
				
			||||||
	g.SetNodeConfigMap("node4", "", "")
 | 
					 | 
				
			||||||
	expectGraph(map[string][]string{
 | 
					 | 
				
			||||||
		"node:node1":            {},
 | 
					 | 
				
			||||||
		"node:node2":            {},
 | 
					 | 
				
			||||||
		"node:node3":            {},
 | 
					 | 
				
			||||||
		"node:node4":            {},
 | 
					 | 
				
			||||||
		"pod:ns/pod2":           {"node:node2"},
 | 
					 | 
				
			||||||
		"pod:ns/pod3":           {"node:node3"},
 | 
					 | 
				
			||||||
		"pod:ns/pod4":           {"node:node1"},
 | 
					 | 
				
			||||||
		"configmap:ns/cm1":      {"node:node2", "node:node3", "pod:ns/pod2", "pod:ns/pod3", "pod:ns/pod4"},
 | 
					 | 
				
			||||||
		"configmap:ns/cm2":      {"pod:ns/pod2", "pod:ns/pod3", "pod:ns/pod4"},
 | 
					 | 
				
			||||||
		"configmap:ns/cm3":      {"pod:ns/pod2", "pod:ns/pod3", "pod:ns/pod4"},
 | 
					 | 
				
			||||||
		"serviceAccount:ns/sa1": {"pod:ns/pod2", "pod:ns/pod3", "pod:ns/pod4"},
 | 
					 | 
				
			||||||
	})
 | 
					 | 
				
			||||||
	expectIndex(map[string][]string{
 | 
					 | 
				
			||||||
		"configmap:ns/cm1":      {"node:node1=1", "node:node2=2", "node:node3=2"},
 | 
					 | 
				
			||||||
		"configmap:ns/cm2":      {"node:node1=1", "node:node2=1", "node:node3=1"},
 | 
					 | 
				
			||||||
		"configmap:ns/cm3":      {"node:node1=1", "node:node2=1", "node:node3=1"},
 | 
					 | 
				
			||||||
		"serviceAccount:ns/sa1": {"node:node1=1", "node:node2=1", "node:node3=1"},
 | 
					 | 
				
			||||||
	})
 | 
					 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -30,7 +30,6 @@ import (
 | 
				
			|||||||
	corev1 "k8s.io/api/core/v1"
 | 
						corev1 "k8s.io/api/core/v1"
 | 
				
			||||||
	storagev1 "k8s.io/api/storage/v1"
 | 
						storagev1 "k8s.io/api/storage/v1"
 | 
				
			||||||
	metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
 | 
						metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
 | 
				
			||||||
	"k8s.io/apimachinery/pkg/types"
 | 
					 | 
				
			||||||
	"k8s.io/apiserver/pkg/authentication/user"
 | 
						"k8s.io/apiserver/pkg/authentication/user"
 | 
				
			||||||
	"k8s.io/apiserver/pkg/authorization/authorizer"
 | 
						"k8s.io/apiserver/pkg/authorization/authorizer"
 | 
				
			||||||
	utilfeature "k8s.io/apiserver/pkg/util/feature"
 | 
						utilfeature "k8s.io/apiserver/pkg/util/feature"
 | 
				
			||||||
@@ -68,11 +67,6 @@ func TestAuthorizer(t *testing.T) {
 | 
				
			|||||||
		expect   authorizer.Decision
 | 
							expect   authorizer.Decision
 | 
				
			||||||
		features featuregate.FeatureGate
 | 
							features featuregate.FeatureGate
 | 
				
			||||||
	}{
 | 
						}{
 | 
				
			||||||
		{
 | 
					 | 
				
			||||||
			name:   "allowed node configmap",
 | 
					 | 
				
			||||||
			attrs:  authorizer.AttributesRecord{User: node0, ResourceRequest: true, Verb: "get", Resource: "configmaps", Name: "node0-configmap", Namespace: "ns0"},
 | 
					 | 
				
			||||||
			expect: authorizer.DecisionAllow,
 | 
					 | 
				
			||||||
		},
 | 
					 | 
				
			||||||
		{
 | 
							{
 | 
				
			||||||
			name:   "allowed configmap",
 | 
								name:   "allowed configmap",
 | 
				
			||||||
			attrs:  authorizer.AttributesRecord{User: node0, ResourceRequest: true, Verb: "get", Resource: "configmaps", Name: "configmap0-pod0-node0", Namespace: "ns0"},
 | 
								attrs:  authorizer.AttributesRecord{User: node0, ResourceRequest: true, Verb: "get", Resource: "configmaps", Name: "configmap0-pod0-node0", Namespace: "ns0"},
 | 
				
			||||||
@@ -128,12 +122,6 @@ func TestAuthorizer(t *testing.T) {
 | 
				
			|||||||
			attrs:  authorizer.AttributesRecord{User: node0, ResourceRequest: true, Verb: "get", Resource: "persistentvolumes", Name: "pv0-pod0-node0-ns0", Namespace: ""},
 | 
								attrs:  authorizer.AttributesRecord{User: node0, ResourceRequest: true, Verb: "get", Resource: "persistentvolumes", Name: "pv0-pod0-node0-ns0", Namespace: ""},
 | 
				
			||||||
			expect: authorizer.DecisionAllow,
 | 
								expect: authorizer.DecisionAllow,
 | 
				
			||||||
		},
 | 
							},
 | 
				
			||||||
 | 
					 | 
				
			||||||
		{
 | 
					 | 
				
			||||||
			name:   "disallowed node configmap",
 | 
					 | 
				
			||||||
			attrs:  authorizer.AttributesRecord{User: node0, ResourceRequest: true, Verb: "get", Resource: "configmaps", Name: "node1-configmap", Namespace: "ns0"},
 | 
					 | 
				
			||||||
			expect: authorizer.DecisionNoOpinion,
 | 
					 | 
				
			||||||
		},
 | 
					 | 
				
			||||||
		{
 | 
							{
 | 
				
			||||||
			name:   "disallowed configmap",
 | 
								name:   "disallowed configmap",
 | 
				
			||||||
			attrs:  authorizer.AttributesRecord{User: node0, ResourceRequest: true, Verb: "get", Resource: "configmaps", Name: "configmap0-pod0-node1", Namespace: "ns0"},
 | 
								attrs:  authorizer.AttributesRecord{User: node0, ResourceRequest: true, Verb: "get", Resource: "configmaps", Name: "configmap0-pod0-node1", Namespace: "ns0"},
 | 
				
			||||||
@@ -385,36 +373,23 @@ func TestAuthorizerSharedResources(t *testing.T) {
 | 
				
			|||||||
	}
 | 
						}
 | 
				
			||||||
	g.AddPod(pod3)
 | 
						g.AddPod(pod3)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	g.SetNodeConfigMap("node1", "shared-configmap", "ns1")
 | 
					 | 
				
			||||||
	g.SetNodeConfigMap("node2", "shared-configmap", "ns1")
 | 
					 | 
				
			||||||
	g.SetNodeConfigMap("node3", "configmap", "ns1")
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	testcases := []struct {
 | 
						testcases := []struct {
 | 
				
			||||||
		User      user.Info
 | 
							User      user.Info
 | 
				
			||||||
		Secret    string
 | 
							Secret    string
 | 
				
			||||||
		ConfigMap string
 | 
							ConfigMap string
 | 
				
			||||||
		ExpectAllowed bool
 | 
							Decision  authorizer.Decision
 | 
				
			||||||
	}{
 | 
						}{
 | 
				
			||||||
		{User: node1, ExpectAllowed: true, Secret: "node1-only"},
 | 
							{User: node1, Decision: authorizer.DecisionAllow, Secret: "node1-only"},
 | 
				
			||||||
		{User: node1, ExpectAllowed: true, Secret: "node1-node2-only"},
 | 
							{User: node1, Decision: authorizer.DecisionAllow, Secret: "node1-node2-only"},
 | 
				
			||||||
		{User: node1, ExpectAllowed: true, Secret: "shared-all"},
 | 
							{User: node1, Decision: authorizer.DecisionAllow, Secret: "shared-all"},
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		{User: node2, ExpectAllowed: false, Secret: "node1-only"},
 | 
							{User: node2, Decision: authorizer.DecisionNoOpinion, Secret: "node1-only"},
 | 
				
			||||||
		{User: node2, ExpectAllowed: true, Secret: "node1-node2-only"},
 | 
							{User: node2, Decision: authorizer.DecisionAllow, Secret: "node1-node2-only"},
 | 
				
			||||||
		{User: node2, ExpectAllowed: true, Secret: "shared-all"},
 | 
							{User: node2, Decision: authorizer.DecisionAllow, Secret: "shared-all"},
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		{User: node3, ExpectAllowed: false, Secret: "node1-only"},
 | 
							{User: node3, Decision: authorizer.DecisionNoOpinion, Secret: "node1-only"},
 | 
				
			||||||
		{User: node3, ExpectAllowed: false, Secret: "node1-node2-only"},
 | 
							{User: node3, Decision: authorizer.DecisionNoOpinion, Secret: "node1-node2-only"},
 | 
				
			||||||
		{User: node3, ExpectAllowed: true, Secret: "shared-all"},
 | 
							{User: node3, Decision: authorizer.DecisionAllow, Secret: "shared-all"},
 | 
				
			||||||
 | 
					 | 
				
			||||||
		{User: node1, ExpectAllowed: true, ConfigMap: "shared-configmap"},
 | 
					 | 
				
			||||||
		{User: node1, ExpectAllowed: false, ConfigMap: "configmap"},
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
		{User: node2, ExpectAllowed: true, ConfigMap: "shared-configmap"},
 | 
					 | 
				
			||||||
		{User: node2, ExpectAllowed: false, ConfigMap: "configmap"},
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
		{User: node3, ExpectAllowed: false, ConfigMap: "shared-configmap"},
 | 
					 | 
				
			||||||
		{User: node3, ExpectAllowed: true, ConfigMap: "configmap"},
 | 
					 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	for i, tc := range testcases {
 | 
						for i, tc := range testcases {
 | 
				
			||||||
@@ -439,8 +414,8 @@ func TestAuthorizerSharedResources(t *testing.T) {
 | 
				
			|||||||
			t.Fatalf("test case must include a request for a Secret or ConfigMap")
 | 
								t.Fatalf("test case must include a request for a Secret or ConfigMap")
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		if (decision == authorizer.DecisionAllow) != tc.ExpectAllowed {
 | 
							if decision != tc.Decision {
 | 
				
			||||||
			t.Errorf("%d: expected %v, got %v", i, tc.ExpectAllowed, decision)
 | 
								t.Errorf("%d: expected %v, got %v", i, tc.Decision, decision)
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -629,11 +604,6 @@ func BenchmarkAuthorization(b *testing.B) {
 | 
				
			|||||||
		expect   authorizer.Decision
 | 
							expect   authorizer.Decision
 | 
				
			||||||
		features featuregate.FeatureGate
 | 
							features featuregate.FeatureGate
 | 
				
			||||||
	}{
 | 
						}{
 | 
				
			||||||
		{
 | 
					 | 
				
			||||||
			name:   "allowed node configmap",
 | 
					 | 
				
			||||||
			attrs:  authorizer.AttributesRecord{User: node0, ResourceRequest: true, Verb: "get", Resource: "configmaps", Name: "node0-configmap", Namespace: "ns0"},
 | 
					 | 
				
			||||||
			expect: authorizer.DecisionAllow,
 | 
					 | 
				
			||||||
		},
 | 
					 | 
				
			||||||
		{
 | 
							{
 | 
				
			||||||
			name:   "allowed configmap",
 | 
								name:   "allowed configmap",
 | 
				
			||||||
			attrs:  authorizer.AttributesRecord{User: node0, ResourceRequest: true, Verb: "get", Resource: "configmaps", Name: "configmap0-pod0-node0", Namespace: "ns0"},
 | 
								attrs:  authorizer.AttributesRecord{User: node0, ResourceRequest: true, Verb: "get", Resource: "configmaps", Name: "configmap0-pod0-node0", Namespace: "ns0"},
 | 
				
			||||||
@@ -649,12 +619,6 @@ func BenchmarkAuthorization(b *testing.B) {
 | 
				
			|||||||
			attrs:  authorizer.AttributesRecord{User: node0, ResourceRequest: true, Verb: "get", Resource: "secrets", Name: "secret0-shared", Namespace: "ns0"},
 | 
								attrs:  authorizer.AttributesRecord{User: node0, ResourceRequest: true, Verb: "get", Resource: "secrets", Name: "secret0-shared", Namespace: "ns0"},
 | 
				
			||||||
			expect: authorizer.DecisionAllow,
 | 
								expect: authorizer.DecisionAllow,
 | 
				
			||||||
		},
 | 
							},
 | 
				
			||||||
 | 
					 | 
				
			||||||
		{
 | 
					 | 
				
			||||||
			name:   "disallowed node configmap",
 | 
					 | 
				
			||||||
			attrs:  authorizer.AttributesRecord{User: node0, ResourceRequest: true, Verb: "get", Resource: "configmaps", Name: "node1-configmap", Namespace: "ns0"},
 | 
					 | 
				
			||||||
			expect: authorizer.DecisionNoOpinion,
 | 
					 | 
				
			||||||
		},
 | 
					 | 
				
			||||||
		{
 | 
							{
 | 
				
			||||||
			name:   "disallowed configmap",
 | 
								name:   "disallowed configmap",
 | 
				
			||||||
			attrs:  authorizer.AttributesRecord{User: node0, ResourceRequest: true, Verb: "get", Resource: "configmaps", Name: "configmap0-pod0-node1", Namespace: "ns0"},
 | 
								attrs:  authorizer.AttributesRecord{User: node0, ResourceRequest: true, Verb: "get", Resource: "configmaps", Name: "configmap0-pod0-node1", Namespace: "ns0"},
 | 
				
			||||||
@@ -779,9 +743,6 @@ func BenchmarkAuthorization(b *testing.B) {
 | 
				
			|||||||
func populate(graph *Graph, nodes []*corev1.Node, pods []*corev1.Pod, pvs []*corev1.PersistentVolume, attachments []*storagev1.VolumeAttachment) {
 | 
					func populate(graph *Graph, nodes []*corev1.Node, pods []*corev1.Pod, pvs []*corev1.PersistentVolume, attachments []*storagev1.VolumeAttachment) {
 | 
				
			||||||
	p := &graphPopulator{}
 | 
						p := &graphPopulator{}
 | 
				
			||||||
	p.graph = graph
 | 
						p.graph = graph
 | 
				
			||||||
	for _, node := range nodes {
 | 
					 | 
				
			||||||
		p.addNode(node)
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
	for _, pod := range pods {
 | 
						for _, pod := range pods {
 | 
				
			||||||
		p.addPod(pod)
 | 
							p.addPod(pod)
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
@@ -830,19 +791,9 @@ func generate(opts *sampleDataOpts) ([]*corev1.Node, []*corev1.Pod, []*corev1.Pe
 | 
				
			|||||||
			attachments = append(attachments, attachment)
 | 
								attachments = append(attachments, attachment)
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		name := fmt.Sprintf("%s-configmap", nodeName)
 | 
					 | 
				
			||||||
		nodes = append(nodes, &corev1.Node{
 | 
							nodes = append(nodes, &corev1.Node{
 | 
				
			||||||
			ObjectMeta: metav1.ObjectMeta{Name: nodeName},
 | 
								ObjectMeta: metav1.ObjectMeta{Name: nodeName},
 | 
				
			||||||
			Spec: corev1.NodeSpec{
 | 
								Spec:       corev1.NodeSpec{},
 | 
				
			||||||
				ConfigSource: &corev1.NodeConfigSource{
 | 
					 | 
				
			||||||
					ConfigMap: &corev1.ConfigMapNodeConfigSource{
 | 
					 | 
				
			||||||
						Name:             name,
 | 
					 | 
				
			||||||
						Namespace:        "ns0",
 | 
					 | 
				
			||||||
						UID:              types.UID(fmt.Sprintf("ns0-%s", name)),
 | 
					 | 
				
			||||||
						KubeletConfigKey: "kubelet",
 | 
					 | 
				
			||||||
					},
 | 
					 | 
				
			||||||
				},
 | 
					 | 
				
			||||||
			},
 | 
					 | 
				
			||||||
		})
 | 
							})
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	return nodes, pods, pvs, attachments
 | 
						return nodes, pods, pvs, attachments
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -2413,7 +2413,7 @@ message NodeSpec {
 | 
				
			|||||||
  // +optional
 | 
					  // +optional
 | 
				
			||||||
  repeated Taint taints = 5;
 | 
					  repeated Taint taints = 5;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  // Deprecated: Previously used to specify the source of the node's configuration for the DynamicKubeletConfig feature. This feature is removed from Kubelets as of 1.24 and will be fully removed in 1.26.
 | 
					  // Deprecated: Previously used to specify the source of the node's configuration for the DynamicKubeletConfig feature. This feature is removed.
 | 
				
			||||||
  // +optional
 | 
					  // +optional
 | 
				
			||||||
  optional NodeConfigSource configSource = 6;
 | 
					  optional NodeConfigSource configSource = 6;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -4898,7 +4898,7 @@ type NodeSpec struct {
 | 
				
			|||||||
	// +optional
 | 
						// +optional
 | 
				
			||||||
	Taints []Taint `json:"taints,omitempty" protobuf:"bytes,5,opt,name=taints"`
 | 
						Taints []Taint `json:"taints,omitempty" protobuf:"bytes,5,opt,name=taints"`
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	// Deprecated: Previously used to specify the source of the node's configuration for the DynamicKubeletConfig feature. This feature is removed from Kubelets as of 1.24 and will be fully removed in 1.26.
 | 
						// Deprecated: Previously used to specify the source of the node's configuration for the DynamicKubeletConfig feature. This feature is removed.
 | 
				
			||||||
	// +optional
 | 
						// +optional
 | 
				
			||||||
	ConfigSource *NodeConfigSource `json:"configSource,omitempty" protobuf:"bytes,6,opt,name=configSource"`
 | 
						ConfigSource *NodeConfigSource `json:"configSource,omitempty" protobuf:"bytes,6,opt,name=configSource"`
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -1189,7 +1189,7 @@ var map_NodeSpec = map[string]string{
 | 
				
			|||||||
	"providerID":    "ID of the node assigned by the cloud provider in the format: <ProviderName>://<ProviderSpecificNodeID>",
 | 
						"providerID":    "ID of the node assigned by the cloud provider in the format: <ProviderName>://<ProviderSpecificNodeID>",
 | 
				
			||||||
	"unschedulable": "Unschedulable controls node schedulability of new pods. By default, node is schedulable. More info: https://kubernetes.io/docs/concepts/nodes/node/#manual-node-administration",
 | 
						"unschedulable": "Unschedulable controls node schedulability of new pods. By default, node is schedulable. More info: https://kubernetes.io/docs/concepts/nodes/node/#manual-node-administration",
 | 
				
			||||||
	"taints":        "If specified, the node's taints.",
 | 
						"taints":        "If specified, the node's taints.",
 | 
				
			||||||
	"configSource":  "Deprecated: Previously used to specify the source of the node's configuration for the DynamicKubeletConfig feature. This feature is removed from Kubelets as of 1.24 and will be fully removed in 1.26.",
 | 
						"configSource":  "Deprecated: Previously used to specify the source of the node's configuration for the DynamicKubeletConfig feature. This feature is removed.",
 | 
				
			||||||
	"externalID":    "Deprecated. Not all kubelets will set this field. Remove field after 1.13. see: https://issues.k8s.io/61966",
 | 
						"externalID":    "Deprecated. Not all kubelets will set this field. Remove field after 1.13. see: https://issues.k8s.io/61966",
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -33,11 +33,8 @@ import (
 | 
				
			|||||||
	metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
 | 
						metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
 | 
				
			||||||
	"k8s.io/apimachinery/pkg/types"
 | 
						"k8s.io/apimachinery/pkg/types"
 | 
				
			||||||
	"k8s.io/apimachinery/pkg/util/wait"
 | 
						"k8s.io/apimachinery/pkg/util/wait"
 | 
				
			||||||
	utilfeature "k8s.io/apiserver/pkg/util/feature"
 | 
					 | 
				
			||||||
	clientset "k8s.io/client-go/kubernetes"
 | 
						clientset "k8s.io/client-go/kubernetes"
 | 
				
			||||||
	featuregatetesting "k8s.io/component-base/featuregate/testing"
 | 
					 | 
				
			||||||
	kubeapiservertesting "k8s.io/kubernetes/cmd/kube-apiserver/app/testing"
 | 
						kubeapiservertesting "k8s.io/kubernetes/cmd/kube-apiserver/app/testing"
 | 
				
			||||||
	"k8s.io/kubernetes/pkg/features"
 | 
					 | 
				
			||||||
	"k8s.io/kubernetes/test/integration/framework"
 | 
						"k8s.io/kubernetes/test/integration/framework"
 | 
				
			||||||
	"k8s.io/utils/pointer"
 | 
						"k8s.io/utils/pointer"
 | 
				
			||||||
)
 | 
					)
 | 
				
			||||||
@@ -52,9 +49,6 @@ func TestNodeAuthorizer(t *testing.T) {
 | 
				
			|||||||
		tokenNode2       = "node2-token"
 | 
							tokenNode2       = "node2-token"
 | 
				
			||||||
	)
 | 
						)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	// Enable DynamicKubeletConfig feature so that Node.Spec.ConfigSource can be set
 | 
					 | 
				
			||||||
	defer featuregatetesting.SetFeatureGateDuringTest(t, utilfeature.DefaultFeatureGate, features.DynamicKubeletConfig, true)()
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	tokenFile, err := os.CreateTemp("", "kubeconfig")
 | 
						tokenFile, err := os.CreateTemp("", "kubeconfig")
 | 
				
			||||||
	if err != nil {
 | 
						if err != nil {
 | 
				
			||||||
		t.Fatal(err)
 | 
							t.Fatal(err)
 | 
				
			||||||
@@ -106,9 +100,6 @@ func TestNodeAuthorizer(t *testing.T) {
 | 
				
			|||||||
	if _, err := superuserClient.CoreV1().ConfigMaps("ns").Create(context.TODO(), &corev1.ConfigMap{ObjectMeta: metav1.ObjectMeta{Name: "myconfigmap"}}, metav1.CreateOptions{}); err != nil {
 | 
						if _, err := superuserClient.CoreV1().ConfigMaps("ns").Create(context.TODO(), &corev1.ConfigMap{ObjectMeta: metav1.ObjectMeta{Name: "myconfigmap"}}, metav1.CreateOptions{}); err != nil {
 | 
				
			||||||
		t.Fatal(err)
 | 
							t.Fatal(err)
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	if _, err := superuserClient.CoreV1().ConfigMaps("ns").Create(context.TODO(), &corev1.ConfigMap{ObjectMeta: metav1.ObjectMeta{Name: "myconfigmapconfigsource"}}, metav1.CreateOptions{}); err != nil {
 | 
					 | 
				
			||||||
		t.Fatal(err)
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
	pvName := "mypv"
 | 
						pvName := "mypv"
 | 
				
			||||||
	if _, err := superuserClientExternal.StorageV1().VolumeAttachments().Create(context.TODO(), &storagev1.VolumeAttachment{
 | 
						if _, err := superuserClientExternal.StorageV1().VolumeAttachments().Create(context.TODO(), &storagev1.VolumeAttachment{
 | 
				
			||||||
		ObjectMeta: metav1.ObjectMeta{Name: "myattachment"},
 | 
							ObjectMeta: metav1.ObjectMeta{Name: "myattachment"},
 | 
				
			||||||
@@ -160,12 +151,6 @@ func TestNodeAuthorizer(t *testing.T) {
 | 
				
			|||||||
			return err
 | 
								return err
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	getConfigMapConfigSource := func(client clientset.Interface) func() error {
 | 
					 | 
				
			||||||
		return func() error {
 | 
					 | 
				
			||||||
			_, err := client.CoreV1().ConfigMaps("ns").Get(context.TODO(), "myconfigmapconfigsource", metav1.GetOptions{})
 | 
					 | 
				
			||||||
			return err
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
	getPVC := func(client clientset.Interface) func() error {
 | 
						getPVC := func(client clientset.Interface) func() error {
 | 
				
			||||||
		return func() error {
 | 
							return func() error {
 | 
				
			||||||
			_, err := client.CoreV1().PersistentVolumeClaims("ns").Get(context.TODO(), "mypvc", metav1.GetOptions{})
 | 
								_, err := client.CoreV1().PersistentVolumeClaims("ns").Get(context.TODO(), "mypvc", metav1.GetOptions{})
 | 
				
			||||||
@@ -260,34 +245,6 @@ func TestNodeAuthorizer(t *testing.T) {
 | 
				
			|||||||
			return err
 | 
								return err
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	setNode2ConfigSource := func(client clientset.Interface) func() error {
 | 
					 | 
				
			||||||
		return func() error {
 | 
					 | 
				
			||||||
			node2, err := client.CoreV1().Nodes().Get(context.TODO(), "node2", metav1.GetOptions{})
 | 
					 | 
				
			||||||
			if err != nil {
 | 
					 | 
				
			||||||
				return err
 | 
					 | 
				
			||||||
			}
 | 
					 | 
				
			||||||
			node2.Spec.ConfigSource = &corev1.NodeConfigSource{
 | 
					 | 
				
			||||||
				ConfigMap: &corev1.ConfigMapNodeConfigSource{
 | 
					 | 
				
			||||||
					Namespace:        "ns",
 | 
					 | 
				
			||||||
					Name:             "myconfigmapconfigsource",
 | 
					 | 
				
			||||||
					KubeletConfigKey: "kubelet",
 | 
					 | 
				
			||||||
				},
 | 
					 | 
				
			||||||
			}
 | 
					 | 
				
			||||||
			_, err = client.CoreV1().Nodes().Update(context.TODO(), node2, metav1.UpdateOptions{})
 | 
					 | 
				
			||||||
			return err
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
	unsetNode2ConfigSource := func(client clientset.Interface) func() error {
 | 
					 | 
				
			||||||
		return func() error {
 | 
					 | 
				
			||||||
			node2, err := client.CoreV1().Nodes().Get(context.TODO(), "node2", metav1.GetOptions{})
 | 
					 | 
				
			||||||
			if err != nil {
 | 
					 | 
				
			||||||
				return err
 | 
					 | 
				
			||||||
			}
 | 
					 | 
				
			||||||
			node2.Spec.ConfigSource = nil
 | 
					 | 
				
			||||||
			_, err = client.CoreV1().Nodes().Update(context.TODO(), node2, metav1.UpdateOptions{})
 | 
					 | 
				
			||||||
			return err
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
	updateNode2Status := func(client clientset.Interface) func() error {
 | 
						updateNode2Status := func(client clientset.Interface) func() error {
 | 
				
			||||||
		return func() error {
 | 
							return func() error {
 | 
				
			||||||
			_, err := client.CoreV1().Nodes().UpdateStatus(context.TODO(), &corev1.Node{
 | 
								_, err := client.CoreV1().Nodes().UpdateStatus(context.TODO(), &corev1.Node{
 | 
				
			||||||
@@ -578,20 +535,6 @@ func TestNodeAuthorizer(t *testing.T) {
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
	// create node2 again
 | 
						// create node2 again
 | 
				
			||||||
	expectAllowed(t, createNode2(node2Client))
 | 
						expectAllowed(t, createNode2(node2Client))
 | 
				
			||||||
	// node2 can not set its own config source
 | 
					 | 
				
			||||||
	expectForbidden(t, setNode2ConfigSource(node2Client))
 | 
					 | 
				
			||||||
	// node2 can not access the configmap config source yet
 | 
					 | 
				
			||||||
	expectForbidden(t, getConfigMapConfigSource(node2Client))
 | 
					 | 
				
			||||||
	// superuser can access the configmap config source
 | 
					 | 
				
			||||||
	expectAllowed(t, getConfigMapConfigSource(superuserClient))
 | 
					 | 
				
			||||||
	// superuser can set node2's config source
 | 
					 | 
				
			||||||
	expectAllowed(t, setNode2ConfigSource(superuserClient))
 | 
					 | 
				
			||||||
	// node2 can now get the configmap assigned as its config source
 | 
					 | 
				
			||||||
	expectAllowed(t, getConfigMapConfigSource(node2Client))
 | 
					 | 
				
			||||||
	// superuser can unset node2's config source
 | 
					 | 
				
			||||||
	expectAllowed(t, unsetNode2ConfigSource(superuserClient))
 | 
					 | 
				
			||||||
	// node2 can no longer get the configmap after it is unassigned as its config source
 | 
					 | 
				
			||||||
	expectForbidden(t, getConfigMapConfigSource(node2Client))
 | 
					 | 
				
			||||||
	// clean up node2
 | 
						// clean up node2
 | 
				
			||||||
	expectAllowed(t, deleteNode2(superuserClient))
 | 
						expectAllowed(t, deleteNode2(superuserClient))
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 
 | 
				
			|||||||
		Reference in New Issue
	
	Block a user