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

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

Instance Attribute Summary collapse

Class Method Summary collapse

Instance Method Summary collapse

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
# File 'lib/inspec/plugin/v2/loader.rb', line 14

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

  # 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]

  # Train plugins aren't InSpec plugins (they don't use our API)
  # but InSpec CLI manages them.  So, we have to wrap them a bit.
  accommodate_train_plugins
end

Instance Attribute Details

#conf_fileObject (readonly)

Returns the value of attribute conf_file.



12
13
14
# File 'lib/inspec/plugin/v2/loader.rb', line 12

def conf_file
  @conf_file
end

#optionsObject (readonly)

Returns the value of attribute options.



12
13
14
# File 'lib/inspec/plugin/v2/loader.rb', line 12

def options
  @options
end

#registryObject (readonly)

Returns the value of attribute registry.



12
13
14
# File 'lib/inspec/plugin/v2/loader.rb', line 12

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-.

Returns:

  • (Array[Gem::Specification])

    Specs of all gems found.



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

def self.list_installed_plugin_gems
  list_managed_gems.select { |spec| spec.name.match(/^(inspec|train)-/) }
end

.list_managed_gemsArray[Gem::Specification]

Lists all gems found in the plugin_gem_path.

Returns:

  • (Array[Gem::Specification])

    Specs of all gems found.



126
127
128
# File 'lib/inspec/plugin/v2/loader.rb', line 126

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

.plugin_gem_pathObject



117
118
119
120
121
122
# File 'lib/inspec/plugin/v2/loader.rb', line 117

def self.plugin_gem_path
  # I can't believe there isn't a simpler way of getting this
  # 2.4.2.p123 => 2.4.0
  ruby_abi_version = (Gem.ruby_version.segments[0, 2] << 0).join('.')
  File.join(Inspec.config_dir, 'gems', ruby_abi_version)
end

Instance Method Details

#activate_mentioned_cli_plugins(cli_args = ARGV) ⇒ Object



82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
# File 'lib/inspec/plugin/v2/loader.rb', line 82

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`, activate all CLI plugins, so they can
    # display their usage message.
    activate_me ||= cli_args.first == 'help'

    # Likewise, if they invoked simply `inspec`, they are confused, and need
    # usage info.
    activate_me ||= cli_args.empty?

    # 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
      registry.activate(:cli_command, act.activator_name)
      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



66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
# File 'lib/inspec/plugin/v2/loader.rb', line 66

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



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

def list_installed_plugin_gems
  self.class.list_managed_gems
end

#list_managed_gemsObject



130
131
132
# File 'lib/inspec/plugin/v2/loader.rb', line 130

def list_managed_gems
  self.class.list_managed_gems
end

#load_allObject



33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
# File 'lib/inspec/plugin/v2/loader.rb', line 33

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`)
      if plugin_details.installation_type == :gem
        activate_managed_gems_for_plugin(plugin_name)
        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



113
114
115
# File 'lib/inspec/plugin/v2/loader.rb', line 113

def plugin_gem_path
  self.class.plugin_gem_path
end