rainforest 1.0.7 → 2.0.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (85) hide show
  1. checksums.yaml +4 -4
  2. data/.gitignore +3 -6
  3. data/.travis.yml +13 -1
  4. data/Gemfile +6 -0
  5. data/README.md +72 -21
  6. data/Rakefile +6 -13
  7. data/VERSION +1 -1
  8. data/bin/rainforest-console +1 -1
  9. data/gemfiles/default-with-activesupport.gemfile +8 -1
  10. data/gemfiles/json.gemfile +10 -2
  11. data/gemfiles/yajl.gemfile +10 -2
  12. data/lib/rainforest.rb +61 -240
  13. data/lib/rainforest/apibits/api_client.rb +28 -0
  14. data/lib/rainforest/apibits/api_endpoint.rb +11 -0
  15. data/lib/rainforest/apibits/api_list.rb +88 -0
  16. data/lib/rainforest/apibits/api_method.rb +95 -0
  17. data/lib/rainforest/apibits/api_object.rb +52 -0
  18. data/lib/rainforest/apibits/api_resource.rb +153 -0
  19. data/lib/rainforest/apibits/headers_builder.rb +47 -0
  20. data/lib/rainforest/apibits/params_builder.rb +27 -0
  21. data/lib/rainforest/apibits/path_builder.rb +38 -0
  22. data/lib/rainforest/apibits/requester.rb +104 -0
  23. data/lib/rainforest/apibits/util.rb +51 -0
  24. data/lib/rainforest/clients/default_client.rb +59 -0
  25. data/lib/rainforest/endpoints/client_stats_endpoint.rb +11 -0
  26. data/lib/rainforest/endpoints/environment_runs_endpoint.rb +11 -0
  27. data/lib/rainforest/endpoints/environments_endpoint.rb +48 -0
  28. data/lib/rainforest/endpoints/generator_rows_endpoint.rb +17 -0
  29. data/lib/rainforest/endpoints/generators_endpoint.rb +48 -0
  30. data/lib/rainforest/endpoints/integrations_endpoint.rb +33 -0
  31. data/lib/rainforest/endpoints/run_tests_endpoint.rb +20 -0
  32. data/lib/rainforest/endpoints/runs_endpoint.rb +48 -0
  33. data/lib/rainforest/endpoints/schedules_endpoint.rb +48 -0
  34. data/lib/rainforest/endpoints/site_environments_endpoint.rb +24 -0
  35. data/lib/rainforest/endpoints/sites_endpoint.rb +39 -0
  36. data/lib/rainforest/endpoints/tests_endpoint.rb +57 -0
  37. data/lib/rainforest/endpoints/users_endpoint.rb +48 -0
  38. data/lib/rainforest/errors/api_connection_error.rb +1 -1
  39. data/lib/rainforest/errors/api_error.rb +32 -1
  40. data/lib/rainforest/errors/authentication_error.rb +1 -1
  41. data/lib/rainforest/errors/rainforest_error.rb +2 -9
  42. data/lib/rainforest/resources/client_stats.rb +31 -0
  43. data/lib/rainforest/resources/environment.rb +73 -0
  44. data/lib/rainforest/resources/generator.rb +73 -0
  45. data/lib/rainforest/resources/integration.rb +52 -0
  46. data/lib/rainforest/resources/run.rb +93 -0
  47. data/lib/rainforest/resources/schedule.rb +63 -0
  48. data/lib/rainforest/resources/site.rb +53 -0
  49. data/lib/rainforest/resources/site_environment.rb +40 -0
  50. data/lib/rainforest/resources/test.rb +98 -0
  51. data/lib/rainforest/resources/user.rb +75 -0
  52. data/rainforest.gemspec +8 -6
  53. data/test/rainforest/api_client_test.rb +51 -0
  54. data/test/rainforest/api_endpoint_test.rb +13 -0
  55. data/test/rainforest/api_list_test.rb +49 -0
  56. data/test/rainforest/api_method_test.rb +78 -0
  57. data/test/rainforest/headers_builder_test.rb +28 -0
  58. data/test/rainforest/params_builder_test.rb +57 -0
  59. data/test/rainforest/path_builder_test.rb +50 -0
  60. data/test/rainforest/requester_test.rb +86 -0
  61. data/test/rainforest/util_test.rb +41 -19
  62. data/test/test_data.rb +72 -0
  63. data/test/test_helper.rb +17 -134
  64. metadata +99 -59
  65. data/CONTRIBUTORS +0 -2
  66. data/History.txt +0 -4
  67. data/LICENSE +0 -21
  68. data/lib/data/ca-certificates.crt +0 -3918
  69. data/lib/rainforest/api_operations/create.rb +0 -16
  70. data/lib/rainforest/api_operations/delete.rb +0 -11
  71. data/lib/rainforest/api_operations/list.rb +0 -16
  72. data/lib/rainforest/api_operations/update.rb +0 -61
  73. data/lib/rainforest/api_resource.rb +0 -33
  74. data/lib/rainforest/errors/invalid_request_error.rb +0 -10
  75. data/lib/rainforest/json.rb +0 -21
  76. data/lib/rainforest/list_object.rb +0 -35
  77. data/lib/rainforest/rainforest_object.rb +0 -165
  78. data/lib/rainforest/run.rb +0 -8
  79. data/lib/rainforest/singleton_api_resource.rb +0 -20
  80. data/lib/rainforest/util.rb +0 -100
  81. data/test/rainforest/api_resource_test.rb +0 -11
  82. data/test/rainforest/auth_test.rb +0 -24
  83. data/test/rainforest/list_object_test.rb +0 -7
  84. data/test/rainforest/metadata_test.rb +0 -7
  85. data/test/rainforest/run_test.rb +0 -36
@@ -0,0 +1,27 @@
1
+ module Rainforest
2
+ module ParamsBuilder
3
+
4
+ def self.clean(params)
5
+ Util.symbolize_keys(params || {})
6
+ end
7
+
8
+ # Clean the params, and the hash to_merge, and then merge them.
9
+ # This ensures that we dont get something like { "id" => 123, :id => 321 }.
10
+ def self.merge(*args)
11
+ ret = {}
12
+ args.each do |arg|
13
+ ret = ret.merge(clean(arg))
14
+ end
15
+ ret
16
+ end
17
+
18
+ def self.build(params, api_key=nil, auth_key=nil)
19
+ default_params.merge(clean(params))
20
+ end
21
+
22
+ def self.default_params
23
+ params = {}
24
+ end
25
+
26
+ end
27
+ end
@@ -0,0 +1,38 @@
1
+ module Rainforest
2
+ module PathBuilder
3
+
4
+ # Take a path like:
5
+ # ":path/:id/dogs/:dog_id"
6
+ # and convert it to:
7
+ # "#{object.path}/#{object.id}/dogs/#{params[:id]}" => "/objects/1/dogs/2"
8
+ #
9
+ # Path priority is:
10
+ # 1. Object - this will be a class or an instance of a class.
11
+ # 2. Params - this is a hash of key values. All keys *must* be symbolized.
12
+ def self.build(path, object, params)
13
+ ret = path.dup
14
+ if ret.include?(":")
15
+ matches = ret.scan(/:([^\/]*)/).flatten.map(&:to_sym)
16
+ missing = Set.new(matches)
17
+
18
+ matches.each do |match|
19
+ value = determine_value(match, object, params)
20
+ missing.delete(match) unless value.nil?
21
+ ret.sub!(match.inspect, "#{value}")
22
+ end
23
+
24
+ if missing.any?
25
+ raise ArgumentError.new("Could not determine the full URL. The following values of the path are missing: #{missing.to_a.join(', ')}. Try setting them in your params.")
26
+ end
27
+ end
28
+ ret
29
+ end
30
+
31
+ def self.determine_value(match, object, params)
32
+ value = object.send(match) if object && object.respond_to?(match)
33
+ value ||= params[match] if params && params.has_key?(match)
34
+ value
35
+ end
36
+
37
+ end
38
+ end
@@ -0,0 +1,104 @@
1
+ module Rainforest
2
+ module Requester
3
+
4
+ def self.request(method, url, params={}, headers={})
5
+ method = method.to_sym
6
+ url, params = prepare_params(method, url, params, headers)
7
+ request_opts = {
8
+ :method => method,
9
+ :url => url,
10
+ :headers => headers,
11
+ :payload => params,
12
+
13
+ :verify_ssl => false,
14
+ :open_timeout => 30,
15
+ :timeout => 60
16
+ }
17
+
18
+ execute_request(request_opts)
19
+ end
20
+
21
+ def self.execute_request(opts)
22
+ RestClient::Request.execute(opts)
23
+ end
24
+
25
+ def self.get(url, params, headers)
26
+ self.request(:get, url, params, headers)
27
+ end
28
+
29
+ def self.delete(url, params, headers)
30
+ self.request(:delete, url, params, headers)
31
+ end
32
+
33
+ def self.put(url, params, headers)
34
+ self.request(:put, url, params, headers)
35
+ end
36
+
37
+ def self.post(url, params, headers)
38
+ self.request(:post, url, params, headers)
39
+ end
40
+
41
+ def self.prepare_params(method, url, params={}, headers={})
42
+ if [:get, :head, :delete].include?(method)
43
+ unless params.empty?
44
+ url += URI.parse(url).query ? '&' : '?' + query_string(params)
45
+ end
46
+ params = nil
47
+ else
48
+ if headers["Content-Type"] == "application/json" || headers[:"Content-Type"] == "application/json"
49
+ params = JSON.generate(params)
50
+ else
51
+ headers["Content-Type"] = "application/x-www-form-urlencoded"
52
+ if !RestClient::Payload.has_file?(params)
53
+ params = query_string(params)
54
+ end
55
+ end
56
+ end
57
+ [url, params]
58
+ end
59
+
60
+ def self.query_string(params)
61
+ params ||= {}
62
+ if params.any?
63
+ query_array(params).join('&')
64
+ else
65
+ ""
66
+ end
67
+ end
68
+
69
+ # Three major use cases (and nesting of them needs to be supported):
70
+ # { :a => { :b => "bvalue" } } => ["a[b]=bvalue"]
71
+ # { :a => [1, 2] } => ["a[]=1", "a[]=2"]
72
+ # { :a => "value" } => ["a=value"]
73
+ def self.query_array(params, key_prefix=nil)
74
+ ret = []
75
+ params.each do |key, value|
76
+ if params.is_a?(Array)
77
+ value = key
78
+ key = ''
79
+ end
80
+ key_suffix = escape(key)
81
+ full_key = key_prefix ? "#{key_prefix}[#{key_suffix}]" : key_suffix
82
+
83
+ if value.is_a?(Hash) || value.is_a?(Array)
84
+ # Handles the following cases:
85
+ # { :a => { :b => "bvalue" } } => ["a[b]=bvalue"]
86
+ # { :a => [1, 2] } => ["a[]=1", "a[]=2"]
87
+ ret += query_array(value, full_key)
88
+ elsif value.is_a?(ApiObject)
89
+ ret += query_array(value.json, full_key)
90
+ else
91
+ # Handles the base case with just key and value:
92
+ # { :a => "value" } => ["a=value"]
93
+ ret << "#{full_key}=#{escape(value)}"
94
+ end
95
+ end
96
+ ret
97
+ end
98
+
99
+ def self.escape(val)
100
+ URI.escape(val.to_s, Regexp.new("[^#{URI::PATTERN::UNRESERVED}]"))
101
+ end
102
+
103
+ end
104
+ end
@@ -0,0 +1,51 @@
1
+ module Rainforest
2
+ module Util
3
+
4
+ def self.symbolize_keys(obj)
5
+ if obj.is_a?(Hash)
6
+ ret = {}
7
+ obj.each do |key, value|
8
+ ret[(key.to_sym rescue key) || key] = symbolize_keys(value)
9
+ end
10
+ return ret
11
+ elsif obj.is_a?(Array)
12
+ return obj.map{ |value| symbolize_keys(value) }
13
+ else
14
+ return obj
15
+ end
16
+ end
17
+
18
+ def self.sorta_deep_clone(json)
19
+ if json.is_a?(Hash)
20
+ ret = {}
21
+ json.each do |k, v|
22
+ ret[k] = sorta_deep_clone(v)
23
+ end
24
+ ret
25
+ elsif json.is_a?(Array)
26
+ json.map{ |j| sorta_deep_clone(j) }
27
+ else
28
+ begin
29
+ json.dup
30
+ rescue
31
+ json
32
+ end
33
+ end
34
+ end
35
+
36
+ def self.constantize(str, prefix=false)
37
+ str = str.to_s
38
+ begin
39
+ str.split('::').reduce(Rainforest, :const_get)
40
+ rescue NameError => e
41
+ if prefix
42
+ raise e
43
+ else
44
+ p = "#{self.name}".split("::").first
45
+ constantize("#{p}::#{str}", true)
46
+ end
47
+ end
48
+ end
49
+
50
+ end
51
+ end
@@ -0,0 +1,59 @@
1
+ module Rainforest
2
+ class DefaultClient < ApiClient
3
+
4
+ def initialize(api_key)
5
+ self.refresh_from(api_key)
6
+ end
7
+
8
+ def refresh_from(api_key)
9
+ headers = {
10
+ :Accept => "application/json",
11
+ :"Content-Type" => "application/x-www-form-urlencoded",
12
+ :CLIENT_TOKEN => api_key,
13
+ }
14
+ params = {}
15
+ super(headers, params)
16
+ end
17
+
18
+ def client_stats
19
+ @client_stats ||= ClientStatsEndpoint.new(self)
20
+ end
21
+
22
+ def environments
23
+ @environments ||= EnvironmentsEndpoint.new(self)
24
+ end
25
+
26
+ def generators
27
+ @generators ||= GeneratorsEndpoint.new(self)
28
+ end
29
+
30
+ def integrations
31
+ @integrations ||= IntegrationsEndpoint.new(self)
32
+ end
33
+
34
+ def runs
35
+ @runs ||= RunsEndpoint.new(self)
36
+ end
37
+
38
+ def schedules
39
+ @schedules ||= SchedulesEndpoint.new(self)
40
+ end
41
+
42
+ def site_environments
43
+ @site_environments ||= SiteEnvironmentsEndpoint.new(self)
44
+ end
45
+
46
+ def sites
47
+ @sites ||= SitesEndpoint.new(self)
48
+ end
49
+
50
+ def tests
51
+ @tests ||= TestsEndpoint.new(self)
52
+ end
53
+
54
+ def users
55
+ @users ||= UsersEndpoint.new(self)
56
+ end
57
+
58
+ end
59
+ end
@@ -0,0 +1,11 @@
1
+ module Rainforest
2
+ class ClientStatsEndpoint < ApiEndpoint
3
+
4
+ def retrieve(params={}, headers={})
5
+ method = ApiMethod.new(:get, "/clients/stats", params, headers, @parent)
6
+ json = @client.execute(method)
7
+ ClientStats.new(json, method)
8
+ end
9
+
10
+ end
11
+ end
@@ -0,0 +1,11 @@
1
+ module Rainforest
2
+ class EnvironmentRunsEndpoint < ApiEndpoint
3
+
4
+ def all(params={}, headers={})
5
+ method = ApiMethod.new(:get, "/environments/:id/runs", params, headers, @parent)
6
+ json = @client.execute(method)
7
+ ApiList.new(:Run, json, method)
8
+ end
9
+
10
+ end
11
+ end
@@ -0,0 +1,48 @@
1
+ module Rainforest
2
+ class EnvironmentsEndpoint < ApiEndpoint
3
+
4
+ def new(id)
5
+ Environment.new({:id => id}, nil, @client)
6
+ end
7
+
8
+ def all(params={}, headers={})
9
+ method = ApiMethod.new(:get, "/environments", params, headers, @parent)
10
+ json = @client.execute(method)
11
+ ApiList.new(:Environment, json, method)
12
+ end
13
+
14
+ def retrieve(environment_id, params={}, headers={})
15
+ params = ParamsBuilder.merge({
16
+ :environment_id => environment_id,
17
+ }, params)
18
+ method = ApiMethod.new(:get, "/environments/:environment_id", params, headers, @parent)
19
+ json = @client.execute(method)
20
+ Environment.new(json, method)
21
+ end
22
+
23
+ def delete(environment_id, params={}, headers={})
24
+ params = ParamsBuilder.merge({
25
+ :environment_id => environment_id,
26
+ }, params)
27
+ method = ApiMethod.new(:delete, "/environments/:environment_id", params, headers, @parent)
28
+ json = @client.execute(method)
29
+ json
30
+ end
31
+
32
+ def update(environment_id, params={}, headers={})
33
+ params = ParamsBuilder.merge({
34
+ :environment_id => environment_id,
35
+ }, params)
36
+ method = ApiMethod.new(:put, "/environments/:environment_id", params, headers, @parent)
37
+ json = @client.execute(method)
38
+ Environment.new(json, method)
39
+ end
40
+
41
+ def create(params={}, headers={})
42
+ method = ApiMethod.new(:post, "/environments", params, headers, @parent)
43
+ json = @client.execute(method)
44
+ Environment.new(json, method)
45
+ end
46
+
47
+ end
48
+ end
@@ -0,0 +1,17 @@
1
+ module Rainforest
2
+ class GeneratorRowsEndpoint < ApiEndpoint
3
+
4
+ def all(params={}, headers={})
5
+ method = ApiMethod.new(:get, "/generators/:id/rows", params, headers, @parent)
6
+ json = @client.execute(method)
7
+ json
8
+ end
9
+
10
+ def create(params={}, headers={})
11
+ method = ApiMethod.new(:post, "/generators/:id/rows", params, headers, @parent)
12
+ json = @client.execute(method)
13
+ json
14
+ end
15
+
16
+ end
17
+ end
@@ -0,0 +1,48 @@
1
+ module Rainforest
2
+ class GeneratorsEndpoint < ApiEndpoint
3
+
4
+ def new(id)
5
+ Generator.new({:id => id}, nil, @client)
6
+ end
7
+
8
+ def all(params={}, headers={})
9
+ method = ApiMethod.new(:get, "/generators", params, headers, @parent)
10
+ json = @client.execute(method)
11
+ ApiList.new(:Generator, json, method)
12
+ end
13
+
14
+ def retrieve(generator_id, params={}, headers={})
15
+ params = ParamsBuilder.merge({
16
+ :generator_id => generator_id,
17
+ }, params)
18
+ method = ApiMethod.new(:get, "/generators/:generator_id", params, headers, @parent)
19
+ json = @client.execute(method)
20
+ Generator.new(json, method)
21
+ end
22
+
23
+ def delete(generator_id, params={}, headers={})
24
+ params = ParamsBuilder.merge({
25
+ :generator_id => generator_id,
26
+ }, params)
27
+ method = ApiMethod.new(:delete, "/generators/:generator_id", params, headers, @parent)
28
+ json = @client.execute(method)
29
+ Generator.new(json, method)
30
+ end
31
+
32
+ def update(generator_id, params={}, headers={})
33
+ params = ParamsBuilder.merge({
34
+ :generator_id => generator_id,
35
+ }, params)
36
+ method = ApiMethod.new(:put, "/generators/:generator_id", params, headers, @parent)
37
+ json = @client.execute(method)
38
+ Generator.new(json, method)
39
+ end
40
+
41
+ def create(params={}, headers={})
42
+ method = ApiMethod.new(:post, "/generators", params, headers, @parent)
43
+ json = @client.execute(method)
44
+ Generator.new(json, method)
45
+ end
46
+
47
+ end
48
+ end
@@ -0,0 +1,33 @@
1
+ module Rainforest
2
+ class IntegrationsEndpoint < ApiEndpoint
3
+
4
+ def new(id)
5
+ Integration.new({:id => id}, nil, @client)
6
+ end
7
+
8
+ def all(params={}, headers={})
9
+ method = ApiMethod.new(:get, "/integrations", params, headers, @parent)
10
+ json = @client.execute(method)
11
+ ApiList.new(:Integration, json, method)
12
+ end
13
+
14
+ def retrieve(integration_id, params={}, headers={})
15
+ params = ParamsBuilder.merge({
16
+ :integration_id => integration_id,
17
+ }, params)
18
+ method = ApiMethod.new(:get, "/integrations/:integration_id", params, headers, @parent)
19
+ json = @client.execute(method)
20
+ Integration.new(json, method)
21
+ end
22
+
23
+ def update(integration_id, params={}, headers={})
24
+ params = ParamsBuilder.merge({
25
+ :integration_id => integration_id,
26
+ }, params)
27
+ method = ApiMethod.new(:put, "/integrations/:integration_id", params, headers, @parent)
28
+ json = @client.execute(method)
29
+ Integration.new(json, method)
30
+ end
31
+
32
+ end
33
+ end