Skip to content

Commit d63a799

Browse files
feat: implement get-facts action (#192)
Refs NethServer/dev#7549
1 parent bb35303 commit d63a799

File tree

1 file changed

+248
-0
lines changed

1 file changed

+248
-0
lines changed
Lines changed: 248 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,248 @@
1+
#!/usr/bin/env python3
2+
3+
#
4+
# Copyright (C) 2025 Nethesis S.r.l.
5+
# SPDX-License-Identifier: GPL-3.0-or-later
6+
#
7+
8+
import os
9+
import json
10+
import sys
11+
import subprocess
12+
13+
def main():
14+
facts = {}
15+
facts.update(get_addresses_facts())
16+
facts.update(get_filter_facts())
17+
facts.update(get_bypass_rules_facts())
18+
facts.update(get_mailboxes_facts())
19+
facts.update(get_public_mailboxes_facts())
20+
facts.update(get_domains_facts())
21+
facts.update(get_relay_rules_facts())
22+
facts.update(get_relay_settings_facts())
23+
facts.update(get_always_bcc_facts())
24+
facts.update(get_configuration_facts())
25+
facts.update(get_mailbox_settings_facts())
26+
facts.update(get_master_users_facts())
27+
facts.update(get_queue_settings_facts())
28+
json.dump(facts, sys.stdout)
29+
30+
def get_addresses_facts():
31+
with subprocess.Popen(["../actions/list-addresses/10list_addresses"], stdout=subprocess.PIPE) as proc:
32+
try:
33+
odata = json.load(proc.stdout)
34+
except json.JSONDecodeError:
35+
return {"get_addresses_facts_error": True}
36+
oaddresses = odata['addresses']
37+
facts = {
38+
"addresses_total_count": len(oaddresses),
39+
"adduser_domains_count": len(odata['adduser_domains']),
40+
"addgroup_domains_count": len(odata['addgroup_domains']),
41+
}
42+
atype_count_dict = dict()
43+
dtype_count_dict = dict()
44+
for adx in oaddresses:
45+
akey = f'addresses_{adx["atype"]}_count'
46+
atype_count_dict.setdefault(akey, 0)
47+
atype_count_dict[akey] += 1
48+
for ddx in adx.get('destinations', []):
49+
dkey = f'destinations_{ddx["dtype"]}_count'
50+
dtype_count_dict.setdefault(dkey, 0)
51+
dtype_count_dict[dkey] += 1
52+
facts.update(atype_count_dict)
53+
facts.update(dtype_count_dict)
54+
return facts
55+
56+
def get_filter_facts():
57+
with subprocess.Popen(["../actions/get-filter-configuration/10get_filter_configuration"], stdout=subprocess.PIPE) as proc:
58+
try:
59+
odata = json.load(proc.stdout)
60+
except json.JSONDecodeError:
61+
return {"get_filter_facts_error": True}
62+
try:
63+
del odata["antispam"]["rspamd_url"] # remove sensitive information
64+
del odata["bypass_rules"] # duplicate
65+
except:
66+
pass
67+
return {"filter": odata}
68+
69+
def get_bypass_rules_facts():
70+
with subprocess.Popen(["../actions/list-bypass-rules/10list_bypass_rules"], stdout=subprocess.PIPE) as proc:
71+
try:
72+
odata = json.load(proc.stdout)["bypass_rules"]
73+
except json.JSONDecodeError:
74+
return {"get_bypass_rules_facts_error": True}
75+
facts = {"bypass_rules_count": len(odata)}
76+
for orule in odata:
77+
bkey = f'bypass_{orule["direction"]}_{orule["type"]}_count'
78+
facts.setdefault(bkey, 0)
79+
facts[bkey] += 1
80+
return facts
81+
82+
def get_mailboxes_facts():
83+
with subprocess.Popen(["../actions/list-user-mailboxes/10list_user_mailboxes"], stdout=subprocess.PIPE) as proc:
84+
try:
85+
odata = json.load(proc.stdout)["user_mailboxes"]
86+
except json.JSONDecodeError:
87+
return {"get_mailboxes_facts_error": True}
88+
89+
disabled_users = os.getenv("DOVECOT_DISABLED_USERS", "")
90+
91+
facts = {
92+
"mailboxes_total_count": len(odata),
93+
"mailboxes_custom_spam_retention_count": 0,
94+
"mailboxes_custom_quota_count": 0,
95+
"mailboxes_forward_total_count": 0,
96+
"mailboxes_forward_keepcopy_count": 0,
97+
"mailboxes_disabled_count": len(disabled_users.split(",")) if disabled_users else 0,
98+
}
99+
for mbx in odata:
100+
if mbx.get('quota', {}).get('custom'):
101+
facts['mailboxes_custom_quota_count'] += 1
102+
if mbx.get('spam_retention', {}).get('custom'):
103+
facts['mailboxes_custom_spam_retention_count'] += 1
104+
if mbx.get('forward'):
105+
facts['mailboxes_forward_total_count'] += 1
106+
if mbx['forward'].get('keepcopy'):
107+
facts['mailboxes_forward_keepcopy_count'] += 1
108+
for fwx in mbx['forward']['destinations']:
109+
fkey = f'mailboxes_forward_{fwx["dtype"]}_count'
110+
facts.setdefault(fkey, 0)
111+
facts[fkey] += 1
112+
return facts
113+
114+
def get_public_mailboxes_facts():
115+
with subprocess.Popen(["../actions/list-public-mailboxes/10list_public_mailboxes"], stdout=subprocess.PIPE) as proc:
116+
try:
117+
odata = json.load(proc.stdout)
118+
except json.JSONDecodeError:
119+
return {"get_public_mailboxes_facts_error": True}
120+
121+
facts = {
122+
"public_mailboxes_total_count": len(odata),
123+
}
124+
return facts
125+
126+
def get_domains_facts():
127+
with subprocess.Popen(["../actions/list-domains/10list_domains"], stdout=subprocess.PIPE) as proc:
128+
try:
129+
odata = json.load(proc.stdout)
130+
except json.JSONDecodeError:
131+
return {"get_domains_facts_error": True}
132+
133+
facts = {
134+
"domains_total_count": len(odata),
135+
"domains_description_count": 0,
136+
}
137+
138+
for odomain in odata:
139+
if odomain.get("description"):
140+
facts["domains_description_count"] += 1
141+
if odomain.get("catchall"):
142+
ckey = f'domains_catchall_{odomain["catchall"]["dtype"]}_count'
143+
facts.setdefault(ckey, 0)
144+
facts[ckey] += 1
145+
146+
return facts
147+
148+
def get_relay_rules_facts():
149+
with subprocess.Popen(["../actions/list-relay-rules/10list_relays"], stdout=subprocess.PIPE) as proc:
150+
try:
151+
odata = json.load(proc.stdout)["rules"]
152+
except json.JSONDecodeError:
153+
return {"get_relay_rules_facts_error": True}
154+
155+
facts = {
156+
"relay_rules_total_count": len(odata),
157+
"relay_rules_tls_count": 0,
158+
"relay_rules_has_password_count": 0,
159+
"relay_rules_enabled_count": 0,
160+
}
161+
162+
for orule in odata:
163+
tkey = f'relay_rules_{orule["rule_type"]}_count'
164+
facts.setdefault(tkey, 0)
165+
facts[tkey] += 1
166+
if orule.get('tls'):
167+
facts['relay_rules_tls_count'] += 1
168+
if orule.get('has_password'):
169+
facts['relay_rules_has_password_count'] += 1
170+
if orule.get('enabled'):
171+
facts['relay_rules_enabled_count'] += 1
172+
173+
return facts
174+
175+
def get_relay_settings_facts():
176+
with subprocess.Popen(["../actions/get-relay-configuration/10get_relay_settings"], stdout=subprocess.PIPE) as proc:
177+
try:
178+
odata = json.load(proc.stdout)
179+
except json.JSONDecodeError:
180+
return {"get_relay_settings_facts_error": True}
181+
182+
return {
183+
"relay_settings_postfix_restricted_sender_enabled": odata.get("postfix_restricted_sender"),
184+
"relay_settings_networks_count": len(odata.get("networks", [])),
185+
}
186+
187+
def get_always_bcc_facts():
188+
with subprocess.Popen(["../actions/get-always-bcc/20read"], stdout=subprocess.PIPE) as proc:
189+
try:
190+
odata = json.load(proc.stdout)
191+
except json.JSONDecodeError:
192+
return {"get_always_bcc_facts_error": True}
193+
194+
return {
195+
"always_bcc_enabled": bool(odata.get("bcc")),
196+
}
197+
198+
def get_configuration_facts():
199+
with subprocess.Popen(["../actions/get-configuration/20read"], stdout=subprocess.PIPE) as proc:
200+
try:
201+
odata = json.load(proc.stdout)
202+
except json.JSONDecodeError:
203+
return {"get_configuration_facts_error": True}
204+
205+
return {
206+
"configuration_user_domain_schema": odata.get("user_domain", {}).get("schema"),
207+
}
208+
209+
def get_mailbox_settings_facts():
210+
with subprocess.Popen(["../actions/get-mailbox-settings/10get_mailbox_settings"], stdout=subprocess.PIPE) as proc:
211+
try:
212+
odata = json.load(proc.stdout)
213+
except json.JSONDecodeError:
214+
return {"get_mailbox_settings_facts_error": True}
215+
216+
return {
217+
"mailbox_settings_spam_prefix_enabled": bool(odata.get("spam_prefix", {}).get("enabled")),
218+
"mailbox_settings_sharedseen_enabled": bool(odata.get("sharedseen", {}).get("enabled")),
219+
"mailbox_settings_spam_folder_enabled": bool(odata.get("spam_folder", {}).get("enabled")),
220+
"mailbox_settings_spam_retention_value": odata.get("spam_retention", {}).get("value"),
221+
"mailbox_settings_quota_enabled": bool(odata.get("quota", {}).get("limit")),
222+
}
223+
224+
def get_queue_settings_facts():
225+
with subprocess.Popen(["../actions/get-queue-settings/10get_queue_settings"], stdout=subprocess.PIPE) as proc:
226+
try:
227+
odata = json.load(proc.stdout)
228+
except json.JSONDecodeError:
229+
return {"get_queue_settings_facts_error": True}
230+
231+
return {
232+
"queue_settings_maximal_queue_lifetime": odata.get("maximal_queue_lifetime"),
233+
}
234+
235+
def get_master_users_facts():
236+
with subprocess.Popen(["../actions/get-master-users/10get_master_users"], stdout=subprocess.PIPE) as proc:
237+
try:
238+
odata = json.load(proc.stdout)
239+
except json.JSONDecodeError:
240+
return {"get_master_users_facts_error": True}
241+
242+
return {
243+
"master_users_count": len(odata.get("master_users", [])),
244+
}
245+
246+
247+
if __name__ == "__main__":
248+
main()

0 commit comments

Comments
 (0)