Skip to content

Commit

Permalink
Add interactive prompt for AWS profile name (#111)
Browse files Browse the repository at this point in the history
* Add feature to prompt user for profile name

* Fix description for test_get_profile_name

* Add better profile name input validation

* Fix get_profile_name prompt message formatting

* Fix profile name without user input and tests

* Fix test_get_profile_name syntax error

* Fix get_profile_name empty default value behavior

* Fix linting for unit_test.py

* Move interactive profile fetch out of tool class

---------

Co-authored-by: Mark Slowikowski <mark.slowikowski@ihsmarkit.com>
  • Loading branch information
opis-mark and Mark Slowikowski committed Feb 21, 2023
1 parent 4d3dacc commit b26d2fd
Show file tree
Hide file tree
Showing 3 changed files with 64 additions and 13 deletions.
43 changes: 37 additions & 6 deletions tests/unit_test.py
Original file line number Diff line number Diff line change
Expand Up @@ -1172,24 +1172,55 @@ def test_process_interactive_input(mocker):
assert user.process_interactive_input({"pytest": "pytest"}) == error


@pytest.mark.parametrize(
"default,submit,expected",
[
("", "", ""),
("", "different_name", "different_name"),
("role_name", "", "role_name"),
("role_name", "different_name", "different_name"),
("role_name", "role_name", "role_name"),
],
)
def test_get_interactive_profile_name(mocker, default, submit, expected):
"""Test getting the AWS profile name form user input."""
from tokendito import user

mocker.patch("tokendito.user.input", return_value=submit)
assert user.get_interactive_profile_name(default) == expected


def test_get_interactive_profile_name_invalid_input(monkeypatch):
"""Test reprompting the AWS profile name form user on invalid input."""
from tokendito import user

# provided inputs
inputs = iter(["_this_is_invalid", "str with space", "1StartsWithNum", "valid"])

# using lambda statement for mocking
monkeypatch.setattr("builtins.input", lambda name: next(inputs))

assert user.get_interactive_profile_name("role_name") == "valid"


@pytest.mark.parametrize(
"value,submit,expected",
[
("pytest", None, "pytest"),
("pytest", "deadbeef", "pytest"),
("pytest", 0xDEADBEEF, "pytest"),
(None, None, "default"),
(None, "", "default"),
(None, 0xDEADBEEF, str(0xDEADBEEF)),
(None, "user_input", "user_input"),
],
)
def test_set_role_name(value, submit, expected):
"""Test setting the AWS Role (profile) name."""
def test_set_profile_name(mocker, value, submit, expected):
"""Test setting the AWS Profile name."""
from tokendito import user, Config

pytest_config = Config(aws=dict(profile=value))

ret = user.set_role_name(pytest_config, submit)
mocker.patch("tokendito.user.get_interactive_profile_name", return_value=submit)

ret = user.set_profile_name(pytest_config, "role_name")
assert ret.aws["profile"] == expected


Expand Down
2 changes: 1 addition & 1 deletion tokendito/tool.py
Original file line number Diff line number Diff line change
Expand Up @@ -63,7 +63,7 @@ def cli(args):
)
sys.exit(1)

user.set_role_name(config, role_name)
user.set_profile_name(config, role_name)

user.set_local_credentials(
response=role_response,
Expand Down
32 changes: 26 additions & 6 deletions tokendito/user.py
Original file line number Diff line number Diff line change
Expand Up @@ -864,17 +864,37 @@ def get_password():
return res


def set_role_name(config_obj, name):
def get_interactive_profile_name(default):
"""Get AWS profile name from user.
:return: string with sanitized value, or the default string.
"""
message = f"Enter a profile name or leave blank to use '{default}': "
res = ""

while res == "":
user_data = get_input(prompt=message)
user_data = user_data.strip()
if user_data == "":
res = default
break
if re.fullmatch("[a-zA-Z][a-zA-Z0-9_-]*", user_data):
res = user_data
else:
print("Invalid input, try again.")
logger.debug(f"Profile name is: {res}")
return res


def set_profile_name(config_obj, role_name):
"""Set AWS Role alias name based on user preferences.
:param config: Config object.
:param name: Role name. Defaults to the string "default"
:param role_name: Role name.
:return: Config object.
"""
if name is None or name == "":
name = "default"
if config_obj.aws["profile"] is None:
config_obj.aws["profile"] = str(name)
if config_obj.aws["profile"] is None or config_obj.aws["profile"] == "":
config_obj.aws["profile"] = get_interactive_profile_name(role_name)

return config_obj

Expand Down

0 comments on commit b26d2fd

Please sign in to comment.