From: <jh...@us...> - 2009-04-02 00:21:36
|
Revision: 79 http://etch.svn.sourceforge.net/etch/?rev=79&view=rev Author: jheiss Date: 2009-04-02 00:21:34 +0000 (Thu, 02 Apr 2009) Log Message: ----------- Convert the cron wrapper script to Ruby so that the client package has no dependency on Perl. Modified Paths: -------------- trunk/client/control trunk/client/depend trunk/client/etch_cron_wrapper Modified: trunk/client/control =================================================================== --- trunk/client/control 2009-04-02 00:20:54 UTC (rev 78) +++ trunk/client/control 2009-04-02 00:21:34 UTC (rev 79) @@ -2,6 +2,6 @@ Version: 1.1-1 Maintainer: etc...@li... Architecture: all -Depends: ruby facter rcs libdigest-sha1-perl +Depends: ruby facter rcs Description: Etch client Modified: trunk/client/depend =================================================================== --- trunk/client/depend 2009-04-02 00:20:54 UTC (rev 78) +++ trunk/client/depend 2009-04-02 00:21:34 UTC (rev 79) @@ -1,5 +1,4 @@ P CSWruby P CSWfacter -P CSWpmdigestsha1 P CSWrcs Modified: trunk/client/etch_cron_wrapper =================================================================== --- trunk/client/etch_cron_wrapper 2009-04-02 00:20:54 UTC (rev 78) +++ trunk/client/etch_cron_wrapper 2009-04-02 00:21:34 UTC (rev 79) @@ -1,20 +1,18 @@ -#!/usr/bin/perl +#!/usr/bin/ruby -w -use Digest::SHA1 qw(sha1_hex); -use Sys::Hostname; -use strict; -use warnings; +require 'socket' +require 'digest/sha1' # Seed the random number generator with the hostname of this box so that # we get a consistent random number. We want to run the registration at a # consistent time on each individual box, but randomize the runs across # the environment. -srand(hex(substr(sha1_hex(hostname), 0, 7))); +srand(Digest::SHA1.hexdigest(Socket.gethostname)[0,7].hex) # Cron job is set to run every hour -my $MAX_SLEEP = 60 * 60; +MAX_SLEEP = 60 * 60 -sleep(int(rand($MAX_SLEEP))); +sleep(rand(MAX_SLEEP)) -exec '/usr/sbin/etch', '--generate-all'; +exec('/usr/sbin/etch', '--generate-all') This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <jh...@us...> - 2009-09-11 16:59:30
|
Revision: 87 http://etch.svn.sourceforge.net/etch/?rev=87&view=rev Author: jheiss Date: 2009-09-11 16:59:21 +0000 (Fri, 11 Sep 2009) Log Message: ----------- Added authentication support. The client will sign messages using its ssh host key. Add support for local requests. Update the method used to eliminate the OpenSSL "using default DH parameters" warning. http://techbits.blogspot.com/2009/08/ive-been-using-workaround-shown-at.html Add timeout to output capturing so that ill-behaved daemons don't cause etch to hang around forever. Add unit tests for output capturing. Note that the output capturing timeout test is commented out as the timeout is rather long, thus causing the test to take a long time to run. Not quite sure the best way to handle that. Move Etch::Client.initialize arguments to a hash so that the method doesn't take 10 or whatever arguments. Set etch version as a constant in the library (Etch::Client::VERSION). Add a command line option to etch to display the version. Modify the make targets to insert the version into the appropriate place rather than having the version hard-coded in a bunch of files. Add redhatprep, debianprep and solarisprep targets which install the packages necessary to extract the version from the library file. Add code to require rubygems if requiring facter fails. Change /usr/lib/ruby/site_ruby to /usr/local/lib/ruby/site_ruby for the Debian package. That seems to be the correct location on Debian systems. Modified Paths: -------------- trunk/client/Makefile trunk/client/control trunk/client/etch trunk/client/etch-client.spec trunk/client/etch.rb trunk/client/pkginfo Added Paths: ----------- trunk/client/dhparams Modified: trunk/client/Makefile =================================================================== --- trunk/client/Makefile 2009-06-25 00:13:39 UTC (rev 86) +++ trunk/client/Makefile 2009-09-11 16:59:21 UTC (rev 87) @@ -1,13 +1,15 @@ -# When updating the version number you currently need to update -# etch-client.spec, control and pkginfo as well -VER=1.1 +BUILDROOT=/var/tmp/etch-client-buildroot +# Grab the current version from the library +VER=$(shell ruby -e "$$:.unshift('.'); require 'etch'; puts Etch::Client::VERSION") all: -redhat: rpmbuild-redhat rpm -rpmbuild-redhat: - rpm --quiet -q rpm-build || yum -y install rpm-build -BUILDROOT=/var/tmp/etch-client-buildroot +redhat: redhatprep rpm +redhatprep: + # Install everything needed for the command which sets VER above + rpm --quiet -q ruby || sudo yum install ruby + # And the package which contains the rpmbuild command + rpm --quiet -q rpm-build || sudo yum install rpm-build TMPSPEC = etch-client-temp.spec rpm: etch-client.spec # @@ -22,6 +24,7 @@ chmod 444 $(BUILDROOT)/usr/lib/ruby/site_ruby/1.8/etch.rb mkdir -p $(BUILDROOT)/etc/etch cp -p ca.pem $(BUILDROOT)/etc/etch + cp -p dhparams $(BUILDROOT)/etc/etch # Cron job mkdir -p $(BUILDROOT)/etc/cron.d cp etch_cron $(BUILDROOT)/etc/cron.d/etch @@ -30,26 +33,38 @@ # # Now build the package # - rpmbuild -bb --buildroot $(BUILDROOT) etch-client.spec + sed 's/VER/$(VER)/' etch-client.spec > etch-client.spec_withversion + rpmbuild -bb --buildroot $(BUILDROOT) etch-client.spec_withversion rm -rf $(BUILDROOT) -debian: control - rm -rf debtmp - mkdir -p debtmp/DEBIAN - grep -v '^#' control > debtmp/DEBIAN/control - mkdir -p debtmp/usr/sbin - cp -p etch debtmp/usr/sbin - chmod 555 debtmp/usr/sbin/etch - mkdir -p debtmp/usr/lib/ruby/site_ruby/1.8 - cp -p etch.rb debtmp/usr/lib/ruby/site_ruby/1.8 - chmod 444 debtmp/usr/lib/ruby/site_ruby/1.8 - mkdir -p debtmp/etc/etch - cp -p ca.pem debtmp/etc/etch - sudo chown -R 0:0 debtmp - dpkg --build debtmp etch-client-$(VER).deb - rm -rf debtmp +debian: debianprep deb +debianprep: + # Install everything needed for the command which sets VER above + sudo apt-get --no-upgrade --quiet install ruby libopenssl-ruby rubygems facter +deb: control + rm -rf $(BUILDROOT) + mkdir -p $(BUILDROOT)/DEBIAN + grep -v '^#' control | sed 's/VER/$(VER)/' > $(BUILDROOT)/DEBIAN/control + mkdir -p $(BUILDROOT)/usr/sbin + cp -p etch $(BUILDROOT)/usr/sbin + chmod 555 $(BUILDROOT)/usr/sbin/etch + mkdir -p $(BUILDROOT)/usr/local/lib/site_ruby/1.8 + cp -p etch.rb $(BUILDROOT)/usr/local/lib/site_ruby/1.8 + chmod 444 $(BUILDROOT)/usr/local/lib/site_ruby/1.8/etch.rb + mkdir -p $(BUILDROOT)/etc/etch + cp -p ca.pem $(BUILDROOT)/etc/etch + cp -p dhparams $(BUILDROOT)/etc/etch + sudo chown -R 0:0 $(BUILDROOT) + dpkg --build $(BUILDROOT) etch-client-$(VER).deb + rm -rf $(BUILDROOT) -solaris: pkginfo depend +solaris: solarisprep sysvpkg sysvpkg-sparc +solarisprep: + # Install everything needed for the command which sets VER above + pkginfo -q CSWruby || sudo pkg-get -i ruby + pkginfo -q CSWrubygems || sudo pkg-get -i rubygems + pkginfo -q CSWfacter || sudo pkg-get -i facter +sysvpkg: pkginfo depend # # Create package file structure in build root # @@ -65,27 +80,33 @@ chmod 444 $(BUILDROOT)/opt/csw/lib/ruby/site_ruby/1.8/etch.rb mkdir -p $(BUILDROOT)/etc/etch cp -p ca.pem $(BUILDROOT)/etc/etch + cp -p dhparams $(BUILDROOT)/etc/etch # Cron job for registration cat etch_cron_wrapper | sed 's,/usr/bin/perl,/opt/csw/bin/perl,' > $(BUILDROOT)/usr/sbin/etch_cron_wrapper chmod 555 $(BUILDROOT)/usr/sbin/etch_cron_wrapper # # Now build the package # - echo "i pkginfo=./pkginfo" > prototype - echo "i depend=./depend" >> prototype - echo "i postinstall=./postinstall" >> prototype - echo "i postremove=./postremove" >> prototype + rm -rf solbuild + mkdir solbuild + sed 's/%VER%/$(VER)/' pkginfo > solbuild/pkginfo + echo "i pkginfo=./pkginfo" > solbuild/prototype + cp depend solbuild/depend + echo "i depend=./depend" >> solbuild/prototype + cp postinstall solbuild/postinstall + echo "i postinstall=./postinstall" >> solbuild/prototype + cp postremove solbuild/postremove + echo "i postremove=./postremove" >> solbuild/prototype # The tail +2 removes the first line, which is the base directory # and doesn't need to be included in the package. # The first sed just cleans up the directory names # The second sed tell pkgadd to not force our permissions on directories # The $$ in that sed escapes the $ from make - find $(BUILDROOT) | pkgproto | tail +2 | sed "s,$(BUILDROOT),," | sed '/^d/s/[^ ]* [^ ]* [^ ]*$$/? ? ?/' >> prototype - pkgmk -r $(BUILDROOT) -d $(PWD) - pkgtrans . YPCetch-$(VER).pkg YPCetch - rm -rf YPCetch + find $(BUILDROOT) | pkgproto | tail +2 | sed "s,$(BUILDROOT),," | sed '/^d/s/[^ ]* [^ ]* [^ ]*$$/? ? ?/' >> solbuild/prototype + cd solbuild && pkgmk -r $(BUILDROOT) -d $(PWD)/solbuild + pkgtrans solbuild ../YPCetch-$(VER).pkg YPCetch + rm -rf solbuild rm -rf $(BUILDROOT) - rm -f prototype # On Sparc systems we're having problems with the CSW/Blastwave ruby # core dumping when running etch. The Sunfreeware ruby seems to work. @@ -94,7 +115,7 @@ # our library file (etch.rb) into /opt/csw. We modify etch to use # the Sunfreeware ruby in /usr/local/bin, but then tell it to also look # in the /opt/csw directory for libraries. -solaris-sparc: pkginfo depend +sysvpkg-sparc: pkginfo depend # # Create package file structure in build root # @@ -114,25 +135,31 @@ chmod 444 $(BUILDROOT)/opt/csw/lib/ruby/site_ruby/1.8/etch.rb mkdir -p $(BUILDROOT)/etc/etch cp -p ca.pem $(BUILDROOT)/etc/etch + cp -p dhparams $(BUILDROOT)/etc/etch # Cron job for registration cat etch_cron_wrapper | sed 's,/usr/bin/perl,/opt/csw/bin/perl,' > $(BUILDROOT)/usr/sbin/etch_cron_wrapper chmod 555 $(BUILDROOT)/usr/sbin/etch_cron_wrapper # # Now build the package # - echo "i pkginfo=./pkginfo" > prototype - echo "i depend=./depend" >> prototype - echo "i postinstall=./postinstall" >> prototype - echo "i postremove=./postremove" >> prototype + rm -rf solbuild + mkdir solbuild + sed 's/%VER%/$(VER)/' pkginfo > solbuild/pkginfo + echo "i pkginfo=./pkginfo" > solbuild/prototype + cp depend solbuild/depend + echo "i depend=./depend" >> solbuild/prototype + cp postinstall solbuild/postinstall + echo "i postinstall=./postinstall" >> solbuild/prototype + cp postremove solbuild/postremove + echo "i postremove=./postremove" >> solbuild/prototype # The tail +2 removes the first line, which is the base directory # and doesn't need to be included in the package. # The first sed just cleans up the directory names # The second sed tell pkgadd to not force our permissions on directories # The $$ in that sed escapes the $ from make - find $(BUILDROOT) | pkgproto | tail +2 | sed "s,$(BUILDROOT),," | sed '/^d/s/[^ ]* [^ ]* [^ ]*$$/? ? ?/' >> prototype - pkgmk -r $(BUILDROOT) -d $(PWD) - pkgtrans . YPCetch-$(VER)-sparc.pkg YPCetch - rm -rf YPCetch + find $(BUILDROOT) | pkgproto | tail +2 | sed "s,$(BUILDROOT),," | sed '/^d/s/[^ ]* [^ ]* [^ ]*$$/? ? ?/' >> solbuild/prototype + cd solbuild && pkgmk -r $(BUILDROOT) -d $(PWD)/solbuild + pkgtrans solbuild ../YPCetch-$(VER)-sparc.pkg YPCetch + rm -rf solbuild rm -rf $(BUILDROOT) - rm -f prototype Modified: trunk/client/control =================================================================== --- trunk/client/control 2009-06-25 00:13:39 UTC (rev 86) +++ trunk/client/control 2009-09-11 16:59:21 UTC (rev 87) @@ -1,5 +1,5 @@ Package: etch-client -Version: 1.1-1 +Version: VER-1 Maintainer: etc...@li... Architecture: all Depends: ruby facter rcs Added: trunk/client/dhparams =================================================================== --- trunk/client/dhparams (rev 0) +++ trunk/client/dhparams 2009-09-11 16:59:21 UTC (rev 87) @@ -0,0 +1,9 @@ +-----BEGIN DH PARAMETERS----- +MIIBCAKCAQEA3HySq1WdL67BCSRCJCZYMUIojAWAsvK63D3cOGk0wI9UeM/yeVhz +jTswvHOVPZFKIBg1Aeo2eAEdPryDnmjVTgvLbuWkCPouQhBCVsQ1El9ZcXPix1rC +tYsg4Kll1jgnwFoHf4xvjPnD/SqsASAiDxYlh4CFVyT1gLgSiUU0rIdudgO3agI5 +NgiyGOKwyHmNOOQSKA62M/JnoxcBDC7Nou3lqtHpR5yWsUz+csyk+hXZeUba97bm +M8OB0PmfK4Vo6JpdO+yc8hjeYBoMsH7g/l3Gm1JqUxxctcY/OuJ+2nkXwsD66E3D +yZCoiVd3u4OqAxNO/GG0iUmskjIvokMhUwIBAg== +-----END DH PARAMETERS----- + Modified: trunk/client/etch =================================================================== --- trunk/client/etch 2009-06-25 00:13:39 UTC (rev 86) +++ trunk/client/etch 2009-09-11 16:59:21 UTC (rev 87) @@ -13,25 +13,16 @@ # Parse the command line options # -$generateall = nil -$dryrun = nil -$interactive = nil -$fullfile = nil -$filenameonly = nil -$disableforce = nil -$lockforce = nil -$debug = nil -$server = nil -$tag = nil -$varbase = nil +options = {} +@generateall = nil opts = OptionParser.new opts.banner = 'Usage: etch [options] [/path/to/config/file]' opts.on('--generate-all', 'Can be used instead of giving a specific file to generate.') do |opt| - $generateall = opt + @generateall = opt end opts.on('--dry-run', '-n', 'Prints contents of generated files instead of writing them out to disk.') do |opt| - $dryrun = opt + options[:dryrun] = opt end opts.on('--damp-run', "Perform a dry run but run 'setup' entries for files. Normally all setup/pre/post entries are ignored for a dry run. However, files with setup entries will generally fail to build if the setup entry hasn't been run.") do |opt| # Rather than sprinkle checks of two different variables throught the code, if @@ -39,35 +30,42 @@ # value. Then we can just check for that specific value at the one place where # the two modes differ: enabling or disabling the execution of 'setup' # entries. - $dryrun = 'damp' + options[:dryrun] = 'damp' end opts.on('--interactive', 'Causes etch to pause before making each change and prompt the user for confirmation.') do |opt| - $interactive = opt + options[:interactive] = opt end opts.on('--full-file', 'Normally etch will print a diff to show what changes it will make to a file. This will cause etch to display the full new file contents instead.') do |opt| - $fullfile = opt + options[:fullfile] = opt end opts.on('--filename-only', 'Similar to the previous option, but in the opposite direction. Etch will only display the name of file to be changed.') do |opt| - $filenameonly = opt + options[:filenameonly] = opt end opts.on('--disable-force', 'Ignore the disable_etch file. Use with caution.') do |opt| - $disableforce = opt + options[:disableforce] = opt end opts.on('--lock-force', 'Force the removal of any existing lockfiles. Normally only lockfile over 2 hours old are removed.') do |opt| - $lockforce = opt + options[:lockforce] = opt end opts.on('--debug', 'Print lots of messages about what etch is doing') do |opt| - $debug = opt + options[:debug] = opt end opts.on('--server SERVER', 'Point etch to an alternate server') do |opt| - $server = opt + options[:server] = opt end opts.on('--tag TAG', 'Request a specific repository tag from the server') do |opt| - $tag = opt + options[:tag] = opt end opts.on('--test-base TESTDIR', 'Use an alternate local working directory (for use by test suite only)') do |opt| - $varbase = opt + options[:varbase] = opt end +opts.on('--key PRIVATE_KEY', 'Use this private key for signing messages that are sent to the server') do |opt| + options[:key] = opt +end +opts.on('--version', 'Show etch client version') do |opt| + puts Etch::Client::VERSION + exit +end opts.on_tail("-h", "--help", "Show this message") do puts opts exit @@ -77,7 +75,7 @@ files_to_generate = opts.parse(ARGV) # Display a usage message if the user did not specify a valid action to perform. -unless (!files_to_generate.nil? && !files_to_generate.empty?) || $generateall +unless (!files_to_generate.nil? && !files_to_generate.empty?) || @generateall puts opts exit end @@ -86,7 +84,7 @@ # Do stuff # -etchclient = Etch::Client.new($server, $tag, $varbase, $debug, $dryrun, $interactive, $filenameonly, $fullfile) -status = etchclient.process_until_done(files_to_generate, $disableforce, $lockforce) +etchclient = Etch::Client.new(options) +status = etchclient.process_until_done(files_to_generate) exit status Modified: trunk/client/etch-client.spec =================================================================== --- trunk/client/etch-client.spec 2009-06-25 00:13:39 UTC (rev 86) +++ trunk/client/etch-client.spec 2009-09-11 16:59:21 UTC (rev 87) @@ -1,6 +1,6 @@ Name: etch-client Summary: Etch client -Version: 1.1 +Version: VER Release: 1 Group: Applications/System License: MIT Modified: trunk/client/etch.rb =================================================================== --- trunk/client/etch.rb 2009-06-25 00:13:39 UTC (rev 86) +++ trunk/client/etch.rb 2009-09-11 16:59:21 UTC (rev 87) @@ -2,9 +2,17 @@ # Etch configuration file management tool library ############################################################################## -require 'facter' +begin + # Try loading facter w/o gems first so that we don't introduce a + # dependency on gems if it is not needed. + require 'facter' # Facter +rescue LoadError + require 'rubygems' + require 'facter' +end require 'find' require 'digest/sha1' # hexdigest +require 'openssl' # OpenSSL require 'base64' # decode64, encode64 require 'uri' require 'net/http' @@ -14,24 +22,19 @@ require 'fcntl' # Fcntl::O_* require 'etc' # getpwnam, getgrnam require 'tempfile' # Tempfile +require 'cgi' +require 'timeout' -# clean up "using default DH parameters" warning for https -# http://blog.zenspider.com/2008/05/httpsssl-warning-cleanup.html -class Net::HTTP - alias :old_use_ssl= :use_ssl= - def use_ssl= flag - self.old_use_ssl = flag - @ssl_context.tmp_dh_callback = proc {} - end -end - module Etch end class Etch::Client + VERSION = '1.13' + CONFIRM_PROCEED = 1 CONFIRM_SKIP = 2 CONFIRM_QUIT = 3 + PRIVATE_KEY_PATHS = ["/etc/ssh/ssh_host_rsa_key", "/etc/ssh_host_rsa_key"] # We need these in relation to the output capturing ORIG_STDOUT = STDOUT.dup @@ -39,16 +42,18 @@ attr_reader :exec_once_per_run - # Cutting down the size of the arg list would be nice - def initialize(server=nil, tag=nil, varbase=nil, debug=false, dryrun=false, interactive=false, filenameonly=false, fullfile=false) - @server = server.nil? ? 'https://etch' : server - @tag = tag - @varbase = varbase.nil? ? '/var/etch' : varbase - @debug = debug - @dryrun = dryrun - @interactive = interactive - @filenameonly = filenameonly - @fullfile = fullfile + def initialize(options) + @server = options[:server] ? options[:server] : 'https://etch' + @tag = options[:tag] + @varbase = options[:varbase] ? options[:varbase] : '/var/etch' + @debug = options[:debug] + @dryrun = options[:dryrun] + @interactive = options[:interactive] + @filenameonly = options[:filenameonly] + @fullfile = options[:fullfile] + @key = options[:key] ? options[:key] : get_private_key_path + @disableforce = options[:disableforce] + @lockforce = options[:lockforce] # Ensure we have a sane path, particularly since we are often run from # cron. @@ -61,10 +66,17 @@ @origbase = File.join(@varbase, 'orig') @historybase = File.join(@varbase, 'history') @lockbase = File.join(@varbase, 'locks') + @requestbase = File.join(@varbase, 'requests') @blankrequest = {} @facts = Facter.to_hash + # If the user specified a non-standard key then override the sshrsakey + # fact so that authentication works + if @key + @facts['sshrsakey'] = IO.read(@key+'.pub').chomp.split[1] + end @facts.each_pair { |key, value| @blankrequest["facts[#{key}]"] = value.to_s } + @blankrequest['fqdn'] = @facts['fqdn'] if @facts['operatingsystemrelease'] # Some versions of Facter have a bug that leaves extraneous # whitespace on this fact. Work around that with strip. I.e. on @@ -90,8 +102,8 @@ @lchown_supported = nil @lchmod_supported = nil end - - def process_until_done(files_to_generate, disableforce, lockforce) + + def process_until_done(files_to_generate) # Our overall status. Will be reported to the server and used as the # return value for this method. Command-line clients should use it as # their exit value. Zero indicates no errors. @@ -100,6 +112,12 @@ http = Net::HTTP.new(@filesuri.host, @filesuri.port) if @filesuri.scheme == "https" + # Eliminate the OpenSSL "using default DH parameters" warning + if File.exist?('/etc/etch/dhparams') + dh = OpenSSL::PKey::DH.new(IO.read('/etc/etch/dhparams')) + Net::HTTP.ssl_context_accessor(:tmp_dh_callback) + http.tmp_dh_callback = proc { dh } + end http.use_ssl = true if File.exist?('/etc/etch/ca.pem') http.ca_file = '/etc/etch/ca.pem' @@ -115,14 +133,14 @@ # begin/raise for error events that end processing catch :stop_processing do begin - enabled, message = check_for_disable_etch_file(disableforce) + enabled, message = check_for_disable_etch_file if !enabled # 200 is the arbitrarily picked exit value indicating # that etch is disabled status = 200 throw :stop_processing end - remove_stale_lock_files(lockforce) + remove_stale_lock_files # Assemble the initial request request = get_blank_request @@ -130,6 +148,10 @@ if !files_to_generate.nil? && !files_to_generate.empty? files_to_generate.each do |file| request["files[#{CGI.escape(file)}][sha1sum]"] = get_orig_sum(file) + local_requests = get_local_requests(file) + if local_requests + request["files[#{CGI.escape(file)}][local_requests]"] = local_requests + end end else request['files[GENERATEALL]'] = '1' @@ -155,6 +177,7 @@ puts "Sending request to server #{@filesuri}" if (@debug) post = Net::HTTP::Post.new(@filesuri.path) post.set_form_data(request) + sign_post!(post, @key) response = http.request(post) response_xml = nil case response @@ -198,12 +221,20 @@ response_xml.root.elements.each('/files/need_sums/need_sum') do |need_sum| puts "Processing request for sum of #{need_sum.text}" if (@debug) request["files[#{CGI.escape(need_sum.text)}][sha1sum]"] = get_orig_sum(need_sum.text) + local_requests = get_local_requests(need_sum.text) + if local_requests + request["files[#{CGI.escape(need_sum.text)}][local_requests]"] = local_requests + end need_to_loop = true end response_xml.root.elements.each('/files/need_origs/need_orig') do |need_orig| puts "Processing request for contents of #{need_orig.text}" if (@debug) request["files[#{CGI.escape(need_orig.text)}][contents]"] = Base64.encode64(get_orig_contents(need_orig.text)) request["files[#{CGI.escape(need_orig.text)}][sha1sum]"] = get_orig_sum(need_orig.text) + local_requests = get_local_requests(need_orig.text) + if local_requests + request["files[#{CGI.escape(need_orig.text)}][local_requests]"] = local_requests + end need_to_loop = true end @@ -226,17 +257,18 @@ # Send results to server if !@dryrun rails_results = [] - # CGI.escape doesn't work on things that aren't strings, so we don't - # call it on a few of the fields here that are numbers or booleans + # A few of the fields here are numbers or booleans and need a + # to_s to make them compatible with CGI.escape, which expects a + # string. rails_results << "fqdn=#{CGI.escape(@facts['fqdn'])}" - rails_results << "status=#{status}" + rails_results << "status=#{CGI.escape(status.to_s)}" rails_results << "message=#{CGI.escape(message)}" @results.each do |result| # Strangely enough this works. Even though the key is not unique to # each result the Rails parameter parsing code keeps track of keys it # has seen, and if it sees a duplicate it starts a new hash. rails_results << "results[][file]=#{CGI.escape(result['file'])}" - rails_results << "results[][success]=#{result['success']}" + rails_results << "results[][success]=#{CGI.escape(result['success'].to_s)}" rails_results << "results[][message]=#{CGI.escape(result['message'])}" end puts "Sending results to server #{@resultsuri}" if (@debug) @@ -244,8 +276,10 @@ # We have to bypass Net::HTTP's set_form_data method in this case # because it expects a hash and we can't provide the results in the # format we want in a hash because we'd have duplicate keys (see above). - resultspost.body = rails_results.join('&') + results_as_string = rails_results.join('&') + resultspost.body = results_as_string resultspost.content_type = 'application/x-www-form-urlencoded' + sign_post!(resultspost, @key) response = http.request(resultspost) case response when Net::HTTPSuccess @@ -259,11 +293,11 @@ status end - def check_for_disable_etch_file(disableforce) + def check_for_disable_etch_file disable_etch = File.join(@varbase, 'disable_etch') message = '' if File.exist?(disable_etch) - if !disableforce + if !@disableforce message = "Etch disabled:\n" message << IO.read(disable_etch) puts message @@ -1464,7 +1498,39 @@ histrcspath = "#{histrcsdir}/#{histbase},v" File.chmod(histperms, histrcspath) if (!@dryrun) end - + + def get_local_requests(file) + requestdir = File.join(@requestbase, file) + requestlist = [] + if File.directory?(requestdir) + Dir.foreach(requestdir) do |entry| + next if entry == '.' + next if entry == '..' + requestfile = File.join(requestdir, entry) + request = IO.read(requestfile) + # Make sure it is valid XML + begin + request_xml = REXML::Document.new(request) + rescue REXML::ParseException => e + warn "Local request file #{requestfile} is not valid XML and will be ignored:\n" + e.message + next + end + # Make sure the root element is <request> + if request_xml.root.name != 'request' + warn "Local request file #{requestfile} is not properly formatted and will be ignored, XML root element is not <request>" + next + end + # Add it to the queue + requestlist << request + end + end + requests = nil + if !requestlist.empty? + requests = "<requests>\n#{requestlist.join('')}\n</requests>" + end + requests + end + # Haven't found a Ruby method for creating temporary directories, # so create a temporary file and replace it with a directory. def tempdir(file) @@ -1866,13 +1932,13 @@ # Any etch lockfiles more than a couple hours old are most likely stale # and can be removed. If told to force we remove all lockfiles. - def remove_stale_lock_files(force=false) + def remove_stale_lock_files twohoursago = Time.at(Time.now - 60 * 60 * 2) Find.find(@lockbase) do |file| next unless file =~ /\.LOCK$/ next unless File.file?(file) - if force || File.mtime(file) < twohoursago + if @lockforce || File.mtime(file) < twohoursago puts "Removing stale lock file #{file}" File.delete(file) end @@ -1883,6 +1949,10 @@ @already_processed.clear end + # We limit capturing to 5 minutes. That should be plenty of time + # for etch to handle any given file, including running any + # setup/pre/post commands. + OUTPUT_CAPTURE_TIMEOUT = 5 * 60 def start_output_capture # Establish a pipe, spawn a child process, and redirect stdout/stderr # to the pipe. The child gathers up anything sent over the pipe and @@ -1928,9 +1998,20 @@ # newline. $stdout.sync = true output = '' - while char = pread.getc - putc(char) - output << char.chr + begin + # A surprising number of apps that we restart are ill-behaved and do + # not properly close stdin/stdout/stderr. With etch's output + # capturing feature this results in etch hanging around forever + # waiting for the pipes to close. We time out after a suitable + # period of time so that etch processes don't hang around forever. + Timeout.timeout(OUTPUT_CAPTURE_TIMEOUT) do + while char = pread.getc + putc(char) + output << char.chr + end + end + rescue Timeout::Error + $stderr.puts "Timeout in output capture, some app restarted via post probably didn't daemonize properly" end pread.close owrite.write(output) @@ -1959,5 +2040,40 @@ Process.wait output end + + def get_private_key_path + key = nil + PRIVATE_KEY_PATHS.each do |path| + if File.readable?(path) + key = path + break + end + end + if !key + warn "No readable private key found, messages to server will not be signed and may be rejected depending on server configuration" + end + key + end + + # This method takes in a Net::HTTP::Post and a path to a private key. + # It will insert a 'timestamp' parameter to the post body, hash the body of + # the post, sign the hash using the private key, and insert that signature + # in the HTTP Authorization header field in the post. + def sign_post!(post, key) + if key + post.body << "×tamp=#{CGI.escape(Time.now.to_s)}" + private_key = OpenSSL::PKey::RSA.new(File.read(key)) + hashed_body = Digest::SHA1.hexdigest(post.body) + signature = Base64.encode64(private_key.private_encrypt(hashed_body)) + # encode64 breaks lines at 60 characters with newlines. Having newlines + # in an HTTP header screws things up (the lines get interpreted as + # separate headers) so strip them out. The Base64 standards seem to + # generally have a limit on line length, but Ruby's decode64 doesn't + # seem to complain. If it ever becomes a problem the server could + # rebreak the lines. + signature.gsub!("\n", '') + post['Authorization'] = "EtchSignature #{signature}" + end + end end Modified: trunk/client/pkginfo =================================================================== --- trunk/client/pkginfo 2009-06-25 00:13:39 UTC (rev 86) +++ trunk/client/pkginfo 2009-09-11 16:59:21 UTC (rev 87) @@ -1,7 +1,7 @@ PKG="OSSetch" NAME="Etch client" ARCH="sparc,i386" -VERSION="1.1" +VERSION="%VER%" CATEGORY="application" CLASSES="none" PSTAMP="none" This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <jh...@us...> - 2009-09-23 01:02:30
|
Revision: 98 http://etch.svn.sourceforge.net/etch/?rev=98&view=rev Author: jheiss Date: 2009-09-23 01:02:24 +0000 (Wed, 23 Sep 2009) Log Message: ----------- Add etch_to_trunk to package. This is a tool for setting the config_mgmt_tag in nVentory to trunk-YYYYMMDD-HH00 for etch clients to temporarily bump them to trunk. Modified Paths: -------------- trunk/client/Makefile trunk/client/etch-client.spec Added Paths: ----------- trunk/client/etch_to_trunk Modified: trunk/client/Makefile =================================================================== --- trunk/client/Makefile 2009-09-23 00:58:08 UTC (rev 97) +++ trunk/client/Makefile 2009-09-23 01:02:24 UTC (rev 98) @@ -19,6 +19,8 @@ mkdir -p $(BUILDROOT)/usr/sbin cp -p etch $(BUILDROOT)/usr/sbin chmod 555 $(BUILDROOT)/usr/sbin/etch + cp -p etch_to_trunk $(BUILDROOT)/usr/sbin + chmod 555 $(BUILDROOT)/usr/sbin/etch_to_trunk mkdir -p $(BUILDROOT)/usr/lib/ruby/site_ruby/1.8 cp -p etch.rb $(BUILDROOT)/usr/lib/ruby/site_ruby/1.8 chmod 444 $(BUILDROOT)/usr/lib/ruby/site_ruby/1.8/etch.rb @@ -48,6 +50,8 @@ mkdir -p $(BUILDROOT)/usr/sbin cp -p etch $(BUILDROOT)/usr/sbin chmod 555 $(BUILDROOT)/usr/sbin/etch + cp -p etch_to_trunk $(BUILDROOT)/usr/sbin + chmod 555 $(BUILDROOT)/usr/sbin/etch_to_trunk mkdir -p $(BUILDROOT)/usr/local/lib/site_ruby/1.8 cp -p etch.rb $(BUILDROOT)/usr/local/lib/site_ruby/1.8 chmod 444 $(BUILDROOT)/usr/local/lib/site_ruby/1.8/etch.rb @@ -75,6 +79,11 @@ cat $(BUILDROOT)/usr/sbin/etch.tmp | sed 's,/usr/bin/ruby,/opt/csw/bin/ruby,' > $(BUILDROOT)/usr/sbin/etch rm $(BUILDROOT)/usr/sbin/etch.tmp chmod 555 $(BUILDROOT)/usr/sbin/etch + cp -p etch_to_trunk $(BUILDROOT)/usr/sbin + mv $(BUILDROOT)/usr/sbin/etch_to_trunk $(BUILDROOT)/usr/sbin/etch_to_trunk.tmp + cat $(BUILDROOT)/usr/sbin/etch_to_trunk.tmp | sed 's,/usr/bin/ruby,/opt/csw/bin/ruby,' > $(BUILDROOT)/usr/sbin/etch_to_trunk + rm $(BUILDROOT)/usr/sbin/etch_to_trunk.tmp + chmod 555 $(BUILDROOT)/usr/sbin/etch_to_trunk mkdir -p $(BUILDROOT)/opt/csw/lib/ruby/site_ruby/1.8 cp -p etch.rb $(BUILDROOT)/opt/csw/lib/ruby/site_ruby/1.8 chmod 444 $(BUILDROOT)/opt/csw/lib/ruby/site_ruby/1.8/etch.rb @@ -115,6 +124,8 @@ # our library file (etch.rb) into /opt/csw. We modify etch to use # the Sunfreeware ruby in /usr/local/bin, but then tell it to also look # in the /opt/csw directory for libraries. +# I'm going to guess that the smaller utilities like etch_to_trunk won't have +# problems, so I'm leaving them set to /opt/csw/bin/ruby. sysvpkg-sparc: pkginfo depend # # Create package file structure in build root @@ -130,6 +141,11 @@ cat $(BUILDROOT)/usr/sbin/etch.tmp | awk '/unshift.*__FILE__/ {print "$$:.unshift \"/opt/csw/lib/ruby/site_ruby/1.8\"\n" $$0; next}; {print}' > $(BUILDROOT)/usr/sbin/etch rm $(BUILDROOT)/usr/sbin/etch.tmp chmod 555 $(BUILDROOT)/usr/sbin/etch + cp -p etch_to_trunk $(BUILDROOT)/usr/sbin + mv $(BUILDROOT)/usr/sbin/etch_to_trunk $(BUILDROOT)/usr/sbin/etch_to_trunk.tmp + cat $(BUILDROOT)/usr/sbin/etch_to_trunk.tmp | sed 's,/usr/bin/ruby,/opt/csw/bin/ruby,' > $(BUILDROOT)/usr/sbin/etch_to_trunk + rm $(BUILDROOT)/usr/sbin/etch_to_trunk.tmp + chmod 555 $(BUILDROOT)/usr/sbin/etch_to_trunk mkdir -p $(BUILDROOT)/opt/csw/lib/ruby/site_ruby/1.8 cp -p etch.rb $(BUILDROOT)/opt/csw/lib/ruby/site_ruby/1.8 chmod 444 $(BUILDROOT)/opt/csw/lib/ruby/site_ruby/1.8/etch.rb Modified: trunk/client/etch-client.spec =================================================================== --- trunk/client/etch-client.spec 2009-09-23 00:58:08 UTC (rev 97) +++ trunk/client/etch-client.spec 2009-09-23 01:02:24 UTC (rev 98) @@ -13,6 +13,7 @@ %files %defattr(-,root,root) /usr/sbin/etch +/usr/sbin/etch_to_trunk /usr/lib/ruby/site_ruby/1.8/etch.rb /etc/etch /usr/sbin/etch_cron_wrapper Added: trunk/client/etch_to_trunk =================================================================== --- trunk/client/etch_to_trunk (rev 0) +++ trunk/client/etch_to_trunk 2009-09-23 01:02:24 UTC (rev 98) @@ -0,0 +1,45 @@ +#!/usr/bin/ruby -w + +require 'nventory' + +@username = ENV['LOGNAME'] + +if ARGV.length == 0 + abort "Usage: #{File.basename($0)} <server1> [<server2> <server3>]" +end + +# The etch servers run in UTC +ENV['TZ'] = 'UTC' +currentheadtag = Time.now.strftime('trunk-%Y%m%d-%H00') + +# Find the requested clients +nvclient = NVentory::Client.new +results = nvclient.get_objects('nodes', {}, { 'name' => ARGV }, {}, {}) +ARGV.each do |name| + if results.empty? && results[name].nil? + abort "No entry found for #{name}" + else + if !results[name]['config_mgmt_tag'].nil? && + !results[name]['config_mgmt_tag'].empty? + puts "Changing #{name} from #{results[name]['config_mgmt_tag']} to #{currentheadtag}" + else + puts "Setting #{name} to #{currentheadtag}" + end + end +end + +while true + print "Proceed? [y|n] " + response = $stdin.gets.chomp + if response == 'y' + break + elsif response == 'n' + exit + end +end + +# Update the clients +successcount = nvclient.set_objects('nodes', results, {'config_mgmt_tag' => currentheadtag}, @username) + +puts "#{File.basename($0)} operation succeeded for #{successcount} of #{results.size} nodes" + Property changes on: trunk/client/etch_to_trunk ___________________________________________________________________ Added: svn:executable + * This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <jh...@us...> - 2009-10-29 20:44:53
|
Revision: 132 http://etch.svn.sourceforge.net/etch/?rev=132&view=rev Author: jheiss Date: 2009-10-29 20:44:32 +0000 (Thu, 29 Oct 2009) Log Message: ----------- Make it easier to run etch from within the distribution directory structure. Remove the run_etch script I added as a poorly thought-out hack to accomplish the same. Add support for requesting specific commands. Add featuring allowing the server to tell the client to retry certain commands on the next request. The "need sum" mechanism is used to do the same thing for files, but as commands have no original content saving mechanism we have to have an explicit feature for retries. The server needs this if it is unable to generate all of the prerequisites for the command, usually because the command depends on a file for which the server needs original content info. Add support for files that depend on commands and vice-versa. Put all data that extracted from the server's response into a responsedata hash rather than a bunch of separate variables. Previous process_file was passed only file configuration and process_commands passed only command configuration, but with the new files-that-depend-on-commands and vice-versa features both methods need all configuration data. Fix bug in get_orig_contents so that it return the contents for temporarily saved originals in addition to finalized originals. Modified Paths: -------------- trunk/client/etchclient.rb Removed Paths: ------------- trunk/client/run_etch Modified: trunk/client/etchclient.rb =================================================================== --- trunk/client/etchclient.rb 2009-10-29 20:41:44 UTC (rev 131) +++ trunk/client/etchclient.rb 2009-10-29 20:44:32 UTC (rev 132) @@ -2,6 +2,13 @@ # Etch configuration file management tool library ############################################################################## +# Ensure we can find etch.rb if run within the development directory structure +# This is roughly equivalent to "../server/lib" +serverlibdir = File.join(File.dirname(File.dirname(File.expand_path(__FILE__))), 'server', 'lib') +if File.exist?(serverlibdir) + $:.unshift(serverlibdir) +end + begin # Try loading facter w/o gems first so that we don't introduce a # dependency on gems if it is not needed. @@ -28,7 +35,7 @@ require 'etch' class Etch::Client - VERSION = '1.16' + VERSION = '1.18' CONFIRM_PROCEED = 1 CONFIRM_SKIP = 2 @@ -120,13 +127,14 @@ @lchmod_supported = nil end - def process_until_done(files_to_generate) + def process_until_done(files, commands) # Our overall status. Will be reported to the server and used as the # return value for this method. Command-line clients should use it as # their exit value. Zero indicates no errors. status = 0 message = '' + # Prep http instance http = nil if !@local http = Net::HTTP.new(@filesuri.host, @filesuri.port) @@ -166,9 +174,9 @@ request = nil if @local request = {} - if files_to_generate && !files_to_generate.empty? - files_to_generate.each do |file| - request[:files] = {} + if files && !files.empty? + request[:files] = {} + files.each do |file| request[:files][file] = {:orig => save_orig(file)} local_requests = get_local_requests(file) if local_requests @@ -176,18 +184,31 @@ end end end + if commands && !commands.empty? + request[:commands] = {} + commands.each do |command| + request[:commands][command] = {} + end + end else request = get_blank_request - if files_to_generate && !files_to_generate.empty? - files_to_generate.each do |file| - request["files[#{CGI.escape(file)}][sha1sum]"] = - get_orig_sum(file) - local_requests = get_local_requests(file) - if local_requests - request["files[#{CGI.escape(file)}][local_requests]"] = - local_requests + if (files && !files.empty?) || (commands && !commands.empty?) + if files + files.each do |file| + request["files[#{CGI.escape(file)}][sha1sum]"] = + get_orig_sum(file) + local_requests = get_local_requests(file) + if local_requests + request["files[#{CGI.escape(file)}][local_requests]"] = + local_requests + end end end + if commands + commands.each do |command| + request["commands[#{CGI.escape(command)}]"] = '1' + end + end else request['files[GENERATEALL]'] = '1' end @@ -210,23 +231,23 @@ # Send request to server # - configs = nil - need_sums = nil - need_origs = nil - allcommands = nil + responsedata = {} if @local results = @etch.generate(@local, @facts, request) - # FIXME: Etch#generate returns parsed XML using whatever XML - # library it happens to use. In order to avoid re-parsing - # the XML we'd have to use the XML abstraction code from Etch - # everwhere here. - # Until then re-parse the XML using REXML. - #configs = results[:configs] - configs = {} - results[:configs].each {|f,c| configs[f] = REXML::Document.new(c.to_s) } - need_sums = {} - need_origs = results[:need_orig] - allcommands = results[:allcommands] + # FIXME: Etch#generate returns parsed XML using whatever XML + # library it happens to use. In order to avoid re-parsing + # the XML we'd have to use the XML abstraction code from Etch + # everwhere here. + # Until then re-parse the XML using REXML. + #responsedata[:configs] = results[:configs] + responsedata[:configs] = {} + results[:configs].each {|f,c| responsedata[:configs][f] = REXML::Document.new(c.to_s) } + responsedata[:need_sums] = {} + responsedata[:need_origs] = results[:need_orig] + #responsedata[:allcommands] = results[:allcommands] + responsedata[:allcommands] = {} + results[:allcommands].each {|cn,c| responsedata[:allcommands][cn] = REXML::Document.new(c.to_s) } + responsedata[:retrycommands] = results[:retrycommands] else puts "Sending request to server #{@filesuri}: #{request.inspect}" if (@debug) post = Net::HTTP::Post.new(@filesuri.path) @@ -241,32 +262,36 @@ puts "Response from server:\n'#{response.body}'" if (@debug) if !response.body.nil? && !response.body.empty? response_xml = REXML::Document.new(response.body) - configs = {} + responsedata[:configs] = {} response_xml.elements.each('/files/configs/config') do |config| file = config.attributes['filename'] # We have to make a new document so that XPath paths are # referenced relative to the configuration for this # specific file. - #configs[file] = REXML::Document.new(response_xml.elements["/files/configs/config[@filename='#{file}']"].to_s) - configs[file] = REXML::Document.new(config.to_s) + #responsedata[:configs][file] = REXML::Document.new(response_xml.elements["/files/configs/config[@filename='#{file}']"].to_s) + responsedata[:configs][file] = REXML::Document.new(config.to_s) end - need_sums = {} + responsedata[:need_sums] = {} response_xml.elements.each('/files/need_sums/need_sum') do |ns| - need_sums[ns.text] = true + responsedata[:need_sums][ns.text] = true end - need_origs = {} + responsedata[:need_origs] = {} response_xml.elements.each('/files/need_origs/need_orig') do |no| - need_origs[no.text] = true + responsedata[:need_origs][no.text] = true end - allcommands = {} + responsedata[:allcommands] = {} response_xml.elements.each('/files/allcommands/commands') do |command| commandname = command.attributes['commandname'] # We have to make a new document so that XPath paths are # referenced relative to the configuration for this # specific file. - #allcommands[commandname] = REXML::Document.new(response_xml.root.elements["/files/allcommands/commands[@commandname='#{commandname}']"].to_s) - allcommands[commandname] = REXML::Document.new(command.to_s) + #responsedata[:allcommands][commandname] = REXML::Document.new(response_xml.root.elements["/files/allcommands/commands[@commandname='#{commandname}']"].to_s) + responsedata[:allcommands][commandname] = REXML::Document.new(command.to_s) end + responsedata[:retrycommands] = {} + response_xml.elements.each('/files/retrycommands/retrycommand') do |rc| + responsedata[:retrycommands][rc.text] = true + end else puts " Response is empty" if (@debug) break @@ -280,7 +305,7 @@ # Prep a clean request hash if @local request = {} - if !need_origs.empty? + if !responsedata[:need_origs].empty? request[:files] = {} end else @@ -296,14 +321,14 @@ reset_already_processed # Process configs first, as they may contain setup entries that are # needed to create the original files. - configs.each_key do |file| + responsedata[:configs].each_key do |file| puts "Processing config for #{file}" if (@debug) - continue_processing = process(file, configs) + continue_processing = process_file(file, responsedata) if !continue_processing throw :stop_processing end end - need_sums.each_key do |need_sum| + responsedata[:need_sums].each_key do |need_sum| puts "Processing request for sum of #{need_sum}" if (@debug) if @local # If this happens we screwed something up, the local mode @@ -324,7 +349,7 @@ end need_to_loop = true end - need_origs.each_key do |need_orig| + responsedata[:need_origs].each_key do |need_orig| puts "Processing request for contents of #{need_orig}" if (@debug) if @local request[:files][need_orig] = {:orig => save_orig(need_orig)} @@ -345,14 +370,23 @@ end need_to_loop = true end - allcommands.each_key do |commandname| + responsedata[:allcommands].each_key do |commandname| puts "Processing commands #{commandname}" if (@debug) - continue_processing = process_commands(commandname, allcommands) + continue_processing = process_commands(commandname, responsedata) if !continue_processing throw :stop_processing end end - + responsedata[:retrycommands].each_key do |commandname| + puts "Processing request to retry command #{commandname}" if (@debug) + if @local + request[:commands][commandname] = true + else + request["commands[#{CGI.escape(commandname)}]"] = '1' + end + need_to_loop = true + end + if !need_to_loop break end @@ -431,7 +465,7 @@ # Raises an exception if any fatal error is encountered # Returns a boolean, true unless the user indicated in interactive mode # that further processing should be halted - def process(file, configs) + def process_file(file, responsedata) continue_processing = true save_results = true exception = nil @@ -439,7 +473,7 @@ # We may not have configuration for this file, if it does not apply # to this host. The server takes care of detecting any errors that # might involve, so here we can just silently return. - config = configs[file] + config = responsedata[:configs][file] if !config puts "No configuration for #{file}, skipping" if (@debug) return continue_processing @@ -486,10 +520,16 @@ # Process any other files that this file depends on config.elements.each('/config/depend') do |depend| - puts "Generating dependency #{depend.text}" if (@debug) - process(depend.text, configs) + puts "Processing dependency #{depend.text}" if (@debug) + process_file(depend.text, responsedata) end - + + # Process any commands that this file depends on + config.elements.each('/config/dependcommand') do |dependcommand| + puts "Processing command dependency #{dependcommand.text}" if (@debug) + process_commands(dependcommand.text, responsedata) + end + # See what type of action the user has requested # Check to see if the user has requested that we revert back to the @@ -1342,11 +1382,20 @@ # Raises an exception if any fatal error is encountered # Returns a boolean, true unless the user indicated in interactive mode # that further processing should be halted - def process_commands(commandname, allcommands) + def process_commands(commandname, responsedata) continue_processing = true save_results = true exception = nil + # We may not have configuration for this file, if it does not apply + # to this host. The server takes care of detecting any errors that + # might involve, so here we can just silently return. + command = responsedata[:allcommands][commandname] + if !command + puts "No configuration for command #{commandname}, skipping" if (@debug) + return continue_processing + end + # Skip commands we've already processed in response to <depend> # statements. if @already_processed.has_key?(commandname) @@ -1386,14 +1435,18 @@ # This needs to be after the circular dependency check lock_file(commandname) - command = allcommands[commandname] - # Process any other commands that this command depends on command.elements.each('/commands/depend') do |depend| - puts "Generating command dependency #{depend.text}" if (@debug) - process_commands(depend.text, allcommands) + puts "Processing command dependency #{depend.text}" if (@debug) + process_commands(depend.text, responsedata) end + # Process any files that this command depends on + command.elements.each('/commands/dependfile') do |dependfile| + puts "Processing file dependency #{dependfile.text}" if (@debug) + process_file(dependfile.text, responsedata) + end + # Perform each step command.elements.each('/commands/step') do |step| guard = step.elements['guard/exec'].text @@ -1502,7 +1555,8 @@ orig_contents = nil # We only send back the actual original file contents if the original is # a regular file, otherwise we send back an empty string. - if origpath =~ /\.ORIG$/ && File.file?(origpath) && !File.symlink?(origpath) + if (origpath =~ /\.ORIG$/ || origpath =~ /\.TMP$/) && + File.file?(origpath) && !File.symlink?(origpath) orig_contents = IO.read(origpath) else orig_contents = '' Deleted: trunk/client/run_etch =================================================================== --- trunk/client/run_etch 2009-10-29 20:41:44 UTC (rev 131) +++ trunk/client/run_etch 2009-10-29 20:44:32 UTC (rev 132) @@ -1,11 +0,0 @@ -#!/bin/sh - -# This script makes it easier to run the etch client from the -# distribution directory structure. It is not needed when the etch -# client is packaged and installed. - -RUBYLIB=../server/lib -export RUBYLIB - -exec ./etch "$@" - This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <jh...@us...> - 2009-10-12 23:44:06
|
Revision: 115 http://etch.svn.sourceforge.net/etch/?rev=115&view=rev Author: jheiss Date: 2009-10-12 23:44:00 +0000 (Mon, 12 Oct 2009) Log Message: ----------- Create etch manpage, add it to the client packages. Simplify the etch help output now that more details can be put into the man page. Rename etch.rb to etchclient.rb to reflect its purpose. Add etch.rb and versiontype.rb to the packages Modified Paths: -------------- trunk/client/Makefile trunk/client/etch trunk/client/etch-client.spec Added Paths: ----------- trunk/client/etch.8 Modified: trunk/client/Makefile =================================================================== --- trunk/client/Makefile 2009-10-12 23:36:25 UTC (rev 114) +++ trunk/client/Makefile 2009-10-12 23:44:00 UTC (rev 115) @@ -1,6 +1,6 @@ BUILDROOT=/var/tmp/etch-client-buildroot # Grab the current version from the library -VER=$(shell ruby -e "$$:.unshift('.'); require 'etch'; puts Etch::Client::VERSION") +VER=$(shell ruby -e "$$:.unshift('.'); require 'etchclient'; puts Etch::Client::VERSION") all: @@ -22,8 +22,14 @@ cp -p etch_to_trunk $(BUILDROOT)/usr/sbin chmod 555 $(BUILDROOT)/usr/sbin/etch_to_trunk mkdir -p $(BUILDROOT)/usr/lib/ruby/site_ruby/1.8 - cp -p etch.rb $(BUILDROOT)/usr/lib/ruby/site_ruby/1.8 + cp -p etchclient.rb $(BUILDROOT)/usr/lib/ruby/site_ruby/1.8 + chmod 444 $(BUILDROOT)/usr/lib/ruby/site_ruby/1.8/etchclient.rb + cp -p ../server/lib/etch.rb $(BUILDROOT)/usr/lib/ruby/site_ruby/1.8 chmod 444 $(BUILDROOT)/usr/lib/ruby/site_ruby/1.8/etch.rb + cp -p ../server/lib/versiontype.rb $(BUILDROOT)/usr/lib/ruby/site_ruby/1.8 + chmod 444 $(BUILDROOT)/usr/lib/ruby/site_ruby/1.8/versiontype.rb + mkdir -p $(BUILDROOT)/usr/share/man/man8 + cp -p etch.8 $(BUILDROOT)/usr/share/man/man8 mkdir -p $(BUILDROOT)/etc/etch cp -p ca.pem $(BUILDROOT)/etc/etch cp -p dhparams $(BUILDROOT)/etc/etch @@ -53,8 +59,14 @@ cp -p etch_to_trunk $(BUILDROOT)/usr/sbin chmod 555 $(BUILDROOT)/usr/sbin/etch_to_trunk mkdir -p $(BUILDROOT)/usr/local/lib/site_ruby/1.8 - cp -p etch.rb $(BUILDROOT)/usr/local/lib/site_ruby/1.8 + cp -p etchclient.rb $(BUILDROOT)/usr/local/lib/site_ruby/1.8 + chmod 444 $(BUILDROOT)/usr/local/lib/site_ruby/1.8/etchclient.rb + cp -p ../server/lib/etch.rb $(BUILDROOT)/usr/local/lib/site_ruby/1.8 chmod 444 $(BUILDROOT)/usr/local/lib/site_ruby/1.8/etch.rb + cp -p ../server/lib/versiontype.rb $(BUILDROOT)/usr/local/lib/site_ruby/1.8 + chmod 444 $(BUILDROOT)/usr/local/lib/site_ruby/1.8/versiontype.rb + mkdir -p $(BUILDROOT)/usr/share/man/man8 + cp -p etch.8 $(BUILDROOT)/usr/share/man/man8 mkdir -p $(BUILDROOT)/etc/etch cp -p ca.pem $(BUILDROOT)/etc/etch cp -p dhparams $(BUILDROOT)/etc/etch @@ -85,8 +97,14 @@ rm $(BUILDROOT)/usr/sbin/etch_to_trunk.tmp chmod 555 $(BUILDROOT)/usr/sbin/etch_to_trunk mkdir -p $(BUILDROOT)/opt/csw/lib/ruby/site_ruby/1.8 - cp -p etch.rb $(BUILDROOT)/opt/csw/lib/ruby/site_ruby/1.8 + cp -p etchclient.rb $(BUILDROOT)/opt/csw/lib/ruby/site_ruby/1.8 + chmod 444 $(BUILDROOT)/opt/csw/lib/ruby/site_ruby/1.8/etchclient.rb + cp -p ../server/lib/etch.rb $(BUILDROOT)/opt/csw/lib/ruby/site_ruby/1.8 chmod 444 $(BUILDROOT)/opt/csw/lib/ruby/site_ruby/1.8/etch.rb + cp -p ../server/lib/versiontype.rb $(BUILDROOT)/opt/csw/lib/ruby/site_ruby/1.8 + chmod 444 $(BUILDROOT)/opt/csw/lib/ruby/site_ruby/1.8/versiontype.rb + mkdir -p $(BUILDROOT)/usr/share/man/man8 + cp -p etch.8 $(BUILDROOT)/usr/share/man/man8 mkdir -p $(BUILDROOT)/etc/etch cp -p ca.pem $(BUILDROOT)/etc/etch cp -p dhparams $(BUILDROOT)/etc/etch @@ -121,7 +139,7 @@ # core dumping when running etch. The Sunfreeware ruby seems to work. # Sunfreeware doesn't play well with pkg-get, so we create a bit of a # hybrid. We still express all the dependencies against CSW, and put -# our library file (etch.rb) into /opt/csw. We modify etch to use +# our library file (etchclient.rb) into /opt/csw. We modify etch to use # the Sunfreeware ruby in /usr/local/bin, but then tell it to also look # in the /opt/csw directory for libraries. # I'm going to guess that the smaller utilities like etch_to_trunk won't have @@ -147,8 +165,14 @@ rm $(BUILDROOT)/usr/sbin/etch_to_trunk.tmp chmod 555 $(BUILDROOT)/usr/sbin/etch_to_trunk mkdir -p $(BUILDROOT)/opt/csw/lib/ruby/site_ruby/1.8 - cp -p etch.rb $(BUILDROOT)/opt/csw/lib/ruby/site_ruby/1.8 + cp -p etchclient.rb $(BUILDROOT)/opt/csw/lib/ruby/site_ruby/1.8 + chmod 444 $(BUILDROOT)/opt/csw/lib/ruby/site_ruby/1.8/etchclient.rb + cp -p ../server/lib/etch.rb $(BUILDROOT)/opt/csw/lib/ruby/site_ruby/1.8 chmod 444 $(BUILDROOT)/opt/csw/lib/ruby/site_ruby/1.8/etch.rb + cp -p ../server/lib/versiontype.rb $(BUILDROOT)/opt/csw/lib/ruby/site_ruby/1.8 + chmod 444 $(BUILDROOT)/opt/csw/lib/ruby/site_ruby/1.8/versiontype.rb + mkdir -p $(BUILDROOT)/usr/share/man/man8 + cp -p etch.8 $(BUILDROOT)/usr/share/man/man8 mkdir -p $(BUILDROOT)/etc/etch cp -p ca.pem $(BUILDROOT)/etc/etch cp -p dhparams $(BUILDROOT)/etc/etch Modified: trunk/client/etch =================================================================== --- trunk/client/etch 2009-10-12 23:36:25 UTC (rev 114) +++ trunk/client/etch 2009-10-12 23:44:00 UTC (rev 115) @@ -3,11 +3,11 @@ # Etch configuration file management tool ############################################################################## -# Ensure we can find etch.rb +# Ensure we can find etchclient.rb $:.unshift File.dirname(__FILE__) require 'optparse' -require 'etch' +require 'etchclient' # # Parse the command line options @@ -16,15 +16,15 @@ options = {} @generateall = nil -opts = OptionParser.new +opts = OptionParser.new(nil, 24, ' ') opts.banner = 'Usage: etch [options] [/path/to/config/file]' -opts.on('--generate-all', 'Can be used instead of giving a specific file to generate.') do |opt| +opts.on('--generate-all', 'Request all configuration.') do |opt| @generateall = opt end -opts.on('--dry-run', '-n', 'Prints contents of generated files instead of writing them out to disk.') do |opt| +opts.on('--dry-run', '-n', 'Make no changes.') do |opt| options[:dryrun] = opt end -opts.on('--damp-run', "Perform a dry run but run 'setup' entries for files. Normally all setup/pre/post entries are ignored for a dry run. However, files with setup entries will generally fail to build if the setup entry hasn't been run.") do |opt| +opts.on('--damp-run', "Perform a dry run but run 'setup' entries for files.") do |opt| # Rather than sprinkle checks of two different variables throught the code, if # we're asked to do a damp run then just set the dry run flag to a unique # value. Then we can just check for that specific value at the one place where @@ -32,41 +32,44 @@ # entries. options[:dryrun] = 'damp' end -opts.on('--interactive', 'Causes etch to pause before making each change and prompt the user for confirmation.') do |opt| +opts.on('--interactive', 'Prompt for confirmation before each change.') do |opt| options[:interactive] = opt end -opts.on('--full-file', 'Normally etch will print a diff to show what changes it will make to a file. This will cause etch to display the full new file contents instead.') do |opt| +opts.on('--full-file', 'Display full new file contents instead of a diff.') do |opt| options[:fullfile] = opt end -opts.on('--filename-only', 'Similar to the previous option, but in the opposite direction. Etch will only display the name of file to be changed.') do |opt| +opts.on('--filename-only', 'Display filename of changed files instead of a diff.') do |opt| options[:filenameonly] = opt end opts.on('--disable-force', 'Ignore the disable_etch file. Use with caution.') do |opt| options[:disableforce] = opt end -opts.on('--lock-force', 'Force the removal of any existing lockfiles. Normally only lockfile over 2 hours old are removed.') do |opt| +opts.on('--lock-force', 'Force the removal of any existing lockfiles.') do |opt| options[:lockforce] = opt end -opts.on('--debug', 'Print lots of messages about what etch is doing') do |opt| - options[:debug] = opt +opts.on('--local DIR', 'Read configuration from local directory, not server.') do |opt| + options[:local] = opt end -opts.on('--server SERVER', 'Point etch to an alternate server') do |opt| +opts.on('--server SERVER', 'Point etch to an alternate server.') do |opt| options[:server] = opt end -opts.on('--tag TAG', 'Request a specific repository tag from the server') do |opt| +opts.on('--tag TAG', 'Request a specific repository tag from the server.') do |opt| options[:tag] = opt end -opts.on('--test-base TESTDIR', 'Use an alternate local working directory (for use by test suite only)') do |opt| +opts.on('--key PRIVATE_KEY', 'Use this private key for signing messages to server.') do |opt| + options[:key] = opt +end +opts.on('--test-base TESTDIR', 'Use an alternate local working directory.') do |opt| options[:varbase] = opt end -opts.on('--key PRIVATE_KEY', 'Use this private key for signing messages that are sent to the server') do |opt| - options[:key] = opt +opts.on('--debug', 'Print lots of messages about what etch is doing.') do |opt| + options[:debug] = opt end -opts.on('--version', 'Show etch client version') do |opt| +opts.on('--version', 'Show etch client version.') do |opt| puts Etch::Client::VERSION exit end -opts.on_tail("-h", "--help", "Show this message") do +opts.on_tail('-h', '--help', 'Show this message.') do puts opts exit end Modified: trunk/client/etch-client.spec =================================================================== --- trunk/client/etch-client.spec 2009-10-12 23:36:25 UTC (rev 114) +++ trunk/client/etch-client.spec 2009-10-12 23:44:00 UTC (rev 115) @@ -14,7 +14,10 @@ %defattr(-,root,root) /usr/sbin/etch /usr/sbin/etch_to_trunk +/usr/lib/ruby/site_ruby/1.8/etchclient.rb /usr/lib/ruby/site_ruby/1.8/etch.rb +/usr/lib/ruby/site_ruby/1.8/versiontype.rb +/usr/share/man/man8/etch.8 /etc/etch /usr/sbin/etch_cron_wrapper /etc/cron.d/etch Added: trunk/client/etch.8 =================================================================== --- trunk/client/etch.8 (rev 0) +++ trunk/client/etch.8 2009-10-12 23:44:00 UTC (rev 115) @@ -0,0 +1,203 @@ +.TH etch 8 "October 2009" + +.SH NAME + +.B etch +\- Configuration management for Unix systems + +.SH SYNOPSIS + +.B etch +.RB [ --generate-all ] +.RB [ --dry-run | \-n ] +.RB [ --damp-run ] +.RB [ --interactive ] +.RB [ --full-file ] +.RB [ --filename-only ] +.RB [ --disable-force ] +.RB [ --lock-force ] +.RB [ --debug ] +.RB [ --local +.IR DIR ] +.RB [ --server +.IR SERVER ] +.RB [ --tag +.IR TAG ] +.RB [ --test-base +.IR TESTDIR ] +.RB [ --key +.IR PRIVATE_KEY ] +.RB [ --version ] +.RB [ --help | \-h ] +.RI [ "file ..." ] + +.SH DESCRIPTION + +Etch is a tool for managing the configuration of Unix systems. Etch can manage +text or binary files, links and directories. The contents of files can be +supplied from static files or generated on the fly by scripts or templates. +Permissions and ownership as well as any pre or post commands to run when +updating the file are configured in simple XML files. + +.SH OPTIONS +.TP +.B --generate-all +Request that the server generate and send over all available configuration. +Can be used instead of specifying specific files to request. +.TP +.B --dry-run | \-n +.B etch +will not make any changes to the system. Contents of generated config +files are displayed instead of being written to disk. +.TP +.B --damp-run +Perform an almost dry run, except that 'setup' entries for files are run. +Normally all setup/pre/post entries are ignored for a dry run. However, files +with setup entries will generally fail to build properly if the setup entry +hasn't been run. This allows you to preview the full and correct +configuration while making minimal changes to the system. +.TP +.B --interactive +Causes +.B etch +to pause before making each change and prompt the user for +confirmation. +.TP +.B --full-file +Normally +.B etch +will print a diff to show what changes it will make to a file. This will cause +.B etch +to display the full new file contents instead. Useful if the diff is hard to +read for a particular file. +.TP +.B --filename-only +Normally +.B etch +will print a diff to show what changes it will make to a file. This will cause +etch to display only the name of file to be changed. Useful on the initial +run during your system build process or other times when you want less output. +.TP +.B --disable-force +Ignore the disable_etch file. Use with caution. Typically used with +--interactive or --dry-run to evaluate what would happen if etch were +re-enabled. +.TP +.B --lock-force +.B Etch +does per-file internal locking as it runs to prevent problems with +simultaneous instances of the +.B etch +client stepping on each other. +.B Etch +automatically cleans up lockfiles over two hours old on the assumption that +any lockfiles that old were left behind by a previous instance that failed for +some (hopefully transient) reason. In a large environment you don't want to +have to run around manually cleaning up lockfiles every time a full disk or +unavailable package server or other transient failure causes +.B etch +to fail +temporarily. This option forces the removal of any existing lockfiles no +matter how old. Useful if a buggy configuration or local environmental issue +caused +.B etch +to abort and you want to immediately retry. +.TP +.BI --local " DIR" +Read configuration from a local directory rather than requesting it from +a server. +.TP +.BI --server " SERVER" +Point +.B etch +to an alternate server, specified in the form of a URL. +.TP +.BI --tag " TAG" +Request a specific repository tag from the server. Tags are directory paths +relative to /etc/etchserver by default. Thus examples might be +.I trunk +for /etc/etchserver/trunk, or +.I branches/mytestbranch +for /etc/etchserver/branches/mytestbranch. +.TP +.BI --key " PRIVATE_KEY" +Use an alternate SSH private key file for signing messages that are sent to +the server. +.TP +.BI --test-base " TESTDIR" +Use an alternate local working directory instead of /var/etch. Generally only +used for allowing the etch test suite to be run as a non-root user. +.TP +.B --debug +Print lots of messages about what etch is doing. +.TP +.B --version +Show the etch client version and exit. +.TP +.B --help | \-h +Display the etch usage message and exit. + +.SH FILES + +.TP +.B /etc/etch/ca.pem +SSL certificate(s) needed to verify the +.B etch +server's identity. If +.B etch +is using a server with an https:// URL and if this file exists then +.B etch +will not proceed if the server's SSL certificate can't be verified against the +certs in this file. +.TP +.B /etc/etch/dhparams +The Diffie-Hellman parameters used as part of the SSL connection process. Etch +comes with a set and there's no need to generate your own, but a new set can +be generated via "openssl dhparam" if desired. If not present the Ruby SSL +library will warn that it is using its internal default set of parameters. +.TP +.B /var/etch/disable_etch +If this file is present +.B etch +will do nothing other than send a message to the +.B etch +server that it is disabled. Any text in this file will be included in +that message to the server and displayed locally. If you are disabling +.B etch +always put a note in this file indicating who you are, today's date, and why +you are disabling +.B etch +so that fellow administrators won't have to guess later why +.B etch +was disabled. Re-enabling +.B etch +after it has been disabled for a long +time can be time-consuming, as the person doing so must review any potential +changes that have been queued up and ensure that they won't interfere with the +current usage of the system. As such be thoughtful about whether disabling +.B etch +is necessary, and re-enable it as soon as possible. +.TP +.B /var/etch/history +A revision history of each +.B etch +managed file, stored using the RCS revision control system. +.TP +.B /var/etch/locks +Directory used by the +.B etch +internal locking mechanism. See the --lock-force option for more details. +.TP +.B /var/etch/orig +A backup of the original contents of each +.B etch +managed file as it was before etch first touched it. + +.SH DIAGNOSTICS + +See the --debug option and the server logs. + +.SH AUTHOR + +.B Etch +is designed and maintained by Jason Heiss This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <jh...@us...> - 2009-11-14 00:50:19
|
Revision: 149 http://etch.svn.sourceforge.net/etch/?rev=149&view=rev Author: jheiss Date: 2009-11-14 00:12:38 +0000 (Sat, 14 Nov 2009) Log Message: ----------- Use %VER% instead of VER for the version template that is replaced with the real version when we make a package. The Solaris pkginfo was already using %VER%, so this makes all of the packages consistent and more resistent to accidently substituting the wrong thing. Modified Paths: -------------- trunk/client/control trunk/client/etch-client.spec Modified: trunk/client/control =================================================================== --- trunk/client/control 2009-11-14 00:08:06 UTC (rev 148) +++ trunk/client/control 2009-11-14 00:12:38 UTC (rev 149) @@ -1,5 +1,5 @@ Package: etch-client -Version: VER-1 +Version: %VER%-1 Maintainer: etc...@li... Architecture: all Depends: ruby facter rcs Modified: trunk/client/etch-client.spec =================================================================== --- trunk/client/etch-client.spec 2009-11-14 00:08:06 UTC (rev 148) +++ trunk/client/etch-client.spec 2009-11-14 00:12:38 UTC (rev 149) @@ -1,6 +1,6 @@ Name: etch-client Summary: Etch client -Version: VER +Version: %VER% Release: 1 Group: Applications/System License: MIT This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <jh...@us...> - 2009-11-14 18:15:34
|
Revision: 161 http://etch.svn.sourceforge.net/etch/?rev=161&view=rev Author: jheiss Date: 2009-11-14 18:15:24 +0000 (Sat, 14 Nov 2009) Log Message: ----------- Add rake task to substitute version into macports portfile. Modified Paths: -------------- trunk/client/Portfile trunk/client/Rakefile Modified: trunk/client/Portfile =================================================================== --- trunk/client/Portfile 2009-11-14 18:05:29 UTC (rev 160) +++ trunk/client/Portfile 2009-11-14 18:15:24 UTC (rev 161) @@ -4,7 +4,7 @@ PortSystem 1.0 name etch -version 3.11 +version %VER% categories sysutils maintainers aput.net:jheiss openmaintainer Modified: trunk/client/Rakefile =================================================================== --- trunk/client/Rakefile 2009-11-14 18:05:29 UTC (rev 160) +++ trunk/client/Rakefile 2009-11-14 18:15:24 UTC (rev 161) @@ -385,6 +385,19 @@ :installbase => '/') end +desc 'Prepare portfile for submission to MacPorts' +task :macport do + portfile = File.join(Dir.tmpdir, 'Portfile') + rm_f(portfile) + File.open(portfile, 'w') do |newfile| + IO.foreach('Portfile') do |line| + line.sub!('%VER%', ETCHVER) + newfile.puts(line) + end + end + puts "Portfile is #{portfile}" +end + task :gem do # # Create package file structure in build root This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <jh...@us...> - 2009-11-14 21:42:50
|
Revision: 166 http://etch.svn.sourceforge.net/etch/?rev=166&view=rev Author: jheiss Date: 2009-11-14 21:42:41 +0000 (Sat, 14 Nov 2009) Log Message: ----------- Update macport task to set checksums in portfile. Modified Paths: -------------- trunk/client/Portfile trunk/client/Rakefile Modified: trunk/client/Portfile =================================================================== --- trunk/client/Portfile 2009-11-14 19:20:11 UTC (rev 165) +++ trunk/client/Portfile 2009-11-14 21:42:41 UTC (rev 166) @@ -24,9 +24,9 @@ master_sites sourceforge -checksums md5 e462d44552ce628b2a2e121eb5825b62 \ - sha1 0cee484b291e89adaa46b1fccc763e14ccb41f90 \ - rmd160 5221532a9bba2b93274a8fd419dc4da6ec965e5e +checksums md5 %MD5% \ + sha1 %SHA1% \ + rmd160 %RMD160% depends_build port:rb-rake depends_run port:ruby \ Modified: trunk/client/Rakefile =================================================================== --- trunk/client/Rakefile 2009-11-14 19:20:11 UTC (rev 165) +++ trunk/client/Rakefile 2009-11-14 21:42:41 UTC (rev 166) @@ -1,8 +1,11 @@ require 'rbconfig' require 'tempfile' require 'tmpdir' +require 'open-uri' ETCHVER = IO.read('../VERSION').chomp +TARBALLFILE = "etch-#{ETCHVER}.tar.gz" +TARBALL = File.expand_path(TARBALLFILE) BUILDROOT = '/var/tmp/etch-client-buildroot' @@ -385,13 +388,33 @@ :installbase => '/') end +desc 'Fetch tarball from sourceforge' +task :fetch do + if !File.exist?(TARBALL) + url = "http://downloads.sourceforge.net/project/etch/etch/#{ETCHVER}/#{TARBALLFILE}?use_mirror=autoselect" + puts "Fetching tarball from #{url}" + open(url) do |df| + open(TARBALL, 'w') do |lf| + lf.write(df.read) + end + end + end +end + desc 'Prepare portfile for submission to MacPorts' -task :macport do +task :macport => :fetch do + md5 = `openssl md5 #{TARBALL}`.chomp.split.last + sha1 = `openssl sha1 #{TARBALL}`.chomp.split.last + rmd160 = `openssl rmd160 #{TARBALL}`.chomp.split.last + portfile = File.join(Dir.tmpdir, 'Portfile') rm_f(portfile) File.open(portfile, 'w') do |newfile| IO.foreach('Portfile') do |line| line.sub!('%VER%', ETCHVER) + line.sub!('%MD5%', md5) + line.sub!('%SHA1%', sha1) + line.sub!('%RMD160%', rmd160) newfile.puts(line) end end This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <jh...@us...> - 2009-11-17 00:35:43
|
Revision: 174 http://etch.svn.sourceforge.net/etch/?rev=174&view=rev Author: jheiss Date: 2009-11-17 00:35:34 +0000 (Tue, 17 Nov 2009) Log Message: ----------- Re-arrange /etc related directory paths so that we can eventually add support for /etc/etch.conf. Secondary config files remain in /etc/etch or equivalent. Modified Paths: -------------- trunk/client/Rakefile trunk/client/etchclient.rb Modified: trunk/client/Rakefile =================================================================== --- trunk/client/Rakefile 2009-11-17 00:34:28 UTC (rev 173) +++ trunk/client/Rakefile 2009-11-17 00:35:34 UTC (rev 174) @@ -79,18 +79,28 @@ chmod(0444, File.join(man8dir, 'etch.8')) etcdir = nil + # Start by calculating the real etc directory that will be used when the + # package is installed. We need to substitute that path into the library + # later. realetcdir = nil if options[:etcdir] realetcdir = options[:etcdir] else realetcdir = '/etc' end + # Then compose the etc directory to copy files to etcdir = File.join(destdir, realetcdir) - mkdir_p(etcdir) - etcfiles = ['ca.pem', 'dhparams'] - etcfiles.each do |etcfile| - cp(etcfile, etcdir, :preserve => true) - chmod(0644, File.join(etcdir, etcfile)) + # FIXME: Need to add support for etch.conf to the code + #mkdir_p(etcdir) + #cp('etch.conf', etcdir, :preserve => true) + #chmod(0644, File.join(etcdir, 'etch.conf')) + # All of the supporting config files go into a subdirectory + etcetchdir = File.join(etcdir, 'etch') + mkdir_p(etcetchdir) + etcetchfiles = ['ca.pem', 'dhparams'] + etcetchfiles.each do |etcetchfile| + cp(etcetchfile, etcetchdir, :preserve => true) + chmod(0644, File.join(etcetchdir, etcetchfile)) end if options[:crondir] @@ -391,7 +401,7 @@ desc 'Fetch tarball from sourceforge' task :fetch do if !File.exist?(TARBALL) - url = "http://downloads.sourceforge.net/project/etch/etch/#{ETCHVER}/#{TARBALLFILE}?use_mirror=autoselect" + url = "http://downloads.sourceforge.net/project/etch/etch/#{ETCHVER}/#{TARBALLFILE}" puts "Fetching tarball from #{url}" open(url) do |df| open(TARBALL, 'w') do |lf| Modified: trunk/client/etchclient.rb =================================================================== --- trunk/client/etchclient.rb 2009-11-17 00:34:28 UTC (rev 173) +++ trunk/client/etchclient.rb 2009-11-17 00:35:34 UTC (rev 174) @@ -41,7 +41,7 @@ CONFIRM_SKIP = 2 CONFIRM_QUIT = 3 PRIVATE_KEY_PATHS = ["/etc/ssh/ssh_host_rsa_key", "/etc/ssh_host_rsa_key"] - CONFIGDIR = '/etc/etch' + CONFIGDIR = '/etc' # We need these in relation to the output capturing ORIG_STDOUT = STDOUT.dup @@ -141,17 +141,17 @@ http = Net::HTTP.new(@filesuri.host, @filesuri.port) if @filesuri.scheme == "https" # Eliminate the OpenSSL "using default DH parameters" warning - if File.exist?(File.join(CONFIGDIR, 'dhparams')) - dh = OpenSSL::PKey::DH.new(IO.read(File.join(CONFIGDIR, 'dhparams'))) + if File.exist?(File.join(CONFIGDIR, 'etch', 'dhparams')) + dh = OpenSSL::PKey::DH.new(IO.read(File.join(CONFIGDIR, 'etch', 'dhparams'))) Net::HTTP.ssl_context_accessor(:tmp_dh_callback) http.tmp_dh_callback = proc { dh } end http.use_ssl = true - if File.exist?(File.join(CONFIGDIR, 'ca.pem')) - http.ca_file = File.join(CONFIGDIR, 'ca.pem') + if File.exist?(File.join(CONFIGDIR, 'etch', 'ca.pem')) + http.ca_file = File.join(CONFIGDIR, 'etch', 'ca.pem') http.verify_mode = OpenSSL::SSL::VERIFY_PEER - elsif File.directory?(File.join(CONFIGDIR, 'ca')) - http.ca_path = File.join(CONFIGDIR, 'ca') + elsif File.directory?(File.join(CONFIGDIR, 'etch', 'ca')) + http.ca_path = File.join(CONFIGDIR, 'etch', 'ca') http.verify_mode = OpenSSL::SSL::VERIFY_PEER end end This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <jh...@us...> - 2009-11-23 22:04:51
|
Revision: 177 http://etch.svn.sourceforge.net/etch/?rev=177&view=rev Author: jheiss Date: 2009-11-23 22:04:44 +0000 (Mon, 23 Nov 2009) Log Message: ----------- For all *dir options to copy_etch_files if the option is not specified the associated files will not be copied. This allows package targets to more precisely pick the files they want to include. The gem target was the only target not specifying directories and was easily modified to specify what it wants. Remove :installbase option from copy_etch_files, it wasn't being used for anything. Fix tasks to specify proper etcdir. Remove everything related to auto-update cron jobs. It would be very unusual for publicly-released software to operate that way. Leave it up to end users to auto-update the software appropriately for their environment. Modified Paths: -------------- trunk/client/Rakefile trunk/client/etch_cron Added Paths: ----------- trunk/client/postinstall.solaris trunk/client/postremove.solaris Removed Paths: ------------- trunk/client/postinstall trunk/client/postremove Modified: trunk/client/Rakefile =================================================================== --- trunk/client/Rakefile 2009-11-18 06:24:17 UTC (rev 176) +++ trunk/client/Rakefile 2009-11-23 22:04:44 UTC (rev 177) @@ -9,99 +9,91 @@ BUILDROOT = '/var/tmp/etch-client-buildroot' -# Copies the etch client files to destdir. Appropriate subdirectories will be -# composed unless specified via options. +# Copies the etch client files to destdir. If any of the dir options +# are not specified the files that would go in that directory will not +# be copied. # options: # :bindir # :libdir # :etcdir # :mandir -# :crondir (note no default here, crontab will not be copied if not specified) +# :crondir # :ruby (#! lines in scripts will be changed to specified ruby) -# :installbase (base directory where files will end up) def copy_etch_files(destdir, options={}) - bindir = nil if options[:bindir] bindir = File.join(destdir, options[:bindir]) - else - bindir = File.join(destdir, 'bin') - end - mkdir_p(bindir) - binapps = ['etch', 'etch_to_trunk', 'etch_cron_wrapper'] - binapps.each do |binapp| - if options[:ruby] - # Change #! line - File.open(File.join(bindir, binapp), 'w') do |newfile| - File.open(binapp) do |oldfile| - # Modify the first line - firstline = oldfile.gets - # Preserve any options. I.e. #!/usr/bin/ruby -w - shebang, shebangopts = firstline.split(' ', 2) - newfile.puts "#!#{options[:ruby]} #{shebangopts}" - # Then dump in the rest of the file - newfile.write(oldfile.read) + mkdir_p(bindir) + binapps = ['etch', 'etch_to_trunk', 'etch_cron_wrapper'] + binapps.each do |binapp| + if options[:ruby] + # Change #! line + File.open(File.join(bindir, binapp), 'w') do |newfile| + File.open(binapp) do |oldfile| + # Modify the first line + firstline = oldfile.gets + # Preserve any options. I.e. #!/usr/bin/ruby -w + shebang, shebangopts = firstline.split(' ', 2) + newfile.puts "#!#{options[:ruby]} #{shebangopts}" + # Then dump in the rest of the file + newfile.write(oldfile.read) + end end + else + cp(binapp, bindir, :preserve => true) end - else - cp(binapp, bindir, :preserve => true) + chmod(0555, File.join(bindir, binapp)) end - chmod(0555, File.join(bindir, binapp)) end - libdir = nil if options[:libdir] libdir = File.join(destdir, options[:libdir]) - else - libdir = File.join(destdir, 'lib') + mkdir_p(libdir) + + # Substitute ETCHVER into etchclient.rb + # Substitute proper path into CONFIGDIR in etchclient.rb if appropriate + File.open(File.join(libdir, 'etchclient.rb.new'), 'w') do |newfile| + IO.foreach(File.join(libdir, 'etchclient.rb')) do |line| + if line =~ /^\s*VERSION/ + line.sub!(/=.*/, "= '#{ETCHVER}'") + end + if options[:etcdir] && line =~ /^\s*CONFIGDIR/ + line.sub!(/=.*/, "= #{options[:etcdir]}") + end + newfile.write(line) + end + end + chmod(0444, File.join(libdir, 'etchclient.rb')) + + serverlibs = ['etch.rb', 'versiontype.rb'] + serverlibs.each do |serverlib| + cp(File.join('..', 'server', 'lib', serverlib), libdir, :preserve => true) + chmod(0444, File.join(libdir, serverlib)) + end end - mkdir_p(libdir) - clientlibs = ['etchclient.rb'] - clientlibs.each do |clientlib| - cp(clientlib, libdir, :preserve => true) - end - serverlibs = ['etch.rb', 'versiontype.rb'] - serverlibs.each do |serverlib| - cp(File.join('..', 'server', 'lib', serverlib), libdir, :preserve => true) - end - clientlibs + serverlibs.each do |lib| - chmod(0444, File.join(libdir, lib)) - end - mandir = nil if options[:mandir] mandir = File.join(destdir, options[:mandir]) - else - mandir = File.join(destdir, 'man') + man8dir = File.join(mandir, 'man8') + mkdir_p(man8dir) + cp('etch.8', man8dir, :preserve => true) + chmod(0444, File.join(man8dir, 'etch.8')) end - man8dir = File.join(mandir, 'man8') - mkdir_p(man8dir) - cp('etch.8', man8dir, :preserve => true) - chmod(0444, File.join(man8dir, 'etch.8')) - etcdir = nil - # Start by calculating the real etc directory that will be used when the - # package is installed. We need to substitute that path into the library - # later. - realetcdir = nil if options[:etcdir] - realetcdir = options[:etcdir] - else - realetcdir = '/etc' + etcdir = File.join(destdir, options[:etcdir]) + # FIXME: Need to add support for etch.conf to the code + #mkdir_p(etcdir) + #cp('etch.conf', etcdir, :preserve => true) + #chmod(0644, File.join(etcdir, 'etch.conf')) + # All of the supporting config files go into a subdirectory + etcetchdir = File.join(etcdir, 'etch') + mkdir_p(etcetchdir) + etcetchfiles = ['ca.pem', 'dhparams'] + etcetchfiles.each do |etcetchfile| + cp(etcetchfile, etcetchdir, :preserve => true) + chmod(0644, File.join(etcetchdir, etcetchfile)) + end end - # Then compose the etc directory to copy files to - etcdir = File.join(destdir, realetcdir) - # FIXME: Need to add support for etch.conf to the code - #mkdir_p(etcdir) - #cp('etch.conf', etcdir, :preserve => true) - #chmod(0644, File.join(etcdir, 'etch.conf')) - # All of the supporting config files go into a subdirectory - etcetchdir = File.join(etcdir, 'etch') - mkdir_p(etcetchdir) - etcetchfiles = ['ca.pem', 'dhparams'] - etcetchfiles.each do |etcetchfile| - cp(etcetchfile, etcetchdir, :preserve => true) - chmod(0644, File.join(etcetchdir, etcetchfile)) - end if options[:crondir] crondir = File.join(destdir, options[:crondir]) @@ -111,24 +103,6 @@ cp('etch_cron', File.join(crondir, 'etch'), :preserve => true) chmod(0444, File.join(crondir, 'etch')) end - - # Substitute ETCHVER into etchclient.rb - # Substitute proper path into CONFIGDIR in etchclient.rb if appropriate - newetchclient = File.join(libdir, 'etchclient.rb.new') - etchclient = File.join(libdir, 'etchclient.rb') - File.open(newetchclient, 'w') do |newfile| - IO.foreach(etchclient) do |line| - if line =~ /^\s*VERSION/ - line.sub!(/=.*/, "= '#{ETCHVER}'") - end - if options[:installbase] && line =~ /^\s*CONFIGDIR/ - line.sub!(/=.*/, "= #{realetcdir}") - end - newfile.write(line) - end - end - mv(newetchclient, etchclient) - chmod(0444, etchclient) end desc 'Build an etch client RPM on a Red Hat box' @@ -149,11 +123,10 @@ sbindir = File.join('usr', 'sbin') libdir = File.join('usr', 'lib', 'ruby', 'site_ruby', '1.8') mandir = File.join('usr', 'share', 'man') - etcdir = File.join('etc', 'etch') + etcdir = '/etc' crondir = File.join('etc', 'cron.d') copy_etch_files(BUILDROOT, :bindir => sbindir, :libdir => libdir, - :mandir => mandir, :etcdir => etcdir, :crondir => crondir, - :installbase => '/') + :mandir => mandir, :etcdir => etcdir, :crondir => crondir) # # Prep spec file @@ -198,11 +171,10 @@ sbindir = File.join('usr', 'sbin') libdir = File.join('usr', 'local', 'lib', 'site_ruby', '1.8') mandir = File.join('usr', 'share', 'man') - etcdir = File.join('etc', 'etch') + etcdir = '/etc' crondir = File.join('etc', 'cron.d') copy_etch_files(BUILDROOT, :bindir => sbindir, :libdir => libdir, - :mandir => mandir, :etcdir => etcdir, :crondir => crondir, - :installbase => '/') + :mandir => mandir, :etcdir => etcdir, :crondir => crondir) # # Set permissions @@ -236,10 +208,10 @@ sbindir = File.join('usr', 'sbin') libdir = File.join('opt', 'csw', 'lib', 'ruby', 'site_ruby', '1.8') mandir = File.join('usr', 'share', 'man') - etcdir = File.join('etc', 'etch') + etcdir = '/etc' copy_etch_files(BUILDROOT, :bindir => sbindir, :libdir => libdir, :mandir => mandir, :etcdir => etcdir, - :ruby => '/opt/csw/bin/ruby', :installbase => '/') + :ruby => '/opt/csw/bin/ruby') # # Prep packaging files @@ -257,9 +229,9 @@ prototype.puts("i pkginfo=./pkginfo") cp('depend', 'solbuild/depend') prototype.puts("i depend=./depend") - cp('postinstall', 'solbuild/postinstall') + cp('postinstall.solaris', 'solbuild/postinstall') prototype.puts("i postinstall=./postinstall") - cp('postremove', 'solbuild/postremove') + cp('postremove.solaris', 'solbuild/postremove') prototype.puts("i postremove=./postremove") # The tail +2 removes the first line, which is the base directory # and doesn't need to be included in the package. @@ -310,10 +282,10 @@ sbindir = File.join('usr', 'sbin') libdir = File.join('opt', 'csw', 'lib', 'ruby', 'site_ruby', '1.8') mandir = File.join('usr', 'share', 'man') - etcdir = File.join('etc', 'etch') + etcdir = '/etc' copy_etch_files(BUILDROOT, :bindir => sbindir, :libdir => libdir, :mandir => mandir, :etcdir => etcdir, - :ruby => '/usr/local/bin/ruby', :installbase => '/') + :ruby => '/usr/local/bin/ruby') # Since we're using the Sunfreeware ruby but CSW libraries we need to add # the CSW ruby library directory to the search path @@ -346,9 +318,9 @@ prototype.puts("i pkginfo=./pkginfo") cp('depend', 'solbuild/depend') prototype.puts("i depend=./depend") - cp('postinstall', 'solbuild/postinstall') + cp('postinstall.solaris', 'solbuild/postinstall') prototype.puts("i postinstall=./postinstall") - cp('postremove', 'solbuild/postremove') + cp('postremove.solaris', 'solbuild/postremove') prototype.puts("i postremove=./postremove") # The tail +2 removes the first line, which is the base directory # and doesn't need to be included in the package. @@ -394,8 +366,7 @@ :mandir => Config::CONFIG['mandir'], :etcdir => Config::CONFIG['sysconfdir'], # Can't find a better way to get the path to the current ruby - :ruby => File.join(Config::CONFIG['bindir'], Config::CONFIG['ruby_install_name']), - :installbase => '/') + :ruby => File.join(Config::CONFIG['bindir'], Config::CONFIG['ruby_install_name'])) end desc 'Fetch tarball from sourceforge' @@ -437,10 +408,12 @@ # rm_rf(BUILDROOT) - copy_etch_files(BUILDROOT) + copy_tpkg_files(BUILDROOT, + :bindir => 'bin', + :libdir => 'lib') # - # Prep gemspec + # Prep gemspec (renaming to Rakefile in the process) # File.open(File.join(BUILDROOT, 'Rakefile'), 'w') do |gemspec| IO.foreach('gemspec') do |line| Modified: trunk/client/etch_cron =================================================================== --- trunk/client/etch_cron 2009-11-18 06:24:17 UTC (rev 176) +++ trunk/client/etch_cron 2009-11-23 22:04:44 UTC (rev 177) @@ -8,6 +8,3 @@ MAILTO="" 0 * * * * root /usr/sbin/etch_cron_wrapper -# Make sure the client package stays updated -MAILTO="" -0 0 * * * root yum -d 0 -e 0 -R 30 -y update etch-client Deleted: trunk/client/postinstall =================================================================== --- trunk/client/postinstall 2009-11-18 06:24:17 UTC (rev 176) +++ trunk/client/postinstall 2009-11-23 22:04:44 UTC (rev 177) @@ -1,9 +0,0 @@ -#!/bin/sh - -# Everything about this makes me feel dirty -crontab -l | grep -v etch > /tmp/root_crontab || exit 1 -echo "0 * * * * /usr/sbin/etch_cron_wrapper > /dev/null 2>&1" >> /tmp/root_crontab || exit 1 -echo "0 0 * * * /opt/csw/bin/pkg-get -U > /dev/null 2>&1; /opt/csw/bin/pkg-get -u YPCetch > /dev/null 2>&1" >> /tmp/root_crontab || exit 1 -crontab /tmp/root_crontab -rm /tmp/root_crontab - Copied: trunk/client/postinstall.solaris (from rev 176, trunk/client/postinstall) =================================================================== --- trunk/client/postinstall.solaris (rev 0) +++ trunk/client/postinstall.solaris 2009-11-23 22:04:44 UTC (rev 177) @@ -0,0 +1,8 @@ +#!/bin/sh + +# Everything about this makes me feel dirty +crontab -l | grep -v etch > /tmp/root_crontab || exit 1 +echo "0 * * * * /usr/sbin/etch_cron_wrapper > /dev/null 2>&1" >> /tmp/root_crontab || exit 1 +crontab /tmp/root_crontab +rm /tmp/root_crontab + Deleted: trunk/client/postremove =================================================================== --- trunk/client/postremove 2009-11-18 06:24:17 UTC (rev 176) +++ trunk/client/postremove 2009-11-23 22:04:44 UTC (rev 177) @@ -1,10 +0,0 @@ -#!/bin/sh - -crontab -l | /usr/xpg4/bin/grep -qs etch -if [ $? = 0 ] -then - crontab -l | grep -v etch > /tmp/root_crontab || exit 1 - crontab /tmp/root_crontab - rm /tmp/root_crontab -fi - Copied: trunk/client/postremove.solaris (from rev 176, trunk/client/postremove) =================================================================== --- trunk/client/postremove.solaris (rev 0) +++ trunk/client/postremove.solaris 2009-11-23 22:04:44 UTC (rev 177) @@ -0,0 +1,10 @@ +#!/bin/sh + +crontab -l | /usr/xpg4/bin/grep -qs etch +if [ $? = 0 ] +then + crontab -l | grep -v etch > /tmp/root_crontab || exit 1 + crontab /tmp/root_crontab + rm /tmp/root_crontab +fi + This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <jh...@us...> - 2010-01-20 22:44:03
|
Revision: 191 http://etch.svn.sourceforge.net/etch/?rev=191&view=rev Author: jheiss Date: 2010-01-20 22:43:55 +0000 (Wed, 20 Jan 2010) Log Message: ----------- Remove dependency on RCS now that history logs are stored as individual files. Modified Paths: -------------- trunk/client/control trunk/client/depend trunk/client/etch-client.spec trunk/client/etch.spec Modified: trunk/client/control =================================================================== --- trunk/client/control 2010-01-20 22:41:41 UTC (rev 190) +++ trunk/client/control 2010-01-20 22:43:55 UTC (rev 191) @@ -2,6 +2,6 @@ Version: %VER%-1 Maintainer: etc...@li... Architecture: all -Depends: ruby facter rcs +Depends: ruby facter Description: Etch client Modified: trunk/client/depend =================================================================== --- trunk/client/depend 2010-01-20 22:41:41 UTC (rev 190) +++ trunk/client/depend 2010-01-20 22:43:55 UTC (rev 191) @@ -1,4 +1,3 @@ P CSWruby P CSWfacter -P CSWrcs Modified: trunk/client/etch-client.spec =================================================================== --- trunk/client/etch-client.spec 2010-01-20 22:41:41 UTC (rev 190) +++ trunk/client/etch-client.spec 2010-01-20 22:43:55 UTC (rev 191) @@ -5,7 +5,7 @@ Group: Applications/System License: MIT buildarch: noarch -Requires: ruby, facter, rcs, crontabs +Requires: ruby, facter, crontabs BuildRoot: %{_builddir}/%{name}-buildroot %description Etch client Modified: trunk/client/etch.spec =================================================================== --- trunk/client/etch.spec 2010-01-20 22:41:41 UTC (rev 190) +++ trunk/client/etch.spec 2010-01-20 22:43:55 UTC (rev 191) @@ -10,7 +10,7 @@ BuildRoot: %{_tmppath}/%{name}-%{version}-%{release}-root-%(%{__id_u} -n) BuildRequires: rubygem-rake -Requires: ruby(abi) = 1.8, facter, rcs +Requires: ruby(abi) = 1.8, facter # Per http://fedoraproject.org/wiki/Packaging:Ruby %{!?ruby_sitelib: %global ruby_sitelib %(ruby -rrbconfig -e 'puts Config::CONFIG["sitelibdir"] ')} This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <jh...@us...> - 2010-12-22 21:04:01
|
Revision: 241 http://etch.svn.sourceforge.net/etch/?rev=241&view=rev Author: jheiss Date: 2010-12-22 21:03:55 +0000 (Wed, 22 Dec 2010) Log Message: ----------- Move the MacPort's Portfile template to Portfile.template. Save the latest Portfile in svn so that we can easily diff against it, as the MacPorts guys have indicated that they prefer a diff to a whole file. Update the Rakefile to generate the Portfile from Portfile.template. Modified Paths: -------------- trunk/client/Rakefile Added Paths: ----------- trunk/client/Portfile.template Removed Paths: ------------- trunk/client/Portfile Deleted: trunk/client/Portfile =================================================================== --- trunk/client/Portfile 2010-12-22 20:44:02 UTC (rev 240) +++ trunk/client/Portfile 2010-12-22 21:03:55 UTC (rev 241) @@ -1,42 +0,0 @@ -# -*- coding: utf-8; mode: tcl; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- vim:fenc=utf-8:ft=tcl:et:sw=4:ts=4:sts=4 -# $Id$ - -PortSystem 1.0 -PortGroup ruby 1.0 - -name etch -version %VER% -categories sysutils -maintainers aput.net:jheiss openmaintainer -supported_archs noarch - -description Etch is a system configuration management tool. - -long_description Etch is a tool for managing the configuration of \ - Unix systems. Etch can manage text or binary \ - files, links and directories. The contents of \ - files can be supplied from static files or \ - generated on the fly by scripts or templates. \ - Permissions and ownership as well as any pre or \ - post commands to run when updating the file are \ - configured in simple XML files. - -homepage http://etch.sourceforge.net/ -platforms darwin - -master_sites sourceforge - -checksums md5 %MD5% \ - sha1 %SHA1% \ - rmd160 %RMD160% - -depends_build port:rb-rake -depends_run port:facter - -worksrcdir ${worksrcdir}/client -use_configure no -build {} -destroot.cmd ${prefix}/bin/rake -destroot.target install\[${destroot}\] -destroot.destdir - Copied: trunk/client/Portfile.template (from rev 240, trunk/client/Portfile) =================================================================== --- trunk/client/Portfile.template (rev 0) +++ trunk/client/Portfile.template 2010-12-22 21:03:55 UTC (rev 241) @@ -0,0 +1,41 @@ +# -*- coding: utf-8; mode: tcl; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- vim:fenc=utf-8:ft=tcl:et:sw=4:ts=4:sts=4 +# $Id$ + +PortSystem 1.0 +PortGroup ruby 1.0 + +name etch +version %VER% +categories sysutils +maintainers aput.net:jheiss openmaintainer +supported_archs noarch + +description Etch is a system configuration management tool. + +long_description Etch is a tool for managing the configuration of \ + Unix systems. Etch can manage text or binary \ + files, links and directories. The contents of \ + files can be supplied from static files or \ + generated on the fly by scripts or templates. \ + Permissions and ownership as well as any pre or \ + post commands to run when updating the file are \ + configured in simple XML files. + +homepage http://etch.sourceforge.net/ +platforms darwin + +master_sites sourceforge + +checksums md5 %MD5% \ + sha1 %SHA1% \ + rmd160 %RMD160% + +depends_build port:rb-rake +depends_run port:facter + +worksrcdir ${worksrcdir}/client +use_configure no +build {} +destroot.cmd ${prefix}/bin/rake +destroot.target install\[${destroot}\] +destroot.destdir Modified: trunk/client/Rakefile =================================================================== --- trunk/client/Rakefile 2010-12-22 20:44:02 UTC (rev 240) +++ trunk/client/Rakefile 2010-12-22 21:03:55 UTC (rev 241) @@ -395,7 +395,7 @@ portfile = File.join(Dir.tmpdir, 'Portfile') rm_f(portfile) File.open(portfile, 'w') do |newfile| - IO.foreach('Portfile') do |line| + IO.foreach('Portfile.template') do |line| line.sub!('%VER%', ETCHVER) line.sub!('%MD5%', md5) line.sub!('%SHA1%', sha1) This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <jh...@us...> - 2011-05-04 17:43:55
|
Revision: 278 http://etch.svn.sourceforge.net/etch/?rev=278&view=rev Author: jheiss Date: 2011-05-04 17:43:47 +0000 (Wed, 04 May 2011) Log Message: ----------- Clean up the client directory structure to look like a real ruby project Modified Paths: -------------- trunk/client/Rakefile Added Paths: ----------- trunk/client/bin/ trunk/client/bin/etch trunk/client/bin/etch_cron_wrapper trunk/client/bin/etch_to_trunk trunk/client/etc/ trunk/client/etc/cron.d/ trunk/client/etc/cron.d/etch trunk/client/etc/etch/ trunk/client/etc/etch/ca.pem trunk/client/etc/etch/dhparams trunk/client/etc/etch.conf trunk/client/lib/ trunk/client/lib/etch/ trunk/client/lib/etch/client.rb trunk/client/man/ trunk/client/man/man8/ trunk/client/man/man8/etch.8 trunk/client/packages/ trunk/client/packages/deb/ trunk/client/packages/deb/control trunk/client/packages/gem/ trunk/client/packages/gem/gemspec trunk/client/packages/macports/ trunk/client/packages/macports/Portfile trunk/client/packages/macports/Portfile.template trunk/client/packages/rpm/ trunk/client/packages/rpm/etch-client.spec trunk/client/packages/rpm/etch.spec trunk/client/packages/sysv/ trunk/client/packages/sysv/depend trunk/client/packages/sysv/pkginfo trunk/client/packages/sysv/postinstall.solaris trunk/client/packages/sysv/postremove.solaris Removed Paths: ------------- trunk/client/Portfile trunk/client/Portfile.template trunk/client/ca.pem trunk/client/control trunk/client/depend trunk/client/dhparams trunk/client/etch trunk/client/etch-client.spec trunk/client/etch.8 trunk/client/etch.conf trunk/client/etch.spec trunk/client/etch_cron trunk/client/etch_cron_wrapper trunk/client/etch_to_trunk trunk/client/etchclient.rb trunk/client/gemspec trunk/client/pkginfo trunk/client/postinstall.solaris trunk/client/postremove.solaris Deleted: trunk/client/Portfile =================================================================== --- trunk/client/Portfile 2011-05-04 14:34:24 UTC (rev 277) +++ trunk/client/Portfile 2011-05-04 17:43:47 UTC (rev 278) @@ -1,41 +0,0 @@ -# -*- coding: utf-8; mode: tcl; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- vim:fenc=utf-8:ft=tcl:et:sw=4:ts=4:sts=4 -# $Id$ - -PortSystem 1.0 -PortGroup ruby 1.0 - -name etch -version 3.17.0 -categories sysutils -maintainers aput.net:jheiss openmaintainer - -description Etch is a system configuration management tool. - -long_description Etch is a tool for managing the configuration of \ - Unix systems. Etch can manage text or binary \ - files, links and directories. The contents of \ - files can be supplied from static files or \ - generated on the fly by scripts or templates. \ - Permissions and ownership as well as any pre or \ - post commands to run when updating the file are \ - configured in simple XML files. - -homepage http://etch.sourceforge.net/ -platforms darwin - -master_sites sourceforge - -checksums md5 9b5216f62d4add225f50984cc07f630b \ - sha1 a4bc1c61f349464ca793d858abeca08760bde6e5 \ - rmd160 f827b360c69cceab1a864b11c7cf434b7c7a4a39 - -depends_build port:rb-rake -depends_run port:facter - -worksrcdir ${worksrcdir}/client -supported_archs noarch -use_configure no -build {} -destroot.cmd ${prefix}/bin/rake -destroot.target install\[${destroot}\] -destroot.destdir Deleted: trunk/client/Portfile.template =================================================================== --- trunk/client/Portfile.template 2011-05-04 14:34:24 UTC (rev 277) +++ trunk/client/Portfile.template 2011-05-04 17:43:47 UTC (rev 278) @@ -1,42 +0,0 @@ -# -*- coding: utf-8; mode: tcl; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- vim:fenc=utf-8:ft=tcl:et:sw=4:ts=4:sts=4 -# $Id$ - -PortSystem 1.0 -PortGroup ruby 1.0 - -name etch -version %VER% -categories sysutils -maintainers aput.net:jheiss openmaintainer -supported_archs noarch - -description Etch is a system configuration management tool. - -long_description Etch is a tool for managing the configuration of \ - Unix systems. Etch can manage text or binary \ - files, links and directories. The contents of \ - files can be supplied from static files or \ - generated on the fly by scripts or templates. \ - Permissions and ownership as well as any pre or \ - post commands to run when updating the file are \ - configured in simple XML files. - -homepage http://etch.sourceforge.net/ -platforms darwin - -master_sites sourceforge - -checksums md5 %MD5% \ - sha1 %SHA1% \ - rmd160 %RMD160% - -depends_build port:rb-rake -depends_run port:facter - -worksrcdir ${worksrcdir}/client -supported_archs noarch -use_configure no -build {} -destroot.cmd ${prefix}/bin/rake -destroot.target install\[${destroot}\] -destroot.destdir Modified: trunk/client/Rakefile =================================================================== --- trunk/client/Rakefile 2011-05-04 14:34:24 UTC (rev 277) +++ trunk/client/Rakefile 2011-05-04 17:43:47 UTC (rev 278) @@ -28,7 +28,7 @@ if options[:ruby] # Change #! line File.open(File.join(bindir, binapp), 'w') do |newfile| - File.open(binapp) do |oldfile| + File.open(File.join('bin', binapp)) do |oldfile| # Modify the first line firstline = oldfile.gets # Preserve any options. I.e. #!/usr/bin/ruby -w @@ -39,7 +39,7 @@ end end else - cp(binapp, bindir, :preserve => true) + cp(File.join('bin', binapp), bindir, :preserve => true) end chmod(0555, File.join(bindir, binapp)) end @@ -48,11 +48,12 @@ if options[:libdir] libdir = File.join(destdir, options[:libdir]) mkdir_p(libdir) + mkdir_p(File.join(libdir, 'etch')) - # Substitute ETCHVER into etchclient.rb - # Substitute proper path into CONFIGDIR in etchclient.rb if appropriate - File.open(File.join(libdir, 'etchclient.rb'), 'w') do |newfile| - IO.foreach('etchclient.rb') do |line| + # Substitute ETCHVER into etch/client.rb + # Substitute proper path into CONFIGDIR in etch/client.rb if appropriate + File.open(File.join(libdir, 'etch', 'client.rb'), 'w') do |newfile| + IO.foreach(File.join('etch', 'client.rb')) do |line| if line =~ /^\s*VERSION/ line.sub!(/=.*/, "= '#{ETCHVER}'") end @@ -62,9 +63,9 @@ newfile.write(line) end end - chmod(0444, File.join(libdir, 'etchclient.rb')) + chmod(0444, File.join(libdir, 'etch', 'client.rb')) - serverlibs = ['etch.rb', 'versiontype.rb'] + serverlibs = ['etch.rb', 'silently.rb', 'versiontype.rb'] serverlibs.each do |serverlib| cp(File.join('..', 'server', 'lib', serverlib), libdir, :preserve => true) chmod(0444, File.join(libdir, serverlib)) @@ -75,21 +76,21 @@ mandir = File.join(destdir, options[:mandir]) man8dir = File.join(mandir, 'man8') mkdir_p(man8dir) - cp('etch.8', man8dir, :preserve => true) + cp(File.join('man', 'man8', 'etch.8'), man8dir, :preserve => true) chmod(0444, File.join(man8dir, 'etch.8')) end if options[:etcdir] etcdir = File.join(destdir, options[:etcdir]) mkdir_p(etcdir) - cp('etch.conf', etcdir, :preserve => true) + cp(File.join('etc', 'etch.conf'), etcdir, :preserve => true) chmod(0644, File.join(etcdir, 'etch.conf')) # All of the supporting config files go into a subdirectory etcetchdir = File.join(etcdir, 'etch') mkdir_p(etcetchdir) etcetchfiles = ['ca.pem', 'dhparams'] etcetchfiles.each do |etcetchfile| - cp(etcetchfile, etcetchdir, :preserve => true) + cp(File.join('etc', 'etch', etcetchfile), etcetchdir, :preserve => true) chmod(0644, File.join(etcetchdir, etcetchfile)) end end @@ -97,9 +98,7 @@ if options[:crondir] crondir = File.join(destdir, options[:crondir]) mkdir_p(crondir) - # Note file renamed to 'etch' here. Filename is different in the repo for - # clarity and to avoid conflict with the main executable. - cp('etch_cron', File.join(crondir, 'etch'), :preserve => true) + cp(File.join('etc', 'cron.d', 'etch'), crondir, :preserve => true) chmod(0444, File.join(crondir, 'etch')) end end @@ -132,7 +131,7 @@ # spec = Tempfile.new('etchrpm') - IO.foreach('etch-client.spec') do |line| + IO.foreach(File.join('packages', 'rpm', 'etch-client.spec')) do |line| line.sub!('%VER%', ETCHVER) spec.puts(line) end @@ -161,7 +160,7 @@ mkdir_p(File.join(BUILDROOT, 'DEBIAN')) File.open(File.join(BUILDROOT, 'DEBIAN', 'control'), 'w') do |control| - IO.foreach('control') do |line| + IO.foreach(File.join('packages', 'deb', 'control')) do |line| next if line =~ /^\s*#/ # Remove comments line.sub!('%VER%', ETCHVER) control.puts(line) @@ -220,19 +219,19 @@ rm_rf('solbuild') mkdir('solbuild') File.open(File.join('solbuild', 'pkginfo'), 'w') do |pkginfo| - IO.foreach('pkginfo') do |line| + IO.foreach(File.join('packages', 'sysv', 'pkginfo')) do |line| line.sub!('%VER%', ETCHVER) pkginfo.puts(line) end end File.open(File.join('solbuild', 'prototype'), 'w') do |prototype| prototype.puts("i pkginfo=./pkginfo") - cp('depend', 'solbuild/depend') + cp(File.join('packages', 'sysv', 'depend'), 'solbuild/depend') prototype.puts("i depend=./depend") - cp('postinstall.solaris', 'solbuild/postinstall') + cp(File.join('packages', 'sysv', 'postinstall.solaris'), 'solbuild/postinstall') chmod(0555, 'solbuild/postinstall') prototype.puts("i postinstall=./postinstall") - cp('postremove.solaris', 'solbuild/postremove') + cp(File.join('packages', 'sysv', 'postremove.solaris'), 'solbuild/postremove') chmod(0555, 'solbuild/postremove') prototype.puts("i postremove=./postremove") # The tail +2 removes the first line, which is the base directory @@ -311,19 +310,19 @@ rm_rf('solbuild') mkdir('solbuild') File.open(File.join('solbuild', 'pkginfo'), 'w') do |pkginfo| - IO.foreach('pkginfo') do |line| + IO.foreach(File.join('packages', 'sysv', 'pkginfo')) do |line| line.sub!('%VER%', ETCHVER) pkginfo.puts(line) end end File.open(File.join('solbuild', 'prototype'), 'w') do |prototype| prototype.puts("i pkginfo=./pkginfo") - cp('depend', 'solbuild/depend') + cp(File.join('packages', 'sysv', 'depend'), 'solbuild/depend') prototype.puts("i depend=./depend") - cp('postinstall.solaris', 'solbuild/postinstall') + cp(File.join('packages', 'sysv', 'postinstall.solaris'), 'solbuild/postinstall') chmod(0555, 'solbuild/postinstall') prototype.puts("i postinstall=./postinstall") - cp('postremove.solaris', 'solbuild/postremove') + cp(File.join('packages', 'sysv', 'postremove.solaris'), 'solbuild/postremove') chmod(0555, 'solbuild/postremove') prototype.puts("i postremove=./postremove") # The tail +2 removes the first line, which is the base directory @@ -395,7 +394,7 @@ portfile = File.join(Dir.tmpdir, 'Portfile') rm_f(portfile) File.open(portfile, 'w') do |newfile| - IO.foreach('Portfile.template') do |line| + IO.foreach(File.join('packages', 'macports', 'Portfile.template')) do |line| line.sub!('%VER%', ETCHVER) line.sub!('%MD5%', md5) line.sub!('%SHA1%', sha1) @@ -421,7 +420,7 @@ # Prep gemspec (renaming to Rakefile in the process) # File.open(File.join(BUILDROOT, 'Rakefile'), 'w') do |gemspec| - IO.foreach('gemspec') do |line| + IO.foreach(File.join('packages', 'gem', 'gemspec')) do |line| line.sub!('%VER%', ETCHVER) gemspec.puts(line) end Copied: trunk/client/bin/etch (from rev 272, trunk/client/etch) =================================================================== --- trunk/client/bin/etch (rev 0) +++ trunk/client/bin/etch 2011-05-04 17:43:47 UTC (rev 278) @@ -0,0 +1,111 @@ +#!/usr/bin/ruby -w +############################################################################## +# Etch configuration file management tool +############################################################################## + +# Ensure we can find etch/client.rb when run within the development repository +$:.unshift(File.join(File.dirname(__FILE__), 'lib')) + +require 'optparse' +require 'etch/client' + +# +# Parse the command line options +# + +options = {} +@generateall = nil + +# Extra options to OptionParser reduce the amount of whitespace it introduces +# into the help message, making it easier to make the help message fit in a +# 80x24 window. +opts = OptionParser.new(nil, 24, ' ') +opts.banner = 'Usage: etch [options] [/path/to/config/file | command] [otherfile ...]' +opts.on('--generate-all', 'Request all configuration.') do |opt| + @generateall = opt +end +opts.on('--dry-run', '-n', 'Make no changes.') do |opt| + options[:dryrun] = opt +end +opts.on('--damp-run', "Perform a dry run but run 'setup' entries for files.") do |opt| + # Rather than sprinkle checks of two different variables throught the code, if + # we're asked to do a damp run then just set the dry run flag to a unique + # value. Then we can just check for that specific value at the one place where + # the two modes differ: enabling or disabling the execution of 'setup' + # entries. + options[:dryrun] = 'damp' +end +opts.on('--list-files', 'Just list the files that would be configured') do |opt| + options[:listfiles] = opt + # generate all is implied + @generateall = true + # Set :dryrun as a extra measure to make sure we don't change anything + options[:dryrun] = 'listfiles' +end +opts.on('--interactive', 'Prompt for confirmation before each change.') do |opt| + options[:interactive] = opt +end +opts.on('--full-file', 'Display full new file contents instead of a diff.') do |opt| + options[:fullfile] = opt +end +opts.on('--filename-only', 'Display filename of changed files instead of a diff.') do |opt| + options[:filenameonly] = opt +end +opts.on('--disable-force', 'Ignore the disable_etch file. Use with caution.') do |opt| + options[:disableforce] = opt +end +opts.on('--lock-force', 'Force the removal of any existing lockfiles.') do |opt| + options[:lockforce] = opt +end +opts.on('--local DIR', 'Read configuration from local directory, not server.') do |opt| + options[:local] = opt +end +opts.on('--server SERVER', 'Point etch to an alternate server.') do |opt| + options[:server] = opt +end +opts.on('--tag TAG', 'Request a specific repository tag from the server.') do |opt| + options[:tag] = opt +end +opts.on('--key PRIVATE_KEY', 'Use this private key for signing messages to server.') do |opt| + options[:key] = opt +end +opts.on('--test-root TESTDIR', 'For use by the test suite only.') do |opt| + options[:file_system_root] = opt +end +opts.on('--debug', 'Print lots of messages about what etch is doing.') do |opt| + options[:debug] = opt +end +opts.on('--version', 'Show etch client version.') do |opt| + puts Etch::Client::VERSION + exit +end +opts.on_tail('-h', '--help', 'Show this message.') do + puts opts + exit +end + +leftovers = opts.parse(ARGV) +files = [] +commands = [] +leftovers.each do |leftover| + if leftover[0,1] == File::SEPARATOR + files << leftover + else + commands << leftover + end +end + +# Display a usage message if the user did not specify a valid action to perform. +if files.empty? && commands.empty? && !@generateall + puts opts + exit +end + +# +# Do stuff +# + +etchclient = Etch::Client.new(options) +status = etchclient.process_until_done(files, commands) +exit status + Copied: trunk/client/bin/etch_cron_wrapper (from rev 272, trunk/client/etch_cron_wrapper) =================================================================== --- trunk/client/bin/etch_cron_wrapper (rev 0) +++ trunk/client/bin/etch_cron_wrapper 2011-05-04 17:43:47 UTC (rev 278) @@ -0,0 +1,18 @@ +#!/usr/bin/ruby -w + +require 'socket' +require 'digest/sha1' + +# Seed the random number generator with the hostname of this box so that +# we get a consistent random number. We want to run the registration at a +# consistent time on each individual box, but randomize the runs across +# the environment. +srand(Digest::SHA1.hexdigest(Socket.gethostname)[0,7].hex) + +# Cron job is set to run every hour +MAX_SLEEP = 60 * 60 + +sleep(rand(MAX_SLEEP)) + +exec('/usr/sbin/etch', '--generate-all') + Copied: trunk/client/bin/etch_to_trunk (from rev 272, trunk/client/etch_to_trunk) =================================================================== --- trunk/client/bin/etch_to_trunk (rev 0) +++ trunk/client/bin/etch_to_trunk 2011-05-04 17:43:47 UTC (rev 278) @@ -0,0 +1,77 @@ +#!/usr/bin/ruby -w + +require 'nventory' +require 'time' +require 'optparse' + +ETCH_SERVER_TZ = 'UTC' # The etch servers run in UTC + +options = {} +opts = OptionParser.new +opts.banner = 'Usage: etch_to_trunk [options] <server1> [<server2> <server3>]' +opts.on('-u', '--username USERNAME', 'Username for connecting to nventory server.') do |opt| + options[:username] = opt +end +opts.on('-t', '--timezone TIMEZONE', 'Time zone of etch server.') do |opt| + options[:timezone] = opt +end +opts.on('--nv SERVER', 'Where nVentory server is running.') do |opt| + options[:nv_server] = opt +end +opts.on_tail('-h', '--help', 'Show this message.') do + puts opts + exit +end + +nodes = opts.parse(ARGV) + +if ARGV.length == 0 + puts opts + exit +end + +@username = options[:username] || ENV['LOGNAME'] +etch_server_tz = options[:timezone] || ETCH_SERVER_TZ + +if etch_server_tz + currentheadtag = Time.at(Time.now.utc + Time.zone_offset(etch_server_tz)).strftime('trunk-%Y%m%d-%H00') +else # if no timezone is specified then just use local time for the tag + currentheadtag = Time.now.strftime('trunk-%Y%m%d-%H00') +end + +# Find the requested clients +nv_server = options[:nv_server] +if nv_server + nvclient = NVentory::Client.new(:server=>"http://#{nv_server}") +else + nvclient = NVentory::Client.new +end +results = nvclient.get_objects('nodes', {}, { 'name' => nodes }, {}, {}) +nodes.each do |name| + if results.empty? && results[name].nil? + abort "No entry found for #{name}" + else + if !results[name]['config_mgmt_tag'].nil? && + !results[name]['config_mgmt_tag'].empty? + puts "Changing #{name} from #{results[name]['config_mgmt_tag']} to #{currentheadtag}" + else + puts "Setting #{name} to #{currentheadtag}" + end + end +end + +while true + print "Proceed? [y|n] " + response = $stdin.gets.chomp + if response == 'y' + break + elsif response == 'n' + exit + end +end + +# Update the clients +successcount = nvclient.set_objects('nodes', results, {'config_mgmt_tag' => currentheadtag}, @username) + +puts "#{File.basename($0)} operation succeeded for #{successcount} of #{results.size} nodes" + Deleted: trunk/client/ca.pem =================================================================== --- trunk/client/ca.pem 2011-05-04 14:34:24 UTC (rev 277) +++ trunk/client/ca.pem 2011-05-04 17:43:47 UTC (rev 278) @@ -1 +0,0 @@ -# Add your SSL certificate authority's cert(s) to this file Deleted: trunk/client/control =================================================================== --- trunk/client/control 2011-05-04 14:34:24 UTC (rev 277) +++ trunk/client/control 2011-05-04 17:43:47 UTC (rev 278) @@ -1,7 +0,0 @@ -Package: etch-client -Version: %VER%-1 -Maintainer: etc...@li... -Architecture: all -Depends: ruby, libopenssl-ruby1.8, facter, lsb-release, lsb-base -Description: Etch client - Deleted: trunk/client/depend =================================================================== --- trunk/client/depend 2011-05-04 14:34:24 UTC (rev 277) +++ trunk/client/depend 2011-05-04 17:43:47 UTC (rev 278) @@ -1,3 +0,0 @@ -P CSWruby -P CSWfacter - Deleted: trunk/client/dhparams =================================================================== --- trunk/client/dhparams 2011-05-04 14:34:24 UTC (rev 277) +++ trunk/client/dhparams 2011-05-04 17:43:47 UTC (rev 278) @@ -1,9 +0,0 @@ ------BEGIN DH PARAMETERS----- -MIIBCAKCAQEA3HySq1WdL67BCSRCJCZYMUIojAWAsvK63D3cOGk0wI9UeM/yeVhz -jTswvHOVPZFKIBg1Aeo2eAEdPryDnmjVTgvLbuWkCPouQhBCVsQ1El9ZcXPix1rC -tYsg4Kll1jgnwFoHf4xvjPnD/SqsASAiDxYlh4CFVyT1gLgSiUU0rIdudgO3agI5 -NgiyGOKwyHmNOOQSKA62M/JnoxcBDC7Nou3lqtHpR5yWsUz+csyk+hXZeUba97bm -M8OB0PmfK4Vo6JpdO+yc8hjeYBoMsH7g/l3Gm1JqUxxctcY/OuJ+2nkXwsD66E3D -yZCoiVd3u4OqAxNO/GG0iUmskjIvokMhUwIBAg== ------END DH PARAMETERS----- - Copied: trunk/client/etc/cron.d/etch (from rev 272, trunk/client/etch_cron) =================================================================== --- trunk/client/etc/cron.d/etch (rev 0) +++ trunk/client/etc/cron.d/etch 2011-05-04 17:43:47 UTC (rev 278) @@ -0,0 +1,10 @@ +# Run the etch client every hour +# If you want to disable etch updates do NOT comment out this cron job. +# Our next client update will just put it back anyway. +# Instead create /var/etch/disable_etch and add a comment as to +# why this box shouldn't be getting updates. Etch will notice +# that file and abort. disable_etch files with no comment will be +# removed by the System Administration team without warning. +MAILTO="" +0 * * * * root /usr/sbin/etch_cron_wrapper + Copied: trunk/client/etc/etch/ca.pem (from rev 272, trunk/client/ca.pem) =================================================================== --- trunk/client/etc/etch/ca.pem (rev 0) +++ trunk/client/etc/etch/ca.pem 2011-05-04 17:43:47 UTC (rev 278) @@ -0,0 +1 @@ +# Add your SSL certificate authority's cert(s) to this file Copied: trunk/client/etc/etch/dhparams (from rev 272, trunk/client/dhparams) =================================================================== --- trunk/client/etc/etch/dhparams (rev 0) +++ trunk/client/etc/etch/dhparams 2011-05-04 17:43:47 UTC (rev 278) @@ -0,0 +1,9 @@ +-----BEGIN DH PARAMETERS----- +MIIBCAKCAQEA3HySq1WdL67BCSRCJCZYMUIojAWAsvK63D3cOGk0wI9UeM/yeVhz +jTswvHOVPZFKIBg1Aeo2eAEdPryDnmjVTgvLbuWkCPouQhBCVsQ1El9ZcXPix1rC +tYsg4Kll1jgnwFoHf4xvjPnD/SqsASAiDxYlh4CFVyT1gLgSiUU0rIdudgO3agI5 +NgiyGOKwyHmNOOQSKA62M/JnoxcBDC7Nou3lqtHpR5yWsUz+csyk+hXZeUba97bm +M8OB0PmfK4Vo6JpdO+yc8hjeYBoMsH7g/l3Gm1JqUxxctcY/OuJ+2nkXwsD66E3D +yZCoiVd3u4OqAxNO/GG0iUmskjIvokMhUwIBAg== +-----END DH PARAMETERS----- + Copied: trunk/client/etc/etch.conf (from rev 272, trunk/client/etch.conf) =================================================================== --- trunk/client/etc/etch.conf (rev 0) +++ trunk/client/etc/etch.conf 2011-05-04 17:43:47 UTC (rev 278) @@ -0,0 +1,25 @@ +# The default server url is https://etch +#server = https://etch + +# Etch is usually run from cron, and cron usually executes jobs with a very +# minimal PATH environment variable setting. You may want etch to have a more +# complete PATH setting so that pre and post commands are more readily found. +#path = /bin:/usr/bin:/sbin:/usr/sbin + +# Etch can read configuration from a local directory rather than from a +# server. If set this will override the server setting. +#local = /var/etch/configs + +# Etch will try to find an SSH host key and use it to sign all requests to the +# etch server. Several standard locations for host keys are searched by +# default. If your host key is not in a standard location then you can point +# etch to it. +# See http://sourceforge.net/apps/trac/etch/wiki/ClientAuthentication +#key = /etc/ssh/ssh_host_rsa_key + +# Etch can send detailed results back to the server for viewing in the web UI +# and/or to a local log file. They are sent to the server by default. +# Note that SERVER is ignored when etch is running in local mode. +#detailed_results = SERVER +#detailed_results = /var/etch/results.log + Deleted: trunk/client/etch =================================================================== --- trunk/client/etch 2011-05-04 14:34:24 UTC (rev 277) +++ trunk/client/etch 2011-05-04 17:43:47 UTC (rev 278) @@ -1,111 +0,0 @@ -#!/usr/bin/ruby -w -############################################################################## -# Etch configuration file management tool -############################################################################## - -# Ensure we can find etchclient.rb -$:.unshift(File.dirname(__FILE__)) - -require 'optparse' -require 'etchclient' - -# -# Parse the command line options -# - -options = {} -@generateall = nil - -# Extra options to OptionParser reduce the amount of whitespace it introduces -# into the help message, making it easier to make the help message fit in a -# 80x24 window. -opts = OptionParser.new(nil, 24, ' ') -opts.banner = 'Usage: etch [options] [/path/to/config/file | command] [otherfile ...]' -opts.on('--generate-all', 'Request all configuration.') do |opt| - @generateall = opt -end -opts.on('--dry-run', '-n', 'Make no changes.') do |opt| - options[:dryrun] = opt -end -opts.on('--damp-run', "Perform a dry run but run 'setup' entries for files.") do |opt| - # Rather than sprinkle checks of two different variables throught the code, if - # we're asked to do a damp run then just set the dry run flag to a unique - # value. Then we can just check for that specific value at the one place where - # the two modes differ: enabling or disabling the execution of 'setup' - # entries. - options[:dryrun] = 'damp' -end -opts.on('--list-files', 'Just list the files that would be configured') do |opt| - options[:listfiles] = opt - # generate all is implied - @generateall = true - # Set :dryrun as a extra measure to make sure we don't change anything - options[:dryrun] = 'listfiles' -end -opts.on('--interactive', 'Prompt for confirmation before each change.') do |opt| - options[:interactive] = opt -end -opts.on('--full-file', 'Display full new file contents instead of a diff.') do |opt| - options[:fullfile] = opt -end -opts.on('--filename-only', 'Display filename of changed files instead of a diff.') do |opt| - options[:filenameonly] = opt -end -opts.on('--disable-force', 'Ignore the disable_etch file. Use with caution.') do |opt| - options[:disableforce] = opt -end -opts.on('--lock-force', 'Force the removal of any existing lockfiles.') do |opt| - options[:lockforce] = opt -end -opts.on('--local DIR', 'Read configuration from local directory, not server.') do |opt| - options[:local] = opt -end -opts.on('--server SERVER', 'Point etch to an alternate server.') do |opt| - options[:server] = opt -end -opts.on('--tag TAG', 'Request a specific repository tag from the server.') do |opt| - options[:tag] = opt -end -opts.on('--key PRIVATE_KEY', 'Use this private key for signing messages to server.') do |opt| - options[:key] = opt -end -opts.on('--test-root TESTDIR', 'For use by the test suite only.') do |opt| - options[:file_system_root] = opt -end -opts.on('--debug', 'Print lots of messages about what etch is doing.') do |opt| - options[:debug] = opt -end -opts.on('--version', 'Show etch client version.') do |opt| - puts Etch::Client::VERSION - exit -end -opts.on_tail('-h', '--help', 'Show this message.') do - puts opts - exit -end - -leftovers = opts.parse(ARGV) -files = [] -commands = [] -leftovers.each do |leftover| - if leftover[0,1] == File::SEPARATOR - files << leftover - else - commands << leftover - end -end - -# Display a usage message if the user did not specify a valid action to perform. -if files.empty? && commands.empty? && !@generateall - puts opts - exit -end - -# -# Do stuff -# - -etchclient = Etch::Client.new(options) -status = etchclient.process_until_done(files, commands) -exit status - Deleted: trunk/client/etch-client.spec =================================================================== --- trunk/client/etch-client.spec 2011-05-04 14:34:24 UTC (rev 277) +++ trunk/client/etch-client.spec 2011-05-04 17:43:47 UTC (rev 278) @@ -1,25 +0,0 @@ -Name: etch-client -Summary: Etch client -Version: %VER% -Release: 1 -Group: Applications/System -License: MIT -buildarch: noarch -Requires: ruby, facter, crontabs -BuildRoot: %{_builddir}/%{name}-buildroot -%description -Etch client - -%files -%defattr(-,root,root) -/usr/sbin/etch -/usr/sbin/etch_to_trunk -/usr/lib/ruby/site_ruby/1.8/etchclient.rb -/usr/lib/ruby/site_ruby/1.8/etch.rb -/usr/lib/ruby/site_ruby/1.8/versiontype.rb -/usr/share/man/man8/etch.8 -/etc/etch.conf -/etc/etch -/usr/sbin/etch_cron_wrapper -/etc/cron.d/etch - Deleted: trunk/client/etch.8 =================================================================== --- trunk/client/etch.8 2011-05-04 14:34:24 UTC (rev 277) +++ trunk/client/etch.8 2011-05-04 17:43:47 UTC (rev 278) @@ -1,229 +0,0 @@ -.TH etch 8 "October 2009" - -.SH NAME - -.B etch -\- Configuration management for Unix systems - -.SH SYNOPSIS - -.B etch -.RB [ --generate-all ] -.RB [ --dry-run | \-n ] -.RB [ --damp-run ] -.RB [ --interactive ] -.RB [ --full-file ] -.RB [ --filename-only ] -.RB [ --disable-force ] -.RB [ --lock-force ] -.RB [ --debug ] -.RB [ --local -.IR DIR ] -.RB [ --server -.IR SERVER ] -.RB [ --tag -.IR TAG ] -.RB [ --test-base -.IR TESTDIR ] -.RB [ --key -.IR PRIVATE_KEY ] -.RB [ --version ] -.RB [ --help | \-h ] -.RI [ "file ..." ] - -.SH DESCRIPTION - -Etch is a tool for managing the configuration of Unix systems. Etch can manage -text or binary files, links and directories. The contents of files can be -supplied from static files or generated on the fly by scripts or templates. -Permissions and ownership as well as any pre or post commands to run when -updating the file are configured in simple XML files. - -.SH OPTIONS -.TP -.B --generate-all -Request that the server generate and send over all available configuration. -Can be used instead of specifying specific files to request. -.TP -.B --dry-run | \-n -.B etch -will not make any changes to the system. Contents of generated config -files are displayed instead of being written to disk. -.TP -.B --damp-run -Perform an almost dry run, except that 'setup' entries for files are run. -Normally all setup/pre/post entries are ignored for a dry run. However, files -with setup entries will generally fail to build properly if the setup entry -hasn't been run. This allows you to preview the full and correct -configuration while making minimal changes to the system. -.TP -.B --interactive -Causes -.B etch -to pause before making each change and prompt the user for -confirmation. -.TP -.B --full-file -Normally -.B etch -will print a diff to show what changes it will make to a file. This will cause -.B etch -to display the full new file contents instead. Useful if the diff is hard to -read for a particular file. -.TP -.B --filename-only -Normally -.B etch -will print a diff to show what changes it will make to a file. This will cause -etch to display only the name of file to be changed. Useful on the initial -run during your system build process or other times when you want less output. -.TP -.B --disable-force -Ignore the disable_etch file. Use with caution. Typically used with ---interactive or --dry-run to evaluate what would happen if etch were -re-enabled. -.TP -.B --lock-force -.B Etch -does per-file internal locking as it runs to prevent problems with -simultaneous instances of the -.B etch -client stepping on each other. -.B Etch -automatically cleans up lockfiles over two hours old on the assumption that -any lockfiles that old were left behind by a previous instance that failed for -some (hopefully transient) reason. In a large environment you don't want to -have to run around manually cleaning up lockfiles every time a full disk or -unavailable package server or other transient failure causes -.B etch -to fail -temporarily. This option forces the removal of any existing lockfiles no -matter how old. Useful if a buggy configuration or local environmental issue -caused -.B etch -to abort and you want to immediately retry. -.TP -.BI --local " DIR" -Read configuration from a local directory rather than requesting it from -a server. -.TP -.BI --server " SERVER" -Point -.B etch -to an alternate server, specified in the form of a URL. -.TP -.BI --tag " TAG" -Request a specific repository tag from the server. Tags are directory paths -relative to /etc/etchserver by default. Thus examples might be -.I trunk -for /etc/etchserver/trunk, or -.I branches/mytestbranch -for /etc/etchserver/branches/mytestbranch. -.TP -.BI --key " PRIVATE_KEY" -Use an alternate SSH private key file for signing messages that are sent to -the server. -.TP -.BI --test-base " TESTDIR" -Use an alternate local working directory instead of /var/etch. Generally only -used for allowing the etch test suite to be run as a non-root user. -.TP -.B --debug -Print lots of messages about what etch is doing. -.TP -.B --version -Show the etch client version and exit. -.TP -.B --help | \-h -Display the etch usage message and exit. - -.SH FILES - -.TP -.B /etc/etch.conf -Optional configuration file for the etch client. The distribution ships with -an example file showing the available settings and their defaults. The file -syntax consists of "name = value" parameters. Lines starting with '#' and -empty lines are interpreted as comments. -.IP -.B server = -The URL for connecting to the server. http:// and https:// are supported. -.IP -.B path = -PATH environment etch should use when executing external commands. -.IP -.B local = -Etch can read configuration from a local directory rather than from a server. -If set this will override the server setting. -.IP -.B key = -SSH host key to use for authentication rather than standard system key. -.IP -.B detailed_results = -Etch can send detailed results back to the server for viewing in the web UI -and/or to a local log file. Value should be SERVER or the full path to a log -file. Setting may be specified multiple times to send logs to multiple -destinations. -.TP -.B /etc/etch/ca.pem -SSL certificate(s) needed to verify the -.B etch -server's identity. If -.B etch -is using a server with an https:// URL and if this file exists then -.B etch -will not proceed if the server's SSL certificate can't be verified against the -certs in this file. -.TP -.B /etc/etch/dhparams -The Diffie-Hellman parameters used as part of the SSL connection process. Etch -comes with a set and there's no need to generate your own, but a new set can -be generated via "openssl dhparam" if desired. If this file is not present the -Ruby SSL library will warn that it is using its internal default set of -parameters. -.TP -.B /var/etch/disable_etch -If this file is present -.B etch -will do nothing other than send a message to the -.B etch -server that it is disabled. Any text in this file will be included in -that message to the server and displayed locally. If you are disabling -.B etch -always put a note in this file indicating who you are, today's date, and why -you are disabling -.B etch -so that fellow administrators won't have to guess later why -.B etch -was disabled. Re-enabling -.B etch -after it has been disabled for a long -time can be time-consuming, as the person doing so must review any potential -changes that have been queued up and ensure that they won't interfere with the -current usage of the system. As such be thoughtful about whether disabling -.B etch -is necessary, and re-enable it as soon as possible. -.TP -.B /var/etch/history -A revision history of each -.B etch -managed file, stored using the RCS revision control system. -.TP -.B /var/etch/locks -Directory used by the -.B etch -internal locking mechanism. See the --lock-force option for more details. -.TP -.B /var/etch/orig -A backup of the original contents of each -.B etch -managed file as it was before etch first touched it. - -.SH DIAGNOSTICS - -See the --debug option and the server logs. - -.SH AUTHOR - -.B Etch -is designed and maintained by Jason Heiss Deleted: trunk/client/etch.conf =================================================================== --- trunk/client/etch.conf 2011-05-04 14:34:24 UTC (rev 277) +++ trunk/client/etch.conf 2011-05-04 17:43:47 UTC (rev 278) @@ -1,25 +0,0 @@ -# The default server url is https://etch -#server = https://etch - -# Etch is usually run from cron, and cron usually executes jobs with a very -# minimal PATH environment variable setting. You may want etch to have a more -# complete PATH setting so that pre and post commands are more readily found. -#path = /bin:/usr/bin:/sbin:/usr/sbin - -# Etch can read configuration from a local directory rather than from a -# server. If set this will override the server setting. -#local = /var/etch/configs - -# Etch will try to find an SSH host key and use it to sign all requests to the -# etch server. Several standard locations for host keys are searched by -# default. If your host key is not in a standard location then you can point -# etch to it. -# See http://sourceforge.net/apps/trac/etch/wiki/ClientAuthentication -#key = /etc/ssh/ssh_host_rsa_key - -# Etch can send detailed results back to the server for viewing in the web UI -# and/or to a local log file. They are sent to the server by default. -# Note that SERVER is ignored when etch is running in local mode. -#detailed_results = SERVER -#detailed_results = /var/etch/results.log - Deleted: trunk/client/etch.spec =================================================================== --- trunk/client/etch.spec 2011-05-04 14:34:24 UTC (rev 277) +++ trunk/client/etch.spec 2011-05-04 17:43:47 UTC (rev 278) @@ -1,44 +0,0 @@ -Name: etch -Version: %VER% -Release: 1%{?dist} -BuildArch: noarch -Summary: A tool for system configuration management -Group: Applications/System -License: MIT -URL: http://etch.sourceforge.net/ -Source0: http://downloads.sourceforge.net/project/etch/etch/%{version}/etch-%{version}.tar.gz -BuildRoot: %{_tmppath}/%{name}-%{version}-%{release}-root-%(%{__id_u} -n) - -BuildRequires: rubygem-rake -Requires: ruby(abi) = 1.8, facter - -# Per http://fedoraproject.org/wiki/Packaging:Ruby -%{!?ruby_sitelib: %global ruby_sitelib %(ruby -rrbconfig -e 'puts Config::CONFIG["sitelibdir"] ')} - -%description -A tool for system configuration management, i.e. management of the -configuration files of the operating system and core applications. Easy for a -professional system administrator to start using, yet scalable to large -and/or complex environments. - -%prep -%setup -q - -%build - -%install -rm -rf %{buildroot} -cd client && rake install[%{buildroot}] - -%clean -rm -rf %{buildroot} - -%files -%defattr(-,root,root,-) -%{_sbindir}/* -%{ruby_sitelib}/* -%{_mandir}/man8/* -%config(noreplace) %{_sysconfdir}/* - -%changelog - Deleted: trunk/client/etch_cron =================================================================== --- trunk/client/etch_cron 2011-05-04 14:34:24 UTC (rev 277) +++ trunk/client/etch_cron 2011-05-04 17:43:47 UTC (rev 278) @@ -1,10 +0,0 @@ -# Run the etch client every hour -# If you want to disable etch updates do NOT comment out this cron job. -# Our next client update will just put it back anyway. -# Instead create /var/etch/disable_etch and add a comment as to -# why this box shouldn't be getting updates. Etch will notice -# that file and abort. disable_etch files with no comment will be -# removed by the System Administration team without warning. -MAILTO="" -0 * * * * root /usr/sbin/etch_cron_wrapper - Deleted: trunk/client/etch_cron_wrapper =================================================================== --- trunk/client/etch_cron_wrapper 2011-05-04 14:34:24 UTC (rev 277) +++ trunk/client/etch_cron_wrapper 2011-05-04 17:43:47 UTC (rev 278) @@ -1,18 +0,0 @@ -#!/usr/bin/ruby -w - -require 'socket' -require 'digest/sha1' - -# Seed the random number generator with the hostname of this box so that -# we get a consistent random number. We want to run the registration at a -# consistent time on each individual box, but randomize the runs across -# the environment. -srand(Digest::SHA1.hexdigest(Socket.gethostname)[0,7].hex) - -# Cron job is set to run every hour -MAX_SLEEP = 60 * 60 - -sleep(rand(MAX_SLEEP)) - -exec('/usr/sbin/etch', '--generate-all') - Deleted: trunk/client/etch_to_trunk =================================================================== --- trunk/client/etch_to_trunk 2011-05-04 14:34:24 UTC (rev 277) +++ trunk/client/etch_to_trunk 2011-05-04 17:43:47 UTC (rev 278) @@ -1,77 +0,0 @@ -#!/usr/bin/ruby -w - -require 'nventory' -require 'time' -require 'optparse' - -ETCH_SERVER_TZ = 'UTC' # The etch servers run in UTC - -options = {} -opts = OptionParser.new -opts.banner = 'Usage: etch_to_trunk [options] <server1> [<server2> <server3>]' -opts.on('-u', '--username USERNAME', 'Username for connecting to nventory server.') do |opt| - options[:username] = opt -end -opts.on('-t', '--timezone TIMEZONE', 'Time zone of etch server.') do |opt| - options[:timezone] = opt -end -opts.on('--nv SERVER', 'Where nVentory server is running.') do |opt| - options[:nv_server] = opt -end -opts.on_tail('-h', '--help', 'Show this message.') do - puts opts - exit -end - -nodes = opts.parse(ARGV) - -if ARGV.length == 0 - puts opts - exit -end - -@username = options[:username] || ENV['LOGNAME'] -etch_server_tz = options[:timezone] || ETCH_SERVER_TZ - -if etch_server_tz - currentheadtag = Time.at(Time.now.utc + Time.zone_offset(etch_server_tz)).strftime('trunk-%Y%m%d-%H00') -else # if no timezone is specified then just use local time for the tag - currentheadtag = Time.now.strftime('trunk-%Y%m%d-%H00') -end - -# Find the requested clients -nv_server = options[:nv_server] -if nv_server - nvclient = NVentory::Client.new(:server=>"http://#{nv_server}") -else - nvclient = NVentory::Client.new -end -results = nvclient.get_objects('nodes', {}, { 'name' => nodes }, {}, {}) -nodes.each do |name| - if results.empty? && results[name].nil? - abort "No entry found for #{name}" - else - if !results[name]['config_mgmt_tag'].nil? && - !results[name]['config_mgmt_tag'].empty? - puts "Changing #{name} from #{results[name]['config_mgmt_tag']} to #{currentheadtag}" - else - puts "Setting #{name} to #{currentheadtag}" - end - end -end - -while true - print "Proceed? [y|n] " - response = $stdin.gets.chomp - if response == 'y' - break - elsif response == 'n' - exit - end -end - -# Update the clients -successcount = nvclient.set_objects('nodes', results, {'config_mgmt_tag' => currentheadtag}, @username) - -puts "#{File.basename($0)} operation succeeded for #{successcount} of #{results.size} nodes" - Deleted: trunk/client/etchclient.rb =================================================================== --- trunk/client/etchclient.rb 2011-05-04 14:34:24 UTC (rev 277) +++ trunk/client/etchclient.rb 2011-05-04 17:43:47 UTC (rev 278) @@ -1,2565 +0,0 @@ -############################################################################## -# Etch configuration file management tool library -############################################################################## - -# Ensure we can find etch.rb if run within the development directory structure -# This is roughly equivalent to "../server/lib" -serverlibdir = File.join(File.dirname(File.dirname(File.expand_path(__FILE__))), 'server', 'lib') -if File.exist?(serverlibdir) - $:.unshift(serverlibdir) -end - -begin - # Try loading facter w/o gems first so that we don't introduce a - # dependency on gems if it is not needed. - require 'facter' # Facter -rescue LoadError - require 'rubygems' - require 'facter' -end -require 'find' -require 'digest/sha1' # hexdigest -require 'openssl' # OpenSSL -require 'base64' # decode64, encode64 -require 'uri' -require 'net/http' -require 'net/https' -require 'rexml/document' -require 'fileutils' # copy, mkpath, rmtree -require 'fcntl' # Fcntl::O_* -require 'etc' # getpwnam, getgrnam -require 'tempfile' # Tempfile -require 'find' # Find.find -require 'cgi' -require 'timeout' -require 'logger' -require 'etch' - -class Etch::Client - VERSION = 'unset' - - CONFIRM_PROCEED = 1 - CONFIRM_SKIP = 2 - CONFIRM_QUIT = 3 - PRIVATE_KEY_PATHS = ["/etc/ssh/ssh_host_rsa_key", "/etc/ssh_host_rsa_key"] - DEFAULT_CONFIGDIR = '/etc' - DEFAULT_VARBASE = '/var/etch' - DEFAULT_DETAILED_RESULTS = ['SERVER'] - - # We need these in relation to the output capturing - ORIG_STDOUT = STDOUT.dup - ORIG_STDERR = STDERR.dup - - attr_reader :exec_once_per_run - - def initialize(options) - @server = options[:server] ? options[:server] : 'https://etch' - @tag = options[:tag] - @local = options[:local] ? File.expand_path(options[:local]) : nil - @debug = options[:debug] - @dryrun = options[:dryrun] - @listfiles = options[:listfiles] - @interactive = options[:interactive] - @filenameonly = options[:filenameonly] - @fullfile = options[:fullfile] - @key = options[:key] ? options[:key] : get_private_key_path - @disableforce = options[:disableforce] - @lockforce = options[:lockforce] - - @last_response = "" - - @configdir = DEFAULT_CONFIGDIR - @varbase = DEFAULT_VARBASE - - @file_system_root = '/' # Not sure if this needs to be more portable - # This option is only intended for use by the test suite - if options[:file_system_root] - @file_system_root = options[:file_system_root] - @varbase = File.join(@file_system_root, @varbase) - @configdir = File.join(@file_system_root, @configdir) - end - - @configfile = File.join(@configdir, 'etch.conf') - @detailed_results = [] - - if File.exist?(@configfile) - IO.foreach(@configfile) do |line| - line.chomp! - next if (line =~ /^\s*$/); # Skip blank lines - next if (line =~ /^\s*#/); # Skip comments - line.strip! # Remove leading/trailing whitespace - key, value = line.split(/\s*=\s*/, 2) - if key == 'server' - # A setting for the server to use which comes from upstream - # (generally from a command line option) takes precedence - # over the config file - if !options[:server] - @server = value - # Warn the user, as this could potentially be confusing - # if they don't realize there's a config file lying - # around - warn "Using server #{@server} from #{@configfile}" if @debug - else - # "command line override" isn't necessarily accurate, we don't - # know why the caller passed us an option to override the config - # file, but most of the time it will be due to a command line - # option and I want the message to be easily understood by users. - # If someone can come up with some better wording without turning - # the message into something as long as this comment that would be - # welcome. - warn "Ignoring 'server' option in #{@configfile} due to command line override" if @debug - end - elsif key == 'local' - if !options[:local] && !options[:server] - @local = value - warn "Using local directory #{@local} from #{@configfile}" if @debug - else - warn "Ignoring 'local' option in #{@configfile} due to command line override" if @debug - end - elsif key == 'key' - if !options[:key] - @key = value - warn "Using key #{@key} from #{@configfile}" if @debug - else - warn "Ignoring 'key' option in #{@configfile} due to command line override" if @debug - end - elsif key == 'path' - ENV['PATH'] = value - elsif key == 'detailed_results' - warn "Adding detailed results destination '#{value}'" if @debug - @detailed_results << value - end - end - end - - if @key && !File.readable?(@key) - @key = nil - end - if !@key - warn "No readable private key found, messages to server will not be signed and may be rejected depending on server configuration" - end - - if @detailed_results.empty? - @detailed_results = DEFAULT_DETAILED_RESULTS - end - - @origbase = File.join(@varbase, 'orig') - @historybase = File.join(@varbase, 'history') - @lockbase = File.join(@varbase, 'locks') - @requestbase = File.join(@varbase, 'requests') - - @facts = Facter.to_hash - if @facts['operatingsystemrelease'] - # Some versions of Facter have a bug that leaves extraneous - # whitespace on this fact. Work around that with strip. I.e. on - # CentOS you'll get '5 ' or '5.2 '. - @facts['operatingsystemrelease'].strip! - end - - if @local - logger = Logger.new(STDOUT) - dlogger = Logger.new(STDOUT) - if @debug - dlogger.level = Logger::DEBUG - else - dlogger.level = Logger::INFO - end - @etch = Etch.new(logger, dlogger) - else - # Make sure the server URL ends in a / so that we can append paths - # to it using URI.join - if @server !~ %r{/$} - @server << '/' - end - @filesuri = URI.join(@server, 'files') - @resultsuri = URI.join(@server, 'results') - - @blankrequest = {} - # If the user specified a non-standard key then override the - # sshrsakey fact so that authentication works - if @key - @facts['sshrsakey'] = IO.read(@key+'.pub').chomp.split[1] - end - @facts.each_pair { |key, value| @blankrequest["facts[#{key}]"] = value.to_s } - @blankrequest['fqdn'] = @facts['fqdn'] - if @debug - @blankrequest['debug'] = '1' - end - if @tag - @blankrequest['tag'] = @tag - end - end - - @locked_files = {} - @first_update = {} - @already_processed = {} - @exec_already_processed = {} - @exec_once_per_run = {} - @results = [] - # See start/stop_output_capture for these - @output_pipes = [] - - @lchown_supported = nil - @lchmod_supported = nil - end - - def process_until_done(files, commands) - # Our overall status. Will be reported to the server and used as the - # return value for this method. Command-line clients should use it as - # their exit value. Zero indicates no errors. - status = 0 - message = '' - - # A variable to collect filenames if operating in @listfiles mode - files_to_list = {} - - # Prep http instance - http = nil - if !@local - http = Net::HTTP.new(@filesuri.host, @filesuri.port) - if @filesuri.scheme == "https" - # Eliminate the OpenSSL "using default DH parameters" warning - if File.exist?(File.join(@configdir, 'etch', 'dhparams')) - dh = OpenSSL::PKey::DH.new(IO.read(File.join(@configdir, 'etch', 'dhparams'))) - Net::HTTP.ssl_context_accessor(:tmp_dh_callback) - http.tmp_dh_callback = proc { dh } - end - http.use_ssl = true - if File.exist?(File.join(@configdir, 'etch', 'ca.pem')) - http.ca_file = File.join(@configdir, 'etch', 'ca.pem') - http.verify_mode = OpenSSL::SSL::VERIFY_PEER - elsif File.directory?(File.join(@configdir, 'etch', 'ca')) - http.ca_path = File.join(@configdir, 'etch', 'ca') - http.verify_mode = OpenSSL::SSL::VERIFY_PEER - end - end - http.start - end - - # catch/throw for expected/non-error events that end processing - # begin/raise for error events that end processing - catch :stop_processing do - begin - enabled, message = check_for_disable_etch_file - if !enabled - # 200 is the arbitrarily picked exit value indicating - # that etch is disabled - status = 200 - throw :stop_processing - end - remove_stale_lock_files - - # Assemble the initial request - request = nil - if @local - request = {} - if files && !files.empty? - request[:files] = {} - files.each do |file| - request[:files][file] = {:orig => save_orig(file)} - local_requests = get_local_requests(file) - if local_requests - request[:files][file][:local_requests] = local_requests - end - end - end - if commands && !commands.empty? - request[:commands] = {} - commands.each do |command| - request[:commands][command] = {} - end - end - else - request = get_blank_request - if (files && !files.empty?) || (commands && !commands.empty?) - if files - files.each do |file| - request["files[#{CGI.escape(file)}][sha1sum]"] = - get_orig_sum(file) - local_requests = get_local_requests(file) - if local_requests - request["files[#{CGI.escape(file)}][local_requests]"] = - local_requests - end - end - end - if commands - commands.each do |command| - request["commands[#{CGI.escape(command)}]"] = '1' - end - end - else - request['files[GENERATEALL]'] = '1' - end - end - - # - # Loop back and forth with the server sending requests for files and - # responding to the server's requests for original contents or sums - # it needs - # - - Signal.trap('EXIT') do - STDOUT.reopen(ORIG_STDOUT) - STDERR.reopen(ORIG_STDERR) - unlock_all_files - end - - # It usually takes a few back and forth exchanges with the server to - # exchange all needed data and get a complete set of configuration. - # The number of iterations is capped at 10 to prevent any unplanned - # infinite loops. The limit of 10 was chosen somewhat arbitrarily but - # seems fine in practice. - 10.times do - # - # Send request to server - # - - responsedata = {} - if @local - results = @etch.generate(@local, @facts, request) - # FIXME: Etch#generate returns parsed XML using whatever XML - # library it happens to use. In order to avoid re-parsing - # the XML we'd have to use the XML abstraction code from Etch - # everwhere here. - # Until then re-parse the XML using REXML. - #responsedata[:configs] = results[:configs] - responsedata[:configs] = {} - results[:configs].each {|f,c| responsedata[:configs][f] = REXML::Document.new(c.to_s) } - responsedata[:need_sums] = {} - responsedata[:need_origs] = results[:need_orig] - #responsedata[:allcommands] = results[:allcommands] - responsedata[:allcommands] = {} - results[:allcommands].each {|cn,c| responsedata[:allcommands][cn] = REXML::Document.new(c.to_s) } - responsedata[:retrycommands] = results[:retrycommands] - else - puts "Sending request to server #{@filesuri}: #{request.inspect}" if (@debug) - post = Net::HTTP::Post.new(@filesuri.path) - post.set_form_data(request) - sign_post!(post, @key) - response = http.request(post) - if !response.kind_of?(Net::HTTPSuccess) - $stderr.puts response.body - # error! raises an exception - response.error! - end - puts "Response from server:\n'#{response.body}'" if (@debug) - if !response.body.nil? && !response.body.empty? - response_xml = REXML::Document.new(response.body) - responsedata[:configs] = {} - response_xml.elements.each('/files/configs/config') do |config| - file = config.attributes['filename'] - # We have to make a new document so that XPath paths are - # referenced relative to the configuration for this - # specific file. - #responsedata[:configs][file] = REXML::Document.new(response_xml.elements["/files/configs/config[@filename='#{file}']"].to_s) - responsedata[:configs][file] = REXML::Document.new(config.to_s) - end - responsedata[:need_sums] = {} - response_xml.elements.each('/files/need_sums/need_sum') do |ns| - responsedata[:need_sums][ns.text] = true - end - responsedata[:need_origs] = {} - response_xml.elements.each('/files/need_origs/need_orig') do |no| - responsedata[:need_origs][no.text] = true - end - responsedata[:allcommands] = {} - response_xml.elements.each('/files/allcommands/commands') do |command| - commandname = command.attributes['commandname'] - # We have to make a new document so that XPath paths are - # referenced relative to the configuration for this - # specific file. - #responsedata[:allcommands][commandname] = REXML::Document.new(response_xml.root.elements["/files/allcommands/commands[@commandname='#{commandname}']"].to_s) - responsedata[:allcommands][commandname] = REXML::Document.new(command.to_s) - end - responsedata[:retrycommands] = {} - response_xml.elements.each('/files/retrycommands/retrycommand') do |rc| - responsedata[:retrycommands][rc.text] = true - end - else - puts " Response is empty" if (@debug) - break - end - end - - # - # Process the response from the server - # - - # Prep a clean request hash - if @local - request = {} - if !responsedata[:need_origs].empty? - request[:files] = {} - end - if !responsedata[:retrycommands].empty? - request[:commands] = {} - end - else - request = get_blank_request - end - - # With generateall we expect to make at least two round trips - # to the server. - # 1) Send GENERATEALL request, get back a list of need_sums - # 2) Send sums, possibly get back some need_origs - # 3) Send origs, get back generated files - need_to_loop = false - reset_already_processed - # Process configs first, as they may contain setup entries that are - # needed to create the original files. - responsedata[:configs].each_key do |file| - puts "Processing config for #{file}" if (@debug) - if !@listfiles - continue_processing = process_file(file, responsedata) - if !continue_processing - throw :stop_processing - end - else - files_to_list[file] = true - end - end - responsedata[:need_sums].each_key do |need_sum| - puts "Processing request for sum of #{need_sum}" if (@debug) - if @local - # If this happens we screwed something up, the local mode - # code never requests sums. - raise "No support for sums in local mode" - else - request["files[#{CGI.escape(need_sum)}][sha1sum]"] = - get_orig_sum(need_sum) - end - local_requests = get_local_requests(need_sum) - if local_requests - if @local - request[:files][need_sum][:local_requests] ... [truncated message content] |
From: <jh...@us...> - 2011-06-01 01:04:27
|
Revision: 289 http://etch.svn.sourceforge.net/etch/?rev=289&view=rev Author: jheiss Date: 2011-06-01 01:04:21 +0000 (Wed, 01 Jun 2011) Log Message: ----------- Change varbase to vardir, to match configdir. Having configdir and varbase seemed odd in retrospect. Make configdir and vardir configurable via command-line options. Suggestion from Nate Johnston. Add additional debugging statement about the server URL in use. Suggestion from Nate Johnston. Modified Paths: -------------- trunk/client/bin/etch trunk/client/lib/etch/client.rb Modified: trunk/client/bin/etch =================================================================== --- trunk/client/bin/etch 2011-05-19 17:55:25 UTC (rev 288) +++ trunk/client/bin/etch 2011-06-01 01:04:21 UTC (rev 289) @@ -69,6 +69,12 @@ opts.on('--key PRIVATE_KEY', 'Use this private key for signing messages to server.') do |opt| options[:key] = opt end +opts.on('--configdir DIR', 'Directory containing etch.conf.') do |opt| + options[:configdir] = opt +end +opts.on('--vardir DIR', 'Directory for etch state and logs.') do |opt| + options[:vardir] = opt +end opts.on('--test-root TESTDIR', 'For use by the test suite only.') do |opt| options[:file_system_root] = opt end Modified: trunk/client/lib/etch/client.rb =================================================================== --- trunk/client/lib/etch/client.rb 2011-05-19 17:55:25 UTC (rev 288) +++ trunk/client/lib/etch/client.rb 2011-06-01 01:04:21 UTC (rev 289) @@ -49,7 +49,7 @@ CONFIRM_QUIT = 3 PRIVATE_KEY_PATHS = ["/etc/ssh/ssh_host_rsa_key", "/etc/ssh_host_rsa_key"] DEFAULT_CONFIGDIR = '/etc' - DEFAULT_VARBASE = '/var/etch' + DEFAULT_VARDIR = '/var/etch' DEFAULT_DETAILED_RESULTS = ['SERVER'] # We need these in relation to the output capturing @@ -60,6 +60,8 @@ def initialize(options) @server = options[:server] ? options[:server] : 'https://etch' + @configdir = options[:configdir] ? options[:configdir] : DEFAULT_CONFIGDIR + @vardir = options[:vardir] ? options[:vardir] : DEFAULT_VARDIR @tag = options[:tag] @local = options[:local] ? File.expand_path(options[:local]) : nil @debug = options[:debug] @@ -71,17 +73,14 @@ @key = options[:key] ? options[:key] : get_private_key_path @disableforce = options[:disableforce] @lockforce = options[:lockforce] - + @last_response = "" - @configdir = DEFAULT_CONFIGDIR - @varbase = DEFAULT_VARBASE - @file_system_root = '/' # Not sure if this needs to be more portable # This option is only intended for use by the test suite if options[:file_system_root] @file_system_root = options[:file_system_root] - @varbase = File.join(@file_system_root, @varbase) + @vardir = File.join(@file_system_root, @vardir) @configdir = File.join(@file_system_root, @configdir) end @@ -149,10 +148,10 @@ @detailed_results = DEFAULT_DETAILED_RESULTS end - @origbase = File.join(@varbase, 'orig') - @historybase = File.join(@varbase, 'history') - @lockbase = File.join(@varbase, 'locks') - @requestbase = File.join(@varbase, 'requests') + @origbase = File.join(@vardir, 'orig') + @historybase = File.join(@vardir, 'history') + @lockbase = File.join(@vardir, 'locks') + @requestbase = File.join(@vardir, 'requests') @facts = Facter.to_hash if @facts['operatingsystemrelease'] @@ -222,6 +221,7 @@ # Prep http instance http = nil if !@local + puts "Connecting to #{@filesuri}" if (@debug) http = Net::HTTP.new(@filesuri.host, @filesuri.port) if @filesuri.scheme == "https" # Eliminate the OpenSSL "using default DH parameters" warning @@ -572,7 +572,7 @@ end def check_for_disable_etch_file - disable_etch = File.join(@varbase, 'disable_etch') + disable_etch = File.join(@vardir, 'disable_etch') message = '' if File.exist?(disable_etch) if !@disableforce This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <jh...@us...> - 2012-03-19 14:39:06
|
Revision: 309 http://etch.svn.sourceforge.net/etch/?rev=309&view=rev Author: jheiss Date: 2012-03-19 14:38:56 +0000 (Mon, 19 Mar 2012) Log Message: ----------- Update macports template to latest macports standards. Fix a bug in the Rakefile related to client directory structure changes. Modified Paths: -------------- trunk/client/Rakefile trunk/client/packages/macports/Portfile.template Modified: trunk/client/Rakefile =================================================================== --- trunk/client/Rakefile 2012-03-19 11:58:44 UTC (rev 308) +++ trunk/client/Rakefile 2012-03-19 14:38:56 UTC (rev 309) @@ -53,7 +53,7 @@ # Substitute ETCHVER into etch/client.rb # Substitute proper path into CONFIGDIR in etch/client.rb if appropriate File.open(File.join(libdir, 'etch', 'client.rb'), 'w') do |newfile| - IO.foreach(File.join('etch', 'client.rb')) do |line| + IO.foreach(File.join('lib', 'etch', 'client.rb')) do |line| if line =~ /^\s*VERSION/ line.sub!(/=.*/, "= '#{ETCHVER}'") end @@ -390,6 +390,7 @@ md5 = `openssl md5 #{TARBALL}`.chomp.split.last sha1 = `openssl sha1 #{TARBALL}`.chomp.split.last rmd160 = `openssl rmd160 #{TARBALL}`.chomp.split.last + sha256 = `openssl sha256 #{TARBALL}`.chomp.split.last portfile = File.join(Dir.tmpdir, 'Portfile') rm_f(portfile) @@ -399,6 +400,7 @@ line.sub!('%MD5%', md5) line.sub!('%SHA1%', sha1) line.sub!('%RMD160%', rmd160) + line.sub!('%SHA256%', sha256) newfile.puts(line) end end Modified: trunk/client/packages/macports/Portfile.template =================================================================== --- trunk/client/packages/macports/Portfile.template 2012-03-19 11:58:44 UTC (rev 308) +++ trunk/client/packages/macports/Portfile.template 2012-03-19 14:38:56 UTC (rev 309) @@ -9,6 +9,7 @@ categories sysutils maintainers aput.net:jheiss openmaintainer supported_archs noarch +license MIT description Etch is a system configuration management tool. @@ -24,17 +25,15 @@ homepage http://etch.sourceforge.net/ platforms darwin -master_sites sourceforge +master_sites sourceforge:project/etch/etch/${version} -checksums md5 %MD5% \ - sha1 %SHA1% \ - rmd160 %RMD160% +checksums rmd160 %RMD160% \ + sha256 %SHA256% depends_build port:rb-rake depends_run port:facter worksrcdir ${worksrcdir}/client -supported_archs noarch use_configure no build {} destroot.cmd ${prefix}/bin/rake This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <jh...@us...> - 2012-04-26 23:34:15
|
Revision: 323 http://etch.svn.sourceforge.net/etch/?rev=323&view=rev Author: jheiss Date: 2012-04-26 23:34:09 +0000 (Thu, 26 Apr 2012) Log Message: ----------- Update now that this is client-specific Modified Paths: -------------- trunk/client/Gemfile trunk/client/Gemfile.lock Modified: trunk/client/Gemfile =================================================================== --- trunk/client/Gemfile 2012-04-26 23:32:47 UTC (rev 322) +++ trunk/client/Gemfile 2012-04-26 23:34:09 UTC (rev 323) @@ -1,7 +1,2 @@ source :rubygems gem 'facter' -gem 'nokogiri' -# Tests will be run with nokogiri by default, but it might be nice to have -# libxml available too if you want to test with it as well. -gem 'libxml-ruby' - Modified: trunk/client/Gemfile.lock =================================================================== --- trunk/client/Gemfile.lock 2012-04-26 23:32:47 UTC (rev 322) +++ trunk/client/Gemfile.lock 2012-04-26 23:34:09 UTC (rev 323) @@ -2,13 +2,9 @@ remote: http://rubygems.org/ specs: facter (1.6.5) - libxml-ruby (2.2.2) - nokogiri (1.5.0) PLATFORMS ruby DEPENDENCIES facter - libxml-ruby - nokogiri This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |