gooddata 0.6.15 → 0.6.16

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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 2be96271a19b80a9bbb9658234c19fafbeadf935
4
- data.tar.gz: 11a5fd29bede6c2258a0954d2e5b0fc6fd8d71ec
3
+ metadata.gz: 40814e8c9d7deee9ac0eca814a3ac3c635f1ede3
4
+ data.tar.gz: fe14bb4f38e410de2e7abc9624e5f3aba6c39e6f
5
5
  SHA512:
6
- metadata.gz: 8590dd4828f12d0bb49beadaafc6b32080678c5df6d38e8fc710a77f2ae54983e6cd5cdeee04c1fc835b91774240e8c2da68486f9c649e101b2131ababca5301
7
- data.tar.gz: de42c006bb3bed502feab54273fa3263f4475f081617de84d5b6eb8746941e1e55d5cf814fab09e47801a9691561b192a5791f6bdaa13e53c1b6a6cdcbb44e64
6
+ metadata.gz: f4128f12fab224bc8a5814fe0dcee35c385c2652defe34afb331562a65332b7f4fdd9199b7bb4c653eebdff39d6dd21950482e10fb1b51c5e81664072c490035
7
+ data.tar.gz: 731f9c3dab1e859777931f44362e4e50c2bc79fa562a4172ad2d53c658d9b3f309ff2000fb36a9090bdecd09be5240d76d3344316d60b281803bcc3d4e90373e
@@ -0,0 +1,42 @@
1
+ # encoding: UTF-8
2
+ require_relative 'base_middleware'
3
+
4
+ module GoodData
5
+ module Bricks
6
+ class FsProjectDownloadMiddleware < Bricks::Middleware
7
+ def call(params)
8
+ (params['gdc_files_to_download'] || []).each do |source|
9
+ case source[:type].to_s
10
+ when 'ads'
11
+ CSV.open(source[:to], 'w') do |csv|
12
+ header_written = false
13
+ header = nil
14
+ dwh = params['ads_client']
15
+ dwh.execute_select(source[:query]) do |row|
16
+ unless header_written
17
+ header_written = true
18
+ header = row.keys
19
+ csv << header
20
+ end
21
+ csv << row.values_at(*header)
22
+ end
23
+ end
24
+ when 'staging'
25
+ webdav_uri = GoodData.project_webdav_path
26
+ dav = Net::DAV.new(webdav_uri, :curl => false)
27
+ dav.verify_server = false
28
+ dav.credentials(params['GDC_USERNAME'], params['GDC_PASSWORD'])
29
+ dav.find(path, recursive: true, suppress_errors: true) do |item|
30
+ puts 'Checking: ' + item.url.to_s
31
+ name = (item.uri - webdav_uri).to_s
32
+ File.open(name, 'w') do |f|
33
+ f << item.content
34
+ end
35
+ end
36
+ end
37
+ end
38
+ @app.call(params)
39
+ end
40
+ end
41
+ end
42
+ end
@@ -1,9 +1,4 @@
1
1
  # encoding: UTF-8
2
-
3
- require 'uri'
4
- require 'net/http'
5
- require 'pathname'
6
-
7
2
  require_relative 'base_middleware'
8
3
 
9
4
  module GoodData
@@ -15,20 +10,21 @@ module GoodData
15
10
  end
16
11
 
17
12
  def call(params)
18
- returning(@app.call(params)) do |_result|
13
+ returning(@app.call(params)) do |_|
19
14
  destination = @destination
20
15
  (params['gdc_files_to_upload'] || []).each do |f|
21
- case destination.to_s
22
- when 'staging'
23
- GoodData.upload_to_project_webdav(f[:path], directory: f[:webdav_directory])
24
- puts "Uploaded local file \"#{f[:path]}\" to webdav."
16
+ path = f[:path]
17
+ case destination.to_sym
18
+ when :staging
19
+ GoodData.client.get '/gdc/account/token', :dont_reauth => true
20
+ url = GoodData.project_webdav_path
21
+ GoodData.upload_to_project_webdav(path)
22
+ puts "Uploaded local file \"#{path}\" to url \"#{url + path}\""
25
23
  end
26
24
  end
27
25
  end
28
26
  end
29
27
  end
30
-
31
- # Alias to make it backwards compatible
32
28
  FsUploadMiddleware = FsProjectUploadMiddleware
33
29
  end
34
30
  end
@@ -1,8 +1,4 @@
1
1
  # encoding: UTF-8
2
-
3
- # TODO: REmove this
4
- # require 'gooddata'
5
-
6
2
  require_relative 'base_middleware'
7
3
 
8
4
  module GoodData
@@ -11,25 +7,26 @@ module GoodData
11
7
  def call(params)
12
8
  logger = params['GDC_LOGGER']
13
9
  token_name = 'GDC_SST'
14
- protocol_name = 'GDC_PROTOCOL'
15
- server_name = 'GDC_HOSTNAME'
10
+ protocol_name = 'CLIENT_GDC_PROTOCOL'
11
+ server_name = 'CLIENT_GDC_HOSTNAME'
16
12
  project_id = params['GDC_PROJECT_ID']
17
13
 
18
- fail 'SST (SuperSecureToken) not present in params' if params[token_name].nil?
19
-
20
- server = if !params[protocol_name].empty? && !params[server_name].empty?
14
+ server = if params[protocol_name] && params[server_name]
21
15
  "#{params[protocol_name]}://#{params[server_name]}"
22
16
  end
23
17
 
24
18
  client = if params['GDC_USERNAME'].nil? || params['GDC_PASSWORD'].nil?
25
- GoodData.connect(sst_token: params['GDC_SST'], server: server)
19
+ puts "Connecting with SST to server #{server}"
20
+ fail 'SST (SuperSecureToken) not present in params' if params[token_name].nil?
21
+ GoodData.connect(sst_token: params[token_name], server: server)
26
22
  else
23
+ puts "Connecting as #{params['GDC_USERNAME']} to server #{server}"
27
24
  GoodData.connect(params['GDC_USERNAME'], params['GDC_PASSWORD'], server: server)
28
25
  end
26
+ project = client.projects(project_id)
27
+ GoodData.project = project
29
28
  GoodData.logger = logger
30
- GoodData.with_project(project_id, :client => client) do |_p|
31
- @app.call(params)
32
- end
29
+ @app.call(params.merge('GDC_GD_CLIENT' => client, 'gdc_project' => project))
33
30
  end
34
31
  end
35
32
  end
@@ -8,8 +8,13 @@ module GoodData
8
8
  module Bricks
9
9
  class LoggerMiddleware < Bricks::Middleware
10
10
  def call(params)
11
- logger = params['GDC_LOGGER'] = params[:GDC_LOGGER_FILE].nil? ? Logger.new(STDOUT) : Logger.new(params[:GDC_LOGGER_FILE])
12
- logger.info('Pipeline starts')
11
+ logger = nil
12
+ if params['GDC_LOGGING_OFF']
13
+ logger = NilLogger.new
14
+ else
15
+ logger = params['GDC_LOGGER'] = params[:GDC_LOGGER_FILE].nil? ? Logger.new(STDOUT) : Logger.new(params[:GDC_LOGGER_FILE])
16
+ logger.info('Pipeline starts')
17
+ end
13
18
  returning(@app.call(params)) do |_result|
14
19
  logger.info('Pipeline ending')
15
20
  end
@@ -77,39 +77,38 @@ module GoodData
77
77
 
78
78
  # Get WebDav directory for project data
79
79
  # @return [String]
80
- def get_project_webdav_path(file, options = { :project => GoodData.project })
80
+ def project_webdav_path(options = { :project => GoodData.project })
81
81
  options = merge_options(options)
82
82
  project = options[:project]
83
- project.get_project_webdav_path(file)
83
+ project.project_webdav_path
84
84
  end
85
85
 
86
86
  # Upload to project directory
87
87
  def upload_to_project_webdav(file, options = { :project => GoodData.project })
88
88
  options = merge_options(options)
89
- webdav_filename = File.basename(file)
90
- url = get_project_webdav_path(webdav_filename, options)
89
+ url = project_webdav_path(options)
91
90
  connection.upload(file, options.merge(:staging_url => url))
92
91
  end
93
92
 
94
93
  # Download from project directory
95
94
  def download_from_project_webdav(file, where, options = { :project => GoodData.project })
96
95
  options = merge_options(options)
97
- url = get_project_webdav_path(file, options)
96
+ url = project_webdav_path(options)
98
97
  connection.download(file, where, options.merge(:staging_url => url))
99
98
  end
100
99
 
101
100
  # Get WebDav directory for user data
102
101
  # @return [String]
103
- def get_user_webdav_path(file, options = { :project => GoodData.project })
102
+ def user_webdav_path(options = { :project => GoodData.project })
104
103
  options = merge_options(options)
105
104
  project = options[:project]
106
- project.get_user_webdav_path(file)
105
+ project.user_webdav_path
107
106
  end
108
107
 
109
108
  # Download from user directory
110
109
  def download_from_user_webdav(file, where, options = { :project => GoodData.project })
111
110
  options = merge_options(options)
112
- url = get_user_webdav_path(file, options)
111
+ url = user_webdav_path(options)
113
112
  connection.download(file, where, options.merge(:staging_url => url))
114
113
  end
115
114
 
@@ -0,0 +1,81 @@
1
+ # encoding: UTF-8
2
+
3
+ require 'csv'
4
+ require 'digest'
5
+ require 'open-uri'
6
+
7
+ module GoodData
8
+ module Helpers
9
+ class DataSource
10
+ attr_reader :realized
11
+
12
+ def initialize(opts = {})
13
+ opts = opts.is_a?(String) ? { type: :staging, path: opts } : opts
14
+ opts = opts.symbolize_keys
15
+ @source = opts[:type]
16
+ @options = opts
17
+ @realized = false
18
+ end
19
+
20
+ def realize_query(params)
21
+ query = @options[:query]
22
+ dwh = params['ads_client']
23
+ fail "Data Source needs a client to ads to be able to query the storage but 'ads_client' is empty." unless dwh
24
+ filename = Digest::SHA256.new.hexdigest(query)
25
+ measure = Benchmark.measure do
26
+ CSV.open(filename, 'w') do |csv|
27
+ header_written = false
28
+ header = nil
29
+
30
+ dwh.execute_select(query) do |row|
31
+ unless header_written
32
+ header_written = true
33
+ header = row.keys
34
+ csv << header
35
+ end
36
+ csv << row.values_at(*header)
37
+ end
38
+ end
39
+ end
40
+ puts "Realizing SQL query \"#{query}\" took #{measure.real}"
41
+ filename
42
+ end
43
+
44
+ def realize_staging(params)
45
+ path = @options[:path]
46
+ url = URI.parse(path)
47
+ filename = Digest::SHA256.new.hexdigest(path)
48
+ if url.relative?
49
+ params['gdc_project'].download_file(path, filename)
50
+ else
51
+ params['GDC_GD_CLIENT'].download_file(path, filename)
52
+ end
53
+ filename
54
+ end
55
+
56
+ def realize_link
57
+ link = @options[:url]
58
+ filename = Digest::SHA256.new.hexdigest(link)
59
+ measure = Benchmark.measure do
60
+ File.open(filename, 'w') do |f|
61
+ open(link) { |rf| f.write(rf.read) }
62
+ end
63
+ end
64
+ puts "Realizing web download from \"#{link}\" took #{measure.real}"
65
+ filename
66
+ end
67
+
68
+ def realize(params = {})
69
+ @realized = true
70
+ case @source.to_s
71
+ when 'ads'
72
+ realize_query(params)
73
+ when 'staging'
74
+ realize_staging(params)
75
+ when 'web'
76
+ realize_link
77
+ end
78
+ end
79
+ end
80
+ end
81
+ end
@@ -120,7 +120,7 @@ module GoodData
120
120
  nested[k] = v
121
121
  end
122
122
  end
123
- key = hidden ? ENCODED_PARAMS_KEY : ENCODED_HIDDEN_PARAMS_KEY
123
+ key = hidden ? ENCODED_HIDDEN_PARAMS_KEY : ENCODED_PARAMS_KEY
124
124
  res[key] = nested.to_json unless nested.empty?
125
125
  res
126
126
  end
@@ -10,8 +10,6 @@ module GoodData
10
10
  class Domain < GoodData::Rest::Object
11
11
  attr_reader :name
12
12
 
13
- USERS_OPTIONS = { :offset => 0, :limit => 10_000 }
14
-
15
13
  class << self
16
14
  # Looks for domain
17
15
  #
@@ -182,21 +180,22 @@ module GoodData
182
180
  # @option opts [Number] :offset The subject
183
181
  # @option opts [Number] :limit From address
184
182
  # TODO: Review opts[:limit] functionality
185
- def users(domain, opts = USERS_OPTIONS.merge(:client => GoodData.connection))
183
+ def users(domain, opts = {})
186
184
  result = []
187
-
188
- offset = 0 || opts[:offset]
189
- uri = "/gdc/account/domains/#{domain}/users?offset=#{offset}&limit=#{opts[:limit]}"
185
+ page_limit = opts[:page_limit] || 1000
186
+ limit = opts[:limit] || Float::INFINITY
187
+ offset = opts[:offset]
188
+ uri = "/gdc/account/domains/#{domain}/users?offset=#{offset}&limit=#{page_limit}"
190
189
  loop do
191
- break unless uri
192
190
  tmp = client(opts).get(uri)
193
191
  tmp['accountSettings']['items'].each do |account|
194
192
  result << client(opts).create(GoodData::Profile, account)
195
193
  end
196
- break if opts[:limit] && result.length >= opts[:limit]
194
+ break if result.length >= limit
195
+
197
196
  uri = tmp['accountSettings']['paging']['next']
197
+ break unless uri
198
198
  end
199
-
200
199
  result
201
200
  end
202
201
 
@@ -205,51 +204,26 @@ module GoodData
205
204
  # @param [String] default_domain_name Default domain name used when no specified in user
206
205
  # @return [Array<GoodData::User>] List of users created
207
206
  def create_users(list, default_domain = nil, opts = { :client => GoodData.connection, :project => GoodData.project })
208
- client = client(opts)
209
207
  default_domain_name = default_domain.respond_to?(:name) ? default_domain.name : default_domain
210
- domain_obj = client.domain(default_domain_name)
211
- domains = {}
212
- list.map do |user|
208
+ domain = client.domain(default_domain_name)
209
+
210
+ domain_users_cache = Hash[domain.users.map { |u| [u.login, u] }]
211
+ list.pmapcat do |user|
213
212
  begin
214
213
  user_data = user.to_hash
215
- # TODO: Add user here
216
- domain_name = user_data[:domain] || default_domain_name
217
-
218
- # Lookup for domain in cache'
219
- domain = domains[domain_name]
220
-
221
- # Get domain info from REST, add to cache
222
- if domain.nil?
223
- domain = {
224
- :domain => domain_obj,
225
- :users => domain_obj.users
226
- }
227
-
228
- domain[:users_map] = Hash[domain[:users].map { |u| [u.login, u] }]
229
- domains[domain_name] = domain
230
- end
231
-
232
- # Check if user exists in domain
233
- domain_user = domain[:users_map][user_data[:login]]
234
-
235
- # Create domain user if needed
214
+ domain_user = domain_users_cache[user_data[:login]]
236
215
  if !domain_user
237
- # Add created user to cache
238
- domain_user = domain[:domain].add_user(user_data, opts)
239
- domain[:users] << domain_user
240
- domain[:users_map][domain_user.login] = domain_user
241
- { type: :user_added_to_domain, user: domain_user }
216
+ added_user = domain.add_user(user_data, opts)
217
+ [{ type: :user_added_to_domain, user: added_user }]
242
218
  else
243
- # fields = [:firstName, :email]
244
- diff = GoodData::Helpers.diff([domain_user.to_hash], [user_data], key: :login)
245
- next if diff[:changed].empty?
246
-
247
- domain_user = domain[:domain].update_user(domain_user.to_hash.merge(user_data.compact), opts)
248
- domain[:users_map][domain_user.login] = domain_user
249
- { type: :user_changed_in_domain, user: domain_user }
219
+ fields_to_check = opts[:fields_to_check] || user_data.keys
220
+ diff = GoodData::Helpers.diff([domain_user.to_hash], [user_data], key: :login, fields: fields_to_check)
221
+ next [] if diff[:changed].empty?
222
+ updated_user = domain.update_user(domain_user.to_hash.merge(user_data.compact), opts)
223
+ [{ type: :user_changed_in_domain, user: updated_user }]
250
224
  end
251
225
  rescue RuntimeError => e
252
- { type: :error, reason: e }
226
+ [{ type: :error, reason: e }]
253
227
  end
254
228
  end
255
229
  end
@@ -358,7 +332,7 @@ module GoodData
358
332
  # domain = GoodData::Domain['gooddata-tomas-korcak']
359
333
  # pp domain.users
360
334
  #
361
- def users(opts = USERS_OPTIONS)
335
+ def users(opts = {})
362
336
  GoodData::Domain.users(name, opts.merge(client: client))
363
337
  end
364
338
 
@@ -50,9 +50,11 @@ module GoodData
50
50
  # And following lines are even much more ugly hack
51
51
  # 'authentication_modes' => ['sso', 'password']
52
52
  },
53
+ 'links' => {},
53
54
  'meta' => {}
54
55
  }
55
56
  }
57
+ json['user']['links']['self'] = data[:uri] if data[:uri]
56
58
  c.create(self, json)
57
59
  end
58
60
 
@@ -123,7 +123,7 @@ module GoodData
123
123
  # @param name [String] name used as a basis for regular expression
124
124
  # @return [GoodData::Label]
125
125
  def label_by_name(name)
126
- labels.find { |label| label.title.downcase =~ /#{name}/ || label.identifier.downcase =~ /#{name}/ }
126
+ labels.find { |label| label.title =~ /#{name}/ || label.identifier =~ /#{name}/ }
127
127
  end
128
128
  end
129
129
  end
@@ -35,7 +35,7 @@ module GoodData
35
35
  #
36
36
  # @return [Array<GoodData::Fact>]
37
37
  def facts
38
- fact_uris.pmap { |a_uri| project.attributes(a_uri) }
38
+ fact_uris.pmap { |a_uri| project.facts(a_uri) }
39
39
  end
40
40
 
41
41
  # Gives you list of fact uris on a dataset
@@ -167,9 +167,10 @@ module GoodData
167
167
  path
168
168
  else
169
169
  with_zip(opts) do |zipfile|
170
- Dir[File.join(path, '**', '**')].reject { |f| files_to_exclude.include?(Pathname(path) + f) }.each do |file|
170
+ files_to_upload = Dir[File.join(path, '**', '**')].reject { |f| files_to_exclude.include?(Pathname(path) + f) }
171
+ puts "Uploading #{files_to_upload.count} files."
172
+ files_to_upload.each do |file|
171
173
  file_pathname = Pathname.new(file)
172
- puts "Including item #{file_pathname}"
173
174
  file_relative_pathname = file_pathname.relative_path_from(Pathname.new(path))
174
175
  zipfile.add(file_relative_pathname, file)
175
176
  end