def __init__(self, job_control: proto_control.JobControl, benchmark_name: str) -> None: """Initialize the Base Benchmark class. Args: job_control: The protobuf object containing the parameters and locations of benchmark artifacts benchmark_name: The name of the benchmark to execute Raises: BaseBenchmarkError: if no job control object is specified """ if job_control is None: raise BenchmarkError("No control object received") self._docker_image = docker_image.DockerImage() self._control = job_control self._benchmark_name = benchmark_name self._mode_remote = self._control.remote self._build_envoy = False self._build_nighthawk = False log.debug(f"Running benchmark: %s {self._benchmark_name} [{self}]", "Remote" if self._mode_remote else "Local")
def build_missing_envoy_docker_image( manager: source_manager.SourceManager, envoy_image_tag: str) -> None: """Builds an image for a commit hash if no image exists. Check available image tags and build an Envoy image if none exists. If there are bazel options specified then we will generate a custom image built using these options. Args: manager: A SourceManager object that is a wrapper for git operations. The source manager can navigate the commit hashes or tags to determine the endpoints for the benchmark envoy_image_tag: A commit hash or tag for which we need to build an envoy_image """ have_build_options = manager.have_build_options( proto_source.SourceRepository.SourceIdentity.SRCID_ENVOY) log.debug(f"Build options exist?: {have_build_options}") # Determine whether the image we need already exists on the local system existing_images = [] if not have_build_options: new_docker_image = docker_image.DockerImage() existing_images = new_docker_image.list_images() log.debug(f"Existing image tags: {existing_images}") image_name = generate_envoy_image_name_from_tag(envoy_image_tag) if image_name not in existing_images: build_envoy_docker_image(manager, envoy_image_tag)
def test_get_client(mock_docker): """Verify that we can return a reference to the instantiated docker client. """ mock_docker.return_value = mock.Mock() new_docker_image = docker_image.DockerImage() docker_client = new_docker_image.get_docker_client() assert docker_client
def test_pull_image(mock_pull, mock_list_images): """Verify that we can pull a docker image specifying only its name and tag. """ mock_list_images.return_value = [] mock_pull.return_value = mock.MagicMock() new_docker_image = docker_image.DockerImage() container = new_docker_image.pull_image("amazonlinux:2") assert container is not None
def test_list_images(mock_list_images): """Verify that we can list all existing cached docker images.""" expected_image_tags = ['image:1', 'image:2', 'image:3'] mock_list_images.return_value = \ map(lambda tag: mock.Mock(tags=[tag]), expected_image_tags) new_docker_image = docker_image.DockerImage() images = new_docker_image.list_images() assert images == expected_image_tags
def test_pull_image_return_existing(mock_pull, mock_list_images): """Verify that we return an existing image if it is already local instead of re-pulling it. """ mock_list_images.return_value = ['amazonlinux:2'] mock_pull.return_value = mock.MagicMock() new_docker_image = docker_image.DockerImage() container = new_docker_image.pull_image("amazonlinux:2") assert container is not None
def test_stop_image(): """Verify that we invoke the proper call to stop a docker image.""" test_image_name = "some_random_running_docker_image" mock_container = docker.models.containers.Container() mock_container.stop = mock.MagicMock(return_value=None) new_docker_image = docker_image.DockerImage() with mock.patch('docker.models.containers.ContainerCollection.get', mock.MagicMock(return_value=mock_container)) \ as image_get_mock: new_docker_image.stop_image(test_image_name) image_get_mock.assert_called_once_with(test_image_name) mock_container.stop.assert_called_once()
def test_pull_image_fail(mock_pull, mock_list_images): """Verify that an exception is raised if we are not able to successfully pull a docker image """ mock_list_images.return_value = [] mock_pull.side_effect = pull_exceptions_side_effect new_docker_image = docker_image.DockerImage() container = None with pytest.raises(docker_image.DockerImagePullError) as not_found: container = new_docker_image.pull_image("NotFound") assert not container assert str(not_found.value) == "image_not_found" with pytest.raises(docker_image.DockerImagePullError) as http_error: container = new_docker_image.pull_image("HttpError") assert not container assert str(http_error.value) == "http_retrieval_failed"
def test_list_processes(): """Verify that we can list running images.""" expected_name_list = ["prefix/image_1", "prefix/image_2", "prefix/image_3"] expected_image_list = [] for image_name in expected_name_list: mock_container = mock.Mock() mock_container.name = image_name expected_image_list.append(mock_container) image_filter = {'status': 'running'} new_docker_image = docker_image.DockerImage() with mock.patch('docker.models.containers.ContainerCollection.list', mock.MagicMock(return_value=expected_image_list)) \ as image_list_mock: image_list = new_docker_image.list_processes() image_list_mock.assert_called_once_with(filters=image_filter) assert image_list == expected_name_list
def _pull_or_build_envoy_images_for_benchmark( self, image_hashes: Set[str]) -> Set[str]: """Pull the docker images needed for the benchmarks. If an image is not available build it. Args: image_hashes: The envoy image hashes that we are locating images Returns: a Set of envoy image tags required for the benchmark: eg ["envoyproxy/envoy:v1.X.X", ...] """ have_build_options = self._source_manager.have_build_options( proto_source.SourceRepository.SourceIdentity.SRCID_ENVOY) envoy_images = set() image_manager = docker_image.DockerImage() log.debug(f"Finding matching images for hashes: {image_hashes}") for image_hash in image_hashes: image_prefix = docker_image_builder.get_envoy_image_prefix( image_hash) envoy_image = "{prefix}:{hash}".format(prefix=image_prefix, hash=image_hash) image_object = None try: image_object = image_manager.pull_image(envoy_image) except docker_image.DockerImagePullError: log.error(f"Image pull failed for {envoy_image}") if have_build_options or not image_object: log.debug(f"Attempting to build {envoy_image}") docker_image_builder.build_envoy_image_from_source( self._source_manager, image_hash) envoy_images.add(envoy_image) return envoy_images
def _pull_or_build_nh_binary_image( self, images: proto_image.DockerImages) -> None: """Attempt to pull the NightHawk Binary Image. Build it if it is unavailable. Args: images: the DockerImages appearing in the control object """ pull_result = False try: image_manager = docker_image.DockerImage() pull_result = image_manager.pull_image( images.nighthawk_binary_image) except docker_image.DockerImagePullError: log.error(f"Image pull failed for {images.nighthawk_binary_image}") if not pull_result: log.debug(f"Attempting to build {images.nighthawk_binary_image}") docker_image_builder.build_nighthawk_binary_image_from_source( self._source_manager)
def test_run_image(mock_docker_run, mock_docker_list, mock_docker_stop): """Verify that we execute the specified docker image""" # Mock the actual docker client invocation to return output from the container mock_docker_output = "docker output" mock_docker_run.return_value = mock_docker_output mock_docker_list.return_value = ['dummy_image'] mock_docker_stop.return_value = None new_docker_image = docker_image.DockerImage() run_parameters = docker_image.DockerRunParameters( environment={}, command='bash', volumes={}, network_mode='host', tty=False, ) assert new_docker_image.run_image('test_image', run_parameters) == \ mock_docker_output mock_docker_run.assert_called_once_with('test_image', stdout=True, stderr=True, detach=False, **run_parameters._asdict())