*

n8n & Warp 10 - Automatisez vos manipulations de séries temporelles


18/10/2021 n8n automation warp10 timeseries workflow

Il y a quelques temps et sachant que j’utilisais n8n pour automatiser la génération des brèves du BigData Hebdo, Mathias m’a demandé s’il était possible de faire la même chose entre n8n et Warp 10 qu’avec node-red et Warp 10.

La réponse est oui mais voyons comment faire cela.

n8n/Warp 10 - workflow

Pour ceux qui ne connaissent pas n8n, c’est un clone open source (sous licence fair-code) à des services comme Zapier ou IFTTT. Il permet d’automatiser des processus via la création de workflows. Ces workflows sont composés d’étapes et d’actions. n8n dispose d’un grand nombre de connecteurs vers les différents services existants, des opérateurs génériques (faire un appel http, appliquer une fonction), des opérateurs logiques (si, etc), des opérateurs de transformation de données, etc. Chacun de ces éléments est implémenté via une node. A chaque étape du workflow, une node est instanciée puis paramétrée. Les nodes peuvent être reliées entre-elles et la sortie d’une node peut alimenter la suivante.

Le workflow se veut basique et va être le suivant :

  • Récupération d’une entrée de monitoring CPU dans Warp 10
  • Si la valeur est supérieure ou égale à 90%, alors création d’une entrée dans une série dédiée à cet effet.

Ce n’est pas le workflow le plus passionnant du monde, mais cela permet de faire deux appels à l’API HTTP de Warp 10 :

  • Le premier permet de tester l’exécution de code WarpScript via l’API /api/v0/exec ; vu le code, j’aurais pu passer par /api/V0/fetch mais cela me permet de tester l’exécution de code WarpScript.
  • Le second utilisera l’API /api/v0/update pour insérer une donnée dans une série. Cela permet de tester le passage du token d’authentification via un header.

Pour commencer le workflow, la donnée de départ est la valeur en pourcentage du métrique “CPU Idle” d’un de mes serveurs.

En WarpScript, cela donne:

'<readToken>' 'readToken'  STORE

[ $readToken 'crnt-ovh.cpu.usage_idle' { "host" "crnt-d10-gitlab" "cpu" "cpu-total" }  NOW -1 ] FETCH

Et la réponse :

[
	[{
		"c": "crnt-ovh.cpu.usage_idle",
		"l": {
			"host": "crnt-d10-gitlab",
			"cpu": "cpu-total",
			"source": "telegraf",
			".app": "io.warp10.bootstrap"
		},
		"a": {},
		"la": 0,
		"v": [
			[1634505650000000, 91.675025]
		]
	}]
]

n8n dispose d’une node HTTP Request, qui comme son nom l’indique permet de faire des requêtes HTTP vers un serveur distant. Toutefois, il n’est pas possible de passer notre code WarpScript directement dans l’appel HTTP. Il faut créer un objet avec le code WarpScript et passer ensuite l’objet créé et le nom de la propriété contenant le code WarpScript à la node HTTP Request.

Pour stocker le code WarpScript dans un objet, il faut utiliser la node Set. Une fois la node Set ajoutée dans le workflow, aller dans Parameters > Add Value > Type: String

Saisir:

  • Name: warpscript
  • Value: le code WarpScript ci-dessus

En cliquant sur “Execute Node”, on peut valider la variable (la partie grisée étant mon token) :

n8n/Warp 10 - set node

On peut maintenant ajouter une node HTTP Request dans le workflow et la relier à la node Set nouvellement créée. Ainsi, la node HTTP Request aura directement accès au résultat de la node Set.

Pour les ajustements à faire :

  • Parameters :
    • Request Method : POST
    • URL : http://url.de.votre.instance.warp.10/api/v0/exec
    • Activer la case JSON/RAW Parameters
  • Options :
    • Add Option > Mime Type : text/plain
    • Add Option > Body Content Type : RAW/Custom
    • Body Parameters > Add Expression > Current Node > Input Data > JSON > warpscript (les colonnes de droites doivent se remplir avec la clé en haut et la valeur en dessous ; cliquer sur la croix pour revenir à l’écran précédent)

En cliquant sur “Execute Node”, le résultat de la requête est visible (la partie grisée étant un bout de mon token) :

n8n/Warp 10 - http request node

On retrouve notre objet JSON mais il est imbriqué dans des Array Javascript, on va applanir tout ça et extraire le timestamp et la valeur du cpu via l’ajout de deux nodes Function que l’on relie à la node HTTP Request. La node Function permet d’exécuter du code javascript sur les données et de réaliser des transformations que l’on ne peut pas forcément faire avec les autres nodes. Cela n’étant pas le coeur du sujet, cela ne sera pas détaillé.

A l’issue des deux exécutions, les données sont réduites à ce qui suit :

[{
	"ts": 1634503660000000,
	"cpu": 93.219488
}]

La node IF ne sera pas détaillée non plus ; elle sert juste à introduire un semblant de logique dans le workflow. En l’occurence, si la valeur de “cpu” >= 90, alors le test est considéré comme vrai et faux sinon. Dans le cas où c’est faux, une node noOp a été ajoutée pour matérialiser la fin du workflow.

Dans le cas où le test est vrai (valeur de “cpu” >= 90), on veut alors insérer le timestamp et la valeur dans une autre série sur une instance Warp 10. Comme précédemment, cela va se faire en deux fois:

  • Préparation de la donnée au format GTS Input Format et mise à disposition sous la forme d’une propriété
  • Exécution de l’appel HTTP.

On ajoute une node Set, ensuite dans Parameters > Add Value > Type: String

Saisir:

  • Name: gtsinput
  • Value > Add Expression et dans la partie expression, on met:
{{$json["ts"]}}// n8n{} {{$json["cpu"]}}

Ce qui nous donne l’écran suivant :

n8n/Warp 10 - set node 2 - expression

On revient à l’écran précédent en cliquant sur la croix à droite et en exécutant la node, on obtient :

n8n/Warp 10 - set node 2 - result

Ensuite, il faut ajouter une nouvelle node HTTP Request avec le paramétrage suivant :

  • Parameters :
    • Authentication > Header Auth
    • Request Method : POST
    • URL : http://url.de.votre.instance.warp.10/api/v0/update
    • Activer la case JSON/RAW Parameters
  • Options :
    • Add Option > Mime Type : text/plain
    • Add Option > Body Content Type : RAW/Custom
    • Add Option > Full Response et activer là pour voir la réponse complète de votre instance Warp 10
    • Body Parameters > Add Expression > Current Node > Input Data > JSON > gtsinput (les colonnes de droites doivent se remplir avec la clé en haut et la valeur en dessous ; cliquer sur la croix pour revenir à l’écran précédent)

En haut du menu de gauche, une section “Credentials” est apparue ; dans la liste déroulante, cliquer sur “Create new” et remplissez le formulaire de la façon suivante:

  • Name: X-Warp10-Token
  • Value : votre token Warp 10 avec des droits d’écriture

n8n/Warp 10 - auth token

Revener ensuite dans votre node HTTP Request dont on peut lancer l’exécution et on obtient :

n8n/Warp 10 - auth token

Si je vais ensuite voir le contenu de ma série n8n :

'<readToken>' 'readToken'  STORE

[ $readToken 'n8n' {}  NOW -100 ] FETCH

J’obtiens comme réponse :

[
	[{
		"c": "n8n",
		"l": {
			".app": "io.warp10.bootstrap"
		},
		"a": {},
		"la": 0,
		"v": [
			[1634503660000000, 93.219488],
			[1634502790000000, 94.808468],
			[1634501690000000, 93.7751],
			[1634501550000000, 91.741742],
			[1634478300000000, 92.774711]
		]
	}]
]

Avec une entrée pour chaque exécution du workflow sous réserve d’avoir un “CPU idle” >= 90%.

En conclusion, nous pouvons retenir que :

  • Il est facile d’intégrer Warp 10 dans un workflow n8n grâce à l’API HTTP de Warp 10 et la node HTTP Request de n8n
  • Pour interagir avec Warp 10, il faut d’abord créer un objet portant le code WarpScript ou les donées au format GTS Input pour l’envoyer ensuite à Warp 10 via la node HTTP Request
  • Même si cela n’a pas été détaillé, il est possible de manipuler les données issues de Warp 10 ou de préparer des données à destination de Warp 10.

Le workflow était très basique pour permettre de montrer rapidement cette intégration. Des workflows plus complexes et riches sont laissés à votre imagination :

  • sur la base d’un événement avec la node Webhook : insertion de données ou lancement d’une analyse suite à un événement, etc.
  • sur la base d’une tache planifiée avec la node Cron : analyse de données, etc
  • ou depuis Warp 10, on peut appeler n8n en utilisant HTTP, URLFETCH ou WEBCALL pour lancer l’exécution d’un workflow ou récupérer le résultat d’un workflow.

Syndication

Restez informé(s) de notre actualité en vous abonnant au flux du blog (Atom)

Nuage de tags

kubernetes docker timeseries influxdb warp10 traefik grafana ansible elasticsearch kafka postgres python aws sécurité terraform mysql redis telegraf ovh tick cassandra chronograf cloud dashboard docker-compose git hashicorp helm timescaledb flux ptsm swarm vector kapacitor podman rancher résilience test gcp gitlab influxdata log machine-learning monitoring prometheus s3 spark timescale vscode architecture arm comptabilité confluent devops gitlab-ci iac java ksql microservice nomad postgresql raspberrypi serverless service-mesh sql angularjs api bilan cert-manager cncf consul container cérénit dns flows gke graphql ingress javascript npm opensource operator optimisation perspective pipeline rook scaleway ssh stream vault warpscript windows cli containerd csp discovery documentation elastic forecast geospatial golang hpkp influxace iot jenkins kafka-streams kibana kubedb lambda lean licence maesh maintenance mariadb microsoft mobile nginx orientdb performance quasardb redhat registry rest rethinkdb reverse-proxy sauvegarde warpstudio agile anomalie apm arima audit automatisation azure bash big-data bigdatahebdo ceph certificat challenge ci/cd cluster continous-delivery continous-integration cookie data datatask dataviz dbt deployment diff facebook fec fluxlang framework gdpr grav hsts http/3 https hypriot hébergement ia influxdays istio jq json k3s lets-encrypt linux load-balancer longhorn meetup metabase molecule mongodb nosql nvidia openebs openssh ovhcloud percona php pip questdb reaper replication rootless rpi rsyslog runc scale secrets société solr sre systemd tempo timezone tls virtualenv vitess vue.js wagtail warpfleet yarn accessibilité acme adoptopenjdk agpl akka alerte alertes alerting alibaba amazon-emr amqp anonymisation anthos apache-pulsar ara arrow artefact automation automl banque bastion beam beat bi bme680 bootstrap bounded-context branche brigade browser buildah buildkit cahier-des-charges calico cassandra-reaper cd cdc cdk centos centralisation-de-logs certificats cgroups chart check checklist chrome ci cilium circuitpython clever-cloud clickhouse cloud-init cloud-native cloud-storage cloudflare clusterip cnab cni co2 cockroachdb code codeurs-en-seine commit confluence conftest consul-connect context continous-deployment conventional-commit coreos cors covid19 cqrs crash cri cron crontab csi csrf css curl d3.js daemonset data-engineer data-pipelining data.gouv.fr databricks datacenter date date-scientist ddd debezium debian delta deprek8 desktop devoxx dig distributed-systems dive docker-app docker-hub docker-registry docker-swarm dockershim documentdb dog dokcer données-personnelles draft drop-in duration déploiement développement-du-site e-commerce ebs ec2 edge elassandra electron elk engineering entreprise ergonomie etcd euclidia event-sourcing faas faisabilité falco falcor feature-policy fedora feed filebeat firebase firefox fish flash flask fleet flink fluentd formation foundation frenchtech frontend fsync fullstack git-filter-repo github gitignore glacier glowroot go google google-cloud-next gpg gpu grid géospatial hacker hadoop haproxy harbor hdfs header holt-winters html html5 http hue iaac ibm immutable incident index indluxdata influxcloud infrastructure-as-code ingénierie inspec jquery jvm jwt k3d k6 k8s k9s kaniko katz kotlin kubeadm kubecon kubectl label laravel leap-second lens letsencrypt libssh linky linter liste-de-diffusion lmap loadbalancer logstash logstatsh loi loki lstm mailing-list management maturité mesh mesos message metallb micro-service minio mot-de-passe mqtt multi-cloud médecine métrique n8n network newsletter nodejs nodeport notebook notifications nrtsearch null object-storage observability observabilité opa opendata openhab openmetrics openshit openstack openweb opnsense over-engineering packaging pandas parquet partiql password persistent-volume-claim pico pipenv pivot pod portainer portworx prediction prescience production promql prophet prévision psp ptyhon publicité pubsub pulsar push pyenv pérénnité qualité quay queue quic ram rambleed raml react readme recaptcha recherche redistimeseries reindex reinvent reliability remote-execution repository responsive retention-policy revocation revue-de-code rexec rgpd rhel rkt rolespec root rpo rto rust rwd résultat safe-harbor sarima scalabilité scanner schema scp sdk search select serverless-architecture service service-account service-worker setuptools sftp sha1 shard shard-duration shard-group sharding shell shipyard sidecar singer souveraineté-numérique spectre spinnaker spécifications sqlite sri ssh-agent ssl stabilité stash statistique storage sudo superset suse sympa sysdig syslog-ng sérénité task template terracost terrascan test-unitaire tidb tiers time timecale timer timestream tinygo training transformation travail trésorerie tsfr tsl ubuntu unikernel unit ux velero vendredi victoria-metrics vie-privée virtualbox virtualisation vm vnc volume voxxeddays vpc wasm web wireguard workflow yaml yield yq yubikey