A new AWS CloudFormation linter – cfn-python-lint

I introduce new AWS Cloudformation linter, cfn-python-lint. I hope you like it.
2018.07.02

この記事は公開されてから1年以上経過しています。情報が古い可能性がありますので、ご注意ください。

Introduction

Have you ever been using any linters for AWS CloudFormation templates? I have been using linters in my project because our team manages many templates every day.

But, you might think it's not necessary that you use those tools for templates which aren't as expressive as programming codes - It's too much.

In some cases, it can be correct. For example, because your project is small, you manage a few templates and you are the one who manages templates. But if your project and templates have grown, templates will be developed with others so that templates will be managed with Git, and developed through Pull Request based development flows like GitHub Flow. In this case, without linters, if your teammates ask you to review his/her templates, you will point out nitpicks over there (e.g., typos, value type definitions, project-specific conventions). It's not productive. Let the tool point out these issues so people should focus on more interesting problems.

From these kinds of reasons, I have tried many linters for months. But I haven't found the best suited for our project. For example, some tools don't support new resources recently introduced by AWS; the runtime is not Python so that installation on CI environment is a bit complicated.

Recently I found new one made by AWS, its name is cfn-python-lint. It seems good to me! Its runtime is Python and it's made by AWS!

So, I try to introduce this tool in this post.

Test Environment

  • Python: 3.6.5
  • cfn-python-lint: 0.3.2

What can cfn-python-lint do?

The README describe its functionality briefly so that I cite the sentence:

Validate CloudFormation yaml/json templates against the CloudFormation spec and additional checks. Includes checking valid values for resource properties and best practices.

It's worth noting that it has flexible functionalities:

But there is the note that you should be careful. This tool is still in its active developing stage so be careful when using it in your project. I quote the sentence about it:

This is an attempt to provide validation for CloudFormation templates properties and their values. For values things can get pretty complicated (mappings, joins, splits, conditions, and nesting those functions inside each other) so its a best effort to validate those values but the promise is to not fail if we can't understand or translate all the things that could be going on.

What is the difference between ValidateTemplate API?

AWS CloudFormation has ValidateTemplate API, which validates templates, as you can see. It can be used with aws cloudformation validate-template command in AWS CLI; however, its design is, at least currently, so simple that it can detect syntax errors only. This is the most prominent difference with cfn-python-lint.

I use both in our project for now to expect stricter checking (but it might be too much).

How to use

Anyway, let's get started. I introduce its basic usage, so if you want more advanced uses, please follow documents.

Installation is very easy with pip.

# install
$ pip install cfn-lint
# verify
$ cfn-lint --version
cfn-lint 0.3.2

Because it supports AWS Serverless Application Model, I use the below template to demonstrate its basic usage.

---
AWSTemplateFormatVersion: "2010-09-09"
Transform: AWS::Serverless-2016-10-31
Description: Test Template

Resources:
  TestFunc:
    Type: AWS::Serverless::Function
    Properties:
      FunctionName: test-func
      CodeUri: src/handlers/test_func
      Handler: index.handler
      Runtime: python3.6

At first, let's use it against the above template normally.

$ cfn-lint sam.yml

Nothing happened, that proves the template is correct. Next, change the template like below (typo), then use it again.

--- sam.yml     2018-06-30 16:45:17.000000000 +0900
+++ sam-invalid.yml     2018-06-30 16:45:15.000000000 +0900
@@ -10,4 +10,4 @@
         test-func
       CodeUri: src/handlers/test_func
       Handler: index.handler
-      Runtime: python3.6
+      runtime: python3.6
$ cfn-lint sam-invalid.yml
E0001 Resource with id [TestFunc] is invalid. property runtime not defined for resource of type AWS::Serverless::Function
sam-invalid.yml:1:1

Yes! It warned me about the error there is no such a property in AWS::Serverless::Function resource. By the way, ValidateTemplate API doesn't warn any error.

$ aws cloudformation validate-template --template-body file://sam-invalid.yml
{
    "Parameters": [],
    "Description": "Test Template"
}

Conclusion

I introduced cfn-python-lint to lint AWS CloudFormation templates. Its quality and flexibility, it's the best for the linter ever! I will continue to use it.

I hope this post is useful to you.