inspec 4.16.0 → 4.17.7

Sign up to get free protection for your applications and to get access to all the features.
Files changed (53) hide show
  1. checksums.yaml +4 -4
  2. data/lib/inspec.rb +0 -1
  3. data/lib/inspec/backend.rb +7 -0
  4. data/lib/inspec/base_cli.rb +2 -0
  5. data/lib/inspec/cli.rb +3 -10
  6. data/lib/inspec/config.rb +3 -4
  7. data/lib/inspec/control_eval_context.rb +5 -3
  8. data/lib/inspec/dsl.rb +24 -1
  9. data/lib/inspec/errors.rb +0 -26
  10. data/lib/inspec/file_provider.rb +33 -43
  11. data/lib/inspec/formatters/base.rb +1 -0
  12. data/lib/inspec/impact.rb +2 -0
  13. data/lib/inspec/input.rb +410 -0
  14. data/lib/inspec/input_registry.rb +10 -1
  15. data/lib/inspec/objects.rb +3 -1
  16. data/lib/inspec/objects/input.rb +5 -387
  17. data/lib/inspec/objects/tag.rb +1 -1
  18. data/lib/inspec/plugin/v1/plugin_types/resource.rb +16 -5
  19. data/lib/inspec/plugin/v2/activator.rb +4 -8
  20. data/lib/inspec/plugin/v2/loader.rb +19 -3
  21. data/lib/inspec/profile.rb +1 -1
  22. data/lib/inspec/profile_context.rb +1 -1
  23. data/lib/inspec/reporters/json.rb +70 -88
  24. data/lib/inspec/resource.rb +1 -0
  25. data/lib/inspec/resources.rb +9 -2
  26. data/lib/inspec/resources/aide_conf.rb +4 -0
  27. data/lib/inspec/resources/apt.rb +19 -19
  28. data/lib/inspec/resources/etc_fstab.rb +4 -0
  29. data/lib/inspec/resources/etc_hosts.rb +4 -0
  30. data/lib/inspec/resources/firewalld.rb +4 -0
  31. data/lib/inspec/resources/json.rb +10 -3
  32. data/lib/inspec/resources/mssql_session.rb +1 -1
  33. data/lib/inspec/resources/platform.rb +18 -13
  34. data/lib/inspec/resources/postfix_conf.rb +6 -2
  35. data/lib/inspec/resources/security_identifier.rb +4 -0
  36. data/lib/inspec/resources/sys_info.rb +65 -4
  37. data/lib/inspec/resources/user.rb +1 -0
  38. data/lib/inspec/rule.rb +68 -6
  39. data/lib/inspec/runner.rb +6 -1
  40. data/lib/inspec/runner_rspec.rb +1 -0
  41. data/lib/inspec/shell.rb +8 -1
  42. data/lib/inspec/utils/pkey_reader.rb +1 -1
  43. data/lib/inspec/version.rb +1 -1
  44. data/lib/matchers/matchers.rb +2 -0
  45. data/lib/plugins/inspec-plugin-manager-cli/test/functional/help_test.rb +23 -0
  46. data/lib/plugins/inspec-plugin-manager-cli/test/functional/helper.rb +62 -0
  47. data/lib/plugins/inspec-plugin-manager-cli/test/functional/install_test.rb +368 -0
  48. data/lib/plugins/inspec-plugin-manager-cli/test/functional/list_test.rb +101 -0
  49. data/lib/plugins/inspec-plugin-manager-cli/test/functional/search_test.rb +129 -0
  50. data/lib/plugins/inspec-plugin-manager-cli/test/functional/uninstall_test.rb +63 -0
  51. data/lib/plugins/inspec-plugin-manager-cli/test/functional/update_test.rb +84 -0
  52. metadata +11 -3
  53. data/lib/plugins/inspec-plugin-manager-cli/test/functional/inspec-plugin_test.rb +0 -845
@@ -0,0 +1,101 @@
1
+ require_relative "helper"
2
+
3
+ class PluginManagerCliList < Minitest::Test
4
+ include CorePluginFunctionalHelper
5
+ include PluginManagerHelpers
6
+
7
+ # Listing all plugins is now default behavior
8
+ LIST_CASES = [
9
+ { arg: "-c", name: "inspec-plugin-manager-cli", type: "core" },
10
+ { arg: "-c", name: "inspec-supermarket", type: "core" },
11
+ { arg: "-s", name: "train-aws", type: "gem (system)" },
12
+ ].freeze
13
+
14
+ def test_list_all_when_no_user_plugins_installed
15
+ result = run_inspec_process_with_this_plugin("plugin list --all")
16
+ skip_windows!
17
+ assert_empty result.stderr
18
+
19
+ plugins_seen = parse_plugin_list_lines(result.stdout)
20
+
21
+ # Look for a specific plugin of each type - core, bundle, and system
22
+ LIST_CASES.each do |test_case|
23
+ plugin_line = plugins_seen.detect { |plugin| plugin[:name] == test_case[:name] }
24
+ refute_nil plugin_line, "#{test_case[:name]} should be detected in plugin list --all output"
25
+ assert_equal test_case[:type], plugin_line[:type], "#{test_case[:name]} should be detected as a '#{test_case[:type]}' type in list --all "
26
+ end
27
+ assert_exit_code 0, result
28
+ end
29
+
30
+ def test_list_selective_when_no_user_plugins_installed
31
+ LIST_CASES.each do |test_case|
32
+ result = run_inspec_process_with_this_plugin("plugin list #{test_case[:arg]}")
33
+ skip_windows!
34
+
35
+ assert_empty result.stderr
36
+ plugins_seen = parse_plugin_list_lines(result.stdout)
37
+ plugin_line = plugins_seen.detect { |plugin| plugin[:name] == test_case[:name] }
38
+ refute_nil plugin_line, "#{test_case[:name]} should be detected in plugin list #{test_case[:arg]} output"
39
+ 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]} "
40
+ assert_exit_code 0, result
41
+ end
42
+ end
43
+
44
+ def test_list_when_gem_and_path_plugins_installed
45
+ pre_block = Proc.new do |plugin_statefile_data, tmp_dir|
46
+ plugin_statefile_data.clear # Signal not to write a file, we'll provide one.
47
+ copy_in_core_config_dir("test-fixture-1-float", tmp_dir)
48
+ end
49
+
50
+ result = run_inspec_process_with_this_plugin("plugin list --user ", pre_run: pre_block)
51
+ skip_windows!
52
+
53
+ assert_empty result.stderr
54
+ plugins_seen = parse_plugin_list_lines(result.stdout)
55
+ assert_equal 2, plugins_seen.count
56
+ # Plugin Name Version Via ApiVer
57
+ # ---------------------------------------------------------
58
+ # inspec-meaning-of-life src path 2
59
+ # inspec-test-fixture 0.1.0 gem (user) 2
60
+ # ---------------------------------------------------------
61
+ # 2 plugin(s) total
62
+ meaning = plugins_seen.detect { |p| p[:name] == "inspec-meaning-of-life" }
63
+ refute_nil meaning
64
+ assert_equal "path", meaning[:type]
65
+
66
+ fixture = plugins_seen.detect { |p| p[:name] == "inspec-test-fixture" }
67
+ refute_nil fixture
68
+ assert_equal "gem (user)", fixture[:type]
69
+ assert_equal "0.1.0", fixture[:version]
70
+
71
+ assert_exit_code 0, result
72
+ end
73
+
74
+ def test_list_when_a_train_plugin_is_installed
75
+ pre_block = Proc.new do |plugin_statefile_data, tmp_dir|
76
+ plugin_statefile_data.clear # Signal not to write a file, we'll provide one.
77
+ copy_in_core_config_dir("train-test-fixture", tmp_dir)
78
+ end
79
+
80
+ result = run_inspec_process_with_this_plugin("plugin list --user ", pre_run: pre_block)
81
+ skip_windows!
82
+
83
+ assert_empty result.stderr
84
+ plugins_seen = parse_plugin_list_lines(result.stdout)
85
+ assert_equal 1, plugins_seen.count
86
+ assert_includes result.stdout, "1 plugin(s) total", "list train should show one plugins"
87
+
88
+ # Plugin Name Version Via ApiVer
89
+ # -------------------------------------------------------------
90
+ # train-test-fixture 0.1.0 gem (user) train-1
91
+ # -------------------------------------------------------------
92
+ # 1 plugin(s) total
93
+ train_plugin = plugins_seen.detect { |p| p[:name] == "train-test-fixture" }
94
+ refute_nil train_plugin
95
+ assert_equal "gem (user)", train_plugin[:type]
96
+ assert_equal "train-1", train_plugin[:generation]
97
+ assert_equal "0.1.0", train_plugin[:version]
98
+
99
+ assert_exit_code 0, result
100
+ end
101
+ end
@@ -0,0 +1,129 @@
1
+ require_relative "helper"
2
+
3
+ class PluginManagerCliSearch < Minitest::Test
4
+ include CorePluginFunctionalHelper
5
+ include PluginManagerHelpers
6
+
7
+ parallelize_me!
8
+
9
+ # TODO: Thor can't hide options, but we wish it could.
10
+ # def test_search_include_fixture_hidden_option
11
+ # result = run_inspec_process_with_this_plugin('plugin help search')
12
+ # refute_includes result.stdout, '--include-test-fixture'
13
+ # end
14
+
15
+ def test_search_for_a_real_gem_with_full_name_no_options
16
+ result = run_inspec_process("plugin search --include-test-fixture inspec-test-fixture")
17
+
18
+ assert_includes result.stdout, "inspec-test-fixture", "Search result should contain the gem name"
19
+ assert_includes result.stdout, "1 plugin(s) found", "Search result should find 1 plugin"
20
+ line = result.stdout.split("\n").grep(/inspec-test-fixture/).first
21
+ assert_match(/\s*inspec-test-fixture\s+\((\d+\.\d+\.\d+){1}\)/, line, "Plugin line should include name and exactly one version")
22
+
23
+ assert_exit_code 0, result
24
+ end
25
+
26
+ def test_search_for_a_real_gem_with_stub_name_no_options
27
+ result = run_inspec_process("plugin search --include-test-fixture inspec-test-")
28
+
29
+ assert_includes result.stdout, "inspec-test-fixture", "Search result should contain the gem name"
30
+ assert_includes result.stdout, "1 plugin(s) found", "Search result should find 1 plugin"
31
+
32
+ line = result.stdout.split("\n").grep(/inspec-test-fixture/).first
33
+ assert_match(/\s*inspec-test-fixture\s+\((\d+\.\d+\.\d+){1}\)/, line, "Plugin line should include name and exactly one version")
34
+
35
+ assert_exit_code 0, result
36
+ end
37
+
38
+ def test_search_for_a_real_gem_with_full_name_and_exact_option
39
+ result = run_inspec_process("plugin search --exact --include-test-fixture inspec-test-fixture")
40
+
41
+ assert_includes result.stdout, "inspec-test-fixture", "Search result should contain the gem name"
42
+ assert_includes result.stdout, "1 plugin(s) found", "Search result should find 1 plugin"
43
+
44
+ assert_exit_code 0, result
45
+
46
+ # TODO: split
47
+ result = run_inspec_process("plugin search -e --include-test-fixture inspec-test-fixture")
48
+
49
+ assert_exit_code 0, result
50
+ end
51
+
52
+ def test_search_for_a_real_gem_with_stub_name_and_exact_option
53
+ result = run_inspec_process("plugin search --exact --include-test-fixture inspec-test-")
54
+
55
+ assert_includes result.stdout, "0 plugin(s) found", "Search result should find 0 plugins"
56
+
57
+ assert_exit_code 2, result
58
+
59
+ # TODO: split
60
+ result = run_inspec_process("plugin search -e --include-test-fixture inspec-test-")
61
+
62
+ assert_exit_code 2, result
63
+ end
64
+
65
+ def test_search_for_a_real_gem_with_full_name_and_all_option
66
+ result = run_inspec_process("plugin search --all --include-test-fixture inspec-test-fixture")
67
+ assert_includes result.stdout, "inspec-test-fixture", "Search result should contain the gem name"
68
+ assert_includes result.stdout, "1 plugin(s) found", "Search result should find 1 plugin"
69
+
70
+ line = result.stdout.split("\n").grep(/inspec-test-fixture/).first
71
+ assert_match(/\s*inspec-test-fixture\s+\((\d+\.\d+\.\d+(,\s)?){2,}\)/, line, "Plugin line should include name and at least two versions")
72
+
73
+ assert_exit_code 0, result
74
+
75
+ # TODO: split
76
+ result = run_inspec_process("plugin search -a --include-test-fixture inspec-test-fixture")
77
+
78
+ assert_exit_code 0, result
79
+ end
80
+
81
+ def test_search_for_a_gem_with_missing_prefix
82
+ result = run_inspec_process("plugin search --include-test-fixture test-fixture")
83
+ assert_exit_code 1, result
84
+ assert_includes result.stdout, "All inspec plugins must begin with either 'inspec-' or 'train-'"
85
+ end
86
+
87
+ def test_search_for_a_gem_that_does_not_exist
88
+ result = run_inspec_process("plugin search --include-test-fixture inspec-test-fixture-nonesuch")
89
+
90
+ assert_includes result.stdout, "0 plugin(s) found", "Search result should find 0 plugins"
91
+
92
+ assert_exit_code 2, result
93
+ end
94
+
95
+ def test_search_for_a_real_gem_with_full_name_no_options_and_train_name
96
+ result = run_inspec_process("plugin search --include-test-fixture train-test-fixture")
97
+
98
+ assert_includes result.stdout, "train-test-fixture", "Search result should contain the gem name"
99
+ assert_includes result.stdout, "1 plugin(s) found", "Search result should find 1 plugin"
100
+ line = result.stdout.split("\n").grep(/train-test-fixture/).first
101
+ assert_match(/\s*train-test-fixture\s+\((\d+\.\d+\.\d+){1}\)/, line, "Plugin line should include name and exactly one version")
102
+
103
+ assert_exit_code 0, result
104
+ end
105
+
106
+ def test_search_omit_excluded_inspec_plugins
107
+ result = run_inspec_process("plugin search --include-test-fixture inspec-")
108
+
109
+ assert_includes result.stdout, "inspec-test-fixture", "Search result should contain the test gem"
110
+ %w{
111
+ inspec-core
112
+ inspec-multi-server
113
+ }.each do |plugin_name|
114
+ refute_includes result.stdout, plugin_name, "Search result should not contain excluded gems"
115
+ end
116
+
117
+ assert_exit_code 0, result
118
+ end
119
+
120
+ def test_search_for_a_real_gem_with_full_name_no_options_filter_fixtures
121
+ result = run_inspec_process("plugin search inspec-test-fixture")
122
+ refute_includes result.stdout, "inspec-test-fixture", "Search result should not contain the fixture gem name"
123
+ end
124
+
125
+ def test_search_for_a_real_gem_with_full_name_no_options_filter_fixtures_train
126
+ result = run_inspec_process("plugin search train-test-fixture")
127
+ refute_includes result.stdout, "train-test-fixture", "Search result should not contain the fixture gem name"
128
+ end
129
+ end
@@ -0,0 +1,63 @@
1
+ require_relative "helper"
2
+
3
+ class PluginManagerCliUninstall < Minitest::Test
4
+ include CorePluginFunctionalHelper
5
+ include PluginManagerHelpers
6
+
7
+ def test_when_a_gem_plugin_can_be_uninstalled
8
+ pre_block = Proc.new do |plugin_statefile_data, tmp_dir|
9
+ plugin_statefile_data.clear # Signal not to write a file, we'll provide one.
10
+ copy_in_core_config_dir("test-fixture-1-float", tmp_dir)
11
+ end
12
+
13
+ # Attempt uninstall
14
+ uninstall_result = run_inspec_process_with_this_plugin("plugin uninstall inspec-test-fixture", pre_run: pre_block, post_run: list_after_run)
15
+
16
+ success_message = uninstall_result.stdout.split("\n").grep(/uninstalled/).last
17
+ skip_windows!
18
+ refute_nil success_message, "Should find a success message at the end"
19
+ assert_includes success_message, "inspec-test-fixture"
20
+ assert_includes success_message, "0.1.0"
21
+ assert_includes success_message, "has been uninstalled"
22
+
23
+ itf_plugins = uninstall_result.payload.list_result.select { |p| p[:name] == "inspec-test-fixture" }
24
+ assert_empty itf_plugins, "inspec-test-fixture should not appear in the output of inspec list"
25
+
26
+ assert_empty uninstall_result.stderr
27
+ assert_exit_code 0, uninstall_result
28
+ end
29
+
30
+ def test_when_a_path_plugin_can_be_uninstalled
31
+ pre_block = Proc.new do |plugin_statefile_data, tmp_dir|
32
+ plugin_statefile_data.clear # Signal not to write a file, we'll provide one.
33
+ # This fixture includes a path install for inspec-meaning-of-life
34
+ copy_in_core_config_dir("test-fixture-1-float", tmp_dir)
35
+ end
36
+ uninstall_result = run_inspec_process_with_this_plugin("plugin uninstall inspec-meaning-of-life", pre_run: pre_block, post_run: list_after_run)
37
+ skip_windows!
38
+
39
+ success_message = uninstall_result.stdout.split("\n").grep(/uninstalled/).last
40
+ refute_nil success_message, "Should find a success message at the end"
41
+ assert_includes success_message, "inspec-meaning-of-life"
42
+ assert_includes success_message, "path-based plugin install"
43
+ assert_includes success_message, "has been uninstalled"
44
+
45
+ itf_plugins = uninstall_result.payload.list_result.select { |p| p[:name] == "inspec-meaning-of-life" }
46
+ assert_empty itf_plugins, "inspec-meaning-of-life should not appear in the output of inspec list"
47
+
48
+ assert_empty uninstall_result.stderr
49
+ assert_exit_code 0, uninstall_result
50
+ end
51
+
52
+ def test_fail_uninstall_from_plugin_that_is_not_installed
53
+ uninstall_result = run_inspec_process_with_this_plugin("plugin uninstall inspec-test-fixture-nonesuch")
54
+
55
+ skip_windows!
56
+ refute_includes "Inspec::Plugin::V2::UnInstallError", uninstall_result.stdout # Stacktrace marker
57
+ assert_match(/No such plugin installed:.+ - uninstall failed/, uninstall_result.stdout)
58
+
59
+ assert_empty uninstall_result.stderr
60
+
61
+ assert_exit_code 1, uninstall_result
62
+ end
63
+ end
@@ -0,0 +1,84 @@
1
+ require_relative "helper"
2
+
3
+ class PluginManagerCliUpdate < Minitest::Test
4
+ include CorePluginFunctionalHelper
5
+ include PluginManagerHelpers
6
+
7
+ def test_when_a_plugin_can_be_updated
8
+ skip "this test requires bundler to pass" unless defined? ::Bundler
9
+
10
+ pre_block = Proc.new do |plugin_statefile_data, tmp_dir|
11
+ plugin_statefile_data.clear # Signal not to write a file, we'll provide one.
12
+ copy_in_core_config_dir("test-fixture-1-float", tmp_dir)
13
+ end
14
+
15
+ update_result = run_inspec_process_with_this_plugin("plugin update inspec-test-fixture", pre_run: pre_block, post_run: list_after_run)
16
+
17
+ success_message = update_result.stdout.split("\n").grep(/updated/).last
18
+ skip_windows!
19
+ refute_nil success_message, "Should find a success message at the end"
20
+ assert_includes success_message, "inspec-test-fixture"
21
+ assert_includes success_message, "0.1.0"
22
+ assert_includes success_message, "0.2.0"
23
+ assert_includes success_message, "updated from rubygems.org"
24
+
25
+ itf_plugin = update_result.payload.list_result.detect { |p| p[:name] == "inspec-test-fixture" }
26
+ refute_nil itf_plugin, "plugin name should now appear in the output of inspec list"
27
+ assert_equal "gem (user)", itf_plugin[:type]
28
+ assert_equal "0.2.0", itf_plugin[:version]
29
+
30
+ assert_empty update_result.stderr
31
+ assert_exit_code 0, update_result
32
+ end
33
+
34
+ def test_refuse_update_when_already_current
35
+ pre_block = Proc.new do |plugin_statefile_data, tmp_dir|
36
+ plugin_statefile_data.clear # Signal not to write a file, we'll provide one.
37
+ copy_in_core_config_dir("test-fixture-2-float", tmp_dir)
38
+ end
39
+
40
+ update_result = run_inspec_process_with_this_plugin("plugin update inspec-test-fixture", pre_run: pre_block)
41
+
42
+ refusal_message = update_result.stdout.split("\n").grep(/refusing/).last
43
+ skip_windows!
44
+ refute_nil refusal_message, "Should find a failure message at the end"
45
+ assert_includes refusal_message, "inspec-test-fixture"
46
+ assert_includes refusal_message, "0.2.0"
47
+ assert_includes refusal_message, "Already installed at latest version"
48
+
49
+ assert_empty update_result.stderr
50
+
51
+ assert_exit_code 2, update_result
52
+ end
53
+
54
+ def test_fail_update_from_nonexistant_gem
55
+ update_result = run_inspec_process_with_this_plugin("plugin update inspec-test-fixture-nonesuch")
56
+
57
+ skip_windows!
58
+ assert_match(/No such plugin installed:.+ - update failed/, update_result.stdout)
59
+
60
+ assert_empty update_result.stderr
61
+
62
+ assert_exit_code 1, update_result
63
+ end
64
+
65
+ def test_fail_update_path
66
+ pre_block = Proc.new do |plugin_statefile_data, tmp_dir|
67
+ plugin_statefile_data.clear # Signal not to write a file, we'll provide one.
68
+ copy_in_core_config_dir("meaning_by_path", tmp_dir)
69
+ end
70
+
71
+ update_result = run_inspec_process_with_this_plugin("plugin update inspec-meaning-of-life", pre_run: pre_block)
72
+
73
+ refusal_message = update_result.stdout.split("\n").grep(/refusing/).last
74
+ skip_windows!
75
+ refute_nil refusal_message, "Should find a failure message at the end"
76
+ assert_includes refusal_message, "inspec-meaning-of-life"
77
+ assert_includes refusal_message, "inspec plugin uninstall"
78
+ assert_includes refusal_message, "Cannot update path-based install"
79
+
80
+ assert_empty update_result.stderr
81
+
82
+ assert_exit_code 2, update_result
83
+ end
84
+ end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: inspec
3
3
  version: !ruby/object:Gem::Version
4
- version: 4.16.0
4
+ version: 4.17.7
5
5
  platform: ruby
6
6
  authors:
7
7
  - Chef InSpec Team
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2019-08-28 00:00:00.000000000 Z
11
+ date: 2019-09-27 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: train
@@ -464,6 +464,7 @@ files:
464
464
  - lib/inspec/formatters/show_progress.rb
465
465
  - lib/inspec/globals.rb
466
466
  - lib/inspec/impact.rb
467
+ - lib/inspec/input.rb
467
468
  - lib/inspec/input_registry.rb
468
469
  - lib/inspec/library_eval_context.rb
469
470
  - lib/inspec/log.rb
@@ -608,6 +609,7 @@ files:
608
609
  - lib/inspec/resources/ssl.rb
609
610
  - lib/inspec/resources/sys_info.rb
610
611
  - lib/inspec/resources/toml.rb
612
+ - lib/inspec/resources/user.rb
611
613
  - lib/inspec/resources/users.rb
612
614
  - lib/inspec/resources/vbscript.rb
613
615
  - lib/inspec/resources/virtualization.rb
@@ -758,7 +760,13 @@ files:
758
760
  - lib/plugins/inspec-plugin-manager-cli/test/fixtures/plugins/inspec-wrong-structure/.gitkeep
759
761
  - lib/plugins/inspec-plugin-manager-cli/test/fixtures/plugins/wrong-name/lib/wrong-name.rb
760
762
  - lib/plugins/inspec-plugin-manager-cli/test/fixtures/plugins/wrong-name/lib/wrong-name/.gitkeep
761
- - lib/plugins/inspec-plugin-manager-cli/test/functional/inspec-plugin_test.rb
763
+ - lib/plugins/inspec-plugin-manager-cli/test/functional/help_test.rb
764
+ - lib/plugins/inspec-plugin-manager-cli/test/functional/helper.rb
765
+ - lib/plugins/inspec-plugin-manager-cli/test/functional/install_test.rb
766
+ - lib/plugins/inspec-plugin-manager-cli/test/functional/list_test.rb
767
+ - lib/plugins/inspec-plugin-manager-cli/test/functional/search_test.rb
768
+ - lib/plugins/inspec-plugin-manager-cli/test/functional/uninstall_test.rb
769
+ - lib/plugins/inspec-plugin-manager-cli/test/functional/update_test.rb
762
770
  - lib/plugins/inspec-plugin-manager-cli/test/unit/cli_args_test.rb
763
771
  - lib/plugins/inspec-plugin-manager-cli/test/unit/plugin_def_test.rb
764
772
  - lib/plugins/shared/core_plugin_test_helper.rb
@@ -1,845 +0,0 @@
1
- #=========================================================================================#
2
- # `inspec plugin SUBCOMMAND` facility
3
- #=========================================================================================#
4
- require_relative "../../../shared/core_plugin_test_helper.rb"
5
-
6
- #-----------------------------------------------------------------------------------------#
7
- # utilities
8
- #-----------------------------------------------------------------------------------------#
9
- module PluginManagerHelpers
10
- let(:project_repo_path) { File.expand_path(File.join(__FILE__, "..", "..", "..")) }
11
- let(:project_fixtures_path) { File.join(project_repo_path, "test", "fixtures") }
12
- let(:project_config_dirs_path) { File.join(project_fixtures_path, "config_dirs") }
13
- let(:empty_config_dir_path) { File.join(project_config_dirs_path, "empty") }
14
-
15
- let(:list_after_run) do
16
- Proc.new do |run_result, tmp_dir|
17
- # After installing/uninstalling/whatevering, run list with config in the same dir, and capture it.
18
- run_result.payload.list_result = parse_plugin_list_lines(
19
- run_inspec_process("plugin list", env: { INSPEC_CONFIG_DIR: tmp_dir }).stdout
20
- )
21
- end
22
- end
23
-
24
- def copy_in_project_config_dir(fixture_name, dest = nil)
25
- src = Dir.glob(File.join(project_config_dirs_path, fixture_name, "*"))
26
- dest ||= File.join(project_config_dirs_path, "empty")
27
- src.each { |path| FileUtils.cp_r(path, dest) }
28
- end
29
-
30
- def copy_in_core_config_dir(fixture_name, dest = nil)
31
- src = Dir.glob(File.join(core_config_dir_path, fixture_name, "*"))
32
- dest ||= File.join(project_config_dirs_path, "empty")
33
- src.each { |path| FileUtils.cp_r(path, dest) }
34
- end
35
-
36
- def clear_empty_config_dir
37
- Dir.glob(File.join(project_config_dirs_path, "empty", "*")).each do |path|
38
- next if path.end_with? ".gitkeep"
39
-
40
- FileUtils.rm_rf(path)
41
- end
42
- end
43
-
44
- def parse_plugin_list_lines(stdout)
45
- plugins = []
46
-
47
- stdout.force_encoding("UTF-8").lines.each do |line|
48
- next if line.strip.empty?
49
- next if line.include? "─────" # This is some unicode glyphiness
50
- next if line.include? "Plugin Name"
51
- next if line.include? "plugin(s) total"
52
-
53
- parts = line.split(/│/u).map(&:strip!).compact
54
- plugins << {
55
- name: parts[0],
56
- version: parts[1],
57
- type: parts[2],
58
- generation: parts[3],
59
- raw: line,
60
- }
61
- end
62
- plugins
63
- end
64
-
65
- def teardown
66
- clear_empty_config_dir
67
- end
68
- end
69
-
70
- #-----------------------------------------------------------------------------------------#
71
- # inspec help
72
- #-----------------------------------------------------------------------------------------#
73
- class PluginManagerCliHelp < Minitest::Test
74
- include CorePluginFunctionalHelper
75
-
76
- # Main inspec help subcommand listing
77
- def test_inspec_help_includes_plugin
78
- result = run_inspec_process_with_this_plugin("help")
79
- skip_windows!
80
- assert_includes result.stdout, "inspec plugin"
81
- end
82
-
83
- # inspec plugin help subcommand listing
84
- def test_inspec_plugin_help_includes_plugin
85
- result = run_inspec_process_with_this_plugin("plugin help")
86
- skip_windows!
87
- assert_includes result.stdout, "inspec plugin list"
88
- assert_includes result.stdout, "inspec plugin search"
89
- assert_includes result.stdout, "inspec plugin install"
90
- assert_includes result.stdout, "inspec plugin update"
91
- assert_includes result.stdout, "inspec plugin uninstall"
92
- end
93
- end
94
-
95
- #-----------------------------------------------------------------------------------------#
96
- # inspec plugin list
97
- #-----------------------------------------------------------------------------------------#
98
- class PluginManagerCliList < Minitest::Test
99
- include CorePluginFunctionalHelper
100
- include PluginManagerHelpers
101
-
102
- # Listing all plugins is now default behavior
103
- LIST_CASES = [
104
- { arg: "-c", name: "inspec-plugin-manager-cli", type: "core" },
105
- { arg: "-c", name: "inspec-supermarket", type: "core" },
106
- { arg: "-s", name: "train-aws", type: "gem (system)" },
107
- ].freeze
108
-
109
- def test_list_all_when_no_user_plugins_installed
110
- result = run_inspec_process_with_this_plugin("plugin list --all")
111
- skip_windows!
112
- assert_empty result.stderr
113
-
114
- plugins_seen = parse_plugin_list_lines(result.stdout)
115
-
116
- # Look for a specific plugin of each type - core, bundle, and system
117
- LIST_CASES.each do |test_case|
118
- plugin_line = plugins_seen.detect { |plugin| plugin[:name] == test_case[:name] }
119
- refute_nil plugin_line, "#{test_case[:name]} should be detected in plugin list --all output"
120
- assert_equal test_case[:type], plugin_line[:type], "#{test_case[:name]} should be detected as a '#{test_case[:type]}' type in list --all "
121
- end
122
- assert_exit_code 0, result
123
- end
124
-
125
- def test_list_selective_when_no_user_plugins_installed
126
- LIST_CASES.each do |test_case|
127
- result = run_inspec_process_with_this_plugin("plugin list #{test_case[:arg]}")
128
- skip_windows!
129
-
130
- assert_empty result.stderr
131
- plugins_seen = parse_plugin_list_lines(result.stdout)
132
- plugin_line = plugins_seen.detect { |plugin| plugin[:name] == test_case[:name] }
133
- refute_nil plugin_line, "#{test_case[:name]} should be detected in plugin list #{test_case[:arg]} output"
134
- 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]} "
135
- assert_exit_code 0, result
136
- end
137
- end
138
-
139
- def test_list_when_gem_and_path_plugins_installed
140
- pre_block = Proc.new do |plugin_statefile_data, tmp_dir|
141
- plugin_statefile_data.clear # Signal not to write a file, we'll provide one.
142
- copy_in_core_config_dir("test-fixture-1-float", tmp_dir)
143
- end
144
-
145
- result = run_inspec_process_with_this_plugin("plugin list --user ", pre_run: pre_block)
146
- skip_windows!
147
-
148
- assert_empty result.stderr
149
- plugins_seen = parse_plugin_list_lines(result.stdout)
150
- assert_equal 2, plugins_seen.count
151
- # Plugin Name Version Via ApiVer
152
- # ---------------------------------------------------------
153
- # inspec-meaning-of-life src path 2
154
- # inspec-test-fixture 0.1.0 gem (user) 2
155
- # ---------------------------------------------------------
156
- # 2 plugin(s) total
157
- meaning = plugins_seen.detect { |p| p[:name] == "inspec-meaning-of-life" }
158
- refute_nil meaning
159
- assert_equal "path", meaning[:type]
160
-
161
- fixture = plugins_seen.detect { |p| p[:name] == "inspec-test-fixture" }
162
- refute_nil fixture
163
- assert_equal "gem (user)", fixture[:type]
164
- assert_equal "0.1.0", fixture[:version]
165
-
166
- assert_exit_code 0, result
167
- end
168
-
169
- def test_list_when_a_train_plugin_is_installed
170
- pre_block = Proc.new do |plugin_statefile_data, tmp_dir|
171
- plugin_statefile_data.clear # Signal not to write a file, we'll provide one.
172
- copy_in_core_config_dir("train-test-fixture", tmp_dir)
173
- end
174
-
175
- result = run_inspec_process_with_this_plugin("plugin list --user ", pre_run: pre_block)
176
- skip_windows!
177
-
178
- assert_empty result.stderr
179
- plugins_seen = parse_plugin_list_lines(result.stdout)
180
- assert_equal 1, plugins_seen.count
181
- assert_includes result.stdout, "1 plugin(s) total", "list train should show one plugins"
182
-
183
- # Plugin Name Version Via ApiVer
184
- # -------------------------------------------------------------
185
- # train-test-fixture 0.1.0 gem (user) train-1
186
- # -------------------------------------------------------------
187
- # 1 plugin(s) total
188
- train_plugin = plugins_seen.detect { |p| p[:name] == "train-test-fixture" }
189
- refute_nil train_plugin
190
- assert_equal "gem (user)", train_plugin[:type]
191
- assert_equal "train-1", train_plugin[:generation]
192
- assert_equal "0.1.0", train_plugin[:version]
193
-
194
- assert_exit_code 0, result
195
- end
196
- end
197
-
198
- #-----------------------------------------------------------------------------------------#
199
- # inspec plugin search
200
- #-----------------------------------------------------------------------------------------#
201
- class PluginManagerCliSearch < Minitest::Test
202
- include CorePluginFunctionalHelper
203
- include PluginManagerHelpers
204
-
205
- # TODO: Thor can't hide options, but we wish it could.
206
- # def test_search_include_fixture_hidden_option
207
- # result = run_inspec_process_with_this_plugin('plugin help search')
208
- # refute_includes result.stdout, '--include-test-fixture'
209
- # end
210
-
211
- def test_search_for_a_real_gem_with_full_name_no_options
212
- result = run_inspec_process("plugin search --include-test-fixture inspec-test-fixture")
213
-
214
- assert_includes result.stdout, "inspec-test-fixture", "Search result should contain the gem name"
215
- assert_includes result.stdout, "1 plugin(s) found", "Search result should find 1 plugin"
216
- line = result.stdout.split("\n").grep(/inspec-test-fixture/).first
217
- assert_match(/\s*inspec-test-fixture\s+\((\d+\.\d+\.\d+){1}\)/, line, "Plugin line should include name and exactly one version")
218
-
219
- assert_exit_code 0, result
220
- end
221
-
222
- def test_search_for_a_real_gem_with_stub_name_no_options
223
- result = run_inspec_process("plugin search --include-test-fixture inspec-test-")
224
-
225
- assert_includes result.stdout, "inspec-test-fixture", "Search result should contain the gem name"
226
- assert_includes result.stdout, "1 plugin(s) found", "Search result should find 1 plugin"
227
-
228
- line = result.stdout.split("\n").grep(/inspec-test-fixture/).first
229
- assert_match(/\s*inspec-test-fixture\s+\((\d+\.\d+\.\d+){1}\)/, line, "Plugin line should include name and exactly one version")
230
-
231
- assert_exit_code 0, result
232
- end
233
-
234
- def test_search_for_a_real_gem_with_full_name_and_exact_option
235
- result = run_inspec_process("plugin search --exact --include-test-fixture inspec-test-fixture")
236
-
237
- assert_includes result.stdout, "inspec-test-fixture", "Search result should contain the gem name"
238
- assert_includes result.stdout, "1 plugin(s) found", "Search result should find 1 plugin"
239
-
240
- assert_exit_code 0, result
241
-
242
- # TODO: split
243
- result = run_inspec_process("plugin search -e --include-test-fixture inspec-test-fixture")
244
-
245
- assert_exit_code 0, result
246
- end
247
-
248
- def test_search_for_a_real_gem_with_stub_name_and_exact_option
249
- result = run_inspec_process("plugin search --exact --include-test-fixture inspec-test-")
250
-
251
- assert_includes result.stdout, "0 plugin(s) found", "Search result should find 0 plugins"
252
-
253
- assert_exit_code 2, result
254
-
255
- # TODO: split
256
- result = run_inspec_process("plugin search -e --include-test-fixture inspec-test-")
257
-
258
- assert_exit_code 2, result
259
- end
260
-
261
- def test_search_for_a_real_gem_with_full_name_and_all_option
262
- result = run_inspec_process("plugin search --all --include-test-fixture inspec-test-fixture")
263
- assert_includes result.stdout, "inspec-test-fixture", "Search result should contain the gem name"
264
- assert_includes result.stdout, "1 plugin(s) found", "Search result should find 1 plugin"
265
-
266
- line = result.stdout.split("\n").grep(/inspec-test-fixture/).first
267
- assert_match(/\s*inspec-test-fixture\s+\((\d+\.\d+\.\d+(,\s)?){2,}\)/, line, "Plugin line should include name and at least two versions")
268
-
269
- assert_exit_code 0, result
270
-
271
- # TODO: split
272
- result = run_inspec_process("plugin search -a --include-test-fixture inspec-test-fixture")
273
-
274
- assert_exit_code 0, result
275
- end
276
-
277
- def test_search_for_a_gem_with_missing_prefix
278
- result = run_inspec_process("plugin search --include-test-fixture test-fixture")
279
- assert_exit_code 1, result
280
- assert_includes result.stdout, "All inspec plugins must begin with either 'inspec-' or 'train-'"
281
- end
282
-
283
- def test_search_for_a_gem_that_does_not_exist
284
- result = run_inspec_process("plugin search --include-test-fixture inspec-test-fixture-nonesuch")
285
-
286
- assert_includes result.stdout, "0 plugin(s) found", "Search result should find 0 plugins"
287
-
288
- assert_exit_code 2, result
289
- end
290
-
291
- def test_search_for_a_real_gem_with_full_name_no_options_and_train_name
292
- result = run_inspec_process("plugin search --include-test-fixture train-test-fixture")
293
-
294
- assert_includes result.stdout, "train-test-fixture", "Search result should contain the gem name"
295
- assert_includes result.stdout, "1 plugin(s) found", "Search result should find 1 plugin"
296
- line = result.stdout.split("\n").grep(/train-test-fixture/).first
297
- assert_match(/\s*train-test-fixture\s+\((\d+\.\d+\.\d+){1}\)/, line, "Plugin line should include name and exactly one version")
298
-
299
- assert_exit_code 0, result
300
- end
301
-
302
- def test_search_omit_excluded_inspec_plugins
303
- result = run_inspec_process("plugin search --include-test-fixture inspec-")
304
-
305
- assert_includes result.stdout, "inspec-test-fixture", "Search result should contain the test gem"
306
- %w{
307
- inspec-core
308
- inspec-multi-server
309
- }.each do |plugin_name|
310
- refute_includes result.stdout, plugin_name, "Search result should not contain excluded gems"
311
- end
312
-
313
- assert_exit_code 0, result
314
- end
315
-
316
- def test_search_for_a_real_gem_with_full_name_no_options_filter_fixtures
317
- result = run_inspec_process("plugin search inspec-test-fixture")
318
- refute_includes result.stdout, "inspec-test-fixture", "Search result should not contain the fixture gem name"
319
- end
320
-
321
- def test_search_for_a_real_gem_with_full_name_no_options_filter_fixtures_train
322
- result = run_inspec_process("plugin search train-test-fixture")
323
- refute_includes result.stdout, "train-test-fixture", "Search result should not contain the fixture gem name"
324
- end
325
-
326
- end
327
-
328
- #-----------------------------------------------------------------------------------------#
329
- # inspec plugin install
330
- #-----------------------------------------------------------------------------------------#
331
- class PluginManagerCliInstall < Minitest::Test
332
- include CorePluginFunctionalHelper # gives us instance methods, like `let` aliases inside test methods
333
- extend CorePluginFunctionalHelper # gives us class methods, like `let` aliases out here outside test methods
334
-
335
- include PluginManagerHelpers
336
- ruby_abi_version = (Gem.ruby_version.segments[0, 2] << 0).join(".")
337
- # Test multiple hueristics of the path-mode install.
338
- # These are all positive tests; they should resolve the entry point to the same path in each case.
339
- {
340
- "is_perfect" => {
341
- given: File.join(core_fixture_plugins_path, "inspec-test-fixture", "lib", "inspec-test-fixture.rb"),
342
- },
343
- "refers_to_the_entry_point_with_no_extension" => {
344
- given: File.join(core_fixture_plugins_path, "inspec-test-fixture", "lib", "inspec-test-fixture"),
345
- },
346
- "refers_to_the_src_root_of_a_plugin" => {
347
- given: File.join(core_fixture_plugins_path, "inspec-test-fixture"),
348
- },
349
- "refers_to_a_versioned_gem_install" => {
350
- 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"),
351
- 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"),
352
- },
353
- "refers_to_a_versioned_gem_install_missing_extension" => {
354
- 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"),
355
- 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"),
356
- },
357
- "refers_to_a_relative_path" => {
358
- given: File.join("test", "unit", "mock", "plugins", "inspec-test-fixture", "lib", "inspec-test-fixture.rb"),
359
- },
360
- "refers_to_a_train_plugin" => {
361
- 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"),
362
- plugin_name: "train-test-fixture",
363
- 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"),
364
- },
365
- }.each do |test_name, fixture_info|
366
- define_method(("test_install_from_path_when_path_" + test_name).to_sym) do
367
- fixture_info = {
368
- plugin_name: "inspec-test-fixture",
369
- resolved_path: File.join(core_fixture_plugins_path, "inspec-test-fixture", "lib", "inspec-test-fixture.rb"),
370
- }.merge(fixture_info)
371
-
372
- install_result = run_inspec_process_with_this_plugin("plugin install #{fixture_info[:given]}", post_run: list_after_run)
373
-
374
- # Check UX messaging
375
- success_message = install_result.stdout.split("\n").grep(/installed/).last
376
- skip_windows!
377
- assert_empty install_result.stderr
378
- refute_nil success_message, "Should find a success message at the end"
379
- assert_includes success_message, fixture_info[:plugin_name]
380
- assert_includes success_message, "plugin installed via source path reference"
381
-
382
- # Check round-trip UX via list
383
- itf_plugin = install_result.payload.list_result.detect { |p| p[:name] == fixture_info[:plugin_name] }
384
- refute_nil itf_plugin, "plugin name should now appear in the output of inspec list"
385
- assert_equal "path", itf_plugin[:type], "list output should show that it is a path installation"
386
-
387
- # Check plugin statefile. Extra important in this case, since all should resolve to the same entry point.
388
- plugin_data = install_result.payload.plugin_data
389
- entry = plugin_data["plugins"].detect { |e| e["name"] == fixture_info[:plugin_name] }
390
- assert_equal fixture_info[:resolved_path], entry["installation_path"], "Regardless of input, the entry point should be correct."
391
-
392
- assert_exit_code 0, install_result
393
- end
394
- end
395
-
396
- def test_fail_install_from_nonexistant_path
397
- bad_path = File.join(project_fixtures_path, "none", "such", "inspec-test-fixture-nonesuch.rb")
398
- install_result = run_inspec_process_with_this_plugin("plugin install #{bad_path}")
399
- skip_windows!
400
-
401
- error_message = install_result.stdout
402
- assert_includes error_message, "No such source code path"
403
- assert_includes error_message, "inspec-test-fixture-nonesuch.rb"
404
- assert_includes error_message, "installation failed"
405
-
406
- assert_empty install_result.stderr
407
-
408
- assert_exit_code 1, install_result
409
- end
410
-
411
- def test_fail_install_from_path_with_wrong_name
412
- bad_path = File.join(project_fixtures_path, "plugins", "wrong-name", "lib", "wrong-name.rb")
413
- install_result = run_inspec_process_with_this_plugin("plugin install #{bad_path}")
414
- skip_windows!
415
-
416
- error_message = install_result.stdout
417
- assert_includes error_message, "Invalid plugin name"
418
- assert_includes error_message, "wrong-name"
419
- assert_includes error_message, "All inspec plugins must begin with either 'inspec-' or 'train-'"
420
- assert_includes error_message, "installation failed"
421
-
422
- assert_empty install_result.stderr
423
-
424
- assert_exit_code 1, install_result
425
- end
426
-
427
- def test_fail_install_from_path_when_it_is_not_a_plugin
428
- bad_path = File.join(project_fixtures_path, "plugins", "inspec-egg-white-omelette", "lib", "inspec-egg-white-omelette.rb")
429
- install_result = run_inspec_process_with_this_plugin("plugin install #{bad_path}")
430
- skip_windows!
431
-
432
- error_message = install_result.stdout
433
- assert_includes error_message, "Does not appear to be a plugin"
434
- assert_includes error_message, "inspec-egg-white-omelette"
435
- assert_includes error_message, "After probe-loading the supposed plugin, it did not register"
436
- assert_includes error_message, "Ensure something inherits from 'Inspec.plugin(2)'"
437
- assert_includes error_message, "installation failed"
438
-
439
- assert_empty install_result.stderr
440
-
441
- assert_exit_code 1, install_result
442
- end
443
-
444
- def test_fail_install_from_path_when_it_is_already_installed
445
- plugin_path = File.join(core_fixture_plugins_path, "inspec-test-fixture", "lib", "inspec-test-fixture.rb")
446
- pre_block = Proc.new do |plugin_data, _tmp_dir|
447
- plugin_data["plugins"] << {
448
- "name" => "inspec-test-fixture",
449
- "installation_type" => "path",
450
- "installation_path" => plugin_path,
451
- }
452
- end
453
-
454
- install_result = run_inspec_process_with_this_plugin("plugin install #{plugin_path}", pre_run: pre_block)
455
- skip_windows!
456
-
457
- error_message = install_result.stdout
458
- assert_includes error_message, "Plugin already installed"
459
- assert_includes error_message, "inspec-test-fixture"
460
- assert_includes error_message, "Use 'inspec plugin list' to see previously installed plugin"
461
- assert_includes error_message, "installation failed"
462
-
463
- assert_empty install_result.stderr
464
-
465
- assert_exit_code 2, install_result
466
- end
467
-
468
- def test_fail_install_from_path_when_the_dir_structure_is_wrong
469
- bad_path = File.join(project_fixtures_path, "plugins", "inspec-wrong-structure")
470
- install_result = run_inspec_process_with_this_plugin("plugin install #{bad_path}")
471
- skip_windows!
472
-
473
- error_message = install_result.stdout
474
- assert_includes error_message, "Unrecognizable plugin structure"
475
- assert_includes error_message, "inspec-wrong-structure"
476
- assert_includes error_message, " When installing from a path, please provide the path of the entry point file"
477
- assert_includes error_message, "installation failed"
478
-
479
- assert_empty install_result.stderr
480
-
481
- assert_exit_code 1, install_result
482
- end
483
-
484
- def test_install_from_gemfile
485
- fixture_gemfile_path = File.join(core_fixture_plugins_path, "inspec-test-fixture", "pkg", "inspec-test-fixture-0.1.0.gem")
486
- install_result = run_inspec_process_with_this_plugin("plugin install #{fixture_gemfile_path}", post_run: list_after_run)
487
- skip_windows!
488
-
489
- success_message = install_result.stdout.split("\n").grep(/installed/).last
490
- refute_nil success_message, "Should find a success message at the end"
491
- assert_includes success_message, "installed from local .gem file"
492
-
493
- itf_plugin = install_result.payload.list_result.detect { |p| p[:name] == "inspec-test-fixture" }
494
- refute_nil itf_plugin, "plugin name should now appear in the output of inspec list"
495
- assert_equal "gem (user)", itf_plugin[:type]
496
- assert_equal "0.1.0", itf_plugin[:version]
497
-
498
- assert_empty install_result.stderr
499
- assert_exit_code 0, install_result
500
- end
501
-
502
- def test_fail_install_from_nonexistant_gemfile
503
- bad_path = File.join(project_fixtures_path, "none", "such", "inspec-test-fixture-nonesuch-0.3.0.gem")
504
- install_result = run_inspec_process_with_this_plugin("plugin install #{bad_path}")
505
-
506
- skip_windows!
507
- assert_match(/No such plugin gem file .+ - installation failed./, install_result.stdout)
508
-
509
- assert_empty install_result.stderr
510
-
511
- assert_exit_code 1, install_result
512
- end
513
-
514
- def test_install_from_rubygems_latest
515
- install_result = run_inspec_process_with_this_plugin("plugin install inspec-test-fixture", post_run: list_after_run)
516
- skip_windows!
517
-
518
- success_message = install_result.stdout.split("\n").grep(/installed/).last
519
- refute_nil success_message, "Should find a success message at the end"
520
- assert_includes success_message, "inspec-test-fixture"
521
- assert_includes success_message, "0.2.0"
522
- assert_includes success_message, "installed from rubygems.org"
523
-
524
- itf_plugin = install_result.payload.list_result.detect { |p| p[:name] == "inspec-test-fixture" }
525
- refute_nil itf_plugin, "plugin name should now appear in the output of inspec list"
526
- assert_equal "gem (user)", itf_plugin[:type]
527
- assert_equal "0.2.0", itf_plugin[:version]
528
-
529
- assert_empty install_result.stderr
530
- assert_exit_code 0, install_result
531
- end
532
-
533
- def test_fail_install_from_nonexistant_remote_rubygem
534
- install_result = run_inspec_process_with_this_plugin("plugin install inspec-test-fixture-nonesuch")
535
-
536
- skip_windows!
537
- assert_match(/No such plugin gem .+ could be found on rubygems.org - installation failed./, install_result.stdout)
538
-
539
- assert_empty install_result.stderr
540
-
541
- assert_exit_code 1, install_result
542
- end
543
-
544
- def test_install_from_rubygems_with_pinned_version
545
- install_result = run_inspec_process_with_this_plugin("plugin install inspec-test-fixture -v 0.1.0", post_run: list_after_run)
546
-
547
- success_message = install_result.stdout.split("\n").grep(/installed/).last
548
- skip_windows!
549
- refute_nil success_message, "Should find a success message at the end"
550
- assert_includes success_message, "inspec-test-fixture"
551
- assert_includes success_message, "0.1.0"
552
- assert_includes success_message, "installed from rubygems.org"
553
-
554
- itf_plugin = install_result.payload.list_result.detect { |p| p[:name] == "inspec-test-fixture" }
555
- refute_nil itf_plugin, "plugin name should now appear in the output of inspec list"
556
- assert_equal "gem (user)", itf_plugin[:type]
557
- assert_equal "0.1.0", itf_plugin[:version]
558
-
559
- assert_empty install_result.stderr
560
-
561
- assert_exit_code 0, install_result
562
- end
563
-
564
- def test_fail_install_from_nonexistant_rubygem_version
565
- install_result = run_inspec_process_with_this_plugin("plugin install inspec-test-fixture -v 99.99.99")
566
-
567
- fail_message = install_result.stdout.split("\n").grep(/failed/).last
568
- skip_windows!
569
- refute_nil fail_message, "Should find a failure message at the end"
570
- assert_includes fail_message, "inspec-test-fixture"
571
- assert_includes fail_message, "99.99.99"
572
- assert_includes fail_message, "no such version"
573
- assert_includes fail_message, "on rubygems.org"
574
-
575
- assert_empty install_result.stderr
576
-
577
- assert_exit_code 1, install_result
578
- end
579
-
580
- def test_refuse_install_when_missing_prefix
581
- install_result = run_inspec_process_with_this_plugin("plugin install test-fixture")
582
-
583
- fail_message = install_result.stdout.split("\n").grep(/failed/).last
584
- skip_windows!
585
- refute_nil fail_message, "Should find a failure message at the end"
586
- assert_includes fail_message, "test-fixture"
587
- assert_includes fail_message, "All inspec plugins must begin with either 'inspec-' or 'train-'"
588
-
589
- assert_empty install_result.stderr
590
-
591
- assert_exit_code 1, install_result
592
- end
593
-
594
- def test_refuse_install_when_already_installed_same_version
595
- pre_block = Proc.new do |plugin_statefile_data, tmp_dir|
596
- plugin_statefile_data.clear # Signal not to write a file, we'll provide one.
597
- copy_in_core_config_dir("test-fixture-2-float", tmp_dir)
598
- end
599
-
600
- install_result = run_inspec_process_with_this_plugin("plugin install inspec-test-fixture", pre_run: pre_block)
601
-
602
- refusal_message = install_result.stdout.split("\n").grep(/refusing/).last
603
- skip_windows!
604
- refute_nil refusal_message, "Should find a failure message at the end"
605
- assert_includes refusal_message, "inspec-test-fixture"
606
- assert_includes refusal_message, "0.2.0"
607
- assert_includes refusal_message, "Plugin already installed at latest version"
608
-
609
- assert_empty install_result.stderr
610
-
611
- assert_exit_code 2, install_result
612
- end
613
-
614
- def test_refuse_install_when_already_installed_can_update
615
- pre_block = Proc.new do |plugin_statefile_data, tmp_dir|
616
- plugin_statefile_data.clear # Signal not to write a file, we'll provide one.
617
- copy_in_core_config_dir("test-fixture-1-float", tmp_dir)
618
- end
619
-
620
- install_result = run_inspec_process_with_this_plugin("plugin install inspec-test-fixture", pre_run: pre_block)
621
-
622
- refusal_message = install_result.stdout.split("\n").grep(/refusing/).last
623
- skip_windows!
624
- refute_nil refusal_message, "Should find a failure message at the end"
625
- assert_includes refusal_message, "inspec-test-fixture"
626
- assert_includes refusal_message, "0.1.0"
627
- assert_includes refusal_message, "0.2.0"
628
- assert_includes refusal_message, "Update required"
629
- assert_includes refusal_message, "inspec plugin update"
630
-
631
- assert_empty install_result.stderr
632
-
633
- assert_exit_code 2, install_result
634
- end
635
-
636
- def test_install_from_rubygems_latest_with_train_plugin
637
- install_result = run_inspec_process_with_this_plugin("plugin install train-test-fixture", post_run: list_after_run)
638
- skip_windows!
639
-
640
- success_message = install_result.stdout.split("\n").grep(/installed/).last
641
- refute_nil success_message, "Should find a success message at the end"
642
- assert_includes success_message, "train-test-fixture"
643
- assert_includes success_message, "0.1.0"
644
- assert_includes success_message, "installed from rubygems.org"
645
-
646
- ttf_plugin = install_result.payload.list_result.detect { |p| p[:name] == "train-test-fixture" }
647
- refute_nil ttf_plugin, "plugin name should now appear in the output of inspec list"
648
- assert_equal "gem (user)", ttf_plugin[:type]
649
- assert_equal "0.1.0", ttf_plugin[:version]
650
-
651
- assert_empty install_result.stderr
652
- assert_exit_code 0, install_result
653
- end
654
-
655
- def test_refuse_install_when_plugin_on_exclusion_list
656
- # Here, 'inspec-core', 'inspec-multi-server', and 'train-tax-collector'
657
- # are the names of real rubygems. They are not InSpec/Train plugins, though,
658
- # and installing them would be a jam-up.
659
- # This is configured in 'etc/plugin-filter.json'.
660
- %w{
661
- inspec-core
662
- inspec-multi-server
663
- train-tax-calculator
664
- }.each do |plugin_name|
665
- install_result = run_inspec_process_with_this_plugin("plugin install #{plugin_name}")
666
- refusal_message = install_result.stdout
667
- refute_nil refusal_message, "Should find a failure message at the end"
668
- skip_windows!
669
- assert_includes refusal_message, plugin_name
670
- assert_includes refusal_message, "Plugin on Exclusion List"
671
- assert_includes refusal_message, "refusing to install"
672
- assert_includes refusal_message, "Rationale:"
673
- assert_includes refusal_message, "etc/plugin_filters.json"
674
- assert_includes refusal_message, "github.com/inspec/inspec/issues/new"
675
-
676
- assert_empty install_result.stderr
677
-
678
- assert_exit_code 2, install_result
679
- end
680
- end
681
-
682
- def test_error_install_with_debug_enabled
683
- skip "this test requires bundler to pass" unless defined? ::Bundler
684
-
685
- install_result = run_inspec_process_with_this_plugin("plugin install inspec-test-fixture -v 0.1.1 --log-level debug")
686
- skip_windows!
687
-
688
- assert_includes install_result.stdout, "DEBUG"
689
-
690
- assert_includes install_result.stderr, "can't activate rake"
691
-
692
- assert_exit_code 1, install_result
693
- end
694
- end
695
-
696
- #-----------------------------------------------------------------------------------------#
697
- # inspec plugin update
698
- #-----------------------------------------------------------------------------------------#
699
- class PluginManagerCliUpdate < Minitest::Test
700
- include CorePluginFunctionalHelper
701
- include PluginManagerHelpers
702
-
703
- def test_when_a_plugin_can_be_updated
704
- skip "this test requires bundler to pass" unless defined? ::Bundler
705
-
706
- pre_block = Proc.new do |plugin_statefile_data, tmp_dir|
707
- plugin_statefile_data.clear # Signal not to write a file, we'll provide one.
708
- copy_in_core_config_dir("test-fixture-1-float", tmp_dir)
709
- end
710
-
711
- update_result = run_inspec_process_with_this_plugin("plugin update inspec-test-fixture", pre_run: pre_block, post_run: list_after_run)
712
-
713
- success_message = update_result.stdout.split("\n").grep(/updated/).last
714
- skip_windows!
715
- refute_nil success_message, "Should find a success message at the end"
716
- assert_includes success_message, "inspec-test-fixture"
717
- assert_includes success_message, "0.1.0"
718
- assert_includes success_message, "0.2.0"
719
- assert_includes success_message, "updated from rubygems.org"
720
-
721
- itf_plugin = update_result.payload.list_result.detect { |p| p[:name] == "inspec-test-fixture" }
722
- refute_nil itf_plugin, "plugin name should now appear in the output of inspec list"
723
- assert_equal "gem (user)", itf_plugin[:type]
724
- assert_equal "0.2.0", itf_plugin[:version]
725
-
726
- assert_empty update_result.stderr
727
- assert_exit_code 0, update_result
728
- end
729
-
730
- def test_refuse_update_when_already_current
731
- pre_block = Proc.new do |plugin_statefile_data, tmp_dir|
732
- plugin_statefile_data.clear # Signal not to write a file, we'll provide one.
733
- copy_in_core_config_dir("test-fixture-2-float", tmp_dir)
734
- end
735
-
736
- update_result = run_inspec_process_with_this_plugin("plugin update inspec-test-fixture", pre_run: pre_block)
737
-
738
- refusal_message = update_result.stdout.split("\n").grep(/refusing/).last
739
- skip_windows!
740
- refute_nil refusal_message, "Should find a failure message at the end"
741
- assert_includes refusal_message, "inspec-test-fixture"
742
- assert_includes refusal_message, "0.2.0"
743
- assert_includes refusal_message, "Already installed at latest version"
744
-
745
- assert_empty update_result.stderr
746
-
747
- assert_exit_code 2, update_result
748
- end
749
-
750
- def test_fail_update_from_nonexistant_gem
751
- update_result = run_inspec_process_with_this_plugin("plugin update inspec-test-fixture-nonesuch")
752
-
753
- skip_windows!
754
- assert_match(/No such plugin installed:.+ - update failed/, update_result.stdout)
755
-
756
- assert_empty update_result.stderr
757
-
758
- assert_exit_code 1, update_result
759
- end
760
-
761
- def test_fail_update_path
762
- pre_block = Proc.new do |plugin_statefile_data, tmp_dir|
763
- plugin_statefile_data.clear # Signal not to write a file, we'll provide one.
764
- copy_in_core_config_dir("meaning_by_path", tmp_dir)
765
- end
766
-
767
- update_result = run_inspec_process_with_this_plugin("plugin update inspec-meaning-of-life", pre_run: pre_block)
768
-
769
- refusal_message = update_result.stdout.split("\n").grep(/refusing/).last
770
- skip_windows!
771
- refute_nil refusal_message, "Should find a failure message at the end"
772
- assert_includes refusal_message, "inspec-meaning-of-life"
773
- assert_includes refusal_message, "inspec plugin uninstall"
774
- assert_includes refusal_message, "Cannot update path-based install"
775
-
776
- assert_empty update_result.stderr
777
-
778
- assert_exit_code 2, update_result
779
- end
780
- end
781
-
782
- #-----------------------------------------------------------------------------------------#
783
- # inspec plugin uninstall
784
- #-----------------------------------------------------------------------------------------#
785
- class PluginManagerCliUninstall < Minitest::Test
786
- include CorePluginFunctionalHelper
787
- include PluginManagerHelpers
788
-
789
- def test_when_a_gem_plugin_can_be_uninstalled
790
- pre_block = Proc.new do |plugin_statefile_data, tmp_dir|
791
- plugin_statefile_data.clear # Signal not to write a file, we'll provide one.
792
- copy_in_core_config_dir("test-fixture-1-float", tmp_dir)
793
- end
794
-
795
- # Attempt uninstall
796
- uninstall_result = run_inspec_process_with_this_plugin("plugin uninstall inspec-test-fixture", pre_run: pre_block, post_run: list_after_run)
797
-
798
- success_message = uninstall_result.stdout.split("\n").grep(/uninstalled/).last
799
- skip_windows!
800
- refute_nil success_message, "Should find a success message at the end"
801
- assert_includes success_message, "inspec-test-fixture"
802
- assert_includes success_message, "0.1.0"
803
- assert_includes success_message, "has been uninstalled"
804
-
805
- itf_plugins = uninstall_result.payload.list_result.select { |p| p[:name] == "inspec-test-fixture" }
806
- assert_empty itf_plugins, "inspec-test-fixture should not appear in the output of inspec list"
807
-
808
- assert_empty uninstall_result.stderr
809
- assert_exit_code 0, uninstall_result
810
- end
811
-
812
- def test_when_a_path_plugin_can_be_uninstalled
813
- pre_block = Proc.new do |plugin_statefile_data, tmp_dir|
814
- plugin_statefile_data.clear # Signal not to write a file, we'll provide one.
815
- # This fixture includes a path install for inspec-meaning-of-life
816
- copy_in_core_config_dir("test-fixture-1-float", tmp_dir)
817
- end
818
- uninstall_result = run_inspec_process_with_this_plugin("plugin uninstall inspec-meaning-of-life", pre_run: pre_block, post_run: list_after_run)
819
- skip_windows!
820
-
821
- success_message = uninstall_result.stdout.split("\n").grep(/uninstalled/).last
822
- refute_nil success_message, "Should find a success message at the end"
823
- assert_includes success_message, "inspec-meaning-of-life"
824
- assert_includes success_message, "path-based plugin install"
825
- assert_includes success_message, "has been uninstalled"
826
-
827
- itf_plugins = uninstall_result.payload.list_result.select { |p| p[:name] == "inspec-meaning-of-life" }
828
- assert_empty itf_plugins, "inspec-meaning-of-life should not appear in the output of inspec list"
829
-
830
- assert_empty uninstall_result.stderr
831
- assert_exit_code 0, uninstall_result
832
- end
833
-
834
- def test_fail_uninstall_from_plugin_that_is_not_installed
835
- uninstall_result = run_inspec_process_with_this_plugin("plugin uninstall inspec-test-fixture-nonesuch")
836
-
837
- skip_windows!
838
- refute_includes "Inspec::Plugin::V2::UnInstallError", uninstall_result.stdout # Stacktrace marker
839
- assert_match(/No such plugin installed:.+ - uninstall failed/, uninstall_result.stdout)
840
-
841
- assert_empty uninstall_result.stderr
842
-
843
- assert_exit_code 1, uninstall_result
844
- end
845
- end