automateit 0.70923
Sign up to get free protection for your applications and to get access to all the features.
- data.tar.gz.sig +1 -0
- data/CHANGES.txt +100 -0
- data/Hoe.rake +35 -0
- data/Manifest.txt +111 -0
- data/README.txt +44 -0
- data/Rakefile +284 -0
- data/TESTING.txt +57 -0
- data/TODO.txt +26 -0
- data/TUTORIAL.txt +390 -0
- data/bin/ai +3 -0
- data/bin/aifield +82 -0
- data/bin/aitag +128 -0
- data/bin/automateit +117 -0
- data/docs/friendly_errors.txt +50 -0
- data/docs/previews.txt +86 -0
- data/env.sh +4 -0
- data/examples/basic/Rakefile +26 -0
- data/examples/basic/config/automateit_env.rb +16 -0
- data/examples/basic/config/fields.yml +3 -0
- data/examples/basic/config/tags.yml +13 -0
- data/examples/basic/dist/README.txt +9 -0
- data/examples/basic/dist/myapp_server.erb +30 -0
- data/examples/basic/install.log +15 -0
- data/examples/basic/lib/README.txt +10 -0
- data/examples/basic/recipes/README.txt +4 -0
- data/examples/basic/recipes/install.rb +53 -0
- data/examples/basic/recipes/uninstall.rb +6 -0
- data/gpl.txt +674 -0
- data/lib/automateit.rb +66 -0
- data/lib/automateit/account_manager.rb +106 -0
- data/lib/automateit/account_manager/linux.rb +171 -0
- data/lib/automateit/account_manager/passwd.rb +69 -0
- data/lib/automateit/account_manager/portable.rb +136 -0
- data/lib/automateit/address_manager.rb +165 -0
- data/lib/automateit/address_manager/linux.rb +80 -0
- data/lib/automateit/address_manager/portable.rb +37 -0
- data/lib/automateit/cli.rb +80 -0
- data/lib/automateit/common.rb +65 -0
- data/lib/automateit/constants.rb +33 -0
- data/lib/automateit/edit_manager.rb +292 -0
- data/lib/automateit/error.rb +10 -0
- data/lib/automateit/field_manager.rb +103 -0
- data/lib/automateit/interpreter.rb +641 -0
- data/lib/automateit/package_manager.rb +242 -0
- data/lib/automateit/package_manager/apt.rb +63 -0
- data/lib/automateit/package_manager/egg.rb +64 -0
- data/lib/automateit/package_manager/gem.rb +179 -0
- data/lib/automateit/package_manager/portage.rb +69 -0
- data/lib/automateit/package_manager/yum.rb +65 -0
- data/lib/automateit/platform_manager.rb +47 -0
- data/lib/automateit/platform_manager/darwin.rb +30 -0
- data/lib/automateit/platform_manager/debian.rb +26 -0
- data/lib/automateit/platform_manager/freebsd.rb +25 -0
- data/lib/automateit/platform_manager/gentoo.rb +26 -0
- data/lib/automateit/platform_manager/lsb.rb +40 -0
- data/lib/automateit/platform_manager/struct.rb +78 -0
- data/lib/automateit/platform_manager/uname.rb +29 -0
- data/lib/automateit/platform_manager/windows.rb +33 -0
- data/lib/automateit/plugin.rb +7 -0
- data/lib/automateit/plugin/base.rb +32 -0
- data/lib/automateit/plugin/driver.rb +218 -0
- data/lib/automateit/plugin/manager.rb +232 -0
- data/lib/automateit/project.rb +460 -0
- data/lib/automateit/root.rb +14 -0
- data/lib/automateit/service_manager.rb +79 -0
- data/lib/automateit/service_manager/chkconfig.rb +39 -0
- data/lib/automateit/service_manager/rc_update.rb +37 -0
- data/lib/automateit/service_manager/sysv.rb +126 -0
- data/lib/automateit/service_manager/update_rcd.rb +35 -0
- data/lib/automateit/shell_manager.rb +261 -0
- data/lib/automateit/shell_manager/base_link.rb +67 -0
- data/lib/automateit/shell_manager/link.rb +24 -0
- data/lib/automateit/shell_manager/portable.rb +421 -0
- data/lib/automateit/shell_manager/symlink.rb +32 -0
- data/lib/automateit/shell_manager/which.rb +25 -0
- data/lib/automateit/tag_manager.rb +63 -0
- data/lib/automateit/tag_manager/struct.rb +101 -0
- data/lib/automateit/tag_manager/tag_parser.rb +91 -0
- data/lib/automateit/tag_manager/yaml.rb +29 -0
- data/lib/automateit/template_manager.rb +55 -0
- data/lib/automateit/template_manager/base.rb +172 -0
- data/lib/automateit/template_manager/erb.rb +17 -0
- data/lib/ext/metaclass.rb +17 -0
- data/lib/ext/object.rb +18 -0
- data/lib/hashcache.rb +22 -0
- data/lib/helpful_erb.rb +63 -0
- data/lib/nested_error.rb +33 -0
- data/lib/queued_logger.rb +68 -0
- data/lib/tempster.rb +239 -0
- data/misc/index_gem_repository.rb +303 -0
- data/misc/setup_egg.rb +12 -0
- data/misc/setup_gem_dependencies.sh +7 -0
- data/misc/setup_rubygems.sh +21 -0
- data/misc/which.cmd +6 -0
- data/spec/extras/automateit_service_sysv_test +50 -0
- data/spec/extras/scratch.rb +15 -0
- data/spec/extras/simple_recipe.rb +8 -0
- data/spec/integration/account_manager_spec.rb +218 -0
- data/spec/integration/address_manager_linux_spec.rb +119 -0
- data/spec/integration/address_manager_portable_spec.rb +30 -0
- data/spec/integration/cli_spec.rb +215 -0
- data/spec/integration/examples_spec.rb +54 -0
- data/spec/integration/examples_spec_editor.rb +71 -0
- data/spec/integration/package_manager_spec.rb +104 -0
- data/spec/integration/platform_manager_spec.rb +69 -0
- data/spec/integration/service_manager_sysv_spec.rb +115 -0
- data/spec/integration/shell_manager_spec.rb +471 -0
- data/spec/integration/template_manager_erb_spec.rb +31 -0
- data/spec/spec_helper.rb +23 -0
- data/spec/unit/edit_manager_spec.rb +162 -0
- data/spec/unit/field_manager_spec.rb +79 -0
- data/spec/unit/hashcache_spec.rb +28 -0
- data/spec/unit/interpreter_spec.rb +98 -0
- data/spec/unit/platform_manager_spec.rb +44 -0
- data/spec/unit/plugins_spec.rb +253 -0
- data/spec/unit/tag_manager_spec.rb +189 -0
- data/spec/unit/template_manager_erb_spec.rb +137 -0
- metadata +249 -0
- metadata.gz.sig +0 -0
@@ -0,0 +1,14 @@
|
|
1
|
+
# See AutomateIt::Interpreter for usage information.
|
2
|
+
module AutomateIt # :nodoc:
|
3
|
+
# Instantiates a new Interpreter. See documentation for
|
4
|
+
# Interpreter#setup.
|
5
|
+
def self.new(opts={})
|
6
|
+
Interpreter.new(opts)
|
7
|
+
end
|
8
|
+
|
9
|
+
# Invokes an Interpreter on the recipe. See documentation for
|
10
|
+
# Interpreter::invoke.
|
11
|
+
def self.invoke(recipe, opts={})
|
12
|
+
Interpreter.invoke(recipe, opts)
|
13
|
+
end
|
14
|
+
end
|
@@ -0,0 +1,79 @@
|
|
1
|
+
# == ServiceManager
|
2
|
+
#
|
3
|
+
# ServiceManager provides a way of managing services, such starting and
|
4
|
+
# stopping Unix daemons.
|
5
|
+
class AutomateIt::ServiceManager < AutomateIt::Plugin::Manager
|
6
|
+
# Is this +service+ started?
|
7
|
+
#
|
8
|
+
# Options:
|
9
|
+
# * :wait -- Maximum number of seconds to wait until service starts. Useful
|
10
|
+
# when a service accepts a #start and returns immediately before the service
|
11
|
+
# has finished starting.
|
12
|
+
def started?(service, opts={}) dispatch(service, opts) end
|
13
|
+
|
14
|
+
# Is this +service+ stopped?
|
15
|
+
#
|
16
|
+
# Options:
|
17
|
+
# * :wait -- Maximum number of seconds to wait until service stops. Useful
|
18
|
+
# when a service accepts a #stop and returns immediately while the service
|
19
|
+
# continues running for a few seconds.
|
20
|
+
def stopped?(service, opts={}) dispatch(service, opts) end
|
21
|
+
|
22
|
+
# Alias for #started?
|
23
|
+
def running?(service, opts={}) dispatch_to(:started?, service, opts) end
|
24
|
+
|
25
|
+
# Start this +service+ if it's not running.
|
26
|
+
def start(service, opts={}) dispatch(service, opts) end
|
27
|
+
|
28
|
+
# Stop this +service+ if it's running.
|
29
|
+
def stop(service, opts={}) dispatch(service, opts) end
|
30
|
+
|
31
|
+
# Restart this +service+ if it's running, or start it if it's stopped.
|
32
|
+
def restart(service, opts={}) dispatch(service, opts) end
|
33
|
+
|
34
|
+
# If +is_restart+, #restart the service, otherwise #start it.
|
35
|
+
#
|
36
|
+
# Example:
|
37
|
+
# modified = edit "/etc/myapp.conf" {#...}
|
38
|
+
# service_manager.start_or_restart("myapp", modified)
|
39
|
+
def start_or_restart(service, is_restart, opts={}) dispatch(service, is_restart, opts) end
|
40
|
+
|
41
|
+
# Start and enable the service using #start and #enable.
|
42
|
+
def start_and_enable(service, opts={}) dispatch(service, opts) end
|
43
|
+
|
44
|
+
# Tell the +service+ to take a specific +action+, e.g., "condrestart".
|
45
|
+
def tell(service, action, opts={}) dispatch(service, action, opts={}) end
|
46
|
+
|
47
|
+
# Will this +service+ start when the computer is rebooted?
|
48
|
+
def enabled?(service) dispatch(service) end
|
49
|
+
|
50
|
+
# Make this +service+ start when the computer is rebooted, but only if it's
|
51
|
+
# not already enabled.
|
52
|
+
def enable(service, opts={}) dispatch(service, opts) end
|
53
|
+
|
54
|
+
# Don't make this +service+ start when the computer is rebooted, but only
|
55
|
+
# if it's already enabled.
|
56
|
+
def disable(service, opts={}) dispatch(service, opts) end
|
57
|
+
end
|
58
|
+
|
59
|
+
# == ServiceManager::BaseDriver
|
60
|
+
#
|
61
|
+
# Base class for all ServiceManager drivers.
|
62
|
+
class AutomateIt::ServiceManager::BaseDriver < AutomateIt::Plugin::Driver
|
63
|
+
# See ServiceManager#start_or_restart
|
64
|
+
def start_or_restart(service, is_restart, opts={})
|
65
|
+
send(is_restart ? :restart : :start, service, opts)
|
66
|
+
end
|
67
|
+
|
68
|
+
# See ServiceManager#start_and_enable
|
69
|
+
def start_and_enable(service, opts={})
|
70
|
+
start(service, opts)
|
71
|
+
enable(service, opts)
|
72
|
+
end
|
73
|
+
end
|
74
|
+
|
75
|
+
# Drivers
|
76
|
+
require 'automateit/service_manager/sysv'
|
77
|
+
require 'automateit/service_manager/update_rcd'
|
78
|
+
require 'automateit/service_manager/chkconfig'
|
79
|
+
require 'automateit/service_manager/rc_update'
|
@@ -0,0 +1,39 @@
|
|
1
|
+
# == ServiceManager::Chkconfig
|
2
|
+
#
|
3
|
+
# The Chkconfig driver implements the ServiceManager methods for #enabled?,
|
4
|
+
# #enable and #disable on RedHat-like platforms. It uses the SYSV driver
|
5
|
+
# for handling the methods #running?, #start and #stop.
|
6
|
+
class AutomateIt::ServiceManager::Chkconfig < AutomateIt::ServiceManager::SYSV
|
7
|
+
depends_on :programs => %w(chkconfig)
|
8
|
+
|
9
|
+
def suitability(method, *args) # :nodoc:
|
10
|
+
return available? ? 2 : 0
|
11
|
+
end
|
12
|
+
|
13
|
+
# See ServiceManager#enabled?
|
14
|
+
def enabled?(service)
|
15
|
+
_raise_unless_available
|
16
|
+
# "chkconfig --list service" may produce output like the below:
|
17
|
+
# service httpd supports chkconfig, but is not referenced in any runlevel (run 'chkconfig --add automateit_service_sysv_test')
|
18
|
+
# => httpd 0:off 1:off 2:off 3:off 4:off 5:off 6:off
|
19
|
+
if matcher = `chkconfig --list #{service} < /dev/null 2>&1` \
|
20
|
+
.match(/^(#{service}).+?(\d+:(on|off).+?)$/)
|
21
|
+
return true if matcher[2].match(/\b\d+:on\b/)
|
22
|
+
end
|
23
|
+
return false
|
24
|
+
end
|
25
|
+
|
26
|
+
# See ServiceManager#enable
|
27
|
+
def enable(service, opts={})
|
28
|
+
_raise_unless_available
|
29
|
+
return false if enabled?(service)
|
30
|
+
interpreter.sh("chkconfig --add #{service}")
|
31
|
+
end
|
32
|
+
|
33
|
+
# See ServiceManager#disable
|
34
|
+
def disable(service, opts={})
|
35
|
+
_raise_unless_available
|
36
|
+
return false unless enabled?(service)
|
37
|
+
interpreter.sh("chkconfig --del #{service}")
|
38
|
+
end
|
39
|
+
end
|
@@ -0,0 +1,37 @@
|
|
1
|
+
# == ServiceManager::RC_Update
|
2
|
+
#
|
3
|
+
# RC_Update implements the #enabled?, #enable and #disable features of the
|
4
|
+
# ServiceManager on Gentoo-like systems.
|
5
|
+
class AutomateIt::ServiceManager::RC_Update < AutomateIt::ServiceManager::SYSV
|
6
|
+
depends_on :programs => %w(rc-update)
|
7
|
+
|
8
|
+
def suitability(method, *args) # :nodoc:
|
9
|
+
return available? ? 2 : 0
|
10
|
+
end
|
11
|
+
|
12
|
+
# See ServiceManager#enabled?
|
13
|
+
def enabled?(service)
|
14
|
+
_raise_unless_available
|
15
|
+
# Do NOT use Gentoo's rc-update because the idiot that wrote that utility
|
16
|
+
# truncates service names to look "prettier" and provides no way to disable
|
17
|
+
# this annoyance for people that need to query services by name.
|
18
|
+
result = %w(boot default).select do |runlevel|
|
19
|
+
File.exists?(File.join("/etc/runlevels", runlevel, service))
|
20
|
+
end
|
21
|
+
return ! result.empty?
|
22
|
+
end
|
23
|
+
|
24
|
+
# See ServiceManager#enable
|
25
|
+
def enable(service, opts={})
|
26
|
+
_raise_unless_available
|
27
|
+
return false if enabled?(service)
|
28
|
+
interpreter.sh("rc-update add #{service} default > /dev/null 2>&1")
|
29
|
+
end
|
30
|
+
|
31
|
+
# See ServiceManager#disable
|
32
|
+
def disable(service, opts={})
|
33
|
+
_raise_unless_available
|
34
|
+
return false unless enabled?(service)
|
35
|
+
interpreter.sh("rc-update del #{service} default > /dev/null 2>&1")
|
36
|
+
end
|
37
|
+
end
|
@@ -0,0 +1,126 @@
|
|
1
|
+
# == ServiceManager::SYSV
|
2
|
+
#
|
3
|
+
# The SYSV driver implements the ServiceManager methods for #running?,
|
4
|
+
# #start and #stop on Unix-like platforms that use the System V init
|
5
|
+
# process using a <tt>/etc/init.d</tt> directory.
|
6
|
+
#
|
7
|
+
# It also implements a basic #enabled? method that's very fast but may not
|
8
|
+
# work correctly on all SysV platforms. This method should be overridden by
|
9
|
+
# more specific drivers when reasonable.
|
10
|
+
#
|
11
|
+
# It does not implement the #enable and #disable methods because these are
|
12
|
+
# not standardized and must be implemented using platform-specific drivers,
|
13
|
+
# e.g., Chkconfig on RedHat-like platforms.
|
14
|
+
class AutomateIt::ServiceManager::SYSV < AutomateIt::ServiceManager::BaseDriver
|
15
|
+
ETC_INITD = "/etc/init.d"
|
16
|
+
|
17
|
+
depends_on :directories => [ETC_INITD]
|
18
|
+
|
19
|
+
def suitability(method, *args) # :nodoc:
|
20
|
+
return 0 if %w(enabled? enable disable).include?(method.to_s)
|
21
|
+
return available? ? 1 : 0
|
22
|
+
end
|
23
|
+
|
24
|
+
def _run_command(args, opts={})
|
25
|
+
_raise_unless_available
|
26
|
+
cmd = String === args ? args : args.join(' ')
|
27
|
+
if opts[:silent] or opts[:check]
|
28
|
+
cmd += " > /dev/null 2>&1" # Discard STDOUT and STDERR
|
29
|
+
elsif opts[:quiet]
|
30
|
+
cmd += " > /dev/null" # Discard only STDOUT
|
31
|
+
end
|
32
|
+
|
33
|
+
level = (opts[:quiet] || opts[:silent] || opts[:check]) ? :debug : :info
|
34
|
+
log.send(level, PEXEC+cmd)
|
35
|
+
if writing? or opts[:check]
|
36
|
+
system(cmd)
|
37
|
+
return $?.exitstatus.zero?
|
38
|
+
else
|
39
|
+
false
|
40
|
+
end
|
41
|
+
end
|
42
|
+
private :_run_command
|
43
|
+
|
44
|
+
# See ServiceManager#tell
|
45
|
+
def tell(service, action, opts={})
|
46
|
+
return _run_command(["#{ETC_INITD}/#{service}", action.to_s], opts)
|
47
|
+
end
|
48
|
+
|
49
|
+
# See ServiceManager#running?
|
50
|
+
def running?(service, opts={})
|
51
|
+
return started?(service, opts)
|
52
|
+
end
|
53
|
+
|
54
|
+
def _started_and_stopped_helper(kind, service, opts={})
|
55
|
+
expected = \
|
56
|
+
case kind
|
57
|
+
when :started?: true
|
58
|
+
when :stopped?: false
|
59
|
+
else raise ArgumentError.new("unknown kind argument: #{kind}")
|
60
|
+
end
|
61
|
+
|
62
|
+
result = tell(service, :status, :check => true)
|
63
|
+
### puts "k %s r %s e %s" % [kind, result, expected]
|
64
|
+
return result if expected == result
|
65
|
+
if opts[:wait]
|
66
|
+
timeout = Time.now + opts[:wait]
|
67
|
+
while timeout > Time.now
|
68
|
+
log.info(PNOTE+" ServiceManager#%s waiting on '%s' for %0.1f more seconds" %
|
69
|
+
[kind, service, timeout - Time.now])
|
70
|
+
sleep 0.5
|
71
|
+
result = tell(service, :status, :check => true)
|
72
|
+
break if expected == result
|
73
|
+
end
|
74
|
+
log.info(PNOTE+" ServiceManager#%s finished waiting for '%s', got: %s" %
|
75
|
+
[kind, service, result])
|
76
|
+
end
|
77
|
+
return result
|
78
|
+
end
|
79
|
+
|
80
|
+
# See ServiceManager#started?
|
81
|
+
def started?(service, opts={})
|
82
|
+
return _started_and_stopped_helper(:started?, service, opts)
|
83
|
+
end
|
84
|
+
|
85
|
+
# See ServiceManager#stopped?
|
86
|
+
def stopped?(service, opts={})
|
87
|
+
return ! _started_and_stopped_helper(:stopped?, service, opts)
|
88
|
+
end
|
89
|
+
|
90
|
+
# See ServiceManager#start
|
91
|
+
def start(service, opts={})
|
92
|
+
# TODO maybe add a :wait option?
|
93
|
+
if started?(service) and not opts[:force]
|
94
|
+
# Already started
|
95
|
+
return false
|
96
|
+
else
|
97
|
+
# Needs starting or forced
|
98
|
+
tell(service, :start, opts)
|
99
|
+
return true
|
100
|
+
end
|
101
|
+
end
|
102
|
+
|
103
|
+
# See ServiceManager#stop
|
104
|
+
def stop(service, opts={})
|
105
|
+
# TODO maybe add a :wait option?
|
106
|
+
if stopped?(service) and not opts[:force]
|
107
|
+
# Already stopped
|
108
|
+
return false
|
109
|
+
else
|
110
|
+
# Needs stopping or forced
|
111
|
+
tell(service, :stop, opts)
|
112
|
+
return true
|
113
|
+
end
|
114
|
+
end
|
115
|
+
|
116
|
+
# See ServiceManager#restart
|
117
|
+
def restart(service, opts={})
|
118
|
+
stop(service, opts) if running?(service)
|
119
|
+
return start(service, opts)
|
120
|
+
end
|
121
|
+
|
122
|
+
# See ServiceManager#enabled?
|
123
|
+
def enabled?(service)
|
124
|
+
return ! Dir["/etc/rc*.d/*"].grep(/\/S\d{2}#{service}$/).empty?
|
125
|
+
end
|
126
|
+
end
|
@@ -0,0 +1,35 @@
|
|
1
|
+
# == ServiceManager::UpdateRCD
|
2
|
+
#
|
3
|
+
# The UpdateRCD driver implements the ServiceManager methods for #enabled?,
|
4
|
+
# #enable and #disable on Debian-like platforms. It uses the SYSV driver
|
5
|
+
# for handling the methods #running?, #start and #stop.
|
6
|
+
class AutomateIt::ServiceManager::UpdateRCD < AutomateIt::ServiceManager::SYSV
|
7
|
+
TOOL = "update-rc.d"
|
8
|
+
|
9
|
+
depends_on :programs => [TOOL]
|
10
|
+
|
11
|
+
def suitability(method, *args) # :nodoc:
|
12
|
+
return available? ? 3 : 0
|
13
|
+
end
|
14
|
+
|
15
|
+
# See ServiceManager#enable
|
16
|
+
def enable(service, opts={})
|
17
|
+
_raise_unless_available
|
18
|
+
return false if enabled?(service)
|
19
|
+
interpreter.sh("#{TOOL} #{service} defaults < /dev/null > /dev/null")
|
20
|
+
end
|
21
|
+
|
22
|
+
# See ServiceManager#disable
|
23
|
+
def disable(service, opts={})
|
24
|
+
_raise_unless_available
|
25
|
+
return false unless enabled?(service)
|
26
|
+
interpreter.sh("#{TOOL} -f #{service} remove < /dev/null > /dev/null")
|
27
|
+
end
|
28
|
+
|
29
|
+
def enabled?(service, opts={})
|
30
|
+
_raise_unless_available
|
31
|
+
cmd = "#{TOOL} -n -f #{service} remove < /dev/null"
|
32
|
+
output = `#{cmd}`
|
33
|
+
return ! output.match(/etc\/rc[\dS].d|Nothing to do\./).nil?
|
34
|
+
end
|
35
|
+
end
|
@@ -0,0 +1,261 @@
|
|
1
|
+
# == ShellManager
|
2
|
+
#
|
3
|
+
# The ShellManager provides Unix-like shell commands for manipulating files and
|
4
|
+
# executing commands.
|
5
|
+
#
|
6
|
+
# *WARNING*: Previewing code can be dangerous. Read
|
7
|
+
# previews.txt[link:files/docs/previews_txt.html] for instructions on how to
|
8
|
+
# write code that can be safely previewed.
|
9
|
+
class AutomateIt::ShellManager < AutomateIt::Plugin::Manager
|
10
|
+
alias_methods :sh, :which, :which!, :mktemp, :mktempdir, :mktempdircd, :chperm, :umask
|
11
|
+
alias_methods :cd, :pwd, :mkdir, :mkdir_p, :rmdir, :ln, :ln_s, :ln_sf, :cp, :cp_r, :cp_R, :mv, :rm, :rm_r, :rm_rf, :install, :chmod, :chmod_R, :chown, :chown_R, :touch
|
12
|
+
|
13
|
+
#...[ Detection commands ]..............................................
|
14
|
+
|
15
|
+
# See ShellManager#provides_mode?
|
16
|
+
def provides_mode?() dispatch_safely end
|
17
|
+
|
18
|
+
# See ShellManager#provides_mode?
|
19
|
+
def provides_ownership?() dispatch_safely end
|
20
|
+
|
21
|
+
# See ShellManager#provides_mode?
|
22
|
+
def provides_symlink?() dispatch_safely end
|
23
|
+
|
24
|
+
# See ShellManager#provides_mode?
|
25
|
+
def provides_link?() dispatch_safely end
|
26
|
+
|
27
|
+
#...[ Custom commands ].................................................
|
28
|
+
|
29
|
+
# Execute a shell command.
|
30
|
+
def sh(*commands) dispatch(*commands) end
|
31
|
+
|
32
|
+
# What is the path for this command? Returns +nil+ if command isn't found.
|
33
|
+
#
|
34
|
+
# Example:
|
35
|
+
# which("ls") # => "/bin/ls"
|
36
|
+
def which(command) dispatch(command) end
|
37
|
+
|
38
|
+
# Same as #which but throws an ArgumentError if command isn't found.
|
39
|
+
def which!(command) dispatch(command) end
|
40
|
+
|
41
|
+
# Creates a temporary file. Optionally takes a +name+ argument which is
|
42
|
+
# purely cosmetic, e.g., if the +name+ is "foo", the routine may create a
|
43
|
+
# temporary file named <tt>/tmp/foo_qeKo7nJk1s</tt>.
|
44
|
+
#
|
45
|
+
# When called with a block, invokes the block with the path of the temporary
|
46
|
+
# file and deletes the file at the end of the block.
|
47
|
+
#
|
48
|
+
# Without a block, returns the path of the temporary file and you're
|
49
|
+
# responsible for removing it when done.
|
50
|
+
def mktemp(name=nil, &block) # :yields: path
|
51
|
+
dispatch(name, &block)
|
52
|
+
end
|
53
|
+
|
54
|
+
# Creates a temporary directory. See #mktemp for details on the +name+
|
55
|
+
# argument.
|
56
|
+
#
|
57
|
+
# When called with a block, invokes the block with the path of the
|
58
|
+
# temporary directory and recursively deletes the directory and its
|
59
|
+
# contents at the end of the block.
|
60
|
+
#
|
61
|
+
# Without a block, returns the path of the temporary directory and you're
|
62
|
+
# responsible for removing it when done.
|
63
|
+
#
|
64
|
+
# CAUTION: Read notes at the top of ShellManager for potentially
|
65
|
+
# problematic situations that may be encountered if using this command in
|
66
|
+
# preview mode!
|
67
|
+
def mktempdir(name=nil, &block) # :yields: path
|
68
|
+
dispatch(name, &block)
|
69
|
+
end
|
70
|
+
|
71
|
+
# Same as #mktempdir but performs a #cd into the directory for the duration
|
72
|
+
# of the block.
|
73
|
+
#
|
74
|
+
# Example:
|
75
|
+
#
|
76
|
+
# puts pwd # => "/home/bubba"
|
77
|
+
# mktempdircd do |path|
|
78
|
+
# puts path # => "/tmp/tempster_qeKo7nJk1s"
|
79
|
+
# puts pwd # => "/tmp/tempster_qeKo7nJk1s"
|
80
|
+
# end
|
81
|
+
# puts File.exists?("/tmp/tempster_qeKo7nJk1s") # => false
|
82
|
+
def mktempdircd(name=nil, &block) # :yields: path
|
83
|
+
dispatch(name, &block)
|
84
|
+
end
|
85
|
+
|
86
|
+
# Change the permissions of the +targets+. This command is like the #chmod
|
87
|
+
# and #chown in a single command.
|
88
|
+
#
|
89
|
+
# Options:
|
90
|
+
# * :recursive -- Change files and directories recursively. Defaults to false.
|
91
|
+
# * :user -- User name to change ownership to.
|
92
|
+
# * :group -- Group name to change ownership to.
|
93
|
+
# * :mode -- Mode to use as octal, e.g., <tt>0400</tt> to make a file
|
94
|
+
# readable only to its owner.
|
95
|
+
# * :details -- Reports the files modified, rather than the arguments
|
96
|
+
# modified. An argument might be a single directory, but this may result in
|
97
|
+
# modifications to many files within that directory. Use :details for
|
98
|
+
# situations when there's a need to see all files actually changed. The
|
99
|
+
# reason :details is off by default is that it will flood the screen with a
|
100
|
+
# list of all files modified in a large directory, which is overwhelming
|
101
|
+
# and probably unnecessary unless you actually need to see these details.
|
102
|
+
# Defaults to false.
|
103
|
+
def chperm(targets, opts={}) dispatch(targets, opts) end
|
104
|
+
|
105
|
+
# Set the umask to +mode+. If given a block, changes the umask only for the
|
106
|
+
# duration of the block and changes it back to its previous setting at the
|
107
|
+
# end.
|
108
|
+
def umask(mode=nil, &block) dispatch(mode, &block) end
|
109
|
+
|
110
|
+
#...[ FileUtils wrappers ]...............................................
|
111
|
+
|
112
|
+
# Changes the directory into the specified +dir+. If called with a block,
|
113
|
+
# changes to the directory for the duration of the block, and then changes
|
114
|
+
# back to the previous directory at the end.
|
115
|
+
#
|
116
|
+
# *WARNING*: Previewing code can be dangerous. Read
|
117
|
+
# previews.txt[link:files/docs/previews_txt.html] for instructions on how to
|
118
|
+
# write code that can be safely previewed.
|
119
|
+
def cd(dir, opts={}, &block) dispatch(dir, opts, &block) end
|
120
|
+
|
121
|
+
# Returns the current directory.
|
122
|
+
def pwd() dispatch() end
|
123
|
+
|
124
|
+
# Create a directory or directories. Returns an array of directories
|
125
|
+
# created or +false+ if all directories are already present.
|
126
|
+
#
|
127
|
+
# Options:
|
128
|
+
# * :parents -- Create parents, like "mkdir -p". Boolean.
|
129
|
+
# * :mode, :user, :group -- See #chperm
|
130
|
+
#
|
131
|
+
# *WARNING*: Previewing code can be dangerous. Read
|
132
|
+
# previews.txt[link:files/docs/previews_txt.html] for instructions on how to
|
133
|
+
# write code that can be safely previewed.
|
134
|
+
def mkdir(dirs, opts={}, &block) dispatch(dirs, &block) end
|
135
|
+
|
136
|
+
# Create a directory or directories with their parents. Returns an array of
|
137
|
+
# directories created or +false+ if all directories are already present.
|
138
|
+
#
|
139
|
+
# Options same as #mkdir.
|
140
|
+
#
|
141
|
+
# Example:
|
142
|
+
# File.exists?("/tmp/foo") # => false
|
143
|
+
# mkdir_p("/tmp/foo/bar")
|
144
|
+
# File.exists?("/tmp/foo") # => true
|
145
|
+
# File.exists?("/tmp/foo/bar") # => true
|
146
|
+
#
|
147
|
+
# *WARNING*: Previewing code can be dangerous. Read
|
148
|
+
# previews.txt[link:files/docs/previews_txt.html] for instructions on how to
|
149
|
+
# write code that can be safely previewed.
|
150
|
+
def mkdir_p(dirs, opts={}, &block) dispatch(dirs, &block) end
|
151
|
+
|
152
|
+
# Remove a directory or directories. The directories must be empty or an
|
153
|
+
# exception is thrown. Returns the directories removed or +false+ if none
|
154
|
+
# of the directories exist.
|
155
|
+
def rmdir(dirs) dispatch(dirs) end
|
156
|
+
|
157
|
+
# Create a hard link between the +source+ and +target+. Your platform must
|
158
|
+
# support hard links to use this. Returns the target created or +false+ if
|
159
|
+
# the link is already present.
|
160
|
+
def ln(source, target, opts={}) dispatch(source, target, opts) end
|
161
|
+
|
162
|
+
# Create a symbolic link between the +sources+ and +target+. Your platform
|
163
|
+
# must support symbolic links to use this. Returns an array of sources
|
164
|
+
# linked or +false+ if all are already present.
|
165
|
+
def ln_s(sources, target, opts={}) dispatch(sources, target, opts) end
|
166
|
+
|
167
|
+
# Create a symbolic link between the +sources+ and +target+. If the
|
168
|
+
# +target+ already exists, will remove it and recreate it. Your platform
|
169
|
+
# must support symbolic links to use this. Returns an array of sources
|
170
|
+
# linked or +false+ if all are already present.
|
171
|
+
def ln_sf(sources, target, opts={}) dispatch(sources, target, opts) end
|
172
|
+
|
173
|
+
# Copy the +sources+ to the +target+. Returns an array of sources copied or
|
174
|
+
# +false+ if all are present.
|
175
|
+
#
|
176
|
+
# Options:
|
177
|
+
# * :preserve -- preserve file modification time and ownership, boolean.
|
178
|
+
# * :recursive -- copy files and directories recursively, boolean.
|
179
|
+
def cp(sources, target, opts={}) dispatch(sources, target, opts) end
|
180
|
+
|
181
|
+
# Copy the +sources+ to the +target+ recursively. Returns an array of
|
182
|
+
# sources copied or +false+ if all are present.
|
183
|
+
def cp_r(sources, target, opts={}) dispatch(sources, target, opts) end
|
184
|
+
|
185
|
+
# Copy the +sources+ to the +target+ recursively. Returns an array of
|
186
|
+
# sources copied or +false+ if all are present.
|
187
|
+
def cp_R(sources, target, opts={}) dispatch(sources, target, opts) end
|
188
|
+
|
189
|
+
# Move the +sources+ to the +target+. Returns an array of sources copied or
|
190
|
+
# +false+ if none of the sources exist.
|
191
|
+
def mv(sources, target) dispatch(sources, target) end
|
192
|
+
|
193
|
+
# Remove the +targets+. Returns a list of targets removed or +false+ if
|
194
|
+
# none of them exist.
|
195
|
+
def rm(targets, opts={}) dispatch(targets, opts) end
|
196
|
+
|
197
|
+
# Remove the +targets+ recursively. Returns a list of targets removed or
|
198
|
+
# +false+ if none of them exist.
|
199
|
+
def rm_r(targets, opts={}) dispatch(targets, opts) end
|
200
|
+
|
201
|
+
# Remove the +targets+ recursively and forcefully. Returns a list of
|
202
|
+
# targets removed or +false+ if none of them exist.
|
203
|
+
def rm_rf(targets, opts={}) dispatch(targets, opts) end
|
204
|
+
|
205
|
+
# Copy the +source+ to the +target+ and set its +mode+. Returns true if the
|
206
|
+
# file was installed or +false+ if already present.
|
207
|
+
def install(source, target, mode) dispatch(source, target, mode) end
|
208
|
+
|
209
|
+
# Change the permission +mode+ of the +targets+. Returns an array of
|
210
|
+
# targets modified or +false+ if all have the desired mode.
|
211
|
+
def chmod(mode, targets, opts={}) dispatch(mode, targets, opts) end
|
212
|
+
|
213
|
+
# Change the permission +mode+ of the +targets+ recursively. Returns an
|
214
|
+
# array of targets modified or +false+ if all have the desired mode.
|
215
|
+
def chmod_R(mode, targets, opts={}) dispatch(mode, targets, opts) end
|
216
|
+
|
217
|
+
# Change the +user+ and +group+ ownership of the +targets+. You can leave
|
218
|
+
# either the user or group as nil if you don't want to change it. Returns
|
219
|
+
# an array of targets modified or +false+ if all have the desired
|
220
|
+
# ownership.
|
221
|
+
def chown(user, group, targets, opts={}) dispatch(user, group, targets, opts) end
|
222
|
+
|
223
|
+
# Change the +user+ and +group+ ownership of the +targets+ recursively. You
|
224
|
+
# can leave either the user or group as nil if you don't want to change it.
|
225
|
+
# Returns an array of targets modified or +false+ if all have the desired
|
226
|
+
# ownership.
|
227
|
+
def chown_R(user, group, targets, opts={}) dispatch(user, group, targets, opts) end
|
228
|
+
|
229
|
+
# Create the +targets+ as files if needed and update their modification
|
230
|
+
# time. Unlike most other commands provided by ShellManager, this one will
|
231
|
+
# always modify the targets. Returns an array of targets modified.
|
232
|
+
def touch(targets) dispatch(targets) end
|
233
|
+
end
|
234
|
+
|
235
|
+
# == ShellManager::BaseDriver
|
236
|
+
#
|
237
|
+
# Base class for all ShellManager drivers.
|
238
|
+
class AutomateIt::ShellManager::BaseDriver < AutomateIt::Plugin::Driver
|
239
|
+
def _replace_owner_with_user(opts)
|
240
|
+
value = opts.delete(:owner)
|
241
|
+
opts[:user] = value if value and not opts[:user]
|
242
|
+
return opts
|
243
|
+
end
|
244
|
+
protected :_replace_owner_with_user
|
245
|
+
|
246
|
+
# Returns hash of verbosity and preview settings for FileUtils commands.
|
247
|
+
def _fileutils_opts
|
248
|
+
opts = {}
|
249
|
+
opts[:verbose] = false # Generate our own log messages
|
250
|
+
opts[:noop] = true if preview?
|
251
|
+
return opts
|
252
|
+
end
|
253
|
+
private :_fileutils_opts
|
254
|
+
end
|
255
|
+
|
256
|
+
# Drivers
|
257
|
+
require 'automateit/shell_manager/portable'
|
258
|
+
require 'automateit/shell_manager/which'
|
259
|
+
require 'automateit/shell_manager/base_link'
|
260
|
+
require 'automateit/shell_manager/symlink'
|
261
|
+
require 'automateit/shell_manager/link'
|