@@ -44,6 +44,21 @@ export class NodeCommand extends BaseCommand {
4444 this . keyManager = opts . keyManager
4545 this . accountManager = opts . accountManager
4646 this . keytoolDepManager = opts . keytoolDepManager
47+ this . _portForwards = [ ]
48+ }
49+
50+ /**
51+ * stops and closes the port forwards
52+ * @returns {Promise<void> }
53+ */
54+ async close ( ) {
55+ if ( this . _portForwards ) {
56+ for ( const srv of this . _portForwards ) {
57+ await this . k8 . stopPortForward ( srv )
58+ }
59+ }
60+
61+ this . _portForwards = [ ]
4762 }
4863
4964 async checkNetworkNodePod ( namespace , nodeId ) {
@@ -637,10 +652,11 @@ export class NodeCommand extends BaseCommand {
637652 title : 'Check node proxies are ACTIVE' ,
638653 task : async ( ctx , parentTask ) => {
639654 const subTasks = [ ]
655+ let localPort = constants . LOCAL_NODE_PROXY_START_PORT
640656 for ( const nodeId of ctx . config . nodeIds ) {
641657 subTasks . push ( {
642658 title : `Check proxy for node: ${ chalk . yellow ( nodeId ) } ` ,
643- task : async ( ) => await self . checkNetworkNodeProxyUp ( ctx . config . namespace , nodeId )
659+ task : async ( ) => await self . checkNetworkNodeProxyUp ( nodeId , localPort ++ )
644660 } )
645661 }
646662
@@ -664,45 +680,47 @@ export class NodeCommand extends BaseCommand {
664680 throw new FullstackTestingError ( `Error starting node: ${ e . message } ` , e )
665681 } finally {
666682 await self . accountManager . close ( )
683+ await self . close ( )
667684 }
668685
669686 return true
670687 }
671688
672- async checkNetworkNodeProxyUp ( namespace , nodeId , maxAttempts = 10 , delay = 5000 ) {
689+ /**
690+ * Check if the network node proxy is up, requires close() to be called after
691+ * @param nodeId the node id
692+ * @param localPort the local port to forward to
693+ * @param maxAttempts the maximum number of attempts
694+ * @param delay the delay between attempts
695+ * @returns {Promise<boolean> } true if the proxy is up
696+ */
697+ async checkNetworkNodeProxyUp ( nodeId , localPort , maxAttempts = 10 , delay = 5000 ) {
673698 const podArray = await this . k8 . getPodsByLabel ( [ `app=haproxy-${ nodeId } ` , 'fullstack.hedera.com/type=haproxy' ] )
674699
675700 let attempts = 0
676701 if ( podArray . length > 0 ) {
677702 const podName = podArray [ 0 ] . metadata . name
703+ this . _portForwards . push ( await this . k8 . portForward ( podName , localPort , 5555 ) )
704+ try {
705+ await this . k8 . testConnection ( 'localhost' , localPort )
706+ } catch ( e ) {
707+ throw new FullstackTestingError ( `failed to create port forward for '${ nodeId } ' proxy on port ${ localPort } ` , e )
708+ }
678709
679710 while ( attempts < maxAttempts ) {
680- const logResponse = await this . k8 . kubeClient . readNamespacedPodLog (
681- podName ,
682- namespace ,
683- 'haproxy' ,
684- undefined ,
685- undefined ,
686- 1024 ,
687- undefined ,
688- undefined ,
689- undefined ,
690- 4
691- )
692-
693- if ( logResponse . response . statusCode !== 200 ) {
694- throw new FullstackTestingError ( `Expected pod ${ podName } log query to execute successful, but instead got a status of ${ logResponse . response . statusCode } ` )
695- }
711+ try {
712+ const status = await this . getNodeProxyStatus ( `http://localhost:${ localPort } /v2/services/haproxy/stats/native?type=backend` )
713+ if ( status === 'UP' ) {
714+ this . logger . debug ( `Proxy ${ podName } is UP. [attempt: ${ attempts } /${ maxAttempts } ]` )
715+ return true
716+ }
696717
697- this . logger . debug ( `Received HAProxy log from ${ podName } ` , { output : logResponse . body } )
698- if ( logResponse . body . includes ( 'Server be_servers/server1 is UP' ) ) {
699- this . logger . debug ( `Proxy ${ podName } is UP [attempt: ${ attempts } /${ maxAttempts } ]` )
700- return true
718+ attempts ++
719+ this . logger . debug ( `Proxy ${ podName } is not UP. Checking again in ${ delay } ms ... [attempt: ${ attempts } /${ maxAttempts } ]` )
720+ await sleep ( delay )
721+ } catch ( e ) {
722+ throw new FullstackTestingError ( `failed to create port forward for '${ nodeId } ' proxy on port ${ localPort } ` , e )
701723 }
702-
703- attempts ++
704- this . logger . debug ( `Proxy ${ podName } is not UP. Checking again in ${ delay } ms ... [attempt: ${ attempts } /${ maxAttempts } ]` )
705- await sleep ( delay )
706724 }
707725 }
708726
@@ -967,4 +985,32 @@ export class NodeCommand extends BaseCommand {
967985 }
968986 }
969987 }
988+
989+ async getNodeProxyStatus ( url ) {
990+ try {
991+ this . logger . debug ( `Fetching proxy status from: ${ url } ` )
992+ const res = await fetch ( url , {
993+ method : 'GET' ,
994+ signal : AbortSignal . timeout ( 5000 ) ,
995+ headers : {
996+ Authorization : `Basic ${ Buffer . from (
997+ `${ constants . NODE_PROXY_USER_ID } :${ constants . NODE_PROXY_PASSWORD } ` ) . toString (
998+ 'base64' ) } `
999+ }
1000+ } )
1001+ const response = await res . json ( )
1002+
1003+ if ( res . status === 200 ) {
1004+ const status = response [ 0 ] ?. stats ?. filter (
1005+ ( stat ) => stat . name === 'http_backend' ) [ 0 ] ?. stats ?. status
1006+ this . logger . debug ( `Proxy status: ${ status } ` )
1007+ return status
1008+ } else {
1009+ this . logger . debug ( `Proxy request status code: ${ res . status } ` )
1010+ return null
1011+ }
1012+ } catch ( e ) {
1013+ this . logger . error ( `Error in fetching proxy status: ${ e . message } ` , e )
1014+ }
1015+ }
9701016}
0 commit comments