@@ -87,7 +87,7 @@ func (c *DeploymentConfigController) Handle(config *appsapi.DeploymentConfig) er
87
87
glog .V (5 ).Infof ("Reconciling %s/%s" , config .Namespace , config .Name )
88
88
// There's nothing to reconcile until the version is nonzero.
89
89
if appsutil .IsInitialDeployment (config ) && ! appsutil .HasTrigger (config ) {
90
- return c .updateStatus (config , []* v1.ReplicationController {})
90
+ return c .updateStatus (config , []* v1.ReplicationController {}, true )
91
91
}
92
92
93
93
// List all ReplicationControllers to find also those we own but that no longer match our selector.
@@ -118,7 +118,18 @@ func (c *DeploymentConfigController) Handle(config *appsapi.DeploymentConfig) er
118
118
// the latest available information. Some deletions make take some time to complete so there
119
119
// is value in doing this.
120
120
if config .DeletionTimestamp != nil {
121
- return c .updateStatus (config , existingDeployments )
121
+ return c .updateStatus (config , existingDeployments , true )
122
+ }
123
+
124
+ // If the config is paused we shouldn't create new deployments for it.
125
+ if config .Spec .Paused {
126
+ // in order for revision history limit cleanup to work for paused
127
+ // deployments, we need to trigger it here
128
+ if err := c .cleanupOldDeployments (existingDeployments , config ); err != nil {
129
+ c .recorder .Eventf (config , v1 .EventTypeWarning , "DeploymentCleanupFailed" , "Couldn't clean up deployments: %v" , err )
130
+ }
131
+
132
+ return c .updateStatus (config , existingDeployments , true )
122
133
}
123
134
124
135
latestExists , latestDeployment := appsutil .LatestDeploymentInfo (config , existingDeployments )
@@ -128,42 +139,56 @@ func (c *DeploymentConfigController) Handle(config *appsapi.DeploymentConfig) er
128
139
return err
129
140
}
130
141
}
131
- // Process triggers and start an initial rollouts
142
+
143
+ // Never deploy with invalid or unresolved images
144
+ for i , container := range config .Spec .Template .Spec .Containers {
145
+ if len (strings .TrimSpace (container .Image )) == 0 {
146
+ glog .V (4 ).Infof ("Postponing rollout #%d for DeploymentConfig %s/%s because of invalid or unresolved image for container #%d (name=%s)" , config .Status .LatestVersion , config .Namespace , config .Name , i , container .Name )
147
+ return c .updateStatus (config , existingDeployments , true )
148
+ }
149
+ }
150
+
132
151
configCopy , err := appsutil .DeploymentConfigDeepCopy (config )
133
152
if err != nil {
134
153
glog .Errorf ("Unable to copy deployment config: %v" , err )
135
- return c .updateStatus (config , existingDeployments )
154
+ return c .updateStatus (config , existingDeployments , false )
136
155
}
137
- shouldTrigger , shouldSkip := triggerActivated ( configCopy , latestExists , latestDeployment , c . codec )
138
- if ! shouldSkip && shouldTrigger {
139
- configCopy . Status . LatestVersion ++
140
- return c . updateStatus ( configCopy , existingDeployments )
156
+ // Process triggers and start an initial rollouts
157
+ shouldTrigger , shouldSkip , err := triggerActivated ( configCopy , latestExists , latestDeployment , c . codec )
158
+ if err != nil {
159
+ return fmt . Errorf ( "triggerActivated failed: %v" , err )
141
160
}
142
- // Have to wait for the image trigger to get the image before proceeding.
143
- if shouldSkip && appsutil .IsInitialDeployment (config ) {
144
- return c .updateStatus (configCopy , existingDeployments )
161
+
162
+ if shouldSkip {
163
+ return c .updateStatus (configCopy , existingDeployments , true )
164
+ }
165
+
166
+ if shouldTrigger {
167
+ configCopy .Status .LatestVersion ++
168
+ _ , err := c .dn .DeploymentConfigs (configCopy .Namespace ).UpdateStatus (configCopy )
169
+ return err
145
170
}
171
+
146
172
// If the latest deployment already exists, reconcile existing deployments
147
173
// and return early.
148
174
if latestExists {
149
175
// If the latest deployment is still running, try again later. We don't
150
176
// want to compete with the deployer.
151
177
if ! appsutil .IsTerminatedDeployment (latestDeployment ) {
152
- return c .updateStatus (config , existingDeployments )
178
+ return c .updateStatus (config , existingDeployments , false )
153
179
}
154
180
155
181
return c .reconcileDeployments (existingDeployments , config , cm )
156
182
}
157
- // If the config is paused we shouldn't create new deployments for it.
158
- if config .Spec .Paused {
159
- // in order for revision history limit cleanup to work for paused
160
- // deployments, we need to trigger it here
161
- if err := c .cleanupOldDeployments (existingDeployments , config ); err != nil {
162
- c .recorder .Eventf (config , v1 .EventTypeWarning , "DeploymentCleanupFailed" , "Couldn't clean up deployments: %v" , err )
163
- }
164
183
165
- return c .updateStatus (config , existingDeployments )
184
+ // Never deploy with invalid or unresolved images
185
+ for i , container := range config .Spec .Template .Spec .Containers {
186
+ if len (strings .TrimSpace (container .Image )) == 0 {
187
+ glog .V (4 ).Infof ("Postponing rollout #%d for DeploymentConfig %s/%s because of invalid or unresolved image for container #%d (name=%s)" , config .Status .LatestVersion , config .Namespace , config .Name , i , container .Name )
188
+ return c .updateStatus (config , existingDeployments , true )
189
+ }
166
190
}
191
+
167
192
// No deployments are running and the latest deployment doesn't exist, so
168
193
// create the new deployment.
169
194
deployment , err := appsutil .MakeDeploymentV1 (config , c .codec )
@@ -186,17 +211,17 @@ func (c *DeploymentConfigController) Handle(config *appsapi.DeploymentConfig) er
186
211
if isOurs {
187
212
// If the deployment was already created, just move on. The cache could be
188
213
// stale, or another process could have already handled this update.
189
- return c .updateStatus (config , existingDeployments )
214
+ return c .updateStatus (config , existingDeployments , true )
190
215
} else {
191
- err = fmt .Errorf ("replication controller %s already exists and deployment config is not allowed to claim it. " , deployment .Name )
216
+ err = fmt .Errorf ("replication controller %s already exists and deployment config is not allowed to claim it" , deployment .Name )
192
217
c .recorder .Eventf (config , v1 .EventTypeWarning , "DeploymentCreationFailed" , "Couldn't deploy version %d: %v" , config .Status .LatestVersion , err )
193
- return c .updateStatus (config , existingDeployments )
218
+ return c .updateStatus (config , existingDeployments , true )
194
219
}
195
220
}
196
221
c .recorder .Eventf (config , v1 .EventTypeWarning , "DeploymentCreationFailed" , "Couldn't deploy version %d: %s" , config .Status .LatestVersion , err )
197
222
// We don't care about this error since we need to report the create failure.
198
223
cond := appsutil .NewDeploymentCondition (appsapi .DeploymentProgressing , kapi .ConditionFalse , appsapi .FailedRcCreateReason , err .Error ())
199
- _ = c .updateStatus (config , existingDeployments , * cond )
224
+ _ = c .updateStatus (config , existingDeployments , true , * cond )
200
225
return fmt .Errorf ("couldn't create deployment for deployment config %s: %v" , appsutil .LabelForDeploymentConfig (config ), err )
201
226
}
202
227
msg := fmt .Sprintf ("Created new replication controller %q for version %d" , created .Name , config .Status .LatestVersion )
@@ -210,7 +235,7 @@ func (c *DeploymentConfigController) Handle(config *appsapi.DeploymentConfig) er
210
235
}
211
236
212
237
cond := appsutil .NewDeploymentCondition (appsapi .DeploymentProgressing , kapi .ConditionTrue , appsapi .NewReplicationControllerReason , msg )
213
- return c .updateStatus (config , existingDeployments , * cond )
238
+ return c .updateStatus (config , existingDeployments , true , * cond )
214
239
}
215
240
216
241
// reconcileDeployments reconciles existing deployment replica counts which
@@ -292,13 +317,13 @@ func (c *DeploymentConfigController) reconcileDeployments(existingDeployments []
292
317
c .recorder .Eventf (config , v1 .EventTypeWarning , "ReplicationControllerCleanupFailed" , "Couldn't clean up replication controllers: %v" , err )
293
318
}
294
319
295
- return c .updateStatus (config , updatedDeployments )
320
+ return c .updateStatus (config , updatedDeployments , true )
296
321
}
297
322
298
323
// Update the status of the provided deployment config. Additional conditions will override any other condition in the
299
324
// deployment config status.
300
- func (c * DeploymentConfigController ) updateStatus (config * appsapi.DeploymentConfig , deployments []* v1.ReplicationController , additional ... appsapi.DeploymentCondition ) error {
301
- newStatus := calculateStatus (config , deployments , additional ... )
325
+ func (c * DeploymentConfigController ) updateStatus (config * appsapi.DeploymentConfig , deployments []* v1.ReplicationController , updateObservedGeneration bool , additional ... appsapi.DeploymentCondition ) error {
326
+ newStatus := calculateStatus (config , deployments , updateObservedGeneration , additional ... )
302
327
303
328
// NOTE: We should update the status of the deployment config only if we need to, otherwise
304
329
// we hotloop between updates.
@@ -390,7 +415,7 @@ func (c *DeploymentConfigController) cancelRunningRollouts(config *appsapi.Deplo
390
415
return nil
391
416
}
392
417
393
- func calculateStatus (config * appsapi.DeploymentConfig , rcs []* v1.ReplicationController , additional ... appsapi.DeploymentCondition ) appsapi.DeploymentConfigStatus {
418
+ func calculateStatus (config * appsapi.DeploymentConfig , rcs []* v1.ReplicationController , updateObservedGeneration bool , additional ... appsapi.DeploymentCondition ) appsapi.DeploymentConfigStatus {
394
419
// UpdatedReplicas represents the replicas that use the current deployment config template which means
395
420
// we should inform about the replicas of the latest deployment and not the active.
396
421
latestReplicas := int32 (0 )
@@ -408,10 +433,15 @@ func calculateStatus(config *appsapi.DeploymentConfig, rcs []*v1.ReplicationCont
408
433
unavailableReplicas = 0
409
434
}
410
435
436
+ generation := config .Status .ObservedGeneration
437
+ if updateObservedGeneration {
438
+ generation = config .Generation
439
+ }
440
+
411
441
status := appsapi.DeploymentConfigStatus {
412
442
LatestVersion : config .Status .LatestVersion ,
413
443
Details : config .Status .Details ,
414
- ObservedGeneration : config . Generation ,
444
+ ObservedGeneration : generation ,
415
445
Replicas : appsutil .GetStatusReplicaCountForDeployments (rcs ),
416
446
UpdatedReplicas : latestReplicas ,
417
447
AvailableReplicas : available ,
@@ -533,17 +563,17 @@ func (c *DeploymentConfigController) cleanupOldDeployments(existingDeployments [
533
563
// triggers were activated (config change or image change). The first bool indicates that
534
564
// the triggers are active and second indicates if we should skip the rollout because we
535
565
// are waiting for the trigger to complete update (waiting for image for example).
536
- func triggerActivated (config * appsapi.DeploymentConfig , latestExists bool , latestDeployment * v1.ReplicationController , codec runtime.Codec ) (bool , bool ) {
566
+ func triggerActivated (config * appsapi.DeploymentConfig , latestExists bool , latestDeployment * v1.ReplicationController , codec runtime.Codec ) (bool , bool , error ) {
537
567
if config .Spec .Paused {
538
- return false , false
568
+ return false , false , nil
539
569
}
540
570
imageTrigger := appsutil .HasImageChangeTrigger (config )
541
571
configTrigger := appsutil .HasChangeTrigger (config )
542
572
hasTrigger := imageTrigger || configTrigger
543
573
544
574
// no-op when no triggers are defined.
545
575
if ! hasTrigger {
546
- return false , false
576
+ return false , false , nil
547
577
}
548
578
549
579
// Handle initial rollouts
@@ -556,50 +586,49 @@ func triggerActivated(config *appsapi.DeploymentConfig, latestExists bool, lates
556
586
// TODO: Technically this is not a config change cause, but we will have to report the image that caused the trigger.
557
587
// In some cases it might be difficult because config can have multiple ICT.
558
588
appsutil .RecordConfigChangeCause (config )
559
- return true , false
589
+ return true , false , nil
560
590
}
561
591
glog .V (4 ).Infof ("Rolling out initial deployment for %s/%s deferred until its images are ready" , config .Namespace , config .Name )
562
- return false , true
592
+ return false , true , nil
563
593
}
564
594
// Rollout if we only have config change trigger.
565
595
if configTrigger {
566
596
glog .V (4 ).Infof ("Rolling out initial deployment for %s/%s" , config .Namespace , config .Name )
567
597
appsutil .RecordConfigChangeCause (config )
568
- return true , false
598
+ return true , false , nil
569
599
}
570
600
// We are waiting for the initial RC to be created.
571
- return false , false
601
+ return false , false , nil
572
602
}
573
603
574
604
// Wait for the RC to be created
575
605
if ! latestExists {
576
- return false , true
606
+ return false , false , nil
577
607
}
578
608
579
609
// We need existing deployment at this point to compare its template with current config template.
580
610
if latestDeployment == nil {
581
- return false , false
611
+ return false , false , nil
582
612
}
583
613
584
614
if imageTrigger {
585
615
if ok , imageNames := appsutil .HasUpdatedImages (config , latestDeployment ); ok {
586
616
glog .V (4 ).Infof ("Rolling out #%d deployment for %s/%s caused by image changes (%s)" , config .Status .LatestVersion + 1 , config .Namespace , config .Name , strings .Join (imageNames , "," ))
587
617
appsutil .RecordImageChangeCauses (config , imageNames )
588
- return true , false
618
+ return true , false , nil
589
619
}
590
620
}
591
621
592
622
if configTrigger {
593
623
isLatest , changes , err := appsutil .HasLatestPodTemplate (config , latestDeployment , codec )
594
624
if err != nil {
595
- glog .Errorf ("Error while checking for latest pod template in replication controller: %v" , err )
596
- return false , true
625
+ return false , false , fmt .Errorf ("error while checking for latest pod template in replication controller: %v" , err )
597
626
}
598
627
if ! isLatest {
599
628
glog .V (4 ).Infof ("Rolling out #%d deployment for %s/%s caused by config change, diff: %s" , config .Status .LatestVersion + 1 , config .Namespace , config .Name , changes )
600
629
appsutil .RecordConfigChangeCause (config )
601
- return true , false
630
+ return true , false , nil
602
631
}
603
632
}
604
- return false , false
633
+ return false , false , nil
605
634
}
0 commit comments