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.
Files changed (5) hide show
  1. data/Rakefile +1 -1
  2. data/bin/etch +5 -2
  3. data/bin/etch_to_trunk +31 -7
  4. data/lib/etchclient.rb +75 -16
  5. 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.16.0'
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-base TESTDIR', 'Use an alternate local working directory.') do |opt|
63
- options[:varbase] = opt
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
- @username = ENV['LOGNAME']
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
- abort "Usage: #{File.basename($0)} <server1> [<server2> <server3>]"
26
+ puts opts
27
+ exit
9
28
  end
10
29
 
11
- # The etch servers run in UTC
12
- ENV['TZ'] = 'UTC'
13
- currentheadtag = Time.now.strftime('trunk-%Y%m%d-%H00')
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' => ARGV }, {}, {})
18
- ARGV.each do |name|
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.16.0'
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
- CONFIGDIR = '/etc'
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
- # Ensure we have a sane path, particularly since we are often run from
67
- # cron.
68
- # FIXME: Read from config file
69
- ENV['PATH'] = '/bin:/usr/bin:/sbin:/usr/sbin:/opt/csw/bin:/opt/csw/sbin'
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(CONFIGDIR, 'etch', 'dhparams'))
145
- dh = OpenSSL::PKey::DH.new(IO.read(File.join(CONFIGDIR, 'etch', 'dhparams')))
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(CONFIGDIR, 'etch', 'ca.pem'))
151
- http.ca_file = File.join(CONFIGDIR, 'etch', 'ca.pem')
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(CONFIGDIR, 'etch', 'ca'))
154
- http.ca_path = File.join(CONFIGDIR, 'etch', 'ca')
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
- version: 3.16.0
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-08-12 00:00:00 -07:00
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
- type: :runtime
18
- version_requirement:
19
- version_requirements: !ruby/object:Gem::Requirement
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
- version:
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.5
84
+ rubygems_version: 1.3.7
68
85
  signing_key:
69
86
  specification_version: 3
70
87
  summary: Etch system configuration management client