class GrafanaReporter::ConsoleConfigurationWizard

This class provides a console configuration wizard, to reduce the manual efforts that have to be spent for that action and to reduce mistakes as good as possible.

Public Instance Methods

start_wizard(config_file, console_config) click to toggle source

Provides a command line configuration wizard for setting up the necessary configuration file. TODO: refactor class

# File lib/grafana_reporter/console_configuration_wizard.rb, line 10
def start_wizard(config_file, console_config)
  action = overwrite_or_use_config_file(config_file)
  return if action == 'abort'

  config = create_config_wizard(config_file, console_config) if action == 'overwrite'
  config ||= Configuration.new

  begin
    config.config = YAML.load_file(config_file)
  rescue StandardError => e
    raise ConfigurationError, "Could not read config file '#{config_file}' (Error: #{e.message})\n"\
          "Source:\n#{File.read(config_file)}"
  end

  begin
    config.validate(true)
    puts 'Configuration file validated successfully.'
  rescue ConfigurationError => e
    raise e
  end

  demo_report = create_demo_report(config)

  demo_report ||= '<<your_report_name>>'
  config_param = config_file == Configuration::DEFAULT_CONFIG_FILE_NAME ? '' : " -c #{config_file}"
  program_call = "#{Gem.ruby} #{$PROGRAM_NAME}"
  program_call = ENV['OCRA_EXECUTABLE'].gsub("#{Dir.pwd}/".gsub('/', '\\'), '') if ENV['OCRA_EXECUTABLE']

  puts
  puts 'Now everything is setup properly. Create your reports as required in the templates '\
       'folder and run the reporter either standalone with e.g. the following command:'
  puts
  puts "   #{program_call}#{config_param} -t #{demo_report} -o demo_report.#{config.report_class.default_result_extension}"
  puts
  puts 'or run it as a service using the following command:'
  puts
  puts "   #{program_call}#{config_param}"
  puts
  puts "Open 'http://localhost:#{config.webserver_port}/render?var-template=#{demo_report}' in a webbrowser to"\
       ' test your configuration.'
end

Private Instance Methods

create_config_wizard(config_file, console_config) click to toggle source
# File lib/grafana_reporter/console_configuration_wizard.rb, line 54
    def create_config_wizard(config_file, console_config)
      config = Configuration.new

      puts 'This wizard will guide you through an initial configuration for'\
           ' the ruby-grafana-reporter. The configuration file will be created'\
           ' in the current folder. Please make sure to specify necessary paths'\
           ' either with a relative or an absolute path properly.'
      puts
      puts "Wizard is creating configuration file '#{config_file}'."
      puts
      port = ui_config_port
      grafana = ui_config_grafana(console_config)
      templates = ui_config_templates_folder
      reports = ui_config_reports_folder
      images = ui_config_images_folder(templates)
      retention = ui_config_retention

      config_yaml = %(# This configuration has been built with the configuration wizard.

#{grafana}

grafana-reporter:
  report-class: GrafanaReporter::Asciidoctor::Report
  templates-folder: #{templates}
  reports-folder: #{reports}
  report-retention: #{retention}
  webservice-port: #{port}
# you may want to configure the following webhook callbacks to get informed on certain events
#  callbacks:
#    all:
#      - <<your_callback_url>>
#      - ...
#    on_before_create:
#      - <<your_callback_url>>
#      - ...
#    on_after_cancel:
#      - <<your_callback_url>>
#      - ...
#    on_after_finish:
#      - <<your_callback_url>>
#      - ...

default-document-attributes:
  imagesdir: #{images}
# feel free to add here additional asciidoctor document attributes which are applied to all your templates
)

      begin
        File.write(config_file, config_yaml, mode: 'w')
        puts 'Configuration file successfully created.'
      rescue StandardError => e
        raise e
      end

      config
    end
create_demo_report(config) click to toggle source
# File lib/grafana_reporter/console_configuration_wizard.rb, line 111
def create_demo_report(config)
  unless Dir.exist?(config.templates_folder)
    puts "Skip creation of DEMO template, as folder '#{config.templates_folder}' does not exist."
    return nil
  end

  create = user_input('Shall I create a demo report for your new configuration file? Please note '\
                      'that this report might contain confidential information, depending on the '\
                      'confidentiality of the information stored in your dashboard.', 'yN')
  return nil unless create =~ /^(?:y|Y)$/

  demo_report = 'demo_report'
  demo_report_file = "#{config.templates_folder}#{demo_report}.#{config.report_class.default_template_extension}"

  # ask to overwrite file
  if File.exist?(demo_report_file)
    input = user_input("Demo template '#{demo_report_file}' does already exist. Do you want to "\
                       'overwrite it?', 'yN')

    case input
    when /^(?:y|Y)$/
      puts 'Overwriting existing DEMO template.'

    else
      puts 'Skip creation of DEMO template.'
      return demo_report
    end
  end

  grafana = ::Grafana::Grafana.new(config.grafana_host, config.grafana_api_key)
  demo_report_content = DemoReportWizard.new(config.report_class.demo_report_classes).build(grafana)

  begin
    File.write(demo_report_file, demo_report_content, mode: 'w')
    puts "DEMO template '#{demo_report_file}' successfully created."
  rescue StandardError => e
    puts e.message
    return nil
  end

  demo_report
end
overwrite_or_use_config_file(config_file) click to toggle source
# File lib/grafana_reporter/console_configuration_wizard.rb, line 296
def overwrite_or_use_config_file(config_file)
  return 'overwrite' unless File.exist?(config_file)

  input = nil
  until input
    input = user_input("Configuration file '#{config_file}' already exists. Do you want to [o]verwrite it, "\
                       'use it to for [d]emo report creation only, or [a]bort?', 'odA')
  end

  return 'demo_report' if input =~ /^(?:d|D)$/
  return 'abort' if input =~ /^(?:A|a|odA)$/

  'overwrite'
end
ui_config_grafana(config) click to toggle source
# File lib/grafana_reporter/console_configuration_wizard.rb, line 154
    def ui_config_grafana(config)
      valid = false
      url = nil
      api_key = nil
      until valid
        url ||= user_input('Specify grafana host', 'http://localhost:3000')
        print "Testing connection to '#{url}' #{api_key ? '_with_' : '_without_'} API key..."
        begin
          res = Grafana::Grafana.new(url,
                                     api_key,
                                     logger: config.logger).test_connection
        rescue StandardError => e
          puts
          puts e.message
        end
        puts 'done.'

        case res
        when 'Admin'
          tmp = user_input('Access to grafana is permitted as Admin, which is a potential security risk.'\
                ' Do you want to use another [a]pi key, [r]e-enter url key or [i]gnore?', 'aRi')

          case tmp
          when /(?:i|I)$/
            valid = true

          when /(?:a|A)$/
            print 'Enter API key: '
            api_key = gets.strip

          else
            url = nil
            api_key = nil

          end

        when 'NON-Admin'
          print 'Access to grafana is permitted as NON-Admin.'
          valid = true

        else
          tmp = user_input("Grafana could not be accessed at '#{url}'. Do you want to use an [a]pi key,"\
                ' [r]e-enter url, or [i]gnore and proceed?', 'aRi')

          case tmp
          when /(?:i|I)$/
            valid = true

          when /(?:a|A)$/
            print 'Enter API key: '
            api_key = gets.strip

          else
            url = nil
            api_key = nil

          end

        end
      end
      %(grafana:
  default:
    host: #{url}#{api_key ? "\n    api_key: #{api_key}" : ''}
)
    end
ui_config_images_folder(parent) click to toggle source
# File lib/grafana_reporter/console_configuration_wizard.rb, line 247
def ui_config_images_folder(parent)
  input = nil
  until input
    input = user_input('Specify path where rendered images shall be stored (relative to templates folder)',
                       './images')
    input = nil unless validate_config_folder(File.join(parent, input))
  end
  input
end
ui_config_port() click to toggle source
# File lib/grafana_reporter/console_configuration_wizard.rb, line 220
def ui_config_port
  input = nil
  until input
    input = user_input('Specify port on which reporter shall run', '8815')
    input = nil unless input =~ /[0-9]+/
  end
  input
end
ui_config_reports_folder() click to toggle source
# File lib/grafana_reporter/console_configuration_wizard.rb, line 238
def ui_config_reports_folder
  input = nil
  until input
    input = user_input('Specify path where created reports shall be stored', './reports')
    input = nil unless validate_config_folder(input)
  end
  input
end
ui_config_retention() click to toggle source
# File lib/grafana_reporter/console_configuration_wizard.rb, line 257
def ui_config_retention
  input = nil
  until input
    input = user_input('Specify report retention duration in hours', '24')
    input = nil unless input =~ /[0-9]+/
  end
  input
end
ui_config_templates_folder() click to toggle source
# File lib/grafana_reporter/console_configuration_wizard.rb, line 229
def ui_config_templates_folder
  input = nil
  until input
    input = user_input('Specify path where templates shall be stored', './templates')
    input = nil unless validate_config_folder(input)
  end
  input
end
user_input(text, default) click to toggle source
# File lib/grafana_reporter/console_configuration_wizard.rb, line 266
def user_input(text, default)
  print "#{text} [#{default}]: "
  input = gets.gsub(/\n$/, '')
  input = default if input.empty?
  input
end
validate_config_folder(folder) click to toggle source
# File lib/grafana_reporter/console_configuration_wizard.rb, line 273
def validate_config_folder(folder)
  return true if Dir.exist?(folder)

  print "Directory '#{folder} does not exist: [c]reate, [r]e-enter path or [i]gnore? [cRi]: "
  case gets
  when /^(?:c|C)$/
    begin
      Dir.mkdir(folder)
      puts "Directory '#{folder}' successfully created."
      return true
    rescue StandardError => e
      puts "WARN: Directory '#{folder}' could not be created. Please create it manually."
      puts e.message
    end

  when /^(?:i|I)$/
    puts "WARN: Directory '#{folder}' does not exist. Please create manually."
    return true
  end

  false
end