#!/usr/bin/env ruby require 'rubygems' require 'taketo' require 'taketo/constructs_factory' require 'taketo/commands' require 'taketo/destination_resolver' require 'optparse' Signal.trap("SIGINT") do puts "Terminating" exit 1 end include Taketo DEFAULT_CONFIG_FILE = File.join(ENV['HOME'], ".taketo.rc.rb") def parse_options options = { :config => DEFAULT_CONFIG_FILE } OptionParser.new do |opts| opts.banner = "Usage: taketo [destination] [options]" opts.version = ::Taketo::VERSION opts.separator "" opts.separator "Common options:" opts.on("-f CONFIG", "--config", "Use custom config file (default: #{DEFAULT_CONFIG_FILE})") do |c| options[:config] = c end opts.on("-c COMMAND", "--command", "Command to execute on destination server", " (COMMAND either declared in config or passed as an argument)") do |c| raise OptionParser::MissingArgument if String(c).strip.empty? options[:command] = c end opts.on("-d DIRECTORY", "--directory", "Directory on destination server to cd to") do |d| raise OptionParser::MissingArgument if String(d).strip.empty? options[:directory] = d end opts.on("-v", "--view", "Show config contents and exit") do |v| require 'taketo/config_printer_visitor' options[:view] = v end opts.on("--generate-ssh-config", "Generate SSH config from taketo config") do |g| require 'taketo/ssh_config_generator_visitor' options[:generate_ssh_config] = g end opts.separator "Special options:" opts.on("--dry-run", "Print out what would be run") do |v| options[:dry_run] = v end opts.on("--debug") do |d| options[:debug] = d end end.parse! options end def parse_config(config) DSL.new.configure(config).tap do |config| traverser = ConfigTraverser.new(config) ConfigValidator.new(traverser).validate! end end def remote_command(server, options) command = options[:command] if String(command).empty? server.default_command else server.find_command(command.to_sym) || Constructs::Command.explicit_command(command) end end def execute(shell_command, options) if options[:dry_run] puts shell_command else system shell_command end end begin options = parse_options config = parse_config(options[:config]) destination_path = ARGV.shift.to_s resolver = DestinationResolver.new(config, destination_path) if options.delete(:view) node = resolver.get_node traverser = ConfigTraverser.new(node) config_printer = ConfigPrinterVisitor.new traverser.visit_depth_first(config_printer) puts config_printer.result elsif options.delete(:generate_ssh_config) traverser = ConfigTraverser.new(config) ssh_config_generator = SSHConfigGeneratorVisitor.new traverser.visit_depth_first(ssh_config_generator) puts ssh_config_generator.result else server = resolver.resolve server_command = remote_command(server, options) command_to_execute = Commands::SSHCommand.new(server).render(server_command.render(server, options)) execute(command_to_execute, options) end rescue SystemExit # Do nothing rescue Exception => e STDERR.puts "An error occurred: #{e.message}" if options && options[:debug] STDERR.puts e.backtrace raise end exit 1 end