lib/kumogata/post_processing.rb in kumogata-0.3.11 vs lib/kumogata/post_processing.rb in kumogata-0.3.12

- old
+ new

@@ -16,25 +16,30 @@ return unless _post options = _post[:options] || {} @command_options.merge(options) + outputs = template['Outputs'] || {} + _post.fetch(:commands).each do |name, attrs| unless attrs.kind_of?(Hash) and attrs['command'] raise "Invalid post processing: #{name} => #{attrs.inspect}" end timing = [(attrs['after'] || TRIGGER_TIMING)].flatten.map {|i| i.to_sym } + command = attrs['command'] + validate_timing(name, timing) + validate_command_template(name, command, outputs) @commands[name] = { :after => timing, - :command => attrs['command'], + :command => command, } if (ssh = attrs['ssh']) - validate_ssh(name, ssh) + validate_ssh(name, ssh, outputs) @commands[name][:ssh] = ssh end end end @@ -68,11 +73,11 @@ raise "Unknown post processing timing: #{name} => #{timing.inspect}" end end end - def validate_ssh(name, ssh) + def validate_ssh(name, ssh, outputs) host, user, options = ssh.values_at('host', 'user', 'options') unless host and user raise "`host` and `user` is required for post processing ssh: #{name}" end @@ -86,10 +91,12 @@ ssh['host'] = "<%= #{host_key} #{host_value.to_s.inspect} %>" else ssh['host'] = host.to_s end + validate_command_template(name, ssh['host'], outputs) + if user.kind_of?(Hash) if user.keys != ['Key'] raise "Invalid post processing ssh user: #{name} => #{user.inspect}" end @@ -97,10 +104,12 @@ ssh['user'] = "<%= #{user_key} #{user_value.to_s.inspect} %>" else ssh['user'] = user.to_s end + validate_command_template(name, ssh['user'], outputs) + if options and not options.kind_of?(Hash) raise "Invalid post processing ssh options: #{name} => #{options.inspect}" end end @@ -168,9 +177,32 @@ end def run_shell_command(command, outputs) command = evaluate_command_template(command, outputs) Open3.capture3(command) + end + + def validate_command_template(name, command, outputs) + command = command.undent if @command_options[:undent] + trim_mode = @command_options[:trim_mode] + expected_outputs = Set.new + + scope = Object.new + scope.instance_variable_set(:@__expected_outputs__, expected_outputs) + + scope.instance_eval(<<-EOS) + def Key(name) + @__expected_outputs__ << name + end + + ERB.new(#{command.inspect}, nil, #{trim_mode.inspect}).result(binding) + EOS + + expected_outputs.each do |key| + unless outputs.keys.include?(key) + raise "Unknown output: #{name} => #{key.inspect}" + end + end end def evaluate_command_template(command, outputs) command = command.undent if @command_options[:undent] trim_mode = @command_options[:trim_mode]