Class: Inspec::Input

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

Defined Under Namespace

Classes: Error, Event, NO_VALUE_SET, 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 =

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.



162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
# File 'lib/inspec/objects/input.rb', line 162

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.



160
161
162
# File 'lib/inspec/objects/input.rb', line 160

def description
  @description
end

#eventsObject (readonly)

Returns the value of attribute events.



160
161
162
# File 'lib/inspec/objects/input.rb', line 160

def events
  @events
end

#identifierObject (readonly)

Returns the value of attribute identifier.



160
161
162
# File 'lib/inspec/objects/input.rb', line 160

def identifier
  @identifier
end

#nameObject (readonly)

Returns the value of attribute name.



160
161
162
# File 'lib/inspec/objects/input.rb', line 160

def name
  @name
end

#requiredObject (readonly)

Returns the value of attribute required.



160
161
162
# File 'lib/inspec/objects/input.rb', line 160

def required
  @required
end

#titleObject (readonly)

Returns the value of attribute title.



160
161
162
# File 'lib/inspec/objects/input.rb', line 160

def title
  @title
end

#typeObject (readonly)

Returns the value of attribute type.



160
161
162
# File 'lib/inspec/objects/input.rb', line 160

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)



218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
# File 'lib/inspec/objects/input.rb', line 218

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



186
187
188
189
# File 'lib/inspec/objects/input.rb', line 186

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

#has_value?Boolean

Returns:

  • (Boolean)


302
303
304
# File 'lib/inspec/objects/input.rb', line 302

def has_value?
  !current_value.is_a? NO_VALUE_SET
end

#ruby_var_identifierObject



321
322
323
# File 'lib/inspec/objects/input.rb', line 321

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

#set_eventsObject



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

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

#to_hashObject

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

Marshalling

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



310
311
312
313
314
315
316
317
318
319
# File 'lib/inspec/objects/input.rb', line 310

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

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

#to_rubyObject



325
326
327
328
329
330
331
332
333
334
335
336
# File 'lib/inspec/objects/input.rb', line 325

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

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



342
343
344
# File 'lib/inspec/objects/input.rb', line 342

def to_s
  "Input #{name} with #{current_value}"
end

#update(options) ⇒ Object

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

Managing Value

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



195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
# File 'lib/inspec/objects/input.rb', line 195

def update(options)
  (options)
  normalize_type_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!
end

#valueObject



297
298
299
300
# File 'lib/inspec/objects/input.rb', line 297

def value
  enforce_required_validation!
  current_value
end

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



283
284
285
286
287
288
289
290
291
292
293
294
295
# File 'lib/inspec/objects/input.rb', line 283

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