@@ -25,6 +25,7 @@ package reconcile
2525import (
2626 "strings"
2727
28+ driver "github.com/arangodb/go-driver"
2829 upgraderules "github.com/arangodb/go-upgrade-rules"
2930 "github.com/rs/zerolog"
3031 "github.com/rs/zerolog/log"
@@ -37,6 +38,8 @@ import (
3738
3839// upgradeDecision is the result of an upgrade check.
3940type upgradeDecision struct {
41+ FromVersion driver.Version
42+ ToVersion driver.Version
4043 UpgradeNeeded bool // If set, the image version has changed
4144 UpgradeAllowed bool // If set, it is an allowed version change
4245 AutoUpgradeNeeded bool // If set, the database must be started with `--database.auto-upgrade` once
@@ -149,33 +152,56 @@ func createPlan(log zerolog.Logger, apiObject k8sutil.APIObject,
149152 }
150153 return nil
151154 }
152- status .Members .ForeachServerGroup (func (group api.ServerGroup , members api.MemberStatusList ) error {
153- for _ , m := range members {
154- if len (plan ) > 0 {
155- // Only 1 change at a time
156- continue
157- }
158- if m .Phase != api .MemberPhaseCreated {
159- // Only rotate when phase is created
160- continue
161- }
162- if podName := m .PodName ; podName != "" {
163- if p := getPod (podName ); p != nil {
164- // Got pod, compare it with what it should be
165- decision := podNeedsUpgrading (* p , spec , status .Images )
166- if decision .UpgradeNeeded && decision .UpgradeAllowed {
167- plan = append (plan , createUpgradeMemberPlan (log , m , group , "Version upgrade" )... )
168- } else {
169- rotNeeded , reason := podNeedsRotation (log , * p , apiObject , spec , group , status .Members .Agents , m .ID , context )
170- if rotNeeded {
171- plan = append (plan , createRotateMemberPlan (log , m , group , reason )... )
155+ // createRotateOrUpgradePlan goes over all pods to check if an upgrade or rotate
156+ // is needed. If an upgrade is needed but not allowed, the second return value
157+ // will be true.
158+ // Returns: (newPlan, upgradeNotAllowed)
159+ createRotateOrUpgradePlan := func () (api.Plan , bool , driver.Version , driver.Version ) {
160+ var newPlan api.Plan
161+ upgradeNotAllowed := false
162+ var fromVersion , toVersion driver.Version
163+ status .Members .ForeachServerGroup (func (group api.ServerGroup , members api.MemberStatusList ) error {
164+ for _ , m := range members {
165+ if m .Phase != api .MemberPhaseCreated {
166+ // Only rotate when phase is created
167+ continue
168+ }
169+ if podName := m .PodName ; podName != "" {
170+ if p := getPod (podName ); p != nil {
171+ // Got pod, compare it with what it should be
172+ decision := podNeedsUpgrading (* p , spec , status .Images )
173+ if decision .UpgradeNeeded && ! decision .UpgradeAllowed {
174+ // Oops, upgrade is not allowed
175+ upgradeNotAllowed = true
176+ fromVersion = decision .FromVersion
177+ toVersion = decision .ToVersion
178+ return nil
179+ } else if len (newPlan ) == 0 {
180+ // Only rotate/upgrade 1 pod at a time
181+ if decision .UpgradeNeeded {
182+ // Yes, upgrade is needed (and allowed)
183+ newPlan = createUpgradeMemberPlan (log , m , group , "Version upgrade" , spec .GetImage (), status )
184+ } else {
185+ // Upgrade is not needed, see if rotation is needed
186+ if rotNeeded , reason := podNeedsRotation (log , * p , apiObject , spec , group , status .Members .Agents , m .ID , context ); rotNeeded {
187+ newPlan = createRotateMemberPlan (log , m , group , reason )
188+ }
189+ }
172190 }
173191 }
174192 }
175193 }
176- }
177- return nil
178- })
194+ return nil
195+ })
196+ return newPlan , upgradeNotAllowed , fromVersion , toVersion
197+ }
198+ if newPlan , upgradeNotAllowed , fromVersion , toVersion := createRotateOrUpgradePlan (); upgradeNotAllowed {
199+ // Upgrade is needed, but not allowed
200+ context .CreateEvent (k8sutil .NewUpgradeNotAllowedEvent (apiObject , fromVersion , toVersion ))
201+ } else {
202+ // Use the new plan
203+ plan = newPlan
204+ }
179205 }
180206
181207 // Check for the need to rotate TLS certificate of a members
@@ -218,18 +244,27 @@ func podNeedsUpgrading(p v1.Pod, spec api.DeploymentSpec, images api.ImageInfoLi
218244 podVersion := podImageInfo .ArangoDBVersion
219245 if err := upgraderules .CheckUpgradeRules (podVersion , specVersion ); err != nil {
220246 // E.g. 3.x -> 4.x, we cannot allow automatically
221- return upgradeDecision {UpgradeNeeded : true , UpgradeAllowed : false }
247+ return upgradeDecision {
248+ FromVersion : podVersion ,
249+ ToVersion : specVersion ,
250+ UpgradeNeeded : true ,
251+ UpgradeAllowed : false ,
252+ }
222253 }
223254 if specVersion .Major () != podVersion .Major () || specVersion .Minor () != podVersion .Minor () {
224255 // Is allowed, with `--database.auto-upgrade`
225256 return upgradeDecision {
257+ FromVersion : podVersion ,
258+ ToVersion : specVersion ,
226259 UpgradeNeeded : true ,
227260 UpgradeAllowed : true ,
228261 AutoUpgradeNeeded : true ,
229262 }
230263 }
231264 // Patch version change, rotate only
232265 return upgradeDecision {
266+ FromVersion : podVersion ,
267+ ToVersion : specVersion ,
233268 UpgradeNeeded : true ,
234269 UpgradeAllowed : true ,
235270 AutoUpgradeNeeded : false ,
@@ -343,7 +378,7 @@ func createRotateMemberPlan(log zerolog.Logger, member api.MemberStatus,
343378// createUpgradeMemberPlan creates a plan to upgrade (stop-recreateWithAutoUpgrade-stop-start) an existing
344379// member.
345380func createUpgradeMemberPlan (log zerolog.Logger , member api.MemberStatus ,
346- group api.ServerGroup , reason string ) api.Plan {
381+ group api.ServerGroup , reason string , imageName string , status api. DeploymentStatus ) api.Plan {
347382 log .Debug ().
348383 Str ("id" , member .ID ).
349384 Str ("role" , group .AsRole ()).
@@ -353,6 +388,11 @@ func createUpgradeMemberPlan(log zerolog.Logger, member api.MemberStatus,
353388 api .NewAction (api .ActionTypeUpgradeMember , group , member .ID , reason ),
354389 api .NewAction (api .ActionTypeWaitForMemberUp , group , member .ID ),
355390 }
391+ if status .CurrentImage == nil || status .CurrentImage .Image != imageName {
392+ plan = append (api.Plan {
393+ api .NewAction (api .ActionTypeSetCurrentImage , group , "" , reason ).SetImage (imageName ),
394+ }, plan ... )
395+ }
356396 return plan
357397}
358398
0 commit comments