lib/gooddata/lcm/actions/create_segment_masters.rb
# encoding: UTF-8
#
# Copyright (c) 2010-2017 GoodData Corporation. All rights reserved.
# This source code is licensed under the BSD-style license found in the
# LICENSE file in the root directory of this source tree.
require_relative 'base_action'
module GoodData
module LCM2
class CreateSegmentMasters < BaseAction
DESCRIPTION = 'Create Master Projects for Segments'
PARAMS = define_params(self) do
description 'Client Used for Connecting to GD'
param :gdc_gd_client, instance_of(Type::GdClientType), required: true
description 'Client used to connecting to development domain'
param :development_client, instance_of(Type::GdClientType), required: true
description 'Organization Name'
param :organization, instance_of(Type::StringType), required: false
description 'Domain'
param :domain, instance_of(Type::StringType), required: false
description 'ADS Client'
param :ads_client, instance_of(Type::AdsClientType), required: false
description 'Segments to manage'
param :segments, array_of(instance_of(Type::SegmentType)), required: true
description 'Tokens'
param :tokens, instance_of(Type::TokensType), required: true
description 'Table Name'
param :release_table_name, instance_of(Type::StringType), required: false
description 'Project Environment'
param :project_environment, instance_of(Type::StringType), required: false
description 'DataProduct to manage'
param :data_product, instance_of(Type::GDDataProductType), required: false
description 'Logger'
param :gdc_logger, instance_of(Type::GdLogger), required: true
end
class << self
def call(params)
results = []
client = params.gdc_gd_client
development_client = params.development_client
domain_name = params.organization || params.domain
fail "Either organisation or domain has to be specified in params" unless domain_name
domain = client.domain(domain_name) || fail("Invalid domain name specified - #{domain_name}")
data_product = params.data_product
domain_segments = domain.segments(:all, data_product)
# TODO: Support for 'per segment' provisioning
segments = params.segments
synchronize_projects = segments.map do |segment_in| # rubocop:disable Metrics/BlockLength
segment_id = segment_in.segment_id
development_pid = segment_in.development_pid
driver = segment_in.driver.downcase
token = params.tokens[driver.to_sym] || fail("Token for driver '#{driver}' was not specified")
ads_output_stage_uri = segment_in.ads_output_stage_uri
ads_output_stage_prefix = segment_in.ads_output_stage_prefix
# Create master project Postgres
version = get_project_version(params, domain_name, data_product, segment_id) + 1
master_name = segment_in.master_name.gsub('#{version}', version.to_s)
# Get project instance based on PID. Fail if invalid one was specified.
# TODO: Use development client for getting project
development_client.projects(development_pid) || fail("Invalid Development PID specified - #{development_pid}")
segment = domain_segments.find do |ds|
ds.segment_id == segment_id
end
# Create new master project
params.gdc_logger.info "Creating master project - name: '#{master_name}' development_project: '#{development_pid}', segment: '#{segment_id}', driver: '#{driver}'"
project = client.create_project(title: master_name, auth_token: token, driver: driver == 'vertica' ? 'vertica' : 'Pg', environment: params.project_environment)
# Does segment exists? If not, create new one and set initial master
if segment
segment_in[:is_new] = false
status = 'untouched'
else
params.gdc_logger.info "Creating segment #{segment_id}, master #{project.pid}"
segment = data_product.create_segment(segment_id: segment_id, master_project: project)
segment.synchronize_clients
segment_in[:is_new] = true
status = 'created'
end
master_project = nil
begin
master_project = segment.master_project
rescue => e
GoodData.logger.warn "Unable to get segment master, reason: #{e.message}"
end
if master_project.nil? || master_project.deleted?
segment.master_project = project
segment.save
segment_in[:is_new] = true
status = 'modified'
end
segment_in[:data_product_id] = data_product.data_product_id
segment_in[:master_pid] = project.pid
segment_in[:version] = version
segment_in[:timestamp] = Time.now.utc.iso8601
# Show new project
params.gdc_logger.info JSON.pretty_generate(project.json)
# Add new segment master project with additional info into output results
results << {
segment_id: segment_id,
name: master_name,
development_pid: development_pid,
master_pid: project.pid,
ads_output_stage_uri: ads_output_stage_uri,
ads_output_stage_prefix: ads_output_stage_prefix,
driver: driver,
status: status
}
{
segment: segment_id,
from: development_pid,
to: [{ pid: project.pid }],
ads_output_stage_uri: ads_output_stage_uri,
ads_output_stage_prefix: ads_output_stage_prefix
}
end
# Return results
{
results: results,
params: {
synchronize: synchronize_projects
}
}
end
def get_project_version(params, domain_name, data_product, segment_id)
if params.ads_client
current_master = GoodData::LCM2::Helpers.latest_master_project_from_ads(
params.release_table_name,
params.ads_client,
segment_id
)
else
data_product_id = data_product.data_product_id # data_product was populated by CollectDataProduct action already
current_master = GoodData::LCM2::Helpers.latest_master_project_from_nfs(domain_name, data_product_id, segment_id)
end
return 0 unless current_master
current_master[:version].to_i
end
end
end
end
end