mirror of
				https://github.com/kevinveenbirkenbach/computer-playbook.git
				synced 2025-10-31 18:29:21 +00:00 
			
		
		
		
	Add custom Ansible filter plugin get_category_entries
This commit introduces a new Ansible filter plugin named 'get_category_entries', which returns all role names under the roles/ directory that start with a given prefix. Additionally, unit tests (unittest framework) have been added under tests/unit/filterplugins/ to ensure correct behavior, including: - Returns empty list when roles/ directory is missing - Correctly filters and sorts by prefix - Ignores non-directory entries - Supports custom roles_path argument - Returns all roles when prefix is empty Reference: https://chatgpt.com/share/68a2f1ab-1fe8-800f-b22a-28c1c95802c2
This commit is contained in:
		
							
								
								
									
										31
									
								
								filter_plugins/get_category_entries.py
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										31
									
								
								filter_plugins/get_category_entries.py
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,31 @@ | ||||
| # Custom Ansible filter to get all role names under "roles/" with a given prefix. | ||||
|  | ||||
| import os | ||||
|  | ||||
| def get_category_entries(prefix, roles_path="roles"): | ||||
|     """ | ||||
|     Returns a list of role names under the given roles_path | ||||
|     that start with the specified prefix. | ||||
|  | ||||
|     :param prefix: String prefix to match role names. | ||||
|     :param roles_path: Path to the roles directory (default: 'roles'). | ||||
|     :return: List of matching role names. | ||||
|     """ | ||||
|     if not os.path.isdir(roles_path): | ||||
|         return [] | ||||
|  | ||||
|     roles = [] | ||||
|     for entry in os.listdir(roles_path): | ||||
|         full_path = os.path.join(roles_path, entry) | ||||
|         if os.path.isdir(full_path) and entry.startswith(prefix): | ||||
|             roles.append(entry) | ||||
|  | ||||
|     return sorted(roles) | ||||
|  | ||||
| class FilterModule(object): | ||||
|     """ Custom filters for Ansible """ | ||||
|  | ||||
|     def filters(self): | ||||
|         return { | ||||
|             "get_category_entries": get_category_entries | ||||
|         } | ||||
							
								
								
									
										85
									
								
								tests/unit/filter_plugins/test_get_category_entries.py
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										85
									
								
								tests/unit/filter_plugins/test_get_category_entries.py
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,85 @@ | ||||
| # Unit tests for the get_category_entries Ansible filter plugin (unittest version). | ||||
|  | ||||
| import os | ||||
| import unittest | ||||
| import tempfile | ||||
| import shutil | ||||
| from pathlib import Path | ||||
|  | ||||
| from filter_plugins.get_category_entries import get_category_entries | ||||
|  | ||||
|  | ||||
| class TestGetCategoryEntries(unittest.TestCase): | ||||
|     def setUp(self): | ||||
|         # Create an isolated temp directory for each test | ||||
|         self._tmpdir = tempfile.TemporaryDirectory() | ||||
|         self.tmp = Path(self._tmpdir.name) | ||||
|  | ||||
|     def tearDown(self): | ||||
|         # Clean up the temp directory | ||||
|         self._tmpdir.cleanup() | ||||
|  | ||||
|     def test_returns_empty_when_roles_dir_missing(self): | ||||
|         """If the roles directory does not exist, the filter must return an empty list.""" | ||||
|         missing_dir = self.tmp / "no_such_roles_dir" | ||||
|         self.assertFalse(missing_dir.exists()) | ||||
|         self.assertEqual(get_category_entries("docker-", roles_path=str(missing_dir)), []) | ||||
|  | ||||
|     def test_matches_prefix_and_sorts(self): | ||||
|         """ | ||||
|         The filter should return only directory names starting with the prefix, | ||||
|         and the result must be sorted. | ||||
|         """ | ||||
|         roles_dir = self.tmp / "roles" | ||||
|         roles_dir.mkdir() | ||||
|  | ||||
|         # Create role directories | ||||
|         (roles_dir / "docker-nginx").mkdir() | ||||
|         (roles_dir / "docker-postgres").mkdir() | ||||
|         (roles_dir / "web-app-keycloak").mkdir() | ||||
|         (roles_dir / "docker-redis").mkdir() | ||||
|  | ||||
|         # A file that should be ignored | ||||
|         (roles_dir / "docker-file").write_text("not a directory") | ||||
|  | ||||
|         result = get_category_entries("docker-", roles_path=str(roles_dir)) | ||||
|         self.assertEqual(result, ["docker-nginx", "docker-postgres", "docker-redis"]) | ||||
|  | ||||
|     def test_ignores_non_directories(self): | ||||
|         """Non-directory entries under roles/ must be ignored.""" | ||||
|         roles_dir = self.tmp / "roles" | ||||
|         roles_dir.mkdir() | ||||
|  | ||||
|         (roles_dir / "docker-engine").mkdir() | ||||
|         (roles_dir / "docker-engine.txt").write_text("file, should be ignored") | ||||
|  | ||||
|         result = get_category_entries("docker-", roles_path=str(roles_dir)) | ||||
|         self.assertEqual(result, ["docker-engine"]) | ||||
|  | ||||
|     def test_respects_custom_roles_path(self): | ||||
|         """When roles_path is provided, the filter should use it instead of 'roles'.""" | ||||
|         custom_roles = self.tmp / "custom" / "rolesdir" | ||||
|         custom_roles.mkdir(parents=True) | ||||
|  | ||||
|         (custom_roles / "docker-a").mkdir() | ||||
|         (custom_roles / "docker-b").mkdir() | ||||
|         (custom_roles / "other-c").mkdir() | ||||
|  | ||||
|         result = get_category_entries("docker-", roles_path=str(custom_roles)) | ||||
|         self.assertEqual(result, ["docker-a", "docker-b"]) | ||||
|  | ||||
|     def test_empty_prefix_returns_all_roles_sorted(self): | ||||
|         """If an empty prefix is passed, the filter should return all role directories (sorted).""" | ||||
|         roles_dir = self.tmp / "roles" | ||||
|         roles_dir.mkdir() | ||||
|  | ||||
|         (roles_dir / "a-role").mkdir() | ||||
|         (roles_dir / "c-role").mkdir() | ||||
|         (roles_dir / "b-role").mkdir() | ||||
|  | ||||
|         result = get_category_entries("", roles_path=str(roles_dir)) | ||||
|         self.assertEqual(result, ["a-role", "b-role", "c-role"]) | ||||
|  | ||||
|  | ||||
| if __name__ == "__main__": | ||||
|     unittest.main() | ||||
		Reference in New Issue
	
	Block a user