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