@@ -4,6 +4,7 @@ import { DEFAULT_COMMAND } from 'ui/components/container-shell/component';
44
55const Terminal = window . Terminal ;
66const FitAddon = window . FitAddon . FitAddon ;
7+ const MAX_RECONNECT_ATTEMPTS = 4 ;
78
89function decodeTerminalData ( data ) {
910 try {
@@ -19,12 +20,28 @@ function terminalCloseAction(options) {
1920 }
2021
2122 if ( ! options . hasHello && ! options . createAttempted ) {
22- return options . entryStatus === 'ended' ? 'ended' : 'create ' ;
23+ return options . entryStatus === 'ended' ? 'ended' : 'probe ' ;
2324 }
2425
2526 return options . status === 'ended' ? 'none' : 'reconnect' ;
2627}
2728
29+ function terminalBrokerStatusAction ( httpStatus , brokerStatus ) {
30+ if ( httpStatus === 404 ) {
31+ return 'create' ;
32+ }
33+ if ( httpStatus === 403 || httpStatus === 409 ) {
34+ return 'rotate' ;
35+ }
36+ if ( typeof httpStatus !== 'number' || httpStatus < 200 || httpStatus >= 300 ) {
37+ return 'error' ;
38+ }
39+ if ( brokerStatus === 'ended' || brokerStatus === 'error' ) {
40+ return 'ended' ;
41+ }
42+ return 'connect' ;
43+ }
44+
2845export default Ember . Component . extend ( ThrottledResize , {
2946 classNames : [ 'workspace-terminal' ] ,
3047 workspace : Ember . inject . service ( 'console-workspace' ) ,
@@ -74,6 +91,7 @@ export default Ember.Component.extend(ThrottledResize, {
7491 this . setProperties ( {
7592 hasHello : false ,
7693 createAttempted : false ,
94+ reconnectAttempts : 0 ,
7795 status : 'connecting' ,
7896 } ) ;
7997 this . connect ( false ) ;
@@ -129,7 +147,50 @@ export default Ember.Component.extend(ThrottledResize, {
129147 return ;
130148 }
131149
132- this . openSocket ( this . get ( 'workspace' ) . brokerUrl ( this . get ( 'entry' ) ) , false ) ;
150+ this . probeBrokerSession ( ) ;
151+ } ,
152+
153+ probeBrokerSession ( ) {
154+ let workspace = this . get ( 'workspace' ) ;
155+ let entry = this . get ( 'entry' ) ;
156+
157+ this . set ( 'status' , 'connecting' ) ;
158+ workspace . brokerStatus ( entry ) . then ( ( response ) => {
159+ if ( this . get ( 'userClosed' ) || this . isDestroyed || this . isDestroying ) {
160+ return ;
161+ }
162+ this . applyBrokerStatusAction ( terminalBrokerStatusAction ( 200 , response && response . status ) ) ;
163+ } ) . catch ( ( error ) => {
164+ if ( this . get ( 'userClosed' ) || this . isDestroyed || this . isDestroying ) {
165+ return ;
166+ }
167+ this . applyBrokerStatusAction ( terminalBrokerStatusAction ( error && error . status , null ) ) ;
168+ } ) ;
169+ } ,
170+
171+ applyBrokerStatusAction ( action ) {
172+ let workspace = this . get ( 'workspace' ) ;
173+ let entry = this . get ( 'entry' ) ;
174+
175+ if ( action === 'create' ) {
176+ workspace . updateSession ( entry , { brokerReady : false , status : 'initializing' } ) ;
177+ this . set ( 'createAttempted' , false ) ;
178+ this . createBrokerSession ( ) ;
179+ } else if ( action === 'rotate' ) {
180+ workspace . rotateBrokerIdentity ( entry ) ;
181+ this . set ( 'createAttempted' , false ) ;
182+ this . createBrokerSession ( ) ;
183+ } else if ( action === 'ended' ) {
184+ this . setTerminalInputEnabled ( false ) ;
185+ this . set ( 'status' , 'ended' ) ;
186+ workspace . updateSession ( entry , { brokerReady : false , status : 'ended' } ) ;
187+ } else if ( action === 'connect' ) {
188+ this . openSocket ( workspace . brokerUrl ( entry ) , false ) ;
189+ } else {
190+ this . setTerminalInputEnabled ( false ) ;
191+ this . set ( 'status' , 'error' ) ;
192+ workspace . updateSession ( entry , { status : 'error' } ) ;
193+ }
133194 } ,
134195
135196 createBrokerSession ( ) {
@@ -154,10 +215,14 @@ export default Ember.Component.extend(ThrottledResize, {
154215 return ;
155216 }
156217 return this . get ( 'workspace' ) . createBrokerSession ( this . get ( 'entry' ) , access ) ;
157- } ) . then ( ( ) => {
218+ } ) . then ( ( response ) => {
158219 if ( this . get ( 'userClosed' ) || this . isDestroyed || this . isDestroying ) {
159220 return ;
160221 }
222+ if ( terminalBrokerStatusAction ( 200 , response && response . status ) === 'ended' ) {
223+ this . applyBrokerStatusAction ( 'ended' ) ;
224+ return ;
225+ }
161226 this . get ( 'workspace' ) . updateSession ( this . get ( 'entry' ) , {
162227 brokerReady : true ,
163228 status : 'connecting' ,
@@ -205,9 +270,7 @@ export default Ember.Component.extend(ThrottledResize, {
205270
206271 if ( action === 'ended' ) {
207272 this . set ( 'status' , 'ended' ) ;
208- } else if ( action === 'create' ) {
209- this . connect ( true ) ;
210- } else if ( action === 'reconnect' ) {
273+ } else if ( action === 'probe' || action === 'reconnect' ) {
211274 this . setTerminalInputEnabled ( false ) ;
212275 this . set ( 'status' , 'disconnected' ) ;
213276 this . get ( 'workspace' ) . updateSession ( this . get ( 'entry' ) , { status : 'disconnected' } ) ;
@@ -334,6 +397,11 @@ export default Ember.Component.extend(ThrottledResize, {
334397 scheduleReconnect ( ) {
335398 this . cancelReconnect ( ) ;
336399 let attempt = this . incrementProperty ( 'reconnectAttempts' ) ;
400+ if ( attempt > MAX_RECONNECT_ATTEMPTS ) {
401+ this . set ( 'status' , 'error' ) ;
402+ this . get ( 'workspace' ) . updateSession ( this . get ( 'entry' ) , { status : 'error' } ) ;
403+ return ;
404+ }
337405 let delay = Math . min ( 10000 , 500 * Math . pow ( 2 , Math . min ( attempt , 5 ) ) ) ;
338406 this . _reconnectTimer = Ember . run . later ( this , ( ) => {
339407 this . set ( 'createAttempted' , false ) ;
@@ -380,4 +448,8 @@ export default Ember.Component.extend(ThrottledResize, {
380448 } ,
381449} ) ;
382450
383- export { decodeTerminalData , terminalCloseAction } ;
451+ export {
452+ decodeTerminalData ,
453+ terminalBrokerStatusAction ,
454+ terminalCloseAction ,
455+ } ;
0 commit comments