Repository: kubernetes/kubernetes (language: go)

Issue:
[FG:InPlacePodVerticalScaling] drop support for windows
1. In `ValidatePodResize`, if the pod OS is windows, forbid resizing
2. In `handlePodResourcesResize`, if the OS is windows set the resize status to Infeasible, and proceed with the allocated pod.

/kind feature
/sig node
/milestone v1.32


Discussion / hints:
There are no sig labels on this issue. Please add an appropriate label by using one of the following commands:
- `/sig <group-name>`
- `/wg <group-name>`
- `/committee <group-name>`

Please see the [group list](https://git.k8s.io/community/sig-list.md) for a listing of the SIGs, working groups, and committees available.


<details>

Instructions for interacting with me using PR comments are available [here](https://git.k8s.io/community/contributors/guide/pull-requests.md).  If you have questions or suggestions related to my behavior, please file an issue against the [kubernetes-sigs/prow](https://github.com/kubernetes-sigs/prow/issues/new?title=Prow%20issue:) repository.
</details>
This issue is currently awaiting triage.

If a SIG or subproject determines this is a relevant issue, they will accept it by applying the `triage/accepted` label and provide further guidance.

The `triage/accepted` label can be added by org members by writing `/triage accepted` in a comment.


<details>

Instructions for interacting with me using PR comments are available [here](https://git.k8s.io/community/contributors/guide/pull-requests.md).  If you have questions or suggestions related to my behavior, please file an issue against the [kubernetes-sigs/prow](https://github.com/kubernetes-sigs/prow/issues/new?title=Prow%20issue:) repository.
</details>
/assign @AnishShah 

Fix patch:
diff --git a/pkg/apis/core/validation/validation.go b/pkg/apis/core/validation/validation.go
index fa0d6e731cc99..5aa310e223dea 100644
--- a/pkg/apis/core/validation/validation.go
+++ b/pkg/apis/core/validation/validation.go
@@ -5503,6 +5503,11 @@ func ValidatePodResize(newPod, oldPod *core.Pod, opts PodValidationOptions) fiel
 		return field.ErrorList{field.Forbidden(field.NewPath(""), "static pods cannot be resized")}
 	}
 
+	// windows pods are not supported.
+	if oldPod.Spec.OS != nil && oldPod.Spec.OS.Name == core.Windows {
+		return field.ErrorList{field.Forbidden(field.NewPath(""), "windows pods cannot be resized")}
+	}
+
 	// Part 2: Validate that the changes between oldPod.Spec.Containers[].Resources and
 	// newPod.Spec.Containers[].Resources are allowed.
 	specPath := field.NewPath("spec")
diff --git a/pkg/kubelet/kubelet.go b/pkg/kubelet/kubelet.go
index 995bb31898d45..c498027ec8698 100644
--- a/pkg/kubelet/kubelet.go
+++ b/pkg/kubelet/kubelet.go
@@ -243,10 +243,13 @@ var (
 		topologymanager.ErrorTopologyAffinity,
 		nodeshutdown.NodeShutdownNotAdmittedReason,
 	)
+
+	// This is exposed for unit tests.
+	goos = sysruntime.GOOS
 )
 
 func getContainerEtcHostsPath() string {
-	if sysruntime.GOOS == "windows" {
+	if goos == "windows" {
 		return windowsEtcHostsPath
 	}
 	return linuxEtcHostsPath
@@ -940,7 +943,7 @@ func NewMainKubelet(kubeCfg *kubeletconfiginternal.KubeletConfiguration,
 		opt(klet)
 	}
 
-	if sysruntime.GOOS == "linux" {
+	if goos == "linux" {
 		// AppArmor is a Linux kernel security module and it does not support other operating systems.
 		klet.appArmorValidator = apparmor.NewValidator()
 		klet.admitHandlers.AddPodAdmitHandler(lifecycle.NewAppArmorAdmitHandler(klet.appArmorValidator))
@@ -1564,7 +1567,7 @@ func (kl *Kubelet) initializeModules() error {
 		}
 	}
 
-	if sysruntime.GOOS == "windows" {
+	if goos == "windows" {
 		// On Windows we should not allow other users to read the logs directory
 		// to avoid allowing non-root containers from reading the logs of other containers.
 		if err := utilfs.Chmod(ContainerLogsDir, 0750); err != nil {
@@ -2865,6 +2868,10 @@ func (kl *Kubelet) handlePodResourcesResize(pod *v1.Pod, podStatus *kubecontaine
 		// Pod allocation does not need to be updated.
 		return allocatedPod, nil
 	}
+	if goos == "windows" {
+		kl.statusManager.SetPodResizeStatus(pod.UID, v1.PodResizeStatusInfeasible)
+		return allocatedPod, nil
+	}
 
 	kl.podResizeMutex.Lock()
 	defer kl.podResizeMutex.Unlock()


Test patch:
diff --git a/pkg/apis/core/validation/validation_test.go b/pkg/apis/core/validation/validation_test.go
index 47944ffd31af5..bd457b40adf60 100644
--- a/pkg/apis/core/validation/validation_test.go
+++ b/pkg/apis/core/validation/validation_test.go
@@ -25075,22 +25075,20 @@ func TestValidateSELinuxChangePolicy(t *testing.T) {
 }
 
 func TestValidatePodResize(t *testing.T) {
-	mkPod := func(req, lim core.ResourceList, tweaks ...podtest.TweakContainer) *core.Pod {
-		return podtest.MakePod("pod",
+	mkPod := func(req, lim core.ResourceList, tweaks ...podtest.Tweak) *core.Pod {
+		return podtest.MakePod("pod", append(tweaks,
 			podtest.SetContainers(
 				podtest.MakeContainer(
 					"container",
-					append(tweaks,
-						podtest.SetContainerResources(
-							core.ResourceRequirements{
-								Requests: req,
-								Limits:   lim,
-							},
-						),
-					)...,
+					podtest.SetContainerResources(
+						core.ResourceRequirements{
+							Requests: req,
+							Limits:   lim,
+						},
+					),
 				),
 			),
-		)
+		)...)
 	}
 
 	tests := []struct {
@@ -25179,6 +25177,16 @@ func TestValidatePodResize(t *testing.T) {
 			old:  mkPod(getResources("100m", "100Mi", "", ""), getResources("200m", "200Mi", "", "")),
 			new:  mkPod(core.ResourceList{}, core.ResourceList{}),
 			err:  "Pod QOS Class may not change as a result of resizing",
+		}, {
+			test: "windows pod, no resource change",
+			old:  mkPod(core.ResourceList{}, getResources("100m", "0", "1Gi", ""), podtest.SetOS(core.Windows)),
+			new:  mkPod(core.ResourceList{}, getResources("100m", "0", "1Gi", ""), podtest.SetOS(core.Windows)),
+			err:  "Forbidden: windows pods cannot be resized",
+		}, {
+			test: "windows pod, resource change",
+			old:  mkPod(core.ResourceList{}, getResources("100m", "0", "1Gi", ""), podtest.SetOS(core.Windows)),
+			new:  mkPod(core.ResourceList{}, getResources("200m", "0", "1Gi", ""), podtest.SetOS(core.Windows)),
+			err:  "Forbidden: windows pods cannot be resized",
 		},
 	}
 
diff --git a/pkg/kubelet/kubelet_test.go b/pkg/kubelet/kubelet_test.go
index b2baa94481c4a..3407b9ee4a5d8 100644
--- a/pkg/kubelet/kubelet_test.go
+++ b/pkg/kubelet/kubelet_test.go
@@ -2676,6 +2676,7 @@ func TestHandlePodResourcesResize(t *testing.T) {
 		newRequestsAllocated bool // Whether the new requests have already been allocated (but not actuated)
 		expectedAllocations  v1.ResourceList
 		expectedResize       v1.PodResizeStatus
+		goos                 string
 	}{
 		{
 			name:                "Request CPU and memory decrease - expect InProgress",
@@ -2741,10 +2742,23 @@ func TestHandlePodResourcesResize(t *testing.T) {
 			expectedAllocations: v1.ResourceList{v1.ResourceCPU: cpu1000m, v1.ResourceMemory: mem1000M},
 			expectedResize:      "",
 		},
+		{
+			name:                "windows node, expect Infeasible",
+			pod:                 testPod2,
+			newRequests:         v1.ResourceList{v1.ResourceCPU: cpu500m, v1.ResourceMemory: mem500M},
+			expectedAllocations: v1.ResourceList{v1.ResourceCPU: cpu1000m, v1.ResourceMemory: mem1000M},
+			expectedResize:      v1.PodResizeStatusInfeasible,
+			goos:                "windows",
+		},
 	}
 
 	for _, tt := range tests {
 		t.Run(tt.name, func(t *testing.T) {
+			oldGOOS := goos
+			defer func() { goos = oldGOOS }()
+			if tt.goos != "" {
+				goos = tt.goos
+			}
 			kubelet.statusManager = status.NewFakeManager()
 
 			newPod := tt.pod.DeepCopy()