github.com/verrazzano/verrazzano@v1.7.0/platform-operator/experimental/controllers/integration/cascade/reconciler.go (about) 1 // Copyright (c) 2023, Oracle and/or its affiliates. 2 // Licensed under the Universal Permissive License v 1.0 as shown at https://oss.oracle.com/licenses/upl. 3 4 package cascade 5 6 import ( 7 ctx "context" 8 moduleapi "github.com/verrazzano/verrazzano-modules/module-operator/apis/platform/v1alpha1" 9 "github.com/verrazzano/verrazzano-modules/pkg/controller/result" 10 "github.com/verrazzano/verrazzano-modules/pkg/controller/spi/controllerspi" 11 "github.com/verrazzano/verrazzano-modules/pkg/vzlog" 12 "github.com/verrazzano/verrazzano/platform-operator/experimental/event" 13 "github.com/verrazzano/verrazzano/platform-operator/internal/config" 14 "golang.org/x/net/context" 15 corev1 "k8s.io/api/core/v1" 16 "k8s.io/apimachinery/pkg/apis/meta/v1/unstructured" 17 "k8s.io/apimachinery/pkg/runtime" 18 "os" 19 "path" 20 ) 21 22 // Reconcile reconciles the IntegrateCascadeRequestEvent (in the form of a configmap). 23 // Cascaded means that a lifecycle event for certain modules, such as prometheus-operator, 24 // require that all integration charts for other modules be installed/upgraded. This controller 25 // finds such modules and creates events that will cause the integration chart for each one to be 26 // applied. 27 func (r Reconciler) Reconcile(spictx controllerspi.ReconcileContext, u *unstructured.Unstructured) result.Result { 28 log := vzlog.DefaultLogger() 29 30 // Get the configmap and convert into an event 31 cm := &corev1.ConfigMap{} 32 if err := runtime.DefaultUnstructuredConverter.FromUnstructured(u.Object, cm); err != nil { 33 spictx.Log.ErrorfThrottled(err.Error()) 34 // This is a fatal error, don't requeue 35 return result.NewResult() 36 } 37 ev, err := event.ConfigMapToModuleIntegrationEvent(log, cm) 38 if err != nil { 39 spictx.Log.ErrorfThrottled(err.Error()) 40 return result.NewResultShortRequeueDelayWithError(err) 41 } 42 43 // Create a single integration event for all the modules that have integration charts 44 res := r.createIntegrationEvents(log, ev) 45 if res.ShouldRequeue() { 46 return res 47 } 48 49 // Delete the event. This is safe to do since the integration controller 50 // is the only controller processing IntegrateCascadeRequestEvent events 51 if err := r.Client.Delete(ctx.TODO(), cm); err != nil { 52 log.ErrorfThrottled("Failed to delete event configmap %s", cm.Name) 53 return result.NewResultShortRequeueDelayWithError(err) 54 } 55 return result.NewResult() 56 } 57 58 // createIntegrationEvents creates integration events for all modules that have an integration chart, 59 // except for the module that was just integrated (i.e. the module in the IntegrateCascadeRequestEvent) 60 func (r Reconciler) createIntegrationEvents(log vzlog.VerrazzanoLogger, ev *event.ModuleIntegrationEvent) result.Result { 61 modules := moduleapi.ModuleList{} 62 err := r.Client.List(context.TODO(), &modules) 63 if err != nil { 64 log.ErrorfThrottled("Failed getting the list of modules in the cluster: %v", err) 65 return result.NewResultShortRequeueDelayWithError(err) 66 } 67 68 var requeue *result.Result 69 for i, module := range modules.Items { 70 // If this module was just integrated then ignore it 71 moduleName := module.Spec.ModuleName 72 if moduleName == ev.ModuleName { 73 continue 74 } 75 76 // Nothing to do if an integration chart doesn't exist for this module 77 moduleChartDir := path.Join(config.GetIntegrationChartsDir(), moduleName) 78 _, err := os.Stat(moduleChartDir) 79 if err != nil { 80 if os.IsNotExist(err) { 81 continue 82 } 83 log.ErrorfThrottled("Failed to check if integration chart exists for module %s: %v", moduleName, err) 84 res := result.NewResultShortRequeueDelayWithError(err) 85 requeue = &res 86 } 87 88 // Create an event requesting that this module be integrated. Always use installed event so that the charts get applied. 89 // Even in the case where the original module got deleted, install action is needed to re-apply the integration 90 // charts for the module. 91 res := event.CreateNonCascadingModuleIntegrationEvent(log, r.Client, &modules.Items[i], event.Installed) 92 if res.ShouldRequeue() { 93 requeue = &res 94 } 95 } 96 97 if requeue != nil { 98 return *requeue 99 } 100 return result.NewResult() 101 }