gooddata 0.6.53 → 0.6.54
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 +5 -5
- data/.flayignore +6 -0
- data/.gitignore +1 -0
- data/.pronto.yml +3 -0
- data/.rspec +2 -0
- data/.rubocop.yml +4 -1
- data/CHANGELOG.md +18 -0
- data/CONTRIBUTING.md +14 -1
- data/DEPENDENCIES.md +324 -253
- data/Dockerfile.jruby +5 -7
- data/Dockerfile.ruby +8 -8
- data/Rakefile +24 -0
- data/ci.rake +47 -0
- data/docker-compose.yml +34 -0
- data/gooddata.gemspec +8 -2
- data/lib/gooddata/bricks/middleware/restforce_middleware.rb +0 -3
- data/lib/gooddata/helpers/data_helper.rb +10 -7
- data/lib/gooddata/helpers/global_helpers_params.rb +8 -3
- data/lib/gooddata/lcm/actions/apply_custom_maql.rb +2 -1
- data/lib/gooddata/lcm/actions/associate_clients.rb +10 -1
- data/lib/gooddata/lcm/actions/collect_client_projects.rb +78 -0
- data/lib/gooddata/lcm/actions/collect_clients.rb +20 -6
- data/lib/gooddata/lcm/actions/collect_data_product.rb +62 -0
- data/lib/gooddata/lcm/actions/collect_dynamic_schedule_params.rb +62 -0
- data/lib/gooddata/lcm/actions/{collect_attrs.rb → collect_ldm_objects.rb} +3 -3
- data/lib/gooddata/lcm/actions/collect_meta.rb +6 -3
- data/lib/gooddata/lcm/actions/collect_segment_clients.rb +2 -1
- data/lib/gooddata/lcm/actions/collect_segments.rb +6 -7
- data/lib/gooddata/lcm/actions/collect_tagged_objects.rb +7 -4
- data/lib/gooddata/lcm/actions/create_segment_masters.rb +7 -3
- data/lib/gooddata/lcm/actions/ensure_data_product.rb +53 -0
- data/lib/gooddata/lcm/actions/ensure_technical_users_domain.rb +6 -2
- data/lib/gooddata/lcm/actions/ensure_technical_users_project.rb +30 -18
- data/lib/gooddata/lcm/actions/execute_schedules.rb +128 -0
- data/lib/gooddata/lcm/actions/provision_clients.rb +32 -21
- data/lib/gooddata/lcm/actions/purge_clients.rb +25 -39
- data/lib/gooddata/lcm/actions/rename_existing_client_projects.rb +70 -0
- data/lib/gooddata/lcm/actions/segments_filter.rb +6 -0
- data/lib/gooddata/lcm/actions/synchronize_cas.rb +11 -0
- data/lib/gooddata/lcm/actions/synchronize_clients.rb +2 -1
- data/lib/gooddata/lcm/actions/synchronize_etls_in_segment.rb +34 -15
- data/lib/gooddata/lcm/actions/synchronize_ldm.rb +10 -1
- data/lib/gooddata/lcm/actions/synchronize_new_segments.rb +2 -1
- data/lib/gooddata/lcm/actions/synchronize_processes.rb +4 -7
- data/lib/gooddata/lcm/actions/synchronize_tag_objects.rb +8 -5
- data/lib/gooddata/lcm/actions/synchronize_user_filters.rb +224 -0
- data/lib/gooddata/lcm/actions/synchronize_user_groups.rb +53 -0
- data/lib/gooddata/lcm/actions/synchronize_users.rb +324 -0
- data/lib/gooddata/lcm/dsl/type_dsl.rb +1 -0
- data/lib/gooddata/lcm/helpers/check_helper.rb +4 -0
- data/lib/gooddata/lcm/helpers/tags_helper.rb +4 -3
- data/lib/gooddata/lcm/lcm2.rb +33 -1
- data/lib/gooddata/lcm/types/complex/segment.rb +3 -0
- data/lib/gooddata/lcm/types/complex/update_preference.rb +8 -2
- data/lib/gooddata/lcm/types/special/array.rb +1 -3
- data/lib/gooddata/lcm/types/special/enum.rb +1 -3
- data/lib/gooddata/mixins/md_id_to_uri.rb +0 -1
- data/lib/gooddata/mixins/md_json.rb +2 -2
- data/lib/gooddata/models/blueprint/project_blueprint.rb +15 -0
- data/lib/gooddata/models/blueprint/to_wire.rb +1 -0
- data/lib/gooddata/models/client.rb +21 -9
- data/lib/gooddata/models/data_product.rb +149 -0
- data/lib/gooddata/models/domain.rb +26 -72
- data/lib/gooddata/models/from_wire.rb +2 -0
- data/lib/gooddata/models/metadata/report.rb +9 -3
- data/lib/gooddata/models/metadata/report_definition.rb +2 -2
- data/lib/gooddata/models/model.rb +1 -1
- data/lib/gooddata/models/process.rb +4 -0
- data/lib/gooddata/models/project.rb +58 -35
- data/lib/gooddata/models/project_creator.rb +13 -0
- data/lib/gooddata/models/segment.rb +63 -16
- data/lib/gooddata/models/style_setting.rb +2 -15
- data/lib/gooddata/models/user_group.rb +2 -0
- data/lib/gooddata/rest/connection.rb +32 -9
- data/lib/gooddata/rest/object_factory.rb +0 -25
- data/lib/gooddata/version.rb +1 -1
- data/spec/data/blueprints/invalid_blueprint.json +2 -2
- data/spec/data/blueprints/test_project_model_spec.json +1 -1
- data/spec/data/dynamic_schedule_params_table.csv +7 -0
- data/spec/data/workspace_table.csv +3 -3
- data/spec/environment/staging.rb +3 -3
- data/spec/integration/ads_output_stage_spec.rb +0 -10
- data/spec/integration/clients_spec.rb +1 -1
- data/spec/{unit → integration}/commands/command_projects_spec.rb +0 -0
- data/spec/{unit → integration}/core/connection_spec.rb +0 -0
- data/spec/{unit → integration}/core/logging_spec.rb +0 -0
- data/spec/{unit → integration}/core/project_spec.rb +0 -0
- data/spec/integration/date_dim_switch_spec.rb +13 -0
- data/spec/integration/full_process_schedule_spec.rb +2 -2
- data/spec/integration/helpers_spec.rb +16 -0
- data/spec/integration/lcm_spec.rb +12 -2
- data/spec/integration/mixins/id_to_uri_spec.rb +44 -0
- data/spec/integration/models/data_product_spec.rb +71 -0
- data/spec/{unit → integration}/models/domain_spec.rb +2 -2
- data/spec/{unit → integration}/models/invitation_spec.rb +0 -0
- data/spec/{unit → integration}/models/membership_spec.rb +0 -0
- data/spec/{unit → integration}/models/params_spec.rb +0 -0
- data/spec/{unit → integration}/models/profile_spec.rb +0 -0
- data/spec/{unit → integration}/models/project_role_spec.rb +0 -0
- data/spec/integration/models/project_spec.rb +225 -0
- data/spec/{unit → integration}/models/schedule_spec.rb +0 -0
- data/spec/{unit → integration}/models/unit_project_spec.rb +0 -0
- data/spec/integration/project_spec.rb +40 -5
- data/spec/integration/segments_spec.rb +27 -26
- data/spec/integration/user_filters_spec.rb +1 -1
- data/spec/spec_helper.rb +15 -19
- data/spec/unit/actions/associate_clients_spec.rb +47 -0
- data/spec/unit/actions/collect_client_projects_spec.rb +47 -0
- data/spec/unit/actions/collect_clients_spec.rb +27 -0
- data/spec/unit/actions/collect_data_product_spec.rb +64 -0
- data/spec/unit/actions/collect_dynamic_schedule_params_spec.rb +56 -0
- data/spec/unit/actions/collect_meta_spec.rb +4 -4
- data/spec/unit/actions/collect_segment_clients_spec.rb +44 -3
- data/spec/unit/actions/collect_tagged_objects_spec.rb +20 -4
- data/spec/unit/actions/create_segment_masters_spec.rb +64 -0
- data/spec/unit/actions/ensure_data_product_spec.rb +38 -0
- data/spec/unit/actions/ensure_technical_users_domain_spec.rb +51 -0
- data/spec/unit/actions/ensure_technical_users_project_spec.rb +72 -0
- data/spec/unit/actions/execute_schedules_spec.rb +94 -0
- data/spec/unit/actions/provision_clients_spec.rb +45 -0
- data/spec/unit/actions/purge_clients_spec.rb +47 -0
- data/spec/unit/actions/rename_existing_client_projects_spec.rb +54 -0
- data/spec/unit/actions/segments_filter_spec.rb +46 -0
- data/spec/unit/actions/shared_examples_for_user_actions.rb +10 -0
- data/spec/unit/actions/synchronize_cas_spec.rb +58 -0
- data/spec/unit/actions/synchronize_etls_in_segment_spec.rb +174 -13
- data/spec/unit/actions/synchronize_ldm_spec.rb +57 -0
- data/spec/unit/actions/synchronize_user_filters_spec.rb +142 -0
- data/spec/unit/actions/synchronize_user_groups_spec.rb +49 -0
- data/spec/unit/actions/synchronize_users_spec.rb +76 -0
- data/spec/unit/helpers/data_helper_spec.rb +17 -0
- data/spec/unit/helpers/global_helpers_spec.rb +16 -0
- data/spec/unit/helpers_spec.rb +0 -6
- data/spec/unit/models/blueprint/project_blueprint_spec.rb +21 -4
- data/spec/unit/models/project_creator_spec.rb +16 -0
- data/spec/unit/models/project_spec.rb +66 -197
- metadata +202 -100
- data/PULL_REQUEST_TEMPLATE.md +0 -5
- data/lib/gooddata/bricks/middleware/params_inspect_middleware.rb +0 -21
|
@@ -25,6 +25,10 @@ module GoodData
|
|
|
25
25
|
fail "Expected parameter '#{param_name}' to be kind of '#{type}', got '#{value.class.name}'"
|
|
26
26
|
end
|
|
27
27
|
|
|
28
|
+
if specification[param_name][:opts][:deprecated]
|
|
29
|
+
puts "WARNING: Parameter '#{param_name}' is deprecated. Please use '#{specification[param_name][:opts][:replacement]}' instead."
|
|
30
|
+
end
|
|
31
|
+
|
|
28
32
|
unless type.check(value)
|
|
29
33
|
fail "Parameter '#{param_name}' has invalid type, expected: #{type}"
|
|
30
34
|
end
|
|
@@ -14,8 +14,8 @@ module GoodData
|
|
|
14
14
|
def segment_production_tags(segments)
|
|
15
15
|
return {} unless segments
|
|
16
16
|
segments
|
|
17
|
-
.reject { |s| s.
|
|
18
|
-
.map { |s| [s.segment_id, s.
|
|
17
|
+
.reject { |s| s.production_tags.nil? }
|
|
18
|
+
.map { |s| [s.segment_id, s.production_tags] }
|
|
19
19
|
.to_h
|
|
20
20
|
end
|
|
21
21
|
|
|
@@ -27,7 +27,8 @@ module GoodData
|
|
|
27
27
|
separator = ','
|
|
28
28
|
tags = segment_production_tags || production_tags
|
|
29
29
|
return [] unless tags
|
|
30
|
-
tags.split(separator).map(&:strip)
|
|
30
|
+
tags = tags.split(separator).map(&:strip) unless tags.is_a?(Array)
|
|
31
|
+
tags
|
|
31
32
|
end
|
|
32
33
|
end
|
|
33
34
|
end
|
data/lib/gooddata/lcm/lcm2.rb
CHANGED
|
@@ -80,12 +80,14 @@ module GoodData
|
|
|
80
80
|
|
|
81
81
|
release: [
|
|
82
82
|
EnsureReleaseTable,
|
|
83
|
+
EnsureDataProduct,
|
|
84
|
+
CollectDataProduct,
|
|
83
85
|
SegmentsFilter,
|
|
84
86
|
CreateSegmentMasters,
|
|
85
87
|
EnsureTechnicalUsersDomain,
|
|
86
88
|
EnsureTechnicalUsersProject,
|
|
87
89
|
SynchronizeLdm,
|
|
88
|
-
|
|
90
|
+
CollectLdmObjects,
|
|
89
91
|
CollectMeta,
|
|
90
92
|
CollectTaggedObjects,
|
|
91
93
|
CollectComputedAttributeMetrics,
|
|
@@ -94,24 +96,30 @@ module GoodData
|
|
|
94
96
|
SynchronizeProcesses,
|
|
95
97
|
SynchronizeSchedules,
|
|
96
98
|
SynchronizeColorPalette,
|
|
99
|
+
SynchronizeUserGroups,
|
|
97
100
|
SynchronizeNewSegments,
|
|
98
101
|
UpdateReleaseTable
|
|
99
102
|
],
|
|
100
103
|
|
|
101
104
|
provision: [
|
|
102
105
|
EnsureReleaseTable,
|
|
106
|
+
CollectDataProduct,
|
|
103
107
|
CollectSegments,
|
|
108
|
+
CollectClientProjects,
|
|
104
109
|
PurgeClients,
|
|
105
110
|
CollectClients,
|
|
106
111
|
AssociateClients,
|
|
112
|
+
RenameExistingClientProjects,
|
|
107
113
|
ProvisionClients,
|
|
108
114
|
EnsureTechnicalUsersDomain,
|
|
109
115
|
EnsureTechnicalUsersProject,
|
|
116
|
+
CollectDymanicScheduleParams,
|
|
110
117
|
SynchronizeETLsInSegment
|
|
111
118
|
],
|
|
112
119
|
|
|
113
120
|
rollout: [
|
|
114
121
|
EnsureReleaseTable,
|
|
122
|
+
CollectDataProduct,
|
|
115
123
|
CollectSegments,
|
|
116
124
|
CollectSegmentClients,
|
|
117
125
|
EnsureTechnicalUsersDomain,
|
|
@@ -120,7 +128,23 @@ module GoodData
|
|
|
120
128
|
ApplyCustomMaql,
|
|
121
129
|
SynchronizeClients,
|
|
122
130
|
SynchronizeComputedAttributes,
|
|
131
|
+
CollectDymanicScheduleParams,
|
|
123
132
|
SynchronizeETLsInSegment
|
|
133
|
+
],
|
|
134
|
+
|
|
135
|
+
users: [
|
|
136
|
+
CollectDataProduct,
|
|
137
|
+
CollectSegments,
|
|
138
|
+
SynchronizeUsers
|
|
139
|
+
],
|
|
140
|
+
|
|
141
|
+
user_filters: [
|
|
142
|
+
CollectDataProduct,
|
|
143
|
+
SynchronizeUserFilters
|
|
144
|
+
],
|
|
145
|
+
|
|
146
|
+
schedules_execution: [
|
|
147
|
+
ExecuteSchedules
|
|
124
148
|
]
|
|
125
149
|
}
|
|
126
150
|
|
|
@@ -130,6 +154,12 @@ module GoodData
|
|
|
130
154
|
def convert_params(params)
|
|
131
155
|
# Symbolize all keys
|
|
132
156
|
GoodData::Helpers.symbolize_keys!(params)
|
|
157
|
+
params.keys.each do |k|
|
|
158
|
+
params[k.downcase] = params[k]
|
|
159
|
+
end
|
|
160
|
+
params.reject! do |k, _|
|
|
161
|
+
k.downcase != k
|
|
162
|
+
end
|
|
133
163
|
convert_to_smart_hash(params)
|
|
134
164
|
end
|
|
135
165
|
|
|
@@ -278,6 +308,8 @@ module GoodData
|
|
|
278
308
|
|
|
279
309
|
# Invoke action
|
|
280
310
|
begin
|
|
311
|
+
GoodData.logger.info("Running #{action.name} action ...")
|
|
312
|
+
|
|
281
313
|
# Check if all required parameters were passed
|
|
282
314
|
BaseAction.check_params(action.const_get('PARAMS'), params)
|
|
283
315
|
|
|
@@ -26,6 +26,9 @@ module GoodData
|
|
|
26
26
|
|
|
27
27
|
description 'Master Project Name'
|
|
28
28
|
param :master_name, instance_of(Type::StringType), required: true
|
|
29
|
+
|
|
30
|
+
description 'Production Tag Names'
|
|
31
|
+
param :production_tags, array_of(instance_of(Type::StringType)), required: false
|
|
29
32
|
end
|
|
30
33
|
|
|
31
34
|
def check(value)
|
|
@@ -17,10 +17,16 @@ module GoodData
|
|
|
17
17
|
|
|
18
18
|
PARAMS = define_type(self) do
|
|
19
19
|
description 'Cascade Drop'
|
|
20
|
-
param :cascade_drops, instance_of(Type::BooleanType), required: false, default: nil
|
|
20
|
+
param :cascade_drops, instance_of(Type::BooleanType), required: false, default: nil, deprecated: true, replacement: :allow_cascade_drops
|
|
21
21
|
|
|
22
22
|
description 'Preserve Data'
|
|
23
|
-
param :preserve_data, instance_of(Type::BooleanType), required: false, default: nil
|
|
23
|
+
param :preserve_data, instance_of(Type::BooleanType), required: false, default: nil, deprecated: true, replacement: :keep_data
|
|
24
|
+
|
|
25
|
+
description 'Allow Cascade Drop'
|
|
26
|
+
param :allow_cascade_drops, instance_of(Type::BooleanType), required: false, default: false
|
|
27
|
+
|
|
28
|
+
description 'Keep Data'
|
|
29
|
+
param :keep_data, instance_of(Type::BooleanType), required: false, default: true
|
|
24
30
|
end
|
|
25
31
|
|
|
26
32
|
def check(value)
|
|
@@ -4,12 +4,10 @@
|
|
|
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
|
-
require_relative '../base_type'
|
|
8
|
-
|
|
9
7
|
module GoodData
|
|
10
8
|
module LCM2
|
|
11
9
|
module Type
|
|
12
|
-
class ArrayType
|
|
10
|
+
class ArrayType
|
|
13
11
|
CATEGORY = :special
|
|
14
12
|
|
|
15
13
|
def initialize(type)
|
|
@@ -4,12 +4,10 @@
|
|
|
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
|
-
require_relative '../base_type'
|
|
8
|
-
|
|
9
7
|
module GoodData
|
|
10
8
|
module LCM2
|
|
11
9
|
module Type
|
|
12
|
-
class EnumType
|
|
10
|
+
class EnumType
|
|
13
11
|
CATEGORY = :special
|
|
14
12
|
end
|
|
15
13
|
end
|
|
@@ -9,7 +9,6 @@ module GoodData
|
|
|
9
9
|
module MdIdToUri
|
|
10
10
|
IDENTIFIERS_CFG = 'instance-identifiers'
|
|
11
11
|
|
|
12
|
-
# TODO: Add test
|
|
13
12
|
def identifier_to_uri(opts = { :client => GoodData.connection, :project => GoodData.project }, *ids)
|
|
14
13
|
client, project = GoodData.get_client_and_project(opts)
|
|
15
14
|
|
|
@@ -742,11 +742,26 @@ module GoodData
|
|
|
742
742
|
stuff.map { |r| { type: :bad_reference, reference: r.data, referencing_dataset: r.data[:dataset] } }
|
|
743
743
|
end
|
|
744
744
|
|
|
745
|
+
# Validate the blueprint in particular if all ids must be unique and valid.
|
|
746
|
+
#
|
|
747
|
+
# @return [Array] array of errors
|
|
748
|
+
def validate_identifiers
|
|
749
|
+
ids = datasets.flat_map { |dataset| dataset.columns.map(&:id) }.compact
|
|
750
|
+
|
|
751
|
+
duplicated_ids = ids.select { |id| ids.count(id) > 1 }.uniq
|
|
752
|
+
errors = duplicated_ids.map { |id| { type: :duplicated_identifier, id: id } } || []
|
|
753
|
+
|
|
754
|
+
ids.uniq.each { |id| errors << { type: :invalid_identifier, id: id } if id !~ /^[\w.]+$/ }
|
|
755
|
+
|
|
756
|
+
errors
|
|
757
|
+
end
|
|
758
|
+
|
|
745
759
|
# Validate the blueprint and all its datasets return array of errors that are found.
|
|
746
760
|
#
|
|
747
761
|
# @return [Array] array of errors
|
|
748
762
|
def validate
|
|
749
763
|
errors = []
|
|
764
|
+
errors.concat validate_identifiers
|
|
750
765
|
errors.concat validate_references
|
|
751
766
|
errors.concat datasets.reduce([]) { |acc, elem| acc.concat(elem.validate) }
|
|
752
767
|
errors.concat datasets.reduce([]) { |acc, elem| acc.concat(elem.validate_gd_data_type_errors) }
|
|
@@ -113,6 +113,7 @@ module GoodData
|
|
|
113
113
|
dd[:name] = dataset[:id]
|
|
114
114
|
dd[:urn] = dataset[:urn] if dataset[:urn]
|
|
115
115
|
dd[:title] = GoodData::Model.title(dataset)
|
|
116
|
+
dd[:identifierPrefix] = dataset[:identifier_prefix] if dataset[:identifier_prefix]
|
|
116
117
|
end
|
|
117
118
|
{ dateDimension: payload }
|
|
118
119
|
end
|
|
@@ -33,13 +33,13 @@ module GoodData
|
|
|
33
33
|
domain = opts[:domain]
|
|
34
34
|
segment = opts[:segment]
|
|
35
35
|
fail ArgumentError, 'No :domain specified' if domain.nil?
|
|
36
|
-
fail ArgumentError, 'No :segment specified' if domain.nil?
|
|
37
|
-
|
|
38
36
|
client = domain.client
|
|
39
37
|
fail ArgumentError, 'No client specified' if client.nil?
|
|
38
|
+
data_product = opts[:data_product] || (segment ? segment.data_product : nil)
|
|
40
39
|
|
|
41
40
|
if id == :all
|
|
42
|
-
tenants_uri = domain
|
|
41
|
+
tenants_uri = base_uri(domain, data_product)
|
|
42
|
+
tenants_uri += "?segment=#{CGI.escape(segment.segment_id)}" if segment
|
|
43
43
|
Enumerator.new do |y|
|
|
44
44
|
loop do
|
|
45
45
|
res = client.get tenants_uri
|
|
@@ -56,7 +56,8 @@ module GoodData
|
|
|
56
56
|
end
|
|
57
57
|
else
|
|
58
58
|
id = id.respond_to?(:client_id) ? id.client_id : id
|
|
59
|
-
|
|
59
|
+
tenant_uri = base_uri(domain, data_product)
|
|
60
|
+
data = client.get(tenant_uri + "/#{CGI.escape(id)}")
|
|
60
61
|
client.create(GoodData::Client, data.merge('domain' => domain))
|
|
61
62
|
end
|
|
62
63
|
end
|
|
@@ -88,17 +89,27 @@ module GoodData
|
|
|
88
89
|
return nil unless value
|
|
89
90
|
domain = opts[:domain]
|
|
90
91
|
client_id = opts[:client_id]
|
|
91
|
-
|
|
92
|
+
data_product_id = opts[:data_product_id]
|
|
93
|
+
uri = data_product_id ? GoodData::DataProduct::ONE_DATA_PRODUCT_PATH % { domain_name: domain.name, id: data_product_id } : domain.segments_uri
|
|
92
94
|
body = {
|
|
93
95
|
setting: {
|
|
94
96
|
name: "#{name}",
|
|
95
97
|
value: "#{value}"
|
|
96
98
|
}
|
|
97
99
|
}
|
|
98
|
-
domain.client.put(uri, body)
|
|
100
|
+
domain.client.put(uri + "/clients/#{client_id}/settings/#{name}", body)
|
|
99
101
|
nil
|
|
100
102
|
end
|
|
101
103
|
alias_method :add_setting, :update_setting
|
|
104
|
+
|
|
105
|
+
def base_uri(domain, data_product)
|
|
106
|
+
if data_product
|
|
107
|
+
uri = GoodData::DataProduct::ONE_DATA_PRODUCT_PATH % { domain_name: domain.name, id: data_product.data_product_id }
|
|
108
|
+
else
|
|
109
|
+
uri = domain.segments_uri
|
|
110
|
+
end
|
|
111
|
+
uri + '/clients'
|
|
112
|
+
end
|
|
102
113
|
end
|
|
103
114
|
|
|
104
115
|
def initialize(data)
|
|
@@ -189,7 +200,8 @@ module GoodData
|
|
|
189
200
|
if uri
|
|
190
201
|
client.put(uri, json)
|
|
191
202
|
else
|
|
192
|
-
|
|
203
|
+
data_product = segment.data_product
|
|
204
|
+
res = client.post(self.class.base_uri(domain, data_product), json)
|
|
193
205
|
@json = res
|
|
194
206
|
end
|
|
195
207
|
self
|
|
@@ -209,8 +221,8 @@ module GoodData
|
|
|
209
221
|
end
|
|
210
222
|
|
|
211
223
|
def settings
|
|
212
|
-
|
|
213
|
-
res = client.get(
|
|
224
|
+
data_product = segment.data_product
|
|
225
|
+
res = client.get(self.class.base_uri(domain, data_product) + "/#{client_id}/settings")
|
|
214
226
|
settings = GoodData::Helpers.get_path(res, %w(settingsList items))
|
|
215
227
|
settings.map do |setting|
|
|
216
228
|
setting = setting['setting']
|
|
@@ -0,0 +1,149 @@
|
|
|
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_relative '../rest/resource'
|
|
8
|
+
|
|
9
|
+
module GoodData
|
|
10
|
+
class DataProduct < Rest::Resource
|
|
11
|
+
include Mixin::UriGetter
|
|
12
|
+
|
|
13
|
+
attr_accessor :domain
|
|
14
|
+
|
|
15
|
+
ALL_DATA_PRODUCTS_PATH = '/gdc/domains/%{domain_name}/dataproducts'
|
|
16
|
+
ONE_DATA_PRODUCT_PATH = '/gdc/domains/%{domain_name}/dataproducts/%{id}'
|
|
17
|
+
|
|
18
|
+
class << self
|
|
19
|
+
def [](id, opts)
|
|
20
|
+
domain = opts[:domain]
|
|
21
|
+
fail ArgumentError, 'No :domain specified' if domain.nil?
|
|
22
|
+
|
|
23
|
+
client = domain.client
|
|
24
|
+
fail ArgumentError, 'No client specified' if client.nil?
|
|
25
|
+
|
|
26
|
+
if id == :all
|
|
27
|
+
GoodData::DataProduct.all(opts)
|
|
28
|
+
else
|
|
29
|
+
data_products_uri = ONE_DATA_PRODUCT_PATH % { domain_name: domain.name, id: id }
|
|
30
|
+
|
|
31
|
+
result = client.get(data_products_uri)
|
|
32
|
+
client.create(GoodData::DataProduct, result.merge('domain' => domain))
|
|
33
|
+
end
|
|
34
|
+
end
|
|
35
|
+
|
|
36
|
+
def all(opts = {})
|
|
37
|
+
domain = opts[:domain]
|
|
38
|
+
fail ArgumentError, 'No :domain specified' if domain.nil?
|
|
39
|
+
|
|
40
|
+
client = domain.client
|
|
41
|
+
fail ArgumentError, 'No client specified' if client.nil?
|
|
42
|
+
|
|
43
|
+
data_products_uri = ALL_DATA_PRODUCTS_PATH % { domain_name: domain.name }
|
|
44
|
+
|
|
45
|
+
GoodData::Helpers.get_path(client.get(data_products_uri), %w(dataProducts items)).map do |i|
|
|
46
|
+
client.create(GoodData::DataProduct, i, domain: domain)
|
|
47
|
+
end
|
|
48
|
+
end
|
|
49
|
+
|
|
50
|
+
def create(data = {}, options = {})
|
|
51
|
+
fail 'id for data_product has to be provided' if data[:id].blank?
|
|
52
|
+
client = options[:client]
|
|
53
|
+
client.create(GoodData::DataProduct, GoodData::Helpers.stringify_keys(dataProduct: data), domain: options[:domain])
|
|
54
|
+
end
|
|
55
|
+
end
|
|
56
|
+
|
|
57
|
+
def initialize(json)
|
|
58
|
+
super
|
|
59
|
+
@json = json
|
|
60
|
+
@domain = json.delete('domain')
|
|
61
|
+
end
|
|
62
|
+
|
|
63
|
+
def clients
|
|
64
|
+
json = client.get(data['links']['clients'])
|
|
65
|
+
|
|
66
|
+
json['clients']['items'].map do |val|
|
|
67
|
+
client.create(GoodData::Client, val, domain: domain)
|
|
68
|
+
end
|
|
69
|
+
end
|
|
70
|
+
|
|
71
|
+
def segments
|
|
72
|
+
json = client.get(data['links']['segments'])
|
|
73
|
+
|
|
74
|
+
json['segments']['items'].map do |val|
|
|
75
|
+
client.create(GoodData::Segment, val, domain: domain, data_product: self)
|
|
76
|
+
end
|
|
77
|
+
end
|
|
78
|
+
|
|
79
|
+
def save
|
|
80
|
+
if @json[:uri]
|
|
81
|
+
client.put(uri, json)
|
|
82
|
+
else
|
|
83
|
+
data_products_uri = ALL_DATA_PRODUCTS_PATH % { domain_name: domain.name }
|
|
84
|
+
res = client.post(data_products_uri, json)
|
|
85
|
+
@json = res
|
|
86
|
+
end
|
|
87
|
+
self
|
|
88
|
+
end
|
|
89
|
+
|
|
90
|
+
def delete(options = {})
|
|
91
|
+
segments.peach { |s| s.delete(options) }
|
|
92
|
+
client.delete(uri) if uri
|
|
93
|
+
self
|
|
94
|
+
end
|
|
95
|
+
|
|
96
|
+
def update_clients(data, options = {})
|
|
97
|
+
if options[:delete_extra] && options[:delete_extra_in_segments]
|
|
98
|
+
fail 'Options delete_extra and delete_extra_in_segments are mutually exclusive.'
|
|
99
|
+
end
|
|
100
|
+
|
|
101
|
+
data_products_uri = ONE_DATA_PRODUCT_PATH % { domain_name: domain.name, id: data_product_id }
|
|
102
|
+
|
|
103
|
+
payload = data.map do |datum|
|
|
104
|
+
{
|
|
105
|
+
:client => {
|
|
106
|
+
:id => datum[:id],
|
|
107
|
+
:segment => data_products_uri + '/segments/' + datum[:segment]
|
|
108
|
+
}
|
|
109
|
+
}.tap do |h|
|
|
110
|
+
h[:client][:project] = datum[:project] if datum.key?(:project)
|
|
111
|
+
end
|
|
112
|
+
end
|
|
113
|
+
|
|
114
|
+
if options[:delete_extra]
|
|
115
|
+
res = client.post(data_products_uri + '/updateClients?deleteExtra=true', updateClients: { items: payload })
|
|
116
|
+
elsif options[:delete_extra_in_segments]
|
|
117
|
+
segments_to_delete_in = options[:delete_extra_in_segments]
|
|
118
|
+
.map { |segment| CGI.escape(segment) }
|
|
119
|
+
.join(',')
|
|
120
|
+
uri = data_products_uri + "/updateClients?deleteExtraInSegments=#{segments_to_delete_in}"
|
|
121
|
+
res = client.post(uri, updateClients: { items: payload })
|
|
122
|
+
else
|
|
123
|
+
res = client.post(data_products_uri + '/updateClients', updateClients: { items: payload })
|
|
124
|
+
end
|
|
125
|
+
data = GoodData::Helpers.get_path(res, ['updateClientsResponse'])
|
|
126
|
+
if data
|
|
127
|
+
result = data.flat_map { |k, v| v.map { |h| GoodData::Helpers.symbolize_keys(h.merge('type' => k)) } }
|
|
128
|
+
result.select { |r| r[:status] == 'DELETED' }.peach { |r| r[:originalProject] && client.delete(r[:originalProject]) } if options[:delete_projects]
|
|
129
|
+
result
|
|
130
|
+
else
|
|
131
|
+
[]
|
|
132
|
+
end
|
|
133
|
+
end
|
|
134
|
+
|
|
135
|
+
def data_product_id
|
|
136
|
+
data['id']
|
|
137
|
+
end
|
|
138
|
+
|
|
139
|
+
def data_product_id=(new_id)
|
|
140
|
+
data['id'] = new_id
|
|
141
|
+
end
|
|
142
|
+
|
|
143
|
+
def create_segment(data)
|
|
144
|
+
segment = GoodData::Segment.create(data, domain: domain, client: domain.client)
|
|
145
|
+
segment.data_product = self
|
|
146
|
+
segment.save
|
|
147
|
+
end
|
|
148
|
+
end
|
|
149
|
+
end
|