36 KiB
у меня есть AirFlow класстер и github репозиторий для хранения DAGs. Я хочу написать Laravel Jetstream Livewire App для учета и загрузки DAGs в репозиторий чтобы AirFlow мог получить к ним доступ. Никто из пользователей не имеет доступ к Github репозиторию. Доступ осуществляется только через Laravel App в рамках предоставленных прав пользователя. Также я хотел бы видеть статусы выполнения и очередь пользовательского загруженного DAG в Laravel App. Обобщи следующие предложения и напиши финальный пошаговый план для реализации моей задачи:
1. Настройка Laravel Jetstream с Livewire
-
Установка Laravel:
composer create-project laravel/laravel airflow-dag-manager
-
Установка Jetstream с Livewire:
composer require laravel/jetstream php artisan jetstream:install livewire npm install npm run dev php artisan migrate
2. Реализация аутентификации и авторизации пользователей
-
Аутентификация:
Jetstream предоставляет готовые механизмы регистрации, входа и восстановления пароля.
-
Авторизация:
-
Определите роли и разрешения пользователей.
-
Используйте Policies или Gates Laravel для контроля доступа.
-
Рекомендуется использовать пакет Spatie Laravel-Permission:
composer require spatie/laravel-permission
-
Настройте роли (например,
admin
,user
) и разрешения (upload dag
,view status
).
-
3. Интеграция с GitHub API для загрузки DAG-файлов
-
Аутентификация GitHub API:
-
Создайте Personal Access Token с необходимыми правами (
repo
для приватных репозиториев). -
Сохраните токен в файле
.env
:GITHUB_TOKEN=ваш_токен
-
-
Использование GitHub API:
-
Используйте пакет knplabs/github-api или Guzzle для взаимодействия с API.
composer require knplabs/github-api
-
Пример загрузки файла в репозиторий:
use Github\Client; $client = new Client(); $client->authenticate(env('GITHUB_TOKEN'), null, Client::AUTH_ACCESS_TOKEN); $username = 'ваш_логин'; $repository = 'имя_репозитория'; $branch = 'main'; $path = 'dags/' . $dagFilename; $content = file_get_contents($uploadedDagFile); // Получение текущего SHA коммита $reference = $client->api('gitData')->references()->show($username, $repository, 'heads/' . $branch); $commitSha = $reference['object']['sha']; // Создание нового блоба $blob = $client->api('gitData')->blobs()->create($username, $repository, [ 'content' => base64_encode($content), 'encoding' => 'base64', ]); // Создание нового дерева $tree = $client->api('gitData')->trees()->create($username, $repository, [ 'base_tree' => $commitSha, 'tree' => [ [ 'path' => $path, 'mode' => '100644', 'type' => 'blob', 'sha' => $blob['sha'], ], ], ]); // Создание нового коммита $commit = $client->api('gitData')->commits()->create($username, $repository, [ 'message' => 'Добавлен DAG ' . $dagFilename, 'tree' => $tree['sha'], 'parents' => [$commitSha], ]); // Обновление ссылки $client->api('gitData')->references()->update($username, $repository, 'heads/' . $branch, [ 'sha' => $commit['sha'], ]);
-
-
Отслеживание загруженных DAG:
-
Создайте таблицу
dags
в базе данных с полямиid
,user_id
,filename
,created_at
и т.д.
5. Получение статусов выполнения и очереди из Airflow
-
API Airflow:
-
Включите REST API в
airflow.cfg
:[api] auth_backend = airflow.api.auth.backend.basic_auth
-
Аутентификация:
- Используйте Basic Auth или другой поддерживаемый метод.
-
Получение статусов DAG:
use Illuminate\Support\Facades\Http; $response = Http::withBasicAuth('airflow_username', 'airflow_password') ->get('http://airflow-server:8080/api/v1/dags/{dag_id}/dagRuns'); $dagRuns = $response->json();
- Компонент для загрузки DAG-файлов 1.1. Создание компонента Создайте Livewire-компонент UploadDagComponent:
php artisan make:livewire UploadDagComponent
1.2. Код компонента app/Http/Livewire/UploadDagComponent.php
<?php
namespace App\Http\Livewire;
use Livewire\Component;
use Livewire\WithFileUploads;
use Illuminate\Support\Facades\Auth;
use Github\Client;
use Illuminate\Support\Facades\Storage;
class UploadDagComponent extends Component
{
use WithFileUploads;
public $dagFile;
protected $rules = [
'dagFile' => 'required|file|mimes:py|max:1024', // Максимальный размер 1MB
];
public function uploadDag()
{
$this->validate();
// Сохранение файла временно
$path = $this->dagFile->store('temp_dags');
$filename = $this->dagFile->getClientOriginalName();
$content = Storage::get($path);
// Интеграция с GitHub API
$client = new Client();
$client->authenticate(env('GITHUB_TOKEN'), null, Client::AUTH_ACCESS_TOKEN);
$username = env('GITHUB_USERNAME');
$repository = env('GITHUB_REPOSITORY');
$branch = 'main';
$dagPath = 'dags/' . $filename;
// Получение SHA последнего коммита
$reference = $client->api('gitData')->references()->show($username, $repository, 'heads/' . $branch);
$commitSha = $reference['object']['sha'];
// Создание нового блоба
$blob = $client->api('gitData')->blobs()->create($username, $repository, [
'content' => base64_encode($content),
'encoding' => 'base64',
]);
// Создание нового дерева
$tree = $client->api('gitData')->trees()->create($username, $repository, [
'base_tree' => $commitSha,
'tree' => [
[
'path' => $dagPath,
'mode' => '100644',
'type' => 'blob',
'sha' => $blob['sha'],
],
],
]);
// Создание нового коммита
$commit = $client->api('gitData')->commits()->create($username, $repository, [
'message' => 'Добавлен DAG ' . $filename,
'tree' => $tree['sha'],
'parents' => [$commitSha],
]);
// Обновление ссылки
$client->api('gitData')->references()->update($username, $repository, 'heads/' . $branch, [
'sha' => $commit['sha'],
]);
// Удаление временного файла
Storage::delete($path);
// Сохранение информации о DAG в базе данных
Auth::user()->dags()->create([
'filename' => $filename,
'commit_sha' => $commit['sha'],
]);
session()->flash('message', 'DAG успешно загружен и отправлен в репозиторий GitHub.');
// Обновление компонента списка DAG
$this->emit('dagUploaded');
}
public function render()
{
return view('livewire.upload-dag-component');
}
}
1.3. Шаблон компонента resources/views/livewire/upload-dag-component.blade.php
<div>
@if (session()->has('message'))
<div class="alert alert-success">
{{ session('message') }}
</div>
@endif
<form wire:submit.prevent="uploadDag" enctype="multipart/form-data">
<div class="form-group">
<label for="dagFile">Выберите DAG-файл (.py):</label>
<input type="file" wire:model="dagFile" id="dagFile" class="form-control">
@error('dagFile') <span class="text-danger">{{ $message }}</span> @enderror
</div>
<button type="submit" class="btn btn-primary mt-2">Загрузить DAG</button>
</form>
</div>
1.4. Обновление модели пользователя Добавьте связь между пользователем и DAG в модели User.
app/Models/User.php
public function dags()
{
return $this->hasMany(Dag::class);
}
- Компонент для отображения списка DAG-файлов 2.1. Создание компонента Создайте Livewire-компонент DagListComponent:
php artisan make:livewire DagListComponent
2.2. Код компонента app/Http/Livewire/DagListComponent.php
<?php
namespace App\Http\Livewire;
use Livewire\Component;
use Illuminate\Support\Facades\Auth;
class DagListComponent extends Component
{
protected $listeners = ['dagUploaded' => 'render'];
public function render()
{
$dags = Auth::user()->dags()->latest()->get();
return view('livewire.dag-list-component', [
'dags' => $dags,
]);
}
}
2.3. Шаблон компонента resources/views/livewire/dag-list-component.blade.php
<div>
<h3>Мои DAG-файлы</h3>
<table class="table">
<thead>
<tr>
<th>Имя файла</th>
<th>Дата загрузки</th>
</tr>
</thead>
<tbody>
@foreach($dags as $dag)
<tr>
<td>{{ $dag->filename }}</td>
<td>{{ $dag->created_at->format('d.m.Y H:i') }}</td>
</tr>
@endforeach
</tbody>
</table>
</div>
- Компонент для отображения статусов DAG из Airflow 3.1. Создание компонента Создайте Livewire-компонент DagStatusComponent:
php artisan make:livewire DagStatusComponent
3.2. Код компонента app/Http/Livewire/DagStatusComponent.php
<?php
namespace App\Http\Livewire;
use Livewire\Component;
use Illuminate\Support\Facades\Auth;
use Illuminate\Support\Facades\Http;
class DagStatusComponent extends Component
{
public $dagRuns = [];
public function mount()
{
$this->fetchDagStatuses();
}
public function fetchDagStatuses()
{
$airflowUrl = env('AIRFLOW_API_URL');
$username = env('AIRFLOW_USERNAME');
$password = env('AIRFLOW_PASSWORD');
$userDags = Auth::user()->dags()->pluck('filename')->toArray();
$dagIds = array_map(function($filename) {
return pathinfo($filename, PATHINFO_FILENAME);
}, $userDags);
$dagRuns = [];
foreach ($dagIds as $dagId) {
$response = Http::withBasicAuth($username, $password)
->get("$airflowUrl/api/v1/dags/$dagId/dagRuns");
if ($response->ok()) {
$dagRuns[$dagId] = $response->json()['dag_runs'];
} else {
$dagRuns[$dagId] = [];
}
}
$this->dagRuns = $dagRuns;
}
public function render()
{
return view('livewire.dag-status-component');
}
}
3.3. Шаблон компонента resources/views/livewire/dag-status-component.blade.php
<div wire:poll.60000ms="fetchDagStatuses">
<h3>Статусы выполнения DAG</h3>
@foreach($dagRuns as $dagId => $runs)
<h4>DAG ID: {{ $dagId }}</h4>
<table class="table">
<thead>
<tr>
<th>Run ID</th>
<th>Старт</th>
<th>Завершение</th>
<th>Статус</th>
</tr>
</thead>
<tbody>
@foreach($runs as $run)
<tr>
<td>{{ $run['dag_run_id'] }}</td>
<td>{{ $run['start_date'] }}</td>
<td>{{ $run['end_date'] }}</td>
<td>{{ $run['state'] }}</td>
</tr>
@endforeach
</tbody>
</table>
@endforeach
</div>
- Маршруты и отображение компонентов 4.1. Обновление маршрутов routes/web.php
Route::middleware(['auth:sanctum', 'verified'])->group(function () {
Route::get('/dashboard', function () {
return view('dashboard');
})->name('dashboard');
});
4.2. Обновление шаблона панели управления resources/views/dashboard.blade.php
@extends('layouts.app')
@section('content')
<div class="container">
<h2>Панель управления</h2>
@livewire('upload-dag-component')
@livewire('dag-list-component')
@livewire('dag-status-component')
</div>
@endsection
- Модель DAG 5.1. Создание модели и миграции Создайте модель Dag с миграцией:
php artisan make:model Dag -m
5.2. Обновление миграции database/migrations/xxxx_xx_xx_create_dags_table.php
public function up()
{
Schema::create('dags', function (Blueprint $table) {
$table->id();
$table->unsignedBigInteger('user_id');
$table->string('filename');
$table->string('commit_sha');
$table->timestamps();
$table->foreign('user_id')->references('id')->on('users')->onDelete('cascade');
});
}
5.3. Обновление модели DAG app/Models/Dag.php
<?php
namespace App\Models;
use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Database\Eloquent\Model;
class Dag extends Model
{
use HasFactory;
protected $fillable = [
'user_id',
'filename',
'commit_sha',
];
public function user()
{
return $this->belongsTo(User::class);
}
}
5.4. Миграция базы данных
php artisan migrate
- Настройка переменных окружения Добавьте следующие переменные в файл .env:
GITHUB_TOKEN=ваш_токен
GITHUB_USERNAME=ваш_логин
GITHUB_REPOSITORY=имя_репозитория
AIRFLOW_API_URL=http://airflow-server:8080
AIRFLOW_USERNAME=airflow_username
AIRFLOW_PASSWORD=airflow_password
- Добавление авторизации (опционально) Для контроля доступа к компонентам и функциям используйте встроенные возможности Laravel или пакет Spatie Laravel-Permission.
8.3. Уведомления Реализуйте систему уведомлений при изменении статусов DAG (например, через Laravel Notifications).
- Компонент UploadDagComponent Описание:
Этот компонент отвечает за загрузку DAG-файлов пользователями и их сохранение в GitHub репозитории через GitHub API.
Основные функции:
Форма для загрузки файлов. Валидация загружаемых файлов. Обработка загрузки и отправка файла в GitHub репозиторий. Сохранение информации о DAG в базе данных. Реализация:
Создание компонента:
php artisan make:livewire UploadDagComponent
Свойства компонента:
$file – для хранения загружаемого файла. $dagName – имя DAG (если требуется). Методы компонента:
rules() – для определения правил валидации:
protected $rules = [
'file' => 'required|file|mimes:py|max:1024', // Максимум 1MB
];
uploadDag() – основной метод для обработки загрузки:
Выполнить валидацию файла. Прочитать содержимое файла. Использовать GitHub API для загрузки файла в репозиторий (как описано в вашем основном коде). Сохранить информацию о DAG в базе данных, связав его с текущим пользователем (auth()->user()->id). Шаблон компонента (Blade):
Форма с полем для выбора файла:
<form wire:submit.prevent="uploadDag">
<input type="file" wire:model="file">
@error('file') <span class="error">{{ $message }}</span> @enderror
<button type="submit">Загрузить DAG</button>
</form>
Отображение сообщений об успехе или ошибках.
- Компонент DagListComponent Описание:
Этот компонент отображает список DAG-файлов, загруженных текущим пользователем.
Основные функции:
Вывод списка DAG с информацией о каждом файле. Возможность удаления или обновления DAG (опционально). Пагинация, если количество DAG большое. Реализация:
Создание компонента:
bash Копировать код php artisan make:livewire DagListComponent Свойства компонента:
$dags – коллекция DAG-файлов пользователя. Методы компонента:
mount() или render() – для загрузки списка DAG:
public function render()
{
$this->dags = Dag::where('user_id', auth()->id())->get();
return view('livewire.dag-list-component');
}
deleteDag($dagId) – метод для удаления DAG (если необходимо).
Шаблон компонента (Blade):
Таблица или список для отображения DAG:
<table>
<thead>
<tr>
<th>Имя файла</th>
<th>Дата загрузки</th>
<th>Действия</th>
</tr>
</thead>
<tbody>
@foreach($dags as $dag)
<tr>
<td>{{ $dag->filename }}</td>
<td>{{ $dag->created_at }}</td>
<td>
<button wire:click="deleteDag({{ $dag->id }})">Удалить</button>
</td>
</tr>
@endforeach
</tbody>
</table>
- Компонент DagStatusComponent Описание:
Отображает текущий статус выполнения DAG, получая данные из Airflow API.
Основные функции:
Получение статусов DAG из Airflow API. Обновление статусов в реальном времени. Отображение статусов в удобном формате. Реализация:
Создание компонента:
bash Копировать код php artisan make:livewire DagStatusComponent Свойства компонента:
$dagStatuses – массив статусов DAG. Методы компонента:
mount() – для инициализации данных.
getDagStatuses() – метод для обращения к Airflow API:
public function getDagStatuses()
{
$dags = Dag::where('user_id', auth()->id())->get();
foreach ($dags as $dag) {
$response = Http::withBasicAuth('airflow_username', 'airflow_password')
->get("http://airflow-server:8080/api/v1/dags/{$dag->dag_id}/dagRuns");
if ($response->successful()) {
$this->dagStatuses[$dag->dag_id] = $response->json();
}
}
}
Вы можете использовать wire:poll для автоматического обновления статусов:
<div wire:poll.5000ms="getDagStatuses">
<!-- отображение статусов -->
</div>
Шаблон компонента (Blade):
Отображение статусов DAG:
<ul>
@foreach($dagStatuses as $dagId => $status)
<li>DAG {{ $dagId }}: {{ $status['state'] }}</li>
@endforeach
</ul>
- Компонент DagQueueComponent Описание:
Отображает очередь задач DAG для текущего пользователя, используя данные из Airflow API.
Основные функции:
Получение информации о запланированных и выполняемых задачах. Обновление данных в реальном времени. Реализация:
Создание компонента:
bash Копировать код php artisan make:livewire DagQueueComponent Свойства компонента:
$dagQueue – массив задач в очереди. Методы компонента:
getDagQueue() – обращение к Airflow API для получения очереди задач:
public function getDagQueue()
{
$response = Http::withBasicAuth('airflow_username', 'airflow_password')
->get('http://airflow-server:8080/api/v1/queues');
if ($response->successful()) {
$this->dagQueue = $response->json();
}
}
Используйте wire:poll для обновления данных:
<div wire:poll.5000ms="getDagQueue">
<!-- отображение очереди -->
</div>
Шаблон компонента (Blade):
Отображение очереди задач:
<ul>
@foreach($dagQueue as $task)
@if(in_array($task['dag_id'], $userDagIds))
<li>Задача {{ $task['task_id'] }} в DAG {{ $task['dag_id'] }}</li>
@endif
@endforeach
</ul>
Здесь $userDagIds – массив dag_id текущего пользователя.
Общие рекомендации для компонентов Валидация и безопасность:
Всегда проверяйте права доступа, чтобы пользователи могли взаимодействовать только со своими данными. Используйте методы authorize() или проверки внутри методов компонентов. Обработка ошибок:
Обрабатывайте возможные исключения при работе с внешними API. Предоставляйте пользователям понятные сообщения об ошибках. Пользовательский интерфейс:
Делайте интерфейс интуитивно понятным и отзывчивым. Используйте стандартные компоненты UI или фреймворки CSS, такие как Tailwind CSS (который идет с Jetstream). Интеграция компонентов в приложение Маршруты и контроллеры:
Определите маршруты в web.php для страниц, где будут использоваться компоненты.
Route::middleware(['auth:sanctum', 'verified'])->get('/dashboard', function () {
return view('dashboard');
})->name('dashboard');
Шаблоны Blade:
Вставьте компоненты в соответствующие шаблоны.
<!-- resources/views/dashboard.blade.php -->
@extends('layouts.app')
@section('content')
<div class="container mx-auto">
<livewire:upload-dag-component />
<livewire:dag-list-component />
<livewire:dag-status-component />
<livewire:dag-queue-component />
</div>
@endsection
Дополнительные настройки Конфигурация Airflow API:
Убедитесь, что Airflow API доступен и настроен для приема запросов от вашего приложения.
Добавьте необходимые переменные в .env файл для хранения URL и данных аутентификации:
AIRFLOW_API_URL=http://airflow-server:8080/api/v1
AIRFLOW_API_USER=airflow_username
AIRFLOW_API_PASSWORD=airflow_password
Конфигурация GitHub API:
Обновите конфигурацию GitHub API, если требуется, и храните токен в .env файле:
GITHUB_TOKEN=ваш_токен
GITHUB_USERNAME=ваш_логин
GITHUB_REPOSITORY=имя_репозитория
GITHUB_BRANCH=main
Модели и миграции:
Создайте модель Dag и соответствующую миграцию:
bash Копировать код php artisan make:model Dag -m Поля таблицы dags могут включать:
id user_id dag_id или filename created_at updated_at Не забудьте установить связь между моделями User и Dag.
// В модели User
public function dags()
{
return $this->hasMany(Dag::class);
}
// В модели Dag
public function user()
{
return $this->belongsTo(User::class);
}
Заключение Следуя этим инструкциям, вы сможете создать полноценное приложение на Laravel Jetstream Livewire, которое позволит пользователям:
Загружать DAG-файлы без прямого доступа к GitHub репозиторию. Просматривать список своих DAG-файлов. Отслеживать статусы выполнения и очередь задач своих DAG в Airflow. Не забудьте протестировать каждую часть приложения и убедиться, что все компоненты работают корректно вместе.
Извиняюсь за недочет. Сейчас я опишу более конкретные шаги разработки приложения с финальным исходным кодом.
Полный пошаговый план разработки приложения с исходным кодом:
Шаг 1: Установка Laravel и Jetstream с Livewire
-
Создание нового проекта Laravel:
composer create-project laravel/laravel airflow-dag-manager
-
Установка Jetstream с Livewire:
composer require laravel/jetstream php artisan jetstream:install livewire npm install npm run dev php artisan migrate
-
Настройка аутентификации: Jetstream автоматически добавит базовые функции аутентификации.
Шаг 2: Настройка ролей и прав доступа
-
Установка пакета Spatie Laravel-Permission для управления ролями и правами доступа:
composer require spatie/laravel-permission
-
Публикация конфигурации и выполнение миграций:
php artisan vendor:publish --provider="Spatie\Permission\PermissionServiceProvider" php artisan migrate
-
Настройка ролей и прав: Добавьте роли, например,
admin
иuser
, а также права, такие какupload dag
,view status
. Пример настройки ролей можно добавить в seeder:use Spatie\Permission\Models\Role; use Spatie\Permission\Models\Permission; // В seeder: Role::create(['name' => 'admin']); Role::create(['name' => 'user']); Permission::create(['name' => 'upload dag']); Permission::create(['name' => 'view status']);
Шаг 3: Интеграция с GitHub API
-
Создание GitHub Personal Access Token: Перейдите в GitHub, создайте новый токен с правами
repo
для доступа к репозиторию. Сохраните его в.env
:GITHUB_TOKEN=ваш_токен GITHUB_USERNAME=ваш_логин GITHUB_REPOSITORY=имя_репозитория GITHUB_BRANCH=main
-
Установка библиотеки для работы с GitHub API:
composer require knplabs/github-api
-
Создание метода для загрузки DAG в репозиторий:
Создайте компонент UploadDagComponent для загрузки DAG:
php artisan make:livewire UploadDagComponent
Код компонента UploadDagComponent:
<?php namespace App\Http\Livewire; use Livewire\Component; use Livewire\WithFileUploads; use Github\Client; use Illuminate\Support\Facades\Storage; class UploadDagComponent extends Component { use WithFileUploads; public $dagFile; protected $rules = [ 'dagFile' => 'required|file|mimes:py|max:1024', ]; public function uploadDag() { $this->validate(); // Сохранение временного файла $path = $this->dagFile->store('temp_dags'); // Получение содержимого файла $filename = $this->dagFile->getClientOriginalName(); $content = Storage::get($path); // Интеграция с GitHub API $client = new Client(); $client->authenticate(env('GITHUB_TOKEN'), null, Client::AUTH_ACCESS_TOKEN); $username = env('GITHUB_USERNAME'); $repository = env('GITHUB_REPOSITORY'); $branch = env('GITHUB_BRANCH'); $dagPath = 'dags/' . $filename; // Получение SHA последнего коммита $reference = $client->api('gitData')->references()->show($username, $repository, 'heads/' . $branch); $commitSha = $reference['object']['sha']; // Создание нового блоба $blob = $client->api('gitData')->blobs()->create($username, $repository, [ 'content' => base64_encode($content), 'encoding' => 'base64', ]); // Создание нового дерева $tree = $client->api('gitData')->trees()->create($username, $repository, [ 'base_tree' => $commitSha, 'tree' => [ [ 'path' => $dagPath, 'mode' => '100644', 'type' => 'blob', 'sha' => $blob['sha'], ], ], ]); // Создание нового коммита $commit = $client->api('gitData')->commits()->create($username, $repository, [ 'message' => 'Добавлен DAG ' . $filename, 'tree' => $tree['sha'], 'parents' => [$commitSha], ]); // Обновление ссылки $client->api('gitData')->references()->update($username, $repository, 'heads/' . $branch, [ 'sha' => $commit['sha'], ]); // Удаление временного файла Storage::delete($path); // Сообщение об успехе session()->flash('message', 'DAG успешно загружен и отправлен в репозиторий GitHub.'); } public function render() { return view('livewire.upload-dag-component'); } }
-
Шаблон компонента (Blade):
<div> @if (session()->has('message')) <div class="alert alert-success"> {{ session('message') }} </div> @endif <form wire:submit.prevent="uploadDag"> <input type="file" wire:model="dagFile"> @error('dagFile') <span class="text-danger">{{ $message }}</span> @enderror <button type="submit" class="btn btn-primary mt-2">Загрузить DAG</button> </form> </div>
Шаг 4: Синхронизация DAG с Airflow
- Настройка Airflow для получения DAG:
Вы можете настроить Airflow для автоматического выполнения
git pull
либо использовать GitHub Actions для деплоя DAG на сервер Airflow.
Шаг 5: Получение статусов выполнения DAG через Airflow API
-
Включение Airflow API: В
airflow.cfg
добавьте или активируйте следующие строки:[api] auth_backend = airflow.api.auth.backend.basic_auth
-
Запросы к Airflow API для получения статусов DAG:
Создайте компонент DagStatusComponent:
php artisan make:livewire DagStatusComponent
Код компонента DagStatusComponent:
<?php namespace App\Http\Livewire; use Livewire\Component; use Illuminate\Support\Facades\Http; class DagStatusComponent extends Component { public $dagRuns = []; public function mount() { $this->fetchDagStatuses(); } public function fetchDagStatuses() { $response = Http::withBasicAuth(env('AIRFLOW_USERNAME'), env('AIRFLOW_PASSWORD')) ->get(env('AIRFLOW_API_URL') . '/api/v1/dags/{dag_id}/dagRuns'); if ($response->ok()) { $this->dagRuns = $response->json(); } } public function render() { return view('livewire.dag-status-component'); } }
-
Шаблон компонента (Blade):
<div wire:poll.60000ms="fetchDagStatuses"> <h3>Статусы выполнения DAG</h3> <table class="table"> <thead> <tr> <th>DAG Run ID</th> <th>Старт</th> <th>Завершение</th> <th>Статус</th> </tr> </thead> <tbody> @foreach($dagRuns as $run) <tr> <td>{{ $run['dag_run_id'] }}</td> <td>{{ $run['start_date'] }}</td> <td>{{ $run['end_date'] }}</td> <td>{{ $run['state'] }}</td> </tr> @endforeach </tbody> </table> </div>