1
0
Fork 0
mirror of https://github.com/ansible-collections/community.general.git synced 2024-09-14 20:13:21 +02:00

dconf: three minor but useful fixes (#6206)

* dconf: Correctly handle setting a key that has no value in DB

We need to check if the value in the database is None before we try to
parse it, because the GVariant parser won't accept None as an input
value. By definition if the value is None, i.e., there's no value in
the database, than any value the user is trying to set is a change, so
just indicate that it's a change without trying to compare the None to
whatever the user specified as the value.x

* dconf: Give a more useful error when writing a key fails

if writing a key fails, then include in the error that is returned the
exact key and value aguments that were given to the dconf command, to
assist in diagnosing failures caused by providing the key or value in
the wrong format.x

* dconf: Convert boolean values into the format that dconf expects

Even though we warn users to be careful to specify GVariant strings
for values, a common error is to be trying to specify a boolean string
which ends up getting converted into a boolean by the YAML parser or
Ansible. Then it gets converted to "True" or "False", the string
representations of Python booleans, which are not valid GVariants.

Rather than just failing with an obscure error when this happens,
let's be more user-friendly and detect when the user has specified a
boolean and convert it into the correct GVariant forms, "true" or
"false", so it just works. There's no good reason to be more pedantic
than that.
This commit is contained in:
Jonathan Kamens 2023-04-13 00:52:14 -04:00 committed by GitHub
parent 86f9a657e7
commit a5765143f1
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
2 changed files with 28 additions and 3 deletions

View file

@ -0,0 +1,2 @@
minor_changes:
- "dconf - be forgiving about boolean values: convert them to GVariant booleans automatically (https://github.com/ansible-collections/community.general/pull/6206)."

View file

@ -70,13 +70,18 @@ options:
description: description:
- A dconf key to modify or read from the dconf database. - A dconf key to modify or read from the dconf database.
value: value:
type: str type: raw
required: false required: false
description: description:
- Value to set for the specified dconf key. Value should be specified in - Value to set for the specified dconf key. Value should be specified in
GVariant format. Due to complexity of this format, it is best to have a GVariant format. Due to complexity of this format, it is best to have a
look at existing values in the dconf database. look at existing values in the dconf database.
- Required for I(state=present). - Required for I(state=present).
- Although the type is specified as "raw", it should typically be
specified as a string. However, boolean values in particular are
handled properly even when specified as booleans rather than strings
(in fact, handling booleans properly is why the type of this parameter
is "raw").
state: state:
type: str type: str
required: false required: false
@ -155,6 +160,7 @@ except ImportError:
HAS_PSUTIL = False HAS_PSUTIL = False
from ansible.module_utils.basic import AnsibleModule, missing_required_lib from ansible.module_utils.basic import AnsibleModule, missing_required_lib
from ansible.module_utils.common.text.converters import to_native
class DBusWrapper(object): class DBusWrapper(object):
@ -288,6 +294,10 @@ class DconfPreference(object):
Returns True if the two values are equal. Returns True if the two values are equal.
""" """
if canonical_value is None:
# It's unset in dconf database, so anything the user is trying to
# set is a change.
return False
try: try:
variant1 = Variant.parse(None, canonical_value) variant1 = Variant.parse(None, canonical_value)
variant2 = Variant.parse(variant1.get_type(), user_value) variant2 = Variant.parse(variant1.get_type(), user_value)
@ -349,7 +359,7 @@ class DconfPreference(object):
rc, out, err = dbus_wrapper.run_command(command) rc, out, err = dbus_wrapper.run_command(command)
if rc != 0: if rc != 0:
self.module.fail_json(msg='dconf failed while write the value with error: %s' % err, self.module.fail_json(msg='dconf failed while writing key %s, value %s with error: %s' % (key, value, err),
out=out, out=out,
err=err) err=err)
@ -401,11 +411,24 @@ def main():
argument_spec=dict( argument_spec=dict(
state=dict(default='present', choices=['present', 'absent', 'read']), state=dict(default='present', choices=['present', 'absent', 'read']),
key=dict(required=True, type='str', no_log=False), key=dict(required=True, type='str', no_log=False),
value=dict(required=False, default=None, type='str'), # Converted to str below after special handling of bool.
value=dict(required=False, default=None, type='raw'),
), ),
supports_check_mode=True supports_check_mode=True
) )
# Try to be forgiving about the user specifying a boolean as the value, or
# more accurately about the fact that YAML and Ansible are quite insistent
# about converting strings that look like booleans into booleans. Convert
# the boolean into a string of the type dconf will understand. Any type for
# the value other than boolean is just converted into a string directly.
if module.params['value'] is not None:
if isinstance(module.params['value'], bool):
module.params['value'] = 'true' if module.params['value'] else 'false'
else:
module.params['value'] = to_native(
module.params['value'], errors='surrogate_or_strict')
if Variant is None: if Variant is None:
module.warn( module.warn(
'WARNING: The gi.repository Python library is not available; ' 'WARNING: The gi.repository Python library is not available; '