Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Catalogd integration foundations #175

Closed
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
203 changes: 0 additions & 203 deletions controllers/catalogsource_controller.go

This file was deleted.

125 changes: 125 additions & 0 deletions controllers/entity_cache_builder.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,125 @@
package controllers

import (
"context"
"fmt"
"time"

"github.com/operator-framework/api/pkg/operators/v1alpha1"
"k8s.io/apimachinery/pkg/api/errors"
"k8s.io/apimachinery/pkg/runtime"
"k8s.io/client-go/tools/record"
ctrl "sigs.k8s.io/controller-runtime"
"sigs.k8s.io/controller-runtime/pkg/client"
"sigs.k8s.io/controller-runtime/pkg/log"

"github.com/operator-framework/operator-controller/internal/entitycache"
"github.com/operator-framework/operator-controller/internal/resolution"
"github.com/operator-framework/operator-controller/internal/resolution/entity_sources/catalogsource"
)

const (
defaultSyncInterval = 5 * time.Minute

eventTypeNormal = "Normal"
eventTypeWarning = "Warning"

eventReasonCacheUpdated = "CacheUpdated"
eventReasonCacheUpdateFailed = "CacheUpdateFailed"
)

type EntityCacheBuilderOption func(reconciler *EntityCacheBuilder)

func WithEntitySourceConnector(entitysourceConnector resolution.EntitySourceConnector) EntityCacheBuilderOption {
return func(reconciler *EntityCacheBuilder) {
reconciler.entitySourceConnector = entitysourceConnector
}
}

func WithSyncInterval(interval time.Duration) EntityCacheBuilderOption {
return func(reconciler *EntityCacheBuilder) {
reconciler.syncInterval = interval
}
}

// applyDefaults applies default values to empty EntityCacheBuilder fields _after_ options have been applied
func applyDefaults() EntityCacheBuilderOption {
return func(reconciler *EntityCacheBuilder) {
if reconciler.entitySourceConnector == nil {
reconciler.entitySourceConnector = catalogsource.NewGRPCClientConnector(0)
}
if reconciler.syncInterval == 0 {
reconciler.syncInterval = defaultSyncInterval
}
}
}

type EntityCacheBuilder struct {
client.Client
scheme *runtime.Scheme
entitySourceConnector resolution.EntitySourceConnector
recorder record.EventRecorder
syncInterval time.Duration
Cache *entitycache.EntityCache
}

func NewEntityCacheBuilder(client client.Client, scheme *runtime.Scheme, recorder record.EventRecorder, options ...EntityCacheBuilderOption) *EntityCacheBuilder {
reconciler := &EntityCacheBuilder{
Client: client,
scheme: scheme,
recorder: recorder,
syncInterval: 0,
}
// apply options
options = append(options, applyDefaults())
for _, option := range options {
option(reconciler)
}

return reconciler
}

// +kubebuilder:rbac:groups=operators.coreos.com,resources=catalogsources,verbs=get;list;watch
// +kubebuilder:rbac:groups="",resources=events,verbs=create;patch

func (r *EntityCacheBuilder) Reconcile(ctx context.Context, req ctrl.Request) (ctrl.Result, error) {
l := log.FromContext(ctx).WithName("entity-cache-builder")
l.V(1).Info("starting")
defer l.V(1).Info("ending")

var catalogSource = &v1alpha1.CatalogSource{}
if err := r.Client.Get(ctx, req.NamespacedName, catalogSource); err != nil {
if errors.IsNotFound(err) {
r.Cache.DropSource(req.String())
}
return ctrl.Result{}, client.IgnoreNotFound(err)
}

entities, err := r.entitySourceConnector.ListEntities(ctx, catalogSource)
// TODO: invalidate stale cache for failed updates
if err != nil {
r.recorder.Event(catalogSource, eventTypeWarning, eventReasonCacheUpdateFailed, fmt.Sprintf("Failed to update bundle cache from %s/%s: %v", catalogSource.GetNamespace(), catalogSource.GetName(), err))
// return ctrl.Result{Requeue: !isManagedCatalogSource(*catalogSource)}, err
return ctrl.Result{Requeue: true}, err
}
if updated := r.Cache.UpdateCache(req.String(), entities); updated {
r.recorder.Event(catalogSource, eventTypeNormal, eventReasonCacheUpdated, fmt.Sprintf("Successfully updated bundle cache from %s/%s", catalogSource.GetNamespace(), catalogSource.GetName()))
}

// if isManagedCatalogSource(*catalogSource) {
// return ctrl.Result{}, nil
// }
return ctrl.Result{RequeueAfter: r.syncInterval}, nil
}

// SetupWithManager sets up the controller with the Manager.
func (r *EntityCacheBuilder) SetupWithManager(mgr ctrl.Manager) error {
return ctrl.NewControllerManagedBy(mgr).
For(&v1alpha1.CatalogSource{}).
Complete(r)
}

// TODO: find better way to identify catalogSources unmanaged by olm
// func isManagedCatalogSource(catalogSource v1alpha1.CatalogSource) bool {
Copy link
Contributor Author

@anik120 anik120 Apr 18, 2023

Choose a reason for hiding this comment

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

I need more information about what this is for. Since an entity_cache_builder shouldn't make any assumptions about what the nature of the entity is (catalogsource or otherwise), I've commented it out now, but once I've learned the purpose of this I can find a better place for this (possibly the catalogsource entitySourceConnector).

Copy link
Member

Choose a reason for hiding this comment

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

I think this was a remnant of the idea that operator-controller would:

  • not need OLMv0's catalog-operator to actually reconcile CatalogSource objects
  • (therefore) the only catalog sources that would be usable in this context are ones where the spec tells us the address to connect to.

In the end, we decided to just run OLMv0 so that we could use any catalog source.

// return len(catalogSource.Spec.Address) == 0
// }
Loading