diff --git a/doc/service/service.md b/doc/service/service.md
index 6896fe3a3..d79e2b222 100644
--- a/doc/service/service.md
+++ b/doc/service/service.md
@@ -14,3 +14,13 @@ Il faut, à la création du service, préciser son nom :
```
+
+Un service peut ne pas être géré :
+
+```
+
+```
+
+Un service non géré est généralement une service qui n'existe pas réellement (par exemple si on configure un client).
+
+Un service non géré ne peut conteneur que des fichiers.
diff --git a/src/rougail/annotator/service.py b/src/rougail/annotator/service.py
index c3f09654c..24baa545e 100644
--- a/src/rougail/annotator/service.py
+++ b/src/rougail/annotator/service.py
@@ -36,6 +36,7 @@ ERASED_ATTRIBUTES = ('redefine', 'exists', 'optional', 'remove_check', 'namespac
'remove_condition', 'path', 'instance_mode', 'index',
'level', 'remove_fill', 'xmlfiles', 'type', 'reflector_name',
'reflector_object',)
+ALLOW_ATTRIBUT_NOT_MANAGE = ['file']
class ServiceAnnotator:
@@ -71,7 +72,13 @@ class ServiceAnnotator:
for elttype, values in dict(vars(service)).items():
if not isinstance(values, (dict, list)) or elttype in ERASED_ATTRIBUTES:
continue
- eltname = elttype + 's'
+ if not service.manage and elttype not in ALLOW_ATTRIBUT_NOT_MANAGE:
+ msg = _(f'unmanage service cannot have "{elttype}"')
+ raise DictConsistencyError(msg, 66, service.xmlfiles)
+ if elttype != 'ip':
+ eltname = elttype + 's'
+ else:
+ eltname = elttype
path = '.'.join(['services', normalize_family(service_name), eltname])
family = self._gen_family(eltname,
path,
diff --git a/tests/dictionaries/70service_not_managed/00-base.xml b/tests/dictionaries/70service_not_managed/00-base.xml
index f07a0700f..82fb00192 100644
--- a/tests/dictionaries/70service_not_managed/00-base.xml
+++ b/tests/dictionaries/70service_not_managed/00-base.xml
@@ -2,6 +2,7 @@
+
diff --git a/tests/dictionaries/70service_not_managed/makedict/base.json b/tests/dictionaries/70service_not_managed/makedict/base.json
index 678b36e6d..fb13dad2e 100644
--- a/tests/dictionaries/70service_not_managed/makedict/base.json
+++ b/tests/dictionaries/70service_not_managed/makedict/base.json
@@ -1 +1 @@
-{"rougail.var": "mailname"}
+{"rougail.var": "mailname", "services.test.files.test.group": "root", "services.test.files.test.mode": "0644", "services.test.files.test.name": "/tmp/test", "services.test.files.test.owner": "root", "services.test.files.test.source": "test", "services.test.files.test.templating": "creole", "services.test.files.test.activate": true}
diff --git a/tests/dictionaries/70service_not_managed/tiramisu/base.py b/tests/dictionaries/70service_not_managed/tiramisu/base.py
index 4de4409bf..0dadb7971 100644
--- a/tests/dictionaries/70service_not_managed/tiramisu/base.py
+++ b/tests/dictionaries/70service_not_managed/tiramisu/base.py
@@ -13,7 +13,16 @@ except:
from tiramisu import *
option_2 = StrOption(name="var", doc="var", default="mailname", properties=frozenset({"mandatory", "normal"}))
option_1 = OptionDescription(name="rougail", doc="rougail", children=[option_2])
-option_4 = OptionDescription(name="test", doc="test", children=[])
+option_7 = StrOption(name="group", doc="group", default="root")
+option_8 = StrOption(name="mode", doc="mode", default="0644")
+option_9 = FilenameOption(name="name", doc="name", default="/tmp/test")
+option_10 = StrOption(name="owner", doc="owner", default="root")
+option_11 = StrOption(name="source", doc="source", default="test")
+option_12 = StrOption(name="templating", doc="templating", default="creole")
+option_13 = BoolOption(name="activate", doc="activate", default=True)
+option_6 = OptionDescription(name="test", doc="test", children=[option_7, option_8, option_9, option_10, option_11, option_12, option_13])
+option_5 = OptionDescription(name="files", doc="files", children=[option_6])
+option_4 = OptionDescription(name="test", doc="test", children=[option_5])
option_4.impl_set_information('manage', False)
option_3 = OptionDescription(name="services", doc="services", children=[option_4], properties=frozenset({"hidden"}))
option_0 = OptionDescription(name="baseoption", doc="baseoption", children=[option_1, option_3])
diff --git a/tests/dictionaries/70services_ip/makedict/base.json b/tests/dictionaries/70services_ip/makedict/base.json
index 70cac6d9a..65c9c77ab 100644
--- a/tests/dictionaries/70services_ip/makedict/base.json
+++ b/tests/dictionaries/70services_ip/makedict/base.json
@@ -1 +1 @@
-{"rougail.nut_monitor_host": null, "services.nut.ips.nut_monitor_host.name": null, "services.nut.ips.nut_monitor_host.activate": true}
+{"rougail.nut_monitor_host": null, "services.nut.ip.nut_monitor_host.name": null, "services.nut.ip.nut_monitor_host.activate": true}
diff --git a/tests/dictionaries/70services_ip/tiramisu/base.py b/tests/dictionaries/70services_ip/tiramisu/base.py
index 41afb6921..cd05490f5 100644
--- a/tests/dictionaries/70services_ip/tiramisu/base.py
+++ b/tests/dictionaries/70services_ip/tiramisu/base.py
@@ -16,7 +16,7 @@ option_1 = OptionDescription(name="rougail", doc="rougail", children=[option_2])
option_7 = SymLinkOption(name="name", opt=option_2)
option_8 = BoolOption(name="activate", doc="activate", default=True)
option_6 = OptionDescription(name="nut_monitor_host", doc="nut_monitor_host", children=[option_7, option_8])
-option_5 = OptionDescription(name="ips", doc="ips", children=[option_6])
+option_5 = OptionDescription(name="ip", doc="ip", children=[option_6])
option_4 = OptionDescription(name="nut", doc="nut", children=[option_5])
option_3 = OptionDescription(name="services", doc="services", children=[option_4], properties=frozenset({"hidden"}))
option_0 = OptionDescription(name="baseoption", doc="baseoption", children=[option_1, option_3])
diff --git a/tests/dictionaries/70services_ip_cidr/makedict/base.json b/tests/dictionaries/70services_ip_cidr/makedict/base.json
index 70cac6d9a..65c9c77ab 100644
--- a/tests/dictionaries/70services_ip_cidr/makedict/base.json
+++ b/tests/dictionaries/70services_ip_cidr/makedict/base.json
@@ -1 +1 @@
-{"rougail.nut_monitor_host": null, "services.nut.ips.nut_monitor_host.name": null, "services.nut.ips.nut_monitor_host.activate": true}
+{"rougail.nut_monitor_host": null, "services.nut.ip.nut_monitor_host.name": null, "services.nut.ip.nut_monitor_host.activate": true}
diff --git a/tests/dictionaries/70services_ip_cidr/tiramisu/base.py b/tests/dictionaries/70services_ip_cidr/tiramisu/base.py
index 72bd1ad20..0f64e5259 100644
--- a/tests/dictionaries/70services_ip_cidr/tiramisu/base.py
+++ b/tests/dictionaries/70services_ip_cidr/tiramisu/base.py
@@ -16,7 +16,7 @@ option_1 = OptionDescription(name="rougail", doc="rougail", children=[option_2])
option_7 = SymLinkOption(name="name", opt=option_2)
option_8 = BoolOption(name="activate", doc="activate", default=True)
option_6 = OptionDescription(name="nut_monitor_host", doc="nut_monitor_host", children=[option_7, option_8])
-option_5 = OptionDescription(name="ips", doc="ips", children=[option_6])
+option_5 = OptionDescription(name="ip", doc="ip", children=[option_6])
option_4 = OptionDescription(name="nut", doc="nut", children=[option_5])
option_3 = OptionDescription(name="services", doc="services", children=[option_4], properties=frozenset({"hidden"}))
option_0 = OptionDescription(name="baseoption", doc="baseoption", children=[option_1, option_3])
diff --git a/tests/dictionaries/70services_ip_iplist/makedict/base.json b/tests/dictionaries/70services_ip_iplist/makedict/base.json
index 9c0805646..36e37e22b 100644
--- a/tests/dictionaries/70services_ip_iplist/makedict/base.json
+++ b/tests/dictionaries/70services_ip_iplist/makedict/base.json
@@ -1 +1 @@
-{"rougail.condition": "no", "rougail.nut_monitor_host": null, "services.nut.ips.nut_monitor_host.name": null, "services.nut.ips.nut_monitor_host.activate": true}
+{"rougail.condition": "no", "rougail.nut_monitor_host": null, "services.nut.ip.nut_monitor_host.name": null, "services.nut.ip.nut_monitor_host.activate": true}
diff --git a/tests/dictionaries/70services_ip_iplist/tiramisu/base.py b/tests/dictionaries/70services_ip_iplist/tiramisu/base.py
index b8cd6e447..75588adb2 100644
--- a/tests/dictionaries/70services_ip_iplist/tiramisu/base.py
+++ b/tests/dictionaries/70services_ip_iplist/tiramisu/base.py
@@ -17,7 +17,7 @@ option_1 = OptionDescription(name="rougail", doc="rougail", children=[option_2,
option_8 = SymLinkOption(name="name", opt=option_3)
option_9 = BoolOption(name="activate", doc="activate", default=Calculation(func.calc_value, Params((ParamValue(False)), kwargs={'default': ParamValue(True), 'condition_0': ParamOption(option_2), 'expected_0': ParamValue("yes")})))
option_7 = OptionDescription(name="nut_monitor_host", doc="nut_monitor_host", children=[option_8, option_9])
-option_6 = OptionDescription(name="ips", doc="ips", children=[option_7])
+option_6 = OptionDescription(name="ip", doc="ip", children=[option_7])
option_5 = OptionDescription(name="nut", doc="nut", children=[option_6])
option_4 = OptionDescription(name="services", doc="services", children=[option_5], properties=frozenset({"hidden"}))
option_0 = OptionDescription(name="baseoption", doc="baseoption", children=[option_1, option_4])
diff --git a/tests/dictionaries/70services_ip_iplist2/makedict/base.json b/tests/dictionaries/70services_ip_iplist2/makedict/base.json
index 1f7016ff8..61551867a 100644
--- a/tests/dictionaries/70services_ip_iplist2/makedict/base.json
+++ b/tests/dictionaries/70services_ip_iplist2/makedict/base.json
@@ -1 +1 @@
-{"rougail.condition": "yes", "rougail.nut_monitor_host": null, "services.nut.ips.nut_monitor_host.name": null, "services.nut.ips.nut_monitor_host.activate": false}
+{"rougail.condition": "yes", "rougail.nut_monitor_host": null, "services.nut.ip.nut_monitor_host.name": null, "services.nut.ip.nut_monitor_host.activate": false}
diff --git a/tests/dictionaries/70services_ip_iplist2/tiramisu/base.py b/tests/dictionaries/70services_ip_iplist2/tiramisu/base.py
index 5133ea274..b148b15b8 100644
--- a/tests/dictionaries/70services_ip_iplist2/tiramisu/base.py
+++ b/tests/dictionaries/70services_ip_iplist2/tiramisu/base.py
@@ -17,7 +17,7 @@ option_1 = OptionDescription(name="rougail", doc="rougail", children=[option_2,
option_8 = SymLinkOption(name="name", opt=option_3)
option_9 = BoolOption(name="activate", doc="activate", default=Calculation(func.calc_value, Params((ParamValue(False)), kwargs={'default': ParamValue(True), 'condition_0': ParamOption(option_2), 'expected_0': ParamValue("yes")})))
option_7 = OptionDescription(name="nut_monitor_host", doc="nut_monitor_host", children=[option_8, option_9])
-option_6 = OptionDescription(name="ips", doc="ips", children=[option_7])
+option_6 = OptionDescription(name="ip", doc="ip", children=[option_7])
option_5 = OptionDescription(name="nut", doc="nut", children=[option_6])
option_4 = OptionDescription(name="services", doc="services", children=[option_5], properties=frozenset({"hidden"}))
option_0 = OptionDescription(name="baseoption", doc="baseoption", children=[option_1, option_4])
diff --git a/tests/dictionaries/70services_ip_leadership/makedict/base.json b/tests/dictionaries/70services_ip_leadership/makedict/base.json
index 0a17121ad..a1988eadd 100644
--- a/tests/dictionaries/70services_ip_leadership/makedict/base.json
+++ b/tests/dictionaries/70services_ip_leadership/makedict/base.json
@@ -1 +1 @@
-{"rougail.general.mode_conteneur_actif": "oui", "rougail.general.nut_monitor_netmask.nut_monitor_netmask": [], "services.ntp.ips.nut_monitor_host.name": [], "services.ntp.ips.nut_monitor_host.netmask": [], "services.ntp.ips.nut_monitor_host.activate": true}
+{"rougail.general.mode_conteneur_actif": "oui", "rougail.general.nut_monitor_netmask.nut_monitor_netmask": [], "services.ntp.ip.nut_monitor_host.name": [], "services.ntp.ip.nut_monitor_host.netmask": [], "services.ntp.ip.nut_monitor_host.activate": true}
diff --git a/tests/dictionaries/70services_ip_leadership/tiramisu/base.py b/tests/dictionaries/70services_ip_leadership/tiramisu/base.py
index c8398af02..ffcd00ec1 100644
--- a/tests/dictionaries/70services_ip_leadership/tiramisu/base.py
+++ b/tests/dictionaries/70services_ip_leadership/tiramisu/base.py
@@ -21,7 +21,7 @@ option_11 = SymLinkOption(name="name", opt=option_6)
option_12 = SymLinkOption(name="netmask", opt=option_5)
option_13 = BoolOption(name="activate", doc="activate", default=True)
option_10 = OptionDescription(name="nut_monitor_host", doc="nut_monitor_host", children=[option_11, option_12, option_13])
-option_9 = OptionDescription(name="ips", doc="ips", children=[option_10])
+option_9 = OptionDescription(name="ip", doc="ip", children=[option_10])
option_8 = OptionDescription(name="ntp", doc="ntp", children=[option_9])
option_7 = OptionDescription(name="services", doc="services", children=[option_8], properties=frozenset({"hidden"}))
option_0 = OptionDescription(name="baseoption", doc="baseoption", children=[option_1, option_7])
diff --git a/tests/dictionaries/70services_ip_network/makedict/base.json b/tests/dictionaries/70services_ip_network/makedict/base.json
index 5300cf330..7deec8b17 100644
--- a/tests/dictionaries/70services_ip_network/makedict/base.json
+++ b/tests/dictionaries/70services_ip_network/makedict/base.json
@@ -1 +1 @@
-{"rougail.nut_monitor_netmask": null, "rougail.nut_monitor_host": null, "services.nut.ips.nut_monitor_host.name": null, "services.nut.ips.nut_monitor_host.netmask": null, "services.nut.ips.nut_monitor_host.activate": true}
+{"rougail.nut_monitor_netmask": null, "rougail.nut_monitor_host": null, "services.nut.ip.nut_monitor_host.name": null, "services.nut.ip.nut_monitor_host.netmask": null, "services.nut.ip.nut_monitor_host.activate": true}
diff --git a/tests/dictionaries/70services_ip_network/tiramisu/base.py b/tests/dictionaries/70services_ip_network/tiramisu/base.py
index a3c397a86..286475e8e 100644
--- a/tests/dictionaries/70services_ip_network/tiramisu/base.py
+++ b/tests/dictionaries/70services_ip_network/tiramisu/base.py
@@ -18,7 +18,7 @@ option_8 = SymLinkOption(name="name", opt=option_3)
option_9 = SymLinkOption(name="netmask", opt=option_2)
option_10 = BoolOption(name="activate", doc="activate", default=True)
option_7 = OptionDescription(name="nut_monitor_host", doc="nut_monitor_host", children=[option_8, option_9, option_10])
-option_6 = OptionDescription(name="ips", doc="ips", children=[option_7])
+option_6 = OptionDescription(name="ip", doc="ip", children=[option_7])
option_5 = OptionDescription(name="nut", doc="nut", children=[option_6])
option_4 = OptionDescription(name="services", doc="services", children=[option_5], properties=frozenset({"hidden"}))
option_0 = OptionDescription(name="baseoption", doc="baseoption", children=[option_1, option_4])