This is an automated email from the ASF dual-hosted git repository.

rom 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 2c67c9fb29 Add missing test for kubernetes compat converters (#43248)
2c67c9fb29 is described below

commit 2c67c9fb29f3c1919b6cf437b5f32061d42758d6
Author: yangyulely <[email protected]>
AuthorDate: Fri Nov 1 18:07:43 2024 +0800

    Add missing test for kubernetes compat converters (#43248)
---
 .../tests/cncf/kubernetes/backcompat/__init__.py   |  16 ++
 .../backcompat/test_backwards_compat_converters.py | 270 +++++++++++++++++++++
 tests/always/test_project_structure.py             |   1 -
 3 files changed, 286 insertions(+), 1 deletion(-)

diff --git a/providers/tests/cncf/kubernetes/backcompat/__init__.py 
b/providers/tests/cncf/kubernetes/backcompat/__init__.py
new file mode 100644
index 0000000000..13a83393a9
--- /dev/null
+++ b/providers/tests/cncf/kubernetes/backcompat/__init__.py
@@ -0,0 +1,16 @@
+# 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/tests/cncf/kubernetes/backcompat/test_backwards_compat_converters.py
 
b/providers/tests/cncf/kubernetes/backcompat/test_backwards_compat_converters.py
new file mode 100644
index 0000000000..7c4e426b48
--- /dev/null
+++ 
b/providers/tests/cncf/kubernetes/backcompat/test_backwards_compat_converters.py
@@ -0,0 +1,270 @@
+# 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.mock import Mock, patch
+
+import pytest
+from kubernetes.client import models as k8s
+
+from airflow.exceptions import AirflowException
+from airflow.providers.cncf.kubernetes.backcompat.backwards_compat_converters 
import (
+    _convert_from_dict,
+    _convert_kube_model_object,
+    convert_affinity,
+    convert_configmap,
+    convert_env_vars,
+    convert_env_vars_or_raise_error,
+    convert_image_pull_secrets,
+    convert_pod_runtime_info_env,
+    convert_port,
+    convert_toleration,
+    convert_volume,
+    convert_volume_mount,
+)
+
+
+# testcase of _convert_kube_model_object() function
+class MockKubeModelObject:
+    def to_k8s_client_obj(self):
+        return "converted_object"
+
+
+def test__convert_kube_model_object_normal_value():
+    obj = MockKubeModelObject()
+    new_class = type(obj)
+
+    result = _convert_kube_model_object(obj, new_class)
+    assert result == "converted_object"
+
+
+def test__convert_kube_model_object_already_instance():
+    result = _convert_kube_model_object("obj", str)
+    assert result == "obj"
+
+
+def test__convert_kube_model_object_invalid_type():
+    obj = "obj"
+    with pytest.raises(AirflowException) as exc_info:
+        _convert_kube_model_object(obj, int)
+
+    assert str(exc_info.value) == f"Expected {int}, got {type(obj)}"
+
+
+# testcase of _convert_from_dict() function
[email protected]
+def mock_api_client():
+    with patch(
+        
"airflow.providers.cncf.kubernetes.backcompat.backwards_compat_converters.ApiClient"
+    ) as mock_class:
+        instance = mock_class.return_value
+        instance._ApiClient__deserialize_model = 
Mock(return_value="mocked_instance")
+        yield instance
+
+
+def test_convert_from_dict_with_new_class_instance(mock_api_client):
+    obj = Mock()
+    result = _convert_from_dict(obj, type(obj))
+
+    assert result == obj
+
+
+def test_convert_from_dict_with_dict(mock_api_client):
+    obj = {"key": "value"}
+    new_class = Mock()
+    result = _convert_from_dict(obj, type(new_class))
+
+    mock_api_client._ApiClient__deserialize_model.assert_called_once_with(obj, 
type(new_class))
+    assert result == "mocked_instance"
+
+
+def test_convert_from_dict_with_invalid_type():
+    obj = "not a dict"
+    new_class = Mock()
+
+    with pytest.raises(AirflowException) as exc_info:
+        _convert_from_dict(obj, type(new_class))
+
+    assert str(exc_info.value) == "Expected dict or <class 
'unittest.mock.Mock'>, got <class 'str'>"
+
+
+# testcase of convert_volume() function
+@patch("airflow.providers.cncf.kubernetes.backcompat.backwards_compat_converters._convert_kube_model_object")
+def test_convert_volume_normal_value(mock_convert_kube_model_object):
+    mock_convert_kube_model_object.return_value = 
k8s.V1Volume(name="test_convert_volume")
+    volume = Mock()
+    result = convert_volume(volume)
+
+    mock_convert_kube_model_object.assert_called_once_with(volume, 
k8s.V1Volume)
+    assert result.name == "test_convert_volume"
+
+
+# testcase of convert_volume_mount() function
+@patch("airflow.providers.cncf.kubernetes.backcompat.backwards_compat_converters._convert_kube_model_object")
+def test_convert_volume_mount_normal_value(mock_convert_kube_model_object):
+    mock_convert_kube_model_object.return_value = k8s.V1VolumeMount(
+        name="test_volume_mount", mount_path="/mnt/test"
+    )
+    volume = Mock()
+    result = convert_volume_mount(volume)
+
+    mock_convert_kube_model_object.assert_called_once_with(volume, 
k8s.V1VolumeMount)
+    assert result.name == "test_volume_mount"
+    assert result.mount_path == "/mnt/test"
+
+
+# testcase of convert_port() function
+@patch("airflow.providers.cncf.kubernetes.backcompat.backwards_compat_converters._convert_kube_model_object")
+def test_convert_port_normal_value(mock_convert_kube_model_object):
+    mock_convert_kube_model_object.return_value = 
k8s.V1ContainerPort(container_port=80)
+    volume = Mock()
+    result = convert_port(volume)
+
+    mock_convert_kube_model_object.assert_called_once_with(volume, 
k8s.V1ContainerPort)
+    assert result.container_port == 80
+
+
+# testcase of convert_env_vars() function
+def test_convert_env_vars_with_dict():
+    # Normal value input case test
+    env_vars = {"FOO": "bar", "BAZ": "qux"}
+    result = convert_env_vars(env_vars)
+    expected_result = [k8s.V1EnvVar(name="FOO", value="bar"), 
k8s.V1EnvVar(name="BAZ", value="qux")]
+
+    assert isinstance(result, list)
+    assert len(result) == 2
+    assert result == expected_result
+
+
+def test_convert_env_vars_with_list():
+    # Normal value input case test
+    env_vars = [k8s.V1EnvVar(name="FOO", value="bar"), 
k8s.V1EnvVar(name="BAZ", value="qux")]
+
+    result = convert_env_vars(env_vars)
+    assert result == env_vars
+
+
+# testcase of convert_env_vars_or_raise_error() function
+def test_convert_env_vars_or_raise_error_normal_value():
+    env_vars_dict = {"ENV1": "value1", "ENV2": "value2"}
+    result = convert_env_vars_or_raise_error(env_vars_dict)
+
+    assert isinstance(result, list)
+    assert len(result) == 2
+    assert result[0].name == "ENV1"
+    assert result[0].value == "value1"
+    assert result[1].name == "ENV2"
+    assert result[1].value == "value2"
+
+
+def test_convert_env_vars_or_raise_error_list_value():
+    env_vars_list = [k8s.V1EnvVar(name="ENV1", value="value1"), 
k8s.V1EnvVar(name="ENV2", value="value2")]
+    result = convert_env_vars_or_raise_error(env_vars_list)
+
+    assert isinstance(result, list)
+    assert len(result) == 2
+    assert result[0].name == "ENV1"
+    assert result[0].value == "value1"
+    assert result[1].name == "ENV2"
+    assert result[1].value == "value2"
+    assert result == env_vars_list
+
+
+def test_convert_env_vars_or_raise_error_invalid_type():
+    invalid_input = 123
+    with pytest.raises(AirflowException) as exc_info:
+        convert_env_vars_or_raise_error(invalid_input)
+
+    assert str(exc_info.value) == f"Expected dict or list, got 
{type(invalid_input)}"
+
+
+# testcase of convert_pod_runtime_info_env() function
+@patch("airflow.providers.cncf.kubernetes.backcompat.backwards_compat_converters._convert_kube_model_object")
+def 
test_convert_pod_runtime_info_env_normal_value(mock_convert_kube_model_object):
+    mock_convert_kube_model_object.return_value = k8s.V1EnvVar(name="FOO", 
value="bar")
+    volume = Mock()
+    result = convert_pod_runtime_info_env(volume)
+
+    mock_convert_kube_model_object.assert_called_once_with(volume, 
k8s.V1EnvVar)
+    assert result.name == "FOO"
+    assert result.value == "bar"
+
+
+# testcase of convert_image_pull_secrets() function
+def test_convert_image_pull_secrets_normal_value():
+    image_pull_secrets = "secret1,secret2,secret3"
+    result = convert_image_pull_secrets(image_pull_secrets)
+
+    expected_result = [
+        k8s.V1LocalObjectReference(name="secret1"),
+        k8s.V1LocalObjectReference(name="secret2"),
+        k8s.V1LocalObjectReference(name="secret3"),
+    ]
+    assert isinstance(result, list)
+    assert len(result) == 3
+    assert result == expected_result
+
+
+def test_convert_image_pull_secrets_not_string():
+    image_pull_secrets = ["single_secret"]
+    result = convert_image_pull_secrets(image_pull_secrets)
+
+    assert isinstance(result, list)
+    assert len(result) == 1
+    assert result == image_pull_secrets
+
+
+# testcase of convert_configmap() function
+def test_convert_configmap_normal_value():
+    configmaps = "test-configmap"
+    result = convert_configmap(configmaps)
+
+    assert isinstance(result, k8s.V1EnvFromSource)
+    assert result.config_map_ref.name == "test-configmap"
+
+
+# testcase of convert_affinity() function
+@patch("airflow.providers.cncf.kubernetes.backcompat.backwards_compat_converters._convert_from_dict")
+def test_convert_affinity_normal_value(mock_convert_from_dict):
+    affinity = {"some_key": "some_value"}
+    expected_result = Mock(k8s.V1Affinity)
+    mock_convert_from_dict.return_value = expected_result
+
+    result = convert_affinity(affinity)
+
+    mock_convert_from_dict.assert_called_once_with(affinity, k8s.V1Affinity)
+    assert result == expected_result
+
+
+# testcase of convert_toleration() function
+@patch("airflow.providers.cncf.kubernetes.backcompat.backwards_compat_converters._convert_from_dict")
+def test_convert_toleration_normal_value(mock_convert_from_dict):
+    toleration = {
+        "key": "key",
+        "operator": "Equal",
+        "value": "value",
+        "effect": "NoExecute",
+        "toleration_seconds": 600,
+    }
+    expected_result = Mock(spec=k8s.V1Toleration)
+    mock_convert_from_dict.return_value = expected_result
+
+    result = convert_toleration(toleration)
+
+    mock_convert_from_dict.assert_called_once_with(toleration, 
k8s.V1Toleration)
+    assert isinstance(result, k8s.V1Toleration)
+    assert result == expected_result
diff --git a/tests/always/test_project_structure.py 
b/tests/always/test_project_structure.py
index 38b5bccba4..683fa7ce79 100644
--- a/tests/always/test_project_structure.py
+++ b/tests/always/test_project_structure.py
@@ -85,7 +85,6 @@ class TestProjectStructure:
             "providers/tests/celery/executors/test_celery_executor_utils.py",
             "providers/tests/celery/executors/test_default_celery.py",
             "providers/tests/cloudant/test_cloudant_fake.py",
-            
"providers/tests/cncf/kubernetes/backcompat/test_backwards_compat_converters.py",
             
"providers/tests/cncf/kubernetes/executors/test_kubernetes_executor_types.py",
             
"providers/tests/cncf/kubernetes/executors/test_kubernetes_executor_utils.py",
             "providers/tests/cncf/kubernetes/operators/test_kubernetes_pod.py",

Reply via email to