From 16605618f578e04693d01665a08569676482a4b0 Mon Sep 17 00:00:00 2001 From: Rahul Rajaram Date: Tue, 10 Sep 2024 13:55:10 -0400 Subject: [PATCH 1/6] Remove dated docker/eb local setup code This commit remvoes unnecessary code to check whether the right version of docker is present. This was necessary a few years ago when older versions of docker, incompatible with local development, were still in use. This commit also assumes the customer has the necessary setup to launch docker locally on a Windows. --- ebcli/containers/compat.py | 84 +---------------- ebcli/controllers/local.py | 3 - tests/unit/containers/test_compat.py | 131 +-------------------------- tests/unit/controllers/test_local.py | 3 - 4 files changed, 2 insertions(+), 219 deletions(-) diff --git a/ebcli/containers/compat.py b/ebcli/containers/compat.py index 6e3f5dc8a..2df31e756 100644 --- a/ebcli/containers/compat.py +++ b/ebcli/containers/compat.py @@ -35,100 +35,18 @@ DOCKER_TLS_VERIFY = 'DOCKER_TLS_VERIFY' -def supported_docker_installed(): - """ - Return whether proper Docker version is installed. - :return: bool - """ - - try: - clean_version = remove_leading_zeros_from_version(commands.version()) - return Version(clean_version) >= Version(SUPPORTED_DOCKER_V) - except (OSError, CommandError): - return False - - -def validate_docker_installed(): - _validate_docker_installed(supported_docker_installed()) - - -def _validate_docker_installed(supported_docker_installed): - versions = {'boot2docker-version': SUPPORTED_BOOT2DOCKER_V, - 'docker-version': SUPPORTED_DOCKER_V} - err = strings['local.dockernotpresent'].format(**versions) - - if not supported_docker_installed: - raise CommandError(err) - - def container_ip(): """ Return the ip address that local containers are or will be running on. :return str """ - try: - return _boot2docker_ip() - except OSError: - return LOCALHOST - - -def _boot2docker_ip(): - args = ['boot2docker', 'ip'] - return utils.exec_cmd_quiet(args).strip() - - -def setup(env=os.environ): - validate_docker_installed() - boot2docker_setup(env) - - -def boot2docker_setup(env=os.environ): - if not heuristics.is_boot2docker_installed(): - return - LOG.debug('Ensuring boot2docker VM has initialized, started and the client is set up...') - - _init_boot2docker() - if not _is_boot2docker_running(): - _start_boot2docker() - - boot2docker_certs_path = os.path.sep.join(['.boot2docker', 'certs', - 'boot2docker-vm']) - - if DOCKER_HOST not in env: - env[DOCKER_HOST] = 'tcp://{}:2376'.format(_boot2docker_ip()) - - if DOCKER_CERT_PATH not in env: - env[DOCKER_CERT_PATH] = os.path.join(fileoperations.get_home(), - boot2docker_certs_path) - if DOCKER_TLS_VERIFY not in env: - env[DOCKER_TLS_VERIFY] = '1' - - LOG.debug('DOCKER_HOST is set to ' + env[DOCKER_HOST]) - LOG.debug('DOCKER_CERT_PATH is set to ' + env[DOCKER_CERT_PATH]) - LOG.debug('DOCKER_TLS_VERIFY is set to ' + env[DOCKER_TLS_VERIFY]) - LOG.debug('PATH is set to ' + env.get('PATH', '')) + return LOCALHOST def is_windows(): return 'win32' in str(sys.platform).lower() -def _is_boot2docker_running(): - return _get_boot2docker_status() == BOOT2DOCKER_RUNNING - - -def _get_boot2docker_status(): - return utils.exec_cmd_quiet(['boot2docker', 'status']).strip() - - -def _start_boot2docker(): - utils.exec_cmd_quiet(['boot2docker', 'start']) - - -def _init_boot2docker(): - utils.exec_cmd_quiet(['boot2docker', 'init']) - - def remove_leading_zeros_from_version(version_string): # regex explaination: remove zeroes if both: # 1. the start of string (major version) or following a '.' diff --git a/ebcli/controllers/local.py b/ebcli/controllers/local.py index 827a5de94..34eb0cf1c 100644 --- a/ebcli/controllers/local.py +++ b/ebcli/controllers/local.py @@ -58,7 +58,6 @@ class Meta: dict(action='store_true', help=flag_text['local.run.insecuressl']))] def do_command(self): - compat.setup() cnt = factory.make_container(self.app.pargs.envvars, self.app.pargs.port, self.app.pargs.allow_insecure_ssl) @@ -93,7 +92,6 @@ class Meta: arguments = [] def do_command(self): - compat.setup() cnt = factory.make_container() cnt_viewmodel = ContainerViewModel.from_container(cnt) localops.open_webpage(cnt_viewmodel) @@ -111,7 +109,6 @@ class Meta: arguments = [] def do_command(self): - compat.setup() cnt = factory.make_container() cnt_viewmodel = ContainerViewModel.from_container(cnt) localops.print_container_details(cnt_viewmodel) diff --git a/tests/unit/containers/test_compat.py b/tests/unit/containers/test_compat.py index 25daa36b4..1024f90f6 100644 --- a/tests/unit/containers/test_compat.py +++ b/tests/unit/containers/test_compat.py @@ -35,135 +35,6 @@ class TestCompat(TestCase): - @patch('ebcli.containers.compat.commands.version') - def test_supported_docker_installed_not_installed(self, version): - version.side_effect = OSError - self.assertFalse(compat.supported_docker_installed()) - - @patch('ebcli.containers.compat.commands.version') - def test_supported_docker_installed_lower_version(self, - version): - version.side_effect = CommandError - self.assertFalse(compat.supported_docker_installed()) - - @patch('ebcli.containers.compat.commands.version') - def test_supported_docker_installed_same_version(self, - version): - version.return_value = compat.SUPPORTED_DOCKER_V - self.assertTrue(compat.supported_docker_installed()) - - @patch('ebcli.containers.compat.commands.version') - def test_supported_docker_installed_higher_version(self, - version): - version.return_value = '1.9.0' - self.assertTrue(compat.supported_docker_installed()) - - @patch('ebcli.containers.compat.commands.version') - def test_supported_docker_installed_v1_10(self, - version): - version.return_value = '1.10.0' - self.assertTrue(compat.supported_docker_installed()) - - @patch('ebcli.containers.compat.commands.version') - def test_supported_docker_installed_v10_0(self, - version): - version.return_value = '10.0.0' - self.assertTrue(compat.supported_docker_installed()) - - @patch('ebcli.containers.compat.utils.exec_cmd_quiet') - def test_container_ip_boot2docker_works(self, exec_cmd_quiet): - exec_cmd_quiet.return_value = MOCK_MAC_CONTAINER_IP - self.assertEqual(MOCK_MAC_CONTAINER_IP, compat.container_ip()) - - @patch('ebcli.containers.compat.utils.exec_cmd_quiet') - def test_container_ip_boot2docker_oserror(self, exec_cmd_quiet): - exec_cmd_quiet.side_effect = OSError - self.assertEqual(compat.LOCALHOST, compat.container_ip()) - - @patch('ebcli.containers.compat.utils') - @patch('ebcli.containers.compat.heuristics.is_boot2docker_installed') - def test_boot2docker_setup_not_installed(self, is_boot2docker_installed, - utils): - is_boot2docker_installed.return_value = False - compat.boot2docker_setup({}) - self.assertFalse(utils.exec_cmd_quiet.called) - - @patch('ebcli.containers.compat.fileoperations') - @patch('ebcli.containers.compat._boot2docker_ip') - @patch('ebcli.containers.compat.utils') - @patch('ebcli.containers.compat.heuristics.is_boot2docker_installed') - def test_boot2docker_setup_envvars_not_set(self, is_boot2docker_installed, - utils, _boot2docker_ip, - fileoperations): - env = {} - expected_env = {'DOCKER_HOST': 'tcp://192.168.59.103:2376', - 'DOCKER_CERT_PATH': os.path.join('home','.boot2docker','certs', 'boot2docker-vm'), - 'DOCKER_TLS_VERIFY': '1'} - - is_boot2docker_installed.return_value = True - _boot2docker_ip.return_value = '192.168.59.103' - fileoperations.get_home.return_value = os.path.join('home') - - compat.boot2docker_setup(env) - - self.assertDictEqual(expected_env, env) - - @patch('ebcli.containers.compat.utils') - @patch('ebcli.containers.compat.heuristics.is_boot2docker_installed') - def test_boot2docker_setup_envvars_is_set(self, is_boot2docker_installed, - utils): - env = {'DOCKER_HOST': 'tcp://192.168.59.103:9000', - 'DOCKER_CERT_PATH': '/new-path/certs', - 'DOCKER_TLS_VERIFY': '1'} - expected_env = env.copy() - is_boot2docker_installed.return_value = True - - compat.boot2docker_setup(env) - - self.assertDictEqual(expected_env, env) - - @patch('ebcli.containers.compat.utils') - @patch('ebcli.containers.compat.heuristics.is_boot2docker_installed') - def test_boot2docker_init_and_start(self, is_boot2docker_installed, utils): - is_boot2docker_installed.return_value = True - - utils.exec_cmd_quiet.side_effect = [None, 'poweroff', - None, '192.168.59.103'] - - compat.boot2docker_setup({}) - - utils.exec_cmd_quiet.assert_any_call(['boot2docker', 'init']) - utils.exec_cmd_quiet.assert_any_call(['boot2docker', 'start']) - - @patch('ebcli.containers.compat.supported_docker_installed') - def test_validate_docker_installed_not_installed(self, supported_docker_installed): - supported_docker_installed.return_value = False - self.assertRaises(CommandError, compat.validate_docker_installed) - - @patch('ebcli.containers.compat.supported_docker_installed') - def test_validate_docker_installed_is_installed(self, supported_docker_installed): - supported_docker_installed.return_value = True - try: - compat.validate_docker_installed() - except CommandError: - self.fail('Docker is installed') - - def test_validate_docker_installed_helper_not_installed(self): - self.assertRaises(CommandError, compat._validate_docker_installed, False) - - def test_validate_docker_installed_helper_is_installed(self): - try: - compat._validate_docker_installed(True) - except CommandError: - self.fail('Docker is installed') - - @patch('ebcli.containers.compat.boot2docker_setup') - @patch('ebcli.containers.compat.validate_docker_installed') - def test_setup(self, validate_docker_installed, boot2docker_setup): - compat.setup(os.environ) - validate_docker_installed.assert_called_once_with() - boot2docker_setup.assert_called_once_with(os.environ) - def test_remove_leading_zeros_from_version(self): versions_tests = [] versions_tests.append(('0001.000.000', '1.0.0')) @@ -174,4 +45,4 @@ def test_remove_leading_zeros_from_version(self): versions_tests.append(('017.030.07-ce', '17.30.7-ce')) versions_tests.append(('17.03.08-ce', '17.3.8-ce')) for test in versions_tests: - self.assertEqual(compat.remove_leading_zeros_from_version(test[0]), test[1]) \ No newline at end of file + self.assertEqual(compat.remove_leading_zeros_from_version(test[0]), test[1]) diff --git a/tests/unit/controllers/test_local.py b/tests/unit/controllers/test_local.py index 303c9513e..166fa483f 100644 --- a/tests/unit/controllers/test_local.py +++ b/tests/unit/controllers/test_local.py @@ -121,7 +121,6 @@ def test_local_run( class TestLocalStatus(TestLocal): - @mock.patch('ebcli.controllers.local.compat.setup') @mock.patch('ebcli.controllers.local.factory.make_container') @mock.patch('ebcli.controllers.local.ContainerViewModel.from_container') @mock.patch('ebcli.controllers.local.localops.print_container_details') @@ -130,9 +129,7 @@ def test_local_run( print_container_details_mock, from_container_mock, make_container_mock, - setup_mock ): - setup_mock.side_effect = None container_mock = mock.MagicMock() make_container_mock.return_value = container_mock container_view_model_mock = mock.MagicMock() From d3ed22554339dd8cde0443f9ef8e8d213a372929 Mon Sep 17 00:00:00 2001 From: Rahul Rajaram Date: Tue, 10 Sep 2024 13:55:37 -0400 Subject: [PATCH 2/6] Avoid checking for pip 21 in dependency checker unit test Assume existence of modern pip versions --- tests/test_dependencies_mismatch.py | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/tests/test_dependencies_mismatch.py b/tests/test_dependencies_mismatch.py index a2ef3f95b..bb6ac752c 100644 --- a/tests/test_dependencies_mismatch.py +++ b/tests/test_dependencies_mismatch.py @@ -14,9 +14,6 @@ from pkg_resources import get_distribution, parse_version -if pip_version != '21.1': - raise RuntimeError('You need pip==21.1 to check for dependency incompatibilities.') - try: from pip._internal.operations.check import ( check_package_set, @@ -41,7 +38,7 @@ def color_green(message): def collect_package_requirements_by_requirement_name(req_name, package_set): required_by = dict() for pkg_name, package in package_set.items(): - for req in package.requires: + for req in package.dependencies: if req.name.lower() == req_name.lower(): required_by[pkg_name] = req.specifier From d8f94e74b7a7416658987ce5500f606ebbf4f404 Mon Sep 17 00:00:00 2001 From: Rahul Rajaram Date: Tue, 10 Sep 2024 13:56:00 -0400 Subject: [PATCH 3/6] Fix sourcecontrol test to accommodate master and main as valid default Git branches "main" came into adoption as the default branch on certain Git clients especially on OS X whereas "master" was historically the default branch. --- tests/unit/objects/test_sourcecontrol.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/unit/objects/test_sourcecontrol.py b/tests/unit/objects/test_sourcecontrol.py index 0eccff864..da933766b 100644 --- a/tests/unit/objects/test_sourcecontrol.py +++ b/tests/unit/objects/test_sourcecontrol.py @@ -210,7 +210,7 @@ def test_get_current_repository__git_cmd_failed( @unittest.skipIf(not fileoperations.program_is_installed('git'), "Skipped because git is not installed") def test_get_current_branch(self): - self.assertEqual('master', sourcecontrol.Git().get_current_branch()) + self.assertTrue(sourcecontrol.Git().get_current_branch() in ['master', 'main']) @unittest.skipIf(not fileoperations.program_is_installed('git'), "Skipped because git is not installed") @mock.patch('ebcli.core.io.log_warning') From ec4c5a3843bb6c80b6e707e9a6c67e5ca4eddec8 Mon Sep 17 00:00:00 2001 From: Rahul Rajaram Date: Tue, 10 Sep 2024 13:56:11 -0400 Subject: [PATCH 4/6] Upgrade dependencies and fix EBCLI for Python 3.12 This commit incorporates cement 2.10.14 that removes accesses to the `imp` module in favour of `importlib` for 3.12. The EB CLI now works for Python 3.12. One limitation is that Pytest 3 is not compatible with Python 3.12 because of it's reliance on `imp` and [this change](https://github.com/pytest-dev/pytest/blob/9515dfa58a144f3644fd29b256113d723c9c1955/src/_pytest/config/argparsing.py#L180) not having been incorporated into Pytest 3.10.1 which hasn't see a new release [since Nov 2018](https://pypi.org/project/pytest/3.10.1/). In future work, we should upgrade Pytest to 8.x. Issue: https://github.com/aws/aws-elastic-beanstalk-cli/issues/493 --- requirements.txt | 21 ++++++++++----------- setup.py | 2 +- 2 files changed, 11 insertions(+), 12 deletions(-) diff --git a/requirements.txt b/requirements.txt index ab090c226..dbc428570 100644 --- a/requirements.txt +++ b/requirements.txt @@ -1,13 +1,12 @@ -botocore>1.23.41,<1.35.0 -cement==2.8.2 -colorama>=0.2.5,<0.4.4 # use the same range that 'docker-compose' uses +botocore>=1.35.0,<1.36.0 +cement==2.10.14 +colorama>=0.4.6,<0.5 pathspec==0.10.1 python-dateutil>=2.1,<3.0.0 # use the same range that 'botocore' uses -requests>=2.31 -setuptools >= 20.0 -semantic_version == 2.8.5 -six>=1.11.0,<1.17.0 -termcolor == 1.1.0 -wcwidth>=0.1.7,<0.2.0 -PyYAML>=5.3.1,<6.1 # use the same range that 'aws-cli' uses. This is also compatible with 'docker-compose' -urllib3>=1.26.5,<2 #1.26.5 fix CVE-2021-33503 +requests>=2.31,<3 +setuptools>=20.0 +semantic_version>=2.10.0,<2.11 +termcolor>=2.4.0,<3 +wcwidth>=0.2.13,<0.3 +PyYAML>=5.3.1,<6.1 # use the same range that 'aws-cli' uses +urllib3>=1.26.5,<2 diff --git a/setup.py b/setup.py index f6dfe0c34..9e681d737 100755 --- a/setup.py +++ b/setup.py @@ -37,7 +37,7 @@ } if not sys.platform.startswith('win'): - requires.append('blessed>=1.9.5') + requires.append('blessed>=1.20.0') setup_options = dict( From 03f3967b5e257cc9a12b71edb474db5343bd49d7 Mon Sep 17 00:00:00 2001 From: Rahul Rajaram Date: Tue, 10 Sep 2024 23:17:52 -0400 Subject: [PATCH 5/6] Fix bug that parses saved configs and ebextensions for the load balancer --- ebcli/controllers/create.py | 51 ++------------ tests/unit/controllers/test_create.py | 98 --------------------------- 2 files changed, 5 insertions(+), 144 deletions(-) diff --git a/ebcli/controllers/create.py b/ebcli/controllers/create.py index 2c42ed730..5f08e0348 100644 --- a/ebcli/controllers/create.py +++ b/ebcli/controllers/create.py @@ -13,7 +13,7 @@ import argparse import os import time -import yaml + from ebcli.core import io, fileoperations, hooks from ebcli.core.abstractcontroller import AbstractBaseController from ebcli.lib import elasticbeanstalk, utils, iam @@ -239,7 +239,7 @@ def do_command(self): cname = cname or get_environment_cname(env_name, provided_env_name, tier) key_name = key_name or commonops.get_default_keyname() vpc = self.form_vpc_object(tier, single) - elb_type = elb_type or get_elb_type_from_customer(interactive, single, tier,cfg_flag_used=cfg) + elb_type = elb_type or get_elb_type_from_customer(interactive, single, tier) shared_lb = get_shared_load_balancer(interactive, elb_type, platform, shared_lb, vpc) shared_lb_port = shared_lb_port or shared_lb_ops.get_shared_lb_port_from_customer(interactive, shared_lb) enable_spot = enable_spot or spotops.get_spot_request_from_customer(interactive) @@ -533,48 +533,8 @@ def get_cname_from_customer(env_name): break return cname -def check_elb_type_from_configs(use_saved_config=False): - """ - Checks if the ELB type is present from either the .ebextensions or saved_configs directories. - :param use_saved_config: Boolean indicating if --cfg flag was used. - :return: True, else False. - """ - - # If --cfg flag is used, prioritize checking saved_configs first - if use_saved_config: - saved_configs_dir = './.elasticbeanstalk/saved_configs' - if os.path.exists(saved_configs_dir): - for config_file in os.listdir(saved_configs_dir): - with open(os.path.join(saved_configs_dir, config_file), 'r') as f: - try: - config = yaml.safe_load(f) - option_settings = config.get('OptionSettings', {}) - for namespace, setting in option_settings.items(): - if namespace == 'aws:elasticbeanstalk:environment' and setting.get('LoadBalancerType'): - return True - except yaml.YAMLError: - raise ValueError(f"Malformed YAML in file {config_file} in saved_configs.") - else: - # Then check in .ebextensions - ebextensions_dir = './.ebextensions' - if os.path.exists(ebextensions_dir): - for config_file in os.listdir(ebextensions_dir): - with open(os.path.join(ebextensions_dir, config_file), 'r') as f: - try: - config = yaml.safe_load(f) - option_settings = config.get('option_settings', []) - for setting in option_settings: - if setting.get('namespace') == 'aws:elasticbeanstalk:environment' and setting.get('option_name') == 'LoadBalancerType': - if setting.get('value'): - return True - except yaml.YAMLError: - raise ValueError(f"Malformed YAML in file {config_file} in .ebextensions.") - - - return False - -def get_elb_type_from_customer(interactive, single, tier, cfg_flag_used=False): +def get_elb_type_from_customer(interactive, single, tier): """ Prompt customer to specify the ELB type if operating in the interactive mode and on a load-balanced environment. @@ -586,9 +546,8 @@ def get_elb_type_from_customer(interactive, single, tier, cfg_flag_used=False): :param tier: the tier type of the environment :return: selected ELB type which is one among ['application', 'classic', 'network'] """ - elb_type_is_configured = check_elb_type_from_configs(use_saved_config=cfg_flag_used) - if single or (tier and not tier.is_webserver()) or elb_type_is_configured: - return + if single or (tier and not tier.is_webserver()): + return elif not interactive: return elb_names.APPLICATION_VERSION diff --git a/tests/unit/controllers/test_create.py b/tests/unit/controllers/test_create.py index 17f0207a8..93057c471 100644 --- a/tests/unit/controllers/test_create.py +++ b/tests/unit/controllers/test_create.py @@ -19,7 +19,6 @@ from unittest.mock import patch, mock_open from ebcli.controllers import create -from ebcli.controllers.create import check_elb_type_from_configs from ebcli.core import fileoperations from ebcli.core.ebcore import EB @@ -2377,77 +2376,6 @@ def test_get_template_name__config_file_name_passed_in( self.assertEqual('some_cfg', create.get_template_name('some_app', 'some_cfg')) - @mock.patch('yaml.safe_load') - @mock.patch('os.path.exists') - @mock.patch('os.listdir') - @mock.patch('builtins.open', new_callable=mock.mock_open, read_data="valid_yaml_content") - def test_check_elb_type_from_configs_saved_configs_prioritized(self, mock_file, mock_listdir, mock_exists, mock_yaml): - mock_exists.return_value = True - mock_listdir.return_value = ['config1.yaml'] - mock_yaml.return_value = { - 'OptionSettings': { - 'aws:elasticbeanstalk:environment': { - 'LoadBalancerType': True - } - } - } - - self.assertTrue(check_elb_type_from_configs(use_saved_config=True)) - - @mock.patch('yaml.safe_load') - @mock.patch('os.path.exists') - @mock.patch('os.listdir') - @mock.patch('builtins.open', new_callable=mock.mock_open, read_data="valid_yaml_content") - def test_check_elb_type_from_configs_ebextensions_checked(self, mock_file, mock_listdir, mock_exists, mock_yaml): - mock_exists.return_value = True - mock_listdir.return_value = ['config1.yaml'] - mock_yaml.return_value = { - 'option_settings': [ - { - 'namespace': 'aws:elasticbeanstalk:environment', - 'option_name': 'LoadBalancerType', - 'value': True - } - ] - } - - self.assertTrue(check_elb_type_from_configs(use_saved_config=False)) - - @mock.patch('os.path.exists') - @mock.patch('os.listdir') - @mock.patch('builtins.open', new_callable=mock.mock_open, read_data="invalid: yaml: data") - def test_check_elb_type_from_configs_malformed_yaml_raises_value_error(self, mock_file, mock_listdir, mock_exists): - mock_exists.return_value = True - mock_listdir.return_value = ['config1.yaml'] - - with self.assertRaises(ValueError): - check_elb_type_from_configs(use_saved_config=False) - - @mock.patch('os.path.exists') - @mock.patch('os.listdir') - @mock.patch('builtins.open', new_callable=mock.mock_open, read_data="option_settings: []") - def test_check_elb_type_from_configs_returns_none_when_elb_not_found(self, mock_file, mock_listdir, mock_exists): - mock_exists.return_value = True - mock_listdir.return_value = ['config1.yaml'] - - self.assertFalse(check_elb_type_from_configs(use_saved_config=False)) - - @mock.patch('yaml.safe_load') - @mock.patch('os.path.exists') - @mock.patch('os.listdir') - @mock.patch('builtins.open', new_callable=mock.mock_open, read_data="OptionSettings: {random_namespace: {random_option: random_value}}") - def test_check_elb_type_from_configs_setting_not_present_in_saved_configs(self, mock_file, mock_listdir, mock_exists, mock_yaml): - mock_exists.return_value = True - mock_listdir.return_value = ['config1.yaml'] - mock_yaml.return_value = { - 'random_namespace': { - 'random_option': 'random_value' - }} - - self.assertFalse(check_elb_type_from_configs(use_saved_config=True)) - - - def test_get_elb_type_from_customer__single_instance_environment(self): self.assertIsNone( create.get_elb_type_from_customer( @@ -2524,32 +2452,6 @@ def test_get_elb_type_from_customer__interactive_mode__not_applicable_for_worker ) ) - @mock.patch('ebcli.controllers.create.check_elb_type_from_configs') - def test_get_elb_type_from_customer_elb_type_configured_interactive(self, mock_check_elb): - mock_check_elb.return_value = True # ELB type is configured - - result = create.get_elb_type_from_customer( - interactive=True, - single=False, - tier=None, - cfg_flag_used=True - ) - - self.assertIsNone(result) - - @mock.patch('ebcli.controllers.create.check_elb_type_from_configs') - def test_get_elb_type_from_customer_elb_type_configured_non_interactive(self, mock_check_elb): - mock_check_elb.return_value = True # ELB type is configured - - result = create.get_elb_type_from_customer( - interactive=False, - single=False, - tier=None, - cfg_flag_used=True - ) - - self.assertIsNone(result) - @mock.patch('ebcli.controllers.create.shared_lb_ops.validate_shared_lb_for_non_interactive') @mock.patch('ebcli.controllers.create.shared_lb_ops.get_shared_lb_from_customer') def test_get_shared_load_balancer__for_interactive( From af0b84c8a9b1fade7916516a38f8d54d95d22b86 Mon Sep 17 00:00:00 2001 From: Rahul Rajaram Date: Tue, 10 Sep 2024 23:26:39 -0400 Subject: [PATCH 6/6] Declare support drop for Python < 3.8 and Python 2.7 --- setup.py | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/setup.py b/setup.py index 9e681d737..32c4ac23d 100755 --- a/setup.py +++ b/setup.py @@ -66,10 +66,12 @@ 'Natural Language :: English', 'License :: OSI Approved :: Apache Software License', 'Programming Language :: Python', - 'Programming Language :: Python :: 2.7', - 'Programming Language :: Python :: 3', - 'Programming Language :: Python :: 3.4', - 'Programming Language :: Python :: 3.5', + 'Programming Language :: Python :: 3.7', + 'Programming Language :: Python :: 3.8', + 'Programming Language :: Python :: 3.9', + 'Programming Language :: Python :: 3.10', + 'Programming Language :: Python :: 3.11', + 'Programming Language :: Python :: 3.12', ), entry_points={ 'console_scripts': [