Class: Inspec::Input

Inherits:
Object
  • Object
show all
Defined in:
lib/inspec/objects/input.rb,
lib/inspec/input.rb

Overview

NOTE: due to namespacing, this reopens and extends the existing Inspec::Input. This should be under Inspec::Objects but that ship has sailed.

Defined Under Namespace

Classes: Error, Event, NO_VALUE_SET, PatternError, RequiredError, TypeError, ValidationError

Constant Summary collapse

VALID_TYPES =

Validation types for input values

%w{
  String
  Numeric
  Regexp
  Array
  Hash
  Boolean
  Any
}.freeze
DEFAULT_PRIORITY_FOR_DSL_ATTRIBUTES =

TODO: this is not used anywhere? If you call ‘input` in a control file, the input will receive this priority. You can override that with a :priority option.

20
DEFAULT_PRIORITY_FOR_UNKNOWN_CALLER =

If you somehow manage to initialize an Input outside of the DSL, AND you don’t provide an Input::Event, this is the priority you get.

10
DEFAULT_PRIORITY_FOR_VALUE_SET =

If you directly call value=, this is the priority assigned. This is the highest priority within InSpec core; though plugins are free to go higher.

60

Instance Attribute Summary collapse

Class Method Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(name, options = {}) ⇒ Input

Returns a new instance of Input.



183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
# File 'lib/inspec/input.rb', line 183

def initialize(name, options = {})
  @name = name
  @opts = options
  if @opts.key?(:default)
    Inspec.deprecate(:attrs_value_replaces_default, "input name: '#{name}'")
    if @opts.key?(:value)
      Inspec::Log.warn "Input #{@name} created using both :default and :value options - ignoring :default"
      @opts.delete(:default)
    end
  end

  # Array of Input::Event objects.  These compete with one another to determine
  # the value of the input when value() is called, as well as providing a
  # debugging record of when and how the value changed.
  @events = []
  events.push make_creation_event(options)
  update(options)
end

Instance Attribute Details

#descriptionObject (readonly)

Returns the value of attribute description.



181
182
183
# File 'lib/inspec/input.rb', line 181

def description
  @description
end

#eventsObject (readonly)

Returns the value of attribute events.



181
182
183
# File 'lib/inspec/input.rb', line 181

def events
  @events
end

#identifierObject (readonly)

Returns the value of attribute identifier.



181
182
183
# File 'lib/inspec/input.rb', line 181

def identifier
  @identifier
end

#nameObject (readonly)

Returns the value of attribute name.



181
182
183
# File 'lib/inspec/input.rb', line 181

def name
  @name
end

#patternObject (readonly)

Returns the value of attribute pattern.



181
182
183
# File 'lib/inspec/input.rb', line 181

def pattern
  @pattern
end

#requiredObject (readonly)

Returns the value of attribute required.



181
182
183
# File 'lib/inspec/input.rb', line 181

def required
  @required
end

#sensitiveObject (readonly)

Returns the value of attribute sensitive.



181
182
183
# File 'lib/inspec/input.rb', line 181

def sensitive
  @sensitive
end

#titleObject (readonly)

Returns the value of attribute title.



181
182
183
# File 'lib/inspec/input.rb', line 181

def title
  @title
end

#typeObject (readonly)

Returns the value of attribute type.



181
182
183
# File 'lib/inspec/input.rb', line 181

def type
  @type
end

Class Method Details

.infer_event(options) ⇒ Object

We can determine a value:

  1. By event.value (preferred)

  2. By options

  3. By options (deprecated)



241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
# File 'lib/inspec/input.rb', line 241

def self.infer_event(options)
  # Don't rely on this working; you really should be passing a proper Input::Event
  # with the context information you have.
  location = Input::Event.probe_stack
  event = Input::Event.new(
    action: :set,
    provider: options[:provider] || :unknown,
    priority: options[:priority] || Inspec::Input::DEFAULT_PRIORITY_FOR_UNKNOWN_CALLER,
    file: location.path,
    line: location.lineno
  )

  if options.key?(:default)
    Inspec.deprecate(:attrs_value_replaces_default, "attribute name: '#{name}'")
    if options.key?(:value)
      Inspec::Log.warn "Input #{@name} created using both :default and :value options - ignoring :default"
      options.delete(:default)
    else
      options[:value] = options.delete(:default)
    end
  end
  event.value = options[:value] if options.key?(:value)
  options[:event] = event
end

Instance Method Details

#diagnostic_stringObject



207
208
209
210
# File 'lib/inspec/input.rb', line 207

def diagnostic_string
  "Input #{name}, with history:\n" +
    events.map(&:diagnostic_string).map { |line| "  #{line}" }.join("\n")
end

#has_value?Boolean

Returns:

  • (Boolean)


329
330
331
# File 'lib/inspec/input.rb', line 329

def has_value?
  !current_value(false).is_a? NO_VALUE_SET
end

#ruby_var_identifierObject



32
33
34
# File 'lib/inspec/objects/input.rb', line 32

def ruby_var_identifier
  identifier || "attr_" + name.downcase.strip.gsub(/\s+/, "-").gsub(/[^\w-]/, "")
end

#set_eventsObject

TODO: is this here just for testing?



203
204
205
# File 'lib/inspec/input.rb', line 203

def set_events
  events.select { |e| e.action == :set }
end

#to_hashObject

————————————————————————–#

Marshalling

————————————————————————–#



21
22
23
24
25
26
27
28
29
30
# File 'lib/inspec/objects/input.rb', line 21

def to_hash
  as_hash = { name: name, options: {} }
  %i{description title identifier type required value sensitive pattern}.each do |field|
    val = send(field)
    next if val.nil?

    as_hash[:options][field] = val
  end
  as_hash
end

#to_rubyObject



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

def to_ruby
  res = ["#{ruby_var_identifier} = attribute('#{name}',{"]
  res.push "  title: '#{title}'," unless title.to_s.empty?
  res.push "  value: #{value.inspect}," unless value.to_s.empty?
  # to_ruby may generate code that is to be used by older versions of inspec.
  # Anything older than 3.4 will not recognize the value: option, so
  # send the default: option as well. See #3759
  res.push "  default: #{value.inspect}," unless value.to_s.empty?
  res.push "  description: '#{description}'," unless description.to_s.empty?
  res.push "})"
  res.join("\n")
end

#to_sObject

————————————————————————–#

Value Type Coercion

————————————————————————–#



348
349
350
# File 'lib/inspec/input.rb', line 348

def to_s
  "Input #{name} with value " + (sensitive ? "*** (senstive)" : "#{current_value}")
end

#update(options) ⇒ Object

————————————————————————–#

Managing Value

————————————————————————–#



216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
# File 'lib/inspec/input.rb', line 216

def update(options)
  (options)
  normalize_type_restriction!
  normalize_pattern_restriction!

  # Values are set by passing events in; but we can also infer an event.
  if options.key?(:value) || options.key?(:default)
    if options.key?(:event)
      if options.key?(:value) || options.key?(:default)
        Inspec::Log.warn "Do not provide both an Event and a value as an option to attribute('#{name}') - using value from event"
      end
    else
      self.class.infer_event(options) # Sets options[:event]
    end
  end
  events << options[:event] if options.key? :event

  enforce_type_restriction!
  enforce_pattern_restriction!
end

#valueObject



324
325
326
327
# File 'lib/inspec/input.rb', line 324

def value
  enforce_required_validation!
  current_value
end

#value=(new_value, priority = DEFAULT_PRIORITY_FOR_VALUE_SET) ⇒ Object



308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
# File 'lib/inspec/input.rb', line 308

def value=(new_value, priority = DEFAULT_PRIORITY_FOR_VALUE_SET)
  # Inject a new Event with the new value.
  location = Event.probe_stack
  events << Event.new(
    action: :set,
    provider: :value_setter,
    priority: priority,
    value: new_value,
    file: location.path,
    line: location.lineno
  )

  enforce_type_restriction!
  enforce_pattern_restriction!
end