Skip to content

Commit

Permalink
Merge pull request #497 from aws/master
Browse files Browse the repository at this point in the history
merge from master
  • Loading branch information
NihalM99 authored Oct 20, 2023
2 parents ce84d0a + 0eeaf04 commit ac1ca0f
Show file tree
Hide file tree
Showing 17 changed files with 95 additions and 33 deletions.
3 changes: 3 additions & 0 deletions .github/dependabot.yml
Original file line number Diff line number Diff line change
Expand Up @@ -14,3 +14,6 @@ updates:
allow:
- dependency-name: "botocore*"
dependency-type: "all"
ignore:
- dependency-name: "botocore*"
update-types: [ "version-update:semver-patch" ]
14 changes: 14 additions & 0 deletions CHANGES.rst
Original file line number Diff line number Diff line change
@@ -1,6 +1,20 @@

Changelog
=========
--------------------
3.20.10 (2023-09-15)
--------------------
- Removed Docker-compose as a dependancy
- Fixed Codebuild image bug

-------------------
3.20.9 (2023-08-31)
-------------------
- Updated botocore requirement to `>1.23.41,<1.32.0`
- Updated six requirement to `>=1.11.0,<1.17.0`
- Update dependabot configuration to only update minor version
- Bug fix for Cloudformation pagination token

-------------------
3.20.8 (2023-08-15)
-------------------
Expand Down
2 changes: 1 addition & 1 deletion ebcli/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,4 +11,4 @@
# distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF
# ANY KIND, either express or implied. See the License for the specific
# language governing permissions and limitations under the License.
__version__ = '3.20.8'
__version__ = '3.20.10'
5 changes: 4 additions & 1 deletion ebcli/containers/commands.py
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@
from ebcli.lib import utils
from ebcli.objects.exceptions import ValidationError, CommandError
from ebcli.resources.strings import strings
from .utils import is_docker_compose_installed


EXPOSE_CMD = 'EXPOSE'
Expand Down Expand Up @@ -113,7 +114,9 @@ def up(compose_path=None, allow_insecure_ssl=False):


def _compose_run(args):
utils.exec_cmd_live_output(['docker-compose'] + args)
if not is_docker_compose_installed():
raise RuntimeError("Docker Compose is not installed. Please install it and try again.")
utils.exec_cmd_live_output(['docker','compose'] + args)


def get_container_lowlvl_info(container_id):
Expand Down
8 changes: 8 additions & 0 deletions ebcli/containers/utils.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
import subprocess

def is_docker_compose_installed():
try:
subprocess.run(['docker','compose','version'], check=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
return True
except subprocess.CalledProcessError:
return False
2 changes: 1 addition & 1 deletion ebcli/controllers/create.py
Original file line number Diff line number Diff line change
Expand Up @@ -218,7 +218,7 @@ def do_command(self):
if (spot_max_price or on_demand_base_capacity or on_demand_above_base_capacity) and not enable_spot:
raise InvalidOptionsError(strings['create.missing_enable_spot'])

if instance_types is "":
if instance_types == "":
raise InvalidOptionsError(strings['spot.instance_types_validation'])

if itype and instance_types:
Expand Down
41 changes: 32 additions & 9 deletions ebcli/controllers/initialize.py
Original file line number Diff line number Diff line change
Expand Up @@ -422,20 +422,43 @@ def get_keyname(keyname, keyname_of_existing_app, interactive, force_non_interac

def handle_buildspec_image(solution, force_non_interactive):
if not fileoperations.build_spec_exists():
return
return None

build_spec = fileoperations.get_build_configuration()

if not force_non_interactive and build_spec and build_spec.image is None:
LOG.debug("Buildspec file is present but image is does not exist. Attempting to fill best guess.")
LOG.debug("Buildspec file is present but image does not exist. Attempting to fill best guess.")
platform_image = initializeops.get_codebuild_image_from_platform(solution)

if type(platform_image) is dict:
io.echo(strings['codebuild.latestplatform'].replace('{platform}', solution))
else:
io.echo(prompts['codebuild.getplatform'].replace('{platform}', solution))
selected = utils.prompt_for_index_in_list([image['description'] for image in platform_image][0])
platform_image = [image for image in platform_image if selected == image['description']][0]
fileoperations.write_buildspec_config_header('Image', platform_image['name'])
if not platform_image:
io.echo("No images found for platform: {platform}".format(platform=solution))
return None

if isinstance(platform_image[0], dict):
if len(platform_image) == 1:
io.echo(strings['codebuild.latestplatform'].replace('{platform}', solution))
selected_image = platform_image[0]
else:
io.echo(prompts['codebuild.getplatform'].replace('{platform}', solution))
selected = int(utils.prompt_for_index_in_list([image['description'] for image in platform_image]))

if selected is not None and 0 <= selected < len(platform_image):
selected_description = platform_image[selected]['description']
else:
LOG.error("Invalid selection.")
return None

matching_images = [image for image in platform_image if selected_description == image['description']]

if not matching_images:
LOG.error(f"No matching images found for selected description: {selected}")
return None

selected_image = matching_images[0]
fileoperations.write_buildspec_config_header('Image', selected_image['name'])

return None



def set_default_env(interactive, force_non_interactive):
Expand Down
5 changes: 1 addition & 4 deletions ebcli/display/screen.py
Original file line number Diff line number Diff line change
Expand Up @@ -439,10 +439,7 @@ def scroll_down(self, reverse=False):
scrolled = visible_tables[0].scroll_down(reverse=reverse)
if scrolled:
for i in range(1, len(visible_tables)):
assert(
len(visible_tables[0].data) >= len(visible_tables[i].data),
'First table should be the largest'
)
assert len(visible_tables[0].data) >= len(visible_tables[i].data),'First table should be the largest'
visible_tables[i].scroll_to_id(scrolled, reverse=reverse)

def scroll_over(self, reverse=False):
Expand Down
2 changes: 1 addition & 1 deletion ebcli/lib/cloudformation.py
Original file line number Diff line number Diff line change
Expand Up @@ -72,7 +72,7 @@ def describe_stacks(stack_name=None):
all_stacks = response['Stacks']
while next_token:
utils.sleep(sleep_time=0.5)
response = _make_api_call('describe_stacks')
response = _make_api_call('describe_stacks',NextToken=next_token)
all_stacks.extend(response['Stacks'])
next_token = response.get('NextToken')
return all_stacks
Expand Down
2 changes: 1 addition & 1 deletion ebcli/lib/codebuild.py
Original file line number Diff line number Diff line change
Expand Up @@ -57,7 +57,7 @@ def list_curated_environment_images():
each available platform from CodeBuild.
:return: array of image dictionaries
"""
regex_search_version = "AWS ElasticBeanstalk - (.*)v([0-9]+\.[0-9]+\.[0-9]+)"
regex_search_version = r"AWS ElasticBeanstalk - (.*?)v([0-9]+\.[0-9]+\.[0-9]+)"
result = _make_api_call('list_curated_environment_images')
beanstalk_images = []
for platform in result['platforms']:
Expand Down
24 changes: 19 additions & 5 deletions ebcli/operations/initializeops.py
Original file line number Diff line number Diff line change
Expand Up @@ -95,12 +95,26 @@ def setup_ignore_file():


def get_codebuild_image_from_platform(platform):
platform_image = None
platform_images = [] # Store multiple matches in a list
beanstalk_images = codebuild.list_curated_environment_images()

# Log the entire list for debugging purposes
LOG.debug("Fetched beanstalk_images: {}".format(beanstalk_images))

# Validate that beanstalk_images is a list of dictionaries
if not isinstance(beanstalk_images, list) or not all(isinstance(i, dict) for i in beanstalk_images):
LOG.error("Unexpected format for beanstalk_images. Expected a list of dictionaries.")
return []

for image in beanstalk_images:
if platform in image['description']:
platform_image = image
if 'description' in image and platform in image['description']:
platform_images.append(image)

# If no platform-specific images found, return all images
if not platform_images:
LOG.debug("No matching platform images found. Returning all images.")
return beanstalk_images

LOG.debug("Searching for images for platform '{0}'. Found: {1}".format(platform, platform_image))
LOG.debug("Searching for images for platform '{0}'. Found: {1}".format(platform, platform_images))

return beanstalk_images if platform_image is None else platform_image
return platform_images
2 changes: 1 addition & 1 deletion requirements.txt
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
botocore>1.23.41,<1.31.32
botocore>1.23.41,<1.32.0
cement==2.8.2
colorama>=0.2.5,<0.4.4 # use the same range that 'docker-compose' uses
pathspec==0.10.1
Expand Down
1 change: 0 additions & 1 deletion setup.py
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,6 @@

}
if not sys.platform.startswith('win'):
requires.append('docker-compose >= 1.25.2, <= 1.29.2')
requires.append('blessed>=1.9.5')


Expand Down
9 changes: 5 additions & 4 deletions tests/unit/controllers/test_init.py
Original file line number Diff line number Diff line change
Expand Up @@ -1436,7 +1436,7 @@ def test_handle_buildspec_image__multiple_matching_images_for_platform(
'description': 'Java 8 Running on Amazon Linux 32bit '
}
]
prompt_for_index_in_list_mock.return_value = 'Java 8 Running on Amazon Linux 32bit '
prompt_for_index_in_list_mock.return_value = 1

self.assertIsNone(initialize.handle_buildspec_image('Java 8', False))

Expand All @@ -1453,7 +1453,8 @@ def test_handle_buildspec_image__multiple_matching_images_for_platform(
)
]
)
prompt_for_index_in_list_mock.assert_called_once_with('Java 8 Running on Amazon Linux 64bit ')
prompt_for_index_in_list_mock.assert_called_once_with(['Java 8 Running on Amazon Linux 64bit ', 'Java 8 Running on Amazon Linux 32bit '])


@mock.patch('ebcli.controllers.initialize.fileoperations.get_build_configuration')
@mock.patch('ebcli.controllers.initialize.initializeops.get_codebuild_image_from_platform')
Expand Down Expand Up @@ -1481,10 +1482,10 @@ def test_handle_buildspec_image__single_image_matches(
)
build_spec_exists_mock.return_value = True
get_build_configuration_mock.return_value = build_config
get_codebuild_image_from_platform_mock.return_value = {
get_codebuild_image_from_platform_mock.return_value = [{
'name': 'aws/codebuild/eb-java-8-amazonlinux-64:2.1.6',
'description': 'Java 8 Running on Amazon Linux 64bit '
}
}]
prompt_for_index_in_list_mock.return_value = 'Java 8 Running on Amazon Linux 32bit '

self.assertIsNone(initialize.handle_buildspec_image('Java 8', False))
Expand Down
2 changes: 1 addition & 1 deletion tests/unit/operations/tagops/test_taglist.py
Original file line number Diff line number Diff line change
Expand Up @@ -134,7 +134,7 @@ def test_validate_key_value_pair__unicode_characters(self):
Python identifies certain Unicode characters as letters, but not others.
For example, the greek delta symbol is not a Unicode letter, and hence
will not match `\w` during regex comparisons, whereas the Swedish `a`
will not match `\\w` during regex comparisons, whereas the Swedish `a`
is a letter.
It is also to be noted that even if Python recognizes a Unicode character
Expand Down
2 changes: 1 addition & 1 deletion tests/unit/operations/test_envvarops.py
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@ def assertListsOfDictsEquivalent(self, ls1, ls2):
Counter(frozenset(iteritems(d)) for d in ls2))

def test_sanitize_environment_variables_from_customer_input(self):
environment_variables_input = ' """ DB_USER""" = "\" r=o\"o\'t\"\" " , DB_PAS\ = SWORD="\"pass=\'\"word\""'
environment_variables_input = ' """ DB_USER""" = "\" r=o\"o\'t\"\" " , DB_PAS\\ = SWORD="\"pass=\'\"word\""'

self.assertEqual(
[
Expand Down
4 changes: 2 additions & 2 deletions tests/unit/operations/test_initializeops.py
Original file line number Diff line number Diff line change
Expand Up @@ -68,8 +68,8 @@ def test_get_codebuild_image_from_platform_that_exists(self, mock_codebuild):

images_for_platform = initializeops.get_codebuild_image_from_platform("Java 8")

self.assertEqual(expected_image, images_for_platform,
"Expected '{0}' but got: {1}".format(expected_image, images_for_platform))
self.assertEqual([expected_image], images_for_platform,
"Expected '{0}' but got: {1}".format([expected_image], images_for_platform))

@mock.patch('ebcli.operations.initializeops.codebuild')
def test_get_codebuild_image_from_platform_that_does_not_match(self, mock_codebuild):
Expand Down

0 comments on commit ac1ca0f

Please sign in to comment.