-
Notifications
You must be signed in to change notification settings - Fork 597
/
If.py
105 lines (92 loc) · 3.55 KB
/
If.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
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
"""
Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
SPDX-License-Identifier: MIT-0
"""
from __future__ import annotations
from collections import deque
from typing import Any
from cfnlint.context.conditions.exceptions import Unsatisfiable
from cfnlint.jsonschema import ValidationError, ValidationResult, Validator
from cfnlint.rules.functions._BaseFn import BaseFn, all_types
class If(BaseFn):
"""Check if Condition exists"""
id = "E1028"
shortdesc = "Check Fn::If structure for validity"
description = "Check Fn::If to make sure its valid. Condition has to be a string."
source_url = "https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/intrinsic-function-reference-conditions.html#intrinsic-function-reference-conditions-if"
tags = ["functions", "if"]
def __init__(self) -> None:
super().__init__("Fn::If", all_types)
self.child_rules["W1028"] = None
def schema(self, validator, instance) -> dict[str, Any]:
return {
"type": ["array"],
"minItems": 3,
"maxItems": 3,
"fn_items": [
{
"functions": [],
"schema": {
"type": ["string"],
"enum": list(validator.context.conditions.conditions.keys()),
},
},
],
}
def fn_if(
self, validator: Validator, s: Any, instance: Any, schema: Any
) -> ValidationResult:
# validate this function will return the correct type
errs = list(self.validate_fn_output_types(validator, s, instance))
key, value = self.key_value(instance)
errs.extend(
list(
self.fix_errors(
self.validator(validator).descend(
value,
self.schema(validator, instance),
path=key,
)
)
)
)
if errs:
yield from iter(errs)
return
for i in [1, 2]:
# we pass through the functions for the paths down
# the second and third element of the if
try:
element_validator = validator.evolve(
context=validator.context.evolve(
path=validator.context.path.descend(
path=key,
),
conditions=validator.context.conditions.evolve(
{value[0]: True if i == 1 else False}
),
)
)
for err in element_validator.descend(
instance=value[i], schema=s, path=i
):
err.path.appendleft(key)
yield err
except Unsatisfiable as e:
yield ValidationError(
f"{[key, i]!r} is not reachable. {e.message}",
path=deque([key, i]),
rule=self.child_rules["W1028"],
)
element_validator = validator.evolve(
context=validator.context.evolve(
path=validator.context.path.descend(
path=key,
),
)
)
for err in element_validator.descend(
instance=value[i], schema=s, path=i
):
err.path.appendleft(key)
yield err