1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
|
#!/usr/bin/python
# -*- coding: utf-8 -*-
# Copyright (c) 2017, Joseph Benden <joe@benden.us>
#
# GNU General Public License v3.0+ (see LICENSES/GPL-3.0-or-later.txt or https://www.gnu.org/licenses/gpl-3.0.txt)
# SPDX-License-Identifier: GPL-3.0-or-later
from __future__ import absolute_import, division, print_function
__metaclass__ = type
DOCUMENTATION = '''
module: xfconf
author:
- "Joseph Benden (@jbenden)"
- "Alexei Znamensky (@russoz)"
short_description: Edit XFCE4 Configurations
description:
- This module allows for the manipulation of Xfce 4 Configuration with the help of
xfconf-query. Please see the xfconf-query(1) man page for more details.
seealso:
- name: xfconf-query(1) man page
description: Manual page of the C(xfconf-query) tool at the XFCE documentation site.
link: 'https://docs.xfce.org/xfce/xfconf/xfconf-query'
- name: xfconf - Configuration Storage System
description: XFCE documentation for the Xfconf configuration system.
link: 'https://docs.xfce.org/xfce/xfconf/start'
extends_documentation_fragment:
- community.general.attributes
attributes:
check_mode:
support: full
diff_mode:
support: full
options:
channel:
description:
- A Xfconf preference channel is a top-level tree key, inside of the
Xfconf repository that corresponds to the location for which all
application properties/keys are stored. See man xfconf-query(1).
required: true
type: str
property:
description:
- A Xfce preference key is an element in the Xfconf repository
that corresponds to an application preference. See man xfconf-query(1).
required: true
type: str
value:
description:
- Preference properties typically have simple values such as strings,
integers, or lists of strings and integers. See man xfconf-query(1).
type: list
elements: raw
value_type:
description:
- The type of value being set.
- When providing more than one O(value_type), the length of the list must
be equal to the length of O(value).
- If only one O(value_type) is provided, but O(value) contains more than
on element, that O(value_type) will be applied to all elements of O(value).
- If the O(property) being set is an array and it can possibly have only one
element in the array, then O(force_array=true) must be used to ensure
that C(xfconf-query) will interpret the value as an array rather than a
scalar.
- Support for V(uchar), V(char), V(uint64), and V(int64) has been added in community.general 4.8.0.
type: list
elements: str
choices: [ string, int, double, bool, uint, uchar, char, uint64, int64, float ]
state:
type: str
description:
- The action to take upon the property/value.
- The state V(get) has been removed in community.general 5.0.0. Please use the module M(community.general.xfconf_info) instead.
choices: [ present, absent ]
default: "present"
force_array:
description:
- Force array even if only one element.
type: bool
default: false
aliases: ['array']
version_added: 1.0.0
'''
EXAMPLES = """
- name: Change the DPI to "192"
xfconf:
channel: "xsettings"
property: "/Xft/DPI"
value_type: "int"
value: "192"
- name: Set workspace names (4)
xfconf:
channel: xfwm4
property: /general/workspace_names
value_type: string
value: ['Main', 'Work1', 'Work2', 'Tmp']
- name: Set workspace names (1)
xfconf:
channel: xfwm4
property: /general/workspace_names
value_type: string
value: ['Main']
force_array: true
"""
RETURN = '''
channel:
description: The channel specified in the module parameters
returned: success
type: str
sample: "xsettings"
property:
description: The property specified in the module parameters
returned: success
type: str
sample: "/Xft/DPI"
value_type:
description:
- The type of the value that was changed (V(none) for O(state=reset)).
Either a single string value or a list of strings for array types.
- This is a string or a list of strings.
returned: success
type: any
sample: '"int" or ["str", "str", "str"]'
value:
description:
- The value of the preference key after executing the module. Either a
single string value or a list of strings for array types.
- This is a string or a list of strings.
returned: success
type: any
sample: '"192" or ["orange", "yellow", "violet"]'
previous_value:
description:
- The value of the preference key before executing the module.
Either a single string value or a list of strings for array types.
- This is a string or a list of strings.
returned: success
type: any
sample: '"96" or ["red", "blue", "green"]'
cmd:
description:
- A list with the resulting C(xfconf-query) command executed by the module.
returned: success
type: list
elements: str
version_added: 5.4.0
sample:
- /usr/bin/xfconf-query
- --channel
- xfce4-panel
- --property
- /plugins/plugin-19/timezone
- --create
- --type
- string
- --set
- Pacific/Auckland
'''
from ansible_collections.community.general.plugins.module_utils.module_helper import StateModuleHelper
from ansible_collections.community.general.plugins.module_utils.xfconf import xfconf_runner
class XFConfProperty(StateModuleHelper):
change_params = ('value', )
diff_params = ('value', )
output_params = ('property', 'channel', 'value')
module = dict(
argument_spec=dict(
state=dict(type='str', choices=("present", "absent"), default="present"),
channel=dict(type='str', required=True),
property=dict(type='str', required=True),
value_type=dict(type='list', elements='str',
choices=('string', 'int', 'double', 'bool', 'uint', 'uchar', 'char', 'uint64', 'int64', 'float')),
value=dict(type='list', elements='raw'),
force_array=dict(type='bool', default=False, aliases=['array']),
),
required_if=[('state', 'present', ['value', 'value_type'])],
required_together=[('value', 'value_type')],
supports_check_mode=True,
)
default_state = 'present'
def __init_module__(self):
self.runner = xfconf_runner(self.module)
self.does_not = 'Property "{0}" does not exist on channel "{1}".'.format(self.vars.property,
self.vars.channel)
self.vars.set('previous_value', self._get())
self.vars.set('type', self.vars.value_type)
self.vars.meta('value').set(initial_value=self.vars.previous_value)
def process_command_output(self, rc, out, err):
if err.rstrip() == self.does_not:
return None
if rc or len(err):
self.do_raise('xfconf-query failed with error (rc={0}): {1}'.format(rc, err))
result = out.rstrip()
if "Value is an array with" in result:
result = result.split("\n")
result.pop(0)
result.pop(0)
return result
def _get(self):
with self.runner('channel property', output_process=self.process_command_output) as ctx:
return ctx.run()
def state_absent(self):
with self.runner('channel property reset', check_mode_skip=True) as ctx:
ctx.run(reset=True)
self.vars.stdout = ctx.results_out
self.vars.stderr = ctx.results_err
self.vars.cmd = ctx.cmd
if self.verbosity >= 4:
self.vars.run_info = ctx.run_info
self.vars.value = None
def state_present(self):
# stringify all values - in the CLI they will all be happy strings anyway
# and by doing this here the rest of the code can be agnostic to it
self.vars.value = [str(v) for v in self.vars.value]
value_type = self.vars.value_type
values_len = len(self.vars.value)
types_len = len(value_type)
if types_len == 1:
# use one single type for the entire list
value_type = value_type * values_len
elif types_len != values_len:
# or complain if lists' lengths are different
self.do_raise('Number of elements in "value" and "value_type" must be the same')
# calculates if it is an array
self.vars.is_array = \
bool(self.vars.force_array) or \
isinstance(self.vars.previous_value, list) or \
values_len > 1
with self.runner('channel property create force_array values_and_types', check_mode_skip=True) as ctx:
ctx.run(create=True, force_array=self.vars.is_array, values_and_types=(self.vars.value, value_type))
self.vars.stdout = ctx.results_out
self.vars.stderr = ctx.results_err
self.vars.cmd = ctx.cmd
if self.verbosity >= 4:
self.vars.run_info = ctx.run_info
if not self.vars.is_array:
self.vars.value = self.vars.value[0]
self.vars.type = value_type[0]
else:
self.vars.type = value_type
def main():
XFConfProperty.execute()
if __name__ == '__main__':
main()
|