gooddata 1.3.6 → 2.0.0

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.
Files changed (37) hide show
  1. checksums.yaml +5 -5
  2. data/.gitignore +1 -0
  3. data/.travis.yml +19 -4
  4. data/CHANGELOG.md +37 -1
  5. data/CONTRIBUTING.md +4 -0
  6. data/Gemfile +9 -0
  7. data/Jenkinsfile-chart +14 -0
  8. data/RELEASING.md +5 -8
  9. data/Rakefile +1 -1
  10. data/SDK_VERSION +1 -1
  11. data/bin/run_brick.rb +1 -1
  12. data/bin/test_projects_cleanup.rb +20 -8
  13. data/ci.rake +2 -2
  14. data/k8s/charts/lcm-bricks/Chart.yaml +4 -0
  15. data/k8s/charts/lcm-bricks/templates/prometheus/alertingRules.yaml +96 -0
  16. data/lcm.rake +1 -1
  17. data/lib/gooddata/bricks/middleware/context_logger_decorator.rb +31 -0
  18. data/lib/gooddata/bricks/middleware/context_manager.rb +68 -0
  19. data/lib/gooddata/bricks/middleware/gooddata_middleware.rb +15 -9
  20. data/lib/gooddata/bricks/middleware/logger_middleware.rb +20 -0
  21. data/lib/gooddata/bricks/middleware/mask_logger_decorator.rb +35 -5
  22. data/lib/gooddata/client.rb +2 -3
  23. data/lib/gooddata/core/gd_logger.rb +92 -0
  24. data/lib/gooddata/core/logging.rb +24 -7
  25. data/lib/gooddata/core/nil_logger.rb +1 -2
  26. data/lib/gooddata/core/splunk_logger.rb +23 -0
  27. data/lib/gooddata/lcm/actions/synchronize_users.rb +2 -1
  28. data/lib/gooddata/lcm/helpers/check_helper.rb +3 -15
  29. data/lib/gooddata/lcm/helpers/safe_failure_helper.rb +19 -0
  30. data/lib/gooddata/lcm/lcm2.rb +21 -10
  31. data/lib/gooddata/mixins/property_accessor.rb +30 -0
  32. data/lib/gooddata/models/execution.rb +5 -0
  33. data/lib/gooddata/models/project.rb +6 -4
  34. data/lib/gooddata/rest/client.rb +17 -6
  35. data/lib/gooddata/rest/connection.rb +20 -6
  36. data/lib/gooddata/rest/rest_aggregator.rb +46 -0
  37. metadata +13 -4
@@ -268,6 +268,8 @@ module GoodData
268
268
  def perform(mode, params = {})
269
269
  params = convert_params(params)
270
270
 
271
+ GoodData.gd_logger.brick = mode
272
+
271
273
  # Get actions for mode specified
272
274
  actions = get_mode_actions(mode)
273
275
 
@@ -353,21 +355,30 @@ module GoodData
353
355
  success: errors.empty?
354
356
  }
355
357
 
356
- has_errors = errors.any?
357
- # Fail whole execution if there is any failed action
358
- fail(JSON.pretty_generate(errors)) if strict_mode && has_errors
358
+ if errors.any?
359
+ error_message = JSON.pretty_generate(errors)
360
+ GoodData.logger.error(error_message)
361
+
362
+ # Fail whole execution if there is any failed action
363
+ fail(error_message) if strict_mode
364
+ end
359
365
 
360
366
  result
361
367
  end
362
368
 
363
369
  def run_action(action, params)
364
- GoodData.logger.info("Running #{action.name} action ...")
365
- params.clear_filters
366
- # Check if all required parameters were passed
367
- BaseAction.check_params(action.const_get('PARAMS'), params)
368
- params.setup_filters(action.const_get('PARAMS'))
369
- out = action.send(:call, params)
370
- params.clear_filters
370
+ begin
371
+ GoodData.gd_logger.start_action action, GoodData.gd_logger
372
+ GoodData.logger.info("Running #{action.name} action ...")
373
+ params.clear_filters
374
+ # Check if all required parameters were passed
375
+ BaseAction.check_params(action.const_get('PARAMS'), params)
376
+ params.setup_filters(action.const_get('PARAMS'))
377
+ out = action.send(:call, params)
378
+ ensure
379
+ params.clear_filters
380
+ GoodData.gd_logger.end_action GoodData.gd_logger
381
+ end
371
382
  out
372
383
  end
373
384
 
@@ -0,0 +1,30 @@
1
+ # Copyright (c) 2010-2018 GoodData Corporation. All rights reserved.
2
+ # This source code is licensed under the BSD-style license found in the
3
+ # LICENSE file in the root directory of this source tree.
4
+
5
+ module GoodData
6
+ module Mixin
7
+ module PropertyAccessor
8
+ def property_reader(where, *props)
9
+ props.each do |prop|
10
+ define_method(prop, proc {
11
+ instance_variable_get(where)[prop]
12
+ })
13
+ end
14
+ end
15
+
16
+ def property_writer(where, *props)
17
+ props.each do |prop|
18
+ define_method("#{prop}=", proc { |val|
19
+ instance_variable_get(where)[prop] = val
20
+ })
21
+ end
22
+ end
23
+
24
+ def property_accessor(*args)
25
+ property_reader(*args)
26
+ property_writer(*args)
27
+ end
28
+ end
29
+ end
30
+ end
@@ -92,7 +92,12 @@ module GoodData
92
92
  #
93
93
  # @return [GoodData::Execution] Execution result
94
94
  def wait_for_result(options = {})
95
+ start_time = Time.now
96
+ timeout = options[:timeout]
95
97
  res = client.poll_on_response(uri, options) do |body|
98
+ timeout_exceeded = timeout && (start_time + timeout) < Time.now
99
+ fail 'Waiting for schedule execution timed out.' if timeout_exceeded
100
+
96
101
  body['execution'] && (body['execution']['status'] == 'RUNNING' || body['execution']['status'] == 'SCHEDULED')
97
102
  end
98
103
  @json = res
@@ -1606,7 +1606,7 @@ module GoodData
1606
1606
  whitelisted_new_users, whitelisted_users = whitelist_users(new_users.map(&:to_hash), users_list, options[:whitelists])
1607
1607
 
1608
1608
  # First check that if groups are provided we have them set up
1609
- check_groups(new_users.map(&:to_hash).flat_map { |u| u[:user_group] || [] }.uniq, options)
1609
+ options[:user_groups_cache] = check_groups(new_users.map(&:to_hash).flat_map { |u| u[:user_group] || [] }.uniq, options[:user_groups_cache], options)
1610
1610
 
1611
1611
  # conform the role on list of new users so we can diff them with the users coming from the project
1612
1612
  diffable_new_with_default_role = whitelisted_new_users.map do |u|
@@ -1706,7 +1706,7 @@ module GoodData
1706
1706
  user_groups(g).set_members(remote_users)
1707
1707
  end
1708
1708
  mentioned_groups = mappings.map(&:last).uniq
1709
- groups_to_cleanup = user_groups.reject { |g| mentioned_groups.include?(g.name) }
1709
+ groups_to_cleanup = options[:user_groups_cache].reject { |g| mentioned_groups.include?(g.name) }
1710
1710
  # clean all groups not mentioned with exception of whitelisted users
1711
1711
  groups_to_cleanup.each do |g|
1712
1712
  g.set_members(whitelist_users(g.members.map(&:to_hash), [], options[:whitelists], :include).first.map { |x| x[:uri] })
@@ -1744,8 +1744,9 @@ module GoodData
1744
1744
  end
1745
1745
  end
1746
1746
 
1747
- def check_groups(specified_groups, options = {})
1748
- groups = user_groups.map(&:name)
1747
+ def check_groups(specified_groups, user_groups_cache = nil, options = {})
1748
+ user_groups_cache = user_groups if user_groups_cache.nil? || user_groups_cache.empty?
1749
+ groups = user_groups_cache.map(&:name)
1749
1750
  missing_groups = specified_groups - groups
1750
1751
  if options[:create_non_existing_user_groups]
1751
1752
  missing_groups.each do |g|
@@ -1758,6 +1759,7 @@ module GoodData
1758
1759
  "#{groups.join(',')} and you asked for #{missing_groups.join(',')}"
1759
1760
  end
1760
1761
  end
1762
+ user_groups_cache
1761
1763
  end
1762
1764
 
1763
1765
  # Update user
@@ -67,6 +67,17 @@ module GoodData
67
67
  # @param password [String] Password to be used for authentication
68
68
  # @return [GoodData::Rest::Client] Client
69
69
  def connect(username, password = 'aaaa', opts = {})
70
+ execution_id = ""
71
+ if username.is_a?(Hash) && username.key?(:execution_id)
72
+ execution_id = username[:execution_id]
73
+ username.delete(:execution_id)
74
+ end
75
+
76
+ if opts.key?(:execution_id)
77
+ execution_id = opts[:execution_id]
78
+ opts.delete(:execution_id)
79
+ end
80
+
70
81
  if username.nil? && password.nil?
71
82
  username = ENV['GD_GEM_USER']
72
83
  password = ENV['GD_GEM_PASSWORD']
@@ -88,7 +99,7 @@ module GoodData
88
99
  new_opts[:password] = password
89
100
  end
90
101
 
91
- new_opts = { verify_ssl: true }.merge(new_opts)
102
+ new_opts = { verify_ssl: true, execution_id: execution_id }.merge(new_opts)
92
103
  if username.is_a?(Hash) && username[:cookies]
93
104
  new_opts[:sst_token] = username[:cookies]['GDCAuthSST']
94
105
  new_opts[:cookies] = username[:cookies]
@@ -195,7 +206,7 @@ module GoodData
195
206
  def disconnect
196
207
  if stats_on?
197
208
  GoodData.logger.info("API call statistics to server #{@connection.server}")
198
- GoodData.logger.info(@connection.stats_table)
209
+ GoodData.logger.info(@connection.stats_table.to_s)
199
210
  end
200
211
  @connection.disconnect
201
212
  end
@@ -256,14 +267,14 @@ module GoodData
256
267
  #
257
268
  # @param uri [String] Target URI
258
269
  def delete(uri, opts = {})
259
- @connection.delete uri, opts
270
+ @connection.delete uri, opts.merge(stats_on: stats_on?)
260
271
  end
261
272
 
262
273
  # HTTP GET
263
274
  #
264
275
  # @param uri [String] Target URI
265
276
  def get(uri, opts = {}, & block)
266
- @connection.get uri, opts, & block
277
+ @connection.get uri, opts.merge(stats_on: stats_on?), & block
267
278
  end
268
279
 
269
280
  def project_webdav_path(opts = { project: GoodData.project })
@@ -349,14 +360,14 @@ module GoodData
349
360
  #
350
361
  # @param uri [String] Target URI
351
362
  def put(uri, data, opts = {})
352
- @connection.put uri, data, opts
363
+ @connection.put uri, data, opts.merge(stats_on: stats_on?)
353
364
  end
354
365
 
355
366
  # HTTP POST
356
367
  #
357
368
  # @param uri [String] Target URI
358
369
  def post(uri, data, opts = {})
359
- @connection.post uri, data, opts
370
+ @connection.post uri, data, opts.merge(stats_on: stats_on?)
360
371
  end
361
372
 
362
373
  # Uploads file to staging
@@ -131,6 +131,7 @@ module GoodData
131
131
  def initialize(opts)
132
132
  super()
133
133
  @stats = ThreadSafe::Hash.new
134
+ @execution_id = opts[:execution_id]
134
135
 
135
136
  headers = opts[:headers] || {}
136
137
  @webdav_headers = DEFAULT_WEBDAV_HEADERS.merge(headers)
@@ -328,10 +329,12 @@ module GoodData
328
329
  def request(method, uri, data, options = {}, &user_block)
329
330
  request_id = options[:request_id] || generate_request_id
330
331
  log_info(options.merge(request_id: request_id))
332
+ stats_on = options[:stats_on]
333
+
331
334
  payload = data.is_a?(Hash) ? data.to_json : data
332
335
 
333
336
  GoodData.rest_logger.info "#{method.to_s.upcase}: #{@server.url}#{uri}, #{scrub_params(data, KEYS_TO_SCRUB)}"
334
- profile "#{method.to_s.upcase} #{uri}" do
337
+ profile method.to_s.upcase, uri, request_id, stats_on do
335
338
  b = proc do
336
339
  params = fresh_request_params(request_id).merge(options)
337
340
  begin
@@ -452,7 +455,7 @@ module GoodData
452
455
  end
453
456
 
454
457
  def generate_request_id
455
- "#{session_id}:#{call_id}"
458
+ "#{@execution_id}:#{session_id}:#{call_id}"
456
459
  end
457
460
 
458
461
  private
@@ -591,13 +594,13 @@ ERR
591
594
  raise $ERROR_INFO
592
595
  end
593
596
 
594
- def profile(title, &block)
597
+ def profile(method, path, request_id, stats_on, &block)
595
598
  t1 = Time.now
596
599
  res = block.call
597
600
  t2 = Time.now
598
601
  delta = t2 - t1
599
602
 
600
- update_stats title, delta
603
+ add_stat_record method, path, delta, t1, request_id if stats_on
601
604
  res
602
605
  end
603
606
 
@@ -617,9 +620,10 @@ ERR
617
620
  new_params
618
621
  end
619
622
 
620
- def update_stats(title, delta)
623
+ def add_stat_record(method, path, delta, time_stamp, request_id)
621
624
  synchronize do
622
- orig_title = title
625
+ orig_title = "#{method.to_s.upcase} #{path}"
626
+ title = "#{method.to_s.upcase} #{path}"
623
627
 
624
628
  placeholders = true
625
629
 
@@ -648,6 +652,16 @@ ERR
648
652
  stat[:entries] << orig_title if placeholders
649
653
 
650
654
  stats[title] = stat
655
+
656
+ endpoint = self.class.map_placeholders path.clone
657
+ duration = delta
658
+ time_stamp = time_stamp.utc.strftime "%Y-%m-%dT%H:%M:%S.%L"
659
+ domain = server_url.gsub %r{http://|https://}, ""
660
+ execution_id = request_id
661
+
662
+ GoodData.gd_logger.update_store(domain, method, duration, endpoint)
663
+ GoodData.gd_logger.add Logger::INFO, { endpoint: endpoint, duration: duration, domain: domain,
664
+ execution_id: execution_id, time_stamp: time_stamp }, "rest_call"
651
665
  end
652
666
  end
653
667
 
@@ -0,0 +1,46 @@
1
+ # Copyright (c) 2010-2017 GoodData Corporation. All rights reserved.
2
+ # This source code is licensed under the BSD-style license found in the
3
+ # LICENSE file in the root directory of this source tree.
4
+
5
+ module GoodData
6
+ module Rest
7
+ # class is responsible for storage and aggregation of REST calls information
8
+ module Aggregator
9
+ attr_reader :store
10
+
11
+ def initialize_store
12
+ @store = {}
13
+ end
14
+
15
+ def clear_store
16
+ @store.clear
17
+ end
18
+
19
+ def update_store(domain, method, duration, endpoint)
20
+ domain = domain.to_sym
21
+ method = method.to_sym
22
+ endpoint = endpoint.to_sym
23
+ @store[domain] = {} unless @store.key?(domain)
24
+ @store[domain][method] = {} unless @store[domain].key?(method)
25
+ if @store[domain][method].key?(endpoint)
26
+ record = @store[domain][method][endpoint]
27
+ record[:min] = [duration, record[:min]].min
28
+ record[:max] = [duration, record[:max]].max
29
+ record[:avg] = (record[:avg] * record[:count] + duration).to_f / (record[:count] + 1)
30
+ record[:count] += 1
31
+ @store[domain][method][endpoint] = record
32
+ else
33
+ @store[domain][method][endpoint] = {
34
+ :min => duration,
35
+ :max => duration,
36
+ :avg => duration,
37
+ :count => 1,
38
+ :method => method.to_s,
39
+ :endpoint => endpoint.to_s,
40
+ :domain => domain.to_s
41
+ }
42
+ end
43
+ end
44
+ end
45
+ end
46
+ end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: gooddata
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.3.6
4
+ version: 2.0.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Pavel Kolesnikov
@@ -14,7 +14,7 @@ authors:
14
14
  autorequire:
15
15
  bindir: bin
16
16
  cert_chain: []
17
- date: 2019-01-16 00:00:00.000000000 Z
17
+ date: 2019-02-14 00:00:00.000000000 Z
18
18
  dependencies:
19
19
  - !ruby/object:Gem::Dependency
20
20
  name: license_finder
@@ -586,6 +586,7 @@ files:
586
586
  - Gemfile
587
587
  - Guardfile
588
588
  - Jenkinsfile
589
+ - Jenkinsfile-chart
589
590
  - LICENSE
590
591
  - LICENSE.rb
591
592
  - README.md
@@ -616,6 +617,8 @@ files:
616
617
  - docker-compose.yml
617
618
  - gooddata
618
619
  - gooddata.gemspec
620
+ - k8s/charts/lcm-bricks/Chart.yaml
621
+ - k8s/charts/lcm-bricks/templates/prometheus/alertingRules.yaml
619
622
  - lcm.rake
620
623
  - lib/gooddata.rb
621
624
  - lib/gooddata/app/app.rb
@@ -628,6 +631,8 @@ files:
628
631
  - lib/gooddata/bricks/middleware/base_middleware.rb
629
632
  - lib/gooddata/bricks/middleware/bench_middleware.rb
630
633
  - lib/gooddata/bricks/middleware/bulk_salesforce_middleware.rb
634
+ - lib/gooddata/bricks/middleware/context_logger_decorator.rb
635
+ - lib/gooddata/bricks/middleware/context_manager.rb
631
636
  - lib/gooddata/bricks/middleware/decode_params_middleware.rb
632
637
  - lib/gooddata/bricks/middleware/dwh_middleware.rb
633
638
  - lib/gooddata/bricks/middleware/fs_download_middleware.rb
@@ -671,10 +676,12 @@ files:
671
676
  - lib/gooddata/commands/user.rb
672
677
  - lib/gooddata/connection.rb
673
678
  - lib/gooddata/core/core.rb
679
+ - lib/gooddata/core/gd_logger.rb
674
680
  - lib/gooddata/core/logging.rb
675
681
  - lib/gooddata/core/nil_logger.rb
676
682
  - lib/gooddata/core/project.rb
677
683
  - lib/gooddata/core/rest.rb
684
+ - lib/gooddata/core/splunk_logger.rb
678
685
  - lib/gooddata/core/user.rb
679
686
  - lib/gooddata/data/data.rb
680
687
  - lib/gooddata/data/guesser.rb
@@ -769,6 +776,7 @@ files:
769
776
  - lib/gooddata/lcm/helpers/check_helper.rb
770
777
  - lib/gooddata/lcm/helpers/helpers.rb
771
778
  - lib/gooddata/lcm/helpers/release_table_helper.rb
779
+ - lib/gooddata/lcm/helpers/safe_failure_helper.rb
772
780
  - lib/gooddata/lcm/helpers/tags_helper.rb
773
781
  - lib/gooddata/lcm/lcm.rb
774
782
  - lib/gooddata/lcm/lcm2.rb
@@ -838,6 +846,7 @@ files:
838
846
  - lib/gooddata/mixins/not_label.rb
839
847
  - lib/gooddata/mixins/not_metric.rb
840
848
  - lib/gooddata/mixins/obj_id.rb
849
+ - lib/gooddata/mixins/property_accessor.rb
841
850
  - lib/gooddata/mixins/rest_getters.rb
842
851
  - lib/gooddata/mixins/rest_resource.rb
843
852
  - lib/gooddata/mixins/root_key_getter.rb
@@ -933,6 +942,7 @@ files:
933
942
  - lib/gooddata/rest/phmap.rb
934
943
  - lib/gooddata/rest/resource.rb
935
944
  - lib/gooddata/rest/rest.rb
945
+ - lib/gooddata/rest/rest_aggregator.rb
936
946
  - lib/gooddata/version.rb
937
947
  - lib/templates/bricks/brick.rb.erb
938
948
  - lib/templates/bricks/main.rb.erb
@@ -964,8 +974,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
964
974
  - !ruby/object:Gem::Version
965
975
  version: '0'
966
976
  requirements: []
967
- rubyforge_project:
968
- rubygems_version: 2.6.11
977
+ rubygems_version: 3.0.2
969
978
  signing_key:
970
979
  specification_version: 4
971
980
  summary: A convenient Ruby wrapper around the GoodData RESTful API