Module: Puppet::ResourceApi::DataTypeHandling
- Defined in:
- lib/puppet/resource_api/data_type_handling.rb
Overview
This module is used to handle data inside types, contains methods for munging and validation of the type values.
Class Method Summary collapse
-
.ambiguous_error_msg(error_msg_prefix, value, type) ⇒ Object
Returns ambiguous error message based on ‘error_msg_prefix`, `value` and `type`.
-
.boolean_munge(value) ⇒ Object
Returns correct boolean ‘value` based on one specified in `type`.
-
.mungify(type, value, error_msg_prefix, unpack_strings = false) ⇒ type
This method handles translating values from the runtime environment to the expected types for the provider with validation.
-
.mungify_core(type, value, error_msg_prefix, unpack_strings = false) ⇒ type
This is core method used in mungify which handles translating values to expected cleaned type values, result is not validated.
- .parse_puppet_type(attr_name, type) ⇒ Object
-
.try_mungify(type, value, error_msg_prefix) ⇒ Array
Recursive implementation part of #mungify_core.
-
.try_validate(type, value, error_msg_prefix) ⇒ String?
Tries to validate the ‘value` against the specified `type`.
-
.validate(type, value, error_msg_prefix) ⇒ Object
Validates the ‘value` against the specified `type`.
- .validate_ensure(definition) ⇒ Object
Class Method Details
.ambiguous_error_msg(error_msg_prefix, value, type) ⇒ Object
Returns ambiguous error message based on ‘error_msg_prefix`, `value` and `type`.
147 148 149 150 |
# File 'lib/puppet/resource_api/data_type_handling.rb', line 147 def self.ambiguous_error_msg(error_msg_prefix, value, type) "#{error_msg_prefix} #{value.inspect} is not unabiguously convertable to " \ "#{type}" end |
.boolean_munge(value) ⇒ Object
Returns correct boolean ‘value` based on one specified in `type`.
130 131 132 133 134 135 136 137 138 139 |
# File 'lib/puppet/resource_api/data_type_handling.rb', line 130 def self.boolean_munge(value) case value when 'true', :true # rubocop:disable Lint/BooleanSymbol true when 'false', :false # rubocop:disable Lint/BooleanSymbol false else value end end |
.mungify(type, value, error_msg_prefix, unpack_strings = false) ⇒ type
This method handles translating values from the runtime environment to the expected types for the provider with validation. When being called from ‘puppet resource`, it tries to transform the strings from the command line into their expected ruby representations, e.g. `“2”` (a string), will be transformed to `2` (the number) if (and only if) the target `type` is `Integer`. Additionally this function also validates that the passed in (and optionally transformed) value matches the specified type. against. legacy type
23 24 25 26 27 28 29 30 31 32 |
# File 'lib/puppet/resource_api/data_type_handling.rb', line 23 def self.mungify(type, value, error_msg_prefix, unpack_strings = false) cleaned_value = mungify_core( type, value, error_msg_prefix, unpack_strings, ) validate(type, cleaned_value, error_msg_prefix) cleaned_value end |
.mungify_core(type, value, error_msg_prefix, unpack_strings = false) ⇒ type
This is core method used in mungify which handles translating values to expected cleaned type values, result is not validated. against. legacy type
45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 |
# File 'lib/puppet/resource_api/data_type_handling.rb', line 45 def self.mungify_core(type, value, error_msg_prefix, unpack_strings = false) if unpack_strings # When the provider is exercised from the `puppet resource` CLI, we need # to unpack strings into the correct types, e.g. "1" (a string) # to 1 (an integer) cleaned_value, error_msg = try_mungify(type, value, error_msg_prefix) raise Puppet::ResourceError, error_msg if error_msg cleaned_value elsif value == :false # rubocop:disable Lint/BooleanSymbol # work around https://tickets.puppetlabs.com/browse/PUP-2368 false elsif value == :true # rubocop:disable Lint/BooleanSymbol # work around https://tickets.puppetlabs.com/browse/PUP-2368 true else # Every other time, we can use the values as is value end end |
.parse_puppet_type(attr_name, type) ⇒ Object
198 199 200 201 202 203 204 205 206 |
# File 'lib/puppet/resource_api/data_type_handling.rb', line 198 def self.parse_puppet_type(attr_name, type) Puppet::Pops::Types::TypeParser.singleton.parse(type) rescue Puppet::ParseErrorWithIssue => e raise Puppet::DevError, "The type of the `#{attr_name}` attribute " \ "`#{type}` could not be parsed: #{e.}" rescue Puppet::ParseError => e raise Puppet::DevError, "The type of the `#{attr_name}` attribute " \ "`#{type}` is not recognised: #{e.}" end |
.try_mungify(type, value, error_msg_prefix) ⇒ Array
Recursive implementation part of #mungify_core. Uses a multi-valued return value to avoid excessive exception throwing for regular usage.
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 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 |
# File 'lib/puppet/resource_api/data_type_handling.rb', line 71 def self.try_mungify(type, value, error_msg_prefix) case type when Puppet::Pops::Types::PArrayType if value.is_a? Array conversions = value.map do |v| try_mungify(type.element_type, v, error_msg_prefix) end # only convert the values if none failed. otherwise fall through and # rely on puppet to render a proper error if conversions.all? { |c| c[1].nil? } value = conversions.map { |c| c[0] } end end when Puppet::Pops::Types::PBooleanType value = boolean_munge(value) when Puppet::Pops::Types::PIntegerType, Puppet::Pops::Types::PFloatType, Puppet::Pops::Types::PNumericType if value.is_a?(String) && (value.match?(%r{^-?\d+$}) || value.match?(Puppet::Pops::Patterns::NUMERIC)) value = Puppet::Pops::Utils.to_n(value) end when Puppet::Pops::Types::PEnumType, Puppet::Pops::Types::PStringType, Puppet::Pops::Types::PPatternType value = value.to_s if value.is_a? Symbol when Puppet::Pops::Types::POptionalType return value.nil? ? [nil, nil] : try_mungify(type.type, value, error_msg_prefix) when Puppet::Pops::Types::PVariantType # try converting to anything except string first string_type = type.types.find { |t| t.is_a? Puppet::Pops::Types::PStringType } conversion_results = (type.types - [string_type]).map do |t| try_mungify(t, value, error_msg_prefix) end # only consider valid results conversion_results = conversion_results.select { |r| r[1].nil? }.to_a # use the conversion result if unambiguous return conversion_results[0] if conversion_results.length == 1 # return an error if ambiguous if conversion_results.length > 1 return [nil, ambiguous_error_msg(error_msg_prefix, value, type)] end # try to interpret as string return try_mungify(string_type, value, error_msg_prefix) if string_type # fall through to default handling end error_msg = try_validate(type, value, error_msg_prefix) return [nil, error_msg] if error_msg # an error [value, nil] # match end |
.try_validate(type, value, error_msg_prefix) ⇒ String?
Tries to validate the ‘value` against the specified `type`.
169 170 171 172 173 174 175 176 177 178 179 180 |
# File 'lib/puppet/resource_api/data_type_handling.rb', line 169 def self.try_validate(type, value, error_msg_prefix) return nil if type.instance?(value) # an error :-( inferred_type = Puppet::Pops::Types::TypeCalculator.infer_set(value) error_msg = Puppet::Pops::Types::TypeMismatchDescriber.new.describe_mismatch( error_msg_prefix, type, inferred_type, ) error_msg end |
.validate(type, value, error_msg_prefix) ⇒ Object
Validates the ‘value` against the specified `type`.
158 159 160 161 |
# File 'lib/puppet/resource_api/data_type_handling.rb', line 158 def self.validate(type, value, error_msg_prefix) error_msg = try_validate(type, value, error_msg_prefix) raise Puppet::ResourceError, error_msg if error_msg end |
.validate_ensure(definition) ⇒ Object
182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 |
# File 'lib/puppet/resource_api/data_type_handling.rb', line 182 def self.validate_ensure(definition) return unless definition[:attributes].key? :ensure = definition[:attributes][:ensure] type = parse_puppet_type(:ensure, [:type]) # If the type is wrapped in optional, then check it unwrapped: type = type.type if type.is_a?(Puppet::Pops::Types::POptionalType) return if type.is_a?(Puppet::Pops::Types::PEnumType) && type.values.sort == %w[absent present].sort # If Variant was used instead, then construct one and use the built-in type comparison: variant_type = Puppet::Pops::Types::TypeParser.singleton.parse('Variant[Undef, Enum[present, absent]]') return if variant_type == type raise Puppet::DevError, '`:ensure` attribute must have a type of: `Enum[present, absent]` or `Optional[Enum[present, absent]]`' end |