diff --git a/src/google/adk/cli/cli_create.py b/src/google/adk/cli/cli_create.py index f5a5810d..a563d6ad 100644 --- a/src/google/adk/cli/cli_create.py +++ b/src/google/adk/cli/cli_create.py @@ -327,48 +327,61 @@ def _handle_login_with_google() -> ( selected_project_id = projects[project_index - 1][0] region = _prompt_for_google_cloud_region(None) return None, selected_project_id, region - else: - if click.confirm( - "No projects found automatically. Would you like to enter one" - " manually?", - default=False, - ): - selected_project_id = _prompt_for_google_cloud(None) - region = _prompt_for_google_cloud_region(None) - return None, selected_project_id, region - # Check Express eligibility - if gcp_utils.check_express_eligibility(): - click.secho(_EXPRESS_TOS_MSG, fg="yellow") - if click.confirm("Do you accept the Terms of Service?", default=False): - selected_region = click.prompt( - """\ + click.secho( + "A Google Cloud project is required to continue. You can enter an" + " existing project ID or create an Express Mode project. Learn more:" + " https://cloud.google.com/resources/cloud-express-faqs", + fg="green", + ) + action = click.prompt( + "1. Enter an existing Google Cloud project ID\n" + "2. Create a new project (Express Mode)\n" + "3. Abandon\n" + "Choose an action", + type=click.Choice(["1", "2", "3"]), + ) + + if action == "3": + raise click.Abort() + + if action == "1": + google_cloud_project = _prompt_for_google_cloud(None) + google_cloud_region = _prompt_for_google_cloud_region(None) + return None, google_cloud_project, google_cloud_region + + elif action == "2": + if gcp_utils.check_express_eligibility(): + click.secho(_EXPRESS_TOS_MSG, fg="yellow") + if click.confirm("Do you accept the Terms of Service?", default=False): + selected_region = click.prompt( + """\ Choose a region for Express Mode: 1. us-central1 2. europe-west1 3. asia-southeast1 Choose region""", - type=click.Choice(["1", "2", "3"]), - default="1", - ) - region_map = { - "1": "us-central1", - "2": "europe-west1", - "3": "asia-southeast1", - } - region = region_map[selected_region] - express_info = gcp_utils.sign_up_express(location=region) - api_key = express_info.get("api_key") - project_id = express_info.get("project_id") - region = express_info.get("region", region) - click.secho( - f"Express Mode project created: {project_id}", - fg="green", - ) - return api_key, project_id, region + type=click.Choice(["1", "2", "3"]), + default="1", + ) + region_map = { + "1": "us-central1", + "2": "europe-west1", + "3": "asia-southeast1", + } + region = region_map[selected_region] + express_info = gcp_utils.sign_up_express(location=region) + api_key = express_info.get("api_key") + project_id = express_info.get("project_id") + region = express_info.get("region", region) + click.secho( + f"Express Mode project created: {project_id}", + fg="green", + ) + return api_key, project_id, region - click.secho(_NOT_ELIGIBLE_MSG, fg="red") - raise click.Abort() + click.secho(_NOT_ELIGIBLE_MSG, fg="red") + raise click.Abort() def _prompt_to_choose_type() -> str: diff --git a/tests/unittests/cli/utils/test_cli_create.py b/tests/unittests/cli/utils/test_cli_create.py index 520245b3..892e5229 100644 --- a/tests/unittests/cli/utils/test_cli_create.py +++ b/tests/unittests/cli/utils/test_cli_create.py @@ -356,17 +356,51 @@ def test_handle_login_with_google_select_gcp_project( assert region == "us-east1" -def test_handle_login_with_google_express_signup( +def test_handle_login_with_google_manual_project( monkeypatch: pytest.MonkeyPatch, ) -> None: - """Handler should sign up for Express if eligible and user accepts TOS.""" + """Handler should allow manual project ID entry when '0' is selected.""" + monkeypatch.setattr(gcp_utils, "check_adc", lambda: True) + monkeypatch.setattr(gcp_utils, "retrieve_express_project", lambda: None) + monkeypatch.setattr( + gcp_utils, "list_gcp_projects", lambda limit: [("p1", "Project 1")] + ) + prompts = iter([0, "manual-proj", "us-east1"]) + monkeypatch.setattr(click, "prompt", lambda *a, **k: next(prompts)) + + api_key, proj, region = cli_create._handle_login_with_google() + assert api_key is None + assert proj == "manual-proj" + assert region == "us-east1" + + +def test_handle_login_with_google_option_1( + monkeypatch: pytest.MonkeyPatch, +) -> None: + """User selects 1, enters project ID and region.""" + monkeypatch.setattr(gcp_utils, "check_adc", lambda: True) + monkeypatch.setattr(gcp_utils, "retrieve_express_project", lambda: None) + monkeypatch.setattr(gcp_utils, "list_gcp_projects", lambda limit: []) + prompts = iter(["1", "test-proj", "us-east1"]) + monkeypatch.setattr(click, "prompt", lambda *a, **k: next(prompts)) + + api_key, proj, region = cli_create._handle_login_with_google() + assert api_key is None + assert proj == "test-proj" + assert region == "us-east1" + + +def test_handle_login_with_google_option_2( + monkeypatch: pytest.MonkeyPatch, +) -> None: + """User selects 2, goes through express sign up.""" monkeypatch.setattr(gcp_utils, "check_adc", lambda: True) monkeypatch.setattr(gcp_utils, "retrieve_express_project", lambda: None) monkeypatch.setattr(gcp_utils, "list_gcp_projects", lambda limit: []) monkeypatch.setattr(gcp_utils, "check_express_eligibility", lambda: True) - confirms = iter([False, True]) - monkeypatch.setattr(click, "confirm", lambda *a, **k: next(confirms)) - monkeypatch.setattr(click, "prompt", lambda *a, **k: "1") + monkeypatch.setattr(click, "confirm", lambda *a, **k: True) + prompts = iter(["2", "1"]) + monkeypatch.setattr(click, "prompt", lambda *a, **k: next(prompts)) monkeypatch.setattr( gcp_utils, "sign_up_express", @@ -383,6 +417,17 @@ def test_handle_login_with_google_express_signup( assert region == "us-central1" +def test_handle_login_with_google_option_3( + monkeypatch: pytest.MonkeyPatch, +) -> None: + """User selects 3, aborts.""" + monkeypatch.setattr(gcp_utils, "retrieve_express_project", lambda: None) + monkeypatch.setattr(gcp_utils, "list_gcp_projects", lambda limit: []) + monkeypatch.setattr(click, "prompt", lambda *a, **k: "3") + with pytest.raises(click.Abort): + cli_create._handle_login_with_google() + + # prompt_str def test_prompt_str_non_empty(monkeypatch: pytest.MonkeyPatch) -> None: """_prompt_str should retry until a non-blank string is provided.""" @@ -416,42 +461,3 @@ def test_get_gcp_region_from_gcloud_fail( ), ) assert cli_create._get_gcp_region_from_gcloud() == "" - - -def test_handle_login_with_google_manual_project( - monkeypatch: pytest.MonkeyPatch, -) -> None: - """Handler should allow manual project ID entry when '0' is selected.""" - monkeypatch.setattr(gcp_utils, "check_adc", lambda: True) - monkeypatch.setattr(gcp_utils, "retrieve_express_project", lambda: None) - monkeypatch.setattr( - gcp_utils, "list_gcp_projects", lambda limit: [("p1", "Project 1")] - ) - # First prompt is for project selection (0), second is for manual ID entry, - # third is for region selection. - prompts = iter([0, "manual-proj", "us-east1"]) - monkeypatch.setattr(click, "prompt", lambda *a, **k: next(prompts)) - - api_key, proj, region = cli_create._handle_login_with_google() - assert api_key is None - assert proj == "manual-proj" - assert region == "us-east1" - - -def test_handle_login_with_google_empty_projects_manual_entry( - monkeypatch: pytest.MonkeyPatch, -) -> None: - """Handler should allow manual entry if no projects are found and user accepts.""" - monkeypatch.setattr(gcp_utils, "check_adc", lambda: True) - monkeypatch.setattr(gcp_utils, "retrieve_express_project", lambda: None) - monkeypatch.setattr(gcp_utils, "list_gcp_projects", lambda limit: []) - - # User says Yes to "enter manually", then provides project ID and region - prompts = iter(["manual-proj", "us-east1"]) - monkeypatch.setattr(click, "confirm", lambda *a, **k: True) - monkeypatch.setattr(click, "prompt", lambda *a, **k: next(prompts)) - - api_key, proj, region = cli_create._handle_login_with_google() - assert api_key is None - assert proj == "manual-proj" - assert region == "us-east1"