From 0cbf74abaae9296e49b0a031dd4e7aee4bc54c25 Mon Sep 17 00:00:00 2001 From: marcinda Date: Fri, 13 Mar 2026 17:03:00 +0100 Subject: [PATCH] possibility of setting priorityClassName in pod template configuration and via yamlMergeStrategy: merge with yaml section --- .../plugins/kubernetes/PodTemplate.java | 12 ++++++++ .../kubernetes/PodTemplateBuilder.java | 3 ++ .../plugins/kubernetes/PodTemplateUtils.java | 3 ++ .../pipeline/KubernetesDeclarativeAgent.java | 16 ++++++++++ .../kubernetes/pipeline/PodTemplateStep.java | 14 +++++++++ .../pipeline/PodTemplateStepExecution.java | 1 + .../kubernetes/PodTemplate/config.jelly | 4 +++ .../PodTemplate/help-priorityClassName.html | 1 + .../KubernetesDeclarativeAgent/config.jelly | 3 ++ .../pipeline/PodTemplateStep/config.jelly | 3 ++ .../kubernetes/PodTemplateBuilderTest.java | 30 +++++++++++++++++++ .../kubernetes/PodTemplateUtilsTest.java | 25 ++++++++++++++++ 12 files changed, 115 insertions(+) create mode 100644 src/main/resources/org/csanchez/jenkins/plugins/kubernetes/PodTemplate/help-priorityClassName.html diff --git a/src/main/java/org/csanchez/jenkins/plugins/kubernetes/PodTemplate.java b/src/main/java/org/csanchez/jenkins/plugins/kubernetes/PodTemplate.java index ae43d991b..bdad2b696 100644 --- a/src/main/java/org/csanchez/jenkins/plugins/kubernetes/PodTemplate.java +++ b/src/main/java/org/csanchez/jenkins/plugins/kubernetes/PodTemplate.java @@ -154,6 +154,8 @@ protected static MessageDigest getLabelDigestFunction() { private String schedulerName; + private String priorityClassName; + private String nodeSelector; private Node.Mode nodeUsageMode; @@ -608,6 +610,15 @@ public void setSchedulerName(String schedulerName) { this.schedulerName = Util.fixEmpty(schedulerName); } + public String getPriorityClassName() { + return priorityClassName; + } + + @DataBoundSetter + public void setPriorityClassName(String priorityClassName) { + this.priorityClassName = Util.fixEmpty(priorityClassName); + } + @Deprecated @DataBoundSetter public void setAlwaysPullImage(boolean alwaysPullImage) { @@ -1173,6 +1184,7 @@ public String toString() { + (label == null ? "" : ", label='" + label + '\'') + (serviceAccount == null ? "" : ", serviceAccount='" + serviceAccount + '\'') + (schedulerName == null ? "" : ", schedulerName='" + schedulerName + '\'') + + (priorityClassName == null ? "" : ", priorityClassName='" + priorityClassName + '\'') + (nodeSelector == null ? "" : ", nodeSelector='" + nodeSelector + '\'') + (nodeUsageMode == null ? "" : ", nodeUsageMode=" + nodeUsageMode) + (resourceRequestCpu == null ? "" : ", resourceRequestCpu='" + resourceRequestCpu + '\'') diff --git a/src/main/java/org/csanchez/jenkins/plugins/kubernetes/PodTemplateBuilder.java b/src/main/java/org/csanchez/jenkins/plugins/kubernetes/PodTemplateBuilder.java index 622d79b1a..fb852840e 100644 --- a/src/main/java/org/csanchez/jenkins/plugins/kubernetes/PodTemplateBuilder.java +++ b/src/main/java/org/csanchez/jenkins/plugins/kubernetes/PodTemplateBuilder.java @@ -256,6 +256,9 @@ public Pod build() { if (template.getSchedulerName() != null) { builder.withSchedulerName(substituteEnv(template.getSchedulerName())); } + if (template.getPriorityClassName() != null) { + builder.withPriorityClassName(substituteEnv(template.getPriorityClassName())); + } List imagePullSecrets = template.getImagePullSecrets().stream() .map((x) -> x.toLocalObjectReference()) diff --git a/src/main/java/org/csanchez/jenkins/plugins/kubernetes/PodTemplateUtils.java b/src/main/java/org/csanchez/jenkins/plugins/kubernetes/PodTemplateUtils.java index ac5b98c90..75027fe25 100644 --- a/src/main/java/org/csanchez/jenkins/plugins/kubernetes/PodTemplateUtils.java +++ b/src/main/java/org/csanchez/jenkins/plugins/kubernetes/PodTemplateUtils.java @@ -332,6 +332,7 @@ public static Pod combine(Pod parent, Pod template) { .withServiceAccount(h.resolve(PodSpec::getServiceAccount, PodTemplateUtils::isNullOrEmpty)) // .withServiceAccountName(h.resolve(PodSpec::getServiceAccountName, PodTemplateUtils::isNullOrEmpty)) // .withSchedulerName(h.resolve(PodSpec::getSchedulerName, PodTemplateUtils::isNullOrEmpty)) + .withPriorityClassName(h.resolve(PodSpec::getPriorityClassName, PodTemplateUtils::isNullOrEmpty)) .withActiveDeadlineSeconds(h.resolve(PodSpec::getActiveDeadlineSeconds, Objects::isNull)) // .withHostNetwork(h.resolve(PodSpec::getHostNetwork, Objects::isNull)) // .withShareProcessNamespace(h.resolve(PodSpec::getShareProcessNamespace, Objects::isNull)) // @@ -473,6 +474,7 @@ public static PodTemplate combine(PodTemplate parent, PodTemplate template) { podTemplate.setNodeSelector(h.resolve(PodTemplate::getNodeSelector, PodTemplateUtils::isNullOrEmpty)); podTemplate.setServiceAccount(h.resolve(PodTemplate::getServiceAccount, PodTemplateUtils::isNullOrEmpty)); podTemplate.setSchedulerName(h.resolve(PodTemplate::getSchedulerName, PodTemplateUtils::isNullOrEmpty)); + podTemplate.setPriorityClassName(h.resolve(PodTemplate::getPriorityClassName, PodTemplateUtils::isNullOrEmpty)); podTemplate.setEnvVars(combineEnvVars(parent, template)); podTemplate.setContainers(new ArrayList<>(combinedContainers.values())); podTemplate.setWorkspaceVolume(workspaceVolume); @@ -496,6 +498,7 @@ public static PodTemplate combine(PodTemplate parent, PodTemplate template) { h.resolve(PodTemplate::getActiveDeadlineSeconds, i -> Objects.equals(i, 0))); podTemplate.setServiceAccount(h.resolve(PodTemplate::getServiceAccount, PodTemplateUtils::isNullOrEmpty)); podTemplate.setSchedulerName(h.resolve(PodTemplate::getSchedulerName, PodTemplateUtils::isNullOrEmpty)); + podTemplate.setPriorityClassName(h.resolve(PodTemplate::getPriorityClassName, PodTemplateUtils::isNullOrEmpty)); podTemplate.setPodRetention(template.getPodRetention()); podTemplate.setShowRawYaml(h.resolve(PodTemplate::isShowRawYaml, v -> v)); podTemplate.setRunAsUser(h.resolve(PodTemplate::getRunAsUser, Objects::isNull)); diff --git a/src/main/java/org/csanchez/jenkins/plugins/kubernetes/pipeline/KubernetesDeclarativeAgent.java b/src/main/java/org/csanchez/jenkins/plugins/kubernetes/pipeline/KubernetesDeclarativeAgent.java index 1c2c8f327..63cbadcbd 100644 --- a/src/main/java/org/csanchez/jenkins/plugins/kubernetes/pipeline/KubernetesDeclarativeAgent.java +++ b/src/main/java/org/csanchez/jenkins/plugins/kubernetes/pipeline/KubernetesDeclarativeAgent.java @@ -62,6 +62,9 @@ public class KubernetesDeclarativeAgent extends RetryableDeclarativeAgent getAsArgs() { if (!StringUtils.isEmpty(serviceAccount)) { argMap.put("serviceAccount", serviceAccount); } + if (!StringUtils.isEmpty(priorityClassName)) { + argMap.put("priorityClassName", priorityClassName); + } if (!StringUtils.isEmpty(nodeSelector)) { argMap.put("nodeSelector", nodeSelector); } @@ -475,6 +490,7 @@ public static class DescriptorImpl extends DeclarativeAgentDescriptor + + + + diff --git a/src/main/resources/org/csanchez/jenkins/plugins/kubernetes/PodTemplate/help-priorityClassName.html b/src/main/resources/org/csanchez/jenkins/plugins/kubernetes/PodTemplate/help-priorityClassName.html new file mode 100644 index 000000000..7a8b335b0 --- /dev/null +++ b/src/main/resources/org/csanchez/jenkins/plugins/kubernetes/PodTemplate/help-priorityClassName.html @@ -0,0 +1 @@ +The Kubernetes priority class name to assign to the pod. diff --git a/src/main/resources/org/csanchez/jenkins/plugins/kubernetes/pipeline/KubernetesDeclarativeAgent/config.jelly b/src/main/resources/org/csanchez/jenkins/plugins/kubernetes/pipeline/KubernetesDeclarativeAgent/config.jelly index b28d8c673..ace995abf 100644 --- a/src/main/resources/org/csanchez/jenkins/plugins/kubernetes/pipeline/KubernetesDeclarativeAgent/config.jelly +++ b/src/main/resources/org/csanchez/jenkins/plugins/kubernetes/pipeline/KubernetesDeclarativeAgent/config.jelly @@ -43,6 +43,9 @@ + + + diff --git a/src/main/resources/org/csanchez/jenkins/plugins/kubernetes/pipeline/PodTemplateStep/config.jelly b/src/main/resources/org/csanchez/jenkins/plugins/kubernetes/pipeline/PodTemplateStep/config.jelly index fac72d05f..4da89fc4a 100755 --- a/src/main/resources/org/csanchez/jenkins/plugins/kubernetes/pipeline/PodTemplateStep/config.jelly +++ b/src/main/resources/org/csanchez/jenkins/plugins/kubernetes/pipeline/PodTemplateStep/config.jelly @@ -82,6 +82,9 @@ + + + diff --git a/src/test/java/org/csanchez/jenkins/plugins/kubernetes/PodTemplateBuilderTest.java b/src/test/java/org/csanchez/jenkins/plugins/kubernetes/PodTemplateBuilderTest.java index 84b4fac6b..6f764063f 100644 --- a/src/test/java/org/csanchez/jenkins/plugins/kubernetes/PodTemplateBuilderTest.java +++ b/src/test/java/org/csanchez/jenkins/plugins/kubernetes/PodTemplateBuilderTest.java @@ -865,6 +865,36 @@ public void yamlOverrideSchedulerName() { assertEquals("custom-scheduler", pod.getSpec().getSchedulerName()); } + @Test + public void yamlOverridePriorityClassName() { + PodTemplate parent = new PodTemplate(); + parent.setYaml("apiVersion: v1\n" + "kind: Pod\n" + + "metadata:\n" + + " labels:\n" + + " some-label: some-label-value\n" + + "spec:\n" + + " priorityClassName: parent-priority\n"); + + PodTemplate child = new PodTemplate(); + child.setYaml("spec:\n" + " priorityClassName: child-priority\n"); + child.setInheritFrom("parent"); + child.setYamlMergeStrategy(merge()); + PodTemplate result = combine(parent, child); + Pod pod = new PodTemplateBuilder(result, slave).build(); + assertEquals("child-priority", pod.getSpec().getPriorityClassName()); + } + + @Test + public void topLevelPriorityClassNameIsApplied() { + PodTemplate template = new PodTemplate(); + template.setPriorityClassName("high-priority"); + setupStubs(); + + Pod pod = new PodTemplateBuilder(template, slave).build(); + + assertEquals("high-priority", pod.getSpec().getPriorityClassName()); + } + @Test public void yamlOverrideSecurityContext() { PodTemplate parent = new PodTemplate(); diff --git a/src/test/java/org/csanchez/jenkins/plugins/kubernetes/PodTemplateUtilsTest.java b/src/test/java/org/csanchez/jenkins/plugins/kubernetes/PodTemplateUtilsTest.java index d9869f631..0d104ba1c 100644 --- a/src/test/java/org/csanchez/jenkins/plugins/kubernetes/PodTemplateUtilsTest.java +++ b/src/test/java/org/csanchez/jenkins/plugins/kubernetes/PodTemplateUtilsTest.java @@ -168,6 +168,26 @@ public void shouldOverrideNodeSelectorIfSpecified() { assertEquals("key:value", result.getNodeSelector()); } + @Test + public void shouldOverridePriorityClassNameIfSpecified() { + PodTemplate parent = new PodTemplate(); + parent.setName("parent"); + parent.setPriorityClassName("parent-priority"); + + PodTemplate template1 = new PodTemplate(); + template1.setName("template1"); + template1.setPriorityClassName("child-priority"); + + PodTemplate template2 = new PodTemplate(); + template2.setName("template2"); + + PodTemplate result = combine(parent, template1); + assertEquals("child-priority", result.getPriorityClassName()); + + result = combine(parent, template2); + assertEquals("parent-priority", result.getPriorityClassName()); + } + @Test public void shouldCombineAllImagePullSecrets() { PodTemplate parent = new PodTemplate(); @@ -252,6 +272,7 @@ public void shouldUnwrapParent() { parent.setName("parent"); parent.setLabel("parent"); parent.setServiceAccount("sa"); + parent.setPriorityClassName("parent-priority"); parent.setNodeSelector("key:value"); parent.setImagePullSecrets(asList(SECRET_1)); parent.setYaml("Yaml"); @@ -263,12 +284,14 @@ public void shouldUnwrapParent() { template1.setName("template1"); template1.setInheritFrom("parent"); template1.setServiceAccount("sa1"); + template1.setPriorityClassName("child-priority"); template1.setImagePullSecrets(asList(SECRET_2, SECRET_3)); template1.setYaml("Yaml2"); PodTemplate result = unwrap(template1, asList(parent, template1)); assertEquals(3, result.getImagePullSecrets().size()); assertEquals("sa1", result.getServiceAccount()); + assertEquals("child-priority", result.getPriorityClassName()); assertEquals("key:value", result.getNodeSelector()); assertThat(result.getYamls(), hasSize(2)); assertThat(result.getYamls(), contains("Yaml", "Yaml2")); @@ -284,6 +307,7 @@ public void shouldDropNoDataWhenIdentical() { podTemplate.setNamespace("NameSpace"); podTemplate.setLabel("Label"); podTemplate.setServiceAccount("ServiceAccount"); + podTemplate.setPriorityClassName("PriorityClassName"); podTemplate.setNodeSelector("NodeSelector"); podTemplate.setNodeUsageMode(Node.Mode.EXCLUSIVE); podTemplate.setImagePullSecrets(asList(SECRET_1)); @@ -301,6 +325,7 @@ public void shouldDropNoDataWhenIdentical() { assertEquals("NameSpace", selfCombined.getNamespace()); assertEquals("Label", selfCombined.getLabel()); assertEquals("ServiceAccount", selfCombined.getServiceAccount()); + assertEquals("PriorityClassName", selfCombined.getPriorityClassName()); assertEquals("NodeSelector", selfCombined.getNodeSelector()); assertEquals(Node.Mode.EXCLUSIVE, selfCombined.getNodeUsageMode()); assertEquals(asList(SECRET_1), selfCombined.getImagePullSecrets());