web-dev-qa-db-fra.com

DAG dynamique et ID de tâche Airflow

Je vois principalement Airflow utilisé pour les travaux liés aux données ETL/Bid. J'essaie de l'utiliser pour les flux de travail d'entreprise dans lesquels une action utilisateur déclenche à l'avenir un ensemble de tâches dépendantes. Certaines de ces tâches peuvent devoir être effacées (supprimées) en fonction de certaines autres actions de l'utilisateur. Je pensais que la meilleure façon de gérer cela serait via les identifiants de tâches dynamiques. J'ai lu que Airflow prend en charge les identifiants dynamiques. J'ai donc créé un simple script python qui prend l'ID DAG et l'ID de tâche comme paramètres de ligne de commande. Cependant, je rencontre des problèmes pour le faire fonctionner. Il donne une erreur dag_id introuvable. Quelqu'un at-il quelqu'un Voici le code du script (appelez-le tmp.py) que j'exécute en ligne de commande comme python (python tmp.py 820 2016-08-24T22: 50: 00):

from __future__ import print_function
import os
import sys
import shutil
from datetime import date, datetime, timedelta
from airflow import DAG
from airflow.operators.bash_operator import BashOperator
execution = '2016-08-24T22:20:00'
if len(sys.argv) > 2  :
   dagid =  sys.argv[1]
   taskid = 'Activate' + sys.argv[1]
   execution = sys.argv[2]
else:
   dagid = 'DAGObjectId'
   taskid = 'Activate'
default_args = {'owner' : 'airflow', 'depends_on_past': False, 'start_date':date.today(), 'email': ['[email protected]'], 'email_on_failure': False, 'email_on_retry': False, 'retries': 1}
dag = DAG(dag_id = dagid,
       default_args=default_args,
       schedule_interval='@once',
      )
 globals()[dagid] = dag
task1 = BashOperator(
    task_id = taskid,
    bash_command='ls -l',
    dag=dag)

fakeTask = BashOperator(
    task_id = 'fakeTask',
    bash_command='sleep 5',
    retries = 3,
    dag=dag)
task1.set_upstream(fakeTask)

airflowcmd = "airflow run " + dagid + " " + taskid + "  " + execution
print("airflowcmd = " + airflowcmd)
os.system(airflowcmd)
19
Dean Sha

Après de nombreux essais et erreurs, j'ai pu le comprendre. J'espère que cela aidera quelqu'un. Voici comment cela fonctionne: vous devez disposer d'un itérateur ou d'une source externe (fichier/table de base de données) pour générer dynamiquement des dags/tâches via un modèle. Vous pouvez garder les noms de dag et de tâche statiques, il suffit de leur attribuer des identifiants dynamiquement afin de différencier un dag de l'autre. Vous placez ce script python dans le dossier dags. Lorsque vous démarrez le planificateur de flux d'air, il exécute ce script à chaque pulsation et écrit les DAG dans la table dag de la base de données. Si un dag ( l'identifiant unique du dag) a déjà été écrit, il l'ignorera simplement. Le planificateur examine également le calendrier des DAG individuels pour déterminer lequel est prêt à être exécuté. Si un DAG est prêt à être exécuté, il l'exécute et met à jour son état. Voici un exemple de code:

from airflow.operators import PythonOperator
from airflow.operators import BashOperator
from airflow.models import DAG
from datetime import datetime, timedelta
import sys
import time

dagid   = 'DA' + str(int(time.time()))
taskid  = 'TA' + str(int(time.time()))

input_file = '/home/directory/airflow/textfile_for_dagids_and_schedule'

def my_sleeping_function(random_base):
    '''This is a function that will run within the DAG execution'''
    time.sleep(random_base)

def_args = {
    'owner': 'airflow',
    'depends_on_past': False,
    'start_date': datetime.now(), 'email_on_failure': False,                
    'retries': 1, 'retry_delay': timedelta(minutes=2)
}
with open(input_file,'r') as f:
    for line in f:
        args = line.strip().split(',')
    if len(args) < 6:
        continue
    dagid = 'DAA' + args[0]
    taskid = 'TAA' + args[0]
    yyyy    = int(args[1])
    mm      = int(args[2])
    dd      = int(args[3])
    hh      = int(args[4])
    mins    = int(args[5])
    ss      = int(args[6])
    dag = DAG(
        dag_id=dagid, default_args=def_args,
        schedule_interval='@once', start_date=datetime(yyyy,mm,dd,hh,mins,ss)
        )

    myBashTask = BashOperator(
        task_id=taskid,
        bash_command='python /home/directory/airflow/sendemail.py',
        dag=dag)

    task2id = taskid + '-X'

    task_sleep = PythonOperator(
        task_id=task2id,
        python_callable=my_sleeping_function,
        op_kwargs={'random_base': 10},
        dag=dag)

    task_sleep.set_upstream(myBashTask)

f.close()
19
Dean Sha

De Comment puis-je créer des DAG dynamiquement? :

Airflow recherche en vous [sic] DAGS_FOLDER les modules qui contiennent des objets DAG dans leur espace de noms global et ajoute les objets qu'il trouve dans le DagBag. Sachant cela, tout ce dont nous avons besoin est un moyen d'affecter dynamiquement une variable dans l'espace de noms global, ce qui se fait facilement dans python en utilisant la fonction globals () pour la bibliothèque standard qui se comporte comme un simple dictionnaire.

for i in range(10):
    dag_id = 'foo_{}'.format(i)
    globals()[dag_id] = DAG(dag_id)
    # or better, call a function that returns a DAG object!
15
Scott Ding