Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Support parsing multiple files #331

Merged

Conversation

kddejong
Copy link
Contributor

@kddejong kddejong commented Sep 7, 2018

Issue #, if available:

Description of changes:

  • Supports linting multiple files

By submitting this pull request, I confirm that you can use, modify, copy, and redistribute this contribution, under the terms of your choice.

@kddejong kddejong added the WIP work in progress -- DO NOT MERGE label Sep 7, 2018
@kddejong kddejong removed the WIP work in progress -- DO NOT MERGE label Sep 15, 2018
@kddejong
Copy link
Contributor Author

A few things may need to get done before merging this one.

  • Make sure there is no adverse affect to the people using cfn-lint as a module
  • Double check that the IDE plugins still work

@cmmeyer
Copy link
Contributor

cmmeyer commented Sep 17, 2018

I noticed you've removed the WIP tag from this PR -- is it ready for review and merge?

@kddejong
Copy link
Contributor Author

yea I think this is about ready. In the past there has a been a few argparse things that trip me up. I'm hoping I can get a few people to put their eyes on it to make sure I didn't miss anything.

@cmmeyer
Copy link
Contributor

cmmeyer commented Sep 19, 2018

@alexjurkiewicz and @adamchainz -- would either of you be willing to do a quick review/test of this PR to see if it helps with your multi-file use cases?

Copy link
Contributor

@cmmeyer cmmeyer left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I can only get this to work if I run it as:
cfn-lint new-temp.yaml with-private-subnets.json

I can't get it to parse multiple files using -template/-t. I tried:

cfn-lint -template new-temp.yaml -template with-private-subnets.json
cfn-lint -t new-temp.yaml -t with-private-subnets.json
cfn-lint -t new-temp.yaml,with-private-subnets.json

In all cases it only parses one file or fails outright. Does this only work with bare filenames?

@kddejong
Copy link
Contributor Author

It should work for both... I'll check in on this.

@kddejong kddejong force-pushed the Feature/LintMultipleFiles branch 3 times, most recently from 6f50ce4 to 5203584 Compare September 19, 2018 19:14
Copy link
Contributor

@cmmeyer cmmeyer left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ok, almost there. Now these all work:

cfn-lint -template new-temp.yaml with-private-subnets.json
cfn-lint -t new-temp.yaml,with-private-subnets.json
cfn-lint -t new-temp.yaml -t with-private-subnets.json
cfn-lint new-temp.yaml with-private-subnets.json

...but these fail:

cfn-lint -template new-temp.yaml -template with-private-subnets.json
cfn-lint new-temp.yaml,with-private-subnets.json


ps -- I have not tested with any other arguments (rules, whitelisting, etc.)

@adamchainz
Copy link
Contributor

@cmmeyer comma separated lists shouldn't really pass since commas are allowed in filenames, and there's already a way of passing multiple with space separation

@adamchainz
Copy link
Contributor

Takes my lint of 73 templates from 53 seconds to 4 seconds!

But one thing that might be worth documenting is using the -- separator, since e.g. --regions consumes multiple arguments, I have to do cfn-lint --regions us-east-1 -- cloudformation/*.yml to make it work. The error message is unclear that there is no template passed without the --.

@cmmeyer
Copy link
Contributor

cmmeyer commented Sep 20, 2018

It would be nice to print each filename in debug mode -- I got an exception when I pointed the linter at a random directory and it was hard to figure out which file caused the exception.

(For what it's worth, the exception was when we hit a binary file(.zip). I'll create a separate issue for that)

Traceback (most recent call last):
  File "/usr/local/bin/cfn-lint", line 11, in <module>
    load_entry_point('cfn-lint==0.7.2', 'console_scripts', 'cfn-lint')()
  File "/usr/local/lib/python3.6/site-packages/cfn_lint-0.7.2-py3.6.egg/cfnlint/__main__.py", line 30, in main
    (template, rules, template_matches) = cfnlint.core.get_template_rules(filename, args)
  File "/usr/local/lib/python3.6/site-packages/cfn_lint-0.7.2-py3.6.egg/cfnlint/core.py", line 245, in get_template_rules
    (template, matches) = cfnlint.decode.decode(filename, args.ignore_bad_template)
  File "/usr/local/lib/python3.6/site-packages/cfn_lint-0.7.2-py3.6.egg/cfnlint/decode/__init__.py", line 40, in decode
    template = cfnlint.decode.cfn_yaml.load(filename)
  File "/usr/local/lib/python3.6/site-packages/cfn_lint-0.7.2-py3.6.egg/cfnlint/decode/cfn_yaml.py", line 206, in load
    return loads(fp.read(), filename)
  File "/usr/local/lib/python3.6/site-packages/cfn_lint-0.7.2-py3.6.egg/cfnlint/decode/cfn_yaml.py", line 191, in loads
    loader = MarkedLoader(yaml_string, fname)
  File "/usr/local/lib/python3.6/site-packages/cfn_lint-0.7.2-py3.6.egg/cfnlint/decode/cfn_yaml.py", line 140, in __init__
    Reader.__init__(self, stream)
  File "/usr/local/lib/python3.6/site-packages/yaml/reader.py", line 74, in __init__
    self.check_printable(stream)
  File "/usr/local/lib/python3.6/site-packages/yaml/reader.py", line 144, in check_printable
    'unicode', "special characters are not allowed")
yaml.reader.ReaderError: unacceptable character #x0000: special characters are not allowed
  in "<unicode string>", position 0

@kddejong
Copy link
Contributor Author

Thanks for the feedback. Added logging for the filename information and did some extra items around the comma/space parsing. Also added some more documentation.

Copy link
Contributor

@alexjurkiewicz alexjurkiewicz left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Great work mate! This is very exciting :)

I have tested locally and no extra bugs from what's above. A few review comments you can accept or ignore

README.md Outdated
`cfn-lint --template template.yaml`
- `cfn-lint template.yaml`
- `cfn-lint --template template.yaml`
- `cfn-lint -t template.yaml`
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is it worth documenting all these different ways to do the same thing so high up in the README? It will take a lot of space. If you want to show both positional and argument -t and --template are wholly redundant

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

To expand on this, for quick start people probably just need to see cfn-lint template.yaml. Other forms can be left for the --help output.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Removed --template and moved up the usage section in the README so it isn't so far down. I will look into the adding information into the help. I think there was a request to make sure we showed the -- in the README so we didn't cause confusion when using the default parameters with other parameters. The -t examples can be moved though.

src/cfnlint/core.py Show resolved Hide resolved
def create_match_file_error(filename, msg):
"""Create a Match for a parser error"""
return cfnlint.Match(
1, 1, 1, 2, filename, cfnlint.ParseError(), message=msg)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

this function call is a bit cryptic. Should it used named parameters?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Updated. Thanks!

@@ -104,10 +104,11 @@ def create_parser():

# Alllow the template to be passes as an optional or a positional argument
standard.add_argument(
'template', nargs='?', help='The CloudFormation template to be linted')
'template', nargs='*', help='The CloudFormation template to be linted')
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is a real nitpick, but should probably call this variable 'templates' (with a metavar of TEMPLATE).

@cmmeyer cmmeyer merged commit c343cd7 into aws-cloudformation:master Sep 26, 2018
@alexjurkiewicz
Copy link
Contributor

alexjurkiewicz commented Sep 27, 2018 via email

@adamchainz
Copy link
Contributor

🐇

@Saichovsky
Copy link

Saichovsky commented Oct 2, 2018

pip install git+git://github.com/awslabs/cfn-python-lint.git works, but when I run pre-commit-validate-config .pre-commit-config.yaml, it fails with the following Traceback:

Traceback (most recent call last):
  File "/usr/bin/pre-commit-validate-config", line 11, in <module>
    sys.exit(validate_config_main())
  File "/usr/lib/python2.7/site-packages/pre_commit/clientlib.py", line 190, in validate_config_main
    load_config(filename)
  File "/usr/lib/python2.7/site-packages/cfgv.py", line 347, in load_from_filename
    contents = f.read()
  File "/usr/lib64/python2.7/encodings/ascii.py", line 26, in decode
    return codecs.ascii_decode(input, self.errors)[0]
UnicodeDecodeError: 'ascii' codec can't decode byte 0xc2 in position 386: ordinal not in range(128)

I'm installing from Github because the version that is on pypi does not seem to support multiple files. I feel that it is not up-to-date.

EDIT: There was a funny character on the last line of my config file which became visible once I viewed the file in vi. However, I think we have an uncovered scenario here, resulting in an uncaught exception being thrown.

@adamchainz
Copy link
Contributor

@Saichovsky that doesn't seem related to this at all, none of the stack trace frames are in cfn-python-lint. From the stacktrace I guess you have non-unicode characters in your configuration file.

@Saichovsky
Copy link

@adamchainz Indeed. Reported on the wrong repo. Apologies.

@kddejong kddejong deleted the Feature/LintMultipleFiles branch November 18, 2018 15:47
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

5 participants