mirror of
https://github.com/inspec/inspec
synced 2024-11-27 15:10:44 +00:00
Merge pull request #4387 from inspec/cw/plugins-list-scope
inspec plugins: List system plugins and other UX improvements
This commit is contained in:
commit
ed90189bbe
10 changed files with 336 additions and 194 deletions
|
@ -60,4 +60,35 @@ module Inspec::Plugin::V2
|
|||
end
|
||||
end
|
||||
end
|
||||
|
||||
# To be a valid plugin name, the plugin must beign with either
|
||||
# inspec- or train-, AND ALSO not be on the exclusion list.
|
||||
# We maintain this exclusion list to avoid confusing users.
|
||||
# For example, we want to have a real gem named inspec-test-fixture,
|
||||
# but we don't want the users to see that.
|
||||
module FilterPredicates
|
||||
def train_plugin_name?(name)
|
||||
valid_plugin_name?(name, :train)
|
||||
end
|
||||
|
||||
def inspec_plugin_name?(name)
|
||||
valid_plugin_name?(name, :inspec)
|
||||
end
|
||||
|
||||
def valid_plugin_name?(name, kind = :either)
|
||||
# Must have a permitted prefix.
|
||||
return false unless case kind
|
||||
when :inspec
|
||||
name.to_s.start_with?("inspec-")
|
||||
when :train
|
||||
name.to_s.start_with?("train-")
|
||||
when :either
|
||||
name.to_s.match(/^(inspec|train)-/)
|
||||
else false
|
||||
end # rubocop: disable Layout/EndAlignment
|
||||
|
||||
# And must not be on the exclusion list.
|
||||
! Inspec::Plugin::V2::PluginFilter.exclude?(name)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
|
@ -60,14 +60,15 @@ module Inspec::Plugin::V2
|
|||
# TODO: - check plugins.json for validity before trying anything that needs to modify it.
|
||||
validate_installation_opts(plugin_name, opts)
|
||||
|
||||
# TODO: change all of these to return installed spec/gem/thingy
|
||||
# TODO: return installed thingy
|
||||
if opts[:path]
|
||||
install_from_path(plugin_name, opts)
|
||||
elsif opts[:gem_file]
|
||||
install_from_gem_file(plugin_name, opts)
|
||||
gem_version = install_from_gem_file(plugin_name, opts)
|
||||
opts[:version] = gem_version.to_s
|
||||
else
|
||||
install_from_remote_gems(plugin_name, opts)
|
||||
gem_version = install_from_remote_gems(plugin_name, opts)
|
||||
opts[:version] = gem_version.to_s
|
||||
end
|
||||
|
||||
update_plugin_config_file(plugin_name, opts.merge({ action: :install }))
|
||||
|
@ -88,9 +89,9 @@ module Inspec::Plugin::V2
|
|||
|
||||
# TODO: Handle installing from a local file
|
||||
# TODO: Perform dependency checks to make sure the new solution is valid
|
||||
install_from_remote_gems(plugin_name, opts)
|
||||
gem_version = install_from_remote_gems(plugin_name, opts)
|
||||
|
||||
update_plugin_config_file(plugin_name, opts.merge({ action: :update }))
|
||||
update_plugin_config_file(plugin_name, opts.merge({ action: :update, version: gem_version.to_s }))
|
||||
end
|
||||
|
||||
# Uninstalls (removes) a plugin. Refers to plugin.json to determine if it
|
||||
|
@ -335,13 +336,15 @@ module Inspec::Plugin::V2
|
|||
# not obliged to during packaging.)
|
||||
# So, after each install, run a scan for all gem(specs) we manage, and copy in their gemspec file
|
||||
# into the exploded gem source area if absent.
|
||||
|
||||
loader.list_managed_gems.each do |spec|
|
||||
path_inside_source = File.join(spec.gem_dir, "#{spec.name}.gemspec")
|
||||
unless File.exist?(path_inside_source)
|
||||
File.write(path_inside_source, spec.to_ruby)
|
||||
end
|
||||
end
|
||||
|
||||
# Locate the GemVersion for the new dependency and return it
|
||||
solution.detect { |g| g.name == new_plugin_dependency.name }.version
|
||||
end
|
||||
|
||||
#===================================================================#
|
||||
|
@ -365,7 +368,7 @@ module Inspec::Plugin::V2
|
|||
# excluding any that are path-or-core-based, excluding the gem to be removed
|
||||
plugin_deps_we_still_must_satisfy = registry.plugin_statuses
|
||||
plugin_deps_we_still_must_satisfy = plugin_deps_we_still_must_satisfy.select do |status|
|
||||
status.installation_type == :gem && status.name != plugin_name_to_be_removed.to_sym
|
||||
status.installation_type == :user_gem && status.name != plugin_name_to_be_removed.to_sym
|
||||
end
|
||||
plugin_deps_we_still_must_satisfy = plugin_deps_we_still_must_satisfy.map do |status|
|
||||
constraint = status.version || "> 0"
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
require "inspec/log"
|
||||
require "inspec/plugin/v2/config_file"
|
||||
require "inspec/plugin/v2/filter"
|
||||
|
||||
# Add the current directory of the process to the load path
|
||||
$LOAD_PATH.unshift(".") unless $LOAD_PATH.include?(".")
|
||||
|
@ -11,9 +12,16 @@ module Inspec::Plugin::V2
|
|||
class Loader
|
||||
attr_reader :conf_file, :registry, :options
|
||||
|
||||
# For {inspec|train}_plugin_name?
|
||||
include Inspec::Plugin::V2::FilterPredicates
|
||||
extend Inspec::Plugin::V2::FilterPredicates
|
||||
|
||||
def initialize(options = {})
|
||||
@options = options
|
||||
@registry = Inspec::Plugin::V2::Registry.instance
|
||||
|
||||
# User plugins are those installed by the user via `inspec plugin install`
|
||||
# and are installed under ~/.inspec/gems
|
||||
unless options[:omit_user_plugins]
|
||||
@conf_file = Inspec::Plugin::V2::ConfigFile.new
|
||||
read_conf_file_into_registry
|
||||
|
@ -27,9 +35,8 @@ module Inspec::Plugin::V2
|
|||
# and may be safely loaded
|
||||
detect_core_plugins unless options[:omit_core_plugins]
|
||||
|
||||
# Train plugins aren't InSpec plugins (they don't use our API)
|
||||
# but InSpec CLI manages them. So, we have to wrap them a bit.
|
||||
accommodate_train_plugins
|
||||
# Identify plugins that inspec is co-installed with
|
||||
detect_system_plugins unless options[:omit_sys_plugins]
|
||||
end
|
||||
|
||||
def load_all
|
||||
|
@ -46,7 +53,7 @@ module Inspec::Plugin::V2
|
|||
begin
|
||||
# We could use require, but under testing, we need to repeatedly reload the same
|
||||
# plugin. However, gems only work with require (rubygems dooes not overload `load`)
|
||||
if plugin_details.installation_type == :gem
|
||||
if plugin_details.installation_type == :user_gem
|
||||
activate_managed_gems_for_plugin(plugin_name)
|
||||
require plugin_details.entry_point
|
||||
else
|
||||
|
@ -130,10 +137,11 @@ module Inspec::Plugin::V2
|
|||
end
|
||||
|
||||
# Lists all plugin gems found in the plugin_gem_path.
|
||||
# This is simply all gems that begin with train- or inspec-.
|
||||
# This is simply all gems that begin with train- or inspec-
|
||||
# and are not on the exclusion list.
|
||||
# @return [Array[Gem::Specification]] Specs of all gems found.
|
||||
def self.list_installed_plugin_gems
|
||||
list_managed_gems.select { |spec| spec.name.match(/^(inspec|train)-/) }
|
||||
list_managed_gems.select { |spec| valid_plugin_name?(spec.name) }
|
||||
end
|
||||
|
||||
def list_installed_plugin_gems
|
||||
|
@ -234,34 +242,70 @@ module Inspec::Plugin::V2
|
|||
end
|
||||
end
|
||||
|
||||
def accommodate_train_plugins
|
||||
registry.plugin_names.map(&:to_s).grep(/^train-/).each do |train_plugin_name|
|
||||
status = registry[train_plugin_name.to_sym]
|
||||
status.api_generation = :'train-1'
|
||||
|
||||
if status.installation_type == :gem
|
||||
# Activate the gem. This allows train to 'require' the gem later.
|
||||
activate_managed_gems_for_plugin(train_plugin_name)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
def read_conf_file_into_registry
|
||||
conf_file.each do |plugin_entry|
|
||||
status = Inspec::Plugin::V2::Status.new
|
||||
status.name = plugin_entry[:name]
|
||||
status.loaded = false
|
||||
status.installation_type = (plugin_entry[:installation_type] || :gem)
|
||||
status.installation_type = (plugin_entry[:installation_type] || :user_gem)
|
||||
case status.installation_type
|
||||
when :gem
|
||||
when :user_gem
|
||||
status.entry_point = status.name.to_s
|
||||
status.version = plugin_entry[:version]
|
||||
when :path
|
||||
status.entry_point = plugin_entry[:installation_path]
|
||||
end
|
||||
|
||||
# Train plugins are not true InSpec plugins; we need to decorate them a
|
||||
# bit more to integrate them.
|
||||
fixup_train_plugin_status(status) if train_plugin_name?(plugin_entry[:name])
|
||||
|
||||
registry[status.name] = status
|
||||
end
|
||||
end
|
||||
|
||||
def fixup_train_plugin_status(status)
|
||||
status.api_generation = :'train-1'
|
||||
if status.installation_type == :user_gem
|
||||
# Activate the gem. This allows train to 'require' the gem later.
|
||||
activate_managed_gems_for_plugin(status.entry_point)
|
||||
end
|
||||
end
|
||||
|
||||
def detect_system_plugins
|
||||
# Find the gemspec for inspec
|
||||
inspec_gemspec = Gem::Specification.find_by_name("inspec", "=#{Inspec::VERSION}")
|
||||
|
||||
# Make a RequestSet that represents the dependencies of inspec
|
||||
inspec_deps_request_set = Gem::RequestSet.new(*inspec_gemspec.dependencies)
|
||||
inspec_deps_request_set.remote = false
|
||||
|
||||
# Resolve the request against the installed gem universe
|
||||
gem_resolver = Gem::Resolver::CurrentSet.new
|
||||
runtime_solution = inspec_deps_request_set.resolve(gem_resolver)
|
||||
|
||||
inspec_gemspec.dependencies.each do |inspec_dep|
|
||||
next unless inspec_plugin_name?(inspec_dep.name) || train_plugin_name?(inspec_dep.name)
|
||||
|
||||
plugin_spec = runtime_solution.detect { |s| s.name == inspec_dep.name }.spec
|
||||
|
||||
status = Inspec::Plugin::V2::Status.new
|
||||
status.name = inspec_dep.name
|
||||
status.entry_point = inspec_dep.name # gem-based, just 'require' the name
|
||||
status.version = plugin_spec.version.to_s
|
||||
status.loaded = false
|
||||
status.installation_type = :system_gem
|
||||
|
||||
if train_plugin_name?(status[:name])
|
||||
# Train plugins are not true InSpec plugins; we need to decorate them a
|
||||
# bit more to integrate them.
|
||||
fixup_train_plugin_status(status)
|
||||
else
|
||||
status.api_generation = 2
|
||||
end
|
||||
|
||||
registry[status.name.to_sym] = status
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
|
@ -6,6 +6,14 @@ require "inspec/dist"
|
|||
module InspecPlugins
|
||||
module PluginManager
|
||||
class CliCommand < Inspec.plugin(2, :cli_command)
|
||||
INSTALL_TYPE_LABELS = {
|
||||
bundle: "core", # Calling this core, too - not much of a distinction
|
||||
core: "core",
|
||||
path: "path",
|
||||
user_gem: "gem (user)",
|
||||
system_gem: "gem (system)",
|
||||
}.freeze
|
||||
|
||||
include Inspec::Dist
|
||||
|
||||
subcommand_desc "plugin SUBCOMMAND", "Manage #{PRODUCT_NAME} and Train plugins"
|
||||
|
@ -15,22 +23,36 @@ module InspecPlugins
|
|||
#==================================================================#
|
||||
|
||||
desc "list [options]", "Lists user-installed #{PRODUCT_NAME} plugins."
|
||||
option :all, desc: "Include plugins shipped with #{PRODUCT_NAME} as well.", type: :boolean, aliases: [:a]
|
||||
option :all, desc: "List all types of plugins (default)", type: :boolean, default: true, aliases: [:a]
|
||||
option :user, desc: "List user plugins, from ~/.inspec/gems", banner: "", type: :boolean, default: false, aliases: [:u]
|
||||
option :system, desc: "List system plugins, those InSpec depends on", banner: "", type: :boolean, default: false, aliases: [:s]
|
||||
option :core, desc: "List core plugins, those InSpec ships with", banner: "", type: :boolean, default: false, aliases: [:c]
|
||||
|
||||
def list
|
||||
plugin_statuses = Inspec::Plugin::V2::Registry.instance.plugin_statuses
|
||||
plugin_statuses.reject! { |s| %i{core bundle}.include?(s.installation_type) } unless options[:all]
|
||||
|
||||
puts
|
||||
ui.bold(format(" %-30s%-10s%-8s%-6s", "Plugin Name", "Version", "Via", "ApiVer"))
|
||||
ui.line
|
||||
plugin_statuses.sort_by(&:name).each do |status|
|
||||
ui.plain(format(" %-30s%-10s%-8s%-6s", status.name,
|
||||
make_pretty_version(status),
|
||||
status.installation_type,
|
||||
status.api_generation.to_s))
|
||||
options[:all] = false if options[:core] || options[:user] || options[:system]
|
||||
plugin_statuses.select! do |status|
|
||||
type = status.installation_type
|
||||
options[:all] ||
|
||||
(options[:core] && %i{core bundle}.include?(type)) ||
|
||||
(options[:user] && %i{user_gem path}.include?(type)) ||
|
||||
(options[:system] && :system_gem == type)
|
||||
end
|
||||
ui.line
|
||||
ui.plain(" #{plugin_statuses.count} plugin(s) total")
|
||||
|
||||
unless plugin_statuses.empty?
|
||||
ui.table do |t|
|
||||
t.header = ["Plugin Name", "Version", "Via", "ApiVer"]
|
||||
plugin_statuses.sort_by { |s| s.name.to_s }.each do |status|
|
||||
t << [
|
||||
status.name,
|
||||
make_pretty_version(status),
|
||||
make_pretty_install_type(status),
|
||||
status.api_generation,
|
||||
]
|
||||
end
|
||||
end
|
||||
end
|
||||
ui.plain_line(" #{plugin_statuses.count} plugin(s) total")
|
||||
puts
|
||||
end
|
||||
|
||||
|
@ -60,15 +82,15 @@ module InspecPlugins
|
|||
end
|
||||
|
||||
puts
|
||||
ui.bold(format(" %-30s%-50s", "Plugin Name", "Versions Available"))
|
||||
ui.bold(format(" %-30s%-50s\n", "Plugin Name", "Versions Available"))
|
||||
ui.line
|
||||
search_results.keys.sort.each do |plugin_name|
|
||||
versions = options[:all] ? search_results[plugin_name] : [search_results[plugin_name].first]
|
||||
versions = "(" + versions.join(", ") + ")"
|
||||
ui.plain(format(" %-30s%-50s", plugin_name, versions))
|
||||
ui.plain_line(format(" %-30s%-50s", plugin_name, versions))
|
||||
end
|
||||
ui.line
|
||||
ui.plain(" #{search_results.count} plugin(s) found")
|
||||
ui.plain_line(" #{search_results.count} plugin(s) found")
|
||||
puts
|
||||
|
||||
ui.exit Inspec::UI::EXIT_PLUGIN_ERROR if search_results.empty?
|
||||
|
@ -118,14 +140,14 @@ module InspecPlugins
|
|||
begin
|
||||
installer.update(plugin_name)
|
||||
rescue Inspec::Plugin::V2::UpdateError => ex
|
||||
ui.plain("#{ui.red("Update error:")} #{ex.message} - update failed")
|
||||
ui.plain_line("#{ui.red("Update error:", print: false)} #{ex.message} - update failed")
|
||||
ui.exit Inspec::UI::EXIT_USAGE_ERROR
|
||||
end
|
||||
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
|
||||
|
||||
ui.bold(plugin_name + " plugin, version #{old_version} -> " \
|
||||
"#{new_version}, updated from rubygems.org")
|
||||
"#{new_version}, updated from rubygems.org\n")
|
||||
end
|
||||
|
||||
#--------------------------
|
||||
|
@ -144,7 +166,7 @@ module InspecPlugins
|
|||
def uninstall(plugin_name)
|
||||
status = Inspec::Plugin::V2::Registry.instance[plugin_name.to_sym]
|
||||
unless status
|
||||
ui.plain("#{ui.red("No such plugin installed:")} #{plugin_name} is not " \
|
||||
ui.plain_line("#{ui.red("No such plugin installed:", print: false)} #{plugin_name} is not " \
|
||||
"installed - uninstall failed")
|
||||
ui.exit Inspec::UI::EXIT_USAGE_ERROR
|
||||
end
|
||||
|
@ -157,11 +179,12 @@ module InspecPlugins
|
|||
|
||||
if status.installation_type == :path
|
||||
ui.bold(plugin_name + " path-based plugin install has been " \
|
||||
"uninstalled")
|
||||
"uninstalled\n")
|
||||
else
|
||||
ui.bold(plugin_name + " plugin, version #{old_version}, has " \
|
||||
"been uninstalled")
|
||||
"been uninstalled\n")
|
||||
end
|
||||
|
||||
ui.exit Inspec::UI::EXIT_NORMAL
|
||||
end
|
||||
|
||||
|
@ -174,7 +197,7 @@ module InspecPlugins
|
|||
|
||||
def install_from_gemfile(gem_file)
|
||||
unless File.exist? gem_file
|
||||
ui.red("No such plugin gem file #{gem_file} - installation failed.")
|
||||
ui.red("No such plugin gem file #{gem_file} - installation failed.\n")
|
||||
ui.exit Inspec::UI::EXIT_USAGE_ERROR
|
||||
end
|
||||
|
||||
|
@ -186,13 +209,13 @@ module InspecPlugins
|
|||
installer.install(plugin_name, gem_file: gem_file)
|
||||
|
||||
ui.bold("#{plugin_name} plugin, version #{version}, installed from " \
|
||||
"local .gem file")
|
||||
"local .gem file\n")
|
||||
ui.exit Inspec::UI::EXIT_NORMAL
|
||||
end
|
||||
|
||||
def install_from_path(path)
|
||||
unless File.exist? path
|
||||
ui.red("No such source code path #{path} - installation failed.")
|
||||
ui.red("No such source code path #{path} - installation failed.\n")
|
||||
ui.exit Inspec::UI::EXIT_USAGE_ERROR
|
||||
end
|
||||
|
||||
|
@ -209,7 +232,7 @@ module InspecPlugins
|
|||
if registry.known_plugin?(plugin_name.to_sym)
|
||||
ui.red("Plugin already installed - #{plugin_name} - Use '#{EXEC_NAME} " \
|
||||
"plugin list' to see previously installed plugin - " \
|
||||
"installation failed.")
|
||||
"installation failed.\n")
|
||||
ui.exit Inspec::UI::EXIT_PLUGIN_ERROR
|
||||
end
|
||||
|
||||
|
@ -223,7 +246,7 @@ module InspecPlugins
|
|||
installer.install(plugin_name, path: entry_point)
|
||||
|
||||
ui.bold("#{plugin_name} plugin installed via source path reference, " \
|
||||
"resolved to entry point #{entry_point}")
|
||||
"resolved to entry point #{entry_point}\n")
|
||||
ui.exit Inspec::UI::EXIT_NORMAL
|
||||
end
|
||||
|
||||
|
@ -288,7 +311,7 @@ module InspecPlugins
|
|||
# Give up.
|
||||
ui.red("Unrecognizable plugin structure - #{parts[2]} - When " \
|
||||
"installing from a path, please provide the path of the " \
|
||||
"entry point file - installation failed.")
|
||||
"entry point file - installation failed.\n")
|
||||
ui.exit Inspec::UI::EXIT_USAGE_ERROR
|
||||
end
|
||||
|
||||
|
@ -299,8 +322,8 @@ module InspecPlugins
|
|||
rescue LoadError => ex
|
||||
ui.red("Plugin contains errors - #{plugin_name} - Encountered " \
|
||||
"errors while trying to test load the plugin entry point, " \
|
||||
"resolved to #{entry_point} - installation failed")
|
||||
ui.plain ex.message
|
||||
"resolved to #{entry_point} - installation failed\n")
|
||||
ui.plain_line ex.message
|
||||
ui.exit Inspec::UI::EXIT_USAGE_ERROR
|
||||
end
|
||||
|
||||
|
@ -313,7 +336,7 @@ module InspecPlugins
|
|||
ui.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.")
|
||||
"'Train.plugin(1)' - installation failed.\n")
|
||||
ui.exit Inspec::UI::EXIT_USAGE_ERROR
|
||||
end
|
||||
else
|
||||
|
@ -321,7 +344,7 @@ module InspecPlugins
|
|||
ui.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.")
|
||||
"'Inspec.plugin(2)' - installation failed.\n")
|
||||
ui.exit Inspec::UI::EXIT_USAGE_ERROR
|
||||
end
|
||||
end
|
||||
|
@ -343,7 +366,7 @@ module InspecPlugins
|
|||
new_version = (post_installed_versions - pre_installed_versions).first
|
||||
|
||||
ui.bold("#{plugin_name} plugin, version #{new_version}, installed " \
|
||||
"from rubygems.org")
|
||||
"from rubygems.org\n")
|
||||
ui.exit Inspec::UI::EXIT_NORMAL
|
||||
end
|
||||
|
||||
|
@ -367,16 +390,16 @@ module InspecPlugins
|
|||
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
|
||||
ui.red("Plugin already installed at requested version - plugin " \
|
||||
"#{plugin_name} #{requested_version} - refusing to install.")
|
||||
"#{plugin_name} #{requested_version} - refusing to install.\n")
|
||||
elsif what_we_would_install_is_already_installed && !they_explicitly_asked_for_a_version
|
||||
ui.red("Plugin already installed at latest version - plugin " \
|
||||
"#{plugin_name} #{requested_version} - refusing to install.")
|
||||
"#{plugin_name} #{requested_version} - refusing to install.\n")
|
||||
else
|
||||
# There are existing versions installed, but none of them are what was requested
|
||||
ui.red("Update required - plugin #{plugin_name}, requested " \
|
||||
"#{requested_version}, have " \
|
||||
"#{pre_installed_versions.join(", ")}; use `inspec " \
|
||||
"plugin update` - refusing to install.")
|
||||
"plugin update` - refusing to install.\n")
|
||||
end
|
||||
|
||||
ui.exit Inspec::UI::EXIT_PLUGIN_ERROR
|
||||
|
@ -387,11 +410,11 @@ module InspecPlugins
|
|||
installer.install(plugin_name, version: options[:version])
|
||||
rescue Inspec::Plugin::V2::PluginExcludedError => ex
|
||||
ui.red("Plugin on Exclusion List - #{plugin_name} is listed as an " \
|
||||
"incompatible gem - refusing to install.")
|
||||
ui.plain("Rationale: #{ex.details.rationale}")
|
||||
ui.plain("Exclusion list location: " +
|
||||
"incompatible gem - refusing to install.\n")
|
||||
ui.plain_line("Rationale: #{ex.details.rationale}")
|
||||
ui.plain_line("Exclusion list location: " +
|
||||
File.join(Inspec.src_root, "etc", "plugin_filters.json"))
|
||||
ui.plain("If you disagree with this determination, please accept " \
|
||||
ui.plain_line("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 Inspec::UI::EXIT_PLUGIN_ERROR
|
||||
|
@ -401,13 +424,13 @@ module InspecPlugins
|
|||
results = installer.search(plugin_name, exact: true)
|
||||
if results.empty?
|
||||
ui.red("No such plugin gem #{plugin_name} could be found on " \
|
||||
"rubygems.org - installation failed.")
|
||||
"rubygems.org - installation failed.\n")
|
||||
elsif options[:version] && !results[plugin_name].include?(options[:version])
|
||||
ui.red("No such version - #{plugin_name} exists, but no such " \
|
||||
"version #{options[:version]} found on rubygems.org - " \
|
||||
"installation failed.")
|
||||
"installation failed.\n")
|
||||
else
|
||||
ui.red("Unknown error occured - installation failed.")
|
||||
ui.red("Unknown error occured - installation failed.\n")
|
||||
end
|
||||
ui.exit Inspec::UI::EXIT_USAGE_ERROR
|
||||
end
|
||||
|
@ -420,10 +443,10 @@ module InspecPlugins
|
|||
# Check for path install
|
||||
status = Inspec::Plugin::V2::Registry.instance[plugin_name.to_sym]
|
||||
if !status
|
||||
ui.plain("#{ui.red("No such plugin installed:")} #{plugin_name} - update failed")
|
||||
ui.plain_line("#{ui.red("No such plugin installed:", print: false)} #{plugin_name} - update failed")
|
||||
ui.exit Inspec::UI::EXIT_USAGE_ERROR
|
||||
elsif status.installation_type == :path
|
||||
ui.plain("#{ui.red("Cannot update path-based install:")} " \
|
||||
ui.plain_line("#{ui.red("Cannot update path-based install:", print: false)} " \
|
||||
"#{plugin_name} is installed via path reference; " \
|
||||
"use `inspec plugin uninstall` to remove - refusing to" \
|
||||
"update")
|
||||
|
@ -436,7 +459,7 @@ module InspecPlugins
|
|||
latest_version = latest_version[plugin_name]&.last
|
||||
|
||||
if pre_update_versions.include?(latest_version)
|
||||
ui.plain("#{ui.red("Already installed at latest version:")} " \
|
||||
ui.plain_line("#{ui.red("Already installed at latest version:", print: false)} " \
|
||||
"#{plugin_name} is at #{latest_version}, which the " \
|
||||
"latest - refusing to update")
|
||||
ui.exit Inspec::UI::EXIT_PLUGIN_ERROR
|
||||
|
@ -458,7 +481,7 @@ module InspecPlugins
|
|||
unless plugin_name =~ /^(inspec|train)-/
|
||||
ui.red("Invalid plugin name - #{plugin_name} - All inspec " \
|
||||
"plugins must begin with either 'inspec-' or 'train-' " \
|
||||
"- #{action} failed.")
|
||||
"- #{action} failed.\n")
|
||||
ui.exit Inspec::UI::EXIT_USAGE_ERROR
|
||||
end
|
||||
end
|
||||
|
@ -467,17 +490,29 @@ module InspecPlugins
|
|||
case status.installation_type
|
||||
when :core, :bundle
|
||||
Inspec::VERSION
|
||||
when :gem
|
||||
when :user_gem, :system_gem
|
||||
if status.version.nil?
|
||||
"(unknown)"
|
||||
elsif status.version =~ /^\d+\.\d+\.\d+$/
|
||||
status.version
|
||||
else
|
||||
# Assume it is a version constraint string and try to resolve
|
||||
# TODO: this is naive, and assumes the latest version is the one that will be used. Logged on #3317
|
||||
# In fact, the logic to determine "what version would be used" belongs in the Loader.
|
||||
plugin_name = status.name.to_s
|
||||
Inspec::Plugin::V2::Loader.list_installed_plugin_gems
|
||||
.select { |spec| spec.name == status.name.to_s }
|
||||
.select { |spec| spec.name == plugin_name }
|
||||
.sort_by(&:version)
|
||||
.last.version
|
||||
end
|
||||
when :path
|
||||
"src"
|
||||
end
|
||||
end
|
||||
|
||||
def make_pretty_install_type(status)
|
||||
INSTALL_TYPE_LABELS[status.installation_type]
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
|
@ -15,7 +15,9 @@ module PluginManagerHelpers
|
|||
let(:list_after_run) do
|
||||
Proc.new do |run_result, tmp_dir|
|
||||
# After installing/uninstalling/whatevering, run list with config in the same dir, and capture it.
|
||||
run_result.payload.list_result = run_inspec_process("plugin list", env: { INSPEC_CONFIG_DIR: tmp_dir })
|
||||
run_result.payload.list_result = parse_plugin_list_lines(
|
||||
run_inspec_process("plugin list", env: { INSPEC_CONFIG_DIR: tmp_dir }).stdout
|
||||
)
|
||||
end
|
||||
end
|
||||
|
||||
|
@ -39,6 +41,27 @@ module PluginManagerHelpers
|
|||
end
|
||||
end
|
||||
|
||||
def parse_plugin_list_lines(stdout)
|
||||
plugins = []
|
||||
|
||||
stdout.force_encoding("UTF-8").lines.each do |line|
|
||||
next if line.strip.empty?
|
||||
next if line.include? "─────" # This is some unicode glyphiness
|
||||
next if line.include? "Plugin Name"
|
||||
next if line.include? "plugin(s) total"
|
||||
|
||||
parts = line.split(/│/u).map(&:strip!).compact
|
||||
plugins << {
|
||||
name: parts[0],
|
||||
version: parts[1],
|
||||
type: parts[2],
|
||||
generation: parts[3],
|
||||
raw: line,
|
||||
}
|
||||
end
|
||||
plugins
|
||||
end
|
||||
|
||||
def teardown
|
||||
clear_empty_config_dir
|
||||
end
|
||||
|
@ -76,32 +99,42 @@ class PluginManagerCliList < Minitest::Test
|
|||
include CorePluginFunctionalHelper
|
||||
include PluginManagerHelpers
|
||||
|
||||
def test_list_when_no_user_plugins_installed
|
||||
result = run_inspec_process_with_this_plugin("plugin list")
|
||||
|
||||
skip_windows!
|
||||
assert_includes result.stdout, "0 plugin(s) total", "Empty list should include zero count"
|
||||
|
||||
assert_exit_code 0, result
|
||||
end
|
||||
# Listing all plugins is now default behavior
|
||||
LIST_CASES = [
|
||||
{ arg: "-c", name: "inspec-plugin-manager-cli", type: "core" },
|
||||
{ arg: "-c", name: "inspec-supermarket", type: "core" },
|
||||
{ arg: "-s", name: "train-aws", type: "gem (system)" },
|
||||
].freeze
|
||||
|
||||
def test_list_all_when_no_user_plugins_installed
|
||||
result = run_inspec_process_with_this_plugin("plugin list --all")
|
||||
|
||||
skip_windows!
|
||||
assert_includes result.stdout, "6 plugin(s) total", "--all list should find six"
|
||||
assert_includes result.stdout, "inspec-plugin-manager-cli", "--all list should find inspec-plugin-manager-cli"
|
||||
assert_includes result.stdout, "habitat", "--all list should find habitat"
|
||||
assert_empty result.stderr
|
||||
|
||||
plugins_seen = parse_plugin_list_lines(result.stdout)
|
||||
|
||||
# Look for a specific plugin of each type - core, bundle, and system
|
||||
LIST_CASES.each do |test_case|
|
||||
plugin_line = plugins_seen.detect { |plugin| plugin[:name] == test_case[:name] }
|
||||
refute_nil plugin_line, "#{test_case[:name]} should be detected in plugin list --all output"
|
||||
assert_equal test_case[:type], plugin_line[:type], "#{test_case[:name]} should be detected as a '#{test_case[:type]}' type in list --all "
|
||||
end
|
||||
assert_exit_code 0, result
|
||||
end
|
||||
|
||||
# TODO: split
|
||||
result = run_inspec_process_with_this_plugin("plugin list -a")
|
||||
|
||||
assert_includes result.stdout, "6 plugin(s) total", "-a list should find six"
|
||||
def test_list_selective_when_no_user_plugins_installed
|
||||
LIST_CASES.each do |test_case|
|
||||
result = run_inspec_process_with_this_plugin("plugin list #{test_case[:arg]}")
|
||||
skip_windows!
|
||||
|
||||
assert_empty result.stderr
|
||||
plugins_seen = parse_plugin_list_lines(result.stdout)
|
||||
plugin_line = plugins_seen.detect { |plugin| plugin[:name] == test_case[:name] }
|
||||
refute_nil plugin_line, "#{test_case[:name]} should be detected in plugin list #{test_case[:arg]} output"
|
||||
assert_equal plugin_line[:type], test_case[:type], "#{test_case[:name]} should be detected as a '#{test_case[:type]}' type in list #{test_case[:arg]} "
|
||||
assert_exit_code 0, result
|
||||
end
|
||||
end
|
||||
|
||||
def test_list_when_gem_and_path_plugins_installed
|
||||
pre_block = Proc.new do |plugin_statefile_data, tmp_dir|
|
||||
|
@ -109,21 +142,26 @@ class PluginManagerCliList < Minitest::Test
|
|||
copy_in_core_config_dir("test-fixture-1-float", tmp_dir)
|
||||
end
|
||||
|
||||
result = run_inspec_process_with_this_plugin("plugin list", pre_run: pre_block)
|
||||
|
||||
result = run_inspec_process_with_this_plugin("plugin list --user ", pre_run: pre_block)
|
||||
skip_windows!
|
||||
assert_includes result.stdout, "2 plugin(s) total", "gem+path should show two plugins"
|
||||
|
||||
assert_empty result.stderr
|
||||
plugins_seen = parse_plugin_list_lines(result.stdout)
|
||||
assert_equal 2, plugins_seen.count
|
||||
# Plugin Name Version Via ApiVer
|
||||
# -------------------------------------------------------
|
||||
# ---------------------------------------------------------
|
||||
# inspec-meaning-of-life src path 2
|
||||
# inspec-test-fixture 0.1.0 gem 2
|
||||
# -------------------------------------------------------
|
||||
# inspec-test-fixture 0.1.0 gem (user) 2
|
||||
# ---------------------------------------------------------
|
||||
# 2 plugin(s) total
|
||||
gem_line = result.stdout.split("\n").grep(/gem/).first
|
||||
assert_match(/\s*inspec-\S+\s+\d+\.\d+\.\d+\s+gem\s+2/, gem_line)
|
||||
path_line = result.stdout.split("\n").grep(/path/).first
|
||||
assert_match(/\s*inspec-\S+\s+src\s+path\s+2/, path_line)
|
||||
meaning = plugins_seen.detect { |p| p[:name] == "inspec-meaning-of-life" }
|
||||
refute_nil meaning
|
||||
assert_equal "path", meaning[:type]
|
||||
|
||||
fixture = plugins_seen.detect { |p| p[:name] == "inspec-test-fixture" }
|
||||
refute_nil fixture
|
||||
assert_equal "gem (user)", fixture[:type]
|
||||
assert_equal "0.1.0", fixture[:version]
|
||||
|
||||
assert_exit_code 0, result
|
||||
end
|
||||
|
@ -134,21 +172,24 @@ class PluginManagerCliList < Minitest::Test
|
|||
copy_in_core_config_dir("train-test-fixture", tmp_dir)
|
||||
end
|
||||
|
||||
result = run_inspec_process_with_this_plugin("plugin list", pre_run: pre_block)
|
||||
|
||||
result = run_inspec_process_with_this_plugin("plugin list --user ", pre_run: pre_block)
|
||||
skip_windows!
|
||||
|
||||
assert_empty result.stderr
|
||||
plugins_seen = parse_plugin_list_lines(result.stdout)
|
||||
assert_equal 1, plugins_seen.count
|
||||
assert_includes result.stdout, "1 plugin(s) total", "list train should show one plugins"
|
||||
|
||||
# Plugin Name Version Via ApiVer
|
||||
# -------------------------------------------------------
|
||||
# train-test-fixture 0.1.0 gem train-1
|
||||
# -------------------------------------------------------
|
||||
# -------------------------------------------------------------
|
||||
# train-test-fixture 0.1.0 gem (user) train-1
|
||||
# -------------------------------------------------------------
|
||||
# 1 plugin(s) total
|
||||
train_line = result.stdout.split("\n").grep(/train/).first
|
||||
assert_includes(train_line, "train-test-fixture")
|
||||
assert_includes(train_line, "0.1.0")
|
||||
assert_includes(train_line, "gem")
|
||||
assert_includes(train_line, "train-1")
|
||||
train_plugin = plugins_seen.detect { |p| p[:name] == "train-test-fixture" }
|
||||
refute_nil train_plugin
|
||||
assert_equal "gem (user)", train_plugin[:type]
|
||||
assert_equal "train-1", train_plugin[:generation]
|
||||
assert_equal "0.1.0", train_plugin[:version]
|
||||
|
||||
assert_exit_code 0, result
|
||||
end
|
||||
|
@ -333,23 +374,21 @@ class PluginManagerCliInstall < Minitest::Test
|
|||
# Check UX messaging
|
||||
success_message = install_result.stdout.split("\n").grep(/installed/).last
|
||||
skip_windows!
|
||||
assert_empty install_result.stderr
|
||||
refute_nil success_message, "Should find a success message at the end"
|
||||
assert_includes success_message, fixture_info[:plugin_name]
|
||||
assert_includes success_message, "plugin installed via source path reference"
|
||||
|
||||
# Check round-trip UX via list
|
||||
list_result = install_result.payload.list_result
|
||||
itf_line = list_result.stdout.split("\n").grep(Regexp.new(fixture_info[:plugin_name])).first
|
||||
refute_nil itf_line, "plugin name should now appear in the output of inspec list"
|
||||
assert_match(/\s*(inspec|train)-test-fixture\s+src\s+path\s+/, itf_line, "list output should show that it is a path installation")
|
||||
itf_plugin = install_result.payload.list_result.detect { |p| p[:name] == fixture_info[:plugin_name] }
|
||||
refute_nil itf_plugin, "plugin name should now appear in the output of inspec list"
|
||||
assert_equal "path", itf_plugin[:type], "list output should show that it is a path installation"
|
||||
|
||||
# Check plugin statefile. Extra important in this case, since all should resolve to the same entry point.
|
||||
plugin_data = install_result.payload.plugin_data
|
||||
entry = plugin_data["plugins"].detect { |e| e["name"] == fixture_info[:plugin_name] }
|
||||
assert_equal fixture_info[:resolved_path], entry["installation_path"], "Regardless of input, the entry point should be correct."
|
||||
|
||||
assert_empty install_result.stderr
|
||||
|
||||
assert_exit_code 0, install_result
|
||||
end
|
||||
end
|
||||
|
@ -357,9 +396,9 @@ class PluginManagerCliInstall < Minitest::Test
|
|||
def test_fail_install_from_nonexistant_path
|
||||
bad_path = File.join(project_fixtures_path, "none", "such", "inspec-test-fixture-nonesuch.rb")
|
||||
install_result = run_inspec_process_with_this_plugin("plugin install #{bad_path}")
|
||||
|
||||
error_message = install_result.stdout.split("\n").last
|
||||
skip_windows!
|
||||
|
||||
error_message = install_result.stdout
|
||||
assert_includes error_message, "No such source code path"
|
||||
assert_includes error_message, "inspec-test-fixture-nonesuch.rb"
|
||||
assert_includes error_message, "installation failed"
|
||||
|
@ -372,9 +411,9 @@ class PluginManagerCliInstall < Minitest::Test
|
|||
def test_fail_install_from_path_with_wrong_name
|
||||
bad_path = File.join(project_fixtures_path, "plugins", "wrong-name", "lib", "wrong-name.rb")
|
||||
install_result = run_inspec_process_with_this_plugin("plugin install #{bad_path}")
|
||||
|
||||
error_message = install_result.stdout.split("\n").last
|
||||
skip_windows!
|
||||
|
||||
error_message = install_result.stdout
|
||||
assert_includes error_message, "Invalid plugin name"
|
||||
assert_includes error_message, "wrong-name"
|
||||
assert_includes error_message, "All inspec plugins must begin with either 'inspec-' or 'train-'"
|
||||
|
@ -388,9 +427,9 @@ class PluginManagerCliInstall < Minitest::Test
|
|||
def test_fail_install_from_path_when_it_is_not_a_plugin
|
||||
bad_path = File.join(project_fixtures_path, "plugins", "inspec-egg-white-omelette", "lib", "inspec-egg-white-omelette.rb")
|
||||
install_result = run_inspec_process_with_this_plugin("plugin install #{bad_path}")
|
||||
|
||||
error_message = install_result.stdout.split("\n").last
|
||||
skip_windows!
|
||||
|
||||
error_message = install_result.stdout
|
||||
assert_includes error_message, "Does not appear to be a plugin"
|
||||
assert_includes error_message, "inspec-egg-white-omelette"
|
||||
assert_includes error_message, "After probe-loading the supposed plugin, it did not register"
|
||||
|
@ -413,9 +452,9 @@ class PluginManagerCliInstall < Minitest::Test
|
|||
end
|
||||
|
||||
install_result = run_inspec_process_with_this_plugin("plugin install #{plugin_path}", pre_run: pre_block)
|
||||
|
||||
error_message = install_result.stdout.split("\n").last
|
||||
skip_windows!
|
||||
|
||||
error_message = install_result.stdout
|
||||
assert_includes error_message, "Plugin already installed"
|
||||
assert_includes error_message, "inspec-test-fixture"
|
||||
assert_includes error_message, "Use 'inspec plugin list' to see previously installed plugin"
|
||||
|
@ -429,9 +468,9 @@ class PluginManagerCliInstall < Minitest::Test
|
|||
def test_fail_install_from_path_when_the_dir_structure_is_wrong
|
||||
bad_path = File.join(project_fixtures_path, "plugins", "inspec-wrong-structure")
|
||||
install_result = run_inspec_process_with_this_plugin("plugin install #{bad_path}")
|
||||
|
||||
error_message = install_result.stdout.split("\n").last
|
||||
skip_windows!
|
||||
|
||||
error_message = install_result.stdout
|
||||
assert_includes error_message, "Unrecognizable plugin structure"
|
||||
assert_includes error_message, "inspec-wrong-structure"
|
||||
assert_includes error_message, " When installing from a path, please provide the path of the entry point file"
|
||||
|
@ -445,21 +484,18 @@ class PluginManagerCliInstall < Minitest::Test
|
|||
def test_install_from_gemfile
|
||||
fixture_gemfile_path = File.join(core_fixture_plugins_path, "inspec-test-fixture", "pkg", "inspec-test-fixture-0.1.0.gem")
|
||||
install_result = run_inspec_process_with_this_plugin("plugin install #{fixture_gemfile_path}", post_run: list_after_run)
|
||||
skip_windows!
|
||||
|
||||
success_message = install_result.stdout.split("\n").grep(/installed/).last
|
||||
skip_windows!
|
||||
refute_nil success_message, "Should find a success message at the end"
|
||||
assert_includes success_message, "inspec-test-fixture"
|
||||
assert_includes success_message, "0.1.0"
|
||||
assert_includes success_message, "installed from local .gem file"
|
||||
|
||||
list_result = install_result.payload.list_result
|
||||
itf_line = list_result.stdout.split("\n").grep(/inspec-test-fixture/).first
|
||||
refute_nil itf_line, "inspec-test-fixture should now appear in the output of inspec list"
|
||||
assert_match(/\s*inspec-test-fixture\s+0.1.0\s+gem\s+/, itf_line, "list output should show that it is a gem installation with version")
|
||||
itf_plugin = install_result.payload.list_result.detect { |p| p[:name] == "inspec-test-fixture" }
|
||||
refute_nil itf_plugin, "plugin name should now appear in the output of inspec list"
|
||||
assert_equal "gem (user)", itf_plugin[:type]
|
||||
assert_equal "0.1.0", itf_plugin[:version]
|
||||
|
||||
assert_empty install_result.stderr
|
||||
|
||||
assert_exit_code 0, install_result
|
||||
end
|
||||
|
||||
|
@ -477,21 +513,20 @@ class PluginManagerCliInstall < Minitest::Test
|
|||
|
||||
def test_install_from_rubygems_latest
|
||||
install_result = run_inspec_process_with_this_plugin("plugin install inspec-test-fixture", post_run: list_after_run)
|
||||
skip_windows!
|
||||
|
||||
success_message = install_result.stdout.split("\n").grep(/installed/).last
|
||||
skip_windows!
|
||||
refute_nil success_message, "Should find a success message at the end"
|
||||
assert_includes success_message, "inspec-test-fixture"
|
||||
assert_includes success_message, "0.2.0"
|
||||
assert_includes success_message, "installed from rubygems.org"
|
||||
|
||||
list_result = install_result.payload.list_result
|
||||
itf_line = list_result.stdout.split("\n").grep(/inspec-test-fixture/).first
|
||||
refute_nil itf_line, "inspec-test-fixture should now appear in the output of inspec list"
|
||||
assert_match(/\s*inspec-test-fixture\s+0.2.0\s+gem\s+/, itf_line, "list output should show that it is a gem installation with version")
|
||||
itf_plugin = install_result.payload.list_result.detect { |p| p[:name] == "inspec-test-fixture" }
|
||||
refute_nil itf_plugin, "plugin name should now appear in the output of inspec list"
|
||||
assert_equal "gem (user)", itf_plugin[:type]
|
||||
assert_equal "0.2.0", itf_plugin[:version]
|
||||
|
||||
assert_empty install_result.stderr
|
||||
|
||||
assert_exit_code 0, install_result
|
||||
end
|
||||
|
||||
|
@ -516,10 +551,10 @@ class PluginManagerCliInstall < Minitest::Test
|
|||
assert_includes success_message, "0.1.0"
|
||||
assert_includes success_message, "installed from rubygems.org"
|
||||
|
||||
list_result = install_result.payload.list_result
|
||||
itf_line = list_result.stdout.split("\n").grep(/inspec-test-fixture/).first
|
||||
refute_nil itf_line, "inspec-test-fixture should now appear in the output of inspec list"
|
||||
assert_match(/\s*inspec-test-fixture\s+0.1.0\s+gem\s+/, itf_line, "list output should show that it is a gem installation with version")
|
||||
itf_plugin = install_result.payload.list_result.detect { |p| p[:name] == "inspec-test-fixture" }
|
||||
refute_nil itf_plugin, "plugin name should now appear in the output of inspec list"
|
||||
assert_equal "gem (user)", itf_plugin[:type]
|
||||
assert_equal "0.1.0", itf_plugin[:version]
|
||||
|
||||
assert_empty install_result.stderr
|
||||
|
||||
|
@ -600,21 +635,20 @@ class PluginManagerCliInstall < Minitest::Test
|
|||
|
||||
def test_install_from_rubygems_latest_with_train_plugin
|
||||
install_result = run_inspec_process_with_this_plugin("plugin install train-test-fixture", post_run: list_after_run)
|
||||
skip_windows!
|
||||
|
||||
success_message = install_result.stdout.split("\n").grep(/installed/).last
|
||||
skip_windows!
|
||||
refute_nil success_message, "Should find a success message at the end"
|
||||
assert_includes success_message, "train-test-fixture"
|
||||
assert_includes success_message, "0.1.0"
|
||||
assert_includes success_message, "installed from rubygems.org"
|
||||
|
||||
list_result = install_result.payload.list_result
|
||||
itf_line = list_result.stdout.split("\n").grep(/train-test-fixture/).first
|
||||
refute_nil itf_line, "train-test-fixture should now appear in the output of inspec list"
|
||||
assert_match(/\s*train-test-fixture\s+0.1.0\s+gem\s+/, itf_line, "list output should show that it is a gem installation with version")
|
||||
ttf_plugin = install_result.payload.list_result.detect { |p| p[:name] == "train-test-fixture" }
|
||||
refute_nil ttf_plugin, "plugin name should now appear in the output of inspec list"
|
||||
assert_equal "gem (user)", ttf_plugin[:type]
|
||||
assert_equal "0.1.0", ttf_plugin[:version]
|
||||
|
||||
assert_empty install_result.stderr
|
||||
|
||||
assert_exit_code 0, install_result
|
||||
end
|
||||
|
||||
|
@ -649,8 +683,8 @@ class PluginManagerCliInstall < Minitest::Test
|
|||
skip "this test requires bundler to pass" unless defined? ::Bundler
|
||||
|
||||
install_result = run_inspec_process_with_this_plugin("plugin install inspec-test-fixture -v 0.1.1 --log-level debug")
|
||||
|
||||
skip_windows!
|
||||
|
||||
assert_includes install_result.stdout, "DEBUG"
|
||||
|
||||
assert_includes install_result.stderr, "can't activate rake"
|
||||
|
@ -684,13 +718,12 @@ class PluginManagerCliUpdate < Minitest::Test
|
|||
assert_includes success_message, "0.2.0"
|
||||
assert_includes success_message, "updated from rubygems.org"
|
||||
|
||||
list_result = update_result.payload.list_result
|
||||
itf_line = list_result.stdout.split("\n").grep(/inspec-test-fixture/).first
|
||||
refute_nil itf_line, "inspec-test-fixture should appear in the output of inspec list"
|
||||
assert_match(/\s*inspec-test-fixture\s+0.2.0\s+gem\s+/, itf_line, "list output should show that it is a gem installation with version 0.2.0")
|
||||
itf_plugin = update_result.payload.list_result.detect { |p| p[:name] == "inspec-test-fixture" }
|
||||
refute_nil itf_plugin, "plugin name should now appear in the output of inspec list"
|
||||
assert_equal "gem (user)", itf_plugin[:type]
|
||||
assert_equal "0.2.0", itf_plugin[:version]
|
||||
|
||||
assert_empty update_result.stderr
|
||||
|
||||
assert_exit_code 0, update_result
|
||||
end
|
||||
|
||||
|
@ -769,12 +802,10 @@ class PluginManagerCliUninstall < Minitest::Test
|
|||
assert_includes success_message, "0.1.0"
|
||||
assert_includes success_message, "has been uninstalled"
|
||||
|
||||
list_result = uninstall_result.payload.list_result
|
||||
itf_line = list_result.stdout.split("\n").grep(/inspec-test-fixture/).first
|
||||
assert_nil itf_line, "inspec-test-fixture should not appear in the output of inspec list"
|
||||
itf_plugins = uninstall_result.payload.list_result.select { |p| p[:name] == "inspec-test-fixture" }
|
||||
assert_empty itf_plugins, "inspec-test-fixture should not appear in the output of inspec list"
|
||||
|
||||
assert_empty uninstall_result.stderr
|
||||
|
||||
assert_exit_code 0, uninstall_result
|
||||
end
|
||||
|
||||
|
@ -784,22 +815,19 @@ class PluginManagerCliUninstall < Minitest::Test
|
|||
# This fixture includes a path install for inspec-meaning-of-life
|
||||
copy_in_core_config_dir("test-fixture-1-float", tmp_dir)
|
||||
end
|
||||
|
||||
uninstall_result = run_inspec_process_with_this_plugin("plugin uninstall inspec-meaning-of-life", pre_run: pre_block, post_run: list_after_run)
|
||||
skip_windows!
|
||||
|
||||
success_message = uninstall_result.stdout.split("\n").grep(/uninstalled/).last
|
||||
skip_windows!
|
||||
refute_nil success_message, "Should find a success message at the end"
|
||||
assert_includes success_message, "inspec-meaning-of-life"
|
||||
assert_includes success_message, "path-based plugin install"
|
||||
assert_includes success_message, "has been uninstalled"
|
||||
|
||||
list_result = uninstall_result.payload.list_result
|
||||
itf_line = list_result.stdout.split("\n").grep(/inspec-meaning-of-life/).first
|
||||
assert_nil itf_line, "inspec-meaning-of-life should not appear in the output of inspec list"
|
||||
itf_plugins = uninstall_result.payload.list_result.select { |p| p[:name] == "inspec-meaning-of-life" }
|
||||
assert_empty itf_plugins, "inspec-meaning-of-life should not appear in the output of inspec list"
|
||||
|
||||
assert_empty uninstall_result.stderr
|
||||
|
||||
assert_exit_code 0, uninstall_result
|
||||
end
|
||||
|
||||
|
|
|
@ -13,13 +13,15 @@ class PluginManagerCliOptions < Minitest::Test
|
|||
|
||||
def test_list_args
|
||||
arg_config = cli_class.all_commands["list"].options
|
||||
assert_equal 1, arg_config.count, "The list command should have 1 option"
|
||||
assert_equal 4, arg_config.count, "The list command should have 4 options"
|
||||
|
||||
assert_includes arg_config.keys, :all, "The list command should have an --all option"
|
||||
assert_equal :boolean, arg_config[:all].type, "The --all option should be boolean"
|
||||
assert_equal :a, arg_config[:all].aliases.first, "The --all option should be aliased as -a"
|
||||
refute_nil arg_config[:all].description, "The --all option should have a description"
|
||||
refute arg_config[:all].required, "The --all option should not be required"
|
||||
{ u: :user, a: :all, c: :core, s: :system }.each do |abbrev, option|
|
||||
assert_includes arg_config.keys, option, "The list command should have an --#{option} option"
|
||||
assert_equal :boolean, arg_config[option].type, "The --#{option} option should be boolean"
|
||||
assert_equal abbrev, arg_config[option].aliases.first, "The --#{option} option should be aliased as -#{abbrev}"
|
||||
refute_nil arg_config[option].description, "The --#{option} option should have a description"
|
||||
refute arg_config[option].required, "The --#{option} option should not be required"
|
||||
end
|
||||
|
||||
assert_equal 0, cli_class.instance_method(:list).arity, "The list command should take no arguments"
|
||||
end
|
||||
|
|
|
@ -2,7 +2,8 @@
|
|||
"plugins_config_version" : "1.0.0",
|
||||
"plugins": [
|
||||
{
|
||||
"name": "inspec-test-fixture"
|
||||
"name": "inspec-test-fixture",
|
||||
"version": "0.1.0"
|
||||
},
|
||||
{
|
||||
"name": "inspec-meaning-of-life",
|
||||
|
|
|
@ -2,7 +2,8 @@
|
|||
"plugins_config_version" : "1.0.0",
|
||||
"plugins": [
|
||||
{
|
||||
"name": "train-test-fixture"
|
||||
"name": "train-test-fixture",
|
||||
"version": "0.1.0"
|
||||
}
|
||||
]
|
||||
}
|
|
@ -321,11 +321,11 @@ class PluginInstallerUpdaterTests < Minitest::Test
|
|||
spec_path = File.join(@installer.gem_path, "specifications", "inspec-test-fixture-0.1.0.gemspec")
|
||||
assert File.exist?(spec_path), "After update, the 0.1.0 gemspec should remain"
|
||||
|
||||
# Plugins file entry should not be version pinned
|
||||
# Plugins file entry should now be version pinned to latest
|
||||
plugin_json_path = File.join(ENV["INSPEC_CONFIG_DIR"], "plugins.json")
|
||||
plugin_json_data = JSON.parse(File.read(plugin_json_path))
|
||||
entry = plugin_json_data["plugins"].detect { |e| e["name"] == "inspec-test-fixture" }
|
||||
refute_includes entry.keys, "version", "plugins.json should NOT include version pinning key"
|
||||
assert_equal "= 0.2.0", entry["version"]
|
||||
end
|
||||
|
||||
def test_update_to_specified_later_version
|
||||
|
|
|
@ -28,6 +28,9 @@ class PluginLoaderTests < Minitest::Test
|
|||
inspec-habitat
|
||||
inspec-init
|
||||
}
|
||||
@system_plugins = [
|
||||
"train-habitat",
|
||||
]
|
||||
end
|
||||
|
||||
def teardown
|
||||
|
@ -42,12 +45,6 @@ class PluginLoaderTests < Minitest::Test
|
|||
# basic constructor usage and bundle detection #
|
||||
#====================================================================#
|
||||
|
||||
def test_constructor_should_not_load_anything_automatically
|
||||
reg = Inspec::Plugin::V2::Registry.instance
|
||||
Inspec::Plugin::V2::Loader.new
|
||||
assert_equal 0, reg.loaded_count, "\nRegistry load count"
|
||||
end
|
||||
|
||||
def test_constructor_should_detect_bundled_plugins
|
||||
reg = Inspec::Plugin::V2::Registry.instance
|
||||
Inspec::Plugin::V2::Loader.new
|
||||
|
@ -106,7 +103,7 @@ class PluginLoaderTests < Minitest::Test
|
|||
|
||||
def test_load_no_plugins_should_load_no_plugins
|
||||
reg = Inspec::Plugin::V2::Registry.instance
|
||||
loader = Inspec::Plugin::V2::Loader.new(omit_bundles: true, omit_core_plugins: true, omit_user_plugins: true)
|
||||
loader = Inspec::Plugin::V2::Loader.new(omit_bundles: true, omit_core_plugins: true, omit_user_plugins: true, omit_sys_plugins: true)
|
||||
loader.load_all
|
||||
assert_equal 0, reg.loaded_count, "\nRegistry load count"
|
||||
end
|
||||
|
|
Loading…
Reference in a new issue