require 'open-uri' require 'socket' require 'yaml' require 'rest-client' require 'lib/ext' class Runpuppet def self.with_lock(lock_file) recently_locked = (File.exists?(lock_file) and File.mtime(lock_file) > Time.now - 15*60) if recently_locked puts "can not run, lockfile #{lock_file} exists" else begin `touch #{lock_file}` yield ensure `rm #{lock_file}` end end end # simplified copy of rake`s sh def self.sh(cmd) puts cmd IO.popen(cmd) do |pipe| while str = pipe.gets puts str end end $?.success? end def self.get(path) path += (path.include?('?') ? '&' : '?') path += "hostname=#{Socket.gethostname}&ip=#{Config.local_ip}" begin open(Config.puppet_controller_url + path, {:http_basic_authentication =>Config.puppet_controller_auth} ) rescue Exception => e puts e.inspect puts "WARNING: error connecting to puppet controller!" end end def self.post(path, params) params[:hostname] = Socket.gethostname params[:ip] = Config.local_ip begin RestClient.post "#{Config.puppet_controller_url}/puppet/#{path}", params rescue Exception => e puts e.inspect puts "WARNING: error connecting to puppet controller!" end end def self.run(options={}) with_lock(Config.lock_file) do time = Time.now.utc.strftime("%Y-%m-%d %H:%M:%S") todo, branch = get("/puppet/run").read.split('-') rescue [] if todo == 'run' or !options[:try] # try allows not running get '/puppet/status?status=started' branch ||= Config.default_branch cmd = Config.command.gsub('@@branch@@', branch) puts "#{time}: run #{branch}" if sh(cmd) get '/puppet/status?status=finished' else get '/puppet/status?status=error' exit 2 end else puts "#{time}: nothing to do" end end end def self.report_facts(options={}) require 'facter/application' facts = Facter::Application.run([]) post('facts', :facts => facts.to_hash) end class Config def self.config home = File.expand_path('~') ["#{home}/.runpuppet.yml", '/etc/runpuppet.yml'].each do |file| return YAML.load(File.read(file)) if File.exist?(file) end raise "No runpuppet.yml found in /etc or #{home}" end def self.puppet_controller_url config['puppet_controller_url'].sub(%r{/$},'') end def self.puppet_controller_auth extract_auth_from_url!(config['puppet_controller_url']) end def self.extract_auth_from_url!(url) url.sub!(%r{//(.*?):(.*?)@}, '//') auth = [$1, $2].compact auth.empty? ? nil : auth end def self.lock_file config['lock_file'] || '/tmp/runpuppet.lock' end def self.command config['command'] || "cd /etc/puppet/repo && git fetch && git checkout -f origin/@@branch@@ && puppet -v --debug --logdest console --modulepath /etc/puppet/repo/modules /etc/puppet/repo/manifests/site.pp" end def self.default_branch config['defaulf_branch'] || 'master' end def self.local_ip if is_ec2? require 'facter' require 'facter/ec2' ip = Facter.value("ec2_public_ipv4") else %x(ifconfig)[/192.168.\d+.\d+/] || config['local_ip'] end end def self.is_ec2? %x(arp -n -i eth0) =~ /fe:ff:ff:ff:ff/ end end end