cfn-check 0.1.1__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.

Potentially problematic release.


This version of cfn-check might be problematic. Click here for more details.

Files changed (35) hide show
  1. cfn_check-0.1.1/LICENSE +21 -0
  2. cfn_check-0.1.1/PKG-INFO +247 -0
  3. cfn_check-0.1.1/README.md +206 -0
  4. cfn_check-0.1.1/cfn_check/__init__.py +2 -0
  5. cfn_check-0.1.1/cfn_check/cli/__init__.py +0 -0
  6. cfn_check-0.1.1/cfn_check/cli/root.py +72 -0
  7. cfn_check-0.1.1/cfn_check/cli/utils/__init__.py +0 -0
  8. cfn_check-0.1.1/cfn_check/cli/utils/attributes.py +12 -0
  9. cfn_check-0.1.1/cfn_check/cli/utils/files.py +68 -0
  10. cfn_check-0.1.1/cfn_check/cli/validate.py +81 -0
  11. cfn_check-0.1.1/cfn_check/evaluation/__init__.py +0 -0
  12. cfn_check-0.1.1/cfn_check/evaluation/check.py +20 -0
  13. cfn_check-0.1.1/cfn_check/evaluation/errors.py +33 -0
  14. cfn_check-0.1.1/cfn_check/evaluation/search.py +137 -0
  15. cfn_check-0.1.1/cfn_check/evaluation/validate.py +51 -0
  16. cfn_check-0.1.1/cfn_check/loader/__init__.py +0 -0
  17. cfn_check-0.1.1/cfn_check/loader/loader.py +21 -0
  18. cfn_check-0.1.1/cfn_check/logging/__init__.py +0 -0
  19. cfn_check-0.1.1/cfn_check/logging/models.py +20 -0
  20. cfn_check-0.1.1/cfn_check/rules/__init__.py +0 -0
  21. cfn_check-0.1.1/cfn_check/rules/rule.py +25 -0
  22. cfn_check-0.1.1/cfn_check/rules/rules.py +2 -0
  23. cfn_check-0.1.1/cfn_check/shared/__init__.py +0 -0
  24. cfn_check-0.1.1/cfn_check/shared/types.py +17 -0
  25. cfn_check-0.1.1/cfn_check/validation/__init__.py +0 -0
  26. cfn_check-0.1.1/cfn_check/validation/validator.py +47 -0
  27. cfn_check-0.1.1/cfn_check.egg-info/PKG-INFO +247 -0
  28. cfn_check-0.1.1/cfn_check.egg-info/SOURCES.txt +33 -0
  29. cfn_check-0.1.1/cfn_check.egg-info/dependency_links.txt +1 -0
  30. cfn_check-0.1.1/cfn_check.egg-info/entry_points.txt +2 -0
  31. cfn_check-0.1.1/cfn_check.egg-info/requires.txt +4 -0
  32. cfn_check-0.1.1/cfn_check.egg-info/top_level.txt +3 -0
  33. cfn_check-0.1.1/example/rules.py +12 -0
  34. cfn_check-0.1.1/pyproject.toml +47 -0
  35. cfn_check-0.1.1/setup.cfg +4 -0
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2025 Ada Lündhé
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
@@ -0,0 +1,247 @@
1
+ Metadata-Version: 2.4
2
+ Name: cfn-check
3
+ Version: 0.1.1
4
+ Summary: Validate Cloud Formation
5
+ Author-email: Ada Lundhe <adalundhe@lundhe.audio>
6
+ License: MIT License
7
+
8
+ Copyright (c) 2025 Ada Lündhé
9
+
10
+ Permission is hereby granted, free of charge, to any person obtaining a copy
11
+ of this software and associated documentation files (the "Software"), to deal
12
+ in the Software without restriction, including without limitation the rights
13
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
14
+ copies of the Software, and to permit persons to whom the Software is
15
+ furnished to do so, subject to the following conditions:
16
+
17
+ The above copyright notice and this permission notice shall be included in all
18
+ copies or substantial portions of the Software.
19
+
20
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
21
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
22
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
23
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
24
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
25
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
26
+ SOFTWARE.
27
+
28
+ Project-URL: Homepage, https://github.com/adalundhe/cfn-check
29
+ Keywords: cloud-formation,testing,aws,cli
30
+ Classifier: Programming Language :: Python :: 3.12
31
+ Classifier: Programming Language :: Python :: 3.13
32
+ Classifier: Operating System :: OS Independent
33
+ Requires-Python: >=3.12
34
+ Description-Content-Type: text/markdown
35
+ License-File: LICENSE
36
+ Requires-Dist: pydantic
37
+ Requires-Dist: pyyaml
38
+ Requires-Dist: hyperlight-cocoa
39
+ Requires-Dist: async-logging
40
+ Dynamic: license-file
41
+
42
+ # <b>CFN Check</b>
43
+ <b>A tool for checking CloudFormation</b>
44
+
45
+ [![PyPI version](https://img.shields.io/pypi/v/cfn-check?color=blue)](https://pypi.org/project/cfn-check/)
46
+ [![License](https://img.shields.io/github/license/adalundhe/cfn-check)](https://github.com/adalundhe/cfn-check/blob/main/LICENSE)
47
+ [![Contributor Covenant](https://img.shields.io/badge/Contributor%20Covenant-2.1-4baaaa.svg)](https://github.com/adalundhe/cfn-check/blob/main/CODE_OF_CONDUCT.md)
48
+ [![PyPI - Python Version](https://img.shields.io/pypi/pyversions/cfn-check?color=red)](https://pypi.org/project/cfn-check/)
49
+
50
+
51
+ | Package | Cocoa |
52
+ | ----------- | ----------- |
53
+ | Version | 0.1.0 |
54
+ | Download | https://pypi.org/project/cfn-check/ |
55
+ | Source | https://github.com/adalundhe/cfn-check |
56
+ | Keywords | cloud-formation, testing, aws, cli |
57
+
58
+
59
+ CFN-Check is a small, fast, friendly tool for validating AWS CloudFormation YAML templates. It is code-driven, with
60
+ rules written as simple, `Rule` decorator wrapped python class methods for `Rules`-inheriting classes.
61
+
62
+ <br/>
63
+
64
+ # Why CFN-Check?
65
+
66
+ AWS has its own tools for validating Cloud Formation - `cfn-lint` and `cfn-guard`. `cfn-check` aims to solve
67
+ problems inherint to `cfn-lint` more than `cfn-guard`, primarily:
68
+
69
+ - Confusing, unclear syntax around rules configuration
70
+ - Inability to parse non-resource wildcards
71
+ - Inability to validate non-resource template data
72
+ - Inabillity to use structured models to validate input
73
+
74
+ In comparison to `cfn-guard`, `cfn-check` is pure Python, thus
75
+ avoiding YADSL (Yet Another DSL) headaches. It also proves
76
+ significantly more configurable/modular/hackable as a result.
77
+
78
+ CFN-Check uses a combination of simple depth-first-search tree
79
+ parsing, friendly `cfn-lint` like query syntax, `Pydantic` models,
80
+ and `pytest`-like assert-driven checks to make validating your
81
+ Cloud Formation easy while offering both CLI and Python API interfaces.
82
+
83
+ <br/>
84
+
85
+ # Getting Started
86
+
87
+ `cfn-check` requires:
88
+
89
+ - `Python 3.12`
90
+ - Any number of valid CloudFormation templates or a path to said templates.
91
+ - A `.py` file containing at least one `Rules` class with at least one valid `@Rule()` decorated method
92
+
93
+ To get started (we recommend using `uv`), run:
94
+
95
+ ```bash
96
+ uv venv
97
+ source .venv/bin/activate
98
+
99
+ uv pip install cfn-check
100
+
101
+ touch rules.py
102
+ touch template.yaml
103
+ ```
104
+
105
+ Next open the `rules.py` file and create a basic Python class
106
+ as below.
107
+
108
+ ```python
109
+ from cfn_check import Rules, Rule
110
+
111
+
112
+ class ValidateResourceType(Rules):
113
+
114
+ @Rule(
115
+ "Resources::*::Type",
116
+ "It checks Resource::Type is correctly definined",
117
+ )
118
+ def validate_test(self, value: str):
119
+ assert value is not None, '❌ Resource Type not defined'
120
+ assert isinstance(value, str), '❌ Resource Type not a string'
121
+ ```
122
+
123
+ This provides us a basic rule set that validates that the `Type` field of our CloudFormation template(s) exists and is the correct data type.
124
+
125
+ > [!NOTE]
126
+ > Don't worry about adding an `__init__()` method to this class!
127
+
128
+ Next open the `template.yaml` file and paste the following CloudFormation:
129
+
130
+ ```yaml
131
+ AWSTemplateFormatVersion: '2010-09-09'
132
+ Parameters:
133
+ ExistingSecurityGroups:
134
+ Type: List<AWS::EC2::SecurityGroup::Id>
135
+ ExistingVPC:
136
+ Type: AWS::EC2::VPC::Id
137
+ Description: The VPC ID that includes the security groups in the ExistingSecurityGroups parameter.
138
+ InstanceType:
139
+ Type: String
140
+ Default: t2.micro
141
+ AllowedValues:
142
+ - t2.micro
143
+ - m1.small
144
+ Mappings:
145
+ AWSInstanceType2Arch:
146
+ t2.micro:
147
+ Arch: HVM64
148
+ m1.small:
149
+ Arch: HVM64
150
+ AWSRegionArch2AMI:
151
+ us-east-1:
152
+ HVM64: ami-0ff8a91507f77f867
153
+ HVMG2: ami-0a584ac55a7631c0c
154
+ Resources:
155
+ SecurityGroup:
156
+ Type: AWS::EC2::SecurityGroup
157
+ Properties:
158
+ GroupDescription: Allow HTTP traffic to the host
159
+ VpcId: !Ref ExistingVPC
160
+ SecurityGroupIngress:
161
+ - IpProtocol: tcp
162
+ FromPort: 80
163
+ ToPort: 80
164
+ CidrIp: 0.0.0.0/0
165
+ SecurityGroupEgress:
166
+ - IpProtocol: tcp
167
+ FromPort: 80
168
+ ToPort: 80
169
+ CidrIp: 0.0.0.0/0
170
+ AllSecurityGroups:
171
+ Type: Custom::Split
172
+ Properties:
173
+ ServiceToken: !GetAtt AppendItemToListFunction.Arn
174
+ List: !Ref ExistingSecurityGroups
175
+ AppendedItem: !Ref SecurityGroup
176
+ AppendItemToListFunction:
177
+ Type: AWS::Lambda::Function
178
+ Properties:
179
+ Handler: index.handler
180
+ Role: !GetAtt LambdaExecutionRole.Arn
181
+ Code:
182
+ ZipFile: !Join
183
+ - ''
184
+ - - var response = require('cfn-response');
185
+ - exports.handler = function(event, context) {
186
+ - ' var responseData = {Value: event.ResourceProperties.List};'
187
+ - ' responseData.Value.push(event.ResourceProperties.AppendedItem);'
188
+ - ' response.send(event, context, response.SUCCESS, responseData);'
189
+ - '};'
190
+ Runtime: nodejs20.x
191
+ MyEC2Instance:
192
+ Type: AWS::EC2::Instance
193
+ Properties:
194
+ ImageId: !FindInMap
195
+ - AWSRegionArch2AMI
196
+ - !Ref AWS::Region
197
+ - !FindInMap
198
+ - AWSInstanceType2Arch
199
+ - !Ref InstanceType
200
+ - Arch
201
+ SecurityGroupIds: !GetAtt AllSecurityGroups.Value
202
+ InstanceType: !Ref InstanceType
203
+ LambdaExecutionRole:
204
+ Type: AWS::IAM::Role
205
+ Properties:
206
+ AssumeRolePolicyDocument:
207
+ Version: '2012-10-17'
208
+ Statement:
209
+ - Effect: Allow
210
+ Principal:
211
+ Service:
212
+ - lambda.amazonaws.com
213
+ Action:
214
+ - sts:AssumeRole
215
+ Path: /
216
+ Policies:
217
+ - PolicyName: root
218
+ PolicyDocument:
219
+ Version: '2012-10-17'
220
+ Statement:
221
+ - Effect: Allow
222
+ Action:
223
+ - logs:*
224
+ Resource: arn:aws:logs:*:*:*
225
+ Outputs:
226
+ AllSecurityGroups:
227
+ Description: Security Groups that are associated with the EC2 instance
228
+ Value: !Join
229
+ - ', '
230
+ - !GetAtt AllSecurityGroups.Value
231
+ ```
232
+
233
+ This represents a basic configuration for an AWS Lambda function.
234
+
235
+ Finally, run:
236
+
237
+ ```bash
238
+ cfn-lint validate -r rules.py template.yaml
239
+ ```
240
+
241
+ which outputs:
242
+
243
+ ```
244
+ 2025-09-17T01:46:41.542078+00:00 - INFO - 19783474 - /Users/adalundhe/Documents/Duckbill/cfn-check/cfn_check/cli/validate.py:validate.80 - ✅ 1 validations met for 1 templates
245
+ ```
246
+
247
+ Congrats! You've just made the cloud a bit better place!
@@ -0,0 +1,206 @@
1
+ # <b>CFN Check</b>
2
+ <b>A tool for checking CloudFormation</b>
3
+
4
+ [![PyPI version](https://img.shields.io/pypi/v/cfn-check?color=blue)](https://pypi.org/project/cfn-check/)
5
+ [![License](https://img.shields.io/github/license/adalundhe/cfn-check)](https://github.com/adalundhe/cfn-check/blob/main/LICENSE)
6
+ [![Contributor Covenant](https://img.shields.io/badge/Contributor%20Covenant-2.1-4baaaa.svg)](https://github.com/adalundhe/cfn-check/blob/main/CODE_OF_CONDUCT.md)
7
+ [![PyPI - Python Version](https://img.shields.io/pypi/pyversions/cfn-check?color=red)](https://pypi.org/project/cfn-check/)
8
+
9
+
10
+ | Package | Cocoa |
11
+ | ----------- | ----------- |
12
+ | Version | 0.1.0 |
13
+ | Download | https://pypi.org/project/cfn-check/ |
14
+ | Source | https://github.com/adalundhe/cfn-check |
15
+ | Keywords | cloud-formation, testing, aws, cli |
16
+
17
+
18
+ CFN-Check is a small, fast, friendly tool for validating AWS CloudFormation YAML templates. It is code-driven, with
19
+ rules written as simple, `Rule` decorator wrapped python class methods for `Rules`-inheriting classes.
20
+
21
+ <br/>
22
+
23
+ # Why CFN-Check?
24
+
25
+ AWS has its own tools for validating Cloud Formation - `cfn-lint` and `cfn-guard`. `cfn-check` aims to solve
26
+ problems inherint to `cfn-lint` more than `cfn-guard`, primarily:
27
+
28
+ - Confusing, unclear syntax around rules configuration
29
+ - Inability to parse non-resource wildcards
30
+ - Inability to validate non-resource template data
31
+ - Inabillity to use structured models to validate input
32
+
33
+ In comparison to `cfn-guard`, `cfn-check` is pure Python, thus
34
+ avoiding YADSL (Yet Another DSL) headaches. It also proves
35
+ significantly more configurable/modular/hackable as a result.
36
+
37
+ CFN-Check uses a combination of simple depth-first-search tree
38
+ parsing, friendly `cfn-lint` like query syntax, `Pydantic` models,
39
+ and `pytest`-like assert-driven checks to make validating your
40
+ Cloud Formation easy while offering both CLI and Python API interfaces.
41
+
42
+ <br/>
43
+
44
+ # Getting Started
45
+
46
+ `cfn-check` requires:
47
+
48
+ - `Python 3.12`
49
+ - Any number of valid CloudFormation templates or a path to said templates.
50
+ - A `.py` file containing at least one `Rules` class with at least one valid `@Rule()` decorated method
51
+
52
+ To get started (we recommend using `uv`), run:
53
+
54
+ ```bash
55
+ uv venv
56
+ source .venv/bin/activate
57
+
58
+ uv pip install cfn-check
59
+
60
+ touch rules.py
61
+ touch template.yaml
62
+ ```
63
+
64
+ Next open the `rules.py` file and create a basic Python class
65
+ as below.
66
+
67
+ ```python
68
+ from cfn_check import Rules, Rule
69
+
70
+
71
+ class ValidateResourceType(Rules):
72
+
73
+ @Rule(
74
+ "Resources::*::Type",
75
+ "It checks Resource::Type is correctly definined",
76
+ )
77
+ def validate_test(self, value: str):
78
+ assert value is not None, '❌ Resource Type not defined'
79
+ assert isinstance(value, str), '❌ Resource Type not a string'
80
+ ```
81
+
82
+ This provides us a basic rule set that validates that the `Type` field of our CloudFormation template(s) exists and is the correct data type.
83
+
84
+ > [!NOTE]
85
+ > Don't worry about adding an `__init__()` method to this class!
86
+
87
+ Next open the `template.yaml` file and paste the following CloudFormation:
88
+
89
+ ```yaml
90
+ AWSTemplateFormatVersion: '2010-09-09'
91
+ Parameters:
92
+ ExistingSecurityGroups:
93
+ Type: List<AWS::EC2::SecurityGroup::Id>
94
+ ExistingVPC:
95
+ Type: AWS::EC2::VPC::Id
96
+ Description: The VPC ID that includes the security groups in the ExistingSecurityGroups parameter.
97
+ InstanceType:
98
+ Type: String
99
+ Default: t2.micro
100
+ AllowedValues:
101
+ - t2.micro
102
+ - m1.small
103
+ Mappings:
104
+ AWSInstanceType2Arch:
105
+ t2.micro:
106
+ Arch: HVM64
107
+ m1.small:
108
+ Arch: HVM64
109
+ AWSRegionArch2AMI:
110
+ us-east-1:
111
+ HVM64: ami-0ff8a91507f77f867
112
+ HVMG2: ami-0a584ac55a7631c0c
113
+ Resources:
114
+ SecurityGroup:
115
+ Type: AWS::EC2::SecurityGroup
116
+ Properties:
117
+ GroupDescription: Allow HTTP traffic to the host
118
+ VpcId: !Ref ExistingVPC
119
+ SecurityGroupIngress:
120
+ - IpProtocol: tcp
121
+ FromPort: 80
122
+ ToPort: 80
123
+ CidrIp: 0.0.0.0/0
124
+ SecurityGroupEgress:
125
+ - IpProtocol: tcp
126
+ FromPort: 80
127
+ ToPort: 80
128
+ CidrIp: 0.0.0.0/0
129
+ AllSecurityGroups:
130
+ Type: Custom::Split
131
+ Properties:
132
+ ServiceToken: !GetAtt AppendItemToListFunction.Arn
133
+ List: !Ref ExistingSecurityGroups
134
+ AppendedItem: !Ref SecurityGroup
135
+ AppendItemToListFunction:
136
+ Type: AWS::Lambda::Function
137
+ Properties:
138
+ Handler: index.handler
139
+ Role: !GetAtt LambdaExecutionRole.Arn
140
+ Code:
141
+ ZipFile: !Join
142
+ - ''
143
+ - - var response = require('cfn-response');
144
+ - exports.handler = function(event, context) {
145
+ - ' var responseData = {Value: event.ResourceProperties.List};'
146
+ - ' responseData.Value.push(event.ResourceProperties.AppendedItem);'
147
+ - ' response.send(event, context, response.SUCCESS, responseData);'
148
+ - '};'
149
+ Runtime: nodejs20.x
150
+ MyEC2Instance:
151
+ Type: AWS::EC2::Instance
152
+ Properties:
153
+ ImageId: !FindInMap
154
+ - AWSRegionArch2AMI
155
+ - !Ref AWS::Region
156
+ - !FindInMap
157
+ - AWSInstanceType2Arch
158
+ - !Ref InstanceType
159
+ - Arch
160
+ SecurityGroupIds: !GetAtt AllSecurityGroups.Value
161
+ InstanceType: !Ref InstanceType
162
+ LambdaExecutionRole:
163
+ Type: AWS::IAM::Role
164
+ Properties:
165
+ AssumeRolePolicyDocument:
166
+ Version: '2012-10-17'
167
+ Statement:
168
+ - Effect: Allow
169
+ Principal:
170
+ Service:
171
+ - lambda.amazonaws.com
172
+ Action:
173
+ - sts:AssumeRole
174
+ Path: /
175
+ Policies:
176
+ - PolicyName: root
177
+ PolicyDocument:
178
+ Version: '2012-10-17'
179
+ Statement:
180
+ - Effect: Allow
181
+ Action:
182
+ - logs:*
183
+ Resource: arn:aws:logs:*:*:*
184
+ Outputs:
185
+ AllSecurityGroups:
186
+ Description: Security Groups that are associated with the EC2 instance
187
+ Value: !Join
188
+ - ', '
189
+ - !GetAtt AllSecurityGroups.Value
190
+ ```
191
+
192
+ This represents a basic configuration for an AWS Lambda function.
193
+
194
+ Finally, run:
195
+
196
+ ```bash
197
+ cfn-lint validate -r rules.py template.yaml
198
+ ```
199
+
200
+ which outputs:
201
+
202
+ ```
203
+ 2025-09-17T01:46:41.542078+00:00 - INFO - 19783474 - /Users/adalundhe/Documents/Duckbill/cfn-check/cfn_check/cli/validate.py:validate.80 - ✅ 1 validations met for 1 templates
204
+ ```
205
+
206
+ Congrats! You've just made the cloud a bit better place!
@@ -0,0 +1,2 @@
1
+ from .rules.rules import Rules as Rules
2
+ from .rules.rule import Rule as Rule
File without changes
@@ -0,0 +1,72 @@
1
+ import asyncio
2
+ import sys
3
+
4
+ from cocoa.cli import CLI, CLIStyle
5
+ from cocoa.ui.config.mode import TerminalMode
6
+ from cocoa.ui.components.terminal import Section, SectionConfig
7
+ from cocoa.ui.components.header import Header, HeaderConfig
8
+ from cocoa.ui.components.terminal import Terminal, EngineConfig
9
+
10
+ from .validate import validate
11
+
12
+ async def create_header(
13
+ terminal_mode: TerminalMode = "full",
14
+ ):
15
+
16
+ cfn_check_terminal_mode = "extended"
17
+ if terminal_mode == "ci":
18
+ cfn_check_terminal_mode = "compatability"
19
+
20
+ header = Section(
21
+ SectionConfig(height="xx-small", width="large"),
22
+ components=[
23
+ Header(
24
+ "header",
25
+ HeaderConfig(
26
+ header_text="cfn-check",
27
+ color="indian_red_3",
28
+ attributes=["bold"],
29
+ terminal_mode=cfn_check_terminal_mode,
30
+ font='cyberpunk'
31
+ ),
32
+ ),
33
+ ],
34
+ )
35
+
36
+ terminal = Terminal(
37
+ [
38
+ header,
39
+ ],
40
+ config=EngineConfig(
41
+ max_height=40,
42
+ max_width=120
43
+ )
44
+ )
45
+
46
+ return await terminal.render_once()
47
+
48
+
49
+
50
+ @CLI.root(
51
+ validate,
52
+ global_styles=CLIStyle(
53
+ header=create_header,
54
+ flag_description_color="white",
55
+ error_color="indian_red_3",
56
+ error_attributes=["italic"],
57
+ flag_color="indian_red_3",
58
+ text_color="slate_blue_2",
59
+ subcommand_color="slate_blue_2",
60
+ indentation=5,
61
+ terminal_mode="extended",
62
+ ),
63
+ )
64
+ async def cfn_check():
65
+ '''
66
+ Check and test CloudFormation
67
+ '''
68
+
69
+
70
+
71
+ def run():
72
+ asyncio.run(CLI.run(sys.argv[1:]))
File without changes
@@ -0,0 +1,12 @@
1
+ from cfn_check.rules.rules import Rules
2
+ from cfn_check.validation.validator import Validator
3
+
4
+
5
+ def bind(
6
+ rule_set: Rules,
7
+ validation: Validator
8
+ ):
9
+ validation.func = validation.func.__get__(rule_set, rule_set.__class__)
10
+ setattr(rule_set, validation.func.__name__, validation.func)
11
+
12
+ return validation
@@ -0,0 +1,68 @@
1
+
2
+ import asyncio
3
+ import os
4
+ import yaml
5
+ from cfn_check.loader.loader import (
6
+ Loader,
7
+ create_tag,
8
+ find_templates,
9
+ )
10
+ from cfn_check.shared.types import YamlObject, Data
11
+
12
+ def open_template(path: str) -> YamlObject | Exception:
13
+ try:
14
+ with open(path, 'r') as f:
15
+ return yaml.load(f, Loader=Loader)
16
+ except (Exception, ) as e:
17
+ raise e
18
+
19
+ def is_file(path: str) -> bool:
20
+ return os.path.isdir(path) is False
21
+
22
+
23
+ async def load_templates(
24
+ path: str,
25
+ tags: list[str],
26
+ file_pattern: str | None = None,
27
+ ):
28
+ loop = asyncio.get_event_loop()
29
+
30
+ if await loop.run_in_executor(
31
+ None,
32
+ is_file,
33
+ path,
34
+ ) or file_pattern is None:
35
+ template_filepaths = [
36
+ path,
37
+ ]
38
+
39
+ elif file_pattern:
40
+
41
+ template_filepaths = await loop.run_in_executor(
42
+ None,
43
+ find_templates,
44
+ path,
45
+ file_pattern,
46
+ )
47
+
48
+ assert len(template_filepaths) > 0 , '❌ No matching files found'
49
+
50
+ for tag in tags:
51
+ new_tag = await loop.run_in_executor(
52
+ None,
53
+ create_tag,
54
+ tag,
55
+ )
56
+
57
+ Loader.add_constructor(f'!{tag}', new_tag)
58
+
59
+
60
+ templates: list[Data] = await asyncio.gather(*[
61
+ loop.run_in_executor(
62
+ None,
63
+ open_template,
64
+ template_path,
65
+ ) for template_path in template_filepaths
66
+ ])
67
+
68
+ return templates