Skip to content

ServiceInstance External-Name Handling#311

Open
Kukkerem wants to merge 4 commits into
mainfrom
external-name-comp-serviceinstance
Open

ServiceInstance External-Name Handling#311
Kukkerem wants to merge 4 commits into
mainfrom
external-name-comp-serviceinstance

Conversation

@Kukkerem

Copy link
Copy Markdown
Contributor

Closes: #246

  1. Implemented correct external-name handling in Create and Delete function
  2. Adapted Unit Tests for Create and Delete function
  3. Created E2E Import Test
  4. Created Upgrade Test for External-Name Behavior
  5. Added documentation

Signed-off-by: Zoltan Szabo <zoltan.szabo03@sap.com>
@Kukkerem Kukkerem self-assigned this Jun 16, 2026
Comment thread apis/resources/v1alpha1/serviceinstance_types.go Outdated
Comment thread internal/controller/serviceinstance/controller_test.go
Comment thread test/upgrade/service_instance_external_name_upgrade_test.go Outdated
Signed-off-by: Zoltan Szabo <zoltan.szabo03@sap.com>

@SatabdiG SatabdiG left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Good work, Some comments from my side.

// - Follows Standard: yes
// - Format: ServiceInstance GUID (UUID format)
// - How to find:
// - UI: In the BTP Cockpit, navigate to your service instance; the GUID is the ID in the URL

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think there is an indentation off here, UI and CLI are children of How to find right?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Other resources has the same because gofmt rewrites the comment in case of nesting. We could definitely work on this, but currently gofmt would fail.


// MatchSingle retrieves external resource by matching CR's ForProvider spec
func (c *Client) MatchSingle(ctx context.Context, spec v1alpha1.ServiceInstanceParameters) (*resource.ServiceInstance, error) {
// Backward-compat lookup requires at least a name to match on.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I know you didn't touch this part, but reading it together, we might have a bug.

I see pollJobComplete intentionally swallows async timeout errors (comment explains this is by design, deferring to later state observation), and the subsequent MatchSingle call returns (nil, nil) when no match is found yet — treating "not visible yet" the same as "doesn't exist".

So c.serviceinstance.Create can return (nil, nil) for a managed service instance whose creation is still in progress when the poll times out. err is nil, so the guard above doesn't catch it, and r.GUID panics.

Maybe we can safeguard it here, make external name handling more robust, what do you think?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Very true, fixed with a new UT!

return managed.ExternalDelete{}, errors.New(errDelete)
// ADR: the external-name (GUID) identifies the resource to delete; nothing to do if unset.
guid := meta.GetExternalName(cr)
if guid == "" {

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

minor: Should we also validate the guid here? Worse case here is CF-side crash but still.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Good point, fixed as well.

@@ -140,19 +140,25 @@ func (c *external) Observe(ctx context.Context, mg resource.Managed) (managed.Ex
return managed.ExternalObservation{}, errors.New(errWrongCRType)
}

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nit: You didn;t touch part of this code:

if _, err := uuid.Parse(guid); err == nil {
		// We have a valid external-name annotation
		return nil
	}

but should we replace uuid.Parse(guid) with clients.IsValidGUID for a single source of truth on what counts as a valid external-nam

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

True, fixed, dropped the now unused uuid.

},
want: want{
mg: serviceInstance("managed", withExternalName(guid)),
mg: serviceInstance("managed", withExternalName(guid), withSpace(spaceGUID), withServicePlan(v1alpha1.ServicePlanParameters{ID: &servicePlan})),

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I see TestObserve, TestCreate, TestCreate case structs declare the kube k8s.Client.

But the test runner never reads tc.kube; it always constructs a hardcoded &test.MockClient{MockUpdate: test.NewMockUpdateFn(nil)}. Wouldn't that mean there's currently no way to simulate c.kube.Update failing? So in return the Observe's adoption path (meta.SetExternalName + c.kube.Update) and postCreate (c.kube.Update then c.kube.Status().Update) both have an errUpdateCR error path that would never exercised?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Good catch, fixed!


serviceInstance := &v1alpha1.ServiceInstance{}

err = r.Get(ctx, serviceInstanceName, cfg.Namespace(), serviceInstance)

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should we also use SchemeBuilder here same as PreUpgrade

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

AddToScheme already covers PostUpgrade I think, same as in the other resources, but we could mirror App if that's preferred.

Signed-off-by: Zoltan Szabo <zoltan.szabo03@sap.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[TASK] External Name (ServiceInstance): Ensure ADR Compliance

3 participants