web-dev-qa-db-fra.com

utiliser regex dans jinja 2 pour les playbooks ansible

HI je suis nouveau sur jinja2 et j'essaie d'utiliser l'expression régulière comme indiqué ci-dessous

{% if ansible_hostname == 'uat' %}
   {% set server = 'thinkingmonster.com' %}

{% else %}
   {% set server = 'define yourself' %}
{% endif %}

{% if {{ server }} match('*thinking*') %}
  {% set ssl_certificate = 'akash' %}

{% Elif {{ server }} match( '*sleeping*')%}
   {% set ssl_certificate = 'akashthakur' %}
{% endif %}

sur la base de la valeur de "serveur", je voudrais évaluer les certificats à utiliser. c'est-à-dire que si le domaine contient le mot-clé "thinking", utilisez ces certificats et s'il contient le mot-clé "sleep", utilisez ce certificat.

Mais je n'ai trouvé aucun filtre jinja2 supportant cela. S'il vous plaît, aidez-moi.J'ai trouvé du code python et sûr que cela peut fonctionner, mais comment utiliser python dans les modèles jinja2?

13
thinkingmonster

Donc, après avoir googlé pendant longtemps et avec l'aide de certains blogueurs, voici la solution finale à mon problème: -

1. Jinja2 n'a pas de filtre pour trouver des sous-chaînes ou des expressions rationnelles, donc la seule solution était de créer un filtre personnalisé. J'ai suivi les étapes ci-dessous pour résoudre mon problème.

2. Dans le répertoire racine de mon playbook, j'ai créé un répertoire "filter_plugins" et a écrit un module personnalisé dans python et placé le fichier dans ce répertoire. Le nom du fichier python peut être n'importe quoi. Mon python le code se présente comme suit:

 __author__ = 'akthakur'
class FilterModule(object):
    ''' Custom filters are loaded by FilterModule objects '''

    def filters(self):
        ''' Filter Module objects return a dict mapping filter names to filter functions. '''
        return {
            'substr': self.substr,
        }

        ''' def substr(self, check,checkin):
        return value1+value2'''
    def substr(self,check,checkin):
         if check in checkin:
            return True
         else:
            return False

. Une fois ce fichier créé, notre tout nouveau filtre "substr" est prêt à l'emploi et peut être utilisé dans des modèles comme indiqué ci-dessous:

{% if 5==5 %}
 {% set server = 'www.thinkingmonster.com' %}
{% endif %}
{% if 'thinking' | substr(server) %}
   {% set ssl_cert = 'abc.crt'%}
{% endif %}
4
thinkingmonster

Jinja2 peut très facilement faire des vérifications de substrats avec une simple comparaison `` en '', par exemple.

{% set server = 'www.thinkingmonster.com' %}
{% if 'thinking' in server %}
   do something...
{% endif %}

Votre filtre d'expression régulière de sous-chaîne n'est donc pas requis. Cependant, si vous souhaitez une correspondance regex plus avancée, il existe en fait des filtres disponibles dans ansible - voir les filtres regex dans http: // docs.ansible.com/playbooks_filters.html#other-useful-filters - curieusement, la syntaxe de votre correspondance ci-dessus est presque exacte.

+1 pour réponse de Bereal cependant, cela donne une alternative sympa sous la forme d'une carte.

13
Halberom

Un filtre "regex_replace" est disponible dans Ansible> 1.6

Autres filtres utiles Faites défiler vers le bas et vous verrez ceci:

Nouveau dans la version 1.6.

Pour remplacer du texte dans une chaîne par regex, utilisez le filtre "regex_replace":

# convert "ansible" to "able"
{{ 'ansible' | regex_replace('^a.*i(.*)$', 'a\\1') }}

# convert "foobar" to "bar"
{{ 'foobar' | regex_replace('^f.*o(.*)$', '\\1') }}

# convert "localhost:80" to "localhost, 80" using named groups
{{ 'localhost:80' | regex_replace('^(?P<Host>.+):(?P<port>\\d+)$', '\\g<Host>, \\g<port>') }}

Cela étant dit, regex est exagéré pour trouver une solution à ce problème particulier.

5
saranicole

Grâce à l'indication de Steve E., j'ai trouvé un moyen d'ajouter des expressions régulières dans une condition de modèle:

{% if server | regex_search('thinking') %}
....
{% endif %}
4
Alexander Svetkin

Il existe certains filtres (actuellement) non documentés dans Ansible 2.1 qui peuvent faire ce dont vous avez besoin:
Plugins Ansible/filter.core.py

Le filtre regex_search effectuera une expression régulière sur la chaîne et renverra la correspondance résultante. Quelque chose de similaire à cela fonctionnerait et serait contenu dans un rôle Ansible:

{% set server = 'www.thinkingmonster.com' %}
{% if regexp_search(server, 'thinking') %}
   do something...
{% endif %}

Il existe également un filtre regex_findall qui effectue une recherche find Python findall au lieu de regex).

Consultez la demande d'extraction d'origine pour plus d'informations

2
Steve E.

C'est plutôt moche, mais ça marche à partir de 1.6.

{% if server|regex_replace('.*thinking.*','matched') == 'matched' %}
  {% set ssl_certificate = 'akash' %}

{% Elif server|regex_replace('.*sleeping.*','matched') == 'matched' %}
   {% set ssl_certificate = 'akashthakur' %}
{% endif %}
2
Todd Lewis

À ma connaissance, il n'y a pas de filtre intégré pour cela dans Jinja2 ni parmi Ansible filtres supplémentaires , mais ce n'est pas un gros problème pour faire le vôtre:

certs = {'.*thinking.*': 'akash', '.*sleeping.*': 'akashthakur'}
def map_regex(value, mapping=certs):
    for k, v in mapping.items():
        if re.match(k, value):
            return v 

Ensuite, vous devrez ajouter un plugin de filtre à Ansible, afin qu'il utilise la fonction ci-dessus dans les modèles (comme {{server|ssl_cert}} si vous nommez le filtre ssl_cert).

Cela dit, une ancienne fonction ou un ancien dictionnaire transmis aux modèles et utilisé explicitement pourrait mieux convenir à ce travail.

1
bereal