jarl 0.7.0 → 0.8.1
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/lib/jarl/application.rb +70 -28
- data/lib/jarl/base.rb +41 -2
- data/lib/jarl/cli.rb +82 -73
- data/lib/jarl/docker.rb +97 -13
- data/lib/jarl/version.rb +1 -1
- metadata +3 -3
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 83b74b296a0d7b717781e0e95afc0229fccf6806
|
4
|
+
data.tar.gz: ad1000a7b31104b2f4c89850acec71e59cd52a12
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 40284867d9621630fa84494ede01af179a92474c61ac1fe723358a55c0115848a056cbba18bc41fc5aa1a3ceb308f48e3219add98ba5695798fe9fc9e80816b1
|
7
|
+
data.tar.gz: f4d2e5ae060dbcfff10601956dac755c706972d3099009017aa78acd762ffb6d28493225a32812d0d05480dc7cb6c240198a526b1a2d29d410dd466289d33b0b
|
data/lib/jarl/application.rb
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
module Jarl
|
2
2
|
class Application
|
3
3
|
attr_reader :group, :name, :hostname, :base_path
|
4
|
-
attr_reader :image, :volumes, :ports, :environment, :entrypoint, :command
|
4
|
+
attr_reader :image, :scale, :volumes, :ports, :environment, :entrypoint, :command
|
5
5
|
attr_reader :serial
|
6
6
|
|
7
7
|
# Create Application object from application definition:
|
@@ -22,6 +22,10 @@ module Jarl
|
|
22
22
|
unless @image.is_a?(String)
|
23
23
|
fail "Application '#{self}' has invalid 'image' definition, String is expected"
|
24
24
|
end
|
25
|
+
@scale = params['scale'] || 1
|
26
|
+
unless @scale.is_a?(Integer) && @scale > 0
|
27
|
+
fail "Application '#{self}' has invalid 'scale' definition, Integer > 0 is expected"
|
28
|
+
end
|
25
29
|
@volumes = params['volumes'] || []
|
26
30
|
unless @volumes.is_a?(Array)
|
27
31
|
fail "Application '#{self}' has invalid 'volumes' definition, Array is expected"
|
@@ -59,18 +63,42 @@ module Jarl
|
|
59
63
|
end
|
60
64
|
|
61
65
|
def running?
|
62
|
-
instances.
|
66
|
+
instances.any?(&:running?)
|
63
67
|
end
|
64
68
|
|
65
69
|
def instances
|
66
|
-
|
67
|
-
|
70
|
+
running_instances + stopped_instances
|
71
|
+
end
|
72
|
+
|
73
|
+
def running_containers
|
74
|
+
@running_containers ||= Docker.containers_running.select do |c|
|
75
|
+
c.name =~ /^#{full_name}(\.\d+)?$/
|
68
76
|
end
|
69
77
|
end
|
70
78
|
|
71
|
-
|
79
|
+
def running_instances
|
80
|
+
@running_instances ||= running_containers.map do |c|
|
81
|
+
n = c.name.sub(/^#{full_name}\.?/, '')
|
82
|
+
n = n.empty? ? nil : n.to_i
|
83
|
+
Instance.new(self, n, c)
|
84
|
+
end
|
85
|
+
end
|
86
|
+
|
87
|
+
def stopped_instances
|
88
|
+
return @stopped_instances if @stopped_instances
|
89
|
+
n_range = scale == 1 ? [nil] : (1..scale).to_a
|
90
|
+
@stopped_instances = n_range.reject do |n|
|
91
|
+
running_instances.map(&:n).include?(n)
|
92
|
+
end
|
93
|
+
@stopped_instances = @stopped_instances.map do |n|
|
94
|
+
Instance.new(self, n, nil)
|
95
|
+
end
|
96
|
+
@stopped_instances
|
97
|
+
end
|
98
|
+
|
99
|
+
# Start instances of the application
|
72
100
|
#
|
73
|
-
def start
|
101
|
+
def start
|
74
102
|
instances.map(&:stop!) if running?
|
75
103
|
if scale > 1
|
76
104
|
scale.times { |n| Instance.start(self, n + 1) }
|
@@ -129,35 +157,60 @@ module Jarl
|
|
129
157
|
# Application::Instance represents a single running instance of the application
|
130
158
|
#
|
131
159
|
class Instance
|
132
|
-
attr_reader :application, :container
|
133
|
-
|
160
|
+
attr_reader :application, :n, :container
|
161
|
+
|
162
|
+
# @param application [Application]
|
163
|
+
# @param n [nil,Integer] Instance number, nil if an instance is the primary instance
|
164
|
+
# @param container [nil,Docker::Container] Running container, if present
|
165
|
+
#
|
166
|
+
def initialize(application, n, container)
|
134
167
|
@application = application
|
168
|
+
@n = n
|
135
169
|
@container = container
|
136
170
|
end
|
137
171
|
|
172
|
+
def running?
|
173
|
+
!@container.nil?
|
174
|
+
end
|
175
|
+
|
176
|
+
def full_name
|
177
|
+
n ? "#{application.full_name}.#{n}" : application.full_name
|
178
|
+
end
|
179
|
+
|
180
|
+
def hostname
|
181
|
+
n ? "#{application.hostname}-#{n}" : application.hostname
|
182
|
+
end
|
183
|
+
|
138
184
|
def stop!
|
185
|
+
return unless running?
|
139
186
|
@container.stop!
|
140
187
|
end
|
141
188
|
|
142
|
-
def
|
143
|
-
|
144
|
-
|
189
|
+
def start!
|
190
|
+
return if running?
|
191
|
+
# puts esc_yellow("Starting #{application.name}.#{n}") if n
|
145
192
|
|
146
|
-
|
147
|
-
|
148
|
-
|
193
|
+
Docker.start(
|
194
|
+
name: full_name,
|
195
|
+
hostname: hostname,
|
196
|
+
image: application.image_name,
|
197
|
+
volumes: application.volumes,
|
198
|
+
ports: application.ports,
|
199
|
+
environment: application.environment,
|
200
|
+
command: application.command
|
201
|
+
)
|
149
202
|
end
|
150
203
|
|
151
204
|
def tail_log(*_args)
|
205
|
+
return unless running?
|
152
206
|
color_code = Console::Colors::SEQUENCE[application.serial % Console::Colors::SEQUENCE.size]
|
153
207
|
begin
|
154
|
-
instance_no = n ? ".#{n}" : ''
|
155
208
|
IO.popen "docker logs -f #{container.id}", 'r' do |p|
|
156
209
|
str = '<<< STARTED >>>'
|
157
210
|
while str
|
158
211
|
str = p.gets
|
159
212
|
str.split("\n").each do |s|
|
160
|
-
puts "#{esc_color color_code,
|
213
|
+
puts "#{esc_color color_code, full_name}: #{s}"
|
161
214
|
end
|
162
215
|
end
|
163
216
|
end
|
@@ -167,20 +220,9 @@ module Jarl
|
|
167
220
|
end
|
168
221
|
|
169
222
|
def ssh(command = nil)
|
223
|
+
fail "Failed to open SSH, no running container for '#{full_name}'" unless running?
|
170
224
|
container.open_ssh_session!(Jarl.config.params, command)
|
171
225
|
end
|
172
|
-
|
173
|
-
def self.start(application, n = nil)
|
174
|
-
Docker.start(
|
175
|
-
name: (n ? "#{application.full_name}.#{n}" : application.full_name),
|
176
|
-
hostname: (n ? "#{application.hostname}-#{n}" : application.hostname),
|
177
|
-
image: application.image_name,
|
178
|
-
volumes: application.volumes,
|
179
|
-
ports: application.ports,
|
180
|
-
environment: application.environment,
|
181
|
-
command: application.command
|
182
|
-
)
|
183
|
-
end
|
184
226
|
end # class Instance
|
185
227
|
end # class Application
|
186
228
|
end # module Jarl
|
data/lib/jarl/base.rb
CHANGED
@@ -42,10 +42,49 @@ module Jarl
|
|
42
42
|
end.flatten
|
43
43
|
end
|
44
44
|
|
45
|
+
# Returns list of running application instances
|
46
|
+
#
|
47
|
+
def self.application_instances
|
48
|
+
@application_instances ||= applications.map(&:instances).flatten
|
49
|
+
end
|
50
|
+
|
45
51
|
# Returns list of applications matching the pattern
|
46
52
|
#
|
47
|
-
|
48
|
-
|
53
|
+
# @param patterns [nil] Match all application instances
|
54
|
+
# @param patterns [String] Match application instances by single pattern
|
55
|
+
# @param patterns [Arary<String>] Match application instances by all patterns
|
56
|
+
#
|
57
|
+
def self.find_applications_by(patterns)
|
58
|
+
find_application_instances_by(patterns).map(&:application).uniq
|
59
|
+
end
|
60
|
+
|
61
|
+
# Returns list of running application instances matching the pattern(s)
|
62
|
+
#
|
63
|
+
# @param patterns [nil] Match all application instances
|
64
|
+
# @param patterns [String] Match application instances by single pattern
|
65
|
+
# @param patterns [Arary<String>] Match application instances by all patterns
|
66
|
+
#
|
67
|
+
def self.find_application_instances_by(patterns)
|
68
|
+
patterns = nil if patterns && patterns.empty?
|
69
|
+
case patterns
|
70
|
+
when nil
|
71
|
+
application_instances
|
72
|
+
when String
|
73
|
+
application_instances.select { |i| i.full_name.index(patterns) }
|
74
|
+
when Array
|
75
|
+
application_instances.select { |i| patterns.any? { |p| i.full_name.index(p) } }
|
76
|
+
else
|
77
|
+
fail "Unexpected #{patterns.class} passed as argument to .find_application_instances_by"
|
78
|
+
end
|
79
|
+
end
|
80
|
+
|
81
|
+
#
|
82
|
+
#
|
83
|
+
def self.reload!
|
84
|
+
@jarl_files = nil
|
85
|
+
@applications = nil
|
86
|
+
@application_instances = nil
|
87
|
+
Docker.reload!
|
49
88
|
end
|
50
89
|
|
51
90
|
private
|
data/lib/jarl/cli.rb
CHANGED
@@ -25,52 +25,58 @@ module Jarl
|
|
25
25
|
puts " #{app.name}"
|
26
26
|
end
|
27
27
|
end
|
28
|
-
# show_jarl_applications_status(apps)
|
29
28
|
end
|
30
29
|
|
31
30
|
#
|
32
|
-
desc 'status [NAME]', '(default) Show applications statuses'
|
33
|
-
def status(
|
31
|
+
desc 'status [NAME ...]', '(default) Show applications statuses'
|
32
|
+
def status(*names)
|
34
33
|
Jarl.load(options)
|
35
|
-
|
36
|
-
|
34
|
+
ais = Jarl.find_application_instances_by(names)
|
35
|
+
show_jarl_application_instances_status(ais)
|
37
36
|
end
|
38
37
|
default_task :status
|
39
38
|
|
40
|
-
|
41
|
-
|
42
|
-
type: :numeric,
|
43
|
-
default: 1,
|
44
|
-
desc: 'Start several instances'
|
45
|
-
desc 'up [NAME]', 'Start or restart applications'
|
46
|
-
def up(name = nil)
|
39
|
+
desc 'up [NAME ...]', 'Start or restart applications'
|
40
|
+
def up(*names)
|
47
41
|
Jarl.load(options)
|
48
|
-
|
49
|
-
|
50
|
-
|
51
|
-
|
42
|
+
if Jarl.find_application_instances_by(names).any?(&:running?)
|
43
|
+
down(*names)
|
44
|
+
Jarl.reload!
|
45
|
+
end
|
46
|
+
ais = Jarl.find_application_instances_by(names)
|
47
|
+
ais.each do |i|
|
48
|
+
puts esc_green "Starting '#{i.full_name}'..."
|
49
|
+
i.start!
|
52
50
|
end
|
51
|
+
# apps = name ? Jarl.find_applications_by(name) : Jarl.applications
|
52
|
+
# apps.each do |app|
|
53
|
+
# puts esc_green(app.running? ? "Restarting '#{app}'..." : "Starting '#{app}'...")
|
54
|
+
# app.start
|
55
|
+
# end
|
53
56
|
# show_jarl_applications_status(apps)
|
54
57
|
end
|
55
58
|
|
56
59
|
#
|
57
|
-
desc 'down [NAME]', 'Stop applications'
|
58
|
-
def down(
|
60
|
+
desc 'down [NAME ...]', 'Stop applications'
|
61
|
+
def down(*names)
|
59
62
|
Jarl.load(options)
|
60
|
-
|
61
|
-
|
62
|
-
|
63
|
-
|
64
|
-
|
65
|
-
i.stop!
|
66
|
-
end
|
63
|
+
ais = Jarl.find_application_instances_by(names).select(&:running?)
|
64
|
+
puts esc_yellow 'No running applications found' unless ais.size > 0
|
65
|
+
ais.each do |i|
|
66
|
+
puts esc_yellow "Stopping '#{i.full_name}'..."
|
67
|
+
i.stop!
|
67
68
|
end
|
68
69
|
end
|
69
70
|
|
70
71
|
desc 'execute NAME [COMMAND ...]', 'Run a single command against application image'
|
71
72
|
def execute(name, command = nil, *args)
|
72
73
|
Jarl.load(options)
|
73
|
-
|
74
|
+
apps = Jarl.find_applications_by(name)
|
75
|
+
if apps.size > 1
|
76
|
+
puts esc_yellow 'More than one application matches the pattern, using the first one:'
|
77
|
+
puts esc_yellow " #{apps.map(&:full_name).join(', ')}"
|
78
|
+
end
|
79
|
+
app = apps.first
|
74
80
|
abort "Failed to find application by name: '#{name}'" unless app
|
75
81
|
app.execute(command, args)
|
76
82
|
end
|
@@ -79,7 +85,13 @@ module Jarl
|
|
79
85
|
desc 'ssh NAME [COMMAND ...]', 'Open an interactive SSH session to a running application or execute a command and exit'
|
80
86
|
def ssh(name, command = nil, *args)
|
81
87
|
Jarl.load(options)
|
82
|
-
|
88
|
+
ais = Jarl.find_application_instances_by(name).select(&:running?)
|
89
|
+
abort 'No running applications found' unless ais.size > 0
|
90
|
+
if ais.size > 1
|
91
|
+
puts esc_yellow 'More than one running application instance matches the pattern, using the first one:'
|
92
|
+
puts esc_yellow " #{ais.map(&:full_name).join(', ')}"
|
93
|
+
end
|
94
|
+
app = ais.first
|
83
95
|
abort "Failed to find application by name: '#{name}'" unless app
|
84
96
|
abort "Application is not running: '#{app.full_name}'" unless app.running?
|
85
97
|
app.ssh([command] + args)
|
@@ -87,45 +99,46 @@ module Jarl
|
|
87
99
|
|
88
100
|
#
|
89
101
|
option :ip, type: :boolean, desc: 'Show only IPs'
|
90
|
-
desc 'inspect [NAME]', 'Inspect
|
91
|
-
def inspect(
|
102
|
+
desc 'inspect [NAME ...]', 'Inspect running application instances'
|
103
|
+
def inspect(*names)
|
92
104
|
Jarl.load(options)
|
93
|
-
|
94
|
-
|
105
|
+
ais = Jarl.find_application_instances_by(names).select(&:running?)
|
106
|
+
abort 'No running applications found' unless ais.size > 0
|
107
|
+
ais.each do |ai|
|
95
108
|
if options[:ip]
|
96
|
-
puts
|
109
|
+
puts ai.container.ip
|
97
110
|
else
|
98
|
-
|
111
|
+
show_jarl_application_instance_inspect(ai)
|
99
112
|
end
|
100
113
|
end
|
101
114
|
end
|
102
115
|
|
103
|
-
desc 'build [NAME]', 'Rebuild docker images for Dockerfile based applications'
|
104
|
-
def build(
|
116
|
+
desc 'build [NAME ...]', 'Rebuild docker images for Dockerfile based applications'
|
117
|
+
def build(*names)
|
105
118
|
Jarl.load(options)
|
106
|
-
apps =
|
119
|
+
apps = Jarl.find_applications_by(names)
|
107
120
|
apps.select(&:image_is_a_path?).each do |app|
|
108
121
|
puts esc_yellow "Building image for '#{app}'..."
|
109
122
|
app.build
|
110
123
|
end
|
111
124
|
end
|
112
125
|
|
113
|
-
desc 'pull [NAME]', 'Pull docker images for regestry based applications'
|
114
|
-
def pull(
|
126
|
+
desc 'pull [NAME ...]', 'Pull docker images for regestry based applications'
|
127
|
+
def pull(*names)
|
115
128
|
Jarl.load(options)
|
116
|
-
apps =
|
129
|
+
apps = Jarl.find_applications_by(names)
|
117
130
|
apps.select(&:image_is_a_registry_path?).each do |app|
|
118
131
|
puts esc_yellow "Pulling image '#{app}'..."
|
119
132
|
app.pull
|
120
133
|
end
|
121
134
|
end
|
122
135
|
|
123
|
-
desc 'logs [NAME]', 'Show log output for applications'
|
124
|
-
def logs(
|
136
|
+
desc 'logs [NAME ...]', 'Show log output for applications'
|
137
|
+
def logs(*names)
|
125
138
|
Jarl.load(options)
|
126
|
-
|
139
|
+
ais = Jarl.find_application_instances_by(names)
|
127
140
|
threads = []
|
128
|
-
|
141
|
+
ais.select(&:running?).flatten.each do |instance|
|
129
142
|
threads << Thread.new { instance.tail_log }
|
130
143
|
end
|
131
144
|
|
@@ -148,14 +161,12 @@ module Jarl
|
|
148
161
|
"Jarl v#{Jarl::VERSION}"
|
149
162
|
end
|
150
163
|
|
151
|
-
def
|
152
|
-
if
|
164
|
+
def show_jarl_application_instances_status(ais)
|
165
|
+
if ais.size == 0
|
153
166
|
puts esc_yellow 'No applications found'
|
154
167
|
return
|
155
168
|
end
|
156
|
-
full_names =
|
157
|
-
app.running? ? app.instances.map { |i| i.container.name } : app.full_name
|
158
|
-
end.flatten
|
169
|
+
full_names = ais.map(&:full_name)
|
159
170
|
max_full_name_len = [full_names.map(&:size).max, 12].max
|
160
171
|
puts esc_format(
|
161
172
|
['APPLICATION', max_full_name_len],
|
@@ -164,20 +175,18 @@ module Jarl
|
|
164
175
|
['IP', 12],
|
165
176
|
['PORTS']
|
166
177
|
)
|
167
|
-
|
168
|
-
if
|
169
|
-
|
170
|
-
|
171
|
-
|
172
|
-
|
173
|
-
|
174
|
-
|
175
|
-
|
176
|
-
)
|
177
|
-
end
|
178
|
+
ais.each do |i|
|
179
|
+
if i.running?
|
180
|
+
puts esc_format(
|
181
|
+
[i.container.name, max_full_name_len, :yellow],
|
182
|
+
[i.container.id, 12, :green],
|
183
|
+
[seconds_to_human(i.container.uptime), 12, :yellow],
|
184
|
+
[i.container.ip, 12, :yellow],
|
185
|
+
[i.container.ports.map { |p| "#{p[:from]}" }.join(', ')]
|
186
|
+
)
|
178
187
|
else
|
179
188
|
puts esc_format(
|
180
|
-
[
|
189
|
+
[i.full_name, max_full_name_len, :yellow],
|
181
190
|
['no', 12],
|
182
191
|
['', 12],
|
183
192
|
['', 12],
|
@@ -187,21 +196,21 @@ module Jarl
|
|
187
196
|
end
|
188
197
|
end
|
189
198
|
|
190
|
-
def
|
191
|
-
unless
|
192
|
-
puts esc_yellow("#{
|
199
|
+
def show_jarl_application_instance_inspect(ai)
|
200
|
+
unless ai.running?
|
201
|
+
puts esc_yellow("#{ai.full_name}: ") + 'off'
|
193
202
|
return
|
194
203
|
end
|
195
|
-
app
|
196
|
-
|
197
|
-
|
198
|
-
|
199
|
-
|
200
|
-
|
201
|
-
|
202
|
-
|
203
|
-
|
204
|
-
|
204
|
+
app = ai.application
|
205
|
+
container = ai.container
|
206
|
+
puts esc_yellow "#{container.name}: " + esc_green(container.id)
|
207
|
+
puts " app: #{esc_yellow app.full_name}"
|
208
|
+
puts " image: #{esc_yellow container.image}"
|
209
|
+
puts " full ID: #{esc_yellow container.long_id}"
|
210
|
+
puts " uptime: #{esc_yellow seconds_to_human container.uptime}"
|
211
|
+
puts " IP: #{esc_yellow container.ip}"
|
212
|
+
puts " ports: #{esc_yellow container.ports.map { |p| "#{p[:from]}->#{p[:to]}"}.join(', ')}"
|
213
|
+
puts " volumes: #{esc_yellow container.volumes}"
|
205
214
|
end
|
206
215
|
end # class CLI
|
207
216
|
end # module Jarl
|
data/lib/jarl/docker.rb
CHANGED
@@ -64,9 +64,17 @@ module Docker
|
|
64
64
|
@docker_containers_running
|
65
65
|
end
|
66
66
|
|
67
|
+
# Returns `docker ps` info inspector instance
|
68
|
+
#
|
69
|
+
def self.ps
|
70
|
+
@docker_ps ||= Ps.new
|
71
|
+
end
|
72
|
+
|
73
|
+
|
67
74
|
# Reloads lists of images and containers
|
68
75
|
#
|
69
76
|
def self.reload!
|
77
|
+
@docker_ps = nil
|
70
78
|
@docker_images = nil
|
71
79
|
@docker_images_used = nil
|
72
80
|
@docker_containers_running = nil
|
@@ -134,6 +142,52 @@ module Docker
|
|
134
142
|
sh docker_cmd
|
135
143
|
end
|
136
144
|
|
145
|
+
# `docker ps` info inspector
|
146
|
+
#
|
147
|
+
class Ps
|
148
|
+
FIELDS = [
|
149
|
+
'CONTAINER ID', 'IMAGE', 'COMMAND', 'CREATED', 'STATUS', 'PORTS', 'NAMES'
|
150
|
+
]
|
151
|
+
|
152
|
+
attr_reader :entries
|
153
|
+
|
154
|
+
def initialize
|
155
|
+
lines = `docker ps`.split("\n")
|
156
|
+
@headers = lines.shift
|
157
|
+
@data = lines
|
158
|
+
@entries = lines.map do |line|
|
159
|
+
FIELDS.map { |name| [name, field(line, name)] }.to_h
|
160
|
+
end
|
161
|
+
end
|
162
|
+
|
163
|
+
def field_i_start(name)
|
164
|
+
i_start = @headers.index(name)
|
165
|
+
fail "Failed to find the field #{name} in docker ps" unless i_start
|
166
|
+
i_start
|
167
|
+
end
|
168
|
+
|
169
|
+
# @return [nil,Integer] right index for field or -1 if the field is rightmost
|
170
|
+
#
|
171
|
+
def field_i_end(name)
|
172
|
+
i_start = field_i_start(name)
|
173
|
+
r_headers = @headers[i_start..-1].sub(/^#{name}/, '')
|
174
|
+
m = r_headers.match(/^(\s+)/)
|
175
|
+
m ? i_start + name.size + m[1].size - 1 : -1
|
176
|
+
end
|
177
|
+
|
178
|
+
def field_i_range(name)
|
179
|
+
field_i_start(name)..field_i_end(name)
|
180
|
+
end
|
181
|
+
|
182
|
+
def field(line, name)
|
183
|
+
line[field_i_range(name)].strip
|
184
|
+
end
|
185
|
+
|
186
|
+
def [](id)
|
187
|
+
entries.find { |e| id == e['CONTAINER ID'] }
|
188
|
+
end
|
189
|
+
end
|
190
|
+
|
137
191
|
# Image
|
138
192
|
#
|
139
193
|
class Image
|
@@ -205,24 +259,54 @@ module Docker
|
|
205
259
|
# Container
|
206
260
|
#
|
207
261
|
class Container
|
208
|
-
attr_accessor :id
|
262
|
+
attr_accessor :id
|
209
263
|
|
210
264
|
def initialize(id)
|
211
265
|
@id = id
|
212
|
-
|
213
|
-
|
214
|
-
|
215
|
-
|
216
|
-
|
217
|
-
|
218
|
-
|
219
|
-
@
|
220
|
-
|
221
|
-
@
|
266
|
+
end
|
267
|
+
|
268
|
+
def ps
|
269
|
+
Docker.ps[id] or fail "Failed to find ps info for #{id}"
|
270
|
+
end
|
271
|
+
|
272
|
+
def container_inspect
|
273
|
+
return @container_inspect if @container_inspect
|
274
|
+
# puts "Loading inspect for: #{ps}"
|
275
|
+
@container_inspect ||= JSON.parse(`docker inspect #{id}`).first
|
276
|
+
end
|
277
|
+
|
278
|
+
def long_id
|
279
|
+
container_inspect['Id']
|
280
|
+
end
|
281
|
+
|
282
|
+
def name
|
283
|
+
ps['NAMES']
|
284
|
+
# container_inspect['Name'].gsub('/', '')
|
285
|
+
end
|
286
|
+
|
287
|
+
def image
|
288
|
+
container_inspect['Config']['Image']
|
289
|
+
end
|
290
|
+
|
291
|
+
def image_id
|
292
|
+
container_inspect['Image']
|
293
|
+
end
|
294
|
+
|
295
|
+
def ip
|
296
|
+
container_inspect['NetworkSettings']['IPAddress']
|
297
|
+
end
|
298
|
+
|
299
|
+
def ports
|
300
|
+
port_maps = container_inspect['NetworkSettings']['Ports']
|
301
|
+
port_maps.keys.map do |port|
|
222
302
|
{ from: port, to: port_maps[port] }
|
223
303
|
end
|
224
304
|
end
|
225
305
|
|
306
|
+
def volumes
|
307
|
+
container_inspect['Volumes']
|
308
|
+
end
|
309
|
+
|
226
310
|
def open_ssh_session!(params = {}, command = nil)
|
227
311
|
ssh_flags = ['-oStrictHostKeyChecking=no']
|
228
312
|
if params['ssh_identity']
|
@@ -246,8 +330,8 @@ module Docker
|
|
246
330
|
end
|
247
331
|
|
248
332
|
def uptime
|
249
|
-
|
250
|
-
Time.now.utc - DateTime.parse(
|
333
|
+
container_inspect['State'] && container_inspect['State']['StartedAt'] &&
|
334
|
+
Time.now.utc - DateTime.parse(container_inspect['State']['StartedAt']).to_time.utc
|
251
335
|
end
|
252
336
|
|
253
337
|
def self.clean_containers(*names)
|
data/lib/jarl/version.rb
CHANGED
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: jarl
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.8.1
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Alex Kukushkin
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2015-
|
11
|
+
date: 2015-07-07 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: thor
|
@@ -111,7 +111,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
111
111
|
version: '0'
|
112
112
|
requirements: []
|
113
113
|
rubyforge_project:
|
114
|
-
rubygems_version: 2.
|
114
|
+
rubygems_version: 2.4.5
|
115
115
|
signing_key:
|
116
116
|
specification_version: 4
|
117
117
|
summary: Jarl, docker container management tool
|