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
6 changes: 5 additions & 1 deletion api/v1alpha1/zz_generated.flavor-resource.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

6 changes: 5 additions & 1 deletion api/v1alpha1/zz_generated.image-resource.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

6 changes: 5 additions & 1 deletion api/v1alpha1/zz_generated.network-resource.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

6 changes: 5 additions & 1 deletion api/v1alpha1/zz_generated.port-resource.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

6 changes: 5 additions & 1 deletion api/v1alpha1/zz_generated.router-resource.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

6 changes: 5 additions & 1 deletion api/v1alpha1/zz_generated.securitygroup-resource.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

6 changes: 5 additions & 1 deletion api/v1alpha1/zz_generated.server-resource.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

6 changes: 5 additions & 1 deletion api/v1alpha1/zz_generated.subnet-resource.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

6 changes: 5 additions & 1 deletion cmd/resource-generator/data/api.template
Original file line number Diff line number Diff line change
Expand Up @@ -151,6 +151,10 @@ type {{ .Name }}List struct {
Items []{{ .Name }} `json:"items"`
}

func (l *{{ .Name }}List) GetItems() []{{ .Name }} {
return l.Items
}

func init() {
SchemeBuilder.Register(&{{ .Name }}{}, &{{ .Name }}List{})
}
Expand All @@ -163,4 +167,4 @@ func (i *{{ .Name }}) GetCloudCredentialsRef() (*string, *CloudCredentialsRefere
return &i.Namespace, &i.Spec.CloudCredentialsRef
}

var _ CloudCredentialsRefProvider = &{{ .Name }}{}
var _ CloudCredentialsRefProvider = &{{ .Name }}{}
2 changes: 1 addition & 1 deletion go.mod
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
module github.com/k-orc/openstack-resource-controller

go 1.22.0
go 1.23.0

require (
github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc
Expand Down
4 changes: 2 additions & 2 deletions internal/controllers/common/deletion_guard.go
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,7 @@ type pointerToObject[T any] interface {

func AddDeletionGuard[guardedP pointerToObject[guarded], dependencyP pointerToObject[dependency], guarded, dependency any](
mgr ctrl.Manager, finalizer string, fieldOwner client.FieldOwner,
getGuardedFromDependency func(client.Object) []string,
getGuardedRefsFromDependency func(client.Object) []string,
getDependenciesFromGuarded func(context.Context, client.Client, guardedP) ([]dependency, error),
) error {
// deletionGuard reconciles the guarded object
Expand Down Expand Up @@ -122,7 +122,7 @@ func AddDeletionGuard[guardedP pointerToObject[guarded], dependencyP pointerToOb
Watches(dependencySpecimen,
handler.Funcs{
DeleteFunc: func(ctx context.Context, evt event.TypedDeleteEvent[client.Object], q workqueue.TypedRateLimitingInterface[reconcile.Request]) {
for _, guarded := range getGuardedFromDependency(evt.Object) {
for _, guarded := range getGuardedRefsFromDependency(evt.Object) {
q.Add(reconcile.Request{
NamespacedName: types.NamespacedName{
Namespace: evt.Object.GetNamespace(),
Expand Down
5 changes: 3 additions & 2 deletions internal/controllers/flavor/actuator.go
Original file line number Diff line number Diff line change
Expand Up @@ -82,8 +82,9 @@ func (obj flavorActuator) GetOSResourceBySpec(ctx context.Context) (*flavors.Fla
return GetByFilter(ctx, obj.osClient, specToFilter(*obj.Spec.Resource))
}

func (obj flavorActuator) CreateResource(ctx context.Context) (*flavors.Flavor, error) {
return createResource(ctx, obj.Flavor, obj.osClient)
func (obj flavorActuator) CreateResource(ctx context.Context) ([]string, *flavors.Flavor, error) {
flavor, err := createResource(ctx, obj.Flavor, obj.osClient)
return nil, flavor, err
}

func (obj flavorActuator) DeleteResource(ctx context.Context, flavor *flavors.Flavor) error {
Expand Down
5 changes: 3 additions & 2 deletions internal/controllers/flavor/reconcile.go
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ import (
"context"
"errors"
"fmt"
"strings"

"github.com/gophercloud/gophercloud/v2/openstack/compute/v2/flavors"
apierrors "k8s.io/apimachinery/pkg/api/errors"
Expand Down Expand Up @@ -107,14 +108,14 @@ func (r *orcFlavorReconciler) reconcileNormal(ctx context.Context, orcObject *or
osClient: osClient,
}

osResource, err := generic.GetOrCreateOSResource(ctx, log, adapter)
waitMsgs, osResource, err := generic.GetOrCreateOSResource(ctx, log, r.client, adapter)
if err != nil {
return ctrl.Result{}, err
}

if osResource == nil {
log.V(3).Info("OpenStack resource does not yet exist")
addStatus(withProgressMessage("Waiting for OpenStack resource to be created externally"))
addStatus(withProgressMessage(strings.Join(waitMsgs, ", ")))
return ctrl.Result{RequeueAfter: externalUpdatePollingPeriod}, err
}

Expand Down
31 changes: 13 additions & 18 deletions internal/controllers/generic/actuator.go
Original file line number Diff line number Diff line change
Expand Up @@ -46,11 +46,11 @@ type ResourceActuator[osResourcePT any] interface {
GetOSResourceByImportFilter(ctx context.Context) (bool, osResourcePT, error)
GetOSResourceBySpec(ctx context.Context) (osResourcePT, error)

CreateResource(ctx context.Context) (osResourcePT, error)
CreateResource(ctx context.Context) ([]string, osResourcePT, error)
DeleteResource(ctx context.Context, osResource osResourcePT) error
}

func GetOrCreateOSResource[osResourcePT *osResourceT, osResourceT any](ctx context.Context, log logr.Logger, actuator ResourceActuator[osResourcePT]) (osResourcePT, error) {
func GetOrCreateOSResource[osResourcePT *osResourceT, osResourceT any](ctx context.Context, log logr.Logger, k8sClient client.Client, actuator ResourceActuator[osResourcePT]) ([]string, osResourcePT, error) {
// Get by status ID
if hasStatusID, osResource, err := actuator.GetOSResourceByStatusID(ctx); hasStatusID {
if orcerrors.IsNotFound(err) {
Expand All @@ -60,7 +60,7 @@ func GetOrCreateOSResource[osResourcePT *osResourceT, osResourceT any](ctx conte
if osResource != nil {
log.V(4).Info("Got existing OpenStack resource", "ID", actuator.GetResourceID(osResource))
}
return osResource, err
return nil, osResource, err
}

// Import by ID
Expand All @@ -72,43 +72,38 @@ func GetOrCreateOSResource[osResourcePT *osResourceT, osResourceT any](ctx conte
if osResource != nil {
log.V(4).Info("Imported existing OpenStack resource by ID", "ID", actuator.GetResourceID(osResource))
}
return osResource, err
return nil, osResource, err
}

// Import by filter
if hasImportFilter, osResource, err := actuator.GetOSResourceByImportFilter(ctx); hasImportFilter {
return osResource, err
var waitMsgs []string
if osResource == nil {
waitMsgs = []string{"Waiting for OpenStack resource to be created externally"}
}
return waitMsgs, osResource, err
}

// Create
if actuator.GetManagementPolicy() == orcv1alpha1.ManagementPolicyUnmanaged {
// We never create an unmanaged resource
// API validation should have ensured that one of the above functions returned
return nil, orcerrors.Terminal(orcv1alpha1.OpenStackConditionReasonInvalidConfiguration, "Not creating unmanaged resource")
return nil, nil, orcerrors.Terminal(orcv1alpha1.OpenStackConditionReasonInvalidConfiguration, "Not creating unmanaged resource")
}

osResource, err := actuator.GetOSResourceBySpec(ctx)
if err != nil {
return nil, err
return nil, nil, err
}
if osResource != nil {
log.V(4).Info("Adopted previously created resource")
return osResource, nil
return nil, osResource, nil
}

log.V(4).Info("Creating resource")
log.V(3).Info("Creating resource")
return actuator.CreateResource(ctx)
}

type DeleteStatus int

const (
DeleteStatusComplete DeleteStatus = iota
DeleteStatusError
DeleteStatusWaitingOnFinalizer
DeleteStatusWaitingOnOpenStack
)

func DeleteResource[osResourcePT *osResourceT, osResourceT any](ctx context.Context, log logr.Logger, obj ResourceActuator[osResourcePT], onComplete func() error) (osResourcePT, ctrl.Result, error) {
// We always fetch the resource by ID so we can continue to report status even when waiting for a finalizer
hasStatusID, osResource, err := obj.GetOSResourceByStatusID(ctx)
Expand Down
Loading
Loading