gooddata 0.6.15 → 0.6.16

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