|
#!/usr/bin/ruby
|
|
|
|
require "foreman.rb"
|
|
require 'optparse'
|
|
begin
|
|
require 'rubygems'
|
|
require 'net/ssh/multi'
|
|
rescue LoadError => detail
|
|
warn "failed to load ssh_multi libraray - try: gem install net-ssh-multi"
|
|
exit 1
|
|
end
|
|
|
|
options = {}
|
|
optparse = OptionParser.new do |opts|
|
|
# Set a banner, displayed at the top
|
|
# of the help screen.
|
|
opts.define_head "execute commands on mulitple hosts
|
|
Query Foreman to provide host list based on collection of facts and classes"
|
|
opts.banner = "Usage: #{$0}"
|
|
opts.separator ""
|
|
|
|
# Define the options, and what they do
|
|
options[:command] = ""
|
|
opts.on( '-c', '--command CMD', 'command to execute' ) do |cmd|
|
|
options[:command] = cmd
|
|
end
|
|
options[:user] = "root"
|
|
opts.on( '-u', '--user USER', 'User to use - defaults to #{options[:user]}' ) do |user|
|
|
options[:user] = user
|
|
end
|
|
|
|
options[:facts] = {}
|
|
opts.on( '-f', '--facts fact=x,fact=y..', 'one or more facts to filter the host list' ) do |facts|
|
|
facts.gsub(" ","").split(",").each do |f|
|
|
name, value = f.split("=")
|
|
options[:facts].merge!({ name => value })
|
|
end
|
|
end
|
|
|
|
options[:klass] = []
|
|
opts.on( '-p', '--puppetclass CLASSA,CLASSB', 'one or more classes to filter the host list') do |k|
|
|
options[:klass] = k.gsub(" ","").split(",")
|
|
end
|
|
|
|
opts.on( '-h', '--help', 'Display this screen' ) do
|
|
puts opts
|
|
exit
|
|
end
|
|
end
|
|
|
|
optparse.parse!
|
|
|
|
if options[:command].empty? or (options[:facts].empty? and options[:class].empty?)
|
|
puts optparse
|
|
exit 1
|
|
end
|
|
|
|
puts "About to execute: #{options[:command]}"
|
|
query = {}
|
|
query.merge!({"fact" => options[:facts]}) unless options[:facts].empty?
|
|
query.merge!({"class" => options[:klass]}) unless options[:klass].empty?
|
|
p query
|
|
|
|
hosts = gethosts query
|
|
|
|
if hosts.nil?
|
|
warn "unable to find any hosts"
|
|
exit 1
|
|
end
|
|
puts "on the following #{hosts.size} hosts: #{hosts.join(" ")}"
|
|
puts "ctrl-c to abort or any key to continue"
|
|
$stdin.gets
|
|
|
|
ssh_options = {:user => options[:user], :auth_methods => "publickey"}
|
|
|
|
Net::SSH::Multi.start(:on_error => :warn) do |session|
|
|
hosts.each { |s| session.use s, ssh_options }
|
|
session.exec options[:command]
|
|
session.loop
|
|
end
|