freighter 0.2.0 → 0.2.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/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