etch 3.16.0 → 3.17.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.
- data/Rakefile +1 -1
- data/bin/etch +5 -2
- data/bin/etch_to_trunk +31 -7
- data/lib/etchclient.rb +75 -16
- metadata +26 -9
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.
|
6
|
+
s.version = '3.17.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/bin/etch
CHANGED
@@ -16,6 +16,9 @@ require 'etchclient'
|
|
16
16
|
options = {}
|
17
17
|
@generateall = nil
|
18
18
|
|
19
|
+
# Extra options to OptionParser reduce the amount of whitespace it introduces
|
20
|
+
# into the help message, making it easier to make the help message fit in a
|
21
|
+
# 80x24 window.
|
19
22
|
opts = OptionParser.new(nil, 24, ' ')
|
20
23
|
opts.banner = 'Usage: etch [options] [/path/to/config/file | command] [otherfile ...]'
|
21
24
|
opts.on('--generate-all', 'Request all configuration.') do |opt|
|
@@ -59,8 +62,8 @@ end
|
|
59
62
|
opts.on('--key PRIVATE_KEY', 'Use this private key for signing messages to server.') do |opt|
|
60
63
|
options[:key] = opt
|
61
64
|
end
|
62
|
-
opts.on('--test-
|
63
|
-
options[:
|
65
|
+
opts.on('--test-root TESTDIR', 'For use by the test suite only.') do |opt|
|
66
|
+
options[:file_system_root] = opt
|
64
67
|
end
|
65
68
|
opts.on('--debug', 'Print lots of messages about what etch is doing.') do |opt|
|
66
69
|
options[:debug] = opt
|
data/bin/etch_to_trunk
CHANGED
@@ -1,21 +1,45 @@
|
|
1
1
|
#!/usr/bin/ruby -w
|
2
2
|
|
3
3
|
require 'nventory'
|
4
|
+
require 'time'
|
5
|
+
require 'optparse'
|
4
6
|
|
5
|
-
|
7
|
+
ETCH_SERVER_TZ = 'UTC' # The etch servers run in UTC
|
8
|
+
|
9
|
+
options = {}
|
10
|
+
opts = OptionParser.new
|
11
|
+
opts.banner = 'Usage: etch_to_trunk [options] <server1> [<server2> <server3>]'
|
12
|
+
opts.on('-u', '--username USERNAME', 'Username for connecting to nventory server.') do |opt|
|
13
|
+
options[:username] = opt
|
14
|
+
end
|
15
|
+
opts.on('-t', '--timezone TIMEZONE', 'Time zone of etch server.') do |opt|
|
16
|
+
options[:timezone] = opt
|
17
|
+
end
|
18
|
+
opts.on_tail('-h', '--help', 'Show this message.') do
|
19
|
+
puts opts
|
20
|
+
exit
|
21
|
+
end
|
22
|
+
|
23
|
+
nodes = opts.parse(ARGV)
|
6
24
|
|
7
25
|
if ARGV.length == 0
|
8
|
-
|
26
|
+
puts opts
|
27
|
+
exit
|
9
28
|
end
|
10
29
|
|
11
|
-
|
12
|
-
|
13
|
-
|
30
|
+
@username = options[:username] || ENV['LOGNAME']
|
31
|
+
etch_server_tz = options[:timezone] || ETCH_SERVER_TZ
|
32
|
+
|
33
|
+
if etch_server_tz
|
34
|
+
currentheadtag = Time.at(Time.now.utc + Time.zone_offset(etch_server_tz)).strftime('trunk-%Y%m%d-%H00')
|
35
|
+
else # if no timezone is specified then just use local time for the tag
|
36
|
+
currentheadtag = Time.now.strftime('trunk-%Y%m%d-%H00')
|
37
|
+
end
|
14
38
|
|
15
39
|
# Find the requested clients
|
16
40
|
nvclient = NVentory::Client.new
|
17
|
-
results = nvclient.get_objects('nodes', {}, { 'name' =>
|
18
|
-
|
41
|
+
results = nvclient.get_objects('nodes', {}, { 'name' => nodes }, {}, {})
|
42
|
+
nodes.each do |name|
|
19
43
|
if results.empty? && results[name].nil?
|
20
44
|
abort "No entry found for #{name}"
|
21
45
|
else
|
data/lib/etchclient.rb
CHANGED
@@ -35,13 +35,14 @@ require 'logger'
|
|
35
35
|
require 'etch'
|
36
36
|
|
37
37
|
class Etch::Client
|
38
|
-
VERSION = '3.
|
38
|
+
VERSION = '3.17.0'
|
39
39
|
|
40
40
|
CONFIRM_PROCEED = 1
|
41
41
|
CONFIRM_SKIP = 2
|
42
42
|
CONFIRM_QUIT = 3
|
43
43
|
PRIVATE_KEY_PATHS = ["/etc/ssh/ssh_host_rsa_key", "/etc/ssh_host_rsa_key"]
|
44
|
-
|
44
|
+
DEFAULT_CONFIGDIR = '/etc'
|
45
|
+
DEFAULT_VARBASE = '/var/etch'
|
45
46
|
|
46
47
|
# We need these in relation to the output capturing
|
47
48
|
ORIG_STDOUT = STDOUT.dup
|
@@ -52,7 +53,6 @@ class Etch::Client
|
|
52
53
|
def initialize(options)
|
53
54
|
@server = options[:server] ? options[:server] : 'https://etch'
|
54
55
|
@tag = options[:tag]
|
55
|
-
@varbase = options[:varbase] ? options[:varbase] : '/var/etch'
|
56
56
|
@local = options[:local] ? File.expand_path(options[:local]) : nil
|
57
57
|
@debug = options[:debug]
|
58
58
|
@dryrun = options[:dryrun]
|
@@ -63,10 +63,72 @@ class Etch::Client
|
|
63
63
|
@disableforce = options[:disableforce]
|
64
64
|
@lockforce = options[:lockforce]
|
65
65
|
|
66
|
-
|
67
|
-
|
68
|
-
|
69
|
-
|
66
|
+
@configdir = DEFAULT_CONFIGDIR
|
67
|
+
@varbase = DEFAULT_VARBASE
|
68
|
+
|
69
|
+
@file_system_root = '/' # Not sure if this needs to be more portable
|
70
|
+
# This option is only intended for use by the test suite
|
71
|
+
if options[:file_system_root]
|
72
|
+
@file_system_root = options[:file_system_root]
|
73
|
+
@varbase = File.join(@file_system_root, @varbase)
|
74
|
+
@configdir = File.join(@file_system_root, @configdir)
|
75
|
+
end
|
76
|
+
|
77
|
+
@configfile = File.join(@configdir, 'etch.conf')
|
78
|
+
|
79
|
+
if File.exist?(@configfile)
|
80
|
+
IO.foreach(@configfile) do |line|
|
81
|
+
line.chomp!
|
82
|
+
next if (line =~ /^\s*$/); # Skip blank lines
|
83
|
+
next if (line =~ /^\s*#/); # Skip comments
|
84
|
+
line.strip! # Remove leading/trailing whitespace
|
85
|
+
key, value = line.split(/\s*=\s*/, 2)
|
86
|
+
if key == 'server'
|
87
|
+
# A setting for the server to use which comes from upstream
|
88
|
+
# (generally from a command line option) takes precedence
|
89
|
+
# over the config file
|
90
|
+
if !options[:server]
|
91
|
+
@server = value
|
92
|
+
# Warn the user, as this could potentially be confusing
|
93
|
+
# if they don't realize there's a config file lying
|
94
|
+
# around
|
95
|
+
warn "Using server #{@server} from #{@configfile}" if @debug
|
96
|
+
else
|
97
|
+
# "command line override" isn't necessarily accurate, we don't
|
98
|
+
# know why the caller passed us an option to override the config
|
99
|
+
# file, but most of the time it will be due to a command line
|
100
|
+
# option and I want the message to be easily understood by users.
|
101
|
+
# If someone can come up with some better wording without turning
|
102
|
+
# the message into something as long as this comment that would be
|
103
|
+
# welcome.
|
104
|
+
warn "Ignoring 'server' option in #{@configfile} due to command line override" if @debug
|
105
|
+
end
|
106
|
+
elsif key == 'local'
|
107
|
+
if !options[:local] && !options[:server]
|
108
|
+
@local = value
|
109
|
+
warn "Using local directory #{@local} from #{@configfile}" if @debug
|
110
|
+
else
|
111
|
+
warn "Ignoring 'local' option in #{@configfile} due to command line override" if @debug
|
112
|
+
end
|
113
|
+
elsif key == 'key'
|
114
|
+
if !options[:key]
|
115
|
+
@key = value
|
116
|
+
warn "Using key #{@key} from #{@configfile}" if @debug
|
117
|
+
else
|
118
|
+
warn "Ignoring 'key' option in #{@configfile} due to command line override" if @debug
|
119
|
+
end
|
120
|
+
elsif key == 'path'
|
121
|
+
ENV['PATH'] = value
|
122
|
+
end
|
123
|
+
end
|
124
|
+
end
|
125
|
+
|
126
|
+
if @key && !File.readable?(@key)
|
127
|
+
@key = nil
|
128
|
+
end
|
129
|
+
if !@key
|
130
|
+
warn "No readable private key found, messages to server will not be signed and may be rejected depending on server configuration"
|
131
|
+
end
|
70
132
|
|
71
133
|
@origbase = File.join(@varbase, 'orig')
|
72
134
|
@historybase = File.join(@varbase, 'history')
|
@@ -141,17 +203,17 @@ class Etch::Client
|
|
141
203
|
http = Net::HTTP.new(@filesuri.host, @filesuri.port)
|
142
204
|
if @filesuri.scheme == "https"
|
143
205
|
# Eliminate the OpenSSL "using default DH parameters" warning
|
144
|
-
if File.exist?(File.join(
|
145
|
-
dh = OpenSSL::PKey::DH.new(IO.read(File.join(
|
206
|
+
if File.exist?(File.join(@configdir, 'etch', 'dhparams'))
|
207
|
+
dh = OpenSSL::PKey::DH.new(IO.read(File.join(@configdir, 'etch', 'dhparams')))
|
146
208
|
Net::HTTP.ssl_context_accessor(:tmp_dh_callback)
|
147
209
|
http.tmp_dh_callback = proc { dh }
|
148
210
|
end
|
149
211
|
http.use_ssl = true
|
150
|
-
if File.exist?(File.join(
|
151
|
-
http.ca_file = File.join(
|
212
|
+
if File.exist?(File.join(@configdir, 'etch', 'ca.pem'))
|
213
|
+
http.ca_file = File.join(@configdir, 'etch', 'ca.pem')
|
152
214
|
http.verify_mode = OpenSSL::SSL::VERIFY_PEER
|
153
|
-
elsif File.directory?(File.join(
|
154
|
-
http.ca_path = File.join(
|
215
|
+
elsif File.directory?(File.join(@configdir, 'etch', 'ca'))
|
216
|
+
http.ca_path = File.join(@configdir, 'etch', 'ca')
|
155
217
|
http.verify_mode = OpenSSL::SSL::VERIFY_PEER
|
156
218
|
end
|
157
219
|
end
|
@@ -2409,9 +2471,6 @@ class Etch::Client
|
|
2409
2471
|
break
|
2410
2472
|
end
|
2411
2473
|
end
|
2412
|
-
if !key
|
2413
|
-
warn "No readable private key found, messages to server will not be signed and may be rejected depending on server configuration"
|
2414
|
-
end
|
2415
2474
|
key
|
2416
2475
|
end
|
2417
2476
|
|
metadata
CHANGED
@@ -1,7 +1,13 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: etch
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
|
4
|
+
hash: 67
|
5
|
+
prerelease: false
|
6
|
+
segments:
|
7
|
+
- 3
|
8
|
+
- 17
|
9
|
+
- 0
|
10
|
+
version: 3.17.0
|
5
11
|
platform: ruby
|
6
12
|
authors:
|
7
13
|
- Jason Heiss
|
@@ -9,19 +15,23 @@ autorequire:
|
|
9
15
|
bindir: bin
|
10
16
|
cert_chain: []
|
11
17
|
|
12
|
-
date: 2010-
|
18
|
+
date: 2010-12-22 00:00:00 -08:00
|
13
19
|
default_executable:
|
14
20
|
dependencies:
|
15
21
|
- !ruby/object:Gem::Dependency
|
16
22
|
name: facter
|
17
|
-
|
18
|
-
|
19
|
-
|
23
|
+
prerelease: false
|
24
|
+
requirement: &id001 !ruby/object:Gem::Requirement
|
25
|
+
none: false
|
20
26
|
requirements:
|
21
27
|
- - ">="
|
22
28
|
- !ruby/object:Gem::Version
|
29
|
+
hash: 3
|
30
|
+
segments:
|
31
|
+
- 0
|
23
32
|
version: "0"
|
24
|
-
|
33
|
+
type: :runtime
|
34
|
+
version_requirements: *id001
|
25
35
|
description:
|
26
36
|
email: etch-users@lists.sourceforge.net
|
27
37
|
executables:
|
@@ -50,21 +60,28 @@ rdoc_options: []
|
|
50
60
|
require_paths:
|
51
61
|
- lib
|
52
62
|
required_ruby_version: !ruby/object:Gem::Requirement
|
63
|
+
none: false
|
53
64
|
requirements:
|
54
65
|
- - ">="
|
55
66
|
- !ruby/object:Gem::Version
|
67
|
+
hash: 31
|
68
|
+
segments:
|
69
|
+
- 1
|
70
|
+
- 8
|
56
71
|
version: "1.8"
|
57
|
-
version:
|
58
72
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
73
|
+
none: false
|
59
74
|
requirements:
|
60
75
|
- - ">="
|
61
76
|
- !ruby/object:Gem::Version
|
77
|
+
hash: 3
|
78
|
+
segments:
|
79
|
+
- 0
|
62
80
|
version: "0"
|
63
|
-
version:
|
64
81
|
requirements: []
|
65
82
|
|
66
83
|
rubyforge_project: etchsyscm
|
67
|
-
rubygems_version: 1.3.
|
84
|
+
rubygems_version: 1.3.7
|
68
85
|
signing_key:
|
69
86
|
specification_version: 3
|
70
87
|
summary: Etch system configuration management client
|