Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
72 changes: 72 additions & 0 deletions .amazonq/rules/base.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,72 @@
---
description: Amazon Q Rules Location
globs: .amazonq/rules/**/*.md
---
# Amazon Q Rules Location

Rules for placing and organizing Amazon Q markdown files in the repository.

<rule>
name: amazonq_rules_location
description: Standards for placing Amazon Q markdown files in the correct directory
filters:
# Match any .md files
- type: file_extension
pattern: "\.md$"
# Match file creation events
- type: event
pattern: "file_create"

actions:
- type: reject
conditions:
- pattern: "^(?!\\.amazonq\\/rules\\/.*\\.md$)"
message: "Amazon Q markdown files must be placed in the .amazonq/rules directory"

- type: suggest
message: |
When creating Amazon Q files:

1. Always place markdown files in PROJECT_ROOT/.amazonq/rules/:
```
.amazonq/rules/
├── your-rule.md
├── another-rule.md [[1]](https://docs.aws.amazon.com/amazonq/latest/api-reference/API_Rule.html)
└── ...
```

2. Follow the naming convention:
- Use kebab-case for filenames
- Always use .md extension
- Make names descriptive of the file's purpose

3. Directory structure:
```
PROJECT_ROOT/
├── .amazonq/
│ └── rules/
│ ├── your-rule.md
│ └── ...
└── ...
```

4. Never place markdown files:
- In the project root
- In subdirectories outside .amazonq/rules
- In any other location

examples:
- input: |
# Bad: File in wrong location
rules/my-rule.md
my-rule.md
.rules/my-rule.md

# Good: File in correct location
.amazonq/rules/my-rule.md
output: "Correctly placed Amazon Q markdown file"

metadata:
priority: high
version: 1.0
</rule>
85 changes: 85 additions & 0 deletions .amazonq/rules/schema-extension-creation.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,85 @@
---
description: Guidelines for creating cfn-lint schema extensions
globs: src/cfnlint/data/schemas/extensions/**/*.json
---
# Creating Schema Extensions for cfn-lint

<rule>
name: schema_extension_creation
description: Guidelines for creating and maintaining schema extensions for cfn-lint
filters:
- type: file_extension
pattern: "\.json$"
- type: path
pattern: "src/cfnlint/data/schemas/extensions/"

actions:
- type: suggest
message: |
When creating schema extensions for cfn-lint:

1. **Follow JSON Schema structure**:
- Use standard JSON Schema with `if/then` conditional validation
- Properly validate property types in the `if` clause
- Use `false` as a schema value to disallow properties
- Use descriptive file names that indicate what aspect is being validated

2. **Base extensions on AWS documentation**:
- Read the official AWS CloudFormation documentation thoroughly
- Focus on property constraints not covered by the base schema
- Validate relationships between properties (e.g., when X is Y, Z must be A)
- Document the source of the validation rule with comments or commit messages

3. **Organize extensions properly**:
- Place extensions in the correct resource type directory
- Create new directories for resource types if needed
- Follow the existing naming conventions

4. **Test your extensions**:
- Create test cases that should pass and fail
- Ensure the error messages are clear and helpful

examples:
- input: |
{
"if": {
"properties": {
"TargetType": {
"enum": ["lambda"]
}
}
},
"then": {
"properties": {
"Protocol": {
"enum": ["HTTP", "HTTPS"]
}
}
}
}
output: |
{
"if": {
"properties": {
"TargetType": {
"enum": ["lambda"]
},
"Protocol": {
"type": "string"
}
},
"required": ["TargetType"]
},
"then": {
"properties": {
"Protocol": false,
"Port": false,
"HealthCheckPath": false
}
}
}

metadata:
priority: high
version: 1.0
</rule>
Original file line number Diff line number Diff line change
@@ -0,0 +1,67 @@
{
"if": {
"properties": {
"Protocol": {
"type": "string"
}
},
"required": [
"Protocol"
]
},
"then": {
"allOf": [
{
"else": {
"properties": {
"Matcher": false,
"ProtocolVersion": false
}
},
"if": {
"properties": {
"Protocol": {
"enum": [
"HTTP",
"HTTPS"
]
}
},
"required": [
"Protocol"
]
}
},
{
"if": {
"properties": {
"Port": {
"type": [
"string",
"integer"
]
},
"Protocol": {
"enum": [
"GENEVE"
]
}
},
"required": [
"Protocol"
]
},
"then": {
"properties": {
"Port": {
"enum": [
6081,
"6081"
]
}
}
}
}
]
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
{
"if": {
"properties": {
"TargetType": {
"type": "string"
}
},
"required": [
"TargetType"
]
},
"then": {
"else": {
"required": [
"Port",
"Protocol",
"VpcId"
]
},
"if": {
"properties": {
"TargetType": {
"enum": [
"lambda"
]
}
},
"required": [
"TargetType"
]
},
"then": {
"properties": {
"HealthCheckPath": false,
"HealthCheckPort": false,
"HealthCheckProtocol": false,
"Matcher": false,
"Port": false,
"Protocol": false,
"ProtocolVersion": false
}
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
[
{
"op": "add",
"path": "/properties/HealthCheckProtocol/enum",
"value": [
"HTTP",
"HTTPS",
"TCP"
]
}
]
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
"""
Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
SPDX-License-Identifier: MIT-0
"""

from typing import Any

import cfnlint.data.schemas.extensions.aws_elasticloadbalancingv2_targetgroup
from cfnlint.jsonschema import ValidationResult, Validator
from cfnlint.rules.jsonschema.CfnLintJsonSchema import CfnLintJsonSchema, SchemaDetails


class TargetGroupProtocolRestrictions(CfnLintJsonSchema):
id = "E3683"
shortdesc = "Validate target group protocol property restrictions"
description = (
"When a TargetGroup protocol is HTTP/HTTPS or GENEVE "
"there are different restrictions on properties."
)
tags = ["resources"]

def __init__(self) -> None:
super().__init__(
keywords=[
"Resources/AWS::ElasticLoadBalancingV2::TargetGroup/Properties",
],
schema_details=SchemaDetails(
module=cfnlint.data.schemas.extensions.aws_elasticloadbalancingv2_targetgroup,
filename="protocol_restrictions.json",
),
all_matches=True,
)

def validate(
self, validator: Validator, keywords: Any, instance: Any, schema: dict[str, Any]
) -> ValidationResult:
for err in super().validate(validator, keywords, instance, schema):
if not err.schema:
err.message = (
f"Additional properties are not allowed ({err.path[0]!r} "
"was unexpected)"
)
err.validator = "additionalProperties"
yield err
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
"""
Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
SPDX-License-Identifier: MIT-0
"""

from typing import Any

import cfnlint.data.schemas.extensions.aws_elasticloadbalancingv2_targetgroup
from cfnlint.jsonschema import ValidationResult, Validator
from cfnlint.rules.jsonschema.CfnLintJsonSchema import CfnLintJsonSchema, SchemaDetails


class TargetGroupTargetTypeRestrictions(CfnLintJsonSchema):
id = "E3681"
shortdesc = "Validate target group target type property restrictions"
description = (
"When a TargetGroup target type is lambda or not "
"there are different restrictions on properties."
)
tags = ["resources"]

def __init__(self) -> None:
super().__init__(
keywords=[
"Resources/AWS::ElasticLoadBalancingV2::TargetGroup/Properties",
],
schema_details=SchemaDetails(
module=cfnlint.data.schemas.extensions.aws_elasticloadbalancingv2_targetgroup,
filename="targettype_restrictions.json",
),
all_matches=True,
)

def validate(
self, validator: Validator, keywords: Any, instance: Any, schema: dict[str, Any]
) -> ValidationResult:
for err in super().validate(validator, keywords, instance, schema):
if not err.schema:
err.message = (
f"Additional properties are not allowed ({err.path[0]!r} "
"was unexpected)"
)
err.validator = "additionalProperties"
yield err
Loading
Loading