cloud_powers 0.2.7.17 → 0.2.7.18
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 +4 -4
- data/.gitignore +1 -0
- data/bin/console +4 -2
- data/cloud_powers.gemspec +3 -2
- data/lib/cloud_powers/context.rb +52 -49
- data/lib/cloud_powers/delegator.rb +3 -2
- data/lib/cloud_powers/helper.rb +4 -4
- data/lib/cloud_powers/node.rb +23 -13
- data/lib/cloud_powers/self_awareness.rb +3 -3
- data/lib/cloud_powers/synapse/pipe/pipe.rb +4 -4
- data/lib/cloud_powers/synapse/queue/board.rb +2 -4
- data/lib/cloud_powers/synapse/queue/queue.rb +1 -1
- data/lib/cloud_powers/synapse/websocket/websocket_adam.rb +46 -0
- data/lib/cloud_powers/synapse/websocket/websocserver.rb +1 -1
- data/lib/cloud_powers/version.rb +1 -1
- data/lib/cloud_powers/workflow_factory.rb +119 -0
- data/lib/cloud_powers.rb +3 -1
- data/lib/stubs/aws_stubs.rb +1 -1
- metadata +21 -7
- data/Gemfile.lock +0 -71
- data/lib/cloud_powers/workflow.rb +0 -34
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 67494328df5302a9b4d213c72db3e9908242b29b
|
4
|
+
data.tar.gz: 1b55bde60cf41b5c91e124adb701c28acdcee806
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 437893087eaad11bd923a28752a13d577c964224e2a587aaf942d1fa5c05c5d36d5329b331f9d62fead7c7e2719d8508753e887e75feeae54a0da218ef53050b
|
7
|
+
data.tar.gz: c3925079a69e4b58d74a8ea42d04e8c6df77fc46a366188e9bc03ccef87d613db65465f3879387507014b553a0bb3ae89d0181d03b0a02787ed92efa16678247
|
data/.gitignore
CHANGED
data/bin/console
CHANGED
@@ -1,7 +1,8 @@
|
|
1
1
|
#!/usr/bin/env ruby
|
2
2
|
|
3
|
-
require
|
4
|
-
require
|
3
|
+
require 'bundler/setup'
|
4
|
+
require 'cloud_powers'
|
5
|
+
require 'stubs/aws_stubs'
|
5
6
|
|
6
7
|
# You can add fixtures and/or initialization code here to make experimenting
|
7
8
|
# with your gem easier. You can also use a different console, if you like.
|
@@ -12,3 +13,4 @@ require "cloud_powers"
|
|
12
13
|
|
13
14
|
require "irb"
|
14
15
|
IRB.start
|
16
|
+
include Smash::CloudPowers
|
data/cloud_powers.gemspec
CHANGED
@@ -15,7 +15,7 @@ Gem::Specification.new do |spec|
|
|
15
15
|
It was developed specifically for the Brain project but hopefully can be used
|
16
16
|
in any other ruby project that needs to use cloud service providers' resources.
|
17
17
|
|
18
|
-
Version 0.2.8 has a
|
18
|
+
Version 0.2.8 has a some EC2, S3, SQS, SNS, Kinesis, websockets and a few other
|
19
19
|
features you can find in the docs. There is also limitted support for stubbing
|
20
20
|
AWS RESTful API calls. That can come in handy for local testing and extra setup on
|
21
21
|
AWS resource clients.
|
@@ -43,8 +43,9 @@ Gem::Specification.new do |spec|
|
|
43
43
|
spec.add_runtime_dependency 'zip-zip', '~> 0.3'
|
44
44
|
spec.add_runtime_dependency 'websocket-eventmachine-server'
|
45
45
|
spec.add_runtime_dependency 'websocket-eventmachine-client'
|
46
|
+
spec.add_runtime_dependency 'workflow'
|
46
47
|
|
47
|
-
spec.add_development_dependency 'bundler', '~> 1.
|
48
|
+
spec.add_development_dependency 'bundler', '~> 1.13.5'
|
48
49
|
spec.add_development_dependency 'byebug', '~> 9'
|
49
50
|
spec.add_development_dependency 'rake', '~> 10.0'
|
50
51
|
spec.add_development_dependency 'rspec', '~> 3.0'
|
data/lib/cloud_powers/context.rb
CHANGED
@@ -13,7 +13,6 @@ module Smash
|
|
13
13
|
include Smash::CloudPowers::Helper
|
14
14
|
|
15
15
|
attr_accessor :package # The given data structure that is used to build @structure
|
16
|
-
attr_reader :structure # A Hash that is used to represent the scheme of the Context
|
17
16
|
|
18
17
|
# Attempts to create a Context out of the argument(s) you've
|
19
18
|
# passed.
|
@@ -110,8 +109,10 @@ module Smash
|
|
110
109
|
end
|
111
110
|
|
112
111
|
# Parse the given JSON
|
113
|
-
# Parameters
|
114
|
-
#
|
112
|
+
# Parameters
|
113
|
+
# +JSON+
|
114
|
+
# Returns
|
115
|
+
# +Hash+
|
115
116
|
def translate_json(json_string)
|
116
117
|
begin
|
117
118
|
JSON.parse(json_string)
|
@@ -121,58 +122,60 @@ module Smash
|
|
121
122
|
end
|
122
123
|
|
123
124
|
# Re-layer this flattened Array or enumerable list so that it looks like the
|
124
|
-
#
|
125
|
-
#
|
126
|
-
#
|
127
|
-
#
|
128
|
-
#
|
129
|
-
#
|
130
|
-
#
|
131
|
-
#
|
132
|
-
#
|
133
|
-
#
|
134
|
-
#
|
135
|
-
#
|
136
|
-
#
|
137
|
-
#
|
138
|
-
#
|
139
|
-
#
|
140
|
-
#
|
141
|
-
#
|
142
|
-
#
|
143
|
-
#
|
144
|
-
#
|
145
|
-
#
|
146
|
-
#
|
147
|
-
#
|
148
|
-
#
|
149
|
-
#
|
150
|
-
#
|
151
|
-
#
|
152
|
-
#
|
153
|
-
#
|
154
|
-
#
|
155
|
-
#
|
156
|
-
#
|
157
|
-
#
|
158
|
-
#
|
159
|
-
#
|
160
|
-
#
|
161
|
-
#
|
162
|
-
#
|
163
|
-
#
|
125
|
+
# Hash that it used to be before the Smash::Context#flatten() method was called
|
126
|
+
#
|
127
|
+
# Parameters
|
128
|
+
# +Array+|+List+|+Enumerable+
|
129
|
+
#
|
130
|
+
# Example
|
131
|
+
# * flat
|
132
|
+
#
|
133
|
+
# [
|
134
|
+
# object_name_1, config_1a, config_2a, ...,
|
135
|
+
# object_2, config_1b, etc,
|
136
|
+
# ...
|
137
|
+
# ]
|
138
|
+
#
|
139
|
+
# * or grouped
|
140
|
+
#
|
141
|
+
# [
|
142
|
+
# [object_name_1, config_1a, config_2a, ...],
|
143
|
+
# [object_2, config_1b, etc],
|
144
|
+
# ...
|
145
|
+
# ]
|
146
|
+
#
|
147
|
+
# * or structured
|
148
|
+
#
|
149
|
+
# [
|
150
|
+
# [object_name_1, [config_1a, config_2a, ...]],
|
151
|
+
# [object_2, [config_1b, etc]],
|
152
|
+
# ...
|
153
|
+
# ]
|
154
|
+
#
|
155
|
+
# * returns
|
156
|
+
#
|
157
|
+
# {
|
158
|
+
# object_1: [config_1a, config_2a, ...],
|
159
|
+
# object_2: [config_1b, ...],
|
160
|
+
# ...
|
161
|
+
# }
|
162
|
+
# Returns
|
163
|
+
# +Hash+
|
164
|
+
#
|
165
|
+
# Notes
|
166
|
+
# If +#valid_package_hash?()+ is called on this Hash, it will return true
|
164
167
|
def translate_list(list)
|
165
168
|
list.first.kind_of?(Enumerable) ? translate_simplified(list) : translate_flattened(list)
|
166
169
|
end
|
167
170
|
|
168
171
|
# Translates an Array into a valid @structure Hash
|
169
172
|
# Parameters arr <Array>
|
170
|
-
#
|
171
|
-
#
|
172
|
-
#
|
173
|
-
#
|
174
|
-
#
|
175
|
-
#
|
173
|
+
# e.g.
|
174
|
+
# [:task, ['demo'], :queue, ['name1','name2',.,.,.,.,.], {other config hash},..., :pipe, ['name1']
|
175
|
+
# Returns
|
176
|
+
# +Hash+
|
177
|
+
# Notes
|
178
|
+
# * calling +#valid_hash_format?()+ on returned Hash will return true
|
176
179
|
def translate_flattened(list)
|
177
180
|
arr = list.to_a
|
178
181
|
results = []
|
@@ -58,11 +58,12 @@ module Smash
|
|
58
58
|
if approved_task? task
|
59
59
|
source_task(task)
|
60
60
|
require_relative task_require_path(task)
|
61
|
-
Smash.const_get(to_pascal(task)).new(id, body)
|
61
|
+
# Smash.const_get(to_pascal(task)).new(id, body)
|
62
|
+
Smash.const_get(to_pascal(task)).create(id, body)
|
62
63
|
else
|
63
64
|
Smash::Task.new(id, body) # returns a default Task
|
64
65
|
end
|
65
|
-
rescue JSON::ParserError
|
66
|
+
rescue JSON::ParserError
|
66
67
|
message = [msg.body, format_error_message(e)].join("\n")
|
67
68
|
logger.info "Message in backlog is ill-formatted: #{message}"
|
68
69
|
pipe_to(:status_stream) { sitrep(extraInfo: { message: message }) }
|
data/lib/cloud_powers/helper.rb
CHANGED
@@ -139,7 +139,7 @@ module Smash
|
|
139
139
|
def format_error_message(error)
|
140
140
|
begin
|
141
141
|
[error.message, error.backtrace.join("\n")].join("\n")
|
142
|
-
rescue Exception
|
142
|
+
rescue Exception
|
143
143
|
# if the formatting won't work, return the original exception
|
144
144
|
error
|
145
145
|
end
|
@@ -272,7 +272,7 @@ module Smash
|
|
272
272
|
begin
|
273
273
|
File.new("#{task_home}/#{file}")
|
274
274
|
true
|
275
|
-
rescue Errno::ENOENT
|
275
|
+
rescue Errno::ENOENT
|
276
276
|
false
|
277
277
|
end
|
278
278
|
end
|
@@ -293,7 +293,7 @@ module Smash
|
|
293
293
|
begin
|
294
294
|
file_sans_extension = File.basename(file_name, '.*')
|
295
295
|
(Pathname.new(task_home) + file_sans_extension).to_s
|
296
|
-
rescue Errno::ENOENT
|
296
|
+
rescue Errno::ENOENT
|
297
297
|
nil
|
298
298
|
end
|
299
299
|
end
|
@@ -433,7 +433,7 @@ module Smash
|
|
433
433
|
begin
|
434
434
|
JSON.parse(json)
|
435
435
|
true
|
436
|
-
rescue Exception
|
436
|
+
rescue Exception
|
437
437
|
false
|
438
438
|
end
|
439
439
|
end
|
data/lib/cloud_powers/node.rb
CHANGED
@@ -19,16 +19,16 @@ module Smash
|
|
19
19
|
# configuration.
|
20
20
|
def node_config(opts = {})
|
21
21
|
{
|
22
|
-
dry_run:
|
23
|
-
image_id:
|
24
|
-
instance_type:
|
25
|
-
min_count:
|
26
|
-
max_count:
|
27
|
-
key_name:
|
28
|
-
security_groups:
|
29
|
-
security_group_ids:
|
30
|
-
placement:
|
31
|
-
disable_api_termination:
|
22
|
+
dry_run: zfind(:testing) || false,
|
23
|
+
image_id: image('crawlbotprod').image_id, # image(:neuron).image_id
|
24
|
+
instance_type: 't2.nano',
|
25
|
+
min_count: opts[:max_count] || 0,
|
26
|
+
max_count: 0,
|
27
|
+
key_name: 'crawlBot',
|
28
|
+
security_groups: ['webCrawler'],
|
29
|
+
security_group_ids: ['sg-940edcf2'],
|
30
|
+
placement: { availability_zone: 'us-west-2c' },
|
31
|
+
disable_api_termination: 'false',
|
32
32
|
instance_initiated_shutdown_behavior: 'terminate'
|
33
33
|
}.merge(opts)
|
34
34
|
end
|
@@ -44,17 +44,27 @@ module Smash
|
|
44
44
|
# an optional instance configuration hash can be passed, which will override
|
45
45
|
# the values in the default configuration returned by #instance_config()
|
46
46
|
def spin_up_neurons(opts = {})
|
47
|
+
should_wait = opts.delete(:wait) || true
|
47
48
|
ids = nil
|
48
49
|
begin
|
49
50
|
response = ec2.run_instances(node_config(opts))
|
50
51
|
ids = response.instances.map(&:instance_id)
|
51
52
|
|
52
|
-
|
53
|
-
|
53
|
+
if should_wait
|
54
|
+
count = 0
|
55
|
+
begin
|
56
|
+
ec2.wait_until(:instance_running, instance_ids: ids) do
|
57
|
+
logger.info "waiting for #{ids.count} Neurons to start..."
|
58
|
+
end
|
59
|
+
rescue Aws::Waiters::Errors::WaiterFailed => e
|
60
|
+
# TODO: deal with failed instances
|
61
|
+
# redo unless (count += 1 <=3 )
|
62
|
+
end
|
54
63
|
end
|
64
|
+
ids
|
55
65
|
|
56
66
|
# tag(ids, { key: 'task', value: to_camel(self.class.to_s) })
|
57
|
-
rescue Aws::EC2::Errors::DryRunOperation
|
67
|
+
rescue Aws::EC2::Errors::DryRunOperation
|
58
68
|
ids = (1..(opts[:max_count] || 0)).to_a.map { |n| n.to_s }
|
59
69
|
logger.info "waiting for #{ids.count} Neurons to start..."
|
60
70
|
end
|
@@ -28,7 +28,7 @@ module Smash
|
|
28
28
|
@boot_time ||=
|
29
29
|
ec2.describe_instances(dry_run: zfind(:testing), instance_ids:[instance_id]).
|
30
30
|
reservations[0].instances[0].launch_time.to_i
|
31
|
-
rescue Aws::EC2::Errors::DryRunOperation
|
31
|
+
rescue Aws::EC2::Errors::DryRunOperation
|
32
32
|
logger.info "dry run for testing: #{e}"
|
33
33
|
@boot_time ||= Time.now.to_i # comment the code below for development mode
|
34
34
|
end
|
@@ -55,7 +55,7 @@ module Smash
|
|
55
55
|
send_logs_to_s3
|
56
56
|
begin
|
57
57
|
ec2.terminate_instances(dry_run: zfind('testing'), ids: [@instance_id])
|
58
|
-
rescue Aws::EC2::Error::DryRunOperation
|
58
|
+
rescue Aws::EC2::Error::DryRunOperation
|
59
59
|
logger.info "dry run testing in die! #{format_error_message(e)}"
|
60
60
|
@instance_id
|
61
61
|
end
|
@@ -176,7 +176,7 @@ module Smash
|
|
176
176
|
begin
|
177
177
|
ec2.describe_instances(dry_run: zfind('TESTING'), instance_ids: [id]).
|
178
178
|
reservations[0].instances[0].state.name
|
179
|
-
rescue Aws::EC2::Errors::DryRunOperation
|
179
|
+
rescue Aws::EC2::Errors::DryRunOperation
|
180
180
|
logger.info "Dry run flag set for testing: #{e}"
|
181
181
|
'testing'
|
182
182
|
end
|
@@ -63,6 +63,7 @@ module Smash
|
|
63
63
|
create_stream(stream) unless stream_exists? stream
|
64
64
|
records = yield if block_given?
|
65
65
|
body = message_body_collection(records)
|
66
|
+
puts body
|
66
67
|
# TODO: this isn't working yet. figure out retry logic
|
67
68
|
# resp = kinesis.put_records(body)
|
68
69
|
# retry(lambda { stream_exists? stream }) flow_to(stream)
|
@@ -132,8 +133,7 @@ module Smash
|
|
132
133
|
# end
|
133
134
|
def pipe_to(stream)
|
134
135
|
message = ''
|
135
|
-
|
136
|
-
create_stream() unless stream_exists? stream
|
136
|
+
create_stream() unless stream_exists?(zfind(stream) || stream)
|
137
137
|
message = yield if block_given?
|
138
138
|
body = update_message_body(message)
|
139
139
|
resp = kinesis.put_record pipe_message_body(stream_name: stream, data: body.to_json)
|
@@ -148,7 +148,7 @@ module Smash
|
|
148
148
|
# * * stream_name - the name to give the stream
|
149
149
|
# * * shard_count - the number of shards to create
|
150
150
|
def stream_config(opts = {})
|
151
|
-
|
151
|
+
{
|
152
152
|
stream_name: opts[:stream_name] || zfind(:status_stream),
|
153
153
|
shard_count: opts[:shard_count] || 1
|
154
154
|
}
|
@@ -165,7 +165,7 @@ module Smash
|
|
165
165
|
begin
|
166
166
|
kinesis.describe_stream(stream_name: name)
|
167
167
|
true
|
168
|
-
rescue Aws::Kinesis::Errors::ResourceNotFoundException
|
168
|
+
rescue Aws::Kinesis::Errors::ResourceNotFoundException
|
169
169
|
false
|
170
170
|
end
|
171
171
|
end
|
@@ -11,11 +11,9 @@ module Smash
|
|
11
11
|
include Smash::CloudPowers::Zenv
|
12
12
|
|
13
13
|
# The URL the Aws::SQS::Queue uses
|
14
|
-
|
14
|
+
attr_writer :address
|
15
15
|
# The name the Aws::SQS::Queue uses
|
16
16
|
attr_accessor :name
|
17
|
-
# An Aws::SQS::QueuePoller for this Board/SQS::Queue
|
18
|
-
attr_accessor :poller
|
19
17
|
# An Aws::SQS::Client. See +#Smash::CloudPowers::AwsResources.sqs()+
|
20
18
|
attr_accessor :sqs
|
21
19
|
|
@@ -105,7 +103,7 @@ module Smash
|
|
105
103
|
begin
|
106
104
|
sqs.create_queue(queue_name: to_camel(@name))
|
107
105
|
self
|
108
|
-
rescue Aws::SQS::Errors::QueueDeletedRecently
|
106
|
+
rescue Aws::SQS::Errors::QueueDeletedRecently
|
109
107
|
sleep 5
|
110
108
|
retry
|
111
109
|
end
|
@@ -0,0 +1,46 @@
|
|
1
|
+
require 'websocket-eventmachine-server'
|
2
|
+
module Smash
|
3
|
+
module CloudPowers
|
4
|
+
module Synapse
|
5
|
+
module WebSocServer
|
6
|
+
def create_wesoc_server(opts = {})
|
7
|
+
channel = opts[:channel] || EM::Channel.new
|
8
|
+
Thread.new do
|
9
|
+
Em.run do
|
10
|
+
WebSocket::EventMachine::Server.start(:host => host, :port => port) do |ws|
|
11
|
+
sid = nil
|
12
|
+
|
13
|
+
open_callback = opts[:on_open] || Proc.new do
|
14
|
+
puts "Client connected"
|
15
|
+
sid = channel.subscribe { |msg| ws.send msg }
|
16
|
+
end
|
17
|
+
ws.onopen { open_callback }
|
18
|
+
|
19
|
+
on_message_callback = opts[:on_message] || Proc.new do |msg, type|
|
20
|
+
@current_websocket_message = msg
|
21
|
+
end
|
22
|
+
ws.onmessage { on_message_callback }
|
23
|
+
|
24
|
+
on_error_callback = opts[:on_error] || Proc.new do |error|
|
25
|
+
puts "Error occured: #{error}"
|
26
|
+
end
|
27
|
+
ws.onerror { on_error_callback }
|
28
|
+
|
29
|
+
on_close_callback = opts[:on_close] || Proc.new do
|
30
|
+
puts "Client disconnected"
|
31
|
+
channel.unsubscribe(sid) unless channel.nil?
|
32
|
+
end
|
33
|
+
ws.onclose { on_close_callback }
|
34
|
+
end
|
35
|
+
end
|
36
|
+
end
|
37
|
+
channel
|
38
|
+
end
|
39
|
+
|
40
|
+
def send(channel, msg)
|
41
|
+
channel.push msg
|
42
|
+
end
|
43
|
+
end
|
44
|
+
end
|
45
|
+
end
|
46
|
+
end
|
data/lib/cloud_powers/version.rb
CHANGED
@@ -0,0 +1,119 @@
|
|
1
|
+
require 'workflow'
|
2
|
+
|
3
|
+
module Smash
|
4
|
+
module CloudPowers
|
5
|
+
# The WorkflowFactory module provides you with a custom, embeddable workflow
|
6
|
+
# for classes. To do this, it takes a description of the workflow, in
|
7
|
+
# the form of a <tt>Hash</tt> and injects it into the class' Singleton/Eigan
|
8
|
+
# class. It uses the +workflow+ gem to handle the workflow stuff for now
|
9
|
+
# but after MVP, this will be a roll-our-own implementation, to cut down on
|
10
|
+
# all dependencies possible.
|
11
|
+
module WorkflowFactory
|
12
|
+
# This is the method responsible for injecting the workflow on the instance
|
13
|
+
# it is called on. After this method is called on an instance of some class,
|
14
|
+
# you can then access any of the described states as methods on that instance.
|
15
|
+
#
|
16
|
+
# Parameters
|
17
|
+
# * description +Hash+ - Describe the workflow you want to use. The format
|
18
|
+
# follows the actual Workflow Specification(s) from the gem that you would
|
19
|
+
# normally write onto the class like normal.
|
20
|
+
#
|
21
|
+
# * Example +description+ +Hash+
|
22
|
+
# * * this description would give you a workflow that starts in the +new+
|
23
|
+
# state and when the <tt>#build!()</tt> method was called on the object
|
24
|
+
# that has this workflow, the state would transition into the +building+
|
25
|
+
# state. The workflow would then listen for the <tt>run!()</tt> method
|
26
|
+
# call, which would progress the state to the +in_progress+ state. Next,
|
27
|
+
# the workflow would listen for the <tt>post_results!()</tt> method
|
28
|
+
# call. When someone or something calls it, the state will progress to
|
29
|
+
# the final state, +done+, from which no more workflow stuff will happen.
|
30
|
+
#
|
31
|
+
# description = {
|
32
|
+
# workflow: {
|
33
|
+
# states: [
|
34
|
+
# { new: { event: :build, transitions_to: :building } },
|
35
|
+
# { building: { event: :run, transitions_to: :in_progress } },
|
36
|
+
# { in_progress: { event: :post_results, transitions_to: :done } },
|
37
|
+
# { done: nil }
|
38
|
+
# ]
|
39
|
+
# }
|
40
|
+
# }
|
41
|
+
#
|
42
|
+
# ##Returns
|
43
|
+
# * +nil+
|
44
|
+
#
|
45
|
+
# ##Example
|
46
|
+
# * build the workflow using the description from above
|
47
|
+
# class Job
|
48
|
+
# # code code code...
|
49
|
+
# def insert_my_workflow(description)
|
50
|
+
# class << build_workflow(description)
|
51
|
+
# end
|
52
|
+
# end
|
53
|
+
#
|
54
|
+
# Which would yield this workflow, from the Workflow gem
|
55
|
+
#
|
56
|
+
# class Job
|
57
|
+
# # all the commented lines below are what `WorkflowFactory#inject_workflow()`
|
58
|
+
# # did for you. These lines don't need to actually be in your class.
|
59
|
+
#
|
60
|
+
# # include Workflow
|
61
|
+
# #
|
62
|
+
# # workflow do
|
63
|
+
# # state :new do
|
64
|
+
# # event :build, :transitions_to => :building
|
65
|
+
# # end
|
66
|
+
# # state :building do
|
67
|
+
# # event :run, :transitions_to => :in_progress
|
68
|
+
# # end
|
69
|
+
# # state :in_progress do
|
70
|
+
# # event :post_results, :transitions_to => :done
|
71
|
+
# # end
|
72
|
+
# # state :done
|
73
|
+
# # end
|
74
|
+
# end
|
75
|
+
#
|
76
|
+
# job = Job.new
|
77
|
+
# # => #<Job:0x007fdaba8956b0>
|
78
|
+
# job.done?
|
79
|
+
# # => NoMethodError
|
80
|
+
# job.insert_workflow(description)
|
81
|
+
# # => nil
|
82
|
+
# job.done?
|
83
|
+
# # => false
|
84
|
+
# job.current_state
|
85
|
+
# # => :building
|
86
|
+
#
|
87
|
+
# Notes
|
88
|
+
# * TODO: There has got to be a better way, so if any of you have suggestions...
|
89
|
+
# The fact that the eval gets evaluated and invoked in the workflow gem
|
90
|
+
# is of little comfort, despite how nice the gem is. Long story short,
|
91
|
+
# be comfortable with what you're doing.
|
92
|
+
# * see the workflow gem docs and question me if you want some nice ways
|
93
|
+
# to really use this module. {workflow homepage}[https://github.com/geekq/workflow]
|
94
|
+
def inject_workflow(description)
|
95
|
+
description_string_builder = ['include Workflow', 'workflow do']
|
96
|
+
description[:workflow][:states].each do |state|
|
97
|
+
state.map do |name, state_description|
|
98
|
+
if state_description.nil? # if this is a final state...
|
99
|
+
description_string_builder << "state :#{name}"
|
100
|
+
else # because it is not a final state, add event information too.
|
101
|
+
description_string_builder.concat([
|
102
|
+
"state :#{name} do",
|
103
|
+
"event :#{state_description[:event]}, transitions_to: :#{state_description[:transitions_to]}",
|
104
|
+
"end"
|
105
|
+
])
|
106
|
+
end
|
107
|
+
end
|
108
|
+
end
|
109
|
+
description_string_builder << "end\n"
|
110
|
+
begin
|
111
|
+
self.class.class_eval(description_string_builder.join("\n"))
|
112
|
+
define_singleton_method(:has_workflow?) { true }
|
113
|
+
rescue Exception => e
|
114
|
+
define_singleton_method(:has_workflow?) { !!(puts e.backtrace) }
|
115
|
+
end
|
116
|
+
end
|
117
|
+
end
|
118
|
+
end
|
119
|
+
end
|
data/lib/cloud_powers.rb
CHANGED
@@ -7,7 +7,7 @@ require 'cloud_powers/node'
|
|
7
7
|
require 'cloud_powers/self_awareness'
|
8
8
|
require 'cloud_powers/storage'
|
9
9
|
require 'cloud_powers/version'
|
10
|
-
require 'cloud_powers/
|
10
|
+
require 'cloud_powers/workflow_factory'
|
11
11
|
|
12
12
|
# The Smash module allows us to use CloudPowers under a shared name space with other projects.
|
13
13
|
module Smash
|
@@ -29,5 +29,7 @@ module Smash
|
|
29
29
|
include Smash::CloudPowers::Synapse
|
30
30
|
# CRUD on Nodes, which are individual instances
|
31
31
|
include Smash::CloudPowers::Node
|
32
|
+
# Dynamically Builds and loads a Workflow into a class at runtime
|
33
|
+
include Smash::CloudPowers::WorkflowFactory
|
32
34
|
end
|
33
35
|
end
|
data/lib/stubs/aws_stubs.rb
CHANGED
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: cloud_powers
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.2.7.
|
4
|
+
version: 0.2.7.18
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Adam Phillipps
|
@@ -9,7 +9,7 @@ authors:
|
|
9
9
|
autorequire:
|
10
10
|
bindir: exe
|
11
11
|
cert_chain: []
|
12
|
-
date: 2016-10-
|
12
|
+
date: 2016-10-23 00:00:00.000000000 Z
|
13
13
|
dependencies:
|
14
14
|
- !ruby/object:Gem::Dependency
|
15
15
|
name: activesupport-core-ext
|
@@ -123,20 +123,34 @@ dependencies:
|
|
123
123
|
- - ">="
|
124
124
|
- !ruby/object:Gem::Version
|
125
125
|
version: '0'
|
126
|
+
- !ruby/object:Gem::Dependency
|
127
|
+
name: workflow
|
128
|
+
requirement: !ruby/object:Gem::Requirement
|
129
|
+
requirements:
|
130
|
+
- - ">="
|
131
|
+
- !ruby/object:Gem::Version
|
132
|
+
version: '0'
|
133
|
+
type: :runtime
|
134
|
+
prerelease: false
|
135
|
+
version_requirements: !ruby/object:Gem::Requirement
|
136
|
+
requirements:
|
137
|
+
- - ">="
|
138
|
+
- !ruby/object:Gem::Version
|
139
|
+
version: '0'
|
126
140
|
- !ruby/object:Gem::Dependency
|
127
141
|
name: bundler
|
128
142
|
requirement: !ruby/object:Gem::Requirement
|
129
143
|
requirements:
|
130
144
|
- - "~>"
|
131
145
|
- !ruby/object:Gem::Version
|
132
|
-
version:
|
146
|
+
version: 1.13.5
|
133
147
|
type: :development
|
134
148
|
prerelease: false
|
135
149
|
version_requirements: !ruby/object:Gem::Requirement
|
136
150
|
requirements:
|
137
151
|
- - "~>"
|
138
152
|
- !ruby/object:Gem::Version
|
139
|
-
version:
|
153
|
+
version: 1.13.5
|
140
154
|
- !ruby/object:Gem::Dependency
|
141
155
|
name: byebug
|
142
156
|
requirement: !ruby/object:Gem::Requirement
|
@@ -184,7 +198,7 @@ description: |2
|
|
184
198
|
It was developed specifically for the Brain project but hopefully can be used
|
185
199
|
in any other ruby project that needs to use cloud service providers' resources.
|
186
200
|
|
187
|
-
Version 0.2.8 has a
|
201
|
+
Version 0.2.8 has a some EC2, S3, SQS, SNS, Kinesis, websockets and a few other
|
188
202
|
features you can find in the docs. There is also limitted support for stubbing
|
189
203
|
AWS RESTful API calls. That can come in handy for local testing and extra setup on
|
190
204
|
AWS resource clients.
|
@@ -208,7 +222,6 @@ files:
|
|
208
222
|
- ".test.env.example"
|
209
223
|
- ".travis.yml"
|
210
224
|
- Gemfile
|
211
|
-
- Gemfile.lock
|
212
225
|
- LICENSE.txt
|
213
226
|
- README.md
|
214
227
|
- README.rdoc.mdown
|
@@ -232,9 +245,10 @@ files:
|
|
232
245
|
- lib/cloud_powers/synapse/queue/queue.rb
|
233
246
|
- lib/cloud_powers/synapse/synapse.rb
|
234
247
|
- lib/cloud_powers/synapse/websocket/websocclient.rb
|
248
|
+
- lib/cloud_powers/synapse/websocket/websocket_adam.rb
|
235
249
|
- lib/cloud_powers/synapse/websocket/websocserver.rb
|
236
250
|
- lib/cloud_powers/version.rb
|
237
|
-
- lib/cloud_powers/
|
251
|
+
- lib/cloud_powers/workflow_factory.rb
|
238
252
|
- lib/cloud_powers/zenv.rb
|
239
253
|
- lib/stubs/aws_stubs.rb
|
240
254
|
homepage: https://github.com/adam-phillipps/cloud_powers
|
data/Gemfile.lock
DELETED
@@ -1,71 +0,0 @@
|
|
1
|
-
PATH
|
2
|
-
remote: .
|
3
|
-
specs:
|
4
|
-
cloud_powers (0.2.7.17)
|
5
|
-
activesupport-core-ext (~> 4)
|
6
|
-
aws-sdk (~> 2)
|
7
|
-
dotenv (~> 2.1)
|
8
|
-
httparty (~> 0.14)
|
9
|
-
rubyzip (~> 1.2)
|
10
|
-
websocket-eventmachine-client
|
11
|
-
websocket-eventmachine-server
|
12
|
-
zip-zip (~> 0.3)
|
13
|
-
|
14
|
-
GEM
|
15
|
-
remote: https://rubygems.org/
|
16
|
-
specs:
|
17
|
-
activesupport-core-ext (4.0.0.3)
|
18
|
-
aws-sdk (2.6.9)
|
19
|
-
aws-sdk-resources (= 2.6.9)
|
20
|
-
aws-sdk-core (2.6.9)
|
21
|
-
jmespath (~> 1.0)
|
22
|
-
aws-sdk-resources (2.6.9)
|
23
|
-
aws-sdk-core (= 2.6.9)
|
24
|
-
byebug (9.0.6)
|
25
|
-
diff-lcs (1.2.5)
|
26
|
-
dotenv (2.1.1)
|
27
|
-
eventmachine (1.2.0.1)
|
28
|
-
httparty (0.14.0)
|
29
|
-
multi_xml (>= 0.5.2)
|
30
|
-
jmespath (1.3.1)
|
31
|
-
multi_xml (0.5.5)
|
32
|
-
rake (10.5.0)
|
33
|
-
rspec (3.5.0)
|
34
|
-
rspec-core (~> 3.5.0)
|
35
|
-
rspec-expectations (~> 3.5.0)
|
36
|
-
rspec-mocks (~> 3.5.0)
|
37
|
-
rspec-core (3.5.4)
|
38
|
-
rspec-support (~> 3.5.0)
|
39
|
-
rspec-expectations (3.5.0)
|
40
|
-
diff-lcs (>= 1.2.0, < 2.0)
|
41
|
-
rspec-support (~> 3.5.0)
|
42
|
-
rspec-mocks (3.5.0)
|
43
|
-
diff-lcs (>= 1.2.0, < 2.0)
|
44
|
-
rspec-support (~> 3.5.0)
|
45
|
-
rspec-support (3.5.0)
|
46
|
-
rubyzip (1.2.0)
|
47
|
-
websocket (1.2.3)
|
48
|
-
websocket-eventmachine-base (1.2.0)
|
49
|
-
eventmachine (~> 1.0)
|
50
|
-
websocket (~> 1.0)
|
51
|
-
websocket-native (~> 1.0)
|
52
|
-
websocket-eventmachine-client (1.2.0)
|
53
|
-
websocket-eventmachine-base (~> 1.0)
|
54
|
-
websocket-eventmachine-server (1.0.1)
|
55
|
-
websocket-eventmachine-base (~> 1.0)
|
56
|
-
websocket-native (1.0.0)
|
57
|
-
zip-zip (0.3)
|
58
|
-
rubyzip (>= 1.0.0)
|
59
|
-
|
60
|
-
PLATFORMS
|
61
|
-
ruby
|
62
|
-
|
63
|
-
DEPENDENCIES
|
64
|
-
bundler (~> 1.12)
|
65
|
-
byebug (~> 9)
|
66
|
-
cloud_powers!
|
67
|
-
rake (~> 10.0)
|
68
|
-
rspec (~> 3.0)
|
69
|
-
|
70
|
-
BUNDLED WITH
|
71
|
-
1.13.2
|
@@ -1,34 +0,0 @@
|
|
1
|
-
module Smash
|
2
|
-
module CloudPowers
|
3
|
-
class Workflow
|
4
|
-
attr_accessor :all_states, :first, :last, :previous, :states
|
5
|
-
|
6
|
-
def initialize(statez = nil)
|
7
|
-
# TODO: figure out wtf here with the i-vars changing each other
|
8
|
-
@all_states = statez || [:backlog, :wip, :done]
|
9
|
-
@states = statez || [:backlog, :wip, :done]
|
10
|
-
@first = (statez || [:backlog, :wip, :done]).first
|
11
|
-
@last = (statez || [:backlog, :wip, :done]).last
|
12
|
-
@previous = [(statez || [:backlog, :wip, :done]).first]
|
13
|
-
end
|
14
|
-
|
15
|
-
def current
|
16
|
-
@states.first
|
17
|
-
end
|
18
|
-
|
19
|
-
def finished?
|
20
|
-
@states.first == @states.last
|
21
|
-
end
|
22
|
-
|
23
|
-
def next
|
24
|
-
finished ? @states.first : @states[1]
|
25
|
-
end
|
26
|
-
|
27
|
-
def next!
|
28
|
-
return if finished?
|
29
|
-
@previous << @states.shift
|
30
|
-
@states.first
|
31
|
-
end
|
32
|
-
end
|
33
|
-
end
|
34
|
-
end
|