jflow 0.1.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 ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: e8525329c288e5a0027699c40ad1539367224ec2
4
+ data.tar.gz: 3545904aeda9e29048224b2983e55a805fbaec39
5
+ SHA512:
6
+ metadata.gz: cdae9e071195443da31a403513674b2cf69378d4b59afde71f5f22d113ed99f9aa9a764d067ebc78a54dd5e5bc7828e4d29a2f8c31d94f091bf54c7c28fac57c
7
+ data.tar.gz: 0b9d85ff36b13e3bd6bee7568b8a622927ae5b9d0cb87b41e25b956215835a98c11f686051e4fe6650fa1fbf7c503009eeffee701367724bad2d93e6438c2d98
data/.gitignore ADDED
@@ -0,0 +1,9 @@
1
+ /.bundle/
2
+ /.yardoc
3
+ /Gemfile.lock
4
+ /_yardoc/
5
+ /coverage/
6
+ /doc/
7
+ /pkg/
8
+ /spec/reports/
9
+ /tmp/
data/.rspec ADDED
@@ -0,0 +1,2 @@
1
+ --format documentation
2
+ --color
data/.travis.yml ADDED
@@ -0,0 +1,4 @@
1
+ language: ruby
2
+ rvm:
3
+ - 1.9.3
4
+ before_install: gem install bundler -v 1.10.6
data/Gemfile ADDED
@@ -0,0 +1,4 @@
1
+ source 'https://rubygems.org'
2
+
3
+ # Specify your gem's dependencies in jflow.gemspec
4
+ gemspec
data/README.md ADDED
@@ -0,0 +1,80 @@
1
+ # Jflow
2
+
3
+ JFlow is a gem that aims to let you start SWF flow activity workers for JRuby.
4
+
5
+ The official framework uses Forking and thus not compatible with the JVM. This aims to give an alternative for Jruby.
6
+
7
+ *For now this only works for Activities and not workflows*
8
+
9
+ ## Installation
10
+
11
+ Add this line to your application's Gemfile:
12
+
13
+ ```ruby
14
+ gem 'jflow'
15
+ ```
16
+
17
+ And then execute:
18
+
19
+ $ bundle
20
+
21
+ Or install it yourself as:
22
+
23
+ $ gem install jflow
24
+
25
+ ## Usage
26
+
27
+ ### Create an Activity
28
+
29
+ ```ruby
30
+ Class FooActivity
31
+ include JFlow::ActivityMixin
32
+
33
+ activity "policy_scan.run" do
34
+ {
35
+ domain: "alexandria-development",
36
+ default_task_list: {
37
+ name: "xray_activity_tasklist"
38
+ },
39
+ version: "1.4",
40
+ default_task_schedule_to_start_timeout: "600",
41
+ default_task_schedule_to_close_timeout: "600",
42
+ default_task_start_to_close_timeout: "600",
43
+ default_task_heartbeat_timeout: "600"
44
+ }
45
+ end
46
+
47
+ def run
48
+ "foo"
49
+ end
50
+ end
51
+ ```
52
+
53
+ ### Launch the workers
54
+
55
+ This gem provides you with a binary called jflow_worker. This binary requires a json configuration file.
56
+
57
+ ```bash
58
+ jflow_worker -f worker.json
59
+ ```
60
+
61
+ Example of a worker.json
62
+ ```json
63
+ {
64
+ "domain": "foodomain",
65
+ "tasklist": "footasklist",
66
+ "number_of_workers": 100,
67
+ "activities_path": ["/home/pate/git/foobar/lib/flow/activities"]
68
+ }
69
+ ```
70
+
71
+ ## Development
72
+
73
+ After checking out the repo, run `bin/setup` to install dependencies. Then, run `rake spec` to run the tests. You can also run `bin/console` for an interactive prompt that will allow you to experiment.
74
+
75
+ To install this gem onto your local machine, run `bundle exec rake install`. To release a new version, update the version number in `version.rb`, and then run `bundle exec rake release`, which will create a git tag for the version, push git commits and tags, and push the `.gem` file to [rubygems.org](https://rubygems.org).
76
+
77
+ ## Contributing
78
+
79
+ Bug reports and pull requests are welcome on GitHub at https://github.com/[USERNAME]/jflow.
80
+
data/Rakefile ADDED
@@ -0,0 +1,6 @@
1
+ require "bundler/gem_tasks"
2
+ require "rspec/core/rake_task"
3
+
4
+ RSpec::Core::RakeTask.new(:spec)
5
+
6
+ task :default => :spec
data/bin/console ADDED
@@ -0,0 +1,7 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ require "bundler/setup"
4
+ require "jflow"
5
+
6
+ require "irb"
7
+ IRB.start
data/bin/jflow_worker ADDED
@@ -0,0 +1,42 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ require "bundler/setup"
4
+ require "jflow"
5
+ require "slop"
6
+
7
+ opts = Slop.parse do |o|
8
+ o.string '-f', '--file', 'worker configuration file'
9
+ end
10
+
11
+ configuration = JSON.parse(File.read(opts[:file]))
12
+
13
+ configuration_validator = {
14
+ "number_of_workers" => "integer",
15
+ "domain" => "string",
16
+ "tasklist" => "string",
17
+ "activities_path" => "array"
18
+ }
19
+
20
+ validator = HashValidator.validate(configuration, configuration_validator)
21
+ raise "configuration is invalid! #{validator.errors}" unless validator.valid?
22
+
23
+ JFlow.configure do |c|
24
+ c.load_paths = configuration["activities_path"]
25
+ end
26
+
27
+ JFlow.load_activities
28
+
29
+ threads = []
30
+
31
+ configuration["number_of_workers"].times do |i|
32
+ threads << Thread.new do
33
+ domain = configuration["domain"]
34
+ tasklist = configuration["tasklist"]
35
+ JFlow::ActivityWorker.new(domain, tasklist)
36
+ .start!
37
+ end
38
+ end
39
+
40
+ threads.each { |thr| thr.join }
41
+
42
+
data/bin/setup ADDED
@@ -0,0 +1,8 @@
1
+ #!/usr/bin/env bash
2
+ set -euo pipefail
3
+ IFS=$'\n\t'
4
+ set -vx
5
+
6
+ bundle install
7
+
8
+ # Do any other automated setup that you need to do here
data/jflow.gemspec ADDED
@@ -0,0 +1,36 @@
1
+ # coding: utf-8
2
+ lib = File.expand_path('../lib', __FILE__)
3
+ $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
4
+ require 'jflow/version'
5
+
6
+ Gem::Specification.new do |spec|
7
+ spec.name = "jflow"
8
+ spec.version = JFlow::VERSION
9
+ spec.authors = ["Christophe Verbinnen"]
10
+ spec.email = ["christophe.verbinnen@lookout.com"]
11
+
12
+ spec.summary = %q{SWF Flow framework for jRuby}
13
+ spec.description = %q{you know, for flow}
14
+ spec.homepage = "https://github.com/djpate/jflow"
15
+
16
+ # Prevent pushing this gem to RubyGems.org by setting 'allowed_push_host', or
17
+ # delete this section to allow pushing this gem to any host.
18
+ if spec.respond_to?(:metadata)
19
+ spec.metadata['allowed_push_host'] = "https://rubygems.org"
20
+ else
21
+ raise "RubyGems 2.0 or newer is required to protect against public gem pushes."
22
+ end
23
+
24
+ spec.files = `git ls-files -z`.split("\x0").reject { |f| f.match(%r{^(test|spec|features)/}) }
25
+ spec.bindir = "bin"
26
+ spec.executables = spec.files.grep(%r{^bin/}) { |f| File.basename(f) }
27
+ spec.require_paths = ["lib"]
28
+
29
+ spec.add_development_dependency "bundler", "~> 1.10"
30
+ spec.add_development_dependency "rake", "~> 10.0"
31
+ spec.add_development_dependency "rspec"
32
+
33
+ spec.add_dependency "aws-sdk", "~> 2"
34
+ spec.add_dependency "hash_validator"
35
+ spec.add_dependency "slop", "~> 4"
36
+ end
data/lib/jflow.rb ADDED
@@ -0,0 +1,36 @@
1
+ require "jflow/version"
2
+ require "jflow/activity.rb"
3
+ require "jflow/activity_mixin.rb"
4
+ require "jflow/activity_worker.rb"
5
+ require "jflow/configuration.rb"
6
+ require "yaml"
7
+ require "json"
8
+ require "hash_validator"
9
+ require 'aws-sdk'
10
+
11
+ module JFlow
12
+ class << self
13
+ attr_writer :configuration
14
+ end
15
+
16
+ def self.configuration
17
+ @configuration ||= Configuration.new
18
+ end
19
+
20
+ def self.reset
21
+ @configuration = Configuration.new
22
+ end
23
+
24
+ def self.configure
25
+ yield(configuration)
26
+ end
27
+
28
+ def self.load_activities
29
+ configuration.load_paths.each do |path|
30
+ Dir["#{path}/*.rb"].each do |file|
31
+ configuration.logger.debug "found #{file}"
32
+ require file
33
+ end
34
+ end
35
+ end
36
+ end
@@ -0,0 +1,81 @@
1
+ module JFlow
2
+ class Activity
3
+
4
+ DEFAULT_OPTIONS = {}
5
+
6
+ OPTIONS_VALIDATOR = {
7
+ :version => "string",
8
+ :domain => "string",
9
+ :name => "string",
10
+ :default_task_list => {
11
+ :name => "string"
12
+ }
13
+ }
14
+
15
+ attr_reader :options, :klass
16
+
17
+ # Possible options are :
18
+ # domain: "DomainName", # required
19
+ # name: "Name", # required
20
+ # version: "Version", # required
21
+ # description: "Description",
22
+ # default_task_start_to_close_timeout: "DurationInSecondsOptional",
23
+ # default_task_heartbeat_timeout: "DurationInSecondsOptional",
24
+ # default_task_list: {
25
+ # name: "Name", # required
26
+ # },
27
+ # default_task_priority: "TaskPriority",
28
+ # default_task_schedule_to_start_timeout: "DurationInSecondsOptional",
29
+ # default_task_schedule_to_close_timeout: "DurationInSecondsOptional",
30
+ def initialize(klass, options = {})
31
+ @klass = klass
32
+ @options = DEFAULT_OPTIONS.merge(options)
33
+ @options[:name] = name
34
+ validate_activity!
35
+ register_activity unless registered?
36
+ add_to_activity_mapping
37
+ end
38
+
39
+ def register_activity
40
+ JFlow.configuration.swf_client.register_activity_type(options)
41
+ JFlow.configuration.logger.info "Activity #{name} was registered successfuly"
42
+ end
43
+
44
+ def add_to_activity_mapping
45
+ $activity_map ||= {}
46
+ $activity_map[name] ||= {}
47
+ $activity_map[name][options[:version]] = {:class => klass, :options => options}
48
+ end
49
+
50
+ def name
51
+ @options[:name] || klass.name.to_s.split('::').last.scan(/[A-Z][a-z]*/).join("_").downcase
52
+ end
53
+
54
+ def version
55
+ @options[:version]
56
+ end
57
+
58
+ def validate_activity!
59
+ validator = HashValidator.validate(@options, OPTIONS_VALIDATOR)
60
+ raise "Activity #{options[:name]}definition is invalid! #{validator.errors}" unless validator.valid?
61
+ end
62
+
63
+ def registered?
64
+ response = JFlow.configuration.swf_client.list_activity_types({
65
+ domain: options[:domain],
66
+ name: name,
67
+ registration_status: "REGISTERED"
68
+ })
69
+
70
+ response.type_infos.each do |type_info|
71
+ if type_info.activity_type.name == name && type_info.activity_type.version == version
72
+ JFlow.configuration.logger.info "Activity #{name} #{version} is already registered"
73
+ return true
74
+ end
75
+ end
76
+
77
+ return false
78
+ end
79
+
80
+ end
81
+ end
@@ -0,0 +1,18 @@
1
+ module JFlow
2
+ module ActivityMixin
3
+
4
+ def self.included base
5
+ base.extend ClassMethods
6
+ end
7
+
8
+ module ClassMethods
9
+ def activity(name = nil)
10
+ options = {}
11
+ options = yield if block_given?
12
+ options[:name] = name
13
+ JFlow.configuration.logger.debug "loading #{name}"
14
+ JFlow::Activity.new(self, options)
15
+ end
16
+ end
17
+ end
18
+ end
@@ -0,0 +1,81 @@
1
+ module JFlow
2
+ class ActivityWorker
3
+
4
+ attr_reader :domain, :tasklist
5
+
6
+ def initialize(domain, tasklist)
7
+ @domain = domain
8
+ @tasklist = tasklist
9
+ end
10
+
11
+ def start!
12
+ loop do
13
+ log "Polling for task on #{domain} - #{tasklist}"
14
+ poll
15
+ end
16
+ end
17
+
18
+ private
19
+
20
+ def poll
21
+ response = JFlow.configuration.swf_client.poll_for_activity_task(poll_params)
22
+ if response.task_token
23
+ process_task(response)
24
+ else
25
+ log "Got no task"
26
+ end
27
+ end
28
+
29
+ def process_task(response)
30
+ log "Got task #{response.task_token}"
31
+
32
+ klass = class_for_activity(response.activity_type)
33
+ raise "Could not find code to run for given activity" unless klass
34
+
35
+ begin
36
+ JFlow.configuration.logger.debug "Started #{klass}#process with #{YAML.load(response.input)}"
37
+ if response.activity_type.name.split('.').size > 1
38
+ method = response.activity_type.name.split('.').last
39
+ else
40
+ method = "process"
41
+ end
42
+ result = klass.new.send(method, YAML.load(response.input)) || true
43
+ JFlow.configuration.logger.debug "Done #{klass}##{method}"
44
+ JFlow.configuration.swf_client.respond_activity_task_completed({
45
+ task_token: response.task_token,
46
+ result: result,
47
+ })
48
+ rescue => e
49
+ JFlow.configuration.swf_client.respond_activity_task_failed({
50
+ task_token: response.task_token,
51
+ reason: e.message,
52
+ details: e.backtrace.join("\n"),
53
+ })
54
+ end
55
+
56
+ end
57
+
58
+ def identity
59
+ @identity ||= "#{`hostname`.chomp}-#{Thread.current.object_id}"
60
+ end
61
+
62
+ def log(str)
63
+ JFlow.configuration.logger.info "[#{Thread.current.object_id}] #{str}"
64
+ end
65
+
66
+ def poll_params
67
+ {
68
+ domain: domain,
69
+ task_list: {
70
+ name: tasklist,
71
+ },
72
+ identity: identity,
73
+ }
74
+ end
75
+
76
+ def class_for_activity(activity_type)
77
+ $activity_map[activity_type.name][activity_type.version][:class]
78
+ end
79
+
80
+ end
81
+ end
@@ -0,0 +1,12 @@
1
+ module JFlow
2
+ class Configuration
3
+
4
+ attr_accessor :swf_client, :load_paths, :logger
5
+
6
+ def initialize
7
+ @swf_client = Aws::SWF::Client.new
8
+ @load_paths = []
9
+ @logger = Logger.new(STDOUT)
10
+ end
11
+ end
12
+ end
@@ -0,0 +1,3 @@
1
+ module JFlow
2
+ VERSION = "0.1.0"
3
+ end
metadata ADDED
@@ -0,0 +1,147 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: jflow
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.1.0
5
+ platform: ruby
6
+ authors:
7
+ - Christophe Verbinnen
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2016-03-10 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: bundler
15
+ version_requirements: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - ~>
18
+ - !ruby/object:Gem::Version
19
+ version: '1.10'
20
+ requirement: !ruby/object:Gem::Requirement
21
+ requirements:
22
+ - - ~>
23
+ - !ruby/object:Gem::Version
24
+ version: '1.10'
25
+ prerelease: false
26
+ type: :development
27
+ - !ruby/object:Gem::Dependency
28
+ name: rake
29
+ version_requirements: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - ~>
32
+ - !ruby/object:Gem::Version
33
+ version: '10.0'
34
+ requirement: !ruby/object:Gem::Requirement
35
+ requirements:
36
+ - - ~>
37
+ - !ruby/object:Gem::Version
38
+ version: '10.0'
39
+ prerelease: false
40
+ type: :development
41
+ - !ruby/object:Gem::Dependency
42
+ name: rspec
43
+ version_requirements: !ruby/object:Gem::Requirement
44
+ requirements:
45
+ - - '>='
46
+ - !ruby/object:Gem::Version
47
+ version: '0'
48
+ requirement: !ruby/object:Gem::Requirement
49
+ requirements:
50
+ - - '>='
51
+ - !ruby/object:Gem::Version
52
+ version: '0'
53
+ prerelease: false
54
+ type: :development
55
+ - !ruby/object:Gem::Dependency
56
+ name: aws-sdk
57
+ version_requirements: !ruby/object:Gem::Requirement
58
+ requirements:
59
+ - - ~>
60
+ - !ruby/object:Gem::Version
61
+ version: '2'
62
+ requirement: !ruby/object:Gem::Requirement
63
+ requirements:
64
+ - - ~>
65
+ - !ruby/object:Gem::Version
66
+ version: '2'
67
+ prerelease: false
68
+ type: :runtime
69
+ - !ruby/object:Gem::Dependency
70
+ name: hash_validator
71
+ version_requirements: !ruby/object:Gem::Requirement
72
+ requirements:
73
+ - - '>='
74
+ - !ruby/object:Gem::Version
75
+ version: '0'
76
+ requirement: !ruby/object:Gem::Requirement
77
+ requirements:
78
+ - - '>='
79
+ - !ruby/object:Gem::Version
80
+ version: '0'
81
+ prerelease: false
82
+ type: :runtime
83
+ - !ruby/object:Gem::Dependency
84
+ name: slop
85
+ version_requirements: !ruby/object:Gem::Requirement
86
+ requirements:
87
+ - - ~>
88
+ - !ruby/object:Gem::Version
89
+ version: '4'
90
+ requirement: !ruby/object:Gem::Requirement
91
+ requirements:
92
+ - - ~>
93
+ - !ruby/object:Gem::Version
94
+ version: '4'
95
+ prerelease: false
96
+ type: :runtime
97
+ description: you know, for flow
98
+ email:
99
+ - christophe.verbinnen@lookout.com
100
+ executables:
101
+ - console
102
+ - jflow_worker
103
+ - setup
104
+ extensions: []
105
+ extra_rdoc_files: []
106
+ files:
107
+ - .gitignore
108
+ - .rspec
109
+ - .travis.yml
110
+ - Gemfile
111
+ - README.md
112
+ - Rakefile
113
+ - bin/console
114
+ - bin/jflow_worker
115
+ - bin/setup
116
+ - jflow.gemspec
117
+ - lib/jflow.rb
118
+ - lib/jflow/activity.rb
119
+ - lib/jflow/activity_mixin.rb
120
+ - lib/jflow/activity_worker.rb
121
+ - lib/jflow/configuration.rb
122
+ - lib/jflow/version.rb
123
+ homepage: https://github.com/djpate/jflow
124
+ licenses: []
125
+ metadata:
126
+ allowed_push_host: https://rubygems.org
127
+ post_install_message:
128
+ rdoc_options: []
129
+ require_paths:
130
+ - lib
131
+ required_ruby_version: !ruby/object:Gem::Requirement
132
+ requirements:
133
+ - - '>='
134
+ - !ruby/object:Gem::Version
135
+ version: '0'
136
+ required_rubygems_version: !ruby/object:Gem::Requirement
137
+ requirements:
138
+ - - '>='
139
+ - !ruby/object:Gem::Version
140
+ version: '0'
141
+ requirements: []
142
+ rubyforge_project:
143
+ rubygems_version: 2.4.5
144
+ signing_key:
145
+ specification_version: 4
146
+ summary: SWF Flow framework for jRuby
147
+ test_files: []