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.



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

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.



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

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

.plugin_gem_pathObject



132
133
134
135
136
137
138
139
# File 'lib/inspec/plugin/v2/loader.rb', line 132

def self.plugin_gem_path
  require "rbconfig" unless defined?(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



101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
# File 'lib/inspec/plugin/v2/loader.rb', line 101

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



85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
# File 'lib/inspec/plugin/v2/loader.rb', line 85

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



159
160
161
# File 'lib/inspec/plugin/v2/loader.rb', line 159

def list_installed_plugin_gems
  self.class.list_managed_gems
end

#list_managed_gemsObject



147
148
149
# File 'lib/inspec/plugin/v2/loader.rb', line 147

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
78
79
80
81
82
# 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]

    # Under some conditions (kitchen-inspec with multiple test suites, for example), this may be
    # called multple times. Don't reload anything.
    next if plugin_details.loaded

    # 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



128
129
130
# File 'lib/inspec/plugin/v2/loader.rb', line 128

def plugin_gem_path
  self.class.plugin_gem_path
end