diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index f5b774c..81843ee 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -22,12 +22,12 @@ jobs: - name: Install kubectl, helm, kind and kuttl ⬇️ env: - KUTTL_VERSION: '0.20.0' - KUTTL_PLUGIN_FILENAME: 'kubectl-kuttl_0.20.0_linux_x86_64' + KUTTL_VERSION: '0.25.0' + KUTTL_PLUGIN_FILENAME: 'kubectl-kuttl_0.25.0_linux_x86_64' run: bash hack/install-dependencies.sh - name: Run kind ⚙️ - run: kind create cluster --name kuttl-cluster + run: kind create cluster --name kuttl-cluster --config ./hack/kind-config.yaml - name: Mount the image in the Kind cluster ⚙️ run: | @@ -36,7 +36,7 @@ jobs: - name: Run the tests 🔎 run: | echo "Running the tests" - kubectl kuttl test test/e2e/ --start-kind=false + kubectl kuttl test --config test/e2e/kuttl-test.yaml test/e2e/kuttl --start-kind=false - name: Clean up Kind cluster ☠️ if: always() diff --git a/.gitignore b/.gitignore index 2eaaf45..bf00ff0 100644 --- a/.gitignore +++ b/.gitignore @@ -31,3 +31,5 @@ hack/tilt/bin hack/tilt/chart *kubeconfig* + +e2e.json \ No newline at end of file diff --git a/Makefile b/Makefile index 387bd9a..80adef1 100644 --- a/Makefile +++ b/Makefile @@ -59,7 +59,7 @@ endif OPERATOR_SDK_VERSION ?= v1.40.0 # ENVTEST_K8S_VERSION refers to the version of kubebuilder assets to be downloaded by envtest binary. -ENVTEST_K8S_VERSION = 1.31.0 +ENVTEST_K8S_VERSION = 1.35.0 # Get the currently used golang install path (in GOPATH/bin, unless GOBIN is set) ifeq (,$(shell go env GOBIN)) @@ -217,7 +217,7 @@ GOLANGCI_LINT = $(LOCALBIN)/golangci-lint ## Tool Versions KUSTOMIZE_VERSION ?= v5.4.3 -CONTROLLER_TOOLS_VERSION ?= v0.16.1 +CONTROLLER_TOOLS_VERSION ?= v0.17.2 ENVTEST_VERSION ?= release-0.19 GOLANGCI_LINT_VERSION ?= v1.59.1 diff --git a/config/crd/bases/overcommit.inditex.dev_overcommitclasses.yaml b/config/crd/bases/overcommit.inditex.dev_overcommitclasses.yaml index 75969b9..47eb667 100644 --- a/config/crd/bases/overcommit.inditex.dev_overcommitclasses.yaml +++ b/config/crd/bases/overcommit.inditex.dev_overcommitclasses.yaml @@ -3,7 +3,7 @@ apiVersion: apiextensions.k8s.io/v1 kind: CustomResourceDefinition metadata: annotations: - controller-gen.kubebuilder.io/version: v0.16.1 + controller-gen.kubebuilder.io/version: v0.17.2 name: overcommitclasses.overcommit.inditex.dev spec: group: overcommit.inditex.dev diff --git a/config/crd/bases/overcommit.inditex.dev_overcommits.yaml b/config/crd/bases/overcommit.inditex.dev_overcommits.yaml index f28bb86..bead084 100644 --- a/config/crd/bases/overcommit.inditex.dev_overcommits.yaml +++ b/config/crd/bases/overcommit.inditex.dev_overcommits.yaml @@ -3,7 +3,7 @@ apiVersion: apiextensions.k8s.io/v1 kind: CustomResourceDefinition metadata: annotations: - controller-gen.kubebuilder.io/version: v0.16.1 + controller-gen.kubebuilder.io/version: v0.17.2 name: overcommits.overcommit.inditex.dev spec: group: overcommit.inditex.dev diff --git a/config/webhook/manifests.yaml b/config/webhook/manifests.yaml index b15a0be..19ad31f 100644 --- a/config/webhook/manifests.yaml +++ b/config/webhook/manifests.yaml @@ -13,6 +13,7 @@ webhooks: path: /mutate--v1-pod failurePolicy: Ignore name: mutating-pod-v1.overcommit.inditex.dev + reinvocationPolicy: IfNeeded rules: - apiGroups: - "" @@ -23,6 +24,7 @@ webhooks: - UPDATE resources: - pods + - pods/resize sideEffects: None --- apiVersion: admissionregistration.k8s.io/v1 diff --git a/docs/e2e-test.md b/docs/e2e-test.md index 841db55..492f088 100644 --- a/docs/e2e-test.md +++ b/docs/e2e-test.md @@ -24,5 +24,5 @@ Then build the image and install the test chart in the kind cluster And finally run the tests ```[sh] -kubectl kuttl test code/test/e2e/ --config code/test/e2e/kuttl-tests.yaml --start-kind=false +kubectl kuttl test --config test/e2e/kuttl-test.yaml test/e2e/kuttl --start-kind=false ``` diff --git a/hack/install-dependencies.sh b/hack/install-dependencies.sh index a26dd80..688618b 100644 --- a/hack/install-dependencies.sh +++ b/hack/install-dependencies.sh @@ -8,7 +8,7 @@ set -e #Kubectl -curl -LO https://dl.k8s.io/release/v1.31.0/bin/linux/amd64/kubectl +curl -LO https://dl.k8s.io/release/v1.35.0/bin/linux/amd64/kubectl sudo install -o root -g root -m 0755 kubectl /usr/local/bin/kubectl #Helm3 @@ -22,6 +22,6 @@ sudo mv ${KUTTL_PLUGIN_FILENAME} /usr/local/bin/kubectl-kuttl sudo chmod +x /usr/local/bin/kubectl-kuttl #Kind -curl -Lo ./kind https://kind.sigs.k8s.io/dl/v0.23.0/kind-linux-amd64 +curl -Lo ./kind https://kind.sigs.k8s.io/dl/v0.31.0/kind-linux-amd64 chmod +x ./kind sudo mv ./kind /usr/local/bin/kind diff --git a/hack/kind-config.yaml b/hack/kind-config.yaml new file mode 100644 index 0000000..d58f723 --- /dev/null +++ b/hack/kind-config.yaml @@ -0,0 +1,24 @@ +kind: Cluster +apiVersion: kind.x-k8s.io/v1alpha4 + +featureGates: + InPlacePodVerticalScaling: true + +nodes: +- role: control-plane + image: kindest/node:v1.35.0 + kubeadmConfigPatches: + - | + kind: ClusterConfiguration + apiServer: + extraArgs: + feature-gates: InPlacePodVerticalScaling=true + controllerManager: + extraArgs: + feature-gates: InPlacePodVerticalScaling=true + scheduler: + extraArgs: + feature-gates: InPlacePodVerticalScaling=true + +- role: worker + image: kindest/node:v1.35.0 \ No newline at end of file diff --git a/internal/resources/generate_resources_pod_mutating_webhooks.go b/internal/resources/generate_resources_pod_mutating_webhooks.go index 6f11e46..05f7a19 100644 --- a/internal/resources/generate_resources_pod_mutating_webhooks.go +++ b/internal/resources/generate_resources_pod_mutating_webhooks.go @@ -175,7 +175,7 @@ func getSelectorClassNotExist(label string) *metav1.LabelSelector { } } -func getMatchCondition(isDefault bool, name string, excludedNamespaces string, label string) []admissionv1.MatchCondition { +func getMatchCondition(excludedNamespaces string) []admissionv1.MatchCondition { matchConditions := []admissionv1.MatchCondition{} matchConditions = append(matchConditions, admissionv1.MatchCondition{ Name: "exclude-namespaces", @@ -202,11 +202,36 @@ func getObjectSelector(isDefault bool, label string, name string) *metav1.LabelS } func CreateMutatingWebhookConfiguration(class overcommit.OvercommitClass, svc corev1.Service, cert certmanager.Certificate, label string) *admissionv1.MutatingWebhookConfiguration { - var path = "/mutate--v1-pod" var scope = admissionv1.NamespacedScope var policy = admissionv1.Fail var sideEffect = admissionv1.SideEffectClassNone + var reinvocationPolicy = admissionv1.IfNeededReinvocationPolicy + + rules := []admissionv1.RuleWithOperations{ + { + Operations: []admissionv1.OperationType{ + admissionv1.Create, + }, + Rule: admissionv1.Rule{ + APIGroups: []string{""}, + APIVersions: []string{"v1"}, + Resources: []string{"pods"}, + Scope: &scope, + }, + }, + { + Operations: []admissionv1.OperationType{ + admissionv1.Update, + }, + Rule: admissionv1.Rule{ + APIGroups: []string{""}, + APIVersions: []string{"v1"}, + Resources: []string{"pods/resize"}, + Scope: &scope, + }, + }, + } webhookConfig := &admissionv1.MutatingWebhookConfiguration{ ObjectMeta: metav1.ObjectMeta{ @@ -225,23 +250,12 @@ func CreateMutatingWebhookConfiguration(class overcommit.OvercommitClass, svc co Path: &path, }, }, - Rules: []admissionv1.RuleWithOperations{ - { - Operations: []admissionv1.OperationType{ - admissionv1.Create, - }, - Rule: admissionv1.Rule{ - APIGroups: []string{""}, - APIVersions: []string{"v1"}, - Resources: []string{"pods"}, - Scope: &scope, - }, - }, - }, + Rules: rules, AdmissionReviewVersions: []string{"v1"}, FailurePolicy: &policy, SideEffects: &sideEffect, - MatchConditions: getMatchCondition(false, class.Name, class.Spec.ExcludedNamespaces, label), + ReinvocationPolicy: &reinvocationPolicy, + MatchConditions: getMatchCondition(class.Spec.ExcludedNamespaces), ObjectSelector: getObjectSelector(false, label, class.Name), }, }, @@ -257,25 +271,15 @@ func CreateMutatingWebhookConfiguration(class overcommit.OvercommitClass, svc co Path: &path, }, }, - Rules: []admissionv1.RuleWithOperations{ - { - Operations: []admissionv1.OperationType{ - admissionv1.Create, - }, - Rule: admissionv1.Rule{ - APIGroups: []string{""}, - APIVersions: []string{"v1"}, - Resources: []string{"pods"}, - Scope: &scope, - }, - }, - }, + Rules: rules, AdmissionReviewVersions: []string{"v1"}, FailurePolicy: &policy, SideEffects: &sideEffect, - MatchConditions: getMatchCondition(class.Spec.IsDefault, class.Name, class.Spec.ExcludedNamespaces, label), + ReinvocationPolicy: &reinvocationPolicy, + MatchConditions: getMatchCondition(class.Spec.ExcludedNamespaces), ObjectSelector: getObjectSelector(class.Spec.IsDefault, label, class.Name), }) } + return webhookConfig } diff --git a/internal/webhook/v1alphav1/mutating/pod_webhook.go b/internal/webhook/v1alphav1/mutating/pod_webhook.go index 0c1ca19..958d10b 100644 --- a/internal/webhook/v1alphav1/mutating/pod_webhook.go +++ b/internal/webhook/v1alphav1/mutating/pod_webhook.go @@ -16,13 +16,12 @@ import ( "k8s.io/client-go/tools/record" ctrl "sigs.k8s.io/controller-runtime" "sigs.k8s.io/controller-runtime/pkg/client" - logf "sigs.k8s.io/controller-runtime/pkg/log" "sigs.k8s.io/controller-runtime/pkg/webhook" + "sigs.k8s.io/controller-runtime/pkg/webhook/admission" ) // nolint:unused // log is for logging in this package. -var podlog = logf.Log.WithName("webhook") // PodCustomDefaulter struct is responsible for setting default values on the custom resource of the Kind Pod. type PodCustomDefaulter struct { @@ -40,19 +39,27 @@ func (d *PodCustomDefaulter) InjectClient(c client.Client) { var _ webhook.CustomDefaulter = &PodCustomDefaulter{} -// Default implements webhook.CustomDefaulter so a webhook will be registered for the Kind Pod. func (d *PodCustomDefaulter) Default(ctx context.Context, obj runtime.Object) error { pod, ok := obj.(*corev1.Pod) if !ok { return fmt.Errorf("expected a Pod object but got %T", obj) } - // Call the Overcommit function and pass the EventRecorder + isResize := false + if req, err := admission.RequestFromContext(ctx); err == nil { + isResize = req.SubResource == "resize" + } + + if isResize { + overcommit.OvercommitOnResize(pod, d.Recorder, d.Client) + return nil + } + overcommit.Overcommit(pod, d.Recorder, d.Client) return nil } -// +kubebuilder:webhook:path=/mutate--v1-pod,mutating=true,failurePolicy=ignore,sideEffects=None,groups="",resources=pods,verbs=create;update,versions=v1,name=mutating-pod-v1.overcommit.inditex.dev,admissionReviewVersions=v1 +// +kubebuilder:webhook:path=/mutate--v1-pod,mutating=true,failurePolicy=ignore,reinvocationPolicy=IfNeeded,sideEffects=None,groups="",resources=pods;pods/resize,verbs=create;update,versions=v1,name=mutating-pod-v1.overcommit.inditex.dev,admissionReviewVersions=v1 // +kubebuilder:rbac:groups="",resources=pods,verbs=get;list;watch // SetupPodWebhookWithManager registers the webhook for Pod in the manager. diff --git a/pkg/overcommit/make_overcommit.go b/pkg/overcommit/make_overcommit.go index d86574a..2108024 100644 --- a/pkg/overcommit/make_overcommit.go +++ b/pkg/overcommit/make_overcommit.go @@ -10,7 +10,6 @@ import ( "os" "github.com/InditexTech/k8s-overcommit-operator/internal/metrics" - corev1 "k8s.io/api/core/v1" "k8s.io/apimachinery/pkg/api/resource" "k8s.io/client-go/tools/record" @@ -24,100 +23,76 @@ func mutateContainers(containers []corev1.Container, pod *corev1.Pod, cpuValue f for i, container := range containers { limits := container.Resources.Limits requests := container.Resources.Requests - // If the container doesn't have limits, don't mutate the container + if requests == nil { + requests = corev1.ResourceList{} + } + if limits == nil { - podlog.Info( - "Limits is nil, don't mutate the container", - "containerName", container.Name, "generateName", pod.GenerateName, - ) - } else if cpuValue == 1 && memoryValue == 1 { - podlog.Info( - "Container didn't mutate the cpu and memory", - "generateName", pod.GenerateName, "cpuValue", cpuValue, "memoryValue", memoryValue, - ) - } else { - if cpuLimit, ok := limits[corev1.ResourceCPU]; ok { - // If the cpu overcommit value is 1, don't mutate the container - if cpuValue == 1 { - podlog.Info( - "Container didn't mutate the cpu", - "generateName", pod.GenerateName, "cpuValue", cpuValue, - ) - } - newCPURequest := float64(cpuLimit.MilliValue()) * cpuValue - requests[corev1.ResourceCPU] = *resource.NewMilliQuantity(int64(newCPURequest), resource.DecimalSI) - } - if memoryLimit, ok := limits[corev1.ResourceMemory]; ok { - // If the memory overcommit value is 1, don't mutate the container - if memoryValue == 1 { - podlog.Info( - "Container didn't mutate the memory", - "generateName", pod.GenerateName, "memoryValue", memoryValue, - ) - } - newMemoryRequest := float64(memoryLimit.Value()) * memoryValue - requests[corev1.ResourceMemory] = *resource.NewQuantity(int64(newMemoryRequest), resource.BinarySI) - } - containers[i].Resources.Requests = requests + continue } - } -} -func makeOvercommit(pod *corev1.Pod, cpuValue float64, memoryValue float64) { - mutateContainers(pod.Spec.Containers, pod, cpuValue, memoryValue) - podlog.Info( - "Containers mutated", "generateName", pod.GenerateName, "cpuValue", cpuValue, "memoryValue", memoryValue, - ) -} + if cpuLimit, ok := limits[corev1.ResourceCPU]; ok && cpuValue != 1 { + newCPURequest := float64(cpuLimit.MilliValue()) * cpuValue + requests[corev1.ResourceCPU] = *resource.NewMilliQuantity(int64(newCPURequest), resource.DecimalSI) + } -func makeOvercommitInitContainers(pod *corev1.Pod, cpuValue float64, memoryValue float64) { - mutateContainers(pod.Spec.InitContainers, pod, cpuValue, memoryValue) - podlog.Info( - "InitContainers mutated", "generateName", pod.GenerateName, "cpuValue", cpuValue, "memoryValue", memoryValue, - ) + if memoryLimit, ok := limits[corev1.ResourceMemory]; ok && memoryValue != 1 { + newMemoryRequest := float64(memoryLimit.Value()) * memoryValue + requests[corev1.ResourceMemory] = *resource.NewQuantity(int64(newMemoryRequest), resource.BinarySI) + } + + containers[i].Resources.Requests = requests + } } func Overcommit(pod *corev1.Pod, recorder record.EventRecorder, client client.Client) { ctx := context.Background() - podlog.Info("Mutating Pod", "generateGame", pod.GenerateName) + metrics.K8sOvercommitOperatorPodsRequestedTotal.WithLabelValues(os.Getenv("OVERCOMMIT_CLASS_NAME")).Inc() - // Get the overcommit values from the labels cpuValue, memoryValue := checkOvercommitType(ctx, *pod, client) - // Check if the values are valid - // Multiplicate the limits by the overcommit value and set the new value as request - makeOvercommit(pod, cpuValue, memoryValue) - podlog.Info( - "Pod mutated", "generateName", pod.GenerateName, "cpuValue", cpuValue, "memoryValue", memoryValue, - ) + mutateContainers(pod.Spec.Containers, pod, cpuValue, memoryValue) - // If it has initContainers, make the overcommit - podlog.Info("cheking if pod has initContainer") + // comportamiento actual para CREATE/UPDATE normales if len(pod.Spec.InitContainers) > 0 { - podlog.Info("Pod has initContainers, mutating them", "generateName", pod.GenerateName) - makeOvercommitInitContainers(pod, cpuValue, memoryValue) + mutateContainers(pod.Spec.InitContainers, pod, cpuValue, memoryValue) } - // Increment the metric K8sOvercommitOperatorMutatedPodsTotal metrics.K8sOvercommitOperatorMutatedPodsTotal.WithLabelValues(os.Getenv("OVERCOMMIT_CLASS_NAME")).Inc() - // Add an event to the pod recorder.Eventf( pod, corev1.EventTypeNormal, "OvercommitApplied", - "Applied overcommit to containers of Pod '%s': OvercommitClass = %s, CPU Overcommit = %.2f, Memory Overcommit = %.2f", + "Applied overcommit to Pod '%s': OvercommitClass = %s, CPU Overcommit = %.2f, Memory Overcommit = %.2f", pod.Name, os.Getenv("OVERCOMMIT_CLASS_NAME"), cpuValue, memoryValue, ) - if cpuValue == 1 && memoryValue == 1 { - metrics.K8sOvercommitOperatorPodsNotMutatedTotal.WithLabelValues( - os.Getenv("OVERCOMMIT_CLASS_NAME"), pod.GenerateName, pod.Namespace, "overcommit values = 1", - ).Inc() +} - } - podlog.Info("Pod mutated", "generateName", pod.GenerateName, "cpuValue", cpuValue, "memoryValue", memoryValue) +func OvercommitOnResize(pod *corev1.Pod, recorder record.EventRecorder, client client.Client) { + ctx := context.Background() + + metrics.K8sOvercommitOperatorPodsRequestedTotal.WithLabelValues(os.Getenv("OVERCOMMIT_CLASS_NAME")).Inc() + + cpuValue, memoryValue := checkOvercommitType(ctx, *pod, client) + + // En resize: solo containers normales. + mutateContainers(pod.Spec.Containers, pod, cpuValue, memoryValue) + + metrics.K8sOvercommitOperatorMutatedPodsTotal.WithLabelValues(os.Getenv("OVERCOMMIT_CLASS_NAME")).Inc() + + recorder.Eventf( + pod, + corev1.EventTypeNormal, + "OvercommitAppliedOnResize", + "Applied overcommit on resize to Pod '%s': OvercommitClass = %s, CPU Overcommit = %.2f, Memory Overcommit = %.2f", + pod.Name, + os.Getenv("OVERCOMMIT_CLASS_NAME"), + cpuValue, + memoryValue, + ) } diff --git a/pkg/overcommit/make_overcommit_test.go b/pkg/overcommit/make_overcommit_test.go index e59b50e..31e7866 100644 --- a/pkg/overcommit/make_overcommit_test.go +++ b/pkg/overcommit/make_overcommit_test.go @@ -17,7 +17,8 @@ import ( var _ = Describe("Overcommit", func() { var ( - pod *corev1.Pod + pod *corev1.Pod + expectedRequests = corev1.ResourceList{ corev1.ResourceCPU: *resource.NewMilliQuantity(500, resource.DecimalSI), corev1.ResourceMemory: *resource.NewQuantity(536870912, resource.BinarySI), @@ -51,6 +52,7 @@ var _ = Describe("Overcommit", func() { }) Describe("mutateContainers", func() { + It("should mutate container requests based on overcommit values", func() { mutateContainers(pod.Spec.Containers, pod, 0.5, 0.5) @@ -59,21 +61,44 @@ var _ = Describe("Overcommit", func() { It("should not mutate containers if limits are nil", func() { pod.Spec.Containers[0].Resources.Limits = nil + mutateContainers(pod.Spec.Containers, pod, 0.5, 0.5) Expect(pod.Spec.Containers[0].Resources.Requests).To(BeEmpty()) }) + + It("should initialize requests if requests is nil", func() { + pod.Spec.Containers[0].Resources.Requests = nil + + mutateContainers(pod.Spec.Containers, pod, 0.5, 0.5) + + Expect(pod.Spec.Containers[0].Resources.Requests).To(Equal(expectedRequests)) + }) + + It("should be idempotent when applied multiple times", func() { + mutateContainers(pod.Spec.Containers, pod, 0.5, 0.5) + + first := pod.Spec.Containers[0].Resources.Requests.Cpu().MilliValue() + + mutateContainers(pod.Spec.Containers, pod, 0.5, 0.5) + + second := pod.Spec.Containers[0].Resources.Requests.Cpu().MilliValue() + + Expect(first).To(Equal(second)) + }) + }) Describe("makeOvercommit", func() { It("should apply overcommit to containers", func() { - makeOvercommit(pod, 0.5, 0.5) + Overcommit(pod, recorder, k8sClient) Expect(pod.Spec.Containers[0].Resources.Requests).To(Equal(expectedRequests)) }) }) Describe("Overcommit", func() { + BeforeEach(func() { os.Setenv("OVERCOMMIT_CLASS_NAME", "test-class") }) @@ -86,7 +111,27 @@ var _ = Describe("Overcommit", func() { Overcommit(pod, recorder, k8sClient) Expect(pod.Spec.Containers[0].Resources.Requests).To(Equal(expectedRequests)) + }) + }) + + Describe("Resize behaviour", func() { + + It("should recompute requests when limits change", func() { + + mutateContainers(pod.Spec.Containers, pod, 0.5, 0.5) + + Expect(pod.Spec.Containers[0].Resources.Requests).To(Equal(expectedRequests)) + + pod.Spec.Containers[0].Resources.Limits[corev1.ResourceCPU] = resource.MustParse("2") + + mutateContainers(pod.Spec.Containers, pod, 0.5, 0.5) + + Expect( + pod.Spec.Containers[0].Resources.Requests.Cpu().MilliValue(), + ).To(Equal(int64(1000))) }) + }) + }) diff --git a/test/e2e/kuttl/1-09_validate_inplace_resize/00-assert.yaml b/test/e2e/kuttl/1-09_validate_inplace_resize/00-assert.yaml new file mode 100644 index 0000000..b562225 --- /dev/null +++ b/test/e2e/kuttl/1-09_validate_inplace_resize/00-assert.yaml @@ -0,0 +1,16 @@ +# SPDX-FileCopyrightText: 2025 2025 INDUSTRIA DE DISEÑO TEXTIL S.A. (INDITEX S.A.) +# SPDX-FileContributor: enriqueavi@inditex.com +# +# SPDX-License-Identifier: Apache-2.0 +apiVersion: v1 +kind: Pod +metadata: + name: resize-test + namespace: resize-test-ns +spec: + containers: + - name: test + resources: + requests: + cpu: "250m" + memory: "512Mi" \ No newline at end of file diff --git a/test/e2e/kuttl/1-09_validate_inplace_resize/00-setup.yaml b/test/e2e/kuttl/1-09_validate_inplace_resize/00-setup.yaml new file mode 100644 index 0000000..fdfe96d --- /dev/null +++ b/test/e2e/kuttl/1-09_validate_inplace_resize/00-setup.yaml @@ -0,0 +1,23 @@ +# SPDX-FileCopyrightText: 2025 2025 INDUSTRIA DE DISEÑO TEXTIL S.A. (INDITEX S.A.) +# SPDX-FileContributor: enriqueavi@inditex.com +# +# SPDX-License-Identifier: Apache-2.0 +apiVersion: v1 +kind: Namespace +metadata: + name: resize-test-ns +--- +apiVersion: v1 +kind: Pod +metadata: + name: resize-test + namespace: resize-test-ns +spec: + containers: + - name: test + image: busybox + command: ["sleep","3600"] + resources: + limits: + cpu: "500m" + memory: "1Gi" \ No newline at end of file diff --git a/test/e2e/kuttl/1-09_validate_inplace_resize/01-assert.yaml b/test/e2e/kuttl/1-09_validate_inplace_resize/01-assert.yaml new file mode 100644 index 0000000..6052a7c --- /dev/null +++ b/test/e2e/kuttl/1-09_validate_inplace_resize/01-assert.yaml @@ -0,0 +1,15 @@ +# SPDX-FileCopyrightText: 2025 2025 INDUSTRIA DE DISEÑO TEXTIL S.A. (INDITEX S.A.) +# SPDX-FileContributor: enriqueavi@inditex.com +# +# SPDX-License-Identifier: Apache-2.0 +apiVersion: v1 +kind: Pod +metadata: + name: resize-test + namespace: resize-test-ns +spec: + containers: + - name: test + resources: + requests: + cpu: "500m" \ No newline at end of file diff --git a/test/e2e/kuttl/1-09_validate_inplace_resize/01-setup.yaml b/test/e2e/kuttl/1-09_validate_inplace_resize/01-setup.yaml new file mode 100644 index 0000000..2156fb8 --- /dev/null +++ b/test/e2e/kuttl/1-09_validate_inplace_resize/01-setup.yaml @@ -0,0 +1,12 @@ +# SPDX-FileCopyrightText: 2025 2025 INDUSTRIA DE DISEÑO TEXTIL S.A. (INDITEX S.A.) +# SPDX-FileContributor: enriqueavi@inditex.com +# +# SPDX-License-Identifier: Apache-2.0 +apiVersion: kuttl.dev/v1beta1 +kind: TestStep +commands: + - command: > + kubectl patch pod resize-test + -n resize-test-ns + --subresource=resize + -p '{"spec":{"containers":[{"name":"test","resources":{"limits":{"cpu":"1"}}}]}}' \ No newline at end of file