Maîtriser le module URI d'Ansible

Maîtriser le module URI d'Ansible

Il est essentiel de savoir utiliser le module URI d'Ansible afin de pouvoir effectuer diverses tâches comme les requêtes API, le téléchargement de fichiers en HTTP, la création d'un web crawler etc...
Après cet article, vous serez en capacité de maîtriser le module URI d'Ansible.

Introduction

Dans cet article, je vais traiter plusieurs cas. Celui de la requête HTTP nécessitant d'injecter un JSON dans le body, d'envoyer des Headers ou encore différentes méthodes HTTP.

Afin de rester dans le thème du DevOps, je vais m'appuyer sur l'API du Docker Hub.

Une simple requête GET

Essayons de récupérer les informations de l'image Redis depuis le Docker Hub.
Il s'agira d'une simple requête GET, que je vais transposer en une task Ansible comme ceci :

---
- name: Récupérer les informations de l'image Docker Redis
  ansible.builtin.uri:
    url: https://hub.docker.com/v2/repositories/library/redis/
  register: get_redis_infos

- name: Afficher le résultat de l'image Redis
  debug:
    var: get_redis_infos
Résultat :
TASK [uri : Afficher le résultat de l'image Redis] **************************************************************************************************************************
ok: [localhost] => {
    "get_redis_infos": {
        "changed": false,
        "connection": "close",
        "content_type": "application/json",
        "cookies": {},
        "cookies_string": "",
        "date": "Mon, 28 Aug 2023 15:11:56 GMT",
        "elapsed": 0,
        "failed": false,
        "json": {
            "affiliation": null,
            "collaborator_count": 0,
            "content_types": [
                "image",
                "unrecognized"
            ],
            "date_registered": "2014-06-05T20:04:50Z",
            "description": "Redis is an open source key-value store that functions as a data structure server.",
            "full_description": "# Quick reference\n\n-\t**Maintained by**:  \n\t[the Docker Community](https://github.com/docker-library/redis)\n\n-\t**Where to get help**:  \n\t[the Docker Community Slack](https://dockr.ly/comm-slack), [Server Fault](https://serverfault.com/help/on-topic), [Unix & Linux](https://unix.stackexchange.com/help/on-topic), or [Stack Overflow]

Nous avons maintenant la variable get_redis_infos qui stocke les informations le JSON contenant les informations de l'image Docker Redis.

Une injection de JSON dans le Body (et pas de Botox dans les lèvres)

Voici le cas d'une requête HTTP un peu plus complexe où l'on va injecter un JSON dans le body. Notre body sera sous forme de YAML, mais sera équivalent à du JSON.

Pour cette requête, nous allons nous authentifier sur le Docker Hub à travers son API. Nous allons injecter dans le Body notre nom d'utilisateur ainsi que notre mot de passe.

---
- name: Authentification auprès du Docker Hub
  ansible.builtin.uri:
    url: https://hub.docker.com/v2/users/login
    method: POST
    body:
      username: MON_USER
      password: MON_MOT_DE_PASSE
    body_format: json
  register: auth_docker_hub

- name: Afficher le token d'Authentification
  debug:
    var: auth_docker_hub
Résultat :
TASK [uri : Afficher le token d'Authentification] ***************************************************************************************************************************
ok: [localhost] => {
    "auth_docker_hub": {
        "changed": false,
        "connection": "close",
        "content_type": "application/json",
        "cookies": {
            "csrftoken": "sapO9AdEOzwrj2qEMNYfOkFs9yEvFEi+zuBo1oSkJJM=",
            "token": "eyJ0eXAiOiJKV1QiLCJ4NWMiOlsiTUlJQytUQ0NBcCtnQXdJQkFnSUJBREFLQmdncWhrak9QUVFEQWpCR01VUXdRZ1lEVlFRREV6dFNUVWxHT2xGTVJqUTZRMGRRTXpwUk1rVmFPbEZJUkVJNlZFZEZWVHBWU0ZWTU9rWk1WalE2UjBkV1dqcEJOVlJIT2xSTE5GTTZVVXhJU1RBZUZ3MHlNekF4TURZd05ESTNORFJhRncweU5EQXhNall3TkRJM05EUmFNRVl4UkRCQ0JnTlZCQU1UTzBORFZVWTZTalZITmpwRlExTkVPa05XUkVjNlZEZE1NanBLV2taUk9sTk5NMFE2V0ZsUE5EcFdOME5IT2tkR1YwSTZXbG8xTmpvMFZVUkRNSUlCSWpBTkJna3Foa2lHOXcwQkFRRUZBQU9DQVE4QU1JSUJDZ0tDQVFFQXpOMGIwajdVeVwvYXNqWVhXaDJnM3FvNkpoT2tBalhXQVVCY3NIdTZoWVpSRkw5dmU4MTNUQjRjbDhRa3hDSTRjVWdHR25H

On peut voir qu'en spécifiant body_format: json, j'ai pu passer l'équivalent de ce JSON :

{
  "username": "MON_USER",
  "password": "MON_MOT_DE_PASSE"
}

En ce YAML :

  username: MON_USER
  password: MON_MOT_DE_PASSE

Les formulaires

Comme vous le savez, il est possible de remplir un formulaire HTML à l'aide d'une requête POST lorsqu'il s'agit de données encodées au format application/x-www-form-urlencoded.
J'ai donc auto-hébérgé le formulaire suivant pour cet exemple :

Essayons de remplir le formulaire suivant avec la task Ansible suivante :

---
- name: Login to Form
  uri:
    url: http://localhost:8000
    method: POST
    body_format: form-urlencoded
    follow_redirects: all
    body:
      username: admin
      password: admin
      enter: Login
    return_content: yes
  register: login
  changed_when: "'you have successfully logged in' in login.content"

- debug: 
    var: login.content
Résultat :
TASK [uri : Login to Form] **************************************************************************************************************************************************
changed: [localhost]

TASK [uri : debug] **********************************************************************************************************************************************************
ok: [localhost] => {
    "login.content": "<html>\n  <head>\n    <title>Form based App</title>\n    <meta name=\"viewport\" content=\"width=device-width, initial-scale=1.0\">\n    <link rel=\"stylesheet\" href=\"https://cdn.jsdelivr.net/npm/bootstrap@4.3.1/dist/css/bootstrap.min.css\" integrity=\"sha384-ggOyR0iXCbMQv3Xipma34MD+dH/1fQ784/j6cY/iJTQUOhcWr7x9JvoRxT2MZw1T\" crossorigin=\"anonymous\">\n<script src=\"https://cdn.jsdelivr.net/npm/bootstrap@4.3.1/dist/js/bootstrap.min.js\" integrity=\"sha384-JjSmVgyd0p3pXB1rRibZUAYoIIy6OrQ6VrjIEaFf/nJGzIxFDsf4x0xIM+B07jRM\" crossorigin=\"anonymous\"></script>\n<style type=\"text/css\">\n    body{\n      padding: 20vh;\n    }\n    .container{\n        border-left: 2px solid gray;\n    }\n  </style>  \n  </head>\n  <body>\n    <div class=\"container\">\n      <h5>you have successfully logged in<img src=\"/static/celebration.jpeg\" height=\"80px\" width=\"80px\"></img><h5> \n        <h1>Welcome to the Sample Form Login App</h1>\n        <hr></hr>\n    </div>\n  </body>\n</html>"
}

Il faut noter que grâce à return_content, j'ai pu parser la réponse HTTP pour ensuite vérifier dans la clause when, si elle contenait bien la chaîne de caractères you have successfully logged in.

Conclusion

Le module URI d'Ansible est très complet et permets d'effectuer des requêtes HTTP en toute simplicité. L'utilisation de variables Jinja et des boucles loop facilitent également ces requêtes.

Ce module offre donc une multitude de possibilités, comme la création de crawlers web, de scraping ou encore de supervision !