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



84
85
86
87
88
89
90
# File 'lib/inspec/control_eval_context.rb', line 84

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



92
93
94
95
96
97
98
99
100
101
102
103
104
# File 'lib/inspec/control_eval_context.rb', line 92

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



106
107
108
# File 'lib/inspec/control_eval_context.rb', line 106

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

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



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

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
59
# File 'lib/inspec/control_eval_context.rb', line 54

def control(id, opts = {}, &block)
  opts[:skip_only_if_eval] = @skip_only_if_eval
  if control_exist_in_controls_list?(id) || controls_list_empty?
    register_control(Inspec::Rule.new(id, profile_id, resources_dsl, opts, &block))
  end
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.



67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
# File 'lib/inspec/control_eval_context.rb', line 67

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

  if control_exist_in_controls_list?(id) || controls_list_empty?
    register_control(rule, &block)
  end

  res
end

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



129
130
131
132
133
134
135
136
137
138
139
# File 'lib/inspec/control_eval_context.rb', line 129

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.



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

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

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



157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
# File 'lib/inspec/control_eval_context.rb', line 157

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



110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
# File 'lib/inspec/control_eval_context.rb', line 110

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



152
153
154
# File 'lib/inspec/control_eval_context.rb', line 152

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