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.
- 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
|