Merge pull request #4365 from inspec/zenspider/the-need-for-speed

Make inspec much faster for most commands.
This commit is contained in:
Ryan Davis 2019-09-09 18:02:10 -07:00 committed by GitHub
commit f5bbfe5fac
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
19 changed files with 78 additions and 27 deletions

View file

@ -28,4 +28,3 @@ require "inspec/base_cli"
require "inspec/fetcher"
require "inspec/source_reader"
require "inspec/resource"
require "inspec/resources"

View file

@ -4,6 +4,7 @@ require "train"
require "inspec/config"
require "inspec/version"
require "inspec/resource"
require "inspec/dsl" # for method_missing_resource
module Inspec
module Backend
@ -77,6 +78,12 @@ module Inspec
connection
end
def method_missing(id, *args, &blk)
Inspec::DSL.method_missing_resource(self, id, *args)
rescue LoadError
super
end
Inspec::Resource.registry.each do |id, r|
define_method id.to_sym do |*args|
r.new(self, id.to_s, *args)

View file

@ -64,7 +64,6 @@ class Inspec::InspecCLI < Inspec::BaseCLI
desc: "A list of controls to include. Ignore all other tests."
profile_options
def json(target)
require "inspec/resources"
require "json"
o = config
@ -103,8 +102,6 @@ class Inspec::InspecCLI < Inspec::BaseCLI
option :format, type: :string
profile_options
def check(path) # rubocop:disable Metrics/AbcSize,Metrics/MethodLength
require "inspec/resources"
o = config
diagnose(o)
o["log_location"] ||= STDERR if o["format"] == "json"
@ -157,8 +154,6 @@ class Inspec::InspecCLI < Inspec::BaseCLI
option :overwrite, type: :boolean, default: false,
desc: "Overwrite existing vendored dependencies and lockfile."
def vendor(path = nil)
require "inspec/resources"
o = config
configure_logger(o)
o[:logger] = Logger.new($stdout)
@ -180,8 +175,6 @@ class Inspec::InspecCLI < Inspec::BaseCLI
option :ignore_errors, type: :boolean, default: false,
desc: "Ignore profile warnings."
def archive(path)
require "inspec/resources"
o = config
diagnose(o)

View file

@ -66,9 +66,11 @@ module Inspec
# We still haven't called it, so do so now.
send(method_name, *arguments, &block)
else
# If we couldn't find a plugin to match, maybe something up above has it,
# or maybe it is just a unknown method error.
super
begin
Inspec::DSL.method_missing_resource(inspec, method_name, *arguments)
rescue LoadError
super
end
end
end

View file

@ -3,6 +3,8 @@ require "inspec/log"
require "inspec/plugin/v2"
module Inspec::DSL
attr_accessor :backend
def require_controls(id, &block)
opts = { profile_id: id, include_all: false, backend: @backend, conf: @conf, dependencies: @dependencies }
::Inspec::DSL.load_spec_files_for_profile(self, opts, &block)
@ -25,6 +27,23 @@ module Inspec::DSL
add_resource(target_name, res)
end
##
# Try to load and instantiate a missing resource or raise LoadError
# if unable. Requiring the resource registers it and generates a
# method for it so you should only hit this once per missing
# resource.
def self.method_missing_resource(backend, id, *arguments)
begin
require "inspec/resources/#{id}"
rescue LoadError
require "resources/aws/#{id}"
end
klass = Inspec::Resource.registry[id.to_s]
klass.new(backend, id, *arguments)
end
# Support for Outer Profile DSL plugins
# This is called when an unknown method is encountered
# "bare" in a control file - outside of a control or describe block.
@ -44,7 +63,11 @@ module Inspec::DSL
# We still haven't called it, so do so now.
send(method_name, *arguments, &block)
else
super
begin
Inspec::DSL.method_missing_resource(backend, method_name, *arguments)
rescue LoadError
super
end
end
end

View file

@ -1,3 +1,5 @@
require "inspec/errors"
# Impact scores based off CVSS 3.0
module Inspec::Impact
IMPACT_SCORES = {

View file

@ -31,8 +31,10 @@ module Inspec
def supports(criteria = nil)
return if criteria.nil?
Inspec::Resource.supports[@name] ||= []
Inspec::Resource.supports[@name].push(criteria)
key = @name.to_sym
Inspec::Resource.supports[key] ||= []
Inspec::Resource.supports[key].push(criteria)
end
def example(example = nil)
@ -80,7 +82,7 @@ module Inspec
def initialize(backend, name, *args)
@resource_skipped = false
@resource_failed = false
@supports = Inspec::Resource.supports[name]
@supports = Inspec::Resource.supports[name.to_sym]
@resource_exception_message = nil
# attach the backend to this instance
@ -124,6 +126,7 @@ module Inspec
end
def check_supports
require "inspec/resources/platform"
status = inspec.platform.supported?(@supports)
fail_msg = "Resource `#{@__resource_name__}` is not supported on platform #{inspec.platform.name}/#{inspec.platform.release}."
fail_resource(fail_msg) unless status
@ -165,7 +168,7 @@ module Inspec
end
module Plugins
class Resource
class Resource # TODO: possibly push up to inspec/resource.rb
extend Inspec::ResourceDSL
include Inspec::ResourceBehaviors
end

View file

@ -74,6 +74,7 @@ module Inspec
# @return [Resource] base class for creating a new resource
def self.resource(version)
validate_resource_dsl_version!(version)
require "inspec/plugin/v1/plugin_types/resource"
Inspec::Plugins::Resource
end

View file

@ -1,11 +1,18 @@
##
# Now that resources are lazily loaded, this file is ONLY here for one
# reason at this point, to load all the resources in order to populate
# the registry for `inspec shell`'s `help commands`. There has to be a
# cheaper way to do this, but this will do for now.
#
# NOTE: I intentionally didn't convert this to a loop over a simple
# glob so this remains a sort of manifest for our resources.
require "inspec/resource"
# Detect if we are running the stripped-down inspec-core
# This relies on AWS being stripped from the inspec-core gem
inspec_core_only = ENV["NO_AWS"] || !File.exist?(File.join(File.dirname(__FILE__), "..", "resource_support", "aws.rb"))
require "rspec/matchers"
# Do not attempt to load cloud resources if we are in inspec-core mode
unless inspec_core_only
require "resource_support/aws"

View file

@ -1,3 +1,5 @@
require "inspec/resource"
module Inspec::Resources
class PlatformResource < Inspec.resource(1)
name "platform"

View file

@ -0,0 +1 @@
require "inspec/resources/users"

View file

@ -9,7 +9,6 @@ require "inspec/metadata"
require "inspec/config"
require "inspec/dependencies/cache"
require "inspec/dist"
require "inspec/resources"
require "inspec/reporters"
require "inspec/runner_rspec"
# spec requirements

View file

@ -112,6 +112,7 @@ module Inspec
#{print_target_info}
EOF
elsif topic == "resources"
require "inspec/resources"
resources.sort.each do |resource|
puts " - #{resource}"
end
@ -134,7 +135,13 @@ module Inspec
info += "https://www.inspec.io/docs/reference/resources/#{topic}\n\n"
puts info
else
puts "The resource #{topic} does not exist. For a list of valid resources, type: help resources"
begin
require "inspec/resources/#{topic}"
help topic
rescue LoadError
# TODO: stderr!
puts "The resource #{topic} does not exist. For a list of valid resources, type: help resources"
end
end
end

View file

@ -1,5 +1,7 @@
# copyright: 2015, Vulcano Security GmbH
require "rspec/matchers"
RSpec::Matchers.define :be_readable do
match do |file|
file.readable?(@by, @by_user)

View file

@ -1,5 +1,3 @@
require "inspec/resources"
class MockLoader
# collects emulation operating systems
OPERATING_SYSTEMS = {

View file

@ -57,10 +57,15 @@ describe Inspec::Plugins::Resource do
describe "supported platform" do
def supports_meta(supports)
Inspec::Resource.supports["os"] = supports
@old = Inspec::Resource.supports[:os]
Inspec::Resource.supports[:os] = supports
load_resource("os")
end
after do
Inspec::Resource.supports[:os] = @old
end
it "loads a profile which supports multiple families" do
m = supports_meta([
{ os_family: "windows" },

View file

@ -1,6 +1,7 @@
require "helper"
require "inspec/resource"
require "inspec/resources/command"
require "inspec/resources/os"
describe Inspec::Resources::Cmd do
let(:x) { rand.to_s }

View file

@ -125,7 +125,7 @@ describe "Inspec::Resources::Package" do
end
# darwin (brew)
it "can parse ouptut from `brew` when package is installed" do
it "can parse ouptut from 'brew' when package is installed" do
resource = MockLoader.new(:osx104).load_resource("package", "curl")
pkg = { name: "curl", installed: true, version: "7.52.1", type: "brew" }
_(resource.installed?).must_equal true
@ -133,7 +133,7 @@ describe "Inspec::Resources::Package" do
_(resource.info).must_equal pkg
end
it "can parse ouptut from `brew` when package is not installed but exists" do
it "can parse ouptut from 'brew' when package is not installed but exists" do
resource = MockLoader.new(:osx104).load_resource("package", "nginx")
pkg = {}
_(resource.installed?).must_equal false
@ -141,7 +141,7 @@ describe "Inspec::Resources::Package" do
_(resource.info).must_equal pkg
end
it "returns {} when `brew` exits non-zero" do
it "returns {} when 'brew' exits non-zero" do
resource = MockLoader.new(:osx104).load_resource("package", "nope")
pkg = {}
_(resource.installed?).must_equal false

View file

@ -1,5 +1,4 @@
require "helper"
require "inspec/resource"
require "inspec/resources/ssl"
require "sslshake"