Class: Kafo::ScenarioManager

Inherits:
Object
  • Object
show all
Defined in:
lib/kafo/scenario_manager.rb

Instance Attribute Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(config, last_scenario_link_name = 'last_scenario.yaml') ⇒ ScenarioManager

Returns a new instance of ScenarioManager.



10
11
12
13
14
15
# File 'lib/kafo/scenario_manager.rb', line 10

def initialize(config, last_scenario_link_name = 'last_scenario.yaml')
  @logger = Logger.new('scenario_manager')
  @config_dir = File.file?(config) ? File.dirname(config) : config
  @last_scenario_link = File.join(config_dir, last_scenario_link_name)
  @previous_scenario = File.exist?(last_scenario_link) ? Pathname.new(last_scenario_link).realpath.to_s : nil
end

Instance Attribute Details

#config_dirObject (readonly)

Returns the value of attribute config_dir.



8
9
10
# File 'lib/kafo/scenario_manager.rb', line 8

def config_dir
  @config_dir
end

Returns the value of attribute last_scenario_link.



8
9
10
# File 'lib/kafo/scenario_manager.rb', line 8

def last_scenario_link
  @last_scenario_link
end

#previous_scenarioObject (readonly)

Returns the value of attribute previous_scenario.



8
9
10
# File 'lib/kafo/scenario_manager.rb', line 8

def previous_scenario
  @previous_scenario
end

Instance Method Details

#available_scenariosObject



17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
# File 'lib/kafo/scenario_manager.rb', line 17

def available_scenarios
  # assume that *.yaml file in config_dir that has key :name is scenario definition
  @available_scenarios ||= Dir.glob(File.join(config_dir, '*.yaml')).reject { |f| f =~ /#{last_scenario_link}$/ }.inject({}) do |scns, scn_file|
    begin
      content = YAML.load_file(scn_file)
      if content.is_a?(Hash) && content.has_key?(:answer_file) && content.fetch(:enabled, true)
        # add scenario name for legacy configs
        content[:name] = Configuration.get_scenario_id(scn_file) unless content.has_key?(:name)
        scns[scn_file] = content
      end
    rescue Psych::SyntaxError => e
      warn "Warning: #{e}"
    end
    scns
  end
end

#check_disable_scenarioObject



138
139
140
141
# File 'lib/kafo/scenario_manager.rb', line 138

def check_disable_scenario
  scenario = scenario_from_args('--disable-scenario')
  set_scenario_availability(scenario, false) if scenario
end

#check_enable_scenarioObject



133
134
135
136
# File 'lib/kafo/scenario_manager.rb', line 133

def check_enable_scenario
  scenario = scenario_from_args('--enable-scenario')
  set_scenario_availability(scenario, true) if scenario
end

#check_scenario_change(scenario) ⇒ Object



121
122
123
124
125
126
127
128
129
130
131
# File 'lib/kafo/scenario_manager.rb', line 121

def check_scenario_change(scenario)
  if scenario_changed?(scenario)
    if ARGV.include? '--compare-scenarios'
      show_scenario_diff(@previous_scenario, scenario)
      dump_log_and_exit(0)
    else
      confirm_scenario_change(scenario)
      @logger.notice "Scenario #{scenario} was selected"
    end
  end
end

#configured?Boolean

Returns:

  • (Boolean)


77
78
79
# File 'lib/kafo/scenario_manager.rb', line 77

def configured?
  !!(defined?(CONFIG_DIR) && CONFIG_DIR)
end

#confirm_scenario_change(new_scenario) ⇒ Object



155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
# File 'lib/kafo/scenario_manager.rb', line 155

def confirm_scenario_change(new_scenario)
  if (ARGV & ['--interactive', '-i']).any?
    show_scenario_diff(@previous_scenario, new_scenario)

    wizard = KafoWizards.wizard(:cli, 'Confirm installation scenario selection',
      :description => "You are trying to replace an existing installation with a different scenario. This may lead to unpredictable states. Please confirm that you want to proceed.")
    wizard.entries << wizard.factory.button(:proceed, :label => 'Proceed with selected installation scenario', :default => false)
    wizard.entries << wizard.factory.button(:cancel, :label => 'Cancel Installation', :default => true)
    result = wizard.run
    if result == :cancel
      say 'Installation was cancelled by user'
      dump_log_and_exit(0)
    end
  elsif !ARGV.include?('--force') && !KafoConfigure.in_help_mode?
    message = "You are trying to replace existing installation with different scenario. This may lead to unpredictable states. " +
    "Use --force to override. You can use --compare-scenarios to see the differences"
    @logger.error(message)
    dump_log_and_exit(:scenario_error)
  end
  true
end


207
208
209
210
211
212
213
# File 'lib/kafo/scenario_manager.rb', line 207

def link_last_scenario(config_file)
  link_path = last_scenario_link
  if link_path
    File.delete(link_path) if File.symlink?(link_path)
    File.symlink(File.basename(config_file), link_path)
  end
end

#list_available_scenariosObject



34
35
36
37
38
39
40
41
42
43
44
45
# File 'lib/kafo/scenario_manager.rb', line 34

def list_available_scenarios
  say ::HighLine.color("Available scenarios", :info)
  available_scenarios.each do |config_file, content|
    scenario = File.basename(config_file, '.yaml')
    use = ((File.expand_path(config_file) == @previous_scenario) ? 'INSTALLED' : "use: --scenario #{scenario}")
    say ::HighLine.color("  #{content[:name]} ", :title)
    say "(#{use})"
    say "        " + content[:description] if !content[:description].nil? && !content[:description].empty?
  end
  say "  No available scenarios found in #{config_dir}" if available_scenarios.empty?
  KafoConfigure.exit(0)
end

#load_and_setup_configuration(config_file) ⇒ Object



215
216
217
218
219
220
# File 'lib/kafo/scenario_manager.rb', line 215

def load_and_setup_configuration(config_file)
  conf = load_configuration(config_file)
  conf.preset_defaults_from_puppet
  conf.preset_defaults_from_yaml
  conf
end

#load_configuration(config_file) ⇒ Object



222
223
224
# File 'lib/kafo/scenario_manager.rb', line 222

def load_configuration(config_file)
  Configuration.new(config_file)
end


177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
# File 'lib/kafo/scenario_manager.rb', line 177

def print_scenario_diff(prev_conf, new_conf)
  missing = new_conf.params_missing(prev_conf)
  changed = new_conf.params_changed(prev_conf)

  say "\n" + ::HighLine.color("Overview of modules used in the scenarios (#{prev_conf.app[:name]} -> #{new_conf.app[:name]}):", :title)
  modules = Hash.new { |h, k| h[k] = {} }
  modules = prev_conf.modules.inject(modules) { |mods, mod| mods[mod.name][:prev] = mod.enabled?; mods }
  modules = new_conf.modules.inject(modules) { |mods, mod| mods[mod.name][:new] = mod.enabled?; mods }
  printables = { "" => 'N/A', 'true' => 'ENABLED', 'false' => 'DISABLED' }
  modules.each do |mod, status|
    module_line = "%-50s: %-09s -> %s" % [mod, printables[status[:prev].to_s], printables[status[:new].to_s]]
    # highlight modules that will be disabled
    module_line = ::HighLine.color(module_line, :important) if status[:prev] == true && (status[:new] == false || status[:new].nil?)
    say module_line
  end

  say "\n" + ::HighLine.color("Defaults that will be updated with values from previous installation:", :title)
  if changed.empty?
    say "  No values will be updated from previous scenario"
  else
    changed.each { |param| say "  #{param.module.class_name}::#{param.name}: #{param.value} -> #{prev_conf.param(param.module.class_name, param.name).value}" }
  end
  say "\n" + ::HighLine.color("Values from previous installation that will be lost by scenario change:", :title)
  if missing.empty?
    say "  No values from previous installation will be lost"
  else
    missing.each { |param| say "  #{param.module.class_name}::#{param.name}: #{param.value}\n" }
  end
end

#scenario_changed?(scenario) ⇒ Boolean

Returns:

  • (Boolean)


72
73
74
75
# File 'lib/kafo/scenario_manager.rb', line 72

def scenario_changed?(scenario)
  scenario = Pathname.new(scenario).realpath.to_s if File.symlink?(scenario)
  !!previous_scenario && scenario != previous_scenario
end

#scenario_enabled?(scenario) ⇒ Boolean

Returns:

  • (Boolean)


151
152
153
# File 'lib/kafo/scenario_manager.rb', line 151

def scenario_enabled?(scenario)
  load_configuration(scenario).app[:enabled]
end

#scenario_from_args(arg_name = '--scenario|-S') ⇒ Object



81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
# File 'lib/kafo/scenario_manager.rb', line 81

def scenario_from_args(arg_name = '--scenario|-S')
  # try scenario provided in the args via -S or --scenario
  ARGV.each_with_index do |arg, index|
    parsed = arg.match(/^(#{arg_name})($|=(?<scenario>\S+))/)
    if parsed
      scenario = parsed[:scenario] || ARGV[index + 1]
      next unless scenario

      scenario_file = File.join(config_dir, "#{scenario}.yaml")
      return scenario_file if File.exist?(scenario_file)
      fail_now("Scenario (#{scenario_file}) was not found, can not continue", :unset_scenario)
    end
  end

  nil
end

#scenario_selection_wizardObject



47
48
49
50
51
52
53
54
55
56
57
58
# File 'lib/kafo/scenario_manager.rb', line 47

def scenario_selection_wizard
  wizard = KafoWizards.wizard(:cli, 'Select installation scenario',
    :description => "Please select one of the pre-set installation scenarios. You can customize your setup later during the installation.")
  f = wizard.factory
  available_scenarios.keys.each do |scn|
    label = available_scenarios[scn][:name].to_s
    label += ": #{available_scenarios[scn][:description]}" if available_scenarios[scn][:description]
    wizard.entries << f.button(scn, :label => label, :default => true)
  end
  wizard.entries << f.button(:cancel, :label => 'Cancel Installation', :default => false)
  wizard
end

#select_scenarioObject



98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
# File 'lib/kafo/scenario_manager.rb', line 98

def select_scenario
  scenario = scenario_from_args || previous_scenario ||
    (available_scenarios.keys.count == 1 && available_scenarios.keys.first) ||
    select_scenario_interactively
  if scenario.nil?
    fail_now("No installation scenario was selected, the installer cannot continue.\n" +
      "       Even --help content is dependent on selected scenario.\n" +
      "       Select scenario with --scenario SCENARIO or list available scenarios with --list-scenarios.", :unset_scenario)
  elsif !scenario_enabled?(scenario)
    fail_now("Selected scenario is DISABLED, can not continue.\n" +
      "       Use --list-scenarios to list available options.\n" +
      "       You can also --enable-scenario SCENARIO to make the selected scenario available.", :scenario_error)
  end
  scenario
end

#select_scenario_interactivelyObject



60
61
62
63
64
65
66
67
68
69
70
# File 'lib/kafo/scenario_manager.rb', line 60

def select_scenario_interactively
  # let the user select if in interactive mode
  if (ARGV & ['--interactive', '-i']).any?
    res = scenario_selection_wizard.run
    if res == :cancel
      say 'Installation was cancelled by user'
      KafoConfigure.exit(0)
    end
    res
  end
end

#set_scenario_availability(scenario, available) ⇒ Object



143
144
145
146
147
148
149
# File 'lib/kafo/scenario_manager.rb', line 143

def set_scenario_availability(scenario, available)
  cfg = load_configuration(scenario)
  cfg.app[:enabled] = available
  cfg.save_configuration(cfg.app)
  say "Scenario #{File.basename(scenario, ".yaml")} was #{available ? "enabled" : "disabled"}"
  KafoConfigure.exit(0)
end

#show_scenario_diff(prev_scenario, new_scenario) ⇒ Object



114
115
116
117
118
119
# File 'lib/kafo/scenario_manager.rb', line 114

def show_scenario_diff(prev_scenario, new_scenario)
  say ::HighLine.color("Scenarios are being compared, that may take a while...", :info)
  prev_conf = load_and_setup_configuration(prev_scenario)
  new_conf = load_and_setup_configuration(new_scenario)
  print_scenario_diff(prev_conf, new_conf)
end