This is an automated email from the ASF dual-hosted git repository.
shahar1 pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/airflow.git
The following commit(s) were added to refs/heads/main by this push:
new 3107af07cd1 Use POSIX-compliant tail to extract token line in EKS
command (#73690)
3107af07cd1 is described below
commit 3107af07cd163a73d43a6e857fcbd21c48804496
Author: Alejandro Morgante <[email protected]>
AuthorDate: Sun Sep 27 15:09:37 2026 -0300
Use POSIX-compliant tail to extract token line in EKS command (#73690)
The bash parameter expansion with $'\n' quoting used to strip to the
last line of the token helper output is a bash-specific extension not
guaranteed by POSIX; it silently breaks on sh implementations that do
not support it. Replace with `printf '%s\n' "$output" | tail -n 1`,
which is portable and also handles spurious stdout lines from
dependencies that bypass the stderr redirect.
---
.../src/airflow/providers/amazon/aws/hooks/eks.py | 6 ++--
.../amazon/tests/unit/amazon/aws/hooks/test_eks.py | 40 ++++++++++++++++++----
2 files changed, 35 insertions(+), 11 deletions(-)
diff --git a/providers/amazon/src/airflow/providers/amazon/aws/hooks/eks.py
b/providers/amazon/src/airflow/providers/amazon/aws/hooks/eks.py
index 032d7e16833..5a20629ef91 100644
--- a/providers/amazon/src/airflow/providers/amazon/aws/hooks/eks.py
+++ b/providers/amazon/src/airflow/providers/amazon/aws/hooks/eks.py
@@ -105,10 +105,8 @@ COMMAND = """
exit "$status"
fi
- # Use pure bash below to parse so that it's posix compliant
- # Only the token line should be on stdout (stderr captured above)
-
- last_line=${{output##*$'\\n'}} # strip everything up to the last
newline
+ # Keep only the token line even if a dependency logs to stdout.
+ last_line=$(printf '%s\\n' "$output" | tail -n 1)
timestamp=${{last_line#expirationTimestamp: }} # drop the label
timestamp=${{timestamp%%,*}} # keep up to the first comma
diff --git a/providers/amazon/tests/unit/amazon/aws/hooks/test_eks.py
b/providers/amazon/tests/unit/amazon/aws/hooks/test_eks.py
index 521005a19ed..af8b7c0e6ce 100644
--- a/providers/amazon/tests/unit/amazon/aws/hooks/test_eks.py
+++ b/providers/amazon/tests/unit/amazon/aws/hooks/test_eks.py
@@ -17,6 +17,8 @@
# under the License.
from __future__ import annotations
+import json
+import subprocess
import sys
from copy import deepcopy
from pathlib import Path
@@ -53,7 +55,7 @@ from moto.eks.models import (
NODEGROUP_NOT_FOUND_MSG,
)
-from airflow.providers.amazon.aws.hooks.eks import EksHook
+from airflow.providers.amazon.aws.hooks.eks import COMMAND, EksHook
from unit.amazon.aws.utils.eks_test_constants import (
DEFAULT_CONN_ID,
@@ -1275,8 +1277,6 @@ class TestEksHook:
def test_command_template_captures_stderr_separately(self):
"""Verify COMMAND keeps stderr out of stdout while preserving
errors."""
- from airflow.providers.amazon.aws.hooks.eks import COMMAND
-
# Verify stderr is not merged with stdout (the core correctness
requirement)
assert "2>&1" not in COMMAND, (
"COMMAND must not use 2>&1 — merging stderr with stdout breaks
bash token parsing"
@@ -1286,10 +1286,38 @@ class TestEksHook:
assert 'cat "$stderr_file" >&2' in COMMAND
assert "2>/dev/null" not in COMMAND
+ def test_command_template_uses_last_stdout_line_with_posix_shell(self,
tmp_path):
+ credentials_file = tmp_path / "credentials"
+ credentials_file.write_text(
+ "export AWS_ACCESS_KEY_ID='test-access-key'\nexport
AWS_SECRET_ACCESS_KEY='test-secret-key'\n"
+ )
+ token_helper = tmp_path / "token-helper"
+ token_helper.write_text(
+ "#!/bin/sh\n"
+ "printf '%s\\n' '2026-09-04T17:50:59Z [info] Found credentials in
environment variables.'\n"
+ "printf '%s\\n' 'expirationTimestamp: 2026-09-04T18:04:59Z, token:
test-token'\n"
+ )
+ token_helper.chmod(0o700)
+ command = COMMAND.format(
+ credentials_file=credentials_file,
+ sts_url="https://sts.us-east-1.amazonaws.com",
+ python_executable=token_helper,
+ eks_cluster_name="test-cluster",
+ args="",
+ authentication_api_version="client.authentication.k8s.io/v1",
+ )
+
+ result = subprocess.run(["sh", "-c", command], capture_output=True,
text=True, check=True)
+
+ assert json.loads(result.stdout) == {
+ "kind": "ExecCredential",
+ "apiVersion": "client.authentication.k8s.io/v1",
+ "spec": {},
+ "status": {"expirationTimestamp": "2026-09-04T18:04:59Z", "token":
"test-token"},
+ }
+
def test_command_template_does_not_print_token_output_on_error(self):
"""Verify the error path does not echo stdout, which can contain a
token."""
- from airflow.providers.amazon.aws.hooks.eks import COMMAND
-
failure_block = COMMAND.split('if [ "$status" -ne 0 ]; then',
1)[1].split("fi", 1)[0]
assert '"$output"' not in failure_block
@@ -1299,8 +1327,6 @@ class TestEksHook:
a malformed ExecCredential with an empty token is sent to the API
server,
resulting in 401 Unauthorized with an empty user identity in audit
logs.
"""
- from airflow.providers.amazon.aws.hooks.eks import COMMAND
-
# Verify token validation check exists
assert 'if [ -z "$token" ]' in COMMAND, (
"COMMAND must validate that token is non-empty before producing
ExecCredential JSON"