module Dopi
DOPi CLI gloable options
Initializes the logger for the CLI
DOPi Plugin: Custom Command
DOPi dummy command.
this simply prints the command hash if there was one given
DOPi Plugin: Custom Command
DOPi Plugin: File Replace
SSH custom command
DOPi Plugin: Reboot a node
DOPi Plugin: Wait For Login
DOPi Plugin: File Contains
SSH custom command
DOPi Plugin: Wait For Login
DOPi Plugin: Wait For Login
Simple command parser class to parse arguments
Dopi
Credentials helper module
This module will provide a credentials method which contains all the credential objects for the plugin.
Make sure you call “validate_credentials” method from your validation method.
Implement a method “supported_credential_types” in your plugin if you want to limit the types which are supported and trow an error during validation if some other type is assigned
Simple command parser module for environment variable hashes
To set plugin specific defaults for the environment create a 'env_defaults' method which returns a hash with: { var => val, var2 => val2, … } This hash will be merged with the user specified hash.
Simple command parser module for exec
This is a mixin for command plugins that need to parse an exit Code of some sort
To set plugin specific defaults you can implement the 'expect_exit_codes_defaults' method which returns an array of expected exit codes
This is a mixin for command plugins that need to parse an output of some sort
Make sure to call the validation method from the class you use the module
To set plugin specific output parser patterns, implement the method 'parse_output_defaults' which should return a hash with the patterns.
This class represents the set commands for a specific node and step.
It will also manage the run group restrictions
This connector will execute commands over ssh
Various error classes for DOPi
Error hierarchy:
PluginLoaderError StateTransitionError NoRoleFoundError CommandParsingError CommandExecutionError CommandExecutionError ConnectionError NodeConnectionError CommandConnectionError
This class registers the plugins as they get loaded by ruby and can create instances based on the plugin name
This is the DOPi state store which persists the state of the steps between and during runs.
Constants
- VERSION
Public Class Methods
# File lib/dopi.rb, line 34 def self.add(raw_plan) raise StandardError, 'Plan not valid; did not add' unless valid?(raw_plan) plan_store.add(raw_plan) end
# File lib/dopi.rb, line 57 def self.list plan_store.list end
# File lib/dopi/log.rb, line 9 def self.log @log ||= DopCommon.log end
# File lib/dopi/log.rb, line 13 def self.logger=(logger) @log = logger DopCommon.logger = logger end
# File lib/dopi.rb, line 112 def self.on_state_change(plan_name) ensure_plan_exists(plan_name) state_store = Dopi::StateStore.new(plan_name, plan_store) state_store.on_change do yield end end
# File lib/dopi.rb, line 53 def self.remove(plan_name, remove_dopi_state = true, remove_dopv_state = false) plan_store.remove(plan_name, remove_dopi_state, remove_dopv_state) end
# File lib/dopi.rb, line 101 def self.reset(plan_name, force = false) ensure_plan_exists(plan_name) plan_store.run_lock(plan_name) do state_store = Dopi::StateStore.new(plan_name, plan_store) plan = get_plan(plan_name) plan.load_state(state_store.state_hash) plan.state_reset_with_children(force) state_store.persist_state(plan) end end
# File lib/dopi.rb, line 71 def self.run(plan_name, options = {}) ensure_plan_exists(plan_name) update_state(plan_name) plan_store.run_lock(plan_name) do state_store = Dopi::StateStore.new(plan_name, plan_store) dopv_state_store = plan_store.state_store(plan_name, 'dopv') dopv_state_store.transaction(true) do dopv_node_info = dopv_state_store[:nodes] || {} api_node_info = options[:node_info] || {} options[:node_info] = dopv_node_info.merge(api_node_info) end plan = get_plan(plan_name) plan.load_state(state_store.state_hash) manager = nil if block_given? manager = Thread.new { yield(plan) } else run_signal_handler(plan) end begin state_store_observer = Dopi::StateStoreObserver.new(plan, state_store) plan.add_observer(state_store_observer) plan.run(options) manager.join if manager ensure state_store_observer.update end end end
TODO: this returns a plan with loaded state at the moment. THIS MAY BE CHANGED IN THE FUTURE!!
# File lib/dopi.rb, line 63 def self.show(plan_name) ensure_plan_exists(plan_name) state_store = Dopi::StateStore.new(plan_name, plan_store) plan = get_plan(plan_name) plan.load_state(state_store.state_hash) plan end
# File lib/dopi.rb, line 39 def self.update_plan(raw_plan, options = {}) raise StandardError, 'Plan not valid; did not add' unless valid?(raw_plan) plan_name = plan_store.update(raw_plan) update_state(plan_name, options) plan_name end
# File lib/dopi.rb, line 46 def self.update_state(plan_name, options = {}) plan_store.run_lock(plan_name) do state_store = Dopi::StateStore.new(plan_name, plan_store) state_store.update(options) end end
# File lib/dopi.rb, line 27 def self.valid?(raw_plan) hash, _ = plan_store.read_plan_file(raw_plan) plan_parser = DopCommon::Plan.new(hash) plan = Dopi::Plan.new(plan_parser) plan.valid? end
Private Class Methods
# File lib/dopi.rb, line 160 def self.ensure_plan_exists(plan_name) unless plan_store.list.include?(plan_name) raise StandardError, "The plan #{plan_name} does not exist in the plan store" end end
# File lib/dopi.rb, line 126 def self.get_plan(plan_name) raise StandardError, 'Please update the plan state, there are pending updates' if pending_updates?(plan_name) plan_parser = plan_store.get_plan(plan_name) Dopi::Plan.new(plan_parser) end
# File lib/dopi.rb, line 132 def self.pending_updates?(plan_name) state_store = Dopi::StateStore.new(plan_name, plan_store) state_store.pending_updates? end
# File lib/dopi.rb, line 122 def self.plan_store @plan_store ||= DopCommon::PlanStore.new(DopCommon.config.plan_store_dir) end
# File lib/dopi.rb, line 137 def self.run_signal_handler(plan) plan.reset_signals signal_handler_thread = Thread.new do Dopi.log.info("Starting signal handling") signal_counter = 0 DopCommon::SignalHandler.new.handle_signals(:INT, :TERM) do signal_counter += 1 case signal_counter when 1 Dopi.log.warn("Signal received! The run will halt after all currently running commands are finished") plan.send_signal(:stop) when 2 Dopi.log.error("Signal received! Sending termination signal to all the processes!") plan.send_signal(:abort) when 3 Dopi.log.error("Signal received! Sending KILL signal to all the processes!") plan.send_signal(:kill) end end end signal_handler_thread.abort_on_exception = true end