From d115ffe82ad480fffda3ebf8343954b18e74de3f Mon Sep 17 00:00:00 2001 From: Irvin Lim Date: Fri, 13 Sep 2024 22:32:50 +0800 Subject: [PATCH] chore: Upgrade Go version to 1.23 (#136) --- .golangci.yml | 7 +- Makefile | 6 +- apis/config/v1alpha1/zz_generated.deepcopy.go | 1 - .../v1alpha1/zz_generated.deepcopy.go | 4 +- .../execution/controller/cluster_role.yaml | 1 - .../rbac/execution/webhook/cluster_role.yaml | 1 - .../common/webhook/execution/manifests.yaml | 26 +- .../bases/execution.furiko.io_jobconfigs.yaml | 275 ++++++++++++--- .../crd/bases/execution.furiko.io_jobs.yaml | 319 ++++++++++++++---- go.mod | 2 +- go.sum | 5 + .../completion/completer_list_jobconfigs.go | 2 - pkg/cli/completion/completer_list_jobs.go | 2 - .../completion/completer_list_namespaces.go | 2 - pkg/cli/printer/printer_test.go | 2 - pkg/core/options/default_test.go | 2 - pkg/core/options/hash_test.go | 2 - pkg/core/options/options_test.go | 2 - pkg/core/options/parameters_test.go | 2 - pkg/core/options/substitution_test.go | 4 - pkg/core/options/util_test.go | 1 - pkg/core/options/validation_test.go | 2 - pkg/core/tzutils/parse_test.go | 1 - pkg/core/validation/generic_test.go | 1 - .../croncontroller/reconciler_test.go | 1 - .../controllers/croncontroller/util_test.go | 2 - pkg/execution/mutation/mutation_test.go | 5 - pkg/execution/mutation/patcher_jobs_test.go | 1 - .../taskexecutor/podtaskexecutor/pod_task.go | 1 - .../podtaskexecutor/pod_task_test.go | 6 - .../podtaskexecutor/substitution_test.go | 1 - .../taskexecutor/podtaskexecutor/util.go | 1 - .../util/cronschedule/schedule_test.go | 2 - pkg/execution/util/job/active_test.go | 1 - pkg/execution/util/job/condition.go | 1 - pkg/execution/util/job/condition_test.go | 1 - pkg/execution/util/job/phase_test.go | 1 - pkg/execution/util/job/task_status_test.go | 3 - pkg/execution/util/jobconfig/job_utils.go | 2 - pkg/execution/util/jobconfig/state_test.go | 1 - pkg/execution/validation/corev1_test.go | 1 - pkg/execution/validation/validation_test.go | 4 - .../clientset/versioned/fake/register.go | 14 +- .../clientset/versioned/scheme/register.go | 14 +- pkg/runtime/configloader/manager_test.go | 3 - pkg/runtime/controllermanager/controller.go | 2 - pkg/runtime/controllermanager/store.go | 1 - pkg/runtime/controllermanager/webhook.go | 1 - pkg/runtime/httphandler/webhooks.go | 3 +- pkg/runtime/leaderelection/config_test.go | 1 - pkg/runtime/testing/testing_test.go | 2 - pkg/utils/ktime/time_test.go | 2 - pkg/utils/meta/annotations_test.go | 1 - pkg/utils/strings/strings_test.go | 1 - 54 files changed, 533 insertions(+), 219 deletions(-) diff --git a/.golangci.yml b/.golangci.yml index bd5b7a5..aed3404 100644 --- a/.golangci.yml +++ b/.golangci.yml @@ -7,6 +7,11 @@ linters-settings: disabled-checks: - singleCaseSwitch - ifElseChain + gosec: + excludes: + # G115: Potential integer overflow when converting between integer types + # Excluded due to false positives. + - G115 issues: exclude-rules: @@ -32,9 +37,9 @@ linters: enable: - asciicheck - bodyclose + - copyloopvar - dupl - errcheck - - exportloopref - gocognit - goconst - gocritic diff --git a/Makefile b/Makefile index b2ea0fd..37ca0c2 100644 --- a/Makefile +++ b/Makefile @@ -76,7 +76,7 @@ help: ## Display this help. ##@ Development .PHONY: generate -generate: generate-deepcopy generate-groups ## Generate Go code. +generate: generate-deepcopy generate-groups fmt ## Generate Go code. generate-deepcopy: controller-gen ## Generate code containing DeepCopy, DeepCopyInto, and DeepCopyObject method implementations. $(CONTROLLER_GEN) object:headerFile="$(LICENSE_HEADER_GO)" paths="./..." @@ -219,10 +219,10 @@ $(LOCALBIN): ## Ensure that the directory exists ## Tool Versions KUSTOMIZE_VERSION ?= v4.5.5 -CONTROLLER_TOOLS_VERSION ?= v0.8.0 +CONTROLLER_TOOLS_VERSION ?= v0.14.0 YQ_VERSION ?= v4.14.1 GOIMPORTS_REVISER_VERSION ?= 32c80678d5d73a50b6966f06b346de58b1d018f1 -GOLANGCI_LINT_VERSION ?= v1.55.2 +GOLANGCI_LINT_VERSION ?= v1.61.0 LICENSEHEADERCHECKER_VERSION ?= v1.3.0 GORELEASER_VERSION ?= v1.8.2 diff --git a/apis/config/v1alpha1/zz_generated.deepcopy.go b/apis/config/v1alpha1/zz_generated.deepcopy.go index e8f51f6..7646f7e 100644 --- a/apis/config/v1alpha1/zz_generated.deepcopy.go +++ b/apis/config/v1alpha1/zz_generated.deepcopy.go @@ -1,5 +1,4 @@ //go:build !ignore_autogenerated -// +build !ignore_autogenerated /* * Copyright 2022 The Furiko Authors. diff --git a/apis/execution/v1alpha1/zz_generated.deepcopy.go b/apis/execution/v1alpha1/zz_generated.deepcopy.go index 717c032..3f441b7 100644 --- a/apis/execution/v1alpha1/zz_generated.deepcopy.go +++ b/apis/execution/v1alpha1/zz_generated.deepcopy.go @@ -1,5 +1,4 @@ //go:build !ignore_autogenerated -// +build !ignore_autogenerated /* * Copyright 2022 The Furiko Authors. @@ -757,7 +756,8 @@ func (in *ParallelismSpec) DeepCopyInto(out *ParallelismSpec) { if val == nil { (*out)[key] = nil } else { - in, out := &val, &outVal + inVal := (*in)[key] + in, out := &inVal, &outVal *out = make([]string, len(*in)) copy(*out, *in) } diff --git a/config/common/rbac/execution/controller/cluster_role.yaml b/config/common/rbac/execution/controller/cluster_role.yaml index 9a675ec..cbd6147 100644 --- a/config/common/rbac/execution/controller/cluster_role.yaml +++ b/config/common/rbac/execution/controller/cluster_role.yaml @@ -2,7 +2,6 @@ apiVersion: rbac.authorization.k8s.io/v1 kind: ClusterRole metadata: - creationTimestamp: null name: controller-role rules: - apiGroups: diff --git a/config/common/rbac/execution/webhook/cluster_role.yaml b/config/common/rbac/execution/webhook/cluster_role.yaml index b49891f..27943aa 100644 --- a/config/common/rbac/execution/webhook/cluster_role.yaml +++ b/config/common/rbac/execution/webhook/cluster_role.yaml @@ -2,7 +2,6 @@ apiVersion: rbac.authorization.k8s.io/v1 kind: ClusterRole metadata: - creationTimestamp: null name: webhook-role rules: - apiGroups: diff --git a/config/common/webhook/execution/manifests.yaml b/config/common/webhook/execution/manifests.yaml index d583616..9ccb266 100644 --- a/config/common/webhook/execution/manifests.yaml +++ b/config/common/webhook/execution/manifests.yaml @@ -2,7 +2,6 @@ apiVersion: admissionregistration.k8s.io/v1 kind: MutatingWebhookConfiguration metadata: - creationTimestamp: null name: mutating-webhook-configuration webhooks: - admissionReviewVersions: @@ -11,9 +10,9 @@ webhooks: service: name: webhook-service namespace: system - path: /mutating/jobs.execution.furiko.io + path: /mutating/jobconfigs.execution.furiko.io failurePolicy: Fail - name: mutating.webhook.jobs.execution.furiko.io + name: mutating.webhook.jobconfigs.execution.furiko.io rules: - apiGroups: - execution.furiko.io @@ -23,7 +22,7 @@ webhooks: - CREATE - UPDATE resources: - - jobs + - jobconfigs sideEffects: None - admissionReviewVersions: - v1 @@ -31,9 +30,9 @@ webhooks: service: name: webhook-service namespace: system - path: /mutating/jobconfigs.execution.furiko.io + path: /mutating/jobs.execution.furiko.io failurePolicy: Fail - name: mutating.webhook.jobconfigs.execution.furiko.io + name: mutating.webhook.jobs.execution.furiko.io rules: - apiGroups: - execution.furiko.io @@ -43,13 +42,12 @@ webhooks: - CREATE - UPDATE resources: - - jobconfigs + - jobs sideEffects: None --- apiVersion: admissionregistration.k8s.io/v1 kind: ValidatingWebhookConfiguration metadata: - creationTimestamp: null name: validating-webhook-configuration webhooks: - admissionReviewVersions: @@ -58,9 +56,9 @@ webhooks: service: name: webhook-service namespace: system - path: /validating/jobs.execution.furiko.io + path: /validating/jobconfigs.execution.furiko.io failurePolicy: Fail - name: validation.webhook.jobs.execution.furiko.io + name: validation.webhook.jobconfigs.execution.furiko.io rules: - apiGroups: - execution.furiko.io @@ -70,7 +68,7 @@ webhooks: - CREATE - UPDATE resources: - - jobs + - jobconfigs sideEffects: None - admissionReviewVersions: - v1 @@ -78,9 +76,9 @@ webhooks: service: name: webhook-service namespace: system - path: /validating/jobconfigs.execution.furiko.io + path: /validating/jobs.execution.furiko.io failurePolicy: Fail - name: validation.webhook.jobconfigs.execution.furiko.io + name: validation.webhook.jobs.execution.furiko.io rules: - apiGroups: - execution.furiko.io @@ -90,5 +88,5 @@ webhooks: - CREATE - UPDATE resources: - - jobconfigs + - jobs sideEffects: None diff --git a/config/crd/bases/execution.furiko.io_jobconfigs.yaml b/config/crd/bases/execution.furiko.io_jobconfigs.yaml index d9c2498..3ca1890 100644 --- a/config/crd/bases/execution.furiko.io_jobconfigs.yaml +++ b/config/crd/bases/execution.furiko.io_jobconfigs.yaml @@ -3,8 +3,7 @@ apiVersion: apiextensions.k8s.io/v1 kind: CustomResourceDefinition metadata: annotations: - controller-gen.kubebuilder.io/version: v0.8.0 - creationTimestamp: null + controller-gen.kubebuilder.io/version: v0.14.0 name: jobconfigs.execution.furiko.io spec: group: execution.furiko.io @@ -46,13 +45,24 @@ spec: name: v1alpha1 schema: openAPIV3Schema: - description: JobConfig is the schema for a single job configuration. Multiple Job objects belong to a single JobConfig. + description: |- + JobConfig is the schema for a single job configuration. Multiple Job objects + belong to a single JobConfig. properties: apiVersion: - description: 'APIVersion defines the versioned schema of this representation of an object. Servers should convert recognized schemas to the latest internal value, and may reject unrecognized values. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources' + description: |- + APIVersion defines the versioned schema of this representation of an object. + Servers should convert recognized schemas to the latest internal value, and + may reject unrecognized values. + More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources type: string kind: - description: 'Kind is a string value representing the REST resource this object represents. Servers may infer this from the endpoint the client submits requests to. Cannot be updated. In CamelCase. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds' + description: |- + Kind is a string value representing the REST resource this object represents. + Servers may infer this from the endpoint the client submits requests to. + Cannot be updated. + In CamelCase. + More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds type: string metadata: type: object @@ -63,7 +73,12 @@ spec: description: Concurrency defines the behaviour of multiple concurrent Jobs. properties: maxConcurrency: - description: "Maximum number of Jobs that can be running concurrently for the same JobConfig. Cannot be specified if Policy is set to Allow. \n Defaults to 1." + description: |- + Maximum number of Jobs that can be running concurrently for the same + JobConfig. Cannot be specified if Policy is set to Allow. + + + Defaults to 1. format: int64 type: integer policy: @@ -73,7 +88,10 @@ spec: - policy type: object option: - description: Option is an optional field that defines how the JobConfig is parameterized. Each option defined here can subsequently be used in the Template via context variable substitution. + description: |- + Option is an optional field that defines how the JobConfig is parameterized. + Each option defined here can subsequently be used in the Template via context + variable substitution. properties: options: description: Options is a list of job options. @@ -87,13 +105,22 @@ spec: description: Default value, will be used to populate the option if not specified. type: boolean falseVal: - description: If Format is custom, will be substituted if value is false. Can also be an empty string. + description: |- + If Format is custom, will be substituted if value is false. + Can also be an empty string. type: string format: - description: "Determines how to format the value as string. Can be one of: TrueFalse, OneZero, YesNo, Custom \n Default: TrueFalse" + description: |- + Determines how to format the value as string. + Can be one of: TrueFalse, OneZero, YesNo, Custom + + + Default: TrueFalse type: string trueVal: - description: If Format is custom, will be substituted if value is true. Can also be an empty string. + description: |- + If Format is custom, will be substituted if value is true. + Can also be an empty string. type: string required: - default @@ -102,17 +129,31 @@ spec: description: Date adds additional configuration for OptionTypeDate. properties: format: - description: "Date format in moment.js format. If not specified, will use RFC3339 format by default. \n Date format reference: https://momentjs.com/docs/#/displaying/format/ \n Default:" + description: |- + Date format in moment.js format. If not specified, will use RFC3339 format by + default. + + + Date format reference: https://momentjs.com/docs/#/displaying/format/ + + + Default: type: string type: object label: - description: Label is an optional human-readable label for this option, which is purely used for display purposes. + description: |- + Label is an optional human-readable label for this option, which is purely + used for display purposes. type: string multi: description: Multi adds additional configuration for OptionTypeMulti. properties: allowCustom: - description: "Whether to allow custom values instead of just the list of allowed values. \n Default: false" + description: |- + Whether to allow custom values instead of just the list of allowed values. + + + Default: false type: boolean default: description: Default values, will be used to populate the option if not specified. @@ -132,16 +173,26 @@ spec: - values type: object name: - description: 'The name of the job option. Will be substituted as `${option.NAME}`. Must match the following regex: ^[a-zA-Z_0-9.-]+$' + description: |- + The name of the job option. Will be substituted as `${option.NAME}`. + Must match the following regex: ^[a-zA-Z_0-9.-]+$ type: string required: - description: "Required defines whether this field is required. \n Default: false" + description: |- + Required defines whether this field is required. + + + Default: false type: boolean select: description: Select adds additional configuration for OptionTypeSelect. properties: allowCustom: - description: "Whether to allow custom values instead of just the list of allowed values. \n Default: false" + description: |- + Whether to allow custom values instead of just the list of allowed values. + + + Default: false type: boolean default: description: Default value, will be used to populate the option if not specified. @@ -159,11 +210,17 @@ spec: description: Optional default value, will be used to populate the option if not specified. type: string trimSpaces: - description: "Whether to trim spaces before substitution. \n Default: false" + description: |- + Whether to trim spaces before substitution. + + + Default: false type: boolean type: object type: - description: 'The type of the job option. Can be one of: bool, string, select, multi, date' + description: |- + The type of the job option. + Can be one of: bool, string, select, multi, date type: string required: - name @@ -172,17 +229,23 @@ spec: type: array type: object schedule: - description: Schedule is an optional field that defines automatic scheduling of the JobConfig. + description: |- + Schedule is an optional field that defines automatic scheduling of the + JobConfig. properties: constraints: description: Specifies any constraints that should apply to this Schedule. properties: notAfter: - description: Specifies the latest possible time that is allowed to be scheduled. If set, the scheduler should not create schedules after this time. + description: |- + Specifies the latest possible time that is allowed to be scheduled. If set, + the scheduler should not create schedules after this time. format: date-time type: string notBefore: - description: Specifies the earliest possible time that is allowed to be scheduled. If set, the scheduler should not create schedules before this time. + description: |- + Specifies the earliest possible time that is allowed to be scheduled. If set, + the scheduler should not create schedules before this time. format: date-time type: string type: object @@ -190,22 +253,68 @@ spec: description: Specify a schedule using cron expressions. properties: expression: - description: "Cron expression to specify how the JobConfig will be periodically scheduled. Example: \"0 0/5 * * *\". \n Supports cron schedules with optional \"seconds\" and \"years\" fields, i.e. can parse between 5 to 7 tokens. \n More information: https://github.com/furiko-io/cronexpr" + description: |- + Cron expression to specify how the JobConfig will be periodically scheduled. + Example: "0 0/5 * * *". + + + Supports cron schedules with optional "seconds" and "years" fields, i.e. can + parse between 5 to 7 tokens. + + + More information: https://github.com/furiko-io/cronexpr type: string expressions: - description: "List of cron expressions to specify how the JobConfig will be periodically scheduled. \n Take for example a requirement to schedule a job every day at 3AM, 3:30AM and 4AM. There is no way to represent this with a single cron expression, but we could do so with two cron expressions: \"0/30 3 * * *\", and \"0 4 * * *\". \n Exactly one of Expression or Expressions must be specified. If two expressions fall on the same time, only one of them will take effect." + description: |- + List of cron expressions to specify how the JobConfig will be periodically scheduled. + + + Take for example a requirement to schedule a job every day at 3AM, 3:30AM and 4AM. + There is no way to represent this with a single cron expression, but we could do so + with two cron expressions: "0/30 3 * * *", and "0 4 * * *". + + + Exactly one of Expression or Expressions must be specified. + If two expressions fall on the same time, only one of them will take effect. items: type: string type: array timezone: - description: "Timezone to interpret the cron schedule in. For example, a cron schedule of \"0 10 * * *\" with a timezone of \"Asia/Singapore\" will be interpreted as running at 02:00:00 UTC time every day. \n Timezone must be one of the following: \n 1. A valid tz string (e.g. \"Asia/Singapore\", \"America/New_York\"). 2. A UTC offset with minutes (e.g. UTC-10:00). 3. A GMT offset with minutes (e.g. GMT+05:30). The meaning is the same as its UTC counterpart. \n This field merely is used for parsing the cron Expression, and has nothing to do with /etc/timezone inside the container (i.e. it will not set $TZ automatically). \n Defaults to the controller's default configured timezone." + description: |- + Timezone to interpret the cron schedule in. For example, a cron schedule of + "0 10 * * *" with a timezone of "Asia/Singapore" will be interpreted as + running at 02:00:00 UTC time every day. + + + Timezone must be one of the following: + + + 1. A valid tz string (e.g. "Asia/Singapore", "America/New_York"). + 2. A UTC offset with minutes (e.g. UTC-10:00). + 3. A GMT offset with minutes (e.g. GMT+05:30). The meaning is the + same as its UTC counterpart. + + + This field merely is used for parsing the cron Expression, and has nothing to + do with /etc/timezone inside the container (i.e. it will not set $TZ + automatically). + + + Defaults to the controller's default configured timezone. type: string type: object disabled: description: If true, then automatic scheduling will be disabled for the JobConfig. type: boolean lastUpdated: - description: "Specifies the time that the schedule was last updated. This prevents accidental back-scheduling. \n For example, if a JobConfig that was previously disabled from automatic scheduling is now enabled, we do not want to perform back-scheduling for schedules after LastScheduled prior to updating of the JobConfig." + description: |- + Specifies the time that the schedule was last updated. This prevents + accidental back-scheduling. + + + For example, if a JobConfig that was previously disabled from automatic + scheduling is now enabled, we do not want to perform back-scheduling for + schedules after LastScheduled prior to updating of the JobConfig. format: date-time type: string type: object @@ -213,31 +322,68 @@ spec: description: Template for creating the Job. properties: metadata: - description: 'Standard object''s metadata that will be added to Job. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#metadata' + description: |- + Standard object's metadata that will be added to Job. More info: + https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#metadata type: object x-kubernetes-preserve-unknown-fields: true spec: description: Specification of the desired behavior of the job. properties: forbidTaskForceDeletion: - description: "Defines whether tasks are allowed to be force deleted or not. If the node is unresponsive, it may be possible that the task cannot be killed by normal graceful deletion. The controller may choose to force delete the task, which would ignore the final state of the task since the node is unable to return whether the task is actually still alive. \n If not set to true, there may be some cases when there may actually be two concurrently running tasks when even when ConcurrencyPolicyForbid. Setting this to true would prevent this from happening, but the Job may remain stuck indefinitely until the node recovers." + description: |- + Defines whether tasks are allowed to be force deleted or not. If the node is + unresponsive, it may be possible that the task cannot be killed by normal + graceful deletion. The controller may choose to force delete the task, which + would ignore the final state of the task since the node is unable to return + whether the task is actually still alive. + + + If not set to true, there may be some cases when there may actually be two + concurrently running tasks when even when ConcurrencyPolicyForbid. Setting + this to true would prevent this from happening, but the Job may remain stuck + indefinitely until the node recovers. type: boolean maxAttempts: - description: "Specifies maximum number of attempts before the Job will terminate in failure. If defined, the controller will wait retryDelaySeconds before creating the next task. Once maxAttempts is reached, the Job terminates in RetryLimitExceeded. \n If parallelism is also defined, this corresponds to the maximum attempts for each parallel task. That is, if there are 5 parallel task to be run at a time, with maxAttempts of 3, the Job may create up to a maximum of 15 tasks if each has failed. \n Value must be a positive integer. Defaults to 1." + description: |- + Specifies maximum number of attempts before the Job will terminate in + failure. If defined, the controller will wait retryDelaySeconds before + creating the next task. Once maxAttempts is reached, the Job terminates in + RetryLimitExceeded. + + + If parallelism is also defined, this corresponds to the maximum attempts for + each parallel task. That is, if there are 5 parallel task to be run at a + time, with maxAttempts of 3, the Job may create up to a maximum of 15 tasks + if each has failed. + + + Value must be a positive integer. Defaults to 1. format: int64 type: integer parallelism: - description: Describes how to run multiple tasks in parallel for the Job. If not set, then there will be at most a single task running at any time. + description: |- + Describes how to run multiple tasks in parallel for the Job. If not set, then + there will be at most a single task running at any time. properties: completionStrategy: - description: Defines when the Job will complete when there are multiple tasks running in parallel. For example, if using the AllSuccessful strategy, the Job will only terminate once all parallel tasks have terminated successfully, or once any task has exhausted its maxAttempts limit. + description: |- + Defines when the Job will complete when there are multiple tasks running in + parallel. For example, if using the AllSuccessful strategy, the Job will only + terminate once all parallel tasks have terminated successfully, or once any + task has exhausted its maxAttempts limit. type: string withCount: - description: Specifies an exact number of tasks to be run in parallel. The index number can be retrieved via the "${task.index_num}" context variable. + description: |- + Specifies an exact number of tasks to be run in parallel. The index number + can be retrieved via the "${task.index_num}" context variable. format: int64 type: integer withKeys: - description: Specifies a list of keys corresponding to each task that will be run in parallel. The index key can be retrieved via the "${task.index_key}" context variable. + description: |- + Specifies a list of keys corresponding to each task that will be run in + parallel. The index key can be retrieved via the "${task.index_key}" context + variable. items: type: string type: array @@ -247,16 +393,37 @@ spec: items: type: string type: array - description: 'Specifies a matrix of key-value pairs, with each key mapped to a list of possible values, such that tasks will be started for each combination of key-value pairs. The matrix values can be retrieved via context variables in the following format: "${task.index_matrix.}".' + description: |- + Specifies a matrix of key-value pairs, with each key mapped to a list of + possible values, such that tasks will be started for each combination of + key-value pairs. The matrix values can be retrieved via context variables in + the following format: "${task.index_matrix.}". type: object x-kubernetes-map-type: atomic type: object retryDelaySeconds: - description: "Optional duration in seconds to wait between retries. If left empty or zero, it means no delay (i.e. retry immediately). \n If parallelism is also defined, the retry delay is from the time of the last failed task with the same index. That is, if there are two parallel tasks - index 0 and index 1 - which failed at t=0 and t=15, with retryDelaySeconds of 30, the controller will only create the next attempts at t=30 and t=45 respectively. \n Value must be a non-negative integer." + description: |- + Optional duration in seconds to wait between retries. If left empty or zero, + it means no delay (i.e. retry immediately). + + + If parallelism is also defined, the retry delay is from the time of the last + failed task with the same index. That is, if there are two parallel tasks - + index 0 and index 1 - which failed at t=0 and t=15, with retryDelaySeconds of + 30, the controller will only create the next attempts at t=30 and t=45 + respectively. + + + Value must be a non-negative integer. format: int64 type: integer taskPendingTimeoutSeconds: - description: Optional duration in seconds to wait before terminating the task if it is still pending. This field is useful to prevent jobs from being stuck forever if the Job has a deadline to start running by. If not set, it will be set to the DefaultPendingTimeoutSeconds configuration value in the controller. To disable pending timeout, set this to 0. + description: |- + Optional duration in seconds to wait before terminating the task if it is + still pending. This field is useful to prevent jobs from being stuck forever + if the Job has a deadline to start running by. If not set, it will be set to + the DefaultPendingTimeoutSeconds configuration value in the controller. To + disable pending timeout, set this to 0. format: int64 type: integer taskTemplate: @@ -266,11 +433,19 @@ spec: description: Describes how to create tasks as Pods. properties: metadata: - description: 'Standard object''s metadata that will be added to Pod. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#metadata' + description: |- + Standard object's metadata that will be added to Pod. More info: + https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#metadata type: object x-kubernetes-preserve-unknown-fields: true spec: - description: "Specification of the desired behavior of the pod. API docs: https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.23/#podspec-v1-core \n Supports context variable substitution in the following fields for containers and initContainers: image, command, args, env.value" + description: |- + Specification of the desired behavior of the pod. API docs: + https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.23/#podspec-v1-core + + + Supports context variable substitution in the following fields for containers + and initContainers: image, command, args, env.value type: object x-kubernetes-map-type: atomic x-kubernetes-preserve-unknown-fields: true @@ -290,7 +465,10 @@ spec: description: JobConfigStatus defines the observed state of the JobConfig. properties: active: - description: Total number of active jobs created for the JobConfig. An active job is one that is waiting to create a task, waiting for a task to be running, or has a running task. + description: |- + Total number of active jobs created for the JobConfig. An active job is one + that is waiting to create a task, waiting for a task to be running, or has a + running task. format: int64 type: integer activeJobs: @@ -322,15 +500,24 @@ spec: type: object type: array lastExecuted: - description: The last timestamp that the job config was executed, including both scheduled and adhoc executions. + description: |- + The last timestamp that the job config was executed, including both scheduled + and adhoc executions. format: date-time type: string lastScheduled: - description: The last known schedule time for this job config, used to persist state during controller downtime. If the controller was down for a short period of time, any schedules that were missed during the downtime will be back-scheduled, subject to the number of schedules missed since LastScheduled. + description: |- + The last known schedule time for this job config, used to persist state + during controller downtime. If the controller was down for a short period of + time, any schedules that were missed during the downtime will be + back-scheduled, subject to the number of schedules missed since + LastScheduled. format: date-time type: string queued: - description: Total number of Jobs queued for the JobConfig. A job that is queued is one that is not yet started. + description: |- + Total number of Jobs queued for the JobConfig. A job that is queued is one + that is not yet started. format: int64 type: integer queuedJobs: @@ -373,9 +560,3 @@ spec: subresources: status: {} preserveUnknownFields: false -status: - acceptedNames: - kind: "" - plural: "" - conditions: [] - storedVersions: [] diff --git a/config/crd/bases/execution.furiko.io_jobs.yaml b/config/crd/bases/execution.furiko.io_jobs.yaml index 677163d..f32dacc 100644 --- a/config/crd/bases/execution.furiko.io_jobs.yaml +++ b/config/crd/bases/execution.furiko.io_jobs.yaml @@ -3,8 +3,7 @@ apiVersion: apiextensions.k8s.io/v1 kind: CustomResourceDefinition metadata: annotations: - controller-gen.kubebuilder.io/version: v0.8.0 - creationTimestamp: null + controller-gen.kubebuilder.io/version: v0.14.0 name: jobs.execution.furiko.io spec: group: execution.furiko.io @@ -40,13 +39,24 @@ spec: name: v1alpha1 schema: openAPIV3Schema: - description: Job is the schema for a single job execution, which may consist of multiple tasks. + description: |- + Job is the schema for a single job execution, which may consist of multiple + tasks. properties: apiVersion: - description: 'APIVersion defines the versioned schema of this representation of an object. Servers should convert recognized schemas to the latest internal value, and may reject unrecognized values. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources' + description: |- + APIVersion defines the versioned schema of this representation of an object. + Servers should convert recognized schemas to the latest internal value, and + may reject unrecognized values. + More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources type: string kind: - description: 'Kind is a string value representing the REST resource this object represents. Servers may infer this from the endpoint the client submits requests to. Cannot be updated. In CamelCase. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds' + description: |- + Kind is a string value representing the REST resource this object represents. + Servers may infer this from the endpoint the client submits requests to. + Cannot be updated. + In CamelCase. + More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds type: string metadata: type: object @@ -54,23 +64,64 @@ spec: description: JobSpec defines the desired state of a Job. properties: configName: - description: "ConfigName allows specifying the name of the JobConfig to create the Job from. The JobConfig must be in the same namespace as the Job. \n It is provided as a write-only input field for convenience, and will override the template, labels and annotations from the JobConfig's template. \n This field will never be returned from the API. To look up the parent JobConfig, use ownerReferences." + description: |- + ConfigName allows specifying the name of the JobConfig to create the Job + from. The JobConfig must be in the same namespace as the Job. + + + It is provided as a write-only input field for convenience, and will override + the template, labels and annotations from the JobConfig's template. + + + This field will never be returned from the API. To look up the parent + JobConfig, use ownerReferences. type: string killTimestamp: - description: Specifies the time to start killing the job. When the time passes this timestamp, the controller will start attempting to kill all tasks. + description: |- + Specifies the time to start killing the job. When the time passes this + timestamp, the controller will start attempting to kill all tasks. format: date-time type: string optionValues: - description: "Specifies key-values pairs of values for Options, in JSON or YAML format. \n Example specification: \n spec: optionValues: |- myStringOption: \"value\" myBoolOption: true mySelectOption: - option1 - option3 \n Each entry in the optionValues struct should consist of the option's name, and the value could be an arbitrary type that corresponds to the option's type itself. Each option value specified will be evaluated to a string based on the JobConfig's OptionsSpec and added to Substitutions. If the key also exists in Substitutions, that one takes priority. \n Cannot be updated after creation." + description: |- + Specifies key-values pairs of values for Options, in JSON or YAML format. + + + Example specification: + + + spec: + optionValues: |- + myStringOption: "value" + myBoolOption: true + mySelectOption: + - option1 + - option3 + + + Each entry in the optionValues struct should consist of the option's name, + and the value could be an arbitrary type that corresponds to the option's + type itself. Each option value specified will be evaluated to a string based + on the JobConfig's OptionsSpec and added to Substitutions. If the key also + exists in Substitutions, that one takes priority. + + + Cannot be updated after creation. type: string startPolicy: - description: Specifies optional start policy for a Job, which specifies certain conditions which have to be met before a Job is started. + description: |- + Specifies optional start policy for a Job, which specifies certain conditions + which have to be met before a Job is started. properties: concurrencyPolicy: - description: Specifies the behaviour when there are other concurrent jobs for the JobConfig. + description: |- + Specifies the behaviour when there are other concurrent jobs for the + JobConfig. type: string startAfter: - description: Specifies the earliest time that the Job can be started after. Can be specified together with other fields. + description: |- + Specifies the earliest time that the Job can be started after. Can be + specified together with other fields. format: date-time type: string required: @@ -79,30 +130,77 @@ spec: substitutions: additionalProperties: type: string - description: "Defines key-value pairs of context variables to be substituted into the TaskTemplate. Each entry should consist of the full context variable name (i.e. `ctx.name`), and the values must be a string. Substitutions defined here take highest precedence over both predefined context variables and evaluated OptionValues. \n Most users should be using OptionValues to specify custom Job Option values for running the Job instead of using Subsitutions directly. \n Cannot be updated after creation." + description: |- + Defines key-value pairs of context variables to be substituted into the + TaskTemplate. Each entry should consist of the full context variable name + (i.e. `ctx.name`), and the values must be a string. Substitutions defined + here take highest precedence over both predefined context variables and + evaluated OptionValues. + + + Most users should be using OptionValues to specify custom Job Option values + for running the Job instead of using Subsitutions directly. + + + Cannot be updated after creation. type: object template: description: Template specifies how to create the Job. properties: forbidTaskForceDeletion: - description: "Defines whether tasks are allowed to be force deleted or not. If the node is unresponsive, it may be possible that the task cannot be killed by normal graceful deletion. The controller may choose to force delete the task, which would ignore the final state of the task since the node is unable to return whether the task is actually still alive. \n If not set to true, there may be some cases when there may actually be two concurrently running tasks when even when ConcurrencyPolicyForbid. Setting this to true would prevent this from happening, but the Job may remain stuck indefinitely until the node recovers." + description: |- + Defines whether tasks are allowed to be force deleted or not. If the node is + unresponsive, it may be possible that the task cannot be killed by normal + graceful deletion. The controller may choose to force delete the task, which + would ignore the final state of the task since the node is unable to return + whether the task is actually still alive. + + + If not set to true, there may be some cases when there may actually be two + concurrently running tasks when even when ConcurrencyPolicyForbid. Setting + this to true would prevent this from happening, but the Job may remain stuck + indefinitely until the node recovers. type: boolean maxAttempts: - description: "Specifies maximum number of attempts before the Job will terminate in failure. If defined, the controller will wait retryDelaySeconds before creating the next task. Once maxAttempts is reached, the Job terminates in RetryLimitExceeded. \n If parallelism is also defined, this corresponds to the maximum attempts for each parallel task. That is, if there are 5 parallel task to be run at a time, with maxAttempts of 3, the Job may create up to a maximum of 15 tasks if each has failed. \n Value must be a positive integer. Defaults to 1." + description: |- + Specifies maximum number of attempts before the Job will terminate in + failure. If defined, the controller will wait retryDelaySeconds before + creating the next task. Once maxAttempts is reached, the Job terminates in + RetryLimitExceeded. + + + If parallelism is also defined, this corresponds to the maximum attempts for + each parallel task. That is, if there are 5 parallel task to be run at a + time, with maxAttempts of 3, the Job may create up to a maximum of 15 tasks + if each has failed. + + + Value must be a positive integer. Defaults to 1. format: int64 type: integer parallelism: - description: Describes how to run multiple tasks in parallel for the Job. If not set, then there will be at most a single task running at any time. + description: |- + Describes how to run multiple tasks in parallel for the Job. If not set, then + there will be at most a single task running at any time. properties: completionStrategy: - description: Defines when the Job will complete when there are multiple tasks running in parallel. For example, if using the AllSuccessful strategy, the Job will only terminate once all parallel tasks have terminated successfully, or once any task has exhausted its maxAttempts limit. + description: |- + Defines when the Job will complete when there are multiple tasks running in + parallel. For example, if using the AllSuccessful strategy, the Job will only + terminate once all parallel tasks have terminated successfully, or once any + task has exhausted its maxAttempts limit. type: string withCount: - description: Specifies an exact number of tasks to be run in parallel. The index number can be retrieved via the "${task.index_num}" context variable. + description: |- + Specifies an exact number of tasks to be run in parallel. The index number + can be retrieved via the "${task.index_num}" context variable. format: int64 type: integer withKeys: - description: Specifies a list of keys corresponding to each task that will be run in parallel. The index key can be retrieved via the "${task.index_key}" context variable. + description: |- + Specifies a list of keys corresponding to each task that will be run in + parallel. The index key can be retrieved via the "${task.index_key}" context + variable. items: type: string type: array @@ -112,16 +210,37 @@ spec: items: type: string type: array - description: 'Specifies a matrix of key-value pairs, with each key mapped to a list of possible values, such that tasks will be started for each combination of key-value pairs. The matrix values can be retrieved via context variables in the following format: "${task.index_matrix.}".' + description: |- + Specifies a matrix of key-value pairs, with each key mapped to a list of + possible values, such that tasks will be started for each combination of + key-value pairs. The matrix values can be retrieved via context variables in + the following format: "${task.index_matrix.}". type: object x-kubernetes-map-type: atomic type: object retryDelaySeconds: - description: "Optional duration in seconds to wait between retries. If left empty or zero, it means no delay (i.e. retry immediately). \n If parallelism is also defined, the retry delay is from the time of the last failed task with the same index. That is, if there are two parallel tasks - index 0 and index 1 - which failed at t=0 and t=15, with retryDelaySeconds of 30, the controller will only create the next attempts at t=30 and t=45 respectively. \n Value must be a non-negative integer." + description: |- + Optional duration in seconds to wait between retries. If left empty or zero, + it means no delay (i.e. retry immediately). + + + If parallelism is also defined, the retry delay is from the time of the last + failed task with the same index. That is, if there are two parallel tasks - + index 0 and index 1 - which failed at t=0 and t=15, with retryDelaySeconds of + 30, the controller will only create the next attempts at t=30 and t=45 + respectively. + + + Value must be a non-negative integer. format: int64 type: integer taskPendingTimeoutSeconds: - description: Optional duration in seconds to wait before terminating the task if it is still pending. This field is useful to prevent jobs from being stuck forever if the Job has a deadline to start running by. If not set, it will be set to the DefaultPendingTimeoutSeconds configuration value in the controller. To disable pending timeout, set this to 0. + description: |- + Optional duration in seconds to wait before terminating the task if it is + still pending. This field is useful to prevent jobs from being stuck forever + if the Job has a deadline to start running by. If not set, it will be set to + the DefaultPendingTimeoutSeconds configuration value in the controller. To + disable pending timeout, set this to 0. format: int64 type: integer taskTemplate: @@ -131,11 +250,19 @@ spec: description: Describes how to create tasks as Pods. properties: metadata: - description: 'Standard object''s metadata that will be added to Pod. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#metadata' + description: |- + Standard object's metadata that will be added to Pod. More info: + https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#metadata type: object x-kubernetes-preserve-unknown-fields: true spec: - description: "Specification of the desired behavior of the pod. API docs: https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.23/#podspec-v1-core \n Supports context variable substitution in the following fields for containers and initContainers: image, command, args, env.value" + description: |- + Specification of the desired behavior of the pod. API docs: + https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.23/#podspec-v1-core + + + Supports context variable substitution in the following fields for containers + and initContainers: image, command, args, env.value type: object x-kubernetes-map-type: atomic x-kubernetes-preserve-unknown-fields: true @@ -145,11 +272,19 @@ spec: - taskTemplate type: object ttlSecondsAfterFinished: - description: Specifies the maximum lifetime of a Job that is finished. If not set, it will be set to the DefaultTTLSecondsAfterFinished configuration value in the controller. + description: |- + Specifies the maximum lifetime of a Job that is finished. If not set, it will + be set to the DefaultTTLSecondsAfterFinished configuration value in the + controller. format: int64 type: integer type: - description: "Specifies the type of Job. Can be one of: Adhoc, Scheduled \n Default: Adhoc" + description: |- + Specifies the type of Job. + Can be one of: Adhoc, Scheduled + + + Default: Adhoc type: string type: object status: @@ -159,18 +294,24 @@ spec: description: Condition stores details about the Job's current condition. properties: finished: - description: Stores the status of the Job's finished state. If specified, it means that all tasks in the Job have terminated. + description: |- + Stores the status of the Job's finished state. If specified, it means that + all tasks in the Job have terminated. properties: finishTime: description: The time at which the Job was first marked as finished by the controller. format: date-time type: string latestCreationTimestamp: - description: The time at which the latest task was created by the controller. May be nil if no tasks were ever created. + description: |- + The time at which the latest task was created by the controller. May be nil + if no tasks were ever created. format: date-time type: string latestRunningTimestamp: - description: The time at which the latest task had started running. May be nil if no tasks had started running. + description: |- + The time at which the latest task had started running. May be nil if no tasks + had started running. format: date-time type: string message: @@ -187,7 +328,9 @@ spec: - result type: object queueing: - description: Stores the status of the Job's queueing condition. If specified, it means that the Job is currently not started and is queued. + description: |- + Stores the status of the Job's queueing condition. If specified, it means + that the Job is currently not started and is queued. properties: message: description: Optional descriptive message explaining the condition's last transition. @@ -197,7 +340,10 @@ spec: type: string type: object running: - description: Stores the status of the Job's running state. If specified, it means that all tasks in the Job have started running. If the Job is already complete, this status may be set of not all tasks are terminated. + description: |- + Stores the status of the Job's running state. If specified, it means that all + tasks in the Job have started running. If the Job is already complete, this + status may be set of not all tasks are terminated. properties: latestRunningTimestamp: description: The time at which the latest task had started running. @@ -216,7 +362,10 @@ spec: - latestTaskCreationTimestamp type: object waiting: - description: Stores the status of the Job's waiting condition. If specified, it means that the Job currently is waiting for at least one task to be created and start running. + description: |- + Stores the status of the Job's waiting condition. If specified, it means that + the Job currently is waiting for at least one task to be created and start + running. properties: message: description: Optional descriptive message explaining the condition's last transition. @@ -231,15 +380,24 @@ spec: format: int64 type: integer parallelStatus: - description: The current status for parallel execution of the job. May not be set if the job is not a parallel job. + description: |- + The current status for parallel execution of the job. + May not be set if the job is not a parallel job. properties: complete: - description: If true, the job is complete and currently in the process of waiting for all remaining tasks to be terminated. + description: |- + If true, the job is complete and currently in the process of waiting for all + remaining tasks to be terminated. type: boolean indexes: - description: The status for each parallel index. The size of the list should be exactly equal to the total parallelism factor, even if no tasks are created yet. + description: |- + The status for each parallel index. The size of the list should be exactly + equal to the total parallelism factor, even if no tasks are created yet. items: - description: ParallelIndexStatus stores the status for a single ParallelIndex in the Job. There should be at most one task running at a time for a single parallel index in the Job. + description: |- + ParallelIndexStatus stores the status for a single ParallelIndex in the Job. + There should be at most one task running at a time for a single parallel + index in the Job. properties: createdTasks: description: Total number of tasks created for this parallel index. @@ -252,16 +410,22 @@ spec: description: The parallel index. properties: indexKey: - description: If withKeys is used for parallelism, contains the index key of the job as a string. + description: |- + If withKeys is used for parallelism, contains the index key of the job as a + string. type: string indexNumber: - description: If withCount is used for parallelism, contains the index number of the job numbered from 0 to N-1. + description: |- + If withCount is used for parallelism, contains the index number of the job + numbered from 0 to N-1. format: int64 type: integer matrixValues: additionalProperties: type: string - description: If withMatrix is used for parallelism, contains key-value pairs of the job as strings. + description: |- + If withMatrix is used for parallelism, contains key-value pairs of the job as + strings. type: object x-kubernetes-map-type: atomic type: object @@ -279,7 +443,9 @@ spec: type: object type: array successful: - description: If complete, contains whether the job is successful according to the ParallelCompletionStrategy. + description: |- + If complete, contains whether the job is successful according to the + ParallelCompletionStrategy. type: boolean required: - complete @@ -293,23 +459,37 @@ spec: format: int64 type: integer startTime: - description: StartTime specifies the time that the Job was started by the controller. If nil, it means that the Job is Queued. Cannot be changed once set. + description: |- + StartTime specifies the time that the Job was started by the controller. If + nil, it means that the Job is Queued. Cannot be changed once set. format: date-time type: string state: - description: 'State stores the high-level state of the Job''s current condition. Must be one of: Queued, Waiting, Running, Finished.' + description: |- + State stores the high-level state of the Job's current condition. + Must be one of: Queued, Waiting, Running, Finished. type: string tasks: - description: Tasks contains a list of tasks created by the controller. The controller updates this field when it creates a task, which helps to guard against recreating tasks after they were deleted, and also stores necessary task data for reconciliation in case tasks are deleted. + description: |- + Tasks contains a list of tasks created by the controller. The controller + updates this field when it creates a task, which helps to guard against + recreating tasks after they were deleted, and also stores necessary task data + for reconciliation in case tasks are deleted. items: description: TaskRef stores information about a Job's owned task. properties: containerStates: - description: States of each container for the task. This field will be reconciled from the relevant task object, and is not guaranteed to be up-to-date. This field will persist the state of tasks beyond the lifetime of the task resources, even if they were deleted. + description: |- + States of each container for the task. This field will be reconciled from the + relevant task object, and is not guaranteed to be up-to-date. This field will + persist the state of tasks beyond the lifetime of the task resources, even if + they were deleted. items: properties: containerID: - description: Container ID of the container. May be empty if the container is not yet created. + description: |- + Container ID of the container. May be empty if the container is not yet + created. type: string exitCode: description: Exit status from the last termination of the container @@ -334,7 +514,21 @@ spec: format: date-time type: string deletedStatus: - description: "DeletedStatus, if set, specifies a placeholder Status of the task after it is reconciled as deleted. If the task is deleted, Status cannot be reconciled from the task any more, and instead uses information stored in DeletedStatus. In other words, this field acts as a tombstone marker, and is only used after the deletion of the task object is complete. \n While the task is in the process of being deleted (i.e. deletionTimestamp is set but object still exists), Status will still be reconciled from the actual task's status. \n If the task is already deleted and DeletedStatus is also not set, then the task's state will be marked as TaskDeletedFinalStateUnknown." + description: |- + DeletedStatus, if set, specifies a placeholder Status of the task after it is + reconciled as deleted. If the task is deleted, Status cannot be reconciled + from the task any more, and instead uses information stored in DeletedStatus. + In other words, this field acts as a tombstone marker, and is only used after + the deletion of the task object is complete. + + + While the task is in the process of being deleted (i.e. deletionTimestamp is + set but object still exists), Status will still be reconciled from the actual + task's status. + + + If the task is already deleted and DeletedStatus is also not set, then the + task's state will be marked as TaskDeletedFinalStateUnknown. properties: message: description: Descriptive message for the task's status. @@ -352,29 +546,39 @@ spec: - state type: object finishTimestamp: - description: Time that the task finished. Will always return a non-zero timestamp if task is finished. + description: |- + Time that the task finished. Will always return a non-zero timestamp if task + is finished. format: date-time type: string name: description: Name of the task. Assumes to share the same namespace as the Job. type: string nodeName: - description: Node name that the task was bound to. May be empty if task was never scheduled. + description: |- + Node name that the task was bound to. May be empty if task was never + scheduled. type: string parallelIndex: description: If the Job is a parallel job, then contains the parallel index of the task. properties: indexKey: - description: If withKeys is used for parallelism, contains the index key of the job as a string. + description: |- + If withKeys is used for parallelism, contains the index key of the job as a + string. type: string indexNumber: - description: If withCount is used for parallelism, contains the index number of the job numbered from 0 to N-1. + description: |- + If withCount is used for parallelism, contains the index number of the job + numbered from 0 to N-1. format: int64 type: integer matrixValues: additionalProperties: type: string - description: If withMatrix is used for parallelism, contains key-value pairs of the job as strings. + description: |- + If withMatrix is used for parallelism, contains key-value pairs of the job as + strings. type: object x-kubernetes-map-type: atomic type: object @@ -383,11 +587,16 @@ spec: format: int64 type: integer runningTimestamp: - description: Timestamp that the task transitioned to running. May be zero if the task was never observed as started running. + description: |- + Timestamp that the task transitioned to running. May be zero if the task was + never observed as started running. format: date-time type: string status: - description: Status of the task. This field will be reconciled from the relevant task object, may not be always up-to-date. This field will persist the state of tasks beyond the lifetime of the task resources, even if they are deleted. + description: |- + Status of the task. This field will be reconciled from the relevant task + object, may not be always up-to-date. This field will persist the state of + tasks beyond the lifetime of the task resources, even if they are deleted. properties: message: description: Descriptive message for the task's status. @@ -426,9 +635,3 @@ spec: subresources: status: {} preserveUnknownFields: false -status: - acceptedNames: - kind: "" - plural: "" - conditions: [] - storedVersions: [] diff --git a/go.mod b/go.mod index 24dced5..6b82b50 100644 --- a/go.mod +++ b/go.mod @@ -1,6 +1,6 @@ module github.com/furiko-io/furiko -go 1.18 +go 1.23 require ( github.com/AlecAivazis/survey/v2 v2.3.4 diff --git a/go.sum b/go.sum index 9cefd95..a90aaee 100644 --- a/go.sum +++ b/go.sum @@ -493,6 +493,7 @@ github.com/nleeper/goment v1.4.1 h1:n3+X/eEiuj+w6ki27L8pATfwAaXcaFUYgz+G/1zBde8= github.com/nleeper/goment v1.4.1/go.mod h1:zDl5bAyDhqxwQKAvkSXMRLOdCowrdZz53ofRJc4VhTo= github.com/nxadm/tail v1.4.4/go.mod h1:kenIhsEOeOJmVchQTgglprH7qJGnHDVpk1VPCcaMI8A= github.com/nxadm/tail v1.4.8 h1:nPr65rt6Y5JFSKQO7qToXr7pePgD6Gwiw05lkbyAQTE= +github.com/nxadm/tail v1.4.8/go.mod h1:+ncqLTQzXmGhMZNUePPaPqPvBxHAIsmXswZKocGu+AU= github.com/oklog/ulid v1.3.1/go.mod h1:CirwcVhetQ6Lv90oh/F+FBtV6XMibvdAFo93nm5qn4U= github.com/olekukonko/tablewriter v0.0.4/go.mod h1:zq6QwlOf5SlnkVbMSr5EoBv3636FWnp+qbPhuoO21uA= github.com/onsi/ginkgo v0.0.0-20170829012221-11459a886d9c/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE= @@ -500,10 +501,12 @@ github.com/onsi/ginkgo v1.6.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+W github.com/onsi/ginkgo v1.12.1/go.mod h1:zj2OWP4+oCPe1qIXoGWkgMRwljMUYCdkwsT2108oapk= github.com/onsi/ginkgo v1.14.0/go.mod h1:iSB4RoI2tjJc9BBv4NKIKWKya62Rps+oPG/Lv9klQyY= github.com/onsi/ginkgo v1.16.5 h1:8xi0RTUf59SOSfEtZMvwTvXYMzG4gV23XVHOZiXNtnE= +github.com/onsi/ginkgo v1.16.5/go.mod h1:+E8gABHa3K6zRBolWtd+ROzc/U5bkGt0FwiG042wbpU= github.com/onsi/gomega v0.0.0-20170829124025-dcabb60a477c/go.mod h1:C1qb7wdrVGGVU+Z6iS04AVkA3Q65CEZX59MT0QO5uiA= github.com/onsi/gomega v1.7.1/go.mod h1:XdKZgCCFLUoM/7CFJVPcG8C1xQ1AJ0vpAezJrB7JYyY= github.com/onsi/gomega v1.10.1/go.mod h1:iN09h71vgCQne3DLsj+A5owkum+a2tYe+TOCB1ybHNo= github.com/onsi/gomega v1.17.0 h1:9Luw4uT5HTjHTN8+aNcSThgH1vdXnmdJ8xIfZ4wyTRE= +github.com/onsi/gomega v1.17.0/go.mod h1:HnhC7FXeEQY45zxNK3PPoIUhzk/80Xly9PcubAlGdZY= github.com/opencontainers/go-digest v1.0.0 h1:apOUWs51W5PlhuyGyz9FCeeBIOUDA/6nW8Oi/yOhh5U= github.com/opencontainers/go-digest v1.0.0/go.mod h1:0JzlMkj0TRzQZfJkVvzbP0HBR3IKzErnv2BNG4W4MAM= github.com/opencontainers/image-spec v1.0.1/go.mod h1:BtxoFyWECRxE4U/7sNtV5W15zMzWCbyJoFRP3s7yZA0= @@ -679,6 +682,7 @@ go.uber.org/atomic v1.7.0 h1:ADUqmZGgLDDfbSL9ZmPxKTybcoEYHgpYfELNoN+7hsw= go.uber.org/atomic v1.7.0/go.mod h1:fEN4uk6kAWBTFdckzkM89CLk9XfWZrxpCo0nPH17wJc= go.uber.org/goleak v1.1.10/go.mod h1:8a7PlsEVH3e/a/GLqe5IIrQx6GzcnRmZEufDUTk4A7A= go.uber.org/goleak v1.1.12 h1:gZAh5/EyT/HQwlpkCy6wTpqfH9H8Lz8zbm3dZh+OyzA= +go.uber.org/goleak v1.1.12/go.mod h1:cwTWslyiVhfpKIDGSZEM2HlOvcqm+tG4zioyIeLoqMQ= go.uber.org/multierr v1.1.0/go.mod h1:wR5kodmAFQ0UK8QlbwjlSNy0Z68gJhDJUG5sjR94q/0= go.uber.org/multierr v1.6.0 h1:y6IPFStTAIT5Ytl7/XYmHvzXQ7S3g/IeZW9hyZ5thw4= go.uber.org/multierr v1.6.0/go.mod h1:cdWPpRnG4AhwMwsgIHip0KRBQjJy5kYEpYjJxpXp9iU= @@ -686,6 +690,7 @@ go.uber.org/zap v1.10.0/go.mod h1:vwi/ZaCAaUcBkycHslxD9B2zi4UTXhF60s6SWpuDF0Q= go.uber.org/zap v1.17.0/go.mod h1:MXVU+bhUf/A7Xi2HNOnopQOrmycQ5Ih87HtOu4q5SSo= go.uber.org/zap v1.19.0/go.mod h1:xg/QME4nWcxGxrpdeYfq7UvYrLh66cuVKdrbD1XF/NI= go.uber.org/zap v1.19.1 h1:ue41HOKd1vGURxrmeKIgELGb3jPW9DMUDGtsinblHwI= +go.uber.org/zap v1.19.1/go.mod h1:j3DNczoxDZroyBnOT1L/Q79cfUMGZxlv/9dzN7SM1rI= golang.org/x/crypto v0.0.0-20180904163835-0709b304e793/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= golang.org/x/crypto v0.0.0-20181029021203-45a5f77698d3/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= golang.org/x/crypto v0.0.0-20190211182817-74369b46fc67/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= diff --git a/pkg/cli/completion/completer_list_jobconfigs.go b/pkg/cli/completion/completer_list_jobconfigs.go index b79fe61..9491922 100644 --- a/pkg/cli/completion/completer_list_jobconfigs.go +++ b/pkg/cli/completion/completer_list_jobconfigs.go @@ -62,8 +62,6 @@ func (c *ListJobConfigsCompleter) Complete(ctx context.Context, ctrlContext cont }) for _, item := range lst.Items { - item := item - // Filter item. if c.Filter != nil && !c.Filter(&item) { continue diff --git a/pkg/cli/completion/completer_list_jobs.go b/pkg/cli/completion/completer_list_jobs.go index 50eea8f..1459637 100644 --- a/pkg/cli/completion/completer_list_jobs.go +++ b/pkg/cli/completion/completer_list_jobs.go @@ -64,8 +64,6 @@ func (c *ListJobsCompleter) Complete(ctx context.Context, ctrlContext controller }) for _, item := range lst.Items { - item := item - // Filter item. if c.Filter != nil && !c.Filter(&item) { continue diff --git a/pkg/cli/completion/completer_list_namespaces.go b/pkg/cli/completion/completer_list_namespaces.go index d132204..726d89e 100644 --- a/pkg/cli/completion/completer_list_namespaces.go +++ b/pkg/cli/completion/completer_list_namespaces.go @@ -60,8 +60,6 @@ func (c *ListNamespacesCompleter) Complete(ctx context.Context, ctrlContext cont }) for _, item := range lst.Items { - item := item - // Filter item. if c.Filter != nil && !c.Filter(&item) { continue diff --git a/pkg/cli/printer/printer_test.go b/pkg/cli/printer/printer_test.go index 1f7602c..1c173e7 100644 --- a/pkg/cli/printer/printer_test.go +++ b/pkg/cli/printer/printer_test.go @@ -200,7 +200,6 @@ func TestPrintObject(t *testing.T) { }, } for _, tt := range tests { - tt := tt t.Run(tt.name, func(t *testing.T) { out := &bytes.Buffer{} err := printer.PrintObject(tt.gvk, tt.output, out, tt.object) @@ -361,7 +360,6 @@ func TestPrintObjects(t *testing.T) { }, } for _, tt := range tests { - tt := tt t.Run(tt.name, func(t *testing.T) { out := &bytes.Buffer{} err := printer.PrintObjects(tt.gvk, tt.output, out, tt.objects) diff --git a/pkg/core/options/default_test.go b/pkg/core/options/default_test.go index e8766df..b1a7eea 100644 --- a/pkg/core/options/default_test.go +++ b/pkg/core/options/default_test.go @@ -286,7 +286,6 @@ func TestMakeDefaultOptions(t *testing.T) { }, } for _, tt := range tests { - tt := tt t.Run(tt.name, func(t *testing.T) { got, err := options.MakeDefaultOptions(tt.cfg) if (err != nil) != tt.wantErr { @@ -554,7 +553,6 @@ func TestEvaluateOptionDefault(t *testing.T) { }, } for _, tt := range tests { - tt := tt t.Run(tt.name, func(t *testing.T) { got, err := options.EvaluateOptionDefault(tt.option) if (err != nil) != tt.wantErr { diff --git a/pkg/core/options/hash_test.go b/pkg/core/options/hash_test.go index f9bd53c..5300c1e 100644 --- a/pkg/core/options/hash_test.go +++ b/pkg/core/options/hash_test.go @@ -121,7 +121,6 @@ func TestHashOptionsSpec(t *testing.T) { }, } for _, tt := range tests { - tt := tt t.Run(tt.name, func(t *testing.T) { got, err := options.HashOptionSpec(tt.spec) if (err != nil) != tt.wantErr { @@ -222,7 +221,6 @@ func TestHashOptionsSpec_Deterministic(t *testing.T) { const numIterations = 10 for _, tt := range tests { - tt := tt t.Run(tt.name, func(t *testing.T) { var hash string for i := 0; i < numIterations; i++ { diff --git a/pkg/core/options/options_test.go b/pkg/core/options/options_test.go index d17a62e..5d08678 100644 --- a/pkg/core/options/options_test.go +++ b/pkg/core/options/options_test.go @@ -792,7 +792,6 @@ func TestEvaluateOption(t *testing.T) { }, } for _, tt := range tests { - tt := tt t.Run(tt.name, func(t *testing.T) { // Validate the option first, as EvaluateOption assumes a valid option. if err := options.ValidateOption(tt.option, rootPath).ToAggregate(); err != nil { @@ -930,7 +929,6 @@ func TestEvaluateOptions(t *testing.T) { }, } for _, tt := range tests { - tt := tt t.Run(tt.name, func(t *testing.T) { got, errs := options.EvaluateOptions(tt.args.options, tt.args.cfg, rootPath) if (errs.ToAggregate() != nil) != tt.wantErr { diff --git a/pkg/core/options/parameters_test.go b/pkg/core/options/parameters_test.go index 48af4c3..fe438a7 100644 --- a/pkg/core/options/parameters_test.go +++ b/pkg/core/options/parameters_test.go @@ -64,7 +64,6 @@ func TestFilterParametersWithPrefix(t *testing.T) { }, } for _, tt := range tests { - tt := tt t.Run(tt.name, func(t *testing.T) { if got := options.FilterParametersWithPrefix(tt.args.parameters, tt.args.prefix); !reflect.DeepEqual(got, tt.want) { t.Errorf("FilterParametersWithPrefix() = %v, want %v", got, tt.want) @@ -130,7 +129,6 @@ func TestFilterParametersWithPrefixes(t *testing.T) { }, } for _, tt := range tests { - tt := tt t.Run(tt.name, func(t *testing.T) { got := options.FilterParametersWithPrefixes(tt.args.parameters, tt.args.prefixes...) if !reflect.DeepEqual(got, tt.want) { diff --git a/pkg/core/options/substitution_test.go b/pkg/core/options/substitution_test.go index 2f17dae..d33ca01 100644 --- a/pkg/core/options/substitution_test.go +++ b/pkg/core/options/substitution_test.go @@ -97,7 +97,6 @@ func TestSubstituteVariables(t *testing.T) { }, } for _, tt := range tests { - tt := tt t.Run(tt.name, func(t *testing.T) { if got := options.SubstituteVariables(tt.args.target, tt.args.submap); got != tt.want { t.Errorf("SubstituteVariables() = %v, want %v", got, tt.want) @@ -158,7 +157,6 @@ func TestSubstituteEmptyStringForPrefixes(t *testing.T) { }, } for _, tt := range tests { - tt := tt t.Run(tt.name, func(t *testing.T) { if got := options.SubstituteEmptyStringForPrefixes(tt.args.target, tt.args.prefixes); got != tt.want { t.Errorf("SubstituteEmptyStringForPrefixes() = %v, want %v", got, tt.want) @@ -233,7 +231,6 @@ func TestSubstituteVariableMaps(t *testing.T) { }, } for _, tt := range tests { - tt := tt t.Run(tt.name, func(t *testing.T) { got := options.SubstituteVariableMaps(tt.args.target, tt.args.submaps, tt.args.prefixes) if got != tt.want { @@ -286,7 +283,6 @@ func TestMergeSubstitutions(t *testing.T) { }, } for _, tt := range tests { - tt := tt t.Run(tt.name, func(t *testing.T) { if got := options.MergeSubstitutions(tt.paramMaps...); !reflect.DeepEqual(got, tt.want) { t.Errorf("MergeParameters() = %v, want %v", got, tt.want) diff --git a/pkg/core/options/util_test.go b/pkg/core/options/util_test.go index de51a9d..1050161 100644 --- a/pkg/core/options/util_test.go +++ b/pkg/core/options/util_test.go @@ -65,7 +65,6 @@ func TestZeroForNonConfig(t *testing.T) { }, } for _, tt := range tests { - tt := tt t.Run(tt.name, func(t *testing.T) { if got := options.ZeroForNonConfig(tt.option); !reflect.DeepEqual(got, tt.want) { t.Errorf("ZeroForNonConfig() = %v, want %v", got, tt.want) diff --git a/pkg/core/options/validation_test.go b/pkg/core/options/validation_test.go index 8c5fb7f..c85a219 100644 --- a/pkg/core/options/validation_test.go +++ b/pkg/core/options/validation_test.go @@ -61,7 +61,6 @@ func TestValidateOptionSpec(t *testing.T) { }, } for _, tt := range tests { - tt := tt t.Run(tt.name, func(t *testing.T) { err := options.ValidateOptionSpec(tt.spec, rootPath).ToAggregate() if (err != nil) != tt.wantErr { @@ -470,7 +469,6 @@ func TestValidateJobOption(t *testing.T) { }, } for _, tt := range tests { - tt := tt t.Run(tt.name, func(t *testing.T) { err := options.ValidateOption(tt.option, rootPath).ToAggregate() if (err != nil) != tt.wantErr { diff --git a/pkg/core/tzutils/parse_test.go b/pkg/core/tzutils/parse_test.go index c56164f..91feaad 100644 --- a/pkg/core/tzutils/parse_test.go +++ b/pkg/core/tzutils/parse_test.go @@ -169,7 +169,6 @@ func TestParseTimezone(t *testing.T) { // nolint: gocognit }, } for _, tt := range tests { - tt := tt t.Run(tt.name, func(t *testing.T) { loc, err := ParseTimezone(tt.val) if (err != nil) != tt.wantErr { diff --git a/pkg/core/validation/generic_test.go b/pkg/core/validation/generic_test.go index 8bd6c51..4f24a52 100644 --- a/pkg/core/validation/generic_test.go +++ b/pkg/core/validation/generic_test.go @@ -47,7 +47,6 @@ func TestToInternalErrorList(t *testing.T) { }, } for _, tt := range tests { - tt := tt t.Run(tt.name, func(t *testing.T) { got := ToInternalErrorList(fldPath, tt.err) if !cmp.Equal(got, tt.want, cmpopts.EquateEmpty()) { diff --git a/pkg/execution/controllers/croncontroller/reconciler_test.go b/pkg/execution/controllers/croncontroller/reconciler_test.go index cf005d8..c5d6013 100644 --- a/pkg/execution/controllers/croncontroller/reconciler_test.go +++ b/pkg/execution/controllers/croncontroller/reconciler_test.go @@ -243,7 +243,6 @@ func TestReconciler(t *testing.T) { }, } for _, tt := range tests { - tt := tt t.Run(tt.name, func(t *testing.T) { ctx, cancel := context.WithTimeout(context.Background(), time.Second*10) defer cancel() diff --git a/pkg/execution/controllers/croncontroller/util_test.go b/pkg/execution/controllers/croncontroller/util_test.go index 9b80969..554ea72 100644 --- a/pkg/execution/controllers/croncontroller/util_test.go +++ b/pkg/execution/controllers/croncontroller/util_test.go @@ -49,7 +49,6 @@ func TestJobConfigKeyFunc(t *testing.T) { }, } for _, tt := range tests { - tt := tt t.Run(tt.name, func(t *testing.T) { jobConfig := &execution.JobConfig{ ObjectMeta: metav1.ObjectMeta{ @@ -100,7 +99,6 @@ func TestSplitJobConfigKey(t *testing.T) { }, } for _, tt := range tests { - tt := tt t.Run(tt.name, func(t *testing.T) { gotName, gotTS, err := croncontroller.SplitJobConfigKeyName(tt.key) if err != nil { diff --git a/pkg/execution/mutation/mutation_test.go b/pkg/execution/mutation/mutation_test.go index 6f725d8..8922169 100644 --- a/pkg/execution/mutation/mutation_test.go +++ b/pkg/execution/mutation/mutation_test.go @@ -326,7 +326,6 @@ func TestMutator_MutateJobConfig(t *testing.T) { }, } for _, tt := range tests { - tt := tt t.Run(tt.name, func(t *testing.T) { mutator := setup(t, tt.cfgs, nil) newRjc := tt.rjc.DeepCopy() @@ -404,7 +403,6 @@ func TestMutator_MutateCreateJobConfig(t *testing.T) { }, } for _, tt := range tests { - tt := tt t.Run(tt.name, func(t *testing.T) { mutator := mutation.NewMutator(mock.NewContext()) if tt.setup != nil { @@ -632,7 +630,6 @@ func TestMutator_MutateUpdateJobConfig(t *testing.T) { }, } for _, tt := range tests { - tt := tt t.Run(tt.name, func(t *testing.T) { mutator := mutation.NewMutator(mock.NewContext()) if tt.setup != nil { @@ -716,7 +713,6 @@ func TestMutator_MutateJob(t *testing.T) { }, } for _, tt := range tests { - tt := tt t.Run(tt.name, func(t *testing.T) { mutator := setup(t, tt.cfgs, nil) newRj := tt.rj.DeepCopy() @@ -1231,7 +1227,6 @@ func TestMutator_MutateCreateJob(t *testing.T) { }, } for _, tt := range tests { - tt := tt t.Run(tt.name, func(t *testing.T) { mutator := setup(t, tt.cfgs, tt.rjcs) if tt.setup != nil { diff --git a/pkg/execution/mutation/patcher_jobs_test.go b/pkg/execution/mutation/patcher_jobs_test.go index 6a0c44f..6e4f72e 100644 --- a/pkg/execution/mutation/patcher_jobs_test.go +++ b/pkg/execution/mutation/patcher_jobs_test.go @@ -98,7 +98,6 @@ func TestNewJobPatcher(t *testing.T) { }, } for _, tt := range tests { - tt := tt t.Run(tt.name, func(t *testing.T) { ctrlContext := setupContext(t, nil, []*v1alpha1.JobConfig{ { diff --git a/pkg/execution/taskexecutor/podtaskexecutor/pod_task.go b/pkg/execution/taskexecutor/podtaskexecutor/pod_task.go index 88914f8..b1cf464 100644 --- a/pkg/execution/taskexecutor/podtaskexecutor/pod_task.go +++ b/pkg/execution/taskexecutor/podtaskexecutor/pod_task.go @@ -196,7 +196,6 @@ func (p *PodTask) IsFinished() bool { func (p *PodTask) IsOOMKilled() bool { for _, container := range p.Status.ContainerStatuses { - container := container if status := GetTerminationStatus(&container); status != nil && status.Reason == reasonOOMKilled { return true } diff --git a/pkg/execution/taskexecutor/podtaskexecutor/pod_task_test.go b/pkg/execution/taskexecutor/podtaskexecutor/pod_task_test.go index afc8fe6..11e4b86 100644 --- a/pkg/execution/taskexecutor/podtaskexecutor/pod_task_test.go +++ b/pkg/execution/taskexecutor/podtaskexecutor/pod_task_test.go @@ -74,7 +74,6 @@ func TestPodTask_GetState(t *testing.T) { }, } for _, tt := range tests { - tt := tt t.Run(tt.name, func(t *testing.T) { p := podtaskexecutor.NewPodTask(&tt.Pod, nil) if got := p.GetState(); got != tt.want { @@ -120,7 +119,6 @@ func TestPodTask_GetResult(t *testing.T) { }, } for _, tt := range tests { - tt := tt t.Run(tt.name, func(t *testing.T) { p := podtaskexecutor.NewPodTask(&tt.Pod, nil) got := p.GetResult() @@ -159,7 +157,6 @@ func TestPodTask_GetRunningTimestamp(t *testing.T) { }, } for _, tt := range tests { - tt := tt t.Run(tt.name, func(t *testing.T) { p := podtaskexecutor.NewPodTask(&tt.Pod, nil) got := p.GetRunningTimestamp() @@ -228,7 +225,6 @@ func TestPodTask_GetFinishTimestamp(t *testing.T) { }, } for _, tt := range tests { - tt := tt t.Run(tt.name, func(t *testing.T) { p := podtaskexecutor.NewPodTask(&tt.Pod, nil) got := p.GetFinishTimestamp() @@ -277,7 +273,6 @@ func TestPodTask_RequiresKillWithDeletion(t *testing.T) { }, } for _, tt := range tests { - tt := tt t.Run(tt.name, func(t *testing.T) { p := podtaskexecutor.NewPodTask(&tt.Pod, nil) if got := p.RequiresKillWithDeletion(); got != tt.want { @@ -372,7 +367,6 @@ func TestPodTask_GetReasonMessage(t *testing.T) { }, } for _, tt := range tests { - tt := tt t.Run(tt.name, func(t *testing.T) { p := podtaskexecutor.NewPodTask(&tt.Pod, nil) reason, message := p.GetReasonMessage() diff --git a/pkg/execution/taskexecutor/podtaskexecutor/substitution_test.go b/pkg/execution/taskexecutor/podtaskexecutor/substitution_test.go index 62e1b0e..048fbdf 100644 --- a/pkg/execution/taskexecutor/podtaskexecutor/substitution_test.go +++ b/pkg/execution/taskexecutor/podtaskexecutor/substitution_test.go @@ -139,7 +139,6 @@ func TestSubstitutePodSpec(t *testing.T) { }, } for _, tt := range tests { - tt := tt t.Run(tt.name, func(t *testing.T) { rj := &execution.Job{ ObjectMeta: metav1.ObjectMeta{ diff --git a/pkg/execution/taskexecutor/podtaskexecutor/util.go b/pkg/execution/taskexecutor/podtaskexecutor/util.go index c541294..3f808b6 100644 --- a/pkg/execution/taskexecutor/podtaskexecutor/util.go +++ b/pkg/execution/taskexecutor/podtaskexecutor/util.go @@ -89,7 +89,6 @@ func GetContainerTerminateTime(pod *corev1.Pod) metav1.Time { var t metav1.Time for _, container := range pod.Status.ContainerStatuses { - container := container if status := GetTerminationStatus(&container); status != nil && !ktime.IsUnixZero(&status.FinishedAt) { t = *ktime.TimeMax(&status.FinishedAt, &t) } diff --git a/pkg/execution/util/cronschedule/schedule_test.go b/pkg/execution/util/cronschedule/schedule_test.go index 01dbf87..f58a118 100644 --- a/pkg/execution/util/cronschedule/schedule_test.go +++ b/pkg/execution/util/cronschedule/schedule_test.go @@ -499,7 +499,6 @@ func TestSchedule(t *testing.T) { }, } for _, tt := range tests { - tt := tt t.Run(tt.name, func(t *testing.T) { initTime := testutils.Mktime(now) if !tt.initTime.IsZero() { @@ -762,7 +761,6 @@ func TestSchedule_Sequence(t *testing.T) { }, } for _, tt := range tests { - tt := tt t.Run(tt.name, func(t *testing.T) { // Change popTime if specified. now := testutils.Mktime(now) diff --git a/pkg/execution/util/job/active_test.go b/pkg/execution/util/job/active_test.go index 1d9b44f..21fbbf4 100644 --- a/pkg/execution/util/job/active_test.go +++ b/pkg/execution/util/job/active_test.go @@ -154,7 +154,6 @@ func TestIsActive(t *testing.T) { }, } for _, tt := range tests { - tt := tt t.Run(tt.name, func(t *testing.T) { if got := job.IsActive(tt.rj); got != tt.want { t.Errorf("IsActive() = %v, want %v", got, tt.want) diff --git a/pkg/execution/util/job/condition.go b/pkg/execution/util/job/condition.go index 8d08f31..69a7f4a 100644 --- a/pkg/execution/util/job/condition.go +++ b/pkg/execution/util/job/condition.go @@ -90,7 +90,6 @@ func GetCondition(rj *execution.Job) (execution.JobCondition, error) { // Compute latest timestamps across all tasks. var latestCreated, latestRunning, latestFinished *metav1.Time for _, task := range rj.Status.Tasks { - task := task latestCreated = ktime.TimeMax(latestCreated, &task.CreationTimestamp) latestRunning = ktime.TimeMax(latestRunning, task.RunningTimestamp) latestFinished = ktime.TimeMax(latestFinished, task.FinishTimestamp) diff --git a/pkg/execution/util/job/condition_test.go b/pkg/execution/util/job/condition_test.go index a74fac3..75d8575 100644 --- a/pkg/execution/util/job/condition_test.go +++ b/pkg/execution/util/job/condition_test.go @@ -1222,7 +1222,6 @@ func TestGetCondition(t *testing.T) { }, } for _, tt := range tests { - tt := tt t.Run(tt.name, func(t *testing.T) { rj := tt.args.rj diff --git a/pkg/execution/util/job/phase_test.go b/pkg/execution/util/job/phase_test.go index cbe1667..2e3c861 100644 --- a/pkg/execution/util/job/phase_test.go +++ b/pkg/execution/util/job/phase_test.go @@ -556,7 +556,6 @@ func TestGetPhase(t *testing.T) { }, } for _, tt := range tests { - tt := tt t.Run(tt.name, func(t *testing.T) { if got := job.GetPhase(tt.rj); got != tt.want { t.Errorf("GetPhase() = %v, want %v", got, tt.want) diff --git a/pkg/execution/util/job/task_status_test.go b/pkg/execution/util/job/task_status_test.go index 2c359ba..381fc17 100644 --- a/pkg/execution/util/job/task_status_test.go +++ b/pkg/execution/util/job/task_status_test.go @@ -232,7 +232,6 @@ func TestGenerateTaskRefs(t *testing.T) { }, } for _, tt := range tests { - tt := tt cmpOpts := cmp.Options{ cmpopts.EquateEmpty(), } @@ -337,7 +336,6 @@ func TestUpdateTaskRefDeletedStatusIfNotSet(t *testing.T) { }, } for _, tt := range tests { - tt := tt t.Run(tt.name, func(t *testing.T) { original := tt.args.rj.DeepCopy() @@ -507,7 +505,6 @@ func TestUpdateJobTaskRefs(t *testing.T) { }, } for _, tt := range tests { - tt := tt t.Run(tt.name, func(t *testing.T) { if got := jobutil.UpdateJobTaskRefs(tt.rj, tt.tasks); !cmp.Equal(tt.want, got) { t.Errorf("UpdateJobTaskRefs() not equal\ndiff = %v", cmp.Diff(tt.want, got)) diff --git a/pkg/execution/util/jobconfig/job_utils.go b/pkg/execution/util/jobconfig/job_utils.go index 19f077b..bde592d 100644 --- a/pkg/execution/util/jobconfig/job_utils.go +++ b/pkg/execution/util/jobconfig/job_utils.go @@ -36,7 +36,6 @@ import ( func GetLastScheduleTime(jobs []*execution.Job) *metav1.Time { var lastScheduleTime metav1.Time for _, rj := range jobs { - rj := rj if t := GetLabelScheduleTime(rj); t != nil && lastScheduleTime.Before(t) { lastScheduleTime = *t } @@ -64,7 +63,6 @@ func GetLabelScheduleTime(rj *execution.Job) *metav1.Time { func GetLastStartTime(jobs []*execution.Job) *metav1.Time { var lastStartTime metav1.Time for _, rj := range jobs { - rj := rj if !job.IsStarted(rj) || rj.Status.StartTime.IsZero() { continue } diff --git a/pkg/execution/util/jobconfig/state_test.go b/pkg/execution/util/jobconfig/state_test.go index 0d4d545..3a78170 100644 --- a/pkg/execution/util/jobconfig/state_test.go +++ b/pkg/execution/util/jobconfig/state_test.go @@ -106,7 +106,6 @@ func TestGetState(t *testing.T) { }, } for _, tt := range tests { - tt := tt t.Run(tt.name, func(t *testing.T) { if got := jobconfig.GetState(tt.rjc); got != tt.want { t.Errorf("GetState() = %v, want %v", got, tt.want) diff --git a/pkg/execution/validation/corev1_test.go b/pkg/execution/validation/corev1_test.go index 4bdf62e..aba96f0 100644 --- a/pkg/execution/validation/corev1_test.go +++ b/pkg/execution/validation/corev1_test.go @@ -82,7 +82,6 @@ func TestValidatePodTemplateSpec(t *testing.T) { }, } for _, tt := range tests { - tt := tt t.Run(tt.name, func(t *testing.T) { original := tt.spec.DeepCopy() fieldPath := field.NewPath("") diff --git a/pkg/execution/validation/validation_test.go b/pkg/execution/validation/validation_test.go index f71f2c6..2601285 100644 --- a/pkg/execution/validation/validation_test.go +++ b/pkg/execution/validation/validation_test.go @@ -492,7 +492,6 @@ func TestValidateJobConfig(t *testing.T) { }, } for _, tt := range tests { - tt := tt t.Run(tt.name, func(t *testing.T) { original := tt.rjc.DeepCopy() ctrlContext := mock.NewContext() @@ -848,7 +847,6 @@ func TestValidateJob(t *testing.T) { }, } for _, tt := range tests { - tt := tt t.Run(tt.name, func(t *testing.T) { original := tt.rj.DeepCopy() ctrlContext := mock.NewContext() @@ -1119,7 +1117,6 @@ func TestValidateJobUpdate(t *testing.T) { }, } for _, tt := range tests { - tt := tt t.Run(tt.name, func(t *testing.T) { fakeClock := fakeclock.NewFakeClock(time.Now()) validation.Clock = fakeClock @@ -1387,7 +1384,6 @@ func TestValidateJobCreate(t *testing.T) { }, } for _, tt := range tests { - tt := tt t.Run(tt.name, func(t *testing.T) { originalRj := tt.rj.DeepCopy() validator := setup(t, tt.cfgs, tt.rjcs) diff --git a/pkg/generated/clientset/versioned/fake/register.go b/pkg/generated/clientset/versioned/fake/register.go index 49a44d3..937a0cb 100644 --- a/pkg/generated/clientset/versioned/fake/register.go +++ b/pkg/generated/clientset/versioned/fake/register.go @@ -37,14 +37,14 @@ var localSchemeBuilder = runtime.SchemeBuilder{ // AddToScheme adds all types of this clientset into the given scheme. This allows composition // of clientsets, like in: // -// import ( -// "k8s.io/client-go/kubernetes" -// clientsetscheme "k8s.io/client-go/kubernetes/scheme" -// aggregatorclientsetscheme "k8s.io/kube-aggregator/pkg/client/clientset_generated/clientset/scheme" -// ) +// import ( +// "k8s.io/client-go/kubernetes" +// clientsetscheme "k8s.io/client-go/kubernetes/scheme" +// aggregatorclientsetscheme "k8s.io/kube-aggregator/pkg/client/clientset_generated/clientset/scheme" +// ) // -// kclientset, _ := kubernetes.NewForConfig(c) -// _ = aggregatorclientsetscheme.AddToScheme(clientsetscheme.Scheme) +// kclientset, _ := kubernetes.NewForConfig(c) +// _ = aggregatorclientsetscheme.AddToScheme(clientsetscheme.Scheme) // // After this, RawExtensions in Kubernetes types will serialize kube-aggregator types // correctly. diff --git a/pkg/generated/clientset/versioned/scheme/register.go b/pkg/generated/clientset/versioned/scheme/register.go index 272e4ca..2c9cc17 100644 --- a/pkg/generated/clientset/versioned/scheme/register.go +++ b/pkg/generated/clientset/versioned/scheme/register.go @@ -37,14 +37,14 @@ var localSchemeBuilder = runtime.SchemeBuilder{ // AddToScheme adds all types of this clientset into the given scheme. This allows composition // of clientsets, like in: // -// import ( -// "k8s.io/client-go/kubernetes" -// clientsetscheme "k8s.io/client-go/kubernetes/scheme" -// aggregatorclientsetscheme "k8s.io/kube-aggregator/pkg/client/clientset_generated/clientset/scheme" -// ) +// import ( +// "k8s.io/client-go/kubernetes" +// clientsetscheme "k8s.io/client-go/kubernetes/scheme" +// aggregatorclientsetscheme "k8s.io/kube-aggregator/pkg/client/clientset_generated/clientset/scheme" +// ) // -// kclientset, _ := kubernetes.NewForConfig(c) -// _ = aggregatorclientsetscheme.AddToScheme(clientsetscheme.Scheme) +// kclientset, _ := kubernetes.NewForConfig(c) +// _ = aggregatorclientsetscheme.AddToScheme(clientsetscheme.Scheme) // // After this, RawExtensions in Kubernetes types will serialize kube-aggregator types // correctly. diff --git a/pkg/runtime/configloader/manager_test.go b/pkg/runtime/configloader/manager_test.go index 3c75afc..36de7c5 100644 --- a/pkg/runtime/configloader/manager_test.go +++ b/pkg/runtime/configloader/manager_test.go @@ -330,7 +330,6 @@ func TestConfigManager(t *testing.T) { }, } for _, tt := range tests { - tt := tt t.Run(tt.name, func(t *testing.T) { mgr := configloader.NewConfigManager() for _, loader := range tt.loaders { @@ -477,7 +476,6 @@ func TestConfigManager_Dynamic(t *testing.T) { }, } for _, tt := range tests { - tt := tt t.Run(tt.name, func(t *testing.T) { mgr := configloader.NewConfigManager() loader := newMockDynamicConfigLoader(tt.initial.config) @@ -488,7 +486,6 @@ func TestConfigManager_Dynamic(t *testing.T) { checkConfig(t, mgr, tt.initial.want, tt.initial.wantErr) for i, update := range tt.updates { - update := update t.Run(fmt.Sprintf("step #%02d: %v", i+1, update.name), func(t *testing.T) { loader.SetConfig(update.config) checkConfig(t, mgr, update.want, update.wantErr) diff --git a/pkg/runtime/controllermanager/controller.go b/pkg/runtime/controllermanager/controller.go index 40fdcd9..8bf3487 100644 --- a/pkg/runtime/controllermanager/controller.go +++ b/pkg/runtime/controllermanager/controller.go @@ -209,7 +209,6 @@ func RunControllers(ctx context.Context, controllers []Controller) error { grp, _ := errgroup.WithContext(ctx) for _, controller := range controllers { - controller := controller grp.Go(func() error { return controller.Run(ctx) }) @@ -224,7 +223,6 @@ func ShutdownRunnables(ctx context.Context, controllers []Runnable) { wg.Add(len(controllers)) for _, controller := range controllers { - controller := controller go func() { defer wg.Done() controller.Shutdown(ctx) diff --git a/pkg/runtime/controllermanager/store.go b/pkg/runtime/controllermanager/store.go index 738cbd3..d4d5ab5 100644 --- a/pkg/runtime/controllermanager/store.go +++ b/pkg/runtime/controllermanager/store.go @@ -33,7 +33,6 @@ func RecoverStores(ctx context.Context, stores []Store) error { group, _ := errgroup.WithContext(ctx) for _, store := range stores { - store := store group.Go(func() error { return store.Recover(ctx) }) diff --git a/pkg/runtime/controllermanager/webhook.go b/pkg/runtime/controllermanager/webhook.go index 616c391..42368e8 100644 --- a/pkg/runtime/controllermanager/webhook.go +++ b/pkg/runtime/controllermanager/webhook.go @@ -111,7 +111,6 @@ func StartWebhooksAndWait(ctx context.Context, webhooks []Webhook) error { grp, ctx := errgroup.WithContext(ctx) for _, webhook := range webhooks { - webhook := webhook grp.Go(func() error { return webhook.Start(ctx) }) diff --git a/pkg/runtime/httphandler/webhooks.go b/pkg/runtime/httphandler/webhooks.go index df64a73..88201da 100644 --- a/pkg/runtime/httphandler/webhooks.go +++ b/pkg/runtime/httphandler/webhooks.go @@ -22,7 +22,6 @@ import ( "encoding/json" "fmt" "io" - "io/ioutil" "net/http" "runtime" "time" @@ -133,7 +132,7 @@ func handleWebhookRequest( } // Print debug logs for input request. - if body, err := ioutil.ReadAll(buf); err == nil { + if body, err := io.ReadAll(buf); err == nil { klog.V(4).InfoS( "httphandler: received request", "name", webhook.Name(), diff --git a/pkg/runtime/leaderelection/config_test.go b/pkg/runtime/leaderelection/config_test.go index 5fca9d6..2495a98 100644 --- a/pkg/runtime/leaderelection/config_test.go +++ b/pkg/runtime/leaderelection/config_test.go @@ -92,7 +92,6 @@ func TestConfig_Prepare(t *testing.T) { }, } for _, tt := range tests { - tt := tt t.Run(tt.name, func(t *testing.T) { cfg := tt.cfg.PrepareValues() if !cmp.Equal(tt.expected, cfg) { diff --git a/pkg/runtime/testing/testing_test.go b/pkg/runtime/testing/testing_test.go index e318eea..9944362 100644 --- a/pkg/runtime/testing/testing_test.go +++ b/pkg/runtime/testing/testing_test.go @@ -160,7 +160,6 @@ func TestCompareAction(t *testing.T) { }, } for _, tt := range tests { - tt := tt t.Run(tt.name, func(t *testing.T) { if err := runtimetesting.CompareAction(tt.want, tt.got); (err != nil) != tt.wantErr { t.Errorf("CompareAction() error = %v, wantErr %v", err, tt.wantErr) @@ -262,7 +261,6 @@ func TestCompareActions(t *testing.T) { }, } for _, tt := range tests { - tt := tt t.Run(tt.name, func(t *testing.T) { newT := &testinginterface.RuntimeT{} var gotErr bool diff --git a/pkg/utils/ktime/time_test.go b/pkg/utils/ktime/time_test.go index 6e7a340..56aa90d 100644 --- a/pkg/utils/ktime/time_test.go +++ b/pkg/utils/ktime/time_test.go @@ -81,7 +81,6 @@ func TestTimeMax(t *testing.T) { }, } for _, tt := range tests { - tt := tt t.Run(tt.name, func(t *testing.T) { if got := ktime.TimeMax(tt.args.ts1, tt.args.ts2); !tt.want.Equal(got) { t.Errorf("TimeMax() = %v, want %v", got, tt.want) @@ -112,7 +111,6 @@ func TestIsUnixZero(t *testing.T) { }, } for _, tt := range tests { - tt := tt t.Run(tt.name, func(t *testing.T) { if got := ktime.IsUnixZero(&tt.ts); got != tt.want { t.Errorf("IsUnixZero() = %v, want %v", got, tt.want) diff --git a/pkg/utils/meta/annotations_test.go b/pkg/utils/meta/annotations_test.go index 81b5374..8bffcb4 100644 --- a/pkg/utils/meta/annotations_test.go +++ b/pkg/utils/meta/annotations_test.go @@ -85,7 +85,6 @@ func TestSetAnnotation(t *testing.T) { }, } for _, tt := range tests { - tt := tt t.Run(tt.name, func(t *testing.T) { meta.SetAnnotation(tt.object, tt.key, tt.value) got := tt.object.GetAnnotations() diff --git a/pkg/utils/strings/strings_test.go b/pkg/utils/strings/strings_test.go index 02e37f4..b9a3962 100644 --- a/pkg/utils/strings/strings_test.go +++ b/pkg/utils/strings/strings_test.go @@ -61,7 +61,6 @@ func TestContainsString(t *testing.T) { }, } for _, tt := range tests { - tt := tt t.Run(tt.name, func(t *testing.T) { if got := strings.ContainsString(tt.strs, tt.s); got != tt.want { t.Errorf("ContainsString() = %v, want %v", got, tt.want)