This is an automated email from the ASF dual-hosted git repository.
bbovenzi pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/airflow.git
The following commit(s) were added to refs/heads/main by this push:
new 27f3be666c Migrate public endpoint Get Airflow Version to FastAPI
(#43312)
27f3be666c is described below
commit 27f3be666cb3aed6668e509ef1a9a84782eacb5d
Author: Omkar P <[email protected]>
AuthorDate: Thu Oct 24 19:25:15 2024 +0530
Migrate public endpoint Get Airflow Version to FastAPI (#43312)
* Migrate public endpoint Get Airflow Version to FastAPI
* Run static checks
---
.../api_fastapi/core_api/openapi/v1-generated.yaml | 30 +++++++++++++
.../api_fastapi/core_api/routes/public/__init__.py | 2 +
.../api_fastapi/core_api/routes/public/version.py | 34 +++++++++++++++
.../api_fastapi/core_api/serializers/version.py | 26 +++++++++++
airflow/ui/openapi-gen/queries/common.ts | 13 ++++++
airflow/ui/openapi-gen/queries/prefetch.ts | 12 +++++
airflow/ui/openapi-gen/queries/queries.ts | 20 +++++++++
airflow/ui/openapi-gen/queries/suspense.ts | 20 +++++++++
airflow/ui/openapi-gen/requests/schemas.gen.ts | 24 ++++++++++
airflow/ui/openapi-gen/requests/services.gen.ts | 16 +++++++
airflow/ui/openapi-gen/requests/types.gen.ts | 20 +++++++++
.../core_api/routes/public/test_version.py | 51 ++++++++++++++++++++++
12 files changed, 268 insertions(+)
diff --git a/airflow/api_fastapi/core_api/openapi/v1-generated.yaml
b/airflow/api_fastapi/core_api/openapi/v1-generated.yaml
index 5eb7aed770..3a3afbab95 100644
--- a/airflow/api_fastapi/core_api/openapi/v1-generated.yaml
+++ b/airflow/api_fastapi/core_api/openapi/v1-generated.yaml
@@ -1358,6 +1358,20 @@ paths:
application/json:
schema:
$ref: '#/components/schemas/HTTPValidationError'
+ /public/version/:
+ get:
+ tags:
+ - Version
+ summary: Get Version
+ description: Get version information.
+ operationId: get_version
+ responses:
+ '200':
+ description: Successful Response
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/VersionInfo'
components:
schemas:
AppBuilderMenuItemResponse:
@@ -2574,3 +2588,19 @@ components:
- value
title: VariableResponse
description: Variable serializer for responses.
+ VersionInfo:
+ properties:
+ version:
+ type: string
+ title: Version
+ git_version:
+ anyOf:
+ - type: string
+ - type: 'null'
+ title: Git Version
+ type: object
+ required:
+ - version
+ - git_version
+ title: VersionInfo
+ description: Version information serializer for responses.
diff --git a/airflow/api_fastapi/core_api/routes/public/__init__.py
b/airflow/api_fastapi/core_api/routes/public/__init__.py
index 89d216e438..ab307409ad 100644
--- a/airflow/api_fastapi/core_api/routes/public/__init__.py
+++ b/airflow/api_fastapi/core_api/routes/public/__init__.py
@@ -26,6 +26,7 @@ from airflow.api_fastapi.core_api.routes.public.plugins
import plugins_router
from airflow.api_fastapi.core_api.routes.public.pools import pools_router
from airflow.api_fastapi.core_api.routes.public.providers import
providers_router
from airflow.api_fastapi.core_api.routes.public.variables import
variables_router
+from airflow.api_fastapi.core_api.routes.public.version import version_router
public_router = AirflowRouter(prefix="/public")
@@ -38,3 +39,4 @@ public_router.include_router(monitor_router)
public_router.include_router(pools_router)
public_router.include_router(providers_router)
public_router.include_router(plugins_router)
+public_router.include_router(version_router)
diff --git a/airflow/api_fastapi/core_api/routes/public/version.py
b/airflow/api_fastapi/core_api/routes/public/version.py
new file mode 100644
index 0000000000..218e0b9070
--- /dev/null
+++ b/airflow/api_fastapi/core_api/routes/public/version.py
@@ -0,0 +1,34 @@
+# 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
+
+import airflow
+from airflow.api_fastapi.common.router import AirflowRouter
+from airflow.api_fastapi.core_api.serializers.version import VersionInfo
+from airflow.utils.platform import get_airflow_git_version
+
+version_router = AirflowRouter(tags=["Version"], prefix="/version")
+
+
+@version_router.get("/")
+async def get_version() -> VersionInfo:
+ """Get version information."""
+ airflow_version = airflow.__version__
+ git_version = get_airflow_git_version()
+ version_info = VersionInfo(version=airflow_version,
git_version=git_version)
+ return VersionInfo.model_validate(version_info)
diff --git a/airflow/api_fastapi/core_api/serializers/version.py
b/airflow/api_fastapi/core_api/serializers/version.py
new file mode 100644
index 0000000000..01c4c45376
--- /dev/null
+++ b/airflow/api_fastapi/core_api/serializers/version.py
@@ -0,0 +1,26 @@
+# 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 VersionInfo(BaseModel):
+ """Version information serializer for responses."""
+
+ version: str
+ git_version: str | None
diff --git a/airflow/ui/openapi-gen/queries/common.ts
b/airflow/ui/openapi-gen/queries/common.ts
index c621a3fdb5..b5e730822f 100644
--- a/airflow/ui/openapi-gen/queries/common.ts
+++ b/airflow/ui/openapi-gen/queries/common.ts
@@ -12,6 +12,7 @@ import {
PoolService,
ProviderService,
VariableService,
+ VersionService,
} from "../requests/services.gen";
import { DagRunState } from "../requests/types.gen";
@@ -345,6 +346,18 @@ export const UsePluginServiceGetPluginsKeyFn = (
} = {},
queryKey?: Array<unknown>,
) => [usePluginServiceGetPluginsKey, ...(queryKey ?? [{ limit, offset }])];
+export type VersionServiceGetVersionDefaultResponse = Awaited<
+ ReturnType<typeof VersionService.getVersion>
+>;
+export type VersionServiceGetVersionQueryResult<
+ TData = VersionServiceGetVersionDefaultResponse,
+ TError = unknown,
+> = UseQueryResult<TData, TError>;
+export const useVersionServiceGetVersionKey = "VersionServiceGetVersion";
+export const UseVersionServiceGetVersionKeyFn = (queryKey?: Array<unknown>) =>
[
+ useVersionServiceGetVersionKey,
+ ...(queryKey ?? []),
+];
export type VariableServicePostVariableMutationResult = Awaited<
ReturnType<typeof VariableService.postVariable>
>;
diff --git a/airflow/ui/openapi-gen/queries/prefetch.ts
b/airflow/ui/openapi-gen/queries/prefetch.ts
index 36a6c251cb..3f681a4a13 100644
--- a/airflow/ui/openapi-gen/queries/prefetch.ts
+++ b/airflow/ui/openapi-gen/queries/prefetch.ts
@@ -12,6 +12,7 @@ import {
PoolService,
ProviderService,
VariableService,
+ VersionService,
} from "../requests/services.gen";
import { DagRunState } from "../requests/types.gen";
import * as Common from "./common";
@@ -429,3 +430,14 @@ export const prefetchUsePluginServiceGetPlugins = (
queryKey: Common.UsePluginServiceGetPluginsKeyFn({ limit, offset }),
queryFn: () => PluginService.getPlugins({ limit, offset }),
});
+/**
+ * Get Version
+ * Get version information.
+ * @returns VersionInfo Successful Response
+ * @throws ApiError
+ */
+export const prefetchUseVersionServiceGetVersion = (queryClient: QueryClient)
=>
+ queryClient.prefetchQuery({
+ queryKey: Common.UseVersionServiceGetVersionKeyFn(),
+ queryFn: () => VersionService.getVersion(),
+ });
diff --git a/airflow/ui/openapi-gen/queries/queries.ts
b/airflow/ui/openapi-gen/queries/queries.ts
index 7141ac0001..31d9e94d61 100644
--- a/airflow/ui/openapi-gen/queries/queries.ts
+++ b/airflow/ui/openapi-gen/queries/queries.ts
@@ -17,6 +17,7 @@ import {
PoolService,
ProviderService,
VariableService,
+ VersionService,
} from "../requests/services.gen";
import {
DAGPatchBody,
@@ -562,6 +563,25 @@ export const usePluginServiceGetPlugins = <
queryFn: () => PluginService.getPlugins({ limit, offset }) as TData,
...options,
});
+/**
+ * Get Version
+ * Get version information.
+ * @returns VersionInfo Successful Response
+ * @throws ApiError
+ */
+export const useVersionServiceGetVersion = <
+ TData = Common.VersionServiceGetVersionDefaultResponse,
+ TError = unknown,
+ TQueryKey extends Array<unknown> = unknown[],
+>(
+ queryKey?: TQueryKey,
+ options?: Omit<UseQueryOptions<TData, TError>, "queryKey" | "queryFn">,
+) =>
+ useQuery<TData, TError>({
+ queryKey: Common.UseVersionServiceGetVersionKeyFn(queryKey),
+ queryFn: () => VersionService.getVersion() as TData,
+ ...options,
+ });
/**
* Post Variable
* Create a variable.
diff --git a/airflow/ui/openapi-gen/queries/suspense.ts
b/airflow/ui/openapi-gen/queries/suspense.ts
index 8fd858a985..eb91e8f1ba 100644
--- a/airflow/ui/openapi-gen/queries/suspense.ts
+++ b/airflow/ui/openapi-gen/queries/suspense.ts
@@ -12,6 +12,7 @@ import {
PoolService,
ProviderService,
VariableService,
+ VersionService,
} from "../requests/services.gen";
import { DagRunState } from "../requests/types.gen";
import * as Common from "./common";
@@ -552,3 +553,22 @@ export const usePluginServiceGetPluginsSuspense = <
queryFn: () => PluginService.getPlugins({ limit, offset }) as TData,
...options,
});
+/**
+ * Get Version
+ * Get version information.
+ * @returns VersionInfo Successful Response
+ * @throws ApiError
+ */
+export const useVersionServiceGetVersionSuspense = <
+ TData = Common.VersionServiceGetVersionDefaultResponse,
+ TError = unknown,
+ TQueryKey extends Array<unknown> = unknown[],
+>(
+ queryKey?: TQueryKey,
+ options?: Omit<UseQueryOptions<TData, TError>, "queryKey" | "queryFn">,
+) =>
+ useSuspenseQuery<TData, TError>({
+ queryKey: Common.UseVersionServiceGetVersionKeyFn(queryKey),
+ queryFn: () => VersionService.getVersion() as TData,
+ ...options,
+ });
diff --git a/airflow/ui/openapi-gen/requests/schemas.gen.ts
b/airflow/ui/openapi-gen/requests/schemas.gen.ts
index afd16d8040..2f3eb390b4 100644
--- a/airflow/ui/openapi-gen/requests/schemas.gen.ts
+++ b/airflow/ui/openapi-gen/requests/schemas.gen.ts
@@ -1856,3 +1856,27 @@ export const $VariableResponse = {
title: "VariableResponse",
description: "Variable serializer for responses.",
} as const;
+
+export const $VersionInfo = {
+ properties: {
+ version: {
+ type: "string",
+ title: "Version",
+ },
+ git_version: {
+ anyOf: [
+ {
+ type: "string",
+ },
+ {
+ type: "null",
+ },
+ ],
+ title: "Git Version",
+ },
+ },
+ type: "object",
+ required: ["version", "git_version"],
+ title: "VersionInfo",
+ description: "Version information serializer for responses.",
+} as const;
diff --git a/airflow/ui/openapi-gen/requests/services.gen.ts
b/airflow/ui/openapi-gen/requests/services.gen.ts
index c4b0c987c4..b9d9f52655 100644
--- a/airflow/ui/openapi-gen/requests/services.gen.ts
+++ b/airflow/ui/openapi-gen/requests/services.gen.ts
@@ -54,6 +54,7 @@ import type {
GetProvidersResponse,
GetPluginsData,
GetPluginsResponse,
+ GetVersionResponse,
} from "./types.gen";
export class AssetService {
@@ -807,3 +808,18 @@ export class PluginService {
});
}
}
+
+export class VersionService {
+ /**
+ * Get Version
+ * Get version information.
+ * @returns VersionInfo Successful Response
+ * @throws ApiError
+ */
+ public static getVersion(): CancelablePromise<GetVersionResponse> {
+ return __request(OpenAPI, {
+ method: "GET",
+ url: "/public/version/",
+ });
+ }
+}
diff --git a/airflow/ui/openapi-gen/requests/types.gen.ts
b/airflow/ui/openapi-gen/requests/types.gen.ts
index aef0f76f28..66f4437cec 100644
--- a/airflow/ui/openapi-gen/requests/types.gen.ts
+++ b/airflow/ui/openapi-gen/requests/types.gen.ts
@@ -441,6 +441,14 @@ export type VariableResponse = {
value: string | null;
};
+/**
+ * Version information serializer for responses.
+ */
+export type VersionInfo = {
+ version: string;
+ git_version: string | null;
+};
+
export type NextRunAssetsData = {
dagId: string;
};
@@ -633,6 +641,8 @@ export type GetPluginsData = {
export type GetPluginsResponse = PluginCollectionResponse;
+export type GetVersionResponse = VersionInfo;
+
export type $OpenApiTs = {
"/ui/next_run_assets/{dag_id}": {
get: {
@@ -1269,4 +1279,14 @@ export type $OpenApiTs = {
};
};
};
+ "/public/version/": {
+ get: {
+ res: {
+ /**
+ * Successful Response
+ */
+ 200: VersionInfo;
+ };
+ };
+ };
};
diff --git a/tests/api_fastapi/core_api/routes/public/test_version.py
b/tests/api_fastapi/core_api/routes/public/test_version.py
new file mode 100644
index 0000000000..2000b03ccb
--- /dev/null
+++ b/tests/api_fastapi/core_api/routes/public/test_version.py
@@ -0,0 +1,51 @@
+# 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 unittest import mock
+
+import pytest
+
+from tests_common.test_utils.db import clear_db_jobs
+
+pytestmark = [pytest.mark.db_test, pytest.mark.skip_if_database_isolation_mode]
+
+
+class TestVersionEndpoint:
+ @pytest.fixture(autouse=True)
+ def setup(self) -> None:
+ clear_db_jobs()
+
+ def teardown_method(self):
+ clear_db_jobs()
+
+
+class TestGetVersion(TestVersionEndpoint):
+ @mock.patch(
+
"airflow.api_fastapi.core_api.routes.public.version.airflow.__version__",
+ "MOCK_VERSION",
+ )
+ @mock.patch(
+
"airflow.api_fastapi.core_api.routes.public.version.get_airflow_git_version",
+ return_value="GIT_COMMIT",
+ )
+ def test_airflow_version_info(self, mock_get_airflow_get_commit, client):
+ response = client().get("/public/version")
+
+ assert 200 == response.status_code
+ assert {"git_version": "GIT_COMMIT", "version": "MOCK_VERSION"} ==
response.json()
+ mock_get_airflow_get_commit.assert_called_once_with()