Skip to content

Commit

Permalink
Add basic container_service_test as a building block
Browse files Browse the repository at this point in the history
PiperOrigin-RevId: 708086780
  • Loading branch information
Zach Howell authored and copybara-github committed Dec 20, 2024
1 parent 738904a commit 2d65cda
Show file tree
Hide file tree
Showing 5 changed files with 116 additions and 4 deletions.
6 changes: 5 additions & 1 deletion perfkitbenchmarker/container_service.py
Original file line number Diff line number Diff line change
Expand Up @@ -177,14 +177,18 @@ def RunRetryableKubectlCommand(
# IssueCommand defaults stack_level to 1, so 2 skips this function.
kwargs['stack_level'] = 2

@vm_util.Retry(timeout=timeout, retryable_exceptions=(RetryableKubectlError,))
@vm_util.Retry(
timeout=timeout,
retryable_exceptions=(RetryableKubectlError,),
)
def _RunRetryablePart(run_cmd: list[str], **kwargs):
"""Inner function retries command so timeout can be passed to decorator."""
kwargs['stack_level'] += 1
out, err, code = RunKubectlCommand(
run_cmd, raise_on_failure=False, **kwargs
)
if err:
logging.warning('Got error %s when running %s', err, run_cmd)
for error_substring in _RETRYABLE_KUBECTL_ERRORS:
if error_substring in err:
raise RetryableKubectlError(
Expand Down
4 changes: 3 additions & 1 deletion perfkitbenchmarker/provider_info.py
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,8 @@
# Though Docker is not a cloud provider, it's inclusion is useful
# for performing on premise to cloud benchmarks
DOCKER = 'Docker'
# Likewise, UnitTest is not a cloud provider, but is useful for testing.
UNIT_TEST = 'UnitTest'

PROVIDER_DIRECTORY_NAMES = (
GCP,
Expand All @@ -52,7 +54,7 @@
DOCKER,
)
# TODO(user): Remove Kubernetes from VALID_CLOUDS.
VALID_CLOUDS = tuple(list(PROVIDER_DIRECTORY_NAMES) + [KUBERNETES])
VALID_CLOUDS = tuple(list(PROVIDER_DIRECTORY_NAMES) + [KUBERNETES, UNIT_TEST])

_PROVIDER_INFO_REGISTRY = {}

Expand Down
86 changes: 86 additions & 0 deletions tests/container_service_test.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,86 @@
import unittest
from unittest import mock
from absl.testing import flagsaver
from perfkitbenchmarker import container_service
from perfkitbenchmarker import errors
from perfkitbenchmarker import provider_info
from perfkitbenchmarker.configs import container_spec
from tests import pkb_common_test_case


# Use Mesos as a valid cloud we can override the implementation for.
_CLUSTER_CLOUD = provider_info.UNIT_TEST


class TestKubernetesCluster(container_service.KubernetesCluster):

CLOUD = _CLUSTER_CLOUD

def _Create(self):
pass

def _Delete(self):
pass


class ContainerServiceTest(pkb_common_test_case.PkbCommonTestCase):

def setUp(self):
super().setUp()
self.enter_context(flagsaver.flagsaver(kubeconfig='kubeconfig'))
self.enter_context(flagsaver.flagsaver(run_uri='123'))
self.kubernetes_cluster = TestKubernetesCluster(
container_spec.ContainerClusterSpec(
'test-cluster',
**{
'cloud': _CLUSTER_CLOUD,
'vm_spec': {
_CLUSTER_CLOUD: {
'machine_type': 'fake-machine-type',
'zone': 'us-east2-a',
},
},
},
)
)

def test_apply_manifest_gets_deployment_name(self):
self.MockIssueCommand(
{'apply -f': [('deployment.apps/test-deployment created', '', 0)]}
)
self.enter_context(
mock.patch.object(
container_service.data,
'ResourcePath',
return_value='path/to/test-deployment.yaml',
)
)
deploy_ids = self.kubernetes_cluster.ApplyManifest(
'test-deployment.yaml',
)
self.assertEqual(next(deploy_ids), 'deployment.apps/test-deployment')

def test_retriable_kubectl_command_fails_on_random_error(self):
self.MockIssueCommand(
{'get podpatchwork': [('', 'error: invalid syntax', 1)]}
)
with self.assertRaises(errors.VmUtil.IssueCommandError):
container_service.RunRetryableKubectlCommand(['get', 'podpatchwork'])

def test_retriable_kubectl_command_retries_on_connection_reset(self):
self.MockIssueCommand({
'get pods': [
('', 'error: read: connection reset by peer', 1),
('pod1, pod2', '', 0),
]
})
out, err, ret = container_service.RunRetryableKubectlCommand(
['get', 'pods']
)
self.assertEqual(out, 'pod1, pod2')
self.assertEqual(err, '')
self.assertEqual(ret, 0)


if __name__ == '__main__':
unittest.main()
12 changes: 11 additions & 1 deletion tests/mock_command.py
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@
"""

import collections
import logging
from unittest import mock
from absl.testing import absltest
from perfkitbenchmarker import virtual_machine
Expand Down Expand Up @@ -72,7 +73,16 @@ def mock_remote_command(self, cmd: str | list[str], **kwargs) -> ReturnValues:
"""Mocks a command, returning the next response for the command."""
del kwargs # Unused but matches type signature.
if isinstance(cmd, list):
cmd = ' '.join(cmd)
try:
cmd = ' '.join(cmd)
except TypeError as ex:
logging.warning(
'Tried joining command %s but not all elements were strings. Got'
' exception: %s',
cmd,
ex,
)
raise ex
for call in self.call_to_response:
if call in cmd:
call_num = self.progress_through_calls[call]
Expand Down
12 changes: 11 additions & 1 deletion tests/pkb_common_test_case.py
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@
from perfkitbenchmarker import linux_virtual_machine
from perfkitbenchmarker import os_mixin
from perfkitbenchmarker import pkb # pylint:disable=unused-import
from perfkitbenchmarker import provider_info
from perfkitbenchmarker import resource
from perfkitbenchmarker import virtual_machine
from perfkitbenchmarker.configs import benchmark_config_spec
Expand Down Expand Up @@ -170,7 +171,7 @@ class TestVirtualMachine(
):
"""Test class that has dummy methods for a base virtual machine."""

CLOUD = 'test_vm_cloud'
CLOUD = provider_info.UNIT_TEST

def _Start(self):
pass
Expand All @@ -188,6 +189,15 @@ def GetConnectionIp(self):
pass


class UbuntuTestVirtualMachine(
TestVirtualMachine
):
"""Test class that has dummy methods for a base virtual machine."""

CLOUD = provider_info.UNIT_TEST
OS_TYPE = 'ubuntu2404'


# Need to provide implementations for all of the abstract methods in
# order to instantiate linux_virtual_machine.BaseLinuxMixin.
class TestLinuxVirtualMachine(
Expand Down

0 comments on commit 2d65cda

Please sign in to comment.