Skip to content

Commit 091f9a7

Browse files
authored
V1 Cleanup based on testing of templates repo (#3303)
* Cleanup issues from testing templates repo * Validate ref values are plausible before resolution * Support future condition logic in context
1 parent 186a63d commit 091f9a7

File tree

106 files changed

+57438
-53144
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

106 files changed

+57438
-53144
lines changed

scripts/update_schemas_format.py

100644100755
File mode changed.

src/cfnlint/conditions/conditions.py

+59
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@
1818
from cfnlint.conditions._condition import ConditionNamed
1919
from cfnlint.conditions._equals import Equal
2020
from cfnlint.conditions._utils import get_hash
21+
from cfnlint.helpers import PSEUDOPARAMS
2122

2223
LOGGER = logging.getLogger(__name__)
2324

@@ -348,3 +349,61 @@ def build_scenerios_on_region(
348349
)
349350
if satisfiable(cnf_test):
350351
yield False
352+
353+
def satisfiable(
354+
self, conditions: dict[str, bool], parameter_values: dict[str, str]
355+
) -> bool:
356+
"""Given a list of condition names this function will
357+
determine if the conditions are satisfied
358+
359+
Args:
360+
condition_names (List[str]): A list of condition names
361+
362+
Returns:
363+
bool: True if the conditions are satisfied
364+
"""
365+
if not conditions:
366+
return True
367+
368+
cnf = self._cnf.copy()
369+
at_least_one_param_found = False
370+
for condition_name, opt in conditions.items():
371+
for c_equals in self._conditions[condition_name].equals:
372+
found_params = {}
373+
for param, value in parameter_values.items():
374+
if param in PSEUDOPARAMS:
375+
continue
376+
377+
ref_hash = get_hash({"Ref": param})
378+
if ref_hash in c_equals.parameters:
379+
found_params = {ref_hash: value}
380+
381+
if not found_params:
382+
continue
383+
384+
at_least_one_param_found = True
385+
if c_equals.test(found_params):
386+
cnf.add_prop(Symbol(c_equals.hash))
387+
else:
388+
cnf.add_prop(Not(Symbol(c_equals.hash)))
389+
390+
if opt:
391+
cnf.add_prop(
392+
self._conditions[condition_name].build_true_cnf(
393+
self._solver_params
394+
)
395+
)
396+
else:
397+
cnf.add_prop(
398+
self._conditions[condition_name].build_false_cnf(
399+
self._solver_params
400+
)
401+
)
402+
403+
if at_least_one_param_found is False:
404+
return True
405+
406+
satisfied = satisfiable(cnf, all_models=False)
407+
if satisfied is False:
408+
return satisfied
409+
return True

src/cfnlint/context/_conditions.py

+70
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,70 @@
1+
"""
2+
Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
3+
SPDX-License-Identifier: MIT-0
4+
"""
5+
6+
from __future__ import annotations
7+
8+
from dataclasses import dataclass, field
9+
from typing import Any
10+
11+
12+
@dataclass(frozen=True)
13+
class Condition:
14+
instance: Any = field(init=True)
15+
status: bool | None = field(init=True, default=None)
16+
17+
def evolve(self, status: bool | None) -> "Condition":
18+
cls = self.__class__
19+
20+
if self.status is not None:
21+
if status != self.status:
22+
raise ValueError("Resetting status to condition")
23+
24+
return cls(
25+
instance=self.instance,
26+
status=status,
27+
)
28+
29+
30+
@dataclass(frozen=True)
31+
class Conditions:
32+
# Template level condition management
33+
conditions: dict[str, Condition] = field(init=True, default_factory=dict)
34+
35+
@classmethod
36+
def create_from_instance(cls, conditions: dict[str, Any]) -> "Conditions":
37+
obj = {}
38+
if not isinstance(conditions, dict):
39+
raise ValueError("Conditions must be a object")
40+
for k, v in conditions.items():
41+
try:
42+
obj[k] = Condition(v)
43+
except ValueError:
44+
pass
45+
46+
return cls(conditions=obj)
47+
48+
def evolve(self, status: dict[str, bool]) -> "Conditions":
49+
cls = self.__class__
50+
51+
conditions: dict[str, Condition] = {}
52+
for condition, value in self.conditions.items():
53+
s = status.get(condition, value.status)
54+
try:
55+
conditions[condition] = value.evolve(status=s)
56+
except ValueError as e:
57+
raise ValueError(f"Error evolving condition {condition}") from e
58+
59+
return cls(
60+
conditions=conditions,
61+
)
62+
63+
@property
64+
def status(self) -> dict[str, bool]:
65+
obj = {}
66+
for name, c in self.conditions.items():
67+
if c.status is not None:
68+
obj[name] = c.status
69+
70+
return obj

src/cfnlint/context/context.py

+9-25
Original file line numberDiff line numberDiff line change
@@ -8,8 +8,9 @@
88
from abc import ABC, abstractmethod
99
from collections import deque
1010
from dataclasses import InitVar, dataclass, field, fields
11-
from typing import Any, Deque, Dict, Iterator, List, Mapping, Sequence, Set, Tuple
11+
from typing import Any, Deque, Dict, Iterator, List, Sequence, Set, Tuple
1212

13+
from cfnlint.context._conditions import Conditions
1314
from cfnlint.helpers import (
1415
BOOLEAN_STRINGS_TRUE,
1516
FUNCTIONS,
@@ -136,7 +137,7 @@ class Context:
136137
# cfn-lint Template class
137138
parameters: Dict[str, "Parameter"] = field(init=True, default_factory=dict)
138139
resources: Dict[str, "Resource"] = field(init=True, default_factory=dict)
139-
conditions: Dict[str, "Condition"] = field(init=True, default_factory=dict)
140+
conditions: Conditions = field(init=True, default_factory=Conditions)
140141
mappings: Dict[str, "Map"] = field(init=True, default_factory=dict)
141142

142143
strict_types: bool = field(init=True, default=True)
@@ -149,9 +150,6 @@ class Context:
149150
# and adds in any Refs available from things like Fn::Sub
150151
ref_values: Dict[str, Any] = field(init=True, default_factory=dict)
151152

152-
# Resolved conditions for reference
153-
resolved_conditions: Mapping[str, bool] = field(init=True, default_factory=dict)
154-
155153
transforms: Transforms = field(init=True, default_factory=lambda: Transforms([]))
156154

157155
def evolve(self, **kwargs) -> "Context":
@@ -187,6 +185,10 @@ def ref_value(self, instance: str) -> Iterator[Tuple[str | List[str], "Context"]
187185
return
188186
if instance in self.parameters:
189187
for v, path in self.parameters[instance].ref(self):
188+
189+
# validate that ref is possible with path
190+
# need to evaluate if Fn::If would be not true if value is
191+
# what it is
190192
yield v, self.evolve(
191193
path=self.path.evolve(
192194
value_path=deque(["Parameters", instance]) + path
@@ -266,11 +268,6 @@ def ref(self, context: Context) -> Iterator[Any]:
266268
pass
267269

268270

269-
@dataclass
270-
class Condition:
271-
instance: Any = field(init=True)
272-
273-
274271
@dataclass
275272
class Parameter(_Ref):
276273
"""
@@ -448,19 +445,6 @@ def _init_transforms(transforms: Any) -> Transforms:
448445
return Transforms([])
449446

450447

451-
def _init_conditions(conditions: Any) -> dict[str, Condition]:
452-
obj = {}
453-
if not isinstance(conditions, dict):
454-
raise ValueError("Conditions must be a object")
455-
for k, v in conditions.items():
456-
try:
457-
obj[k] = Condition(v)
458-
except ValueError:
459-
pass
460-
461-
return obj
462-
463-
464448
def _init_mappings(mappings: Any) -> dict[str, Map]:
465449
obj = {}
466450
if not isinstance(mappings, dict):
@@ -489,9 +473,9 @@ def create_context_for_template(cfn):
489473

490474
transforms = _init_transforms(cfn.template.get("Transform", []))
491475

492-
conditions = {}
476+
conditions = Conditions({})
493477
try:
494-
conditions = _init_conditions(cfn.template.get("Conditions", {}))
478+
conditions = Conditions.create_from_instance(cfn.template.get("Conditions", {}))
495479
except (ValueError, AttributeError):
496480
pass
497481

Original file line numberDiff line numberDiff line change
@@ -1 +1 @@
1-
{"etag": "\"d0827f5391a01752db21fee73f3bb56f\"", "url": "https://schema.cloudformation.eu-south-1.amazonaws.com/CloudformationSchema.zip"}
1+
{"etag": "\"8e21dc9f4caa5b99df836d2724e85007\"", "url": "https://schema.cloudformation.eu-south-1.amazonaws.com/CloudformationSchema.zip"}
Original file line numberDiff line numberDiff line change
@@ -1 +1 @@
1-
{"etag": "\"2c3fe9abad68e57f03edaa326b343db6\"", "url": "https://schema.cloudformation.us-gov-east-1.amazonaws.com/CloudformationSchema.zip"}
1+
{"etag": "\"3efb1f36bf2069dfd90693d73255b99b\"", "url": "https://schema.cloudformation.us-gov-east-1.amazonaws.com/CloudformationSchema.zip"}
Original file line numberDiff line numberDiff line change
@@ -1 +1 @@
1-
{"etag": "\"edbad4a5419cb79a91b306b985b73155\"", "url": "https://schema.cloudformation.me-south-1.amazonaws.com/CloudformationSchema.zip"}
1+
{"etag": "\"e862b8d52f9fb2a4800ed9ae537c381d\"", "url": "https://schema.cloudformation.me-south-1.amazonaws.com/CloudformationSchema.zip"}
Original file line numberDiff line numberDiff line change
@@ -1 +1 @@
1-
{"etag": "\"721feac4151695b971f278d8036d377c\"", "url": "https://schema.cloudformation.us-gov-west-1.amazonaws.com/CloudformationSchema.zip"}
1+
{"etag": "\"f0cbfdd2a88a3e39fe4587698aece4bc\"", "url": "https://schema.cloudformation.us-gov-west-1.amazonaws.com/CloudformationSchema.zip"}
Original file line numberDiff line numberDiff line change
@@ -1 +1 @@
1-
{"etag": "\"b1def23a3f79fa2a029ccfbb10446a45\"", "url": "https://schema.cloudformation.me-central-1.amazonaws.com/CloudformationSchema.zip"}
1+
{"etag": "\"b995e7d567bfe5107c701b7708ccc12c\"", "url": "https://schema.cloudformation.me-central-1.amazonaws.com/CloudformationSchema.zip"}
Original file line numberDiff line numberDiff line change
@@ -1 +1 @@
1-
{"etag": "\"3ed4f5619dadc27801d4a7a38863f8be\"", "url": "https://schema.cloudformation.eu-west-2.amazonaws.com/CloudformationSchema.zip"}
1+
{"etag": "\"71b34442c9fb5fae86f1a0ef0bca7c70\"", "url": "https://schema.cloudformation.eu-west-2.amazonaws.com/CloudformationSchema.zip"}
Original file line numberDiff line numberDiff line change
@@ -1 +1 @@
1-
{"etag": "\"c89014c462ab96b20b6cd5b719c331f4\"", "url": "https://schema.cloudformation.af-south-1.amazonaws.com/CloudformationSchema.zip"}
1+
{"etag": "\"03a41aa9d5c778053c384b4135e05f42\"", "url": "https://schema.cloudformation.af-south-1.amazonaws.com/CloudformationSchema.zip"}
Original file line numberDiff line numberDiff line change
@@ -1 +1 @@
1-
{"etag": "\"4678f072d4101c242220c89a8dbf3939\"", "url": "https://schema.cloudformation.us-west-1.amazonaws.com/CloudformationSchema.zip"}
1+
{"etag": "\"dc0a4ce69ad2a682aa4f63ccfc0c9880\"", "url": "https://schema.cloudformation.us-west-1.amazonaws.com/CloudformationSchema.zip"}
Original file line numberDiff line numberDiff line change
@@ -1 +1 @@
1-
{"etag": "\"6b48036379a0751d366f95bcbc4b3192\"", "url": "https://schema.cloudformation.eu-central-1.amazonaws.com/CloudformationSchema.zip"}
1+
{"etag": "\"3293c078f8550d3960de9ee1279093bc\"", "url": "https://schema.cloudformation.eu-central-1.amazonaws.com/CloudformationSchema.zip"}
Original file line numberDiff line numberDiff line change
@@ -1 +1 @@
1-
{"etag": "\"d23dce937982dc37fa7044b43fffd977\"", "url": "https://schema.cloudformation.ap-south-1.amazonaws.com/CloudformationSchema.zip"}
1+
{"etag": "\"f24d7e523686f97241c4735c1840d62e\"", "url": "https://schema.cloudformation.ap-south-1.amazonaws.com/CloudformationSchema.zip"}
Original file line numberDiff line numberDiff line change
@@ -1 +1 @@
1-
{"etag": "\"f376b05bbeeefd37c12e7245754d6c48\"", "url": "https://schema.cloudformation.ap-southeast-4.amazonaws.com/CloudformationSchema.zip"}
1+
{"etag": "\"9571fcb8dfb44407cfd91787059d29d4\"", "url": "https://schema.cloudformation.ap-southeast-4.amazonaws.com/CloudformationSchema.zip"}
Original file line numberDiff line numberDiff line change
@@ -1 +1 @@
1-
{"etag": "\"598ef6013e6125ca185b72e6f942afca\"", "url": "https://schema.cloudformation.us-east-2.amazonaws.com/CloudformationSchema.zip"}
1+
{"etag": "\"0901a777ed5ca3b8655822dd065e606d\"", "url": "https://schema.cloudformation.us-east-2.amazonaws.com/CloudformationSchema.zip"}
Original file line numberDiff line numberDiff line change
@@ -1 +1 @@
1-
{"etag": "\"8930df3c87aaf45508bdc05f0e8a0eba\"", "url": "https://schema.cloudformation.ap-southeast-1.amazonaws.com/CloudformationSchema.zip"}
1+
{"etag": "\"6e7282388d60ba18f7a1e810c32ae5e6\"", "url": "https://schema.cloudformation.ap-southeast-1.amazonaws.com/CloudformationSchema.zip"}
Original file line numberDiff line numberDiff line change
@@ -1 +1 @@
1-
{"etag": "\"2e2def035877586c429f950f7d8b5e65\"", "url": "https://schema.cloudformation.ap-northeast-2.amazonaws.com/CloudformationSchema.zip"}
1+
{"etag": "\"4481d14e13ecb83021f3fa7732a072d4\"", "url": "https://schema.cloudformation.ap-northeast-2.amazonaws.com/CloudformationSchema.zip"}
Original file line numberDiff line numberDiff line change
@@ -1 +1 @@
1-
{"etag": "\"397de2415e3b51b7aa0284bf8a2a2e70\"", "url": "https://schema.cloudformation.ap-southeast-3.amazonaws.com/CloudformationSchema.zip"}
1+
{"etag": "\"b18c7ffb485d2d897035614eacbb4ff7\"", "url": "https://schema.cloudformation.ap-southeast-3.amazonaws.com/CloudformationSchema.zip"}
Original file line numberDiff line numberDiff line change
@@ -1 +1 @@
1-
{"etag": "\"8c39a53d13779450ebf7d03191cf6bc9\"", "url": "https://schema.cloudformation.ap-east-1.amazonaws.com/CloudformationSchema.zip"}
1+
{"etag": "\"8da7617ff7251272a0ecc94bb36d8c23\"", "url": "https://schema.cloudformation.ap-east-1.amazonaws.com/CloudformationSchema.zip"}
Original file line numberDiff line numberDiff line change
@@ -1 +1 @@
1-
{"etag": "\"bf0cc975ad2ddb6a5b1b15b1b3b262d7\"", "url": "https://schema.cloudformation.sa-east-1.amazonaws.com/CloudformationSchema.zip"}
1+
{"etag": "\"a8ef7c07a5b62c4de0f8e6fb79fc4b0b\"", "url": "https://schema.cloudformation.sa-east-1.amazonaws.com/CloudformationSchema.zip"}
Original file line numberDiff line numberDiff line change
@@ -1 +1 @@
1-
{"etag": "\"644e4e47b1e4aad9af5a6936855db14d\"", "url": "https://schema.cloudformation.ap-southeast-2.amazonaws.com/CloudformationSchema.zip"}
1+
{"etag": "\"78df17182748cca99b8a8efba79d2ecd\"", "url": "https://schema.cloudformation.ap-southeast-2.amazonaws.com/CloudformationSchema.zip"}
Original file line numberDiff line numberDiff line change
@@ -1 +1 @@
1-
{"etag": "\"709be88da2e091792f0123cb2574e962\"", "url": "https://schema.cloudformation.ca-west-1.amazonaws.com/CloudformationSchema.zip"}
1+
{"etag": "\"b2bf37b2de7adcd8ebe025b8c1b7e3f3\"", "url": "https://schema.cloudformation.ca-west-1.amazonaws.com/CloudformationSchema.zip"}
Original file line numberDiff line numberDiff line change
@@ -1 +1 @@
1-
{"etag": "\"1bab187bb389ee733aac163e25414e21\"", "url": "https://schema.cloudformation.eu-central-2.amazonaws.com/CloudformationSchema.zip"}
1+
{"etag": "\"586ccc967824b79951230311f96a5c8f\"", "url": "https://schema.cloudformation.eu-central-2.amazonaws.com/CloudformationSchema.zip"}
Original file line numberDiff line numberDiff line change
@@ -1 +1 @@
1-
{"etag": "\"b4cfe9d40d2399256ed406cd41c4eb59\"", "url": "https://schema.cloudformation.eu-north-1.amazonaws.com/CloudformationSchema.zip"}
1+
{"etag": "\"f4b1a7c7eb7851f07eb698cffc58ac08\"", "url": "https://schema.cloudformation.eu-north-1.amazonaws.com/CloudformationSchema.zip"}
Original file line numberDiff line numberDiff line change
@@ -1 +1 @@
1-
{"etag": "\"4d3a350d93c07575dbe1e6a53f0bf334\"", "url": "https://schema.cloudformation.eu-south-2.amazonaws.com/CloudformationSchema.zip"}
1+
{"etag": "\"997d1c02e4833e76905453998aeadaf1\"", "url": "https://schema.cloudformation.eu-south-2.amazonaws.com/CloudformationSchema.zip"}
Original file line numberDiff line numberDiff line change
@@ -1 +1 @@
1-
{"etag": "\"e30e1b7061ecf6c46d1b495c9d658e42\"", "url": "https://schema.cloudformation.ca-central-1.amazonaws.com/CloudformationSchema.zip"}
1+
{"etag": "\"9c8967d0c5f53fc40ed297cd2b08aa35\"", "url": "https://schema.cloudformation.ca-central-1.amazonaws.com/CloudformationSchema.zip"}
Original file line numberDiff line numberDiff line change
@@ -1 +1 @@
1-
{"etag": "\"240e8979bb194a0e76adde5a119be6fa\"", "url": "https://schema.cloudformation.eu-west-3.amazonaws.com/CloudformationSchema.zip"}
1+
{"etag": "\"189d61fc63b82d5afd6fa1d7c24df012\"", "url": "https://schema.cloudformation.eu-west-3.amazonaws.com/CloudformationSchema.zip"}
Original file line numberDiff line numberDiff line change
@@ -1 +1 @@
1-
{"etag": "\"7fe1519ba3544adef2fed648f7cdcda5\"", "url": "https://schema.cloudformation.ap-northeast-3.amazonaws.com/CloudformationSchema.zip"}
1+
{"etag": "\"ed6a3644fb2576d2c563b9b5dc7e4f99\"", "url": "https://schema.cloudformation.ap-northeast-3.amazonaws.com/CloudformationSchema.zip"}
Original file line numberDiff line numberDiff line change
@@ -1 +1 @@
1-
{"etag": "\"d9bc56584ee4ec888eab4dc0d1e7c0cf\"", "url": "https://schema.cloudformation.ap-south-2.amazonaws.com/CloudformationSchema.zip"}
1+
{"etag": "\"15ff053fecb2d9f390ead75a04a9fc40\"", "url": "https://schema.cloudformation.ap-south-2.amazonaws.com/CloudformationSchema.zip"}
Original file line numberDiff line numberDiff line change
@@ -1 +1 @@
1-
{"etag": "\"187b7949251051e2debb57afc128bfe9\"", "url": "https://schema.cloudformation.us-east-1.amazonaws.com/CloudformationSchema.zip"}
1+
{"etag": "\"cf72a169c13940c71da83696f76618c4\"", "url": "https://schema.cloudformation.us-east-1.amazonaws.com/CloudformationSchema.zip"}
Original file line numberDiff line numberDiff line change
@@ -1 +1 @@
1-
{"etag": "\"7e7e5a070b1128c8756143f7a5906ab9\"", "url": "https://schema.cloudformation.il-central-1.amazonaws.com/CloudformationSchema.zip"}
1+
{"etag": "\"5789ec51cc517240c3ff889d308c1c8d\"", "url": "https://schema.cloudformation.il-central-1.amazonaws.com/CloudformationSchema.zip"}
Original file line numberDiff line numberDiff line change
@@ -1 +1 @@
1-
{"etag": "\"751a5f39158897603b1a80a1f38de264\"", "url": "https://schema.cloudformation.eu-west-1.amazonaws.com/CloudformationSchema.zip"}
1+
{"etag": "\"4416b41626f4d09ed7365062e52517d8\"", "url": "https://schema.cloudformation.eu-west-1.amazonaws.com/CloudformationSchema.zip"}
Original file line numberDiff line numberDiff line change
@@ -1 +1 @@
1-
{"etag": "\"013c70fbc5816a1ff09667ee596ce5d5\"", "url": "https://schema.cloudformation.ap-northeast-1.amazonaws.com/CloudformationSchema.zip"}
1+
{"etag": "\"a384225460a33fa84f23423dae5ba6ba\"", "url": "https://schema.cloudformation.ap-northeast-1.amazonaws.com/CloudformationSchema.zip"}

src/cfnlint/data/schemas/patches/extensions/all/aws_elasticloadbalancing_loadbalancer/format.json

+5
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,9 @@
11
[
2+
{
3+
"op": "add",
4+
"path": "/properties/SourceSecurityGroup/properties/GroupName/format",
5+
"value": "AWS::EC2::SecurityGroup.GroupName"
6+
},
27
{
38
"op": "add",
49
"path": "/properties/SecurityGroups/format",

src/cfnlint/data/schemas/patches/providers/all/aws_elasticloadbalancing_loadbalancer/readonlyproperties.json

+1
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,7 @@
3737
"value": {
3838
"properties": {
3939
"GroupName": {
40+
"format": "AWS::EC2::SecurityGroup.GroupName",
4041
"type": "string"
4142
},
4243
"OwnerAlias": {

0 commit comments

Comments
 (0)