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

Version 0.1.0 Release #91

Merged
merged 36 commits into from
Nov 1, 2019
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
36 commits
Select commit Hold shift + click to select a range
7e1a163
Update Travis
jbouter Oct 25, 2019
52e76c3
Update travis config
jbouter Oct 25, 2019
bdff84d
Update Dockerfile
jbouter Oct 25, 2019
5631387
Update dockerfile
jbouter Oct 25, 2019
8e2e987
Update Travis
jbouter Oct 25, 2019
5d56cf4
Add JSON formatter
roaldnefs Oct 25, 2019
acad989
Update Travis Config
jbouter Oct 25, 2019
ce1604b
Update badges in README.md
roaldnefs Oct 25, 2019
2926fdb
Update tox
jbouter Oct 25, 2019
d2d947e
Merge pull request #77 from warpnet/dockerfile
jbouter Oct 25, 2019
b8c54ea
Merge pull request #78 from warpnet/fix/badges
jbouter Oct 25, 2019
270edfc
Merge branch 'master' of github.com:warpnet/salt-lint into develop
roaldnefs Oct 25, 2019
5d49cad
Update README.md to include --json flag
roaldnefs Oct 25, 2019
f788dde
Merge branch 'develop' into feature/json-format
roaldnefs Oct 25, 2019
b40f5b4
Update readme
jbouter Oct 25, 2019
f3ffa57
Fix output encoding
roaldnefs Oct 25, 2019
d5e851b
Fix syntax errors
roaldnefs Oct 25, 2019
7b6f604
Update rules list in README.md
roaldnefs Oct 25, 2019
1be2696
Read input from stdin
jacobbudin Oct 26, 2019
151cbb6
Updated table in readme
jbouter Oct 26, 2019
caa5bd0
Merge branch 'readme-ruletable' of github.com:warpnet/salt-lint into …
jbouter Oct 26, 2019
5532d70
Merge pull request #82 from warpnet/readme-ruletable
jbouter Oct 26, 2019
1f74710
Merge pull request #83 from jacobbudin/read-stdin
roaldnefs Oct 27, 2019
7377c26
Fix encoding to use utf-8
roaldnefs Oct 27, 2019
56f5b4a
Merge branch 'develop' into feature/json-format
roaldnefs Oct 27, 2019
6ddf634
Merge pull request #84 from warpnet/fix/encoding
roaldnefs Oct 28, 2019
e6b5964
Merge branch 'develop' into feature/json-format
roaldnefs Oct 28, 2019
f2bd78c
Fix encoding in Formatter
roaldnefs Oct 28, 2019
210fb9d
Add severity in JSON output
roaldnefs Oct 28, 2019
b74d5da
Merge pull request #81 from warpnet/feature/json-format
roaldnefs Oct 31, 2019
fdcfd7c
Fix format string to use square brackets
roaldnefs Oct 31, 2019
a4ea16b
Merge pull request #87 from warpnet/fix/formatstr
roaldnefs Oct 31, 2019
14a28e7
Change all 'Salt state' occurrences to 'Salt State'
Nov 1, 2019
af1d80d
Merge pull request #88 from arjenzijlstra/fix-consistency
matthijswendelaar Nov 1, 2019
0fb111d
Bump version to v0.1.0
roaldnefs Nov 1, 2019
2985128
Merge pull request #90 from warpnet/v0.1.0
roaldnefs Nov 1, 2019
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
45 changes: 38 additions & 7 deletions .travis.yml
Original file line number Diff line number Diff line change
Expand Up @@ -4,21 +4,52 @@ language: python

matrix:
include:
- env: TOXENV=flake8
install:
- pip install tox
script:
- tox

- python: 2.7
env: TOXENV=py27
install:
- pip install tox
script:
- tox

- python: 3.5
env: TOXENV=py35
install:
- pip install tox
script:
- tox

- python: 3.6
env: TOXENV=py36
install:
- pip install tox
script:
- tox

- python: 3.7
env: TOXENV=py37
- env: TOXENV=flake8

install:
- pip install tox
install:
- pip install tox
script:
- tox

script:
- tox
- language: generic
sudo: false
env:
HADOLINT: "${HOME}/hadolint"
install:
# Download hadolint binary and set it as executable
- curl -sL -o ${HADOLINT} "https://github.com/hadolint/hadolint/releases/download/v1.16.0/hadolint-$(uname -s)-$(uname -m)"
&& chmod 700 ${HADOLINT}
script:
# List files which name starts with 'Dockerfile'
# eg. Dockerfile, Dockerfile.build, etc.
- git ls-files --exclude='Dockerfile*' --ignored | xargs --max-lines=1 ${HADOLINT}

# Deploy a new release to PyPi for every new tag on the 'master' branch on the
# repository 'warpnet/salt-lint'.
Expand All @@ -35,4 +66,4 @@ deploy:
tags: true
branch: master
python: 3.6
condition: "$TOXENV = py36"
condition: "$TOXENV = py36"
2 changes: 1 addition & 1 deletion LICENSE
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ MIT License

Copyright (c) 2013-2018 Will Thames <will@thames.id.au>
Copyright (c) 2018 Ansible by Red Hat
Modified work Copyright (c) 2019 Roald Nefs
Modified work Copyright (c) 2019 Warpnet B.V.

Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
Expand Down
42 changes: 30 additions & 12 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,10 +1,10 @@
[![PyPI](https://img.shields.io/pypi/v/salt-lint.svg?style=for-the-badge)](https://pypi.org/project/salt-lint)
[![Travis (.org)](https://img.shields.io/travis/warpnet/salt-lint.svg?style=for-the-badge)](https://travis-ci.org/warpnet/salt-lint)
[![Coveralls](https://img.shields.io/coveralls/github/warpnet/salt-lint.svg?style=for-the-badge)](https://coveralls.io/github/warpnet/salt-lint)
[![Travis (.org)](https://img.shields.io/travis/warpnet/salt-lint/master.svg?style=for-the-badge)](https://travis-ci.org/warpnet/salt-lint)
[![Coveralls](https://img.shields.io/coveralls/github/warpnet/salt-lint/master.svg?style=for-the-badge)](https://coveralls.io/github/warpnet/salt-lint)

# Salt-lint

`salt-lint` checks Salt state files (SLS) for practices and behavior that could potentially be improved.
`salt-lint` checks Salt State files (SLS) for practices and behavior that could potentially be improved.

The project is heavily based on [ansible-lint](https://github.com/ansible/ansible-lint), which was created by [Will Thames](https://github.com/willthames) and is now maintained as part of the [Ansible](https://www.ansible.com/) by [Red Hat](https://www.redhat.com) project.

Expand Down Expand Up @@ -37,14 +37,12 @@ Options:
-L list all the rules
-r RULESDIR specify one or more rules directories using one or
more -r arguments. Any -r flags override the default
rules in
/home/roald/workspace/github.com/roaldnefs/salt-
lint/saltlint/rules, unless -R is also used.
rules in /path/to/salt-lint/saltlint/rules, unless
-R is also used.
-R Use default rules in
/home/roald/workspace/github.com/roaldnefs/salt-
lint/saltlint/rules in addition to any extra rules
directories specified with -r. There is no need to
specify this if no -r flags are used.
/path/to/salt-lint/saltlint/rules in addition to any
extra rules directories specified with -r. There is
no need to specify this if no -r flags are used.
-t TAGS only check rules whose id/tags match these values
-T list all the tags
-v Increase verbosity level
Expand All @@ -55,13 +53,14 @@ Options:
--exclude=EXCLUDE_PATHS
path to directories or files to skip. This option is
repeatable.
--json parse the output as JSON
-c C Specify configuration file to use. Defaults to
".salt-lint"
```

## Linting Salt state files
## Linting Salt State files

It's important to note that `salt-lint` accepts a list of Salt state files or a list of directories.
It's important to note that `salt-lint` accepts a list of Salt State files or a list of directories.

## GitHub Action

Expand Down Expand Up @@ -135,6 +134,25 @@ To use salt-lint with [pre-commit](https://pre-commit.com), just add the follow

# Rules


## List of rules

Rule | Description
:-:|:--
[201](https://github.com/warpnet/salt-lint/wiki/201) | Trailing whitespace
[202](https://github.com/warpnet/salt-lint/wiki/202) | Jinja statement should have spaces before and after: `{% statement %}`
[203](https://github.com/warpnet/salt-lint/wiki/203) | Most files should not contain tabs
[204](https://github.com/warpnet/salt-lint/wiki/204) | Lines should be no longer that 160 chars
[205](https://github.com/warpnet/salt-lint/wiki/205) | Use ".sls" as a Salt State file extension
[206](https://github.com/warpnet/salt-lint/wiki/206) | Jinja variables should have spaces before and after `{{ var_name }}`
[207](https://github.com/warpnet/salt-lint/wiki/207) | File modes should always be encapsulated in quotation marks
[208](https://github.com/warpnet/salt-lint/wiki/208) | File modes should always contain a leading zero
[209](https://github.com/warpnet/salt-lint/wiki/209) | Jinja comment should have spaces before and after: `{# comment #}`
[210](https://github.com/warpnet/salt-lint/wiki/210) | Numbers that start with `0` should always be encapsulated in quotation marks
[211](https://github.com/warpnet/salt-lint/wiki/211) | `pillar.get` or `grains.get` should be formatted differently
[212](https://github.com/warpnet/salt-lint/wiki/212) | Most files should not contain irregular spaces


## False Positives: Skipping Rules

Some rules are bit of a rule of thumb. To skip a specific rule for a specific task, inside your state add `# noqa [rule_id]` at the end of the line. You can skip multiple rules via a space-separated list. Example:
Expand Down
21 changes: 21 additions & 0 deletions docker/Dockerfile
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
FROM python:3.7-alpine
LABEL maintainer="info@warpnet.nl"

# Install required alpine packages
# hadolint ignore=DL3018,DL3019
RUN apk add --no-cache gcc g++ build-base libzmq musl-dev zeromq-dev

# Install the salt-lint package
RUN pip install --no-cache salt-lint==v0.1.0

# Remove development utilities
RUN apk del --no-cache gcc g++ build-base libzmq musl-dev zeromq-dev \
&& rm -rf /var/cache/apk/*

RUN addgroup -S -g 800 linter \
&& adduser -S -u 800 -S -H -D -G linter linter

# Run as linter user
USER linter

CMD ["/usr/local/bin/salt-lint"]
4 changes: 2 additions & 2 deletions saltlint/__init__.py
Original file line number Diff line number Diff line change
@@ -1,11 +1,11 @@
# -*- coding: utf-8 -*-
# Copyright (c) 2019 Roald Nefs
# Copyright (c) 2019 Warpnet B.V.

"""A command-line utility that checks for best practices in SaltStack.
"""

NAME = 'salt-lint'
VERSION = '0.0.10'
VERSION = '0.1.0'
DESCRIPTION = __doc__

__author__ = 'Warpnet B.V.'
Expand Down
41 changes: 34 additions & 7 deletions saltlint/cli.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,15 +5,22 @@
from __future__ import print_function

import optparse
import os
import sys
import tempfile
import codecs

from saltlint import formatters, NAME, VERSION
from saltlint.config import SaltLintConfig, SaltLintConfigError, default_rulesdir
from saltlint.linter import RulesCollection, Runner


def run(args=None):
formatter = formatters.Formatter()
# Wrap `sys.stdout` in an object that automatically encodes an unicode
# string into utf-8, in Python 2 only. The default encoding for Python 3
# is already utf-8.
if sys.version_info[0] < 3:
sys.stdout = codecs.getwriter('utf-8')(sys.stdout)

parser = optparse.OptionParser("%prog [options] init.sls [state ...]",
version='{} {}'.format(NAME, VERSION))
Expand Down Expand Up @@ -56,9 +63,23 @@ def run(args=None):
help='path to directories or files to skip. This option'
' is repeatable.',
default=[])
parser.add_option('--json', dest='json', action='store_true', default=False,
help='parse the output as JSON')
parser.add_option('-c', help='Specify configuration file to use. Defaults to ".salt-lint"')
(options, parsed_args) = parser.parse_args(args if args is not None else sys.argv[1:])

stdin_state = None
states = set(parsed_args)
matches = list()
checked_files = set()

# Read input from stdin
if not sys.stdin.isatty():
stdin_state = tempfile.NamedTemporaryFile('w', suffix='.sls', delete=False)
stdin_state.write(sys.stdin.read())
stdin_state.flush()
states.add(stdin_state.name)

# Read, parse and validate the configration
options_dict = vars(options)
try:
Expand All @@ -68,7 +89,7 @@ def run(args=None):
return 2

# Show a help message on the screen
if len(parsed_args) == 0 and not (options.listrules or options.listtags):
if len(states) == 0 and not (options.listrules or options.listtags):
parser.print_help(file=sys.stderr)
return 1

Expand All @@ -87,9 +108,12 @@ def run(args=None):
print(rules.listtags())
return 0

states = set(parsed_args)
matches = list()
checked_files = set()
# Define the formatter
if config.json:
formatter = formatters.JsonFormatter()
else:
formatter = formatters.Formatter()

for state in states:
runner = Runner(rules, state, config, checked_files)
matches.extend(runner.run())
Expand All @@ -98,8 +122,11 @@ def run(args=None):
matches.sort(key=lambda x: (x.filename, x.linenumber, x.rule.id))

# Show the matches on the screen
for match in matches:
print(formatter.format(match, config.colored).encode('utf-8'))
formatter.process(matches, config.colored)

# Delete stdin temporary file
if stdin_state:
os.unlink(stdin_state.name)

# Return the exit code
if len(matches):
Expand Down
3 changes: 3 additions & 0 deletions saltlint/config.py
Original file line number Diff line number Diff line change
Expand Up @@ -95,6 +95,9 @@ def _parse(self, content):
hasattr(sys.stdout, 'isatty') and sys.stdout.isatty()
)

# Parse json
self.json = self._options.get('json', False)

# Parse rule specific configuration, the configration can be listed by
# the rule ID and/or tag.
self.rules = dict()
Expand Down
37 changes: 32 additions & 5 deletions saltlint/formatters/__init__.py
Original file line number Diff line number Diff line change
@@ -1,7 +1,10 @@
# -*- coding: utf-8 -*-
# Copyright (c) 2013-2018 Will Thames <will@thames.id.au>
# Copyright (c) 2018 Ansible by Red Hat
# Modified work Copyright (c) 2019 Roald Nefs

import json

# Import salt libs
try:
import salt.utils.color as saltcolor
Expand All @@ -11,6 +14,10 @@

class Formatter(object):

def process(self, matches, colored=False):
for match in matches:
print(self.format(match, colored))

def format(self, match, colored=False):
formatstr = u"{0} {1}\n{2}:{3}\n{4}\n"
if colored:
Expand All @@ -27,8 +34,28 @@ def format(self, match, colored=False):
u'{0}{1}{2}'.format(color['MAGENTA'], match.line, color['ENDC'])
)
else:
return formatstr.format(match.rule.id,
match.message,
match.filename,
match.linenumber,
match.line)
return formatstr.format(
u'[{0}]'.format(match.rule.id),
match.message,
match.filename,
match.linenumber,
match.line)


class JsonFormatter(object):

def process(self, matches, *args, **kwargs):
items = []
for match in matches:
items.append(self.format(match))
print(json.dumps(items))

def format(self, match):
return {
'id': match.rule.id,
'message': match.message,
'filename': match.filename,
'linenumber': match.linenumber,
'line': match.line,
'severity': match.rule.severity,
}
2 changes: 1 addition & 1 deletion saltlint/rules/NoIrregularSpacesRule.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ class NoIrregularSpacesRule(SaltLintRule):
description = 'Irregular spaces can cause unexpected display issues, use spaces'
severity = 'LOW'
tags = ['formatting']
version_added = 'develop'
version_added = 'v0.1.0'

irregular_spaces = [
u"\u000B", # Line Tabulation (\v) - <VT>
Expand Down