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.
- checksums.yaml +15 -0
- data/.gitignore +4 -0
- data/.travis.yml +28 -0
- data/Gemfile +9 -0
- data/LICENSE +8 -0
- data/README.md +197 -0
- data/Rakefile.rb +9 -0
- data/bin/rig +5 -0
- data/inprovise.gemspec +22 -0
- data/lib/inprovise/channel/ssh.rb +202 -0
- data/lib/inprovise/cli/group.rb +86 -0
- data/lib/inprovise/cli/node.rb +95 -0
- data/lib/inprovise/cli/provision.rb +84 -0
- data/lib/inprovise/cli.rb +105 -0
- data/lib/inprovise/cmd_channel.rb +100 -0
- data/lib/inprovise/cmd_helper.rb +150 -0
- data/lib/inprovise/control.rb +326 -0
- data/lib/inprovise/execution_context.rb +277 -0
- data/lib/inprovise/group.rb +67 -0
- data/lib/inprovise/helper/cygwin.rb +43 -0
- data/lib/inprovise/helper/linux.rb +181 -0
- data/lib/inprovise/helper/windows.rb +123 -0
- data/lib/inprovise/infra.rb +122 -0
- data/lib/inprovise/local_file.rb +120 -0
- data/lib/inprovise/logger.rb +79 -0
- data/lib/inprovise/node.rb +271 -0
- data/lib/inprovise/remote_file.rb +128 -0
- data/lib/inprovise/resolver.rb +36 -0
- data/lib/inprovise/script.rb +175 -0
- data/lib/inprovise/script_index.rb +46 -0
- data/lib/inprovise/script_runner.rb +110 -0
- data/lib/inprovise/sniff.rb +46 -0
- data/lib/inprovise/sniffer/linux.rb +64 -0
- data/lib/inprovise/sniffer/platform.rb +46 -0
- data/lib/inprovise/sniffer/unknown.rb +11 -0
- data/lib/inprovise/sniffer/windows.rb +32 -0
- data/lib/inprovise/template/inprovise.rb.erb +92 -0
- data/lib/inprovise/template.rb +38 -0
- data/lib/inprovise/trigger_runner.rb +36 -0
- data/lib/inprovise/version.rb +10 -0
- data/lib/inprovise.rb +145 -0
- data/test/cli_test.rb +314 -0
- data/test/cli_test_helper.rb +19 -0
- data/test/dsl_test.rb +43 -0
- data/test/fixtures/example.txt +1 -0
- data/test/fixtures/include.rb +4 -0
- data/test/fixtures/inprovise.rb +1 -0
- data/test/fixtures/myscheme.rb +1 -0
- data/test/infra_test.rb +189 -0
- data/test/local_file_test.rb +64 -0
- data/test/remote_file_test.rb +106 -0
- data/test/resolver_test.rb +66 -0
- data/test/script_index_test.rb +53 -0
- data/test/script_test.rb +56 -0
- data/test/test_helper.rb +237 -0
- 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,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
|
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'
|