mio-config 1.3.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.
Files changed (81) hide show
  1. checksums.yaml +7 -0
  2. data/#mio-config.gemspec# +23 -0
  3. data/Gemfile +16 -0
  4. data/Gemfile.lock +68 -0
  5. data/LICENCE.md +8 -0
  6. data/README.md +162 -0
  7. data/Rakefile +7 -0
  8. data/circle.yml +3 -0
  9. data/config/mio.yml +4 -0
  10. data/coverage/assets/0.10.0/application.css +799 -0
  11. data/coverage/assets/0.10.0/application.js +1707 -0
  12. data/coverage/assets/0.10.0/colorbox/border.png +0 -0
  13. data/coverage/assets/0.10.0/colorbox/controls.png +0 -0
  14. data/coverage/assets/0.10.0/colorbox/loading.gif +0 -0
  15. data/coverage/assets/0.10.0/colorbox/loading_background.png +0 -0
  16. data/coverage/assets/0.10.0/favicon_green.png +0 -0
  17. data/coverage/assets/0.10.0/favicon_red.png +0 -0
  18. data/coverage/assets/0.10.0/favicon_yellow.png +0 -0
  19. data/coverage/assets/0.10.0/loading.gif +0 -0
  20. data/coverage/assets/0.10.0/magnify.png +0 -0
  21. data/coverage/assets/0.10.0/smoothness/images/ui-bg_flat_0_aaaaaa_40x100.png +0 -0
  22. data/coverage/assets/0.10.0/smoothness/images/ui-bg_flat_75_ffffff_40x100.png +0 -0
  23. data/coverage/assets/0.10.0/smoothness/images/ui-bg_glass_55_fbf9ee_1x400.png +0 -0
  24. data/coverage/assets/0.10.0/smoothness/images/ui-bg_glass_65_ffffff_1x400.png +0 -0
  25. data/coverage/assets/0.10.0/smoothness/images/ui-bg_glass_75_dadada_1x400.png +0 -0
  26. data/coverage/assets/0.10.0/smoothness/images/ui-bg_glass_75_e6e6e6_1x400.png +0 -0
  27. data/coverage/assets/0.10.0/smoothness/images/ui-bg_glass_95_fef1ec_1x400.png +0 -0
  28. data/coverage/assets/0.10.0/smoothness/images/ui-bg_highlight-soft_75_cccccc_1x100.png +0 -0
  29. data/coverage/assets/0.10.0/smoothness/images/ui-icons_222222_256x240.png +0 -0
  30. data/coverage/assets/0.10.0/smoothness/images/ui-icons_2e83ff_256x240.png +0 -0
  31. data/coverage/assets/0.10.0/smoothness/images/ui-icons_454545_256x240.png +0 -0
  32. data/coverage/assets/0.10.0/smoothness/images/ui-icons_888888_256x240.png +0 -0
  33. data/coverage/assets/0.10.0/smoothness/images/ui-icons_cd0a0a_256x240.png +0 -0
  34. data/coverage/index.html +4884 -0
  35. data/lib/mio.rb +24 -0
  36. data/lib/mio/#model.rb# +130 -0
  37. data/lib/mio/client.rb +106 -0
  38. data/lib/mio/config.rb +14 -0
  39. data/lib/mio/errors.rb +18 -0
  40. data/lib/mio/migrations.rb +96 -0
  41. data/lib/mio/model.rb +133 -0
  42. data/lib/mio/model/autoload.rb +7 -0
  43. data/lib/mio/model/groovy_script.rb +40 -0
  44. data/lib/mio/model/groovy_script_wait.rb +44 -0
  45. data/lib/mio/model/hotfolder.rb +56 -0
  46. data/lib/mio/model/import_action.rb +69 -0
  47. data/lib/mio/model/s3.rb +37 -0
  48. data/lib/mio/model/workflow.rb +98 -0
  49. data/lib/mio/model/workflow/node.rb +35 -0
  50. data/lib/mio/model/workflow/transition.rb +20 -0
  51. data/lib/mio/requests.rb +16 -0
  52. data/lib/mio/search.rb +29 -0
  53. data/lib/mio/tasks.rb +5 -0
  54. data/lib/mio/tasks/migrations.rb +17 -0
  55. data/lib/mio/tasks/skeletons.rb +38 -0
  56. data/migrations/20160429130853_create-an-s3-bucket-for-ingestion.rb +11 -0
  57. data/mio-config.gemspec +24 -0
  58. data/notes +1 -0
  59. data/spec/factories/client_factories.rb +41 -0
  60. data/spec/factories/mio_factories.rb +9 -0
  61. data/spec/factories/model_factories.rb +128 -0
  62. data/spec/fixtures/vcr_cassettes/client.yml +2415 -0
  63. data/spec/fixtures/vcr_cassettes/client.yml~ +2141 -0
  64. data/spec/lib/mio/client_spec.rb +79 -0
  65. data/spec/lib/mio/config_spec.rb +11 -0
  66. data/spec/lib/mio/model/groovy_script_spec.rb +13 -0
  67. data/spec/lib/mio/model/groovy_script_wait_spec.rb +13 -0
  68. data/spec/lib/mio/model/hotfolder_spec.rb +13 -0
  69. data/spec/lib/mio/model/import_action_spec.rb +13 -0
  70. data/spec/lib/mio/model/s3_spec.rb +13 -0
  71. data/spec/lib/mio/model/workflow/node_spec.rb +35 -0
  72. data/spec/lib/mio/model/workflow/transition_spec.rb +12 -0
  73. data/spec/lib/mio/model/workflow_spec.rb +38 -0
  74. data/spec/lib/mio/search_spec.rb +37 -0
  75. data/spec/lib/mio_spec.rb +30 -0
  76. data/spec/spec_helper.rb +16 -0
  77. data/spec/support/factory_girl.rb +3 -0
  78. data/spec/support/shared_examples_for_client.rb +27 -0
  79. data/spec/support/shared_examples_for_model.rb +87 -0
  80. data/spec/support/vcr.rb +12 -0
  81. metadata +195 -0
data/lib/mio.rb ADDED
@@ -0,0 +1,24 @@
1
+ require 'mio/client'
2
+ require 'mio/search'
3
+ require 'mio/errors'
4
+
5
+ require 'mio/model'
6
+ require 'mio/model/autoload'
7
+
8
+ class Mio
9
+
10
+ attr_accessor :base_uri, :username, :password
11
+ attr_reader :client
12
+ def initialize base_uri=nil, username=nil, password=nil
13
+ @base_uri = base_uri
14
+ @username = username
15
+ @password = password
16
+
17
+ if block_given?
18
+ yield self
19
+ end
20
+
21
+ @client = Mio::Client.new @base_uri, @username, @password
22
+ end
23
+
24
+ end
@@ -0,0 +1,130 @@
1
+ class Mio
2
+ class Model
3
+ class << self
4
+ attr_accessor :fields, :resource_name
5
+ def set_resource r
6
+ @resource_name = r.to_s
7
+ end
8
+
9
+ def field key, type, desc, default=nil, matcher=nil
10
+ @fields ||= []
11
+ @fields << {name: key,
12
+ type: type,
13
+ default: default,
14
+ matcher: matcher,
15
+ desc: desc,}
16
+
17
+ end
18
+
19
+ def nested val=nil
20
+ if val.nil?
21
+ @nested_value || false
22
+ else
23
+ @nested_value = val
24
+ end
25
+ end
26
+ alias_method :nested?, :nested
27
+
28
+ def mappings
29
+ m = {}
30
+ ObjectSpace.each_object(Class).each do |k|
31
+ if k < Mio::Model
32
+ m[ k.to_s.split('::').last.downcase ] = k
33
+ end
34
+ end
35
+ m
36
+ end
37
+ end
38
+
39
+ def initialize client, args
40
+ @client = client
41
+ @args = args
42
+ @search = Mio::Search.new @client
43
+ end
44
+
45
+ def go
46
+ unless look_up
47
+ @object = create
48
+ else
49
+ @object = look_up
50
+
51
+ # We can't edit a running resource
52
+ set_start :stop
53
+ end
54
+
55
+ configure if self.respond_to? :config_hash
56
+ set_enable
57
+ set_start
58
+
59
+ return @object
60
+ end
61
+
62
+ def create
63
+ @client.create self.class.resource_name, create_hash
64
+ end
65
+
66
+ def configure
67
+ @client.configure self.class.resource_name,
68
+ @object['id'],
69
+ config_hash
70
+ end
71
+
72
+ def set_enable a=nil
73
+ if a.nil?
74
+ action = @args.enable == :true ? 'enable' : 'disable'
75
+ else
76
+ action = a.to_s
77
+ end
78
+ @client.action self.class.resource_name,
79
+ @object['id'],
80
+ {action: action}
81
+ end
82
+ alias_method :disable!, :set_enable
83
+ alias_method :enable!, :set_enable
84
+
85
+ def set_start a=nil
86
+ if a.nil?
87
+ action = @args.start == :true ? 'start' : 'stop'
88
+ else
89
+ action = a.to_s
90
+ end
91
+ @client.action self.class.resource_name,
92
+ @object['id'],
93
+ {action: action}
94
+ end
95
+ alias_method :stop!, :set_start
96
+ alias_method :start!, :set_start
97
+
98
+ def validate
99
+ testable = @args.dup.to_h
100
+
101
+ self.class.fields.each do |f|
102
+ unless testable.key? f[:name]
103
+ raise Mio::Model::MissingField, "Missing field #{f[:name]} to #{self}"
104
+ end
105
+
106
+ extracted_field = testable.delete f[:name]
107
+ unless extracted_field.is_a? f[:type]
108
+ raise Mio::Model::DataTypeError, "#{f[:name]} should be of type #{f[:type]} for #{self}"
109
+ end
110
+
111
+ unless f['matcher'].nil? or extracted_field.to_s.match(f[:matcher])
112
+ raise Mio::Model::DataValueError, "#{self} #{f[:name]} value '#{extracted_field}' does not match #{f[:matcher]}"
113
+ end
114
+ end
115
+
116
+ testable.keys.each do |k|
117
+ raise Mio::Model::NoSuchField, "#{k} for #{self}"
118
+ end
119
+ true
120
+ end
121
+ alias_method :valid?, :validate
122
+
123
+ private
124
+ def look_up
125
+ r = self.class.resource_name
126
+ @client.find_all(r)[r].find{|o| o['name'] == @args.name}
127
+ end
128
+ end
129
+
130
+ end
data/lib/mio/client.rb ADDED
@@ -0,0 +1,106 @@
1
+ require 'faraday'
2
+ require 'faraday/detailed_logger'
3
+ require 'hashie/mash'
4
+ require 'net/http/persistent'
5
+ require 'json'
6
+
7
+ require 'pp'
8
+
9
+ require 'mio/requests'
10
+
11
+ class Mio
12
+ class Client
13
+
14
+ def initialize base_uri, username, password
15
+ @base_uri = base_uri
16
+ @agent = Faraday.new(url: base_uri) do |f|
17
+ f.adapter :net_http_persistent
18
+ f.response :detailed_logger if ENV.fetch('VERBOSE', 'false').to_s.downcase == 'true'
19
+ end
20
+ @agent.basic_auth(username, password)
21
+ end
22
+
23
+ def find_all resource, opts={}
24
+ url = path(resource)
25
+ response = get url, opts
26
+
27
+ unless response.success?
28
+ raise Mio::Client::LoadOfBollocks, "GET on #{url} returned #{response.status}"
29
+ end
30
+ make_object response.body
31
+ end
32
+
33
+ def create resource, payload, opts={}
34
+ url = path(resource)
35
+ response = post url, payload, opts
36
+ unless response.success?
37
+ raise Mio::Client::LoadOfBollocks, "POST on #{url}, with #{payload.inspect} returned #{response.status}"
38
+ end
39
+
40
+ make_object response.body
41
+ end
42
+
43
+ def update resource, payload, opts={}
44
+ url = path(resource)
45
+ response = put url, payload, opts
46
+ unless response.success?
47
+ raise Mio::Client::LoadOfBollocks, "PUT on #{url}, with #{payload.inspect} returned #{response.status}"
48
+ end
49
+
50
+ make_object response.body
51
+ end
52
+
53
+
54
+ def configure resource, id, payload, opts={}
55
+ url = path(resource, id, :configuration)
56
+ response = put url, payload, opts
57
+ unless response.success?
58
+ raise Mio::Client::LoadOfBollocks, "PUT on #{url}, with #{payload.inspect} returned #{response.status}"
59
+ end
60
+
61
+ make_object response.body
62
+ end
63
+
64
+ def action resource, id, payload, opts={}
65
+ url = path(resource, id, :actions)
66
+ statuses = get url, opts
67
+ unless statuses.success?
68
+ raise Mio::Client::LoadOfBollocks, "GET on #{url} returned #{statuses.status}"
69
+ end
70
+
71
+ if JSON.parse(statuses.body).find{|h| h['action'] == payload[:action]}
72
+ response = post url, payload, opts
73
+
74
+ unless response.success?
75
+ raise Mio::Client::LoadOfBollocks, "PUT on #{url}, with #{payload.inspect} returned #{response.status}"
76
+ end
77
+ return make_object response.body
78
+ end
79
+ end
80
+
81
+ private
82
+ def get url, opts
83
+ Mio::Requests.make_request :get, @agent, url, opts
84
+ end
85
+
86
+ def post url, payload, opts
87
+ Mio::Requests.make_request :post, @agent, url, opts, payload
88
+ end
89
+
90
+ def put url, payload, opts
91
+ Mio::Requests.make_request :put, @agent, url, opts, payload
92
+ end
93
+
94
+ def make_object response
95
+ JSON.parse(response)
96
+ end
97
+
98
+ def path resource, id=nil, endpoint=nil
99
+ path_string = "#{@base_uri}/#{resource.sub(/^\//, '')}"
100
+ path_string += "/#{id}" if id
101
+ path_string += "/#{endpoint.to_s}" if endpoint
102
+ path_string
103
+ end
104
+
105
+ end
106
+ end
data/lib/mio/config.rb ADDED
@@ -0,0 +1,14 @@
1
+ require 'hashie/mash'
2
+ require 'yaml'
3
+ require 'erb'
4
+
5
+ class Mio
6
+ class Config
7
+ def self.read filename
8
+ unless File.exist? filename
9
+ raise Mio::Config::FileMissing, "The config file '#{filename}' is missing"
10
+ end
11
+ OpenStruct.new YAML.load( ERB.new(File.read(filename)).result )
12
+ end
13
+ end
14
+ end
data/lib/mio/errors.rb ADDED
@@ -0,0 +1,18 @@
1
+ class Mio
2
+ class Client
3
+ class LoadOfBollocks < ArgumentError ; end
4
+ end
5
+
6
+ class Model
7
+ class NoSuchField < ArgumentError ; end
8
+ class MissingField < ArgumentError ; end
9
+ class DataTypeError < ArgumentError ; end
10
+ class DataValueError < ArgumentError ; end
11
+ class NoSuchResource < ArgumentError ; end
12
+ class EmptyField < ArgumentError ; end
13
+ end
14
+
15
+ class Config
16
+ class FileMissing < IOError ; end
17
+ end
18
+ end
@@ -0,0 +1,96 @@
1
+ require 'mio'
2
+ require 'colorize'
3
+ require 'mio/config'
4
+
5
+ class Mio
6
+ class Migrations
7
+ def initialize base_uri, username, password, base_dir='./migrations'
8
+ @mio = Mio.new do |m|
9
+ m.base_uri = base_uri
10
+ m.username = username
11
+ m.password = password
12
+ end
13
+ @base = File.expand_path(base_dir)
14
+ @migrations = Dir.glob( File.join(@base, '*.rb') ).sort
15
+ end
16
+
17
+ def create_migration_file desc
18
+ File.join(@base,
19
+ "#{Time.now.strftime('%Y%m%d%H%M%S')}_#{desc.gsub(/\W/, '-')}.rb")
20
+ end
21
+
22
+ def run_migrations
23
+ @migrations.each do |migration|
24
+ unless has_run? migration
25
+ load_migration migration
26
+ end
27
+ end
28
+ end
29
+
30
+ def has_run? migration
31
+ false
32
+ end
33
+
34
+ def load_migration migration
35
+ eval File.read(migration)
36
+ end
37
+
38
+ # Helper methods for within the migrations
39
+ def migrate desc, &block
40
+ msg desc, 'starting'
41
+ block.call
42
+
43
+ msg desc, 'completed'
44
+ end
45
+
46
+ def type_migration klass, conf
47
+ if klass.nested?
48
+ get_it klass.new(@mio.client, conf)
49
+ else
50
+ do_it klass.new(@mio.client, conf)
51
+ end
52
+ end
53
+
54
+ def method_missing method_sym, *arguments, &block
55
+ mapped = Mio::Model.mappings[method_sym.to_s]
56
+
57
+ if mapped.nil?
58
+ super
59
+ else
60
+ conf = OpenStruct.new
61
+ yield conf
62
+ type_migration mapped, conf
63
+ end
64
+ end
65
+
66
+ def respond_to? method_sym, include_private=false
67
+ if Mio::Model.mappings[method_sym.to_s].nil?
68
+ super
69
+ else
70
+ true
71
+ end
72
+ end
73
+
74
+ private
75
+ def do_it thing
76
+ if thing.valid?
77
+ obj = thing.go
78
+ end
79
+ puts "Created '#{obj['name']}' with id '#{obj['id']}'"
80
+ end
81
+
82
+ def get_it thing
83
+ if thing.valid?
84
+ return thing.create_hash
85
+ end
86
+ return nil
87
+ end
88
+
89
+
90
+ def msg desc, state
91
+ print '======> '.magenta
92
+ print "#{desc}:\t".cyan
93
+ puts "#{state.upcase}".magenta
94
+ end
95
+ end
96
+ end
data/lib/mio/model.rb ADDED
@@ -0,0 +1,133 @@
1
+ class Mio
2
+ class Model
3
+ class << self
4
+ attr_accessor :fields, :resource_name
5
+ def set_resource r
6
+ @resource_name = r.to_s
7
+ end
8
+
9
+ def field key, type, desc, default=nil, matcher=nil
10
+ @fields ||= []
11
+ @fields << {name: key,
12
+ type: type,
13
+ default: default,
14
+ matcher: matcher,
15
+ desc: desc,}
16
+
17
+ end
18
+
19
+ def nested val=nil
20
+ if val.nil?
21
+ @nested_value || false
22
+ else
23
+ @nested_value = val
24
+ end
25
+ end
26
+ alias_method :nested?, :nested
27
+
28
+ def mappings
29
+ m = {}
30
+ ObjectSpace.each_object(Class).each do |k|
31
+ if k < Mio::Model
32
+ m[ k.to_s.split('::').last.downcase ] = k
33
+ end
34
+ end
35
+ m
36
+ end
37
+ end
38
+
39
+ def initialize client, args
40
+ @client = client
41
+ @args = args
42
+ @search = Mio::Search.new @client
43
+ end
44
+
45
+ def go
46
+ unless look_up
47
+ @object = create
48
+ else
49
+ @object = look_up
50
+
51
+ # We can't edit a running resource
52
+ set_start :stop
53
+ end
54
+
55
+ configure if self.respond_to? :config_hash
56
+ set_enable
57
+ set_start
58
+
59
+ return @object
60
+ end
61
+
62
+ def create
63
+ @client.create self.class.resource_name, create_hash
64
+ end
65
+
66
+ def configure
67
+ @client.configure self.class.resource_name,
68
+ @object['id'],
69
+ config_hash
70
+ end
71
+
72
+ def set_enable a=nil
73
+ if a.nil?
74
+ action = @args.enable == :true ? 'enable' : 'disable'
75
+ else
76
+ action = a.to_s
77
+ end
78
+ @client.action self.class.resource_name,
79
+ @object['id'],
80
+ {action: action}
81
+ end
82
+ alias_method :disable!, :set_enable
83
+ alias_method :enable!, :set_enable
84
+
85
+ def set_start a=nil
86
+ if a.nil?
87
+ action = @args.start == :true ? 'start' : 'stop'
88
+ else
89
+ action = a.to_s
90
+ end
91
+ @client.action self.class.resource_name,
92
+ @object['id'],
93
+ {action: action}
94
+ end
95
+ alias_method :stop!, :set_start
96
+ alias_method :start!, :set_start
97
+
98
+ def validate
99
+ testable = @args.dup.to_h
100
+
101
+ self.class.fields.each do |f|
102
+ unless testable.key? f[:name]
103
+ raise Mio::Model::MissingField, "Missing field #{f[:name]} to #{self}"
104
+ end
105
+
106
+ extracted_field = testable.delete f[:name]
107
+ unless extracted_field.is_a? f[:type]
108
+ raise Mio::Model::DataTypeError, "#{f[:name]} should be of type #{f[:type]} for #{self}"
109
+ end
110
+
111
+ unless f['matcher'].nil? or extracted_field.to_s.match(f[:matcher])
112
+ raise Mio::Model::DataValueError, "#{self} #{f[:name]} value '#{extracted_field}' does not match #{f[:matcher]}"
113
+ end
114
+ end
115
+
116
+ testable.keys.each do |k|
117
+ raise Mio::Model::NoSuchField, "#{k} for #{self}"
118
+ end
119
+ true
120
+ end
121
+ alias_method :valid?, :validate
122
+
123
+ private
124
+ def look_up
125
+ r = self.class.resource_name
126
+ all_resources = @client.find_all(r)
127
+ return nil if all_resources['totalCount'] == 0
128
+
129
+ all_resources[r].find{|o| o['name'] == @args.name}
130
+ end
131
+ end
132
+
133
+ end