# frozen_string_literal: true # Note this file includes very few 'requires' because it expects to be used from the CLI. require 'optparse' module Bolt class BoltOptionParser < OptionParser PROJECT_PATHS = %w[project].freeze OPTIONS = { inventory: %w[targets query rerun], authentication: %w[user password password-prompt private-key host-key-check ssl ssl-verify], escalation: %w[run-as sudo-password sudo-password-prompt sudo-executable], run_context: %w[concurrency inventoryfile save-rerun cleanup], global_config_setters: PROJECT_PATHS + %w[modulepath], transports: %w[transport connect-timeout tty native-ssh ssh-command copy-command], display: %w[format color verbose trace stream], global: %w[help version log-level clear-cache] }.freeze ACTION_OPTS = OPTIONS.values.flatten.freeze def get_help_text(subcommand, action = nil) case subcommand when 'apply' { flags: ACTION_OPTS + %w[noop execute compile-concurrency hiera-config], banner: APPLY_HELP } when 'command' case action when 'run' { flags: ACTION_OPTS + %w[env-var], banner: COMMAND_RUN_HELP } else { flags: OPTIONS[:global], banner: COMMAND_HELP } end when 'file' case action when 'upload' { flags: ACTION_OPTS + %w[tmpdir], banner: FILE_UPLOAD_HELP } when 'download' { flags: ACTION_OPTS, banner: FILE_DOWNLOAD_HELP } else { flags: OPTIONS[:global], banner: FILE_HELP } end when 'inventory' case action when 'show' { flags: OPTIONS[:inventory] + OPTIONS[:global] + PROJECT_PATHS + %w[format inventoryfile detail], banner: INVENTORY_SHOW_HELP } else { flags: OPTIONS[:global], banner: INVENTORY_HELP } end when 'group' case action when 'show' { flags: OPTIONS[:global] + PROJECT_PATHS + %w[format inventoryfile], banner: GROUP_SHOW_HELP } else { flags: OPTIONS[:global], banner: GROUP_HELP } end when 'guide' { flags: OPTIONS[:global] + %w[format], banner: GUIDE_HELP } when 'lookup' { flags: ACTION_OPTS + %w[hiera-config plan-hierarchy], banner: LOOKUP_HELP } when 'module' case action when 'add' { flags: OPTIONS[:global] + PROJECT_PATHS, banner: MODULE_ADD_HELP } when 'generate-types' { flags: OPTIONS[:global] + OPTIONS[:global_config_setters], banner: MODULE_GENERATETYPES_HELP } when 'install' { flags: OPTIONS[:global] + PROJECT_PATHS + %w[force resolve], banner: MODULE_INSTALL_HELP } when 'show' { flags: OPTIONS[:global] + OPTIONS[:global_config_setters], banner: MODULE_SHOW_HELP } else { flags: OPTIONS[:global], banner: MODULE_HELP } end when 'plan' case action when 'convert' { flags: OPTIONS[:global] + OPTIONS[:global_config_setters], banner: PLAN_CONVERT_HELP } when 'new' { flags: OPTIONS[:global] + PROJECT_PATHS + %w[pp], banner: PLAN_NEW_HELP } when 'run' { flags: ACTION_OPTS + %w[params compile-concurrency tmpdir hiera-config], banner: PLAN_RUN_HELP } when 'show' { flags: OPTIONS[:global] + OPTIONS[:global_config_setters] + %w[filter format], banner: PLAN_SHOW_HELP } else { flags: OPTIONS[:global], banner: PLAN_HELP } end when 'plugin' case action when 'show' { flags: OPTIONS[:global] + %w[color format modulepath project], banner: PLUGIN_SHOW_HELP } else { flags: OPTIONS[:global], banner: PLUGIN_HELP } end when 'policy' case action when 'apply' { flags: ACTION_OPTS + %w[compile-concurrency hiera-config noop], banner: POLICY_APPLY_HELP } when 'new' { flags: OPTIONS[:global] + PROJECT_PATHS, banner: POLICY_NEW_HELP } when 'show' { flags: OPTIONS[:global] + PROJECT_PATHS, banner: POLICY_SHOW_HELP } else { flags: OPTIONS[:global], banner: POLICY_HELP } end when 'project' case action when 'init' { flags: OPTIONS[:global] + %w[modules], banner: PROJECT_INIT_HELP } when 'migrate' { flags: OPTIONS[:global] + PROJECT_PATHS + %w[inventoryfile], banner: PROJECT_MIGRATE_HELP } else { flags: OPTIONS[:global], banner: PROJECT_HELP } end when 'script' case action when 'run' { flags: ACTION_OPTS + %w[tmpdir env-var], banner: SCRIPT_RUN_HELP } else { flags: OPTIONS[:global], banner: SCRIPT_HELP } end when 'secret' case action when 'createkeys' { flags: OPTIONS[:global] + OPTIONS[:global_config_setters] + %w[plugin force], banner: SECRET_CREATEKEYS_HELP } when 'decrypt' { flags: OPTIONS[:global] + OPTIONS[:global_config_setters] + %w[plugin], banner: SECRET_DECRYPT_HELP } when 'encrypt' { flags: OPTIONS[:global] + OPTIONS[:global_config_setters] + %w[plugin], banner: SECRET_ENCRYPT_HELP } else { flags: OPTIONS[:global], banner: SECRET_HELP } end when 'task' case action when 'run' { flags: ACTION_OPTS + %w[params tmpdir noop], banner: TASK_RUN_HELP } when 'show' { flags: OPTIONS[:global] + OPTIONS[:global_config_setters] + %w[filter format], banner: TASK_SHOW_HELP } else { flags: OPTIONS[:global], banner: TASK_HELP } end else { flags: OPTIONS[:global], banner: BANNER } end end COLORS = { cyan: "36" }.freeze def self.colorize(color, string) if $stdout.isatty "\033[#{COLORS[color]}m#{string}\033[0m" else string end end BANNER = <<~HELP #{colorize(:cyan, 'Name')} bolt #{colorize(:cyan, 'Usage')} bolt [action] [options] #{colorize(:cyan, 'Description')} Bolt is an orchestration tool that automates the manual work it takes to maintain your infrastructure. #{colorize(:cyan, 'Subcommands')} apply Apply Puppet manifest code command Run a command remotely file Copy files between the controller and targets group Show the list of groups in the inventory guide View guides for Bolt concepts and features inventory Show the list of targets an action would run on module Manage Bolt project modules lookup Look up a value with Hiera plan Convert, create, show, and run Bolt plans plugin Show available plugins policy Apply, create, and show policies project Create and migrate Bolt projects script Upload a local script and run it remotely secret Create encryption keys and encrypt and decrypt values task Show and run Bolt tasks #{colorize(:cyan, 'Guides')} For a list of guides on Bolt's concepts and features, run 'bolt guide'. Find Bolt's documentation at https://bolt.guide. HELP APPLY_HELP = <<~HELP #{colorize(:cyan, 'Name')} apply #{colorize(:cyan, 'Usage')} bolt apply [manifest] {--targets TARGETS | --query QUERY | --rerun FILTER} [options] #{colorize(:cyan, 'Description')} Apply Puppet manifest code on the specified targets. #{colorize(:cyan, 'Documentation')} For documentation see http://pup.pt/bolt-apply. #{colorize(:cyan, 'Examples')} bolt apply manifest.pp -t target bolt apply -e "file { '/etc/puppetlabs': ensure => present }" -t target HELP COMMAND_HELP = <<~HELP #{colorize(:cyan, 'Name')} command #{colorize(:cyan, 'Usage')} bolt command [options] #{colorize(:cyan, 'Description')} Run a command on the specified targets. #{colorize(:cyan, 'Documentation')} For documentation see http://pup.pt/bolt-commands. #{colorize(:cyan, 'Actions')} run Run a command on the specified targets. HELP COMMAND_RUN_HELP = <<~HELP #{colorize(:cyan, 'Name')} command run #{colorize(:cyan, 'Usage')} bolt command run {--targets TARGETS | --query QUERY | --rerun FILTER} [options] #{colorize(:cyan, 'Description')} Run a command on the specified targets. #{colorize(:cyan, 'Documentation')} For documentation see http://pup.pt/bolt-commands. #{colorize(:cyan, 'Examples')} bolt command run 'uptime' -t target1,target2 HELP FILE_HELP = <<~HELP #{colorize(:cyan, 'Name')} file #{colorize(:cyan, 'Usage')} bolt file [options] #{colorize(:cyan, 'Description')} Copy files and directories between the controller and targets. #{colorize(:cyan, 'Documentation')} For documentation see http://pup.pt/bolt-commands. #{colorize(:cyan, 'Actions')} download Download a file or directory to the controller upload Upload a local file or directory from the controller HELP FILE_DOWNLOAD_HELP = <<~HELP #{colorize(:cyan, 'Name')} file download #{colorize(:cyan, 'Usage')} bolt file download {--targets TARGETS | --query QUERY | --rerun FILTER} [options] #{colorize(:cyan, 'Description')} Download a file or directory from one or more targets. Downloaded files and directories are saved to the a subdirectory matching the target's name under the destination directory. The destination directory is expanded relative to the downloads subdirectory of the project directory. #{colorize(:cyan, 'Documentation')} For documentation see http://pup.pt/bolt-commands. #{colorize(:cyan, 'Examples')} bolt file download /etc/ssh_config ssh_config -t all HELP FILE_UPLOAD_HELP = <<~HELP #{colorize(:cyan, 'Name')} file upload #{colorize(:cyan, 'Usage')} bolt file upload {--targets TARGETS | --query QUERY | --rerun FILTER} [options] #{colorize(:cyan, 'Description')} Upload a local file or directory. #{colorize(:cyan, 'Documentation')} For documentation see http://pup.pt/bolt-commands. #{colorize(:cyan, 'Examples')} bolt file upload /tmp/source /etc/profile.d/login.sh -t target1 HELP GROUP_HELP = <<~HELP #{colorize(:cyan, 'Name')} group #{colorize(:cyan, 'Usage')} bolt group [options] #{colorize(:cyan, 'Description')} Show the list of groups in the inventory. #{colorize(:cyan, 'Documentation')} To learn more about the inventory run 'bolt guide inventory'. #{colorize(:cyan, 'Actions')} show Show the list of groups in the inventory HELP GROUP_SHOW_HELP = <<~HELP #{colorize(:cyan, 'Name')} group show #{colorize(:cyan, 'Usage')} bolt group show [options] #{colorize(:cyan, 'Description')} Show the list of groups in the inventory. #{colorize(:cyan, 'Documentation')} To learn more about the inventory run 'bolt guide inventory'. HELP GUIDE_HELP = <<~HELP #{colorize(:cyan, 'Name')} guide #{colorize(:cyan, 'Usage')} bolt guide [topic] [options] #{colorize(:cyan, 'Description')} View guides for Bolt's concepts and features. Omitting a topic will display a list of available guides, while providing a topic will display the relevant guide. #{colorize(:cyan, 'Examples')} View a list of available guides bolt guide View the 'project' guide page bolt guide project HELP INVENTORY_HELP = <<~HELP #{colorize(:cyan, 'Name')} inventory #{colorize(:cyan, 'Usage')} bolt inventory [options] #{colorize(:cyan, 'Description')} Show the list of targets an action would run on. #{colorize(:cyan, 'Documentation')} To learn more about the inventory run 'bolt guide inventory'. #{colorize(:cyan, 'Actions')} show Show the list of targets an action would run on HELP INVENTORY_SHOW_HELP = <<~HELP #{colorize(:cyan, 'Name')} inventory show #{colorize(:cyan, 'Usage')} bolt inventory show [options] #{colorize(:cyan, 'Description')} Show the list of targets an action would run on. This command will list all targets in the project's inventory by default. To filter the targets in the list, use the --targets, --query, or --rerun options. To view detailed configuration and data for targets, use the --detail option. To learn more about the inventory run 'bolt guide inventory'. #{colorize(:cyan, 'Documentation')} To learn more about the inventory run 'bolt guide inventory'. HELP LOOKUP_HELP = <<~HELP #{colorize(:cyan, 'Name')} lookup #{colorize(:cyan, 'Usage')} bolt lookup {--targets TARGETS | --query QUERY | --rerun FILTER | --plan-hierarchy} [options] #{colorize(:cyan, 'Description')} Look up a value with Hiera. #{colorize(:cyan, 'Documentation')} Learn more about using Hiera with Bolt at https://pup.pt/bolt-hiera. #{colorize(:cyan, 'Examples')} bolt lookup password --targets servers bolt lookup password --plan-hierarchy variable=value HELP MODULE_HELP = <<~HELP #{colorize(:cyan, 'Name')} module #{colorize(:cyan, 'Usage')} bolt module [options] #{colorize(:cyan, 'Description')} Manage Bolt project modules. #{colorize(:cyan, 'Documentation')} To learn more about Bolt modules run 'bolt guide module'. #{colorize(:cyan, 'Actions')} add Add a module to the project generate-types Generate type references to register in plans install Install the project's modules show List modules available to the Bolt project HELP MODULE_ADD_HELP = <<~HELP #{colorize(:cyan, 'Name')} module add #{colorize(:cyan, 'Usage')} bolt module add [options] #{colorize(:cyan, 'Description')} Add a module to the project. Module declarations are loaded from the project's configuration file. Bolt will automatically resolve all module dependencies, generate a Puppetfile, and install the modules. #{colorize(:cyan, 'Documentation')} To learn more about Bolt modules, run 'bolt guide module'. HELP MODULE_GENERATETYPES_HELP = <<~HELP #{colorize(:cyan, 'Name')} module generate-types #{colorize(:cyan, 'Usage')} bolt module generate-types [options] #{colorize(:cyan, 'Description')} Generate type references to register in plans. To learn more about Bolt modules, run 'bolt guide module'. #{colorize(:cyan, 'Documentation')} To learn more about Bolt modules, run 'bolt guide module'. HELP MODULE_INSTALL_HELP = <<~HELP #{colorize(:cyan, 'Name')} module install #{colorize(:cyan, 'Usage')} bolt module install [options] #{colorize(:cyan, 'Description')} Install the project's modules. Module declarations are loaded from the project's configuration file. Bolt will automatically resolve all module dependencies, generate a Puppetfile, and install the modules. #{colorize(:cyan, 'Documentation')} To learn more about Bolt modules, run 'bolt guide module'. HELP MODULE_SHOW_HELP = <<~HELP #{colorize(:cyan, 'Name')} module show #{colorize(:cyan, 'Usage')} bolt module show [module name] [options] #{colorize(:cyan, 'Description')} List modules available to the Bolt project. Providing the name of a module will display detailed documentation for the module. #{colorize(:cyan, 'Documentation')} To learn more about Bolt modules, run 'bolt guide module'. HELP PLAN_HELP = <<~HELP #{colorize(:cyan, 'Name')} plan #{colorize(:cyan, 'Usage')} bolt plan [options] #{colorize(:cyan, 'Description')} Convert, create, show, and run Bolt plans. #{colorize(:cyan, 'Documentation')} Learn more about Bolt plans at https://pup.pt/bolt-plans. #{colorize(:cyan, 'Actions')} convert Convert a YAML plan to a Bolt plan new Create a new plan in the current project run Run a plan on the specified targets show Show available plans and plan documentation HELP PLAN_CONVERT_HELP = <<~HELP #{colorize(:cyan, 'Name')} plan convert #{colorize(:cyan, 'Usage')} bolt plan convert [options] #{colorize(:cyan, 'Description')} Convert a YAML plan to a Puppet language plan and print the converted plan to stdout. Converting a YAML plan might result in a plan that is syntactically correct but has different behavior. Always verify a converted plan's functionality. Note that the converted plan is not written to a file. #{colorize(:cyan, 'Documentation')} Learn more about Bolt plans at https://pup.pt/bolt-plans. #{colorize(:cyan, 'Examples')} bolt plan convert myproject::myplan bolt plan convert path/to/plan/myplan.yaml HELP PLAN_NEW_HELP = <<~HELP #{colorize(:cyan, 'Name')} plan new #{colorize(:cyan, 'Usage')} bolt plan new [options] #{colorize(:cyan, 'Description')} Create a new plan in the current project. #{colorize(:cyan, 'Documentation')} Learn more about Bolt plans at https://pup.pt/bolt-plans. #{colorize(:cyan, 'Examples')} bolt plan new myproject::myplan HELP PLAN_RUN_HELP = <<~HELP #{colorize(:cyan, 'Name')} plan run #{colorize(:cyan, 'Usage')} bolt plan run [parameters] [options] #{colorize(:cyan, 'Description')} Run a plan on the specified targets. #{colorize(:cyan, 'Documentation')} Learn more about Bolt plans at https://pup.pt/bolt-plans. #{colorize(:cyan, 'Examples')} bolt plan run canary --targets target1,target2 command=hostname HELP PLAN_SHOW_HELP = <<~HELP #{colorize(:cyan, 'Name')} plan show #{colorize(:cyan, 'Usage')} bolt plan show [plan name] [options] #{colorize(:cyan, 'Description')} Show available plans and plan documentation. Omitting the name of a plan will display a list of plans available in the Bolt project. Providing the name of a plan will display detailed documentation for the plan, including a list of available parameters. #{colorize(:cyan, 'Documentation')} Learn more about Bolt plans at https://pup.pt/bolt-plans. #{colorize(:cyan, 'Examples')} Display a list of available plans bolt plan show Display documentation for the aggregate::count plan bolt plan show aggregate::count HELP PLUGIN_HELP = <<~HELP #{colorize(:cyan, 'Name')} plugin #{colorize(:cyan, 'Usage')} bolt plugin [options] #{colorize(:cyan, 'Description')} Show available plugins. #{colorize(:cyan, 'Documentation')} Learn more about Bolt plugins at https://pup.pt/bolt-plugins. #{colorize(:cyan, 'Actions')} show Show available plugins HELP PLUGIN_SHOW_HELP = <<~HELP #{colorize(:cyan, 'Name')} plugin show #{colorize(:cyan, 'Usage')} bolt plugin show [options] #{colorize(:cyan, 'Description')} Show available plugins. #{colorize(:cyan, 'Documentation')} Learn more about Bolt plugins at https://pup.pt/bolt-plugins. HELP POLICY_HELP = <<~HELP #{colorize(:cyan, 'Name')} policy #{colorize(:cyan, 'Usage')} bolt policy [options] #{colorize(:cyan, 'Description')} Apply, create, and show policies. #{colorize(:cyan, 'Actions')} apply Apply a policy to the specified targets new Create a new policy in the current project show Show available policy HELP POLICY_APPLY_HELP = <<~HELP #{colorize(:cyan, 'Name')} policy apply #{colorize(:cyan, 'Usage')} bolt policy apply [options] #{colorize(:cyan, 'Description')} Apply a policy to the specified targets. HELP POLICY_NEW_HELP = <<~HELP #{colorize(:cyan, 'Name')} policy new #{colorize(:cyan, 'Usage')} bolt policy new [options] #{colorize(:cyan, 'Description')} Create a new policy in the current project. HELP POLICY_SHOW_HELP = <<~HELP #{colorize(:cyan, 'Name')} policy show #{colorize(:cyan, 'Usage')} bolt policy show [options] #{colorize(:cyan, 'Description')} Show available policies. HELP PROJECT_HELP = <<~HELP #{colorize(:cyan, 'Name')} project #{colorize(:cyan, 'Usage')} bolt project [options] #{colorize(:cyan, 'Description')} Create and migrate Bolt projects #{colorize(:cyan, 'Documentation')} To learn more about Bolt projects, run 'bolt guide project'. #{colorize(:cyan, 'Actions')} init Create a new Bolt project migrate Migrate a Bolt project to the latest version HELP PROJECT_INIT_HELP = <<~HELP #{colorize(:cyan, 'Name')} project init #{colorize(:cyan, 'Usage')} bolt project init [name] [options] #{colorize(:cyan, 'Description')} Create a new Bolt project in the current working directory. Specify a name for the Bolt project. Defaults to the basename of the current working directory. #{colorize(:cyan, 'Documentation')} To learn more about Bolt projects, run 'bolt guide project'. #{colorize(:cyan, 'Examples')} Create a new Bolt project using the directory as the project name. bolt project init Create a new Bolt project with a specified name. bolt project init myproject Create a new Bolt project with existing modules. bolt project init --modules puppetlabs-apt,puppetlabs-ntp HELP PROJECT_MIGRATE_HELP = <<~HELP #{colorize(:cyan, 'Name')} project migrate #{colorize(:cyan, 'Usage')} bolt project migrate [options] #{colorize(:cyan, 'Description')} Migrate a Bolt project to use current best practices and the latest version of configuration files. #{colorize(:cyan, 'Documentation')} To learn more about Bolt projects, run 'bolt guide project'. HELP SCRIPT_HELP = <<~HELP #{colorize(:cyan, 'Name')} script #{colorize(:cyan, 'Usage')} bolt script [options] #{colorize(:cyan, 'Description')} Run a script on the specified targets. #{colorize(:cyan, 'Documentation')} Learn more about running scripts at https://pup.pt/bolt-commands. #{colorize(:cyan, 'Actions')} run Run a script on the specified targets. HELP SCRIPT_RUN_HELP = <<~HELP #{colorize(:cyan, 'Name')} script run #{colorize(:cyan, 'Usage')} bolt script run