automateit 0.71021 → 0.71030

Sign up to get free protection for your applications and to get access to all the features.
data.tar.gz.sig CHANGED
Binary file
@@ -1,3 +1,13 @@
1
+ 0.71030:
2
+ Date: Tue, 30 Oct 2007 01:43:02 -0700
3
+ Desc:
4
+ - (%) Fixed bug in AddressManager#add_user when called with multiple groups. Improved AddressManager spec.
5
+ - (+) Added documentation to Project explaining how to partition recipes, and run recipes from other recipes.
6
+ - (+) Added AddressManager::POSIX which provides support for Linux and SunOS, and eliminated the OS-specific drivers for these.
7
+ - Added AddressManager::NSCD by extracting methods from old OS-specific drivers.
8
+ - Added AddressManager::PasswdExpect which uses Expect for much more reliable password changes.
9
+ - Improved AddressManager::PasswdPty by adding retry capability.
10
+
1
11
  0.71021:
2
12
  Date: Sun, 21 Oct 2007 04:58:01 -0700
3
13
  Desc:
data/Hoe.rake CHANGED
@@ -18,17 +18,19 @@ task :manifest do
18
18
  end
19
19
 
20
20
  Hoe.new("AutomateIt", AutomateIt::VERSION.to_s) do |s|
21
+ slogan = "AutomateIt is an open source tool for automating the setup and maintenance of servers, applications and their dependencies."
22
+ title = "AutomateIt: Open source server automation"
21
23
  s.author = "Igal Koshevoy"
22
24
  s.changes = s.paragraphs_of('CHANGES.txt', 0).join("\n")
23
- s.description = "AutomateIt is an open-source tool for automating the setup and maintenance of UNIX-like systems"
25
+ s.description = slogan
24
26
  s.email = "igal@pragmaticraft.com"
25
27
  s.extra_deps = [["activesupport", ">= 1.4"], ["open4", ">= 0.9"]]
26
28
  s.name = "automateit"
27
- s.summary = "AutomateIt is an open-source tool for automating the setup and maintenance of UNIX-like systems"
29
+ s.summary = slogan
28
30
  s.url = "http://automateit.org/"
29
31
  s.spec_extras = {
30
32
  :platform => Gem::Platform::RUBY,
31
- :rdoc_options => %w(--main README.txt --promiscuous --accessor class_inheritable_accessor=R --title) << 'AutomateIt is an open-source tool for automating the setup and maintenance of UNIX-like systems.' << %w(lib docs),
33
+ :rdoc_options => %w(--main README.txt --promiscuous --accessor class_inheritable_accessor=R --title) << title << %w(lib docs),
32
34
  :extra_rdoc_files => FileList[%w(README.txt TUTORIAL.txt TESTING.txt), "docs/*.txt"],
33
35
  }
34
36
  s.spec_extras.merge!(HoeInclude)
data/README.txt CHANGED
@@ -1,6 +1,6 @@
1
1
  == AutomateIt
2
2
 
3
- <em>AutomateIt is an open-source tool for automating the setup and maintenance of servers.</em>
3
+ <em>AutomateIt is an open source tool for automating the setup and maintenance of servers, applications and their dependencies.</em>
4
4
 
5
5
  Information about AutomateIt is best read in the following order:
6
6
  1. http://AutomateIt.org -- website explaining what it is and why it's useful
data/Rakefile CHANGED
@@ -159,6 +159,13 @@ task :now do
159
159
  puts time.to_s(:rfc822)
160
160
  end
161
161
 
162
+ desc "RFC-822 time for yesterday"
163
+ task :yesterday do
164
+ require 'active_support'
165
+ time = Time.now - 1.day
166
+ puts time.to_s(:rfc822)
167
+ end
168
+
162
169
  namespace :gem do
163
170
  desc "View Gem metadata"
164
171
  task :metadata do
@@ -226,7 +233,7 @@ namespace :rdoc do
226
233
  desc "Generate documentation"
227
234
  task :make do
228
235
  # Uses Jamis Buck's RDoc template from http://weblog.jamisbuck.org/2005/4/8/rdoc-template
229
- sh "rdoc --template=jamis --main README.txt --promiscuous --accessor class_inheritable_accessor=R --title 'AutomateIt is an open-source tool for automating the setup and maintenance of UNIX-like systems.' lib docs/*.txt README.txt TUTORIAL.txt TESTING.txt"
236
+ sh "rdoc --template=jamis --main README.txt --promiscuous --accessor class_inheritable_accessor=R --title 'AutomateIt: Open source server automation' lib docs/*.txt README.txt TUTORIAL.txt TESTING.txt"
230
237
  # Create a tutorial index
231
238
  File.open("doc/tutorial.html", "w+") do |writer|
232
239
  writer.write(File.read("doc/index.html").sub(/README_txt.html/, 'TUTORIAL_txt.html'))
@@ -274,7 +281,7 @@ namespace :rdoc do
274
281
  puts "checking %s" % File.mtime(target)
275
282
  puts "different" if different
276
283
 
277
- sh "rdoc --template=jamis --promiscuous --accessor class_inheritable_accessor=R --title 'AutomateIt is an open-source tool for automating the setup and maintenance of UNIX-like systems.' %s" % sources_and_targets.values.join(" ") if different
284
+ sh "rdoc --template=jamis --promiscuous --accessor class_inheritable_accessor=R --title 'AutomateIt: Open source server automation' %s" % sources_and_targets.values.join(" ") if different
278
285
  sleep 1
279
286
  end
280
287
  end
@@ -304,8 +311,11 @@ task :chown do
304
311
  end
305
312
  end
306
313
 
314
+ desc "Link to local rdoc stash"
307
315
  task :rdoclink do
308
316
  automateit.ln_s("/home/lagi/stash/automateit_rdoc", "doc")
309
317
  end
310
318
 
319
+ task :after => [:rdoclink, :rdoc, :regem]
320
+
311
321
  #===[ fin ]=============================================================
data/TODO.txt CHANGED
@@ -2,22 +2,27 @@ KEY: Important? Urgent? Easy? 1=yes, 0=no
2
2
 
3
3
  #===[ App ]=============================================================
4
4
 
5
- Solaris 10
6
- - Create AccountManager::SunOS
7
- - Create ServiceManager::SMF
8
- - Create PackageManager::Blastwave
9
- - Create PackageManager::SunPkg
5
+ BUGS
6
+ - does service_manager.start_and_enable work as expected?
10
7
 
11
- 111 Shell -- Write #su(user, *command)
12
- 100 Shell -- Expand glob patterns, e.g. chown_R(500, 500, "*")
8
+ 111 aissh or aion -- Write command for running stuff against servers with ssh, e.g., "aissh rails_servers ls", which is basically a wrapper over "for t in aitag -w rails_servers; do echo $t; ssh $t "ls"; done"
9
+ 111 Shell -- Write #su(user, *command) as a wrapper around #sh
10
+ 101 Shell -- Expand glob patterns, e.g. chown_R(500, 500, "*")
13
11
 
14
12
  100 Edit -- Display summary of edits, return with :details as [rv, list]
15
13
  100 Shell -- Incorporate which.cmd so #which can work on Windows
16
14
  100 Interpreter#invoke and HelpfulERB -- Extract error context code into class
17
15
 
16
+ 001 CPAN -- Write driver for PackageManager::CPAN
17
+ 001 FreeBSD -- Write driver for PackageManager::FreeBSD_Ports (or generic ::Ports?) and FreeBSD_Pkg
18
+ 000 Darwin -- Write drivers, e.g. PackageManager for Fink and MacPorts (or generic ::Ports?)
18
19
  000 Shell#chperm -- With symbolic mode, wrap `chmod -v` as temporary workaround?
19
- 000 FreeBSD -- Write driver for PackageManager::Ports
20
- 000 Darwin -- Write drivers, e.g. PackageManager for Fink, MacPorts, Pkgsrc
20
+ 000 PackageManager -- Provide a way to specify desired versions and upgrade via recipes
21
+
22
+ Solaris 10
23
+ 000 Create ServiceManager::SMF
24
+ 000 Create PackageManager::Blastwave
25
+ 000 Create PackageManager::SunOS_Pkg
21
26
 
22
27
  ??? Shell -- Return false or list, never single item?
23
28
  ??? Driver -- How to determine if a manager or driver method is available? Manager#available?, Manager#available and Driver#suitable? only say if it should be a default.
@@ -1,6 +1,6 @@
1
1
  == A hands-on tutorial for learning AutomateIt
2
2
 
3
- <em>AutomateIt is an open-source tool for automating the setup and maintenance of servers.</em>
3
+ <em>AutomateIt is an open source tool for automating the setup and maintenance of servers, applications and their dependencies.</em>
4
4
 
5
5
  This hands-on guide will teach you to use AutomateIt and explain where to find more detailed instructions.
6
6
 
@@ -0,0 +1,65 @@
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
+ require 'erb'
16
+
17
+ # Load ActiveSupport pieces individually to save ~0.5s
18
+ ### require 'active_support'
19
+ gem 'activesupport'
20
+ require 'active_support/core_ext/array' # [].extract_options, new in AS 1.4.4
21
+ require 'active_support/core_ext/blank' # foo.blank?
22
+ require 'active_support/core_ext/class/attribute_accessors' # cattr_accessor
23
+ require 'active_support/core_ext/class/inheritable_attributes' # inheritable_cattr_accessor
24
+ require 'active_support/core_ext/module/aliasing' # alias_method_chain
25
+ require 'active_support/core_ext/string' # "asdf".demodulize.underscore
26
+ require 'active_support/clean_logger' # cleans up Logger output
27
+ require 'active_support/core_ext/symbol' # [:foo, :bar].map(&:to_s)
28
+
29
+ # Handle ActiveSupport includes
30
+ require 'active_support/core_ext/hash/keys' # {:foo => :bar}.stringify_keys
31
+ Hash.module_eval{include ActiveSupport::CoreExtensions::Hash::Keys}
32
+
33
+ # Extensions
34
+ require 'ext/object.rb'
35
+ require 'ext/metaclass.rb'
36
+
37
+ # Helpers
38
+ require 'hashcache'
39
+ require 'queued_logger'
40
+ require 'tempster'
41
+ require 'helpful_erb'
42
+ require 'nested_error'
43
+
44
+ # Core
45
+ require 'automateit/root'
46
+ require 'automateit/constants'
47
+ require 'automateit/error'
48
+ require 'automateit/common'
49
+ require 'automateit/interpreter'
50
+ require 'automateit/plugin'
51
+ require 'automateit/cli'
52
+ require 'automateit/project'
53
+
54
+ # Plugins which must be loaded early
55
+ require 'automateit/shell_manager'
56
+ require 'automateit/platform_manager' # requires shell
57
+ require 'automateit/address_manager' # requires shell
58
+ require 'automateit/tag_manager' # requires address, platform
59
+ require 'automateit/field_manager' # requires shell
60
+ require 'automateit/service_manager' # requires shell
61
+ require 'automateit/package_manager' # requires shell
62
+ require 'automateit/template_manager'
63
+ require 'automateit/edit_manager'
64
+ require 'automateit/account_manager'
65
+ require 'automateit/download_manager'
@@ -3,6 +3,17 @@
3
3
  # The AccountManager provides a way of managing system accounts, such as Unix
4
4
  # users and groups.
5
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
+
6
17
  # Find a user account. Method returns a query helper which takes a
7
18
  # +username+ as an index argument and returns a Struct::Passwd entry as
8
19
  # described in Etc::getpwent if the user exists or a nil if not.
@@ -50,7 +61,7 @@ class AutomateIt::AccountManager < AutomateIt::Plugin::Manager
50
61
  def remove_groups_from_user(groups, user) dispatch(groups, user) end
51
62
 
52
63
  # Change the +password+ for the +user+.
53
- def passwd(user, password) dispatch(user, password) end
64
+ def passwd(user, password, opts={}) dispatch(user, password, opts) end
54
65
 
55
66
  #.......................................................................
56
67
 
@@ -94,13 +105,10 @@ class AutomateIt::AccountManager < AutomateIt::Plugin::Manager
94
105
  def users_to_groups() dispatch() end
95
106
  end # class AccountManager
96
107
 
97
- # == AccountManager::BaseDriver
98
- #
99
- # Base class for all AccountManager drivers.
100
- class ::AutomateIt::AccountManager::BaseDriver < AutomateIt::Plugin::Driver
101
- end
102
-
103
108
  # Drivers
104
- require 'automateit/account_manager/portable'
105
- require 'automateit/account_manager/linux'
106
- require 'automateit/account_manager/passwd'
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,133 @@
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: user = user.to_s
21
+ when Integer: user = users[user]
22
+ when String: # leave it alone
23
+ else raise TypeError.new("Unknown user type: #{user.class}")
24
+ end
25
+
26
+ return block.call(user, password, opts)
27
+ end
28
+
29
+ def _add_user_helper(username, opts={}, &block)
30
+ return false if has_user?(username)
31
+
32
+ # Create group first, then the user. Necessary because some OSes can't add users with non-existent groups.
33
+
34
+ if opts[:personal_group].nil? and not opts[:group] and not opts[:gid]
35
+ opts[:personal_group] = true
36
+ end
37
+
38
+ # FIXME how to default personal_group to false?
39
+ # FIXME what if want to add user to a specific group, rather than creating?
40
+ # FIXME what if want or not want to crease user group?
41
+ # FIXME how to find an unused gid/uid combo?
42
+
43
+ unless opts[:group] == false
44
+ groupname = opts[:group] || username
45
+ unless has_group?(groupname)
46
+ if not opts[:uid] and not opts[:gid] and group = add_group(groupname, opts)
47
+ opts[:uid] = opts[:gid] = group.gid
48
+ end
49
+ end
50
+ end
51
+
52
+ block.call(username, opts)
53
+
54
+ passwd_opts = {:quiet => opts[:quiet]}
55
+ manager.passwd(username, opts[:passwd], passwd_opts) if opts[:passwd]
56
+
57
+ manager.invalidate(:passwd)
58
+ return users[username]
59
+ end
60
+
61
+ def _remove_user_helper(username, opts={}, &block)
62
+ return false unless has_user?(username)
63
+
64
+ block.call(username, opts)
65
+ manager.invalidate(:passwd)
66
+ remove_group(username) if has_group?(username)
67
+
68
+ return true
69
+ end
70
+
71
+ def _add_groups_to_user_helper(groups, username, &block)
72
+ groups = [groups].flatten
73
+ present = groups_for_user(username)
74
+ missing = groups - present
75
+ return false if missing.empty?
76
+
77
+ block.call(missing, username)
78
+ manager.invalidate(:group)
79
+
80
+ return missing
81
+ end
82
+
83
+ def _remove_groups_from_user_helper(groups, username, &block)
84
+ groups = [groups].flatten
85
+ matched = groups_for_user(username)
86
+ present = groups & matched
87
+ return false if present.empty?
88
+
89
+ block.call(present, username)
90
+ manager.invalidate(:group)
91
+
92
+ return present
93
+ end
94
+
95
+ def _add_users_to_group_helper(users, groupname, &block)
96
+ users = [users].flatten
97
+ # XXX Include pwent.gid?
98
+ grent = groups[groupname]
99
+ missing = \
100
+ if writing? and not grent
101
+ raise ArgumentError.new("no such group: #{groupname}")
102
+ elsif writing? or grent
103
+ users - grent.mem
104
+ else
105
+ users
106
+ end
107
+ return false if missing.empty?
108
+
109
+ block.call(missing, groupname)
110
+ manager.invalidate(:groups)
111
+
112
+ return missing
113
+ end
114
+
115
+ def _remove_users_from_group_helper(users, groupname, &block)
116
+ users = [users].flatten
117
+ grent = groups[groupname]
118
+ present = \
119
+ if writing? and not grent
120
+ raise ArgumentError.new("no such group: #{groupname}")
121
+ elsif writing? or grent
122
+ grent.mem & users
123
+ else
124
+ users
125
+ end
126
+ return false if present.empty?
127
+
128
+ block.call(present, groupname)
129
+ manager.invalidate(:groups)
130
+
131
+ return present
132
+ end
133
+ end
@@ -1,10 +1,11 @@
1
- # == AccountManager::Portable
1
+ # == AccountManager::Etc
2
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?}]
3
+ # An AccountManager driver for Unix-like OSes that have the Ruby Etc module. It
4
+ # is only suitable for doing queries and lacks methods that perform
5
+ # modifications, such as +add_user+. Platform-specific drivers inherit from
6
+ # this class and provide methods that perform modifications.
7
+ class ::AutomateIt::AccountManager::Etc< ::AutomateIt::AccountManager::BaseDriver
8
+ depends_on :callbacks => [lambda{AutomateIt::AccountManager::Etc.has_etc?}]
8
9
 
9
10
  def suitability(method, *args) # :nodoc:
10
11
  return 1
@@ -14,14 +15,14 @@ class ::AutomateIt::AccountManager::Portable < ::AutomateIt::AccountManager::Bas
14
15
  # the 'etc' module?
15
16
  def self.has_etc?
16
17
  begin
17
- require 'etc'
18
+ require './spec/integration/account_manager_spec.rb:1etc'
18
19
  return defined?(Etc)
19
20
  rescue LoadError
20
21
  return false
21
22
  end
22
23
  end
23
24
 
24
- # Alias for AccountManager::Portable.has_etc?
25
+ # Alias for AccountManager::Etc.has_etc?
25
26
  def has_etc?
26
27
  self.has_etc?
27
28
  end
@@ -0,0 +1,28 @@
1
+ # == AccountManager::NSCD
2
+ #
3
+ # AccountManager driver for invalidating records stored in the NSCD, Name
4
+ # Service Cache Daemon, found on Unix-like systems.
5
+ class ::AutomateIt::AccountManager::NSCD < ::AutomateIt::AccountManager::BaseDriver
6
+ depends_on :programs => %w(nscd ps),
7
+ :callbacks => [lambda{`ps -ef`.match(%r{/usr/sbin/nscd$})}]
8
+
9
+ def suitability(method, *args) # :nodoc:
10
+ # Level must be higher than Portable
11
+ return available? ? 5 : 0
12
+ end
13
+
14
+ def invalidate(database)
15
+ return false unless available?
16
+
17
+ name = \
18
+ case database.to_sym
19
+ when :user, :users, :passwd
20
+ :passwd
21
+ when :group, :groups
22
+ :group
23
+ else
24
+ raise ArgumentError.new("Unknown cache database: #{database}")
25
+ end
26
+ interpreter.sh("nscd -i #{name}")
27
+ end
28
+ end