automateit 0.70923
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.
- 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,165 @@
|
|
|
1
|
+
# == AddressManager
|
|
2
|
+
#
|
|
3
|
+
# The AddressManager provides a way to query, add and remove network
|
|
4
|
+
# addresses on a host.
|
|
5
|
+
class AutomateIt::AddressManager < AutomateIt::Plugin::Manager
|
|
6
|
+
# Does host have an address or interface? Arguments hash must include
|
|
7
|
+
# either a :device (e.g., "eth0") or :address (e.g., "10.0.0.10"), and an
|
|
8
|
+
# optional :label (e.g., "foo"). Note that an interface is the combination
|
|
9
|
+
# of a :device and :label, so "eth0" isn't the same as "eth0:foo".
|
|
10
|
+
#
|
|
11
|
+
# Examples on a host with address "10.0.0.10" on interface "eth0:foo":
|
|
12
|
+
# has?(:address => "10.0.0.10")
|
|
13
|
+
# => true
|
|
14
|
+
# has?(:address => "10.0.0.10", :device => "eth0")
|
|
15
|
+
# => false
|
|
16
|
+
# has?(:address => "10.0.0.10", :device => "eth0", :label => "foo")
|
|
17
|
+
# => true
|
|
18
|
+
# has?(:device => "eth0")
|
|
19
|
+
# => false
|
|
20
|
+
# has?(:device => "eth0", :label => "foo")
|
|
21
|
+
# => true
|
|
22
|
+
def has?(opts) dispatch(opts) end
|
|
23
|
+
|
|
24
|
+
# Add address to host if it doesn't have it. Requires root-level access.
|
|
25
|
+
# Returns +true+ if action was taken and succeeded.
|
|
26
|
+
#
|
|
27
|
+
# Arguments hash must include either a :device (e.g., "eth0") or :address
|
|
28
|
+
# (e.g., "10.0.0.10"), and an optional :label (e.g., "foo") and :mask (e.g.
|
|
29
|
+
# "24").
|
|
30
|
+
#
|
|
31
|
+
# An optional number of ARP :announcements may be specified, defaulting to
|
|
32
|
+
# AutomateIt::AddressManager::DEFAULT_ANNOUNCEMENTS. Drivers that handle
|
|
33
|
+
# announcements will block an extra second while making each announcement.
|
|
34
|
+
#
|
|
35
|
+
# Example:
|
|
36
|
+
# add(:address => "10.0.0.10", :mask => 24, :device => "eth0",
|
|
37
|
+
# :label => "foo", :announcements => 3)
|
|
38
|
+
def add(opts) dispatch(opts) end
|
|
39
|
+
|
|
40
|
+
# Number of ARP announcements to make by default during #add.
|
|
41
|
+
DEFAULT_ANNOUNCEMENTS = 3
|
|
42
|
+
|
|
43
|
+
# Remove address from host if it has it. Requires root-level access.
|
|
44
|
+
# Returns +true+ if action was taken and succeeded.
|
|
45
|
+
#
|
|
46
|
+
# Arguments hash must include either a :device (e.g., "eth0") or :address
|
|
47
|
+
# (e.g., "10.0.0.10"), and an optional :label (e.g., "foo") and :mask (e.g.
|
|
48
|
+
# "24").
|
|
49
|
+
#
|
|
50
|
+
# Example:
|
|
51
|
+
# remove(:address => "10.0.0.10", :mask => 24, :device => "eth0",
|
|
52
|
+
# :label => "foo")
|
|
53
|
+
def remove(opts) dispatch(opts) end
|
|
54
|
+
|
|
55
|
+
# Array of addresses for this host. Example:
|
|
56
|
+
# addresses
|
|
57
|
+
# => ["10.0.0.10", "127.0.0.1"]
|
|
58
|
+
def addresses() dispatch() end
|
|
59
|
+
|
|
60
|
+
# Array of interfaces for this host. Example:
|
|
61
|
+
# interfaces
|
|
62
|
+
# => ["eth0", "lo"]
|
|
63
|
+
def interfaces() dispatch() end
|
|
64
|
+
|
|
65
|
+
# Array of hostnames for this host, including variants by trying to resolve
|
|
66
|
+
# names for all addresses owned by this host. Example:
|
|
67
|
+
# hostnames
|
|
68
|
+
# => ["kagami", "kagami.lucky-channel", "kagami.lucky-channel.jp"]
|
|
69
|
+
def hostnames() dispatch() end
|
|
70
|
+
|
|
71
|
+
# Array of hostname variants for this +hostname+. This method performs no
|
|
72
|
+
# name resolution and simply infers a less qualified name from a more
|
|
73
|
+
# qualified hostname argument. Example:
|
|
74
|
+
# hostnames_for("kagami.lucky-channel")
|
|
75
|
+
# => ["kagami", "kagami.lucky-channel"]
|
|
76
|
+
# hostnames_for("kagami")
|
|
77
|
+
# => ["kagami"]
|
|
78
|
+
def hostnames_for(hostname) dispatch(hostname) end
|
|
79
|
+
|
|
80
|
+
# Convert a mask to a CIDR.
|
|
81
|
+
#
|
|
82
|
+
# Example:
|
|
83
|
+
# mask_to_cidr("255.255.255.0") # => 24
|
|
84
|
+
def mask_to_cidr(mask) dispatch(mask) end
|
|
85
|
+
|
|
86
|
+
# Convert CIDR to mask.
|
|
87
|
+
#
|
|
88
|
+
# Example:
|
|
89
|
+
# cidr_to_mask(24) # => "255.255.255.0"
|
|
90
|
+
def cidr_to_mask(cidr) dispatch(cidr) end
|
|
91
|
+
|
|
92
|
+
# Convert a decimal number to binary notation.
|
|
93
|
+
#
|
|
94
|
+
# Example:
|
|
95
|
+
# dec2bin(255) # => "11111111"
|
|
96
|
+
def dec2bin(n) dispatch(n) end
|
|
97
|
+
|
|
98
|
+
# Convert a binary number to decimal.
|
|
99
|
+
#
|
|
100
|
+
# Example:
|
|
101
|
+
# bin2dec("11111111") # => 255
|
|
102
|
+
def bin2dec(s) dispatch(s) end
|
|
103
|
+
end
|
|
104
|
+
|
|
105
|
+
# == AddressManager::BaseDriver
|
|
106
|
+
#
|
|
107
|
+
# Base class for all AddressManager drivers.
|
|
108
|
+
class AutomateIt::AddressManager::BaseDriver< AutomateIt::Plugin::Driver
|
|
109
|
+
# See AddressManager#hostnames
|
|
110
|
+
def hostnames()
|
|
111
|
+
# NOTE: depends on driver's implementation of addresses
|
|
112
|
+
names = addresses.inject(Set.new) do |sum, address|
|
|
113
|
+
# Some addresses can't be resolved, bummer.
|
|
114
|
+
sum.merge(Resolv.getnames(address)) rescue Resolv::ResolvError; sum
|
|
115
|
+
end
|
|
116
|
+
names << Socket.gethostname
|
|
117
|
+
names.merge(Socket.gethostbyname(Socket.gethostname)[1]) rescue SocketError
|
|
118
|
+
|
|
119
|
+
names.each{|name| names.merge(hostnames_for(name))}
|
|
120
|
+
names << "localhost"
|
|
121
|
+
return names.to_a.sort
|
|
122
|
+
end
|
|
123
|
+
|
|
124
|
+
# See AddressManager#hostname_for
|
|
125
|
+
def hostnames_for(hostname)
|
|
126
|
+
results = []
|
|
127
|
+
elements = hostname.split(".")
|
|
128
|
+
for i in 1..elements.size
|
|
129
|
+
results << elements[0..i-1].join(".")
|
|
130
|
+
end
|
|
131
|
+
return results.to_a.sort
|
|
132
|
+
end
|
|
133
|
+
|
|
134
|
+
# See AddressManager#mask_to_cidr
|
|
135
|
+
def mask_to_cidr(mask)
|
|
136
|
+
# TODO Find less horrible solution which can handle IPv6.
|
|
137
|
+
result = ''
|
|
138
|
+
for chunk in mask.split(".")
|
|
139
|
+
result += dec2bin(chunk.to_i)
|
|
140
|
+
end
|
|
141
|
+
return result.scan(/1/).size
|
|
142
|
+
end
|
|
143
|
+
|
|
144
|
+
# See AddressManager#cidr_to_mask
|
|
145
|
+
def cidr_to_mask(cidr)
|
|
146
|
+
# TODO Find less horrible solution which can handle IPv6.
|
|
147
|
+
require 'ipaddr'
|
|
148
|
+
IPAddr.new("0.0.0.0/#{cidr}").inspect.match(%r{/([\d\.]+)>})[1]
|
|
149
|
+
end
|
|
150
|
+
|
|
151
|
+
# See AddressManager#dec2bin
|
|
152
|
+
def dec2bin(n)
|
|
153
|
+
# dec2bin(255)
|
|
154
|
+
return "%b" % n
|
|
155
|
+
end
|
|
156
|
+
|
|
157
|
+
# See AddressManager#bin2dec
|
|
158
|
+
def bin2dec(s)
|
|
159
|
+
return s.to_i(2)
|
|
160
|
+
end
|
|
161
|
+
end
|
|
162
|
+
|
|
163
|
+
# Drivers
|
|
164
|
+
require 'automateit/address_manager/portable'
|
|
165
|
+
require 'automateit/address_manager/linux'
|
|
@@ -0,0 +1,80 @@
|
|
|
1
|
+
# == AddressManager::Linux
|
|
2
|
+
#
|
|
3
|
+
# A Linux-specific driver for the AddressManager provides complete support for
|
|
4
|
+
# querying, adding and removing addresses on platforms that feature Linux-like
|
|
5
|
+
# tools.
|
|
6
|
+
class AutomateIt::AddressManager::Linux < AutomateIt::AddressManager::BaseDriver
|
|
7
|
+
depends_on :programs => "ifconfig",
|
|
8
|
+
:callbacks => lambda{`ifconfig --version 2>&1`.match(/net-tools/)}
|
|
9
|
+
|
|
10
|
+
def suitability(method, *args) # :nodoc:
|
|
11
|
+
available? ? 2 : 0
|
|
12
|
+
end
|
|
13
|
+
|
|
14
|
+
# See AddressManager#has?
|
|
15
|
+
def has?(opts)
|
|
16
|
+
raise ArgumentError.new(":device or :address must be specified") unless opts[:device] or opts[:address]
|
|
17
|
+
result = true
|
|
18
|
+
result &= interfaces.include?(opts[:device]) if opts[:device] and not opts[:label]
|
|
19
|
+
result &= interfaces.include?(opts[:device]+":"+opts[:label]) if opts[:device] and opts[:label]
|
|
20
|
+
result &= addresses.include?(opts[:address]) if opts[:address]
|
|
21
|
+
return result
|
|
22
|
+
end
|
|
23
|
+
|
|
24
|
+
# See AddressManager#add
|
|
25
|
+
def add(opts)
|
|
26
|
+
announcements = opts[:announcements].to_i || AutomateIt::AddressManager::DEFAULT_ANNOUNCEMENTS
|
|
27
|
+
raise SecurityError.new("you must be root") unless superuser?
|
|
28
|
+
raise ArgumentError.new(":device and :address must be specified") unless opts[:device] and opts[:address]
|
|
29
|
+
return false if has?(opts)
|
|
30
|
+
interpreter.sh(_add_or_remove_command(:add, opts))
|
|
31
|
+
if interpreter.which("arping")
|
|
32
|
+
interpreter.sh("arping -q -c #{announcements} -w #{announcements} -I #{opts[:device]} #{opts[:address]}")
|
|
33
|
+
end
|
|
34
|
+
return true
|
|
35
|
+
end
|
|
36
|
+
|
|
37
|
+
# See AddressManager#remove
|
|
38
|
+
def remove(opts)
|
|
39
|
+
return false unless has?(opts)
|
|
40
|
+
raise SecurityError.new("you must be root") unless superuser?
|
|
41
|
+
raise ArgumentError.new(":device and :address must be specified") unless opts[:device] and opts[:address]
|
|
42
|
+
return interpreter.sh(_add_or_remove_command(:remove, opts))
|
|
43
|
+
end
|
|
44
|
+
|
|
45
|
+
def _add_or_remove_command(action, opts)
|
|
46
|
+
_raise_unless_available
|
|
47
|
+
action = :del if action.to_sym == :remove
|
|
48
|
+
|
|
49
|
+
# Accept common alternative names
|
|
50
|
+
opts[:mask] ||= opts[:netmask] if opts[:netmask]
|
|
51
|
+
opts[:alias] ||= opts[:alias] if opts[:alias]
|
|
52
|
+
opts[:device] ||= opts[:interface] if opts[:interface]
|
|
53
|
+
|
|
54
|
+
if opts[:mask] and not opts[:mask].match(/\./)
|
|
55
|
+
opts[:mask] = cidr_to_mask(opts[:mask])
|
|
56
|
+
end
|
|
57
|
+
|
|
58
|
+
ipcmd = "ifconfig"
|
|
59
|
+
ipcmd << " %s" % opts[:device] if opts[:device] and not opts[:label]
|
|
60
|
+
ipcmd << " %s:%s" % [opts[:device], opts[:label]] if opts[:device] and opts[:label]
|
|
61
|
+
ipcmd << " %s" % opts[:address]
|
|
62
|
+
ipcmd << " netmask %s" % opts[:mask] if opts[:mask]
|
|
63
|
+
ipcmd << " up" if action == :add
|
|
64
|
+
ipcmd << " down" if action == :del
|
|
65
|
+
return ipcmd
|
|
66
|
+
end
|
|
67
|
+
private :_add_or_remove_command
|
|
68
|
+
|
|
69
|
+
# See AddressManager#interfaces
|
|
70
|
+
def interfaces()
|
|
71
|
+
_raise_unless_available
|
|
72
|
+
return `ifconfig`.scan(/^(\w+?(?::\w+)?)\b\s+Link/).flatten
|
|
73
|
+
end
|
|
74
|
+
|
|
75
|
+
# See AddressManager#addresses
|
|
76
|
+
def addresses()
|
|
77
|
+
_raise_unless_available
|
|
78
|
+
return `ifconfig`.scan(/inet6? addr:\s*(.+?)\s+/).flatten
|
|
79
|
+
end
|
|
80
|
+
end
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
# == AddressManager::Portable
|
|
2
|
+
#
|
|
3
|
+
# A pure-Ruby, portable driver for the AddressManager which provides
|
|
4
|
+
# minimal support for querying the hostname using sockets. Although it
|
|
5
|
+
# lacks advanced features found in other drivers, it will work on all
|
|
6
|
+
# platforms.
|
|
7
|
+
class AutomateIt::AddressManager::Portable < AutomateIt::AddressManager::BaseDriver
|
|
8
|
+
def suitability(method, *args) # :nodoc:
|
|
9
|
+
return 1
|
|
10
|
+
end
|
|
11
|
+
|
|
12
|
+
# See AddressManager#has?
|
|
13
|
+
def has?(opts)
|
|
14
|
+
raise NotImplementedError.new("this driver doesn't support queries for devices or labels") if opts[:device] or opts[:label]
|
|
15
|
+
result = true
|
|
16
|
+
result &= addresses.include?(opts[:address]) if opts[:address]
|
|
17
|
+
return result
|
|
18
|
+
end
|
|
19
|
+
|
|
20
|
+
# See AddressManager#hostnames
|
|
21
|
+
def hostnames
|
|
22
|
+
results = Set.new
|
|
23
|
+
results << Socket.gethostname
|
|
24
|
+
results.merge(Socket.gethostbyname(Socket.gethostname)[1]) rescue SocketError
|
|
25
|
+
|
|
26
|
+
results.each{|name| results.merge(hostnames_for(name))}
|
|
27
|
+
results << "localhost"
|
|
28
|
+
return results.to_a.sort
|
|
29
|
+
end
|
|
30
|
+
|
|
31
|
+
# See AddressManager#addresses
|
|
32
|
+
def addresses
|
|
33
|
+
results = Set.new("127.0.0.1")
|
|
34
|
+
results.merge(TCPSocket.gethostbyname(Socket.gethostname)[3]) rescue SocketError
|
|
35
|
+
return results.flatten
|
|
36
|
+
end
|
|
37
|
+
end
|
|
@@ -0,0 +1,80 @@
|
|
|
1
|
+
module AutomateIt
|
|
2
|
+
# == CLI
|
|
3
|
+
#
|
|
4
|
+
# The CLI class provides AutomateIt's command-line interface. It's
|
|
5
|
+
# responsible for invoking recipes from the command line, starting the
|
|
6
|
+
# interactive shell and creating projects. It's run from
|
|
7
|
+
# <tt>bin/automate</tt>.
|
|
8
|
+
class CLI < Common
|
|
9
|
+
# Create a new CLI interpreter. If no :recipe or :eval option is provided,
|
|
10
|
+
# it starts an interactive IRB session for the Interpreter.
|
|
11
|
+
#
|
|
12
|
+
# Examples:
|
|
13
|
+
# AutomateIt::CLI.run("myrecipe.rb")
|
|
14
|
+
# AutomateIt::CLI.run(:recipe => "myrecipe.rb")
|
|
15
|
+
# AutomateIt::CLI.run(:eval => "42")
|
|
16
|
+
#
|
|
17
|
+
# Options:
|
|
18
|
+
# * :project -- Project directory to load.
|
|
19
|
+
# * :recipe -- Recipe file to execute.
|
|
20
|
+
# * :eval -- Evaluate this string.
|
|
21
|
+
# * :quiet -- Don't print shell header.
|
|
22
|
+
def self.run(*a)
|
|
23
|
+
args, opts = args_and_opts(*a)
|
|
24
|
+
recipe = args.first || opts[:recipe]
|
|
25
|
+
if recipe and not opts[:project]
|
|
26
|
+
opts[:project] = File.join(File.dirname(recipe), "..")
|
|
27
|
+
opts[:guessed_project] = true
|
|
28
|
+
end
|
|
29
|
+
opts[:verbosity] ||= Logger::INFO
|
|
30
|
+
if opts[:create]
|
|
31
|
+
Project::create(opts)
|
|
32
|
+
elsif code = opts.delete(:eval)
|
|
33
|
+
interpreter = AutomateIt.new(opts)
|
|
34
|
+
interpreter.instance_eval(code)
|
|
35
|
+
elsif recipe
|
|
36
|
+
AutomateIt.invoke(recipe, opts)
|
|
37
|
+
else
|
|
38
|
+
# Welcome messages
|
|
39
|
+
display = lambda{|msg| puts msg if opts[:verbosity] <= Logger::INFO}
|
|
40
|
+
display.call PNOTE+"AutomateIt Shell v#{AutomateIt::VERSION} #{$0}"
|
|
41
|
+
|
|
42
|
+
# Create and connect instances
|
|
43
|
+
require "irb"
|
|
44
|
+
IRB.setup(__FILE__)
|
|
45
|
+
# XXX irb: warn: can't alias context from irb_context.
|
|
46
|
+
irb = IRB::Irb.new
|
|
47
|
+
opts[:irb] = irb
|
|
48
|
+
IRB.conf[:MAIN_CONTEXT] = irb.context
|
|
49
|
+
interpreter = AutomateIt.new(opts)
|
|
50
|
+
irb.context.workspace.instance_variable_set(:@binding, interpreter.send(:binding))
|
|
51
|
+
|
|
52
|
+
# Tab completion
|
|
53
|
+
begin
|
|
54
|
+
require 'irb/completion'
|
|
55
|
+
irb.context.auto_indent_mode = true
|
|
56
|
+
irb.context.load_modules << 'irb/completion' unless irb.context.load_modules.include?('irb/completion')
|
|
57
|
+
irb.context.instance_eval{ @use_readline = true }
|
|
58
|
+
display.call PNOTE+"<CTRL-D> to quit, <Tab> to auto-complete"
|
|
59
|
+
rescue LoadError
|
|
60
|
+
display.call PNOTE+"<CTRL-D> to quit"
|
|
61
|
+
end
|
|
62
|
+
|
|
63
|
+
# Set prompt
|
|
64
|
+
unless opts[:custom_prompt] == false
|
|
65
|
+
irb.context.prompt_i = "ai> "
|
|
66
|
+
irb.context.prompt_s = "ai%l "
|
|
67
|
+
irb.context.prompt_c = "ai* "
|
|
68
|
+
begin
|
|
69
|
+
irb.context.prompt_n = "ai%i "
|
|
70
|
+
rescue NoMethodError
|
|
71
|
+
# Not available on Ruby 1.8.2 bundled with Mac OS X 10.4 Tiger
|
|
72
|
+
end
|
|
73
|
+
end
|
|
74
|
+
|
|
75
|
+
# Run loop to read user input
|
|
76
|
+
irb.eval_input
|
|
77
|
+
end
|
|
78
|
+
end
|
|
79
|
+
end
|
|
80
|
+
end
|
|
@@ -0,0 +1,65 @@
|
|
|
1
|
+
module AutomateIt
|
|
2
|
+
# == Common
|
|
3
|
+
#
|
|
4
|
+
# Common is the abstract class that most AutomateIt classes inherit from.
|
|
5
|
+
class Common
|
|
6
|
+
include AutomateIt::Constants
|
|
7
|
+
|
|
8
|
+
# Interpreter instance for this class.
|
|
9
|
+
attr_accessor :interpreter
|
|
10
|
+
|
|
11
|
+
# Calls #setup with +options+ for processing.
|
|
12
|
+
def initialize(options={})
|
|
13
|
+
setup(options)
|
|
14
|
+
end
|
|
15
|
+
|
|
16
|
+
# Setup the class. Options:
|
|
17
|
+
# * :interpreter - Set the Interpreter.
|
|
18
|
+
def setup(options={})
|
|
19
|
+
@interpreter = options[:interpreter] if options[:interpreter]
|
|
20
|
+
end
|
|
21
|
+
|
|
22
|
+
#---[ Interpreter aliases ]---------------------------------------------
|
|
23
|
+
|
|
24
|
+
unless defined?(AutomateIt::Interpreter) and AutomateIt::Interpreter === self
|
|
25
|
+
# See Interpreter#log
|
|
26
|
+
def log() @interpreter.log end
|
|
27
|
+
|
|
28
|
+
# See Interpreter#noop=
|
|
29
|
+
def noop=(value) @interpreter.noop=(value) end
|
|
30
|
+
|
|
31
|
+
# See Interpreter#noop
|
|
32
|
+
def noop(value) @interpreter.noop(value) end
|
|
33
|
+
|
|
34
|
+
# See Interpreter#noop?
|
|
35
|
+
def noop?() @interpreter.noop?() end
|
|
36
|
+
|
|
37
|
+
# See Interpreter#writing=
|
|
38
|
+
def writing=(value) @interpreter.writing=(value) end
|
|
39
|
+
|
|
40
|
+
# See Interpreter#writing
|
|
41
|
+
def writing(value) @interpreter.writing(value) end
|
|
42
|
+
|
|
43
|
+
# See Interpreter#writing?
|
|
44
|
+
def writing?() @interpreter.writing?() end
|
|
45
|
+
|
|
46
|
+
# See Interpreter#preview?
|
|
47
|
+
def preview?() @interpreter.preview?() end
|
|
48
|
+
|
|
49
|
+
# See Interpreter#preview
|
|
50
|
+
def preview(value=nil) @interpreter.preview(value) end
|
|
51
|
+
|
|
52
|
+
# See Interpreter#preview=
|
|
53
|
+
def preview=(value) @interpreter.preview=(value) end
|
|
54
|
+
|
|
55
|
+
# See Interpreter#preview_for
|
|
56
|
+
def preview_for(message, &block) @interpreter.preview_for(message, &block) end
|
|
57
|
+
|
|
58
|
+
# See Interpreter#superuser?
|
|
59
|
+
def superuser?() @interpreter.superuser? end
|
|
60
|
+
|
|
61
|
+
# See Interpreter#nitpick
|
|
62
|
+
def nitpick(value=nil) @interpreter.nitpick(value) end
|
|
63
|
+
end
|
|
64
|
+
end
|
|
65
|
+
end
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
module AutomateIt # :nodoc:
|
|
2
|
+
# === AutomateIt::Constants
|
|
3
|
+
#
|
|
4
|
+
# Various constants.
|
|
5
|
+
module AutomateIt::Constants
|
|
6
|
+
# AutomateIt version
|
|
7
|
+
VERSION=Gem::Version.new("0.70923")
|
|
8
|
+
|
|
9
|
+
# Output prefix for command execution, e.g., "** ls -la"
|
|
10
|
+
PEXEC = "** "
|
|
11
|
+
|
|
12
|
+
# Output prefix for notes, e.g., "=> Something happened"
|
|
13
|
+
PNOTE = "=> "
|
|
14
|
+
|
|
15
|
+
# Output prefix for errors, e.g., "!! Something bad happened"
|
|
16
|
+
PERROR = "!! "
|
|
17
|
+
|
|
18
|
+
# Boilerplate to add to tops of generated files, warning people not to edit
|
|
19
|
+
# them directly.
|
|
20
|
+
WARNING_BOILERPLATE = "# +---------------------------------------------------------------------+
|
|
21
|
+
# | WARNING: Do NOT edit this file directly or your changes will be |
|
|
22
|
+
# | lost. If you need to change this file, you must incorporate your |
|
|
23
|
+
# | changes into the AutomateIt project that created it. If you don't |
|
|
24
|
+
# | know what this means, please talk to your system administrator. |
|
|
25
|
+
# +---------------------------------------------------------------------+
|
|
26
|
+
#
|
|
27
|
+
"
|
|
28
|
+
end
|
|
29
|
+
|
|
30
|
+
# Inject constants back into top, providing AutomateIt::VERSION and such.
|
|
31
|
+
module_eval { include Constants }
|
|
32
|
+
end
|
|
33
|
+
|