@@ -4,8 +4,11 @@ import (
4
4
"fmt"
5
5
"time"
6
6
7
+ "k8s.io/apimachinery/pkg/api/errors"
7
8
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
8
9
"k8s.io/apimachinery/pkg/fields"
10
+ utilruntime "k8s.io/apimachinery/pkg/util/runtime"
11
+ "k8s.io/apimachinery/pkg/util/wait"
9
12
"k8s.io/apimachinery/pkg/watch"
10
13
11
14
buildapi "github.com/openshift/origin/pkg/build/apis/build"
@@ -18,41 +21,91 @@ var (
18
21
ErrBuildDeleted = fmt .Errorf ("build was deleted" )
19
22
)
20
23
24
+ type ErrWatchError struct {
25
+ error
26
+ }
27
+
21
28
// WaitForRunningBuild waits until the specified build is no longer New or Pending. Returns true if
22
29
// the build ran within timeout, false if it did not, and an error if any other error state occurred.
23
30
// The last observed Build state is returned.
24
31
func WaitForRunningBuild (buildClient buildtypedclient.BuildsGetter , build * buildapi.Build , timeout time.Duration ) (* buildapi.Build , bool , error ) {
25
32
fieldSelector := fields .OneTermEqualSelector ("metadata.name" , build .Name )
26
- options := metav1.ListOptions {FieldSelector : fieldSelector .String (), ResourceVersion : build .ResourceVersion }
27
- w , err := buildClient .Builds (build .Namespace ).Watch (options )
28
- if err != nil {
29
- return build , false , err
30
- }
33
+ options := metav1.ListOptions {FieldSelector : fieldSelector .String (), ResourceVersion : "0" }
31
34
32
- observed := build
33
- _ , err = watch .Until (timeout , w , func (event watch.Event ) (bool , error ) {
34
- obj , ok := event .Object .(* buildapi.Build )
35
- if ! ok {
36
- return false , fmt .Errorf ("received unknown object while watching for builds: %T" , event .Object )
37
- }
38
- observed = obj
35
+ done := make (chan interface {}, 1 )
36
+ var resultBuild * buildapi.Build
37
+ var success bool
38
+ var resultErr error
39
39
40
- if event .Type == watch .Deleted {
41
- return false , ErrBuildDeleted
42
- }
43
- switch obj .Status .Phase {
44
- case buildapi .BuildPhaseRunning , buildapi .BuildPhaseComplete , buildapi .BuildPhaseFailed , buildapi .BuildPhaseError , buildapi .BuildPhaseCancelled :
45
- return true , nil
46
- case buildapi .BuildPhaseNew , buildapi .BuildPhasePending :
47
- default :
48
- return false , ErrUnknownBuildPhase
40
+ deadline := time .Now ().Add (timeout )
41
+ go func () {
42
+ defer close (done )
43
+ defer utilruntime .HandleCrash ()
44
+
45
+ for time .Now ().Before (deadline ) {
46
+
47
+ // make sure the build has not been deleted before we start trying to watch on it because
48
+ // we won't get a watch event for it if it's been deleted (because we are watching starting
49
+ // at resource version 0).
50
+ _ , err := buildClient .Builds (build .Namespace ).Get (build .Name , metav1.GetOptions {})
51
+ if err != nil {
52
+ resultErr = err
53
+ if errors .IsNotFound (err ) {
54
+ resultErr = ErrBuildDeleted
55
+ }
56
+ return
57
+ }
58
+
59
+ w , err := buildClient .Builds (build .Namespace ).Watch (options )
60
+ if err != nil {
61
+ resultErr = err
62
+ return
63
+ }
64
+
65
+ _ , err = watch .Until (timeout , w , func (event watch.Event ) (bool , error ) {
66
+ if event .Type == watch .Error {
67
+ return false , ErrWatchError {fmt .Errorf ("watch event type error: %v" , event )}
68
+ }
69
+ obj , ok := event .Object .(* buildapi.Build )
70
+ if ! ok {
71
+ return false , fmt .Errorf ("received unknown object while watching for builds: %T" , event .Object )
72
+ }
73
+
74
+ if event .Type == watch .Deleted {
75
+ return false , ErrBuildDeleted
76
+ }
77
+
78
+ switch obj .Status .Phase {
79
+ case buildapi .BuildPhaseRunning , buildapi .BuildPhaseComplete , buildapi .BuildPhaseFailed , buildapi .BuildPhaseError , buildapi .BuildPhaseCancelled :
80
+ resultBuild = obj
81
+ return true , nil
82
+ case buildapi .BuildPhaseNew , buildapi .BuildPhasePending :
83
+ default :
84
+ return false , ErrUnknownBuildPhase
85
+ }
86
+
87
+ return false , nil
88
+ })
89
+
90
+ if err != nil {
91
+ if _ , ok := err .(ErrWatchError ); ok {
92
+ continue
93
+ }
94
+ resultErr = err
95
+ success = false
96
+ resultBuild = nil
97
+ return
98
+ }
99
+ success = true
100
+ return
49
101
}
102
+ }()
50
103
51
- return false , nil
52
- })
53
- if err != nil {
54
- return nil , false , err
104
+ select {
105
+ case <- time .After (timeout ):
106
+ return nil , false , wait .ErrWaitTimeout
107
+ case <- done :
108
+ return resultBuild , success , resultErr
55
109
}
56
110
57
- return observed , true , nil
58
111
}
0 commit comments