automate-it 0.9.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (137) hide show
  1. checksums.yaml +7 -0
  2. data/.gitignore +19 -0
  3. data/.hgignore +10 -0
  4. data/.loadpath +5 -0
  5. data/.project +17 -0
  6. data/CHANGES.txt +314 -0
  7. data/Hoe.rake +40 -0
  8. data/Manifest.txt +164 -0
  9. data/README.txt +40 -0
  10. data/Rakefile +256 -0
  11. data/TESTING.txt +57 -0
  12. data/TODO.txt +50 -0
  13. data/TUTORIAL.txt +391 -0
  14. data/automate-it.gemspec +25 -0
  15. data/bin/ai +3 -0
  16. data/bin/aifield +75 -0
  17. data/bin/aissh +93 -0
  18. data/bin/aitag +134 -0
  19. data/bin/automateit +133 -0
  20. data/docs/friendly_errors.txt +50 -0
  21. data/docs/previews.txt +86 -0
  22. data/examples/basic/Rakefile +26 -0
  23. data/examples/basic/config/automateit_env.rb +16 -0
  24. data/examples/basic/config/fields.yml +3 -0
  25. data/examples/basic/config/tags.yml +7 -0
  26. data/examples/basic/dist/README.txt +9 -0
  27. data/examples/basic/dist/myapp_server.erb +30 -0
  28. data/examples/basic/install.log +15 -0
  29. data/examples/basic/lib/README.txt +10 -0
  30. data/examples/basic/recipes/README.txt +4 -0
  31. data/examples/basic/recipes/install.rb +61 -0
  32. data/examples/basic/recipes/uninstall.rb +6 -0
  33. data/gpl.txt +674 -0
  34. data/helpers/cpan_wrapper.pl +220 -0
  35. data/helpers/which.cmd +7 -0
  36. data/lib/automateit.rb +55 -0
  37. data/lib/automateit/account_manager.rb +114 -0
  38. data/lib/automateit/account_manager/base.rb +138 -0
  39. data/lib/automateit/account_manager/etc.rb +128 -0
  40. data/lib/automateit/account_manager/nscd.rb +33 -0
  41. data/lib/automateit/account_manager/passwd_expect.rb +40 -0
  42. data/lib/automateit/account_manager/passwd_pty.rb +69 -0
  43. data/lib/automateit/account_manager/posix.rb +138 -0
  44. data/lib/automateit/address_manager.rb +88 -0
  45. data/lib/automateit/address_manager/base.rb +171 -0
  46. data/lib/automateit/address_manager/bsd.rb +28 -0
  47. data/lib/automateit/address_manager/freebsd.rb +59 -0
  48. data/lib/automateit/address_manager/linux.rb +42 -0
  49. data/lib/automateit/address_manager/openbsd.rb +66 -0
  50. data/lib/automateit/address_manager/portable.rb +37 -0
  51. data/lib/automateit/address_manager/sunos.rb +34 -0
  52. data/lib/automateit/cli.rb +85 -0
  53. data/lib/automateit/common.rb +65 -0
  54. data/lib/automateit/constants.rb +35 -0
  55. data/lib/automateit/download_manager.rb +48 -0
  56. data/lib/automateit/edit_manager.rb +321 -0
  57. data/lib/automateit/error.rb +10 -0
  58. data/lib/automateit/field_manager.rb +103 -0
  59. data/lib/automateit/interpreter.rb +631 -0
  60. data/lib/automateit/package_manager.rb +257 -0
  61. data/lib/automateit/package_manager/apt.rb +27 -0
  62. data/lib/automateit/package_manager/cpan.rb +101 -0
  63. data/lib/automateit/package_manager/dpkg.rb +54 -0
  64. data/lib/automateit/package_manager/egg.rb +64 -0
  65. data/lib/automateit/package_manager/gem.rb +201 -0
  66. data/lib/automateit/package_manager/pear.rb +95 -0
  67. data/lib/automateit/package_manager/pecl.rb +80 -0
  68. data/lib/automateit/package_manager/portage.rb +69 -0
  69. data/lib/automateit/package_manager/yum.rb +65 -0
  70. data/lib/automateit/platform_manager.rb +49 -0
  71. data/lib/automateit/platform_manager/darwin.rb +30 -0
  72. data/lib/automateit/platform_manager/debian.rb +26 -0
  73. data/lib/automateit/platform_manager/freebsd.rb +29 -0
  74. data/lib/automateit/platform_manager/gentoo.rb +26 -0
  75. data/lib/automateit/platform_manager/lsb.rb +44 -0
  76. data/lib/automateit/platform_manager/openbsd.rb +28 -0
  77. data/lib/automateit/platform_manager/struct.rb +80 -0
  78. data/lib/automateit/platform_manager/sunos.rb +39 -0
  79. data/lib/automateit/platform_manager/uname.rb +29 -0
  80. data/lib/automateit/platform_manager/windows.rb +40 -0
  81. data/lib/automateit/plugin.rb +7 -0
  82. data/lib/automateit/plugin/base.rb +32 -0
  83. data/lib/automateit/plugin/driver.rb +256 -0
  84. data/lib/automateit/plugin/manager.rb +224 -0
  85. data/lib/automateit/project.rb +493 -0
  86. data/lib/automateit/root.rb +17 -0
  87. data/lib/automateit/service_manager.rb +93 -0
  88. data/lib/automateit/service_manager/chkconfig.rb +39 -0
  89. data/lib/automateit/service_manager/rc_update.rb +37 -0
  90. data/lib/automateit/service_manager/sysv.rb +139 -0
  91. data/lib/automateit/service_manager/update_rcd.rb +35 -0
  92. data/lib/automateit/shell_manager.rb +316 -0
  93. data/lib/automateit/shell_manager/base_link.rb +67 -0
  94. data/lib/automateit/shell_manager/link.rb +24 -0
  95. data/lib/automateit/shell_manager/portable.rb +523 -0
  96. data/lib/automateit/shell_manager/symlink.rb +32 -0
  97. data/lib/automateit/shell_manager/which_base.rb +30 -0
  98. data/lib/automateit/shell_manager/which_unix.rb +16 -0
  99. data/lib/automateit/shell_manager/which_windows.rb +20 -0
  100. data/lib/automateit/tag_manager.rb +127 -0
  101. data/lib/automateit/tag_manager/struct.rb +121 -0
  102. data/lib/automateit/tag_manager/tag_parser.rb +93 -0
  103. data/lib/automateit/tag_manager/yaml.rb +29 -0
  104. data/lib/automateit/template_manager.rb +56 -0
  105. data/lib/automateit/template_manager/base.rb +181 -0
  106. data/lib/automateit/template_manager/erb.rb +17 -0
  107. data/lib/ext/metaclass.rb +17 -0
  108. data/lib/ext/object.rb +18 -0
  109. data/lib/ext/shell_escape.rb +7 -0
  110. data/lib/hashcache.rb +22 -0
  111. data/lib/helpful_erb.rb +63 -0
  112. data/lib/inactive_support.rb +53 -0
  113. data/lib/inactive_support/basic_object.rb +6 -0
  114. data/lib/inactive_support/clean_logger.rb +127 -0
  115. data/lib/inactive_support/core_ext/array/extract_options.rb +19 -0
  116. data/lib/inactive_support/core_ext/blank.rb +50 -0
  117. data/lib/inactive_support/core_ext/class/attribute_accessors.rb +48 -0
  118. data/lib/inactive_support/core_ext/class/inheritable_attributes.rb +140 -0
  119. data/lib/inactive_support/core_ext/enumerable.rb +63 -0
  120. data/lib/inactive_support/core_ext/hash/keys.rb +54 -0
  121. data/lib/inactive_support/core_ext/module/aliasing.rb +70 -0
  122. data/lib/inactive_support/core_ext/numeric/time.rb +91 -0
  123. data/lib/inactive_support/core_ext/string/inflections.rb +153 -0
  124. data/lib/inactive_support/core_ext/symbol.rb +14 -0
  125. data/lib/inactive_support/core_ext/time/conversions.rb +96 -0
  126. data/lib/inactive_support/duration.rb +96 -0
  127. data/lib/inactive_support/inflections.rb +53 -0
  128. data/lib/inactive_support/inflector.rb +282 -0
  129. data/lib/nested_error.rb +33 -0
  130. data/lib/nitpick.rb +33 -0
  131. data/lib/queued_logger.rb +68 -0
  132. data/lib/tempster.rb +250 -0
  133. data/misc/index_gem_repository.rb +304 -0
  134. data/misc/setup_egg.rb +12 -0
  135. data/misc/setup_gem_dependencies.sh +6 -0
  136. data/misc/setup_rubygems.sh +21 -0
  137. metadata +279 -0
@@ -0,0 +1,171 @@
1
+ # == AddressManager::BaseDriver
2
+ #
3
+ # Base class for all AddressManager drivers.
4
+ class AutomateIt::AddressManager::BaseDriver< AutomateIt::Plugin::Driver
5
+ public
6
+
7
+ # See AddressManager#hostnames
8
+ def hostnames()
9
+ # NOTE: depends on driver's implementation of addresses
10
+ names = manager.addresses.inject(Set.new) do |sum, address|
11
+ # Some addresses can't be resolved, bummer.
12
+ sum.merge(Resolv.getnames(address)) rescue Resolv::ResolvError; sum
13
+ end
14
+ names << Socket.gethostname
15
+ names.merge(Socket.gethostbyname(Socket.gethostname)[1]) rescue SocketError
16
+
17
+ names.each{|name| names.merge(hostnames_for(name))}
18
+ names << "localhost"
19
+ return names.to_a.sort
20
+ end
21
+
22
+ # See AddressManager#hostname_for
23
+ def hostnames_for(hostname)
24
+ results = []
25
+ elements = hostname.split(".")
26
+ for i in 1..elements.size
27
+ results << elements[0..i-1].join(".")
28
+ end
29
+ return results.to_a.sort
30
+ end
31
+
32
+ # See AddressManager#has?
33
+ def has?(opts)
34
+ raise ArgumentError.new(":device or :address must be specified") unless opts[:device] or opts[:address]
35
+ result = true
36
+ result &= manager.interfaces.include?(opts[:device]) if opts[:device] and not opts[:label]
37
+ result &= manager.interfaces.include?(opts[:device]+":"+opts[:label]) if opts[:device] and opts[:label]
38
+ result &= manager.addresses.include?(opts[:address]) if opts[:address]
39
+ return result
40
+ end
41
+
42
+ #-----------------------------------------------------------------------
43
+
44
+ protected
45
+
46
+ # Convert a mask to a CIDR.
47
+ #
48
+ # Example:
49
+ # mask_to_cidr("255.255.255.0") # => 24
50
+ def mask_to_cidr(mask)
51
+ # TODO Find less horrible solution which can handle IPv6.
52
+ result = ''
53
+ for chunk in mask.split(".")
54
+ result += dec2bin(chunk.to_i)
55
+ end
56
+ return result.scan(/1/).size
57
+ end
58
+
59
+ # Convert CIDR to mask.
60
+ #
61
+ # Example:
62
+ # cidr_to_mask(24) # => "255.255.255.0"
63
+ def cidr_to_mask(cidr)
64
+ # TODO Find less horrible solution which can handle IPv6.
65
+ require 'ipaddr'
66
+ IPAddr.new("0.0.0.0/#{cidr}").inspect.match(%r{/([\d\.]+)>})[1]
67
+ end
68
+
69
+ # Convert a decimal number to binary notation.
70
+ #
71
+ # Example:
72
+ # dec2bin(255) # => "11111111"
73
+ def dec2bin(n)
74
+ # dec2bin(255)
75
+ return "%b" % n
76
+ end
77
+
78
+ # Convert a binary number to decimal.
79
+ #
80
+ # Example:
81
+ # bin2dec("11111111") # => 255
82
+ def bin2dec(s)
83
+ return s.to_i(2)
84
+ end
85
+
86
+ # Helper for #add method.
87
+ def _add_helper(opts, &block)
88
+ opts[:announcements] = opts[:announcements].to_i || AutomateIt::AddressManager::DEFAULT_ANNOUNCEMENTS
89
+ raise SecurityError.new("you must be root") unless superuser?
90
+ raise ArgumentError.new(":device and :address must be specified") unless opts[:device] and opts[:address]
91
+ return false if manager.has?(opts)
92
+ block.call(opts)
93
+ return true
94
+ end
95
+
96
+ # Helper for #remove method.
97
+ def _remove_helper(opts, &block)
98
+ return false unless manager.has?(opts)
99
+ raise SecurityError.new("you must be root") unless superuser?
100
+ raise ArgumentError.new(":device and :address must be specified") unless opts[:device] and opts[:address]
101
+ return block.call(opts)
102
+ end
103
+
104
+ # Alter +opts+ hash to add alternative names for various options.
105
+ def _normalize_opts(opts)
106
+ # Accept common alternative names
107
+ opts[:mask] ||= opts[:netmask] if opts[:netmask]
108
+ opts[:alias] ||= opts[:alias] if opts[:alias]
109
+ opts[:device] ||= opts[:interface] if opts[:interface]
110
+
111
+ if opts[:mask] and not opts[:mask].match(/\./)
112
+ opts[:mask] = cidr_to_mask(opts[:mask])
113
+ end
114
+
115
+ return opts
116
+ end
117
+
118
+ # Return the interface and label specified in +opts+ hash, e.g., "eth0:1".
119
+ def _interface_and_label(opts)
120
+ return(
121
+ if opts[:device] and not opts[:label]
122
+ opts[:device]
123
+ elsif opts[:device] and opts[:label]
124
+ "%s:%s" % [opts[:device], opts[:label]]
125
+ else
126
+ raise ArgumentError.new("Can't derive interface and label for: #{opts.inspect}")
127
+ end
128
+ )
129
+ end
130
+
131
+ # Returns a string used to construct an ifconfig command, e.g.
132
+ # ifconfig hme0 192.9.2.106 netmask 255.255.255.0 up
133
+ # ifconfig hme0:1 172.40.30.4 netmask 255.255.0.0 up
134
+ #
135
+ # Options:
136
+ # * :device -- Interface, e.g., "eth0". String.
137
+ # * :label -- Alias label, e.g., "1". String.
138
+ # * :address -- IP address, e.g., "127.0.0.1". String.
139
+ # * :mask -- Netmask, e.g., "255.255.255.0" or 24. String or Fixnum.
140
+ #
141
+ # Helper options:
142
+ # * :append -- Array of strings to append to end of command, e.g., ["-alias"].
143
+ # * :prepend -- Array of strings to prepend to string, adding them after after "ifconfig", e.g., ["inet"].
144
+ # * :state -- Whether to list "up" and "down" in command. Defaults to true.
145
+ def _ifconfig_helper(action, opts, helper_opts={})
146
+ _raise_unless_available
147
+
148
+ # Translate common names
149
+ action = :del if action.to_sym == :remove
150
+
151
+ # Defaults
152
+ _normalize_opts(opts)
153
+ helper_opts[:state] = true unless helper_opts[:state] == false
154
+
155
+ ipcmd = "ifconfig"
156
+ ipcmd << " " << _interface_and_label(opts)
157
+ if helper_opts[:prepend]
158
+ ipcmd << " " << [helper_opts[:prepend]].flatten.join(" ")
159
+ end
160
+ ipcmd << " %s" % opts[:address]
161
+ ipcmd << " netmask %s" % opts[:mask] if opts[:mask]
162
+ if helper_opts[:state]
163
+ ipcmd << " up" if action == :add
164
+ ipcmd << " down" if action == :del
165
+ end
166
+ if helper_opts[:append]
167
+ ipcmd << " " << [helper_opts[:append]].flatten.join(" ")
168
+ end
169
+ return ipcmd
170
+ end
171
+ end
@@ -0,0 +1,28 @@
1
+ # == AddressManager::BSD
2
+ #
3
+ # An AddressManager driver for operating systems using a BSD-like ifconfig.
4
+ # Driver provides querying addresses and interfaces.
5
+ class AutomateIt::AddressManager::BSD < AutomateIt::AddressManager::BaseDriver
6
+ def self.token
7
+ :bsd
8
+ end
9
+
10
+ depends_on :programs => %w(ifconfig uname),
11
+ :callbacks => lambda{`uname -s 2>&1`.match(/openbsd|freebsd|sunos/i)}
12
+
13
+ def suitability(method, *args) # :nodoc:
14
+ available? ? 2 : 0
15
+ end
16
+
17
+ # See AddressManager#interfaces
18
+ def interfaces()
19
+ _raise_unless_available
20
+ return `ifconfig -a`.scan(/^([^\s]+):\s+/s).flatten
21
+ end
22
+
23
+ # See AddressManager#addresses
24
+ def addresses()
25
+ _raise_unless_available
26
+ return `ifconfig -a`.scan(/\s+inet\s+([^\s]+)\s+/).flatten
27
+ end
28
+ end
@@ -0,0 +1,59 @@
1
+ # == AddressManager::FreeBSD
2
+ #
3
+ # A FreeBSD-specific driver for the AddressManager provides complete support for
4
+ # querying, adding and removing addresses.
5
+ class AutomateIt::AddressManager::FreeBSD < AutomateIt::AddressManager::BaseDriver
6
+ def self.token
7
+ :freebsd
8
+ end
9
+
10
+ depends_on :programs => %w(ifconfig uname),
11
+ :callbacks => lambda{`uname -s 2>&1`.match(/freebsd/i)}
12
+
13
+ def suitability(method, *args) # :nodoc:
14
+ # Must be higher than AddressManager::BSD
15
+ available? ? 3 : 0
16
+ end
17
+
18
+ # See AddressManager#add
19
+ def add(opts)
20
+ _add_helper(opts) do |opts|
21
+ interpreter.sh(_freebsd_ifconfig_helper(:add, opts))
22
+ end
23
+ end
24
+
25
+ # See AddressManager#remove
26
+ def remove(opts)
27
+ _remove_helper(opts) do |opts|
28
+ interpreter.sh(_freebsd_ifconfig_helper(:remove, opts))
29
+ true
30
+ end
31
+ end
32
+
33
+ # See AddressManager#has?
34
+ def has?(opts)
35
+ opts2 = opts.clone
36
+ is_alias = opts2.delete(:label)
37
+ return super(opts2)
38
+ end
39
+
40
+ protected
41
+
42
+ # ifconfig fxp0 inet 172.16.1.3 netmask 255.255.255.255 alias
43
+ def _freebsd_ifconfig_helper(action, opts)
44
+ helper_opts = {:state => false, :prepend => %w(inet)}
45
+ opts2 = opts.clone
46
+ if opts2.delete(:label)
47
+ helper_opts[:append] = \
48
+ case action
49
+ when :add
50
+ %w(alias)
51
+ when :remove, :del
52
+ %w(-alias)
53
+ else
54
+ ArgumentError.new("Unknown action: #{action}")
55
+ end
56
+ end
57
+ return _ifconfig_helper(action, opts2, helper_opts)
58
+ end
59
+ end
@@ -0,0 +1,42 @@
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#add
15
+ def add(opts)
16
+ _add_helper(opts) do |opts|
17
+ interpreter.sh(_ifconfig_helper(:add, opts))
18
+ if interpreter.which("arping")
19
+ interpreter.sh("arping -q -c #{opts[:announcements]} -w #{opts[:announcements]} -I #{opts[:device]} #{opts[:address]}")
20
+ end
21
+ end
22
+ end
23
+
24
+ # See AddressManager#remove
25
+ def remove(opts)
26
+ _remove_helper(opts) do |opts|
27
+ interpreter.sh(_ifconfig_helper(:remove, opts))
28
+ end
29
+ end
30
+
31
+ # See AddressManager#interfaces
32
+ def interfaces()
33
+ _raise_unless_available
34
+ return `ifconfig`.scan(/^(\w+?(?::\w+)?)\b\s+Link/).flatten
35
+ end
36
+
37
+ # See AddressManager#addresses
38
+ def addresses()
39
+ _raise_unless_available
40
+ return `ifconfig`.scan(/inet6? addr:\s*(.+?)\s+/).flatten
41
+ end
42
+ end
@@ -0,0 +1,66 @@
1
+ # == AddressManager::OpenBSD
2
+ #
3
+ # A OpenBSD-specific driver for the AddressManager provides complete support for
4
+ # querying, adding and removing addresses.
5
+ class AutomateIt::AddressManager::OpenBSD < AutomateIt::AddressManager::BaseDriver
6
+ def self.token
7
+ :openbsd
8
+ end
9
+
10
+ depends_on :programs => %w(ifconfig uname),
11
+ :callbacks => lambda{`uname -s 2>&1`.match(/openbsd/i)}
12
+
13
+ def suitability(method, *args) # :nodoc:
14
+ # Must be higher than AddressManager::BSD
15
+ available? ? 3 : 0
16
+ end
17
+
18
+ # See AddressManager#add
19
+ def add(opts)
20
+ _add_helper(opts) do |opts|
21
+ interpreter.sh(_openbsd_ifconfig_helper(:add, opts))
22
+ end
23
+ end
24
+
25
+ # See AddressManager#remove
26
+ def remove(opts)
27
+ _remove_helper(opts) do |opts|
28
+ interpreter.sh(_openbsd_ifconfig_helper(:remove, opts))
29
+ true
30
+ end
31
+ end
32
+
33
+ # See AddressManager#addresses
34
+ def addresses()
35
+ _raise_unless_available
36
+ # OpenBSD requires an "-A" to display aliases, not the usual "-a"
37
+ return `ifconfig -A`.scan(/\s+inet\s+([^\s]+)\s+/).flatten
38
+ end
39
+
40
+ # See AddressManager#has?
41
+ def has?(opts)
42
+ opts2 = opts.clone
43
+ is_alias = opts2.delete(:label)
44
+ return super(opts2)
45
+ end
46
+
47
+ protected
48
+
49
+ # ifconfig dc0 inet alias 192.168.0.3 netmask 255.255.255.255
50
+ def _openbsd_ifconfig_helper(action, opts)
51
+ helper_opts = {:state => false, :prepend => %w(inet)}
52
+ opts2 = opts.clone
53
+ if opts2.delete(:label)
54
+ helper_opts[:prepend] << \
55
+ case action
56
+ when :add
57
+ "alias"
58
+ when :remove, :del
59
+ "delete"
60
+ else
61
+ ArgumentError.new("Unknown action: #{action}")
62
+ end
63
+ end
64
+ return _ifconfig_helper(action, opts2, helper_opts)
65
+ end
66
+ 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,34 @@
1
+ # == AddressManager::SunOS
2
+ #
3
+ # A SunOS-specific driver for the AddressManager provides complete support for
4
+ # querying, adding and removing addresses.
5
+ class AutomateIt::AddressManager::SunOS < AutomateIt::AddressManager::BaseDriver
6
+ def self.token
7
+ :sunos
8
+ end
9
+
10
+ depends_on :programs => %w(ifconfig uname),
11
+ :callbacks => lambda{`uname -s 2>&1`.match(/sunos/i)}
12
+
13
+ def suitability(method, *args) # :nodoc:
14
+ # Must be higher than AddressManager::BSD
15
+ available? ? 3 : 0
16
+ end
17
+
18
+ # See AddressManager#add
19
+ def add(opts)
20
+ _add_helper(opts) do |opts|
21
+ interpreter.sh("ifconfig %s plumb" % _interface_and_label(opts))
22
+ interpreter.sh(_ifconfig_helper(:add, opts))
23
+ end
24
+ end
25
+
26
+ # See AddressManager#remove
27
+ def remove(opts)
28
+ _remove_helper(opts) do |opts|
29
+ interpreter.sh(_ifconfig_helper(:remove, opts))
30
+ interpreter.sh("ifconfig %s unplumb" % _interface_and_label(opts))
31
+ true
32
+ end
33
+ end
34
+ end
@@ -0,0 +1,85 @@
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
+ # * :tags -- Array of tags to add for this run.
19
+ # * :project -- Project directory to load.
20
+ # * :recipe -- Recipe file to execute.
21
+ # * :eval -- Evaluate this string.
22
+ # * :quiet -- Don't print shell header.
23
+ def self.run(*a)
24
+ args, opts = args_and_opts(*a)
25
+ recipe = args.first || opts[:recipe]
26
+ if recipe and not opts[:project]
27
+ opts[:project] = File.join(File.dirname(recipe), "..")
28
+ opts[:guessed_project] = true
29
+ end
30
+
31
+ opts[:verbosity] ||= Logger::INFO
32
+
33
+ if opts[:create]
34
+ Project::create(opts)
35
+ elsif code = opts.delete(:eval)
36
+ interpreter = AutomateIt.new(opts)
37
+ interpreter.instance_eval(code)
38
+ elsif recipe
39
+ AutomateIt.invoke(recipe, opts)
40
+ else
41
+ # Welcome messages
42
+ display = lambda{|msg| puts msg if opts[:verbosity] <= Logger::INFO}
43
+ display.call PNOTE+"AutomateIt Shell v#{AutomateIt::VERSION} #{$0}"
44
+
45
+ # Create and connect instances
46
+ require "irb"
47
+ IRB.setup(__FILE__)
48
+ # XXX irb: warn: can't alias context from irb_context.
49
+ irb = IRB::Irb.new
50
+ opts[:irb] = irb
51
+ IRB.conf[:MAIN_CONTEXT] = irb.context
52
+ interpreter = AutomateIt.new(opts)
53
+ irb.context.workspace.instance_variable_set(:@binding, interpreter.send(:binding))
54
+
55
+ # Tab completion
56
+ message = "<CTRL-D> to quit"
57
+ begin
58
+ require 'irb/completion'
59
+ irb.context.auto_indent_mode = true
60
+ irb.context.load_modules << 'irb/completion' unless irb.context.load_modules.include?('irb/completion')
61
+ irb.context.instance_eval{ @use_readline = true }
62
+ message << ", <Tab> to auto-complete"
63
+ rescue LoadError
64
+ # Ignore
65
+ end
66
+ display.call PNOTE+message
67
+
68
+ # Set prompt
69
+ unless opts[:custom_prompt] == false
70
+ irb.context.prompt_i = "ai> "
71
+ irb.context.prompt_s = "ai%l "
72
+ irb.context.prompt_c = "ai* "
73
+ begin
74
+ irb.context.prompt_n = "ai%i "
75
+ rescue NoMethodError
76
+ # Not available on Ruby 1.8.2 bundled with Mac OS X 10.4 Tiger
77
+ end
78
+ end
79
+
80
+ # Run loop to read user input
81
+ irb.eval_input
82
+ end
83
+ end
84
+ end
85
+ end