def test_worker_raises_key_error(self): """ Test that a KeyError is raised if the attributes of a Deployment model, that uniquely identifies a record, are not passed. """ worker_payload_1 = { 'application': 'adsws', 'environment': 'staging', } worker_payload_2 = { 'environment': 'production', 'commit': 'latest-commit', } worker_payload_3 = { 'application': 'graphics', } worker_payload_4 = { 'commit': 'latest-commit', } worker_payload_5 = { 'environment': 'staging' } payloads = [worker_payload_1, worker_payload_2, worker_payload_3, worker_payload_4, worker_payload_5] worker = DatabaseWriterWorker() for payload in payloads: with self.assertRaises(KeyError): worker.process_payload(payload)
def test_worker_raises_key_error(self): """ Test that a KeyError is raised if the attributes of a Deployment model, that uniquely identifies a record, are not passed. """ worker_payload_1 = {"application": "adsws", "environment": "staging"} worker_payload_2 = {"environment": "production", "version": "latest-commit"} worker_payload_3 = {"application": "graphics"} worker_payload_4 = {"version": "latest-commit"} worker_payload_5 = {"environment": "staging"} payloads = [worker_payload_1, worker_payload_2, worker_payload_3, worker_payload_4, worker_payload_5] worker = DatabaseWriterWorker() for payload in payloads: with self.assertRaises(KeyError): worker.process_payload(payload)
def test_worker_updates_deployed_status(self): """ When a new service is successful in being deployed, it should update any other service with the same env/app combination to not being deployed. There is most likely a smarter way to do this.... """ first_payload = { 'application': 'staging', 'environment': 'adsws', 'commit': 'first-commit', 'tag': 'first-tag', 'deployed': True, 'tested': False } second_payload = { 'application': 'staging', 'environment': 'adsws', 'commit': 'second-commit', 'tag': 'second-tag', 'deployed': True, 'tested': False } worker = DatabaseWriterWorker() worker.process_payload(first_payload) with self.app.session_scope() as session: deployment = session.query(Deployment).filter( Deployment.commit == 'first-commit' ).one() self.assertTrue(deployment.deployed) worker.process_payload(second_payload) with self.app.session_scope() as session: deployment_2 = session.query(Deployment).filter( Deployment.commit == 'second-commit' ).one() self.assertTrue(deployment_2.deployed) deployment_1 = session.query(Deployment).filter( Deployment.commit == 'first-commit' ).one() self.assertFalse(deployment_1.deployed)
def test_worker_overwrites_entry(self): """ Test that the worker overwrites the relevant data in the database """ # Stub the database entry with self.app.session_scope() as session: deployment = Deployment( application='staging', environment='adsws', commit='latest-commit', tag='latest-tag', deployed=True, tested=False ) session.add(deployment) session.commit() worker_payload = { 'application': 'staging', 'environment': 'adsws', 'commit': 'latest-commit', 'tag': 'latest-tag', 'deployed': True, 'tested': True, } worker = DatabaseWriterWorker() worker.process_payload(worker_payload) with self.app.session_scope() as session: deployment = session.query(Deployment).filter( Deployment.application == 'staging', Deployment.environment == 'adsws', Deployment.commit == 'latest-commit' ).one() self.assertTrue(deployment.tested) self.assertTrue( deployment.date_last_modified > deployment.date_created )
def test_worker_writes_to_database(self): """ Test that the worker writes the relevant data to the database """ worker_payload = { "application": "staging", "environment": "adsws", "version": "latest-commit", "deployed": True, "tested": False, } worker = DatabaseWriterWorker() worker.process_payload(worker_payload) with self.app.session_scope() as session: deployment = ( session.query(Deployment) .filter( Deployment.application == "staging", Deployment.environment == "adsws", Deployment.version == "latest-commit", ) .one() ) for key in worker_payload: expected_value = worker_payload[key] stored_value = getattr(deployment, key) self.assertEqual( expected_value, stored_value, msg='Attr "{}", expected value: "{}" != stored value: "{}"'.format( key, expected_value, stored_value ), ) self.assertIsInstance(deployment.date_created, datetime) self.assertIsInstance(deployment.date_last_modified, datetime)
def test_worker_writes_to_database(self): """ Test that the worker writes the relevant data to the database """ worker_payload = { 'application': 'staging', 'environment': 'adsws', 'commit': 'latest-commit', 'tag': 'latest-tag', 'deployed': True, 'tested': False, } worker = DatabaseWriterWorker() worker.process_payload(worker_payload) with self.app.session_scope() as session: deployment = session.query(Deployment).filter( Deployment.application == 'staging', Deployment.environment == 'adsws', Deployment.commit == 'latest-commit' ).one() for key in worker_payload: expected_value = worker_payload[key] stored_value = getattr(deployment, key) self.assertEqual( expected_value, stored_value, msg='Attr "{}", expected value: "{}" != stored value: "{}"' .format(key, expected_value, stored_value) ) self.assertIsInstance(deployment.date_created, datetime) self.assertIsInstance(deployment.date_last_modified, datetime)
def test_worker_overwrites_entry(self): """ Test that the worker overwrites the relevant data in the database """ # Stub the database entry with self.app.session_scope() as session: deployment = Deployment( application="staging", environment="adsws", version="latest-commit", deployed=True, tested=False ) session.add(deployment) session.commit() worker_payload = { "application": "staging", "environment": "adsws", "version": "latest-commit", "deployed": True, "tested": True, } worker = DatabaseWriterWorker() worker.process_payload(worker_payload) with self.app.session_scope() as session: deployment = ( session.query(Deployment) .filter( Deployment.application == "staging", Deployment.environment == "adsws", Deployment.version == "latest-commit", ) .one() ) self.assertTrue(deployment.tested) self.assertTrue(deployment.date_last_modified > deployment.date_created)
def test_worker_updates_deployed_status(self): """ When a new service is successful in being deployed, it should update any other service with the same env/app combination to not being deployed. There is most likely a smarter way to do this.... """ first_payload = { "application": "staging", "environment": "adsws", "version": "first-commit", "deployed": True, "tested": False, } second_payload = { "application": "staging", "environment": "adsws", "version": "second-commit", "deployed": True, "tested": False, } worker = DatabaseWriterWorker() worker.process_payload(first_payload) with self.app.session_scope() as session: deployment = session.query(Deployment).filter(Deployment.version == "first-commit").one() self.assertTrue(deployment.deployed) worker.process_payload(second_payload) with self.app.session_scope() as session: deployment_2 = session.query(Deployment).filter(Deployment.version == "second-commit").one() self.assertTrue(deployment_2.deployed) deployment_1 = session.query(Deployment).filter(Deployment.version == "first-commit").one() self.assertFalse(deployment_1.deployed)
def test_before_deploy_fails(self, mock_is_timedout): """ Test that the correct database entires are made by BeforeDeploy worker when the worker fails on its actions """ # Worker receives a packet, most likely from the webapp # Example packet: # # { # 'application': 'staging', # '....': '....', # } # # packet = { 'environment': 'staging', 'application': 'adsws', 'version': 'v1.0.0', } # Override the run test returned value. This means the logic of the test # does not have to be mocked mock_is_timedout.return_value = True with MiniRabbit(RABBITMQ_URL) as w: w.publish(route='in', exchange='test', payload=json.dumps(packet)) # Worker runs the tests params = { 'RABBITMQ_URL': RABBITMQ_URL, 'exchange': 'test', 'subscribe': 'in', 'publish': 'ads.deploy.deploy', 'header_frame': None, 'error': 'error', 'status': 'database', 'TEST_RUN': True } before_deploy_worker = BeforeDeploy(params=params) before_deploy_worker.run() before_deploy_worker.connection.close() # Worker sends a packet to the next worker with MiniRabbit(RABBITMQ_URL) as w: self.assertEqual(w.message_count('in'), 0) self.assertEqual(w.message_count('ads.deploy.deploy'), 0) self.assertEqual(w.message_count('database'), 1) self.assertEqual(w.message_count('error'), 1) # Start the DB Writer worker params = { 'RABBITMQ_URL': RABBITMQ_URL, 'exchange': 'test', 'subscribe': 'database', 'TEST_RUN': True } db_worker = DatabaseWriterWorker(params=params) db_worker.app = self.app db_worker.run() db_worker.connection.close() with self.app.session_scope() as session: all_deployments = session.query(Deployment).all() self.assertEqual( len(all_deployments), 1, msg='More (or less) than 1 deployment entry: {}' .format(all_deployments) ) deployment = all_deployments[0] for key in packet: self.assertEqual( packet[key], getattr(deployment, key) ) self.assertEqual(deployment.deployed, False) self.assertEqual( deployment.msg, 'BeforeDeploy: waiting too long for the environment to come up' )
def test_before_deploy_receives_restart(self, mock_executioner): """ Test that the correct database entires are made by BeforeDeploy worker when the worker succeeds on its actions """ # Worker receives a packet, most likely from the webapp # Example packet: # # { # 'application': 'staging', # '....': '....', # }a # # packet = { 'environment': 'staging', 'application': 'adsws', 'action': 'restart' } # Override the run test returned value. This means the logic of the test # does not have to be mocked mock_r = mock.Mock(retcode=0) mock_r.out.splitlines.return_value = [] mock_x = mock_executioner.return_value mock_x.cmd.return_value = mock_r with MiniRabbit(RABBITMQ_URL) as w: w.publish(route='in', exchange='test', payload=json.dumps(packet)) # Worker runs the tests params = { 'RABBITMQ_URL': RABBITMQ_URL, 'exchange': 'test', 'subscribe': 'in', 'publish': 'ads.deploy.deploy', 'header_frame': None, 'status': 'database', 'error': 'error', 'status': 'database', 'TEST_RUN': True } before_deploy_worker = BeforeDeploy(params=params) before_deploy_worker.run() before_deploy_worker.connection.close() # Worker sends a packet to the next worker with MiniRabbit(RABBITMQ_URL) as w: self.assertEqual(w.message_count('in'), 0) self.assertEqual(w.message_count('ads.deploy.deploy'), 0) self.assertEqual(w.message_count('ads.deploy.restart'), 1) self.assertEqual(w.message_count('database'), 1) self.assertEqual(w.message_count('error'), 0) # Start the DB Writer worker params = { 'RABBITMQ_URL': RABBITMQ_URL, 'exchange': 'test', 'subscribe': 'database', 'TEST_RUN': True } db_worker = DatabaseWriterWorker(params=params) db_worker.app = self.app db_worker.run() db_worker.connection.close() # remove irrelevant keys before checking things packet.pop('action') # check database entries with self.app.session_scope() as session: all_deployments = session.query(Deployment).all() self.assertEqual( len(all_deployments), 1, msg='More (or less) than 1 deployment entry: {}' .format(all_deployments) ) deployment = all_deployments[0] for key in packet: self.assertEqual( packet[key], getattr(deployment, key) ) self.assertEqual(deployment.deployed, None) self.assertEqual( deployment.msg, 'Deploy to be restarted' )
def test_db_writes_on_test_pass(self, mocked_run_test): """ Check that the database is being written to when a test passes """ # Stub data packet = { 'application': 'adsws', 'environment': 'staging', 'tag': 'v1.0.0', 'commit': 'gf9gd8f', } expected_packet = packet.copy() expected_packet['tested'] = True mocked_run_test.return_value = expected_packet # Start the IntegrationTester worker params = { 'RABBITMQ_URL': RABBITMQ_URL, 'exchange': 'test', 'subscribe': 'in', 'publish': 'out', 'status': 'database', 'TEST_RUN': True } # Push to rabbitmq with MiniRabbit(RABBITMQ_URL) as w: w.publish(route='in', exchange='test', payload=json.dumps(packet)) test_worker = IntegrationTestWorker(params=params) test_worker.run() test_worker.connection.close() # Assert there is a packet on the publish queue with MiniRabbit(RABBITMQ_URL) as w: self.assertEqual(w.message_count('out'), 1) self.assertEqual(w.message_count('database'), 1) # Start the DB Writer worker params = { 'RABBITMQ_URL': RABBITMQ_URL, 'exchange': 'test', 'subscribe': 'database', 'TEST_RUN': True } db_worker = DatabaseWriterWorker(params=params) db_worker.app = self.app db_worker.run() db_worker.connection.close() with self.app.session_scope() as session: all_deployments = session.query(Deployment).all() self.assertEqual( len(all_deployments), 1, msg='More (or less) than 1 deployment entry: {}' .format(all_deployments) ) deployment = all_deployments[0] for key in packet: self.assertEqual( packet[key], getattr(deployment, key) ) self.assertEqual(deployment.tested, True)
def test_before_deploy_fails(self, mock_is_timedout): """ Test that the correct database entires are made by BeforeDeploy worker when the worker fails on its actions """ # Worker receives a packet, most likely from the webapp # Example packet: # # { # 'application': 'staging', # '....': '....', # } # # packet = {"environment": "staging", "application": "adsws", "tag": "v1.0.0", "commit": "gf9gd8f"} # Override the run test returned value. This means the logic of the test # does not have to be mocked mock_is_timedout.return_value = True with MiniRabbit(RABBITMQ_URL) as w: w.publish(route="in", exchange="test", payload=json.dumps(packet)) # Worker runs the tests params = { "RABBITMQ_URL": RABBITMQ_URL, "exchange": "test", "subscribe": "in", "publish": "ads.deploy.deploy", "header_frame": None, "error": "error", "status": "database", "TEST_RUN": True, } before_deploy_worker = BeforeDeploy(params=params) before_deploy_worker.run() before_deploy_worker.connection.close() # Worker sends a packet to the next worker with MiniRabbit(RABBITMQ_URL) as w: self.assertEqual(w.message_count("in"), 0) self.assertEqual(w.message_count("ads.deploy.deploy"), 0) self.assertEqual(w.message_count("database"), 1) self.assertEqual(w.message_count("error"), 1) # Start the DB Writer worker params = {"RABBITMQ_URL": RABBITMQ_URL, "exchange": "test", "subscribe": "database", "TEST_RUN": True} db_worker = DatabaseWriterWorker(params=params) db_worker.app = self.app db_worker.run() db_worker.connection.close() with self.app.session_scope() as session: all_deployments = session.query(Deployment).all() self.assertEqual( len(all_deployments), 1, msg="More (or less) than 1 deployment entry: {}".format(all_deployments) ) deployment = all_deployments[0] for key in packet: self.assertEqual(packet[key], getattr(deployment, key)) self.assertEqual(deployment.deployed, False) self.assertEqual(deployment.msg, "BeforeDeploy: waiting too long for the environment to come up")
def test_before_deploy_receives_restart(self, mock_executioner): """ Test that the correct database entires are made by BeforeDeploy worker when the worker succeeds on its actions """ # Worker receives a packet, most likely from the webapp # Example packet: # # { # 'application': 'staging', # '....': '....', # }a # # packet = { "environment": "staging", "application": "adsws", "tag": "v1.0.0", "commit": "gf9gd8f", "action": "restart", } # Override the run test returned value. This means the logic of the test # does not have to be mocked mock_r = mock.Mock(retcode=0) mock_r.out.splitlines.return_value = [] mock_x = mock_executioner.return_value mock_x.cmd.return_value = mock_r with MiniRabbit(RABBITMQ_URL) as w: w.publish(route="in", exchange="test", payload=json.dumps(packet)) # Worker runs the tests params = { "RABBITMQ_URL": RABBITMQ_URL, "exchange": "test", "subscribe": "in", "publish": "ads.deploy.deploy", "header_frame": None, "status": "database", "error": "error", "status": "database", "TEST_RUN": True, } before_deploy_worker = BeforeDeploy(params=params) before_deploy_worker.run() before_deploy_worker.connection.close() # Worker sends a packet to the next worker with MiniRabbit(RABBITMQ_URL) as w: self.assertEqual(w.message_count("in"), 0) self.assertEqual(w.message_count("ads.deploy.deploy"), 0) self.assertEqual(w.message_count("ads.deploy.restart"), 1) self.assertEqual(w.message_count("database"), 1) self.assertEqual(w.message_count("error"), 0) # Start the DB Writer worker params = {"RABBITMQ_URL": RABBITMQ_URL, "exchange": "test", "subscribe": "database", "TEST_RUN": True} db_worker = DatabaseWriterWorker(params=params) db_worker.app = self.app db_worker.run() db_worker.connection.close() # remove irrelevant keys before checking things packet.pop("action") # check database entries with self.app.session_scope() as session: all_deployments = session.query(Deployment).all() self.assertEqual( len(all_deployments), 1, msg="More (or less) than 1 deployment entry: {}".format(all_deployments) ) deployment = all_deployments[0] for key in packet: self.assertEqual(packet[key], getattr(deployment, key)) self.assertEqual(deployment.deployed, None) self.assertEqual(deployment.msg, "Deploy to be restarted")
def test_restart_fails(self, mock_executioner): """ Test that when a restart is requested, and the restart worker fails, the messages are updated """ # Worker receives a packet, most likely from the webapp # Example packet: # # { # 'application': 'staging', # '....': '....', # } # # packet = { 'environment': 'staging', 'application': 'adsws', 'tag': 'v1.0.0', 'commit': 'gf9gd8f', } # Override the run test returned value. This means the logic of the test # does not have to be mocked. retcode = 1 means it has failed mock_r = mock.MagicMock(retcode=1) mock_r.__str__.return_value = 'restart failed' mock_x = mock_executioner.return_value mock_x.cmd.return_value = mock_r with MiniRabbit(RABBITMQ_URL) as w: w.publish(route='in', exchange='test', payload=json.dumps(packet)) # Worker runs the tests params = { 'RABBITMQ_URL': RABBITMQ_URL, 'exchange': 'test', 'subscribe': 'in', 'publish': 'out', 'header_frame': None, 'error': 'error', 'status': 'database', 'TEST_RUN': True } restart_worker = Restart(params=params) restart_worker.run() restart_worker.connection.close() # Worker sends a packet to the next worker with MiniRabbit(RABBITMQ_URL) as w: self.assertEqual(w.message_count('in'), 0) self.assertEqual(w.message_count('out'), 0) self.assertEqual(w.message_count('database'), 2) self.assertEqual(w.message_count('error'), 1) # Start the DB Writer worker params = { 'RABBITMQ_URL': RABBITMQ_URL, 'exchange': 'test', 'subscribe': 'database', 'TEST_RUN': True } # First message should be starting of the deployment db_worker = DatabaseWriterWorker(params=params) db_worker.app = self.app db_worker.run() with self.app.session_scope() as session: deployment = session.query(Deployment)\ .filter(Deployment.commit == 'gf9gd8f').one() self.assertEqual( deployment.msg, 'staging-adsws restart-soft starts' ) self.assertIsNone(deployment.deployed) db_worker.run() with self.app.session_scope() as session: deployment = session.query(Deployment)\ .filter(Deployment.commit == 'gf9gd8f').one() for key in packet: self.assertEqual( packet[key], getattr(deployment, key) ) self.assertFalse(deployment.deployed) self.assertEqual( deployment.msg, 'restart failed' )
def test_deploy_fails(self, mock_executioner): """ Test that when the deploy fails the correct entries are sent and stored in the backend database """ # Worker receives a packet, most likely from the webapp # Example packet: # # { # 'application': 'staging', # 'environment': 'adsws', # 'version': 'v1.0.3' # } # # packet = { 'environment': 'adsws', 'application': 'staging', 'version': 'v1.0.0' } # Stub the database with some early entries first_deployment = Deployment( environment=packet['environment'], application=packet['application'], version='v0.0.1', deployed=True ) with self.app.session_scope() as session: session.add(first_deployment) session.commit() # Override the run test returned value. This means the logic of the test # does not have to be mocked. retcode = 1 means it has failed mock_r = mock.Mock(retcode=1, command='r-command', err='r-err', out='r-out') mock_x = mock_executioner.return_value mock_x.cmd.return_value = mock_r with MiniRabbit(RABBITMQ_URL) as w: w.publish(route='in', exchange='test', payload=json.dumps(packet)) # Worker runs the tests params = { 'RABBITMQ_URL': RABBITMQ_URL, 'exchange': 'test', 'subscribe': 'in', 'publish': 'out', 'header_frame': None, 'error': 'error', 'status': 'database', 'TEST_RUN': True } deploy_worker = Deploy(params=params) deploy_worker.run() deploy_worker.connection.close() # Worker sends a packet to the next worker with MiniRabbit(RABBITMQ_URL) as w: self.assertEqual(w.message_count('in'), 0) self.assertEqual(w.message_count('out'), 0) self.assertEqual(w.message_count('database'), 2) self.assertEqual(w.message_count('error'), 1) # Start the DB Writer worker params = { 'RABBITMQ_URL': RABBITMQ_URL, 'exchange': 'test', 'subscribe': 'database', 'TEST_RUN': True } # First message should be starting of the deployment db_worker = DatabaseWriterWorker(params=params) db_worker.app = self.app db_worker.run() with self.app.session_scope() as session: deployment = session.query(Deployment)\ .filter(Deployment.version == 'v1.0.0').one() self.assertEqual( deployment.msg, 'staging-adsws deployment starts' ) self.assertIsNone(deployment.deployed) deployment = session.query(Deployment)\ .filter(Deployment.version == 'v0.0.1').one() self.assertTrue(deployment.deployed) db_worker.run() with self.app.session_scope() as session: deployment = session.query(Deployment)\ .filter(Deployment.version == 'v1.0.0').one() for key in packet: self.assertEqual( packet[key], getattr(deployment, key) ) self.assertFalse(deployment.deployed) self.assertEqual( deployment.msg, 'deployment failed; command: r-command, reason: r-err, stdout: r-out' ) deployment = session.query(Deployment)\ .filter(Deployment.version == 'v0.0.1').one() self.assertTrue(deployment.deployed)