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 @@ -32,7 +32,7 @@ class VariableResponse(BaseModel):
"""Variable serializer for responses."""

key: str
val: str = Field(alias="value")
val: str | None = Field(alias="value", default=None)
description: str | None
is_encrypted: bool
team_name: str | None
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14977,7 +14977,9 @@ components:
type: string
title: Key
value:
type: string
anyOf:
- type: string
- type: 'null'
title: Value
description:
anyOf:
Expand All @@ -14995,7 +14997,6 @@ components:
type: object
required:
- key
- value
- description
- is_encrypted
- team_name
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7041,7 +7041,14 @@ export const $VariableResponse = {
title: 'Key'
},
value: {
type: 'string',
anyOf: [
{
type: 'string'
},
{
type: 'null'
}
],
title: 'Value'
},
description: {
Expand Down Expand Up @@ -7072,7 +7079,7 @@ export const $VariableResponse = {
}
},
type: 'object',
required: ['key', 'value', 'description', 'is_encrypted', 'team_name'],
required: ['key', 'description', 'is_encrypted', 'team_name'],
title: 'VariableResponse',
description: 'Variable serializer for responses.'
} as const;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -1709,7 +1709,7 @@ export type VariableCollectionResponse = {
*/
export type VariableResponse = {
key: string;
value: string;
value?: string | null;
description: string | null;
is_encrypted: boolean;
team_name: string | null;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -50,7 +50,7 @@ const EditVariableButton = ({ disabled, variable }: Props) => {
description: variable.description ?? "",
key: variable.key,
team_name: variable.team_name ?? "",
value: formatValue(variable.value),
value: formatValue(variable.value ?? ""),
};
const { editVariable, error, isPending, setError } = useEditVariable(initialVariableValue, {
onSuccessConfirm: onClose,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -94,9 +94,9 @@ const getColumns = ({
cell: ({ row }) => (
<Box minWidth={0} overflowWrap="anywhere" wordBreak="break-word">
<TrimText
charLimit={open ? row.original.value.length : undefined}
charLimit={open ? (row.original.value?.length ?? 0) : undefined}
showTooltip
text={row.original.value}
text={row.original.value ?? null}
/>
</Box>
),
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -254,6 +254,32 @@ def test_get_should_respond_404(self, test_client):
body = response.json()
assert f"The Variable with key: `{TEST_VARIABLE_KEY}` was not found" == body["detail"]

def test_get_should_respond_200_with_null_value_when_decryption_fails(self, test_client, session):
"""
Regression test for https://github.com/apache/airflow/pull/65452.

If the stored value cannot be decrypted (for example after a Fernet key
rotation) ``Variable.get_val`` returns ``None``. The endpoint must then
respond with HTTP 200 and ``"value": null`` instead of failing with an
HTTP 500 caused by response-schema validation.
"""
from cryptography.fernet import InvalidToken

self.create_variables()
with mock.patch("airflow.models.variable.get_fernet") as mock_get_fernet:
mock_get_fernet.return_value.decrypt.side_effect = InvalidToken
response = test_client.get(f"/variables/{TEST_VARIABLE_KEY}")

assert response.status_code == 200
body = response.json()
assert body == {
"key": TEST_VARIABLE_KEY,
"value": None,
"description": TEST_VARIABLE_DESCRIPTION,
"is_encrypted": True,
"team_name": None,
}


class TestGetVariables(TestVariableEndpoint):
@pytest.mark.enable_redact
Expand Down
2 changes: 1 addition & 1 deletion airflow-ctl/src/airflowctl/api/datamodels/generated.py
Original file line number Diff line number Diff line change
Expand Up @@ -992,7 +992,7 @@ class VariableResponse(BaseModel):
"""

key: Annotated[str, Field(title="Key")]
value: Annotated[str, Field(title="Value")]
value: Annotated[str | None, Field(title="Value")] = None
description: Annotated[str | None, Field(title="Description")] = None
is_encrypted: Annotated[bool, Field(title="Is Encrypted")]
team_name: Annotated[str | None, Field(title="Team Name")] = None
Expand Down
Loading