From 97905dacb65eda631ce0b1f2a0d56fbb1c104a11 Mon Sep 17 00:00:00 2001 From: Amogh Desai Date: Fri, 27 Jun 2025 20:33:47 +0530 Subject: [PATCH 1/2] Handle directory creation for tests more robustly in airflow-ctl --- airflow-ctl/src/airflowctl/api/client.py | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/airflow-ctl/src/airflowctl/api/client.py b/airflow-ctl/src/airflowctl/api/client.py index 44ea80e9e61e6..162e21c9422dc 100644 --- a/airflow-ctl/src/airflowctl/api/client.py +++ b/airflow-ctl/src/airflowctl/api/client.py @@ -130,8 +130,7 @@ def input_cli_config_file(self) -> str: def save(self): """Save the credentials to keyring and URL to disk as a file.""" default_config_dir = os.environ.get("AIRFLOW_HOME", os.path.expanduser("~/airflow")) - if not os.path.exists(default_config_dir): - os.makedirs(default_config_dir) + os.makedirs(default_config_dir, exist_ok=True) with open(os.path.join(default_config_dir, self.input_cli_config_file), "w") as f: json.dump({"api_url": self.api_url}, f) try: From 38a39e0bc2e8c15d014f8a0b1463658367b309f5 Mon Sep 17 00:00:00 2001 From: Amogh Desai Date: Fri, 27 Jun 2025 22:37:16 +0530 Subject: [PATCH 2/2] generalising it to temp home --- .../ctl/commands/test_auth_command.py | 49 ++++++++++--------- 1 file changed, 26 insertions(+), 23 deletions(-) diff --git a/airflow-ctl/tests/airflow_ctl/ctl/commands/test_auth_command.py b/airflow-ctl/tests/airflow_ctl/ctl/commands/test_auth_command.py index f1d4b95f014b7..c5285710d58c3 100644 --- a/airflow-ctl/tests/airflow_ctl/ctl/commands/test_auth_command.py +++ b/airflow-ctl/tests/airflow_ctl/ctl/commands/test_auth_command.py @@ -19,6 +19,7 @@ import io import json import os +import tempfile from unittest import mock from unittest.mock import patch @@ -40,32 +41,34 @@ class TestCliAuthCommands: @patch.dict(os.environ, {"AIRFLOW_CLI_ENVIRONMENT": "TEST_AUTH_LOGIN"}) @patch("airflowctl.api.client.keyring") @pytest.mark.flaky(reruns=3, reruns_delay=10) - def test_login(self, mock_keyring, api_client_maker): - api_client = api_client_maker( - path="/auth/token/cli", - response_json=self.login_response.model_dump(), - expected_http_status_code=201, - kind=ClientKind.AUTH, - ) + def test_login(self, mock_keyring, api_client_maker, monkeypatch): + with tempfile.TemporaryDirectory() as temp_airflow_home: + monkeypatch.setenv("AIRFLOW_HOME", temp_airflow_home) - mock_keyring.set_password = mock.MagicMock() - mock_keyring.get_password.return_value = None - env = "TEST_AUTH_LOGIN" + api_client = api_client_maker( + path="/auth/token/cli", + response_json=self.login_response.model_dump(), + expected_http_status_code=201, + kind=ClientKind.AUTH, + ) - auth_command.login( - self.parser.parse_args(["auth", "login", "--api-url", "http://localhost:8080"]), - api_client=api_client, - ) - default_config_dir = os.environ.get("AIRFLOW_HOME", os.path.expanduser("~/airflow")) - assert os.path.exists(default_config_dir) - with open(os.path.join(default_config_dir, f"{env}.json")) as f: - assert json.load(f) == { - "api_url": "http://localhost:8080", - } + mock_keyring.set_password = mock.MagicMock() + mock_keyring.get_password.return_value = None + env = "TEST_AUTH_LOGIN" - mock_keyring.set_password.assert_called_once_with( - "airflowctl", "api_token-TEST_AUTH_LOGIN", "TEST_TOKEN" - ) + auth_command.login( + self.parser.parse_args(["auth", "login", "--api-url", "http://localhost:8080"]), + api_client=api_client, + ) + + config_path = os.path.join(temp_airflow_home, f"{env}.json") + assert os.path.exists(config_path) + with open(config_path) as f: + assert json.load(f) == {"api_url": "http://localhost:8080"} + + mock_keyring.set_password.assert_called_once_with( + "airflowctl", "api_token-TEST_AUTH_LOGIN", "TEST_TOKEN" + ) # Test auth login with username and password @patch("airflowctl.api.client.keyring")