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.
Files changed (119) hide show
  1. data.tar.gz.sig +1 -0
  2. data/CHANGES.txt +100 -0
  3. data/Hoe.rake +35 -0
  4. data/Manifest.txt +111 -0
  5. data/README.txt +44 -0
  6. data/Rakefile +284 -0
  7. data/TESTING.txt +57 -0
  8. data/TODO.txt +26 -0
  9. data/TUTORIAL.txt +390 -0
  10. data/bin/ai +3 -0
  11. data/bin/aifield +82 -0
  12. data/bin/aitag +128 -0
  13. data/bin/automateit +117 -0
  14. data/docs/friendly_errors.txt +50 -0
  15. data/docs/previews.txt +86 -0
  16. data/env.sh +4 -0
  17. data/examples/basic/Rakefile +26 -0
  18. data/examples/basic/config/automateit_env.rb +16 -0
  19. data/examples/basic/config/fields.yml +3 -0
  20. data/examples/basic/config/tags.yml +13 -0
  21. data/examples/basic/dist/README.txt +9 -0
  22. data/examples/basic/dist/myapp_server.erb +30 -0
  23. data/examples/basic/install.log +15 -0
  24. data/examples/basic/lib/README.txt +10 -0
  25. data/examples/basic/recipes/README.txt +4 -0
  26. data/examples/basic/recipes/install.rb +53 -0
  27. data/examples/basic/recipes/uninstall.rb +6 -0
  28. data/gpl.txt +674 -0
  29. data/lib/automateit.rb +66 -0
  30. data/lib/automateit/account_manager.rb +106 -0
  31. data/lib/automateit/account_manager/linux.rb +171 -0
  32. data/lib/automateit/account_manager/passwd.rb +69 -0
  33. data/lib/automateit/account_manager/portable.rb +136 -0
  34. data/lib/automateit/address_manager.rb +165 -0
  35. data/lib/automateit/address_manager/linux.rb +80 -0
  36. data/lib/automateit/address_manager/portable.rb +37 -0
  37. data/lib/automateit/cli.rb +80 -0
  38. data/lib/automateit/common.rb +65 -0
  39. data/lib/automateit/constants.rb +33 -0
  40. data/lib/automateit/edit_manager.rb +292 -0
  41. data/lib/automateit/error.rb +10 -0
  42. data/lib/automateit/field_manager.rb +103 -0
  43. data/lib/automateit/interpreter.rb +641 -0
  44. data/lib/automateit/package_manager.rb +242 -0
  45. data/lib/automateit/package_manager/apt.rb +63 -0
  46. data/lib/automateit/package_manager/egg.rb +64 -0
  47. data/lib/automateit/package_manager/gem.rb +179 -0
  48. data/lib/automateit/package_manager/portage.rb +69 -0
  49. data/lib/automateit/package_manager/yum.rb +65 -0
  50. data/lib/automateit/platform_manager.rb +47 -0
  51. data/lib/automateit/platform_manager/darwin.rb +30 -0
  52. data/lib/automateit/platform_manager/debian.rb +26 -0
  53. data/lib/automateit/platform_manager/freebsd.rb +25 -0
  54. data/lib/automateit/platform_manager/gentoo.rb +26 -0
  55. data/lib/automateit/platform_manager/lsb.rb +40 -0
  56. data/lib/automateit/platform_manager/struct.rb +78 -0
  57. data/lib/automateit/platform_manager/uname.rb +29 -0
  58. data/lib/automateit/platform_manager/windows.rb +33 -0
  59. data/lib/automateit/plugin.rb +7 -0
  60. data/lib/automateit/plugin/base.rb +32 -0
  61. data/lib/automateit/plugin/driver.rb +218 -0
  62. data/lib/automateit/plugin/manager.rb +232 -0
  63. data/lib/automateit/project.rb +460 -0
  64. data/lib/automateit/root.rb +14 -0
  65. data/lib/automateit/service_manager.rb +79 -0
  66. data/lib/automateit/service_manager/chkconfig.rb +39 -0
  67. data/lib/automateit/service_manager/rc_update.rb +37 -0
  68. data/lib/automateit/service_manager/sysv.rb +126 -0
  69. data/lib/automateit/service_manager/update_rcd.rb +35 -0
  70. data/lib/automateit/shell_manager.rb +261 -0
  71. data/lib/automateit/shell_manager/base_link.rb +67 -0
  72. data/lib/automateit/shell_manager/link.rb +24 -0
  73. data/lib/automateit/shell_manager/portable.rb +421 -0
  74. data/lib/automateit/shell_manager/symlink.rb +32 -0
  75. data/lib/automateit/shell_manager/which.rb +25 -0
  76. data/lib/automateit/tag_manager.rb +63 -0
  77. data/lib/automateit/tag_manager/struct.rb +101 -0
  78. data/lib/automateit/tag_manager/tag_parser.rb +91 -0
  79. data/lib/automateit/tag_manager/yaml.rb +29 -0
  80. data/lib/automateit/template_manager.rb +55 -0
  81. data/lib/automateit/template_manager/base.rb +172 -0
  82. data/lib/automateit/template_manager/erb.rb +17 -0
  83. data/lib/ext/metaclass.rb +17 -0
  84. data/lib/ext/object.rb +18 -0
  85. data/lib/hashcache.rb +22 -0
  86. data/lib/helpful_erb.rb +63 -0
  87. data/lib/nested_error.rb +33 -0
  88. data/lib/queued_logger.rb +68 -0
  89. data/lib/tempster.rb +239 -0
  90. data/misc/index_gem_repository.rb +303 -0
  91. data/misc/setup_egg.rb +12 -0
  92. data/misc/setup_gem_dependencies.sh +7 -0
  93. data/misc/setup_rubygems.sh +21 -0
  94. data/misc/which.cmd +6 -0
  95. data/spec/extras/automateit_service_sysv_test +50 -0
  96. data/spec/extras/scratch.rb +15 -0
  97. data/spec/extras/simple_recipe.rb +8 -0
  98. data/spec/integration/account_manager_spec.rb +218 -0
  99. data/spec/integration/address_manager_linux_spec.rb +119 -0
  100. data/spec/integration/address_manager_portable_spec.rb +30 -0
  101. data/spec/integration/cli_spec.rb +215 -0
  102. data/spec/integration/examples_spec.rb +54 -0
  103. data/spec/integration/examples_spec_editor.rb +71 -0
  104. data/spec/integration/package_manager_spec.rb +104 -0
  105. data/spec/integration/platform_manager_spec.rb +69 -0
  106. data/spec/integration/service_manager_sysv_spec.rb +115 -0
  107. data/spec/integration/shell_manager_spec.rb +471 -0
  108. data/spec/integration/template_manager_erb_spec.rb +31 -0
  109. data/spec/spec_helper.rb +23 -0
  110. data/spec/unit/edit_manager_spec.rb +162 -0
  111. data/spec/unit/field_manager_spec.rb +79 -0
  112. data/spec/unit/hashcache_spec.rb +28 -0
  113. data/spec/unit/interpreter_spec.rb +98 -0
  114. data/spec/unit/platform_manager_spec.rb +44 -0
  115. data/spec/unit/plugins_spec.rb +253 -0
  116. data/spec/unit/tag_manager_spec.rb +189 -0
  117. data/spec/unit/template_manager_erb_spec.rb +137 -0
  118. metadata +249 -0
  119. metadata.gz.sig +0 -0
@@ -0,0 +1,303 @@
1
+ #!/usr/bin/env jruby
2
+ # http://svn.codehaus.org/jruby/trunk/jruby/bin/index_gem_repository.rb
3
+ #--
4
+ # Copyright 2006 by Chad Fowler, Rich Kilmer, Jim Weirich and others.
5
+ # All rights reserved.
6
+ # See LICENSE.txt for permissions.
7
+ #++
8
+
9
+
10
+ # Generate the yaml/yaml.Z index files for a gem server directory.
11
+ #
12
+ # Usage: generate_yaml_index.rb --dir DIR [--verbose]
13
+
14
+ $:.unshift '~/rubygems' if File.exist? "~/rubygems"
15
+
16
+ require 'optparse'
17
+ require 'rubygems'
18
+ require 'zlib'
19
+ require 'digest/sha2'
20
+ begin
21
+ require 'builder/xchar'
22
+ rescue LoadError
23
+ fail "index_gem_repository requires that the XML Builder library be installed"
24
+ end
25
+
26
+ Gem.manage_gems
27
+
28
+ ######################################################################
29
+ # Mixin that provides a +compress+ method for compressing files on
30
+ # disk.
31
+ #
32
+ module Compressor
33
+ # Compress the given file.
34
+ def compress(filename, ext="rz")
35
+ File.open(filename + ".#{ext}", "w") do |file|
36
+ file.write(zip(File.read(filename)))
37
+ end
38
+ end
39
+
40
+ # Return a compressed version of the given string.
41
+ def zip(string)
42
+ Zlib::Deflate.deflate(string)
43
+ end
44
+
45
+ # Return an uncompressed version of a compressed string.
46
+ def unzip(string)
47
+ Zlib::Inflate.inflate(string)
48
+ end
49
+ end
50
+
51
+ ######################################################################
52
+ # Announcer provides a way of announcing activities to the user.
53
+ #
54
+ module Announcer
55
+ # Announce +msg+ to the user.
56
+ def announce(msg)
57
+ puts msg if @options[:verbose]
58
+ end
59
+ end
60
+
61
+ ######################################################################
62
+ # Abstract base class for building gem indicies. Uses the template
63
+ # pattern with subclass specialization in the +begin_index+,
64
+ # +end_index+ and +cleanup+ methods.
65
+ #
66
+ class AbstractIndexBuilder
67
+ include Compressor
68
+ include Announcer
69
+
70
+ # Build a Gem index. Yields to block to handle the details of the
71
+ # actual building. Calls +begin_index+, # +end_index+ and +cleanup+
72
+ # at appropriate times to customize basic operations.
73
+ def build
74
+ if ! @enabled
75
+ yield
76
+ else
77
+ unless File.exist?(@directory)
78
+ FileUtils.mkdir_p(@directory)
79
+ end
80
+ fail "not a directory: #{@directory}" unless File.directory?(@directory)
81
+ File.open(File.join(@directory, @filename), "w") do |file|
82
+ @file = file
83
+ start_index
84
+ yield
85
+ end_index
86
+ end
87
+ cleanup
88
+ end
89
+ ensure
90
+ @file = nil
91
+ end
92
+
93
+ # Called immediately before the yield in build. The index file is
94
+ # open and availabe as @file.
95
+ def start_index
96
+ end
97
+
98
+ # Called immediately after the yield in build. The index file is
99
+ # still open and available as @file.
100
+ def end_index
101
+ end
102
+
103
+ # Called from within builder after the index file has been closed.
104
+ def cleanup
105
+ end
106
+ end
107
+
108
+ ######################################################################
109
+ # Construct the master Gem index file.
110
+ #
111
+ class MasterIndexBuilder < AbstractIndexBuilder
112
+ def initialize(filename, options)
113
+ @filename = filename
114
+ @options = options
115
+ @directory = options[:directory]
116
+ @enabled = true
117
+ end
118
+
119
+ def start_index
120
+ super
121
+ @file.puts "--- !ruby/object:Gem::Cache"
122
+ @file.puts "gems:"
123
+ end
124
+
125
+ def cleanup
126
+ super
127
+ index_file_name = File.join(@directory, @filename)
128
+ compress(index_file_name, "Z")
129
+ paranoid(index_file_name, "#{index_file_name}.Z")
130
+ end
131
+
132
+ def add(spec)
133
+ @file.puts " #{spec.full_name}: #{nest(spec.to_yaml)}"
134
+ end
135
+
136
+ def nest(yaml_string)
137
+ yaml_string[4..-1].gsub(/\n/, "\n ")
138
+ end
139
+
140
+ private
141
+
142
+ def paranoid(fn, compressed_fn)
143
+ data = File.read(fn)
144
+ compressed_data = File.read(compressed_fn)
145
+ if data != unzip(compressed_data)
146
+ fail "Compressed file #{compressed_fn} does not match uncompressed file #{fn}"
147
+ end
148
+ end
149
+ end
150
+
151
+ ######################################################################
152
+ # Construct a quick index file and all of the individual specs to
153
+ # support incremental loading.
154
+ #
155
+ class QuickIndexBuilder < AbstractIndexBuilder
156
+ def initialize(filename, options)
157
+ @filename = filename
158
+ @options = options
159
+ @directory = options[:quick_directory]
160
+ @enabled = options[:quick]
161
+ end
162
+
163
+ def cleanup
164
+ compress(File.join(@directory, @filename))
165
+ end
166
+
167
+ def add(spec)
168
+ return unless @enabled
169
+ @file.puts spec.full_name
170
+ fn = File.join(@directory, "#{spec.full_name}.gemspec.rz")
171
+ File.open(fn, "w") do |gsfile|
172
+ gsfile.write(zip(spec.to_yaml))
173
+ end
174
+ end
175
+ end
176
+
177
+ ######################################################################
178
+ # Top level class for building the repository index. Initialize with
179
+ # an options hash and call +build_index+.
180
+ #
181
+ class Indexer
182
+ include Compressor
183
+ include Announcer
184
+
185
+ # Create an indexer with the options specified by the options hash.
186
+ def initialize(options)
187
+ @options = options.dup
188
+ @directory = @options[:directory]
189
+ @options[:quick_directory] = File.join(@directory, "quick")
190
+ @master_index = MasterIndexBuilder.new("yaml", @options)
191
+ @quick_index = QuickIndexBuilder.new("index", @options)
192
+ end
193
+
194
+ # Build the index.
195
+ def build_index
196
+ announce "Building Server Index"
197
+ FileUtils.rm_r(@options[:quick_directory]) rescue nil
198
+ @master_index.build do
199
+ @quick_index.build do
200
+ gem_file_list.each do |gemfile|
201
+ spec = Gem::Format.from_file_by_path(gemfile).spec
202
+ abbreviate(spec)
203
+ sanitize(spec)
204
+ announce " ... adding #{spec.full_name}"
205
+ @master_index.add(spec)
206
+ @quick_index.add(spec)
207
+ end
208
+ end
209
+ end
210
+ end
211
+
212
+ # List of gem file names to index.
213
+ def gem_file_list
214
+ Dir.glob(File.join(@directory, "gems", "*.gem"))
215
+ end
216
+
217
+ # Abbreviate the spec for downloading. Abbreviated specs are only
218
+ # used for searching, downloading and related activities and do not
219
+ # need deployment specific information (e.g. list of files). So we
220
+ # abbreviate the spec, making it much smaller for quicker downloads.
221
+ def abbreviate(spec)
222
+ spec.files = []
223
+ spec.test_files = []
224
+ spec.rdoc_options = []
225
+ spec.extra_rdoc_files = []
226
+ spec.cert_chain = []
227
+ spec
228
+ end
229
+
230
+ # Sanitize the descriptive fields in the spec. Sometimes non-ASCII
231
+ # characters will garble the site index. Non-ASCII characters will
232
+ # be replaced by their XML entity equivalent.
233
+ def sanitize(spec)
234
+ spec.summary = sanitize_string(spec.summary)
235
+ spec.description = sanitize_string(spec.description)
236
+ spec.post_install_message = sanitize_string(spec.post_install_message)
237
+ spec.authors = spec.authors.collect { |a| sanitize_string(a) }
238
+ spec
239
+ end
240
+
241
+ # Sanitize a single string.
242
+ def sanitize_string(string)
243
+ string ? string.to_xs : string
244
+ end
245
+ end
246
+
247
+ ######################################################################
248
+ # Top Level Functions
249
+ ######################################################################
250
+
251
+ def handle_options(args)
252
+ # default options
253
+ options = {
254
+ :directory => '.',
255
+ :verbose => false,
256
+ :quick => true,
257
+ }
258
+
259
+ args.options do |opts|
260
+ opts.on_tail("--help", "show this message") do
261
+ puts opts
262
+ exit
263
+ end
264
+ opts.on(
265
+ '-d', '--dir=DIRNAME', '--directory=DIRNAME',
266
+ "repository base dir containing gems subdir",
267
+ String) do |value|
268
+ options[:directory] = value
269
+ end
270
+ opts.on('--[no-]quick', "include quick index") do |value|
271
+ options[:quick] = value
272
+ end
273
+ opts.on('-v', '--verbose', "show verbose output") do |value|
274
+ options[:verbose] = value
275
+ end
276
+ opts.on('-V', '--version',
277
+ "show version") do |value|
278
+ puts Gem::RubyGemsVersion
279
+ exit
280
+ end
281
+ opts.parse!
282
+ end
283
+
284
+ if options[:directory].nil?
285
+ puts "Error, must specify directory name. Use --help"
286
+ exit
287
+ elsif ! File.exist?(options[:directory]) ||
288
+ ! File.directory?(options[:directory])
289
+ puts "Error, unknown directory name #{directory}."
290
+ exit
291
+ end
292
+ options
293
+ end
294
+
295
+ # Main program.
296
+ def main_index(args)
297
+ options = handle_options(args)
298
+ Indexer.new(options).build_index
299
+ end
300
+
301
+ if __FILE__ == $0 then
302
+ main_index(ARGV)
303
+ end
@@ -0,0 +1,12 @@
1
+ #!/usr/bin/env automateit
2
+
3
+ # Install Python's easy_install package manager for 'egg' files
4
+
5
+ SOURCE = 'http://peak.telecommunity.com/dist/ez_setup.py'
6
+
7
+ require 'open-uri'
8
+
9
+ mktemp do |t|
10
+ File.open(t, "w+") {|h| h.write(open(SOURCE).read)}
11
+ sh "python #{t}"
12
+ end
@@ -0,0 +1,7 @@
1
+ #!/bin/sh
2
+
3
+ cmd = 'gem install -y rake open4 activesupport rspec ruby-breakpoint ruby-debug --no-rdoc --no-ri'
4
+
5
+ # Run it twice because the first one will usually fail. Oh how I hate gem. :/
6
+ $cmd
7
+ $cmd
@@ -0,0 +1,21 @@
1
+ #!/usr/bin/env bash
2
+
3
+ # RELEASES: http://rubyforge.org/frs/?group_id=126
4
+
5
+ PACKAGE="rubygems-0.9.3"
6
+ URL="http://rubyforge.org/frs/download.php/20585/rubygems-0.9.3.tgz"
7
+
8
+ pushd "/tmp"
9
+
10
+ CACHE=`mktemp -d install_rubygems.XXXXXXXXXX`
11
+ pushd "$CACHE"
12
+
13
+ wget -c -T20 -q "$URL"
14
+ tar xfz "$PACKAGE.tgz"
15
+ cd "$PACKAGE"
16
+ sudo ruby setup.rb
17
+
18
+ popd
19
+ rm -rf "$CACHE"
20
+
21
+ popd
@@ -0,0 +1,6 @@
1
+ @ rem "which" workalike for Windows. Searches current directory and PATH for all extensions, stops after first match, and returns meaningful exit value for "system" or "ERRORLEVEL" checks.
2
+ @setlocal
3
+ @set P2=.;%PATH%
4
+ @for %%e in (%PATHEXT%) do @for %%i in (%1%%e) do @if NOT "%%~$P2:i"=="" echo %%~$P2:i && goto end
5
+ @exit 1
6
+ :end
@@ -0,0 +1,50 @@
1
+ #!/bin/bash -e
2
+ set -e
3
+
4
+ ### BEGIN INIT INFO
5
+ # Provides: automateit_service_test
6
+ # Default-Start: 5
7
+ # Default-Stop: 6
8
+ # Short-Description: automateit_service_test
9
+ # Description: automateit_service_test
10
+ ### END INIT INFO
11
+
12
+ STATE="/tmp/automateit_service_test.state"
13
+ status() {
14
+ test -f $STATE;
15
+ }
16
+ case $1 in
17
+ start)
18
+ if status; then
19
+ echo "ERROR: already running"
20
+ exit 1
21
+ else
22
+ echo "started"
23
+ touch $STATE
24
+ exit 0
25
+ fi
26
+ ;;
27
+ stop)
28
+ if status; then
29
+ echo "stopping"
30
+ rm $STATE
31
+ exit 0
32
+ else
33
+ echo "ERROR: not running"
34
+ exit 1
35
+ fi
36
+ ;;
37
+ status)
38
+ if status; then
39
+ echo "running"
40
+ exit 0
41
+ else
42
+ echo "not running"
43
+ exit 1
44
+ fi
45
+ ;;
46
+ *)
47
+ echo "ERROR: unknown command"
48
+ exit 1
49
+ ;;
50
+ esac
@@ -0,0 +1,15 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ $LOAD_PATH << "lib"
4
+
5
+ require "automateit"
6
+
7
+ puts "==0"
8
+ ai = AutomateIt.new
9
+ #puts "==1"
10
+ #ai.sh "ls"
11
+ #puts "==2"
12
+ #ai.platform_manager.setup(:default => :struct)
13
+ ai.shell_manager.sh "id"
14
+ ai.sh "id"
15
+ ai.eval{sh "id"}
@@ -0,0 +1,8 @@
1
+ #!/usr/bin/env automateit
2
+
3
+ puts "Hello world!"
4
+ puts "I'm an #{self.class}"
5
+ puts "My tags, let me show them to you: %s" % tags.to_a.inspect
6
+ preview_for("I'm in preview mode") do
7
+ puts "I'm not in preview mode"
8
+ end
@@ -0,0 +1,218 @@
1
+ require File.join(File.dirname(File.expand_path(__FILE__)), "/../spec_helper.rb")
2
+
3
+ if not INTERPRETER.euid?
4
+ puts "NOTE: Can't check 'euid' on this platform, #{__FILE__}"
5
+ elsif not INTERPRETER.superuser?
6
+ puts "NOTE: Must be root to check #{__FILE__}"
7
+ elsif not INTERPRETER.account_manager.available?(:add_user)
8
+ puts "NOTE: Can't find AccountManager for this platform, #{__FILE__}"
9
+ else
10
+ describe "AutomateIt::AccountManager" do
11
+ before(:all) do
12
+ @a = AutomateIt.new(:verbosity => Logger::WARN)
13
+ @m = @a.account_manager
14
+
15
+ @username = "automateit_testuser"
16
+ @groupname = "automateit_testgroup"
17
+
18
+ raise "User named '#{@username}' found. If this isn't a real user, delete it so that the test can contineu. If this is a real user, change the spec to test with a user that shouldn't exist." if @m.users[@username]
19
+ raise "Group named '#{@groupname}' found. If this isn't a real group, delete it so that the test can contineu. If this is a real group, change the spec to test with a group that shouldn't exist." if @m.groups[@groupname]
20
+ end
21
+
22
+ after(:all) do
23
+ @m.remove_user(@username, :quiet => true)
24
+ @m.remove_group(@username, :quiet => true)
25
+ @m.remove_group(@groupname, :quiet => true)
26
+ end
27
+
28
+ it "should find root user" do
29
+ entry = @m.users["root"]
30
+ entry.should_not be_nil
31
+ entry.uid.should == 0
32
+ end
33
+
34
+ it "should not have a user before one is created" do
35
+ @m.has_user?(@username).should be_false
36
+ end
37
+
38
+ it "should create a user" do
39
+ entry = @m.add_user(@username, :passwd => "asdf", :shell => "/bin/false")
40
+
41
+ entry.should_not be_nil
42
+ entry.name.should == @username
43
+ # Leaves behind user for further tests
44
+ end
45
+
46
+ it "should have a user after one is created" do
47
+ # Depends on user to be created by previous tests
48
+ @m.has_user?(@username).should be_true
49
+ end
50
+
51
+ it "should query user data by name" do
52
+ # Depends on user to be created by previous tests
53
+ entry = @m.users[@username]
54
+ entry.should_not be_nil
55
+ entry.name.should == @username
56
+ end
57
+
58
+ it "should query user data by id" do
59
+ # Depends on user to be created by previous tests
60
+ uid = @m.users[@username].uid
61
+
62
+ entry = @m.users[uid]
63
+ entry.should_not be_nil
64
+ entry.name.should == @username
65
+ end
66
+
67
+ it "should not query user data by invalid type" do
68
+ lambda{ @m.users[false] }.should raise_error(TypeError)
69
+ end
70
+
71
+ it "should create user group" do
72
+ # Depends on user to be created by previous tests
73
+ @m.groups[@username].should_not be_nil
74
+ end
75
+
76
+ it "should not re-add an existing user" do
77
+ # Depends on user to be created by previous tests
78
+ @m.add_user(@username).should be_false
79
+ end
80
+
81
+ it "should not have a non-existent group" do
82
+ @m.has_group?(@groupname).should be_false
83
+ end
84
+
85
+ it "should add a group" do
86
+ entry = @m.add_group(@groupname)
87
+ entry.should_not be_nil
88
+ entry.name.should == @groupname
89
+ # Leaves behind group for further tests
90
+ end
91
+
92
+ it "should not re-add a group" do
93
+ @m.add_group(@groupname).should be_false
94
+ end
95
+
96
+ it "should query group data by name" do
97
+ entry = @m.groups[@groupname]
98
+ entry.should_not be_nil
99
+ entry.name.should == @groupname
100
+ end
101
+
102
+ it "should query group data by id" do
103
+ gid = @m.groups[@groupname].gid
104
+
105
+ entry = @m.groups[gid]
106
+ entry.should_not be_nil
107
+ entry.name.should == @groupname
108
+ end
109
+
110
+ it "should not query group data by invalid type" do
111
+ lambda{ @m.groups[false] }.should raise_error(TypeError)
112
+ end
113
+
114
+ it "should remove a group" do
115
+ # Depends on group to be created by previous tests
116
+ @m.remove_group(@groupname).should be_true
117
+ end
118
+
119
+ it "should not remove a non-existent group" do
120
+ @m.remove_group(@groupname).should be_false
121
+ end
122
+
123
+ it "should not have members for a non-existent group" do
124
+ @m.users_for_group(@groupname).should == []
125
+ end
126
+
127
+ it "should add a group with members" do
128
+ # Depends on user to be created by previous tests
129
+ @m.add_group(@groupname, :members => @username)
130
+ # Leaves behind group for further tests
131
+ end
132
+
133
+ it "should query users in a group" do
134
+ # Depends on group to be created by previous tests
135
+ @m.users_for_group(@groupname).should == [@username]
136
+ end
137
+
138
+ it "should query groups for a user" do
139
+ # Depends on user to be created by previous tests
140
+ # Depends on group to be created by previous tests
141
+ @m.groups_for_user(@username).should include(@groupname)
142
+ end
143
+
144
+ it "should remove users from a group" do
145
+ # Depends on user to be created by previous tests
146
+ # Depends on group to be created by previous tests
147
+ @m.remove_users_from_group(@username, @groupname).should == [@username]
148
+ end
149
+
150
+ it "should add groups to a user" do
151
+ # Depends on user to be created by previous tests
152
+ @m.add_groups_to_user(@groupname, @username).should == [@groupname]
153
+ end
154
+
155
+ it "should remove groups from user" do
156
+ # Depends on user to be created by previous tests
157
+ @m.remove_groups_from_user(@groupname, @username).should == [@groupname]
158
+ end
159
+
160
+ it "should remove a group with members" do
161
+ # Depends on group to be created by previous tests
162
+ @m.remove_group(@groupname).should be_true
163
+ end
164
+
165
+ it "should not add users to non-existent group" do
166
+ lambda{ @m.add_users_to_group(@username, @groupname) }.should raise_error(ArgumentError)
167
+ end
168
+
169
+ it "should pretend to add users to non-existent group in preview mode" do
170
+ begin
171
+ @a.preview = true
172
+ @m.add_users_to_group(@username, @groupname).should == [@username]
173
+ ensure
174
+ @a.preview = false
175
+ end
176
+ end
177
+
178
+ it "should not remove users from non-existent group" do
179
+ lambda{ @m.remove_users_from_group(@username, @groupname) }.should raise_error(ArgumentError)
180
+ end
181
+
182
+ it "should pretend to remove users from non-existent group in preview mode" do
183
+ begin
184
+ @a.preview = true
185
+ @m.remove_users_from_group(@username, @groupname).should == [@username]
186
+ ensure
187
+ @a.preview = false
188
+ end
189
+ end
190
+
191
+ it "should change password" do
192
+ # Depends on user to be created by previous tests
193
+ pass = "automateit"
194
+
195
+ # TODO This isn't portable
196
+ def extract_pwent(username)
197
+ for filename in %w(/etc/shadow /etc/passwd)
198
+ next unless File.exist?(filename)
199
+ return File.read(filename).split(/\n/).grep(/^#{username}\b/)
200
+ end
201
+ end
202
+
203
+ before = extract_pwent(@username)
204
+ @m.passwd(@username, pass).should be_true
205
+ after = extract_pwent(@username)
206
+ before.should_not eql(after)
207
+ end
208
+
209
+ it "should remove a user" do
210
+ # Depends on user to be created by previous tests
211
+ @m.remove_user(@username, :quiet => true).should be_true
212
+ end
213
+
214
+ it "should not remove a non-existent user" do
215
+ @m.remove_user(@username).should be_false
216
+ end
217
+ end
218
+ end