Skip to content

Commit

Permalink
layered mandatory module deletion, installation logic
Browse files Browse the repository at this point in the history
  • Loading branch information
ruanxin committed Feb 27, 2025
1 parent 464028b commit 3ff5353
Show file tree
Hide file tree
Showing 17 changed files with 325 additions and 195 deletions.
30 changes: 13 additions & 17 deletions cmd/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -58,6 +58,7 @@ import (
"github.com/kyma-project/lifecycle-manager/internal/event"
"github.com/kyma-project/lifecycle-manager/internal/maintenancewindows"
"github.com/kyma-project/lifecycle-manager/internal/manifest/manifestclient"
"github.com/kyma-project/lifecycle-manager/internal/manifest/parser"
"github.com/kyma-project/lifecycle-manager/internal/pkg/flags"
"github.com/kyma-project/lifecycle-manager/internal/pkg/metrics"
"github.com/kyma-project/lifecycle-manager/internal/remote"
Expand Down Expand Up @@ -319,7 +320,8 @@ func setupKymaReconciler(mgr ctrl.Manager, descriptorProvider *provider.CachedDe
Metrics: kymaMetrics,
RemoteCatalog: remote.NewRemoteCatalogFromKyma(mgr.GetClient(), skrContextFactory,
flagVar.RemoteSyncNamespace),
TemplateLookup: templatelookup.NewTemplateLookup(mgr.GetClient(), descriptorProvider, moduleTemplateInfoLookupStrategies),
TemplateLookup: templatelookup.NewTemplateLookup(mgr.GetClient(), descriptorProvider,
moduleTemplateInfoLookupStrategies),
}).SetupWithManager(
mgr, options, kyma.SetupOptions{
ListenerAddr: flagVar.KymaListenerAddr,
Expand Down Expand Up @@ -464,19 +466,15 @@ func setupMandatoryModuleReconciler(mgr ctrl.Manager,
options.CacheSyncTimeout = flagVar.CacheSyncTimeout
options.MaxConcurrentReconciles = flagVar.MaxConcurrentMandatoryModuleReconciles

if err := (&mandatorymodule.InstallationReconciler{
Client: mgr.GetClient(),
RequeueIntervals: queue.RequeueIntervals{
parser := parser.NewParser(mgr.GetClient(), descriptorProvider, flagVar.InKCPMode, flagVar.RemoteSyncNamespace)

if err := mandatorymodule.NewInstallationReconciler(
mgr.GetClient(), queue.RequeueIntervals{
Success: flagVar.MandatoryModuleRequeueSuccessInterval,
Busy: flagVar.KymaRequeueBusyInterval,
Error: flagVar.KymaRequeueErrInterval,
Warning: flagVar.KymaRequeueWarningInterval,
},
RemoteSyncNamespace: flagVar.RemoteSyncNamespace,
InKCPMode: flagVar.InKCPMode,
DescriptorProvider: descriptorProvider,
Metrics: metrics,
}).SetupWithManager(mgr, options); err != nil {
}, parser, metrics).SetupWithManager(mgr, options); err != nil {
setupLog.Error(err, "unable to create controller", "controller", "MandatoryModule")
os.Exit(bootstrapFailedExitCode)
}
Expand All @@ -494,17 +492,15 @@ func setupMandatoryModuleDeletionReconciler(mgr ctrl.Manager,
options.CacheSyncTimeout = flagVar.CacheSyncTimeout
options.MaxConcurrentReconciles = flagVar.MaxConcurrentMandatoryModuleDeletionReconciles

if err := (&mandatorymodule.DeletionReconciler{
Client: mgr.GetClient(),
Event: event,
DescriptorProvider: descriptorProvider,
RequeueIntervals: queue.RequeueIntervals{
if err := mandatorymodule.NewDeletionReconciler(
mgr.GetClient(),
event, descriptorProvider,
queue.RequeueIntervals{
Success: flagVar.MandatoryModuleDeletionRequeueSuccessInterval,
Busy: flagVar.KymaRequeueBusyInterval,
Error: flagVar.KymaRequeueErrInterval,
Warning: flagVar.KymaRequeueWarningInterval,
},
}).SetupWithManager(mgr, options); err != nil {
}).SetupWithManager(mgr, options); err != nil {
setupLog.Error(err, "unable to create controller", "controller", "MandatoryModule")
os.Exit(bootstrapFailedExitCode)
}
Expand Down
103 changes: 30 additions & 73 deletions internal/controller/mandatorymodule/deletion_controller.go
Original file line number Diff line number Diff line change
Expand Up @@ -20,17 +20,15 @@ import (
"context"
"fmt"

k8slabels "k8s.io/apimachinery/pkg/labels"
ctrl "sigs.k8s.io/controller-runtime"
"sigs.k8s.io/controller-runtime/pkg/client"
"sigs.k8s.io/controller-runtime/pkg/controller/controllerutil"
logf "sigs.k8s.io/controller-runtime/pkg/log"

"github.com/kyma-project/lifecycle-manager/api/shared"
"github.com/kyma-project/lifecycle-manager/api/v1beta2"
"github.com/kyma-project/lifecycle-manager/internal/descriptor/provider"
"github.com/kyma-project/lifecycle-manager/internal/event"
"github.com/kyma-project/lifecycle-manager/internal/service"
"github.com/kyma-project/lifecycle-manager/internal/service/mandatorymodule"
"github.com/kyma-project/lifecycle-manager/pkg/log"
"github.com/kyma-project/lifecycle-manager/pkg/queue"
"github.com/kyma-project/lifecycle-manager/pkg/util"
Expand All @@ -42,10 +40,22 @@ const (
)

type DeletionReconciler struct {
client.Client
event.Event
queue.RequeueIntervals
moduleTemplateService *service.ModuleTemplateService
moduleTemplateService *service.ModuleTemplateService
mandatoryModuleDeletionService *mandatorymodule.MandatoryModuleDeletionService
}

func NewDeletionReconciler(client client.Client, event event.Event,
descriptorProvider *provider.CachedDescriptorProvider,
requeueIntervals queue.RequeueIntervals,
) *DeletionReconciler {
return &DeletionReconciler{
Event: event,
RequeueIntervals: requeueIntervals,
moduleTemplateService: service.NewModuleTemplateService(client),
mandatoryModuleDeletionService: mandatorymodule.NewMandatoryModuleDeletionService(client, descriptorProvider),
}
}

func (r *DeletionReconciler) Reconcile(ctx context.Context, req ctrl.Request) (ctrl.Result, error) {
Expand All @@ -67,84 +77,31 @@ func (r *DeletionReconciler) Reconcile(ctx context.Context, req ctrl.Request) (c
return ctrl.Result{}, nil
}

updateRequired := controllerutil.AddFinalizer(template, shared.MandatoryModuleFinalizer)
updateRequired, err := r.moduleTemplateService.UpdateFinalizer(ctx, template, shared.MandatoryModuleFinalizer)
if err != nil {
r.Event.Warning(template, settingFinalizerError, err)
return ctrl.Result{}, fmt.Errorf("failed to update ModuleTemplate finalizer: %w", err)
}
if updateRequired {
return r.updateTemplateFinalizer(ctx, template)
return ctrl.Result{Requeue: true}, nil
}

if template.DeletionTimestamp.IsZero() {
return ctrl.Result{}, nil
}

manifests, err := r.getCorrespondingManifests(ctx, template)
if err != nil {
return ctrl.Result{}, fmt.Errorf("failed to get MandatoryModuleManifests: %w", err)
}

if len(manifests) == 0 {
if controllerutil.RemoveFinalizer(template, shared.MandatoryModuleFinalizer) {
return r.updateTemplateFinalizer(ctx, template)
noManifestLeft, err := r.mandatoryModuleDeletionService.DeleteMandatoryModules(ctx, template)
if noManifestLeft {
updateRequired, err := r.moduleTemplateService.RemoveFinalizer(ctx, template, shared.MandatoryModuleFinalizer)
if err != nil {
r.Event.Warning(template, settingFinalizerError, err)
return ctrl.Result{}, fmt.Errorf("failed to update ModuleTemplate finalizer: %w", err)
}
if updateRequired {
return ctrl.Result{Requeue: true}, nil
}
return ctrl.Result{}, nil
}

if err := r.removeManifests(ctx, manifests); err != nil {
r.Event.Warning(template, deletingManifestError, err)
return ctrl.Result{}, fmt.Errorf("failed to remove MandatoryModule Manifest: %w", err)
}

return ctrl.Result{Requeue: true}, nil
}

func (r *DeletionReconciler) updateTemplateFinalizer(ctx context.Context,
template *v1beta2.ModuleTemplate,
) (ctrl.Result, error) {
if err := r.Update(ctx, template); err != nil {
r.Event.Warning(template, settingFinalizerError, err)
return ctrl.Result{}, fmt.Errorf("failed to update MandatoryModuleTemplate finalizer: %w", err)
}
return ctrl.Result{Requeue: true}, nil
}

func (r *DeletionReconciler) getCorrespondingManifests(ctx context.Context,
template *v1beta2.ModuleTemplate) ([]v1beta2.Manifest,
error,
) {
manifests := &v1beta2.ManifestList{}
descriptor, err := r.DescriptorProvider.GetDescriptor(template)
if err != nil {
return nil, fmt.Errorf("not able to get descriptor from template: %w", err)
}
if err := r.List(ctx, manifests, &client.ListOptions{
Namespace: template.Namespace,
LabelSelector: k8slabels.SelectorFromSet(k8slabels.Set{shared.IsMandatoryModule: "true"}),
}); client.IgnoreNotFound(err) != nil {
return nil, fmt.Errorf("not able to list mandatory module manifests: %w", err)
}

filtered := filterManifestsByAnnotation(manifests.Items, shared.FQDN, descriptor.GetName())

return filtered, nil
}

func (r *DeletionReconciler) removeManifests(ctx context.Context, manifests []v1beta2.Manifest) error {
for _, manifest := range manifests {
if err := r.Delete(ctx, &manifest); err != nil {
return fmt.Errorf("not able to delete manifest %s/%s: %w", manifest.Namespace, manifest.Name, err)
}
}
logf.FromContext(ctx).V(log.DebugLevel).Info("Marked all MandatoryModule Manifests for deletion")
return nil
}

func filterManifestsByAnnotation(manifests []v1beta2.Manifest,
annotationKey, annotationValue string,
) []v1beta2.Manifest {
filteredManifests := make([]v1beta2.Manifest, 0)
for _, manifest := range manifests {
if manifest.Annotations[annotationKey] == annotationValue {
filteredManifests = append(filteredManifests, manifest)
}
}
return filteredManifests
}
26 changes: 21 additions & 5 deletions internal/controller/mandatorymodule/installation_controller.go
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,10 @@ import (
"sigs.k8s.io/controller-runtime/pkg/client"
logf "sigs.k8s.io/controller-runtime/pkg/log"

"github.com/kyma-project/lifecycle-manager/internal/manifest/parser"
"github.com/kyma-project/lifecycle-manager/internal/pkg/metrics"
"github.com/kyma-project/lifecycle-manager/internal/service"
"github.com/kyma-project/lifecycle-manager/internal/service/mandatorymodule"
"github.com/kyma-project/lifecycle-manager/pkg/log"
"github.com/kyma-project/lifecycle-manager/pkg/queue"
"github.com/kyma-project/lifecycle-manager/pkg/util"
Expand All @@ -17,14 +20,28 @@ import (
type InstallationReconciler struct {
client.Client
queue.RequeueIntervals
KymaService *service.KymaService
kymaService *service.KymaService
mandatoryModuleService *mandatorymodule.MandatoryModuleInstallationService
}

func NewInstallationReconciler(client client.Client,
requeueIntervals queue.RequeueIntervals,
parser *parser.Parser,
metrics *metrics.MandatoryModulesMetrics,
) *InstallationReconciler {
return &InstallationReconciler{
Client: client,
RequeueIntervals: requeueIntervals,
kymaService: service.NewKymaService(client),
mandatoryModuleService: mandatorymodule.NewMandatoryModuleInstallationService(client, metrics, parser),
}
}

func (r *InstallationReconciler) Reconcile(ctx context.Context, req ctrl.Request) (ctrl.Result, error) {
logger := logf.FromContext(ctx)
logger.V(log.DebugLevel).Info("Mandatory Module Reconciliation started")

kyma, err := r.KymaService.GetKyma(ctx, req.NamespacedName)
kyma, err := r.kymaService.GetKyma(ctx, req.NamespacedName)
if err != nil {
if util.IsNotFound(err) {
logger.V(log.DebugLevel).Info(fmt.Sprintf("Kyma %s not found, probably already deleted",
Expand All @@ -39,10 +56,9 @@ func (r *InstallationReconciler) Reconcile(ctx context.Context, req ctrl.Request
return ctrl.Result{RequeueAfter: r.RequeueIntervals.Success}, nil
}

result, err := r.KymaService.ReconcileMandatoryModules(ctx, kyma)
if err != nil {
if err := r.mandatoryModuleService.ReconcileMandatoryModules(ctx, kyma); err != nil {
return ctrl.Result{}, fmt.Errorf("failed to reconcile mandatory modules: %w", err)
}

return result, nil
return ctrl.Result{}, nil
}
7 changes: 6 additions & 1 deletion internal/repository/kyma.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ package repository

import (
"context"
"fmt"

"sigs.k8s.io/controller-runtime/pkg/client"

Expand All @@ -12,10 +13,14 @@ type KymaRepository struct {
Client client.Client
}

func NewKymaRepository(client client.Client) *KymaRepository {
return &KymaRepository{Client: client}
}

func (r *KymaRepository) GetKyma(ctx context.Context, namespacedName client.ObjectKey) (*v1beta2.Kyma, error) {
kyma := &v1beta2.Kyma{}
if err := r.Client.Get(ctx, namespacedName, kyma); err != nil {
return nil, err
return nil, fmt.Errorf("failed to get Kyma: %w", err)
}
return kyma, nil
}
29 changes: 26 additions & 3 deletions internal/repository/manifest.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,19 +6,31 @@ import (

k8slabels "k8s.io/apimachinery/pkg/labels"
"sigs.k8s.io/controller-runtime/pkg/client"
logf "sigs.k8s.io/controller-runtime/pkg/log"

"github.com/kyma-project/lifecycle-manager/api/shared"
"github.com/kyma-project/lifecycle-manager/api/v1beta2"
"github.com/kyma-project/lifecycle-manager/internal/descriptor/provider"
"github.com/kyma-project/lifecycle-manager/pkg/log"
)

type ManifestRepository struct {
Client client.Client
DescriptorProvider *provider.CachedDescriptorProvider
}

func (r *ManifestRepository) GetCorrespondingManifests(ctx context.Context,
template *v1beta2.ModuleTemplate) ([]v1beta2.Manifest, error) {
func NewManifestRepository(client client.Client,
descriptorProvider *provider.CachedDescriptorProvider,
) *ManifestRepository {
return &ManifestRepository{
Client: client,
DescriptorProvider: descriptorProvider,
}
}

func (r *ManifestRepository) GetMandatoryManifests(ctx context.Context,
template *v1beta2.ModuleTemplate,
) ([]v1beta2.Manifest, error) {
manifests := &v1beta2.ManifestList{}
descriptor, err := r.DescriptorProvider.GetDescriptor(template)
if err != nil {
Expand All @@ -34,8 +46,19 @@ func (r *ManifestRepository) GetCorrespondingManifests(ctx context.Context,
return filterManifestsByAnnotation(manifests.Items, shared.FQDN, descriptor.GetName()), nil
}

func (r *ManifestRepository) RemoveManifests(ctx context.Context, manifests []v1beta2.Manifest) error {
for _, manifest := range manifests {
if err := r.Client.Delete(ctx, &manifest); err != nil {
return fmt.Errorf("not able to delete manifest %s/%s: %w", manifest.Namespace, manifest.Name, err)
}
}
logf.FromContext(ctx).V(log.DebugLevel).Info("Marked all Manifests for deletion")
return nil
}

func filterManifestsByAnnotation(manifests []v1beta2.Manifest,
annotationKey, annotationValue string) []v1beta2.Manifest {
annotationKey, annotationValue string,
) []v1beta2.Manifest {
filteredManifests := make([]v1beta2.Manifest, 0)
for _, manifest := range manifests {
if manifest.Annotations[annotationKey] == annotationValue {
Expand Down
Loading

0 comments on commit 3ff5353

Please sign in to comment.