bodhi-slam 0.0.1

Sign up to get free protection for your applications and to get access to all the features.
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: []