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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 9739746b3edb3b6a5501f9a06527001ba44bde9a
4
- data.tar.gz: 2286c47c829338ab1517f253d91e708015e054ae
3
+ metadata.gz: f46424de56a54174c0feeb60213a0802bbd2f1d9
4
+ data.tar.gz: 884308db7063d5319f0bf5e34c63b9abb629cb83
5
5
  SHA512:
6
- metadata.gz: 346ef0d893e55776c1b350ea8365a7111c1cd04c51de5e4581eb27fd298d60780cba18fd2a2d4ac2af5a80a3a4828cb2642a5ff64f636c1a11a170c4044ccdb7
7
- data.tar.gz: 63d2046ad8739b5bf6d3bffb2cfbe24226c5b3dcf80c342ebb6370787da1ca8e72e8c8297b5eb09e54de852a8ceb65df2055c51618615510ecfab98adce2ffdb
6
+ metadata.gz: e658a0d63238b37b3ee9bc1bed406e6a075a533f819cde405c3ddfbc8ca912ce4fc2345f65f416c407e22e92c9531b1dcc00dff5c712f5180b2384015e8ce4a4
7
+ data.tar.gz: 6b3d156462bcf74cca7ba5ab9ee1830bacec6816571f0ad572880beed8d39d198210b4e8c4eaab459c6db9088341dd9d8b069a5330f9d50ab4e746948e3be0ac
@@ -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["Connected"]
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["Could not reach the docker REST API"]
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["Pulling image: #{image_name}"]
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["Skip pull image"]
60
- logger.error msg["Skipping is not yet implemented. Please run again without the --no-pull option"]
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["Existing image(s) found #{image_ids.join(', ')}"]
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["Container already running with the latest image: #{pull_response.id}"]
87
+ logger.info msg "Container already running with the latest image: #{pull_response.id}"
86
88
  else
87
- logger.info msg["Stopped containers: #{stopped_containers.map(&:info).map(&:to_json)}"]
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["Finished:"]
90
- logger.info msg[" started: #{results[:started]}"]
91
- logger.info msg[" stopped: #{results[:stopped]}"]
92
- logger.info msg[" started container ids: #{results[:container_ids_started]}"]
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 existing_containers=[], image
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
@@ -1,3 +1,3 @@
1
1
  module Freighter
2
- VERSION = "0.2.0"
2
+ VERSION = "0.2.1"
3
3
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: freighter
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.2.0
4
+ version: 0.2.1
5
5
  platform: ruby
6
6
  authors:
7
7
  - Sean McCleary