Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
110 changes: 1 addition & 109 deletions blueprints/fedramp-high/gemini-enterprise/gem4gov-cli/gem4gov.py
Original file line number Diff line number Diff line change
Expand Up @@ -258,7 +258,7 @@ def onboard():
sys.exit(1)
click.echo(click.style(f"Gemini Enterprise data stores allow end-users to search and ask questions based on a variety of first and third-party datasets. Currently, the only data stores that are available in Gemini for Governement customers are: {supported_data_stores}", fg='yellow'))
while True:
if click.confirm('Do you have an existing data store(s) already created and loaded with data?'):
if click.confirm('Do you have an existing data store(s) already created?'):
# User specified they have existing data stores
data_store_input = click.prompt('Please enter a comma-separated list of data stores that you would like to connect to Gemini Enterprise', type=str).strip()
data_store_list = [item.strip() for item in data_store_input.split(',')]
Expand Down Expand Up @@ -771,114 +771,6 @@ def distribute_licenses(billing_account, config_id, target_project_number, locat
except Exception as e:
click.echo(f"An unexpected error occurred: {e}")

##############################################################
################ gem4gov license ################
##############################################################

@cli.group()
def license():
"""Manages Gemini for Government licenses."""
pass

@license.command(name='list')
@click.option('--billing-account', required=True, help='The billing account ID.')
@click.option('--quota-project', required=False, help='The project ID to use for API quota.')
@click.option('--format', type=click.Choice(['text', 'json']), default='text', help='The output format.')
def list_licenses(billing_account, quota_project, format):
"""Lists available Gemini for Government license configurations for a billing account."""
credentials = get_credentials()
if quota_project:
credentials = credentials.with_quota_project(quota_project)

# Use discoveryengine v1alpha as per PDF
client_options = ClientOptions(api_endpoint="https://us-discoveryengine.googleapis.com")
service = build('discoveryengine', 'v1alpha', credentials=credentials, client_options=client_options)

try:
request = service.billingAccounts().billingAccountLicenseConfigs().list(
parent=f'billingAccounts/{billing_account}'
)
response = request.execute()

configs = response.get('billingAccountLicenseConfigs', [])

if format == 'json':
click.echo(json.dumps(configs, indent=2))
return

if not configs:
click.echo(f"No license configurations found for billing account {billing_account}.")
return

for config in configs:
name = config.get('subscriptionDisplayName', config.get('name'))
total = config.get('licenseCount', 0)
distributions = config.get('licenseConfigDistributions', {})
distributed = sum(int(v) for v in distributions.values())
available = int(total) - distributed

# Extract ID from name: billingAccounts/ID/billingAccountLicenseConfigs/CONFIG_ID
config_id = config.get('name').split('/')[-1]

click.echo(f"Subscription: {name}")
click.echo(f" ID: {config_id}")
click.echo(f" Total Licenses: {total}")
click.echo(f" Distributed: {distributed}")
click.echo(f" Available: {available}")
click.echo("---")

except HttpError as e:
click.echo(f"An error occurred: {e}")
except Exception as e:
click.echo(f"An unexpected error occurred: {e}")

@license.command(name='distribute')
@click.option('--billing-account', required=True, help='The billing account ID.')
@click.option('--config-id', required=True, help='The billing account license config ID.')
@click.option('--target-project-number', required=True, help='The target project number.')
@click.option('--location', default='global', type=click.Choice(['global', 'us', 'eu']), help='The location.')
@click.option('--count', required=True, type=int, help='The number of licenses to distribute (incremental).')
@click.option('--license-config-id', help='The existing project-level license config ID (optional).')
@click.option('--quota-project', required=False, help='The project ID to use for API quota.')
def distribute_licenses(billing_account, config_id, target_project_number, location, count, license_config_id, quota_project):
"""Distributes Gemini for Government licenses to a project."""
credentials = get_credentials()
if quota_project:
credentials = credentials.with_quota_project(quota_project)

endpoint = "https://discoveryengine.googleapis.com"
if location == 'us':
endpoint = "https://us-discoveryengine.googleapis.com"
elif location == 'eu':
endpoint = "https://eu-discoveryengine.googleapis.com"

client_options = ClientOptions(api_endpoint=endpoint)
# v1alpha is needed for billingAccountLicenseConfigs
service = build('discoveryengine', 'v1alpha', credentials=credentials, client_options=client_options)

name = f'billingAccounts/{billing_account}/billingAccountLicenseConfigs/{config_id}'

body = {
"projectNumber": target_project_number,
"location": location,
"licenseCount": count
}
if license_config_id:
body["licenseConfigId"] = license_config_id

try:
request = service.billingAccounts().billingAccountLicenseConfigs().distributeLicenseConfig(
name=name,
body=body
)
response = request.execute()
click.echo("Licenses distributed successfully!")
click.echo(json.dumps(response, indent=2))

except HttpError as e:
click.echo(f"An error occurred: {e}")
except Exception as e:
click.echo(f"An unexpected error occurred: {e}")



Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -34,17 +34,6 @@ variable "compliance_regime" {
}
}

variable "kms_project_id" {
description = "The Project ID where CMEK keys are stored."
type = string
}

variable "us_keyring_name" {
description = "The name of the US Multi-Region KeyRing (if existing). If empty, one will be created."
type = string
default = ""
}

variable "domain" {
description = "FQDN for the load-balancer hosted apps, where the subdomain will be prepended to."
type = string
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,8 +19,5 @@ stage_0_state_bucket = "sedev-gemini-enterprise-tf-state-sedev-test-mike-iac-cor
# This domain will point to the Load Balancer's IP Address
gemini_enterprise_domain = "gemini.yourdomain.gov"

# Gemini Enterprise Config ID (Output from Gem4Gov CLI)
gemini_config_id = "your_gemini_config_id"

# Google Cloud Self-Managed SSL Cert Name (Pre-uploaded to Google Cloud Certificate Manager)
ssl_certificate_name = "your-cert-name-here"
Loading