Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions apis/resources/v1alpha1/servicecredentialbinding_types.go
Original file line number Diff line number Diff line change
Expand Up @@ -109,6 +109,8 @@ type ServiceCredentialBindingStatus struct {
type SCBResource struct {
// The GUID of the Cloud Foundry resource
GUID string `json:"guid,omitempty"`
// The name of the Cloud Foundry resource
Name string `json:"name,omitempty"`
Comment thread
lennardrother marked this conversation as resolved.
// The date and time when the resource was created.
CreatedAt *metav1.Time `json:"createdAt,omitempty"`
}
Expand Down
2 changes: 2 additions & 0 deletions internal/clients/servicecredentialbinding/keyrotator.go
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ import (
cfresource "github.com/cloudfoundry/go-cfclient/v3/resource"
"github.com/crossplane/crossplane-runtime/v2/pkg/meta"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/utils/ptr"

"github.com/SAP/crossplane-provider-cloudfoundry/apis/resources/v1alpha1"
)
Expand Down Expand Up @@ -55,6 +56,7 @@ func (r *SCBKeyRotator) RetireBinding(cr *v1alpha1.ServiceCredentialBinding, ser
}
cr.Status.AtProvider.RetiredKeys = append(cr.Status.AtProvider.RetiredKeys, &v1alpha1.SCBResource{
GUID: serviceBinding.GUID,
Name: ptr.Deref(serviceBinding.Name, ""), // only set during retirement; already retired keys are not backfilled
CreatedAt: &metav1.Time{Time: serviceBinding.CreatedAt},
})
return true
Expand Down
6 changes: 6 additions & 0 deletions internal/clients/servicecredentialbinding/keyrotator_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ import (
"github.com/google/go-cmp/cmp"
"github.com/stretchr/testify/mock"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/utils/ptr"

cfresource "github.com/cloudfoundry/go-cfclient/v3/resource"

Expand Down Expand Up @@ -84,6 +85,7 @@ func TestSCBKeyRotator_RetireBinding(t *testing.T) {

serviceBindingResource := &cfresource.ServiceCredentialBinding{
Resource: cfresource.Resource{GUID: "test-guid"},
Name: ptr.To("my-binding-abc12"),
}

cases := map[string]struct {
Expand Down Expand Up @@ -134,6 +136,10 @@ func TestSCBKeyRotator_RetireBinding(t *testing.T) {
for _, retiredKey := range tc.args.cr.Status.AtProvider.RetiredKeys {
if retiredKey.GUID == serviceBindingResource.GUID {
found = true
if retiredKey.Name != ptr.Deref(serviceBindingResource.Name, "") {
t.Errorf("RetireBinding(...): Name mismatch in retired key, want %q, got %q",
ptr.Deref(serviceBindingResource.Name, ""), retiredKey.Name)
}
break
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ import (
"github.com/crossplane/crossplane-runtime/v2/pkg/reconciler/managed"
xpresource "github.com/crossplane/crossplane-runtime/v2/pkg/resource"
"github.com/google/uuid"
"k8s.io/utils/ptr"

"github.com/SAP/crossplane-provider-cloudfoundry/apis/resources/v1alpha1"
"github.com/SAP/crossplane-provider-cloudfoundry/internal/clients/job"
Expand Down Expand Up @@ -222,6 +223,7 @@ func newUpdateOption(mg xpresource.Managed, forProvider v1alpha1.ServiceCredenti
// UpdateObservation updates the CR's AtProvider status from the observed resource
func UpdateObservation(observation *v1alpha1.ServiceCredentialBindingObservation, r *resource.ServiceCredentialBinding) {
observation.GUID = r.GUID
observation.Name = ptr.Deref(r.Name, "")
observation.LastOperation = &v1alpha1.LastOperation{
Type: r.LastOperation.Type,
State: r.LastOperation.State,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -376,30 +376,58 @@ func TestNewCreateOption(t *testing.T) {
}

func TestUpdateObservation(t *testing.T) {
observation := &v1alpha1.ServiceCredentialBindingObservation{}

now := time.Now()
resource := &cfresource.ServiceCredentialBinding{
Resource: cfresource.Resource{GUID: testGUID},
LastOperation: cfresource.LastOperation{
Type: v1alpha1.LastOperationCreate,
State: v1alpha1.LastOperationSucceeded,
Description: "Create succeeded",
UpdatedAt: now,
CreatedAt: now,

cases := map[string]struct {
resource *cfresource.ServiceCredentialBinding
wantName string
}{
"WithName": {
resource: &cfresource.ServiceCredentialBinding{
Resource: cfresource.Resource{GUID: testGUID},
Name: ptr.To("my-binding-abc12"),
LastOperation: cfresource.LastOperation{
Type: v1alpha1.LastOperationCreate,
State: v1alpha1.LastOperationSucceeded,
UpdatedAt: now,
CreatedAt: now,
},
},
wantName: "my-binding-abc12",
},
"WithoutName": {
resource: &cfresource.ServiceCredentialBinding{
Resource: cfresource.Resource{GUID: testGUID},
Name: nil,
LastOperation: cfresource.LastOperation{
Type: v1alpha1.LastOperationCreate,
State: v1alpha1.LastOperationSucceeded,
UpdatedAt: now,
CreatedAt: now,
},
},
wantName: "",
},
}

UpdateObservation(observation, resource)
for n, tc := range cases {
t.Run(n, func(t *testing.T) {
observation := &v1alpha1.ServiceCredentialBindingObservation{}
UpdateObservation(observation, tc.resource)

if observation.GUID != testGUID {
t.Errorf("UpdateObservation(...): GUID mismatch, want %s, got %s", testGUID, observation.GUID)
}
if observation.LastOperation.Type != v1alpha1.LastOperationCreate {
t.Errorf("UpdateObservation(...): LastOperation.Type mismatch")
}
if observation.LastOperation.State != v1alpha1.LastOperationSucceeded {
t.Errorf("UpdateObservation(...): LastOperation.State mismatch")
if observation.GUID != testGUID {
t.Errorf("UpdateObservation(...): GUID mismatch, want %s, got %s", testGUID, observation.GUID)
}
if observation.Name != tc.wantName {
t.Errorf("UpdateObservation(...): Name mismatch, want %q, got %q", tc.wantName, observation.Name)
}
if observation.LastOperation.Type != v1alpha1.LastOperationCreate {
t.Errorf("UpdateObservation(...): LastOperation.Type mismatch")
}
if observation.LastOperation.State != v1alpha1.LastOperationSucceeded {
t.Errorf("UpdateObservation(...): LastOperation.State mismatch")
}
})
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -81,6 +81,7 @@ func withObservedLabels(labels map[string]*string) modifier {
func withObservation(guid string, lastOp *v1alpha1.LastOperation) modifier {
return func(r *v1alpha1.ServiceCredentialBinding) {
r.Status.AtProvider.GUID = guid
r.Status.AtProvider.Name = name
r.Status.AtProvider.CreatedAt = &metav1.Time{}
r.Status.AtProvider.LastOperation = lastOp
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -456,6 +456,9 @@ spec:
was updated in RFC3339 format.
type: string
type: object
name:
description: The name of the Cloud Foundry resource
type: string
retiredKeys:
description: If the binding is rotated, `retiredBindings` stores
resources that have been rotated out but are still transitionally
Expand All @@ -469,6 +472,9 @@ spec:
guid:
description: The GUID of the Cloud Foundry resource
type: string
name:
description: The name of the Cloud Foundry resource
type: string
type: object
type: array
type: object
Expand Down
Loading