Skip to content

Commit b164bc7

Browse files
committed
WIP: Implement actuator
1 parent 8f8edca commit b164bc7

2 files changed

Lines changed: 33 additions & 115 deletions

File tree

internal/controllers/applicationcredential/actuator.go

Lines changed: 17 additions & 90 deletions
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,6 @@ import (
2929
orcv1alpha1 "github.com/k-orc/openstack-resource-controller/v2/api/v1alpha1"
3030
"github.com/k-orc/openstack-resource-controller/v2/internal/controllers/generic/interfaces"
3131
"github.com/k-orc/openstack-resource-controller/v2/internal/controllers/generic/progress"
32-
"github.com/k-orc/openstack-resource-controller/v2/internal/logging"
3332
"github.com/k-orc/openstack-resource-controller/v2/internal/osclients"
3433
orcerrors "github.com/k-orc/openstack-resource-controller/v2/internal/util/errors"
3534
)
@@ -70,30 +69,23 @@ func (actuator applicationcredentialActuator) ListOSResourcesForAdoption(ctx con
7069
return nil, false
7170
}
7271

73-
// TODO(scaffolding) If you need to filter resources on fields that the List() function
74-
// of gophercloud does not support, it's possible to perform client-side filtering.
75-
// Check osclients.ResourceFilter
72+
// TODO: Filter by ID? Client side filtering using Check osclients.ResourceFilter?
7673

7774
listOpts := applicationcredentials.ListOpts{
78-
Name: getResourceName(orcObject),
79-
Description: ptr.Deref(resourceSpec.Description, ""),
75+
Name: getResourceName(orcObject),
8076
}
8177

82-
return actuator.osClient.ListApplicationCredentials(ctx, listOpts), true
78+
return actuator.osClient.ListApplicationCredentials(ctx, resourceSpec.UserID, listOpts), true
8379
}
8480

8581
func (actuator applicationcredentialActuator) ListOSResourcesForImport(ctx context.Context, obj orcObjectPT, filter filterT) (iter.Seq2[*osResourceT, error], progress.ReconcileStatus) {
86-
// TODO(scaffolding) If you need to filter resources on fields that the List() function
87-
// of gophercloud does not support, it's possible to perform client-side filtering.
88-
// Check osclients.ResourceFilter
82+
// TODO: Filter by ID? Client side filtering using Check osclients.ResourceFilter?
8983

9084
listOpts := applicationcredentials.ListOpts{
91-
Name: string(ptr.Deref(filter.Name, "")),
92-
Description: string(ptr.Deref(filter.Description, "")),
93-
// TODO(scaffolding): Add more import filters
85+
Name: string(ptr.Deref(filter.Name, "")),
9486
}
9587

96-
return actuator.osClient.ListApplicationCredentials(ctx, listOpts), nil
88+
return actuator.osClient.ListApplicationCredentials(ctx, filter.UserID, listOpts), nil
9789
}
9890

9991
func (actuator applicationcredentialActuator) CreateResource(ctx context.Context, obj orcObjectPT) (*osResourceT, progress.ReconcileStatus) {
@@ -105,12 +97,16 @@ func (actuator applicationcredentialActuator) CreateResource(ctx context.Context
10597
orcerrors.Terminal(orcv1alpha1.ConditionReasonInvalidConfiguration, "Creation requested, but spec.resource is not set"))
10698
}
10799
createOpts := applicationcredentials.CreateOpts{
108-
Name: getResourceName(obj),
109-
Description: ptr.Deref(resource.Description, ""),
110-
// TODO(scaffolding): Add more fields
100+
Name: getResourceName(obj),
101+
Description: ptr.Deref(resource.Description, ""),
102+
Unrestricted: ptr.Deref(resource.Unrestricted, false),
103+
Secret: ptr.Deref(resource.Secret, ""),
104+
// TODO: ExpiresAt
105+
// TODO: Roles
106+
// TODO: AccessRules
111107
}
112108

113-
osResource, err := actuator.osClient.CreateApplicationCredential(ctx, createOpts)
109+
osResource, err := actuator.osClient.CreateApplicationCredential(ctx, resource.UserID, createOpts)
114110
if err != nil {
115111
// We should require the spec to be updated before retrying a create which returned a conflict
116112
if !orcerrors.IsRetryable(err) {
@@ -123,81 +119,12 @@ func (actuator applicationcredentialActuator) CreateResource(ctx context.Context
123119
}
124120

125121
func (actuator applicationcredentialActuator) DeleteResource(ctx context.Context, _ orcObjectPT, resource *osResourceT) progress.ReconcileStatus {
126-
return progress.WrapError(actuator.osClient.DeleteApplicationCredential(ctx, resource.ID))
127-
}
128-
129-
func (actuator applicationcredentialActuator) updateResource(ctx context.Context, obj orcObjectPT, osResource *osResourceT) progress.ReconcileStatus {
130-
log := ctrl.LoggerFrom(ctx)
131-
resource := obj.Spec.Resource
132-
if resource == nil {
133-
// Should have been caught by API validation
134-
return progress.WrapError(
135-
orcerrors.Terminal(orcv1alpha1.ConditionReasonInvalidConfiguration, "Update requested, but spec.resource is not set"))
136-
}
137-
138-
updateOpts := applicationcredentials.UpdateOpts{}
139-
140-
handleNameUpdate(&updateOpts, obj, osResource)
141-
handleDescriptionUpdate(&updateOpts, resource, osResource)
142-
143-
// TODO(scaffolding): add handler for all fields supporting mutability
144-
145-
needsUpdate, err := needsUpdate(updateOpts)
146-
if err != nil {
147-
return progress.WrapError(
148-
orcerrors.Terminal(orcv1alpha1.ConditionReasonInvalidConfiguration, "invalid configuration updating resource: "+err.Error(), err))
149-
}
150-
if !needsUpdate {
151-
log.V(logging.Debug).Info("No changes")
152-
return nil
153-
}
154-
155-
_, err = actuator.osClient.UpdateApplicationCredential(ctx, osResource.ID, updateOpts)
156-
157-
// We should require the spec to be updated before retrying an update which returned a conflict
158-
if orcerrors.IsConflict(err) {
159-
err = orcerrors.Terminal(orcv1alpha1.ConditionReasonInvalidConfiguration, "invalid configuration updating resource: "+err.Error(), err)
160-
}
161-
162-
if err != nil {
163-
return progress.WrapError(err)
164-
}
165-
166-
return progress.NeedsRefresh()
167-
}
168-
169-
func needsUpdate(updateOpts applicationcredentials.UpdateOpts) (bool, error) {
170-
updateOptsMap, err := updateOpts.ToApplicationCredentialUpdateMap()
171-
if err != nil {
172-
return false, err
173-
}
174-
175-
updateMap, ok := updateOptsMap["application_credential"].(map[string]any)
176-
if !ok {
177-
updateMap = make(map[string]any)
178-
}
179-
180-
return len(updateMap) > 0, nil
181-
}
182-
183-
func handleNameUpdate(updateOpts *applicationcredentials.UpdateOpts, obj orcObjectPT, osResource *osResourceT) {
184-
name := getResourceName(obj)
185-
if osResource.Name != name {
186-
updateOpts.Name = &name
187-
}
188-
}
189-
190-
func handleDescriptionUpdate(updateOpts *applicationcredentials.UpdateOpts, resource *resourceSpecT, osResource *osResourceT) {
191-
description := ptr.Deref(resource.Description, "")
192-
if osResource.Description != description {
193-
updateOpts.Description = &description
194-
}
122+
return progress.WrapError(actuator.osClient.DeleteApplicationCredential(ctx, resource.resource.ID))
195123
}
196124

197125
func (actuator applicationcredentialActuator) GetResourceReconcilers(ctx context.Context, orcObject orcObjectPT, osResource *osResourceT, controller interfaces.ResourceController) ([]resourceReconciler, progress.ReconcileStatus) {
198-
return []resourceReconciler{
199-
actuator.updateResource,
200-
}, nil
126+
// ApplicationCredentials are immutable - no update reconcilers needed
127+
return []resourceReconciler{}, nil
201128
}
202129

203130
type applicationcredentialHelperFactory struct{}

internal/osclients/applicationcredential.go

Lines changed: 16 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -28,11 +28,10 @@ import (
2828
)
2929

3030
type ApplicationCredentialClient interface {
31-
ListApplicationCredentials(ctx context.Context, listOpts applicationcredentials.ListOptsBuilder) iter.Seq2[*applicationcredentials.ApplicationCredential, error]
32-
CreateApplicationCredential(ctx context.Context, opts applicationcredentials.CreateOptsBuilder) (*applicationcredentials.ApplicationCredential, error)
33-
DeleteApplicationCredential(ctx context.Context, resourceID string) error
34-
GetApplicationCredential(ctx context.Context, resourceID string) (*applicationcredentials.ApplicationCredential, error)
35-
UpdateApplicationCredential(ctx context.Context, id string, opts applicationcredentials.UpdateOptsBuilder) (*applicationcredentials.ApplicationCredential, error)
31+
ListApplicationCredentials(ctx context.Context, userID string, listOpts applicationcredentials.ListOptsBuilder) iter.Seq2[*applicationcredentials.ApplicationCredential, error]
32+
CreateApplicationCredential(ctx context.Context, userID string, opts applicationcredentials.CreateOptsBuilder) (*applicationcredentials.ApplicationCredential, error)
33+
DeleteApplicationCredential(ctx context.Context, userID string, resourceID string) error
34+
GetApplicationCredential(ctx context.Context, userID string, resourceID string) (*applicationcredentials.ApplicationCredential, error)
3635
}
3736

3837
type applicationcredentialClient struct{ client *gophercloud.ServiceClient }
@@ -51,27 +50,23 @@ func NewApplicationCredentialClient(providerClient *gophercloud.ProviderClient,
5150
return &applicationcredentialClient{client}, nil
5251
}
5352

54-
func (c applicationcredentialClient) ListApplicationCredentials(ctx context.Context, listOpts applicationcredentials.ListOptsBuilder) iter.Seq2[*applicationcredentials.ApplicationCredential, error] {
55-
pager := applicationcredentials.List(c.client, listOpts)
53+
func (c applicationcredentialClient) ListApplicationCredentials(ctx context.Context, userID string, listOpts applicationcredentials.ListOptsBuilder) iter.Seq2[*applicationcredentials.ApplicationCredential, error] {
54+
pager := applicationcredentials.List(c.client, userID, listOpts)
5655
return func(yield func(*applicationcredentials.ApplicationCredential, error) bool) {
5756
_ = pager.EachPage(ctx, yieldPage(applicationcredentials.ExtractApplicationCredentials, yield))
5857
}
5958
}
6059

61-
func (c applicationcredentialClient) CreateApplicationCredential(ctx context.Context, opts applicationcredentials.CreateOptsBuilder) (*applicationcredentials.ApplicationCredential, error) {
62-
return applicationcredentials.Create(ctx, c.client, opts).Extract()
60+
func (c applicationcredentialClient) CreateApplicationCredential(ctx context.Context, userID string, opts applicationcredentials.CreateOptsBuilder) (*applicationcredentials.ApplicationCredential, error) {
61+
return applicationcredentials.Create(ctx, c.client, userID, opts).Extract()
6362
}
6463

65-
func (c applicationcredentialClient) DeleteApplicationCredential(ctx context.Context, resourceID string) error {
66-
return applicationcredentials.Delete(ctx, c.client, resourceID).ExtractErr()
64+
func (c applicationcredentialClient) DeleteApplicationCredential(ctx context.Context, userID string, resourceID string) error {
65+
return applicationcredentials.Delete(ctx, c.client, userID, resourceID).ExtractErr()
6766
}
6867

69-
func (c applicationcredentialClient) GetApplicationCredential(ctx context.Context, resourceID string) (*applicationcredentials.ApplicationCredential, error) {
70-
return applicationcredentials.Get(ctx, c.client, resourceID).Extract()
71-
}
72-
73-
func (c applicationcredentialClient) UpdateApplicationCredential(ctx context.Context, id string, opts applicationcredentials.UpdateOptsBuilder) (*applicationcredentials.ApplicationCredential, error) {
74-
return applicationcredentials.Update(ctx, c.client, id, opts).Extract()
68+
func (c applicationcredentialClient) GetApplicationCredential(ctx context.Context, userID string, resourceID string) (*applicationcredentials.ApplicationCredential, error) {
69+
return applicationcredentials.Get(ctx, c.client, userID, resourceID).Extract()
7570
}
7671

7772
type applicationcredentialErrorClient struct{ error }
@@ -81,24 +76,20 @@ func NewApplicationCredentialErrorClient(e error) ApplicationCredentialClient {
8176
return applicationcredentialErrorClient{e}
8277
}
8378

84-
func (e applicationcredentialErrorClient) ListApplicationCredentials(_ context.Context, _ applicationcredentials.ListOptsBuilder) iter.Seq2[*applicationcredentials.ApplicationCredential, error] {
79+
func (e applicationcredentialErrorClient) ListApplicationCredentials(_ context.Context, _ string, _ applicationcredentials.ListOptsBuilder) iter.Seq2[*applicationcredentials.ApplicationCredential, error] {
8580
return func(yield func(*applicationcredentials.ApplicationCredential, error) bool) {
8681
yield(nil, e.error)
8782
}
8883
}
8984

90-
func (e applicationcredentialErrorClient) CreateApplicationCredential(_ context.Context, _ applicationcredentials.CreateOptsBuilder) (*applicationcredentials.ApplicationCredential, error) {
85+
func (e applicationcredentialErrorClient) CreateApplicationCredential(_ context.Context, _ string, _ applicationcredentials.CreateOptsBuilder) (*applicationcredentials.ApplicationCredential, error) {
9186
return nil, e.error
9287
}
9388

94-
func (e applicationcredentialErrorClient) DeleteApplicationCredential(_ context.Context, _ string) error {
89+
func (e applicationcredentialErrorClient) DeleteApplicationCredential(_ context.Context, _ string, _ string) error {
9590
return e.error
9691
}
9792

98-
func (e applicationcredentialErrorClient) GetApplicationCredential(_ context.Context, _ string) (*applicationcredentials.ApplicationCredential, error) {
99-
return nil, e.error
100-
}
101-
102-
func (e applicationcredentialErrorClient) UpdateApplicationCredential(_ context.Context, _ string, _ applicationcredentials.UpdateOptsBuilder) (*applicationcredentials.ApplicationCredential, error) {
93+
func (e applicationcredentialErrorClient) GetApplicationCredential(_ context.Context, _ string, _ string) (*applicationcredentials.ApplicationCredential, error) {
10394
return nil, e.error
10495
}

0 commit comments

Comments
 (0)