forked from cloudfoundry/cli
-
Notifications
You must be signed in to change notification settings - Fork 0
/
poll_start.go
129 lines (115 loc) · 3.3 KB
/
poll_start.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
package shared
import (
"context"
"code.cloudfoundry.org/cli/actor/actionerror"
"code.cloudfoundry.org/cli/actor/sharedaction"
"code.cloudfoundry.org/cli/actor/v2action"
"code.cloudfoundry.org/cli/command"
"code.cloudfoundry.org/cli/command/translatableerror"
)
func PollStart(ui command.UI, config command.Config,
messages <-chan sharedaction.LogMessage,
logErrs <-chan error,
appState <-chan v2action.ApplicationStateChange,
apiWarnings <-chan string,
apiErrs <-chan error,
stopStreaming context.CancelFunc) (apiError error) {
handleMessage := func(message sharedaction.LogMessage) {
if message.Staging() {
ui.DisplayLogMessage(message, false)
}
}
handleLogErr := func(logErr error) {
switch logErr.(type) {
case actionerror.LogCacheTimeoutError:
ui.DisplayWarning("timeout connecting to log server, no log will be shown")
default:
ui.DisplayWarning("Failed to retrieve logs from Log Cache: {{.Error}}", map[string]interface{}{
"Error": logErr,
})
}
}
for appState != nil || apiWarnings != nil || apiErrs != nil {
select {
case message, ok := <-messages:
if !ok {
messages = nil
continue
}
handleMessage(message)
case state, ok := <-appState:
if !ok {
appState = nil
continue
}
switch state {
case v2action.ApplicationStateStopping:
ui.DisplayNewline()
ui.DisplayText("Stopping app...")
case v2action.ApplicationStateStaging:
ui.DisplayNewline()
ui.DisplayText("Staging app and tracing logs...")
case v2action.ApplicationStateStarting:
defer func() {
ui.DisplayNewline()
ui.DisplayText("Waiting for app to start...")
}()
}
case warning, ok := <-apiWarnings:
if !ok {
apiWarnings = nil
continue
}
ui.DisplayWarning(warning)
case logErr, ok := <-logErrs:
if !ok {
logErrs = nil
continue
}
handleLogErr(logErr)
case e, ok := <-apiErrs:
if !ok {
apiErrs = nil
continue
}
switch err := e.(type) {
case actionerror.StagingFailedError:
apiError = translatableerror.StagingFailedError{Message: err.Error()}
case actionerror.StagingFailedNoAppDetectedError:
apiError = translatableerror.StagingFailedNoAppDetectedError{BinaryName: config.BinaryName(), Message: err.Error()}
case actionerror.StagingTimeoutError:
apiError = translatableerror.StagingTimeoutError{AppName: err.AppName, Timeout: err.Timeout}
case actionerror.ApplicationInstanceCrashedError:
apiError = translatableerror.ApplicationUnableToStartError{AppName: err.Name, BinaryName: config.BinaryName()}
case actionerror.ApplicationInstanceFlappingError:
apiError = translatableerror.ApplicationUnableToStartError{AppName: err.Name, BinaryName: config.BinaryName()}
case actionerror.StartupTimeoutError:
apiError = translatableerror.StartupTimeoutError{AppName: err.Name, BinaryName: config.BinaryName()}
default:
apiError = err
}
// if an api error occurred, exit immediately
stopStreaming()
return apiError
}
}
stopStreaming()
// Consume any pending streamed messages
for messages != nil || logErrs != nil {
select {
case message, ok := <-messages:
if !ok {
messages = nil
continue
}
handleMessage(message)
case logErr, ok := <-logErrs:
if !ok {
logErrs = nil
continue
}
handleLogErr(logErr)
}
}
return nil
}