gooddata 0.6.18 → 0.6.19

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 (133) hide show
  1. checksums.yaml +4 -4
  2. data/.gitignore +2 -1
  3. data/.travis.yml +8 -19
  4. data/Guardfile +5 -0
  5. data/README.md +1 -3
  6. data/bin/gooddata +1 -1
  7. data/gooddata.gemspec +6 -4
  8. data/lib/gooddata.rb +1 -1
  9. data/lib/gooddata/bricks/middleware/aws_middleware.rb +24 -0
  10. data/lib/gooddata/cli/commands/console_cmd.rb +1 -1
  11. data/lib/gooddata/cli/commands/project_cmd.rb +29 -9
  12. data/lib/gooddata/cli/hooks.rb +9 -3
  13. data/lib/gooddata/commands/datawarehouse.rb +1 -7
  14. data/lib/gooddata/commands/project.rb +4 -3
  15. data/lib/gooddata/core/logging.rb +14 -2
  16. data/lib/gooddata/exceptions/execution_limit_exceeded.rb +9 -0
  17. data/lib/gooddata/exceptions/uncomputable_report.rb +8 -0
  18. data/lib/gooddata/exceptions/validation_error.rb +1 -1
  19. data/lib/gooddata/goodzilla/goodzilla.rb +5 -1
  20. data/lib/gooddata/helpers/data_helper.rb +40 -9
  21. data/lib/gooddata/mixins/md_finders.rb +35 -0
  22. data/lib/gooddata/models/blueprint/anchor_field.rb +46 -0
  23. data/lib/gooddata/models/blueprint/attribute_field.rb +25 -0
  24. data/lib/gooddata/models/blueprint/blueprint.rb +7 -0
  25. data/lib/gooddata/models/blueprint/blueprint_field.rb +66 -0
  26. data/lib/gooddata/models/{dashboard_builder.rb → blueprint/dashboard_builder.rb} +0 -0
  27. data/lib/gooddata/models/{schema_blueprint.rb → blueprint/dataset_blueprint.rb} +176 -117
  28. data/lib/gooddata/models/blueprint/date_dimension.rb +10 -0
  29. data/lib/gooddata/models/blueprint/fact_field.rb +16 -0
  30. data/lib/gooddata/models/blueprint/label_field.rb +39 -0
  31. data/lib/gooddata/models/{project_blueprint.rb → blueprint/project_blueprint.rb} +366 -168
  32. data/lib/gooddata/models/blueprint/project_builder.rb +79 -0
  33. data/lib/gooddata/models/blueprint/reference_field.rb +39 -0
  34. data/lib/gooddata/models/blueprint/schema_blueprint.rb +156 -0
  35. data/lib/gooddata/models/blueprint/schema_builder.rb +85 -0
  36. data/lib/gooddata/models/{to_manifest.rb → blueprint/to_manifest.rb} +25 -20
  37. data/lib/gooddata/models/{to_wire.rb → blueprint/to_wire.rb} +33 -52
  38. data/lib/gooddata/models/datawarehouse.rb +2 -2
  39. data/lib/gooddata/models/domain.rb +3 -2
  40. data/lib/gooddata/models/execution.rb +2 -2
  41. data/lib/gooddata/models/execution_detail.rb +7 -2
  42. data/lib/gooddata/models/from_wire.rb +60 -71
  43. data/lib/gooddata/models/from_wire_parse.rb +125 -125
  44. data/lib/gooddata/models/metadata.rb +14 -0
  45. data/lib/gooddata/models/metadata/dashboard.rb +2 -2
  46. data/lib/gooddata/models/metadata/label.rb +1 -1
  47. data/lib/gooddata/models/metadata/report.rb +6 -5
  48. data/lib/gooddata/models/metadata/report_definition.rb +44 -59
  49. data/lib/gooddata/models/model.rb +131 -43
  50. data/lib/gooddata/models/process.rb +13 -11
  51. data/lib/gooddata/models/profile.rb +12 -1
  52. data/lib/gooddata/models/project.rb +223 -19
  53. data/lib/gooddata/models/project_creator.rb +4 -15
  54. data/lib/gooddata/models/schedule.rb +1 -0
  55. data/lib/gooddata/models/user_filters/user_filter_builder.rb +2 -2
  56. data/lib/gooddata/rest/client.rb +18 -18
  57. data/lib/gooddata/rest/connection.rb +113 -94
  58. data/lib/gooddata/version.rb +1 -1
  59. data/lib/templates/project/model/model.rb.erb +15 -16
  60. data/spec/data/blueprints/additional_dataset_module.json +32 -0
  61. data/spec/data/blueprints/big_blueprint_not_pruned.json +2079 -0
  62. data/spec/data/blueprints/invalid_blueprint.json +103 -0
  63. data/spec/data/blueprints/m_n_model.json +104 -0
  64. data/spec/data/blueprints/model_module.json +25 -0
  65. data/spec/data/blueprints/test_blueprint.json +38 -0
  66. data/spec/data/blueprints/test_project_model_spec.json +106 -0
  67. data/spec/data/gd_gse_data_manifest.json +34 -34
  68. data/spec/data/manifests/test_blueprint.json +32 -0
  69. data/spec/data/{manifest_test_project.json → manifests/test_project.json} +9 -18
  70. data/spec/data/wire_models/test_blueprint.json +63 -0
  71. data/spec/data/wire_test_project.json +5 -5
  72. data/spec/environment/default.rb +33 -0
  73. data/spec/environment/develop.rb +26 -0
  74. data/spec/environment/environment.rb +14 -0
  75. data/spec/environment/hotfix.rb +17 -0
  76. data/spec/environment/production.rb +31 -0
  77. data/spec/environment/release.rb +17 -0
  78. data/spec/helpers/blueprint_helper.rb +10 -7
  79. data/spec/helpers/cli_helper.rb +24 -22
  80. data/spec/helpers/connection_helper.rb +27 -25
  81. data/spec/helpers/crypto_helper.rb +7 -5
  82. data/spec/helpers/csv_helper.rb +5 -3
  83. data/spec/helpers/process_helper.rb +15 -10
  84. data/spec/helpers/project_helper.rb +40 -33
  85. data/spec/helpers/schedule_helper.rb +15 -9
  86. data/spec/helpers/spec_helper.rb +11 -0
  87. data/spec/integration/blueprint_updates_spec.rb +93 -0
  88. data/spec/integration/command_datawarehouse_spec.rb +2 -1
  89. data/spec/integration/command_projects_spec.rb +9 -8
  90. data/spec/integration/create_from_template_spec.rb +1 -1
  91. data/spec/integration/create_project_spec.rb +1 -1
  92. data/spec/integration/full_process_schedule_spec.rb +1 -1
  93. data/spec/integration/full_project_spec.rb +91 -30
  94. data/spec/integration/over_to_user_filters_spec.rb +24 -28
  95. data/spec/integration/partial_md_export_import_spec.rb +4 -4
  96. data/spec/integration/project_spec.rb +1 -1
  97. data/spec/integration/rest_spec.rb +1 -1
  98. data/spec/integration/user_filters_spec.rb +19 -24
  99. data/spec/integration/variables_spec.rb +7 -9
  100. data/spec/logging_in_logging_out_spec.rb +1 -1
  101. data/spec/spec_helper.rb +10 -1
  102. data/spec/unit/bricks/middleware/aws_middelware_spec.rb +47 -0
  103. data/spec/unit/core/connection_spec.rb +2 -2
  104. data/spec/unit/core/logging_spec.rb +12 -4
  105. data/spec/unit/helpers/data_helper_spec.rb +60 -0
  106. data/spec/unit/models/blueprint/attributes_spec.rb +24 -0
  107. data/spec/unit/models/blueprint/dataset_spec.rb +116 -0
  108. data/spec/unit/models/blueprint/labels_spec.rb +39 -0
  109. data/spec/unit/models/blueprint/project_blueprint_spec.rb +643 -0
  110. data/spec/unit/models/blueprint/reference_spec.rb +24 -0
  111. data/spec/unit/models/{schema_builder_spec.rb → blueprint/schema_builder_spec.rb} +12 -4
  112. data/spec/unit/models/blueprint/to_wire_spec.rb +169 -0
  113. data/spec/unit/models/domain_spec.rb +13 -2
  114. data/spec/unit/models/from_wire_spec.rb +277 -98
  115. data/spec/unit/models/metadata_spec.rb +22 -4
  116. data/spec/unit/models/model_spec.rb +49 -39
  117. data/spec/unit/models/profile_spec.rb +1 -0
  118. data/spec/unit/models/project_spec.rb +7 -7
  119. data/spec/unit/models/schedule_spec.rb +20 -0
  120. data/spec/unit/models/to_manifest_spec.rb +31 -11
  121. data/spec/unit/rest/polling_spec.rb +86 -0
  122. metadata +102 -30
  123. data/lib/gooddata/models/project_builder.rb +0 -136
  124. data/lib/gooddata/models/schema_builder.rb +0 -77
  125. data/out.txt +0 -0
  126. data/spec/data/additional_dataset_module.json +0 -18
  127. data/spec/data/blueprint_invalid.json +0 -38
  128. data/spec/data/m_n_model/blueprint.json +0 -76
  129. data/spec/data/model_module.json +0 -18
  130. data/spec/data/test_project_model_spec.json +0 -76
  131. data/spec/unit/models/attribute_column_spec.rb +0 -7
  132. data/spec/unit/models/project_blueprint_spec.rb +0 -239
  133. data/spec/unit/models/to_wire_spec.rb +0 -71
@@ -1,7 +1,7 @@
1
1
  # encoding: UTF-8
2
2
 
3
3
  require_relative 'project'
4
- require_relative 'project_blueprint'
4
+ require_relative 'blueprint/project_blueprint'
5
5
 
6
6
  require 'open-uri'
7
7
 
@@ -10,19 +10,16 @@ module GoodData
10
10
  class ProjectCreator
11
11
  class << self
12
12
  def migrate(opts = {})
13
- opts = { client: GoodData.connection, project: GoodData.project }.merge(opts)
13
+ opts = { client: GoodData.connection }.merge(opts)
14
14
  client = opts[:client]
15
15
  fail ArgumentError, 'No :client specified' if client.nil?
16
16
 
17
17
  spec = opts[:spec] || fail('You need to provide spec for migration')
18
18
  bp = ProjectBlueprint.new(spec)
19
- spec = bp.to_hash
20
-
21
19
  fail GoodData::ValidationError, "Blueprint is invalid #{bp.validate.inspect}" unless bp.valid?
20
+ spec = bp.to_hash
22
21
 
23
- token = opts[:token]
24
- project = opts[:project] || GoodData::Project.create(:title => spec[:title], :auth_token => token, :client => client)
25
- fail('You need to specify token for project creation') if token.nil? && project.nil?
22
+ project = opts[:project] || client.create_project(opts.merge(:title => spec[:title], :client => client, :environment => opts[:environment]))
26
23
 
27
24
  begin
28
25
  migrate_datasets(spec, opts.merge(project: project, client: client))
@@ -46,10 +43,7 @@ module GoodData
46
43
 
47
44
  project = client.projects(p)
48
45
  fail ArgumentError, 'Wrong :project specified' if project.nil?
49
-
50
46
  bp = ProjectBlueprint.new(spec)
51
- # schema = Schema.load(schema) unless schema.respond_to?(:to_maql_create)
52
- # project = GoodData.project unless project
53
47
  uri = "/gdc/projects/#{project.pid}/model/diff"
54
48
  result = client.post(uri, bp.to_wire)
55
49
 
@@ -72,11 +66,6 @@ module GoodData
72
66
  result = project.execute_maql(chunk)
73
67
  fail 'Creating dataset failed' if result['wTaskStatus']['status'] == 'ERROR'
74
68
  end
75
- bp.datasets.zip(GoodData::Model::ToManifest.to_manifest(bp.to_hash)).each do |ds|
76
- dataset = ds[0]
77
- manifest = ds[1]
78
- GoodData::ProjectMetadata["manifest_#{dataset.name}", :client => client, :project => project] = manifest.to_json
79
- end
80
69
  end
81
70
  chunks
82
71
  end
@@ -103,6 +103,7 @@ module GoodData
103
103
 
104
104
  schedule = c.create(GoodData::Schedule, GoodData::Helpers.stringify_keys_deep!(SCHEDULE_TEMPLATE.deep_dup), client: c, project: p)
105
105
 
106
+ schedule.name = options[:name]
106
107
  schedule.hidden_params = options[:hidden_params]
107
108
  schedule.set_trigger(trigger)
108
109
  schedule.params = default_opts[:params].merge(options[:params] || {})
@@ -216,9 +216,9 @@ module GoodData
216
216
  elsif filter[:over] && filter[:to]
217
217
  over = attr_cache[filter[:over]]
218
218
  to = attr_cache[filter[:to]]
219
- "([#{label.attribute_uri}] IN (#{ element_uris.compact.sort.map { |e| '[' + e + ']' }.join(', ') })) OVER [#{over && over.uri}] TO [#{to && to.uri}]"
219
+ "([#{label.attribute_uri}] IN (#{element_uris.compact.sort.map { |e| '[' + e + ']' }.join(', ')})) OVER [#{over && over.uri}] TO [#{to && to.uri}]"
220
220
  else
221
- "[#{label.attribute_uri}] IN (#{ element_uris.compact.sort.map { |e| '[' + e + ']' }.join(', ') })"
221
+ "[#{label.attribute_uri}] IN (#{element_uris.compact.sort.map { |e| '[' + e + ']' }.join(', ')})"
222
222
  end
223
223
  [expression, errors]
224
224
  end
@@ -61,18 +61,21 @@ module GoodData
61
61
  # @param username [String] Username to be used for authentication
62
62
  # @param password [String] Password to be used for authentication
63
63
  # @return [GoodData::Rest::Client] Client
64
- def connect(username, password, opts = { :verify_ssl => true })
64
+ def connect(username, password, opts = { verify_ssl: true })
65
65
  if username.nil? && password.nil?
66
66
  username = ENV['GD_GEM_USER']
67
67
  password = ENV['GD_GEM_PASSWORD']
68
68
  end
69
69
 
70
+ username = username.symbolize_keys if username.is_a?(Hash)
71
+
70
72
  new_opts = opts.dup
71
73
  if username.is_a?(Hash) && username.key?(:sst_token)
72
- new_opts[:sst_token] = username[:sst_token]
74
+ new_opts = username
73
75
  elsif username.is_a? Hash
74
76
  new_opts[:username] = username[:login] || username[:user] || username[:username]
75
77
  new_opts[:password] = username[:password]
78
+ new_opts[:verify_ssl] = username[:verify_ssl] if username[:verify_ssl] == false || !username[:verify_ssl].blank?
76
79
  elsif username.nil? && password.nil? && (opts.nil? || opts.empty?)
77
80
  new_opts = Helpers::AuthHelper.read_credentials
78
81
  else
@@ -100,14 +103,14 @@ module GoodData
100
103
  end
101
104
 
102
105
  def disconnect
103
- if @@instance # rubocop:disable ClassVars, Style/GuardClause
104
- @@instance.disconnect # rubocop:disable ClassVars
106
+ if @@instance # rubocop:disable Style/GuardClause
107
+ @@instance.disconnect
105
108
  @@instance = nil # rubocop:disable ClassVars
106
109
  end
107
110
  end
108
111
 
109
112
  def connection
110
- @@instance # rubocop:disable ClassVars
113
+ @@instance
111
114
  end
112
115
 
113
116
  # Retry block if exception thrown
@@ -146,7 +149,7 @@ module GoodData
146
149
  end
147
150
 
148
151
  def create_project_from_blueprint(blueprint, options = {})
149
- GoodData::Model::ProjectCreator.migrate(spec: blueprint, token: options[:auth_token], client: self)
152
+ GoodData::Model::ProjectCreator.migrate(options.merge(spec: blueprint, client: self))
150
153
  end
151
154
 
152
155
  def domain(domain_name)
@@ -209,7 +212,7 @@ module GoodData
209
212
  @stats = true
210
213
  end
211
214
 
212
- def stats_on? # rubocop:disable Style/TrivialAccessors
215
+ def stats_on?
213
216
  @stats
214
217
  end
215
218
 
@@ -234,7 +237,7 @@ module GoodData
234
237
  @connection.get uri, opts, & block
235
238
  end
236
239
 
237
- def project_webdav_path(opts = { :project => GoodData.project })
240
+ def project_webdav_path(opts = { project: GoodData.project })
238
241
  p = opts[:project]
239
242
  fail ArgumentError, 'No :project specified' if p.nil?
240
243
 
@@ -246,7 +249,7 @@ module GoodData
246
249
  url
247
250
  end
248
251
 
249
- def user_webdav_path(opts = { :project => GoodData.project })
252
+ def user_webdav_path(opts = { project: GoodData.project })
250
253
  p = opts[:project]
251
254
  fail ArgumentError, 'No :project specified' if p.nil?
252
255
 
@@ -294,21 +297,18 @@ module GoodData
294
297
  sleep_interval = options[:sleep_interval] || DEFAULT_SLEEP_INTERVAL
295
298
  time_limit = options[:time_limit] || DEFAULT_POLL_TIME_LIMIT
296
299
 
297
- # by default the response is processed
298
- process = options[:process]
299
-
300
300
  # get the first status and start the timer
301
- response = get(link, :process => process)
301
+ response = get(link, options)
302
302
  poll_start = Time.now
303
303
 
304
304
  while bl.call(response)
305
- if time_limit && (Time.now - poll_start > time_limit)
306
- fail "The time limit #{time_limit} secs for polling on #{link} is over"
305
+ limit_breached = time_limit && (Time.now - poll_start > time_limit)
306
+ if limit_breached
307
+ fail ExecutionLimitExceeded, "The time limit #{time_limit} secs for polling on #{link} is over"
307
308
  end
308
309
  sleep sleep_interval
309
310
  GoodData::Rest::Client.retryable(:tries => 3, :refresh_token => proc { connection.refresh_token }) do
310
- sleep sleep_interval
311
- response = get(link, :process => process)
311
+ response = get(link, options)
312
312
  end
313
313
  end
314
314
  response
@@ -345,7 +345,7 @@ module GoodData
345
345
  @connection.download source_relative_path, target_file_path, options
346
346
  end
347
347
 
348
- def download_from_user_webdav(source_relative_path, target_file_path, options = { :client => GoodData.client, :project => project })
348
+ def download_from_user_webdav(source_relative_path, target_file_path, options = { client: GoodData.client, project: project })
349
349
  download(source_relative_path, target_file_path, options.merge(:directory => options[:directory],
350
350
  :staging_url => get_user_webdav_url(options)))
351
351
  end
@@ -38,6 +38,9 @@ module GoodData
38
38
  Timeout::Error
39
39
  ]
40
40
 
41
+ RETRIES_ON_TOO_MANY_REQUESTS_ERROR = 10
42
+ RETRY_TIME_INITIAL_VALUE = 1
43
+ RETRY_TIME_COEFFICIENT = 1.5
41
44
  RETRYABLE_ERRORS << Net::ReadTimeout if Net.const_defined?(:ReadTimeout)
42
45
 
43
46
  class << self
@@ -58,12 +61,13 @@ module GoodData
58
61
 
59
62
  retry_exception = opts[:on]
60
63
  retries = opts[:tries]
64
+ too_many_requests_tries = RETRIES_ON_TOO_MANY_REQUESTS_ERROR
61
65
 
62
66
  unless retry_exception.is_a?(Array)
63
67
  retry_exception = [retry_exception]
64
68
  end
65
69
 
66
- retry_time = 1
70
+ retry_time = RETRY_TIME_INITIAL_VALUE
67
71
  begin
68
72
  return yield
69
73
  rescue RestClient::Unauthorized, RestClient::Forbidden => e # , RestClient::Unauthorized => e
@@ -71,16 +75,16 @@ module GoodData
71
75
  raise e if options[:dont_reauth]
72
76
  options[:refresh_token].call # (dont_reauth: true)
73
77
  retry if (retries -= 1) > 0
74
- rescue RestClient::TooManyRequests
78
+ rescue RestClient::TooManyRequests, RestClient::ServiceUnavailable
75
79
  GoodData.logger.warn "Too many requests, retrying in #{retry_time} seconds"
76
80
  sleep retry_time
77
- retry_time *= 1.5
78
- retry
81
+ retry_time *= RETRY_TIME_COEFFICIENT
82
+ # 10 requests with 1.5 coefficent should take ~ 3 mins to finish
83
+ retry if (too_many_requests_tries -= 1) > 1
79
84
  rescue *retry_exception => e
80
85
  GoodData.logger.warn e.inspect
81
- retry if (retries -= 1) > 0
86
+ retry if (retries -= 1) > 1
82
87
  end
83
-
84
88
  yield
85
89
  end
86
90
  end
@@ -89,12 +93,12 @@ module GoodData
89
93
 
90
94
  # backward compatibility
91
95
  alias_method :cookies, :request_params
96
+ attr_reader :server
92
97
  attr_reader :stats
93
98
  attr_reader :user
94
99
 
95
100
  def initialize(opts)
96
101
  @stats = {}
97
- @opts = opts
98
102
 
99
103
  headers = opts[:headers] || {}
100
104
  @webdav_headers = DEFAULT_WEBDAV_HEADERS.merge(headers)
@@ -112,11 +116,12 @@ module GoodData
112
116
  # Connect using username and password
113
117
  def connect(username, password, options = {})
114
118
  server = options[:server] || DEFAULT_URL
115
-
116
119
  options = DEFAULT_LOGIN_PAYLOAD.merge(options)
117
120
  headers = options[:headers] || {}
118
121
 
119
- @server = RestClient::Resource.new server, DEFAULT_LOGIN_PAYLOAD.merge(headers)
122
+ options = options.merge(headers)
123
+
124
+ @server = RestClient::Resource.new server, options
120
125
 
121
126
  # Install at_exit handler first
122
127
  unless @at_exit_handler_installed
@@ -200,7 +205,8 @@ module GoodData
200
205
  :user_agent => GoodData.gem_version_string
201
206
  },
202
207
  :method => :get,
203
- :url => url
208
+ :url => url,
209
+ :verify_ssl => (@opts[:verify_ssl] == false || @opts[:verify_ssl] == OpenSSL::SSL::VERIFY_NONE) ? OpenSSL::SSL::VERIFY_NONE : OpenSSL::SSL::VERIFY_PEER
204
210
  }.merge(cookies)
205
211
 
206
212
  if where.is_a?(IO) || where.is_a?(StringIO)
@@ -250,14 +256,16 @@ module GoodData
250
256
  #
251
257
  # @param uri [String] Target URI
252
258
  def delete(uri, options = {})
259
+ options = log_info(options)
253
260
  GoodData.logger.debug "DELETE: #{@server.url}#{uri}"
254
261
  profile "DELETE #{uri}" do
255
262
  b = proc do
263
+ params = fresh_request_params(options[:request_id])
256
264
  begin
257
- @server[uri].delete(fresh_request_params(options[:request_id]))
265
+ @server[uri].delete(params)
258
266
  rescue RestClient::Exception => e
259
267
  # log the error if it happens
260
- GoodData.logger.error(e.inspect)
268
+ GoodData.logger.error(format_error(e, params))
261
269
  raise e
262
270
  end
263
271
  end
@@ -269,14 +277,16 @@ module GoodData
269
277
  #
270
278
  # @param uri [String] Target URI
271
279
  def get(uri, options = {}, &user_block)
280
+ options = log_info(options)
272
281
  GoodData.logger.debug "GET: #{@server.url}#{uri}"
273
282
  profile "GET #{uri}" do
274
283
  b = proc do
284
+ params = fresh_request_params(options[:request_id])
275
285
  begin
276
- @server[uri].get(fresh_request_params(options[:request_id]), &user_block)
286
+ @server[uri].get(params, &user_block)
277
287
  rescue RestClient::Exception => e
278
288
  # log the error if it happens
279
- GoodData.logger.error(e.inspect)
289
+ GoodData.logger.error(format_error(e, params))
280
290
  raise e
281
291
  end
282
292
  end
@@ -288,15 +298,17 @@ module GoodData
288
298
  #
289
299
  # @param uri [String] Target URI
290
300
  def put(uri, data, options = {})
301
+ options = log_info(options)
291
302
  payload = data.is_a?(Hash) ? data.to_json : data
292
303
  GoodData.logger.debug "PUT: #{@server.url}#{uri}, #{scrub_params(data, KEYS_TO_SCRUB)}"
293
304
  profile "PUT #{uri}" do
294
305
  b = proc do
306
+ params = fresh_request_params(options[:request_id])
295
307
  begin
296
- @server[uri].put(payload, fresh_request_params(options[:request_id]))
308
+ @server[uri].put(payload, params)
297
309
  rescue RestClient::Exception => e
298
310
  # log the error if it happens
299
- GoodData.logger.error(e.inspect)
311
+ GoodData.logger.error(format_error(e, params))
300
312
  raise e
301
313
  end
302
314
  end
@@ -308,15 +320,17 @@ module GoodData
308
320
  #
309
321
  # @param uri [String] Target URI
310
322
  def post(uri, data, options = {})
323
+ options = log_info(options)
311
324
  GoodData.logger.debug "POST: #{@server.url}#{uri}, #{scrub_params(data, KEYS_TO_SCRUB)}"
312
325
  profile "POST #{uri}" do
313
326
  payload = data.is_a?(Hash) ? data.to_json : data
314
327
  b = proc do
328
+ params = fresh_request_params(options[:request_id])
315
329
  begin
316
- @server[uri].post(payload, fresh_request_params(options[:request_id]))
330
+ @server[uri].post(payload, params)
317
331
  rescue RestClient::Exception => e
318
332
  # log the error if it happens
319
- GoodData.logger.error(e.inspect)
333
+ GoodData.logger.error(format_error(e, params))
320
334
  raise e
321
335
  end
322
336
  end
@@ -357,68 +371,6 @@ module GoodData
357
371
 
358
372
  # Uploads a file to GoodData server
359
373
  def upload(file, options = {})
360
- def do_stream_file(uri, filename, _options = {})
361
- puts "uploading the file #{uri}"
362
-
363
- to_upload = File.new(filename)
364
- cookies_str = request_params[:cookies].map { |cookie| "#{cookie[0]}=#{cookie[1]}" }.join(';')
365
- req = Net::HTTP::Put.new(uri.path, 'User-Agent' => GoodData.gem_version_string, 'Cookie' => cookies_str)
366
- req.content_length = to_upload.size
367
- req.body_stream = to_upload
368
- http = Net::HTTP.new(uri.host, uri.port)
369
- http.use_ssl = true
370
- http.verify_mode = OpenSSL::SSL::VERIFY_NONE
371
-
372
- response = nil
373
- GoodData::Rest::Connection.retryable(:tries => 2, :refresh_token => proc { refresh_token }) do
374
- response = http.start { |client| client.request(req) }
375
- end
376
- response
377
- end
378
-
379
- def webdav_dir_exists?(url)
380
- method = :get
381
- GoodData.logger.debug "#{method}: #{url}"
382
-
383
- b = proc do
384
- raw = {
385
- :method => method,
386
- :url => url,
387
- :headers => @webdav_headers
388
- }.merge(cookies)
389
- begin
390
- RestClient::Request.execute(raw)
391
- rescue RestClient::Exception => e
392
- false if e.http_code == 404
393
- end
394
- end
395
-
396
- res = nil
397
- GoodData::Rest::Connection.retryable(:tries => 2, :refresh_token => proc { refresh_token }) do
398
- res = b.call
399
- end
400
- res
401
- end
402
-
403
- def create_webdav_dir_if_needed(url)
404
- return if webdav_dir_exists?(url)
405
-
406
- method = :mkcol
407
- GoodData.logger.debug "#{method}: #{url}"
408
- b = proc do
409
- raw = {
410
- :method => method,
411
- :url => url,
412
- :headers => @webdav_headers
413
- }.merge(cookies)
414
- RestClient::Request.execute(raw)
415
- end
416
-
417
- GoodData::Rest::Connection.retryable(:tries => 2, :refresh_token => proc { refresh_token }) do
418
- b.call
419
- end
420
- end
421
-
422
374
  dir = options[:directory] || ''
423
375
  staging_uri = options[:staging_url].to_s
424
376
  url = dir.empty? ? staging_uri : URI.join(staging_uri, "#{dir}/").to_s
@@ -438,6 +390,49 @@ module GoodData
438
390
 
439
391
  ID_LENGTH = 16
440
392
 
393
+ def create_webdav_dir_if_needed(url)
394
+ return if webdav_dir_exists?(url)
395
+
396
+ method = :mkcol
397
+ GoodData.logger.debug "#{method}: #{url}"
398
+ b = proc do
399
+ raw = {
400
+ :method => method,
401
+ :url => url,
402
+ :headers => @webdav_headers,
403
+ :verify_ssl => (@opts[:verify_ssl] == false || @opts[:verify_ssl] == OpenSSL::SSL::VERIFY_NONE) ? OpenSSL::SSL::VERIFY_NONE : OpenSSL::SSL::VERIFY_PEER
404
+ }.merge(cookies)
405
+ RestClient::Request.execute(raw)
406
+ end
407
+
408
+ GoodData::Rest::Connection.retryable(:tries => 2, :refresh_token => proc { refresh_token }) do
409
+ b.call
410
+ end
411
+ end
412
+
413
+ def do_stream_file(uri, filename, _options = {})
414
+ GoodData.logger.info "Uploading file user storage #{uri}"
415
+
416
+ to_upload = File.new(filename)
417
+ cookies_str = request_params[:cookies].map { |cookie| "#{cookie[0]}=#{cookie[1]}" }.join(';')
418
+ req = Net::HTTP::Put.new(uri.path, 'User-Agent' => GoodData.gem_version_string, 'Cookie' => cookies_str)
419
+ req.content_length = to_upload.size
420
+ req.body_stream = to_upload
421
+ http = Net::HTTP.new(uri.host, uri.port)
422
+ http.use_ssl = true
423
+ http.verify_mode = (@opts[:verify_ssl] == false || @opts[:verify_ssl] == OpenSSL::SSL::VERIFY_NONE) ? OpenSSL::SSL::VERIFY_NONE : OpenSSL::SSL::VERIFY_PEER
424
+
425
+ response = nil
426
+ GoodData::Rest::Connection.retryable(:tries => 2, :refresh_token => proc { refresh_token }) do
427
+ response = http.start { |client| client.request(req) }
428
+ end
429
+ response
430
+ end
431
+
432
+ def format_error(e, params)
433
+ "#{params[:x_gdc_request]} #{e.inspect}"
434
+ end
435
+
441
436
  def generate_string
442
437
  SecureRandom.urlsafe_base64(ID_LENGTH)
443
438
  end
@@ -460,6 +455,16 @@ module GoodData
460
455
  @session_id = nil
461
456
  end
462
457
 
458
+ # log info_message given in options and make sure request_id is there
459
+ def log_info(options)
460
+ # if info_message given, log it with request_id (given or generated)
461
+ if options[:info_message]
462
+ request_id = options[:request_id] || generate_request_id
463
+ GoodData.logger.info "#{options[:info_message]} Request id: #{request_id}"
464
+ end
465
+ options
466
+ end
467
+
463
468
  # request heders with freshly generated request id
464
469
  def fresh_request_params(request_id = nil)
465
470
  @request_params.merge(:x_gdc_request => request_id || generate_request_id)
@@ -470,20 +475,9 @@ module GoodData
470
475
  end
471
476
 
472
477
  def process_response(options = {}, &block)
473
- # begin
474
- # # Simply try again when ConnectionReset, ConnectionRefused etc.. (see e.g. MSF-7591)
475
- # response = GoodData::Rest::Connection.retryable(:tries => 2, :refresh_token => Proc.new { refresh_token }) do
476
- # block.call
477
- # end
478
- # rescue RestClient::Unauthorized
479
- # raise $ERROR_INFO if options[:dont_reauth]
480
- # GoodData::Rest::Connection.retryable(:tries => 2) do
481
- # refresh_token
482
- # response = block.call
483
- # end
484
- # end
485
-
486
- response = GoodData::Rest::Connection.retryable(:tries => 2, :refresh_token => proc { refresh_token unless options[:dont_reauth] }) do
478
+ retries = options[:tries] || 3
479
+
480
+ response = GoodData::Rest::Connection.retryable(:tries => retries, :refresh_token => proc { refresh_token unless options[:dont_reauth] }) do
487
481
  block.call
488
482
  end
489
483
 
@@ -596,6 +590,31 @@ module GoodData
596
590
 
597
591
  stats[title] = stat
598
592
  end
593
+
594
+ def webdav_dir_exists?(url)
595
+ method = :get
596
+ GoodData.logger.debug "#{method}: #{url}"
597
+
598
+ b = proc do
599
+ raw = {
600
+ :method => method,
601
+ :url => url,
602
+ :headers => @webdav_headers,
603
+ :verify_ssl => (@opts[:verify_ssl] == false || @opts[:verify_ssl] == OpenSSL::SSL::VERIFY_NONE) ? OpenSSL::SSL::VERIFY_NONE : OpenSSL::SSL::VERIFY_PEER
604
+ }.merge(cookies)
605
+ begin
606
+ RestClient::Request.execute(raw)
607
+ rescue RestClient::Exception => e
608
+ false if e.http_code == 404
609
+ end
610
+ end
611
+
612
+ res = nil
613
+ GoodData::Rest::Connection.retryable(:tries => 2, :refresh_token => proc { refresh_token }) do
614
+ res = b.call
615
+ end
616
+ res
617
+ end
599
618
  end
600
619
  end
601
620
  end