@@ -44,6 +44,7 @@ def fetch_cached_hashes(cache, hashes)
44
44
# @param context [Object] the Puppet runtime context to operate in and send feedback to
45
45
# @param resources [Hash] the hash of the resource to canonicalize from either manifest or invocation
46
46
# @return [Hash] returns a hash representing the current state of the object, if it exists
47
+ # rubocop:disable Metrics/BlockLength, Metrics/MethodLength
47
48
def canonicalize ( context , resources )
48
49
canonicalized_resources = [ ]
49
50
resources . collect do |r |
@@ -83,9 +84,18 @@ def canonicalize(context, resources)
83
84
downcased_result . each do |key , value |
84
85
# Canonicalize to the manifest value unless the downcased strings match and the attribute is not an enum:
85
86
# - When the values don't match at all, the manifest value is desired;
86
- # - When the values match case insensitively but the attribute is an enum, prefer the casing of the manifest enum.
87
- # - When the values match case insensitively and the attribute is not an enum, prefer the casing from invoke_get_method
88
- canonicalized [ key ] = r [ key ] unless same? ( value , downcased_resource [ key ] ) && !enum_attributes ( context ) . include? ( key )
87
+ # - When the values match case insensitively but the attribute is an enum, and the casing from invoke_get_method
88
+ # is not int the enum, prefer the casing of the manifest enum.
89
+ # - When the values match case insensitively and the attribute is not an enum, or is an enum and invoke_get_method casing
90
+ # is in the enum, prefer the casing from invoke_get_method
91
+ is_enum = enum_attributes ( context ) . include? ( key )
92
+ canonicalized_value_in_enum = if is_enum
93
+ enum_values ( context , key ) . include? ( canonicalized [ key ] )
94
+ else
95
+ false
96
+ end
97
+ match_insensitively = same? ( value , downcased_resource [ key ] )
98
+ canonicalized [ key ] = r [ key ] unless match_insensitively && ( canonicalized_value_in_enum || !is_enum )
89
99
canonicalized . delete ( key ) unless downcased_resource . key? ( key )
90
100
end
91
101
# Cache the actually canonicalized resource separately
@@ -104,6 +114,7 @@ def canonicalize(context, resources)
104
114
context . debug ( "Canonicalized Resources: #{ canonicalized_resources } " )
105
115
canonicalized_resources
106
116
end
117
+ # rubocop:enable Metrics/BlockLength, Metrics/MethodLength
107
118
108
119
# Attempts to retrieve an instance of the DSC resource, invoking the `Get` method and passing any
109
120
# namevars as the Properties to Invoke-DscResource. The result object, if any, is compared to the
@@ -686,6 +697,28 @@ def enum_attributes(context)
686
697
context . type . attributes . select { |_name , properties | properties [ :type ] . include? ( 'Enum[' ) } . keys
687
698
end
688
699
700
+ # Parses the DSC resource type definition to retrieve the values of any attributes which are specified as enums
701
+ #
702
+ # @param context [Object] the Puppet runtime context to operate in and send feedback to
703
+ # @param attribute [String] the enum attribute to retrieve the allowed values from
704
+ # @return [Array] returns an array of attribute names as symbols which are enums
705
+ def enum_values ( context , attribute )
706
+ # Get the attribute's type string for the given key
707
+ type_string = context . type . attributes [ attribute ] [ :type ]
708
+
709
+ # Return an empty array if the key doesn't have an Enum type or doesn't exist
710
+ return [ ] unless type_string &.include? ( 'Enum[' )
711
+
712
+ # Extract the enum values from the type string
713
+ enum_content = type_string . match ( /Enum\[ (.*?)\] / ) &.[]( 1 )
714
+
715
+ # Return an empty array if we couldn't find the enum values
716
+ return [ ] if enum_content . nil?
717
+
718
+ # Return an array of the enum values, stripped of extra whitespace and quote marks
719
+ enum_content . split ( ',' ) . map { |val | val . strip . delete ( '\'' ) }
720
+ end
721
+
689
722
# Look through a fully formatted string, replacing all instances where a value matches the formatted properties
690
723
# of an instantiated variable with references to the variable instead. This allows us to pass complex and nested
691
724
# CIM instances to the Invoke-DscResource parameter hash without constructing them *in* the hash.
0 commit comments