incubator-airflow/tests/kubernetes/test_pod_launcher.py

191 строка
7.7 KiB
Python

# 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.
import unittest
from unittest import mock
from requests.exceptions import BaseHTTPError
from airflow.exceptions import AirflowException
from airflow.kubernetes.pod_launcher import PodLauncher
class TestPodLauncher(unittest.TestCase):
def setUp(self):
self.mock_kube_client = mock.Mock()
self.pod_launcher = PodLauncher(kube_client=self.mock_kube_client)
def test_read_pod_logs_successfully_returns_logs(self):
mock.sentinel.metadata = mock.MagicMock()
self.mock_kube_client.read_namespaced_pod_log.return_value = mock.sentinel.logs
logs = self.pod_launcher.read_pod_logs(mock.sentinel)
self.assertEqual(mock.sentinel.logs, logs)
def test_read_pod_logs_retries_successfully(self):
mock.sentinel.metadata = mock.MagicMock()
self.mock_kube_client.read_namespaced_pod_log.side_effect = [
BaseHTTPError('Boom'),
mock.sentinel.logs,
]
logs = self.pod_launcher.read_pod_logs(mock.sentinel)
self.assertEqual(mock.sentinel.logs, logs)
self.mock_kube_client.read_namespaced_pod_log.assert_has_calls(
[
mock.call(
_preload_content=False,
container='base',
follow=True,
timestamps=False,
name=mock.sentinel.metadata.name,
namespace=mock.sentinel.metadata.namespace,
),
mock.call(
_preload_content=False,
container='base',
follow=True,
timestamps=False,
name=mock.sentinel.metadata.name,
namespace=mock.sentinel.metadata.namespace,
),
]
)
def test_read_pod_logs_retries_fails(self):
mock.sentinel.metadata = mock.MagicMock()
self.mock_kube_client.read_namespaced_pod_log.side_effect = [
BaseHTTPError('Boom'),
BaseHTTPError('Boom'),
BaseHTTPError('Boom'),
]
self.assertRaises(AirflowException, self.pod_launcher.read_pod_logs, mock.sentinel)
def test_read_pod_logs_successfully_with_tail_lines(self):
mock.sentinel.metadata = mock.MagicMock()
self.mock_kube_client.read_namespaced_pod_log.side_effect = [mock.sentinel.logs]
logs = self.pod_launcher.read_pod_logs(mock.sentinel, tail_lines=100)
self.assertEqual(mock.sentinel.logs, logs)
self.mock_kube_client.read_namespaced_pod_log.assert_has_calls(
[
mock.call(
_preload_content=False,
container='base',
follow=True,
timestamps=False,
name=mock.sentinel.metadata.name,
namespace=mock.sentinel.metadata.namespace,
tail_lines=100,
),
]
)
def test_read_pod_logs_successfully_with_since_seconds(self):
mock.sentinel.metadata = mock.MagicMock()
self.mock_kube_client.read_namespaced_pod_log.side_effect = [mock.sentinel.logs]
logs = self.pod_launcher.read_pod_logs(mock.sentinel, since_seconds=2)
self.assertEqual(mock.sentinel.logs, logs)
self.mock_kube_client.read_namespaced_pod_log.assert_has_calls(
[
mock.call(
_preload_content=False,
container='base',
follow=True,
timestamps=False,
name=mock.sentinel.metadata.name,
namespace=mock.sentinel.metadata.namespace,
since_seconds=2,
),
]
)
def test_read_pod_events_successfully_returns_events(self):
mock.sentinel.metadata = mock.MagicMock()
self.mock_kube_client.list_namespaced_event.return_value = mock.sentinel.events
events = self.pod_launcher.read_pod_events(mock.sentinel)
self.assertEqual(mock.sentinel.events, events)
def test_read_pod_events_retries_successfully(self):
mock.sentinel.metadata = mock.MagicMock()
self.mock_kube_client.list_namespaced_event.side_effect = [
BaseHTTPError('Boom'),
mock.sentinel.events,
]
events = self.pod_launcher.read_pod_events(mock.sentinel)
self.assertEqual(mock.sentinel.events, events)
self.mock_kube_client.list_namespaced_event.assert_has_calls(
[
mock.call(
namespace=mock.sentinel.metadata.namespace,
field_selector=f"involvedObject.name={mock.sentinel.metadata.name}",
),
mock.call(
namespace=mock.sentinel.metadata.namespace,
field_selector=f"involvedObject.name={mock.sentinel.metadata.name}",
),
]
)
def test_read_pod_events_retries_fails(self):
mock.sentinel.metadata = mock.MagicMock()
self.mock_kube_client.list_namespaced_event.side_effect = [
BaseHTTPError('Boom'),
BaseHTTPError('Boom'),
BaseHTTPError('Boom'),
]
self.assertRaises(AirflowException, self.pod_launcher.read_pod_events, mock.sentinel)
def test_read_pod_returns_logs(self):
mock.sentinel.metadata = mock.MagicMock()
self.mock_kube_client.read_namespaced_pod.return_value = mock.sentinel.pod_info
pod_info = self.pod_launcher.read_pod(mock.sentinel)
self.assertEqual(mock.sentinel.pod_info, pod_info)
def test_read_pod_retries_successfully(self):
mock.sentinel.metadata = mock.MagicMock()
self.mock_kube_client.read_namespaced_pod.side_effect = [
BaseHTTPError('Boom'),
mock.sentinel.pod_info,
]
pod_info = self.pod_launcher.read_pod(mock.sentinel)
self.assertEqual(mock.sentinel.pod_info, pod_info)
self.mock_kube_client.read_namespaced_pod.assert_has_calls(
[
mock.call(mock.sentinel.metadata.name, mock.sentinel.metadata.namespace),
mock.call(mock.sentinel.metadata.name, mock.sentinel.metadata.namespace),
]
)
def test_read_pod_retries_fails(self):
mock.sentinel.metadata = mock.MagicMock()
self.mock_kube_client.read_namespaced_pod.side_effect = [
BaseHTTPError('Boom'),
BaseHTTPError('Boom'),
BaseHTTPError('Boom'),
]
self.assertRaises(AirflowException, self.pod_launcher.read_pod, mock.sentinel)
def test_parse_log_line(self):
timestamp, message = self.pod_launcher.parse_log_line(
'2020-10-08T14:16:17.793417674Z Valid message\n'
)
self.assertEqual(timestamp, '2020-10-08T14:16:17.793417674Z')
self.assertEqual(message, 'Valid message')
self.assertRaises(
Exception,
self.pod_launcher.parse_log_line('2020-10-08T14:16:17.793417674ZInvalid message\n'),
)