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 +4 -4
- data/lib/zygote/cell_queue.rb +39 -37
- data/lib/zygote/http.rb +105 -109
- data/lib/zygote/identifier.rb +35 -0
- data/lib/zygote/memory.rb +19 -16
- data/lib/zygote/server.rb +40 -31
- data/lib/zygote/test.rb +4 -2
- data/lib/zygote/util.rb +1 -1
- data/lib/zygote/version.rb +1 -1
- metadata +17 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 79f6d6d816134c8cfadd3335a62a59c5c199da29
|
4
|
+
data.tar.gz: 95426b7b07578c63f29d74c3eeb54385abe66ba1
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 59fbfb4088ae7fe0adbd49c0b5a172ce943d6cb20b5fa876f37277e01a0b16cce8bfeb905ed27e2281b1c9ceed6998131fb12fe67a8518bcd283f5f7b8577e07
|
7
|
+
data.tar.gz: dc120384aad70375fd37cb4ce71c9ca003f639c0e2b6045b7540cbe4c991862a254064912be1b48d8a9aed299eada522ec578aa2537c473e607c38ded37d0d3d
|
data/lib/zygote/cell_queue.rb
CHANGED
@@ -1,49 +1,51 @@
|
|
1
1
|
require 'zygote/memory'
|
2
2
|
|
3
|
-
|
4
|
-
|
5
|
-
|
6
|
-
|
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
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
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
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
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
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
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
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
36
|
+
def show(key)
|
37
|
+
entry = CellQueueEntry.find_by_name(key)
|
38
|
+
entry ? entry.data : []
|
39
|
+
end
|
39
40
|
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
|
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
|
-
|
47
|
-
|
47
|
+
def all
|
48
|
+
CellQueueEntry.all
|
49
|
+
end
|
48
50
|
end
|
49
51
|
end
|
data/lib/zygote/http.rb
CHANGED
@@ -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
|
-
#
|
13
|
-
|
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
|
54
|
-
|
55
|
-
|
56
|
-
|
57
|
-
|
58
|
-
|
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
|
-
|
68
|
-
|
69
|
-
|
70
|
-
|
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
|
-
|
100
|
-
|
101
|
-
|
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
|
-
|
104
|
-
|
105
|
-
|
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
|
-
|
108
|
-
|
109
|
-
|
110
|
-
|
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
|
-
#
|
114
|
-
|
115
|
-
|
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
|
-
|
119
|
-
|
120
|
-
|
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
|
-
|
126
|
-
|
127
|
-
|
128
|
-
|
129
|
-
|
130
|
-
|
131
|
-
|
132
|
-
|
133
|
-
|
134
|
-
|
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
|
data/lib/zygote/memory.rb
CHANGED
@@ -3,24 +3,27 @@ require 'fileutils'
|
|
3
3
|
|
4
4
|
require 'supermodel'
|
5
5
|
|
6
|
-
#
|
7
|
-
|
8
|
-
#
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
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
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
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
|
-
|
20
|
-
|
21
|
+
def load
|
22
|
+
SuperModel::Marshal.load
|
23
|
+
end
|
21
24
|
end
|
22
|
-
end
|
23
25
|
|
24
|
-
at_exit do
|
25
|
-
|
26
|
+
at_exit do
|
27
|
+
Memory.save
|
28
|
+
end
|
26
29
|
end
|
data/lib/zygote/server.rb
CHANGED
@@ -1,44 +1,53 @@
|
|
1
1
|
require 'zygote/http'
|
2
2
|
require 'thin'
|
3
3
|
|
4
|
-
|
5
|
-
|
6
|
-
|
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
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
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
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
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
|
-
|
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
|
-
|
43
|
-
|
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
|
data/lib/zygote/test.rb
CHANGED
@@ -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
|
-
|
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)
|
data/lib/zygote/util.rb
CHANGED
@@ -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
|
|
data/lib/zygote/version.rb
CHANGED
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.
|
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.
|
232
|
+
rubygems_version: 2.2.3
|
218
233
|
signing_key:
|
219
234
|
specification_version: 4
|
220
235
|
summary: Differentiate servers with iPXE
|