This is an automated email from the ASF dual-hosted git repository.
smolnar82 pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/knox.git
The following commit(s) were added to refs/heads/master by this push:
new 10eedcc34 KNOX-3335: Add pylint pre-push linting for
.github/workflows/tests Python integration tests (#1260)
10eedcc34 is described below
commit 10eedcc34a8bfd8d09c946ad95f6801d9ada6c35
Author: Raghav Maheshwari <[email protected]>
AuthorDate: Fri Jun 12 20:43:31 2026 +0530
KNOX-3335: Add pylint pre-push linting for .github/workflows/tests Python
integration tests (#1260)
---
.github/workflows/compose/docker-compose.yml | 9 ++--
.github/workflows/tests/common_utils.py | 8 +++-
.github/workflows/tests/requirements.txt | 1 +
.github/workflows/tests/test_health.py | 13 +++---
..._LDAP.py => test_knox_auth_service_and_ldap.py} | 49 +++++++++++++---------
.github/workflows/tests/test_knox_configs.py | 18 ++++----
.../tests/test_knoxauth_preauth_and_paths.py | 4 +-
.github/workflows/tests/test_remote_auth.py | 19 ++++-----
.../test_remoteauth_extauthz_additional_path.py | 11 ++++-
9 files changed, 80 insertions(+), 52 deletions(-)
diff --git a/.github/workflows/compose/docker-compose.yml
b/.github/workflows/compose/docker-compose.yml
index e03e90e5a..3364c7f08 100644
--- a/.github/workflows/compose/docker-compose.yml
+++ b/.github/workflows/compose/docker-compose.yml
@@ -37,16 +37,17 @@ services:
- ldap
tests:
- image: python:3.9-slim
+ image: python:3.10-slim
working_dir: /tests
volumes:
- ../tests:/tests
environment:
- KNOX_GATEWAY_URL=https://knox:8443/
command: >
- bash -c "pip install -r requirements.txt
- && echo 'Waiting for knox...'
- && sleep 30
+ bash -c "pip install -r requirements.txt
+ && pylint *.py
+ && echo 'Waiting for knox...'
+ && sleep 30
&& pytest --junitxml=test-results.xml"
depends_on:
- knox
diff --git a/.github/workflows/tests/common_utils.py
b/.github/workflows/tests/common_utils.py
index 41198b09e..0a773b44e 100644
--- a/.github/workflows/tests/common_utils.py
+++ b/.github/workflows/tests/common_utils.py
@@ -13,6 +13,8 @@
# See the License for the specific language governing permissions and
# limitations under the License.
+"""Shared helpers for Knox gateway integration tests."""
+
from __future__ import annotations
import os
@@ -54,7 +56,10 @@ def knox_post(url: str, **kwargs: Any) -> requests.Response:
def collect_actor_group_values(
response: requests.Response, prefix: str = "x-knox-actor-groups"
) -> list[str]:
- """Comma-split values from all response headers whose names start with
prefix (case-insensitive)."""
+ """Comma-split values from response headers whose names start with prefix.
+
+ Matching is case-insensitive.
+ """
prefix_lower = prefix.lower()
all_groups: list[str] = []
for name in response.headers:
@@ -64,5 +69,6 @@ def collect_actor_group_values(
def assert_hsts_header(testcase: unittest.TestCase, response:
requests.Response) -> None:
+ """Assert the response includes the expected Strict-Transport-Security
header."""
testcase.assertIn(HSTS_HEADER_NAME, response.headers)
testcase.assertEqual(response.headers[HSTS_HEADER_NAME],
HSTS_EXPECTED_VALUE)
diff --git a/.github/workflows/tests/requirements.txt
b/.github/workflows/tests/requirements.txt
index 9967c535d..9f223fca6 100644
--- a/.github/workflows/tests/requirements.txt
+++ b/.github/workflows/tests/requirements.txt
@@ -1,2 +1,3 @@
requests==2.32.4
pytest==8.3.4
+pylint==4.0.5
\ No newline at end of file
diff --git a/.github/workflows/tests/test_health.py
b/.github/workflows/tests/test_health.py
index a62e2f2bd..cb99e3495 100644
--- a/.github/workflows/tests/test_health.py
+++ b/.github/workflows/tests/test_health.py
@@ -12,6 +12,9 @@
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
+
+"""Integration tests for the Knox gateway health REST API."""
+
import json
import unittest
@@ -44,11 +47,11 @@ class TestKnoxHealth(unittest.TestCase):
assert_hsts_header(self, response)
except requests.exceptions.ConnectionError:
self.fail("Failed to connect to Knox on port 8443 - Connection
refused")
- except Exception as e:
- self.fail(f"Health check failed with unexpected error: {e}")
+ except requests.exceptions.RequestException as exc:
+ self.fail(f"Health check failed with unexpected error: {exc}")
def test_health_metrics_returns_json(self):
- """Metrics with pretty=true returns 200 and a JSON object with
application/json content type."""
+ """Metrics with pretty=true returns 200 and JSON with application/json
type."""
url = self.base_url + "gateway/health/v1/metrics?pretty=true"
response = knox_get(url)
self.assertEqual(response.status_code, 200)
@@ -71,7 +74,7 @@ class TestKnoxHealth(unittest.TestCase):
)
def test_health_metrics_without_pretty_returns_json(self):
- """Metrics without pretty still returns 200, parseable JSON, and the
same top-level keys as pretty."""
+ """Metrics without pretty returns 200, parseable JSON, and the same
top-level keys."""
url = self.base_url + "gateway/health/v1/metrics"
response = knox_get(url)
self.assertEqual(response.status_code, 200)
@@ -92,6 +95,6 @@ class TestKnoxHealth(unittest.TestCase):
content_type = response.headers.get("Content-Type", "")
self.assertIn("text/plain", content_type)
+
if __name__ == '__main__':
unittest.main()
-
diff --git a/.github/workflows/tests/test_knox_auth_service_and_LDAP.py
b/.github/workflows/tests/test_knox_auth_service_and_ldap.py
similarity index 81%
rename from .github/workflows/tests/test_knox_auth_service_and_LDAP.py
rename to .github/workflows/tests/test_knox_auth_service_and_ldap.py
index 575d63a92..3f3ccea6e 100644
--- a/.github/workflows/tests/test_knox_auth_service_and_LDAP.py
+++ b/.github/workflows/tests/test_knox_auth_service_and_ldap.py
@@ -12,22 +12,19 @@
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
+
+"""Integration tests for Knox Auth Service with LDAP authentication."""
+
import unittest
+
from requests.auth import HTTPBasicAuth
from common_utils import collect_actor_group_values, gateway_base_url, knox_get
-########################################################
-# This test is verifying the behavior of the Knox Auth Service + LDAP
authentication.
-# It is using the 'auth/api/v1/pre' endpoint to get the actor ID and group
headers.
-# It is using the 'guest' user to get the guest user headers.
-# It is using the 'admin' user to get the admin user headers.
-# It is verifying that the actor ID and group headers are correct.
-# It is verifying that the actor ID and group headers are not empty.
-# It is verifying that the actor ID and group headers are not None.
-########################################################
class TestKnoxAuthService(unittest.TestCase):
+ """Verify actor ID and group headers from the knoxldap preauth endpoint."""
+
def setUp(self):
self.base_url = gateway_base_url()
# The topology name is based on the filename knoxldap.xml
@@ -42,12 +39,13 @@ class TestKnoxAuthService(unittest.TestCase):
self.topology_url,
auth=HTTPBasicAuth('guest', 'guest-password'),
)
-
+
print(f"Status Code: {response.status_code}")
self.assertEqual(response.status_code, 200)
-
+
# Check for Actor ID header
- # The config in knoxldap.xml sets 'preauth.auth.header.actor.id.name'
to 'x-knox-actor-username'
+ # The config in knoxldap.xml sets 'preauth.auth.header.actor.id.name'
+ # to 'x-knox-actor-username'
actor_id_header = 'x-knox-actor-username'
self.assertIn(actor_id_header, response.headers)
self.assertEqual(response.headers[actor_id_header], 'guest')
@@ -56,7 +54,11 @@ class TestKnoxAuthService(unittest.TestCase):
# Check for Actor Group header - should be empty for guest
prefix = 'x-knox-actor-groups'
all_groups = collect_actor_group_values(response, prefix=prefix)
- self.assertEqual(len(all_groups), 0, f"Guest user should not have any
group headers starting with {prefix}")
+ self.assertEqual(
+ len(all_groups),
+ 0,
+ f"Guest user should not have any group headers starting with
{prefix}",
+ )
def test_auth_service_admin_groups(self):
"""
@@ -67,26 +69,32 @@ class TestKnoxAuthService(unittest.TestCase):
self.topology_url,
auth=HTTPBasicAuth('admin', 'admin-password'),
)
-
+
print(f"Status Code: {response.status_code}")
self.assertEqual(response.status_code, 200)
-
+
# Check for Actor ID header
actor_id_header = 'x-knox-actor-username'
self.assertIn(actor_id_header, response.headers)
self.assertEqual(response.headers[actor_id_header], 'admin')
print(f"Verified {actor_id_header}:
{response.headers[actor_id_header]}")
-
+
# Config: 'preauth.auth.header.actor.groups.prefix' =
'x-knox-actor-groups'
# We mapped admin to
'longGroupName1,longGroupName2,longGroupName3,longGroupName4'
prefix = 'x-knox-actor-groups'
all_groups = collect_actor_group_values(response, prefix=prefix)
self.assertTrue(len(all_groups) > 0, f"No headers found starting with
{prefix}")
- for h in response.headers:
- if h.lower().startswith(prefix.lower()):
- print(f"Found group header {h}: {response.headers[h]}")
+ for header_name in response.headers:
+ if header_name.lower().startswith(prefix.lower()):
+ print(f"Found group header {header_name}:
{response.headers[header_name]}")
- expected_groups = ['admin', 'longGroupName1', 'longGroupName2',
'longGroupName3', 'longGroupName4']
+ expected_groups = [
+ 'admin',
+ 'longGroupName1',
+ 'longGroupName2',
+ 'longGroupName3',
+ 'longGroupName4',
+ ]
for group in expected_groups:
self.assertIn(group, all_groups)
@@ -119,5 +127,6 @@ class TestKnoxAuthService(unittest.TestCase):
self.assertIn(group, all_groups)
print(f"Verified recursive groups: {all_groups}")
+
if __name__ == '__main__':
unittest.main()
diff --git a/.github/workflows/tests/test_knox_configs.py
b/.github/workflows/tests/test_knox_configs.py
index 0a9b5e78c..752b1dc5d 100644
--- a/.github/workflows/tests/test_knox_configs.py
+++ b/.github/workflows/tests/test_knox_configs.py
@@ -12,19 +12,19 @@
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
+
+"""Integration tests for global Knox gateway configuration."""
+
import unittest
+
from requests.auth import HTTPBasicAuth
from common_utils import assert_hsts_header, gateway_base_url, knox_get
-########################################################
-# This test is verifying the global HSTS headers for 404 response.
-# It executes new GET request on non-existent Knox path
-# It verifies header is present with the correct value.
-########################################################
-
class TestKnoxConfigs(unittest.TestCase):
+ """Verify global gateway settings such as HSTS on error responses."""
+
def setUp(self):
self.base_url = gateway_base_url()
self.non_existent_path = self.base_url + "gateway/not-exists"
@@ -33,7 +33,7 @@ class TestKnoxConfigs(unittest.TestCase):
"""
Verifies header is present with the correct value
"""
- print(f"\nTesting global HSTS config for 404 response")
+ print("\nTesting global HSTS config for 404 response")
response = knox_get(
self.non_existent_path,
auth=HTTPBasicAuth('admin', 'admin-password'),
@@ -43,5 +43,5 @@ class TestKnoxConfigs(unittest.TestCase):
self.assertEqual(response.status_code, 404)
assert_hsts_header(self, response)
- print(f"Verified Strict-Transport-Security:
{response.headers['Strict-Transport-Security']}")
-
+ hsts_value = response.headers['Strict-Transport-Security']
+ print(f"Verified Strict-Transport-Security: {hsts_value}")
diff --git a/.github/workflows/tests/test_knoxauth_preauth_and_paths.py
b/.github/workflows/tests/test_knoxauth_preauth_and_paths.py
index 45d51a5c8..28a3f0940 100644
--- a/.github/workflows/tests/test_knoxauth_preauth_and_paths.py
+++ b/.github/workflows/tests/test_knoxauth_preauth_and_paths.py
@@ -12,6 +12,9 @@
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
+
+"""Integration tests for KnoxLDAP preauth and extauthz path handling."""
+
import unittest
from requests.auth import HTTPBasicAuth
@@ -84,4 +87,3 @@ class TestKnoxAuthServicePreAuthAndPaths(unittest.TestCase):
if __name__ == "__main__":
unittest.main()
-
diff --git a/.github/workflows/tests/test_remote_auth.py
b/.github/workflows/tests/test_remote_auth.py
index ae87c5393..8e3120ff5 100644
--- a/.github/workflows/tests/test_remote_auth.py
+++ b/.github/workflows/tests/test_remote_auth.py
@@ -12,21 +12,19 @@
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
+
+"""Integration tests for the RemoteAuthProvider topology."""
+
import unittest
+
from requests.auth import HTTPBasicAuth
from common_utils import collect_actor_group_values, gateway_base_url, knox_get
-########################################################
-# This test is verifying the behavior of the RemoteAuthProvider.
-# It is using the 'auth/api/v1/pre' endpoint to get the actor ID and group
headers.
-# It is using the 'guest' user to get the guest user headers.
-# It is using the 'admin' user to get the admin user headers.
-# It is verifying that the actor ID and group headers are correct.
-# It is verifying that the actor ID and group headers are not empty.
-# It is verifying that the actor ID and group headers are not None.
-########################################################
+
class TestRemoteAuth(unittest.TestCase):
+ """Verify RemoteAuthProvider actor ID and group headers via the pre
endpoint."""
+
def setUp(self):
self.base_url = gateway_base_url()
self.topology_url = self.base_url +
"gateway/remoteauth/auth/api/v1/pre"
@@ -67,7 +65,7 @@ class TestRemoteAuth(unittest.TestCase):
# knoxldap maps admin to:
longGroupName1,longGroupName2,longGroupName3,longGroupName4
# RemoteAuthFilter picks these up from x-knox-actor-groups-*
# And KNOX-AUTH-SERVICE echoes them back in X-Knox-Actor-Groups-*
-
+
all_groups = collect_actor_group_values(response)
print(f"Found groups: {all_groups}")
@@ -87,5 +85,6 @@ class TestRemoteAuth(unittest.TestCase):
# When remote auth fails (knoxldap returns 401), RemoteAuthFilter
should return 401
self.assertEqual(response.status_code, 401)
+
if __name__ == '__main__':
unittest.main()
diff --git
a/.github/workflows/tests/test_remoteauth_extauthz_additional_path.py
b/.github/workflows/tests/test_remoteauth_extauthz_additional_path.py
index 069dbc166..1abeb4233 100644
--- a/.github/workflows/tests/test_remoteauth_extauthz_additional_path.py
+++ b/.github/workflows/tests/test_remoteauth_extauthz_additional_path.py
@@ -12,6 +12,9 @@
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
+
+"""Integration tests for RemoteAuth extauthz path handling."""
+
import unittest
from requests.auth import HTTPBasicAuth
@@ -20,11 +23,14 @@ from common_utils import gateway_base_url, knox_get
class TestRemoteAuthExtAuthzAdditionalPath(unittest.TestCase):
+ """Verify RemoteAuth extauthz success, path handling, and auth failures."""
+
def setUp(self):
self.base_url = gateway_base_url()
self.extauthz_url = self.base_url +
"gateway/remoteauth/auth/api/v1/extauthz"
def test_extauthz_success(self):
+ """Valid credentials on extauthz return 200 and X-Knox-Actor-ID."""
response = knox_get(
self.extauthz_url,
auth=HTTPBasicAuth("guest", "guest-password"),
@@ -34,6 +40,7 @@ class TestRemoteAuthExtAuthzAdditionalPath(unittest.TestCase):
self.assertEqual(response.headers["X-Knox-Actor-ID"], "guest")
def test_extauthz_additional_path_is_ignored(self):
+ """Extra path segments under extauthz still authenticate
successfully."""
response = knox_get(
self.extauthz_url + "/some/extra/path",
auth=HTTPBasicAuth("guest", "guest-password"),
@@ -43,6 +50,7 @@ class TestRemoteAuthExtAuthzAdditionalPath(unittest.TestCase):
self.assertEqual(response.headers["X-Knox-Actor-ID"], "guest")
def test_extauthz_bad_credentials_unauthorized(self):
+ """Invalid credentials on extauthz return 401."""
response = knox_get(
self.extauthz_url,
auth=HTTPBasicAuth("baduser", "badpass"),
@@ -50,11 +58,10 @@ class
TestRemoteAuthExtAuthzAdditionalPath(unittest.TestCase):
self.assertEqual(response.status_code, 401)
def test_extauthz_missing_credentials(self):
- # No Authorization header: 401 (no longer hit the NPE because of
missing cache key from the header).
+ """Missing Authorization header on extauthz returns 401."""
response = knox_get(self.extauthz_url)
self.assertEqual(response.status_code, 401)
if __name__ == "__main__":
unittest.main()
-