automate-it 0.9.0
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.
- checksums.yaml +7 -0
- data/.gitignore +19 -0
- data/.hgignore +10 -0
- data/.loadpath +5 -0
- data/.project +17 -0
- data/CHANGES.txt +314 -0
- data/Hoe.rake +40 -0
- data/Manifest.txt +164 -0
- data/README.txt +40 -0
- data/Rakefile +256 -0
- data/TESTING.txt +57 -0
- data/TODO.txt +50 -0
- data/TUTORIAL.txt +391 -0
- data/automate-it.gemspec +25 -0
- data/bin/ai +3 -0
- data/bin/aifield +75 -0
- data/bin/aissh +93 -0
- data/bin/aitag +134 -0
- data/bin/automateit +133 -0
- data/docs/friendly_errors.txt +50 -0
- data/docs/previews.txt +86 -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 +7 -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 +61 -0
- data/examples/basic/recipes/uninstall.rb +6 -0
- data/gpl.txt +674 -0
- data/helpers/cpan_wrapper.pl +220 -0
- data/helpers/which.cmd +7 -0
- data/lib/automateit.rb +55 -0
- data/lib/automateit/account_manager.rb +114 -0
- data/lib/automateit/account_manager/base.rb +138 -0
- data/lib/automateit/account_manager/etc.rb +128 -0
- data/lib/automateit/account_manager/nscd.rb +33 -0
- data/lib/automateit/account_manager/passwd_expect.rb +40 -0
- data/lib/automateit/account_manager/passwd_pty.rb +69 -0
- data/lib/automateit/account_manager/posix.rb +138 -0
- data/lib/automateit/address_manager.rb +88 -0
- data/lib/automateit/address_manager/base.rb +171 -0
- data/lib/automateit/address_manager/bsd.rb +28 -0
- data/lib/automateit/address_manager/freebsd.rb +59 -0
- data/lib/automateit/address_manager/linux.rb +42 -0
- data/lib/automateit/address_manager/openbsd.rb +66 -0
- data/lib/automateit/address_manager/portable.rb +37 -0
- data/lib/automateit/address_manager/sunos.rb +34 -0
- data/lib/automateit/cli.rb +85 -0
- data/lib/automateit/common.rb +65 -0
- data/lib/automateit/constants.rb +35 -0
- data/lib/automateit/download_manager.rb +48 -0
- data/lib/automateit/edit_manager.rb +321 -0
- data/lib/automateit/error.rb +10 -0
- data/lib/automateit/field_manager.rb +103 -0
- data/lib/automateit/interpreter.rb +631 -0
- data/lib/automateit/package_manager.rb +257 -0
- data/lib/automateit/package_manager/apt.rb +27 -0
- data/lib/automateit/package_manager/cpan.rb +101 -0
- data/lib/automateit/package_manager/dpkg.rb +54 -0
- data/lib/automateit/package_manager/egg.rb +64 -0
- data/lib/automateit/package_manager/gem.rb +201 -0
- data/lib/automateit/package_manager/pear.rb +95 -0
- data/lib/automateit/package_manager/pecl.rb +80 -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 +49 -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 +29 -0
- data/lib/automateit/platform_manager/gentoo.rb +26 -0
- data/lib/automateit/platform_manager/lsb.rb +44 -0
- data/lib/automateit/platform_manager/openbsd.rb +28 -0
- data/lib/automateit/platform_manager/struct.rb +80 -0
- data/lib/automateit/platform_manager/sunos.rb +39 -0
- data/lib/automateit/platform_manager/uname.rb +29 -0
- data/lib/automateit/platform_manager/windows.rb +40 -0
- data/lib/automateit/plugin.rb +7 -0
- data/lib/automateit/plugin/base.rb +32 -0
- data/lib/automateit/plugin/driver.rb +256 -0
- data/lib/automateit/plugin/manager.rb +224 -0
- data/lib/automateit/project.rb +493 -0
- data/lib/automateit/root.rb +17 -0
- data/lib/automateit/service_manager.rb +93 -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 +139 -0
- data/lib/automateit/service_manager/update_rcd.rb +35 -0
- data/lib/automateit/shell_manager.rb +316 -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 +523 -0
- data/lib/automateit/shell_manager/symlink.rb +32 -0
- data/lib/automateit/shell_manager/which_base.rb +30 -0
- data/lib/automateit/shell_manager/which_unix.rb +16 -0
- data/lib/automateit/shell_manager/which_windows.rb +20 -0
- data/lib/automateit/tag_manager.rb +127 -0
- data/lib/automateit/tag_manager/struct.rb +121 -0
- data/lib/automateit/tag_manager/tag_parser.rb +93 -0
- data/lib/automateit/tag_manager/yaml.rb +29 -0
- data/lib/automateit/template_manager.rb +56 -0
- data/lib/automateit/template_manager/base.rb +181 -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/ext/shell_escape.rb +7 -0
- data/lib/hashcache.rb +22 -0
- data/lib/helpful_erb.rb +63 -0
- data/lib/inactive_support.rb +53 -0
- data/lib/inactive_support/basic_object.rb +6 -0
- data/lib/inactive_support/clean_logger.rb +127 -0
- data/lib/inactive_support/core_ext/array/extract_options.rb +19 -0
- data/lib/inactive_support/core_ext/blank.rb +50 -0
- data/lib/inactive_support/core_ext/class/attribute_accessors.rb +48 -0
- data/lib/inactive_support/core_ext/class/inheritable_attributes.rb +140 -0
- data/lib/inactive_support/core_ext/enumerable.rb +63 -0
- data/lib/inactive_support/core_ext/hash/keys.rb +54 -0
- data/lib/inactive_support/core_ext/module/aliasing.rb +70 -0
- data/lib/inactive_support/core_ext/numeric/time.rb +91 -0
- data/lib/inactive_support/core_ext/string/inflections.rb +153 -0
- data/lib/inactive_support/core_ext/symbol.rb +14 -0
- data/lib/inactive_support/core_ext/time/conversions.rb +96 -0
- data/lib/inactive_support/duration.rb +96 -0
- data/lib/inactive_support/inflections.rb +53 -0
- data/lib/inactive_support/inflector.rb +282 -0
- data/lib/nested_error.rb +33 -0
- data/lib/nitpick.rb +33 -0
- data/lib/queued_logger.rb +68 -0
- data/lib/tempster.rb +250 -0
- data/misc/index_gem_repository.rb +304 -0
- data/misc/setup_egg.rb +12 -0
- data/misc/setup_gem_dependencies.sh +6 -0
- data/misc/setup_rubygems.sh +21 -0
- metadata +279 -0
@@ -0,0 +1,220 @@
|
|
1
|
+
# This file can be used as both a Perl library (read the POD below) and a
|
2
|
+
# stand-alone program (run it with "--help" for instructions).
|
3
|
+
|
4
|
+
=head1 NAME
|
5
|
+
|
6
|
+
CpanWrapper - Provides a simpler wrapper for the CPAN package manager.
|
7
|
+
|
8
|
+
=head1 DESCRIPTION
|
9
|
+
|
10
|
+
This module provides easy-to-use methods for installing, uninstalling and
|
11
|
+
querying the status of CPAN modules.
|
12
|
+
|
13
|
+
=over
|
14
|
+
|
15
|
+
=cut
|
16
|
+
|
17
|
+
use warnings "all";
|
18
|
+
|
19
|
+
package CpanWrapper;
|
20
|
+
|
21
|
+
require CPAN;
|
22
|
+
require ExtUtils::Packlist;
|
23
|
+
require ExtUtils::Installed;
|
24
|
+
require Tie::Handle;
|
25
|
+
|
26
|
+
=head1 CLASS VARIABLES
|
27
|
+
|
28
|
+
=item $CpanWrapper::DRYRUN
|
29
|
+
|
30
|
+
Should actions really happen? E.g., in dry-run mode, the uninstall will only
|
31
|
+
pretend to delete files.
|
32
|
+
|
33
|
+
=cut
|
34
|
+
|
35
|
+
our $DRYRUN = 0;
|
36
|
+
|
37
|
+
=head1 CLASS METHODS
|
38
|
+
|
39
|
+
=item CpanWrapper->query($module_name)
|
40
|
+
|
41
|
+
Query the module and return 1 if it's installed, 0 if not.
|
42
|
+
|
43
|
+
=cut
|
44
|
+
sub query {
|
45
|
+
my($class, $module) = @_;
|
46
|
+
no warnings;
|
47
|
+
my $result = $CPAN::META->has_inst($module);
|
48
|
+
use warnings "all";
|
49
|
+
return $result;
|
50
|
+
}
|
51
|
+
|
52
|
+
=item CpanWrapper->uninstall($module_name)
|
53
|
+
|
54
|
+
Uninstall the module. Returns an array of files removed.
|
55
|
+
|
56
|
+
=cut
|
57
|
+
sub uninstall {
|
58
|
+
# /usr/local/lib/perl/5.8.8/auto/ack/.packlist
|
59
|
+
my($class, $module) = @_;
|
60
|
+
my $packlists = ExtUtils::Installed->new;
|
61
|
+
my @result;
|
62
|
+
foreach my $file ($packlists->files($module)) {
|
63
|
+
push(@result, $file);
|
64
|
+
unlink $file unless $DRYRUN;
|
65
|
+
}
|
66
|
+
my $packlist = $packlists->packlist($module)->packlist_file();
|
67
|
+
push(@result, $packlist);
|
68
|
+
unlink $packlist unless $DRYRUN;
|
69
|
+
return @result;
|
70
|
+
}
|
71
|
+
|
72
|
+
=item CpanWrapper->install($module_name)
|
73
|
+
|
74
|
+
Install the module. Returns 0 if can't find module.
|
75
|
+
|
76
|
+
=cut
|
77
|
+
sub install {
|
78
|
+
no warnings;
|
79
|
+
my($class, $module) = @_;
|
80
|
+
tie *NO, 'NoHandle';
|
81
|
+
open(SAVEIN, ">&STDIN");
|
82
|
+
open(STDIN, ">&NO"); # TODO why isn't this enough?
|
83
|
+
*STDIN = *NO;
|
84
|
+
my $result;
|
85
|
+
if (my $module_ref = CPAN::Shell->expand('Module', $module)) {
|
86
|
+
$module_ref->install unless $DRYRUN;
|
87
|
+
$result = 1;
|
88
|
+
} else {
|
89
|
+
$result = 0;
|
90
|
+
}
|
91
|
+
open(STDIN, ">&SAVEIN");
|
92
|
+
close NO;
|
93
|
+
use warnings "all";
|
94
|
+
return $result;
|
95
|
+
}
|
96
|
+
|
97
|
+
=item NoHandle
|
98
|
+
|
99
|
+
File handle that responds with "no" to all readline queries. This is used
|
100
|
+
during the install process to reject CPAN's unreasonable defaults.
|
101
|
+
|
102
|
+
=cut
|
103
|
+
package NoHandle;
|
104
|
+
sub TIEHANDLE { my $self; bless \$self, shift }
|
105
|
+
sub WRITE { die }
|
106
|
+
sub PRINT { die }
|
107
|
+
sub PRINTF { die }
|
108
|
+
sub READ { die }
|
109
|
+
sub READLINE { print "no\n"; return "no\n" }
|
110
|
+
sub GETC { die }
|
111
|
+
sub CLOSE { }
|
112
|
+
sub OPEN { }
|
113
|
+
sub BINMODE { }
|
114
|
+
sub EOF { 0 }
|
115
|
+
sub TELL { }
|
116
|
+
sub DESTROY { }
|
117
|
+
|
118
|
+
#===[ command-line usage ]==============================================
|
119
|
+
|
120
|
+
package main;
|
121
|
+
if ($0 eq __FILE__) {
|
122
|
+
sub usage {
|
123
|
+
my($message) = @_;
|
124
|
+
print <<HERE;
|
125
|
+
USAGE: cpan_wrapper.pl [OPTIONS] ACTION module [modules...]
|
126
|
+
|
127
|
+
OPTIONS:
|
128
|
+
--help
|
129
|
+
Show this help
|
130
|
+
--quiet
|
131
|
+
Don't print anything other than what CPAN generates
|
132
|
+
--dryrun
|
133
|
+
Don't actually perform actions, just pretend to
|
134
|
+
|
135
|
+
ACTIONS:
|
136
|
+
|
137
|
+
--install
|
138
|
+
Install modules
|
139
|
+
--uninstall
|
140
|
+
Uninstall modules
|
141
|
+
--query
|
142
|
+
Display which packages are installed and which aren't
|
143
|
+
HERE
|
144
|
+
|
145
|
+
if ($message) {
|
146
|
+
print "ERROR: $message\n";
|
147
|
+
exit 1;
|
148
|
+
} else {
|
149
|
+
exit 0;
|
150
|
+
}
|
151
|
+
}
|
152
|
+
|
153
|
+
use Getopt::Long;
|
154
|
+
our $quiet = 0;
|
155
|
+
our $dryrun = 0;
|
156
|
+
our $help = 0;
|
157
|
+
our $install = 0;
|
158
|
+
our $uninstall = 0;
|
159
|
+
our $query = 0;
|
160
|
+
GetOptions(
|
161
|
+
'quiet' => \$quiet,
|
162
|
+
'dryrun' => \$dryrun,
|
163
|
+
'n' => \$dryrun,
|
164
|
+
'help' => \$help,
|
165
|
+
'install' => \$install,
|
166
|
+
'uninstall' => \$uninstall,
|
167
|
+
'query' => \$query,
|
168
|
+
'q' => \$query
|
169
|
+
);
|
170
|
+
my @modules = @ARGV;
|
171
|
+
|
172
|
+
usage(0) if 1 == $help;
|
173
|
+
usage("No action specified") unless $install or $uninstall or $query;
|
174
|
+
usage("No modules specified") unless $#modules >= 0;
|
175
|
+
|
176
|
+
if ($install) {
|
177
|
+
foreach my $module (@modules) {
|
178
|
+
if (CpanWrapper->install($module)) {
|
179
|
+
print "* Installed: $module\n" unless $quiet;
|
180
|
+
} else {
|
181
|
+
print "! Can't find CPAN module: $module\n";
|
182
|
+
exit 1
|
183
|
+
}
|
184
|
+
}
|
185
|
+
} elsif ($uninstall) {
|
186
|
+
foreach my $module (@modules) {
|
187
|
+
print "* Uninstalling module: $module\n" unless $quiet;
|
188
|
+
|
189
|
+
my(@files) = CpanWrapper->uninstall($module);
|
190
|
+
foreach my $file (@files) {
|
191
|
+
print "- $file\n" unless $quiet;
|
192
|
+
}
|
193
|
+
}
|
194
|
+
} elsif ($query) {
|
195
|
+
my @available;
|
196
|
+
my @unavailable;
|
197
|
+
foreach my $module (@modules) {
|
198
|
+
if (CpanWrapper->query($module)) {
|
199
|
+
push(@available, $module);
|
200
|
+
} else {
|
201
|
+
push(@unavailable, $module);
|
202
|
+
}
|
203
|
+
}
|
204
|
+
|
205
|
+
sub print_contents {
|
206
|
+
my($name, @modules) = @_;
|
207
|
+
return if $#modules < 0;
|
208
|
+
print "$name:\n";
|
209
|
+
foreach my $module (@modules) {
|
210
|
+
print " - $module\n";
|
211
|
+
}
|
212
|
+
}
|
213
|
+
|
214
|
+
print "--- %YAML:1.0\n";
|
215
|
+
print_contents 'available', @available;
|
216
|
+
print_contents 'unavailable', @unavailable;
|
217
|
+
}
|
218
|
+
}
|
219
|
+
|
220
|
+
1;
|
data/helpers/which.cmd
ADDED
@@ -0,0 +1,7 @@
|
|
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
|
+
@rem REM This exits the shell on failure, so don't use it directly
|
6
|
+
@exit 1
|
7
|
+
:end
|
data/lib/automateit.rb
ADDED
@@ -0,0 +1,55 @@
|
|
1
|
+
# == Dependencies
|
2
|
+
|
3
|
+
# Standard libraries
|
4
|
+
require 'etc'
|
5
|
+
require 'fileutils'
|
6
|
+
require 'find'
|
7
|
+
require 'logger'
|
8
|
+
require 'open3'
|
9
|
+
require 'pp'
|
10
|
+
require 'pathname'
|
11
|
+
require 'resolv'
|
12
|
+
require 'set'
|
13
|
+
require 'socket'
|
14
|
+
require 'yaml'
|
15
|
+
|
16
|
+
# Gems
|
17
|
+
require 'rubygems'
|
18
|
+
require 'erb'
|
19
|
+
|
20
|
+
# Extensions
|
21
|
+
require 'inactive_support'
|
22
|
+
require 'ext/object.rb'
|
23
|
+
require 'ext/metaclass.rb'
|
24
|
+
require 'ext/shell_escape.rb'
|
25
|
+
|
26
|
+
# Helpers
|
27
|
+
require 'hashcache'
|
28
|
+
require 'queued_logger'
|
29
|
+
require 'tempster'
|
30
|
+
require 'helpful_erb'
|
31
|
+
require 'nested_error'
|
32
|
+
require 'nitpick'
|
33
|
+
|
34
|
+
# Core
|
35
|
+
require 'automateit/root'
|
36
|
+
require 'automateit/constants'
|
37
|
+
require 'automateit/error'
|
38
|
+
require 'automateit/common'
|
39
|
+
require 'automateit/interpreter'
|
40
|
+
require 'automateit/plugin'
|
41
|
+
require 'automateit/cli'
|
42
|
+
require 'automateit/project'
|
43
|
+
|
44
|
+
# Plugins which must be loaded early
|
45
|
+
require 'automateit/shell_manager'
|
46
|
+
require 'automateit/platform_manager' # requires shell
|
47
|
+
require 'automateit/address_manager' # requires shell
|
48
|
+
require 'automateit/tag_manager' # requires address, platform
|
49
|
+
require 'automateit/field_manager' # requires shell
|
50
|
+
require 'automateit/service_manager' # requires shell
|
51
|
+
require 'automateit/package_manager' # requires shell
|
52
|
+
require 'automateit/template_manager'
|
53
|
+
require 'automateit/edit_manager'
|
54
|
+
require 'automateit/account_manager'
|
55
|
+
require 'automateit/download_manager'
|
@@ -0,0 +1,114 @@
|
|
1
|
+
# == AccountManager
|
2
|
+
#
|
3
|
+
# The AccountManager provides a way of managing system accounts, such as Unix
|
4
|
+
# users and groups.
|
5
|
+
class AutomateIt::AccountManager < AutomateIt::Plugin::Manager
|
6
|
+
# Invalidate system cache for +database+. The +database+ can be either :users
|
7
|
+
# or :groups. This is necessary on operating systems that lack logic to
|
8
|
+
# notify their caching system that an entry changed. If the OS doesn't need
|
9
|
+
# invalidation, will do nothing and return false.
|
10
|
+
#
|
11
|
+
# This method is primarily for the sake of driver authors, recipe authors
|
12
|
+
# will probably never need to use this.
|
13
|
+
def invalidate(database) dispatch_safely(database) end
|
14
|
+
|
15
|
+
#-----------------------------------------------------------------------
|
16
|
+
|
17
|
+
# Find a user account. Method returns a query helper which takes a
|
18
|
+
# +username+ as an index argument and returns a Struct::Passwd entry as
|
19
|
+
# described in Etc::getpwent if the user exists or a nil if not.
|
20
|
+
#
|
21
|
+
# Example:
|
22
|
+
# users["root"] # => #<struct Struct::Passwd name="root"...
|
23
|
+
#
|
24
|
+
# users["does_not_exist"] # => nil
|
25
|
+
def users() dispatch() end
|
26
|
+
|
27
|
+
# Add the +username+ if not already created.
|
28
|
+
#
|
29
|
+
# Options:
|
30
|
+
# * :description -- User's full name. Defaults to username.
|
31
|
+
# * :home -- Path to user's home directory. If not specified, uses system
|
32
|
+
# default like "/home/username".
|
33
|
+
# * :create_home -- Create homedir. Defaults to true.
|
34
|
+
# * :groups -- Array of group names to add this user to.
|
35
|
+
# * :shell -- Path to login shell. If not specified, uses system default
|
36
|
+
# like "/bin/bash".
|
37
|
+
# * :uid -- Fixnum user ID for user. Default chooses an unused id.
|
38
|
+
# * :gid -- Fixnum group ID for user. Default chooses same gid as uid.
|
39
|
+
#
|
40
|
+
# Example:
|
41
|
+
# add_user("bob", :description => "Bob Smith")
|
42
|
+
def add_user(username, opts={}) dispatch(username, opts) end
|
43
|
+
|
44
|
+
# TODO AccountManager#update_user -- implement
|
45
|
+
### def update_user(username, opts={}) dispatch(username, opts) end
|
46
|
+
|
47
|
+
# Remove the +username+ if present.
|
48
|
+
#
|
49
|
+
# Options:
|
50
|
+
# * :remove_home -- Delete user's home directory and mail spool. Default is
|
51
|
+
# true.
|
52
|
+
def remove_user(username, opts={}) dispatch(username, opts) end
|
53
|
+
|
54
|
+
# Is +user+ present?
|
55
|
+
def has_user?(user) dispatch(user) end
|
56
|
+
|
57
|
+
# Add +groups+ (array of groupnames) to +user+.
|
58
|
+
def add_groups_to_user(groups, user) dispatch(groups, user) end
|
59
|
+
|
60
|
+
# Remove +groups+ (array of groupnames) from +user+.
|
61
|
+
def remove_groups_from_user(groups, user) dispatch(groups, user) end
|
62
|
+
|
63
|
+
# Change the +password+ for the +user+.
|
64
|
+
def passwd(user, password, opts={}) dispatch(user, password, opts) end
|
65
|
+
|
66
|
+
#.......................................................................
|
67
|
+
|
68
|
+
# Find a group. Method returns a query helper which takes a
|
69
|
+
# +groupname+ as an index argument and returns a Struct::Group entry as
|
70
|
+
# described in Etc::getgrent if the group exists or a nil if not.
|
71
|
+
#
|
72
|
+
# Example:
|
73
|
+
# groups["root"] # => #<struct Struct::Group name="root"...
|
74
|
+
#
|
75
|
+
# groups["does_not_exist"] # => nil
|
76
|
+
def groups() dispatch() end
|
77
|
+
|
78
|
+
# Add +groupname+ if it doesn't exist. Options:
|
79
|
+
# * :members -- Array of usernames to add as members.
|
80
|
+
# * :gid -- Group ID to use. Default is to find an unused id.
|
81
|
+
def add_group(groupname, opts={}) dispatch(groupname, opts) end
|
82
|
+
|
83
|
+
# TODO AccountManager#update_group -- implement
|
84
|
+
### def update_group(groupname, opts={}) dispatch(groupname, opts) end
|
85
|
+
|
86
|
+
# Remove +groupname+ if it exists.
|
87
|
+
def remove_group(groupname, opts={}) dispatch(groupname, opts) end
|
88
|
+
|
89
|
+
# Does +group+ exist?
|
90
|
+
def has_group?(group) dispatch(group) end
|
91
|
+
|
92
|
+
# Add +users+ (array of usernames) to +group+.
|
93
|
+
def add_users_to_group(users, group) dispatch(users, group) end
|
94
|
+
|
95
|
+
# Remove +users+ (array of usernames) from +group+.
|
96
|
+
def remove_users_from_group(users, group) dispatch(users, group) end
|
97
|
+
|
98
|
+
# Array of groupnames this user is a member of.
|
99
|
+
def groups_for_user(query) dispatch(query) end
|
100
|
+
|
101
|
+
# Array of usernames in group.
|
102
|
+
def users_for_group(query) dispatch(query) end
|
103
|
+
|
104
|
+
# Hash of usernames and the groupnames they're members of.
|
105
|
+
def users_to_groups() dispatch() end
|
106
|
+
end # class AccountManager
|
107
|
+
|
108
|
+
# Drivers
|
109
|
+
require 'automateit/account_manager/base'
|
110
|
+
require 'automateit/account_manager/passwd_pty'
|
111
|
+
require 'automateit/account_manager/passwd_expect'
|
112
|
+
require 'automateit/account_manager/nscd'
|
113
|
+
require 'automateit/account_manager/etc'
|
114
|
+
require 'automateit/account_manager/posix'
|
@@ -0,0 +1,138 @@
|
|
1
|
+
# == AccountManager::BaseDriver
|
2
|
+
#
|
3
|
+
# Base class for all AccountManager drivers.
|
4
|
+
class ::AutomateIt::AccountManager::BaseDriver < ::AutomateIt::Plugin::Driver
|
5
|
+
protected
|
6
|
+
|
7
|
+
def _passwd_helper(user, password, opts={}, &block)
|
8
|
+
users = manager.users
|
9
|
+
|
10
|
+
unless users[user]
|
11
|
+
if preview?
|
12
|
+
log.info(PNOTE+"Setting password for user: #{user}")
|
13
|
+
return true
|
14
|
+
else
|
15
|
+
raise ArgumentError.new("No such user: #{user}")
|
16
|
+
end
|
17
|
+
end
|
18
|
+
|
19
|
+
case user
|
20
|
+
when Symbol
|
21
|
+
user = user.to_s
|
22
|
+
when Integer
|
23
|
+
user = users[user]
|
24
|
+
when String
|
25
|
+
# leave it alone
|
26
|
+
else
|
27
|
+
raise TypeError.new("Unknown user type: #{user.class}")
|
28
|
+
end
|
29
|
+
|
30
|
+
return block.call(user, password, opts)
|
31
|
+
end
|
32
|
+
|
33
|
+
def _add_user_helper(username, opts={}, &block)
|
34
|
+
return false if has_user?(username)
|
35
|
+
|
36
|
+
# Create group first, then the user. Necessary because some OSes can't add users with non-existent groups.
|
37
|
+
|
38
|
+
if opts[:personal_group].nil? and not opts[:group] and not opts[:gid]
|
39
|
+
opts[:personal_group] = true
|
40
|
+
end
|
41
|
+
|
42
|
+
# FIXME how to default personal_group to false?
|
43
|
+
# FIXME what if want to add user to a specific group, rather than creating?
|
44
|
+
# FIXME what if want or not want to crease user group?
|
45
|
+
# FIXME how to find an unused gid/uid combo?
|
46
|
+
|
47
|
+
unless opts[:group] == false
|
48
|
+
groupname = opts[:group] || username
|
49
|
+
unless has_group?(groupname)
|
50
|
+
if not opts[:uid] and not opts[:gid] and group = add_group(groupname, opts)
|
51
|
+
opts[:uid] = opts[:gid] = group.gid
|
52
|
+
end
|
53
|
+
end
|
54
|
+
end
|
55
|
+
|
56
|
+
block.call(username, opts)
|
57
|
+
manager.invalidate(:passwd)
|
58
|
+
|
59
|
+
passwd_opts = {:quiet => opts[:quiet]}
|
60
|
+
manager.passwd(username, opts[:passwd], passwd_opts) if opts[:passwd]
|
61
|
+
|
62
|
+
manager.invalidate(:passwd)
|
63
|
+
return users[username]
|
64
|
+
end
|
65
|
+
|
66
|
+
def _remove_user_helper(username, opts={}, &block)
|
67
|
+
return false unless has_user?(username)
|
68
|
+
|
69
|
+
block.call(username, opts)
|
70
|
+
manager.invalidate(:passwd)
|
71
|
+
remove_group(username) if has_group?(username)
|
72
|
+
|
73
|
+
return true
|
74
|
+
end
|
75
|
+
|
76
|
+
def _add_groups_to_user_helper(groups, username, &block)
|
77
|
+
groups = [groups].flatten
|
78
|
+
present = groups_for_user(username)
|
79
|
+
missing = groups - present
|
80
|
+
return false if missing.empty?
|
81
|
+
|
82
|
+
block.call(missing, username)
|
83
|
+
manager.invalidate(:group)
|
84
|
+
|
85
|
+
return missing
|
86
|
+
end
|
87
|
+
|
88
|
+
def _remove_groups_from_user_helper(groups, username, &block)
|
89
|
+
groups = [groups].flatten
|
90
|
+
matched = groups_for_user(username)
|
91
|
+
present = groups & matched
|
92
|
+
return false if present.empty?
|
93
|
+
|
94
|
+
block.call(present, username)
|
95
|
+
manager.invalidate(:group)
|
96
|
+
|
97
|
+
return present
|
98
|
+
end
|
99
|
+
|
100
|
+
def _add_users_to_group_helper(users, groupname, &block)
|
101
|
+
users = [users].flatten
|
102
|
+
# XXX Include pwent.gid?
|
103
|
+
grent = groups[groupname]
|
104
|
+
missing = \
|
105
|
+
if writing? and not grent
|
106
|
+
raise ArgumentError.new("no such group: #{groupname}")
|
107
|
+
elsif writing? or grent
|
108
|
+
users - grent.mem
|
109
|
+
else
|
110
|
+
users
|
111
|
+
end
|
112
|
+
return false if missing.empty?
|
113
|
+
|
114
|
+
block.call(missing, groupname)
|
115
|
+
manager.invalidate(:groups)
|
116
|
+
|
117
|
+
return missing
|
118
|
+
end
|
119
|
+
|
120
|
+
def _remove_users_from_group_helper(users, groupname, &block)
|
121
|
+
users = [users].flatten
|
122
|
+
grent = groups[groupname]
|
123
|
+
present = \
|
124
|
+
if writing? and not grent
|
125
|
+
raise ArgumentError.new("no such group: #{groupname}")
|
126
|
+
elsif writing? or grent
|
127
|
+
grent.mem & users
|
128
|
+
else
|
129
|
+
users
|
130
|
+
end
|
131
|
+
return false if present.empty?
|
132
|
+
|
133
|
+
block.call(present, groupname)
|
134
|
+
manager.invalidate(:groups)
|
135
|
+
|
136
|
+
return present
|
137
|
+
end
|
138
|
+
end
|