From 971311e0f5bca1897ee5c8fa876a7ac0b9d55e79 Mon Sep 17 00:00:00 2001 From: Emmanuel Garette Date: Wed, 12 Feb 2025 15:36:48 +0100 Subject: [PATCH] fix: many improvment --- locale/fr/LC_MESSAGES/user_data_bitwarden.po | 98 ++++++++++++++ locale/fr/LC_MESSAGES/user_data_yaml.po | 49 ------- locale/rougail_user_data_bitwarden.pot | 73 +++++++++++ locale/rougail_user_data_yaml.pot | 49 ------- src/rougail/structural_bitwarden/__init__.py | 22 ++++ .../__pycache__/__init__.cpython-313.pyc | Bin 0 -> 952 bytes .../__pycache__/config.cpython-313.pyc | Bin 0 -> 1193 bytes .../__pycache__/object_model.cpython-313.pyc | Bin 0 -> 1381 bytes src/rougail/structural_bitwarden/config.py | 32 +++++ .../structural_bitwarden/object_model.py | 31 +++++ src/rougail/user_data_bitwarden/__init__.py | 21 +++ src/rougail/user_data_bitwarden/annotator.py | 64 +++++++++ src/rougail/user_data_bitwarden/config.py | 17 +++ src/rougail/user_data_bitwarden/data.py | 108 ++++++++++----- .../fr/LC_MESSAGES/user_data_bitwarden.mo | Bin 0 -> 2725 bytes .../locale/fr/LC_MESSAGES/user_data_yaml.mo | Bin 1502 -> 0 bytes tests/results/1_secret/errors/bitwarden.json | 4 + .../results/1_secret/makedict/bitwarden.json | 3 + .../2_username_secret/errors/bitwarden.json | 4 + .../2_username_secret/makedict/bitwarden.json | 4 + .../3_leadership_secret/errors/bitwarden.json | 4 + .../makedict/bitwarden.json | 12 ++ .../errors/bitwarden.json | 4 + .../makedict/bitwarden.json | 12 ++ .../4_several_secrets/errors/bitwarden.json | 6 + .../4_several_secrets/makedict/bitwarden.json | 3 + .../test/00_6secret/errors/bitwarden.json | 7 - .../test/00_6secret/makedict/bitwarden.json | 4 - .../00_6secret/errors/bitwarden.json | 7 - .../00_6secret/makedict/bitwarden.json | 4 - tests/structures/1_secret/00-base.yml | 8 ++ .../structures/2_username_secret/00-base.yml | 14 ++ .../3_leadership_secret/00-base.yml | 18 +++ .../3_leadership_secret_several/00-base.yml | 17 +++ .../structures/4_several_secrets/00-base.yml | 8 ++ tests/structures/5_default_value/00-base.yml | 7 + .../00-base.yml | 15 +++ .../00-base.yml | 23 ++++ tests/structures/8_multi_variable/00-base.yml | 9 ++ tests/structures/9_unknown_type/00-base.yml | 6 + tests/test_load.py | 123 +++++++++--------- 41 files changed, 681 insertions(+), 209 deletions(-) create mode 100644 locale/fr/LC_MESSAGES/user_data_bitwarden.po delete mode 100644 locale/fr/LC_MESSAGES/user_data_yaml.po create mode 100644 locale/rougail_user_data_bitwarden.pot delete mode 100644 locale/rougail_user_data_yaml.pot create mode 100644 src/rougail/structural_bitwarden/__init__.py create mode 100644 src/rougail/structural_bitwarden/__pycache__/__init__.cpython-313.pyc create mode 100644 src/rougail/structural_bitwarden/__pycache__/config.cpython-313.pyc create mode 100644 src/rougail/structural_bitwarden/__pycache__/object_model.cpython-313.pyc create mode 100644 src/rougail/structural_bitwarden/config.py create mode 100644 src/rougail/structural_bitwarden/object_model.py create mode 100644 src/rougail/user_data_bitwarden/annotator.py create mode 100644 src/rougail/user_data_bitwarden/locale/fr/LC_MESSAGES/user_data_bitwarden.mo delete mode 100644 src/rougail/user_data_yaml/locale/fr/LC_MESSAGES/user_data_yaml.mo create mode 100644 tests/results/1_secret/errors/bitwarden.json create mode 100644 tests/results/1_secret/makedict/bitwarden.json create mode 100644 tests/results/2_username_secret/errors/bitwarden.json create mode 100644 tests/results/2_username_secret/makedict/bitwarden.json create mode 100644 tests/results/3_leadership_secret/errors/bitwarden.json create mode 100644 tests/results/3_leadership_secret/makedict/bitwarden.json create mode 100644 tests/results/3_leadership_secret_several/errors/bitwarden.json create mode 100644 tests/results/3_leadership_secret_several/makedict/bitwarden.json create mode 100644 tests/results/4_several_secrets/errors/bitwarden.json create mode 100644 tests/results/4_several_secrets/makedict/bitwarden.json delete mode 100644 tests/results/test/00_6secret/errors/bitwarden.json delete mode 100644 tests/results/test/00_6secret/makedict/bitwarden.json delete mode 100644 tests/results/test_namespace/00_6secret/errors/bitwarden.json delete mode 100644 tests/results/test_namespace/00_6secret/makedict/bitwarden.json create mode 100644 tests/structures/1_secret/00-base.yml create mode 100644 tests/structures/2_username_secret/00-base.yml create mode 100644 tests/structures/3_leadership_secret/00-base.yml create mode 100644 tests/structures/3_leadership_secret_several/00-base.yml create mode 100644 tests/structures/4_several_secrets/00-base.yml create mode 100644 tests/structures/5_default_value/00-base.yml create mode 100644 tests/structures/6_leadership_secret_default_value/00-base.yml create mode 100644 tests/structures/6_leadership_secret_follower_variable/00-base.yml create mode 100644 tests/structures/8_multi_variable/00-base.yml create mode 100644 tests/structures/9_unknown_type/00-base.yml diff --git a/locale/fr/LC_MESSAGES/user_data_bitwarden.po b/locale/fr/LC_MESSAGES/user_data_bitwarden.po new file mode 100644 index 0000000..dbe5121 --- /dev/null +++ b/locale/fr/LC_MESSAGES/user_data_bitwarden.po @@ -0,0 +1,98 @@ +# SOME DESCRIPTIVE TITLE. +# Copyright (C) YEAR ORGANIZATION +# FIRST AUTHOR , YEAR. +# +msgid "" +msgstr "" +"Project-Id-Version: \n" +"POT-Creation-Date: 2025-02-12 15:36+0100\n" +"PO-Revision-Date: 2025-02-12 15:39+0100\n" +"Last-Translator: \n" +"Language-Team: \n" +"Language: fr\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Generated-By: pygettext.py 1.5\n" +"X-Generator: Poedit 3.5\n" + +#: src/rougail/user_data_bitwarden/annotator.py:46 +msgid "" +"only \"unix_user\" or \"secret\" variable type can have \"bitwarden\" " +"attribute, but \"{0}\" has type \"{1}\"" +msgstr "" +"seule une variable de type \"unix_user\" ou \"secret\" peuvent avoir " +"l'attribut \"bitwarden\", mais \"{0}\" a le type \"{1}\"" + +#: src/rougail/user_data_bitwarden/annotator.py:49 +msgid "" +"the variable \"{0}\" has attribute \"bitwarden\" but is a multi variable" +msgstr "" +"la variable \"{0}\" a un attribut \"bitwarden\" mais est une variable " +"multiple" + +#: src/rougail/user_data_bitwarden/annotator.py:58 +msgid "" +"the variable \"{0}\" is a follower and leader variable (\"{1}\") is also in " +"Bitwarden so this variable could not have default value" +msgstr "" +"la variable \"{0}\" est une suiveuse et la variable leader (\"{1}\") est " +"aussi dans Bitwarden donc cette variable ne peut avoir de valeur par défaut" + +#: src/rougail/user_data_bitwarden/annotator.py:62 +msgid "the variable \"{0}\" is in Bitwarden so should have default value" +msgstr "" +"la variable \"{0}\" est dans Bitwarden donc doit avoir une valeur par défaut" + +#: src/rougail/user_data_bitwarden/data.py:51 +msgid "\"bitwarden\" is not set in step.user_data" +msgstr "\"bitwarden\" n'est pas dans step.user_data" + +#: src/rougail/user_data_bitwarden/data.py:70 +msgid "" +"the value for \"{0}\" at index {1} is already set while it should be filled " +"in by Bitwarden" +msgstr "" +"la valeur de \"{0}\" à l'index {1} est déjà renseigné alors que celle doit " +"devrait être renseigné par Bitwarden" + +#: src/rougail/user_data_bitwarden/data.py:72 +msgid "" +"the value for \"{0}\" is already set while it should be filled in by " +"Bitwarden" +msgstr "" +"la valeur de \"{0}\" est déjà renseigné alors que celle doit devrait être " +"renseigné par Bitwarden" + +#: src/rougail/user_data_bitwarden/data.py:101 +msgid "the default value for \"{0}\" must be the Bitwarden item name" +msgstr "" +"la valeur par défaut pour \"{0}\" doit être un nom d'élément de Bitwarden" + +#: src/rougail/user_data_bitwarden/data.py:110 +msgid "cannot execute the \"bw\" commandline from Bitwarden for \"{0}\": {1}" +msgstr "" +"ne peut exécuter la ligne de commande \"bw\" pour Bitwarden pour \"{0}\": {1}" + +#: src/rougail/user_data_bitwarden/data.py:115 +msgid "cannot get {0} \"{1}\" from Bitwarden for \"{2}\": {3} ({4})" +msgstr "ne peut récupérer {0} \"{1}\" pour Bitwarden pour \"{2}\": {3} ({4})" + +#: src/rougail/user_data_bitwarden/data.py:120 +msgid "cannot load {0} \"{1}\" from Bitwarden for \"{2}\": {3}" +msgstr "ne peut charger {0} \"{1}\" pour Bitwarden pour \"{2}\": {3}" + +#: src/rougail/user_data_bitwarden/data.py:123 +msgid "cannot find {0} \"{1}\" from Bitwarden for \"{2}\"" +msgstr "ne peut trouver {0} \"{1}\" pour Bitwarden pour \"{2}\"" + +#: src/rougail/user_data_bitwarden/data.py:130 +msgid "" +"several items found with name \"{0}\" from Bitwarden for \"{1}\": \"{2}\"" +msgstr "" +"plusieurs éléments trouvés avec le nom \"{0}\" pour Bitwarden pour \"{1}\": " +"\"{2}\"" + +#: src/rougail/user_data_bitwarden/data.py:140 +msgid "unexpected datas \"{0}\" from Bitwarden for \"{1}\": {2}" +msgstr "données inattendues \"{0}\" pour Bitwarden pour \"{1}\": {2}" diff --git a/locale/fr/LC_MESSAGES/user_data_yaml.po b/locale/fr/LC_MESSAGES/user_data_yaml.po deleted file mode 100644 index bea5f40..0000000 --- a/locale/fr/LC_MESSAGES/user_data_yaml.po +++ /dev/null @@ -1,49 +0,0 @@ -# SOME DESCRIPTIVE TITLE. -# Copyright (C) YEAR ORGANIZATION -# FIRST AUTHOR , YEAR. -# -msgid "" -msgstr "" -"Project-Id-Version: \n" -"POT-Creation-Date: 2025-02-05 11:18+0100\n" -"PO-Revision-Date: 2025-02-05 11:21+0100\n" -"Last-Translator: \n" -"Language-Team: \n" -"Language: fr\n" -"MIME-Version: 1.0\n" -"Content-Type: text/plain; charset=UTF-8\n" -"Content-Transfer-Encoding: 8bit\n" -"Generated-By: pygettext.py 1.5\n" -"X-Generator: Poedit 3.5\n" - -#: src/rougail/user_data_bitwarden/data.py:50 -msgid "\"bitwarden\" is not set in step.user_data" -msgstr "\"bitwarden\" n'est pas dans step.user_data" - -#: src/rougail/user_data_bitwarden/data.py:67 -msgid "the default value for \"{0}\" must be the Bitwarden password name" -msgstr "la valeur par défaut pour \"{0}\" doit être un nom de mot de passe de Bitwarden" - -#: src/rougail/user_data_bitwarden/data.py:72 -msgid "cannot execute the \"bw\" commandline from Bitwarden for \"{0}\": {1}" -msgstr "ne peut exécuter la ligne de commande \"bw\" pour Bitwarden pour \"{0}\": {1}" - -#: src/rougail/user_data_bitwarden/data.py:77 -msgid "cannot get password \"{0}\" from Bitwarden for \"{1}\": {2} ({3})" -msgstr "ne peut récupérer le mot de passe \"{0}\" pour Bitwarden pour \"{1}\": {2} ({3})" - -#: src/rougail/user_data_bitwarden/data.py:82 -msgid "cannot load password \"{0}\" from Bitwarden for \"{1}\": {2}" -msgstr "ne peut charger le mot de passe \"{0}\" pour Bitwarden pour \"{1}\": {2}" - -#: src/rougail/user_data_bitwarden/data.py:85 -msgid "cannot find password \"{0}\" from Bitwarden for \"{1}\"" -msgstr "ne peut trouver le mot de passe \"{0}\" pour Bitwarden pour \"{1}\"" - -#: src/rougail/user_data_bitwarden/data.py:89 -msgid "several passwords found with name \"{0}\" from Bitwarden for \"{1}\": \"{2}\"" -msgstr "plusieurs mots de passe trouvés avec le nom \"{0}\" pour Bitwarden pour \"{1}\": \"{2}\"" - -#: src/rougail/user_data_bitwarden/data.py:94 -msgid "unexpected password \"{0}\" from Bitwarden for \"{1}\": {2}" -msgstr "mot de passe inattendu \"{0}\" pour Bitwarden pour \"{1}\": {2}" diff --git a/locale/rougail_user_data_bitwarden.pot b/locale/rougail_user_data_bitwarden.pot new file mode 100644 index 0000000..81a4d09 --- /dev/null +++ b/locale/rougail_user_data_bitwarden.pot @@ -0,0 +1,73 @@ +# SOME DESCRIPTIVE TITLE. +# Copyright (C) YEAR ORGANIZATION +# FIRST AUTHOR , YEAR. +# +msgid "" +msgstr "" +"Project-Id-Version: PACKAGE VERSION\n" +"POT-Creation-Date: 2025-02-12 15:39+0100\n" +"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" +"Last-Translator: FULL NAME \n" +"Language-Team: LANGUAGE \n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Generated-By: pygettext.py 1.5\n" + + +#: src/rougail/user_data_bitwarden/annotator.py:46 +msgid "only \"unix_user\" or \"secret\" variable type can have \"bitwarden\" attribute, but \"{0}\" has type \"{1}\"" +msgstr "" + +#: src/rougail/user_data_bitwarden/annotator.py:49 +msgid "the variable \"{0}\" has attribute \"bitwarden\" but is a multi variable" +msgstr "" + +#: src/rougail/user_data_bitwarden/annotator.py:58 +msgid "the variable \"{0}\" is a follower and leader variable (\"{1}\") is also in Bitwarden so this variable could not have default value" +msgstr "" + +#: src/rougail/user_data_bitwarden/annotator.py:62 +msgid "the variable \"{0}\" is in Bitwarden so should have default value" +msgstr "" + +#: src/rougail/user_data_bitwarden/data.py:51 +msgid "\"bitwarden\" is not set in step.user_data" +msgstr "" + +#: src/rougail/user_data_bitwarden/data.py:70 +msgid "the value for \"{0}\" at index {1} is already set while it should be filled in by Bitwarden" +msgstr "" + +#: src/rougail/user_data_bitwarden/data.py:72 +msgid "the value for \"{0}\" is already set while it should be filled in by Bitwarden" +msgstr "" + +#: src/rougail/user_data_bitwarden/data.py:101 +msgid "the default value for \"{0}\" must be the Bitwarden item name" +msgstr "" + +#: src/rougail/user_data_bitwarden/data.py:110 +msgid "cannot execute the \"bw\" commandline from Bitwarden for \"{0}\": {1}" +msgstr "" + +#: src/rougail/user_data_bitwarden/data.py:115 +msgid "cannot get {0} \"{1}\" from Bitwarden for \"{2}\": {3} ({4})" +msgstr "" + +#: src/rougail/user_data_bitwarden/data.py:120 +msgid "cannot load {0} \"{1}\" from Bitwarden for \"{2}\": {3}" +msgstr "" + +#: src/rougail/user_data_bitwarden/data.py:123 +msgid "cannot find {0} \"{1}\" from Bitwarden for \"{2}\"" +msgstr "" + +#: src/rougail/user_data_bitwarden/data.py:130 +msgid "several items found with name \"{0}\" from Bitwarden for \"{1}\": \"{2}\"" +msgstr "" + +#: src/rougail/user_data_bitwarden/data.py:140 +msgid "unexpected datas \"{0}\" from Bitwarden for \"{1}\": {2}" +msgstr "" + diff --git a/locale/rougail_user_data_yaml.pot b/locale/rougail_user_data_yaml.pot deleted file mode 100644 index 9f55612..0000000 --- a/locale/rougail_user_data_yaml.pot +++ /dev/null @@ -1,49 +0,0 @@ -# SOME DESCRIPTIVE TITLE. -# Copyright (C) YEAR ORGANIZATION -# FIRST AUTHOR , YEAR. -# -msgid "" -msgstr "" -"Project-Id-Version: PACKAGE VERSION\n" -"POT-Creation-Date: 2025-02-05 11:21+0100\n" -"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" -"Last-Translator: FULL NAME \n" -"Language-Team: LANGUAGE \n" -"MIME-Version: 1.0\n" -"Content-Type: text/plain; charset=UTF-8\n" -"Content-Transfer-Encoding: 8bit\n" -"Generated-By: pygettext.py 1.5\n" - - -#: src/rougail/user_data_bitwarden/data.py:50 -msgid "\"bitwarden\" is not set in step.user_data" -msgstr "" - -#: src/rougail/user_data_bitwarden/data.py:67 -msgid "the default value for \"{0}\" must be the Bitwarden password name" -msgstr "" - -#: src/rougail/user_data_bitwarden/data.py:72 -msgid "cannot execute the \"bw\" commandline from Bitwarden for \"{0}\": {1}" -msgstr "" - -#: src/rougail/user_data_bitwarden/data.py:77 -msgid "cannot get password \"{0}\" from Bitwarden for \"{1}\": {2} ({3})" -msgstr "" - -#: src/rougail/user_data_bitwarden/data.py:82 -msgid "cannot load password \"{0}\" from Bitwarden for \"{1}\": {2}" -msgstr "" - -#: src/rougail/user_data_bitwarden/data.py:85 -msgid "cannot find password \"{0}\" from Bitwarden for \"{1}\"" -msgstr "" - -#: src/rougail/user_data_bitwarden/data.py:89 -msgid "several passwords found with name \"{0}\" from Bitwarden for \"{1}\": \"{2}\"" -msgstr "" - -#: src/rougail/user_data_bitwarden/data.py:94 -msgid "unexpected password \"{0}\" from Bitwarden for \"{1}\": {2}" -msgstr "" - diff --git a/src/rougail/structural_bitwarden/__init__.py b/src/rougail/structural_bitwarden/__init__.py new file mode 100644 index 0000000..d5d2b22 --- /dev/null +++ b/src/rougail/structural_bitwarden/__init__.py @@ -0,0 +1,22 @@ +""" +Silique (https://www.silique.fr) +Copyright (C) 2025 + +This program is free software: you can redistribute it and/or modify it +under the terms of the GNU Lesser General Public License as published by the +Free Software Foundation, either version 3 of the License, or (at your +option) any later version. + +This program is distributed in the hope that it will be useful, but WITHOUT +ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS +FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more +details. + +You should have received a copy of the GNU Lesser General Public License +along with this program. If not, see . +""" +from .object_model import Variable + + +__all__ = ("Variable",) + diff --git a/src/rougail/structural_bitwarden/__pycache__/__init__.cpython-313.pyc b/src/rougail/structural_bitwarden/__pycache__/__init__.cpython-313.pyc new file mode 100644 index 0000000000000000000000000000000000000000..19abe5496f81de7ad0a1fd9c78dbc65f778d64b8 GIT binary patch literal 952 zcmah|O>fgc5VezvR)$KPP>&6r!dL4QXUMR5@82du%V-c*E{GAxC}$ zKcXl8PdIYoR#XsIX46JJaOfWFot=+;Z|3dI?yl$1`uqJV|6OyOAJ*6`ve)ZokA7dB z&{0n4hP89|T}{=%32UmJ*Be{x8wGkH7yMI&uwNK6(}%vlSS(ul_OO+yhS!m^rQ&&E zV87FVgO>-dJufP_hMAJNVpE`PrVv5P%q*C~Ls-fR5>|r3lxw5-q%sKH04q~pDwxWY zXG=Qpsxn0dra&;LrW$0nHckg4=%d!;JH-+e6ELhMf+x`D36>gx(e?I37ns6iX|uep z1rgqXfUczC%y3yY0Xg{<%u#8w;nn7zyJ}4!Q2WeS+{%+Po75n%OAw53ZSq?G^S-B- z0x#Ft3ppb;1yv)$3oZmq5GsvXC7M8ufXiNVb}@>)_FxQ`?I36mqVXGwG=(HD&hfSm zpUwm)a@0}9O0%?>-=74XGm3A&?e%-n*uw7iqQOZRdfkfv+AwSfQLi)Vw*wfCg5gDY z(gFynEw;rEcQsoNN1>OZVO(fpJf=}5`-y?rP@)Q=Cl%4jNml?Kny zMpcQaNPh8zTWP0Q`fzR&l}`i!&u2o(Gj4UD#k#|)J&;j z_h2SVh-m?eC0rZDhoxb_4bUP9q=J!5csj!iuPhR#z~l@JQzH#BT^t_w4q%sQjkd?E zV2TRZFNcE1u*+jsXa*G1+Z&y;1co!~uZLux>byw5Ha1`?rW+)dL zD?Y?gYD6Xy$mxXPNMpt)h>Jpu#8`Fmm$5x6WRWe(L@+1pL44g53TZY$BhCkwg-a4< zMd?eG1vqy*a~(YNy}^-FT^`c-Z){5v#d0*p5f72AW~Oi{NYzx#l&XkVo8h41;?Ek7 z&!WKXz|9Ejq3hSLlXjz5of>k>+k_RBhioll3_!)_=lHl?uiS!;Sk*$Z$H>U4A#g(C zh$!40qHT1jxxxVqW dvF0@Yy$W;tKW~zz_pN2M%jEPQZ(ECS-vJNWaB2Vm literal 0 HcmV?d00001 diff --git a/src/rougail/structural_bitwarden/__pycache__/object_model.cpython-313.pyc b/src/rougail/structural_bitwarden/__pycache__/object_model.cpython-313.pyc new file mode 100644 index 0000000000000000000000000000000000000000..b81e69a9c44918134be099c29b18d382b2e055fa GIT binary patch literal 1381 zcmaJ>Uuzpj5Z{wde|$|SZBrVDQijq{3lyFIU`pdskd5Uiu_d9C8VrVGb+@|Pu)0-t z_oV8reQLfy=x4|mDn-z~^eJyCPTxCslIoVyF5GH%X6HBao0--1?b{B)b@=P6=*J=< zzh#HbDy@a^P^juuYl z+sdMQ>*&yuh)NBY$q_IlfdOVrX*>f`Sp`_5)sdRBLrs>j0y)i`YMA9>&3EnB_&4Dj zULo)#Pdb)Uq!A+;5}R`&V8kHRY@CX^GfE9SZ4VxGhXZJKF5zjj-*0vXmq&S>C0f~x zt#J5cDtOiasuWGk0&{jQPWva1@P6~Secm2iW*up@2c1*TgI2c>P3SfIgZ9bryxE7| zu;1%?rwsrP%Yyu!|0(ACl5MnxG*u;SG874#_z>(RM@V`MF zDr6F^2FUzvP>z6)A(5sIbH#BWjLhrykM21)-K#@82^w`c{1OHXYr>!>Xu#^=rJ47^ z!EPOnr8Y9D!$lKdcYkkh@4?=|?iT<@Td zM6N$W%}a7cl!ec);9078pLhjjUzM)PUh#9ZdbX-WrCNDe{e~(|M}ocHMs;hsHR9Ry zhb(zTI<@Mu>iY?uFyCJ~zK;{1icG%c`_EG<)|PjDf6SFOf+sAIzOSkXwX{c4iY3}; zg4N0=S)=QRzOS=W;8T-7Qo~TKw$SAoKeFt)v79hBO420#){VGvu{bm4Dw#&uTUV># zMm8!9Oo|W8|0{1-j-Ii=WXUqoz(0pFqUKx1P~XDs2lDfs?eE$z%un{VdT(Q{S^2F_ zt+K56ekcRXwrmzto. +""" + + +def get_rougail_config( + *, + backward_compatibility: bool = True, # pylint: disable=unused-argument +) -> dict: + return { + "name": "bitwarden", + "process": "structural", + "level": 90, + } + + +__all__ = ("get_rougail_config",) + diff --git a/src/rougail/structural_bitwarden/object_model.py b/src/rougail/structural_bitwarden/object_model.py new file mode 100644 index 0000000..ce7370b --- /dev/null +++ b/src/rougail/structural_bitwarden/object_model.py @@ -0,0 +1,31 @@ +""" +Silique (https://www.silique.fr) +Copyright (C) 2025 + +distribued with GPL-2 or later license + +This program is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2 of the License, or +(at your option) any later version. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with this program; if not, write to the Free Software +Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +""" +from typing import Optional +from pydantic import BaseModel + + +class Variable(BaseModel): + bitwarden: bool=False + + +__all__ = ('Variable',) + + diff --git a/src/rougail/user_data_bitwarden/__init__.py b/src/rougail/user_data_bitwarden/__init__.py index 237b084..c5212e7 100644 --- a/src/rougail/user_data_bitwarden/__init__.py +++ b/src/rougail/user_data_bitwarden/__init__.py @@ -1,3 +1,24 @@ +""" +Silique (https://www.silique.fr) +Copyright (C) 2025 + +distribued with GPL-2 or later license + +This program is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2 of the License, or +(at your option) any later version. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with this program; if not, write to the Free Software +Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +""" + from .data import RougailUserDataBitwarden RougailUserData = RougailUserDataBitwarden __all__ = ('RougailUserDataBitwarden',) diff --git a/src/rougail/user_data_bitwarden/annotator.py b/src/rougail/user_data_bitwarden/annotator.py new file mode 100644 index 0000000..5853627 --- /dev/null +++ b/src/rougail/user_data_bitwarden/annotator.py @@ -0,0 +1,64 @@ +""" +Silique (https://www.silique.fr) +Copyright (C) 2025 + +distribued with GPL-2 or later license + +This program is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2 of the License, or +(at your option) any later version. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with this program; if not, write to the Free Software +Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +""" +from rougail.error import DictConsistencyError +from rougail.annotator.variable import Walk +from .i18n import _ + + +class Annotator(Walk): + """Annotate for bitwarden""" + + level = 95 + + def __init__( + self, + objectspace, + *args, # pylint: disable=unused-argument + ) -> None: + if not objectspace.paths: + return + self.objectspace = objectspace + self.check_variable() + + def check_variable(self): + for variable in self.get_variables(): + if not variable.bitwarden: + continue + if variable.type not in ["unix_user", "secret"]: + msg = _('only "unix_user" or "secret" variable type can have "bitwarden" attribute, but "{0}" has type "{1}"') + raise DictConsistencyError(msg.format(variable.path, variable.type), 301, variable.xmlfiles) + if variable.multi and variable.path not in self.objectspace.leaders: + msg = _('the variable "{0}" has attribute "bitwarden" but is a multi variable') + raise DictConsistencyError(msg.format(variable.path), 302, variable.xmlfiles) + check_default_value = True + if variable.path in self.objectspace.followers: + leadership = variable.path.rsplit('.', 1)[0] + leader_path = self.objectspace.parents[leadership][0] + leader = self.objectspace.paths[leader_path] + if leader.bitwarden: + if variable.default: + msg = _('the variable "{0}" is a follower and leader variable ("{1}") is also in Bitwarden so this variable could not have default value') + raise DictConsistencyError(msg.format(variable.path, leader_path), 303, variable.xmlfiles) + check_default_value = False + if check_default_value and not variable.default: + msg = _('the variable "{0}" is in Bitwarden so should have default value') + raise DictConsistencyError(msg.format(variable.path), 304, variable.xmlfiles) + self.objectspace.informations.add(variable.path, "bitwarden", True) diff --git a/src/rougail/user_data_bitwarden/config.py b/src/rougail/user_data_bitwarden/config.py index 08c1b7c..45ebc51 100644 --- a/src/rougail/user_data_bitwarden/config.py +++ b/src/rougail/user_data_bitwarden/config.py @@ -23,8 +23,25 @@ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA def get_rougail_config(*, backward_compatibility=True, ) -> dict: + options = """ +step: + + structural: + redefine: true + default: + jinja: |- + {% if step.user_data == ['bitwarden'] %} + bitwarden + {% endif %} + {% if step.user_data == ['risotto'] %} + risotto + {% else %} + directory + {% endif %} +""" return {'name': 'bitwarden', 'process': 'user data', + "options": options, 'level': 90, } diff --git a/src/rougail/user_data_bitwarden/data.py b/src/rougail/user_data_bitwarden/data.py index 90a9d1b..d3b4043 100644 --- a/src/rougail/user_data_bitwarden/data.py +++ b/src/rougail/user_data_bitwarden/data.py @@ -21,6 +21,7 @@ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA from subprocess import run from json import loads +from os import environ from rougail.error import ExtentionError @@ -50,6 +51,7 @@ class RougailUserDataBitwarden: raise ExtentionError(_('"bitwarden" is not set in step.user_data')) self.errors = [] self.warnings = [] + self.leader_informations = {} def run(self): self.set_passwords(self.config) @@ -61,35 +63,79 @@ class RougailUserDataBitwarden: for option in optiondescription: if option.isoptiondescription(): self.set_passwords(option) - elif option.owner.isdefault() and option.type() == 'password': - key_bitwarden = option.value.get() - if not isinstance(key_bitwarden, str): - self.errors.append(_('the default value for "{0}" must be the Bitwarden password name').format(option.path())) - continue - try: - cpe = run(["bw", "list", "items", "--search", key_bitwarden, '--nointeraction'], capture_output=True) - except Exception as exc: - self.errors.append(_('cannot execute the "bw" commandline from Bitwarden for "{0}": {1}').format(option.path(), exc)) - continue - out = cpe.stdout.decode('utf8') - err = cpe.stderr.decode('utf8') - if cpe.returncode != 0 or err: - self.errors.append(_('cannot get password "{0}" from Bitwarden for "{1}": {2} ({3})').format(key_bitwarden, option.path(), err, cpe.returncode)) - continue - try: - data = loads(out) - except Exception as exc: - self.errors.append(_('cannot load password "{0}" from Bitwarden for "{1}": {2}').format(key_bitwarden, option.path(), exc)) - continue - if not data: - self.errors.append(_('cannot find password "{0}" from Bitwarden for "{1}"').format(key_bitwarden, option.path())) - continue - if len(data) != 1: - names = [d["name"] for d in data] - self.errors.append(_('several passwords found with name "{0}" from Bitwarden for "{1}": "{2}"').format(key_bitwarden, option.path(), "\", \"".join(names))) - continue - try: - option.value.set(data[0]['login']['password']) - except Exception as exc: - self.errors.append(_('unexpected password "{0}" from Bitwarden for "{1}": {2}').format(key_bitwarden, option.path(), exc)) + elif option.information.get('bitwarden', False): + path = option.path() + if not option.owner.isdefault(): + if option.isfollower(): + self.errors.append(_('the value for "{0}" at index {1} is already set while it should be filled in by Bitwarden').format(path, option.index())) + else: + self.errors.append(_('the value for "{0}" is already set while it should be filled in by Bitwarden').format(path)) continue + type_ = option.information.get('type') + if option.isleader(): + leader_values = [] + self.leader_informations[path] = [] + for val in option.value.get(): + names, values = self.get_values(path, type_, val, allow_multiple=True) + print(names, values) + if isinstance(values, list): + leader_values.extend(values) + self.leader_informations[path].extend(names) + else: + leader_values.append(values) + self.leader_informations[path].append(names) + option.value.set(leader_values) + else: + if option.isfollower(): + leader_path = optiondescription.leader().path() + if leader_path in self.leader_informations: + key_bitwarden = self.leader_informations[leader_path][option.index()] + else: + key_bitwarden = option.value.get() + else: + key_bitwarden = option.value.get() + option.value.set(self.get_values(path, type_, key_bitwarden)[1]) + + def get_values(self, path, type_, key_bitwarden, *, allow_multiple=False): + if not isinstance(key_bitwarden, str): + self.errors.append(_('the default value for "{0}" must be the Bitwarden item name').format(path)) + return None, None + if 'ROUGAIL_BITWARDEN_MOCK_ENABLE' in environ: + if type_ == 'secret': + return 'Ex4mpL3_P4ssw0rD' + return 'example_login' + try: + cpe = run(["bw", "list", "items", "--search", key_bitwarden, '--nointeraction'], capture_output=True) + except Exception as exc: + self.errors.append(_('cannot execute the "bw" commandline from Bitwarden for "{0}": {1}').format(path, exc)) + return None, None + out = cpe.stdout.decode('utf8') + err = cpe.stderr.decode('utf8') + if cpe.returncode != 0 or err: + self.errors.append(_('cannot get {0} "{1}" from Bitwarden for "{2}": {3} ({4})').format(type_, key_bitwarden, path, err, cpe.returncode)) + return None, None + try: + data = loads(out) + except Exception as exc: + self.errors.append(_('cannot load {0} "{1}" from Bitwarden for "{2}": {3}').format(type_, key_bitwarden, path, exc)) + return None, None + if not data: + self.errors.append(_('cannot find {0} "{1}" from Bitwarden for "{2}"').format(type_, key_bitwarden, path)) + return None, None + if len(data) != 1: + names = [d["name"] for d in data] + if allow_multiple: + ret = [] + return names, [self.get_value(key_bitwarden, path, type_, d) for d in data] + self.errors.append(_('several items found with name "{0}" from Bitwarden for "{1}": "{2}"').format(key_bitwarden, path, "\", \"".join(names))) + return None, None + return data[0]['name'], self.get_value(key_bitwarden, path, type_, data[0]) + + def get_value(self, key_bitwarden: str, path: str, type_: str, data: dict) -> str: + try: + if type_ == 'secret': + return data['login']['password'] + return data['login']['username'] + except Exception as exc: + self.errors.append(_('unexpected datas "{0}" from Bitwarden for "{1}": {2}').format(key_bitwarden, path, exc)) + return None diff --git a/src/rougail/user_data_bitwarden/locale/fr/LC_MESSAGES/user_data_bitwarden.mo b/src/rougail/user_data_bitwarden/locale/fr/LC_MESSAGES/user_data_bitwarden.mo new file mode 100644 index 0000000000000000000000000000000000000000..7100f303a79750e99629ea48fada96c02709be1c GIT binary patch literal 2725 zcmcIlO^+Kz5N$~KG65tmZ~&z>m)#Ya#r9^UjROKU2`I1;E3`!6fTH$H+3qmz8M=GC zwpJFufCC8b95Dxe1Cp;CIRbwKA@OR)<1ZXG2r*Lod1kt*x?WYi`TfO<-wIqWV7-F% z4c1Fommb3pt{!k3sDbYQzXt9Ce*qo99`Frd1k8Xp_&xAC@Z}3ad;&ZH9sz#@ z-UR*u`~vv)MIqh-{sg=V6i*28Ctx4A1KfL3i1&e?0y)n2z(e4#K#qU;DIpy29`G3W zGw=i8t528DH895gZ$S2Q_>2%=0lx(DzRNWst^q#-A|(zlE@3erIFfi4YyCoM0>>|| z=kW_uf#Znhun=Z`;V1%O$}4DVf2wRuCXm`mlX~gMOKqg{l{wPYSm7V^e7_< zB4keuIQ=TqKq~L8ZiARB62E2E*yT!-B2(dLKvpGEd+IxolY@s-?R(OwKD;qeo7n(O zExcz^nD&@DDo;F)mE_>OB3brx=ViMr&7ue#t%y+AuG=UsbxcDp5Z7NNmQ*|{df>FD zk+Via^wKy)J3B}wU?a`vp8$JI=XEVl2R+z{+!z;Wq*&GSUCtlAhH9OIYlVV#Z zO_KDKtVGMo1gYZhyu8~*opwqdT*_%Kc*MQ$!N+`eRFJ|mQFOyfRUQ(5-QkSb4feUA zVMdV$**tyj-1b0sh+~^RfK7Ni4)2n6IyEg>JN_{Ihz6SP!kfxdOE&Ax{jlB)8%^2R zZ|z-st=_2DYe&lY@Wd+P66I41%OhpFx$07QLaM)X-$Iwx?%cj}YZ0ZfTd&S(h>>RYqtW8cruHW>zLj zCc2B~G3L7zw3)nRX>OOgptxPqw91vYX^!b$QmV~{Jj0cZ<>=XTVjsh@e%xw2x zm_vhd%rv@d(Z@)+(6try%NObgss^a5RD)E5sjX@dm*?<`>?_PhIj!Kba>)uWvLtt! za_i)Dl1wLkID;-SVbcjlcR&#v7<@WP`_0TPi6E*49fLlfl=w&&OwM-A zl(iC6-mY@zbUBW5Ccv7BKp+Nu(T`Pcm;HvS{Jqu>IZ-j|YtDx@QG+TE|h-3*NB1kYG1kw0rhVE@yvYpw?&bBn9(LdoI z@U6yIV|?+Y|HF@8;giNQEnA9#2u^Zyc6R2T`!VN!y*=?(VBLh>fkm)eun#b|zQd+q zKVT1GrAtE00M~&Fz&F4-;1}R3@F#E)xOiEJ2f)|BU%*emY2e2zLOcO}1G;;6Cxmzk z+y^cLKLeiue*-sx+gF8{2fhP>THJtvO5k{qGk%L}Ft1I=^D2WwQ-RLGQ6@*mRhRTP2 zw;a-8&@CA1v5F{_S=QDj8lIo-7<9{pPXj5P(*?1rU79+a=}s5kiI(S%IB*vkx7f&J z6f;9DInr*&c8`>7qIOr;nR$meuOfZdrHJb?Pb{@$lA}dMPpFw^mUf4oJnq@3N*6`s ziVsq*S-xQYTSo80&0CAS7i_XvtB^`to8C6JVz={_rR9*Ses$LKtDZkgK@e7hdw$^i zrFEHEZ^uZLCDLjG&vmI9xoohv!?HQH57B_q#@fcpag?CqmmXY8>ytmW|DeXW7j;xY)D5%Vq zUV29tT#j3squA06{)=%73?j;Xt#vPS0+4<$@Z%nNATlNN$Gox~}<@HZ}#wBIuq=NOlMLFYQ&_)jX4CV3Wf zZZcO2I#|>)sIlM6NVd4K;Y6HSU@;PCFeU+{=!>DK-@|m^fn0Nk43Wk=_TO8> el&b+V;+|+F_M?FjCr)A|ArTej|IP;UDgFS{M#)A1 diff --git a/tests/results/1_secret/errors/bitwarden.json b/tests/results/1_secret/errors/bitwarden.json new file mode 100644 index 0000000..217db0a --- /dev/null +++ b/tests/results/1_secret/errors/bitwarden.json @@ -0,0 +1,4 @@ +{ + "errors": [], + "warnings": [] +} \ No newline at end of file diff --git a/tests/results/1_secret/makedict/bitwarden.json b/tests/results/1_secret/makedict/bitwarden.json new file mode 100644 index 0000000..fa80369 --- /dev/null +++ b/tests/results/1_secret/makedict/bitwarden.json @@ -0,0 +1,3 @@ +{ + "rougail.secret": "bitwarden_password" +} \ No newline at end of file diff --git a/tests/results/2_username_secret/errors/bitwarden.json b/tests/results/2_username_secret/errors/bitwarden.json new file mode 100644 index 0000000..217db0a --- /dev/null +++ b/tests/results/2_username_secret/errors/bitwarden.json @@ -0,0 +1,4 @@ +{ + "errors": [], + "warnings": [] +} \ No newline at end of file diff --git a/tests/results/2_username_secret/makedict/bitwarden.json b/tests/results/2_username_secret/makedict/bitwarden.json new file mode 100644 index 0000000..dd5d89d --- /dev/null +++ b/tests/results/2_username_secret/makedict/bitwarden.json @@ -0,0 +1,4 @@ +{ + "rougail.username": "bitwarden_username", + "rougail.secret": "bitwarden_password" +} \ No newline at end of file diff --git a/tests/results/3_leadership_secret/errors/bitwarden.json b/tests/results/3_leadership_secret/errors/bitwarden.json new file mode 100644 index 0000000..217db0a --- /dev/null +++ b/tests/results/3_leadership_secret/errors/bitwarden.json @@ -0,0 +1,4 @@ +{ + "errors": [], + "warnings": [] +} \ No newline at end of file diff --git a/tests/results/3_leadership_secret/makedict/bitwarden.json b/tests/results/3_leadership_secret/makedict/bitwarden.json new file mode 100644 index 0000000..3a72ff2 --- /dev/null +++ b/tests/results/3_leadership_secret/makedict/bitwarden.json @@ -0,0 +1,12 @@ +{ + "rougail.leader.username": [ + { + "rougail.leader.username": "bitwarden_username", + "rougail.leader.secret": "bitwarden_password" + }, + { + "rougail.leader.username": "bitwarden_username_2", + "rougail.leader.secret": "bitwarden_password_2" + } + ] +} \ No newline at end of file diff --git a/tests/results/3_leadership_secret_several/errors/bitwarden.json b/tests/results/3_leadership_secret_several/errors/bitwarden.json new file mode 100644 index 0000000..217db0a --- /dev/null +++ b/tests/results/3_leadership_secret_several/errors/bitwarden.json @@ -0,0 +1,4 @@ +{ + "errors": [], + "warnings": [] +} \ No newline at end of file diff --git a/tests/results/3_leadership_secret_several/makedict/bitwarden.json b/tests/results/3_leadership_secret_several/makedict/bitwarden.json new file mode 100644 index 0000000..44a823a --- /dev/null +++ b/tests/results/3_leadership_secret_several/makedict/bitwarden.json @@ -0,0 +1,12 @@ +{ + "rougail.leader.username": [ + { + "rougail.leader.username": "test_multi_username1", + "rougail.leader.secret": "test_multi_password1" + }, + { + "rougail.leader.username": "test_multi_username2", + "rougail.leader.secret": "test_multi_password2" + } + ] +} \ No newline at end of file diff --git a/tests/results/4_several_secrets/errors/bitwarden.json b/tests/results/4_several_secrets/errors/bitwarden.json new file mode 100644 index 0000000..6a829c3 --- /dev/null +++ b/tests/results/4_several_secrets/errors/bitwarden.json @@ -0,0 +1,6 @@ +{ + "errors": [ + "several items found with name \"test_secret_\" from Bitwarden for \"rougail.secret\": \"test_secret_1\", \"test_secret_2\"" + ], + "warnings": [] +} \ No newline at end of file diff --git a/tests/results/4_several_secrets/makedict/bitwarden.json b/tests/results/4_several_secrets/makedict/bitwarden.json new file mode 100644 index 0000000..fd8daba --- /dev/null +++ b/tests/results/4_several_secrets/makedict/bitwarden.json @@ -0,0 +1,3 @@ +{ + "rougail.secret": null +} \ No newline at end of file diff --git a/tests/results/test/00_6secret/errors/bitwarden.json b/tests/results/test/00_6secret/errors/bitwarden.json deleted file mode 100644 index 1563bb3..0000000 --- a/tests/results/test/00_6secret/errors/bitwarden.json +++ /dev/null @@ -1,7 +0,0 @@ -{ - "errors": [ - "the default value for \"secret1\" must be the Bitwarden password name", - "cannot get password \"value\" from Bitwarden for \"secret2\": Vault is locked. (1)" - ], - "warnings": [] -} \ No newline at end of file diff --git a/tests/results/test/00_6secret/makedict/bitwarden.json b/tests/results/test/00_6secret/makedict/bitwarden.json deleted file mode 100644 index 98ad1d3..0000000 --- a/tests/results/test/00_6secret/makedict/bitwarden.json +++ /dev/null @@ -1,4 +0,0 @@ -{ - "secret1": null, - "secret2": "value" -} \ No newline at end of file diff --git a/tests/results/test_namespace/00_6secret/errors/bitwarden.json b/tests/results/test_namespace/00_6secret/errors/bitwarden.json deleted file mode 100644 index 5759673..0000000 --- a/tests/results/test_namespace/00_6secret/errors/bitwarden.json +++ /dev/null @@ -1,7 +0,0 @@ -{ - "errors": [ - "the default value for \"rougail.secret1\" must be the Bitwarden password name", - "cannot get password \"value\" from Bitwarden for \"rougail.secret2\": Vault is locked. (1)" - ], - "warnings": [] -} \ No newline at end of file diff --git a/tests/results/test_namespace/00_6secret/makedict/bitwarden.json b/tests/results/test_namespace/00_6secret/makedict/bitwarden.json deleted file mode 100644 index d21a23e..0000000 --- a/tests/results/test_namespace/00_6secret/makedict/bitwarden.json +++ /dev/null @@ -1,4 +0,0 @@ -{ - "rougail.secret1": null, - "rougail.secret2": "value" -} \ No newline at end of file diff --git a/tests/structures/1_secret/00-base.yml b/tests/structures/1_secret/00-base.yml new file mode 100644 index 0000000..941c2bb --- /dev/null +++ b/tests/structures/1_secret/00-base.yml @@ -0,0 +1,8 @@ +--- +version: 1.1 + +secret: + description: the second variable + type: secret + default: test_secret_1 + bitwarden: true diff --git a/tests/structures/2_username_secret/00-base.yml b/tests/structures/2_username_secret/00-base.yml new file mode 100644 index 0000000..5026895 --- /dev/null +++ b/tests/structures/2_username_secret/00-base.yml @@ -0,0 +1,14 @@ +--- +version: 1.1 + +username: + description: the username + type: unix_user + default: test_secret_1 + bitwarden: true + +secret: + description: the secret + type: secret + default: test_secret_1 + bitwarden: true diff --git a/tests/structures/3_leadership_secret/00-base.yml b/tests/structures/3_leadership_secret/00-base.yml new file mode 100644 index 0000000..d309428 --- /dev/null +++ b/tests/structures/3_leadership_secret/00-base.yml @@ -0,0 +1,18 @@ +--- +version: 1.1 + +leader: + type: leadership + + username: + description: the username + type: unix_user + default: + - test_secret_1 + - test_secret_2 + bitwarden: true + + secret: + description: the secret + type: secret + bitwarden: true diff --git a/tests/structures/3_leadership_secret_several/00-base.yml b/tests/structures/3_leadership_secret_several/00-base.yml new file mode 100644 index 0000000..5079719 --- /dev/null +++ b/tests/structures/3_leadership_secret_several/00-base.yml @@ -0,0 +1,17 @@ +--- +version: 1.1 + +leader: + type: leadership + + username: + description: the username + type: unix_user + default: + - test_multi_ + bitwarden: true + + secret: + description: the secret + type: secret + bitwarden: true diff --git a/tests/structures/4_several_secrets/00-base.yml b/tests/structures/4_several_secrets/00-base.yml new file mode 100644 index 0000000..0056345 --- /dev/null +++ b/tests/structures/4_several_secrets/00-base.yml @@ -0,0 +1,8 @@ +--- +version: 1.1 + +secret: + description: the second variable + type: secret + default: test_secret_ + bitwarden: true diff --git a/tests/structures/5_default_value/00-base.yml b/tests/structures/5_default_value/00-base.yml new file mode 100644 index 0000000..cbf3f97 --- /dev/null +++ b/tests/structures/5_default_value/00-base.yml @@ -0,0 +1,7 @@ +--- +version: 1.1 + +secret2: + description: the variable + type: secret + bitwarden: true diff --git a/tests/structures/6_leadership_secret_default_value/00-base.yml b/tests/structures/6_leadership_secret_default_value/00-base.yml new file mode 100644 index 0000000..029e2fa --- /dev/null +++ b/tests/structures/6_leadership_secret_default_value/00-base.yml @@ -0,0 +1,15 @@ +--- +version: 1.1 + +leader: + type: leadership + + username: + description: the username + type: unix_user + bitwarden: true + + secret: + description: the secret + type: secret + bitwarden: true diff --git a/tests/structures/6_leadership_secret_follower_variable/00-base.yml b/tests/structures/6_leadership_secret_follower_variable/00-base.yml new file mode 100644 index 0000000..d632e62 --- /dev/null +++ b/tests/structures/6_leadership_secret_follower_variable/00-base.yml @@ -0,0 +1,23 @@ +--- +version: 1.1 + +leader: + type: leadership + + username: + description: the username + type: unix_user + default: + - test_secret_1 + - test_secret_2 + bitwarden: true + + secret: + description: the secret + type: secret + default: + jinja: test_secret_{{ index + 1 }} + params: + index: + type: index + bitwarden: true diff --git a/tests/structures/8_multi_variable/00-base.yml b/tests/structures/8_multi_variable/00-base.yml new file mode 100644 index 0000000..00f78b3 --- /dev/null +++ b/tests/structures/8_multi_variable/00-base.yml @@ -0,0 +1,9 @@ +--- +version: 1.1 + +secret: + description: the secret variable + type: secret + default: + - test_secret_1 + bitwarden: true diff --git a/tests/structures/9_unknown_type/00-base.yml b/tests/structures/9_unknown_type/00-base.yml new file mode 100644 index 0000000..aa999f5 --- /dev/null +++ b/tests/structures/9_unknown_type/00-base.yml @@ -0,0 +1,6 @@ +--- +version: 1.1 + +secret: + description: the first variable + bitwarden: true diff --git a/tests/test_load.py b/tests/test_load.py index 4df4829..f3fbcad 100644 --- a/tests/test_load.py +++ b/tests/test_load.py @@ -1,68 +1,39 @@ import os -from pytest import fixture # , raises from pathlib import Path -from rougail import Rougail +from rougail import Rougail, RougailConfig +from rougail.error import DictConsistencyError ######################### -from dotenv import load_dotenv from rougail.user_data_bitwarden import RougailUserDataBitwarden as RougailUserData from json import load, dump ######################### - -from rougail_tests.utils import get_structures_list, get_rougail_config, get_values_for_config, config_to_dict - -EXT = "env" - -######################### -#let's save the original environment -save = os.environ.copy() -######################### +from pytest import raises -excludes = [] - -test_ok = get_structures_list(excludes) -test_ok = [Path('../rougail-tests/structures/00_6secret')] +from rougail_tests.utils import config_to_dict -def idfn(fixture_value): - return fixture_value.name +test_dir = Path(__file__).parent / 'structures' -@fixture(scope="module", params=test_ok, ids=idfn) -def test_dir(request): - return request.param - - -def _test_dictionaries(test_dir, namespace, ext): - rougailconfig = get_rougail_config(test_dir, namespace) - if not rougailconfig: - return - ################################## +def _test_dictionaries(test_dir): + rougailconfig = RougailConfig.copy() + rougailconfig['main_dictionaries'] = [str(test_dir)] +# rougailconfig['tiramisu_cache'] = "cache.py" rougailconfig['step.user_data'] = ['bitwarden'] - ################################## - dir_name = 'test' - if namespace: - dir_name += '_namespace' - elif (test_dir / 'force_namespace').is_file(): - return rougail = Rougail(rougailconfig) config = rougail.run() - ################################## - if not has_secrets(config): - return - ################################## # loads variables in the tiramisu config errors = RougailUserData(config, rougailconfig=rougailconfig).run() #expected output config_dict = dict(config_to_dict(config.value.get())) - ok_file = Path('tests') / 'results' / dir_name / test_dir.name / 'makedict' / 'bitwarden.json' + ok_file = Path('tests') / 'results' / test_dir.name / 'makedict' / 'bitwarden.json' if not ok_file.is_file(): ok_file.parent.mkdir(parents=True, exist_ok=True) with open(ok_file, 'a') as json_file: dump(config_dict, json_file, indent=4) with open(ok_file) as json_file: expected = load(json_file) - errors_file = Path('tests') / 'results' / dir_name / test_dir.name / 'errors' / 'bitwarden.json' + errors_file = Path('tests') / 'results' / test_dir.name / 'errors' / 'bitwarden.json' if not errors_file.is_file(): errors_file.parent.mkdir(parents=True, exist_ok=True) with open(errors_file, 'a') as json_file: @@ -77,27 +48,63 @@ def _test_dictionaries(test_dir, namespace, ext): # config.property.read_only() assert expected == config_dict - ###################################### - #teardown: set the original environement again - os.environ = save.copy() - ###################################### -def has_secrets(optiondescription): - for option in optiondescription: - if option.isoptiondescription(): - if has_secrets(option): - return True - elif option.information.get('type', None) == 'secret': - return True - return False - - -def test_dictionaries_all(test_dir): +def test_dictionaries_1_secret(): "tests the output" - _test_dictionaries(test_dir, False, EXT) + _test_dictionaries(test_dir / '1_secret') -def test_dictionaries_namespace_all(test_dir): +def test_dictionaries_2_username_secret(): "tests the output" - _test_dictionaries(test_dir, True, EXT) + _test_dictionaries(test_dir / '2_username_secret') + + +def test_dictionaries_3_leadership_secret(): + "tests the output" + _test_dictionaries(test_dir / '3_leadership_secret') + + +def test_dictionaries_3_leadership_secret_several(): + "tests the output" + _test_dictionaries(test_dir / '3_leadership_secret_several') + + +def test_dictionaries_4_several_secrets(): + "tests the output" + _test_dictionaries(test_dir / '4_several_secrets') + + +def test_dictionaries_5_default_value(): + "tests the output" + with raises(DictConsistencyError) as err: + _test_dictionaries(test_dir / '5_default_value') + assert err.errno == 304 + + +def test_dictionaries_6_leadership_secret_default_value(): + "tests the output" + with raises(DictConsistencyError) as err: + _test_dictionaries(test_dir / '6_leadership_secret_default_value') + assert err.errno == 304 + + +def test_dictionaries_6_leadership_secret_follower_variable(): + "tests the output" + with raises(DictConsistencyError) as err: + _test_dictionaries(test_dir / '6_leadership_secret_follower_variable') + assert err.errno == 303 + + +def test_dictionaries_8_multi_variable(): + "tests the output" + with raises(DictConsistencyError) as err: + _test_dictionaries(test_dir / '8_multi_variable') + assert err.errno == 302 + + +def test_dictionaries_9_unknown_type(): + "tests the output" + with raises(DictConsistencyError) as err: + _test_dictionaries(test_dir / '9_unknown_type') + assert err.errno == 301