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 005fd649bdf Add dedicated tests for cncf.kubernetes secret and 
k8s_model modules (#73751)
005fd649bdf is described below

commit 005fd649bdf44d1cae66a48da341fef039b3ec67
Author: Karthik Mohankumar <[email protected]>
AuthorDate: Sat Sep 26 10:59:40 2026 -0500

    Add dedicated tests for cncf.kubernetes secret and k8s_model modules 
(#73751)
    
    * Add dedicated tests for cncf.kubernetes secret and k8s_model modules
    
    The Secret tests lived under a models/ test package that has no matching 
source package, so the project-structure check could not see them and both 
modules stayed on the OVERLOOKED_TESTS allowlist. Placing the tests where the 
check expects them lets the allowlist shrink, and covers constructor 
validation, equality semantics and append_to_pod chaining, which were 
previously untested.
    
    * Remove secret and k8s_model from OVERLOOKED_TESTS
    
    * Remove models test package now that Secret tests mirror source 
layoutDelete providers/cncf/kubernetes/tests/unit/cncf/kubernetes/models 
directory
---
 .../tests/unit/always/test_project_structure.py    |  2 -
 .../tests/unit/cncf/kubernetes/models/__init__.py  | 17 --------
 .../tests/unit/cncf/kubernetes/test_k8s_model.py   | 47 ++++++++++++++++++++++
 .../cncf/kubernetes/{models => }/test_secret.py    | 45 +++++++++++++++++++++
 4 files changed, 92 insertions(+), 19 deletions(-)

diff --git a/airflow-core/tests/unit/always/test_project_structure.py 
b/airflow-core/tests/unit/always/test_project_structure.py
index 106df1e7336..ed83b0aae0a 100644
--- a/airflow-core/tests/unit/always/test_project_structure.py
+++ b/airflow-core/tests/unit/always/test_project_structure.py
@@ -76,10 +76,8 @@ class TestProjectStructure:
             
"providers/cncf/kubernetes/tests/unit/cncf/kubernetes/executors/test_kubernetes_executor_types.py",
             
"providers/cncf/kubernetes/tests/unit/cncf/kubernetes/executors/test_kubernetes_executor_utils.py",
             
"providers/cncf/kubernetes/tests/unit/cncf/kubernetes/test_exceptions.py",
-            
"providers/cncf/kubernetes/tests/unit/cncf/kubernetes/test_k8s_model.py",
             
"providers/cncf/kubernetes/tests/unit/cncf/kubernetes/test_kube_config.py",
             
"providers/cncf/kubernetes/tests/unit/cncf/kubernetes/test_python_kubernetes_script.py",
-            
"providers/cncf/kubernetes/tests/unit/cncf/kubernetes/test_secret.py",
             
"providers/cncf/kubernetes/tests/unit/cncf/kubernetes/utils/test_delete_from.py",
             
"providers/common/compat/tests/unit/common/compat/standard/test_utils.py",
             
"providers/fab/tests/unit/fab/auth_manager/api_fastapi/datamodels/test_login.py",
diff --git 
a/providers/cncf/kubernetes/tests/unit/cncf/kubernetes/models/__init__.py 
b/providers/cncf/kubernetes/tests/unit/cncf/kubernetes/models/__init__.py
deleted file mode 100644
index 217e5db9607..00000000000
--- a/providers/cncf/kubernetes/tests/unit/cncf/kubernetes/models/__init__.py
+++ /dev/null
@@ -1,17 +0,0 @@
-#
-# Licensed to the Apache Software Foundation (ASF) under one
-# or more contributor license agreements.  See the NOTICE file
-# distributed with this work for additional information
-# regarding copyright ownership.  The ASF licenses this file
-# to you under the Apache License, Version 2.0 (the
-# "License"); you may not use this file except in compliance
-# with the License.  You may obtain a copy of the License at
-#
-#   http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing,
-# software distributed under the License is distributed on an
-# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
-# KIND, either express or implied.  See the License for the
-# specific language governing permissions and limitations
-# under the License.
diff --git 
a/providers/cncf/kubernetes/tests/unit/cncf/kubernetes/test_k8s_model.py 
b/providers/cncf/kubernetes/tests/unit/cncf/kubernetes/test_k8s_model.py
new file mode 100644
index 00000000000..7dace4ed558
--- /dev/null
+++ b/providers/cncf/kubernetes/tests/unit/cncf/kubernetes/test_k8s_model.py
@@ -0,0 +1,47 @@
+# Licensed to the Apache Software Foundation (ASF) under one
+# or more contributor license agreements.  See the NOTICE file
+# distributed with this work for additional information
+# regarding copyright ownership.  The ASF licenses this file
+# to you under the Apache License, Version 2.0 (the
+# "License"); you may not use this file except in compliance
+# with the License.  You may obtain a copy of the License at
+#
+#   http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing,
+# software distributed under the License is distributed on an
+# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+# KIND, either express or implied.  See the License for the
+# specific language governing permissions and limitations
+# under the License.
+from __future__ import annotations
+
+from unittest import mock
+
+import pytest
+from kubernetes.client import models as k8s
+
+from airflow.providers.cncf.kubernetes.k8s_model import K8SModel, append_to_pod
+
+
[email protected]
+def pod() -> k8s.V1Pod:
+    return k8s.V1Pod(metadata=k8s.V1ObjectMeta(name="base"))
+
+
+class TestAppendToPod:
+    @pytest.mark.parametrize("k8s_objects", [None, []], ids=["none", "empty"])
+    def test_no_objects_returns_pod_unchanged(self, pod, k8s_objects):
+        assert append_to_pod(pod, k8s_objects) is pod
+
+    def test_each_object_receives_previous_result(self, pod):
+        intermediate = 
k8s.V1Pod(metadata=k8s.V1ObjectMeta(name="intermediate"))
+        final = k8s.V1Pod(metadata=k8s.V1ObjectMeta(name="final"))
+        first = mock.create_autospec(K8SModel, instance=True)
+        first.attach_to_pod.return_value = intermediate
+        second = mock.create_autospec(K8SModel, instance=True)
+        second.attach_to_pod.return_value = final
+
+        assert append_to_pod(pod, [first, second]) is final
+        first.attach_to_pod.assert_called_once_with(pod)
+        second.attach_to_pod.assert_called_once_with(intermediate)
diff --git 
a/providers/cncf/kubernetes/tests/unit/cncf/kubernetes/models/test_secret.py 
b/providers/cncf/kubernetes/tests/unit/cncf/kubernetes/test_secret.py
similarity index 74%
rename from 
providers/cncf/kubernetes/tests/unit/cncf/kubernetes/models/test_secret.py
rename to providers/cncf/kubernetes/tests/unit/cncf/kubernetes/test_secret.py
index 1f299529687..9ccdae57921 100644
--- a/providers/cncf/kubernetes/tests/unit/cncf/kubernetes/models/test_secret.py
+++ b/providers/cncf/kubernetes/tests/unit/cncf/kubernetes/test_secret.py
@@ -19,14 +19,59 @@ from __future__ import annotations
 import uuid
 from unittest import mock
 
+import pytest
 from kubernetes.client import ApiClient, models as k8s
 
+from airflow.exceptions import AirflowConfigException
 from airflow.providers.cncf.kubernetes.k8s_model import append_to_pod
 from airflow.providers.cncf.kubernetes.pod_generator import PodGenerator
 from airflow.providers.cncf.kubernetes.secret import Secret
 
 
 class TestSecret:
+    def test_invalid_deploy_type(self):
+        with pytest.raises(AirflowConfigException, match="deploy_type must be 
env or volume"):
+            Secret("file", "/etc/foo", "secret")
+
+    def test_key_without_deploy_target(self):
+        with pytest.raises(
+            AirflowConfigException, match="If `key` is set, `deploy_target` 
should not be None"
+        ):
+            Secret("env", None, "secret", "key")
+
+    @pytest.mark.parametrize(
+        ("deploy_type", "deploy_target", "expected_target"),
+        [
+            pytest.param("env", "my_var", "MY_VAR", 
id="env-target-uppercased"),
+            pytest.param("volume", "/etc/lower", "/etc/lower", 
id="volume-target-unchanged"),
+        ],
+    )
+    def test_deploy_target_normalization(self, deploy_type, deploy_target, 
expected_target):
+        assert Secret(deploy_type, deploy_target, "secret").deploy_target == 
expected_target
+
+    def test_equality_and_hash(self):
+        secret = Secret("env", "name", "secret", "key")
+        same = Secret("env", "NAME", "secret", "key")
+        different = Secret("env", "name", "secret", "other_key")
+
+        assert secret == same
+        assert hash(secret) == hash(same)
+        assert secret != different
+        assert len({secret, same, different}) == 2
+
+    def test_repr(self):
+        assert repr(Secret("env", "name", "secret", "key")) == "Secret(env, 
NAME, secret, key)"
+
+    def test_attach_to_pod_does_not_mutate_input(self):
+        pod = 
k8s.V1Pod(spec=k8s.V1PodSpec(containers=[k8s.V1Container(name="base")]))
+
+        result = Secret("env", None, "secret_a").attach_to_pod(pod)
+
+        assert result.spec.containers[0].env_from == [
+            
k8s.V1EnvFromSource(secret_ref=k8s.V1SecretEnvSource(name="secret_a"))
+        ]
+        assert pod.spec.containers[0].env_from is None
+
     def test_to_env_secret(self):
         secret = Secret("env", "name", "secret", "key")
         assert secret.to_env_secret() == k8s.V1EnvVar(

Reply via email to