Module: Inspec::DSL

Defined in:
lib/inspec/dsl_shared.rb,
lib/inspec/dsl.rb

Overview

Contains methods we would like in multiple DSL

Defined Under Namespace

Modules: RequireOverride

Instance Attribute Summary collapse

Class Method Summary collapse

Instance Method Summary collapse

Dynamic Method Handling

This class handles dynamic methods through the method_missing method

#method_missing(method_name, *arguments, &block) ⇒ Object

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.



50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
# File 'lib/inspec/dsl.rb', line 50

def method_missing(method_name, *arguments, &block)
  # Check to see if there is a outer_profile_dsl plugin activator hook with the method name
  registry = Inspec::Plugin::V2::Registry.instance
  hook = registry.find_activators(plugin_type: :outer_profile_dsl, activator_name: method_name).first
  if hook
    # OK, load the hook if it hasn't been already.  We'll then know a module,
    # which we can then inject into the context
    hook.activate
    # Inject the module's methods into the context
    # implementation_class is the field name, but this is actually a module.
    self.class.include(hook.implementation_class)
    # Now that the module is loaded, it defined one or more methods
    # (presumably the one we were looking for.)
    # We still haven't called it, so do so now.
    send(method_name, *arguments, &block)
  else
    begin
      Inspec::DSL.method_missing_resource(backend, method_name, *arguments)
    rescue LoadError
      super
    end
  end
end

Instance Attribute Details

#backendObject

Returns the value of attribute backend.



6
7
8
# File 'lib/inspec/dsl.rb', line 6

def backend
  @backend
end

Class Method Details

.filter_included_controls(context, profile, &block) ⇒ Object



100
101
102
103
104
105
106
107
108
109
110
111
112
# File 'lib/inspec/dsl.rb', line 100

def self.filter_included_controls(context, profile, &block)
  mock = Inspec::Backend.create(Inspec::Config.mock)
  include_ctx = Inspec::ProfileContext.for_profile(profile, mock)
  include_ctx.load(block) if block_given?
  # remove all rules that were not registered
  context.all_rules.each do |r|
    id = Inspec::Rule.rule_id(r)
    fid = Inspec::Rule.profile_id(r) + "/" + id
    unless include_ctx.rules[id] || include_ctx.rules[fid]
      context.remove_rule(fid)
    end
  end
end

.load_spec_files_for_profile(bind_context, opts, &block) ⇒ Object



74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
# File 'lib/inspec/dsl.rb', line 74

def self.load_spec_files_for_profile(bind_context, opts, &block)
  dependencies = opts[:dependencies]
  profile_id = opts[:profile_id]
  dep_entry = dependencies.list[profile_id]

  if dep_entry.nil?
    raise <<~EOF
      Cannot load '#{profile_id}' since it is not listed as a dependency of #{bind_context.profile_name}.

      Dependencies available from this context are:
          #{dependencies.list.keys.join("\n    ")}
    EOF
  end

  # Do not load any controls if the profile is not supported
  return unless dep_entry.profile.supports_platform?

  context = dep_entry.profile.runner_context
  # if we don't want all the rules, then just make 1 pass to get all rule_IDs
  # that we want to keep from the original
  filter_included_controls(context, dep_entry.profile, &block) unless opts[:include_all]
  # interpret the block and skip/modify as required
  context.load(block) if block_given?
  bind_context.add_subcontext(context)
end

.method_missing_resource(backend, id, *arguments) ⇒ Object

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.



36
37
38
39
40
41
42
43
44
45
# File 'lib/inspec/dsl.rb', line 36

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

Instance Method Details

#include_controls(id, &block) ⇒ Object Also known as: include_rules



13
14
15
16
# File 'lib/inspec/dsl.rb', line 13

def include_controls(id, &block)
  opts = { profile_id: id, include_all: true, backend: @backend, conf: @conf, dependencies: @dependencies }
  ::Inspec::DSL.load_spec_files_for_profile(self, opts, &block)
end

#require_controls(id, &block) ⇒ Object Also known as: require_rules



8
9
10
11
# File 'lib/inspec/dsl.rb', line 8

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)
end

#require_resource(options = {}) ⇒ Object



21
22
23
24
25
26
27
28
# File 'lib/inspec/dsl.rb', line 21

def require_resource(options = {})
  raise "You must specify a specific resource name when calling require_resource()" if options[:resource].nil?

  from_profile = options[:profile] || profile_name
  target_name = options[:as] || options[:resource]
  res = resource_class(from_profile, options[:resource])
  add_resource(target_name, res)
end