Skip to content
Closed
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
16 changes: 13 additions & 3 deletions airflow-core/src/airflow/cli/commands/variable_command.py
Original file line number Diff line number Diff line change
Expand Up @@ -23,10 +23,12 @@
import os
from typing import TYPE_CHECKING

from airflowctl.api.operations import ServerResponseError
from sqlalchemy import select

from airflow.cli.api_client import NEW_API_CLIENT, Client, provide_api_client
from airflow.cli.simple_table import AirflowConsole
from airflow.cli.utils import SENSITIVE_PLACEHOLDER, print_export_output
from airflow.cli.utils import SENSITIVE_PLACEHOLDER, deprecated_for_airflowctl, print_export_output
from airflow.exceptions import (
AirflowFileParseException,
AirflowUnsupportedFileTypeException,
Expand Down Expand Up @@ -116,10 +118,18 @@ def variables_set(args):


@cli_utils.action_cli
@deprecated_for_airflowctl("airflowctl variables delete")
@suppress_logs_and_warning
@providers_configuration_loaded
def variables_delete(args):
@provide_api_client
def variables_delete(args, api_client: Client = NEW_API_CLIENT):
"""Delete variable by a given name."""
Variable.delete(args.key)
try:
api_client.variables.delete(variable_key=args.key)
except ServerResponseError as e:
if e.response.status_code == 404:
raise SystemExit(f"Variable {args.key} does not exist")
raise
print(f"Variable {args.key} deleted")


Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@

import pytest

from airflow.cli.commands import asset_command, dag_command, pool_command
from airflow.cli.commands import asset_command, dag_command, pool_command, variable_command
from airflow.exceptions import RemovedInAirflow4Warning

# (command callable, argv to parse, expected airflowctl replacement named in the warning)
Expand All @@ -52,6 +52,7 @@
["assets", "materialize", "--name=foo"],
"airflowctl assets materialize",
),
(variable_command.variables_delete, ["variables", "delete", "foo"], "airflowctl variables delete"),
]


Expand Down
23 changes: 18 additions & 5 deletions airflow-core/tests/unit/cli/commands/test_variable_command.py
Original file line number Diff line number Diff line change
Expand Up @@ -22,8 +22,10 @@
from contextlib import redirect_stdout
from io import StringIO

import httpx
import pytest
import yaml
from airflowctl.api.operations import ServerResponseError
from sqlalchemy import select

from airflow import models
Expand All @@ -37,6 +39,12 @@
pytestmark = pytest.mark.db_test


def _server_error(status_code: int) -> ServerResponseError:
request = httpx.Request("GET", "http://testserver/api/v2/variables/foo")
response = httpx.Response(status_code, request=request, json={"detail": "boom"})
return ServerResponseError(message="boom", request=request, response=response)


# Test data fixtures
@pytest.fixture
def simple_variable_data():
Expand Down Expand Up @@ -324,12 +332,16 @@ def test_variables_list_edge_cases(self):
if item["key"] in ["empty_var", "none_var", "normal_var"]:
assert item["val"] == "***"

def test_variables_delete(self):
def test_variables_delete(self, mock_cli_api_client):
"""Test variable_delete command"""
variable_command.variables_set(self.parser.parse_args(["variables", "set", "foo", "bar"]))
variable_command.variables_delete(self.parser.parse_args(["variables", "delete", "foo"]))
with pytest.raises(KeyError):
Variable.get("foo")
mock_cli_api_client.variables.delete.assert_called_once_with(variable_key="foo")

def test_variables_delete_missing(self, mock_cli_api_client):
"""Deleting a missing variable exits with an error."""
mock_cli_api_client.variables.delete.side_effect = _server_error(404)
with pytest.raises(SystemExit):
variable_command.variables_delete(self.parser.parse_args(["variables", "delete", "foo"]))

@pytest.mark.parametrize(
"filename",
Expand Down Expand Up @@ -372,7 +384,8 @@ def test_variables_isolation(self, tmp_path):

variable_command.variables_set(self.parser.parse_args(["variables", "set", "bar", "updated"]))
variable_command.variables_set(self.parser.parse_args(["variables", "set", "foo", '{"foo":"oops"}']))
variable_command.variables_delete(self.parser.parse_args(["variables", "delete", "foo"]))
# ``delete`` is migrated to airflowctl, so remove via the model here
Variable.delete("foo")
with create_session() as session:
variable_command.variables_import(
self.parser.parse_args(["variables", "import", os.fspath(path1)]), session=session
Expand Down
Loading