etch 3.12
Sign up to get free protection for your applications and to get access to all the features.
- data/Rakefile +16 -0
- data/bin/etch +101 -0
- data/bin/etch_cron_wrapper +18 -0
- data/bin/etch_to_trunk +45 -0
- data/etc/ca.pem +1 -0
- data/etc/dhparams +9 -0
- data/lib/etch.rb +1391 -0
- data/lib/etchclient.rb +2420 -0
- data/lib/versiontype.rb +84 -0
- data/man/man8/etch.8 +204 -0
- metadata +78 -0
data/Rakefile
ADDED
@@ -0,0 +1,16 @@
|
|
1
|
+
require 'rake/gempackagetask'
|
2
|
+
spec = Gem::Specification.new do |s|
|
3
|
+
s.name = 'etch'
|
4
|
+
s.summary = 'Etch system configuration management client'
|
5
|
+
s.add_dependency('facter')
|
6
|
+
s.version = '3.12'
|
7
|
+
s.author = 'Jason Heiss'
|
8
|
+
s.email = 'etch-users@lists.sourceforge.net'
|
9
|
+
s.homepage = 'http://etch.sourceforge.net'
|
10
|
+
s.platform = Gem::Platform::RUBY
|
11
|
+
s.required_ruby_version = '>=1.8'
|
12
|
+
s.files = Dir['**/**']
|
13
|
+
s.executables = [ 'etch', 'etch_to_trunk', 'etch_cron_wrapper' ]
|
14
|
+
end
|
15
|
+
Rake::GemPackageTask.new(spec).define
|
16
|
+
|
data/bin/etch
ADDED
@@ -0,0 +1,101 @@
|
|
1
|
+
#!/usr/bin/ruby -w
|
2
|
+
##############################################################################
|
3
|
+
# Etch configuration file management tool
|
4
|
+
##############################################################################
|
5
|
+
|
6
|
+
# Ensure we can find etchclient.rb
|
7
|
+
$:.unshift(File.dirname(__FILE__))
|
8
|
+
|
9
|
+
require 'optparse'
|
10
|
+
require 'etchclient'
|
11
|
+
|
12
|
+
#
|
13
|
+
# Parse the command line options
|
14
|
+
#
|
15
|
+
|
16
|
+
options = {}
|
17
|
+
@generateall = nil
|
18
|
+
|
19
|
+
opts = OptionParser.new(nil, 24, ' ')
|
20
|
+
opts.banner = 'Usage: etch [options] [/path/to/config/file | command] [otherfile ...]'
|
21
|
+
opts.on('--generate-all', 'Request all configuration.') do |opt|
|
22
|
+
@generateall = opt
|
23
|
+
end
|
24
|
+
opts.on('--dry-run', '-n', 'Make no changes.') do |opt|
|
25
|
+
options[:dryrun] = opt
|
26
|
+
end
|
27
|
+
opts.on('--damp-run', "Perform a dry run but run 'setup' entries for files.") do |opt|
|
28
|
+
# Rather than sprinkle checks of two different variables throught the code, if
|
29
|
+
# we're asked to do a damp run then just set the dry run flag to a unique
|
30
|
+
# value. Then we can just check for that specific value at the one place where
|
31
|
+
# the two modes differ: enabling or disabling the execution of 'setup'
|
32
|
+
# entries.
|
33
|
+
options[:dryrun] = 'damp'
|
34
|
+
end
|
35
|
+
opts.on('--interactive', 'Prompt for confirmation before each change.') do |opt|
|
36
|
+
options[:interactive] = opt
|
37
|
+
end
|
38
|
+
opts.on('--full-file', 'Display full new file contents instead of a diff.') do |opt|
|
39
|
+
options[:fullfile] = opt
|
40
|
+
end
|
41
|
+
opts.on('--filename-only', 'Display filename of changed files instead of a diff.') do |opt|
|
42
|
+
options[:filenameonly] = opt
|
43
|
+
end
|
44
|
+
opts.on('--disable-force', 'Ignore the disable_etch file. Use with caution.') do |opt|
|
45
|
+
options[:disableforce] = opt
|
46
|
+
end
|
47
|
+
opts.on('--lock-force', 'Force the removal of any existing lockfiles.') do |opt|
|
48
|
+
options[:lockforce] = opt
|
49
|
+
end
|
50
|
+
opts.on('--local DIR', 'Read configuration from local directory, not server.') do |opt|
|
51
|
+
options[:local] = opt
|
52
|
+
end
|
53
|
+
opts.on('--server SERVER', 'Point etch to an alternate server.') do |opt|
|
54
|
+
options[:server] = opt
|
55
|
+
end
|
56
|
+
opts.on('--tag TAG', 'Request a specific repository tag from the server.') do |opt|
|
57
|
+
options[:tag] = opt
|
58
|
+
end
|
59
|
+
opts.on('--key PRIVATE_KEY', 'Use this private key for signing messages to server.') do |opt|
|
60
|
+
options[:key] = opt
|
61
|
+
end
|
62
|
+
opts.on('--test-base TESTDIR', 'Use an alternate local working directory.') do |opt|
|
63
|
+
options[:varbase] = opt
|
64
|
+
end
|
65
|
+
opts.on('--debug', 'Print lots of messages about what etch is doing.') do |opt|
|
66
|
+
options[:debug] = opt
|
67
|
+
end
|
68
|
+
opts.on('--version', 'Show etch client version.') do |opt|
|
69
|
+
puts Etch::Client::VERSION
|
70
|
+
exit
|
71
|
+
end
|
72
|
+
opts.on_tail('-h', '--help', 'Show this message.') do
|
73
|
+
puts opts
|
74
|
+
exit
|
75
|
+
end
|
76
|
+
|
77
|
+
leftovers = opts.parse(ARGV)
|
78
|
+
files = []
|
79
|
+
commands = []
|
80
|
+
leftovers.each do |leftover|
|
81
|
+
if leftover[0,1] == File::SEPARATOR
|
82
|
+
files << leftover
|
83
|
+
else
|
84
|
+
commands << leftover
|
85
|
+
end
|
86
|
+
end
|
87
|
+
|
88
|
+
# Display a usage message if the user did not specify a valid action to perform.
|
89
|
+
if files.empty? && commands.empty? && !@generateall
|
90
|
+
puts opts
|
91
|
+
exit
|
92
|
+
end
|
93
|
+
|
94
|
+
#
|
95
|
+
# Do stuff
|
96
|
+
#
|
97
|
+
|
98
|
+
etchclient = Etch::Client.new(options)
|
99
|
+
status = etchclient.process_until_done(files, commands)
|
100
|
+
exit status
|
101
|
+
|
@@ -0,0 +1,18 @@
|
|
1
|
+
#!/usr/bin/ruby -w
|
2
|
+
|
3
|
+
require 'socket'
|
4
|
+
require 'digest/sha1'
|
5
|
+
|
6
|
+
# Seed the random number generator with the hostname of this box so that
|
7
|
+
# we get a consistent random number. We want to run the registration at a
|
8
|
+
# consistent time on each individual box, but randomize the runs across
|
9
|
+
# the environment.
|
10
|
+
srand(Digest::SHA1.hexdigest(Socket.gethostname)[0,7].hex)
|
11
|
+
|
12
|
+
# Cron job is set to run every hour
|
13
|
+
MAX_SLEEP = 60 * 60
|
14
|
+
|
15
|
+
sleep(rand(MAX_SLEEP))
|
16
|
+
|
17
|
+
exec('/usr/sbin/etch', '--generate-all')
|
18
|
+
|
data/bin/etch_to_trunk
ADDED
@@ -0,0 +1,45 @@
|
|
1
|
+
#!/usr/bin/ruby -w
|
2
|
+
|
3
|
+
require 'nventory'
|
4
|
+
|
5
|
+
@username = ENV['LOGNAME']
|
6
|
+
|
7
|
+
if ARGV.length == 0
|
8
|
+
abort "Usage: #{File.basename($0)} <server1> [<server2> <server3>]"
|
9
|
+
end
|
10
|
+
|
11
|
+
# The etch servers run in UTC
|
12
|
+
ENV['TZ'] = 'UTC'
|
13
|
+
currentheadtag = Time.now.strftime('trunk-%Y%m%d-%H00')
|
14
|
+
|
15
|
+
# Find the requested clients
|
16
|
+
nvclient = NVentory::Client.new
|
17
|
+
results = nvclient.get_objects('nodes', {}, { 'name' => ARGV }, {}, {})
|
18
|
+
ARGV.each do |name|
|
19
|
+
if results.empty? && results[name].nil?
|
20
|
+
abort "No entry found for #{name}"
|
21
|
+
else
|
22
|
+
if !results[name]['config_mgmt_tag'].nil? &&
|
23
|
+
!results[name]['config_mgmt_tag'].empty?
|
24
|
+
puts "Changing #{name} from #{results[name]['config_mgmt_tag']} to #{currentheadtag}"
|
25
|
+
else
|
26
|
+
puts "Setting #{name} to #{currentheadtag}"
|
27
|
+
end
|
28
|
+
end
|
29
|
+
end
|
30
|
+
|
31
|
+
while true
|
32
|
+
print "Proceed? [y|n] "
|
33
|
+
response = $stdin.gets.chomp
|
34
|
+
if response == 'y'
|
35
|
+
break
|
36
|
+
elsif response == 'n'
|
37
|
+
exit
|
38
|
+
end
|
39
|
+
end
|
40
|
+
|
41
|
+
# Update the clients
|
42
|
+
successcount = nvclient.set_objects('nodes', results, {'config_mgmt_tag' => currentheadtag}, @username)
|
43
|
+
|
44
|
+
puts "#{File.basename($0)} operation succeeded for #{successcount} of #{results.size} nodes"
|
45
|
+
|
data/etc/ca.pem
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
# Add your SSL certificate authority's cert(s) to this file
|
data/etc/dhparams
ADDED
@@ -0,0 +1,9 @@
|
|
1
|
+
-----BEGIN DH PARAMETERS-----
|
2
|
+
MIIBCAKCAQEA3HySq1WdL67BCSRCJCZYMUIojAWAsvK63D3cOGk0wI9UeM/yeVhz
|
3
|
+
jTswvHOVPZFKIBg1Aeo2eAEdPryDnmjVTgvLbuWkCPouQhBCVsQ1El9ZcXPix1rC
|
4
|
+
tYsg4Kll1jgnwFoHf4xvjPnD/SqsASAiDxYlh4CFVyT1gLgSiUU0rIdudgO3agI5
|
5
|
+
NgiyGOKwyHmNOOQSKA62M/JnoxcBDC7Nou3lqtHpR5yWsUz+csyk+hXZeUba97bm
|
6
|
+
M8OB0PmfK4Vo6JpdO+yc8hjeYBoMsH7g/l3Gm1JqUxxctcY/OuJ+2nkXwsD66E3D
|
7
|
+
yZCoiVd3u4OqAxNO/GG0iUmskjIvokMhUwIBAg==
|
8
|
+
-----END DH PARAMETERS-----
|
9
|
+
|