summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorAlexander Sulfrian <alexander.sulfrian@fu-berlin.de>2015-07-23 17:04:20 +0200
committerAlexander Sulfrian <alexander.sulfrian@fu-berlin.de>2015-07-23 17:26:13 +0200
commitf733133c835193a884edcf34e5daff6365745d21 (patch)
treec43aa445f574bb1e15843b00388914f5f7c0b9b7
parentc7e67299381df961ff8274e9b53827c2bddbb47b (diff)
downloadbcfg2-f733133c835193a884edcf34e5daff6365745d21.tar.gz
bcfg2-f733133c835193a884edcf34e5daff6365745d21.tar.bz2
bcfg2-f733133c835193a884edcf34e5daff6365745d21.zip
Options/Types: Fix database OPTIONS parsing
This is mostly from 257eb0c17 and 16d3e04cb to allow for setting arbitrary database options since some settings require nested dictionaries, etc. This got lost during merge from maint into master because of the completely different Options parsing.
-rw-r--r--doc/releases/1.4.0pre2.txt5
-rw-r--r--src/lib/Bcfg2/DBSettings.py4
-rw-r--r--src/lib/Bcfg2/Options/Types.py27
-rw-r--r--testsuite/Testsrc/Testlib/TestOptions/TestTypes.py20
4 files changed, 23 insertions, 33 deletions
diff --git a/doc/releases/1.4.0pre2.txt b/doc/releases/1.4.0pre2.txt
index a5c10777a..195f81df0 100644
--- a/doc/releases/1.4.0pre2.txt
+++ b/doc/releases/1.4.0pre2.txt
@@ -31,6 +31,11 @@ backwards-incompatible user-facing changes
This fixes potentially long client runs when comparing files that have
diverged significantly.
+* The database options in the config (options and reporting_options in database
+ section) now have to be literal python dictionaries.
+
+ This allows to set arbitrary options with nested settings.
+
Thanks
------
diff --git a/src/lib/Bcfg2/DBSettings.py b/src/lib/Bcfg2/DBSettings.py
index 5a83c25c3..1c8c34978 100644
--- a/src/lib/Bcfg2/DBSettings.py
+++ b/src/lib/Bcfg2/DBSettings.py
@@ -229,7 +229,7 @@ class _OptionContainer(object):
dest='db_schema', default='public'),
Bcfg2.Options.Option(
cf=('database', 'options'), help='Database options',
- dest='db_opts', type=Bcfg2.Options.Types.comma_dict,
+ dest='db_opts', type=Bcfg2.Options.Types.literal_dict,
default=dict()),
# reporting database options
Bcfg2.Options.Option(
@@ -258,7 +258,7 @@ class _OptionContainer(object):
Bcfg2.Options.Option(
cf=('database', 'reporting_options'),
help='Reporting database options', dest='reporting_db_opts',
- type=Bcfg2.Options.Types.comma_dict, default=dict()),
+ type=Bcfg2.Options.Types.literal_dict, default=dict()),
# Django options
Bcfg2.Options.Option(
cf=('reporting', 'time_zone'), help='Django timezone'),
diff --git a/src/lib/Bcfg2/Options/Types.py b/src/lib/Bcfg2/Options/Types.py
index ac099e135..ad2e04f10 100644
--- a/src/lib/Bcfg2/Options/Types.py
+++ b/src/lib/Bcfg2/Options/Types.py
@@ -5,6 +5,7 @@ import os
import re
import pwd
import grp
+from Bcfg2.Compat import literal_eval
_COMMA_SPLIT_RE = re.compile(r'\s*,\s*')
@@ -32,28 +33,10 @@ def colon_list(value):
return value.split(':')
-def comma_dict(value):
- """ Split an option string on commas, optionally surrounded by
- whitespace, and split the resulting items again on equals signs,
- returning a dict """
- result = dict()
- if value:
- items = comma_list(value)
- for item in items:
- if '=' in item:
- key, value = item.split(r'=', 1)
- if value in ["true", "yes", "on"]:
- result[key] = True
- elif value in ["false", "no", "off"]:
- result[key] = False
- else:
- try:
- result[key] = int(value)
- except ValueError:
- result[key] = value
- else:
- result[item] = True
- return result
+def literal_dict(value):
+ """ literally evaluate the option in order to allow for arbitrarily nested
+ dictionaries """
+ return literal_eval(value)
def anchored_regex_list(value):
diff --git a/testsuite/Testsrc/Testlib/TestOptions/TestTypes.py b/testsuite/Testsrc/Testlib/TestOptions/TestTypes.py
index 404d67fdc..0b67db38a 100644
--- a/testsuite/Testsrc/Testlib/TestOptions/TestTypes.py
+++ b/testsuite/Testsrc/Testlib/TestOptions/TestTypes.py
@@ -46,21 +46,23 @@ class TestOptionTypes(Bcfg2TestCase):
self.assertItemsEqual(self._test_options(["--test", "one:two three"]),
["one", "two three"])
- def test_comma_dict(self):
- """parse comma-dict values."""
- self.options = [Option("--test", type=Types.comma_dict)]
+ def test_literal_dict(self):
+ """parse literal-dict values."""
+ self.options = [Option("--test", type=Types.literal_dict)]
expected = {
"one": True,
"two": 2,
"three": "three",
- "four": False}
+ "four": False,
+ "five": {
+ "a": 1,
+ "b": 2
+ }}
self.assertDictEqual(
self._test_options(["--test",
- "one=yes, two=2 , three=three,four=no"]),
- expected)
-
- self.assertDictEqual(
- self._test_options(["--test", "one,two=2,three=three,four=off"]),
+ '''{ "one": True, "two": 2,
+ "three": "three", "four": False,
+ "five": { "a": 1, "b": 2 }}''']),
expected)
def test_anchored_regex_list(self):