def is_input_int_and_in_range_for_mfa_failure(int_obj: IntObject, message: str) -> bool: """ While loop をテストするために、IntObject クラスを介して Validation と IntObject インスタンスの更新を行う """ menu_num = 4 # メニューを表示 print(MFA_FAILURE_MESSAGE) # インプットを促す user_input = get_input(message) try: # 値を引き継ぐために、IntObject インスタンスを使用 int_obj.prompt_num = user_input # int に変換してエラーとなるかどうかをチェック int(int_obj.prompt_num) # int 変換でエラーにならなかった場合、今度は下記で、値が範囲内かどうかcheck if int(int_obj.prompt_num) <= menu_num: return True else: print("1 から {0} の値を入力してください".format(menu_num)) return False except ValueError: # 誤りを指摘し、再入力を促すプロンプトを表示 print(PROMPT_USER_INPUT_BEFORE + str(user_input) + PROMPT_USER_INPUT_AFTER) print(PROMPT_ENTER_AN_INT + "\n") return False
def ask_for_selection(prompt_msg: str, min_menu_num: int, max_menu_num: int) -> int: """番号入力 input() が validate するまでループさせる""" int_obj = IntObject() while not is_input_int_and_in_range(int_obj, prompt_msg, min_menu_num, max_menu_num): pass return int_obj.prompt_num
def get_selected_profile(): profile_list = get_profile_obj_list() perfect_profile_list = get_perfect_profile_list(profile_list, get_credentials_obj_list()) validated_input = validate.ask_profile_num_input_till_its_validated( IntObject(), perfect_profile_list) return get_specified_profile(perfect_profile_list, validated_input)
def reset_aws_account_id(perfect_profile: ProfileTuple): # aws account id の入力を要求し、 prompts.prompt_for_update_aws_account_id(perfect_profile) aws_account_id = helper.ask_int_input_till_its_validated( IntObject(), ASKING_AWS_ACCOUNT_ID_INPUT_MESSAGE) # 該当ファイルに書き込む writing_aws_account_to_the_file(perfect_profile, aws_account_id) # 再帰的に本関数を呼び出して、書き込み済みの aws account id を取得する get_aws_account_id(perfect_profile)
def test_user_input_is_int(monkeypatch): # GIVEN: ユーザーインプットが integer ではない場合、を Mock user_input_not_int = "12345" # GIVEN: Mock user input string monkeypatch.setattr(BUILTIN_INPUTS, lambda _: user_input_not_int) # WHEN: Validate the input is_int = helper.is_input_int_loop(IntObject(), data_manager.ASKING_AWS_ACCOUNT_ID_INPUT_MESSAGE) # THEN: It's not an int assert is_int
def test_input_wrong_mfa_code_and_re_enter_another_mfa_code( get_sts_client, get_valid_mfa_arn, monkeypatch): # GIVEN: select profile modification selected_measure = 1 # GIVEN: Mock user input string number monkeypatch.setattr(BUILTIN_INPUTS, lambda _: selected_measure) validated_selection = validate.ask_for_mfa_failure_inputs(IntObject()) assert type(validated_selection) is int
def test_return_user_input_num(monkeypatch, perfect_profile_list): # GIVEN: Mock user input string number monkeypatch.setattr(BUILTIN_INPUTS, lambda _: "3") # WHEN: validate with this function user_input = validate.ask_profile_num_input_till_its_validated( IntObject(), perfect_profile_list) # THEN: the returned value is int assert type(user_input) is int
def test_classes_magic_methods(): temp_name = "Suzuki" temp_region = "eu-central-1" temp_profile = ProfileTuple(temp_name, temp_region).__repr__() assert temp_name in temp_profile assert temp_region in temp_profile temp_cred = CredentialTuple(temp_name).__repr__() assert temp_name in temp_cred temp_int = IntObject(9).__repr__() assert "9" in temp_int
def test_input_is_not_in_list_range(): # GIVEN: a static length of list _list = [1, 2, 3] # GIVEN: a num profile_num_input = IntObject(prompt_num=0) # WHEN: check if a num is in range of the list # THEN: True is_in_range = validate.is_input_in_profile_list_range( profile_num_input, _list) assert not is_in_range
def test_user_input_num_ok_validation(perfect_profile_list, monkeypatch): # GIVEN: User inputs random integer within perfect_profile_list range user_input_int = randint(1, len(perfect_profile_list)) # GIVEN: Mock user input integer monkeypatch.setattr('builtins.input', lambda _: user_input_int) # WHEN: Validate the number is_that_int = validate.is_input_int_and_in_range_for_profile_selection( IntObject(), perfect_profile_list, validate.ASKING_USER_INPUT_MESSAGE) # THEN: the returned value is True assert is_that_int
def test_user_input_num_not_ok_validation(perfect_profile_list, monkeypatch): # GIVEN: User inputs random strings letters = string.ascii_letters user_input_str = ''.join(choice(letters)) # GIVEN: Mock user input string monkeypatch.setattr('builtins.input', lambda _: user_input_str) # WHEN: Validate the input is_int = validate.is_input_int_and_in_range_for_profile_selection( IntObject(), perfect_profile_list, validate.ASKING_USER_INPUT_MESSAGE) # THEN: It's not an int assert not is_int
def test_input_for_mfa_with_string_error(capsys, monkeypatch): """input が範囲外の数値だった場合に、プロンプトが表示され、かつ False が返ってくる""" # GIVEN: some message msg = "nothing" # GIVEN: out of range input int_input = "aiueo" monkeypatch.setattr(BUILTIN_INPUTS, lambda _: int_input) # WHEN: check if the input is in range result = validate.is_input_int_and_in_range_for_mfa_failure( IntObject(), msg) out, err = capsys.readouterr() assert not result assert PROMPT_USER_INPUT_BEFORE in out.rstrip()
def test_input_range_failure(capsys, monkeypatch): """input が範囲外の数値だった場合に、プロンプトが表示され、かつ False が返ってくる""" # GIVEN: some message msg = "nothing" menu_num = 4 # GIVEN: out of range input int_input = 33333 monkeypatch.setattr(BUILTIN_INPUTS, lambda _: int_input) # WHEN: check if the input is in range result = validate.is_input_int_and_in_range_for_mfa_failure( IntObject(), msg) out, err = capsys.readouterr() assert not result assert "1 から {0} の値を入力してください".format(menu_num) in out.rstrip()
def test_input_in_range_for_role_for_the_profile_list( capsys, monkeypatch, role_for_the_profile_list): """input が範囲内の数値だった場合に、 True が返ってくる""" # GIVEN: select out of range num int_input = len(role_for_the_profile_list) monkeypatch.setattr(BUILTIN_INPUTS, lambda _: int_input) # GIVEN: property to validate select role prompt_str = validate.INPUT_No min_menu_num = 0 max_menu_num = len(role_for_the_profile_list) # WHEN: check if the input is in range is_validated = validate.is_input_int_and_in_range(IntObject(), prompt_str, min_menu_num, max_menu_num) assert is_validated
def is_input_int_and_in_range(int_obj: IntObject, prompt_str: str, min_menu_num: int, max_menu_num: int) -> bool: user_input = get_input(prompt_str) try: # 値を引き継ぐために、IntObject インスタンスを使用 int_obj.prompt_num = user_input # int に変換してエラーとなるかどうかをチェック int(int_obj.prompt_num) # int 変換でエラーにならなかった場合、今度は下記で、値が範囲内かどうかcheck if (int(int_obj.prompt_num) <= max_menu_num) and (int(int_obj.prompt_num) >= min_menu_num): return True else: print("{} から {} の値を入力してください".format(min_menu_num, max_menu_num)) return False except ValueError: # 誤りを指摘し、再入力を促すプロンプトを表示 print(PROMPT_USER_INPUT_BEFORE + str(user_input) + PROMPT_USER_INPUT_AFTER) print(PROMPT_ENTER_AN_INT + "\n") return False
def get_aws_account_id(perfect_profile: ProfileTuple) -> int: """該当 profile の AWS account id を取得する""" account_id_section_dict = get_aws_account_id_file_section_dict() aws_account_id = 0 # 該当ファイルのセクションに、該当 profile が存在している場合 if perfect_profile.name in account_id_section_dict.keys(): for profile, values in account_id_section_dict.items(): if profile == perfect_profile.name: # 該当profile の aws_account_id の値を取得する aws_account_id = values.get("aws_account_id") else: # 該当ファイルのセクションに、該当 profile が存在しない場合 # aws account id の入力を要求し、 prompts.prompt_for_asking_aws_account_id(perfect_profile) aws_account_id = helper.ask_int_input_till_its_validated( IntObject(), ASKING_AWS_ACCOUNT_ID_INPUT_MESSAGE) # 該当ファイルに書き込む writing_aws_account_to_the_file(perfect_profile, aws_account_id) # 再帰的に本関数を呼び出して、書き込み済みの aws account id を取得する get_aws_account_id(perfect_profile) return int(aws_account_id)
def is_input_int_and_in_range_for_profile_selection(int_obj: IntObject, _list: list, message: str) -> bool: """ While loop をテストするために、IntObject クラスを介して Validation と IntObject インスタンスの更新を行う """ # メニューを表示 prompt_user_selection(_list) # インプットを促す user_input = helper.get_input(message) try: # validate_is_input_int_and_in_range() に値を引き継ぐために、 # NumInputForWhileLoop インスタンスを使用 int_obj.prompt_num = user_input # int に変換してエラーとなるかどうかをチェック int(int_obj.prompt_num) # int 変換でエラーにならなかった場合、今度は下記で、値が範囲内かどうか✅ return is_input_in_profile_list_range(int_obj, _list) except ValueError: # 誤りを指摘し、再入力を促すプロンプトを表示 print(PROMPT_USER_INPUT_BEFORE + str(user_input) + PROMPT_USER_INPUT_AFTER) print(PROMPT_ENTER_AN_INT + "\n") return False
def get_token_info(selected_profile: ProfileTuple, sts_client: boto3.session.Session, mfa_arn: str, mfa_code: str): """session token を取得する""" token_info = None try: token_info = sts_client.get_session_token( DurationSeconds=43200, # 12 hours SerialNumber=mfa_arn, TokenCode=mfa_code) except ClientError as e: if "less than or equal to 6" in str(e): print(MSG_TOO_LONG_MFA_CODE) cli.access_aws_with_mfa_code(selected_profile) elif "MultiFactorAuthentication" in str(e): selected_measure = validate.ask_for_mfa_failure_inputs(IntObject()) switcher = { 1: lambda: print(MSG_EDIT_AWS_FILES), # update profile 2: lambda: cli.access_aws_after_reset_aws_account_id( selected_profile), # update aws account id 3: lambda: cli.access_aws_with_mfa_code(selected_profile ), # update mfa code 4: lambda: exit(1) } return switcher[int(selected_measure)]() except ParamValidationError as e: if "Invalid length" in str(e): print(MSG_TOO_SHORT_MFA_CODE) cli.access_aws_with_mfa_code(selected_profile) return token_info
def get_mfa_code(perfect_profile: ProfileTuple): prompts.prompt_for_asking_mfa_code(perfect_profile) return helper.ask_int_input_till_its_validated( IntObject(), ASKING_MFA_CODE_BEFORE + perfect_profile.name + ASKING_MFA_CODE_AFTER)