gooddata 0.6.0 → 0.6.2

Sign up to get free protection for your applications and to get access to all the features.
Files changed (208) hide show
  1. checksums.yaml +13 -5
  2. data/.rubocop.yml +23 -0
  3. data/.travis.yml +9 -4
  4. data/CLI.md +439 -0
  5. data/Gemfile +0 -1
  6. data/README.md +2 -2
  7. data/Rakefile +60 -8
  8. data/doc/templates/default/module/setup.rb +1 -1
  9. data/examples.rb +2 -0
  10. data/gooddata +2 -0
  11. data/gooddata.gemspec +12 -8
  12. data/lib/gooddata.rb +0 -2
  13. data/lib/gooddata/bricks/base_downloader.rb +52 -47
  14. data/lib/gooddata/bricks/brick.rb +20 -31
  15. data/lib/gooddata/bricks/bricks.rb +1 -1
  16. data/lib/gooddata/bricks/middleware/base_middleware.rb +9 -7
  17. data/lib/gooddata/bricks/middleware/bench_middleware.rb +12 -10
  18. data/lib/gooddata/bricks/middleware/bulk_salesforce_middleware.rb +28 -28
  19. data/lib/gooddata/bricks/middleware/fs_upload_middleware.rb +20 -16
  20. data/lib/gooddata/bricks/middleware/gooddata_middleware.rb +21 -19
  21. data/lib/gooddata/bricks/middleware/logger_middleware.rb +10 -8
  22. data/lib/gooddata/bricks/middleware/restforce_middleware.rb +36 -34
  23. data/lib/gooddata/bricks/middleware/stdout_middleware.rb +11 -9
  24. data/lib/gooddata/bricks/middleware/twitter_middleware.rb +14 -12
  25. data/lib/gooddata/bricks/pipeline.rb +28 -0
  26. data/lib/gooddata/bricks/utils.rb +10 -8
  27. data/lib/gooddata/cli/cli.rb +1 -6
  28. data/lib/gooddata/cli/commands/auth_cmd.rb +1 -1
  29. data/lib/gooddata/cli/commands/console_cmd.rb +7 -5
  30. data/lib/gooddata/cli/commands/domain_cmd.rb +45 -0
  31. data/lib/gooddata/cli/commands/process_cmd.rb +42 -5
  32. data/lib/gooddata/cli/commands/project_cmd.rb +96 -36
  33. data/lib/gooddata/cli/commands/projects_cmd.rb +21 -0
  34. data/lib/gooddata/cli/commands/role_cmd.rb +28 -0
  35. data/lib/gooddata/cli/commands/run_ruby_cmd.rb +5 -5
  36. data/lib/gooddata/cli/commands/scaffold_cmd.rb +1 -1
  37. data/lib/gooddata/cli/commands/{profile_cmd.rb → user_cmd.rb} +7 -9
  38. data/lib/gooddata/cli/shared.rb +3 -2
  39. data/lib/gooddata/client.rb +16 -304
  40. data/lib/gooddata/commands/api.rb +13 -5
  41. data/lib/gooddata/commands/auth.rb +47 -40
  42. data/lib/gooddata/commands/base.rb +4 -2
  43. data/lib/gooddata/commands/commands.rb +1 -1
  44. data/lib/gooddata/commands/datasets.rb +20 -7
  45. data/lib/gooddata/commands/domain.rb +23 -0
  46. data/lib/gooddata/commands/process.rb +23 -117
  47. data/lib/gooddata/commands/project.rb +147 -0
  48. data/lib/gooddata/commands/projects.rb +8 -102
  49. data/lib/gooddata/commands/role.rb +26 -0
  50. data/lib/gooddata/commands/runners.rb +41 -38
  51. data/lib/gooddata/commands/scaffold.rb +46 -43
  52. data/lib/gooddata/commands/user.rb +33 -0
  53. data/lib/gooddata/connection.rb +43 -353
  54. data/lib/gooddata/core/connection.rb +389 -0
  55. data/lib/gooddata/core/core.rb +5 -4
  56. data/lib/gooddata/core/logging.rb +48 -0
  57. data/lib/gooddata/core/nil_logger.rb +13 -0
  58. data/lib/gooddata/core/project.rb +70 -0
  59. data/lib/gooddata/core/rest.rb +120 -0
  60. data/lib/gooddata/core/threaded.rb +14 -0
  61. data/lib/gooddata/core/user.rb +19 -0
  62. data/lib/gooddata/data/data.rb +2 -1
  63. data/lib/gooddata/data/guesser.rb +16 -12
  64. data/lib/gooddata/exceptions/command_failed.rb +1 -1
  65. data/lib/gooddata/exceptions/exceptions.rb +2 -1
  66. data/lib/gooddata/exceptions/no_project_error.rb +11 -0
  67. data/lib/gooddata/exceptions/project_not_found.rb +1 -1
  68. data/lib/gooddata/extensions/big_decimal.rb +6 -2
  69. data/lib/gooddata/extract.rb +10 -8
  70. data/lib/gooddata/goodzilla/goodzilla.rb +61 -59
  71. data/lib/gooddata/helpers.rb +15 -9
  72. data/lib/gooddata/models/account_settings.rb +124 -0
  73. data/lib/gooddata/models/attributes/anchor.rb +37 -0
  74. data/lib/gooddata/models/attributes/attributes.rb +8 -0
  75. data/lib/gooddata/models/attributes/date_attribute.rb +25 -0
  76. data/lib/gooddata/models/attributes/time_attribute.rb +24 -0
  77. data/lib/gooddata/models/columns/attribute.rb +71 -0
  78. data/lib/gooddata/models/columns/columns.rb +8 -0
  79. data/lib/gooddata/models/columns/date_column.rb +63 -0
  80. data/lib/gooddata/models/columns/fact_model.rb +54 -0
  81. data/lib/gooddata/models/columns/label.rb +55 -0
  82. data/lib/gooddata/models/columns/reference.rb +57 -0
  83. data/lib/gooddata/models/dashboard_builder.rb +26 -0
  84. data/lib/gooddata/models/data_result.rb +10 -9
  85. data/lib/gooddata/models/domain.rb +131 -0
  86. data/lib/gooddata/models/empty_result.rb +5 -8
  87. data/lib/gooddata/models/facts/facts.rb +8 -0
  88. data/lib/gooddata/models/facts/time_fact.rb +20 -0
  89. data/lib/gooddata/models/folders/attribute_folder.rb +20 -0
  90. data/lib/gooddata/models/folders/fact_folder.rb +20 -0
  91. data/lib/gooddata/models/folders/folders.rb +8 -0
  92. data/lib/gooddata/models/invitation.rb +78 -0
  93. data/lib/gooddata/models/links.rb +6 -6
  94. data/lib/gooddata/models/md_object.rb +25 -0
  95. data/lib/gooddata/models/metadata.rb +160 -62
  96. data/lib/gooddata/models/metadata/attribute.rb +81 -0
  97. data/lib/gooddata/models/metadata/column.rb +61 -0
  98. data/lib/gooddata/models/{dashboard.rb → metadata/dashboard.rb} +12 -7
  99. data/lib/gooddata/models/{data_set.rb → metadata/data_set.rb} +5 -4
  100. data/lib/gooddata/models/metadata/date_dimension.rb +26 -0
  101. data/lib/gooddata/models/metadata/display_form.rb +61 -0
  102. data/lib/gooddata/models/metadata/fact.rb +36 -0
  103. data/lib/gooddata/models/metadata/folder.rb +24 -0
  104. data/lib/gooddata/models/metadata/metadata.rb +8 -0
  105. data/lib/gooddata/models/metadata/metric.rb +197 -0
  106. data/lib/gooddata/models/metadata/report.rb +115 -0
  107. data/lib/gooddata/models/{report_definition.rb → metadata/report_definition.rb} +16 -10
  108. data/lib/gooddata/models/metadata/schema.rb +227 -0
  109. data/lib/gooddata/models/model.rb +38 -1339
  110. data/lib/gooddata/models/models.rb +5 -2
  111. data/lib/gooddata/models/module_constants.rb +29 -0
  112. data/lib/gooddata/models/process.rb +142 -13
  113. data/lib/gooddata/models/profile.rb +4 -6
  114. data/lib/gooddata/models/project.rb +406 -136
  115. data/lib/gooddata/models/project_blueprint.rb +221 -0
  116. data/lib/gooddata/models/project_builder.rb +136 -0
  117. data/lib/gooddata/models/project_creator.rb +138 -0
  118. data/lib/gooddata/models/project_metadata.rb +11 -10
  119. data/lib/gooddata/models/project_role.rb +92 -0
  120. data/lib/gooddata/models/references/date_reference.rb +44 -0
  121. data/lib/gooddata/models/references/references.rb +8 -0
  122. data/lib/gooddata/models/references/time_reference.rb +13 -0
  123. data/lib/gooddata/models/report_data_result.rb +11 -11
  124. data/lib/gooddata/models/schedule.rb +284 -0
  125. data/lib/gooddata/models/schema_blueprint.rb +158 -0
  126. data/lib/gooddata/models/schema_builder.rb +81 -0
  127. data/lib/gooddata/models/tab_builder.rb +23 -0
  128. data/lib/gooddata/models/user.rb +165 -0
  129. data/lib/gooddata/version.rb +1 -1
  130. data/lib/templates/project/data/devs.csv +1 -1
  131. data/lib/templates/project/data/repos.csv +1 -1
  132. data/lib/templates/project/model/model.rb.erb +7 -11
  133. data/spec/bricks/bricks_spec.rb +2 -0
  134. data/spec/data/test-ci-data.csv +2 -0
  135. data/spec/data/test_project_model_spec.json +7 -27
  136. data/spec/helpers/blueprint_helper.rb +2 -0
  137. data/spec/helpers/cli_helper.rb +2 -0
  138. data/spec/helpers/connection_helper.rb +14 -1
  139. data/spec/helpers/project_helper.rb +16 -0
  140. data/spec/helpers/schema_helper.rb +16 -0
  141. data/spec/integration/command_projects_spec.rb +7 -7
  142. data/spec/integration/create_from_template_spec.rb +2 -2
  143. data/spec/integration/full_project_spec.rb +160 -7
  144. data/spec/integration/partial_md_export_import_spec.rb +3 -3
  145. data/spec/logging_in_logging_out_spec.rb +2 -1
  146. data/spec/spec_helper.rb +26 -4
  147. data/spec/unit/bricks/bricks_spec.rb +15 -7
  148. data/spec/unit/bricks/middleware/bench_middleware_spec.rb +2 -0
  149. data/spec/unit/bricks/middleware/bulk_salesforce_middleware_spec.rb +2 -0
  150. data/spec/unit/bricks/middleware/gooddata_middleware_spec.rb +2 -0
  151. data/spec/unit/bricks/middleware/logger_middleware_spec.rb +2 -0
  152. data/spec/unit/bricks/middleware/restforce_middleware_spec.rb +2 -0
  153. data/spec/unit/bricks/middleware/stdout_middleware_spec.rb +2 -0
  154. data/spec/unit/bricks/middleware/twitter_middleware_spec.rb +2 -0
  155. data/spec/unit/cli/cli_spec.rb +2 -0
  156. data/spec/unit/cli/commands/cmd_api_spec.rb +23 -15
  157. data/spec/unit/cli/commands/cmd_auth_spec.rb +8 -4
  158. data/spec/unit/cli/commands/cmd_domain_spec.rb +82 -0
  159. data/spec/unit/cli/commands/cmd_process_spec.rb +29 -13
  160. data/spec/unit/cli/commands/cmd_project_spec.rb +51 -30
  161. data/spec/unit/cli/commands/cmd_role_spec.rb +44 -0
  162. data/spec/unit/cli/commands/cmd_run_ruby_spec.rb +8 -4
  163. data/spec/unit/cli/commands/cmd_scaffold_spec.rb +48 -11
  164. data/spec/unit/cli/commands/cmd_user_spec.rb +29 -0
  165. data/spec/unit/commands/command_api_spec.rb +1 -1
  166. data/spec/unit/commands/command_auth_spec.rb +100 -18
  167. data/spec/unit/commands/command_dataset_spec.rb +4 -0
  168. data/spec/unit/commands/command_process_spec.rb +9 -4
  169. data/spec/unit/commands/command_projects_spec.rb +10 -6
  170. data/spec/unit/commands/command_scaffold_spec.rb +5 -1
  171. data/spec/unit/commands/command_user_spec.rb +22 -0
  172. data/spec/unit/core/connection_spec.rb +35 -6
  173. data/spec/unit/core/logging_spec.rb +65 -0
  174. data/spec/unit/core/nil_logger_spec.rb +9 -0
  175. data/spec/unit/core/project_spec.rb +51 -0
  176. data/spec/unit/core/rest_spec.rb +33 -0
  177. data/spec/unit/data/guesser_spec.rb +5 -0
  178. data/spec/unit/godzilla/goodzilla_spec.rb +2 -0
  179. data/spec/unit/models/account_settings_spec.rb +28 -0
  180. data/spec/unit/models/anchor_spec.rb +32 -0
  181. data/spec/unit/models/attribute_column_spec.rb +7 -0
  182. data/spec/unit/models/domain_spec.rb +45 -0
  183. data/spec/unit/models/invitation_spec.rb +13 -0
  184. data/spec/unit/models/md_object_spec.rb +47 -0
  185. data/spec/unit/models/metric.rb +92 -0
  186. data/spec/unit/{model → models}/model_spec.rb +9 -7
  187. data/spec/unit/models/project_blueprint_spec.rb +202 -0
  188. data/spec/unit/models/project_creator.rb +73 -0
  189. data/spec/unit/models/project_role_spec.rb +90 -0
  190. data/spec/unit/models/project_spec.rb +143 -0
  191. data/spec/unit/models/schedule_spec.rb +491 -0
  192. data/spec/unit/{model → models}/schema_builder_spec.rb +2 -0
  193. data/spec/unit/{model → models}/tools_spec.rb +13 -7
  194. data/spec/unit/models/user_spec.rb +16 -0
  195. data/test/test_upload.rb +2 -0
  196. metadata +189 -86
  197. data/lib/gooddata/commands/profile.rb +0 -11
  198. data/lib/gooddata/models/attribute.rb +0 -29
  199. data/lib/gooddata/models/display_form.rb +0 -9
  200. data/lib/gooddata/models/fact.rb +0 -19
  201. data/lib/gooddata/models/metric.rb +0 -99
  202. data/lib/gooddata/models/report.rb +0 -89
  203. data/spec/data/blueprint_valid.json +0 -37
  204. data/spec/unit/cli/commands/cmd_profile_spec.rb +0 -16
  205. data/spec/unit/commands/command_profile_spec.rb +0 -18
  206. data/spec/unit/core/core_spec.rb +0 -7
  207. data/spec/unit/model/blueprint_spec.rb +0 -132
  208. data/spec/unit/model/project_blueprint_spec.rb +0 -44
@@ -0,0 +1,389 @@
1
+ # encoding: UTF-8
2
+
3
+ require 'multi_json'
4
+ require 'rest-client'
5
+
6
+ require_relative '../version'
7
+
8
+ module GoodData
9
+ # # GoodData HTTP wrapper
10
+ #
11
+ # Provides a convenient HTTP wrapper for talking with the GoodData API.
12
+ #
13
+ # Remember that the connection is shared amongst the entire application.
14
+ # Therefore you can't be logged in to more than _one_ GoodData account.
15
+ # per session. Simultaneous connections to multiple GoodData accounts is not
16
+ # supported at this time.
17
+ #
18
+ # The GoodData API is a RESTful API that communicates using JSON. This wrapper
19
+ # makes sure that the session is stored between requests and that the JSON is
20
+ # parsed both when sending and receiving.
21
+ #
22
+ # ## Usage
23
+ #
24
+ # Before a connection can be made to the GoodData API, you have to supply the user credentials like this:
25
+ #
26
+ # Connection.new(username, password)
27
+ #
28
+ # To send a HTTP request use either the get, post or delete methods documented below.
29
+ #
30
+ class Connection
31
+ DEFAULT_URL = 'https://secure.gooddata.com'
32
+ LOGIN_PATH = '/gdc/account/login'
33
+ TOKEN_PATH = '/gdc/account/token'
34
+
35
+ attr_reader(:auth_token, :url)
36
+ attr_accessor :status, :options
37
+
38
+ # Options:
39
+ # * :tries - Number of retries to perform. Defaults to 1.
40
+ # * :on - The Exception on which a retry will be performed. Defaults to Exception, which retries on any Exception.
41
+ #
42
+ # ### Example
43
+ #
44
+ # retryable(:tries => 1, :on => OpenURI::HTTPError) do
45
+ # # your code here
46
+ # end
47
+ #
48
+ def retryable(options = {}, &block)
49
+ opts = { :tries => 1, :on => Exception }.merge(options)
50
+
51
+ retry_exception, retries = opts[:on], opts[:tries]
52
+
53
+ begin
54
+ return yield
55
+ rescue retry_exception
56
+ retry if (retries -= 1) > 0
57
+ end
58
+
59
+ yield
60
+ end
61
+
62
+ # Set the GoodData account credentials.
63
+ #
64
+ # This have to be performed before any calls to the API.
65
+ #
66
+ # @param username The GoodData account username
67
+ # @param password The GoodData account password
68
+ #
69
+ def initialize(username, password, options = {})
70
+ @status = :not_connected
71
+ @username = username
72
+ @password = password
73
+ @url = options[:server] || DEFAULT_URL
74
+ @auth_token = options[:gdc_temporary_token]
75
+ @options = options
76
+
77
+ @headers = options[:headers] || {}
78
+
79
+ default_headers = {
80
+ :content_type => :json,
81
+ :accept => [:json, :zip],
82
+ :user_agent => GoodData.gem_version_string
83
+ }
84
+ default_headers.merge! @headers
85
+
86
+ @server = RestClient::Resource.new @url,
87
+ :timeout => @options[:timeout],
88
+ :headers => default_headers
89
+
90
+ @server = create_server_connection(@url, @options)
91
+ end
92
+
93
+ # Returns the user JSON object of the currently logged in GoodData user account.
94
+ def user
95
+ ensure_connection
96
+ @user
97
+ end
98
+
99
+ # Performs a HTTP GET request.
100
+ #
101
+ # Retuns the JSON response formatted as a Hash object.
102
+ #
103
+ # @param path The HTTP path on the GoodData server (must be prefixed with a forward slash)
104
+ #
105
+ # ### Examples
106
+ #
107
+ # Connection.new(username, password).get '/gdc/projects'
108
+ #
109
+ def get(path, options = {})
110
+ GoodData.logger.debug "GET #{@server}#{path}"
111
+ ensure_connection
112
+ b = proc { @server[path].get cookies }
113
+ process_response(options, &b)
114
+ end
115
+
116
+ # Performs a HTTP POST request.
117
+ #
118
+ # Retuns the JSON response formatted as a Hash object.
119
+ #
120
+ # @param path The HTTP path on the GoodData server (must be prefixed with a forward slash)
121
+ # @param data The payload data in the format of a Hash object
122
+ #
123
+ # ### Examples
124
+ #
125
+ # Connection.new(username, password).post '/gdc/projects', { ... }
126
+ #
127
+ def post(path, data, options = {})
128
+ GoodData.logger.debug("POST #{@server}#{path}, payload: #{scrub_params(data, [:password, :login, :authorizationToken])}")
129
+ ensure_connection
130
+ payload = data.is_a?(Hash) ? data.to_json : data
131
+ b = proc { @server[path].post payload, cookies }
132
+ process_response(options, &b)
133
+ end
134
+
135
+ # Performs a HTTP PUT request.
136
+ #
137
+ # Retuns the JSON response formatted as a Hash object.
138
+ #
139
+ # @param path The HTTP path on the GoodData server (must be prefixed with a forward slash)
140
+ # @param data The payload data in the format of a Hash object
141
+ #
142
+ # ### Examples
143
+ #
144
+ # Connection.new(username, password).put '/gdc/projects', { ... }
145
+ #
146
+ def put(path, data, options = {})
147
+ payload = data.is_a?(Hash) ? data.to_json : data
148
+ GoodData.logger.debug "PUT #{@server}#{path}, payload: #{payload}"
149
+ ensure_connection
150
+ b = proc { @server[path].put payload, cookies }
151
+ process_response(options, &b)
152
+ end
153
+
154
+ # Performs a HTTP DELETE request.
155
+ #
156
+ # Retuns the JSON response formatted as a Hash object.
157
+ #
158
+ # @param path The HTTP path on the GoodData server (must be prefixed with a forward slash)
159
+ #
160
+ # ### Examples
161
+ #
162
+ # Connection.new(username, password).delete '/gdc/project/1'
163
+ #
164
+ def delete(path, options = {})
165
+ GoodData.logger.debug "DELETE #{@server}#{path}"
166
+ ensure_connection
167
+ b = proc { @server[path].delete cookies }
168
+ process_response(options, &b)
169
+ end
170
+
171
+ # Get the cookies associated with the current connection.
172
+ def cookies
173
+ @cookies ||= { :cookies => {} }
174
+ end
175
+
176
+ # Set the cookies used when communicating with the GoodData API.
177
+ def merge_cookies!(cookies)
178
+ self.cookies
179
+ @cookies[:cookies].merge! cookies
180
+ end
181
+
182
+ # Returns true if a connection have been established to the GoodData API
183
+ # and the login was successful.
184
+ def logged_in?
185
+ @status == :logged_in
186
+ end
187
+
188
+ def url=(url = nil)
189
+ @url = url || DEFAULT_URL
190
+ @server = create_server_connection(@url, @options)
191
+ end
192
+
193
+ # The connection will automatically be established once it's needed, which it
194
+ # usually is when either the user, get, post or delete method is called. If you
195
+ # want to force a connection (or a re-connect) you can use this method.
196
+ def connect!
197
+ connect
198
+ end
199
+
200
+ # Uploads a file to GoodData server
201
+ # /uploads/ resources are special in that they use a different
202
+ # host and a basic authentication.
203
+ def upload(file, options = {})
204
+ ensure_connection
205
+
206
+ dir = options[:directory] || ''
207
+ staging_uri = options[:staging_url].to_s
208
+ url = dir.empty? ? staging_uri : URI.join(staging_uri, "#{dir}/").to_s
209
+
210
+ # Make a directory, if needed
211
+ unless dir.empty?
212
+ method = :get
213
+ GoodData.logger.debug "#{method}: #{url}"
214
+ begin
215
+ # first check if it does exits
216
+ RestClient::Request.execute({
217
+ :method => method,
218
+ :url => url,
219
+ :timeout => @options[:timeout],
220
+ :headers => {
221
+ :user_agent => GoodData.gem_version_string
222
+ }
223
+ }.merge(cookies)
224
+ )
225
+ rescue RestClient::Exception => e
226
+ if e.http_code == 404
227
+ method = :mkcol
228
+ GoodData.logger.debug "#{method}: #{url}"
229
+ RestClient::Request.execute({
230
+ :method => method,
231
+ :url => url,
232
+ :timeout => @options[:timeout],
233
+ :headers => {
234
+ :user_agent => GoodData.gem_version_string
235
+ }
236
+ }.merge(cookies))
237
+ end
238
+ end
239
+ end
240
+
241
+ payload = options[:stream] ? 'file' : File.read(file)
242
+ filename = options[:filename] || options[:stream] ? 'randome-filename.txt' : File.basename(file)
243
+
244
+ # Upload the file
245
+ # puts "uploading the file #{URI.join(url, filename).to_s}"
246
+ req = RestClient::Request.new(
247
+ :method => :put,
248
+ :url => URI.join(url, filename).to_s,
249
+ :timeout => @options[:timeout],
250
+ :headers => {
251
+ :user_agent => GoodData.gem_version_string
252
+ },
253
+ :payload => payload,
254
+ :raw_response => true,
255
+ :user => @username,
256
+ :password => @password
257
+ )
258
+ # .merge(cookies))
259
+ req.execute
260
+ true
261
+ end
262
+
263
+ def download(what, where, options = {})
264
+ staging_uri = options[:staging_url].to_s
265
+ url = staging_uri + what
266
+ req = RestClient::Request.new(
267
+ :method => 'GET',
268
+ :url => url,
269
+ :user => @username,
270
+ :password => @password)
271
+
272
+ if where.is_a?(String)
273
+ File.open(where, 'w') do |f|
274
+ req.execute do |chunk, x, y|
275
+ f.write chunk
276
+ end
277
+ end
278
+ else
279
+ # Assume it is a IO stream
280
+ req.execute do |chunk, x, y|
281
+ where.write chunk
282
+ end
283
+ end
284
+ end
285
+
286
+ def connected?
287
+ @status == :logged_in
288
+ end
289
+
290
+ def disconnect
291
+ if connected? && GoodData.connection.user['state']
292
+ GoodData.delete(GoodData.connection.user['state'])
293
+ @status = :not_connected
294
+ end
295
+ end
296
+
297
+ private
298
+
299
+ def create_server_connection(url, options)
300
+ RestClient::Resource.new url,
301
+ :timeout => options[:timeout],
302
+ :headers => {
303
+ :content_type => :json,
304
+ :accept => [:json, :zip],
305
+ :user_agent => GoodData.gem_version_string
306
+ }
307
+ end
308
+
309
+ def ensure_connection
310
+ connect if @status == :not_connected
311
+ end
312
+
313
+ def connect
314
+ GoodData.logger.info 'Connecting to GoodData...'
315
+ @status = :connecting
316
+ authenticate
317
+ end
318
+
319
+ def authenticate
320
+ credentials = {
321
+ 'postUserLogin' => {
322
+ 'login' => @username,
323
+ 'password' => @password,
324
+ 'remember' => 1
325
+ }
326
+ }
327
+ GoodData.logger.debug 'Logging in...'
328
+ @user = post(LOGIN_PATH, credentials, :dont_reauth => true)['userLogin']
329
+ refresh_token :dont_reauth => true # avoid infinite loop if refresh_token fails with 401
330
+
331
+ @status = :logged_in
332
+ end
333
+
334
+ def process_response(options = {}, &block)
335
+ begin
336
+ response = block.call
337
+ rescue RestClient::Unauthorized
338
+ raise $ERROR_INFO if options[:dont_reauth]
339
+ refresh_token
340
+ response = block.call
341
+ end
342
+ merge_cookies! response.cookies
343
+ content_type = response.headers[:content_type]
344
+ return response if options[:process] == false
345
+
346
+ if content_type == 'application/json' || content_type == 'application/json;charset=UTF-8'
347
+ result = response.to_str == '""' ? {} : MultiJson.load(response.to_str)
348
+ GoodData.logger.debug "Response: #{result.inspect}"
349
+ elsif content_type == 'application/zip'
350
+ result = response
351
+ GoodData.logger.debug 'Response: a zipped stream'
352
+ elsif response.headers[:content_length].to_s == '0'
353
+ result = nil
354
+ GoodData.logger.debug 'Response: Empty response possibly 204'
355
+ elsif response.code == 204
356
+ result = nil
357
+ GoodData.logger.debug 'Response: 204 no content'
358
+ else
359
+ fail "Unsupported response content type '%s':\n%s" % [content_type, response.to_str[0..127]]
360
+ end
361
+ result
362
+ rescue RestClient::Exception => e
363
+ GoodData.logger.debug "Response: #{e.response}"
364
+ raise $ERROR_INFO
365
+ end
366
+
367
+ def refresh_token(options = {})
368
+ GoodData.logger.debug 'Getting authentication token...'
369
+ begin
370
+ get TOKEN_PATH, :dont_reauth => true # avoid infinite loop GET fails with 401
371
+ rescue RestClient::Unauthorized
372
+ raise $ERROR_INFO if options[:dont_reauth]
373
+ authenticate
374
+ end
375
+ end
376
+
377
+ def scrub_params(params, keys)
378
+ keys = keys.reduce([]) { |a, e| a.concat([e.to_s, e.to_sym]) }
379
+
380
+ new_params = Marshal.load(Marshal.dump(params))
381
+ GoodData::Helpers.hash_dfs(new_params) do |k, key|
382
+ keys.each do |key_to_scrub|
383
+ k[key_to_scrub] = ('*' * k[key_to_scrub].length) if k && k.key?(key_to_scrub) && k[key_to_scrub]
384
+ end
385
+ end
386
+ new_params
387
+ end
388
+ end
389
+ end
@@ -1,7 +1,8 @@
1
1
  # encoding: UTF-8
2
2
 
3
- module GoodData
4
- # Core of GoodData Gem
5
- class Core
6
- end
3
+ require 'pathname'
4
+
5
+ base = Pathname(__FILE__).dirname.expand_path
6
+ Dir.glob(base + '*.rb').each do |file|
7
+ require file
7
8
  end
@@ -0,0 +1,48 @@
1
+ # encoding: UTF-8
2
+
3
+ require_relative 'nil_logger'
4
+ require_relative 'threaded'
5
+
6
+ module GoodData
7
+ class << self
8
+ attr_writer :logger
9
+
10
+ # Turn logging on
11
+ #
12
+ # ### Example
13
+ #
14
+ # GoodData.logging_on
15
+ #
16
+ def logging_on
17
+ GoodData.logger = Logger.new(STDOUT) if logger.is_a? NilLogger
18
+ end
19
+
20
+ # Turn logging on
21
+ #
22
+ # ### Example
23
+ #
24
+ # GoodData.logging_off
25
+ #
26
+ def logging_off
27
+ GoodData.logger = NilLogger.new
28
+ end
29
+
30
+ def logging_on?
31
+ !GoodData.logger.instance_of?(NilLogger)
32
+ end
33
+
34
+ # Returns the logger instance. The default implementation
35
+ # does not log anything
36
+ # For some serious logging, set the logger instance using
37
+ # the logger= method
38
+ #
39
+ # ### Example
40
+ #
41
+ # require 'logger'
42
+ # GoodData.logger = Logger.new(STDOUT)
43
+ #
44
+ def logger
45
+ @logger ||= NilLogger.new
46
+ end
47
+ end
48
+ end