automateit 0.70923

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