Skip to content

Commit 8b03304

Browse files
authored
Fix list-envs auth status for env names containing .json (#64677)
1 parent 8c1d4cc commit 8b03304

3 files changed

Lines changed: 36 additions & 7 deletions

File tree

airflow-ctl/src/airflowctl/api/client.py

Lines changed: 15 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -168,6 +168,11 @@ def input_cli_config_file(self) -> str:
168168
"""Generate path for the CLI config file."""
169169
return f"{self.api_environment}.json"
170170

171+
@staticmethod
172+
def token_key_for_environment(api_environment: str) -> str:
173+
"""Build the keyring/debug token key for a given environment name."""
174+
return f"api_token_{api_environment}"
175+
171176
def save(self, skip_keyring: bool = False):
172177
"""
173178
Save the credentials to keyring and URL to disk as a file.
@@ -185,7 +190,7 @@ def save(self, skip_keyring: bool = False):
185190
with open(
186191
os.path.join(default_config_dir, f"debug_creds_{self.input_cli_config_file}"), "w"
187192
) as f:
188-
json.dump({f"api_token_{self.api_environment}": self.api_token}, f)
193+
json.dump({self.token_key_for_environment(self.api_environment): self.api_token}, f)
189194
else:
190195
if skip_keyring:
191196
return
@@ -198,7 +203,11 @@ def save(self, skip_keyring: bool = False):
198203
for candidate in candidates:
199204
if hasattr(candidate, "_get_new_password"):
200205
candidate._get_new_password = _bounded_get_new_password
201-
keyring.set_password("airflowctl", f"api_token_{self.api_environment}", self.api_token) # type: ignore[arg-type]
206+
keyring.set_password(
207+
"airflowctl",
208+
self.token_key_for_environment(self.api_environment),
209+
self.api_token, # type: ignore[arg-type]
210+
)
202211
except (NoKeyringError, NotImplementedError) as e:
203212
log.error(e)
204213
raise AirflowCtlKeyringException(
@@ -229,11 +238,13 @@ def load(self) -> Credentials:
229238
)
230239
with open(debug_creds_path) as df:
231240
debug_credentials = json.load(df)
232-
self.api_token = debug_credentials.get(f"api_token_{self.api_environment}")
241+
self.api_token = debug_credentials.get(
242+
self.token_key_for_environment(self.api_environment)
243+
)
233244
else:
234245
try:
235246
self.api_token = keyring.get_password(
236-
"airflowctl", f"api_token_{self.api_environment}"
247+
"airflowctl", self.token_key_for_environment(self.api_environment)
237248
)
238249
except ValueError as e:
239250
# Incorrect keyring password

airflow-ctl/src/airflowctl/ctl/commands/auth_command.py

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -144,7 +144,7 @@ def list_envs(args) -> None:
144144
if filename.startswith("debug_creds_") or filename.endswith("_generated.json"):
145145
continue
146146

147-
env_name = filename.replace(".json", "")
147+
env_name, _ = os.path.splitext(filename)
148148

149149
# Try to read config file
150150
api_url = None
@@ -168,11 +168,11 @@ def list_envs(args) -> None:
168168
if os.path.exists(debug_path):
169169
with open(debug_path) as f:
170170
debug_creds = json.load(f)
171-
if f"api_token_{env_name}" in debug_creds:
171+
if Credentials.token_key_for_environment(env_name) in debug_creds:
172172
token_status = "authenticated"
173173
else:
174174
# Check keyring
175-
token = keyring.get_password("airflowctl", f"api_token_{env_name}")
175+
token = keyring.get_password("airflowctl", Credentials.token_key_for_environment(env_name))
176176
if token:
177177
token_status = "authenticated"
178178
except NoKeyringError:

airflow-ctl/tests/airflow_ctl/ctl/commands/test_auth_command.py

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -477,3 +477,21 @@ def test_list_envs_filters_special_files(self, monkeypatch):
477477

478478
# Only production environment should be checked, not the special files
479479
mock_get_password.assert_called_once_with("airflowctl", "api_token_production")
480+
481+
def test_list_envs_environment_name_with_json_substring(self, monkeypatch):
482+
"""Test list-envs keeps '.json' substrings in environment name for key lookup."""
483+
with (
484+
tempfile.TemporaryDirectory() as temp_airflow_home,
485+
patch("keyring.get_password") as mock_get_password,
486+
):
487+
monkeypatch.setenv("AIRFLOW_HOME", temp_airflow_home)
488+
489+
with open(os.path.join(temp_airflow_home, "prod.json.region.json"), "w") as f:
490+
json.dump({"api_url": "http://localhost:8080"}, f)
491+
492+
mock_get_password.return_value = "test_token"
493+
494+
args = self.parser.parse_args(["auth", "list-envs"])
495+
auth_command.list_envs(args)
496+
497+
mock_get_password.assert_called_once_with("airflowctl", "api_token_prod.json.region")

0 commit comments

Comments
 (0)