docker-compose 0.3.0 → 0.3.1
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/docker-compose.gemspec +2 -0
- data/lib/docker/compose.rb +0 -1
- data/lib/docker/compose/rake_tasks.rb +1 -1
- data/lib/docker/compose/session.rb +10 -8
- data/lib/docker/compose/version.rb +1 -1
- metadata +15 -2
- data/lib/docker/compose/shell.rb +0 -210
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 03253ecae7a727eaba835a5042ec07bd4af06aee
|
4
|
+
data.tar.gz: f82b24d7ade2a1621eab41bb8dc8da1188b7afef
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 49ae1c849beb8c5b9623faea4fd73057be4660979f1ea570e4ce013deb4d4e6807498090ae741859a530036ce420b068a587153514aa7b77b9c41072e7d72f59
|
7
|
+
data.tar.gz: 3350c7abbd3ae4fcefba35661b82abc314de369f8b7105b0430c10fd7b7031efc9e10e550d47da23898250fc00d76c9bb715d224fe8ebcf0cfbace0623f00d54
|
data/docker-compose.gemspec
CHANGED
@@ -19,6 +19,8 @@ Gem::Specification.new do |spec|
|
|
19
19
|
spec.executables = spec.files.grep(%r{^exe/}) { |f| File.basename(f) }
|
20
20
|
spec.require_paths = ["lib"]
|
21
21
|
|
22
|
+
spec.add_dependency "backticks", "~> 0.1"
|
23
|
+
|
22
24
|
spec.add_development_dependency "bundler", "~> 1.10"
|
23
25
|
spec.add_development_dependency "rake", "~> 10.0"
|
24
26
|
spec.add_development_dependency "rspec"
|
data/lib/docker/compose.rb
CHANGED
@@ -53,7 +53,7 @@ module Docker::Compose
|
|
53
53
|
self.extra_server_env = {}
|
54
54
|
yield self if block_given?
|
55
55
|
|
56
|
-
@shell =
|
56
|
+
@shell = Backticks::Runner.new
|
57
57
|
@session = Docker::Compose::Session.new(@shell, dir:dir, file:file)
|
58
58
|
@net_info = Docker::Compose::NetInfo.new
|
59
59
|
|
@@ -1,3 +1,5 @@
|
|
1
|
+
require 'backticks'
|
2
|
+
|
1
3
|
module Docker::Compose
|
2
4
|
# A Ruby OOP interface to a docker-compose session. A session is bound to
|
3
5
|
# a particular directory and docker-compose file (which are set at initialize
|
@@ -13,7 +15,7 @@ module Docker::Compose
|
|
13
15
|
class Session
|
14
16
|
attr_reader :dir, :file
|
15
17
|
|
16
|
-
def initialize(shell=
|
18
|
+
def initialize(shell=Backticks::Runner.new,
|
17
19
|
dir:Dir.pwd, file:'docker-compose.yml')
|
18
20
|
@shell = shell
|
19
21
|
@dir = dir
|
@@ -89,20 +91,20 @@ module Docker::Compose
|
|
89
91
|
#
|
90
92
|
# @see Docker::Compose::Shell#command
|
91
93
|
#
|
92
|
-
# @param [Array]
|
93
|
-
#
|
94
|
+
# @param [Array] args command-line arguments in the format accepted by
|
95
|
+
# Backticks::Runner#command
|
94
96
|
# @return [String] output of the command
|
95
97
|
# @raise [RuntimeError] if command fails
|
96
|
-
def run!(*
|
98
|
+
def run!(*args)
|
97
99
|
project_opts = {
|
98
100
|
file: @file
|
99
101
|
}
|
100
102
|
|
101
103
|
Dir.chdir(@dir) do
|
102
|
-
|
103
|
-
|
104
|
-
|
105
|
-
|
104
|
+
cmd = @shell.command('docker-compose', project_opts, *args).join
|
105
|
+
status, out, err= cmd.status, cmd.captured_output, cmd.captured_error
|
106
|
+
status.success? || raise(Error.new(args.first, status, err))
|
107
|
+
out
|
106
108
|
end
|
107
109
|
end
|
108
110
|
end
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: docker-compose
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.3.
|
4
|
+
version: 0.3.1
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Tony Spataro
|
@@ -10,6 +10,20 @@ bindir: exe
|
|
10
10
|
cert_chain: []
|
11
11
|
date: 2015-12-24 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
|
+
- !ruby/object:Gem::Dependency
|
14
|
+
name: backticks
|
15
|
+
requirement: !ruby/object:Gem::Requirement
|
16
|
+
requirements:
|
17
|
+
- - "~>"
|
18
|
+
- !ruby/object:Gem::Version
|
19
|
+
version: '0.1'
|
20
|
+
type: :runtime
|
21
|
+
prerelease: false
|
22
|
+
version_requirements: !ruby/object:Gem::Requirement
|
23
|
+
requirements:
|
24
|
+
- - "~>"
|
25
|
+
- !ruby/object:Gem::Version
|
26
|
+
version: '0.1'
|
13
27
|
- !ruby/object:Gem::Dependency
|
14
28
|
name: bundler
|
15
29
|
requirement: !ruby/object:Gem::Requirement
|
@@ -78,7 +92,6 @@ files:
|
|
78
92
|
- lib/docker/compose/net_info.rb
|
79
93
|
- lib/docker/compose/rake_tasks.rb
|
80
94
|
- lib/docker/compose/session.rb
|
81
|
-
- lib/docker/compose/shell.rb
|
82
95
|
- lib/docker/compose/version.rb
|
83
96
|
homepage: https://github.com/xeger/docker-compose
|
84
97
|
licenses:
|
data/lib/docker/compose/shell.rb
DELETED
@@ -1,210 +0,0 @@
|
|
1
|
-
require 'open3'
|
2
|
-
require 'pty'
|
3
|
-
|
4
|
-
module Docker::Compose
|
5
|
-
# An easy-to-use interface for invoking commands and capturing their output.
|
6
|
-
# Instances of Shell can be interactive, which prints the command's output
|
7
|
-
# to the terminal and also allows the user to interact with the command.
|
8
|
-
class Shell
|
9
|
-
# If true, commands run in the shell will have their stdio streams tied
|
10
|
-
# to the parent process so the user can view their output and send input
|
11
|
-
# to them. Commands' stdout is still captured normally when they are
|
12
|
-
# interactive.
|
13
|
-
#
|
14
|
-
# Note that interactivity doesn't work very well because we use popen,
|
15
|
-
# which uses pipes to communicate with the child process and pipes have
|
16
|
-
# a fixed buffer size; the displayed output tends to "lag" behind the
|
17
|
-
# actual program, and bytes sent to stdin may not arrive until you send
|
18
|
-
# a lot of them!
|
19
|
-
#
|
20
|
-
# @return [Boolean]
|
21
|
-
attr_accessor :interactive
|
22
|
-
|
23
|
-
# Convert Ruby keyword arguments into CLI parameters that are compatible
|
24
|
-
# with the syntax of golang's flags package.
|
25
|
-
#
|
26
|
-
# Options are translated to CLI parameters using the following convention:
|
27
|
-
# 1) Snake-case symbols are hyphenated, e.g. :no_foo => "--no-foo"
|
28
|
-
# 2) boolean values indicate a CLI flag; true includes the flag, false or nil omits it
|
29
|
-
# 3) other values indicate a CLI option that has a value.
|
30
|
-
# 4) single character values are passed as short options e.g. "-X V"
|
31
|
-
# 5) multi-character values are passed as long options e.g. "--XXX=V"
|
32
|
-
#
|
33
|
-
def self.options(**opts)
|
34
|
-
flags = []
|
35
|
-
|
36
|
-
# Transform opts into golang flags-style command line parameters;
|
37
|
-
# append them to the command.
|
38
|
-
opts.each do |kw, arg|
|
39
|
-
if kw.length == 1
|
40
|
-
if arg == true
|
41
|
-
# true: boolean flag
|
42
|
-
flags << "-#{kw}"
|
43
|
-
elsif arg
|
44
|
-
# truthey: option that has a value
|
45
|
-
flags << "-#{kw}" << arg.to_s
|
46
|
-
else
|
47
|
-
# falsey: omit boolean flag
|
48
|
-
end
|
49
|
-
else
|
50
|
-
kw = kw.to_s.gsub('_','-')
|
51
|
-
if arg == true
|
52
|
-
# true: boolean flag
|
53
|
-
flags << "--#{kw}"
|
54
|
-
elsif arg
|
55
|
-
# truthey: option that has a value
|
56
|
-
flags << "--#{kw}=#{arg}"
|
57
|
-
else
|
58
|
-
# falsey: omit boolean flag
|
59
|
-
end
|
60
|
-
end
|
61
|
-
end
|
62
|
-
|
63
|
-
flags
|
64
|
-
end
|
65
|
-
|
66
|
-
# Create an instance of Shell.
|
67
|
-
def initialize
|
68
|
-
@interactive = false
|
69
|
-
end
|
70
|
-
|
71
|
-
# Run a shell command whose arguments and flags are expressed using some
|
72
|
-
# Rubyish sugar. This method accepts an arbitrary number of positional
|
73
|
-
# parameters; each parameter can be a Hash, an array, or a simple Object.
|
74
|
-
# Arrays and simple objects are appended to argv as "bare" words; Hashes
|
75
|
-
# are translated to golang flags and then appended to argv.
|
76
|
-
#
|
77
|
-
# @return [Array] an (Integer,String,String) triple of exitstatus, stdout and stderr
|
78
|
-
#
|
79
|
-
# @example Run docker-compose with complex parameters
|
80
|
-
# command('docker-compose', {file: 'joe.yml'}, 'up', {d:true}, 'mysvc')
|
81
|
-
#
|
82
|
-
# @see #options for information on Hash-to-flag translation
|
83
|
-
def command(*cmd)
|
84
|
-
argv = []
|
85
|
-
|
86
|
-
cmd.each do |item|
|
87
|
-
case item
|
88
|
-
when Array
|
89
|
-
# list of words to append to argv
|
90
|
-
argv.concat(item.map { |e| e.to_s })
|
91
|
-
when Hash
|
92
|
-
# list of options to convert to CLI parameters
|
93
|
-
argv.concat(self.class.options(item))
|
94
|
-
else
|
95
|
-
# single word to append to argv
|
96
|
-
argv << item.to_s
|
97
|
-
end
|
98
|
-
end
|
99
|
-
|
100
|
-
run(argv)
|
101
|
-
end
|
102
|
-
|
103
|
-
# Run a simple command.
|
104
|
-
#
|
105
|
-
# @param [Array] argv list of command words
|
106
|
-
# @return [Array] triple of integer exitstatus, string stdout, and stderr
|
107
|
-
private def run(argv)
|
108
|
-
if self.interactive
|
109
|
-
run_interactive(argv)
|
110
|
-
else
|
111
|
-
run_noninteractive(argv)
|
112
|
-
end
|
113
|
-
end
|
114
|
-
|
115
|
-
# Run a shell command. Use a pty to capture the unbuffered output.
|
116
|
-
#
|
117
|
-
# @param [Array] argv command to run; argv[0] is program name and the
|
118
|
-
# remaining elements are parameters and flags
|
119
|
-
# @return [Array] an (Integer,String,String) triple of exitstatus, stdout and (empty) stderr
|
120
|
-
private def run_interactive(argv)
|
121
|
-
stdout, stdout_w = PTY.open
|
122
|
-
stdin_r, stdin = IO.pipe
|
123
|
-
stderr, stderr_w = IO.pipe
|
124
|
-
pid = spawn(*argv, in: stdin_r, out: stdout_w, err: stderr_w)
|
125
|
-
stdin_r.close
|
126
|
-
stdout_w.close
|
127
|
-
stderr_w.close
|
128
|
-
|
129
|
-
output, error = run_inner(stdin, stdout, stderr)
|
130
|
-
|
131
|
-
Process.waitpid(pid)
|
132
|
-
|
133
|
-
[$?.exitstatus, output, error]
|
134
|
-
end
|
135
|
-
|
136
|
-
# Run a shell command. Perform no translation or substitution. Use a pipe
|
137
|
-
# to read the output, which may be buffered by the OS. Return the program's
|
138
|
-
# exit status and stdout.
|
139
|
-
#
|
140
|
-
# TODO eliminate interactive path (it can't happen anymore) and move flourishes to run_interactive
|
141
|
-
#
|
142
|
-
# @param [Array] argv command to run; argv[0] is program name and the
|
143
|
-
# remaining elements are parameters and flags
|
144
|
-
# @return [Array] an (Integer,String,String) triple of exitstatus, stdout and stderr
|
145
|
-
private def run_noninteractive(argv)
|
146
|
-
stdin, stdout, stderr, thr = Open3.popen3(*argv)
|
147
|
-
|
148
|
-
output, error = run_inner(stdin, stdout, stderr)
|
149
|
-
|
150
|
-
# This blocks until the process exits (which probably already happened,
|
151
|
-
# given that we have received EOF on its output streams).
|
152
|
-
status = thr.value.exitstatus
|
153
|
-
|
154
|
-
[status, output, error]
|
155
|
-
rescue Interrupt
|
156
|
-
# Proxy Ctrl+C to our child process
|
157
|
-
Process.kill('INT', thr.pid) rescue nil
|
158
|
-
raise
|
159
|
-
end
|
160
|
-
|
161
|
-
private def run_inner(stdin, stdout, stderr)
|
162
|
-
streams = [stdout, stderr]
|
163
|
-
|
164
|
-
if @interactive
|
165
|
-
streams << STDIN
|
166
|
-
else
|
167
|
-
stdin.close
|
168
|
-
end
|
169
|
-
|
170
|
-
output = String.new.force_encoding(Encoding::BINARY)
|
171
|
-
error = String.new.force_encoding(Encoding::BINARY)
|
172
|
-
|
173
|
-
until streams.empty? || (streams.length == 1 && streams.first == STDIN)
|
174
|
-
ready, _, _ = IO.select(streams, [], [], 1)
|
175
|
-
|
176
|
-
if ready && ready.include?(STDIN)
|
177
|
-
input = STDIN.readpartial(1_024) rescue nil
|
178
|
-
if input
|
179
|
-
stdin.write(input)
|
180
|
-
else
|
181
|
-
# our own STDIN got closed; proxy to child's stdin
|
182
|
-
stdin.close
|
183
|
-
end
|
184
|
-
end
|
185
|
-
|
186
|
-
if ready && ready.include?(stderr)
|
187
|
-
data = stderr.readpartial(1_024) rescue nil
|
188
|
-
if data
|
189
|
-
error << data
|
190
|
-
STDERR.write(data) if @interactive
|
191
|
-
else
|
192
|
-
streams.delete(stderr)
|
193
|
-
end
|
194
|
-
end
|
195
|
-
|
196
|
-
if ready && ready.include?(stdout)
|
197
|
-
data = stdout.readpartial(1_024) rescue nil
|
198
|
-
if data
|
199
|
-
output << data
|
200
|
-
STDOUT.write(data) if @interactive
|
201
|
-
else
|
202
|
-
streams.delete(stdout)
|
203
|
-
end
|
204
|
-
end
|
205
|
-
end
|
206
|
-
|
207
|
-
[output, error]
|
208
|
-
end
|
209
|
-
end
|
210
|
-
end
|