/usr/lib/ruby/vendor_ruby/octocatalog-diff/api/v1/override.rb is in octocatalog-diff 1.5.3-1.
This file is owned by root:root, with mode 0o644.
The actual contents of the file can be viewed below.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 | # frozen_string_literal: true
require 'json'
module OctocatalogDiff
module API
module V1
# Sets up the override of a fact or ENC parameter during catalog compilation.
class Override
# Accessors
attr_reader :key, :value
# Constructor: Accepts a key and value.
# @param input [Hash] Must contain :key and :value
def initialize(input)
key = input.fetch(:key)
@key = key =~ %r{\A/(.+)/\Z} ? Regexp.new(Regexp.last_match(1)) : key
@value = parsed_value(input.fetch(:value))
end
# Initialize from a parsed command line
# @param input [String] Command line parameter
# @return [OctocatalogDiff::API::V1::Override] Initialized object
def self.create_from_input(input, key = nil)
# Normally the input will be a string in the format key=(data type)value where the data
# type is optional and the parentheses are literal. Example:
# foo=1 (auto-determine data type - in this case it would be a fixnum)
# foo=(fixnum)1 (will be a fixnum)
# foo=(string)1 (will be '1' the string)
# If input is not a string, we can still construct the object if the key is given.
# That input would come directly from code and not from the command line, since inputs
# from the command line are always strings.
# Also support regular expressions for the key name, if delimited by //.
if key.nil? && input.is_a?(String)
unless input.include?('=')
raise ArgumentError, "Fact override '#{input}' is not in 'key=(data type)value' format"
end
k, v = input.strip.split('=', 2).map(&:strip)
new(key: k, value: v)
elsif key.nil?
message = "Define a key when the input is not a string (#{input.class} => #{input.inspect})"
raise ArgumentError, message
else
new(key: key, value: input)
end
end
private
# Guess the datatype from a particular input
# @param input [String] Input in string format
# @return [?] Output in appropriate format
def parsed_value(input)
# If data type is explicitly given
if input =~ /^\((\w+)\)(.*)$/m
datatype = Regexp.last_match(1)
value = Regexp.last_match(2)
return convert_to_data_type(datatype.downcase, value)
end
# Guess data type
return input.to_i if input =~ /^-?\d+$/
return input.to_f if input =~ /^-?\d*\.\d+$/
return true if input.casecmp('true').zero?
return false if input.casecmp('false').zero?
input
end
# Handle data type that's explicitly given
# @param datatype [String] Data type (as a string)
# @param value [String] Value given
# @return [?] Value converted to specified data type
def convert_to_data_type(datatype, value)
return value if datatype == 'string'
return parse_json(value) if datatype == 'json'
return nil if datatype == 'nil'
if datatype == 'fixnum' || datatype == 'integer'
return Regexp.last_match(1).to_i if value =~ /^(-?\d+)$/
raise ArgumentError, "Illegal integer '#{value}'"
end
if datatype == 'float'
return Regexp.last_match(1).to_f if value =~ /^(-?\d*\.\d+)$/
return Regexp.last_match(1).to_f if value =~ /^(-?\d+)$/
raise ArgumentError, "Illegal float '#{value}'"
end
if datatype == 'boolean'
return true if value.casecmp('true').zero?
return false if value.casecmp('false').zero?
raise ArgumentError, "Illegal boolean '#{value}'"
end
raise ArgumentError, "Unknown data type '#{datatype}'"
end
# Parse JSON value
# @param input [String] Input, hopefully in JSON format
# @return [?] Output data structure
def parse_json(input)
JSON.parse(input)
rescue JSON::ParserError => exc
raise JSON::ParserError, "Failed to parse JSON: input=#{input} error=#{exc}"
end
end
end
end
end
|