diff --git a/.devcontainer/install-medal-hook.sh b/.devcontainer/install-medal-hook.sh new file mode 100755 index 0000000..8d9e61a --- /dev/null +++ b/.devcontainer/install-medal-hook.sh @@ -0,0 +1,10 @@ +#!/bin/sh + +if [ $# -eq 1 ]; then + download_str="download/$1" +else + download_str=latest/download +fi + +curl -SL https://github.com/tom-tan/medal-hook/releases/${download_str}/medal-hook-linux-x86_64.tar.gz \ + | tar xC /usr/bin diff --git a/ep3 b/ep3 index 93de943..5a2e14d 100755 --- a/ep3 +++ b/ep3 @@ -3,5 +3,6 @@ basedir=$(cd $(dirname $0) && pwd -P) export EP3_LIBPATH=$basedir/lib/ep3 export EP3_TEMPLATE_DIR=$basedir/share/ep3 +export EP3_EXT_PATH=$basedir/lib/ep3/extensions $EP3_LIBPATH/ep3.rb "$@" diff --git a/ep3-runner b/ep3-runner index 808c43e..516cd06 100755 --- a/ep3-runner +++ b/ep3-runner @@ -41,6 +41,8 @@ rescue => e end if $0 == __FILE__ + extensions = [] + parser = OptionParser.new parser.banner = "Usage: #{$0} cwl [jobfile]" parser.on('--tmpdir=TMP', 'directory for temporary files') @@ -48,6 +50,9 @@ if $0 == __FILE__ parser.on('--leave-tmpdir', 'do not remove temporary directory') parser.on('--debug', 'enable debug output') parser.on('--quiet', 'disable information output') + parser.on('--extension', 'specify extension') { |ext| + extensions.push ext + } parser.on('--version', 'show version information') { system('git describe', :chdir => File.dirname($0)) exit @@ -84,6 +89,15 @@ if $0 == __FILE__ end begin + unless extensions.empty? + ret_hook = run_cmd("#{basedir}/ep3 hook --extensions=#{extensions.join(',')} #{target_arg}") + if ret_hook.include? 'interrupted' + exit 1 + elsif not ret_hook['success'] + exit ret_hook.fetch('return', 1) + end + end + qopt = quiet ? '--quiet ' : '' dopt = debug ? '--debug ' : '' ret_run = run_cmd("#{basedir}/ep3 run #{qopt}#{dopt}#{target_arg} #{job}", debug) diff --git a/lib/ep3/ep3-hook.rb b/lib/ep3/ep3-hook.rb new file mode 100644 index 0000000..f70885d --- /dev/null +++ b/lib/ep3/ep3-hook.rb @@ -0,0 +1,68 @@ +#!/usr/bin/env ruby +require 'optparse' +require 'fileutils' + +def ep3_hook(args) + extensions = [] + + parser = OptionParser.new + parser.banner = "Usage: ep3 list [options]" + parser.on('--target-dir=DIR') + parser.on('--extensions=EXTS') { |exts| + extensions = exts.split(',') + } + + opts = parser.getopts(args) + unless args.empty? + puts parser.help + exit + end + + dir = if opts.include? 'target-dir' + opts['target-dir'] + else + raise '--target-dir is needed' + end + unless Dir.exist? dir + raise "Directory not found: #{dir}" + end + + unless ENV.include? 'EP3_EXT_PATH' + raise 'EP3_EXT_PATH is necessary to apply extensions' + end + extPaths = ENV['EP3_EXT_PATH'].split(':') + + extFiles = extensions.map{ |e| + ret = extPaths.find{ |path| + File.exist?(File.join(path, e)) + } + if ret.nil? + raise "Extension #{e} not found" + end + File.join(ret, e, 'extension.yml') + } + extArgs = extFiles.map{ |e| "--hook=#{e}" } + apply(File.join(dir, 'workdir', 'job.yml'), extArgs) +end + +def apply(network, exts) + orig = "#{network}.orig" + unless File.exist?(orig) + FileUtils.mv(network, orig) + end + ret = system("medal-hook #{orig} #{exts.join(' ')} > #{network}") + ret = 0 + return 1 unless ret + stepdir = File.join(File.dirname(network), 'steps') + if Dir.exist?(stepdir) + Dir.glob("#{stepdir}/*") { |d| + r = apply(File.join(d, 'job.yml'), exts) + ret = (ret and r) + } + end + ret +end + +if $0 == __FILE__ + ep3_hook(ARGV) +end diff --git a/lib/ep3/ep3.rb b/lib/ep3/ep3.rb index 54a1dad..2b53237 100755 --- a/lib/ep3/ep3.rb +++ b/lib/ep3/ep3.rb @@ -3,6 +3,7 @@ require_relative 'ep3-init' require_relative 'ep3-run' require_relative 'ep3-list' +require_relative 'ep3-hook' if $0 == __FILE__ parser = OptionParser.new @@ -13,7 +14,7 @@ init initialize a configuration for a given workflow run run the workflow for a given input list show the output object for the given workflow - stop (stop running the workflow) + hook apply extensions to Petri Nets for a given workflow resume (not yet implemented) EOS @@ -28,7 +29,7 @@ when 'init' then ep3_init(ARGV) when 'run' then ep3_run(ARGV) when 'list' then ep3_list(ARGV) - when 'stop' then ep3_stop(ARGV) + when 'hook' then ep3_hook(ARGV) when 'resume' then ep3_resume(ARGV) else raise "No such subcommand: #{cmd}" end