Skip to content
Closed
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
30 changes: 15 additions & 15 deletions cli/commands/configure.py
Original file line number Diff line number Diff line change
Expand Up @@ -20,9 +20,6 @@

PLUGINS = ["CKAN", "Socrata", "ArcGIS"]

# Bucket name must match the `backend "s3"` block in terraform/aws/main.tf.
TERRAFORM_STATE_BUCKET = "opencontext-terraform-state"


def _ensure_state_bucket(bucket_name: str, region: str) -> None:
"""Check that the Terraform S3 state bucket exists; create it if not.
Expand Down Expand Up @@ -198,19 +195,8 @@ def _write_tfvars(


@friendly_exit
def configure(
state_bucket: str = typer.Option(
TERRAFORM_STATE_BUCKET,
"--state-bucket",
help="S3 bucket name for Terraform state (default: opencontext-terraform-state)",
),
) -> None:
def configure() -> None:
"""Interactive wizard to configure your OpenContext MCP server."""
# When called programmatically (e.g. in tests), Typer does not resolve
# Option defaults — guard against receiving the raw OptionInfo sentinel.
if not isinstance(state_bucket, str):
state_bucket = TERRAFORM_STATE_BUCKET

project_root = get_project_root()
terraform_dir = get_terraform_dir()

Expand Down Expand Up @@ -274,6 +260,19 @@ def configure(
raise typer.Exit(0)

city_slug = city_name.lower().replace(" ", "-")

# Prompt for a unique S3 bucket name for Terraform state.
# S3 bucket names are globally unique across all AWS accounts, so the
# default includes the org city slug to avoid collisions with other
# deployments of this project.
suggested_bucket = f"opencontext-terraform-state-{city_slug}"
state_bucket = questionary.text(
"S3 bucket name for Terraform state:",
default=suggested_bucket,
).ask()
if state_bucket is None:
raise typer.Exit(0)

suggested_lambda = f"{city_slug}-opencontext-mcp-{env}"

lambda_name = questionary.text(
Expand Down Expand Up @@ -398,6 +397,7 @@ def configure(
summary.add_row("City", city_name)
summary.add_row("Environment", env)
summary.add_row("Plugin", plugin)
summary.add_row("Terraform state bucket", state_bucket)
summary.add_row("Lambda name", lambda_name)
summary.add_row("AWS region", region)
summary.add_row("Lambda memory", f"{lambda_memory} MB")
Expand Down
37 changes: 7 additions & 30 deletions cli/commands/validate.py
Original file line number Diff line number Diff line change
Expand Up @@ -130,36 +130,13 @@ def run_checks(env: str) -> bool:
".terraform directory found" if tf_initialized else "Run: opencontext configure",
))

# 7. terraform validate
if tf_installed and tf_initialized:
try:
result = subprocess.run(
["terraform", "validate", "-json"],
cwd=terraform_dir,
capture_output=True, text=True, timeout=30,
)
if result.returncode == 0:
checks.append(("terraform validate", True, "Configuration valid"))
else:
error_msg = ""
try:
data = json.loads(result.stdout)
error_msg = data.get("error_message", "")
except Exception:
pass
if not error_msg:
error_msg = (result.stderr or result.stdout or "Validation failed").strip()
checks.append(("terraform validate", False, error_msg[:100]))
except (FileNotFoundError, subprocess.TimeoutExpired) as e:
checks.append(("terraform validate", False, str(e)[:80]))
else:
checks.append((
"terraform validate",
False,
"Skipped — terraform not installed or not initialized",
))
# Note: terraform validate is intentionally skipped here because it
# references lambda-deployment.zip, which does not exist until the
# packaging step inside `opencontext deploy`. Running validate before
# packaging would always fail. Terraform plan (run inside deploy) catches
# the same configuration errors after the zip has been created.

# 8. AWS credentials valid
# 7. AWS credentials valid
try:
result = subprocess.run(
["aws", "sts", "get-caller-identity", "--output", "json"],
Expand All @@ -179,7 +156,7 @@ def run_checks(env: str) -> bool:
except (subprocess.TimeoutExpired, json.JSONDecodeError):
checks.append(("AWS credentials valid", False, "Run: aws configure"))

# 9. ACM cert exists for custom domain (only if custom_domain is set)
# 8. ACM cert exists for custom domain (only if custom_domain is set)
if custom_domain:
try:
result = subprocess.run(
Expand Down
1 change: 0 additions & 1 deletion terraform/bootstrap/variables.tf
Original file line number Diff line number Diff line change
Expand Up @@ -7,5 +7,4 @@ variable "aws_region" {
variable "state_bucket_name" {
description = "Name of the S3 bucket for Terraform state"
type = string
default = "opencontext-terraform-state"
}
Loading