mirror of
https://github.com/inspec/inspec
synced 2024-11-23 05:03:07 +00:00
Convert to new Inspec::UI in inspec-plugin-manager-cli
Signed-off-by: Miah Johnson <miah@chia-pet.org>
This commit is contained in:
parent
da9bd13fd4
commit
a524dc030f
1 changed files with 106 additions and 72 deletions
|
@ -1,13 +1,11 @@
|
||||||
require "term/ansicolor"
|
require 'pathname'
|
||||||
require "pathname"
|
require 'inspec/plugin/v2'
|
||||||
require "inspec/plugin/v2"
|
require 'inspec/plugin/v2/installer'
|
||||||
require "inspec/plugin/v2/installer"
|
require 'inspec/dist'
|
||||||
require "inspec/dist"
|
|
||||||
|
|
||||||
module InspecPlugins
|
module InspecPlugins
|
||||||
module PluginManager
|
module PluginManager
|
||||||
class CliCommand < Inspec.plugin(2, :cli_command)
|
class CliCommand < Inspec.plugin(2, :cli_command)
|
||||||
include Term::ANSIColor
|
|
||||||
include Inspec::Dist
|
include Inspec::Dist
|
||||||
|
|
||||||
subcommand_desc "plugin SUBCOMMAND", "Manage #{PRODUCT_NAME} and Train plugins"
|
subcommand_desc "plugin SUBCOMMAND", "Manage #{PRODUCT_NAME} and Train plugins"
|
||||||
|
@ -22,15 +20,17 @@ module InspecPlugins
|
||||||
plugin_statuses = Inspec::Plugin::V2::Registry.instance.plugin_statuses
|
plugin_statuses = Inspec::Plugin::V2::Registry.instance.plugin_statuses
|
||||||
plugin_statuses.reject! { |s| %i{core bundle}.include?(s.installation_type) } unless options[:all]
|
plugin_statuses.reject! { |s| %i{core bundle}.include?(s.installation_type) } unless options[:all]
|
||||||
|
|
||||||
# TODO: ui object support
|
|
||||||
puts
|
puts
|
||||||
puts(bold { format(" %-30s%-10s%-8s%-6s", "Plugin Name", "Version", "Via", "ApiVer") })
|
ui.bold(format(' %-30s%-10s%-8s%-6s', 'Plugin Name', 'Version', 'Via', 'ApiVer'))
|
||||||
puts "-" * 55
|
ui.line
|
||||||
plugin_statuses.sort_by(&:name).each do |status|
|
plugin_statuses.sort_by(&:name).each do |status|
|
||||||
puts(format(" %-30s%-10s%-8s%-6s", status.name, make_pretty_version(status), status.installation_type, status.api_generation.to_s))
|
ui.plain(format(' %-30s%-10s%-8s%-6s', status.name,
|
||||||
|
make_pretty_version(status),
|
||||||
|
status.installation_type,
|
||||||
|
status.api_generation.to_s))
|
||||||
end
|
end
|
||||||
puts "-" * 55
|
ui.line
|
||||||
puts(" #{plugin_statuses.count} plugin(s) total")
|
ui.plain(" #{plugin_statuses.count} plugin(s) total")
|
||||||
puts
|
puts
|
||||||
end
|
end
|
||||||
|
|
||||||
|
@ -59,23 +59,22 @@ module InspecPlugins
|
||||||
search_results.delete("train-test-fixture")
|
search_results.delete("train-test-fixture")
|
||||||
end
|
end
|
||||||
|
|
||||||
# TODO: ui object support
|
|
||||||
puts
|
puts
|
||||||
puts(bold { format(" %-30s%-50s", "Plugin Name", "Versions Available") })
|
ui.bold(format(' %-30s%-50s', 'Plugin Name', 'Versions Available'))
|
||||||
puts "-" * 55
|
ui.line
|
||||||
search_results.keys.sort.each do |plugin_name|
|
search_results.keys.sort.each do |plugin_name|
|
||||||
versions = options[:all] ? search_results[plugin_name] : [search_results[plugin_name].first]
|
versions = options[:all] ? search_results[plugin_name] : [search_results[plugin_name].first]
|
||||||
versions = "(" + versions.join(", ") + ")"
|
versions = '(' + versions.join(', ') + ')'
|
||||||
puts(format(" %-30s%-50s", plugin_name, versions))
|
ui.plain(format(' %-30s%-50s', plugin_name, versions))
|
||||||
end
|
end
|
||||||
puts "-" * 55
|
ui.line
|
||||||
puts(" #{search_results.count} plugin(s) found")
|
ui.plain(" #{search_results.count} plugin(s) found")
|
||||||
puts
|
puts
|
||||||
|
|
||||||
exit 2 if search_results.empty?
|
ui.exit 2 if search_results.empty?
|
||||||
rescue Inspec::Plugin::V2::SearchError => ex
|
rescue Inspec::Plugin::V2::SearchError => ex
|
||||||
Inspec::Log.error ex.message
|
Inspec::Log.error ex.message
|
||||||
exit 1
|
ui.exit 1
|
||||||
end
|
end
|
||||||
|
|
||||||
#==================================================================#
|
#==================================================================#
|
||||||
|
@ -119,13 +118,14 @@ module InspecPlugins
|
||||||
begin
|
begin
|
||||||
installer.update(plugin_name)
|
installer.update(plugin_name)
|
||||||
rescue Inspec::Plugin::V2::UpdateError => ex
|
rescue Inspec::Plugin::V2::UpdateError => ex
|
||||||
puts(red { "Update error: " } + ex.message + " - update failed")
|
ui.red('Update error: ' + ex.message + ' - update failed')
|
||||||
exit 1
|
ui.exit 1
|
||||||
end
|
end
|
||||||
post_update_versions = installer.list_installed_plugin_gems.select { |spec| spec.name == plugin_name }.map { |spec| spec.version.to_s }
|
post_update_versions = installer.list_installed_plugin_gems.select { |spec| spec.name == plugin_name }.map { |spec| spec.version.to_s }
|
||||||
new_version = (post_update_versions - pre_update_versions).first
|
new_version = (post_update_versions - pre_update_versions).first
|
||||||
|
|
||||||
puts(bold { plugin_name } + " plugin, version #{old_version} -> #{new_version}, updated from rubygems.org")
|
ui.bold(plugin_name + " plugin, version #{old_version} -> " \
|
||||||
|
"#{new_version}, updated from rubygems.org")
|
||||||
end
|
end
|
||||||
|
|
||||||
#--------------------------
|
#--------------------------
|
||||||
|
@ -144,9 +144,9 @@ module InspecPlugins
|
||||||
def uninstall(plugin_name)
|
def uninstall(plugin_name)
|
||||||
status = Inspec::Plugin::V2::Registry.instance[plugin_name.to_sym]
|
status = Inspec::Plugin::V2::Registry.instance[plugin_name.to_sym]
|
||||||
unless status
|
unless status
|
||||||
puts(red { "No such plugin installed: " } + "#{plugin_name} is not installed - uninstall failed")
|
ui.red("No such plugin installed: #{plugin_name} is not " \
|
||||||
|
'installed - uninstall failed')
|
||||||
exit 1
|
ui.exit 1
|
||||||
end
|
end
|
||||||
installer = Inspec::Plugin::V2::Installer.instance
|
installer = Inspec::Plugin::V2::Installer.instance
|
||||||
|
|
||||||
|
@ -156,11 +156,13 @@ module InspecPlugins
|
||||||
installer.uninstall(plugin_name)
|
installer.uninstall(plugin_name)
|
||||||
|
|
||||||
if status.installation_type == :path
|
if status.installation_type == :path
|
||||||
puts(bold { plugin_name } + " path-based plugin install has been uninstalled")
|
ui.bold(plugin_name + ' path-based plugin install has been ' \
|
||||||
|
'uninstalled')
|
||||||
else
|
else
|
||||||
puts(bold { plugin_name } + " plugin, version #{old_version}, has been uninstalled")
|
ui.bold(plugin_name + " plugin, version #{old_version}, has " \
|
||||||
|
'been uninstalled')
|
||||||
end
|
end
|
||||||
exit 0
|
ui.exit 0
|
||||||
end
|
end
|
||||||
|
|
||||||
private
|
private
|
||||||
|
@ -172,8 +174,8 @@ module InspecPlugins
|
||||||
|
|
||||||
def install_from_gemfile(gem_file)
|
def install_from_gemfile(gem_file)
|
||||||
unless File.exist? gem_file
|
unless File.exist? gem_file
|
||||||
puts(red { "No such plugin gem file " } + gem_file + " - installation failed.")
|
ui.red("No such plugin gem file #{gem_file} - installation failed.")
|
||||||
exit 1
|
ui.exit 1
|
||||||
end
|
end
|
||||||
|
|
||||||
plugin_name_parts = File.basename(gem_file, ".gem").split("-")
|
plugin_name_parts = File.basename(gem_file, ".gem").split("-")
|
||||||
|
@ -183,14 +185,15 @@ module InspecPlugins
|
||||||
|
|
||||||
installer.install(plugin_name, gem_file: gem_file)
|
installer.install(plugin_name, gem_file: gem_file)
|
||||||
|
|
||||||
puts(bold { plugin_name } + " plugin, version #{version}, installed from local .gem file")
|
ui.bold("#{plugin_name} plugin, version #{version}, installed from " \
|
||||||
exit 0
|
'local .gem file')
|
||||||
|
ui.exit 0
|
||||||
end
|
end
|
||||||
|
|
||||||
def install_from_path(path)
|
def install_from_path(path)
|
||||||
unless File.exist? path
|
unless File.exist? path
|
||||||
puts(red { "No such source code path " } + path + " - installation failed.")
|
ui.red('No such source code path ' + path + ' - installation failed.')
|
||||||
exit 1
|
ui.exit 1
|
||||||
end
|
end
|
||||||
|
|
||||||
plugin_name = File.basename(path, ".rb")
|
plugin_name = File.basename(path, ".rb")
|
||||||
|
@ -204,8 +207,10 @@ module InspecPlugins
|
||||||
|
|
||||||
# Already installed?
|
# Already installed?
|
||||||
if registry.known_plugin?(plugin_name.to_sym)
|
if registry.known_plugin?(plugin_name.to_sym)
|
||||||
puts(red { "Plugin already installed" } + " - #{plugin_name} - Use '#{EXEC_NAME} plugin list' to see previously installed plugin - installation failed.")
|
ui.red("Plugin already installed - #{plugin_name} - Use '#{EXEC_NAME}" \
|
||||||
exit 2
|
"plugin list' to see previously installed plugin - " \
|
||||||
|
'installation failed.')
|
||||||
|
ui.exit 2
|
||||||
end
|
end
|
||||||
|
|
||||||
# Can we figure out how to load it?
|
# Can we figure out how to load it?
|
||||||
|
@ -217,8 +222,9 @@ module InspecPlugins
|
||||||
# OK, install it!
|
# OK, install it!
|
||||||
installer.install(plugin_name, path: entry_point)
|
installer.install(plugin_name, path: entry_point)
|
||||||
|
|
||||||
puts(bold { plugin_name } + " plugin installed via source path reference, resolved to entry point " + entry_point)
|
ui.bold("#{plugin_name} plugin installed via source path reference, " \
|
||||||
exit 0
|
"resolved to entry point #{entry_point}")
|
||||||
|
ui.exit 0
|
||||||
end
|
end
|
||||||
|
|
||||||
# Rationale for rubocop variances: It's a heuristics method, and will be full of
|
# Rationale for rubocop variances: It's a heuristics method, and will be full of
|
||||||
|
@ -279,8 +285,10 @@ module InspecPlugins
|
||||||
|
|
||||||
# Well, if we got here, parts[2] matches an inspec/train prefix, but we have no idea about anything.
|
# Well, if we got here, parts[2] matches an inspec/train prefix, but we have no idea about anything.
|
||||||
# Give up.
|
# Give up.
|
||||||
puts(red { "Unrecognizable plugin structure" } + " - #{parts[2]} - When installing from a path, please provide the path of the entry point file - installation failed.")
|
ui.red("Unrecognizable plugin structure - #{parts[2]} - When " \
|
||||||
exit 1
|
'installing from a path, please provide the path of the ' \
|
||||||
|
'entry point file - installation failed.')
|
||||||
|
ui.exit 1
|
||||||
end
|
end
|
||||||
|
|
||||||
def install_from_path__probe_load(entry_point, plugin_name)
|
def install_from_path__probe_load(entry_point, plugin_name)
|
||||||
|
@ -288,9 +296,11 @@ module InspecPlugins
|
||||||
begin
|
begin
|
||||||
require entry_point
|
require entry_point
|
||||||
rescue LoadError => ex
|
rescue LoadError => ex
|
||||||
puts(red { "Plugin contains errors" } + " - #{plugin_name} - Encountered errors while trying to test load the plugin entry point, resolved to #{entry_point} - installation failed")
|
ui.red("Plugin contains errors - #{plugin_name} - Encountered " \
|
||||||
puts ex.message
|
'errors while trying to test load the plugin entry point, ' \
|
||||||
exit 1
|
"resolved to #{entry_point} - installation failed")
|
||||||
|
ui.plain ex.message
|
||||||
|
ui.exit 1
|
||||||
end
|
end
|
||||||
|
|
||||||
# OK, the wheels didn't fall off. But is it a plugin?
|
# OK, the wheels didn't fall off. But is it a plugin?
|
||||||
|
@ -299,13 +309,19 @@ module InspecPlugins
|
||||||
# And the registry is keyed on Strings
|
# And the registry is keyed on Strings
|
||||||
registry_key = plugin_name.to_s.sub(/^train-/, "")
|
registry_key = plugin_name.to_s.sub(/^train-/, "")
|
||||||
unless Train::Plugins.registry.key?(registry_key)
|
unless Train::Plugins.registry.key?(registry_key)
|
||||||
puts(red { "Does not appear to be a plugin" } + " - #{plugin_name} - After probe-loading the supposed plugin, it did not register itself to Train. Ensure something inherits from 'Train.plugin(1)' - installation failed.")
|
ui.red("Does not appear to be a plugin - #{plugin_name} - After " \
|
||||||
exit 1
|
'probe-loading the supposed plugin, it did not register ' \
|
||||||
|
'itself to Train. Ensure something inherits from ' \
|
||||||
|
"'Train.plugin(1)' - installation failed.")
|
||||||
|
ui.exit 1
|
||||||
end
|
end
|
||||||
else
|
else
|
||||||
unless registry.known_plugin?(plugin_name.to_sym)
|
unless registry.known_plugin?(plugin_name.to_sym)
|
||||||
puts(red { "Does not appear to be a plugin" } + " - #{plugin_name} - After probe-loading the supposed plugin, it did not register itself to InSpec. Ensure something inherits from 'Inspec.plugin(2)' - installation failed.")
|
ui.red("Does not appear to be a plugin - #{plugin_name} - After " \
|
||||||
exit 1
|
'probe-loading the supposed plugin, it did not register ' \
|
||||||
|
'itself to InSpec. Ensure something inherits from ' \
|
||||||
|
"'Inspec.plugin(2)' - installation failed.")
|
||||||
|
ui.exit 1
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
@ -325,8 +341,9 @@ module InspecPlugins
|
||||||
post_installed_versions = installer.list_installed_plugin_gems.select { |spec| spec.name == plugin_name }.map { |spec| spec.version.to_s }
|
post_installed_versions = installer.list_installed_plugin_gems.select { |spec| spec.name == plugin_name }.map { |spec| spec.version.to_s }
|
||||||
new_version = (post_installed_versions - pre_installed_versions).first
|
new_version = (post_installed_versions - pre_installed_versions).first
|
||||||
|
|
||||||
puts(bold { plugin_name } + " plugin, version #{new_version}, installed from rubygems.org")
|
ui.bold("#{plugin_name} plugin, version #{new_version}, installed " \
|
||||||
exit 0
|
'from rubygems.org')
|
||||||
|
ui.exit 0
|
||||||
end
|
end
|
||||||
|
|
||||||
def install_from_remote_gem_verson_preflight_check(plugin_name, requested_version, pre_installed_versions)
|
def install_from_remote_gem_verson_preflight_check(plugin_name, requested_version, pre_installed_versions)
|
||||||
|
@ -348,38 +365,50 @@ module InspecPlugins
|
||||||
they_explicitly_asked_for_a_version = !options[:version].nil?
|
they_explicitly_asked_for_a_version = !options[:version].nil?
|
||||||
what_we_would_install_is_already_installed = pre_installed_versions.include?(requested_version)
|
what_we_would_install_is_already_installed = pre_installed_versions.include?(requested_version)
|
||||||
if what_we_would_install_is_already_installed && they_explicitly_asked_for_a_version
|
if what_we_would_install_is_already_installed && they_explicitly_asked_for_a_version
|
||||||
puts(red { "Plugin already installed at requested version" } + " - plugin #{plugin_name} #{requested_version} - refusing to install.")
|
ui.red('Plugin already installed at requested version - plugin ' \
|
||||||
|
"#{plugin_name} #{requested_version} - refusing to install.")
|
||||||
elsif what_we_would_install_is_already_installed && !they_explicitly_asked_for_a_version
|
elsif what_we_would_install_is_already_installed && !they_explicitly_asked_for_a_version
|
||||||
puts(red { "Plugin already installed at latest version" } + " - plugin #{plugin_name} #{requested_version} - refusing to install.")
|
ui.red('Plugin already installed at latest version - plugin ' \
|
||||||
|
"#{plugin_name} #{requested_version} - refusing to install.")
|
||||||
else
|
else
|
||||||
# There are existing versions installed, but none of them are what was requested
|
# There are existing versions installed, but none of them are what was requested
|
||||||
puts(red { "Update required" } + " - plugin #{plugin_name}, requested #{requested_version}, have #{pre_installed_versions.join(", ")}; use `inspec plugin update` - refusing to install.")
|
ui.red("Update required - plugin #{plugin_name}, requested " \
|
||||||
|
"#{requested_version}, have " \
|
||||||
|
"#{pre_installed_versions.join(', ')}; use `inspec " \
|
||||||
|
'plugin update` - refusing to install.')
|
||||||
end
|
end
|
||||||
|
|
||||||
exit 2
|
ui.exit 2
|
||||||
end
|
end
|
||||||
|
|
||||||
# Rationale for RuboCop variance: This is a one-line method with heavy UX-focused error handling.
|
# Rationale for RuboCop variance: This is a one-line method with heavy UX-focused error handling.
|
||||||
def install_attempt_install(plugin_name) # rubocop: disable Metrics/AbcSize
|
def install_attempt_install(plugin_name) # rubocop: disable Metrics/AbcSize
|
||||||
installer.install(plugin_name, version: options[:version])
|
installer.install(plugin_name, version: options[:version])
|
||||||
rescue Inspec::Plugin::V2::PluginExcludedError => ex
|
rescue Inspec::Plugin::V2::PluginExcludedError => ex
|
||||||
puts(red { "Plugin on Exclusion List" } + " - #{plugin_name} is listed as an incompatible gem - refusing to install.")
|
ui.red("Plugin on Exclusion List - #{plugin_name} is listed as an " \
|
||||||
puts "Rationale: #{ex.details.rationale}"
|
'incompatible gem - refusing to install.')
|
||||||
puts "Exclusion list location: " + File.join(Inspec.src_root, "etc", "plugin_filters.json")
|
ui.plain("Rationale: #{ex.details.rationale}")
|
||||||
puts "If you disagree with this determination, please accept our apologies for the misunderstanding, and open an issue at https://github.com/inspec/inspec/issues/new"
|
ui.plain('Exclusion list location: ' +
|
||||||
exit 2
|
File.join(Inspec.src_root, 'etc', 'plugin_filters.json'))
|
||||||
|
ui.plain('If you disagree with this determination, please accept ' \
|
||||||
|
'our apologies for the misunderstanding, and open an issue ' \
|
||||||
|
'at https://github.com/inspec/inspec/issues/new')
|
||||||
|
ui.exit 2
|
||||||
rescue Inspec::Plugin::V2::InstallError
|
rescue Inspec::Plugin::V2::InstallError
|
||||||
raise if Inspec::Log.level == :debug
|
raise if Inspec::Log.level == :debug
|
||||||
|
|
||||||
results = installer.search(plugin_name, exact: true)
|
results = installer.search(plugin_name, exact: true)
|
||||||
if results.empty?
|
if results.empty?
|
||||||
puts(red { "No such plugin gem " } + plugin_name + " could be found on rubygems.org - installation failed.")
|
ui.red("No such plugin gem #{plugin_name} could be found on " \
|
||||||
|
'rubygems.org - installation failed.')
|
||||||
elsif options[:version] && !results[plugin_name].include?(options[:version])
|
elsif options[:version] && !results[plugin_name].include?(options[:version])
|
||||||
puts(red { "No such version" } + " - " + plugin_name + " exists, but no such version #{options[:version]} found on rubygems.org - installation failed.")
|
ui.red("No such version - #{plugin_name} exists, but no such " \
|
||||||
|
"version #{options[:version]} found on rubygems.org - " \
|
||||||
|
'installation failed.')
|
||||||
else
|
else
|
||||||
puts(red { "Unknown error occured " } + " - installation failed.")
|
ui.red('Unknown error occured - installation failed.')
|
||||||
end
|
end
|
||||||
exit 1
|
ui.exit 1
|
||||||
end
|
end
|
||||||
|
|
||||||
#==================================================================#
|
#==================================================================#
|
||||||
|
@ -390,11 +419,13 @@ module InspecPlugins
|
||||||
# Check for path install
|
# Check for path install
|
||||||
status = Inspec::Plugin::V2::Registry.instance[plugin_name.to_sym]
|
status = Inspec::Plugin::V2::Registry.instance[plugin_name.to_sym]
|
||||||
if !status
|
if !status
|
||||||
puts(red { "No such plugin installed: " } + "#{plugin_name} - update failed")
|
ui.red("No such plugin installed: #{plugin_name} - update failed")
|
||||||
exit 1
|
ui.exit 1
|
||||||
elsif status.installation_type == :path
|
elsif status.installation_type == :path
|
||||||
puts(red { "Cannot update path-based install: " } + "#{plugin_name} is installed via path reference; use `inspec plugin uninstall` to remove - refusing to update")
|
ui.red("Cannot update path-based install: #{plugin_name} is " \
|
||||||
exit 2
|
'installed via path reference; use `inspec plugin ' \
|
||||||
|
'uninstall` to remove - refusing to update')
|
||||||
|
ui.exit 2
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
@ -403,8 +434,9 @@ module InspecPlugins
|
||||||
latest_version = latest_version[plugin_name]&.last
|
latest_version = latest_version[plugin_name]&.last
|
||||||
|
|
||||||
if pre_update_versions.include?(latest_version)
|
if pre_update_versions.include?(latest_version)
|
||||||
puts(red { "Already installed at latest version: " } + "#{plugin_name} is at #{latest_version}, which the latest - refusing to update")
|
ui.red("Already installed at latest version: #{plugin_name} is at " \
|
||||||
exit 2
|
"#{latest_version}, which the latest - refusing to update")
|
||||||
|
ui.exit 2
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
@ -421,8 +453,10 @@ module InspecPlugins
|
||||||
|
|
||||||
def check_plugin_name(plugin_name, action)
|
def check_plugin_name(plugin_name, action)
|
||||||
unless plugin_name =~ /^(inspec|train)-/
|
unless plugin_name =~ /^(inspec|train)-/
|
||||||
puts(red { "Invalid plugin name" } + " - #{plugin_name} - All inspec plugins must begin with either 'inspec-' or 'train-' - #{action} failed.")
|
ui.red("Invalid plugin name - #{plugin_name} - All inspec " \
|
||||||
exit 1
|
"plugins must begin with either 'inspec-' or 'train-' " \
|
||||||
|
"- #{action} failed.")
|
||||||
|
ui.exit 1
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue