zygote 0.2.11 → 0.2.12

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: 6e1710f705eaf6deb71e1287c48ccb34aa694ac5
4
- data.tar.gz: dc68648147162e92d2769f3c61dc24bf5d795fa9
3
+ metadata.gz: 79f6d6d816134c8cfadd3335a62a59c5c199da29
4
+ data.tar.gz: 95426b7b07578c63f29d74c3eeb54385abe66ba1
5
5
  SHA512:
6
- metadata.gz: 50fd707aff6f9d087059356a75c2265a31d154d5195e398dfe1a3216edfd14e45e2df69e1961c6442c708157a8b5dcd4883acc27b9a91b3320509d5f23f051f4
7
- data.tar.gz: 055e5c78d9cb948f3e42b0a7ef9a2c40f04488ff3b82641303ac56febf4ed374f152aea0d58e2a0c662417d7f7a30288eee63a04fa4e832a9f42c5b0a2bb3e08
6
+ metadata.gz: 59fbfb4088ae7fe0adbd49c0b5a172ce943d6cb20b5fa876f37277e01a0b16cce8bfeb905ed27e2281b1c9ceed6998131fb12fe67a8518bcd283f5f7b8577e07
7
+ data.tar.gz: dc120384aad70375fd37cb4ce71c9ca003f639c0e2b6045b7540cbe4c991862a254064912be1b48d8a9aed299eada522ec578aa2537c473e607c38ded37d0d3d
@@ -1,49 +1,51 @@
1
1
  require 'zygote/memory'
2
2
 
3
- # An entry into the queue
4
- class CellQueueEntry < SuperModel::Base
5
- include SuperModel::Marshal::Model
6
- end
3
+ module Zygote
4
+ # An entry into the queue
5
+ class CellQueueEntry < SuperModel::Base
6
+ include SuperModel::Marshal::Model
7
+ end
7
8
 
8
- # A means of storing Cell queue data for a given sku
9
- module CellQueue
10
- extend self
11
- COLLECTION = :assets
12
- ARRAY_KEY = :cell_queue
13
- Memory.load
9
+ # A means of storing Cell queue data for a given sku
10
+ module CellQueue
11
+ extend self
12
+ COLLECTION = :assets
13
+ ARRAY_KEY = :cell_queue
14
+ Memory.load
14
15
 
15
- def push(key, data)
16
- entry = CellQueueEntry.find_by_name(key)
17
- unless entry
18
- entry = CellQueueEntry.new(name: key, data: [])
16
+ def push(key, data)
17
+ entry = CellQueueEntry.find_by_name(key)
18
+ unless entry
19
+ entry = CellQueueEntry.new(name: key, data: [])
20
+ entry.save
21
+ end
22
+ entry.data << data
19
23
  entry.save
24
+ Memory.save
20
25
  end
21
- entry.data << data
22
- entry.save
23
- Memory.save
24
- end
25
26
 
26
- def shift(key)
27
- entry = CellQueueEntry.find_by_name(key)
28
- return nil unless entry
29
- first = entry.data.shift
30
- entry.save
31
- Memory.save
32
- first
33
- end
27
+ def shift(key)
28
+ entry = CellQueueEntry.find_by_name(key)
29
+ return nil unless entry
30
+ first = entry.data.shift
31
+ entry.save
32
+ Memory.save
33
+ first
34
+ end
34
35
 
35
- def show(key)
36
- entry = CellQueueEntry.find_by_name(key)
37
- entry ? entry.data : []
38
- end
36
+ def show(key)
37
+ entry = CellQueueEntry.find_by_name(key)
38
+ entry ? entry.data : []
39
+ end
39
40
 
40
- def purge(key)
41
- entry = CellQueueEntry.find_by_name(key)
42
- entry.data = [] if entry
43
- entry.save if entry
44
- end
41
+ def purge(key)
42
+ entry = CellQueueEntry.find_by_name(key)
43
+ entry.data = [] if entry
44
+ entry.save if entry
45
+ end
45
46
 
46
- def all
47
- CellQueueEntry.all
47
+ def all
48
+ CellQueueEntry.all
49
+ end
48
50
  end
49
51
  end
@@ -8,130 +8,126 @@ require 'rack/contrib'
8
8
 
9
9
  require 'zygote/util'
10
10
  require 'zygote/cell_queue'
11
+ require 'zygote/identifier'
12
+
13
+ # Main zygote container namespace
14
+ module Zygote
15
+ # Main HTTP class, handles routing methods
16
+ # Uses sinatra format (all sinatra docs on routing methods apply)
17
+ class Web < Sinatra::Base
18
+ register Sinatra::Async
19
+
20
+ use ::Rack::PostBodyContentTypeParser
21
+
22
+ # Throw exceptions so we can catch and nicely log them
23
+ set :raise_errors, true
24
+ set :show_exceptions, false
25
+ set :dump_errors, false
26
+
27
+ # Requested by iPXE on boot, chains into /boot.
28
+ # This enables us to customize what details we want iPXE to send us
29
+ # The iPXE undionly.kpxe should contain an embedded script to call this URL
30
+ aget '/' do
31
+ body { erb :boot }
32
+ end
11
33
 
12
- # Main HTTP class, handles routing methods
13
- # Uses sinatra format (all sinatra docs on routing methods apply)
14
- class ZygoteWeb < Sinatra::Base
15
- register Sinatra::Async
16
-
17
- use ::Rack::PostBodyContentTypeParser
18
-
19
- # Throw exceptions so we can catch and nicely log them
20
- set :raise_errors, true
21
- set :show_exceptions, false
22
- set :dump_errors, false
23
-
24
- # Requested by iPXE on boot, chains into /boot.
25
- # This enables us to customize what details we want iPXE to send us
26
- # The iPXE undionly.kpxe should contain an embedded script to call this URL
27
- aget '/' do
28
- body { erb :boot }
29
- end
30
-
31
- # Chainload the primary menu
32
- aget '/chain' do
33
- # Clean params into a simple hash
34
- cleaned = clean_params(params.to_h)
35
- # Add the request ip into the params
36
- ip = request.ip == '127.0.0.1' ? @env['HTTP_X_FORWARDED_FOR'] : request.ip
37
- ip = '127.0.0.1' if ENV['TESTING'] || ip.nil? || ip.empty?
38
- cleaned['ip'] = ip
39
- # Compute SKU from parameters
40
- sku = compute_sku(cleaned['manufacturer'], cleaned['serial'], cleaned['board-serial'])
41
- cleaned['sku'] = sku
42
- # Check if there are is any queued data for this SKU, and if so, merge it in to params
43
- queued_data = CellQueue.shift(sku)
44
- cleaned.merge!(queued_data) if queued_data
45
- body { erb :menu, locals: { opts: ZygoteWeb.cell_config.merge('params' => cleaned || {}) } }
46
- end
47
-
48
- [ :aget, :apost ].each do |method|
49
- send method, %r{/cell/(?<cell>\S*)/(?<action>\S*)$} do
50
- # Render an action for a particular cell
34
+ # Chainload the primary menu
35
+ aget '/chain' do
51
36
  # Clean params into a simple hash
52
37
  cleaned = clean_params(params.to_h)
53
- # Add the cell to the parameters
54
- cell = cleaned['cell']
55
- # Merge the cleaned params in with any cell options
56
- cell_opts = ZygoteWeb.cell_config['index']['cells'][cell] || {}
57
- opts = cell_opts.merge('params' => cleaned || {})
58
- body { erb :"#{cell}/#{cleaned['action']}".to_sym, locals: { opts: opts } }
38
+ # Add the request ip into the params
39
+ ip = request.ip == '127.0.0.1' ? @env['HTTP_X_FORWARDED_FOR'] : request.ip
40
+ ip = '127.0.0.1' if ENV['TESTING'] || ip.nil? || ip.empty?
41
+ cleaned['ip'] = ip
42
+ # Compute SKU from parameters
43
+ sku = compute_sku(cleaned['manufacturer'], cleaned['serial'], cleaned['board-serial'])
44
+ cleaned['sku'] = sku
45
+ # Check if there are is any queued data for this SKU, and if so, merge it in to params
46
+ queued_data = CellQueue.shift(sku)
47
+ cleaned.merge!(queued_data) if queued_data
48
+
49
+ # Provide a hook for an external identifier to alter behavior
50
+ cleaned = Zygote::Identifier.identify(cleaned)
51
+ body { erb :menu, locals: { opts: Zygote::Web.cell_config.merge('params' => cleaned || {}) } }
59
52
  end
60
- end
61
-
62
- # Show the queue for a SKU
63
- aget %r{/queue/(?<sku>\S*)$} do
64
- body { JSON.pretty_generate(CellQueue.show(params['sku'])) }
65
- end
66
53
 
67
- aget %r{/queue} do
68
- response = {}
69
- CellQueue.all.each do |queue_entry|
70
- response[queue_entry.name] = queue_entry.data
54
+ [:aget, :apost].each do |method|
55
+ send method, %r{/cell/(?<cell>\S*)/(?<action>\S*)$} do
56
+ # Render an action for a particular cell
57
+ # Clean params into a simple hash
58
+ cleaned = clean_params(params.to_h)
59
+ # Add the cell to the parameters
60
+ cell = cleaned['cell']
61
+ # Merge the cleaned params in with any cell options
62
+ cell_opts = Zygote::Web.cell_config['index']['cells'][cell] || {}
63
+ opts = cell_opts.merge('params' => cleaned || {})
64
+ body { erb :"#{cell}/#{cleaned['action']}".to_sym, locals: { opts: opts } }
65
+ end
71
66
  end
72
- body { JSON.pretty_generate(response) }
73
- end
74
-
75
- # Delete the queue for a SKU
76
- adelete %r{/queue$} do
77
- CellQueue.purge(params['sku'])
78
- body { JSON.pretty_generate(CellQueue.show(params['sku'])) }
79
- end
80
-
81
- # Enable push cells (with optional data) to the cell queue for a SKU
82
- apost %r{/queue/(?<sku>\S*)/(?<selected_cell>\S*)$} do
83
- # Clean params into a simple hash
84
- cleaned = clean_params(params.to_h)
85
- # Enqueue some data for this sku
86
- sku = cleaned.delete('sku')
87
- CellQueue.push(sku, cleaned)
88
- body { JSON.pretty_generate(CellQueue.show(sku)) }
89
- end
90
-
91
- def self::cell_config
92
- @@cell_config
93
- end
94
-
95
- def self::cell_config=(value)
96
- @@cell_config = value
97
- end
98
67
 
99
- def self::views
100
- @@views
101
- end
68
+ # Show the queue for a SKU
69
+ aget %r{/queue/(?<sku>\S*)$} do
70
+ body { JSON.pretty_generate(CellQueue.show(params['sku'])) }
71
+ end
102
72
 
103
- def self::views=(value)
104
- @@views = value
105
- end
73
+ aget %r{/queue} do
74
+ response = {}
75
+ CellQueue.all.each do |queue_entry|
76
+ response[queue_entry.name] = queue_entry.data
77
+ end
78
+ body { JSON.pretty_generate(response) }
79
+ end
106
80
 
107
- helpers do
108
- # Enable partial template rendering
109
- def partial(template, locals = {})
110
- erb(template, layout: false, locals: locals)
81
+ # Delete the queue for a SKU
82
+ adelete %r{/queue$} do
83
+ CellQueue.purge(params['sku'])
84
+ body { JSON.pretty_generate(CellQueue.show(params['sku'])) }
111
85
  end
112
86
 
113
- # Override template search directorys to add spells
114
- def find_template(_views, *a, &block)
115
- Array(ZygoteWeb.views).each { |v| super(v, *a, &block) }
87
+ # Enable push cells (with optional data) to the cell queue for a SKU
88
+ apost %r{/queue/(?<sku>\S*)/(?<selected_cell>\S*)$} do
89
+ # Clean params into a simple hash
90
+ cleaned = clean_params(params.to_h)
91
+ # Enqueue some data for this sku
92
+ sku = cleaned.delete('sku')
93
+ CellQueue.push(sku, cleaned)
94
+ body { JSON.pretty_generate(CellQueue.show(sku)) }
116
95
  end
117
96
 
118
- # Define our asynchronous scheduling mechanism, could be anything
119
- # Chose EM.defer for simplicity
120
- # This powers our asynchronous requests, and keeps us from blocking the main thread.
121
- def native_async_schedule(&b)
122
- EM.defer(&b)
97
+ class << self
98
+ attr_accessor :cell_config
99
+ attr_accessor :views
123
100
  end
124
101
 
125
- # Needed to properly catch exceptions in async threads
126
- def handle_exception!(context)
127
- if context.message == 'Sinatra::NotFound'
128
- error_msg = "Resource #{request.path} does not exist"
129
- puts error_msg
130
- ahalt(404, error_msg)
131
- else
132
- puts context.message
133
- puts context.backtrace.join("\n")
134
- ahalt(500, 'Uncaught exception occurred')
102
+ helpers do
103
+ # Enable partial template rendering
104
+ def partial(template, locals = {})
105
+ erb(template.to_sym, layout: false, locals: locals)
106
+ end
107
+
108
+ # Override template search directorys to add spells
109
+ def find_template(_views, *a, &block)
110
+ Array(Zygote::Web.views).each { |v| super(v, *a, &block) }
111
+ end
112
+
113
+ # Define our asynchronous scheduling mechanism, could be anything
114
+ # Chose EM.defer for simplicity
115
+ # This powers our asynchronous requests, and keeps us from blocking the main thread.
116
+ def native_async_schedule(&b)
117
+ EM.defer(&b)
118
+ end
119
+
120
+ # Needed to properly catch exceptions in async threads
121
+ def handle_exception!(context)
122
+ if context.message == 'Sinatra::NotFound'
123
+ error_msg = "Resource #{request.path} does not exist"
124
+ puts error_msg
125
+ ahalt(404, error_msg)
126
+ else
127
+ puts context.message
128
+ puts context.backtrace.join("\n")
129
+ ahalt(500, 'Uncaught exception occurred')
130
+ end
135
131
  end
136
132
  end
137
133
  end
@@ -0,0 +1,35 @@
1
+ module Zygote
2
+ # Provides a hook for identifiers to alter boot-time behavior
3
+ # To do so, extend this class with a new identify method.
4
+ # You may NOT define more than one identifier - the last one wins.
5
+ # class MyIdentifier < Zygote::Identifier
6
+ # def identify
7
+ # mutate_params(@params)
8
+ # end
9
+ # end
10
+ class Identifier
11
+ class << self
12
+ def inherited(subclass)
13
+ @identifier = subclass
14
+ end
15
+
16
+ def identify(params)
17
+ @identifier ||= self
18
+ @identifier.new(params).identify
19
+ end
20
+
21
+ def reset!
22
+ @identifier = self
23
+ end
24
+ end
25
+
26
+ def initialize(params)
27
+ @params = params
28
+ end
29
+
30
+ # Called only if this class is never subclassed
31
+ def identify
32
+ @params
33
+ end
34
+ end
35
+ end
@@ -3,24 +3,27 @@ require 'fileutils'
3
3
 
4
4
  require 'supermodel'
5
5
 
6
- # A simple means of persistence
7
- # This can easily be swapped out for redis, but file-based is simpler and good enough for now
8
- # https://github.com/maccman/supermodel/blob/master/README
9
- module Memory
10
- extend self
11
- DATABASE_PATH = (ENV['DATABASE_PATH'] || File.expand_path('../data/memory.db', $PROGRAM_NAME)).freeze
12
- SuperModel::Marshal.path = DATABASE_PATH
6
+ # Zygote container
7
+ module Zygote
8
+ # A simple means of persistence
9
+ # This can easily be swapped out for redis, but file-based is simpler and good enough for now
10
+ # https://github.com/maccman/supermodel/blob/master/README
11
+ module Memory
12
+ extend self
13
+ DATABASE_PATH = (ENV['DATABASE_PATH'] || File.expand_path('../data/memory.db', $PROGRAM_NAME)).freeze
14
+ SuperModel::Marshal.path = DATABASE_PATH
13
15
 
14
- def save
15
- FileUtils.mkdir_p(File.dirname(DATABASE_PATH)) # FIXME: - don't make if it already exists
16
- SuperModel::Marshal.dump
17
- end
16
+ def save
17
+ FileUtils.mkdir_p(File.dirname(DATABASE_PATH)) # FIXME: - don't make if it already exists
18
+ SuperModel::Marshal.dump
19
+ end
18
20
 
19
- def load
20
- SuperModel::Marshal.load
21
+ def load
22
+ SuperModel::Marshal.load
23
+ end
21
24
  end
22
- end
23
25
 
24
- at_exit do
25
- Memory.save
26
+ at_exit do
27
+ Memory.save
28
+ end
26
29
  end
@@ -1,44 +1,53 @@
1
1
  require 'zygote/http'
2
2
  require 'thin'
3
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']
4
+ # Main zygote namespace
5
+ module Zygote
6
+ # Wrapper around thin / event machine to run zygote sinatra rack app in.
7
+ class Server
8
+ def initialize(port: 7000, threads: 1000, host: '0.0.0.0', config_path: nil, cells: [], debug: false)
9
+ debug ||= ENV['DEBUG']
7
10
 
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
11
+ cell_config = YAML.load(File.read(config_path || File.join(Dir.pwd, 'config', 'cells.yml')))
12
+ Zygote::Web.views = [File.expand_path('../../../views', __FILE__), cells].flatten
13
+ Zygote::Web.cell_config = cell_config
14
+ if debug
15
+ $stdout.sync = true
16
+ $stderr.sync = true
17
+ end
15
18
 
16
- app = ZygoteWeb.new
17
- dispatch = Rack::Builder.app do
18
- map '/' do
19
- run app
19
+ app = Zygote::Web.new
20
+ dispatch = Rack::Builder.app do
21
+ map '/' do
22
+ run app
23
+ end
20
24
  end
25
+ Thin::Logging.trace = true if debug
26
+ @server = Thin::Server.new(port, host, dispatch, threadpool_size: threads).backend
21
27
  end
22
- Thin::Logging.trace=true if debug
23
- @server = Thin::Server.new(port, host, dispatch, threadpool_size: threads).backend
24
- end
25
28
 
26
- def start
27
- @server.start
28
- rescue => ex
29
- puts ex
30
- puts ex.backtrace.join("\n")
31
- end
32
-
33
- def run
34
- EM.run do
35
- init_sighandlers
29
+ def start
36
30
  @server.start
31
+ rescue => ex
32
+ puts ex
33
+ puts ex.backtrace.join("\n")
34
+ end
35
+
36
+ def run
37
+ EM.run do
38
+ init_sighandlers
39
+ @server.start
40
+ end
37
41
  end
38
42
  end
39
- end
40
43
 
41
- def init_sighandlers
42
- Signal.trap('INT') { 'Got interrupt'; EM.stop; exit }
43
- Signal.trap('TERM') { 'Got term'; EM.stop; exit }
44
+ def init_sighandlers
45
+ clean_quit = lambda do
46
+ EM.stop
47
+ exit
48
+ end
49
+
50
+ Signal.trap('INT') { clean_quit.call }
51
+ Signal.trap('TERM') { clean_quit.call }
52
+ end
44
53
  end
@@ -6,7 +6,9 @@ require 'rspec'
6
6
  require 'em-synchrony'
7
7
  require 'em-synchrony/em-http'
8
8
 
9
+ # Main zygote class
9
10
  module Zygote
11
+ # Helper to set up test config
10
12
  module TestConfig
11
13
  extend self
12
14
  attr_reader :config_path, :cells, :port, :fixtures
@@ -24,7 +26,7 @@ module Zygote
24
26
  mod.class_eval %[
25
27
  around(:each) do |example|
26
28
  EM.synchrony do
27
- ZygoteServer.new(
29
+ Zygote::Server.new(
28
30
  config_path: TestConfig.config_path,
29
31
  cells: TestConfig.cells
30
32
  ).start
@@ -70,7 +72,7 @@ module Zygote
70
72
 
71
73
  # Returns EventMachine::HttpClient
72
74
  def post(uri, params = {})
73
- EM::Synchrony.sync(EventMachine::HttpRequest.new("http://127.0.0.1:#{TestConfig.port}/#{uri}").apost(body: JSON.dump(params), head: {'Content-Type' => 'application/json'}))
75
+ EM::Synchrony.sync(EventMachine::HttpRequest.new("http://127.0.0.1:#{TestConfig.port}/#{uri}").apost(body: JSON.dump(params), head: { 'Content-Type' => 'application/json' }))
74
76
  end
75
77
 
76
78
  def parameterize(params)
@@ -26,7 +26,7 @@ end
26
26
 
27
27
  def clean_params(params)
28
28
  params.delete_if { |x, _| x == 'splat' || x == 'captures' }
29
- params = params.map { |k,v| [k, v.is_a?(Hash) ? encode64(v) : v] }.to_h
29
+ params = params.map { |k, v| [k, v.is_a?(Hash) ? encode64(v) : v] }.to_h
30
30
  params
31
31
  end
32
32
 
@@ -1,4 +1,4 @@
1
1
  # Namespace for our gem
2
2
  module Zygote
3
- VERSION = '0.2.11'.freeze
3
+ VERSION = '0.2.12'.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.2.11
4
+ version: 0.2.12
5
5
  platform: ruby
6
6
  authors:
7
7
  - Dale Hamel
@@ -178,6 +178,20 @@ dependencies:
178
178
  - - '='
179
179
  - !ruby/object:Gem::Version
180
180
  version: 3.2.0
181
+ - !ruby/object:Gem::Dependency
182
+ name: rubocop
183
+ requirement: !ruby/object:Gem::Requirement
184
+ requirements:
185
+ - - "~>"
186
+ - !ruby/object:Gem::Version
187
+ version: 0.40.0
188
+ type: :development
189
+ prerelease: false
190
+ version_requirements: !ruby/object:Gem::Requirement
191
+ requirements:
192
+ - - "~>"
193
+ - !ruby/object:Gem::Version
194
+ version: 0.40.0
181
195
  description: Automate baremetal server actions with iPXE
182
196
  email: dale.hamel@srvthe.net
183
197
  executables: []
@@ -187,6 +201,7 @@ files:
187
201
  - lib/zygote.rb
188
202
  - lib/zygote/cell_queue.rb
189
203
  - lib/zygote/http.rb
204
+ - lib/zygote/identifier.rb
190
205
  - lib/zygote/memory.rb
191
206
  - lib/zygote/server.rb
192
207
  - lib/zygote/test.rb
@@ -214,7 +229,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
214
229
  version: '0'
215
230
  requirements: []
216
231
  rubyforge_project:
217
- rubygems_version: 2.4.8
232
+ rubygems_version: 2.2.3
218
233
  signing_key:
219
234
  specification_version: 4
220
235
  summary: Differentiate servers with iPXE