def test_raise_exception_on_circular_dependency(self): collection = ServiceCollection() class NewServiceBase(Service): name = "not used" image = "not used" collection._base_class = NewServiceBase class ServiceOne(NewServiceBase): name = "hello" image = "hello" dependencies = ["howareyou"] class ServiceTwo(NewServiceBase): name = "goodbye" image = "hello" dependencies = ["hello"] class ServiceThree(NewServiceBase): name = "howareyou" image = "hello" dependencies = ["goodbye"] with pytest.raises(ServiceLoadError): collection.load_definitions()
def test_stop_without_remove(self): container1 = FakeContainer(name='service1-testing-1234', network='the-network', status='running') container2 = FakeContainer(name='service2-testing-5678', network='the-network', status='exited') self.docker._existing_containers = [container1, container2] collection = ServiceCollection() class NewServiceBase(Service): name = "not used" image = "not used" class ServiceOne(NewServiceBase): name = "service1" image = "howareyou/image" class ServiceTwo(NewServiceBase): name = "service2" image = "howareyou/image" collection._base_class = NewServiceBase collection.load_definitions() collection.stop_all(DEFAULT_OPTIONS) assert container1.stopped assert container1.timeout == 1 assert container1.removed_at is None assert not container2.stopped assert self.docker._networks_removed == []
def test_start_all(self): # This test does not fake threading, which is somehow dangerous, but the # aim is to make sure that the error handling etc. works also when there # is an exception in the service agent thread, and the # collection.start_all method does not hang. collection = ServiceCollection() class NewServiceBase(Service): name = "not used" image = "not used" collection._base_class = NewServiceBase class ServiceOne(NewServiceBase): name = "hello" image = "hello/image" dependencies = ["howareyou"] class ServiceTwo(NewServiceBase): name = "goodbye" image = "goodbye/image" dependencies = ["hello"] class ServiceThree(NewServiceBase): name = "howareyou" image = "howareyou/image" collection.load_definitions() retval = collection.start_all(DEFAULT_OPTIONS) assert set(retval) == {"hello", "goodbye", "howareyou"} assert len(self.docker._services_started) == 3 # The one without dependencies should have been started first name_prefix, service, network_name = self.docker._services_started[0] assert service.image == 'howareyou/image' assert name_prefix == "howareyou-testing"
def test_start_all_with_build(self): collection = ServiceCollection() class NewServiceBase(Service): name = "not used" image = "not used" collection._base_class = NewServiceBase class ServiceTwo(NewServiceBase): name = "goodbye" image = "goodbye/image" build_from = "goodbye/dir" dockerfile = "Dockerfile.alt" collection.load_definitions() options = attr.evolve(DEFAULT_OPTIONS, build=['goodbye']) retval = collection.start_all(options) assert len(self.docker._images_built) == 1 build_dir, dockerfile, image_tag = self.docker._images_built[0] assert build_dir == "/etc/goodbye/dir" assert dockerfile == 'Dockerfile.alt' assert image_tag.startswith("goodbye-") service = collection.all_by_name['goodbye'] assert service.image == image_tag
def test_stop_dependency_and_dependant_excluded(self): collection = ServiceCollection() class NewServiceBase(Service): name = "not used" image = "not used" collection._base_class = NewServiceBase class ServiceOne(NewServiceBase): name = "hello" image = "hello" dependencies = ["howareyou"] class ServiceTwo(NewServiceBase): name = "goodbye" image = "hello" dependencies = ["hello"] class ServiceThree(NewServiceBase): name = "howareyou" image = "hello" collection.load_definitions() collection.exclude_for_stop(['howareyou', 'hello'])
def test_populate_dependants(self): collection = ServiceCollection() class NewServiceBase(Service): name = "not used" image = "not used" collection._base_class = NewServiceBase class ServiceOne(NewServiceBase): name = "hello" image = "not/used" dependencies = ["howareyou"] class ServiceTwo(NewServiceBase): name = "goodbye" image = "not/used" dependencies = ["hello", "howareyou"] class ServiceThree(NewServiceBase): name = "howareyou" image = "not/used" collection.load_definitions() assert len(collection.all_by_name) == 3 hello = collection.all_by_name['hello'] assert len(hello.dependants) == 1 assert hello.dependants[0].name == 'goodbye' howareyou = collection.all_by_name['howareyou'] assert len(howareyou.dependants) == 2 names = [x.name for x in howareyou.dependants] assert 'hello' in names assert 'goodbye' in names
def test_error_on_stop_dependency_excluded(self): collection = ServiceCollection() class NewServiceBase(Service): name = "not used" image = "not used" collection._base_class = NewServiceBase class ServiceOne(NewServiceBase): name = "hello" image = "hello" dependencies = ["howareyou"] class ServiceTwo(NewServiceBase): name = "goodbye" image = "hello" dependencies = ["hello"] class ServiceThree(NewServiceBase): name = "howareyou" image = "hello" collection.load_definitions() with pytest.raises(ServiceLoadError): collection.exclude_for_stop(['goodbye'])
def test_start_dependency_and_dependant_excluded(self): collection = ServiceCollection() class NewServiceBase(Service): name = "not used" image = "not used" collection._base_class = NewServiceBase class ServiceOne(NewServiceBase): name = "hello" image = "hello" dependencies = ["howareyou"] class ServiceTwo(NewServiceBase): name = "goodbye" image = "hello" dependencies = ["hello"] class ServiceThree(NewServiceBase): name = "howareyou" image = "hello" collection.load_definitions() # There shouldn't be an exception, since we are excluding both hello and # goodbye collection.exclude_for_start(['hello', 'goodbye'])
def test_exclude_for_start(self): collection = ServiceCollection() class NewServiceBase(Service): name = "not used" image = "not used" collection._base_class = NewServiceBase class ServiceOne(NewServiceBase): name = "hello" image = "hello" dependencies = ["howareyou"] class ServiceTwo(NewServiceBase): name = "goodbye" image = "hello" dependencies = ["hello"] class ServiceThree(NewServiceBase): name = "howareyou" image = "hello" collection.load_definitions() collection.exclude_for_start(['goodbye']) assert len(collection) == 2
def test_continue_if_start_failed(self): """If a service fails, those that don't depend on it should still be started""" collection = ServiceCollection() class NewServiceBase(Service): name = "not used" image = "not used" class FirstService(NewServiceBase): name = "first-service" image = "howareyou/image" def ping(self): raise ValueError("I failed miserably") class SecondService(NewServiceBase): name = "second-service" image = "howareyou/image" def ping(self): time.sleep(0.5) return True collection._base_class = NewServiceBase collection.load_definitions() started = collection.start_all(DEFAULT_OPTIONS) assert started == ["second-service"]
def test_raise_exception_on_no_services(self): collection = ServiceCollection() class NewServiceBase(Service): name = "not used" image = "not used" collection._base_class = NewServiceBase with pytest.raises(ServiceLoadError): collection.load_definitions()
def test_start_all_create_network(self): collection = ServiceCollection() class NewServiceBase(Service): name = "not used" image = "not used" class ServiceTwo(NewServiceBase): name = "goodbye" image = "goodbye/image" collection._base_class = NewServiceBase collection.load_definitions() collection.start_all(DEFAULT_OPTIONS) assert self.docker._networks_created == ["the-network"]
def test_stop_with_remove_and_order(self): container1 = FakeContainer(name='service1-testing-1234', network='the-network', status='running') container2 = FakeContainer(name='service2-testing-5678', network='the-network', status='running') container3 = FakeContainer(name='service3-testing-5678', network='the-network', status='running') self.docker._existing_containers = [container1, container2, container3] collection = ServiceCollection() class NewServiceBase(Service): name = "not used" image = "not used" class ServiceOne(NewServiceBase): name = "service1" image = "howareyou/image" class ServiceTwo(NewServiceBase): name = "service2" image = "howareyou/image" dependencies = ['service1'] class ServiceThree(NewServiceBase): name = "service3" image = "howareyou/image" dependencies = ['service2'] collection._base_class = NewServiceBase collection.load_definitions() options = Options(network=Network(name='the-network', id='the-network-id'), timeout=50, remove=True, run_dir='/etc', build=[]) collection.stop_all(options) assert container1.stopped assert container1.removed_at is not None assert container2.stopped assert container2.removed_at is not None assert container3.stopped assert container3.removed_at is not None assert container1.removed_at > container2.removed_at > container3.removed_at assert self.docker._networks_removed == ['the-network']
def test_stop_on_fail(self): collection = ServiceCollection() class NewServiceBase(Service): name = "not used" image = "not used" class TheService(NewServiceBase): name = "howareyou" image = "howareyou/image" def ping(self): raise ValueError("I failed miserably") collection._base_class = NewServiceBase collection.load_definitions() started = collection.start_all(DEFAULT_OPTIONS) assert started == []
def test_update_for_base_service(self): container1 = FakeContainer(name='service1-testing-1234', network='the-network', status='running') container2 = FakeContainer(name='service2-testing-5678', network='the-network', status='running') container3 = FakeContainer(name='service3-testing-5678', network='the-network', status='running') self.docker._existing_containers = [container1, container2, container3] collection = ServiceCollection() class NewServiceBase(Service): name = "not used" image = "not used" class ServiceOne(NewServiceBase): name = "service1" image = "howareyou/image" class ServiceTwo(NewServiceBase): name = "service2" image = "howareyou/image" dependencies = ['service1'] class ServiceThree(NewServiceBase): name = 'service3' image = 'howareyou/image' dependencies = ['service1', 'service2'] collection._base_class = NewServiceBase collection.load_definitions() collection.update_for_base_service('service2') assert collection.all_by_name == { 'service2': ServiceTwo(), 'service3': ServiceThree() } collection.stop_all(DEFAULT_OPTIONS) assert not container1.stopped assert container2.stopped assert container3.stopped
def test_stop_with_remove_and_exclude(self): container1 = FakeContainer(name='service1-testing-1234', network='the-network', status='running') container2 = FakeContainer(name='service2-testing-5678', network='the-network', status='running') self.docker._existing_containers = [container1, container2] collection = ServiceCollection() class NewServiceBase(Service): name = "not used" image = "not used" class ServiceOne(NewServiceBase): name = "service1" image = "howareyou/image" class ServiceTwo(NewServiceBase): name = "service2" image = "howareyou/image" collection._base_class = NewServiceBase collection.load_definitions() collection.exclude_for_stop(['service2']) options = Options(network=Network(name='the-network', id='the-network-id'), timeout=50, remove=True, run_dir='/etc', build=[]) collection.stop_all(options) assert container1.stopped assert container1.removed_at is not None # service2 was excluded assert not container2.stopped assert container2.removed_at is None # If excluded is not empty, network should not be removed assert self.docker._networks_removed == []
def test_check_can_be_built(self): collection = ServiceCollection() class NewServiceBase(Service): name = "not used" image = "not used" class ServiceOne(NewServiceBase): name = "service1" image = "howareyou/image" class ServiceTwo(NewServiceBase): name = "service2" image = "howareyou/image" build_from = "the/service/dir" collection._base_class = NewServiceBase collection.load_definitions() with pytest.raises(ServiceDefinitionError): collection.check_can_be_built('no-such-service') with pytest.raises(ServiceDefinitionError): collection.check_can_be_built('service1') collection.check_can_be_built('service2')
def test_dont_return_failed_services(self): collection = ServiceCollection() class NewServiceBase(Service): name = "not used" image = "not used" class TheFirstService(NewServiceBase): name = "howareyou" image = "howareyou/image" class TheService(NewServiceBase): name = "imok" image = "howareyou/image" dependencies = ["howareyou"] def ping(self): raise ValueError("I failed miserably") collection._base_class = NewServiceBase collection.load_definitions() started = collection.start_all(DEFAULT_OPTIONS) assert started == ["howareyou"]