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
|
@@ -0,0 +1,62 @@
|
|
|
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 'base_action'
|
|
8
|
+
|
|
9
|
+
module GoodData
|
|
10
|
+
module LCM2
|
|
11
|
+
class CollectDataProduct < BaseAction
|
|
12
|
+
DESCRIPTION = 'Collect DataProduct to be used in the actions'
|
|
13
|
+
|
|
14
|
+
PARAMS = define_params(self) do
|
|
15
|
+
description 'Client Used for Connecting to GD'
|
|
16
|
+
param :gdc_gd_client, instance_of(Type::GdClientType), required: true
|
|
17
|
+
|
|
18
|
+
description 'DataProduct to manage'
|
|
19
|
+
param :data_product, instance_of(Type::StringType), required: false
|
|
20
|
+
end
|
|
21
|
+
|
|
22
|
+
RESULT_HEADER = [
|
|
23
|
+
:data_product
|
|
24
|
+
]
|
|
25
|
+
|
|
26
|
+
class << self
|
|
27
|
+
def call(params)
|
|
28
|
+
params = params.to_hash
|
|
29
|
+
client = params.gdc_gd_client
|
|
30
|
+
domain_name = params.organization || params.domain
|
|
31
|
+
domain = client.domain(domain_name) || fail("Invalid domain name specified - #{domain_name}")
|
|
32
|
+
|
|
33
|
+
if params.key?(:data_product)
|
|
34
|
+
begin
|
|
35
|
+
data_product = domain.data_products(params.data_product)
|
|
36
|
+
rescue RestClient::BadRequest
|
|
37
|
+
fail 'the specified DataProduct does not exist'
|
|
38
|
+
end
|
|
39
|
+
else
|
|
40
|
+
params.gdc_logger.info 'Please specify the data_product parameter when using the brick - trying to find a fallback'
|
|
41
|
+
data_products = domain.data_products(:all)
|
|
42
|
+
fail 'No data_product parameter specified - unable to fallback to a default' if data_products.length > 1 || data_products.empty?
|
|
43
|
+
data_product = data_products.first
|
|
44
|
+
end
|
|
45
|
+
|
|
46
|
+
results = [
|
|
47
|
+
{
|
|
48
|
+
data_product: data_product
|
|
49
|
+
}
|
|
50
|
+
]
|
|
51
|
+
|
|
52
|
+
{
|
|
53
|
+
results: results,
|
|
54
|
+
params: {
|
|
55
|
+
data_product: data_product
|
|
56
|
+
}
|
|
57
|
+
}
|
|
58
|
+
end
|
|
59
|
+
end
|
|
60
|
+
end
|
|
61
|
+
end
|
|
62
|
+
end
|
|
@@ -0,0 +1,62 @@
|
|
|
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 'base_action'
|
|
8
|
+
|
|
9
|
+
module GoodData
|
|
10
|
+
module LCM2
|
|
11
|
+
class CollectDymanicScheduleParams < BaseAction
|
|
12
|
+
DESCRIPTION = 'Collect Dynamic Schedule Params'
|
|
13
|
+
|
|
14
|
+
PARAMS = define_params(self) do
|
|
15
|
+
description 'Schedule Title Column'
|
|
16
|
+
param :schedule_title_column, instance_of(Type::StringType), required: false
|
|
17
|
+
|
|
18
|
+
description 'Dynamic Params'
|
|
19
|
+
param :dynamic_params, instance_of(Type::HashType), required: false
|
|
20
|
+
end
|
|
21
|
+
|
|
22
|
+
class << self
|
|
23
|
+
def call(params)
|
|
24
|
+
return [] unless params.dynamic_params
|
|
25
|
+
|
|
26
|
+
schedule_title_column = params.schedule_title_column || 'schedule_title'
|
|
27
|
+
client_id_column = params.client_id_column || 'client_id'
|
|
28
|
+
param_name_column = params.param_name_column || 'param_name'
|
|
29
|
+
param_value_column = params.param_value_column || 'param_value'
|
|
30
|
+
results = []
|
|
31
|
+
|
|
32
|
+
input_source = params.dynamic_params.input_source
|
|
33
|
+
data_source = GoodData::Helpers::DataSource.new(input_source)
|
|
34
|
+
input_data = File.open(data_source.realize(params), 'r:UTF-8')
|
|
35
|
+
GoodData.logger.debug("Input data: #{input_data.read}")
|
|
36
|
+
|
|
37
|
+
schedule_params = {}
|
|
38
|
+
|
|
39
|
+
CSV.foreach(input_data, :headers => true, :return_headers => false, encoding: 'utf-8') do |row|
|
|
40
|
+
GoodData.logger.debug("Processing row: #{row}")
|
|
41
|
+
results << row.to_hash
|
|
42
|
+
|
|
43
|
+
client_id = row[client_id_column] ? row[client_id_column] : :all_clients
|
|
44
|
+
schedule_name = row[schedule_title_column] ? row[schedule_title_column] : :all_schedules
|
|
45
|
+
|
|
46
|
+
schedule_params[client_id] ||= {}
|
|
47
|
+
schedule_params[client_id][schedule_name] ||= {}
|
|
48
|
+
|
|
49
|
+
schedule_params[client_id][schedule_name].merge!(row[param_name_column] => row[param_value_column])
|
|
50
|
+
end
|
|
51
|
+
|
|
52
|
+
{
|
|
53
|
+
results: results,
|
|
54
|
+
params: {
|
|
55
|
+
schedule_params: schedule_params
|
|
56
|
+
}
|
|
57
|
+
}
|
|
58
|
+
end
|
|
59
|
+
end
|
|
60
|
+
end
|
|
61
|
+
end
|
|
62
|
+
end
|
|
@@ -8,8 +8,8 @@ require_relative 'base_action'
|
|
|
8
8
|
|
|
9
9
|
module GoodData
|
|
10
10
|
module LCM2
|
|
11
|
-
class
|
|
12
|
-
DESCRIPTION = "Collect all attributes (include CAs)
|
|
11
|
+
class CollectLdmObjects < BaseAction
|
|
12
|
+
DESCRIPTION = "Collect all objects in LDM: attributes (include CAs), facts, datasets"
|
|
13
13
|
|
|
14
14
|
PARAMS = define_params(self) do
|
|
15
15
|
description 'Development Client Used for Connecting to GD'
|
|
@@ -28,7 +28,7 @@ module GoodData
|
|
|
28
28
|
synchronize = params.synchronize.pmap do |info|
|
|
29
29
|
from = info.from
|
|
30
30
|
from_project = development_client.projects(from) || fail("Invalid 'from' project specified - '#{from}'")
|
|
31
|
-
objects = (from_project.attributes.to_a + from_project.labels.to_a).map(&:uri)
|
|
31
|
+
objects = (from_project.attributes.to_a + from_project.labels.to_a + from_project.datasets.to_a + from_project.facts.to_a).map(&:uri)
|
|
32
32
|
|
|
33
33
|
info[:transfer_uris] ||= []
|
|
34
34
|
info[:transfer_uris] += objects
|
|
@@ -13,8 +13,11 @@ module GoodData
|
|
|
13
13
|
with objects inside dashboards (reports, metrics ...) from development projects"
|
|
14
14
|
|
|
15
15
|
PARAMS = define_params(self) do
|
|
16
|
-
description 'Production Tag
|
|
17
|
-
param :
|
|
16
|
+
description 'Production Tag Names'
|
|
17
|
+
param :production_tags, array_of(instance_of(Type::StringType)), required: false
|
|
18
|
+
|
|
19
|
+
description 'Production Tag Names'
|
|
20
|
+
param :production_tag, instance_of(Type::StringType), required: false, deprecated: true, replacement: :production_tags
|
|
18
21
|
|
|
19
22
|
description 'Development Client Used for Connecting to GD'
|
|
20
23
|
param :development_client, instance_of(Type::GdClientType), required: true
|
|
@@ -42,7 +45,7 @@ module GoodData
|
|
|
42
45
|
from_project = development_client.projects(from) || fail("Invalid 'from' project specified - '#{from}'")
|
|
43
46
|
|
|
44
47
|
segment_tags = segments_to_tags[info.segment]
|
|
45
|
-
production_tags = Helpers.parse_production_tags(params.production_tag, segment_tags)
|
|
48
|
+
production_tags = Helpers.parse_production_tags(params.production_tags || params.production_tag, segment_tags)
|
|
46
49
|
|
|
47
50
|
if transfer_all || production_tags.empty?
|
|
48
51
|
old_dashboards = GoodData::Dashboard.all(
|
|
@@ -43,7 +43,8 @@ module GoodData
|
|
|
43
43
|
|
|
44
44
|
domain_name = params.organization || params.domain
|
|
45
45
|
domain = client.domain(domain_name) || fail("Invalid domain name specified - #{domain_name}")
|
|
46
|
-
|
|
46
|
+
data_product = params.data_product
|
|
47
|
+
domain_segments = domain.segments(:all, data_product)
|
|
47
48
|
|
|
48
49
|
segments = params.segments.map do |seg|
|
|
49
50
|
domain_segments.find do |s|
|
|
@@ -24,19 +24,18 @@ module GoodData
|
|
|
24
24
|
|
|
25
25
|
class << self
|
|
26
26
|
def call(params)
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
domain = client.domain(domain_name) || fail("Invalid domain name specified - #{domain_name}")
|
|
31
|
-
domain_segments = domain.segments
|
|
27
|
+
data_product = params.data_product
|
|
28
|
+
data_product_segments = data_product.segments
|
|
29
|
+
params.gdc_logger.info("Domain segments: #{data_product_segments}")
|
|
32
30
|
|
|
33
31
|
if params.segments_filter
|
|
34
|
-
|
|
32
|
+
params.gdc_logger.info("Segments filter: #{params.segments_filter}")
|
|
33
|
+
data_product_segments.select! do |segment|
|
|
35
34
|
params.segments_filter.include?(segment.segment_id)
|
|
36
35
|
end
|
|
37
36
|
end
|
|
38
37
|
|
|
39
|
-
segments =
|
|
38
|
+
segments = data_product_segments.pmap do |segment|
|
|
40
39
|
project = nil
|
|
41
40
|
|
|
42
41
|
begin
|
|
@@ -19,8 +19,11 @@ module GoodData
|
|
|
19
19
|
description 'Synchronization Info'
|
|
20
20
|
param :synchronize, array_of(instance_of(Type::SynchronizationInfoType)), required: true, generated: true
|
|
21
21
|
|
|
22
|
-
description 'Tag
|
|
23
|
-
param :
|
|
22
|
+
description 'Production Tag Names'
|
|
23
|
+
param :production_tags, array_of(instance_of(Type::StringType)), required: false
|
|
24
|
+
|
|
25
|
+
description 'Production Tag Names'
|
|
26
|
+
param :production_tag, instance_of(Type::StringType), required: false, deprecated: true, replacement: :production_tags
|
|
24
27
|
|
|
25
28
|
description 'Segments to search for segment-specific production tags'
|
|
26
29
|
param :segments, array_of(instance_of(Type::SegmentType)), required: false
|
|
@@ -34,7 +37,7 @@ module GoodData
|
|
|
34
37
|
results = []
|
|
35
38
|
segments_to_tags = Helpers.segment_production_tags(params.segments)
|
|
36
39
|
transfer_all = GoodData::Helpers.to_boolean(params.transfer_all)
|
|
37
|
-
return results unless params.production_tag || segments_to_tags.any? || transfer_all
|
|
40
|
+
return results unless params.production_tags || params.production_tag || segments_to_tags.any? || transfer_all
|
|
38
41
|
development_client = params.development_client
|
|
39
42
|
|
|
40
43
|
synchronize = params.synchronize.pmap do |info|
|
|
@@ -42,7 +45,7 @@ module GoodData
|
|
|
42
45
|
from_project = development_client.projects(from) || fail("Invalid 'from' project specified - '#{from}'")
|
|
43
46
|
|
|
44
47
|
segment_tags = segments_to_tags[info.segment]
|
|
45
|
-
production_tags = Helpers.parse_production_tags(params.production_tag, segment_tags)
|
|
48
|
+
production_tags = Helpers.parse_production_tags(params.production_tags || params.production_tag, segment_tags)
|
|
46
49
|
objects = []
|
|
47
50
|
if transfer_all
|
|
48
51
|
vizs = MdObject.query('visualization', MdObject, client: development_client, project: from_project)
|
|
@@ -32,6 +32,9 @@ module GoodData
|
|
|
32
32
|
|
|
33
33
|
description 'Table Name'
|
|
34
34
|
param :release_table_name, instance_of(Type::StringType), required: false
|
|
35
|
+
|
|
36
|
+
description 'Project Environment'
|
|
37
|
+
param :project_environment, instance_of(Type::StringType), required: false
|
|
35
38
|
end
|
|
36
39
|
|
|
37
40
|
DEFAULT_TABLE_NAME = 'LCM_RELEASE'
|
|
@@ -45,7 +48,8 @@ module GoodData
|
|
|
45
48
|
|
|
46
49
|
domain_name = params.organization || params.domain
|
|
47
50
|
domain = client.domain(domain_name) || fail("Invalid domain name specified - #{domain_name}")
|
|
48
|
-
|
|
51
|
+
data_product = params.data_product
|
|
52
|
+
domain_segments = domain.segments(:all, data_product)
|
|
49
53
|
|
|
50
54
|
# TODO: Support for 'per segment' provisioning
|
|
51
55
|
segments = params.segments
|
|
@@ -71,7 +75,7 @@ module GoodData
|
|
|
71
75
|
|
|
72
76
|
# Create new master project
|
|
73
77
|
params.gdc_logger.info "Creating master project - name: '#{master_name}' development_project: '#{development_pid}', segment: '#{segment_id}', driver: '#{driver}'"
|
|
74
|
-
project = client.create_project(title: master_name, auth_token: token, driver: driver == 'vertica' ? 'vertica' : 'Pg')
|
|
78
|
+
project = client.create_project(title: master_name, auth_token: token, driver: driver == 'vertica' ? 'vertica' : 'Pg', environment: params.project_environment)
|
|
75
79
|
|
|
76
80
|
# Does segment exists? If not, create new one and set initial master
|
|
77
81
|
if segment
|
|
@@ -79,7 +83,7 @@ module GoodData
|
|
|
79
83
|
status = 'untouched'
|
|
80
84
|
else
|
|
81
85
|
params.gdc_logger.info "Creating segment #{segment_id}, master #{project.pid}"
|
|
82
|
-
segment =
|
|
86
|
+
segment = data_product.create_segment(segment_id: segment_id, master_project: project)
|
|
83
87
|
segment.synchronize_clients
|
|
84
88
|
segment_in[:is_new] = true
|
|
85
89
|
status = 'created'
|
|
@@ -0,0 +1,53 @@
|
|
|
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 'base_action'
|
|
8
|
+
|
|
9
|
+
module GoodData
|
|
10
|
+
module LCM2
|
|
11
|
+
class EnsureDataProduct < BaseAction
|
|
12
|
+
DESCRIPTION = 'Creates the DataProduct if it does not exist yet'
|
|
13
|
+
|
|
14
|
+
PARAMS = define_params(self) do
|
|
15
|
+
description 'client to connect to GD'
|
|
16
|
+
param :gdc_gd_client, instance_of(Type::GdClientType), required: true
|
|
17
|
+
|
|
18
|
+
description 'DataProduct to ensure'
|
|
19
|
+
param :data_product, instance_of(Type::StringType), required: false
|
|
20
|
+
end
|
|
21
|
+
|
|
22
|
+
RESULT_HEADER = [
|
|
23
|
+
:data_product
|
|
24
|
+
]
|
|
25
|
+
|
|
26
|
+
class << self
|
|
27
|
+
def call(params)
|
|
28
|
+
params = params.to_hash
|
|
29
|
+
client = params.gdc_gd_client
|
|
30
|
+
domain_name = params.organization || params.domain
|
|
31
|
+
domain = client.domain(domain_name) || fail("Invalid domain name specified - #{domain_name}")
|
|
32
|
+
|
|
33
|
+
if params.key?(:data_product)
|
|
34
|
+
begin
|
|
35
|
+
data_product = domain.data_products(params.data_product)
|
|
36
|
+
rescue RestClient::BadRequest
|
|
37
|
+
params.gdc_logger.info "Can not find DataProduct #{params.data_product}, creating it instead"
|
|
38
|
+
data_product = domain.create_data_product(id: params.data_product)
|
|
39
|
+
end
|
|
40
|
+
end
|
|
41
|
+
|
|
42
|
+
{
|
|
43
|
+
results: [
|
|
44
|
+
{
|
|
45
|
+
data_product: data_product
|
|
46
|
+
}
|
|
47
|
+
]
|
|
48
|
+
}
|
|
49
|
+
end
|
|
50
|
+
end
|
|
51
|
+
end
|
|
52
|
+
end
|
|
53
|
+
end
|
|
@@ -19,7 +19,11 @@ module GoodData
|
|
|
19
19
|
param :organization, instance_of(Type::StringType), required: true
|
|
20
20
|
|
|
21
21
|
description 'Technical users'
|
|
22
|
-
param :technical_user, array_of(instance_of(Type::StringType)),
|
|
22
|
+
param :technical_user, array_of(instance_of(Type::StringType)),
|
|
23
|
+
required: false, deprecated: true, replacement: :technical_users
|
|
24
|
+
|
|
25
|
+
description 'Technical users'
|
|
26
|
+
param :technical_users, array_of(instance_of(Type::StringType)), required: false
|
|
23
27
|
end
|
|
24
28
|
|
|
25
29
|
RESULT_HEADER = [
|
|
@@ -36,7 +40,7 @@ module GoodData
|
|
|
36
40
|
domain_name = params.organization || params.domain
|
|
37
41
|
domain = client.domain(domain_name) || fail("Invalid domain name specified - #{domain_name}")
|
|
38
42
|
|
|
39
|
-
technical_users = (params.technical_user || []).uniq
|
|
43
|
+
technical_users = (params.technical_users || params.technical_user || []).uniq
|
|
40
44
|
technical_users.pmap do |technical_user|
|
|
41
45
|
domain_user = domain.users.find do |du|
|
|
42
46
|
du.login == technical_user
|
|
@@ -16,7 +16,11 @@ module GoodData
|
|
|
16
16
|
param :gdc_gd_client, instance_of(Type::GdClientType), required: true
|
|
17
17
|
|
|
18
18
|
description 'Technical users'
|
|
19
|
-
param :technical_user, array_of(instance_of(Type::StringType)),
|
|
19
|
+
param :technical_user, array_of(instance_of(Type::StringType)),
|
|
20
|
+
required: false, deprecated: true, replacement: :technical_users
|
|
21
|
+
|
|
22
|
+
description 'Technical users'
|
|
23
|
+
param :technical_users, array_of(instance_of(Type::StringType)), required: false
|
|
20
24
|
|
|
21
25
|
description 'Synchronization Info'
|
|
22
26
|
param :synchronize, array_of(instance_of(Type::SynchronizationInfoType)), required: true, generated: true
|
|
@@ -36,7 +40,7 @@ module GoodData
|
|
|
36
40
|
def call(params)
|
|
37
41
|
client = params.gdc_gd_client
|
|
38
42
|
|
|
39
|
-
technical_users = params.technical_user || []
|
|
43
|
+
technical_users = params.technical_users || params.technical_user || []
|
|
40
44
|
new_users = technical_users.map do |technical_user|
|
|
41
45
|
{
|
|
42
46
|
login: technical_user,
|
|
@@ -46,24 +50,32 @@ module GoodData
|
|
|
46
50
|
|
|
47
51
|
results = params.synchronize.pmap do |synchronize_info|
|
|
48
52
|
synchronize_info[:to].pmap do |entry|
|
|
49
|
-
|
|
50
|
-
res = project.create_users(new_users)
|
|
51
|
-
|
|
52
|
-
new_users.zip(res).map do |f, s|
|
|
53
|
-
{
|
|
54
|
-
project: project.title,
|
|
55
|
-
pid: project.pid,
|
|
56
|
-
login: f[:login],
|
|
57
|
-
role: f[:role],
|
|
58
|
-
result: s[:type],
|
|
59
|
-
message: s[:message],
|
|
60
|
-
url: s[:user]
|
|
61
|
-
}
|
|
62
|
-
end
|
|
53
|
+
ensure_users(client, entry[:pid], new_users)
|
|
63
54
|
end
|
|
64
|
-
end
|
|
55
|
+
end.flatten
|
|
56
|
+
|
|
57
|
+
results += params.clients.pmap { |input_client| input_client[:project] }.compact.pmap { |pid| ensure_users(client, pid, new_users) }.flatten if params.clients
|
|
58
|
+
|
|
59
|
+
results
|
|
60
|
+
end
|
|
61
|
+
|
|
62
|
+
private
|
|
63
|
+
|
|
64
|
+
def ensure_users(client, project_id, new_users)
|
|
65
|
+
project = client.projects(project_id)
|
|
66
|
+
res = project.create_users(new_users)
|
|
65
67
|
|
|
66
|
-
|
|
68
|
+
new_users.zip(res).map do |f, s|
|
|
69
|
+
{
|
|
70
|
+
project: project.title,
|
|
71
|
+
pid: project.pid,
|
|
72
|
+
login: f[:login],
|
|
73
|
+
role: f[:role],
|
|
74
|
+
result: s[:type],
|
|
75
|
+
message: s[:message],
|
|
76
|
+
url: s[:user]
|
|
77
|
+
}
|
|
78
|
+
end
|
|
67
79
|
end
|
|
68
80
|
end
|
|
69
81
|
end
|
|
@@ -0,0 +1,128 @@
|
|
|
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 'base_action'
|
|
8
|
+
|
|
9
|
+
module GoodData
|
|
10
|
+
module LCM2
|
|
11
|
+
class ExecuteSchedules < BaseAction
|
|
12
|
+
DESCRIPTION = 'Execute schedules'
|
|
13
|
+
|
|
14
|
+
PARAMS = define_params(self) do
|
|
15
|
+
description 'Client Used for Connecting to GD'
|
|
16
|
+
param :gdc_gd_client, instance_of(Type::GdClientType), required: true
|
|
17
|
+
|
|
18
|
+
description 'List Of Modes'
|
|
19
|
+
param :list_of_modes, instance_of(Type::StringType), required: true
|
|
20
|
+
|
|
21
|
+
description 'Work Done Identificator'
|
|
22
|
+
param :work_done_identificator, instance_of(Type::StringType), required: true
|
|
23
|
+
|
|
24
|
+
description 'Number Of Schedules In Batch'
|
|
25
|
+
param :number_of_schedules_in_batch, instance_of(Type::StringType), required: false, default: '1000'
|
|
26
|
+
|
|
27
|
+
description 'Delay Between Batches'
|
|
28
|
+
param :delay_between_batches, instance_of(Type::StringType), required: false, default: '0'
|
|
29
|
+
|
|
30
|
+
description 'Control Parameter'
|
|
31
|
+
param :control_parameter, instance_of(Type::StringType), required: false, default: 'MODE'
|
|
32
|
+
|
|
33
|
+
description 'Wait For Schedule'
|
|
34
|
+
param :wait_for_schedule, instance_of(Type::StringType), required: false, default: 'false'
|
|
35
|
+
|
|
36
|
+
description 'Segment List'
|
|
37
|
+
param :segment_list, instance_of(Type::StringType), required: false
|
|
38
|
+
|
|
39
|
+
description 'Domain'
|
|
40
|
+
param :domain, instance_of(Type::StringType), required: false
|
|
41
|
+
|
|
42
|
+
description 'Number Of Threads'
|
|
43
|
+
param :number_of_threads, instance_of(Type::StringType), required: false, default: '5'
|
|
44
|
+
end
|
|
45
|
+
|
|
46
|
+
class << self
|
|
47
|
+
def call(params)
|
|
48
|
+
logger = params.gdc_logger
|
|
49
|
+
|
|
50
|
+
client = params.gdc_gd_client
|
|
51
|
+
project = client.projects(params.gdc_project) || client.projects(params.gdc_project_id)
|
|
52
|
+
|
|
53
|
+
list_of_modes = params.list_of_modes.split('|').map(&:strip)
|
|
54
|
+
work_done_identificator = params.work_done_identificator
|
|
55
|
+
number_of_schedules_in_batch = Integer(params.number_of_schedules_in_batch || "1000")
|
|
56
|
+
delay_between_batches = Integer(params.delay_between_batches || "0")
|
|
57
|
+
control_parameter = params.control_parameter || "MODE"
|
|
58
|
+
wait = GoodData::Helpers.to_boolean(params.wait_for_schedule)
|
|
59
|
+
|
|
60
|
+
segment_list = params.segment_list
|
|
61
|
+
domain_name = params.domain
|
|
62
|
+
fail "In case that you are using SEGMENT_LIST parameter, you need to fill out DOMAIN parameter" if !segment_list.nil? && domain_name.nil?
|
|
63
|
+
|
|
64
|
+
number_of_threads = Integer(params.number_of_threads || '5')
|
|
65
|
+
|
|
66
|
+
# The WORK_DONE_IDENTIFICATOR is flag which tells the executor to execute the schedules
|
|
67
|
+
# It could have special value IGNORE. In this case all corresponding schedules will be started during every run of this brick
|
|
68
|
+
|
|
69
|
+
start_schedules = work_done_identificator == 'IGNORE' || GoodData::Helpers.to_boolean(project.metadata[work_done_identificator])
|
|
70
|
+
|
|
71
|
+
project_list = []
|
|
72
|
+
if !segment_list.nil? && segment_list != ''
|
|
73
|
+
domain = client.domain(domain_name)
|
|
74
|
+
segment_list.split('|').each do |segment_identification|
|
|
75
|
+
segment = domain.segments(segment_identification)
|
|
76
|
+
project_list += segment.clients.map { |c| !c.project.nil? ? c.project.obj_id : nil }.compact
|
|
77
|
+
end
|
|
78
|
+
project_list.uniq!
|
|
79
|
+
end
|
|
80
|
+
|
|
81
|
+
if start_schedules
|
|
82
|
+
schedules_to_filter = client.projects.pmapcat do |p|
|
|
83
|
+
begin
|
|
84
|
+
p.schedules
|
|
85
|
+
rescue => e
|
|
86
|
+
logger.info "The retrieval of project schedules, for project #{p.obj_id} has failed. Message: #{e.message}."
|
|
87
|
+
[]
|
|
88
|
+
end
|
|
89
|
+
end
|
|
90
|
+
|
|
91
|
+
schedules_to_start = schedules_to_filter.select { |schedule| list_of_modes.include?(schedule.params[control_parameter]) }
|
|
92
|
+
|
|
93
|
+
if !segment_list.nil? && segment_list != ''
|
|
94
|
+
schedules_to_start.delete_if { |schedule| !project_list.include?(schedule.project.obj_id) }
|
|
95
|
+
end
|
|
96
|
+
|
|
97
|
+
logger.info "Found #{schedules_to_start.count} schedules to execute"
|
|
98
|
+
|
|
99
|
+
schedules_to_start.each_slice(number_of_schedules_in_batch).each_with_index do |batch_schedules, batch_index|
|
|
100
|
+
batch_number = batch_index + 1
|
|
101
|
+
logger.info "Starting batch number #{batch_number}. Number of schedules in batch #{batch_schedules.count}."
|
|
102
|
+
batch_schedules.peach(number_of_threads) do |schedule|
|
|
103
|
+
begin
|
|
104
|
+
tries ||= 5
|
|
105
|
+
logger.info "Starting schedule for project #{schedule.project.pid} - #{schedule.project.title}. Schedule ID is #{schedule.obj_id}"
|
|
106
|
+
schedule.execute(wait: wait)
|
|
107
|
+
rescue => e
|
|
108
|
+
if (tries -= 1) > 0
|
|
109
|
+
logger.warn "There was error during operation: #{e.message}. Retrying"
|
|
110
|
+
sleep(5)
|
|
111
|
+
retry
|
|
112
|
+
else
|
|
113
|
+
logger.info "We could not start schedule for project #{schedule.project.pid} - #{schedule.project.title} - #{e.message}"
|
|
114
|
+
end
|
|
115
|
+
else
|
|
116
|
+
logger.info "Operation finished"
|
|
117
|
+
end
|
|
118
|
+
end
|
|
119
|
+
logger.info "Entering sleep mode for #{delay_between_batches} seconds"
|
|
120
|
+
sleep(delay_between_batches)
|
|
121
|
+
end
|
|
122
|
+
project.set_metadata(work_done_identificator, 'false') unless work_done_identificator == 'IGNORE'
|
|
123
|
+
end
|
|
124
|
+
end
|
|
125
|
+
end
|
|
126
|
+
end
|
|
127
|
+
end
|
|
128
|
+
end
|