bodhi-slam 0.0.1

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 (3) hide show
  1. checksums.yaml +7 -0
  2. data/lib/bodhi-slam.rb +243 -0
  3. metadata +86 -0
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: a5847a2624bbebdcca10694961184c705fe2a291
4
+ data.tar.gz: 2cc55276b1d0d2f56334ed704e638655c8c10715
5
+ SHA512:
6
+ metadata.gz: 9a42e6cb3c52fec9c87d124bd7f45c81ec3111a58ed2d64579167cb471db55681f3501d4276590f83c639f08c203505052a2447093f73c9814979bdcf7a59575
7
+ data.tar.gz: 1374f972b39667ccf2d56b21c346cd5c7cbed9dfa073828d822d6501febd1ccf09ee2a8ec6277acca86d54f2734a7b119277248ec434ec0a0a48e6010ec1bb44
@@ -0,0 +1,243 @@
1
+ require "faraday"
2
+ require "factory_girl"
3
+ require "json"
4
+ require "time"
5
+
6
+ class BodhiSlam
7
+ def self.context(params, &block)
8
+ bodhi_context = BodhiContext.new params
9
+ bodhi_context.validate!
10
+
11
+ puts "Switching context to: #{bodhi_context.attributes}"
12
+
13
+ yield bodhi_context
14
+
15
+ puts "Exiting context: #{bodhi_context.attributes}"
16
+ end
17
+
18
+ def self.analyze(context)
19
+ context.validate!
20
+
21
+ #Get the types for this namespace
22
+ result = context.connection.get do |request|
23
+ request.url "/#{context.namespace}/types"
24
+ request.headers[context.credentials_header] = context.credentials
25
+ end
26
+
27
+ if result.status != 200
28
+ errors = JSON.parse result.body
29
+ errors.each{|error| error['status'] = result.status } if errors.is_a? Array
30
+ errors["status"] = result.status if errors.is_a? Hash
31
+ raise errors.to_s
32
+ end
33
+ types = JSON.parse(result.body)
34
+
35
+ #Get the enumerations for this namespace
36
+ result = context.connection.get do |request|
37
+ request.url "/#{context.namespace}/enums"
38
+ request.headers[context.credentials_header] = context.credentials
39
+ end
40
+
41
+ if result.status != 200
42
+ errors = JSON.parse result.body
43
+ errors.each{|error| error['status'] = result.status } if errors.is_a? Array
44
+ errors["status"] = result.status if errors.is_a? Hash
45
+ raise errors.to_s
46
+ end
47
+ enumerations = JSON.parse(result.body)
48
+
49
+ #Create a class & factory for each type
50
+ setup_factory = lambda do |name, properties|
51
+ FactoryGirl.define do
52
+ factory name.to_sym do
53
+ properties.each_pair do |k,v|
54
+ unless v["system"]
55
+
56
+ case v["type"]
57
+ when "GeoJSON"
58
+ send(k) { {type: "Point", coordinates: [10,20]} } if v["multi"].nil?
59
+ send(k) { [*0..5].sample.times.collect{ {type: "Point", coordinates: [10,20]} } } if v["multi"]
60
+ when "Boolean"
61
+ send(k) { [true, false].sample } if v["multi"].nil?
62
+ send(k) { [*0..5].sample.times.collect{ [true, false].sample } } if v["multi"]
63
+ when "Enumerated"
64
+ enum = enumerations.select{ |enumeration| enumeration["name"] == v["ref"].split('.')[0] }[0]
65
+ send(k) { enum["values"].sample[v["ref"].split('.')[1]] } if v["multi"].nil?
66
+ send(k) { [*0..5].sample.times.collect{ enum["values"].sample[v["ref"].split('.')[1]] } } if v["multi"]
67
+ when "Object"
68
+ send(k) { {"foo" => SecureRandom.hex} } if v["multi"].nil?
69
+ send(k) { [*0..5].sample.times.collect{ {"foo" => SecureRandom.hex} } } if v["multi"]
70
+ when "String"
71
+ send(k) { SecureRandom.hex } if v["multi"].nil?
72
+ send(k) { [*0..5].sample.times.collect{ SecureRandom.hex } } if v["multi"]
73
+ when "DateTime"
74
+ send(k) { Time.at(rand * Time.now.to_i).iso8601 } if v["multi"].nil?
75
+ send(k) { [*0..5].sample.times.collect{ Time.at(rand * Time.now.to_i).iso8601 } } if v["multi"]
76
+ when "Integer"
77
+ send(k) { SecureRandom.random_number(100) } if v["multi"].nil?
78
+ send(k) { [*0..5].sample.times.collect{ SecureRandom.random_number(100) } } if v["multi"]
79
+ when "Real"
80
+ send(k) { SecureRandom.random_number } if v["multi"].nil?
81
+ send(k) { [*0..5].sample.times.collect{ SecureRandom.random_number } } if v["multi"]
82
+ else # Its an embedded type
83
+ send(k) { FactoryGirl.build(v["type"]).attributes } if v["multi"].nil?
84
+ send(k) { [*0..5].sample.times.collect{ FactoryGirl.build(v["type"]).attributes } } if v["multi"]
85
+ end
86
+
87
+ end
88
+ end
89
+ end
90
+ end
91
+ end
92
+
93
+ create_type = lambda do |type|
94
+ if type["package"] != "system"
95
+ properties = type["properties"].keys.collect{ |key| key.to_sym }
96
+ klass = Object.const_set(type["name"], Class.new {
97
+ include BodhiResource
98
+ attr_accessor *properties
99
+ })
100
+ klass.define_singleton_method(:find) do |id, context|
101
+ result = context.connection.get do |request|
102
+ request.url "/#{context.namespace}/resources/#{klass.name}/#{id}"
103
+ request.headers[context.credentials_header] = context.credentials
104
+ end
105
+
106
+ if result.status != 200
107
+ errors = JSON.parse result.body
108
+ errors.each{|error| error['status'] = result.status } if errors.is_a? Array
109
+ errors["status"] = result.status if errors.is_a? Hash
110
+ raise errors.to_s
111
+ end
112
+
113
+ object_hash = JSON.parse(result.body)
114
+ object_hash["bodhi_context"] = context
115
+ return FactoryGirl.build(klass.name, object_hash)
116
+ end
117
+
118
+ setup_factory.call(klass.name, type["properties"]) unless FactoryGirl.factories.registered?(klass.name)
119
+ puts "Created Class & Factory for: #{klass.name}"
120
+ end
121
+ end
122
+
123
+ embedded_types = types.select{ |type| type["embedded"] }
124
+ normal_types = types.select{ |type| !type["embedded"] }
125
+
126
+ embedded_types.each{ |type| create_type.call(type) }
127
+ normal_types.each{ |type| create_type.call(type) }
128
+
129
+ #Party!
130
+ end
131
+ end
132
+
133
+
134
+ class BodhiContext
135
+ attr_reader :connection, :server, :namespace,
136
+ :credentials, :credentials_type, :credentials_header
137
+
138
+ def initialize(params)
139
+ params.symbolize_keys!
140
+
141
+ @connection = Faraday.new(url: params[:server]) do |faraday|
142
+ faraday.request :url_encoded # form-encode POST params
143
+ #faraday.response :logger # log requests to STDOUT
144
+ faraday.adapter Faraday.default_adapter # make requests with Net::HTTP
145
+ end
146
+ @server = params[:server]
147
+ @namespace = params[:namespace]
148
+
149
+ if params[:cookie]
150
+ @credentials = params[:cookie]
151
+ @credentials_header = "Cookie"
152
+ @credentials_type = "HTTP_COOKIE"
153
+ else
154
+ @credentials = @connection.basic_auth params[:username], params[:password]
155
+ @credentials_header = "Authorization"
156
+ @credentials_type = "HTTP_BASIC"
157
+ end
158
+ end
159
+
160
+ def attributes
161
+ attributes = Hash.new
162
+ self.instance_variables.each do |variable|
163
+ attribute_name = variable.to_s.delete('@').to_sym
164
+ attributes[attribute_name] = send(attribute_name) unless [:connection, :credentials_header].include?(attribute_name)
165
+ end
166
+ attributes
167
+ end
168
+
169
+ def validate!
170
+ raise ArgumentError, "Server URL must be a String" unless server.is_a?(String)
171
+ raise ArgumentError, "Namespace name must be a String" unless namespace.is_a?(String)
172
+ end
173
+ end
174
+
175
+
176
+ module BodhiResource
177
+ SYSTEM_ATTRIBUTES = [:bodhi_context, :sys_created_at, :sys_version, :sys_modified_at, :sys_modified_by,
178
+ :sys_namespace, :sys_created_by, :sys_type_version, :sys_id]
179
+ attr_accessor *SYSTEM_ATTRIBUTES
180
+
181
+ # - Returns a Hash of the objects attributes
182
+ def attributes
183
+ attributes = Hash.new
184
+ self.instance_variables.each do |variable|
185
+ #Convert :@variable to :variable
186
+ attribute_name = variable.to_s.delete('@').to_sym
187
+ #Get the value of :attribute_name and add it to the Hash
188
+ #Unless the attribute is one of the BASE_ATTRIBUTES
189
+ attributes[attribute_name] = send(attribute_name) unless SYSTEM_ATTRIBUTES.include?(attribute_name)
190
+ end
191
+ attributes
192
+ end
193
+
194
+ def save!
195
+ result = bodhi_context.connection.post do |request|
196
+ request.url "/#{bodhi_context.namespace}/resources/#{self.class}"
197
+ request.headers['Content-Type'] = 'application/json'
198
+ request.headers[bodhi_context.credentials_header] = bodhi_context.credentials
199
+ request.body = attributes.to_json
200
+ end
201
+
202
+ if result.status != 201
203
+ errors = JSON.parse result.body
204
+ errors.each{|error| error['status'] = result.status } if errors.is_a? Array
205
+ errors["status"] = result.status if errors.is_a? Hash
206
+ raise errors.to_s
207
+ end
208
+
209
+ if result.headers['location']
210
+ @sys_id = result.headers['location'].match(/(?<id>[a-zA-Z0-9]{8}-[a-zA-Z0-9]{4}-[a-zA-Z0-9]{4}-[a-zA-Z0-9]{4}-[a-zA-Z0-9]{12})/)[:id]
211
+ end
212
+ end
213
+
214
+ def delete!
215
+ result = bodhi_context.connection.delete do |request|
216
+ request.url "/#{bodhi_context.namespace}/resources/#{self.class}/#{sys_id}"
217
+ request.headers[bodhi_context.credentials_header] = bodhi_context.credentials
218
+ end
219
+
220
+ if result.status != 204
221
+ errors = JSON.parse result.body
222
+ errors.each{|error| error['status'] = result.status } if errors.is_a? Array
223
+ errors["status"] = result.status if errors.is_a? Hash
224
+ raise errors.to_s
225
+ end
226
+ end
227
+
228
+ def patch!(params)
229
+ result = bodhi_context.connection.patch do |request|
230
+ request.url "/#{bodhi_context.namespace}/resources/#{self.class}/#{sys_id}"
231
+ request.headers['Content-Type'] = 'application/json'
232
+ request.headers[bodhi_context.credentials_header] = bodhi_context.credentials
233
+ request.body = params
234
+ end
235
+
236
+ if result.status != 204
237
+ errors = JSON.parse result.body
238
+ errors.each{|error| error['status'] = result.status } if errors.is_a? Array
239
+ errors["status"] = result.status if errors.is_a? Hash
240
+ raise errors.to_s
241
+ end
242
+ end
243
+ end
metadata ADDED
@@ -0,0 +1,86 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: bodhi-slam
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.0.1
5
+ platform: ruby
6
+ authors:
7
+ - Will Davis
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2015-05-11 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: factory_girl
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - "~>"
18
+ - !ruby/object:Gem::Version
19
+ version: '4.5'
20
+ type: :runtime
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - "~>"
25
+ - !ruby/object:Gem::Version
26
+ version: '4.5'
27
+ - !ruby/object:Gem::Dependency
28
+ name: faraday
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - "~>"
32
+ - !ruby/object:Gem::Version
33
+ version: '0.9'
34
+ type: :runtime
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - "~>"
39
+ - !ruby/object:Gem::Version
40
+ version: '0.9'
41
+ - !ruby/object:Gem::Dependency
42
+ name: json
43
+ requirement: !ruby/object:Gem::Requirement
44
+ requirements:
45
+ - - "~>"
46
+ - !ruby/object:Gem::Version
47
+ version: '1.7'
48
+ type: :runtime
49
+ prerelease: false
50
+ version_requirements: !ruby/object:Gem::Requirement
51
+ requirements:
52
+ - - "~>"
53
+ - !ruby/object:Gem::Version
54
+ version: '1.7'
55
+ description: Generate data in serial or parallel
56
+ email: will.davis@hotschedules.com
57
+ executables: []
58
+ extensions: []
59
+ extra_rdoc_files: []
60
+ files:
61
+ - lib/bodhi-slam.rb
62
+ homepage:
63
+ licenses:
64
+ - MIT
65
+ metadata: {}
66
+ post_install_message:
67
+ rdoc_options: []
68
+ require_paths:
69
+ - lib
70
+ required_ruby_version: !ruby/object:Gem::Requirement
71
+ requirements:
72
+ - - ">="
73
+ - !ruby/object:Gem::Version
74
+ version: '0'
75
+ required_rubygems_version: !ruby/object:Gem::Requirement
76
+ requirements:
77
+ - - ">="
78
+ - !ruby/object:Gem::Version
79
+ version: '0'
80
+ requirements: []
81
+ rubyforge_project:
82
+ rubygems_version: 2.4.5
83
+ signing_key:
84
+ specification_version: 4
85
+ summary: Generate data and push to the Bodhi API
86
+ test_files: []