climatic 0.2.26
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +7 -0
- data/.gitignore +14 -0
- data/.rspec +2 -0
- data/.travis.yml +5 -0
- data/CODE_OF_CONDUCT.md +74 -0
- data/Gemfile +4 -0
- data/LICENSE.txt +21 -0
- data/README.md +52 -0
- data/Rakefile +6 -0
- data/bin/console +14 -0
- data/bin/setup +8 -0
- data/climatic.gemspec +28 -0
- data/example/simple_app/.gitignore +12 -0
- data/example/simple_app/.rspec +2 -0
- data/example/simple_app/.ruby-version +1 -0
- data/example/simple_app/.travis.yml +5 -0
- data/example/simple_app/CODE_OF_CONDUCT.md +74 -0
- data/example/simple_app/Gemfile +6 -0
- data/example/simple_app/LICENSE.txt +21 -0
- data/example/simple_app/README.md +43 -0
- data/example/simple_app/Rakefile +6 -0
- data/example/simple_app/bin/console +14 -0
- data/example/simple_app/bin/setup +8 -0
- data/example/simple_app/etc/command_line.yml +52 -0
- data/example/simple_app/exe/user +57 -0
- data/example/simple_app/lib/tst_climatic/version.rb +3 -0
- data/example/simple_app/lib/tst_climatic.rb +5 -0
- data/example/simple_app/spec/spec_helper.rb +14 -0
- data/example/simple_app/spec/tst_climatic_spec.rb +11 -0
- data/example/simple_app/tst_climatic.gemspec +39 -0
- data/lib/climatic/config_layers/command_line_layer.rb +46 -0
- data/lib/climatic/config_layers/command_line_manager_binder.rb +84 -0
- data/lib/climatic/config_layers/env_layer.rb +41 -0
- data/lib/climatic/config_layers/executable_gem_layer.rb +45 -0
- data/lib/climatic/config_layers/gem_layer.rb +50 -0
- data/lib/climatic/config_layers/generic_layer.rb +62 -0
- data/lib/climatic/config_layers/global_layer.rb +28 -0
- data/lib/climatic/config_layers/program_description_helper.rb +94 -0
- data/lib/climatic/config_layers/project_layer.rb +61 -0
- data/lib/climatic/config_layers/provided_config_file_layer.rb +26 -0
- data/lib/climatic/config_layers/source_helper.rb +48 -0
- data/lib/climatic/config_layers/system_layer.rb +37 -0
- data/lib/climatic/config_layers/user_layer.rb +40 -0
- data/lib/climatic/initializer.rb +87 -0
- data/lib/climatic/layers_manager.rb +81 -0
- data/lib/climatic/logger/accumulator.rb +49 -0
- data/lib/climatic/logger/manager.rb +50 -0
- data/lib/climatic/logger/wrapper.rb +12 -0
- data/lib/climatic/processes/base.rb +51 -0
- data/lib/climatic/processes/command.rb +15 -0
- data/lib/climatic/processes/synchronous.rb +51 -0
- data/lib/climatic/processes/time_management.rb +21 -0
- data/lib/climatic/proxy.rb +27 -0
- data/lib/climatic/script/base.rb +65 -0
- data/lib/climatic/script/simple.rb +31 -0
- data/lib/climatic/script/unimplemented_processor.rb +19 -0
- data/lib/climatic/script.rb +4 -0
- data/lib/climatic/utils/error.rb +5 -0
- data/lib/climatic/utils/input.rb +65 -0
- data/lib/climatic/utils/safe_exec.rb +28 -0
- data/lib/climatic/utils/script_helper.rb +18 -0
- data/lib/climatic/version.rb +3 -0
- data/lib/climatic.rb +45 -0
- metadata +162 -0
@@ -0,0 +1,87 @@
|
|
1
|
+
module Climatic
|
2
|
+
|
3
|
+
module Initializer
|
4
|
+
|
5
|
+
include Climatic::Utils::ScriptHelper
|
6
|
+
|
7
|
+
attr_reader :config
|
8
|
+
|
9
|
+
def bootstrap(cmd_line_args: ARGV.dup,
|
10
|
+
command_manager: Climatic::ConfigLayers::CommandLineLayer.default_command_line_manager)
|
11
|
+
raise Climatic::Error, 'You cannot bootstrap Climatic framework twice !' if climatic_bootstrapped?
|
12
|
+
@climatic_status = :bootstrapping
|
13
|
+
setup_initial_logger
|
14
|
+
Climatic.logger.debug 'Starting Climatic framework setup...'
|
15
|
+
# Get the config first to correctly setup the definitive logger
|
16
|
+
setup_config_manager cmd_line_args, command_manager
|
17
|
+
# Now we can setup the definitive logger
|
18
|
+
setup_logger
|
19
|
+
Climatic.logger.debug 'Climatic framework setup complete.'
|
20
|
+
@climatic_status = :bootstrapped
|
21
|
+
rescue Slop::UnknownOption
|
22
|
+
Climatic.logger.debug 'Climatic initialization failed (wrong command line options) !'
|
23
|
+
end
|
24
|
+
|
25
|
+
def climatic_bootstrapping?
|
26
|
+
@climatic_status == :bootstrapping
|
27
|
+
end
|
28
|
+
|
29
|
+
def climatic_bootstrapped?
|
30
|
+
@climatic_status == :bootstrapped
|
31
|
+
end
|
32
|
+
|
33
|
+
private
|
34
|
+
|
35
|
+
def setup_config_manager(cmd_line_args, command_manager)
|
36
|
+
@config = Climatic::LayersManager.new
|
37
|
+
config.command_line_layer.command_line_manager = command_manager
|
38
|
+
config.command_line_layer.cmd_line_args = cmd_line_args
|
39
|
+
end
|
40
|
+
|
41
|
+
def setup_initial_logger
|
42
|
+
@logger = Climatic::Logger::Accumulator.new
|
43
|
+
UltraCommandLine.logger = @logger
|
44
|
+
end
|
45
|
+
|
46
|
+
def setup_logger
|
47
|
+
if config[:debug]
|
48
|
+
log_device = if config[:'log-file']
|
49
|
+
if File.exists? config[:'log-file']
|
50
|
+
if File.writable? config[:'log-file']
|
51
|
+
if config[:'truncate-log-file']
|
52
|
+
File.open(config[:'log-file'], 'w') do |log_file|
|
53
|
+
log_file.puts "Log truncated on #{Time.now}"
|
54
|
+
end
|
55
|
+
end
|
56
|
+
config[:'log-file']
|
57
|
+
else
|
58
|
+
STDERR.puts "WARNING: Log file '#{config[:'log-file']}' is not writable. Switching to STDERR..."
|
59
|
+
config[:'log-file'] = nil
|
60
|
+
STDERR
|
61
|
+
end
|
62
|
+
else
|
63
|
+
if File.writable? File.dirname(config[:'log-file'])
|
64
|
+
config[:'log-file']
|
65
|
+
else
|
66
|
+
STDERR.puts "WARNING: Cannot write log file in '#{File.dirname config[:'log-file']}'. Switching to STDERR..."
|
67
|
+
config[:'log-file'] = nil
|
68
|
+
STDERR
|
69
|
+
end
|
70
|
+
end
|
71
|
+
elsif config[:'debug-on-stderr']
|
72
|
+
STDERR
|
73
|
+
else
|
74
|
+
STDOUT
|
75
|
+
end
|
76
|
+
|
77
|
+
new_logger = ::Logger.new log_device
|
78
|
+
new_logger.level = config[:'log-level'] || Climatic::Logger::Manager::DEFAULT_LOG_LEVEL
|
79
|
+
self.logger = new_logger
|
80
|
+
else
|
81
|
+
self.logger = user_defined_logger
|
82
|
+
end
|
83
|
+
end
|
84
|
+
|
85
|
+
end
|
86
|
+
|
87
|
+
end
|
@@ -0,0 +1,81 @@
|
|
1
|
+
module Climatic
|
2
|
+
class LayersManager < SuperStack::Manager
|
3
|
+
|
4
|
+
include Climatic::ConfigLayers::ProgramDescriptionHelper
|
5
|
+
|
6
|
+
attr_reader :system_layer, :global_layer, :executable_gem_layer, :user_layer, :env_layer,
|
7
|
+
:command_line_layer, :provided_config_file_layer, :project_layer
|
8
|
+
|
9
|
+
def initialize
|
10
|
+
super
|
11
|
+
self.merge_policy = SuperStack::MergePolicies::FullMergePolicy
|
12
|
+
setup_layers
|
13
|
+
end
|
14
|
+
|
15
|
+
|
16
|
+
def self.default_config_file_base_name
|
17
|
+
File.basename($PROGRAM_NAME).gsub /\.[^\.]+$/, ''
|
18
|
+
end
|
19
|
+
|
20
|
+
def include_project_layer(file_or_directory, project_file_basename=nil, priority = 65)
|
21
|
+
@project_layer = Climatic::ConfigLayers::ProjectLayer.new file_or_directory, project_file_basename
|
22
|
+
project_layer.name = 'Project level'
|
23
|
+
project_layer.priority = priority
|
24
|
+
self << project_layer
|
25
|
+
end
|
26
|
+
|
27
|
+
def include_env_layer(filter = nil, priority = 70)
|
28
|
+
@env_layer = Climatic::ConfigLayers::EnvLayer.new filter
|
29
|
+
env_layer.name = 'Environment variables level'
|
30
|
+
env_layer.priority = priority
|
31
|
+
self << env_layer
|
32
|
+
end
|
33
|
+
|
34
|
+
def include_gem_layer_for(gem_name, priority = 30)
|
35
|
+
gem_layer = Climatic::ConfigLayers::GemLayer.new
|
36
|
+
gem_layer.gem_name = gem_name
|
37
|
+
raise "No config found in gem #{gem_name}" if gem_layer.file_name.nil?
|
38
|
+
gem_layer.name = "#{gem_name} Gem configuration level"
|
39
|
+
gem_layer.priority = priority
|
40
|
+
self << gem_layer
|
41
|
+
end
|
42
|
+
|
43
|
+
private
|
44
|
+
|
45
|
+
def setup_layers
|
46
|
+
# The command line level.
|
47
|
+
@command_line_layer = setup_layer Climatic::ConfigLayers::CommandLineLayer, 'Command line configuration level', 100
|
48
|
+
|
49
|
+
# The system level
|
50
|
+
@system_layer = setup_layer Climatic::ConfigLayers::SystemLayer, 'System-wide configuration level', 10
|
51
|
+
|
52
|
+
# The executable gem level
|
53
|
+
@executable_gem_layer = setup_layer Climatic::ConfigLayers::ExecutableGemLayer, 'Gem associated to the executable running configuration level', 20
|
54
|
+
|
55
|
+
# The global level
|
56
|
+
@global_layer = setup_layer Climatic::ConfigLayers::GlobalLayer, 'Global configuration level', 40
|
57
|
+
|
58
|
+
# The user level
|
59
|
+
@user_layer = setup_layer Climatic::ConfigLayers::UserLayer, 'User configuration level', 50
|
60
|
+
|
61
|
+
# The specifically provided config file level
|
62
|
+
@provided_config_file_layer = setup_layer Climatic::ConfigLayers::ProvidedConfigFileLayer, 'Specific config file configuration level', 60
|
63
|
+
|
64
|
+
# The layer to write something
|
65
|
+
override_layer = setup_layer SuperStack::Layer, 'Overridden configuration level', 1000
|
66
|
+
self.write_layer = override_layer
|
67
|
+
|
68
|
+
reload_layers
|
69
|
+
end
|
70
|
+
|
71
|
+
def setup_layer(class_type, name, priority)
|
72
|
+
layer = class_type.new
|
73
|
+
layer.name = name
|
74
|
+
layer.priority = priority
|
75
|
+
self << layer
|
76
|
+
layer
|
77
|
+
end
|
78
|
+
|
79
|
+
|
80
|
+
end
|
81
|
+
end
|
@@ -0,0 +1,49 @@
|
|
1
|
+
module Climatic
|
2
|
+
module Logger
|
3
|
+
|
4
|
+
class Accumulator
|
5
|
+
|
6
|
+
STACK_OPS = %i(debug info warn error fatal unknown).freeze
|
7
|
+
|
8
|
+
attr_accessor :level
|
9
|
+
|
10
|
+
def initialize
|
11
|
+
@log_lines = [{op: :debug, args: ['Starting special temporary "accumulator" logger...']}]
|
12
|
+
end
|
13
|
+
|
14
|
+
def stack(op, *args)
|
15
|
+
log_lines << {op: op, args: args}
|
16
|
+
end
|
17
|
+
|
18
|
+
def transfer_content_to(other_logger)
|
19
|
+
debug "Transferring accumulated logs to logger '#{other_logger.inspect}'"
|
20
|
+
if other_logger.nil?
|
21
|
+
@log_lines = []
|
22
|
+
return
|
23
|
+
end
|
24
|
+
log_lines.each do |log_line|
|
25
|
+
other_logger.send log_line[:op], *log_line[:args]
|
26
|
+
end
|
27
|
+
@log_lines = []
|
28
|
+
end
|
29
|
+
|
30
|
+
def method_missing(method_name, *args)
|
31
|
+
if STACK_OPS.include? method_name
|
32
|
+
stack method_name, *args
|
33
|
+
else
|
34
|
+
super
|
35
|
+
end
|
36
|
+
end
|
37
|
+
|
38
|
+
def respond_to_missing?(method_name, include_private = false)
|
39
|
+
STACK_OPS.include?(method_name) || super
|
40
|
+
end
|
41
|
+
|
42
|
+
private
|
43
|
+
|
44
|
+
attr_reader :log_lines
|
45
|
+
|
46
|
+
end
|
47
|
+
|
48
|
+
end
|
49
|
+
end
|
@@ -0,0 +1,50 @@
|
|
1
|
+
require 'logger'
|
2
|
+
|
3
|
+
|
4
|
+
module Climatic
|
5
|
+
module Logger
|
6
|
+
|
7
|
+
module Manager
|
8
|
+
|
9
|
+
attr_reader :logger
|
10
|
+
|
11
|
+
def puts_and_logs(*args)
|
12
|
+
logger.puts_and_logs *args
|
13
|
+
end
|
14
|
+
|
15
|
+
def logger=(new_logger)
|
16
|
+
|
17
|
+
new_logger ||= DEVNULL_LOGGER
|
18
|
+
|
19
|
+
unless climatic_bootstrapped? or climatic_bootstrapping?
|
20
|
+
@user_defined_logger = new_logger
|
21
|
+
return
|
22
|
+
end
|
23
|
+
|
24
|
+
if climatic_bootstrapped?
|
25
|
+
new_logger.level = config[:'log-level'].nil? ? Climatic::Logger::Manager::DEFAULT_LOG_LEVEL : config[:'log-level']
|
26
|
+
end
|
27
|
+
|
28
|
+
new_logger.extend Climatic::Logger::Wrapper
|
29
|
+
|
30
|
+
if self.logger.respond_to? :transfer_content_to
|
31
|
+
self.logger.transfer_content_to new_logger
|
32
|
+
end
|
33
|
+
|
34
|
+
UltraCommandLine.logger = new_logger
|
35
|
+
@logger = new_logger
|
36
|
+
end
|
37
|
+
|
38
|
+
protected
|
39
|
+
|
40
|
+
attr_reader :user_defined_logger
|
41
|
+
|
42
|
+
private
|
43
|
+
|
44
|
+
DEFAULT_LOG_LEVEL = ::Logger::Severity::WARN
|
45
|
+
DEVNULL_LOGGER = UltraCommandLine::Utils::BasicLogger::NullLogger.new
|
46
|
+
|
47
|
+
end
|
48
|
+
|
49
|
+
end
|
50
|
+
end
|
@@ -0,0 +1,51 @@
|
|
1
|
+
require 'open3'
|
2
|
+
|
3
|
+
module Climatic
|
4
|
+
module Processes
|
5
|
+
|
6
|
+
class Base
|
7
|
+
|
8
|
+
include Climatic::Processes::Command
|
9
|
+
include Climatic::Processes::TimeManagement
|
10
|
+
|
11
|
+
attr_reader :process_state, :exit_status, :last_pid, :mode
|
12
|
+
attr_accessor :show_output, :log_output
|
13
|
+
|
14
|
+
def initialize(command = nil, mode = :synchronous)
|
15
|
+
self.command = command
|
16
|
+
self.process_state = :not_started
|
17
|
+
self.mode = mode
|
18
|
+
self.creation_time = Time.now
|
19
|
+
end
|
20
|
+
|
21
|
+
def mode=(mode)
|
22
|
+
mode_processor = Object.const_get "Climatic::Processes::#{mode.to_s.capitalize}"
|
23
|
+
self.extend mode_processor
|
24
|
+
@mode = mode.to_sym
|
25
|
+
rescue
|
26
|
+
raise "Invalid process mode '#{mode}'"
|
27
|
+
end
|
28
|
+
|
29
|
+
private
|
30
|
+
|
31
|
+
attr_writer :process_state, :exit_status, :last_pid
|
32
|
+
|
33
|
+
def report(message, to_stdout = true)
|
34
|
+
if show_output
|
35
|
+
to_stdout ? puts(message) : STDERR.puts(message)
|
36
|
+
end
|
37
|
+
if log_output
|
38
|
+
log_line = "[subprocess #{last_pid}] - #{message}"
|
39
|
+
if to_stdout
|
40
|
+
Climatic.logger.debug log_line
|
41
|
+
else
|
42
|
+
Climatic.logger.warn log_line
|
43
|
+
end
|
44
|
+
end
|
45
|
+
|
46
|
+
end
|
47
|
+
|
48
|
+
end
|
49
|
+
|
50
|
+
end
|
51
|
+
end
|
@@ -0,0 +1,51 @@
|
|
1
|
+
module Climatic
|
2
|
+
module Processes
|
3
|
+
|
4
|
+
module Synchronous
|
5
|
+
|
6
|
+
def execute
|
7
|
+
self.exit_status = nil
|
8
|
+
self.last_pid = nil
|
9
|
+
self.process_state = :running
|
10
|
+
self.start_time = Time.now
|
11
|
+
Open3.popen3(command) do |stdin, stdout, stderr, wait_thread|
|
12
|
+
stdin.close
|
13
|
+
self.last_pid = wait_thread.pid
|
14
|
+
begin
|
15
|
+
monitored_streams = [stdout, stderr]
|
16
|
+
loop do
|
17
|
+
begin
|
18
|
+
readables, writables = IO.select(monitored_streams)
|
19
|
+
writables.each(&:close)
|
20
|
+
readables.each do |io|
|
21
|
+
begin
|
22
|
+
buffer = ''
|
23
|
+
buffer << io.read_nonblock(1) while buffer[-1] != "\n"
|
24
|
+
report buffer, io == stdout
|
25
|
+
rescue IO::WaitReadable
|
26
|
+
next
|
27
|
+
rescue EOFError => e
|
28
|
+
monitored_streams.delete io
|
29
|
+
monitored_streams.empty? ? raise(e) : next
|
30
|
+
end
|
31
|
+
end
|
32
|
+
rescue EOFError
|
33
|
+
report "End of process #{wait_thread.value.pid}"
|
34
|
+
break
|
35
|
+
end
|
36
|
+
end
|
37
|
+
rescue Errno::EAGAIN
|
38
|
+
retry
|
39
|
+
end
|
40
|
+
self.exit_status = wait_thread.value
|
41
|
+
return self.exit_status
|
42
|
+
end
|
43
|
+
ensure
|
44
|
+
self.end_time = Time.now
|
45
|
+
self.process_state = :terminated
|
46
|
+
end
|
47
|
+
|
48
|
+
end
|
49
|
+
|
50
|
+
end
|
51
|
+
end
|
@@ -0,0 +1,21 @@
|
|
1
|
+
require 'open3'
|
2
|
+
|
3
|
+
module Climatic
|
4
|
+
module Processes
|
5
|
+
|
6
|
+
module TimeManagement
|
7
|
+
|
8
|
+
attr_reader :creation_time, :start_time, :end_time
|
9
|
+
|
10
|
+
def duration
|
11
|
+
end_time - start_time
|
12
|
+
end
|
13
|
+
|
14
|
+
private
|
15
|
+
|
16
|
+
attr_writer :creation_time, :start_time, :end_time
|
17
|
+
|
18
|
+
end
|
19
|
+
|
20
|
+
end
|
21
|
+
end
|
@@ -0,0 +1,27 @@
|
|
1
|
+
module Climatic
|
2
|
+
|
3
|
+
module Proxy
|
4
|
+
|
5
|
+
def config
|
6
|
+
Climatic.config
|
7
|
+
end
|
8
|
+
|
9
|
+
def logger
|
10
|
+
Climatic.logger
|
11
|
+
end
|
12
|
+
|
13
|
+
def command_line_manager
|
14
|
+
config.command_line_layer.command_line_manager
|
15
|
+
end
|
16
|
+
|
17
|
+
def help
|
18
|
+
config.command_line_layer.help
|
19
|
+
end
|
20
|
+
|
21
|
+
def puts_and_logs(*args)
|
22
|
+
Climatic.logger.puts_and_logs *args
|
23
|
+
end
|
24
|
+
|
25
|
+
end
|
26
|
+
|
27
|
+
end
|
@@ -0,0 +1,65 @@
|
|
1
|
+
module Climatic
|
2
|
+
module Script
|
3
|
+
|
4
|
+
module Base
|
5
|
+
|
6
|
+
include Climatic::Utils::ScriptHelper
|
7
|
+
|
8
|
+
module ClassMethods
|
9
|
+
|
10
|
+
def start
|
11
|
+
script = new
|
12
|
+
script.run
|
13
|
+
end
|
14
|
+
|
15
|
+
end
|
16
|
+
|
17
|
+
def run
|
18
|
+
# logging startup configuration
|
19
|
+
Climatic.config.command_line_layer.cmd_line_args = ARGV.dup
|
20
|
+
Climatic.logger.debug "Config layers ->\n#{Climatic.config.detailed_layers_info}"
|
21
|
+
Climatic.logger.debug "Merged config -> #{Climatic.config[].to_yaml}"
|
22
|
+
# Displaying (and exiting) command line help
|
23
|
+
display_help_and_exit if Climatic.config[:help]
|
24
|
+
check_config
|
25
|
+
Climatic.logger.info 'Application is starting...'
|
26
|
+
do_process
|
27
|
+
Climatic.logger.info 'Application ended normally...'
|
28
|
+
rescue => e
|
29
|
+
display_exit_error e
|
30
|
+
exit_code = e.respond_to?(:exit_code) ? e.exit_code : 1
|
31
|
+
exit exit_code
|
32
|
+
ensure
|
33
|
+
Climatic.logger.info 'Exiting...'
|
34
|
+
end
|
35
|
+
|
36
|
+
def self.included(base)
|
37
|
+
base.extend ClassMethods
|
38
|
+
end
|
39
|
+
|
40
|
+
private
|
41
|
+
|
42
|
+
def display_help_and_exit
|
43
|
+
puts Climatic.config.command_line_help
|
44
|
+
exit 0
|
45
|
+
end
|
46
|
+
|
47
|
+
def do_process
|
48
|
+
cmd_line_mngr.processor.execute
|
49
|
+
end
|
50
|
+
|
51
|
+
def cmd_line_mngr
|
52
|
+
Climatic.config.command_line_layer.command_line_manager
|
53
|
+
end
|
54
|
+
|
55
|
+
def check_config
|
56
|
+
# Check options validity in terms of dependencies
|
57
|
+
cmd_line_mngr.command.valid? raise_error: true
|
58
|
+
# Delegates to the processor the functional checks of the config
|
59
|
+
cmd_line_mngr.processor.check_params cmd_line_mngr.cmd_line_args_for_command(cmd_line_mngr.command)
|
60
|
+
end
|
61
|
+
|
62
|
+
end
|
63
|
+
|
64
|
+
end
|
65
|
+
end
|
@@ -0,0 +1,31 @@
|
|
1
|
+
module Climatic
|
2
|
+
|
3
|
+
module Script
|
4
|
+
|
5
|
+
class Simple
|
6
|
+
|
7
|
+
include Climatic::Script::UnimplementedProcessor
|
8
|
+
include Climatic::Script::Base
|
9
|
+
|
10
|
+
def initialize
|
11
|
+
register_processor
|
12
|
+
end
|
13
|
+
|
14
|
+
def register_processor(commands = cmd_line_mngr.commands, processor = self)
|
15
|
+
commands = [commands] unless commands.is_a? Array
|
16
|
+
commands.each do |command|
|
17
|
+
cmd_line_mngr.register_processor command, processor
|
18
|
+
end
|
19
|
+
end
|
20
|
+
|
21
|
+
private
|
22
|
+
|
23
|
+
def cmd_line_mngr
|
24
|
+
Climatic.config.command_line_layer.command_line_manager
|
25
|
+
end
|
26
|
+
|
27
|
+
end
|
28
|
+
|
29
|
+
end
|
30
|
+
end
|
31
|
+
|
@@ -0,0 +1,19 @@
|
|
1
|
+
module Climatic
|
2
|
+
|
3
|
+
module Script
|
4
|
+
|
5
|
+
module UnimplementedProcessor
|
6
|
+
|
7
|
+
def check_params(command_args)
|
8
|
+
Climatic.logger.debug Climatic.config[].inspect
|
9
|
+
true
|
10
|
+
end
|
11
|
+
|
12
|
+
def execute
|
13
|
+
raise Climatic::Error, 'Not yet implemented !'
|
14
|
+
end
|
15
|
+
|
16
|
+
end
|
17
|
+
|
18
|
+
end
|
19
|
+
end
|
@@ -0,0 +1,65 @@
|
|
1
|
+
module Climatic
|
2
|
+
module Utils
|
3
|
+
|
4
|
+
module Input
|
5
|
+
|
6
|
+
DEFAULT_CONFIRMATION_CHOICES = {
|
7
|
+
true => %w(Yes y),
|
8
|
+
false => %w(No n)
|
9
|
+
}
|
10
|
+
|
11
|
+
def get_user_confirmation(choices: DEFAULT_CONFIRMATION_CHOICES,
|
12
|
+
default_choice: 'No',
|
13
|
+
prompt: 'Are you sure ?',
|
14
|
+
strict: false)
|
15
|
+
|
16
|
+
raise Climatic::Error, 'Invalid choices !' unless choices.is_a? Hash
|
17
|
+
values = choices.values.flatten
|
18
|
+
raise Climatic::Error, "Invalid default choice '#{default_choice}' !" unless values.include? default_choice
|
19
|
+
if Climatic.config[:auto]
|
20
|
+
yield if block_given?
|
21
|
+
return true
|
22
|
+
end
|
23
|
+
full_prompt = '%s (%s): ' % [prompt, choices_string(values, default_choice)]
|
24
|
+
STDOUT.print full_prompt
|
25
|
+
STDOUT.flush
|
26
|
+
input = nil
|
27
|
+
until values.include? input
|
28
|
+
input = STDIN.gets.chomp
|
29
|
+
input = default_choice if input.nil? || input.empty?
|
30
|
+
unless strict
|
31
|
+
input = default_choice unless values.include? input
|
32
|
+
end
|
33
|
+
end
|
34
|
+
choices.each_pair do |res, possible_choices|
|
35
|
+
if possible_choices.include? input
|
36
|
+
if res and block_given?
|
37
|
+
yield
|
38
|
+
end
|
39
|
+
return res
|
40
|
+
end
|
41
|
+
end
|
42
|
+
raise 'Something wrong happened !'
|
43
|
+
end
|
44
|
+
|
45
|
+
|
46
|
+
def get_user_input(prompt, default=nil)
|
47
|
+
full_prompt = (default.nil? or default.empty?) ? "#{prompt}: " : "#{prompt} (default: #{default}): "
|
48
|
+
STDOUT.print full_prompt
|
49
|
+
STDOUT.flush
|
50
|
+
STDIN.gets.chomp
|
51
|
+
end
|
52
|
+
|
53
|
+
private
|
54
|
+
|
55
|
+
|
56
|
+
def choices_string(choices, default_choice, highlight= %w([ ]))
|
57
|
+
choices
|
58
|
+
.map { |choice| choice == default_choice ? "#{highlight.first}#{choice}#{highlight.last}" : choice }
|
59
|
+
.join '/'
|
60
|
+
end
|
61
|
+
|
62
|
+
end
|
63
|
+
|
64
|
+
end
|
65
|
+
end
|
@@ -0,0 +1,28 @@
|
|
1
|
+
module Climatic
|
2
|
+
module Utils
|
3
|
+
|
4
|
+
module SafeExec
|
5
|
+
|
6
|
+
def safely_exec_code(*args, message: nil, &block)
|
7
|
+
if self.config[:simulate]
|
8
|
+
Climatic.logger.puts_and_logs "[SIMULATION MODE]: #{message}" unless message.nil?
|
9
|
+
else
|
10
|
+
Climatic.logger.puts_and_logs message
|
11
|
+
block.call *args
|
12
|
+
end
|
13
|
+
end
|
14
|
+
|
15
|
+
def safely_exec_command(command, message: nil, show_output: false, log_output: true)
|
16
|
+
safely_exec_code command, message: message do |cmd|
|
17
|
+
process = Climatic::Processes::Base.new cmd
|
18
|
+
process.show_output = show_output
|
19
|
+
process.log_output = log_output
|
20
|
+
process.execute
|
21
|
+
process
|
22
|
+
end
|
23
|
+
end
|
24
|
+
|
25
|
+
end
|
26
|
+
|
27
|
+
end
|
28
|
+
end
|
@@ -0,0 +1,18 @@
|
|
1
|
+
module Climatic
|
2
|
+
module Utils
|
3
|
+
|
4
|
+
module ScriptHelper
|
5
|
+
|
6
|
+
def display_exit_error(e)
|
7
|
+
puts "Program aborted with message: '#{e.message}'."
|
8
|
+
if Climatic.config[:debug]
|
9
|
+
Climatic.logger.fatal "#{e.message}\nBacktrace:\n#{e.backtrace.join("\n\t")}"
|
10
|
+
else
|
11
|
+
puts ' Use --debug option for more detail (see --help).'
|
12
|
+
end
|
13
|
+
end
|
14
|
+
|
15
|
+
end
|
16
|
+
|
17
|
+
end
|
18
|
+
end
|