fragrant 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 (39) hide show
  1. data/LICENSE +22 -0
  2. data/README.md +6 -0
  3. data/bin/fragrant +14 -0
  4. data/lib/fragrant/address_manager.rb +80 -0
  5. data/lib/fragrant/vagrantfile_generator.rb +64 -0
  6. data/lib/fragrant.rb +323 -0
  7. data/spec/fragrant/environments_spec.rb +18 -0
  8. data/spec/fragrant/vagrantfile_generator_spec.rb +40 -0
  9. data/spec/fragrant/vms_spec.rb +26 -0
  10. data/spec/spec_helper.rb +15 -0
  11. data/vendor/grape/LICENSE +20 -0
  12. data/vendor/grape/lib/grape/api.rb +420 -0
  13. data/vendor/grape/lib/grape/cookies.rb +41 -0
  14. data/vendor/grape/lib/grape/endpoint.rb +377 -0
  15. data/vendor/grape/lib/grape/entity.rb +378 -0
  16. data/vendor/grape/lib/grape/exceptions/base.rb +17 -0
  17. data/vendor/grape/lib/grape/exceptions/validation_error.rb +10 -0
  18. data/vendor/grape/lib/grape/middleware/auth/basic.rb +30 -0
  19. data/vendor/grape/lib/grape/middleware/auth/digest.rb +30 -0
  20. data/vendor/grape/lib/grape/middleware/auth/oauth2.rb +72 -0
  21. data/vendor/grape/lib/grape/middleware/base.rb +154 -0
  22. data/vendor/grape/lib/grape/middleware/error.rb +87 -0
  23. data/vendor/grape/lib/grape/middleware/filter.rb +17 -0
  24. data/vendor/grape/lib/grape/middleware/formatter.rb +81 -0
  25. data/vendor/grape/lib/grape/middleware/prefixer.rb +21 -0
  26. data/vendor/grape/lib/grape/middleware/versioner/header.rb +59 -0
  27. data/vendor/grape/lib/grape/middleware/versioner/param.rb +44 -0
  28. data/vendor/grape/lib/grape/middleware/versioner/path.rb +42 -0
  29. data/vendor/grape/lib/grape/middleware/versioner.rb +29 -0
  30. data/vendor/grape/lib/grape/route.rb +23 -0
  31. data/vendor/grape/lib/grape/util/deep_merge.rb +23 -0
  32. data/vendor/grape/lib/grape/util/hash_stack.rb +100 -0
  33. data/vendor/grape/lib/grape/validations/coerce.rb +61 -0
  34. data/vendor/grape/lib/grape/validations/presence.rb +11 -0
  35. data/vendor/grape/lib/grape/validations/regexp.rb +13 -0
  36. data/vendor/grape/lib/grape/validations.rb +192 -0
  37. data/vendor/grape/lib/grape/version.rb +3 -0
  38. data/vendor/grape/lib/grape.rb +44 -0
  39. metadata +216 -0
@@ -0,0 +1,420 @@
1
+ require 'rack/mount'
2
+ require 'rack/auth/basic'
3
+ require 'rack/auth/digest/md5'
4
+ require 'logger'
5
+ require 'grape/util/deep_merge'
6
+
7
+ module Grape
8
+ # The API class is the primary entry point for
9
+ # creating Grape APIs.Users should subclass this
10
+ # class in order to build an API.
11
+ class API
12
+ extend Validations::ClassMethods
13
+
14
+ class << self
15
+ attr_reader :route_set
16
+ attr_reader :versions
17
+ attr_reader :routes
18
+ attr_reader :settings
19
+ attr_writer :logger
20
+ attr_reader :endpoints
21
+ attr_reader :mountings
22
+ attr_reader :instance
23
+
24
+ def logger(logger = nil)
25
+ if logger
26
+ @logger = logger
27
+ else
28
+ @logger ||= Logger.new($stdout)
29
+ end
30
+ end
31
+
32
+ def reset!
33
+ @settings = Grape::Util::HashStack.new
34
+ @route_set = Rack::Mount::RouteSet.new
35
+ @endpoints = []
36
+ @mountings = []
37
+ @routes = nil
38
+ reset_validations!
39
+ end
40
+
41
+ def compile
42
+ @instance = self.new
43
+ end
44
+
45
+ def change!
46
+ @instance = nil
47
+ end
48
+
49
+ def call(env)
50
+ compile unless instance
51
+ call!(env)
52
+ end
53
+
54
+ def call!(env)
55
+ instance.call(env)
56
+ end
57
+
58
+ # Set a configuration value for this namespace.
59
+ #
60
+ # @param key [Symbol] The key of the configuration variable.
61
+ # @param value [Object] The value to which to set the configuration variable.
62
+ def set(key, value)
63
+ settings[key.to_sym] = value
64
+ end
65
+
66
+ # Add to a configuration value for this
67
+ # namespace.
68
+ #
69
+ # @param key [Symbol] The key of the configuration variable.
70
+ # @param value [Object] The value to which to set the configuration variable.
71
+ def imbue(key, value)
72
+ settings.imbue(key, value)
73
+ end
74
+
75
+ # Define a root URL prefix for your entire
76
+ # API.
77
+ def prefix(prefix = nil)
78
+ prefix ? set(:root_prefix, prefix) : settings[:root_prefix]
79
+ end
80
+
81
+ # Specify an API version.
82
+ #
83
+ # @example API with legacy support.
84
+ # class MyAPI < Grape::API
85
+ # version 'v2'
86
+ #
87
+ # get '/main' do
88
+ # {:some => 'data'}
89
+ # end
90
+ #
91
+ # version 'v1' do
92
+ # get '/main' do
93
+ # {:legacy => 'data'}
94
+ # end
95
+ # end
96
+ # end
97
+ #
98
+ def version(*args, &block)
99
+ if args.any?
100
+ options = args.pop if args.last.is_a? Hash
101
+ options ||= {}
102
+ options = {:using => :path}.merge!(options)
103
+ @versions = versions | args
104
+ nest(block) do
105
+ set(:version, args)
106
+ set(:version_options, options)
107
+ end
108
+ end
109
+ end
110
+
111
+ # Add a description to the next namespace or function.
112
+ def desc(description, options = {})
113
+ @last_description = options.merge(:description => description)
114
+ end
115
+
116
+ # Specify the default format for the API's serializers.
117
+ # May be `:json` or `:txt` (default).
118
+ def default_format(new_format = nil)
119
+ new_format ? set(:default_format, new_format.to_sym) : settings[:default_format]
120
+ end
121
+
122
+ # Specify the format for the API's serializers.
123
+ # May be `:json` or `:txt`.
124
+ def format(new_format = nil)
125
+ new_format ? set(:format, new_format.to_sym) : settings[:format]
126
+ end
127
+
128
+ # Specify the format for error messages.
129
+ # May be `:json` or `:txt` (default).
130
+ def error_format(new_format = nil)
131
+ new_format ? set(:error_format, new_format.to_sym) : settings[:error_format]
132
+ end
133
+
134
+ # Specify additional content-types, e.g.:
135
+ # content_type :xls, 'application/vnd.ms-excel'
136
+ def content_type(key, val)
137
+ settings.imbue(:content_types, key.to_sym => val)
138
+ end
139
+
140
+ # Specify the default status code for errors.
141
+ def default_error_status(new_status = nil)
142
+ new_status ? set(:default_error_status, new_status) : settings[:default_error_status]
143
+ end
144
+
145
+ # Allows you to rescue certain exceptions that occur to return
146
+ # a grape error rather than raising all the way to the
147
+ # server level.
148
+ #
149
+ # @example Rescue from custom exceptions
150
+ # class ExampleAPI < Grape::API
151
+ # class CustomError < StandardError; end
152
+ #
153
+ # rescue_from CustomError
154
+ # end
155
+ #
156
+ # @overload rescue_from(*exception_classes, options = {})
157
+ # @param [Array] exception_classes A list of classes that you want to rescue, or
158
+ # the symbol :all to rescue from all exceptions.
159
+ # @param [Block] block Execution block to handle the given exception.
160
+ # @param [Hash] options Options for the rescue usage.
161
+ # @option options [Boolean] :backtrace Include a backtrace in the rescue response.
162
+ def rescue_from(*args, &block)
163
+ if block_given?
164
+ args.each do |arg|
165
+ imbue(:rescue_handlers, { arg => block })
166
+ end
167
+ end
168
+ imbue(:rescue_options, args.pop) if args.last.is_a?(Hash)
169
+ set(:rescue_all, true) and return if args.include?(:all)
170
+ imbue(:rescued_errors, args)
171
+ end
172
+
173
+ # Allows you to specify a default representation entity for a
174
+ # class. This allows you to map your models to their respective
175
+ # entities once and then simply call `present` with the model.
176
+ #
177
+ # @example
178
+ # class ExampleAPI < Grape::API
179
+ # represent User, :with => Entity::User
180
+ #
181
+ # get '/me' do
182
+ # present current_user # :with => Entity::User is assumed
183
+ # end
184
+ # end
185
+ #
186
+ # Note that Grape will automatically go up the class ancestry to
187
+ # try to find a representing entity, so if you, for example, define
188
+ # an entity to represent `Object` then all presented objects will
189
+ # bubble up and utilize the entity provided on that `represent` call.
190
+ #
191
+ # @param model_class [Class] The model class that will be represented.
192
+ # @option options [Class] :with The entity class that will represent the model.
193
+ def represent(model_class, options)
194
+ raise ArgumentError, "You must specify an entity class in the :with option." unless options[:with] && options[:with].is_a?(Class)
195
+ imbue(:representations, model_class => options[:with])
196
+ end
197
+
198
+ # Add helper methods that will be accessible from any
199
+ # endpoint within this namespace (and child namespaces).
200
+ #
201
+ # When called without a block, all known helpers within this scope
202
+ # are included.
203
+ #
204
+ # @param mod [Module] optional module of methods to include
205
+ # @param &block [Block] optional block of methods to include
206
+ #
207
+ # @example Define some helpers.
208
+ # class ExampleAPI < Grape::API
209
+ # helpers do
210
+ # def current_user
211
+ # User.find_by_id(params[:token])
212
+ # end
213
+ # end
214
+ # end
215
+ def helpers(new_mod = nil, &block)
216
+ if block_given? || new_mod
217
+ mod = settings.peek[:helpers] || Module.new
218
+ if new_mod
219
+ mod.class_eval do
220
+ include new_mod
221
+ end
222
+ end
223
+ mod.class_eval &block if block_given?
224
+ set(:helpers, mod)
225
+ else
226
+ mod = Module.new
227
+ settings.stack.each do |s|
228
+ mod.send :include, s[:helpers] if s[:helpers]
229
+ end
230
+ change!
231
+ mod
232
+ end
233
+ end
234
+
235
+ # Add an authentication type to the API. Currently
236
+ # only `:http_basic`, `:http_digest` and `:oauth2` are supported.
237
+ def auth(type = nil, options = {}, &block)
238
+ if type
239
+ set(:auth, {:type => type.to_sym, :proc => block}.merge(options))
240
+ else
241
+ settings[:auth]
242
+ end
243
+ end
244
+
245
+ # Add HTTP Basic authorization to the API.
246
+ #
247
+ # @param [Hash] options A hash of options.
248
+ # @option options [String] :realm "API Authorization" The HTTP Basic realm.
249
+ def http_basic(options = {}, &block)
250
+ options[:realm] ||= "API Authorization"
251
+ auth :http_basic, options, &block
252
+ end
253
+
254
+ def http_digest(options = {}, &block)
255
+ options[:realm] ||= "API Authorization"
256
+ options[:opaque] ||= "secret"
257
+ auth :http_digest, options, &block
258
+ end
259
+
260
+ def mount(mounts)
261
+ mounts = {mounts => '/'} unless mounts.respond_to?(:each_pair)
262
+ mounts.each_pair do |app, path|
263
+ if app.respond_to?(:inherit_settings)
264
+ app.inherit_settings(settings.clone)
265
+ end
266
+
267
+ endpoints << Grape::Endpoint.new(settings.clone,
268
+ :method => :any,
269
+ :path => path,
270
+ :app => app
271
+ )
272
+ end
273
+ end
274
+
275
+ # Defines a route that will be recognized
276
+ # by the Grape API.
277
+ #
278
+ # @param methods [HTTP Verb] One or more HTTP verbs that are accepted by this route. Set to `:any` if you want any verb to be accepted.
279
+ # @param paths [String] One or more strings representing the URL segment(s) for this route.
280
+ #
281
+ # @example Defining a basic route.
282
+ # class MyAPI < Grape::API
283
+ # route(:any, '/hello') do
284
+ # {:hello => 'world'}
285
+ # end
286
+ # end
287
+ def route(methods, paths = ['/'], route_options = {}, &block)
288
+ endpoint_options = {
289
+ :method => methods,
290
+ :path => paths,
291
+ :route_options => (@namespace_description || {}).deep_merge(@last_description || {}).deep_merge(route_options || {})
292
+ }
293
+ endpoints << Grape::Endpoint.new(settings.clone, endpoint_options, &block)
294
+
295
+ @last_description = nil
296
+ reset_validations!
297
+ end
298
+
299
+ def before(&block)
300
+ imbue(:befores, [block])
301
+ end
302
+
303
+ def after(&block)
304
+ imbue(:afters, [block])
305
+ end
306
+
307
+ def get(paths = ['/'], options = {}, &block); route('GET', paths, options, &block) end
308
+ def post(paths = ['/'], options = {}, &block); route('POST', paths, options, &block) end
309
+ def put(paths = ['/'], options = {}, &block); route('PUT', paths, options, &block) end
310
+ def head(paths = ['/'], options = {}, &block); route('HEAD', paths, options, &block) end
311
+ def delete(paths = ['/'], options = {}, &block); route('DELETE', paths, options, &block) end
312
+ def options(paths = ['/'], options = {}, &block); route('OPTIONS', paths, options, &block) end
313
+ def patch(paths = ['/'], options = {}, &block); route('PATCH', paths, options, &block) end
314
+
315
+ def namespace(space = nil, &block)
316
+ if space || block_given?
317
+ previous_namespace_description = @namespace_description
318
+ @namespace_description = (@namespace_description || {}).deep_merge(@last_description || {})
319
+ @last_description = nil
320
+ nest(block) do
321
+ set(:namespace, space.to_s) if space
322
+ end
323
+ @namespace_description = previous_namespace_description
324
+ else
325
+ Rack::Mount::Utils.normalize_path(settings.stack.map{|s| s[:namespace]}.join('/'))
326
+ end
327
+ end
328
+
329
+ alias_method :group, :namespace
330
+ alias_method :resource, :namespace
331
+ alias_method :resources, :namespace
332
+ alias_method :segment, :namespace
333
+
334
+ # Create a scope without affecting the URL.
335
+ #
336
+ # @param name [Symbol] Purely placebo, just allows to to name the scope to make the code more readable.
337
+ def scope(name = nil, &block)
338
+ nest(block)
339
+ end
340
+
341
+ # Apply a custom middleware to the API. Applies
342
+ # to the current namespace and any children, but
343
+ # not parents.
344
+ #
345
+ # @param middleware_class [Class] The class of the middleware you'd like
346
+ # to inject.
347
+ def use(middleware_class, *args, &block)
348
+ arr = [middleware_class, *args]
349
+ arr << block if block_given?
350
+ imbue(:middleware, [arr])
351
+ end
352
+
353
+ # Retrieve an array of the middleware classes
354
+ # and arguments that are currently applied to the
355
+ # application.
356
+ def middleware
357
+ settings.stack.inject([]){|a,s| a += s[:middleware] if s[:middleware]; a}
358
+ end
359
+
360
+ # An array of API routes.
361
+ def routes
362
+ @routes ||= prepare_routes
363
+ end
364
+
365
+ def versions
366
+ @versions ||= []
367
+ end
368
+
369
+ protected
370
+
371
+ def prepare_routes
372
+ routes = []
373
+ endpoints.each do |endpoint|
374
+ routes.concat(endpoint.routes)
375
+ end
376
+ routes
377
+ end
378
+
379
+ # Execute first the provided block, then each of the
380
+ # block passed in. Allows for simple 'before' setups
381
+ # of settings stack pushes.
382
+ def nest(*blocks, &block)
383
+ blocks.reject!{|b| b.nil?}
384
+ if blocks.any?
385
+ settings.push # create a new context to eval the follow
386
+ instance_eval &block if block_given?
387
+ blocks.each{|b| instance_eval &b}
388
+ settings.pop # when finished, we pop the context
389
+ reset_validations!
390
+ else
391
+ instance_eval &block
392
+ end
393
+ end
394
+
395
+ def inherited(subclass)
396
+ subclass.reset!
397
+ subclass.logger = logger.clone
398
+ end
399
+
400
+ def inherit_settings(other_stack)
401
+ settings.prepend other_stack
402
+ endpoints.each{|e| e.settings.prepend(other_stack)}
403
+ end
404
+ end
405
+
406
+ def initialize
407
+ @route_set = Rack::Mount::RouteSet.new
408
+ self.class.endpoints.each do |endpoint|
409
+ endpoint.mount_in(@route_set)
410
+ end
411
+ @route_set.freeze
412
+ end
413
+
414
+ def call(env)
415
+ @route_set.call(env)
416
+ end
417
+
418
+ reset!
419
+ end
420
+ end
@@ -0,0 +1,41 @@
1
+ module Grape
2
+ class Cookies
3
+
4
+ def initialize
5
+ @cookies = {}
6
+ @send_cookies = {}
7
+ end
8
+
9
+ def read(request)
10
+ request.cookies.each do |name, value|
11
+ @cookies[name.to_sym] = value
12
+ end
13
+ end
14
+
15
+ def write(header)
16
+ @cookies.select { |key, value|
17
+ @send_cookies[key.to_sym] == true
18
+ }.each { |name, value|
19
+ Rack::Utils.set_cookie_header!(
20
+ header, name, value.instance_of?(Hash) ? value : { :value => value })
21
+ }
22
+ end
23
+
24
+ def [](name)
25
+ @cookies[name]
26
+ end
27
+
28
+ def []=(name, value)
29
+ @cookies[name.to_sym] = value
30
+ @send_cookies[name.to_sym] = true
31
+ end
32
+
33
+ def each(&block)
34
+ @cookies.each(&block)
35
+ end
36
+
37
+ def delete(name)
38
+ self.[]=(name, { :value => 'deleted', :expires => Time.at(0) })
39
+ end
40
+ end
41
+ end