def test_project_up_with_no_recreate_stopped(self): web = self.create_service('web') db = self.create_service('db', volumes=['/var/db']) project = Project('composetest', [web, db], self.client) project.start() self.assertEqual(len(project.containers()), 0) project.up(['db']) project.kill() old_containers = project.containers(stopped=True) self.assertEqual(len(old_containers), 1) old_db_id = old_containers[0].id db_volume_path = old_containers[0].inspect()['Volumes']['/var/db'] project.up(allow_recreate=False) new_containers = project.containers(stopped=True) self.assertEqual(len(new_containers), 2) self.assertEqual([c.is_running for c in new_containers], [True, True]) db_container = [c for c in new_containers if 'db' in c.name][0] self.assertEqual(db_container.id, old_db_id) self.assertEqual(db_container.inspect()['Volumes']['/var/db'], db_volume_path) project.kill() project.remove_stopped()
def test_no_warning_in_normal_mode(self): self.mock_client.info.return_value = {'Swarm': {'LocalNodeState': 'inactive'}} project = Project('composetest', [], self.mock_client) with mock.patch('compose.project.log') as fake_log: project.up() assert fake_log.warn.call_count == 0
def test_project_up_with_no_recreate_stopped(self): web = self.create_service('web') db = self.create_service('db', volumes=[VolumeSpec.parse('/var/db')]) project = Project('composetest', [web, db], self.client) project.start() self.assertEqual(len(project.containers()), 0) project.up(['db']) project.kill() old_containers = project.containers(stopped=True) self.assertEqual(len(old_containers), 1) old_container, = old_containers old_db_id = old_container.id db_volume_path = old_container.get_mount('/var/db')['Source'] project.up(strategy=ConvergenceStrategy.never) new_containers = project.containers(stopped=True) self.assertEqual(len(new_containers), 2) self.assertEqual([c.is_running for c in new_containers], [True, True]) db_container = [c for c in new_containers if 'db' in c.name][0] self.assertEqual(db_container.id, old_db_id) self.assertEqual( db_container.get_mount('/var/db')['Source'], db_volume_path)
def test_no_warning_with_no_swarm_info(self): self.mock_client.info.return_value = {} project = Project('composetest', [], self.mock_client) with mock.patch('compose.project.log') as fake_log: project.up() assert fake_log.warn.call_count == 0
def test_project_up_with_no_recreate_stopped(self): web = self.create_service("web") db = self.create_service("db", volumes=["/var/db"]) project = Project("composetest", [web, db], self.client) project.start() self.assertEqual(len(project.containers()), 0) project.up(["db"]) project.kill() old_containers = project.containers(stopped=True) self.assertEqual(len(old_containers), 1) old_db_id = old_containers[0].id db_volume_path = old_containers[0].inspect()["Volumes"]["/var/db"] project.up(strategy=ConvergenceStrategy.never) new_containers = project.containers(stopped=True) self.assertEqual(len(new_containers), 2) self.assertEqual([c.is_running for c in new_containers], [True, True]) db_container = [c for c in new_containers if "db" in c.name][0] self.assertEqual(db_container.id, old_db_id) self.assertEqual(db_container.inspect()["Volumes"]["/var/db"], db_volume_path)
class ResilienceTest(DockerClientTestCase): def setUp(self): self.db = self.create_service("db", volumes=["/var/db"], command="top") self.project = Project("composetest", [self.db], self.client) container = self.db.create_container() self.db.start_container(container) self.host_path = container.get("Volumes")["/var/db"] def test_successful_recreate(self): self.project.up() container = self.db.containers()[0] self.assertEqual(container.get("Volumes")["/var/db"], self.host_path) def test_create_failure(self): with mock.patch("compose.service.Service.create_container", crash): with self.assertRaises(Crash): self.project.up() self.project.up() container = self.db.containers()[0] self.assertEqual(container.get("Volumes")["/var/db"], self.host_path) def test_start_failure(self): with mock.patch("compose.service.Service.start_container", crash): with self.assertRaises(Crash): self.project.up() self.project.up() container = self.db.containers()[0] self.assertEqual(container.get("Volumes")["/var/db"], self.host_path)
class ResilienceTest(DockerClientTestCase): def setUp(self): self.db = self.create_service( 'db', volumes=[VolumeSpec.parse('/var/db')], command='top') self.project = Project('composetest', [self.db], self.client) container = self.db.create_container() container.start() self.host_path = container.get_mount('/var/db')['Source'] def test_successful_recreate(self): self.project.up(strategy=ConvergenceStrategy.always) container = self.db.containers()[0] self.assertEqual(container.get_mount('/var/db')['Source'], self.host_path) def test_create_failure(self): with mock.patch('compose.service.Service.create_container', crash): with self.assertRaises(Crash): self.project.up(strategy=ConvergenceStrategy.always) self.project.up() container = self.db.containers()[0] self.assertEqual(container.get_mount('/var/db')['Source'], self.host_path) def test_start_failure(self): with mock.patch('compose.container.Container.start', crash): with self.assertRaises(Crash): self.project.up(strategy=ConvergenceStrategy.always) self.project.up() container = self.db.containers()[0] self.assertEqual(container.get_mount('/var/db')['Source'], self.host_path)
class ResilienceTest(DockerClientTestCase): def setUp(self): self.db = self.create_service('db', volumes=['/var/db'], command='top') self.project = Project('composetest', [self.db], self.client) container = self.db.create_container() self.db.start_container(container) self.host_path = container.get('Volumes')['/var/db'] def test_successful_recreate(self): self.project.up(force_recreate=True) container = self.db.containers()[0] self.assertEqual(container.get('Volumes')['/var/db'], self.host_path) def test_create_failure(self): with mock.patch('compose.service.Service.create_container', crash): with self.assertRaises(Crash): self.project.up(force_recreate=True) self.project.up() container = self.db.containers()[0] self.assertEqual(container.get('Volumes')['/var/db'], self.host_path) def test_start_failure(self): with mock.patch('compose.service.Service.start_container', crash): with self.assertRaises(Crash): self.project.up(force_recreate=True) self.project.up() container = self.db.containers()[0] self.assertEqual(container.get('Volumes')['/var/db'], self.host_path)
def test_containers(self): web = self.create_service('web') db = self.create_service('db') project = Project('composetest', [web, db], self.client) project.up() containers = project.containers() self.assertEqual(len(containers), 2)
def test_containers(self): web = self.create_service("web") db = self.create_service("db") project = Project("composetest", [web, db], self.client) project.up() containers = project.containers() self.assertEqual(len(containers), 2)
def test_containers_with_service_names(self): web = self.create_service("web") db = self.create_service("db") project = Project("composetest", [web, db], self.client) project.up() containers = project.containers(["web"]) self.assertEqual([c.name for c in containers], ["composetest_web_1"])
def test_project_up(self): web = self.create_service('web') db = self.create_service('db', volumes=[VolumeSpec.parse('/var/db')]) project = Project('composetest', [web, db], self.client) project.start() self.assertEqual(len(project.containers()), 0) project.up(['db']) self.assertEqual(len(project.containers()), 1) self.assertEqual(len(db.containers()), 1) self.assertEqual(len(web.containers()), 0)
def test_project_up_without_all_services(self): console = self.create_service('console') db = self.create_service('db') project = Project('composetest', [console, db], self.client) project.start() self.assertEqual(len(project.containers()), 0) project.up() self.assertEqual(len(project.containers()), 2) self.assertEqual(len(db.containers()), 1) self.assertEqual(len(console.containers()), 1)
def test_containers_with_service_names(self): web = self.create_service('web') db = self.create_service('db') project = Project('composetest', [web, db], self.client) project.up() containers = project.containers(['web']) self.assertEqual( [c.name for c in containers], ['composetest_web_1'])
def test_project_up_starts_uncreated_services(self): db = self.create_service('db') web = self.create_service('web', links=[(db, 'db')]) project = Project('composetest', [db, web], self.client) project.up(['db']) self.assertEqual(len(project.containers()), 1) project.up() self.assertEqual(len(project.containers()), 2) self.assertEqual(len(db.containers()), 1) self.assertEqual(len(web.containers()), 1)
def test_project_up_starts_uncreated_services(self): db = self.create_service("db") web = self.create_service("web", links=[(db, "db")]) project = Project("composetest", [db, web], self.client) project.up(["db"]) self.assertEqual(len(project.containers()), 1) project.up() self.assertEqual(len(project.containers()), 2) self.assertEqual(len(db.containers()), 1) self.assertEqual(len(web.containers()), 1)
def test_project_up(self): web = self.create_service("web") db = self.create_service("db", volumes=["/var/db"]) project = Project("composetest", [web, db], self.client) project.start() self.assertEqual(len(project.containers()), 0) project.up(["db"]) self.assertEqual(len(project.containers()), 1) self.assertEqual(len(db.containers()), 1) self.assertEqual(len(web.containers()), 0)
def test_project_up_with_custom_network(self): self.require_api_version('1.21') client = docker_client(version='1.21') network_name = 'composetest-custom' client.create_network(network_name) self.addCleanup(client.remove_network, network_name) web = self.create_service('web', net=Net(network_name)) project = Project('composetest', [web], client, use_networking=True) project.up() assert project.get_network() is None
def test_project_up_without_all_services(self): console = self.create_service('console') db = self.create_service('db') project = Project('composetest', [console, db], self.client) project.start() self.assertEqual(len(project.containers()), 0) project.up() self.assertEqual(len(project.containers()), 2) self.assertEqual(len(db.containers()), 1) self.assertEqual(len(console.containers()), 1) project.kill() project.remove_stopped()
def test_project_up(self): web = self.create_service('web') db = self.create_service('db', volumes=['/var/db']) project = Project('composetest', [web, db], self.client) project.start() self.assertEqual(len(project.containers()), 0) project.up(['db']) self.assertEqual(len(project.containers()), 1) self.assertEqual(len(db.containers()), 1) self.assertEqual(len(web.containers()), 0) project.kill() project.remove_stopped()
def test_project_up_starts_links(self): console = self.create_service('console') db = self.create_service('db', volumes=[VolumeSpec.parse('/var/db')]) web = self.create_service('web', links=[(db, 'db')]) project = Project('composetest', [web, db, console], self.client) project.start() self.assertEqual(len(project.containers()), 0) project.up(['web']) self.assertEqual(len(project.containers()), 2) self.assertEqual(len(web.containers()), 1) self.assertEqual(len(db.containers()), 1) self.assertEqual(len(console.containers()), 0)
def test_project_up_starts_links(self): console = self.create_service("console") db = self.create_service("db", volumes=["/var/db"]) web = self.create_service("web", links=[(db, "db")]) project = Project("composetest", [web, db, console], self.client) project.start() self.assertEqual(len(project.containers()), 0) project.up(["web"]) self.assertEqual(len(project.containers()), 2) self.assertEqual(len(web.containers()), 1) self.assertEqual(len(db.containers()), 1) self.assertEqual(len(console.containers()), 0)
def docker_containers( docker_project: Project) -> Iterator[Dict[str, Container]]: """ Spins up a the containers for the Docker project and returns them. Note that this fixture's scope is a single test; the containers will be stopped after the test is finished. This is intentional; stopping the containers destroys local storage, so that the next test can start with fresh containers. """ containers: List[Container] = docker_project.up(DOCKER_SERVICES) if not containers: raise ValueError("`docker-compose` didn't launch any containers!") containers_by_name = dict([(c.name, c) for c in containers]) yield containers_by_name # Send container logs to stdout, so that they get included in # the test report. # https://docs.pytest.org/en/latest/capture.html for container in sorted(containers, key=lambda c: c.name): header = "Logs from {0}:".format(container.name) logger.info(header) logger.info("=" * len(header)) logger.info(container.logs().decode("utf-8", errors="replace") or "(no logs)") logger.info('') docker_project.down(ImageType.none, False)
def scoped_containers_fixture(docker_project: Project, request): now = datetime.utcnow() if request.config.getoption("--use-running-containers"): containers = docker_project.containers( ) # type: List[Container] else: if any(docker_project.containers()): raise ContainersAlreadyExist( 'pytest-docker-compose tried to start containers but there are' ' already running containers: %s, you probably scoped your' ' tests wrong' % docker_project.containers()) containers = docker_project.up() if not containers: raise ValueError( "`docker-compose` didn't launch any containers!") container_getter = ContainerGetter(docker_project) yield container_getter if request.config.getoption("--verbose"): for container in sorted(containers, key=lambda c: c.name): header = "Logs from {name}:".format(name=container.name) print(header, '\n', "=" * len(header)) print( container.logs(since=now).decode("utf-8", errors="replace") or "(no logs)", '\n') if not request.config.getoption("--use-running-containers"): docker_project.down( ImageType.none, request.config.getoption( "--docker-compose-remove-volumes"))
def test_project_up_with_no_deps(self): console = self.create_service('console') db = self.create_service('db', volumes=['/var/db']) web = self.create_service('web', links=[(db, 'db')]) project = Project('composetest', [web, db, console], self.client) project.start() self.assertEqual(len(project.containers()), 0) project.up(['web'], start_links=False) self.assertEqual(len(project.containers()), 1) self.assertEqual(len(web.containers()), 1) self.assertEqual(len(db.containers()), 0) self.assertEqual(len(console.containers()), 0) project.kill() project.remove_stopped()
def test_project_up_recreates_containers(self): web = self.create_service('web') db = self.create_service('db', volumes=['/etc']) project = Project('composetest', [web, db], self.client) project.start() self.assertEqual(len(project.containers()), 0) project.up(['db']) self.assertEqual(len(project.containers()), 1) old_db_id = project.containers()[0].id db_volume_path = project.containers()[0].get('Volumes./etc') project.up() self.assertEqual(len(project.containers()), 2) db_container = [c for c in project.containers() if 'db' in c.name][0] self.assertNotEqual(db_container.id, old_db_id) self.assertEqual(db_container.get('Volumes./etc'), db_volume_path)
def test_recreate_preserves_volumes(self): web = self.create_service('web') db = self.create_service('db', volumes=[VolumeSpec.parse('/etc')]) project = Project('composetest', [web, db], self.client) project.start() self.assertEqual(len(project.containers()), 0) project.up(['db']) self.assertEqual(len(project.containers()), 1) old_db_id = project.containers()[0].id db_volume_path = project.containers()[0].get('Volumes./etc') project.up(strategy=ConvergenceStrategy.always) self.assertEqual(len(project.containers()), 2) db_container = [c for c in project.containers() if 'db' in c.name][0] self.assertNotEqual(db_container.id, old_db_id) self.assertEqual(db_container.get('Volumes./etc'), db_volume_path)
def test_recreate_preserves_volumes(self): web = self.create_service("web") db = self.create_service("db", volumes=["/etc"]) project = Project("composetest", [web, db], self.client) project.start() self.assertEqual(len(project.containers()), 0) project.up(["db"]) self.assertEqual(len(project.containers()), 1) old_db_id = project.containers()[0].id db_volume_path = project.containers()[0].get("Volumes./etc") project.up(strategy=ConvergenceStrategy.always) self.assertEqual(len(project.containers()), 2) db_container = [c for c in project.containers() if "db" in c.name][0] self.assertNotEqual(db_container.id, old_db_id) self.assertEqual(db_container.get("Volumes./etc"), db_volume_path)
def test_project_up_with_no_recreate_running(self): web = self.create_service("web") db = self.create_service("db", volumes=["/var/db"]) project = Project("composetest", [web, db], self.client) project.start() self.assertEqual(len(project.containers()), 0) project.up(["db"]) self.assertEqual(len(project.containers()), 1) old_db_id = project.containers()[0].id db_volume_path = project.containers()[0].inspect()["Volumes"]["/var/db"] project.up(strategy=ConvergenceStrategy.never) self.assertEqual(len(project.containers()), 2) db_container = [c for c in project.containers() if "db" in c.name][0] self.assertEqual(db_container.id, old_db_id) self.assertEqual(db_container.inspect()["Volumes"]["/var/db"], db_volume_path)
def test_project_up_with_no_recreate_running(self): web = self.create_service('web') db = self.create_service('db', volumes=['/var/db']) project = Project('composetest', [web, db], self.client) project.start() self.assertEqual(len(project.containers()), 0) project.up(['db']) self.assertEqual(len(project.containers()), 1) old_db_id = project.containers()[0].id db_volume_path = project.containers()[0].inspect()['Volumes']['/var/db'] project.up(strategy=ConvergenceStrategy.never) self.assertEqual(len(project.containers()), 2) db_container = [c for c in project.containers() if 'db' in c.name][0] self.assertEqual(db_container.id, old_db_id) self.assertEqual(db_container.inspect()['Volumes']['/var/db'], db_volume_path)
def _containers_up(cls, docker_project: Project) -> typing.List[Container]: """ Brings up all containers in the specified project. """ containers = docker_project.up() # type: typing.List[Container] if not containers: raise ValueError("`docker-compose` didn't launch any containers!") return containers
def test_project_up_with_no_recreate_running(self): web = self.create_service('web') db = self.create_service('db', volumes=['/var/db']) project = Project('composetest', [web, db], self.client) project.start() self.assertEqual(len(project.containers()), 0) project.up(['db']) self.assertEqual(len(project.containers()), 1) old_db_id = project.containers()[0].id db_volume_path = project.containers()[0].inspect()['Volumes']['/var/db'] project.up(allow_recreate=False) self.assertEqual(len(project.containers()), 2) db_container = [c for c in project.containers() if 'db' in c.name][0] self.assertEqual(db_container.id, old_db_id) self.assertEqual(db_container.inspect()['Volumes']['/var/db'], db_volume_path)
def test_project_up_with_no_recreate_running(self): web = self.create_service('web') db = self.create_service('db', volumes=[VolumeSpec.parse('/var/db')]) project = Project('composetest', [web, db], self.client) project.start() self.assertEqual(len(project.containers()), 0) project.up(['db']) self.assertEqual(len(project.containers()), 1) old_db_id = project.containers()[0].id container, = project.containers() db_volume_path = container.get_mount('/var/db')['Source'] project.up(strategy=ConvergenceStrategy.never) self.assertEqual(len(project.containers()), 2) db_container = [c for c in project.containers() if 'db' in c.name][0] self.assertEqual(db_container.id, old_db_id) self.assertEqual( db_container.get_mount('/var/db')['Source'], db_volume_path)
class ResilienceTest(DockerClientTestCase): def setUp(self): self.db = self.create_service('db', volumes=[VolumeSpec.parse('/var/db')], command='top') self.project = Project('composetest', [self.db], self.client) container = self.db.create_container() self.db.start_container(container) self.host_path = container.get_mount('/var/db')['Source'] def tearDown(self): del self.project del self.db super(ResilienceTest, self).tearDown() def test_successful_recreate(self): self.project.up(strategy=ConvergenceStrategy.always) container = self.db.containers()[0] self.assertEqual( container.get_mount('/var/db')['Source'], self.host_path) def test_create_failure(self): with mock.patch('compose.service.Service.create_container', crash): with self.assertRaises(Crash): self.project.up(strategy=ConvergenceStrategy.always) self.project.up() container = self.db.containers()[0] self.assertEqual( container.get_mount('/var/db')['Source'], self.host_path) def test_start_failure(self): with mock.patch('compose.service.Service.start_container', crash): with self.assertRaises(Crash): self.project.up(strategy=ConvergenceStrategy.always) self.project.up() container = self.db.containers()[0] self.assertEqual( container.get_mount('/var/db')['Source'], self.host_path)
def test_unscale_after_restart(self): web = self.create_service('web') project = Project('composetest', [web], self.client) project.start() service = project.get_service('web') service.scale(1) self.assertEqual(len(service.containers()), 1) service.scale(3) self.assertEqual(len(service.containers()), 3) project.up() service = project.get_service('web') self.assertEqual(len(service.containers()), 3) service.scale(1) self.assertEqual(len(service.containers()), 1) project.up() service = project.get_service('web') self.assertEqual(len(service.containers()), 1) # does scale=0 ,makes any sense? after recreating at least 1 container is running service.scale(0) project.up() service = project.get_service('web') self.assertEqual(len(service.containers()), 1) project.kill() project.remove_stopped()
def test_recreate_fails(self): db = self.create_service('db', volumes=['/var/db'], command='top') project = Project('composetest', [db], self.client) container = db.create_container() db.start_container(container) host_path = container.get('Volumes')['/var/db'] project.up() container = db.containers()[0] self.assertEqual(container.get('Volumes')['/var/db'], host_path) with mock.patch('compose.service.Service.create_container', crash): with self.assertRaises(Crash): project.up() project.up() container = db.containers()[0] self.assertEqual(container.get('Volumes')['/var/db'], host_path)
async def docker_compose(loop, request, docker_project: Project, postgres_override_addr): async def check_postgres(url): conn = await asyncpg.connect(url, loop=loop) await conn.close() checks = { ('postgres', 'POSTGRES_DSN', postgres_override_addr, 'postgresql://[email protected]:%d/postgres' '' % COMPOSE_POSTGRES_PORT, check_postgres), } result = {} fns = [] to_start = [] for svc, name, override, url, fn in checks: if override: result[name] = override else: to_start.append(svc) fns.append((fn, url)) result[name] = url if not to_start: yield result else: containers = docker_project.up(to_start, remove_orphans=True) if not containers: raise ValueError("`docker-compose` didn't launch any containers!") try: timeout = 60 start_time = time.time() print() print('Waiting for docker services...') last_err = None while start_time + timeout > time.time(): try: await asyncio.gather(*[fn(url) for fn, url in fns], loop=loop) break except Exception as err: last_err = err await asyncio.sleep(1, loop=loop) else: last_err_type = type(last_err) raise TimeoutError(f'Unable to start all container services' f' within {timeout} seconds. Last error:' f' {last_err} ({last_err_type})') print('Docker services are ready') yield result finally: # Send container logs to stdout, so that they get included in # the test report. # https://docs.pytest.org/en/latest/capture.html for container in sorted(containers, key=lambda c: c.name): if request.config.getoption('show_docker_logs'): header = f"Logs from {container.name}:" print(header) print("=" * len(header)) print(container.logs().decode("utf-8", errors="replace") or "(no logs)") print() docker_project.down(ImageType.none, False)
async def compose(loop, request, docker_project: Project, postgres_override_addr, rabbit_override_addr): async def check_postgres(url): conn = await asyncpg.connect(url, loop=loop) await conn.close() async def check_rabbit(url): transport, protocol = await aioamqp.from_url(url, loop=loop) await protocol.close() # async def check_redis(url): # conn = await aioredis.create_connection(url) # conn.close() # async def check_http(url): # async with aiohttp.ClientSession(loop=loop) as ses: # resp = await ses.get(url) # assert resp.status == 200 checks = { ( 'postgres', 'DB_URL', postgres_override_addr, COMPOSE_POSTGRES_URL, check_postgres ), ( 'rabbit', 'RABBIT_URL', rabbit_override_addr, COMPOSE_RABBIT_URL, check_rabbit ), } result = {} fns = [] to_start = [] urls = [] for svc, name, override, url, fn in checks: if override: result[name] = override else: to_start.append(svc) urls.append(url) fns.append((fn, url)) result[name] = url if not to_start: yield result else: containers = docker_project.up(to_start) if not containers: raise ValueError("`docker-compose` didn't launch any containers!") try: timeout = 60 start_time = time.time() print() print('Waiting for docker services...') print('\n'.join(urls)) last_err = None while start_time + timeout > time.time(): try: await asyncio.gather(*[fn(url) for fn, url in fns], loop=loop) break except Exception as err: last_err = err await asyncio.sleep(1, loop=loop) else: last_err_type = type(last_err) raise TimeoutError(f'Unable to start all container services' f' within {timeout} seconds. Last error:' f' {last_err} ({last_err_type})') print('Docker services are ready') yield result finally: # Send container logs to stdout, so that they get included in # the test report. # https://docs.pytest.org/en/latest/capture.html for container in sorted(containers, key=lambda c: c.name): if request.config.getoption('show_docker_logs'): header = f"Logs from {container.name}:" print(header) print("=" * len(header)) print( container.logs().decode("utf-8", errors="replace") or "(no logs)" ) print() docker_project.down(ImageType.none, False)