Skip to content

Commit

Permalink
Use fakeClock in subresourceClient
Browse files Browse the repository at this point in the history
  • Loading branch information
shafeeqes committed Dec 1, 2024
1 parent 4cef7c9 commit fdd9a5c
Show file tree
Hide file tree
Showing 2 changed files with 44 additions and 5 deletions.
18 changes: 16 additions & 2 deletions pkg/client/fake/client.go
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,7 @@ import (
"k8s.io/apimachinery/pkg/watch"
"k8s.io/client-go/kubernetes/scheme"
"k8s.io/client-go/testing"
"k8s.io/utils/clock"
"k8s.io/utils/ptr"

"sigs.k8s.io/controller-runtime/pkg/client"
Expand All @@ -77,6 +78,7 @@ type fakeClient struct {

schemeWriteLock sync.Mutex
scheme *runtime.Scheme
clock clock.Clock

restMapper meta.RESTMapper
withStatusSubresource sets.Set[schema.GroupVersionKind]
Expand Down Expand Up @@ -110,6 +112,7 @@ func NewClientBuilder() *ClientBuilder {
// ClientBuilder builds a fake client.
type ClientBuilder struct {
scheme *runtime.Scheme
clock clock.Clock
restMapper meta.RESTMapper
initObject []client.Object
initLists []client.ObjectList
Expand All @@ -130,6 +133,13 @@ func (f *ClientBuilder) WithScheme(scheme *runtime.Scheme) *ClientBuilder {
return f
}

// WithClock sets this builder's internal clock.
// If not set, defaults to clock.RealClock.
func (f *ClientBuilder) WithClock(clock clock.Clock) *ClientBuilder {
f.clock = clock
return f
}

// WithRESTMapper sets this builder's restMapper.
// The restMapper is directly set as mapper in the Client. This can be used for example
// with a meta.DefaultRESTMapper to provide a static rest mapping.
Expand Down Expand Up @@ -222,6 +232,9 @@ func (f *ClientBuilder) Build() client.WithWatch {
if f.restMapper == nil {
f.restMapper = meta.NewDefaultRESTMapper([]schema.GroupVersion{})
}
if f.clock == nil {
f.clock = clock.RealClock{}
}

var tracker versionedTracker

Expand Down Expand Up @@ -259,6 +272,7 @@ func (f *ClientBuilder) Build() client.WithWatch {
var result client.WithWatch = &fakeClient{
tracker: tracker,
scheme: f.scheme,
clock: f.clock,
restMapper: f.restMapper,
indexes: f.indexes,
withStatusSubresource: withStatusSubResource,
Expand Down Expand Up @@ -1190,8 +1204,8 @@ func (sw *fakeSubResourceClient) Create(ctx context.Context, obj client.Object,
return apierrors.NewNotFound(schema.GroupResource{}, "")
}

tokenRequest.Status.Token = "fake-token"
tokenRequest.Status.ExpirationTimestamp = metav1.Date(6041, 1, 1, 0, 0, 0, 0, time.UTC)
tokenRequest.Status.Token = fmt.Sprintf("fake-token-%d", (ptr.Deref(tokenRequest.Spec.ExpirationSeconds, 3600)))
tokenRequest.Status.ExpirationTimestamp = metav1.Time{Time: sw.client.clock.Now().Add(time.Duration(ptr.Deref(tokenRequest.Spec.ExpirationSeconds, 3600)) * time.Second)}

return sw.client.Get(ctx, client.ObjectKeyFromObject(obj), obj)
default:
Expand Down
31 changes: 28 additions & 3 deletions pkg/client/fake/client_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,7 @@ import (
"k8s.io/apimachinery/pkg/types"
"k8s.io/apimachinery/pkg/watch"
"k8s.io/client-go/kubernetes/fake"
testclock "k8s.io/utils/clock/testing"
"k8s.io/utils/ptr"

"sigs.k8s.io/controller-runtime/pkg/client"
Expand Down Expand Up @@ -1964,14 +1965,38 @@ var _ = Describe("Fake client", func() {

It("should create a ServiceAccount token through the token subresource", func() {
sa := &corev1.ServiceAccount{ObjectMeta: metav1.ObjectMeta{Name: "foo"}}
cl := NewClientBuilder().WithObjects(sa).Build()
fakeNow := time.Date(2021, 10, 4, 10, 0, 0, 0, time.UTC)
fakeClock := testclock.NewFakeClock(fakeNow)

cl := NewClientBuilder().WithClock(fakeClock).WithObjects(sa).Build()

tokenRequest := &authenticationv1.TokenRequest{
Spec: authenticationv1.TokenRequestSpec{
ExpirationSeconds: ptr.To[int64](600),
},
}
err := cl.SubResource("token").Create(context.Background(), sa, tokenRequest)
Expect(err).NotTo(HaveOccurred())

Expect(tokenRequest.Status.Token).To(Equal("fake-token-600"))
expectedTimeStamp := metav1.NewTime(fakeNow.Add(600 * time.Second))
Expect(tokenRequest.Status.ExpirationTimestamp).To(Equal(metav1.Time{Time: expectedTimeStamp.Time}))
})

It("should create a ServiceAccount token with default expiration if expirationSeconds is nil through the token subresource", func() {
sa := &corev1.ServiceAccount{ObjectMeta: metav1.ObjectMeta{Name: "foo"}}
fakeNow := time.Date(2021, 10, 4, 10, 0, 0, 0, time.UTC)
fakeClock := testclock.NewFakeClock(fakeNow)

cl := NewClientBuilder().WithClock(fakeClock).WithObjects(sa).Build()

tokenRequest := &authenticationv1.TokenRequest{}
err := cl.SubResource("token").Create(context.Background(), sa, tokenRequest)
Expect(err).NotTo(HaveOccurred())

Expect(tokenRequest.Status.Token).NotTo(Equal(""))
Expect(tokenRequest.Status.ExpirationTimestamp).NotTo(Equal(metav1.Time{}))
Expect(tokenRequest.Status.Token).To(Equal("fake-token-3600"))
expectedTimeStamp := metav1.NewTime(fakeNow.Add(3600 * time.Second))
Expect(tokenRequest.Status.ExpirationTimestamp).To(Equal(metav1.Time{Time: expectedTimeStamp.Time}))
})

It("should return not found when creating a token for a ServiceAccount that doesn't exist", func() {
Expand Down

0 comments on commit fdd9a5c

Please sign in to comment.