spurious-server 0.3.1 → 0.4.0

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: 19f55a1b5c6d49a367b38d3d562e2ca8c9598bc8
4
- data.tar.gz: 8625d6c9b6401b5c48bbaaeb7d104db643dff8d8
3
+ metadata.gz: 7af8bff11bf2fda45cc441abe270a73dea2a3691
4
+ data.tar.gz: b2e6b3769c6d72ee57c1e56a45dccc252fa58b6f
5
5
  SHA512:
6
- metadata.gz: 18d5128a1933f0c477fa36472f74f6f3a6d54419a414cda20a75f44d777158021f485873fd7a6ddf8d20f4b5d13c57f61d36a244eff8fc59d8a8f0c9be97aab1
7
- data.tar.gz: b1b4637dbfa38ce2713a951fc75d8e4c00efc8c2e815d3c1b5de35a84a292a4689fda5712d3ef044940cacea640bc23549df50695551b8bef1eb50d5da01fd9c
6
+ metadata.gz: ffd92f6f4f681176d369506817aa3008bb9613d460532aa864ab212e328480e474bd9d5f412e50f0fa09e26a257fa7ee1e7052e3b646864f05bcbc3a1c89ade8
7
+ data.tar.gz: a5ba053aea4eab0ce5fb0c8fafeb1b2baaf195da3981e639db37dc8389642aab4efb6099384a7d95accca81fd5c2f5d36ef5b4a466a5414b45cafe0b1be85f82
data/bin/spurious-server CHANGED
@@ -6,13 +6,12 @@ require 'spurious/server'
6
6
  require 'spurious/server/version'
7
7
  require 'daemons'
8
8
  require 'eventmachine'
9
+ require 'em-synchrony'
9
10
  require 'spurious/server/options'
10
11
 
11
12
  options = Spurious::Server::Options.new(ENV)
13
+ ENV['DOCKER_HOST'] = options.ssl_docker_host
12
14
 
13
- Excon.defaults[:write_timeout] = options.write_timeout
14
- Excon.defaults[:read_timeout] = options.read_timeout
15
-
16
- Daemons.run_proc('Spurious Server', :dir => '/tmp', :log_output => true) do
17
- EventMachine.run Spurious::Server.handle(options)
15
+ Daemons.run_proc('Spurious_Server', :dir => '/tmp', :log_output => true) do
16
+ EventMachine.synchrony Spurious::Server.handle(options)
18
17
  end
data/config/images.yaml CHANGED
@@ -19,5 +19,8 @@
19
19
 
20
20
  'spurious-elasticache-docker':
21
21
  :image: 'smaj/fake-elasticache'
22
+ :ignore:
23
+ :create: true
24
+ :delete: true
22
25
  :link:
23
26
  - 'spurious-memcached:memcached01'
@@ -16,9 +16,14 @@ module Spurious
16
16
  def receive_data data
17
17
  payload = parse_payload data
18
18
  state(payload[:type]).execute!
19
- rescue Exception => e
20
- puts e.message
21
- state(:error).tap { |s| s.message = "JSON payload malformed" }.execute!
19
+ rescue Excon::Errors::Timeout, Excon::Errors::SocketError => e
20
+ error('Connection to the docker daemon has failed, please check that docker is running on the host or VM', true)
21
+ rescue StandardError => e
22
+ error(e.message, true)
23
+ end
24
+
25
+ def error(message, close = false)
26
+ send_data "#{JSON.generate({:message_type => 'error', :type => 'error', :response => message, :close => close, :colour => :red})}\n"
22
27
  end
23
28
 
24
29
  protected
@@ -1,7 +1,7 @@
1
1
  module Spurious
2
2
  module Server
3
3
  class Options
4
- attr_reader :docker_full_path, :docker_host, :docker_port, :docker_api, :server_port, :server_ip, :write_timeout, :read_timeout
4
+ attr_reader :docker_full_path, :docker_host, :docker_port, :docker_api, :server_port, :server_ip, :write_timeout, :read_timeout, :cert_path
5
5
 
6
6
  def initialize(env)
7
7
  @docker_host = env['DOCKER_HOST'].nil? ? 'localhost' : env['DOCKER_HOST'][/\/\/([0-9a-z\.]+):/,1]
@@ -11,8 +11,33 @@ module Spurious
11
11
  @server_ip = env.fetch('SPURIOUS_SERVER_IP', '0.0.0.0')
12
12
  @write_timeout = env.fetch('EXCON_WRITE_TIMEOUT', 30000)
13
13
  @read_timeout = env.fetch('EXCON_READ_TIMEOUT', 30000)
14
+ @cert_path = env.fetch('DOCKER_CERT_PATH', nil)
15
+ setup_ssl if @cert_path
14
16
  end
15
17
 
18
+ def ssl_docker_host
19
+ "https://#{docker_host}:#{docker_port}"
20
+ end
21
+
22
+ protected
23
+
24
+ def setup_ssl
25
+ Docker.options = {
26
+ :client_cert => valid_cert_path?('cert.pem'),
27
+ :client_key => valid_cert_path?('key.pem'),
28
+ :ssl_ca_file => valid_cert_path?('ca.pem')
29
+ }
30
+ end
31
+
32
+ def valid_cert_path?(cert)
33
+ File.join(absolute_cert_path, cert).tap do |path|
34
+ raise "Could not find: #{path}, please check it exists in your DOCKER_CERTS_PATH folder" unless File.exists? path
35
+ end
36
+ end
37
+
38
+ def absolute_cert_path
39
+ @absolute_cert_path ||= File.expand_path cert_path
40
+ end
16
41
  end
17
42
  end
18
43
  end
@@ -1,6 +1,7 @@
1
1
  require 'docker'
2
2
  require 'peach'
3
3
  require 'spurious/server'
4
+ require 'excon'
4
5
 
5
6
  module Spurious
6
7
  module Server
@@ -9,8 +10,15 @@ module Spurious
9
10
  attr_accessor :connection, :config
10
11
 
11
12
  def initialize(connection, config)
12
- @connection = connection
13
- @config = config
13
+ @connection = connection
14
+ @config = config
15
+ connection_timeouts
16
+ end
17
+
18
+ def connection_timeouts(connect = 1, read = 5, write = 5)
19
+ Excon.defaults[:write_timeout] = write
20
+ Excon.defaults[:read_timeout] = read
21
+ Excon.defaults[:connect_timeout] = connect
14
22
  end
15
23
 
16
24
  def execute!
@@ -35,18 +43,22 @@ module Spurious
35
43
  config.for sanitize(image)
36
44
  end
37
45
 
38
- def send(data, close = false)
39
- connection.send_data "#{JSON.generate({:type => state_identifer, :response => data, :close => close})}\n"
46
+ def send(data, message_type = 'info', close = false, colour = :white)
47
+ connection.send_data "#{JSON.generate({:message_type => message_type, :type => state_identifer, :response => data, :close => close, :colour => colour})}\n"
40
48
  end
41
49
 
42
50
  def error(message, close = false)
43
- connection.send_data "#{JSON.generate({:type => 'error', :response => message, :close => close})}\n"
51
+ connection.error(message, close)
44
52
  end
45
53
 
46
54
  def sanitize(name)
47
55
  name.gsub('/', '')
48
56
  end
49
57
 
58
+ def docker_available?
59
+
60
+ end
61
+
50
62
  private
51
63
 
52
64
  def state_identifer
@@ -7,20 +7,44 @@ module Spurious
7
7
  module State
8
8
  class Delete < Base
9
9
 
10
+ def initialize(connection, config)
11
+ super
12
+ connection_timeouts 2, 600, 600
13
+ end
14
+
10
15
  def execute!
11
- containers = spurious_containers.length
12
- spurious_containers.peach do |container|
13
- send "Removing container #{container.json["Name"]}..."
14
- container.tap do |c|
15
- c.kill
16
- c.delete(:force => true)
16
+ containers = spurious_containers.length - 1
17
+
18
+ spurious_containers.each_with_index do |container, index|
19
+ container_name = container.json["Name"].gsub('/', '')
20
+ container_config = config.for(container_name)
21
+ container_meta = container.json
22
+
23
+ remove_container = Proc.new do
24
+ send "Removing #{container_name}", :debug
25
+ container.delete(:force => true)
26
+
27
+ unless container_config[:ignore] && container_config[:ignore][:delete]
28
+ image = container_config[:image]
29
+
30
+ Docker::Image.get(container_meta["Image"]).tap do |image|
31
+ image.remove(:force => true)
32
+ end
33
+ end
34
+
35
+ index_to_check = index + 1
36
+ containers == index_to_check
17
37
  end
38
+
39
+ EM.defer(remove_container, operation_complete)
40
+
18
41
  end
19
- send "#{containers} containers successfully removed", true
42
+ end
20
43
 
21
- connection.unbind
22
- rescue Exception => e
23
- puts e.message
44
+ def operation_complete
45
+ Proc.new do |complete|
46
+ send("5 containers successfully removed", :info, true, :green) if complete
47
+ end
24
48
  end
25
49
  end
26
50
  end
@@ -2,7 +2,6 @@ require 'spurious/server/state/init'
2
2
  require 'spurious/server/state/start'
3
3
  require 'spurious/server/state/stop'
4
4
  require 'spurious/server/state/delete'
5
- require 'spurious/server/state/update'
6
5
  require 'spurious/server/state/ports'
7
6
  require 'spurious/server/state/error'
8
7
 
@@ -11,7 +10,7 @@ module Spurious
11
10
  module State
12
11
  module Factory
13
12
 
14
- def self.create(type, connection, config, options)
13
+ def self.create(type, connection, config, options = {})
15
14
  case type.to_sym
16
15
  when :init
17
16
  Init.new(connection, config, options.docker_host)
@@ -23,8 +22,6 @@ module Spurious
23
22
  Ports.new(connection, config, options.docker_host)
24
23
  when :delete
25
24
  Delete.new(connection, config)
26
- when :update
27
- Update.new(connection, config)
28
25
  when :error
29
26
  Error.new(connection)
30
27
  else
@@ -7,69 +7,62 @@ module Spurious
7
7
  module Server
8
8
  module State
9
9
  class Init < Base
10
-
11
10
  attr_accessor :completed_containers, :docker_host
12
11
 
13
12
  def initialize(connection, config, docker_host)
14
13
  super(connection, config)
14
+ connection_timeouts 2, 600, 600
15
15
  @docker_host = docker_host
16
16
  end
17
17
 
18
18
  def execute!
19
- this = self
20
- completed_containers = 0
19
+
20
+ raise "Containers have already been initilised, please run 'spurious start'" if spurious_containers.length > 0
21
+
22
+
23
+
24
+ send("Pulling containers from the registry can take some time, please be patient...", :info, false, :blue)
25
+
26
+ containers = app_config.length
27
+ index = 0
21
28
 
22
29
  app_config.each do |name, meta|
23
- image_meta = { 'fromImage' => meta[:image]}
24
- image_meta['Env'] = meta[:env] unless meta[:env].nil?
30
+ image_meta = {}.tap do |h|
31
+ h['fromImage'] = meta[:image]
32
+ h['Env'] = meta[:env] unless meta[:env].nil?
33
+ end
25
34
  container_cmd = []
26
35
 
27
36
  if meta[:image] == 'smaj/spurious-s3'
28
37
  container_cmd = ['-h', docker_host]
29
38
  end
30
39
 
31
- container_operation = Proc.new do
32
-
40
+ create_container = Proc.new do
33
41
  begin
34
- this.send "Creating container with name: #{name}"
42
+ send "Creating #{name} container", :debug
35
43
  Docker::Container.create("name" => name, "Image" => meta[:image], 'Cmd' => container_cmd)
36
- rescue Exception => e
37
- case e.message
38
- when /409 Conflict/
39
- this.error "Container with name: #{name} already exists"
40
- else
41
- this.error "Error creating container: #{e.message}"
42
- end
44
+ rescue Docker::Error::ArgumentError, Docker::Error::NotFoundError
45
+ rescue Excon::Errors::Conflict
46
+ error "#{name} container already exists"
43
47
  end
44
-
48
+ index = index + 1
49
+ operation_complete(containers == index)
45
50
  end
46
51
 
47
- container_callback = Proc.new do
48
- completed_containers = completed_containers + 1
49
- this.send("#{config.app.length} containers successfully initialized", true) if completed_containers == app_config.length
50
- end
51
-
52
- image_operation = Proc.new do
52
+ create_image = Proc.new do
53
53
  begin
54
- this.send "Pulling #{name} from the public repo..."
54
+ send "Pulling latest version of #{name} from registry", :debug
55
55
  Docker::Image.create(image_meta)
56
- rescue Exception => e
57
- this.error "Error pulling down image: #{e.message}"
58
- end
59
-
60
- end
61
-
62
- image_callback = Proc.new do
63
- EM.add_timer(1) do
64
- EM.defer(container_operation, container_callback)
56
+ rescue Docker::Error::ArgumentError, Docker::Error::NotFoundError, Excon::Errors::Timeout, Excon::Errors::SocketError
65
57
  end
66
58
  end
67
59
 
68
- EM.add_timer(1) do
69
- EM.defer(image_operation, image_callback)
70
- end
60
+ EM.defer(create_image, create_container)
71
61
  end
62
+ end
72
63
 
64
+ def operation_complete(complete)
65
+ send("6 containers successfully initialized", :info, true, :green) if complete
73
66
  end
74
67
 
75
68
  end
@@ -34,11 +34,12 @@ module Spurious
34
34
  end
35
35
 
36
36
  end
37
- send ports, true
37
+ send ports, :info, true
38
38
 
39
39
  connection.unbind
40
40
  rescue Exception => e
41
41
  puts e.message
42
+ raise('There was a problem connecting to the Docker API (check that docker is running or if not running under linux check the VM hosting docker is running and the API is accesbile')
42
43
  end
43
44
 
44
45
  end
@@ -9,38 +9,51 @@ module Spurious
9
9
  class Start < Base
10
10
  attr_accessor :docker_host
11
11
 
12
- def initialize(connection, config, docker_host)
12
+ def initialize(connection, config, docker_host_ip)
13
13
  super(connection, config)
14
- @docker_host = docker_host
14
+ connection_timeouts 2, 600, 600
15
+ @docker_host_ip = docker_host_ip
15
16
  end
16
17
 
17
18
  def execute!
19
+ started_containers = 0
20
+
21
+ raise "Containers haven't been initialised, please run 'spurious init' first." if spurious_containers.length == 0
22
+
18
23
  spurious_containers.each do |container|
19
24
  begin
25
+ started_containers = started_containers + 1
20
26
  config = container_config(container.json["Name"])
21
- send "Starting container #{container.json["Name"]}..."
22
- meta = {"PublishAllPorts" => true}
23
- meta["Links"] = config[:link] unless config[:link].nil?
27
+ send "Starting #{container.json["Name"].gsub('/', '')}", :debug
28
+ meta = {}.tap do |m|
29
+ m["PublishAllPorts"] = true
30
+ m["Links"] = config[:link] unless config[:link].nil?
31
+ end
32
+
24
33
  container.start meta
25
34
 
26
35
  if container.json["Name"] == '/spurious-sqs' then
27
36
  port_setup = Proc.new do
28
- port = container.json["NetworkSettings"]["Ports"]['4568/tcp'].first['HostPort']
29
- Net::HTTP.get(URI("http://#{docker_host}:#{port}/host-details?host=#{docker_host}&port=#{port}"))
37
+ begin
38
+ port = container.json["NetworkSettings"]["Ports"]['4568/tcp'].first['HostPort']
39
+ Net::HTTP.get(URI("http://#{docker_host_ip}:#{port}/host-details?host=#{docker_host_ip}&port=#{port}"))
40
+ rescue StandardError => e
41
+ end
30
42
  end
31
-
32
43
  EM.add_timer(5) { EM.defer(port_setup) }
33
44
  end
34
45
  rescue Exception => e
35
- error(e.message)
46
+ started_containers = started_containers - 1
47
+ case e.message
48
+ when /304 Not Modified/
49
+ error('Container is already running...')
50
+ else
51
+ error(e.message)
52
+ end
36
53
  end
37
54
  end
38
55
 
39
- send "#{spurious_containers.length} containers successfully started", true
40
-
41
- connection.unbind
42
- rescue Exception => e
43
- puts e.message
56
+ send("Started #{started_containers} containers", :info, true, :green)
44
57
  end
45
58
 
46
59
  end
@@ -7,17 +7,32 @@ module Spurious
7
7
  module State
8
8
  class Stop < Base
9
9
 
10
+ def initialize(connection, config)
11
+ super
12
+ connection_timeouts 2, 600, 600
13
+ end
14
+
10
15
  def execute!
11
- spurious_containers.peach do |container|
12
- send "Stopping container #{container.json["Name"]}..."
13
- container.stop
16
+ containers = spurious_containers.length - 1
17
+
18
+ spurious_containers.each_with_index do |container, index|
19
+ stop_containers = Proc.new do
20
+
21
+ send "Stopping #{container.json["Name"].gsub('/', '')}", :debug
22
+ container.stop
23
+ index_to_check = index + 1
24
+ containers == index_to_check
25
+ end
26
+ EM.defer(stop_containers, operation_complete)
14
27
  end
15
- send "#{spurious_containers.length} containers successfully stopped", true
28
+ end
16
29
 
17
- connection.unbind
18
- rescue Exception => e
19
- puts e.message
30
+ def operation_complete
31
+ Proc.new do |complete|
32
+ send("Stopped 6 containers", :info, true, :green) if complete
33
+ end
20
34
  end
35
+
21
36
  end
22
37
  end
23
38
  end
@@ -1,5 +1,5 @@
1
1
  module Spurious
2
2
  module Server
3
- VERSION = "0.3.1"
3
+ VERSION = "0.4.0"
4
4
  end
5
5
  end
@@ -23,6 +23,7 @@ Gem::Specification.new do |spec|
23
23
  spec.add_development_dependency "rspec"
24
24
 
25
25
  spec.add_runtime_dependency "eventmachine"
26
+ spec.add_runtime_dependency "em-synchrony"
26
27
  spec.add_runtime_dependency "docker-api"
27
28
  spec.add_runtime_dependency "daemons"
28
29
  spec.add_runtime_dependency "peach"
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: spurious-server
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.3.1
4
+ version: 0.4.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Steven Jack
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2014-09-10 00:00:00.000000000 Z
11
+ date: 2014-10-26 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: bundler
@@ -66,6 +66,20 @@ dependencies:
66
66
  - - '>='
67
67
  - !ruby/object:Gem::Version
68
68
  version: '0'
69
+ - !ruby/object:Gem::Dependency
70
+ name: em-synchrony
71
+ requirement: !ruby/object:Gem::Requirement
72
+ requirements:
73
+ - - '>='
74
+ - !ruby/object:Gem::Version
75
+ version: '0'
76
+ type: :runtime
77
+ prerelease: false
78
+ version_requirements: !ruby/object:Gem::Requirement
79
+ requirements:
80
+ - - '>='
81
+ - !ruby/object:Gem::Version
82
+ version: '0'
69
83
  - !ruby/object:Gem::Dependency
70
84
  name: docker-api
71
85
  requirement: !ruby/object:Gem::Requirement
@@ -136,7 +150,6 @@ files:
136
150
  - lib/spurious/server/state/ports.rb
137
151
  - lib/spurious/server/state/start.rb
138
152
  - lib/spurious/server/state/stop.rb
139
- - lib/spurious/server/state/update.rb
140
153
  - lib/spurious/server/version.rb
141
154
  - spec/app_spec.rb
142
155
  - spec/config_spec.rb
@@ -1,20 +0,0 @@
1
- require 'docker'
2
- require 'peach'
3
- require 'json'
4
- require 'spurious/server/state/base'
5
-
6
- module Spurious
7
- module Server
8
- module State
9
- class Update < Base
10
-
11
- def execute!
12
- ['stop', 'delete', 'init', 'up'].each do |state|
13
- connection.receive_data(JSON.generate({:type => state}))
14
- end
15
- end
16
-
17
- end
18
- end
19
- end
20
- end