Skip to content

Commit

Permalink
AIP84: UI endpoint for config (apache#44265)
Browse files Browse the repository at this point in the history
* AIP84:UI endpoint for config

* remove show_trigger_form_if_no_params

* flatten the dict
  • Loading branch information
vatsrahul1001 authored Nov 22, 2024
1 parent 00fd540 commit 4f8cb6e
Show file tree
Hide file tree
Showing 12 changed files with 939 additions and 369 deletions.
44 changes: 44 additions & 0 deletions airflow/api_fastapi/core_api/datamodels/ui/config.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
# Licensed to the Apache Software Foundation (ASF) under one
# or more contributor license agreements. See the NOTICE file
# distributed with this work for additional information
# regarding copyright ownership. The ASF licenses this file
# to you under the Apache License, Version 2.0 (the
# "License"); you may not use this file except in compliance
# with the License. You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing,
# software distributed under the License is distributed on an
# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
# KIND, either express or implied. See the License for the
# specific language governing permissions and limitations
# under the License.
from __future__ import annotations

from pydantic import BaseModel


class ConfigResponse(BaseModel):
"""configuration serializer."""

navbar_color: str
navbar_text_color: str
navbar_hover_color: str
navbar_text_hover_color: str
navbar_logo_text_color: str
page_size: int
auto_refresh_interval: int
default_ui_timezone: str
hide_paused_dags_by_default: bool
instance_name: str
instance_name_has_markup: bool
enable_swagger_ui: bool
require_confirmation_dag_change: bool
default_wrap: bool
warn_deployment_exposure: bool
audit_view_excluded_events: str
audit_view_included_events: str
is_k8s: bool
test_connection: str
state_color_mapping: dict
106 changes: 106 additions & 0 deletions airflow/api_fastapi/core_api/openapi/v1-generated.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -174,6 +174,26 @@ paths:
application/json:
schema:
$ref: '#/components/schemas/HTTPValidationError'
/ui/config:
get:
tags:
- Config
summary: Get Configs
description: Get configs for UI.
operationId: get_configs
responses:
'200':
description: Successful Response
content:
application/json:
schema:
$ref: '#/components/schemas/ConfigResponse'
'404':
description: Not Found
content:
application/json:
schema:
$ref: '#/components/schemas/HTTPExceptionResponse'
/public/assets:
get:
tags:
Expand Down Expand Up @@ -5268,6 +5288,92 @@ components:
- value
title: ConfigOption
description: Config option.
ConfigResponse:
properties:
navbar_color:
type: string
title: Navbar Color
navbar_text_color:
type: string
title: Navbar Text Color
navbar_hover_color:
type: string
title: Navbar Hover Color
navbar_text_hover_color:
type: string
title: Navbar Text Hover Color
navbar_logo_text_color:
type: string
title: Navbar Logo Text Color
page_size:
type: integer
title: Page Size
auto_refresh_interval:
type: integer
title: Auto Refresh Interval
default_ui_timezone:
type: string
title: Default Ui Timezone
hide_paused_dags_by_default:
type: boolean
title: Hide Paused Dags By Default
instance_name:
type: string
title: Instance Name
instance_name_has_markup:
type: boolean
title: Instance Name Has Markup
enable_swagger_ui:
type: boolean
title: Enable Swagger Ui
require_confirmation_dag_change:
type: boolean
title: Require Confirmation Dag Change
default_wrap:
type: boolean
title: Default Wrap
warn_deployment_exposure:
type: boolean
title: Warn Deployment Exposure
audit_view_excluded_events:
type: string
title: Audit View Excluded Events
audit_view_included_events:
type: string
title: Audit View Included Events
is_k8s:
type: boolean
title: Is K8S
test_connection:
type: string
title: Test Connection
state_color_mapping:
type: object
title: State Color Mapping
type: object
required:
- navbar_color
- navbar_text_color
- navbar_hover_color
- navbar_text_hover_color
- navbar_logo_text_color
- page_size
- auto_refresh_interval
- default_ui_timezone
- hide_paused_dags_by_default
- instance_name
- instance_name_has_markup
- enable_swagger_ui
- require_confirmation_dag_change
- default_wrap
- warn_deployment_exposure
- audit_view_excluded_events
- audit_view_included_events
- is_k8s
- test_connection
- state_color_mapping
title: ConfigResponse
description: configuration serializer.
ConfigSection:
properties:
name:
Expand Down
2 changes: 2 additions & 0 deletions airflow/api_fastapi/core_api/routes/ui/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@

from airflow.api_fastapi.common.router import AirflowRouter
from airflow.api_fastapi.core_api.routes.ui.assets import assets_router
from airflow.api_fastapi.core_api.routes.ui.config import config_router
from airflow.api_fastapi.core_api.routes.ui.dags import dags_router
from airflow.api_fastapi.core_api.routes.ui.dashboard import dashboard_router

Expand All @@ -26,3 +27,4 @@
ui_router.include_router(assets_router)
ui_router.include_router(dashboard_router)
ui_router.include_router(dags_router)
ui_router.include_router(config_router)
71 changes: 71 additions & 0 deletions airflow/api_fastapi/core_api/routes/ui/config.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,71 @@
# Licensed to the Apache Software Foundation (ASF) under one
# or more contributor license agreements. See the NOTICE file
# distributed with this work for additional information
# regarding copyright ownership. The ASF licenses this file
# to you under the Apache License, Version 2.0 (the
# "License"); you may not use this file except in compliance
# with the License. You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing,
# software distributed under the License is distributed on an
# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
# KIND, either express or implied. See the License for the
# specific language governing permissions and limitations
# under the License.
from __future__ import annotations

from typing import Any

from fastapi import status

from airflow.api_fastapi.common.router import AirflowRouter
from airflow.api_fastapi.core_api.datamodels.ui.config import ConfigResponse
from airflow.api_fastapi.core_api.openapi.exceptions import create_openapi_http_exception_doc
from airflow.configuration import conf
from airflow.settings import IS_K8S_OR_K8SCELERY_EXECUTOR, STATE_COLORS

config_router = AirflowRouter(tags=["Config"])

WEBSERVER_CONFIG_KEYS = [
"navbar_color",
"page_size",
"auto_refresh_interval",
"default_ui_timezone",
"hide_paused_dags_by_default",
"warn_deployment_exposure",
"default_wrap",
"require_confirmation_dag_change",
"enable_swagger_ui",
"instance_name_has_markup",
"navbar_text_color",
"navbar_hover_color",
"navbar_text_hover_color",
"navbar_logo_text_color",
]


@config_router.get(
"/config",
include_in_schema=False,
responses=create_openapi_http_exception_doc([status.HTTP_404_NOT_FOUND]),
)
def get_configs() -> ConfigResponse:
"""Get configs for UI."""
conf_dict = conf.as_dict()

config = {key: conf_dict["webserver"].get(key) for key in WEBSERVER_CONFIG_KEYS}

additional_config: dict[str, Any] = {
"instance_name": conf.get("webserver", "instance_name", fallback="Airflow"),
"audit_view_included_events": conf.get("webserver", "audit_view_included_events", fallback=""),
"audit_view_excluded_events": conf.get("webserver", "audit_view_excluded_events", fallback=""),
"test_connection": conf.get("core", "test_connection", fallback="Disabled"),
"state_color_mapping": STATE_COLORS,
"is_k8s": IS_K8S_OR_K8SCELERY_EXECUTOR,
}

config.update({key: value for key, value in additional_config.items()})

return ConfigResponse.model_validate(config)
94 changes: 53 additions & 41 deletions airflow/ui/openapi-gen/queries/common.ts
Original file line number Diff line number Diff line change
Expand Up @@ -270,6 +270,59 @@ export const UseDagsServiceRecentDagRunsKeyFn = (
},
]),
];
export type ConfigServiceGetConfigsDefaultResponse = Awaited<
ReturnType<typeof ConfigService.getConfigs>
>;
export type ConfigServiceGetConfigsQueryResult<
TData = ConfigServiceGetConfigsDefaultResponse,
TError = unknown,
> = UseQueryResult<TData, TError>;
export const useConfigServiceGetConfigsKey = "ConfigServiceGetConfigs";
export const UseConfigServiceGetConfigsKeyFn = (queryKey?: Array<unknown>) => [
useConfigServiceGetConfigsKey,
...(queryKey ?? []),
];
export type ConfigServiceGetConfigDefaultResponse = Awaited<
ReturnType<typeof ConfigService.getConfig>
>;
export type ConfigServiceGetConfigQueryResult<
TData = ConfigServiceGetConfigDefaultResponse,
TError = unknown,
> = UseQueryResult<TData, TError>;
export const useConfigServiceGetConfigKey = "ConfigServiceGetConfig";
export const UseConfigServiceGetConfigKeyFn = (
{
accept,
section,
}: {
accept?: "application/json" | "text/plain" | "*/*";
section?: string;
} = {},
queryKey?: Array<unknown>,
) => [useConfigServiceGetConfigKey, ...(queryKey ?? [{ accept, section }])];
export type ConfigServiceGetConfigValueDefaultResponse = Awaited<
ReturnType<typeof ConfigService.getConfigValue>
>;
export type ConfigServiceGetConfigValueQueryResult<
TData = ConfigServiceGetConfigValueDefaultResponse,
TError = unknown,
> = UseQueryResult<TData, TError>;
export const useConfigServiceGetConfigValueKey = "ConfigServiceGetConfigValue";
export const UseConfigServiceGetConfigValueKeyFn = (
{
accept,
option,
section,
}: {
accept?: "application/json" | "text/plain" | "*/*";
option: string;
section: string;
},
queryKey?: Array<unknown>,
) => [
useConfigServiceGetConfigValueKey,
...(queryKey ?? [{ accept, option, section }]),
];
export type BackfillServiceListBackfillsDefaultResponse = Awaited<
ReturnType<typeof BackfillService.listBackfills>
>;
Expand Down Expand Up @@ -495,47 +548,6 @@ export const UseDagStatsServiceGetDagStatsKeyFn = (
} = {},
queryKey?: Array<unknown>,
) => [useDagStatsServiceGetDagStatsKey, ...(queryKey ?? [{ dagIds }])];
export type ConfigServiceGetConfigDefaultResponse = Awaited<
ReturnType<typeof ConfigService.getConfig>
>;
export type ConfigServiceGetConfigQueryResult<
TData = ConfigServiceGetConfigDefaultResponse,
TError = unknown,
> = UseQueryResult<TData, TError>;
export const useConfigServiceGetConfigKey = "ConfigServiceGetConfig";
export const UseConfigServiceGetConfigKeyFn = (
{
accept,
section,
}: {
accept?: "application/json" | "text/plain" | "*/*";
section?: string;
} = {},
queryKey?: Array<unknown>,
) => [useConfigServiceGetConfigKey, ...(queryKey ?? [{ accept, section }])];
export type ConfigServiceGetConfigValueDefaultResponse = Awaited<
ReturnType<typeof ConfigService.getConfigValue>
>;
export type ConfigServiceGetConfigValueQueryResult<
TData = ConfigServiceGetConfigValueDefaultResponse,
TError = unknown,
> = UseQueryResult<TData, TError>;
export const useConfigServiceGetConfigValueKey = "ConfigServiceGetConfigValue";
export const UseConfigServiceGetConfigValueKeyFn = (
{
accept,
option,
section,
}: {
accept?: "application/json" | "text/plain" | "*/*";
option: string;
section: string;
},
queryKey?: Array<unknown>,
) => [
useConfigServiceGetConfigValueKey,
...(queryKey ?? [{ accept, option, section }]),
];
export type DagWarningServiceListDagWarningsDefaultResponse = Awaited<
ReturnType<typeof DagWarningService.listDagWarnings>
>;
Expand Down
Loading

0 comments on commit 4f8cb6e

Please sign in to comment.