def test_get_docker_ps(self, mockLogging, mockClient): """ Assert that the docker_ps task calls the docker client.containers() function. """ containers = [{'Id': 'Aaa', 'Status': 'Running'}, {'Id': 'Bbb', 'Status': 'Host Down'}, {'Id': 'Ccc', 'Status': 'Up'}, ] def inspect(container=''): if container == 'Ccc': raise else: return {'Id': container, 'Config': {'Labels': {'type': 'preprocess'}}} mockClient.return_value.containers.return_value = containers mockClient.return_value.inspect_container.side_effect = inspect get_docker_ps.delay() # Call docker ps for all containers, but only once mockClient.return_value.containers.assert_called_with(all=True) self.assertEqual(mockClient.return_value.containers.call_count, 1) # Call inspect for all but Host Down container self.assertEqual( mockClient.return_value.inspect_container.call_count, 2) # Log error only for Ccc container self.assertEqual(mockLogging.call_count, 1)
def _get_latest_docker_status(self): """ Synchronise local Django Container models with remote Docker containers """ ps = get_docker_ps.delay() containers_docker = None try: containers_docker = ps.get(timeout=30) except celery.exceptions.TimeoutError as e: logging.exception("get_docker_ps timed out (30 seconds)") if containers_docker is None: # Apparently something is wrong with the remote docker or celery # To prevent new task creation by Containers exit beat. return docker_dict = {x['Id']: x for x in containers_docker} docker_set = set(docker_dict.keys()) # retrieve container from database container_set = set( Container.objects.values_list('docker_id', flat=True)) # Work out matching matrix # docker yes non # model x # yes 1_1 1_0 # no 0_1 0_0 # m_1_1 = container_set & docker_set m_1_0 = container_set - docker_set m_0_1 = docker_set - container_set m_0_0 = ((docker_set | container_set) - (docker_set ^ container_set) - (docker_set & container_set) ) # Update state of all matching containers container_match = m_1_1 | m_1_0 for con_id in container_match: snapshot = docker_dict[ con_id] if con_id in docker_dict else None for c in Container.objects.filter(docker_id=con_id): c.update_from_docker_snapshot(snapshot) # Call error for mismatch container_mismatch = m_0_1 | m_0_0 for container in container_mismatch: info = docker_dict[container] if ('Config' in info and 'Labels' in info['Config'] and 'type' in info['Config']['Labels']): type = info['Config']['Labels']['type'] if type in [choice[0] for choice in Container.CONTAINER_TYPE_CHOICES]: self.stderr.write( "Docker container {} not found in database!".format(container)) do_docker_remove.delay(container, force=True) else: logging.info("Found non-delft3dgt docker container, ignoring.")
def test_get_docker_ps(self, mockLogging, mockClient): """ Assert that the docker_ps task calls the docker client.containers() function. """ containers = [ { 'Id': 'Aaa', 'Status': 'Running' }, { 'Id': 'Bbb', 'Status': 'Host Down' }, { 'Id': 'Ccc', 'Status': 'Up' }, ] def inspect(container=''): if container == 'Ccc': raise else: return { 'Id': container, 'Config': { 'Labels': { 'type': 'preprocess' } } } mockClient.return_value.containers.return_value = containers mockClient.return_value.inspect_container.side_effect = inspect get_docker_ps.delay() # Call docker ps for all containers, but only once mockClient.return_value.containers.assert_called_with(all=True) self.assertEqual(mockClient.return_value.containers.call_count, 1) # Call inspect for all but Host Down container self.assertEqual(mockClient.return_value.inspect_container.call_count, 2) # Log error only for Ccc container self.assertEqual(mockLogging.call_count, 1)