-
Notifications
You must be signed in to change notification settings - Fork 183
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Add configuration variable expansion #681
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1 @@ | ||
secret-password |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,28 @@ | ||
# -*- coding: utf-8 -*- | ||
# (c) 2023 The mqttwarn developers | ||
# | ||
# mqttwarn configuration file for testing variable expansion. | ||
# | ||
|
||
; ------- | ||
; General | ||
; ------- | ||
|
||
[defaults] | ||
hostname = $ENV:HOSTNAME | ||
port = $ENV:PORT | ||
username = ${ENV:USERNAME} | ||
password = ${FILE:./password.txt} | ||
|
||
; name the service providers you will be using. | ||
launch = file | ||
|
||
|
||
; -------- | ||
; Services | ||
; -------- | ||
|
||
[config:file] | ||
targets = { | ||
'mylog' : [ '$ENV:LOG_FILE' ], | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,13 +1,15 @@ | ||
# -*- coding: utf-8 -*- | ||
# (c) 2022 The mqttwarn developers | ||
import os | ||
import re | ||
import ssl | ||
from unittest.mock import Mock, call | ||
from unittest.mock import Mock, call, patch | ||
|
||
import pytest | ||
|
||
import mqttwarn.configuration | ||
from mqttwarn.configuration import load_configuration | ||
from tests import configfile_better_addresses | ||
from tests import configfile_better_addresses, configfile_with_variables | ||
|
||
|
||
def test_config_with_ssl(): | ||
|
@@ -81,3 +83,85 @@ def test_config_better_addresses_pushsafer(): | |
assert apprise_service_targets["nagios"]["device"] == "52|65|78" | ||
assert apprise_service_targets["nagios"]["priority"] == 2 | ||
assert apprise_service_targets["tracking"]["device"] == "gs23" | ||
|
||
|
||
@patch.dict(os.environ, {"HOSTNAME": "example.com", "PORT": "3000", "USERNAME": "bob", "LOG_FILE": "/tmp/out.log"}) | ||
def test_config_expand_variables(): | ||
""" | ||
Verify reading configuration file expands variables. | ||
""" | ||
config = load_configuration(configfile_with_variables) | ||
assert config.hostname == "example.com" | ||
assert config.port == 3000 | ||
assert config.username == "bob" | ||
assert config.password == "secret-password" | ||
assert config.getdict("config:file", "targets")["mylog"][0] == "/tmp/out.log" | ||
|
||
|
||
@pytest.mark.parametrize( | ||
"input, expected", | ||
[ | ||
("my-password", "my-password"), | ||
("$SRC_1:PASSWORD_1", "my-password"), | ||
("$SRC_1:PASSWORD_2", "super-secret"), | ||
("-->$SRC_1:PASSWORD_1<--", "-->my-password<--"), | ||
("$SRC_2:PASSWORD_1", "p4ssw0rd"), | ||
("$SRC_1:PÄSSWÖRD_3", "non-ascii-secret"), | ||
("${SRC_1:PASSWORD_1}", "my-password"), | ||
("${SRC_1:/path/to/password.txt}", "file-contents"), | ||
("${SRC_1:PASSWORD_1} ${SRC_1:PASSWORD_2}", "my-password super-secret"), | ||
("$SRC_1:PASSWORD_1 ${SRC_1:/path/to/password.txt} $SRC_1:PASSWORD_1", "my-password file-contents my-password"), | ||
( | ||
"${SRC_1:/path/to/password.txt} $SRC_1:PASSWORD_1 ${SRC_1:/path/to/password.txt}", | ||
"file-contents my-password file-contents", | ||
), | ||
("/$SRC_1:PASSWORD_1/$SRC_1:PASSWORD_2/foo.txt", "/my-password/super-secret/foo.txt"), | ||
], | ||
) | ||
def test_expand_vars_ok(input, expected): | ||
""" | ||
Verify that `expand_vars` expands variables in configuration. | ||
""" | ||
|
||
def create_source(variables): | ||
return lambda name: variables[name] | ||
|
||
sources = { | ||
"SRC_1": create_source( | ||
{ | ||
"PASSWORD_1": "my-password", | ||
"PASSWORD_2": "super-secret", | ||
"PÄSSWÖRD_3": "non-ascii-secret", | ||
"/path/to/password.txt": "file-contents", | ||
} | ||
), | ||
"SRC_2": create_source( | ||
{ | ||
"PASSWORD_1": "p4ssw0rd", | ||
} | ||
), | ||
} | ||
expanded = mqttwarn.configuration.expand_vars(input, sources) | ||
assert expanded == expected | ||
|
||
|
||
def test_expand_vars_variable_type_not_supported(): | ||
""" | ||
Verify that `expand_vars` raises error when variable type is not supported. | ||
""" | ||
with pytest.raises( | ||
KeyError, match=re.escape("$DOES_NOT_EXIST:VARIABLE: Variable type 'DOES_NOT_EXIST' not supported") | ||
): | ||
mqttwarn.configuration.expand_vars("-->$DOES_NOT_EXIST:VARIABLE<--", {}) | ||
|
||
|
||
def test_expand_vars_variable_not_found(): | ||
""" | ||
Verify that `expand_vars` raises error when variable is not in source. | ||
""" | ||
|
||
def empty_source(name): | ||
raise KeyError("Variable not found") | ||
|
||
with pytest.raises(KeyError, match=re.escape("$SRC_1:VARIABLE: 'Variable not found'")): | ||
mqttwarn.configuration.expand_vars("-->$SRC_1:VARIABLE<--", {"SRC_1": empty_source}) | ||
Comment on lines
+166
to
+167
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. If my statement above is true, we may have a leak in the suite between test functions. I.e., the types There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. These test functions shouldn't affect each other as there is no global state used in Here in this test function we're passing in a new dict of sources I tried moving [nix-shell:~/mqttwarn]$ pytest --no-header --disable-warnings --no-cov -k test_expand_vars
=================================================== test session starts ===================================================
collected 318 items / 304 deselected / 1 skipped / 14 selected
tests/test_configuration.py::test_expand_vars_variable_not_found PASSED [ 7%]
tests/test_configuration.py::test_expand_vars_ok[my-password-my-password] PASSED [ 14%]
tests/test_configuration.py::test_expand_vars_ok[$SRC_1:PASSWORD_1-my-password] PASSED [ 21%]
tests/test_configuration.py::test_expand_vars_ok[$SRC_1:PASSWORD_2-super-secret] PASSED [ 28%]
tests/test_configuration.py::test_expand_vars_ok[-->$SRC_1:PASSWORD_1<----->my-password<--] PASSED [ 35%]
tests/test_configuration.py::test_expand_vars_ok[$SRC_2:PASSWORD_1-p4ssw0rd] PASSED [ 42%]
tests/test_configuration.py::test_expand_vars_ok[$SRC_1:P\xc4SSW\xd6RD_3-non-ascii-secret] PASSED [ 50%]
tests/test_configuration.py::test_expand_vars_ok[${SRC_1:PASSWORD_1}-my-password] PASSED [ 57%]
tests/test_configuration.py::test_expand_vars_ok[${SRC_1:/path/to/password.txt}-file-contents] PASSED [ 64%]
tests/test_configuration.py::test_expand_vars_ok[${SRC_1:PASSWORD_1} ${SRC_1:PASSWORD_2}-my-password super-secret] PASSED [ 71%]
tests/test_configuration.py::test_expand_vars_ok[$SRC_1:PASSWORD_1 ${SRC_1:/path/to/password.txt} $SRC_1:PASSWORD_1-my-password file-contents my-password] PASSED [ 78%]
tests/test_configuration.py::test_expand_vars_ok[${SRC_1:/path/to/password.txt} $SRC_1:PASSWORD_1 ${SRC_1:/path/to/password.txt}-file-contents my-password file-contents] PASSED [ 85%]
tests/test_configuration.py::test_expand_vars_ok[/$SRC_1:PASSWORD_1/$SRC_1:PASSWORD_2/foo.txt-/my-password/super-secret/foo.txt] PASSED [ 92%]
tests/test_configuration.py::test_expand_vars_variable_type_not_supported PASSED [100%]
================================================= short test summary info =================================================
SKIPPED [1] tests/services/test_apns.py:11: The `apns` package is not ready for Python3
================================ 14 passed, 1 skipped, 304 deselected, 1 warning in 1.06s ================================= There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I see, probably missed to spot the point. Thanks for clarifying! |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
SRC_1
andSRC_2
are two synthetic variable interpolation types likeENV
orFILE
, but only used within the test suite?There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yes. I'm testing
expand_vars()
function here directly, bypassing concrete implementation ofENV
andFILE
sources, so I've replaced them with these fakes.