gooddata 0.6.18 → 0.6.19
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.gitignore +2 -1
- data/.travis.yml +8 -19
- data/Guardfile +5 -0
- data/README.md +1 -3
- data/bin/gooddata +1 -1
- data/gooddata.gemspec +6 -4
- data/lib/gooddata.rb +1 -1
- data/lib/gooddata/bricks/middleware/aws_middleware.rb +24 -0
- data/lib/gooddata/cli/commands/console_cmd.rb +1 -1
- data/lib/gooddata/cli/commands/project_cmd.rb +29 -9
- data/lib/gooddata/cli/hooks.rb +9 -3
- data/lib/gooddata/commands/datawarehouse.rb +1 -7
- data/lib/gooddata/commands/project.rb +4 -3
- data/lib/gooddata/core/logging.rb +14 -2
- data/lib/gooddata/exceptions/execution_limit_exceeded.rb +9 -0
- data/lib/gooddata/exceptions/uncomputable_report.rb +8 -0
- data/lib/gooddata/exceptions/validation_error.rb +1 -1
- data/lib/gooddata/goodzilla/goodzilla.rb +5 -1
- data/lib/gooddata/helpers/data_helper.rb +40 -9
- data/lib/gooddata/mixins/md_finders.rb +35 -0
- data/lib/gooddata/models/blueprint/anchor_field.rb +46 -0
- data/lib/gooddata/models/blueprint/attribute_field.rb +25 -0
- data/lib/gooddata/models/blueprint/blueprint.rb +7 -0
- data/lib/gooddata/models/blueprint/blueprint_field.rb +66 -0
- data/lib/gooddata/models/{dashboard_builder.rb → blueprint/dashboard_builder.rb} +0 -0
- data/lib/gooddata/models/{schema_blueprint.rb → blueprint/dataset_blueprint.rb} +176 -117
- data/lib/gooddata/models/blueprint/date_dimension.rb +10 -0
- data/lib/gooddata/models/blueprint/fact_field.rb +16 -0
- data/lib/gooddata/models/blueprint/label_field.rb +39 -0
- data/lib/gooddata/models/{project_blueprint.rb → blueprint/project_blueprint.rb} +366 -168
- data/lib/gooddata/models/blueprint/project_builder.rb +79 -0
- data/lib/gooddata/models/blueprint/reference_field.rb +39 -0
- data/lib/gooddata/models/blueprint/schema_blueprint.rb +156 -0
- data/lib/gooddata/models/blueprint/schema_builder.rb +85 -0
- data/lib/gooddata/models/{to_manifest.rb → blueprint/to_manifest.rb} +25 -20
- data/lib/gooddata/models/{to_wire.rb → blueprint/to_wire.rb} +33 -52
- data/lib/gooddata/models/datawarehouse.rb +2 -2
- data/lib/gooddata/models/domain.rb +3 -2
- data/lib/gooddata/models/execution.rb +2 -2
- data/lib/gooddata/models/execution_detail.rb +7 -2
- data/lib/gooddata/models/from_wire.rb +60 -71
- data/lib/gooddata/models/from_wire_parse.rb +125 -125
- data/lib/gooddata/models/metadata.rb +14 -0
- data/lib/gooddata/models/metadata/dashboard.rb +2 -2
- data/lib/gooddata/models/metadata/label.rb +1 -1
- data/lib/gooddata/models/metadata/report.rb +6 -5
- data/lib/gooddata/models/metadata/report_definition.rb +44 -59
- data/lib/gooddata/models/model.rb +131 -43
- data/lib/gooddata/models/process.rb +13 -11
- data/lib/gooddata/models/profile.rb +12 -1
- data/lib/gooddata/models/project.rb +223 -19
- data/lib/gooddata/models/project_creator.rb +4 -15
- data/lib/gooddata/models/schedule.rb +1 -0
- data/lib/gooddata/models/user_filters/user_filter_builder.rb +2 -2
- data/lib/gooddata/rest/client.rb +18 -18
- data/lib/gooddata/rest/connection.rb +113 -94
- data/lib/gooddata/version.rb +1 -1
- data/lib/templates/project/model/model.rb.erb +15 -16
- data/spec/data/blueprints/additional_dataset_module.json +32 -0
- data/spec/data/blueprints/big_blueprint_not_pruned.json +2079 -0
- data/spec/data/blueprints/invalid_blueprint.json +103 -0
- data/spec/data/blueprints/m_n_model.json +104 -0
- data/spec/data/blueprints/model_module.json +25 -0
- data/spec/data/blueprints/test_blueprint.json +38 -0
- data/spec/data/blueprints/test_project_model_spec.json +106 -0
- data/spec/data/gd_gse_data_manifest.json +34 -34
- data/spec/data/manifests/test_blueprint.json +32 -0
- data/spec/data/{manifest_test_project.json → manifests/test_project.json} +9 -18
- data/spec/data/wire_models/test_blueprint.json +63 -0
- data/spec/data/wire_test_project.json +5 -5
- data/spec/environment/default.rb +33 -0
- data/spec/environment/develop.rb +26 -0
- data/spec/environment/environment.rb +14 -0
- data/spec/environment/hotfix.rb +17 -0
- data/spec/environment/production.rb +31 -0
- data/spec/environment/release.rb +17 -0
- data/spec/helpers/blueprint_helper.rb +10 -7
- data/spec/helpers/cli_helper.rb +24 -22
- data/spec/helpers/connection_helper.rb +27 -25
- data/spec/helpers/crypto_helper.rb +7 -5
- data/spec/helpers/csv_helper.rb +5 -3
- data/spec/helpers/process_helper.rb +15 -10
- data/spec/helpers/project_helper.rb +40 -33
- data/spec/helpers/schedule_helper.rb +15 -9
- data/spec/helpers/spec_helper.rb +11 -0
- data/spec/integration/blueprint_updates_spec.rb +93 -0
- data/spec/integration/command_datawarehouse_spec.rb +2 -1
- data/spec/integration/command_projects_spec.rb +9 -8
- data/spec/integration/create_from_template_spec.rb +1 -1
- data/spec/integration/create_project_spec.rb +1 -1
- data/spec/integration/full_process_schedule_spec.rb +1 -1
- data/spec/integration/full_project_spec.rb +91 -30
- data/spec/integration/over_to_user_filters_spec.rb +24 -28
- data/spec/integration/partial_md_export_import_spec.rb +4 -4
- data/spec/integration/project_spec.rb +1 -1
- data/spec/integration/rest_spec.rb +1 -1
- data/spec/integration/user_filters_spec.rb +19 -24
- data/spec/integration/variables_spec.rb +7 -9
- data/spec/logging_in_logging_out_spec.rb +1 -1
- data/spec/spec_helper.rb +10 -1
- data/spec/unit/bricks/middleware/aws_middelware_spec.rb +47 -0
- data/spec/unit/core/connection_spec.rb +2 -2
- data/spec/unit/core/logging_spec.rb +12 -4
- data/spec/unit/helpers/data_helper_spec.rb +60 -0
- data/spec/unit/models/blueprint/attributes_spec.rb +24 -0
- data/spec/unit/models/blueprint/dataset_spec.rb +116 -0
- data/spec/unit/models/blueprint/labels_spec.rb +39 -0
- data/spec/unit/models/blueprint/project_blueprint_spec.rb +643 -0
- data/spec/unit/models/blueprint/reference_spec.rb +24 -0
- data/spec/unit/models/{schema_builder_spec.rb → blueprint/schema_builder_spec.rb} +12 -4
- data/spec/unit/models/blueprint/to_wire_spec.rb +169 -0
- data/spec/unit/models/domain_spec.rb +13 -2
- data/spec/unit/models/from_wire_spec.rb +277 -98
- data/spec/unit/models/metadata_spec.rb +22 -4
- data/spec/unit/models/model_spec.rb +49 -39
- data/spec/unit/models/profile_spec.rb +1 -0
- data/spec/unit/models/project_spec.rb +7 -7
- data/spec/unit/models/schedule_spec.rb +20 -0
- data/spec/unit/models/to_manifest_spec.rb +31 -11
- data/spec/unit/rest/polling_spec.rb +86 -0
- metadata +102 -30
- data/lib/gooddata/models/project_builder.rb +0 -136
- data/lib/gooddata/models/schema_builder.rb +0 -77
- data/out.txt +0 -0
- data/spec/data/additional_dataset_module.json +0 -18
- data/spec/data/blueprint_invalid.json +0 -38
- data/spec/data/m_n_model/blueprint.json +0 -76
- data/spec/data/model_module.json +0 -18
- data/spec/data/test_project_model_spec.json +0 -76
- data/spec/unit/models/attribute_column_spec.rb +0 -7
- data/spec/unit/models/project_blueprint_spec.rb +0 -239
- 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
|
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
|
-
|
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 (#{
|
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 (#{
|
221
|
+
"[#{label.attribute_uri}] IN (#{element_uris.compact.sort.map { |e| '[' + e + ']' }.join(', ')})"
|
222
222
|
end
|
223
223
|
[expression, errors]
|
224
224
|
end
|
data/lib/gooddata/rest/client.rb
CHANGED
@@ -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 = { :
|
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
|
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
|
104
|
-
@@instance.disconnect
|
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
|
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,
|
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?
|
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 = { :
|
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 = { :
|
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,
|
301
|
+
response = get(link, options)
|
302
302
|
poll_start = Time.now
|
303
303
|
|
304
304
|
while bl.call(response)
|
305
|
-
|
306
|
-
|
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
|
-
|
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 = { :
|
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 =
|
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 *=
|
78
|
-
|
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) >
|
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
|
-
|
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(
|
265
|
+
@server[uri].delete(params)
|
258
266
|
rescue RestClient::Exception => e
|
259
267
|
# log the error if it happens
|
260
|
-
GoodData.logger.error(e
|
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(
|
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
|
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,
|
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
|
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,
|
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
|
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
|
-
|
474
|
-
|
475
|
-
|
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
|