Repository: warpnet/salt-lint (python)

Issue:
File/Dir mode regex's have false positives
**Describe the bug**
False positive for rule 207 and 208 for `mode` lines in other states

**To Reproduce**
Steps to reproduce the behavior:

1. State file for `network.managed`
```
bond0:
  network.managed:
    - type: bond
    - mode: 802.3ad
    - proto: static
    - ipaddr: 10.1.1.77
    - netmask: 255.255.255.0
    - gateway: 10.1.1.1
    - dns: 10.1.1.1
```
2. Run salt-lint against this file, it will fail with an error like:
```
[207] File modes should always be encapsulated in quotation marks
states/networking/server.sls:4
    - mode: 802.3ad

[208] File modes should always contain a leading zero
states/networking/server:4
    - mode: 802.3ad
```

**Expected behavior**
Only throw warnings for 207/208 when the mode line is part of a file/directory state.


**Desktop (please complete the following information):**

- OS: Ubuntu
- Version 20.04



Pull request:
Ignore non file mode lines in rule 207 and 208
Ignore non file mode lines in rule 207 and 208.

Closes #255

Patch:
diff --git a/.pylintrc b/.pylintrc
index 76b8563..294dfd0 100644
--- a/.pylintrc
+++ b/.pylintrc
@@ -16,3 +16,4 @@ disable=
     duplicate-code,
     dangerous-default-value,
     import-error,
+    fixme,
diff --git a/CHANGELOG.md b/CHANGELOG.md
index 3ea4106..7de90ff 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -7,6 +7,7 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
 ### Fixed
 - False positive when detecting missing spaces in Jinja variables when the Jinja statement is nested in literal braces ([#272](https://github.com/warpnet/salt-lint/pull/272)).
 - Ensure a single missing quote in the file mode is also detected as incorrect quotation of a file mode ([#273](https://github.com/warpnet/salt-lint/pull/273)).
+- Ignore non file mode arguments for the file mode quotation and leading zero checks ([#274](https://github.com/warpnet/salt-lint/pull/274)).
 
 ## [0.7.0] (2021-11-01)
 ### Added
diff --git a/saltlint/rules/FileModeLeadingZeroRule.py b/saltlint/rules/FileModeLeadingZeroRule.py
index 2849a57..1bc6394 100644
--- a/saltlint/rules/FileModeLeadingZeroRule.py
+++ b/saltlint/rules/FileModeLeadingZeroRule.py
@@ -1,7 +1,7 @@
 # -*- coding: utf-8 -*-
 # Copyright (c) 2016 Will Thames and contributors
 # Copyright (c) 2018 Ansible Project
-# Modified work Copyright (c) 2020 Warpnet B.V.
+# Modified work Copyright (c) 2020-2021 Warpnet B.V.
 
 import re
 from saltlint.linter.rule import Rule
@@ -17,7 +17,19 @@ class FileModeLeadingZeroRule(Rule):
     tags = ['formatting']
     version_added = 'v0.0.3'
 
-    regex = re.compile(r"^\s+- ((dir_)|(file_))?mode: ((')|(\"))?[0-9]{3}([\D]|$)")
+    regex = re.compile(
+        r"""^\s+             # line starting with whitespace
+        -\                   # whitespace escaped due to re.VERBOSE
+        (?:dir_|file_)?mode  # file_mode, dir_mode or mode
+        :\                   # whitespace escaped due to re.VERBOSE
+        ['"]?                # optional quotation character
+        ([0-9]{3})           # three number digit
+        (?:['"\s]|$)         # followed by whitespace, quoation or EOL
+        """,
+        re.VERBOSE
+    )
 
     def match(self, file, line):
+        # TODO: when salt-lint becomes state aware it should ignore the mode
+        # argument in the network.managed state.
         return self.regex.search(line)
diff --git a/saltlint/rules/FileModeQuotationRule.py b/saltlint/rules/FileModeQuotationRule.py
index 38bbae7..cdc6079 100644
--- a/saltlint/rules/FileModeQuotationRule.py
+++ b/saltlint/rules/FileModeQuotationRule.py
@@ -24,13 +24,16 @@ class FileModeQuotationRule(Rule):
         :\                   # whitespace escaped duo to re.VERBOSE
         (?:
             (\d{3,4})        # mode without quotation
+            (?:
+                ['"]         # followed by a quotation character
+              |
+                \s           # followed by a whitespace
+              |
+                $            # followed by EOL
+            )
           |
             (['"]\d{3,4}     # mode prefixed with quotation
-              (?:
-                  $          # end of line
-                |            # or
-                  [^\d'"]    # ending quotation missing
-              )
+              (?:[^\d'"]|$)  # not followed by digit, quoation or EOL
             )
         )
         """,
@@ -38,4 +41,6 @@ class FileModeQuotationRule(Rule):
     )
 
     def match(self, file, line):
+        # TODO: when salt-lint becomes state aware it should ignore the mode
+        # argument in the network.managed state.
         return self.regex.search(line)


Test patch:
diff --git a/tests/unit/TestFileModeLeadingZeroRule.py b/tests/unit/TestFileModeLeadingZeroRule.py
index 7f842c8..d892c0e 100644
--- a/tests/unit/TestFileModeLeadingZeroRule.py
+++ b/tests/unit/TestFileModeLeadingZeroRule.py
@@ -1,7 +1,7 @@
 # -*- coding: utf-8 -*-
 # Copyright (c) 2013-2018 Will Thames <will@thames.id.au>
 # Copyright (c) 2018 Ansible by Red Hat
-# Modified work Copyright (c) 2020 Warpnet B.V.
+# Modified work Copyright (c) 2020-2021 Warpnet B.V.
 
 import unittest
 
@@ -25,23 +25,44 @@ testfile:
     - name: /tmp/badfile
     - user: root
     - group: root
-    - mode: 700
+    - mode: 600
     - file_mode: '660'
     - dir_mode: '775'
 '''
 
+NETWORK_MANAGED_MODE = '''
+bond0:
+  network.managed:
+    - type: bond
+    - mode: 802.3ad
+    - proto: static
+    - ipaddr: 10.1.1.77
+    - netmask: 255.255.255.0
+    - gateway: 10.1.1.1
+    - dns: 10.1.1.1
+'''
+
+
 class TestFileModeLeadingZeroRule(unittest.TestCase):
     collection = RulesCollection()
 
     def setUp(self):
         self.collection.register(FileModeLeadingZeroRule())
+        self.runner = RunFromText(self.collection)
 
     def test_statement_positive(self):
-        runner = RunFromText(self.collection)
-        results = runner.run_state(GOOD_MODE_LEADING_ZERO_LINE)
+        results = self.runner.run_state(GOOD_MODE_LEADING_ZERO_LINE)
         self.assertEqual(0, len(results))
 
     def test_statement_negative(self):
-        runner = RunFromText(self.collection)
-        results = runner.run_state(BAD_MODE_LEADING_ZERO_LINE)
+        results = self.runner.run_state(BAD_MODE_LEADING_ZERO_LINE)
         self.assertEqual(3, len(results))
+
+    def test_network_mode(self):
+        """
+        Ensure the mode argument in the network.managed state gets ignored. See
+        related GitHub issue:
+        https://github.com/warpnet/salt-lint/issues/255
+        """
+        results = self.runner.run_state(NETWORK_MANAGED_MODE)
+        self.assertEqual(0, len(results))
diff --git a/tests/unit/TestFileModeQuotationRule.py b/tests/unit/TestFileModeQuotationRule.py
index 698fa5e..ea70bb5 100644
--- a/tests/unit/TestFileModeQuotationRule.py
+++ b/tests/unit/TestFileModeQuotationRule.py
@@ -41,6 +41,18 @@ testfile:
     - dir_mode: 0775"
 '''
 
+NETWORK_MANAGED_MODE = '''
+bond0:
+  network.managed:
+    - type: bond
+    - mode: 802.3ad
+    - proto: static
+    - ipaddr: 10.1.1.77
+    - netmask: 255.255.255.0
+    - gateway: 10.1.1.1
+    - dns: 10.1.1.1
+'''
+
 
 class TestModeQuotationRule(unittest.TestCase):
     collection = RulesCollection()
@@ -60,3 +72,12 @@ class TestModeQuotationRule(unittest.TestCase):
     def test_missing_quotes(self):
         results = self.runner.run_state(MODE_MISSING_QUOTATION_LINE)
         self.assertEqual(3, len(results))
+
+    def test_network_mode(self):
+        """
+        Ensure the mode argument in the network.managed state gets ignored. See
+        related GitHub issue:
+        https://github.com/warpnet/salt-lint/issues/255
+        """
+        results = self.runner.run_state(NETWORK_MANAGED_MODE)
+        self.assertEqual(0, len(results))