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,66 @@
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 'open4'
19
+ require 'erb'
20
+
21
+ # Load ActiveSupport pieces individually to save ~0.5s
22
+ ### require 'active_support'
23
+ require 'active_support/core_ext/blank' # foo.blank?
24
+ require 'active_support/core_ext/class/attribute_accessors' # cattr_accessor
25
+ require 'active_support/core_ext/class/inheritable_attributes' # inheritable_cattr_accessor
26
+ require 'active_support/core_ext/module/aliasing' # alias_method_chain
27
+ require 'active_support/core_ext/string' # "asdf".demodulize.underscore
28
+ require 'active_support/clean_logger' # cleans up Logger output
29
+ require 'active_support/core_ext/symbol' # [:foo, :bar].map(&:to_s)
30
+
31
+ # Handle ActiveSupport includes
32
+ require 'active_support/core_ext/hash/keys' # {:foo => :bar}.stringify_keys
33
+ Hash.module_eval{include ActiveSupport::CoreExtensions::Hash::Keys}
34
+
35
+ # Extensions
36
+ require 'ext/object.rb'
37
+ require 'ext/metaclass.rb'
38
+
39
+ # Helpers
40
+ require 'hashcache'
41
+ require 'queued_logger'
42
+ require 'tempster'
43
+ require 'helpful_erb'
44
+ require 'nested_error'
45
+
46
+ # Core
47
+ require 'automateit/root'
48
+ require 'automateit/constants'
49
+ require 'automateit/error'
50
+ require 'automateit/common'
51
+ require 'automateit/interpreter'
52
+ require 'automateit/plugin'
53
+ require 'automateit/cli'
54
+ require 'automateit/project'
55
+
56
+ # Plugins which must be loaded early
57
+ require 'automateit/shell_manager'
58
+ require 'automateit/platform_manager' # requires shell
59
+ require 'automateit/address_manager' # requires shell
60
+ require 'automateit/tag_manager' # requires address, platform
61
+ require 'automateit/field_manager' # requires shell
62
+ require 'automateit/service_manager' # requires shell
63
+ require 'automateit/package_manager' # requires shell
64
+ require 'automateit/template_manager'
65
+ require 'automateit/edit_manager'
66
+ require 'automateit/account_manager'
@@ -0,0 +1,106 @@
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
+ # Find a user account. Method returns a query helper which takes a
7
+ # +username+ as an index argument and returns a Struct::Passwd entry as
8
+ # described in Etc::getpwent if the user exists or a nil if not.
9
+ #
10
+ # Example:
11
+ # users["root"] # => #<struct Struct::Passwd name="root"...
12
+ #
13
+ # users["does_not_exist"] # => nil
14
+ def users() dispatch() end
15
+
16
+ # Add the +username+ if not already created.
17
+ #
18
+ # Options:
19
+ # * :description -- User's full name. Defaults to username.
20
+ # * :home -- Path to user's home directory. If not specified, uses system
21
+ # default like "/home/username".
22
+ # * :create_home -- Create homedir. Defaults to true.
23
+ # * :groups -- Array of group names to add this user to.
24
+ # * :shell -- Path to login shell. If not specified, uses system default
25
+ # like "/bin/bash".
26
+ # * :uid -- Fixnum user ID for user. Default chooses an unused id.
27
+ # * :gid -- Fixnum group ID for user. Default chooses same gid as uid.
28
+ #
29
+ # Example:
30
+ # add_user("bob", :description => "Bob Smith")
31
+ def add_user(username, opts={}) dispatch(username, opts) end
32
+
33
+ # TODO AccountManager#update_user -- implement
34
+ ### def update_user(username, opts={}) dispatch(username, opts) end
35
+
36
+ # Remove the +username+ if present.
37
+ #
38
+ # Options:
39
+ # * :remove_home -- Delete user's home directory and mail spool. Default is
40
+ # true.
41
+ def remove_user(username, opts={}) dispatch(username, opts) end
42
+
43
+ # Is +user+ present?
44
+ def has_user?(user) dispatch(user) end
45
+
46
+ # Add +groups+ (array of groupnames) to +user+.
47
+ def add_groups_to_user(groups, user) dispatch(groups, user) end
48
+
49
+ # Remove +groups+ (array of groupnames) from +user+.
50
+ def remove_groups_from_user(groups, user) dispatch(groups, user) end
51
+
52
+ # Change the +password+ for the +user+.
53
+ def passwd(user, password) dispatch(user, password) end
54
+
55
+ #.......................................................................
56
+
57
+ # Find a group. Method returns a query helper which takes a
58
+ # +groupname+ as an index argument and returns a Struct::Group entry as
59
+ # described in Etc::getgrent if the group exists or a nil if not.
60
+ #
61
+ # Example:
62
+ # groups["root"] # => #<struct Struct::Group name="root"...
63
+ #
64
+ # groups["does_not_exist"] # => nil
65
+ def groups() dispatch() end
66
+
67
+ # Add +groupname+ if it doesn't exist. Options:
68
+ # * :members -- Array of usernames to add as members.
69
+ # * :gid -- Group ID to use. Default is to find an unused id.
70
+ def add_group(groupname, opts={}) dispatch(groupname, opts) end
71
+
72
+ # TODO AccountManager#update_group -- implement
73
+ ### def update_group(groupname, opts={}) dispatch(groupname, opts) end
74
+
75
+ # Remove +groupname+ if it exists.
76
+ def remove_group(groupname, opts={}) dispatch(groupname, opts) end
77
+
78
+ # Does +group+ exist?
79
+ def has_group?(group) dispatch(group) end
80
+
81
+ # Add +users+ (array of usernames) to +group+.
82
+ def add_users_to_group(users, group) dispatch(users, group) end
83
+
84
+ # Remove +users+ (array of usernames) from +group+.
85
+ def remove_users_from_group(users, group) dispatch(users, group) end
86
+
87
+ # Array of groupnames this user is a member of.
88
+ def groups_for_user(query) dispatch(query) end
89
+
90
+ # Array of usernames in group.
91
+ def users_for_group(query) dispatch(query) end
92
+
93
+ # Hash of usernames and the groupnames they're members of.
94
+ def users_to_groups() dispatch() end
95
+ end # class AccountManager
96
+
97
+ # == AccountManager::BaseDriver
98
+ #
99
+ # Base class for all AccountManager drivers.
100
+ class ::AutomateIt::AccountManager::BaseDriver < AutomateIt::Plugin::Driver
101
+ end
102
+
103
+ # Drivers
104
+ require 'automateit/account_manager/portable'
105
+ require 'automateit/account_manager/linux'
106
+ require 'automateit/account_manager/passwd'
@@ -0,0 +1,171 @@
1
+ # == AccountManager::Linux
2
+ #
3
+ # A Linux-specific driver for the AccountManager.
4
+ class ::AutomateIt::AccountManager::Linux < ::AutomateIt::AccountManager::Portable
5
+ depends_on \
6
+ :programs => %w(useradd usermod userdel groupadd groupmod groupdel),
7
+ :callbacks => [lambda{AutomateIt::AccountManager::Portable.has_etc?}]
8
+
9
+ def suitability(method, *args) # :nodoc:
10
+ # Level must be higher than Portable
11
+ return available? ? 2 : 0
12
+ end
13
+
14
+ def setup(*args) # :nodoc:
15
+ super(*args)
16
+ end
17
+
18
+ # Is "nscd" available on this platform?
19
+ def nscd?
20
+ @nscd ||= interpreter.which("nscd")
21
+ end
22
+
23
+ #.......................................................................
24
+
25
+ # See AccountManager#add_user
26
+ def add_user(username, opts={})
27
+ return false if has_user?(username)
28
+ cmd = "useradd"
29
+ cmd << " --comment #{opts[:description] || username}"
30
+ cmd << " --home #{opts[:home]}" if opts[:home]
31
+ cmd << " --create-home" unless opts[:create_home] == false
32
+ cmd << " --groups #{opts[:groups].join(' ')}" if opts[:groups]
33
+ cmd << " --shell #{opts[:shell] || "/bin/bash"}"
34
+ cmd << " --uid #{opts[:uid]}" if opts[:uid]
35
+ cmd << " --gid #{opts[:gid]}" if opts[:gid]
36
+ cmd << " #{username} < /dev/null"
37
+ cmd << " > /dev/null" if opts[:quiet]
38
+ interpreter.sh(cmd)
39
+ interpreter.sh("nscd --invalidate passwd") if nscd?
40
+
41
+ unless opts[:group] == false
42
+ groupname = opts[:group] || username
43
+ unless has_group?(groupname)
44
+ opts = {:members => [username]}
45
+ # In preview mode, user doesn't exist and has no UID
46
+ opts[:gid] = users[username].uid if writing?
47
+ add_group(groupname, opts)
48
+ end
49
+ end
50
+
51
+ interpreter.account_manager.passwd(username, opts[:passwd]) if opts[:passwd]
52
+
53
+ return users[username]
54
+ end
55
+
56
+ # TODO AccountManager#update_user -- implement
57
+ ### def update_user(username, opts={}) dispatch(username, opts) end
58
+
59
+ # See AccountManager#remove_user
60
+ def remove_user(username, opts={})
61
+ return false unless has_user?(username)
62
+ # Options: -r -- remove the home directory and mail spool
63
+ cmd = "userdel"
64
+ cmd << " -r" unless opts[:remove_home] == false
65
+ cmd << " #{username}"
66
+ cmd << " > /dev/null" if opts[:quiet]
67
+ interpreter.sh(cmd)
68
+ interpreter.sh("nscd --invalidate passwd") if nscd?
69
+ remove_group(username) if has_group?(username)
70
+ return true
71
+ end
72
+
73
+ # See AccountManager#add_groups_to_user
74
+ def add_groups_to_user(groups, username)
75
+ groups = [groups].flatten
76
+ present = groups_for_user(username)
77
+ missing = groups - present
78
+ return false if missing.empty?
79
+
80
+ cmd = "usermod -a -G #{missing.join(',')} #{username}"
81
+ interpreter.sh(cmd)
82
+ interpreter.sh("nscd --invalidate group") if nscd?
83
+ return missing
84
+ end
85
+
86
+ # See AccountManager#remove_groups_from_user
87
+ def remove_groups_from_user(groups, username)
88
+ groups = [groups].flatten
89
+ present = groups_for_user(username)
90
+ removeable = groups & present
91
+ return false if removeable.empty?
92
+
93
+ cmd = "usermod -G #{(present-groups).join(',')} #{username}"
94
+ interpreter.sh(cmd)
95
+ interpreter.sh("nscd --invalidate group") if nscd?
96
+ return removeable
97
+ end
98
+
99
+ #.......................................................................
100
+
101
+ # See AccountManager#add_group
102
+ def add_group(groupname, opts={})
103
+ return false if has_group?(groupname)
104
+ cmd = "groupadd"
105
+ cmd << " -g #{opts[:gid]}" if opts[:gid]
106
+ cmd << " #{groupname}"
107
+ interpreter.sh(cmd)
108
+ interpreter.sh("nscd --invalidate group") if nscd?
109
+ add_users_to_group(opts[:members], groupname) if opts[:members]
110
+ return groups[groupname]
111
+ end
112
+
113
+ # TODO AccountManager#update_group -- implement
114
+ ### def update_group(groupname, opts={}) dispatch(groupname, opts) end
115
+
116
+ # See AccountManager#remove_group
117
+ def remove_group(groupname, opts={})
118
+ return false unless has_group?(groupname)
119
+ cmd = "groupdel #{groupname}"
120
+ interpreter.sh(cmd)
121
+ interpreter.sh("nscd --invalidate group") if nscd?
122
+ return true
123
+ end
124
+
125
+ # See AccountManager#add_users_to_group
126
+ def add_users_to_group(users, groupname)
127
+ users = [users].flatten
128
+ # XXX Include pwent.gid?
129
+ grent = groups[groupname]
130
+ missing = \
131
+ if writing? and not grent
132
+ raise ArgumentError.new("no such group: #{groupname}")
133
+ elsif writing? or grent
134
+ users - grent.mem
135
+ else
136
+ users
137
+ end
138
+ return false if missing.empty?
139
+
140
+ for username in missing
141
+ cmd = "usermod -a -G #{groupname} #{username}"
142
+ interpreter.sh(cmd)
143
+ end
144
+ interpreter.sh("nscd --invalidate group") if nscd?
145
+ return missing
146
+ end
147
+
148
+ # See AccountManager#remove_users_from_group
149
+ def remove_users_from_group(users, groupname)
150
+ users = [users].flatten
151
+ grent = groups[groupname]
152
+ present = \
153
+ if writing? and not grent
154
+ raise ArgumentError.new("no such group: #{groupname}")
155
+ elsif writing? or grent
156
+ grent.mem & users
157
+ else
158
+ users
159
+ end
160
+ return false if present.empty?
161
+
162
+ u2g = users_to_groups
163
+ for username in present
164
+ user_groups = u2g[username]
165
+ cmd = "usermod -G #{(user_groups.to_a-[groupname]).join(',')} #{username}"
166
+ interpreter.sh(cmd)
167
+ end
168
+ interpreter.sh("nscd --invalidate group") if nscd?
169
+ return present
170
+ end
171
+ end
@@ -0,0 +1,69 @@
1
+ # == AccountManager::Passwd
2
+ #
3
+ # An AccountManager driver for the +passwd+ command found on Unix-like systems.
4
+ class ::AutomateIt::AccountManager::Passwd < ::AutomateIt::AccountManager::BaseDriver
5
+ depends_on \
6
+ :programs => %w(passwd),
7
+ :libraries => %w(open3 expect pty)
8
+
9
+ def suitability(method, *args) # :nodoc:
10
+ # Level must be higher than Linux
11
+ return available? ? 3 : 0
12
+ end
13
+
14
+ # See AccountManager#passwd
15
+ def passwd(user, password, opts={})
16
+ users = interpreter.account_manager.users
17
+
18
+ unless users[user]
19
+ if preview?
20
+ log.info(PNOTE+"Setting password for user: #{user}")
21
+ return true
22
+ else
23
+ raise ArgumentError.new("No such user: #{user}")
24
+ end
25
+ end
26
+
27
+ case user
28
+ when Symbol: user = user.to_s
29
+ when Integer: user = users[user]
30
+ when String: # leave it alone
31
+ else raise TypeError.new("Unknown user type: #{user.class}")
32
+ end
33
+
34
+ tries = 5
35
+ exitstatus = nil
36
+ begin
37
+ exitstruct = _passwd_raw(user, password, opts)
38
+ if exitstatus and not exitstruct.exitstatus.zero?
39
+ # FIXME AccountManager::Linux#passwd -- The `passwd` command randomly returns exit status 10 even when it succeeds. What does this mean and how to deal with it?! Temporary workaround is to throw an error and force a retry.
40
+ raise Errno::EPIPE.new("bad exitstatus %s" % exitstruct.exitstatus)
41
+ end
42
+ rescue Errno::EPIPE => e
43
+ # FIXME AccountManager::Linux#passwd -- EPIPE exception randomly thrown even when `passwd` succeeds. How to eliminate it? How to differentiate between this false error and a real one?
44
+ if tries <= 0
45
+ raise e
46
+ else
47
+ tries -= 1
48
+ retry
49
+ end
50
+ end
51
+
52
+ return exitstruct.exitstatus.zero?
53
+ end
54
+
55
+ def _passwd_raw(user, password, opts={})
56
+ quiet = (opts[:quiet] or not log.info?)
57
+
58
+ return Open4::popen4("passwd %s 2>&1" % user) do |pid, sin, sout, serr|
59
+ $expect_verbose = ! quiet
60
+ 2.times do
61
+ sout.expect(/:/)
62
+ sleep 0.1 # Reduce chance of passwd thinking we're a robot :(
63
+ sin.puts password
64
+ puts "*" * 12 unless quiet
65
+ end
66
+ end
67
+ end
68
+ protected :_passwd_raw
69
+ end
@@ -0,0 +1,136 @@
1
+ # == AccountManager::Portable
2
+ #
3
+ # A pure-Ruby, portable driver for the AccountManager. It is only suitable
4
+ # for doing queries and lacks methods such as +add_user+. Platform-specific
5
+ # drivers inherit from this class and provide these methods.
6
+ class ::AutomateIt::AccountManager::Portable < ::AutomateIt::AccountManager::BaseDriver
7
+ depends_on :callbacks => [lambda{AutomateIt::AccountManager::Portable.has_etc?}]
8
+
9
+ def suitability(method, *args) # :nodoc:
10
+ return 1
11
+ end
12
+
13
+ # Does this platform provide a way of querying users and groups through
14
+ # the 'etc' module?
15
+ def self.has_etc?
16
+ begin
17
+ require 'etc'
18
+ return defined?(Etc)
19
+ rescue LoadError
20
+ return false
21
+ end
22
+ end
23
+
24
+ # Alias for AccountManager::Portable.has_etc?
25
+ def has_etc?
26
+ self.has_etc?
27
+ end
28
+
29
+ #.......................................................................
30
+
31
+ # == UserQuery
32
+ #
33
+ # A class used for querying users. See AccountManager#users.
34
+ class UserQuery
35
+ # See AccountManager#users
36
+ def [](query)
37
+ Etc.endpwent
38
+ begin
39
+ case query
40
+ when String
41
+ return Etc.getpwnam(query)
42
+ when Fixnum
43
+ return Etc.getpwuid(query)
44
+ else
45
+ raise TypeError.new("unknonwn type for query: #{query.class}")
46
+ end
47
+ rescue ArgumentError
48
+ return nil
49
+ end
50
+ end
51
+ end
52
+
53
+ # See AccountManager#users
54
+ def users
55
+ return UserQuery.new
56
+ end
57
+
58
+ # See AccountManager#has_user?
59
+ def has_user?(query)
60
+ return ! users[query].nil?
61
+ end
62
+
63
+ #.......................................................................
64
+
65
+ # == GroupQuery
66
+ #
67
+ # A class used for querying groups. See AccountManager#groups.
68
+ class GroupQuery
69
+ # See AccountManager#groups
70
+ def [](query)
71
+ Etc.endgrent
72
+ begin
73
+ case query
74
+ when String
75
+ return Etc.getgrnam(query)
76
+ when Fixnum
77
+ return Etc.getgrgid(query)
78
+ else
79
+ raise TypeError.new("unknonwn type for query: #{query.class}")
80
+ end
81
+ rescue ArgumentError
82
+ return nil
83
+ end
84
+ end
85
+ end
86
+
87
+ # See AccountManager#groups
88
+ def groups
89
+ return GroupQuery.new
90
+ end
91
+
92
+ # See AccountManager#has_group?
93
+ def has_group?(query)
94
+ return ! groups[query].nil?
95
+ end
96
+
97
+ # See AccountManager#groups_for_user
98
+ def groups_for_user(query)
99
+ pwent = users[query]
100
+ return [] if preview? and not pwent
101
+ username = pwent.name
102
+ result = Set.new
103
+ result << groups[pwent.gid].name if groups[pwent.gid]
104
+ Etc.group do |grent|
105
+ result << grent.name if grent.mem.include?(username)
106
+ end
107
+ return result.to_a
108
+ end
109
+
110
+ # See AccountManager#users_for_group
111
+ def users_for_group(query)
112
+ grent = groups[query]
113
+ return (preview? || ! grent) ? [] : grent.mem
114
+ end
115
+
116
+ # See AccountManager#users_to_groups
117
+ def users_to_groups
118
+ result = {}
119
+ Etc.group do |grent|
120
+ grent.mem.each do |username|
121
+ result[username] ||= Set.new
122
+ result[username] << grent.name
123
+ end
124
+ end
125
+ Etc.passwd do |pwent|
126
+ grent = groups[pwent.gid]
127
+ unless grent
128
+ log.fatal(PNOTE+"WARNING: User's default group doesn't exist: user %s, gid %s" % [pwent.name, pwent.gid])
129
+ next
130
+ end
131
+ result[pwent.name] ||= Set.new
132
+ result[pwent.name] << grent.name
133
+ end
134
+ return result
135
+ end
136
+ end