freighter 0.2.0 → 0.2.1
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/lib/freighter/deploy.rb +60 -19
- data/lib/freighter/version.rb +1 -1
- metadata +1 -1
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: f46424de56a54174c0feeb60213a0802bbd2f1d9
|
4
|
+
data.tar.gz: 884308db7063d5319f0bf5e34c63b9abb629cb83
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: e658a0d63238b37b3ee9bc1bed406e6a075a533f819cde405c3ddfbc8ca912ce4fc2345f65f416c407e22e92c9531b1dcc00dff5c712f5180b2384015e8ce4a4
|
7
|
+
data.tar.gz: 6b3d156462bcf74cca7ba5ab9ee1830bacec6816571f0ad572880beed8d39d198210b4e8c4eaab459c6db9088341dd9d8b069a5330f9d50ab4e746948e3be0ac
|
data/lib/freighter/deploy.rb
CHANGED
@@ -1,8 +1,10 @@
|
|
1
1
|
require 'docker'
|
2
|
+
require 'thread'
|
3
|
+
require 'thwait'
|
2
4
|
|
3
5
|
module Freighter
|
4
6
|
class Deploy
|
5
|
-
attr_reader :logger, :config
|
7
|
+
attr_reader :logger, :config
|
6
8
|
|
7
9
|
def initialize
|
8
10
|
@parser = Parser.new OPTIONS.config_path
|
@@ -28,6 +30,7 @@ module Freighter
|
|
28
30
|
|
29
31
|
@environment.fetch('hosts').each_with_index do |host, i|
|
30
32
|
host_name = host.fetch('host')
|
33
|
+
@current_host_name = host_name
|
31
34
|
images = @parser.images(host_name)
|
32
35
|
|
33
36
|
ssh = SSH.new(host_name, ssh_options)
|
@@ -35,9 +38,8 @@ module Freighter
|
|
35
38
|
# docker_api = DockerRestAPI.new("http://localhost:#{local_port}")
|
36
39
|
|
37
40
|
ssh.tunneled_proxy(local_port) do |session|
|
38
|
-
msg = ->(m) { "#{host_name}: #{m}" }
|
39
41
|
|
40
|
-
logger.debug msg
|
42
|
+
logger.debug msg "Connected"
|
41
43
|
begin
|
42
44
|
# The timeout is needed in the case that we are unable to communicate with the docker REST API
|
43
45
|
Timeout::timeout(5) do
|
@@ -45,7 +47,7 @@ module Freighter
|
|
45
47
|
end
|
46
48
|
rescue Timeout::Error
|
47
49
|
ssh.thread.exit
|
48
|
-
logger.error msg
|
50
|
+
logger.error msg "Could not reach the docker REST API"
|
49
51
|
end
|
50
52
|
|
51
53
|
|
@@ -53,11 +55,11 @@ module Freighter
|
|
53
55
|
image_name = image['name']
|
54
56
|
# pull image
|
55
57
|
if OPTIONS.pull_image
|
56
|
-
logger.info msg
|
58
|
+
logger.info msg "Pulling image: #{image_name}"
|
57
59
|
pull_response = Docker::Image.create 'fromImage' => image_name
|
58
60
|
else
|
59
|
-
logger.info msg
|
60
|
-
logger.error msg
|
61
|
+
logger.info msg "Skip pull image"
|
62
|
+
logger.error msg "Skipping is not yet implemented. Please run again without the --no-pull option"
|
61
63
|
end
|
62
64
|
|
63
65
|
# find existing images on the machine
|
@@ -65,7 +67,7 @@ module Freighter
|
|
65
67
|
img.info['RepoTags'].member?(image_name)
|
66
68
|
end.map { |img| img.id[0...12] }
|
67
69
|
|
68
|
-
logger.info msg
|
70
|
+
logger.info msg "Existing image(s) found #{image_ids.join(', ')}"
|
69
71
|
|
70
72
|
# determine if a the latest version of the image is currently running
|
71
73
|
matching_containers = containers_matching_port_map(Docker::Container.all, image['containers'].map { |c| c['port_mapping'] })
|
@@ -82,14 +84,19 @@ module Freighter
|
|
82
84
|
end
|
83
85
|
end
|
84
86
|
if !current_running_containers.empty? and stopped_containers.empty?
|
85
|
-
logger.info msg
|
87
|
+
logger.info msg "Container already running with the latest image: #{pull_response.id}"
|
86
88
|
else
|
87
|
-
logger.info msg
|
89
|
+
logger.info msg "Stopped containers: #{stopped_containers.map(&:info).map(&:to_json)}"
|
88
90
|
results = update_containers matching_containers, image
|
89
|
-
logger.info msg
|
90
|
-
logger.info msg
|
91
|
-
logger.info msg
|
92
|
-
logger.info msg
|
91
|
+
logger.info msg "Finished:"
|
92
|
+
logger.info msg " started: #{results[:started]}"
|
93
|
+
logger.info msg " stopped: #{results[:stopped]}"
|
94
|
+
logger.info msg " started container ids: #{results[:container_ids_started]}"
|
95
|
+
|
96
|
+
# cleanup old containers
|
97
|
+
cleanup_old_containers
|
98
|
+
# cleanup unused/outdated images
|
99
|
+
cleanup_dangling_images
|
93
100
|
end
|
94
101
|
end
|
95
102
|
end
|
@@ -98,6 +105,11 @@ module Freighter
|
|
98
105
|
|
99
106
|
private
|
100
107
|
|
108
|
+
# Used for logging to prefix log messages with the current host
|
109
|
+
def msg(message)
|
110
|
+
"#{@current_host_name}: #{message}"
|
111
|
+
end
|
112
|
+
|
101
113
|
# Sets up the Docker gem by setting the local URL and authenticating to the host's REST API
|
102
114
|
def setup_docker_client(local_port)
|
103
115
|
Docker.url = "http://localhost:#{local_port}"
|
@@ -135,16 +147,16 @@ module Freighter
|
|
135
147
|
end
|
136
148
|
end
|
137
149
|
|
138
|
-
def update_containers
|
150
|
+
def update_containers(existing_containers=[], image)
|
139
151
|
totals = { stopped: 0, started: 0, container_ids_started: [] }
|
140
152
|
# stop the existing matching containers
|
141
153
|
existing_containers.map do |container|
|
142
154
|
Thread.new do
|
143
155
|
existing_container = Docker::Container.get(container.id)
|
144
|
-
logger.info "Stopping container: #{contianer.id}"
|
156
|
+
logger.info msg "Stopping container: #{contianer.id}"
|
145
157
|
existing_container.stop
|
146
158
|
existing_container.wait()
|
147
|
-
logger.info "Container stopped (#{container.id}"
|
159
|
+
logger.info msg "Container stopped (#{container.id}"
|
148
160
|
totals[:stopped] += 1
|
149
161
|
end
|
150
162
|
end.join
|
@@ -162,17 +174,46 @@ module Freighter
|
|
162
174
|
}
|
163
175
|
|
164
176
|
new_container = Docker::Container.create container_options
|
165
|
-
logger.info "Starting container with port_mapping: host #{[port_map.ip, port_map.host].join(':')}, container #{port_map.container}"
|
177
|
+
logger.info msg "Starting container with port_mapping: host #{[port_map.ip, port_map.host].join(':')}, container #{port_map.container}"
|
166
178
|
new_container.start(
|
167
179
|
"PortBindings" => { "#{port_map.container}/tcp" => [{ "HostPort" => port_map.host.to_s, "HostIp" => port_map.ip }] }
|
168
180
|
)
|
169
181
|
totals[:container_ids_started] << new_container.id
|
170
|
-
logger.info "New container started with id: #{new_container.id}"
|
182
|
+
logger.info msg "New container started with id: #{new_container.id}"
|
171
183
|
totals[:started] += 1
|
172
184
|
end
|
173
185
|
|
174
186
|
totals
|
175
187
|
end
|
176
188
|
|
189
|
+
# cleans up all exited containers
|
190
|
+
def cleanup_old_containers
|
191
|
+
thread_pool = []
|
192
|
+
Docker::Container.all(all: true).select { |c| c.info['Status'] =~ /^Exited/ }.each do |container|
|
193
|
+
thread_pool << Thread.new do
|
194
|
+
logger.info msg "Removing container: #{container.info.to_json}"
|
195
|
+
container.remove
|
196
|
+
end
|
197
|
+
end
|
198
|
+
if thread_pool.empty?
|
199
|
+
logger.info msg "No containers need to be cleaned up"
|
200
|
+
else
|
201
|
+
logger.info msg "Waiting for old containers to be cleaned up"
|
202
|
+
ThreadsWait.all_waits(*thread_pool)
|
203
|
+
end
|
204
|
+
end
|
205
|
+
|
206
|
+
def cleanup_dangling_images
|
207
|
+
thread_pool = []
|
208
|
+
Docker::Image.all(filters: '{"dangling":["true"]}').each do |image|
|
209
|
+
thread_pool << Thread.new do
|
210
|
+
image.remove
|
211
|
+
logger.info msg "Removed image: #{image.info.to_json}"
|
212
|
+
end
|
213
|
+
end
|
214
|
+
logger.info msg "Waiting for dangling images to be cleaned up"
|
215
|
+
ThreadsWait.all_waits(*thread_pool)
|
216
|
+
end
|
217
|
+
|
177
218
|
end
|
178
219
|
end
|
data/lib/freighter/version.rb
CHANGED