Skip to content

Commit dc97391

Browse files
authored
Merge pull request #103 from SAP/fix/si-importing
fix: fixing crash for external-name imported ServiceInstances
2 parents 011ea99 + 4a2e876 commit dc97391

2 files changed

Lines changed: 45 additions & 40 deletions

File tree

internal/clients/serviceinstance/serviceinstance.go

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -311,13 +311,13 @@ func UpdateObservation(in *v1alpha1.ServiceInstanceObservation, r *resource.Serv
311311

312312
// IsUpToDate checks if the managed resource is in sync with CR.
313313
func IsUpToDate(in *v1alpha1.ServiceInstanceParameters, observed *resource.ServiceInstance) bool {
314-
if *in.Name != observed.Name {
314+
if in.Name != nil && *in.Name != observed.Name {
315315
return false
316316
}
317317

318318
switch in.Type {
319319
case v1alpha1.ManagedService:
320-
if in.ServicePlan.ID != nil && observed.Relationships.ServicePlan.Data.GUID != *in.ServicePlan.ID {
320+
if in.ServicePlan != nil && in.ServicePlan.ID != nil && observed.Relationships.ServicePlan.Data.GUID != *in.ServicePlan.ID {
321321
return false
322322
}
323323
case v1alpha1.UserProvidedService:

internal/controller/serviceinstance/controller.go

Lines changed: 43 additions & 38 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,6 @@ import (
44
"bytes"
55
"context"
66
"crypto/sha256"
7-
"encoding/json"
87
"time"
98

109
"github.com/cloudfoundry/go-cfclient/v3/client"
@@ -16,6 +15,7 @@ import (
1615
"github.com/crossplane/crossplane-runtime/pkg/ratelimiter"
1716
"github.com/crossplane/crossplane-runtime/pkg/reconciler/managed"
1817
"github.com/crossplane/crossplane-runtime/pkg/resource"
18+
"github.com/google/uuid"
1919
"github.com/nsf/jsondiff"
2020
"github.com/pkg/errors"
2121
ctrl "sigs.k8s.io/controller-runtime"
@@ -31,19 +31,20 @@ import (
3131
)
3232

3333
const (
34-
resourceType = "ServiceInstance"
35-
externalSystem = "Cloud Foundry"
36-
errTrackPCUsage = "cannot track ProviderConfig usage"
37-
errNewClient = "cannot create a client for " + externalSystem
38-
errWrongCRType = "managed resource is not a " + resourceType
39-
errUpdateCR = "cannot update the managed resource"
40-
errGet = "cannot get " + resourceType + " in " + externalSystem
41-
errCreate = "cannot create " + resourceType + " in " + externalSystem
42-
errUpdate = "cannot update " + resourceType + " in " + externalSystem
43-
errDelete = "cannot delete " + resourceType + " in " + externalSystem
44-
errCleanFailed = "cannot delete failed service instance"
45-
errSecret = "cannot resolve secret reference"
46-
errGetParameters = "cannot get parameters of the service instance for drift detection. Please check this is supported or set enableParameterDriftDetection to false."
34+
resourceType = "ServiceInstance"
35+
externalSystem = "Cloud Foundry"
36+
errTrackPCUsage = "cannot track ProviderConfig usage"
37+
errNewClient = "cannot create a client for " + externalSystem
38+
errWrongCRType = "managed resource is not a " + resourceType
39+
errUpdateCR = "cannot update the managed resource"
40+
errGet = "cannot get " + resourceType + " in " + externalSystem
41+
errCreate = "cannot create " + resourceType + " in " + externalSystem
42+
errUpdate = "cannot update " + resourceType + " in " + externalSystem
43+
errDelete = "cannot delete " + resourceType + " in " + externalSystem
44+
errCleanFailed = "cannot delete failed service instance"
45+
errSecret = "cannot resolve secret reference"
46+
errGetParameters = "cannot get parameters of the service instance for drift detection. Please check this is supported or set enableParameterDriftDetection to false."
47+
errMissingServicePlan = "managed resource service instance requires a service plan"
4748
)
4849

4950
// Setup adds a controller that reconciles ServiceInstance CR.
@@ -374,37 +375,41 @@ func (s servicePlanInitializer) Initialize(ctx context.Context, mg resource.Mana
374375
return nil
375376
}
376377

377-
if cr.Spec.ForProvider.ServicePlan == nil {
378-
// fallback on crossplane.io/external-data annotation for backward compatibility
379-
sp := struct {
380-
ServicePlan *v1alpha1.ServicePlanParameters `json:"service_plan"`
381-
}{ServicePlan: &v1alpha1.ServicePlanParameters{}}
378+
if cr.Spec.ForProvider.ServicePlan != nil {
379+
// When ServicePlan is set we populate the service
380+
// plan ID based on the external resource GUID.
381+
cf, err := clients.ClientFnBuilder(ctx, s.kube)(mg)
382+
if err != nil {
383+
return errors.Wrapf(err, errNewClient)
384+
}
382385

383-
if data, ok := mg.GetAnnotations()["crossplane.io/external-data"]; ok {
384-
if err := json.Unmarshal([]byte(data), &sp); err == nil {
385-
cr.Spec.ForProvider.ServicePlan = sp.ServicePlan
386-
}
386+
opt := client.NewServicePlanListOptions()
387+
if cr.Spec.ForProvider.ServicePlan.Offering != nil {
388+
opt.ServiceOfferingNames.EqualTo(*cr.Spec.ForProvider.ServicePlan.Offering)
389+
}
390+
if cr.Spec.ForProvider.ServicePlan.Plan != nil {
391+
opt.Names.EqualTo(*cr.Spec.ForProvider.ServicePlan.Plan)
392+
}
393+
sp, err := cf.ServicePlans.Single(ctx, opt)
394+
if err != nil {
395+
return errors.Wrapf(err, "Cannot initialize service plan using serviceName/servicePlanName: %s:%s`", *cr.Spec.ForProvider.ServicePlan.Offering, *cr.Spec.ForProvider.ServicePlan.Plan)
387396
}
388-
}
389397

390-
// Lookup service plan during every reconciliation to detect an update service_plan of existing service.
391-
cf, err := clients.ClientFnBuilder(ctx, s.kube)(mg)
392-
if err != nil {
393-
return errors.Wrapf(err, errNewClient)
394-
}
395-
opt := client.NewServicePlanListOptions()
396-
opt.ServiceOfferingNames.EqualTo(*cr.Spec.ForProvider.ServicePlan.Offering)
397-
opt.Names.EqualTo(*cr.Spec.ForProvider.ServicePlan.Plan)
398+
cr.Spec.ForProvider.ServicePlan.ID = &sp.GUID
398399

399-
// There must be exactly one matching service plan
400-
sp, err := cf.ServicePlans.Single(ctx, opt)
401-
if err != nil {
402-
return errors.Wrapf(err, "Cannot initialize service plan using serviceName/servicePlanName: %s:%s`", *cr.Spec.ForProvider.ServicePlan.Offering, *cr.Spec.ForProvider.ServicePlan.Plan)
400+
return s.kube.Update(ctx, cr)
403401
}
404402

405-
cr.Spec.ForProvider.ServicePlan.ID = &sp.GUID
403+
// Service plan is not set
404+
guid := meta.GetExternalName(cr)
405+
406+
if _, err := uuid.Parse(guid); err == nil {
407+
// We have a valid external-name annotation
408+
return nil
409+
}
406410

407-
return s.kube.Update(ctx, cr)
411+
// No valid external-name annotation
412+
return errors.New(errMissingServicePlan)
408413
}
409414

410415
// Small wrapper around sha256.Sum256()

0 commit comments

Comments
 (0)