github.com/verrazzano/verrazzano@v1.7.1/platform-operator/controllers/module/component-handler/installupdate/install_update_handler.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 installupdate 5 6 import ( 7 moduleapi "github.com/verrazzano/verrazzano-modules/module-operator/apis/platform/v1alpha1" 8 modulestatus "github.com/verrazzano/verrazzano-modules/module-operator/controllers/module/status" 9 "github.com/verrazzano/verrazzano-modules/pkg/controller/result" 10 "github.com/verrazzano/verrazzano-modules/pkg/controller/spi/handlerspi" 11 vzerrors "github.com/verrazzano/verrazzano/pkg/controller/errors" 12 vzapi "github.com/verrazzano/verrazzano/platform-operator/apis/verrazzano/v1alpha1" 13 "github.com/verrazzano/verrazzano/platform-operator/constants" 14 "github.com/verrazzano/verrazzano/platform-operator/controllers/module/component-handler/common" 15 ) 16 17 type ActionType string 18 19 const ( 20 InstallAction ActionType = constants.InstallOperation 21 UpdateAction ActionType = constants.UpdateOperation 22 ) 23 24 type ComponentHandler struct { 25 action ActionType 26 } 27 28 var ( 29 _ handlerspi.StateMachineHandler = &ComponentHandler{} 30 ) 31 32 func NewHandler(action ActionType) handlerspi.StateMachineHandler { 33 return &ComponentHandler{action: action} 34 } 35 36 // GetWorkName returns the work name 37 func (h ComponentHandler) GetWorkName() string { 38 return string(h.action) 39 } 40 41 // IsWorkNeeded returns true if install/update is needed 42 func (h ComponentHandler) IsWorkNeeded(ctx handlerspi.HandlerContext) (bool, result.Result) { 43 return true, result.NewResult() 44 } 45 46 // CheckDependencies checks if the dependencies are ready 47 func (h ComponentHandler) CheckDependencies(ctx handlerspi.HandlerContext) result.Result { 48 return common.CheckDependencies(ctx, string(h.action), h.getStartedReason()) 49 } 50 51 // PreWorkUpdateStatus does the pre-Work status update 52 func (h ComponentHandler) PreWorkUpdateStatus(ctx handlerspi.HandlerContext) result.Result { 53 module := ctx.CR.(*moduleapi.Module) 54 55 // Update the Verrazzano component status 56 nsn, err := common.GetVerrazzanoNSN(ctx) 57 if err != nil { 58 return result.NewResultShortRequeueDelayWithError(err) 59 } 60 sd := common.StatusData{ 61 Vznsn: *nsn, 62 CondType: vzapi.CondInstallStarted, 63 CompName: module.Spec.ModuleName, 64 Msg: string(vzapi.CondInstallStarted), 65 Ready: false, 66 } 67 res := common.UpdateVerrazzanoComponentStatus(ctx, sd) 68 if res.ShouldRequeue() { 69 return res 70 } 71 72 // Update the module status 73 return modulestatus.UpdateReadyConditionReconciling(ctx, module, h.getStartedReason()) 74 } 75 76 // PreWork does the pre-work 77 func (h ComponentHandler) PreWork(ctx handlerspi.HandlerContext) result.Result { 78 module := ctx.CR.(*moduleapi.Module) 79 80 compCtx, comp, err := common.GetComponentAndContext(ctx, string(h.action)) 81 if err != nil { 82 return result.NewResultShortRequeueDelayWithError(err) 83 } 84 85 // Do the pre-install 86 if err := comp.PreInstall(compCtx); err != nil { 87 if !vzerrors.IsRetryableError(err) { 88 modulestatus.UpdateReadyConditionFailed(ctx, module, h.getStartedReason(), err.Error()) 89 } 90 return result.NewResultShortRequeueDelayWithError(err) 91 } 92 modulestatus.UpdateReadyConditionReconciling(ctx, module, h.getStartedReason()) 93 return result.NewResult() 94 } 95 96 // DoWorkUpdateStatus does th status update 97 func (h ComponentHandler) DoWorkUpdateStatus(ctx handlerspi.HandlerContext) result.Result { 98 return result.NewResult() 99 } 100 101 // DoWork installs the module using Helm 102 func (h ComponentHandler) DoWork(ctx handlerspi.HandlerContext) result.Result { 103 module := ctx.CR.(*moduleapi.Module) 104 105 compCtx, comp, err := common.GetComponentAndContext(ctx, string(h.action)) 106 if err != nil { 107 return result.NewResultShortRequeueDelayWithError(err) 108 } 109 110 if err := comp.Install(compCtx); err != nil { 111 if !vzerrors.IsRetryableError(err) { 112 modulestatus.UpdateReadyConditionFailed(ctx, module, h.getStartedReason(), err.Error()) 113 } 114 return result.NewResultShortRequeueDelayWithError(err) 115 } 116 modulestatus.UpdateReadyConditionReconciling(ctx, module, h.getStartedReason()) 117 return result.NewResult() 118 } 119 120 // IsWorkDone Indicates whether a module is installed and ready 121 func (h ComponentHandler) IsWorkDone(ctx handlerspi.HandlerContext) (bool, result.Result) { 122 compCtx, comp, err := common.GetComponentAndContext(ctx, string(h.action)) 123 if err != nil { 124 return false, result.NewResultShortRequeueDelayWithError(err) 125 } 126 127 ready := comp.IsReady(compCtx) 128 return ready, result.NewResult() 129 } 130 131 // PostWorkUpdateStatus does the post-work status update 132 func (h ComponentHandler) PostWorkUpdateStatus(ctx handlerspi.HandlerContext) result.Result { 133 return result.NewResult() 134 } 135 136 // PostWork does installation post-work 137 func (h ComponentHandler) PostWork(ctx handlerspi.HandlerContext) result.Result { 138 module := ctx.CR.(*moduleapi.Module) 139 140 compCtx, comp, err := common.GetComponentAndContext(ctx, string(h.action)) 141 if err != nil { 142 return result.NewResultShortRequeueDelayWithError(err) 143 } 144 if err := comp.PostInstall(compCtx); err != nil { 145 if !vzerrors.IsRetryableError(err) { 146 modulestatus.UpdateReadyConditionFailed(ctx, module, h.getStartedReason(), err.Error()) 147 } 148 return result.NewResultShortRequeueDelayWithError(err) 149 } 150 modulestatus.UpdateReadyConditionReconciling(ctx, module, h.getStartedReason()) 151 return result.NewResult() 152 } 153 154 // WorkCompletedUpdateStatus updates the status to completed 155 func (h ComponentHandler) WorkCompletedUpdateStatus(ctx handlerspi.HandlerContext) result.Result { 156 module := ctx.CR.(*moduleapi.Module) 157 var reason moduleapi.ModuleConditionReason 158 var cond vzapi.ConditionType 159 160 if h.action == InstallAction { 161 reason = moduleapi.ReadyReasonInstallSucceeded 162 cond = vzapi.CondInstallComplete 163 } else { 164 reason = moduleapi.ReadyReasonUpdateSucceeded 165 // Note, Verrazzano uses install condition for update 166 cond = vzapi.CondInstallComplete 167 } 168 169 // Update the Verrazzano component status 170 nsn, err := common.GetVerrazzanoNSN(ctx) 171 if err != nil { 172 return result.NewResultShortRequeueDelayWithError(err) 173 } 174 sd := common.StatusData{ 175 Vznsn: *nsn, 176 CondType: cond, 177 CompName: module.Spec.ModuleName, 178 CompVersion: module.Spec.Version, 179 Msg: string(cond), 180 Ready: true, 181 } 182 res := common.UpdateVerrazzanoComponentStatus(ctx, sd) 183 if res.ShouldRequeue() { 184 return res 185 } 186 187 // Update the module status 188 return modulestatus.UpdateReadyConditionSucceeded(ctx, module, reason) 189 } 190 191 func (h ComponentHandler) getStartedReason() moduleapi.ModuleConditionReason { 192 if h.action == InstallAction { 193 return moduleapi.ReadyReasonInstallStarted 194 } 195 return moduleapi.ReadyReasonUpdateStarted 196 }