automateit 0.71006 → 0.71012

Sign up to get free protection for your applications and to get access to all the features.
@@ -45,3 +45,4 @@ require 'automateit/platform_manager/gentoo'
45
45
  require 'automateit/platform_manager/darwin'
46
46
  require 'automateit/platform_manager/windows'
47
47
  require 'automateit/platform_manager/freebsd'
48
+ require 'automateit/platform_manager/sunos'
@@ -2,10 +2,10 @@
2
2
  #
3
3
  # A PlatformManager driver for Apple's Darwin.
4
4
  class AutomateIt::PlatformManager::Darwin < AutomateIt::PlatformManager::Struct
5
- depends_on :files => ["/usr/sbin/scutil"], :programs => ["which"]
5
+ depends_on :files => ["/usr/sbin/scutil"], :programs => ["which", "uname"]
6
6
 
7
7
  def suitability(method, *args) # :nodoc:
8
- # Must be higher than PlatformManager::Struct
8
+ # Must be higher than PlatformManager::Uname
9
9
  return available? ? 3 : 0
10
10
  end
11
11
 
@@ -2,6 +2,10 @@
2
2
  #
3
3
  # A PlatformManager driver for FreeBSD.
4
4
  class AutomateIt::PlatformManager::FreeBSD < AutomateIt::PlatformManager::Uname
5
+ def self.token
6
+ :freebsd
7
+ end
8
+
5
9
  depends_on :files => %w(/etc/portsnap.conf /etc/rc.conf)
6
10
 
7
11
  def suitability(method, *args) # :nodoc:
@@ -0,0 +1,39 @@
1
+ # == PlatformManager::SunOS
2
+ #
3
+ # A PlatformManager driver for SunOS.
4
+ class AutomateIt::PlatformManager::SunOS < AutomateIt::PlatformManager::Uname
5
+ def self.token
6
+ :sunos
7
+ end
8
+
9
+ depends_on \
10
+ :programs => %w(uname),
11
+ :callbacks => [lambda {
12
+ begin
13
+ not `uname -s`.match(/SunOS/i).nil?
14
+ rescue
15
+ false
16
+ end
17
+ }]
18
+
19
+ def suitability(method, *args) # :nodoc:
20
+ # Must be higher than PlatformManager::Struct and Uname
21
+ return available? ? 3 : 0
22
+ end
23
+
24
+ def _prepare
25
+ return if @struct[:release]
26
+ @struct[:distro] = "sun"
27
+ @struct[:release] = `uname -r`.strip.downcase
28
+ @struct
29
+ end
30
+
31
+ def query(search)
32
+ _prepare
33
+ super(search)
34
+ end
35
+
36
+ def single_vendor?
37
+ return true
38
+ end
39
+ end
@@ -45,6 +45,18 @@ module AutomateIt
45
45
  cattr_accessor :classes
46
46
  self.classes = {}
47
47
 
48
+ # Returns the Plugin::Manager instance for this Driver.
49
+ attr_accessor :manager
50
+
51
+ # Setup a Driver.
52
+ #
53
+ # Options:
54
+ # * :manager -- The Plugin::Manager instance controlling this driver.
55
+ def setup(opts={})
56
+ self.manager = opts[:manager] if opts[:manager]
57
+ super(opts)
58
+ end
59
+
48
60
  # Retrieve the manager token for this driver
49
61
  def self.manager_token
50
62
  fragments = base_driver.to_s.split(/::/)
@@ -70,10 +82,14 @@ module AutomateIt
70
82
  if subclass.base_driver?
71
83
  # Ignore, base drivers should never be registered
72
84
  elsif base_driver
73
- manager = subclass.manager_token
74
- classes[manager] ||= []
75
- classes[manager] << subclass unless classes[manager].include?(subclass)
76
- ### puts "manager %s / driver %s" % [manager, subclass]
85
+ manager_token = subclass.manager_token
86
+ classes[manager_token] ||= []
87
+
88
+ unless classes[manager_token].include?(subclass)
89
+ classes[manager_token] << subclass
90
+ end
91
+
92
+ ### puts "manager_token %s / driver %s" % [manager_token, subclass]
77
93
  else
78
94
  # XXX Should this really raise an exception?
79
95
  raise TypeError.new("Can't determine manager for driver: #{subclass}")
@@ -197,6 +213,7 @@ module AutomateIt
197
213
  raise NotImplementedError.new("Missing dependencies -- %s" % msg)
198
214
  end
199
215
  end
216
+ protected :_raise_unless_available
200
217
 
201
218
  # What is this driver's suitability for automatic detection? The Manager
202
219
  # queries its drivers when there isn't a driver specified with a
@@ -80,7 +80,8 @@ module AutomateIt
80
80
  end
81
81
  self.class.driver_classes.each do |driver_class|
82
82
  driver_token = driver_class.token
83
- @drivers[driver_token].setup(:interpreter => @interpreter)
83
+ @drivers[driver_token].setup(
84
+ :interpreter => @interpreter, :manager => self)
84
85
  end
85
86
  end
86
87
 
@@ -1,7 +1,7 @@
1
1
  # See AutomateIt::Interpreter for usage information.
2
2
  module AutomateIt # :nodoc:
3
3
  # AutomateIt version
4
- VERSION=Gem::Version.new("0.71006")
4
+ VERSION=Gem::Version.new("0.71012")
5
5
 
6
6
  # Instantiates a new Interpreter. See documentation for
7
7
  # Interpreter#setup.
@@ -60,7 +60,7 @@ class AutomateIt::ServiceManager::SYSV < AutomateIt::ServiceManager::BaseDriver
60
60
  end
61
61
 
62
62
  result = tell(service, :status, :check => true)
63
- ### puts "k %s r %s e %s" % [kind, result, expected]
63
+ nitpick("_sash top: k=%s r=%s e=%s" % [kind, result, expected])
64
64
  return result if expected == result
65
65
  if opts[:wait]
66
66
  timeout = Time.now + opts[:wait]
@@ -69,6 +69,7 @@ class AutomateIt::ServiceManager::SYSV < AutomateIt::ServiceManager::BaseDriver
69
69
  [kind, service, timeout - Time.now])
70
70
  sleep 0.5
71
71
  result = tell(service, :status, :check => true)
72
+ nitpick("_sash rep: k=%s r=%s e=%s" % [kind, result, expected])
72
73
  break if expected == result
73
74
  end
74
75
  log.info(PNOTE+" ServiceManager#%s finished waiting for '%s', got: %s" %
@@ -28,6 +28,9 @@ class AutomateIt::ShellManager < AutomateIt::Plugin::Manager
28
28
 
29
29
  # Backup +sources+ if they exist. Returns the names of the backups created.
30
30
  #
31
+ # Options:
32
+ # * :quiet -- Don't display output? Default is false.
33
+ #
31
34
  # These backups are copies of the original sources saved into the same
32
35
  # directories as the originals. The pathnames of these copies are timestamped
33
36
  # and guaranteed to be unique, so you can have multiple backups of the same
@@ -30,6 +30,8 @@ class AutomateIt::ShellManager::Portable < AutomateIt::ShellManager::BaseDriver
30
30
 
31
31
  # See ShellManager#backup
32
32
  def backup(*sources)
33
+ sources, opts = args_and_opts(*sources)
34
+
33
35
  targets = []
34
36
  for source in sources
35
37
  is_dir = File.directory?(source)
@@ -46,17 +48,19 @@ class AutomateIt::ShellManager::Portable < AutomateIt::ShellManager::BaseDriver
46
48
 
47
49
  target = ::Tempster.tempster(tempster_opts)
48
50
 
49
- if is_dir
50
- cp_opts = {}
51
- cp_opts[:recursive] = true if is_dir
52
- cp_opts[:preserve] = :try
51
+ log.silence(opts[:quiet] ? Logger::WARN : log.level) do
52
+ if is_dir
53
+ cp_opts = {}
54
+ cp_opts[:recursive] = true if is_dir
55
+ cp_opts[:preserve] = :try
53
56
 
54
- source_children = _directory_contents(source)
55
- #puts "sc: %s" % source_children.inspect
57
+ source_children = _directory_contents(source)
58
+ #puts "sc: %s" % source_children.inspect
56
59
 
57
- interpreter.cp_r(source_children, target, cp_opts)
58
- else
59
- interpreter.cp(source, target)
60
+ interpreter.cp_r(source_children, target, cp_opts)
61
+ else
62
+ interpreter.cp(source, target)
63
+ end
60
64
  end
61
65
 
62
66
  targets << target
@@ -393,6 +397,8 @@ class AutomateIt::ShellManager::Portable < AutomateIt::ShellManager::BaseDriver
393
397
  end
394
398
 
395
399
  modified_entries = []
400
+ modified_ownership = false
401
+ modified_permission = false
396
402
  Find.find(*targets) do |path|
397
403
  modified = false
398
404
  stat = writing? || File.exists?(path) ? File.stat(path) : nil
@@ -401,15 +407,18 @@ class AutomateIt::ShellManager::Portable < AutomateIt::ShellManager::BaseDriver
401
407
  mode = opts[:mode] | (stat.directory? ? DIRECTORY_MASK : FILE_MASK) if stat
402
408
  unless stat and (mode ^ stat.mode).zero?
403
409
  modified = true
410
+ modified_permission = true
404
411
  File.chmod(mode, path) if writing?
405
412
  end
406
413
  end
407
414
  if user and (not stat or user != stat.uid)
408
415
  modified = true
416
+ modified_ownership = true
409
417
  File.chown(user, nil, path) if writing?
410
418
  end
411
419
  if group and (not stat or group != stat.gid)
412
420
  modified = true
421
+ modified_ownership = true
413
422
  File.chown(nil, group, path) if writing?
414
423
  end
415
424
  modified_entries << path if modified
@@ -421,19 +430,18 @@ class AutomateIt::ShellManager::Portable < AutomateIt::ShellManager::BaseDriver
421
430
  display_entries = opts[:details] ? modified_entries : targets
422
431
  display_entries = [display_entries].flatten
423
432
 
424
- if opts[:mode]
433
+ if modified_permission
425
434
  msg = "chmod"
426
435
  msg << " -R" if opts[:recursive]
427
436
  msg << " 0%o" % opts[:mode] if opts[:mode]
428
437
  msg << " " << display_entries.join(' ')
429
438
  log.info(PEXEC+msg)
430
439
  end
431
- if opts[:user] or opts[:group]
440
+ if modified_ownership
432
441
  msg = "chown"
433
442
  msg << " -R" if opts[:recursive]
434
443
  msg << " %s" % opts[:user] if opts[:user]
435
444
  msg << ":" if opts[:user] and opts[:group]
436
- msg << " " unless opts[:user] and opts[:group]
437
445
  msg << "%s" % opts[:group] if opts[:group]
438
446
  msg << " " << display_entries.join(' ')
439
447
  log.info(PEXEC+msg)
@@ -484,11 +492,11 @@ class AutomateIt::ShellManager::Portable < AutomateIt::ShellManager::BaseDriver
484
492
  end
485
493
 
486
494
  unless quiet
487
- msg = PEXEC << "touch"
495
+ msg = "touch"
488
496
  msg << " --reference %s" % like if like
489
497
  msg << " --stamp %s" % stamp if stamp
490
498
  msg << " " << [targets].flatten.join(" ")
491
- log.info(msg)
499
+ log.info(PEXEC+msg)
492
500
  end
493
501
 
494
502
  results = []
@@ -17,9 +17,10 @@ class AutomateIt::TemplateManager < AutomateIt::Plugin::Manager
17
17
  # * :text -- Read the template from this string.
18
18
  # * :to -- Render to a file, otherwise returns the rendered string.
19
19
  # * :locals -- Hash of variables passed to template as local variables.
20
- # * :dependencies -- When checking timestamps, include this Array of
21
- # filenames when checking timestamps.
22
- # * :force -- Boolean to force rendering without checking timestamps.
20
+ # * :dependencies -- Array of filenames to check timestamps on, only used
21
+ # when :check is :timestamp.
22
+ # * :backup -- Make a backup? Default is true.
23
+ # * :force -- Render without making a check. Default is false.
23
24
  # * :check -- Determines when to render, otherwise uses value of
24
25
  # +default_check+, possible values:
25
26
  # * :compare -- Only render if rendered template is different than the
@@ -16,6 +16,10 @@ class AutomateIt::TemplateManager::BaseDriver < AutomateIt::Plugin::Driver
16
16
  end
17
17
  end
18
18
 
19
+ #.......................................................................
20
+
21
+ protected
22
+
19
23
  # Return Array of +dependencies+ newer than +filename+. Will be empty if
20
24
  # +filename+ is newer than all of the +dependencies+.
21
25
  def _newer(filename, *dependencies)
@@ -26,13 +30,11 @@ class AutomateIt::TemplateManager::BaseDriver < AutomateIt::Plugin::Driver
26
30
  end
27
31
  return updated
28
32
  end
29
- protected :_newer
30
33
 
31
34
  # Does +filename+ exist?
32
35
  def _exists?(filename)
33
36
  return File.exists?(filename)
34
37
  end
35
- protected :_exists?
36
38
 
37
39
  # Return the contents of +filename+.
38
40
  def _read(filename)
@@ -47,20 +49,22 @@ class AutomateIt::TemplateManager::BaseDriver < AutomateIt::Plugin::Driver
47
49
  end
48
50
  end
49
51
  end
50
- protected :_read
51
52
 
52
53
  # Write +contents+ to +filename+.
53
54
  def _write(filename, contents)
54
55
  File.open(filename, "w+"){|writer| writer.write(contents)} if writing?
55
56
  return true
56
57
  end
57
- protected :_write
58
+
59
+ # Backup +filename+.
60
+ def _backup(filename)
61
+ interpreter.backup(filename)
62
+ end
58
63
 
59
64
  # Return the modification date for +filename+.
60
65
  def _mtime(filename)
61
66
  return _exists? ? File.mtime(filename) : nil
62
67
  end
63
- protected :_mtime
64
68
 
65
69
  # Render a template specified in the block. It takes the same arguments and
66
70
  # returns the same results as the #render call.
@@ -84,6 +88,7 @@ class AutomateIt::TemplateManager::BaseDriver < AutomateIt::Plugin::Driver
84
88
  source_filename = args[0] || opts[:file]
85
89
  target_filename = args[1] || opts[:to]
86
90
  source_text = opts[:text]
91
+ opts[:backup] = true if opts[:backup].nil?
87
92
 
88
93
  raise ArgumentError.new("No source specified with :file or :text") if not source_filename and not source_text
89
94
  raise Errno::ENOENT.new(source_filename) if writing? and source_filename and not _exists?(source_filename)
@@ -155,11 +160,13 @@ class AutomateIt::TemplateManager::BaseDriver < AutomateIt::Plugin::Driver
155
160
  log.debug(PNOTE+"Rendering for '#{target_filename}' skipped because contents are the same")
156
161
  return false
157
162
  else
158
- log.info(PNOTE+"Rendering '#{target_filename} because its contents changed")
163
+ log.info(PNOTE+"Rendering '#{target_filename}' because its contents changed")
159
164
  end
160
165
  when :timestamp
161
166
  log.info(PNOTE+"Rendering '#{target_filename}' because of updated: #{updates.join(' ')}")
162
167
  end
168
+
169
+ _backup(target_filename) if target_exists and opts[:backup]
163
170
  result = _write(target_filename, output)
164
171
  return result
165
172
  ensure
@@ -168,5 +175,4 @@ class AutomateIt::TemplateManager::BaseDriver < AutomateIt::Plugin::Driver
168
175
  end
169
176
  end
170
177
  end
171
- protected :_render_helper
172
178
  end
@@ -0,0 +1,8 @@
1
+ require File.join(File.dirname(File.expand_path(__FILE__)), "/spec_helper.rb")
2
+
3
+ describe "Breaker" do
4
+ it "should breakpoint within the RSpec environment" do
5
+ require "breakpoint"
6
+ breakpoint
7
+ end
8
+ end
@@ -4,34 +4,26 @@ if not INTERPRETER.euid?
4
4
  puts "NOTE: Can't check 'euid' on this platform, #{__FILE__}"
5
5
  elsif not INTERPRETER.superuser?
6
6
  puts "NOTE: Must be root to check #{__FILE__}"
7
- elsif not INTERPRETER.address_manager[:linux].available?
8
- puts "NOTE: Can't check AddressManager::Linux on this platform, #{__FILE__}"
9
7
  else
10
- describe "AutomateIt::AddressManager::Linux" do
8
+ describe AutomateIt::AddressManager, :shared => true do
11
9
  before(:all) do
10
+ # Should examples be independent? True is correct and lets you run a
11
+ # single example. False is evil and requires you to run the entire suite,
12
+ # but it's much faster. On Linux false yields a 5x speed-up.
13
+ @independent = false
14
+
12
15
  @a = AutomateIt.new(:verbosity => Logger::WARN)
13
16
  @m = @a.address_manager
14
-
15
- @properties = {
16
- :device => "eth0",
17
- :label => "xxxx",
18
- :address => "10.0.0.249",
19
- :mask => "24",
20
- :announcements => 1,
21
- }
22
-
23
- @device_and_label = @properties[:device]+":"+@properties[:label]
24
-
25
- if @m.interfaces.include?(@device_and_label) \
26
- or @m.addresses.include?(@properties[:address])
27
- raise "ERROR: This computer already has the device/address used for testing! Either disable #{@device_and_label} and #{@properties[:address]}, or change the spec to test using different properties."
28
- end
29
17
  end
30
18
 
31
19
  after(:all) do
32
20
  @m.remove(@properties)
33
21
  end
34
22
 
23
+ after(:each) do
24
+ @m.remove(@properties) if @independent
25
+ end
26
+
35
27
  it "should find interfaces for top-level device" do
36
28
  @m.interfaces.should include(@properties[:device])
37
29
  end
@@ -50,36 +42,41 @@ else
50
42
 
51
43
  it "should add an address" do
52
44
  @m.add(@properties).should be_true
53
- # Leaves active interface behind for other tests
54
45
  end
55
46
 
56
47
  it "should find added interface" do
57
- # Depends on active interface being created by earlier test
48
+ @m.add(@properties).should be_true if @independent
49
+
58
50
  @m.interfaces.should include(@device_and_label)
59
51
  end
60
52
 
61
53
  it "should find added IP address" do
62
- # Depends on active interface being created by earlier test
54
+ @m.add(@properties).should be_true if @independent
55
+
63
56
  @m.addresses.should include(@properties[:address])
64
57
  end
65
58
 
66
59
  it "should find added address using a properties bundle" do
67
- # Depends on user to be created by previous tests
60
+ @m.add(@properties).should be_true if @independent
61
+
68
62
  @m.has?(@properties).should be_true
69
63
  end
70
64
 
71
65
  it "should find added address using the IP address" do
72
- # Depends on user to be created by previous tests
66
+ @m.add(@properties).should be_true if @independent
67
+
73
68
  @m.has?(:address => @properties[:address]).should be_true
74
69
  end
75
70
 
76
71
  it "should find added address using device and label" do
77
- # Depends on user to be created by previous tests
72
+ @m.add(@properties).should be_true if @independent
73
+
78
74
  @m.has?(:device => @properties[:device], :label => @properties[:label]).should be_true
79
75
  end
80
76
 
81
77
  it "should remove an address" do
82
- # Depends on active interface being created by earlier test
78
+ @m.add(@properties).should be_true if @independent
79
+
83
80
  @m.remove(@properties).should be_true
84
81
  end
85
82
 
@@ -116,4 +113,47 @@ else
116
113
  @m.hostnames_for("kagami").should == ["kagami"]
117
114
  end
118
115
  end
116
+
117
+ #---[ Targets ]---------------------------------------------------------
118
+
119
+ %w(linux sunos).each do |driver_name|
120
+ driver_token = driver_name.to_sym
121
+ driver = INTERPRETER.address_manager[driver_token]
122
+ if driver.available?
123
+ describe driver.class.to_s do
124
+ it_should_behave_like "AutomateIt::AddressManager"
125
+
126
+ before(:all) do
127
+
128
+ @properties = {
129
+ :device => @m.interfaces.reject{|t| t =~ /^lo\d+$/}.first,
130
+ :label => "1",
131
+ :address => "10.0.0.249",
132
+ :mask => "24",
133
+ }
134
+
135
+ case driver_token
136
+ when :sunos
137
+ # Accept defaults
138
+ when :linux
139
+ @properties[:label] = "atst"
140
+ @properties[:announcements] = 1
141
+ else
142
+ raise ArgumentError.new("Unknown AddressManager driver: #{driver_token}")
143
+ end
144
+
145
+ @device_and_label = @properties[:device]+":"+@properties[:label]
146
+
147
+ if @m.interfaces.include?(@device_and_label) \
148
+ or @m.addresses.include?(@properties[:address])
149
+ raise "ERROR: This computer already has the device/address used for testing! Either disable #{@device_and_label} and #{@properties[:address]}, or change the spec to test using different properties."
150
+ end
151
+
152
+ @d = @m[driver_token]
153
+ end
154
+ end
155
+ else
156
+ puts %{NOTE: Can't check %s on this platform, #{__FILE__}} % driver.class
157
+ end
158
+ end
119
159
  end