From 3724c8a78a4a70622e36de10c2f6b335cd51f6d3 Mon Sep 17 00:00:00 2001 From: Matthew Aynalem Date: Tue, 1 May 2018 13:34:00 -0700 Subject: [PATCH] python 3 compatibility / add tox / pytest runner --- .editorconfig | 13 +++++++++++++ .gitignore | 3 +++ .travis.yml | 9 +++++---- License2Deploy/rolling_deploy.py | 18 +++++++++--------- setup.cfg | 13 +++++++++++++ setup.py | 4 +++- tests/__init__.py | 1 - tests/cloudformation_client_test.py | 10 +++++----- tests/rolling_deploy_test.py | 20 +++++++------------- tox.ini | 25 +++++++++++++++++++++++++ 10 files changed, 83 insertions(+), 33 deletions(-) create mode 100644 .editorconfig create mode 100644 setup.cfg create mode 100644 tox.ini diff --git a/.editorconfig b/.editorconfig new file mode 100644 index 0000000..503acc3 --- /dev/null +++ b/.editorconfig @@ -0,0 +1,13 @@ +# top-most EditorConfig file +root = true + +[*] +charset = utf-8 +end_of_line = lf +insert_final_newline = true +indent_style = space +trim_trailing_whitespace = true + +[*.py] +max_line_length = 119 +indent_size = 4 diff --git a/.gitignore b/.gitignore index 22a1b42..fbc521d 100644 --- a/.gitignore +++ b/.gitignore @@ -6,3 +6,6 @@ *htmlcov .DS_Store .localized +*.idea +.tox +.pytest_cache diff --git a/.travis.yml b/.travis.yml index a560a33..04aeea7 100644 --- a/.travis.yml +++ b/.travis.yml @@ -1,17 +1,18 @@ language: python python: - - "2.7" - "2.6" + - "2.7" + - "3.6" install: - - python setup.py install - pip install coveralls + - pip install tox-travis before_script: - export PYTHONPATH=$PYTHONPATH:$PWD script: - - coverage run --source License2Deploy setup.py test + - tox after_success: - coveralls + - if [ "$TRAVIS_PYTHON_VERSION" == "2.7" ]; then coveralls; fi diff --git a/License2Deploy/rolling_deploy.py b/License2Deploy/rolling_deploy.py index c991001..057b474 100644 --- a/License2Deploy/rolling_deploy.py +++ b/License2Deploy/rolling_deploy.py @@ -4,8 +4,8 @@ import argparse from sys import exit, argv from time import sleep, time -from AWSConn import AWSConn -from set_logging import SetLogging +from .AWSConn import AWSConn +from .set_logging import SetLogging from retry.api import retry_call class RollingDeploy(object): @@ -94,7 +94,7 @@ def get_autoscale_group_name(self): ''' Search for project in autoscale groups and return autoscale group name ''' if self.stack_name: return self.get_autoscaling_group_name_from_cloudformation() - return next((instance.name for instance in filter(lambda n: n.name, self.get_group_info()) if self.project in instance.name and self.env in instance.name), None) + return next((instance.name for instance in [n for n in self.get_group_info() if n.name] if self.project in instance.name and self.env in instance.name), None) def get_autoscaling_group_name_from_cloudformation(self): if not self.autoscaling_group: @@ -133,7 +133,7 @@ def calculate_autoscale_desired_instance_count(self, group_name, desired_state): except Exception as e: logging.error("Please make sure the desired_state is set to either increase or decrease: {0}".format(e)) exit(self.exit_error_code) - + def double_autoscale_instance_count(self, count): ''' Multiply current count by 2 ''' return count * 2 @@ -223,16 +223,16 @@ def wait_for_new_instances(self, instance_ids, retry=10, wait_time=30): def lb_healthcheck(self, new_ids): ''' Confirm that the healthchecks report back OK in the LB. ''' instance_ids = self.conn_elb.describe_instance_health(self.load_balancer, new_ids) - status = filter(lambda instance: instance.state != "InService", instance_ids) + status = [instance for instance in instance_ids if instance.state != "InService"] if status: raise Exception('Must check load balancer again. Following instance(s) are not "InService": {0}'.format(status)) else: logging.info('ELB healthcheck OK') return True - + def calculate_max_minutes(self, tries, delay): return tries * delay / 60 - + def only_new_instances_check(self): instance_ids = self.conn_elb.describe_instance_health(self.load_balancer) for instance in instance_ids: @@ -254,7 +254,7 @@ def tag_ami(self, ami_id, env): ''' Tagging AMI with DEPLOYED tag ''' try: current_tag = self.conn_ec2.get_all_images(image_ids=ami_id)[0].tags.get('deployed') - if not current_tag: + if not current_tag: logging.info("No DEPLOY tags exist, tagging with {0}".format(env)) self.conn_ec2.create_tags([self.ami_id], {"deployed": env}) elif env not in current_tag: @@ -407,6 +407,6 @@ def main(): # pragma: no cover SetLogging.setup_logging() deployObj = RollingDeploy(args.env, args.project, args.build_number, args.ami_id, args.profile, args.config, args.stack_name, args.force_redeploy, None, args.creation_wait, args.ready_wait, args.health_wait, args.only_new_wait) deployObj.deploy() - + if __name__ == "__main__": # pragma: no cover main() diff --git a/setup.cfg b/setup.cfg new file mode 100644 index 0000000..b44f221 --- /dev/null +++ b/setup.cfg @@ -0,0 +1,13 @@ +[coverage:run] +branch = true +source = License2Deploy + +[coverage:report] +omit = + tests + .tox + +[tool:pytest] +addopts = --verbose +testpaths = + tests diff --git a/setup.py b/setup.py index 2167f43..eb8882a 100644 --- a/setup.py +++ b/setup.py @@ -20,7 +20,9 @@ "PyYaml", 'placebo', 'boto3', - 'retry' + 'retry', + 'pytest', + 'coverage', ] def read(fname): diff --git a/tests/__init__.py b/tests/__init__.py index 792d600..e69de29 100644 --- a/tests/__init__.py +++ b/tests/__init__.py @@ -1 +0,0 @@ -# diff --git a/tests/cloudformation_client_test.py b/tests/cloudformation_client_test.py index 5721dcd..6558634 100644 --- a/tests/cloudformation_client_test.py +++ b/tests/cloudformation_client_test.py @@ -17,15 +17,15 @@ def setUp(self): self.rolling_deploy = RollingDeploy('stg', 'server-gms-extender', '0', 'ami-abcd1234', None, './regions.yml', stack_name='test-stack-name', session=session) def test_get_autoscaling_group_name_via_cloudformation(self): - self.assertEquals(self.rolling_deploy.autoscaling_group, False) + self.assertEqual(self.rolling_deploy.autoscaling_group, False) asg_name = self.rolling_deploy.get_autoscale_group_name() self.assertTrue(self.rolling_deploy.autoscaling_group) - self.assertEquals(asg_name, 'dnbi-backend-qa-dnbigmsextenderASGqa-1NP5ZBSVZRD0N') + self.assertEqual(asg_name, 'dnbi-backend-qa-dnbigmsextenderASGqa-1NP5ZBSVZRD0N') def test_retrieve_project_cloudwatch_alarms(self): - self.assertEquals(self.rolling_deploy.stack_resources, False) - self.assertEquals(self.rolling_deploy.cloudwatch_alarms, False) + self.assertEqual(self.rolling_deploy.stack_resources, False) + self.assertEqual(self.rolling_deploy.cloudwatch_alarms, False) cloudwatch_alarms = self.rolling_deploy.retrieve_project_cloudwatch_alarms() self.assertTrue(self.rolling_deploy.stack_resources) - self.assertEquals(cloudwatch_alarms, ['dnbi-servergmsextender-SCALEDOWNALARMqa-123123', 'dnbi-servergmsextender-SCALEUPALARMqa-4asdhjks']) + self.assertEqual(cloudwatch_alarms, ['dnbi-servergmsextender-SCALEDOWNALARMqa-123123', 'dnbi-servergmsextender-SCALEUPALARMqa-4asdhjks']) diff --git a/tests/rolling_deploy_test.py b/tests/rolling_deploy_test.py index e144195..76c4f22 100644 --- a/tests/rolling_deploy_test.py +++ b/tests/rolling_deploy_test.py @@ -1,6 +1,7 @@ #!/usr/bin/env python import sys +import pytest import unittest import boto from boto.ec2.autoscale.launchconfig import LaunchConfiguration @@ -10,7 +11,6 @@ from moto import mock_ec2_deprecated from moto import mock_elb_deprecated from moto.cloudwatch import mock_cloudwatch_deprecated -from nose.tools import raises from License2Deploy.rolling_deploy import RollingDeploy from License2Deploy.AWSConn import AWSConn @@ -137,7 +137,7 @@ def test_retrieve_project_cloudwatch_alarms(self): instance_ids = self.setUpEC2() self.setUpCloudWatch(instance_ids) cloud_watch_alarms = self.rolling_deploy.retrieve_project_cloudwatch_alarms() - print cloud_watch_alarms + print(cloud_watch_alarms) self.assertEqual(1, len(cloud_watch_alarms)) @mock_cloudwatch_deprecated @@ -214,7 +214,7 @@ def test_confirm_lb_has_only_new_instances(self): @mock_elb_deprecated def test_get_lb(self): self.setUpELB() - self.assertEqual(u'servergmsextenderELBstg', self.rolling_deploy.get_lb()) #Return All LB's with the proper build number + self.assertEqual('servergmsextenderELBstg', self.rolling_deploy.get_lb()) #Return All LB's with the proper build number # assertRaises is a context manager since Python 2.7. Only testing in Python 2.7 # https://docs.python.org/2.7/library/unittest.html @@ -295,15 +295,15 @@ def test_is_redeploy(self): self.setUpEC2() self.assertTrue(self.rolling_deploy.is_redeploy()) - @raises(SystemExit) @mock_ec2_deprecated def test_is_redeploy_fails(self): self.setUpEC2(tag=False) - self.assertRaises(self.rolling_deploy.is_redeploy(), Exception) + with pytest.raises(SystemExit): + self.rolling_deploy.is_redeploy() - @raises(SystemExit) def test_stop_deploy(self): - self.assertRaises(self.rolling_deploy.stop_deploy('error!'), Exception) + with pytest.raises(SystemExit): + self.rolling_deploy.stop_deploy('error!') @mock_ec2_deprecated @mock_autoscaling_deprecated @@ -389,9 +389,3 @@ def test_double_autoscale_instance_count(self): def test_decrease_autoscale_instance_count(self): self.assertEqual(self.rolling_deploy.decrease_autoscale_instance_count(4), 2) - -def main(): - unittest.main() - -if __name__ == "__main__": - main() diff --git a/tox.ini b/tox.ini new file mode 100644 index 0000000..a74e9c7 --- /dev/null +++ b/tox.ini @@ -0,0 +1,25 @@ +[tox] +minversion=2.6.0 +envlist = py26,py27,py36 +skip_missing_interpreters = True + +[testenv] +usedevelop = true +extras = + test +whitelist_externals = + find +commands= + find . -type f -name "*.pyc" -delete + find . -type d -name "__pycache__" -delete + {envbindir}/coverage erase + {envbindir}/coverage run \ + {envbindir}/pytest --basetemp={envtmpdir} {posargs} + {envbindir}/coverage html -d {toxinidir}/htmlcov/{envname} + +[testenv:appveyor] +basepython = {env:PYTHON:}\python.exe +commands= + {envbindir}/coverage run \ + -m pytest --basetemp={envtmpdir} {posargs} + {envbindir}/coverage html -d {toxinidir}/htmlcov/{envname}