Class: Inspec::ControlEvalContext

Inherits:
Object
  • Object
show all
Includes:
DSL, DSL::RequireOverride
Defined in:
lib/inspec/control_eval_context.rb

Overview

ControlEvalContext constructs an anonymous class that control files will be instance_exec’d against.

The anonymous class includes the given passed resource_dsl as well as the basic DSL of the control files (describe, control, title, etc).

Instance Attribute Summary collapse

Attributes included from DSL

#backend

Instance Method Summary collapse

Methods included from DSL::RequireOverride

#__ruby_require, #require

Methods included from DSL

filter_included_controls, #include_controls, load_spec_files_for_profile, #method_missing, method_missing_resource, #require_controls, #require_resource

Constructor Details

#initialize(profile_context, resources_dsl, backend, conf, dependencies, require_loader, skip_only_if_eval) ⇒ ControlEvalContext

Returns a new instance of ControlEvalContext.



22
23
24
25
26
27
28
29
30
31
32
33
34
# File 'lib/inspec/control_eval_context.rb', line 22

def initialize(profile_context, resources_dsl, backend, conf, dependencies, require_loader, skip_only_if_eval)
  @profile_context = profile_context
  @resources_dsl = resources_dsl
  @backend = backend
  @conf = conf
  @dependencies = dependencies
  @require_loader = require_loader
  @skip_file_message = nil
  @skip_file = false
  @skip_only_if_eval = skip_only_if_eval

  extend resources_dsl # TODO: remove? push to method_missing?
end

Dynamic Method Handling

This class handles dynamic methods through the method_missing method in the class Inspec::DSL

Instance Attribute Details

#profile_contextObject Also known as: profile_context_owner

Returns the value of attribute profile_context.



19
20
21
# File 'lib/inspec/control_eval_context.rb', line 19

def profile_context
  @profile_context
end

#resources_dslObject

Returns the value of attribute resources_dsl.



20
21
22
# File 'lib/inspec/control_eval_context.rb', line 20

def resources_dsl
  @resources_dsl
end

#skip_fileObject

Returns the value of attribute skip_file.



18
19
20
# File 'lib/inspec/control_eval_context.rb', line 18

def skip_file
  @skip_file
end

Instance Method Details

#add_resource(name, new_res) ⇒ Object



79
80
81
82
83
84
85
# File 'lib/inspec/control_eval_context.rb', line 79

def add_resource(name, new_res)
  resources_dsl.module_exec do
    define_method name.to_sym do |*args|
      new_res.new(@backend, name.to_s, *args)
    end
  end
end

#add_resources(context) ⇒ Object



87
88
89
90
91
92
93
94
95
96
97
98
99
# File 'lib/inspec/control_eval_context.rb', line 87

def add_resources(context)
  # # TODO: write real unit tests for this and then make this change:
  # dsl = context.to_resources_dsl
  # self.class.include dsl
  # Inspec::Rule.include dsl

  self.class.class_eval do
    include context.to_resources_dsl
  end

  # TODO: seriously consider getting rid of the NPM model
  extend context.to_resources_dsl
end

#add_subcontext(context) ⇒ Object



101
102
103
# File 'lib/inspec/control_eval_context.rb', line 101

def add_subcontext(context)
  profile_context_owner.add_subcontext(context)
end

#attribute(name, options = {}) ⇒ Object



142
143
144
145
# File 'lib/inspec/control_eval_context.rb', line 142

def attribute(name, options = {})
  Inspec.deprecate(:attrs_dsl, "Input name: #{name}, Profile: #{profile_id}")
  input(name, options)
end

#control(id, opts = {}, &block) ⇒ Object Also known as: rule



54
55
56
57
58
# File 'lib/inspec/control_eval_context.rb', line 54

def control(id, opts = {}, &block)
  opts[:skip_only_if_eval] = @skip_only_if_eval

  register_control(Inspec::Rule.new(id, profile_id, resources_dsl, opts, &block))
end

#describe(*args, &block) ⇒ Object

Describe allows users to write rspec-like bare describe blocks without declaring an inclosing control. Here, we generate a control for them automatically and then execute the describe block in the context of that control.



66
67
68
69
70
71
72
73
74
75
76
77
# File 'lib/inspec/control_eval_context.rb', line 66

def describe(*args, &block)
  loc = block_location(block, caller(1..1).first)
  id = "(generated from #{loc} #{SecureRandom.hex})"

  res = nil
  rule = Inspec::Rule.new(id, profile_id, resources_dsl, {}) do
    res = describe(*args, &block)
  end
  register_control(rule, &block)

  res
end

#input(input_name, options = {}) ⇒ Object



124
125
126
127
128
129
130
131
132
133
134
# File 'lib/inspec/control_eval_context.rb', line 124

def input(input_name, options = {})
  if options.empty?
    # Simply an access, no event here
    Inspec::InputRegistry.find_or_register_input(input_name, profile_id).value
  else
    options[:priority] ||= 20
    options[:provider] = :inline_control_code
    evt = Inspec::Input.infer_event(options)
    Inspec::InputRegistry.find_or_register_input(input_name, profile_id, event: evt).value
  end
end

#input_object(input_name) ⇒ Object

Find the Input object, but don’t collapse to a value. Will return nil on a miss.



138
139
140
# File 'lib/inspec/control_eval_context.rb', line 138

def input_object(input_name)
  Inspec::InputRegistry.find_or_register_input(input_name, profile_id)
end

#only_if(message = nil, &block) ⇒ Object



152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
# File 'lib/inspec/control_eval_context.rb', line 152

def only_if(message = nil, &block)
  return unless block
  return if @skip_file == true
  return if @skip_only_if_eval == true

  return if block.yield == true

  # Apply `set_skip_rule` for other rules in the same file
  profile_context_owner.rules.values.each do |r|
    sources_match = r.source_file == block.source_location[0]
    Inspec::Rule.set_skip_rule(r, true, message) if sources_match
  end

  @skip_file_message = message
  @skip_file = true
end

#profile_idObject



38
39
40
# File 'lib/inspec/control_eval_context.rb', line 38

def profile_id
  profile_context.profile_id
end

#profile_nameObject



50
51
52
# File 'lib/inspec/control_eval_context.rb', line 50

def profile_name
  profile_id
end

#register_control(control, &block) ⇒ Object



105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
# File 'lib/inspec/control_eval_context.rb', line 105

def register_control(control, &block)
  if @skip_file
    ::Inspec::Rule.set_skip_rule(control, true, @skip_file_message)
  end

  unless profile_context_owner.profile_supports_platform?
    platform = inspec.platform
    msg = "Profile `#{profile_id}` is not supported on platform #{platform.name}/#{platform.release}."
    ::Inspec::Rule.set_skip_rule(control, true, msg)
  end

  unless profile_context_owner.profile_supports_inspec_version?
    msg = "Profile `#{profile_id}` is not supported on InSpec version (#{Inspec::VERSION})."
    ::Inspec::Rule.set_skip_rule(control, true, msg)
  end

  profile_context_owner.register_rule(control, &block) unless control.nil?
end

#skip_control(id) ⇒ Object Also known as: skip_rule



147
148
149
# File 'lib/inspec/control_eval_context.rb', line 147

def skip_control(id)
  profile_context_owner.unregister_rule(id)
end

#title(arg) ⇒ Object



46
47
48
# File 'lib/inspec/control_eval_context.rb', line 46

def title(arg)
  profile_context_owner.set_header(:title, arg)
end

#to_sObject



42
43
44
# File 'lib/inspec/control_eval_context.rb', line 42

def to_s
  "Control Evaluation Context (#{profile_name})"
end