Class: Docker::Compose::Shell

Inherits:
Object
  • Object
show all
Defined in:
lib/docker/compose/shell.rb

Overview

An easy-to-use interface for invoking commands and capturing their output. Instances of Shell can be interactive, which prints the command’s output to the terminal and also allows the user to interact with the command.

Instance Attribute Summary collapse

Class Method Summary collapse

Instance Method Summary collapse

Constructor Details

#initializeShell

Create an instance of Shell.



68
69
70
# File 'lib/docker/compose/shell.rb', line 68

def initialize
  @interactive = false
end

Instance Attribute Details

#interactiveBoolean

If true, commands run in the shell will have their stdio streams tied to the parent process so the user can view their output and send input to them. Commands’ stdout is still captured normally when they are interactive.

Note that interactivity doesn’t work very well because we use popen, which uses pipes to communicate with the child process and pipes have a fixed buffer size; the displayed output tends to “lag” behind the actual program, and bytes sent to stdin may not arrive until you send a lot of them!

TODO: solve pipe buffering issues, perhaps with a pty…

Returns:

  • (Boolean)


22
23
24
# File 'lib/docker/compose/shell.rb', line 22

def interactive
  @interactive
end

Class Method Details

.options(**opts) ⇒ Object

Convert Ruby keyword arguments into CLI parameters that are compatible with the syntax of golang’s flags package.

Options are translated to CLI parameters using the following convention: 1) Snake-case symbols are hyphenated, e.g. :no_foo => “–no-foo” 2) boolean values indicate a CLI flag; true includes the flag, false or nil omits it 3) other values indicate a CLI option that has a value. 4) single character values are passed as short options e.g. “-X V” 5) multi-character values are passed as long options e.g. “–XXX=V”



34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
# File 'lib/docker/compose/shell.rb', line 34

def self.options(**opts)
  flags = []

  # Transform opts into golang flags-style command line parameters;
  # append them to the command.
  opts.each do |kw, arg|
    if kw.length == 1
      if arg == true
        # true: boolean flag
        flags << "-#{kw}"
      elsif arg
        # truthey: option that has a value
        flags << "-#{kw}" << arg.to_s
      else
        # falsey: omit boolean flag
      end
    else
      kw = kw.to_s.gsub('_','-')
      if arg == true
        # true: boolean flag
        flags << "--#{kw}"
      elsif arg
        # truthey: option that has a value
        flags << "--#{kw}=#{arg}"
      else
        # falsey: omit boolean flag
      end
    end
  end

  flags
end

Instance Method Details

#command(*cmd) ⇒ Array

Run a shell command whose arguments and flags are expressed using some Rubyish sugar. This method accepts an arbitrary number of positional parameters; each parameter can be a Hash, an array, or a simple Object. Arrays and simple objects are appended to argv as “bare” words; Hashes are translated to golang flags and then appended to argv.

Examples:

Run docker-compose with complex parameters

command('docker-compose', {file: 'joe.yml'}, 'up', {d:true}, 'mysvc')

Returns:

  • (Array)

    an (Integer,String,String) triple of exitstatus, stdout and stderr

See Also:

  • for information on Hash-to-flag translation


84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
# File 'lib/docker/compose/shell.rb', line 84

def command(*cmd)
  argv = []

  cmd.each do |item|
    case item
    when Array
      # list of words to append to argv
      argv.concat(item.map { |e| e.to_s })
    when Hash
      # list of options to convert to CLI parameters
      argv.concat(self.class.options(item))
    else
      # single word to append to argv
      argv << item.to_s
    end
  end

  run(argv)
end