zygote 0.1.5 → 0.2.0

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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 2994a2e5d4616b4b1b0c39f9796f733a65ef5d76
4
- data.tar.gz: 591d695efd51df62d38be73844ef4555fe21ccee
3
+ metadata.gz: b78db9a651e1cda67167ffa88e926df3cab9fd62
4
+ data.tar.gz: ba8540429aa499f8613f0b1964d2a50886bf9155
5
5
  SHA512:
6
- metadata.gz: d09fd0845bb835e317aa70f84658abf38e6ae41066ef15a0c57f59ecc1eab924e2e2626aab4580a2a43e2754f4ddae5fd3ccfe026d899e3df2705f9310721256
7
- data.tar.gz: 697211d6109bdb7607b55fba918cc417b9012f12f475e12ccd1bf2b613178ca3959f31d4264505668042782be15254c857634e02d0c5ed3bab4bc420402eec54
6
+ metadata.gz: e792b386ece097ebdbe99cc518d2ae714389d04637bf8c24f8185ce4b830b2e3f78705c70c7721d7b1a153afb0cae3f8c3d8e14a7de04346b0d9316db0a18243
7
+ data.tar.gz: c02407331e5644fba8699cb9f98e5388f85923abb1dea8f83a2c05ed1ffdec42f206a5f338eec9258486b079d8a105041d718574d37157c3d34518fb18c59c23
@@ -2,3 +2,4 @@ $LOAD_PATH.unshift(File.expand_path('../lib', __FILE__))
2
2
 
3
3
  require 'zygote/version'
4
4
  require 'zygote/http'
5
+ require 'zygote/server'
@@ -1,24 +1,28 @@
1
1
  require 'yaml'
2
2
  require 'json'
3
- require 'genesisreactor'
4
- require 'genesis/protocol/http'
3
+
5
4
  require 'active_support/all'
5
+ require 'sinatra/async'
6
+ require 'tilt/erubis'
6
7
 
7
8
  require 'zygote/util'
8
9
  require 'zygote/cell_queue'
9
10
 
10
11
  # Main HTTP class, handles routing methods
11
12
  # Uses sinatra format (all sinatra docs on routing methods apply)
12
- class ZygoteWeb < Genesis::Http::Handler
13
+ class ZygoteWeb < Sinatra::Base
14
+ register Sinatra::Async
15
+
16
+ set :show_exceptions, ENV['DEBUG'] || false
13
17
  # Requested by iPXE on boot, chains into /boot.
14
18
  # This enables us to customize what details we want iPXE to send us
15
19
  # The iPXE undionly.kpxe should contain an embedded script to call this URL
16
- get '/' do
20
+ aget '/' do
17
21
  body { erb :boot }
18
22
  end
19
23
 
20
24
  # Chainload the primary menu
21
- get '/chain' do
25
+ aget '/chain' do
22
26
  # Clean params into a simple hash
23
27
  cleaned = clean_params(params.to_h)
24
28
  # Add the request ip into the params
@@ -31,12 +35,11 @@ class ZygoteWeb < Genesis::Http::Handler
31
35
  # Check if there are is any queued data for this SKU, and if so, merge it in to params
32
36
  queued_data = CellQueue.shift(sku)
33
37
  cleaned.merge!(queued_data) if queued_data
34
- @channel << cleaned
35
38
  body { erb :menu, locals: { opts: ZygoteWeb.cell_config.merge('params' => cleaned || {}) } }
36
39
  end
37
40
 
38
41
  # Render an action for a particular cell
39
- get %r{/cell/(?<cell>\S*)/(?<action>\S*)$} do
42
+ aget %r{/cell/(?<cell>\S*)/(?<action>\S*)$} do
40
43
  # Clean params into a simple hash
41
44
  cleaned = clean_params(params.to_h)
42
45
  # Add the cell to the parameters
@@ -44,16 +47,15 @@ class ZygoteWeb < Genesis::Http::Handler
44
47
  # Merge the cleaned params in with any cell options
45
48
  cell_opts = ZygoteWeb.cell_config['index']['cells'][cell] || {}
46
49
  opts = cell_opts.merge('params' => cleaned || {})
47
- @channel << opts # for debugging
48
50
  body { erb :"#{cell}/#{cleaned['action']}".to_sym, locals: { opts: opts } }
49
51
  end
50
52
 
51
53
  # Show the queue for a SKU
52
- get %r{/queue/(?<sku>\S*)$} do
54
+ aget %r{/queue/(?<sku>\S*)$} do
53
55
  body { JSON.pretty_generate(CellQueue.show(params['sku'])) }
54
56
  end
55
57
 
56
- get %r{/queue} do
58
+ aget %r{/queue} do
57
59
  response = {}
58
60
  CellQueue.all.each do |queue_entry|
59
61
  response[queue_entry.name] = queue_entry.data
@@ -62,12 +64,12 @@ class ZygoteWeb < Genesis::Http::Handler
62
64
  end
63
65
 
64
66
  # Delete the queue for a SKU
65
- delete %r{/queue$} do
67
+ adelete %r{/queue$} do
66
68
  CellQueue.purge(params['sku'])
67
69
  body { JSON.pretty_generate(CellQueue.show(params['sku'])) }
68
70
  end
69
71
 
70
- post %r{/queue/bulk$} do
72
+ apost %r{/queue/bulk$} do
71
73
  bulk_queue = JSON.parse(request.body.read)
72
74
  bulk_queue.each do |asset, queue|
73
75
  queue = [queue] unless queue.is_a?(Array)
@@ -80,7 +82,7 @@ class ZygoteWeb < Genesis::Http::Handler
80
82
  end
81
83
 
82
84
  # Enable push cells (with optional data) to the cell queue for a SKU
83
- post %r{/queue/(?<sku>\S*)/(?<selected_cell>\S*)$} do
85
+ apost %r{/queue/(?<sku>\S*)/(?<selected_cell>\S*)$} do
84
86
  # Clean params into a simple hash
85
87
  cleaned = clean_params(params.to_h)
86
88
  # Enqueue some data for this sku
@@ -89,10 +91,6 @@ class ZygoteWeb < Genesis::Http::Handler
89
91
  body { JSON.pretty_generate(CellQueue.show(sku)) }
90
92
  end
91
93
 
92
- subscribe do |args|
93
- puts args if ENV['DEBUG']
94
- end
95
-
96
94
  def self::cell_config
97
95
  @@cell_config
98
96
  end
@@ -100,25 +98,44 @@ class ZygoteWeb < Genesis::Http::Handler
100
98
  def self::cell_config=(value)
101
99
  @@cell_config = value
102
100
  end
103
- end
104
101
 
105
- def zygote(port: 7000, threads:1000, config_path: nil, cells: [], debug:false)
106
- debug ||= ENV['DEBUG']
107
-
108
- cell_config = YAML.load(File.read(config_path || File.join(Dir.pwd, 'config', 'cells.yml')))
109
- ZygoteWeb.cell_config = cell_config
110
- zygote = Genesis::Reactor.new(
111
- threads: threads,
112
- protocols: {
113
- Genesis::Http::Protocol => port
114
- },
115
- handlers: [ZygoteWeb],
116
- views: [File.expand_path('../../../views', __FILE__), cells].flatten,
117
- debug: debug
118
- )
119
- if debug
120
- $stdout.sync = true
121
- $stderr.sync = true
102
+ def self::views
103
+ @@views
104
+ end
105
+
106
+ def self::views=(value)
107
+ @@views = value
108
+ end
109
+
110
+ helpers do
111
+ # Enable partial template rendering
112
+ def partial(template, locals = {})
113
+ erb(template, layout: false, locals: locals)
114
+ end
115
+
116
+ # Override template search directorys to add spells
117
+ def find_template(_views, *a, &block)
118
+ Array(ZygoteWeb.views).each { |v| super(v, *a, &block) }
119
+ end
120
+
121
+ # Define our asynchronous scheduling mechanism, could be anything
122
+ # Chose EM.defer for simplicity
123
+ # This powers our asynchronous requests, and keeps us from blocking the main thread.
124
+ def native_async_schedule(&b)
125
+ EM.defer(&b)
126
+ end
127
+
128
+ # Needed to properly catch exceptions in async threads
129
+ def handle_exception!(context)
130
+ if context.message == 'Sinatra::NotFound'
131
+ error_msg = "Resource #{request.path} does not exist"
132
+ puts error_msg
133
+ ahalt(404, error_msg)
134
+ else
135
+ puts context.message
136
+ puts context.backtrace.join("\n")
137
+ ahalt(500, 'Uncaught exception occurred')
138
+ end
139
+ end
122
140
  end
123
- zygote
124
141
  end
@@ -8,11 +8,11 @@ require 'supermodel'
8
8
  # https://github.com/maccman/supermodel/blob/master/README
9
9
  module Memory
10
10
  extend self
11
- DATABASE_PATH = (ENV['DATABASE_PATH'] || File.expand_path('../data/memory.db', $0)).freeze
11
+ DATABASE_PATH = (ENV['DATABASE_PATH'] || File.expand_path('../data/memory.db', $PROGRAM_NAME)).freeze
12
12
  SuperModel::Marshal.path = DATABASE_PATH
13
13
 
14
14
  def save
15
- FileUtils.mkdir_p(File.dirname(DATABASE_PATH)) # FIXME - don't make if it already exists
15
+ FileUtils.mkdir_p(File.dirname(DATABASE_PATH)) # FIXME: - don't make if it already exists
16
16
  SuperModel::Marshal.dump
17
17
  end
18
18
 
@@ -0,0 +1,41 @@
1
+ require 'zygote/http'
2
+ require 'thin'
3
+
4
+ class ZygoteServer
5
+ def initialize(port: 7000, threads:1000, host: '0.0.0.0', config_path: nil, cells: [], debug:false)
6
+ debug ||= ENV['DEBUG']
7
+
8
+ cell_config = YAML.load(File.read(config_path || File.join(Dir.pwd, 'config', 'cells.yml')))
9
+ ZygoteWeb.views = [File.expand_path('../../../views', __FILE__), cells].flatten
10
+ ZygoteWeb.cell_config = cell_config
11
+ if debug
12
+ $stdout.sync = true
13
+ $stderr.sync = true
14
+ end
15
+
16
+ app = ZygoteWeb.new
17
+ dispatch = Rack::Builder.app do
18
+ map '/' do
19
+ run app
20
+ end
21
+ end
22
+ @server = Thin::Server.new(port, host, dispatch, threadpool_size: threads).backend
23
+ end
24
+
25
+ def start
26
+ @server.start
27
+ end
28
+
29
+ def run
30
+ EM.run do
31
+ init_sighandlers
32
+ @server.start
33
+ end
34
+ end
35
+ end
36
+
37
+ def init_sighandlers
38
+ trap(:INT) { 'Got interrupt'; EM.stop; exit }
39
+ trap(:TERM) { 'Got term'; EM.stop; exit }
40
+ trap(:KILL) { 'Got kill'; EM.stop; exit }
41
+ end
@@ -24,7 +24,7 @@ module Zygote
24
24
  mod.class_eval %[
25
25
  around(:each) do |example|
26
26
  EM.synchrony do
27
- zygote(
27
+ ZygoteServer.new(
28
28
  config_path: TestConfig.config_path,
29
29
  cells: TestConfig.cells
30
30
  ).start
@@ -59,18 +59,18 @@ module Zygote
59
59
  # Returns EventMachine::HttpClient
60
60
  def get(uri, params = {})
61
61
  uriq = "#{uri}#{parameterize(params)}"
62
- EM::Synchrony.sync(EventMachine::HttpRequest.new(File.join("http://#{Socket.gethostname}:#{TestConfig.port}/", uriq)).aget(query: params))
62
+ EM::Synchrony.sync(EventMachine::HttpRequest.new(File.join("http://127.0.0.1:#{TestConfig.port}/", uriq)).aget(query: params))
63
63
  end
64
64
 
65
65
  # Returns EventMachine::HttpClient
66
66
  def delete(uri, params = {})
67
67
  uriq = "#{uri}#{parameterize(params)}"
68
- EM::Synchrony.sync(EventMachine::HttpRequest.new(File.join("http://#{Socket.gethostname}:#{TestConfig.port}/", uriq)).adelete(query: params))
68
+ EM::Synchrony.sync(EventMachine::HttpRequest.new(File.join("http://127.0.0.1:#{TestConfig.port}/", uriq)).adelete(query: params))
69
69
  end
70
70
 
71
71
  # Returns EventMachine::HttpClient
72
72
  def post(uri, params = {})
73
- EM::Synchrony.sync(EventMachine::HttpRequest.new("http://#{Socket.gethostname}:#{TestConfig.port}/#{uri}").apost(body: params))
73
+ EM::Synchrony.sync(EventMachine::HttpRequest.new("http://127.0.0.1:#{TestConfig.port}/#{uri}").apost(body: params))
74
74
  end
75
75
 
76
76
  def parameterize(params)
@@ -9,14 +9,14 @@ def compute_sku(vendor, serial, board_serial)
9
9
 
10
10
  serial = board_serial unless board_serial.empty?
11
11
 
12
- case vendor
13
- when 'DellInc'
14
- sku = 'DEL'
15
- when 'Supermicro'
16
- sku = 'SPM'
17
- else
18
- sku = 'UKN' # unknown manufacturer
19
- end
12
+ sku = case vendor
13
+ when 'DellInc'
14
+ 'DEL'
15
+ when 'Supermicro'
16
+ 'SPM'
17
+ else
18
+ 'UKN' # unknown manufacturer
19
+ end
20
20
 
21
21
  sku = "#{sku}-#{serial}"
22
22
  sku
@@ -36,5 +36,5 @@ def discover_domain
36
36
  end
37
37
 
38
38
  def kernel_params(hash)
39
- hash.map{ |k,v| v == true ? k : "#{k}=#{v}" }.join(' ')
39
+ hash.map { |k, v| v == true ? k : "#{k}=#{v}" }.join(' ')
40
40
  end
@@ -1,4 +1,4 @@
1
1
  # Namespace for our gem
2
2
  module Zygote
3
- VERSION = '0.1.5'
3
+ VERSION = '0.2.0'.freeze
4
4
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: zygote
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.5
4
+ version: 0.2.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Dale Hamel
@@ -25,47 +25,75 @@ dependencies:
25
25
  - !ruby/object:Gem::Version
26
26
  version: 0.2.0
27
27
  - !ruby/object:Gem::Dependency
28
- name: genesisreactor
28
+ name: supermodel
29
29
  requirement: !ruby/object:Gem::Requirement
30
30
  requirements:
31
31
  - - '='
32
32
  - !ruby/object:Gem::Version
33
- version: 0.0.5
33
+ version: 0.1.6
34
34
  type: :runtime
35
35
  prerelease: false
36
36
  version_requirements: !ruby/object:Gem::Requirement
37
37
  requirements:
38
38
  - - '='
39
39
  - !ruby/object:Gem::Version
40
- version: 0.0.5
40
+ version: 0.1.6
41
41
  - !ruby/object:Gem::Dependency
42
- name: supermodel
42
+ name: em-http-request
43
43
  requirement: !ruby/object:Gem::Requirement
44
44
  requirements:
45
45
  - - '='
46
46
  - !ruby/object:Gem::Version
47
- version: 0.1.6
47
+ version: 1.1.2
48
48
  type: :runtime
49
49
  prerelease: false
50
50
  version_requirements: !ruby/object:Gem::Requirement
51
51
  requirements:
52
52
  - - '='
53
53
  - !ruby/object:Gem::Version
54
- version: 0.1.6
54
+ version: 1.1.2
55
55
  - !ruby/object:Gem::Dependency
56
- name: em-http-request
56
+ name: async_sinatra
57
57
  requirement: !ruby/object:Gem::Requirement
58
58
  requirements:
59
59
  - - '='
60
60
  - !ruby/object:Gem::Version
61
- version: 1.1.2
61
+ version: 1.2.1
62
62
  type: :runtime
63
63
  prerelease: false
64
64
  version_requirements: !ruby/object:Gem::Requirement
65
65
  requirements:
66
66
  - - '='
67
67
  - !ruby/object:Gem::Version
68
- version: 1.1.2
68
+ version: 1.2.1
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: 1.0.4
76
+ type: :runtime
77
+ prerelease: false
78
+ version_requirements: !ruby/object:Gem::Requirement
79
+ requirements:
80
+ - - '='
81
+ - !ruby/object:Gem::Version
82
+ version: 1.0.4
83
+ - !ruby/object:Gem::Dependency
84
+ name: thin
85
+ requirement: !ruby/object:Gem::Requirement
86
+ requirements:
87
+ - - ">="
88
+ - !ruby/object:Gem::Version
89
+ version: 1.6.4
90
+ type: :runtime
91
+ prerelease: false
92
+ version_requirements: !ruby/object:Gem::Requirement
93
+ requirements:
94
+ - - ">="
95
+ - !ruby/object:Gem::Version
96
+ version: 1.6.4
69
97
  - !ruby/object:Gem::Dependency
70
98
  name: pry
71
99
  requirement: !ruby/object:Gem::Requirement
@@ -146,6 +174,7 @@ files:
146
174
  - lib/zygote/cell_queue.rb
147
175
  - lib/zygote/http.rb
148
176
  - lib/zygote/memory.rb
177
+ - lib/zygote/server.rb
149
178
  - lib/zygote/test.rb
150
179
  - lib/zygote/util.rb
151
180
  - lib/zygote/version.rb