Class: Inspec::Plugin::V2::Loader

Inherits:
Object
  • Object
show all
Extended by:
FilterPredicates
Includes:
FilterPredicates
Defined in:
lib/inspec/plugin/v2/loader.rb

Instance Attribute Summary collapse

Class Method Summary collapse

Instance Method Summary collapse

Methods included from FilterPredicates

inspec_plugin_name?, train_plugin_name?, valid_plugin_name?

Constructor Details

#initialize(options = {}) ⇒ Loader

Returns a new instance of Loader.



14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
# File 'lib/inspec/plugin/v2/loader.rb', line 14

def initialize(options = {})
  @options = options
  @registry = Inspec::Plugin::V2::Registry.instance

  # User plugins are those installed by the user via `inspec plugin install`
  # and are installed under ~/.inspec/gems
  unless options[:omit_user_plugins]
    @conf_file = Inspec::Plugin::V2::ConfigFile.new
    read_conf_file_into_registry
  end

  # Old-style (v0, v1) co-distributed plugins were called 'bundles'
  # and were located in lib/bundles
  detect_bundled_plugins unless options[:omit_bundles]

  # New-style (v2) co-distributed plugins are in lib/plugins,
  # and may be safely loaded
  detect_core_plugins unless options[:omit_core_plugins]

  # Identify plugins that inspec is co-installed with
  detect_system_plugins unless options[:omit_sys_plugins]

  # Train plugins are not true InSpec plugins; we need to decorate them a
  # bit more to integrate them. Wait to do this until after we know if
  # they are system or user.
  registry.each do |plugin_name, status|
    fixup_train_plugin_status(status) if train_plugin_name?(plugin_name)
  end
end

Instance Attribute Details

#conf_fileObject (readonly)

Returns the value of attribute conf_file.



8
9
10
# File 'lib/inspec/plugin/v2/loader.rb', line 8

def conf_file
  @conf_file
end

#optionsObject (readonly)

Returns the value of attribute options.



8
9
10
# File 'lib/inspec/plugin/v2/loader.rb', line 8

def options
  @options
end

#registryObject (readonly)

Returns the value of attribute registry.



8
9
10
# File 'lib/inspec/plugin/v2/loader.rb', line 8

def registry
  @registry
end

Class Method Details

.list_installed_plugin_gemsArray[Gem::Specification]

Lists all plugin gems found in the plugin_gem_path. This is simply all gems that begin with train- or inspec- and are not on the exclusion list.

Returns:

  • (Array[Gem::Specification])

    Specs of all gems found.



150
151
152
# File 'lib/inspec/plugin/v2/loader.rb', line 150

def self.list_installed_plugin_gems
  list_managed_gems.select { |spec| valid_plugin_name?(spec.name) }
end

.list_managed_gemsArray[Gem::Specification]

Lists all gems found in the plugin_gem_path.

Returns:

  • (Array[Gem::Specification])

    Specs of all gems found.



138
139
140
# File 'lib/inspec/plugin/v2/loader.rb', line 138

def self.list_managed_gems
  Dir.glob(File.join(plugin_gem_path, "specifications", "*.gemspec")).map { |p| Gem::Specification.load(p) }
end

.plugin_gem_pathObject



127
128
129
130
131
132
133
134
# File 'lib/inspec/plugin/v2/loader.rb', line 127

def self.plugin_gem_path
  require "rbconfig"
  ruby_abi_version = RbConfig::CONFIG["ruby_version"]
  # TODO: why are we installing under the api directory for plugins?
  base_dir = Inspec.config_dir
  base_dir = File.realpath base_dir if File.exist? base_dir
  File.join(base_dir, "gems", ruby_abi_version)
end

Instance Method Details

#activate_mentioned_cli_plugins(cli_args = ARGV) ⇒ Object



96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
# File 'lib/inspec/plugin/v2/loader.rb', line 96

def activate_mentioned_cli_plugins(cli_args = ARGV)
  # Get a list of CLI plugin activation hooks
  registry.find_activators(plugin_type: :cli_command).each do |act|
    next if act.activated?

    # Decide whether to activate.  Several conditions, so split them out for clarity.
    # Assume no, to start.  Each condition may flip it true, which will short-circuit
    # all following ||= ops.
    activate_me = false

    # If the user invoked `inspec help`, `inspec --help`, or only `inspec`
    # then activate all CLI plugins so they can display their usage message.
    activate_me ||= ["help", "--help", nil].include?(cli_args.first)

    # If there is anything in the CLI args with the same name, activate it.
    # This is the expected usual activation for individual plugins.
    # `inspec dosomething` => activate the :dosomething hook
    activate_me ||= cli_args.include?(act.activator_name.to_s)

    # OK, activate.
    if activate_me
      act.activate
      act.implementation_class.register_with_thor
    end
  end
end

#exit_on_load_errorObject

This should possibly be in either lib/inspec/cli.rb or Registry



80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
# File 'lib/inspec/plugin/v2/loader.rb', line 80

def exit_on_load_error
  if registry.any_load_failures?
    Inspec::Log.error "Errors were encountered while loading plugins..."
    registry.plugin_statuses.select(&:load_exception).each do |plugin_status|
      Inspec::Log.error "Plugin name: " + plugin_status.name.to_s
      Inspec::Log.error "Error: " + plugin_status.load_exception.message
      if ARGV.include?("--debug")
        Inspec::Log.error "Exception: " + plugin_status.load_exception.class.name
        Inspec::Log.error "Trace: " + plugin_status.load_exception.backtrace.join("\n")
      end
    end
    Inspec::Log.error("Run again with --debug for a stacktrace.") unless ARGV.include?("--debug")
    exit 2
  end
end

#list_installed_plugin_gemsObject



154
155
156
# File 'lib/inspec/plugin/v2/loader.rb', line 154

def list_installed_plugin_gems
  self.class.list_managed_gems
end

#list_managed_gemsObject



142
143
144
# File 'lib/inspec/plugin/v2/loader.rb', line 142

def list_managed_gems
  self.class.list_managed_gems
end

#load_allObject



44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
# File 'lib/inspec/plugin/v2/loader.rb', line 44

def load_all
  # This fixes the gem paths on some bundles
  Gem.path << plugin_gem_path
  Gem.refresh

  # Be careful not to actually iterate directly over the registry here;
  # we want to allow "sidecar loading", in which case a plugin may add an entry to the registry.
  registry.plugin_names.dup.each do |plugin_name|
    plugin_details = registry[plugin_name]
    # We want to capture literally any possible exception here, since we are storing them.
    # rubocop: disable Lint/RescueException
    begin
      # We could use require, but under testing, we need to repeatedly reload the same
      # plugin.  However, gems only work with require (rubygems dooes not overload `load`)
      case plugin_details.installation_type
      when :user_gem
        activate_managed_gems_for_plugin(plugin_name)
        require plugin_details.entry_point
      when :system_gem
        require plugin_details.entry_point
      else
        load_path = plugin_details.entry_point
        load_path += ".rb" unless plugin_details.entry_point.end_with?(".rb")
        load load_path
      end
      plugin_details.loaded = true
      annotate_status_after_loading(plugin_name)
    rescue ::Exception => ex
      plugin_details.load_exception = ex
      Inspec::Log.error "Could not load plugin #{plugin_name}: #{ex.message}"
    end
    # rubocop: enable Lint/RescueException
  end
end

#plugin_gem_pathObject



123
124
125
# File 'lib/inspec/plugin/v2/loader.rb', line 123

def plugin_gem_path
  self.class.plugin_gem_path
end