diff --git a/pkg/apis/batch/validation/validation_test.go b/pkg/apis/batch/validation/validation_test.go index 0fd38241cd8..64c50e50318 100644 --- a/pkg/apis/batch/validation/validation_test.go +++ b/pkg/apis/batch/validation/validation_test.go @@ -134,6 +134,25 @@ func TestValidateJob(t *testing.T) { }, }, }, + "valid pod failure policy with negative exitCodes - need for Windows support": { + opts: JobValidationOptions{RequirePrefixedLabels: true}, + job: batch.Job{ + ObjectMeta: validJobObjectMeta, + Spec: batch.JobSpec{ + Selector: validGeneratedSelector, + Template: validPodTemplateSpecForGeneratedRestartPolicyNever, + PodFailurePolicy: &batch.PodFailurePolicy{ + Rules: []batch.PodFailurePolicyRule{{ + Action: batch.PodFailurePolicyActionFailJob, + OnExitCodes: &batch.PodFailurePolicyOnExitCodesRequirement{ + Operator: batch.PodFailurePolicyOnExitCodesOpNotIn, + Values: []int32{-1073741819, -1073741676, -1073741510}, + }, + }}, + }, + }, + }, + }, "valid pod failure policy": { opts: JobValidationOptions{RequirePrefixedLabels: true}, job: batch.Job{ diff --git a/pkg/controller/job/pod_failure_policy_test.go b/pkg/controller/job/pod_failure_policy_test.go index 00c8aa5fa40..76691883426 100644 --- a/pkg/controller/job/pod_failure_policy_test.go +++ b/pkg/controller/job/pod_failure_policy_test.go @@ -216,6 +216,37 @@ func TestMatchPodFailurePolicy(t *testing.T) { wantCountFailed: false, wantAction: &ignore, }, + "ignore rule matched on negative exit codes - needed for Windows support": { + podFailurePolicy: &batch.PodFailurePolicy{ + Rules: []batch.PodFailurePolicyRule{ + { + Action: batch.PodFailurePolicyActionIgnore, + OnExitCodes: &batch.PodFailurePolicyOnExitCodesRequirement{ + Operator: batch.PodFailurePolicyOnExitCodesOpIn, + Values: []int32{-1073741676, -1073741510}, + }, + }, + }, + }, + failedPod: &v1.Pod{ + ObjectMeta: validPodObjectMeta, + Status: v1.PodStatus{ + Phase: v1.PodFailed, + ContainerStatuses: []v1.ContainerStatus{ + { + State: v1.ContainerState{ + Terminated: &v1.ContainerStateTerminated{ + ExitCode: -1073741510, + }, + }, + }, + }, + }, + }, + wantJobFailureMessage: nil, + wantCountFailed: false, + wantAction: &ignore, + }, "FailJob rule matched for exit codes": { podFailurePolicy: &batch.PodFailurePolicy{ Rules: []batch.PodFailurePolicyRule{ diff --git a/test/integration/job/job_test.go b/test/integration/job/job_test.go index 78d821ba73c..496f77a529e 100644 --- a/test/integration/job/job_test.go +++ b/test/integration/job/job_test.go @@ -428,6 +428,59 @@ func TestJobPodFailurePolicy(t *testing.T) { Value: 0, }, }, + "pod status matching the configured FailJob rule on a negative exit code - needed for Windows support": { + job: batchv1.Job{ + Spec: batchv1.JobSpec{ + Template: v1.PodTemplateSpec{ + Spec: v1.PodSpec{ + Containers: []v1.Container{ + { + Name: "main-container", + Image: "foo", + ImagePullPolicy: v1.PullIfNotPresent, + TerminationMessagePolicy: v1.TerminationMessageFallbackToLogsOnError, + }, + }, + }, + }, + PodFailurePolicy: &batchv1.PodFailurePolicy{ + Rules: []batchv1.PodFailurePolicyRule{ + { + Action: batchv1.PodFailurePolicyActionFailJob, + OnExitCodes: &batchv1.PodFailurePolicyOnExitCodesRequirement{ + Operator: batchv1.PodFailurePolicyOnExitCodesOpIn, + Values: []int32{-1073741510, 137}, + }, + }, + }, + }, + }, + }, + podStatus: v1.PodStatus{ + Phase: v1.PodFailed, + ContainerStatuses: []v1.ContainerStatus{ + { + Name: "main-container", + State: v1.ContainerState{ + Terminated: &v1.ContainerStateTerminated{ + ExitCode: -1073741510, + }, + }, + }, + }, + }, + wantActive: 0, + wantFailed: 1, + wantJobConditionType: batchv1.JobFailed, + wantJobFinishedMetric: metricLabelsWithValue{ + Labels: []string{"NonIndexed", "failed", "PodFailurePolicy"}, + Value: 1, + }, + wantPodFailuresHandledByPolicyRuleMetric: &metricLabelsWithValue{ + Labels: []string{"FailJob"}, + Value: 1, + }, + }, } closeFn, restConfig, clientSet, ns := setup(t, "pod-failure-policy")