class Vcloud::Core::ConfigValidator

self::validate is entry point; this class method is called to instantiate ConfigValidator. For example:

Core::ConfigValidator.validate(key, data, schema)

Recursion in this class

Note that this class will recursively call itself in order to validate deep hash and array structures.

The data variable is usually either an array or hash and so will pass through the ConfigValidator#validate_array and ConfigValidator#validate_hash methods respectively.

These methods then recursively instantiate this class by calling ConfigValidator::validate again (ConfigValidator#validate_hash calls this indirectly via the ConfigValidator#check_hash_parameter method).

Constants

VALID_ALPHABETICAL_VALUES_FOR_IP_RANGE

Attributes

data[R]
errors[R]
key[R]
schema[R]
type[R]
warnings[R]

Public Class Methods

new(key, data, schema) click to toggle source
# File lib/vcloud/core/config_validator.rb, line 34
def initialize(key, data, schema)
  raise "Nil schema" unless schema
  raise "Invalid schema" unless schema.key?(:type)
  @type = schema[:type].to_s.downcase
  @errors   = []
  @warnings = []
  @data   = data
  @schema = schema
  @key    = key
  validate
end
validate(key, data, schema) click to toggle source
# File lib/vcloud/core/config_validator.rb, line 30
def self.validate(key, data, schema)
  new(key, data, schema)
end

Public Instance Methods

valid?() click to toggle source
# File lib/vcloud/core/config_validator.rb, line 46
def valid?
  @errors.empty?
end

Private Instance Methods

check_emptyness_ok() click to toggle source
# File lib/vcloud/core/config_validator.rb, line 120
def check_emptyness_ok
  unless schema.key?(:allowed_empty) && schema[:allowed_empty]
    if data.empty?
      @errors << "#{key}: cannot be empty #{type}"
      return false
    end
  end
  true
end
check_for_invalid_deprecations() click to toggle source

Raise an exception if any `deprecated_by` params refer to params that don't exist in the schema.

# File lib/vcloud/core/config_validator.rb, line 132
def check_for_invalid_deprecations
  schema[:internals].each do |param_key,param_schema|
    deprecated_by = param_schema[:deprecated_by]
    if deprecated_by && !schema[:internals].key?(deprecated_by.to_sym)
      raise "#{param_key}: deprecated_by target '#{deprecated_by}' not found in schema"
    end
  end
end
check_for_unknown_parameters() click to toggle source
# File lib/vcloud/core/config_validator.rb, line 141
def check_for_unknown_parameters
  internals = schema[:internals]
  # if there are no parameters specified, then assume all are ok.
  return true unless internals
  return true if schema[:permit_unknown_parameters]
  data.keys.each do |k|
    @errors << "#{key}: parameter '#{k}' is invalid" unless internals[k]
  end
end
check_hash_parameter(sub_key, sub_schema, ignore_required=false) click to toggle source
# File lib/vcloud/core/config_validator.rb, line 151
def check_hash_parameter(sub_key, sub_schema, ignore_required=false)
  unless data.key?(sub_key)
    if sub_schema[:required] == false || ignore_required
      return true
    end

    @errors << "#{key}: missing '#{sub_key}' parameter"
    return false
  end

  sub_validator = ConfigValidator.validate(
    sub_key,
    data[sub_key],
    sub_schema
  )
  @warnings = warnings + sub_validator.warnings
  unless sub_validator.valid?
    @errors = errors + sub_validator.errors
  end
end
check_matcher_matches() click to toggle source
# File lib/vcloud/core/config_validator.rb, line 172
def check_matcher_matches
  regex = schema[:matcher]
  return unless regex
  raise "#{key}: #{regex} is not a Regexp" unless regex.is_a? Regexp
  unless data =~ regex
    @errors << "#{key}: #{data} does not match"
    return false
  end
  true
end
get_deprecations_used() click to toggle source

Return a hash of deprecated params referenced in @data. Where the structure is: `{ :deprecator => :deprecatee }`

# File lib/vcloud/core/config_validator.rb, line 100
def get_deprecations_used
  used = {}
  schema[:internals].each do |param_key,param_schema|
    deprecated_by = param_schema[:deprecated_by]
    if deprecated_by && data[param_key]
      used[deprecated_by.to_sym] = param_key
    end
  end

  used
end
valid_alphabetical_ip_range?() click to toggle source
# File lib/vcloud/core/config_validator.rb, line 183
def valid_alphabetical_ip_range?
  VALID_ALPHABETICAL_VALUES_FOR_IP_RANGE.include?(data)
end
valid_cidr_or_ip_address?() click to toggle source
# File lib/vcloud/core/config_validator.rb, line 193
def valid_cidr_or_ip_address?
  begin
    ip = IPAddr.new(data)
    ip.ipv4?
  rescue ArgumentError
    false
  end
end
valid_ip_address?(ip_address) click to toggle source
# File lib/vcloud/core/config_validator.rb, line 219
def valid_ip_address? ip_address
  begin
    #valid formats recognized by IPAddr are : “address”, “address/prefixlen” and “address/mask”.
    # Attribute like member_ip in case of load-balancer is an "address"
    # and we should not accept “address/prefixlen” and “address/mask” for such fields.
    ip = IPAddr.new(ip_address)
    ip.ipv4? && !ip_address.include?('/')
  rescue ArgumentError
    false
  end
end
valid_ip_range?() click to toggle source
# File lib/vcloud/core/config_validator.rb, line 240
def valid_ip_range?
  range_parts = data.split('-')
  return false if range_parts.size != 2
  start_address = range_parts.first
  end_address = range_parts.last
  valid_ip_address?(start_address) &&  valid_ip_address?(end_address) &&
    valid_start_and_end_address_combination?(end_address, start_address)
end
valid_start_and_end_address_combination?(end_address, start_address) click to toggle source
# File lib/vcloud/core/config_validator.rb, line 249
def valid_start_and_end_address_combination?(end_address, start_address)
  IPAddr.new(start_address) < IPAddr.new(end_address)
end
validate() click to toggle source

Call the corresponding function in this class (dependant on schema)

# File lib/vcloud/core/config_validator.rb, line 53
def validate
  self.send("validate_#{type}".to_sym)
end
validate_array() click to toggle source
# File lib/vcloud/core/config_validator.rb, line 57
def validate_array
  unless data.is_a? Array
    @errors << "#{key} is not an array"
    return
  end
  return unless check_emptyness_ok
  if schema.key?(:each_element_is)
    element_schema = schema[:each_element_is]
    data.each do |element|
      sub_validator = ConfigValidator.validate(key, element, element_schema)
      @warnings = warnings + sub_validator.warnings
      unless sub_validator.valid?
        @errors = errors + sub_validator.errors
      end
    end
  end
end
validate_boolean() click to toggle source
# File lib/vcloud/core/config_validator.rb, line 187
def validate_boolean
  unless [true, false].include?(data)
    @errors << "#{key}: #{data} is not a valid boolean value."
  end
end
validate_enum() click to toggle source
# File lib/vcloud/core/config_validator.rb, line 202
def validate_enum
  acceptable_values = schema[:acceptable_values]
  raise "Must set :acceptable_values for type 'enum'" unless acceptable_values.is_a?(Array)
  unless acceptable_values.include?(data)
    acceptable_values_string = acceptable_values.collect {|v| "'#{v}'" }.join(', ')
    @errors << "#{key}: #{@data} is not a valid value. Acceptable values are #{acceptable_values_string}."
  end
end
validate_hash() click to toggle source
# File lib/vcloud/core/config_validator.rb, line 75
def validate_hash
  unless data.is_a? Hash
    @errors << "#{key}: is not a hash"
    return
  end
  return unless check_emptyness_ok
  check_for_unknown_parameters

  if schema.key?(:internals)
    check_for_invalid_deprecations
    deprecations_used = get_deprecations_used
    warn_on_deprecations_used(deprecations_used)

    schema[:internals].each do |param_key,param_schema|
      ignore_required = (
        param_schema[:deprecated_by] ||
        deprecations_used.key?(param_key)
      )
      check_hash_parameter(param_key, param_schema, ignore_required)
    end
  end
end
validate_ip_address() click to toggle source
# File lib/vcloud/core/config_validator.rb, line 211
def validate_ip_address
  unless data.is_a?(String)
    @errors << "#{key}: #{@data} is not a valid ip_address"
    return
  end
  @errors << "#{key}: #{@data} is not a valid ip_address" unless valid_ip_address?(data)
end
validate_ip_address_range() click to toggle source
# File lib/vcloud/core/config_validator.rb, line 231
def validate_ip_address_range
  unless data.is_a?(String)
    @errors << "#{key}: #{@data} is not a valid IP address range. Valid values can be IP address, CIDR, IP range, 'Any','internal' and 'external'."
    return
  end
  valid = valid_cidr_or_ip_address? || valid_alphabetical_ip_range? || valid_ip_range?
  @errors << "#{key}: #{@data} is not a valid IP address range. Valid values can be IP address, CIDR, IP range, 'Any','internal' and 'external'." unless valid
end
validate_string() click to toggle source
# File lib/vcloud/core/config_validator.rb, line 253
def validate_string
  unless @data.is_a? String
    @errors << "#{key}: #{@data} is not a string"
    return
  end
  return unless check_emptyness_ok
  return unless check_matcher_matches
end
validate_string_or_number() click to toggle source
# File lib/vcloud/core/config_validator.rb, line 262
def validate_string_or_number
  unless data.is_a?(String) || data.is_a?(Numeric)
    @errors << "#{key}: #{@data} is not a string_or_number"
    return
  end
end
warn_on_deprecations_used(deprecations_used) click to toggle source

Append warnings for any deprecations used. Takes the output of `#get_deprecations_used`.

# File lib/vcloud/core/config_validator.rb, line 114
def warn_on_deprecations_used(deprecations_used)
  deprecations_used.each do |deprecator, deprecatee|
    @warnings << "#{deprecatee}: is deprecated by '#{deprecator}'"
  end
end