Skip to content

Commit dbdff60

Browse files
committed
feat: Add --extra-lint-rules option for flexible linting rules support
- Mark existing --serverless-rules option as deprecated - Add more flexible --extra-lint-rules option - Implement support for comma-separated multiple rule modules - Design to work regardless of installation environment - Update documentation and schema accordingly
1 parent ae6b24c commit dbdff60

File tree

4 files changed

+309
-47
lines changed

4 files changed

+309
-47
lines changed

docs/extra-lint-rules.md

Lines changed: 55 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,55 @@
1+
# SAM CLI 추가 Lint 규칙 사용 가이드
2+
3+
AWS SAM CLI의 `validate` 명령어는 템플릿 검증을 위해 [cfn-lint](https://github.com/aws-cloudformation/cfn-lint)를 사용합니다.
4+
이제 SAM CLI는 `--extra-lint-rules` 옵션을 통해 추가 lint 규칙을 지원합니다.
5+
6+
## 사용 방법
7+
8+
```bash
9+
sam validate --lint --extra-lint-rules="cfn_lint_serverless.rules"
10+
```
11+
12+
## 인스톨러로 SAM CLI 설치 시 고려사항
13+
14+
SAM CLI를 인스톨러(설치 프로그램)로 설치한 경우, SAM CLI는 자체 Python 환경을 사용합니다. 이 경우 추가 규칙 모듈이 해당 환경에 설치되어 있어야 합니다. 이 때 두 가지 접근 방식이 있습니다:
15+
16+
1. **인스톨러 Python 환경에 패키지 설치**: 인스톨러의 Python 환경에 필요한 패키지를 설치합니다.
17+
2. **모듈 경로를 전체 경로로 지정**: 사용자 환경에 설치된 패키지의 전체 경로를 지정합니다.
18+
19+
## 사용 예제
20+
21+
### 서버리스 규칙 사용 (cfn-lint-serverless)
22+
23+
```bash
24+
# 먼저 패키지 설치
25+
pip install cfn-lint-serverless
26+
27+
# SAM 템플릿 검증 실행
28+
sam validate --lint --extra-lint-rules="cfn_lint_serverless.rules"
29+
```
30+
31+
### 여러 규칙 모듈 사용
32+
33+
#### 방법 1: 콤마(,)로 구분하여 지정
34+
35+
여러 규칙 모듈을 콤마(,)로 구분하여 한 번의 옵션으로 지정할 수 있습니다:
36+
37+
```bash
38+
sam validate --lint --extra-lint-rules="module1.rules,module2.rules,module3.rules"
39+
```
40+
41+
각 모듈은 자동으로 분리되어 cfn-lint에 전달됩니다.
42+
43+
#### 방법 2: 옵션을 여러 번 사용
44+
45+
`--extra-lint-rules` 옵션을 여러 번 사용하여 여러 규칙 모듈을 지정할 수도 있습니다:
46+
47+
```bash
48+
sam validate --lint --extra-lint-rules="module1.rules" --extra-lint-rules="module2.rules"
49+
```
50+
51+
## 참고사항
52+
53+
* 과거에 사용하던 `--serverless-rules` 옵션은 deprecated 되었습니다.
54+
* 새로운 `--extra-lint-rules` 옵션을 사용하는 것이 좋습니다.
55+
* 인스톨러로 SAM CLI를 설치한 경우 추가 규칙이 작동하지 않으면 인스톨러의 Python 환경에 패키지가 설치되어 있는지 확인하세요.

samcli/commands/validate/validate.py

Lines changed: 89 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -60,24 +60,40 @@ class SamTemplate:
6060
@click.option(
6161
"--serverless-rules",
6262
is_flag=True,
63-
help="Enable Serverless Rules for linting validation. "
63+
help="[DEPRECATED] Enable Serverless Rules for linting validation. "
6464
"Requires the cfn-lint-serverless package to be installed. "
65+
"Use --extra-lint-rules=\"cfn_lint_serverless.rules\" instead. "
6566
"For more information, see: https://github.com/awslabs/serverless-rules",
6667
)
68+
@click.option(
69+
"--extra-lint-rules",
70+
help="Specify additional lint rules to be used with cfn-lint. "
71+
"Format: module.path (e.g. 'cfn_lint_serverless.rules')",
72+
default=None
73+
)
6774
@save_params_option
6875
@pass_context
6976
@track_command
7077
@check_newer_version
7178
@print_cmdline_args
7279
@unsupported_command_cdk(alternative_command="cdk doctor")
7380
@command_exception_handler
74-
def cli(ctx, template_file, config_file, config_env, lint, save_params, serverless_rules):
81+
def cli(ctx, template_file, config_file, config_env, lint, save_params, serverless_rules, extra_lint_rules):
7582
# All logic must be implemented in the ``do_cli`` method. This helps with easy unit testing
7683

77-
do_cli(ctx, template_file, lint, serverless_rules) # pragma: no cover
84+
# serverless_rules 옵션이 사용되면 경고 표시 및 extra_lint_rules로 변환
85+
if serverless_rules and not extra_lint_rules:
86+
click.secho(
87+
"Warning: --serverless-rules is deprecated. Please use --extra-lint-rules=\"cfn_lint_serverless.rules\" instead.",
88+
fg="yellow"
89+
)
90+
# 이전 옵션을 새 옵션으로 변환
91+
extra_lint_rules = "cfn_lint_serverless.rules"
92+
93+
do_cli(ctx, template_file, lint, serverless_rules, extra_lint_rules) # pragma: no cover
7894

7995

80-
def do_cli(ctx, template, lint, serverless_rules):
96+
def do_cli(ctx, template, lint, serverless_rules, extra_lint_rules=None):
8197
"""
8298
Implementation of the ``cli`` method, just separated out for unit testing purposes
8399
"""
@@ -91,7 +107,7 @@ def do_cli(ctx, template, lint, serverless_rules):
91107
sam_template = _read_sam_file(template)
92108

93109
if lint:
94-
_lint(ctx, sam_template.serialized, template, serverless_rules)
110+
_lint(ctx, sam_template.serialized, template, serverless_rules, extra_lint_rules)
95111
else:
96112
iam_client = boto3.client("iam")
97113
validator = SamTemplateValidator(
@@ -143,7 +159,7 @@ def _read_sam_file(template) -> SamTemplate:
143159
return SamTemplate(serialized=template_string, deserialized=sam_template)
144160

145161

146-
def _lint(ctx: Context, template: str, template_path: str, serverless_rules: bool) -> None:
162+
def _lint(ctx: Context, template: str, template_path: str, serverless_rules: bool = False, extra_lint_rules: str = None) -> None:
147163
"""
148164
Parses provided SAM template and maps errors from CloudFormation template back to SAM template.
149165
@@ -166,6 +182,10 @@ def _lint(ctx: Context, template: str, template_path: str, serverless_rules: boo
166182

167183
from cfnlint.api import ManualArgs, lint
168184
from cfnlint.runner import InvalidRegionException
185+
from samcli.lib.telemetry.event import EventTracker
186+
187+
# 디버그 정보 추가
188+
print(f"디버그 정보: serverless_rules 옵션 값 = {serverless_rules}")
169189

170190
cfn_lint_logger = logging.getLogger(CNT_LINT_LOGGER_NAME)
171191
cfn_lint_logger.propagate = False
@@ -179,29 +199,44 @@ def _lint(ctx: Context, template: str, template_path: str, serverless_rules: boo
179199
cfn_lint_logger.propagate = True
180200
cfn_lint_logger.setLevel(logging.DEBUG)
181201

182-
# Add Serverless Rules if enabled
202+
print(f"디버그 정보: linter_config 초기값 = {linter_config}")
203+
204+
# 두 옵션을 함께 처리하기 위한 변수 초기화
205+
rules_to_append = []
206+
207+
# 이전 serverless_rules 옵션 지원 (deprecated)
183208
if serverless_rules:
184-
try:
185-
# Track usage of Serverless Rules
186-
EventTracker.track_event("UsedFeature", "ServerlessRules")
209+
print("디버그 정보: serverless_rules 옵션이 활성화되었습니다.")
210+
# Track usage of Serverless Rules
211+
EventTracker.track_event("UsedFeature", "ServerlessRules")
212+
213+
# Check if cfn-lint-serverless is installed
214+
import importlib.util
215+
serverless_spec = importlib.util.find_spec("cfn_lint_serverless")
216+
print(f"디버그 정보: cfn_lint_serverless 패키지 설치 여부 = {serverless_spec is not None}")
217+
218+
if serverless_spec is None:
219+
print("디버그 정보: cfn_lint_serverless 패키지가 설치되어 있지 않습니다.")
220+
click.secho(
221+
"Serverless Rules package (cfn-lint-serverless) is not installed. "
222+
"Please install it using: pip install cfn-lint-serverless",
223+
fg="red",
224+
)
225+
raise UserException(
226+
"Serverless Rules package (cfn-lint-serverless) is not installed. "
227+
"Please install it using: pip install cfn-lint-serverless"
228+
)
187229

188-
# Check if cfn-lint-serverless is installed
189-
import importlib.util
190-
if importlib.util.find_spec("cfn_lint_serverless") is None:
191-
click.secho(
192-
"Serverless Rules package (cfn-lint-serverless) is not installed. "
193-
"Please install it using: pip install cfn-lint-serverless",
194-
fg="red",
195-
)
196-
raise UserException(
197-
"Serverless Rules package (cfn-lint-serverless) is not installed. "
198-
"Please install it using: pip install cfn-lint-serverless"
199-
)
230+
try:
231+
# Try to import the package
232+
import cfn_lint_serverless
233+
print("디버그 정보: cfn_lint_serverless 패키지 임포트 성공")
200234

201-
# Add Serverless Rules to the linter config
202-
linter_config["append_rules"] = ["cfn_lint_serverless.rules"]
235+
# Serverless Rules를 규칙 목록에 추가
236+
rules_to_append.append("cfn_lint_serverless.rules")
203237
click.secho("Serverless Rules enabled for linting", fg="green")
204-
except ImportError:
238+
except ImportError as e:
239+
print(f"디버그 정보: cfn_lint_serverless 임포트 오류 = {e}")
205240
click.secho(
206241
"Serverless Rules package (cfn-lint-serverless) is not installed. "
207242
"Please install it using: pip install cfn-lint-serverless",
@@ -211,21 +246,50 @@ def _lint(ctx: Context, template: str, template_path: str, serverless_rules: boo
211246
"Serverless Rules package (cfn-lint-serverless) is not installed. "
212247
"Please install it using: pip install cfn-lint-serverless"
213248
)
249+
250+
# 새로운 extra_lint_rules 옵션 지원
251+
if extra_lint_rules:
252+
print(f"디버그 정보: extra_lint_rules 옵션이 활성화되었습니다. 값: {extra_lint_rules}")
253+
# Track usage of Extra Lint Rules
254+
EventTracker.track_event("UsedFeature", "ExtraLintRules")
255+
256+
# 콤마로 구분된 여러 규칙 모듈을 파싱
257+
modules = [module.strip() for module in extra_lint_rules.split(',') if module.strip()]
258+
print(f"디버그 정보: 파싱된 규칙 모듈 목록 = {modules}")
259+
260+
# 각 모듈을 규칙 목록에 추가
261+
rules_to_append.extend(modules)
262+
click.secho(f"Extra lint rules enabled: {extra_lint_rules}", fg="green")
263+
264+
# 규칙이 있으면 linter_config에 추가
265+
if rules_to_append:
266+
print(f"디버그 정보: 추가할 규칙 목록 = {rules_to_append}")
267+
linter_config["append_rules"] = rules_to_append
268+
print(f"디버그 정보: linter_config 업데이트 = {linter_config}")
214269

215270
config = ManualArgs(**linter_config)
271+
print(f"디버그 정보: config 생성 완료")
216272

217273
try:
274+
print(f"디버그 정보: lint 함수 호출 시작")
218275
matches = lint(template, config=config)
276+
print(f"디버그 정보: lint 함수 호출 완료, matches = {matches}")
219277
except InvalidRegionException as ex:
278+
print(f"디버그 정보: InvalidRegionException 발생 = {ex}")
220279
raise UserException(
221280
f"AWS Region was not found. Please configure your region through the --region option.\n{ex}",
222281
wrapped_from=ex.__class__.__name__,
223282
) from ex
283+
except Exception as e:
284+
print(f"디버그 정보: 예외 발생 = {e}")
285+
raise
224286

225287
if not matches:
288+
print(f"디버그 정보: 템플릿 검증 성공")
226289
click.secho("{} is a valid SAM Template".format(template_path), fg="green")
227290
return
228291

292+
print(f"디버그 정보: 템플릿 검증 실패, matches = {matches}")
229293
click.secho(matches)
230294

231295
raise LinterRuleMatchedException("Linting failed. At least one linting rule was matched to the provided template.")

schema/samcli.json

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -196,7 +196,7 @@
196196
"properties": {
197197
"parameters": {
198198
"title": "Parameters for the validate command",
199-
"description": "Available parameters for the validate command:\n* template_file:\nAWS SAM template file.\n* profile:\nSelect a specific profile from your credential file to get AWS credentials.\n* region:\nSet the AWS Region of the service. (e.g. us-east-1)\n* beta_features:\nEnable/Disable beta features.\n* debug:\nTurn on debug logging to print debug message generated by AWS SAM CLI and display timestamps.\n* lint:\nRun linting validation on template through cfn-lint. Create a cfnlintrc config file to specify additional parameters. For more information, see: https://github.com/aws-cloudformation/cfn-lint\n* serverless_rules:\nEnable Serverless Rules for linting validation. Requires the cfn-lint-serverless package to be installed. For more information, see: https://github.com/awslabs/serverless-rules\n* save_params:\nSave the parameters provided via the command line to the configuration file.",
199+
"description": "Available parameters for the validate command:\n* template_file:\nAWS SAM template file.\n* profile:\nSelect a specific profile from your credential file to get AWS credentials.\n* region:\nSet the AWS Region of the service. (e.g. us-east-1)\n* beta_features:\nEnable/Disable beta features.\n* debug:\nTurn on debug logging to print debug message generated by AWS SAM CLI and display timestamps.\n* lint:\nRun linting validation on template through cfn-lint. Create a cfnlintrc config file to specify additional parameters. For more information, see: https://github.com/aws-cloudformation/cfn-lint\n* serverless_rules:\n[DEPRECATED] Enable Serverless Rules for linting validation. Use --extra-lint-rules=\"cfn_lint_serverless.rules\" instead. Requires the cfn-lint-serverless package to be installed. For more information, see: https://github.com/awslabs/serverless-rules\n* extra_lint_rules:\nSpecify additional lint rules to be used with cfn-lint. Format: module.path (e.g. 'cfn_lint_serverless.rules')\n* save_params:\nSave the parameters provided via the command line to the configuration file.",
200200
"type": "object",
201201
"properties": {
202202
"template_file": {
@@ -233,7 +233,12 @@
233233
"serverless_rules": {
234234
"title": "serverless_rules",
235235
"type": "boolean",
236-
"description": "Enable Serverless Rules for linting validation. Requires the cfn-lint-serverless package to be installed. For more information, see: https://github.com/awslabs/serverless-rules"
236+
"description": "[DEPRECATED] Enable Serverless Rules for linting validation. Use --extra-lint-rules=\"cfn_lint_serverless.rules\" instead. Requires the cfn-lint-serverless package to be installed. For more information, see: https://github.com/awslabs/serverless-rules"
237+
},
238+
"extra_lint_rules": {
239+
"title": "extra_lint_rules",
240+
"type": "string",
241+
"description": "Specify additional lint rules to be used with cfn-lint. Format: module.path (e.g. 'cfn_lint_serverless.rules')"
237242
},
238243
"save_params": {
239244
"title": "save_params",

0 commit comments

Comments
 (0)