Skip to content

Commit 2b09c8a

Browse files
authored
Use an uncached client to retrieve composed resources not found in the cache (crossplane#6261)
* Do not cache Unstructured resources Fixes crossplane#6260 Signed-off-by: Bob Haddleton <[email protected]> * Use a no-cache client to retrieve not-found composed resources Signed-off-by: Bob Haddleton <[email protected]> * refactor variable names Signed-off-by: Bob Haddleton <[email protected]> --------- Signed-off-by: Bob Haddleton <[email protected]>
1 parent c103f21 commit 2b09c8a

File tree

16 files changed

+432
-145
lines changed

16 files changed

+432
-145
lines changed

.gitignore

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,8 @@ cover.out
99
/.vendor-new
1010
.DS_Store
1111
Zone.Identifier
12+
.tmp-earthly-out/
13+
build/
1214

1315
# gitlab example
1416
# exclude files generate by running the example

cmd/crossplane/core/core.go

Lines changed: 14 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -346,7 +346,7 @@ func (c *startCommand) Run(s *runtime.Scheme, log logging.Logger) error { //noli
346346
log.Info("API extensions cache stopped")
347347
}()
348348

349-
cl, err := client.New(mgr.GetConfig(), client.Options{
349+
cached, err := client.New(mgr.GetConfig(), client.Options{
350350
HTTPClient: mgr.GetHTTPClient(),
351351
Scheme: mgr.GetScheme(),
352352
Mapper: mgr.GetRESTMapper(),
@@ -364,13 +364,25 @@ func (c *startCommand) Run(s *runtime.Scheme, log logging.Logger) error { //noli
364364
return errors.Wrap(err, "cannot create client for API extension controllers")
365365
}
366366

367+
// Create a separate no-cache client for use when the composite controller does not find an Unstructured
368+
// resource that it expects to find in the cache.
369+
uncached, err := client.New(mgr.GetConfig(), client.Options{
370+
HTTPClient: mgr.GetHTTPClient(),
371+
Scheme: mgr.GetScheme(),
372+
Mapper: mgr.GetRESTMapper(),
373+
})
374+
if err != nil {
375+
return errors.Wrap(err, "cannot create uncached client for API extension controllers")
376+
}
377+
367378
// It's important the engine's client is wrapped with unstructured.NewClient
368379
// because controller-runtime always caches *unstructured.Unstructured, not
369380
// our wrapper types like *composite.Unstructured. This client takes care of
370381
// automatically wrapping and unwrapping *unstructured.Unstructured.
371382
ce := engine.New(mgr,
372383
engine.TrackInformers(ca, mgr.GetScheme()),
373-
unstructured.NewClient(cl),
384+
unstructured.NewClient(cached),
385+
unstructured.NewClient(uncached),
374386
engine.WithLogger(log),
375387
)
376388

internal/controller/apiextensions/composite/composition_functions.go

Lines changed: 18 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -217,18 +217,18 @@ func WithManagedFieldsUpgrader(u ManagedFieldsUpgrader) FunctionComposerOption {
217217

218218
// NewFunctionComposer returns a new Composer that supports composing resources using
219219
// both Patch and Transform (P&T) logic and a pipeline of Composition Functions.
220-
func NewFunctionComposer(kube client.Client, r FunctionRunner, o ...FunctionComposerOption) *FunctionComposer {
221-
f := NewSecretConnectionDetailsFetcher(kube)
220+
func NewFunctionComposer(cached, uncached client.Client, r FunctionRunner, o ...FunctionComposerOption) *FunctionComposer {
221+
f := NewSecretConnectionDetailsFetcher(cached)
222222

223223
c := &FunctionComposer{
224-
client: kube,
224+
client: cached,
225225

226226
composite: xr{
227227
ConnectionDetailsFetcher: f,
228-
ComposedResourceObserver: NewExistingComposedResourceObserver(kube, f),
229-
ComposedResourceGarbageCollector: NewDeletingComposedResourceGarbageCollector(kube),
230-
NameGenerator: names.NewNameGenerator(kube),
231-
ManagedFieldsUpgrader: NewPatchingManagedFieldsUpgrader(kube),
228+
ComposedResourceObserver: NewExistingComposedResourceObserver(cached, uncached, f),
229+
ComposedResourceGarbageCollector: NewDeletingComposedResourceGarbageCollector(cached),
230+
NameGenerator: names.NewNameGenerator(cached),
231+
ManagedFieldsUpgrader: NewPatchingManagedFieldsUpgrader(cached),
232232
},
233233

234234
pipeline: r,
@@ -580,14 +580,15 @@ func ComposedFieldOwnerName(xr *composite.Unstructured) string {
580580
// any existing composed resources from the API server. It also loads their
581581
// connection details.
582582
type ExistingComposedResourceObserver struct {
583-
resource client.Reader
583+
cached client.Reader
584+
uncached client.Reader
584585
details managed.ConnectionDetailsFetcher
585586
}
586587

587588
// NewExistingComposedResourceObserver returns a ComposedResourceGetter that
588589
// fetches an XR's existing composed resources.
589-
func NewExistingComposedResourceObserver(c client.Reader, f managed.ConnectionDetailsFetcher) *ExistingComposedResourceObserver {
590-
return &ExistingComposedResourceObserver{resource: c, details: f}
590+
func NewExistingComposedResourceObserver(c, uc client.Reader, f managed.ConnectionDetailsFetcher) *ExistingComposedResourceObserver {
591+
return &ExistingComposedResourceObserver{cached: c, uncached: uc, details: f}
591592
}
592593

593594
// ObserveComposedResources begins building composed resource state by
@@ -613,10 +614,14 @@ func (g *ExistingComposedResourceObserver) ObserveComposedResources(ctx context.
613614

614615
r := composed.New(composed.FromReference(ref))
615616
nn := types.NamespacedName{Namespace: ref.Namespace, Name: ref.Name}
616-
err := g.resource.Get(ctx, nn, r)
617+
err := g.cached.Get(ctx, nn, r)
617618
if kerrors.IsNotFound(err) {
618-
// We believe we created this resource, but it doesn't exist.
619-
continue
619+
// We believe we created this resource, but it is not in the cache yet? Try again without the cache.
620+
err = g.uncached.Get(ctx, nn, r)
621+
if kerrors.IsNotFound(err) {
622+
// We believe we created this resource, but it no longer exists.
623+
continue
624+
}
620625
}
621626
if err != nil {
622627
return nil, errors.Wrap(err, errGetComposed)

0 commit comments

Comments
 (0)