@@ -23,8 +23,6 @@ package reconcile
2323import (
2424 "context"
2525
26- "github.com/arangodb/kube-arangodb/pkg/deployment/rotation"
27-
2826 "github.com/arangodb/kube-arangodb/pkg/deployment/features"
2927
3028 "github.com/arangodb/kube-arangodb/pkg/deployment/resources"
@@ -37,6 +35,7 @@ import (
3735 api "github.com/arangodb/kube-arangodb/pkg/apis/deployment/v1"
3836 "github.com/arangodb/kube-arangodb/pkg/deployment/actions"
3937 "github.com/arangodb/kube-arangodb/pkg/deployment/agency"
38+ "github.com/arangodb/kube-arangodb/pkg/deployment/rotation"
4039 "github.com/arangodb/kube-arangodb/pkg/util/k8sutil"
4140 inspectorInterface "github.com/arangodb/kube-arangodb/pkg/util/k8sutil/inspector"
4241 "github.com/rs/zerolog"
@@ -123,118 +122,170 @@ func createRotateOrUpgradePlanInternal(log zerolog.Logger, apiObject k8sutil.API
123122 decision := createRotateOrUpgradeDecision (log , spec , status , context )
124123
125124 if decision .IsUpgrade () {
125+ return createUpgradePlanInternalCondition (log , apiObject , spec , status , context , decision )
126+ } else if decision .IsUpdate () {
127+ return createUpdatePlanInternalCondition (log , apiObject , spec , status , cachedStatus , decision )
128+ } else {
129+ upgradeCondition := status .Conditions .IsTrue (api .ConditionTypeUpgradeInProgress )
130+ updateCondition := status .Conditions .IsTrue (api .ConditionTypeUpdateInProgress )
126131
127- for _ , m := range status .Members .AsList () {
128- // Pre-check
129- d := decision [m .Member .ID ]
130- if ! d .upgrade {
131- continue
132- }
132+ if upgradeCondition || updateCondition {
133+ p := make (api.Plan , 0 , 2 )
133134
134- // We have member to upgrade
135- if d .upgradeDecision .Hold {
136- // Holding upgrade
137- continue
135+ if upgradeCondition {
136+ p = append (p , removeConditionActionV2 ("Upgrade done" , api .ConditionTypeUpgradeInProgress ))
138137 }
139138
140- if ! d .upgradeDecision .UpgradeAllowed {
141- context .CreateEvent (k8sutil .NewUpgradeNotAllowedEvent (apiObject , d .upgradeDecision .FromVersion , d .upgradeDecision .ToVersion , d .upgradeDecision .FromLicense , d .upgradeDecision .ToLicense ))
142- return nil , false
139+ if updateCondition {
140+ p = append (p , removeConditionActionV2 ("Update done" , api .ConditionTypeUpdateInProgress ))
143141 }
142+
143+ return p , false
144144 }
145+ }
145146
146- // Upgrade phase
147- // During upgrade always get first member which needs to be upgraded
148- for _ , m := range status .Members .AsList () {
149- d := decision [m .Member .ID ]
150- if ! d .upgrade {
151- continue
152- }
147+ return nil , false
148+ }
153149
154- // We have member to upgrade
155- if d .upgradeDecision .Hold {
156- // Holding upgrade
157- return nil , false
158- }
150+ func createUpdatePlanInternalCondition (log zerolog.Logger , apiObject k8sutil.APIObject , spec api.DeploymentSpec , status api.DeploymentStatus , cachedStatus inspectorInterface.Inspector , decision updateUpgradeDecisionMap ) (api.Plan , bool ) {
151+ plan , idle := createUpdatePlanInternal (log , apiObject , spec , status , cachedStatus , decision )
159152
160- if ! d .upgradeDecision .UpgradeNeeded {
161- // In upgrade scenario but upgrade is not needed
162- return nil , false
163- }
153+ if idle || len (plan ) > 0 {
154+ if ! status .Conditions .IsTrue (api .ConditionTypeUpdateInProgress ) {
155+ plan = append (api.Plan {
156+ updateConditionActionV2 ("Update in progress" , api .ConditionTypeUpdateInProgress , true , "" , "" , "" ),
157+ }, plan ... )
158+ }
159+ }
164160
165- if ! d .upgradeDecision .UpgradeAllowed {
166- context .CreateEvent (k8sutil .NewUpgradeNotAllowedEvent (apiObject , d .upgradeDecision .FromVersion , d .upgradeDecision .ToVersion , d .upgradeDecision .FromLicense , d .upgradeDecision .ToLicense ))
167- return nil , false
168- }
161+ return plan , idle
162+ }
169163
170- if d .updateAllowed {
171- // We are fine, group is alive so we can proceed
172- log .Info ().Str ("member" , m .Member .ID ).Str ("Reason" , d .updateMessage ).Msg ("Upgrade allowed" )
173- return createUpgradeMemberPlan (log , m .Member , m .Group , "Version upgrade" , spec , status , ! d .upgradeDecision .AutoUpgradeNeeded ), false
174- } else if d .unsafeUpdateAllowed {
175- log .Info ().Str ("member" , m .Member .ID ).Str ("Reason" , d .updateMessage ).Msg ("Pod needs upgrade but cluster is not ready. Either some shards are not in sync or some member is not ready, but unsafe upgrade is allowed" )
176- return createUpgradeMemberPlan (log , m .Member , m .Group , "Version upgrade" , spec , status , ! d .upgradeDecision .AutoUpgradeNeeded ), false
177- } else {
178- log .Info ().Str ("member" , m .Member .ID ).Str ("Reason" , d .updateMessage ).Msg ("Pod needs upgrade but cluster is not ready. Either some shards are not in sync or some member is not ready." )
179- return nil , true
180- }
164+ func createUpdatePlanInternal (log zerolog.Logger , apiObject k8sutil.APIObject , spec api.DeploymentSpec , status api.DeploymentStatus , cachedStatus inspectorInterface.Inspector , decision updateUpgradeDecisionMap ) (api.Plan , bool ) {
165+ // Update phase
166+ for _ , m := range status .Members .AsList () {
167+ d := decision [m .Member .ID ]
168+ if ! d .update {
169+ continue
181170 }
182171
183- log .Warn ().Msg ("Pod upgrade plan has been made, but it has been dropped due to missing flag" )
184- return nil , false
185- } else if decision .IsUpdate () {
186- // Update phase
187- for _ , m := range status .Members .AsList () {
188- d := decision [m .Member .ID ]
189- if ! d .update {
172+ if ! d .updateAllowed {
173+ // Update is not allowed due to constraint
174+ if ! d .unsafeUpdateAllowed {
175+ log .Info ().Str ("member" , m .Member .ID ).Str ("Reason" , d .updateMessage ).Msg ("Pod needs restart but cluster is not ready. Either some shards are not in sync or some member is not ready." )
190176 continue
191177 }
178+ log .Info ().Str ("member" , m .Member .ID ).Str ("Reason" , d .updateMessage ).Msg ("Pod needs restart but cluster is not ready. Either some shards are not in sync or some member is not ready, but unsafe upgrade is allowed" )
179+ }
192180
193- if ! d .updateAllowed {
194- // Update is not allowed due to constraint
195- if ! d .unsafeUpdateAllowed {
196- log .Info ().Str ("member" , m .Member .ID ).Str ("Reason" , d .updateMessage ).Msg ("Pod needs restart but cluster is not ready. Either some shards are not in sync or some member is not ready." )
197- continue
198- }
199- log .Info ().Str ("member" , m .Member .ID ).Str ("Reason" , d .updateMessage ).Msg ("Pod needs restart but cluster is not ready. Either some shards are not in sync or some member is not ready, but unsafe upgrade is allowed" )
200- }
181+ if m .Member .Conditions .IsTrue (api .ConditionTypeRestart ) {
182+ return createRotateMemberPlan (log , m .Member , m .Group , spec , "Restart flag present" ), false
183+ }
184+ arangoMember , ok := cachedStatus .ArangoMember ().V1 ().GetSimple (m .Member .ArangoMemberName (apiObject .GetName (), m .Group ))
185+ if ! ok {
186+ continue
187+ }
201188
202- if m .Member .Conditions .IsTrue (api .ConditionTypeRestart ) {
203- return createRotateMemberPlan (log , m .Member , m .Group , spec , "Restart flag present" ), false
204- }
205- arangoMember , ok := cachedStatus .ArangoMember ().V1 ().GetSimple (m .Member .ArangoMemberName (apiObject .GetName (), m .Group ))
206- if ! ok {
207- continue
208- }
189+ p , ok := cachedStatus .Pod ().V1 ().GetSimple (m .Member .PodName )
190+ if ! ok {
191+ p = nil
192+ }
209193
210- p , ok := cachedStatus .Pod ().V1 ().GetSimple (m .Member .PodName )
211- if ! ok {
212- p = nil
213- }
194+ if mode , p , reason , err := rotation .IsRotationRequired (log , cachedStatus , spec , m .Member , m .Group , p , arangoMember .Spec .Template , arangoMember .Status .Template ); err != nil {
195+ log .Err (err ).Str ("member" , m .Member .ID ).Msgf ("Error while generating update plan" )
196+ continue
197+ } else if mode != rotation .InPlaceRotation {
198+ return api.Plan {actions .NewAction (api .ActionTypeSetMemberCondition , m .Group , m .Member , "Cleaning update" ).
199+ AddParam (api .ConditionTypePendingUpdate .String (), "" ).
200+ AddParam (api .ConditionTypeUpdating .String (), "T" )}, false
201+ } else {
202+ p = p .After (
203+ actions .NewAction (api .ActionTypeWaitForMemberUp , m .Group , m .Member ),
204+ actions .NewAction (api .ActionTypeWaitForMemberInSync , m .Group , m .Member ))
205+
206+ p = p .Wrap (actions .NewAction (api .ActionTypeSetMemberCondition , m .Group , m .Member , reason ).
207+ AddParam (api .ConditionTypePendingUpdate .String (), "" ).AddParam (api .ConditionTypeUpdating .String (), "T" ),
208+ actions .NewAction (api .ActionTypeSetMemberCondition , m .Group , m .Member , reason ).
209+ AddParam (api .ConditionTypeUpdating .String (), "" ))
210+
211+ return p , false
212+ }
213+ }
214+ return nil , true
215+ }
214216
215- if mode , p , reason , err := rotation .IsRotationRequired (log , cachedStatus , spec , m .Member , m .Group , p , arangoMember .Spec .Template , arangoMember .Status .Template ); err != nil {
216- log .Err (err ).Str ("member" , m .Member .ID ).Msgf ("Error while generating update plan" )
217- continue
218- } else if mode != rotation .InPlaceRotation {
219- return api.Plan {actions .NewAction (api .ActionTypeSetMemberCondition , m .Group , m .Member , "Cleaning update" ).
220- AddParam (api .ConditionTypePendingUpdate .String (), "" ).
221- AddParam (api .ConditionTypeUpdating .String (), "T" )}, false
222- } else {
223- p = p .After (
224- actions .NewAction (api .ActionTypeWaitForMemberUp , m .Group , m .Member ),
225- actions .NewAction (api .ActionTypeWaitForMemberInSync , m .Group , m .Member ))
226-
227- p = p .Wrap (actions .NewAction (api .ActionTypeSetMemberCondition , m .Group , m .Member , reason ).
228- AddParam (api .ConditionTypePendingUpdate .String (), "" ).AddParam (api .ConditionTypeUpdating .String (), "T" ),
229- actions .NewAction (api .ActionTypeSetMemberCondition , m .Group , m .Member , reason ).
230- AddParam (api .ConditionTypeUpdating .String (), "" ))
231-
232- return p , false
233- }
217+ func createUpgradePlanInternalCondition (log zerolog.Logger , apiObject k8sutil.APIObject , spec api.DeploymentSpec , status api.DeploymentStatus , context PlanBuilderContext , decision updateUpgradeDecisionMap ) (api.Plan , bool ) {
218+ plan , idle := createUpgradePlanInternal (log , apiObject , spec , status , context , decision )
219+
220+ if idle || len (plan ) > 0 {
221+ if ! status .Conditions .IsTrue (api .ConditionTypeUpgradeInProgress ) {
222+ plan = append (api.Plan {
223+ updateConditionActionV2 ("Upgrade in progress" , api .ConditionTypeUpgradeInProgress , true , "" , "" , "" ),
224+ }, plan ... )
225+ }
226+ }
227+
228+ return plan , idle
229+ }
230+
231+ func createUpgradePlanInternal (log zerolog.Logger , apiObject k8sutil.APIObject , spec api.DeploymentSpec , status api.DeploymentStatus , context PlanBuilderContext , decision updateUpgradeDecisionMap ) (api.Plan , bool ) {
232+ for _ , m := range status .Members .AsList () {
233+ // Pre-check
234+ d := decision [m .Member .ID ]
235+ if ! d .upgrade {
236+ continue
237+ }
238+
239+ // We have member to upgrade
240+ if d .upgradeDecision .Hold {
241+ // Holding upgrade
242+ continue
243+ }
244+
245+ if ! d .upgradeDecision .UpgradeAllowed {
246+ context .CreateEvent (k8sutil .NewUpgradeNotAllowedEvent (apiObject , d .upgradeDecision .FromVersion , d .upgradeDecision .ToVersion , d .upgradeDecision .FromLicense , d .upgradeDecision .ToLicense ))
247+ return nil , false
248+ }
249+ }
250+
251+ // Upgrade phase
252+ // During upgrade always get first member which needs to be upgraded
253+ for _ , m := range status .Members .AsList () {
254+ d := decision [m .Member .ID ]
255+ if ! d .upgrade {
256+ continue
257+ }
258+
259+ // We have member to upgrade
260+ if d .upgradeDecision .Hold {
261+ // Holding upgrade
262+ return nil , false
263+ }
264+
265+ if ! d .upgradeDecision .UpgradeNeeded {
266+ // In upgrade scenario but upgrade is not needed
267+ return nil , false
268+ }
269+
270+ if ! d .upgradeDecision .UpgradeAllowed {
271+ context .CreateEvent (k8sutil .NewUpgradeNotAllowedEvent (apiObject , d .upgradeDecision .FromVersion , d .upgradeDecision .ToVersion , d .upgradeDecision .FromLicense , d .upgradeDecision .ToLicense ))
272+ return nil , false
273+ }
274+
275+ if d .updateAllowed {
276+ // We are fine, group is alive so we can proceed
277+ log .Info ().Str ("member" , m .Member .ID ).Str ("Reason" , d .updateMessage ).Msg ("Upgrade allowed" )
278+ return createUpgradeMemberPlan (log , m .Member , m .Group , "Version upgrade" , spec , status , ! d .upgradeDecision .AutoUpgradeNeeded ), false
279+ } else if d .unsafeUpdateAllowed {
280+ log .Info ().Str ("member" , m .Member .ID ).Str ("Reason" , d .updateMessage ).Msg ("Pod needs upgrade but cluster is not ready. Either some shards are not in sync or some member is not ready, but unsafe upgrade is allowed" )
281+ return createUpgradeMemberPlan (log , m .Member , m .Group , "Version upgrade" , spec , status , ! d .upgradeDecision .AutoUpgradeNeeded ), false
282+ } else {
283+ log .Info ().Str ("member" , m .Member .ID ).Str ("Reason" , d .updateMessage ).Msg ("Pod needs upgrade but cluster is not ready. Either some shards are not in sync or some member is not ready." )
284+ return nil , true
234285 }
235- return nil , true
236286 }
237287
288+ log .Warn ().Msg ("Pod upgrade plan has been made, but it has been dropped due to missing flag" )
238289 return nil , false
239290}
240291
0 commit comments