Class: SwitchTower::CLI
- Inherits:
-
Object
- Object
- SwitchTower::CLI
- Defined in:
- lib/switchtower/cli.rb
Overview
The CLI class encapsulates the behavior of switchtower when it is invoked as a command-line utility. This allows other programs to embed ST and preserve it’s command-line semantics.
Instance Attribute Summary collapse
-
#args ⇒ Object
readonly
The array of (unparsed) command-line options.
-
#options ⇒ Object
readonly
The hash of (parsed) command-line options.
Class Method Summary collapse
-
.execute! ⇒ Object
Invoke switchtower using the ARGV array as the option parameters.
-
.password_prompt(prompt = "Password: ") ⇒ Object
Prompt for a password using echo suppression.
-
.with_echo ⇒ Object
execute the associated block with echo-suppression enabled.
Instance Method Summary collapse
-
#execute! ⇒ Object
Beginning running SwitchTower based on the configured options.
-
#initialize(args = ARGV) ⇒ CLI
constructor
Create a new CLI instance using the given array of command-line parameters to initialize it.
Constructor Details
#initialize(args = ARGV) ⇒ CLI
Create a new CLI instance using the given array of command-line parameters to initialize it. By default, ARGV
is used, but you can specify a different set of parameters (such as when embedded ST in a program):
require 'switchtower/cli'
SwitchTower::CLI.new(%w(-vvvv -r config/deploy -a update_code)).execute!
Note that you can also embed ST directly by creating a new Configuration instance and setting it up, but you’ll often wind up duplicating logic defined in the CLI class. The above snippet, redone using the Configuration class directly, would look like:
require 'switchtower'
require 'switchtower/cli'
config = SwitchTower::Configuration.new
config.logger_level = SwitchTower::Logger::TRACE
config.set(:password) { SwitchTower::CLI.password_prompt }
config.load "standard", "config/deploy"
config.actor.update_code
There may be times that you want/need the additional control offered by manipulating the Configuration directly, but generally interfacing with the CLI class is recommended.
96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 |
# File 'lib/switchtower/cli.rb', line 96 def initialize(args = ARGV) @args = args @options = { :verbose => 0, :recipes => [], :actions => [], :vars => {}, :pre_vars => {} } OptionParser.new do |opts| opts. = "Usage: #{$0} [options] [args]" opts.separator "" opts.separator "Recipe Options -----------------------" opts.separator "" opts.on("-a", "--action ACTION", "An action to execute. Multiple actions may", "be specified, and are loaded in the given order." ) { |value| @options[:actions] << value } opts.on("-p", "--password [PASSWORD]", "The password to use when connecting. If the switch", "is given without a password, the password will be", "prompted for immediately. (Default: prompt for password", "the first time it is needed.)" ) { |value| @options[:password] = value } opts.on("-r", "--recipe RECIPE", "A recipe file to load. Multiple recipes may", "be specified, and are loaded in the given order." ) { |value| @options[:recipes] << value } opts.on("-s", "--set NAME=VALUE", "Specify a variable and it's value to set. This", "will be set after loading all recipe files." ) do |pair| name, value = pair.split(/=/, 2) @options[:vars][name.to_sym] = value end opts.on("-S", "--set-before NAME=VALUE", "Specify a variable and it's value to set. This", "will be set BEFORE loading all recipe files." ) do |pair| name, value = pair.split(/=/, 2) @options[:pre_vars][name.to_sym] = value end opts.separator "" opts.separator "Framework Integration Options --------" opts.separator "" opts.on("-A", "--apply-to DIRECTORY", "Create a minimal set of scripts and recipes to use", "switchtower with the application at the given", "directory. (Currently only works with Rails apps.)" ) { |value| @options[:apply_to] = value } opts.separator "" opts.separator "Miscellaneous Options ----------------" opts.separator "" opts.on("-h", "--help", "Display this help message") do puts opts exit end opts.on("-P", "--[no-]pretend", "Run the task(s), but don't actually connect to or", "execute anything on the servers. (For various reasons", "this will not necessarily be an accurate depiction", "of the work that will actually be performed.", "Default: don't pretend.)" ) { |value| @options[:pretend] = value } opts.on("-v", "--verbose", "Specify the verbosity of the output.", "May be given multiple times. (Default: silent)" ) { @options[:verbose] += 1 } opts.on("-V", "--version", "Display the version info for this utility" ) do require 'switchtower/version' puts "SwitchTower v#{SwitchTower::Version::STRING}" exit end opts.separator "" opts.separator <<-DETAIL.split(/\n/) You can use the --apply-to switch to generate a minimal set of switchtower scripts and recipes for an application. Just specify the path to the application as the argument to --apply-to, like this: switchtower --apply-to ~/projects/myapp You'll wind up with a sample deployment recipe in config/deploy.rb, some new rake tasks in config/tasks, and a switchtower script in your script directory. (Currently, --apply-to only works with Rails applications.) DETAIL if args.empty? puts opts exit else opts.parse!(args) end end password_proc = Proc.new { self.class.password_prompt } if !@options.has_key?(:password) @options[:password] = password_proc elsif !@options[:password] @options[:password] = password_proc.call end end |
Instance Attribute Details
#args ⇒ Object (readonly)
The array of (unparsed) command-line options
68 69 70 |
# File 'lib/switchtower/cli.rb', line 68 def args @args end |
#options ⇒ Object (readonly)
The hash of (parsed) command-line options
71 72 73 |
# File 'lib/switchtower/cli.rb', line 71 def @options end |
Class Method Details
.execute! ⇒ Object
Invoke switchtower using the ARGV array as the option parameters. This is what the command-line switchtower utility does.
11 12 13 |
# File 'lib/switchtower/cli.rb', line 11 def self.execute! new.execute! end |
.password_prompt(prompt = "Password: ") ⇒ Object
Prompt for a password using echo suppression.
53 54 55 56 57 58 59 60 61 62 63 64 65 |
# File 'lib/switchtower/cli.rb', line 53 def self.password_prompt(prompt="Password: ") sync = STDOUT.sync begin with_echo do STDOUT.sync = true print(prompt) STDIN.gets.chomp end ensure STDOUT.sync = sync puts end end |
.with_echo ⇒ Object
execute the associated block with echo-suppression enabled. Note that if termios is not available, echo suppression will not be available either.
45 46 47 48 49 50 |
# File 'lib/switchtower/cli.rb', line 45 def self.with_echo echo(false) yield ensure echo(true) end |
Instance Method Details
#execute! ⇒ Object
Beginning running SwitchTower based on the configured options.
215 216 217 218 219 220 221 |
# File 'lib/switchtower/cli.rb', line 215 def execute! if !@options[:recipes].empty? execute_recipes! elsif @options[:apply_to] execute_apply_to! end end |