-
Notifications
You must be signed in to change notification settings - Fork 602
/
Copy pathQueueDLQ.py
103 lines (86 loc) · 3.54 KB
/
QueueDLQ.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
"""
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, Iterator
import cfnlint.data.schemas.extensions.aws_sqs_queue
from cfnlint.helpers import bool_compare, is_function
from cfnlint.jsonschema import ValidationError, ValidationResult, Validator
from cfnlint.rules.helpers import get_value_from_path
from cfnlint.rules.jsonschema.CfnLintJsonSchema import CfnLintJsonSchema, SchemaDetails
class QueueDLQ(CfnLintJsonSchema):
id = "E3502"
shortdesc = "Validate SQS DLQ queues are the same type"
description = (
"SQS queues using DLQ have to have the destination "
"queue as the same type (FIFO or standard)"
)
source_url = "https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-sqs-queue.html"
tags = ["resources", "sqs"]
def __init__(self) -> None:
super().__init__(
keywords=[
"Resources/AWS::SQS::Queue/Properties",
],
schema_details=SchemaDetails(
module=cfnlint.data.schemas.extensions.aws_sqs_queue,
filename="properties.json",
),
all_matches=True,
)
def _is_fifo_queue(
self, validator: Validator, instance: Any
) -> Iterator[tuple[str, Validator]]:
standard = "standard"
fifo = "FIFO"
if "FifoQueue" not in instance:
yield standard, validator
return
for queue_type, queue_type_validator in get_value_from_path(
validator=validator, instance=instance, path=deque(["FifoQueue"])
):
yield (
fifo if bool_compare(queue_type, True) else standard
), queue_type_validator
def validate(
self, validator: Validator, _: Any, instance: Any, schema: dict[str, Any]
) -> ValidationResult:
for queue_type, queue_type_validator in self._is_fifo_queue(
validator=validator,
instance=instance,
):
queue_type_validator = queue_type_validator.evolve(
context=queue_type_validator.context.evolve(
path=validator.context.path.evolve()
)
)
for target, target_validator in get_value_from_path(
queue_type_validator,
instance,
path=deque(["RedrivePolicy", "deadLetterTargetArn"]),
):
k, v = is_function(target)
if k != "Fn::GetAtt":
return
if target_validator.is_type(v, "string"):
v = v.split(".")
if len(v) < 1:
return
dest_queue = validator.cfn.template.get("Resources", {}).get(v[0], {})
if dest_queue.get("Type") != "AWS::SQS::Queue":
return
for dest_queue_type, _ in self._is_fifo_queue(
target_validator,
instance=dest_queue.get("Properties", {}),
):
if queue_type != dest_queue_type:
yield ValidationError(
(
f"Source queue type {queue_type!r} does not "
f"match destination queue type {dest_queue_type!r}"
),
rule=self,
path=target_validator.context.path.path,
)