Repository: furiko-io/furiko (go)

Issue:
Migrate to k8s.io/utils/clock
Ref https://github.com/kubernetes/kubernetes/issues/94738

Internally we upgraded to use v0.24.x of client-go (was previously on v0.20.9), and found that some usages of `k8s.io/apimachinery/pkg/util/clock` is not 100% compatible with the now-preferred `k8s.io/utils/clock`.

It seems that v0.23.0 is still okay, but we should migrate it still.

Pull request description:
chore(cleanup): Migrate to k8s.io/utils/clock
Fixes #99.

Patch:
diff --git a/pkg/execution/controllers/croncontroller/cron_worker.go b/pkg/execution/controllers/croncontroller/cron_worker.go
index a550c1b..87646ed 100644
--- a/pkg/execution/controllers/croncontroller/cron_worker.go
+++ b/pkg/execution/controllers/croncontroller/cron_worker.go
@@ -25,9 +25,9 @@ import (
 	"github.com/pkg/errors"
 	metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
 	"k8s.io/apimachinery/pkg/labels"
-	"k8s.io/apimachinery/pkg/util/clock"
 	"k8s.io/client-go/tools/cache"
 	"k8s.io/klog/v2"
+	"k8s.io/utils/clock"
 	utiltrace "k8s.io/utils/trace"
 
 	configv1alpha1 "github.com/furiko-io/furiko/apis/config/v1alpha1"
diff --git a/pkg/execution/mutation/mutation.go b/pkg/execution/mutation/mutation.go
index 92b5f73..af37f93 100644
--- a/pkg/execution/mutation/mutation.go
+++ b/pkg/execution/mutation/mutation.go
@@ -27,8 +27,8 @@ import (
 	kerrors "k8s.io/apimachinery/pkg/api/errors"
 	metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
 	"k8s.io/apimachinery/pkg/labels"
-	"k8s.io/apimachinery/pkg/util/clock"
 	"k8s.io/apimachinery/pkg/util/validation/field"
+	"k8s.io/utils/clock"
 	"k8s.io/utils/pointer"
 
 	"github.com/furiko-io/furiko/apis/execution"
diff --git a/pkg/execution/util/schedule/option.go b/pkg/execution/util/schedule/option.go
index 963c9d7..09ddf9e 100644
--- a/pkg/execution/util/schedule/option.go
+++ b/pkg/execution/util/schedule/option.go
@@ -17,7 +17,7 @@
 package schedule
 
 import (
-	"k8s.io/apimachinery/pkg/util/clock"
+	"k8s.io/utils/clock"
 
 	configv1alpha1 "github.com/furiko-io/furiko/apis/config/v1alpha1"
 	"github.com/furiko-io/furiko/pkg/config"
diff --git a/pkg/execution/util/schedule/schedule.go b/pkg/execution/util/schedule/schedule.go
index 9d6f48d..a20120b 100644
--- a/pkg/execution/util/schedule/schedule.go
+++ b/pkg/execution/util/schedule/schedule.go
@@ -23,8 +23,8 @@ import (
 	"github.com/furiko-io/cronexpr"
 	"github.com/pkg/errors"
 	metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
-	"k8s.io/apimachinery/pkg/util/clock"
 	"k8s.io/client-go/tools/cache"
+	"k8s.io/utils/clock"
 
 	configv1alpha1 "github.com/furiko-io/furiko/apis/config/v1alpha1"
 	execution "github.com/furiko-io/furiko/apis/execution/v1alpha1"
diff --git a/pkg/execution/validation/validation.go b/pkg/execution/validation/validation.go
index 18c5481..b9c2f73 100644
--- a/pkg/execution/validation/validation.go
+++ b/pkg/execution/validation/validation.go
@@ -23,10 +23,10 @@ import (
 	"github.com/pkg/errors"
 	corev1 "k8s.io/api/core/v1"
 	metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
-	"k8s.io/apimachinery/pkg/util/clock"
 	apimachineryvalidation "k8s.io/apimachinery/pkg/util/validation"
 	"k8s.io/apimachinery/pkg/util/validation/field"
 	apivalidation "k8s.io/kubernetes/pkg/apis/core/validation"
+	"k8s.io/utils/clock"
 
 	configv1alpha1 "github.com/furiko-io/furiko/apis/config/v1alpha1"
 	"github.com/furiko-io/furiko/apis/execution/v1alpha1"
diff --git a/pkg/utils/ktime/time.go b/pkg/utils/ktime/time.go
index e543b72..79b8496 100644
--- a/pkg/utils/ktime/time.go
+++ b/pkg/utils/ktime/time.go
@@ -20,7 +20,7 @@ import (
 	"time"
 
 	metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
-	"k8s.io/apimachinery/pkg/util/clock"
+	"k8s.io/utils/clock"
 )
 
 var (


Test patch:
diff --git a/pkg/execution/controllers/croncontroller/control_test.go b/pkg/execution/controllers/croncontroller/control_test.go
index f52f262..d6d6bdd 100644
--- a/pkg/execution/controllers/croncontroller/control_test.go
+++ b/pkg/execution/controllers/croncontroller/control_test.go
@@ -26,9 +26,9 @@ import (
 	kerrors "k8s.io/apimachinery/pkg/api/errors"
 	metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
 	"k8s.io/apimachinery/pkg/runtime"
-	"k8s.io/apimachinery/pkg/util/clock"
 	"k8s.io/apimachinery/pkg/util/validation/field"
 	ktesting "k8s.io/client-go/testing"
+	fakeclock "k8s.io/utils/clock/testing"
 
 	execution "github.com/furiko-io/furiko/apis/execution/v1alpha1"
 	"github.com/furiko-io/furiko/pkg/execution/controllers/croncontroller"
@@ -75,7 +75,7 @@ func TestExecutionControl(t *testing.T) {
 	ctx, cancel := context.WithTimeout(context.Background(), time.Second*10)
 	defer cancel()
 
-	ktime.Clock = clock.NewFakeClock(time.Now())
+	ktime.Clock = fakeclock.NewFakeClock(time.Now())
 	c := mock.NewContext()
 	fakeClient := c.MockClientsets().FurikoMock()
 	client := fakeClient.ExecutionV1alpha1()
diff --git a/pkg/execution/controllers/croncontroller/cron_worker_test.go b/pkg/execution/controllers/croncontroller/cron_worker_test.go
index fd1f56c..eb0fd69 100644
--- a/pkg/execution/controllers/croncontroller/cron_worker_test.go
+++ b/pkg/execution/controllers/croncontroller/cron_worker_test.go
@@ -26,8 +26,8 @@ import (
 	"github.com/stretchr/testify/assert"
 	metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
 	"k8s.io/apimachinery/pkg/runtime"
-	"k8s.io/apimachinery/pkg/util/clock"
 	"k8s.io/client-go/tools/cache"
+	fakeclock "k8s.io/utils/clock/testing"
 	"k8s.io/utils/pointer"
 
 	configv1alpha1 "github.com/furiko-io/furiko/apis/config/v1alpha1"
@@ -354,7 +354,7 @@ func TestCronWorker(t *testing.T) {
 			defer cancel()
 
 			prevtime := tt.now
-			fakeClock := clock.NewFakeClock(prevtime)
+			fakeClock := fakeclock.NewFakeClock(prevtime)
 			croncontroller.Clock = fakeClock
 
 			// Initialize contexts and worker
diff --git a/pkg/execution/controllers/croncontroller/ticker_test.go b/pkg/execution/controllers/croncontroller/ticker_test.go
index ab019ec..248ba1d 100644
--- a/pkg/execution/controllers/croncontroller/ticker_test.go
+++ b/pkg/execution/controllers/croncontroller/ticker_test.go
@@ -22,7 +22,7 @@ import (
 	"time"
 
 	"github.com/stretchr/testify/assert"
-	"k8s.io/apimachinery/pkg/util/clock"
+	fakeclock "k8s.io/utils/clock/testing"
 
 	"github.com/furiko-io/furiko/pkg/execution/controllers/croncontroller"
 )
@@ -38,7 +38,7 @@ func TestClockTickUntil(t *testing.T) {
 	work := func() {
 		atomic.AddInt64(&i, 1)
 	}
-	fakeClock := clock.NewFakeClock(initialTime)
+	fakeClock := fakeclock.NewFakeClock(initialTime)
 	croncontroller.Clock = fakeClock
 
 	step := 5
@@ -90,7 +90,7 @@ func TestCronTimerUntil_Seconds(t *testing.T) {
 	work := func() {
 		atomic.AddInt64(&i, 1)
 	}
-	fakeClock := clock.NewFakeClock(initialTime)
+	fakeClock := fakeclock.NewFakeClock(initialTime)
 	croncontroller.Clock = fakeClock
 
 	timestep := time.Second
diff --git a/pkg/execution/controllers/jobcontroller/control_test.go b/pkg/execution/controllers/jobcontroller/control_test.go
index 35fa82c..122dcdd 100644
--- a/pkg/execution/controllers/jobcontroller/control_test.go
+++ b/pkg/execution/controllers/jobcontroller/control_test.go
@@ -24,7 +24,7 @@ import (
 	"github.com/stretchr/testify/assert"
 	kerrors "k8s.io/apimachinery/pkg/api/errors"
 	metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
-	"k8s.io/apimachinery/pkg/util/clock"
+	fakeclock "k8s.io/utils/clock/testing"
 
 	execution "github.com/furiko-io/furiko/apis/execution/v1alpha1"
 	"github.com/furiko-io/furiko/pkg/execution/controllers/jobcontroller"
@@ -37,7 +37,7 @@ func TestExecutionControl(t *testing.T) {
 	ctx, cancel := context.WithTimeout(context.Background(), time.Second*10)
 	defer cancel()
 
-	ktime.Clock = clock.NewFakeClock(time.Now())
+	ktime.Clock = fakeclock.NewFakeClock(time.Now())
 	c := mock.NewContext()
 	client := c.MockClientsets().FurikoMock().ExecutionV1alpha1()
 	control := jobcontroller.NewExecutionControl(client, "test")
diff --git a/pkg/execution/mutation/mutation_test.go b/pkg/execution/mutation/mutation_test.go
index 95b9e44..5158396 100644
--- a/pkg/execution/mutation/mutation_test.go
+++ b/pkg/execution/mutation/mutation_test.go
@@ -29,8 +29,8 @@ import (
 	corev1 "k8s.io/api/core/v1"
 	metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
 	"k8s.io/apimachinery/pkg/runtime"
-	"k8s.io/apimachinery/pkg/util/clock"
 	"k8s.io/client-go/tools/cache"
+	fakeclock "k8s.io/utils/clock/testing"
 	"k8s.io/utils/pointer"
 	"sigs.k8s.io/yaml"
 
@@ -368,7 +368,7 @@ func TestMutator_MutateCreateJobConfig(t *testing.T) {
 		{
 			name: "bump LastUpdatedTime with updated cron schedule",
 			setup: func() {
-				mutation.Clock = clock.NewFakeClock(mockNow.Time)
+				mutation.Clock = fakeclock.NewFakeClock(mockNow.Time)
 			},
 			rjc: &v1alpha1.JobConfig{
 				ObjectMeta: objectMetaJobConfig,
@@ -388,7 +388,7 @@ func TestMutator_MutateCreateJobConfig(t *testing.T) {
 		{
 			name: "don't reset future LastUpdated",
 			setup: func() {
-				mutation.Clock = clock.NewFakeClock(mockNow.Time)
+				mutation.Clock = fakeclock.NewFakeClock(mockNow.Time)
 			},
 			rjc: &v1alpha1.JobConfig{
 				ObjectMeta: objectMetaJobConfig,
@@ -473,7 +473,7 @@ func TestMutator_MutateUpdateJobConfig(t *testing.T) {
 		{
 			name: "no change expected",
 			setup: func() {
-				mutation.Clock = clock.NewFakeClock(mockNow.Time)
+				mutation.Clock = fakeclock.NewFakeClock(mockNow.Time)
 			},
 			oldRjc: &v1alpha1.JobConfig{
 				ObjectMeta: objectMetaJobConfig,
@@ -493,7 +493,7 @@ func TestMutator_MutateUpdateJobConfig(t *testing.T) {
 		{
 			name: "no change expected without schedule",
 			setup: func() {
-				mutation.Clock = clock.NewFakeClock(mockNow.Time)
+				mutation.Clock = fakeclock.NewFakeClock(mockNow.Time)
 			},
 			oldRjc: &v1alpha1.JobConfig{
 				ObjectMeta: objectMetaJobConfig,
@@ -511,7 +511,7 @@ func TestMutator_MutateUpdateJobConfig(t *testing.T) {
 		{
 			name: "bump LastUpdated",
 			setup: func() {
-				mutation.Clock = clock.NewFakeClock(mockNow.Time)
+				mutation.Clock = fakeclock.NewFakeClock(mockNow.Time)
 			},
 			oldRjc: &v1alpha1.JobConfig{
 				ObjectMeta: objectMetaJobConfig,
@@ -538,7 +538,7 @@ func TestMutator_MutateUpdateJobConfig(t *testing.T) {
 		{
 			name: "bump LastUpdated add schedule",
 			setup: func() {
-				mutation.Clock = clock.NewFakeClock(mockNow.Time)
+				mutation.Clock = fakeclock.NewFakeClock(mockNow.Time)
 			},
 			oldRjc: &v1alpha1.JobConfig{
 				ObjectMeta: objectMetaJobConfig,
@@ -564,7 +564,7 @@ func TestMutator_MutateUpdateJobConfig(t *testing.T) {
 		{
 			name: "bump LastUpdated update disabled",
 			setup: func() {
-				mutation.Clock = clock.NewFakeClock(mockNow.Time)
+				mutation.Clock = fakeclock.NewFakeClock(mockNow.Time)
 			},
 			oldRjc: &v1alpha1.JobConfig{
 				ObjectMeta: objectMetaJobConfig,
@@ -602,7 +602,7 @@ func TestMutator_MutateUpdateJobConfig(t *testing.T) {
 		{
 			name: "don't reset future LastUpdated",
 			setup: func() {
-				mutation.Clock = clock.NewFakeClock(mockNow.Time)
+				mutation.Clock = fakeclock.NewFakeClock(mockNow.Time)
 			},
 			oldRjc: &v1alpha1.JobConfig{
 				ObjectMeta: objectMetaJobConfig,
diff --git a/pkg/execution/util/job/condition_test.go b/pkg/execution/util/job/condition_test.go
index cae7cb9..a74fac3 100644
--- a/pkg/execution/util/job/condition_test.go
+++ b/pkg/execution/util/job/condition_test.go
@@ -23,7 +23,7 @@ import (
 
 	"github.com/google/go-cmp/cmp"
 	metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
-	"k8s.io/apimachinery/pkg/util/clock"
+	fakeclock "k8s.io/utils/clock/testing"
 	"k8s.io/utils/pointer"
 
 	execution "github.com/furiko-io/furiko/apis/execution/v1alpha1"
@@ -34,7 +34,7 @@ import (
 
 func TestGetCondition(t *testing.T) {
 	timeNow := time.Now()
-	ktime.Clock = clock.NewFakeClock(timeNow)
+	ktime.Clock = fakeclock.NewFakeClock(timeNow)
 
 	type args struct {
 		rj         *execution.Job
diff --git a/pkg/execution/util/schedule/schedule_test.go b/pkg/execution/util/schedule/schedule_test.go
index 0625d30..6a2bb28 100644
--- a/pkg/execution/util/schedule/schedule_test.go
+++ b/pkg/execution/util/schedule/schedule_test.go
@@ -25,8 +25,8 @@ import (
 	"github.com/google/go-cmp/cmp/cmpopts"
 	"github.com/stretchr/testify/assert"
 	metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
-	"k8s.io/apimachinery/pkg/util/clock"
 	"k8s.io/client-go/tools/cache"
+	fakeclock "k8s.io/utils/clock/testing"
 
 	configv1alpha1 "github.com/furiko-io/furiko/apis/config/v1alpha1"
 	execution "github.com/furiko-io/furiko/apis/execution/v1alpha1"
@@ -474,7 +474,7 @@ func TestSchedule(t *testing.T) {
 			}
 
 			// Initialize the Schedule from initTime.
-			fakeClock := clock.NewFakeClock(initTime)
+			fakeClock := fakeclock.NewFakeClock(initTime)
 			sched, err := schedule.New(
 				tt.jobConfigs,
 				schedule.WithClock(fakeClock),
@@ -700,7 +700,7 @@ func TestSchedule_Sequence(t *testing.T) {
 			}
 
 			// Use UTC time for the fake clock.
-			fakeClock := clock.NewFakeClock(now.In(time.UTC))
+			fakeClock := fakeclock.NewFakeClock(now.In(time.UTC))
 
 			sched, err := schedule.New(
 				[]*execution.JobConfig{tt.jobConfig},
@@ -749,7 +749,7 @@ func TestSchedule_Sequence(t *testing.T) {
 
 func TestSchedule_FlushNextScheduleTime(t *testing.T) {
 	now := testutils.Mktime(now)
-	fakeClock := clock.NewFakeClock(now)
+	fakeClock := fakeclock.NewFakeClock(now)
 	jobConfig := &execution.JobConfig{
 		ObjectMeta: metav1.ObjectMeta{
 			Name: "job-config-to-be-updated",
@@ -884,7 +884,7 @@ func TestSchedule_Bump(t *testing.T) {
 	for _, tt := range tests {
 		t.Run(tt.name, func(t *testing.T) {
 			now := testutils.Mktime(now)
-			fakeClock := clock.NewFakeClock(now)
+			fakeClock := fakeclock.NewFakeClock(now)
 			sched, err := schedule.New([]*execution.JobConfig{tt.jobConfig}, schedule.WithClock(fakeClock))
 			if err != nil {
 				t.Fatalf("cannot initialize schedule: %v", err)
diff --git a/pkg/execution/validation/validation_test.go b/pkg/execution/validation/validation_test.go
index c1511d1..cd2bdf4 100644
--- a/pkg/execution/validation/validation_test.go
+++ b/pkg/execution/validation/validation_test.go
@@ -26,8 +26,8 @@ import (
 	corev1 "k8s.io/api/core/v1"
 	metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
 	"k8s.io/apimachinery/pkg/runtime"
-	"k8s.io/apimachinery/pkg/util/clock"
 	"k8s.io/client-go/tools/cache"
+	fakeclock "k8s.io/utils/clock/testing"
 	"k8s.io/utils/pointer"
 
 	configv1alpha1 "github.com/furiko-io/furiko/apis/config/v1alpha1"
@@ -1071,7 +1071,7 @@ func TestValidateJobUpdate(t *testing.T) {
 	for _, tt := range tests {
 		tt := tt
 		t.Run(tt.name, func(t *testing.T) {
-			fakeClock := clock.NewFakeClock(time.Now())
+			fakeClock := fakeclock.NewFakeClock(time.Now())
 			validation.Clock = fakeClock
 			if tt.now != nil {
 				fakeClock.SetTime(*tt.now)
diff --git a/pkg/runtime/testing/command.go b/pkg/runtime/testing/command.go
index f67787f..0e69a1a 100644
--- a/pkg/runtime/testing/command.go
+++ b/pkg/runtime/testing/command.go
@@ -27,8 +27,8 @@ import (
 	"github.com/google/go-cmp/cmp"
 	"github.com/stretchr/testify/assert"
 	"k8s.io/apimachinery/pkg/runtime"
-	"k8s.io/apimachinery/pkg/util/clock"
 	"k8s.io/cli-runtime/pkg/genericclioptions"
+	fakeclock "k8s.io/utils/clock/testing"
 
 	"github.com/furiko-io/furiko/pkg/cli/cmd"
 	"github.com/furiko-io/furiko/pkg/cli/console"
@@ -117,7 +117,7 @@ func (c *CommandTest) Run(t *testing.T) {
 	if !c.Now.IsZero() {
 		now = c.Now
 	}
-	ktime.Clock = clock.NewFakeClock(now)
+	ktime.Clock = fakeclock.NewFakeClock(now)
 
 	// Run command with I/O.
 	iostreams, _, stdout, stderr := genericclioptions.NewTestIOStreams()
diff --git a/pkg/runtime/testing/reconciler.go b/pkg/runtime/testing/reconciler.go
index 6851aad..66adeb3 100644
--- a/pkg/runtime/testing/reconciler.go
+++ b/pkg/runtime/testing/reconciler.go
@@ -26,10 +26,10 @@ import (
 	"github.com/pkg/errors"
 	"github.com/stretchr/testify/assert"
 	"k8s.io/apimachinery/pkg/runtime"
-	"k8s.io/apimachinery/pkg/util/clock"
 	ktesting "k8s.io/client-go/testing"
 	"k8s.io/client-go/tools/cache"
 	"k8s.io/client-go/tools/record"
+	fakeclock "k8s.io/utils/clock/testing"
 
 	"github.com/furiko-io/furiko/pkg/runtime/controllercontext"
 	"github.com/furiko-io/furiko/pkg/runtime/controllercontext/mock"
@@ -202,7 +202,7 @@ func (r *ReconcilerTest) setupContext(
 	if !tt.Now.IsZero() {
 		now = tt.Now
 	}
-	fakeClock := clock.NewFakeClock(now)
+	fakeClock := fakeclock.NewFakeClock(now)
 	ktime.Clock = fakeClock
 
 	// Set up fake recorder.