Skip to content

Commit

Permalink
isso: config: Add support for environment variables in config
Browse files Browse the repository at this point in the history
- Updated `IssoParser` to support environment variable substitution.
- Enhanced documentation to include details on using environment variables in the configuration file.
- Added unit tests to verify the functionality of environment variable substitution in `IssoParser`.

Closes #397
  • Loading branch information
pkvach committed Sep 27, 2024
1 parent 6f3874c commit 246b135
Show file tree
Hide file tree
Showing 3 changed files with 77 additions and 0 deletions.
22 changes: 22 additions & 0 deletions docs/docs/reference/server-config.rst
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
Server Configuration
====================


The Isso configuration file is an `INI-style`__ textfile. It reads integers,
booleans, strings and lists. Here's the default isso configuration:
`isso.cfg <https://github.com/isso-comments/isso/blob/master/isso/isso.cfg>`_. A
Expand Down Expand Up @@ -572,3 +573,24 @@ Booleans
``on``/``off`` etc.

.. _getboolean: https://docs.python.org/3/library/configparser.html#configparser.ConfigParser.getboolean

Environment Variables
^^^^^^^^^^^^^^^^^^^^
.. versionadded:: 0.13.1

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.

Example:

.. code-block:: ini
:caption: ``isso.cfg``
[general]
dbpath = /var/lib/isso/comments.db
host = https://example.tld/
[smtp]
username = $SMTP_USERNAME
password = ${SMTP_PASSWORD}
In this example, the values for ``username`` and ``password`` will be taken from the environment variables ``SMTP_USERNAME`` and ``SMTP_PASSWORD``, respectively.
6 changes: 6 additions & 0 deletions isso/config.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@

import datetime
import logging
import os
import pkg_resources
import re

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

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

def get(self, section, key, **kwargs):
value = super(IssoParser, self).get(section, key, **kwargs)
return os.path.expandvars(value)

def getint(self, section, key):
try:
delta = timedelta(self.get(section, key))
Expand Down
49 changes: 49 additions & 0 deletions isso/tests/test_config.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@

import unittest
import io
import os

from isso import config

Expand Down Expand Up @@ -34,3 +35,51 @@ def test_parser(self):
# Section.get() should function the same way as plain IssoParser
foosection = parser.section("foo")
self.assertEqual(foosection.get("password"), '%s%%foo')

def test_parser_with_environment_variables(self):

parser = config.IssoParser()
parser.read_file(io.StringIO("""
[foo]
bar = $TEST_ENV_VAR
baz = ${TEST_ENV_VAR2}
"""))

# Set environment variables
os.environ['TEST_ENV_VAR'] = 'test_value'
os.environ['TEST_ENV_VAR2'] = 'another_test_value'

# Test environment variable expansion
self.assertEqual(parser.get("foo", "bar"), 'test_value')
self.assertEqual(parser.get("foo", "baz"), 'another_test_value')

# Test Section.get() with environment variables
foosection = parser.section("foo")
self.assertEqual(foosection.get("bar"), 'test_value')
self.assertEqual(foosection.get("baz"), 'another_test_value')

# Clean up environment variables
del os.environ['TEST_ENV_VAR']
del os.environ['TEST_ENV_VAR2']

def test_parser_with_missing_environment_variables(self):

parser = config.IssoParser()
parser.read_file(io.StringIO("""
[foo]
bar = $MISSING_ENV_VAR
"""))

self.assertEqual(parser.get("foo", "bar"), '$MISSING_ENV_VAR')

def test_parser_with_special_characters_in_environment_variables(self):

os.environ['SPECIAL_ENV_VAR'] = 'value_with_$pecial_characters'
parser = config.IssoParser()
parser.read_file(io.StringIO("""
[foo]
bar = $SPECIAL_ENV_VAR
"""))

self.assertEqual(parser.get("foo", "bar"), 'value_with_$pecial_characters')
del os.environ['SPECIAL_ENV_VAR']

0 comments on commit 246b135

Please sign in to comment.