def handle_buildspec_image(solution, force_non_interactive): if not fileoperations.build_spec_exists(): return 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." ) 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'])
def test_prompt_for_index_in_list__explicit_none_default_no_selection_made( self, echo_mock, prompt_mock, ): call_tracker = mock.Mock() call_tracker.attach_mock(echo_mock, 'echo_mock') call_tracker.attach_mock(prompt_mock, 'prompt_mock') lst = ['a', 'b', 'c'] prompt_mock.side_effect = [0, 1] result = utils.prompt_for_index_in_list(lst, None) call_tracker.assert_has_calls([ mock.call.echo_mock('1)', 'a'), mock.call.echo_mock('2)', 'b'), mock.call.echo_mock('3)', 'c'), mock.call.prompt_mock('make a selection', default=0), mock.call.echo_mock( 'Sorry, that is not a valid choice. Please choose a number between 1 and 3.' ), mock.call.prompt_mock('make a selection', default=0), mock.call.echo_mock(), ], any_order=False) self.assertEqual(0, result)
def open_webpage(cnt_viewmodel): """ Open the webpage at container ip and host port we exposed when we ran this container. Raise error if container not running and prompt user to choose host port if multiple host ports exposed under this container. :param cnt_viewmodel: ContainerViewModel: contains view info about container :return: None """ if not cnt_viewmodel.is_running(): raise RuntimeError(strings['local.open.nocontainer']) # Get container id, exposed host port pairs cid_hostports = cnt_viewmodel.get_cid_hostport_pairs() num_exposed_hostports = cnt_viewmodel.num_exposed_hostports() if num_exposed_hostports == 1: _, host_port = cid_hostports[0] elif num_exposed_hostports > 1: io.echo() io.echo('Select a container applcation to open') io.echo() disp = ['Container {}, host port {}'.format(cid, p) for cid, p in cid_hostports] ind = utils.prompt_for_index_in_list(disp) _, host_port = cid_hostports[ind] else: raise RuntimeError(strings['local.open.noexposedport']) url = '{}:{}'.format(cnt_viewmodel.ip, host_port) commonops.open_webpage_in_browser(url)
def get_shared_lb_from_customer(interactive, elb_type, platform, vpc=None): """ Prompt customer to select if they would like to use shared load balancer. Selection defaults to 'N' Prompt customer to select load balancer from a list, if they selected 'y' for previous prompt return: ARN of selected load balancer """ if not interactive or elb_type != elb_names.APPLICATION_VERSION: return alb_list = elasticbeanstalk.list_application_load_balancers(platform, vpc) if not alb_list: return should_continue = io.get_boolean_response( text=prompts['sharedlb.shared_load_balancer_request_prompt'], default=False) if not should_continue: return alb_list_display_labels = [] for load_balancer_arn in alb_list: load_balancer_name = parse_load_balancer_name(load_balancer_arn) alb_list_display_labels.append(load_balancer_name + ' - ' + load_balancer_arn) io.echo(prompts['sharedlb.shared_load_balancer_prompt']) selected_index = utils.prompt_for_index_in_list(alb_list_display_labels, default=1) return alb_list[selected_index]
def prompt_for_platform_branch(family): branches = platform_branch_ops.list_nonretired_platform_branches() branches = [branch for branch in branches if branch['PlatformName'] == family] branches = _sort_platform_branches_for_prompt(branches) if len(branches) == 1: return PlatformBranch.from_platform_branch_summary(branches[0]) branch_display_names = [_generate_platform_branch_prompt_text(branch) for branch in branches] default = utils.index_of( branches, value=platform_branch_lifecycle_states.SUPPORTED, key=lambda b: b['LifecycleState']) if default == -1: default = None else: default += 1 io.echo(prompts['platformbranch.prompt']) index = utils.prompt_for_index_in_list(branch_display_names, default=default) return PlatformBranch.from_platform_branch_summary(branches[index])
def test_prompt_for_index_in_list__explicit_none_default( self, echo_mock, prompt_mock, ): call_tracker = mock.Mock() call_tracker.attach_mock(echo_mock, 'echo_mock') call_tracker.attach_mock(prompt_mock, 'prompt_mock') lst = ['a', 'b', 'c'] prompt_mock.return_value = 1 result = utils.prompt_for_index_in_list(lst, None) call_tracker.assert_has_calls([ mock.call.echo_mock('1)', 'a'), mock.call.echo_mock('2)', 'b'), mock.call.echo_mock('3)', 'c'), mock.call.prompt_mock('make a selection', default=0), mock.call.echo_mock(), ], any_order=False) self.assertEqual(0, result)
def do_command(self): # get arguments self.interactive = self.app.pargs.interactive self.region = self.app.pargs.region self.noverify = self.app.pargs.no_verify_ssl self.force_non_interactive = False # Determine if the customer is avoiding interactive mode by setting the platform flag if self.app.pargs.platform: self.force_non_interactive = True # Code Commit integration self.source = self.app.pargs.source source_location = None branch = None repository = None if self.source is not None: source_location, repository, branch = utils.parse_source(self.source) # The user specifies directories to initialize self.modules = self.app.pargs.modules if self.modules and len(self.modules) > 0: self.initialize_multiple_directories() return default_env = self.get_old_values() fileoperations.touch_config_folder() if self.interactive: self.region = get_region(self.region, self.interactive, self.force_non_interactive) else: self.region = get_region_from_inputs(self.region) aws.set_region(self.region) self.region = set_up_credentials(self.app.pargs.profile, self.region, self.interactive) self.solution = self.get_solution_stack() self.app_name = self.get_app_name() if self.noverify: fileoperations.write_config_setting('global', 'no-verify-ssl', True) if not default_env and not self.interactive: # try to get default env from config file if exists try: default_env = commonops.get_current_branch_environment() except NotInitializedError: default_env = None elif self.interactive: default_env = None if self.force_non_interactive: default_env = '/ni' # Create application sstack, key = commonops.pull_down_app_info(self.app_name, default_env=default_env) if elasticbeanstalk.application_exist(self.app_name) \ else commonops.create_app(self.app_name, default_env=default_env) if not self.solution: self.solution = sstack platform_set = False if not self.solution or \ (self.interactive and not self.app.pargs.platform): if fileoperations.env_yaml_exists(): env_yaml_platform = fileoperations.get_platform_from_env_yaml() if env_yaml_platform: platform = solutionstack.SolutionStack(env_yaml_platform).platform_shorthand self.solution = platform platform_set = True if not platform_set: self.solution = solution_stack_ops.get_solution_stack_from_customer().platform_shorthand # Select CodeBuild image if BuildSpec is present do not prompt or show if we are non-interactive if fileoperations.build_spec_exists() and not self.force_non_interactive: build_spec = fileoperations.get_build_configuration() if build_spec is not None and build_spec.image is None: LOG.debug("Buildspec file is present but image is does not exist. Attempting to fill best guess.") platform_image = initializeops.get_codebuild_image_from_platform(self.solution) # If the return is a dictionary then it must be a single image and we can use that automatically if type(platform_image) is dict: io.echo('codebuild.latestplatform'.replace('{platform}', self.solution)) else: # Otherwise we have an array for images which we must prompt the customer to pick from io.echo(prompts['codebuild.getplatform'].replace('{platform}', self.solution)) selected = utils.prompt_for_index_in_list(map(lambda image: image['description'], platform_image)) platform_image = platform_image[selected] platform_image['name'] = utils.decode_bytes(platform_image['name']) # Finally write the CodeBuild image back to the buildspec file fileoperations.write_config_setting(fileoperations.buildspec_config_header, 'Image', platform_image['name'], file=fileoperations.buildspec_name) # Setup code commit integration # Ensure that git is setup source_control = SourceControl.get_source_control() try: source_control_setup = source_control.is_setup() if source_control_setup is None: source_control_setup = False except CommandError: source_control_setup = False default_branch_exists = False if gitops.git_management_enabled() and not self.interactive: default_branch_exists = True # Warn the customer if they picked a region that CodeCommit is not supported codecommit_region_supported = codecommit.region_supported(self.region) if self.source is not None and not codecommit_region_supported: io.log_warning(strings['codecommit.badregion']) # Prompt customer to opt into CodeCommit unless one of the follows holds: if self.force_non_interactive: prompt_codecommit = False elif not codecommit.region_supported(self.region): prompt_codecommit = False elif self.source and source_location.lower() != 'codecommit': # Do not prompt if customer has already specified a code source to # associate the EB workspace with prompt_codecommit = False elif default_branch_exists: # Do not prompt if customer has already configured the EB application # in the present working directory with Git prompt_codecommit = False else: prompt_codecommit = True # Prompt for interactive CodeCommit if prompt_codecommit: if not source_control_setup: io.echo(strings['codecommit.nosc']) else: io.echo(strings['codecommit.ccwarning']) try: if not self.source: io.validate_action(prompts['codecommit.usecc'], "y") # Setup git config settings for code commit credentials source_control.setup_codecommit_cred_config() # Get user specified repository remote_url = None if repository is None: repository = get_repository_interactive() else: try: setup_codecommit_remote_repo(repository, source_control) except ServiceError as ex: if self.source: create_codecommit_repository(repository) setup_codecommit_remote_repo(repository, source_control) else: io.log_error(strings['codecommit.norepo']) raise ex # Get user specified branch if branch is None: branch = get_branch_interactive(repository) else: try: codecommit.get_branch(repository, branch) except ServiceError as ex: if self.source: create_codecommit_branch(source_control, branch) else: io.log_error(strings['codecommit.nobranch']) raise ex source_control.setup_existing_codecommit_branch(branch, remote_url) except ValidationError: LOG.debug("Denied option to use CodeCommit, continuing initialization") # Initialize the whole setup initializeops.setup(self.app_name, self.region, self.solution, dir_path=None, repository=repository, branch=branch) if 'IIS' not in self.solution: self.keyname = self.get_keyname(default=key) if self.keyname == -1: self.keyname = None fileoperations.write_config_setting('global', 'default_ec2_keyname', self.keyname) # Default to including git submodules when creating zip files through `eb create`/`eb deploy`. fileoperations.write_config_setting('global', 'include_git_submodules', True)
def do_command(self): # get arguments self.interactive = self.app.pargs.interactive self.region = self.app.pargs.region self.noverify = self.app.pargs.no_verify_ssl self.force_non_interactive = False # Determine if the customer is avoiding interactive mode by setting the platform flag if self.app.pargs.platform: self.force_non_interactive = True # Code Commit integration self.source = self.app.pargs.source source_location = None branch = None repository = None if self.source is not None: source_location, repository, branch = utils.parse_source( self.source) # The user specifies directories to initialize self.modules = self.app.pargs.modules if self.modules and len(self.modules) > 0: self.initialize_multiple_directories() return default_env = self.get_old_values() fileoperations.touch_config_folder() if self.interactive: self.region = get_region(self.region, self.interactive, self.force_non_interactive) else: self.region = get_region_from_inputs(self.app.pargs.region) aws.set_region(self.region) # Warn the customer if they picked a region that CodeCommit is not supported codecommit_region_supported = codecommit.region_supported(self.region) if self.source is not None and not codecommit_region_supported: io.log_warning(strings['codecommit.badregion']) self.region = set_up_credentials(self.app.pargs.profile, self.region, self.interactive) self.solution = self.get_solution_stack() self.app_name = self.get_app_name() if self.noverify: fileoperations.write_config_setting('global', 'no-verify-ssl', True) if not default_env and not self.interactive: # try to get default env from config file if exists try: default_env = commonops.get_current_branch_environment() except NotInitializedError: default_env = None elif self.interactive: default_env = None if self.force_non_interactive: default_env = '/ni' # Create application sstack, key = commonops.pull_down_app_info(self.app_name, default_env=default_env) if elasticbeanstalk.application_exist(self.app_name) \ else commonops.create_app(self.app_name, default_env=default_env) if not self.solution: self.solution = sstack platform_set = False if not self.solution or \ (self.interactive and not self.app.pargs.platform): if fileoperations.env_yaml_exists(): env_yaml_platform = fileoperations.get_platform_from_env_yaml() if env_yaml_platform: platform = solutionstack.SolutionStack( env_yaml_platform).version self.solution = platform platform_set = True if not platform_set: result = commonops.prompt_for_solution_stack() self.solution = result.version # Select CodeBuild image if BuildSpec is present do not prompt or show if we are non-interactive if fileoperations.build_spec_exists( ) and not self.force_non_interactive: build_spec = fileoperations.get_build_configuration() if build_spec is not None and build_spec.image is None: LOG.debug( "Buildspec file is present but image is does not exist. Attempting to fill best guess." ) platform_image = initializeops.get_codebuild_image_from_platform( self.solution) # If the return is a dictionary then it must be a single image and we can use that automatically if type(platform_image) is dict: io.echo('codebuild.latestplatform'.replace( '{platform}', self.solution)) else: # Otherwise we have an array for images which we must prompt the customer to pick from io.echo(prompts['codebuild.getplatform'].replace( '{platform}', self.solution)) selected = utils.prompt_for_index_in_list( map(lambda image: image['description'], platform_image)) platform_image = platform_image[selected] platform_image['name'] = utils.decode_bytes( platform_image['name']) # Finally write the CodeBuild image back to the buildspec file fileoperations.write_config_setting( fileoperations.buildspec_config_header, 'Image', platform_image['name'], file=fileoperations.buildspec_name) # Setup code commit integration # Ensure that git is setup source_control = SourceControl.get_source_control() try: source_control_setup = source_control.is_setup() if source_control_setup is None: source_control_setup = False except CommandError: source_control_setup = False default_branch_exists = False if gitops.git_management_enabled() and not self.interactive: default_branch_exists = True prompt_codecommit = True # Do not prompt if we are in non-interactive mode, the region is not supported for CodeCommit, # the specified source is from CodeCommit OR we already have default CodeCommit values set. if self.force_non_interactive \ or not codecommit.region_supported(self.region) \ or self.source is not None \ or default_branch_exists: prompt_codecommit = False # Prompt for interactive CodeCommit if prompt_codecommit: if not source_control_setup: io.echo(strings['codecommit.nosc']) else: io.echo(strings['codecommit.ccwarning']) try: io.validate_action(prompts['codecommit.usecc'], "y") # Setup git config settings for code commit credentials source_control.setup_codecommit_cred_config() # Get user specified repository if repository is None: repository = get_repository_interactive() else: try: result = codecommit.get_repository(repository) source_control.setup_codecommit_remote_repo( remote_url=result['repositoryMetadata'] ['cloneUrlHttp']) except ServiceError as ex: io.log_error(strings['codecommit.norepo']) raise ex # Get user specified branch if branch is None: branch = get_branch_interactive(repository) else: try: codecommit.get_branch(repository, branch) except ServiceError as ex: io.log_error(strings['codecommit.nobranch']) raise ex source_control.setup_existing_codecommit_branch(branch) except ValidationError: LOG.debug( "Denied option to use CodeCommit, continuing initialization" ) # Initialize the whole setup initializeops.setup(self.app_name, self.region, self.solution, dir_path=None, repository=repository, branch=branch) if 'IIS' not in self.solution: self.keyname = self.get_keyname(default=key) if self.keyname == -1: self.keyname = None fileoperations.write_config_setting('global', 'default_ec2_keyname', self.keyname) # Default to including git submodules when creating zip files through `eb create`/`eb deploy`. fileoperations.write_config_setting('global', 'include_git_submodules', True)