Class: Bolt::BoltOptionParser

Inherits:
OptionParser
  • Object
show all
Defined in:
lib/bolt/bolt_option_parser.rb

Defined Under Namespace

Modules: SwitchHider

Constant Summary collapse

<<-HELP
Usage: bolt <subcommand> <action> [options]

Available subcommands:
  bolt command run <command>       Run a command remotely
  bolt file upload <src> <dest>    Upload a local file
  bolt script run <script>         Upload a local script and run it remotely
  bolt task show                   Show list of available tasks
  bolt task show <task>            Show documentation for task
  bolt task run <task> [params]    Run a Puppet task
  bolt plan show                   Show list of available plans
  bolt plan show <plan>            Show details for plan
  bolt plan run <plan> [params]    Run a Puppet task plan
  bolt apply <manifest>            Apply Puppet manifest code
  bolt puppetfile install          Install modules from a Puppetfile into a Boltdir
  bolt puppetfile show-modules     List modules available to Bolt

Run `bolt <subcommand> --help` to view specific examples.

where [options] are:
HELP
TASK_HELP =
<<-HELP
Usage: bolt task <action> <task> [options] [parameters]

Available actions are:
  show                             Show list of available tasks
  show <task>                      Show documentation for task
  run                              Run a Puppet task

Parameters are of the form <parameter>=<value>.

#{examples('task run facts', 'run facter on')}
Available options are:
HELP
COMMAND_HELP =
<<-HELP
Usage: bolt command <action> <command> [options]

Available actions are:
  run                              Run a command remotely

#{examples('command run hostname', 'run hostname on')}
Available options are:
HELP
SCRIPT_HELP =
<<-HELP
Usage: bolt script <action> <script> [[arg1] ... [argN]] [options]

Available actions are:
  run                              Upload a local script and run it remotely

#{examples('script run my_script.ps1 some args', 'run a script on')}
Available options are:
HELP
PLAN_HELP =
<<-HELP
Usage: bolt plan <action> <plan> [options] [parameters]

Available actions are:
  show                             Show list of available plans
  show <plan>                      Show details for plan
  run                              Run a Puppet task plan

Parameters are of the form <parameter>=<value>.

#{examples('plan run canary command=hostname', 'run the canary plan on')}
Available options are:
HELP
FILE_HELP =
<<-HELP
Usage: bolt file <action> [options]

Available actions are:
  upload <src> <dest>              Upload local file <src> to <dest> on each node

#{examples('file upload /tmp/source /etc/profile.d/login.sh', 'upload a file to')}
Available options are:
HELP
PUPPETFILE_HELP =
<<-HELP
Usage: bolt puppetfile <action> [options]

Available actions are:
  install                          Install modules from a Puppetfile into a Boltdir
  show-modules                     List modules available to Bolt

Install modules into the local Boltdir
  bolt puppetfile install

Available options are:
HELP
APPLY_HELP =
<<-HELP
Usage: bolt apply <manifest.pp> [options]

#{examples('apply site.pp', 'apply a manifest on')}
  bolt apply site.pp --nodes foo.example.com,bar.example.com
HELP

Class Method Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(options) ⇒ BoltOptionParser

Returns a new instance of BoltOptionParser.



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
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
# File 'lib/bolt/bolt_option_parser.rb', line 132

def initialize(options)
  super()

  @options = options

  @nodes = define('-n', '--nodes NODES',
                  'Identifies the nodes to target.',
                  'Enter a comma-separated list of node URIs or group names.',
                  "Or read a node list from an input file '@<file>' or stdin '-'.",
                  'Example: --nodes localhost,node_group,ssh://nix.com:23,winrm://windows.puppet.com',
                  'URI format is [protocol://]host[:port]',
                  "SSH is the default protocol; may be #{TRANSPORTS.keys.join(', ')}",
                  'For Windows nodes, specify the winrm:// protocol if it has not be configured',
                  'For SSH, port defaults to `22`',
                  'For WinRM, port defaults to `5985` or `5986` based on the --[no-]ssl setting') do |nodes|
    @options[:nodes] << get_arg_input(nodes)
  end.extend(SwitchHider)
  @query = define('-q', '--query QUERY', 'Query PuppetDB to determine the targets') do |query|
    @options[:query] = query
  end.extend(SwitchHider)
  define('--noop', 'Execute a task that supports it in noop mode') do |_|
    @options[:noop] = true
  end
  define('--description DESCRIPTION',
         'Description to use for the job') do |description|
    @options[:description] = description
  end
  define('--params PARAMETERS',
         "Parameters to a task or plan as json, a json file '@<file>', or on stdin '-'") do |params|
    @options[:task_options] = parse_params(params)
  end
  @execute = define('-e', '--execute CODE',
                    "Puppet manifest code to apply to the targets") do |code|
    @options[:code] = code
  end.extend(SwitchHider)

  separator 'Authentication:'
  define('-u', '--user USER', 'User to authenticate as') do |user|
    @options[:user] = user
  end
  define('-p', '--password [PASSWORD]',
         'Password to authenticate with. Omit the value to prompt for the password.') do |password|
    if password.nil?
      STDOUT.print "Please enter your password: "
      @options[:password] = STDIN.noecho(&:gets).chomp
      STDOUT.puts
    else
      @options[:password] = password
    end
  end
  define('--private-key KEY', 'Private ssh key to authenticate with') do |key|
    @options[:'private-key'] = key
  end
  define('--[no-]host-key-check', 'Check host keys with SSH') do |host_key_check|
    @options[:'host-key-check'] = host_key_check
  end
  define('--[no-]ssl', 'Use SSL with WinRM') do |ssl|
    @options[:ssl] = ssl
  end
  define('--[no-]ssl-verify', 'Verify remote host SSL certificate with WinRM') do |ssl_verify|
    @options[:'ssl-verify'] = ssl_verify
  end

  separator 'Escalation:'
  define('--run-as USER', 'User to run as using privilege escalation') do |user|
    @options[:'run-as'] = user
  end
  define('--sudo-password [PASSWORD]',
         'Password for privilege escalation. Omit the value to prompt for the password.') do |password|
    if password.nil?
      STDOUT.print "Please enter your privilege escalation password: "
      @options[:'sudo-password'] = STDIN.noecho(&:gets).chomp
      STDOUT.puts
    else
      @options[:'sudo-password'] = password
    end
  end

  separator 'Run context:'
  define('-c', '--concurrency CONCURRENCY', Integer,
         'Maximum number of simultaneous connections (default: 100)') do |concurrency|
    @options[:concurrency] = concurrency
  end
  define('--compile-concurrency CONCURRENCY', Integer,
         'Maximum number of simultaneous manifest block compiles (default: number of cores)') do |concurrency|
    @options[:'compile-concurrency'] = concurrency
  end
  define('-m', '--modulepath MODULES',
         "List of directories containing modules, separated by '#{File::PATH_SEPARATOR}'") do |modulepath|
    # When specified from the CLI, modulepath entries are relative to pwd
    @options[:modulepath] = modulepath.split(File::PATH_SEPARATOR).map do |moduledir|
      File.expand_path(moduledir)
    end
  end
  define('--boltdir FILEPATH',
         'Specify what Boltdir to load config from (default: autodiscovered from current working dir)') do |path|
    @options[:boltdir] = path
  end
  define('--configfile FILEPATH',
         'Specify where to load config from (default: ~/.puppetlabs/bolt/bolt.yaml)') do |path|
    @options[:configfile] = path
  end
  define('-i', '--inventoryfile FILEPATH',
         'Specify where to load inventory from (default: ~/.puppetlabs/bolt/inventory.yaml)') do |path|
    if ENV.include?(Bolt::Inventory::ENVIRONMENT_VAR)
      raise Bolt::CLIError, "Cannot pass inventory file when #{Bolt::Inventory::ENVIRONMENT_VAR} is set"
    end
    @options[:inventoryfile] = File.expand_path(path)
  end

  separator 'Transports:'
  define('--transport TRANSPORT', TRANSPORTS.keys.map(&:to_s),
         "Specify a default transport: #{TRANSPORTS.keys.join(', ')}") do |t|
    @options[:transport] = t
  end
  define('--connect-timeout TIMEOUT', Integer, 'Connection timeout (defaults vary)') do |timeout|
    @options[:'connect-timeout'] = timeout
  end
  define('--[no-]tty', 'Request a pseudo TTY on nodes that support it') do |tty|
    @options[:tty] = tty
  end
  define('--tmpdir DIR', 'The directory to upload and execute temporary files on the target') do |tmpdir|
    @options[:tmpdir] = tmpdir
  end

  separator 'Display:'
  define('--format FORMAT', 'Output format to use: human or json') do |format|
    @options[:format] = format
  end
  define('--[no-]color', 'Whether to show output in color') do |color|
    @options[:color] = color
  end
  define('-h', '--help', 'Display help') do |_|
    @options[:help] = true
  end
  define('-v', '--verbose', 'Display verbose logging') do |_|
    @options[:verbose] = true
  end
  define('--debug', 'Display debug logging') do |_|
    @options[:debug] = true
  end
  define('--trace', 'Display error stack traces') do |_|
    @options[:trace] = true
  end
  define('--version', 'Display the version') do |_|
    puts Bolt::VERSION
    raise Bolt::CLIExit
  end

  update
end

Class Method Details

.examples(cmd, desc) ⇒ Object



9
10
11
12
13
14
15
16
17
18
# File 'lib/bolt/bolt_option_parser.rb', line 9

def self.examples(cmd, desc)
  <<-EXAMP
#{desc} a Windows host via WinRM, providing for the password
  bolt #{cmd} -n winrm://winhost -u Administrator -p
#{desc} the local machine, a Linux host via SSH, and hosts from a group specified in an inventory file
  bolt #{cmd} -n localhost,nixhost,node_group
#{desc} Windows hosts queried from PuppetDB via WinRM as a domain user, prompting for the password
  bolt #{cmd} -q 'inventory[certname] { facts.os.family = "windows" }' --transport winrm -u 'domain\\Administrator' -p
EXAMP
end

Instance Method Details

#get_arg_input(value) ⇒ Object



321
322
323
324
325
326
327
328
329
330
# File 'lib/bolt/bolt_option_parser.rb', line 321

def get_arg_input(value)
  if value.start_with?('@')
    file = value.sub(/^@/, '')
    read_arg_file(file)
  elsif value == '-'
    STDIN.read
  else
    value
  end
end

#parse_params(params) ⇒ Object



314
315
316
317
318
319
# File 'lib/bolt/bolt_option_parser.rb', line 314

def parse_params(params)
  json = get_arg_input(params)
  JSON.parse(json)
rescue JSON::ParserError => err
  raise Bolt::CLIError, "Unable to parse --params value as JSON: #{err}"
end

#read_arg_file(file) ⇒ Object



332
333
334
335
336
# File 'lib/bolt/bolt_option_parser.rb', line 332

def read_arg_file(file)
  File.read(File.expand_path(file))
rescue StandardError => err
  raise Bolt::FileError.new("Error attempting to read #{file}: #{err}", file)
end

#updateObject



284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
# File 'lib/bolt/bolt_option_parser.rb', line 284

def update
  # show the --nodes and --query switches by default
  @nodes.hide = @query.hide = false
  # Don't show the --execute switch except for `apply`
  @execute.hide = true

  # Update the banner according to the subcommand
  self.banner = case @options[:subcommand]
                when 'plan'
                  # don't show the --nodes and --query switches in the plan help
                  @nodes.hide = @query.hide = true
                  PLAN_HELP
                when 'command'
                  COMMAND_HELP
                when 'script'
                  SCRIPT_HELP
                when 'task'
                  TASK_HELP
                when 'file'
                  FILE_HELP
                when 'puppetfile'
                  PUPPETFILE_HELP
                when 'apply'
                  @execute.hide = false
                  APPLY_HELP
                else
                  BANNER
                end
end