@@ -83,9 +83,12 @@ const (
8383// Deployment is the in process state of an ArangoDeployment.
8484type Deployment struct {
8585 apiObject * api.ArangoDeployment // API object
86- status api.DeploymentStatus // Internal status of the CR
87- config Config
88- deps Dependencies
86+ status struct {
87+ version int32
88+ last api.DeploymentStatus // Internal status copy of the CR
89+ }
90+ config Config
91+ deps Dependencies
8992
9093 eventCh chan * deploymentEvent
9194 stopCh chan struct {}
@@ -112,20 +115,20 @@ func New(config Config, deps Dependencies, apiObject *api.ArangoDeployment) (*De
112115 }
113116 d := & Deployment {
114117 apiObject : apiObject ,
115- status : * (apiObject .Status .DeepCopy ()),
116118 config : config ,
117119 deps : deps ,
118120 eventCh : make (chan * deploymentEvent , deploymentEventQueueSize ),
119121 stopCh : make (chan struct {}),
120122 eventsCli : deps .KubeCli .Core ().Events (apiObject .GetNamespace ()),
121123 clientCache : newClientCache (deps .KubeCli , apiObject ),
122124 }
125+ d .status .last = * (apiObject .Status .DeepCopy ())
123126 d .reconciler = reconcile .NewReconciler (deps .Log , d )
124127 d .resilience = resilience .NewResilience (deps .Log , d )
125128 d .resources = resources .NewResources (deps .Log , d )
126- if d .status .AcceptedSpec == nil {
129+ if d .status .last . AcceptedSpec == nil {
127130 // We've validated the spec, so let's use it from now.
128- d .status .AcceptedSpec = apiObject .Spec .DeepCopy ()
131+ d .status .last . AcceptedSpec = apiObject .Spec .DeepCopy ()
129132 }
130133
131134 go d .run ()
@@ -185,7 +188,7 @@ func (d *Deployment) send(ev *deploymentEvent) {
185188func (d * Deployment ) run () {
186189 log := d .deps .Log
187190
188- if d .status . Phase == api .DeploymentPhaseNone {
191+ if d .GetPhase () == api .DeploymentPhaseNone {
189192 // Create secrets
190193 if err := d .resources .EnsureSecrets (); err != nil {
191194 d .CreateEvent (k8sutil .NewErrorEvent ("Failed to create secrets" , err , d .GetAPIObject ()))
@@ -211,8 +214,9 @@ func (d *Deployment) run() {
211214 d .CreateEvent (k8sutil .NewErrorEvent ("Failed to create pods" , err , d .GetAPIObject ()))
212215 }
213216
214- d .status .Phase = api .DeploymentPhaseRunning
215- if err := d .updateCRStatus (); err != nil {
217+ status , lastVersion := d .GetStatus ()
218+ status .Phase = api .DeploymentPhaseRunning
219+ if err := d .UpdateStatus (status , lastVersion ); err != nil {
216220 log .Warn ().Err (err ).Msg ("update initial CR status failed" )
217221 }
218222 log .Info ().Msg ("start running..." )
@@ -277,13 +281,14 @@ func (d *Deployment) handleArangoDeploymentUpdatedEvent() error {
277281 }
278282
279283 specBefore := d .apiObject .Spec
280- if d .status .AcceptedSpec != nil {
281- specBefore = * d .status .AcceptedSpec
284+ status := d .status .last
285+ if d .status .last .AcceptedSpec != nil {
286+ specBefore = * status .AcceptedSpec .DeepCopy ()
282287 }
283288 newAPIObject := current .DeepCopy ()
284289 newAPIObject .Spec .SetDefaultsFrom (specBefore )
285290 newAPIObject .Spec .SetDefaults (d .apiObject .GetName ())
286- newAPIObject .Status = d . status
291+ newAPIObject .Status = status
287292 resetFields := specBefore .ResetImmutableFields (& newAPIObject .Spec )
288293 if len (resetFields ) > 0 {
289294 log .Debug ().Strs ("fields" , resetFields ).Msg ("Found modified immutable fields" )
@@ -309,9 +314,12 @@ func (d *Deployment) handleArangoDeploymentUpdatedEvent() error {
309314 return maskAny (fmt .Errorf ("failed to update ArangoDeployment spec: %v" , err ))
310315 }
311316 // Save updated accepted spec
312- d .status .AcceptedSpec = newAPIObject .Spec .DeepCopy ()
313- if err := d .updateCRStatus (); err != nil {
314- return maskAny (fmt .Errorf ("failed to update ArangoDeployment status: %v" , err ))
317+ {
318+ status , lastVersion := d .GetStatus ()
319+ status .AcceptedSpec = newAPIObject .Spec .DeepCopy ()
320+ if err := d .UpdateStatus (status , lastVersion ); err != nil {
321+ return maskAny (fmt .Errorf ("failed to update ArangoDeployment status: %v" , err ))
322+ }
315323 }
316324
317325 // Notify cluster of desired server count
@@ -351,7 +359,7 @@ func (d *Deployment) updateCRStatus(force ...bool) error {
351359 attempt := 0
352360 for {
353361 attempt ++
354- update .Status = d .status
362+ update .Status = d .status . last
355363 if update .GetDeletionTimestamp () == nil {
356364 ensureFinalizers (update )
357365 }
@@ -388,7 +396,7 @@ func (d *Deployment) updateCRSpec(newSpec api.DeploymentSpec) error {
388396 for {
389397 attempt ++
390398 update .Spec = newSpec
391- update .Status = d .status
399+ update .Status = d .status . last
392400 ns := d .apiObject .GetNamespace ()
393401 newAPIObject , err := d .deps .DatabaseCRCli .DatabaseV1alpha ().ArangoDeployments (ns ).Update (update )
394402 if err == nil {
@@ -417,7 +425,7 @@ func (d *Deployment) updateCRSpec(newSpec api.DeploymentSpec) error {
417425// Since there is no recovery from a failed deployment, use with care!
418426func (d * Deployment ) failOnError (err error , msg string ) {
419427 log .Error ().Err (err ).Msg (msg )
420- d .status .Reason = err .Error ()
428+ d .status .last . Reason = err .Error ()
421429 d .reportFailedStatus ()
422430}
423431
@@ -428,7 +436,7 @@ func (d *Deployment) reportFailedStatus() {
428436 log .Info ().Msg ("deployment failed. Reporting failed reason..." )
429437
430438 op := func () error {
431- d .status .Phase = api .DeploymentPhaseFailed
439+ d .status .last . Phase = api .DeploymentPhaseFailed
432440 err := d .updateCRStatus ()
433441 if err == nil || k8sutil .IsNotFound (err ) {
434442 // Status has been updated
0 commit comments