inprovise 0.2.2
Sign up to get free protection for your applications and to get access to all the features.
- 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'
|