@@ -8,7 +8,7 @@ SCRIPTDIR="$( cd "$( dirname "${UNALIASED_SCRIPT_NAME}" )" && pwd )"
8
8
SCRIPTNAME=$( echo $0 | sed ' s#.*/##g' )
9
9
MINARGS=1
10
10
MAXARGS=99
11
- PREREQUISITES=" curl jq mail column"
11
+ PREREQUISITES=" curl jq mail column tput rev "
12
12
13
13
# Determine if this shell is interactive:
14
14
ISINTERACTIVESHELL=true
@@ -52,6 +52,7 @@ FOLDER_URL=$( echo ${CROMWELL_URL} | sed -e 's#ht.*://##g' )
52
52
CROMWELL_METADATA_PARAMETERS=" excludeKey=submittedFiles&expandSubWorkflows=true"
53
53
54
54
CURL_CONNECT_TIMEOUT=5
55
+ CURL_MAX_TIMEOUT=10
55
56
56
57
PING_CMD=' ping -c1 -W1 -w10'
57
58
if [[ $( uname ) == " Darwin" ]] ; then
@@ -100,7 +101,7 @@ function turtleDead()
100
101
function simpleUsage()
101
102
{
102
103
if [[ $# -ne 0 ]] ; then
103
- usage | grep ${1} | sed -e ' s#\(.*]\).*#\1#g' -e " s#^[ \\ t]*#Usage: ${SCRIPTNAME} #g"
104
+ usage | grep " ${1} " | sed -e ' s#\(.*]\).*#\1#g' -e " s#^[ \\ t]*#Usage: ${SCRIPTNAME} #g"
104
105
else
105
106
echo -e " Usage: ${SCRIPTNAME} SUB-COMMAND [options]"
106
107
echo -e " Run and inspect workflows on a Cromwell server."
@@ -125,7 +126,9 @@ function usage()
125
126
echo -e " Supported Subcommands:"
126
127
echo -e " "
127
128
echo -e " Start/Stop workflows:"
128
- echo -e " submit <wdl> <inputs_json> [options_json] [included_wdl_zip_file] Submit a new workflow"
129
+ echo -e " submit [-w] <wdl> <inputs_json> [options_json] [included_wdl_zip_file] Submit a new workflow"
130
+ echo -e " -w Wait for workflow to transition from 'Submitted' to some other status"
131
+ echo -e " before ${SCRIPTNAME} exits"
129
132
echo -e " included_wdl_zip_file Zip file containing any WDL files included in the input WDL"
130
133
echo -e " "
131
134
echo -e " abort [workflow-id] [[workflow-id]...] Abort a running workflow."
@@ -402,12 +405,178 @@ function populateWorkflowIdAndServerUrl()
402
405
fi
403
406
}
404
407
408
+ function _turtleSpinner()
409
+ {
410
+ # Require a flag file to be given to this function.
411
+ # This keeps it safe.
412
+ if [[ $# -ne 1 ]] ; then
413
+ return 1
414
+ fi
415
+
416
+ local flagFile=$1
417
+
418
+ # Let's be fancy and make turtles that are walking while we wait:
419
+ local tmpTurtFile=$( makeTemp )
420
+ local turtFile=$( makeTemp )
421
+ local turtRFile=$( makeTemp )
422
+ turtle & > ${tmpTurtFile}
423
+ sed ' s#^ ##g' ${tmpTurtFile} > ${turtFile}
424
+ rev ${turtFile} | sed -e ' s$/$#$g' -e ' s#\\#/#g' -e ' s$#$\\$g' -e ' s#(#)#g' -e ' s#)#(#g' > ${turtRFile}
425
+
426
+ # Set up some loop variables:
427
+ local i=3
428
+ local incrementString=" +1"
429
+ local curTurtFile=${turtFile}
430
+
431
+ # Let's loop while the ${flagFile} exists.
432
+ # Note that this will be spun off into its own thread:
433
+ while [ -f ${flagFile} ] ; do
434
+ # Create padding for turtle:
435
+ padding=$( printf " %${i} s" " " )
436
+
437
+ # Display our turtle, moved a little to the right:
438
+ cat ${curTurtFile} | sed -e " s#^#${padding} #g"
439
+ sleep 0.1
440
+
441
+ # Move the cursor back up to the top line of the turtle
442
+ # so we create the illusion of movement:
443
+ tput cuu 6
444
+
445
+ # Now we update our loop variables in a clever way
446
+ # so that the turtle will go back and forth.
447
+ let i=i${incrementString}
448
+ if [ $i -eq 15 ] ; then
449
+ incrementString=" -1"
450
+ curTurtFile=${turtRFile}
451
+ elif [ $i -eq 0 ] ; then
452
+ incrementString=" +1"
453
+ curTurtFile=${turtFile}
454
+ fi
455
+
456
+ done & # The & here spins this off as a background thread/process
457
+ }
458
+
459
+ function waitOnSubmittedStatus()
460
+ {
461
+ local id=$1
462
+ local cromwellServerUrl=$2
463
+
464
+ echo " Waiting on status to progress from 'Submitted' ..."
465
+ echo
466
+
467
+ # Use tput to save the cursor position:
468
+ tput sc
469
+
470
+ # The turtle starts 9 rows above where the cursor is at this point,
471
+ # so if we need to move it, we have to move the cursor there before
472
+ # we output anything:
473
+ tput cuu 9
474
+
475
+ # Reserve the name for a file whose non-existence will cause
476
+ # the following loop to exit.
477
+ # This is good because all temp files made with `makeTemp`
478
+ # are automatically removed at exit, so this sub-process
479
+ # will always die gracefully.
480
+ local flagFile=$( makeTemp)
481
+ echo ' TEST' > ${flagFile}
482
+
483
+ # Kick off a turtle spinner...
484
+ _turtleSpinner ${flagFile}
485
+
486
+ # Now we check the status periodically and if we get a new one
487
+ # Other than `Submitted` we can tell the other process to finish.
488
+ local gotNewStatus=false
489
+ local isDone=false
490
+ local nChecks=0
491
+ local statusFile=$( makeTemp )
492
+ local r
493
+ while ! $isDone ; do
494
+ # Wait for a little bit so we don't kill the server:
495
+ sleep 2
496
+
497
+ # Check the status of our last submission:
498
+ status ${id} ${cromwellServerUrl} & > ${statusFile}
499
+ r=$?
500
+ grep -q ' ^[ \t]*"status": "Submitted",' ${statusFile}
501
+
502
+ # We could no longer field the status as `Submitted`, so we're done.
503
+ if [ $? -eq 1 ] && [ $r -ne 2 ] ; then
504
+ gotNewStatus=true
505
+ fi
506
+
507
+ # Check if our status changed yet:
508
+ if $gotNewStatus ; then
509
+ isDone=true
510
+
511
+ # Delete the flag file to end the display process:
512
+ rm -f ${flagFile}
513
+
514
+ # Wait for the _turtleSpinner to exit:
515
+ wait
516
+
517
+ # Clear out the lines from our fancy animation:
518
+ tput el; echo ; tput el; echo ; tput el; echo ; tput el; echo ; tput el; echo ; tput el; echo ; tput el; echo ; tput el; echo
519
+ tput cuu 8
520
+
521
+ # Display the status file:
522
+ cat ${statusFile} | sed ' s#^Using ##g'
523
+
524
+ # If we have waited too long, then we quit:
525
+ elif [[ $nChecks -ge 10 ]] ; then
526
+ isDone=true
527
+
528
+ # Delete the flag file to end the display process:
529
+ rm -f ${flagFile}
530
+
531
+ # Wait for the _turtleSpinner to exit:
532
+ wait
533
+
534
+ echo " {\" id\" :\" ${id} \" ,\" status\" :\" Submitted\" }"
535
+ error " WARNING: Could not validate submission status with server. Try again later."
536
+ break
537
+ fi
538
+
539
+ let nChecks=$nChecks +1
540
+ done
541
+
542
+ # Restore cursor position:
543
+ tput rc
544
+
545
+ # Add a line for padding:
546
+ echo
547
+
548
+ # Send a proper return code:
549
+ if $gotNewStatus ; then
550
+ return 0
551
+ else
552
+ return 1
553
+ fi
554
+ }
555
+
405
556
# Submit a workflow and arguments to the Cromwell Server
406
557
function submit()
407
558
{
559
+ local doWait=false
560
+
561
+ # Handle Arguments:
562
+ local OPTIND
563
+ while getopts " w" opt ; do
564
+ case ${opt} in
565
+ w)
566
+ doWait=true
567
+ ;;
568
+ * )
569
+ invalidSubCommand submit flag ${OPTARG}
570
+ ;;
571
+ esac
572
+ done
573
+ shift $(( OPTIND- 1 ))
574
+
575
+ # ----------------------------------------
576
+
408
577
assertCanCommunicateWithServer $CROMWELL_URL
409
578
410
- local response=$( curl --connect-timeout $CURL_CONNECT_TIMEOUT -s -F workflowSource=@${1} ${2: + -F workflowInputs=@ ${2} } ${3: + -F workflowOptions=@ ${3} } ${4: + -F workflowDependencies=@ ${4} } ${CROMWELL_URL} /api/workflows/v1)
579
+ local response=$( curl --connect-timeout $CURL_CONNECT_TIMEOUT --max-time $CURL_MAX_TIMEOUT - s -F workflowSource=@${1} ${2: + -F workflowInputs=@ ${2} } ${3: + -F workflowOptions=@ ${3} } ${4: + -F workflowDependencies=@ ${4} } ${CROMWELL_URL} /api/workflows/v1)
411
580
local r=$?
412
581
413
582
# Check to make sure that we actually submitted the job correctly
@@ -449,6 +618,11 @@ function submit()
449
618
450
619
echo -e " $( date +%Y%m%d_%H%M%S) \t${CROMWELL_URL} \t${id} \t$( basename ${1} ) \tSubmitted" >> ${CROMWELL_SUBMISSIONS_FILE}
451
620
621
+ # Now that we've submitted our task, we should see if we have to wait:
622
+ if $doWait ; then
623
+ waitOnSubmittedStatus ${id} ${CROMWELL_URL}
624
+ fi
625
+
452
626
return 0
453
627
}
454
628
@@ -459,7 +633,7 @@ function status()
459
633
460
634
assertCanCommunicateWithServer $2
461
635
local f=$( makeTemp )
462
- curl --connect-timeout $CURL_CONNECT_TIMEOUT -s ${2} /api/workflows/v1/${1} /status > $f
636
+ curl --connect-timeout $CURL_CONNECT_TIMEOUT --max-time $CURL_MAX_TIMEOUT - s ${2} /api/workflows/v1/${1} /status > $f
463
637
[[ $? -ne 0 ]] && error " Could not connect to Cromwell server." && return 2
464
638
465
639
grep -qE ' "Failed"|"Aborted"|"fail"' $f
@@ -487,7 +661,7 @@ function logs()
487
661
{
488
662
assertCanCommunicateWithServer $2
489
663
turtle
490
- curl --connect-timeout $CURL_CONNECT_TIMEOUT -s ${2} /api/workflows/v1/${1} /logs | jq .
664
+ curl --connect-timeout $CURL_CONNECT_TIMEOUT --max-time $CURL_MAX_TIMEOUT - s ${2} /api/workflows/v1/${1} /logs | jq .
491
665
checkPipeStatus " Could not connect to Cromwell server." " Could not parse JSON output from cromwell server."
492
666
return $?
493
667
}
@@ -497,7 +671,7 @@ function metadata()
497
671
{
498
672
assertCanCommunicateWithServer $2
499
673
turtle
500
- curl --connect-timeout $CURL_CONNECT_TIMEOUT --compressed -s ${2} /api/workflows/v1/${1} /metadata? ${CROMWELL_METADATA_PARAMETERS} | jq .
674
+ curl --connect-timeout $CURL_CONNECT_TIMEOUT --max-time $CURL_MAX_TIMEOUT -- compressed -s ${2} /api/workflows/v1/${1} /metadata? ${CROMWELL_METADATA_PARAMETERS} | jq .
501
675
checkPipeStatus " Could not connect to Cromwell server." " Could not parse JSON output from cromwell server."
502
676
return $?
503
677
}
@@ -507,7 +681,7 @@ function slim-metadata()
507
681
{
508
682
assertCanCommunicateWithServer $2
509
683
turtle
510
- curl --connect-timeout $CURL_CONNECT_TIMEOUT --compressed -s " ${2} /api/workflows/v1/$1 /metadata?includeKey=executionStatus&includeKey=backendStatus&expandSubWorkflows=true" | jq .
684
+ curl --connect-timeout $CURL_CONNECT_TIMEOUT --max-time $CURL_MAX_TIMEOUT -- compressed -s " ${2} /api/workflows/v1/$1 /metadata?includeKey=executionStatus&includeKey=backendStatus&expandSubWorkflows=true" | jq .
511
685
checkPipeStatus " Could not connect to Cromwell server." " Could not parse JSON output from cromwell server."
512
686
return $?
513
687
}
@@ -518,7 +692,7 @@ function execution-status-count()
518
692
assertCanCommunicateWithServer $2
519
693
turtle
520
694
f=$( makeTemp )
521
- curl --connect-timeout $CURL_CONNECT_TIMEOUT --compressed -s ${2} /api/workflows/v1/$1 /metadata? ${CROMWELL_METADATA_PARAMETERS} > $f
695
+ curl --connect-timeout $CURL_CONNECT_TIMEOUT --max-time $CURL_MAX_TIMEOUT -- compressed -s ${2} /api/workflows/v1/$1 /metadata? ${CROMWELL_METADATA_PARAMETERS} > $f
522
696
[[ $? -ne 0 ]] && error " Could not connect to Cromwell server." && return 9
523
697
524
698
# Make sure the query succeeded:
@@ -548,7 +722,7 @@ function abort()
548
722
{
549
723
assertCanCommunicateWithServer $2
550
724
turtle
551
- response=$( curl --connect-timeout $CURL_CONNECT_TIMEOUT -X POST --header " Content-Type: application/json" --header " Accept: application/json" " ${2} /api/workflows/v1/${1} /abort" )
725
+ response=$( curl --connect-timeout $CURL_CONNECT_TIMEOUT --max-time $CURL_MAX_TIMEOUT - X POST --header " Content-Type: application/json" --header " Accept: application/json" " ${2} /api/workflows/v1/${1} /abort" )
552
726
local r=$?
553
727
echo $response
554
728
return $r
@@ -582,9 +756,28 @@ function list()
582
756
583
757
# If we need to update the data, do so here:
584
758
if $doUpdate ; then
585
- error " Updating cached status list"
759
+ error " Updating cached status list... "
586
760
local tmpFile srv id runSt
587
761
762
+ # Use tput to save the cursor position:
763
+ tput sc
764
+
765
+ # The turtle starts 7 rows above where the cursor is at this point,
766
+ # so if we need to move it, we have to move the cursor there before
767
+ # we output anything:
768
+ tput cuu 7
769
+
770
+ # Reserve the name for a file whose non-existence will cause
771
+ # the following loop to exit.
772
+ # This is good because all temp files made with `makeTemp`
773
+ # are automatically removed at exit, so this sub-process
774
+ # will always die gracefully.
775
+ local flagFile=$( makeTemp)
776
+ echo ' TEST' > ${flagFile}
777
+
778
+ # Kick off a turtle spinner...
779
+ _turtleSpinner ${flagFile}
780
+
588
781
# Make a copy of our file because we'll be modifying it:
589
782
tmpFile=$( makeTemp )
590
783
cp ${CROMWELL_SUBMISSIONS_FILE} ${tmpFile}
@@ -602,6 +795,13 @@ function list()
602
795
fi
603
796
fi
604
797
done < ${tmpFile}
798
+
799
+ # Remove the flag file to kill the spinner and wait for it to finish:
800
+ rm ${flagFile}
801
+ wait
802
+
803
+ # Restore cursor position:
804
+ tput rc
605
805
fi
606
806
607
807
# If we have to colorize the output, we do so:
0 commit comments