Pour la première fois de ma carrière, je me lance dans l’écriture d’un article. Pourquoi seulement maintenant ? Parce que j’ai rencontré de nombreuses difficultés à rechercher des solutions techniques pour simplement synchroniser des fichiers entre un dossier Google Drive et un bucket sur GCP. Je m’imaginais pourtant qu’il existait déjà des solutions clés en main répondant à cette problématique, mais j’ai été assez surpris de découvrir que : 1) ce n’était pas le cas ; 2) il n’y avait pas beaucoup d’informations autour de ce cas d’usage. Je souhaitais donc apporter ma pierre à l’édifice et vous partager une solution permettant d’avoir une synchronisation automatique entre votre dossier Google Drive et votre bucket GCP. Cette solution n’est clairement pas parfaite mais c’est une solution qui fonctionne (pour l’instant).
Pourquoi la synchronisation entre un dossier Google drive et votre bucket GCP n’existe pas nativement ?
Si vous recherchez dans votre console GCP des ressources liées à Google Drive, vous allez uniquement tomber sur l’API externe Google Drive. On peut ainsi en déduire que les ressources Google Drive sont externalisées par rapport à votre environnement GCP.
Donc, vous n’avez pas la possibilité de capter un événement Google Drive (ajout, modification, suppression de ressource) directement dans GCP (Eventarc, logs…). Cependant rien n’est perdu.
Ma solution technique étape par étape
En effet, en fouillant la documentation de l’API Drive, on peut trouver une route “watch” : https://developers.google.com/drive/api/reference/rest/v3/files/watch?hl=en
Cette route permet à partir d’un objet Channel, contenant l’adresse HTTP d’un callback et d’un id de ressource Drive (dossier ou fichier), de créer un webhook lorsqu'une opération est faite sur la ressource voulue.
⚠️ L’opération de renommage d’un fichier ne déclenche pas un webhook.
L’idée derrière tout cela est de surveiller l’état d’une ressource Google Drive via un webhook qui ira déclencher une Cloud Function pour s’occuper de la partie synchronisation des fichiers.
Le webhook Google Drive
Maintenant, voyons ce que contient une requête d’un webhook HTTP créée sur un dossier Google Drive :
Ce qui nous intéresse ici, ce sont les champs suivants :
- X-Goog-Changed : indique le niveau du changement détecté
- X-Goog-Resource-Uri : indique l’url de la ressource surveillée
- X-Goog-Resource-State : indique l’action de la mise à jour (ça peut être update ou delete)
Il faudra donc installer ces dépendances :
Voilà ce que donne le code en python pour créer le webhook :
Lorsqu’on crée le webhook, l’API Google Drive nous renvoie un id du webhook généré côté backend. Je n’ai pas trouvé de moyen pour fixer cet id. Ceci est nécessaire si vous voulez supprimer le webhook dans votre utilisation. A vous de voir comment vous souhaitez le stocker.
Récupérer le détail de l’opération de modification
Le contenu des headers du webhook est assez succinct. Nous savons seulement s’il y a eu une action d’ajout ou de suppression d’un fichier dans le dossier surveillé. Il faudra donc chercher plus de détails à propos de l’action dans l’API Drive Activity. Cette API est utilisée pour afficher toutes les activités d’une ressource (ainsi que les enfants de la ressource).
Donc, grâce à cette API, nous pouvons récupérer les informations du fichier liées à l’action détectée, notamment son nom, son format et son id dans Google Drive. Voilà ce que cela donne en Python :
Cloud Function pour mettre à jour l’état du bucket
La création du webhook étant terminée, il nous reste à implémenter le code qui téléchargera le fichier récemment uploadé ou récupérera le nom du fichier récemment supprimé pour synchroniser l’état du bucket via les clients des différentes APIs. Ce code sera exécuté dans une Cloud Function car cela est très utile pour déployer du code uniquement pour une fonction, et puis cela propose automatiquement un endpoint pour déclencher la fonction via une requête POST ou GET.
⚠️ Lors de la création de la Cloud Function via la console GCP ou TerraForm, il sera important de ne pas oublier d’autoriser l’accès au déclenchement HTTP à “allUsers” car la requête HTTP du webhook ne portera pas de token d’authentification.
Sélim, Lead Tech MLOps chez Valeuriad