Skip to content

Commit dd2ee3d

Browse files
committed
merge w/ build failure fixup
1 parent 9983952 commit dd2ee3d

File tree

5 files changed

+67
-35
lines changed

5 files changed

+67
-35
lines changed

pkg/build/controller/buildpod/controller.go

+33-16
Original file line numberDiff line numberDiff line change
@@ -183,40 +183,56 @@ func (bc *BuildPodController) HandlePod(pod *kapi.Pod) error {
183183
build.Status.Message = ""
184184
}
185185
}
186+
187+
needsUpdate := false
186188
// Update the build object when it progress to a next state or the reason for
187-
// the current state changed.
188-
if (!common.HasBuildPodNameAnnotation(build) || build.Status.Phase != nextStatus || build.Status.Phase == buildapi.BuildPhaseFailed) || !buildutil.IsBuildComplete(build) {
189+
// the current state changed. Do not touch builds that are complete
190+
// because we'd potentially be overwriting build state information set by the
191+
// build pod directly.
192+
if (!common.HasBuildPodNameAnnotation(build) || build.Status.Phase != nextStatus) && !buildutil.IsBuildComplete(build) {
193+
needsUpdate = true
189194
common.SetBuildPodNameAnnotation(build, pod.Name)
190195
reason := ""
191196
if len(build.Status.Reason) > 0 {
192197
reason = " (" + string(build.Status.Reason) + ")"
193198
}
194199
glog.V(4).Infof("Updating build %s/%s status %s -> %s%s", build.Namespace, build.Name, build.Status.Phase, nextStatus, reason)
195200
build.Status.Phase = nextStatus
196-
197-
if buildutil.IsBuildComplete(build) {
198-
common.SetBuildCompletionTimeAndDuration(build)
199-
switch build.Status.Phase {
200-
case buildapi.BuildPhaseComplete:
201-
bc.recorder.Eventf(build, kapi.EventTypeNormal, buildapi.BuildCompletedEventReason, fmt.Sprintf(buildapi.BuildCompletedEventMessage, build.Namespace, build.Name))
202-
case buildapi.BuildPhaseError, buildapi.BuildPhaseFailed:
203-
bc.recorder.Eventf(build, kapi.EventTypeNormal, buildapi.BuildFailedEventReason, fmt.Sprintf(buildapi.BuildFailedEventMessage, build.Namespace, build.Name))
204-
}
205-
}
206201
if build.Status.Phase == buildapi.BuildPhaseRunning {
207202
now := unversioned.Now()
208203
build.Status.StartTimestamp = &now
209204
bc.recorder.Eventf(build, kapi.EventTypeNormal, buildapi.BuildRunningEventReason, fmt.Sprintf(buildapi.BuildRunningEventMessage, build.Namespace, build.Name))
210205
}
206+
}
207+
208+
// we're going to get pod relist events for completed/failed pods,
209+
// there's no reason to re-update the build and rerun
210+
// HandleBuildCompletion if we've already done it for this
211+
// build previously.
212+
buildWasComplete := build.Status.CompletionTimestamp != nil
213+
if !buildWasComplete && buildutil.IsBuildComplete(build) && build.Status.Phase != buildapi.BuildPhaseCancelled {
214+
needsUpdate = common.SetBuildCompletionTimeAndDuration(build)
215+
}
216+
if needsUpdate {
211217
if err := bc.buildUpdater.Update(build.Namespace, build); err != nil {
212218
return fmt.Errorf("failed to update build %s/%s: %v", build.Namespace, build.Name, err)
213219
}
214220
glog.V(4).Infof("Build %s/%s status was updated to %s", build.Namespace, build.Name, build.Status.Phase)
215-
216-
if buildutil.IsBuildComplete(build) {
217-
common.HandleBuildCompletion(build, bc.runPolicies)
218-
}
219221
}
222+
// if the build was not previously marked complete but it's complete now,
223+
// handle completion for it. otherwise ignore it because we've already
224+
// handled its completion previously.
225+
if !buildWasComplete && buildutil.IsBuildComplete(build) {
226+
common.SetBuildCompletionTimeAndDuration(build)
227+
switch build.Status.Phase {
228+
case buildapi.BuildPhaseComplete:
229+
bc.recorder.Eventf(build, kapi.EventTypeNormal, buildapi.BuildCompletedEventReason, fmt.Sprintf(buildapi.BuildCompletedEventMessage, build.Namespace, build.Name))
230+
case buildapi.BuildPhaseError, buildapi.BuildPhaseFailed:
231+
bc.recorder.Eventf(build, kapi.EventTypeNormal, buildapi.BuildFailedEventReason, fmt.Sprintf(buildapi.BuildFailedEventMessage, build.Namespace, build.Name))
232+
}
233+
common.HandleBuildCompletion(build, bc.runPolicies)
234+
}
235+
220236
return nil
221237
}
222238

@@ -260,6 +276,7 @@ func (bc *BuildPodController) HandleBuildPodDeletion(pod *kapi.Pod) error {
260276
if err := bc.buildUpdater.Update(build.Namespace, build); err != nil {
261277
return fmt.Errorf("Failed to update build %s/%s: %v", build.Namespace, build.Name, err)
262278
}
279+
common.HandleBuildCompletion(build, bc.runPolicies)
263280
}
264281
return nil
265282
}

pkg/build/controller/buildpod/controller_test.go

+3-3
Original file line numberDiff line numberDiff line change
@@ -158,7 +158,7 @@ func TestHandlePod(t *testing.T) {
158158
outStatus: buildapi.BuildPhaseComplete,
159159
podStatus: kapi.PodSucceeded,
160160
exitCode: 0,
161-
startTimestamp: nil,
161+
startTimestamp: curtime,
162162
completionTimestamp: curtime,
163163
},
164164
{ // 4
@@ -167,7 +167,7 @@ func TestHandlePod(t *testing.T) {
167167
outStatus: buildapi.BuildPhaseFailed,
168168
podStatus: kapi.PodFailed,
169169
exitCode: -1,
170-
startTimestamp: nil,
170+
startTimestamp: curtime,
171171
completionTimestamp: curtime,
172172
},
173173
{ // 5
@@ -177,7 +177,7 @@ func TestHandlePod(t *testing.T) {
177177
podStatus: kapi.PodSucceeded,
178178
exitCode: 0,
179179
buildUpdater: &errBuildUpdater{},
180-
startTimestamp: nil,
180+
startTimestamp: curtime,
181181
completionTimestamp: curtime,
182182
},
183183
{ // 6

pkg/build/controller/common/util.go

+14-3
Original file line numberDiff line numberDiff line change
@@ -11,12 +11,23 @@ import (
1111
utilruntime "k8s.io/kubernetes/pkg/util/runtime"
1212
)
1313

14-
func SetBuildCompletionTimeAndDuration(build *buildapi.Build) {
14+
// SetBuildCompletionTimeAndDuration will set the build completion timestamp
15+
// to the current time if it is nil. It will also set the start timestamp to
16+
// the same value if it is nil. Returns true if the build object was
17+
// modified.
18+
func SetBuildCompletionTimeAndDuration(build *buildapi.Build) bool {
19+
if build.Status.CompletionTimestamp != nil {
20+
return false
21+
}
1522
now := unversioned.Now()
1623
build.Status.CompletionTimestamp = &now
17-
if build.Status.StartTimestamp != nil {
18-
build.Status.Duration = build.Status.CompletionTimestamp.Rfc3339Copy().Time.Sub(build.Status.StartTimestamp.Rfc3339Copy().Time)
24+
// apparently this build completed so fast we didn't see the pod running event,
25+
// so just use the completion time as the start time.
26+
if build.Status.StartTimestamp == nil {
27+
build.Status.StartTimestamp = &now
1928
}
29+
build.Status.Duration = build.Status.CompletionTimestamp.Rfc3339Copy().Time.Sub(build.Status.StartTimestamp.Rfc3339Copy().Time)
30+
return true
2031
}
2132

2233
func HandleBuildCompletion(build *buildapi.Build, runPolicies []policy.RunPolicy) {

pkg/build/controller/controller_test.go

+3-3
Original file line numberDiff line numberDiff line change
@@ -447,23 +447,23 @@ func TestCancelBuild(t *testing.T) {
447447
inStatus: buildapi.BuildPhaseNew,
448448
outStatus: buildapi.BuildPhaseCancelled,
449449
exitCode: 0,
450-
startTimestamp: nil,
450+
startTimestamp: curtime,
451451
completionTimestamp: curtime,
452452
},
453453
{ // 1
454454
inStatus: buildapi.BuildPhasePending,
455455
outStatus: buildapi.BuildPhaseCancelled,
456456
podStatus: kapi.PodRunning,
457457
exitCode: 0,
458-
startTimestamp: nil,
458+
startTimestamp: curtime,
459459
completionTimestamp: curtime,
460460
},
461461
{ // 2
462462
inStatus: buildapi.BuildPhaseRunning,
463463
outStatus: buildapi.BuildPhaseCancelled,
464464
podStatus: kapi.PodRunning,
465465
exitCode: 0,
466-
startTimestamp: nil,
466+
startTimestamp: curtime,
467467
completionTimestamp: curtime,
468468
},
469469
{ // 3

pkg/build/controller/policy/policy.go

+14-10
Original file line numberDiff line numberDiff line change
@@ -142,17 +142,21 @@ func handleComplete(lister buildclient.BuildLister, updater buildclient.BuildUpd
142142
}
143143
for _, build := range nextBuilds {
144144
// TODO: replace with informer notification requeueing in the future
145-
build.Annotations[buildapi.BuildAcceptedAnnotation] = uuid.NewRandom().String()
146-
err := wait.Poll(500*time.Millisecond, 5*time.Second, func() (bool, error) {
147-
err := updater.Update(build.Namespace, build)
148-
if err != nil && errors.IsConflict(err) {
149-
glog.V(5).Infof("Error updating build %s/%s: %v (will retry)", build.Namespace, build.Name, err)
150-
return false, nil
145+
146+
// only set the annotation once.
147+
if _, ok := build.Annotations[buildapi.BuildAcceptedAnnotation]; !ok {
148+
build.Annotations[buildapi.BuildAcceptedAnnotation] = uuid.NewRandom().String()
149+
err := wait.Poll(500*time.Millisecond, 5*time.Second, func() (bool, error) {
150+
err := updater.Update(build.Namespace, build)
151+
if err != nil && errors.IsConflict(err) {
152+
glog.V(5).Infof("Error updating build %s/%s: %v (will retry)", build.Namespace, build.Name, err)
153+
return false, nil
154+
}
155+
return true, err
156+
})
157+
if err != nil {
158+
return err
151159
}
152-
return true, err
153-
})
154-
if err != nil {
155-
return err
156160
}
157161
}
158162
return nil

0 commit comments

Comments
 (0)