Skip to content

Commit fb426b2

Browse files
committed
extend testing library (uid injection)
1 parent ec41a06 commit fb426b2

File tree

2 files changed

+54
-0
lines changed

2 files changed

+54
-0
lines changed

pkg/testing/complex_environment.go

Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,10 +9,12 @@ import (
99

1010
"github.com/onsi/gomega"
1111
"k8s.io/apimachinery/pkg/runtime"
12+
"k8s.io/apimachinery/pkg/util/uuid"
1213
clientgoscheme "k8s.io/client-go/kubernetes/scheme"
1314
ctrl "sigs.k8s.io/controller-runtime"
1415
"sigs.k8s.io/controller-runtime/pkg/client"
1516
"sigs.k8s.io/controller-runtime/pkg/client/fake"
17+
"sigs.k8s.io/controller-runtime/pkg/client/interceptor"
1618
"sigs.k8s.io/controller-runtime/pkg/reconcile"
1719

1820
"github.com/openmcp-project/controller-utils/pkg/logging"
@@ -121,6 +123,7 @@ type ComplexEnvironmentBuilder struct {
121123
ClusterInitObjectPaths map[string][]string
122124
ClientCreationCallbacks map[string][]func(client.Client)
123125
loggerIsSet bool
126+
InjectUIDs map[string]bool
124127
}
125128

126129
type ClusterEnvironment struct {
@@ -163,6 +166,7 @@ func NewComplexEnvironmentBuilder() *ComplexEnvironmentBuilder {
163166
ClusterStatusObjects: map[string][]client.Object{},
164167
ClusterInitObjectPaths: map[string][]string{},
165168
ClientCreationCallbacks: map[string][]func(client.Client){},
169+
InjectUIDs: map[string]bool{},
166170
}
167171
}
168172

@@ -264,6 +268,16 @@ func (eb *ComplexEnvironmentBuilder) WithAfterClientCreationCallback(name string
264268
return eb
265269
}
266270

271+
// WithUIDs enables UID injection for the specified cluster.
272+
// All objects that are initially loaded or afterwards created via the client's 'Create' method will have a random UID injected, if they do not already have one.
273+
// Note that this function registers an interceptor function, which will be overwritten if 'WithFakeClientBuilderCall(..., "WithInterceptorFuncs", ...)' is also called.
274+
// This would lead to newly created objects not having a UID injected.
275+
// To avoid this, pass 'InjectUIDOnObjectCreation(...)' into the interceptor.Funcs' Create field. The argument allows to inject your own additional Create logic, if desired.
276+
func (eb *ComplexEnvironmentBuilder) WithUIDs(name string) *ComplexEnvironmentBuilder {
277+
eb.InjectUIDs[name] = true
278+
return eb
279+
}
280+
267281
// WithFakeClientBuilderCall allows to inject method calls to fake.ClientBuilder when the fake clients are created during Build().
268282
// The fake clients are usually created using WithScheme(...).WithObjects(...).WithStatusSubresource(...).Build().
269283
// This function allows to inject additional method calls. It is only required for advanced use-cases.
@@ -284,6 +298,8 @@ func (eb *ComplexEnvironmentBuilder) WithFakeClientBuilderCall(name string, meth
284298
// Build constructs the environment from the builder.
285299
// Note that this function panics instead of throwing an error,
286300
// as it is intended to be used in tests, where all information is static anyway.
301+
//
302+
//nolint:gocyclo
287303
func (eb *ComplexEnvironmentBuilder) Build() *ComplexEnvironment {
288304
res := eb.internal
289305

@@ -335,6 +351,18 @@ func (eb *ComplexEnvironmentBuilder) Build() *ComplexEnvironment {
335351
if len(eb.ClusterInitObjects) > 0 {
336352
objs = append(objs, eb.ClusterInitObjects[name]...)
337353
}
354+
if eb.InjectUIDs[name] {
355+
// ensure that objects have a uid
356+
for _, obj := range objs {
357+
if obj.GetUID() == "" {
358+
// set a random UID if not already set
359+
obj.SetUID(uuid.NewUUID())
360+
}
361+
}
362+
fcb.WithInterceptorFuncs(interceptor.Funcs{
363+
Create: InjectUIDOnObjectCreation(nil),
364+
})
365+
}
338366
statusObjs := []client.Object{}
339367
statusObjs = append(statusObjs, objs...)
340368
statusObjs = append(statusObjs, eb.ClusterStatusObjects[name]...)
@@ -396,3 +424,19 @@ func (eb *ComplexEnvironmentBuilder) Build() *ComplexEnvironment {
396424

397425
return res
398426
}
427+
428+
// InjectUIDOnObjectCreation returns an interceptor function for Create which injects a random UID into the object, if it does not already have one.
429+
// If additionalLogic is nil, the object is created regularly afterwards.
430+
// Otherwise, additionalLogic is called.
431+
// If you called 'WithUIDs(...)' on the ComplexEnvironmentBuilder AND 'WithFakeClientBuilderCall(..., "WithInterceptorFuncs", ...)', then you need to pass this function into the interceptor.Funcs' Create field, optionally adding your own creation logic via additionalLogic.
432+
func InjectUIDOnObjectCreation(additionalLogic func(ctx context.Context, client client.WithWatch, obj client.Object, opts ...client.CreateOption) error) func(ctx context.Context, client client.WithWatch, obj client.Object, opts ...client.CreateOption) error {
433+
return func(ctx context.Context, client client.WithWatch, obj client.Object, opts ...client.CreateOption) error {
434+
if obj.GetUID() == "" {
435+
obj.SetUID(uuid.NewUUID())
436+
}
437+
if additionalLogic != nil {
438+
return additionalLogic(ctx, client, obj, opts...)
439+
}
440+
return client.Create(ctx, obj, opts...)
441+
}
442+
}

pkg/testing/environment.go

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -153,6 +153,16 @@ func (eb *EnvironmentBuilder) WithAfterClientCreationCallback(callback func(clie
153153
return eb
154154
}
155155

156+
// WithUIDs enables UID injection.
157+
// All objects that are initially loaded or afterwards created via the client's 'Create' method will have a random UID injected, if they do not already have one.
158+
// Note that this function registers an interceptor function, which will be overwritten if 'WithFakeClientBuilderCall("WithInterceptorFuncs", ...)' is also called.
159+
// This would lead to newly created objects not having a UID injected.
160+
// To avoid this, pass 'InjectUIDOnObjectCreation(...)' into the interceptor.Funcs' Create field. The argument allows to inject your own additional Create logic, if desired.
161+
func (eb *EnvironmentBuilder) WithUIDs() *EnvironmentBuilder {
162+
eb.ComplexEnvironmentBuilder.WithUIDs(SimpleEnvironmentDefaultKey)
163+
return eb
164+
}
165+
156166
// WithFakeClientBuilderCall allows to inject method calls to fake.ClientBuilder when the fake client is created during Build().
157167
// The fake client is usually created using WithScheme(...).WithObjects(...).WithStatusSubresource(...).Build().
158168
// This function allows to inject additional method calls. It is only required for advanced use-cases.

0 commit comments

Comments
 (0)