jarl 0.7.0 → 0.8.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- 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
|