Copilot commented on code in PR #65212:
URL: https://github.com/apache/airflow/pull/65212#discussion_r3081674884
##########
providers/cncf/kubernetes/src/airflow/providers/cncf/kubernetes/hooks/kubernetes.py:
##########
@@ -818,6 +818,31 @@ def __init__(
self._event_polling_fallback = False
self._config_loaded = False
+ def _uses_exec_auth(self, kubeconfig_data: dict, context: str | None =
None) -> bool:
+ """
+ Detect if the active kubeconfig context uses exec-based authentication.
+
+ Exec plugins return short-lived tokens (EKS, GKE, etc). Only the user
+ tied to the active context is checked.
+ """
+ active_context = context or kubeconfig_data.get("current-context")
+
+ active_user: str | None = None
+ for ctx in kubeconfig_data.get("contexts", []):
+ if ctx.get("name") == active_context:
+ active_user = ctx.get("context", {}).get("user")
+ break
+
+ users = kubeconfig_data.get("users", [])
+ if active_user is not None:
+ for user in users:
+ if user.get("name") == active_user:
+ return "exec" in user.get("user", {})
+ return False
+
+ # fallback to check all users if active context user cannot be
resolved; this is a safe fallback since it errs on the side of not caching
+ return any("exec" in u.get("user", {}) for u in users)
+
async def _load_config(self):
"""Load Kubernetes configuration once per hook instance."""
Review Comment:
The `_load_config()` docstring says the config is loaded "once per hook
instance", but with the new exec-auth behavior the config may intentionally be
reloaded on every call (since `_config_loaded` stays `False`). Please update
the docstring to reflect the new semantics so callers aren’t misled when
debugging repeated config loads.
##########
providers/cncf/kubernetes/src/airflow/providers/cncf/kubernetes/hooks/kubernetes.py:
##########
@@ -846,50 +871,76 @@ async def _load_config(self):
self._config_loaded = True
return
- # If above block does not return, we are not in a cluster.
self._is_in_cluster = False
-
if self.config_dict:
self.log.debug(LOADING_KUBE_CONFIG_FILE_RESOURCE.format("config
dictionary"))
- await async_config.load_kube_config_from_dict(self.config_dict,
context=cluster_context)
- self._config_loaded = True
- return
+ await async_config.load_kube_config_from_dict(
+ self.config_dict,
+ context=cluster_context,
+ )
+
+ if not self._uses_exec_auth(self.config_dict,
context=cluster_context):
+ self._config_loaded = True
+
+ return
if kubeconfig_path is not None:
self.log.debug("loading kube_config from: %s", kubeconfig_path)
+
await async_config.load_kube_config(
config_file=kubeconfig_path,
client_configuration=self.client_configuration,
context=cluster_context,
)
- self._config_loaded = True
- return
+ try:
+ async with aiofiles.open(kubeconfig_path) as f:
+ content = await f.read()
+ data = yaml.safe_load(content)
+
+ if not self._uses_exec_auth(data, context=cluster_context):
+ self._config_loaded = True
+ except Exception as exc:
+ self.log.warning(
+ "Error while parsing kube_config from %s to detect exec
auth; "
+ "continuing without caching the config: %s",
+ kubeconfig_path,
+ exc,
+ )
+
+ return
Review Comment:
New exec-auth detection for `kube_config_path` isn’t covered by tests. There
are existing tests for loading from `kube_config_path`, but none assert the new
caching behavior (`_config_loaded` stays `False` when the active context uses
exec, and `True` otherwise). Adding a unit test that writes an exec-based
kubeconfig to `tmp_path` and asserts the resulting `_config_loaded` value would
prevent regressions.
##########
providers/cncf/kubernetes/src/airflow/providers/cncf/kubernetes/hooks/kubernetes.py:
##########
@@ -818,6 +818,31 @@ def __init__(
self._event_polling_fallback = False
self._config_loaded = False
+ def _uses_exec_auth(self, kubeconfig_data: dict, context: str | None =
None) -> bool:
+ """
+ Detect if the active kubeconfig context uses exec-based authentication.
+
+ Exec plugins return short-lived tokens (EKS, GKE, etc). Only the user
+ tied to the active context is checked.
Review Comment:
`_uses_exec_auth()` docstring says "Only the user tied to the active context
is checked", but the implementation falls back to scanning *all* users when the
active context/user can’t be resolved. Please document this fallback behavior
(and its intent to err on the side of not caching) to keep the docstring
accurate.
##########
providers/cncf/kubernetes/src/airflow/providers/cncf/kubernetes/hooks/kubernetes.py:
##########
@@ -818,6 +818,31 @@ def __init__(
self._event_polling_fallback = False
self._config_loaded = False
+ def _uses_exec_auth(self, kubeconfig_data: dict, context: str | None =
None) -> bool:
+ """
+ Detect if the active kubeconfig context uses exec-based authentication.
+
+ Exec plugins return short-lived tokens (EKS, GKE, etc). Only the user
+ tied to the active context is checked.
+ """
+ active_context = context or kubeconfig_data.get("current-context")
+
+ active_user: str | None = None
+ for ctx in kubeconfig_data.get("contexts", []):
+ if ctx.get("name") == active_context:
+ active_user = ctx.get("context", {}).get("user")
+ break
+
+ users = kubeconfig_data.get("users", [])
+ if active_user is not None:
+ for user in users:
+ if user.get("name") == active_user:
+ return "exec" in user.get("user", {})
+ return False
+
+ # fallback to check all users if active context user cannot be
resolved; this is a safe fallback since it errs on the side of not caching
+ return any("exec" in u.get("user", {}) for u in users)
Review Comment:
`_uses_exec_auth()` assumes `ctx["context"]` and `user["user"]` are dicts,
but kubeconfig YAML can legally contain empty mappings like `context:` /
`user:` which `yaml.safe_load` parses as `None`. In that case,
`ctx.get("context", {}).get(...)` or `'exec' in user.get('user', {})` will
raise (AttributeError/TypeError) and can fail `_load_config()` for exec
detection. Consider normalizing with `ctx_context = ctx.get("context") or {}`
and `user_spec = user.get("user") or {}` (and similarly in the fallback
`any(...)`) so detection is best-effort and never breaks config loading.
--
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.
To unsubscribe, e-mail: [email protected]
For queries about this service, please contact Infrastructure at:
[email protected]