Skip to content

Commit 56c05cb

Browse files
authored
Merge pull request #1037 from pkvach/feat/config-env-var-support
isso: config: Add support for environment variables in config
2 parents 6c812cd + 0ee2758 commit 56c05cb

4 files changed

Lines changed: 78 additions & 0 deletions

File tree

CHANGES.rst

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@ New Features
1414
- Add support for comment search by Thread URL in admin interface (`#1020`_, pkvach)
1515
- Add sorting option for comments (`#1005`_, pkvach)
1616
- admin: Add log out button (`#870`_, bbaovanc)
17+
- Add support for environment variables in config (`#1037`_, pkvach)
1718

1819
.. _#870: https://github.com/posativ/isso/pull/870
1920
.. _#966: https://github.com/posativ/isso/pull/966
@@ -22,6 +23,7 @@ New Features
2223
.. _#1001: https://github.com/isso-comments/isso/pull/1001
2324
.. _#1020: https://github.com/isso-comments/isso/pull/1020
2425
.. _#1005: https://github.com/isso-comments/isso/pull/1005
26+
.. _#1037: https://github.com/isso-comments/isso/pull/1037
2527

2628
Breaking Changes
2729
^^^^^^^^^^^^^^^^

docs/docs/reference/server-config.rst

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -572,3 +572,24 @@ Booleans
572572
``on``/``off`` etc.
573573

574574
.. _getboolean: https://docs.python.org/3/library/configparser.html#configparser.ConfigParser.getboolean
575+
576+
Environment Variables
577+
^^^^^^^^^^^^^^^^^^^^^
578+
.. versionadded:: 0.13.1
579+
580+
You can use environment variables in the configuration file. This is useful for keeping sensitive information, such as passwords, out of the configuration file itself. Environment variables are referenced using the ``$VAR_NAME`` or ``${VAR_NAME}`` syntax.
581+
582+
Example:
583+
584+
.. code-block:: ini
585+
:caption: ``isso.cfg``
586+
587+
[general]
588+
dbpath = /var/lib/isso/comments.db
589+
host = https://example.tld/
590+
591+
[smtp]
592+
username = $SMTP_USERNAME
593+
password = ${SMTP_PASSWORD}
594+
595+
In this example, the values for ``username`` and ``password`` will be taken from the environment variables ``SMTP_USERNAME`` and ``SMTP_PASSWORD``, respectively.

isso/config.py

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22

33
import datetime
44
import logging
5+
import os
56
import pkg_resources
67
import re
78

@@ -82,6 +83,7 @@ class IssoParser(ConfigParser):
8283
* Parse human-readable timedelta such as "15m" as "15 minutes"
8384
* Handle indented lines as "lists"
8485
* Disable string interpolation ('%s') for values
86+
* Support environment variable substitution
8587
"""
8688

8789
def __init__(self, *args, **kwargs):
@@ -95,6 +97,10 @@ def __init__(self, *args, **kwargs):
9597
return super(IssoParser, self).__init__(
9698
allow_no_value=True, interpolation=None, *args, **kwargs)
9799

100+
def get(self, section, key, **kwargs):
101+
value = super(IssoParser, self).get(section, key, **kwargs)
102+
return os.path.expandvars(value)
103+
98104
def getint(self, section, key):
99105
try:
100106
delta = timedelta(self.get(section, key))

isso/tests/test_config.py

Lines changed: 49 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22

33
import unittest
44
import io
5+
import os
56

67
from isso import config
78

@@ -34,3 +35,51 @@ def test_parser(self):
3435
# Section.get() should function the same way as plain IssoParser
3536
foosection = parser.section("foo")
3637
self.assertEqual(foosection.get("password"), '%s%%foo')
38+
39+
def test_parser_with_environment_variables(self):
40+
41+
parser = config.IssoParser()
42+
parser.read_file(io.StringIO("""
43+
[foo]
44+
bar = $TEST_ENV_VAR
45+
baz = ${TEST_ENV_VAR2}
46+
"""))
47+
48+
# Set environment variables
49+
os.environ['TEST_ENV_VAR'] = 'test_value'
50+
os.environ['TEST_ENV_VAR2'] = 'another_test_value'
51+
52+
# Test environment variable expansion
53+
self.assertEqual(parser.get("foo", "bar"), 'test_value')
54+
self.assertEqual(parser.get("foo", "baz"), 'another_test_value')
55+
56+
# Test Section.get() with environment variables
57+
foosection = parser.section("foo")
58+
self.assertEqual(foosection.get("bar"), 'test_value')
59+
self.assertEqual(foosection.get("baz"), 'another_test_value')
60+
61+
# Clean up environment variables
62+
del os.environ['TEST_ENV_VAR']
63+
del os.environ['TEST_ENV_VAR2']
64+
65+
def test_parser_with_missing_environment_variables(self):
66+
67+
parser = config.IssoParser()
68+
parser.read_file(io.StringIO("""
69+
[foo]
70+
bar = $MISSING_ENV_VAR
71+
"""))
72+
73+
self.assertEqual(parser.get("foo", "bar"), '$MISSING_ENV_VAR')
74+
75+
def test_parser_with_special_characters_in_environment_variables(self):
76+
77+
os.environ['SPECIAL_ENV_VAR'] = 'value_with_$pecial_characters'
78+
parser = config.IssoParser()
79+
parser.read_file(io.StringIO("""
80+
[foo]
81+
bar = $SPECIAL_ENV_VAR
82+
"""))
83+
84+
self.assertEqual(parser.get("foo", "bar"), 'value_with_$pecial_characters')
85+
del os.environ['SPECIAL_ENV_VAR']

0 commit comments

Comments
 (0)