module GoodData::LCM2
Constants
- MODES
- MODE_NAMES
Public Class Methods
Source
# File lib/gooddata/lcm/lcm2.rb, line 456 def check_unused_params(actions, params) default_params = [ :client_gdc_hostname, :client_gdc_protocol, :fail_early, :gdc_logger, :gdc_password, :gdc_username, :strict ] action_params = actions.map do |action| action.const_get(:PARAMS).keys.map(&:downcase) end action_params.flatten!.uniq! param_names = params.keys.map(&:downcase) unused_params = param_names - (action_params + default_params) if unused_params.any? GoodData.logger.warn("Following params are not used by any action: #{JSON.pretty_generate(unused_params)}") rows = [] actions.each do |action| action_params = action.const_get(:PARAMS) action_params.each do |_k, v| rows << [action.short_name, v[:name], v[:description], v[:type].class.short_name] end end table = Terminal::Table.new :headings => ['Action', 'Parameter', 'Description', 'Parameter Type'], :rows => rows GoodData.logger.info("\n#{table}") end end
Source
# File lib/gooddata/lcm/lcm2.rb, line 191 def convert_params(params) # Symbolize all keys GoodData::Helpers.symbolize_keys!(params) params.keys.each do |k| params[k.downcase] = params[k] end params.reject! do |k, _| k.downcase != k end convert_to_smart_hash(params) end
Source
# File lib/gooddata/lcm/lcm2.rb, line 203 def convert_to_smart_hash(params) if params.is_a?(Hash) res = SmartHash.new params.each_pair do |k, v| if v.is_a?(Hash) || v.is_a?(Array) res[k] = convert_to_smart_hash(v) else res[k] = v end end res elsif params.is_a?(Array) params.map do |item| convert_to_smart_hash(item) end else params end end
Source
# File lib/gooddata/lcm/lcm2.rb, line 223 def get_mode_actions(mode) mode = mode.to_sym actions = MODES[mode] if mode == :generic_lifecycle [] else actions || fail("Invalid mode specified '#{mode}', supported modes are: '#{MODE_NAMES.join(', ')}'") end end
Source
# File lib/gooddata/lcm/lcm2.rb, line 297 def perform(mode, params = {}) # Default setting for $pmap_default_thread_count = 20 in gooddata.rb file. We are going to decrease default # number of threads count to 10 for LCM bricks only $pmap_default_thread_count = 10 # rubocop:disable GlobalVars params = convert_params(params) GoodData.gd_logger.brick = mode final_mode = if params.set_master_project && mode == 'release' 'release_set_master_project' else mode end # Get actions for mode specified actions = get_mode_actions(final_mode) if params.actions actions = params.actions.map do |action| "GoodData::LCM2::#{action}".split('::').inject(Object) do |o, c| begin o.const_get(c) rescue NameError fail NameError, "Cannot find action 'GoodData::LCM2::#{action}'" end end end end # TODO: Check all action params first fail_early = if params.key?(:fail_early) params.fail_early.to_b else true end strict_mode = if params.key?(:strict) params.strict.to_b else true end skip_actions = (params.skip_actions || []) actions = actions.reject do |action| skip_actions.include?(action.name.split('::').last) end sync_mode = params.fetch(:sync_mode, nil) if mode == 'users' && %w[add_to_organization remove_from_organization].include?(sync_mode) actions = actions.reject do |action| %w[CollectDataProduct CollectSegments].include?(action.name.split('::').last) end end check_unused_params(actions, params) print_action_names(mode, actions) # Run actions errors = [] results = [] actions.each do |action| GoodData.logger.info("\n") # Invoke action begin out = run_action action, params rescue Exception => e # rubocop:disable Style/RescueException errors << { action: action, err: e, backtrace: e.backtrace } break if fail_early results << nil end # in case fail_early = false, we need to execute another action next unless out # Handle output results and params res = out.is_a?(Array) ? out : out[:results] out_params = out.is_a?(Hash) ? out[:params] || {} : {} new_params = convert_to_smart_hash(out_params) # Merge with new params params.merge!(new_params) # Print action result print_action_result(action, res) if action.send(:print_result, params) # Store result for final summary results << res end brick_results = {} actions.each_with_index do |action, index| brick_results[action.short_name] = results[index] end result = { actions: actions.map(&:short_name), results: brick_results, params: params, success: errors.empty? } if errors.any? error_message = JSON.pretty_generate(errors) if strict_mode raise GoodData::LcmExecutionError.new(errors[0][:err], error_message) else GoodData.logger.error(error_message) end end process_sync_failed_projects(params) if GoodData::LCM2::Helpers.collect_synced_status(params) && strict_mode result end
Source
# File lib/gooddata/lcm/lcm2.rb, line 233 def print_action_names(mode, actions) title = "Actions to be performed for mode '#{mode}'" headings = %w(# NAME DESCRIPTION) rows = [] actions.each_with_index do |action, index| rows << [index, action.short_name, action.const_defined?(:DESCRIPTION) && action.const_get(:DESCRIPTION)] end table = Terminal::Table.new :title => title, :headings => headings do |t| rows.each_with_index do |row, index| t << row t.add_separator if index < rows.length - 1 end end GoodData.logger.info("\n#{table}") end
Source
# File lib/gooddata/lcm/lcm2.rb, line 252 def print_action_result(action, messages) title = "Result of #{action.short_name}" keys = if action.const_defined?('RESULT_HEADER') action.const_get('RESULT_HEADER') else GoodData.logger.warn("Action #{action.name} does not have RESULT_HEADERS, inferring headers from results.") (messages.first && messages.first.keys) || [] end headings = keys.map(&:upcase) rows = messages && messages.map do |message| unless message GoodData.logger.warn("Found an empty message in the results of the #{action.name} action") next end row = [] keys.each do |heading| row << message[heading] end row end rows ||= [] rows.compact! table = Terminal::Table.new :title => title, :headings => headings do |t| rows.each_with_index do |row, index| t << (row || []) t.add_separator if index < rows.length - 1 end end GoodData.logger.info("\n#{table}") end
Source
# File lib/gooddata/lcm/lcm2.rb, line 289 def print_actions_result(actions, results) actions.each_with_index do |action, index| print_action_result(action, results[index]) GoodData.logger.info end nil end
Source
# File lib/gooddata/lcm/lcm2.rb, line 417 def process_sync_failed_projects(params) sync_failed_list = params[:sync_failed_list] sync_project_list = sync_failed_list[:project_client_mappings] sync_failed_project_list = sync_failed_list[:failed_detailed_projects] if sync_project_list && sync_failed_project_list && sync_project_list.size.positive? && sync_failed_project_list.size.positive? failed_project = sync_failed_project_list[0] summary_message = "Existing errors during execution. See log for details" error_message = failed_project[:message] if sync_project_list.size == sync_failed_project_list.size raise GoodData::LcmExecutionError.new(summary_message, error_message) else raise GoodData::LcmExecutionWarning.new(summary_message, error_message) end end end
Source
# File lib/gooddata/lcm/lcm2.rb, line 434 def run_action(action, params) begin GoodData.gd_logger.start_action action, GoodData.gd_logger GoodData.gd_logger.info("Running #{action.name} action ...") params.clear_filters # Check if all required parameters were passed BaseAction.check_params(action.const_get('PARAMS'), params) params.setup_filters(action.const_get('PARAMS')) out = action.send(:call, params) rescue Exception => e # rubocop:disable Style/RescueException # Log to splunk GoodData.gd_logger.error("action=#{action} status=failed message=#{e} exception=#{e.backtrace}") # Log to execution log GoodData.logger.error("Execution #{action} failed. Error: #{e}. Detail:#{e.backtrace}") raise e ensure params.clear_filters GoodData.gd_logger.end_action GoodData.gd_logger end out end