From d7b04ebed0011a87d92594a6a42d41196aefe850 Mon Sep 17 00:00:00 2001 From: Emmanuel Garette Date: Tue, 11 Mar 2014 18:57:19 +0100 Subject: [PATCH] add consistency in_network for IPOption This new consistency can validate that an IPv4 is a specified (network/netmask) network --- test/test_option_consistency.py | 23 ++++ tiramisu/option.py | 12 ++ translations/fr/tiramisu.po | 128 ++++++++++---------- translations/tiramisu.pot | 200 ++++++++++++++++---------------- 4 files changed, 203 insertions(+), 160 deletions(-) diff --git a/test/test_option_consistency.py b/test/test_option_consistency.py index 1beb4bb..b40c340 100644 --- a/test/test_option_consistency.py +++ b/test/test_option_consistency.py @@ -169,6 +169,29 @@ def test_consistency_network_netmask(): raises(ValueError, "c.a = '192.168.1.1'") +def test_consistency_ip_in_network(): + a = NetworkOption('a', '') + b = NetmaskOption('b', '') + c = IPOption('c', '') + od = OptionDescription('od', '', [a, b, c]) + c.impl_add_consistency('in_network', a, b) + cfg = Config(od) + cfg.a = '192.168.1.0' + cfg.b = '255.255.255.0' + cfg.c = '192.168.1.1' + raises(ValueError, "cfg.c = '192.168.2.1'") + + +def test_consistency_ip_in_network_len_error(): + a = NetworkOption('a', '') + b = NetmaskOption('b', '') + c = IPOption('c', '') + od = OptionDescription('od', '', [a, b, c]) + c.impl_add_consistency('in_network', a) + cfg = Config(od) + raises(ConfigError, "cfg.a = '192.168.2.0'") + + def test_consistency_ip_netmask_network_error(): a = IPOption('a', '') b = NetworkOption('b', '') diff --git a/tiramisu/option.py b/tiramisu/option.py index 20cdf86..7622811 100644 --- a/tiramisu/option.py +++ b/tiramisu/option.py @@ -784,6 +784,18 @@ class IPOption(Option): if self._private_only and not ip.iptype() == 'PRIVATE': raise ValueError(_("invalid IP, must be in private class")) + def _cons_in_network(self, opts, vals): + if len(vals) != 3: + raise ConfigError(_('invalid len for vals')) + if None in vals: + return + ip, network, netmask = vals + if IP(ip) not in IP('{0}/{1}'.format(network, netmask)): + raise ValueError(_('invalid IP {0} ({1}) with network {2} ' + '({3}) and netmask {4} ({5})').format( + ip, opts[0]._name, network, + opts[1]._name, netmask, opts[2]._name)) + class PortOption(Option): """represents the choice of a port diff --git a/translations/fr/tiramisu.po b/translations/fr/tiramisu.po index 459e281..d80b026 100644 --- a/translations/fr/tiramisu.po +++ b/translations/fr/tiramisu.po @@ -2,7 +2,7 @@ msgid "" msgstr "" "Project-Id-Version: Tiramisu\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2014-03-09 20:13+CET\n" +"POT-Creation-Date: 2014-03-11 18:51+CET\n" "PO-Revision-Date: \n" "Last-Translator: Emmanuel Garette \n" "Language-Team: Tiramisu's team \n" @@ -203,187 +203,191 @@ msgstr "adresse IP invalide, ne doit pas être d'une classe reservée" msgid "invalid IP, must be in private class" msgstr "adresse IP invalide, doit être dans la classe privée" -#: tiramisu/option.py:823 +#: tiramisu/option.py:789 tiramisu/option.py:955 +msgid "invalid len for vals" +msgstr "longueur invalide pour vals" + +#: tiramisu/option.py:794 +msgid "invalid IP {0} ({1}) with network {2} ({3}) and netmask {4} ({5})" +msgstr "IP invalide {0} ({1}) avec le réseau {2} ({3}) et le masque {4} ({5})" + +#: tiramisu/option.py:835 msgid "inconsistency in allowed range" msgstr "inconsistence dans la plage autorisée" -#: tiramisu/option.py:828 +#: tiramisu/option.py:840 msgid "max value is empty" msgstr "la valeur maximum est vide" -#: tiramisu/option.py:845 +#: tiramisu/option.py:857 msgid "invalid port, range must have two values only" msgstr "port invalide, une plage doit avoir deux valeurs seulement" -#: tiramisu/option.py:848 +#: tiramisu/option.py:860 msgid "invalid port, first port in range must be smaller than the second one" msgstr "" "port invalide, le premier port d'une plage doit être plus petit que le second" -#: tiramisu/option.py:857 +#: tiramisu/option.py:869 msgid "invalid port" msgstr "port invalide" -#: tiramisu/option.py:859 +#: tiramisu/option.py:871 msgid "invalid port, must be an between {0} and {1}" msgstr "port invalide, port doit être entre {0} et {1}" -#: tiramisu/option.py:873 +#: tiramisu/option.py:885 msgid "invalid network address" msgstr "adresse réseau invalide" -#: tiramisu/option.py:878 +#: tiramisu/option.py:890 msgid "invalid network address, must not be in reserved class" msgstr "adresse réseau invalide, ne doit pas être dans la classe reservée" -#: tiramisu/option.py:890 +#: tiramisu/option.py:902 msgid "invalid netmask address" msgstr "masque de sous-réseau invalide" -#: tiramisu/option.py:906 +#: tiramisu/option.py:918 msgid "invalid len for opts" msgstr "longueur invalide pour opts" -#: tiramisu/option.py:920 +#: tiramisu/option.py:932 msgid "invalid IP {0} ({1}) with netmask {2}, this IP is a network" msgstr "IP invalide {0} ({1}) avec masque {2}, cette IP est un réseau" -#: tiramisu/option.py:925 +#: tiramisu/option.py:937 msgid "invalid network {0} ({1}) with netmask {2}" msgstr "réseau invalide {0} ({1}) avec masque {2}" -#: tiramisu/option.py:939 +#: tiramisu/option.py:951 msgid "invalid broadcast address" msgstr "adresse de broadcast invalide" -#: tiramisu/option.py:943 -msgid "invalid len for vals" -msgstr "longueur invalide pour vals" - -#: tiramisu/option.py:948 +#: tiramisu/option.py:960 msgid "" "invalid broadcast {0} ({1}) with network {2} ({3}) and netmask {4} ({5})" msgstr "" "Broadcast invalide {0} ({1}) avec le réseau {2} ({3}) et le masque {4} ({5})" -#: tiramisu/option.py:970 +#: tiramisu/option.py:982 msgid "unknown type_ {0} for hostname" msgstr "type_ inconnu {0} pour le nom d'hôte" -#: tiramisu/option.py:973 +#: tiramisu/option.py:985 msgid "allow_ip must be a boolean" msgstr "allow_ip doit être un booléen" -#: tiramisu/option.py:975 +#: tiramisu/option.py:987 msgid "allow_without_dot must be a boolean" msgstr "allow_without_dot doit être un booléen" -#: tiramisu/option.py:1019 +#: tiramisu/option.py:1031 msgid "invalid domainname, must have dot" msgstr "nom de domaine invalide, doit avoir un point" -#: tiramisu/option.py:1021 +#: tiramisu/option.py:1033 msgid "invalid domainname's length (max 255)" msgstr "longueur du nom de domaine invalide (maximum {1})" -#: tiramisu/option.py:1023 +#: tiramisu/option.py:1035 msgid "invalid domainname's length (min 2)" msgstr "longueur du nom de domaine invalide (minimum 2)" -#: tiramisu/option.py:1025 +#: tiramisu/option.py:1037 msgid "invalid domainname" msgstr "nom de domaine invalide" -#: tiramisu/option.py:1038 +#: tiramisu/option.py:1050 msgid "invalid email address, should contains one @" msgstr "adresse email invalide, devrait contenir un @" -#: tiramisu/option.py:1041 +#: tiramisu/option.py:1053 msgid "invalid username in email address" msgstr "nom d'utilisateur invalide dans une adresse email" -#: tiramisu/option.py:1054 +#: tiramisu/option.py:1066 msgid "invalid url, should start with http:// or https://" msgstr "URL invalide, devrait démarré avec http:// ou https://" -#: tiramisu/option.py:1073 +#: tiramisu/option.py:1085 msgid "invalid url, port must be an between 0 and 65536" msgstr "URL invalide, port doit être entre 0 et 65536" -#: tiramisu/option.py:1079 +#: tiramisu/option.py:1091 msgid "invalid url, should ends with filename" msgstr "URL invalide, devrait finir avec un nom de fichier" -#: tiramisu/option.py:1091 +#: tiramisu/option.py:1103 msgid "invalid username" msgstr "utilisateur invalide" -#: tiramisu/option.py:1102 +#: tiramisu/option.py:1114 msgid "invalid filename" msgstr "nom de fichier invalide" -#: tiramisu/option.py:1129 +#: tiramisu/option.py:1141 msgid "duplicate option name: {0}" msgstr "nom de l'option dupliqué : {0}" -#: tiramisu/option.py:1147 +#: tiramisu/option.py:1159 msgid "unknown Option {0} in OptionDescription {1}" msgstr "Option {0} inconnue pour l'OptionDescription {1}" -#: tiramisu/option.py:1198 +#: tiramisu/option.py:1210 msgid "duplicate option: {0}" msgstr "option dupliquée : {0}" -#: tiramisu/option.py:1228 +#: tiramisu/option.py:1240 msgid "consistency with option {0} which is not in Config" msgstr "consistency avec l'option {0} qui n'est pas dans une Config" -#: tiramisu/option.py:1236 +#: tiramisu/option.py:1248 msgid "no option for path {0}" msgstr "pas d'option pour le chemin {0}" -#: tiramisu/option.py:1242 +#: tiramisu/option.py:1254 msgid "no option {0} found" msgstr "pas d'option {0} trouvée" -#: tiramisu/option.py:1252 +#: tiramisu/option.py:1264 msgid "cannot change group_type if already set (old {0}, new {1})" msgstr "ne peut changer group_type si déjà spécifié (ancien {0}, nouveau {1})" -#: tiramisu/option.py:1264 +#: tiramisu/option.py:1276 msgid "master group {0} shall not have a subgroup" msgstr "groupe maître {0} ne doit pas avoir de sous-groupe" -#: tiramisu/option.py:1267 +#: tiramisu/option.py:1279 msgid "master group {0} shall not have a symlinkoption" msgstr "groupe maître {0} ne doit pas avoir de symlinkoption" -#: tiramisu/option.py:1270 +#: tiramisu/option.py:1282 msgid "not allowed option {0} in group {1}: this option is not a multi" msgstr "" "option non autorisée {0} dans le groupe {1} : cette option n'est pas une " "multi" -#: tiramisu/option.py:1280 +#: tiramisu/option.py:1292 msgid "master group with wrong master name for {0}" msgstr "le groupe maître avec un nom de maître érroné pour {0}" -#: tiramisu/option.py:1288 +#: tiramisu/option.py:1300 msgid "callback of master's option shall not refered a slave's ones" msgstr "" "callback d'une variable maitre ne devrait pas référencer des variables " "esclaves" -#: tiramisu/option.py:1296 +#: tiramisu/option.py:1308 msgid "group_type: {0} not allowed" msgstr "group_type : {0} non autorisé" -#: tiramisu/option.py:1385 +#: tiramisu/option.py:1397 msgid "malformed requirements type for option: {0}, must be a dict" msgstr "" "type requirements malformé pour l'option : {0}, doit être un dictionnaire" -#: tiramisu/option.py:1402 +#: tiramisu/option.py:1414 msgid "" "malformed requirements for option: {0} require must have option, expected " "and action keys" @@ -391,66 +395,66 @@ msgstr "" "requirements malformé pour l'option : {0} l'exigence doit avoir les clefs " "option, expected et action" -#: tiramisu/option.py:1407 +#: tiramisu/option.py:1419 msgid "malformed requirements for option: {0} inverse must be boolean" msgstr "" "requirements mal formés pour l'option : {0} inverse doit être un booléen" -#: tiramisu/option.py:1411 +#: tiramisu/option.py:1423 msgid "malformed requirements for option: {0} transitive must be boolean" msgstr "" "requirements mal formés pour l'option : {0} transitive doit être booléen" -#: tiramisu/option.py:1415 +#: tiramisu/option.py:1427 msgid "malformed requirements for option: {0} same_action must be boolean" msgstr "" "requirements mal formés pour l'option : {0} same_action doit être un booléen" -#: tiramisu/option.py:1419 +#: tiramisu/option.py:1431 msgid "malformed requirements must be an option in option {0}" msgstr "requirements mal formés doit être une option dans l'option {0}" -#: tiramisu/option.py:1422 +#: tiramisu/option.py:1434 msgid "malformed requirements option {0} should not be a multi" msgstr "requirements mal formés l'option {0} ne doit pas être une multi" -#: tiramisu/option.py:1428 +#: tiramisu/option.py:1440 msgid "" "malformed requirements second argument must be valid for option {0}: {1}" msgstr "" "requirements mal formés deuxième argument doit être valide pour l'option " "{0} : {1}" -#: tiramisu/option.py:1433 +#: tiramisu/option.py:1445 msgid "inconsistency in action types for option: {0} action: {1}" msgstr "incohérence dans les types action pour l'option : {0} action {1}" -#: tiramisu/option.py:1458 +#: tiramisu/option.py:1470 msgid "{0} should be a function" msgstr "{0} doit être une fonction" -#: tiramisu/option.py:1461 +#: tiramisu/option.py:1473 msgid "{0}_params should be a dict" msgstr "{0}_params devrait être un dict" -#: tiramisu/option.py:1464 +#: tiramisu/option.py:1476 msgid "{0}_params with key {1} should not have length different to 1" msgstr "" "{0}_params avec la clef {1} devrait ne pas avoir une longueur différent de 1" -#: tiramisu/option.py:1468 +#: tiramisu/option.py:1480 msgid "{0}_params should be tuple for key \"{1}\"" msgstr "{0}_params devrait être un tuple pour la clef \"{1}\"" -#: tiramisu/option.py:1474 +#: tiramisu/option.py:1486 msgid "validator not support tuple" msgstr "validator n'accepte pas de tuple" -#: tiramisu/option.py:1477 +#: tiramisu/option.py:1489 msgid "{0}_params should have an option not a {0} for first argument" msgstr "{0}_params devrait avoir une option pas un {0} pour premier argument" -#: tiramisu/option.py:1481 +#: tiramisu/option.py:1493 msgid "{0}_params should have a boolean not a {0} for second argument" msgstr "{0}_params devrait avoir un boolean pas un {0} pour second argument" diff --git a/translations/tiramisu.pot b/translations/tiramisu.pot index 2a20646..d35e6a5 100644 --- a/translations/tiramisu.pot +++ b/translations/tiramisu.pot @@ -5,7 +5,7 @@ msgid "" msgstr "" "Project-Id-Version: PACKAGE VERSION\n" -"POT-Creation-Date: 2014-03-09 20:13+CET\n" +"POT-Creation-Date: 2014-03-11 18:51+CET\n" "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" "Last-Translator: FULL NAME \n" "Language-Team: LANGUAGE \n" @@ -192,235 +192,239 @@ msgstr "" msgid "invalid IP, must be in private class" msgstr "" -#: tiramisu/option.py:823 -msgid "inconsistency in allowed range" -msgstr "" - -#: tiramisu/option.py:828 -msgid "max value is empty" -msgstr "" - -#: tiramisu/option.py:845 -msgid "invalid port, range must have two values only" -msgstr "" - -#: tiramisu/option.py:848 -msgid "invalid port, first port in range must be smaller than the second one" -msgstr "" - -#: tiramisu/option.py:857 -msgid "invalid port" -msgstr "" - -#: tiramisu/option.py:859 -msgid "invalid port, must be an between {0} and {1}" -msgstr "" - -#: tiramisu/option.py:873 -msgid "invalid network address" -msgstr "" - -#: tiramisu/option.py:878 -msgid "invalid network address, must not be in reserved class" -msgstr "" - -#: tiramisu/option.py:890 -msgid "invalid netmask address" -msgstr "" - -#: tiramisu/option.py:906 -msgid "invalid len for opts" -msgstr "" - -#: tiramisu/option.py:920 -msgid "invalid IP {0} ({1}) with netmask {2}, this IP is a network" -msgstr "" - -#: tiramisu/option.py:925 -msgid "invalid network {0} ({1}) with netmask {2}" -msgstr "" - -#: tiramisu/option.py:939 -msgid "invalid broadcast address" -msgstr "" - -#: tiramisu/option.py:943 +#: tiramisu/option.py:789 tiramisu/option.py:955 msgid "invalid len for vals" msgstr "" -#: tiramisu/option.py:948 +#: tiramisu/option.py:794 +msgid "invalid IP {0} ({1}) with network {2} ({3}) and netmask {4} ({5})" +msgstr "" + +#: tiramisu/option.py:835 +msgid "inconsistency in allowed range" +msgstr "" + +#: tiramisu/option.py:840 +msgid "max value is empty" +msgstr "" + +#: tiramisu/option.py:857 +msgid "invalid port, range must have two values only" +msgstr "" + +#: tiramisu/option.py:860 +msgid "invalid port, first port in range must be smaller than the second one" +msgstr "" + +#: tiramisu/option.py:869 +msgid "invalid port" +msgstr "" + +#: tiramisu/option.py:871 +msgid "invalid port, must be an between {0} and {1}" +msgstr "" + +#: tiramisu/option.py:885 +msgid "invalid network address" +msgstr "" + +#: tiramisu/option.py:890 +msgid "invalid network address, must not be in reserved class" +msgstr "" + +#: tiramisu/option.py:902 +msgid "invalid netmask address" +msgstr "" + +#: tiramisu/option.py:918 +msgid "invalid len for opts" +msgstr "" + +#: tiramisu/option.py:932 +msgid "invalid IP {0} ({1}) with netmask {2}, this IP is a network" +msgstr "" + +#: tiramisu/option.py:937 +msgid "invalid network {0} ({1}) with netmask {2}" +msgstr "" + +#: tiramisu/option.py:951 +msgid "invalid broadcast address" +msgstr "" + +#: tiramisu/option.py:960 msgid "invalid broadcast {0} ({1}) with network {2} ({3}) and netmask {4} ({5})" msgstr "" -#: tiramisu/option.py:970 +#: tiramisu/option.py:982 msgid "unknown type_ {0} for hostname" msgstr "" -#: tiramisu/option.py:973 +#: tiramisu/option.py:985 msgid "allow_ip must be a boolean" msgstr "" -#: tiramisu/option.py:975 +#: tiramisu/option.py:987 msgid "allow_without_dot must be a boolean" msgstr "" -#: tiramisu/option.py:1019 +#: tiramisu/option.py:1031 msgid "invalid domainname, must have dot" msgstr "" -#: tiramisu/option.py:1021 +#: tiramisu/option.py:1033 msgid "invalid domainname's length (max 255)" msgstr "" -#: tiramisu/option.py:1023 +#: tiramisu/option.py:1035 msgid "invalid domainname's length (min 2)" msgstr "" -#: tiramisu/option.py:1025 +#: tiramisu/option.py:1037 msgid "invalid domainname" msgstr "" -#: tiramisu/option.py:1038 +#: tiramisu/option.py:1050 msgid "invalid email address, should contains one @" msgstr "" -#: tiramisu/option.py:1041 +#: tiramisu/option.py:1053 msgid "invalid username in email address" msgstr "" -#: tiramisu/option.py:1054 +#: tiramisu/option.py:1066 msgid "invalid url, should start with http:// or https://" msgstr "" -#: tiramisu/option.py:1073 +#: tiramisu/option.py:1085 msgid "invalid url, port must be an between 0 and 65536" msgstr "" -#: tiramisu/option.py:1079 +#: tiramisu/option.py:1091 msgid "invalid url, should ends with filename" msgstr "" -#: tiramisu/option.py:1091 +#: tiramisu/option.py:1103 msgid "invalid username" msgstr "" -#: tiramisu/option.py:1102 +#: tiramisu/option.py:1114 msgid "invalid filename" msgstr "" -#: tiramisu/option.py:1129 +#: tiramisu/option.py:1141 msgid "duplicate option name: {0}" msgstr "" -#: tiramisu/option.py:1147 +#: tiramisu/option.py:1159 msgid "unknown Option {0} in OptionDescription {1}" msgstr "" -#: tiramisu/option.py:1198 +#: tiramisu/option.py:1210 msgid "duplicate option: {0}" msgstr "" -#: tiramisu/option.py:1228 +#: tiramisu/option.py:1240 msgid "consistency with option {0} which is not in Config" msgstr "" -#: tiramisu/option.py:1236 +#: tiramisu/option.py:1248 msgid "no option for path {0}" msgstr "" -#: tiramisu/option.py:1242 +#: tiramisu/option.py:1254 msgid "no option {0} found" msgstr "" -#: tiramisu/option.py:1252 +#: tiramisu/option.py:1264 msgid "cannot change group_type if already set (old {0}, new {1})" msgstr "" -#: tiramisu/option.py:1264 +#: tiramisu/option.py:1276 msgid "master group {0} shall not have a subgroup" msgstr "" -#: tiramisu/option.py:1267 +#: tiramisu/option.py:1279 msgid "master group {0} shall not have a symlinkoption" msgstr "" -#: tiramisu/option.py:1270 +#: tiramisu/option.py:1282 msgid "not allowed option {0} in group {1}: this option is not a multi" msgstr "" -#: tiramisu/option.py:1280 +#: tiramisu/option.py:1292 msgid "master group with wrong master name for {0}" msgstr "" -#: tiramisu/option.py:1288 +#: tiramisu/option.py:1300 msgid "callback of master's option shall not refered a slave's ones" msgstr "" -#: tiramisu/option.py:1296 +#: tiramisu/option.py:1308 msgid "group_type: {0} not allowed" msgstr "" -#: tiramisu/option.py:1385 +#: tiramisu/option.py:1397 msgid "malformed requirements type for option: {0}, must be a dict" msgstr "" -#: tiramisu/option.py:1402 +#: tiramisu/option.py:1414 msgid "malformed requirements for option: {0} require must have option, expected and action keys" msgstr "" -#: tiramisu/option.py:1407 +#: tiramisu/option.py:1419 msgid "malformed requirements for option: {0} inverse must be boolean" msgstr "" -#: tiramisu/option.py:1411 +#: tiramisu/option.py:1423 msgid "malformed requirements for option: {0} transitive must be boolean" msgstr "" -#: tiramisu/option.py:1415 +#: tiramisu/option.py:1427 msgid "malformed requirements for option: {0} same_action must be boolean" msgstr "" -#: tiramisu/option.py:1419 +#: tiramisu/option.py:1431 msgid "malformed requirements must be an option in option {0}" msgstr "" -#: tiramisu/option.py:1422 +#: tiramisu/option.py:1434 msgid "malformed requirements option {0} should not be a multi" msgstr "" -#: tiramisu/option.py:1428 +#: tiramisu/option.py:1440 msgid "malformed requirements second argument must be valid for option {0}: {1}" msgstr "" -#: tiramisu/option.py:1433 +#: tiramisu/option.py:1445 msgid "inconsistency in action types for option: {0} action: {1}" msgstr "" -#: tiramisu/option.py:1458 +#: tiramisu/option.py:1470 msgid "{0} should be a function" msgstr "" -#: tiramisu/option.py:1461 +#: tiramisu/option.py:1473 msgid "{0}_params should be a dict" msgstr "" -#: tiramisu/option.py:1464 +#: tiramisu/option.py:1476 msgid "{0}_params with key {1} should not have length different to 1" msgstr "" -#: tiramisu/option.py:1468 +#: tiramisu/option.py:1480 msgid "{0}_params should be tuple for key \"{1}\"" msgstr "" -#: tiramisu/option.py:1474 +#: tiramisu/option.py:1486 msgid "validator not support tuple" msgstr "" -#: tiramisu/option.py:1477 +#: tiramisu/option.py:1489 msgid "{0}_params should have an option not a {0} for first argument" msgstr "" -#: tiramisu/option.py:1481 +#: tiramisu/option.py:1493 msgid "{0}_params should have a boolean not a {0} for second argument" msgstr ""