inspec/lib/plugins/inspec-plugin-manager-cli/test/functional/inspec-plugin_test.rb
Jared Quick 970d2ec32b
Add debug and sort options for plugins (#3530)
* Add log options to plugin cli base.
* Sort search results to always show the latest.
* Add testing for debug logs
* Fix lint.

Signed-off-by: Jared Quick <jquick@chef.io>
2018-10-18 16:01:02 -04:00

713 lines
36 KiB
Ruby

#=========================================================================================#
# `inspec plugin SUBCOMMAND` facility
#=========================================================================================#
require_relative '../../../shared/core_plugin_test_helper.rb'
#-----------------------------------------------------------------------------------------#
# utilities
#-----------------------------------------------------------------------------------------#
module PluginManagerHelpers
let(:project_repo_path) { File.expand_path(File.join(__FILE__, '..', '..', '..')) }
let(:project_fixtures_path) { File.join(project_repo_path, 'test', 'fixtures') }
let(:project_config_dirs_path) { File.join(project_fixtures_path, 'config_dirs') }
let(:empty_config_dir_path) { File.join(project_config_dirs_path, 'empty') }
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 })
end
end
def copy_in_project_config_dir(fixture_name, dest = nil)
src = Dir.glob(File.join(project_config_dirs_path, fixture_name, '*'))
dest ||= File.join(project_config_dirs_path, 'empty')
src.each { |path| FileUtils.cp_r(path, dest) }
end
def copy_in_core_config_dir(fixture_name, dest = nil)
src = Dir.glob(File.join(core_config_dir_path, fixture_name, '*'))
dest ||= File.join(project_config_dirs_path, 'empty')
src.each { |path| FileUtils.cp_r(path, dest) }
end
def clear_empty_config_dir
Dir.glob(File.join(project_config_dirs_path, 'empty', '*')).each do |path|
next if path.end_with? '.gitkeep'
FileUtils.rm_rf(path)
end
end
def teardown
clear_empty_config_dir
end
end
#-----------------------------------------------------------------------------------------#
# inspec help
#-----------------------------------------------------------------------------------------#
class PluginManagerCliHelp < MiniTest::Test
include CorePluginFunctionalHelper
# Main inspec help subcommand listing
def test_inspec_help_includes_plugin
result = run_inspec_process_with_this_plugin('help')
assert_includes result.stdout, 'inspec plugin'
end
# inspec plugin help subcommand listing
def test_inspec_plugin_help_includes_plugin
result = run_inspec_process_with_this_plugin('plugin help')
assert_includes result.stdout, 'inspec plugin list'
assert_includes result.stdout, 'inspec plugin search'
assert_includes result.stdout, 'inspec plugin install'
assert_includes result.stdout, 'inspec plugin update'
assert_includes result.stdout, 'inspec plugin uninstall'
end
end
#-----------------------------------------------------------------------------------------#
# inspec plugin list
#-----------------------------------------------------------------------------------------#
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')
assert_equal 0, result.exit_status, 'exist status must be 0'
assert_includes result.stdout, '0 plugin(s) total', 'Empty list should include zero count'
end
def test_list_all_when_no_user_plugins_installed
result = run_inspec_process_with_this_plugin('plugin list --all')
assert_equal 0, result.exit_status, 'exist status must be 0'
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'
result = run_inspec_process_with_this_plugin('plugin list -a')
assert_equal 0, result.exit_status, 'exist status must be 0'
assert_includes result.stdout, '6 plugin(s) total', '-a list should find six'
end
def test_list_when_gem_and_path_plugins_installed
pre_block = Proc.new do |plugin_statefile_data, tmp_dir|
plugin_statefile_data.clear # Signal not to write a file, we'll provide one.
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)
assert_equal 0, result.exit_status, 'exist status must be 0'
assert_includes result.stdout, '2 plugin(s) total', 'gem+path should show two plugins'
# Plugin Name Version Via ApiVer
# -------------------------------------------------------
# inspec-meaning-of-life src path 2
# inspec-test-fixture 0.1.0 gem 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)
end
def test_list_when_a_train_plugin_is_installed
pre_block = Proc.new do |plugin_statefile_data, tmp_dir|
plugin_statefile_data.clear # Signal not to write a file, we'll provide one.
copy_in_core_config_dir('train-test-fixture', tmp_dir)
end
result = run_inspec_process_with_this_plugin('plugin list', pre_run: pre_block)
assert_equal 0, result.exit_status, 'exist status must be 0'
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
# -------------------------------------------------------
# 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')
end
end
#-----------------------------------------------------------------------------------------#
# inspec plugin search
#-----------------------------------------------------------------------------------------#
class PluginManagerCliSearch < MiniTest::Test
include CorePluginFunctionalHelper
include PluginManagerHelpers
# TODO: Thor can't hide options, but we wish it could.
# def test_search_include_fixture_hidden_option
# result = run_inspec_process_with_this_plugin('plugin help search')
# refute_includes result.stdout, '--include-test-fixture'
# end
def test_search_for_a_real_gem_with_full_name_no_options
result = run_inspec_process('plugin search --include-test-fixture inspec-test-fixture')
assert_equal 0, result.exit_status, 'Search should exit 0 on a hit'
assert_includes result.stdout, 'inspec-test-fixture', 'Search result should contain the gem name'
assert_includes result.stdout, '1 plugin(s) found', 'Search result should find 1 plugin'
line = result.stdout.split("\n").grep(/inspec-test-fixture/).first
assert_match(/\s*inspec-test-fixture\s+\((\d+\.\d+\.\d+){1}\)/,line,'Plugin line should include name and exactly one version')
end
def test_search_for_a_real_gem_with_stub_name_no_options
result = run_inspec_process('plugin search --include-test-fixture inspec-test-')
assert_equal 0, result.exit_status, 'Search should exit 0 on a hit'
assert_includes result.stdout, 'inspec-test-fixture', 'Search result should contain the gem name'
assert_includes result.stdout, '1 plugin(s) found', 'Search result should find 1 plugin'
line = result.stdout.split("\n").grep(/inspec-test-fixture/).first
assert_match(/\s*inspec-test-fixture\s+\((\d+\.\d+\.\d+){1}\)/,line,'Plugin line should include name and exactly one version')
end
def test_search_for_a_real_gem_with_full_name_and_exact_option
result = run_inspec_process('plugin search --exact --include-test-fixture inspec-test-fixture')
assert_equal 0, result.exit_status, 'Search should exit 0 on a hit'
assert_includes result.stdout, 'inspec-test-fixture', 'Search result should contain the gem name'
assert_includes result.stdout, '1 plugin(s) found', 'Search result should find 1 plugin'
result = run_inspec_process('plugin search -e --include-test-fixture inspec-test-fixture')
assert_equal 0, result.exit_status, 'Search should exit 0 on a hit'
end
def test_search_for_a_real_gem_with_stub_name_and_exact_option
result = run_inspec_process('plugin search --exact --include-test-fixture inspec-test-')
assert_equal 2, result.exit_status, 'Search should exit 2 on a miss'
assert_includes result.stdout, '0 plugin(s) found', 'Search result should find 0 plugins'
result = run_inspec_process('plugin search -e --include-test-fixture inspec-test-')
assert_equal 2, result.exit_status, 'Search should exit 2 on a miss'
end
def test_search_for_a_real_gem_with_full_name_and_all_option
result = run_inspec_process('plugin search --all --include-test-fixture inspec-test-fixture')
assert_equal 0, result.exit_status, 'Search should exit 0 on a hit'
assert_includes result.stdout, 'inspec-test-fixture', 'Search result should contain the gem name'
assert_includes result.stdout, '1 plugin(s) found', 'Search result should find 1 plugin'
line = result.stdout.split("\n").grep(/inspec-test-fixture/).first
assert_match(/\s*inspec-test-fixture\s+\((\d+\.\d+\.\d+(,\s)?){2,}\)/,line,'Plugin line should include name and at least two versions')
result = run_inspec_process('plugin search -a --include-test-fixture inspec-test-fixture')
assert_equal 0, result.exit_status, 'Search should exit 0 on a hit'
end
def test_search_for_a_gem_with_missing_prefix
result = run_inspec_process('plugin search --include-test-fixture test-fixture')
assert_equal 1, result.exit_status, 'Search should exit 1 on user error'
assert_includes result.stdout, "All inspec plugins must begin with either 'inspec-' or 'train-'"
end
def test_search_for_a_gem_that_does_not_exist
result = run_inspec_process('plugin search --include-test-fixture inspec-test-fixture-nonesuch')
assert_equal 2, result.exit_status, 'Search should exit 2 on a miss'
assert_includes result.stdout, '0 plugin(s) found', 'Search result should find 0 plugins'
end
def test_search_for_a_real_gem_with_full_name_no_options_and_train_name
result = run_inspec_process('plugin search --include-test-fixture train-test-fixture')
assert_equal 0, result.exit_status, 'Search should exit 0 on a hit'
assert_includes result.stdout, 'train-test-fixture', 'Search result should contain the gem name'
assert_includes result.stdout, '1 plugin(s) found', 'Search result should find 1 plugin'
line = result.stdout.split("\n").grep(/train-test-fixture/).first
assert_match(/\s*train-test-fixture\s+\((\d+\.\d+\.\d+){1}\)/,line,'Plugin line should include name and exactly one version')
end
def test_search_omit_excluded_inspec_plugins
result = run_inspec_process('plugin search --include-test-fixture inspec-')
assert_equal 0, result.exit_status, 'Search should exit 0'
assert_includes result.stdout, 'inspec-test-fixture', 'Search result should contain the test gem'
[
'inspec-core',
'inspec-multi-server',
].each do |plugin_name|
refute_includes result.stdout, plugin_name, 'Search result should not contain excluded gems'
end
end
def test_search_for_a_real_gem_with_full_name_no_options_filter_fixtures
result = run_inspec_process('plugin search inspec-test-fixture')
refute_includes result.stdout, 'inspec-test-fixture', 'Search result should not contain the fixture gem name'
end
def test_search_for_a_real_gem_with_full_name_no_options_filter_fixtures_train
result = run_inspec_process('plugin search train-test-fixture')
refute_includes result.stdout, 'train-test-fixture', 'Search result should not contain the fixture gem name'
end
end
#-----------------------------------------------------------------------------------------#
# inspec plugin install
#-----------------------------------------------------------------------------------------#
class PluginManagerCliInstall < MiniTest::Test
include CorePluginFunctionalHelper # gives us instance methods, like `let` aliases inside test methods
extend CorePluginFunctionalHelper # gives us class methods, like `let` aliases out here outside test methods
include PluginManagerHelpers
ruby_abi_version = (Gem.ruby_version.segments[0, 2] << 0).join('.')
# Test multiple hueristics of the path-mode install.
# These are all positive tests; they should resolve the entry point to the same path in each case.
{
'is_perfect' => {
given: File.join(core_fixture_plugins_path, 'inspec-test-fixture', 'lib', 'inspec-test-fixture.rb'),
},
'refers_to_the_entry_point_with_no_extension' => {
given: File.join(core_fixture_plugins_path, 'inspec-test-fixture', 'lib', 'inspec-test-fixture'),
},
'refers_to_the_src_root_of_a_plugin' => {
given: File.join(core_fixture_plugins_path, 'inspec-test-fixture'),
},
'refers_to_a_versioned_gem_install' => {
given: File.join(core_config_dir_path, 'test-fixture-1-float', 'gems', ruby_abi_version, 'gems', 'inspec-test-fixture-0.1.0', 'lib', 'inspec-test-fixture.rb'),
resolved_path: File.join(core_config_dir_path, 'test-fixture-1-float', 'gems', ruby_abi_version, 'gems', 'inspec-test-fixture-0.1.0', 'lib', 'inspec-test-fixture.rb'),
},
'refers_to_a_versioned_gem_install_missing_extension' => {
given: File.join(core_config_dir_path, 'test-fixture-1-float', 'gems', ruby_abi_version, 'gems', 'inspec-test-fixture-0.1.0', 'lib', 'inspec-test-fixture'),
resolved_path: File.join(core_config_dir_path, 'test-fixture-1-float', 'gems', ruby_abi_version, 'gems', 'inspec-test-fixture-0.1.0', 'lib', 'inspec-test-fixture.rb'),
},
'refers_to_a_relative_path' => {
given: File.join('test', 'unit', 'mock', 'plugins', 'inspec-test-fixture', 'lib', 'inspec-test-fixture.rb'),
},
'refers_to_a_train_plugin' => {
given: File.join(core_config_dir_path, 'train-test-fixture', 'gems', ruby_abi_version, 'gems', 'train-test-fixture-0.1.0', 'lib', 'train-test-fixture.rb'),
plugin_name: 'train-test-fixture',
resolved_path: File.join(core_config_dir_path, 'train-test-fixture', 'gems', ruby_abi_version, 'gems', 'train-test-fixture-0.1.0', 'lib', 'train-test-fixture.rb'),
},
}.each do |test_name, fixture_info|
define_method(('test_install_from_path_when_path_' + test_name).to_sym) do
fixture_info = {
plugin_name: 'inspec-test-fixture',
resolved_path: File.join(core_fixture_plugins_path, 'inspec-test-fixture', 'lib', 'inspec-test-fixture.rb')
}.merge(fixture_info)
install_result = run_inspec_process_with_this_plugin("plugin install #{fixture_info[:given]}", post_run: list_after_run)
assert_empty install_result.stderr
assert_equal 0, install_result.exit_status, 'Exit status should be 0'
# Check UX messaging
success_message = install_result.stdout.split("\n").grep(/installed/).last
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')
# 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.'
end
end
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}")
assert_empty install_result.stderr
assert_equal 1, install_result.exit_status, 'Exit status should be 1'
error_message = install_result.stdout.split("\n").last
assert_includes error_message, "No such source code path"
assert_includes error_message, 'inspec-test-fixture-nonesuch.rb'
assert_includes error_message, 'installation failed'
end
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}")
assert_empty install_result.stderr
assert_equal 1, install_result.exit_status, 'Exit status should be 1'
error_message = install_result.stdout.split("\n").last
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-'"
assert_includes error_message, 'installation failed'
end
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}")
assert_empty install_result.stderr
assert_equal 1, install_result.exit_status, 'Exit status should be 1'
error_message = install_result.stdout.split("\n").last
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"
assert_includes error_message, "Ensure something inherits from 'Inspec.plugin(2)'"
assert_includes error_message, 'installation failed'
end
def test_fail_install_from_path_when_it_is_already_installed
plugin_path = File.join(core_fixture_plugins_path, 'inspec-test-fixture', 'lib', 'inspec-test-fixture.rb')
pre_block = Proc.new do |plugin_data, _tmp_dir|
plugin_data["plugins"] << {
"name" => "inspec-test-fixture",
"installation_type" => "path",
"installation_path" => plugin_path,
}
end
install_result = run_inspec_process_with_this_plugin("plugin install #{plugin_path}", pre_run: pre_block)
assert_empty install_result.stderr
assert_equal 2, install_result.exit_status, 'Exit status on second install should be 2'
error_message = install_result.stdout.split("\n").last
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"
assert_includes error_message, 'installation failed'
end
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}")
assert_empty install_result.stderr
assert_equal 1, install_result.exit_status, 'Exit status should be 1'
error_message = install_result.stdout.split("\n").last
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'
assert_includes error_message, 'installation failed'
end
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)
assert_empty install_result.stderr
assert_equal 0, install_result.exit_status, 'Exit status should be 0'
success_message = install_result.stdout.split("\n").grep(/installed/).last
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')
end
def test_fail_install_from_nonexistant_gemfile
bad_path = File.join(project_fixtures_path, 'none', 'such', 'inspec-test-fixture-nonesuch-0.3.0.gem')
install_result = run_inspec_process_with_this_plugin("plugin install #{bad_path}")
assert_empty install_result.stderr
assert_equal 1, install_result.exit_status, 'Exit status should be 1'
assert_match(/No such plugin gem file .+ - installation failed./, install_result.stdout)
end
def test_install_from_rubygems_latest
install_result = run_inspec_process_with_this_plugin('plugin install inspec-test-fixture', post_run: list_after_run)
assert_empty install_result.stderr
assert_equal 0, install_result.exit_status, 'Exit status should be 0'
success_message = install_result.stdout.split("\n").grep(/installed/).last
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')
end
def test_fail_install_from_nonexistant_remote_rubygem
install_result = run_inspec_process_with_this_plugin('plugin install inspec-test-fixture-nonesuch')
assert_empty install_result.stderr
assert_equal 1, install_result.exit_status, 'Exit status should be 1'
assert_match(/No such plugin gem .+ could be found on rubygems.org - installation failed./, install_result.stdout)
end
def test_install_from_rubygems_with_pinned_version
install_result = run_inspec_process_with_this_plugin('plugin install inspec-test-fixture -v 0.1.0', post_run: list_after_run)
assert_empty install_result.stderr
assert_equal 0, install_result.exit_status, 'Exit status should be 0'
success_message = install_result.stdout.split("\n").grep(/installed/).last
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 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')
end
def test_fail_install_from_nonexistant_rubygem_version
install_result = run_inspec_process_with_this_plugin('plugin install inspec-test-fixture -v 99.99.99')
assert_empty install_result.stderr
assert_equal 1, install_result.exit_status, 'Exit status should be 1'
fail_message = install_result.stdout.split("\n").grep(/failed/).last
refute_nil fail_message, 'Should find a failure message at the end'
assert_includes fail_message, 'inspec-test-fixture'
assert_includes fail_message, '99.99.99'
assert_includes fail_message, 'no such version'
assert_includes fail_message, 'on rubygems.org'
end
def test_refuse_install_when_missing_prefix
install_result = run_inspec_process_with_this_plugin('plugin install test-fixture')
assert_empty install_result.stderr
assert_equal 1, install_result.exit_status, 'Exit status should be 1'
fail_message = install_result.stdout.split("\n").grep(/failed/).last
refute_nil fail_message, 'Should find a failure message at the end'
assert_includes fail_message, 'test-fixture'
assert_includes fail_message, "All inspec plugins must begin with either 'inspec-' or 'train-'"
end
def test_refuse_install_when_already_installed_same_version
pre_block = Proc.new do |plugin_statefile_data, tmp_dir|
plugin_statefile_data.clear # Signal not to write a file, we'll provide one.
copy_in_core_config_dir('test-fixture-2-float', tmp_dir)
end
install_result = run_inspec_process_with_this_plugin('plugin install inspec-test-fixture', pre_run: pre_block)
assert_empty install_result.stderr
assert_equal 2, install_result.exit_status, 'Exit status should be 2'
refusal_message = install_result.stdout.split("\n").grep(/refusing/).last
refute_nil refusal_message, 'Should find a failure message at the end'
assert_includes refusal_message, 'inspec-test-fixture'
assert_includes refusal_message, '0.2.0'
assert_includes refusal_message, 'Plugin already installed at latest version'
end
def test_refuse_install_when_already_installed_can_update
pre_block = Proc.new do |plugin_statefile_data, tmp_dir|
plugin_statefile_data.clear # Signal not to write a file, we'll provide one.
copy_in_core_config_dir('test-fixture-1-float', tmp_dir)
end
install_result = run_inspec_process_with_this_plugin('plugin install inspec-test-fixture', pre_run: pre_block)
assert_empty install_result.stderr
assert_equal 2, install_result.exit_status, 'Exit status should be 2'
refusal_message = install_result.stdout.split("\n").grep(/refusing/).last
refute_nil refusal_message, 'Should find a failure message at the end'
assert_includes refusal_message, 'inspec-test-fixture'
assert_includes refusal_message, '0.1.0'
assert_includes refusal_message, '0.2.0'
assert_includes refusal_message, 'Update required'
assert_includes refusal_message, 'inspec plugin update'
end
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)
assert_empty install_result.stderr
assert_equal 0, install_result.exit_status, 'Exit status should be 0'
success_message = install_result.stdout.split("\n").grep(/installed/).last
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')
end
def test_refuse_install_when_plugin_on_exclusion_list
# Here, 'inspec-core', 'inspec-multi-server', and 'train-tax-collector'
# are the names of real rubygems. They are not InSpec/Train plugins, though,
# and installing them would be a jam-up.
# This is configured in 'etc/plugin-filter.json'.
[
'inspec-core',
'inspec-multi-server',
'train-tax-calculator',
].each do |plugin_name|
install_result = run_inspec_process_with_this_plugin("plugin install #{plugin_name}")
assert_empty install_result.stderr
assert_equal 2, install_result.exit_status, 'Exit status should be 2'
refusal_message = install_result.stdout
refute_nil refusal_message, 'Should find a failure message at the end'
assert_includes refusal_message, plugin_name
assert_includes refusal_message, 'Plugin on Exclusion List'
assert_includes refusal_message, 'refusing to install'
assert_includes refusal_message, 'Rationale:'
assert_includes refusal_message, 'etc/plugin_filters.json'
assert_includes refusal_message, 'github.com/inspec/inspec/issues/new'
end
end
def test_error_install_with_debug_enabled
install_result = run_inspec_process_with_this_plugin('plugin install inspec-test-fixture -v 0.1.1 --log-level debug')
assert_equal 1, install_result.exit_status, 'Exit status should be 1'
assert_includes install_result.stdout, 'DEBUG'
assert_includes install_result.stderr, "can't activate rake"
end
end
#-----------------------------------------------------------------------------------------#
# inspec plugin update
#-----------------------------------------------------------------------------------------#
class PluginManagerCliUpdate < MiniTest::Test
include CorePluginFunctionalHelper
include PluginManagerHelpers
def test_when_a_plugin_can_be_updated
pre_block = Proc.new do |plugin_statefile_data, tmp_dir|
plugin_statefile_data.clear # Signal not to write a file, we'll provide one.
copy_in_core_config_dir('test-fixture-1-float', tmp_dir)
end
update_result = run_inspec_process_with_this_plugin('plugin update inspec-test-fixture', pre_run: pre_block, post_run: list_after_run)
assert_empty update_result.stderr
assert_equal 0, update_result.exit_status, 'Exit status should be 0'
success_message = update_result.stdout.split("\n").grep(/updated/).last
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, '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')
end
def test_refuse_update_when_already_current
pre_block = Proc.new do |plugin_statefile_data, tmp_dir|
plugin_statefile_data.clear # Signal not to write a file, we'll provide one.
copy_in_core_config_dir('test-fixture-2-float', tmp_dir)
end
update_result = run_inspec_process_with_this_plugin('plugin update inspec-test-fixture', pre_run: pre_block)
assert_empty update_result.stderr
assert_equal 2, update_result.exit_status, 'Exit status should be 2'
refusal_message = update_result.stdout.split("\n").grep(/refusing/).last
refute_nil refusal_message, 'Should find a failure message at the end'
assert_includes refusal_message, 'inspec-test-fixture'
assert_includes refusal_message, '0.2.0'
assert_includes refusal_message, 'Already installed at latest version'
end
def test_fail_update_from_nonexistant_gem
update_result = run_inspec_process_with_this_plugin('plugin update inspec-test-fixture-nonesuch')
assert_empty update_result.stderr
assert_equal 1, update_result.exit_status, 'Exit status should be 1'
assert_match(/No such plugin installed: .+ - update failed/, update_result.stdout)
end
def test_fail_update_path
pre_block = Proc.new do |plugin_statefile_data, tmp_dir|
plugin_statefile_data.clear # Signal not to write a file, we'll provide one.
copy_in_core_config_dir('meaning_by_path', tmp_dir)
end
update_result = run_inspec_process_with_this_plugin('plugin update inspec-meaning-of-life', pre_run: pre_block)
assert_empty update_result.stderr
assert_equal 2, update_result.exit_status, 'Exit status should be 2'
refusal_message = update_result.stdout.split("\n").grep(/refusing/).last
refute_nil refusal_message, 'Should find a failure message at the end'
assert_includes refusal_message, 'inspec-meaning-of-life'
assert_includes refusal_message, 'inspec plugin uninstall'
assert_includes refusal_message, 'Cannot update path-based install'
end
end
#-----------------------------------------------------------------------------------------#
# inspec plugin uninstall
#-----------------------------------------------------------------------------------------#
class PluginManagerCliUninstall < MiniTest::Test
include CorePluginFunctionalHelper
include PluginManagerHelpers
def test_when_a_gem_plugin_can_be_uninstalled
pre_block = Proc.new do |plugin_statefile_data, tmp_dir|
plugin_statefile_data.clear # Signal not to write a file, we'll provide one.
copy_in_core_config_dir('test-fixture-1-float', tmp_dir)
end
# Attempt uninstall
uninstall_result = run_inspec_process_with_this_plugin('plugin uninstall inspec-test-fixture', pre_run: pre_block, post_run: list_after_run)
assert_empty uninstall_result.stderr
assert_equal 0, uninstall_result.exit_status, 'Exit status should be 0'
success_message = uninstall_result.stdout.split("\n").grep(/uninstalled/).last
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, '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'
end
def test_when_a_path_plugin_can_be_uninstalled
pre_block = Proc.new do |plugin_statefile_data, tmp_dir|
plugin_statefile_data.clear # Signal not to write a file, we'll provide one.
# 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)
assert_empty uninstall_result.stderr
assert_equal 0, uninstall_result.exit_status, 'Exit status should be 0'
success_message = uninstall_result.stdout.split("\n").grep(/uninstalled/).last
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'
end
def test_fail_uninstall_from_plugin_that_is_not_installed
uninstall_result = run_inspec_process_with_this_plugin('plugin uninstall inspec-test-fixture-nonesuch')
assert_empty uninstall_result.stderr
assert_equal 1, uninstall_result.exit_status, 'Exit status should be 1'
refute_includes 'Inspec::Plugin::V2::UnInstallError', uninstall_result.stdout # Stacktrace marker
assert_match(/No such plugin installed: .+ - uninstall failed/, uninstall_result.stdout)
end
end