예제 #1
0
 def test_service_started_lock_call(self, mock_threading):
     services = connect_services([FakeService(name='service1', dependencies=[]),
                                  FakeService(name='service2', dependencies=['service1'])])
     context = RunningContext(services, DEFAULT_OPTIONS)
     context.service_started(services['service1'])
     mock_lock = mock_threading.Lock.return_value
     assert mock_lock.__enter__.call_count == 1
예제 #2
0
    def test_start_new_if_always_start_new(self):
        service = FakeService()
        service.always_start_new = True
        options = Options(network=Network(name='the-network',
                                          id='the-network-id'),
                          timeout=1,
                          remove=True,
                          run_dir='/etc',
                          build=[])
        agent = ServiceAgent(service, options, None)
        restarted = False

        def start():
            nonlocal restarted
            restarted = True

        self.docker._existing_containers = [
            Bunch(status='exited',
                  start=start,
                  network='the-network',
                  attrs={'Config': {
                      'Env': []
                  }},
                  name="{}-testing-123".format(service.name))
        ]
        agent.run_image()
        assert len(self.docker._services_started) == 1
        assert not restarted
예제 #3
0
 def test_fail_dependencies(self):
     """If a service fails to start, all the other services that depend on it are
     also registered as failed"""
     services = connect_services([FakeService(name='service1', dependencies=[]),
                                  FakeService(name='service2', dependencies=['service1'])])
     context = RunningContext(services, DEFAULT_OPTIONS)
     context.service_failed(services['service1'])
     assert len(context.failed_services) == 2
예제 #4
0
 def test_ready_to_start_and_stop(self):
     services = connect_services([FakeService(name='service1', dependencies=[]),
                                  FakeService(name='service2', dependencies=['service1'])])
     context = RunningContext(services, DEFAULT_OPTIONS)
     assert len(context.ready_to_start) == 1
     assert context.ready_to_start[0].service == services['service1']
     assert len(context.ready_to_stop) == 1
     assert context.ready_to_stop[0].service == services['service2']
예제 #5
0
 def test_done_on_fail(self):
     services = connect_services([FakeService(name='service1', dependencies=[]),
                                  FakeService(name='service2', dependencies=[])])
     context = RunningContext(services, DEFAULT_OPTIONS)
     assert not context.done
     context.service_started(services['service1'])
     assert not context.done
     context.service_failed(services['service2'])
     assert context.done
예제 #6
0
 def test_service_failed_lock_call(self, mock_threading):
     services = connect_services([FakeService(name='service1', dependencies=[]),
                                  FakeService(name='service2', dependencies=['service1'])])
     context = RunningContext(services, DEFAULT_OPTIONS)
     context.service_failed(services['service1'])
     mock_lock = mock_threading.Lock.return_value
     # This has to be 2 because service1 has a dependency, and it has to be
     # locked as well
     assert mock_lock.__enter__.call_count == 2
예제 #7
0
 def test_if_build_from_and_latest(self):
     fake_context = FakeRunningContext()
     fake_service = FakeService()
     fake_service.image = "service:latest"
     fake_service.build_from = "the/service/dir"
     agent = ServiceAgent(fake_service, DEFAULT_OPTIONS, fake_context)
     agent.start_service()
     agent.join()
     assert len(self.docker._images_built) == 1
예제 #8
0
 def test_build_on_start(self):
     fake_context = FakeRunningContext()
     fake_service = FakeService()
     fake_service.build_from = "the/service/dir"
     options = attr.evolve(DEFAULT_OPTIONS, build=[fake_service.name])
     agent = ServiceAgent(fake_service, options, fake_context)
     agent.start_service()
     agent.join()
     assert len(self.docker._images_built) == 1
예제 #9
0
 def test_build_image_dockerfile(self):
     fake_service = FakeService(name='myservice')
     fake_service.dockerfile = 'Dockerfile.other'
     fake_service.build_from = "the/service/dir"
     agent = ServiceAgent(fake_service, DEFAULT_OPTIONS,
                          FakeRunningContext())
     agent.build_image()
     assert len(self.docker._images_built) == 1
     _, dockerfile, _ = self.docker._images_built[0]
     assert dockerfile == 'Dockerfile.other'
예제 #10
0
 def test_service_stopped(self):
     services = connect_services([FakeService(name='service1', dependencies=[]),
                                  FakeService(name='service2', dependencies=['service1'])])
     context = RunningContext(services, DEFAULT_OPTIONS)
     context.service_stopped(services['service2'])
     assert len(context.agent_set) == 1
     assert len(context.processed_services) == 1
     assert context.processed_services[0] is services['service2']
     assert services['service1'] in context.agent_set
     assert context.agent_set[services['service1']].can_stop
예제 #11
0
 def test_run_image_extrapolate_env(self):
     service = FakeService()
     service.env = {'ENV_ONE': 'http://{host}:{port:d}'}
     context.Context['host'] = 'zombo.com'
     context.Context['port'] = 80
     agent = ServiceAgent(service, DEFAULT_OPTIONS, None)
     agent.run_image()
     assert len(self.docker._services_started) == 1
     _, service, _ = self.docker._services_started[0]
     assert service.env['ENV_ONE'] == 'http://zombo.com:80'
예제 #12
0
 def test_build_image(self, mock_datetime):
     now = datetime.now()
     mock_datetime.now.return_value = now
     fake_service = FakeService(name='myservice')
     fake_service.build_from = "the/service/dir"
     agent = ServiceAgent(fake_service, DEFAULT_OPTIONS,
                          FakeRunningContext())
     retval = agent.build_image()
     assert len(self.docker._images_built) == 1
     build_dir, dockerfile, image_tag = self.docker._images_built[0]
     assert build_dir == "/etc/the/service/dir"
     assert dockerfile == 'Dockerfile'
     assert image_tag == now.strftime("myservice-%Y-%m-%d-%H%M")
     assert retval == image_tag
     assert RunCondition.BUILD_IMAGE in agent.run_condition.actions
예제 #13
0
 def test_stop_container_does_not_exist(self):
     fake_context = FakeRunningContext()
     fake_service = FakeService(exception_at_init=ValueError)
     agent = ServiceAgent(fake_service, DEFAULT_OPTIONS, fake_context)
     agent.stop_service()
     agent.join()
     assert agent.status == AgentStatus.STOPPED
예제 #14
0
 def test_service_failed(self):
     service = FakeService(name='service1', dependencies=[])
     context = RunningContext({'service': service}, DEFAULT_OPTIONS)
     context.service_failed(service)
     assert len(context.failed_services) == 1
     assert len(context.agent_set) == 0
     assert len(context.processed_services) == 0
예제 #15
0
 def test_start_existing_if_differing_env_value_type_but_not_string(self):
     service = FakeService()
     service.env = {'KEY': 12345}
     agent = ServiceAgent(service, DEFAULT_OPTIONS, None)
     self.docker._existing_containers = [
         Bunch(status='exited',
               network='the-network',
               id='longass-container-id',
               image=Bunch(tags=[service.image]),
               attrs={'Config': {
                   'Env': ['KEY=12345']
               }},
               name="{}-testing-123".format(service.name))
     ]
     agent.run_image()
     assert len(self.docker._services_started) == 0
예제 #16
0
 def test_pre_start_before_run(self):
     fake_context = FakeRunningContext()
     fake_service = FakeService()
     assert not fake_service.pre_start_called
     agent = ServiceAgent(fake_service, DEFAULT_OPTIONS, fake_context)
     agent.start_service()
     agent.join()
     assert fake_service.pre_start_called
예제 #17
0
 def test_run_image(self):
     agent = ServiceAgent(FakeService(), DEFAULT_OPTIONS, None)
     agent.run_image()
     assert len(self.docker._services_started) == 1
     prefix, service, network = self.docker._services_started[0]
     assert prefix == "service1-testing"
     assert service.name == 'service1'
     assert service.image == 'not/used'
     assert network.name == 'the-network'
예제 #18
0
 def test_ping_and_init_after_run(self):
     fake_context = FakeRunningContext()
     fake_service = FakeService()
     agent = ServiceAgent(fake_service, DEFAULT_OPTIONS, fake_context)
     agent.start_service()
     agent.join()
     assert len(fake_context.started_services) == 1
     assert fake_context.started_services[0].name == 'service1'
     assert fake_service.ping_count == 1
     assert fake_service.init_called
예제 #19
0
 def test_call_collection_failed_on_error(self):
     fake_context = FakeRunningContext()
     fake_service = FakeService(exception_at_init=ValueError)
     agent = ServiceAgent(fake_service, DEFAULT_OPTIONS, fake_context)
     agent.start_service()
     agent.join()
     assert fake_service.ping_count > 0
     assert fake_context.started_services == []
     assert len(fake_context.failed_services) == 1
     assert fake_context.failed_services[0].name == 'service1'
예제 #20
0
 def test_repeat_ping_and_timeout(self, mock_time):
     mock_time.monotonic.side_effect = [0, 0.2, 0.6, 0.8, 1]
     fake_context = FakeRunningContext()
     fake_service = FakeService(fail_ping=True)
     agent = ServiceAgent(fake_service, DEFAULT_OPTIONS, fake_context)
     agent.start_service()
     agent.join()
     assert fake_service.ping_count == 3
     assert mock_time.sleep.call_count == 3
     assert agent.status == AgentStatus.FAILED
     assert len(fake_context.failed_services) == 1
     assert fake_context.failed_services[0] is fake_service
예제 #21
0
    def test_agent_status_change_happy_path(self):
        class ServiceAgentTestSubclass(ServiceAgent):
            def ping(self):
                assert self.status == 'in-progress'
                return super().ping()

        agent = ServiceAgentTestSubclass(FakeService(), DEFAULT_OPTIONS,
                                         FakeRunningContext())
        assert agent.status == 'null'
        agent.start_service()
        agent.join()
        assert agent.status == 'started'
예제 #22
0
    def test_agent_status_change_sad_path(self):
        class ServiceAgentTestSubclass(ServiceAgent):
            def ping(self):
                assert self.status == 'in-progress'
                raise ValueError("I failed miserably")

        agent = ServiceAgentTestSubclass(FakeService(), DEFAULT_OPTIONS,
                                         FakeRunningContext())
        assert agent.status == 'null'
        agent.start_service()
        agent.join()
        assert agent.status == 'failed'
예제 #23
0
 def test_start_new_container_if_differing_env_value(self):
     service = FakeService()
     service.env = {'KEY': 'some-value'}
     agent = ServiceAgent(service, DEFAULT_OPTIONS, None)
     self.docker._existing_containers = [
         Bunch(status='exited',
               network='the-network',
               id='longass-container-id',
               image=Bunch(tags=[service.image]),
               attrs={'Config': {
                   'Env': ['KEY=other-value']
               }},
               name="{}-miniboss-123".format(service.name))
     ]
     agent.run_image()
     assert len(self.docker._services_started) == 1
     prefix, service, network = self.docker._services_started[0]
     assert prefix == "service1-testing"
     assert service.name == 'service1'
     assert service.image == 'not/used'
     assert network.name == 'the-network'
     assert self.docker._containers_ran == []
예제 #24
0
 def test_skip_if_running_on_same_network(self):
     service = FakeService()
     agent = ServiceAgent(service, DEFAULT_OPTIONS, None)
     self.docker._existing_containers = [
         Bunch(status='running',
               name="{}-testing-123".format(service.name),
               network='the-network')
     ]
     agent.run_image()
     assert len(self.docker._services_started) == 0
     assert len(self.docker._existing_queried) == 1
     assert self.docker._existing_queried[0] == ("service1-testing",
                                                 Network(
                                                     name="the-network",
                                                     id="the-network-id"))
예제 #25
0
 def test_stop_existing_container(self):
     fake_context = FakeRunningContext()
     fake_service = FakeService(exception_at_init=ValueError)
     container = FakeContainer(name='{}-testing-5678'.format(
         fake_service.name),
                               network='the-network',
                               status='running')
     self.docker._existing_containers = [container]
     agent = ServiceAgent(fake_service, DEFAULT_OPTIONS, fake_context)
     agent.stop_service()
     agent.join()
     assert agent.status == AgentStatus.STOPPED
     assert container.stopped
     assert len(fake_context.stopped_services) == 1
     assert fake_context.stopped_services[0] is fake_service
예제 #26
0
 def test_start_old_container_if_exists(self):
     service = FakeService()
     agent = ServiceAgent(service, DEFAULT_OPTIONS, None)
     self.docker._existing_containers = [
         Bunch(status='exited',
               network='the-network',
               id='longass-container-id',
               image=Bunch(tags=[service.image]),
               attrs={'Config': {
                   'Env': []
               }},
               name="{}-testing-123".format(service.name))
     ]
     agent.run_image()
     assert len(self.docker._services_started) == 0
     assert self.docker._containers_ran == ['longass-container-id']
예제 #27
0
 def test_service_failed_on_failed_ping(self):
     fake_context = FakeRunningContext()
     fake_service = FakeService(fail_ping=True)
     # Using options with low timeout so that test doesn't hang
     options = Options(network=Network(name='the-network',
                                       id='the-network-id'),
                       timeout=0.1,
                       remove=True,
                       run_dir='/etc',
                       build=[])
     agent = ServiceAgent(fake_service, options, fake_context)
     agent.start_service()
     agent.join()
     assert fake_service.ping_count > 0
     assert fake_context.started_services == []
     assert len(fake_context.failed_services) == 1
     assert fake_context.failed_services[0].name == 'service1'
예제 #28
0
 def test_yes_ping_no_init_if_started(self):
     service = FakeService()
     fake_context = FakeRunningContext()
     agent = ServiceAgent(service, DEFAULT_OPTIONS, fake_context)
     self.docker._existing_containers = [
         Bunch(status='exited',
               network='the-network',
               id='longass-container-id',
               image=Bunch(tags=[service.image]),
               attrs={'Config': {
                   'Env': []
               }},
               name="{}-testing-123".format(service.name))
     ]
     agent.start_service()
     agent.join()
     assert service.ping_count == 1
     assert not service.init_called
     assert self.docker._containers_ran == ['longass-container-id']
예제 #29
0
 def test_no_pre_ping_or_init_if_running(self):
     service = FakeService()
     fake_context = FakeRunningContext()
     options = Options(network=Network(name='the-network',
                                       id='the-network-id'),
                       timeout=1,
                       remove=True,
                       run_dir='/etc',
                       build=[])
     agent = ServiceAgent(service, options, fake_context)
     self.docker._existing_containers = [
         Bunch(status='running',
               network='the-network',
               name="{}-testing-123".format(service.name))
     ]
     agent.start_service()
     agent.join()
     assert service.ping_count == 0
     assert not service.init_called
     assert not service.pre_start_called