diff --git a/filter_plugins/safe_var.py b/filter_plugins/safe_var.py new file mode 100644 index 00000000..df82f323 --- /dev/null +++ b/filter_plugins/safe_var.py @@ -0,0 +1,27 @@ +# file: filter_plugins/safe_var.py + +from jinja2 import Undefined + +def safe_var(value): + """ + Returns the original value unless it is None or Jinja2‐Undefined. + Catches all exceptions and returns an empty string on error. + """ + try: + # If the value is an Undefined from Jinja2, treat it as missing + if isinstance(value, Undefined): + return '' + # Treat None as missing as well + if value is None: + return '' + # Otherwise return the actual value + return value + except Exception: + # Catch any other errors and return empty string + return '' + +class FilterModule(object): + def filters(self): + return { + 'safe_var': safe_var + } diff --git a/group_vars/all/15_about.yml b/group_vars/all/15_about.yml index f3d1ecc3..aa0b86de 100644 --- a/group_vars/all/15_about.yml +++ b/group_vars/all/15_about.yml @@ -9,12 +9,18 @@ defaults_service_provider: city: "Cybertown" postal_code: "00001" country: "Nexusland" - logo: "{{applications.assets_server.url}}/logo.png" + logo: >- + {{ (applications.assets_server.url | safe_var ~ '/logo.png') + if applications.assets_server.url | safe_var else '' }} platform: titel: "CyMaIS Demo" subtitel: "The Future of Self-Hosted Infrastructure. Secure. Automated. Sovereign." - logo: "{{applications.assets_server.url}}/img/logo.png" - favicon: "{{applications.assets_server.url}}/img/favicon.ico" + logo: >- + {{ (applications.assets_server.url | safe_var ~ '/logo.png') + if applications.assets_server.url | safe_var else '' }} + favicon: >- + {{ (applications.assets_server.url | safe_var ~ '/favicon.ico') + if applications.assets_server.url | safe_var else '' }} contact: bluesky: >- {{ ('@' ~ users.administrator.username ~ '.' ~ domains[application_id]['api']) diff --git a/roles/nginx-serve-assets/vars/configuration.yml b/roles/nginx-serve-assets/vars/configuration.yml index 10bc1bc5..eda96980 100644 --- a/roles/nginx-serve-assets/vars/configuration.yml +++ b/roles/nginx-serve-assets/vars/configuration.yml @@ -1,2 +1,4 @@ -source_directory: "{{ playbook_dir }}/assets" # Directory from which the assets will be copied -url: "{{ web_protocol }}://{{domains.file_server}}/assets" # Public address of the assets directory \ No newline at end of file +source_directory: "{{ playbook_dir }}/assets" # Directory from which the assets will be copied +url: >- + {{ (web_protocol ~ '://' ~ domains.file_server | safe_var ~ '/assets') + if applications.assets_server.url | safe_var else '' }} diff --git a/tests/unit/test_safe_var.py b/tests/unit/test_safe_var.py new file mode 100644 index 00000000..6811bbcc --- /dev/null +++ b/tests/unit/test_safe_var.py @@ -0,0 +1,44 @@ +import unittest +import sys +import os +from jinja2 import Undefined + +# Ensure filter_plugins directory is on the path +sys.path.insert( + 0, + os.path.abspath(os.path.join(os.path.dirname(__file__), '../../filter_plugins')) +) + +from safe_var import FilterModule + +class TestSafeVarFilter(unittest.TestCase): + def setUp(self): + # Retrieve the safe_var filter function + self.filter = FilterModule().filters()['safe_var'] + + def test_returns_non_empty_string(self): + self.assertEqual(self.filter('hello'), 'hello') + + def test_returns_empty_string(self): + self.assertEqual(self.filter(''), '') + + def test_returns_empty_for_none(self): + self.assertEqual(self.filter(None), '') + + def test_returns_empty_for_jinja_undefined(self): + # Instantiate an Undefined without arguments + undef = Undefined() + self.assertEqual(self.filter(undef), '') + + def test_returns_zero_for_zero(self): + # 0 is falsey but not None or Undefined, so safe_var returns it + self.assertEqual(self.filter(0), 0) + + def test_returns_list_and_dict_unchanged(self): + data = {'key': 'value'} + self.assertEqual(self.filter(data), data) + lst = [1, 2, 3] + self.assertEqual(self.filter(lst), lst) + +if __name__ == '__main__': + unittest.main()