αžšαž”αŸ€αž”αž”αž„αŸ’αž€αžΎαž DAG trigger αž“αŸ…αž€αŸ’αž“αž»αž„ Airflow αžŠαŸ„αž™αž”αŸ’αžšαžΎ API αžŸαžΆαž€αž›αŸ’αž”αž„

αž€αŸ’αž“αž»αž„αž€αžΆαžšαžšαŸ€αž”αž…αŸ†αž€αž˜αŸ’αž˜αžœαž·αž’αžΈαž’αž”αŸ‹αžšαŸ†αžšαž”αžŸαŸ‹αž™αžΎαž„ αž™αžΎαž„αž‡αž½αž”αž”αŸ’αžšαž‘αŸ‡αž€αžΆαžšαž›αŸ†αž”αžΆαž€αž‡αžΆαž”αŸ’αžšαž…αžΆαŸ†αž‘αžΆαž€αŸ‹αž‘αž„αž“αžΉαž„αž€αžΆαžšαž’αŸ’αžœαžΎαž€αžΆαžšαž‡αžΆαž˜αž½αž™αž§αž”αž€αžšαžŽαŸαž˜αž½αž™αž…αŸ†αž“αž½αž“αŸ” αž αžΎαž™αž“αŸ…αž–αŸαž›αž“αŸαŸ‡αž“αŸ…αž–αŸαž›αžŠαŸ‚αž›αž™αžΎαž„αž‡αž½αž”αž”αŸ’αžšαž‘αŸ‡αž–αž½αž€αž‚αŸ αžœαžΆαž˜αž·αž“αžαŸ‚αž„αžαŸ‚αž˜αžΆαž“αž―αž€αžŸαžΆαžš αž“αž·αž„αž’αžαŸ’αžαž”αž‘αž‚αŸ’αžšαž”αŸ‹αž‚αŸ’αžšαžΆαž“αŸ‹αžŠαŸ‚αž›αž’αžΆαž…αž‡αž½αž™αžŠαŸ„αŸ‡αžŸαŸ’αžšαžΆαž™αž”αž‰αŸ’αž αžΆαž“αŸαŸ‡αž”αžΆαž“αž‘αŸαŸ”

αžŠαžΌαž…αŸ’αž“αŸαŸ‡αžœαžΆαž‡αžΆαž§αž‘αžΆαž αžšαžŽαŸαž€αŸ’αž“αž»αž„αž†αŸ’αž“αžΆαŸ† 2015 αž αžΎαž™αž™αžΎαž„αž”αžΆαž“αž”αŸ’αžšαžΎαž…αž„αŸ’αž€αŸ„αž˜ Hadoop αž‡αžΆαž˜αž½αž™ Spark αžŸαž˜αŸ’αžšαžΆαž”αŸ‹αž’αŸ’αž“αž€αž”αŸ’αžšαžΎαž”αŸ’αžšαžΆαžŸαŸ‹ 35 αž“αžΆαž€αŸ‹αž€αŸ’αž“αž»αž„αž–αŸαž›αžŠαŸ†αžŽαžΆαž›αž‚αŸ’αž“αžΆαž“αŸ…αž›αžΎαž€αž˜αŸ’αž˜αžœαž·αž’αžΈ Big Data Specialist αŸ” αžœαžΆαž˜αž·αž“αž…αŸ’αž”αžΆαžŸαŸ‹αž’αŸ†αž–αžΈαžšαž”αŸ€αž”αžšαŸ€αž”αž…αŸ†αžœαžΆαžŸαž˜αŸ’αžšαžΆαž”αŸ‹αž€αžšαžŽαžΈαž’αŸ’αž“αž€αž”αŸ’αžšαžΎαž”αŸ’αžšαžΆαžŸαŸ‹αž”αŸ‚αž”αž“αŸαŸ‡αžŠαŸ„αž™αž”αŸ’αžšαžΎ YARN αž‘αŸαŸ” αž‡αžΆαž›αž‘αŸ’αž’αž•αž› αžŠαŸ„αž™αž”αžΆαž“αžŸαŸ’αžœαŸ‚αž„αž™αž›αŸ‹ αž“αž·αž„αžŠαžΎαžšαž›αžΎαž•αŸ’αž›αžΌαžœαžŠαŸ„αž™αžαŸ’αž›αž½αž“αž―αž„ αž–αž½αž€αž‚αŸαž”αžΆαž“αž’αŸ’αžœαžΎ αž”αŸ’αžšαž€αžΆαžŸαž“αŸ…αž›αžΎ Habre αž“αž·αž„αž”αžΆαž“αž’αž“αž»αžœαžαŸ’αžαž•αž„αžŠαŸ‚αžšαŸ” αž€αž·αž…αŸ’αž…αž”αŸ’αžšαž‡αž»αŸ† Spark αž‘αžΈαž€αŸ’αžšαž»αž„αž˜αŸ‰αžΌαžŸαŸ’αž‚αžΌ.

αžŸαž˜αŸαž™αž”αž»αžšαŸαž”αŸ’αžšαžœαžαŸ’αžαž·αžŸαžΆαžŸαŸ’αžαŸ’αžš

αž›αžΎαž€αž“αŸαŸ‡αž™αžΎαž„αž“αžΉαž„αž“αž·αž™αžΆαž™αž’αŸ†αž–αžΈαž€αž˜αŸ’αž˜αžœαž·αž’αžΈαž•αŸ’αžŸαŸαž„ - αžœαž·αžŸαŸ’αžœαž€αžšαž‘αž·αž“αŸ’αž“αž“αŸαž™. αž“αŸ…αž›αžΎαžœαžΆ αž’αŸ’αž“αž€αž…αžΌαž›αžšαž½αž˜αžšαž”αžŸαŸ‹αž™αžΎαž„αžŸαžΆαž„αžŸαž„αŸ‹αžŸαŸ’αžαžΆαž”αžαŸ’αž™αž€αž˜αŸ’αž˜αž–αžΈαžšαž”αŸ’αžšαž—αŸαž‘αž‚αžΊ lambda αž“αž·αž„ kappa αŸ” αž αžΎαž™αž“αŸ…αž€αŸ’αž“αž»αž„αžŸαŸ’αžαžΆαž”αžαŸ’αž™αž€αž˜αŸ’αž˜ lamdba Airflow αžαŸ’αžšαžΌαžœαž”αžΆαž“αž”αŸ’αžšαžΎαž‡αžΆαž•αŸ’αž“αŸ‚αž€αž“αŸƒαžŠαŸ†αžŽαžΎαžšαž€αžΆαžšαž”αžŽαŸ’αžαž»αŸ†αžŠαžΎαž˜αŸ’αž”αžΈαž•αŸ’αž‘αŸαžšαž€αŸ†αžŽαžαŸ‹αž αŸαžαž»αž–αžΈ HDFS αž‘αŸ… ClickHouse αŸ”

αž‡αžΆαž‘αžΌαž‘αŸ…αž’αŸ’αžœαžΈαŸ—αž‚αžΊαž›αŸ’αž’αŸ” αž’αž“αž»αž‰αŸ’αž‰αžΆαžαž±αŸ’αž™αž–αž½αž€αž‚αŸαžŸαžΆαž„αžŸαž„αŸ‹αž”αŸ†αž–αž„αŸ‹αžšαž”αžŸαŸ‹αž–αž½αž€αž‚αŸαŸ” αž‘αŸ„αŸ‡αž™αŸ‰αžΆαž„αžŽαžΆαž€αŸαžŠαŸ„αž™ αž˜αžΆαž“ "αž”αŸ‰αž»αž“αŸ’αžαŸ‚"αŸ– αž€αž˜αŸ’αž˜αžœαž·αž’αžΈαžšαž”αžŸαŸ‹αž™αžΎαž„αž‘αžΆαŸ†αž„αž’αžŸαŸ‹αž‚αžΊαž˜αžΆαž“αž—αžΆαž–αž‡αžΏαž“αž›αžΏαž“αžαžΆαž„αž”αž…αŸ’αž…αŸαž€αžœαž·αž‘αŸ’αž™αžΆαž‘αžΆαž€αŸ‹αž‘αž„αž“αžΉαž„αžŠαŸ†αžŽαžΎαžšαž€αžΆαžšαžŸαž·αž€αŸ’αžŸαžΆαžŠαŸ„αž™αžαŸ’αž›αž½αž“αž―αž„αŸ” αžŠαžΎαž˜αŸ’αž”αžΈαž–αž·αž“αž·αžαŸ’αž™αž˜αžΎαž›αž˜αž“αŸ’αž‘αžΈαžšαž–αž·αžŸαŸ„αž’αž“αŸ αž™αžΎαž„αž”αŸ’αžšαžΎαž§αž”αž€αžšαžŽαŸαž–αž·αž“αž·αžαŸ’αž™αžŠαŸ„αž™αžŸαŸ’αžœαŸαž™αž”αŸ’αžšαžœαžαŸ’αžαž·αŸ– αž’αŸ’αž“αž€αž…αžΌαž›αžšαž½αž˜αžαŸ’αžšαžΌαžœαž…αžΌαž›αž‘αŸ…αž€αžΆαž“αŸ‹αž‚αžŽαž“αžΈαž•αŸ’αž‘αžΆαž›αŸ‹αžαŸ’αž›αž½αž“αžšαž”αžŸαŸ‹αž‚αžΆαžαŸ‹ αž…αž»αž…αž”αŸŠαžΌαžαž»αž„ "αž–αž·αž“αž·αžαŸ’αž™" αž αžΎαž™αž˜αž½αž™αžŸαž“αŸ’αž‘αž»αŸ‡αž€αŸ’αžšαŸ„αž™αž˜αž€αž‚αžΆαžαŸ‹αžƒαžΎαž‰αž”αŸ’αžšαž—αŸαž‘αž“αŸƒαž˜αžαž·αž€αŸ‚αž›αž˜αŸ’αž’αž˜αž½αž™αž…αŸ†αž“αž½αž“αž›αžΎαž’αŸ’αžœαžΈαžŠαŸ‚αž›αž‚αžΆαžαŸ‹αž”αžΆαž“αž’αŸ’αžœαžΎαŸ” αž αžΎαž™αžœαžΆαž‚αžΊαž“αŸ…αž…αŸ†αžŽαž»αž…αž“αŸαŸ‡αžŠαŸ‚αž›αž™αžΎαž„αž…αžΆαž”αŸ‹αž•αŸ’αžαžΎαž˜αžαž·αžαž‘αŸ…αžšαž€αž”αž‰αŸ’αž αžΆαžšαž”αžŸαŸ‹αž™αžΎαž„αŸ”

αž€αžΆαžšαž–αž·αž“αž·αžαŸ’αž™αž˜αžΎαž›αž˜αž“αŸ’αž‘αžΈαžšαž–αž·αžŸαŸ„αž’αž“αŸαž“αŸαŸ‡αžαŸ’αžšαžΌαžœαž”αžΆαž“αžšαŸ€αž”αž…αŸ†αžŠαžΌαž…αžαžΆαž„αž€αŸ’αžšαŸ„αž˜αŸ– αž™αžΎαž„αž•αŸ’αž‰αžΎαž€αž‰αŸ’αž…αž”αŸ‹αž‘αž·αž“αŸ’αž“αž“αŸαž™αžαŸ’αžšαž½αžαž–αž·αž“αž·αžαŸ’αž™αž‘αŸ… Kafka αžšαž”αžŸαŸ‹αž’αŸ’αž“αž€αž…αžΌαž›αžšαž½αž˜ αž”αž“αŸ’αž‘αžΆαž”αŸ‹αž˜αž€ Gobblin αž•αŸ’αž‘αŸαžšαž€αž‰αŸ’αž…αž”αŸ‹αž‘αž·αž“αŸ’αž“αž“αŸαž™αž“αŸαŸ‡αž‘αŸ… HDFS αž”αž“αŸ’αž‘αžΆαž”αŸ‹αž˜αž€ Airflow αž™αž€αž€αž‰αŸ’αž…αž”αŸ‹αž‘αž·αž“αŸ’αž“αž“αŸαž™αž“αŸαŸ‡ αž αžΎαž™αžŠαžΆαž€αŸ‹αžœαžΆαž“αŸ…αž€αŸ’αž“αž»αž„ ClickHouse αŸ” αž›αŸ’αž”αž·αž…αž‚αžΊαžαžΆ Airflow αž˜αž·αž“αž…αžΆαŸ†αž”αžΆαž…αŸ‹αž’αŸ’αžœαžΎαž”αŸ‚αž”αž“αŸαŸ‡αž€αŸ’αž“αž»αž„αž–αŸαž›αžœαŸαž›αžΆαž‡αžΆαž€αŸ‹αžŸαŸ’αžαŸ‚αž„αž“αŸ„αŸ‡αž‘αŸ αžœαžΆαž’αŸ’αžœαžΎαžœαžΆαžαžΆαž˜αž€αžΆαž›αžœαž·αž—αžΆαž‚αŸ– αžšαŸ€αž„αžšαžΆαž›αŸ‹ 15 αž“αžΆαž‘αžΈαž˜αŸ’αžαž„ αžœαžΆαžαŸ’αžšαžΌαžœαž€αžΆαžšαž―αž€αžŸαžΆαžšαž‡αžΆαž…αŸ’αžšαžΎαž“ αž αžΎαž™αž”αž„αŸ’αž αŸ„αŸ‡αžœαžΆαŸ”

αžœαžΆαž”αŸ’αžšαŸ‚αžαžΆαž™αžΎαž„αž…αžΆαŸ†αž”αžΆαž…αŸ‹αžαŸ’αžšαžΌαžœαž…αžΆαž”αŸ‹αž•αŸ’αžαžΎαž˜ DAG αžšαž”αžŸαŸ‹αž–αž½αž€αž‚αŸαžŠαŸ„αž™αžαŸ’αž›αž½αž“αž―αž„αžαžΆαž˜αžŸαŸ†αžŽαžΎαžšαž”αžŸαŸ‹αž™αžΎαž„αžαžŽαŸˆαž–αŸαž›αžŠαŸ‚αž›αž’αŸ’αž“αž€αžαŸ’αžšαž½αžαž–αž·αž“αž·αžαŸ’αž™αž€αŸ†αž–αž»αž„αžŠαŸ†αžŽαžΎαžšαž€αžΆαžšαž“αŸ…αž‘αžΈαž“αŸαŸ‡αž“αž·αž„αž₯αž‘αžΌαžœαž“αŸαŸ‡αŸ” Googling αž™αžΎαž„αž”αžΆαž“αžšαž€αžƒαžΎαž‰αžαžΆαžŸαž˜αŸ’αžšαžΆαž”αŸ‹αž€αŸ†αžŽαŸ‚αž€αŸ’αžšαŸ„αž™αž“αŸƒ Airflow αž‚αžΊαž‡αžΆαž’αŸ’αžœαžΈαžŠαŸ‚αž›αž‚αŸαž αŸ…αžαžΆ API αž–αž·αžŸαŸ„αž’αž“αŸαŸ” αž–αžΆαž€αŸ’αž™ experimentalαž–αž·αžαžŽαžΆαžŸαŸ‹ αžœαžΆαžŸαŸ’αžαžΆαž”αŸ‹αž‘αŸ…αž‚αž½αžšαž±αŸ’αž™αžαŸ’αž›αžΆαž… αž”αŸ‰αž»αž“αŸ’αžαŸ‚αž’αŸ’αžœαžΈαžŠαŸ‚αž›αžαŸ’αžšαžΌαžœαž’αŸ’αžœαžΎ ... αžœαžΆαžŸαŸ’αžšαžΆαž”αŸ‹αžαŸ‚αžšαž›αžαŸ‹αž‘αŸ…αžœαž·αž‰αŸ”

αž”αž“αŸ’αž‘αžΆαž”αŸ‹ αž™αžΎαž„αž“αžΉαž„αžšαŸ€αž”αžšαžΆαž”αŸ‹αž’αŸ†αž–αžΈαž•αŸ’αž›αžΌαžœαž‘αžΆαŸ†αž„αž˜αžΌαž›αŸ– αž–αžΈαž€αžΆαžšαžŠαŸ†αž‘αžΎαž„ Airflow αžŠαž›αŸ‹αž€αžΆαžšαž”αž„αŸ’αž€αžΎαžαžŸαŸ†αžŽαžΎ POST αžŠαŸ‚αž›αž”αž„αŸ’αž€αž±αŸ’αž™αž˜αžΆαž“ DAG αžŠαŸ„αž™αž”αŸ’αžšαžΎ API αž–αž·αžŸαŸ„αž’αž“αŸαŸ” αž™αžΎαž„αž“αžΉαž„αž’αŸ’αžœαžΎαž€αžΆαžšαž‡αžΆαž˜αž½αž™ Ubuntu 16.04 αŸ”

1. αž€αžΆαžšαžŠαŸ†αž‘αžΎαž„αž›αŸ†αž αžΌαžšαžαŸ’αž™αž›αŸ‹

αžŸαžΌαž˜αž–αž·αž“αž·αžαŸ’αž™αž˜αžΎαž›αžαžΆαž™αžΎαž„αž˜αžΆαž“ Python 3 αž“αž·αž„ virtualenv αŸ”

$ python3 --version
Python 3.6.6
$ virtualenv --version
15.2.0

αž”αŸ’αžšαžŸαž·αž“αž”αžΎαž˜αž½αž™αž€αŸ’αž“αž»αž„αž…αŸ†αžŽαŸ„αž˜αž‘αžΆαŸ†αž„αž“αŸαŸ‡αž”αžΆαžαŸ‹, αž”αž“αŸ’αž‘αžΆαž”αŸ‹αž˜αž€αžŠαŸ†αž‘αžΎαž„αžœαžΆαŸ”

αž₯αž‘αžΌαžœαž“αŸαŸ‡ αž…αžΌαžšαž™αžΎαž„αž”αž„αŸ’αž€αžΎαžαžαžαžŠαŸ‚αž›αž™αžΎαž„αž“αžΉαž„αž”αž“αŸ’αžαž’αŸ’αžœαžΎαž€αžΆαžšαž‡αžΆαž˜αž½αž™ Airflow αŸ”

$ mkdir <your name of directory>
$ cd /path/to/your/new/directory
$ virtualenv -p which python3 venv
$ source venv/bin/activate
(venv) $

αžŠαŸ†αž‘αžΎαž„αž›αŸ†αž αžΌαžšαžαŸ’αž™αž›αŸ‹αŸ–

(venv) $ pip install airflow

αž€αŸ†αžŽαŸ‚αžŠαŸ‚αž›αž™αžΎαž„αž”αžΆαž“αž’αŸ’αžœαžΎαž€αžΆαžšαž›αžΎαŸ– 1.10.

αž₯αž‘αžΌαžœαž™αžΎαž„αžαŸ’αžšαžΌαžœαž”αž„αŸ’αž€αžΎαžαžαžαž―αž€αžŸαžΆαžš airflow_homeαžŠαŸ‚αž›αž‡αžΆαž€αž“αŸ’αž›αŸ‚αž„αžŠαŸ‚αž›αž―αž€αžŸαžΆαžš DAG αž“αž·αž„αž€αž˜αŸ’αž˜αžœαž·αž’αžΈαž‡αŸ†αž“αž½αž™ Airflow αž“αžΉαž„αž˜αžΆαž“αž‘αžΈαžαžΆαŸ†αž„αž“αŸ…αŸ” αž”αž“αŸ’αž‘αžΆαž”αŸ‹αž–αžΈαž”αž„αŸ’αž€αžΎαžαžαžαž€αŸ†αžŽαžαŸ‹αž’αžαŸαžšαž”αžšαž·αžŸαŸ’αžαžΆαž“ AIRFLOW_HOME.

(venv) $ cd /path/to/my/airflow/workspace
(venv) $ mkdir airflow_home
(venv) $ export AIRFLOW_HOME=<path to airflow_home>

αž‡αŸ†αž αžΆαž“αž”αž“αŸ’αž‘αžΆαž”αŸ‹αž‚αžΊαžαŸ’αžšαžΌαžœαžŠαŸ†αžŽαžΎαžšαž€αžΆαžšαž–αžΆαž€αŸ’αž™αž”αž‰αŸ’αž‡αžΆαžŠαŸ‚αž›αž“αžΉαž„αž”αž„αŸ’αž€αžΎαž αž“αž·αž„αž…αžΆαž”αŸ‹αž•αŸ’αžαžΎαž˜αž˜αžΌαž›αžŠαŸ’αž‹αžΆαž“αž‘αž·αž“αŸ’αž“αž“αŸαž™αž›αŸ†αž αžΌαžšαž‘αž·αž“αŸ’αž“αž“αŸαž™αž€αŸ’αž“αž»αž„ SQLiteαŸ–

(venv) $ airflow initdb

αž˜αžΌαž›αžŠαŸ’αž‹αžΆαž“αž‘αž·αž“αŸ’αž“αž“αŸαž™αž“αžΉαž„αžαŸ’αžšαžΌαžœαž”αžΆαž“αž”αž„αŸ’αž€αžΎαžαž“αŸ…αž€αŸ’αž“αž»αž„ airflow.db αž›αŸ†αž“αžΆαŸ†αžŠαžΎαž˜

αž–αž·αž“αž·αžαŸ’αž™αž˜αžΎαž›αžαžΆαžαžΎ Airflow αžαŸ’αžšαžΌαžœαž”αžΆαž“αžŠαŸ†αž‘αžΎαž„αž¬αž’αžαŸ‹αŸ–

$ airflow version
[2018-11-26 19:38:19,607] {__init__.py:57} INFO - Using executor SequentialExecutor
[2018-11-26 19:38:19,745] {driver.py:123} INFO - Generating grammar tables from /usr/lib/python3.6/lib2to3/Grammar.txt
[2018-11-26 19:38:19,771] {driver.py:123} INFO - Generating grammar tables from /usr/lib/python3.6/lib2to3/PatternGrammar.txt
  ____________       _____________
 ____    |__( )_________  __/__  /________      __
____  /| |_  /__  ___/_  /_ __  /_  __ _ | /| / /
___  ___ |  / _  /   _  __/ _  / / /_/ /_ |/ |/ /
 _/_/  |_/_/  /_/    /_/    /_/  ____/____/|__/
   v1.10.0

αž”αŸ’αžšαžŸαž·αž“αž”αžΎαž–αžΆαž€αŸ’αž™αž”αž‰αŸ’αž‡αžΆαžŠαŸ†αžŽαžΎαžšαž€αžΆαžšαž“αŸ„αŸ‡ Airflow αž”αžΆαž“αž”αž„αŸ’αž€αžΎαžαž―αž€αžŸαžΆαžšαž€αŸ†αžŽαžαŸ‹αžšαž…αž“αžΆαžŸαž˜αŸ’αž–αŸαž“αŸ’αž’αž•αŸ’αž‘αžΆαž›αŸ‹αžαŸ’αž›αž½αž“αžšαž”αžŸαŸ‹αžœαžΆαŸ” airflow.cfg Π² AIRFLOW_HOME:

$ tree
.
β”œβ”€β”€ airflow.cfg
└── unittests.cfg

Airflow αž˜αžΆαž“αž…αŸ†αžŽαž»αž…αž”αŸ’αžšαž‘αžΆαž€αŸ‹αž”αžŽαŸ’αžŠαžΆαž‰αŸ” αžœαžΆαž’αžΆαž…αžαŸ’αžšαžΌαžœαž”αžΆαž“αž”αžΎαž€αžŠαŸ†αžŽαžΎαžšαž€αžΆαžšαžŠαŸ„αž™αžŠαŸ†αžŽαžΎαžšαž€αžΆαžšαž–αžΆαž€αŸ’αž™αž”αž‰αŸ’αž‡αžΆ:

(venv) $ airflow webserver --port 8081

αž₯αž‘αžΌαžœαž“αŸαŸ‡αž’αŸ’αž“αž€αž’αžΆαž…αž…αžΌαž›αž”αŸ’αžšαžΎαž…αŸ†αžŽαž»αž…αž”αŸ’αžšαž‘αžΆαž€αŸ‹αž”αžŽαŸ’αžŠαžΆαž‰αž“αŸ…αž€αŸ’αž“αž»αž„αž€αž˜αŸ’αž˜αžœαž·αž’αžΈαžšαž»αž€αžšαž€αžαžΆαž˜αž…αŸ’αžšαž€ 8081 αž“αŸ…αž›αžΎαž˜αŸ‰αžΆαžŸαŸŠαžΈαž“αžŠαŸ‚αž› Airflow αž€αŸ†αž–αž»αž„αžŠαŸ†αžŽαžΎαžšαž€αžΆαžšαžŠαžΌαž…αž“αŸαŸ‡αŸ– <hostname:8081>.

2. αž’αŸ’αžœαžΎαž€αžΆαžšαž‡αžΆαž˜αž½αž™ API αž–αž·αžŸαŸ„αž’αž“αŸ

αž“αŸ…αž›αžΎ Airflow αž“αŸαŸ‡αžαŸ’αžšαžΌαžœαž”αžΆαž“αž€αŸ†αžŽαžαŸ‹αžšαž…αž“αžΆαžŸαž˜αŸ’αž–αŸαž“αŸ’αž’ αž“αž·αž„αžαŸ’αžšαŸ€αž˜αžšαž½αž…αžšαžΆαž›αŸ‹αŸ” αž‘αŸ„αŸ‡αž™αŸ‰αžΆαž„αžŽαžΆαž€αŸαžŠαŸ„αž™ αž™αžΎαž„αž€αŸαžαŸ’αžšαžΌαžœαžŠαŸ†αžŽαžΎαžšαž€αžΆαžš API αžŸαžΆαž€αž›αŸ’αž”αž„αž•αž„αžŠαŸ‚αžšαŸ” αž§αž”αž€αžšαžŽαŸαž–αž·αž“αž·αžαŸ’αž™αžšαž”αžŸαŸ‹αž™αžΎαž„αžαŸ’αžšαžΌαžœαž”αžΆαž“αžŸαžšαžŸαŸαžšαž“αŸ…αž€αŸ’αž“αž»αž„ Python αžŠαžΌαž…αŸ’αž“αŸαŸ‡αžŸαŸ†αžŽαžΎαž‘αžΆαŸ†αž„αž’αžŸαŸ‹αž“αžΉαž„αž˜αžΆαž“αž“αŸ…αž›αžΎαžœαžΆαžŠαŸ„αž™αž”αŸ’αžšαžΎαž”αžŽαŸ’αžŽαžΆαž›αŸαž™ requests.

αžαžΆαž˜αž–αž·αž API αž€αŸ†αž–αž»αž„αžŠαŸ†αžŽαžΎαžšαž€αžΆαžšαžŸαž˜αŸ’αžšαžΆαž”αŸ‹αžŸαŸ†αžŽαžΎαžŸαžΆαž˜αž‰αŸ’αž‰αžšαž½αž…αž αžΎαž™αŸ” αž§αž‘αžΆαž αžšαžŽαŸ αžŸαŸ†αžŽαžΎαž”αŸ‚αž”αž“αŸαŸ‡αž’αž“αž»αž‰αŸ’αž‰αžΆαžαž±αŸ’αž™αž’αŸ’αž“αž€αžŸαžΆαž€αž›αŸ’αž”αž„αž€αžΆαžšαž„αžΆαžšαžšαž”αžŸαŸ‹αžœαžΆαŸ–

>>> import requests
>>> host = <your hostname>
>>> airflow_port = 8081 #Π² нашСм случаС Ρ‚Π°ΠΊΠΎΠΉ, Π° ΠΏΠΎ Π΄Π΅Ρ„ΠΎΠ»Ρ‚Ρƒ 8080
>>> requests.get('http://{}:{}/{}'.format(host, airflow_port, 'api/experimental/test').text
'OK'

αž”αŸ’αžšαžŸαž·αž“αž”αžΎαž’αŸ’αž“αž€αž”αžΆαž“αž‘αž‘αž½αž›αžŸαžΆαžšαž”αŸ‚αž”αž“αŸαŸ‡αž‡αžΆαž€αžΆαžšαž†αŸ’αž›αžΎαž™αžαž” αžœαžΆαž˜αžΆαž“αž“αŸαž™αžαžΆαž’αŸ’αžœαžΈαŸ—αžŠαŸ†αžŽαžΎαžšαž€αžΆαžšαž αžΎαž™αŸ”

αž‘αŸ„αŸ‡αž™αŸ‰αžΆαž„αžŽαžΆαž€αŸαžŠαŸ„αž™ αž“αŸ…αž–αŸαž›αžŠαŸ‚αž›αž™αžΎαž„αž…αž„αŸ‹αž€αŸαŸ‡ DAG αž“αŸ„αŸ‡ αž™αžΎαž„αžŠαŸ†αžŽαžΎαžšαž€αžΆαžšαž‘αŸ…αž€αžΆαžšαž–αž·αžαžŠαŸ‚αž›αžαžΆαžŸαŸ†αžŽαžΎαž”αŸ’αžšαž—αŸαž‘αž“αŸαŸ‡αž˜αž·αž“αž’αžΆαž…αžαŸ’αžšαžΌαžœαž”αžΆαž“αž’αŸ’αžœαžΎαž‘αžΎαž„αžŠαŸ„αž™αž‚αŸ’αž˜αžΆαž“αž€αžΆαžšαž•αŸ’αž‘αŸ€αž„αž•αŸ’αž‘αžΆαžαŸ‹αž“αŸ„αŸ‡αž‘αŸαŸ”

αžŠαžΎαž˜αŸ’αž”αžΈαž’αŸ’αžœαžΎαžŠαžΌαž…αž“αŸαŸ‡αž’αŸ’αž“αž€αž“αžΉαž„αžαŸ’αžšαžΌαžœαž’αŸ’αžœαžΎαžŸαž€αž˜αŸ’αž˜αž—αžΆαž–αž˜αž½αž™αž…αŸ†αž“αž½αž“αŸ”

αžŠαŸ†αž”αžΌαž„αž’αŸ’αž“αž€αžαŸ’αžšαžΌαžœαž”αž“αŸ’αžαŸ‚αž˜αžœαžΆαž‘αŸ… configαŸ–

[api]
auth_backend = airflow.contrib.auth.backends.password_auth

αž”αž“αŸ’αž‘αžΆαž”αŸ‹αž˜αž€ αž’αŸ’αž“αž€αžαŸ’αžšαžΌαžœαž”αž„αŸ’αž€αžΎαžαž’αŸ’αž“αž€αž”αŸ’αžšαžΎαž”αŸ’αžšαžΆαžŸαŸ‹αžšαž”αžŸαŸ‹αž’αŸ’αž“αž€αž‡αžΆαž˜αž½αž™αž“αžΉαž„αžŸαž·αž‘αŸ’αž’αž·αž‚αŸ’αžšαž”αŸ‹αž‚αŸ’αžšαž„αŸ–

>>> import airflow
>>> from airflow import models, settings
>>> from airflow.contrib.auth.backends.password_auth import PasswordUser
>>> user = PasswordUser(models.Admin())
>>> user.username = 'new_user_name'
>>> user.password = 'set_the_password'
>>> session = settings.Session()
>>> session.add(user)
>>> session.commit()
>>> session.close()
>>> exit()

αž”αž“αŸ’αž‘αžΆαž”αŸ‹αž˜αž€ αž’αŸ’αž“αž€αžαŸ’αžšαžΌαžœαž”αž„αŸ’αž€αžΎαžαž’αŸ’αž“αž€αž”αŸ’αžšαžΎαž”αŸ’αžšαžΆαžŸαŸ‹αžŠαŸ‚αž›αž˜αžΆαž“αžŸαž·αž‘αŸ’αž’αž·αž’αž˜αŸ’αž˜αžαžΆ αžŠαŸ‚αž›αž“αžΉαž„αžαŸ’αžšαžΌαžœαž”αžΆαž“αž’αž“αž»αž‰αŸ’αž‰αžΆαžαž±αŸ’αž™αž”αž„αŸ’αž€αžΎαž DAG trigger αŸ”

>>> import airflow
>>> from airflow import models, settings
>>> from airflow.contrib.auth.backends.password_auth import PasswordUser
>>> user = PasswordUser(models.User())
>>> user.username = 'newprolab'
>>> user.password = 'Newprolab2019!'
>>> session = settings.Session()
>>> session.add(user)
>>> session.commit()
>>> session.close()
>>> exit()

αž₯αž‘αžΌαžœαž“αŸαŸ‡αž’αŸ’αžœαžΈαž‚αŸ’αžšαž”αŸ‹αž™αŸ‰αžΆαž„αž‚αžΊαžšαž½αž…αžšαžΆαž›αŸ‹αŸ”

3. αž…αžΆαž”αŸ‹αž•αŸ’αžαžΎαž˜αžŸαŸ†αžŽαžΎ POST

αžŸαŸ†αžŽαžΎαžšαž”αžŸαŸ‹ POST αžαŸ’αž›αž½αž“αžœαžΆαž“αžΉαž„αž˜αžΎαž›αž‘αŸ…αžŠαžΌαž…αž“αŸαŸ‡αŸ–

>>> dag_id = newprolab
>>> url = 'http://{}:{}/{}/{}/{}'.format(host, airflow_port, 'api/experimental/dags', dag_id, 'dag_runs')
>>> data = {"conf":"{"key":"value"}"}
>>> headers = {'Content-type': 'application/json'}
>>> auth = ('newprolab', 'Newprolab2019!')
>>> uri = requests.post(url, data=json.dumps(data), headers=headers, auth=auth)
>>> uri.text
'{n  "message": "Created <DagRun newprolab @ 2019-03-27 10:24:25+00:00: manual__2019-03-27T10:24:25+00:00, externally triggered: True>"n}n'

αžŸαŸ†αžŽαžΎαžαŸ’αžšαžΌαžœαž”αžΆαž“αžŠαŸ†αžŽαžΎαžšαž€αžΆαžšαžŠαŸ„αž™αž‡αŸ„αž‚αž‡αŸαž™αŸ”

αžŠαžΌαž…αŸ’αž“αŸ„αŸ‡αž αžΎαž™ αž™αžΎαž„αž•αŸ’αžαž›αŸ‹αž–αŸαž›αžœαŸαž›αžΆαžαŸ’αž›αŸ‡αžŠαž›αŸ‹ DAG αžŠαžΎαž˜αŸ’αž”αžΈαžŠαŸ†αžŽαžΎαžšαž€αžΆαžš αž“αž·αž„αž’αŸ’αžœαžΎαž€αžΆαžšαžŸαŸ’αž“αžΎαžŸαž»αŸ†αž‘αŸ…αž€αžΆαž“αŸ‹αžαžΆαžšαžΆαž„ ClickHouse αžŠαŸ„αž™αž–αŸ’αž™αžΆαž™αžΆαž˜αž…αžΆαž”αŸ‹αž™αž€αž€αž‰αŸ’αž…αž”αŸ‹αž‘αž·αž“αŸ’αž“αž“αŸαž™αž‚αŸ’αžšαž”αŸ‹αž‚αŸ’αžšαž„αŸ”

αž€αžΆαžšαž•αŸ’αž‘αŸ€αž„αž•αŸ’αž‘αžΆαžαŸ‹αž”αžΆαž“αž”αž‰αŸ’αž…αž”αŸ‹αŸ”

αž”αŸ’αžšαž—αž–: www.habr.com

αž”αž“αŸ’αžαŸ‚αž˜αž˜αžαž·αž™αŸ„αž”αž›αŸ‹