Module: StateMate

Defined in:
lib/state_mate.rb,
lib/state_mate/error.rb,
lib/state_mate/version.rb,
lib/state_mate/adapters.rb

Defined Under Namespace

Modules: Adapters, Error Classes: StateSet

Constant Summary collapse

DIRECTIVES =
Set.new [
  :set,
  :unset,
  :array_contains,
  :array_missing,
]
VERSION =
"0.0.7"

Class Method Summary collapse

Class Method Details

.array_contains(key, current, value, options) ⇒ Object



446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
# File 'lib/state_mate.rb', line 446

def self.array_contains key, current, value, options
  case current
  when Array
    # this is just to make the function consistent, so it doesn't add another
    # copy of value if it's there... in practice StateMate should not
    # call {.array_contains} if the value is alreay in the array
    # (that's what {.array_contains?} tests for)
    if current.include? value
      current
    else
      current + [value]
    end

  when nil
    # it needs to be created
    if options[:create] || options[:clobber]
      [value]
    else
      raise Error::StructureConflictError.new "        can not ensure \#{ key.inspect } contains \#{ value.inspect } because\n        the key does not exist and options[:create] is not true.\n      BLOCK\n    end\n\n  else\n    # there is something there, but it's not an array. out only option\n    # to achieve the declared state is to replace it with a new array\n    # where value is the only element, but we don't want to do that unless\n    # we've been told to clobber\n    if options[:clobber]\n      [value]\n    else\n      raise Error::StructureConflictError.new <<-BLOCK.unblock\n        can not ensure \#{ key.inspect } contains \#{ value.inspect } because\n        the value is \#{ current.inspect } and options[:clobber] is not true.\n      BLOCK\n    end\n  end # case current\nend\n".unblock

.array_contains?(key, current, value, adapter, options) ⇒ Boolean

Returns:

  • (Boolean)


440
441
442
443
444
# File 'lib/state_mate.rb', line 440

def self.array_contains? key, current, value, adapter, options
  current.is_a?(Array) && current.any? {|v|
    values_equal? v, value, adapter
  }
end

.array_missing(key, current, value, options) ⇒ Object



508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
# File 'lib/state_mate.rb', line 508

def self.array_missing key, current, value, options
  case current
  when Array
    current - [value]

  when nil
    # if we're ok with the value being unset (`nil` to us here), then
    # we're done
    if options[:unset_ok]
      nil
    else
      # there is no value, only option is to create a new empty array there
      if options[:create] || options[:clobber]
        []
      else
        raise Error::StructureConflictError.new "          can not ensure \#{ key.inspect } missing \#{ value.inspect } because\n          the key does not exist and options[:create] is not true.\n        BLOCK\n      end\n    end\n\n  else\n    # there is something there, but it's not an array. out only option\n    # to achieve the declared state is to replace it with a new empty array\n    # but we don't want to do that unless we've been told to clobber\n    if options[:clobber]\n      []\n    else\n      raise Error::StructureConflictError.new <<-BLOCK.unblock\n        can not ensure \#{ key.inspect } missing \#{ value.inspect } because\n        the value is \#{ current.inspect } and options[:clobber] is not true.\n      BLOCK\n    end\n  end # case current\nend\n".unblock

.array_missing?(key, current, value, adapter, options) ⇒ Boolean

Parameters:

  • options (Hash)

Options Hash (options):

  • :unset_ok (Boolean)

    if true, the value being unset is acceptible. many plist files will simply omit the key rather than store an empty array in the case that an array value is empty, and setting these to an empty array when all we want to do is make sure that if it is there, it doesn't contain the value seems pointless.

Returns:

  • (Boolean)


493
494
495
496
497
498
499
500
501
502
503
504
505
506
# File 'lib/state_mate.rb', line 493

def self.array_missing? key, current, value, adapter, options
  case current
  when nil
    if options[:unset_ok]
      true
    else
      false
    end
  when Array
    !current.any? {|v| values_equal? v, value, adapter}
  else
    false
  end
end

.cast(type_name, value) ⇒ Object

pure

casts a value to a type, or raises an error if not possible. this is useful because ansible in particular likes to pass things as strings.

Parameters:

  • type_name (String)

    the 'name' of the type to cast to.

  • value

    the value to cast.



353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
# File 'lib/state_mate.rb', line 353

def self.cast type_name, value
  case type_name
  when 'string', 'str'
    value.to_s
  when 'integer', 'int'
    case value
    when Fixnum
      value
    when true
      1
    when false
      0
    when String
      if value =~ /\A[-+]?[0-9]*\Z/
        value.to_i
      elsif value.downcase == 'true'
        1
      elsif value.downcase == 'false'
        0
      else
        raise ArgumentError.new "can't cast to integer: #{ value.inspect }"
      end
    else
      raise TypeError.new "can't cast type to integer: #{ value.inspect }"
    end
  when 'float'
    case value
    when Float
      value
    when Fixnum
      value.to_f
    when String
      if value =~ /\A[-+]?[0-9]*\.?[0-9]+\Z/
        value.to_f
      else
        raise ArgumentError.new "can't cast to float: #{ value.inspect }"
      end
    else
      raise TypeError.new "can't cast type to float: #{ value.inspect }"
    end
  when 'boolean', 'bool'
    case value
    when true, false
      value
    when 0, '0', 'False', 'false', 'FALSE'
      false
    when 1, '1', 'True', 'true', 'TRUE'
      true
    else 
      raise ArgumentError.new "can't cast type to boolean: #{ value.inspect }"
    end
  else 
    raise ArgumentError.new "bad type name: #{ type_name.inspect }"
  end
end

.debug(*messages) ⇒ Object



324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
# File 'lib/state_mate.rb', line 324

def self.debug *messages
  return unless @debug
  
  @debug_file ||= File.open('./state_mate.debug.log', @debug_mode)
  
  messages.each_with_index do |message, index|
    if index == 0
      @debug_file.write 'DEBUG '
    end
    
    if message.is_a? String
      @debug_file.puts message
    else
      @debug_file.puts
      PP.pp(message, @debug_file)
    end
  end
end

.debug=(mode) ⇒ Object

turns debug on or off

Parameters:

  • mode (Boolean|String)

    if a string, enables and sets the debug file mode (use 'a' or 'w'). if a boolean, sets enabled.



317
318
319
320
321
322
# File 'lib/state_mate.rb', line 317

def self.debug= mode
  if mode.is_a? String
    @debug_mode = mode
  end
  @debug = !!mode
end

.execute(spec) ⇒ Object



409
410
411
# File 'lib/state_mate.rb', line 409

def self.execute spec
  StateSet.from_spec(spec).execute
end

.set(key, current, value, options) ⇒ Object



425
426
427
428
# File 'lib/state_mate.rb', line 425

def self.set key, current, value, options
  # TODO: handle options
  value
end

.set?(key, current, value, adapter, options) ⇒ Boolean

Returns:

  • (Boolean)


421
422
423
# File 'lib/state_mate.rb', line 421

def self.set? key, current, value, adapter, options
  values_equal? current, value, adapter
end

.unset(key, current, value, options) ⇒ Object



434
435
436
437
438
# File 'lib/state_mate.rb', line 434

def self.unset key, current, value, options
  # TODO: handle options
  raise "value most be nil to unset" unless value.nil?
  nil
end

.unset?(key, current, value, adapter, options) ⇒ Boolean

Returns:

  • (Boolean)


430
431
432
# File 'lib/state_mate.rb', line 430

def self.unset? key, current, value, adapter, options
  current.nil?
end

.values_equal?(current, desired, adapter) ⇒ Boolean

Returns:

  • (Boolean)


413
414
415
416
417
418
419
# File 'lib/state_mate.rb', line 413

def self.values_equal? current, desired, adapter
  if adapter.respond_to? :values_equal?
    adapter.values_equal? current, desired
  else
    current == desired
  end
end