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()

Reply via email to