gooddata 1.0.2-java → 1.1.0-java

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 (149) hide show
  1. checksums.yaml +5 -5
  2. data/.gitignore +1 -0
  3. data/CONTRIBUTING.md +12 -0
  4. data/README.md +5 -2
  5. data/Rakefile +0 -1
  6. data/dev-gooddata-sso.pub.encrypted +40 -0
  7. data/gooddata.gemspec +3 -3
  8. data/lib/gooddata/connection.rb +23 -13
  9. data/lib/gooddata/helpers/data_helper.rb +0 -1
  10. data/lib/gooddata/lcm/actions/apply_custom_maql.rb +8 -1
  11. data/lib/gooddata/lcm/actions/associate_clients.rb +8 -1
  12. data/lib/gooddata/lcm/actions/base_action.rb +10 -0
  13. data/lib/gooddata/lcm/actions/collect_ca_metrics.rb +7 -1
  14. data/lib/gooddata/lcm/actions/collect_client_projects.rb +3 -0
  15. data/lib/gooddata/lcm/actions/collect_clients.rb +3 -1
  16. data/lib/gooddata/lcm/actions/collect_data_product.rb +10 -2
  17. data/lib/gooddata/lcm/actions/collect_dynamic_schedule_params.rb +12 -1
  18. data/lib/gooddata/lcm/actions/collect_ldm_objects.rb +6 -2
  19. data/lib/gooddata/lcm/actions/collect_meta.rb +1 -1
  20. data/lib/gooddata/lcm/actions/collect_segment_clients.rb +8 -1
  21. data/lib/gooddata/lcm/actions/collect_segments.rb +6 -5
  22. data/lib/gooddata/lcm/actions/collect_tagged_objects.rb +1 -1
  23. data/lib/gooddata/lcm/actions/collect_users_brick_users.rb +10 -4
  24. data/lib/gooddata/lcm/actions/create_segment_masters.rb +12 -2
  25. data/lib/gooddata/lcm/actions/ensure_data_product.rb +10 -0
  26. data/lib/gooddata/lcm/actions/ensure_technical_users_domain.rb +5 -1
  27. data/lib/gooddata/lcm/actions/ensure_technical_users_project.rb +3 -0
  28. data/lib/gooddata/lcm/actions/execute_schedules.rb +10 -0
  29. data/lib/gooddata/lcm/actions/import_object_collections.rb +1 -1
  30. data/lib/gooddata/lcm/actions/provision_clients.rb +12 -2
  31. data/lib/gooddata/lcm/actions/purge_clients.rb +2 -0
  32. data/lib/gooddata/lcm/actions/rename_existing_client_projects.rb +3 -0
  33. data/lib/gooddata/lcm/actions/synchronize_attribute_drillpaths.rb +4 -1
  34. data/lib/gooddata/lcm/actions/synchronize_cas.rb +7 -1
  35. data/lib/gooddata/lcm/actions/synchronize_clients.rb +11 -1
  36. data/lib/gooddata/lcm/actions/synchronize_color_palette.rb +7 -1
  37. data/lib/gooddata/lcm/actions/synchronize_etls_in_segment.rb +12 -7
  38. data/lib/gooddata/lcm/actions/synchronize_label_types.rb +4 -1
  39. data/lib/gooddata/lcm/actions/synchronize_ldm.rb +18 -7
  40. data/lib/gooddata/lcm/actions/synchronize_meta.rb +9 -0
  41. data/lib/gooddata/lcm/actions/synchronize_new_segments.rb +11 -1
  42. data/lib/gooddata/lcm/actions/synchronize_processes.rb +7 -1
  43. data/lib/gooddata/lcm/actions/synchronize_schedules.rb +4 -1
  44. data/lib/gooddata/lcm/actions/synchronize_tag_objects.rb +6 -0
  45. data/lib/gooddata/lcm/actions/synchronize_user_filters.rb +60 -15
  46. data/lib/gooddata/lcm/actions/synchronize_user_groups.rb +7 -1
  47. data/lib/gooddata/lcm/actions/synchronize_users.rb +106 -3
  48. data/lib/gooddata/lcm/actions/update_release_table.rb +19 -0
  49. data/lib/gooddata/lcm/helpers/check_helper.rb +21 -6
  50. data/lib/gooddata/lcm/lcm2.rb +35 -22
  51. data/lib/gooddata/lcm/types/class/gd_logger.rb +23 -0
  52. data/lib/gooddata/lcm/types/class/gd_product.rb +23 -0
  53. data/lib/gooddata/lcm/types/class/gd_project.rb +23 -0
  54. data/lib/gooddata/lcm/types/class/smart_hash.rb +23 -0
  55. data/lib/gooddata/lcm/types/complex/segment.rb +1 -1
  56. data/lib/gooddata/lcm/types/scalar/integer.rb +2 -2
  57. data/lib/gooddata/lcm/types/special/any.rb +18 -0
  58. data/lib/gooddata/models/blueprint/dataset_blueprint.rb +1 -1
  59. data/lib/gooddata/models/blueprint/to_manifest.rb +1 -3
  60. data/lib/gooddata/models/blueprint/to_wire.rb +2 -1
  61. data/lib/gooddata/models/from_wire.rb +13 -1
  62. data/lib/gooddata/models/metadata/folder.rb +22 -0
  63. data/lib/gooddata/models/metadata/metric.rb +5 -8
  64. data/lib/gooddata/models/model.rb +1 -1
  65. data/lib/gooddata/models/process.rb +42 -32
  66. data/lib/gooddata/models/project.rb +19 -36
  67. data/lib/gooddata/models/project_creator.rb +3 -1
  68. data/lib/gooddata/models/project_role.rb +3 -4
  69. data/lib/gooddata/models/schedule.rb +0 -2
  70. data/lib/gooddata/models/user_filters/mandatory_user_filter.rb +9 -1
  71. data/lib/gooddata/models/user_filters/user_filter.rb +1 -2
  72. data/lib/gooddata/models/user_filters/user_filter_builder.rb +18 -6
  73. data/lib/gooddata/rest/client.rb +1 -2
  74. data/lib/gooddata/rest/connection.rb +12 -46
  75. data/lib/gooddata/rest/phmap.rb +101 -56
  76. data/lib/gooddata/version.rb +1 -1
  77. data/rubydev_public.gpg.encrypted +51 -0
  78. data/rubydev_secret_keys.gpg.encrypted +109 -0
  79. data/spec/data/user_filters.csv +2 -0
  80. data/spec/environment/default.rb +2 -2
  81. data/spec/environment/development.rb +1 -1
  82. data/spec/environment/staging.rb +2 -3
  83. data/spec/environment/testing.rb +4 -4
  84. data/spec/integration/connection_spec.rb +37 -0
  85. data/spec/integration/core/connection_spec.rb +1 -1
  86. data/spec/integration/core/logging_spec.rb +8 -6
  87. data/spec/integration/core/project_spec.rb +1 -1
  88. data/spec/integration/mandatory_user_filter_spec.rb +53 -0
  89. data/spec/integration/mixins/id_to_uri_spec.rb +17 -5
  90. data/spec/integration/models/label_spec.rb +9 -0
  91. data/spec/integration/models/metric_spec.rb +24 -0
  92. data/spec/integration/models/process_spec.rb +35 -0
  93. data/spec/integration/models/project_role_spec.rb +1 -1
  94. data/spec/integration/models/schedule_spec.rb +0 -8
  95. data/spec/integration/schedule_spec.rb +4 -6
  96. data/spec/integration/user_filters_spec.rb +20 -16
  97. data/spec/integration/user_group_spec.rb +1 -1
  98. data/spec/integration/vcr_cassettes/GoodData_-_logging/_logger/can_assign_a_custom_logger.yml +2287 -0
  99. data/spec/integration/vcr_cassettes/GoodData_-_logging/_logger/client_logs_when_given_custom_message.yml +2287 -0
  100. data/spec/integration/vcr_cassettes/GoodData_-_logging/_logger/has_the_request_id_logged_when_I_passed_it.yml +2287 -0
  101. data/spec/integration/vcr_cassettes/GoodData_-_logging/_logging_off/Disables_logging.yml +2287 -0
  102. data/spec/integration/vcr_cassettes/GoodData_-_logging/_logging_on/Enables_logging.yml +2287 -0
  103. data/spec/integration/vcr_cassettes/GoodData_-_project/_project/Returns_project_assigned.yml +354 -0
  104. data/spec/integration/vcr_cassettes/GoodData_-_project/_project_/Assigns_nil.yml +299 -0
  105. data/spec/integration/vcr_cassettes/GoodData_-_project/_project_/Assigns_project_directly.yml +354 -0
  106. data/spec/integration/vcr_cassettes/GoodData_-_project/_project_/Assigns_project_using_project_ID.yml +354 -0
  107. data/spec/integration/vcr_cassettes/GoodData_-_project/_project_/Assigns_project_using_project_URL.yml +354 -0
  108. data/spec/integration/vcr_cassettes/GoodData_-_project/_with_project/Uses_project_specified.yml +354 -0
  109. data/spec/integration/vcr_cassettes/GoodData_Metric/all.yml +2065 -0
  110. data/spec/integration/vcr_cassettes/GoodData_Metric/should_be_able_to_update_folders.yml +119 -0
  111. data/spec/integration/vcr_cassettes/GoodData_Mixin_MdIdToUri/all.yml +9812 -0
  112. data/spec/integration/vcr_cassettes/GoodData_Mixin_MdIdToUri/should_get_json_containing_correct_id.yml +174 -0
  113. data/spec/integration/vcr_cassettes/GoodData_Mixin_MdIdToUri/should_return_nil_for_unknown_id.yml +58 -0
  114. data/spec/integration/vcr_cassettes/GoodData_Mixin_MdIdToUri/should_throw_BadRequest_for_-1.yml +63 -0
  115. data/spec/integration/vcr_cassettes/GoodData_Rest_Connection/_connect/Connects_using_username_and_password.yml +299 -0
  116. data/spec/integration/vcr_cassettes/GoodData_Rest_Connection/_disconnect/Connects_using_username_and_password.yml +299 -0
  117. data/spec/integration/vcr_cassettes/GoodData_Rest_Connection/_generate_request_id/Generates_a_non-empty_string.yml +2287 -0
  118. data/spec/integration/vcr_cassettes/GoodData_UserGroup/_/Should_list_user_groups_as_Array.yml +56 -0
  119. data/spec/integration/vcr_cassettes/GoodData_UserGroup/_add_members/Should_add_member.yml +315 -0
  120. data/spec/integration/vcr_cassettes/GoodData_UserGroup/_members/Should_return_members_as_array.yml +54 -0
  121. data/spec/integration/vcr_cassettes/GoodData_UserGroup/_remove_members/Should_remove_existing_members.yml +258 -0
  122. data/spec/integration/vcr_cassettes/GoodData_UserGroup/_save/updates_existing_group.yml +159 -0
  123. data/spec/integration/vcr_cassettes/GoodData_UserGroup/_set_members/Should_set_new_members.yml +158 -0
  124. data/spec/integration/vcr_cassettes/GoodData_UserGroup/all.yml +809 -0
  125. data/spec/spec_helper.rb +46 -2
  126. data/spec/unit/actions/associate_clients_spec.rb +2 -1
  127. data/spec/unit/actions/collect_data_product_spec.rb +3 -1
  128. data/spec/unit/actions/collect_segment_clients_spec.rb +1 -0
  129. data/spec/unit/actions/create_segment_masters_spec.rb +1 -0
  130. data/spec/unit/actions/ensure_data_product_spec.rb +1 -0
  131. data/spec/unit/actions/ensure_technical_users_domain_spec.rb +2 -0
  132. data/spec/unit/actions/ensure_technical_users_project_spec.rb +4 -0
  133. data/spec/unit/actions/provision_clients_spec.rb +2 -1
  134. data/spec/unit/actions/synchronize_etls_in_segment_spec.rb +0 -6
  135. data/spec/unit/actions/synchronize_ldm_spec.rb +20 -7
  136. data/spec/unit/actions/synchronize_user_filters_spec.rb +21 -0
  137. data/spec/unit/helpers/check_helper_production_spec.rb +34 -0
  138. data/spec/unit/helpers/check_helper_spec.rb +97 -9
  139. data/spec/unit/lcm/lcm2_spec.rb +67 -3
  140. data/spec/unit/models/blueprint/to_wire_spec.rb +1 -0
  141. data/spec/unit/models/dataset_blueprint.rb +14 -0
  142. data/spec/unit/models/from_wire_spec.rb +20 -0
  143. data/spec/unit/models/model_spec.rb +10 -0
  144. data/spec/unit/models/to_manifest_spec.rb +29 -0
  145. data/spec/unit/models/user_filters/user_filter_builder_spec.rb +44 -6
  146. data/spec/unit/rest/phmap_spec.rb +117 -0
  147. data/spec/vcr_configurer.rb +63 -0
  148. metadata +283 -24
  149. data/lib/gooddata/lcm/actions/ensure_segments.rb +0 -32
@@ -6,16 +6,29 @@
6
6
 
7
7
  require 'gooddata/lcm/lcm2'
8
8
 
9
+ shared_examples 'a smart hash' do
10
+ let(:expected_value) { 'bar' }
11
+ it 'fetches value' do
12
+ expect(subject.FOO).to eq(expected_value)
13
+ expect(subject.foo).to eq(expected_value)
14
+ expect(subject['FOO']).to eq(expected_value)
15
+ expect(subject['foo']).to eq(expected_value)
16
+ expect(subject[:FOO]).to eq(expected_value)
17
+ expect(subject[:foo]).to eq(expected_value)
18
+ end
19
+ end
20
+
9
21
  describe 'GoodData::LCM2' do
10
22
  describe '#skip_actions' do
11
23
  let(:client) { double(:client) }
12
- let(:domain) { double(:domain) }
13
- let(:logger) { double(:logger) }
24
+ let(:domain) { 'domain' }
25
+ let(:logger) { GoodData.logger }
14
26
  let(:params) do
15
27
  params = {
16
28
  skip_actions: %w(CollectSegments SynchronizeUsers),
17
29
  GDC_GD_CLIENT: client,
18
- GDC_LOGGER: logger
30
+ GDC_LOGGER: logger,
31
+ domain: domain
19
32
  }
20
33
  GoodData::LCM2.convert_to_smart_hash(params)
21
34
  end
@@ -33,4 +46,55 @@ describe 'GoodData::LCM2' do
33
46
  GoodData::LCM2.perform('users', params)
34
47
  end
35
48
  end
49
+
50
+ describe '#convert_to_smart_hash' do
51
+ subject do
52
+ GoodData::LCM2.convert_to_smart_hash(hash)
53
+ end
54
+
55
+ let(:hash) { { fooBarBaz: 'qUx' } }
56
+
57
+ it 'keeps letter case' do
58
+ expect(subject.to_h).to eq(hash)
59
+ end
60
+
61
+ context 'when hash contains symbol key in lower-case' do
62
+ it_behaves_like 'a smart hash' do
63
+ let(:hash) { { foo: 'bar' } }
64
+ end
65
+ end
66
+
67
+ context 'when hash contains string key in lower-case' do
68
+ it_behaves_like 'a smart hash' do
69
+ let(:hash) { { 'foo' => 'bar' } }
70
+ end
71
+ end
72
+
73
+ context 'when hash contains symbol key in upper-case' do
74
+ it_behaves_like 'a smart hash' do
75
+ let(:hash) { { FOO: 'bar' } }
76
+ end
77
+ end
78
+
79
+ context 'when hash contains string key in upper-case' do
80
+ it_behaves_like 'a smart hash' do
81
+ let(:hash) { { 'FOO' => 'bar' } }
82
+ end
83
+ end
84
+ end
85
+
86
+ describe '#run_action' do
87
+ let(:params) { double('params') }
88
+ let(:logger) { GoodData.logger }
89
+ it 'runs the action' do
90
+ expect(params).to receive(:clear_filters).exactly(2).times
91
+ expect(params).to receive(:segments_filter)
92
+ expect(params).to receive(:data_product)
93
+ expect(params).to receive(:gdc_logger) { logger }
94
+ expect(params).to receive(:setup_filters)
95
+
96
+ expect(GoodData::LCM2::CollectSegments).to receive(:call)
97
+ GoodData::LCM2.run_action(GoodData::LCM2::CollectSegments, params)
98
+ end
99
+ end
36
100
  end
@@ -146,6 +146,7 @@ describe GoodData::Model::ProjectBlueprint do
146
146
  result = ToWire.fact_to_wire(nil, fact_def)
147
147
  expect(result).to eq(
148
148
  fact: {
149
+ type: "fact",
149
150
  identifier: "fact.stage_history.stage_velocity",
150
151
  title: "Stage Velocity",
151
152
  dataType: "DECIMAL(12,2)",
@@ -0,0 +1,14 @@
1
+ describe GoodData::Model::DatasetBlueprint do
2
+ let(:dataset) do
3
+ { columns: [{ type: 'hll' },
4
+ { type: 'fact' },
5
+ { type: 'date_fact' }] }
6
+ end
7
+ subject { GoodData::Model::DatasetBlueprint }
8
+ describe '.facts' do
9
+ it 'returns facts of supported types' do
10
+ result = subject.facts(dataset)
11
+ expect(result).to eq(dataset[:columns])
12
+ end
13
+ end
14
+ end
@@ -233,6 +233,26 @@ describe GoodData::Model::FromWire do
233
233
  }
234
234
  ])
235
235
  end
236
+
237
+ it 'supports hll' do
238
+ model = @model_view['projectModelView']['model']['projectModel']['datasets'].first
239
+ hll_fact = { "fact" => {
240
+ "identifier" => "hll_test",
241
+ "title" => "Test HLL Fact",
242
+ "dataType" => "HLL",
243
+ 'type' => 'hll'
244
+ } }
245
+ model['dataset']['facts'] << hll_fact
246
+ expected = {
247
+ type: :hll,
248
+ id: "hll_test",
249
+ title: "Test HLL Fact",
250
+ gd_data_type: "HLL",
251
+ folder: nil
252
+ }
253
+ facts = GoodData::Model::FromWire.parse_facts(model)
254
+ expect(facts).to include(expected)
255
+ end
236
256
  end
237
257
 
238
258
  describe '#parse_dataset' do
@@ -74,4 +74,14 @@ describe GoodData::Model do
74
74
  @base_blueprint.merge!(@additional_blueprint)
75
75
  @base_blueprint.find_dataset("dataset.repos").attributes.include?(type: "attribute", id: "some_attr_id", :title => "Repository Name")
76
76
  end
77
+
78
+ describe '.check_gd_data_type' do
79
+ let(:hll_types) { %w(HLL hll hLl) }
80
+ it 'supports HLL type' do
81
+ hll_types.each do |type|
82
+ actual = subject.check_gd_data_type(type)
83
+ expect(actual).to be(true)
84
+ end
85
+ end
86
+ end
77
87
  end
@@ -18,6 +18,35 @@ describe GoodData::Model::ToManifest do
18
18
  expect(ToManifest.to_manifest(@spec)).to eq @result
19
19
  end
20
20
 
21
+ context 'when HLL fact is in the spec' do
22
+ let(:hll_fact) do
23
+ {
24
+ type: "hll",
25
+ id: 'fact.commits.lines_added',
26
+ column_name: 'lines_added',
27
+ title: 'Lines Added'
28
+ }
29
+ end
30
+
31
+ let(:spec) do
32
+ hll_spec = @spec
33
+ hll_spec[:datasets]
34
+ .find { |d| d[:id] == 'dataset.commits' }[:columns] << hll_fact
35
+ hll_spec
36
+ end
37
+
38
+ it "converts the HLL fact to manifest" do
39
+ actual = ToManifest.to_manifest(spec)
40
+ expected = {
41
+ 'populates' => ['fact.commits.lines_added'],
42
+ 'mode' => 'FULL',
43
+ 'columnName' => 'lines_added'
44
+ }
45
+ parts = actual[2]['dataSetSLIManifest']['parts']
46
+ expect(parts).to include(expected)
47
+ end
48
+ end
49
+
21
50
  it 'blueprint can be set with date reference and default format is set' do
22
51
  blueprint = GoodData::Model::ProjectBlueprint.build("my_bp") do |p|
23
52
  p.add_date_dimension("committed_on")
@@ -4,6 +4,14 @@
4
4
  # This source code is licensed under the BSD-style license found in the
5
5
  # LICENSE file in the root directory of this source tree.
6
6
 
7
+ shared_examples 'a user filter deleter' do
8
+ it 'deletes the filter' do
9
+ expect(existing_filter).to receive(:delete)
10
+ result = subject.execute_mufs(filter_definitions, options)
11
+ expect(result[:deleted].length).to be(1)
12
+ end
13
+ end
14
+
7
15
  describe GoodData::UserFilterBuilder do
8
16
  describe '.execute_mufs' do
9
17
  let(:login) { 'rubydev+admin@gooddata.com' }
@@ -63,10 +71,29 @@ describe GoodData::UserFilterBuilder do
63
71
  end
64
72
 
65
73
  it 'resolves mufs to be created/deleted' do
66
- expect(existing_filter).to receive(:delete)
74
+ expect(existing_filter).to_not receive(:delete)
67
75
  result = subject.execute_mufs(filter_definitions, options)
68
76
  expect(result[:created].length).to be(1)
69
- expect(result[:deleted].length).to be(1)
77
+ expect(result[:deleted].length).to be(0)
78
+ end
79
+
80
+ context 'when dry_run option set to true' do
81
+ let(:options) do
82
+ { client: client,
83
+ project: project,
84
+ dry_run: true }
85
+ end
86
+
87
+ it 'does not alter filters' do
88
+ expect(client).not_to receive(:post)
89
+ subject.execute_mufs(filter_definitions, options)
90
+ end
91
+
92
+ it 'returns results' do
93
+ result = subject.execute_mufs(filter_definitions, options)
94
+ expected = [{ status: 'dry_run', user: nil, type: 'create' }]
95
+ expect(result[:results]).to eq(expected)
96
+ end
70
97
  end
71
98
 
72
99
  context 'when users_brick_input option specified' do
@@ -88,10 +115,10 @@ describe GoodData::UserFilterBuilder do
88
115
  allow(existing_filter).to receive(:json)
89
116
  .and_return(related: profile_url)
90
117
  end
91
- it 'deletes the filter' do
92
- expect(existing_filter).to receive(:delete)
93
- result = subject.execute_mufs(filter_definitions, options)
94
- expect(result[:deleted].length).to be(1)
118
+ it_behaves_like 'a user filter deleter'
119
+ context 'when users_brick_input has symbols as keys' do
120
+ let(:users_brick_input) { [{ login: login }] }
121
+ it_behaves_like 'a user filter deleter'
95
122
  end
96
123
  end
97
124
 
@@ -107,5 +134,16 @@ describe GoodData::UserFilterBuilder do
107
134
  end
108
135
  end
109
136
  end
137
+
138
+ context 'when creating MUFs results in errors' do
139
+ before do
140
+ allow(client).to receive(:post)
141
+ .and_return 'userFiltersUpdateResult' => { 'failed' => [{ status: :failed }] }
142
+ end
143
+
144
+ it 'fails' do
145
+ expect { subject.execute_mufs(filter_definitions, options) }.to raise_error(/Creating MUFs resulted in errors/)
146
+ end
147
+ end
110
148
  end
111
149
  end
@@ -0,0 +1,117 @@
1
+ # encoding: UTF-8
2
+ #
3
+ # Copyright (c) 2010-2017 GoodData Corporation. All rights reserved.
4
+ # This source code is licensed under the BSD-style license found in the
5
+ # LICENSE file in the root directory of this source tree.
6
+
7
+ require 'gooddata/rest/phmap'
8
+
9
+ PlaceholderExample = Struct.new(:name, :title, :mapped)
10
+
11
+ describe GoodData::Rest::Connection do
12
+ [
13
+ PlaceholderExample.new('execute', '/gdc/projects/uif55z7zg9zunnsffsqu6nzyg38j20qg/execute', '/gdc/projects/{id}/execute'),
14
+
15
+ PlaceholderExample.new('outputStage', '/gdc/dataload/projects/uif55z7zg9zunnsffsqu6nzyg38j20qg/outputStage', '/gdc/dataload/projects/{id}/outputStage'),
16
+
17
+ PlaceholderExample.new('datawarehouse instance', '/gdc/datawarehouse/instances/c90ef89f07978760523dd409165c71f3', '/gdc/datawarehouse/instances/{id}'),
18
+ PlaceholderExample.new('datawarehouse execution', '/gdc/datawarehouse/executions/exec123', '/gdc/datawarehouse/executions/{id}'),
19
+
20
+ PlaceholderExample.new('dataproduct client segment', '/gdc/domains/stg2-lcm-prod/dataproducts/MY-DP/clients?segment=MY-SEG4',
21
+ '/gdc/domains/{id}/dataproducts/{data_product}/clients?segment={segment}'),
22
+ PlaceholderExample.new('dataproduct client', '/gdc/domains/MY_DOMAIN3/dataproducts/4_7-prod/clients/some-client1',
23
+ '/gdc/domains/{id}/dataproducts/{data_product}/clients/{client}'),
24
+ PlaceholderExample.new('dataproduct clients', '/gdc/domains/D_-3/dataproducts/DP_1-/clients', '/gdc/domains/{id}/dataproducts/{data_product}/clients'),
25
+
26
+ PlaceholderExample.new('synchronizeClients result details', '/gdc/domains/d2/dataproducts/dp-6/segments/seg_1/synchronizeClients/results/_-res8/details?offset=0&limit=1000',
27
+ '/gdc/domains/{id}/dataproducts/{data_product}/segments/{segment}/synchronizeClients/results/{result}/details?offset={offset}&limit={limit}'),
28
+ PlaceholderExample.new('synchronizeClients result', '/gdc/domains/D/dataproducts/DP/segments/SEG/synchronizeClients/results/RES',
29
+ '/gdc/domains/{id}/dataproducts/{data_product}/segments/{segment}/synchronizeClients/results/{result}'),
30
+ PlaceholderExample.new('dataproduct segment', '/gdc/domains/D/dataproducts/DP/segments/SEG', '/gdc/domains/{id}/dataproducts/{data_product}/segments/{segment}'),
31
+ PlaceholderExample.new('dataproduct segments', '/gdc/domains/D/dataproducts/DP/segments', '/gdc/domains/{id}/dataproducts/{data_product}/segments'),
32
+
33
+ PlaceholderExample.new('provisionClientProjects result details', '/gdc/domains/D/dataproducts/DP/provisionClientProjects/results/RES/details?offset=7&limit=50',
34
+ '/gdc/domains/{id}/dataproducts/{data_product}/provisionClientProjects/results/{result}/details?offset={offset}&limit={limit}'),
35
+ PlaceholderExample.new('provisionClientProjects result', '/gdc/domains/D/dataproducts/DP/provisionClientProjects/results/RES',
36
+ '/gdc/domains/{id}/dataproducts/{data_product}/provisionClientProjects/results/{result}'),
37
+ PlaceholderExample.new('provisionClientProjects', '/gdc/domains/D/dataproducts/DP/provisionClientProjects',
38
+ '/gdc/domains/{id}/dataproducts/{data_product}/provisionClientProjects'),
39
+ PlaceholderExample.new('updateClients delet extra', '/gdc/domains/D/dataproducts/DP/updateClients?deleteExtraInSegments=SEG',
40
+ '/gdc/domains/{id}/dataproducts/{data_product}/updateClients?deleteExtraInSegments={segments}'),
41
+ PlaceholderExample.new('updateClients', '/gdc/domains/D/dataproducts/DP/updateClients', '/gdc/domains/{id}/dataproducts/{data_product}/updateClients'),
42
+
43
+ PlaceholderExample.new('domain dataproducts', '/gdc/domains/D/dataproducts/DP', '/gdc/domains/{id}/dataproducts/{data_product}'),
44
+ PlaceholderExample.new('domain dataproducts', '/gdc/domains/D/dataproducts', '/gdc/domains/{id}/dataproducts'),
45
+
46
+ PlaceholderExample.new('segment synchronizeClients result details', '/gdc/domains/D/segments/SEG/synchronizeClients/results/RES/details?offset=0&limit=100',
47
+ '/gdc/domains/{id}/segments/{segment}/synchronizeClients/results/{result}/details?offset={offset}&limit={limit}'),
48
+ PlaceholderExample.new('segment synchronizeClients result', '/gdc/domains/D/segments/SEG/synchronizeClients/results/RES',
49
+ '/gdc/domains/{id}/segments/{segment}/synchronizeClients/results/{result}'),
50
+ PlaceholderExample.new('domain segment', '/gdc/domains/D/segments/SEG/', '/gdc/domains/{id}/segments/{segment}/'),
51
+ PlaceholderExample.new('domain segment', '/gdc/domains/D/segments/SEG', '/gdc/domains/{id}/segments/{segment}'),
52
+
53
+ PlaceholderExample.new('domain client segment', '/gdc/domains/D/clients?segment=SEG', '/gdc/domains/{id}/clients?segment={segment}'),
54
+ PlaceholderExample.new('client settings title', '/gdc/domains/D/clients/C/settings/lcm.title', '/gdc/domains/{id}/clients/{client_id}/settings/lcm.title'),
55
+ PlaceholderExample.new('client settings token', '/gdc/domains/D/clients/C/settings/lcm.token', '/gdc/domains/{id}/clients/{client_id}/settings/lcm.token'),
56
+ PlaceholderExample.new('domain client', '/gdc/domains/D/clients/C', '/gdc/domains/{id}/clients/{client_id}'),
57
+ PlaceholderExample.new('domain provisionClientProjects result details', '/gdc/domains/D/provisionClientProjects/results/R/details?offset=0&limit=100',
58
+ '/gdc/domains/{id}/provisionClientProjects/results/{result}/details?offset={offset}&limit={limit}'),
59
+ PlaceholderExample.new('domain provisionClientProjects result', '/gdc/domains/D/provisionClientProjects/results/R',
60
+ '/gdc/domains/{id}/provisionClientProjects/results/{result}'),
61
+ PlaceholderExample.new('domain provisionClientProjects', '/gdc/domains/D/provisionClientProjects', '/gdc/domains/{id}/provisionClientProjects'),
62
+ PlaceholderExample.new('domain updateClients', '/gdc/domains/D/updateClients', '/gdc/domains/{id}/updateClients'),
63
+ PlaceholderExample.new('domain', '/gdc/domains/D/', '/gdc/domains/{id}/'),
64
+
65
+ PlaceholderExample.new('exporter result', '/gdc/exporter/result/a23f/c56', '/gdc/exporter/result/{id}/{id}'),
66
+
67
+ PlaceholderExample.new('syncProcesses task', '/gdc/internal/lcm/domains/D/dataproducts/DP/segments/SEG/syncProcesses/P',
68
+ '/gdc/internal/lcm/domains/{id}/dataproducts/{data_product}/segments/{segment}/syncProcesses/{process}'),
69
+ PlaceholderExample.new('syncProcesses', '/gdc/internal/lcm/domains/D/dataproducts/DP/segments/SEG/syncProcesses',
70
+ '/gdc/internal/lcm/domains/{id}/dataproducts/{data_product}/segments/{segment}/syncProcesses'),
71
+
72
+ PlaceholderExample.new('setPermissions', '/gdc/internal/projects/PID/objects/setPermissions', '/gdc/internal/projects/{id}/objects/setPermissions'),
73
+
74
+ PlaceholderExample.new('md variable', '/gdc/md/PID/variables/item/54', '/gdc/md/{id}/variables/item/{id}'),
75
+ PlaceholderExample.new('md validate task', '/gdc/md/PID/validate/task/some-task56', '/gdc/md/{id}/validate/task/{id}'),
76
+ PlaceholderExample.new('md using', '/gdc/md/PID/using2/456/980', '/gdc/md/{id}/using2/{id}/{id}'),
77
+ PlaceholderExample.new('md using', '/gdc/md/PID/using2/456', '/gdc/md/{id}/using2/{id}'),
78
+ PlaceholderExample.new('md userfilters user', '/gdc/md/PID/userfilters?users=/gdc/account/profile/rubydev+admin@goo', '/gdc/md/{id}/userfilters?users={users}'),
79
+ PlaceholderExample.new('md userfilters', '/gdc/md/PID/userfilters?count=1&offset=5', '/gdc/md/{id}/userfilters?count={count}&offset={offset}'),
80
+ PlaceholderExample.new('md usedby', '/gdc/md/PID/usedby2/4/5', '/gdc/md/{id}/usedby2/{id}/{id}'),
81
+ PlaceholderExample.new('md usedby', '/gdc/md/PID/usedby2/4', '/gdc/md/{id}/usedby2/{id}'),
82
+ PlaceholderExample.new('md task status', '/gdc/md/PID/tasks/567/status', '/gdc/md/{id}/tasks/{id}/status'),
83
+ PlaceholderExample.new('md validElements', '/gdc/md/PID/obj/876/validElements', '/gdc/md/{id}/obj/{id}/validElements'),
84
+ PlaceholderExample.new('md elements', '/gdc/md/PID/obj/876/elements', '/gdc/md/{id}/obj/{id}/elements'),
85
+ PlaceholderExample.new('md obj', '/gdc/md/PID/obj/876', '/gdc/md/{id}/obj/{id}'),
86
+ PlaceholderExample.new('md etltaks', '/gdc/md/PID/etltask/567', '/gdc/md/{id}/etltask/{id}'),
87
+ PlaceholderExample.new('md dataResult', '/gdc/md/PID/dataResult/666', '/gdc/md/{id}/dataResult/{id}'),
88
+ PlaceholderExample.new('md', '/gdc/md/PID', '/gdc/md/{id}'),
89
+
90
+ PlaceholderExample.new('project user roles', '/gdc/projects/PID/users/UID/roles', '/gdc/projects/{id}/users/{id}/roles'),
91
+ PlaceholderExample.new('project user permissions', '/gdc/projects/PID/users/UID/permissions', '/gdc/projects/{id}/users/{id}/permissions'),
92
+ PlaceholderExample.new('project users', '/gdc/projects/PID/users', '/gdc/projects/{id}/users'),
93
+ PlaceholderExample.new('schedule execution', '/gdc/projects/PID/schedules/SCHED/executions/EX', '/gdc/projects/{id}/schedules/{id}/executions/{id}'),
94
+ PlaceholderExample.new('schedule', '/gdc/projects/PID/schedules/SCHED', '/gdc/projects/{id}/schedules/{id}'),
95
+ PlaceholderExample.new('project role', '/gdc/projects/PID/roles/555', '/gdc/projects/{id}/roles/{id}'),
96
+ PlaceholderExample.new('model view view', '/gdc/projects/PID/model/view/VIEW', '/gdc/projects/{id}/model/view/{id}'),
97
+ PlaceholderExample.new('model view', '/gdc/projects/PID/model/view', '/gdc/projects/{id}/model/view'),
98
+ PlaceholderExample.new('model diff diff', '/gdc/projects/PID/model/diff/DIFF', '/gdc/projects/{id}/model/diff/{id}'),
99
+ PlaceholderExample.new('model diff', '/gdc/projects/PID/model/diff', '/gdc/projects/{id}/model/diff'),
100
+ PlaceholderExample.new('dataload metadata', '/gdc/projects/PID/dataload/metadata/PID', '/gdc/projects/{id}/dataload/metadata/{project}'),
101
+ PlaceholderExample.new('dataload execution', '/gdc/projects/PID/dataload/processes/PRID/executions/EX', '/gdc/projects/{id}/dataload/processes/{id}/executions/{id}'),
102
+ PlaceholderExample.new('dataload process', '/gdc/projects/PID/dataload/processes/PRID', '/gdc/projects/{id}/dataload/processes/{id}'),
103
+ PlaceholderExample.new('project', '/gdc/projects/PID/', '/gdc/projects/{id}/'),
104
+ PlaceholderExample.new('project', '/gdc/projects/PID', '/gdc/projects/{id}'),
105
+
106
+ PlaceholderExample.new('userGroup', '/gdc/userGroups/GID', '/gdc/userGroups/{id}'),
107
+
108
+ PlaceholderExample.new('profile', '/gdc/account/profile/UID', '/gdc/account/profile/{id}'),
109
+ PlaceholderExample.new('login', '/gdc/account/login/UID', '/gdc/account/login/{id}'),
110
+ PlaceholderExample.new('domain user', '/gdc/account/domains/D/users?login=rubydev+admin@gooddata.com', '/gdc/account/domains/{id}/users?login={login}'),
111
+ PlaceholderExample.new('account domain', '/gdc/account/domains/D', '/gdc/account/domains/{id}')
112
+ ].each do |example|
113
+ it "should map placeholders in #{example.name} API" do
114
+ expect(GoodData::Rest::Connection.map_placeholders(example.title)).to eq(example.mapped)
115
+ end
116
+ end
117
+ end
@@ -0,0 +1,63 @@
1
+ require 'vcr'
2
+ require 'active_support/core_ext/string'
3
+
4
+ module GoodData
5
+ module Helpers
6
+ # Configures VCR for integration tests
7
+ class VcrConfigurer
8
+ def self.name_to_placeholder(name)
9
+ "<#{name.underscore.upcase}>"
10
+ end
11
+
12
+ def self.filter_body_field(vcr_config, part, field)
13
+ placeholder = name_to_placeholder(field)
14
+ vcr_config.filter_sensitive_data(placeholder) do |interaction|
15
+ body_match = interaction[part].body.match(/"#{Regexp.quote(field)}":\s*"([^"]+)"/)
16
+ body_match.captures.first if body_match
17
+ end
18
+ end
19
+
20
+ def self.filter_header(vcr_config, part, header_name)
21
+ placeholder = name_to_placeholder(header_name)
22
+ vcr_config.filter_sensitive_data(placeholder) do |interaction|
23
+ header = interaction[part].headers[header_name]
24
+ header.first if header
25
+ end
26
+ end
27
+
28
+ # custom path matcher, sanitizing the randomness of uploads dirs
29
+ gdc_path_matcher = lambda do |client_request, recorded_request|
30
+ client_path = client_request.parsed_uri.path
31
+ recorded_path = recorded_request.parsed_uri.path
32
+ uploads_regex = %r{(\/gdc\/uploads\/)[^\/]+(\/.*)}
33
+ if client_path.match(uploads_regex) && recorded_path.match(uploads_regex)
34
+ client_path.gsub(uploads_regex, '\1UPLOADS_TMP\2') == recorded_path.gsub(uploads_regex, '\1UPLOADS_TMP\2')
35
+ else
36
+ client_path == recorded_path
37
+ end
38
+ end
39
+
40
+ VCR.configure do |vcr_config|
41
+ vcr_config.cassette_library_dir = 'spec/integration/vcr_cassettes'
42
+ vcr_config.hook_into :webmock
43
+ vcr_config.allow_http_connections_when_no_cassette = true
44
+ vcr_config.configure_rspec_metadata!
45
+
46
+ vcr_config.default_cassette_options = {
47
+ :decode_compressed_response => true,
48
+ :match_requests_on => [gdc_path_matcher, :method, :query],
49
+ # allow to set record mode from environment, see https://relishapp.com/vcr/vcr/v/3-0-3/docs/record-modes
50
+ :record => (ENV['VCR_RECORD_MODE'] && ENV['VCR_RECORD_MODE'].to_sym) || :once
51
+ }
52
+
53
+ %w(request response).each do |part|
54
+ filter_body_field(vcr_config, part, 'password')
55
+ filter_body_field(vcr_config, part, 'token')
56
+ filter_body_field(vcr_config, part, 'authorizationToken')
57
+ filter_header(vcr_config, part, 'X-Gdc-Authsst')
58
+ filter_header(vcr_config, part, 'X-Gdc-Authtt')
59
+ end
60
+ end
61
+ end
62
+ end
63
+ end