inprovise 0.2.2

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.
Files changed (56) hide show
  1. checksums.yaml +15 -0
  2. data/.gitignore +4 -0
  3. data/.travis.yml +28 -0
  4. data/Gemfile +9 -0
  5. data/LICENSE +8 -0
  6. data/README.md +197 -0
  7. data/Rakefile.rb +9 -0
  8. data/bin/rig +5 -0
  9. data/inprovise.gemspec +22 -0
  10. data/lib/inprovise/channel/ssh.rb +202 -0
  11. data/lib/inprovise/cli/group.rb +86 -0
  12. data/lib/inprovise/cli/node.rb +95 -0
  13. data/lib/inprovise/cli/provision.rb +84 -0
  14. data/lib/inprovise/cli.rb +105 -0
  15. data/lib/inprovise/cmd_channel.rb +100 -0
  16. data/lib/inprovise/cmd_helper.rb +150 -0
  17. data/lib/inprovise/control.rb +326 -0
  18. data/lib/inprovise/execution_context.rb +277 -0
  19. data/lib/inprovise/group.rb +67 -0
  20. data/lib/inprovise/helper/cygwin.rb +43 -0
  21. data/lib/inprovise/helper/linux.rb +181 -0
  22. data/lib/inprovise/helper/windows.rb +123 -0
  23. data/lib/inprovise/infra.rb +122 -0
  24. data/lib/inprovise/local_file.rb +120 -0
  25. data/lib/inprovise/logger.rb +79 -0
  26. data/lib/inprovise/node.rb +271 -0
  27. data/lib/inprovise/remote_file.rb +128 -0
  28. data/lib/inprovise/resolver.rb +36 -0
  29. data/lib/inprovise/script.rb +175 -0
  30. data/lib/inprovise/script_index.rb +46 -0
  31. data/lib/inprovise/script_runner.rb +110 -0
  32. data/lib/inprovise/sniff.rb +46 -0
  33. data/lib/inprovise/sniffer/linux.rb +64 -0
  34. data/lib/inprovise/sniffer/platform.rb +46 -0
  35. data/lib/inprovise/sniffer/unknown.rb +11 -0
  36. data/lib/inprovise/sniffer/windows.rb +32 -0
  37. data/lib/inprovise/template/inprovise.rb.erb +92 -0
  38. data/lib/inprovise/template.rb +38 -0
  39. data/lib/inprovise/trigger_runner.rb +36 -0
  40. data/lib/inprovise/version.rb +10 -0
  41. data/lib/inprovise.rb +145 -0
  42. data/test/cli_test.rb +314 -0
  43. data/test/cli_test_helper.rb +19 -0
  44. data/test/dsl_test.rb +43 -0
  45. data/test/fixtures/example.txt +1 -0
  46. data/test/fixtures/include.rb +4 -0
  47. data/test/fixtures/inprovise.rb +1 -0
  48. data/test/fixtures/myscheme.rb +1 -0
  49. data/test/infra_test.rb +189 -0
  50. data/test/local_file_test.rb +64 -0
  51. data/test/remote_file_test.rb +106 -0
  52. data/test/resolver_test.rb +66 -0
  53. data/test/script_index_test.rb +53 -0
  54. data/test/script_test.rb +56 -0
  55. data/test/test_helper.rb +237 -0
  56. metadata +182 -0
@@ -0,0 +1,110 @@
1
+ # Script runner for Inprovise
2
+ #
3
+ # Author:: Martin Corino
4
+ # License:: Distributes under the same license as Ruby
5
+
6
+ class Inprovise::ScriptRunner
7
+ COMMANDS = {apply: %w{Applying to}, revert: %w(Reverting on), validate: %w(Validating on)}
8
+
9
+ def initialize(node, script, skip_dependencies=false)
10
+ @node = node
11
+ @script = script
12
+ @index = Inprovise::ScriptIndex.default
13
+ @perform = true
14
+ @skip_dependencies = skip_dependencies
15
+ @log = Inprovise::Logger.new(@node, script)
16
+ end
17
+
18
+ def set_index(index)
19
+ @index = index
20
+ end
21
+
22
+ def script
23
+ Inprovise::Script === @script ? @script : @index.get(@script)
24
+ end
25
+
26
+ def scripts
27
+ return [script] if @skip_dependencies
28
+ resolver = Inprovise::Resolver.new(script, @index)
29
+ resolver.resolve
30
+ resolver.scripts
31
+ end
32
+
33
+ def execute(command_name, config=nil)
34
+ Inprovise.log.local("#{COMMANDS[command_name].first} #{script.name} #{COMMANDS[command_name].last} #{@node.to_s}")
35
+ scrs = scripts
36
+ scrs.reverse! if command_name.to_sym == :revert
37
+ @log.say scrs.map(&:name).join(', ').yellow if Inprovise.verbosity > 0
38
+ context = @perform ? Inprovise::ExecutionContext.new(@node, @log, @index, config) : Inprovise::MockExecutionContext.new(@node, @log, @index, config)
39
+ context.config.command = command_name
40
+ scrs.each { |script| script.merge_configuration(context.config) }
41
+ scrs.each do |script|
42
+ send(:"execute_#{command_name}", script, context)
43
+ end
44
+ end
45
+
46
+ def demonstrate(command_name, config=nil)
47
+ @perform = false
48
+ execute(command_name, config)
49
+ @perform = true
50
+ end
51
+
52
+ def execute_apply(script, context)
53
+ return unless should_run?(script, :apply, context)
54
+ exec(script, :apply, context)
55
+ validate!(script, context)
56
+ end
57
+
58
+ def execute_revert(script, context)
59
+ return unless should_run?(script, :revert, context)
60
+ exec(script, :revert, context)
61
+ end
62
+
63
+ def execute_validate(script, context)
64
+ validate!(script, context)
65
+ end
66
+
67
+ def should_run?(script, command_name, context)
68
+ return false unless script.provides_command?(command_name)
69
+ return true unless @perform
70
+ return true unless command_name == :apply || command_name == :revert
71
+ return true unless script.provides_command?(:validate)
72
+ is_present = is_valid?(script, context)
73
+ return !is_present if command_name == :apply
74
+ is_present
75
+ end
76
+
77
+ def validate!(script, context)
78
+ return true unless @perform
79
+ return unless script.provides_command?(:validate)
80
+ return if is_valid?(script, context)
81
+ raise ValidationFailureError.new(@node, script)
82
+ end
83
+
84
+ def is_valid?(script, context)
85
+ results = exec(script, :validate, context)
86
+ rc = results.all?
87
+ context.log.command("validate -> #{rc}") if Inprovise.verbosity > 0
88
+ rc
89
+ end
90
+
91
+ def exec(script, command_name, context)
92
+ cmds = script.command(command_name)
93
+ context = context.for_user(script.user) if script.user
94
+ context.log.set_task(script)
95
+ context.log.command(command_name)
96
+ context.script = script
97
+ cmds.map {|cmd| context.exec(cmd) }
98
+ end
99
+
100
+ class ValidationFailureError < StandardError
101
+ def initialize(node, script)
102
+ @node = node
103
+ @script = script
104
+ end
105
+
106
+ def message
107
+ "Script #{@script.name} failed validation on #{@node.to_s}"
108
+ end
109
+ end
110
+ end
@@ -0,0 +1,46 @@
1
+ # Sniffer main module for Inprovise
2
+ #
3
+ # Author:: Martin Corino
4
+ # License:: Distributes under the same license as Ruby
5
+
6
+ module Inprovise::Sniffer
7
+
8
+ ROOT_SCRIPT = 'sniffers'
9
+
10
+ class << self
11
+
12
+ def sniffers
13
+ @sniffers ||= Inprovise::ScriptIndex.new('sniffers')
14
+ end
15
+
16
+ def add_sniffer(name, &definition)
17
+ Inprovise.log.local("Adding sniffer script #{name}") if Inprovise.verbosity > 2
18
+ script = Inprovise::Script.new(name)
19
+ Inprovise::Script::DSL.new(script).instance_eval(&definition) if block_given?
20
+ sniffers.add(script)
21
+ script
22
+ end
23
+ private :add_sniffer
24
+
25
+ def define(name, auto_trigger=true, &definition)
26
+ script = add_sniffer("sniff[#{name}]", &definition)
27
+ sniffers.get(ROOT_SCRIPT).triggers(script.name) if auto_trigger
28
+ script
29
+ end
30
+
31
+ def run_sniffers_for(node)
32
+ node.config[:attributes] ||= {}
33
+ runner = Inprovise::ScriptRunner.new(node, 'sniffers')
34
+ runner.set_index(@sniffers)
35
+ runner.execute(:apply)
36
+ end
37
+
38
+ end
39
+
40
+ # add root sniffer script
41
+ # (doesn't do anything by itself except provide a container triggering all specific sniffers)
42
+ add_sniffer(ROOT_SCRIPT)
43
+
44
+ end
45
+
46
+ require_relative './sniffer/platform.rb'
@@ -0,0 +1,64 @@
1
+ # Linux platform sniffer for Inprovise
2
+ #
3
+ # Author:: Martin Corino
4
+ # License:: Distributes under the same license as Ruby
5
+
6
+ Inprovise::Sniffer.define('linux', false) do
7
+
8
+ action('main') do |attrs|
9
+ attrs[:machine] = run('uname -m').chomp
10
+ if remote('/etc/os-release').exists?
11
+ trigger 'sniff[linux]:os-release', attrs
12
+ elsif remote('/etc/redhat-release').exists?
13
+ trigger 'sniff[linux]:redhat-release', attrs
14
+ elsif remote('/etc/SuSE-release').exists?
15
+ trigger 'sniff[linux]:suse-release', attrs
16
+ end
17
+ attrs[:pkgman] = case attrs[:os_distro]
18
+ when 'fedora', 'centos', 'rhel'
19
+ binary_exists?('dnf') ? 'dnf' : 'yum'
20
+ when /suse/
21
+ 'zypper'
22
+ end
23
+ end
24
+
25
+ action('os-release') do |attrs|
26
+ data = remote('/etc/os-release').content.split("\n").collect {|l| l.strip }
27
+ vars = data.inject({}) do |hash, line|
28
+ unless line.empty? || line.start_with?('#') || !(line =~ /[^=]+=.*/)
29
+ var, val = line.split('=')
30
+ hash[var] = val.strip.gsub(/(\A")|("\Z)/, '')
31
+ end
32
+ hash
33
+ end
34
+ attrs[:os_distro] = vars['ID'].downcase
35
+ attrs[:os_version] = vars['VERSION_ID']
36
+ if attrs[:os_distro] == 'centos' && remote('/etc/centos-release').exists?
37
+ data = remote('/etc/centos-release').content.split("\n").collect {|l| l.strip }
38
+ data.each do |line|
39
+ if line =~ /\s+release\s+(\d+)\.(\d+).*/
40
+ attrs[:os_version] = "#{$1}.#{$2}"
41
+ end
42
+ end
43
+ end
44
+ end
45
+
46
+ action('redhat-release') do |attrs|
47
+ data = remote('/etc/redhat-release').content.split("\n").collect {|l| l.strip }
48
+ data.each do |line|
49
+ if line =~ /\A(.+)\s+release\s+(\d+)(\.(\d+))?/
50
+ attrs[:os_version] = "#{$2}.#{$4 || '0'}"
51
+ tmpos = $1.strip.downcase
52
+ attrs[:os_distro] = case tmpos
53
+ when /fedora/
54
+ 'fedora'
55
+ when /red\s+hat/
56
+ 'rhel'
57
+ when /centos/
58
+ 'centos'
59
+ end
60
+ end
61
+ end
62
+ end
63
+
64
+ end
@@ -0,0 +1,46 @@
1
+ # Platform sniffer for Inprovise
2
+ #
3
+ # Author:: Martin Corino
4
+ # License:: Distributes under the same license as Ruby
5
+
6
+ Inprovise::Sniffer.define('platform') do
7
+
8
+ action('helper') do |attrs|
9
+ # determin the best CmdHelper if not user defined
10
+ attrs[:helper] = case attrs[:os]
11
+ when 'linux'
12
+ 'linux'
13
+ when 'windows'
14
+ # check for Cygwin environment
15
+ ostype = node.channel.run('echo $OSTYPE').strip
16
+ # configure the Linux command helper here first;
17
+ # this way we can use the full context functionality from now on
18
+ node.config[:helper] = (/cygwin/i =~ ostype ? 'cygwin' : 'windows')
19
+ end unless attrs[:helper]
20
+ end
21
+
22
+ apply do
23
+ attrs = {}
24
+ os = node.channel.run('echo %OS%').chomp
25
+ os = node.channel.run('echo $OS').chomp if os == '%OS%'
26
+ os = node.channel.run('uname -o').chomp if os.empty?
27
+ attrs[:os] = case os
28
+ when /windows/i
29
+ 'windows'
30
+ when /linux/i
31
+ 'linux'
32
+ else
33
+ 'unknown'
34
+ end
35
+ # determin and initialize helper
36
+ trigger 'sniff[platform]:helper', attrs
37
+ # detect detailed platform props
38
+ trigger "sniff[#{attrs[:os]}]:main", attrs
39
+ (node.config[:attributes][:platform] ||= {}).merge!(attrs)
40
+ end
41
+
42
+ end
43
+
44
+ require_relative './windows.rb'
45
+ require_relative './linux.rb'
46
+ require_relative './unknown.rb'
@@ -0,0 +1,11 @@
1
+ # Unknown platform sniffer for Inprovise
2
+ #
3
+ # Author:: Martin Corino
4
+ # License:: Distributes under the same license as Ruby
5
+
6
+ Inprovise::Sniffer.define('unknown', false) do
7
+
8
+ action('main') do |attrs|
9
+ end
10
+
11
+ end
@@ -0,0 +1,32 @@
1
+ # Windows platform sniffer for Inprovise
2
+ #
3
+ # Author:: Martin Corino
4
+ # License:: Distributes under the same license as Ruby
5
+
6
+ Inprovise::Sniffer.define('windows', false) do
7
+
8
+ action('main') do |attrs|
9
+ attrs[:machine] = env('PROCESSOR_ARCHITECTURE').chomp =~ /amd64/i ? 'x86_64' : 'x86'
10
+ osver = run('cmd /c ver').strip
11
+ if /\[version\s+(\d+)\.(\d+)\.(\d+)\]/i =~ osver
12
+ attrs[:os_version] = case $1
13
+ when '5'
14
+ 'xp'
15
+ when '6'
16
+ case $2
17
+ when '1'
18
+ '7'
19
+ when '2'
20
+ '8'
21
+ when '3'
22
+ '8.1'
23
+ end
24
+ when '10'
25
+ '10'
26
+ else
27
+ $1
28
+ end
29
+ end
30
+ end
31
+
32
+ end
@@ -0,0 +1,92 @@
1
+ # Scheme template for Inprovise
2
+ #
3
+ # Author:: Martin Corino
4
+ # License:: Distributes under the same license as Ruby
5
+
6
+ # include 'another_scheme.rb'
7
+
8
+ # script 'script' do
9
+ #
10
+ # description 'description'
11
+ #
12
+ # configuration <data>
13
+ #
14
+ # action('action1') { }
15
+ # action('action2') { }
16
+ #
17
+ # apply do
18
+ #
19
+ # end
20
+ #
21
+ # revert do
22
+ #
23
+ # end
24
+ #
25
+ # validate do
26
+ #
27
+ # end
28
+ # end
29
+ #
30
+ #
31
+ # All blocks (action,apply,revert,validate,file props,file block) execute in a special context providing the
32
+ # following methods:
33
+ #
34
+ # node current node
35
+ #
36
+ # config current (consolidated, transient) config
37
+ #
38
+ # as 'user' do ... end creates a nested execution context where all remote commands
39
+ # will be executed for the given user
40
+ #
41
+ # in_dir 'path' do ... end creates a nested execution context where all remote commands
42
+ # will be executed using the given path as working directory
43
+ #
44
+ # trigger 'script:action'[,*args] runs specified action code blocks
45
+ #
46
+ # run 'command'[, {}] execute command on current node over SSH connection
47
+ # options:
48
+ # :once => true
49
+ # run command only once (from whatever script executes it first)
50
+ # :log => true
51
+ # force logging SSH commands and output
52
+ #
53
+ # run_local 'command' execute command locally
54
+ #
55
+ # log 'msg' log a message
56
+ #
57
+ # sudo 'command'[, {}] execute command on current node over SSH connection using 'sudo'
58
+ # options: see 'run'
59
+ #
60
+ # env 'var' returns value of environment variable on current node
61
+ #
62
+ # upload '/from/local/path', '/to/remote/path' up-/download files using SFTP connection for current node
63
+ # download '/from/remote/path', '/to/local/path'
64
+ #
65
+ # local('/local/path') creates a local/remote file object providing the following
66
+ # remote('/remote/path') methods:
67
+ # .hash returns an SHA1 hash as hex string
68
+ # .exists?
69
+ # .file?
70
+ # .directory?
71
+ # .content
72
+ # .matches?(other_file)
73
+ # .copy_to(dest_file)
74
+ # .copy_from(src_file)
75
+ # .delete!
76
+ # .permissions
77
+ # .set_permissions
78
+ # .user
79
+ # .group
80
+ # .set_owner('user'[,'group'])
81
+ # .is_local?
82
+ #
83
+ # mkdir '/remote/path' create directory(-ies) on current node
84
+ #
85
+ # binary_exists?('bin-name')
86
+ #
87
+ # template('/local/file') creates a template object for the specified (ERB) template file
88
+ # providing 2 rendering options
89
+ # .render(locals ={}) returns rendered result string
90
+ # .render_to_tempfile(locals = {}) returns path of tempfile containing rendered result
91
+ #
92
+
@@ -0,0 +1,38 @@
1
+ # Template support for Inprovise
2
+ #
3
+ # Author:: Martin Corino
4
+ # License:: Distributes under the same license as Ruby
5
+
6
+ require 'erb'
7
+ require 'tilt'
8
+ require 'tempfile'
9
+
10
+ class Inprovise::Template
11
+ def initialize(path, context = nil)
12
+ @context = context || Object.new
13
+ @path = resolve(path)
14
+ @template = @path.respond_to?(:call) ? Tilt['erb'].new(&@path) : Tilt.new(@path)
15
+ end
16
+
17
+ def render(locals={})
18
+ @template.render(@context, locals)
19
+ end
20
+
21
+ def render_to_tempfile(locals={})
22
+ basename = @path.respond_to?(:call) ? 'inprovise-inline-tpl' : File.basename(@path).gsub('.', '-')
23
+ file = Tempfile.new(basename)
24
+ file.write render(locals)
25
+ file.close
26
+ file.path
27
+ end
28
+
29
+ private
30
+
31
+ def resolve(path)
32
+ if path.respond_to?(:call) || path =~ /^\//
33
+ path
34
+ else
35
+ File.join(Inprovise.root, path)
36
+ end
37
+ end
38
+ end
@@ -0,0 +1,36 @@
1
+ # Trigger runner for Inprovise
2
+ #
3
+ # Author:: Martin Corino
4
+ # License:: Distributes under the same license as Ruby
5
+
6
+ class Inprovise::TriggerRunner
7
+ def initialize(node, action_ref_with_args)
8
+ @node = node
9
+ @action_ref, @args = *parse_action_ref(action_ref_with_args)
10
+ @log = Inprovise::Logger.new(@node, @action_ref)
11
+ @index = Inprovise::ScriptIndex.default
12
+ end
13
+
14
+ def set_index(index)
15
+ @index = index
16
+ end
17
+
18
+ def execute(_, config=nil)
19
+ Inprovise.log.local("Triggering #{@action_ref} for #{@node.to_s}")
20
+ Inprovise::ExecutionContext.new(@node, @log, @index, config).trigger(@action_ref, *@args)
21
+ end
22
+
23
+ def demonstrate(_, config=nil)
24
+ Inprovise::MockExecutionContext.new(@node, @log, @index, config).trigger(@action_ref, *@args)
25
+ end
26
+
27
+ private
28
+
29
+ def parse_action_ref(action_ref_with_args)
30
+ matches = action_ref_with_args.match(/([\w\-\:]+?)(\[([\w\-\,]+?)\])/)
31
+ return [action_ref_with_args,[]] unless matches
32
+ action_ref = matches[1]
33
+ args = matches[3].split(',').map(&:strip)
34
+ [action_ref, args]
35
+ end
36
+ end
@@ -0,0 +1,10 @@
1
+ # Version definition for Inprovise
2
+ #
3
+ # Author:: Martin Corino
4
+ # License:: Distributes under the same license as Ruby
5
+
6
+ module Inprovise
7
+
8
+ VERSION = '0.2.2'
9
+
10
+ end
data/lib/inprovise.rb ADDED
@@ -0,0 +1,145 @@
1
+ # Main loader for Inprovise
2
+ #
3
+ # Author:: Martin Corino
4
+ # License:: Distributes under the same license as Ruby
5
+
6
+ require 'rubygems'
7
+ require 'colored'
8
+
9
+ module Inprovise
10
+
11
+ INFRA_FILE = 'infra.json'
12
+ RC_FILE = 'rigrc'
13
+ DEFAULT_SCHEME = 'inprovise.rb'
14
+
15
+ class << self
16
+ def verbosity
17
+ @verbose ||= 0
18
+ end
19
+
20
+ def verbosity=(val)
21
+ @verbose = val.to_i
22
+ end
23
+
24
+ def show_backtrace
25
+ @show_backtrace ||= false
26
+ end
27
+
28
+ def show_backtrace=(f)
29
+ @show_backtrace = (f == true)
30
+ end
31
+
32
+ def sequential
33
+ @sequential ||= false
34
+ end
35
+
36
+ def sequential=(f)
37
+ @sequential = (f == true)
38
+ end
39
+
40
+ def demonstrate
41
+ @demonstrate ||= false
42
+ end
43
+
44
+ def demonstrate=(f)
45
+ @demonstrate = (f == true)
46
+ end
47
+
48
+ def skip_dependencies
49
+ @skip_dependencies ||= false
50
+ end
51
+
52
+ def skip_dependencies=(f)
53
+ @skip_dependencies = (f == true)
54
+ end
55
+
56
+ def infra
57
+ @infra ||= (ENV['INPROVISE_INFRA'] || find_infra)
58
+ end
59
+
60
+ def root
61
+ @root ||= File.dirname(infra)
62
+ end
63
+
64
+ def default_scheme
65
+ ENV['INPROVISE_SCHEME'] || Inprovise::DEFAULT_SCHEME
66
+ end
67
+
68
+ def schemes
69
+ @schemes ||= []
70
+ end
71
+
72
+ def loaded?(scheme)
73
+ schemes.include?(File.expand_path(scheme, root))
74
+ end
75
+
76
+ def log
77
+ @log ||= Inprovise::Logger.new('Local', 'cli')
78
+ end
79
+
80
+ def add_script(script)
81
+ yield(script) if block_given?
82
+ Inprovise::ScriptIndex.default.add(script)
83
+ script
84
+ end
85
+
86
+ private
87
+
88
+ def find_infra
89
+ curpath = File.expand_path('.')
90
+ begin
91
+ # check if this is where the infra file lives
92
+ if File.file?(File.join(curpath, Inprovise::INFRA_FILE))
93
+ return File.join(curpath, Inprovise::INFRA_FILE)
94
+ end
95
+ # not found yet, move one dir up until we reach the root
96
+ curpath = File.expand_path(File.join(curpath, '..'))
97
+ end while !(curpath =~ /^(#{File::SEPARATOR}|.:#{File::SEPARATOR})$/)
98
+ INFRA_FILE
99
+ end
100
+ end
101
+
102
+ module DSL
103
+
104
+ def self.singleton_class
105
+ class << self; self; end
106
+ end unless self.respond_to?(:singleton_class)
107
+
108
+ singleton_class.class_eval do
109
+ def dsl_define(*args, &block)
110
+ Inprovise::DSL.singleton_class.class_eval(*args, &block)
111
+ end
112
+ end
113
+
114
+ dsl_define do
115
+ def include(path)
116
+ path = File.expand_path(path, Inprovise.root)
117
+ unless Inprovise.schemes.include?(path)
118
+ Inprovise.schemes << path
119
+ Inprovise.log.local("Loading provisioning scheme #{path}") if Inprovise.verbosity > 0
120
+ Inprovise::DSL.module_eval(File.read(path), path)
121
+ end
122
+ end
123
+ end
124
+
125
+ end
126
+
127
+ end
128
+
129
+ require_relative './inprovise/version'
130
+ require_relative './inprovise/logger'
131
+ require_relative './inprovise/cmd_channel'
132
+ require_relative './inprovise/cmd_helper'
133
+ require_relative './inprovise/script'
134
+ require_relative './inprovise/script_index'
135
+ require_relative './inprovise/local_file'
136
+ require_relative './inprovise/remote_file'
137
+ require_relative './inprovise/script_runner'
138
+ require_relative './inprovise/trigger_runner'
139
+ require_relative './inprovise/resolver'
140
+ require_relative './inprovise/template'
141
+ require_relative './inprovise/execution_context'
142
+ require_relative './inprovise/infra'
143
+ require_relative './inprovise/sniff'
144
+ require_relative './inprovise/control'
145
+ require_relative './inprovise/cli'