mirror of
https://github.com/k3s-io/kubernetes.git
synced 2025-07-25 20:53:33 +00:00
Merge pull request #51519 from hzxuzhonghu/cronjob
Automatic merge from submit-queue update deprecated interface and fix bug not return when list pod failed in cronjob_controller.go **What this PR does / why we need it**: remove some unused redundant code, and fix bug: when list pod failed, job still deleted but pod may still exist in func `deleteJob` **Which issue this PR fixes** *(optional, in `fixes #<issue number>(, fixes #<issue_number>, ...)` format, will close that issue when PR gets merged)*: fixes # **Special notes for your reviewer**: **Release note**: ```release-note NONE ```
This commit is contained in:
commit
fc9e214a84
@ -72,7 +72,7 @@ func NewCronJobController(kubeClient clientset.Interface) *CronJobController {
|
|||||||
// TODO: remove the wrapper when every clients have moved to use the clientset.
|
// TODO: remove the wrapper when every clients have moved to use the clientset.
|
||||||
eventBroadcaster.StartRecordingToSink(&v1core.EventSinkImpl{Interface: v1core.New(kubeClient.Core().RESTClient()).Events("")})
|
eventBroadcaster.StartRecordingToSink(&v1core.EventSinkImpl{Interface: v1core.New(kubeClient.Core().RESTClient()).Events("")})
|
||||||
|
|
||||||
if kubeClient != nil && kubeClient.Core().RESTClient().GetRateLimiter() != nil {
|
if kubeClient != nil && kubeClient.CoreV1().RESTClient().GetRateLimiter() != nil {
|
||||||
metrics.RegisterMetricAndTrackRateLimiterUsage("cronjob_controller", kubeClient.Core().RESTClient().GetRateLimiter())
|
metrics.RegisterMetricAndTrackRateLimiterUsage("cronjob_controller", kubeClient.Core().RESTClient().GetRateLimiter())
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -253,10 +253,12 @@ func syncOne(sj *batchv2alpha1.CronJob, js []batchv1.Job, now time.Time, jc jobC
|
|||||||
glog.V(4).Infof("Not starting job for %s because it is suspended", nameForLog)
|
glog.V(4).Infof("Not starting job for %s because it is suspended", nameForLog)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
times, err := getRecentUnmetScheduleTimes(*sj, now)
|
times, err := getRecentUnmetScheduleTimes(*sj, now)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
recorder.Eventf(sj, v1.EventTypeWarning, "FailedNeedsStart", "Cannot determine if job needs to be started: %v", err)
|
recorder.Eventf(sj, v1.EventTypeWarning, "FailedNeedsStart", "Cannot determine if job needs to be started: %v", err)
|
||||||
glog.Errorf("Cannot determine if %s needs to be started: %v", nameForLog, err)
|
glog.Errorf("Cannot determine if %s needs to be started: %v", nameForLog, err)
|
||||||
|
return
|
||||||
}
|
}
|
||||||
// TODO: handle multiple unmet start times, from oldest to newest, updating status as needed.
|
// TODO: handle multiple unmet start times, from oldest to newest, updating status as needed.
|
||||||
if len(times) == 0 {
|
if len(times) == 0 {
|
||||||
@ -266,6 +268,7 @@ func syncOne(sj *batchv2alpha1.CronJob, js []batchv1.Job, now time.Time, jc jobC
|
|||||||
if len(times) > 1 {
|
if len(times) > 1 {
|
||||||
glog.V(4).Infof("Multiple unmet start times for %s so only starting last one", nameForLog)
|
glog.V(4).Infof("Multiple unmet start times for %s so only starting last one", nameForLog)
|
||||||
}
|
}
|
||||||
|
|
||||||
scheduledTime := times[len(times)-1]
|
scheduledTime := times[len(times)-1]
|
||||||
tooLate := false
|
tooLate := false
|
||||||
if sj.Spec.StartingDeadlineSeconds != nil {
|
if sj.Spec.StartingDeadlineSeconds != nil {
|
||||||
@ -376,6 +379,7 @@ func deleteJob(sj *batchv2alpha1.CronJob, job *batchv1.Job, jc jobControlInterfa
|
|||||||
podList, err := pc.ListPods(job.Namespace, options)
|
podList, err := pc.ListPods(job.Namespace, options)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
recorder.Eventf(sj, v1.EventTypeWarning, "FailedList", "List job-pods: %v", err)
|
recorder.Eventf(sj, v1.EventTypeWarning, "FailedList", "List job-pods: %v", err)
|
||||||
|
return false
|
||||||
}
|
}
|
||||||
errList := []error{}
|
errList := []error{}
|
||||||
for _, pod := range podList.Items {
|
for _, pod := range podList.Items {
|
||||||
|
@ -17,6 +17,7 @@ limitations under the License.
|
|||||||
package cronjob
|
package cronjob
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"errors"
|
||||||
"sort"
|
"sort"
|
||||||
"strconv"
|
"strconv"
|
||||||
"strings"
|
"strings"
|
||||||
@ -34,9 +35,10 @@ import (
|
|||||||
_ "k8s.io/kubernetes/pkg/apis/batch/install"
|
_ "k8s.io/kubernetes/pkg/apis/batch/install"
|
||||||
)
|
)
|
||||||
|
|
||||||
// schedule is hourly on the hour
|
|
||||||
var (
|
var (
|
||||||
onTheHour string = "0 * * * ?"
|
// schedule is hourly on the hour
|
||||||
|
onTheHour string = "0 * * * ?"
|
||||||
|
errorSchedule string = "obvious error schedule"
|
||||||
)
|
)
|
||||||
|
|
||||||
func justBeforeTheHour() time.Time {
|
func justBeforeTheHour() time.Time {
|
||||||
@ -197,6 +199,9 @@ func TestSyncOne_RunOrNot(t *testing.T) {
|
|||||||
expectActive int
|
expectActive int
|
||||||
expectedWarnings int
|
expectedWarnings int
|
||||||
}{
|
}{
|
||||||
|
"never ran, not valid schedule, A": {A, F, errorSchedule, noDead, F, F, justBeforeTheHour(), F, F, 0, 1},
|
||||||
|
"never ran, not valid schedule, F": {f, F, errorSchedule, noDead, F, F, justBeforeTheHour(), F, F, 0, 1},
|
||||||
|
"never ran, not valid schedule, R": {f, F, errorSchedule, noDead, F, F, justBeforeTheHour(), F, F, 0, 1},
|
||||||
"never ran, not time, A": {A, F, onTheHour, noDead, F, F, justBeforeTheHour(), F, F, 0, 0},
|
"never ran, not time, A": {A, F, onTheHour, noDead, F, F, justBeforeTheHour(), F, F, 0, 0},
|
||||||
"never ran, not time, F": {f, F, onTheHour, noDead, F, F, justBeforeTheHour(), F, F, 0, 0},
|
"never ran, not time, F": {f, F, onTheHour, noDead, F, F, justBeforeTheHour(), F, F, 0, 0},
|
||||||
"never ran, not time, R": {R, F, onTheHour, noDead, F, F, justBeforeTheHour(), F, F, 0, 0},
|
"never ran, not time, R": {R, F, onTheHour, noDead, F, F, justBeforeTheHour(), F, F, 0, 0},
|
||||||
@ -480,6 +485,16 @@ func TestCleanupFinishedJobs_DeleteOrNot(t *testing.T) {
|
|||||||
{"2016-05-19T08:00:00Z", F, F, F, F},
|
{"2016-05-19T08:00:00Z", F, F, F, F},
|
||||||
{"2016-05-19T09:00:00Z", F, F, F, F},
|
{"2016-05-19T09:00:00Z", F, F, F, F},
|
||||||
}, justBeforeTheHour(), &limitZero, &limitZero, 6},
|
}, justBeforeTheHour(), &limitZero, &limitZero, 6},
|
||||||
|
|
||||||
|
"failed list pod err": {
|
||||||
|
[]CleanupJobSpec{
|
||||||
|
{"2016-05-19T04:00:00Z", T, F, F, F},
|
||||||
|
{"2016-05-19T05:00:00Z", T, F, F, F},
|
||||||
|
{"2016-05-19T06:00:00Z", T, T, F, F},
|
||||||
|
{"2016-05-19T07:00:00Z", T, T, F, F},
|
||||||
|
{"2016-05-19T08:00:00Z", T, F, F, F},
|
||||||
|
{"2016-05-19T09:00:00Z", T, F, F, F},
|
||||||
|
}, justBeforeTheHour(), &limitZero, &limitZero, 0},
|
||||||
}
|
}
|
||||||
|
|
||||||
for name, tc := range testCases {
|
for name, tc := range testCases {
|
||||||
@ -551,6 +566,9 @@ func TestCleanupFinishedJobs_DeleteOrNot(t *testing.T) {
|
|||||||
pc := &fakePodControl{}
|
pc := &fakePodControl{}
|
||||||
sjc := &fakeSJControl{}
|
sjc := &fakeSJControl{}
|
||||||
recorder := record.NewFakeRecorder(10)
|
recorder := record.NewFakeRecorder(10)
|
||||||
|
if name == "failed list pod err" {
|
||||||
|
pc.Err = errors.New("fakePodControl err")
|
||||||
|
}
|
||||||
|
|
||||||
cleanupFinishedJobs(&sj, js, jc, sjc, pc, recorder)
|
cleanupFinishedJobs(&sj, js, jc, sjc, pc, recorder)
|
||||||
|
|
||||||
@ -569,6 +587,9 @@ func TestCleanupFinishedJobs_DeleteOrNot(t *testing.T) {
|
|||||||
|
|
||||||
// Check for events
|
// Check for events
|
||||||
expectedEvents := len(jobsToDelete)
|
expectedEvents := len(jobsToDelete)
|
||||||
|
if name == "failed list pod err" {
|
||||||
|
expectedEvents = len(tc.jobSpecs)
|
||||||
|
}
|
||||||
if len(recorder.Events) != expectedEvents {
|
if len(recorder.Events) != expectedEvents {
|
||||||
t.Errorf("%s: expected %d event, actually %v", name, expectedEvents, len(recorder.Events))
|
t.Errorf("%s: expected %d event, actually %v", name, expectedEvents, len(recorder.Events))
|
||||||
}
|
}
|
||||||
|
@ -216,11 +216,11 @@ type realPodControl struct {
|
|||||||
var _ podControlInterface = &realPodControl{}
|
var _ podControlInterface = &realPodControl{}
|
||||||
|
|
||||||
func (r realPodControl) ListPods(namespace string, opts metav1.ListOptions) (*v1.PodList, error) {
|
func (r realPodControl) ListPods(namespace string, opts metav1.ListOptions) (*v1.PodList, error) {
|
||||||
return r.KubeClient.Core().Pods(namespace).List(opts)
|
return r.KubeClient.CoreV1().Pods(namespace).List(opts)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (r realPodControl) DeletePod(namespace string, name string) error {
|
func (r realPodControl) DeletePod(namespace string, name string) error {
|
||||||
return r.KubeClient.Core().Pods(namespace).Delete(name, nil)
|
return r.KubeClient.CoreV1().Pods(namespace).Delete(name, nil)
|
||||||
}
|
}
|
||||||
|
|
||||||
type fakePodControl struct {
|
type fakePodControl struct {
|
||||||
@ -235,6 +235,9 @@ var _ podControlInterface = &fakePodControl{}
|
|||||||
func (f *fakePodControl) ListPods(namespace string, opts metav1.ListOptions) (*v1.PodList, error) {
|
func (f *fakePodControl) ListPods(namespace string, opts metav1.ListOptions) (*v1.PodList, error) {
|
||||||
f.Lock()
|
f.Lock()
|
||||||
defer f.Unlock()
|
defer f.Unlock()
|
||||||
|
if f.Err != nil {
|
||||||
|
return nil, f.Err
|
||||||
|
}
|
||||||
return &v1.PodList{Items: f.Pods}, nil
|
return &v1.PodList{Items: f.Pods}, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user