Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@

import json

from pydantic import Field, model_validator
from pydantic import Field, JsonValue, model_validator

from airflow.api_fastapi.core_api.base import BaseModel, StrictBaseModel
from airflow.models.base import ID_LEN
Expand Down Expand Up @@ -54,7 +54,7 @@ class VariableBody(StrictBaseModel):
"""Variable serializer for bodies."""

key: str = Field(max_length=ID_LEN)
value: str = Field(serialization_alias="val")
value: JsonValue = Field(serialization_alias="val")
description: str | None = Field(default=None)


Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9129,6 +9129,7 @@ components:
- unixname
title: JobResponse
description: Job serializer for responses.
JsonValue: {}
PatchTaskInstanceBody:
properties:
new_state:
Expand Down Expand Up @@ -10407,8 +10408,7 @@ components:
maxLength: 250
title: Key
value:
type: string
title: Value
$ref: '#/components/schemas/JsonValue'
description:
anyOf:
- type: string
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3410,6 +3410,8 @@ export const $JobResponse = {
description: "Job serializer for responses.",
} as const;

export const $JsonValue = {} as const;

export const $PatchTaskInstanceBody = {
properties: {
new_state: {
Expand Down Expand Up @@ -5451,8 +5453,7 @@ export const $VariableBody = {
title: "Key",
},
value: {
type: "string",
title: "Value",
$ref: "#/components/schemas/JsonValue",
},
description: {
anyOf: [
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -898,6 +898,8 @@ export type JobResponse = {
unixname: string | null;
};

export type JsonValue = unknown;

/**
* Request body for Clear Task Instances endpoint.
*/
Expand Down Expand Up @@ -1323,7 +1325,7 @@ export type ValidationError = {
*/
export type VariableBody = {
key: string;
value: string;
value: JsonValue;
description?: string | null;
};

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -58,7 +58,7 @@ const ImportVariablesForm = ({ onClose }: ImportVariablesFormProps) => {

const [actionIfExists, setActionIfExists] = useState<"fail" | "overwrite" | "skip">("fail");
const [isParsing, setIsParsing] = useState(false);
const [fileContent, setFileContent] = useState<Record<string, string> | undefined>(undefined);
const [fileContent, setFileContent] = useState<Record<string, unknown> | undefined>(undefined);

const onFileChange = (file: File) => {
setIsParsing(true);
Expand All @@ -67,21 +67,9 @@ const ImportVariablesForm = ({ onClose }: ImportVariablesFormProps) => {
reader.addEventListener("load", (event) => {
try {
const text = event.target?.result as string;
const parsedContent = JSON.parse(text) as unknown;
const parsedContent = JSON.parse(text) as Record<string, unknown>;

if (
typeof parsedContent === "object" &&
parsedContent !== null &&
Object.entries(parsedContent).every(
([key, value]) => typeof key === "string" && typeof value === "string",
)
) {
const typedContent = parsedContent as Record<string, string>;

setFileContent(typedContent);
} else {
throw new Error("Invalid JSON format");
}
setFileContent(parsedContent);
} catch {
setError({
body: {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -478,25 +478,6 @@ def test_post_should_respond_422_when_key_too_large(self, test_client):
]
}

def test_post_should_respond_422_when_value_is_null(self, test_client):
body = {
"key": "null value key",
"value": None,
"description": "key too large",
}
response = test_client.post("/variables", json=body)
assert response.status_code == 422
assert response.json() == {
"detail": [
{
"type": "string_type",
"loc": ["body", "value"],
"msg": "Input should be a valid string",
"input": None,
}
]
}

@pytest.mark.parametrize(
"body",
[
Expand Down Expand Up @@ -728,7 +709,13 @@ class TestBulkVariables(TestVariableEndpoint):
"actions": [
{
"action": "create",
"entities": [{"key": "new_var1", "value": "new_value1"}],
"entities": [
{"key": "new_var1", "value": "new_value1"},
{"key": "new_var2", "value": ["new_value1"]},
{"key": "new_var3", "value": 1},
{"key": "new_var4", "value": None},
{"key": "new_var5", "value": {"foo": "bar"}},
],
"action_on_existence": "skip",
},
{
Expand All @@ -750,7 +737,10 @@ class TestBulkVariables(TestVariableEndpoint):
]
},
{
"create": {"success": ["new_var1"], "errors": []},
"create": {
"success": ["new_var1", "new_var2", "new_var3", "new_var4", "new_var5"],
"errors": [],
},
"update": {"success": ["test_variable_key"], "errors": []},
"delete": {"success": ["dictionary_password"], "errors": []},
},
Expand Down
6 changes: 5 additions & 1 deletion airflow-ctl/src/airflowctl/api/datamodels/generated.py
Original file line number Diff line number Diff line change
Expand Up @@ -562,6 +562,10 @@ class JobResponse(BaseModel):
unixname: Annotated[str | None, Field(title="Unixname")] = None


class JsonValue(RootModel[Any]):
root: Any


class PluginImportErrorResponse(BaseModel):
"""
Plugin Import Error serializer for responses.
Expand Down Expand Up @@ -837,7 +841,7 @@ class VariableBody(BaseModel):
extra="forbid",
)
key: Annotated[str, Field(max_length=250, title="Key")]
value: Annotated[str, Field(title="Value")]
value: JsonValue
description: Annotated[str | None, Field(title="Description")] = None


Expand Down
10 changes: 6 additions & 4 deletions airflow-ctl/tests/airflow_ctl/api/test_operations.py
Original file line number Diff line number Diff line change
Expand Up @@ -662,10 +662,12 @@ class TestVariablesOperations:
key = "key"
value = "val"
description = "description"
variable = VariableBody(
key=key,
value=value,
description=description,
variable = VariableBody.model_validate(
{
"key": key,
"value": value,
"description": description,
}
)
variable_response = VariableResponse(
key=key,
Expand Down