Beispiel #1
0
def _prompt_issue(recent_command_list):
    if recent_command_list:
        max_idx = len(recent_command_list) - 1
        ans = -1
        help_string = 'Please choose between 0 and {}, or enter q to quit: '.format(
            max_idx)

        while ans < 0 or ans > max_idx:
            try:
                ans = prompt(_MSG_CMD_ISSUE.format(max_idx),
                             help_string=help_string)
                if ans.lower() in ["q", "quit"]:
                    ans = ans.lower()
                    break
                ans = int(ans)
            except ValueError:
                logger.warning(help_string)
                ans = -1

    else:
        ans = None
        help_string = 'Please choose between Y and N: '

        while not ans:
            ans = prompt(_MSG_ISSUE, help_string=help_string)
            if ans.lower() not in ["y", "n", "yes", "no", "q"]:
                ans = None
                continue

            # strip to short form
            ans = ans[0].lower() if ans else None

    if ans in ["y", "n"]:
        if ans == "y":
            browser_instruction, url, issue_body = _build_issue_info_tup()
        else:
            return False
    else:
        if ans in ["q", "quit"]:
            return False
        if ans == 0:
            browser_instruction, url, issue_body = _build_issue_info_tup()
        else:
            browser_instruction, url, issue_body = _build_issue_info_tup(
                recent_command_list[ans])

    logger.info(issue_body)
    print(browser_instruction)

    # if we are not in cloud shell and can launch a browser, launch it with the issue draft
    if can_launch_browser() and not in_cloud_console():
        open_page_in_browser(url)
    else:
        print(
            "There isn't an available browser to create an issue draft. You can copy and paste the url"
            " below in a browser to submit.\n\n{}\n\n".format(url))

    return True
Beispiel #2
0
def _prompt_issue(recent_command_list):
    if recent_command_list:
        max_idx = len(recent_command_list) - 1
        ans = -1
        help_string = 'Please choose between 0 and {}, or enter q to quit: '.format(
            max_idx)

        while ans < 0 or ans > max_idx:
            try:
                ans = prompt(_MSG_CMD_ISSUE.format(max_idx),
                             help_string=help_string)
                if ans.lower() in ["q", "quit"]:
                    ans = ans.lower()
                    break
                ans = int(ans)
            except ValueError:
                logger.warning(help_string)
                ans = -1

    else:
        ans = None
        help_string = 'Please choose between Y and N: '

        while not ans:
            ans = prompt(_MSG_ISSUE, help_string=help_string)
            if ans.lower() not in ["y", "n", "yes", "no", "q"]:
                ans = None
                continue

            # strip to short form
            ans = ans[0].lower() if ans else None

    if ans in ["y", "n"]:
        if ans == "y":
            prefix, body, url = _build_issue_info_tup()
        else:
            return False
    else:
        if ans in ["q", "quit"]:
            return False
        if ans == 0:
            prefix, body, url = _build_issue_info_tup()
        else:
            prefix, body, url = _build_issue_info_tup(recent_command_list[ans])

    print(prefix)

    # open issues page in browser and copy issue body to clipboard
    try:
        pyperclip.copy(body)
    except pyperclip.PyperclipException as ex:
        logger.debug(ex)

    logger.info(body)
    open_page_in_browser(url)

    return True
Beispiel #3
0
def resolve_registry_from_cli_args(registry_server, registry_user,
                                   registry_pass):
    if registry_server is not None:
        if registry_user is None and registry_pass is None:
            registry_user = prompt("Please enter the registry's username: "******"Please enter the registry's password: "******"Please enter the registry's password: ")
    return (registry_server, registry_user, registry_pass)
    def _create_project(self):
        project_name = prompt("Please enter a name for your new project: ")
        project = self.adbp.create_project(self.organization_name, project_name)
        # Keep retrying to create a new project if it fails
        while not project.valid:
            self.logger.error(project.message)
            project_name = prompt("Please enter a name for your new project: ")
            project = self.adbp.create_project(self.organization_name, project_name)

        self.project_name = project.name
        self.created_project = True
Beispiel #5
0
    def _create_project(self):
        project_name = prompt("Please enter the name of the new project: ")
        project = self.adbp.create_project(self.organization_name, project_name)
        # Keep retrying to create a new project if it fails
        while not project.valid:
            self.logger.error(project.message)
            project_name = prompt("Please enter the name of the new project: ")
            project = self.adbp.create_project(self.organization_name, project_name)

        url = "https://dev.azure.com/" + self.organization_name + "/" + project.name + "/"
        self.logger.info("Finished creating the new project. Click the link to see your new project: %s", url)
        self.project_name = project.name
        self.created_project = True
Beispiel #6
0
def handle_feedback():
    try:
        print(MSG_INTR)
        score = _prompt_net_promoter_score()
        if score == 10:
            suggestion = prompt(MSG_GOOD)
        else:
            suggestion = prompt(MSG_BAD)
        email_address = prompt(MSG_EMIL)
        set_feedback('[{}]{}[{}]'.format(score, suggestion, email_address))
        print(MSG_THNK)
    except NoTTYException:
        raise CLIError('This command is interactive and no tty available.')
    except (EOFError, KeyboardInterrupt):
        print()
def _prompt_repair_username(namespace):

    from knack.prompting import prompt, NoTTYException
    try:
        namespace.repair_username = prompt('Repair VM admin username: '******'Please specify username in non-interactive mode.')
    def _create_organization(self):
        self.logger.info(
            "Starting process to create a new Azure DevOps organization")
        regions = self.adbp.list_regions()
        region_names = sorted(
            [region.display_name for region in regions.value])
        self.logger.info(
            "The region for an Azure DevOps organization is where the organization will be located. "
            "Try locate it near your other resources and your location")
        choice_index = prompt_choice_list(
            'Please select a region for the new organization: ', region_names)
        region = [
            region for region in regions.value
            if region.display_name == region_names[choice_index]
        ][0]

        while True:
            organization_name = prompt(
                "Please enter a name for your new organization: ")
            new_organization = self.adbp.create_organization(
                organization_name, region.name)
            if new_organization.valid is False:
                self.logger.warning(new_organization.message)
                self.logger.warning("Note: all names must be globally unique")
            else:
                break

        self.organization_name = new_organization.name
Beispiel #9
0
 def process_github_repository(self):
     while (
             not self.github_repository or
             not AzureDevopsBuildProvider.check_github_repository(self.github_pat, self.github_repository)
     ):
         self.github_repository = prompt(msg="Github Repository Path (e.g. Azure/azure-cli): ").strip()
     self.logger.warning("Successfully found Github repository.")
def _prompt_for_prop_input(prop_name, prop_type):
    verify_is_a_tty_or_raise_error('The template requires a few inputs. These cannot be provided as in command '
                                   'arguments. It can only be input interatively.')
    val = prompt(msg='Please enter a value for {prop_name}: '.format(prop_name=prop_name),
                 help_string='Value of type {prop_type} is required.'.format(prop_type=prop_type))
    print('')
    return val
Beispiel #11
0
    def _create_organization(self):
        self.logger.info(
            "Starting process to create a new Azure DevOps organization")
        regions = self.adbp.list_regions()
        region_names = sorted(
            [region.display_name for region in regions.value])
        self.logger.info("The region for an Azure DevOps organization is where the organization will be located. Try locate it near your other resources and your location")  # pylint: disable=line-too-long
        choice_index = prompt_choice_list(
            'Please select a region for the new organization: ', region_names)
        region = [
            region for region in regions.value
            if region.display_name == region_names[choice_index]
        ][0]

        while True:
            organization_name = prompt(
                "Please enter the name of the new organization: ")
            new_organization = self.adbp.create_organization(
                organization_name, region.name)
            if new_organization.valid is False:
                self.logger.warning(new_organization.message)
                self.logger.warning("Note: any name must be globally unique")
            else:
                break
        url = "https://dev.azure.com/" + new_organization.name + "/"
        self.logger.info(
            "Finished creating the new organization. Click the link to see your new organization: %s",
            url)
        self.organization_name = new_organization.name
def _handle_yml_props(params_required, template_id, cix_client, repo_name, organization, project):
    logger.warning('The template requires a few inputs. We will help you fill them out')
    params_to_render = {}
    for param in params_required:
        param_name_for_user = param.name
        # override with more user friendly name if available
        if param.display_name:
            param_name_for_user = param.display_name
        logger.debug('Looking for param %s in props', param.name)
        prop_found = False
        if param.default_value:
            prop_found = True
            user_input_val = prompt(msg='Enter a value for {param_name} [Press Enter for default: {param_default}]:'
                                    .format(param_name=param_name_for_user, param_default=param.default_value))
            print('')
            if user_input_val:
                params_to_render[param.name] = user_input_val
            else:
                params_to_render[param.name] = param.default_value
        elif _is_intelligent_handling_enabled_for_prop_type(prop_name=param.name, prop_type=param.type):
            logger.debug('This property is handled intelligently (Name: %s) (Type: %s)', param.name, param.type)
            fetched_value = fetch_yaml_prop_intelligently(param.name, param.type, organization, project, repo_name)
            if fetched_value is not None:
                logger.debug('Auto filling param %s with value %s', param.name, fetched_value)
                params_to_render[param.name] = fetched_value
                prop_found = True
        if not prop_found:
            input_value = _prompt_for_prop_input(param_name_for_user, param.type)
            params_to_render[param.name] = input_value
            prop_found = True
    rendered_template = cix_client.render_template(template_id=template_id,
                                                   template_parameters={'tokens': params_to_render})
    return rendered_template.content, rendered_template.assets
def _add_to_codeowners(repo_path, prefix, name, github_alias):
    # add the user Github alias to the CODEOWNERS file for new packages
    if not github_alias:
        display(
            '\nWhat is the Github alias of the person responsible for maintaining this package?'
        )
        while not github_alias:
            github_alias = prompt('Alias: ')

    # accept a raw alias or @alias
    github_alias = '@{}'.format(
        github_alias) if not github_alias.startswith('@') else github_alias
    try:
        codeowners = find_files(repo_path, 'CODEOWNERS')[0]
    except IndexError:
        raise CLIError('unexpected error: unable to find CODEOWNERS file.')

    if prefix == EXTENSION_PREFIX:
        new_line = '/src/{}{}/ {}'.format(prefix, name, github_alias)
    else:
        # ensure Linux-style separators when run on Windows
        new_line = '/{} {}'.format(
            os.path.join('', _MODULE_ROOT_PATH, name, ''),
            github_alias).replace('\\', '/')

    with open(codeowners, 'a') as f:
        f.write(new_line)
        f.write('\n')
def create_connection(connection_info_json, prompt_prefix, typeOfInfo):
    user_name = connection_info_json.get('userName', None) or prompt(prompt_prefix + 'Username: '******'password', None) or prompt_pass(msg=prompt_prefix + 'Password: '******'serverName', None)
    if "mysql" in typeOfInfo:
        port = connection_info_json.get('port', 3306)
        return MySqlConnectionInfo(user_name=user_name,
                                   password=password,
                                   server_name=server_name,
                                   port=port)
    elif "postgres" in typeOfInfo:
        database_name = connection_info_json.get('databaseName', "postgres")
        port = connection_info_json.get('port', 5432)
        return PostgreSqlConnectionInfo(user_name=user_name,
                                        password=password,
                                        server_name=server_name,
                                        database_name=database_name,
                                        port=port)
    elif "mongo" in typeOfInfo:
        connection_string = connection_info_json['connectionString']
        # Strip out the username and password from the connection string (if they exist) to store them securely.
        rex_conn_string = re.compile(r'^(mongodb://|mongodb\+srv://|http://|https://)(.*:.*@)?(.*)')
        connection_string_match = rex_conn_string.search(connection_string)
        connection_string = connection_string_match.group(1) + connection_string_match.group(3)
        if connection_string_match.group(2) is not None and not user_name and not password:
            rex_un_pw = re.compile('^(.*):(.*)@')
            un_pw_match = rex_un_pw.search(connection_string_match.group(2))
            user_name = un_pw_match.group(1)
            password = un_pw_match.group(2)
        return MongoDbConnectionInfo(connection_string=connection_string,
                                     user_name=user_name,
                                     password=password)
    else:
        # If no match, Pass the connection info through
        return connection_info_json
Beispiel #15
0
def create_connection(connection_info_json, prompt_prefix, typeOfInfo):
    user_name = connection_info_json.get('userName', None) or prompt(prompt_prefix + 'Username: '******'password', None) or prompt_pass(msg=prompt_prefix + 'Password: '******'serverName', None)
    if "mysql" in typeOfInfo:
        port = connection_info_json.get('port', 3306)
        return MySqlConnectionInfo(user_name=user_name,
                                   password=password,
                                   server_name=server_name,
                                   port=port)
    elif "postgres" in typeOfInfo:
        database_name = connection_info_json.get('databaseName', "postgres")
        port = connection_info_json.get('port', 5432)
        return PostgreSqlConnectionInfo(user_name=user_name,
                                        password=password,
                                        server_name=server_name,
                                        database_name=database_name,
                                        port=port)
    elif "mongo" in typeOfInfo:
        connection_string = connection_info_json['connectionString']
        # Strip out the username and password from the connection string (if they exist) to store them securely.
        rex_conn_string = re.compile(r'^(mongodb://|mongodb\+srv://|http://|https://)(.*:.*@)?(.*)')
        connection_string_match = rex_conn_string.search(connection_string)
        connection_string = connection_string_match.group(1) + connection_string_match.group(3)
        if connection_string_match.group(2) is not None and not user_name and not password:
            rex_un_pw = re.compile('^(.*):(.*)@')
            un_pw_match = rex_un_pw.search(connection_string_match.group(2))
            user_name = un_pw_match.group(1)
            password = un_pw_match.group(2)
        return MongoDbConnectionInfo(connection_string=connection_string,
                                     user_name=user_name,
                                     password=password)
    else:
        # If no match, Pass the connection info through
        return connection_info_json
Beispiel #16
0
def create_connection(connection_info_json, prompt_prefix, typeOfInfo):
    typeOfInfo = typeOfInfo.lower()

    user_name = connection_info_json.get(
        'userName', None) or prompt(prompt_prefix + 'Username: '******'password', None) or prompt_pass(msg=prompt_prefix + 'Password: '******'serverName', None)
    if "mysql" in typeOfInfo:
        port = connection_info_json.get('port', 3306)
        return MySqlConnectionInfo(user_name=user_name,
                                   password=password,
                                   server_name=server_name,
                                   port=port)
    elif "postgre" in typeOfInfo:
        database_name = connection_info_json.get('databaseName', "postgres")
        port = connection_info_json.get('port', 5432)
        return PostgreSqlConnectionInfo(user_name=user_name,
                                        password=password,
                                        server_name=server_name,
                                        database_name=database_name,
                                        port=port)
    data_source = connection_info_json.get('dataSource', None)
    authentication = connection_info_json.get('authentication', None)
    encrypt_connection = connection_info_json.get('encryptConnection', None)
    trust_server_certificate = connection_info_json.get(
        'trustServerCertificate', None)
    additional_settings = connection_info_json.get('additionalSettings', None)
    return SqlConnectionInfo(user_name=user_name,
                             password=password,
                             data_source=data_source,
                             authentication=authentication,
                             encrypt_connection=encrypt_connection,
                             trust_server_certificate=trust_server_certificate,
                             additional_settings=additional_settings)
Beispiel #17
0
def _config_env_public_azure(cli_ctx, _):
    from adal.adal_error import AdalError
    from azure.cli.core.commands.client_factory import get_mgmt_service_client
    from azure.cli.core._profile import Profile
    from azure.cli.core.profiles import ResourceType
    # Determine if user logged in

    try:
        list(
            get_mgmt_service_client(
                cli_ctx,
                ResourceType.MGMT_RESOURCE_RESOURCES).resources.list())
    except CLIError:
        # Not logged in
        login_successful = False
        while not login_successful:
            method_index = prompt_choice_list(MSG_PROMPT_LOGIN,
                                              LOGIN_METHOD_LIST)
            answers['login_index'] = method_index
            answers['login_options'] = str(LOGIN_METHOD_LIST)
            profile = Profile(cli_ctx=cli_ctx)
            interactive = False
            username = None
            password = None
            service_principal = None
            tenant = None
            if method_index == 0:  # device auth
                interactive = True
            elif method_index == 1:  # username and password
                username = prompt('Username: '******'Password: '******'Service principal: ')
                tenant = prompt('Tenant: ')
                password = prompt_pass(msg='Client secret: ')
            elif method_index == 3:  # skip
                return
            try:
                profile.find_subscriptions_on_login(interactive, username,
                                                    password,
                                                    service_principal, tenant)
                login_successful = True
                logger.warning('Login successful!')
            except AdalError as err:
                logger.error('Login error!')
                logger.error(err)
Beispiel #18
0
def _get_credentials(cli_ctx,
                     registry_name,
                     resource_group_name,
                     username,
                     password,
                     only_refresh_token,
                     repository=None,
                     permission='*'):
    """Try to get AAD authorization tokens or admin user credentials.
    :param str registry_name: The name of container registry
    :param str resource_group_name: The name of resource group
    :param str username: The username used to log into the container registry
    :param str password: The password used to log into the container registry
    :param bool only_refresh_token: Whether to ask for only refresh token, or for both refresh and access tokens
    :param str repository: Repository for which the access token is requested
    :param str permission: The requested permission on the repository, '*' or 'pull'
    """
    registry, resource_group_name = get_registry_by_name(cli_ctx, registry_name, resource_group_name)
    login_server = registry.login_server

    # 1. if username was specified, verify that password was also specified
    if username:
        if not password:
            try:
                password = prompt_pass(msg='Password: '******'Please specify both username and password in non-interactive mode.')

        return login_server, username, password

    # 2. if we don't yet have credentials, attempt to get a refresh token
    if not password and registry.sku.name in MANAGED_REGISTRY_SKU:
        try:
            username = '******' if only_refresh_token else None
            password = _get_aad_token(cli_ctx, login_server, only_refresh_token, repository, permission)
            return login_server, username, password
        except CLIError as e:
            logger.warning("Unable to get AAD authorization tokens with message: %s", str(e))

    # 3. if we still don't have credentials, attempt to get the admin credentials (if enabled)
    if not password and registry.admin_user_enabled:
        try:
            cred = cf_acr_registries(cli_ctx).list_credentials(resource_group_name, registry_name)
            username = cred.username
            password = cred.passwords[0].value
            return login_server, username, password
        except CLIError as e:
            logger.warning("Unable to get admin user credentials with message: %s", str(e))

    # 4. if we still don't have credentials, prompt the user
    if not password:
        try:
            username = prompt('Username: '******'Password: '******'Unable to authenticate using AAD or admin login credentials. ' +
                'Please specify both username and password in non-interactive mode.')
def get_upload_oci_driver_input(task_options_json):
    driver_path = task_options_json.get('ociDriverPath', None)
    user_name = task_options_json.get('userName',
                                      None) or prompt('Share Path Username: '******'password', None) or prompt_pass(msg='Share Path Password: ')
    return UploadOCIDriverTaskInput(driver_share=FileShare(
        path=driver_path, user_name=user_name, password=password))
Beispiel #20
0
def handle_feedback():
    try:
        print(MESSAGES['intro'])
        score = _prompt_net_promoter_score()
        response_do_well = None
        response_what_changes = None
        if score == 10:
            response_do_well = prompt(MESSAGES['prompt_do_well'])
        else:
            response_what_changes = prompt(MESSAGES['prompt_what_changes'])
        email_address = prompt(MESSAGES['prompt_email_addr'])
        _send_feedback(score, response_what_changes, response_do_well, email_address)
        print(MESSAGES['thanks'])
    except NoTTYException:
        raise CLIError('This command is interactive and no tty available.')
    except (EOFError, KeyboardInterrupt):
        print()
Beispiel #21
0
def _config_env_public_azure(cli_ctx, _):
    from adal.adal_error import AdalError
    from azure.cli.core.commands.client_factory import get_mgmt_service_client
    from azure.mgmt.resource import ResourceManagementClient
    from azure.cli.core._profile import Profile
    # Determine if user logged in
    try:
        list(get_mgmt_service_client(cli_ctx, ResourceManagementClient).resources.list())
    except CLIError:
        # Not logged in
        login_successful = False
        while not login_successful:
            method_index = prompt_choice_list(MSG_PROMPT_LOGIN, LOGIN_METHOD_LIST)
            answers['login_index'] = method_index
            answers['login_options'] = str(LOGIN_METHOD_LIST)
            profile = Profile(cli_ctx=cli_ctx)
            interactive = False
            username = None
            password = None
            service_principal = None
            tenant = None
            if method_index == 0:  # device auth
                interactive = True
            elif method_index == 1:  # username and password
                username = prompt('Username: '******'Password: '******'Service principal: ')
                tenant = prompt('Tenant: ')
                password = prompt_pass(msg='Client secret: ')
            elif method_index == 3:  # skip
                return
            try:
                profile.find_subscriptions_on_login(
                    interactive,
                    username,
                    password,
                    service_principal,
                    tenant)
                login_successful = True
                logger.warning('Login successful!')
            except AdalError as err:
                logger.error('Login error!')
                logger.error(err)
Beispiel #22
0
def create_sql_connection_info(connection_info_json, prompt_prefix):
    return SqlConnectionInfo(
        user_name=connection_info_json.get('userName', None) or prompt(prompt_prefix + 'Username: '******'password', None) or prompt_pass(msg=prompt_prefix + 'Password: '******'dataSource', None),
        authentication=connection_info_json.get('authentication', None),
        encrypt_connection=connection_info_json.get('encryptConnection', None),
        trust_server_certificate=connection_info_json.get('trustServerCertificate', None),
        additional_settings=connection_info_json.get('additionalSettings', None))
Beispiel #23
0
def _prompt_net_promoter_score():
    while True:
        try:
            score = int(prompt(MESSAGES['prompt_how_likely']))
            if 0 <= score <= 10:
                return score
            raise ValueError
        except ValueError:
            logger.warning('Valid values are %s', list(range(11)))
Beispiel #24
0
def prompt_user_friendly_choice_list(msg,
                                     a_list,
                                     default=1,
                                     help_string=None,
                                     error_msg=None):
    """Prompt user to select from a list of possible choices.
    :param msg: A message displayed to the user before the choice list
    :type msg: str
    :param a_list: The list of choices (list of strings or list of dicts with 'name' & 'desc')
    "type a_list: list
    :param default: The default option that should be chosen if user doesn't enter a choice
    :type default: int
    :param help_string: Help message to be displayed on the input terminal
    :type help_string: str
    :param error_msg: Error message to display if the terminal is non interactive
    :type error_msg: str
    :returns: The list index of the item chosen.
    """
    verify_is_a_tty_or_raise_error(error_msg=error_msg)
    options = '\n'.join([
        ' [{}] {}{}'.format(
            i + 1, x['name'] if isinstance(x, dict) and 'name' in x else x,
            ' - ' + x['desc'] if isinstance(x, dict) and 'desc' in x else '')
        for i, x in enumerate(a_list)
    ])
    allowed_vals = list(range(1, len(a_list) + 1))
    linesToDelete = len(a_list) + 1
    while True:
        val = prompt(
            '{}\n{}\nPlease enter a choice [Default choice({})]: '.format(
                msg, options, default))
        if val == '?' and help_string is not None:
            for x in range(0, linesToDelete):
                delete_last_line()
            print('Please enter a choice [Default choice({})]: {}'.format(
                default, '?'))
            print(help_string)
            continue
        if not val:
            val = '{}'.format(default)
        try:
            ans = int(val)
            if ans in allowed_vals:
                for x in range(0, linesToDelete):
                    delete_last_line()
                print('Please enter a choice [Default choice({})]: {}'.format(
                    default, a_list[ans - 1]))
                print('')
                # array index is 0-based, user input is 1-based
                return ans - 1
            raise ValueError
        except ValueError:
            for x in range(0, linesToDelete):
                delete_last_line()
            print('Please enter a choice [Default choice({})]: {}'.format(
                default, val))
            logger.warning('Valid values are %s', allowed_vals)
Beispiel #25
0
def process_query(cli_term):
    print(random.choice(WAIT_MESSAGE))
    response = call_aladdin_service(cli_term)

    if response.status_code != 200:
        err_msg = '[?] Unexpected Error: [HTTP {0}]: Content: {1}'.format(
            response.status_code, response.content)
        logger.error(err_msg)
    else:
        if (platform.system() == 'Windows' and should_enable_styling()):
            colorama.init(convert=True)

        answer_list = json.loads(response.content)
        if (not answer_list or answer_list[0]['source'] == 'bing'):
            print("\nSorry I am not able to help with [" + cli_term + "]."
                  "\nTry typing the beginning of a command e.g. " +
                  style_message('az vm') + ".")
        else:
            print("\nHere are the most common ways to use [" + cli_term +
                  "]: \n")
            num_results_to_show = min(3, len(answer_list))
            for i in range(num_results_to_show):
                current_title = answer_list[i]['title'].strip()
                current_snippet = answer_list[i]['snippet'].strip()
                if current_title.startswith("az "):
                    current_title, current_snippet = current_snippet, current_title
                    current_title = current_title.split('\r\n')[0]
                elif '```azurecli\r\n' in current_snippet:
                    start_index = current_snippet.index(
                        '```azurecli\r\n') + len('```azurecli\r\n')
                    current_snippet = current_snippet[start_index:]
                current_snippet = current_snippet.replace('```', '').replace(
                    current_title, '').strip()
                current_snippet = re.sub(r'\[.*\]', '',
                                         current_snippet).strip()
                print(style_message(current_title))
                print(current_snippet)

                print("")
            feedback = prompt(
                "[Enter to close. Press + or - to give feedback]:")
            if feedback in ['+', '-']:
                print('Wow, you are a true hero!')
                print("""\
        O_
       """ + style_message("""<T>""") + """`-.
        """ + style_message("""|""") + """`-‘
        """ + style_message("""I""") + """
                        """)
                print(
                    'My human overlords review each of these reports; I\'m told these reports makes me smarter.'
                )
                print(
                    'Send us more feedback by email: [email protected]')
            properties = {}
            set_custom_properties(properties, 'Feedback', feedback)
            telemetry_core.add_extension_event(EXTENSION_NAME, properties)
Beispiel #26
0
def prompt_not_empty(msg, help_string=None):
    """
    Wrapper on knacks prompt function which does not return until non none value is recieved from user input.
    """
    if not help_string:
        help_string = 'This field cannot be left blank.'
    user_input = None
    while not user_input:
        user_input = prompt(msg=msg, help_string=help_string)
    return user_input
Beispiel #27
0
 def test_prompt_msg_question_with_help_string(self, _):
     expected_result = 'My response'
     with mock.patch('knack.prompting._input',
                     side_effect=['?', expected_result]):
         with mock.patch('sys.stdout',
                         new_callable=StringIO) as mock_stdout:
             actual_result = prompt('Please enter some text: ',
                                    help_string='Anything you want!')
             self.assertEqual(expected_result, actual_result)
             self.assertIn('Anything you want!', mock_stdout.getvalue())
Beispiel #28
0
def _prompt_net_promoter_score():
    score = -1
    help_string = 'Please rate between 0 and 10'
    while score < 0 or score > 10:
        try:
            score = int(prompt(MSG_RATE, help_string=help_string))
        except ValueError:
            logger.warning(help_string)

    return score
Beispiel #29
0
def _create_image_registry_credentials(registry_login_server,
                                       registry_username, registry_password,
                                       image):
    """Create image registry credentials. """
    image_registry_credentials = None
    if registry_login_server:
        if not registry_username:
            raise CLIError(
                'Please specify --registry-username in order to use custom image registry.'
            )
        if not registry_password:
            try:
                registry_password = prompt_pass(
                    msg='Image registry password: '******'Please specify --registry-password in order to use custom image registry.'
                )
        image_registry_credentials = [
            ImageRegistryCredential(server=registry_login_server,
                                    username=registry_username,
                                    password=registry_password)
        ]
    elif SERVER_DELIMITER in image.split("/")[0]:
        if not registry_username:
            try:
                registry_username = prompt(msg='Image registry username: '******'Please specify --registry-username in order to use Azure Container Registry.'
                )

        if not registry_password:
            try:
                registry_password = prompt_pass(
                    msg='Image registry password: '******'Please specify --registry-password in order to use Azure Container Registry.'
                )

        acr_server = image.split("/")[0] if image.split("/") else None
        if acr_server:
            image_registry_credentials = [
                ImageRegistryCredential(server=acr_server,
                                        username=registry_username,
                                        password=registry_password)
            ]
        else:
            raise CLIError(
                'Failed to parse ACR server from image name; please explicitly specify --registry-server.'
            )

    return image_registry_credentials
Beispiel #30
0
    def process_github_personal_access_token(self):
        if not self.github_pat:
            self.logger.warning("If you need to create a Github Personal Access Token, "
                                "please follow the steps found at the following link:")
            self.logger.warning("https://help.github.com/en/articles/"
                                "creating-a-personal-access-token-for-the-command-line{ls}".format(ls=os.linesep))
            self.logger.warning("The required Personal Access Token permissions can be found here:")
            self.logger.warning("https://aka.ms/azure-devops-source-repos")

        while not self.github_pat or not AzureDevopsBuildProvider.check_github_pat(self.github_pat):
            self.github_pat = prompt(msg="Github Personal Access Token: ").strip()
        self.logger.warning("Successfully validated Github personal access token.")
Beispiel #31
0
    def process_local_repository(self):
        has_local_git_repository = AzureDevopsBuildProvider.check_git_local_repository()
        if has_local_git_repository:
            self.logger.warning("Detected a local Git repository already exists.")

        # Collect repository name on Azure Devops
        if not self.repository_name:
            self.repository_name = prompt("Push to which Azure Devops repository (default: {repo}): ".format(
                repo=self.project_name
            ))
            if not self.repository_name:  # Select default value
                self.repository_name = self.project_name

        expected_remote_name = self.adbp.get_local_git_remote_name(
            self.organization_name,
            self.project_name,
            self.repository_name
        )
        expected_remote_url = self.adbp.get_azure_devops_repo_url(
            self.organization_name,
            self.project_name,
            self.repository_name
        )

        # If local repository already has a remote
        # Let the user to know s/he can push to the remote directly for context update
        # Or let s/he remove the git remote manually
        has_local_git_remote = self.adbp.check_git_remote(
            self.organization_name,
            self.project_name,
            self.repository_name
        )
        if has_local_git_remote:
            raise CLIError("There's a git remote bound to {url}.{ls}"
                           "To update the repository and trigger an Azure Devops build, please use "
                           "'git push {remote} master'".format(
                               url=expected_remote_url,
                               remote=expected_remote_name,
                               ls=os.linesep)
                           )

        # Setup a local git repository and create a new commit on top of this context
        try:
            self.adbp.setup_local_git_repository(self.organization_name, self.project_name, self.repository_name)
        except GitOperationException as goe:
            raise CLIError("Failed to setup local git repository when running '{message}'{ls}"
                           "Please ensure you have setup git user.email and user.name".format(
                               message=goe.message, ls=os.linesep
                           ))

        self.repository_remote_name = expected_remote_name
        self.logger.warning("Added git remote {remote}".format(remote=expected_remote_name))
Beispiel #32
0
def _create_image_registry_credentials(cmd, resource_group_name, registry_login_server, registry_username, registry_password, image, identity):
    from msrestazure.tools import is_valid_resource_id
    image_registry_credentials = None
    if registry_login_server:
        if not registry_username:
            raise RequiredArgumentMissingError('Please specify --registry-username in order to use custom image registry.')
        if not registry_password:
            try:
                registry_password = prompt_pass(msg='Image registry password: '******'Please specify --registry-password in order to use custom image registry.')
        image_registry_credentials = [ImageRegistryCredential(server=registry_login_server,
                                                              username=registry_username,
                                                              password=registry_password)]
    elif ACR_SERVER_DELIMITER in image.split("/")[0]:
        acr_server = image.split("/")[0] if image.split("/") else None
        if identity:
            if not is_valid_resource_id(identity):
                msi_client = cf_msi(cmd.cli_ctx)
                identity = msi_client.user_assigned_identities.get(resource_group_name=resource_group_name,
                                                                   resource_name=identity).id
            if acr_server:
                image_registry_credentials = [ImageRegistryCredential(server=acr_server,
                                                                      username=registry_username,
                                                                      password=registry_password,
                                                                      identity=identity)]
        else:
            if not registry_username:
                try:
                    registry_username = prompt(msg='Image registry username: '******'Please specify --registry-username in order to use Azure Container Registry.')

            if not registry_password:
                try:
                    registry_password = prompt_pass(msg='Image registry password: '******'Please specify --registry-password in order to use Azure Container Registry.')
            if acr_server:
                image_registry_credentials = [ImageRegistryCredential(server=acr_server,
                                                                      username=registry_username,
                                                                      password=registry_password)]
    elif registry_username and registry_password and SERVER_DELIMITER in image.split("/")[0]:
        login_server = image.split("/")[0] if image.split("/") else None
        if login_server:
            image_registry_credentials = [ImageRegistryCredential(server=login_server,
                                                                  username=registry_username,
                                                                  password=registry_password)]
        else:
            raise RequiredArgumentMissingError('Failed to parse login server from image name; please explicitly specify --registry-server.')

    return image_registry_credentials
Beispiel #33
0
 def _create_token(self, note=None):
     logger.warning('We need to create a Personal Access Token to communicate with GitHub. '
                    'A new PAT with scopes (admin:repo_hook, repo, user) will be created.')
     logger.warning('You can set the PAT in the environment variable (%s) to avoid getting prompted.',
                    AZ_DEVOPS_GITHUB_PAT_ENVKEY)
     self.username = prompt(msg='Enter your GitHub username (leave blank for using already generated PAT): ')
     print('')
     if not self.username:
         while not self.token:
             self.token = prompt_pass(msg='Enter your GitHub PAT: ', help_string='Generate a Personal Access Token '
                                      'with approproate permissions from GitHub Developer settings and paste here.')
         print('')
         return
     self.password = prompt_pass(msg='Enter your GitHub password: '******'')
     if not note:
         note = "AzureDevopsCLIExtensionToken_" + datetime_now_as_string()
     encoded_pass = base64.b64encode(self.username.encode('utf-8') + b':' + self.password.encode('utf-8'))
     basic_auth = 'basic ' + encoded_pass.decode("utf-8")
     request_body = {
         'scopes': [
             'admin:repo_hook',
             'repo',
             'user'
         ],
         'note': note
     }
     headers = {'Content-Type': 'application/json' + '; charset=utf-8',
                'Accept': 'application/json',
                'Authorization': basic_auth}
     response = self.post_authorization_request(headers=headers, body=request_body)
     if (response.status_code == 401 and response.headers.get('X-GitHub-OTP') and
             response.headers.get('X-GitHub-OTP').startswith('required')):
         two_factor_code = None
         while not two_factor_code:
             two_factor_code = prompt_pass(msg='Enter your two factor authentication code: ')
         print('')
         headers = {'Content-Type': 'application/json' + '; charset=utf-8',
                    'Accept': 'application/json',
                    'Authorization': basic_auth,
                    'X-GitHub-OTP': two_factor_code}
         response = self.post_authorization_request(headers=headers, body=request_body)
     import json
     response_json = json.loads(response.content)
     if response.status_code == 200 or response.status_code == 201:
         logger.warning('Created new personal access token with scopes (admin:repo_hook, repo, user). Name: %s '
                        'You can revoke this from your GitHub settings if the pipeline is no longer required.',
                        note)
         self.token = response_json['token']
     else:
         raise CLIError('Could not create a Personal Access Token for GitHub. Check your credentials and try again.')
Beispiel #34
0
def _handle_global_configuration(config, cloud_forbid_telemetry):
    # print location of global configuration
    print(MSG_GLOBAL_SETTINGS_LOCATION.format(config.config_path))
    # set up the config parsers
    file_config = configparser.ConfigParser()
    config_exists = file_config.read([config.config_path])
    should_modify_global_config = False
    if config_exists:
        # print current config and prompt to allow global config modification
        _print_cur_configuration(file_config)
        should_modify_global_config = prompt_y_n(MSG_PROMPT_MANAGE_GLOBAL,
                                                 default='n')
        answers['modify_global_prompt'] = should_modify_global_config
    if not config_exists or should_modify_global_config:
        # no config exists yet so configure global config or user wants to modify global config
        with ConfiguredDefaultSetter(config, False):
            output_index = prompt_choice_list(MSG_PROMPT_GLOBAL_OUTPUT,
                                              OUTPUT_LIST,
                                              default=get_default_from_config(
                                                  config, 'core', 'output',
                                                  OUTPUT_LIST))
            answers['output_type_prompt'] = output_index
            answers['output_type_options'] = str(OUTPUT_LIST)
            enable_file_logging = prompt_y_n(MSG_PROMPT_FILE_LOGGING,
                                             default='n')
            if cloud_forbid_telemetry:
                allow_telemetry = False
            else:
                allow_telemetry = prompt_y_n(MSG_PROMPT_TELEMETRY, default='y')
            answers['telemetry_prompt'] = allow_telemetry
            cache_ttl = None
            while not cache_ttl:
                try:
                    cache_ttl = prompt(
                        MSG_PROMPT_CACHE_TTL) or DEFAULT_CACHE_TTL
                    # ensure valid int by casting
                    cache_value = int(cache_ttl)
                    if cache_value < 1:
                        raise ValueError
                except ValueError:
                    logger.error('TTL must be a positive integer')
                    cache_ttl = None
            # save the global config
            config.set_value('core', 'output',
                             OUTPUT_LIST[output_index]['name'])
            config.set_value('core', 'collect_telemetry',
                             'yes' if allow_telemetry else 'no')
            config.set_value('core', 'cache_ttl', cache_ttl)
            config.set_value('logging', 'enable_log_file',
                             'yes' if enable_file_logging else 'no')
def process_query(cli_term):
    print(random.choice(WAIT_MESSAGE))
    response = call_aladdin_service(cli_term)

    if response.status_code != 200:
        logger.error('[?] Unexpected Error: [HTTP {0}]: Content: {1}'.format(response.status_code, response.content))
    else:
        if (platform.system() == 'Windows' and should_enable_styling()):
            colorama.init(convert=True)

        answer_list = json.loads(response.content)
        if (not answer_list or answer_list[0]['source'] == 'bing'):
            print("\nSorry I am not able to help with [" + cli_term + "]."
                  "\nTry typing the beginning of a command e.g. " + style_message('az vm') + ".")
        else:
            print("\nHere are the most common ways to use [" + cli_term + "]: \n")
            num_results_to_show = min(3, len(answer_list))
            for i in range(num_results_to_show):
                current_title = answer_list[i]['title'].strip()
                current_snippet = answer_list[i]['snippet'].strip()
                if current_title.startswith("az "):
                    current_title, current_snippet = current_snippet, current_title
                    current_title = current_title.split('\r\n')[0]
                elif '```azurecli\r\n' in current_snippet:
                    start_index = current_snippet.index('```azurecli\r\n') + len('```azurecli\r\n')
                    current_snippet = current_snippet[start_index:]
                current_snippet = current_snippet.replace('```', '').replace(current_title, '').strip()
                current_snippet = re.sub(r'\[.*\]', '', current_snippet).strip()
                print(style_message(current_title))
                print(current_snippet)

                print("")
            feedback = prompt("[Enter to close. Press + or - to give feedback]:")
            if feedback in ['+', '-']:
                print('Wow, you are a true hero!')
                print("""\
        O_
       """ + style_message("""<T>""") + """`-.
        """ + style_message("""|""") + """`-‘
        """ + style_message("""I""") + """
                        """)
                print('My human overlords review each of these reports; I\'m told these reports makes me smarter.')
                print('Send us more feedback by email: [email protected]')
            properties = {}
            set_custom_properties(properties, 'Feedback', feedback)
            telemetry_core.add_extension_event(EXTENSION_NAME, properties)
Beispiel #36
0
def _create_image_registry_credentials(registry_login_server, registry_username, registry_password, image):
    """Create image registry credentials. """
    image_registry_credentials = None
    if registry_login_server:
        if not registry_username:
            raise CLIError('Please specify --registry-username in order to use custom image registry.')
        if not registry_password:
            try:
                registry_password = prompt_pass(msg='Image registry password: '******'Please specify --registry-password in order to use custom image registry.')
        image_registry_credentials = [ImageRegistryCredential(server=registry_login_server,
                                                              username=registry_username,
                                                              password=registry_password)]
    elif ACR_SERVER_DELIMITER in image.split("/")[0]:
        if not registry_username:
            try:
                registry_username = prompt(msg='Image registry username: '******'Please specify --registry-username in order to use Azure Container Registry.')

        if not registry_password:
            try:
                registry_password = prompt_pass(msg='Image registry password: '******'Please specify --registry-password in order to use Azure Container Registry.')

        acr_server = image.split("/")[0] if image.split("/") else None
        if acr_server:
            image_registry_credentials = [ImageRegistryCredential(server=acr_server,
                                                                  username=registry_username,
                                                                  password=registry_password)]
    elif registry_username and registry_password and SERVER_DELIMITER in image.split("/")[0]:
        login_server = image.split("/")[0] if image.split("/") else None
        if login_server:
            image_registry_credentials = [ImageRegistryCredential(server=login_server,
                                                                  username=registry_username,
                                                                  password=registry_password)]
        else:
            raise CLIError('Failed to parse login server from image name; please explicitly specify --registry-server.')

    return image_registry_credentials
Beispiel #37
0
def acr_import(cmd,
               client,
               registry_name,
               source,
               source_registry=None,
               source_registry_username=None,
               source_registry_password=None,
               target_tags=None,
               resource_group_name=None,
               repository=None,
               force=False):

    _, resource_group_name = validate_managed_registry(
        cmd.cli_ctx, registry_name, resource_group_name, IMPORT_NOT_SUPPORTED)

    if not source:
        raise CLIError(INVALID_SOURCE_IMAGE)
    source_image = source

    slash = source.find('/')

    if slash < 0:
        if not source_registry:
            from knack.prompting import prompt, NoTTYException
            try:
                source_registry = prompt(SOURCE_REGISTRY_MISSING)
            except NoTTYException:
                raise CLIError(NO_TTY_ERROR)
        if not is_valid_resource_id(source_registry):
            registry = get_registry_from_name_or_login_server(cmd.cli_ctx, source_registry, source_registry)
            if registry:
                source_registry = registry.id
        source = ImportSource(resource_id=source_registry, source_image=source_image)
    else:
        source_registry_login_server = source_image[:slash]
        source_image = source_image[slash + 1:]
        if not source_image or not source_registry_login_server:
            raise CLIError(INVALID_SOURCE_IMAGE)
        registry = get_registry_from_name_or_login_server(cmd.cli_ctx, source_registry_login_server)
        if registry:
            if source_registry and \
               source_registry.lower() != registry.id.lower() and \
               source_registry.lower() != registry.name.lower() and \
               source_registry.lower() != registry.login_server.lower():
                raise CLIError(REGISTRY_MISMATCH)
            source = ImportSource(resource_id=registry.id,
                                  source_image=source_image)
        else:
            if source_registry_password:
                if source_registry_username:
                    source = ImportSource(registry_uri=source_registry_login_server,
                                          source_image=source_image,
                                          credentials=ImportSourceCredentials(password=source_registry_password,
                                                                              username=source_registry_username))
                else:
                    source = ImportSource(registry_uri=source_registry_login_server,
                                          source_image=source_image,
                                          credentials=ImportSourceCredentials(password=source_registry_password))
            else:
                source = ImportSource(registry_uri=source_registry_login_server, source_image=source_image)

    if not target_tags and not repository:
        index = source_image.find("@")
        if index > 0:
            target_tags = [source_image[:index]]
        else:
            target_tags = [source_image]

    import_parameters = ImportImageParameters(source=source,
                                              target_tags=target_tags,
                                              untagged_target_repositories=repository,
                                              mode=ImportMode.force.value if force else ImportMode.no_force.value)
    return client.import_image(
        resource_group_name=resource_group_name,
        registry_name=registry_name,
        parameters=import_parameters)
def _prompt_for_parameters(missing_parameters, fail_on_no_tty=True):  # pylint: disable=too-many-statements

    prompt_list = missing_parameters.keys() if isinstance(missing_parameters, OrderedDict) \
        else sorted(missing_parameters)
    result = OrderedDict()
    no_tty = False
    for param_name in prompt_list:
        param = missing_parameters[param_name]
        param_type = param.get('type', 'string')
        description = 'Missing description'
        metadata = param.get('metadata', None)
        if metadata is not None:
            description = metadata.get('description', description)
        allowed_values = param.get('allowedValues', None)

        prompt_str = "Please provide {} value for '{}' (? for help): ".format(param_type, param_name)
        while True:
            if allowed_values is not None:
                try:
                    ix = prompt_choice_list(prompt_str, allowed_values, help_string=description)
                    result[param_name] = allowed_values[ix]
                except NoTTYException:
                    result[param_name] = None
                    no_tty = True
                break
            elif param_type == 'securestring':
                try:
                    value = prompt_pass(prompt_str, help_string=description)
                except NoTTYException:
                    value = None
                    no_tty = True
                result[param_name] = value
                break
            elif param_type == 'int':
                try:
                    int_value = prompt_int(prompt_str, help_string=description)
                    result[param_name] = int_value
                except NoTTYException:
                    result[param_name] = 0
                    no_tty = True
                break
            elif param_type == 'bool':
                try:
                    value = prompt_t_f(prompt_str, help_string=description)
                    result[param_name] = value
                except NoTTYException:
                    result[param_name] = False
                    no_tty = True
                break
            elif param_type in ['object', 'array']:
                try:
                    value = prompt(prompt_str, help_string=description)
                except NoTTYException:
                    value = ''
                    no_tty = True

                if value == '':
                    value = {} if param_type == 'object' else []
                else:
                    try:
                        value = shell_safe_json_parse(value)
                    except Exception as ex:  # pylint: disable=broad-except
                        logger.error(ex)
                        continue
                result[param_name] = value
                break
            else:
                try:
                    result[param_name] = prompt(prompt_str, help_string=description)
                except NoTTYException:
                    result[param_name] = None
                    no_tty = True
                break
    if no_tty and fail_on_no_tty:
        raise NoTTYException
    return result
Beispiel #39
0
def _get_credentials(cli_ctx,
                     registry_name,
                     resource_group_name,
                     username,
                     password,
                     only_refresh_token,
                     repository=None,
                     artifact_repository=None,
                     permission=None):
    """Try to get AAD authorization tokens or admin user credentials.
    :param str registry_name: The name of container registry
    :param str resource_group_name: The name of resource group
    :param str username: The username used to log into the container registry
    :param str password: The password used to log into the container registry
    :param bool only_refresh_token: Whether to ask for only refresh token, or for both refresh and access tokens
    :param str repository: Repository for which the access token is requested
    :param str artifact_repository: Artifact repository for which the access token is requested
    :param str permission: The requested permission on the repository, '*' or 'pull'
    """
    # 1. if username was specified, verify that password was also specified
    if username:
        # Try to use the pre-defined login server suffix to construct login server from registry name.
        # This is to avoid a management server request if username/password are already provided.
        # In all other cases, including the suffix not defined, login server will be obtained from server.
        login_server_suffix = get_login_server_suffix(cli_ctx)
        if login_server_suffix:
            login_server = '{}{}'.format(registry_name, login_server_suffix)
        else:
            registry, _ = get_registry_by_name(cli_ctx, registry_name, resource_group_name)
            login_server = registry.login_server

        if not password:
            try:
                password = prompt_pass(msg='Password: '******'Please specify both username and password in non-interactive mode.')

        return login_server, username, password

    registry, resource_group_name = get_registry_by_name(cli_ctx, registry_name, resource_group_name)
    login_server = registry.login_server

    # 2. if we don't yet have credentials, attempt to get a refresh token
    if not password and registry.sku.name in MANAGED_REGISTRY_SKU:
        try:
            password = _get_aad_token(
                cli_ctx, login_server, only_refresh_token, repository, artifact_repository, permission)
            return login_server, EMPTY_GUID, password
        except CLIError as e:
            logger.warning("Unable to get AAD authorization tokens with message: %s", str(e))

    # 3. if we still don't have credentials, attempt to get the admin credentials (if enabled)
    if not password and registry.admin_user_enabled:
        try:
            cred = cf_acr_registries(cli_ctx).list_credentials(resource_group_name, registry_name)
            username = cred.username
            password = cred.passwords[0].value
            return login_server, username, password
        except CLIError as e:
            logger.warning("Unable to get admin user credentials with message: %s", str(e))

    # 4. if we still don't have credentials, prompt the user
    if not password:
        try:
            username = prompt('Username: '******'Password: '******'Unable to authenticate using AAD or admin login credentials. ' +
                'Please specify both username and password in non-interactive mode.')

    return login_server, None, None
Beispiel #40
0
def _get_credentials(cmd,  # pylint: disable=too-many-statements
                     registry_name,
                     tenant_suffix,
                     username,
                     password,
                     only_refresh_token,
                     repository=None,
                     artifact_repository=None,
                     permission=None):
    """Try to get AAD authorization tokens or admin user credentials.
    :param str registry_name: The name of container registry
    :param str tenant_suffix: The registry login server tenant suffix
    :param str username: The username used to log into the container registry
    :param str password: The password used to log into the container registry
    :param bool only_refresh_token: Whether to ask for only refresh token, or for both refresh and access tokens
    :param str repository: Repository for which the access token is requested
    :param str artifact_repository: Artifact repository for which the access token is requested
    :param str permission: The requested permission on the repository, '*' or 'pull'
    """
    # Raise an error if password is specified but username isn't
    if not username and password:
        raise CLIError('Please also specify username if password is specified.')

    cli_ctx = cmd.cli_ctx
    resource_not_found, registry = None, None
    try:
        registry, resource_group_name = get_registry_by_name(cli_ctx, registry_name)
        login_server = registry.login_server
        if tenant_suffix:
            logger.warning(
                "Obtained registry login server '%s' from service. The specified suffix '%s' is ignored.",
                login_server, tenant_suffix)
    except (ResourceNotFound, CLIError) as e:
        resource_not_found = str(e)
        logger.debug("Could not get registry from service. Exception: %s", resource_not_found)
        if not isinstance(e, ResourceNotFound) and _AZ_LOGIN_MESSAGE not in resource_not_found:
            raise
        # Try to use the pre-defined login server suffix to construct login server from registry name.
        login_server_suffix = get_login_server_suffix(cli_ctx)
        if not login_server_suffix:
            raise
        login_server = '{}{}{}'.format(
            registry_name, '-{}'.format(tenant_suffix) if tenant_suffix else '', login_server_suffix).lower()

    # Validate the login server is reachable
    url = 'https://' + login_server + '/v2/'
    try:
        challenge = requests.get(url, verify=(not should_disable_connection_verify()))
        if challenge.status_code in [403]:
            raise CLIError("Looks like you don't have access to registry '{}'. "
                           "Are firewalls and virtual networks enabled?".format(login_server))
    except RequestException as e:
        logger.debug("Could not connect to registry login server. Exception: %s", str(e))
        if resource_not_found:
            logger.warning("%s\nUsing '%s' as the default registry login server.", resource_not_found, login_server)
        raise CLIError("Could not connect to the registry login server '{}'. ".format(login_server) +
                       "Please verify that the registry exists and " +
                       "the URL '{}' is reachable from your environment.".format(url))

    # 1. if username was specified, verify that password was also specified
    if username:
        if not password:
            try:
                password = prompt_pass(msg='Password: '******'Please specify both username and password in non-interactive mode.')

        return login_server, username, password

    # 2. if we don't yet have credentials, attempt to get a refresh token
    if not registry or registry.sku.name in get_managed_sku(cmd):
        try:
            return login_server, EMPTY_GUID, _get_aad_token(
                cli_ctx, login_server, only_refresh_token, repository, artifact_repository, permission)
        except CLIError as e:
            logger.warning("%s: %s", AAD_TOKEN_BASE_ERROR_MESSAGE, str(e))

    # 3. if we still don't have credentials, attempt to get the admin credentials (if enabled)
    if registry:
        if registry.admin_user_enabled:
            try:
                cred = cf_acr_registries(cli_ctx).list_credentials(resource_group_name, registry_name)
                return login_server, cred.username, cred.passwords[0].value
            except CLIError as e:
                logger.warning("%s: %s", ADMIN_USER_BASE_ERROR_MESSAGE, str(e))
        else:
            logger.warning("%s: %s", ADMIN_USER_BASE_ERROR_MESSAGE, "Admin user is disabled.")
    else:
        logger.warning("%s: %s", ADMIN_USER_BASE_ERROR_MESSAGE, resource_not_found)

    # 4. if we still don't have credentials, prompt the user
    try:
        username = prompt('Username: '******'Password: '******'Unable to authenticate using AAD or admin login credentials. ' +
            'Please specify both username and password in non-interactive mode.')

    return login_server, None, None