thoughtbot / cocaine

A small library for doing (command) lines.
https://robots.thoughtbot.com
Other
785 stars 55 forks source link

Interpolated arguments not working as intended #88

Closed scalp42 closed 9 years ago

scalp42 commented 9 years ago

First, thanks for the gem!

Please have a look at the following gist:

[1] pry(main)> require 'cocaine'
=> true
[2] pry(main)> parse = Cocaine::CommandLine.new(
[2] pry(main)*   "knife job start",
[2] pry(main)*   %q|:job -s :query --timeout 1200 --quorum 10% --no-wait|,
[2] pry(main)*   swallow_stderr: true
[2] pry(main)* )
=> #<Cocaine::CommandLine:0x007ffb72369190
 @binary="knife job start",
 @environment={},
 @expected_outcodes=[0],
 @logger=nil,
 @options={},
 @params=":job -s :query --timeout 1200 --quorum 10% --no-wait",
 @runner=#<Cocaine::CommandLine::PosixRunner:0x007ffb722396d0>,
 @runner_options={},
 @swallow_stderr=true>
[3] pry(main)> parse.command(job: 'uptime', query: 'name:loadbalancer-i*', swallow_stderr: true)
=> "knife job start 'uptime' -s 'name:loadbalancer-i*' --timeout 1200 --quorum 10% --no-wait 2>/dev/null"
[4] pry(main)> parse.run
Cocaine::ExitStatusError: Command 'knife job start :job -s :query --timeout 1200 --quorum 10% --no-wait 2>/dev/null' returned 100. Expected 0
Here is the command output:

invalid search query: ':query'
from /Users/scalp/.rvm/gems/ruby-2.2.1@gzbot/gems/cocaine-0.5.7/lib/cocaine/command_line.rb:92:in `run'`

Where I would expect parse.run to run the following:

"knife job start 'uptime' -s 'name:loadbalancer-i*' --timeout 1200 --quorum 10% --no-wait 2>/dev/null"

it appears to run without interpolating:

Cocaine::ExitStatusError: Command 'knife job start :job -s :query --timeout 1200 --quorum 10% --no-wait 2>/dev/null' returned 100. Expected 0

Any idea @jyurek ?

Thanks in advance!

scalp42 commented 9 years ago

I added some printing output in the interpolate method, the output is interesting when calling parse.run once:


    def interpolate(pattern, interpolations)
      ap "in interpolate method"
      interpolations = stringify_keys(interpolations)
      res = pattern.gsub(/:\{?(\w+)\b\}?/) do |match|
        key = match.tr(":{}", "")
        if interpolations.key?(key)
          shell_quote_all_values(interpolations[key])
        else
          match
        end
      end
      ap res
      res
    end
"in interpolate method"
"'uptime' -s 'name:loadbalancer-i*' --timeout 1200 --quorum 10% --no-wait"
"in interpolate method"
":job -s :query --timeout 1200 --quorum 10% --no-wait"

Looks like it gets executed twice disregarding the interpolated one.

jyurek commented 9 years ago

The problem is that you have to pass your interpolations to run, not command. The command method just returns the command that will be run given the interpolations you pass in. It does not run the command and it does not change the state of the object.