Skip to content

Commit

Permalink
Add variable key search support (apache#44794)
Browse files Browse the repository at this point in the history
* add primary search

* added tests

* fix tests

* fix test
  • Loading branch information
shubhamraj-git authored Dec 10, 2024
1 parent 5079f7d commit ddae5a5
Show file tree
Hide file tree
Showing 10 changed files with 111 additions and 16 deletions.
6 changes: 6 additions & 0 deletions airflow/api_fastapi/common/parameters.py
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,7 @@
from airflow.models.dag import DagModel, DagTag
from airflow.models.dagrun import DagRun
from airflow.models.taskinstance import TaskInstance
from airflow.models.variable import Variable
from airflow.typing_compat import Self
from airflow.utils import timezone
from airflow.utils.state import DagRunState, TaskInstanceState
Expand Down Expand Up @@ -583,3 +584,8 @@ def _transform_ti_states(states: list[str] | None) -> list[TaskInstanceState | N
QueryAssetDagIdPatternSearch = Annotated[
_DagIdAssetReferenceFilter, Depends(_DagIdAssetReferenceFilter().depends)
]

# Variables
QueryVariableKeyPatternSearch = Annotated[
_SearchParam, Depends(search_param_factory(Variable.key, "variable_key_pattern"))
]
8 changes: 8 additions & 0 deletions airflow/api_fastapi/core_api/openapi/v1-generated.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -5549,6 +5549,14 @@ paths:
type: string
default: id
title: Order By
- name: variable_key_pattern
in: query
required: false
schema:
anyOf:
- type: string
- type: 'null'
title: Variable Key Pattern
responses:
'200':
description: Successful Response
Expand Down
9 changes: 8 additions & 1 deletion airflow/api_fastapi/core_api/routes/public/variables.py
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,12 @@
from sqlalchemy import select

from airflow.api_fastapi.common.db.common import SessionDep, paginated_select
from airflow.api_fastapi.common.parameters import QueryLimit, QueryOffset, SortParam
from airflow.api_fastapi.common.parameters import (
QueryLimit,
QueryOffset,
QueryVariableKeyPatternSearch,
SortParam,
)
from airflow.api_fastapi.common.router import AirflowRouter
from airflow.api_fastapi.core_api.datamodels.variables import (
VariableBody,
Expand Down Expand Up @@ -86,10 +91,12 @@ def get_variables(
),
],
session: SessionDep,
varaible_key_pattern: QueryVariableKeyPatternSearch,
) -> VariableCollectionResponse:
"""Get all Variables entries."""
variable_select, total_entries = paginated_select(
statement=select(Variable),
filters=[varaible_key_pattern],
order_by=order_by,
offset=offset,
limit=limit,
Expand Down
4 changes: 3 additions & 1 deletion airflow/ui/openapi-gen/queries/common.ts
Original file line number Diff line number Diff line change
Expand Up @@ -1597,15 +1597,17 @@ export const UseVariableServiceGetVariablesKeyFn = (
limit,
offset,
orderBy,
variableKeyPattern,
}: {
limit?: number;
offset?: number;
orderBy?: string;
variableKeyPattern?: string;
} = {},
queryKey?: Array<unknown>,
) => [
useVariableServiceGetVariablesKey,
...(queryKey ?? [{ limit, offset, orderBy }]),
...(queryKey ?? [{ limit, offset, orderBy, variableKeyPattern }]),
];
export type MonitorServiceGetHealthDefaultResponse = Awaited<
ReturnType<typeof MonitorService.getHealth>
Expand Down
12 changes: 11 additions & 1 deletion airflow/ui/openapi-gen/queries/prefetch.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2183,6 +2183,7 @@ export const prefetchUseVariableServiceGetVariable = (
* @param data.limit
* @param data.offset
* @param data.orderBy
* @param data.variableKeyPattern
* @returns VariableCollectionResponse Successful Response
* @throws ApiError
*/
Expand All @@ -2192,19 +2193,28 @@ export const prefetchUseVariableServiceGetVariables = (
limit,
offset,
orderBy,
variableKeyPattern,
}: {
limit?: number;
offset?: number;
orderBy?: string;
variableKeyPattern?: string;
} = {},
) =>
queryClient.prefetchQuery({
queryKey: Common.UseVariableServiceGetVariablesKeyFn({
limit,
offset,
orderBy,
variableKeyPattern,
}),
queryFn: () => VariableService.getVariables({ limit, offset, orderBy }),
queryFn: () =>
VariableService.getVariables({
limit,
offset,
orderBy,
variableKeyPattern,
}),
});
/**
* Get Health
Expand Down
12 changes: 10 additions & 2 deletions airflow/ui/openapi-gen/queries/queries.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2580,6 +2580,7 @@ export const useVariableServiceGetVariable = <
* @param data.limit
* @param data.offset
* @param data.orderBy
* @param data.variableKeyPattern
* @returns VariableCollectionResponse Successful Response
* @throws ApiError
*/
Expand All @@ -2592,21 +2593,28 @@ export const useVariableServiceGetVariables = <
limit,
offset,
orderBy,
variableKeyPattern,
}: {
limit?: number;
offset?: number;
orderBy?: string;
variableKeyPattern?: string;
} = {},
queryKey?: TQueryKey,
options?: Omit<UseQueryOptions<TData, TError>, "queryKey" | "queryFn">,
) =>
useQuery<TData, TError>({
queryKey: Common.UseVariableServiceGetVariablesKeyFn(
{ limit, offset, orderBy },
{ limit, offset, orderBy, variableKeyPattern },
queryKey,
),
queryFn: () =>
VariableService.getVariables({ limit, offset, orderBy }) as TData,
VariableService.getVariables({
limit,
offset,
orderBy,
variableKeyPattern,
}) as TData,
...options,
});
/**
Expand Down
12 changes: 10 additions & 2 deletions airflow/ui/openapi-gen/queries/suspense.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2555,6 +2555,7 @@ export const useVariableServiceGetVariableSuspense = <
* @param data.limit
* @param data.offset
* @param data.orderBy
* @param data.variableKeyPattern
* @returns VariableCollectionResponse Successful Response
* @throws ApiError
*/
Expand All @@ -2567,21 +2568,28 @@ export const useVariableServiceGetVariablesSuspense = <
limit,
offset,
orderBy,
variableKeyPattern,
}: {
limit?: number;
offset?: number;
orderBy?: string;
variableKeyPattern?: string;
} = {},
queryKey?: TQueryKey,
options?: Omit<UseQueryOptions<TData, TError>, "queryKey" | "queryFn">,
) =>
useSuspenseQuery<TData, TError>({
queryKey: Common.UseVariableServiceGetVariablesKeyFn(
{ limit, offset, orderBy },
{ limit, offset, orderBy, variableKeyPattern },
queryKey,
),
queryFn: () =>
VariableService.getVariables({ limit, offset, orderBy }) as TData,
VariableService.getVariables({
limit,
offset,
orderBy,
variableKeyPattern,
}) as TData,
...options,
});
/**
Expand Down
2 changes: 2 additions & 0 deletions airflow/ui/openapi-gen/requests/services.gen.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3010,6 +3010,7 @@ export class VariableService {
* @param data.limit
* @param data.offset
* @param data.orderBy
* @param data.variableKeyPattern
* @returns VariableCollectionResponse Successful Response
* @throws ApiError
*/
Expand All @@ -3023,6 +3024,7 @@ export class VariableService {
limit: data.limit,
offset: data.offset,
order_by: data.orderBy,
variable_key_pattern: data.variableKeyPattern,
},
errors: {
401: "Unauthorized",
Expand Down
1 change: 1 addition & 0 deletions airflow/ui/openapi-gen/requests/types.gen.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2054,6 +2054,7 @@ export type GetVariablesData = {
limit?: number;
offset?: number;
orderBy?: string;
variableKeyPattern?: string | null;
};

export type GetVariablesResponse = VariableCollectionResponse;
Expand Down
61 changes: 52 additions & 9 deletions tests/api_fastapi/core_api/routes/public/test_variables.py
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,11 @@
TEST_VARIABLE_DESCRIPTION3 = "Some description for the variable"


TEST_VARIABLE_SEARCH_KEY = "test_variable_search_key"
TEST_VARIABLE_SEARCH_VALUE = "random search value"
TEST_VARIABLE_SEARCH_DESCRIPTION = "Some description for the variable"


@provide_session
def _create_variables(session) -> None:
Variable.set(
Expand All @@ -63,6 +68,13 @@ def _create_variables(session) -> None:
session=session,
)

Variable.set(
key=TEST_VARIABLE_SEARCH_KEY,
value=TEST_VARIABLE_SEARCH_VALUE,
description=TEST_VARIABLE_SEARCH_DESCRIPTION,
session=session,
)


class TestVariableEndpoint:
@pytest.fixture(autouse=True)
Expand All @@ -80,11 +92,11 @@ class TestDeleteVariable(TestVariableEndpoint):
def test_delete_should_respond_204(self, test_client, session):
self.create_variables()
variables = session.query(Variable).all()
assert len(variables) == 3
assert len(variables) == 4
response = test_client.delete(f"/public/variables/{TEST_VARIABLE_KEY}")
assert response.status_code == 204
variables = session.query(Variable).all()
assert len(variables) == 2
assert len(variables) == 3

def test_delete_should_respond_404(self, test_client):
response = test_client.delete(f"/public/variables/{TEST_VARIABLE_KEY}")
Expand Down Expand Up @@ -122,6 +134,14 @@ class TestGetVariable(TestVariableEndpoint):
"description": TEST_VARIABLE_DESCRIPTION3,
},
),
(
TEST_VARIABLE_SEARCH_KEY,
{
"key": TEST_VARIABLE_SEARCH_KEY,
"value": TEST_VARIABLE_SEARCH_VALUE,
"description": TEST_VARIABLE_SEARCH_DESCRIPTION,
},
),
],
)
def test_get_should_respond_200(self, test_client, session, key, expected_response):
Expand All @@ -143,14 +163,37 @@ class TestGetVariables(TestVariableEndpoint):
"query_params, expected_total_entries, expected_keys",
[
# Filters
({}, 3, [TEST_VARIABLE_KEY, TEST_VARIABLE_KEY2, TEST_VARIABLE_KEY3]),
({"limit": 1}, 3, [TEST_VARIABLE_KEY]),
({"limit": 1, "offset": 1}, 3, [TEST_VARIABLE_KEY2]),
({}, 4, [TEST_VARIABLE_KEY, TEST_VARIABLE_KEY2, TEST_VARIABLE_KEY3, TEST_VARIABLE_SEARCH_KEY]),
({"limit": 1}, 4, [TEST_VARIABLE_KEY]),
({"limit": 1, "offset": 1}, 4, [TEST_VARIABLE_KEY2]),
# Sort
({"order_by": "id"}, 3, [TEST_VARIABLE_KEY, TEST_VARIABLE_KEY2, TEST_VARIABLE_KEY3]),
({"order_by": "-id"}, 3, [TEST_VARIABLE_KEY3, TEST_VARIABLE_KEY2, TEST_VARIABLE_KEY]),
({"order_by": "key"}, 3, [TEST_VARIABLE_KEY3, TEST_VARIABLE_KEY2, TEST_VARIABLE_KEY]),
({"order_by": "-key"}, 3, [TEST_VARIABLE_KEY, TEST_VARIABLE_KEY2, TEST_VARIABLE_KEY3]),
(
{"order_by": "id"},
4,
[TEST_VARIABLE_KEY, TEST_VARIABLE_KEY2, TEST_VARIABLE_KEY3, TEST_VARIABLE_SEARCH_KEY],
),
(
{"order_by": "-id"},
4,
[TEST_VARIABLE_SEARCH_KEY, TEST_VARIABLE_KEY3, TEST_VARIABLE_KEY2, TEST_VARIABLE_KEY],
),
(
{"order_by": "key"},
4,
[TEST_VARIABLE_KEY3, TEST_VARIABLE_KEY2, TEST_VARIABLE_KEY, TEST_VARIABLE_SEARCH_KEY],
),
(
{"order_by": "-key"},
4,
[TEST_VARIABLE_SEARCH_KEY, TEST_VARIABLE_KEY, TEST_VARIABLE_KEY2, TEST_VARIABLE_KEY3],
),
# Search
(
{"variable_key_pattern": "~"},
4,
[TEST_VARIABLE_KEY, TEST_VARIABLE_KEY2, TEST_VARIABLE_KEY3, TEST_VARIABLE_SEARCH_KEY],
),
({"variable_key_pattern": "search"}, 1, [TEST_VARIABLE_SEARCH_KEY]),
],
)
def test_should_respond_200(
Expand Down

0 comments on commit ddae5a5

Please sign in to comment.