@@ -127,62 +127,116 @@ def _split_inset_properties(self, property_chain):
127
127
128
128
return None , []
129
129
130
- def _check_value (self , value , path , property_chain , cfn ):
130
+ def _check_value_defined (self , value , path , property_chain , cfn , ** _ ):
131
131
matches = []
132
132
child_property , new_property_chain = self ._split_inset_properties (
133
133
property_chain
134
134
)
135
- if self .is_defined and (
136
- value is None or value .get (child_property , None ) is None
135
+ # Specific for !Ref AWS::NoValue, no callback even for pass_if_null=True
136
+ if len (property_chain ) == 1 and value == {
137
+ child_property : {"Ref" : "AWS::NoValue" }
138
+ }:
139
+ matches .append (
140
+ cfnlint .rules .RuleMatch (
141
+ path , error_message or f"{ path } must be defined"
142
+ )
143
+ )
144
+ return matches
145
+ if value is None or (
146
+ isinstance (value , dict ) and value .get ("Ref" , None ) == "AWS::NoValue"
137
147
):
138
148
matches .append (
139
149
cfnlint .rules .RuleMatch (
140
150
path , error_message or f"{ path } must be defined"
141
151
)
142
152
)
153
+ return matches
154
+
143
155
if child_property is not None :
144
156
matches .extend (
145
157
cfn .check_value (
146
158
value ,
147
159
child_property ,
148
160
path ,
149
- check_value = self ._check_value ,
161
+ check_value = self ._check_value_defined ,
162
+ check_ref = self ._check_value_defined ,
163
+ check_get_att = self ._check_value_defined ,
164
+ check_find_in_map = self ._check_value_defined ,
165
+ check_split = self ._check_value_defined ,
166
+ check_join = self ._check_value_defined ,
167
+ check_import_value = self ._check_value_defined ,
168
+ check_sub = self ._check_value_defined ,
169
+ pass_if_null = True ,
150
170
property_chain = new_property_chain ,
151
171
cfn = cfn ,
152
172
)
153
173
)
174
+ return matches
175
+
176
+ def _check_value_not_defined (self , value , path , property_chain , cfn , ** _ ):
177
+ matches = []
178
+ if value is None :
154
179
return matches
155
- if not self . is_defined and value is not None :
180
+ if len ( property_chain ) == 0 and value is not None :
156
181
matches .append (
157
182
cfnlint .rules .RuleMatch (
158
183
path , error_message or f"{ path } must not be defined"
159
184
)
160
185
)
186
+ return matches
187
+
188
+ child_property , new_property_chain = self ._split_inset_properties (
189
+ property_chain
190
+ )
191
+ matches .extend (
192
+ cfn .check_value (
193
+ value ,
194
+ child_property ,
195
+ path ,
196
+ check_value = self ._check_value_not_defined ,
197
+ check_ref = self ._check_value_not_defined ,
198
+ check_get_att = self ._check_value_not_defined ,
199
+ check_find_in_map = self ._check_value_not_defined ,
200
+ check_split = self ._check_value_not_defined ,
201
+ check_join = self ._check_value_not_defined ,
202
+ check_import_value = self ._check_value_not_defined ,
203
+ check_sub = self ._check_value_not_defined ,
204
+ property_chain = new_property_chain ,
205
+ cfn = cfn ,
206
+ pass_if_null = True ,
207
+ )
208
+ )
161
209
return matches
162
210
163
211
def match_resource_properties (self , properties , _ , path , cfn ):
164
212
child_property , new_property_chain = self ._split_inset_properties (
165
213
self .property_chain
166
214
)
215
+ check_fn = (
216
+ self ._check_value_defined
217
+ if self .is_defined
218
+ else self ._check_value_not_defined
219
+ )
167
220
matches = []
168
221
# here does nothing when the value is not defined, this is checked separately below
169
222
matches .extend (
170
223
cfn .check_value (
171
224
properties ,
172
225
child_property ,
173
226
path ,
174
- check_value = self ._check_value ,
227
+ check_value = check_fn ,
228
+ check_ref = check_fn ,
229
+ check_get_att = check_fn ,
230
+ check_find_in_map = check_fn ,
231
+ check_split = check_fn ,
232
+ check_join = check_fn ,
233
+ check_import_value = check_fn ,
234
+ check_sub = check_fn ,
175
235
property_chain = new_property_chain ,
176
236
cfn = cfn ,
237
+ pass_if_null = True ,
177
238
)
178
239
)
179
- # check child exists separately when checking is_defined
180
- if self .is_defined and properties .get (child_property , None ) is None :
181
- matches .append (
182
- cfnlint .rules .RuleMatch (
183
- path , error_message or f"{ path } must be defined"
184
- )
185
- )
186
240
return matches
187
241
188
242
return CustomIsDefinedRule (
0 commit comments