etch 3.20.1 → 4.0.0
Sign up to get free protection for your applications and to get access to all the features.
- data/Rakefile +1 -1
- data/lib/etch/client.rb +46 -29
- data/lib/etch.rb +17 -5
- 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 = '
|
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 = '
|
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(
|
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 #{
|
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
|
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
|
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
|
2318
|
-
|
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
|
2321
|
-
@last_response = response
|
2331
|
+
elsif response =~ /s/i
|
2332
|
+
@last_response = response
|
2322
2333
|
return CONFIRM_SKIP
|
2323
|
-
elsif response =~ /q/i
|
2324
|
-
@last_response = response
|
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 =
|
2398
|
+
fd = File.sysopen(lockpath, Fcntl::O_WRONLY|Fcntl::O_CREAT|Fcntl::O_EXCL)
|
2388
2399
|
puts "Lock acquired for #{file}" if (@debug)
|
2389
|
-
|
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
|
2463
|
-
|
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
|
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
|
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
|
-
#
|
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
|
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
|
-
|
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:
|
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-
|
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:
|
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:
|
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.
|
67
|
+
rubygems_version: 1.8.23
|
63
68
|
signing_key:
|
64
69
|
specification_version: 3
|
65
70
|
summary: Etch system configuration management client
|