gooddata 0.6.18 → 0.6.19

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