Базовый сценарий#

Приведенный здесь пример демонстрирует базовые операции с использованием API:

  1. Получение токена авторизации.

  2. Создание проекта на основе публичного репозитория Git.

  3. Синхронизация проекта.

  4. Получение идентификаторов свода правил и среды принятия решений.

  5. Получение идентификатора типа полномочий для потока событий.

  6. Создание полномочий для потока событий.

  7. Создание потока событий.

  8. Создание активации свода правил.

  9. Отправка тестового события {"ping":"pong"}.

  10. Проверка результата через журналы активации, поток событий и аудит правил.

Предварительные требования#

Перед выполнением сценария произведите следующие действия:

  1. Установите на узле, с которого будут выполняться запросы, утилиты curl и jq:

    sudo apt install --yes curl jq
    
  2. Проверьте доступность репозитория с примерами ansible/eda-sample-project.

  3. Получите токен авторизации.

Подготовка проекта#

Для подготовки проекта выполните следующие действия:

  1. Создайте проект Event-Driven Automation:

    curl -X POST \
       -H 'Content-Type: application/json' \
       -H 'Authorization: Bearer <your_token>' \
       -d '{
                "name": "<your_project_name>",
                "url": "https://github.com/ansible/eda-sample-project",
                "organization_id": <organization_id>
             }' \
          https://<address>/api/eda/v1/projects/ | jq
    

    Подставьте собственные значения параметров вместо употребленных в примере:

    • <address> – FQDN или IP-адрес шлюза, например 192.168.56.11.

    • <your_token> – токен, полученный при подготовке, например 3wijiG7********VtL2gseJESzjJsD.

    • <your_project_name> – название проекта, например Demo Project.

    • <organization_id> – идентификатор организации, которой будет принадлежать проект, например 1. Пример создания организации с помощью API см. в инструкции.

    Внимание

    При отсутствии удостоверяющего сертификата TLS на рабочей станции добавьте параметр -k в команду curl, например:

    curl -k -X POST ...
    
    Пример вывода
    {
      "name": "Demo Project",
      "description": "",
      "organization_id": 1,
      "eda_credential_id": null,
      "signature_validation_credential_id": null,
      "scm_branch": "",
      "scm_refspec": "",
      "verify_ssl": true,
      "proxy": "",
      "created_by": {
        "id": 1,
        "username": "admin",
        "first_name": "",
        "last_name": ""
      },
      "modified_by": {
        "id": 1,
        "username": "admin",
        "first_name": "",
        "last_name": ""
      },
      "id": 3,
      "url": "https://github.com/ansible/eda-sample-project",
      "scm_type": "git",
      "git_hash": "",
      "import_state": "pending",
      "import_error": null,
      "created_at": "2026-03-29T16:46:29.649986Z",
      "modified_at": "2026-03-29T16:46:29.650053Z"
    }
    
  2. Синхронизируйте проект:

    curl -X POST \
       -H 'Authorization: Bearer <your_token>' \
       https://<address>/api/eda/v1/projects/<project_id>/sync/ | jq
    

    Здесь <project_id> – идентификатор проекта, созданного на предыдущем шаге, например 3.

После успешной синхронизации платформа обнаружит своды правил, находящиеся в каталоге extensions/eda/rulebooks.

Получение идентификаторов#

Для выполнения сценария необходимо узнать идентификаторы свода правил, среды принятия решений и типа полномочий. Для этого выполните следующие действия:

  1. Получите список сводов правил:

    curl \
       -H 'Authorization: Bearer <your_token>' \
       https://<address>/api/eda/v1/rulebooks/ | jq
    
    Пример вывода
    {
      "count": 84,
      "next": "/api/eda/v1/rulebooks/?page=2",
      "previous": null,
      "page_size": 20,
      "page": 1,
      "results": [
        {
          "id": 1,
          "name": "multiple_rules_single_fact.yml",
          "description": "",
          "rulesets": "---\n- name: Mutliple rules fired for single fact\n  hosts: all\n  sources:\n    - ansible.eda.range:\n        limit: 5\n  rules:\n    - name: Say Hello\n      condition: event.i == 0\n      action:\n        set_fact:\n          fact:\n             j: 42 \n    - name: fact_rule1\n      condition: fact.j == 42 \n      action:\n        print_event:\n    - name: fact_rule2\n      condition: fact.j == 42 \n      action:\n        debug:\n",
          "project_id": 2,
          "organization_id": 1,
          "created_at": "2026-03-29T14:51:19.080239Z",
          "modified_at": "2026-03-29T14:51:19.080373Z"
        },
        {
          "id": 2,
          "name": "data_center_lock.yml",
          "description": "",
          "rulesets": "---\n- name: Test run job templates with lock\n  hosts: all\n  execution_strategy: parallel\n  sources:\n    - ansible.eda.generic:\n        payload:\n           - name: DataCenter1\n             error: 678\n             sleep: 20\n           - name: DataCenter2\n             error: 303\n             sleep: 15\n           - name: DataCenter3\n             error: 353\n             sleep: 10\n        loop_count: 3   \n        shutdown_after: 90\n        create_index: index\n  rules:\n    - name: \"Run job template\"\n      condition: event.error >= 303\n      action:\n        run_job_template:\n          name: \"{{ job_template_name }}\" \n          organization: \"{{ organization | default('Default') }}\"\n          job_args:\n            extra_vars:\n              hello: Fred\n              sleep_interval: \"{{ event.sleep }}\"\n          lock: \"{{ event.name }}\"\n",
          "project_id": 2,
          "organization_id": 1,
          "created_at": "2026-03-29T14:51:19.104787Z",
          "modified_at": "2026-03-29T14:51:19.104813Z"
        },
        {
          "id": 3,
          "name": "awx_storm_single_action.yml",
          "description": "",
          "rulesets": "---\n- name: \"Launch storm of JT's with a single action\" \n  hosts: all\n  sources:\n    - ansible.eda.generic:\n        shutdown_after: 3600\n        repeat_count: 100\n        create_index: \"index\"\n        payload:\n          - state: \"down\"\n\n\n  rules:\n    - name: \"Run job template - storm mode - single action\"\n      condition: event.state == \"down\"\n      action:\n        run_job_template:\n          name: run_basic\n          organization: Default\n          job_args:\n            extra_vars:\n              fake_execution_time: \"10\"\n",
          "project_id": 2,
          "organization_id": 1,
          "created_at": "2026-03-29T14:51:19.117948Z",
          "modified_at": "2026-03-29T14:51:19.117975Z"
        },
        {
          "id": 4,
          "name": "basic_short.yml",
          "description": "",
          "rulesets": "---\n# Basic rulebook with job template, \n# to be used with https://github.com/Alex-Izquierdo/eda-awx-project-sample\n- name: Basic short\n  hosts: all\n  sources:\n    - ansible.eda.range:\n        limit: 10\n        delay: 0.5\n  rules:\n    - name: Run JT at 8\n      condition: event.i == 8\n      actions:\n        - run_job_template:\n            organization: Default\n            name: run_basic\n            job_args:\n              extra_vars:\n                fake_execution_time: \"5\"\n\n        - debug:\n            msg: \"Basic short rulebook, event {{ event.i }}\"",
          "project_id": 2,
          "organization_id": 1,
          "created_at": "2026-03-29T14:51:19.128196Z",
          "modified_at": "2026-03-29T14:51:19.128218Z"
        },
        {
          "id": 5,
          "name": "match_multiple_rules_with_all.yml",
          "description": "",
          "rulesets": "---\n- name: match multiple rules with all\n  match_multiple_rules: true\n  hosts: all\n  sources:\n    - ansible.eda.generic:\n        payload:\n          - i: 1\n          - i: 9\n          - i: 3\n  rules:\n    - name: r1\n      condition: event.i == 1\n      action:\n        debug:\n    - name: r11\n      condition: \n        all:\n          - event.i == 1\n          - event.i == 3\n      action:\n        print_event:\n",
          "project_id": 2,
          "organization_id": 1,
          "created_at": "2026-03-29T14:51:19.138967Z",
          "modified_at": "2026-03-29T14:51:19.138988Z"
        },
        {
          "id": 6,
          "name": "awx_bad_template_name.yml",
          "description": "",
          "rulesets": "---\n# Basic rulebook with an invalid job template, \n# to be used with https://github.com/Alex-Izquierdo/eda-awx-project-sample\n- name: Basic short with an invalid job template name\n  hosts: all\n  sources:\n    - ansible.eda.range:\n        limit: 10\n        delay: 0.5\n  rules:\n    - name: Run an invalid JT at 8\n      condition: event.i == 8\n      actions:\n        - run_job_template:\n            organization: Default\n            name: run_bad_basic\n            job_args:\n              extra_vars:\n                fake_execution_time: \"5\"\n",
          "project_id": 2,
          "organization_id": 1,
          "created_at": "2026-03-29T14:51:19.150208Z",
          "modified_at": "2026-03-29T14:51:19.150229Z"
        },
        {
          "id": 7,
          "name": "hello_echo_multiaction_multirule_shutdown.yml",
          "description": "",
          "rulesets": "---\n- name: Hello World with multiaction, multirule and shutdown\n  hosts: all\n  sources:\n    - ansible.eda.range:\n        limit: 10\n        delay: \"{{ delay_seconds | default(2) | int }}\"\n  rules:\n    - name: Set event\n      condition: event.i == 1\n      actions:\n        - debug:\n            msg: \"One has come, delay seconds is {{ delay_seconds | default(2) | int }}\"\n        - print_event:\n            pretty: true\n        - post_event:\n            event:\n              say_hello: true\n\n    - name: Say Hello to everyone\n      condition: event.say_hello == true\n      actions:\n        - debug:\n            msg: \"Hello everyone\"\n        - print_event:\n            pretty: true\n        - shutdown:\n            message: \"Bye bye\"\n\n",
          "project_id": 2,
          "organization_id": 1,
          "created_at": "2026-03-29T14:51:19.161209Z",
          "modified_at": "2026-03-29T14:51:19.161229Z"
        },
        {
          "id": 8,
          "name": "one_minute_of_events.yml",
          "description": "",
          "rulesets": "---\n- name: \"One minute of events\"\n  hosts: all\n  sources:\n    - ansible.eda.range:\n        limit: 60\n        delay: 1  # 60 seconds\n  rules:\n    - name: One minute of events rule\n      condition: >-\n        event.i in [\n          0, 10, 20, 30, 40, 50, 59\n        ]\n      action:\n        debug:\n          msg: \"Event {{ event.i }} triggered\"\n",
          "project_id": 2,
          "organization_id": 1,
          "created_at": "2026-03-29T14:51:19.171227Z",
          "modified_at": "2026-03-29T14:51:19.171246Z"
        },
        {
          "id": 9,
          "name": "multi_event_multi_action.yml",
          "description": "",
          "rulesets": "- name: Multi event and multi action combo\n  hosts: all\n  sources:\n    - ansible.eda.range:\n        limit: 5\n        delay: 0.5\n\n  rules:\n    - name: Multi-match\n      condition:\n        all:\n          - event.i == 1\n          - event.i == 3\n      actions:\n        - print_event:\n        - debug:\n            msg: \"Good night\"\n\n",
          "project_id": 2,
          "organization_id": 1,
          "created_at": "2026-03-29T14:51:19.181319Z",
          "modified_at": "2026-03-29T14:51:19.181337Z"
        },
        {
          "id": 10,
          "name": "range_long_running.yml",
          "description": "",
          "rulesets": "---\n- name: Long Running Range\n  hosts: all\n  sources:\n    - ansible.eda.range:\n        limit: 63072000 # 2 years\n        delay: 1\n  rules:\n    - name: Say Hello long running\n      # Gap increases exponentially the first day\n      # then increases linearly after that\n      # one time per day the first month\n      # after one time per month. \n      condition: >-\n        event.i in [5, 30, 90, 300, 3600, 9000, 18000, 36000]\n        or event.i in [86400,\n                       172800,\n                       259200,\n                       345600,\n                       432000,\n                       518400,\n                       604800,\n                       691200,\n                       777600,\n                       864000,\n                       950400,\n                       1036800,\n                       1123200,\n                       1209600,\n                       1296000,\n                       1382400,\n                       1468800,\n                       1555200,\n                       1641600,\n                       1728000,\n                       1814400,\n                       1900800,\n                       1987200,\n                       2073600,\n                       2160000,\n                       2246400,\n                       2332800,\n                       2419200,\n                       2505600]\n        or event.i in [2591999,\n                       5183999,\n                       7775999,\n                       10367999,\n                       12959999,\n                       15551999,\n                       18143999,\n                       20735999,\n                       23327999,\n                       25919999,\n                       28511999,\n                       31103999,\n                       33695999,\n                       36287999,\n                       38879999,\n                       41471999,\n                       44063999,\n                       46655999,\n                       49247999,\n                       51839999,\n                       54431999,\n                       57023999,\n                       59615999,\n                       62207999]\n      action:\n        debug:\n          msg: \"Hello World!, event.i = {{ event.i }}\"\n",
          "project_id": 2,
          "organization_id": 1,
          "created_at": "2026-03-29T14:51:19.191656Z",
          "modified_at": "2026-03-29T14:51:19.191681Z"
        },
        {
          "id": 11,
          "name": "non_alpha_numeric_keys.yml",
          "description": "",
          "rulesets": "---\n- name: non alpha numeric keys\n  hosts: all\n  sources:\n    - ansible.eda.generic:\n        payload:\n          - \"http://www.example.com\": \"down\"\n          - urls:\n              \"http://www.example.com\": \"up\"\n          - नाम: മധു\n\n  rules:\n    - name: r1\n      condition: event[\"http://www.example.com\"] == \"down\"\n      action:\n        debug:\n          msg: \"First check worked\"\n    - name: r2\n      condition: event.urls[\"http://www.example.com\"] == \"up\"\n      action:\n        debug:\n          msg: \"Second check worked\"\n    - name: r3\n      condition: event[\"नाम\"] is search(\"മധു\", ignorecase=true) \n      action:\n        print_event:\n",
          "project_id": 2,
          "organization_id": 1,
          "created_at": "2026-03-29T14:51:19.204410Z",
          "modified_at": "2026-03-29T14:51:19.204429Z"
        },
        {
          "id": 12,
          "name": "awx_long_running.yml",
          "description": "",
          "rulesets": "---\n- name: Long Running with Awx JT\n  hosts: all\n  sources:\n    - ansible.eda.generic:\n        loop_count: \"{{ total_loops | default(63072000) | int }}\" # default two years\n        loop_delay: 1\n        event_delay: 5\n        create_index: iteration\n        payload:\n          - user: \"Rick\"\n            universe: C-137\n\n          - user: \"Morty\"\n            universe: C-137\n\n          - user: \"Rick\"\n            universe: C-132\n\n          - user: \"Rick\"\n            universe: J-19-Zeta-1\n\n          - user: \"Beth\"\n            universe: K-22\n\n          - user: \"Jerry\"\n            universe: C-137\n\n  rules:\n    - name: Awx long running rule\n      condition: event.user == \"Rick\" and event.universe == \"C-137\"\n      actions:\n        - run_job_template:\n            organization: Default\n            name: run_basic\n\n        - debug:\n            msg: \"Awx long running rulebook, event {{ event.iteration }}\"\n",
          "project_id": 2,
          "organization_id": 1,
          "created_at": "2026-03-29T14:51:19.217694Z",
          "modified_at": "2026-03-29T14:51:19.217715Z"
        },
        {
          "id": 13,
          "name": "multi_action_delayed.yml",
          "description": "",
          "rulesets": "- name: Multi action with delay\n  hosts: all\n  sources:\n    - ansible.eda.range:\n        limit: 15\n        delay: 1\n\n  rules:\n    - name: Greetings with delay\n      condition: event.i == 1\n      actions:\n        - debug:\n            msg: \"Good morning\"\n        - run_job_template:\n            organization: Default\n            name: run_basic\n            job_args:\n              extra_vars:\n                fake_execution_time: \"3\"\n        - debug:\n            msg: \"Good night\"\n        - run_job_template:\n            organization: Default\n            name: run_basic\n            job_args:\n              extra_vars:\n                fake_execution_time: \"2\"\n",
          "project_id": 2,
          "organization_id": 1,
          "created_at": "2026-03-29T14:51:19.230011Z",
          "modified_at": "2026-03-29T14:51:19.230033Z"
        },
        {
          "id": 14,
          "name": "awx_basic_custom_limit.yml",
          "description": "",
          "rulesets": "---\n- name: Basic run with custom host limit\n  hosts: all\n  sources:\n    - ansible.eda.generic:\n        event_delay: 1\n        payload:\n          - user: \"Rick\"\n            universe: C-137\n            hosts:\n              - eda_localhost2\n\n          - user: \"Morty\"\n            universe: C-137\n\n          - user: \"Rick\"\n            universe: C-132\n\n          - user: \"Rick\"\n            universe: J-19-Zeta-1\n\n          - user: \"Beth\"\n            universe: K-22\n\n          - user: \"Jerry\"\n            universe: C-137\n\n  rules:\n    - name: Run basic with custom host limit\n      condition: event.user == \"Rick\" and event.universe == \"C-137\"\n      actions:\n        - run_job_template:\n            organization: Default\n            name: run_basic\n            job_args:\n              limit: \"{{ event.hosts }}\"\n",
          "project_id": 2,
          "organization_id": 1,
          "created_at": "2026-03-29T14:51:19.243048Z",
          "modified_at": "2026-03-29T14:51:19.243094Z"
        },
        {
          "id": 15,
          "name": "succeed_and_fail.yml",
          "description": "",
          "rulesets": "# rulebook with failed and successful job templates, \n# to be used with https://github.com/Alex-Izquierdo/eda-awx-project-sample\n  - name: Fail and succeed\n    hosts: all\n    sources:\n      - ansible.eda.range:\n          limit: 3\n    rules:\n      - name: Run multiple actions with success and failure\n        condition: event.i == 0\n        actions:\n          - run_job_template:\n              organization: Default\n              name: run_basic\n              job_args:\n                extra_vars:\n                  fake_execution_time: '1'\n          - run_job_template:\n              organization: Default\n              name: fail_basic\n          - run_job_template:\n              organization: Default\n              name: run_basic\n              job_args:\n                extra_vars:\n                  fake_execution_time: '1'\n",
          "project_id": 2,
          "organization_id": 1,
          "created_at": "2026-03-29T14:51:19.255352Z",
          "modified_at": "2026-03-29T14:51:19.255373Z"
        },
        {
          "id": 16,
          "name": "data_center_label.yml",
          "description": "",
          "rulesets": "---\n- name: Test run job templates with labels\n  hosts: all\n  sources:\n    - ansible.eda.generic:\n        payload:\n           - name: \"{{ event_name }}\"\n             error: 678\n        shutdown_after: 45\n  rules:\n    - name: \"Run job template\"\n      condition: event.error >= 303\n      action:\n        run_job_template:\n          name: \"{{ job_template_name }}\"\n          organization: \"{{ organization }}\"\n          job_args:\n            extra_vars:\n              hello: Fred\n          labels: \n            - \"{{ event.name }}\"\n            - I am label\n            - \"{{ user_label }}\"\n",
          "project_id": 2,
          "organization_id": 1,
          "created_at": "2026-03-29T14:51:19.265030Z",
          "modified_at": "2026-03-29T14:51:19.265050Z"
        },
        {
          "id": 17,
          "name": "basic_workflow_template_failed.yml",
          "description": "",
          "rulesets": "---\n- name: Test run workflow templates with failure\n  hosts: all\n  sources:\n    - ansible.eda.range:\n        limit: 5\n        delay: 10\n  rules:\n    - name: \"Run workflow template\"\n      condition: event.i == 0\n      action:\n        run_workflow_template:\n          name: workflow_basic_fail\n          job_args:\n            extra_vars:\n              fake_execution_time: \"2\"\n          retries: 1\n          delay: 10\n          organization: Default\n",
          "project_id": 2,
          "organization_id": 1,
          "created_at": "2026-03-29T14:51:19.276312Z",
          "modified_at": "2026-03-29T14:51:19.276340Z"
        },
        {
          "id": 18,
          "name": "webhook_servicenow.yml",
          "description": "",
          "rulesets": "---\n- name: Run a webhook listener service for ServiceNow integration tests\n  hosts: all\n  sources:\n    - ansible.eda.webhook:\n        port: 5005\n  rules:\n    - name: ServiceNow Incident\n      condition: event.payload.number is search(\"INC\", ignorecase=false)\n      action:\n        debug:\n          msg: \"ServiceNow Incident received!\"\n\n    - name: ServiceNow Problem\n      condition: event.payload.number is search(\"PRB\", ignorecase=false)\n      action:\n        debug:\n          msg: \"ServiceNow Problem received!\"\n\n    - name: ServiceNow Catalog Request\n      condition: event.payload.number is search(\"REQ\", ignorecase=false)\n      action:\n        debug:\n          msg: \"ServiceNow Catalog Request received!\"\n\n    - name: Shutdown\n      condition: event.payload.shutdown is defined\n      action:\n        shutdown:\n",
          "project_id": 2,
          "organization_id": 1,
          "created_at": "2026-03-29T14:51:19.285867Z",
          "modified_at": "2026-03-29T14:51:19.285887Z"
        },
        {
          "id": 19,
          "name": "webhook_defaults.yml",
          "description": "",
          "rulesets": "---\n- name: Run a webhook listener service\n  hosts: all\n  sources:\n    - ansible.eda.webhook:\n  rules:\n    - name: Webhook event\n      condition: event.payload.ping == \"pong\"\n      action:\n        debug:\n          msg: \"Webhook triggered!\"\n\n    - name: Shutdown\n      condition: event.payload.shutdown is defined\n      action:\n        shutdown:\n",
          "project_id": 2,
          "organization_id": 1,
          "created_at": "2026-03-29T14:51:19.296215Z",
          "modified_at": "2026-03-29T14:51:19.296234Z"
        },
        {
          "id": 20,
          "name": "webhook_with_vars.yml",
          "description": "",
          "rulesets": "---\n- name: Test webhook with extra vars\n  hosts: all\n  sources:\n    - name: webhook\n      ansible.eda.webhook:\n        host: 0.0.0.0\n        port: 5555\n  rules:\n    - name: rule1\n      condition: event.payload.username == vars.username\n      action:\n        debug:\n          msg: \"Expected user is here\"\n    - name: Shutdown\n      condition: event.payload.shutdown is defined\n      action:\n        shutdown:\n          \n\n",
          "project_id": 2,
          "organization_id": 1,
          "created_at": "2026-03-29T14:51:19.305862Z",
          "modified_at": "2026-03-29T14:51:19.305882Z"
        }
      ]
    }
    
  2. Найдите в ответе свод правил с названием webhook_defaults.yml и сохраните его идентификатор.

  3. Получите список доступных сред принятия решений:

    curl \
       -H 'Authorization: Bearer <your_token>' \
       https://<address>/api/eda/v1/decision-environments/ | jq
    
    Пример вывода
    {
      "count": 2,
      "next": null,
      "previous": null,
      "page_size": 20,
      "page": 1,
      "results": [
        {
          "name": "Default Decision Environment",
          "description": "",
          "image_url": "hub.astra-automation.ru/aa-2.0/aa-full-de:latest",
          "organization_id": 1,
          "eda_credential_id": null,
          "created_by": {
            "id": 1,
            "username": "admin",
            "first_name": "",
            "last_name": ""
          },
          "modified_by": {
            "id": 1,
            "username": "admin",
            "first_name": "",
            "last_name": ""
          },
          "id": 1,
          "created_at": "2026-01-15T11:26:55.168428Z",
          "modified_at": "2026-01-15T11:26:55.168448Z"
        },
        {
          "name": "Automation Hub Default Decision Environment",
          "description": "",
          "image_url": "10.205.212.131/aa-2.0/aa-full-de:latest",
          "organization_id": 1,
          "eda_credential_id": 2,
          "created_by": {
            "id": 1,
            "username": "admin",
            "first_name": "",
            "last_name": ""
          },
          "modified_by": {
            "id": 1,
            "username": "admin",
            "first_name": "",
            "last_name": ""
          },
          "id": 2,
          "created_at": "2026-01-15T11:26:57.394938Z",
          "modified_at": "2026-01-15T11:26:57.394957Z"
        }
      ]
    }
    
  4. Найдите в ответе среду принятия решений с названием Default Decision Environment и сохраните ее идентификатор.

  5. Получите список типов полномочий:

    curl \
       -H 'Authorization: Bearer <your_token>' \
       https://<address>/api/eda/v1/credential-types/?page_size=100 | jq
    
    Пример вывода
    {
      "count": 16,
      "next": null,
      "previous": null,
      "page_size": 100,
      "page": 1,
      "results": [
        {
          "name": "Astra Automation Platform",
          "namespace": "controller",
          "kind": "cloud",
          "description": "",
          "inputs": {
            "fields": [
              {
                "id": "host",
                "type": "string",
                "label": "Astra Automation Platform",
                "help_text": "Astra Automation Platform base URL to authenticate with."
              },
              {
                "id": "username",
                "type": "string",
                "label": "Username",
                "help_text": "Astra Automation Platform username id to authenticate as.This should not be set if an OAuth token is being used."
              },
              {
                "id": "password",
                "type": "string",
                "label": "Password",
                "secret": true
              },
              {
                "id": "oauth_token",
                "type": "string",
                "label": "OAuth Token",
                "secret": true,
                "help_text": "An OAuth token to use to authenticate with.This should not be set if username/password are being used."
              },
              {
                "id": "verify_ssl",
                "type": "boolean",
                "label": "Verify SSL",
                "secret": false
              },
              {
                "id": "request_timeout",
                "type": "string",
                "label": "Request Timeout",
                "secret": false,
                "default": "10",
                "help_text": "Specify the timeout Ansible should use in requests tothe host. Defaults to 10s"
              }
            ],
            "required": ["host"]
          },
          "injectors": {
            "env": {
              "AAP_TOKEN": "{{oauth_token}}",
              "TOWER_HOST": "{{host}}",
              "AAP_HOSTNAME": "{{host}}",
              "AAP_PASSWORD": "{{password}}",
              "AAP_USERNAME": "{{username}}",
              "AAP_VERIFY_SSL": "{{verify_ssl}}",
              "TOWER_PASSWORD": "{{password}}",
              "TOWER_USERNAME": "{{username}}",
              "CONTROLLER_HOST": "{{host}}",
              "TOWER_VERIFY_SSL": "{{verify_ssl}}",
              "TOWER_OAUTH_TOKEN": "{{oauth_token}}",
              "AAP_REQUEST_TIMEOUT": "{{request_timeout}}",
              "CONTROLLER_PASSWORD": "{{password}}",
              "CONTROLLER_USERNAME": "{{username}}",
              "CONTROLLER_VERIFY_SSL": "{{verify_ssl}}",
              "CONTROLLER_OAUTH_TOKEN": "{{oauth_token}}",
              "CONTROLLER_REQUEST_TIMEOUT": "{{request_timeout}}"
            },
            "extra_vars": {
              "aap_token": "{{oauth_token}}",
              "aap_hostname": "{{host}}",
              "aap_password": "{{password}}",
              "aap_username": "{{username}}",
              "aap_verify_ssl": "{{verify_ssl}}",
              "aap_request_timeout": "{{request_timeout}}"
            }
          },
          "id": 4,
          "created_at": "2026-01-15T11:17:15.935512Z",
          "modified_at": "2026-01-15T11:17:15.935535Z",
          "managed": true
        },
        {
          "name": "Basic Event Stream",
          "namespace": "event_stream",
          "kind": "basic",
          "description": "Credential for EventStreams that use Basic Authentication. It requires a username and password",
          "inputs": {
            "fields": [
              {
                "id": "auth_type",
                "type": "string",
                "label": "Event Stream Authentication Type",
                "hidden": true,
                "default": "basic"
              },
              {
                "id": "username",
                "type": "string",
                "label": "Username",
                "help_text": "The username used to authenticate the incoming event stream"
              },
              {
                "id": "password",
                "type": "string",
                "label": "Password",
                "secret": true,
                "help_text": "The password used to authenticate the incoming event stream"
              },
              {
                "id": "http_header_key",
                "type": "string",
                "label": "HTTP Header Key",
                "hidden": true,
                "default": "Authorization"
              }
            ],
            "required": ["auth_type", "password", "username", "http_header_key"]
          },
          "injectors": {},
          "id": 7,
          "created_at": "2026-01-15T11:17:15.965117Z",
          "modified_at": "2026-01-15T11:17:15.965152Z",
          "managed": true
        }
      ]
    }
    
  6. Найдите в ответе тип полномочий Basic Event Stream и сохраните его идентификатор.

Подготовка потока событий#

Для подготовки потока событий выполните следующие действия:

  1. Создайте полномочие типа Basic Event Stream:

    curl -X POST \
       -H 'Authorization: Bearer <your_token>' \
       -H 'Content-Type: application/json' \
       -d '{
                "name": "<credential_name>",
                "organization_id": <organization_id>,
                "credential_type_id": <credential_type_id>,
                "inputs": {
                   "username": "<username>",
                   "password": "<password>"
                         }
             }' \
       https://<address>/api/eda/v1/eda-credentials/ | jq
    

    Подставьте собственные значения параметров вместо употребленных в примере:

    • <credential_name> – название создаваемого полномочия, например basic-event-stream-credential;

    • <credential_type_id> – идентификатор типа полномочий, полученный ранее, например 7;

    • <username> – название учетной записи, используемой для авторизации;

    • <password> – пароль.

    Пример вывода
    {
      "id": 4,
      "name": "basic-event-stream-credential",
      "description": "",
      "managed": false,
      "inputs": {
        "auth_type": "basic",
        "http_header_key": "Authorization",
        "password": "$encrypted$",
        "username": "admin"
      },
      "credential_type": {
        "id": 7,
        "name": "Basic Event Stream",
        "namespace": "event_stream",
        "kind": "basic"
      },
      "organization": {
        "id": 1,
        "name": "Default",
        "description": "The default organization for Astra Automation"
      },
      "references": null,
      "created_at": "2026-03-29T20:41:50.201077Z",
      "modified_at": "2026-03-29T20:41:50.201140Z",
      "created_by": {
        "id": 1,
        "username": "admin",
        "first_name": "",
        "last_name": ""
      },
      "modified_by": {
        "id": 1,
        "username": "admin",
        "first_name": "",
        "last_name": ""
      }
    }
    
  2. Создайте поток событий:

    curl -X POST \
       -H 'Authorization: Bearer <your_token>' \
       -H 'Content-Type: application/json' \
       -d '{
                "name": "<event_stream_name>",
                "organization_id": <organization_id>,
                "eda_credential_id": <eda_credential_id>,
                "headers": "Authorization,Content-Type",
                "forward_events": false
            }' \
       https://<address>/api/eda/v1/event-streams/ | jq
    

    Подставьте собственные значения параметров вместо употребленных в примере:

    • <event_stream_name> – название создаваемого потока событий, например basic-auth-stream;

    • <eda_credential_id> – идентификатор полномочия, созданного ранее, например 4.

    Пример вывода
    {
      "name": "basic-auth-stream",
      "test_mode": false,
      "additional_data_headers": "",
      "organization": {
        "id": 1,
        "name": "Default",
        "description": "The default organization for Astra Automation"
      },
      "eda_credential": {
        "id": 4,
        "name": "basic-event-stream-credential",
        "description": "Credential for Event Stream demo",
        "inputs": {
          "auth_type": "basic",
          "http_header_key": "Authorization",
          "password": "$encrypted$",
          "username": "admin"
        },
        "managed": false,
        "credential_type_id": 7,
        "organization_id": 1
      },
      "event_stream_type": "basic",
      "created_by": {
        "id": 1,
        "username": "admin",
        "first_name": "",
        "last_name": ""
      },
      "modified_by": {
        "id": 1,
        "username": "admin",
        "first_name": "",
        "last_name": ""
      },
      "id": 1,
      "owner": "admin",
      "url": "https://<adress>/eda-event-streams/api/eda/v1/external_event_stream/e7c690be-16b7-4eee-a743-e2dcf7719161/post/",
      "created_at": "2026-03-29T20:52:44.459302Z",
      "modified_at": "2026-03-29T20:52:44.459481Z",
      "test_content_type": "",
      "test_content": "",
      "test_error_message": "",
      "test_headers": "",
      "events_received": 0,
      "last_event_received_at": null
    }
    

    В ответе найдите поле url и сохраните его значение. Это URL приема событий, он понадобится для отправки тестового события в контроллер Event-Driven Automation. Этот URL может отличаться по префиксу от URI ресурсов /api/eda/v1/, так как входящий прием событий обслуживается отдельной службой.

Подготовка активации свода правил#

Для подготовки активации свода правил выполните следующие действия:

  1. Узнайте хеш свода правил:

    curl \
       -H 'Authorization: Bearer <your_token>' \
       https://<address>/api/eda/v1/rulebooks/<rulebook_id>/sources/ | jq
    

    Здесь <rulebook_id> – идентификатор свода правил webhook_defaults.yml, например 19.

    Пример вывода
    {
      "count": 1,
      "next": null,
      "previous": null,
      "page_size": 20,
      "page": 1,
      "results": [
        {
          "name": "__SOURCE_1",
          "source_info": "ansible.eda.webhook: null\n",
          "rulebook_hash": "739fc83f68da2f69186cc1a8b5db40ced4f0f668d0a39a73ba37f525c3320fa5"
        }
      ]
    }
    
  2. Создайте активацию свода правил:

    curl -X POST \
       -H 'Authorization: Bearer <your_token>' \
       -H 'Content-Type: application/json' \
       -d '{
                "organization_id": <organization_id>,
                "restart_policy": "on-failure",
                "log_level": "error",
                "is_enabled": true,
                "name": "<activation_name>",
                "project_id": <project_id>,
                "rulebook_id": <rulebook_id>,
                "eda_credentials": [],
                "decision_environment_id": <decision_environment_id>,
                "source_mappings": "- source_name: __SOURCE_1\n  event_stream_id: 1\n  event_stream_name: basic-auth-stream\n  rulebook_hash: <rulebook_hash>\n"
                }' \
       https://<address>/api/eda/v1/activations/ | jq
    

    Подставьте собственные значения параметров вместо употребленных в примере:

    • <activation_name> – название активации свода правил, например webhook-activation.

    • <decision_environment_id> – идентификатор среды принятия решений, например 1;

    • <rulebook_hash> – хеш свода правил, полученный на предыдущем шаге.

    Пример вывода
    {
      "id": 11,
      "name": "webhook-activation",
      "description": "",
      "is_enabled": true,
      "decision_environment": {
        "id": 1,
        "name": "Default Decision Environment",
        "description": "",
        "image_url": "hub.astra-automation.ru/aa-2.0/aa-full-de:latest",
        "organization_id": 1
      },
      "status": "pending",
      "git_hash": "fb761c11ed7d313195c0dc346ba76d64fdf4a4d5",
      "project": {
        "id": 2,
        "git_hash": "fb761c11ed7d313195c0dc346ba76d64fdf4a4d5",
        "url": "https://github.com/ansible/eda-sample-project",
        "scm_type": "git",
        "name": "test",
        "description": "test",
        "organization_id": 1
      },
      "rulebook": {
        "id": 19,
        "name": "webhook_defaults.yml",
        "description": "",
        "organization_id": 1
      },
      "extra_var": "postgres_db_host: <adress>\npostgres_db_name: automationedacontroller\npostgres_db_password: $encrypted$\npostgres_db_port: 5432\npostgres_db_user: automationedacontroller\npostgres_sslmode: prefer\npostgres_sslpassword: null\n",
      "organization": {
        "id": 1,
        "name": "Default",
        "description": "The default organization for Astra Automation"
      },
      "instances": [],
      "restart_policy": "on-failure",
      "restart_count": 0,
      "rulebook_name": "webhook_defaults.yml",
      "current_job_id": null,
      "ruleset_stats": "",
      "rules_count": 0,
      "rules_fired_count": 0,
      "created_at": "2026-03-30T15:21:20.716451Z",
      "modified_at": "2026-03-30T15:21:20.716479Z",
      "edited_at": null,
      "restarted_at": null,
      "status_message": "Wait for a worker to be available to start activation",
      "awx_token_id": null,
      "log_level": "error",
      "eda_credentials": [],
      "k8s_service_name": null,
      "event_streams": [
        {
          "name": "basic-auth-stream",
          "test_mode": false,
          "additional_data_headers": "",
          "organization": {
            "id": 1,
            "name": "Default",
            "description": "The default organization for Astra Automation"
          },
          "eda_credential": {
            "id": 4,
            "name": "basic-event-stream-credential",
            "description": "Credential for Event Stream demo",
            "inputs": {
              "auth_type": "basic",
              "http_header_key": "Authorization",
              "password": "$encrypted$",
              "username": "admin"
            },
            "managed": false,
            "credential_type_id": 7,
            "organization_id": 1
          },
          "event_stream_type": "basic",
          "created_by": {
            "id": 1,
            "username": "admin",
            "first_name": "",
            "last_name": ""
          },
          "modified_by": {
            "id": 1,
            "username": "admin",
            "first_name": "",
            "last_name": ""
          },
          "id": 1,
          "owner": "admin",
          "url": "https://<adress>/eda-event-streams/api/eda/v1/external_event_stream/e7c690be-16b7-4eee-a743-e2dcf7719161/post/",
          "created_at": "2026-03-29T20:52:44.459302Z",
          "modified_at": "2026-03-29T20:52:44.459481Z",
          "test_content_type": "",
          "test_content": "",
          "test_error_message": "",
          "test_headers": "",
          "events_received": 1,
          "last_event_received_at": "2026-03-29T22:25:23.124793Z"
        }
      ],
      "source_mappings": "- source_name: __SOURCE_1\n  event_stream_id: 1\n  event_stream_name: basic-auth-stream\n  rulebook_hash: 739fc83f68da2f69186cc1a8b5db40ced4f0f668d0a39a73ba37f525c3320fa5",
      "skip_audit_events": false,
      "log_tracking_id": "47acb6b7-94a0-4435-bfaa-7419f15b9458",
      "created_by": {
        "id": 1,
        "username": "admin",
        "first_name": "",
        "last_name": ""
      },
      "modified_by": {
        "id": 1,
        "username": "admin",
        "first_name": "",
        "last_name": ""
      },
      "edited_by": {
        "id": 1,
        "username": "admin",
        "first_name": "",
        "last_name": ""
      }
    }
    

Отправка тестового события#

После запуска активации отправьте сообщение, имитирующее обнаружение события сервисом webhook. Используемый свод правил ожидает событие с условием event.payload.ping == \"pong\".

Отправьте запрос вида:

curl -X POST \
   -u "<username>:<password>" \
  -H "Content-Type: application/json" \
  -d '{"ping":"pong"}' \
  <event_stream_url>

Здесь <event_stream_url> – URL приема событий, полученный при создании потока событий.

Проверка результата#

Для проверки выполните следующие действия:

  1. Проверьте поток событий:

    curl \
       -H 'Authorization: Bearer <your_token>' \
       https://<address>/api/eda/v1/event-streams/<event_stream_id>/ | jq
    

    Здесь <event_stream_id> – идентификатор потока событий, созданного ранее, например 1.

    Пример вывода
    {
      "name": "basic-auth-stream",
      "test_mode": false,
      "additional_data_headers": "",
      "organization": {
        "id": 1,
        "name": "Default",
        "description": "The default organization for Astra Automation"
      },
      "eda_credential": {
        "id": 4,
        "name": "basic-event-stream-credential",
        "description": "Credential for Event Stream demo",
        "inputs": {
          "auth_type": "basic",
          "http_header_key": "Authorization",
          "password": "$encrypted$",
          "username": "admin"
        },
        "managed": false,
        "credential_type_id": 7,
        "organization_id": 1
      },
      "event_stream_type": "basic",
      "created_by": {
        "id": 1,
        "username": "admin",
        "first_name": "",
        "last_name": ""
      },
      "modified_by": {
        "id": 1,
        "username": "admin",
        "first_name": "",
        "last_name": ""
      },
      "id": 1,
      "owner": "admin",
      "url": "https://<adress>/eda-event-streams/api/eda/v1/external_event_stream/e7c690be-16b7-4eee-a743-e2dcf7719161/post/",
      "created_at": "2026-03-29T20:52:44.459302Z",
      "modified_at": "2026-03-29T20:52:44.459481Z",
      "test_content_type": "",
      "test_content": "",
      "test_error_message": "",
      "test_headers": "",
      "events_received": 2,
      "last_event_received_at": "2026-03-30T15:36:01.438940Z"
    }
    

    Убедитесь, что в ответе увеличилось количество принятых событий в поле events_received.

  2. Получите список активаций:

    curl \
       -H 'Authorization: Bearer <your_token>' \
    https://<address>/api/eda/v1/activations/ | jq
    
    Пример вывода
    {
      "count": 1,
      "next": null,
      "previous": null,
      "page_size": 20,
      "page": 1,
      "results": [
        {
          "id": 11,
          "name": "webhook-activation",
          "description": "",
          "is_enabled": true,
          "status": "running",
          "decision_environment_id": 1,
          "project_id": 2,
          "rulebook_id": 19,
          "extra_var": "postgres_db_host: <adress>\npostgres_db_name: automationedacontroller\npostgres_db_password: $encrypted$\npostgres_db_port: 5432\npostgres_db_user: automationedacontroller\npostgres_sslmode: prefer\npostgres_sslpassword: null\n",
          "organization_id": 1,
          "restart_policy": "on-failure",
          "restart_count": 0,
          "rulebook_name": "webhook_defaults.yml",
          "current_job_id": null,
          "rules_count": 2,
          "rules_fired_count": 1,
          "created_at": "2026-03-30T15:21:20.716451Z",
          "modified_at": "2026-03-30T15:21:40.581219Z",
          "edited_at": null,
          "status_message": "Container running activation",
          "awx_token_id": null,
          "log_level": "error",
          "eda_credentials": [],
          "k8s_service_name": null,
          "event_streams": [
            {
              "name": "basic-auth-stream",
              "test_mode": false,
              "additional_data_headers": "",
              "organization": {
                "id": 1,
                "name": "Default",
                "description": "The default organization for Astra Automation"
              },
              "eda_credential": {
                "id": 4,
                "name": "basic-event-stream-credential",
                "description": "Credential for Event Stream demo",
                "inputs": {
                  "auth_type": "basic",
                  "http_header_key": "Authorization",
                  "password": "$encrypted$",
                  "username": "admin"
                },
                "managed": false,
                "credential_type_id": 7,
                "organization_id": 1
              },
              "event_stream_type": "basic",
              "created_by": {
                "id": 1,
                "username": "admin",
                "first_name": "",
                "last_name": ""
              },
              "modified_by": {
                "id": 1,
                "username": "admin",
                "first_name": "",
                "last_name": ""
              },
              "id": 1,
              "owner": "admin",
              "url": "https://<adress>/eda-event-streams/api/eda/v1/external_event_stream/e7c690be-16b7-4eee-a743-e2dcf7719161/post/",
              "created_at": "2026-03-29T20:52:44.459302Z",
              "modified_at": "2026-03-29T20:52:44.459481Z",
              "test_content_type": "",
              "test_content": "",
              "test_error_message": "",
              "test_headers": "",
              "events_received": 2,
              "last_event_received_at": "2026-03-30T15:36:01.438940Z"
            }
          ],
          "source_mappings": "- source_name: __SOURCE_1\n  event_stream_id: 1\n  event_stream_name: basic-auth-stream\n  rulebook_hash: 739fc83f68da2f69186cc1a8b5db40ced4f0f668d0a39a73ba37f525c3320fa5",
          "skip_audit_events": false,
          "log_tracking_id": "47acb6b7-94a0-4435-bfaa-7419f15b9458",
          "created_by": {
            "id": 1,
            "username": "admin",
            "first_name": "",
            "last_name": ""
          },
          "modified_by": {
            "id": 1,
            "username": "admin",
            "first_name": "",
            "last_name": ""
          },
          "edited_by": {
            "username": "",
            "first_name": "",
            "last_name": ""
          }
        }
      ]
    }
    

    Найдите в ответе активацию со значением running в поле status.

  3. Получите список экземпляров активации:

    curl \
       -H 'Authorization: Bearer <your_token>' \
       https://<address>/api/eda/v1/activations/<activation_id>/instances/ | jq
    

    Здесь <activation_id> – идентификатор активации, полученный на предыдущем шаге.

    Пример вывода
    {
      "count": 1,
      "next": null,
      "previous": null,
      "page_size": 20,
      "page": 1,
      "results": [
        {
          "id": 1,
          "name": "webhook-activation",
          "status": "running",
          "git_hash": "fb761c11ed7d313195c0dc346ba76d64fdf4a4d5",
          "status_message": "Container running activation",
          "activation_id": 1,
          "organization_id": 1,
          "started_at": "2026-03-29T17:27:16.872767Z",
          "ended_at": "2026-03-29T17:51:28.432151Z",
          "queue_name": "eda-aa-docdoc04-6a2e24ba-2dc3-4cdc-8644-3e6f451a3d1f"
        }
      ]
    }
    

    Найдите в ответе экземпляр со значением running в поле status.

  4. Получите журнал экземпляра активации:

    curl \
       -H 'Authorization: Bearer <your_token>' \
       https://<address>/api/eda/v1/activation-instances/<instances_id>/logs/ | jq
    

    Здесь <instances_id> – идентификатор экземпляра, полученный на предыдущем шаге.

    Пример вывода
    {
      "count": 10,
      "next": null,
      "previous": null,
      "page_size": 20,
      "page": 1,
      "results": [
        {
          "id": 372,
          "log": "Pulling image hub.astra-automation.ru/aa-2.0/aa-full-de:latest",
          "log_timestamp": 1774884083,
          "log_created_at": null,
          "activation_instance": 35
        },
        {
          "id": 373,
          "log": "Log tracking id: 47acb6b7-94a0-4435-bfaa-7419f15b9458",
          "log_timestamp": 1774884083,
          "log_created_at": null,
          "activation_instance": 35
        },
        {
          "id": 374,
          "log": "Starting Container",
          "log_timestamp": 1774884085,
          "log_created_at": null,
          "activation_instance": 35
        },
        {
          "id": 375,
          "log": "Container args ['ansible-rulebook', '--worker', '--websocket-ssl-verify', 'yes', '--websocket-url', 'wss://localhost:443/api/eda/ws/ansible-rulebook', '--websocket-access-token', '******', '--websocket-refresh-token', '******', '--websocket-token-url', 'https://localhost:443/api/eda/v1/auth/token/refresh/', '--id', '35', '--heartbeat', '300']",
          "log_timestamp": 1774884085,
          "log_created_at": null,
          "activation_instance": 35
        },
        {
          "id": 376,
          "log": "Container 88864bc6f5cd85374e8b8f0a38a68fa83de8613e52fb5bc0f371fd22c5e913d5 is running.",
          "log_timestamp": 1774884085,
          "log_created_at": null,
          "activation_instance": 35
        },
        {
          "id": 377,
          "log": "[0.006s][warning][perf,memops] Cannot use file /tmp/hsperfdata_yc-user/15 because it is locked by another process (errno = 11)",
          "log_timestamp": 1774884094,
          "log_created_at": null,
          "activation_instance": 35
        },
        {
          "id": 383,
          "log": "[debug] ******************************************",
          "log_timestamp": 1774884962,
          "log_created_at": "2026-03-30T15:36:02.680961Z",
          "activation_instance": 35
        },
        {
          "id": 384,
          "log": "Webhook triggered!",
          "log_timestamp": 1774884962,
          "log_created_at": null,
          "activation_instance": 35
        },
        {
          "id": 385,
          "log": "********************************************************************************",
          "log_timestamp": 1774884962,
          "log_created_at": null,
          "activation_instance": 35
        },
        {
          "id": 386,
          "log": "********************************************************************************",
          "log_timestamp": 1774884962,
          "log_created_at": null,
          "activation_instance": 35
        }
      ]
    }
    

    Убедитесь, что в выводе присутствует сообщение Webhook triggered!.

  5. Проверьте аудит правил:

    curl \
        -H 'Authorization: Bearer <your_token>' \
        https://<address>/api/eda/v1/audit-rules/?page_size=100 | jq
    
    Пример вывода
    {
      "count": 4,
      "next": null,
      "previous": null,
      "page_size": 100,
      "page": 1,
      "results": [
        {
          "id": 1,
          "name": "Webhook event",
          "status": "successful",
          "activation_instance": {
            "id": 1,
            "name": "webhook-activation"
          },
          "organization": {
            "id": 1,
            "name": "Default",
            "description": "The default organization for Astra Automation"
          },
          "fired_at": "2026-03-30T15:36:01.572394Z"
        }
      ]
    }
    

    Убедитесь, что поле status активации, созданной ранее, имеет значение successful.

Заключение#

В этом сценарии показано, как с помощью API в Event-Driven Automation создать и настроить ресурсы, необходимые для запуска активации свода правил. В результате вы подготовили рабочую активацию, связали ее с потоком активности и проверили обработку тестового события. Полученный сценарий можно использовать как базовый пример для дальнейшей интеграции Event-Driven Automation с внешними источниками событий через API.