etch 3.20.1 → 4.0.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.
Files changed (4) hide show
  1. data/Rakefile +1 -1
  2. data/lib/etch/client.rb +46 -29
  3. data/lib/etch.rb +17 -5
  4. metadata +10 -5
data/Rakefile CHANGED
@@ -3,7 +3,7 @@ spec = Gem::Specification.new do |s|
3
3
  s.name = 'etch'
4
4
  s.summary = 'Etch system configuration management client'
5
5
  s.add_dependency('facter')
6
- s.version = '3.20.1'
6
+ s.version = '4.0.0'
7
7
  s.author = 'Jason Heiss'
8
8
  s.email = 'etch-users@lists.sourceforge.net'
9
9
  s.homepage = 'http://etch.sourceforge.net'
data/lib/etch/client.rb CHANGED
@@ -42,7 +42,7 @@ end
42
42
  require 'etch'
43
43
 
44
44
  class Etch::Client
45
- VERSION = '3.20.1'
45
+ VERSION = '4.0.0'
46
46
 
47
47
  CONFIRM_PROCEED = 1
48
48
  CONFIRM_SKIP = 2
@@ -204,7 +204,7 @@ class Etch::Client
204
204
  @already_processed = {}
205
205
  @exec_already_processed = {}
206
206
  @exec_once_per_run = {}
207
- @results = []
207
+ @results = {}
208
208
  # See start/stop_output_capture for these
209
209
  @output_pipes = []
210
210
 
@@ -521,11 +521,11 @@ class Etch::Client
521
521
  rails_results << "status=#{CGI.escape(status.to_s)}"
522
522
  rails_results << "message=#{CGI.escape(message)}"
523
523
  if @detailed_results.include?('SERVER')
524
- @results.each do |result|
524
+ @results.each do |file, result|
525
525
  # Strangely enough this works. Even though the key is not unique to
526
526
  # each result the Rails parameter parsing code keeps track of keys it
527
527
  # has seen, and if it sees a duplicate it starts a new hash.
528
- rails_results << "results[][file]=#{CGI.escape(result['file'])}"
528
+ rails_results << "results[][file]=#{CGI.escape(file)}"
529
529
  rails_results << "results[][success]=#{CGI.escape(result['success'].to_s)}"
530
530
  rails_results << "results[][message]=#{CGI.escape(result['message'])}"
531
531
  end
@@ -563,8 +563,8 @@ class Etch::Client
563
563
  file.puts "Message:\n#{message}\n"
564
564
  end
565
565
  # Then the detailed results
566
- @results.each do |result|
567
- file.puts "File #{result['file']}, result #{result['success']}:\n"
566
+ @results.each do |resultfile, result|
567
+ file.puts "File #{resultfile}, result #{result['success']}:\n"
568
568
  file.puts result['message']
569
569
  end
570
570
  end
@@ -621,7 +621,6 @@ class Etch::Client
621
621
 
622
622
  # Prep the results capturing for this file
623
623
  result = {}
624
- result['file'] = file
625
624
  result['success'] = true
626
625
  result['message'] = ''
627
626
 
@@ -654,13 +653,19 @@ class Etch::Client
654
653
  # Process any other files that this file depends on
655
654
  config.elements.each('/config/depend') do |depend|
656
655
  puts "Processing dependency #{depend.text}" if (@debug)
657
- process_file(depend.text, responsedata)
656
+ continue_processing = process_file(depend.text, responsedata)
657
+ if !continue_processing
658
+ throw :process_done
659
+ end
658
660
  end
659
661
 
660
662
  # Process any commands that this file depends on
661
663
  config.elements.each('/config/dependcommand') do |dependcommand|
662
664
  puts "Processing command dependency #{dependcommand.text}" if (@debug)
663
- process_commands(dependcommand.text, responsedata)
665
+ continue_processing = process_commands(dependcommand.text, responsedata)
666
+ if !continue_processing
667
+ throw :process_done
668
+ end
664
669
  end
665
670
 
666
671
  # See what type of action the user has requested
@@ -834,7 +839,6 @@ class Etch::Client
834
839
  save_results = false
835
840
  throw :process_done
836
841
  when CONFIRM_QUIT
837
- unlock_all_files
838
842
  continue_processing = false
839
843
  save_results = false
840
844
  throw :process_done
@@ -1099,7 +1103,6 @@ class Etch::Client
1099
1103
  save_results = false
1100
1104
  throw :process_done
1101
1105
  when CONFIRM_QUIT
1102
- unlock_all_files
1103
1106
  continue_processing = false
1104
1107
  save_results = false
1105
1108
  throw :process_done
@@ -1279,7 +1282,6 @@ class Etch::Client
1279
1282
  save_results = false
1280
1283
  throw :process_done
1281
1284
  when CONFIRM_QUIT
1282
- unlock_all_files
1283
1285
  continue_processing = false
1284
1286
  save_results = false
1285
1287
  throw :process_done
@@ -1404,7 +1406,6 @@ class Etch::Client
1404
1406
  save_results = false
1405
1407
  throw :process_done
1406
1408
  when CONFIRM_QUIT
1407
- unlock_all_files
1408
1409
  continue_processing = false
1409
1410
  save_results = false
1410
1411
  throw :process_done
@@ -1504,7 +1505,7 @@ class Etch::Client
1504
1505
  end
1505
1506
  result['message'] << output
1506
1507
  if save_results
1507
- @results << result
1508
+ @results[file] = result
1508
1509
  end
1509
1510
 
1510
1511
  if exception
@@ -1542,7 +1543,6 @@ class Etch::Client
1542
1543
 
1543
1544
  # Prep the results capturing for this command
1544
1545
  result = {}
1545
- result['file'] = commandname
1546
1546
  result['success'] = true
1547
1547
  result['message'] = ''
1548
1548
 
@@ -1575,13 +1575,19 @@ class Etch::Client
1575
1575
  # Process any other commands that this command depends on
1576
1576
  command.elements.each('/commands/depend') do |depend|
1577
1577
  puts "Processing command dependency #{depend.text}" if (@debug)
1578
- process_commands(depend.text, responsedata)
1578
+ continue_processing = process_commands(depend.text, responsedata)
1579
+ if !continue_processing
1580
+ throw :process_done
1581
+ end
1579
1582
  end
1580
1583
 
1581
1584
  # Process any files that this command depends on
1582
1585
  command.elements.each('/commands/dependfile') do |dependfile|
1583
1586
  puts "Processing file dependency #{dependfile.text}" if (@debug)
1584
- process_file(dependfile.text, responsedata)
1587
+ continue_processing = process_file(dependfile.text, responsedata)
1588
+ if !continue_processing
1589
+ throw :process_done
1590
+ end
1585
1591
  end
1586
1592
 
1587
1593
  # Perform each step
@@ -1593,6 +1599,9 @@ class Etch::Client
1593
1599
  guard_result = process_guard(guard, commandname)
1594
1600
 
1595
1601
  if !guard_result
1602
+ # Tell the user what we're going to do
1603
+ puts "Will run command '#{command}'"
1604
+
1596
1605
  # If the user requested interactive mode ask them for
1597
1606
  # confirmation to proceed.
1598
1607
  if @interactive
@@ -1603,7 +1612,6 @@ class Etch::Client
1603
1612
  save_results = false
1604
1613
  throw :process_done
1605
1614
  when CONFIRM_QUIT
1606
- unlock_all_files
1607
1615
  continue_processing = false
1608
1616
  save_results = false
1609
1617
  throw :process_done
@@ -1637,7 +1645,7 @@ class Etch::Client
1637
1645
  end
1638
1646
  result['message'] << output
1639
1647
  if save_results
1640
- @results << result
1648
+ @results[commandname] = result
1641
1649
  end
1642
1650
 
1643
1651
  if exception
@@ -2314,14 +2322,17 @@ class Etch::Client
2314
2322
  else print "[p|s|q] "
2315
2323
  end
2316
2324
  response = $stdin.gets.chomp
2317
- if response =~ /p/i || @last_response =~ /p/i
2318
- @last_response = response if !response.strip.empty?
2325
+ if response.empty?
2326
+ response = @last_response
2327
+ end
2328
+ if response =~ /p/i
2329
+ @last_response = response
2319
2330
  return CONFIRM_PROCEED
2320
- elsif response =~ /s/i || @last_response =~ /s/i
2321
- @last_response = response if !response.strip.empty?
2331
+ elsif response =~ /s/i
2332
+ @last_response = response
2322
2333
  return CONFIRM_SKIP
2323
- elsif response =~ /q/i || @last_response =~ /q/i
2324
- @last_response = response if !response.strip.empty?
2334
+ elsif response =~ /q/i
2335
+ @last_response = response
2325
2336
  return CONFIRM_QUIT
2326
2337
  end
2327
2338
  end
@@ -2384,9 +2395,9 @@ class Etch::Client
2384
2395
  # Make 30 attempts (1s sleep after each attempt)
2385
2396
  30.times do |i|
2386
2397
  begin
2387
- fd = IO::sysopen(lockpath, Fcntl::O_WRONLY|Fcntl::O_CREAT|Fcntl::O_EXCL)
2398
+ fd = File.sysopen(lockpath, Fcntl::O_WRONLY|Fcntl::O_CREAT|Fcntl::O_EXCL)
2388
2399
  puts "Lock acquired for #{file}" if (@debug)
2389
- f = IO.open(fd) { |lockfile| lockfile.puts $$ }
2400
+ File.open(fd) { |lockfile| lockfile.puts $$ }
2390
2401
  @locked_files[file] = true
2391
2402
  return
2392
2403
  rescue Errno::EEXIST
@@ -2459,8 +2470,14 @@ class Etch::Client
2459
2470
  # to the pipe. The child gathers up anything sent over the pipe and
2460
2471
  # when we close the pipe later it sends the captured output back to us
2461
2472
  # over a second pipe.
2462
- pread, pwrite = IO.pipe
2463
- oread, owrite = IO.pipe
2473
+ pread = pwrite = oread = owrite = nil
2474
+ if RUBY_VERSION.split('.')[0..1].join('.').to_f >= 1.9
2475
+ pread, pwrite = IO.pipe(Encoding.default_external, 'UTF-8', :invalid => :replace, :undef => :replace)
2476
+ oread, owrite = IO.pipe(Encoding.default_external, 'UTF-8', :invalid => :replace, :undef => :replace)
2477
+ else
2478
+ pread, pwrite = IO.pipe
2479
+ oread, owrite = IO.pipe
2480
+ end
2464
2481
  if fork
2465
2482
  # Parent
2466
2483
  pread.close
data/lib/etch.rb CHANGED
@@ -51,16 +51,16 @@ end
51
51
  class Etch
52
52
  # FIXME: I'm not really proud of this, it seems like there ought to be a way
53
53
  # to just use one logger. The problem is that on the server we'd like to
54
- # use RAILS_DEFAULT_LOGGER for general logging (which is logging to
54
+ # use Rails.logger for general logging (which is logging to
55
55
  # log/production.log), but be able to turn on debug-level logging for
56
56
  # individual connections (via the debug parameter sent in the HTTP
57
- # requests). If we twiddle the log level of RAILS_DEFAULT_LOGGER then all
57
+ # requests). If we twiddle the log level of Rails.logger then all
58
58
  # connections coming in at the same time as the debug connection will also
59
59
  # get logged as debug, making the logs confusing. And if the debug
60
60
  # connection aborts for some reason we also risk leaving
61
- # RAILS_DEFAULT_LOGGER set to debug, flooding the logs. So it seems like we
61
+ # Rails.logger set to debug, flooding the logs. So it seems like we
62
62
  # need a seperate logger for debugging. But that just seems wrong somehow.
63
- # We don't want to just dup RAILS_DEFAULT_LOGGER for each connection, even
63
+ # We don't want to just dup Rails.logger for each connection, even
64
64
  # if Logger didn't immediately blow up we'd probably end up with scrambled
65
65
  # logs as simultaneous connections tried to write at the same time. Or
66
66
  # maybe that would work, depending on how Ruby and the OS buffer writes to
@@ -285,7 +285,11 @@ class Etch
285
285
  end
286
286
 
287
287
  # Load the config.xml file
288
- config_xml = Etch.xmlload(config_xml_file)
288
+ begin
289
+ config_xml = Etch.xmlload(config_xml_file)
290
+ rescue Exception => e
291
+ raise Etch.wrap_exception(e, "Error loading config.xml for #{file}:\n" + e.message)
292
+ end
289
293
 
290
294
  # Filter the config.xml file by looking for attributes
291
295
  begin
@@ -822,6 +826,10 @@ class Etch
822
826
  end
823
827
  end
824
828
 
829
+ # Earlier we chdir'd into the file's directory in the repository. It
830
+ # seems best not to leave this process with that as the cwd.
831
+ Dir.chdir('/')
832
+
825
833
  # In addition to successful configs return configs for files that need
826
834
  # orig data (generation_status==false) because any setup commands might be
827
835
  # needed to create the original file.
@@ -961,6 +969,10 @@ class Etch
961
969
  generation_status = :success
962
970
  end
963
971
 
972
+ # Earlier we chdir'd into the command's directory in the repository. It
973
+ # seems best not to leave this process with that as the cwd.
974
+ Dir.chdir('/')
975
+
964
976
  # If filtering didn't remove all the content then add this to the list of
965
977
  # commands to be returned to the client.
966
978
  if generation_status && generation_status != :unknown &&
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: etch
3
3
  version: !ruby/object:Gem::Version
4
- version: 3.20.1
4
+ version: 4.0.0
5
5
  prerelease:
6
6
  platform: ruby
7
7
  authors:
@@ -9,11 +9,11 @@ authors:
9
9
  autorequire:
10
10
  bindir: bin
11
11
  cert_chain: []
12
- date: 2012-03-21 00:00:00.000000000 Z
12
+ date: 2012-04-30 00:00:00.000000000 Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
15
  name: facter
16
- requirement: &70164344222100 !ruby/object:Gem::Requirement
16
+ requirement: !ruby/object:Gem::Requirement
17
17
  none: false
18
18
  requirements:
19
19
  - - ! '>='
@@ -21,7 +21,12 @@ dependencies:
21
21
  version: '0'
22
22
  type: :runtime
23
23
  prerelease: false
24
- version_requirements: *70164344222100
24
+ version_requirements: !ruby/object:Gem::Requirement
25
+ none: false
26
+ requirements:
27
+ - - ! '>='
28
+ - !ruby/object:Gem::Version
29
+ version: '0'
25
30
  description:
26
31
  email: etch-users@lists.sourceforge.net
27
32
  executables:
@@ -59,7 +64,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
59
64
  version: '0'
60
65
  requirements: []
61
66
  rubyforge_project: etchsyscm
62
- rubygems_version: 1.8.15
67
+ rubygems_version: 1.8.23
63
68
  signing_key:
64
69
  specification_version: 3
65
70
  summary: Etch system configuration management client